【问题标题】:Is gcc reordering my volatile variables?gcc 是否重新排序了我的 volatile 变量?
【发布时间】:2017-08-17 04:32:58
【问题描述】:

我正在使用 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 重新排序的加载/存储指令或时间问题。我检查了 CPU (STM32F746) 或数据表的勘误表,但没有找到任何东西。

这里是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 被定义为 volatile。

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

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

【问题讨论】:

  • 跨编译域使用结构可能会导致失败。我知道这是当前的时尚,但它会过去的......
  • 顺便说一句,你有什么问题?
  • 这可能是控制器启动所需时间的时间限制。如果 RCC_AHB1ENR_DMA1EN 是 256 或 0x100,则 GCC NOT 在您的汇编器中重新排序。我建议在启用和写入之间添加延迟。控制器内存的地址将帮助人们理解编译器汇编器,除非您希望有人非常熟悉您的控制器来回答这里。即RCCDMA1_Stream3的物理地址。
  • RCC base address is 0x40023800, DMA1_Stream3 base address is 0x40026058 Also, here is the values used in those structures: RCC_AHB1ENR_DMA1EN = 0x00200000, DMA_SxCR_PL = 0x00030000, DMA_SxCR_MINC = 0x00000400, DMA_SxCR_TCIE = 0x00000010, DMA_SxCR_TEIE = 0x00000002, DMA_SxCR_DMEIE = 0x00000001
  • 你启用缓存了吗?

标签: gcc optimization arm volatile cortex-m


【解决方案1】:

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

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

2.1.5 RCC 外设时钟使能后的延迟 说明 RCC 外设时钟使能与有效之间的延迟 应考虑外围启用,以便管理 外设读/写寄存器。这种延迟取决于 外设映射: • 如果外设映射到 AHB:延迟 应等于 2 个 AHB 周期。 • 如果外设映射到 APB: 延迟应等于 1 + (AHB/APB 预分频器) 周期。 解决方法 1. 使用 DSB 指令停止 Cortex ® -M4 CPU 流水线直到指令完成。 2. 在 RCC 使能位写入和外设寄存器写入之间插入“n”个 NOP(对于 AHB 外设,n = 2,n = 1 + AHB/ APB 外设的情况下的 APB 预分频器)。 3. 或者只是在启用外设时钟后从相应的寄存器中插入一个虚拟读操作。

【讨论】:

  • 完全正确!非常感谢。阅读您的答案后,我查看了 STM32F7 HAL,发现他们在设置 DMA1EN 位后添加了一个虚拟读取。
猜你喜欢
  • 2018-09-01
  • 1970-01-01
  • 2016-01-06
  • 2019-06-02
  • 2011-08-30
  • 1970-01-01
  • 2014-10-22
  • 2013-01-18
相关资源
最近更新 更多