STM32臃肿还是神学?

Lpa*_*son 4 c embedded stm32

我并不是想发起一场 HAL 圣战,我很好奇这段代码是否具有更高的功能。

\n

在 STM32 设备上使用 GPIO 时,您需要使用 启用 GPIO 时钟__HAL_RCC_GPIOA_CLK_ENABLE()。进一步深入研究代码,我发现该函数到底在做什么,如下所示。据我所知,该代码唯一有用的部分是SET_BIT(RCC->IOPENR, RCC_IOPENR_GPIOAEN);,其余部分似乎毫无用处。

\n

我明白为什么 __IO uint32_t tmpreg;并且UNUSED(tmpreg);可以使用,但是这条线并tmpreg = READ_BIT(RCC->IOPENR, RCC_IOPENR_GPIOAEN);没有真正做任何事情,所以这三个看起来毫无意义。我错过了什么吗?

\n
#define __HAL_RCC_GPIOA_CLK_ENABLE() \xc2\xa0\\ \n    do { \\\n    __IO uint32_t tmpreg; \\\n\xc2\xa0 \xc2\xa0 SET_BIT(RCC->IOPENR, RCC_IOPENR_GPIOAEN);\\ \n\xc2\xa0 \xc2\xa0 tmpreg = READ_BIT(RCC->IOPENR, RCC_IOPENR_GPIOAEN);\\\n\xc2\xa0 \xc2\xa0 UNUSED(tmpreg); \\\n\xc2\xa0 \xc2\xa0 } while(0)\n
Run Code Online (Sandbox Code Playgroud)\n

设置位

\n
#define SET_BIT(REG, BIT) \xc2\xa0 \xc2\xa0 ((REG) |= (BIT))\n
Run Code Online (Sandbox Code Playgroud)\n

读位

\n
#define READ_BIT(REG, BIT) \xc2\xa0 \xc2\xa0((REG) & (BIT))\n
Run Code Online (Sandbox Code Playgroud)\n

没用过

\n
#define UNUSED(X) (void)X \xc2\xa0 \xc2\xa0 \xc2\xa0/* To avoid gcc/g++ warnings */\n
Run Code Online (Sandbox Code Playgroud)\n

pma*_*ane 7

这个答案完全是猜测。只有 STMicro 可以给出这个宏的原因。但我认为我的理论是合理的,并且不适合评论。

首先要注意的是,STM32 微控制器具有非常灵活的时钟控制。CPU 完全有可能以 160MHz 运行,外围总线以 1MHz 运行。

随意挑选一个我最近使用的 STM32,STM32L4P5,您可以查看参考手册的第 6.2.18 节,其中谈到启用外设时钟...

使能位具有同步机制,可为外设创建无干扰时钟。使能位设置后,时钟激活之前有 2 个时钟周期的延迟

因此,使能外设时钟后,需要等待2个周期后时钟才有效。但这不是CPU时钟的2个周期,而是外设时钟的2个周期。

因此,宏不能通过执行某些NOP指令来延迟 2 个周期。它必须在(可能慢得多)外设总线上延迟几个周期。这种强制读取(通过易失性指针)可以实现这一点。

  • NOP 实际上是 Cortex M 之前处理此类情况的标准方法。非常方便的方法来计算时钟周期的精确数量,而无需深入研究核心手册。在硬件层面上优化 NOP 是 ARM 的一个错误……我的意思是,该指令对其他方面没有什么好处。 (4认同)