mirror of
https://github.com/No-Chicken/Power-Pico.git
synced 2026-04-03 13:02:36 +08:00
更新跳转逻辑
This commit is contained in:
@@ -175,50 +175,43 @@ int main(void)
|
|||||||
// 如果没按下KEY1, 且有APP程序, 则运行APP, 没有APP则
|
// 如果没按下KEY1, 且有APP程序, 则运行APP, 没有APP则
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
uint32_t data1, data2;
|
UpgradeInfo_t app_info;
|
||||||
char *str_flag;
|
pFunction Jump_To_Application;
|
||||||
uint32_t address = 0x08008000; // Flash 中数据的起始地址
|
|
||||||
|
|
||||||
// 读取地址为 0x08008000 的数据
|
// 1. 从独立的校验区(Sector 3)读取升级信息结构体
|
||||||
data1 = *(uint32_t *)address;
|
memcpy(&app_info, (void*)UPGRADE_INFO_ADDRESS, sizeof(UpgradeInfo_t));
|
||||||
|
|
||||||
// 读取地址为 0x08008004 的数据
|
// 2. 检查标志是否有效 (魔法字和完成状态)
|
||||||
data2 = *(uint32_t *)(address + sizeof(uint32_t));
|
if (app_info.magic_word == MAGIC_WORD && app_info.upgrade_status == UPGRADE_STATUS_COMPLETE)
|
||||||
|
|
||||||
// 将数据转换为字符数组
|
|
||||||
char str1[5], str2[5];
|
|
||||||
memcpy(str1, &data1, sizeof(data1));
|
|
||||||
memcpy(str2, &data2, sizeof(data2));
|
|
||||||
str1[4] = '\0';
|
|
||||||
str2[4] = '\0';
|
|
||||||
|
|
||||||
// 拼接两个字符数组
|
|
||||||
char combined_str[9];
|
|
||||||
strcpy(combined_str, str1);
|
|
||||||
strcat(combined_str, str2);
|
|
||||||
|
|
||||||
// 检查是否与 "APP FLAG" 相同
|
|
||||||
if (strcmp(combined_str, "APP FLAG") == 0)
|
|
||||||
{
|
{
|
||||||
// 如果相同则跳转
|
// 3. 校验APP固件的完整性
|
||||||
USB_PutString("APP FLAG OK, jump to app\r\n");
|
uint32_t current_crc = Calculate_CRC32(APPLICATION_ADDRESS, app_info.new_app_size);
|
||||||
//user code here
|
|
||||||
SysTick->CTRL = 0X00;//禁止SysTick
|
if (current_crc == app_info.new_app_crc32)
|
||||||
|
{
|
||||||
|
// 4. 校验成功,执行跳转
|
||||||
|
USB_PutString("Valid APP found, jumping to application...\r\n");
|
||||||
|
// 获取APP的堆栈指针和跳转地址
|
||||||
|
uint32_t JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);
|
||||||
|
Jump_To_Application = (pFunction) JumpAddress;
|
||||||
|
// 在跳转前反初始化所有Bootloader用过的外设
|
||||||
|
USER_USB_DEVICE_DeInit();
|
||||||
|
HAL_RCC_DeInit();
|
||||||
|
HAL_DeInit();
|
||||||
|
SysTick->CTRL = 0;
|
||||||
SysTick->LOAD = 0;
|
SysTick->LOAD = 0;
|
||||||
SysTick->VAL = 0;
|
SysTick->VAL = 0;
|
||||||
__disable_irq();
|
__disable_irq();
|
||||||
|
|
||||||
//set JumpAddress
|
// 设置APP的堆栈指针并跳转
|
||||||
JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);
|
|
||||||
/* Jump to user application */
|
|
||||||
Jump_To_Application = (pFunction) JumpAddress;
|
|
||||||
/* Initialize user application's Stack Pointer */
|
|
||||||
__set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);
|
__set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);
|
||||||
Jump_To_Application();
|
Jump_To_Application();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// no legal APP
|
// no legal APP
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
USB_PutString("No App found, enter firmware update mode\r\n");
|
||||||
LCD_ShowString(74, LCD_H/3, (uint8_t*)"No App!", WHITE, BLACK, 24, 0);//12*6,16*8,24*12,32*16
|
LCD_ShowString(74, LCD_H/3, (uint8_t*)"No App!", WHITE, BLACK, 24, 0);//12*6,16*8,24*12,32*16
|
||||||
LCD_ShowString(24, LCD_H/3+48, (uint8_t*)"Plz Download APP", WHITE, BLACK, 24, 0);
|
LCD_ShowString(24, LCD_H/3+48, (uint8_t*)"Plz Download APP", WHITE, BLACK, 24, 0);
|
||||||
HAL_Delay(2000);
|
HAL_Delay(2000);
|
||||||
|
|||||||
@@ -325,5 +325,22 @@ void GetInputString (uint8_t * buffP)
|
|||||||
buffP[bytes_read] = '\0';
|
buffP[bytes_read] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Calculates the CRC32 of a given memory area.
|
||||||
|
* @param start_address: Start address of the data
|
||||||
|
* @param size: Size of the data in bytes
|
||||||
|
* @retval Calculated CRC32 value
|
||||||
|
*/
|
||||||
|
uint32_t Calculate_CRC32(uint32_t start_address, uint32_t size)
|
||||||
|
{
|
||||||
|
// ??CRC????
|
||||||
|
__HAL_RCC_CRC_CLK_ENABLE();
|
||||||
|
CRC_HandleTypeDef CrcHandle;
|
||||||
|
CrcHandle.Instance = CRC;
|
||||||
|
HAL_CRC_Init(&CrcHandle);
|
||||||
|
|
||||||
|
return HAL_CRC_Calculate(&CrcHandle, (uint32_t*)start_address, size / 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*******************(C)COPYRIGHT 2011 STMicroelectronics *****END OF FILE******/
|
/*******************(C)COPYRIGHT 2011 STMicroelectronics *****END OF FILE******/
|
||||||
|
|||||||
@@ -46,6 +46,20 @@
|
|||||||
|
|
||||||
#define USBPutString(x) USB_PutString((uint8_t*)(x))
|
#define USBPutString(x) USB_PutString((uint8_t*)(x))
|
||||||
|
|
||||||
|
// 定义升级信息结构体
|
||||||
|
typedef struct {
|
||||||
|
uint32_t magic_word; // 魔法字,如 0xDEADBEEF,用于标识此结构体有效
|
||||||
|
uint32_t upgrade_status; // 升级状态标志
|
||||||
|
uint32_t new_app_size; // 新APP的固件大小
|
||||||
|
uint32_t new_app_crc32; // 新APP的CRC32校验和
|
||||||
|
} UpgradeInfo_t;
|
||||||
|
|
||||||
|
// 定义升级状态
|
||||||
|
#define UPGRADE_STATUS_NONE 0xFFFFFFFF
|
||||||
|
#define UPGRADE_STATUS_START 0xABCD1234
|
||||||
|
#define UPGRADE_STATUS_COMPLETE 0x5A5A5A5A
|
||||||
|
#define MAGIC_WORD 0xDEADBEEF
|
||||||
|
|
||||||
/* Exported functions ------------------------------------------------------- */
|
/* Exported functions ------------------------------------------------------- */
|
||||||
void Int2Str(uint8_t* str,int32_t intnum);
|
void Int2Str(uint8_t* str,int32_t intnum);
|
||||||
uint32_t Str2Int(uint8_t *inputstr,int32_t *intnum);
|
uint32_t Str2Int(uint8_t *inputstr,int32_t *intnum);
|
||||||
@@ -55,9 +69,7 @@ uint8_t GetKey(void);
|
|||||||
void USB_PutChar(uint8_t c);
|
void USB_PutChar(uint8_t c);
|
||||||
void USB_PutString(char *s);
|
void USB_PutString(char *s);
|
||||||
void GetInputString(uint8_t * buffP);
|
void GetInputString(uint8_t * buffP);
|
||||||
|
uint32_t Calculate_CRC32(uint32_t start_address, uint32_t size);
|
||||||
//????
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* __COMMON_H */
|
#endif /* __COMMON_H */
|
||||||
|
|
||||||
|
|||||||
@@ -48,21 +48,15 @@
|
|||||||
#define USER_FLASH_SIZE (USER_FLASH_END_ADDRESS - APPLICATION_ADDRESS + 1)
|
#define USER_FLASH_SIZE (USER_FLASH_END_ADDRESS - APPLICATION_ADDRESS + 1)
|
||||||
|
|
||||||
/* Define the address from where user application will be loaded.
|
/* Define the address from where user application will be loaded.
|
||||||
Note: the 1st sector 0x08000000-0x08003FFF is reserved for the IAP code */
|
Note: the 1st sector 0x08000000-0x0800FFFF is reserved for the IAP code */
|
||||||
#define APPLICATION_ADDRESS (uint32_t)0x0800C000
|
#define APPLICATION_ADDRESS ADDR_FLASH_SECTOR_4
|
||||||
|
|
||||||
|
/* Sector 3 (16KB) 被保留用作升级校验区 */
|
||||||
|
#define UPGRADE_INFO_SECTOR_ADDR ADDR_FLASH_SECTOR_3
|
||||||
|
#define UPGRADE_INFO_SECTOR_NUM FLASH_SECTOR_3
|
||||||
|
#define UPGRADE_INFO_ADDRESS UPGRADE_INFO_SECTOR_ADDR
|
||||||
|
|
||||||
/* Exported types ------------------------------------------------------------*/
|
/* Exported types ------------------------------------------------------------*/
|
||||||
|
|
||||||
#define UPGRADE_INFO_ADDRESS (USER_FLASH_END_ADDRESS - sizeof(UpgradeInfo_t) + 1)
|
|
||||||
// 定义升级信息结构体
|
|
||||||
typedef struct {
|
|
||||||
uint32_t magic_word; // 魔法字,如 0xDEADBEEF,用于标识此结构体有效
|
|
||||||
uint32_t upgrade_status; // 升级状态标志
|
|
||||||
uint32_t new_app_size; // 新APP的固件大小
|
|
||||||
uint32_t new_app_crc32; // 新APP的CRC32校验和
|
|
||||||
} UpgradeInfo_t;
|
|
||||||
|
|
||||||
|
|
||||||
/* Exported macro ------------------------------------------------------------*/
|
/* Exported macro ------------------------------------------------------------*/
|
||||||
/* Exported functions ------------------------------------------------------- */
|
/* Exported functions ------------------------------------------------------- */
|
||||||
void FLASH_If_Init(void);
|
void FLASH_If_Init(void);
|
||||||
|
|||||||
@@ -40,11 +40,6 @@
|
|||||||
/* Private typedef -----------------------------------------------------------*/
|
/* Private typedef -----------------------------------------------------------*/
|
||||||
/* Private define ------------------------------------------------------------*/
|
/* Private define ------------------------------------------------------------*/
|
||||||
|
|
||||||
// 定义升级状态
|
|
||||||
#define UPGRADE_STATUS_NONE 0xFFFFFFFF
|
|
||||||
#define UPGRADE_STATUS_START 0xABCD1234
|
|
||||||
#define UPGRADE_STATUS_COMPLETE 0x5A5A5A5A
|
|
||||||
|
|
||||||
/* Private macro -------------------------------------------------------------*/
|
/* Private macro -------------------------------------------------------------*/
|
||||||
/* Private variables ---------------------------------------------------------*/
|
/* Private variables ---------------------------------------------------------*/
|
||||||
pFunction Jump_To_Application;
|
pFunction Jump_To_Application;
|
||||||
@@ -68,11 +63,9 @@ void USB_Download(void);
|
|||||||
*/
|
*/
|
||||||
static void Write_Upgrade_Info(UpgradeInfo_t* info)
|
static void Write_Upgrade_Info(UpgradeInfo_t* info)
|
||||||
{
|
{
|
||||||
// 假设校验区在最后一个扇区 (Sector 7 for 512KB device)
|
// 1. 擦除专门用于校验的 Sector 3
|
||||||
// 注意:擦除会擦除整个扇区,如果扇区很大,需要先备份再写入
|
FLASH_If_Erase_One_Sector(UPGRADE_INFO_SECTOR_NUM);
|
||||||
// 为简化,我们直接擦除并写入
|
// 2. 写入升级信息
|
||||||
FLASH_If_Erase_One_Sector(7);
|
|
||||||
|
|
||||||
uint32_t flash_address = UPGRADE_INFO_ADDRESS;
|
uint32_t flash_address = UPGRADE_INFO_ADDRESS;
|
||||||
FLASH_If_Write((__IO uint32_t*)&flash_address, (uint32_t*)info, sizeof(UpgradeInfo_t) / 4);
|
FLASH_If_Write((__IO uint32_t*)&flash_address, (uint32_t*)info, sizeof(UpgradeInfo_t) / 4);
|
||||||
}
|
}
|
||||||
@@ -87,21 +80,16 @@ static void Read_Upgrade_Info(UpgradeInfo_t* info)
|
|||||||
memcpy(info, (void*)UPGRADE_INFO_ADDRESS, sizeof(UpgradeInfo_t));
|
memcpy(info, (void*)UPGRADE_INFO_ADDRESS, sizeof(UpgradeInfo_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// Int-to-Hex函数
|
||||||
* @brief Calculates the CRC32 of a given memory area.
|
static void Int2Hex(uint8_t* str, uint32_t intnum)
|
||||||
* @param start_address: Start address of the data
|
|
||||||
* @param size: Size of the data in bytes
|
|
||||||
* @retval Calculated CRC32 value
|
|
||||||
*/
|
|
||||||
static uint32_t Calculate_CRC32(uint32_t start_address, uint32_t size)
|
|
||||||
{
|
{
|
||||||
// 启用CRC外设时钟
|
const char hex_chars[] = "0123456789ABCDEF";
|
||||||
__HAL_RCC_CRC_CLK_ENABLE();
|
for (int i = 0; i < 8; i++)
|
||||||
CRC_HandleTypeDef CrcHandle;
|
{
|
||||||
CrcHandle.Instance = CRC;
|
str[7 - i] = hex_chars[intnum & 0x0F];
|
||||||
HAL_CRC_Init(&CrcHandle);
|
intnum >>= 4;
|
||||||
|
}
|
||||||
return HAL_CRC_Calculate(&CrcHandle, (uint32_t*)start_address, size / 4);
|
str[8] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -134,12 +122,11 @@ void USB_Download(void)
|
|||||||
|
|
||||||
USB_PutString("\n\n\r File reception complete. Verifying...\n\r");
|
USB_PutString("\n\n\r File reception complete. Verifying...\n\r");
|
||||||
// 4. 最终校验
|
// 4. 最终校验
|
||||||
// 理想情况下,这里应该有一个从上位机获取的CRC32值进行对比
|
// 理想情况下,这里应该有一个从上位机获取的CRC32值进行对比, 此处不对比
|
||||||
// 作为演示,我们只计算并保存
|
|
||||||
uint32_t calculated_crc = Calculate_CRC32(APPLICATION_ADDRESS, file_size);
|
uint32_t calculated_crc = Calculate_CRC32(APPLICATION_ADDRESS, file_size);
|
||||||
|
|
||||||
// 5. 写入校验信息到Flash末尾
|
// 5. 写入校验信息到Flash末尾
|
||||||
received_info.magic_word = 0xDEADBEEF;
|
received_info.magic_word = MAGIC_WORD;
|
||||||
received_info.upgrade_status = UPGRADE_STATUS_COMPLETE; // 标记为升级完成
|
received_info.upgrade_status = UPGRADE_STATUS_COMPLETE; // 标记为升级完成
|
||||||
received_info.new_app_size = file_size;
|
received_info.new_app_size = file_size;
|
||||||
received_info.new_app_crc32 = calculated_crc;
|
received_info.new_app_crc32 = calculated_crc;
|
||||||
@@ -152,14 +139,15 @@ void USB_Download(void)
|
|||||||
USB_PutString(Number);
|
USB_PutString(Number);
|
||||||
USB_PutString(" Bytes\r\n");
|
USB_PutString(" Bytes\r\n");
|
||||||
USB_PutString(" CRC32: 0x");
|
USB_PutString(" CRC32: 0x");
|
||||||
// 打印CRC值 (需要实现一个Int-to-Hex函数)
|
uint8_t calculated_crc_str[9];
|
||||||
|
Int2Hex(calculated_crc_str, calculated_crc);
|
||||||
|
USB_PutString(calculated_crc_str);
|
||||||
USB_PutString("\r\n-------------------\n");
|
USB_PutString("\r\n-------------------\n");
|
||||||
USB_PutString("Please reboot the device.\r\n");
|
USB_PutString("Please reboot the device.\r\n");
|
||||||
}
|
}
|
||||||
else /* An error occurred while writing to Flash memory */
|
else /* An error occurred while writing to Flash memory */
|
||||||
{
|
{
|
||||||
// 升级失败,清除标志区,强制下次进入Bootloader
|
FLASH_If_Erase_One_Sector(UPGRADE_INFO_SECTOR_NUM); // 擦除升级校验区,避免误跳转
|
||||||
FLASH_If_Erase_One_Sector(7); // 假设校验区在最后一个扇区
|
|
||||||
USB_PutString("\n\rUpgrade failed!\r\n");
|
USB_PutString("\n\rUpgrade failed!\r\n");
|
||||||
if (file_size == -1)
|
if (file_size == -1)
|
||||||
{
|
{
|
||||||
@@ -239,7 +227,11 @@ void Main_Menu(void)
|
|||||||
}
|
}
|
||||||
else if (key == 0x33) /* execute the new program */
|
else if (key == 0x33) /* execute the new program */
|
||||||
{
|
{
|
||||||
USBD_DeInit(&hUsbDeviceFS);
|
USB_PutString("Start to execute the user application...\r\n");
|
||||||
|
HAL_Delay(1000);
|
||||||
|
USER_USB_DEVICE_DeInit();
|
||||||
|
HAL_RCC_DeInit();
|
||||||
|
HAL_DeInit();
|
||||||
//user code here
|
//user code here
|
||||||
SysTick->CTRL = 0X00;//禁止SysTick
|
SysTick->CTRL = 0X00;//禁止SysTick
|
||||||
SysTick->LOAD = 0;
|
SysTick->LOAD = 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user