嵌入式Linux驱动案例之一


前几天解决一个嵌入式Linux驱动问题,作为一个案例进行记录。函数


   本案例是一个CPU经过LocalBus总线访问外围一个设备,具体设备是一个DSP器件,在实际应用中,性能要求很高,对数据访问速度提出比较高的要求。既然是经过LocalBus总线来访问,实际上也就是在CPU的IO寻址空间。原来的作法是经过ioremap的方式将这个空间进行重映射,而后CPU对其进行读写访问。读取DSP的一个数据须要通过写地址,读数据两个步骤。性能


   现象描述:学习

        发现不管如何,在写完地址以后必定要等待一段时间,或者必定要先读取一下DSP的Ready寄存器。这个操做在大数据处理时消耗至关可观,而实际应用上对性能要求很高,这个等待或者读取Ready寄存器的动做必须清除。大数据


缘由分析:spa

      本系统中采用的CPU是Powerpc,对LocalBus进行读写操做,那么读和写操做两个之间进行切换是有一个过程的,先写后读,转换太快可能写会不成功,问题的根本是驱动中采用的是ioremap以后的操做方式。接口


解决方法:开发

    改变ioremap的方式,使用Linux 内核中对IO的操做接口out和in的方式。调用函数为in_be16和out_le16。定义以下:rem


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;
}
rpc


能够看出是用汇编实现的,其中有一个指令sync,表示同步操做。应该是相似于cache操做的原理,加上同步操做以后数据能够完成读和写的所有操做过程。同步

通过修改,问题获得解决,不须要等待也不须要在写和读的切换过程当中增长其它操做。最后,整个系统比原来使用ioremap的方式在实时性上有很大的提升,并且CPU占用率大大下降。


总结:

    在Linux驱动开发中,对于IO的操做应该使用内核提供的IO接口函数,最好是参照内核其它驱动的例子,平时多阅读内核代码是最好的学习方法。