2010年4月16日 星期五

Linux device driver access physical address

一般我們在寫嵌入式系統 Stand alone (Non-OS) 的程式時
如果想存取一段Physcial address
通常我們會以下面的方式來定義指標:
#define CLCDC_BASE    (volatile unsigned long *) 0x10120000;
如果想要取得其值則會定義為:
#define CLCDC_R0        *((volatile unsigned long *) 0x10120000);
如此在存取CLCDC_R0值時,就是在對該Physical address做存取:
CLCDC_R0 = 123;

但如果現在在有OS的情況下
由於OS會有記憶體保護的機制
因此user space的應用程式都無法如同Stand alone的程式直接對某段Physical address做存取
至於device driver也必須使用ioremap()函式來將一段Physical address映射到一段Virtual address才能夠存取:
void * ioremap(unsigned long phys_addr, unsigned long size);


今天剛好有機會測試到這兩種方法在Linux內所會造成結果的差別...
因為VersatilePB板上的Color LCD Controller (CLCDC)
(其在VersatilePB板上的Base address為:0x1012000,Size為:64KB)
會在啟動時將記憶體某一個區段map為frame buffer來使用
而其使用的記憶體位置會存在CLCDC中的某一個register內
因為要將資料輸出到frame buffer中
因此必須先取得該register所存放frame buffer的physical address...

一開始是先使用一般嵌入式系統Stand alone (Non-OS) 程式的方式來取得該值:
static unsigned long clcdc_base = *((volatile unsigned long *) 0x10120000);
再將我要輸出的資料指定給frame_buffer變數
結果可以正常Compile
但放到QEMU所模擬的VersatilePB環境,insmod時...
就會噴出:
Unable to handle kernel paging request at virtual address 10120000 
的錯誤訊息...


在搜尋一些網頁後才發現一般這樣使用在Kernel中會被視為Virtual address
但因為Kernel並沒有map這段Virtual address到某段Physical address
所以沒辦法做轉換,因此噴出錯誤訊息...

正確的使用方法應該先將此Physical address透過ioremap()函式映射到一段Virtual address
之後再對該Virtual address做存取:
static unsigned long clcdc_base = ioremap(0x10120000, 64 * 1024);

如此便可正確存取到CLCDC的registers了...


事後想想其實自己原本就有利用ioremap()來存取我們3D晶片上的registers
結果想再新增一個功能頭腦反而就轉不過來了... <囧>

不過這也算是一個還不錯的經驗...
發現原來就算是在kernel space中也是必須透過ioremap()才能存取Physcial address的...

P.S.
根據定義... ioremap()所回傳的Virtual address
是不可被直接存取,而是必須間接透過Kernel所提供的存取函式的
ex:ioread8()、ioread16()、ioread32()、iowrite8()、iowrite16()、iowrite32()、memset_io()、memcpy_fromio()、memcpy_toio() ...etc

但這次改之前OS Lab所留下來的device driver
卻發現全都是直接存取ioremap()所回傳的Virtual address
或許這不是正確的寫法?!
(不過仍然可以跑就是.....)
哪天有機會再把它改掉看看是不是也能正常使用?! XDDD


最近device driver寫得差不多了
(改人家寫的都馬寫得很快... Orz)

原本畢業論文要做效能分析的程式被中途喊卡
老闆改叫我去接學長做軟/硬體整合的工作
原先進來這個實驗室的時候就是只想focus在OS部份,不想看wave form的!!
看來這下真的是沒得選了... QQ


接下來就要開始嗑 AMBA AHB / AXI 的bus protocal spec. 哩...
或許能有這個機會接觸到平常碰不太到的硬體也是個不錯的經驗?!
希望最後不會做不出來就好... QQ

不過最好佳在的是現在老闆"有機會"放寬他的條件,大家都有機會兩年畢業了.......................... 吧?!

誠心希望這張支票最後不會跳票... (●皿●)"

3 則留言:

Jeff 提到...

最上面要放單據核銷清單,後面放請款單,再來放黏貼憑證,工作日誌表給計畫主持人簽完名之後放在最後,如果是第一次申報要附上助理申請表在最後面,整份訂起來之後再去蓋章,送到會計室去之後就申請到人事費了,耶!

咦~你們研究所學的怎麼不一樣!?

法克 提到...

哈...
好像我那時候當會長跑核銷的樣子~

你研究所有學到如何"報假帳"啊...
以後就像阿扁一樣口袋麥可麥可!! XDDD

法克 提到...

結果問了OS Lab的老師...
那樣的寫法是沒問題的~
但是使用ioread()、iowrite()系列的函式
內部函式的實做會確保architecture independent

目前我們driver只會在我們的平台上使用
所以比較沒啥關係...
但若是需要跨平台的話可能就會有問題發生了!!