Tiny storage(file) system on MCU internal flash memory for Nucleo F4xx. 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.

Dependents:   storage_on_flash_demo mbed_controller_demo mbed-os-example-blinky-2

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SOFBlock.h Source File

SOFBlock.h

Go to the documentation of this file.
00001 /**
00002  * @file SOFBlock.h
00003  *
00004  * @author hillkim7@gmail.com
00005  * @brief Simple storage implementation on internal MCU flash memory.
00006  *
00007  * The SOF in SOFBlock is abbreviation of "Storage On Flash".
00008  * The purpose of SOFBlock class is to provide a way to write data on flash memory
00009  * in the same way of file handling class in the file system.
00010  * It manages a chunk of data on the Flash memory efficiently by minimizing flash erase operation as little as possible.
00011  * Note: Currently it only supports STM32F4xx series platforms.
00012  *       - NUCLEO-F401RE, NUCLEO-F411RE, Seeed Arch Max
00013  * The STM32 F4xx series from ST have plenty of internal Flash memory inside MCU core.
00014  * For example STM32 401RE has 512Kbyts Flash.
00015  * Typical size of firmware file is less than 256KB, so remaining area is free to use.
00016  * The simplest way of flash utilization as data storage is to use a chunk of Flash area as an unit of storage.
00017  * A block of flash is called sector in STM32F4xx domain. It requires to erase a sector before update bits in flash.
00018  *
00019  * Conceptually it is quite simple.
00020  * Here is typical write operation:
00021  * 1) Erase sector #n
00022  * 2) Write data to sector #n
00023  * Read operation:
00024  * 1) Just read physical memory address of sector #n
00025  *    The base physical address of STM32 flash is 0x08000000.
00026  *
00027  * There may be inefficiency in this flash usage scenario when size of data is too small compared with sector size.
00028  * The size of sectors from #5 to #7 of STM32-F4xx Flash is 128KB. For example, if I only need to maintain 1KB data,
00029  * whenever I need to update data I need to erase whole 128KB of sector.
00030  * This produces two problems.
00031  * One is time consumption of the erase operation. The operation of ERASE128KB takes 1~4 seconds long.
00032  * The other is related to lifetime of Flash memory.
00033  * More you erase and write and lifetime of flash is shorter.
00034  *
00035  * To overcome such problems, here simple flash management algorithm is used for.
00036  * By tracking data offset and size it can hold multiple data in a sector.
00037  * Bear in mind that is impossible rewriting data on Flash.
00038  * Keeping tracking data along with data itself without frequent erase operation is crucial.
00039  * To do this, data itself is growing from low address.
00040  * On the other hand tracking data is growing down from high address.
00041  * Let's assume the size of data is 1KB and store it in sector #6 which address range is from 0x08040000 to 0x0805ffff.
00042  * +-------------+----------------------------------------------------------------------+-----+
00043  * <data>                                                                        <tracking data>
00044  * +-------------+----------------------------------------------------------------------+-----+
00045  * data grows ->                                                           <- tracking data grows
00046  * Writing data will be placed at the end of data always and reading data will pick the last data.
00047  * It is like simple file system that only keep a file only.
00048  *
00049  * Unlike file manipulation operation, there is caution you need to check if write operation fails
00050  * or need to check free size before you start to write data.
00051  * It is required to format flash sector when there is no more free space.
00052  */
00053 
00054 #pragma once
00055 
00056 #include "SOF_dev.h"
00057 
00058 /** SOF(Storage On Flash) usage example
00059  *
00060  * Example:
00061  * @code
00062  * #include "mbed.h"
00063  * #include "SOFBlock.h"
00064  *
00065  * int main()
00066  * {
00067  *  const uint8_t sector_index = 7;
00068  *  SOFBlock::format(sector_index); // Erase flash sector 7 and make structure for storage.
00069  *
00070  *  SOFWriter writer;
00071  *  SOFReader reader;
00072  *
00073  *  writer.open(sector_index);
00074  *  writer.write_data((uint8_t*)"First Data", 10);
00075  *  writer.close();
00076  *
00077  *  reader.open(sector_index);
00078  *  printf("data %d bytes at %p :\r\n", reader.get_data_size(), reader.get_physical_base_addr());
00079  *  printf("%.*s\r\n", reader.get_data_size(), reader.get_physical_base_addr());
00080  *  // "First Data" printed
00081  *  reader.close();
00082  *
00083  *  SOF_Statics_t statics;
00084  *  if (!SOFBlock(sector_index, statics) || statics.free_size < 11) { // check available byte
00085  *     SOFBlock::format(sector_index);
00086  *  }
00087  *  writer.open(sector_index);
00088  *  // Overwrite previous data without erasing flash.
00089  *  writer.write_data((uint8_t*)"Second Data", 11);
00090  *  writer.close();
00091  *
00092  *  reader.open(sector_index);
00093  *  printf("data %d bytes at %p :\r\n", reader.get_data_size(), reader.get_physical_base_addr());
00094  *  printf("%.*s\r\n", reader.get_data_size(), reader.get_physical_base_addr());
00095  *  // "Second Data" printed
00096  *  reader.close();
00097  * }
00098  */
00099 
00100 /**
00101  * Base class of SOF(Storage On Flash)
00102  */
00103 class SOFBlock
00104 {
00105 public:
00106     SOFBlock();
00107 
00108     virtual ~SOFBlock();
00109 
00110     void close();
00111 
00112 public:
00113     /*** Returns whether instance of SOFBlock is currently associated to flash storage.  */
00114     bool is_open() const {
00115         return hblock_ != NULL;
00116     }
00117 
00118 public:
00119     /*** Erase flash sector and put signature to setup file system struct */
00120     static bool format(uint8_t sector_index);
00121 
00122     /*** Get statistics of storage */
00123     static bool get_stat(uint8_t sector_index, SOF_Statics_t &statics);
00124 
00125 protected:
00126     SOF_BlockHandle_t hblock_;
00127 };
00128 
00129 
00130 /**
00131  * It provides interface for writing data to flash memory.
00132  */
00133 class SOFWriter : public SOFBlock
00134 {
00135 public:
00136     SOFWriter();
00137     virtual ~SOFWriter();
00138 
00139     /*** Open for writing mode */
00140     SOF_Error_t open(uint8_t sector_index);
00141 
00142     /*** Return max available for writing */
00143     size_t get_free_size();
00144 
00145     /*** Write one byte of data.
00146      * Note: in case of storage full, it can't write data any more.
00147      * It is required to format sector and write it again.
00148      */
00149     bool write_byte_data(uint8_t c);
00150 
00151     /*** Write n bytes of data */
00152     size_t write_data(const uint8_t *p, size_t p_size);
00153 };
00154 
00155 
00156 /**
00157 * It provides interface for reading data from flash memory.
00158 * It can read data directly by accessing physical flash address or
00159 * calling function like traditional file API style.
00160 */
00161 class SOFReader : public SOFBlock
00162 {
00163 public:
00164     SOFReader();
00165     virtual ~SOFReader();
00166 
00167     /*** Open for read mode */
00168     SOF_Error_t open(uint8_t sector_index);
00169 
00170     /*** Return flash physical address of data for direct access */
00171     uint8_t *get_physical_data_addr();
00172 
00173     /*** Return data size */
00174     size_t get_data_size();
00175 
00176     /*** Return one byte of data */
00177     bool read_byte_data(uint8_t *c);
00178 
00179     /*** Return n bytes of data */
00180     size_t read_data( uint8_t *p, size_t p_size);
00181 };
00182 
00183