MMC
该示例演示了如何使用 SD library实现芯片与 MMC 读、写的应用。
示例中首先对存储卡进行初始化,并对存储卡进行了数据写入操作。随后进行数据读取并检查与之前写入的数据是否一致。
环境需求
该示例支持以下开发套件:
Hardware Platforms |
Board Name |
---|---|
RTL87x2G HDK |
RTL87x2G EVB |
更多信息请参考快速入门。
硬件连线
MMC子板及接线,参考Model B评估板 中 WiFi和SD Nand Flash复用接口 。
MMC接口引脚如下表:
引脚名称 |
PIN |
含义 |
---|---|---|
DAT3 / CS |
P9_5 |
数据线3 |
CMD / DI |
P9_3 |
命令响应线 |
VSS1 |
GND |
GND |
VDD |
VCC(3.3V) |
3.3V供电 |
CLK |
P9_4 |
时钟 |
VSS2 |
GND |
GND |
DAT0 / DO |
P10_0 |
数据线0 |
DAT1 |
P9_7 |
数据线1 |
DAT2 |
P9_6 |
数据线2 |
编译和下载
该示例的工程路径如下:
Project file: samples\sd\mmc\proj\mdk
Project file: samples\sd\mmc\proj\gcc
请按照以下步骤操作构建并运行该示例:
打开工程文件。
按照 快速入门 中 编译APP Image 给出的步骤构建目标文件。
编译成功后,在路径
mdk\bin
或gcc\bin
下会生成 app binapp_MP_xxx.bin
文件。按下复位按键,开始运行。
测试验证
当EVB启动后,在Debug Analyzer工具内观察MMC初始化的状态,认卡成功则打印状态:
Init: 0
。Init: 0
将准备好的数据(前30 block数据为0xff,后30 block数据为0x00)写到MMC中,写成功则打印状态:
Write: 0
。Write: 0
读MMC数据,读成功则打印状态:
Read: 0
,同时打印读到的数据。Read: 0 Block 0: 0x0000 -> 0xFF - 0xFF - 0xFF - 0xFF --- 0xFF - 0xFF - 0xFF - 0xFF ... Block 30: 0x0000 -> 0x00 - 0x00 - 0x00 - 0x00 --- 0x00 - 0x00 - 0x00 - 0x00 ...
检查读写数据是否一致,如果不一致会打印错误数据,例如:第1 block第 100 个数据错误数据为0x33打印如下:
Block 0: 0xA0 -> 0x33 data error
代码介绍
该章节分为以下几个部分:
源码路径
工程路径:
sdk\samples\sd\mmc\proj
源码路径:
sdk\samples\sd\mmc\src
该工程的工程文件代码结构如下:
└── Project: mmc
└── secure_only_app
└── Device includes startup code
├── startup_rtl.c
└── system_rtl.c
├── CMSIS includes CMSIS header files
├── CMSE Library Non-secure callable lib
├── lib includes all binary symbol files that user application is built on
├── sd.lib
└── rtl87x2g_io.lib
├── peripheral includes all peripheral drivers and module code used by the application
├── rtl_rcc.c
├── rtl_pinmux.c
├── io_dlps.c
└── rtl_nvic.c
└── APP includes the ble_peripheral user application implementation
├── main_ns.c
├── app_task.c
└── sd_test.c
初始化
设置初始化参数。
设置Card类型为EMMC。
设置数据宽度为4BIT。
设置时钟输出频率为52MHz。
static const SdEmmcInitParm_t Parm =
{
.CardType = CARDTYPE_EMMC,
.DataWidth = DATAWIDTH_4BIT,
.ClkOutFreq_kHz = 52 * 1000,
};
...
功能实现
执行
Emmc_Init
,对MMC初始化。执行
os_mem_alloc
申请内存pBuf。准备好数据(前30 block数据为0xff,后30 block数据为0x00),执行
Emmc_Write
函数,将pBuf数据写入MMC中。将pBuf数据预填为0x77,执行
Emmc_Read
函数,读取数据到pBuf内。打印读取的数据,同时检查读写数据是否一致,如果不一致会打印错误数据。
执行
os_mem_free
释放内存pBuf。
SdEmmcRes_t Res = Init(SD_Demo, &Parm);
uint8_t *pBuf = os_mem_alloc(RAM_TYPE_EXT_DATA_SRAM, BUF_BYTES);
memset(pBuf, 0xff, BUF_BYTES / 2);
memset(pBuf + BUF_BYTES / 2, 0, BUF_BYTES / 2);
Res = Write(SD_Demo, START_BLOCK, BLOCK_CNT, pBuf);
memset(pBuf, 0x77, BUF_BYTES);
Res = Read(SD_Demo, START_BLOCK, BLOCK_CNT, pBuf);
/* Print all read data */
for (size_t i = 0; i < BUF_BYTES; i += 8)
{
DBG_DIRECT("Block %d: 0x%04x -> 0x%02x - 0x%02x - 0x%02x - 0x%02x --- 0x%02x - 0x%02x - 0x%02x - 0x%02x",
i / 512, i % 512,
pBuf[i], pBuf[i + 1], pBuf[i + 2], pBuf[i + 3],
pBuf[i + 4], pBuf[i + 5], pBuf[i + 6], pBuf[i + 7]);
}
/* Compare whether the read data is correct from write data */
for (uint32_t j = 0; j < BUF_BYTES; j++)
{
if (((j < BUF_BYTES / 2) && ((pBuf[j] != 0xff))) ||
((j >= BUF_BYTES / 2) && (j < BUF_BYTES) && (pBuf[j] != 0x00)))
{
DBG_DIRECT("Block %d: 0x%04x -> 0x%02x data error", j / 512, j % 512, pBuf[j]);
if (pBuf[j] == 0x77) { break; }
}
}
os_mem_free(pBuf);