在保存和检索机制之间拥抱命令的代码

标签 c arm stm32 cpu-registers

最近我正在C库中实现STM32F0系列MCU的内部外设。

当我研究 ST 如何利用他们的 HAL 库完成同样的事情时,我进入了这段代码......

  1 /*--------------------- EXTI Mode Configuration ------------------------*/
  2 /* Configure the External Interrupt or event for the current IO */
  3 if((GPIO_Init->Mode & EXTI_MODE) == EXTI_MODE) 
  4 {
  5  /* Enable SYSCFG Clock */
  6  __HAL_RCC_SYSCFG_CLK_ENABLE();

  7  temp = SYSCFG->EXTICR[position >> 2];
  8  CLEAR_BIT(temp, (0x0FU) << (4U * (position & 0x03U)));
  9  SET_BIT(temp, (GPIO_GET_INDEX(GPIOx)) << (4U * (position & 0x03U)));
  10 SYSCFG->EXTICR[position >> 2] = temp;

  11 /* Clear EXTI line configuration */
  12  temp = EXTI->IMR;
  13  CLEAR_BIT(temp, (uint32_t)iocurrent);
  14  if((GPIO_Init->Mode & GPIO_MODE_IT) == GPIO_MODE_IT)
  15  {
  16   SET_BIT(temp, iocurrent); 
  17  }
  18  EXTI->IMR = temp;

我试图理解的是为什么使用7-1012-18行中的pair命令。 为什么有这些?为什么要存储一些东西然后写入它,然后从内存中检索它丢弃写入的内容? 与多任务处理和竞争条件有关吗?我不太明白!

最佳答案

这用于速度优化并避免内存映射寄存器中出现不需要的状态。
想象一些内存映射变量 EXT->ABC 的示例。想象一下这样夸张的示例情况:

  • 我们有一些硬件内存地址,可以通过内存映射的 EXT->ABC 变量访问
  • 我们知道 EXT->ABC 中的位 1 已设置,位 2 已清除
  • 我们希望在 EXT->ABC 中清除位 1 并设置位 2 并保持所有其他位不变
  • 硬件不允许 EXT->ABC 寄存器中的位 1 和位 2 同时被清除或被设置。此类状态是被禁止的,并且可能会导致未定义的行为(这意味着任何行为,例如软件重置)。
  • 读写 EXT->ABC 寄存器非常慢。

如果我们直接操作EXT->ABC变量:

CLEAR_BIT(EXT->ABC, 1); // expands to: EXT->ABC = EXT->ABC & ~1;
SET_BIT(EXT->ABC, 2);   // expands to: EXT->ABC = EXT->ABC | 2;

这将导致两条线之间处于禁止状态,因为位 1 和位 2 将被设置。另外,在这两行中,EXTI->IMR 被访问了 4 次。 为了解决这个问题,我们需要将 EXTI->IMR 寄存器中的值存储在某处,修改所需的位,然后将修改后的值写入 EXTI->IMR 寄存器。所以我们会:

uint32_t temp;
temp = EXT->ABC; // store
CLEAR_BIT(temp, 1);
SET_BIT(temp, 2);
EXT->ABC = temp; // write

我们从内存映射变量中读取一次,修改并使用该值,做我们想做的任何事情。之后,我们向内存映射变量写入一次。这样 EXT->ABC 寄存器仅被触及两次,并且代码被安全地写入,因此不会发生未定义/禁止/不需要的状态。
例如:对于第7-10行:访问SYSCFG->EXTICR[position >> 2U]您需要多个CPU操作(计算 position >> 2U ,乘以 sizeof(SYSCFG->EXTICR) ,添加到 SYSCFG->EXTICR 地址,取消引用)。也许开发人员的意图是更快地执行这些行。或者您需要清除位 0x0F<<(4*(position&0x03)当写信给(GPIO_GET_INDEX(GPIOx))<<(4*position&0x03)时.

关于在保存和检索机制之间拥抱命令的代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48178263/

相关文章:

c - 函数以某种方式从一次调用中返回两次

c - 为什么 travis-ci.org 总是显示 [ build : failing ] badge?

c - 当我们用完 Cortex M3 上的内存时会发生什么

c++ - 这个计算是如何工作的?

c - map 文件中 STM32 的 IAR 堆栈使用情况

microcontroller - STMicro 是否错误地解释了术语 "shadow register"?

c++ - 混合 gtk+ 和 c++

c - 具有可变参数的函数 - 奇怪的输出

C 字符串在循环中没有正确迭代

c - STM32 HAL C标准