Open Model Railroad Network (OpenMRN)
Loading...
Searching...
No Matches
Stm32EEPROMEmulation.cxx
Go to the documentation of this file.
1
35
36#include <cstring>
37
38#include "stm32f_hal_conf.hxx"
39
40#if defined (STM32F030x6) || defined (STM32F031x6) || defined (STM32F038xx) \
41 || defined (STM32F030x8) || defined (STM32F030xC) || defined (STM32F042x6) \
42 || defined (STM32F048xx) || defined (STM32F051x8) || defined (STM32F058xx)
43const size_t Stm32EEPROMEmulation::PAGE_SIZE = 0x400;
44const size_t EEPROMEmulation::BLOCK_SIZE = 4;
46#elif defined (STM32F070x6) || defined (STM32F070xB) || defined (STM32F071xB) \
47 || defined (STM32F072xB) || defined (STM32F078xx) \
48 || defined (STM32F091xC) || defined (STM32F098xx) \
49 || defined (STM32F303xC) || defined (STM32F303xE)
50const size_t Stm32EEPROMEmulation::PAGE_SIZE = 0x800;
51const size_t EEPROMEmulation::BLOCK_SIZE = 4;
53#elif defined(STM32L432xx) || defined(STM32L431xx)
54const size_t Stm32EEPROMEmulation::PAGE_SIZE = 0x800;
55const size_t EEPROMEmulation::BLOCK_SIZE = 8;
57#define L4_FLASH
58#elif defined(STM32F767xx)
59// Note this assumes single-bank usage
60const size_t Stm32EEPROMEmulation::PAGE_SIZE = 256*1024;
61const size_t EEPROMEmulation::BLOCK_SIZE = 8;
63#define F7_FLASH
64#elif defined(STM32G0B1xx)
65// Note this assumes single-bank usage
66const size_t Stm32EEPROMEmulation::PAGE_SIZE = 0x800;
67const size_t EEPROMEmulation::BLOCK_SIZE = 8;
69#define L4_FLASH
70#else
71#error "stm32EEPROMEmulation unsupported STM32 device"
72#endif
73
78Stm32EEPROMEmulation::Stm32EEPROMEmulation(const char *name, size_t file_size)
79 : EEPROMEmulation(name, file_size)
80{
82 mount();
83}
84
85inline const uint32_t *Stm32EEPROMEmulation::get_block(
86 unsigned sector, unsigned offset)
87{
88 return (uint32_t*)(&__eeprom_start + sector * EEPROMEmulation::SECTOR_SIZE + offset * EEPROMEmulation::BLOCK_SIZE);
89}
90
97const uint32_t* Stm32EEPROMEmulation::block(unsigned sector, unsigned offset) {
98 return get_block(sector, offset);
99}
100
101#ifdef F7_FLASH
102extern "C" {
103extern const unsigned __stm32_eeprom_flash_sector_start;
104}
105#endif
106
111{
112 HASSERT(sector < sectorCount_);
113 uint32_t page_error;
114
115#ifdef F7_FLASH
116 FLASH_EraseInitTypeDef erase_init;
117 memset(&erase_init, 0, sizeof(erase_init));
118
119 erase_init.TypeErase = TYPEERASE_SECTORS;
120 erase_init.Sector =
121 ((unsigned)(&__stm32_eeprom_flash_sector_start)) + sector;
122 erase_init.NbSectors = 1;
123 erase_init.VoltageRange = FLASH_VOLTAGE_RANGE_3; // 3.3 to 3.6 volts powered.
125 portENTER_CRITICAL();
126 HAL_FLASH_Unlock();
127 HASSERT(HAL_OK == HAL_FLASHEx_Erase(&erase_init, &page_error));
128 HAL_FLASH_Lock();
129 portEXIT_CRITICAL();
130
131#else
132 auto* address = get_block(sector, 0);
133
134 FLASH_EraseInitTypeDef erase_init;
135 erase_init.TypeErase = FLASH_TYPEERASE_PAGES;
136#ifdef L4_FLASH
137 erase_init.Banks = FLASH_BANK_1;
138 uint32_t start_page = erase_init.Page =
139 (((uint32_t)address) - FLASH_BASE) / PAGE_SIZE;
140#else
141 erase_init.PageAddress = (uint32_t)address;
142#endif
143 erase_init.NbPages = SECTOR_SIZE / PAGE_SIZE;
144
145 portENTER_CRITICAL();
146 HAL_FLASH_Unlock();
147 // We erase the first page at the end, because the magic bytes are
148 // there. This is to make corruption less likely in case of a power
149 // interruption happens.
150 if (SECTOR_SIZE > PAGE_SIZE) {
151#ifdef L4_FLASH
152 erase_init.Page += 1;
153#else
154 erase_init.PageAddress += PAGE_SIZE;
155#endif
156 erase_init.NbPages--;
157 HAL_FLASHEx_Erase(&erase_init, &page_error);
158 erase_init.NbPages = 1;
159#ifdef L4_FLASH
160 erase_init.Page = start_page;
161#else
162 erase_init.PageAddress = (uint32_t)address;
163#endif
164 }
165 HAL_FLASHEx_Erase(&erase_init, &page_error);
166 HAL_FLASH_Lock();
167 portEXIT_CRITICAL();
168#endif
169}
170
180 unsigned relative_sector, unsigned start_block, uint32_t *data, uint32_t count)
181{
182 HASSERT(relative_sector < sectorCount_);
183 HASSERT((count % BLOCK_SIZE) == 0);
184 HASSERT(start_block + (count / BLOCK_SIZE) <= rawBlockCount_);
185 auto* address = get_block(relative_sector, start_block);
186
187 uintptr_t uint_address = (uintptr_t)address;
188
189 /* The STM32 program size is 16-bits, however BLOCK_SIZE is [at least]
190 * 32-bits. Because the upper 16-bits contains the EEPROM address, while
191 * the lower 16-bits contains the data. 0xFFFF is not considered a valid
192 * address by the generic EEPROM driver, therefore, so long as the data
193 * half-word is written ahead of the address half-word, there is no race
194 * condition on power failure.
195 */
196 while (count)
197 {
198 portENTER_CRITICAL();
199 HAL_FLASH_Unlock();
200#if defined(F7_FLASH)|| defined(L4_FLASH)
201 HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, uint_address, *(uint64_t*)data);
202#else
203 HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, uint_address, *data);
204#endif
205 HAL_FLASH_Lock();
206 portEXIT_CRITICAL();
207
208 count -= BLOCK_SIZE;
209 uint_address += BLOCK_SIZE;
210 data += (BLOCK_SIZE / sizeof(uint32_t));
211 }
212}
const char __eeprom_start
Linker-defined symbol where in the memory space (flash) the eeprom emulation data starts.
Emulates EEPROM in FLASH for the Tiva, LPC17xx and LPC40xx platforms.
static const size_t BLOCK_SIZE
block size in bytes
const uint16_t rawBlockCount_
How many blocks are there in a sector.
static const size_t SECTOR_SIZE
Sector size in bytes.
void mount()
Mount the EEPROM file.
static const size_t BYTES_PER_BLOCK
useful data bytes size in bytes
const uint8_t sectorCount_
Total number of sectors available.
void flash_erase(unsigned sector) override
Simple hardware abstraction for FLASH erase API.
const uint32_t * block(unsigned sector, unsigned offset) override
Computes the pointer to load the data stored in a specific block from.
void flash_program(unsigned sector, unsigned start_block, uint32_t *data, uint32_t byte_count) override
Simple hardware abstraction for FLASH program API.
Stm32EEPROMEmulation()
Default constructor.
static const uintptr_t PAGE_SIZE
The erase page length for the particular MCU.
#define HASSERT(x)
Checks that the value of expression x is true, else terminates the current process.
Definition macros.h:138