【发布时间】:2021-05-12 05:08:49
【问题描述】:
我正在为 GPIO 编写 C++ 模板包装器。对于 STM32,我使用 HAL 和 LL 代码作为基础。 GPIO 初始化归结为一系列read register to temp variable -> Mask pin specific bits in temp -> shift and write pin specific bits in temp -> write temp back to register。寄存器声明为volatile。
首先对 volatile 进行所有读取,然后是所有更新,然后是对 volatile 的所有写入,而不是像现在这样(在例如ST的代码)?当然,写入仍然是有序的。
所以从场景A:
uint32_t temp;
temp = struct->reg1;
temp |= ...
temp &= ...
struct->reg1 = temp;
temp = struct->reg2;
temp |= ...
temp &= ...
struct->reg2 = temp;
到场景B:
uint32_t temp1, temp2;
temp1 = struct->reg1;
temp2 = struct->reg2;
temp1 |= ...
temp1 &= ...
temp2 |= ...
temp2 &= ...
struct->reg1 = temp1;
struct->reg2 = temp2;
场景 B 可能会使用更多(或 4 个)内存,但不必像我预期的那样经常中断主程序流。是否可以在场景 B 中对代码进行更多优化,例如通过组合读取或写入?
【问题讨论】:
-
不会有太大区别。无法优化对易失性寄存器的访问,并且 STM 没有内存缓存……场景 A 使用的堆栈空间比场景 B 少一点,可以忽略不计。它也更具可读性,这是您在这里唯一需要瞄准的东西。
-
一般来说它可能有不同的行为。在第一个版本中,您写入
reg1,然后从reg2读取。对reg1的易失性写入可能会影响从reg2读取的值?只有您可以知道这是否是您的代码可能遇到的实际场景,但需要牢记这一点。 -
场景 B 需要 2 个临时变量,而 A 只需要 1 个。鉴于 STM32 没有很多备用寄存器来保存临时值,因此 A 是一个更优的解决方案。如有疑问,请始终检查/比较生成的程序集。
-
@MichaëlRoy
STM has no memory cache真的吗?发帖前检查。 -
@MichaëlRoy 你写了关于内存缓存的文章。许多 STM uC 确实有内存缓存。如果硬件寄存器地址是可缓存的,则不会。
标签: c++ embedded stm32 cpu-registers