SylixOS SD协议栈之四:SD Core设备

1. SD Core设备的功能

在第二篇【SD总体结构】中,介绍了系统的各个层次,其中的Core主要包含了Core Xfer和SDM两个重要组件。Core这个词在软件设计中通常隐含着【封装】和【隔离】两个意思。【封装】指的是将其他外部组件需要的通用操作包装为简单易用的模块(或接口),让其他组件达到“拿来即用”的效果,这些模块通常隐藏了很多繁琐的细节,通常这些细节不应该由使用它的组件关心。由于SD设备可使用SDI传输,但要通过SPI总线完成一次完整的会话(发送命令、获取命令应答、数据传输),将在软件上有比较复杂的处理,比如发送命令时,首先要发送命令字,然后发送该命令对应的参数,之后读取应答数据,这过程中还需要处理命令字和应答数据的CRC计算等,这些需要使用多次SPI完成,这些工作在SD总线上,都是由SD控制器来完成的。另外,使用SPI模式下,与许多命令与应答结构都与SD模式不同,这些都需要软件来区分处理。对应应用层来说,只是想通过总线传输数据而已,不管你使用什么硬件,采取什么方式。Core Xfer的主要功能即使对SD和SPI两种传输模式的封装,或者说是对两种硬件控制器行为的统一。Xfer即为transfer,这说明,Core设备主要提供的是传输控制功能。【隔离】表示将各个组件的功能和生命周期独立。功能独立表示,组件之间不能直接感知到彼此的存在,生命周期独立表示,各个组件的产生和消亡并没有严格的先后顺序,换句话说,我可能需要你,但我不关心你什么时候来,何时走。SDM主要处理的就是隔离的问题。

本篇主要讲解Core Xfer,即SD Core设备,SDM将在下一篇讲解。

2. SD Core设备实现简介

首先来看看SD Core设备的描述,在core/sdcore.h文件里面定义了如下结构体:

/*********************************************************************************************************
  SD 核心层设备
*********************************************************************************************************/

typedef struct lw_sdcore_device {
    PVOID      COREDEV_pvDevHandle;                                     /*  设备句柄                    */
    INT        COREDEV_iAdapterType;                                    /*  所在的适配器类型            */
#define COREDEV_IS_SD(pcdev)            (pcdev->COREDEV_iAdapterType == SDADAPTER_TYPE_SD)
#define COREDEV_IS_SPI(pcdev)           (pcdev->COREDEV_iAdapterType == SDADAPTER_TYPE_SPI)

    INT        COREDEV_iDevSta;
#define COREDEV_STA_HIGHSPEED_EN        (1 << 0)
#define COREDEV_HIGHSPEED_SET(pcdev)    (pcdev->COREDEV_iDevSta |= COREDEV_STA_HIGHSPEED_EN)
#define COREDEV_IS_HIGHSPEED(pcdev)     (pcdev->COREDEV_iDevSta & COREDEV_STA_HIGHSPEED_EN)

#define COREDEV_STA_HIGHCAP_OCR         (1 << 1)                        /*  设备 OCR 包含高容量信息     */

    spinlock_t COREDEV_slLock;

    INT      (*COREDEV_pfuncCoreDevXfer)(PVOID  pvDevHandle, PLW_SD_MESSAGE psdmsg, INT iNum);
    INT      (*COREDEV_pfuncCoreDevCtl)(PVOID   pvDevHandle, INT iCmd, LONG lArg);
    INT      (*COREDEV_pfuncCoreDevDelet)(PVOID pvDevHandle);
} LW_SDCORE_DEVICE, *PLW_SDCORE_DEVICE;

COREDEV_pvDevHandle:为实际的抽象设备句柄。显然,有SD适配器设备PLW_SD_DEVICE和SPI适配器设备PLW_SPI_DEVICE两种。由于SPI适配器设备本身的定义并未考虑到SD卡的应用,因此,实际上Core在内部将原始的SPI适配器包装为适合于SD协议传输的数据结构,COREDEV_pvDevHandle在SPI模式下时,实际对应的是该结构的一个对象。

COREDEV_iAdapterType:记录对应的适配器类型。

COREDEV_iDevSta:设备状态,应用层驱动需要一些设备的状态信息执行不同的操作。

之后的三个回调函数就是对应适配器下的操作函数。它们在创建Core设备时根据适配器类型初始化。创建Core设备的函数原型如下:

/*********************************************************************************************************
** 函数名称: API_SdCoreDevCreate
** 功能描述: 创建一个核心SD设备
** 输    入: iAdapterType     设备挂接的适配器类型 (SDADAPTER_TYPE_SPI 或 SDADAPTER_TYPE_SD)
**           pcAdapterName    挂接的适配器名称
**           pcDeviceName     设备名称
**           psdcorechan      通道
** 输    出: NONE
** 返    回: 成功,返回设备设备指针,否则返回LW_NULL
** 全局变量:
** 调用模块:
*********************************************************************************************************/
LW_API PLW_SDCORE_DEVICE  API_SdCoreDevCreate (INT                       iAdapterType,
                                               CPCHAR                    pcAdapterName,
                                               CPCHAR                    pcDeviceName,
                                               PLW_SDCORE_CHAN           psdcorechan)

从该函数的参数,我们可以大致猜测它的工作过程:根据iAdapterType是SPI还是SD,调用对应的适配器设备创建函数,创建一个名称为pcDeviceName的适配器设备,它对应的适配器名称为pcAdapterName。之后为Core分配内存,设置Core设备成员变量。这里的参数psdcorechan为Core设备通道信息,其定义如下:

/*********************************************************************************************************
  SD 通道结构
*********************************************************************************************************/

struct  __sdcore_drv_funcs;
typedef struct __sdcore_drv_funcs    SDCORE_DRV_FUNCS;

typedef struct __sdcore_chan {
    SDCORE_DRV_FUNCS    *SDCORECHA_pDrvFuncs;
} LW_SDCORE_CHAN, *PLW_SDCORE_CHAN;                                     /*  SD 驱动结构体               */
#define SDCORE_CHAN_INSTALL(cha)                    ((cha)->SDCORECHA_pDrvFuncs->callbackInstall)
#define SDCORE_CHAN_CBINSTALL(cha, type, cb, arg)   SDCORE_CHAN_INSTALL(cha)(cha, type, cb, arg)

#define SDCORE_CHAN_SPICSEN(cha)                    ((cha)->SDCORECHA_pDrvFuncs->callbackSpicsEn)
#define SDCORE_CHAN_SPICSDIS(cha)                   ((cha)->SDCORECHA_pDrvFuncs->callbackSpicsDis)
/*********************************************************************************************************
  SD 回调函数
*********************************************************************************************************/

#ifdef  __cplusplus
typedef INT     (*SDCORE_CALLBACK)(...);
#else
typedef INT     (*SDCORE_CALLBACK)();
#endif

/*********************************************************************************************************
  SD 驱动安装回调函数
*********************************************************************************************************/

typedef INT     (*SDCORE_CALLBACK_INSTALL)
                (
                PLW_SDCORE_CHAN  psdcorechan,                           /*  安装回调使用的参数 驱动定义 */
                INT              iCallbackType,                         /*  安装的回调函数的类型        */
                SDCORE_CALLBACK  callback,                              /*  回调函数指针                */
                PVOID            pvCallbackArg                          /*  回调函数的参数              */
                );

/*********************************************************************************************************
  SD SPI模式下的片选回调
*********************************************************************************************************/
typedef VOID    (*SDCORE_CALLBACK_SPICS_ENABLE)(PLW_SDCORE_CHAN psdcorechan);
typedef VOID    (*SDCORE_CALLBACK_SPICS_DISABLE)(PLW_SDCORE_CHAN psdcorechan);

/*********************************************************************************************************
  SD 驱动结构
*********************************************************************************************************/

struct __sdcore_drv_funcs {
    SDCORE_CALLBACK_INSTALL       callbackInstall;
    SDCORE_CALLBACK_SPICS_ENABLE  callbackSpicsEn;
    SDCORE_CALLBACK_SPICS_DISABLE callbackSpicsDis;
};

SDCORE_DRV_FUNCS为设备需要的驱动函数集,当前包括SPI模式下从设备的片选操作,即使能片选和禁能片选,callbackInstall为控制器驱动层安装来自应用层的函数的一个回调函数,这里有点绕,直观点讲,就是控制器驱动层保存来自应用层定义的函数指针以及对应的函数参数,在控制器感知到指定的事件发生时,由控制器调用这些函数,以便快速通知应用层这些事件。LW_SDCORE_CHAN里面只有一个SDCORE_DRV_FUNCS类型的成员变量指针,那为什么不直接使用SDCORE_DRV_FUNCS呢,这是从可扩展性考虑的。通道的含义表示,它不仅仅包含函数操作,还可能包含一些数据信息。在SylixOS中,很多地方都使用了这样的处理方式。SD Core设备引出了以下两个最基本的函数:

/*********************************************************************************************************
** 函数名称: API_SdCoreDevCtl
** 功能描述: 核心设备控制
** 输    入: psdcoredevice 设备结构指针
**           iCmd          控制命令
**           lArg          命令参数
** 输    出: NONE
** 返    回: ERROR CODE
** 全局变量:
** 调用模块:
*********************************************************************************************************/
LW_API INT  API_SdCoreDevCtl (PLW_SDCORE_DEVICE    psdcoredevice,
                              INT                  iCmd,
                              LONG                 lArg)
                              
/*********************************************************************************************************
** 函数名称: API_SdCoreDevTransfer
** 功能描述: 核心设备请求
** 输    入: psdcoredevice 设备结构指针
**           psdmsg        控制消息
**           iNum          消息个数
** 输    出: NONE
** 返    回: ERROR CODE
** 全局变量:
** 调用模块:
*********************************************************************************************************/
LW_API INT  API_SdCoreDevTransfer (PLW_SDCORE_DEVICE  psdcoredevice,
                                   PLW_SD_MESSAGE     psdmsg,
                                   INT                iNum)

对照上一篇讲的SD总线适配器引出的两个函数,可以看到参数非常相似,唯一的不同就是第一个参数由之前的总线适配器类型变为了现在的SD Core设备类型。这正说明,Core设备是对SD和SPI总线传输的封装。此外,还有以下两个函数:

/*********************************************************************************************************
** 函数名称: API_SdCoreDevCmd
** 功能描述: 核心设备发送命令
** 输    入: psdcoredevice 设备结构指针
**           psdcmd        命令
**           uiRetry       重试计数
** 输    出: NONE
** 返    回: ERROR CODE
** 全局变量:
** 调用模块:
*********************************************************************************************************/
LW_API INT  API_SdCoreDevCmd (PLW_SDCORE_DEVICE psdcoredevice,
                              PLW_SD_COMMAND    psdcmd,
                              UINT32            uiRetry)
                              
/*********************************************************************************************************
** 函数名称: API_SdCoreDevAppCmd
** 功能描述: 核心设备发送APP命令
** 输    入: psdcoredevice  设备结构指针
**           psdcmdAppCmd   应用命令
**           bIsBc          是否是广播命令
**           uiRetry        重试计数
** 输    出: NONE
** 返    回: ERROR CODE
** 全局变量:
** 调用模块:
*********************************************************************************************************/
LW_API INT   API_SdCoreDevAppCmd (PLW_SDCORE_DEVICE psdcoredevice,
                                  PLW_SD_COMMAND    psdcmdAppCmd,
                                  BOOL              bIsBc,
                                  UINT32            uiRetry)

这两个为最基本的仅发送SD命令的函数,分别针对一般命令和APP命令(SD协议定义的两类不同的命令类型),之所以提供这两个函数,是因为很多时候的操作不会涉及到数据传输而仅仅发送命令。

3. SD Core设备工具库

SD Core设备工具库里面所有的函数均是使用SD Core设备作为传输操作对象,实现一些SD协议里面常用的操作,这些操用于设备初始化和数据传输。这些工具函数位于core/sdcoreLib.h和core/sdiocoreLib.h,前者为对SD存储卡(包括MMC)卡相关协议的处理,后者为对SDIO设备的一些特有处理。这里不再具体讲解这些函数,有兴趣的读者可参照SD相关协议与源码实现进行理解。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值