573 lines
17 KiB
C
573 lines
17 KiB
C
|
|
#include "ota_boot.h"
|
|||
|
|
#include "main.h"
|
|||
|
|
#include "boot_share.h"
|
|||
|
|
#include "../HardWare/W25Q64/w25q64.h"
|
|||
|
|
#include "../HardWare/LOG/log.h"
|
|||
|
|
#include <stdint.h>
|
|||
|
|
#include <string.h>
|
|||
|
|
|
|||
|
|
extern UART_HandleTypeDef huart3; /* main.c <20>ж<EFBFBD><D0B6>壬<EFBFBD><E5A3AC>ת APP ǰ<><C7B0>Ҫ<EFBFBD>ر<EFBFBD> */
|
|||
|
|
extern DMA_HandleTypeDef hdma_usart3_rx;
|
|||
|
|
extern IWDG_HandleTypeDef hiwdg; /* main.c <20>ж<EFBFBD><D0B6><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF>Ź<EFBFBD><C5B9><EFBFBD><EFBFBD><EFBFBD> */
|
|||
|
|
|
|||
|
|
#define IWDG_FEED() HAL_IWDG_Refresh(&hiwdg)
|
|||
|
|
|
|||
|
|
/* <20>ⲿ<EFBFBD><E2B2BF><EFBFBD>Ź<EFBFBD> TPL5010<31><30>DONE <20><><EFBFBD>Ž<EFBFBD> PC13(LED2)<29><><EFBFBD><EFBFBD>ƽ<EFBFBD><C6BD>ת<EFBFBD><D7AA>ι<EFBFBD><CEB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱԼ 7 <20><><EFBFBD>ӡ<EFBFBD>
|
|||
|
|
* BootLoader <EFBFBD>IJ<EFBFBD><EFBFBD><EFBFBD>/<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȫ<EFBFBD><EFBFBD>ԶС<EFBFBD><EFBFBD> 7 <EFBFBD><EFBFBD><EFBFBD>ӣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ι<EFBFBD><EFBFBD> */
|
|||
|
|
#define EXT_WDOG_FEED() HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13)
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
/*======================================================================*/
|
|||
|
|
/*=========================Flash <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(start)=========================*/
|
|||
|
|
/*======================================================================*/
|
|||
|
|
|
|||
|
|
static void FLASH_Unlock_Reg(void)
|
|||
|
|
{
|
|||
|
|
if ((FLASH->CR & FLASH_CR_LOCK) == 0) return;
|
|||
|
|
FLASH->KEYR = 0x45670123;
|
|||
|
|
FLASH->KEYR = 0xCDEF89AB;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static void FLASH_Lock_Reg(void)
|
|||
|
|
{
|
|||
|
|
FLASH->CR |= FLASH_CR_LOCK;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* <20>ȴ<EFBFBD><C8B4>ڲ<EFBFBD> Flash <20><><EFBFBD>У<EFBFBD><D0A3><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1=<3D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>0=<3D><>ʱ */
|
|||
|
|
static int FLASH_WaitBusy(uint32_t timeout_ms)
|
|||
|
|
{
|
|||
|
|
uint32_t start = HAL_GetTick();
|
|||
|
|
while (FLASH->SR & FLASH_SR_BSY)
|
|||
|
|
{
|
|||
|
|
if ((HAL_GetTick() - start) > timeout_ms) return 0;
|
|||
|
|
}
|
|||
|
|
return 1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static void FLASH_ClearFlags(void)
|
|||
|
|
{
|
|||
|
|
FLASH->SR = (FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPRTERR);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static int Erase_page(unsigned int pageaddr, unsigned int num)
|
|||
|
|
{
|
|||
|
|
log_info("> <20><><EFBFBD><EFBFBD> %u ҳ<><D2B3><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC>ַ 0x%X...", num, pageaddr);
|
|||
|
|
|
|||
|
|
for (unsigned int i = 0; i < num; i++)
|
|||
|
|
{
|
|||
|
|
unsigned int pg_addr = pageaddr + i * PageSize;
|
|||
|
|
|
|||
|
|
IWDG_FEED();
|
|||
|
|
EXT_WDOG_FEED();
|
|||
|
|
|
|||
|
|
FLASH_Unlock_Reg();
|
|||
|
|
FLASH_ClearFlags();
|
|||
|
|
if (!FLASH_WaitBusy(500))
|
|||
|
|
{
|
|||
|
|
log_error("> <20><><EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7> @0x%X<><58>æ<EFBFBD>ȴ<EFBFBD><C8B4><EFBFBD>ʱ", pg_addr);
|
|||
|
|
FLASH_Lock_Reg();
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
FLASH->CR |= FLASH_CR_PER;
|
|||
|
|
FLASH->AR = pg_addr;
|
|||
|
|
FLASH->CR |= FLASH_CR_STRT;
|
|||
|
|
if (!FLASH_WaitBusy(500))
|
|||
|
|
{
|
|||
|
|
log_error("> <20><><EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7> @0x%X<><58>æ<EFBFBD>ȴ<EFBFBD><C8B4><EFBFBD>ʱ", pg_addr);
|
|||
|
|
FLASH->CR &= ~FLASH_CR_PER;
|
|||
|
|
FLASH_Lock_Reg();
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
uint32_t sr = FLASH->SR;
|
|||
|
|
FLASH->CR &= ~FLASH_CR_PER;
|
|||
|
|
|
|||
|
|
if (sr & FLASH_SR_WRPRTERR)
|
|||
|
|
{
|
|||
|
|
log_error("> <20><><EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7> @0x%X<><58>SR=0x%X", pg_addr, (unsigned int)sr);
|
|||
|
|
FLASH_ClearFlags();
|
|||
|
|
FLASH_Lock_Reg();
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
FLASH_Lock_Reg();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
log_info("> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɣ<EFBFBD>%u ҳ<><D2B3>", num);
|
|||
|
|
return 1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static int FLASH_WriteHalfWord(unsigned int addr, uint16_t data)
|
|||
|
|
{
|
|||
|
|
FLASH_Unlock_Reg();
|
|||
|
|
FLASH_ClearFlags();
|
|||
|
|
if (!FLASH_WaitBusy(100))
|
|||
|
|
{
|
|||
|
|
FLASH_Lock_Reg();
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
FLASH->CR |= FLASH_CR_PG;
|
|||
|
|
*(__IO uint16_t *)addr = data;
|
|||
|
|
if (!FLASH_WaitBusy(100))
|
|||
|
|
{
|
|||
|
|
FLASH->CR &= ~FLASH_CR_PG;
|
|||
|
|
FLASH_Lock_Reg();
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
uint32_t sr = FLASH->SR;
|
|||
|
|
FLASH->CR &= ~FLASH_CR_PG;
|
|||
|
|
FLASH_ClearFlags();
|
|||
|
|
|
|||
|
|
if (sr & FLASH_SR_WRPRTERR)
|
|||
|
|
{
|
|||
|
|
FLASH_Lock_Reg();
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
FLASH_Lock_Reg();
|
|||
|
|
return 1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static int WriteFlash(unsigned int addr, unsigned int * buff, int word_size)
|
|||
|
|
{
|
|||
|
|
for (int i = 0; i < word_size; i++)
|
|||
|
|
{
|
|||
|
|
unsigned int val = buff[i];
|
|||
|
|
uint16_t low = (uint16_t)(val & 0xFFFF);
|
|||
|
|
uint16_t high = (uint16_t)(val >> 16);
|
|||
|
|
|
|||
|
|
if (!FLASH_WriteHalfWord(addr + 4 * i, low))
|
|||
|
|
{
|
|||
|
|
log_error("> д<><D0B4>ʧ<EFBFBD><CAA7> @0x%X (low=0x%04X)", addr + 4 * i, low);
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
if (!FLASH_WriteHalfWord(addr + 4 * i + 2, high))
|
|||
|
|
{
|
|||
|
|
log_error("> д<><D0B4>ʧ<EFBFBD><CAA7> @0x%X (high=0x%04X)", addr + 4 * i + 2, high);
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return 1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static void ReadFlash(unsigned int addr, unsigned int * buff, uint16_t word_size)
|
|||
|
|
{
|
|||
|
|
for(int i =0; i < word_size; i++)
|
|||
|
|
{
|
|||
|
|
buff[i] = *(__IO unsigned int*)(addr + 4 * i);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
/*====================================================================*/
|
|||
|
|
/*=========================Flash <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(end)=========================*/
|
|||
|
|
/*====================================================================*/
|
|||
|
|
|
|||
|
|
/* MODBUS CRC16 */
|
|||
|
|
static uint16_t crc16_modbus_update(uint16_t crc, uint8_t data)
|
|||
|
|
{
|
|||
|
|
crc ^= data;
|
|||
|
|
for (int i = 0; i < 8; i++) {
|
|||
|
|
if (crc & 1) crc = (crc >> 1) ^ 0xA001;
|
|||
|
|
else crc >>= 1;
|
|||
|
|
}
|
|||
|
|
return crc;
|
|||
|
|
}
|
|||
|
|
static uint16_t crc16_modbus(const uint8_t *data, uint32_t len)
|
|||
|
|
{
|
|||
|
|
uint16_t crc = 0xFFFF;
|
|||
|
|
for (uint32_t i = 0; i < len; i++) crc = crc16_modbus_update(crc, data[i]);
|
|||
|
|
return crc;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*======================================================================*/
|
|||
|
|
/* <20>ⲿ Flash <20><><EFBFBD>ڲ<EFBFBD> Flash ֮<>俽<EFBFBD><E4BFBD> */
|
|||
|
|
/*======================================================================*/
|
|||
|
|
#define COPY_CHUNK_WORDS 256 /* 1024 bytes */
|
|||
|
|
#define COPY_CHUNK_BYTES (COPY_CHUNK_WORDS * 4)
|
|||
|
|
|
|||
|
|
static int Copy_External_To_App1(uint32_t ext_addr, uint32_t byte_size)
|
|||
|
|
{
|
|||
|
|
static uint32_t words[COPY_CHUNK_WORDS];
|
|||
|
|
static uint8_t tmp[COPY_CHUNK_BYTES];
|
|||
|
|
uint32_t offset = 0;
|
|||
|
|
|
|||
|
|
log_info("[BL] <20><><EFBFBD><EFBFBD><EFBFBD>ⲿ Flash 0x%06X -> APP1 0x%08X<38><58><EFBFBD><EFBFBD>С=%u",
|
|||
|
|
(unsigned)ext_addr, Application_1_Addr, (unsigned)byte_size);
|
|||
|
|
|
|||
|
|
while (offset < byte_size)
|
|||
|
|
{
|
|||
|
|
uint32_t chunk = (byte_size - offset > COPY_CHUNK_BYTES) ? COPY_CHUNK_BYTES : (byte_size - offset);
|
|||
|
|
IWDG_FEED();
|
|||
|
|
EXT_WDOG_FEED();
|
|||
|
|
W25Q64_Read(ext_addr + offset, tmp, chunk);
|
|||
|
|
|
|||
|
|
for (uint32_t i = 0; i < chunk / 4; i++) {
|
|||
|
|
words[i] = ((uint32_t)tmp[i * 4]) |
|
|||
|
|
((uint32_t)tmp[i * 4 + 1] << 8) |
|
|||
|
|
((uint32_t)tmp[i * 4 + 2] << 16) |
|
|||
|
|
((uint32_t)tmp[i * 4 + 3] << 24);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (!WriteFlash(Application_1_Addr + offset, words, chunk / 4))
|
|||
|
|
{
|
|||
|
|
log_error("[FAIL] д<><D0B4> APP1 ʧ<><CAA7> @0x%X", Application_1_Addr + offset);
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
for (uint32_t i = 0; i < chunk / 4; i++) {
|
|||
|
|
uint32_t r = *(__IO uint32_t *)(Application_1_Addr + offset + i * 4);
|
|||
|
|
if (r != words[i]) {
|
|||
|
|
log_error("[FAIL] У<><D0A3> APP1 ʧ<><CAA7> @0x%X<><58>wrote=0x%08X read=0x%08X",
|
|||
|
|
Application_1_Addr + offset + i * 4, (unsigned)words[i], (unsigned)r);
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
offset += chunk;
|
|||
|
|
if ((offset & 0x3FFF) == 0) {
|
|||
|
|
log_info("> <20><><EFBFBD><EFBFBD>: %u/%u KB (%u%%)", offset / 1024, byte_size / 1024, offset * 100 / byte_size);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
log_info("[ OK ] <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
|
|||
|
|
return 1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static int Copy_App1_To_External(uint32_t ext_addr, uint32_t byte_size)
|
|||
|
|
{
|
|||
|
|
static uint32_t words[COPY_CHUNK_WORDS];
|
|||
|
|
static uint8_t tmp[COPY_CHUNK_BYTES];
|
|||
|
|
uint32_t offset = 0;
|
|||
|
|
|
|||
|
|
log_info("[BL] <20><><EFBFBD><EFBFBD> APP1 -> <20>ⲿ Flash 0x%06X<36><58><EFBFBD><EFBFBD>С=%u", (unsigned)ext_addr, (unsigned)byte_size);
|
|||
|
|
|
|||
|
|
while (offset < byte_size)
|
|||
|
|
{
|
|||
|
|
uint32_t chunk = (byte_size - offset > COPY_CHUNK_BYTES) ? COPY_CHUNK_BYTES : (byte_size - offset);
|
|||
|
|
IWDG_FEED();
|
|||
|
|
EXT_WDOG_FEED();
|
|||
|
|
ReadFlash(Application_1_Addr + offset, words, chunk / 4);
|
|||
|
|
for (uint32_t i = 0; i < chunk / 4; i++) {
|
|||
|
|
tmp[i * 4] = (uint8_t)(words[i]);
|
|||
|
|
tmp[i * 4 + 1] = (uint8_t)(words[i] >> 8);
|
|||
|
|
tmp[i * 4 + 2] = (uint8_t)(words[i] >> 16);
|
|||
|
|
tmp[i * 4 + 3] = (uint8_t)(words[i] >> 24);
|
|||
|
|
}
|
|||
|
|
W25Q64_WriteBuffer(ext_addr + offset, tmp, chunk);
|
|||
|
|
if (!W25Q64_Verify(ext_addr + offset, tmp, chunk)) {
|
|||
|
|
log_error("[FAIL] W25Q64 <20><><EFBFBD><EFBFBD>У<EFBFBD><D0A3>ʧ<EFBFBD><CAA7> @0x%06X", (unsigned)(ext_addr + offset));
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
offset += chunk;
|
|||
|
|
}
|
|||
|
|
return 1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/* У<><D0A3><EFBFBD>̼<EFBFBD><CCBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԣ<EFBFBD><D4A3><EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD>λ<EFBFBD><CEBB><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7>Ϸ<EFBFBD> */
|
|||
|
|
static int Verify_Firmware(unsigned int addr, unsigned int size)
|
|||
|
|
{
|
|||
|
|
/* <20><><EFBFBD><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD>ַ<EFBFBD>Ƿ<EFBFBD><C7B7>ںϷ<DABA>RAM<41><4D>Χ (0x20000000) */
|
|||
|
|
unsigned int sp = *(__IO unsigned int *)addr;
|
|||
|
|
if ((sp & 0x2FFE0000) != 0x20000000)
|
|||
|
|
{
|
|||
|
|
log_error("> У<><D0A3>ʧ<EFBFBD>ܣ<EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD>ַ<EFBFBD>Ƿ<EFBFBD> SP=0x%X", sp);
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* <20><><EFBFBD>鸴λ<E9B8B4><CEBB><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD>APP1<50>̼<EFBFBD><CCBC><EFBFBD>Χ<EFBFBD>ڣ<EFBFBD><DAA3>̼<EFBFBD><CCBC><EFBFBD><EFBFBD>ӵ<EFBFBD>ַ<EFBFBD><D6B7>APP1<50><31> */
|
|||
|
|
unsigned int reset_vector = *(__IO unsigned int *)(addr + 4);
|
|||
|
|
if (reset_vector < Application_1_Addr || reset_vector > (Application_1_Addr + size))
|
|||
|
|
{
|
|||
|
|
log_error("> У<><D0A3>ʧ<EFBFBD>ܣ<EFBFBD><DCA3><EFBFBD>λ<EFBFBD><CEBB><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD>=0x%X", reset_vector);
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
log_info("> <20>̼<EFBFBD>У<EFBFBD><D0A3>ͨ<EFBFBD><CDA8>");
|
|||
|
|
return 1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><D5BB>ջֵ */
|
|||
|
|
__asm void MSR_MSP (unsigned int ulAddr)
|
|||
|
|
{
|
|||
|
|
MSR MSP, r0 //set Main Stack value
|
|||
|
|
BX r14
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD><D7AA><EFBFBD><EFBFBD>: <20><><EFBFBD><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD>Ϸ<EFBFBD><CFB7>Ժ<EFBFBD><D4BA><EFBFBD>ת<EFBFBD><D7AA>Ŀ<EFBFBD><C4BF> APP */
|
|||
|
|
typedef void (*Jump_Fun)(void);
|
|||
|
|
void IAP_ExecuteApp (unsigned int App_Addr)
|
|||
|
|
{
|
|||
|
|
Jump_Fun JumpToApp;
|
|||
|
|
|
|||
|
|
if ( ( ( * ( __IO unsigned int * ) App_Addr ) & 0x2FFE0000 ) == 0x20000000 )
|
|||
|
|
{
|
|||
|
|
unsigned int sp = *(__IO unsigned int *)App_Addr;
|
|||
|
|
unsigned int pc = *(__IO unsigned int *)(App_Addr + 4);
|
|||
|
|
log_info("[BL] <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD><D7AA> APP1 @0x%08X...", App_Addr);
|
|||
|
|
|
|||
|
|
/* <20><>תǰ<D7AA>ر<EFBFBD> BootLoader ʹ<>õ<EFBFBD><C3B5>жϺ<D0B6><CFBA><EFBFBD><EFBFBD>裬<EFBFBD><E8A3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> APP<50><50>
|
|||
|
|
* ע<EFBFBD>ⲻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> __disable_irq()<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD><EFBFBD><EFBFBD>Ǹ<EFBFBD>λ<EFBFBD><EFBFBD>PRIMASK <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> APP<EFBFBD><EFBFBD> */
|
|||
|
|
HAL_UART_DMAStop(&huart3);
|
|||
|
|
__HAL_UART_DISABLE_IT(&huart3, UART_IT_IDLE);
|
|||
|
|
HAL_NVIC_DisableIRQ(USART3_IRQn);
|
|||
|
|
HAL_NVIC_DisableIRQ(DMA1_Channel3_IRQn);
|
|||
|
|
NVIC_ClearPendingIRQ(USART3_IRQn);
|
|||
|
|
NVIC_ClearPendingIRQ(DMA1_Channel3_IRQn);
|
|||
|
|
SysTick->CTRL = 0; /* ֹͣ SysTick */
|
|||
|
|
SCB->ICSR = SCB_ICSR_PENDSTCLR_Msk; /* <20><> SysTick <20><><EFBFBD><EFBFBD>λ */
|
|||
|
|
|
|||
|
|
JumpToApp = (Jump_Fun)pc;
|
|||
|
|
MSR_MSP(sp);
|
|||
|
|
JumpToApp();
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
log_error("[BL] <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>APP @0x%08X ջ<><D5BB><EFBFBD><EFBFBD>ַ<EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD>", App_Addr);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
/*==== <20><><EFBFBD><EFBFBD>Դ<EFBFBD><D4B4><EFBFBD>⣨PA0/ADC1_CH0<48><30><EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD>ֱ<EFBFBD><D6B1><EFBFBD><EFBFBD>BL <20><> ADC HAL ģ<>飩====
|
|||
|
|
* <EFBFBD>ⲿ 12V <EFBFBD>Ͽ<EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ά<EFBFBD>֣<EFBFBD><EFBFBD><EFBFBD>ѹ<EFBFBD><EFBFBD><EFBFBD>ٵ<EFBFBD><EFBFBD>䣻
|
|||
|
|
* <EFBFBD><EFBFBD>ֵ 20%<EFBFBD><EFBFBD>Լ 11.2V<EFBFBD><EFBFBD>ADC<EFBFBD><EFBFBD>1196<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е糡<EFBFBD><EFBFBD>=12V <EFBFBD>Ͽ<EFBFBD><EFBFBD>оݣ<EFBFBD>
|
|||
|
|
* ﮵<EFBFBD><EFBFBD>س<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> APP <EFBFBD><EFBFBD> <10% <EFBFBD>ϵ<EFBFBD>Ԥ<EFBFBD><EFBFBD><EFBFBD>γ<EFBFBD><EFBFBD>ͻأ<EFBFBD><EFBFBD><EFBFBD>ֹ<EFBFBD>ص<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
|
|||
|
|
#define BL_MAIN_POWER_ADC_MIN 1196u
|
|||
|
|
|
|||
|
|
static uint16_t BL_ReadPowerAdc(void)
|
|||
|
|
{
|
|||
|
|
__HAL_RCC_GPIOA_CLK_ENABLE();
|
|||
|
|
__HAL_RCC_ADC1_CLK_ENABLE();
|
|||
|
|
GPIOA->CRL &= ~0xFu; /* PA0 ģ<><C4A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
|
|||
|
|
ADC1->SMPR2 |= 7u; /* ͨ<><CDA8>0 <20><><EFBFBD><EFBFBD> 239.5 <20><><EFBFBD><EFBFBD> */
|
|||
|
|
ADC1->SQR3 = 0;
|
|||
|
|
ADC1->CR2 |= ADC_CR2_ADON; /* ADC <20>ϵ<EFBFBD> */
|
|||
|
|
for (volatile uint32_t i = 0; i < 8000; i++); /* <20>ȶ<EFBFBD>ʱ<EFBFBD><CAB1> */
|
|||
|
|
ADC1->CR2 |= ADC_CR2_RSTCAL;
|
|||
|
|
while (ADC1->CR2 & ADC_CR2_RSTCAL);
|
|||
|
|
ADC1->CR2 |= ADC_CR2_CAL;
|
|||
|
|
while (ADC1->CR2 & ADC_CR2_CAL);
|
|||
|
|
ADC1->CR2 |= ADC_CR2_EXTTRIG | ADC_CR2_EXTSEL; /* SWSTART <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
|
|||
|
|
ADC1->CR2 |= ADC_CR2_SWSTART;
|
|||
|
|
for (volatile uint32_t i = 0; i < 100000; i++) {
|
|||
|
|
if (ADC1->SR & ADC_SR_EOC) break;
|
|||
|
|
}
|
|||
|
|
return (uint16_t)ADC1->DR;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* <20><><EFBFBD><EFBFBD>Դδ<D4B4>ϵ<EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD> APP<50><50>ѭ<EFBFBD><D1AD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD><D6B1> 12V <20>ָ<EFBFBD><D6B8><EFBFBD>
|
|||
|
|
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݺľ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ磬12V <EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȼͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
|
|||
|
|
static void BL_WaitMainPower(void)
|
|||
|
|
{
|
|||
|
|
uint16_t adc = BL_ReadPowerAdc();
|
|||
|
|
if (adc >= BL_MAIN_POWER_ADC_MIN) return;
|
|||
|
|
/* <20><>ѹ(<28><>10) = ADC*363/4096 + 6<><36><EFBFBD><EFBFBD><EFBFBD><EFBFBD>% = (V-10.8)*100/1.8<EFBFBD><EFBFBD>10.8V=0%<25><>12.6V=100%<25><><EFBFBD><EFBFBD>
|
|||
|
|
* <EFBFBD><EFBFBD>ֵ 20%<EFBFBD><EFBFBD>Լ 11.2V<EFBFBD><EFBFBD><EFBFBD><EFBFBD> APP <EFBFBD><EFBFBD> <10% <EFBFBD>ϵ<EFBFBD>Ԥ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>γ<EFBFBD><EFBFBD>ͻأ<EFBFBD>
|
|||
|
|
* ﮵<EFBFBD><EFBFBD>س<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֹ"<EFBFBD>ص<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٸ<EFBFBD>λ"<EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
|
|||
|
|
uint32_t v10 = (uint32_t)adc * 363u / 4096u + 6u;
|
|||
|
|
uint32_t pct = (v10 > 108u) ? (v10 - 108u) * 100u / 18u : 0;
|
|||
|
|
if (pct > 100u) pct = 100u;
|
|||
|
|
log_warn("[BL] <20><><EFBFBD><EFBFBD><EFBFBD>ͣ<EFBFBD><CDA3><EFBFBD>ѹ %u.%uV<75><56><EFBFBD><EFBFBD><EFBFBD><EFBFBD> %u%%<25><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 20%% <20><><EFBFBD>ϻָ<CFBB>...",
|
|||
|
|
(unsigned)(v10 / 10u), (unsigned)(v10 % 10u), (unsigned)pct);
|
|||
|
|
while (1) {
|
|||
|
|
IWDG_FEED();
|
|||
|
|
EXT_WDOG_FEED(); /* <20>ⲿ TPL5010 ҲҪι<D2AA><CEB9><EFBFBD>Ž<EFBFBD><C5BD>ȴ<EFBFBD><C8B4><EFBFBD><EFBFBD>ܳ<EFBFBD><DCB3><EFBFBD><EFBFBD>ܾ<EFBFBD> */
|
|||
|
|
HAL_Delay(500);
|
|||
|
|
adc = BL_ReadPowerAdc();
|
|||
|
|
if (adc >= BL_MAIN_POWER_ADC_MIN) {
|
|||
|
|
v10 = (uint32_t)adc * 363u / 4096u + 6u;
|
|||
|
|
pct = (v10 > 108u) ? (v10 - 108u) * 100u / 18u : 0;
|
|||
|
|
log_info("[BL] <20><><EFBFBD><EFBFBD><EFBFBD>ѻָ<D1BB><D6B8><EFBFBD>%u%%<25><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת APP", (unsigned)pct);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void Start_BootLoader(void)
|
|||
|
|
{
|
|||
|
|
log_info("");
|
|||
|
|
log_info("* * * * * * * * * * * * * * * * * *");
|
|||
|
|
log_info("* BootLoader *");
|
|||
|
|
log_info("* Flash: %dKB *", *(volatile uint16_t *)0x1FFFF7E0);
|
|||
|
|
log_info("* * * * * By Helei * * * * * *");
|
|||
|
|
|
|||
|
|
EXT_WDOG_FEED(); /* <20><> BootLoader <20><>ιһ<CEB9><D2BB><EFBFBD>ⲿ<EFBFBD><E2B2BF><EFBFBD>Ź<EFBFBD> */
|
|||
|
|
|
|||
|
|
/* <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λԭ<CEBB><D4AD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"<22>̼<EFBFBD><CCBC><EFBFBD><EFBFBD><EFBFBD>(<28><><EFBFBD>Ź<EFBFBD><C5B9><EFBFBD>λ)"<22><>"<22>ֳ<EFBFBD><D6B3>ϵ<EFBFBD>/<2F><><EFBFBD><EFBFBD>/<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"<22><>
|
|||
|
|
ͬʱ<EFBFBD><EFBFBD> CSR <EFBFBD><EFBFBD>־д<EFBFBD><EFBFBD> BOOT_SHARE <EFBFBD><EFBFBD><EFBFBD><EFBFBD> RAM <EFBFBD><EFBFBD><EFBFBD><EFBFBD> APP<EFBFBD><EFBFBD><EFBFBD><EFBFBD>λԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><EFBFBD> APP <EFBFBD><EFBFBD><EFBFBD>ɣ<EFBFBD> */
|
|||
|
|
uint32_t reset_flags = RCC->CSR;
|
|||
|
|
RCC->CSR |= RCC_CSR_RMVF;
|
|||
|
|
if (boot_share_valid()) {
|
|||
|
|
BOOT_SHARE->csr_flags = reset_flags; /* <20><><EFBFBD><EFBFBD> uptime/pending_reason<6F><6E><EFBFBD>ȸ<EFBFBD>λ<EFBFBD><CEBB>Ϣ<EFBFBD><CFA2> */
|
|||
|
|
} else {
|
|||
|
|
BOOT_SHARE->uptime_sec = 0;
|
|||
|
|
BOOT_SHARE->pending_reason = 0;
|
|||
|
|
BOOT_SHARE->csr_flags = reset_flags;
|
|||
|
|
BOOT_SHARE->magic = BOOT_SHARE_MAGIC;
|
|||
|
|
}
|
|||
|
|
boot_share_store();
|
|||
|
|
/* <20><>λԭ<CEBB><D4AD><EFBFBD><EFBFBD><EFBFBD>ٴ<EFBFBD><D9B4>ڴ<EFBFBD>ӡ<EFBFBD><D3A1>CSR <20><>ͨ<EFBFBD><CDA8> BOOT_SHARE <20><><EFBFBD><EFBFBD> APP<50><50><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> HISTORY <20>鿴<EFBFBD><E9BFB4> */
|
|||
|
|
|
|||
|
|
/* <20><><EFBFBD><EFBFBD>Դδ<D4B4>ϵ磨<CFB5><E7A3A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ά<EFBFBD>֣<EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD> APP<50><50><EFBFBD><EFBFBD>ֹ<EFBFBD><D6B9><EFBFBD><EFBFBD>û<EFBFBD>ϵ<EFBFBD><CFB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
|
|||
|
|
BL_WaitMainPower();
|
|||
|
|
|
|||
|
|
W25Q64_OtaInfo info;
|
|||
|
|
int info_ok = (W25Q64_OTA_ReadInfo(&info) == 0);
|
|||
|
|
|
|||
|
|
/* <20>̼<EFBFBD><CCBC><EFBFBD>С<EFBFBD>Ϸ<EFBFBD><CFB7>Լ<EFBFBD><D4BC>飺<EFBFBD><E9A3BA>Ϣ<EFBFBD><CFA2> checksum <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֹ<EFBFBD><EFBFBD> size <20><><EFBFBD><EFBFBD>Խ<EFBFBD><D4BD>д<EFBFBD>ڲ<EFBFBD> Flash */
|
|||
|
|
if (info_ok && info.new_valid
|
|||
|
|
&& (info.update_state == W25Q64_STATE_DOWNLOADED || info.update_state == W25Q64_STATE_COPYING)
|
|||
|
|
&& (info.new_size == 0 || info.new_size > Application_Size || (info.new_size & 0x3) != 0))
|
|||
|
|
{
|
|||
|
|
log_warn("[BL] <20>¹̼<C2B9><CCBC><EFBFBD>С<EFBFBD>Ƿ<EFBFBD> new_size=%u<><75><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¹̼<C2B9>", (unsigned)info.new_size);
|
|||
|
|
W25Q64_OTA_ClearNew();
|
|||
|
|
info.new_valid = 0; /* <20><>ֹ<EFBFBD><D6B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD><C4B8>·<EFBFBD>֧ */
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 1. <20>¹̼<C2B9><CCBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD><D8B5>ⲿ Flash<73><68><EFBFBD><EFBFBD><EFBFBD>ݵ<EFBFBD>ǰ APP1<50><31>Ȼ<EFBFBD><C8BB>д<EFBFBD><D0B4> APP1<50><31>
|
|||
|
|
* COPYING Ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>/<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>;<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ź<EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
* <EFBFBD>ⲿ<EFBFBD>¹̼<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD>и<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̣<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ῠ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>"<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч APP"״̬ */
|
|||
|
|
if (info_ok && info.new_valid
|
|||
|
|
&& (info.update_state == W25Q64_STATE_DOWNLOADED || info.update_state == W25Q64_STATE_COPYING))
|
|||
|
|
{
|
|||
|
|
log_info("[BL] <20>ⲿ Flash <20><><EFBFBD><EFBFBD><EFBFBD>¹̼<C2B9><CCBC><EFBFBD>ver=%u size=%u crc=0x%04X",
|
|||
|
|
(unsigned)info.new_version, (unsigned)info.new_size, (unsigned)info.new_crc16);
|
|||
|
|
|
|||
|
|
W25Q64_OTA_SetState(W25Q64_STATE_COPYING);
|
|||
|
|
|
|||
|
|
/* <20><><EFBFBD>ݲ<EFBFBD><DDB2>ԣ<EFBFBD><D4A3><EFBFBD>ǰ APP1 <20><>Чʱ<D0A7><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч<EFBFBD><D0A7><EFBFBD>ݲ<EFBFBD><DDB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>£<EFBFBD>
|
|||
|
|
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¹̼<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD>ް汾<EFBFBD>ɻ<EFBFBD><EFBFBD>ˣ<EFBFBD><EFBFBD><EFBFBD>ש<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʧ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>θ<EFBFBD><EFBFBD>£<EFBFBD>
|
|||
|
|
* <EFBFBD>ⲿ<EFBFBD>¹̼<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>´<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԣ<EFBFBD>APP1 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɱ<EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD>Ӹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ծȣ<EFBFBD> */
|
|||
|
|
int app1_valid = Verify_Firmware(Application_1_Addr, Application_Size);
|
|||
|
|
if (!info.backup_valid && app1_valid)
|
|||
|
|
{
|
|||
|
|
/* <20><><EFBFBD><EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD>Ȳ<EFBFBD><C8B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݲۣ<DDB2>W25Q64 ֻ<>ܰ<EFBFBD>λ<EFBFBD><CEBB> 1 д 0<><30><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD><D6B1>д<EFBFBD><D0B4><EFBFBD>õ<EFBFBD><C3B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
|
|||
|
|
log_info("[BL] <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݲ<EFBFBD>...");
|
|||
|
|
W25Q64_EraseRegion(W25Q64_SLOT_BACKUP_ADDR, Application_Size);
|
|||
|
|
uint16_t backup_crc = crc16_modbus((const uint8_t *)Application_1_Addr, Application_Size);
|
|||
|
|
if (Copy_App1_To_External(W25Q64_SLOT_BACKUP_ADDR, Application_Size)
|
|||
|
|
&& W25Q64_OTA_SetBackupInfo(Application_Size, backup_crc) == 0)
|
|||
|
|
{
|
|||
|
|
info.backup_valid = 1; /* ͬ<><CDAC><EFBFBD><EFBFBD><EFBFBD>ظ<EFBFBD><D8B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD><C4B8>·<EFBFBD>֧Ҫ<D6A7><D2AA> */
|
|||
|
|
log_info("[BL] <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɣ<EFBFBD>crc=0x%04X", (unsigned)backup_crc);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
log_error("[BL] <20><><EFBFBD><EFBFBD>ʧ<EFBFBD>ܣ<EFBFBD><DCA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>£<EFBFBD><C2A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> APP1<50><31><EFBFBD>´<EFBFBD><C2B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԣ<EFBFBD>");
|
|||
|
|
W25Q64_OTA_SetState(W25Q64_STATE_DOWNLOADED);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else if (!app1_valid)
|
|||
|
|
{
|
|||
|
|
log_warn("[BL] APP1 <20><>Ч<EFBFBD><D0A7><EFBFBD>ɱ<DEBF><C9B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD><DDA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ψһ<CEA8>Ծ<EFBFBD><D4BE>ֶ<EFBFBD>");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (info.backup_valid || !app1_valid)
|
|||
|
|
{
|
|||
|
|
log_info("[BL] <20><><EFBFBD>ڸ<EFBFBD><DAB8><EFBFBD> APP1...");
|
|||
|
|
if (Erase_page(Application_1_Addr, Application_Size / PageSize))
|
|||
|
|
{
|
|||
|
|
if (Copy_External_To_App1(W25Q64_SLOT_NEW_ADDR, info.new_size))
|
|||
|
|
{
|
|||
|
|
uint16_t app_crc = crc16_modbus((const uint8_t *)Application_1_Addr, info.new_size);
|
|||
|
|
if (app_crc == info.new_crc16 && Verify_Firmware(Application_1_Addr, info.new_size))
|
|||
|
|
{
|
|||
|
|
log_info("[BL] APP1 <20><><EFBFBD>³ɹ<C2B3><C9B9><EFBFBD>crc=0x%04X<34><58><EFBFBD><EFBFBD>ת<EFBFBD><D7AA><EFBFBD><EFBFBD>", (unsigned)app_crc);
|
|||
|
|
W25Q64_OTA_SetState(W25Q64_STATE_INSTALLED);
|
|||
|
|
W25Q64_OTA_ClearConfirmed();
|
|||
|
|
IAP_ExecuteApp(Application_1_Addr);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
log_error("[BL] APP1 CRC <20><>ͷ<EFBFBD><CDB7>У<EFBFBD>鲻ƥ<E9B2BB>䣡app_crc=0x%04X", (unsigned)app_crc);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
log_warn("[BL] APP1 <20><><EFBFBD><EFBFBD>ʧ<EFBFBD>ܣ<EFBFBD><DCA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ⲿ<EFBFBD>¹̼<C2B9><CCBC>Ա<EFBFBD><D4B1><EFBFBD><EFBFBD><EFBFBD>");
|
|||
|
|
W25Q64_OTA_SetState(W25Q64_STATE_DOWNLOADED);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 2. <20>Ѱ<EFBFBD>װ<EFBFBD><D7B0>δȷ<CEB4>ϣ<EFBFBD><CFA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
|
|||
|
|
if (info_ok && info.update_state == W25Q64_STATE_INSTALLED)
|
|||
|
|
{
|
|||
|
|
if (info.app_confirmed)
|
|||
|
|
{
|
|||
|
|
log_info("[BL] <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȷ<EFBFBD>ϣ<EFBFBD><CFA3><EFBFBD><EFBFBD><EFBFBD> OTA <20><>־");
|
|||
|
|
W25Q64_OTA_ClearNew();
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
/* ֻ<>п<EFBFBD><D0BF>Ź<EFBFBD><C5B9><EFBFBD>λ<EFBFBD><CEBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˵<EFBFBD><CBB5><EFBFBD>¹̼<C2B9><CCBC><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
<EFBFBD>ϵ<EFBFBD>/<EFBFBD><EFBFBD><EFBFBD><EFBFBD>/<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD>ƣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֳ<EFBFBD><EFBFBD>ϵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ˡ<EFBFBD>
|
|||
|
|
APP <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD><EFBFBD><EFBFBD> W25Q64_OTA_IncTrial() <EFBFBD><EFBFBD>һ<EFBFBD>Ρ<EFBFBD> */
|
|||
|
|
if (reset_flags & (RCC_CSR_IWDGRSTF | RCC_CSR_WWDGRSTF))
|
|||
|
|
{
|
|||
|
|
W25Q64_OTA_IncTrial();
|
|||
|
|
info.boot_trial_count++;
|
|||
|
|
log_warn("[BL] APP <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ź<EFBFBD><C5B9><EFBFBD>λ<EFBFBD><CEBB><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD><EFBFBD>=%u", (unsigned)info.boot_trial_count);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
log_info("[BL] <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><CEBB>־=0x%08X<38><58><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>", (unsigned)reset_flags);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (info.boot_trial_count >= W25Q64_MAX_TRIALS)
|
|||
|
|
{
|
|||
|
|
log_warn("[BL] <20>ﵽ<EFBFBD><EFB5BD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˵<EFBFBD><CBB5><EFBFBD><EFBFBD>ݹ̼<DDB9>");
|
|||
|
|
/* <20><><EFBFBD>ݴ<EFBFBD>С<EFBFBD>Ϸ<EFBFBD><CFB7>Լ<EFBFBD><D4BC>飬<EFBFBD><E9A3AC>ֹԽ<D6B9><D4BD>д<EFBFBD>ڲ<EFBFBD> Flash */
|
|||
|
|
if (info.backup_valid && info.backup_size > 0
|
|||
|
|
&& info.backup_size <= Application_Size && (info.backup_size & 0x3) == 0
|
|||
|
|
&& Erase_page(Application_1_Addr, Application_Size / PageSize))
|
|||
|
|
{
|
|||
|
|
if (Copy_External_To_App1(W25Q64_SLOT_BACKUP_ADDR, info.backup_size))
|
|||
|
|
{
|
|||
|
|
uint16_t app_crc = crc16_modbus((const uint8_t *)Application_1_Addr, info.backup_size);
|
|||
|
|
if (app_crc == info.backup_crc16 && Verify_Firmware(Application_1_Addr, Application_Size))
|
|||
|
|
{
|
|||
|
|
W25Q64_OTA_SetState(W25Q64_STATE_ROLLBACK);
|
|||
|
|
IAP_ExecuteApp(Application_1_Addr);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
log_error("[BL] <20><><EFBFBD><EFBFBD>ʧ<EFBFBD>ܣ<EFBFBD>");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 3. <20><><EFBFBD><EFBFBD>״̬<D7B4><CCAC><EFBFBD><EFBFBD>ת<EFBFBD><D7AA>ǰ APP1<50><31><EFBFBD><EFBFBD>У<EFBFBD>飬<EFBFBD><E9A3AC>ֹ APP <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƭ<EFBFBD><C6AC> */
|
|||
|
|
if (info_ok && info.update_state == W25Q64_STATE_ROLLBACK)
|
|||
|
|
{
|
|||
|
|
if (Verify_Firmware(Application_1_Addr, Application_Size))
|
|||
|
|
{
|
|||
|
|
IAP_ExecuteApp(Application_1_Addr);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
log_warn("[BL] <20><><EFBFBD><EFBFBD>״̬<D7B4><CCAC> APP1 <20><>Ч<EFBFBD><D0A7><EFBFBD><EFBFBD><EFBFBD><EFBFBD> OTA <20><>־");
|
|||
|
|
W25Q64_OTA_ClearNew();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 4. û<><C3BB> OTA <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD><D6B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD> APP1 */
|
|||
|
|
if (Verify_Firmware(Application_1_Addr, Application_Size))
|
|||
|
|
{
|
|||
|
|
IAP_ExecuteApp(Application_1_Addr);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
/* δ<>ҵ<EFBFBD><D2B5><EFBFBD>Ч APP<50><50><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֻˢ<D6BB><CBA2> BL<42><4C><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ 3s <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><CEBB><EFBFBD>ԣ<EFBFBD>
|
|||
|
|
* ֮<EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD> JLink/OTA ˢ<EFBFBD><EFBFBD> APP <EFBFBD><EFBFBD><EFBFBD>ɻָ<EFBFBD> */
|
|||
|
|
log_error("[BL] δ<>ҵ<EFBFBD><D2B5><EFBFBD>Ч<EFBFBD><D0A7> APP1<50><31>3s <20><><EFBFBD><EFBFBD>λ<EFBFBD><CEBB><EFBFBD><EFBFBD>");
|
|||
|
|
HAL_Delay(3000);
|
|||
|
|
NVIC_SystemReset();
|
|||
|
|
}
|
|||
|
|
}
|