2009年10月28日 星期三

Samsung touchscreen driver issue

三星的主流核心支援其實已存在相當久,幾乎可說是所有 ARM-based SoC 中支援最完整的。但經常關心 ARM Linux kernel 發展的網友也許會發現到,怎麼核心中每項周邊都有驅動程式支援,卻獨獨缺了觸控面板?

其實相關的 patch 早已在各個專案中使用 (如 OpenMoko),但由於都是直接操作暫存器,而非架構在 Ben Dooks 的 adc driver 之上(詳見之前的文章),是故一直沒有被整合進去。今年四月初 Nelson Castillo 將原來在 OpenMoko 使用的驅動程式移植至主流核心,並使用 adc driver 來做取樣的工作。雖然已有作為先期準備的 patch 被整合,但直到目前為止完整的驅動程式仍未進行合併。

最近關於這個議題又有了新的爭論。由於 Nelson 的版本引進了多層次的濾波器(filter)來去除不合法的取樣點,Russell King 認為這違背了 policy-mechanism 分離的原則;所有的取樣點應該原封不動地往上傳遞至 user-space(tslib)來做處理,在驅動程式中使用 filter 是缺乏彈性的作法(附帶一提,Russell 是 tslib 的作者)。但 Nelson 認為,在驅動程式中,filter 可以根據需要,透過回傳值來要求 adc driver 多抓一些取樣點來作判斷;而這是 user-space 所無法達成的優點。且這樣的設計方式可以解決在電阻式面板所遇到的問題(在觸控筆按下和釋放的瞬間,會有大量的雜訊出現)。

就我個人測試過的經驗,Nelson 的 patch 確實比單純只使用 tslib,觸控板的表現要好得多,筆觸變得比較順暢,且抖動的情況減少很多。雖然在整合進 board-dependent 的程式碼時相對比較麻煩,不過其效果似乎是值得這麼做的。

2009年10月13日 星期二

雜記

最近這幾個月來因為在做新專案的關係,比較沒時間上來寫寫東西;而 Linux kernel 方面也只 post 了幾個小修正 (因為最近突然發現我所維護的開發板支援無法編譯成功),如此而已。目前三星上的 Linux 開發主力都轉往 S3C64XX 及新的 S5P 系列,因此 S3C24XX 這邊似乎已經沒有什麼好修的了。也許現在是時候去研究其他的子系統了。

2009年8月30日 星期日

Samsung 將釋出 Linux 原始碼

昨天收信時看到了這封信件,以及 Harald Welte 承諾將在三星採用社群開發模式上提供協助。一直以來,S3C24XX 及 S3C64XX 系列的核心支援,包含原始碼的目錄架構、驅動程式,以及各種修正,大部分都是由 Ben Dooks 所完成,也因為他所貢獻的大量基礎建設,使得像我這樣的開發者能夠相當容易地將各種 Samsung-based 開發板的支援加入 Linux 核心之中。如今三星這間半導體大廠願意投入人力來共襄盛舉,若三星自已維護的 kernel tree 能夠順利合併進入主流版本,那麼我們將可以直接自主流核心就得到官方的支援。有了大公司的加持,相信未來 Linux 對於三星 SoC 的支援完整度及執行效率上會得到大幅度的增進。對我們這些使用三星 SoC 的開發者來說,自然是再好不過了。

當然,聽其言,觀其行,我們還是要持續注意三星的實際作為才行。
PS. 有興趣的人可參考這裡所提,下載目前三星所釋出的 kernel tree.

2009年7月29日 星期三

Linux gpiolib

GPIO 在嵌入式系統中是相當常見的 I/O 裝置,全名為 General Purpose I/O。由於 GPIO 針腳可被個別設定和輸出訊號,因此我們可以利用 GPIO 來驅動 LED、或者實作低速的 I/O 通訊協定(如 I2C、SPI)。也可以利用 GPIO 來做為外部訊號的輸入端,在訊號觸發時,驅動程式中可使用 polling 或中斷方式來獲得通知。在嵌入式 SoC 平台上通常配有大量的 GPIO,且多半會和其他週邊裝置共用針腳,因此在使用時要特別注意,以免發生衝突。

過去在 Linux 上的 GPIO 程式碼大部分是屬平台相依的程式碼,因此 API 的實作也是由各平台的開發者自行設計,但除了 SoC 內建的 GPIO 外,系統設計者也會額外以 FPGA 或 I/O expander 來擴充 GPIO 的數量;因此要設計一種方式,除了能夠使用內建的 GPIO 外,也能使用這些額外的 GPIO,並透過一個統一的介面來存取它們。

gpiolib 的引入為上述的問題提供了一個解決方式。gpiolib 將每個 GPIO 的來源 (SoC、FPGA,或是 I/O expander) 用 gpio_chip 結構來表示,開發者可以定義其 GPIO 的編號、數量,以及相關的回呼函式 (callback function)。開發者需要為這些 gpio_chip 結構定義不同的回呼函式來處理不同的 GPIO 來源。如此一來,使用者只需指定 GPIO 編號,gpiolib 會替我們尋找對應的 GPIO 來源,並呼叫適合的函式來存取它,非常地方便。

PS. 需要注意的是,某些 GPIO 來源(如 I2C 介面的 I/O expander)存取時可能會進入睡眠狀態,因此不能夠使用於 ISR 或 tasklet 等不可睡眠的函式之中。

2009年6月17日 星期三

Kernel API always changes

最近因為工作上的需要,花了些時間學習如何撰寫 Linux 區塊裝置驅動程式,以及了解 Linux block subsystem 的架構。我主要參考兩本書藉,其中一本正是大名鼎鼎的 Linux Device Drivers 3rd (LDD3);而另外一本則是去年才出版的書藉 Essential Linux Device Drivers

我嘗試依照書本上的內容寫了一個 RAM-based 的區塊驅動程式,但在我的電腦上卻因為參考不到函式呼叫而無法成功編譯 (核心版本 2.6.28)。原因當然是因為核心 API 的改變,正如許多資深開發者所言,由於開發的需要,核心 API 總是不斷地在變化,因此若不將程式碼合併回主流版本,後續的維護將會非常麻煩。

以 LDD3 來說,其所列的範例程式片段如下:

sectors_xferred = sbull_xfer_request(dev, req);
if (! end_that_request_first(req, 1, sectors_xferred)) {
    blkdev_dequeue_request(req);
    end_that_request_last(req);
}

請注意 LDD3 所依據的核心版本為 2.6.10,到了 2.6.28,這些函式已被移除,取而代之的是:

sectors_xferred = sbull_xfer_request(dev, req);
__blk_end_request(req, 0, sectors_xferred << 9);

由於 __blk_end_request() 函式的第三個參數為成功傳輸的位元組 (byte),而非區段 (sector),所以需做單位轉換。另外可能會造成混淆的地方是 block subsystem 也提供另一個函式 blk_end_request(),兩者功能相同,差別在於後者是有加上 spin lock 的版本;不過由於核心在執行上述的程式碼之前已先行上鎖了,是故就不需要再上鎖一次了。

由以上範例,我們可以了解到,核心 API 的改變對於驅動程式的維護而言,並不僅僅是舊函式的消滅或新函式的加入而已,我們還需要評估應如何修改程式,以及修改後是否會影響程式的行為。通常核心開發者會負責將所有相關的驅動程式修改到好,但若是 out of tree 的程式碼,這部分可就得自己傷腦筋了。

2009年6月8日 星期一

移植 Ångström

因為看到另一個基於 OpenEmbedded 的 distribution Ångström,覺得它比起 Poky 來說提供更多的套件選擇,且由於 Ångström 的目錄架構和 OE 相同,所以在 OE 下新增的套件,馬上就可以套用在 Ångström 之上,而不需做任何修正。是故就決定以 Ångström 做為我移植軟體至開發板的基礎開發套件。

於是上個月的工作就是將原來寫給 Poky 用的設定檔修改以後再移到 Ångström 的目錄之下,然後再修改 Ångström 下的 linux recipe 來支援我目前使用的開發板,接著測試完成後,再提交至 OE mailing list。大功告成。

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 認為應該要維持程式碼的簡潔,因此否決了這個提議。

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