2008年3月24日 星期一

Linux SPI subsystem (2)

我們在上一篇文章中提到,master driver 負責初始化硬體控制器,寫入暫存器以及中斷處理。換句話說,它必須要能夠做到低階的硬體控制;在以 ARM 為基礎的 SoC 當中,也就是要實際上對 I/O memory 做讀寫的動作。因此撰寫 master driver 前,必須要先熟讀 SoC 的使用手冊,充分了解如何操作這些暫存器以支援相關的功能。

此外,master driver 還必須要將從上層傳送來的訊息封包加以解析,並將傳送該封包所需要的硬體參數設定事先寫入暫存器,最後才起始資料傳送。如果控制器支援中斷,那麼 master driver 也必須先註冊中斷常式以便處理例外狀況。接下來我們就來看看一些細節部分的資料結構與函式。

一般在 SoC 系統下,SPI 控制器會以 platform device 的形式存在,是故我們會將 master driver 註冊為一種 platform driver,接著在 probe 函式中呼叫 spi_alloc_master,該函式宣告如下:

struct spi_master *spi_alloc_master(struct device *host, unsigned size);

該函式會分配一塊記憶體並回傳指向 spi_master 結構的指標,參數 size 則可以指定額外的空間大小,該空間可以透過 spi_master_get_devdata 來取得,開發者可用以存放額外的資訊。接著我們需要設定一些關於該控制器的資訊,如:

master->bus_num = 0;
master->num_chipselect = 1;
master->setup = mysetup;
master->transfer = mytransfer;
master->cleanup = mycleanup;

其中 bus_num 是代表控制器的識別號碼,若指定 -1 則表示由系統動態分配。num_chipselect 是這個控制器所能連接的裝置編號的最大值,1 代表最多可連接 2 個裝置 (0, 1)。最後呼叫 spi_register_master 來向系統註冊即可。

當開始要進行傳輸時,在上面程式片段中的 setup 會在傳送前被呼叫,讓 master driver 根據周邊所能接受的傳輸模式參數來設定控制器;接著 transfer 會被呼叫,其參數包括要傳送的周邊以及指向 spi_message 結構的指標。其中 spi_message 結構還包含了一個或多個要傳輸的 buffer,定義在 spi_transfer 結構中。要注意的是,由於 transfer 函式中不可呼叫任何會進入睡眠的函式,是故實際的傳輸會由另外產生的 worker thread 來達成;並且在傳輸完成後,呼叫 spi_message 結構中的 complete 函式以通知 bus driver。最後則是 cleanup 函式被呼叫以釋放進行傳輸時所使用的資源。

另外當要卸載核心模組時,需要呼叫 spi_unregister_master 以解除註冊。

下一篇我們將會來討論 protocol driver 的部分。

3 則留言:

deeptree 提到...

請問一下
這邊提到的master info應該要設定在什麼地方?

我也是在s3c24XX系列板子上try
沒有要自己寫driver
是想使用drivers/spi/spi_s3c24xx.c這個driver

因為是初學者,很多概念我不是很清楚,
我的想法是:
利用make menuconfig裡spi那個部份把
SPI support,
Debug support for SPI drivers,
Bitbanging SPI master,
Samsung S3C24XX series SPI,
User mode SPI device driver support
這幾個選項設為編入kernel

但遇到了一些問題,查了一些資料發現
需要在plat-s3c24xx/devs.c這裡面加入一些參數,雖然第一次遇到的問題似乎解決了,但卡在driver現在告訴我"Failed to register SPI master",很想知道版主這邊提到的參數設定在哪裡

Ramax 提到...

Hi,
不好意思,之前只顧著寫自己的文章,沒注意到你的回應,沒想到竟已過了一個多月…

我並沒有花很多時間看 s3c24xx 的 SPI driver,但從你的錯誤訊息看來,似乎是在呼叫 spi_bitbang_start() 這個函式時出錯了,以致於 driver 無法運作。但只有這樣的訊息仍無法精確掌握究竟是在該函式中的哪一步出錯,還需要再加入些除錯訊息才能了解。

另外,請教你用的是那一版本的核心?

deeptree 提到...

hello!
沒關係沒關係,這樣突然來問,不好意思的是我^^"我後來發現可能是kernel版本的問題,我的是2.6.24的kernel,然後後來是看2.6.31的kernel發現這個部分他有多定義一個硬體參數,我就直接把它加進去,spi看起來是可以動了,雖然說也沒有弄得很清楚(亂用一通)XD現在遇上了其他的問題,在努力中orz