Stores data on the flash memory of stm32f4xx
Diff: SOFBlock.h
- Revision:
- 0:4cb438b58dc2
diff -r 000000000000 -r 4cb438b58dc2 SOFBlock.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SOFBlock.h Fri Nov 18 14:37:15 2016 +0000 @@ -0,0 +1,184 @@ +/** + * @file SOFBlock.h + * + * @author hillkim7@gmail.com + * @brief Simple storage implementation on internal MCU flash memory. + * + * The SOF in SOFBlock is abbreviation of "Storage On Flash". + * The purpose of SOFBlock class is to provide a way to write data on flash memory + * in the same way of file handling class in the file system. + * It manages a chunk of data on the Flash memory efficiently by minimizing flash erase operation as little as possible. + * Note: Currently it only supports STM32F4xx series platforms. + * - NUCLEO-F401RE, NUCLEO-F411RE, Seeed Arch Max + * The STM32 F4xx series from ST have plenty of internal Flash memory inside MCU core. + * For example STM32 401RE has 512Kbyts Flash. + * Typical size of firmware file is less than 256KB, so remaining area is free to use. + * The simplest way of flash utilization as data storage is to use a chunk of Flash area as an unit of storage. + * A block of flash is called sector in STM32F4xx domain. It requires to erase a sector before update bits in flash. + * + * Conceptually it is quite simple. + * Here is typical write operation: + * 1) Erase sector #n + * 2) Write data to sector #n + * Read operation: + * 1) Just read physical memory address of sector #n + * The base physical address of STM32 flash is 0x08000000. + * + * There may be inefficiency in this flash usage scenario when size of data is too small compared with sector size. + * The size of sectors from #5 to #7 of STM32-F4xx Flash is 128KB. For example, if I only need to maintain 1KB data, + * whenever I need to update data I need to erase whole 128KB of sector. + * This produces two problems. + * One is time consumption of the erase operation. The operation of ERASE128KB takes 1~4 seconds long. + * The other is related to lifetime of Flash memory. + * More you erase and write and lifetime of flash is shorter. + * + * To overcome such problems, here simple flash management algorithm is used for. + * By tracking data offset and size it can hold multiple data in a sector. + * Bear in mind that is impossible rewriting data on Flash. + * Keeping tracking data along with data itself without frequent erase operation is crucial. + * To do this, data itself is growing from low address. + * On the other hand tracking data is growing down from high address. + * Let's assume the size of data is 1KB and store it in sector #6 which address range is from 0x08040000 to 0x0805ffff. + * +-------------+----------------------------------------------------------------------+-----+ + * <data> <tracking data> + * +-------------+----------------------------------------------------------------------+-----+ + * data grows -> <- tracking data grows + * Writing data will be placed at the end of data always and reading data will pick the last data. + * It is like simple file system that only keep a file only. + * + * Unlike file manipulation operation, there is caution you need to check if write operation fails + * or need to check free size before you start to write data. + * It is required to format flash sector when there is no more free space. + */ + +#pragma once + +#include "SOF_dev.h" + +/** SOF(Storage On Flash) usage example + * + * Example: + * @code + * #include "mbed.h" + * #include "SOFBlock.h" + * + * int main() + * { + * const uint8_t sector_index = 7; + * SOFBlock::format(sector_index); // Erase flash sector 7 and make structure for storage. + * + * SOFWriter writer; + * SOFReader reader; + * + * writer.open(sector_index); + * writer.write_data((uint8_t*)"First Data", 10); + * writer.close(); + * + * reader.open(sector_index); + * printf("data %d bytes at %p :\r\n", reader.get_data_size(), reader.get_physical_base_addr()); + * printf("%.*s\r\n", reader.get_data_size(), reader.get_physical_base_addr()); + * // "First Data" printed + * reader.close(); + * + * SOF_Statics_t statics; + * if (!SOFBlock(sector_index, statics) || statics.free_size < 11) { // check available byte + * SOFBlock::format(sector_index); + * } + * writer.open(sector_index); + * // Overwrite previous data without erasing flash. + * writer.write_data((uint8_t*)"Second Data", 11); + * writer.close(); + * + * reader.open(sector_index); + * printf("data %d bytes at %p :\r\n", reader.get_data_size(), reader.get_physical_base_addr()); + * printf("%.*s\r\n", reader.get_data_size(), reader.get_physical_base_addr()); + * // "Second Data" printed + * reader.close(); + * } + */ + +/** + * Base class of SOF(Storage On Flash) + */ +class SOFBlock +{ +public: + SOFBlock(); + + virtual ~SOFBlock(); + + void close(); + +public: + /*** Returns whether instance of SOFBlock is currently associated to flash storage. */ + bool is_open() const { + return hblock_ != NULL; + } + +public: + /*** Erase flash sector and put signature to setup file system struct */ + static bool format(uint8_t sector_index); + + /*** Get statistics of storage */ + static bool get_stat(uint8_t sector_index, SOF_Statics_t &statics); + +protected: + SOF_BlockHandle_t hblock_; +}; + + +/** + * It provides interface for writing data to flash memory. + */ +class SOFWriter : public SOFBlock +{ +public: + SOFWriter(); + virtual ~SOFWriter(); + + /*** Open for writing mode */ + SOF_Error_t open(uint8_t sector_index); + + /*** Return max available for writing */ + size_t get_free_size(); + + /*** Write one byte of data. + * Note: in case of storage full, it can't write data any more. + * It is required to format sector and write it again. + */ + bool write_byte_data(uint8_t c); + + /*** Write n bytes of data */ + size_t write_data(const uint8_t *p, size_t p_size); +}; + + +/** +* It provides interface for reading data from flash memory. +* It can read data directly by accessing physical flash address or +* calling function like traditional file API style. +*/ +class SOFReader : public SOFBlock +{ +public: + SOFReader(); + virtual ~SOFReader(); + + /*** Open for read mode */ + SOF_Error_t open(uint8_t sector_index); + + /*** Return flash physical address of data for direct access */ + uint8_t *get_physical_data_addr(); + + /*** Return data size */ + size_t get_data_size(); + + /*** Return one byte of data */ + bool read_byte_data(uint8_t *c); + + /*** Return n bytes of data */ + size_t read_data( uint8_t *p, size_t p_size); +}; + + +