Stores data on the flash memory of stm32f4xx

Dependents:   DISCO-F429ZI_LCDTS_demo_richard

Fork of storage_on_flash by henning l

Committer:
pierrebizouard
Date:
Fri Mar 16 15:50:04 2018 +0000
Revision:
1:801ddc4634a5
Parent:
0:4cb438b58dc2
added support for 429ZI up to bank 11

Who changed what in which revision?

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