Skip to content

Commit eb2fc66

Browse files
author
Richard Unger
committed
unfinished STM32FlashSettingsStorage
1 parent 2316b78 commit eb2fc66

File tree

4 files changed

+252
-1
lines changed

4 files changed

+252
-1
lines changed

src/settings/README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@ Supported hardware:
1717

1818
- [SAMD NVM](samd/) \
1919
Some SAMD chips have a built-in NVRAM flash, which can be written from user code.
20-
- [CAT24 I2C Flash EEPROMs](i2c/) \ :warning: UNFINISHED
20+
- [CAT24 I2C Flash EEPROMs](i2c/) :warning: UNFINISHED \
2121
Simple programmable memories with I2C interface. Memory space is quite limited, but enough for storing settings.
22+
- [STM32 Flash](stm32/) :warning: UNFINISHED \
23+
Store settings directly to STM32 on-board flash
2224

2325
See Roadmap, below, for systems we may support in the future.
2426

src/settings/stm32/README.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
2+
# STM32 Flash Settings Storage
3+
4+
Store your settings directly to STM32 MCU's on-board flash memory.
5+
6+
To store the settings, the flash memory has to be erased in whole pages.
7+
8+
The page size is typically 1kB or 2kB. You can check your page size in the datasheet for your MCU.
9+
10+
The default settings storage location is the last page of the flash memory, meaning you have one page worth
11+
of space, maximum. If you need more space than this, you can provide the start address for the settings storage.
12+
13+
Needless to say, you can only store settings to flash if that memory is not also needed by your program. So you have to have some reserve space in the flash of the MCU you're using. If memory is too tight, use a STM32 model with more flash.
14+
15+
## Board setup
16+
17+
When storing settings to the Flash of your STM32 MCU, you have to consider what happens when you reprogram the MCU. Unless you have taken steps in the board setup files to reserve the pages of flash used by the settings, they will generally be erased and/or overwritten when programming the MCU.
18+
19+
To solve this, you can configure your board setup to reserve memory for settings, and not use that memory for program storage. Configuring STM32 board definitions for Arduino is out of scope for this readme, please find another reference.
20+
21+
## Usage
22+
23+
Using it is easy. Watch out if you have more than one page worth of settings to store, in which case you will need to configure the address to a different value from the default one.
24+
25+
```c++
26+
// uses default address, which is 1 page below the maximum flash address, e.g. the last page of the flash
27+
STM32FlashSettingsStorage settings = STM32FlashSettingsStorage();
28+
29+
// or use an address of your choice, in this case 10kB below the end of flash:
30+
#define SETTINGS_ADDRESS (FLASH_BASE + FLASH_SIZE - (1024*10))
31+
STM32FlashSettingsStorage settings = STM32FlashSettingsStorage(SETTINGS_ADDRESS);
32+
33+
// use as normal in the setup method:
34+
void setup() {
35+
SimpleFOCDebug::enable();
36+
37+
// link driver etc
38+
// set default settings on motor, etc
39+
40+
settings.addMotor(&motor);
41+
settings.init();
42+
SettingsStatus loadStatus = settings.loadSettings();
43+
driver.init();
44+
motor.init();
45+
motor.initFOC();
46+
if (motor.motor_status == FOCMotorStatus::motor_ready && loadStatus != SFOC_SETTINGS_SUCCESS) {
47+
settings.saveSettings();
48+
}
49+
}
50+
```
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
2+
3+
#include "./STM32FlashSettingsStorage.h"
4+
5+
#if defined(_STM32_DEF_)
6+
7+
#include "communication/SimpleFOCDebug.h"
8+
9+
10+
STM32FlashSettingsStorage::STM32FlashSettingsStorage(uint32_t address) {
11+
_address = address;
12+
};
13+
14+
STM32FlashSettingsStorage::~STM32FlashSettingsStorage(){};
15+
16+
17+
void STM32FlashSettingsStorage::init(){
18+
if (!IS_FLASH_PROGRAM_ADDRESS(_address))
19+
SimpleFOCDebug::println("SS: Invalid address");
20+
SettingsStorage::init();
21+
reset();
22+
};
23+
24+
25+
void STM32FlashSettingsStorage::reset() {
26+
_currptr = (uint8_t*)_address;
27+
};
28+
29+
30+
void STM32FlashSettingsStorage::beforeLoad(){
31+
reset();
32+
};
33+
34+
void STM32FlashSettingsStorage::beforeSave(){
35+
_writeptr = (uint8_t*)_address;
36+
_buffed = 0;
37+
_writeBuffer.l = 0;
38+
_page = PAGE_OF(_writeptr);
39+
if (HAL_FLASH_Unlock()!=HAL_OK)
40+
SimpleFOCDebug::println("SS: Flash unlock err");
41+
delay(50);
42+
erasePage(_page);
43+
delay(50);
44+
};
45+
46+
47+
void STM32FlashSettingsStorage::erasePage(uint32_t page) {
48+
FLASH_EraseInitTypeDef eraseInit;
49+
eraseInit.TypeErase = FLASH_TYPEERASE_PAGES;
50+
eraseInit.Page = page;
51+
eraseInit.Banks = _bank;
52+
eraseInit.NbPages = 1;
53+
uint32_t err;
54+
SimpleFOCDebug::print("SS: erase page ");
55+
SimpleFOCDebug::println((int)page);
56+
if (HAL_FLASHEx_Erase(&eraseInit, &err) != HAL_OK) {
57+
SimpleFOCDebug::println("SS: flash erase err");
58+
HAL_FLASH_Lock();
59+
return;
60+
}
61+
};
62+
63+
64+
void STM32FlashSettingsStorage::flushBuffer() {
65+
uint32_t page = PAGE_OF(_writeptr+7);
66+
if (page != _page) {
67+
erasePage(page);
68+
_page = page;
69+
}
70+
if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, (uint32_t)_writeptr, _writeBuffer.l)!=HAL_OK)
71+
SimpleFOCDebug::println("SS: Flash write err");
72+
_writeptr += 8;
73+
_buffed = 0;
74+
_writeBuffer.l = 0;
75+
};
76+
77+
78+
void STM32FlashSettingsStorage::afterSave(){
79+
if (_buffed > 0)
80+
flushBuffer();
81+
HAL_FLASH_Lock();
82+
};
83+
84+
85+
86+
int STM32FlashSettingsStorage::writeBytes(void* value, int numBytes) {
87+
uint8_t* bytes = (uint8_t*)value;
88+
for (int i=0;i<numBytes;i++) {
89+
_writeBuffer.b[_buffed++] = bytes[i];
90+
if (_buffed == 8)
91+
flushBuffer();
92+
}
93+
return numBytes;
94+
}
95+
96+
97+
98+
int STM32FlashSettingsStorage::readBytes(void* valueToSet, int numBytes) {
99+
uint8_t* bytes = (uint8_t*)valueToSet;
100+
for (int i=0;i<numBytes;i++) {
101+
uint8_t val = *_currptr++;
102+
bytes[i] = val;
103+
}
104+
return numBytes;
105+
}
106+
107+
108+
uint8_t STM32FlashSettingsStorage::readByte(uint8_t* valueToSet) {
109+
uint8_t val;
110+
uint8_t num = readBytes(&val, 1);
111+
if (num==1)
112+
*valueToSet = val;
113+
return num;
114+
};
115+
116+
uint8_t STM32FlashSettingsStorage::readFloat(float* valueToSet) {
117+
float val;
118+
uint8_t num = readBytes(&val, 4);
119+
if (num==4)
120+
*valueToSet = val;
121+
return num;
122+
};
123+
124+
uint8_t STM32FlashSettingsStorage::readInt(uint32_t* valueToSet) {
125+
uint32_t val;
126+
uint8_t num = readBytes(&val, 4);
127+
if (num==4)
128+
*valueToSet = val;
129+
return num;
130+
};
131+
132+
133+
134+
uint8_t STM32FlashSettingsStorage::writeByte(uint8_t value) {
135+
return writeBytes(&value, 1);
136+
};
137+
138+
139+
uint8_t STM32FlashSettingsStorage::writeFloat(float value) {
140+
return writeBytes(&value, 4);
141+
};
142+
143+
144+
uint8_t STM32FlashSettingsStorage::writeInt(uint32_t value) {
145+
return writeBytes(&value, 4);
146+
};
147+
148+
#endif
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
2+
#pragma once
3+
4+
#include "../SettingsStorage.h"
5+
6+
#if defined(_STM32_DEF_)
7+
8+
#define PAGE_OF(x) (((uint32_t)x - FLASH_BASE) / FLASH_PAGE_SIZE)
9+
10+
11+
class STM32FlashSettingsStorage : public SettingsStorage {
12+
public:
13+
STM32FlashSettingsStorage(uint32_t address = FLASH_BASE + FLASH_SIZE - FLASH_PAGE_SIZE);
14+
~STM32FlashSettingsStorage();
15+
16+
void init() override;
17+
18+
uint32_t _bank = FLASH_BANK_1;
19+
20+
protected:
21+
uint8_t readByte(uint8_t* valueToSet) override;
22+
uint8_t readFloat(float* valueToSet) override;
23+
uint8_t readInt(uint32_t* valueToSet) override;
24+
25+
uint8_t writeByte(uint8_t value) override;
26+
uint8_t writeFloat(float value) override;
27+
uint8_t writeInt(uint32_t value) override;
28+
29+
void beforeLoad() override;
30+
void beforeSave() override;
31+
void afterSave() override;
32+
33+
void flushBuffer();
34+
void erasePage(uint32_t page);
35+
void reset();
36+
int readBytes(void* valueToSet, int numBytes);
37+
int writeBytes(void* value, int numBytes);
38+
39+
uint32_t _address;
40+
uint8_t* _currptr;
41+
uint8_t* _writeptr;
42+
uint8_t _buffed = 0;
43+
uint32_t _page = 0;
44+
union {
45+
uint8_t b[8];
46+
uint64_t l;
47+
} _writeBuffer; // 64-bit buffer
48+
};
49+
50+
51+
#endif

0 commit comments

Comments
 (0)