S32K Bootloader 开发流程–

1. 功能

bootlloader一般分为三个部分,上位机客户端,boot程序和App程序。

上位机客户端软件:用来将mcu的app程序文件发送给mcu,发送的通讯方式有很多种,常见的如串口,can,甚至以太网。上位机发送的文件类型有很多种格式,如bin、hex、s19等。

boot程序:boot程序的主要功能分为三部分,第一,接收客户端软件发来的程序;第二,将接收到的程序写入到mcu的flash中,即对片内flash进行编程;第三,跳转到App程序。

App程序:就是我们正常运转的应用程序,和普通引用的程序不同的是它是由bootloader引导才开始执行的,不是reset之后执行的默认程序。

  1. 每次ECU 复位后,都会运行Bootloader ,检查是否有来自通信总线的远程程序加载请求,如果有则进入Bootloader 模式
  2. 与远程程序下载主机(Bootloader host)建立可靠的总线通信以获取要更新应用程序,解析其地址和数据代码
  3. 解析应用程序编程文件(S19/HEX/BIN)获得其在 NVM 中的地址和程序代码及数据
  4. 运行 NVM 驱动将应用程序的代码和数据编程到 NVM 中并校验;
  5. 如果没有来自通信总线的远程程序加载请求,则直接跳转到应用程序的复位入口函数(复位中断ISR),运行应用程序
2. 总线通信

为了保证通信的可靠性,必须开发一个基于通信总线完善的通信协议,应用程序下载端和 Bootloader 之间需要建立**请求命令(request command)、确认(acknowledge)、等待(block wait)、错误重传(error re-send)**等机制----Bootloader 根据不同的请求命令完成不同的任务并确认操作是否完成(ACK)以及数据是否正被确完整的传输,若出现数据错误(通过校验和或者 ECC 实现),需要进行自动重传;

应用程序编程文件(S19/HEX/BIN)都具有相应的校验和机制,所以可以采取直接传送程序编程文件行的方式;否则,用户需要在上位机软件中首先解析编程文件,再将其中的地址和数据及代码封装打包成某种定制的通信协议

为了实现数据的可靠传输,一般在总线通信协议中添加信源编码,即在发送是对有效数据进行校验和或者ECC计算并将结果在通信数据帧中和有效数据一起发送,Bootloader接收端,接收到数据帧后对有效数据域进行发送端同样的校验和或者ECC计算,得出结果与接收到的校验和或者ECC计算结果值进行比较从而判断数据的完整性

一些正规的大主机厂要求其ECU供应商开发放入ECU Bootloader必须基于UDS等总线诊断协议,在UDS中规定了相应的CAN ID给Bootloader使用,那么必须在该类ECU中的Bootloader工程中加入相应的UDS协议栈;

3. 解析编程文件

对编程文件的解析, 目的在于获得应用程序的程序代码和数据及其在 NVM 中的存储地址;

MCU 的软件开发 IDE 一般都集成不同编程文件之间的转换工具:比如 S32DS 的objcopy(Create Flash Image )
以及 Keil 的 Motorola S-Record to BINARY File Converter:http://www.keil.com/download/docs/10.asp

Srecord 软件进行合并S19 文件。

4. NVM 驱动程序开发
  • ECU的NVM一般包括其MCU片内集成的用于存放数据的EEPROM或者Data-Flash和用于存储程序代码/数据的Code-Flash/Program-Flash以及MPU扩展的片外NOR Flash或者NAND-Flash
  • NVM 驱动程序包括对 NVM 的擦除(erase)、编程(program)和校验(verify)等基本操作,也包括对 NVM 的加密(secure)/解密(unsecure)和加保护(protection)/解保护(unprotection)操作
  • MCU片上集成的NVM中EEPROM/D-Flash和C_Flash/P-Flash一般属于不同的block,所以可以直接在Flash上运行NVM驱动对EEPROM/D-Flash进行擦除和编程操作
  • NVM驱动一般都是通过运行一个NVM command序列,在其中通过NVM控制器寄存器给出不同的NVM操作命令代码、NVM编程数据和目标地址的方式完成,典型的NVM command序列如下(S32K144 write command sequence)

S32 Design Studio for S32 Platform的激活问题_中断向量表

  • 由于 NVM 的工作速度一般较 CPU 内核频率和总线频率低,所以运行 NVM 驱动前必须对 NVM 进行初始化,将设置分频器其工作频率设置为正常工作所需频率范围;
  • MCU片内的NVM同一个block/partition上不能运行NVM的驱动对其自身进行擦除和编程操作,否则会造成RWW-Read While Write的总线访问冲突(每个NVM block/partition只有一条数据总线,一个时刻只能进行读出或者写入,不支持同时读出和写入),因此对于仅有一个block Flash的MCU来说,就必须在RAM中调用其NVM驱动,来对其自身进行擦除和编程操作,同时在launch Flash command到等待command完成期间必须关闭CPU全局中断,禁止外设中断响应,否则取中断向量和运行中断ISR都会访问Flash,要使能中断,就必须将中断向量表偏移到RAM或者NVM block(EEPROM/D-Flash)并将响应的中断ISR也拷贝到其他RAM或者NVM block上(当然该中断向量表也必须更新指向新的中断ISR);
  • 由于以上write sequence 的要求,通常需要将Bootloader的NVM驱动拷贝到MCU的RAM中运行,其可以将其完整的NVM驱动拷贝到RAM中运行,也可以只拷贝NVM command launch到等待command完成的几条指令到RAM执行即可,因为NVM驱动中其他操作(比如填写NVM操作命令、写入编程地址和数据等操作)并不会占用MCU数据总线上往NVM中写入数据;
  • 更为安全的方法是不将NVM驱动程序存放在NVM中,而是在Bootloader最开始通过上位机将其下载到RAM中运行,Bootloader结束后将该区域RAM清除,从而避免由于意外运行NVM驱动程序造成的NVM数据丢失和修改
  • 一般MCU厂商都会给出其MCU的NVM驱动库,用户可以使用该类库实现NVM操作,如果是Freescale/NXP的汽车级MCU,还可以使用CodeWarrior IDE集成的Processor Expert生成相应的NVM驱动程序;
5. Bootloader 其他开发要点
5.1 Bootloader 与应用程序的关系

Bootloader 和应用程序分别是两个完整的 MCU 软件工程,各自都由自己的启动代码、 main()函数、链接文件、外设驱动程序和中断向量表

S32 Design Studio for S32 Platform的激活问题_中断向量表_02

Bootloader和应用程序的链接文件中,对NVM的地址空间分配必须分开独立,不能重叠(overlap),但其RAM分配没有约束,两者都可以使用整个RAM空间,因为跳转到应用工程后,将启动代码将重新初始化RAM;

Bootloader 必须使用 MCU 默认的中断向量表因为每次复位后 MCU 都是从其认中断向量表的复位向量取地址执行的;应用程序的中断向量必须进行偏移,通过相应的中断向量偏移寄存器ARMCortex M 系列 MCU 的 SCB->VTOR 寄存器,而 NVM(P-Flash)的擦除都是按照sector 进行的,所以为了充分利用 NVM(P-Flash)空间,都将 Bootloader 分区到 包含默认中断向量表的若干 NVM(P-Flash)sector(S12(X)系列 MCU 的 NVM 最后若干 sector, ARM Cortex M 系列 MCU 从 0 地址开始的若干 sector);

为了避免应用程序更新过程中应用程序更新失败,为了避免这种情况出现,常常对BootLoader 对应用程序进行双备份,两个不同NVM 来保存应用程序,只有新的应用程序更新完成后,才擦除旧的应用程序。

5.2 Bootloader 到应用程序(APP)的跳转方法

开发使用 Bootloader 后,每次 ECU 复位之后都将首先运行 Bootloader,若无远程应用程序下载请求则直接跳转到应用程序复位函数地址,这里面有两个问题需要考虑

如何获得应用程序复位函数地址,方法有以下两种:
1)通过链接文件固定应用程序的复位启动函数地址;
2)从应用程序中断向量表的复位向量地址获取;

推荐方法2):因为其灵活性好,每次应用程序变化后无需关心应用程序复位函数被编译到了NVM的具体地址,只需要将应用程序中断向量表中的复位向量取出运行即可:

//典型S12 MCU的应用程序中断向量表基地址寄存器 IVBR= 0X7F 
typedef void (*near tIsrFunc)(void); /* ISR prototype definition */
word *Ptr; /*pointer used for ISR vector fecth*/
Ptr = (word *)0x7FFE; /*get the ISR vector from the interrupt vector table of APP project */
((tIsFunc)(* Ptr))(); /* covert and run */

跳转时机:

  1. Bootloader更新完应用程序并校验其完整性OK之后,将用到的外设(比如CAN/LIN通信总线模块、定时器、GPIO等)寄存器恢复到复位后的默认状态,然后直接跳转;
  2. Bootloader更新完应用程序并校验其完整性OK之后,等待看门狗定时器超时溢出复位,在Bootloader最开始判断无远程应用程序下载请求而跳转;推荐: 看门狗复位则属于硬件复位,其会将绝大部分外设(模拟、时钟和外设)电路复位,更接近直接运行应用程序的情况
5.3 开发 Bootloader 需要掌握的知识和调试方法技巧

开发Bootloader需要对ECU所用的MCU的RAM和NVM资源十分清楚,然后对其进行分区,保证应用程序和Bootloader的NVM分配没有重叠。所以必须了解所用软件开发工具IDE的链接文件的使用方法和编写规则

需要判断中断向量表偏移是否成功,NVM驱动拷贝的地址和大小等信息,所以必须掌握所用软件开发工具IDE的编译链接结果中map文件的具体信息

掌握如何将NVM函数重定向(将函数程序代码的存储地址和运行时地址分开)到RAM中执行的方法也十分有用;

在开发应用程序时,需要先对其进行单独调试以保证其功能正常,这时虽然其外设中断向量表已经进行了偏移,但其复位向量必须的放置在默认中断向量表中复位向量所在的地址,否则下载后无法运行,进行正常调试,因为如果把应用程序的复位向量放在偏移后的应用程序中断向量表中,则默认的复位向量内容为0xFFFF(Flash擦除后的状态),CPU内核就会到0xFFFF的地址取指运行,显然不是真实的工程启动函数,所以无法运行,其结果跟一个新MCU未写入任何程序时上电运行的情况一样,会不断的出现非法地址复位;而在应用程序开发完成后,再将其偏移到应用程序中断向量中,以避免与Bootloader工程的Flash地址冲突;

掌握利用调试器的Hotsync或者attach方法加载elf文件中的调试信息对Bootloader和应用程序进行无缝调试也是非常实用的,可以大大提高Bootloader的调试效率;

5.4 量产时 Bootloader 和应用程序的下载方法

推荐将Bootloader和应用程序编译链接生成的编程文件进行合并,一次性使用量产工具(如Cyclone编程器)下载以提高生产效率。

6. Bootlloader 开发架构

Bootloader 可以分解3层:

  • Bootloader : 负责启动用户应用程序并且轮询传入数据
  • communication handling /Memory handling:负责处理接收的数据并且对NVM 的写入
  • Microcontroller drivers: 负责与MCU 上可用的实际外设的低级通信

The bootloader is placed in the D-Flash section. The application should be placed in the P-Flash section.


S32 Design Studio for S32 Platform的激活问题_中断向量表_03


S32 Design Studio for S32 Platform的激活问题_数据_04