123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382 |
- #include "at32f403a_407.h"
- #include "iap.h"
- #include "common_config.h"
- #include "FreeRTOS.h"
- #include "task.h"
- #include "semphr.h"
- #include "fr_timers.h"
- #include "event_groups.h"
- #include "mb.h"
- #include "mbport.h"
- #include "mbrtu.h"
- #include <stdio.h>
- #include <string.h>
- EventGroupHandle_t event;
- SemaphoreHandle_t buf_sem;
- SemaphoreHandle_t flash_sem;
- TimerHandle_t led_timer_handle;
- uint32_t fw_size; // Размер FW (передается в первом пакете)
- static uint16_t i_big_package;
- static uint16_t i_short_package;
- uint8_t fw_buf_1[FW_BUF_SIZE];
- uint8_t fw_buf_2[FW_BUF_SIZE];
- bool flash_err_flag = false;
- void led_timer(TimerHandle_t timer);
- void iap_task(void *params);
- //
- void iap_init(void)
- {
- flash_sem = xSemaphoreCreateBinary();
-
- led_timer_handle = xTimerCreate("led_timer", 500, pdTRUE, (void *)0, led_timer);
- xTimerStart(led_timer_handle, 0);
-
- xTaskCreate(iap_task, "iap_task", 4*configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL);
- }
- //
- void iap_task(void *params)
- {
- (void)(params);
- unsigned int ev;
- event = xEventGroupCreate();
- buf_sem = xSemaphoreCreateBinary();
- xSemaphoreGive(buf_sem);
-
- if (ev = xEventGroupWaitBits(event, IAP_START | IAP_RETURN, pdTRUE, pdFALSE, 60000) != IAP_START)
- {
- printf("IAP: switch to FW!\r\n");
- bpr_data_write(BPR_DATA1, 0);
- NVIC_SystemReset();
- }
-
- if (ev == IAP_RETURN)
- {
- printf("IAP: return to FW\r\n");
- bpr_data_write(BPR_DATA1, 0);
- vTaskDelay(200);
- NVIC_SystemReset();
- }
-
- for (;;)
- {
- ev = xEventGroupWaitBits(event,
- IAP_BLOCK | IAP_FINISH | IAP_RETURN |
- IAP_FLASH_ERROR | IAP_RESET,
- pdTRUE, pdFALSE, portMAX_DELAY);
- switch (ev)
- {
- case IAP_BLOCK :
-
- write_buf();
-
- break;
-
- // Запись завершена. Нужно провести проверку CRC.
- case IAP_FINISH :
-
- flash_lock();
- DBG printf("IAP: finish\r\n");
- bpr_data_write(BPR_DATA1, 0);
- vTaskDelay(100);
- NVIC_SystemReset();
-
- break;
-
- // Возврат в основное ПО
- case IAP_RETURN :
-
- DBG printf("IAP: return to FW\r\n");
- bpr_data_write(BPR_DATA1, 0);
- vTaskDelay(100);
- NVIC_SystemReset();
-
- break;
-
- // Ошибка работы с flash
- case IAP_FLASH_ERROR :
-
- DBG printf("IAP: flash error");
- vTaskDelay(100);
- NVIC_SystemReset();
-
- break;
-
- // Общая ошибка (что-то пошло не так)
- case IAP_RESET :
-
- DBG printf("IAP: common error");
- vTaskDelay(100);
- NVIC_SystemReset();
-
- break;
-
- default : break;
- }
- }
- }
- // Обработчик приема первого пакета с ключом и размером
- mb_err_code_t iap_start(uint8_t *data, uint8_t len)
- {
- // Проверка контрольного слова
- if (data[0] != 0xEF || data[1] != 0xBE || data[2] != 0xAD || data[3] != 0xDE)
- return MB_BOOT_ERR_WRONG_CONTENT;
- swap((uint8_t*)&data[4], (uint8_t*)&fw_size, 4);
-
- DBG printf("FW size: %u\r\n", fw_size);
-
- erase_flash();
-
- /*
- // Проверка размера загружаемого файла
- if (fw_size != FW_SIZE)
- {
- DBG printf("ERR: wrong FW size! Size should be: %u\r\n", (uint32_t)FW_SIZE);
- xEventGroupSetBits(event, IAP_RETURN);
- return MB_BOOT_ERR_WRONG_FW_SIZE;
- }
- */
- i_big_package = 0;
- i_short_package = 0;
- xEventGroupSetBits(event, IAP_START);
- return MB_BOOT_ERR_NO;
- }
- // Обработчик приема блока прошивки
- mb_err_code_t iap_block(uint8_t *data, uint8_t len)
- {
- uint16_t pack_num;
- static uint16_t pack_index = 0;
- // Проверка номера пакета
- swap(data, (uint8_t*)&pack_num, 2);
- if (pack_num != pack_index) {
- xEventGroupSetBits(event, IAP_RESET);
- return MB_BOOT_WRONG_PACK_INDEX;
- }
- pack_index++;
-
- memcpy(&fw_buf_1[BLOCK_SIZE*i_short_package++], &data[2], BLOCK_SIZE);
-
- // Когда буфер заполняется нужно писать во флеш
- if (i_short_package == (FLASH_PAGE_SIZE / BLOCK_SIZE))
- {
- i_short_package = 0;
- i_big_package++;
-
- if (i_big_package != 1)
- {
- memcpy(fw_buf_2, fw_buf_1, FLASH_PAGE_SIZE);
- xEventGroupSetBits(event, IAP_BLOCK);
- return MB_BOOT_ERR_NO;
- }
- }
- // Собрали данные для первой станицы. Нужно проверить ключ прошивки.
- if ((i_big_package == 1) && (i_short_package == 0))
- {
- memcpy(fw_buf_2, fw_buf_1, FLASH_PAGE_SIZE);
- xEventGroupSetBits(event, IAP_BLOCK);
- return MB_BOOT_ERR_NO;
- #if 0
- if (memcmp(&fw_buf_1[KEY_FW_SHIFT], HW_REW, strlen(HW_REW)))
- {
- DBG printf("ERR: wrong fw key! Should be: %s\r\n", HW_REW);
- xEventGroupSetBits(event, IAP_RETURN);
- return MB_BOOT_ERR_WRONG_KEY;
- }
- else
- {
- memcpy(fw_buf_2, fw_buf_1, FLASH_PAGE_SIZE);
- xEventGroupSetBits(event, IAP_BLOCK);
- return MB_BOOT_ERR_NO;
- }
- #endif
- }
- xSemaphoreGive(flash_sem);
- return MB_BOOT_ERR_NO;
- }
- //
- bool write_buf(void)
- {
- uint32_t *ptr = (uint32_t*)fw_buf_2;
- uint32_t addr = FW_BEGIN_ADDRESS + FLASH_PAGE_SIZE*(i_big_package - 1);
-
- // Когда принят и проверен первый блок данных (2кБт) нужно очистить память
- if (i_big_package == 1)
- {
- /*
- if (!erase_flash())
- {
- flash_err_flag = true; // ошибка flash
- xSemaphoreGive(flash_sem);
- return false;
- }
- */
- }
-
- flash_unlock();
-
- for (uint32_t i = 0; i < 512; i++)
- {
- if (flash_word_program(addr, *ptr) != FLASH_OPERATE_DONE)
- {
- flash_lock();
- flash_err_flag = true; // ошибка flash
- }
- ptr++;
- addr += 4;
- }
-
- #if 0
- for (uint32_t i = 0; i < 256; i++)
- {
- if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, addr, (uint64_t)*ptr) != HAL_OK)
- {
- HAL_FLASH_Lock();
- flash_err_flag = true; // ошибка flash
- }
- ptr++;
- addr += 8;
- }
- #endif
-
- xSemaphoreGive(flash_sem);
-
- return true;
- }
- // Нужно определить количество секторов для записи FW
- bool erase_flash(void)
- {
- uint32_t sector = FW_BEGIN_ADDRESS;
- int sector_number = fw_size/FLASH_PAGE_SIZE + 1;
-
- //DBG printf("Need to erase %u sectros\r\n", sector_number);
-
- flash_unlock();
-
- for (int i = 0; i < sector_number; i++)
- {
- if (flash_sector_erase(sector) != FLASH_OPERATE_DONE) {
- return false;
- }
- //DBG printf("Sector %X erased\r\n", sector);
- sector += FLASH_PAGE_SIZE;
- }
-
- flash_lock();
-
- return true;
- }
- //
- mb_err_code_t check_crc(void)
- {
- uint32_t calc_crc;
- uint32_t read_crc;
- #if 0
- cortex_crc_init();
- read_crc = (*(uint32_t*)FW_CRC_ADDRESS);
- calc_crc = cortex_crc((uint8_t*)FW_BEGIN_ADDRESS, (FW_SIZE - 4));
-
- if (read_crc != calc_crc)
- return MB_BOOT_ERR_WRONG_FW_CRC;
- #endif
- return MB_BOOT_ERR_NO;
- }
- //
- void iap_finish(void)
- {
- xEventGroupSetBits(event, IAP_BLOCK | IAP_FINISH);
- }
- //
- void led_timer(TimerHandle_t timer)
- {
-
- }
- //
- // 65 (0x41) Read Input Registers
- eMBErrorCode
- eMBUpdateCB( UCHAR * pucFrame, USHORT * usLen)
- {
- int res;
-
- switch (pucFrame[1])
- {
- case 1:
- pucFrame[1] = iap_start(&pucFrame[2], *usLen);
- *usLen = 2;
- return MB_ENOERR;
- break;
- case 2:
- #if 1
- res = iap_block(&pucFrame[2], *usLen);
-
- xSemaphoreTake(flash_sem, 500);
-
- if (flash_err_flag) {
- pucFrame[1] = MB_BOOT_FLASH_ERR;
- xEventGroupSetBits(event, IAP_FLASH_ERROR);
- }
- else if (res == MB_BOOT_ERR_NO)
- pucFrame[1] = WRITE_BLOCK_COM;
- else if (res == MB_BOOT_ERR_WRONG_KEY)
- pucFrame[1] = MB_BOOT_ERR_WRONG_KEY;
- else if (res == MB_BOOT_WRONG_PACK_INDEX)
- pucFrame[1] = MB_BOOT_WRONG_PACK_INDEX;
-
- *usLen = 2;
- #endif
- return MB_ENOERR;
- break;
- case 3:
- #if 1
- res = check_crc();
-
- if (res == MB_BOOT_ERR_WRONG_FW_CRC)
- pucFrame[1] = WRITE_BLOCK_COM;
- else
- iap_finish();
-
- *usLen = 2;
- #endif
- return MB_ENOERR;
-
- break;
- default:
- return MB_EPORTERR;
- }
- }
- //
- void swap(uint8_t *in_buf, uint8_t *out_buf, uint8_t size)
- {
- for (uint8_t i = 0; i < size; i++)
- out_buf[size - i - 1] = in_buf[i];
- }
|