437 lines
10 KiB
Markdown
437 lines
10 KiB
Markdown
|
# FSDIO 驱动程序
|
|||
|
|
|||
|
## 1. 概述
|
|||
|
|
|||
|
SD/SDIO/eMMC控制器,主要支持SD卡,eMMC介质的访问能力,同时支持连接SDIO接口设备,目前 FSDIO 驱动已经支持 SD 卡的访问
|
|||
|
|
|||
|
## 2. 功能
|
|||
|
|
|||
|
FSDIO 驱动提供了SD/MMC卡的控制访问方法,
|
|||
|
- 初始化SD/MMC控制器
|
|||
|
- 以轮询方式发送/接收数据和命令
|
|||
|
|
|||
|
访问SD/MMC卡需要兼容一系列协议命令,这一部分驱动不提供,可以通过第三方框架sdmmc使用
|
|||
|
|
|||
|
驱动相关的源文件包括,
|
|||
|
```
|
|||
|
fsdio
|
|||
|
├── fsdio.c
|
|||
|
├── fsdio.h
|
|||
|
├── fsdio_cmd.c
|
|||
|
├── fsdio_dma.c
|
|||
|
├── fsdio_g.c
|
|||
|
├── fsdio_hw.h
|
|||
|
├── fsdio_intr.c
|
|||
|
├── fsdio_pio.c
|
|||
|
├── fsdio_selftest.
|
|||
|
```
|
|||
|
|
|||
|
## 3. 配置方法
|
|||
|
|
|||
|
以下部分将指导您完成 FSDIO 驱动的软件配置:
|
|||
|
|
|||
|
- 初始化 FSDIO 控制器
|
|||
|
- 通过协议命令完成 SD/MMC 卡初始化
|
|||
|
- 通过协议命令读写 SD/MMC 卡数据
|
|||
|
|
|||
|
## 4 应用示例
|
|||
|
|
|||
|
|
|||
|
### [通过协议命令读写SD卡](../../../baremetal/example/storage/sdio_cmds)
|
|||
|
|
|||
|
## 5. API参考
|
|||
|
|
|||
|
### 5.1. 用户数据结构
|
|||
|
|
|||
|
#### FSdio
|
|||
|
|
|||
|
- SDIO intance
|
|||
|
|
|||
|
```c
|
|||
|
typedef struct _FSdio
|
|||
|
{
|
|||
|
FSdioConfig config; /* Current active configs */
|
|||
|
u32 is_ready; /* Device is initialized and ready */
|
|||
|
FSdioIDmaDescList desc_list; /* DMA descriptor list, valid in DMA trans mode */
|
|||
|
FSdioEvtHandler evt_handlers[FSDIO_NUM_OF_EVT]; /* call-backs for interrupt event */
|
|||
|
void *evt_args[FSDIO_NUM_OF_EVT]; /* arguments for event call-backs */
|
|||
|
} FSdio; /* SDIO intance */
|
|||
|
```
|
|||
|
|
|||
|
#### FSdioConfig
|
|||
|
|
|||
|
- SDIO intance configuration
|
|||
|
|
|||
|
```c
|
|||
|
typedef struct
|
|||
|
{
|
|||
|
u32 instance_id; /* Device instance id */
|
|||
|
uintptr base_addr; /* Device base address */
|
|||
|
u32 irq_num; /* Interrupt num */
|
|||
|
FSdioTransMode trans_mode; /* Trans mode, PIO/DMA */
|
|||
|
FSdioSpeedType speed; /* Trans speed type */
|
|||
|
FSdioVoltageType voltage; /* Card voltage type */
|
|||
|
} FSdioConfig; /* SDIO intance configuration */
|
|||
|
```
|
|||
|
#### FSdioCmdData
|
|||
|
|
|||
|
- SDIO trans command and data
|
|||
|
|
|||
|
```c
|
|||
|
typedef struct
|
|||
|
{
|
|||
|
u32 cmdidx; /* command index */
|
|||
|
u32 cmdarg; /* command argument */
|
|||
|
u32 response[4]; /* command response buffer */
|
|||
|
u32 flag; /* command flags */
|
|||
|
#define FSDIO_CMD_FLAG_NEED_INIT BIT(1) /* need initialization */
|
|||
|
#define FSDIO_CMD_FLAG_EXP_RESP BIT(2) /* need reply */
|
|||
|
#define FSDIO_CMD_FLAG_EXP_LONG_RESP BIT(3) /* need 136 bits long reply */
|
|||
|
#define FSDIO_CMD_FLAG_NEED_RESP_CRC BIT(4) /* need CRC */
|
|||
|
#define FSDIO_CMD_FLAG_EXP_DATA BIT(5) /* need trans data */
|
|||
|
#define FSDIO_CMD_FLAG_WRITE_DATA BIT(6) /* need trans data to write card */
|
|||
|
#define FSDIO_CMD_FLAG_READ_DATA BIT(7) /* need trans data to read card */
|
|||
|
#define FSDIO_CMD_FLAG_NEED_AUTO_STOP BIT(8) /* need auto stop after command */
|
|||
|
#define FSDIO_CMD_FLAG_ADTC BIT(9) /* need ADTC */
|
|||
|
#define FSDIO_CMD_FLAG_SWITCH_VOLTAGE BIT(10) /* need switch voltage */
|
|||
|
FSdioData *data_p; /* SDIO trans data */
|
|||
|
} FSdioCmdData; /* SDIO trans command and data */
|
|||
|
```
|
|||
|
#### FSdioIDmaDesc
|
|||
|
|
|||
|
- SDIO DMA descriptor
|
|||
|
|
|||
|
```c
|
|||
|
typedef struct
|
|||
|
{
|
|||
|
u32 attribute; /* ds0 */
|
|||
|
#define FSDIO_IDMAC_DES0_DIC BIT(1)/* 内部描述表不触发TI/RI中断 */
|
|||
|
#define FSDIO_IDMAC_DES0_LD BIT(2)/* 数据的最后一个描述符 */
|
|||
|
#define FSDIO_IDMAC_DES0_FD BIT(3)/* 数据的第一个描述符 */
|
|||
|
#define FSDIO_IDMAC_DES0_CH BIT(4)/* 链接下一个描述符地址 */
|
|||
|
#define FSDIO_IDMAC_DES0_ER BIT(5)/* 链表已经到达最后一个链表 */
|
|||
|
#define FSDIO_IDMAC_DES0_CES BIT(30)/* RINTSTS寄存器错误汇总 */
|
|||
|
#define FSDIO_IDMAC_DES0_OWN BIT(31)/* 描述符关联DMA,完成传输后该位置置0 */
|
|||
|
u32 non1; /* ds1 --> unused */
|
|||
|
u32 len; /* ds2 bit[25:13] buffer2 size,bit[12:0] buffer1 size*/
|
|||
|
#define FSDIO_IDMAC_DES2_BUF1_MASK GENMASK(12, 0)
|
|||
|
#define FSDIO_IDMAC_DES2_BUF1_SIZE(x) (FSDIO_IDMAC_DES2_BUF1_MASK & (x))
|
|||
|
#define FSDIO_IDMAC_DES2_BUF2_MASK GENMASK(25, 13)
|
|||
|
#define FSDIO_IDMAC_DES2_BUF2_SIZE(x) (FSDIO_IDMAC_DES2_BUF2_MASK & (x << 13))
|
|||
|
u32 non2; /* ds3 --> unused */
|
|||
|
u32 addr_lo; /* ds4 Lower 32-bits of Buffer Address Pointer 1 --> buffer 1 */
|
|||
|
u32 addr_hi; /* ds5 Upper 32-bits of Buffer Address Pointer 1 */
|
|||
|
u32 desc_lo; /* ds6 Lower 32-bits of Next Descriptor Address --> buffer 2 */
|
|||
|
u32 desc_hi; /* ds7 Upper 32-bits of Next Descriptor Address */
|
|||
|
} __attribute__ ((packed)) __attribute((aligned(4))) FSdioIDmaDesc; /* SDIO DMA descriptor */
|
|||
|
|
|||
|
```
|
|||
|
|
|||
|
### 5.2 错误码定义
|
|||
|
|
|||
|
- FSDIO_SUCCESS : 操作成功
|
|||
|
- FSDIO_ERR_TIMEOUT :操作超时失败
|
|||
|
- FSDIO_ERR_NOT_INIT :控制器未初始化
|
|||
|
- FSDIO_ERR_SHORT_BUF :缓冲区大小不足
|
|||
|
- FSDIO_ERR_NOT_SUPPORT :操作不支持
|
|||
|
- FSDIO_ERR_INVALID_STATE :控制器的状态不合法
|
|||
|
- FSDIO_ERR_TRANS_TIMEOUT :传输数据超时失败
|
|||
|
- FSDIO_ERR_CMD_TIMEOUT :传输命令超时失败
|
|||
|
- FSDIO_ERR_NO_CARD :卡不在位
|
|||
|
- FSDIO_ERR_BUSY : 卡处于繁忙状态
|
|||
|
|
|||
|
### 5.3. 用户API接口
|
|||
|
|
|||
|
#### FSdioLookupConfig
|
|||
|
|
|||
|
```c
|
|||
|
const FSdioConfig *FSdioLookupConfig(u32 instance_id)
|
|||
|
```
|
|||
|
|
|||
|
Note:
|
|||
|
|
|||
|
- Get the device instance default configure
|
|||
|
|
|||
|
Input:
|
|||
|
|
|||
|
- {u32} instance_id
|
|||
|
|
|||
|
Return:
|
|||
|
|
|||
|
- {const FSdioConfig *} default configure
|
|||
|
|
|||
|
#### FSdioCfgInitialize
|
|||
|
|
|||
|
```c
|
|||
|
FError FSdioCfgInitialize(FSdio *const instance_p, const FSdioConfig *input_config_p)
|
|||
|
```
|
|||
|
|
|||
|
Note:
|
|||
|
|
|||
|
- initialization SDIO controller instance
|
|||
|
- get into card-detect mode after initialization, bus width = 1, card freq = 400kHz
|
|||
|
|
|||
|
Input:
|
|||
|
|
|||
|
- {FSdio} *instance_p, SDIO controller instance
|
|||
|
- {FSdioConfig} *input_config_p, SDIO controller configure
|
|||
|
|
|||
|
Return:
|
|||
|
|
|||
|
- {FError} FSDIO_SUCCESS if initialization success, otherwise failed
|
|||
|
|
|||
|
#### FSdioDeInitialize
|
|||
|
|
|||
|
```c
|
|||
|
void FSdioDeInitialize(FSdio *const instance_p)
|
|||
|
```
|
|||
|
|
|||
|
Note:
|
|||
|
|
|||
|
- deinitialization SDIO controller instance
|
|||
|
|
|||
|
Input:
|
|||
|
|
|||
|
- {FSdio} *instance_p, SDIO controller instance
|
|||
|
|
|||
|
Return:
|
|||
|
|
|||
|
- {NONE}
|
|||
|
|
|||
|
#### FSdioSetIDMAList
|
|||
|
|
|||
|
```c
|
|||
|
FError FSdioSetIDMAList(FSdio *const instance_p, volatile FSdioIDmaDesc *desc, u32 desc_num)
|
|||
|
```
|
|||
|
|
|||
|
Note:
|
|||
|
|
|||
|
- Setup DMA descriptor for SDIO controller instance
|
|||
|
|
|||
|
Input:
|
|||
|
|
|||
|
- {FSdio} *instance_p, SDIO controller instance
|
|||
|
- {volatile FSdioIDmaDesc} *desc, first item in DMA descriptor lists
|
|||
|
- {u32} desc_num, number of items in DMA descriptor lists
|
|||
|
|
|||
|
Return:
|
|||
|
|
|||
|
- {FError} FSDIO_SUCCESS if setup done, otherwise failed
|
|||
|
|
|||
|
#### FSdioSetClkFreq
|
|||
|
|
|||
|
```c
|
|||
|
void FSdioSetClkFreq(FSdio *const instance_p, u32 input_clk_hz)
|
|||
|
```
|
|||
|
|
|||
|
Note:
|
|||
|
|
|||
|
- Set the Card clock freqency
|
|||
|
|
|||
|
Input:
|
|||
|
|
|||
|
- {FSdio} *instance_p, SDIO controller instance
|
|||
|
- {u32} input_clk_hz, Card clock freqency in Hz
|
|||
|
|
|||
|
Return:
|
|||
|
|
|||
|
- {None}
|
|||
|
|
|||
|
#### FSdioDMATransfer
|
|||
|
|
|||
|
```c
|
|||
|
FError FSdioDMATransfer(FSdio *const instance_p, FSdioCmdData *const cmd_data_p)
|
|||
|
```
|
|||
|
|
|||
|
Note:
|
|||
|
|
|||
|
- Start command and data transfer in DMA mode
|
|||
|
|
|||
|
Input:
|
|||
|
|
|||
|
- {FSdio} *instance_p, SDIO controller instance
|
|||
|
- {FSdioCmdData} *cmd_data_p, contents of transfer command and data
|
|||
|
|
|||
|
Return:
|
|||
|
|
|||
|
- {FError} FSDIO_SUCCESS if transfer success, otherwise failed
|
|||
|
|
|||
|
#### FSdioPollWaitDMAEnd
|
|||
|
|
|||
|
```c
|
|||
|
FError FSdioPollWaitDMAEnd(FSdio *const instance_p, FSdioCmdData *const cmd_data_p, FSdioRelaxHandler relax)
|
|||
|
```
|
|||
|
|
|||
|
Note:
|
|||
|
|
|||
|
- Wait DMA transfer finished by poll
|
|||
|
|
|||
|
Input:
|
|||
|
|
|||
|
- {FSdio} *instance_p, SDIO controller instance
|
|||
|
- {FSdioCmdData} *cmd_data_p, contents of transfer command and data
|
|||
|
- {FSdioRelaxHandler} relax, handler of relax when wait busy
|
|||
|
|
|||
|
Return:
|
|||
|
|
|||
|
- {FError} FSDIO_SUCCESS if wait success, otherwise wait failed
|
|||
|
|
|||
|
#### FSdioGetInterruptMask
|
|||
|
|
|||
|
|
|||
|
```c
|
|||
|
u32 FSdioGetInterruptMask(FSdio *const instance_p, FSdioIntrType type)
|
|||
|
```
|
|||
|
|
|||
|
Note:
|
|||
|
|
|||
|
- Get SDIO controller interrupt mask
|
|||
|
|
|||
|
Input:
|
|||
|
|
|||
|
- {FSdio} *instance_p, SDIO controller instance
|
|||
|
- {FSdioIntrType} type, Type of interrupt, controller/DMA interrupt
|
|||
|
|
|||
|
Return:
|
|||
|
|
|||
|
- {u32} interrupt mask bits
|
|||
|
|
|||
|
#### FSdioSetInterruptMask
|
|||
|
|
|||
|
|
|||
|
```c
|
|||
|
void FSdioSetInterruptMask(FSdio *const instance_p, FSdioIntrType type, u32 set_mask, boolean enable)
|
|||
|
```
|
|||
|
|
|||
|
Note:
|
|||
|
|
|||
|
- Enable/Disable SDIO controller interrupt
|
|||
|
|
|||
|
Input:
|
|||
|
|
|||
|
- {FSdio} *instance_p, SDIO controller instance
|
|||
|
- {FSdioIntrType} type, Type of interrupt, controller/DMA interrupt
|
|||
|
- {u32} set_mask, interrupt mask bits
|
|||
|
- {boolean} enable, TRUE: enable interrupt mask bits
|
|||
|
|
|||
|
Return:
|
|||
|
|
|||
|
- {NONE}
|
|||
|
|
|||
|
#### FSdioInterruptHandler
|
|||
|
|
|||
|
```c
|
|||
|
void FSdioInterruptHandler(s32 vector, void *param)
|
|||
|
```
|
|||
|
|
|||
|
Note:
|
|||
|
|
|||
|
- Interrupt handler for SDIO instance
|
|||
|
|
|||
|
Input:
|
|||
|
|
|||
|
- {s32} vector, Interrupt id
|
|||
|
- {void} *param, Interrupt params, is SDIO instance
|
|||
|
|
|||
|
Return:
|
|||
|
|
|||
|
- {NONE}
|
|||
|
|
|||
|
#### FSdioRegisterEvtHandler
|
|||
|
|
|||
|
```c
|
|||
|
void FSdioRegisterEvtHandler(FSdio *const instance_p, FSdioEvtType evt, FSdioEvtHandler handler, void *handler_arg)
|
|||
|
```
|
|||
|
|
|||
|
Note:
|
|||
|
|
|||
|
- Register event call-back function as handler for interrupt events
|
|||
|
|
|||
|
Input:
|
|||
|
|
|||
|
- {FSdio} *instance_p, SDIO controller instance
|
|||
|
- {FSdioEvtType} evt, interrupt event
|
|||
|
- {FSdioEvtHandler} handler, event call-back function
|
|||
|
- {void} *handler_arg, argument of event call-back function
|
|||
|
|
|||
|
Return:
|
|||
|
|
|||
|
- {NONE}
|
|||
|
|
|||
|
|
|||
|
#### FSdioPIOTransfer
|
|||
|
|
|||
|
```c
|
|||
|
FError FSdioPIOTransfer(FSdio *const instance_p, FSdioCmdData *const cmd_data_p)
|
|||
|
```
|
|||
|
|
|||
|
Note:
|
|||
|
|
|||
|
- Start command and data transfer in PIO mode
|
|||
|
|
|||
|
Input:
|
|||
|
|
|||
|
- {FSdio} *instance_p, SDIO controller instance
|
|||
|
- {FSdioCmdData} *cmd_data_p, contents of transfer command and data
|
|||
|
|
|||
|
Return:
|
|||
|
|
|||
|
- {FError} FSDIO_SUCCESS if transfer success, otherwise failed
|
|||
|
|
|||
|
#### FSdioPollWaitPIOEnd
|
|||
|
|
|||
|
```c
|
|||
|
FError FSdioPollWaitPIOEnd(FSdio *const instance_p, FSdioCmdData *const cmd_data_p, FSdioRelaxHandler relax);
|
|||
|
```
|
|||
|
|
|||
|
Note:
|
|||
|
|
|||
|
- Wait PIO transfer finished by poll
|
|||
|
|
|||
|
Input:
|
|||
|
|
|||
|
- {FSdio} *instance_p, SDIO controller instance
|
|||
|
- {FSdioCmdData} *cmd_data_p, contents of transfer command and data
|
|||
|
- {FSdioRelaxHandler} relax, handler of relax when wait busy
|
|||
|
|
|||
|
Return:
|
|||
|
|
|||
|
- {FError} FSDIO_SUCCESS if wait success, otherwise wait failed
|
|||
|
|
|||
|
#### FSdioGetCmdResponse
|
|||
|
|
|||
|
```c
|
|||
|
FError FSdioGetCmdResponse(FSdio *const instance_p, FSdioCmdData *const cmd_data_p)
|
|||
|
```
|
|||
|
|
|||
|
Note:
|
|||
|
|
|||
|
- Get cmd response and received data after wait poll status or interrupt signal
|
|||
|
|
|||
|
Input:
|
|||
|
|
|||
|
- {FSdio} *instance_p, SDIO controller instance
|
|||
|
- {FSdioCmdData} *cmd_data_p, contents of transfer command and data
|
|||
|
|
|||
|
Return:
|
|||
|
|
|||
|
- {FError} FSDIO_SUCCESS if get success
|
|||
|
|
|||
|
#### FSdioRestart
|
|||
|
|
|||
|
```c
|
|||
|
FError FSdioRestart(FSdio *const instance_p)
|
|||
|
```
|
|||
|
|
|||
|
Note:
|
|||
|
|
|||
|
- reset controller from error state
|
|||
|
|
|||
|
Input:
|
|||
|
|
|||
|
- {FSdio} *instance_p, instance of controller
|
|||
|
|
|||
|
Return:
|
|||
|
|
|||
|
- {FError} FSDIO_SUCCESS if restart success
|