嵌入式Linux驱动案例之一
来源:互联网 发布:java用户管理系统设计 编辑:程序博客网 时间:2024/06/02 13:22
前几天解决一个嵌入式Linux驱动问题,做为一个案例进行记录。
本案例是一个CPU通过LocalBus总线访问外围一个设备,具体设备是一个DSP器件,在实际应用中,性能要求很高,对数据访问速度提出比较高的要求。既然是通过LocalBus总线来访问,实际上也就是在CPU的IO寻址空间。原来的做法是通过ioremap的方式将这个空间进行重映射,然后CPU对其进行读写访问。读取DSP的一个数据需要经过写地址,读数据两个步骤。
现象描述:
发现无论如何,在写完地址之后一定要等待一段时间,或者一定要先读取一下DSP的Ready寄存器。这个操作在大数据处理时消耗相当可观,而实际应用上对性能要求很高,这个等待或者读取Ready寄存器的动作必须清除。
原因分析:
本系统中采用的CPU是Powerpc,对LocalBus进行读写操作,那么读和写操作两个之间进行切换是有一个过程的,先写后读,转换太快可能写会不成功,问题的根本是驱动中采用的是ioremap之后的操作方式。
解决方法:
改变ioremap的方式,使用Linux 内核中对IO的操作接口out和in的方式。调用函数为in_be16和out_le16。定义如下:
inline void out_8(volatile unsigned char *addr, int val)
{
__asm__ __volatile__("stb%U0%X0 %1,%0; sync"
: "=m" (*addr) : "r" (val));
}
inline unsigned in_le16(const volatile u16 *addr)
{
unsigned ret;
__asm__ __volatile__("lhbrx %0,0,%1; twi 0,%0,0; isync"
: "=r" (ret) : "r" (addr), "m" (*addr));
return ret;
}
可以看出是用汇编实现的,其中有一个指令sync,表示同步操作。应该是类似于cache操作的原理,加上同步操作之后数据可以完成读和写的全部操作过程。
经过修改,问题得到解决,不需要等待也不需要在写和读的切换过程中增加其它操作。最后,整个系统比原来使用ioremap的方式在实时性上有很大的提高,而且CPU占用率大大降低。
总结:
在Linux驱动开发中,对于IO的操作应该使用内核提供的IO接口函数,最好是参照内核其它驱动的例子,平时多阅读内核代码是最好的学习方法。
- 嵌入式Linux驱动案例之一
- 嵌入式Linux驱动开发案例流程--LED驱动
- 嵌入式linux驱动与软件详解之一 led驱动与程序
- 嵌入式 linux 驱动 ADC驱动
- 嵌入式 linux 驱动 ADC驱动
- linux i2c 驱动之一
- Linux 块驱动之一
- 嵌入式linux驱动
- 嵌入式linux UART驱动
- 嵌入式Linux驱动开发
- 嵌入式Linux案例开发指南
- 嵌入式Linux开发系列之一
- 嵌入式linux环境搭建之一
- Linux设备驱动----之一 cdev
- Linux设备驱动----之一 cdev
- Linux ALSA声卡驱动之一
- 嵌入式Linux的串口驱动
- linux嵌入式打印机驱动开发
- 二十八 我在软件园的那些日子里
- hdu 1196 求一个数二进制的低位,i&(-i)
- ios开发登录界面
- Redis应用场景
- 超级实用的php函数片段
- 嵌入式Linux驱动案例之一
- 创建子进程时fork()上面的内容为什么在屏幕上只打印一次,而在输出到文件时为什么打印了两次。
- [笔记]javascript面向对象 - 属性
- Jacob操作Word (总结的很好)
- Maven的学习资料收集--(三)使用Maven构建Web项目
- B - Big String
- C++ primer(第五版) 练习 6.12 个人 code
- 无标题
- Qt子线程如何更新UI?