1# SDIO 2 3## 概述 4 5### 功能简介 6 7SDIO是安全数字输入输出接口(Secure Digital Input and Output)的缩写,是从SD内存卡接口的基础上演化出来的一种外设接口。SDIO接口兼容以前的SD卡,并且可以连接支持SDIO接口的其他设备。 8 9SDIO接口定义了操作SDIO的通用方法集合,包括: 10 11- 打开/关闭SDIO控制器 12 13- 独占/释放HOST 14 15- 使能/去使能设备 16 17- 申请/释放中断 18 19- 读写、获取/设置公共信息 20 21### 运作机制 22 23在HDF框架中,SDIO的接口适配模式采用独立服务模式。在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。独立服务模式可以直接借助HDFDeviceManager的服务管理能力,但需要为每个设备单独配置设备节点,若设备过多可能增加内存占用。 24 25独立服务模式下,核心层不会统一发布一个服务供上层使用,因此这种模式下驱动要为每个控制器发布一个服务,具体表现为: 26 27- 驱动适配者需要实现HdfDriverEntry的Bind钩子函数以绑定服务。 28 29- device_info.hcs文件中deviceNode的policy字段为1或2,不能为0。 30 31SDIO模块各分层作用: 32 33- 接口层提供打开SDIO设备、设置块的大小、读取数据、写数据、设置公共信息、获取公共信息、刷新数据、独占HOST、释放Host、使能SDIO功能设备、去使能SDIO功能设备、申请中断、释放中断关闭SDIO设备的接口。 34 35- 核心层主要提供SDIO控制器的添加、移除及管理的能力,通过钩子函数与适配层交互。 36 37- 适配层主要是将钩子函数的功能实例化,实现具体的功能。 38 39**图 1** SDIO独立服务模式结构图 40 41 42 43SDIO总线有两端,其中一端是主机端(HOST),另一端是设备端(DEVICE)。所有的通信都是由HOST端发出命令开始的,在DEVICE端只要能解析HOST的命令,就可以同HOST进行通信了。SDIO的HOST可以连接多个DEVICE,如图2所示: 44 45- CLK信号:HOST给DEVICE的时钟信号。 46 47- VDD信号:电源信号。 48 49- VSS信号:Ground信号。 50 51- D0-3信号:4条数据线,其中,DAT1信号线复用为中断线,在1BIT模式下DAT0用来传输数据,在4BIT模式下DAT0-DAT3用来传输数据。 52 53- CMD信号:用于HOST发送命令和DEVICE回复响应。 54 55**图 2** SDIO的HOST-DEVICE连接示意图 56 57 58 59### 约束与限制 60 61SDIO模块API当前仅支持内核态调用。 62 63## 使用指导 64 65### 场景介绍 66 67SDIO的应用比较广泛,目前,有许多手机都支持SDIO功能,并且很多SDIO外设也被开发出来,使得手机外接外设更加容易。常见的SDIO外设有WLAN、GPS、CAMERA、蓝牙等。 68 69### 接口说明 70 71SDIO模块提供的主要接口如表1所示,具体API详见//drivers/hdf_core/framework/include/platform/sdio_if.h。 72 73**表 1** SDIO驱动API接口功能介绍 74 75| 接口名 | 接口描述 | 76| -------- | -------- | 77| DevHandle SdioOpen(int16_t mmcBusNum, struct SdioFunctionConfig \*config) | 打开指定总线号的SDIO控制器 | 78| void SdioClose(DevHandle handle) | 关闭SDIO控制器 | 79| int32_t SdioReadBytes(DevHandle handle, uint8_t \*data, uint32_t addr, uint32_t size) | 从指定地址开始,增量读取指定长度的数据 | 80| int32_t SdioWriteBytes(DevHandle handle, uint8_t \*data, uint32_t addr, uint32_t size) | 从指定地址开始,增量写入指定长度的数据 | 81| int32_t SdioReadBytesFromFixedAddr(DevHandle handle, uint8_t \*data, uint32_t addr, uint32_t size, uint32_t scatterLen) | 从固定地址读取指定长度的数据 | 82| int32_t SdioWriteBytesToFixedAddr(DevHandle handle, uint8_t \*data, uint32_t addr, uint32_t size, uint32_t scatterLen) | 向固定地址写入指定长度的数据 | 83| int32_t SdioReadBytesFromFunc0(DevHandle handle, uint8_t \*data, uint32_t addr, uint32_t size) | 从SDIO function 0的指定地址空间读取指定长度的数据 | 84| int32_t SdioWriteBytesToFunc0(DevHandle handle, uint8_t \*data, uint32_t addr, uint32_t size) | 向SDIO function 0的指定地址空间写入指定长度的数据 | 85| int32_t SdioSetBlockSize(DevHandle handle, uint32_t blockSize) | 设置块的大小 | 86| int32_t SdioGetCommonInfo(DevHandle handle, SdioCommonInfo \*info, SdioCommonInfoType infoType) | 获取公共信息 | 87| int32_t SdioSetCommonInfo(DevHandle handle, SdioCommonInfo \*info, SdioCommonInfoType infoType) | 设置公共信息 | 88| int32_t SdioFlushData(DevHandle handle) | 刷新数据 | 89| void SdioClaimHost(DevHandle handle) | 独占Host | 90| void SdioReleaseHost(DevHandle handle) | 释放Host | 91| int32_t SdioEnableFunc(DevHandle handle) | 使能SDIO功能设备 | 92| int32_t SdioDisableFunc(DevHandle handle) | 去使能SDIO功能设备 | 93| int32_t SdioClaimIrq(DevHandle handle, SdioIrqHandler \*irqHandler) | 申请中断 | 94| int32_t SdioReleaseIrq(DevHandle handle) | 释放中断 | 95 96### 使用流程 97 98使用SDIO的一般流程如图3所示。 99 100**图 3** SDIO使用流程图 101 102 103 104#### 打开SDIO控制器 105 106在使用SDIO进行通信前,首先要调用SdioOpen获取SDIO控制器的设备句柄,该函数会返回指定总线号的SDIO控制器的设备句柄。 107 108```c 109DevHandle SdioOpen(int16_t mmcBusNum, struct SdioFunctionConfig *config); 110``` 111 112**表 2** SdioOpen函数的参数和返回值描述 113 114| 参数 | 参数描述 | 115| -------- | -------- | 116| mmcBusNum | int16_t类型,总线号 | 117| config | 结构体指针,SDIO功能配置信息 | 118| **返回值** | **返回值描述** | 119| NULL | 获取SDIO控制器的设备句柄失败 | 120| 设备句柄 | SDIO控制器的设备句柄 | 121 122打开SDIO控制器的示例如下: 123 124```c 125DevHandle handle = NULL; 126struct SdioFunctionConfig config; 127config.funcNr = 1; 128config.vendorId = 0x123; 129config.deviceId = 0x456; 130// 打开总线号为1的SDIO控制器 131handle = SdioOpen(1, &config); 132if (handle == NULL) { 133 HDF_LOGE("SdioOpen: open sdio fail!\n"); 134 return NULL; 135} 136``` 137 138#### 独占HOST 139 140获取到SDIO控制器的设备句柄之后,需要先独占HOST才能进行SDIO后续的一系列操作,独占HOST函数如下所示: 141 142```c 143void SdioClaimHost(DevHandle handle); 144``` 145 146**表 3** SdioClaimHost函数的参数描述 147 148| 参数 | 参数描述 | 149| -------- | -------- | 150| handle | DevHandle类型,SDIO控制器的设备句柄 | 151 152独占HOST示例如下: 153 154```c 155SdioClaimHost(handle); // 独占HOST 156``` 157 158#### 使能SDIO设备 159 160在访问寄存器之前,需要先使能SDIO设备,使能SDIO设备的函数如下所示: 161 162```c 163int32_t SdioEnableFunc(DevHandle handle); 164``` 165 166**表 4** SdioEnableFunc函数的参数和返回值描述 167 168| 参数 | 参数描述 | 169| -------- | -------- | 170| handle | DevHandle类型,SDIO控制器的设备句柄 | 171| **返回值** | **返回值描述** | 172| HDF_SUCCESS | SDIO使能成功 | 173| 负数 | SDIO使能失败 | 174 175使能SDIO设备的示例如下: 176 177```c 178int32_t ret; 179// 使能SDIO设备 180ret = SdioEnableFunc(handle); 181if (ret != HDF_SUCCESS) { 182 HDF_LOGE("SdioEnableFunc: sdio enable func fail, ret:%d\n", ret); 183 return ret; 184} 185``` 186 187#### 注册SDIO中断 188 189在通信之前,还需要注册SDIO中断,注册SDIO中断函数如下所示: 190 191```c 192int32_t SdioClaimIrq(DevHandle handle, SdioIrqHandler *handler); 193``` 194 195**表 5** SdioClaimIrq函数的参数和返回值描述 196 197| 参数 | 参数描述 | 198| -------- | -------- | 199| handle | DevHandle类型,SDIO控制器的设备句柄 | 200| handler | 函数指针,中断服务函数 | 201| **返回值** | **返回值描述** | 202| HDF_SUCCESS | 注册SDIO中断成功 | 203| 负数 | 注册SDIO中断失败 | 204 205 注册SDIO中的示例如下: 206 207```c 208// 中断服务函数需要根据各自平台的情况去实现 209static void SdioIrqFunc(void *data) 210{ 211 if (data == NULL) { 212 HDF_LOGE("SdioIrqFunc: data is NULL.\n"); 213 return; 214 } 215 // 需要开发者自行添加具体实现 216} 217 218int32_t ret; 219// 注册SDIO中断 220ret = SdioClaimIrq(handle, SdioIrqFunc); 221if (ret != HDF_SUCCESS) { 222 HDF_LOGE("SdioClaimIrq: sdio claim irq fail, ret:%d\n", ret); 223 return ret; 224} 225``` 226 227#### 进行SDIO通信 228 229- 向SDIO设备增量写入指定长度的数据 230 231 对应的接口函数如下所示: 232 233 ```c 234 int32_t SdioWriteBytes(DevHandle handle, uint8_t *data, uint32_t addr, uint32_t size); 235 ``` 236 237 **表 6** SdioWriteBytes函数的参数和返回值描述 238 239 | 参数 | 参数描述 | 240 | -------- | -------- | 241 | handle | DevHandle类型,SDIO控制器的设备句柄 | 242 | data | uint8_t类型指针,待写入数据 | 243 | addr | uint32_t类型,待写入数据的起始地址 | 244 | size | uint32_t类型,待写入数据的长度 | 245 | **返回值** | **返回值描述** | 246 | HDF_SUCCESS | SDIO写数据成功 | 247 | 负数 | SDIO写数据失败 | 248 249 向SDIO设备增量写入指定长度的数据的示例如下: 250 251 ```c 252 int32_t ret; 253 uint8_t wbuff[] = {1,2,3,4,5}; 254 uint32_t addr = 0x100 + 0x09; 255 // 向SDIO设备起始地址0x109,增量写入5个字节的数据 256 ret = SdioWriteBytes(handle, wbuff, addr, sizeof(wbuff) / sizeof(wbuff[0])); 257 if (ret != HDF_SUCCESS) { 258 HDF_LOGE("SdioWriteBytes: sdio write bytes fail, ret:%d\n", ret); 259 return ret; 260 } 261 ``` 262 263- 从SDIO设备增量读取指定长度的数据 264 265 对应的接口函数如下所示: 266 267 ```c 268 int32_t SdioReadBytes(DevHandle handle, uint8_t *data, uint32_t addr, uint32_t size); 269 ``` 270 271 **表 7** SdioReadBytes函数的参数和返回值描述 272 273 | 参数 | 参数描述 | 274 | -------- | -------- | 275 | handle | DevHandle类型,SDIO控制器的设备句柄 | 276 | data | uint8_t类型指针,接收读取数据 | 277 | addr | uint32_t类型,待读取数据的起始地址 | 278 | size | uint32_t类型,待读取数据的长度 | 279 | **返回值** | **返回值描述** | 280 | HDF_SUCCESS | SDIO读数据成功 | 281 | 负数 | SDIO读数据失败 | 282 283 从SDIO设备增量读取指定长度的数据的示例如下: 284 285 ```c 286 int32_t ret; 287 uint8_t rbuff[5] = {0}; 288 uint32_t addr = 0x100 + 0x09; 289 // 从SDIO设备起始地址0x109,增量读取5个字节的数据 290 ret = SdioReadBytes(handle, rbuff, addr, 5); 291 if (ret != HDF_SUCCESS) { 292 HDF_LOGE("SdioReadBytes: sdio read bytes fail, ret:%d\n", ret); 293 return ret; 294 } 295 ``` 296 297- 向SDIO设备的固定地址写入指定长度的数据 298 299 对应的接口函数如下所示: 300 301 ```c 302 int32_t SdioWriteBytesToFixedAddr(DevHandle handle, uint8_t *data, uint32_t addr, uint32_t size, uint32_t scatterLen); 303 ``` 304 305 **表 8** SdioWriteBytesToFixedAddr函数的参数和返回值描述 306 307 | 参数 | 参数描述 | 308 | -------- | -------- | 309 | handle | DevHandle类型,SDIO控制器的设备句柄 | 310 | data | uint8_t类型指针,待写入数据 | 311 | addr | uint32_t类型,待写入数据的固定地址 | 312 | size | uint32_t类型,待写入数据的长度 | 313 | scatterLen | uint32_t类型,集散表的长度。如果该字段不为0,则data为集散表类型。 | 314 | **返回值** | **返回值描述** | 315 | HDF_SUCCESS | SDIO写数据成功 | 316 | 负数 | SDIO写数据失败 | 317 318 向SDIO设备的固定地址写入指定长度的数据的示例如下: 319 320 ```c 321 int32_t ret; 322 uint8_t wbuff[] = {1, 2, 3, 4, 5}; 323 uint32_t addr = 0x100 + 0x09; 324 // 向SDIO设备固定地址0x109写入5个字节的数据 325 ret = SdioWriteBytesToFixedAddr(handle, wbuff, addr, sizeof(wbuff) / sizeof(wbuff[0]), 0); 326 if (ret != HDF_SUCCESS) { 327 HDF_LOGE("SdioWriteBytesToFixedAddr: sdio write bytes to fixed addr fail, ret:%d\n", ret); 328 return ret; 329 } 330 ``` 331 332- 从SDIO设备的固定地址读取指定长度的数据 333 334 对应的接口函数如下所示: 335 336 ```c 337 int32_t SdioReadBytesFromFixedAddr(DevHandle handle, uint8_t *data, uint32_t addr, uint32_t size, uint32_t scatterLen); 338 ``` 339 340 **表 9** SdioReadBytesFromFixedAddr函数的参数和返回值描述 341 342 | 参数 | 参数描述 | 343 | -------- | -------- | 344 | handle | DevHandle类型,SDIO控制器的设备句柄 | 345 | data | uint8_t类型指针,接收读取数据 | 346 | addr | uint32_t类型,待读取数据的起始地址 | 347 | size | uint32_t类型,待读取数据的长度 | 348 | scatterLen | uint32_t类型,集散表的长度。如果该字段不为0,则data为集散表类型。 | 349 | **返回值** | **返回值描述** | 350 | HDF_SUCCESS | SDIO读数据成功 | 351 | 负数 | SDIO读数据失败 | 352 353 从SDIO设备的固定地址读取指定长度的数据的示例如下: 354 355 ```c 356 int32_t ret; 357 uint8_t rbuff[5] = {0}; 358 uint32_t addr = 0x100 + 0x09; 359 // 从SDIO设备固定地址0x109中读取5个字节的数据 360 ret = SdioReadBytesFromFixedAddr(handle, rbuff, addr, 5, 0); 361 if (ret != HDF_SUCCESS) { 362 HDF_LOGE("SdioReadBytesFromFixedAddr: sdio read bytes from fixed addr fail, ret:%d\n", ret); 363 return ret; 364 } 365 ``` 366 367- 向SDIO function 0的指定地址空间写入指定长度的数据 368 369 当前只支持写入一个字节的数据,对应的接口函数如下所示: 370 371 ```c 372 int32_t SdioWriteBytesToFunc0(DevHandle handle, uint8_t *data, uint32_t addr, uint32_t size); 373 ``` 374 375 **表 10** SdioWriteBytesToFunc0函数的参数和返回值描述 376 377 | 参数 | 参数描述 | 378 | -------- | -------- | 379 | handle | DevHandle类型,SDIO控制器的设备句柄 | 380 | data | uint8_t类型指针,待写入数据 | 381 | addr | uint32_t类型,待写入数据的起始地址 | 382 | size | uint32_t类型,待写入数据的长度 | 383 | **返回值** | **返回值描述** | 384 | HDF_SUCCESS | SDIO写数据成功 | 385 | 负数 | SDIO写数据失败 | 386 387 向SDIO function 0的指定地址空间写入指定长度的数据的示例如下: 388 389 ```c 390 int32_t ret; 391 uint8_t wbuff = 1; 392 // 向SDIO function 0地址0x2中写入1字节的数据 393 ret = SdioWriteBytesToFunc0(handle, &wbuff, 0x2, 1); 394 if (ret != HDF_SUCCESS) { 395 HDF_LOGE("SdioWriteBytesToFunc0: sdio write bytes to func0 fail, ret:%d\n", ret); 396 return ret; 397 } 398 ``` 399 400- 从SDIO function 0的指定地址空间读取指定长度的数据 401 402 当前只支持读取一个字节的数据,对应的接口函数如下所示: 403 404 ```c 405 int32_t SdioReadBytesFromFunc0(DevHandle handle, uint8_t *data, uint32_t addr, uint32_t size); 406 ``` 407 408 **表 11** SdioReadBytesFromFunc0函数的参数和返回值描述 409 410 | 参数 | 参数描述 | 411 | -------- | -------- | 412 | handle | DevHandle类型,SDIO控制器的设备句柄 | 413 | data | uint8_t类型指针,接收读取数据 | 414 | addr | uint32_t类型,待读取数据的起始地址 | 415 | size | uint32_t类型,待读取数据的长度 | 416 | **返回值** | **返回值描述** | 417 | HDF_SUCCESS | SDIO读数据成功 | 418 | 负数 | SDIO读数据失败 | 419 420 从SDIO function 0的指定地址空间读取指定长度的数据的示例如下: 421 422 ```c 423 int32_t ret; 424 uint8_t rbuff; 425 /* 从SDIO function 0设备地址0x2中读取1字节的数据 */ 426 ret = SdioReadBytesFromFunc0(handle, &rbuff, 0x2, 1); 427 if (ret != 0) { 428 HDF_LOGE("SdioReadBytesFromFunc0: sdio read bytes from func0 fail, ret:%d\n", ret); 429 return ret; 430 } 431 ``` 432 433#### 释放SDIO中断 434 435通信完成之后,需要释放SDIO中断,函数如下所示: 436 437int32_t SdioReleaseIrq(DevHandle handle); 438 439**表 12** SdioReleaseIrq函数的参数和返回值描述 440 441| 参数 | 参数描述 | 442| -------- | -------- | 443| handle | DevHandle类型,SDIO控制器的设备句柄 | 444| **返回值** | **返回值描述** | 445| HDF_SUCCESS | 释放SDIO中断成功 | 446| 负数 | 释放SDIO中断失败 | 447 448释放SDIO中断的示例如下: 449 450```c 451int32_t ret; 452// 释放SDIO中断 453ret = SdioReleaseIrq(handle); 454if (ret != HDF_SUCCESS) { 455 HDF_LOGE("SdioReleaseIrq: sdio release irq fail, ret:%d\n", ret); 456 return ret; 457} 458``` 459 460#### 去使能SDIO设备 461 462通信完成之后,还需要去使能SDIO设备,函数如下所示: 463 464int32_t SdioDisableFunc(DevHandle handle); 465 466**表 13** SdioDisableFunc函数的参数和返回值描述 467 468| 参数 | 参数描述 | 469| -------- | -------- | 470| handle | DevHandle类型,SDIO控制器的设备句柄 | 471| **返回值** | **返回值描述** | 472| HDF_SUCCESS | 去使能SDIO设备成功 | 473| 负数 | 去使能SDIO设备失败 | 474 475去使能SDIO设备的示例如下: 476 477```c 478int32_t ret; 479// 去使能SDIO设备 480ret = SdioDisableFunc(handle); 481if (ret != HDF_SUCCESS) { 482 HDF_LOGE("SdioDisableFunc: sdio disable func fail, ret:%d\n", ret); 483 return ret; 484} 485``` 486 487#### 释放HOST 488 489通信完成之后,还需要释放去HOST,函数如下所示: 490 491```c 492void SdioReleaseHost(DevHandle handle); 493``` 494 495**表 14** SdioReleaseHost函数的参数描述 496 497| 参数 | 参数描述 | 498| -------- | -------- | 499| handle | DevHandle类型,SDIO控制器的设备句柄 | 500 501释放HOST的示例如下: 502 503```c 504SdioReleaseHost(handle); // 释放HOST 505``` 506 507#### 关闭SDIO控制器 508 509SDIO通信完成之后,最后需要关闭SDIO控制器,函数如下所示: 510 511```c 512void SdioClose(DevHandle handle); 513``` 514 515该函数会释放掉申请的资源。 516 517**表 15** SdioClose函数的参数描述 518 519| 参数 | 参数描述 | 520| -------- | -------- | 521| handle | DevHandle类型,SDIO控制器的设备句柄 | 522 523关闭SDIO控制器的示例如下: 524 525```c 526SdioClose(handle); // 关闭SDIO控制器 527``` 528 529### 使用实例 530 531本例拟对Hi3516DV300开发板上SDIO设备进行操作。 532 533SDIO设备完整的使用示例如下所示,首先打开总线号为1的SDIO控制器,然后独占HOST、使能设备、注册中断,接着进行SDIO通信(读写等),通信完成之后,释放中断、去使能设备、释放HOST,最后关闭SDIO控制器。 534 535```c 536#include "hdf_log.h" 537#include "sdio_if.h" 538 539#define TEST_FUNC_NUM 1 /* 本测试用例中,使用编号为1的I/O function */ 540#define TEST_FBR_BASE_ADDR 0x100 /* 编号为1的I/O function的FBR基地址 */ 541#define TEST_ADDR_OFFSET 9 /* 本测试用例中,需要读写的寄存器的地址偏移 */ 542#define TEST_DATA_LEN 3 /* 本测试用例中,读写数据的长度 */ 543#define TEST_BLOCKSIZE 2 /* 本测试用例中,数据块的大小,单位字节 */ 544 545/* 中断服务函数,需要根据各自平台的情况去实现 */ 546static void SdioIrqFunc(void *data) 547{ 548 if (data == NULL) { 549 HDF_LOGE("SdioIrqFunc: data is NULL.\n"); 550 return; 551 } 552 /* 需要开发者自行添加具体的实现 */ 553} 554 555void SdioTestSample(void) 556{ 557 int32_t ret; 558 DevHandle handle = NULL; 559 uint8_t data[TEST_DATA_LEN] = {0}; 560 struct SdioFunctionConfig config = {1, 0x123, 0x456}; 561 uint8_t val; 562 uint32_t addr; 563 564 /* 打开总线号为1的SDIO设备 */ 565 handle = SdioOpen(1, &config); 566 if (handle == NULL) { 567 HDF_LOGE("SdioOpen: failed!\n"); 568 return; 569 } 570 /* 独占HOST */ 571 SdioClaimHost(handle); 572 /* 使能SDIO设备 */ 573 ret = SdioEnableFunc(handle); 574 if (ret != 0) { 575 HDF_LOGE("SdioEnableFunc: failed, ret %d\n", ret); 576 goto ENABLE_ERR; 577 } 578 /* 注册中断 */ 579 ret = SdioClaimIrq(handle, SdioIrqFunc); 580 if (ret != 0) { 581 HDF_LOGE("SdioClaimIrq: failed, ret %d\n", ret); 582 goto CLAIM_IRQ_ERR; 583 } 584 /* 设置块大小为2字节 */ 585 ret = SdioSetBlockSize(handle, TEST_BLOCKSIZE); 586 if (ret != 0) { 587 HDF_LOGE("SdioSetBlockSize: failed, ret %d\n", ret); 588 goto COMM_ERR; 589 } 590 /* 从SDIO设备增量地址读取3字节的数据 */ 591 addr = TEST_FBR_BASE_ADDR * TEST_FUNC_NUM + TEST_ADDR_OFFSET; 592 ret = SdioReadBytes(handle, data, addr, TEST_DATA_LEN); 593 if (ret != 0) { 594 HDF_LOGE("SdioReadBytes: failed, ret %d\n", ret); 595 goto COMM_ERR; 596 } 597 /* 向SDIO设备增量地址写入3字节的数据 */ 598 ret = SdioWriteBytes(handle, data, addr, TEST_DATA_LEN); 599 if (ret != 0) { 600 HDF_LOGE("SdioWriteBytes: failed, ret %d\n", ret); 601 goto COMM_ERR; 602 } 603 /* 从SDIO设备读取1字节的数据 */ 604 ret = SdioReadBytes(handle, &val, addr, 1); 605 if (ret != 0) { 606 HDF_LOGE("SdioReadBytes: failed, ret %d\n", ret); 607 goto COMM_ERR; 608 } 609 /* 向SDIO设备写入1字节的数据 */ 610 ret = SdioWriteBytes(handle, &val, addr, 1); 611 if (ret != 0) { 612 HDF_LOGE("SdioWriteBytes: failed, ret %d\n", ret); 613 goto COMM_ERR; 614 } 615 /* 从SDIO设备固定地址读取3字节的数据 */ 616 ret = SdioReadBytesFromFixedAddr(handle, data, addr, TEST_DATA_LEN, 0); 617 if (ret != 0) { 618 HDF_LOGE("SdioReadBytesFromFixedAddr: failed, ret %d\n", ret); 619 goto COMM_ERR; 620 } 621 /* 向SDIO设备固定地址写入1字节的数据 */ 622 ret = SdioWriteBytesToFixedAddr(handle, data, addr, 1, 0); 623 if (ret != 0) { 624 HDF_LOGE("SdioWriteBytesToFixedAddr: failed, ret %d\n", ret); 625 goto COMM_ERR; 626 } 627 /* 从SDIO function 0读取1字节的数据 */ 628 addr = 0x02; 629 ret = SdioReadBytesFromFunc0(handle, &val, addr, 1); 630 if (ret != 0) { 631 HDF_LOGE("SdioReadBytesFromFunc0: failed, ret %d\n", ret); 632 goto COMM_ERR; 633 } 634 /* 向SDIO function 0写入1字节的数据 */ 635 ret = SdioWriteBytesToFunc0(handle, &val, addr, 1); 636 if (ret != 0) { 637 HDF_LOGE("SdioWriteBytesToFunc0: failed, ret %d\n", ret); 638 goto COMM_ERR; 639 } 640COMM_ERR: 641 /* 释放中断 */ 642 ret = SdioReleaseIrq(handle); 643 if (ret != 0) { 644 HDF_LOGE("SdioReleaseIrq: failed, ret %d\n", ret); 645 } 646CLAIM_IRQ_ERR: 647 /* 去使能SDIO设备 */ 648 ret = SdioDisableFunc(handle); 649 if (ret != 0) { 650 HDF_LOGE("SdioDisableFunc: failed, ret %d\n", ret); 651 } 652ENABLE_ERR: 653 /* 释放HOST */ 654 SdioReleaseHost(handle); 655 /* 关闭SDIO设备 */ 656 SdioClose(handle); 657} 658``` 659