浏览器老是出现站长工具,做pc和移动网站的适配,凤凰天机精品资料网,广州文化网站模板功能简介
SDIO是安全数字输入输出接口#xff08;Secure Digital Input and Output#xff09;的缩写#xff0c;是从SD内存卡接口的基础上演化出来的一种外设接口。SDIO接口兼容以前的SD卡#xff0c;并且可以连接支持SDIO接口的其他设备。
SDIO接口定义了操作SDIO的通用…功能简介
SDIO是安全数字输入输出接口Secure Digital Input and Output的缩写是从SD内存卡接口的基础上演化出来的一种外设接口。SDIO接口兼容以前的SD卡并且可以连接支持SDIO接口的其他设备。
SDIO接口定义了操作SDIO的通用方法集合包括 打开/关闭SDIO控制器 独占/释放HOST 使能/去使能设备 申请/释放中断 读写、获取/设置公共信息
运作机制
在HDF框架中SDIO的接口适配模式采用独立服务模式。在这种模式下每一个设备对象会独立发布一个设备服务来处理外部访问设备管理器收到API的访问请求之后通过提取该请求的参数达到调用实际设备对象的相应内部方法的目的。独立服务模式可以直接借助HDFDeviceManager的服务管理能力但需要为每个设备单独配置设备节点若设备过多可能增加内存占用。
独立服务模式下核心层不会统一发布一个服务供上层使用因此这种模式下驱动要为每个控制器发布一个服务具体表现为 驱动适配者需要实现HdfDriverEntry的Bind钩子函数以绑定服务。 device_info.hcs文件中deviceNode的policy字段为1或2不能为0。
SDIO模块各分层作用 接口层提供打开SDIO设备、设置块的大小、读取数据、写数据、设置公共信息、获取公共信息、刷新数据、独占HOST、释放Host、使能SDIO功能设备、去使能SDIO功能设备、申请中断、释放中断关闭SDIO设备的接口。 核心层主要提供SDIO控制器的添加、移除及管理的能力通过钩子函数与适配层交互。 适配层主要是将钩子函数的功能实例化实现具体的功能。
图 1 SDIO独立服务模式结构图 SDIO总线有两端其中一端是主机端HOST另一端是设备端DEVICE。所有的通信都是由HOST端发出命令开始的在DEVICE端只要能解析HOST的命令就可以同HOST进行通信了。SDIO的HOST可以连接多个DEVICE如图2所示 CLK信号HOST给DEVICE的时钟信号。 VDD信号电源信号。 VSS信号Ground信号。 D0-3信号4条数据线其中DAT1信号线复用为中断线在1BIT模式下DAT0用来传输数据在4BIT模式下DAT0-DAT3用来传输数据。 CMD信号用于HOST发送命令和DEVICE回复响应。
图 2 SDIO的HOST-DEVICE连接示意图 约束与限制
SDIO模块API当前仅支持内核态调用。
使用指导
场景介绍
SDIO的应用比较广泛目前有许多手机都支持SDIO功能并且很多SDIO外设也被开发出来使得手机外接外设更加容易。常见的SDIO外设有WLAN、GPS、CAMERA、蓝牙等。
接口说明
SDIO模块提供的主要接口如表1所示具体API详见//drivers/hdf_core/framework/include/platform/sdio_if.h。
表 1 SDIO驱动API接口功能介绍
接口名接口描述DevHandle SdioOpen(int16_t mmcBusNum, struct SdioFunctionConfig *config)打开指定总线号的SDIO控制器void SdioClose(DevHandle handle)关闭SDIO控制器int32_t SdioReadBytes(DevHandle handle, uint8_t *data, uint32_t addr, uint32_t size)从指定地址开始增量读取指定长度的数据int32_t SdioWriteBytes(DevHandle handle, uint8_t *data, uint32_t addr, uint32_t size)从指定地址开始增量写入指定长度的数据int32_t SdioReadBytesFromFixedAddr(DevHandle handle, uint8_t *data, uint32_t addr, uint32_t size, uint32_t scatterLen)从固定地址读取指定长度的数据int32_t SdioWriteBytesToFixedAddr(DevHandle handle, uint8_t *data, uint32_t addr, uint32_t size, uint32_t scatterLen)向固定地址写入指定长度的数据int32_t SdioReadBytesFromFunc0(DevHandle handle, uint8_t *data, uint32_t addr, uint32_t size)从SDIO function 0的指定地址空间读取指定长度的数据int32_t SdioWriteBytesToFunc0(DevHandle handle, uint8_t *data, uint32_t addr, uint32_t size)向SDIO function 0的指定地址空间写入指定长度的数据int32_t SdioSetBlockSize(DevHandle handle, uint32_t blockSize)设置块的大小int32_t SdioGetCommonInfo(DevHandle handle, SdioCommonInfo *info, SdioCommonInfoType infoType)获取公共信息int32_t SdioSetCommonInfo(DevHandle handle, SdioCommonInfo *info, SdioCommonInfoType infoType)设置公共信息int32_t SdioFlushData(DevHandle handle)刷新数据void SdioClaimHost(DevHandle handle)独占Hostvoid SdioReleaseHost(DevHandle handle)释放Hostint32_t SdioEnableFunc(DevHandle handle)使能SDIO功能设备int32_t SdioDisableFunc(DevHandle handle)去使能SDIO功能设备int32_t SdioClaimIrq(DevHandle handle, SdioIrqHandler *irqHandler)申请中断int32_t SdioReleaseIrq(DevHandle handle)释放中断
使用流程
使用SDIO的一般流程如图3所示。
图 3 SDIO使用流程图 打开SDIO控制器
在使用SDIO进行通信前首先要调用SdioOpen获取SDIO控制器的设备句柄该函数会返回指定总线号的SDIO控制器的设备句柄。
DevHandle SdioOpen(int16_t mmcBusNum, struct SdioFunctionConfig *config);
表 2 SdioOpen函数的参数和返回值描述
参数参数描述mmcBusNumint16_t类型总线号config结构体指针SDIO功能配置信息返回值返回值描述NULL获取SDIO控制器的设备句柄失败设备句柄SDIO控制器的设备句柄
打开SDIO控制器的示例如下
DevHandle handle NULL;
struct SdioFunctionConfig config;
config.funcNr 1;
config.vendorId 0x123;
config.deviceId 0x456;
// 打开总线号为1的SDIO控制器
handle SdioOpen(1, config);
if (handle NULL) {HDF_LOGE(SdioOpen: open sdio fail!\n);return NULL;
}
独占HOST
获取到SDIO控制器的设备句柄之后需要先独占HOST才能进行SDIO后续的一系列操作独占HOST函数如下所示
void SdioClaimHost(DevHandle handle);
表 3 SdioClaimHost函数的参数描述
参数参数描述handleDevHandle类型SDIO控制器的设备句柄
独占HOST示例如下
SdioClaimHost(handle); // 独占HOST
使能SDIO设备
在访问寄存器之前需要先使能SDIO设备使能SDIO设备的函数如下所示
int32_t SdioEnableFunc(DevHandle handle);
表 4 SdioEnableFunc函数的参数和返回值描述
参数参数描述handleDevHandle类型SDIO控制器的设备句柄返回值返回值描述HDF_SUCCESSSDIO使能成功负数SDIO使能失败
使能SDIO设备的示例如下
int32_t ret;
// 使能SDIO设备
ret SdioEnableFunc(handle);
if (ret ! HDF_SUCCESS) {HDF_LOGE(SdioEnableFunc: sdio enable func fail, ret:%d\n, ret);return ret;
}
注册SDIO中断
在通信之前还需要注册SDIO中断注册SDIO中断函数如下所示
int32_t SdioClaimIrq(DevHandle handle, SdioIrqHandler *handler);
表 5 SdioClaimIrq函数的参数和返回值描述
参数参数描述handleDevHandle类型SDIO控制器的设备句柄handler函数指针中断服务函数返回值返回值描述HDF_SUCCESS注册SDIO中断成功负数注册SDIO中断失败
注册SDIO中的示例如下
// 中断服务函数需要根据各自平台的情况去实现
static void SdioIrqFunc(void *data)
{if (data NULL) {HDF_LOGE(SdioIrqFunc: data is NULL.\n);return;}// 需要开发者自行添加具体实现
}int32_t ret;
// 注册SDIO中断
ret SdioClaimIrq(handle, SdioIrqFunc);
if (ret ! HDF_SUCCESS) {HDF_LOGE(SdioClaimIrq: sdio claim irq fail, ret:%d\n, ret);return ret;
}
进行SDIO通信 向SDIO设备增量写入指定长度的数据 对应的接口函数如下所示 int32_t SdioWriteBytes(DevHandle handle, uint8_t *data, uint32_t addr, uint32_t size); 表 6 SdioWriteBytes函数的参数和返回值描述 参数参数描述handleDevHandle类型SDIO控制器的设备句柄datauint8_t类型指针待写入数据addruint32_t类型待写入数据的起始地址sizeuint32_t类型待写入数据的长度返回值返回值描述HDF_SUCCESSSDIO写数据成功负数SDIO写数据失败向SDIO设备增量写入指定长度的数据的示例如下 int32_t ret;
uint8_t wbuff[] {1,2,3,4,5};
uint32_t addr 0x100 0x09;
// 向SDIO设备起始地址0x109增量写入5个字节的数据
ret SdioWriteBytes(handle, wbuff, addr, sizeof(wbuff) / sizeof(wbuff[0]));
if (ret ! HDF_SUCCESS) {HDF_LOGE(SdioWriteBytes: sdio write bytes fail, ret:%d\n, ret);return ret;
} 从SDIO设备增量读取指定长度的数据 对应的接口函数如下所示 int32_t SdioReadBytes(DevHandle handle, uint8_t *data, uint32_t addr, uint32_t size); 表 7 SdioReadBytes函数的参数和返回值描述 参数参数描述handleDevHandle类型SDIO控制器的设备句柄datauint8_t类型指针接收读取数据addruint32_t类型待读取数据的起始地址sizeuint32_t类型待读取数据的长度返回值返回值描述HDF_SUCCESSSDIO读数据成功负数SDIO读数据失败从SDIO设备增量读取指定长度的数据的示例如下 int32_t ret;
uint8_t rbuff[5] {0};
uint32_t addr 0x100 0x09;
// 从SDIO设备起始地址0x109增量读取5个字节的数据
ret SdioReadBytes(handle, rbuff, addr, 5);
if (ret ! HDF_SUCCESS) {HDF_LOGE(SdioReadBytes: sdio read bytes fail, ret:%d\n, ret);return ret;
} 向SDIO设备的固定地址写入指定长度的数据 对应的接口函数如下所示 int32_t SdioWriteBytesToFixedAddr(DevHandle handle, uint8_t *data, uint32_t addr, uint32_t size, uint32_t scatterLen); 表 8 SdioWriteBytesToFixedAddr函数的参数和返回值描述 参数参数描述handleDevHandle类型SDIO控制器的设备句柄datauint8_t类型指针待写入数据addruint32_t类型待写入数据的固定地址sizeuint32_t类型待写入数据的长度scatterLenuint32_t类型集散表的长度。如果该字段不为0则data为集散表类型。返回值返回值描述HDF_SUCCESSSDIO写数据成功负数SDIO写数据失败向SDIO设备的固定地址写入指定长度的数据的示例如下 int32_t ret;
uint8_t wbuff[] {1, 2, 3, 4, 5};
uint32_t addr 0x100 0x09;
// 向SDIO设备固定地址0x109写入5个字节的数据
ret SdioWriteBytesToFixedAddr(handle, wbuff, addr, sizeof(wbuff) / sizeof(wbuff[0]), 0);
if (ret ! HDF_SUCCESS) {HDF_LOGE(SdioWriteBytesToFixedAddr: sdio write bytes to fixed addr fail, ret:%d\n, ret);return ret;
} 从SDIO设备的固定地址读取指定长度的数据 对应的接口函数如下所示 int32_t SdioReadBytesFromFixedAddr(DevHandle handle, uint8_t *data, uint32_t addr, uint32_t size, uint32_t scatterLen); 表 9 SdioReadBytesFromFixedAddr函数的参数和返回值描述 参数参数描述handleDevHandle类型SDIO控制器的设备句柄datauint8_t类型指针接收读取数据addruint32_t类型待读取数据的起始地址sizeuint32_t类型待读取数据的长度scatterLenuint32_t类型集散表的长度。如果该字段不为0则data为集散表类型。返回值返回值描述HDF_SUCCESSSDIO读数据成功负数SDIO读数据失败从SDIO设备的固定地址读取指定长度的数据的示例如下 int32_t ret;
uint8_t rbuff[5] {0};
uint32_t addr 0x100 0x09;
// 从SDIO设备固定地址0x109中读取5个字节的数据
ret SdioReadBytesFromFixedAddr(handle, rbuff, addr, 5, 0);
if (ret ! HDF_SUCCESS) {HDF_LOGE(SdioReadBytesFromFixedAddr: sdio read bytes from fixed addr fail, ret:%d\n, ret);return ret;
} 向SDIO function 0的指定地址空间写入指定长度的数据 当前只支持写入一个字节的数据对应的接口函数如下所示 int32_t SdioWriteBytesToFunc0(DevHandle handle, uint8_t *data, uint32_t addr, uint32_t size); 表 10 SdioWriteBytesToFunc0函数的参数和返回值描述 参数参数描述handleDevHandle类型SDIO控制器的设备句柄datauint8_t类型指针待写入数据addruint32_t类型待写入数据的起始地址sizeuint32_t类型待写入数据的长度返回值返回值描述HDF_SUCCESSSDIO写数据成功负数SDIO写数据失败向SDIO function 0的指定地址空间写入指定长度的数据的示例如下 int32_t ret;
uint8_t wbuff 1;
// 向SDIO function 0地址0x2中写入1字节的数据
ret SdioWriteBytesToFunc0(handle, wbuff, 0x2, 1);
if (ret ! HDF_SUCCESS) {HDF_LOGE(SdioWriteBytesToFunc0: sdio write bytes to func0 fail, ret:%d\n, ret);return ret;
} 从SDIO function 0的指定地址空间读取指定长度的数据 当前只支持读取一个字节的数据对应的接口函数如下所示 int32_t SdioReadBytesFromFunc0(DevHandle handle, uint8_t *data, uint32_t addr, uint32_t size); 表 11 SdioReadBytesFromFunc0函数的参数和返回值描述 参数参数描述handleDevHandle类型SDIO控制器的设备句柄datauint8_t类型指针接收读取数据addruint32_t类型待读取数据的起始地址sizeuint32_t类型待读取数据的长度返回值返回值描述HDF_SUCCESSSDIO读数据成功负数SDIO读数据失败从SDIO function 0的指定地址空间读取指定长度的数据的示例如下 int32_t ret;
uint8_t rbuff;
/* 从SDIO function 0设备地址0x2中读取1字节的数据 */
ret SdioReadBytesFromFunc0(handle, rbuff, 0x2, 1);
if (ret ! 0) {HDF_LOGE(SdioReadBytesFromFunc0: sdio read bytes from func0 fail, ret:%d\n, ret);return ret;
}
释放SDIO中断
通信完成之后需要释放SDIO中断函数如下所示
int32_t SdioReleaseIrq(DevHandle handle);
表 12 SdioReleaseIrq函数的参数和返回值描述
参数参数描述handleDevHandle类型SDIO控制器的设备句柄返回值返回值描述HDF_SUCCESS释放SDIO中断成功负数释放SDIO中断失败
释放SDIO中断的示例如下
int32_t ret;
// 释放SDIO中断
ret SdioReleaseIrq(handle);
if (ret ! HDF_SUCCESS) {HDF_LOGE(SdioReleaseIrq: sdio release irq fail, ret:%d\n, ret);return ret;
}
去使能SDIO设备
通信完成之后还需要去使能SDIO设备函数如下所示
int32_t SdioDisableFunc(DevHandle handle);
表 13 SdioDisableFunc函数的参数和返回值描述
参数参数描述handleDevHandle类型SDIO控制器的设备句柄返回值返回值描述HDF_SUCCESS去使能SDIO设备成功负数去使能SDIO设备失败
去使能SDIO设备的示例如下
int32_t ret;
// 去使能SDIO设备
ret SdioDisableFunc(handle);
if (ret ! HDF_SUCCESS) {HDF_LOGE(SdioDisableFunc: sdio disable func fail, ret:%d\n, ret);return ret;
}
释放HOST
通信完成之后还需要释放去HOST函数如下所示
void SdioReleaseHost(DevHandle handle);
表 14 SdioReleaseHost函数的参数描述
参数参数描述handleDevHandle类型SDIO控制器的设备句柄
释放HOST的示例如下
SdioReleaseHost(handle); // 释放HOST
关闭SDIO控制器
SDIO通信完成之后最后需要关闭SDIO控制器函数如下所示
void SdioClose(DevHandle handle);
该函数会释放掉申请的资源。
表 15 SdioClose函数的参数描述
参数参数描述handleDevHandle类型SDIO控制器的设备句柄
关闭SDIO控制器的示例如下
SdioClose(handle); // 关闭SDIO控制器
使用实例
本例拟对Hi3516DV300开发板上SDIO设备进行操作。
SDIO设备完整的使用示例如下所示首先打开总线号为1的SDIO控制器然后独占HOST、使能设备、注册中断接着进行SDIO通信读写等通信完成之后释放中断、去使能设备、释放HOST最后关闭SDIO控制器。
#include hdf_log.h
#include sdio_if.h#define TEST_FUNC_NUM 1 /* 本测试用例中使用编号为1的I/O function */
#define TEST_FBR_BASE_ADDR 0x100 /* 编号为1的I/O function的FBR基地址 */
#define TEST_ADDR_OFFSET 9 /* 本测试用例中需要读写的寄存器的地址偏移 */
#define TEST_DATA_LEN 3 /* 本测试用例中读写数据的长度 */
#define TEST_BLOCKSIZE 2 /* 本测试用例中数据块的大小单位字节 *//* 中断服务函数需要根据各自平台的情况去实现 */
static void SdioIrqFunc(void *data)
{if (data NULL) {HDF_LOGE(SdioIrqFunc: data is NULL.\n);return;}/* 需要开发者自行添加具体的实现 */
}void SdioTestSample(void)
{int32_t ret; DevHandle handle NULL;uint8_t data[TEST_DATA_LEN] {0};struct SdioFunctionConfig config {1, 0x123, 0x456};uint8_t val;uint32_t addr;/* 打开总线号为1的SDIO设备 */handle SdioOpen(1, config);if (handle NULL) {HDF_LOGE(SdioOpen: failed!\n);return;}/* 独占HOST */SdioClaimHost(handle);/* 使能SDIO设备 */ret SdioEnableFunc(handle);if (ret ! 0) {HDF_LOGE(SdioEnableFunc: failed, ret %d\n, ret);goto ENABLE_ERR;}/* 注册中断 */ret SdioClaimIrq(handle, SdioIrqFunc);if (ret ! 0) {HDF_LOGE(SdioClaimIrq: failed, ret %d\n, ret);goto CLAIM_IRQ_ERR;}/* 设置块大小为2字节 */ret SdioSetBlockSize(handle, TEST_BLOCKSIZE);if (ret ! 0) {HDF_LOGE(SdioSetBlockSize: failed, ret %d\n, ret);goto COMM_ERR;}/* 从SDIO设备增量地址读取3字节的数据 */addr TEST_FBR_BASE_ADDR * TEST_FUNC_NUM TEST_ADDR_OFFSET;ret SdioReadBytes(handle, data, addr, TEST_DATA_LEN);if (ret ! 0) {HDF_LOGE(SdioReadBytes: failed, ret %d\n, ret);goto COMM_ERR;}/* 向SDIO设备增量地址写入3字节的数据 */ret SdioWriteBytes(handle, data, addr, TEST_DATA_LEN);if (ret ! 0) {HDF_LOGE(SdioWriteBytes: failed, ret %d\n, ret);goto COMM_ERR;}/* 从SDIO设备读取1字节的数据 */ret SdioReadBytes(handle, val, addr, 1);if (ret ! 0) {HDF_LOGE(SdioReadBytes: failed, ret %d\n, ret);goto COMM_ERR;}/* 向SDIO设备写入1字节的数据 */ret SdioWriteBytes(handle, val, addr, 1);if (ret ! 0) {HDF_LOGE(SdioWriteBytes: failed, ret %d\n, ret);goto COMM_ERR;}/* 从SDIO设备固定地址读取3字节的数据 */ret SdioReadBytesFromFixedAddr(handle, data, addr, TEST_DATA_LEN, 0);if (ret ! 0) {HDF_LOGE(SdioReadBytesFromFixedAddr: failed, ret %d\n, ret);goto COMM_ERR;}/* 向SDIO设备固定地址写入1字节的数据 */ret SdioWriteBytesToFixedAddr(handle, data, addr, 1, 0);if (ret ! 0) {HDF_LOGE(SdioWriteBytesToFixedAddr: failed, ret %d\n, ret);goto COMM_ERR;}/* 从SDIO function 0读取1字节的数据 */addr 0x02;ret SdioReadBytesFromFunc0(handle, val, addr, 1);if (ret ! 0) {HDF_LOGE(SdioReadBytesFromFunc0: failed, ret %d\n, ret);goto COMM_ERR;}/* 向SDIO function 0写入1字节的数据 */ret SdioWriteBytesToFunc0(handle, val, addr, 1);if (ret ! 0) {HDF_LOGE(SdioWriteBytesToFunc0: failed, ret %d\n, ret);goto COMM_ERR;}
COMM_ERR:/* 释放中断 */ret SdioReleaseIrq(handle);if (ret ! 0) {HDF_LOGE(SdioReleaseIrq: failed, ret %d\n, ret);}
CLAIM_IRQ_ERR:/* 去使能SDIO设备 */ret SdioDisableFunc(handle);if (ret ! 0) {HDF_LOGE(SdioDisableFunc: failed, ret %d\n, ret);}
ENABLE_ERR:/* 释放HOST */SdioReleaseHost(handle);/* 关闭SDIO设备 */SdioClose(handle);
}
最后
有很多小伙伴不知道学习哪些鸿蒙开发技术不知道需要重点掌握哪些鸿蒙应用开发知识点而且学习时频繁踩坑最终浪费大量时间。所以有一份实用的鸿蒙HarmonyOS NEXT资料用来跟着学习是非常有必要的。
这份鸿蒙HarmonyOS NEXT资料包含了鸿蒙开发必掌握的核心知识要点内容包含了ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、Harmony南向开发、鸿蒙项目实战等等鸿蒙HarmonyOS NEXT技术知识点。
希望这一份鸿蒙学习资料能够给大家带来帮助有需要的小伙伴自行领取限时开源先到先得~无套路领取
获取这份完整版高清学习路线请点击→纯血版全套鸿蒙HarmonyOS学习资料
鸿蒙HarmonyOS NEXT最新学习路线 HarmonOS基础技能 HarmonOS就业必备技能 HarmonOS多媒体技术 鸿蒙NaPi组件进阶 HarmonOS高级技能 初识HarmonOS内核 实战就业级设备开发 有了路线图怎么能没有学习资料呢小编也准备了一份联合鸿蒙官方发布笔记整理收纳的一套系统性的鸿蒙OpenHarmony 学习手册共计1236页与鸿蒙OpenHarmony 开发入门教学视频内容包含ArkTS、ArkUI、Web开发、应用模型、资源分类…等知识点。
获取以上完整版高清学习路线请点击→纯血版全套鸿蒙HarmonyOS学习资料
《鸿蒙 (OpenHarmony)开发入门教学视频》 《鸿蒙生态应用开发V2.0白皮书》 《鸿蒙 (OpenHarmony)开发基础到实战手册》
OpenHarmony北向、南向开发环境搭建 《鸿蒙开发基础》
ArkTS语言安装DevEco Studio运用你的第一个ArkTS应用ArkUI声明式UI开发.…… 《鸿蒙开发进阶》
Stage模型入门网络管理数据管理电话服务分布式应用开发通知与窗口管理多媒体技术安全技能任务管理WebGL国际化开发应用测试DFX面向未来设计鸿蒙系统移植和裁剪定制…… 《鸿蒙进阶实战》
ArkTS实践UIAbility应用网络案例…… 获取以上完整鸿蒙HarmonyOS学习资料请点击→纯血版全套鸿蒙HarmonyOS学习资料
总结
总的来说华为鸿蒙不再兼容安卓对中年程序员来说是一个挑战也是一个机会。只有积极应对变化不断学习和提升自己他们才能在这个变革的时代中立于不败之地。