在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

rt-thread SDIO驅(qū)動(dòng)框架分析(貼片SD卡flash驅(qū)動(dòng)\SD Nand flash驅(qū)動(dòng))

深圳市雷龍發(fā)展有限公司 ? 2023-04-04 17:41 ? 次閱讀

文章目錄

rt-thread SDIO驅(qū)動(dòng)框架分析之SD卡驅(qū)動(dòng)

1. 前言

2. SDIO通用驅(qū)動(dòng)框架介紹

3. 文件架構(gòu)分析

4. SDIO設(shè)備驅(qū)動(dòng)分析

5. SDIO設(shè)備驅(qū)動(dòng)架構(gòu)分析

6. 調(diào)試記錄

7. 總結(jié)


1. 前言

RT-Thread是一款國(guó)產(chǎn)化的嵌入式操作系統(tǒng),目前在嵌入式領(lǐng)域得到廣泛應(yīng)用,其強(qiáng)大的擴(kuò)展功能以及通用的外設(shè)驅(qū)動(dòng)框架備受大家追捧。

關(guān)于基本的外設(shè)驅(qū)動(dòng),其官網(wǎng)上基本也都有部分描述,但是關(guān)于SDIO設(shè)備驅(qū)動(dòng)目前為止還沒有相關(guān)文檔說明,因此本文筆者將根據(jù)自己的調(diào)試使用經(jīng)驗(yàn),與大家分享下rtthread的通用SDIO設(shè)備驅(qū)動(dòng)的實(shí)現(xiàn)。

本文基于代碼倉庫 rt-thread/bsp/stm32/stm32f103-fire-arbitrary 分析代碼

分支:main

commit:6808f48bdcf914f03ac757cc19b264a5d0db56de

說明:main分支會(huì)有不斷更新,但是SDIO驅(qū)動(dòng)框架目前應(yīng)該不會(huì)有大變更

硬件介紹:

控制器:STM32 基于手上為數(shù)不多的野火開發(fā)板吧

SD卡:本次采用的并非SD卡,而是創(chuàng)世CS家的一顆SD Nand, CSNP4GCR01-AMW,有幸申請(qǐng)到了一顆樣片

這里多說幾句,SD nand使用起來和SD卡完全一樣,而且SD Nand相比SD卡感覺好用太多,貼片LGA-8封裝,和SPI flash 差不多,完美的解決了SD卡松動(dòng)導(dǎo)致系統(tǒng)不穩(wěn)定的問題,而且容量又大,個(gè)人感覺以后必定是嵌入式存儲(chǔ)應(yīng)用上的主流 (除了價(jià)格貴點(diǎn)啥都好,哈哈)想要樣片試試水的可以去找深圳雷龍公司官網(wǎng)申請(qǐng)下

2. SDIO通用驅(qū)動(dòng)框架介紹

首先來介紹下 SDIO 通用驅(qū)動(dòng)框架。

RT-Thread 區(qū)別于其他操作系統(tǒng),如FreeRTOS,的一大重要特征是,RT-Thread 中引入了設(shè)備驅(qū)動(dòng)框架,并且針對(duì)絕大多數(shù)外設(shè)基本上都已完成對(duì)應(yīng)的設(shè)備驅(qū)動(dòng)框架編寫,所謂的設(shè)備驅(qū)動(dòng)框架,也就是我們所說的建立在應(yīng)用層與底層驅(qū)動(dòng)層之間的中間件

如下圖所示:

應(yīng)用層:完成業(yè)務(wù)應(yīng)用,調(diào)用通用接口操作設(shè)備驅(qū)動(dòng)層

設(shè)備驅(qū)動(dòng)框架層:完成外設(shè)通用驅(qū)動(dòng)框架設(shè)計(jì),脫離具體的芯片,將驅(qū)動(dòng)中相同部分,如針對(duì)SPI,關(guān)于SPI的完整讀寫邏輯等抽離出來

設(shè)備驅(qū)動(dòng)層:完成對(duì)應(yīng)芯片的外設(shè)驅(qū)動(dòng)程序編寫,實(shí)現(xiàn)設(shè)備驅(qū)動(dòng)框架層的具體接口

SD NAND,貼片式TF卡,貼片式SD卡

對(duì)于SDIO外設(shè)亦是如此:

在設(shè)備驅(qū)動(dòng)框架層中,實(shí)現(xiàn)SD卡、SDIO卡、MMC卡的通用外設(shè)驅(qū)動(dòng)邏輯,如卡的識(shí)別、卡的模塊切換、卡的讀寫操作等,這些都是通用的,遵循SD標(biāo)準(zhǔn)協(xié)議;

在設(shè)備驅(qū)動(dòng)層中,根據(jù)對(duì)應(yīng)的硬件,完成具體芯片的SDIO外設(shè)配置,并實(shí)現(xiàn)設(shè)備驅(qū)動(dòng)框架層所需要實(shí)現(xiàn)的具體接口,如發(fā)送CMD命令等。

在應(yīng)用層實(shí)現(xiàn)具體的應(yīng)用,應(yīng)用層與驅(qū)動(dòng)層解耦

通過這種方式,這樣便可以輕松的做到:

需要驅(qū)動(dòng)具體的SD、SDIO、MMC時(shí),根據(jù)具體的芯片實(shí)現(xiàn)對(duì)應(yīng)的SDIO驅(qū)動(dòng)接口即可

應(yīng)用層可直接移植,如出現(xiàn)方案芯片替代時(shí),只需完成設(shè)備驅(qū)動(dòng)層適配即可

這也就是RT-Thread讓眾多開發(fā)者瘋狂追捧的重大原因了,接下來,我們將具體分析關(guān)于SD卡的具體框架層實(shí)現(xiàn),關(guān)于SDIO卡、MMC卡,由于使用不多,本文不做深入分析。

3. 文件架構(gòu)分析

首先我們先來看下SDIO驅(qū)動(dòng)框架有關(guān)文件及架構(gòu)

SDIO驅(qū)動(dòng)框架文件:

SD NAND,貼片式TF卡,貼片式SD卡

SDIO驅(qū)動(dòng)框架文件架構(gòu):

SD NAND,貼片式TF卡,貼片式SD卡

4. SDIO設(shè)備驅(qū)動(dòng)分析

設(shè)備驅(qū)動(dòng)與驅(qū)動(dòng)框架文件在不同的目錄,設(shè)備驅(qū)動(dòng)一般在 bsp 目錄中

通常設(shè)備驅(qū)動(dòng)完成以下幾個(gè)事情:

初始化具體外設(shè)有關(guān)數(shù)據(jù)結(jié)構(gòu);

完成具體外設(shè)初始化程序編寫;

實(shí)現(xiàn)設(shè)備框架層的具體接口,如:open,read,write,close,control 等;

將具體設(shè)備注冊(cè)到內(nèi)核中;

需要注意的是,SDIO設(shè)備驅(qū)動(dòng)會(huì)有些許區(qū)別,在SDIO設(shè)備驅(qū)動(dòng)程序中,主要完成以下幾件事:

初始化具體外設(shè)有關(guān)數(shù)據(jù)結(jié)構(gòu);

SDIO外設(shè)的初始化配置;

實(shí)現(xiàn)設(shè)備框架層的以下幾個(gè)接口:

struct rt_mmcsd_host_ops {

void (*request)(struct rt_mmcsd_host *host, struct rt_mmcsd_req *req);

void (*set_iocfg)(struct rt_mmcsd_host *host, struct rt_mmcsd_io_cfg *io_cfg);

rt_int32_t (*get_card_status)(struct rt_mmcsd_host *host);

void (*enable_sdio_irq)(struct rt_mmcsd_host *host, rt_int32_t en);

};

4.通知驅(qū)動(dòng)框架層(此處demo程序默認(rèn)上電前sd卡已接入);

以 rt-thread/bsp/stm32/libraries/HAL_Drivers/drv_sdio.c 程序?yàn)槔琒DIO驅(qū)動(dòng)層程序從 rt_hw_sdio_init 函數(shù)開始,由于使能了自動(dòng)初始化,此函數(shù)由 INIT_DEVICE_EXPORT(rt_hw_sdio_init); 宏實(shí)現(xiàn)初始化調(diào)用

(關(guān)于自動(dòng)初始化如何實(shí)現(xiàn)的細(xì)節(jié),可參考筆者另外一篇博文對(duì)自動(dòng)初始化的詳細(xì)分析:代碼自動(dòng)初始化(點(diǎn)擊跳轉(zhuǎn)))

在 rt_hw_sdio_init 函數(shù)中,驅(qū)動(dòng)程序主要初始化以下幾個(gè)結(jié)構(gòu)體:

stm32外設(shè)HAL庫配置結(jié)構(gòu)體 SD_HandleTypeDef hsd

stm32 sdio 設(shè)備結(jié)構(gòu)體 struct stm32_sdio_des sdio_des

sdio硬件外設(shè)結(jié)構(gòu)體 struct rthw_sdio *sdio

mmc sd host結(jié)構(gòu)體struct rt_mmcsd_host

其關(guān)系如下圖所示:

SD NAND,貼片式TF卡,貼片式SD卡

結(jié)構(gòu)體數(shù)據(jù)初始化完成以后,調(diào)用mmcsd_change()函數(shù),觸發(fā)框架層邏輯

SD NAND,貼片式TF卡,貼片式SD卡

此外,在設(shè)備驅(qū)動(dòng)層提供的操作函數(shù)主要有:

SD NAND,貼片式TF卡,貼片式SD卡SD NAND,貼片式TF卡,貼片式SD卡

static const struct rt_mmcsd_host_ops ops =

{

rthw_sdio_request,

rthw_sdio_iocfg,

rthw_sd_detect,

rthw_sdio_irq_update,

};

rthw_sdio_request 實(shí)現(xiàn)一次SDIO數(shù)據(jù)發(fā)送

rthw_sdio_iocfg 實(shí)現(xiàn)SDIO外設(shè)配置,注意在SD識(shí)別過程中會(huì)反復(fù)調(diào)用,不斷更新SDIO外設(shè)配置

rthw_sd_detect 實(shí)現(xiàn)獲取卡的狀態(tài)獲取,demo里這里實(shí)際沒有實(shí)現(xiàn)

rthw_sdio_irq_update 實(shí)現(xiàn)SDIO外設(shè)中斷的開關(guān)配置

函數(shù)調(diào)用順序如下:

/* 函數(shù)調(diào)用順序 */

rt_hw_sdio_init()

-> sdio_host_create(&sdio_des)

-> mmcsd_change(host)

5. SDIO設(shè)備驅(qū)動(dòng)架構(gòu)分析

設(shè)備驅(qū)動(dòng)架構(gòu)層,也就是中間層,文件框架如下圖所示:

SD NAND,貼片式TF卡,貼片式SD卡

我們首先來看下 mmcsd_core.c 這個(gè)文件:

rt_mmcsd_core_init() 初始化函數(shù)通過 INIT_PREV_EXPORT(rt_mmcsd_core_init); 被初始化調(diào)用,同時(shí)初始化用于 mmc、sd、sdio檢測(cè)的郵箱mmcsd_detect_mb,用于熱插拔處理的 mmcsd_hotpluge_mb 以及 mmc、sd、sdio檢測(cè)線程 mmcsd_detect_thread;

在線程mmcsd_detect_thread 中,等待mmcsd_detect_mb郵箱喚醒;

當(dāng)SDIO驅(qū)動(dòng)層完成初始化話之后,通過調(diào)用 mmcsd_change(host) 函數(shù),將mmcsd_detect_thread線程喚醒,開始進(jìn)行mmc、sd卡、sdio卡的識(shí)別過程

mmcsd_core_init()函數(shù)內(nèi)容如下:

int rt_mmcsd_core_init(void)

{

rt_err_t ret;

/* initialize detect SD cart thread */

/* initialize mailbox and create detect SD card thread */

ret = rt_mb_init(&mmcsd_detect_mb, "mmcsdmb",

&mmcsd_detect_mb_pool[0], sizeof(mmcsd_detect_mb_pool) / sizeof(mmcsd_detect_mb_pool[0]),

RT_IPC_FLAG_FIFO);

RT_ASSERT(ret == RT_EOK);

ret = rt_mb_init(&mmcsd_hotpluge_mb, "mmcsdhotplugmb",

&mmcsd_hotpluge_mb_pool[0], sizeof(mmcsd_hotpluge_mb_pool) / sizeof(mmcsd_hotpluge_mb_pool[0]),

RT_IPC_FLAG_FIFO);

RT_ASSERT(ret == RT_EOK);

ret = rt_thread_init(&mmcsd_detect_thread, "mmcsd_detect", mmcsd_detect, RT_NULL,

&mmcsd_stack[0], RT_MMCSD_STACK_SIZE, RT_MMCSD_THREAD_PREORITY, 20);

if (ret == RT_EOK)

{

rt_thread_startup(&mmcsd_detect_thread);

}

rt_sdio_init();

return 0;

}

INIT_PREV_EXPORT(rt_mmcsd_core_init);

mmcsd_detect()線程以及mmcsd_change()函數(shù)如下:

mmcsd_detect() 函數(shù)主要負(fù)責(zé)完成 SDIO卡、SD卡、MMC卡的初步識(shí)別,初步識(shí)別確認(rèn)是哪種類型的卡接入之后,將會(huì)調(diào)用對(duì)應(yīng)卡驅(qū)動(dòng)文件(SD卡對(duì)應(yīng)sd.c,SDIO卡對(duì)應(yīng)sdio.c,MMC卡對(duì)應(yīng)mmc.c)內(nèi)的初始化函數(shù),重新完成卡的完整識(shí)別流程

如果對(duì)于SD卡識(shí)別流程不了解,建議先熟悉SD卡識(shí)別流程,參考 SD Nand 與 SD卡 SDIO模式應(yīng)用流程(點(diǎn)擊跳轉(zhuǎn))

具體流程見下述函數(shù)描述,對(duì)應(yīng)步驟已補(bǔ)充注釋描述

void mmcsd_change(struct rt_mmcsd_host *host)

{

rt_mb_send(&mmcsd_detect_mb, (rt_uint32_t)host);

}

void mmcsd_detect(void *param)

{

struct rt_mmcsd_host *host;

rt_uint32_t ocr;

rt_int32_t err;

while (1)

{

/* 首先等待 mmcsd_detect_mb 信號(hào)量,此信號(hào)量由 mmcsd_change() 函數(shù)發(fā)送過來 */

if (rt_mb_recv(&mmcsd_detect_mb, (rt_ubase_t *)&host, RT_WAITING_FOREVER) == RT_EOK)

{

/* 通過判斷 host->card 確認(rèn)此次操作是識(shí)別卡還是移除卡 */

if (host->card == RT_NULL) /* 識(shí)別卡 */

{

mmcsd_host_lock(host); /* 獲取鎖 */

mmcsd_power_up(host); /* 配置SDIO外設(shè)電源控制器,power up, 即卡的時(shí)鐘開啟,同時(shí)配置SDIO外設(shè)時(shí)鐘為低速模式 */

mmcsd_go_idle(host); /* 發(fā)送CMD0指令,使卡進(jìn)入空閑狀態(tài) */

mmcsd_send_if_cond(host, host->valid_ocr); /* 發(fā)送CMD8命令,查詢SD卡接口條件 (獲取OCR寄存器) */

/*

* 檢測(cè)SDIO卡使用,SD卡不用管

*/

err = sdio_io_send_op_cond(host, 0, &ocr); /* 發(fā)送CMD5命令,此處是針對(duì)SDIO卡使用,SD卡不會(huì)響應(yīng) */

if (!err) /* SD卡不會(huì)響應(yīng)此指令,因此此條件不會(huì)成立 */

{

if (init_sdio(host, ocr))

mmcsd_power_off(host);

mmcsd_host_unlock(host);

continue;

}

/*

* 檢測(cè)SD卡使用,使用SD卡重點(diǎn)關(guān)注此項(xiàng)!!!

*/

err = mmcsd_send_app_op_cond(host, 0, &ocr); /* 發(fā)送ACMD41指令(ACMD41:CMD55+CMD41) SD卡將應(yīng)答此指令 */

if (!err)

{

if (init_sd(host, ocr)) /* 此函數(shù)內(nèi)完成SD卡完整的識(shí)別流程 */

mmcsd_power_off(host); /* 設(shè)置SDIO外設(shè),電源關(guān)閉,卡的時(shí)鐘停止 */

mmcsd_host_unlock(host); /* 釋放鎖 */

rt_mb_send(&mmcsd_hotpluge_mb, (rt_uint32_t)host); /* 發(fā)送郵箱,通知熱插拔事件 */

continue;

}

/*

* 檢測(cè)MMC卡檢測(cè)使用,SD卡不用管

*/

err = mmc_send_op_cond(host, 0, &ocr);

if (!err)

{

if (init_mmc(host, ocr))

mmcsd_power_off(host);

mmcsd_host_unlock(host);

rt_mb_send(&mmcsd_hotpluge_mb, (rt_uint32_t)host);

continue;

}

mmcsd_host_unlock(host); /* 識(shí)別失敗,釋放鎖 */

}

else /* 移除卡 */

{

/* card removed */

mmcsd_host_lock(host); /* 獲取鎖 */

if (host->card->sdio_function_num != 0)

{

LOG_W("unsupport sdio card plug out!");

}

else

{

rt_mmcsd_blk_remove(host->card);

rt_free(host->card);

host->card = RT_NULL;

}

mmcsd_host_unlock(host); /* 釋放鎖 */

rt_mb_send(&mmcsd_hotpluge_mb, (rt_uint32_t)host);

}

}

}

}

在mmcsd_detect()函數(shù)內(nèi)完成SD卡的初步識(shí)別之后,之后將調(diào)用sd.c文件內(nèi)的init_sd()函數(shù)完成 sd 卡的完整識(shí)別過程

/*

* Starting point for SD card init.

*/

rt_int32_t init_sd(struct rt_mmcsd_host *host, rt_uint32_t ocr)

{

rt_int32_t err;

rt_uint32_t current_ocr;

/*

* We need to get OCR a different way for SPI.

*/

if (controller_is_spi(host)) /* 判斷是否采用SPI模式訪問SD卡 */

{

mmcsd_go_idle(host);

err = mmcsd_spi_read_ocr(host, 0, &ocr);

if (err)

goto err;

}

if (ocr & VDD_165_195)

{

LOG_I(" SD card claims to support the "

"incompletely defined 'low voltage range'. This "

"will be ignored.");

ocr &= ~VDD_165_195;

}

current_ocr = mmcsd_select_voltage(host, ocr); /* 配置SDIO外設(shè)設(shè)置為合適的電壓,對(duì)于stm32、gd32等相關(guān)控制器,實(shí)際是不支持不同等級(jí)電壓配置的,所以這里可以忽略,不過你需要注意你所使用的sd卡的電源在硬件上是匹配的 */

/*

* Can we support the voltage(s) of the card(s)?

*/

if (!current_ocr)

{

err = -RT_ERROR;

goto err;

}

/*

* Detect and init the card.

*/

err = mmcsd_sd_init_card(host, current_ocr); /* 完整的SD卡初始化流程在此函數(shù)內(nèi)實(shí)現(xiàn) */

if (err)

goto err;

mmcsd_host_unlock(host); /* 釋放鎖 */

err = rt_mmcsd_blk_probe(host->card); /* 注冊(cè)塊設(shè)備 */

if (err) /* 如果注冊(cè)塊設(shè)備失敗,將移除卡 */

goto remove_card;

mmcsd_host_lock(host); /* 獲取鎖 */

return 0;

remove_card:

mmcsd_host_lock(host); /* 獲取鎖 */

rt_mmcsd_blk_remove(host->card); /* 移除塊設(shè)備 */

rt_free(host->card); /* 釋放對(duì)應(yīng)的內(nèi)存 */

host->card = RT_NULL;

err:

LOG_D("init SD card failed!");

return err;

}

調(diào)用mmcsd_sd_init_card()函數(shù)完成SD卡檢測(cè)以及初始化配置

static rt_int32_t mmcsd_sd_init_card(struct rt_mmcsd_host *host,

rt_uint32_t ocr)

{

struct rt_mmcsd_card *card;

rt_int32_t err;

rt_uint32_t resp[4];

rt_uint32_t max_data_rate;

mmcsd_go_idle(host); /* 發(fā)送CMD0,復(fù)位SD卡,使卡進(jìn)入空閑模式 */

/*

* If SD_SEND_IF_COND indicates an SD 2.0

* compliant card and we should set bit 30

* of the ocr to indicate that we can handle

* block-addressed SDHC cards.

*/

err = mmcsd_send_if_cond(host, ocr); /* 發(fā)送CMD8指令,判斷是否為V2.0或V2.0以上的卡,并獲取OCR寄存器值 */

if (!err) /* 如果是V2.0及以上版本的卡,將置為OCR的bit30位,表明主機(jī)支持高容量SDHC卡(OCR將在ACMD41指令時(shí)作為參數(shù)發(fā)送給卡) */

ocr |= 1 << 30;

err = mmcsd_send_app_op_cond(host, ocr, RT_NULL); /* 發(fā)送ACMD41(ACMD41 = CMD55+CMD41)指令,發(fā)送主機(jī)容量支持信息,并詢問卡的操作條件 */

if (err)

goto err;

if (controller_is_spi(host)) /* 判斷是否使用SPI方式訪問SD卡 */

err = mmcsd_get_cid(host, resp); /* 采用SPI方式獲取CID寄存器值 */

else

err = mmcsd_all_get_cid(host, resp);/* 發(fā)送CMD2命令,獲取CID寄存器值 */

if (err)

goto err;

card = rt_malloc(sizeof(struct rt_mmcsd_card)); /* 創(chuàng)建rt_mmcsd_card結(jié)構(gòu)體,用于存儲(chǔ)對(duì)應(yīng)SD卡的CID寄存器內(nèi)容 */

if (!card)

{

LOG_E("malloc card failed!");

err = -RT_ENOMEM;

goto err;

}

rt_memset(card, 0, sizeof(struct rt_mmcsd_card));

card->card_type = CARD_TYPE_SD;

card->host = host;

rt_memcpy(card->resp_cid, resp, sizeof(card->resp_cid));

/*

* For native busses: get card RCA and quit open drain mode.

*/

if (!controller_is_spi(host)) /* 如果不是采用SPI方式訪問SD卡 */

{

err = mmcsd_get_card_addr(host, &card->rca); /* 發(fā)送CMD3命令,獲取RCA地址 */

if (err)

goto err1;

mmcsd_set_bus_mode(host, MMCSD_BUSMODE_PUSHPULL);/* 設(shè)置CMD總線為推挽輸出模式,需要注意的是,MMC卡V3.31版本以前的卡,初始化階段,CMD總線需要為開路模式,對(duì)于SD/SD I/O卡和MMC V4.2在初始化時(shí)也使用推挽驅(qū)動(dòng) */

}

err = mmcsd_get_csd(card, card->resp_csd); /* 發(fā)送CMD9命令,獲取CSD寄存器值 */

if (err)

goto err1;

err = mmcsd_parse_csd(card); /* 解析CSD寄存器值,將解析完成的數(shù)據(jù)存放在剛剛申請(qǐng)的card結(jié)構(gòu)體內(nèi) */

if (err)

goto err1;

if (!controller_is_spi(host)) /* 如果不是采用SPI方式訪問SD卡 */

{

err = mmcsd_select_card(card); /* 發(fā)送CMD7命令,選擇卡 */

if (err)

goto err1;

}

err = mmcsd_get_scr(card, card->resp_scr); /* 發(fā)送CMD9命令,獲取SCR寄存器值,并保存在剛剛申請(qǐng)的card結(jié)構(gòu)體內(nèi) */

if (err)

goto err1;

mmcsd_parse_scr(card); /* 解析SCR寄存器的值,并將解析結(jié)果存放在在card結(jié)構(gòu)體內(nèi) */

if (controller_is_spi(host))

{

err = mmcsd_spi_use_crc(host, 1);

if (err)

goto err1;

}

/*

* change SD card to high-speed, only SD2.0 spec

*/

err = mmcsd_switch(card); /* 發(fā)送CMD6指令,切換卡訪問速率由默認(rèn)的12.5MB/Sec為25MB/Sec高速接口 */

if (err)

goto err1;

/* set bus speed */

max_data_rate = (unsigned int)-1;

if (card->flags & CARD_FLAG_HIGHSPEED)

{

if (max_data_rate > card->hs_max_data_rate)

max_data_rate = card->hs_max_data_rate;

}

else if (max_data_rate > card->max_data_rate)

{

max_data_rate = card->max_data_rate;

}

mmcsd_set_clock(host, max_data_rate); /* 修改SDIO外設(shè)時(shí)鐘速度 */

/*switch bus width*/

if ((host->flags & MMCSD_BUSWIDTH_4) &&

(card->scr.sd_bus_widths & SD_SCR_BUS_WIDTH_4)) /* 根據(jù)SD卡的SCR寄存器反饋的值,判斷SD卡是否支持4線寬度訪問模式,如果支持則切換為4線寬度訪問模式 */

{

err = mmcsd_app_set_bus_width(card, MMCSD_BUS_WIDTH_4); /* 發(fā)送ACMD6(ACMD6=CMD55+CMD6)指令,通知SD卡切換為4線訪問模式 */

if (err)

goto err1;

mmcsd_set_bus_width(host, MMCSD_BUS_WIDTH_4); /* 修改SDIO外設(shè)配置為4線訪問模式 */

}

host->card = card; /* 將card結(jié)構(gòu)體數(shù)據(jù)與host結(jié)構(gòu)體建立綁定關(guān)系 */

return 0;

err1:

rt_free(card);

err:

return err;

}


6. 調(diào)試記錄

RT-Thread的SDIO驅(qū)動(dòng),默認(rèn)上層使用到了 elm-fatfs 文件系統(tǒng),因此通常我們配置好對(duì)應(yīng)的芯片的SDIO驅(qū)動(dòng)之后,直接就可以快速使用文件系統(tǒng)來操作訪問SD Nand了,關(guān)于文件系統(tǒng)的有關(guān)內(nèi)容,不在此文中做過多描述,有興趣的同學(xué)可以關(guān)注本人博客,后續(xù)將及時(shí)更新。

此外,在實(shí)際使用中有一點(diǎn)需要注意,當(dāng)我們首次使用芯片的時(shí)候,sd nand內(nèi)還未寫入任何數(shù)據(jù),此時(shí)通常是沒有文件系統(tǒng)的,所以當(dāng)一次執(zhí)行之后你會(huì)見到如下錯(cuò)誤:

SD NAND,貼片式TF卡,貼片式SD卡

這是由于SD nand內(nèi)沒有掛載文件系統(tǒng)導(dǎo)致,解決此問題有以下兩個(gè)方法:

方法一:在命令終端使用mkfs掛載文件系統(tǒng),具體命令步驟如下:

使用list_device查看sd nand對(duì)應(yīng)的設(shè)備名

使用mkfs命令格式化sd nand:mkfs -t elm sd0-t指定文件系統(tǒng)類型為elm-FAT文件系統(tǒng),對(duì)sd0設(shè)備操作)

由 drv_sdio.c 外設(shè)驅(qū)動(dòng)或其他調(diào)用 mmcsd_change() 觸發(fā) mmcsd_detect() 檢測(cè)

在 mmcsd_detect () 任務(wù)中,實(shí)現(xiàn)對(duì)SD卡、SD I/O卡、MMC卡的初步識(shí)別(發(fā)送對(duì)應(yīng)卡特有命令,并判斷是否正確響應(yīng)),之后根據(jù)卡片類型調(diào)用不同類型卡片驅(qū)動(dòng)文件內(nèi)的初始化程序

如針對(duì)SD卡,則調(diào)用sd.c文件內(nèi)的 init_sd() 函數(shù)完成

在init_sd()函數(shù)內(nèi)調(diào)用 mmcsd_sd_init_card() 完成SD卡的完整識(shí)別流程以及初始化流程,同時(shí)同步修改SDIO外設(shè)配置

SD卡初始化完成之后,調(diào)用 rt_mmcsd_blk_probe() 將sd卡注冊(cè)為塊設(shè)備

至此SD的識(shí)別與初始化流程順利完成

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • FlaSh
    +關(guān)注

    關(guān)注

    10

    文章

    1644

    瀏覽量

    148757
  • SD卡
    +關(guān)注

    關(guān)注

    2

    文章

    566

    瀏覽量

    64144
  • SD NAND
    +關(guān)注

    關(guān)注

    0

    文章

    84

    瀏覽量

    1294
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    雷龍SD NAND試用

    了解以便測(cè)試與使用。 芯片不用寫驅(qū)動(dòng)程序自帶壞塊管理的NAND Flash貼片式TF),尺寸小巧,簡(jiǎn)單易用,兼容性強(qiáng),穩(wěn)定可靠,固件可定
    發(fā)表于 01-19 13:26

    SD NAND、SPI NAND 和 Raw NAND 的定義與比較

    SD nand貼片SD,使用起來和SD一致,
    的頭像 發(fā)表于 01-15 18:16 ?177次閱讀
    <b class='flag-5'>SD</b> <b class='flag-5'>NAND</b>、SPI <b class='flag-5'>NAND</b> 和 Raw <b class='flag-5'>NAND</b> 的定義與比較

    關(guān)于SD NAND 的概述

    NAND芯片內(nèi)部包含一個(gè)控制器和一個(gè)Flash存儲(chǔ)單元,支持SDIO模式和SPI模式,具備ECC、磨損平均、電源管理和時(shí)鐘控制等功能。   封裝優(yōu)勢(shì):采用LGA-8封裝,便于機(jī)器貼片
    發(fā)表于 12-06 11:22

    【S32K146 RT-Thread】之 使用SFUD組件驅(qū)動(dòng)spi flash

    【S32K146 RT-Thread】之 使用SFUD組件驅(qū)動(dòng)spi flash
    的頭像 發(fā)表于 11-21 01:05 ?438次閱讀
    【S32K146 <b class='flag-5'>RT-Thread</b>】之 使用SFUD組件<b class='flag-5'>驅(qū)動(dòng)</b>spi <b class='flag-5'>flash</b>

    基于NXP MCXA153 MCU實(shí)現(xiàn)RT-Thread的MTD NOR Flash驅(qū)動(dòng)

    在嵌入式系統(tǒng)中,片上Flash存儲(chǔ)器是一個(gè)關(guān)鍵組件,用于存儲(chǔ)程序代碼和關(guān)鍵數(shù)據(jù)。本文將詳細(xì)介紹如何在NXPMCXA153 MCU上實(shí)現(xiàn)RT-Thread的MTD (Memory Technology Device) NOR Flash
    的頭像 發(fā)表于 11-09 14:00 ?654次閱讀
    基于NXP MCXA153 MCU實(shí)現(xiàn)<b class='flag-5'>RT-Thread</b>的MTD NOR <b class='flag-5'>Flash</b><b class='flag-5'>驅(qū)動(dòng)</b>

    國(guó)產(chǎn)安路FPGA SD NAND FLASH 初步描述

    說起SD NAND FLASH常被聯(lián)想到SDSD NAN
    發(fā)表于 10-16 18:12

    【好書推薦】RT-Thread設(shè)備驅(qū)動(dòng)開發(fā)指南

    近年來國(guó)內(nèi)芯片產(chǎn)業(yè)和物聯(lián)網(wǎng)產(chǎn)業(yè)的快速崛起,行業(yè)發(fā)展迫切需要更多人才,尤其需要掌握嵌入式操作系統(tǒng)等底層技術(shù)的人才。隨著RT-Thread被更廣泛地應(yīng)用于行業(yè)中,開發(fā)者對(duì)嵌入式驅(qū)動(dòng)開發(fā)的需求越來越
    的頭像 發(fā)表于 08-01 08:35 ?744次閱讀
    【好書推薦】<b class='flag-5'>RT-Thread</b>設(shè)備<b class='flag-5'>驅(qū)動(dòng)</b>開發(fā)指南

    貼片SD功能介紹【MK SD NAND

    SDNAND,通常稱為嵌入式SD貼片式TFSD Flash、直接貼裝
    的頭像 發(fā)表于 07-05 17:03 ?934次閱讀
    <b class='flag-5'>貼片</b>式<b class='flag-5'>SD</b><b class='flag-5'>卡</b>功能介紹【MK <b class='flag-5'>SD</b> <b class='flag-5'>NAND</b>】

    貼片式tf Nand flash芯片試用體驗(yàn)

    Flash貼片式TF),尺寸小巧,簡(jiǎn)單易用,兼容性強(qiáng),穩(wěn)定可靠,固件可定制,LGA-8封裝,標(biāo)準(zhǔn)SDIO接口,兼容SPI,兼容拔插式TF
    發(fā)表于 06-05 17:57

    【GD32H757Z海棠派開發(fā)板使用手冊(cè)】第十二講 SDIO-SD讀寫實(shí)驗(yàn)

    SD是一種主要以Nand Flash作為存儲(chǔ)介質(zhì),具有體積小、數(shù)據(jù)傳輸速度快以及支持熱插拔的優(yōu)點(diǎn)。如今,已被廣泛應(yīng)用于數(shù)碼相機(jī)、便攜式移動(dòng)設(shè)備以及手機(jī)等多種設(shè)備中。
    的頭像 發(fā)表于 06-05 10:35 ?848次閱讀
    【GD32H757Z海棠派開發(fā)板使用手冊(cè)】第十二講 <b class='flag-5'>SDIO-SD</b><b class='flag-5'>卡</b>讀寫實(shí)驗(yàn)

    SD NAND 簡(jiǎn)介

    SD NAND是一種創(chuàng)新的存儲(chǔ)芯片,可直接貼片,又名貼片式TF貼片式T
    的頭像 發(fā)表于 05-29 16:34 ?1322次閱讀
    <b class='flag-5'>SD</b> <b class='flag-5'>NAND</b> 簡(jiǎn)介

    NAND Flash貼片式TF)存儲(chǔ)新突破,基礎(chǔ)示例

    服務(wù),把數(shù)據(jù)存儲(chǔ)在云端。   SD NAND的特性與優(yōu)勢(shì)   以CSNP4GCR01-AMW為例。   不用寫驅(qū)動(dòng)程序自帶壞塊管理的NAND Fl
    發(fā)表于 05-21 17:13

    RT-Thread驅(qū)動(dòng)開發(fā)指南進(jìn)階篇-動(dòng)手驅(qū)動(dòng)先楫未適配的外設(shè)LCD

    經(jīng)過上一篇的《《RT-Thread設(shè)備驅(qū)動(dòng)開發(fā)指南》基礎(chǔ)篇--以先楫bsp的hwtimer設(shè)備為例》闡述,可以大致了解到RT-thread設(shè)備驅(qū)動(dòng)開發(fā)的方法步驟,開發(fā)指南中的進(jìn)階篇外設(shè)
    的頭像 發(fā)表于 02-25 11:04 ?2839次閱讀
    <b class='flag-5'>RT-Thread</b><b class='flag-5'>驅(qū)動(dòng)</b>開發(fā)指南進(jìn)階篇-動(dòng)手<b class='flag-5'>驅(qū)動(dòng)</b>先楫未適配的外設(shè)LCD

    RT-Thread設(shè)備驅(qū)動(dòng)開發(fā)指南》基礎(chǔ)篇--以先楫bsp的hwtimer設(shè)備為例

    一、概述(一)RT-Thread設(shè)備驅(qū)動(dòng)RT-Thread設(shè)備驅(qū)動(dòng)開發(fā)指南》書籍是RT-thread官方出品撰寫,系統(tǒng)講解
    的頭像 發(fā)表于 02-24 08:16 ?1875次閱讀
    《<b class='flag-5'>RT-Thread</b>設(shè)備<b class='flag-5'>驅(qū)動(dòng)</b>開發(fā)指南》基礎(chǔ)篇--以先楫bsp的hwtimer設(shè)備為例

    RT-Thread SDIO驅(qū)動(dòng)SDget scr返回失敗是什么原因呢?

    STM32F429芯片,rt-thread標(biāo)準(zhǔn)版,添加了SD驅(qū)動(dòng),調(diào)試時(shí)發(fā)現(xiàn)在mmcsd_get_scr時(shí)返回-1,打印錯(cuò)誤日志發(fā)現(xiàn)是cmd.err=-1,這是什么原因呢? 打印信
    發(fā)表于 02-23 06:05
    主站蜘蛛池模板: 久久婷婷五综合一区二区 | 国产亚洲第一伦理第一区 | 在线你懂得 | 视频在线观看免费视频 | www.av在线免费观看 | 亚洲一区二区三区在线 | 一卡二卡≡卡四卡亚洲高清 | 精品久久久久久中文字幕欧美 | 色香视频在线 | 男女爱爱视频免费 | 九色视频在线看 | 久久综合色区 | 91夜夜人人揉人人捏人人添 | www狠狠干| 国产精品毛片在线大全 | 亚洲色图视频在线 | 一级aa 毛片高清免费看 | 日本黄色美女视频 | 天天做天天爱天天一爽一毛片 | 久久精品视频5 | 9984四虎永久免费网站 | 久久mimi色| 亚洲人成在线精品不卡网 | 精品国产自在在线在线观看 | 双性受粗大撑开白浊 | 女人张开腿让男人桶视频免费大全 | 好男人www社区影视在线 | 午夜毛片不卡高清免费 | 91av在线免费观看 | 永久精品免费影院在线观看网站 | 三级免费黄色片 | 国产人成午夜免视频网站 | www.天天干.com | 亚洲成人激情电影 | 国产成人精品日本亚洲网站 | 国产精品久久久久久久久久影院 | 国产二区三区 | 天天爱夜夜做 | 天天爱天天做天天爽天天躁 | 中文字幕亚洲综合久久2 | 一区在线视频 |