volatile关键字如何影响静态const数组?

Ala*_*irG 1 c volatile

这是一个思想家,任何能够回答它的人都值得大家认可!这实际上是我要求更好理解的几个相关问题.

STM32 ARM Cortex平台的驱动程序包含以下代码:

static __I uint8_t APBAHBPrescTable[16] = {0, 0, 0, 0, 1, 2, 3, 4, 1, 2, 3, 4, 6, 7, 8, 9};
Run Code Online (Sandbox Code Playgroud)

__I 定义为:

#ifdef __cplusplus
  #define     __I     volatile                /*!< defines 'read only'   permissions      */
#else
  #define     __I     volatile const          /*!< defines 'read only'   permissions      */
#endif
Run Code Online (Sandbox Code Playgroud)

我的程序是一个用GCC交叉编译器编译的C程序.因此数组声明是有效的:

static volatile const uint8_t APBAHBPrescTable[16] = {0, 0, 0, 0, 1, 2, 3, 4, 1, 2, 3, 4, 6, 7, 8, 9};
Run Code Online (Sandbox Code Playgroud)

问题1:

鉴于这是一个常数数组,为什么要在volatile这里使用关键字?

我的理解是volatile关键字意味着数组的内容可以改变,但const意味着它们不能改变.

在代码中唯一使用此数组是这样的三个用法:

tmp = RCC->CFGR & CFGR_PPRE1_Set_Mask;
tmp = tmp >> 8;
presc = APBAHBPrescTable[tmp];
Run Code Online (Sandbox Code Playgroud)

当我转储的值tmppresc我发现tmp具有为4的值,并且presc具有0指数4的值是具有1有没有其他访问或该值的用途的值数组的第5个元素.. .所有......任何地方.

问题2:

如何宣布它之间的价值变化?

当我转储数组时,我看到它充满了零.

它可靠地发生......直到我__I从数组声明中删除它.这让我觉得它不是缓冲区溢出.除此之外,我什么都想不到.

我认为volatile关键字是有原因的,除了我在中断处理程序中看到如下代码,据我所知,volatile关键字是多余的:

volatile uint32_t status = USART2->SR;
Run Code Online (Sandbox Code Playgroud)

此变量是函数的本地变量,因此其他地方的代码永远不会更改.

========额外细节========

以下是相关代码段的带注释的反汇编.(RCC_GetClocksFreq + 128)处的值为零,但在某些时候出现以将预分频器查找表的地址复制到其中:

0x000001d0 <+56>:    ldr     r1, [pc, #68]   ; (0x218 <RCC_GetClocksFreq+128>)
       ...
   tmp = RCC->CFGR & CFGR_PPRE1_Set_Mask;
   tmp = tmp >> 8;
0x000001de <+70>:    ldr     r4, [r2, #4]
0x000001e0 <+72>:    ubfx    r4, r4, #8, #3
   presc = APBAHBPrescTable[tmp];
0x000001e4 <+76>:    ldrb    r4, [r1, r4]
   RCC_Clocks->PCLK1_Frequency = RCC_Clocks->HCLK_Frequency >> presc;
0x000001e6 <+78>:    lsr.w   r4, r3, r4
0x000001ea <+82>:    str     r4, [r0, #8]
Run Code Online (Sandbox Code Playgroud)

这是相同的,但volatile const宏替换为const:

0x000001d0 <+56>:    ldr     r4, [pc, #68]   ; (0x218 <RCC_GetClocksFreq+128>)
       ...
   tmp = RCC->CFGR & CFGR_PPRE1_Set_Mask;
   tmp = tmp >> 8;
0x000001de <+70>:    ldr     r1, [r2, #4]
0x000001e0 <+72>:    ubfx    r1, r1, #8, #3
   presc = APBAHBPrescTable[tmp];
0x000001e4 <+76>:    ldrb    r1, [r4, r1]
   RCC_Clocks->PCLK1_Frequency = RCC_Clocks->HCLK_Frequency >> presc;
0x000001e6 <+78>:    lsr.w   r1, r3, r1
0x000001ea <+82>:    str     r1, [r0, #8]
Run Code Online (Sandbox Code Playgroud)

它们基本相同.然而,以某种方式删除volatile关键字解决了这个问题!

ala*_*ain 7

我的理解是volatile关键字意味着数组的内容可以改变,但const意味着它们不能改变.

volatile表示程序必须在每次使用时从内存中读取值.const表示程序可能不会更改值,但环境(或"OS")可能会更改.

这解释了您观察到的行为:如果没有volatile,编译器会认为可以读取一次值并多次使用它.