1.OpenHarmony 3GPP协议开发深度剖析——一文读懂RIL
2.LoRaWAN网关搭建
3.STM32H7教程第17章 STM32H7之GPIO的库l库HAL库API
4.HUAWEI LiteOS 移植过程
5.HAL库驱动框架简介
6.标准库和HAL库到底有什么不同?怎么选?
OpenHarmony 3GPP协议开发深度剖析——一文读懂RIL
市场上针对终端操作系统3GPP协议开发的相关资料较为稀缺,即便在Android领域,源码源码相关学习文档也较为有限,库l库更不用说专门的源码源码协议开发书籍了。这可能与市场需求有关,库l库目前市场上从事前后端软件开发的源码源码jquery同步特效源码人员最多,包括我自己。库l库
鉴于我在某手机协议开发团队工作过一段时间,源码源码对协议的库l库AP侧和CP侧开发都有所涉猎,因此我尝试基于OpenAtom OpenHarmony(以下简称“OpenHarmony”)源码编写一些内容,源码源码旨在帮助大家了解协议开发领域,库l库尽可能将3gpp协议内容与OpenHarmony电话子系统模块相结合进行讲解。源码源码据我所知,库l库目前终端协议开发人才非常紧缺。源码源码首先声明,库l库我不是协议专家,且已离开该领域五六年,如有错误,欢迎指正。
谈到终端协议开发,我首先想到的就是RIL。
CP:Communication Processor(通信处理器),通常理解为modem侧,也可以理解为底层协议,这部分由各个modem芯片厂商完成(如海思、高通)。
AP:Application Processor(应用处理器),通常指手机终端,通常理解为上层协议,主要由操作系统Telephony服务进行处理。
RIL:Radio Interface Layer(无线电接口层),通常理解为硬件抽象层,即AP侧将通信请求传给CP侧的中间层。
AT指令:AT指令是应用于终端设备与PC应用之间连接与通信的指令。
常规的Modem开发与调试可以使用AT指令进行操作,而各家的Modem芯片的AT指令都会有各自的差异。因此,手机终端厂商为了能在各种不同型号的产品中集成不同modem芯片,需要进行解耦设计来屏蔽各家AT指令的差异。
于是,OpenHarmony采用RIL对Modem进行HAL(硬件抽象),作为系统与Modem之间的通信桥梁,为AP侧提供控制Modem的接口,各Modem厂商则负责提供对应于AT命令的Vender RIL(这些一般为封装好的so库),从而实现操作系统与Modem间的解耦。
框架层:Telephony Service,电话子系统核心服务模块,主要功能是初始化RIL管理、SIM卡和搜网模块。对应OpenHarmony的源码仓库OpenHarmony/telephony_core_service。这个模块也是非常重要的一个模块,后期单独再做详细解读。
硬件抽象层:即我们要讲的RIL,对应OpenHarmony的源码仓库OpenHarmony/telephony_ril_adapter。RIL Adapter模块主要包括厂商库加载,业务接口实现以及事件调度管理。主要用于屏蔽不同modem厂商硬件差异,为上层提供统一的接口,通过注册HDF服务与上层接口通讯。
芯片层:Modem芯片相关代码,仿《爱美眉》源码即CP侧,这些代码各个Modem厂商是不开放的,不出现在OpenHarmony中。
硬件抽象层又被划分为hril_hdf层、hril层和venderlib层。
hril_hdf层:HDF服务,基于OpenHarmony HDF框架,提供hril层与Telephony Service层进行通讯。
hril层:hril层的各个业务模块接口实现,比如通话、短彩信、数据业务等。
vendorlib层:各Modem厂商提供的对应于AT命令库,各个厂商可以出于代码闭源政策,在这里以so库形式提供。目前源码仓中已经提供了一套提供代码的AT命令操作,至于这个是针对哪个型号modem芯片的,我后续了解清楚再补充。
下面是ril_adapter仓的源码结构:
本文解读RIL层很小一部分代码,RIL是如何通过HDF与Telephony连接上的,以后更加完整的逻辑梳理会配上时序图讲解,会更加清晰。首先,我们要对OpenHarmony的HDF(Hardware Driver Foundation)驱动框架做一定了解,最好是动手写一个Demo案例,具体的可以单独去官网查阅HDF资料。
首先,找到hril_hdf.c文件的代码,它承担的是驱动业务部分,源码中是不带中文注释的,为了梳理清楚流程,我给源码关键部分加上了中文注释。
上述代码中配置了对应该驱动的moduleName为"hril_hdf",因此我们需要去找到对应驱动的配置文件,以HiDV开发板为例,它的驱动配置在vendor_hisilicon/HiDV/hdf_config/uhdf/device_info.hcs代码中可以找到,如下:
这里可以发现该驱动对应的服务名称为cellular_radio1,那么telephony_core_service通过HDF与RIL进行通信肯定会调用到该服务名称,因此无查找telephony_core_service的相关代码,可以很快定位到telephony_core_service/services/tel_ril/src/tel_ril_manager.cpp该代码,该代码中有一个关键类TelRilManager,它用来负责管理tel_ril。
看tel_ril_manager.cpp中的一个关键函数ConnectRilAdapterService,它就是用来通过HDF框架获取RIL_ADAPTER的服务,之前定义过RIL_ADAPTER_SERVICE_NAME常量为"cellular_radio1",它就是在vendor_hisilicon/XXXX/hdf_config/uhdf/device_info.hcs中配置的hril_hdf驱动对应的服务名称。
LoRaWAN网关搭建
搭建LoRaWAN网关的方案使用南京仁珏的LoRaWAN网关开发组件M-GWS-EV。该组件以树莓派的CM3+作为主要处理器,搭载南京仁珏自研的M-GWS射频模块,集成GPS、RJ和4G模块,方便软件开发。
M-GWS-EV的接口包括GPS、RJ和4G模块等,与CM3+的SPI0接口相连接。GPIO7连接到M-GWS的LoRa_PERST管脚,确保硬件接口的正确配置。
搭建过程中,选择使用官方带桌面的仿造梦西游源码Raspberry Pi OS作为运行系统,直接运行CM3+模块。Semtech的官方代码库sx_hal提供快速搭建网关接入LoRaWAN服务器的方案,简化了开发过程。在本地目录下获取gws源码,通过编译工程生成可执行文件,然后安装到CM3+上,执行make install_conf完成配置项的安装。
为了解决复位问题,修改reset_lgw.sh脚本,使用Raspberry Pi OS提供的gpio操作工具替代,确保了启动gwstart.sh脚本的正确执行。配置global.json文件,修改server_address为自建服务器地址,完成基本配置。
接入Chirpstack服务器,通过浏览器登录后台,选择Gateways选项,添加网关的gateway_ID,完成服务器接入。至此,LoRaWAN网关的构建和服务器接入流程全部完成。
STMH7教程第章 STMH7之GPIO的HAL库API
.1 初学者重要提示
1、 如何阅读HAL库源码的问题
HAL库实现的函数有复杂的,也有简单的,简单的可以直接阅读代码。复杂的代码阅读起来比较耗时间,如果再配合参考手册抠每个寄存器的配置,那就更消耗时间了。所以对于这种函数,用户仅需了解每个部分实行的功能即可,而且HAL库都做了关键注释,以说明这部分实现的功能。所以用户没有必要去抠每个配置是如何实现的,仅需知道实现了什么功能。以后工程项目有需要了解具体配置时,再看即可。
2、 学习本章节前,务必保证已经学习了第章。
.2 GPIO涉及到的寄存器
GPIO外设涉及到的寄存器比较少,也容易理解,推荐大家阅读GPIO源码的时候将参考手册中对应的寄存器功能做一个了解。
很多时候,我们会直接调用GPIO的寄存器进行配置,而不使用HAL进行调用,以提高执行效率,特别是中断里面执行时。
.3 源文件stmh7xx_hal_gpio.c
这个文件主要是实现GPIO的引脚配置,学习这个文件注意事项:
.3.1 函数HAL_GPIO_Init
函数原型:
函数描述:
此函数用于初始化GPIO,此函数主要实现如下功能:
函数参数:
下面将结构体每个成员做个说明:
成员Pull用于配置上拉下拉电阻:
成员Speed用于配置GPIO速度等级,有下面四种可选:
成员Alternate用于配置引脚复用,可选择的复用方式在文件stmh7xx_hal_gpio_ex.h里面进行了定义,比如串口复用:
注意事项:
如果是程序运行期间的引脚状态切换,最好采用下面的方式或者直接寄存器操作:
.3.2 函数HAL_GPIO_DeInit
函数原型:
函数描述:
此函数用于复位IO到初始化状态,具体状态看函数原型中的注释即可。
函数参数:
使用举例:
此函数的使用比较简单,需要调用的时候直接调用即可。
.3.3 函数HAL_GPIO_ReadPin
函数原型:
函数描述:
此函数用于读取引脚状态,通过GPIO的源码信息技术IDR寄存器读取。
函数参数:
使用举例:
此函数的使用比较简单,需要调用的时候直接调用即可。
.3.4 函数HAL_GPIO_WritePin
函数原型:
函数描述:
此函数用于设置引脚输出高电平或者低电平。使用GPIO的BSRR寄存器进行设置,使用这个寄存器的好处是支持原子操作,由硬件支持的。原子操作的含义是操作过程不会被中断打断,而我们使用GPIO中另一个设置输出的寄存ODR是会被中断打断的。大家看下寄存器赋值操作对应的反汇编,是由多条汇编指令组成的。
函数参数:
使用举例:
此函数的使用比较简单,需要调用的时候直接调用即可。
.3.5 函数HAL_GPIO_TogglePin
函数原型:
函数描述:
此函数用于设置引脚的电平翻转,使用GPIO的ODR寄存器进行设置。
函数参数:
使用举例:
此函数的使用比较简单,需要调用的时候直接调用即可。
.3.6 函数HAL_GPIO_LockPin
函数原型:
函数描述:
此函数用于锁住GPIO引脚所涉及到的寄存器,这些寄存器包括GPIOx_MODER,GPIOx_OTYPER,GPIOx_OSPEEDR,GPIOx_PUPDR,GPIOx_AFRL 和 GPIOx_AFRH。
函数参数:
注意事项:
使用举例:
此函数的使用比较简单,需要调用的时候直接调用即可。
.4 如何使用HAL库的GPIO驱动
使用方法由HAL库提供(本章.3.1小节提供的例子就是这种方式):
第1步:使能GPIO所在总线的AHB时钟,__HAL_RCC_GPIOx_CLK_ENABLE()。
第2步:通过函数HAL_GPIO_Init()配置GPIO。
(1) 通过结构体GPIO_InitTypeDef的成员Mode配置输入、输出、模拟等模式。
(2) 通过结构体GPIO_InitTypeDef的成员Pull配置上拉、下拉电阻。
(3) 通过结构体GPIO_InitTypeDef的成员Speed配置GPIO速度等级。
(4) 如果选择了复用模式,那么就需要配置结构体GPIO_InitTypeDef的成员Alternate。
(5) 如果引脚功能用于ADC、DAC的话,需要配置引脚为模拟模式。
(6) 如果是用于外部中断/事件,结构体GPIO_InitTypeDef的成员Mode可以配置相应模式,相应的上升沿、下降沿或者双沿触发也可以选择。
第3步:如果配置了外部中断/事件,可以通过函数HAL_NVIC_SetPriority设置优先级,然后调用函数HAL_NVIC_EnableIRQ使能此中断。
第4步:输入模式读取引脚状态可以使用函数HAL_GPIO_ReadPin。
第5步:输出模式设置引脚状态可以调用函数HAL_GPIO_WritePin()和HAL_GPIO_TogglePin。
另外注意下面三个问题:
.5 总结
本章节就为大家讲解这么多,建议大家将GPIO的驱动源码结合参考手册中的寄存器通读一遍,对于我们后面章节的学习大有裨益。
HUAWEI LiteOS 移植过程
本文主要介绍了将LiteOS系统移植到STMFZGT6单片机开发板的过程。
在开发环境中,主要使用的工具包括以下几种。
本文主要记录了基于gcc开发的LiteOS移植过程,如果使用vscode的朋友,其原理相同,也可以作为参考。
在基础工程准备阶段,我使用的火山视频解析源码是STMCubeMX生成的工程文件。生成过程如下:
1. 打开STMCubeMX程序。
2. 选择对应的芯片(STMFZGT6)。
3. 设置时钟来源为外部晶振。
4. Debug设置为串行(我用的是Jlink下载程序),为了方便移植,将系统tick来源设置为TIM1。
5. 配置LED的引脚为输出,我的开发板两个可控led分别为GPIOF_9和GPIOF_。
6. 设置系统时钟,配置为MHz。
7. 分别设置头文件和.c文件。
8. 中着急打了个病句...
9. 最后生成工程,选择为makefile生成格式。
工程将在对应文件夹内生成。
切换到文件夹内,执行make指令构建工程,将在build文件夹下生成你在cubemx里设置的工程名.elf文件。
此时修改Core文件夹下的main.c文件,就可以实现基础的基于HAL库的单片机控制。
修改Makefile文件,添加烧录命令如下:
此时执行make run就可以将.elf文件烧录到单片机中。
在移植LiteOS源码下载过程中,我所使用的源码是GitHub上的LiteOS代码的develop分支。
下载该仓库的代码,得到文件夹结构如下。
在STMCubeMX创建的工程下面新建文件夹为LiteOS(具体什么名看你心情),并将以下几个文件夹导入:
得到
OS_CONFIG文件夹下的target_config包含头文件是stmf的HAL头文件,如果是cortex-m3或者其他内核的单片机需要在这里修改包含的头文件,我的工程将之改为了#include "stmf4xx.h"。
此时需要修改你工程的Makefile文件,将新添加的LiteOS的代码添加到你的工程当中去。
具体修改如下:
此时执行make构建工程,会出现报错,说是重复定义了PendSV_Handler和SysTick_Handler,这是因为这两个函数在LiteOS系统中已经有了定义。这时要到Core/Src文件夹下的stmf4xx_it.c将重复定义的两个处理函数注释掉。
注释掉两个函数的定义。
此时再执行make clean删除原来的构建生成文件,重新make构建。
构建成功,能够生成elf文件,移植成功。
可以修改OS_CONFIG文件夹下的target_config文件,适配自己的开发板。
在移植测试阶段,可以根据STMCubeMX构建工程时所用的GPIO引脚在程序中定义任务。我的测试任务如下:
我的任务定义位于main.c,也可以将任务定义移动到单独的文件中。
功能就是两个led灯实现不同频率的闪烁。
可以观察到上面的led灯闪烁频率低于下面的led,任务创建成功,移植成功。
HAL库驱动框架简介
HAL库驱动框架简介旨在简化硬件抽象层,使得硬件操作对上层软件而言更加便捷。理解HAL库的关键在于其对外设的封装,以下为驱动框架的主要使用主线与功能。
首先,外设初始化是HAL库驱动框架中的重要一步,通过调用特定的初始化函数,可以完成外设的配置,如时钟、引脚等,确保外设在程序运行前处于正确的状态。初始化后,外设便可以被上层代码直接访问和控制。
在使用外设时,HAL库提供了丰富的API,将复杂的底层操作抽象为简洁的接口。例如,对GPIO的读写、定时器的计数等,使得开发者无需深入底层硬件细节,仅需调用对应的函数即可完成所需功能。
阻塞轮询(Polling)和中断(Interrupt)是两种常见的外设访问方式。阻塞轮询通过循环检查外设状态,直至满足特定条件后执行相应操作。这种方式简单直观,但效率较低,尤其是在高频率操作场景下可能会导致CPU资源浪费。相比之下,中断机制允许外设在状态改变时主动通知处理器,从而触发相应处理逻辑,实现更加高效的异步操作。
数据传输方面,DMA(Direct Memory Access)提供了硬件辅助的数据传输机制,使得数据可以在外设与内存之间直接移动,无需CPU介入。这对于数据密集型应用而言,能够显著提升系统性能。
全面了解HAL库涉及其各个层面的功能与实现细节。开发者需要熟练掌握初始化、外设访问、中断处理、DMA等核心概念,并通过实际项目实践,逐步积累经验。通过查阅官方文档、源代码注释以及社区资源,可以深入理解HAL库的内部机制,进而灵活运用其功能,解决实际问题。
标准库和HAL库到底有什么不同?怎么选?
通常新手在入门STM时,都会面临选择开发方式的决策,不同的方式对编程架构影响显著。主要选择为标准库和HAL库,而较少选择直接配置寄存器。虽然网络上有大量关于标准库、HAL库的描述,但对刚入门的朋友来说,可能难以直观理解这些开发方式之间的差异。本篇将以直白的方式,用作者的理解来阐述标准库、HAL库的区别,如有不妥之处,欢迎提出不同意见。
一、配置寄存器
对于熟悉单片机的开发者,可能有一部分会直接使用汇编语言操作寄存器实现功能。但到了STM,这种方法变得不太可行,因为STM的寄存器数量远超单片机的十倍,无法全部记忆。直接操作寄存器变得非常繁琐,需要频繁查阅芯片数据手册。然而,仍有一小部分人偏好直接配置寄存器,因其能更深入理解原理。
二、标准库
面对众多寄存器导致的开发困难,ST公司为每款芯片提供库文件,如stmF1xx...,包含常用宏定义和外设封装结构体。我们只需配置结构体变量成员即可修改外设配置寄存器,实现不同功能。这是目前最常用的方式,也是接触STM开发最常见的方式。
三、HAL库
HAL库是ST公司力推的开发方法,全称为Hardware Abstraction Layer(硬件抽象层)。库如其名,功能抽象,一眼难辨其作用。与标准库相比,它更注重节省开发时间,提供更高效的集成功能。例如,标准库可能需要多行代码实现的功能,HAL库只需一行。它还有效解决了程序移植问题,使用相通外设的程序可以轻松复制粘贴,前提是遵循相同外设设计。STMcube软件通过图形化配置生成HAL库工程文件,极大方便开发。然而,其高效性也带来了执行效率的低下,常被用户吐槽。
四、总结
综合上述,强烈推荐HAL库,原因有两个:一是自F7系列开始,ST公司已停止更新标准库,F7及以后无法使用标准库,表明公司主推HAL库。二是追求方便、模块化是行业趋势,高效、便捷的HAL库必将迅速发展。
学习HAL库的同时,底层原理同样重要,这是每个学有所成者共识。HAL库并非万能,结合底层理解,开发水准会显著提高。
五、STM HAL库与标准库的区别
1. 句柄
在标准库中,初始化外设(如USART)需要配置多个寄存器,通过结构体变量+初始化函数实现。而在HAL库中,使用全局句柄贯穿初始化流程,不仅包含基本参数,还包含更多与单片机相关的设置,如中断处理、DMA相关变量等。
2. MSP函数
MSP函数负责与单片机相关的初始化,与标准库不同,HAL库在初始化外设时,还会初始化与单片机相关的外设配置,如引脚配置。这使得HAL库具有极强的移植性,但同时增加了代码量和嵌套层级。
3. Callback函数
Callback函数简化应用层代码编写,用户只需设置句柄参数,由HAL库自动处理中断、数据读取等操作,无需手动清除标志位,增强代码逻辑性。
六、HAL库结构
STM的HAL库在STMCubeMX可视化配置工具的支持下,大大节省了开发时间。HAL库结构包含多个层次,从主头文件开始,到具体型号头文件,再到源码文件。其包含三大类API,宏定义用于中断、配置等操作,用户代码分为处理外设句柄、MSP、回调函数等。
整体来看,HAL库通过句柄、MSP、回调等机制,提供了强大的移植性和更清晰的编程结构,但带来了代码量增加和编译速度降低的挑战。开发者需根据项目需求权衡选择。
STM HAL库的框架结构
全文链接:
HAL库的框架结构涉及了Cortex系列微控制器软件接口标准(CMSIS)的背景,以及STM微控制器库的构建方式。CMSIS标准由ARM与芯片厂商共同制定,旨在解决不同芯片厂商生产的Cortex微控制器软件兼容性问题,提供通用API接口以简化移植工作。STM的库遵循CMSIS标准,分为三种类型,提供硬件抽象层,屏蔽硬件差异,便于软件移植。
MCU固件包包含HAL库,它是STM芯片开发的核心部分,文件结构清晰,分为Src和Inc两个主要部分,分别存储源码和头部文件。HAL库API函数遵循特定命名规则,提供初始化、读写、控制、状态和错误查询等功能。对寄存器位操作使用宏定义,便于高效操作。
HAL库设计借鉴面向对象思想,采用句柄概念抽象外设,简化用户代码编写。句柄贯穿整个外设操作流程,例如USART2初始化时定义句柄huart2,用于管理串口操作。句柄内部结构包含串口初始化数据类型,用于配置串口参数。初始化过程涉及配置寄存器和中断处理,确保外设功能正常。
总之,STM HAL库通过CMSIS标准和面向对象设计,提供了高效、统一的微控制器软件接口,简化了开发流程,提高了代码可移植性。
STMH7教程第章 STMH7的USART串口基础知识和HAL库API
本章内容深入讲解了STMH7的USART串口基础知识,包括其HAL库API的使用。相较于STMF1和F4系列,H7系列在串口功能上有所增强。.1 初学者须知
USART(通用同步异步收发器)是通信核心,异步串口(UART)是其常见形式。理解串口硬件框图至关重要,它展示了唤醒中断、中断处理、DMA传输、寄存器位置、FIFO功能及引脚互换等。.2 串口详解
串口硬件框图揭示了中断、DMA、时钟配置及数据传输路径。
STMH7串口功能强大,常用模式包括异步通信,支持多种中断和高级特性,如自适应波特率检测。
串口支持的数据帧格式和校验,以及发送时序图帮助理解中断机制。
.3 HAL库操作
使用HAL库配置串口涉及USART_TypeDef结构体、UART_HandleTypeDef的配置,以及GPIO、时钟、中断和DMA的底层设置。HAL库提供了操作寄存器和配置高级特性的便利。
串口初始化流程包括初始化结构体、GPIO配置、中断和DMA设置,以及高级特性和基础参数的配置。
.4 源码文件概述
主要函数如HAL_UART_Init、HAL_UART_Transmit和HAL_UART_Receive展示了HAL库API的使用示例。这些函数涉及的数据发送、接收和中断传输功能提供了实际操作指导。
.5 总结
深入理解USART的基础知识和HAL库API是STMH7开发的关键。随着实践的积累,这些内容将变得熟练。更多细节和实例可以参考原文链接获取。STM SPI DMA 源码解析及总结
一 前言
在调试STM的SPI接口时,我遇到了一个复杂的难题。解决这一问题花费了大量时间,这次经历促使我回顾并总结了STM的SPI代码。本文将以此为主线,分享我在这个过程中的心得。
二 初始化
STM SPI接口的初始化遵循标准流程,包括初始化和配置两部分。确保接口正确初始化,需注意以下几点:
1. 避免重复使用接口,确保其唯一性。
2. 检查接口硬件部分是否正常连接,可通过GPIO端口的电平检测。
3. 选择合适的系统主频,避免设置过高,以匹配SPI接口的速率。
三 数据收发
数据收发功能通过HAL库的API实现,主要包括:
1. 数据发送:`HAL_SPI_Transmit_DMA`函数。
2. 数据接收:`HAL_SPI_Receive_DMA`函数。
使用时应特别注意CS(Chip Select)信号的控制,确保在DMA操作期间保持CS低电平,避免数据丢失。
四 总结
在SPI开发中,遵循正确流程至关重要。面对问题,应基于对代码的理解和实践经验进行分析,而不是依赖计算机自动解决。正确处理初始化、数据收发等环节,避免常见错误,能有效提升开发效率。
STM驱动DHT(HAL库版)
一、DHT传感器工作原理
1. DHT传感器使用单总线通信方式,实现数据传输与控制。在操作中,其工作过程如下:
(1)设备首先检查总线上是否存在DHT设备,并确认设备的响应。
(2)随后,DHT传感器发送数据至STM。
二、STMCubeMX配置开发环境
选用STMFZET6开发板,DHT模块与PG5引脚连接,使用模拟IIC信号驱动。
1. 设置高速外部时钟。
2. 配置STLink烧录。
3. 配置定时器3。
4. 配置串口。
5. 配置时钟电路。
6. 设置项目名。
注意:使用Keil时,工具链选择MDK-ARM,STMCubeIDE选择STMCubeIDE,CLion选择SW4STM。
7. 选择生成的.h和.c文件。
三、DHT传感器驱动程序
编写dht.h和dht.c文件,实现传感器驱动程序。
主函数中重定义printf函数。
四、源码下载
代码可在github.com/LMFzzz/DHT...