视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
DSP程序在线升级报告(本人觉得最给力的资料)
2025-09-27 11:17:50 责编:小OO
文档
DSP程序在线升级

唐俊松

tangjunsong@zju.edu.cn

2015/12/04

1. 引言

一般而言,DSP程序更新是在CCS环境下通过JTAG接口来实现的。但JTAG烧写程序只能实现一对一烧写(即电脑到DSP),且不能远距离烧写程序。而当产品发布后或需要同时升级多个DSP程序时,通过JTAG烧写程序则很难实现。

在线程序升级的主要思想是通过串口通信更新程序,通过串口通信可实现程序远程升级且可同时实现对多个DSP的程序更新,这有效地解决了JTAG烧写程序所存在的弊端。

图1.通过不同方式实现DSP程序更新

2.  程序在线升级的基本思想

基于串口通信的程序在线升级功能框图如图2.1所示,底层程序(Prog Local)和应用程序(Prog App)分别由两个的CCS Project产生。

底层程序(Prog Local)是产品发布前通过JTAG烧写固化在DSP指定Flash空间中的程序,不允许用户修改和擦除,主要用于实现与上位机的通信,同时在需要升级程序时将上位机发送过来的程序代码烧写到FLASH中。

应用程序(Prog App)是可以更新的程序。通过CCS编译产生程序代码文件(hex),然后通过RS232通信将程序代码发送到DSP,继而由底层程序(Prog Local)将应用程序代码烧写到应用程序所对应FLSH空间(Prog App)中。

图2.1   DSP程序在线升级功能框图

在线升级程序流程图如图2.2所示。 DSP上电复位后先运行底层程序,在底层程序中判断是否需要升级,如不需要升级,则跳转到应用程序执行。如需要升级,则擦除应用程序对应FLASH区,并将升级代码写入到应用程序FLASH区中。

图2.2  DSP程序更新流程图

3. 在线程序升级的具体实现

3.1  FLASH分配

要实现程序在线升级,必须使底层程序和应用程序相互。如图2.1所示,本项目将底层程序(Local Program)配置在FLASH A中,应用程序(Application Program)配置在FLASH E中,从而实现底层程序与应用程序的。实现程序相互需通过配置cmd文件完成,具体配置方法见附录1。

图3.1  DSP FLASH分区示意图

3. 2  应用程序更新代码产生

需要更新的应用程序代码是通过CCS Project A编译产生的,但CCS编译生成的是具有模块化格式的目标文件(.out文件),该文件中的代码和数据分别存放在不同的段中,因而不能直接用来烧写Flash,需将其转换为能识别的数据格式(hex文件)(hex数据文件格式详见附录4)。生成hex文件后,通过上位机读取hex文件数据,并将数据通过RS232通信发送至DSP。

CCS自带工具hex2000.exe可实现.out文件到.hex文件的转换。(转换方法见附录6)

图3.2  应用程序代码产生方法

3.3  底层程序(Local Prog)

底层程序主要实现两个功能:(1)与上位机通信;(2)升级时,将串口接收到的数据烧写至Flash的指定区域。

底层程序主要实现以下功能,其流程图如右图所示:

(1)与上位机通信,判断是否升级

DSP上电复位后与上位机通信,判断是否需要升级。若上位机发送的是升级命令,则跳转到底层程序中升级部分执行;否则,跳转到原有的应用程序处执行。

(2)从上位机接受程序代码并校验

接收上位机发送的应用程序代码并保存到DSP指定内存中(RAM 区),(如何将数据保存到指定内存,详见附录2)。与此同时,需校验接收数据是否准确。

(3)烧写程序的搬移

由于DSP不支持对FLASH烧写的同时在FLASH中运行程序,因此负责烧写Flash的这部分程序应搬移至片内RAM执行。(如何实现程序搬移,详见附录3)

(4)烧写程序代码

搬移结束后,将之前RAM中接受到的程序代码烧写至指定Flash扇区,该步骤通过调用Flash28335_API库函数完成(Flash28335_API的使用请看附件中FLASH_API文档)。

4. 总结

   实现程序在线升级的主要难点是如何实现底层程序和应用程序相互,以及如何通过CCS产生需要更新的应用代码。本报告首先介绍了DSP程序在线升级的主要思想,然后对程序在线升级的实现方法作了简单介绍,并在附录中给出了具体实现过程中可能会遇到的问题及解决办法。

附录1  底层程序和应用程序cmd配置

要实现如图4.1所示的FLASH分配,须通过配置底层程序和应用程序cmd文件完成。其中底层程序对应CCS Project L,配置其cmd文件使其程序分配在FLASH A区;应用程序对应CCS Project A,配置其cmd文件使其程序分配在FLASH E区。

图4.1  DSP FLASH分区示意图

1.1 底层程序cmd配置

DSP F28335上电复位后,当硬件配置为FLASH启动时,程序指针将跳转到Flash的0x33FFF6处(F28335启动过程,详见附录5)。由于这个地址是固定的,因此底层程序必须烧写在以这个地址为起始地址的空间内,即底层程序cmd配置应为:

MEMORY

{

PAGE 0 :

   BEGIN: origin = 0x33FFF6, length = 0x000002   /* Boot to FLASH will go here     */

...

}

SECTIONS

{...

codestart           : > BEGIN       PAGE = 0

...}

与此同时,底层程序所有程序代码段应全部烧写到FLASH A中:

MEMORY

{

PAGE 0 :

 FLASHA      : origin = 0x338000, length = 0x007F80     /* on-chip FLASH */

...

}

SECTIONS

{...

.cinit : > FLASHA PAGE = 0

.pinit : > FLASHA, PAGE = 0

.text : > FLASHA PAGE = 0

...}

1.2  应用程序cmd配置

采用绝对地址跳转实现由底层程序到应用程序的跳转,为保证程序正常执行,其跳转地址必须固定,且该地址在应用程序中的位置必须固定。将应用程序的首地址作为跳转地址,即跳转地址固定为FLASH E的起始地址:0x318000,如图4.2所示。

图4.2  应用程序FLASH示意图

采用绝对地址跳转实现从底层程序跳转到应用程序。跳转指令为:

#define Jump_App_Program (void(*)(void))0x318000  /*use the Flash E sector to save the application program */

(*Jump_App_Program)(); /*Jump to the application program */

同时应配置Prog App 的程序起始地址为从(FLASH E)起始地址0x318000开始,对应CMD配置为:

MEMORY

{

PAGE 0 :

 BEGIN  : origin = 0x318000, length = 0x000002  /*0x318000 is the start address of FLASH E */

...

}

SECTIONS

{...

codestart           : > BEGIN       PAGE = 0  /* codestart is the start address of the program*/

...}

与此同时,底层程序所有程序代码段应全部烧写到FLASH E中:

MEMORY

{

PAGE 0 :

 FLASHE      : origin = 0x318002, length = 0x007F80     /* on-chip FLASH */

...

}

SECTIONS

{...

.cinit : > FLASHE      PAGE = 0

.pinit : > FLASHE,     PAGE = 0

.text : > FLASHE      PAGE = 0

...}

附录2: 如何将程序和变量放到指定位置

在CCS编程中,如果我们不指定变量的存放位置,编译器会自动的给变量分配一个位置,但是如果有时候需要把变量放在一个特定的空间内,我们应该如何操作呢,CCS提供了如下的两个指令:

#pragma CODE_SECTION

#pragma DATA_SECTION

其中DATA_SECTION是针对数据空间的,CODE_SECTION是针对程序空间的,具体的使用办法是:

#pragma DATA_SECTION(buffer, ”DATA_sect”)

char buffer[512]; //buffer为一数组

#pragma CODE_SECTION(fun, ”CODE_sect”)

Int fun();  //fun 为任意函数

与此同时,在CMD文件中为DATA_sect、CODE_sect开辟空间:

DATA_sect :  >PAGE = 1 

CODE_sec PAGE

附录3:如何将FALSH中程序搬移到RAM中运行

CCS中经常会遇到如下语句:

MemCopy(&RamfuncsLoadStart, &RamfuncsLoadEnd, &RamfuncsRunStart)

它的作用是将ramfuncs段复制到内存中然后运行。

CMD文件中ramfuncs的定义如下;

ramfuncs   : LOAD = FLASHD, 

                         RUN = RAML0, 

                         LOAD_START(_RamfuncsLoadStart),

                         LOAD_END(_RamfuncsLoadEnd),

                         RUN_START(_RamfuncsRunStart),

                         PAGE = 0

第1行表示该段的装载在PAGA0的FLASHD中

第2行表示该段的运行地址在PAGE0的RAML0中

LOAD_ START(_RamfuncsLoadStart)令编译器创建了一个变量RamfuncsLoadStart,该变量指向段ramfuncs的装载地址的首地址(LOAD_ START为编译伪指令,请见CCS的帮助文档);

LOAD_ START(_RamfuncsLoadEnd)令编译器创建了一个变量RamfuncsLoadEnd,该变量指向段ramfuncs的装载地址的末地址(LOAD_ END为编译伪指令,请见CCS的帮助文档);

LOAD_ START(_RamfuncsRunStart)令编译器创建了一个变量RamfuncsRunStart,该变量指向段ramfuncs的运行地址的首地址(LOAD_ START为编译伪指令,请见CCS的帮助文档);

从第1和2行可以看出,段ramfuncs中的函数DSP28x_usDelay()的装载地址和运行地址是不同的,本程序中装载在Flash的块 FLASHD中,而在SARAM L0中运行,这只是目标,实际运行时DSP并不会自动将Flash中的代码拷贝到SARAM中,因此需要手动添加代码来完成。

在C函数中,为了使用变量RamfuncsLoadStart、RamfuncsLoadEnd和RamfuncsRunStart,必须先声明,本工程在文件DSP2833x_GlobalPrototypes.h中做了如下声明:

extern Uint16 RamfuncsLoadStart;

extern Uint16 RamfuncsLoadEnd;

extern Uint16 RamfuncsRunStart;

然后就可以使用了。在Main.c中,使用MemCopy()函数将段ramfuncs中的函数DSP28x_usDelay()的代码从装载地址 RamfuncsLoadStart—RamfuncsLoadEnd拷贝到RamfuncsRunStart开始的SARAM空间中。之后在程序运行 时,只要调用DSP28x_usDelay()函数,都会自动地指向SARAM中相应的函数入口地址,这一点是自动完成的。MemCopy()函数原型在 MemCopy.c中,DSP2833x_GlobalPrototypes.h声明。

附录4:十六进制数据流文件(Hex文件)

十六进制数据流(Hex)是规律性极强的一种文件格式,该类文件是由‘行’组成的,一行即是一个单元。

Hex文件的‘行’单元由以下6部分组成:

:  LL  AAAA  RR  DD…DD  CC

1行的开端 : ‘ : ’ 标志一个新的‘行’的开端;

2数据长度 : ‘LL’ 表示后面DDDD的长度(单位Byte);

3存储地址 : ‘AAAA’ 表十六位地址,当记录类型是‘04’时表高十六位地址,记录类型是‘00’时表低十六位地址;

4记录类型 : ‘RR’ 共有‘00’‘01’和‘04’三种记录类型;

‘00’:表该行携带数据信息

‘01’:表Hex文件结束

‘04’:表高十六位地址有变化

5数据内容 : ‘DDDD’ 是数据内容;

6校验内容 : ‘CC’ 是该行除去 ‘ : ’ 和 ‘CC’ 之外的数据的校验值。校验规律是:所有值加和后取反。

附录5:TMS320F28335-启动过程 

1.DSP reset后运行的起始地址是多少?

0x3FFFC0

2.仿真器烧写程序的步骤是?

根据cmd文件把程序烧到指定位置,然后执行。

3.DSP的Flash启动过程是什么?

首先假设硬件配置GPIO84~87上拉为1,即处于Flash启动过程。当DSP复位后,会从复位向量0x3FFFC0处取得复位向量,并跳转到 InitBoot处开始执行,InitBoot会读GPIO84~87的值,当值全为1后,判断为Flash启动方式。然后会跳到0x33FFF6处执行。在 CCS5.2工程的cmd文件中有如下代码:

MEMORY

{

PAGE 0 :

   BEGIN       : origin = 0x33FFF6, length = 0x000002     /* Boot to M0 will go here                      */

...

}

SECTIONS

{...

codestart           : > BEGIN       PAGE = 0

...}

即表示把codestart段放到0x33FFF6位置处,文件“DSP2833x_CodeStartBranch.asm”中有 codestart段的定义,实际上codestart段只是包含了一个跳转指令,是程序跳转到_c_int00处,_c_int00在boot.asm in RTS library中有定义,_c_int00的代码最终会调用c的main函数,之后就是main函数的执行。

附录6:Hex2000使用:

CCS软件默认生成的是.out格式的文件,而很多应用场合往往需要的是纯二进制代码,TI提供了一个小工具HEX2000能帮助实现格式的转化,具体的说明还是请参看TMS320C28x Assembly Language Tools手册。这里简单的说明下该工具的使用:

1.hex2000是在ccs安装目录下的。

2.hex2000 转化工具支持多种输出格式,至于用那种格式,通常是由所用的烧写器来决定的。常见的有:

Ascii hex: 这种格式其实是会将所有的code转化为字符形式,比如本来的0x3132, 它就用'3' '1' '3' '2'来表示,当中有空格,这种格式比较使用通过串口等工具来更新数据。

binary:-b 选项,纯二进制格式。它还支持intel,motorola-s, ti-tagged, tektronix等格式。

3.hex2000 有memory width的概念,输入文件的(--memwidth),一般来说都是16bit的(因为编译出来就是这样的),输出格式--romwidth,可以指定 为8或者16(有些格式不支持16)。如果输入16,输出是8,hex工具会自动生成两个文件,一个放低8位的数据,一个放高8位的数据。当然你也可以自 己制定这两个文件的名字。

4. -image选项:打开该选项,系统会产生一个和你在roms中指定大小一样的文件,不足部分用fill的值来替代,多余部分被忽略。

6.hex2000工具,可以通过命令行通过一句话将所有的参数和输入输出写在一起来运行,比如:hex2000 -t firmware -o firm.lsb -o firm.msb

也可以通过ROMS指令写一个脚本文件,这种脚本文件的好处是可以编写比较复杂的要求,而且易于修改。

hex2000转换的具体方法见附件。下载本文

显示全文
专题