25
25
#include "mc_interface.h"
26
26
#include "timeout.h"
27
27
#include "hw.h"
28
+ #include "crc.h"
28
29
#include <string.h>
29
30
30
31
/*
35
36
#define APP_BASE 0
36
37
#define NEW_APP_BASE 8
37
38
#define NEW_APP_SECTORS 3
39
+ #define APP_MAX_SIZE (3 * (1 << 17))
40
+ #define EEPROM_EMULATION_SIZE 0x8000
38
41
39
42
// Base address of the Flash sectors
40
43
#define ADDR_FLASH_SECTOR_0 ((uint32_t)0x08000000) // Base @ of Sector 0, 16 Kbytes
50
53
#define ADDR_FLASH_SECTOR_10 ((uint32_t)0x080C0000) // Base @ of Sector 10, 128 Kbytes
51
54
#define ADDR_FLASH_SECTOR_11 ((uint32_t)0x080E0000) // Base @ of Sector 11, 128 Kbytes
52
55
56
+ #define APP_CRC_WAS_CALCULATED_FLAG ((uint32_t)0xAAAAAAAA)
57
+ #define APP_CRC_WAS_CALCULATED_FLAG_ADDRESS (uint32_t*)(APP_MAX_SIZE - 8)
58
+
59
+ #define VECTOR_TABLE_ADDRESS ((uint32_t *)ADDR_FLASH_SECTOR_0)
60
+ #define VECTOR_TABLE_SIZE ((uint32_t)(ADDR_FLASH_SECTOR_1 - ADDR_FLASH_SECTOR_0))
61
+
62
+ #define APP_START_ADDRESS ((uint32_t *)(ADDR_FLASH_SECTOR_1 + EEPROM_EMULATION_SIZE))
63
+ #define APP_SIZE ((uint32_t)(APP_MAX_SIZE - VECTOR_TABLE_SIZE - EEPROM_EMULATION_SIZE))
64
+
65
+ typedef struct {
66
+ uint32_t crc_flag ;
67
+ uint32_t crc ;
68
+ }crc_info_t ;
69
+
70
+ //Make sure the app image has the CRC bits set to '1' to later write the flag and CRC.
71
+ const crc_info_t __attribute__((section (".crcinfo" ))) crc_info = {0xFFFFFFFF , 0xFFFFFFFF };
72
+
53
73
// Private constants
54
74
static const uint32_t flash_addr [FLASH_SECTORS ] = {
55
75
ADDR_FLASH_SECTOR_0 ,
@@ -96,12 +116,14 @@ uint16_t flash_helper_erase_new_app(uint32_t new_app_size) {
96
116
if (new_app_size > flash_addr [NEW_APP_BASE + i ]) {
97
117
uint16_t res = FLASH_EraseSector (flash_sector [NEW_APP_BASE + i ], VoltageRange_3 );
98
118
if (res != FLASH_COMPLETE ) {
119
+ FLASH_Lock ();
99
120
return res ;
100
121
}
101
122
} else {
102
123
break ;
103
124
}
104
125
}
126
+ FLASH_Lock ();
105
127
106
128
timeout_configure_IWDT ();
107
129
utils_sys_unlock_cnt ();
@@ -110,6 +132,7 @@ uint16_t flash_helper_erase_new_app(uint32_t new_app_size) {
110
132
}
111
133
112
134
uint16_t flash_helper_write_new_app_data (uint32_t offset , uint8_t * data , uint32_t len ) {
135
+ FLASH_Unlock ();
113
136
FLASH_ClearFlag (FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR |
114
137
FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR );
115
138
@@ -121,9 +144,11 @@ uint16_t flash_helper_write_new_app_data(uint32_t offset, uint8_t *data, uint32_
121
144
for (uint32_t i = 0 ;i < len ;i ++ ) {
122
145
uint16_t res = FLASH_ProgramByte (flash_addr [NEW_APP_BASE ] + offset + i , data [i ]);
123
146
if (res != FLASH_COMPLETE ) {
147
+ FLASH_Lock ();
124
148
return res ;
125
149
}
126
150
}
151
+ FLASH_Lock ();
127
152
128
153
timeout_configure_IWDT ();
129
154
@@ -191,3 +216,98 @@ uint8_t* flash_helper_get_sector_address(uint32_t fsector) {
191
216
192
217
return res ;
193
218
}
219
+
220
+ /**
221
+ * @brief Compute the CRC of the application code to verify its integrity
222
+ * @retval FAULT_CODE_NONE or FAULT_CODE_FLASH_CORRUPTION
223
+ */
224
+ uint32_t flash_helper_verify_flash_memory (void ) {
225
+ uint32_t crc ;
226
+ // Look for a flag indicating that the CRC was previously computed.
227
+ // If it is blank (0xFFFFFFFF), calculate and store the CRC.
228
+ if ( (APP_CRC_WAS_CALCULATED_FLAG_ADDRESS )[0 ] == APP_CRC_WAS_CALCULATED_FLAG )
229
+ {
230
+ RCC_AHB1PeriphClockCmd (RCC_AHB1Periph_CRC , ENABLE );
231
+ crc32_reset ();
232
+
233
+ // compute vector table (sector 0)
234
+ crc32 ((VECTOR_TABLE_ADDRESS ), (VECTOR_TABLE_SIZE )/4 );
235
+
236
+ // skip emulated EEPROM (sector 1 and 2)
237
+
238
+ // compute application code
239
+ crc = crc32 (APP_START_ADDRESS , (APP_SIZE )/4 );
240
+
241
+ RCC_AHB1PeriphClockCmd (RCC_AHB1Periph_CRC , DISABLE );
242
+
243
+ // A CRC over the full image should return zero.
244
+ return (crc == 0 )? FAULT_CODE_NONE : FAULT_CODE_FLASH_CORRUPTION ;
245
+ }
246
+ else {
247
+ FLASH_Unlock ();
248
+ FLASH_ClearFlag (FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR |
249
+ FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR );
250
+
251
+ //Write the flag to indicate CRC has been computed.
252
+ uint16_t res = FLASH_ProgramWord ((uint32_t )APP_CRC_WAS_CALCULATED_FLAG_ADDRESS , APP_CRC_WAS_CALCULATED_FLAG );
253
+ if (res != FLASH_COMPLETE ) {
254
+ FLASH_Lock ();
255
+ return FAULT_CODE_FLASH_CORRUPTION ;
256
+ }
257
+
258
+ // Compute flash crc including the new flag
259
+ RCC_AHB1PeriphClockCmd (RCC_AHB1Periph_CRC , ENABLE );
260
+ crc32_reset ();
261
+
262
+ // compute vector table (sector 0)
263
+ crc32 (VECTOR_TABLE_ADDRESS , (VECTOR_TABLE_SIZE )/4 );
264
+
265
+ // skip emulated EEPROM (sector 1 and 2)
266
+
267
+ // compute application code
268
+ crc = crc32 (APP_START_ADDRESS , (APP_SIZE - 4 )/4 );
269
+
270
+ RCC_AHB1PeriphClockCmd (RCC_AHB1Periph_CRC , DISABLE );
271
+
272
+ //Store CRC
273
+ res = FLASH_ProgramWord (APP_MAX_SIZE - 4 , crc );
274
+ if (res != FLASH_COMPLETE ) {
275
+ FLASH_Lock ();
276
+ return FAULT_CODE_FLASH_CORRUPTION ;
277
+ }
278
+ FLASH_Lock ();
279
+
280
+ // reboot
281
+ NVIC_SystemReset ();
282
+ return FAULT_CODE_NONE ;
283
+ }
284
+ }
285
+
286
+ uint32_t flash_helper_verify_flash_memory_chunk (void ) {
287
+ static uint32_t index = 0 ;
288
+ const uint32_t chunk_size = 8192 ;
289
+ uint32_t res = FAULT_CODE_NONE ;
290
+ uint32_t crc = 0 ;
291
+
292
+ // Make sure RCC_AHB1Periph_CRC is enabled
293
+ if (index == 0 ) {
294
+ crc32_reset ();
295
+ }
296
+
297
+ if (index < VECTOR_TABLE_SIZE ) {
298
+ crc32 ((VECTOR_TABLE_ADDRESS + index ), chunk_size /4 );
299
+ }
300
+ else {
301
+ crc = crc32 ((uint32_t * )((uint32_t )APP_START_ADDRESS + index - VECTOR_TABLE_SIZE ), chunk_size /4 );
302
+ }
303
+
304
+ index += chunk_size ;
305
+ if (index >= (VECTOR_TABLE_SIZE + APP_SIZE )) {
306
+ index = 0 ;
307
+ if (crc != 0 ) {
308
+ res = FAULT_CODE_FLASH_CORRUPTION ;
309
+ }
310
+ }
311
+ return res ;
312
+ }
313
+
0 commit comments