can控制器 Bootloader刷新流程,及其完整代码c写的(stm32 N32 系列MCU可用)
可以帮忙调试,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); } }
微信扫码关注
更新实时通知