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

March 26, 2015

Seeed Arch Max platform which is based on STM32-F407 is supported.

Committer:
hillkim7
Date:
Mon Jan 19 12:57:44 2015 +0000
Revision:
0:7f4bc855cb46
Child:
1:33afe074c8f8
Tiny storage(file) system on MCU internal flash 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.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
hillkim7 0:7f4bc855cb46 1 /**
hillkim7 0:7f4bc855cb46 2 * @file SOFBlock.h
hillkim7 0:7f4bc855cb46 3 *
hillkim7 0:7f4bc855cb46 4 * @author hillkim7@gmail.com
hillkim7 0:7f4bc855cb46 5 * @brief Simple storage implementation on internal MCU flash memory.
hillkim7 0:7f4bc855cb46 6
hillkim7 0:7f4bc855cb46 7 The SOF in SOFBlock is abbreviation of "Storage On Flash".
hillkim7 0:7f4bc855cb46 8 The purpose of SOFBlock class is to provide a way to write data on flash memory
hillkim7 0:7f4bc855cb46 9 in the same way of file handling class in the file system.
hillkim7 0:7f4bc855cb46 10 It manages a chunk of data on the Flash memory efficiently by minimizing flash erase operation as little as possible.
hillkim7 0:7f4bc855cb46 11 Note: Currently I only support STM32F4xx series platforms.
hillkim7 0:7f4bc855cb46 12
hillkim7 0:7f4bc855cb46 13 The STM32 F4xx series from ST have plenty of internal Flash memory inside MCU core.
hillkim7 0:7f4bc855cb46 14 For example STM32 401RE has 512Kbyts Flash.
hillkim7 0:7f4bc855cb46 15 Typical size of firmware file is less than 256KB, so remaining area is free to use.
hillkim7 0:7f4bc855cb46 16 The simplest way of flash utilization as data storage is to use a chunk of Flash area as an unit of storage.
hillkim7 0:7f4bc855cb46 17 A block of Flash is called sector in STM32 domain. It requires to erase a sector before update bits in Flash.
hillkim7 0:7f4bc855cb46 18
hillkim7 0:7f4bc855cb46 19 Conceptually it is quite simple.
hillkim7 0:7f4bc855cb46 20 Here is write operation:
hillkim7 0:7f4bc855cb46 21 1) Erase sector #n
hillkim7 0:7f4bc855cb46 22 2) Write data to sector #n
hillkim7 0:7f4bc855cb46 23 Read operation:
hillkim7 0:7f4bc855cb46 24 1) Just read physical memory address of sector #n
hillkim7 0:7f4bc855cb46 25 The base address of STM32 Flash is 0x00000000.
hillkim7 0:7f4bc855cb46 26
hillkim7 0:7f4bc855cb46 27 There may be inefficiency in this Flash usage scenario when size of data is too small compared with sector size.
hillkim7 0:7f4bc855cb46 28 The size of sectors from #5 to #7 of STM32 401RE Flash 128KB. If I only need to maintain 1KB data,
hillkim7 0:7f4bc855cb46 29 whenever I need to update data I need to erase whole 128KB of sector.
hillkim7 0:7f4bc855cb46 30 This produces two problems.
hillkim7 0:7f4bc855cb46 31 One is time consumption of erase operation. The operation of ERASE128KB takes 1~4 seconds long.
hillkim7 0:7f4bc855cb46 32 The other is lifetime of Flash memory. More you erase and write and lifetime of Flash is shorter.
hillkim7 0:7f4bc855cb46 33
hillkim7 0:7f4bc855cb46 34 To overcome such problem, here simple flash management algorithm is used for.
hillkim7 0:7f4bc855cb46 35 By tracking data offset and size it can hold multiple data in a sector. Bear in mind that is impossible rewriting data on Flash.
hillkim7 0:7f4bc855cb46 36 Keeping tracking data along with data itself is crucial.
hillkim7 0:7f4bc855cb46 37 Data itself is growing from low address. On the other hand tracking data is growing down from high address.
hillkim7 0:7f4bc855cb46 38 Let's assume the size of data is 1KB and store it in sector #6 which address range is from 0x08040000 to 0x0805ffff.
hillkim7 0:7f4bc855cb46 39 +-------------+----------------------------------------------------------------------+-----+
hillkim7 0:7f4bc855cb46 40 <data> <tracking data>
hillkim7 0:7f4bc855cb46 41 +-------------+----------------------------------------------------------------------+-----+
hillkim7 0:7f4bc855cb46 42 data grows -> <- tracking data grows
hillkim7 0:7f4bc855cb46 43 Writing data will be placed at the end of data always and reading data will pick the last data.
hillkim7 0:7f4bc855cb46 44 It is like simple file system that only keep a file only.
hillkim7 0:7f4bc855cb46 45 */
hillkim7 0:7f4bc855cb46 46
hillkim7 0:7f4bc855cb46 47 #pragma once
hillkim7 0:7f4bc855cb46 48
hillkim7 0:7f4bc855cb46 49 #include "SOF_dev.h"
hillkim7 0:7f4bc855cb46 50
hillkim7 0:7f4bc855cb46 51 /** SOF(Storage On Flash) usage example
hillkim7 0:7f4bc855cb46 52 *
hillkim7 0:7f4bc855cb46 53 * Example:
hillkim7 0:7f4bc855cb46 54 * @code
hillkim7 0:7f4bc855cb46 55 #include "mbed.h"
hillkim7 0:7f4bc855cb46 56 #include "SOFBlock.h"
hillkim7 0:7f4bc855cb46 57
hillkim7 0:7f4bc855cb46 58 int main()
hillkim7 0:7f4bc855cb46 59 {
hillkim7 0:7f4bc855cb46 60 const uint8_t sector_index = 7;
hillkim7 0:7f4bc855cb46 61 SOFBlock::format(sector_index); // Erase flash sector 7 and make structure for storage.
hillkim7 0:7f4bc855cb46 62
hillkim7 0:7f4bc855cb46 63 SOFWriter writer;
hillkim7 0:7f4bc855cb46 64 SOFReader reader;
hillkim7 0:7f4bc855cb46 65
hillkim7 0:7f4bc855cb46 66 writer.open(sector_index) ;
hillkim7 0:7f4bc855cb46 67 writer.write_data((uint8_t*)"First Data", 10);
hillkim7 0:7f4bc855cb46 68 writer.close();
hillkim7 0:7f4bc855cb46 69
hillkim7 0:7f4bc855cb46 70 reader.open(sector_index);
hillkim7 0:7f4bc855cb46 71 printf("data %d bytes at %p :\r\n", reader.get_data_size(), reader.get_physical_base_addr());
hillkim7 0:7f4bc855cb46 72 printf("%.*s\r\n", reader.get_data_size(), reader.get_physical_base_addr());
hillkim7 0:7f4bc855cb46 73 // "First Data" printed
hillkim7 0:7f4bc855cb46 74 reader.close();
hillkim7 0:7f4bc855cb46 75
hillkim7 0:7f4bc855cb46 76 writer.open(sector_index) ;
hillkim7 0:7f4bc855cb46 77 // Overwrite previous data without erasing flash.
hillkim7 0:7f4bc855cb46 78 writer.write_data((uint8_t*)"Second Data", 11);
hillkim7 0:7f4bc855cb46 79 writer.close();
hillkim7 0:7f4bc855cb46 80
hillkim7 0:7f4bc855cb46 81 reader.open(sector_index);
hillkim7 0:7f4bc855cb46 82 printf("data %d bytes at %p :\r\n", reader.get_data_size(), reader.get_physical_base_addr());
hillkim7 0:7f4bc855cb46 83 printf("%.*s\r\n", reader.get_data_size(), reader.get_physical_base_addr());
hillkim7 0:7f4bc855cb46 84 // "Second Data" printed
hillkim7 0:7f4bc855cb46 85 reader.close();
hillkim7 0:7f4bc855cb46 86 }
hillkim7 0:7f4bc855cb46 87
hillkim7 0:7f4bc855cb46 88 */
hillkim7 0:7f4bc855cb46 89
hillkim7 0:7f4bc855cb46 90 /**
hillkim7 0:7f4bc855cb46 91 * Base class of SOF(Storage On Flash)
hillkim7 0:7f4bc855cb46 92 */
hillkim7 0:7f4bc855cb46 93 class SOFBlock
hillkim7 0:7f4bc855cb46 94 {
hillkim7 0:7f4bc855cb46 95 public:
hillkim7 0:7f4bc855cb46 96 SOFBlock();
hillkim7 0:7f4bc855cb46 97
hillkim7 0:7f4bc855cb46 98 virtual ~SOFBlock();
hillkim7 0:7f4bc855cb46 99
hillkim7 0:7f4bc855cb46 100 void close();
hillkim7 0:7f4bc855cb46 101
hillkim7 0:7f4bc855cb46 102 public:
hillkim7 0:7f4bc855cb46 103 bool is_open() const { return hblock_ != NULL; }
hillkim7 0:7f4bc855cb46 104
hillkim7 0:7f4bc855cb46 105 public:
hillkim7 0:7f4bc855cb46 106 /*** erase flash sector and put signature to setup struct */
hillkim7 0:7f4bc855cb46 107 static bool format(uint8_t sector_index);
hillkim7 0:7f4bc855cb46 108
hillkim7 0:7f4bc855cb46 109 protected:
hillkim7 0:7f4bc855cb46 110 SOF_BlockHandle_t hblock_;
hillkim7 0:7f4bc855cb46 111 };
hillkim7 0:7f4bc855cb46 112
hillkim7 0:7f4bc855cb46 113
hillkim7 0:7f4bc855cb46 114 /**
hillkim7 0:7f4bc855cb46 115 * It provides interface for writing data to flash memory.
hillkim7 0:7f4bc855cb46 116 */
hillkim7 0:7f4bc855cb46 117 class SOFWriter : public SOFBlock
hillkim7 0:7f4bc855cb46 118 {
hillkim7 0:7f4bc855cb46 119 public:
hillkim7 0:7f4bc855cb46 120 SOFWriter();
hillkim7 0:7f4bc855cb46 121 virtual ~SOFWriter();
hillkim7 0:7f4bc855cb46 122
hillkim7 0:7f4bc855cb46 123 /*** Open for writing mode */
hillkim7 0:7f4bc855cb46 124 SOF_Error_t open(uint8_t sector_index);
hillkim7 0:7f4bc855cb46 125
hillkim7 0:7f4bc855cb46 126 /*** Return max available for writing */
hillkim7 0:7f4bc855cb46 127 size_t get_free_size();
hillkim7 0:7f4bc855cb46 128
hillkim7 0:7f4bc855cb46 129 /*** Write one byte of data */
hillkim7 0:7f4bc855cb46 130 bool write_byte_data(uint8_t c);
hillkim7 0:7f4bc855cb46 131
hillkim7 0:7f4bc855cb46 132 /*** Write n bytes of data */
hillkim7 0:7f4bc855cb46 133 size_t write_data(const uint8_t *p, size_t p_size);
hillkim7 0:7f4bc855cb46 134 };
hillkim7 0:7f4bc855cb46 135
hillkim7 0:7f4bc855cb46 136
hillkim7 0:7f4bc855cb46 137 /**
hillkim7 0:7f4bc855cb46 138 * It provides interface for reading data from flash memory.
hillkim7 0:7f4bc855cb46 139 * It can read data directly by accessing physical flash address or
hillkim7 0:7f4bc855cb46 140 * calling function like traditional file API style.
hillkim7 0:7f4bc855cb46 141 */
hillkim7 0:7f4bc855cb46 142 class SOFReader : public SOFBlock
hillkim7 0:7f4bc855cb46 143 {
hillkim7 0:7f4bc855cb46 144 public:
hillkim7 0:7f4bc855cb46 145 SOFReader();
hillkim7 0:7f4bc855cb46 146 virtual ~SOFReader();
hillkim7 0:7f4bc855cb46 147
hillkim7 0:7f4bc855cb46 148 /*** Open for read mode */
hillkim7 0:7f4bc855cb46 149 SOF_Error_t open(uint8_t sector_index);
hillkim7 0:7f4bc855cb46 150
hillkim7 0:7f4bc855cb46 151 /*** Return flash physical address of data for direct access */
hillkim7 0:7f4bc855cb46 152 uint8_t *get_physical_base_addr();
hillkim7 0:7f4bc855cb46 153
hillkim7 0:7f4bc855cb46 154 /*** Return data size */
hillkim7 0:7f4bc855cb46 155 size_t get_data_size();
hillkim7 0:7f4bc855cb46 156
hillkim7 0:7f4bc855cb46 157 /*** Return one byte of data */
hillkim7 0:7f4bc855cb46 158 bool read_byte_data(uint8_t *c);
hillkim7 0:7f4bc855cb46 159
hillkim7 0:7f4bc855cb46 160 /*** Return n bytes of data */
hillkim7 0:7f4bc855cb46 161 size_t read_data( uint8_t *p, size_t p_size);
hillkim7 0:7f4bc855cb46 162 };
hillkim7 0:7f4bc855cb46 163