5.1.5. 设计说明¶
5.1.5.1. 源码说明¶
源代码位于 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的文件系统实现 
5.1.5.2. 模块架构¶
SDMC 驱动 Driver 层采用 RT-Thread 的SDIO设备驱动框架,如果只使用HAL层也可以支持 baremetal 方式的应用场景。
 
图 5.29 SDMC 模块驱动的软件框架¶
其中:
- DFS层:baremetal文件系统层,提供接口给Baremetal APP读写Baremetal SDMC文件。 
- Baremetal MMC层:向上对接DFS,提供读写接口;向下对接Baremetal SDMC driver层。 
- Baremetal SDMC Driver层:提供SDMC驱动初始化接口,方便Baremetal MMC层的访问。 
- SDMC Driver层:负责对接 SDIO设备框架,注册成块设备,方便应用层的访问。 
- SDMC HAL层:封装了寄存器级别的操作,对Driver层屏蔽硬件级别的访问。 
5.1.5.3. 关键流程设计¶
5.1.5.3.1. RT-Thread初始化流程¶
SDMC 控制器驱动的初始化接口通过 INIT_DEVICE_EXPORT(drv_sdmc_init) 完成注册。
其中,主要步骤如下:
- 分配 host 管理结构(包括 rt_mmcsd_host 和 aic_sdmc) 
- 初始化模块的clk 
- 注册中断 
- 初始化控制器 
- 通知 mmcsd 监测线程(mmcsd_change) 
5.1.5.3.2. Baremetal初始化流程¶
SDMC 控制器驱动通过 mmc_init() 完成初始化。
其中,主要步骤如下:
- 分配host管理结构和dev设备信息结构(aic_sdmc 和 aic_sdmc_dev) 
- 初始化模块的clk 
- 注册中断 
- 初始化控制器 
注解
为了简化设计,SDMC驱动中目前未使用中断方式,使用轮询方式完成和Device的交互。
5.1.5.4. 数据结构设计¶
5.1.5.4.1. struct aic_sdmc_host¶
属于 HAL 层接口,定义了 SDMC控制器 管理信息:
struct aic_sdmc_host {
    volatile void *base;
    u32 is_sdio;
    u32 fifoth_val;
};
5.1.5.4.2. struct aic_sdmc_idma_desc¶
属于 HAL 层接口,记录了 SDMC控制器内部DMA访问的描述符:
struct aic_sdmc_idma_desc {
    u32 flags;
    u32 cnt;
    u32 addr;
    u32 next_addr;
} __aligned(8);
5.1.5.4.3. struct aic_sdmc¶
5.1.5.4.3.1. RT-Thread¶
属于 Driver 层的内部接口,用于记录 SDMC 控制器的管理信息:
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;
    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;
};
5.1.5.4.3.2. Baremetal¶
属于 Baremetal Driver 层的内部接口,用于记录 SDMC 控制器的管理信息:
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;
};
5.1.5.5. 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);
};
5.1.5.5.1. aic_sdmc_request¶
5.1.5.5.1.1. RT-Thread¶
| 函数原型 | void aic_sdmc_request(struct rt_mmcsd_host *rthost, struct rt_mmcsd_req *req) | 
|---|---|
| 功能说明 | 请求SDMC控制器向Device发送一个报文 | 
| 参数定义 | rthost: 指向SDIO层的mmcsd控制器 req:请求的参数和资源 | 
| 返回值 | 无 | 
| 注意事项 | 
5.1.5.5.1.2. Baremetal¶
| 函数原型 | void aic_sdmc_request(struct aic_sdmc *host, struct aic_sdmc_cmd *cmd, struct aic_sdmc_data *data) | 
|---|---|
| 功能说明 | 请求SDMC控制器向Device发送一个报文 | 
| 参数定义 | host: 指向上层调用的mmcsd控制器 cmd: 请求发送的命令 data: 请求发送的数据 | 
| 返回值 | 无 | 
| 注意事项 | 
5.1.5.5.2. aic_sdmc_set_iocfg¶
5.1.5.5.2.1. RT-Thread¶
| 函数原型 | 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:配置参数 | 
| 返回值 | 无 | 
| 注意事项 | 
5.1.5.5.2.2. Baremetal¶
| 函数原型 | void aic_sdmc_set_cfg(struct aic_sdmc *host) | 
|---|---|
| 功能说明 | 配置位宽、DDR模式、clock、power模式等信息 | 
| 参数定义 | host: 指向上层调用的mmcsd控制器 | 
| 返回值 | 无 | 
| 注意事项 | 
5.1.5.6. HAL 层接口设计¶
HAL 层的函数接口声明存放在 hal_sdmc.h 中,主要接口有:
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_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_enable(struct aic_sdmc_host *host);
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);