mirror of
https://github.com/ArduPilot/ardupilot
synced 2025-01-05 15:38:29 -04:00
b967140572
This adds a "minimal" dataflash mode with a board specific macro. The QURT port uses this to avoid problematic system calls that are buggy in the QURT RTOS With some pending updates to QURT we may be able to remove some (or all) of this
158 lines
4.8 KiB
C++
158 lines
4.8 KiB
C++
/// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*-
|
|
|
|
/*
|
|
DataFlash logging - file oriented variant
|
|
|
|
This uses posix file IO to create log files called logNN.dat in the
|
|
given directory
|
|
*/
|
|
|
|
#ifndef DataFlash_File_h
|
|
#define DataFlash_File_h
|
|
|
|
#if HAL_OS_POSIX_IO
|
|
|
|
#include "DataFlash_Backend.h"
|
|
|
|
#if CONFIG_HAL_BOARD == HAL_BOARD_QURT
|
|
/*
|
|
the QURT port has a limited range of system calls available. It
|
|
cannot provide all the facilities that DataFlash_File wants. It can
|
|
provide enough to be useful though, which is what
|
|
DATAFLASH_FILE_MINIMAL is for
|
|
*/
|
|
#define DATAFLASH_FILE_MINIMAL 1
|
|
#else
|
|
#define DATAFLASH_FILE_MINIMAL 0
|
|
#endif
|
|
|
|
class DataFlash_File : public DataFlash_Backend
|
|
{
|
|
public:
|
|
// constructor
|
|
DataFlash_File(DataFlash_Class &front,
|
|
DFMessageWriter_DFLogStart *,
|
|
const char *log_directory);
|
|
|
|
// initialisation
|
|
void Init() override;
|
|
bool CardInserted(void);
|
|
|
|
// erase handling
|
|
void EraseAll();
|
|
|
|
// possibly time-consuming preparation handling:
|
|
bool NeedPrep();
|
|
void Prep();
|
|
|
|
/* Write a block of data at current offset */
|
|
bool WritePrioritisedBlock(const void *pBuffer, uint16_t size, bool is_critical);
|
|
uint16_t bufferspace_available();
|
|
|
|
// high level interface
|
|
uint16_t find_last_log() override;
|
|
void get_log_boundaries(uint16_t log_num, uint16_t & start_page, uint16_t & end_page);
|
|
void get_log_info(uint16_t log_num, uint32_t &size, uint32_t &time_utc);
|
|
int16_t get_log_data(uint16_t log_num, uint16_t page, uint32_t offset, uint16_t len, uint8_t *data);
|
|
uint16_t get_num_logs() override;
|
|
uint16_t start_new_log(void) override;
|
|
void LogReadProcess(const uint16_t log_num,
|
|
uint16_t start_page, uint16_t end_page,
|
|
print_mode_fn print_mode,
|
|
AP_HAL::BetterStream *port);
|
|
void DumpPageInfo(AP_HAL::BetterStream *port);
|
|
void ShowDeviceInfo(AP_HAL::BetterStream *port);
|
|
void ListAvailableLogs(AP_HAL::BetterStream *port);
|
|
|
|
#if CONFIG_HAL_BOARD == HAL_BOARD_SITL || CONFIG_HAL_BOARD == HAL_BOARD_LINUX
|
|
void flush(void);
|
|
#endif
|
|
void periodic_fullrate(const uint32_t now);
|
|
|
|
private:
|
|
int _write_fd;
|
|
int _read_fd;
|
|
uint16_t _read_fd_log_num;
|
|
uint32_t _read_offset;
|
|
uint32_t _write_offset;
|
|
volatile bool _initialised;
|
|
volatile bool _open_error;
|
|
const char *_log_directory;
|
|
|
|
uint16_t _cached_oldest_log;
|
|
|
|
/*
|
|
read a block
|
|
*/
|
|
bool ReadBlock(void *pkt, uint16_t size) override;
|
|
|
|
uint16_t _log_num_from_list_entry(const uint16_t list_entry);
|
|
|
|
// possibly time-consuming preparations handling
|
|
void Prep_MinSpace();
|
|
uint16_t find_oldest_log();
|
|
int64_t disk_space_avail();
|
|
int64_t disk_space();
|
|
float avail_space_percent();
|
|
|
|
bool file_exists(const char *filename) const;
|
|
bool log_exists(const uint16_t lognum) const;
|
|
|
|
#if CONFIG_HAL_BOARD == HAL_BOARD_SITL || CONFIG_HAL_BOARD == HAL_BOARD_LINUX
|
|
// I always seem to have less than 10% free space on my laptop:
|
|
const float min_avail_space_percent = 0.1f;
|
|
#else
|
|
const float min_avail_space_percent = 10.0f;
|
|
#endif
|
|
// write buffer
|
|
uint8_t *_writebuf;
|
|
uint32_t _writebuf_size; // in bytes; may be == 65536, thus 32-bits
|
|
const uint16_t _writebuf_chunk;
|
|
volatile uint16_t _writebuf_head;
|
|
volatile uint16_t _writebuf_tail;
|
|
uint32_t _last_write_time;
|
|
|
|
/* construct a file name given a log number. Caller must free. */
|
|
char *_log_file_name(const uint16_t log_num) const;
|
|
char *_lastlog_file_name() const;
|
|
uint32_t _get_log_size(const uint16_t log_num) const;
|
|
uint32_t _get_log_time(const uint16_t log_num) const;
|
|
|
|
void stop_logging(void);
|
|
|
|
void _io_timer(void);
|
|
|
|
uint16_t critical_message_reserved_space() const {
|
|
// possibly make this a proportional to buffer size?
|
|
uint16_t ret = 1024;
|
|
if (ret > _writebuf_size) {
|
|
// in this case you will only get critical messages
|
|
ret = _writebuf_size;
|
|
}
|
|
return ret;
|
|
};
|
|
uint16_t non_messagewriter_message_reserved_space() const {
|
|
// possibly make this a proportional to buffer size?
|
|
uint16_t ret = 1024;
|
|
if (ret >= _writebuf_size) {
|
|
// need to allow messages out from the messagewriters. In
|
|
// this case while you have a messagewriter you won't get
|
|
// any other messages. This should be a corner case!
|
|
ret = 0;
|
|
}
|
|
return ret;
|
|
};
|
|
|
|
AP_HAL::Semaphore *semaphore;
|
|
|
|
// performance counters
|
|
AP_HAL::Util::perf_counter_t _perf_write;
|
|
AP_HAL::Util::perf_counter_t _perf_fsync;
|
|
AP_HAL::Util::perf_counter_t _perf_errors;
|
|
AP_HAL::Util::perf_counter_t _perf_overruns;
|
|
};
|
|
|
|
#endif // HAL_OS_POSIX_IO
|
|
|
|
#endif // DataFlash_File_h
|