Line data Source code
1 : /* 2 : AP_Logger logging - file oriented variant 3 : 4 : This uses posix file IO to create log files called logNN.dat in the 5 : given directory 6 : */ 7 : #pragma once 8 : 9 : #include <AP_Filesystem/AP_Filesystem.h> 10 : 11 : #include <AP_HAL/utility/RingBuffer.h> 12 : #include "AP_Logger_Backend.h" 13 : 14 : #if HAL_LOGGING_FILESYSTEM_ENABLED 15 : 16 : #ifndef HAL_LOGGER_WRITE_CHUNK_SIZE 17 : #if AP_FILESYSTEM_LITTLEFS_ENABLED 18 : #define HAL_LOGGER_WRITE_CHUNK_SIZE 2048 19 : #elif AP_FILESYSTEM_FATFS_ENABLED 20 : #define HAL_LOGGER_WRITE_CHUNK_SIZE (AP_Filesystem_FATFS::get_io_size()) 21 : #else 22 : #define HAL_LOGGER_WRITE_CHUNK_SIZE AP_FATFS_MIN_IO_SIZE 23 : #endif 24 : #endif 25 : 26 : class AP_Logger_File : public AP_Logger_Backend 27 : { 28 : public: 29 : // constructor 30 : AP_Logger_File(AP_Logger &front, 31 : LoggerMessageWriter_DFLogStart *); 32 : 33 2088 : static AP_Logger_Backend *probe(AP_Logger &front, 34 : LoggerMessageWriter_DFLogStart *ls) { 35 2088 : return NEW_NOTHROW AP_Logger_File(front, ls); 36 : } 37 : 38 : // initialisation 39 : void Init() override; 40 : bool CardInserted(void) const override; 41 : 42 : // erase handling 43 : void EraseAll() override; 44 : 45 : /* Write a block of data at current offset */ 46 : bool _WritePrioritisedBlock(const void *pBuffer, uint16_t size, bool is_critical) override; 47 : uint32_t bufferspace_available() override; 48 : 49 : // high level interface 50 : uint16_t find_last_log() override; 51 : void get_log_boundaries(uint16_t log_num, uint32_t & start_page, uint32_t & end_page) override; 52 : void get_log_info(uint16_t log_num, uint32_t &size, uint32_t &time_utc) override; 53 : int16_t get_log_data(uint16_t log_num, uint16_t page, uint32_t offset, uint16_t len, uint8_t *data) override; 54 : void end_log_transfer() override; 55 : uint16_t get_num_logs() override; 56 : void start_new_log(void) override; 57 : uint16_t find_oldest_log() override; 58 : 59 : #if CONFIG_HAL_BOARD == HAL_BOARD_SITL || CONFIG_HAL_BOARD == HAL_BOARD_LINUX 60 : void flush(void) override; 61 : #endif 62 : void periodic_1Hz() override; 63 : void periodic_fullrate() override; 64 : 65 : // this method is used for mavlink system status and arming checks 66 : bool logging_failed() const override; 67 : 68 45173816 : bool logging_started(void) const override { return _write_fd != -1; } 69 : void io_timer(void) override; 70 : 71 : protected: 72 : 73 : bool WritesOK() const override; 74 : bool StartNewLogOK() const override; 75 : void PrepForArming_start_logging() override; 76 : 77 : private: 78 : int _write_fd = -1; 79 : char *_write_filename; 80 : bool last_log_is_marked_discard; 81 : uint32_t _last_write_ms; 82 : #if AP_RTC_ENABLED && CONFIG_HAL_BOARD == HAL_BOARD_CHIBIOS 83 : bool _need_rtc_update; 84 : #endif 85 : 86 : int _read_fd = -1; 87 : uint16_t _read_fd_log_num; 88 : uint32_t _read_offset; 89 : uint32_t _write_offset; 90 : volatile uint32_t _open_error_ms; 91 : const char *_log_directory; 92 : bool _last_write_failed; 93 : 94 : uint32_t _io_timer_heartbeat; 95 : bool io_thread_alive() const; 96 : uint8_t io_thread_warning_decimation_counter; 97 : 98 : // do we have a recent open error? 99 : bool recent_open_error(void) const; 100 : 101 : // possibly time-consuming preparations handling 102 : void Prep_MinSpace(); 103 : int64_t disk_space_avail(); 104 : int64_t disk_space(); 105 : 106 : void ensure_log_directory_exists(); 107 : 108 : bool file_exists(const char *filename) const; 109 : bool log_exists(const uint16_t lognum) const; 110 : 111 : bool dirent_to_log_num(const dirent *de, uint16_t &log_num) const; 112 : bool write_lastlog_file(uint16_t log_num); 113 : 114 : // write buffer 115 : ByteBuffer _writebuf{0}; 116 : const uint16_t _writebuf_chunk = HAL_LOGGER_WRITE_CHUNK_SIZE; 117 : uint32_t _last_write_time; 118 : 119 : /* construct a file name given a log number. Caller must free. */ 120 : char *_log_file_name(const uint16_t log_num) const; 121 : char *_lastlog_file_name() const; 122 : uint32_t _get_log_size(const uint16_t log_num); 123 : uint32_t _get_log_time(const uint16_t log_num); 124 : 125 : void stop_logging(void) override; 126 : 127 : uint32_t last_messagewrite_message_sent; 128 : 129 : // free-space checks; filling up SD cards under NuttX leads to 130 : // corrupt filesystems which cause loss of data, failure to gather 131 : // data and failures-to-boot. 132 : uint32_t _free_space_last_check_time; // milliseconds 133 : static constexpr uint32_t _free_space_check_interval = 1000UL; // milliseconds 134 : #if AP_FILESYSTEM_LITTLEFS_ENABLED 135 : #if AP_FILESYSTEM_LITTLEFS_FLASH_TYPE == AP_FILESYSTEM_FLASH_W25NXX 136 : static constexpr uint32_t _free_space_min_avail = 1024 * 1024; // bytes 137 : #else 138 : static constexpr uint32_t _free_space_min_avail = 1024 * 256; // bytes 139 : #endif 140 : #else 141 : static constexpr uint32_t _free_space_min_avail = 8388608; // bytes 142 : #endif 143 : 144 : // semaphore mediates access to the ringbuffer 145 : HAL_Semaphore semaphore; 146 : // write_fd_semaphore mediates access to write_fd so the frontend 147 : // can open/close files without causing the backend to write to a 148 : // bad fd 149 : HAL_Semaphore write_fd_semaphore; 150 : 151 : // async erase state 152 : struct { 153 : bool was_logging; 154 : uint16_t log_num; 155 : } erase; 156 : void erase_next(void); 157 : 158 : const char *last_io_operation = ""; 159 : 160 : bool start_new_log_pending; 161 : }; 162 : 163 : #endif // HAL_LOGGING_FILESYSTEM_ENABLED