Gcc 为什么对内存映射外围寄存器的写入未执行操作(LPC43xx)?

Gcc 为什么对内存映射外围寄存器的写入未执行操作(LPC43xx)?,gcc,arm,embedded,nxp-microcontroller,Gcc,Arm,Embedded,Nxp Microcontroller,我正在为NXP LPC4330(Arm Cortex M0/M4双核)构建一个应用程序。我正在使用arm none eabi gcc 4.9.3进行编译。在我的代码中的某一点上,我正在执行对(32位)内存位置的写入。紧接着,如果我从那个内存位置读回数据,大约十分之一的结果表明写操作没有发生。在以后的时间进行的后续读取指示相同的情况,因此这不是一个瞬态条件。中断在全局级别被禁用,并且编译器生成的汇编器显然正在尝试写操作,那么写操作怎么可能没有被执行呢 具体地说,我正在写入SLICE_MUX_CFG

我正在为NXP LPC4330(Arm Cortex M0/M4双核)构建一个应用程序。我正在使用arm none eabi gcc 4.9.3进行编译。在我的代码中的某一点上,我正在执行对(32位)内存位置的写入。紧接着,如果我从那个内存位置读回数据,大约十分之一的结果表明写操作没有发生。在以后的时间进行的后续读取指示相同的情况,因此这不是一个瞬态条件。中断在全局级别被禁用,并且编译器生成的汇编器显然正在尝试写操作,那么写操作怎么可能没有被执行呢

具体地说,我正在写入SLICE_MUX_CFG0,它是SGPIO外围设备中的内存映射寄存器。当写入工作时,外围设备正常工作。当读回指示写入未工作时,外围设备无法正常工作。因此,如回读所示,所述寄存器的设置似乎不正确

查看.asm(如下所列),写操作是明确的。当我事后读回该值时,它的读数为零,考虑到下面的列表,这在我看来是不可能的。如果我在写之前立即执行读操作(请参见下面的.c清单),问题就会消失,这可能是一个线索

那么上面所说的是什么?这是否违反了内存总线的使用规则?我已经查看了GCC bug列表,没有看到任何与此相关的内容

下面的函数包括源代码和ASM,并带有一些注释。这里会发生什么?为什么写入“存储值”显然没有任何效果

20000f7c <camera_SGPIO_init_sub>:
; disable interrupts globally
20000f7c:   b672        cpsid   i
20000f7e:   2346        movs    r3, #70 ; 0x46
20000f80:   4a16        ldr r2, [pc, #88]   ; (20000fdc <camera_SGPIO_init_sub+0x60>)
20000f82:   6013        str r3, [r2, #0]
20000f84:   4a16        ldr r2, [pc, #88]   ; (20000fe0 <camera_SGPIO_init_sub+0x64>)
20000f86:   6013        str r3, [r2, #0]
20000f88:   4a16        ldr r2, [pc, #88]   ; (20000fe4 <camera_SGPIO_init_sub+0x68>)
20000f8a:   6013        str r3, [r2, #0]
20000f8c:   4a16        ldr r2, [pc, #88]   ; (20000fe8 <camera_SGPIO_init_sub+0x6c>)
20000f8e:   6013        str r3, [r2, #0]
20000f90:   4a16        ldr r2, [pc, #88]   ; (20000fec <camera_SGPIO_init_sub+0x70>)
20000f92:   3301        adds    r3, #1
20000f94:   6013        str r3, [r2, #0]
20000f96:   4a16        ldr r2, [pc, #88]   ; (20000ff0 <camera_SGPIO_init_sub+0x74>)
20000f98:   6013        str r3, [r2, #0]
20000f9a:   4a16        ldr r2, [pc, #88]   ; (20000ff4 <camera_SGPIO_init_sub+0x78>)
20000f9c:   6013        str r3, [r2, #0]
20000f9e:   4a16        ldr r2, [pc, #88]   ; (20000ff8 <camera_SGPIO_init_sub+0x7c>)
20000fa0:   6013        str r3, [r2, #0]
20000fa2:   4a16        ldr r2, [pc, #88]   ; (20000ffc <camera_SGPIO_init_sub+0x80>)
20000fa4:   6013        str r3, [r2, #0]
20000fa6:   2240        movs    r2, #64 ; 0x40
20000fa8:   4b15        ldr r3, [pc, #84]   ; (20001000 <camera_SGPIO_init_sub+0x84>)
20000faa:   601a        str r2, [r3, #0]
20000fac:   2290        movs    r2, #144    ; 0x90
20000fae:   4b15        ldr r3, [pc, #84]   ; (20001004 <camera_SGPIO_init_sub+0x88>)
20000fb0:   0512        lsls    r2, r2, #20
20000fb2:   601a        str r2, [r3, #0]
; load value
20000fb4:   23c6        movs    r3, #198    ; 0xc6
; load destination address
20000fb6:   4a14        ldr r2, [pc, #80]   ; (20001008 <camera_SGPIO_init_sub+0x8c>)
; store value
20000fb8:   6013        str r3, [r2, #0]
; read value back
20000fba:   6810        ldr r0, [r2, #0]
20000fbc:   4a13        ldr r2, [pc, #76]   ; (2000100c <camera_SGPIO_init_sub+0x90>)
20000fbe:   6013        str r3, [r2, #0]
20000fc0:   4a13        ldr r2, [pc, #76]   ; (20001010 <camera_SGPIO_init_sub+0x94>)
20000fc2:   6013        str r3, [r2, #0]
20000fc4:   4a13        ldr r2, [pc, #76]   ; (20001014 <camera_SGPIO_init_sub+0x98>)
20000fc6:   6013        str r3, [r2, #0]
20000fc8:   4a13        ldr r2, [pc, #76]   ; (20001018 <camera_SGPIO_init_sub+0x9c>)
20000fca:   6013        str r3, [r2, #0]
20000fcc:   4a13        ldr r2, [pc, #76]   ; (2000101c <camera_SGPIO_init_sub+0xa0>)
20000fce:   6013        str r3, [r2, #0]
20000fd0:   4a13        ldr r2, [pc, #76]   ; (20001020 <camera_SGPIO_init_sub+0xa4>)
20000fd2:   6013        str r3, [r2, #0]
20000fd4:   4a13        ldr r2, [pc, #76]   ; (20001024 <camera_SGPIO_init_sub+0xa8>)
20000fd6:   6013        str r3, [r2, #0]
; enable interrupts globally
20000fd8:   b662        cpsie   i
20000fda:   4770        bx  lr
20000fdc:   40086480    .word   0x40086480
20000fe0:   40086484    .word   0x40086484
20000fe4:   40086488    .word   0x40086488
20000fe8:   40086494    .word   0x40086494
20000fec:   40086380    .word   0x40086380
20000ff0:   40086384    .word   0x40086384
20000ff4:   40086388    .word   0x40086388
20000ff8:   4008639c    .word   0x4008639c
20000ffc:   40086208    .word   0x40086208
20001000:   40086204    .word   0x40086204
20001004:   40050064    .word   0x40050064
20001008:   40101080    .word   0x40101080
2000100c:   401010a0    .word   0x401010a0
20001010:   40101090    .word   0x40101090
20001014:   401010a4    .word   0x401010a4
20001018:   40101088    .word   0x40101088
2000101c:   401010a8    .word   0x401010a8
20001020:   40101094    .word   0x40101094
20001024:   401010ac    .word   0x401010ac
20000f7c:
; 全局禁用中断
20000f7c:b672 cpsid i
20000f7e:2346 MOV r3,#70;0x46
20000f80:4a16 ldr r2,[pc,#88];(20000fdc)
20000f82:6013 str r3[r2,#0]
20000f84:4a16 ldr r2,[pc,#88];(20000fe0)
20000f86:6013 str r3[r2,#0]
20000f88:4a16 ldr r2,[pc,#88];(20000fe4)
20000f8a:6013 str r3[r2,#0]
20000f8c:4a16 ldr r2,[pc,#88];(20000fe8)
20000f8e:6013STRR3[r2,#0]
20000f90:4a16 ldr r2,[pc,#88];(20000fec)
20000f92:3301加上r3,#1
20000f94:6013街r3[r2,#0]
20000f96:4a16 ldr r2,[pc,#88];(20000ff0)
20000f98:6013 str r3[r2,#0]
20000f9a:4a16 ldr r2,[pc,#88];(20000ff4)
20000f9c:6013 str r3[r2,#0]
20000f9e:4a16 ldr r2,[pc,#88];(20000ff8)
20000fa0:6013 str r3[r2,#0]
20000fa2:4a16 ldr r2,[pc,#88];(20000ffc)
20000fa4:6013 str r3[r2,#0]
20000fa6:2240 movs r2,#64;0x40
20000fa8:4b15 ldr r3,[pc,#84];(20001000 )
20000faa:601a str r2[r3,#0]
20000fac:2290 movs r2,#144;0x90
20000fae:4b15 ldr r3,[pc,#84];(20001004 )
20000fb0:0512 lsls r2,r2,#20
20000fb2:601a str r2[r3,#0]
; 负荷值
20000fb4:23c6 movs r3,#198;0xc6
; 加载目标地址
20000fb6:4a14 ldr r2,[pc,#80];(20001008 )
; 存储值
20000fb8:6013 str r3[r2,#0]
; 读回值
20000fba:6810 ldr r0,[r2,#0]
20000fbc:4a13 ldr r2,[pc,#76];(2000100c)
20000fbe:6013 str r3[r2,#0]
20000fc0:4a13 ldr r2,[pc,#76];(20001010 )
20000fc2:6013 str r3[r2,#0]
20000fc4:4a13 ldr r2,[pc,#76];(20001014 )
20000fc6:6013 str r3[r2,#0]
20000fc8:4a13 ldr r2,[pc,#76];(20001018 )
20000fca:6013 str r3[r2,#0]
20000fcc:4a13 ldr r2,[pc,#76];(2000101c)
20000fce:6013 str r3[r2,#0]
20000fd0:4a13 ldr r2,[pc,#76];(20001020 )
20000fd2:6013 str r3[r2,#0]
20000fd4:4a13 ldr r2,[pc,#76];(20001024 )
20000fd6:6013 str r3[r2,#0]
; 全局启用中断
20000fd8:b662 cpsie i
20000fda:4770 bx lr
20000fdc:40086480。字0x40086480
20000fe0:40086484。字0x40086484
20000fe4:40086488。字0x40086488
20000fe8:40086494。字0x40086494
20000fec:40086380。字0x40086380
20000ff0:40086384.字0x40086384
20000ff4:40086388。字0x40086388
20000ff8:4008639c。字0x4008639c
20000ffc:40086208。字0x40086208
20001000:40086204.字0x40086204
20001004:40050064.字0x40050064
2000008:4010100.字0x4010100
200000C:401010a0.字0x401010a0
20001010:40101090.字0x40101090
20001014:401010a4。字0x401010a4
20001018:40101088.字0x40101088
2000101c:401010 A8.字0x401010 A8
20001020:40101094.字0x40101094
200001024:401010交流电。字0x401010交流电
编译成上述代码的C代码如下

volatile uint32_t vol_dummy_for_read;
#define __SFS(addr, value) *((volatile uint32_t*)addr) = value;
#define SGPIO_SLICE_MUX_CFG0 (*((volatile uint32_t*)  ... some address ... ))

uint32_t camera_SGPIO_init_sub()
{
    __asm volatile ("cpsid i" : : : "memory");

    //  configure pins to SGPIO
    __SFS(P9_0, SCU_SFS_INPUT | 6); // D0, SGPIO0
    __SFS(P9_1, SCU_SFS_INPUT | 6);
    __SFS(P9_2, SCU_SFS_INPUT | 6);
    __SFS(P9_5, SCU_SFS_INPUT | 6);
    __SFS(P7_0, SCU_SFS_INPUT | 7);
    __SFS(P7_1, SCU_SFS_INPUT | 7);
    __SFS(P7_2, SCU_SFS_INPUT | 7);
    __SFS(P7_7, SCU_SFS_INPUT | 7); // D7, SGPIO7

    //  SGPIO8
    __SFS(P4_2, SCU_SFS_INPUT | 7); // PCLK, SGPIO8

    //  configure pins to GPIO
    __SFS(P4_1, SCU_SFS_INPUT | 0); // HSYNC, GPIO2[1]

    //  bring SGPIO clock up to full speed (same as PLL1, M4)
    CGU_BASE_PERIPH_CLK = (0 << 1) | (0 << 11) | (9 << 24);

    //  SLICE_MUX_CFG
    uint32_t SLICE_MUX_CFG_VALUE =
          (1 << 1) /* clock on falling edge */
        | (1 << 2) /* clock from external pin */
        | (3 << 6) /* shift 8 bytes per clock */
        ;

////    see note above (this fixes it)
//vol_dummy_for_read = SGPIO_SLICE_MUX_CFG0 ;

    SGPIO_SLICE_MUX_CFG0  = SLICE_MUX_CFG_VALUE; // A
    uint32_t ret = SGPIO_SLICE_MUX_CFG0;
    SGPIO_SLICE_MUX_CFG8  = SLICE_MUX_CFG_VALUE; // I
    SGPIO_SLICE_MUX_CFG4  = SLICE_MUX_CFG_VALUE; // E
    SGPIO_SLICE_MUX_CFG9  = SLICE_MUX_CFG_VALUE; // J
    SGPIO_SLICE_MUX_CFG2  = SLICE_MUX_CFG_VALUE; // C
    SGPIO_SLICE_MUX_CFG10 = SLICE_MUX_CFG_VALUE; // K
    SGPIO_SLICE_MUX_CFG5  = SLICE_MUX_CFG_VALUE; // F
    SGPIO_SLICE_MUX_CFG11 = SLICE_MUX_CFG_VALUE; // L

    __asm volatile ("cpsie i" : : : "memory");

    return ret;
}
volatile uint32\u t volu\u dummy\u用于读取;
#定义u SFS(addr,value)*((volatile uint32_t*)addr)=值;
#定义SGPIO_SLICE_MUX_CFG0(*(易失性uint32_t*)…某些地址…)
uint32_t摄像头_SGPIO_init_sub()
{
__asm易失性(“cpsid i”:“内存”);
//将管脚配置为SGPIO
__SFS(P9_0,SCU_SFS_输入| 6);//D0,SGPIO0
__SFS(P9_1,SCU_SFS_输入| 6);
__SFS(P9_2,SCU_SFS_输入| 6);
__SFS(P9_5,SCU_SFS_输入| 6);
__SFS(P7_0,SCU_SFS_输入| 7);
__SFS(P7_1,SCU_SFS_输入| 7);
__SFS(P7|2,SCU|SFS|U输入| 7);
__SFS(P7_7,SCU_SFS_输入| 7);//D7,SGPIO7
//SGPIO8
__SFS(P4_2,SCU_SFS_输入| 7);//PCLK,SGPIO8
//将管脚配置为GPIO
__SFS(P4_1,SCU_SFS_输入| 0);//HSYNC,GPIO2[1]
//使SGPIO时钟达到全速(与PLL1、M4相同)
CGU_BASE_PERIPH_CLK=(0(我在回答我自己的问题;这个答案是根据t