设计说明
源码说明
源代码位于 bsp/artinchip/
:
-
bsp/artinchip/drv/sdmc/drv_sdmc.c,SDMC Driver 层实现
-
bsp/artinchip/hal/sdmc/hal_sdmc.c,SDMC HAL 层实现
-
bsp/artinchip/include/hal/hal_sdmc.h,SDMC HAL 层接口头文件
此外,提供了一个 Baremetal 设计实例供参考,源代码位于:
-
bsp/artinchip/drv_bare/sdmc/sdmc.c,Baremetal 的 SDMC Driver 层实现
-
bsp/artinchip/drv_bare/sdmc/mmc.c,Baremetal 的 SDMC Driver 层使用实例
-
bsp/artinchip/drv_bare/sdmc/sdmc.h,Baremetal 的 SDMC Driver 层头文件
-
bsp/artinchip/include/drv_bare/mmc.h,Baremetal 的 SDMC Driver 层使用实例头文件
-
packages/third-party/dfs,Baremetal 的文件系统实现
模块架构
SDMC 驱动 Driver 层采用 RT-Thread 的 SDIO 设备驱动框架,如果只使用 HAL 层也可以支持 Baremetal 方式的应用场景。
其中:
-
DFS 层:Baremetal 文件系统层,提供接口给 Baremetal APP 读写 Baremetal SDMC 文件。
-
Baremetal MMC 层:向上对接 DFS,提供读写接口;向下对接 Baremetal SDMC driver 层。
-
Baremetal SDMC Driver 层:提供 SDMC 驱动初始化接口,方便 Baremetal MMC 层的访问。
-
SDMC Driver 层:负责对接 SDIO 设备框架,注册成块设备,方便应用层的访问。
-
SDMC HAL 层:封装了寄存器级别的操作,对 Driver 层屏蔽硬件级别的访问。
关键流程设计
SDMC 控制器驱动的初始化接口通过 INIT_DEVICE_EXPORT(drv_sdmc_init)
完成注册。
其中,主要步骤如下:
-
分配 host 管理结构(包括 rt_mmcsd_host 和 aic_sdmc)
-
初始化模块的 clk
-
注册中断
-
初始化控制器
-
通知 mmcsd 监测线程(mmcsd_change)
SDMC 控制器驱动通过 mmc_init()
完成初始化。 其中,主要步骤如下:
-
分配 host 管理结构和 dev 设备信息结构(aic_sdmc 和 aic_sdmc_dev)
-
初始化模块的 clk
-
注册中断
-
初始化控制器
为了简化设计,SDMC 驱动中目前未使用中断方式,使用轮询方式完成和 Device 的交互。
数据结构设计
struct aic_sdmc_host {
volatile void *base;
u32 is_sdio;
u32 fifoth_val;
#ifdef AIC_SDMC_IRQ_MODE
aicos_sem_t complete;
#endif
};
struct aic_sdmc_idma_desc {
u32 flags;
u32 cnt;
u32 addr;
u32 next_addr;
} __aligned(8);
struct aic_sdmc {
struct rt_mmcsd_host *rthost;
struct rt_mmcsd_req *req;
struct rt_mmcsd_cmd *cmd;
struct aic_sdmc_host host;
rt_uint32_t *buf;
u32 clk;
u32 irq;
u32 index;
u32 cid[4];
unsigned int quirks;
unsigned int caps;
unsigned int version;
unsigned int clock;
unsigned int sclk_rate;
unsigned int div;
int buswidth;
int ddr_mode;
/* use fifo mode to read and write data */
int fifo_mode;
struct aic_sdmc_pdata *pdata;
u8 is_enable;
};
struct aic_sdmc {
struct aic_sdmc_dev *dev;
struct aic_sdmc_cmd *cmd;
struct aic_sdmc_data *data;
struct aic_sdmc_host host;
u32 *buf;
u32 clk;
u32 irq;
u32 index;
unsigned int quirks;
unsigned int caps;
unsigned int version;
unsigned int clock;
unsigned int sclk_rate;
unsigned int div;
int buswidth;
int ddr_mode;
/* use fifo mode to read and write data */
int fifo_mode;
struct aic_sdmc_pdata *pdata;
};
Driver 层接口设计
-
Baremetal Driver 参考 Driver 层设计,去除了 RT-Thread 所需的结构信息。
-
以下接口皆为 SDIO 设备驱动框架所需要的标准接口,目前 SDMC 驱动仅实现了其中的 request 和 set_iocfg 接口。
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); };
函数原型 | void aic_sdmc_request(struct rt_mmcsd_host *rthost, struct rt_mmcsd_req *req) |
---|---|
功能说明 | 请求 SDMC 控制器向 Device 发送一个报文 |
参数定义 |
rthost : 指向 SDIO 层的 mmcsd 控制器req :请求的参数和资源 |
返回值 | 无 |
注意事项 | - |
函数原型 | void aic_sdmc_request(struct aic_sdmc *host, struct aic_sdmc_cmd *cmd, struct aic_sdmc_data *data) |
---|---|
功能说明 | 请求 SDMC 控制器向 Device 发送一个报文 |
参数定义 |
host: 指向上层调用的 mmcsd 控制器
cmd : 请求发送的命令data : 请求发送的数据 |
返回值 | 无 |
注意事项 | - |
函数原型 | void aic_sdmc_set_iocfg(struct rt_mmcsd_host *rthost, struct rt_mmcsd_io_cfg *io_cfg) |
---|---|
功能说明 | 配置位宽、DDR 模式、clock、power 模式等信息 |
参数定义 |
rthost : 指向 SDIO 层的 mmcsd 控制器io_cfg :配置参数 |
返回值 | 无 |
注意事项 | - |
函数原型 | void aic_sdmc_set_cfg(struct aic_sdmc *host) |
---|---|
功能说明 | 配置位宽、DDR 模式、clock、power 模式等信息 |
参数定义 |
host : 指向上层调用的 mmcsd 控制器 |
返回值 | 无 |
注意事项 | - |
HAL 层接口设计
void hal_sdmc_idma_update_intstat(struct aic_sdmc_host *host);
int hal_sdmc_idma_start(struct aic_sdmc_host *host, u32 size, u32 read,
u32 *buf, struct bounce_buffer *bbstate);
int hal_sdmc_idma_stop(struct aic_sdmc_host *host,
struct bounce_buffer *bbstate, u32 read);
void hal_sdmc_idma_disable(struct aic_sdmc_host *host);
u8 hal_sdmc_get_idma_status(struct aic_sdmc_host *host);
void hal_sdmc_idma_prepare(struct aic_sdmc_host *host,
u32 blksize, u32 blks,
struct aic_sdmc_idma_desc *cur_idma,
void *bounce_buffer);
int hal_sdmc_data_rx(struct aic_sdmc_host *host, u32 *buf, u32 size);
int hal_sdmc_data_tx(struct aic_sdmc_host *host, u32 *buf, u32 size);
u32 hal_sdmc_int_stat(struct aic_sdmc_host *host);
void hal_sdmc_int_clr(struct aic_sdmc_host *host, u32 mask);
int hal_sdmc_is_busy(struct aic_sdmc_host *host);
void hal_sdmc_set_blk(struct aic_sdmc_host *host, u32 blksize, u32 blks);
void hal_sdmc_set_arg(struct aic_sdmc_host *host, u32 arg);
void hal_sdmc_set_cmd(struct aic_sdmc_host *host, u32 cmd);
u32 hal_sdmc_wait_cmd_started(struct aic_sdmc_host *host);
void hal_sdmc_get_rsp(struct aic_sdmc_host *host, u32 *buf, u32 all);
void aic_sdmc_set_ext_clk_mux(struct aic_sdmc_host *host, u32 mux);
void hal_sdmc_set_phase(struct aic_sdmc_host *host, u32 drv, u32 smp);
void hal_sdmc_set_buswidth(struct aic_sdmc_host *host, u32 buswidth);
void hal_sdmc_set_ddrmode(struct aic_sdmc_host *host, u32 ddr);
void hal_sdmc_clk_disable(struct aic_sdmc_host *host);
void hal_sdmc_clk_enable(struct aic_sdmc_host *host);
void hal_sdmc_sdio_irq_enable(struct aic_sdmc_host *host, u32 en);
void hal_sdmc_set_div(struct aic_sdmc_host *host, u32 div);
void hal_sdmc_fifo_init(struct aic_sdmc_host *host, u32 *thd);
int hal_sdmc_reset(struct aic_sdmc_host *host, u32 value);
void hal_sdmc_init(struct aic_sdmc_host *host);