ARM Cortex M4 - C 编程和内存访问优化
ARM Cortex M4 - C Programming and Memory Access Optimization
以下三行代码是使用 1 条 MOV 指令修改位的优化方法,而不是使用中断安全性较低的 read-modify-write 习惯用法。它们彼此相同,并在 GPIO 端口的数据寄存器中设置 LED_RED 位:
*((volatile unsigned long*)(0x40025000 + (LED_RED << 2))) = LED_RED;
*(GPIO_PORTF_DATA_BITS_R + LED_RED) = LED_RED;
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)
我的问题是:为什么我在使用指针算法或数组索引(分别是第二种方法和第三种方法)时不需要左移两次?我很难理解。提前谢谢你。
记住 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)。
以下三行代码是使用 1 条 MOV 指令修改位的优化方法,而不是使用中断安全性较低的 read-modify-write 习惯用法。它们彼此相同,并在 GPIO 端口的数据寄存器中设置 LED_RED 位:
*((volatile unsigned long*)(0x40025000 + (LED_RED << 2))) = LED_RED;
*(GPIO_PORTF_DATA_BITS_R + LED_RED) = LED_RED;
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)
我的问题是:为什么我在使用指针算法或数组索引(分别是第二种方法和第三种方法)时不需要左移两次?我很难理解。提前谢谢你。
记住 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)。