2009年5月13日 星期三

S3C24xx ADC driver (2)

第一篇文章中我們提到,adc driver 簡化了一部分硬體操作的細節,並提供 API 讓驅動程式使用。但就 touchscreen 驅動程式開發者的立場來看,它仍然有一些問題(以下純屬個人意見,僅供參考):
  • 雖然它給予驅動程式開發者在擷取數據上的方便性,但並未處理與觸控板相關的硬體操作,故開發者仍必須自行設定相關的暫存器來處理按下及釋放的事件;由於 ADC 硬體本身就額外支援觸控板的功能,adc driver 做為硬體與 touchscreen driver 間的中介層,應儘量隱藏硬體的細節,並提供完整的介面供上層驅動程式使用,而如今開發者除了須自行設定暫存器外,還必須先查看 adc driver 的原始碼,了解它如何設定暫存器,以避免自己的程式碼去干擾 adc driver 的運作,似乎失去了資訊隱藏的意義。
  • 這點比較見人見智;一般來說,驅動程式在呼叫 ioremap() 之前,會先呼叫 request_mem_region() 來防止其他驅動程式存取特定的暫存器群。但為了讓 touchscreen driver 也能夠存取暫存器,adc driver 允許 touchscreen driver 映射該區塊,於是變成兩個驅動程式存取同一組暫存器群的局面。我是不知道其他人怎麼想,但我就是覺得很怪,其中一部分程式碼若不小心更新了不該更新的暫存器,那是有可能會影響到另一個驅動程式的運作,造成潛在的錯誤。
基於上述兩項理由,我曾徵詢是否可將觸控板的功能也納入 adc driver 之中,也弄了一個 patch,不過 Ben 認為應該要維持程式碼的簡潔,因此否決了這個提議。

也許以後會有所改變吧,不過,誰知道呢 :)

2009年4月3日 星期五

S3C24xx ADC driver

上個月花了相當多的時間在研究 S3C24xx 的觸控面板控制器和驅動程式,在這邊稍微分享一下心得,並介紹目前在 mainstream kernel 所實做的 ADC driver core。

S3C24xx 的 ADC 控制器共有 8 個 channel,其中有四個 channel 可設定來接收觸控螢幕的訊號,並提供多種轉換模式,例如手動轉換 x 及 y 座標,或是讓控制器自動轉換等等。同時控制器也可偵測觸控筆「按下」或「釋放」的動作。但是需注意的是,同一時間只能有一種模式可以運作;換言之,驅動程式必須適時地在以下三種模式間切換:
  • 偵測「按下」的動作
  • 偵測「釋放」的動作
  • 取樣並轉換 x 及 y 座標
設定不同的模式皆需要對暫存器 (ADCTSC) 寫入不同的值。

除了被用做接收觸控訊號的四個 channel 外,剩下的另外四個則可連接其他的感測器。過去分散於各個專案中的觸控驅動程式 (截至目前尚未整合進入 mainstream),都是直接操作控制器,因而多出的四個 channel 即便接上了裝置,該驅動程式也無法與 touchscreen driver 共存 (不同的 driver 存取同一組暫存器會發生 race condition 的問題)。因此為了讓這些不同裝置的驅動程式能夠共用該控制器,Ben Dooks 在 2.6.28 引入了 ADC driver core (以下簡稱 adc driver),定義了一組介面,讓上層驅動程式能夠透過該介面來使用控制器。

若要使用 adc driver,驅動程式需要定義自己的回呼函式 (callback function),並向它註冊,註冊函式會回傳一個型態為 s3c_adc_client 的指標,其後的函式呼叫則以該指標做為第一個引數。adc driver 內部維護了一個要求佇列來紀錄來自外部的服務需求,並給予觸控有關的需求最高的優先權,以便可即時回應使用者的操作。在運作過程中,adc driver 會不斷地呼叫先前所註冊的 callback 以通知驅動程式處理取樣的數據,次數則可在要求服務時以參數設定。

對觸控驅動程式的開發者來說,adc driver 簡化了一部分複雜的細節,讓開發者透過函式介面來要求服務,而不必操作底層的暫存器。但我必須指出,它只是簡化了「一部分」,並非全部;至於為何,我們留待下一篇文章來探討。

2009年2月22日 星期日

Poky porting (2)

之前能夠以核心 2.6.29-rc4 成功編譯出的 task 為 poky-image-minimal,最近這兩天開始嘗試執行 poky-image-core,兩者的差別在於 minimal 只編譯了最少量的套件,只求可以開機就行;而 core image 則包括了完整的 GNOME Mobile 環境,也因此所需的編譯時間更久,也陸陸續續地遇到一些問題,其中比較大的問題主要是在核心模組的編譯之上。

怎麼說呢?目前所使用的版本為 Pinky-3.1.1 (08年六月釋出),如果沒記錯的話,那時的核心大約是在 2.6.25 rc 階段。不過自 2.6.28 版以後,核心引頭檔的目錄架構出現了大變動:原來在 include/asm-*/ 之下的引頭檔搬移至 arch/*/include、arch/*/mach-*/include 及 arch/*/plat-*/include 之下,並取消了 symbolic link 的使用,全由 makefile 來決定要引用的目錄。因此問題就來了,用來編譯舊版核心的 bb 檔只需要複製 include/asm-*/ 下的引頭檔至 staging 目錄下即可;但到 2.6.28 版以後,引頭檔的路徑已經改變,故需要做特別的處理。因此在 Pinky-3.1.1 下,編譯完核心後,還得再手動複製必要的引頭檔至正確的路徑之下,後續的核心模組編譯才能正確執行。

不過看了一下 Poky git 中,最新的核心版本是 moblin 的 2.6.29-rc2,不確定能不能正確處理,嗯嗯…

PS.
用 uclibc 要編譯 poky-image-core 的套件還是會遇到許多問題,且都是編譯過程的錯誤;想要順利完成的話,建議還是用 glibc 比較好。

2009年2月17日 星期二

Poky porting

最近這幾天,我一邊研究 OpenEmbedded building system 的目錄結構及設定檔撰寫,一邊嘗試利用 Poky 來編譯目前最新穩定版本 (2.6.28) 的核心。原因無他,主要是 2.6.27 以後的核心才有支援我現在使用的開發板。是故整個過程可分為兩階段,一是增加新版本核心用的 bb 檔案,另一項則為增加新硬體的設定檔。

要加入新版本核心其實可以將 meta/packages/linux/ 下的 bb 檔找一個你覺得適合的複製一份來改,內容大同小異,操作如下:

cd meta/packages/linux
vi linux-<MACHINE>_2.6.28.bb
# 填入自訂的內容,或複製現有的來修改
...

要注意的是,我們還需要再新建一個目錄,名稱如下所示,並複製核心使用的組態檔到該目錄下,檔名隨意,方便記憶即可:

mkdir linux-<MACHINE>
cp ~/defconfig ./defconfig-2.6.28

接著在修改 bb 檔時,幾個重要的變數需要設定:
  • PV: 套件版號,OpenEmbedded 會利用該變數來決定使用那個版本來編譯,預設是找最新的版本。
  • S: 套件原始碼目錄,也就是 tarball 解開後放置的路徑,在這個例子中是 ${WORKDIR}/linux-2.6.28
再來就是在 bb 檔中撰寫上 patch 以及複製核心組態檔用的 shell script,這部分可以參考其他 bb 檔的做法,在此就不贅述。

加入新硬體的設定檔可參考 meta/conf/machine/ 下的檔案來修改,由於我的開發板和 OpenMoko 所使用的硬體是同屬於 S3C2440 的晶片,是故就直接複製 fic-gta01.conf 來修改:

cd meta/conf/machine
cp fic-gta01.conf <MACHINE>.conf

修改的部分如下:
  • MACHINE_FEATURES = "kernel26 vfat ext2"
  • MACHINE_DISPLAY_WIDTH_PIXELS = "800"
  • MACHINE_DISPLAY_HEIGHT_PIXELS = "480"
  • PREFERRED_PROVIDER_virtual/kernel = "linux-<MACHINE>"
  • 移除 MACHINE_CLASS
  • 移除 MACHINE_EXTRA_RDEPENDS, MACHINE_EXTRA_RRECOMMENDS
  • 移除 EXTRA_IMAGECMD_JFFS2
  • 移除 SERIAL_CONSOLE
  • 移除 EXTRA_IMAGEDEPENDS
其餘照舊。

修改完成後,在 build 目錄下 (別忘了要 source poky-init-build-env),鍵入以下的指令:

bitbake linux-<MACHINE>

就會開始進行編譯程序。若發生錯誤,查看 build/tmp/work/<MACHINE>-poky-linux-gnueabi/linux-<MACHINE>.../temp/ 下的紀錄檔並修正。

目前已經加入了 2.6.28 及 2.6.29-rc4 的 recipe。其中 2.6.29-rc4 包含了開發板上 SD 控制器LCD 控制器的支援,相信不久應該就可以看到跑 GNOME Mobile 的樣子了。

2009年2月13日 星期五

Poky Linux 建構系統使用感想

最近為了要建立一個完整可供核心掛載的檔案系統,去玩一玩了 Poky 這個嵌入式套件。無可否認的,它所根基的 OpenEmbedded 是個很有彈性的套件建構系統,在已支援的開發板上,只要改一些設定,就可從無到有建構核心及所需的檔案系統映象 (file system image),並且會幫你處理套件間相依性的問題,也可以只建構特定套件,打包成 ipkg 或 deb 檔以供其他系統使用。有過土法煉鋼、自己抓原始碼回來編譯的痛苦經驗的人,就會了解這個功能是多麼地令人叫好。

雖然功能強大,但若要加入新的開發板的支援,或是要解決某個套件不能順利編譯的問題,你就會發現,它的設定檔也是異常的複雜難懂;每個設定檔會去引用其他共享的檔案,並且預先設定一大堆變數。有些變數是在目前檔案被設定,有些則是在被引用時才設定。而被引用的檔案又會去引用其他的檔案……沒完沒了。

就在不久前,uClibc 發生編譯錯誤 (poky 3.1.1),從錯誤訊息看來,發現是硬體架構設定錯誤所致。但找了老半天,就是不知道應該要改那個設定檔,令人懊惱。花了一個下午的時間,才找到問題的關鍵,修正後,這才能順利編譯。我另外把它做成了一個 patch,但我沒有網頁空間可以放,有相同問題的朋友可以來找我要,或有朋友願意提供他的空間也成。

延伸閱讀:
Embedded Linux 系統性的教學看法
Embedded Linux 應用的痛處: OpenEmbedded

2008年12月20日 星期六

關於 touch screen driver

其實 touch screen driver 的部分,這裡這裡的文章已經提過了,只要把 patch 抓下來 apply 至核心原始碼中,再加上些修正即可。不過沒人規定不能重新發明輪子吧?我還是想先自己寫寫看,來了解一下應該如何去設定相關的控制器,以及實際在板子上的運作情況如何。既然是自己找樂趣玩,又有何不可?

不過實際寫了之後,發現雖然使用手冊詳實敘述了各個暫存器的意義,但對於該如何設定以及設定順序為何,還是非常空洞;沒辦法,再回去參考了 patch 的原始碼,才豁然開朗。但話說回來,經過了親手下去實作的過程,有了更深一層的了解,再回來看原始程式,才能很快地抓住你所想知道的關鍵部分,並立即套用至你的程式中。這也算是一種學習驅動程式撰寫的方法之一吧…

接下來,再把程式修改修改,就可以上版子來測試了。

2008年11月17日 星期一

近況報告

自從 2.6.27 發布以來,我就沒有再 post 新的 patch 了。當然不是因為熱情消失了,主要是因為最近這幾個月工作上的事情比較繁忙,下班回到家就有些懶了;再加上上個禮拜個人家中開發用的 PC 主機板出了問題,開不了機,拿去送修又折騰了一段時日,是故這個月沒什麼產出。
不過好在主機板送修回來了,如果測試後確定沒問題,那麼等到工作告一段落,計畫應該就可以繼續進行下去。