Pawel,
> # a simple testcase #
>
> typedef volatile unsigned int reg32;
>
> #define __DECLARE_IO_REG32_BIT(name) \
> typedef volatile union { \
> name##_bits bit; \
> reg32 reg; \
> } name##_bits_t
>
> typedef struct {
> reg32 MR0INT :1;
> reg32 MR0RES :1;
> reg32 MR0STOP :1;
> reg32 MR1INT :1;
> reg32 MR1RES :1;
> reg32 MR1STOP :1;
> reg32 MR2INT :1;
> reg32 MR2RES :1;
> reg32 MR2STOP :1;
> reg32 MR3INT :1;
> reg32 MR3RES :1;
> reg32 MR3STOP :1;
> reg32 :20;
> } __mcr_bits;
>
> __DECLARE_IO_REG32_BIT(__mcr);
>
> #define T0MCR (*(__mcr_bits_t *)0xE0004014)
>
> void test()
> {
> T0MCR.reg = 0x00000000; // dumpT0MCR -> 0x00000000
> /* disassembled code
> mov r2, #-536870912
> add r2, r2, #16384
> add r2, r2, #20
> mov r3, #0
> str r3, [r2, #0] // r2 == 0xe0004014
> */
> #if 0
> T0MCR.reg |= 0x01; // dumpT0MCR -> 0x00000001
> T0MCR.reg |= 0x02; // dumpT0MCR -> 0x00000003
> /* disassembled code
> ldr r3, [r2, #0]
> orr r3, r3, #1
> str r3, [r2, #0]
> ldr r3, [r2, #0]
> orr r3, r3, #2
> str r3, [r2, #0]
> */
> #else
> T0MCR.bit.MR0INT = 1; // dumpT0MCR -> 0x00000101
> T0MCR.bit.MR0RES = 1; // dumpT0MCR -> 0x00000303
> /* disassembled code
> ldrb r3, [r2, #0]
> orr r3, r3, #1
> strb r3, [r2, #0]
> ldrb r3, [r2, #0]
> orr r3, r3, #2
> strb r3, [r2, #0]
> */
> #endif
> }
>
> # possible STRB behaviour (tested with T0MCR and T0IR) #
>
> [address][7:0] = Rn[7:0]
> [address][15:8]= Rn[7:0]
>
> Could anyone confirm this?
Combination of compiler and ARM is your problem. The registers need to
be accessed as 32-bit data, they can't be accessed as byte-wise data.
Hence, the LDRB and STRB are not correct for the peripheral registers.
How you convince GCC to generate word accesses in this case, I'm not
sure, but it's got more options than a nuclear power station, so there
must be one somewhere to say "don't narrow".
-- Paul.Message
RE: [lpc2000] [LPC2104] hardware bug...
2004-09-09 by Paul Curtis
Attachments
- No local attachments were found for this message.