1. 一般io access, 有所謂的IO bus或使用memory mapped IO, 以I386而言, 它有in/out系列的instruction來做IO bus access, 而ARM則沒有.
2. 對於IO bus access, 一般driver只要有access right就可, 而由於一般而 言C/C++ 無法generate in/out系列的instruction, 所以要以inline assembly來達成這個目的, 而一般的inb(), inw(), outb(), outw()...等 等的functions或macros會可以做到這件事.
3. 對於memory mapped IO, 由於是直接access memory, 必須跟OS的memory system結合, 所以就會有一些access right, non-cacheable, virtual address等的問題.
4. 對PCI而言, 還有所謂的PCI bus address, 而一般PCI bus driver在啟動 後會enumerate上面的card, 了解它們的memory regions的size, 並assign PCI bus address給每一memory region, 至於如何由system bus address 對到PCI bus address要看SOC的設計. 在access時, 是virtual address-> physical address->PCI bus address.
5. OS並不會知道那一塊被拿來當memory mapped IO, 所以, 往往是只有開放 RAM的部份的space, 其實一般startup code其MMU的部份還會打開SOC的 register space或一些local bus banks的space, 以相同的virtual address 來使用對應的physical address, 但是, startup code一般我們希望不要 放太多變動性太大的東西, 這樣也會把太多枝枝葉葉的codes放入主要程式 中, 另外, 與PCI相關的考量放入startup code, 也會變得很繁瑣. 所以 ioremap很重要的是就是讓driver可以為它要使用的空間找到一塊virtual address的space.
6. 有一些扁平式的設計, 直接一開始全部對應好, 將4G virtual address對應 到等值的physical address, 所以你不用ioremap也可使用正常, 不過, 使 用ioremap也沒甚麼不好吧, 反而是養成良好的習慣. 而通常, 有virtual memory的MMU, 一般都是只開有限的區域, 即使它們只是直接對應等值的 address, 因為這樣可以加強系統的debug功能, report非法的memory access.
7. 一般ARM有分TLB或protection unit的, protection unit只做保護和cache/ write buffer的控制, TLB則可以實現virtual memory.
因為一般在kernel模式下操作的是virtual address,透過MMU的page table來處理virtual address與physical address,但是實體io port或者memory,要是直接存取會產生兩個問題,一個是受限於特殊硬體架構,另外一個是不應直接處理physical address。於是乎ioremap就是透過修改page table,讓physical address對應到virtual address(等於在virtual address規劃出一區塊,使OS知道使用該區塊等同在使用某區塊的physical address),這樣一來就某種程度隔開特殊的硬體架構,也避免直接使用physical address。
跟著由於硬體的特性,雖然ioreamp讓程式設計師使用實體記憶體如同使用一般memory一樣,但是因為有時硬體可能只是個io port,訊號隨著時間一直變動(有點類似volatile變數一樣),所以在讀取跟寫入的時候最好透過特殊函數如writel或者readl之類,不要直接用assign operator(等號)
http://www.programmer-club.com/showSameTitleN/embedded/1820.html
http://blog.csdn.net/do2jiang/article/details/5450839
沒有留言:
張貼留言