DSP

【dsPIC33E】Bootloader(一)Bootloader的介绍与Flash结构

2019-07-13 15:16发布

对于嵌入式开发而言,Bootloader几乎与操作系统同等重要,它可以让我们摆脱MCU官方工具,定制自己的烧录工具,不仅提高产品辨识度,同时也大大减少了对外引脚数量(例如兼容通信的Uart或CAN等,而不需要另外接JTAG)。 要开发Bootloader,相对于普通程序,是有一定难度的,这其中涉及到MCU的工作原理内部存储结构等,而且仅仅依靠C语言可能无法完成,有时需要配合汇编来精确执行特殊指令(例如Flash擦写)。 一般MCU的机器码都是存储在Flash中,MCU启动时PC指针会从内部Flash第一个地址开始读取指令运行,这个过程我们一般无法干涉。但由于我们写的代码存于Flash中,所以一旦从Flash启动,后续操作就完全可以由我们来指定,我们可以指定程序执行位置。 对于低端MCU来说,我们可以通过在Flash初始的位置设置指令,来启动内部不同flash区域的程序,以及烧写程序到这些flash区域,这些操作集合叫做Bootloader。Bootloader承担着用户程序的烧写以及跳转。 对于高级MCU或者CPU来说,可以轻松映射外部存储(外部Flash、U盘、硬盘等),MCU启动后,我们可以指定其从哪个存储启动,甚至通过通信接口接收数据存储到这些外部存储。这些操作集合在嵌入式操作系统中一般称之为UBoot,在PC中称之为BIOS,外部存储一般存放的是操作系统。 实际上上述两种功能是一样,后者相对复杂一点,此处我们着重讲述前者。 下图为通用MCU带Bootloader程序和用户程序的Flash存储结构: 常规Bootloader逻辑是这样的: 1、开机Goto到Bootloader的Main函数 2、判断是否有按键按下或者是否接收到通讯命令 3、若有操作,则停留在Bootloader,执行后续操作,例如烧录程序 4、若超过一定时间未有操作或者命令,进入用户程序 注意: 1、Bootloader应从Flash第二页之后开始,避免擦除编程中断向量表时,导致Bootloader缺失故障。 2、Bootloader中不要使用中断,因为Bootloader和用户程序共用中断向量表,更新用户软件会重新修改IVT。   以下详细介绍dsPIC33E系列Flash操作。 对于dsPIC33E系列,内部Flash存储如下,对于部分低端MCU,部分区域(例如附属闪存)是没有的,详细参考该MCU的Datasheet:   而以dsPIC33EP256GP506为例,很多空间被阉割了,实际flash结构如下:   下面讲讲如何在MCU运行时,对内部Flash进行擦除、编程(注意,建议不要对当前程序运行区域进行擦写,会导致运行异常)。 Flash编程相比于EEPROM,要麻烦不少。 Flash编程采用的方式是与模式,即编程时,将数据与Flash地址上的数据与操作。因此,如果一个地址上的数据位不是全都为1,那么编程该地址的结果就是错误的,所以我们在操作Flash时要有一个共识,即,同一个地址不应该被编程超过2次。我们可以在第二次编程前,将该地址所有数据位全部置1。 我们该如何在编程前将对应地址的数据位全部置1呢? 那就是擦除,Flash擦除会把对应区域的数据位全部置1。但是。。。擦除不能仅擦除一个地址的数据,而是必须擦除一页的数据,那么一页的大小是多少呢?是1024个指令字,一个指令字为32位(实际24位,高8位为虚字节,始终保持为0),由于dsPIC33E系列都是16位单片机,因此每个指令字占2个16位数据,占2个地址,实际擦除的地址跨度为2048,即0x800。假设我们擦除0x000000,实际会擦除0x000000-0x0007FF,擦除其中任意地址,都会擦除该页。 基于以上原因,若是我们要编程某部分flash数据,需要先将该页内所有数据读出来,然后擦除flash页,再修改读出来的数据,最后重新写入该页所有数据。 dsPIC33E系列编程功能体现在闪存控制寄存器NVMCON的NVMOP<3:0>中。通用功能如下,实际功能可能会有所阉割,参考对应数据手册。 编程时可以进行行编程、字编程、单个配置寄存器字节编程,一行为128个指令字,字编程为2个指令字,单个配置寄存器字节编程比较特殊,不需要擦除,可以直接编程,但需要注意的是,编程配置字时,时钟只能是FRC,不能带PLL。能否进行行编程依赖于写锁存器长度,写锁存器在0xFA0000处,部分长度只有2个指令字,所以无法进行行编程。 针对我们使用的示例单片机,dsPIC33EP256GP506,参考Datasheet我们发现: 这款单片机功能阉割较多,只支持也擦除和双字编程,其写锁存器只有2个指令字。同时,这款单片机的无法编程配置字,所以在更新用户程序时,不能通过Bootloader烧写配置字。 最后,需要提醒的是,由于配置字在用户存储区域最后一页,擦除最后一页会触发代码保护,所有地址数据全部清零。以dsPIC33EP256GP506为例,0x02A800之后的地址不能擦除。 本节到此结束,下一节将剖析dsPIC33E系列程序编译后的Hex文件。