Open FFBoard
Open source force feedback firmware
flash_helpers.cpp
Go to the documentation of this file.
1/*
2 * flash_helpers.cpp
3 *
4 * Created on: 31.01.2020
5 * Author: Yannick
6 */
7#include "flash_helpers.h"
8#include "eeprom_addresses.h"
9#include <vector>
10#include "mutex.hpp"
11
13// Flash helpers
14
15// TODO sometimes on F4 chips when writing HAL_FLASH_ERROR_PGS and HAL_FLASH_ERROR_PGP occur and it is not writing
16
17
18#ifdef USE_EEPROM_EMULATION
19
24 HAL_FLASH_Unlock();
25 bool res = (EE_Format() == HAL_OK);
26 HAL_FLASH_Lock();
27 return res;
28}
32__weak bool Flash_Init(){
33 HAL_FLASH_Unlock();
34 // Clear all the error flags
35 __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP);
36 __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPERR);
37 __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_WRPERR);
38 __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_PGAERR);
39 __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_PGPERR);
40 __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_PGSERR);
41
42 bool state = (EE_Init() == EE_OK);
43 HAL_FLASH_Lock();
44 return state;
45}
46/*
47 * Writes a variable to eeprom emulation adr
48 * Returns true on success or false if variable is the same or error
49 */
50bool Flash_Write(uint16_t adr,uint16_t dat){
51 //flashMutex.Lock();
52 uint16_t buf;
53 uint16_t readRes = EE_ReadVariable(adr, &buf);
54 bool res = false;
55 if(readRes == 1 || (readRes == 0 && buf != dat) ){ // Only write if var updated
56 HAL_FLASH_Unlock();
57 __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP);
58 __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPERR);
59 __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_WRPERR);
60 __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_PGAERR);
61 __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_PGPERR);
62 __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_PGSERR);
63 if(EE_WriteVariable(adr, dat) == HAL_OK){
64 res = true;
65 }
66 HAL_FLASH_Lock();
67
68 }
69 //flashMutex.Unlock();
70 return res;
71
72}
73
74
75/*
76 * Reads a variable from eeprom emulation and returns true on success
77 */
78bool Flash_Read(uint16_t adr,uint16_t *buf,bool checkempty){
79 //flashMutex.Lock();
80 bool res = EE_ReadVariable(adr, buf) == 0;
81 //flashMutex.Unlock();
82 return res;
83}
84
85/*
86 * Reads a variable or if it does not exist default is written
87 */
88bool Flash_ReadWriteDefault(uint16_t adr,uint16_t *buf,uint16_t def){
89 if(EE_ReadVariable(adr, buf) != 0){
90 *buf = def;
91 HAL_FLASH_Unlock();
92 // Clear all the error flags
93 __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP);
94 __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPERR);
95 __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_WRPERR);
96 __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_PGAERR);
97 __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_PGPERR);
98 __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_PGSERR);
100 HAL_FLASH_Lock();
101 return false;
102 }
103 return true;
104}
105
106#elif defined(I2C_PORT_EEPROM)
107uint8_t i2cBufferEeprom[sizeof(uint16_t)] = {0};
108#include "string.h" // Memcpy
109#include "cassert"
110
111
112bool Flash_Write(uint16_t adr,uint16_t dat){
113 uint16_t dataLength = sizeof(dat);
114 memcpy(i2cBufferEeprom,&dat, dataLength);
115 adr *= sizeof(dat)/I2C_EEPROM_DATA_SIZE;
116 adr = I2C_EEPROM_OFS+adr;
117 uint16_t curAdr = adr;
118 assert(adr < I2C_EEPROM_SIZE);
119
120 // Do segmented writes
121 bool res = false;
122 while(curAdr < adr+dataLength){
123 while(!HAL_I2C_IsDeviceReady(&I2C_PORT_EEPROM, I2C_EEPROM_ADR, 100, I2C_EEPROM_TIMEOUT) == HAL_OK){
124 HAL_Delay(1);
125 }
126
127 uint16_t wLen = std::min<uint16_t>(dataLength,I2C_EEPROM_PAGEWRITE_SIZE - (adr % I2C_EEPROM_PAGEWRITE_SIZE));
128 res = HAL_I2C_Mem_Write(&I2C_PORT_EEPROM, I2C_EEPROM_ADR, curAdr, I2C_EEPROM_ADR_SIZE, i2cBufferEeprom, wLen,I2C_EEPROM_TIMEOUT) == HAL_OK;
129 curAdr+=wLen;
130 if(!res){
131 break;
132 }
133 }
134
135 return res;
136}
137bool Flash_ReadWriteDefault(uint16_t adr,uint16_t *buf,uint16_t def){
138 if(!Flash_Read(adr,buf)){
139 return Flash_Write(adr, def);
140 }
141 return true;
142}
146bool Flash_Read(uint16_t adr,uint16_t *buf, bool checkempty){
147 adr *= sizeof(*buf)/I2C_EEPROM_DATA_SIZE;
148 assert(adr < I2C_EEPROM_SIZE);
149 while(!HAL_I2C_IsDeviceReady(&I2C_PORT_EEPROM, I2C_EEPROM_ADR, 100, I2C_EEPROM_TIMEOUT) == HAL_OK){
150 HAL_Delay(1);
151 }
152 bool res = HAL_I2C_Mem_Read(&I2C_PORT_EEPROM, I2C_EEPROM_ADR, I2C_EEPROM_OFS+adr, I2C_EEPROM_ADR_SIZE, i2cBufferEeprom, 2, I2C_EEPROM_TIMEOUT) == HAL_OK;
153
154 if(checkempty){
155 bool empty = true;
156 for(uint8_t i = 0;i<sizeof(i2cBufferEeprom);i++){
157 if(i2cBufferEeprom[i] != I2C_EEPROM_ERASED){
158 empty = false;
159 break;
160 }
161 }
162 res = empty ? false : res;
163 }
164 if(res) // Only copy if success
166 return res;
167}
168
173 bool flag = true;
174 std::array<uint8_t,I2C_EEPROM_PAGEWRITE_SIZE> eraseBuf;
175 eraseBuf.fill(I2C_EEPROM_ERASED);
176 for(uint32_t i=I2C_EEPROM_OFS;i<I2C_EEPROM_SIZE;i+=I2C_EEPROM_PAGEWRITE_SIZE){
177
178 bool res = HAL_I2C_Mem_Write(&I2C_PORT_EEPROM, I2C_EEPROM_ADR, I2C_EEPROM_OFS+i, I2C_EEPROM_ADR_SIZE, eraseBuf.data(), std::min<int>(I2C_EEPROM_PAGEWRITE_SIZE,I2C_EEPROM_SIZE-i),I2C_EEPROM_TIMEOUT) == HAL_OK;
179 if(!res){
180 flag = false;
181 }else{
182 while(!HAL_I2C_IsDeviceReady(&I2C_PORT_EEPROM, I2C_EEPROM_ADR, 100, I2C_EEPROM_TIMEOUT) == HAL_OK){
183 HAL_Delay(1);
184 }
185 }
186 }
187 return flag;
188}
190 return HAL_I2C_IsDeviceReady(&I2C_PORT_EEPROM, I2C_EEPROM_ADR, 10, I2C_EEPROM_TIMEOUT) == HAL_OK;
191}
192
193#else
194// No flash mode defined
195
196__weak bool Flash_Write(uint16_t adr,uint16_t dat){
197 return true;
198}
199__weak bool Flash_ReadWriteDefault(uint16_t adr,uint16_t *buf,uint16_t def){
200 return true;
201}
202__weak bool Flash_Read(uint16_t adr,uint16_t *buf){
203 return false;
204}
205__weak bool Flash_Format(){
206 return false;
207}
208__weak bool Flash_Init(){
209 return true;
210}
211#endif
212/*
213 * Dumps all set variables from flash to a vector
214 * does by default not include certain calibration constants that could break something if imported on a different board
215 */
216void Flash_Dump(std::vector<std::tuple<uint16_t,uint16_t>> *result,bool includeAll){
217 uint16_t amount = NB_EXPORTABLE_ADR;
218 const uint16_t* list = exportableFlashAddresses;
219 if(includeAll){
220 amount = NB_OF_VAR;
221 list = VirtAddVarTab;
222 }
223 //extern uint16_t VirtAddVarTab[NB_OF_VAR];
224 //std::vector<std::pair<uint16_t,uint16_t>> result;
225
226 for(uint32_t i = 0;i<amount ; i++){
227 uint16_t v;
228 uint16_t adr = list[i];
229
230 if(Flash_Read(adr,&v)){
231 result->push_back(std::tuple<uint16_t,uint16_t>{adr,v});
232 }
233
234 }
235}
uint8_t adr
const uint16_t VirtAddVarTab[NB_OF_VAR]
const uint16_t exportableFlashAddresses[NB_EXPORTABLE_ADR]
__weak bool Flash_Init()
bool Flash_Read(uint16_t adr, uint16_t *buf, bool checkempty)
bool Flash_Format()
bool Flash_ReadWriteDefault(uint16_t adr, uint16_t *buf, uint16_t def)
bool Flash_Write(uint16_t adr, uint16_t dat)
void Flash_Dump(std::vector< std::tuple< uint16_t, uint16_t > > *result, bool includeAll)
uint8_t i2cBufferEeprom[sizeof(uint16_t)]
cpp_freertos::MutexStandard flashMutex
uint16_t EE_ReadVariable(uint16_t VirtAddress, uint16_t *Data)
Returns the last stored variable data, if found, which correspond to the passed virtual address.
Definition: eeprom.c:370
uint16_t EE_WriteVariable(uint16_t VirtAddress, uint16_t Data)
Writes/upadtes variable data in EEPROM.
Definition: eeprom.c:429
HAL_StatusTypeDef EE_Format()
Erases PAGE and PAGE1 and writes VALID_PAGE header to PAGE.
Definition: eeprom.c:453
uint16_t EE_Init(void)
Restore the pages to a known good state in case of page's status corruption after a power loss.
Definition: eeprom.c:79
static void * memcpy(void *dst, const void *src, size_t n)
Definition: ringbuffer.c:8