ardupilot/libraries/AP_Logger/AP_Logger_Block.h
Andy Piper ccb583d092 AP_Logger: make block logger conform to mavlink expectations of numbering
add support for log time to block logger
refactor rotation into backed. Don't start logs when erasing
correct log start logic
separate read and write points so that requesting log information does not corrupt the current log
when starting a new log stop logging first
clear the write buffer when starting a new log
insert utc time when requesting info for the current log
stop logging and request formats again when starting a new log
cope with erase happening while we are logging
keep pushing out startup messages even when format messages are done
don't log to the gcs in the io thread
don't start new logs in the io thread
don't validate logs while erasing
flush logs when stopping logging
account for page header when calculating logs sizes
don't return data when asked for more data than in the log
optimize locking and use separate semaphore to mediate ring buffer access
stop logging when the chip is full and send a notification
calculate logs sizes correctly even when they wrap
read log data correctly even when it wraps
add stats support to block logger
reset dropped when starting a new log
fail logging when the chip is full
refactor critical bufferspace checks
increase messagewriter budget to 250us and to 300us for FMT
2020-09-05 10:20:39 +10:00

162 lines
5.0 KiB
C++

/*
AP_Logger logging - block oriented variant
*/
#pragma once
#include "AP_Logger_Backend.h"
#define BLOCK_LOG_VALIDATE 0
class AP_Logger_Block : public AP_Logger_Backend {
public:
AP_Logger_Block(AP_Logger &front, LoggerMessageWriter_DFLogStart *writer);
virtual void Init(void) override;
virtual bool CardInserted(void) const override = 0;
// erase handling
void EraseAll() override;
void Prep() override;
// high level interface
uint16_t find_last_log() override;
void get_log_boundaries(uint16_t list_entry, uint32_t & start_page, uint32_t & end_page) override;
void get_log_info(uint16_t list_entry, uint32_t &size, uint32_t &time_utc) override;
int16_t get_log_data(uint16_t list_entry, uint16_t page, uint32_t offset, uint16_t len, uint8_t *data) override WARN_IF_UNUSED;
uint16_t get_num_logs() override;
void start_new_log(void) override;
uint32_t bufferspace_available() override;
void stop_logging(void) override;
bool logging_failed() const override;
bool logging_started(void) const override { return log_write_started; }
protected:
/* Write a block of data at current offset */
bool _WritePrioritisedBlock(const void *pBuffer, uint16_t size, bool is_critical) override;
void periodic_1Hz() override;
void periodic_10Hz(const uint32_t now) override;
bool WritesOK() const override;
// get the current sector from the current page
uint32_t get_sector(uint32_t current_page) {
return ((current_page - 1) / df_PagePerSector);
}
// get the current block from the current page
uint32_t get_block(uint32_t current_page) {
return ((current_page - 1) / df_PagePerBlock);
}
// number of bytes in a page
uint32_t df_PageSize;
// number of pages in a (generally 64k) block
uint16_t df_PagePerBlock;
// number of pages in a (generally 4k) sector
uint16_t df_PagePerSector;
// number of pages on the chip
uint32_t df_NumPages;
volatile bool log_write_started;
static const uint16_t page_size_max = 256;
uint8_t *buffer;
uint32_t last_messagewrite_message_sent;
private:
/*
functions implemented by the board specific backends
*/
virtual void BufferToPage(uint32_t PageAdr) = 0;
virtual void PageToBuffer(uint32_t PageAdr) = 0;
virtual void SectorErase(uint32_t SectorAdr) = 0;
virtual void Sector4kErase(uint32_t SectorAdr) = 0;
virtual void StartErase() = 0;
virtual bool InErase() = 0;
struct PACKED PageHeader {
uint32_t FilePage;
uint16_t FileNumber;
#if BLOCK_LOG_VALIDATE
uint32_t crc;
#endif
};
struct PACKED FileHeader {
uint32_t utc_secs;
};
// semaphore to mediate access to the chip
HAL_Semaphore sem;
// semaphore to mediate access to the ring buffer
HAL_Semaphore write_sem;
ByteBuffer writebuf;
// state variables
uint16_t df_Read_BufferIdx;
uint32_t df_PageAdr;
uint32_t df_Read_PageAdr;
// file numbers
uint16_t df_FileNumber;
uint16_t df_Write_FileNumber;
uint32_t df_FileTime;
// relative page index of the current read/write file starting at 1
uint32_t df_FilePage;
uint32_t df_Write_FilePage;
// page to wipe from in the case of corruption
uint32_t df_EraseFrom;
// offset from adding FMT messages to log data
bool adding_fmt_headers;
// are we waiting on an erase to finish?
volatile bool erase_started;
// were we logging before the erase started?
volatile bool new_log_pending;
// latch to make sure we only write out the full message once
volatile bool chip_full;
// io thread health
volatile uint32_t io_timer_heartbeat;
uint8_t warning_decimation_counter;
volatile enum class StatusMessage {
NONE,
ERASE_COMPLETE,
RECOVERY_COMPLETE,
} status_msg;
// read size bytes of data to a page. The caller must ensure that
// the data fits within the page, otherwise it will wrap to the
// start of the page
bool BlockRead(uint16_t IntPageAdr, void *pBuffer, uint16_t size);
// erase handling
bool NeedErase(void);
void validate_log_structure();
// internal high level functions
int16_t get_log_data_raw(uint16_t log_num, uint32_t page, uint32_t offset, uint16_t len, uint8_t *data) WARN_IF_UNUSED;
// read from the page address and return the file number at that location
uint16_t StartRead(uint32_t PageAdr);
// read the headers at the current read point returning the file number
uint16_t ReadHeaders();
uint32_t find_last_page(void);
uint32_t find_last_page_of_log(uint16_t log_number);
bool is_wrapped(void);
void StartWrite(uint32_t PageAdr);
void FinishWrite(void);
// Read methods
bool ReadBlock(void *pBuffer, uint16_t size);
void StartLogFile(uint16_t FileNumber);
// file numbers
uint16_t GetFileNumber();
void _print_log_formats(AP_HAL::BetterStream *port);
// callback on IO thread
bool io_thread_alive() const;
void io_timer(void);
void write_log_page();
};