/* ************************************************************ */ /* DataFlash_Revo Log library */ /* ************************************************************ */ #pragma once #if CONFIG_HAL_BOARD == HAL_BOARD_F4LIGHT #include #include "DataFlash_Backend.h" #include #include // flash size #define DF_PAGE_SIZE 256L #define DF_RESET BOARD_DATAFLASH_CS_PIN // RESET (PB3) //Micron M25P16 Serial Flash Embedded Memory 16 Mb, 3V #define JEDEC_WRITE_ENABLE 0x06 #define JEDEC_WRITE_DISABLE 0x04 #define JEDEC_READ_STATUS 0x05 #define JEDEC_WRITE_STATUS 0x01 #define JEDEC_READ_DATA 0x03 #define JEDEC_FAST_READ 0x0b #define JEDEC_DEVICE_ID 0x9F #define JEDEC_PAGE_WRITE 0x02 #define JEDEC_BULK_ERASE 0xC7 #define JEDEC_SECTOR_ERASE 0x20 // 4k erase #define JEDEC_PAGE_ERASE 0xD8 // 64K erase #define JEDEC_STATUS_BUSY 0x01 #define JEDEC_STATUS_WRITEPROTECT 0x02 #define JEDEC_STATUS_BP0 0x04 #define JEDEC_STATUS_BP1 0x08 #define JEDEC_STATUS_BP2 0x10 #define JEDEC_STATUS_TP 0x20 #define JEDEC_STATUS_SEC 0x40 #define JEDEC_STATUS_SRP0 0x80 using namespace F4Light; class DataFlash_Revo : public DataFlash_Backend { private: //Methods void BufferWrite (uint8_t BufferNum, uint16_t IntPageAdr, uint8_t Data); void BufferToPage (uint8_t BufferNum, uint16_t PageAdr, uint8_t wait); void PageToBuffer(uint8_t BufferNum, uint16_t PageAdr); void WaitReady(); uint8_t ReadStatusReg(); uint16_t PageSize() { return df_PageSize; } void PageErase (uint16_t PageAdr); void BlockErase (uint16_t BlockAdr); void ChipErase(); void Flash_Jedec_WriteEnable(); void Flash_Jedec_EraseSector(uint32_t chip_offset); // write 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 // If pHeader is not nullptr then write the header bytes before the data void BlockWrite(uint8_t BufferNum, uint16_t IntPageAdr, const void *pHeader, uint8_t hdr_size, const void *pBuffer, uint16_t size); // 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(uint8_t BufferNum, uint16_t IntPageAdr, void *pBuffer, uint16_t size); ////////////////// static AP_HAL::OwnPtr _spi; static AP_HAL::Semaphore *_spi_sem; static bool log_write_started; static bool _sem_take(uint8_t timeout); // take a semaphore safely bool cs_assert(); // Select device void cs_release(); // Deselect device // uint8_t spi_read(void) { uint8_t b; _spi->transfer(NULL,0, &b, 1); return b; } inline void spi_write(uint8_t b) { _spi->transfer(&b,1, NULL, 0); } inline void spi_write(int data) { spi_write((uint8_t)data); } static bool flash_died; //[ from died Dataflash_Block struct PageHeader { uint16_t FileNumber; uint16_t FilePage; }; // DataFlash Log variables... uint8_t df_BufferNum; uint8_t df_Read_BufferNum; uint16_t df_BufferIdx; uint16_t df_Read_BufferIdx; uint16_t df_PageAdr; uint16_t df_Read_PageAdr; uint16_t df_FileNumber; uint16_t df_FilePage; // offset from adding FMT messages to log data bool adding_fmt_headers; // erase handling bool NeedErase(void); // internal high level functions void StartRead(uint16_t PageAdr); uint16_t find_last_page(void); uint16_t find_last_page_of_log(uint16_t log_number); bool check_wrapped(void); uint16_t GetPage(void); uint16_t GetWritePage(void); void StartWrite(uint16_t PageAdr); void FinishWrite(void); bool getSectorCount(uint32_t *ptr); // Read methods bool ReadBlock(void *pBuffer, uint16_t size); // file numbers void SetFileNumber(uint16_t FileNumber); uint16_t GetFilePage(); uint16_t GetFileNumber(); uint8_t erase_cmd; uint32_t erase_size; uint16_t last_block_num; protected: uint8_t df_manufacturer; uint16_t df_device; // page handling uint16_t df_PageSize; uint32_t df_NumPages; bool WritesOK() const override; //] public: DataFlash_Revo(DataFlash_Class &front, DFMessageWriter_DFLogStart *writer) : DataFlash_Backend(front, writer) { } void Init() override; void ReadManufacturerID(); bool CardInserted(void) const { return true; } uint8_t ReadStatus(); bool logging_enabled() const { return true; } bool logging_failed() const { return false; }; void stop_logging(void) { log_write_started = false; } //[ from died Dataflash_Block // erase handling void EraseAll(); bool NeedPrep(void); void Prep(); /* Write a block of data at current offset */ bool _WritePrioritisedBlock(const void *pBuffer, uint16_t size, bool is_critical); // high level interface uint16_t get_num_logs() override; uint16_t start_new_log(void); void get_log_boundaries(uint16_t log_num, uint16_t & start_page, uint16_t & end_page); uint16_t find_last_log() override; void get_log_info(uint16_t log_num, uint32_t &size, uint32_t &time_utc); int16_t get_log_data_raw(uint16_t log_num, uint16_t page, uint32_t offset, uint16_t len, uint8_t *data); int16_t get_log_data(uint16_t log_num, uint16_t page, uint32_t offset, uint16_t len, uint8_t *data); uint32_t bufferspace_available(); bool logging_started(void) const { return log_write_started; } }; #endif // CONFIG_HAL_BOARD == HAL_BOARD_Revo