IO端口和IO內存
在驅動程序編寫過程中,很少會注意到IO Port和IO Mem的區別。雖然使用一些不符合規範的代碼可以達到最終目的,這是極其不推薦使用的。
結合下圖,我們徹底講述IO端口和IO內存以及內存之間的關係。主存16M字節的SDRAM,外設是個視頻採集卡,上面有16M字節的SDRAM作爲緩衝區。
1. CPU是i386架構的情況
在i386系列的處理中,內存和外部IO是獨立編址,也是獨立尋址的。MEM的內存空間是32位可以尋址到4G,IO空間是16位可以尋址到64K。
在Linux內核中,訪問外設上的IO Port必須通過IO Port的尋址方式。而訪問IO Mem就比較羅嗦,外部MEM不能和主存一樣訪問,雖然大小上不相上下,可是外部MEM是沒有在系統中註冊的。訪問外部IO MEM必須通過remap映射到內核的MEM空間後才能訪問。
爲了達到接口的同一性,內核提供了IO Port到IO Mem的映射函數。映射後IO Port就可以看作是IO Mem,按照IO Mem的訪問方式即可。
2. CPU是ARM 或PPC架構的情況
在這一類的嵌入式處理器中,IO Port的尋址方式是採用內存映射,也就是IO bus就是Mem bus。系統的尋址能力如果是32位,IO Port+Mem(包括IO Mem)可以達到4G。
訪問這類IO Port時,我們也可以用IO Port專用尋址方式。至於在對IO Port尋址時,內核是具體如何完成的,這個在內核移植時就已經完成。在這種架構的處理器中,仍然保持對IO Port的支持,完全是i386架構遺留下來的問題,在此不多討論。而訪問IO Mem的方式和i386一致。
注意:linux內核給我提供了完全對IO Port和IO Mem的支持,然而具體去看看driver目錄下的驅動程序,很少按照這個規範去組織IO Port和IO Mem資源。對這二者訪問最關鍵問題就是地址的定位,在C語言中,使用volatile 就可以實現。很多的代碼訪問IO Port中的寄存器時,就使用volatile關鍵字,雖然功能可以實現,我們還是不推薦使用。就像最簡單的延時莫過於while,可是在多任務的系統中是堅決避免的!