写完这个就准备收手,接着开始看linux了,毕竟,哎!不说了,直接进正题吧!
IAP即在应用编程。是用户为程序在运行过程中对芯片flash的部分区域进行烧写,实现产品在发布后可以很方便地通过预留的通信接口对产品中的固件程序进行更新升级。通常实现IAP功能时,芯片需要在程序设计时编写两个项目代码,一个程序不执行正常的功能操作,而只是通过某种通信方式接受新程序,并在接收完数据后执行对新程序的更新,第二个代码才是真正的功能代码。这两部分项目代码都同时烧录在用户flash中,芯片上电后首先执行第一个程序,这段程序类似于windows中的BIOS引导,在刚上电时执行某些操作进而指向新固件数据接收操作,接收完数据后程序自动跳转到新固件的地址。我们一般把第一个程序称为Bootloader或IAP程序,第二个程序称为APP,这两段程序都存在MCU的flash中的不同地址中,默认情况下是IAP程序在flash 的起始处,APP程序自己根据程序APP程序大小来确定,同时如果MCU的flash足够大也可以设计多个APP在不同的flash地址段。
了解了上面的定义,接下来我们来看看LPC1788的ROM和SRAM分布
我所用的LPC1788 是512kB flash、96kB SRAM,所以容量很足嘛,再来看看flash的扇区划分:
可以看出前16个扇区每个扇区4kB,后14个扇区每个扇区32kB,每个扇区很大嘛,可以写好多APP了。还有一点非常有意思,1788并没有寄存器来让我们操作flash,它内置了iap的flash算法:
我们可以通过开放的命令来操作flash:
具体的命令介绍,自己看数据手册的flashmemory。 再来看看我们MCU刚上电时的程序运行情况,这里不想在画图了,就借助stm32的流程图来说一下,这个是程序正常启动的流程:
我们上面也说过1788的flash起始地址是0x00000000,一般情况下,程序文件就从此地址开始写入执行,再来对比一下我们程序的启动文件:
这是中断向量表,和正常的程序启动刚好对的上。再来看一下加入IAP程序之后的程序流程:
我们默认IAP程序的其实地址在0x00000000, 当然也可以修改的,一般情况下IAP程序起始地址为mcu的flash起始地址,芯片在上电复位后先从0x00000004处取出复位中断向量表的地址,并跳转到复位向量中断服务程序,在复位中断程序执行完之后,会跳转到程序的main函数,这个在启动文件中也可以看出来:
这里我的程序在复位中断服务函数处理中先跳转到SystemInit()函数接着在跳转到__main中,这里__main是C++的一个连接库,__main中包含main,所以这里直接写main也是可以的,具体细节自己百度吧,这里的systemInit从名称也可以看到是系统时钟初始化,这也是为什么有些mcu在main函数中没有初始化系统时钟的原因,因为在之前就已经初始化了。
好了再说一下中断向量表,这是M3权威指南中介绍的:
这里的地址根据不同的mcu而不同。
好了简单介绍了1788的内存分布,接着干嘛呐?说一下我们下载的数据吧,标准的IAP下载的是bin文件的数据,我们一般使用keil时生成的是hex文件。其实bin文件和hex文件是差不多的,hex文件包含了数据的地址信息,而bin文件只包含了数据并没有包含数据的地址信息:
右边是hex文件内容, 左边是其对应的bin文件内容,具体的hex文件格式有必要自己查看资料了解一下,我们IAP下载时下载的就是bin文件的内容。 其实这里有一个问题,如果不注意到可能不会发现,这个问题留到最后面说。 好了,理论的就说这些,下面开始进入程序实现,首先要让keil生成bin文件: 这里划线部分:
D:\Keil\Keil_v4\ARM\ARMCC\bin\fromelf.exe--bin --output ./Output/LPC1788_Blinky.bin ./Output/LPC1788_Blinky.axf 前面到.exe为keil安装目录下的fromelf.exe执行程序目录,后面的为要输出的bin文件和axf文件,这里注意Output后面的路径要与这里一样:
接着编译一下就OK了。 接着先说一下IAP程序:这里IAP程序和正常程序一样只是在芯片刚上电时检测是否需要更新程序,上电瞬间检测是否有按键按下,有则需要更新程序,没有则执行老的程序,我这里IAP程序不是标准的,可以通过选择来让程序执行那段程序,老的程序:
这里重点是新程序的接收,当上电检测到按键后进入更新程序段,接着在通过按键选择:
接收数据,或跳转到新程序:
这里我把APP程序放在flash的第16个扇区即起始地址为:0x00010000, 说一下这里的这句:
这里是判断栈地址是否在1788的SRAM的64kB区域内,因为刚上电时MSP指针指向的是栈地址,而1788的栈地址在0x10000000-0x1000FFFF这段区间,所以用上面的判断APP区是否有程序。还有一个APP程序文件数据的接收问题,这个我没留着下面说,再来说说APP程序。APP程序也和正常的程序一样写,这里只要注意一下几点就可以了: 1. 在keil的Target选项中把IROM地址设置好,我的APP要运行在0x00010000起始处,所以我的设置如下:
这个要和IAP程序中设置的APP程序起始地址一样。同时在main函数的开始处进行中断向量表偏移设置:
APP程序设置好了编译一下,发现可能编译后并不能生成.bin文件,很奇怪,后来在网上看到需要在Target选项中的Asm定义NO_CRP,这个NO_CRP是NXP特有的一段flash加密程序,在启动文件中有如下对应:
具体的还是百度吧! 好了最后说一下IAP中接收APP程序文件的事,标准的IAP下载中有很多协议用来接收bin文件数据,最典型的是Xmodem、Ymodem、Zmodem,我这里用的是1K-Xmodem,也有人叫做Ymodem,他的接收是这样的,首先mcu先发送一个字符‘C’,告诉上位机mcu使用CRC16来校验接收到的数据,然后上位机接收到字符‘C’后开始下发1KB数据+3Byte报头+2Byte CRC校验,mcu接收到数据包后进行数据校验如果校验正确则把1KB数据写到APP的起始地址也就是上面我们的0x00010000处,并回复上位机ACK表示数据接收完成并校验正确,然后上位机接收到ACK再发下一包数据,如果mcu接收校验错误则回复NAK,上位机接收到NAK后重发上一包数据…,最后上位机发送数据结束后发送一个EOT表示数据包发送结束完成。具体细节看程序吧!下面附上我用Qt写的IAP上位机:
and
这个是IAP程序: |