打印

嵌入式Linux下ARM通过主机接口加载DSP

[复制链接]
727|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
Roses|  楼主 | 2019-3-24 13:44 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
嵌入式Linux下ARM通过主机接口加载DSP



摘要:本文介绍了一种利用嵌入式微控制器AT91RM9200,在嵌入式linux操作系统的环境下,通过主机接口(HPI)来加载DSP程序的设计方案。
关键字:ARM;DSP;linux驱动程序;HPI bootloader

1 引言
       在通信系统的设计中,通常利用DSP强大的计算能力来执行运算量较大的复杂通信算法,但DSP在控制和交互方面不足。而ARM此类32位嵌入式微控制器,具有丰富的接口和灵活的控制功能,能运行嵌入式linux操作系统,可满足控制、人机交互、网络通信等方面的处理需要。有鉴于此,在一款基带信号处理模块的开发中,利用ARM与DSP的优势互补,搭建了一套ARM-DSP双核平台,同时利用DSP的主机接口(HPI)来实现了ARM与DSP之间的高速通信,并在此基础之上,利用ARM来完成对DSP的程序加载,减少了DSP对于外部非易失性存储器的需求,有效的降低了整个系统设计的成本和复杂性。

2硬件设计
        2.1 TMS320VC5416主机接口(HPI)特性
        TMS320VC5416的主机接口(HPI) 是TI公司专门设计的一个接口,使用HPI能大大简化DSP与外部进行数据交互的硬件设计。HPI是一个8位的并行口,用来与主处理器对接。外部主机是HPI的主控者,它可以通过HPI直接访问DSP的存储空间,包括存储器映像寄存器。
HPI提供地址寄存器(HPIA)、数据寄存器(HPID)和控制寄存器(HPIC),由主机直接访问。主机将要访问的存储单元地址写入HPIA,HPI自动将地址所指向的存储单元的值读取到HPID中供主机读取。此外,HPI还支持连续的读取方式,将HCNTL[1..0]控制线置01,可以实现HPI的自增式读写。在这种方式下,HPIA在每读一次后自动增1或者每写一次前自动增1,减少了每次设置HPIA的开销,这种访问方式非常方便,在主机访问DSP片内连续存储单元时一般使用这种方式。

2.2硬件设计实现
          AT91RM9200与TMS320VC5416的连接电路如图1所示 [2] 。从图1可以看出,HPI与主机进行连接时,只需要连接8位的数据线和较少几条的控制线,非常简单方便。


TMS320vc5416在上电后,首先扫描是否进入HPI boot模式,此时HPI的HINT会置低。DSP检查INT2是否为低,若为低则进入HPI boot模式。所以在原理图中,HINT与INT2直连。
    At91rm9200的地址线A2、A3连接HPI的选通信号HCNTL[1..0],负责选通HPIA、HPID和HPIC三个寄存器。A1与HBIL连接,当A1=0时,表明当前传输的是第一字节;当A1=1时,表明当前传输的是第二字节。ARM的片选NCS4与/HCS相连,将HPI挂在ARM的0x50000000至0x5FFFFFFF的地址段。
    此外,HPI的HR/W信号,用来指示读写,At91rm9200无对应信号,用A4替代。当A4=0,代表主机写HPI,反之代表读HPI。在HPI传输过程中,所有的信号都是在/HDS1和/HDS2的下降沿采样,At91rm9200采用CFOE和CFWE与其对接。

3 HPI通信接口的linux驱动程序设计
HPI在通信过程中是At91rm9200的一个外围设备。At91rm9200运行的是ARM-LINUX的嵌入式操作系统,所以必须设计HPI的linux驱动程序。
3.1 linux驱动程序简介
在linux下,设备被分为字符设备,块设备和网络设备三种,所有设备都看成是文件。因此对设备的操作,就如同对普通文件的操作一样,通过系统调用来打开、读取、写入、关闭设备。
Linux驱动程序的实质是一组函数的集合,它包含设备服务子程序和中断处理程序。每个设备服务子程序只处理一种设备。设备程序利用结构file_operations与文件系统联系起来。驱动程序的编写,实质上是对open、close、read、write、mmap等各种操作的填充。
3.2 HPI驱动程序设计
HPI驱动程序具体要实现的文件操作如下:
static struct file_operations hpi_fops=
{
open:  hpi_open,
mmap:  hpi_mmap,
release:   hpi_release,
};
依据硬件电路的设计,HPI挂在At91rm92000的x50000000至0x5FFFFFFF的地址段。首先对物理地址定义:
#define HPI_BASE  0x50000000
在Linux下,用户程序是无法直接操作物理地址的。而Linux通过内存映像机制来提供用户程序对内存直接访问的能力。内存映像的意思是把内核中特定部分的内存空间映射到用户级程序的内存空间去。在mmap系统调用中,利用remap_page_range内核函数 [3] ,构造一段以HPI_BASE为起始物理地址的新页表。此后运行于用户空间的程序就可以直接操作HPI物理地址。

4 HPI 加载程序设计
       DSP bootloader[4]的功能就是在上电时将用户程序从外部存储器搬移到内部的程序空间去运行。在TMS320vc5416的片内ROM固化了TI公司的bootloader程序。在上电后,按顺序对每种模式进行轮询,如果符合条件就将进入某种boot模式。
首先轮询的是HPI boot模式,bootloader将数据存储空间的007Eh 和 007Fh单元清零,将HINT置低,根据之前所述的硬件电路,INT2与HINT捆绑在一起,所以上电后TMS320VC5416就进入了HPI boot模式。AT91RM9200通过HPI接口下载程序到TMS320VC5416的片内RAM中。在此过程中,TMS320VC5416不停的查询007Eh 和 007Fh单元的值是否变化。当AT91RM9200将程序加载完毕后,再附加2个传送周期,在007Eh 和 007Fh单元写入适当的值。其中007Fh中的值将作为程序的入口地址。TMS320vc5416查询到007Fh中的这个非零值,就将它作为入口地址,跳转执行加载的程序。
通过HPI加载的DSP程序只能包含程序本身,不能含有如段的大小和寄存器的值等其他额外信息。DSP程序在CCS中经过编译生成的.out文件,再用TI公司提供的hex500.exe将.out文件转化成.hex文件,其中包含了文件存储地址、文件长度等信息。从.hex文件中提取16进制代码。在HPI 加载程序中,将提取出的这段16进制代码定义为一个数组。
/**************  DSP程序的16进制代码  **************/
constant unsigned int code[length]={ 77 18 0C 00 F2 73 00 FC F4 95 F4 95 F4 EB F4 95 F4 95 F4 95 08 F4 95 F7 BD F4 95 48 1D F0 30 FF F7 F4 95 F4 95 F4 95 F4 95 80………… };
在HPI加载程序中,通过mmap系统调用, hpi_start=mmap(); 可以获得物理地址HPI_BASE的虚拟地址hpi_start,此后对hpi_start的操作,即相当于对物理地址HPI_BASE的操作。这样在用户空间就可以直接对HPI接口对应的物理地址进行操作。HPI加载程序的主体部分如下:
首先是读写地址的定义:
/************    写HPIC    ************/
#define HPIC_W_F(HPI_START) *(UNIT8*)(HPI_START + 0x0)  
#define HPIC_W_S(HPI_START) *(UNIT8*)(HPI_START + 0x2)   
/************    写HPIA    ************/
#define HPIA_W_F(HPI_START) *(UNIT8*)(HPI_START + 0x8)
#define HPIA_W_S(HPI_START) *(UNIT8*)(HPI_START + 0xA)
/************    写HPID    ************/
#define HPID_A_W_F(HPI_START) *(UNIT8*)(HPI_START + 0xC)
#define HPID_A_W_S(HPI_START) *(UNIT8*)(HPI_START + 0xE)
/************ 自增式写HPID ************/
#define HPID_A_W_F(HPI_START) *(UNIT8*)(HPI_START + 0x4)
#define HPID_A_W_S(HPI_START) *(UNIT8*)(HPI_START + 0x6)
/**********  将DSP程序的十六进制代码自增式写入DSP的片内RAM  *************/
for(i=0;i<length;i++)
  {
  HPID_A_R_F(hpi_start) =code>>8;  //将DSP可执行代码自增写入RAM
  HPID_A_R_S(hpi_start) =code;
   }
/**********  传送完毕,将程序入口地址写入007E和007Fh  **********/
      HPIA_W_F(hpi_start)=0x00;
      HPIA_W_S(hpi_start)=0x7e;
      HPID_W_F(hpi_start)=0x00;
      HPID_W_S(hpi_start)=0x00;
      HPIA_W_F(hpi_start)=0x00;
      HPIA_W_S(hpi_start)=0x7f;
      HPID_W_F(hpi_start)=0x00;
      HPID_W_S(hpi_start)=0x80;

5 结论
      在许多嵌入式通信应用场合,我们既需要ARM强大的控制功能和在人机交互、网络应用等方面的优势,又必须依靠DSP的强大运算功能完成复杂的通信算法。经多次测试,本设计已经稳定的运行在RFID(射频识别)阅读器的基带信号处理模块中。
在此次应用的基础上,还可以对HPI的加载程序做进一步的功能扩展,使其支持TCP/IP网络通信协议,利用internet远程对DSP进行程序加载,从而轻松实现对基带信号处理模块的固件升级,支持新的射频识别协议和标准。

创新点:提出了通过ARM来加载DSP程序的方法,充分利用DSP本身的接口资源(HPI),省去了一般DSP最小系统中所需的flash,简化了硬件设计,使整个系统设计更加紧凑,并加快了系统初始化速度,提高了系统的稳定性。

使用特权

评论回复

相关帖子

沙发
Roses|  楼主 | 2019-3-24 13:44 | 只看该作者
嵌入式Linux下ARM通过主机接口加载DSP

文档1.pdf

160.39 KB

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

709

主题

1023

帖子

7

粉丝