嵌入式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接口函數,最好是參照內核其它驅動的例子,平時多閱讀內核代碼是最好的學習方法。