diff --git a/Core/Bootloader/boot_can.c b/Core/Bootloader/boot_can.c index 5a83457..77d73c7 100644 --- a/Core/Bootloader/boot_can.c +++ b/Core/Bootloader/boot_can.c @@ -72,57 +72,62 @@ void MX_BOOT_CAN_Init(void) // ----------------------------- void Bootloader_CAN_Receive_Page(Bootloader_t *bl) { - uint16_t bytes_received = 0; - uint8_t crc_buf[4]; - CAN_RxHeaderTypeDef canHeader; - uint8_t canData[8]; - uint32_t start_tick = HAL_GetTick(); + uint16_t bytes_received = 0; + CAN_RxHeaderTypeDef canHeader; + uint8_t canData[8]; + uint32_t start_tick = HAL_GetTick(); - // Приём данных страницы - while(bytes_received < PAGE_SIZE) - { - if(HAL_CAN_GetRxFifoFillLevel(bl->hcan, CAN_RX_FIFO0) > 0) + // Приём страницы прошивки + while(bytes_received < PAGE_SIZE) { - if(HAL_CAN_GetRxMessage(bl->hcan, CAN_RX_FIFO0, &canHeader, canData) == HAL_OK) - { - uint8_t len = canHeader.DLC; - if(bytes_received + len > PAGE_SIZE) - len = PAGE_SIZE - bytes_received; + if(HAL_CAN_GetRxFifoFillLevel(bl->hcan, CAN_RX_FIFO0) > 0) + { + if(HAL_CAN_GetRxMessage(bl->hcan, CAN_RX_FIFO0, &canHeader, canData) == HAL_OK) + { + uint8_t len = canHeader.DLC; + if(bytes_received + len > PAGE_SIZE) + len = PAGE_SIZE - bytes_received; - memcpy(&bl->fw_buffer[bytes_received], canData, len); - bytes_received += len; - start_tick = HAL_GetTick(); // сброс таймера - } + memcpy(&bl->fw_buffer[bytes_received], canData, len); + bytes_received += len; + start_tick = HAL_GetTick(); // сброс таймера + } + } + + // проверка таймаута + if(HAL_GetTick() - start_tick >= FW_RECEIVE_TIMEOUT_MS) + { + bl->error.bit.timeout_receive = 1; + bl->state = BL_STATE_ERROR; + return; + } } - // проверка таймаута - if(HAL_GetTick() - start_tick >= FW_RECEIVE_TIMEOUT_MS) + // Приём CRC (4 байта) + while(1) { - bl->state = BL_STATE_ERROR; - return; - } - } + if(HAL_CAN_GetRxFifoFillLevel(bl->hcan, CAN_RX_FIFO0) > 0) + { + if(HAL_CAN_GetRxMessage(bl->hcan, CAN_RX_FIFO0, &canHeader, canData) == HAL_OK) + { + // CRC в первых 4 байтах пакета + bl->fw_crc = (canData[0] << 24) | + (canData[1] << 16) | + (canData[2] << 8) | + canData[3]; + break; + } + } - // Приём CRC (следующий CAN пакет) - while(1) - { - if(HAL_CAN_GetRxFifoFillLevel(bl->hcan, CAN_RX_FIFO0) > 0) - { - if(HAL_CAN_GetRxMessage(bl->hcan, CAN_RX_FIFO0, &canHeader, canData) == HAL_OK) - { - // первые 4 байта = CRC - bl->fw_crc = (canData[0] << 24) | (canData[1] << 16) | (canData[2] << 8) | canData[3]; - break; - } + if(HAL_GetTick() - start_tick >= FW_RECEIVE_TIMEOUT_MS) + { + bl->error.bit.timeout_receive = 1; + bl->state = BL_STATE_ERROR; + return; + } } - if(HAL_GetTick() - start_tick >= FW_RECEIVE_TIMEOUT_MS) - { - bl->state = BL_STATE_ERROR; - return; - } - } + bl->fw_len = PAGE_SIZE; + bl->state = BL_STATE_IDLE; +} - bl->fw_len = bytes_received; - bl->state = BL_STATE_IDLE; -} \ No newline at end of file diff --git a/Core/Bootloader/boot_main.c b/Core/Bootloader/boot_main.c index 5edb88d..dad8f4e 100644 --- a/Core/Bootloader/boot_main.c +++ b/Core/Bootloader/boot_main.c @@ -2,7 +2,15 @@ Bootloader_t boot = {0}; int main() -{ +{ + __disable_irq(); + SCB->VTOR = 0x08000000; + __enable_irq(); + + /* Включаем тактирование PWR и BKP (APB1) и разрешаем доступ к BKP domain */ + /* Записываем напрямую в регистры RCC/APB1ENR и PWR->CR */ + RCC->APB1ENR |= (RCC_APB1ENR_PWREN | RCC_APB1ENR_BKPEN); + boot.state = BL_STATE_INIT; while (1) { @@ -22,4 +30,165 @@ void SysTick_Handler(void) /* USER CODE BEGIN SysTick_IRQn 1 */ /* USER CODE END SysTick_IRQn 1 */ +} + + + +void Boot_SystemClock_Config(void) +{ + RCC_OscInitTypeDef RCC_OscInitStruct = {0}; + RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; + + /* Включаем внутренний генератор HSI */ + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; + RCC_OscInitStruct.HSIState = RCC_HSI_ON; + RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_OFF; // без PLL + if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) + { + Error_Handler(); + } + + /* Настройка шин AHB/APB */ + RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK + |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI; // HSI = 8 MHz + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; // HCLK = 8 MHz + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; // PCLK1 = 8 MHz + RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; // PCLK2 = 8 MHz + if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK) + { + Error_Handler(); + } +} + + +/******************************************************************************/ +/* Cortex-M3 Processor Interruption and Exception Handlers */ +/******************************************************************************/ +/** + * @brief This function handles Non maskable interrupt. + */ +void NMI_Handler(void) +{ + /* USER CODE BEGIN NonMaskableInt_IRQn 0 */ + + /* USER CODE END NonMaskableInt_IRQn 0 */ + /* USER CODE BEGIN NonMaskableInt_IRQn 1 */ + while (1) + { + } + /* USER CODE END NonMaskableInt_IRQn 1 */ +} + +/** + * @brief This function handles Hard fault interrupt. + */ +void HardFault_Handler(void) +{ + /* USER CODE BEGIN HardFault_IRQn 0 */ + + PWR->CR |= PWR_CR_DBP; + BKP->DR1 = 0xDEAD; // записываем код ошибки + BKP->DR2 = BKP->DR2 + 1; // счётчик ошибок + NVIC_SystemReset(); + /* USER CODE END HardFault_IRQn 0 */ + while (1) + { + /* USER CODE BEGIN W1_HardFault_IRQn 0 */ + /* USER CODE END W1_HardFault_IRQn 0 */ + } +} + +/** + * @brief This function handles Memory management fault. + */ +void MemManage_Handler(void) +{ + /* USER CODE BEGIN MemoryManagement_IRQn 0 */ + PWR->CR |= PWR_CR_DBP; + BKP->DR1 = 0xBEEF; // записываем код ошибки + BKP->DR2 = BKP->DR2 + 1; // счётчик ошибок + NVIC_SystemReset(); + /* USER CODE END MemoryManagement_IRQn 0 */ + while (1) + { + /* USER CODE BEGIN W1_MemoryManagement_IRQn 0 */ + /* USER CODE END W1_MemoryManagement_IRQn 0 */ + } +} + +/** + * @brief This function handles Prefetch fault, memory access fault. + */ +void BusFault_Handler(void) +{ + /* USER CODE BEGIN BusFault_IRQn 0 */ + + /* USER CODE END BusFault_IRQn 0 */ + while (1) + { + /* USER CODE BEGIN W1_BusFault_IRQn 0 */ + /* USER CODE END W1_BusFault_IRQn 0 */ + } +} + +/** + * @brief This function handles Undefined instruction or illegal state. + */ +void UsageFault_Handler(void) +{ + /* USER CODE BEGIN UsageFault_IRQn 0 */ + + /* USER CODE END UsageFault_IRQn 0 */ + while (1) + { + /* USER CODE BEGIN W1_UsageFault_IRQn 0 */ + /* USER CODE END W1_UsageFault_IRQn 0 */ + } +} + +/** + * @brief This function handles System service call via SWI instruction. + */ +void SVC_Handler(void) +{ + /* USER CODE BEGIN SVCall_IRQn 0 */ + + /* USER CODE END SVCall_IRQn 0 */ + /* USER CODE BEGIN SVCall_IRQn 1 */ + + /* USER CODE END SVCall_IRQn 1 */ +} + +/** + * @brief This function handles Debug monitor. + */ +void DebugMon_Handler(void) +{ + /* USER CODE BEGIN DebugMonitor_IRQn 0 */ + + /* USER CODE END DebugMonitor_IRQn 0 */ + /* USER CODE BEGIN DebugMonitor_IRQn 1 */ + + /* USER CODE END DebugMonitor_IRQn 1 */ +} + +/** + * @brief This function handles Pendable request for system service. + */ +void PendSV_Handler(void) +{ + /* USER CODE BEGIN PendSV_IRQn 0 */ + + /* USER CODE END PendSV_IRQn 0 */ + /* USER CODE BEGIN PendSV_IRQn 1 */ + + /* USER CODE END PendSV_IRQn 1 */ +} + + +void Error_Handler(void) +{ + NVIC_SystemReset(); } \ No newline at end of file diff --git a/Core/Bootloader/boot_project_setup.h b/Core/Bootloader/boot_project_setup.h index c13146e..a23bfae 100644 --- a/Core/Bootloader/boot_project_setup.h +++ b/Core/Bootloader/boot_project_setup.h @@ -7,26 +7,17 @@ // KEY defines #define BOOTLOADER_KEY_ADR (uint32_t)0x08009800 #define BOOTLOADER_KEY_PAGE 20 + // MAIN APP defines #define MAIN_APP_START_ADR (uint32_t)0x0800C000 #define MAIN_APP_PAGE 21 #define MAIN_APP_NUM_OF_PAGE 250-MAIN_APP_PAGE - +// RECEIVE defines #define FW_RECEIVE_TIMEOUT_MS 5000 // таймаут приёма страницы -#define PAGE_SIZE 2048 +#define PAGE_SIZE 2048 // страницы принимаются размером с page_size (размер страниц флеш должен быть кратен PAGE_SIZE) -typedef enum { - CMD_ERASE = 0x01, ///< Команда на стирание прошивки - CMD_START_RECEIVE, ///< Команда на старт приема прошивки - CMD_WRITE, ///< Команда на запись блока прошивки - CMD_VERIFY, ///< Команда на проверку прошивки - CMD_GOTOAPP, ///< Команда на переход в приложение - CMD_RESET, ///< Команда на переход в приложение - CMD_GO_TO_BOOT, ///< Команда на переход в приложение -}BootloaderCommand_t; - // === RCC defines === @@ -49,8 +40,8 @@ typedef enum { // === CAN defines === #define CAN_BOOT CAN1 #define CAN_MODE CAN_MODE_NORMAL -// Presacler = 1: 500 kbps при 8 MHz -#define CAN_SPEED_PRESCALER 2 +// Presacler = 1 для 500 kbps при 8 MHz +#define CAN_SPEED_PRESCALER 4 #define CAN_SPEED_BS1 CAN_BS1_13TQ #define CAN_SPEED_BS2 CAN_BS2_2TQ diff --git a/Core/Bootloader/boot_uart.c b/Core/Bootloader/boot_uart.c index 23cc1d3..3bebac2 100644 --- a/Core/Bootloader/boot_uart.c +++ b/Core/Bootloader/boot_uart.c @@ -63,6 +63,7 @@ void Bootloader_UART_Receive_Page(Bootloader_t *bl) // проверка таймаута if(HAL_GetTick() - start_tick >= FW_RECEIVE_TIMEOUT_MS) { + bl->error.bit.timeout_receive = 1; bl->state = BL_STATE_ERROR; // превышен таймаут return; } @@ -82,6 +83,7 @@ void Bootloader_UART_Receive_Page(Bootloader_t *bl) { if(HAL_GetTick() - start_tick >= FW_RECEIVE_TIMEOUT_MS) { + bl->error.bit.timeout_receive = 1; bl->state = BL_STATE_ERROR; return; } diff --git a/Core/Bootloader/bootloader.c b/Core/Bootloader/bootloader.c index 33afd93..59b8b2f 100644 --- a/Core/Bootloader/bootloader.c +++ b/Core/Bootloader/bootloader.c @@ -3,37 +3,52 @@ #include "boot_uart.h" #include "boot_can.h" -CAN_TxHeaderTypeDef TxHeader; -CAN_RxHeaderTypeDef RxHeader; -uint32_t TxMailBox = 0; // num of used mail +HAL_StatusTypeDef res_hal; +CAN_TxHeaderTypeDef TxHeaderBoot; +CAN_RxHeaderTypeDef RxHeaderBoot; +uint32_t TxMailBoxBoot = 0; +uint8_t TXDataBoot[8] = {0}; +int receive_uart_flag = 0; void SetKey(void); uint32_t ReadKey(void); -void ResetKey(void); +void EraseKey(void); void Boot_SystemClock_Config(void); void JumpToApplocation(void); void Bootloader_UART_Receive_Page(Bootloader_t *bl); void Bootloader_CAN_Receive_Page(Bootloader_t *bl); -void Bootloader_Init(void) +uint32_t CRC32_Compute(const uint8_t* data, uint32_t length); + +void Bootloader_Init(Bootloader_t *bl) { - HAL_Init(); - Boot_SystemClock_Config(); + HAL_Init(); + + Boot_SystemClock_Config(); MX_BOOT_UART_Init(); MX_BOOT_CAN_Init(); + } -HAL_StatusTypeDef res_hal; + + +uint32_t code = 0; +uint32_t cnt = 0; void Bootloader_Task(Bootloader_t *bl) { + switch (bl->state) { case BL_STATE_INIT: + code = LoadErrorCode(); + cnt = LoadErrorCnt(); + + bl->prev_state = bl->state; // Проверяем ключ, чтобы понять запускать приложение или программирование - if (ReadKey() == BL_KEY_APP_WRITTEN) + if ((ReadKey() == BL_KEY_APP_WRITTEN) && (cnt <= 5)) { bl->state = BL_STATE_JUMP_TO_APP; break; // не инициализируем, а сразу прыгаем в приложение @@ -44,89 +59,202 @@ void Bootloader_Task(Bootloader_t *bl) } // Инициализация периферии - Bootloader_Init(); + Bootloader_Init(bl); bl->huart = &huart_boot; bl->hcan = &hcan_boot; + bl->TxHeader.DLC = 8; + bl->TxHeader.StdId = 123; bl->addr = MAIN_APP_START_ADR; + + if(cnt > 5) + { + ClearErrorCode(); + if(code == 0xDEAD) // HardFault + { + ResetKey(); + bl->error.bit.hardfault_cycle = 1; + TXDataBoot[0] = 0xAA; + TXDataBoot[1] = (bl->error.all >> 8) & 0xFF; + TXDataBoot[2] = bl->error.all & 0xFF; + res_hal = HAL_CAN_AddTxMessage(bl->hcan, &bl->TxHeader, TXDataBoot, &TxMailBoxBoot); + res_hal = HAL_UART_Transmit(bl->huart, TXDataBoot, 1, 100); + } + else if(code == 0xBEEF) // MemManage + { + ResetKey(); + bl->error.bit.memmanage_cycle = 1; + TXDataBoot[0] = 0x55; + TXDataBoot[1] = (bl->error.all >> 8) & 0xFF; + TXDataBoot[2] = bl->error.all & 0xFF; + res_hal = HAL_CAN_AddTxMessage(bl->hcan, &bl->TxHeader, TXDataBoot, &TxMailBoxBoot); + res_hal = HAL_UART_Transmit(bl->huart, TXDataBoot, 1, 100); + } + } + break; case BL_STATE_IDLE: - // Ждем команды по UART или CAN - if(bl->state != bl->prev_state) + if((bl->state != bl->prev_state) && (bl->prev_state != BL_STATE_ERROR)) { - static uint8_t Data[8] = {0}; - static uint32_t TxMail = {0}; - Data[0] = 0xFA; - HAL_CAN_AddTxMessage(bl->hcan, &bl->TxHeader, Data, &TxMail); - HAL_UART_Transmit() + TXDataBoot[0] = 0x00; + res_hal = HAL_CAN_AddTxMessage(bl->hcan, &bl->TxHeader, TXDataBoot, &TxMailBoxBoot); + res_hal = HAL_UART_Transmit(bl->huart, TXDataBoot, 1, 100); } + bl->prev_state = bl->state; + // Ждем команды по UART или CAN if (Receive_FW_Command(bl) == 0xFF) // функция обработки команд, возвращает 1 если ошибка { + bl->error.bit.unknown_cmd = 1; bl->state = BL_STATE_ERROR; } break; - + + case BL_STATE_RESET: + NVIC_SystemReset(); + break; + case BL_STATE_ERASE: - ResetKey(); + bl->prev_state = bl->state; + EraseKey(); if (FLASH_Erase_App() == HAL_OK) // твоя функция стирания MAIN_APP_PAGE..NUM { bl->state = BL_STATE_IDLE; } else { + bl->error.bit.erase_err = 1; bl->state = BL_STATE_ERROR; } break; case BL_STATE_RECEIVE_UART: - // В этом состоянии мы просто принимаем страницу + CRC - Bootloader_UART_Receive_Page(bl); - break; case BL_STATE_RECEIVE_CAN: - Bootloader_CAN_Receive_Page(bl); + receive_uart_flag = (bl->state == BL_STATE_RECEIVE_UART) ? 1 : 0; + + TXDataBoot[0] = 0x00; + bl->prev_state = bl->state; + if(receive_uart_flag) + { + res_hal = HAL_UART_Transmit(bl->huart, TXDataBoot, 1, 100); + Bootloader_UART_Receive_Page(bl); + } + else + { + res_hal = HAL_CAN_AddTxMessage(bl->hcan, &bl->TxHeader, TXDataBoot, &TxMailBoxBoot); + Bootloader_CAN_Receive_Page(bl); + } + uint32_t crc_calculated = CRC32_Compute((uint8_t *)bl->fw_buffer, bl->fw_len); + if(crc_calculated != bl->fw_crc) + { + for(int i = 0; i < bl->fw_len; i++) + { + bl->fw_buffer[i] = 0; + } + bl->error.bit.crc_err = 1; + bl->state = BL_STATE_ERROR; + } break; case BL_STATE_WRITE: + bl->prev_state = bl->state; if (FLASH_Write_Page(&bl->addr, bl->fw_buffer, bl->fw_len) == HAL_OK) // запись блока во Flash { bl->state = BL_STATE_IDLE; // ждём следующего блока } else { + bl->error.bit.write_err = 1; bl->state = BL_STATE_ERROR; } break; case BL_STATE_VERIFY: + bl->prev_state = bl->state; if (/*Verify_Flash_CRC(bl->fw_crc)*/0 == HAL_OK) { - ResetKey(); + EraseKey(); SetKey(); // отметка, что прошивка записана bl->state = BL_STATE_IDLE; } else { + bl->error.bit.verify_err = 1; bl->state = BL_STATE_ERROR; } break; case BL_STATE_JUMP_TO_APP: + bl->prev_state = bl->state; JumpToApplocation(); break; + + case BL_STATE_JUMP_TO_BOOT: + bl->prev_state = bl->state; + JumpToBootloader(); + break; + case BL_STATE_ERROR: - // обработка ошибок (можно светодиод, повторная инициализация, лог по UART) - Error_Handler(); + if(bl->state != bl->prev_state) + { + TXDataBoot[0] = 0xFF; + TXDataBoot[1] = (bl->error.all >> 8) & (0xFF); + TXDataBoot[2] = bl->error.all & (0xFF); + res_hal = HAL_CAN_AddTxMessage(bl->hcan, &bl->TxHeader, TXDataBoot, &TxMailBoxBoot); + res_hal = HAL_UART_Transmit(bl->huart, TXDataBoot, 1, 100); + } + bl->prev_state = bl->state; + // Ждем команды по UART или CAN + if (Receive_FW_Command(bl) == 0xFF) // функция обработки команд, возвращает 1 если ошибка + { + bl->error.bit.unknown_cmd = 1; + bl->state = BL_STATE_ERROR; + } break; default: + bl->error.bit.unknown_cmd = 1; bl->state = BL_STATE_ERROR; break; } - bl->prev_state = bl->state; } + +uint8_t SetBootState(Bootloader_t *bl, BootloaderCommand_t cmd, uint8_t uart_flag) +{ + switch(cmd) + { + case CMD_ERASE: // команда: стереть Flash + bl->state = BL_STATE_ERASE; + return 0x00; + case CMD_START_RECEIVE: // команда: принять блок + if(uart_flag) + bl->state = BL_STATE_RECEIVE_UART; + else + bl->state = BL_STATE_RECEIVE_CAN; + return 0x00; + case CMD_WRITE: // команда: записать блок + bl->state = BL_STATE_WRITE; + return 0x00; + case CMD_VERIFY: // команда: проверка прошивки + bl->state = BL_STATE_VERIFY; + return 0x00; + case CMD_GOTOAPP: // команда: прыжок в приложение + bl->state = BL_STATE_JUMP_TO_APP; + return 0x00; + case CMD_RESET: // команда: прыжок в приложение + bl->state = BL_STATE_RESET; + return 0x00; + case CMD_GOTOBOOT: // команда: прыжок в бутлоадер + bl->state = BL_STATE_JUMP_TO_BOOT; + return 0x00; + + default: + return 0xFF; // неизвестная команда + } +} + /** * @brief Обработка команд прошивки по UART или CAN * @param bl: указатель на структуру бутлоадера @@ -136,6 +264,7 @@ uint8_t Receive_FW_Command(Bootloader_t *bl) { BootloaderCommand_t cmd = 0; HAL_StatusTypeDef res = HAL_ERROR; + uint8_t ret_val = 0x00; // --------------------------- // Чтение команды по UART @@ -143,83 +272,68 @@ uint8_t Receive_FW_Command(Bootloader_t *bl) res = HAL_UART_Receive(bl->huart, &cmd, 1, 10); // таймаут 10 ms if (res == HAL_OK) { - switch(cmd) - { - case CMD_ERASE: // команда: стереть Flash - bl->state = BL_STATE_ERASE; - return 0x00; - case CMD_START_RECEIVE: // команда: принять блок - bl->state = BL_STATE_RECEIVE_UART; - return 0x00; - case CMD_WRITE: // команда: записать блок - bl->state = BL_STATE_WRITE; - return 0x00; - case CMD_VERIFY: // команда: проверка прошивки - bl->state = BL_STATE_VERIFY; - return 0x00; - case CMD_GOTOAPP: // команда: прыжок в приложение - bl->state = BL_STATE_JUMP_TO_APP; - return 0x00; - - default: - return 0xFF; // неизвестная команда - } + ret_val = SetBootState(bl, cmd, 1); } // --------------------------- // Чтение команды по CAN // --------------------------- - CAN_RxHeaderTypeDef canHeader; uint8_t canData[8]; if (HAL_CAN_GetRxFifoFillLevel(bl->hcan, CAN_RX_FIFO0) > 0) { - if (HAL_CAN_GetRxMessage(bl->hcan, CAN_RX_FIFO0, &canHeader, canData) == HAL_OK) + if (HAL_CAN_GetRxMessage(bl->hcan, CAN_RX_FIFO0, &RxHeaderBoot, canData) == HAL_OK) { cmd = canData[0]; // предполагаем, что команда в первом байте - switch(cmd) - { - case CMD_ERASE: - bl->state = BL_STATE_ERASE; - return 0x00; - case CMD_START_RECEIVE: - // запускаем прием первой страницы + crc, затем после приема всего массива ждем следующей комманды - bl->state = BL_STATE_RECEIVE_CAN; - return 0x00; - case CMD_WRITE: // команда: записать блок - bl->state = BL_STATE_WRITE; - return 0x00; - case CMD_VERIFY: - bl->state = BL_STATE_VERIFY; - return 0x00; - case CMD_GOTOAPP: - bl->state = BL_STATE_JUMP_TO_APP; - return 0x00; - - default: - return 0xFF; - } + ret_val = SetBootState(bl, cmd, 0); } } #ifdef TEST_CAN - TxHeader.StdId = 0x200; // ID OF MESSAGE - TxHeader.ExtId = 0; // STANDART FRAME (NOT EXTENTED) - TxHeader.RTR = CAN_RTR_DATA; // TRANSMIT DATA OR - TxHeader.IDE = CAN_ID_STD; // STANDART FRAME - TxHeader.DLC = 8; // DATA SIZE - TxHeader.TransmitGlobalTime = DISABLE; //THIS MODE IS NOT USED, SO DISABLE + TxHeaderBoot.StdId = 0x200; // ID OF MESSAGE + TxHeaderBoot.ExtId = 0; // STANDART FRAME (NOT EXTENTED) + TxHeaderBoot.RTR = CAN_RTR_DATA; // TRANSMIT DATA OR + TxHeaderBoot.IDE = CAN_ID_STD; // STANDART FRAME + TxHeaderBoot.DLC = 8; // DATA SIZE + TxHeaderBoot.TransmitGlobalTime = DISABLE; //THIS MODE IS NOT USED, SO DISABLE uint8_t asd[8] = "ABCDEFGL"; - res_hal = HAL_CAN_AddTxMessage(&hcan_boot, &TxHeader, asd, &TxMailBox); // add to mail for transmit + res_hal = HAL_CAN_AddTxMessage(&hcan_boot, &TxHeaderBoot, asd, &TxMailBoxBoot); // add to mail for transmit HAL_Delay(1000); #endif - return 0x00; // если команды нет, ничего не делаем, остаёмся в BL_STATE_IDLE + return ret_val; +} + +uint32_t CRC32_Compute(const uint8_t* data, uint32_t length) +{ + const uint32_t polynomial = 0x04C11DB7; + uint32_t crc = 0xFFFFFFFF; + + for(uint32_t i = 0; i < length; i++) + { + crc ^= ((uint32_t)data[i] << 24); + for(uint8_t j = 0; j < 8; j++) + { + if(crc & 0x80000000) + crc = (crc << 1) ^ polynomial; + else + crc <<= 1; + } + } + + return crc ^ 0xFFFFFFFF; } +// key functions +void ResetKey(void) +{ + HAL_FLASH_Unlock(); + + HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, BOOTLOADER_KEY_ADR, 0); + + HAL_FLASH_Lock(); +} - -// reset/set key function void SetKey(void) { HAL_FLASH_Unlock(); @@ -234,7 +348,7 @@ uint32_t ReadKey(void) return (*(__IO uint32_t*)BOOTLOADER_KEY_ADR); } -void ResetKey(void) +void EraseKey(void) { FLASH_EraseInitTypeDef EraseInitStruct; HAL_FLASH_Unlock(); @@ -252,55 +366,62 @@ void ResetKey(void) void JumpToApplocation(void) { - // jump to main app - //Задаётся адрес программы со смещением от начала вектора прерываний - uint32_t app_jump_adr; - app_jump_adr=*((volatile uint32_t*)(MAIN_APP_START_ADR+4)); - void(*GoToApp)(void); - //Деинициализация HAL HAL_DeInit(); - GoToApp = (void (*) (void)) app_jump_adr; //Перенос вектора прерываний на начало зашитой программы __disable_irq(); __set_MSP(*((volatile uint32_t*)MAIN_APP_START_ADR)); __enable_irq(); + //Переход к выполнению зашитой программы - GoToApp(); + __ASM volatile( + "ldr r0, [%0, #4]\n" // r0 = *(MAIN_APP_START_ADR + 4) + "bx r0\n" // переход по адресу в r0 + : + : "r"(MAIN_APP_START_ADR) + : "r0" + ); + //Note: asm потому что при O0 компилятор делал локальные переменные, + // из-за чего при смене стека он не мог получить адрес для прыжка } - -void Boot_SystemClock_Config(void) +void JumpToBootloader(void) { - RCC_OscInitTypeDef RCC_OscInitStruct = {0}; - RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; - - /* Включаем внутренний генератор HSI */ - RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; - RCC_OscInitStruct.HSIState = RCC_HSI_ON; - RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; - RCC_OscInitStruct.PLL.PLLState = RCC_PLL_OFF; // без PLL - if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) - { - Error_Handler(); - } - - /* Настройка шин AHB/APB */ - RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK - |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; - RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI; // HSI = 8 MHz - RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; // HCLK = 8 MHz - RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; // PCLK1 = 8 MHz - RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; // PCLK2 = 8 MHz - if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK) - { - Error_Handler(); - } + // jump to boot + ResetKey(); // сброс ключа (не erase, просто битый ключ + NVIC_SystemReset(); // сброс и переход в бутлоадер (т.к. нет ключа) } -void Error_Handler(void) + +// Сохранение кода ошибки +// Чтение после ресета +uint32_t LoadErrorCode(void) { - NVIC_SystemReset(); -} \ No newline at end of file + return BKP->DR1; +} + +uint32_t LoadErrorCnt(void) +{ + return BKP->DR2; +} + +void ClearErrorCode(void) +{ + PWR->CR |= PWR_CR_DBP; + BKP->DR1 = 0; + BKP->DR2 = 0; +} + + +__WEAK void Boot_SystemClock_Config(void) +{ +} + + +__WEAK void Error_Handler(void) +{ + while(1); +} + diff --git a/Core/Bootloader/bootloader.h b/Core/Bootloader/bootloader.h index cd712dd..619884e 100644 --- a/Core/Bootloader/bootloader.h +++ b/Core/Bootloader/bootloader.h @@ -8,6 +8,18 @@ #define BL_KEY_APP_WRITTEN 0xAAAA5555 // ERROR DEFINES +/** + * @brief Комманды бутлоадера + */ +typedef enum { + CMD_ERASE = 0x01, ///< Команда на стирание прошивки + CMD_START_RECEIVE, ///< Команда на старт приема прошивки + CMD_WRITE, ///< Команда на запись блока прошивки + CMD_VERIFY, ///< Команда на проверку прошивки + CMD_GOTOAPP, ///< Команда на переход в приложение + CMD_RESET, ///< Команда на переход в приложение + CMD_GOTOBOOT, ///< Команда на переход в приложение +}BootloaderCommand_t; /** * @brief Состояние бутлоадера @@ -21,12 +33,33 @@ typedef enum { BL_STATE_RECEIVE_CAN, ///< Состояние: прием прошивки по CAN BL_STATE_WRITE, ///< Состояние: запись данных BL_STATE_VERIFY, ///< Состояние: проверка прошивки - BL_STATE_ERROR ///< Состояние: ошибка + BL_STATE_ERROR, ///< Состояние: ошибка + BL_STATE_RESET, ///< Состояние: сброс контролллера + BL_STATE_JUMP_TO_BOOT, ///< Состояние: запуск приложения } BootloaderState_t; +/** + * @brief Ошибки бутлоадера + */ +typedef union { + uint16_t all; + struct { + unsigned unknown_cmd:1; + unsigned erase_err:1; + unsigned write_err:1; + unsigned verify_err:1; + unsigned timeout_receive:1; + unsigned crc_err:1; + unsigned hardfault_cycle:1; + unsigned memmanage_cycle:1; + }bit; +} BootloaderError_t; + typedef struct { BootloaderState_t state; ///< текущее состояние бутлоадера + BootloaderError_t error; + uint32_t addr; ///< текущий адрес прошивки uint8_t fw_size; ///< размер прошивки @@ -40,7 +73,19 @@ typedef struct { BootloaderState_t prev_state; ///< предыдущее состояние бутлоадера } Bootloader_t; +extern uint32_t TxMailBoxBoot; +extern uint8_t TXDataBoot[8]; +void ResetKey(void); +void JumpToBootloader(void); + + +void SaveErrorCode(uint32_t code); +uint32_t LoadErrorCode(void); +uint32_t LoadErrorCnt(void); +void ClearErrorCode(void); + +void Boot_SystemClock_Config(void); void Bootloader_Task(Bootloader_t *bl); uint8_t Receive_FW_Command(Bootloader_t *bl); diff --git a/Core/Src/can.c b/Core/Src/can.c index 3289606..7c2cbce 100644 --- a/Core/Src/can.c +++ b/Core/Src/can.c @@ -23,6 +23,7 @@ /* USER CODE BEGIN 0 */ #include "message.h" #include "gpio.h" +#include "bootloader.h" void CAN_filterConfig(void); CAN_TxHeaderTypeDef TxHeader; @@ -189,6 +190,15 @@ void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan_i) /* Reception Error */ Error_Handler(); } + + if(msgData[0] == CMD_GOTOBOOT) + { + JumpToBootloader(); + } + else if(msgData[0] == CMD_RESET) + { + NVIC_SystemReset(); + } if((msgHeader.ExtId & 0xFF00000) != RX_box_ID) if((msgHeader.ExtId & 0xFF00000) != BC_box_ID) return; diff --git a/MDK-ARM/uksvep_2_2_v1.uvoptx b/MDK-ARM/uksvep_2_2_v1.uvoptx index c515ee6..ce0ab68 100644 --- a/MDK-ARM/uksvep_2_2_v1.uvoptx +++ b/MDK-ARM/uksvep_2_2_v1.uvoptx @@ -25,227 +25,6 @@ uksvep_2_2_v1 0x4 ARM-ADS - - 8000000 - - 1 - 1 - 0 - 1 - 0 - - - 1 - 65535 - 0 - 0 - 0 - - - 79 - 66 - 8 - - - - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 0 - 0 - 0 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - - - 1 - 0 - 1 - - 18 - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 1 - 1 - 0 - 0 - 1 - 0 - 0 - 4 - - - - - - - - - - - Segger\JL2CM3.dll - - - - 0 - ARMRTXEVENTFLAGS - -L70 -Z18 -C0 -M0 -T1 - - - 0 - DLGTARM - (1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0) - - - 0 - ARMDBGFLAGS - - - - 0 - DLGUARM - - - - 0 - JL2CM3 - -U11111118 -O14 -S2 -ZTIFSpeedSel5000 -A0 -C0 -JU1 -JI127.0.0.1 -JP0 -RST0 -N00("ARM CoreSight JTAG-DP") -D00(3BA00477) -L00(4) -N01("Unknown JTAG device") -D01(06414041) -L01(5) -TO18 -TC10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -TB1 -TFE0 -FO7 -FD20000000 -FC1000 -FN1 -FF0STM32F10x_512.FLM -FS08000000 -FL080000 -FP0($$Device:STM32F103RC$Flash\STM32F10x_512.FLM) - - - 0 - UL2CM3 - UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0STM32F10x_512 -FS08000000 -FL080000 -FP0($$Device:STM32F103RC$Flash\STM32F10x_512.FLM)) - - - - - - 0 - 1 - input - - - 1 - 1 - Inputs - - - 2 - 1 - duty_cycle,0x0A - - - 3 - 1 - frequency,0x0A - - - 4 - 1 - uwTick,0x0A - - - - - 1 - 0 - 0x0800C000 - 0 - - - - 0 - - - 0 - 1 - 1 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 0 - 0 - 0 - - - - - - - - - - - System Viewer\GPIOB - 35905 - - - - 1 - 0 - 0 - 2 - 10000000 - - - - - - bootloader - 0x4 - ARM-ADS 8000000 @@ -361,7 +140,7 @@ 0 JL2CM3 - -U60145543 -O14 -S2 -ZTIFSpeedSel5000 -A0 -C0 -JU1 -JI127.0.0.1 -JP0 -RST0 -N00("ARM CoreSight JTAG-DP") -D00(3BA00477) -L00(4) -N01("Unknown JTAG device") -D01(06414041) -L01(5) -TO18 -TC10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -TB1 -TFE0 -FO7 -FD20000000 -FC1000 -FN1 -FF0STM32F10x_512.FLM -FS08000000 -FL080000 -FP0($$Device:STM32F103RC$Flash\STM32F10x_512.FLM) + -U11111118 -O14 -S2 -ZTIFSpeedSel5000 -A0 -C0 -JU1 -JI127.0.0.1 -JP0 -RST0 -N00("ARM CoreSight JTAG-DP") -D00(3BA00477) -L00(4) -N01("Unknown JTAG device") -D01(06414041) -L01(5) -TO18 -TC10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -TB1 -TFE0 -FO7 -FD20000000 -FC1000 -FN1 -FF0STM32F10x_512.FLM -FS08000000 -FL080000 -FP0($$Device:STM32F103RC$Flash\STM32F10x_512.FLM) 0 @@ -369,12 +148,29 @@ UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0STM32F10x_512 -FS08000000 -FL080000 -FP0($$Device:STM32F103RC$Flash\STM32F10x_512.FLM)) - + + + 0 + 0 + 81 + 1 +
134288232
+ 0 + 0 + 0 + 0 + 0 + 1 + ../Core/Src/main.c + + \\uksvep_2_2_v1\../Core/Src/main.c\81 +
+
0 1 - boot + input 1 @@ -399,22 +195,35 @@ 5 1 - GoToApp + modbus 6 1 - app_jump_adr + msgData[0] + + + 7 + 1 + CMD_GOTOBOOT 1 0 - 0x08009800 + 0x0800d000 0 + + + 2 + 0 + 0x08009800 + 0 + + 0 @@ -477,6 +286,347 @@
+ + bootloader + 0x4 + ARM-ADS + + 8000000 + + 1 + 1 + 0 + 1 + 0 + + + 1 + 65535 + 0 + 0 + 0 + + + 79 + 66 + 8 + + + + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 0 + 0 + 0 + 0 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + + + 1 + 0 + 1 + + 18 + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 4 + + + + + + + + + + + Segger\JL2CM3.dll + + + + 0 + ARMRTXEVENTFLAGS + -L70 -Z18 -C0 -M0 -T1 + + + 0 + DLGTARM + (1010=-1605,104,-1155,661,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0) + + + 0 + ARMDBGFLAGS + + + + 0 + DLGUARM + + + + 0 + JL2CM3 + -U60145543 -O14 -S2 -ZTIFSpeedSel5000 -A0 -C0 -JU1 -JI127.0.0.1 -JP0 -RST0 -N00("ARM CoreSight JTAG-DP") -D00(3BA00477) -L00(4) -N01("Unknown JTAG device") -D01(06414041) -L01(5) -TO18 -TC10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -TB1 -TFE0 -FO7 -FD20000000 -FC1000 -FN1 -FF0STM32F10x_512.FLM -FS08000000 -FL080000 -FP0($$Device:STM32F103RC$Flash\STM32F10x_512.FLM) + + + 0 + UL2CM3 + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0STM32F10x_512 -FS08000000 -FL080000 -FP0($$Device:STM32F103RC$Flash\STM32F10x_512.FLM)) + + + + + 0 + 0 + 210 + 1 +
134220168
+ 0 + 0 + 0 + 0 + 0 + 1 + ..\Core\Bootloader\bootloader.c + + \\bootloader\../Core/Bootloader/bootloader.c\210 +
+ + 1 + 0 + 216 + 1 +
134220188
+ 0 + 0 + 0 + 0 + 0 + 1 + ..\Core\Bootloader\bootloader.c + + \\bootloader\../Core/Bootloader/bootloader.c\216 +
+ + 2 + 0 + 111 + 1 +
134219682
+ 0 + 0 + 0 + 0 + 0 + 1 + ..\Core\Bootloader\bootloader.c + + \\bootloader\../Core/Bootloader/bootloader.c\111 +
+ + 3 + 0 + 214 + 1 +
0
+ 0 + 0 + 0 + 0 + 0 + 0 + ..\Core\Bootloader\bootloader.c + + +
+ + 4 + 0 + 219 + 1 +
0
+ 0 + 0 + 0 + 0 + 0 + 0 + ..\Core\Bootloader\bootloader.c + + +
+
+ + + 0 + 1 + boot + + + 1 + 1 + Inputs + + + 2 + 1 + duty_cycle,0x0A + + + 3 + 1 + frequency,0x0A + + + 4 + 1 + uwTick,0x0A + + + 5 + 1 + GoToApp + + + 6 + 1 + app_jump_adr + + + 7 + 1 + TXDataBoot + + + + + 1 + 0 + 0x0800d000 + 0 + + + + + 2 + 0 + 0x08009800 + 0 + + + + 0 + + + 0 + 1 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + 0 + 0 + 0 + + + + + + + + + + + System Viewer\BKP + 35903 + + + System Viewer\CAN + 35904 + + + System Viewer\GPIOB + 35905 + + + System Viewer\PWR + 35901 + + + System Viewer\RCC + 35902 + + + + 1 + 0 + 0 + 2 + 10000000 + +
+
+ Application/MDK-ARM 1 @@ -906,6 +1056,18 @@ 0 0 0 + ..\Core\Bootloader\boot_main.c + boot_main.c + 0 + 0 + + + 5 + 34 + 1 + 0 + 0 + 0 ..\Core\Bootloader\bootloader.c bootloader.c 0 @@ -913,7 +1075,7 @@ 5 - 34 + 35 5 0 0 @@ -925,7 +1087,7 @@ 5 - 35 + 36 1 0 0 @@ -937,7 +1099,7 @@ 5 - 36 + 37 5 0 0 @@ -949,7 +1111,7 @@ 5 - 37 + 38 1 0 0 @@ -961,7 +1123,7 @@ 5 - 38 + 39 5 0 0 @@ -973,7 +1135,7 @@ 5 - 39 + 40 1 0 0 @@ -985,7 +1147,7 @@ 5 - 40 + 41 5 0 0 @@ -995,18 +1157,6 @@ 0 0 - - 5 - 41 - 1 - 0 - 0 - 0 - ..\Core\Bootloader\boot_main.c - boot_main.c - 0 - 0 - diff --git a/MDK-ARM/uksvep_2_2_v1.uvprojx b/MDK-ARM/uksvep_2_2_v1.uvprojx index 91b6564..aa60635 100644 --- a/MDK-ARM/uksvep_2_2_v1.uvprojx +++ b/MDK-ARM/uksvep_2_2_v1.uvprojx @@ -315,7 +315,7 @@ 1 - 2 + 1 0 0 1 @@ -661,81 +661,68 @@ Bootloader - - - 0 - 0 - 0 - 0 - 0 - 0 - 2 - 2 - 2 - 2 - 11 - - - 1 - - - - 2 - 0 - 2 - 2 - 2 - 2 - 2 - 2 - 2 - 2 - 0 - 2 - 2 - 2 - 2 - 2 - 0 - 0 - 2 - 2 - 2 - 2 - 2 - - - - - - - - - 2 - 2 - 2 - 2 - 2 - 2 - 2 - 2 - 2 - 0 - - - - - - - - - boot_project_setup.h 5 ..\Core\Bootloader\boot_project_setup.h + + boot_main.c + 1 + ..\Core\Bootloader\boot_main.c + + + 2 + 0 + 0 + 0 + 0 + 0 + 2 + 2 + 2 + 2 + 11 + + + 1 + + + + 2 + 0 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 0 + 2 + 2 + 2 + 2 + 2 + 0 + 0 + 2 + 2 + 2 + 2 + 2 + + + + + + + + + + bootloader.c 1 @@ -776,11 +763,6 @@ 5 ..\Core\Bootloader\boot_uart.h - - boot_main.c - 1 - ..\Core\Bootloader\boot_main.c - @@ -1097,7 +1079,7 @@ 1 - 2 + 1 0 0 1 @@ -1467,6 +1449,11 @@ 5 ..\Core\Bootloader\boot_project_setup.h + + boot_main.c + 1 + ..\Core\Bootloader\boot_main.c + bootloader.c 1 @@ -1507,11 +1494,6 @@ 5 ..\Core\Bootloader\boot_uart.h - - boot_main.c - 1 - ..\Core\Bootloader\boot_main.c -