这几天在研究KE02做BootLoader,目前有点心得,想跟大家分享一下。当然,只是下位机部分。
程序的思路比较简单:
1. 程序存储:用串口接收到数据,然后写到Flash中去,写完后跳到应用程序中运行。
2. 操作标志:BootFlag,上电的时候先判断BootFlag的状态两种结果
a. 如果BootFlag是操作过的状态(即里面有完整的应用程序),那么启动定时器,开始计时,2秒内如果没有接收到串口的数据,那么就跳到应用程序去运行。
b. 如果BootFlag是未被操作的状态(即应用程序不完整),那么,不启动定时器,一直在Boot中运行。
c. 当接到擦除命令的时候,将BootFlag擦除,处于Flash未操作状态。
d. 当接到结束命令的时候,将BootFlag置起,处于Flash已操作状态。
通讯协议:
我个人比较懒,也懒得去研究ModernBus之类的协议,就看着HEX的文件格式就是不错的协议,所以就直接拿来用了,而且HEX文件都是ASCII字符,在数据传输过程中不容易出错,它的格式如下:
:LLAAAATTDDVV
: 每一行的头
LL 数据域的长度
AAAA 地址域
TT 类型域
DD 数据域
VV 校验域
结尾
以上要重点说明的是类型域,HEX的类型域一般有以下几种:
00 表示数据记录
01 文件结束记录
02 扩展段地址记录
04 扩展线性地址记录
05 开始线性地址记录
也就是说当类型域为00的时候,表示此段数据需要按照地址域的地址写到Flash中去。01的时候表示文件结束了,也就是说已经发送完了,可以跳到应用程序去了。然后还有一个需要注意的是04,它是扩展地址,可以理解成高16位地址。
按照上面的格式应该就可以进行通讯烧录,但是考虑到BootFlag操作,所以我添加了一个06,为擦除命令。即是说在烧录前可以将所有应用程序空间擦除一次,包括BootFlag,也被擦掉。
按照上面的描述,我的协议也有了。
BootFlag:
刚才我们说需要做一个BootFlag,但是BootFlag所处的位置让我大伤脑筋,如果放在Boot区的Flash中,那么,我在擦除与置位的时候有太多的麻烦,所以只能放在应用程序区。经过综合考虑,最终,我决定将BootFlag放在Flash最后一段的最后几个字节。在擦除Flash的时候,我从最后面一个段开始往前面擦除,这样的话就最先擦掉BootFlag。而在Flash编程的时候,根据HEX文件的特性,会是从前往后编程,等编程完后,再把BootFlag置位。这样就避免了在任何时候断电重启时,内部残余的应用程序可能会启动的情况。
应用程序:
在考虑BootLoader程序的时候,考虑最多的是中断向量的问题。因为BootLoader跟Applaction程序不可能公用中断向量。一开始想的是要实在不行的话,在RAM中做一个函数指针数组,然后将中断向量指向这个数组,然后在BootLoader与Applaction程序启动的时候都可以将中断句柄初始化到数组中,可以完成中断向量相同,但中断函数不同。但这样的做法很麻烦,面对目前飞思卡尔提供的例程架构,要改的东西太多。后来发现其实ARM的NVMI寄存器中有中断向量重影射的寄存器,这下解决大问题了,只要在应用程序启动的时候将中断向量直接写入此寄存器就可以了:
SCB_VTOR = (uint32_t)(&__vect_table);
做应用程序的时候要注意的两点:
1、 就是刚才说的中断向量表的重影射。
2、 应用程序起始地址。其实说完了就是分散加载的问题,我用的是KEIL,分散加载文件是用PE生成的,然后拿来做修改就可以了。
现在所有的问题基本思路都清楚了,可以开干了!我用KE02提供的程序库,开始做,当我将程序做完之后,我发现妈呀,将近15K呀,这怎么行啊,优化,一定要优化。当然将KEIL中的优化级别设为最高,还是不行啊,10K多呀,这太郁闷了,我用的芯片是KE02Z64VQH2,只有64KFlash,我不能有10K多的Boot呀。后来打开MAP文件一看,里面有好多没有用到的函数啊,晕,没用到,但他也占空间啊,删吧,于是把不用的函数全给屏了,这回好多了,只有2.5K了,2.5K也大,再想办法,从MAP文件中看到有哪个函数占用空间大了,进行优化,能省一点是一点,在我的不断努力下,终于,小于2K了,成功!
源码如下:
KE02BootLoader.zip
(2.32 MB, 下载次数: 75)
2014-5-5 17:30 上传
点击文件名下载附件
是的
但是串口传的数据不是很容易出现误码,这个有没得校验?
原来如此,感谢讲解。
一周热门 更多>