罗 博,仇 傲
(中海油田服务股份有限公司,河北三河 065201)
一般情况下,MC9S12X 系列单片机进行代码升级需使用BDM 仿真器,如果电路板在汽车或者其他工业设备里,就需要拆卸设备,拆出电路板,操作繁琐,耗时较多。在石油随钻仪器、航空航天、兵器等电路系统中,电路工作环境恶劣,震动剧烈,为增强抗震动冲击及绝缘性能,电路板需要灌封胶[1-5],如果使用BDM 仿真器更新程序,选择去除封胶直接下载程序,则很容易损伤电路板,选择在接口引出程序下载线则会浪费宝贵的接口。如果可以通过原有通信总线完成程序升级,则可节约时间,简化操作,降低成本。
Code Warrior 是一款集成开发平台,可用于MC9S12X 系列芯片的工程开发,具有实际应用开发所需的IDE、编译器、链接器、调试器等[6]。PE(Processor Expert)是一款革命性的编程工具,可与CW开发平台相结合,作为其内部菜单实用,使用时只需要图形化添加需要的模块即可生成对应代码。PE的选项式初始化操作简单、快捷、方便,对于不同的飞思卡尔单片机,只要是相同的模块,PE的初始化配置属性就基本相同。PE 还可以自动生成中断向量表,自动声明中断服务函数[7-9]。使用PE 编写飞思卡尔系列嵌入式芯片程序,开发时间短,效率高,不易出错。对于PE 开发的工程,如果可以用Bootloader在线升级程序,则将大大减少开发和维护时间。
Bootloader 固化在芯片中,是上电后首先运行的程序,其主要功能是在电路系统初始化后,从ROM、Flash 等非易失存储器上加载用户应用程序(APP)代码,然后引导APP 运行[10-13],使电路系统正常工作。
Bootloader的开发,首先需要对单片机的存储空间进行合理的分配。把Flash的程序存储空间分为Bootloader 区域以及APP 区域。APP 区域是用户应用程序代码存放的区域。Bootloader 固化在相应的Flash 区域中,不能修改,通过BMD 仿真器下载后可一直使用,但是APP 区域可以重复由Bootloader 修改更新。Bootloader 区域存放的代码控制存放APP 代码的区域。上电后,Bootloader 与上位机建立通信成功后,通过串口、CAN 等通信方式接收APP 代码,将其存放在相应的Flash 区域,完成修改后可以跳出Bootloader,执行APP 区域的代码,完成更新程序。
文中方案使用MC9S12X 单片机的SCI 模块进行串口通信,选择RS-485 总线作为通信方式,RS-485总线采用半双工工作方式,可进行多节点、远距离通信,抗干扰能力强,在工业中使用广泛。SCI 模块连接到RS485 数据收发芯片来进行串口通信,芯片选择TI 公司的SN65HVD11Q,最大速率为10 Mbps,最高温度为125 ℃[14],可满足石油、汽车等行业要求。
有多种方式决定上电时先进入Bootloader 还是APP。一般根据MC9S12X 系列单片机的PP0 引脚状态决定,如果PP0引脚接地,则上电后进入Bootloader;若PP0 引脚为高电平,则上电时进入APP[15]。
文中方案选择PP0 引脚接地,电路图如图1 所示。刚上电时进入Bootloader 状态,在一定时间内,如果收到在线升级命令,则继续停留在Bootloader,等待上位机发送APP 代码,接收完成后对APP 代码进行修改,如果超过此时间,未收到在线升级命令,则进入APP,正常工作。
图1 PP0引脚连接
Bootloader 简要工作流程如图2 所示。
图2 Bootloader简要工作流程
由于上电后PP0 引脚为0,因此首先进入Bootloader,完成初始化;然后,在较短时间内决定继续停留在Bootloader 状态还是进入用户应用程序,时间选择为3 s。判断依据为存储在EEPROM 区域的数据B_flag,如果上电后第三秒时B_flag 为0,则跳转执行用户应用程序;如果B_flag 为1,则停留在Bootloader 状态,等待接收其他命令。MCU 收到命令后,判断命令是否合法,不合法则继续等待,合法则执行相应命令。在上电后3 s 内,上位机可以通过RS-485 总线向MCU 发送命令,改变B_flag的值。如果收到擦除APP 命令,则擦除存储App的Flash 区域,并向上位机发送擦除成功命令,上位机收到命令后,发送s19文件,Bootloader 接收s19 文件完毕后,进行校验,如果正确,则将代码写入对应的Flash 区域,写入成功后,向上位机发送更新代码成功消息,上位机收到消息后,如果发送进入App 命令,则跳转进入APP,否则继续停留在Bootloader 状态,等待接收其他命令。
单片机通过SCI 模块与上位机通信和下载APP代码,对传输准确率要求高,对速率要求不高,因此,虽然目前RS-485 总线大数据量传输速率可以达到1 Mbps,但考虑到速率过高会导致电路工作时总线抗干扰能力差,从稳定性考虑,波特率不需设置过高,通过SCIBDH 和SCIBDL 两个寄存器将波特率最高设置为115 200 即可。帧格式设置包括1 个起始位、8 数据位、1 停止位。
Bootloader 擦除APP 代码如图3 所示。不同的芯片,其内存空间不同,存储APP的Falsh 区域也不同。根据内存空间区别,NXP 公司为每一种MC9S12系列单片机分配对应的Part ID,Part ID 为16 位数据,高8 位固化在地址0x001A,低8 位固化在地址0x001B[16]。所以,收到擦除App 命令后,读取Part ID值,判断属于哪种芯片,然后擦除该芯片对应的FLASH 区域,将存储的App 代码擦除,不可擦除用户重置向量和Bootloader[15]。
图3 Bootloader擦除APP代码
Bootloader 擦除APP 区域成功后才可接收新的APP 代码。Code Warrior 生成工程的Project.abs.s19文件不能直接发送给Bootloader。Bootloader 接收的s19 文件要求是全局(线性)地址,且数据必须对齐为32 字节,数据长度也为32 字节。转换s19 文件使用NXP官方提供的SRecCvt-GUI.exe即可[15],如图4所示。
图4 转换s19文件
Bootloader 接收完s19 文件后,根据Part ID 判断s19 文件中地址是否与芯片匹配,如果地址正确,则向对应的FLASH 区域写入APP 代码,每次写入32 个字节。代码如图5 所示。
图5 将APP代码写入Flash
Bootloader 代码与APP 代码存储区域不能重叠。Bootloader 代码存放在地址0xF000~0xFFFF的区域,APP的重置向量存储在地址0xEFE0~0xEFFF的区域,每个中断向量地址为16 位,因此需要把ROM_C000的地址范围从原来的0xC000~0xFEFF 改成0xC000~0xEFDF。
在Processor Expert的Build Option 中,点 击Memery segments,再点击ROM/RAM segments,选择ROM_C000 区域,此处可设置ROM_C000 区域的各项参数,只需要将size 修改为2FE0 即可,这样结束地址就变为0xEFDF,如图6 所示。
图6 修改ROM_C000长度
0x7F10~0x7FFF 会被用于重定位中断向量表,所以需要把ROM_4000的地址从原来的0x4000~0x7FFF 改成0x4000~0x7F0F。
在Processor Expert 中选择ROM_4000 区域,将size 修改为0x3F10 即可,这样结束地址就变为0x7F0F,如图7 所示。
图7 修改ROM_4000长度
用户中断向量原存储地址范围为0xFF10~0xFFF8,每个向量为16 位地址,因为地址范围0xF000~0xFFFF的区域要存放BootLoader,所以必须改变用户中断向量存储地址范围,改为0x7F10~0x7FF8。在Processor Expert的Properties 中选择Internel resource mapping,然后选择Interrupt/Reset vector table,最后在Interrupt vector table 中将Address修改为0x7F10,长度0xEA,最后一个用户中断向量地址变为0x7FF8,如图8 所示。
图8 修改中断向量地址
Reset vector table 不能修改,其包括3 个地址分别为0xFFFA(COP Watchdog Timeout),0xFFFC(Clock Monitor Fail)和0xFFFE(Reset)的系统重置向量,其中地址为0xFFFE的Reset 向量包括引脚复位、上电复位、低电压复位、非法地址复位4 种功能[16]。MC9S12X 系列单片机上电后先从地址0xFFFE 处读取第一条指令,如果该地址改变,则上电后Bootloader 将无法工作。
在Code Warrior 生成的代码中,3 个系统重置向量与其他中断向量地址一起存放在vectors_s12xep.c文件中的tIsrFunc _vect[ ]中,将IVBR 修改为0x7F,中断向量表起始地址从0xFF10 改为0x7F10,其他中断向量基地址从0xFF 变为0x7F,但对这3 个系统重置向量无影响,其地址(0xFFFA~0xFFFE)不会改变,并不影响上电后Bootloader的正常运行[16]。但在Processor Expert 中,修改这3 个系统重置向量的地址时,其地址会改变,使Bootloader 无法正常工作,导致上电后芯片无法正常工作。
使用传统方式进入Bootaloader 状态时,必须重新上电,然后根据PP0 引脚是否为高电平进入Bootaloader。如果系统统一供电,则重新上电会影响系统其他子系统工作,如果单独控制供电,则增加电路复杂性和成本。因此,可以在用户程序中添加代码,增加用户程序进入Bootloader 功能,不需要重新上电。上位机通过RS-485 总线向单片机发送进入Bootloader 命令,命令校验通过后,B_flag 赋值为1,然后重启单片机。因为PP0 引脚一直接地,所以单片机重启后进Bootloader 状态,如果在3 s 内没有收到上位机命令,则将B_flag 值变为0,停留在Bootloader状态,可以更新用户程序。
为了给Bootloader 发送s19 文件,开发上位机软件。按照RS-485 通信协议,使用Visual C++开发,完成与Bootloader 握手、读取MCU 状态、发送s19 文件、切换至用户应用程序等功能。
传统MC9S12X 系列单片机的在线升级均基于Code Warrior 生成代码,代码开发时间较长。文中设计的BootLoader 实现方式可以使用PE 图形化方式完成用户代码开发,编程基础差和没有系统训练编程的开发人员也可编写应用代码,开发和维护效率高,不易出错,利用系统本身的RS-485 总线更新程序,电路系统不用重新上电也可准确方便地实现代码的现场更新升级,方便实际应用。通过对中海油服自研随钻测井工具和旋转导向钻井工具的实际应用表明,该方案至少可节约50%以上的开发和维护时间,大大减轻了科研人员负担。