王璐
(中国科学院长春光学精密机械与物理研究所 吉林省长春市 130000)
数字控制处理器(DSP)具有高速的数据运算能力,功能丰富,接口多样,具有强大的控制能力,而且易于开发。基于TMS320F28335DSP的嵌入式系统,更是广泛应用于电机控制、通信、医疗、工业控制等领域[1]。在伺服控制上,为了提高控制精度往往需要大量复杂的算法和更高的采样频率,这就对DSP 的运算能力提出了更高的要求,双DSP 并行处理的嵌入式系统是一种解决方案[2][3]。传统的程序升级方式依赖于JTAG 接口,通过仿真器连接计算机访问DSP 的存储空间,进行仿真和烧写。这种连接方式稳定,方便操作,但价格昂贵,使用场所受限,适用于实验室设计开发阶段[4]。嵌入式系统设备交付后实际使用环境往往复杂多变。可能面临无法插拔仿真器,或者出现JTAG 接口距离过长无法烧写成功的情况。限制了DSP 的进一步应用,对系统的可维护和易更新等方面提出了进一步的要求。所以开发出稳定,并且能够远距离传输,不受JTAG 仿真器接口限制的程序升级方法非常重要。
文献[5][6]基于TMS320F2812 内部FLASН 提出一种在线烧写技术,提高了系统的可维护性。文献[7][8]通过配置GPIO84~GPIO87引脚的电平选择启动方式,选择从SCI、SPI或CAN总线等方式启动。烧写完毕后将GPIO87 重新拉高,重新启动DSP 即可实现程序的升级运行。文献[9]通过SCI 串口分别与上位机和辅助芯片STM32接收指令和用户程序实现烧写。文献[10]通过将待升级程序复制到FLASН 备份扇区,保证程序完成性,能够在烧写意外断点情况下修复并运行。文献[11]设计一种基于GPRS 通信模块的系统结构实现了远程无线通讯。文献[12][13]基于CAN 总线通讯设计了一种远程程序方案。
本文基于一种双DSP 伺服控制硬件电路上进行远程程序升级的方案设计。采用一种基于SCI 通讯的程序升级方案,无须仿真器,同时将控制函数嵌入到用户程序中,进行控制函数的搬移,实现程序的升级。
可通过TI 自带的Flash API (The Flash Application Program Interface)功能库可实现脱离仿真器JTAG 的多种程序升级方式,无论采用什么方式烧写都需要用Flash API 库内的算法实现对Flash 区域的操作和编辑[14][15]。API 库主要由以下几个函数组成:
API 库的函数APIVersion 和APIVersionНex 用于确定当前API库文件的版本,前者返回浮点型的数,后者返回Нex 的数,用于判断当前API 库的版本防止由于版本错误导致的升级失败。
擦除函数仅对Flash 区域进行操作,且当烧写进行时无法进行擦除操作,擦除操作将Flash 区域的数据全部写0xFFFF,擦除Flash 时操作单元时一个扇区,不可对扇区内的某一位再进行操作,没有擦除指令的扇区内容保持不变。Flash28335_Erase(Uint16SectorMask,FLASН_ST*FEraseStat); 函数中的SectorMask 定义标示位来指示擦除的扇区;定义FLASН 结构的状态指针FeraseStat,用于确定执行擦除操作后状态返回值,判断操作是否成功。
擦除程序后的各个扇区数据均为0xFFFF,烧写程序的实质就是对扇区内的1 进行写0 操作,烧写程序函数为:
Flash28335_Program(Uint16*FlashAddr,Uint16*BufAddr, Uint32 Length, FLASН_ST *FProgStatus);
其中*FlashAddr 指向烧写的数据存入Flash 区域的第一个地址,*BufAddr 为缓冲区域指针,Length 为数据长度,*FprogStatus 表示为烧写的状态指针。
验证程序为烧写后的附加程序。API 库中有如下定义。
Flash28335_Verify(Uint16 *FlashAddr,
Uint16 *BufAddr, Uint32 Length,
FLASН_ST *FVerifyStat);
其中*FlashAddr 指向烧写的数据存Flash 区域的第一个地址,*BufAddr 为缓冲区域指针,Length 为数据长度,*FVerifyStat 表示为验证地址。
由于API 库函数需要对FLASН 区域进行操作,所以不可运行于在Flash 区域,运行时需要将储存在FLASН 区域的程序搬移到RAM 中运行。几种搬移方式流程如图1 所示。
API 程序的搬移方式有三种,一是通过JTAG 引脚,依然需要仿真器。二是通过SCI、SPI 等通讯的A 通道实现烧写的控制程序,这种升级方法需要对相应的引脚进行拉高和拉低,并且需要严格用通讯的A 通道进行升级,操作相对较为复杂,也不灵活。三是API函数代码嵌入到FLASН 代码中,每次程序运行都将程序运行至RAM 中去。
API 库函数搬移到RAM 区运行可通过在.cmd 工程文件的配置实现,程序文件中必须包含以下两个工程的语句-lFlash28335_API_V210.lib(.econst) 库文件源代码-l Flash28335_API_V210.lib(.text),是API 库文件的参数。
图2:双DSP 系统嵌入式系统框图
此段程序定义了API 函数段装载在PAGA0 的FLASНA 中,运行地址在PAGE0 的RAML0 中。令编译器创建了变量分别指向该段的首地址、末地址和起始地址。上述.cmd 文件中定义了起始终止和运行地址,这些均已在API_Library.h 中进行了定义。
在用户程序.c 文件中,添加代码进行如下调用和定义。即可实现API 程序的搬移到RAM 中。
图3:升级程序流程图
随着精度要求越来越高,为了提高控制精度,需要大量算法,需要一段时间进行计算,可能出现采样周期内算不完的情况,因此很多嵌入式控制系统需要更为强大的运算能力。本系统的硬件电路采用两个DSP 并行处理的方式,实现了性能的拓展。
系统采集信号为RS422 通信,通过芯片MAX3490 将RS422通信转换为RS232 信号,这些信号作为高速芯片SC16C654 的输入,转换为数据线被双DSP 接收,这些信号均可通过CPLD 配置决定交给主控DSP 处理还是辅助计算DSP 处理。将双DSP 的Zone7 映射到ST16C654 和DA 芯片的外部存储空间,在CPLD 中逻辑进行通道的选择。
双DSP 均采用TMS320F28335 芯片,在CPLD 中进行功能分配使其能合理的并行处理运算,通过双口RAM 型号IDT70V28 进行双向通信,IDT70V28 可进行16 位64k 空间,最大延迟小于25纳秒的高速传输,最大限度地减少了双DSP 之间通信的延迟时间。两个DSP 都存在远程升级的问题,将两个DSP 的SCIA 通道作为远程升级的串口,连接到CPLD 中。双DSP 系统嵌入式系统框图如图2 所示。
双DSP 之间采用CPLD 芯片EPM2210F256。双DSP 的SCI 串口、各种控制信号以及外部的高速传感器信号都连接到CPLD 中。CPLD 中进行时钟分频,产生控制信号进行芯片使能,逻辑控制,对通信通道进行灵活配置选择等。上位机和两个DSP 进行通信,由上位机控制决定待烧写的DSP 芯片,在CPLD 中建立待升级DSP 的SCIA 通道。
DSP 在线仿真时,程序直接从page0 的地址0X000000 中运行。然后跳转到主函数中运行。程序正常运行时,芯片上电后首先直接跳到中断向量表中0x3FFFC0 处的RESET 处执行,在这个地址下存放一个指令用于跳转至初始化引导函数InitBoot,然后调用引导模式选择函数SelectBootMode,用来检测配置为输入的GPIO84~GPIO87 的引脚的状态,若四个引脚都为高电平则为FLASН 启动方式,跳转到FLASН 入口地址0X33FFF6,此地址下存放了程序codestart,coderstart 为引导后重定向代码,在此程序中关闭看门狗,后跳转到c_int00,_c_int00 的代码最终会调用主函数,后进入用户程序开始执行用户主循环程序。
.cmd 文件中主要包含PAGE0、PAGE1 和SECTIONS 三个部分,SECTION 为伪指令块,将数据段装载到相应的储存空间,PAGE0和PAGE1 为数据空间和程序空间,主要为指令MEMORY,将装载的储存空间分配到FLASН 区域中的具体位置。.cmd 为程序代码和数据分配响应的存储空间。
该文件为矢量跳转表文件,通常是汇编文件(.asm)形式,此文件需要准确的定位在程序的起始地址,其内容是汇编语句中的无条件跳转语句“LB”。
首先进行锁相环、时钟初始化、关闭看门狗。由于API 函数包含具有软件延迟循环的时间关键型代码,这些代码必须执行以满足特定的计时要求。因此,在调用Flash API 函数之前,设备必须以正确的CPU 频率运行。如果设备的输入时钟丢失,PLL 将进入所谓的低电平模式,CPU 将以更低的频率计时,DSP 将被锁死。然后将预留的串口相应的GPIO 管脚配置为SCI 通讯模式,并初始化通讯波特率。初始化CPU 中断并清除中断标志,API 必须保存全局中断之前的状态并在结束后恢复中断如果在擦除、程序在烧写过程中中断,FLASН 被锁死。因此中断使用的代码或数据不能存储在flash 或OTP 中。
将API 函数库从FLASН 区域搬移到RAM 区域中。对API 函数进行初始化,Flash_CallbackPtr 是全局函数指针,用于指定API操作时的函数,在API 算法进行程序擦除、烧写和验证时都需要进行调用。所以首先进行Flash_CallbackPtr 的初始化,将其定义为空。擦除FLASН 将FLASН 区域所有位置1,擦除前要进行预处理,由于烧写过程需要对GPIO 进行初始化,引脚将电平都拉高,所以进行预处理将关掉PWM 等,防止GPIO 电平拉高对系统产生影响。
最后进入程序主循环,检测SCI 通讯时DSP 收到的字符,当检测到秘钥指令时正确时进入烧写函数FlashIAP_UpdataKey,此函数通过指令#pragma CODE_SECTION(FlashIAP_UpdataKey,"ramfuncs")将烧写函数搬移到SARAM 中运行。烧写函数进行。升级程序总体流程图如图3 所示。
TI 公司软件CCS 对整个工程文件进行编译和链接后格式文件COFF,该数据格式复杂,不仅包含了以段的形式组织的代码和数据,而且还包含了文件头、符号表、段地址、初始化段入口等信息,程序中的代码和数据在COFF 文件中是以段的形式存在,通过编译时配置不同的CMD 文件,将这些段分配到不同的DSP 地址空间。该文件格式的模块化结构与实际的内存存储区间不匹配,不能直接用来加载到RAM 或写入FLASН 中,需要将其转换成内存能识别的НEX 数据格式[16]。НEX 文件每段的代码可作如下表示:
:BBAAAATTНННН……НННCC
其中“:”为记录开始的标志;BB 为长度域,站一个字节长度,代表该段数据的数据字节数,通常数据字节数为32 个字节。AAAA 为地址域代表该段第一个数据的地址,随后在此地址基础上增加以储存数据。TT 为类型域,表示该段数据的数据类型。类型域为0X04,代表该行数据为扩展地址,类型域为0X00 时代表该行数据为程序数据,类型域为0X01 时代表该行数据为文件的结尾。 НН 为数据域。CC 该段所有字节相加将模除256 得到的余数取补码作为校验和,占一个字节长度。
程序中Boot_LoaderFunc 函数为接收НEX 文件函数,判断SCI通讯收数为“:”则代表接收开始,只要接收字节数不为零均开始接收,当数据类型为0x00 时进行储存,数据类型为04 代表扩展地址,接收数据类型为01 时代表接收完毕。
在双DSP 伺服控制板上与PC 机的上位机进行实验。通过上位机选择升级主控DSP 的程序时将该GPIO 拉高,CPLD 中逻辑进行判断当相应GPIO 被拉高时,主控DSP 的SCIA 通道和上位机进行交互。设置上位机波特率与程序中SCI 配置相同。要升级时输入字符密钥“u”。将编译生成的НEX 文件发送,经过擦除、烧写和校验过程,返回程序烧写成功。
本实验中主控DSP的用户程序为GPIO60每经过0.1s翻转一次,返回烧写成功后重新上电运行程序,通过示波器观测相应GPIO 的输出波形,可以看出反转周期为0.1s 和预期一致,证明烧写成功。实验测试升级过程,烧写成功标志和测试结果分别如图4 到图6 所示。
采用TMS320F28335 芯片的嵌入式系统在工业控制上应用广泛。本文在双DSP 嵌入式系统硬件上开发了一种基于SCI 的程序升级方法,解决了远距离或者复杂环境下程序无法升级的问题,具有较大的实用性。本方案通过实验测试,运行结果和用户程序一致,表明程序烧写到FLASН 区域,验证了烧写方法的正确性。
图4:上位机确认升级
图5:上位机烧写成功
图6:程序翻转的GPIO 测试波形