历史上的今天
返回首页

历史上的今天

今天是:2025年12月21日(星期日)

2022年12月21日 | 通过mmap方式应用程序在Linux下访问物理地址提高实时性

2022-12-21 来源:elecfans

前言

按照Linux分层驱动思想,外设驱动与主机控制器的驱动不相关,主机控制器的驱动不关心外设,而外设驱动也不关心主机,外设访问核心层的通用应用程序接口进行数据传输,主机和外设之间可以进行任意的组合。这样思想要求应用程序不应当直接访问物理地址,而是应当通过驱动程序的调用来实现,以便保持应用程序的可移植性,操作访问的统一性,应用程序利用系统的统一调用接口访问外设,如使用write(),read()等函数进行实际的外设读写控制。应用程序通过调用接口进入内核函数后,内核利用copy_from_user()获得应用层数据,内核驱动程序也通过分层最终执行物理访问,之后把获得的数据用copy_to_user()回传给应用程序的调用者。由于驱动对外需要有个统一接口,所以定义了一些结构体,链表等机制,以便让应用程序操作简单化,数据在内核一应用之间的复制,填充结构体等都需要时间开销,有时按这种标准调用方式,因为操作时间过长,无法完成设计目的。


操作效率评估

我们的一个项目中,系统由FPGA和ARM11结合为核心控制器,其中FPGA连接外部高速ADC、DAC和RF器件在ARM11的控制下,实现GB18000-6C标准的UHF RFID读写控制状态机。FPGA与ARM11的接口采用SPI,其中ARM11选用三星S3C6410,作为SPI的主机,FPGA作为SPI的从机,受S3C6410的控制。在本系统中,SPI接口充当ARM11和FPGA交互的桥梁,ARM11的命令和动作参数传给FPGA并启动FPGA处理状态机,FPGA动作的结果也通过SPI回传给ARM11,两者之间的通讯效率在系统中需要重点关注。


评估通讯接口时,利用三星提供的SPI驱动函数,系统运行在533MHz,SPI时钟配置为16MHz,程序在linux3.0环境下通过read/write进行操作,为了评估效率,另外采用一个GPIO输出脉冲指示操作过程,试验结果显示效率非常低下,从应用层执行write代码开始到SPI端口输出时钟,延时长达72μs,SPI操作之后,再回到应用层的下一个语句也延时42μs,对于比较少的数据传输情况,附加的额外等待时间远远长于实际传输有效时间,从前面数据看出,通过标准库调用严重影响系统性能,没法满足系统需求。通过查看驱动程序的源代码,可以发现因为驱动程序层层封装,并且包含应用层到内核的copy_from_user()和内核到应用层的copy_to_user()两次数据搬移,导致执行效率很低。为了提高数据交互效率,就要设法绕开数据搬移等时间开销,最好能直接操作寄存器,虽然这种想法与Linux分层驱动思想不相符合,但是在嵌入式系统中,有时需要高的执行效率,如果利用系统一些特定函数,实现高效率的数据交互从而完成设计目标是有必要和可能的。


linux存在名为mmap的函数,能把物理地址映射为虚拟地址,并且这个函数能直接在应用程序中直接调用而不是仅仅属于内核调用的函数,这样在应用层直接操作S3C6410的物理外设成为可能。考虑到在特定的嵌入式系统中,特定外设的使用可以由程序控制,这样可以简化共享设备的互斥保护,进一步减少代码量,提高了访问效率。


mmap函数调用实例

mmap函数作用是将物理地址映射至用户空间。下面是函数的参数简单说明

void* mmap(void * addr, size_t len, int prot, int flags, int fd, off_t offset);

addr: 指定文件应被映射到进程空间的起始地址

len: 映射到用户空间的字节数

prot: 指定被映射空间的访问权限,

flags: 由以下几个常值指定:

fd: 映射到用户空间的文件的描述符

offset: 被映射内存区在文件中的偏移值该函数映射文件描述符

通过这个函数,我们可以在应用层访问对应物理地址正确映射后的虚拟地址,这个函数使我们在应用层也具有对任意物理地址的操作权限,下面代码配置S3C6410的SPI0,因为使用mmap映射,所以不论内核是否带有SPI驱动都不影响我们使用SPI0,但是因为本程序需要对比研究标准驱动方式与直接存储器访问方式的执行差异,所以在内核中编译了标准SPI的驱动程序。由于S3C6410多数脚都有复用功能,为了使SPI0正确工作,还需要配置相关对应的GPIO为SPI功能(实际上因为我们编译的内核带有SPI0的驱动,内核程序已经完成了SPI的初始化,有的内核没有编译SPI,所以下面还是完整配置了SPI,供参考),同时为了观察研究SPI的执行效率,我们程序还对其他GPIO做了配置以便输出脉冲,通过示波器来评估观察。另外我们还使用若干时间标志来记录操作过程时间,对于在没有示波器的情况下也能评估执行时间。


下面是测试程序代码以及测试过程的示波器记录抓图。

#include “test.h”

void Init_FPGA_SPI(){ //配置SPI端口

int fbb;

fbb=open(“/dev/mem”,O_RDWR | O_SYNC);

map_base=(char *)mmap(0,4096,PROT_READ|PROT_WRITE,MAP_SHARED,fbb,0x7f00b000);

*(volaTIle unsigned int *)(map_base+0x04)=0x00000101; //CLK=16.625MHz

*(volaTIle unsigned int *)(map_base+0x08)=0x00000000;

*(volaTIle unsigned int *)(map_base+0x0c)=0x00000002;

*(volaTIle unsigned int *)(map_base)=0x00000003;

FPGA_RUN=map_base+0x18;

map_base=(char *)mmap(0,4096,PROT_READ|PROT_WRITE,MAP_SHARED,fbb,0x7f008000);

GPC=map_base+0x40; //配置端口复用功能为SPI

map_GPC=*(volatile unsigned int *)(GPC+4);

*(volatile unsigned int *)(GPC)=0x12201222;

GPC+=4;

virt_addr2=map_base+0x824;//配置观察IO

GLEDstate=*(volatile unsigned int *)(virt_addr2);

}

void Init_Timer(){ //添加加配置1微秒时基定时器

int fbb;

unsigned int temp;

fbb=open(“/dev/mem”,O_RDWR | O_SYNC);

map_base=(char *)mmap(0,4096,PROT_READ|PROT_WRITE,MAP_SHARED,fbb,0x7f006000);

…………………… 篇幅原因略去部分次要代码

MYSYSTICK=map_base+0x14;

}

void SPI_init(){

bits=8;

speed = 16625000;

trr.len =20;

trr.delay_usecs = 0;

trr.speed_hz = speed;

trr.bits_per_word = bits;

fspi = open(“/dev/spidev0.0”, O_RDWR);

ioctl(fspi, SPI_IOC_RD_MODE, &mode);

ioctl(fspi, SPI_IOC_WR_MODE, &mode);

}

__inline unsigned int GETSYSCLK(){

return(*(volatile unsigned int *)(MYSYSTICK));

}

__inline void CSFPGAL(){

map_GPC&=0xfffffff7;

*(volatile unsigned int *)(GPC)=map_GPC;

}

__inline void CSFPGAH(){

map_GPC|=0x00000008;

*(volatile unsigned int *)(GPC)=map_GPC;

}

void test(){

GLEDstate&=0xfffffffe;

*(volatile unsigned int *)(virt_addr2)=GLEDstate;//产生GPIO负跳变

starttime2=GETSYSCLK();

*(volatile unsigned int *)(FPGA_RUN-0x0c)=0x00;

*(volatile unsigned int *)(FPGA_RUN-0x18)=0x23;

*(volatile unsigned int *)(FPGA_RUN-0x18)=0x03;

CSFPGAL();

*(volatile unsigned int *)(FPGA_RUN)=tx[0];

*(volatile unsigned int *)(FPGA_RUN)=tx[1];

*(volatile unsigned int *)(FPGA_RUN)=tx[2];

*(volatile unsigned int *)(FPGA_RUN)=tx[3];

*(volatile unsigned int *)(FPGA_RUN)=tx[4];

while (((*(volatile unsigned int *)(FPGA_RUN-4)&0xfe000)》》13)2000000){ //2000ms测试一次

waittime=GETSYSCLK();

test();

}

}

}

图1示波器截图添加了一些时间信息以便对应代码注释说明,对应于代码mmap方式和标准驱动调用方式产生了两组SCK时钟,GPIO观察脚显示第一次SPI访问消耗5μs,第二次访问消耗114μs,其中真正操作SPI的时间也就4μs不到,其它时间消耗在系统应用层到内核两次双向的数据拷贝以及为了统一对外接口所做的数据结构配置等方面,由此对比可以看出两种方式访问效率上的巨大差异。

通过mmap方式应用程序在Linux下访问物理地址提高实时性

图 1

结语

通过mmap方式应用程序在Linux下操作硬件寄存器,适合于关注高效率的访问场合,在嵌入式应用中,我们既能够获得使用操作系统管理任务和丰富开源驱动库的好处,同时又能在局部提升处理效率,提高处理数据的实时性。


推荐阅读

史海拾趣

科通(COMTEK)公司的发展小趣事

面对快速变化的电子行业市场,科通技术始终坚持以技术创新为驱动,不断推动公司的转型升级。公司加大在研发方面的投入,积极引进先进的技术和设备,提升产品的技术含量和附加值。同时,科通技术还不断拓展业务领域,从单一的元器件分销逐渐发展到提供全方位的技术整合方案和应用方案,为客户提供更加全面、专业的服务。

广东爱晟电子(exsense)公司的发展小趣事

面对日益激烈的市场竞争和不断变化的市场需求,爱晟电子始终坚持以创新驱动发展。公司不断投入研发资金,加强研发团队的建设,推动技术的不断进步和创新。同时,公司还积极探索新的应用场景和市场领域,为未来的发展奠定了坚实的基础。这些努力使得爱晟电子在电子行业中保持了持续的发展势头和竞争力。

Aptiv公司的发展小趣事

Aptiv一直秉持开放合作的理念,积极与产业链上下游企业开展创新合作。公司与多家科技公司、研究机构以及高校建立了战略合作关系,共同推动自动驾驶技术的研发和应用。通过共享资源、优势互补,Aptiv不仅加快了自身的发展步伐,还为整个电子行业的进步做出了积极贡献。

启珑(CHIPLON)公司的发展小趣事

Aptiv公司在电子行业中以其领先的技术实力著称。早在1995年,公司便成立了自动驾驶研究实验室,开始探索自动驾驶技术的可能性。经过多年的研发与试验,Aptiv在自动驾驶领域取得了显著的突破。2004年,公司首次在内华达州成功测试了自动驾驶汽车,获得了州政府的批准,这标志着Aptiv在自动驾驶技术上迈出了坚实的步伐。此后,Aptiv不断推动自动驾驶技术的商业化进程,为全球汽车行业带来了新的发展机遇。

AEC Design公司的发展小趣事
某电子行业的AEC Design公司凭借其独特的技术创新能力,成功开发出一款具有颠覆性的新产品。这款产品不仅满足了市场的迫切需求,还凭借其卓越的性能和用户体验赢得了消费者的广泛好评。随着产品的热销,公司的知名度和市场份额迅速提升,为公司的持续发展奠定了坚实基础。
First Sensor公司的发展小趣事
某电子行业的AEC Design公司凭借其独特的技术创新能力,成功开发出一款具有颠覆性的新产品。这款产品不仅满足了市场的迫切需求,还凭借其卓越的性能和用户体验赢得了消费者的广泛好评。随着产品的热销,公司的知名度和市场份额迅速提升,为公司的持续发展奠定了坚实基础。

问答坊 | AI 解惑

哪位高手有PIC16F877点阵方面的程序啊?

哪位高手有没有PIC16F877点阵方面的程序啊? 最好是16*16点阵的 有请发到729951948@qq.com 谢谢啦…

查看全部问答>

SSD 总代理

以 eSATA 接口的闪存设备简称E 盘(易盘),是一款高速度、大容量、小体积、易便携的移动储存设备,也可以说是ESATA 接口的SSD;eSATA就是外置式SATA II规范,逐渐取代IEEE1394及USB2.0的新接口。目前在很多主板上也开始逐渐出现。和一般的U盘比起 ...…

查看全部问答>

懂JAVA手机研发的请进

电子信息科学与技术 系。 越来越喜欢JAVA,想做手机研发的这块。 请高手们指导一下具体情况, 业务大部分是游戏吗? 需要用到哪些知识? …

查看全部问答>

用自带的CEDB的问题

用自带的数据库,,运行的时候提示组件不存在 请问还得加入数据库组件么?哪一个?…

查看全部问答>

0X1u是什么值?

知道0x开头的是16进制的数值,后面跟个u不知道表示什么? 0x1u …

查看全部问答>

鼠标右键点击问题

我用vs2003 开发 wince4.2下的程序,发现无法判断鼠标是点击了左键还是右键,我如何才能开启鼠标右键功能?请高手指点…

查看全部问答>

求rtl8187的datasheet

那位有rtl8187B的datasheet传一下,不胜感激 谢了 li.wencheng2004@gmail.com 谢了…

查看全部问答>

片内flash和片外flash?

刚接触开发板, 不清楚什么是片内RAM和片外RAM,以及片内Flash和片外Flash. 请大家解释一下, 我用的是philips的板子. 难道LPC2214处理器内部也有ARM和Flash吗? …

查看全部问答>

华为西安研究所招聘信息,真诚推荐

我前几天到华为西安研究所应聘,结果不错。 负责的面试官,希望我给他多推荐几个校友。 我认识的人不多,所以在这里广播一下。 谁有兴趣,请将简历发送至 我的邮箱 blue_boy_fly@163.com  。 我会立即推荐到华为西研所面试官那里, ...…

查看全部问答>

简单的bootloader,但是不显示对应的字符串,不知为何?

USE16                           ;default is USE16 org 0x7c00                  & ...…

查看全部问答>