当前位置: 首页 > news >正文

广告网站设计界面设计属于什么专业

广告网站设计,界面设计属于什么专业,什么叫电商怎么做电商,吉安网站推广徽hyhyk1Audio驱动概述 多媒体系统是物联网设备开发中不可缺少的一部分#xff0c;Audio作为其中重要的一个模块#xff0c;Audio驱动模型的构建显得尤为重要。 本文主要介绍基于HDF#xff08;Hardware Driver Foundation#xff09;驱动框架开发的Audio驱动#xff0c;包括Aud…Audio驱动概述 多媒体系统是物联网设备开发中不可缺少的一部分Audio作为其中重要的一个模块Audio驱动模型的构建显得尤为重要。 本文主要介绍基于HDFHardware Driver Foundation驱动框架开发的Audio驱动包括Audio驱动的架构组成和功能部件。芯片厂商可以根据此驱动架构进行各自驱动的开发及HAL层接口的调用。 Audio驱动框架介绍 Audio驱动框架基于HDF驱动框架实现。Audio驱动架构组成 驱动架构主要由以下几部分组成。 HDI adapter实现Audio HAL层驱动HDI接口适配给Audio服务frameworks提供所需的音频硬件驱动能力接口。包含 Audio Manager、Audio Adapter、Audio Control、Audio Capture、Audio Render等接口对象。 Audio Interface Lib配合内核中的Audio Driver Model使用实现音频硬件的控制、录音数据的读取、播放数据的写入。它里面包括Stream_ctrl_common 通用层主要是为了和上层的Audio HDI Adapter层进行对接。 ADMAudio Driver Model音频驱动框架模型向上服务于多媒体音频子系统便于系统开发者能够更便捷的根据场景来开发应用。向下服务于具体的设备厂商对于Codec和DSP设备厂商来说可根据ADM模块提供的向下统一接口适配各自的驱动代码就可以实现快速开发和适配OpenHarmony系统。 Audio Control Dispatch: 接收lib层的控制指令并将控制指令分发到驱动层。 Audio Stream Dispatch: 接收lib层的数据并将数据分发到驱动层。 Card Manager: 多声卡管理模块。每个声卡含有Dai、Platform、Codec、Dsp、SAPM模块。 Platform Drivers: 驱动适配层。 SAPMSmart Audio Power Manager电源管理模块对整个ADM电源进行功耗策略优化。 Audio驱动开发 以下将基于Audio驱动框架并以Hi3516DV300平台为例介绍相关驱动开发的具体步骤。 Audio ADM模块框架介绍 Audio驱动对HDI层提供三个服务hdf_audio_render、hdf_audio_capture、hdf_audio_control。开发板dev目录下驱动服务节点如下 # ls -l hdf_audio* crw-rw---- 1 system system 247, 6 1970-01-01 00:00 hdf_audio_capture // 音频数据录音流服务。 crw-rw---- 1 root root 247, 4 1970-01-01 00:00 hdf_audio_codec_primary_dev0 // 音频声卡设备0名称。 crw-rw---- 1 root root 247, 4 1970-01-01 00:00 hdf_audio_codec_primary_dev11 // 音频声卡设备1名称。 crw-rw---- 1 system system 247, 5 1970-01-01 00:00 hdf_audio_control // 音频控制流服务。 crw-rw---- 1 system system 247, 7 1970-01-01 00:00 hdf_audio_render // 音频数据播放流务。 音频声卡设备包括的驱动服务 hdf_audio_codec_primary_dev0 dma_service_0 : dma服务dai_service : CPU dai服务codec_service_0 : codec服务可以是smartPAdsp_service_0 : dsp 服务可选项 hdf_audio_codec_primary_dev11 dma_service_0 : dma服务dai_service : CPU dai服务codec_service_1 : codec服务可以是smartPAdsp_service_0 : dsp服务可选项 启动流程 系统启动时Audio模块的Platform、Codec、Dsp、Dai各个驱动首先被加载各驱动从各自私有配置文件中获取配置信息并将获取的配置信息保存到各驱动的Data数据结构中。 各驱动模块调用ADM注册接口将自己添加到各驱动模块的链表中。 ADM模块读取hdf_audio_driver_0和hdf_audio_driver_1配置信息加载各模块的具体设备。 ADM模块调用各模块的初始化函数对各模块设备进行初始化。 将初始化成功的音频设备添加到cardManager链表。 播放流程 播放音频时Interface Lib层通过播放流服务下发Render Open指令Audio Stream Dispatch服务收到指令后分别调用各模块的函数接口对指令进行下发。 Interface Lib层通过控制服务下发通路选择指令Control Dispatch控制服务收到指令后调用Dai模块接口设置通路。 Interface Lib层通过播放流服务下发硬件参数Audio Stream Dispatch服务收到参数后分别调用各模块参数设置接口对硬件参数进行设置。 Interface Lib层通过播放流服务下发播放启动指令Audio Stream Dispatch服务收到指令后分别调用各模块启动接口对各模块进行启动设置。 Interface Lib层通过播放流服务下发音频数据Audio Stream Dispatch服务收到数据后调用Platform AudioPcmWrite接口将音频数据传给Dma。 Interface Lib层通过播放流服务下发播放停止指令Audio Stream Dispatch服务收到指令后分别调用各模块停止接口对各模块进行停止设置。 Interface Lib层通过播放流服务下发Render Close指令Audio Stream Dispatch服务收到指令后调用Platform AudioRenderClose对已申请资源进行释放。 控制流程 设置音量首先Interface Lib层通过控制服务下发获取音量范围指令Control Dispatch控制服务收到指令后进行解析并调用Codec模块Get函数获取可设置音量的范围。Interface Lib层通过控制服务下发设置音量指令Control Dispatch控制服务收到指令后进行解析并调用Codec模块Set函数设置音量。 Audio驱动公共函数介绍 函数名功能CodecDeviceReadRegcodec寄存器读函数CodecDeviceWriteRegcodec寄存器写函数CodecDaiRegI2cReadcodec dai通过I2C接口读寄存器函数CodecDaiRegI2cWritecodec dai通过I2C接口写寄存器函数CodecDeviceRegI2cReadcodec通过I2C接口读寄存器函数CodecDeviceRegI2cWritecodec通过I2C接口写寄存器函数CodecDeviceInitRegConfigcodec初始化函数CodecDaiDeviceStartupRegConfigcodec启动函数CodecSetCtlFunccodec设置set和get接口实现函数CodecSetConfigInfoOfControlscodec设置控制功能函数接口和寄存器信息的函数CodecGetConfigInfocodec获取HCS配置信息函数CodecGetDaiNamecodec获取HCS配置dai名称函数CodecGetServiceNamecodec获取HCS配置服务名称函数DaiDeviceReadRegdai读寄存器函数DaiDeviceWriteRegdai写寄存器函数DaiSetConfigInfoOfControlsdai设置控制功能函数接口和寄存器信息的函数DaiGetConfigInfodai获取HCS配置信息函数 Audio驱动开发步骤 已有平台开发 ADM适配已有平台Hi3516DV300Codec或Smart PA的驱动开发流程 根据芯片说明将相关寄存器信息配置到Codec或Smart PA的私有HCS中。 如果新添加Codec或Smart PA和已适配Codec或Smart PA的工作流程相同则不需要实现Codec或Smart PA的操作函数集和配置编译文件。 进行编译调试验证。 新平台开发 ADM适配新平台Audio驱动开发流程 Audio驱动需要将Audio相关的Codec可选、Dai、DMA、DSP可选、Smart PA可选驱动进行适配。 根据芯片说明将各模块驱动的寄存器信息配置到各模块的私有配置文件中。 实现各模块的操作函数集。 修改配置Audio模块编译文件。 进行编译调试验证。 Audio驱动开发实例 代码路径device/board/hisilicon/hispark_taurus/audio_drivers 下面以Hi3516DV300为例介绍Audio的Codec驱动、Dai驱动、Platform驱动开发步骤。 Codec驱动开发实例 代码路径device/board/hisilicon/hispark_taurus/audio_drivers/codec/hi3516 codec驱动开发主要包含如下几个重要步骤 定义填充一个具体的codec。实现codec回调函数。注册绑定到HDF框架。配置HCS和Makefile。 Codec数据结构填充 Codec模块需要填充如下3个结构体 g_codecDatacodec设备的操作函数集和私有数据集。 g_codecDaiDeviceOpscodecDai的操作函数集包括启动传输和参数配置等函数接口。 g_codecDaiDatacodec的数字音频接口的操作函数集和私有数据集。 struct CodecData g_codecData {.Init CodecDeviceInit, // codec设备初始化适配新平台需重新实现.Read AudioDeviceReadReg, // 读寄存器现有框架已实现可使用.Write AudioDeviceWriteReg, // 写寄存器现有框架已实现可使用 };struct AudioDaiOps g_codecDaiDeviceOps {.Startup CodecDaiStartup, // 启动传输适配新平台需重新实现.HwParams CodecDaiHwParams, // 参数配置适配新平台需重新实现 };struct DaiData g_codecDaiData {.DaiInit CodecDaiDeviceInit, // codecdai设备初始化适配新平台需重新实现.ops g_codecDaiDeviceOps, // codecdai操作函数 }; codecDevice和codecDai设备初始化 CodecDeviceInit将完成AIAO的设置、寄存器默认值初始化、g_audioControls插入到controls链、电源管理初始化、通路选择设置等。 int32_t CodecDeviceInit(struct AudioCard *audioCard, struct CodecDevice *codec) {.../* hi3516平台AIAO的Set和Get注册 */CodecSetCtlFunc(codec-devData, AudioCodecAiaoGetCtrlOps, AudioCodecAiaoSetCtrlOps).../* hi3516平台codec寄存器IoRemap */CodecHalSysInit();.../* hi3516平台codec寄存器默认值初始化 */CodecRegDefaultInit(codec-devData-regCfgGroup);.../* hi3516平台g_audioControls挂到Control链表上 */AudioAddControls(audioCard, codec-devData-controls, codec-devData-numControls);.../* hi3516平台codec加载到sapm */AudioSapmNewComponents(audioCard, codec-devData-sapmComponents, codec-devData-numSapmComponent);.../* hi3516平台codec加挂到通路选择链表上 */AudioSapmAddRoutes(audioCard, g_audioRoutes, HDF_ARRAY_SIZE(g_audioRoutes);...AudioSapmNewControls(audioCard);.../* hi3516平台codec电源管理 */AudioSapmSleep(audioCard);...return HDF_SUCCESS; } CodecDaiDeviceInit将完成codecDai侧初始化hi3516此处未涉及接口保留 int32_t CodecDaiDeviceInit(struct AudioCard *card, const struct DaiDevice *device){...AUDIO_DRIVER_LOG_DEBUG(codec dai device name: %s\n, device-devDaiName);(void)card;return HDF_SUCCESS; } Codec操作函数集实现 codec模块当前封装了OSAL读写寄存器的Read、Write函数。 如新增平台无法使用OSAL的Read、Write函数来操作寄存器则此Read、Write函数接口需自行实现。 int32_t AudioDeviceReadReg(unsigned long virtualAddress, uint32_t reg, uint32_t *val) {...*val OSAL_READL((void *)((uintptr_t)(virtualAddress reg)));return HDF_SUCCESS; }int32_t AudioDeviceWriteReg(unsigned long virtualAddress, uint32_t reg, uint32_t value) {OSAL_WRITEL(value, (void *)((uintptr_t)(virtualAddress reg)));return HDF_SUCCESS; } CodecDaiStartup为启动时的一些设置。 int32_t CodecDaiStartup(const struct AudioCard *card, const struct DaiDevice *device) {int32_t ret;...(void)card;ret CodecSetAdcTuneEnable(device-devData-regCfgGroup);...return HDF_SUCCESS; } CodecDaiHwParams为参数配置包括采样率、位宽等。 int32_t CodecDaiHwParams(const struct AudioCard *card, const struct AudioPcmHwParams *param) {unsigned int bitWidth;struct CodecDaiParamsVal codecDaiParamsVal;...int ret AudioFormatToBitWidth(param-format, bitWidth);...codecDaiParamsVal.frequencyVal param-rate;codecDaiParamsVal.formatVal bitWidth;ret CodecDaiParamsUpdate(card-rtd-codecDai-devData-regCfgGroup, codecDaiParamsVal);...return HDF_SUCCESS; } Codec注册绑定到HDF 此处依赖HDF框架的驱动实现方式具体流程可参考HDF驱动框架指导。 填充g_codecDriverEntry结构体moduleName与device_info.hcs中的moduleName匹配实现Bind、Init、Release函数指针。 device/board/hisilicon/hispark_taurus/audio_drivers/codec/hi3516/src/hi3516_codec_adapter.c struct HdfDriverEntry g_codecDriverEntry {.moduleVersion 1,.moduleName CODEC_HI3516,.Bind CodecDriverBind,.Init CodecDriverInit,.Release CodecDriverRelease, }; HDF_INIT(g_codecDriverEntry); CodecDriverBind将HDF中device绑定到codec将codec service注册到HDF框架。 static int32_t CodecDriverBind(struct HdfDeviceObject *device) {struct CodecHost *codecHost (struct CodecHost *)OsalMemCalloc(sizeof(*codecHost));...codecHost-device device;device-service codecHost-service;return HDF_SUCCESS; } CodecDriverInit获取codecService名字和私有寄存器配置并通过AudioRegisterCodec插入到链表中。 static int32_t CodecDriverInit(struct HdfDeviceObject *device) {...CodecGetConfigInfo(device, g_codecData);CodecSetConfigInfo(g_codecData, g_codecDaiData);CodecGetServiceName(device, g_codecData.drvCodecName);CodecGetDaiName(device, g_codecDaiData.drvDaiName);AudioRegisterCodec(device, g_codecData, g_codecDaiData);...return HDF_SUCCESS; } CodecDriverRelease释放驱动资源。 static void CodecDriverRelease(struct HdfDeviceObject *device) {codecHost (struct CodecHost *)device-service;OsalMemFree(codecHost); } HCS配置流程 hcs中配置驱动节点、加载顺序、服务名称等。hcs语法可参考HDF框架的配置管理。 标准系统配置文件路径 vendor/hisilicon/hispark_taurus_standard/hdf_config/khdf/ 小型系统配置文件路径 vendor/hisilicon/hispark_taurus/hdf_config/ device_info.hcs中配置Codec设备信息 添加Codec节点配置。修改如下配置中的moduleName该名字会与HdfDriverEntry结构体中moduleName进行匹配一般情况需体现出硬件平台名称。例moduleName CODEC_HI3516。 代码片段如下 audio :: host {device_codec :: device {device0 :: deviceNode {policy 1; // codec模块只对内核提供服务priority 50; // codec模块需在HDF_AUDIO模块之前加载preload 0;permission 0666;moduleName CODEC_HI3516; // 名字会与HdfDriverEntry结构体中moduleName进行匹配serviceName codec_service_0; // 对外提供的服务名称deviceMatchAttr hdf_codec_driver; // 私有配置属性名称通过此名称匹配对应的私有数据包含寄存器配置}} audio_config.hcs中配置私有依赖 配置audio_card设备依赖的Codec、Platform、Dai、Dsp之间的依赖关系。 代码片段如下 root {platform {...controller_0x120c1001 :: card_controller {// 配置私有数据属性名称与device_info.hcs中的deviceMatchAttr对应match_attr hdf_audio_driver_1; serviceName hdf_audio_codec_primary_dev11; // 对外提供的服务名称codecName codec_service_1; // codec服务名称platformName dma_service_0; // dma服务cpuDaiName dai_service; // CPU dai服务codecDaiName tfa9879_codec_dai; // codec dai服务dspName dsp_service_0; // dsp服务名称dspDaiName dsp_dai; // dsp dai}} } codec_config.hcs中配置私有寄存器 与配置在device_info.hcs中codec的deviceMatchAttr匹配目前配置中包含寄存器配置。 绑定控制功能配置主要是将控制功能及其寄存器参数按统一的结构规范配置在HCS文件中并获取与解析后增加到控制链表中。 regConfig寄存器与控制功能配置组名称。 ctrlParamsSeqConfig控制功能寄存器配置组名称其中item与controlsConfig组中的item位置顺序一一对应表示某一功能对应的寄存器配置。 daiStartupSeqConfigDai启动配置配置组名称。 daiParamsSeqConfig播放参数配置组名称。 resetSeqConfig重置过程寄存器配置组名称。 initSeqConfig初始化过程寄存器配置组名称。 controlsConfig控制功能配置组名称其中array index具体业务场景和iface与HAL保持一致为固定的值。 sapmConfig电源管理控制功能配置组名称其中array index具体业务场景和iface与HAL保持一致为固定的值。 ctrlSapmParamsSeqConfig电源管理控制功能寄存器配置组名称。 sapmComponent电源管理组件配置组名称。 array index controlsConfig配置组的array index是audio_codec_base.c文件中g_audioCodecControlsList数组的元素标号。 sapmConfig配置组的array index是audio_codec_base.c文件中g_audioSapmCfgNameList数组的元素标号。 sapmComponent配置组的compNameIndex是audio_codec_base.c文件中g_audioSapmCompNameList数组元素标号。 iface虚拟混合器设备配置为2。 root {platform {template codec_controller {match_attr ;serviceName ;codecDaiName ;}controller_0x120c1030 :: codec_controller {match_attr hdf_codec_driver;serviceName codec_service_0;codecDaiName codec_dai;/* hi3516寄存器基地址 */idInfo {chipName hi3516; // codec名字chipIdRegister 0x113c0000; // codec基地址chipIdSize 0x1000; // codec地址偏移}/* 寄存器配置包含各种寄存器配置信息 */regConfig { /* reg: register addressrreg: register addressshift: shift bitsrshift: rshift bitsmin: min valuemax: max valuemask: mask of valueinvert: enum InvertVal 0-uninvert 1-invertvalue: value*//* reg, value */initSeqConfig [0x14, 0x04000002,0x18, 0xFD200004,0x1C, 0x00180018,0x20, 0x83830028,0x24, 0x00005C5C,0x28, 0x00130000,0x30, 0xFF035A00,0x34, 0x08000001,0x38, 0x06062424,0x3C, 0x1E1EC001,0x14, 0x04000002]; /* control function config array index, iface, mixer/mux, enable, */0, 2, 0, 0,1, 2, 0, 1,2, 2, 0, 1,3, 2, 0, 1,4, 2, 0, 1,5, 2, 0, 1,8, 2, 0, 0,9, 2, 0, 0,]; /* control function register config reg, rreg, shift, rshift, min, max, mask, invert, value */ctrlParamsSeqConfig [0x3c, 0x3c, 24, 24, 0x0, 0x57, 0x7F, 1, 0, // Main Capture Volume0x38, 0x38, 31, 31, 0x0, 0x1, 0x1, 0, 0, // Playback Mute0x3c, 0x3c, 31, 31, 0x0, 0x1, 0x1, 0, 0, // Capture Mute0x20, 0x20, 16, 16, 0x0, 0xF, 0x1F, 0, 0, // Mic Left Gain0x20, 0x20, 24, 24, 0x0, 0xF, 0x1F, 0, 0, // Mic Right Gain0x2000, 0x2000, 16, 16, 0x0, 0x7, 0x7, 0, 0, // Render Channel Mode0x1000, 0x1000, 16, 16, 0x0, 0x7, 0x7, 0, 0 // Capture Channel Mode];/* 上层下发参数后写入音频相关信息的寄存器 reg, rreg, shift, rshift, min, max, mask, invert, value */daiParamsSeqConfig [ 0x30, 0x30, 13, 13, 0x0, 0x1F, 0x1F, 0, 0x0, // i2s_frequency0x1C, 0x1C, 6, 6, 0x0, 0x3, 0x3, 0, 0x0, // adc_mode_sel0x30, 0x30, 22, 22, 0x0, 0x3, 0x3, 0, 0x0, // i2s_datawith];/* 电源管理功能寄存器配置 reg, rreg, shift, rshift, min, max, mask, invert, value */ctrlSapmParamsSeqConfig [ 0x20, 0x20, 23, 23, 0x0, 0x1, 0x1, 0, 0, // LPGA MIC 0 -- connect MIC0x20, 0x20, 31, 31, 0x0, 0x1, 0x1, 0, 0, // RPGA MIC 0 -- connect MIC0x30, 0x30, 27, 27, 0x0, 0x1, 0x1, 0, 0, // dacl to dacr mixer0x30, 0x30, 26, 26, 0x0, 0x1, 0x1, 0, 0 // dacr to dacl mixer];/*电源管理组件配置sapmType, compNameIndex, reg, mask, shift, invert, kcontrolNews, kcontrolsNumreg 0xFFFF: component has no sapm register bit*/sapmComponent [ 10, 0, 0x20, 0x1, 15, 1, 0, 0, // ADCL10, 1, 0x20, 0x1, 14, 1, 0, 0, // ADCR11, 2, 0x14, 0x1, 11, 1, 0, 0, // DACL11, 3, 0x14, 0x1, 12, 1, 0, 0, // DACR17, 4, 0x20, 0x1, 13, 1, 1, 1, // LPGA17, 5, 0x20, 0x1, 12, 1, 2, 1, // RPGA15, 6, 0xFFFF, 0xFFFF, 0, 0, 0, 0, // SPKL15, 7, 0xFFFF, 0xFFFF, 0, 0, 0, 0, // SPKR17, 52, 0xFFFF, 0xFFFF, 0, 0, 3, 1, // SPKL PGA17, 53, 0xFFFF, 0xFFFF, 0, 0, 4, 1, // SPKR PGA13, 40, 0xFFFF, 0xFFFF, 0, 0, 0, 0, // MIC113, 41, 0xFFFF, 0xFFFF, 0, 0, 0, 0 // MIC2];/* 电源管理功能配置 array index, iface, mixer/mux, enable*/ sapmConfig [0, 2, 0, 1,1, 2, 0, 1,2, 2, 0, 1,3, 2, 0, 1];}}} } 在C代码中读取HCS配置文件来寄存器配置。 static int32_t CodecDriverInit(struct HdfDeviceObject *device) {...CodecGetConfigInfo(device, g_codecData) ;CodecSetConfigInfo(g_codecData, g_codecDaiData);...return HDF_SUCCESS; } Codec注册时入参device中已有controller_0x120c1030的节点信息只需要解析其中的节点就可以获取配置信息。 int32_t CodecGetConfigInfo(const struct HdfDeviceObject *device, struct CodecData *codecData) {codecData-regConfig (struct AudioRegCfgData *)OsalMemCalloc(sizeof(*(codecData-regConfig)));CodecGetRegConfig(device, codecData-regConfig);return HDF_SUCCESS; } 配置信息获取配置节点。 int32_t CodecGetRegConfig(const struct HdfDeviceObject *device, struct AudioRegCfgData *configData) {...drsOps DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);...idNode drsOps-GetChildNode(root, idInfo);ParseAudioAttr(drsOps, idNode, configData-audioIdInfo);regCfgNode drsOps-GetChildNode(root, regConfig);...DEV_RES_NODE_FOR_EACH_ATTR(regCfgNode, regAttr) {...return HDF_SUCCESS; } regConfig节点中子项的配置信息获取并使用。在框架进行配置文件解析后可直接替换代码中的寄存器信息。 int32_t CodecDeviceInit(struct AudioCard *audioCard, struct CodecDevice *codec) { ...if (CodecRegDefaultInit(codec-devData-regCfgGroup) ! HDF_SUCCESS) {AUDIO_DRIVER_LOG_ERR(CodecRegDefaultInit failed.);return HDF_FAILURE;} ...return HDF_SUCCESS; } SmartPA驱动开发实例 代码路径device/board/hisilicon/hispark_taurus/audio_drivers/codec/tfa9879 SmartPA归属于codec驱动的一种其开发流程为 定义填充一个具体的codec。实现codec回调函数。注册绑定到HDF框架。配置HCS和Makefile。 codec数据结构填充 codec模块需要填充如下3个结构体 g_tfa9879Datacodec设备操作函数集其中包含HCS文件中的配置信息且定义与映射了codec设备的初始化、读写寄存器的方法函数。 g_tfa9879DaiDeviceOpscodec设备DAI的数据集其中定义与映射了codec设备DAI的操作集。 g_tfa9879DaiDatacodec设备DAI的数据集其中定义与映射了codec设备的数据访问接口的驱动名、初始化和操作集。 struct CodecData g_tfa9879Data {.Init Tfa9879DeviceInit,.Read CodecDeviceRegI2cRead,.Write CodecDeviceRegI2cWrite, };struct AudioDaiOps g_tfa9879DaiDeviceOps {.Startup Tfa9879DaiStartup,.HwParams Tfa9879DaiHwParams, };struct DaiData g_tfa9879DaiData {.drvDaiName tfa9879_codec_dai,.DaiInit Tfa9879DaiDeviceInit,.ops g_tfa9879DaiDeviceOps,.Read CodecDaiRegI2cRead,.Write CodecDaiRegI2cWrite, }; codecDevice和codecDai设备初始化 设备初始化入口函数为Tfa9879DeviceInit其中主要包括设置SmartPA I2C设备地址获取配置数据、初始化含重置设备寄存器和绑定控制功能配置到控制链表中当前Demo实现中也包括了Hi3516DV300设备的相关寄存器初始化如初始化GPIO引脚等。 int32_t Tfa9879DeviceInit(struct AudioCard *audioCard, const struct CodecDevice *device) {int32_t ret;...// 初始化GPIO引脚ret Hi35xxGpioPinInit();...// 配置I2C参数g_transferParam.i2cBusNumber TFA9879_I2C_BUS_NUMBER;g_transferParam.i2cDevAddr TFA9879_I2C_DEV_ADDR;g_transferParam.i2cRegDataLen TFA9879_I2C_REG_DATA_LEN;device-devData-privateParam g_transferParam;...// 初始化设备寄存器ret CodecDeviceInitRegConfig(device);...// 绑定功能控制配置if (AudioAddControls(audioCard, device-devData-controls, device-devData-numControls) !HDF_SUCCESS) {AUDIO_DRIVER_LOG_ERR(add controls failed.);return HDF_FAILURE;}... } I2C读写寄存器公用函数 int32_t CodecDeviceRegI2cRead(const struct CodecDevice *codec, uint32_t reg, uint32_t *val) {int32_t ret;struct AudioAddrConfig regAttr;struct I2cTransferParam *i2cTransferParam NULL;...i2cTransferParam (struct I2cTransferParam *)codec-devData-privateParam;...regAttr.addr (uint8_t)reg;regAttr.value 0;ret CodecI2cTransfer(i2cTransferParam, regAttr, I2C_FLAG_READ);...*val regAttr.value;return HDF_SUCCESS; }int32_t CodecDeviceRegI2cWrite(const struct CodecDevice *codec, uint32_t reg, uint32_t value) {int32_t ret;struct AudioAddrConfig regAttr;struct I2cTransferParam *i2cTransferParam NULL;...i2cTransferParam (struct I2cTransferParam *)codec-devData-privateParam;...regAttr.addr (uint8_t)reg;regAttr.value (uint16_t)value;ret CodecI2cTransfer(i2cTransferParam, regAttr, 0);...return HDF_SUCCESS; }int32_t CodecDaiRegI2cRead(const struct DaiDevice *dai, uint32_t reg, uint32_t *value) {...ret CodecI2cTransfer(i2cTransferParam, regAttr, I2C_FLAG_READ);...return HDF_SUCCESS; }int32_t CodecDaiRegI2cWrite(const struct DaiDevice *dai, uint32_t reg, uint32_t value) {...ret CodecI2cTransfer(i2cTransferParam, regAttr, 0);...return HDF_SUCCESS; } Codec操作函数集实现 Tfa9879DaiStartup为启动时的一些设置代码片段如下 int32_t Tfa9879DaiStartup(const struct AudioCard *card, const struct DaiDevice *device) {int ret;(void)card;(void)device;// 设置SmartPA的启动的寄存器配置ret CodecDaiDeviceStartupRegConfig(device);...return HDF_SUCCESS; } Tfa9879DaiHwParams为下发播放参数接口函数代码片段如下 int32_t Tfa9879DaiHwParams(const struct AudioCard *card, const struct AudioPcmHwParams *param) {int32_t ret;uint16_t frequency, bitWidth;struct DaiParamsVal daiParamsVal;(void)card;...// 匹配采样率ret Tfa9879FrequencyParse(param-rate, frequency);...// 匹配位宽ret Tfa9879FormatParse(param-format, bitWidth);...daiParamsVal.frequencyVal frequency;daiParamsVal.formatVal bitWidth;daiParamsVal.channelVal param-channels; // 匹配声道ret Tfa9879DaiParamsUpdate(card-rtd-codecDai, daiParamsVal);...return HDF_SUCCESS; } Codec注册绑定到HDF 此处依赖HDF框架的驱动实现方式具体流程可参考HDF驱动框架。 填充g_tfa9879DriverEntry结构体moduleName与device_info.hcs中的moduleName匹配实现Bind、Init、Release函数指针。 device/board/hisilicon/hispark_taurus/audio_drivers/codec/tfa9879/src/tfa9879_accessory_adapter.c static int32_t Tfa9879DriverBind(struct HdfDeviceObject *device) {(void)device;AUDIO_DRIVER_LOG_INFO(success!);return HDF_SUCCESS; }static int32_t Tfa9879DriverInit(struct HdfDeviceObject *device) {int32_t ret;...// 获取HCS中的配置数据ret CodecGetConfigInfo(device, g_tfa9879Data);...// 设置codec控制相关的接口函数和寄存器信息ret CodecSetConfigInfoOfControls(g_tfa9879Data, g_tfa9879DaiData);...ret CodecGetServiceName(device, g_tfa9879Data.drvCodecName);...ret CodecGetDaiName(device, g_tfa9879DaiData.drvDaiName);...// 注册codec到声卡ret AudioRegisterCodec(device, g_tfa9879Data, g_tfa9879DaiData);....return HDF_SUCCESS; }/* HdfDriverEntry definitions */ struct HdfDriverEntry g_tfa9879DriverEntry {.moduleVersion 1,.moduleName CODEC_TFA9879,.Bind Tfa9879DriverBind,.Init Tfa9879DriverInit,.Release NULL, }; HDF_INIT(g_tfa9879DriverEntry); HCS配置流程 配置过程可参考Codec驱动开发实例HCS配置流程章节。 Platform驱动开发实例 代码路径device/board/hisilicon/hispark_taurus/audio_drivers/soc 在Audio驱动开发中platform为DMA驱动的适配。platform驱动开发主要包含如下几个重要步骤 定义填充一个具体的platform实现platform回调函数注册绑定到HDF框架配置HCS和Makefile Platform数据结构填充 Platform模块需要填充如下2个结构体 g_platformData platform设备私有配置其中包含platform设备的初始化和操作函数。 g_dmaDeviceOps Dma设备操作函数集包含了DMA一些通用接口的封装。 struct AudioDmaOps g_dmaDeviceOps {.DmaBufAlloc Hi3516DmaBufAlloc, // dma内存申请函数接口.DmaBufFree Hi3516DmaBufFree, // dma内存释放函数接口.DmaRequestChannel Hi3516DmaRequestChannel, // dma申请通道函数接口.DmaConfigChannel Hi3516DmaConfigChannel, // dma通道配置函数接口.DmaPrep Hi3516DmaPrep, // dma准备函数接口.DmaSubmit Hi3516DmaSubmit, // dma submit函数接口.DmaPending Hi3516DmaPending, // dma pending函数接口.DmaPause Hi3516DmaPause, // dma暂停、停止函数接口.DmaResume Hi3516DmaResume, // dma恢复函数接口.DmaPointer Hi3516DmaPointer, // dma获取当前播放或录音位置函数接口 };struct PlatformData g_platformData {.PlatformInit AudioDmaDeviceInit, // dma设备初始化接口.ops g_dmaDeviceOps, }; dmaDevice设备初始化 设备初始化入口函数为AudioDmaDeviceInit其中主要包括设置3516平台特有的AIAO初始化等。 int32_t AudioDmaDeviceInit(const struct AudioCard *card, const struct PlatformDevice *platformDevice) { ... AiaoHalSysInit();/* PIN MUX */AiaoSysPinMux();/* CLK reset */AiaoClockReset();/* aiao init */AiaoDeviceInit(chnId); ...return HDF_SUCCESS; } DMA操作函数集实现 Dma设备操作函数集包含了DMA通用接口的封装。如通用接口不能满足开发要求可自行实现新的DMA回调函数。 int32_t AudioDmaDeviceInit(const struct AudioCard *card, const struct PlatformDevice *platform); int32_t Hi3516DmaBufAlloc(struct PlatformData *data, const enum AudioStreamType streamType); int32_t Hi3516DmaBufFree(struct PlatformData *data, const enum AudioStreamType streamType); int32_t Hi3516DmaRequestChannel(const struct PlatformData *data, const enum AudioStreamType streamType); int32_t Hi3516DmaConfigChannel(const struct PlatformData *data, const enum AudioStreamType streamType); int32_t Hi3516DmaPrep(const struct PlatformData *data, const enum AudioStreamType streamType); int32_t Hi3516DmaSubmit(const struct PlatformData *data, const enum AudioStreamType streamType); int32_t Hi3516DmaPending(struct PlatformData *data, const enum AudioStreamType streamType); int32_t Hi3516DmaPause(struct PlatformData *data, const enum AudioStreamType streamType); int32_t Hi3516DmaResume(const struct PlatformData *data, const enum AudioStreamType streamType); int32_t Hi3516DmaPointer(struct PlatformData *data, const enum AudioStreamType streamType, uint32_t *pointer); Platform注册绑定到HDF 此处依赖HDF框架的驱动实现方式具体流程可参考HDF驱动框架。 填充g_platformDriverEntry结构体moduleName与device_info.hcs中的moduleName匹配实现Bind、Init、Release函数指针 device/board/hisilicon/hispark_taurus/audio_drivers/soc/src/hi3516_dma_adapter.c static int32_t Hi3516DmaDriverInit(struct HdfDeviceObject *device) { ...OsalMutexInit(g_platformData.renderBufInfo.buffMutex);OsalMutexInit(g_platformData.captureBufInfo.buffMutex);g_platformData.platformInitFlag false;ret AudioSocRegisterPlatform(device, g_platformData); ...return HDF_SUCCESS; }static void Hi3516DmaDriverRelease(struct HdfDeviceObject *device) {struct PlatformHost *platformHost NULL; ...platformHost (struct PlatformHost *)device-service; ...OsalMutexDestroy(g_platformData.renderBufInfo.buffMutex);OsalMutexDestroy(g_platformData.captureBufInfo.buffMutex);OsalMemFree(platformHost); }/* HdfDriverEntry definitions */ struct HdfDriverEntry g_platformDriverEntry {.moduleVersion 1,.moduleName DMA_HI3516,.Bind Hi3516DmaDriverBind,.Init Hi3516DmaDriverInit,.Release Hi3516DmaDriverRelease, }; HDF_INIT(g_platformDriverEntry); HCS配置流程 配置过程可参考Codec驱动开发实例HCS配置流程章节。 Dai驱动开发实例 代码路径device/board/hisilicon/hispark_taurus/audio_drivers/soc Dai驱动开发主要包含如下几个重要步骤 定义填充一个具体的dai实现dai回调函数注册绑定到HDF框架配置HCS和Makefile Dai数据结构填充 Dai模块需要填充如下2个结构体 g_daiDatadai设备私有配置其中包含dai设备的初始化、读写寄存器、操作函数。 g_daiDeviceOpsdai设备操作函数集包含了dai的参数设置、触发、启动。 struct AudioDaiOps g_daiDeviceOps {.HwParams DaiHwParams,.Trigger DaiTrigger,.Startup DaiStartup, };struct DaiData g_daiData {.DaiInit DaiDeviceInit,.Read AudioDeviceReadReg,.Write AudioDeviceWriteReg,.ops g_daiDeviceOps, }; daiDevice设备初始化 设备初始化入口函数为DaiDeviceInit其中主要包括设置dai的配置信息初始化添加到Controls等。 int32_t DaiDeviceInit(struct AudioCard *audioCard, const struct DaiDevice *dai) { ...struct DaiData *data dai-devData;struct AudioRegCfgData *regConfig dai-devData-regConfig; ...g_regCodecBase OsalIoRemap(CODEC_REG_BASE, CODEC_MAX_REG_SIZE); ...data-regVirtualAddr (uintptr_t)g_regCodecBase;DaiSetConfigInfo(data);AudioAddControls(audioCard, data-controls, data-numControls);I2c6PinInit(); ...data-daiInitFlag true;return HDF_SUCCESS; } Dai操作函数集实现 AudioDeviceReadReg和AudioDeviceWriteReg在3516平台均未使用作为接口预留。 DaiHwParams中主要完成一些pcm流信息的设置。 int32_t DaiHwParams(const struct AudioCard *card, const struct AudioPcmHwParams *param) {uint32_t bitWidth;struct DaiDevice *device card-rtd-cpuDai; ...DaiCheckSampleRate(param-rate);struct DaiData *data DaiDataFromCard(card);data-pcmInfo.channels param-channels; ...AudioFormatToBitWidth(param-format, bitWidth); ...data-pcmInfo.bitWidth bitWidth;data-pcmInfo.rate param-rate;data-pcmInfo.streamType param-streamType;data-regVirtualAddr (uintptr_t)g_regDaiBase; ...DaiParamsUpdate(device);data-regVirtualAddr (uintptr_t)g_regCodecBase;return HDF_SUCCESS; } DaiTrigger在3516平台也未使用作为接口预留。 DaiStartup为dai的启动函数主要包括更新初始化寄存器配置、配置I2S等。 int32_t DaiStartup(const struct AudioCard *card, const struct DaiDevice *device) {struct AudioMixerControl *regCfgItem NULL; ...regCfgItem device-devData-regConfig-audioRegParams[AUDIO_DAI_STARTUP_PATAM_GROUP]-regCfgItem;itemNum device-devData-regConfig-audioRegParams[AUDIO_DAI_STARTUP_PATAM_GROUP]-itemNum;device-devData-regVirtualAddr (uintptr_t)g_regDaiBase;for (int i 0; i itemNum; i) {int ret AudioUpdateDaiRegBits(device, regCfgItem[i], regCfgItem[i].value);if (ret ! HDF_SUCCESS) {AUDIO_DRIVER_LOG_ERR(set frequency fail.);return HDF_FAILURE;}}device-devData-regVirtualAddr (uintptr_t)g_regCodecBase;if (I2sPinInit() ! HDF_SUCCESS) {AUDIO_DRIVER_LOG_ERR(I2sPinInit fail.);}return HDF_SUCCESS; } Dai注册绑定到HDF 此处依赖HDF框架的驱动实现方式具体流程可参考HDF驱动框架。 填充g_daiDriverEntry结构体moduleName与device_info.hcs中的moduleName匹配实现Bind、Init、Release函数指针 device/board/hisilicon/hispark_taurus/audio_drivers/soc/src/hi3516_dai_adapter.c static int32_t DaiDriverBind(struct HdfDeviceObject *device) { ...struct DaiHost *daiHost (struct DaiHost *)OsalMemCalloc(sizeof(*daiHost)); ...daiHost-device device;device-service daiHost-service;g_daiData.daiInitFlag false; ...return HDF_SUCCESS; }static int32_t DaiDriverInit(struct HdfDeviceObject *device) { ...DaiGetConfigInfo(device, g_daiData);DaiGetServiceName(device); ...OsalMutexInit(g_daiData.mutex);AudioSocRegisterDai(device, g_daiData); ...return HDF_SUCCESS; }static void DaiDriverRelease(struct HdfDeviceObject *device) { ...OsalMutexDestroy(g_daiData.mutex); ...struct DaiHost *daiHost (struct DaiHost *)device-service; ...OsalMemFree(daiHost); }/* HdfDriverEntry definitions */ struct HdfDriverEntry g_daiDriverEntry {.moduleVersion 1,.moduleName DAI_HI3516,.Bind DaiDriverBind,.Init DaiDriverInit,.Release DaiDriverRelease, }; HDF_INIT(g_daiDriverEntry); HCS配置流程 配置过程可参考Codec驱动开发实例HCS配置流程章节。 Makefile中添加编译配置 添加新增文件到对应的Makefile中将其编译链接到内核镜像。 标准系统linuxdevice/board/hisilicon/hispark_taurus/audio_drivers/Makefile obj-$(CONFIG_DRIVERS_HDF_AUDIO_HI3516CODEC) \codec/tfa9879/src/tfa9879_codec_adapter.o \codec/tfa9879/src/tfa9879_codec_ops.o \codec/hi3516/src/hi3516_codec_adapter.o \codec/hi3516/src/hi3516_codec_impl.o \codec/hi3516/src/hi3516_codec_ops.o \dsp/src/dsp_adapter.o \dsp/src/dsp_ops.o \soc/src/hi3516_dai_adapter.o \soc/src/hi3516_dai_ops.o \soc/src/hi3516_aiao_impl.o \soc/src/hi3516_dma_ops.o \soc/src/hi3516_dma_adapter.o 小型系统liteOSdrivers/hdf_core/adapter/khdf/liteos/model/audio/Makefile LOCAL_SRCS \$(KHDF_AUDIO_HI3516DV300_DIR)/codec/tfa9879/src/tfa9879_codec_adapter.c \\$(KHDF_AUDIO_HI3516DV300_DIR)/codec/tfa9879/src/tfa9879_codec_ops.c \$(KHDF_AUDIO_HI3516DV300_DIR)/codec/hi3516/src/hi3516_codec_adapter.c \\$(KHDF_AUDIO_HI3516DV300_DIR)/codec/hi3516/src/hi3516_codec_impl.c \$(KHDF_AUDIO_HI3516DV300_DIR)/codec/hi3516/src/hi3516_codec_ops.c \\$(KHDF_AUDIO_HI3516DV300_DIR)/dsp/src/dsp_adapter.c \$(KHDF_AUDIO_HI3516DV300_DIR)/dsp/src/dsp_ops.c \\$(KHDF_AUDIO_HI3516DV300_DIR)/soc/src/hi3516_dai_adapter.c \$(KHDF_AUDIO_HI3516DV300_DIR)/soc/src/hi3516_dai_ops.c \\$(KHDF_AUDIO_HI3516DV300_DIR)/soc/src/hi3516_aiao_impl.c \$(KHDF_AUDIO_HI3516DV300_DIR)/soc/src/hi3516_dma_ops.c \\$(KHDF_AUDIO_HI3516DV300_DIR)/soc/src/hi3516_dma_adapter.c 源码结构与目录 实现驱动接口头文件中的函数。以Hi3516为例目录架构如下 驱动实现示例代码路径device/board/hisilicon/hispark_taurus/audio_drivers/ . ├── codec │ ├── hi3516 │ │ ├── include │ │ │ ├── hi3516_codec_impl.h │ │ │ └── hi3516_codec_ops.h │ │ └── src │ │ ├── hi3516_codec_adapter.c // codec驱动入口 │ │ ├── hi3516_codec_impl.c // codec硬件相关操作实现 │ │ └── hi3516_codec_ops.c // codec驱动函数接口实现 │ └── tfa9879 │ ├── include │ │ └── tfa9879_codec_ops.h │ └── src │ ├── tfa9879_codec_adapter.c │ └── tfa9879_codec_ops.c ├── dsp │ ├── include │ │ └── dsp_ops.h │ └── src │ ├── dsp_adapter.c // dsp驱动入口 │ └── dsp_ops.c ├── LICENSE ├── Makefile └── soc├── include│ ├── hi3516_aiao_impl.h│ ├── hi3516_dai_ops.h│ └── hi3516_dma_ops.h└── src├── hi3516_aiao_impl.c├── hi3516_dai_adapter.c // dai驱动入口├── hi3516_dai_ops.c├── hi3516_dma_adapter.c // dma驱动入口└── hi3516_dma_ops.c hcs文件与目录 标准系统 vendor/hisilicon/hispark_taurus_standard/ └── hdf_config└── khdf├── audio│ ├── audio_config.hcs│ ├── codec_config.hcs│ ├── dai_config.hcs│ ├── dma_config.hcs│ └── dsp_config.hcs├── device_info│ └── device_info.hcs└── hdf.hcs小型系统 vendor/hisilicon/hispark_taurus/ ├── config.json └── hdf_config├── audio│ ├── audio_config.hcs│ ├── codec_config.hcs│ ├── dai_config.hcs│ ├── dma_config.hcs│ └── dsp_config.hcs├── device_info│ └── device_info.hcs└── hdf.hcs 使用HAL的开发步骤与实例 HALHardware Abstraction Layer的核心功能说明如下: 提供Audio HDI接口供北向音频服务调用实现音频服务的基本功能。作为标准南向接口保证南向OEM产商实现HDI-adapter的规范性保证生态良性演进。 代码路径drivers_interface/audio/v1_0 HAL模块使用步骤 使用入口函数IAudioManagerGet()获取函数方法。 使用GetAllAdapters()获取所支持的声卡信息调用LoadAdapter()加载对应的声卡。 创建播放类CreateRender()或者录音类下发音频文件音频相关属性。 调用创建好的播放类中挂载的方法例如开始播放时调用render-Start()音频数据循环下发时调用render-RenderFrame()。 播放过程中可调用其他控制命令对播放业务进行控制操作例如调节音量render-SetVolume()、暂停render-Pause()、恢复render-Resume()等。 播放业务完成后下发停止命令render-Stop()、销毁播放类adapter-DestroyRender()、卸载声卡audioManagerIns-UnloadAdapter()。 HAL使用示例 #include string.h #include stdio.h #include pthread.h #include v1_0/audio_types.h #include v1_0/iaudio_manager.hstruct IAudioRender *g_render NULL; struct IAudioAdapter *g_adapter NULL; struct AudioDeviceDescriptor g_devDesc; struct AudioSampleAttributes g_attrs; struct AudioHeadInfo g_wavHeadInfo; bool g_isDirect false; //IPC Loading uint32_t g_renderId 0;static int32_t FrameStart(const struct StrPara *param) { .../* 初始化参数 */char *frame param-frame;int32_t bufferSize param-bufferSize;size_t remainingDataSize g_wavHeadInfo.riffSize;/* 循环进行下发音频数据 */do {uint64_t replyBytes 0;size_t readSize (remainingDataSize bufferSize) ? (size_t)bufferSize : remainingDataSize;numRead fread(frame, 1, readSize, g_file);if (numRead 0) {int32_t ret render-RenderFrame(render, (int8_t *)frame, numRead, replyBytes);if (ret HDF_ERR_INVALID_OBJECT) {AUDIO_FUNC_LOGE(Render already stop!);break;}remainingDataSize - numRead;}/* 暂停等待函数 */while (g_waitSleep) {printf(music pause now.\n);pthread_cond_wait(g_functionCond, g_mutex);printf(music resume now.\n);}} while (!g_closeEnd numRead 0 remainingDataSize 0); ... }static void *hal_main() {int32_t adapterIndex 0;struct AudioPort *renderPort;/* 通过IAudioManagerGet()获取入口函数 */struct IAudioManager *audioManagerIns IAudioManagerGet(g_isDirect);if (audioManagerIns NULL) {AUDIO_FUNC_LOGE(Get Audio Manager Fail);return HDF_FAILURE;}/* 获取声卡列表 */struct AudioAdapterDescriptor *descs (struct AudioAdapterDescriptor *)OsalMemCalloc(sizeof(struct AudioAdapterDescriptor) * (MAX_AUDIO_ADAPTER_DESC));uint32_t adapterNum MAX_AUDIO_ADAPTER_DESC;int32_t ret audioManagerIns-GetAllAdapters(audioManagerIns, descs, adapterNum);/* 根据用户指定的声卡名称和端口描述进行匹配声卡及端口 */SelectAudioCard(descs, adapterNum, adapterIndex);strcpy_s(g_adapterName, PATH_LEN, descs[adapterIndex - 1].adapterName);SwitchAudioPort(descs[adapterIndex - 1], PORT_OUT, renderPort); // 端口类型为OUT放音/* 根据匹配到的声卡信息进行加载声卡 */audioManagerIns-LoadAdapter(audioManagerIns, descs[adapterIndex - 1], g_adapter); // 加载声卡获取声卡方法实例/* 创建播放类 */uint32_t portId renderPort-portId;InitDevDesc(g_devDesc, portId); // 初始化设置设备参数InitAttrs(g_attrs); // 初始化音频属性参数CheckWavFileHeader(g_file, g_wavHeadInfo, g_attrs); // 解析音频文件及设置Attributesg_adapter-CreateRender(g_adapter, g_devDesc, g_attrs, g_render, g_renderId);/* 下发音频数播放 */g_render-Start((void *)g_render); // 下发控制命令start准备动作pthread_create(g_tids, tidsAttr, (void *)(FrameStart), g_str); // 拉起线程进行播放/* 控制命令 */g_render-Pause((void *)g_render); // 下发暂停操作g_render-Resume((void *)g_render); // 下发恢复操作g_render-SetVolume((void *)g_render, 0.5); // 设置音量/* 停止播放销毁播放类 */g_render-Stop((void *)g_render);g_adapter-DestroyRender(g_adapter, g_renderId);/* 卸载声卡 */audioManagerIns-UnloadAdapter(audioManagerIns, g_adapterName); } 总结 以上就是基于Audio驱动框架进行移植开发过程中所涉及的所有关键适配点。重点介绍了 Audio驱动适配方法、HDI层接口使用方法。开发者可以根据不同芯片进行适配方便简单。希望通过本次的文档您能初步掌握基于HDF框架的Audio驱动开发。 最后 有很多小伙伴不知道学习哪些鸿蒙开发技术不知道需要重点掌握哪些鸿蒙应用开发知识点而且学习时频繁踩坑最终浪费大量时间。所以有一份实用的鸿蒙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.zqtcl.cn/news/84366/

相关文章:

  • gta5网站建设中什么意思如何制作网站?
  • 塘沽企业网站建设建设银行园区公积金管理中心网站
  • 淘客网站模板门店广告牌设计
  • 微网站开发 mui框架谷歌搜索引擎入口2021
  • 好站站网站建设推广在网上做兼职美工有哪些网站
  • 外贸网站建设公司咨询建网站成本
  • 网站建设的相应技术如何使用网站营销
  • 网站建设项目开发贵阳网站设计方案
  • 免费创建企业网站北京南站地图
  • 平台网站建设在哪里深圳网络公司网站
  • 怎么做网站切图枣强县住房和城乡建设局网站
  • 阿里云模板建站好不好商城网站开发代码案例
  • 网站商城建设员招聘福州免费项目建设管理系统
  • 响应式培训网站模板下载网站优化要素
  • 惠州做网站广告内蒙古建设银行网站
  • 企业网站邮箱建设新乡网站建设waterseo
  • python编程入门北京seo运营推广
  • 汉中网站制作二维码如何制作
  • 简述网站的四种常见结构爱站网官网
  • seo推广方法有哪些北京网站整站优化
  • 杭州公司注册代理中介南京百度快照优化排名
  • 西安网站建设那家强桂林北站有核酸检测点吗
  • 网站开发合同文档视频制作哪里可以学
  • 建站节专业网站建设定制
  • 做网站是用的那个开发软件搜索引擎网站入口
  • 口腔门诊建设网站wordpress用户上传资源验证码
  • 建设网站范文分类信息发布 wordpress
  • js 取网站域名资源搜索引擎搜索神器网
  • 网站数据库名称怎么改wordpress怎么连接数据库配置文件
  • 做网站要用什么语言jsp 响应式网站模板