0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

基于Linux操作系统和ARM处理器实现数据通信系统的设计

电子设计 来源:电子设计工程 作者:孙文康,段义隆, 2021-06-11 16:03 次阅读

作者:孙文康,段义隆,张媛媛

1 引言

基于ARM核心处理器嵌入式系统以其自身资源丰富、功耗低、价格低廉、支持厂商众多的缘故,越来越多地应用在各种需要复杂控制和通信功能的嵌入式系统中。

内核源码开放的Linux与ARM体系处理器相结合,可以发挥Linux系统支持各种协议及存在多进程调度机制的优点,从而使开发周期缩短,扩展性增强。作为数字处理专用电路,DSP数字信号处理能力十分强大,但对诸如任务管理、通信、人机交互等功能的实现较为困难。

如果将这三者结合起来,即由DSP结合采样电路采集并处理信号,由ARM处理器作为平台,运行Linux操作系统,将经过DSP运算的结果发送给用户程序进行进一步处理,然后提供给图形化友好的人机交互环境完成数据分析和网络传输等功能,就会最大限度的发挥三者所长。

2 系统结构

该系统硬件由二部分组成,其中一部分为若干块DSP板,各自独立承接数据采集和信号处理。另一部分为以ARM为核心处理器的CPU板。系统硬件框图如图1所示(仅接口部分)。

3 接口硬件部分设计

3.1 HPI接口简介

HPI接口是TI公司新一代、高性能DSP上用以完成与主机或其他DSP之间数据交换的接口,这里主要介绍实际电路中使用的控制引脚和时序。

HCNTL0和HCNTL1为访问控制选择。用来确定主机(ARM)究竟对TMS320C6711中的哪一个HPI寄存器进行处理。具体功能如表1所列。

HR/W:读写选择控制。为“1”表示是从DSP中读,反之则为写。

HHWIL:半字节定义选择,与HPIC寄存器中的HWOB位进行配合可以选择当前传输的是高半字还是低半字。低电平是第一个半字,高电平是第二个半字。

HCS:选通脉冲(Strobe),与HDS1、HDS2相互配合完成内部信号HSTROBE的生成。逻辑关系如图2所示。

将HDS1、HDS2分别固定为高电平和低电平,这样HCS就和HSTROBE完全一致。

HSTROBE读时序如图3所示。

3.2 接口电路

ARM处理器通过DSP的HPI接口与DSP进行连接的硬件原理如图4所示(以单板DSP为例)。其中SN74LVTH16245为16位(二个8位)双向三态总线收发器,主要起总线驱动和方向控制的作用同时也保证在不对HPI口进行操作时数据总线锁闭。AT91RM9200为Atmel公司生产的ARM9为核心的处理器,其中引脚D0-D15为数据总线,A2-A8为地址总线的一部分,CS3为片选信号线,当ARM对总线地址范围为0x40000 0000~0x4FFF FFFF的外部设备进行操作时,会在该引脚产生一个片选信号。同时该信号控制SN74LVTH16245的使能端,避免在读写其他地址时对HPI端口造成影响。TMS320C6711D是TI公司生产的DSP,每秒可以完成15亿次浮点运算,数据处理功能十分强大。引脚D0-D15为数据总线。其余端口是HPI接口的控制引脚。

4 驱动程序设计

4.1 Linux驱动程序简介

在Linux操作系统下有二种方式将驱动程序装入操作系统内核:一种是直接将驱动程序编译进内核,另外一种是将驱动程序构建为驱动程序模块后采用insmod/rmmod命令将模块加载内核中。由于是在嵌入式系统中进行程序开,所以笔者选用了模块加载方式。这样,在整个程序的调试过程中不必因为修改某处而反复编译整个内核,只需编译驱动程序模块并重新加载。

本例中Linux下的驱动程序主要用来完成文件(Linux把外部设备也认为是文件)的打开、关闭、读、写等操作。也就是对如下结合的填充。

Static struct file_operations fops=

{open:hpi_open,

release:hpi_release,

mmap:hpi_mmap,

};

其中,open和release完成设备的打开和关闭。mmap为内存地址映射操作。因为采用的是模块加载方式,所以还应该加上int init_module(void)和void cleanup_module(void)函数,以完成模块的注册和卸载。

4.2 驱动程序中映射的实现

由于驱动程序的内存空间是在内核空间中,因此首先应解决内核空间与用户空间的交互问题。这里采用最直接的方式将内核空间和用户空间联系起来实现映射,即利用remap_page_range内核函数(通过mmap系统调用实现)。

函数原形如下:

int remap_page_range(unsigned long virt_add,unsigned long phys_add,unsigned long size,pgprot_tprot);

函数的功能是构造用于映射一段物理地址的新页表。函数返回的值通常是0或者一个负的错误码。函数参数的确切含义如下:

virt_add:重映射起始处的用户虚拟地址。phys_add:虚拟地址所映射的物理地址。Size:被重映射的区域的大小。Prot:新VMA(virtual memory area)的“保证(protection)”标志。具体定义在源泉文件/include/linux/mm.h中。系统调用MMAP的程序代码如下:

static int hpi_mmap(struct file *f,struct vm_area_struct *vma)

vma->vm_flags|=VM_WRITE;

if(remap_page_range(vma->vm_start,((0x40000000)),

vma->vm_end-vma->vm_start,(_pgprot (pgprot_val(pgprot_noncached(vma->vm_page_prot))|

(L_PTE_WRITE|L_PTE_DIRTY))))) //进行映射

{return -1;} //映射失败

return 0;

}

结合硬件结构可对函数remap_page_range()分别填充如下参数

remap_page_range(vma->vm_start,((0x40000000)),vma->vm_end-vma->vm_start,(__pgprot(pgprot_val(pgprot_noncached(vma->vm_page_prot)) |(L_PTE_WRITE|L_PTE_DIRTY)))))

其中vma为结合vm_area_struct,在中定义。

应用中需要注意以下字段:unsigned long vm_flags应该使用标志VM_RESERVED,以避免内存管理系统将该VMA交换出去。因为要对DSP写入数据,所以必须使用标志VM_WRITE说明对这一段VMA是允许写入的。pgport_t vm_page_prot指明了对VMA的保护权限。由于利用CS3对DSP的HPI接口进行控制,所以应用pgprot_noncached禁止高速缓冲。 通过mmap的构建就能够将内核空间的数据映射到用户空间去,也就是说可以在用户空间内直接对地址为0x4000_0000的内存空间进行操作,而该段空间正是DSP的HPI接口所对应的地址。

在实际应用中,应对CS3的低电平脉宽加以控制,方法是在初始化模块时对ARM的控制寄存器CSR进行调节。该寄存器的D0-D6确定了ARM外部总线的时钟延时周期,D7为等待周期的使能,D12-D14为数据宽度。具体定义如下:AT91_SYS->EBI_SMC2_CSR=0x00003083,即使用16bit数据宽度,等待周期为3个。当ARM主频为180MHz时,CS3低电平脉宽约为150ns。

4.3 驱动程序的系统调用接口

为对处于总线地址0x4000_0000的DSP板进行操作,首先应用open打开设备,该设备可以通过mknod建立(本例建立的是/dev/hpi)。然后mmap完成映射。

Int dev_hpi_open(str_HPI *ss)

{size_t length=“1024”;

int i;

if((*ss).hpi_number==0)

{

(*ss).hpi_fd=open(“/dev/hpi”,O_RDWR);

}

if((*ss).hpi_fd==-1)return -1;

(*ss).hpi_mmap_start =mmap(NULL,length,PROT_READ|PROT_WRITE,MAP_SHARED,((*ss).hpi_fd),0); //获得映射区内存的起始地址

return 0;

} //dev_hpi_open

mmap的作用是将文件内容映射到内存中。函数的原形及各参数定义如下:

*mmap(void *start,size_length

,int prot,int flags,intfd,off_t offset)

start指向欲对应的内存地址,size-length的含义是要映射的量;prot代表映射区域的保护方式;flag会影响映射区域的各种特性;fd为文件描述符;offtoffset代表文件的偏移量,通常设置为零。

示例程序中的结构体变量ss用来总知各种变量。通过mmap可以获得映射后的内存地址,用(*ss).hpi_mmap_start表示。

一旦获得了这个起始地址,就能对0x4000_0000起始的总线地址进行操作,因为映射已经完成,对(*ss).hpi_mmap_start的操作就是对0x4000_0000起始的总线地址进行操作,而DSP板HPI接口的控制线正是在这个位置。这样就实现了物理地址和用户空间的转换。

4.4 用户程序接口部分

下面以HPI接口读写中最复杂的自增读方式用户程序为例说明用户接口程序的设计过程。要完成自增读的操作,对于HPI一侧,假设采用软件握手的方式。要完成的工作如下:

首先读HPIC以查询其中的HRDY位是否为1,如果为1则表示DSP中数据已经备妥。然后写HPIA以告诉DSP从什么位置开始进行自增读。接着将HPIC的FETCH位置1以刷新写入。再读HPIC以查询其中的HRDY位是否为1,如果为1则表示DSP中数据已经备妥。最后从HPID中读取数据。

对于ARM一侧,要对HPIC、HPID、HPIA寄存器进行读写必须满足HPI接口的定义,具体如下(以自增读为例):

读前半字节(高16位)时,HCNTL0=0、HCNTL1=1、HR/W=1、HHWRL=0。

读后半字节(低16位)时,HCNTL0=0、HCNTL1=1、HR/W=1、HHWRL=0。

从硬件的原理图可知,这些HPI的控制口线分别与ARM的一部分地址总线连接。具体为HCNTL0----A2、HCNTL1----A3、HR/W------A4、HHWIL-----A5。

宏定义过程如下:

#define HPIC_R_F(HPI_VA_BASE)*((unsigned long*)((HPI_VA_BASE)+0x00000004+DSPNUMBER))

//读HPIC第一半字

#define HPIC_R_S(HPI_VA_BASE)*((unsigned long*)((HPI_VA_BASE)+0x0000000C+DSPNUMBER))

//读HPIC第二半字

等等,只要改变在HPI_BA_BASE基础上增加的数字就可以获取对控制口线的操作。 在这里HPI_VA_BASE将由映射得到的用户空间虚拟地址代替,所以如果“自增模式读HPID第一半字”那么就可求满足前文提到的HCNTL0=0、HCNTL1=1、HR/W=1、HHWRL=0,也就是要满足地址位A2=0、A3=1、A4=1、A5=0,所以只要在HPI_VA_BASE的基础上加0x0000_0006就可以了。要注意的是ARM处理器的地址是32位。所以是加上0x0000_0006而不是0x0000_0018。

另外,还有二点需要说明:

通过改变宏定义中的DSPNUMBER常量可以控制地址总线A6、A7、A8。通过这3个总线组合并通过简单地址译码电路就可以完成对多块DSP板的读写。在硬件电路中可以定义为0。

A4(HR/W)同时还用做SN74LVTH16245的方向控制。读的时候A4=1,此时SN74LVTH16245的数据从A-->B;反之,则从B-->A。

下面给出程序中的自增读和注释部分:

int dev_hpi_auto1(str_HPI *ss)

{volatile unsigned long DSP_addr_hign_read_auto;//定义各种中间变量

volatile unsigned long dsp_addr_low_read_auto;

volatile unsigned long dsp_data_hign_read_auto;

volatile unsigned long dsp_data_low_read_auto;

volatile unsigned long dsp_add_temp;

int i;

volatile unsigned long data_length;

//---read hpic----the host polls the HPIC for HRDY=“1”

vol

atile unsigned long polltest;

polltest=HPIC_R_F((*ss).hpi_mmap_start);

while((polltest&0x00000008)!=0x00000008)

{polltest=HPIC_R_F((*ss).hpi_mmap_start);

}

dsp_add_temp=((*ss).hpi_dsp_add);//从应用程序传过来的参数,指明希望从DSP的哪一个地址读起

dsp_addr_low_read_auto=((dsp_add_temp)&0x0000ffff)+((dsp_add_temp)<<16); //完成数据转换

dsp_addr_hign_read_auto=((dsp_add_temp)&0xffff0000)+((dsp_add_temp)>>16);

//---write dsp s addr to HPIA

HPIA_W_F ((*ss).hpi_mmap_start)=(dsp_addr_hign_read_auto);

HPIA_W_S((*ss).hpi_mmap_start)=(dsp_addr_low_read_auto);

//--------write hpic----------to FETCH bit

HPIC_W_F((*ss).hpi_mmap_start)=0xfff8fff8;

HPIC_W_S((*ss).hpi_mmap_start)=0xfff8fff8;

//---read dsp s data from HPID,autoincrement mode

data_length=(*ss).hpi_dsp_data_length;//从应用程序传过来的参数,指明期望读取多少个字

for(i=0;i<=data_length;i++)

{//---read hpic----the host polls the HPIC for HRDY=“1” again

polltest=HPIC_R_F((*ss).hpi_mmap_start);

while((polltest&0x00000008)!=0x00000008)

{polltest=HPIC_R_F((*ss).hpi_mmap_start);

}

dsp_data_hign_read_auto =HPID_R_F_A((*ss).hpi_mmap_start); //读第一个半字。

dsp_data_low_read_auto =HPID_R_S_A((*ss).hpi_mmap_start); //第二个个半字

{(*ss).buffer [(i)]=(dsp_data_hign_read_auto&oxffff0000)+(dsp_data_low_read_auto&0x0000ffff);

//数据拼接,放入结构体,回传给调用的用户程序。

}

}

} //dev_hpi_read_auto(str_HPI *ss)

5 结束语

本文通过一个实例说明了如何实现在Linux操作系统下ARM体系结构的处理器与DSP的数据通信。给出了接口部分的硬件处理和部分驱动程序。

在某款智能仪表的研发过程中,给出一个简单的地址译码电路对二块(或更多)DSP板进行交替读写,并以自增读方式进行操作,当ARM主频为180MHz,DSP主频为125MHz时,对DSP数据的读写速度可以达到每毫秒1k的32位字。

责任编辑:gt

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 处理器
    +关注

    关注

    68

    文章

    18273

    浏览量

    222119
  • dsp
    dsp
    +关注

    关注

    544

    文章

    7682

    浏览量

    344347
  • Linux
    +关注

    关注

    87

    文章

    10990

    浏览量

    206728
收藏 人收藏

    评论

    相关推荐

    SEP3203处理器的FPGA数据通信接口设计

    多的性能(0.89MIPS/MHz),极大地缩短了软件执行时间,提高了系统性能。6 总结本文给出了SEP3203处理器的FPGA数据通信接口设计,限于篇幅,具体的硬件电路和软件源代码未能详细列出。目前,该
    发表于 12-05 10:13

    SEP3203处理器实现FPGA数据通信接口设计

    ARM7TDMI处理器内核,为用户提供了面向移动终端应用的丰富外设、低功耗管理和低成本的外存配置,整个芯片可以运行在75 MHz。数据通信系统使用的主要功能模块如下:20 KB片上零等
    发表于 04-26 07:00

    基于ARM920T平台怎么移植Linux操作系统

    嵌入式Linux的一个热点应用就是将Linux内核移植到一些典型的微控制和微处理器上,提供操作系统层面支持,以
    发表于 09-26 06:36

    ARM与DSP的数据通信有什么方法?

    提供良好的人机交互、任务管理、网络通信等方面功能。因此,发挥DSP和ARM处理器各自的优势,采用ARM+DSP结构的设计方案已成为嵌入式系统
    发表于 10-31 06:17

    无线气象数据通信系统的组成有什么?

    个值得研究的课题。文中基于ARM处理器Linux操作系统平台,借助前端无线传感网络的数据
    发表于 04-06 07:03

    VxWorks操作系统基于ARM处理器的中断怎么处理

    本文通过基于S3C44B0X处理器VxWorks嵌入式操作系统的BSP移植,详细分析了VxWorks操作系统基于ARM处理器的中断
    发表于 04-27 06:28

    如何用ARM和FPGA搭建神经网络处理器通信方案?

    某人工神经网络的FPGA处理器能够对数据进行运算处理,为了实现数据通信操作控制和
    发表于 05-21 06:35

    如何实现ARM体系结构的处理器与DSP的数据通信

    如何实现Linux操作系统ARM体系结构的处理器与DSP的数据通信
    发表于 05-28 06:11

    linux操作系统只能在以arm处理器的pc上运行吗

    linux操作系统只能在以arm处理器的pc上运行吗?可以在英特尔的各种处理器上运行吗?
    发表于 07-27 15:04

    基于ARM的无线气象数据通信系统设计

    为了实现自动气象站无线化、网络化的需要,开发了一种基于ARM、嵌入式Linux和CC2530构建的无线气象数据通信系统。对
    发表于 06-04 15:35 81次下载
    基于<b class='flag-5'>ARM</b>的无线气象<b class='flag-5'>数据通信系统</b>设计

    基于ARM-Linux和单片机的数据通信系统设计

    基于ARM-Linux和单片机的数据通信系统设计
    发表于 01-04 17:03 37次下载

    基于嵌入式Linux和FPGA的数据通信系统设计_陈鑫旺

    基于嵌入式Linux和FPGA的数据通信系统设计_陈鑫旺
    发表于 03-16 10:16 2次下载

    基于ARM-Linux的无线气象数据通信系统的设计与实现

    ,是一个值得研究的课题。 文中基于ARM处理器Linux操作系统平台,借助前端无线传感器网络的数据输入,利用嵌入式Qt的开发优势并设计
    发表于 11-30 08:19 254次阅读
     基于<b class='flag-5'>ARM-Linux</b>的无线气象<b class='flag-5'>数据通信</b><b class='flag-5'>系统</b>的设计与<b class='flag-5'>实现</b>

    基于ARM处理器Linux的无线气象数据通信系统

    文中基于 ARM处理器Linux 操作系统平台,借助前端无线传感器网络的数据输入,利用嵌入式Qt的开发优势并设计
    发表于 03-27 10:46 964次阅读
    基于<b class='flag-5'>ARM</b>微<b class='flag-5'>处理器</b>和<b class='flag-5'>Linux</b>的无线气象<b class='flag-5'>数据通信</b><b class='flag-5'>系统</b>

    基于ARM的无线气象数据通信系统设计

    电子发烧友网站提供《基于ARM的无线气象数据通信系统设计.pdf》资料免费下载
    发表于 10-24 09:48 0次下载
    基于<b class='flag-5'>ARM</b>的无线气象<b class='flag-5'>数据通信系统</b>设计