|
1 | 1 | /*
|
2 |
| - Copyright 2016 - 2019 Benjamin Vedder [email protected] |
| 2 | + Copyright 2016 - 2021 Benjamin Vedder [email protected] |
3 | 3 |
|
4 | 4 | This file is part of the VESC firmware.
|
5 | 5 |
|
|
26 | 26 | #include "timeout.h"
|
27 | 27 | #include "hw.h"
|
28 | 28 | #include "crc.h"
|
| 29 | +#include "buffer.h" |
29 | 30 | #include <string.h>
|
30 | 31 |
|
31 | 32 | /*
|
|
36 | 37 | #define APP_BASE 0
|
37 | 38 | #define NEW_APP_BASE 8
|
38 | 39 | #define NEW_APP_SECTORS 3
|
39 |
| -#define APP_MAX_SIZE (393216 - 8) // Note that the bootloader needs 8 extra bytes |
| 40 | +#define APP_MAX_SIZE (1024 * 128 * 3 - 8) // Note that the bootloader needs 8 extra bytes |
| 41 | +#define QMLUI_BASE 7 |
| 42 | +#define QMLUI_MAX_SIZE (1024 * 128 - 8) |
40 | 43 |
|
41 | 44 | // Base address of the Flash sectors
|
42 | 45 | #define ADDR_FLASH_SECTOR_0 ((uint32_t)0x08000000) // Base @ of Sector 0, 16 Kbytes
|
|
66 | 69 | typedef struct {
|
67 | 70 | uint32_t crc_flag;
|
68 | 71 | uint32_t crc;
|
69 |
| -}crc_info_t; |
| 72 | +} crc_info_t; |
70 | 73 |
|
71 |
| -//Make sure the app image has the CRC bits set to '1' to later write the flag and CRC. |
| 74 | +// Make sure the app image has the CRC bits set to '1' to later write the flag and CRC. |
72 | 75 | const crc_info_t __attribute__((section (".crcinfo"))) crc_info = {0xFFFFFFFF, 0xFFFFFFFF};
|
73 | 76 |
|
| 77 | +// Private functions |
| 78 | +static uint16_t erase_sector(uint32_t sector); |
| 79 | +static uint16_t write_data(uint32_t base, uint8_t *data, uint32_t len); |
| 80 | +static void qmlui_check(void); |
| 81 | + |
| 82 | +// Private variables |
| 83 | +static bool qmlui_check_done = false; |
| 84 | +static bool qmlui_ok = false; |
| 85 | + |
74 | 86 | // Private constants
|
75 | 87 | static const uint32_t flash_addr[FLASH_SECTORS] = {
|
76 | 88 | ADDR_FLASH_SECTOR_0,
|
@@ -135,52 +147,57 @@ uint16_t flash_helper_erase_new_app(uint32_t new_app_size) {
|
135 | 147 | }
|
136 | 148 |
|
137 | 149 | uint16_t flash_helper_erase_bootloader(void) {
|
138 |
| - FLASH_Unlock(); |
139 |
| - FLASH_ClearFlag(FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | |
140 |
| - FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR); |
141 |
| - |
142 |
| - mc_interface_unlock(); |
143 |
| - mc_interface_release_motor(); |
144 |
| - utils_sys_lock_cnt(); |
145 |
| - timeout_configure_IWDT_slowest(); |
146 |
| - |
147 |
| - uint16_t res = FLASH_EraseSector(flash_sector[BOOTLOADER_BASE], VoltageRange_3); |
148 |
| - if (res != FLASH_COMPLETE) { |
149 |
| - FLASH_Lock(); |
150 |
| - return res; |
151 |
| - } |
| 150 | + return erase_sector(flash_sector[BOOTLOADER_BASE]); |
| 151 | +} |
152 | 152 |
|
153 |
| - FLASH_Lock(); |
154 |
| - timeout_configure_IWDT(); |
155 |
| - utils_sys_unlock_cnt(); |
| 153 | +uint16_t flash_helper_write_new_app_data(uint32_t offset, uint8_t *data, uint32_t len) { |
| 154 | + return write_data(flash_addr[NEW_APP_BASE] + offset, data, len); |
| 155 | +} |
156 | 156 |
|
157 |
| - return FLASH_COMPLETE; |
| 157 | +uint16_t flash_helper_erase_qmlui(void) { |
| 158 | + qmlui_check_done = false; |
| 159 | + qmlui_ok = false; |
| 160 | + return erase_sector(flash_sector[QMLUI_BASE]); |
158 | 161 | }
|
159 | 162 |
|
160 |
| -uint16_t flash_helper_write_new_app_data(uint32_t offset, uint8_t *data, uint32_t len) { |
161 |
| - FLASH_Unlock(); |
162 |
| - FLASH_ClearFlag(FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | |
163 |
| - FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR); |
| 163 | +uint16_t flash_helper_write_qmlui(uint32_t offset, uint8_t *data, uint32_t len) { |
| 164 | + qmlui_check_done = false; |
| 165 | + qmlui_ok = false; |
| 166 | + return write_data(flash_addr[QMLUI_BASE] + offset, data, len); |
| 167 | +} |
164 | 168 |
|
165 |
| - mc_interface_unlock(); |
166 |
| - mc_interface_release_motor(); |
167 |
| - utils_sys_lock_cnt(); |
168 |
| - timeout_configure_IWDT_slowest(); |
| 169 | +uint8_t *flash_helper_qmlui_data(void) { |
| 170 | + qmlui_check(); |
169 | 171 |
|
170 |
| - for (uint32_t i = 0;i < len;i++) { |
171 |
| - uint16_t res = FLASH_ProgramByte(flash_addr[NEW_APP_BASE] + offset + i, data[i]); |
172 |
| - if (res != FLASH_COMPLETE) { |
173 |
| - FLASH_Lock(); |
174 |
| - return res; |
175 |
| - } |
| 172 | + if (qmlui_check_done && qmlui_ok) { |
| 173 | + return (uint8_t*)(flash_addr[QMLUI_BASE]) + 8; |
| 174 | + } else { |
| 175 | + return 0; |
176 | 176 | }
|
177 |
| - FLASH_Lock(); |
| 177 | +} |
178 | 178 |
|
179 |
| - timeout_configure_IWDT(); |
| 179 | +uint32_t flash_helper_qmlui_size(void) { |
| 180 | + qmlui_check(); |
180 | 181 |
|
181 |
| - utils_sys_unlock_cnt(); |
| 182 | + if (qmlui_check_done && qmlui_ok) { |
| 183 | + uint8_t *qmlui_base = (uint8_t*)(flash_addr[QMLUI_BASE]); |
| 184 | + int32_t ind = 0; |
| 185 | + return buffer_get_uint32(qmlui_base, &ind); |
| 186 | + } else { |
| 187 | + return 0; |
| 188 | + } |
| 189 | +} |
182 | 190 |
|
183 |
| - return FLASH_COMPLETE; |
| 191 | +uint16_t flash_helper_qmlui_flags(void) { |
| 192 | + qmlui_check(); |
| 193 | + |
| 194 | + if (qmlui_check_done && qmlui_ok) { |
| 195 | + uint8_t *qmlui_base = (uint8_t*)(flash_addr[QMLUI_BASE]); |
| 196 | + int32_t ind = 6; |
| 197 | + return buffer_get_uint16(qmlui_base, &ind); |
| 198 | + } else { |
| 199 | + return 0; |
| 200 | + } |
184 | 201 | }
|
185 | 202 |
|
186 | 203 | /**
|
@@ -339,3 +356,72 @@ uint32_t flash_helper_verify_flash_memory_chunk(void) {
|
339 | 356 |
|
340 | 357 | return res;
|
341 | 358 | }
|
| 359 | + |
| 360 | +static uint16_t erase_sector(uint32_t sector) { |
| 361 | + FLASH_Unlock(); |
| 362 | + FLASH_ClearFlag(FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | |
| 363 | + FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR); |
| 364 | + |
| 365 | + mc_interface_unlock(); |
| 366 | + mc_interface_release_motor(); |
| 367 | + utils_sys_lock_cnt(); |
| 368 | + timeout_configure_IWDT_slowest(); |
| 369 | + |
| 370 | + uint16_t res = FLASH_EraseSector(sector, VoltageRange_3); |
| 371 | + if (res != FLASH_COMPLETE) { |
| 372 | + FLASH_Lock(); |
| 373 | + return res; |
| 374 | + } |
| 375 | + |
| 376 | + FLASH_Lock(); |
| 377 | + timeout_configure_IWDT(); |
| 378 | + utils_sys_unlock_cnt(); |
| 379 | + |
| 380 | + return FLASH_COMPLETE; |
| 381 | +} |
| 382 | + |
| 383 | +static uint16_t write_data(uint32_t base, uint8_t *data, uint32_t len) { |
| 384 | + FLASH_Unlock(); |
| 385 | + FLASH_ClearFlag(FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | |
| 386 | + FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR); |
| 387 | + |
| 388 | + mc_interface_unlock(); |
| 389 | + mc_interface_release_motor(); |
| 390 | + utils_sys_lock_cnt(); |
| 391 | + timeout_configure_IWDT_slowest(); |
| 392 | + |
| 393 | + for (uint32_t i = 0;i < len;i++) { |
| 394 | + uint16_t res = FLASH_ProgramByte(base + i, data[i]); |
| 395 | + if (res != FLASH_COMPLETE) { |
| 396 | + FLASH_Lock(); |
| 397 | + return res; |
| 398 | + } |
| 399 | + } |
| 400 | + FLASH_Lock(); |
| 401 | + |
| 402 | + timeout_configure_IWDT(); |
| 403 | + |
| 404 | + utils_sys_unlock_cnt(); |
| 405 | + |
| 406 | + return FLASH_COMPLETE; |
| 407 | +} |
| 408 | + |
| 409 | +static void qmlui_check(void) { |
| 410 | + if (qmlui_check_done) { |
| 411 | + return; |
| 412 | + } |
| 413 | + |
| 414 | + uint8_t *qmlui_base = (uint8_t*)(flash_addr[QMLUI_BASE]); |
| 415 | + int32_t ind = 0; |
| 416 | + uint32_t qmlui_len = buffer_get_uint32(qmlui_base, &ind); |
| 417 | + uint16_t qmlui_crc = buffer_get_uint16(qmlui_base, &ind); |
| 418 | + |
| 419 | + if (qmlui_len <= QMLUI_MAX_SIZE) { |
| 420 | + uint16_t crc_calc = crc16(qmlui_base + ind, qmlui_len + 2); // CRC includes the 2 byte flags |
| 421 | + qmlui_ok = crc_calc == qmlui_crc; |
| 422 | + } else { |
| 423 | + qmlui_ok = false; |
| 424 | + } |
| 425 | + |
| 426 | + qmlui_check_done = true; |
| 427 | +} |
0 commit comments