2022-11-10 22:22:48 +08:00
|
|
|
|
# FSDMMC 驱动程序
|
|
|
|
|
|
|
|
|
|
## 1. 概述
|
|
|
|
|
|
|
|
|
|
SD/MMC控制器主要提供对固态非易失性存储的内存卡的访问能力,包括多媒体存储卡(MMC,MultiMedia Card)和安全和数据保护卡(SD,Secure Digital Card)。
|
|
|
|
|
|
|
|
|
|
## 2. 功能
|
|
|
|
|
|
|
|
|
|
SD/MMC控制器驱动提供了SD/MMC卡的控制访问方法,
|
|
|
|
|
- 初始化SD/MMC控制器
|
|
|
|
|
- 以轮询方式发送/接收数据和命令
|
|
|
|
|
- 以中断方式发送/接收数据和命令
|
|
|
|
|
- 设置SD/MMC控制器的中断工作模式和中断响应函数
|
|
|
|
|
|
|
|
|
|
访问SD/MMC卡需要兼容一系列协议命令,这一部分驱动不提供,可以通过第三方框架sdmmc使用
|
|
|
|
|
|
|
|
|
|
驱动相关的源文件包括,
|
|
|
|
|
```
|
|
|
|
|
fsdmmc
|
|
|
|
|
├── fsdmmc.c
|
|
|
|
|
├── fsdmmc.h
|
|
|
|
|
├── fsdmmc_dma.c
|
|
|
|
|
├── fsdmmc_dma.h
|
|
|
|
|
├── fsdmmc_g.c
|
|
|
|
|
├── fsdmmc_hw.c
|
|
|
|
|
├── fsdmmc_hw.h
|
|
|
|
|
├── fsdmmc_intr.c
|
|
|
|
|
└── fsdmmc_sinit.c
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## 3. 配置方法
|
|
|
|
|
|
|
|
|
|
以下部分将指导您完成 FSDMMC 驱动的软件配置:
|
|
|
|
|
|
|
|
|
|
- 初始化FSDMMC控制器
|
|
|
|
|
- 通过协议命令完成SD/MMC卡初始化
|
|
|
|
|
- 通过协议命令读写SD/MMC卡数据
|
|
|
|
|
|
|
|
|
|
## 4 应用示例
|
|
|
|
|
|
|
|
|
|
### [检测SD卡](../../../baremetal/example/peripheral/mmc/fsdmmc_probe)
|
|
|
|
|
|
|
|
|
|
### [SD/MMC卡协议实现](../../../third-party/sdmmc)
|
|
|
|
|
|
|
|
|
|
### [通过协议命令读写SD卡](../../../baremetal/example/storage/sdmmc_cmds)
|
|
|
|
|
|
|
|
|
|
### [通过文件系统使用SD卡](../../../baremetal/example/storage/sdmmc_fatfs)
|
|
|
|
|
|
|
|
|
|
## 5. API参考
|
|
|
|
|
|
|
|
|
|
### 5.1. 用户数据结构
|
|
|
|
|
|
|
|
|
|
- FSDMMC控制数据
|
|
|
|
|
|
|
|
|
|
```c
|
|
|
|
|
typedef struct
|
|
|
|
|
{
|
|
|
|
|
FSdmmcConfig config; /* Current active configs */
|
|
|
|
|
u32 is_ready; /* Device is initialized and ready */
|
|
|
|
|
FSdmmcEventHandler evt_handler[FSDMMC_EVT_NUM];
|
2023-05-11 10:25:21 +08:00
|
|
|
|
void *evt_args[FSDMMC_EVT_NUM];
|
2022-11-10 22:22:48 +08:00
|
|
|
|
} FSdmmc; /* Device instance */
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
- FSDMMC配置数据
|
|
|
|
|
|
|
|
|
|
```c
|
|
|
|
|
typedef struct
|
|
|
|
|
{
|
|
|
|
|
u32 instance_id; /* Device instance id */
|
|
|
|
|
uintptr base_addr; /* Device base address */
|
|
|
|
|
u32 irq_num[FSDMMC_INTR_NUM];
|
|
|
|
|
} FSdmmcConfig;
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
- FSDMMC命令结构
|
|
|
|
|
```c
|
|
|
|
|
typedef struct
|
|
|
|
|
{
|
|
|
|
|
u32 cmdidx;
|
|
|
|
|
u32 cmdarg;
|
|
|
|
|
u32 resptype;
|
|
|
|
|
u32 response[4];
|
|
|
|
|
u32 flag;
|
|
|
|
|
#define FSDMMC_CMD_FLAG_NEED_STOP BIT(0)
|
|
|
|
|
#define FSDMMC_CMD_FLAG_NEED_INIT BIT(1)
|
|
|
|
|
#define FSDMMC_CMD_FLAG_EXP_RESP BIT(2)
|
|
|
|
|
#define FSDMMC_CMD_FLAG_EXP_LONG_RESP BIT(3)
|
|
|
|
|
#define FSDMMC_CMD_FLAG_NEED_RESP_CRC BIT(4)
|
|
|
|
|
#define FSDMMC_CMD_FLAG_EXP_DATA BIT(5)
|
|
|
|
|
#define FSDMMC_CMD_FLAG_WRITE_DATA BIT(6)
|
|
|
|
|
#define FSDMMC_CMD_FLAG_READ_DATA BIT(7)
|
|
|
|
|
#define FSDMMC_CMD_FLAG_NEED_AUTO_STOP BIT(8)
|
|
|
|
|
#define FSDMMC_CMD_FLAG_ADTC BIT(9)
|
|
|
|
|
FSdmmcData *data_p;
|
|
|
|
|
} FSdmmcCmd;
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
- FSDMMC数据结构
|
|
|
|
|
```c
|
|
|
|
|
typedef struct
|
|
|
|
|
{
|
|
|
|
|
u8 *buf;
|
|
|
|
|
u32 blksz;
|
|
|
|
|
u32 blkcnt;
|
|
|
|
|
u32 datalen;
|
|
|
|
|
} FSdmmcData;
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
- FSDMMC中断类型和中断事件
|
|
|
|
|
```c
|
|
|
|
|
enum
|
|
|
|
|
{
|
|
|
|
|
FSDMMC_DMA_BD_INTR = 0,
|
|
|
|
|
FSDMMC_CMD_INTR,
|
|
|
|
|
FSDMMC_ERROR_INTR,
|
|
|
|
|
|
|
|
|
|
FSDMMC_INTR_NUM
|
|
|
|
|
}; /* 中断类型 */
|
|
|
|
|
|
|
|
|
|
enum
|
|
|
|
|
{
|
|
|
|
|
FSDMMC_EVT_CARD_REMOVED = 0,
|
|
|
|
|
FSDMMC_EVT_CMD_DONE,
|
|
|
|
|
FSDMMC_EVT_CMD_ERROR,
|
|
|
|
|
FSDMMC_EVT_CMD_RESP_ERROR,
|
|
|
|
|
FSDMMC_EVT_DATA_ERROR,
|
|
|
|
|
FSDMMC_EVT_DATA_READ_DONE,
|
|
|
|
|
FSDMMC_EVT_DATA_WRITE_DONE,
|
|
|
|
|
|
|
|
|
|
FSDMMC_EVT_NUM
|
|
|
|
|
}; /* 事件类型 */
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 5.2 错误码定义
|
|
|
|
|
|
|
|
|
|
- [0x0] FSDMMC_SUCCESS : success
|
|
|
|
|
|
|
|
|
|
- [0x10c0001] FSDMMC_ERR_NOT_READY : FSDMMC控制器未初始化
|
|
|
|
|
|
|
|
|
|
- [0x10c0001] FSDMMC_ERR_TIMEOUT : 数据或者命令传输等待超时
|
|
|
|
|
|
|
|
|
|
- [0x10c0001] FSDMMC_ERR_CMD_FAILED : 命令传输失败
|
|
|
|
|
|
|
|
|
|
- [0x10c0001] FSDMMC_ERR_DATA_FAILED : 数据传输失败
|
|
|
|
|
|
|
|
|
|
- [0x10c0001] FSDMMC_ERR_CARD_NO_FOUND : 卡未检测到
|
|
|
|
|
|
|
|
|
|
- [0x10c0001] FSDMMC_ERR_INVALID_BUF : 数据缓冲区不合法
|
|
|
|
|
|
|
|
|
|
### 5.3. 用户API接口
|
|
|
|
|
|
|
|
|
|
#### FSdmmcLookupConfig
|
|
|
|
|
|
|
|
|
|
- 获取FSDMMC控制器默认配置
|
|
|
|
|
|
|
|
|
|
```c
|
|
|
|
|
const FSdmmcConfig *FSdmmcLookupConfig(u32 instance_id);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Note:
|
|
|
|
|
|
|
|
|
|
- instance_id从0开始,取决于FSDMMC控制器的个数
|
|
|
|
|
|
|
|
|
|
Input:
|
|
|
|
|
|
|
|
|
|
- {u32} instance_id 驱动控制器ID
|
|
|
|
|
|
|
|
|
|
Return:
|
|
|
|
|
|
|
|
|
|
- {const FSdmmcConfig *} FSDMMC默认配置,返回NULL如果找不到默认配置
|
|
|
|
|
|
|
|
|
|
#### FSdmmcCfgInitialize
|
|
|
|
|
|
|
|
|
|
- 初始化FSDMMC控制器, 使之可以使用
|
|
|
|
|
|
|
|
|
|
```c
|
|
|
|
|
FError FSdmmcCfgInitialize(FSdmmc *instance_p, const FSdmmcConfig *input_config_p);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Note:
|
|
|
|
|
|
|
|
|
|
- 输入配置通过FSdmmcLookupConfig获取,用户按照需要修改后传入此函数
|
|
|
|
|
|
|
|
|
|
Input:
|
|
|
|
|
|
|
|
|
|
- {FSdmmc} *instance_p FSDMMC驱动控制数据
|
|
|
|
|
- {FSdmmcConfig} *input_config_p FSDMMC用户输入配置
|
|
|
|
|
|
|
|
|
|
Return:
|
|
|
|
|
|
|
|
|
|
- {FError} 驱动初始化的错误码信息,FSDMMC_SUCCESS 表示初始化成功,其它返回值表示初始化失败
|
|
|
|
|
|
|
|
|
|
#### FSdmmcDeInitialize
|
|
|
|
|
|
|
|
|
|
- 去使能FSDMMC控制器, 清零实例数据
|
|
|
|
|
|
|
|
|
|
```c
|
|
|
|
|
void FSdmmcDeInitialize(FSdmmc *instance_p);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Note:
|
|
|
|
|
|
|
|
|
|
- 无
|
|
|
|
|
|
|
|
|
|
Input:
|
|
|
|
|
|
|
|
|
|
- {FSdmmc} *instance_p FSDMMC驱动控制数据
|
|
|
|
|
|
|
|
|
|
Return:
|
|
|
|
|
|
|
|
|
|
- 无
|
|
|
|
|
|
|
|
|
|
#### FSdmmcPollTransfer
|
|
|
|
|
|
|
|
|
|
- 通过FSDMMC轮询方式发送/接收数据和命令
|
|
|
|
|
|
|
|
|
|
```c
|
|
|
|
|
FError FSdmmcPollTransfer(FSdmmc *instance_p, FSdmmcCmd *cmd_data_p);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Note:
|
|
|
|
|
|
|
|
|
|
- FSDMMC控制器初始化后才能调用此函数
|
|
|
|
|
|
|
|
|
|
Input:
|
|
|
|
|
|
|
|
|
|
- {FSdmmc} *instance_p FSDMMC驱动控制数据
|
|
|
|
|
- {FSdmmcCmd} *cmd_data_p FSDMMC数据和命令
|
|
|
|
|
|
|
|
|
|
Return:
|
|
|
|
|
|
|
|
|
|
- {FError} 驱动初始化的错误码信息,FSDMMC_SUCCESS 表示发送/接收成功,其它返回值表示发送/接收失败
|
|
|
|
|
|
|
|
|
|
#### FSdmmcInterruptTransfer
|
|
|
|
|
|
|
|
|
|
- 通过FSDMMC中断方式发送/接收数据和命令
|
|
|
|
|
|
|
|
|
|
```c
|
|
|
|
|
FError FSdmmcInterruptTransfer(FSdmmc *instance_p, FSdmmcCmd *cmd_data_p);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Note:
|
|
|
|
|
|
|
|
|
|
- FSDMMC控制器初始化后才能调用此函数,使用前需要确保FSDMMC中断设置完成
|
|
|
|
|
|
|
|
|
|
Input:
|
|
|
|
|
|
|
|
|
|
- {FSdmmc} *instance_p FSDMMC驱动控制数据
|
|
|
|
|
- {FSdmmcCmd} *cmd_data_p FSDMMC数据和命令
|
|
|
|
|
|
|
|
|
|
Return:
|
|
|
|
|
|
|
|
|
|
- {FError} 驱动初始化的错误码信息,FSDMMC_SUCCESS 表示发送/接收成功,其它返回值表示发送/接收失败
|
|
|
|
|
|
|
|
|
|
#### FSdmmcGetInterruptMask
|
|
|
|
|
|
|
|
|
|
- 获取FSDMMC的中断掩码
|
|
|
|
|
|
|
|
|
|
```c
|
|
|
|
|
u32 FSdmmcGetInterruptMask(uintptr base_addr, u32 intr_type);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Note:
|
|
|
|
|
|
|
|
|
|
- FSDMMC控制器初始化后才能调用此函数
|
|
|
|
|
|
|
|
|
|
Input:
|
|
|
|
|
|
|
|
|
|
- {uintptr} base_addr FSDMMC控制器基地址
|
|
|
|
|
- {u32} intr_type FSDMMC中断类型, 参考FSDMMC_INTR_NUM
|
|
|
|
|
|
|
|
|
|
Return:
|
|
|
|
|
|
|
|
|
|
- {u32} 中断掩码
|
|
|
|
|
|
|
|
|
|
#### FSdmmcSetInterruptMask
|
|
|
|
|
|
|
|
|
|
- 设置FSDMMC的中断掩码
|
|
|
|
|
|
|
|
|
|
```c
|
|
|
|
|
void FSdmmcSetInterruptMask(uintptr base_addr, u32 intr_type, u32 mask, boolean enable);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Note:
|
|
|
|
|
|
|
|
|
|
- FSDMMC控制器初始化后才能调用此函数
|
|
|
|
|
|
|
|
|
|
Input:
|
|
|
|
|
|
|
|
|
|
- {uintptr} base_addr FSDMMC控制器基地址
|
|
|
|
|
- {u32} intr_type FSDMMC中断类型, 参考FSDMMC_INTR_NUM
|
|
|
|
|
- {u32} mask 中断掩码
|
|
|
|
|
- {boolean} enable TRUE:打开中断, FALSE:关闭中断
|
|
|
|
|
|
|
|
|
|
Return:
|
|
|
|
|
|
|
|
|
|
- 无
|
|
|
|
|
|
|
|
|
|
#### FSdmmcCmdInterrupHandler
|
|
|
|
|
|
|
|
|
|
- 命令中断响应函数
|
|
|
|
|
|
|
|
|
|
```c
|
|
|
|
|
void FSdmmcCmdInterrupHandler(s32 vector, void *param);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Note:
|
|
|
|
|
|
|
|
|
|
- 此函数用于设置FSDMMC中断时注册,用户可以自定义一个中断响应函数替换此函数
|
|
|
|
|
|
|
|
|
|
Input:
|
|
|
|
|
|
|
|
|
|
- vector 中断向量号
|
|
|
|
|
- {void} *param 中断响应输入参数
|
|
|
|
|
|
|
|
|
|
Return:
|
|
|
|
|
|
|
|
|
|
- 无
|
|
|
|
|
|
|
|
|
|
#### FSdmmcDmaInterrupHandler
|
|
|
|
|
|
|
|
|
|
- DMA中断响应函数
|
|
|
|
|
|
|
|
|
|
```c
|
|
|
|
|
void FSdmmcDmaInterrupHandler(s32 vector, void *param);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Note:
|
|
|
|
|
|
|
|
|
|
- 此函数用于设置FSDMMC中断时注册,用户可以自定义一个中断响应函数替换此函数
|
|
|
|
|
|
|
|
|
|
Input:
|
|
|
|
|
|
|
|
|
|
- {s32} vector 中断向量号
|
|
|
|
|
- {void} *param 中断响应输入参数
|
|
|
|
|
|
|
|
|
|
Return:
|
|
|
|
|
|
|
|
|
|
- 无
|
|
|
|
|
|
|
|
|
|
#### FSdmmcErrInterrupHandler
|
|
|
|
|
|
|
|
|
|
- 错误中断响应函数
|
|
|
|
|
|
|
|
|
|
```c
|
|
|
|
|
void FSdmmcErrInterrupHandler(s32 vector, void *param);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Note:
|
|
|
|
|
|
|
|
|
|
- 此函数用于设置FSDMMC中断时注册,用户可以自定义一个中断响应函数替换此函数
|
|
|
|
|
|
|
|
|
|
Input:
|
|
|
|
|
|
|
|
|
|
- {s32} vector 中断向量号
|
|
|
|
|
- {void} *param 中断响应输入参数
|
|
|
|
|
|
|
|
|
|
Return:
|
|
|
|
|
|
|
|
|
|
- 无
|
|
|
|
|
|
|
|
|
|
#### FSdmmcRegisterInterruptHandler
|
|
|
|
|
|
|
|
|
|
- 注册中断事件响应函数
|
|
|
|
|
|
|
|
|
|
```c
|
2023-05-11 10:25:21 +08:00
|
|
|
|
void FSdmmcRegisterInterruptHandler(FSdmmc *instance_p, u32 event, FSdmmcEventHandler handler, void *args);
|
2022-11-10 22:22:48 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Note:
|
|
|
|
|
|
|
|
|
|
- 此函数用于设置FSDMMC中断时注册,被注册的函数被FSdmmcCmdInterrupHandler、FSdmmcErrInterrupHandler
|
|
|
|
|
* 和FSdmmcDmaInterrupHandler调用
|
|
|
|
|
|
|
|
|
|
Input:
|
|
|
|
|
|
|
|
|
|
- {FSdmmc} *instance_p FSDMMC驱动控制数据
|
|
|
|
|
- {u32} event FSDMMC中断事件类型,参考FSDMMC_EVT_NUM
|
|
|
|
|
- {FSdmmcEventHandler} handler, FSDMMC中断事件响应函数
|
|
|
|
|
|
|
|
|
|
Return:
|
|
|
|
|
|
2023-05-11 10:25:21 +08:00
|
|
|
|
- 无
|