可以帮忙调试,QQ:778292363
Bootloader是在ECU上电初始化时运行的一段代码,它通过can线接收来自上位机的命令,将数据写进ECU的指定Flash区段中。 本文件主要约束控制器(以下简称ECU)的Bootloader数据刷写流程。该项目中BT刷新流程采用UDS统一诊断服务来实现。
该项目需要将ECU待刷写的区域划分成逻辑块,并对每个块进行编号,每个块的大小和起始地址一经确定,后续不允许修改,需要供应商根据功能类别进行准确定位。本项目对ECU的块的个数有限制要求,根据待刷写程序的类别,要求擦除程序、引导程序、应用程序、应用数据各自只能有1个逻辑块。如果同种类型有多个块,请与陕汽刷写工程师联系确定最终状态。
待刷写的ECU内部不需要内置擦除程序,擦除程序的块号编号为0,每次刷写时都需要从数据管理平台上下载;引导程序的块编号为1,应用程序的块编号为2,应用数据的块编号为3。
块的使用体现34服务和31服务上,在34服务中表示即将传输的程序的块编号,31服务中表示需要对某个块进行编程完整性和兼容性检查。BT中使用的34服务的数据格式定义和UDS国际标准定义完全不一样,详细的定义见服务描述。
ECU供应商提供给OEM生产线或者售后服务处的应用程序与应用数据文件使用.bin格式。需要ECU供应商反馈bin文件的基本信息,
整个项目完整代码已经在前装车载设备上使用:
#include "main.h"
#include "bt_define.h"
uint8_t flash_driver_arr[FLASH_DRIVER_LENGTH] __attribute__((at(0x20007000))) = {0};
typedef void (*pFunction)(void);
pFunction Jump_To_Application;
uint32_t JumpAddress;
void Jump_To_App(uint32_t address)
{
/* Judge whether the top of stack address is legal or not */
if (((*(__IO uint32_t*)address) & 0x2FFE0000) == 0x20000000)
{
/* 屏蔽所有中断,防止在跳转过程中,中断干扰出现异常 */
__disable_irq();
/* Jump to user application */
JumpAddress = *(__IO uint32_t*) (address + 4);
Jump_To_Application = (pFunction) JumpAddress;
/* Initialize user application's Stack Pointer */
__set_MSP(*(__IO uint32_t*) address);
Jump_To_Application();
}
}
//#include "n32g43x_crc.h"
int main(void)
{
Systick_MS_Config(); //Setup SysTick Timer for 1 msec interrupts
tim6_7_init();
can0_init();
earse_flash_4_page();
uds_init();
if(flash_read(REQ_PROGRAM_UPDATE_FLAG_ADDR) == 0x1)
{
//如果ECU在正确的条件下收到“$10 $02”指令,ECU将重编程请求标志状态位设为有效,并执行ECU重启。
flash_write(REQ_PROGRAM_UPDATE_FLAG_ADDR, 0x0);
m_SecurityLevel = UDS_SA_NON;
uds_session = (uds_session_t)UDS_SESSION_PROG;
uds_timer_start (UDS_TIMER_S3server);
}
else
{
sys_delay_ms(15);
if(is_force_update == 0x1)
{
is_force_update = 0x0;
m_SecurityLevel = UDS_SA_NON;
uds_session = (uds_session_t)UDS_SESSION_PROG;
uds_timer_start (UDS_TIMER_S3server);
}
else
{
RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_CRC, ENABLE);
__IO uint32_t CRCValue = 0;
/* Compute the 32bit CRC of "DataBuffer" */
CRC32_ResetCrc();
CRCValue = CRC32_CalcBufCrc((uint32_t*)FLASH_APP1_ADDR, FLASH_APP1_CRC_LENGTH/0x4);
CRC32_ResetCrc();
if(CRCValue == (*(__IO uint32_t*)(FLASH_APP1_CRC_ADRR)) && 0x2 == (*(__IO uint32_t*)(FLASH_APP1_LOGIC_BLOCK_ADRR)))
{
flash_write(FLASH_APP1_VALID_ADRR, 0x1);
CRC32_ResetCrc();
CRCValue = CRC32_CalcBufCrc((uint32_t*)(FLASH_APP1_ADDR+0xC800), FLASH_APP1_CRC_LENGTH/0x4);
CRC32_ResetCrc();
if(CRCValue != (*(__IO uint32_t*)(FLASH_APP1_CRC_ADRR+0xC800)))
{
bt_flash_erase(FLASH_APP2_ADDR, FLASH_APP2_LENGTH);
bt_flash_write(FLASH_APP2_ADDR, (u8 *)FLASH_APP1_ADDR, FLASH_APP2_LENGTH);
}
}
else
{
flash_write(FLASH_APP1_VALID_ADRR, 0x0);
bt_flash_erase(FLASH_APP1_ADDR, FLASH_APP1_LENGTH);
bt_flash_write(FLASH_APP1_ADDR, (u8 *)FLASH_APP2_ADDR, FLASH_APP1_LENGTH);
/* Compute the 32bit CRC of "DataBuffer" */
CRC32_ResetCrc();
CRCValue = CRC32_CalcBufCrc((uint32_t*)FLASH_APP1_ADDR, FLASH_APP1_CRC_LENGTH/0x4);
CRC32_ResetCrc();
if(CRCValue == (*(__IO uint32_t*)(FLASH_APP1_CRC_ADRR)) && 0x2 == (*(__IO uint32_t*)(FLASH_APP1_LOGIC_BLOCK_ADRR)))
{
flash_write(FLASH_APP1_VALID_ADRR, 0x1);
}
else
{
flash_write(FLASH_APP1_VALID_ADRR, 0x0);
}
}
if(flash_read(FLASH_APP1_VALID_ADRR) == 0x1)
{
if(((*(vu32*)(FLASH_APP1_ADDR+4))&0xFF000000)==0x08000000)
{
Jump_To_App(FLASH_APP1_ADDR); //跳转到APP起始地址,期间不能被其他中断打断,否则会跳转失败
}
}
}
}
while(1)
{
// u8 send_buf[8] = {0x0};
// can_send_mess(0x222, send_buf, 8);
sys_delay_ms(1);
}
}