DSP学习入门

DSP学习入门,第1张

DSP学习入门:

DSP的特点 :

对于没有使用过DSP的初学者来说,第一个困惑就是DSP其他的嵌入式处理器究竟有什么不同,它和单片机,ARM有什么区别.事实上,DSP也是一种嵌入式处理器,它完全可以完成单片机的功能.。

唯一的重要的区别在于DSP支持单时钟周期的"乘-加"运算.这几乎是所有厂家的DSP芯片的一个共有特征.几乎所有的DSP处理器的指令集中都会有一条MAC指令,这条指令可以把两个 *** 作数从RAM中取出相乘,然后加到一个累加器中,所有这些 *** 作都在一个时钟周期内完成.拥有这样一条指令的处理器就具备了

DSP功能:

具有这条指令就称之为数字信号处理器的原因在于,所有的数字信号处理算法中最为常见的算术 *** 作就是"乘-加".这是因为数字信号处理中大量使用了内积,或称"点积"的运算.无论是FIR滤波,FFT,信号相关,数字混频,下变频.所有这些数字信号处理的运算经常是将输入信号与一个系数表或者与一个本地参考信号相乘然后积分(累加),这就表现为将两个向量(或称序列)进行点积,在编程上就变成将输入的采样放在一个循环buffer里,本地的系数表或参考信号也放在一个buffer里,然后使用两个指针指向这两个buffer.这样就可以在一个loop里面使用一个MAC指令将二者进行点积运算.这样的点积运算对与处理器来说是最快的,因为仅需一个始终周期就可以完成一次乘加.

了解DSP的这一特点后,当我们设计一个嵌入式系统时,首先要考虑处理器所实现的算法中是否有点积运算,即是否要经常进行两个数组的乘加,(记住数字滤波,相关等都表现燃慧州为两个数组的点积)如果有的话,每秒要做多少次,这样就能够决定是否采用DSP,采用多高性能的DSP了.

浮点与定点 :

浮点与定点也是经常是初学者困惑的问题,在选择DSP器件的时候,是采用浮点还是采用定点,如果用定点是16位还是32位?其实这个问题和你的算法所要求的信号的动态范围有关.

定点的计算不过是把一个数据当作整数来处理,通常AD采样来的都是整数,这个数相对于真实的模拟信号有一个刻度因子,大家都知道用一个16位的AD去采样一个0到5V的信号,那么AD输出的整数除以2^16再乘以5V就是对应的电压.在定点DSP中是直接对这个16位的采样进行处理,并不将它转换成以小数表示的电压,因为定点DSP无法以足够的精度表示一个小数,它只能对整数进行计算.

而浮点DSP的优势在于它可以把这个采样得到的整数转换成小数表示的电压,并不损失精度(这个小数用科学记数法来表示),原因在于科学记数法可以表示很大的动态范围的一个信号,以IEEE754浮点数为例,

单精度浮碧或点格式: [31] 1位符号 [30-23]8位指数 [22-00]23位小数

这样的能表示的最小的数是+-2^-149,最大的数是+-(2-2^23)*2^127.动态范围为20*log(最大的数/最小的数)=1667.6dB 这样大的动态范围使得我们在编程的时候几乎不必考虑乘法和累加的溢出,而如果使用定点处理器编程,对计算结果进行舍入和移位则是家常便饭,这在一定程度上会损失是精度.原因在于定点处理处理的信号的动态范围有限,比如16位定点DSP,可以表示整数范围为1-65536,其动态范围为20*log(65536/1)=96dB.对于32定点DSP,动态范围为20*log(2^32/1)=192dB,远小于32位ieee浮点数的1667.6dB,但是,实际上192dB对绝大多数应用所处理的信号已经足够了。

由于AD转换器的位数限制,一般输入信号的动态范围都比较小,但在DSP的信号处理中,由于点积运算会使中间节点信号的动态范围增加,所以主要考虑信号处理流程中中间结果的动态范围,以及算法对中间结果的精度要求,来选择相应的DSP.另外就是浮点的DSP更易于编程,定点DSP编皮蔽程中程序员要不断调整中间结果的P,Q值,实际就是不断对中间结果进行移位调整和舍入.。

DSP与RTOS:

TI的CCS提供BIOS,ADI的VDSP提供VDK,都是基于各自DSP的嵌入式多任务内核.DSP编程可以用单用C,也可以用汇编,或者二者结合,一般软件编译工具都提供了很好的支持.我不想在这里多说BIOS,VDK怎么用这在相应的文档里说的很详细.我想给初学者说说DSP的RTOS原理.用短短几段话说这个复杂的东西也是挑战!

其实DSP的RTOS和基于其他处理器的通用RTOS没什么大的区别,现在几乎人人皆知的uCOSii也很容易移植到DSP上来,只要把寄存器保存与恢复部分和堆栈部分改改就可以.一般在用BIOS和VDK之前,先看看 *** 作系统原理的书比较好.uCOS那本书也不错.

BIOS和VDK其实是一个RTOS内核函数集,DSP的应用程序会和这些函数连接成一个可执行文件.其实实现一个简单的多任务内核并不复杂,首先定义好内核的各种数据结构,然后写一个scheduler函数,功能是从所有就绪任务中(通过查找就绪任务队列或就绪任务表)找出优先级最高的任务,并恢复其执行.然后在此基础上写几个用于任务间通信的函数就可以了,比如event,message box,等等.

RTOS一般采用抢先式的任务调度方式,举例说当任务A等待的资源available的时候,DSP会执行一个任务调度函数scheduler,这个函数会检查当前任务是否比任务A优先级低,如果是的话,就会把它当前挂起,然后把任务A保存在堆栈里寄存器值全部pop到DSP处理器中(这就是所谓的任务现场恢复).接着scheduler还会把从堆栈中取出任务A挂起时的程序执行的地址,pop到PC,使任务A继续执行.这样当前任务就被任务A抢先了.

使用RTOS之后,每个任务都会有一个主函数,这个函数的起始地址就是该任务的入口.一般每个任务的主函数里有一个死循环,这个循环使该任务周期地执行,完成一部分算法模块的功能,其实这个函数跟普通函数没任何区别,类似于C语言中的main函数.一个任务创建的时候,RTOS会把这个函数入口地址压入任务的堆栈中,好象这个函数(任务)刚发生过一次中断一样.一旦这个新创建任务的优先级在就绪队列中是最高的,RTOS就会从其堆栈中d出其入口地址开始执行.

有一个疑问是,不使用RTOS,而是简单使用一个主循环在程序中调用各个函数模块,一样可以实现软件的调度执行.那么,这种常用的方法与使用RTOS相比有什么区别呢?其实,使用主循环的方法不过是一种没有优先级的顺序执行的调度策略而已.这种方法的缺点在于,主循环中调用的各个函数是顺序执行的,那么,即使是一个无关紧要的函数(比如闪烁一个LED),只要他不主动返回,也会一直执行直到结束,这时,如果发生一个重要的事件(比如DMA buffer full 中断),就会得不到及时的响应和处理,只能等到那个闪烁LED的函数执行完毕.这样就使整个DSP处理的优先次序十分不合理.而在使用了RTOS之后,当一个重要的事件发生时,中断处理会进入RTOS,并调用scheduler,这时scheduler 会让处理这一事件的任务抢占DSP处理器(因为它的优先级高).而哪个闪烁LED任务即使晚执行几毫秒都没任何影响.这样整个DSP的调度策略就十分合理。

在采用TI数字信号处理器(DSP)的嵌放式硬件系统开发完成,软件也有CCS2.0集成开发环境下仿真测试通过后,怎样将编译、链接后生成的可执行文件(.Out),经过转换后的十六进制文件(.Hex)写入硬件系统的Flash存储器中,让系统脱机运行,这是许多DSP开发人员及初学者遇到并需要解决的问题。

从JTAG接口对DSP外部Flash的编程方法不只一种。本文以TMS320C6711-150 DSK板为例,介绍“在线仿真状态下”对Flash的编程。

1 Flash存储器的擦除

Flash编程之前,应对Flash进行擦除,使其每个数据位都恢复为1状态,即全FF状态。对Flash的擦除 *** 作需要6个总线周期,总线时序如图1。

 

    从图1可知,各总线周期的 *** 作为:

第一总线周期——向郑喊2AAAH地址的存储单元写入数据55H;

第二总线周期——向2AAAH地址的存储单元写入数据55H;

第三总线周期——向5555H地址的存储单元写入数据80H;

第四总线周期——向5555H地址的存储单元写入数据AAH;

第五总线周期——向2AAAH地址的存储单元写入数据55H;

第六总线周期——向5555H地址的存储单元写入数据10H。

完成上述 *** 作后,Flash存储器被完全擦除,内部数据恢复为初始状态,全为FFH。

在TMS320C6711中,用C语言完成上述 *** 作为:

void erase_flash()

{

*(unsigned volatile char*)FLASH_ADR1=0x00aa

*(unsigned volatile char*)FLASH_ADR2=0x0055

*(unsigned volatile char*)FLASH_ADR1=0x0080

*(unsigned volatile char*)FLASH_ADR1=0x00aa

*(unsigned volatile char*)FLASH_ADR2=0x0055;

*(unsigned volatile char*)FLASH_ADR1=0x0010;

}

在TMS320C6711系统中,Flash所在地址段为CE1空间,其开始地址为0x90000000。这样,其中的FLASH_ADR1、FLASH_ADR2在头文件中被定义为:

#define FLASH_ADR1 0x90005555

#define FLASH_ADR2 0x90002AAA

需要说明的是,在对Flash进行擦除时,应对DSP及EMIF外存储器接口进行初始化,CE1空间定义为8位读写模式。

初始化函数如下:

void c6x11_dsk_init(){ /*DSP和EMIF初始化*/

CSR=0x100/*禁止所有中断*/

IER=1; /*禁止除NMI外的所饥皮有中断*/

ICR=0xffff/*清除所有未完成的中断*/

*(unsigned volatile int *)EMIF_GCR=0x3300

*(unsigned volatile int *)EMIF_CE0=0x30

*(unsigned volatile int*)EMIF_CE1=0xffffff03

*(unsigned volatile int*)EMIF_SDCTRL=0x07227000

*(unsigned volatile int*)EMIF_SDRP=0x61a

*(unsigned volatile int*)EMIF_SDEXT=0x54529

}

2 Flash存储器的编程

对Flash存储器进行字节编程之前,需要对它进行3个周期的编程指令 *** 作,总线时序如图2。

 

从图2可知,各总线周期的 *** 作如下:

第一总线周期——向5555H地址的存储单元写入数据AAH;

第二总线周期——向2AAAH地址的存储单元写入数据55H;

第三总线周期——向5555H地址的存储单元写入数据A0H;

第四总线周期——向地址的存储单元写入编程数据;

……

在TMS320C6711中,用C语言完成上述 *** 作为:

/*---------------------------------------------------------------------*/

/*入口参数:pattern[]:数组,用于存储编喊肢野程数据*/

*/ start_address:所要编程的起始地址指针*/

/* page_size:所要编程的Flash的页面尺寸*/

/*出口参数:无*/

/*---------------------------------------------------------------------*/

void flash_page_prog(unsigned char pattern[],unsigned volatile char *start_address,int page_size){

volatile int i

unsigned volatile char *flash_ptr=start_address

*(unsigned volatile char *)FLASH_ADR1=FLASH_KEY1

*(unsigned volatile char *)FLASH_ADR2=FLASH_KEY2

*(unsigned volatile char *)FLASH_ADR1=FLASH_KEY3

for(i=0i<PAGE_SIZEI++)<P>

*flash_ptr++=pattern[i]

}

其中,FLASH_KEY1、FLASH_KEY2、FLASH_KEY3的定义如下:

#define FLASH_KEY1 0xAA

#define FLASH_KEY2 0x55

#define FLASH_KEY3 0xA0

3 校验和的计算与编程原理

(1)校验和的计算

在程序中,应对Flash编程的正确性进行自动检查,把编程前数据的校验和编程后Flash中读出数据的校验和进行比较:如果相同,则编程成功;如果不相同,则编程失败。需要注意的是,在对Flash 进行编程的过程中,不能用CCS2.0中的“VIEW/MEMORY…”功能看Flash中的编程数据,这样会导致一会地址编程的失败。

其C语言程序如下:

/*----------------------------------------------------------------------*/

/*入口参数:start_address:所要校验的起始地址*/

/* size_in_byte:所要校验的Flash数据字节数*/

/*出口参数:lchecksum:校验和 */

/*----------------------------------------------------------------------*/

int flash_checksum(int start_address,int size_in_byte){

int i

int lchecksum

unsigned volatile char*flash_ptr=(unsigned volatile char*)

start_address

int temp

i=0

lchecksum=0

while(i<SIZE_IN_BYTE-4){<P>

temp=*flash_ptr++

temp&=0xff

lchecksum=lchecksum+temp

i++

}

return lchecksum

}

(2)编程原理

基本原理是:在仿真状态下,在PC机上运行DSP编程软件,由运行的DSP通过JTAG口从PC机上读入待编程的十六进制数据文件,由DSP将其写入到其外部Flash中,即完成用户数据文件的烧写工作。

4 编程数据的读入及编程

编程时,由DSP程序从终端仿真计算机上打开要编程的十六进制文件,从十六进制文件中依次读入编程数据,并由DSP将其写入到其外部Flash中,程序段如下:

while(data_flag=0){

display_count++

if(display_count==DISPLAY_SIZE){

display_count=0

/*printf(".")*/

}

for(i=0i<FLASH_WRITE_SIZEI++){<P>

j=fscanf(hex_fp,“%x”,&data)/*从文件中读入编程数据,每次取一个字节*/

if(j==EOF||j==0){

data_flag=1

break

}

host_buffer[i]=data

checksum+=data

flash_addr+=1

if(falsh_addr>0x90020001){

printf("ERROR:beyond valid flash address!")

}

}

//写入Flash

ptr=(unsigned volatile char *)(flash_addr-0x80)

if(data_flasg==0){

length=FLASH_WRITE_SIXZE

flash_page_prog(host_buffer,ptr,length)

printf("Programming address:%x",flash_addr-0x80)

}

}

注意:所采用的十六进制文件应使用“Hex6x.exe”命令,并在hex.cmd命令文件中使用“-a”参数生成的文件;指定的存储器长度必须能被128 整数(len参数能被128整除)。因为AT29LV010A以扇区为 *** 作单位,每个扇区为128字节,共1024个扇区,其格式如下:

-map hex.map

-a

-image

-zero

-memwidth 8

ROMS

{

FLASH:org=0x90000000,len=0x20000,romwidth=8,files={test.hex}

}

5 仿真运行

将上述程序组成一个完整的程序,经过编译、链接(Project/Build命令)后,使用“File/Load Program...”将编程代码Load到DSP中,运行程序,经过几分种后即编程完毕。

结语

对DSP外部Flash编程虽不是一项关键技术,但它在整个DSP嵌入式系统开发中却有着至关重要的作用。如果开发者在设计之初就掌握了这项技术,就会大大方便系统的调试,缩短开发时间。

京东年货节羊排每满599元减200,速戳!

京东

广告

dsp flash烧写工具

27下载·0评论

2015年7月13日

DSP学习第六篇——Flash 的使用

1.0W阅读·1评论·1点赞

2015年6月2日

JTAG 详解

2.9W阅读·3评论·17点赞

2009年4月21日

ADI DSP的JTAG设计规范(提供JTAG标准设计原理图)

152阅读·0评论·0点赞

2022年12月8日

把DSP TMS320F28XXX的程序段从flash复制到ram中运行

1646阅读·0评论·0点赞

2014年10月22日

DSP外部FLASH烧写的两种方法

77下载·3评论

2013年2月18日

提前备年货,京东超市,哈尔滨红肠年货礼盒,爆款直降,超值!

京东

广告

DSP与FPGA之EMIF接口的调试说明

4896阅读·0评论·7点赞

2021年6月9日

DSP外部Flash存储器在线编程的软硬件设计

2057阅读·0评论·1点赞

2012年6月14日

dsp2812外部FLASH数据读取与发送

52下载·3评论

2013年6月3日

C2000系列DSP生成hex/bin文件并使用串口下载程序的方法

1238阅读·0评论·0点赞

2022年3月17日

让DSP从FLASH启动——step bystep

6419阅读·2评论·1点赞

2013年5月26日

6713_EMIF *** 作外部flash

7728阅读·2评论·16点赞

2016年11月16日

使用JTAG是如何烧写SPI/BPI Flash的?

2711阅读·0评论·5点赞

2021年5月26日

浅谈单片机之JTAG

801阅读·0评论·2点赞

2022年5月26日

TI C2000系列DSP Flash烧写解决方案

53下载·2评论

2010年1月13日

去首页

看看更多热门内容

TI公司为自己的DSP芯片提供了丰富的软硬件开发工具,如仿真器、烧写器、C语言开发环境CCS2.2和C2000等,这些工具为开发DSP软件提供了很大的方便。

根据切割机的工作过程以及工作过程中各种控制任务的需要,将DSP的控制程序主要完成的功能划分为若干模块:插补命令处理模块、辅助控制命令处理模块、切割机状态反馈模块、插补算法模块丛悉、粗插补脉冲发生模块。

插补命令程序的主要任务是读取上位机发送来的对G代码解释所得到的插补命令,调用插补计算模块进行插补计算,并把计算结

果放到ARM缓冲区中供脉冲发生模块使用。

辅助控制命令程清郑散序读取并处理上位机传下来的各种控制命令,如回机械原点、对刀、手摇脉冲发生器的开关以及主轴、冷却泵、润滑泵的开闭等。

状态反馈程序的主要任务是将刀模机当前的状态信息存放到答氏ARM的状态缓冲区中,供上位机读取。插补计算模块则负责具体的插补计算任务。脉冲发生模块进行粗插补计算,将数据发送至ARM的脉冲发生缓冲区中,输出四个进给轴的脉冲。

DSP软件中定义了若干不同的刀模机工作状态:关闭状态、空闲状态、手摇脉冲发生器状态、回机械原点状态、对刀状态、加工状态、紧急停止状态。关闭状态下,运动控制卡将忽略一切命令,只接受控制卡打开命令。打开控制卡后,DSP将打开四个进给轴的伺服驱动器,并转入空闲状态。空闲状态下,刀模机可执行一切控制命令。当进入到手摇脉冲发生器状态时为了避免和G代码等加工指令冲突,将禁止执行插补计算和加工命令。退出手摇脉冲发生状态并转入空闲状态后才可以执行加工命令


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/12352345.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-24
下一篇 2023-05-24

发表评论

登录后才能评论

评论列表(0条)

保存