gcc 是否正在重新排序我的 volatile 变量?

Is gcc reordering my volatile variables?

我正在使用 FreeRTOS 使用 GNU ARM 工具链 (gcc 5.4.1) 在 STM32F746 (ARM Cortex-M7) 上进行开发。我正在使用以下 CFLAGS 集:

-g -Werror -Wextra -O2  -fno-common -ffunction-sections -fmessage-length=0 -g -mcpu=cortex-m7 -mthumb -mfloat-abi=hard -mfpu=fpv5-sp-d16 -fno-common -ffunction-sections -fmessage-length=0 -g -mcpu=cortex-m7 -mthumb -mfloat-abi=hard -mfpu=fpv5-sp-d16

以下代码在控制台中显示“0”,就好像 DMA 控制器未开机一样。通常情况下,在AHB1ENR寄存器中写RCC_AHB1ENR_DMA1EN,给DMA控制器上电

/* *** Other peripheral configurations *** */
RCC->AHB1ENR |= RCC_AHB1ENR_DMA1EN;                                     
DMA1_Stream3->CR = DMA_SxCR_PL | DMA_SxCR_MINC |                        
        DMA_SxCR_TCIE | DMA_SxCR_TEIE | DMA_SxCR_DMEIE;
DEBUG_PRINTF("%x\r\n", DMA1_Stream3->CR);

但是下面的代码打印了 DMA1_Stream3->CR 的正确值。

/* *** Other peripheral configurations *** */
RCC->AHB1ENR |= RCC_AHB1ENR_DMA1EN;
__asm__ __volatile__ ("" ::: "memory");                                     
DMA1_Stream3->CR = DMA_SxCR_PL | DMA_SxCR_MINC |                        
        DMA_SxCR_TCIE | DMA_SxCR_TEIE | DMA_SxCR_DMEIE;
DEBUG_PRINTF("%x\r\n", DMA1_Stream3->CR);

我从来不需要为任何其他控制器添加这些内存屏障,所以为什么我必须为这个控制器添加这些内存屏障?我正在考虑由 GCC 重新排序的 load/store 指令或者时间问题。我检查了 CPU (STM32F746) 的勘误表 sheet 或数据 sheet 但没有找到任何东西。

这里是RCC结构体的定义:

typedef struct
{
    /* ... */
    __IO uint32_t AHB1ENR;
    /* ... */
} RCC_TypeDef;

下面是 DMA1_Stream3 结构类型的定义:

typedef struct                                                                  
{                                                                               
  __IO uint32_t CR;     /*!< DMA stream x configuration register      */        
  __IO uint32_t NDTR;   /*!< DMA stream x number of data register     */        
  __IO uint32_t PAR;    /*!< DMA stream x peripheral address register */        
  __IO uint32_t M0AR;   /*!< DMA stream x memory 0 address register   */        
  __IO uint32_t M1AR;   /*!< DMA stream x memory 1 address register   */        
  __IO uint32_t FCR;    /*!< DMA stream x FIFO control register       */        
} DMA_Stream_TypeDef;

__IO 定义为易变的。

下面是为函数生成的汇编代码:

08003f4c <bsp_initSPIADIS>:
 8003f4c:       4956            ldr     r1, [pc, #344]  ; (80040a8 <bsp_initSPIADIS+0x15c>)
 8003f4e:       4a57            ldr     r2, [pc, #348]  ; (80040ac <bsp_initSPIADIS+0x160>)
 8003f50:       6b08            ldr     r0, [r1, #48]   ; 0x30
 8003f52:       f440 7080       orr.w   r0, r0, #256    ; 0x100
 8003f56:       b5f8            push    {r3, r4, r5, r6, r7, lr}
 8003f58:       6308            str     r0, [r1, #48]   ; 0x30
 8003f5a:       2500            movs    r5, #0
 8003f5c:       6810            ldr     r0, [r2, #0]
 8003f5e:       f240 3607       movw    r6, #775        ; 0x307
 8003f62:       4b53            ldr     r3, [pc, #332]  ; (80040b0 <bsp_initSPIADIS+0x164>)
 8003f64:       f44f 5eb8       mov.w   lr, #5888       ; 0x1700
 8003f68:       f020 000c       bic.w   r0, r0, #12
 8003f6c:       4c51            ldr     r4, [pc, #324]  ; (80040b4 <bsp_initSPIADIS+0x168>)
 8003f6e:       4f52            ldr     r7, [pc, #328]  ; (80040b8 <bsp_initSPIADIS+0x16c>)
 8003f70:       6010            str     r0, [r2, #0]
 8003f72:       6810            ldr     r0, [r2, #0]
 8003f74:       f040 0008       orr.w   r0, r0, #8
 8003f78:       6010            str     r0, [r2, #0]
 8003f7a:       6890            ldr     r0, [r2, #8]
 8003f7c:       f020 000c       bic.w   r0, r0, #12
 8003f80:       6090            str     r0, [r2, #8]
 8003f82:       6890            ldr     r0, [r2, #8]
 8003f84:       f040 0004       orr.w   r0, r0, #4
 8003f88:       6090            str     r0, [r2, #8]
 8003f8a:       6890            ldr     r0, [r2, #8]
 8003f8c:       f040 0008       orr.w   r0, r0, #8
 8003f90:       6090            str     r0, [r2, #8]
 8003f92:       6a10            ldr     r0, [r2, #32]
 8003f94:       f020 00f0       bic.w   r0, r0, #240    ; 0xf0
 8003f98:       6210            str     r0, [r2, #32]
 8003f9a:       6a10            ldr     r0, [r2, #32]
 8003f9c:       f040 0010       orr.w   r0, r0, #16
 8003fa0:       6210            str     r0, [r2, #32]
 8003fa2:       6a10            ldr     r0, [r2, #32]
 8003fa4:       f040 0040       orr.w   r0, r0, #64     ; 0x40
 8003fa8:       6210            str     r0, [r2, #32]
 8003faa:       6b08            ldr     r0, [r1, #48]   ; 0x30
 8003fac:       4a43            ldr     r2, [pc, #268]  ; (80040bc <bsp_initSPIADIS+0x170>)
 8003fae:       f040 0002       orr.w   r0, r0, #2
 8003fb2:       6308            str     r0, [r1, #48]   ; 0x30
 8003fb4:       6818            ldr     r0, [r3, #0]
 8003fb6:       f020 5040       bic.w   r0, r0, #805306368      ; 0x30000000
 8003fba:       6018            str     r0, [r3, #0]
 8003fbc:       6818            ldr     r0, [r3, #0]
 8003fbe:       f040 5000       orr.w   r0, r0, #536870912      ; 0x20000000
 8003fc2:       6018            str     r0, [r3, #0]
 8003fc4:       6898            ldr     r0, [r3, #8]
 8003fc6:       f020 5040       bic.w   r0, r0, #805306368      ; 0x30000000
 8003fca:       6098            str     r0, [r3, #8]
 8003fcc:       6898            ldr     r0, [r3, #8]
 8003fce:       f040 5080       orr.w   r0, r0, #268435456      ; 0x10000000
 8003fd2:       6098            str     r0, [r3, #8]
 8003fd4:       6898            ldr     r0, [r3, #8]
 8003fd6:       f040 5000       orr.w   r0, r0, #536870912      ; 0x20000000
 8003fda:       6098            str     r0, [r3, #8]
 8003fdc:       6a58            ldr     r0, [r3, #36]   ; 0x24
 8003fde:       f020 6070       bic.w   r0, r0, #251658240      ; 0xf000000
 8003fe2:       6258            str     r0, [r3, #36]   ; 0x24
 8003fe4:       6a58            ldr     r0, [r3, #36]   ; 0x24
 8003fe6:       f040 7080       orr.w   r0, r0, #16777216       ; 0x1000000
 8003fea:       6258            str     r0, [r3, #36]   ; 0x24
 8003fec:       6a58            ldr     r0, [r3, #36]   ; 0x24
 8003fee:       f040 6080       orr.w   r0, r0, #67108864       ; 0x4000000
 8003ff2:       6258            str     r0, [r3, #36]   ; 0x24
 8003ff4:       6b08            ldr     r0, [r1, #48]   ; 0x30
 8003ff6:       f040 0002       orr.w   r0, r0, #2
 8003ffa:       6308            str     r0, [r1, #48]   ; 0x30
 8003ffc:       6818            ldr     r0, [r3, #0]
 8003ffe:       f020 4040       bic.w   r0, r0, #3221225472     ; 0xc0000000
 8004002:       6018            str     r0, [r3, #0]
 8004004:       6818            ldr     r0, [r3, #0]
 8004006:       f040 4000       orr.w   r0, r0, #2147483648     ; 0x80000000
 800400a:       6018            str     r0, [r3, #0]
 800400c:       6898            ldr     r0, [r3, #8]
 800400e:       f020 4040       bic.w   r0, r0, #3221225472     ; 0xc0000000
 8004012:       6098            str     r0, [r3, #8]
 8004014:       6898            ldr     r0, [r3, #8]
 8004016:       f040 4080       orr.w   r0, r0, #1073741824     ; 0x40000000
 800401a:       6098            str     r0, [r3, #8]
 800401c:       6898            ldr     r0, [r3, #8]
 800401e:       f040 4000       orr.w   r0, r0, #2147483648     ; 0x80000000
 8004022:       6098            str     r0, [r3, #8]
 8004024:       6a58            ldr     r0, [r3, #36]   ; 0x24
 8004026:       f020 4070       bic.w   r0, r0, #4026531840     ; 0xf0000000
 800402a:       6258            str     r0, [r3, #36]   ; 0x24
 800402c:       6a58            ldr     r0, [r3, #36]   ; 0x24
 800402e:       f040 5080       orr.w   r0, r0, #268435456      ; 0x10000000
 8004032:       6258            str     r0, [r3, #36]   ; 0x24
 8004034:       6a58            ldr     r0, [r3, #36]   ; 0x24
 8004036:       f040 4080       orr.w   r0, r0, #1073741824     ; 0x40000000
 800403a:       6258            str     r0, [r3, #36]   ; 0x24
 800403c:       6c0b            ldr     r3, [r1, #64]   ; 0x40
 800403e:       4820            ldr     r0, [pc, #128]  ; (80040c0 <bsp_initSPIADIS+0x174>)
 8004040:       f443 4380       orr.w   r3, r3, #16384  ; 0x4000
 8004044:       640b            str     r3, [r1, #64]   ; 0x40
 8004046:       61e5            str     r5, [r4, #28]
 8004048:       6026            str     r6, [r4, #0]
 800404a:       6823            ldr     r3, [r4, #0]
 800404c:       4e1d            ldr     r6, [pc, #116]  ; (80040c4 <bsp_initSPIADIS+0x178>)
 800404e:       f023 0338       bic.w   r3, r3, #56     ; 0x38
 8004052:       6023            str     r3, [r4, #0]
 8004054:       6823            ldr     r3, [r4, #0]
 8004056:       f043 0338       orr.w   r3, r3, #56     ; 0x38
 800405a:       6023            str     r3, [r4, #0]
 800405c:       f8c4 e004       str.w   lr, [r4, #4]
 8004060:       6b0b            ldr     r3, [r1, #48]   ; 0x30
 8004062:       4c19            ldr     r4, [pc, #100]  ; (80040c8 <bsp_initSPIADIS+0x17c>)
 8004064:       f443 1300       orr.w   r3, r3, #2097152        ; 0x200000
 8004068:       630b            str     r3, [r1, #48]   ; 0x30
 800406a:       603a            str     r2, [r7, #0]
 800406c:       6839            ldr     r1, [r7, #0]
 800406e:       f000 faab       bl      80045c8 <printf>
 8004072:       4b16            ldr     r3, [pc, #88]   ; (80040cc <bsp_initSPIADIS+0x180>)
 8004074:       4629            mov     r1, r5
 8004076:       2203            movs    r2, #3
 8004078:       601c            str     r4, [r3, #0]
 800407a:       2001            movs    r0, #1
 800407c:       f7fe f90e       bl      800229c <xQueueGenericCreate>
 8004080:       4629            mov     r1, r5
 8004082:       6170            str     r0, [r6, #20]
 8004084:       2203            movs    r2, #3
 8004086:       2001            movs    r0, #1
 8004088:       f44f 4480       mov.w   r4, #16384      ; 0x4000
 800408c:       f7fe f906       bl      800229c <xQueueGenericCreate>
 8004090:       4b0f            ldr     r3, [pc, #60]   ; (80040d0 <bsp_initSPIADIS+0x184>)
 8004092:       2240            movs    r2, #64 ; 0x40
 8004094:       f44f 4100       mov.w   r1, #32768      ; 0x8000
 8004098:       6130            str     r0, [r6, #16]
 800409a:       601c            str     r4, [r3, #0]
 800409c:       6019            str     r1, [r3, #0]
 800409e:       f883 230e       strb.w  r2, [r3, #782]  ; 0x30e
 80040a2:       f883 230f       strb.w  r2, [r3, #783]  ; 0x30f
 80040a6:       bdf8            pop     {r3, r4, r5, r6, r7, pc}
 80040a8:       40023800        andmi   r3, r2, r0, lsl #16
 80040ac:       40022000        andmi   r2, r2, r0
 80040b0:       40020400        andmi   r0, r2, r0, lsl #8
 80040b4:       40003800        andmi   r3, r0, r0, lsl #16
 80040b8:       40026058        andmi   r6, r2, r8, asr r0
 80040bc:       00030416        andeq   r0, r3, r6, lsl r4
 80040c0:       08008ec8        stmdaeq r0, {r3, r6, r7, r9, sl, fp, pc}
 80040c4:       2000c2d0        ldrdcs  ip, [r0], -r0
 80040c8:       00030456        andeq   r0, r3, r6, asr r4
 80040cc:       40026070        andmi   r6, r2, r0, ror r0
 80040d0:       e000e100        and     lr, r0, r0, lsl #2

是的,在启用外设时钟的任何操作之后,STM32F4 和 F7 微处理器中都存在错误。需要一点延迟

我通常使用__dsb();。您可以提供此延迟(勘误表中对此进行了描述,但并非针对所有受影响的 uC(实际上我还没有发现任何未受影响的 F4 或 F7))。我个人按照 F4 勘误表中的建议使用 dsb,它让我想起了这个错误。

2.1.5 Delay after an RCC peripheral clock enabling Description A delay between an RCC peripheral clock enable and the effective peripheral enabling should be taken into account in order to manage the peripheral read/write to registers. This delay depends on the peripheral mapping: • If the peripheral is mapped on AHB: the delay should be equal to 2 AHB cycles. • If the peripheral is mapped on APB: the delay should be equal to 1 + (AHB/APB prescaler) cycles. Workarounds 1. Use the DSB instructio n to stall the Cortex ® -M4 CPU pipeline until the instruction is completed. 2. Insert “n” NOPs between the RCC enable bi t write and the peripheral register writes (n = 2 for AHB peripherals, n = 1 + AHB/ APB prescaler in case of APB peripherals). 3. Or simply insert a dummy read operation from the corresponding register just after enabling the peripheral clock.