0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

rt-thread SDIO驱动框架分析(贴片SD卡flash驱动\SD Nand flash驱动)

深圳市雷龙发展有限公司 2023-04-04 17:41 次阅读

文章目录

rt-thread SDIO驱动框架分析之SD卡驱动

1. 前言

2. SDIO通用驱动框架介绍

3. 文件架构分析

4. SDIO设备驱动分析

5. SDIO设备驱动架构分析

6. 调试记录

7. 总结


1. 前言

RT-Thread是一款国产化的嵌入式操作系统,目前在嵌入式领域得到广泛应用,其强大的扩展功能以及通用的外设驱动框架备受大家追捧。

关于基本的外设驱动,其官网上基本也都有部分描述,但是关于SDIO设备驱动目前为止还没有相关文档说明,因此本文笔者将根据自己的调试使用经验,与大家分享下rtthread的通用SDIO设备驱动的实现。

本文基于代码仓库 rt-thread/bsp/stm32/stm32f103-fire-arbitrary 分析代码

分支:main

commit:6808f48bdcf914f03ac757cc19b264a5d0db56de

说明:main分支会有不断更新,但是SDIO驱动框架目前应该不会有大变更

硬件介绍:

控制器:STM32 基于手上为数不多的野火开发板吧

SD卡:本次采用的并非SD卡,而是创世CS家的一颗SD Nand, CSNP4GCR01-AMW,有幸申请到了一颗样片

这里多说几句,SD nand使用起来和SD卡完全一样,而且SD Nand相比SD卡感觉好用太多,贴片LGA-8封装,和SPI flash 差不多,完美的解决了SD卡松动导致系统不稳定的问题,而且容量又大,个人感觉以后必定是嵌入式存储应用上的主流 (除了价格贵点啥都好,哈哈)想要样片试试水的可以去找深圳雷龙公司官网申请下

2. SDIO通用驱动框架介绍

首先来介绍下 SDIO 通用驱动框架。

RT-Thread 区别于其他操作系统,如FreeRTOS,的一大重要特征是,RT-Thread 中引入了设备驱动框架,并且针对绝大多数外设基本上都已完成对应的设备驱动框架编写,所谓的设备驱动框架,也就是我们所说的建立在应用层与底层驱动层之间的中间件

如下图所示:

应用层:完成业务应用,调用通用接口操作设备驱动层

设备驱动框架层:完成外设通用驱动框架设计,脱离具体的芯片,将驱动中相同部分,如针对SPI,关于SPI的完整读写逻辑等抽离出来

设备驱动层:完成对应芯片的外设驱动程序编写,实现设备驱动框架层的具体接口

SD NAND,贴片式TF卡,贴片式SD卡

对于SDIO外设亦是如此:

在设备驱动框架层中,实现SD卡、SDIO卡、MMC卡的通用外设驱动逻辑,如卡的识别、卡的模块切换、卡的读写操作等,这些都是通用的,遵循SD标准协议;

在设备驱动层中,根据对应的硬件,完成具体芯片的SDIO外设配置,并实现设备驱动框架层所需要实现的具体接口,如发送CMD命令等。

在应用层实现具体的应用,应用层与驱动层解耦

通过这种方式,这样便可以轻松的做到:

需要驱动具体的SD、SDIO、MMC时,根据具体的芯片实现对应的SDIO驱动接口即可

应用层可直接移植,如出现方案芯片替代时,只需完成设备驱动层适配即可

这也就是RT-Thread让众多开发者疯狂追捧的重大原因了,接下来,我们将具体分析关于SD卡的具体框架层实现,关于SDIO卡、MMC卡,由于使用不多,本文不做深入分析。

3. 文件架构分析

首先我们先来看下SDIO驱动框架有关文件及架构

SDIO驱动框架文件:

SD NAND,贴片式TF卡,贴片式SD卡

SDIO驱动框架文件架构:

SD NAND,贴片式TF卡,贴片式SD卡

4. SDIO设备驱动分析

设备驱动与驱动框架文件在不同的目录,设备驱动一般在 bsp 目录中

通常设备驱动完成以下几个事情:

初始化具体外设有关数据结构;

完成具体外设初始化程序编写;

实现设备框架层的具体接口,如:open,read,write,close,control 等;

将具体设备注册到内核中;

需要注意的是,SDIO设备驱动会有些许区别,在SDIO设备驱动程序中,主要完成以下几件事:

初始化具体外设有关数据结构;

SDIO外设的初始化配置;

实现设备框架层的以下几个接口:

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.通知驱动框架层(此处demo程序默认上电前sd卡已接入);

以 rt-thread/bsp/stm32/libraries/HAL_Drivers/drv_sdio.c 程序为例,SDIO驱动层程序从 rt_hw_sdio_init 函数开始,由于使能了自动初始化,此函数由 INIT_DEVICE_EXPORT(rt_hw_sdio_init); 宏实现初始化调用

(关于自动初始化如何实现的细节,可参考笔者另外一篇博文对自动初始化的详细分析:代码自动初始化(点击跳转))

在 rt_hw_sdio_init 函数中,驱动程序主要初始化以下几个结构体:

stm32外设HAL库配置结构体 SD_HandleTypeDef hsd

stm32 sdio 设备结构体 struct stm32_sdio_des sdio_des

sdio硬件外设结构体 struct rthw_sdio *sdio

mmc sd host结构体struct rt_mmcsd_host

其关系如下图所示:

SD NAND,贴片式TF卡,贴片式SD卡

结构体数据初始化完成以后,调用mmcsd_change()函数,触发框架层逻辑

SD NAND,贴片式TF卡,贴片式SD卡

此外,在设备驱动层提供的操作函数主要有:

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 实现一次SDIO数据发送

rthw_sdio_iocfg 实现SDIO外设配置,注意在SD识别过程中会反复调用,不断更新SDIO外设配置

rthw_sd_detect 实现获取卡的状态获取,demo里这里实际没有实现

rthw_sdio_irq_update 实现SDIO外设中断的开关配置

函数调用顺序如下:

/* 函数调用顺序 */

rt_hw_sdio_init()

-> sdio_host_create(&sdio_des)

-> mmcsd_change(host)

5. SDIO设备驱动架构分析

设备驱动架构层,也就是中间层,文件框架如下图所示:

SD NAND,贴片式TF卡,贴片式SD卡

我们首先来看下 mmcsd_core.c 这个文件:

rt_mmcsd_core_init() 初始化函数通过 INIT_PREV_EXPORT(rt_mmcsd_core_init); 被初始化调用,同时初始化用于 mmc、sd、sdio检测的邮箱mmcsd_detect_mb,用于热插拔处理的 mmcsd_hotpluge_mb 以及 mmc、sd、sdio检测线程 mmcsd_detect_thread;

在线程mmcsd_detect_thread 中,等待mmcsd_detect_mb邮箱唤醒;

当SDIO驱动层完成初始化话之后,通过调用 mmcsd_change(host) 函数,将mmcsd_detect_thread线程唤醒,开始进行mmc、sd卡、sdio卡的识别过程

mmcsd_core_init()函数内容如下:

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()函数如下:

mmcsd_detect() 函数主要负责完成 SDIO卡、SD卡、MMC卡的初步识别,初步识别确认是哪种类型的卡接入之后,将会调用对应卡驱动文件(SD卡对应sd.c,SDIO卡对应sdio.c,MMC卡对应mmc.c)内的初始化函数,重新完成卡的完整识别流程

如果对于SD卡识别流程不了解,建议先熟悉SD卡识别流程,参考 SD Nand 与 SD卡 SDIO模式应用流程(点击跳转)

具体流程见下述函数描述,对应步骤已补充注释描述

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 信号量,此信号量由 mmcsd_change() 函数发送过来 */

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

{

/* 通过判断 host->card 确认此次操作是识别卡还是移除卡 */

if (host->card == RT_NULL) /* 识别卡 */

{

mmcsd_host_lock(host); /* 获取锁 */

mmcsd_power_up(host); /* 配置SDIO外设电源控制器,power up, 即卡的时钟开启,同时配置SDIO外设时钟为低速模式 */

mmcsd_go_idle(host); /* 发送CMD0指令,使卡进入空闲状态 */

mmcsd_send_if_cond(host, host->valid_ocr); /* 发送CMD8命令,查询SD卡接口条件 (获取OCR寄存器) */

/*

* 检测SDIO卡使用,SD卡不用管

*/

err = sdio_io_send_op_cond(host, 0, &ocr); /* 发送CMD5命令,此处是针对SDIO卡使用,SD卡不会响应 */

if (!err) /* SD卡不会响应此指令,因此此条件不会成立 */

{

if (init_sdio(host, ocr))

mmcsd_power_off(host);

mmcsd_host_unlock(host);

continue;

}

/*

* 检测SD卡使用,使用SD卡重点关注此项!!!

*/

err = mmcsd_send_app_op_cond(host, 0, &ocr); /* 发送ACMD41指令(ACMD41:CMD55+CMD41) SD卡将应答此指令 */

if (!err)

{

if (init_sd(host, ocr)) /* 此函数内完成SD卡完整的识别流程 */

mmcsd_power_off(host); /* 设置SDIO外设,电源关闭,卡的时钟停止 */

mmcsd_host_unlock(host); /* 释放锁 */

rt_mb_send(&mmcsd_hotpluge_mb, (rt_uint32_t)host); /* 发送邮箱,通知热插拔事件 */

continue;

}

/*

* 检测MMC卡检测使用,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); /* 识别失败,释放锁 */

}

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()函数内完成SD卡的初步识别之后,之后将调用sd.c文件内的init_sd()函数完成 sd 卡的完整识别过程

/*

* 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外设设置为合适的电压,对于stm32、gd32等相关控制器,实际是不支持不同等级电压配置的,所以这里可以忽略,不过你需要注意你所使用的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卡初始化流程在此函数内实现 */

if (err)

goto err;

mmcsd_host_unlock(host); /* 释放锁 */

err = rt_mmcsd_blk_probe(host->card); /* 注册块设备 */

if (err) /* 如果注册块设备失败,将移除卡 */

goto remove_card;

mmcsd_host_lock(host); /* 获取锁 */

return 0;

remove_card:

mmcsd_host_lock(host); /* 获取锁 */

rt_mmcsd_blk_remove(host->card); /* 移除块设备 */

rt_free(host->card); /* 释放对应的内存 */

host->card = RT_NULL;

err:

LOG_D("init SD card failed!");

return err;

}

调用mmcsd_sd_init_card()函数完成SD卡检测以及初始化配置

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); /* 发送CMD0,复位SD卡,使卡进入空闲模式 */

/*

* 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); /* 发送CMD8指令,判断是否为V2.0或V2.0以上的卡,并获取OCR寄存器值 */

if (!err) /* 如果是V2.0及以上版本的卡,将置为OCR的bit30位,表明主机支持高容量SDHC卡(OCR将在ACMD41指令时作为参数发送给卡) */

ocr |= 1 << 30;

err = mmcsd_send_app_op_cond(host, ocr, RT_NULL); /* 发送ACMD41(ACMD41 = CMD55+CMD41)指令,发送主机容量支持信息,并询问卡的操作条件 */

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);/* 发送CMD2命令,获取CID寄存器值 */

if (err)

goto err;

card = rt_malloc(sizeof(struct rt_mmcsd_card)); /* 创建rt_mmcsd_card结构体,用于存储对应SD卡的CID寄存器内容 */

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); /* 发送CMD3命令,获取RCA地址 */

if (err)

goto err1;

mmcsd_set_bus_mode(host, MMCSD_BUSMODE_PUSHPULL);/* 设置CMD总线为推挽输出模式,需要注意的是,MMC卡V3.31版本以前的卡,初始化阶段,CMD总线需要为开路模式,对于SD/SD I/O卡和MMC V4.2在初始化时也使用推挽驱动 */

}

err = mmcsd_get_csd(card, card->resp_csd); /* 发送CMD9命令,获取CSD寄存器值 */

if (err)

goto err1;

err = mmcsd_parse_csd(card); /* 解析CSD寄存器值,将解析完成的数据存放在刚刚申请的card结构体内 */

if (err)

goto err1;

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

{

err = mmcsd_select_card(card); /* 发送CMD7命令,选择卡 */

if (err)

goto err1;

}

err = mmcsd_get_scr(card, card->resp_scr); /* 发送CMD9命令,获取SCR寄存器值,并保存在刚刚申请的card结构体内 */

if (err)

goto err1;

mmcsd_parse_scr(card); /* 解析SCR寄存器的值,并将解析结果存放在在card结构体内 */

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); /* 发送CMD6指令,切换卡访问速率由默认的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外设时钟速度 */

/*switch bus width*/

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

(card->scr.sd_bus_widths & SD_SCR_BUS_WIDTH_4)) /* 根据SD卡的SCR寄存器反馈的值,判断SD卡是否支持4线宽度访问模式,如果支持则切换为4线宽度访问模式 */

{

err = mmcsd_app_set_bus_width(card, MMCSD_BUS_WIDTH_4); /* 发送ACMD6(ACMD6=CMD55+CMD6)指令,通知SD卡切换为4线访问模式 */

if (err)

goto err1;

mmcsd_set_bus_width(host, MMCSD_BUS_WIDTH_4); /* 修改SDIO外设配置为4线访问模式 */

}

host->card = card; /* 将card结构体数据与host结构体建立绑定关系 */

return 0;

err1:

rt_free(card);

err:

return err;

}


6. 调试记录

RT-Thread的SDIO驱动,默认上层使用到了 elm-fatfs 文件系统,因此通常我们配置好对应的芯片的SDIO驱动之后,直接就可以快速使用文件系统来操作访问SD Nand了,关于文件系统的有关内容,不在此文中做过多描述,有兴趣的同学可以关注本人博客,后续将及时更新。

此外,在实际使用中有一点需要注意,当我们首次使用芯片的时候,sd nand内还未写入任何数据,此时通常是没有文件系统的,所以当一次执行之后你会见到如下错误:

SD NAND,贴片式TF卡,贴片式SD卡

这是由于SD nand内没有挂载文件系统导致,解决此问题有以下两个方法:

方法一:在命令终端使用mkfs挂载文件系统,具体命令步骤如下:

使用list_device查看sd nand对应的设备名

使用mkfs命令格式化sd nand:mkfs -t elm sd0-t指定文件系统类型为elm-FAT文件系统,对sd0设备操作)

由 drv_sdio.c 外设驱动或其他调用 mmcsd_change() 触发 mmcsd_detect() 检测

在 mmcsd_detect () 任务中,实现对SD卡、SD I/O卡、MMC卡的初步识别(发送对应卡特有命令,并判断是否正确响应),之后根据卡片类型调用不同类型卡片驱动文件内的初始化程序

如针对SD卡,则调用sd.c文件内的 init_sd() 函数完成

在init_sd()函数内调用 mmcsd_sd_init_card() 完成SD卡的完整识别流程以及初始化流程,同时同步修改SDIO外设配置

SD卡初始化完成之后,调用 rt_mmcsd_blk_probe() 将sd卡注册为块设备

至此SD的识别与初始化流程顺利完成

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • FlaSh
    +关注

    关注

    10

    文章

    1633

    浏览量

    147940
  • SD卡
    +关注

    关注

    2

    文章

    564

    浏览量

    63889
  • SD NAND
    +关注

    关注

    0

    文章

    83

    浏览量

    1234
收藏 人收藏

    评论

    相关推荐

    关于SD NAND 的概述

    NAND芯片内部包含一个控制器和一个Flash存储单元,支持SDIO模式和SPI模式,具备ECC、磨损平均、电源管理和时钟控制等功能。   封装优势:采用LGA-8封装,便于机器贴片
    发表于 12-06 11:22

    【S32K146 RT-Thread】之 使用SFUD组件驱动spi flash

    【S32K146 RT-Thread】之 使用SFUD组件驱动spi flash
    的头像 发表于 11-21 01:05 261次阅读
    【S32K146 <b class='flag-5'>RT-Thread</b>】之 使用SFUD组件<b class='flag-5'>驱动</b>spi <b class='flag-5'>flash</b>

    基于NXP MCXA153 MCU实现RT-Thread的MTD NOR Flash驱动

    在嵌入式系统中,片上Flash存储器是一个关键组件,用于存储程序代码和关键数据。本文将详细介绍如何在NXPMCXA153 MCU上实现RT-Thread的MTD (Memory Technology Device) NOR Flash
    的头像 发表于 11-09 14:00 435次阅读
    基于NXP MCXA153 MCU实现<b class='flag-5'>RT-Thread</b>的MTD NOR <b class='flag-5'>Flash</b><b class='flag-5'>驱动</b>

    国产安路FPGA SD NAND FLASH 初步描述

    说起SD NAND FLASH常被联想到SDSD NAN
    发表于 10-16 18:12

    贴片SD功能介绍【MK SD NAND

    SDNAND,通常称为嵌入式SD贴片式TFSD Flash、直接贴装
    的头像 发表于 07-05 17:03 771次阅读
    <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芯片试用体验

    Flash贴片式TF),尺寸小巧,简单易用,兼容性强,稳定可靠,固件可定制,LGA-8封装,标准SDIO接口,兼容SPI,兼容拔插式TF
    发表于 06-05 17:57

    【GD32H757Z海棠派开发板使用手册】第十二讲 SDIO-SD读写实验

    SD是一种主要以Nand Flash作为存储介质,具有体积小、数据传输速度快以及支持热插拔的优点。如今,已被广泛应用于数码相机、便携式移动设备以及手机等多种设备中。
    的头像 发表于 06-05 10:35 694次阅读
    【GD32H757Z海棠派开发板使用手册】第十二讲 <b class='flag-5'>SDIO-SD</b><b class='flag-5'>卡</b>读写实验

    SD NAND 简介

    SD NAND是一种创新的存储芯片,可直接贴片,又名贴片式TF贴片式T
    的头像 发表于 05-29 16:34 1186次阅读
    <b class='flag-5'>SD</b> <b class='flag-5'>NAND</b> 简介

    NAND Flash贴片式TF)存储新突破,基础示例

    服务,把数据存储在云端。   SD NAND的特性与优势   以CSNP4GCR01-AMW为例。   不用写驱动程序自带坏块管理的NAND Fl
    发表于 05-21 17:13

    RT-Thread驱动开发指南进阶篇-动手驱动先楫未适配的外设LCD

    经过上一篇的《《RT-Thread设备驱动开发指南》基础篇--以先楫bsp的hwtimer设备为例》阐述,可以大致了解到RT-thread设备驱动开发的方法步骤,开发指南中的进阶篇外设
    的头像 发表于 02-25 11:04 2516次阅读
    <b class='flag-5'>RT-Thread</b><b class='flag-5'>驱动</b>开发指南进阶篇-动手<b class='flag-5'>驱动</b>先楫未适配的外设LCD

    RT-Thread设备驱动开发指南》基础篇--以先楫bsp的hwtimer设备为例

    一、概述(一)RT-Thread设备驱动RT-Thread设备驱动开发指南》书籍是RT-thread官方出品撰写,系统讲解
    的头像 发表于 02-24 08:16 1632次阅读
    《<b class='flag-5'>RT-Thread</b>设备<b class='flag-5'>驱动</b>开发指南》基础篇--以先楫bsp的hwtimer设备为例

    RT-Thread SDIO驱动SDget scr返回失败是什么原因呢?

    STM32F429芯片,rt-thread标准版,添加了SD驱动,调试时发现在mmcsd_get_scr时返回-1,打印错误日志发现是cmd.err=-1,这是什么原因呢? 打印信
    发表于 02-23 06:05

    CS 创世SD NAND FLASH 存储芯片,比TF更小巧轻便易用的大容量存储,TF替代方案

    /6196382.html   下图是大小比对,可以看到 创世SD NAND的尺寸非常小,而且是一种可以表贴的存储芯片。 []()   SD NAND
    发表于 01-24 18:30

    什么是SD NAND存储芯片? SD NAND与TF的区别

    什么是SD NAND?它俗称贴片式T贴片式TF贴片
    的头像 发表于 01-06 14:35 1773次阅读
    什么是<b class='flag-5'>SD</b> <b class='flag-5'>NAND</b>存储芯片? <b class='flag-5'>SD</b> <b class='flag-5'>NAND</b>与TF<b class='flag-5'>卡</b>的区别

    什么是SD NAND存储芯片?

    ![](//file1.elecfans.com/web2/M00/BB/22/wKgZomWXzQSAOlprAAENYh0MY3Y411.   不用写驱动程序自带坏块管理的NAND Flash
    发表于 01-05 17:54