【问题标题】:ARM Cortex M4 - C Programming and Memory Access OptimizationARM Cortex M4 - C 编程和内存访问优化
【发布时间】:2021-08-15 01:14:53
【问题描述】:

以下三行代码是用 1 条 MOV 指令修改位的优化方法,而不是使用较少中断安全的 read-modify-write 习惯用法。它们彼此相同,并且设置了 GPIO 端口的数据寄存器中的 LED_RED 位:

  1. *((volatile unsigned long*)(0x40025000 + (LED_RED << 2))) = LED_RED;
  2. *(GPIO_PORTF_DATA_BITS_R + LED_RED) = LED_RED;
  3. GPIO_PORTF_DATA_BITS_R[LED_RED] = LED_RED;

LED_RED 就是(volatile unsigned long) 0x02。在此微控制器的内存映射中,该寄存器(和其他)的前 2 个 LSB 未使用,因此第一个示例中的左移是有意义的。

GPIO_PORTF_DATA_BITS_R 的定义是:

#define GPIO_PORTF_DATA_BITS_R ((volatile unsigned long *)0x40025000)

我的问题是: 为什么在使用指针算术或数组索引(分别为第 2 方法和第 3 方法)时不需要左移两次?我很难理解。提前谢谢你。

【问题讨论】:

  • 不存在“较少中断安全”的代码——有中断安全的代码和非中断安全的代码。并且不要假设单行 C 意味着单次写入 - 确保您正在写入 GPIO 中的“设置”或“清除”寄存器,这样才会安全。
  • 使用相同的 LED_RED 值作为地址的一部分,并且作为您正在写入的值,几乎可以肯定是错误的。但是如果不知道微控制器的细节和 LED_RED 的值,就不可能知道。它可能会像您所期望的那样工作,但不是设计使然。

标签: c arm gpio cortex-m


【解决方案1】:

请记住 C 指针算法的工作原理:向指针添加偏移量以指向的类型为单位进行操作。由于GPIO_PORTF_DATA_BITS_R 具有unisgned long *sizeof(unsigned long) == 4 类型,因此GPIO_PORTF_DATA_BITS_R + LED_RED 有效地添加了2 * 4 = 8 个字节。

注意,(1) 对0x40025000 进行算术运算,这是一个整数,而不是指针,所以我们需要加 8 才能得到相同的结果。左移 2 与乘以 4 相同,所以 LED_RED << 2 再次等于 8。

根据[] 运算符的定义,(3) 完全等价于 (2)。

【讨论】:

  • 太棒了!谢谢,现在很清楚了。似乎我在没有直观地理解指针算术和数组索引之间的联系以及类型如何发挥作用的情况下做到了这一点。感谢您一键点击
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-12-14
  • 1970-01-01
  • 1970-01-01
  • 2018-09-29
  • 2017-12-03
  • 2014-10-19
  • 1970-01-01
相关资源
最近更新 更多