Yahoo Groups archive

Lpc2000

Index last updated: 2026-04-28 23:31 UTC

Thread

[LPC2104] hardware bug...

[LPC2104] hardware bug...

2004-09-09 by Pawel Sikora

# 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?



		
__________________________________
Do you Yahoo!?
Read only the mail you want - Yahoo! Mail SpamGuard.
http://promotions.yahoo.com/new_mail

RE: [lpc2000] [LPC2104] hardware bug...

2004-09-09 by Paul Curtis

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.

Re: [lpc2000] [LPC2104] hardware bug...

2004-09-09 by Arie de Muynck

> > 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;

The problem here is that gcc for bit field access will generate 8/16/32 bits
access depending on the width of the bit field. This is allowed for memory
based operations if the memeory accepts 8/1/632 bit transfers (most
configurations do), but deadly in case of I/O registers that can only be
written 32 bits at a time.

We have seen large projects where the original sources with I/O as bitfields
(ADS or Greenhills compiler) were all rewritten into macro's for use with
the GCC toolchain.
We also stay safely with that method   ;-)

Regards,
Arie de Muynck

Move to quarantaine

This moves the raw source file on disk only. The archive index is not changed automatically, so you still need to run a manual refresh afterward.