s32k144 canbootloader工程包含三部分.
===================2.1canbootloader程序进行模式判断
程序首先在CANbootlloaer中运行,进行更新标志的读取.更新标志保存在eeprom(掉电不丢失)中预先设定的地址,每次开机到固定地址读取该标志位.若为APP_UPDATE_MODE则表示需要进行程序更新.否则直接跳转到app程序运行.
/*read the UpdateFlag*/
UpdateMode = (uint8_t)EEPROM_Read(UPDATA_FLAG_EEPROM_ADDR);
/*update app*/
if((UpdateMode == APP_UPDATE_MODE) || (UpdateMode == 0xFF)) //若为0xFF,则为首次写入,此时还没有下载任何app,进入update_mode
{ //若为0xab,则进入到update_mode
EEPROM_Write(UPDATA_FLAG_EEPROM_ADDR, 0x00); //防止下次CPU重启进入到下载状态
IAP_UpdateApp(); //更新程序
}
/*directive jump to app*/
else
{
#ifdef DE_BUG
UART_TransmitString("jump!\n");
#endif
IAP_JumpApp(FLASH_APP_ADDR);//跳转到app
}
=================2.2 若为APP_UPDATE_MODE,则进行程序更新
通过CAN中断接收CAN上位机发送的app.bin文件,当可执行文件发送完成后,跳转到app程序中运行.
while(1)
{
/*接收数据*/
if(CanRevCount)
{
if(OldCount == CanRevCount)//是否还有新的数据被接收
{
DelayMs(200); //延迟等待,判断是否结束传输.
if(OldCount == CanRevCount)
{
AppLenth = CanRevCount*4; //32bit/8bit = 4,文件传输完成,保存文件size.
OldCount = 0;
CanRevCount = 0;
}
else
{
OldCount = CanRevCount; //更新接收数据计数
}
}
else
{
OldCount = CanRevCount; //更新接收数据计数
}
}
/*接收结束*/
if(AppLenth > 0)
{
#ifdef DE_BUG
UART_TransmitChar(GET_BIT_0_7(AppLenth));//打印size
UART_TransmitChar(GET_BIT_8_15(AppLenth));
#endif
IAP_WriteFLash(FLASH_APP_ADDR, (uint8_t *)CanBuf, AppLenth);//将app写入到flash中.
UART_TransmitString("download!\n");
IAP_JumpApp(FLASH_APP_ADDR);//跳转到app.
}
}
================ 2.3 从CANbootloaer跳转到app程序.
1.在IAP_JumpApp(uint32_t AppAddr)调用时,传入FLASH_APP_ADDR .FLASH_APP_ADDR 处存放SP指针,FLASH_APP_ADDR +4即为app程序的中断向量表在flash中的起始地址.
2.赋值函数指针JumpToApp
3.通过函数指针方式调用函数.
#define FLASH_APP_ADDR 0x00004000为预先设定的app程序的起始FLASH地址.
typedef void (*IapFun)(void);
IapFun JumpToApp; //函数指针
void IAP_JumpApp(uint32_t AppAddr)
{
/*获取app.bin的reset handle中断向量.*/
JumpToApp = (IapFun)(*(uint32_t *)(AppAddr + 4));/*强制转化为函数指针.*/
JumpToApp(); /*通过函数指针间接访问函数,运行函数reset_handle*/
}
=================2.4 app程序运行
app程序在bootloader阶段,即start.S中对中断向量表进行偏移设置(在本工程中,映射到RAM中).
在CAN中断中监听程序更新指令,0x111111110x11111111,若接收到8字节0x11,则进入到app程序更新模式.设置APP_UPDATE_MODE标志位,并延迟10ms(等待eeprom写入完成)后,软件重启s32k144.则跳转到2.1节进行app程序更新.
if(RxDATA[0] == 0x11111111 && RxDATA[1] == 0x11111111)
{
/*set and save flag*/
UpdateFlag1 = 0xab;
EEPROM_Write(UPDATA_FLAG_EEPROM_ADDR, UpdateFlag1);
DelayMs(10); //wait 10ms for eeprom to save UpdateFlag
/*software reset CPU*/
S32_SCB->AIRCR = S32_SCB_AIRCR_VECTKEY(0x05FA) | S32_SCB_AIRCR_SYSRESETREQ_MASK;
for(;;); /* wait until reset */
}
=========================3.1 app程序进行中断向量表的偏移设置.
本工程中使用S32DS IDE,并将中断向量表的偏移地址设置RAM的起始地址处.在链接器脚本中指定中断向量表偏移设置标志位,并在startup.c中将flash中的中断向量表复制到RAM中.实际上中断向量表的偏移即设置中断向量表偏移量寄存器 SCB_VICTOR的VTOR位段(在S32DS IDE中,如果__VECTOR_RAM__标识符被设置,则IDE应该会自行设置该寄存器).
__VECTOR_RAM = DEFINED(__flash_vector_table__) ? ORIGIN(m_interrupts) : __VECTOR_RAM__ ;
/*复制中断向量表 flash-->RAM*/
/* Check if VECTOR_TABLE copy is needed */
if (__VECTOR_RAM != __VECTOR_TABLE)
{
/* Copy the vector table from ROM to RAM */
for (n = 0; n < (((uint32_t)__RAM_VECTOR_TABLE_SIZE)/sizeof(uint32_t)); n++)
{
__VECTOR_RAM[n] = __VECTOR_TABLE[n];
}
/* Point the VTOR to the position of vector table */
INT_VECTOR_Reg = (uint32_t)__VECTOR_RAM;
}
===========================3.2 修改链接器脚本,划分CANbootloaer和APP工程的falsh存储.
需要为bootloader和app工程明确划分flash.一般将bootloader存放在低地址,app存放在高地址flash.在两个链接工程的链接器脚本中指定划分规则.
/*CANbootloader*/
/* Specify the memory areas */
MEMORY
{
/* Flash */
m_interrupts (RX) : ORIGIN = 0x00000000, LENGTH = 0x00000400
m_flash_config (RX) : ORIGIN = 0x00000400, LENGTH = 0x00000010
m_text (RX) : ORIGIN = 0x00000410, LENGTH = 0x0007FBF0
/* SRAM_L */
m_data (RW) : ORIGIN = 0x1FFF8000, LENGTH = 0x00008000
/* SRAM_U */
m_data_2 (RW) : ORIGIN = 0x20000000, LENGTH = 0x00007000
}
/*app */
/* Specify the memory areas */
MEMORY
{
/* Flash */
m_interrupts (RX) : ORIGIN = 0x00004000, LENGTH = 0x00000400
m_flash_config (RX) : ORIGIN = 0x00004400, LENGTH = 0x00000010
m_text (RX) : ORIGIN = 0x00004410, LENGTH = 0x0007BBF0
/*
m_interrupts (RX) : ORIGIN = 0x00000000, LENGTH = 0x00000400
m_flash_config (RX) : ORIGIN = 0x0000400, LENGTH = 0x00000010
m_text (RX) : ORIGIN = 0x0000410, LENGTH = 0x0007BBF0
*/
/* SRAM_L */
m_data (RW) : ORIGIN = 0x1FFF8000, LENGTH = 0x00008000
/* SRAM_U */
m_data_2 (RW) : ORIGIN = 0x20000000, LENGTH = 0x00007000
}
上位机由队友负责.使用VB编写,对原有上位机进行了功能扩展,支持二进制文件烧录.在此放上界面.