Files
RS485_T1_Transition/Source/SYSTEM/Bootload_fun.c
yeyangwen 13980737e3 feat:修改设备类型
feat:修改为红外转发设备,将中弘网关协议转换为主机红外协议
2026-02-09 17:32:59 +08:00

501 lines
14 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
******************************************************************************
* @file Bootload.c
* @author caocong
* @version V1.00
* @date 2025/04/03
* @Description
* MCU空间规划
* Boot 0x0000 ~ 0x27FF 10K
* APP 0x2800 ~ 0xFEFF 53.8K
* APP_FEATURE 0xFF00 ~ 0xFFFF 256Byte
* EEPROM空间规划
* APP设备信息 0x10000000 - Size:0x40 - 64Byte
*
*/
#include "includes.h"
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
BOOT_INFO_T g_boot;
APP_FEATURE_INFO_T g_app_feature;
void Boot_Function_Init(void)
{
U8_T app_ready = 0;
U16_T sys_reset_sta = 0;
memset(&g_boot,0,sizeof(BOOT_INFO_T));
memset(&g_app_feature,0,sizeof(APP_FEATURE_INFO_T));
g_boot.ackValidity = 1000; //数据默认有效期为1000ms
EEPROM_Init();
/*读取APP 特征区*/
// app_ready = Check_APP_Feature();
//#if DBG_LOG_EN
// if(app_ready == 0x00)
// {
// Dbg_Println(DBG_BIT_SYS_STATUS,"APP Feature SUCC");
// Dbg_Println(DBG_BIT_SYS_STATUS,"APP app_flag:%d",g_app_feature.app_flag);
// Dbg_Println(DBG_BIT_SYS_STATUS,"APP app_start_addr:%08x",g_app_feature.app_start_addr);
// Dbg_Println(DBG_BIT_SYS_STATUS,"APP app_end_addr:%08x",g_app_feature.app_end_addr);
// Dbg_Println(DBG_BIT_SYS_STATUS,"APP app_crc_size:%d",g_app_feature.app_crc_size);
// Dbg_Println(DBG_BIT_SYS_STATUS,"APP app_crc_len:%d",g_app_feature.app_crc_len);
// Dbg_Print_Buff(DBG_BIT_SYS_STATUS,"APP app_crc:",g_app_feature.app_crc,g_app_feature.app_crc_len);
//
// }else {
// Dbg_Println(DBG_BIT_SYS_STATUS,"APP Feature Fail!");
//
// }
//#endif
sys_reset_sta = SYSCON->UREG3;
if(sys_reset_sta == 0x100) //软件复位 -- 升级开始复位源
{
g_boot.bootTimeout = 5000;
#if DBG_LOG_EN
Dbg_Println(DBG_BIT_SYS_STATUS," Boot software reset");
#endif
}else if(sys_reset_sta == 0x01) //上电复位RPOR
{
g_boot.bootTimeout = 500;
#if DBG_LOG_EN
Dbg_Println(DBG_BIT_SYS_STATUS,"Boot power on reset");
#endif
}else if(sys_reset_sta == 0x04) //外部手动复位
{
g_boot.bootTimeout = 2000;
#if DBG_LOG_EN
Dbg_Println(DBG_BIT_SYS_STATUS,"Boot ex-pin reset");
#endif
}else if(sys_reset_sta == 0x10) //看门狗超时复位 --升级完成复位源
{
g_boot.bootTimeout = 2000;
#if DBG_LOG_EN
Dbg_Println(DBG_BIT_SYS_STATUS,"Boot wdt reset");
#endif
}else if(sys_reset_sta == 0x40) //外部时钟无效复位
{
g_boot.bootTimeout = 2000;
#if DBG_LOG_EN
Dbg_Println(DBG_BIT_SYS_STATUS,"Boot ex clock invalid reset");
#endif
}else if(sys_reset_sta == 0x80) //CPU请求复位 - link调试复位
{
g_boot.bootTimeout = 2000;
#if DBG_LOG_EN
Dbg_Println(DBG_BIT_SYS_STATUS,"Boot cpu request reset");
#endif
}else
{
g_boot.bootTimeout = 2000;
#if DBG_LOG_EN
Dbg_Println(DBG_BIT_SYS_STATUS,"Boot other reset 0x%x",sys_reset_sta);
#endif
}
}
U8_T Boot_Comm_CheckSum(U8_T * buffer, U16_T len)
{
U8_T sum = 0;
U16_T i=0;
while(len--)
{
sum += buffer[i];
i++;
}
return (~sum);
}
U16_T NetCRC16(U8_T * aStr, U16_T len)
{
U16_T xda , xdapoly ;
U16_T i, j, xdabit ;
xda = 0xFFFF ;
xdapoly = 0xA001 ; // (X**16 + X**15 + X**2 + 1)
for (i = 0; i < len; i++)
{
xda ^= aStr[i] ;
for (j = 0; j < 8; j++)
{
xdabit = (unsigned char)(xda & 0x01) ;
xda >>= 1 ;
if ( xdabit ) xda ^= xdapoly ;
}
}
return xda;
}
void Boot_Comm_FillReplyPack(BOOT_INFO_T *ack_uart)
{
U16_T data_len = ack_uart->ackLen + BCOMM_FMT_PARAM;
ack_uart->ackBuffer[BCOMM_FMT_TXAddr] = g_mcu_dev.dev_addr;
ack_uart->ackBuffer[BCOMM_FMT_SN] = ack_uart->sn;
ack_uart->ackBuffer[BCOMM_FMT_TYPE] = g_mcu_dev.dev_type;
ack_uart->ackBuffer[BCOMM_FMT_RXAddr] = g_boot.pc_addr;
ack_uart->ackBuffer[BCOMM_FMT_CMD] = ack_uart->cmd;
ack_uart->ackBuffer[BCOMM_FMT_LEN_L] = data_len & 0xFF;
ack_uart->ackBuffer[BCOMM_FMT_LEN_H] = (data_len >> 8) & 0xFF;
ack_uart->ackBuffer[BCOMM_FMT_CKS] = 0;
ack_uart->ackBuffer[BCOMM_FMT_CKS] = Boot_Comm_CheckSum(ack_uart->ackBuffer, data_len);
#if DBG_LOG_EN
Dbg_Print_Buff(DBG_BIT_SYS_STATUS,"ACKBuff ",ack_uart->ackBuffer,data_len);
#endif
//MCU485_SendData(ack_uart->ackBuffer, data_len);
Set_GroupSend(ack_uart->ackBuffer,data_len,0x01,ack_uart->ackValidity,100);
//ack_uart->ackLen = 0x00;
}
/*******************************************************************************
* Function Name : APP_Flash_AllEase
* Description : 擦除APP Flash空间
*******************************************************************************/
void APP_Flash_AllEase(void)
{
for(U32_T index = APP_Flash_StartAddr; index < APP_Flash_EndAddr;index+=APP_Flash_PageSize){
SYSCON_IWDCNT_Reload();
PageErase(index);
}
}
/*******************************************************************************
* Function Name : MCU_EEPROM_AllEase
* Description : 擦除EEPROM 空间
*******************************************************************************/
void MCU_EEPROM_AllEase(void)
{
for(U32_T index = MCU_EEPROM_StartAddr; index < MCU_EEPROM_EndAddr;index+=MCU_EEPROM_PageSize){
SYSCON_IWDCNT_Reload();
PageErase(index);
}
}
/*******************************************************************************
* Function Name : APP_FEATURE_Flash_Ease
* Description : 擦除APP特征区 Flash空间
*******************************************************************************/
void APP_FEATURE_Flash_Ease(void)
{
PageErase(APP_FEATURE_Flash_Addr);
}
/*******************************************************************************
* Function Name : Boot_Comm_UpgradeProcess
* Description : Boot通讯数据处理函数
*******************************************************************************/
U8_T Boot_Comm_UpgradeProcess(U8_T *data,U16_T len)
{
U8_T deal_flag = 0,group_flag = 0,reply_flag = 0,setinfo_flag = 0,crcResultFlag = 0;
U16_T data_len = 0,crcNumIndex = 0;
U32_T temp_data = 0,temp_data_2 = 0;
data_len = data[BCOMM_FMT_LEN_H];
data_len <<= 8;
data_len |= data[BCOMM_FMT_LEN_L];
if(len != data_len) {
#if DBG_LOG_EN
Dbg_Println(DBG_BIT_SYS_STATUS,"Len Fail ");
#endif
return 0x01;
}
if(Boot_Comm_CheckSum(data,len) != 0) {
#if DBG_LOG_EN
Dbg_Println(DBG_BIT_SYS_STATUS,"Boot_Comm_CheckSum Fail ");
#endif
return 0x02;
}
if( (data[BCOMM_FMT_SN] & 0x80) == 0x80){
//群发标志位
group_flag = 0x01;
if( (data[BCOMM_FMT_SN] & 0x0F) != g_boot.sn){
deal_flag = 0x01;
#if DBG_LOG_EN
Dbg_Println(DBG_BIT_SYS_STATUS,"Group Data SN Disaffinity,Processing Data");
#endif
}else {
deal_flag = 0x00;
#if DBG_LOG_EN
Dbg_Println(DBG_BIT_SYS_STATUS,"Group Data SN The Same,No Processing Data");
#endif
}
}else {
//单发标志位
group_flag = 0x00;
if( (data[BCOMM_FMT_SN] & 0x0F) != g_boot.sn){
//包序号不太相同,需要处理
#if DBG_LOG_EN
Dbg_Println(DBG_BIT_SYS_STATUS,"Single Data SN Disaffinity,Processing Data");
#endif
deal_flag = 0x01;
reply_flag = 0x01;
}else if( (data[BCOMM_FMT_SN] & 0x40) == 0x40 ){
//包序号相同,重发标志位置位,不处理,但是需要回复数据,回复上次的数据内容
deal_flag = 0x00;
/*重发数据包命令与上一次的命令相同的话,直接回复上一次的数据内容*/
if(data[BCOMM_FMT_CMD] == g_boot.ackBuffer[BCOMM_FMT_CMD] ){
reply_flag = 0x01;
}
#if DBG_LOG_EN
Dbg_Println(DBG_BIT_SYS_STATUS,"Single Data SN The Same,No Processing Data");
#endif
}
}
/*判断类型是否相同,且不是广播类型*/
if( (data[BCOMM_FMT_TYPE] != g_mcu_dev.dev_type) && (data[BCOMM_FMT_TYPE] != 0xFF) ){
#if DBG_LOG_EN
Dbg_Println(DBG_BIT_SYS_STATUS,"Boot_Comm_RecvType %d - %d ",g_mcu_dev.dev_type,data[BCOMM_FMT_TYPE]);
#endif
return 0x03;
}
/*判断是否广播类型与广播地址*/
if( (data[BCOMM_FMT_RXAddr] != g_mcu_dev.dev_addr) && (data[BCOMM_FMT_RXAddr] != 0xFF) ){
#if DBG_LOG_EN
Dbg_Println(DBG_BIT_SYS_STATUS,"Boot_Comm_RecvAddr %d - %d ",g_mcu_dev.dev_addr,data[BCOMM_FMT_RXAddr]);
#endif
return 0x04;
}
Boot_Time_Refresh();
g_boot.pc_addr = data[BCOMM_FMT_TXAddr];
g_boot.sn = data[BCOMM_FMT_SN] & 0x0F;
g_boot.cmd = data[BCOMM_FMT_CMD];
switch(g_boot.cmd){
case BCOMM_CMD_Handshake: //握手命令
if( (deal_flag == 0x01) && (data_len >= (BCOMM_FMT_PARAM + 4) ) ){
#if DBG_LOG_EN
Dbg_Println(DBG_BIT_SYS_STATUS,"BCOMM_CMD_Handshake Proecessing ");
#endif
/*设置Boot 超时时间*/
temp_data = data[BCOMM_FMT_PARAM + 1];
temp_data <<= 8;
temp_data |= data[BCOMM_FMT_PARAM];
if(temp_data != g_boot.bootTimeout){
g_boot.bootTimeout = temp_data;
if(g_boot.bootTimeout < 10) g_boot.bootTimeout = 10;
g_boot.bootTimeout = g_boot.bootTimeout * 1000;
}
/*回复数据的有效期*/
temp_data = data[BCOMM_FMT_PARAM + 3];
temp_data <<= 8;
temp_data |= data[BCOMM_FMT_PARAM + 2];
g_boot.ackValidity = temp_data;
}
//握手命令 - 需要回复的数据,正常回复
if(reply_flag != 0x01) break; //不回复,直接退出
g_boot.ackBuffer[BCOMM_FMT_PARAM] = Project_Area; //当前处于Bootload区域 0x01Boot;0x02APP
g_boot.ackBuffer[BCOMM_FMT_PARAM + 1] = g_mcu_dev.dev_boot_ver; //Boot 软件版本号
g_boot.ackBuffer[BCOMM_FMT_PARAM + 2] = g_mcu_dev.dev_app_ver; //APP 软件版本号
//MCU UID
g_boot.ackBuffer[BCOMM_FMT_PARAM + 3] = 0x03; //UUID 长度 MD203 UID 3Byte
g_boot.ackBuffer[BCOMM_FMT_PARAM + 4] = SYSCON->UID0;
g_boot.ackBuffer[BCOMM_FMT_PARAM + 5] = SYSCON->UID1;
g_boot.ackBuffer[BCOMM_FMT_PARAM + 6] = SYSCON->UID2;
//机型编号 - 32Byte 最长32Byte
if(g_mcu_dev.dev_name_len > EEPROM_DEV_NAME_Size) g_mcu_dev.dev_name_len = EEPROM_DEV_NAME_Size;
g_boot.ackBuffer[BCOMM_FMT_PARAM + 7] = g_mcu_dev.dev_name_len;
for(U8_T i=0;i<EEPROM_DEV_NAME_Size;i++){
g_boot.ackBuffer[BCOMM_FMT_PARAM + i + 8] = g_mcu_dev.dev_name[i];
}
g_boot.ackLen = 0x08 + EEPROM_DEV_NAME_Size;
break;
case BCOMM_CMD_Jump: //跳转命令 //boot
if(deal_flag != 0x01) break; //不处理直接退出
#if DBG_LOG_EN
Dbg_Println(DBG_BIT_SYS_STATUS,"BCOMM_CMD_Jump Proecessing ");
#endif
if(data[BCOMM_FMT_PARAM] == 0x01){
/*跳转至APP区域*/
BUS485_Jump_Boot(0x01);
g_boot.ackBuffer[BCOMM_FMT_PARAM] = BCOMM_CMD_ReplySUCC;
}else {
/*参数错误*/
#if DBG_LOG_EN
Dbg_Println(DBG_BIT_SYS_STATUS,"ERR:Jump_boot");
#endif
g_boot.ackBuffer[BCOMM_FMT_PARAM] = BCOMM_CMD_ReplyFAIL;
}
g_boot.ackLen = 1;
break;
default: //未知命令
g_boot.ackBuffer[BCOMM_FMT_PARAM] = BCOMM_CMD_ReplyFAIL;
g_boot.ackLen = 1;
break;
}
/*回复通讯数据*/
if( (group_flag == 0x00) && (reply_flag == 0x01) )
{
Boot_Comm_FillReplyPack(&g_boot);
}
}
void Boot_Time_Refresh(void)
{
g_boot.bootTick = SysTick_1ms;
}
void Boot_TimeOut_Task(void)
{
if(SysTick_1ms - g_boot.bootTick >= g_boot.bootTimeout)
{
while(1); //执行看门狗复位
}
}
void Jump_To_APP(void)
{
volatile U32_T EIPaddr = g_app_feature.app_start_addr + 0x010C;
asm("mov r0,%0\n"::"r"(EIPaddr):); // APP入口地址 __start label的值
asm(" jmp r0 ");
}
U8_T Check_APP_Feature(void)
{
U8_T temp_buff[530];
U16_T crcNumIndex = 0,temp_data = 0,temp_data_2 = 0;
U32_T crc_data_len = 0,crc_feature_len = 0;
/*读取APP 特征区*/
ReadDataArry_U8(APP_FEATURE_Flash_Addr,sizeof(APP_FEATURE_INFO_T),temp_buff);
#if DBG_LOG_EN
Dbg_Println(DBG_BIT_SYS_STATUS,"App Feature Size:%d",sizeof(APP_FEATURE_INFO_T));
Dbg_Print_Buff(DBG_BIT_SYS_STATUS,"App Feature Buff:",temp_buff,sizeof(APP_FEATURE_INFO_T));
#endif
crc_data_len = temp_buff[1];
crc_data_len <<= 8;
crc_data_len |= temp_buff[0];
temp_buff[0] = 0x00;
temp_buff[1] = 0x00;
if( NetCRC16((U8_T *)temp_buff,sizeof(APP_FEATURE_INFO_T)) != crc_data_len )
{
#if DBG_LOG_EN
Dbg_Println(DBG_BIT_SYS_STATUS,"App Feature CRC ERROR");
#endif
return 0x01;
}
memcpy(&g_app_feature,temp_buff,sizeof(APP_FEATURE_INFO_T));
g_app_feature.crcL_check = crc_data_len & 0xFF;
g_app_feature.crcH_check = (crc_data_len >> 8) & 0xFF;
if(g_app_feature.app_flag != App_Procedure_Ready)
{
#if DBG_LOG_EN
Dbg_Println(DBG_BIT_SYS_STATUS,"App Feature Flag ERROR");
#endif
return 0x02; //没有APP标志位
}
if( (g_app_feature.app_start_addr >= APP_Flash_StartAddr)
&& (g_app_feature.app_end_addr < APP_Flash_EndAddr)
&& (g_app_feature.app_end_addr > g_app_feature.app_start_addr)
&& (g_app_feature.app_crc_size == 512) )
{
crc_data_len = g_app_feature.app_end_addr - g_app_feature.app_start_addr;
#if DBG_LOG_EN
Dbg_Println(DBG_BIT_SYS_STATUS,"App Len :%d ",crc_data_len);
#endif
if( (crc_data_len % g_app_feature.app_crc_size ) != 0x00 ){
crc_feature_len = ((crc_data_len / g_app_feature.app_crc_size) + 1) * 2;
}else {
crc_feature_len = (crc_data_len / g_app_feature.app_crc_size) * 2;
}
if(g_app_feature.app_crc_len != crc_feature_len) {
#if DBG_LOG_EN
Dbg_Println(DBG_BIT_SYS_STATUS,"App CRC Len :%d - %d",crc_feature_len,g_app_feature.app_crc_len);
#endif
return 0x03; //APP CRC长度不对
}
for(U32_T crc_addr = g_app_feature.app_start_addr; crc_addr < g_app_feature.app_end_addr;crc_addr += g_app_feature.app_crc_size)
{
SYSCON_IWDCNT_Reload();
if( g_app_feature.app_end_addr - crc_addr >= g_app_feature.app_crc_size) {
crc_data_len = g_app_feature.app_crc_size;
}else {
crc_data_len = g_app_feature.app_end_addr - crc_addr;
}
ReadDataArry_U8(crc_addr,crc_data_len,temp_buff);
temp_data = NetCRC16(temp_buff,crc_data_len);
temp_data_2 = g_app_feature.app_crc[crcNumIndex + 1];
temp_data_2 <<= 8;
temp_data_2 |= g_app_feature.app_crc[crcNumIndex];
#if DBG_LOG_EN
Dbg_Println(DBG_BIT_SYS_STATUS,"App CRC ADDR:%08x %04x-%04x",crc_addr,temp_data,temp_data_2);
#endif
if(temp_data != temp_data_2){
/*校验失败 - */
#if DBG_LOG_EN
Dbg_Println(DBG_BIT_SYS_STATUS,"App CRC Fail ADDR:%08X %04X-%04X",crc_addr,temp_data,temp_data_2);
#endif
return 0x04; //校验失败
}
crcNumIndex += 2;
}
}else {
#if DBG_LOG_EN
Dbg_Println(DBG_BIT_SYS_STATUS,"App Feature StartAddr ERROR");
Dbg_Println(DBG_BIT_SYS_STATUS,"APP app_start_addr:%08x",g_app_feature.app_start_addr);
Dbg_Println(DBG_BIT_SYS_STATUS,"APP app_end_addr:%08x",g_app_feature.app_end_addr);
Dbg_Println(DBG_BIT_SYS_STATUS,"APP app_crc_len:%d",g_app_feature.app_crc_len);
#endif
return 0x05; //起始地址不正确
}
return 0x00;
}