嵌入式linux应用程序实例,嵌入式Linux应用程序访问物理地址的实例

前言  按照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)<5){};

CSFPGAH();

stoptime2=GETSYSCLK();

GLEDstate|=0x00000001;

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

GLEDstate&=0xfffffffe;

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

starttime1=GETSYSCLK(); //产生GPIO一个正脉冲

write(fspi,&tx,5);

stoptime1=GETSYSCLK();

GLEDstate|=0x00000001;

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

printf("DRVtime=%d  REGtime=%d ",starttime1-stoptime1,starttime2-stoptime2);

}

int main(void){

SPI_init(); Init_FPGA_SPI(); Init_Timer();

waittime=GETSYSCLK();

while(1){

if ((waittime-GETSYSCLK())>2000000){ //2000ms测试一次

waittime=GETSYSCLK();

test();

}

}

}

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

224fd6cf3051cb55f66b1923aa83a60b.png

图 1

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/335355.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

线程同步 线程安全_同步装饰器来替换线程安全类

线程同步 线程安全您知道什么是线程安全吗&#xff1f; 如果没有&#xff0c;下面是一个简单的示例。 所有类都必须是线程安全的&#xff0c;对吗&#xff1f; 并不是的。 其中一些必须是线程安全的&#xff1f; 又错了。 我认为它们都不必是线程安全的&#xff0c;而它们都必须…

forge开发_使用Forge,WildFly Swarm和Arquillian开发微服务

forge开发在这篇文章中&#xff0c;我们将看到如何使用WildFly Swarm和Forge开发微服务&#xff0c;以及如何使用Arquillian和Rest Assured对其进行测试。 WildFly Swarm提供了一种创新的方法来打包和运行Java EE应用程序&#xff0c;方法是将它们与足够的服务器运行时一起打包…

zynq+linux固化程序,如何在 Zynq UltraScale+ MPSoC 上实现 Linux UIO 设计

原标题&#xff1a;如何在 Zynq UltraScale MPSoC 上实现 Linux UIO 设计简介作者&#xff1a; Alex He (何晔)&#xff0c; 赛灵思高级嵌入式应用工程师这里的 UIO 即 Userspace I/O&#xff0c;本文中 UIO 泛指 UIO 设备和 UIO 驱动。它在 Linux kernel 的世界里比较小众&…

thinkpad笔记本散热风扇_极致的散热体验,ORICO 全铝DIY双风扇笔记本散热垫评测...

电脑的出现&#xff0c;极大的改变了人类的生活。娱乐、办公、游戏、电子竞技等等都需要用到电脑。而电脑也慢慢的在升级着。电脑的体积也由最开始的的占据几间屋子的庞大体积&#xff0c;到后来的台式机、台式一体机、电脑的体积慢慢的变的越来越小。而便携式笔记本电脑的出现…

Web产品的交互说明文档应该怎么写?

经常与开发同学聊天&#xff0c;他们说有一个详细的说明文档可以帮助他们更准确的进行工时评估&#xff0c;还可以帮助他们提高工作效率&#xff0c;减少多余的思考时间。因此在这里分享一些制作交互说明文档的经验。 我先说说说交互原型包含哪些部分&#xff1f; 版本说明及更…

linux类似360软件,linux下有什么类似鲁大师查看电脑配置的软

满意答案drqyna2017.05.26采纳率&#xff1a;40% 等级&#xff1a;11已帮助&#xff1a;5455人linux如何查看系统的硬件配置如何在linux系统下查看系统配置&#xff1f;在图形模式下我们可以很方便的利用Linux的图形工具&#xff0c;点击几下就可以查看到Linux系统的的硬件信…

thinkphp json_原创干货 | Thinkphp序列化合总

听说转发文章会给你带来好运最近Thinkphp几个版本都出了反序列化利用链&#xff0c;这里集结在一起&#xff0c;下面是复现文章&#xff0c;poc会放在最后01Thinkphp5.1.37环境搭建composercreate-project topthink/think5.1.37 v5.1.37poc演示截图调用链单步调试漏洞起点在\th…

笔记本能安装联想智能云教室吗_挑战Jupyter Notebook:云协作、云硬件,上云的Notebook编程环境...

对全世界的 Python 高手而言&#xff0c;Jupyter Notebook 是目前最流行的编程环境&#xff0c;但它也有一些令人难以忍受的缺点。为此&#xff0c;一个位于旧金山的小团队开发了一款名为 Deepnote 的笔记本工具&#xff0c;这是一种云协作、云硬件&#xff0c;上云的 Notebook…

在Linux中su和sudo区别,Linux中su和sudo的用法和区别

目录sudosudo&#xff1a;暂时切换到超级用户模式以执行超级用户权限&#xff0c;提示输入密码时该密码为当前用户的密码&#xff0c;而不是超级账户的密码。缺点是每次执行超级用户权限都要在命令前加上 sudo &#xff0c;优点是在当前终端再使用 sudo 不要再重复输入密码(只对…

python 提升效率_@Python 程序员,如何最大化提升编码效率?

作者 | Enoch CK 译者 | 刘畅 整理 | Jane 出品 | Python大本营 【导语】无论你是一位高级的AI工程师还是学生&#xff0c;你都会在工作或学习过程中需要用到 Python。自 1991 年首次发布后&#xff0c;Python 很快就成为了程序员和技术人员最喜欢的语言。作为一种拥有相对简单…

spring boot rabbitmq_Spring Boot+RabbitMQ 实现延迟消息实现完整版,实用!

本文同步Java知音社区&#xff0c;专注于Java作者&#xff1a;Sam哥哥http://blog.csdn.net/linsongbin1/article/details/80178122概述曾经去网易面试的时候&#xff0c;面试官问了我一个问题&#xff0c;说下完订单后&#xff0c;如果用户未支付&#xff0c;需要取消订单&…

jax-rs jax-ws_信守承诺:针对JAX-RS API的基于合同的测试

jax-rs jax-ws自从我们谈论测试和应用有效的TDD做法以来&#xff0c;已经有一段时间了&#xff0c;特别是与REST&#xff08;ful&#xff09; Web服务和API有关的做法。 但是&#xff0c;这个主题永远都不应忘记&#xff0c;特别是在每个人都在做微服务的世界中&#xff0c;无论…

怎么运行aws的示例程序_使Spring Boot应用程序在AWS上无服务器运行

怎么运行aws的示例程序在之前的 几篇 文章中&#xff0c;我描述了如何设置Spring Boot应用程序并在AWS Elastic Beanstalk上运行它。 尽管这是从物理服务器到云服务器的重要一步&#xff0c;但还有更好的可能&#xff01; 走向无服务器 。 这意味着无需花费任何服务器费用&…

linux useradd 数字,详解linux useradd用户组合权限管理等

1&#xff0c;权限相关概念Rwx任何一个文件都应该由两部分组成&#xff0c;这两部分其实基于文件系统来组织&#xff0c;磁盘分区创建完成后&#xff0c;在高级格式化的时候&#xff0c;就把整个磁盘分区分成两部分&#xff0c;其中一部分是源数据&#xff0c;一部分是来放数据…

junit jndi_使用Spring创建用于JUnit测试的JNDI资源

junit jndi直到最近&#xff0c;我还使用静态方法来设置内存数据库&#xff08;HSQLDB&#xff09;。 我在JUnit测试的setUp / tearDown中调用了这些方法。 当我使用Spring时&#xff0c;这对我来说总是有点不自然&#xff0c;并且所有内容都应在其应用程序上下文中运行。 创建…

c语言程序经过编译以后生成的文件名的后缀为,c语言源文件经过编译后生成文件的后缀是什么...

c语言源文件经过编译后生成文件的后缀是什么c语言源文件经过编译后生成文件的后缀是“.obj”。C语言源程序经过编译程序编译之后&#xff0c;生成一个后缀为“.obj”的文件&#xff0c;最后由称为“连接程序”的软件&#xff0c;把此“.obj”文件与各种库函数连接在一起&#x…

通过PL/SQL developer工具访问远程的Oracle数据库_访问数据库_连接数据库_登录数据库

文章目录工具简介电脑没有安装 Oracle 数据库电脑安装了 Oracle 数据库工具简介 PL/SQL Developer 是 Oracle 数据库开发工具&#xff0c;PL/SQL Developer 功能很强大&#xff0c;可以做为集成调试器&#xff0c;有 SQL 窗口&#xff0c;命令窗口&#xff0c;对象浏览器和性能…

xgboost简单介绍_好文干货|全面理解项目中最主流的集成算法XGBoost 和 LightGBM

点击上方“智能与算法之路”&#xff0c;选择“星标”公众号第一时间获取价值内容本文主要介绍基于 Boosting 框架的主流集成算法&#xff0c;包括 XGBoost 和 LightGBM。送上完整的思维导图&#xff1a;XGBoostXGBoost 是大规模并行 boosting tree 的工具&#xff0c;它是目前…

本地 Windows 如何将 Web 工程部署到远程 Windows 主机上

文章目录第一步&#xff1a;先连接远程 Windows 主机&#xff1a;第二步&#xff1a;连接远程 Windows 主机后&#xff0c;把发布包复制到远程主机上并确定有关的目录第三步&#xff1a;删除远程主机的数据库中的旧数据第四步&#xff1a;创建新的用户和表空间第五步&#xff1…

r语言三维柱状图_R语言三维图的绘制

R语言在可视化方面的地位是毋庸置疑的&#xff0c;但是呢相对于MatalabR语言在三维图形的展示上存在一定的劣势。当然&#xff0c;作为大众的免费软件&#xff0c;指定不服&#xff0c;很多人为此也基于R语言开发了一些相应的三维图的绘制包&#xff0c;像rgl&#xff0c;gg3D&…