arm系统代码固化的串口实现方法
早期的嵌入式程序采用“编程—烧写—修改—烧写”的开发模式,大量的时间消耗在重复烧写芯片上,增加了开发成本和研发周期。之后发展到仿真器阶段,虽然简化了开发模式,但是由于仿真器与arm芯片的兼容性等因素,经常会发生程序在仿真器上能正确运行,但是固化之后运行却出现问题的情况。
程序的固化是软件开发过程中重要的一环,一般可通过jatg口、网口及串口等进行烧写。相比之下,串口实现更为便捷,更值得推广。笔者在开发1c1t小灵通中继站的过程中,通过编制烧写程序,利用串口将编译后的目标代码发送给arm处理器;由arm处理器内部的监控程序将目标代码写入片外flash,实现程序的在线烧写。这样不仅简化了电路设计,而且降低了开发成本,缩短了开发时间。
1 烧写原理及过程
硬件连接如图1所示,arm开发板一方面通过串口与pc机连接,另一方面通过20针idc宽带线与仿真器相连,再由仿真器通过25针并口插座与pc机的lpt口相连。开发板通电后即可进行烧写工作。
如图2所示,代码固化分2个步骤进行。第1步,如虚线一所示,监控程序的映像通过仿真器下载到arm的内部ram中运行,用户可以在主机端用超级终端或者其他串口调试工具与开发板通信。第2步,将应用程序的可执行代码通过串口发送,如虚线二所示,此时内部ram里的监控程序就会接收并把它烧写到flash中。
图1 arm开发板与pc机的连接
图2 代码烧写原理
2 监控程序的设计
2.1 启动代码设计
实现串口烧写的监控程序包括arm启动代码、串口通信代码和flash烧写代码3部分。arm启动代码是整个程序运行的入口点,完成arm系统正常运行所必需的简单初始化,然后把系统控制权交给操作系统或者高级语言编写的监控程序。由于启动代码直接对soc内核和硬件控制器进行编程,因此必须采用汇编语言。
启动代码包括异常向量表的定义、各种模式的堆栈初始化、系统硬件初始化、程序运行环境初始化,最后跳转到用户c语言主程序。当系统上电或复位后首先会从逻辑地址0x0处执行。
arm处理器有7种运行模式,如表1所列。每一种模式都有独立的堆栈指针寄存器(sp),因此对使用的模式都要给堆栈指针寄存器sp定义堆栈地址。改变状态寄存器(cpsr)内的状态位,使处理器切换到不同模式,然后给sp赋值就可以实现堆栈的初始化。当然,堆栈的大小视需要而定。
表1 arm处理器的7种运行模式
堆栈初始化程序如下:
initstack
movr0,lr;保存返回地址
mov r1,#mode_svc:or:i_bit:or:f_bit;设置管理模式堆栈
msrcpsr_c, r1
ldrr13, =svc_stack
movpc,r0;子程序返回
系统硬件初始化包括设置外部存储器的类型、数据位宽度等,完成之后即可通过“b main”语句跳转到c语言主程序。与ldr指令相比,虽然跳转范围小,但是32 mb的地址空间跳转足以满足程序需要,而且运行得更快。
2.2 烧写主程序设计
main函数功能主要包括接收串口数据、解析映像文件及写入外部flash,如图3所示。串口函数主要由init_sio()、init_val()和send_data()组成。函数init_sio()用于对串口通信参数的设置:波特率,57 600 b/s;奇偶校验,无;数据位,8位;停止位,1位。init_val()是对接收到的数据进行转存,为了提高接收速率,把接收到的数据先暂存到外部sram中。如果程序量较小也可以选择暂存到芯片内部的ram(64 kb)中,等接收完毕后再对其进行解析。send_data()用于向串口回送烧写工作的信息。
图3 main函数流程
下一步就是要对映像文件进行解析并正确地写入外部flash中。嵌入式程序通过编译器生成的映像文件是elf格式的axf文件,里面有文件头、段信息等信息,不能直接烧录,一般将它转化为bin或者hex文件。这里将嵌入式程序编译成srecord十六进制文件。这是一种motorola公司推出的标准文件格式,用来将数据从pc机传送到目标平台flash,在嵌入式开发中广为应用。srecord文件格式如下:
其中,sid表示当前记录的类型,常见的有s0、s1、s5和s9等,各个类型代表的意义不同,如s9所在语句表示文件的结束;数据长度代表本句后面数据的长度;地址的字节数会因不同的s记录而异,一般为2字节,表示的是后面的数据在存储器中的地址。
一个s记录的长度不会超过78字节,所以每次读数据的长度设为78字节,通过判断文件类型(如s3为0x5333)的标志位来确定一个s记录的开始。解析过程就是根据sid确定数据长度,截取数据部分,传递要写入flash中的地址。
最后一步就是如何将数据写入flash。不同类型flash存储器的编程与擦除指令也不太一样。本系统使用的是hyundai公司生产的hy29lv160。
向flash存储器的特定寄存器写入地址和数据命令,就可对flash存储器进行烧写、擦除等操作。编程指令只能使“1”变为“0”,而擦除命令则可使“0”变为“1”,因此正确的操作顺序是先擦除、后编程。当flash被擦除后读出的数据应为0xff。写指令编程如下:
*((volatile uint16 *)start_addr + addr_unlock1)=data_unlock1;
start_add为flash起始地址,addr_unlock1为0x555,//data_unlock1为0xaaaa
*((volatile uint16 *)start_addr +addr_unlock2)= data_unlock2;
//addr_unlock2为0x2aa,data_unlock2为0x5555
*((volatile uint16 *)start_addr +addr_unlock1)= setup_write;
//setup_write为0xa0a0
*to_add=data_pra;//写入数据
应在每个单元烧写命令发出后进行检测,以保证前一个单元烧写结束后再进行下一个存储单元的烧写,当然也可采用延时等待的方法进行连续的烧写。
2.3 编译与执行
由于日本oki公司的小灵通芯片ml7338是基于arm7tdmi核,所以系统采用arm集成开发调试环境ads1.2,使用techorice仿真器。具体编译语句如下:
armlink startup.o main.o
-rw-base 0x10000000
-first startup.o(vectors)//中断向量表位于映像头部
-o loader.axf
-info totals
其中,0x10000000是ml7338内部ram的起始地址,编译完成后生成loader.axf文件。
需要注意的是,要固化的代码应转化为srecord文件。可在编译器下arm fromelf﹥output format中选择motorola 32 bit hex,或者使用以下编译语句处理:
>fromelfnodebug filename.axfm32 filename.txt
以上两种方式都将产生srecord文件。通过仿真器把烧写程序下载到ml7338的内部ram中,运行后即可固化pc端通过串口工具发送过来的应用程序代码。固化完成后拔掉仿真器,当系统复位或上电后flash存储器被映射到起始地址0x0处,装入的可执行映像文件即可得到执行。
结语
本文所写的烧写程序虽然是针对小灵通芯片ml7338的,但是已经把它拓展到了基于arm的32位嵌入式系统,开发人员只需对框架略做修改即可编写自己的烧写程序。整个系统采用arm汇编语言和c语言开发,因此可以方便地移植,而且对编写基于网口的监控程序也具有重要的参考价值。
S7300以太网转以太网模块作为ModbusTCP主站 实现PLC与其它Modbus TCP设备的通讯
借助人工智能与物联网技术,未来健身将更加智能
电阻器的标注方法有几种_电阻器常用的标注方法
兆芯国产x86处理器亮相SWEDCS 2017
杜比与联想合作推出笔记本电脑新品类
ARM系统代码固化的串口实现方法
飞腾平台共与67家国内厂商的108款产品完成兼容适配
裁员成常态,魅族能否把握住5G机遇逆风翻盘
Redmi Note 9系列将于明日发布
贴片电阻上丝印标注50B、10C是什么意思?
一文带你了解热设计
PCIE相关概念和带宽计算方法
基于智能家居场景的POALRDB性能体验
航空航天系统电力技术介绍
灵活的4mA至20mA压力传感器变送器,集成电压或电流驱动
特斯拉黑盒子的出现给智能门锁浇上了一盆冷水
苹果真的有那么厉害,纷纷引来Android制造商争先效仿
新一代“芯片级”北斗形变监测解决方案发布!
中国出现共享宝,马共享马扎现身北京下面你们猜一猜谁会被共享?
华为P40 Lite E具有6.39英寸高清打孔FullView显示屏