linux的mmc spi學習筆記

2021-06-23 00:46:24 字數 3383 閱讀 6226

** 

核心為linux3.0

硬體平台為:龍芯1b開發板

1、驅動檔案結構:

mmc驅動共分為三個目錄:card/、core/、host/

card目錄下的驅動檔案是卡的裝置驅動,也就是針對mmc或者sd卡的塊裝置驅動

core目錄下的驅動檔案是mmc匯流排驅動程式

host目錄下的驅動檔案是mmc或者sd卡的通訊介面驅動

2、體系結構簡述(以mmc為例)

(1)card部分中的block.c檔案中的初始化函式:

staticint __init mmc_blk_init(void)

可以看到,register_blkdev為註冊乙個塊裝置,

mmc_register_driver為註冊乙個mmc驅動。

其中mmc_driver就是從mmc匯流排驅動中註冊乙個mmc_driver,這樣,我們就可以從probe函式中得到mmc_device,這裡叫mmc_card。

staticint mmc_blk_probe(struct mmc_card *card);

其中mmc_card結構體有乙個成員指標為:

structmmc_host *host;

該指標指向乙個mmc主機例項,塊裝置中的讀寫操作就是呼叫這個mmc主機的操作函式host->ops->request來實現對實際硬體的操作。

從上面的分析來看,要找到這mmc_card,就得先把mmc_card這個裝置掛載到mmc_bus去。

(2)core部分中的core.c檔案中的初始化函式:

staticint __init mmc_init(void)

這個函式一開始建立了乙個工作佇列workqueue,這個工作佇列的作用主要是用來支援熱插拔,在後面我們將會看到。然後分別註冊乙個mmc匯流排mmc_bus_type,註冊了乙個mmc_host類,和註冊了乙個sdio_bus_type。這裡我們以mmc為例,主要是知道註冊了乙個mmc匯流排。那麼怎樣生成乙個mmc裝置,並掛載到該匯流排上呢?

(3)host部分中的mmc_spi.c檔案中的初始化函式:

staticint __init mmc_spi_init(void)

該函式只是註冊了乙個spi驅動,由於我們的mmc是通過spi介面來通訊的,所以這個驅動實則上就是最低層的硬體介面驅動。當然,在這之前,我們得註冊乙個spi匯流排,並在該spi匯流排掛載了乙個spi介面裝置。這樣,在註冊spi驅動的時候,就會呼叫該驅動中的probe函式。probe函式中呼叫了函式:

mmc= mmc_alloc_host(sizeof(*host), &spi->dev);

建立乙個mmc_host結構,這個結構就是在mmc_card所需要的mmc主機例項。

在mmc_alloc_host中,建立乙個mmc_host和mmc_spi_host,且mmc_host的最後乙個成員指標private指向mmc_spi_host。

該函式乙個重要的初始化操作:

mmc->ops= &mmc_spi_ops;

這個mmc_spi_ops操作函式就是spi介面的操作函式。

除此之外,最重要的是建立了乙個工作佇列任務structdelayed_work detect。工作佇列任務執行的函式為mmc_rescan,在這個函式中以不同的頻率掃瞄:

staticint mmc_rescan_try_freq(struct mmc_host *host, unsigned freq)

從這個函式看到,一開始就是設定某乙個時鐘頻率,然後對mmc或者sd傳送一些命令進行探測。這裡以mmc為例,所以看mmc_attach_mmc這個函式:

intmmc_attach_mmc(struct mmc_host *host)

一開始設定mmc的電壓,然後就對mmc卡進行初始化,主要是讀取mmc卡里的一些暫存器資訊,且對這些暫存器的值進行設定。然後,呼叫mmc_add_card來把mmc_card掛載到mmc_bus_type匯流排去:

voidbus_probe_device(struct device *dev)

} 這樣,在匯流排mmc_bus_type中就有了mmc裝置mmc_card了。

不過這裡有個問題,就是這個工作佇列任務什麼時候開始執行呢,又與(1)部分建立的工作佇列workqueue有什麼關係,跟熱插拔有什麼關係。

繼續把焦點放到probe函式:

if(host->pdata && host->pdata->init)

這裡有個

mmc_spi_detect_irq的函式,這個函式顧名思義是檢測mmc_spi中斷。意思大概是當mmc插入時檢測到乙個外部中斷。

staticirqreturn_t

mmc_spi_detect_irq(intirq, void *mmc)

mmc_detect_change呼叫了:

mmc_schedule_delayed_work(&host->detect,delay);

再呼叫:

queue_delayed_work(workqueue,work, delay);

這個函式就是把工作佇列任務host->detect放到一開始就建立的工作佇列workqueue中。也就是這個時候開始執行mmc_rescan來掃瞄mmc卡。

那麼什麼時候產生這個中斷的呢,至少要申請乙個外部中斷,這是熱插拔的功能,同時是移植驅動的關鍵。

再來看host->pdata->init(&spi->dev,mmc_spi_detect_irq,mmc);這個函式。先找到host->pdata的由來,還是在probe函式中:

host->pdata= mmc_spi_get_pdata(spi);

staticinline *

mmc_spi_get_pdata(structspi_device *spi)

由此可知,我們要實現乙個

structmmc_spi_platform_data結構,並將其賦值給spi_device的dev的platform_data成員。

structmmc_spi_platform_data ;

從這個結構中,可以看到,要實現init這個函式來申請外部io中斷,並把mmc_spi_detect_irq作為中斷服務程式。再來看幾個成員函式:

get_ro:讀取寫保護狀態(getthe state of read only)。

get_cd:讀取卡插入或者拔出狀態(getthe state of card detected)。

setpower:設定卡上電或者下電狀態。

那麼這些函式在**被呼叫呢。看到mmc->ops= &mmc_spi_ops中的mmc_spi_ops結構:

staticconst struct mmc_host_ops mmc_spi_ops = ;

對應的操作函式中呼叫了

mmc_spi_platform_data對應的函式。

mmc_spi_ops操作函式在card塊裝置驅動中被呼叫。

android actionbar的學習筆記

我主要學習了actionbar的 1.如何顯示和關閉 2.如何在actionbar中顯示自定義的view 3.如何顯示隱藏的和直接顯示的menu item 1.如何顯示 2.如何得到actionbar?actionbar有兩種,一種是android系統自帶的,一種是support包中的actionb...

C Primer Chapter One學習筆記

筆記 1.流 從io裝置上讀入或寫出的字串行,用來說明字元隨時間順序生成或消耗。2.輸入輸出符可連用原因 operator 或operator 返回stream物件。3.要測試程式那個語句出錯,使用cout 4.新建乙個內建型別,如int i 0 最好先初始化,不然用到的時候沒初始化會產生奇怪的錯誤...

BroadcastReceiver學習筆記

需要注意 的是,不要在 onreceive 方法中新增過多的邏輯或者進行任何的耗時操作,因為在廣播接收 器中是不允許開啟執行緒的,當 onreceive 方法執行了較長時間而沒有結束時,程式就會報錯。有序broadcast,sendorderedbroadcast intent,null abort...