Harmony鸿蒙南向驱动开发-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独立服务模式结构图

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的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)独占Host
void SdioReleaseHost(DevHandle handle)释放Host
int32_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控制器

在使用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学习资料

总结

总的来说,华为鸿蒙不再兼容安卓,对中年程序员来说是一个挑战,也是一个机会。只有积极应对变化,不断学习和提升自己,他们才能在这个变革的时代中立于不败之地。 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/306854.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

总分410+专业130+国防科技大学831信号与系统考研经验国防科大电子信息与通信工程,真题,大纲,参考书。

好几个学弟催着,总结一下我自己的复习经历,希望大家复习少走弯路,投入的复习正比换回分数。我专业课831信号与系统130(感觉比估分要低,后面找Jenny老师讨论了自己拿不准的地方也没有错误,心里最近也这经常回…

记账本|基于SSM的家庭记账本小程序设计与实现(源码+数据库+文档)

家庭记账本小程序目录 基于SSM的家庭记账本小程序设计与实现 一、前言 二、系统设计 三、系统功能设计 1、小程序端: 2、后台 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取: 博主介绍:✌️大…

【opencv】示例-imagelist_creator.cpp 从命令行参数中创建一个图像文件列表(yaml格式)...

/* 这个程序可以创建一个命令行参数列表的yaml或xml文件列表 */ // 包含必要的OpenCV头文件 #include "opencv2/core.hpp" #include "opencv2/imgcodecs.hpp" #include "opencv2/highgui.hpp" #include <string> #include <iostream>…

视频秒播优化实践

本文字数&#xff1a;2259字 预计阅读时间&#xff1a;10分钟 视频起播时间&#xff0c;即首帧时间&#xff0c;是视频类应用的一个重要核心指标&#xff0c;也是影响用户观看体验的核心因素之一。如果视频要加载很久才能开始播放&#xff0c;用户放弃播放甚至离开 App 的概率都…

飞书api增加权限

1&#xff0c;进入飞书开发者后台&#xff1a;飞书开放平台 给应用增加权限 2&#xff0c;进入飞书管理后台 https://fw5slkpbyb3.feishu.cn/admin/appCenter/audit 审核最新发布的版本 如果还是不行&#xff0c;则需要修改数据权限&#xff0c;修改为全部成员可修改。 改完…

大数据架构之关系型数据仓库——解读大数据架构(二)

文章目录 前言什么是关系型数仓对数仓的错误认识与使用自上而下的方法关系型数仓的优点关系型数仓的缺点数据加载加载数据的频率如何确定变更数据 关系型数仓会消失吗总结 前言 本文对关系型数据仓库&#xff08;RDW&#xff09;进行了简要的介绍说明&#xff0c;包括什么是关…

课时93:流程控制_函数进阶_综合练习

1.1.3 综合练习 学习目标 这一节&#xff0c;我们从 案例解读、脚本实践、小结 三个方面来学习。 案例解读 案例需求 使用shell脚本绘制一个杨辉三角案例解读 1、每行数字左右对称&#xff0c;从1开始变大&#xff0c;然后变小为1。    2、第n行的数字个数为n个&#xf…

Bug及异常:unity场景角色移动卡墙壁的问题

场景是一个小的杠铃形状封闭空间&#xff0c;美术没有给包围盒&#xff0c;我自己用blender做了一个&#xff08;属于兴趣爱好&#xff09;&#xff0c;如下&#xff1a; 导入场景中使用meshcollider做成空气墙&#xff0c;发现角色移动到角落继续行走会卡角落处&#x…

谷歌pixel6/7pro等手机WiFi不能上网,显示网络连接受限

近期在项目中遇到一个机型出现的问题,先对项目代码进行排查,发现别的设备都能正常运行,就开始来排查机型的问题,特意写出来方便后续查看,也方便其它开发者来自查。 设备机型:Pixel 6a 设备安卓版本:13 该方法无需root,只需要电脑设备安装adb(即Android Debug Bridge…

分布式技术---------------消息队列中间件之 Kafka

目录 一、Kafka 概述 1.1为什么需要消息队列&#xff08;MQ&#xff09; 1.2使用消息队列的好处 1.2.1解耦 1.2.2可恢复性 1.2.3缓冲 1.2.4灵活性 & 峰值处理能力 1.2.5异步通信 1.3消息队列的两种模式 1.3.1点对点模式&#xff08;一对一&#xff0c;消费者主动…

出海企业如何从海外云手机中受益?

随着全球化的推进&#xff0c;越来越多的企业开始将目光投向海外市场。然而&#xff0c;不同国家和地区的网络环境、政策限制&#xff0c;以及语言文化的差异&#xff0c;给出海企业的市场拓展带来了诸多挑战。在这一背景下&#xff0c;海外云手机作为一种新兴解决方案&#xf…

MySQL如何定位慢查询?如何分析这条慢查询?

常见的慢查询 聚合查询&#xff08;常用的聚合函数有&#xff1a;MAX&#xff08;&#xff09;、MIN&#xff08;&#xff09;、COUNT&#xff08;&#xff09;、SUM&#xff08;&#xff09;、AVG&#xff08;&#xff09;&#xff09;。 多表查询 表数据过大查询 深度分页…

【Tomcat 文件读取/文件包含(CVE-2020-1938)漏洞复现】

文章目录 前言 一、漏洞名称 二、漏洞描述 三、受影响端口 四、受影响版本 五、漏洞验证 六、修复建议 前言 近日在做漏扫时发现提示服务器存在CVE-2020-1938漏洞&#xff0c;故文章记录一下相关内容。 一、漏洞名称 Tomcat 文件读取/文件包含漏洞(CVE-2020-1938) 二、漏洞描…

【SpringBoot】mybatis-plus实现增删改查

mapper继承BaseMapper service 继承ServiceImpl 使用方法新增 save,updateById新增和修改方法返回boolean值,或者使用saveOrUpdate方法有id执行修改操作,没有id 执行新增操作 案例 Service public class UserService extends ServiceImpl<UserMapper,User> {// Au…

送礼物动态特效直播和短视频特效源码送礼物动态连麦PK特效语音视频聊天室朋友圈十套

内附十套动画效果源码&#xff0c;可F5刷新随机显示特效预览。送礼物动态特效直播和短视频特效源码送礼物动态连麦PK特效语音视频聊天室朋友圈十套 SVGA 是一种用于嵌入式动画的矢量文件格式&#xff0c;通常用于在移动应用程序和网页中展示高质量的动画效果。相对于传统的 GIF…

办公软件巨头CCED、WPS迎来新挑战,新款办公软件已形成普及之势

办公软件巨头CCED、WPS的成长经历 CCED与WPS&#xff0c;这两者均是中国办公软件行业的佼佼者&#xff0c;为人们所熟知。 然而&#xff0c;它们的成功并非一蹴而就&#xff0c;而是经过了长时间的积累与沉淀。 CCED&#xff0c;这款中国大陆早期的文本编辑器&#xff0c;在上…

区块链安全-----区块链基础

区块链是一种全新的信息网络架构 &#xff0c;是新一代信息基础设施 &#xff0c;是新型的价值交换方式、 分布式协 同生产机制以及新型的算法经济模式的基础。 区块链技术可以集成到多个领域。 区块链的主要用途 是作为加密货币的分布式总帐。 它在银行 &#xff0c;金融 &…

软件定义车队面临网络安全的曲折之路

当以色列 REE Automotive 设计其 P7 电动汽车底盘时&#xff0c;它是从软件开始工作的&#xff1a;扁平的车辆底盘完全可配置&#xff0c;每个轮胎附近有四个独立的模块&#xff0c;用于转向、制动、悬架和动力传动系统&#xff0c;每个模块均由电子驱动控制单元&#xff08;EC…

【Hadoop】下载安装及伪分布式集群搭建教程

目录 1.概述 2.环境准备 3.hadoop安装 3.1.下载安装配置 3.2.伪分布式集群 3.3.注意事项 4.Hadoop集群的组成 1.概述 hadoop有三种安装模式 单机模式&#xff0c;只在一台机器上运行&#xff0c;存储用的本地文件系统而不是HDFS。 伪分布式模式&#xff0c;存储采用HD…

LDF、DBC、BIN、HEX、S19、BLF、ARXML、slx等

文章目录 如题 如题 LDF是LIN报文格式文件&#xff0c;把这个直接拖到软件里面&#xff0c;可以发报文和接收报文 DBC是CAN报文格式文件&#xff0c;把这个直接拖到软件里面&#xff0c;可以发报文和接收报文 BIN文件烧录在BOOT里面&#xff08;stm32&#xff09;&#xff0c…