root {
            device_info {
                match_attr = "hdf_manager";
                platform :: host {
                    hostName = "platform_host";
                    priority = 50;
                    device_mmc:: device {
                        device0 :: deviceNode {                     // 驱动的DeviceNode节点
                            policy = 2;                             // policy字段是驱动服务发布的策略,如果需要面向用户态,则为2
                            priority = 10;                          // 驱动启动优先级
                            permission = 0644;                      // 驱动创建设备节点权限
                            moduleName = "hi3516_mmc_driver";       // 【必要】用于指定驱动名称,需要与驱动Entry中的moduleName一致。
                            serviceName = "HDF_PLATFORM_MMC_0";     // 【必要】驱动对外发布服务的名称,必须唯一。
                            deviceMatchAttr = "hi3516_mmc_emmc";    // 【必要】用于配置控制器私有数据,要与mmc_config.hcs中对应控制器保持一致。emmc类型。
                        }
                        device1 :: deviceNode {
                            policy = 1;
                            priority = 20;
                            permission = 0644;
                            moduleName = "hi3516_mmc_driver";
                            serviceName = "HDF_PLATFORM_MMC_1";
                            deviceMatchAttr = "hi3516_mmc_sd";      // SD类型
                        }
                        device2 :: deviceNode {
                            policy = 1;
                            priority = 30;
                            permission = 0644;
                            moduleName = "hi3516_mmc_driver";
                            serviceName = "HDF_PLATFORM_MMC_2";
                            deviceMatchAttr = "hi3516_mmc_sdio";    // SDIO类型
                        }
                        ......
                    }
                }
            }
        }
        c
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
class="hide-preCode-box">
        root {
            platform {
                mmc_config {
                    template mmc_controller {                     // 配置模板,如果下面节点使用时继承该模板,则节点中未声明的字段会使用该模板中的默认值。
                        match_attr = "";
                        voltDef = 0;                              // MMC默认电压,0代表3.3V,1代表1.8V,2代表1.2V
                        freqMin = 50000;                          // 【必要】最小频率值
                        freqMax = 100000000;                      // 【必要】最大频率值
                        freqDef = 400000;                         // 【必要】默认频率值
                        maxBlkNum = 2048;                         // 【必要】最大的block号
                        maxBlkSize = 512;                         // 【必要】最大block大小
                        ocrDef = 0x300000;                        // 【必要】工作电压设置相关
                        caps2 = 0;                                // 【必要】属性寄存器相关,见mmc_caps.h中MmcCaps2定义。
                        regSize = 0x118;                          // 【必要】寄存器位宽
                        hostId = 0;                               // 【必要】主机号
                        regBasePhy = 0x10020000;                  // 【必要】寄存器物理基地址
                        irqNum = 63;                              // 【必要】中断号
                        devType = 2;                              // 【必要】模式选择:EMMC、SD、SDIO、COMBO
                        caps = 0x0001e045;                        // 【必要】属性寄存器相关,见mmc_caps.h中MmcCaps定义。
                    }
                    controller_0x10100000 :: mmc_controller {
                        match_attr = "hi3516_mmc_emmc";           // 【必要】需要和device_info.hcs中的deviceMatchAttr值一致
                        hostId = 0;
                        regBasePhy = 0x10100000;
                        irqNum = 96;
                        devType = 0;                              // eMMC类型
                        caps = 0xd001e045;
                        caps2 = 0x60;
                    }
                    controller_0x100f0000 :: mmc_controller {
                        match_attr = "hi3516_mmc_sd";
                        hostId = 1;
                        regBasePhy = 0x100f0000;
                        irqNum = 62;
                        devType = 1;                              // SD类型
                        caps = 0xd001e005;
                    }
                    controller_0x10020000 :: mmc_controller {
                        match_attr = "hi3516_mmc_sdio";
                        hostId = 2;
                        regBasePhy = 0x10020000;
                        irqNum = 63;
                        devType = 2;                              // SDIO类型
                        caps = 0x0001e04d;
                    }
                }
            }
        }
        c
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}"> class="hide-preCode-box">

需要注意的是,新增mmc_config.hcs配置文件后,必须在产品对应的hdf.hcs文件中将其包含如下语句所示,否则配置文件无法生效。

        #include "../../../../device/soc/hisilicon/hi3516dv300/sdk_liteos/hdf_config/mmc/mmc_config.hcs" // 配置文件相对路径
        c
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
  1. 实例化MMC控制器对象

完成配置属性文件之后,下一步就是以核心层MmcCntlr对象的初始化为核心,包括驱动适配自定义结构体(传递参数和数据),实例化MmcCntlr成员MmcCntlrOps(让用户可以通过接口来调用驱动底层函数),实现HdfDriverEntry成员函数(Bind、Init、Release)。

从驱动的角度看,自定义结构体是参数和数据的载体,而且mmc_config.hcs文件中的数值会被HDF读入并通过DeviceResourceIface来初始化结构体成员,一些重要数值也会传递给核心层对象。

        struct HimciHost {
            struct MmcCntlr *mmc;                              // 【必要】核心层控制对象
            struct MmcCmd *cmd;                                // 【必要】核心层结构体,传递命令,相关命令见枚举量MmcCmdCode
            void *base;                                        // 地址映射需要,寄存器基地址
            enum HimciPowerStatus powerStatus;
            uint8_t *alignedBuff;
            uint32_t buffLen;
            struct scatterlist dmaSg;
            struct scatterlist *sg;
            uint32_t dmaSgNum;
            DMA_ADDR_T dmaPaddr;
            uint32_t *dmaVaddr;
            uint32_t irqNum;
            bool isTuning;
            uint32_t id;
            struct OsalMutex mutex;
            bool waitForEvent;
            HIMCI_EVENT himciEvent;
        };
        // MmcCntlr是核心层控制器结构体,其中的成员在Bind函数中会被赋值。
        struct MmcCntlr {
            struct IDeviceIoService service;
            struct HdfDeviceObject *hdfDevObj;
            struct PlatformDevice device;
            struct OsalMutex mutex;
            struct OsalSem released;
            uint32_t devType;
            struct MmcDevice *curDev;
            struct MmcCntlrOps *ops;
            struct PlatformQueue *msgQueue;
            uint16_t index;
            uint16_t voltDef;
            uint32_t vddBit;
            uint32_t freqMin;
            uint32_t freqMax;
            uint32_t freqDef;
            union MmcOcr ocrDef;
            union MmcCaps caps;
            union MmcCaps2 caps2;
            uint32_t maxBlkNum;
            uint32_t maxBlkSize;
            uint32_t maxReqSize;
            bool devPlugged;
            bool detecting;
            void *priv;
        };
        c
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}"> class="hide-preCode-box">
        static struct MmcCntlrOps g_himciHostOps = {
            .request = HimciDoRequest,
            .setClock = HimciSetClock,
            .setPowerMode = HimciSetPowerMode,
            .setBusWidth = HimciSetBusWidth,
            .setBusTiming = HimciSetBusTiming,
            .setSdioIrq = HimciSetSdioIrq,
            .hardwareReset = HimciHardwareReset,
            .systemInit = HimciSystemInit,
            .setEnhanceStrobe = HimciSetEnhanceStrobe,
            .switchVoltage = HimciSwitchVoltage,
            .devReadOnly = HimciDevReadOnly,
            .devPlugged = HimciCardPlugged,
            .devBusy = HimciDevBusy,
            .tune = HimciTune,
            .rescanSdioDev = HimciRescanSdioDev,
        };
        c
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}"> class="hide-preCode-box">

入参:

HdfDeviceObject:HDF框架给每一个驱动创建的设备对象,用来保存设备相关的私有数据和服务接口。

返回值:

HDF_STATUS相关状态(表3为部分展示,如需使用其他状态,可参考//drivers/hdf_core/interfaces/inner_api/utils/hdf_base.h中HDF_STATUS的定义)。

表 3 HDF_STATUS相关状态说明

class="table-box">
状态(值)问题描述
HDF_ERR_INVALID_OBJECT控制器对象非法
HDF_ERR_MALLOC_FAIL内存分配失败
HDF_ERR_INVALID_PARAM参数非法
HDF_ERR_IOI/O 错误
HDF_SUCCESS初始化成功
HDF_FAILURE初始化失败

函数说明: MmcCntlr、HimciHost、HdfDeviceObject之间互相赋值,方便其他函数可以相互转化,初始化自定义结构体HimciHost对象,初始化MmcCntlr成员,调用核心层MmcCntlrAdd函数,完成MMC控制器的添加。

        static int32_t HimciMmcBind(struct HdfDeviceObject *obj)
        {
            struct MmcCntlr *cntlr = NULL;
            struct HimciHost *host = NULL;
            int32_t ret;
            cntlr = (struct MmcCntlr *)OsalMemCalloc(sizeof(struct MmcCntlr));
            host = (struct HimciHost *)OsalMemCalloc(sizeof(struct HimciHost));

            host->mmc = cntlr;                              // 【必要】使HimciHost与MmcCntlr可以相互转化的前提
            cntlr->priv = (void *)host;                     // 【必要】使HimciHost与MmcCntlr可以相互转化的前提
            cntlr->ops = &g_himciHostOps;                   // 【必要】MmcCntlrOps的实例化对象的挂载
            cntlr->hdfDevObj = obj;                         // 【必要】使HdfDeviceObject与MmcCntlr可以相互转化的前提
            obj->service = &cntlr->service;                 // 【必要】使HdfDeviceObject与MmcCntlr可以相互转化的前提
            ret = MmcCntlrParse(cntlr, obj);                // 【必要】 初始化cntlr,失败就goto _ERR。
            ......
            ret = HimciHostParse(host, obj);                // 【必要】 初始化host对象的相关属性,失败就goto _ERR。
            ......
            ret = HimciHostInit(host, cntlr);               // 驱动适配者自定义的初始化,失败就goto _ERR。
            ......
            ret = MmcCntlrAdd(cntlr);                       // 调用核心层函数,失败就goto _ERR。
            ......
            (void)MmcCntlrAddDetectMsgToQueue(cntlr);       // 将卡检测消息添加到队列中。
            HDF_LOGD("HimciMmcBind: success.");
            return HDF_SUCCESS;
        ERR:
            HimciDeleteHost(host);
            HDF_LOGD("HimciMmcBind: fail, err = %d.", ret);
            return ret;
        }
        c
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}"> class="hide-preCode-box">

入参:
HdfDeviceObject:HDF框架给每一个驱动创建的设备对象,用来保存设备相关的私有数据和服务接口。

返回值:
HDF_STATUS相关状态。

函数说明:
实现ProcMciInit。

        static int32_t HimciMmcInit(struct HdfDeviceObject *obj)
        {
            static bool procInit = false;
            (void)obj;
            if (procInit == false) {
                if (ProcMciInit() == HDF_SUCCESS) {
                    procInit = true;
                    HDF_LOGD("HimciMmcInit: proc init success.");
                }
            }
            HDF_LOGD("HimciMmcInit: success.");
            return HDF_SUCCESS;
        }
        c
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">

入参:
HdfDeviceObject:HDF框架给每一个驱动创建的设备对象,用来保存设备相关的私有数据和服务接口。

返回值:
无。

函数说明:
释放内存和删除控制器等操作,该函数需要在驱动入口结构体中赋值给Release接口,当HDF框架调用Init函数初始化驱动失败时,可以调用Release释放驱动资源。

说明:
所有强制转换获取相应对象的操作前提是在Init函数中具备对应赋值的操作。

        static void HimciMmcRelease(struct HdfDeviceObject *obj)
        {
            struct MmcCntlr *cntlr = NULL;
            ......
            cntlr = (struct MmcCntlr *)obj->service;             // 这里有HdfDeviceObject到MmcCntlr的强制转化,通过service成员,赋值见Bind函数。
            ......
            HimciDeleteHost((struct HimciHost *)cntlr->priv);    // 驱动适配者自定义的内存释放函数,这里有MmcCntlr到HimciHost的强制转化。
        }
        c
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
  1. 驱动调试

【可选】针对新增驱动程序,建议验证驱动基本功能,例如挂载后的信息反馈,数据读写成功与否等。

data-report-view="{"mod":"1585297308_001","spm":"1001.2101.3001.6548","dest":"https://blog.csdn.net/maniuT/article/details/141030798","extend1":"pc","ab":"new"}">> id="blogExtensionBox" style="width:400px;margin:auto;margin-top:12px" class="blog-extension-box"> class="blog_extension blog_extension_type2" id="blog_extension"> class="extension_official" data-report-click="{"spm":"1001.2101.3001.6471"}" data-report-view="{"spm":"1001.2101.3001.6471"}"> class="blog_extension_card_left"> class="blog_extension_card_cont"> 鸿蒙开发学习资料领取!!! class="blog_extension_card_cont_r"> 微信名片
注:本文转载自blog.csdn.net的沧海一笑-dj的文章"https://blog.csdn.net/dengjin20104042056/article/details/99417893"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接

评论记录:

未查询到任何数据!