基于can接口的bootloader实现,当然要用的物理接口就是can接口和flash操作接口。
这部分在 MPC5744PRM 中写的很详细。
5744有2种启动模式:
这里我们主要看SC(single chip)模式,具体可以看56.4.5节。
在FLASH的一些sector,是boot location。芯片可以从这里启动。
复位后,PC指针不会再需要固定在一个固定的位置,比如stm32的0x8000000地址,mpc5744支持修改到不同的boot loaction。这个是在.ld文件中指定的。这个应该是cotex-m3内核和powerPC的区别。
究竟哪些地址可以作为启动分区?在flash map中有列出。
Small flash | ||
---|---|---|
0x00F98000~0x00F9BFFF | 16kb | boot location 0 |
0x00F9C000~0x00F9FFFF | 16kb | boot location 1 |
Medium flash | ||
0x00FA0000~0x00FAFFFF | 64kb | boot location 2 |
0x00FB0000~0x00FBFFFF | 64kb | boot location 3 |
Large flash | ||
0x01000000~0x0103FFFF | 256kb | boot location 4 |
0x01040000~0x0107FFFF | 256kb | boot location 5 |
0x01080000~0x010BFFFF | 256kb | boot location 6 |
0x010C0000~0x010FFFFF | 256kb | boot location 7 |
以上8个分区可以作为启动分区。
芯片内部有8个分区可以做为启动分区,那系统如何去寻找?如何知道从哪个分区启动?
芯片从低到高去找对应的boot location,以找到 boot ID为准。
每一个启动分区boot sector都在0偏移地址是RCHW(Reset Configuration Half-Word)。
RCHW的定义如下:
如果BOOT_ID有0x5A,则说明可以用这个分区启动。
VLE是标明代码格式是否是VLE的,不太懂,略过。
找到了系统启动分区,PC指针是如何移动的,RPM也给了介绍:
一旦设备找到启动分区,就会从偏移为4的地方取出地址数据,跳转过去。
我们的.ld文件声明如下:
MEMORY
{
flash_rchw : org = 0x00FA0000, len = 0x4
cpu0_reset_vec : org = 0x00FA0000+0x04, len = 0x4
m_text : org = FLASH_BASE_ADDR, len = FLASH_SIZE
m_data : org = SRAM_BASE_ADDR, len = SRAM_SIZE
local_dmem : org = LOCAL_DMEM_BASE_ADDR, len = LOCAL_DMEM_SIZE
}
单步调试过程中,去查看内存,可以看到:
整个bin是load到0x00FA0000地址的
可以看到偏移地址为0的地方是0x5A00,确实是启动分区。
偏移位置为4的地方是启动地址,0x01000000。
跳转看一下,确实代码数据在这里
和生成的二进制bin文件对比了一下,确实是一致的。
这一步操作和之前S32K144的操作是一致的(毕竟都是S32DS的开发环境)
BOOT
MEMORY
{
flash_rchw : org = 0x00F98000, len = 0x4
cpu0_reset_vec : org = 0x00F98000+0x04, len = 0x4
m_text : org = 0x00F99000, len = 92k
m_data : org = SRAM_BASE_ADDR, len = SRAM_SIZE
local_dmem : org = LOCAL_DMEM_BASE_ADDR, len = LOCAL_DMEM_SIZE
}
APP
MEMORY
{
flash_rchw : org = 0x01000000, len = 0x4
cpu0_reset_vec : org = 0x01000000+0x04, len = 0x4
m_text : org = 0x01000400, len = 2047K
m_data : org = SRAM_BASE_ADDR, len = SRAM_SIZE
local_dmem : org = LOCAL_DMEM_BASE_ADDR, len = LOCAL_DMEM_SIZE
}
在设计can升级的过程中,我并没有找到类似串口的Xmodeml,Ymodem,Zmodem这样成熟的协议,所以就自行设计了一种很简单的。
系统分成命令包,应答包,升级包等几种,利用第一个字节来划分。
将整个升级的bin包切分成若干个1k包,每个1k又切分成177帧can报文(每条报文有6字节的有效数据),加入每个1k包的应答重传等机制,1k包确认无误后写入flash。
全部完成后,做CRC校验,CRC校验通过,完成升级。
升级实现我是用状态机来做的,这部分看不同的代码习惯。
升级过程每个过程有明确的状态,根据收到不同的上位机报文来做事件触发状态迁移。
状态迁移有明确的交互报文来做确认。
static FsmTable_t g_MvIapFsmTable[] =
{
{FSM_NULL, EVENT_NULL, FSM_NULL, NULL},
{FSM_NULL, NO_REQ, FSM_NO_UPDATE, Jump2App},
{FSM_NULL, REC_DETECT_REQ, FSM_DETECT_ACK, HandleDetectReq},
{FSM_DETECT_ACK, REC_UPDATE_REQ, FSM_UPDATE_ACK, HandleUpdateReq},
{FSM_UPDATE_ACK, REC_UPDATE_REQ, FSM_UPDATE_ACK, HandleUpdateReq},
{FSM_UPDATE_ACK, REC_UPDATE_DATA, FSM_UPDATE, HandleUpdateData},
{FSM_UPDATE, REC_UPDATE_DATA, FSM_UPDATE, HandleUpdateData},
{FSM_UPDATE, REC_UPDATE_OVER, FSM_UPDATE_OVER, HandleUpdateOver},
};
无法实现跳转运行
使用开发板进行实际调试(调试器openSDA)过程中,在烧录boot时,烧录器会把App擦除,需要添加对应的保护,否则无法跳转。
跳转后Can无法正常运行。
之前怀疑是bootloader里用了can,没有关干净导致的,或者是app的中断不能正常。
但测了,都不是。
这部分还在查,有结果后我会更新上来
Mpc5744生成的bin太大了。
功能差不多的代码,MPC5744做出来的bin比st的我感觉要大出来3~4倍。不知道是不是优化选项的问题。
暂时还没找到解决方法。
MPC5744 官网 PRM
【5744】MPC5744入门笔记(1)开发环境搭建
【5744】MPC5744入门笔记(2)CAN实验
【5744】MPC5744入门笔记(3)Flash实验