STM32中HAL库接口函数的共性以及架构思想

最近,我在使用STM32CUBEMX这个软件生成HAL库的模板,并学习STM32单片机的USB Device外设功能以及相关协议栈,发现了HAL的一些特点,现在记录下来。

(1)"函数的本质是一个数据处理器"这句话的理解。

首先理解一下寄存器的作用,首先要明白操作那个寄存器就是操作硬件,也就是读写寄存器就是实现了STM32单片机功能的控制。

首先看一下以下代码:

cpp 复制代码
typedef struct
{
  __IO uint32_t GOTGCTL;              /*!<  USB_OTG Control and Status Register       Address offset: 000h */
  __IO uint32_t GOTGINT;              /*!<  USB_OTG Interrupt Register                Address offset: 004h */
  __IO uint32_t GAHBCFG;              /*!<  Core AHB Configuration Register           Address offset: 008h */
  __IO uint32_t GUSBCFG;              /*!<  Core USB Configuration Register           Address offset: 00Ch */
  __IO uint32_t GRSTCTL;              /*!<  Core Reset Register                       Address offset: 010h */
  __IO uint32_t GINTSTS;              /*!<  Core Interrupt Register                   Address offset: 014h */
  __IO uint32_t GINTMSK;              /*!<  Core Interrupt Mask Register              Address offset: 018h */
  __IO uint32_t GRXSTSR;              /*!<  Receive Sts Q Read Register               Address offset: 01Ch */
  __IO uint32_t GRXSTSP;              /*!<  Receive Sts Q Read & POP Register         Address offset: 020h */
  __IO uint32_t GRXFSIZ;              /*!< Receive FIFO Size Register                 Address offset: 024h */
  __IO uint32_t DIEPTXF0_HNPTXFSIZ;   /*!<  EP0 / Non Periodic Tx FIFO Size Register  Address offset: 028h */
  __IO uint32_t HNPTXSTS;             /*!<  Non Periodic Tx FIFO/Queue Sts reg        Address offset: 02Ch */
  uint32_t Reserved30[2];             /*!< Reserved 030h*/
  __IO uint32_t GCCFG;                /*!< General Purpose IO Register                Address offset: 038h */
  __IO uint32_t CID;                  /*!< User ID Register                           Address offset: 03Ch */
  uint32_t  Reserved40[48];           /*!< Reserved 040h-0FFh */
  __IO uint32_t HPTXFSIZ;             /*!< Host Periodic Tx FIFO Size Reg             Address offset: 100h */
  __IO uint32_t DIEPTXF[0x0F];        /*!< dev Periodic Transmit FIFO                 Address offset: 0x104 */
} USB_OTG_GlobalTypeDef;
cpp 复制代码
#define USB_OTG_FS_PERIPH_BASE               0x50000000U
cpp 复制代码
#define USB_OTG_FS          ((USB_OTG_GlobalTypeDef *)USB_OTG_FS_PERIPH_BASE)

其中第一个类型表示USB_OTG的寄存器组数据,第二个宏表示寄存器组首地址值,最终定义了一个宏"USB_OTG_FS"代表整个寄存器组的地址。到这里数据已经有了,而在HAL库的源文件"stm32f1xx_ll_usb.c"中定义的API函数的参数列表中都有USB_OTG_GlobalTypeDef *类型的参数。这样调用这些API函数的时候就实现了参数的传递,也就在函数内部实现了对寄存器组的控制。

cpp 复制代码
HAL_StatusTypeDef USB_CoreInit(USB_OTG_GlobalTypeDef *USBx, USB_OTG_CfgTypeDef cfg);
HAL_StatusTypeDef USB_EnableGlobalInt(USB_OTG_GlobalTypeDef *USBx);
HAL_StatusTypeDef USB_DisableGlobalInt(USB_OTG_GlobalTypeDef *USBx);
...
static HAL_StatusTypeDef USB_CoreReset(USB_OTG_GlobalTypeDef *USBx);

真正验证了"函数其实是一个数据处理器"这句话,而且更进一步"HAL库中API函数组其实是指针变间接处理同一个自定义结构体类型数据的数据处理器"。

在其他HAL库中也有相似的用法,所以我们需要做的就是定义这个结构体类型的数据(寄存器组已经定义了,无需定义,硬件上自然存在),然后在需要的时候,调用这些API函数完成参数传参。函数内部就自动完成对这些结构体类型数据的访问了,只不过是以指针间接访问的方式实现的。

真的很难想象,HAL库每一个源文件中少则十几个,多册几十个函数居然都是操作寄存器组,那可想而知,寄存器虽然没那么多,但是操作它的花样还是很多的,主要原因是每一个寄存器都有32bit,寄存器内部各个bit位代表不同硬件操作。

当然了,其他类似的自定义结构体类型是内存变量的情况,函数参数为自定义结构体类型指针变量,函数内部实现对自定义结构体变量内部成员的读写访问,一般不会涉及到位操作,只是简单内存变量的读写访问。

(2)关于架构的思想。

我现在有一个感受就是:我已经看了好多linux源码程序了,c语言的各种用法也都遇到过,熟悉了,为什么切换到STM32单片机的程序就感觉无从下手,不知道从哪里看呢?

我现在的答案是:缺乏架构思想,也就是那些源文件是在顶层,哪些顶层源文件中的函数调用底层源文件中的函数。

首先,最顶层的是唯一的main.c,因为其他函数都是从main.c中的main()开始调用的。

然后是adc.c、can.c、tim.c等STM32CUBEMX软件自动生成的外设源文件,每一个源文件中定义了第一条论述中的自定义结构体类型变量实体。然后调用API函数实现简单的初始化、去初始化等操作,让外设处于准备工作状态。这一层如果是复杂的外设例如USB、以太网等,可能需要调用一些协议栈,这就是我接下来要说的了

然后是协议栈,中间层、RTOS操作系统等这些纯软件的操作。这一层一般不涉及到硬件操作,具有一定可移植性。

最后,HAL库层(硬件抽象层),这一层是软件的最底层,主要就是操作寄存器组实现各个功能控制,主要用到了位运算。

再往下,就是硬件层了,属于纯数字电路、模拟电路等就不论述了。

注意:以上只是简单的说明,并不固定死的,也并不规定不能跨层访问,只是大致的分层等。到这里可能有人要问了,那业务功能层在那一层呢?我们都知道业务功能层是实现具体的客户需求,属于应用层的范畴,他应该在高于第二层或者与第二层平行的关系。因为应用层主要是实现客户需求功能会调用到中间层(去操纵内存变量,内存变量代表业务逻辑)、或者HAL库层(去操作寄存器)。

相关推荐
恶魔泡泡糖2 小时前
51单片机点阵屏应用
单片机·嵌入式硬件·51单片机
南烟斋..2 小时前
ARM Cortex-A7(IMX6ULL)嵌入式裸机开发指南:从点灯到中断
arm开发·单片机·嵌入式硬件
bai5459362 小时前
stm32 CubeIDE DMA模式的串口收发
stm32·单片机·嵌入式硬件
M宝可梦2 小时前
新一代Transformer 架构MAT: Engram-STEM-PLE
深度学习·架构·transformer·deepseek·记忆机制
嗯嗯=2 小时前
STM32单片机学习篇7
stm32·单片机·学习
码界奇点3 小时前
基于前后端分离架构的智能面试刷题系统设计与实现
spring boot·面试·职场和发展·架构·毕业设计·源代码管理
赋创小助手3 小时前
超微2U高密度服务器AS-2126HS-TN评测(双AMD EPYC 9005 Turin)
运维·服务器·人工智能·深度学习·神经网络·自然语言处理·架构
jiang153237942433 小时前
MS51FB9AE 新唐 TSSOP-20
单片机·嵌入式硬件
开开心心就好3 小时前
打印机驱动搜索下载工具,自动识别手动搜
java·linux·开发语言·网络·stm32·物联网·电脑