iap.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. #include "at32f403a_407.h"
  2. #include "iap.h"
  3. #include "common_config.h"
  4. #include "FreeRTOS.h"
  5. #include "task.h"
  6. #include "semphr.h"
  7. #include "fr_timers.h"
  8. #include "event_groups.h"
  9. #include "mb.h"
  10. #include "mbport.h"
  11. #include "mbrtu.h"
  12. #include <stdio.h>
  13. #include <string.h>
  14. EventGroupHandle_t event;
  15. SemaphoreHandle_t buf_sem;
  16. SemaphoreHandle_t flash_sem;
  17. TimerHandle_t led_timer_handle;
  18. uint32_t fw_size; // Размер FW (передается в первом пакете)
  19. static uint16_t i_big_package;
  20. static uint16_t i_short_package;
  21. uint8_t fw_buf_1[FW_BUF_SIZE];
  22. uint8_t fw_buf_2[FW_BUF_SIZE];
  23. bool flash_err_flag = false;
  24. void led_timer(TimerHandle_t timer);
  25. void iap_task(void *params);
  26. //
  27. void iap_init(void)
  28. {
  29. flash_sem = xSemaphoreCreateBinary();
  30. led_timer_handle = xTimerCreate("led_timer", 500, pdTRUE, (void *)0, led_timer);
  31. xTimerStart(led_timer_handle, 0);
  32. xTaskCreate(iap_task, "iap_task", 4*configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL);
  33. }
  34. //
  35. void iap_task(void *params)
  36. {
  37. (void)(params);
  38. unsigned int ev;
  39. event = xEventGroupCreate();
  40. buf_sem = xSemaphoreCreateBinary();
  41. xSemaphoreGive(buf_sem);
  42. if (ev = xEventGroupWaitBits(event, IAP_START | IAP_RETURN, pdTRUE, pdFALSE, 60000) != IAP_START)
  43. {
  44. printf("IAP: switch to FW!\r\n");
  45. bpr_data_write(BPR_DATA1, 0);
  46. NVIC_SystemReset();
  47. }
  48. if (ev == IAP_RETURN)
  49. {
  50. printf("IAP: return to FW\r\n");
  51. bpr_data_write(BPR_DATA1, 0);
  52. vTaskDelay(200);
  53. NVIC_SystemReset();
  54. }
  55. for (;;)
  56. {
  57. ev = xEventGroupWaitBits(event,
  58. IAP_BLOCK | IAP_FINISH | IAP_RETURN |
  59. IAP_FLASH_ERROR | IAP_RESET,
  60. pdTRUE, pdFALSE, portMAX_DELAY);
  61. switch (ev)
  62. {
  63. case IAP_BLOCK :
  64. write_buf();
  65. break;
  66. // Запись завершена. Нужно провести проверку CRC.
  67. case IAP_FINISH :
  68. flash_lock();
  69. DBG printf("IAP: finish\r\n");
  70. bpr_data_write(BPR_DATA1, 0);
  71. vTaskDelay(100);
  72. NVIC_SystemReset();
  73. break;
  74. // Возврат в основное ПО
  75. case IAP_RETURN :
  76. DBG printf("IAP: return to FW\r\n");
  77. bpr_data_write(BPR_DATA1, 0);
  78. vTaskDelay(100);
  79. NVIC_SystemReset();
  80. break;
  81. // Ошибка работы с flash
  82. case IAP_FLASH_ERROR :
  83. DBG printf("IAP: flash error");
  84. vTaskDelay(100);
  85. NVIC_SystemReset();
  86. break;
  87. // Общая ошибка (что-то пошло не так)
  88. case IAP_RESET :
  89. DBG printf("IAP: common error");
  90. vTaskDelay(100);
  91. NVIC_SystemReset();
  92. break;
  93. default : break;
  94. }
  95. }
  96. }
  97. // Обработчик приема первого пакета с ключом и размером
  98. mb_err_code_t iap_start(uint8_t *data, uint8_t len)
  99. {
  100. // Проверка контрольного слова
  101. if (data[0] != 0xEF || data[1] != 0xBE || data[2] != 0xAD || data[3] != 0xDE)
  102. return MB_BOOT_ERR_WRONG_CONTENT;
  103. swap((uint8_t*)&data[4], (uint8_t*)&fw_size, 4);
  104. DBG printf("FW size: %u\r\n", fw_size);
  105. erase_flash();
  106. /*
  107. // Проверка размера загружаемого файла
  108. if (fw_size != FW_SIZE)
  109. {
  110. DBG printf("ERR: wrong FW size! Size should be: %u\r\n", (uint32_t)FW_SIZE);
  111. xEventGroupSetBits(event, IAP_RETURN);
  112. return MB_BOOT_ERR_WRONG_FW_SIZE;
  113. }
  114. */
  115. i_big_package = 0;
  116. i_short_package = 0;
  117. xEventGroupSetBits(event, IAP_START);
  118. return MB_BOOT_ERR_NO;
  119. }
  120. // Обработчик приема блока прошивки
  121. mb_err_code_t iap_block(uint8_t *data, uint8_t len)
  122. {
  123. uint16_t pack_num;
  124. static uint16_t pack_index = 0;
  125. // Проверка номера пакета
  126. swap(data, (uint8_t*)&pack_num, 2);
  127. if (pack_num != pack_index) {
  128. xEventGroupSetBits(event, IAP_RESET);
  129. return MB_BOOT_WRONG_PACK_INDEX;
  130. }
  131. pack_index++;
  132. memcpy(&fw_buf_1[BLOCK_SIZE*i_short_package++], &data[2], BLOCK_SIZE);
  133. // Когда буфер заполняется нужно писать во флеш
  134. if (i_short_package == (FLASH_PAGE_SIZE / BLOCK_SIZE))
  135. {
  136. i_short_package = 0;
  137. i_big_package++;
  138. if (i_big_package != 1)
  139. {
  140. memcpy(fw_buf_2, fw_buf_1, FLASH_PAGE_SIZE);
  141. xEventGroupSetBits(event, IAP_BLOCK);
  142. return MB_BOOT_ERR_NO;
  143. }
  144. }
  145. // Собрали данные для первой станицы. Нужно проверить ключ прошивки.
  146. if ((i_big_package == 1) && (i_short_package == 0))
  147. {
  148. memcpy(fw_buf_2, fw_buf_1, FLASH_PAGE_SIZE);
  149. xEventGroupSetBits(event, IAP_BLOCK);
  150. return MB_BOOT_ERR_NO;
  151. #if 0
  152. if (memcmp(&fw_buf_1[KEY_FW_SHIFT], HW_REW, strlen(HW_REW)))
  153. {
  154. DBG printf("ERR: wrong fw key! Should be: %s\r\n", HW_REW);
  155. xEventGroupSetBits(event, IAP_RETURN);
  156. return MB_BOOT_ERR_WRONG_KEY;
  157. }
  158. else
  159. {
  160. memcpy(fw_buf_2, fw_buf_1, FLASH_PAGE_SIZE);
  161. xEventGroupSetBits(event, IAP_BLOCK);
  162. return MB_BOOT_ERR_NO;
  163. }
  164. #endif
  165. }
  166. xSemaphoreGive(flash_sem);
  167. return MB_BOOT_ERR_NO;
  168. }
  169. //
  170. bool write_buf(void)
  171. {
  172. uint32_t *ptr = (uint32_t*)fw_buf_2;
  173. uint32_t addr = FW_BEGIN_ADDRESS + FLASH_PAGE_SIZE*(i_big_package - 1);
  174. // Когда принят и проверен первый блок данных (2кБт) нужно очистить память
  175. if (i_big_package == 1)
  176. {
  177. /*
  178. if (!erase_flash())
  179. {
  180. flash_err_flag = true; // ошибка flash
  181. xSemaphoreGive(flash_sem);
  182. return false;
  183. }
  184. */
  185. }
  186. flash_unlock();
  187. for (uint32_t i = 0; i < 512; i++)
  188. {
  189. if (flash_word_program(addr, *ptr) != FLASH_OPERATE_DONE)
  190. {
  191. flash_lock();
  192. flash_err_flag = true; // ошибка flash
  193. }
  194. ptr++;
  195. addr += 4;
  196. }
  197. #if 0
  198. for (uint32_t i = 0; i < 256; i++)
  199. {
  200. if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, addr, (uint64_t)*ptr) != HAL_OK)
  201. {
  202. HAL_FLASH_Lock();
  203. flash_err_flag = true; // ошибка flash
  204. }
  205. ptr++;
  206. addr += 8;
  207. }
  208. #endif
  209. xSemaphoreGive(flash_sem);
  210. return true;
  211. }
  212. // Нужно определить количество секторов для записи FW
  213. bool erase_flash(void)
  214. {
  215. uint32_t sector = FW_BEGIN_ADDRESS;
  216. int sector_number = fw_size/FLASH_PAGE_SIZE + 1;
  217. //DBG printf("Need to erase %u sectros\r\n", sector_number);
  218. flash_unlock();
  219. for (int i = 0; i < sector_number; i++)
  220. {
  221. if (flash_sector_erase(sector) != FLASH_OPERATE_DONE) {
  222. return false;
  223. }
  224. //DBG printf("Sector %X erased\r\n", sector);
  225. sector += FLASH_PAGE_SIZE;
  226. }
  227. flash_lock();
  228. return true;
  229. }
  230. //
  231. mb_err_code_t check_crc(void)
  232. {
  233. uint32_t calc_crc;
  234. uint32_t read_crc;
  235. #if 0
  236. cortex_crc_init();
  237. read_crc = (*(uint32_t*)FW_CRC_ADDRESS);
  238. calc_crc = cortex_crc((uint8_t*)FW_BEGIN_ADDRESS, (FW_SIZE - 4));
  239. if (read_crc != calc_crc)
  240. return MB_BOOT_ERR_WRONG_FW_CRC;
  241. #endif
  242. return MB_BOOT_ERR_NO;
  243. }
  244. //
  245. void iap_finish(void)
  246. {
  247. xEventGroupSetBits(event, IAP_BLOCK | IAP_FINISH);
  248. }
  249. //
  250. void led_timer(TimerHandle_t timer)
  251. {
  252. }
  253. //
  254. // 65 (0x41) Read Input Registers
  255. eMBErrorCode
  256. eMBUpdateCB( UCHAR * pucFrame, USHORT * usLen)
  257. {
  258. int res;
  259. switch (pucFrame[1])
  260. {
  261. case 1:
  262. pucFrame[1] = iap_start(&pucFrame[2], *usLen);
  263. *usLen = 2;
  264. return MB_ENOERR;
  265. break;
  266. case 2:
  267. #if 1
  268. res = iap_block(&pucFrame[2], *usLen);
  269. xSemaphoreTake(flash_sem, 500);
  270. if (flash_err_flag) {
  271. pucFrame[1] = MB_BOOT_FLASH_ERR;
  272. xEventGroupSetBits(event, IAP_FLASH_ERROR);
  273. }
  274. else if (res == MB_BOOT_ERR_NO)
  275. pucFrame[1] = WRITE_BLOCK_COM;
  276. else if (res == MB_BOOT_ERR_WRONG_KEY)
  277. pucFrame[1] = MB_BOOT_ERR_WRONG_KEY;
  278. else if (res == MB_BOOT_WRONG_PACK_INDEX)
  279. pucFrame[1] = MB_BOOT_WRONG_PACK_INDEX;
  280. *usLen = 2;
  281. #endif
  282. return MB_ENOERR;
  283. break;
  284. case 3:
  285. #if 1
  286. res = check_crc();
  287. if (res == MB_BOOT_ERR_WRONG_FW_CRC)
  288. pucFrame[1] = WRITE_BLOCK_COM;
  289. else
  290. iap_finish();
  291. *usLen = 2;
  292. #endif
  293. return MB_ENOERR;
  294. break;
  295. default:
  296. return MB_EPORTERR;
  297. }
  298. }
  299. //
  300. void swap(uint8_t *in_buf, uint8_t *out_buf, uint8_t size)
  301. {
  302. for (uint8_t i = 0; i < size; i++)
  303. out_buf[size - i - 1] = in_buf[i];
  304. }