Yahoo Groups archive

Lpc2000

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

Thread

GNUARM weirdness ?

GNUARM weirdness ?

2005-07-19 by DECwiz (Fred van Kempen)

Hi All,
 
I've stumbled into something very weird this weekend, and I can't seem
to figure out what the problem is.  Here is a snippet of code:
 
/* Write a value to a CS8900A I/O register. */
static void
lan_iow(unsigned char *base, int reg, unsigned short val)
{
    unsigned char *p;
    unsigned char x;
 
    /* Write low and high byte of register number. */
    p = (base + reg);
printf(" IOW(%d, %d) P=%08lx\n", reg, val, p);
    x = (val & 0xff);
    *p = x;
    p++;
    x = ((val >> 8) & 0xff);
    *p = x;
printf(" done\n");
}

/* Read data from a CS8900A I/O register. */
static unsigned short
lan_ior(unsigned char *base, int reg)
{
    unsigned char *p;
    unsigned char x;
    unsigned short val;
 
    p = (base + reg);
printf(" IOR(%d) P=%08lx\n", reg, p);
    x = *p;
printf(" IOR(%d) P=%08lx L=%02x\n", reg, p, x);
    val = x;
    x = *(p + 1);
    val |= (x << 8);
printf(" IOR(%d) XXX P=%08lx VAL=%04x\n", reg, p, val);
    return(val);
}

/* Write a value to one of the CS8900A PacketPage registers. */
static void
lan_ppw(unsigned char *base, int reg, unsigned short val)
{
    /* Write low and high byte of register number. */
    lan_iow(base, CSIO_PPTR, (unsigned short)reg);
 
    /* Write low and high byte of value. */
    lan_iow(base, CSIO_PDATA0, val);
}

/* Read data from one of the CS8900A PacketPage registers. */
static unsigned short
lan_ppr(unsigned char *base, int reg)
{
printf("PPR(%d)\n", reg);
    /* Write low and high byte of register number. */
    lan_iow(base, CSIO_PPTR, (unsigned short)reg);
printf(" IOW done\n");
 
    /* Read the low and high bytes of the value. */
    return(lan_ior(base, CSIO_PDATA0));
}
 
This is basically a set of routines to write data from and to the I/O mode
registers of the CS8900A ethernet chip, which is connected to the CPU
over the EMC interface, in 8-bit mode.  The EMC bank is configured as
follows:
 
    /*
     * Put the CS8900A bank in 8-bit mode.
     *
     * IDCY = 1+1 ~ 33ns
     * WST1 = 8+3 (read)  ~183ns
     * WST2 = 6+1 (write) ~ 117ns
     * RBLE = 1 (enable byte lane mode)
     * WP = 0, BM = 0
     */
    BCFG2_bit.MW = 0;
    BCFG2_bit.IDCY = 1;
    BCFG2_bit.WST1 = 8;
    BCFG2_bit.WST2 = 6;
    BCFG2_bit.RBLE = 1;
    BCFG2_bit.WP = 0;
    BCFG2_bit.BM = 0;
 
    /* Enable the A0 line for this (CS2) bank (P3.0 / A0). */
    PINSEL2 |= 0x00804000;
 
which I believe is correct.
 
The above code works fine when compiled with the IAR compiler (which
I normally use, by the way).  However, when trying to make this package
suitable for a friend's use (who uses the GNUARM environment) I found
that things are NOT working.
 
Basically, the driver *hangs*.  It hangs at the lines doing:
 
printf(" IOR(%d) P=%08lx\n", reg, p);
    x = *p;

right after printing the IOR(12) P=8200000C
 
line.  Meaning, it's hanging in the "x = *p" line (whatever is generated by
GCC for that).  Assembler output is useless; the function has been
optimized out (even with -O0.)
 
I checked the schematics, and since there is no IORDY line, the ARM
basically never knows when a memory READ is finished, so it would not
WAIT for it, either....
 
Does anyone know what could cause this ?
 
I *do* have DABORT etc traps installed, and they don't fire.  They do if I
specify "bad" memory addresses above, and the above code also works
OK if I use "real" (RAM) memory.  So its just the dealing with the memory-
mapped range at CS2 that gets messed up....
 
Heeeeelp!
 
--fred
 

__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 

[Non-text portions of this message have been removed]

Re: [lpc2000] GNUARM weirdness ?

2005-07-19 by 42Bastian Schick

DECwiz (Fred van Kempen) <decwiz@...> schrieb am Tue, 19 Jul 2005 
01:14:33 -0700 (PDT):

> Hi All,
>
> I've stumbled into something very weird this weekend, and I can't seem
> to figure out what the problem is.  Here is a snippet of code:
>
> /* Write a value to a CS8900A I/O register. */
> static void
> lan_iow(unsigned char *base, int reg, unsigned short val)
> {
>     unsigned char *p;
>     unsigned char x;
>
>     /* Write low and high byte of register number. */
>     p = (base + reg);
> printf(" IOW(%d, %d) P=%08lx\n", reg, val, p);
>     x = (val & 0xff);
>     *p = x;
>     p++;
>     x = ((val >> 8) & 0xff);
>     *p = x;
> printf(" done\n");
> }

One note: Make pointers volatile otherwise the compiler might do things
_you_ do not intend (like removing code).
This might not be related to your problem.

-- 
42Bastian Schick

Re: [lpc2000] GNUARM weirdness ?

2005-07-20 by Michael Anburaj

Fred,

Compare the assembly code generated by both IAR & gcc
around that piece of code that's causing this or email
me.

And also do you have enaugh stack to handle printf?

Cheers,
-Mike.

--- "DECwiz (Fred van Kempen)" <decwiz@...>
wrote:

> Hi All,
>  
> I've stumbled into something very weird this
> weekend, and I can't seem
> to figure out what the problem is.  Here is a
> snippet of code:
>  
> /* Write a value to a CS8900A I/O register. */
> static void
> lan_iow(unsigned char *base, int reg, unsigned short
> val)
> {
>     unsigned char *p;
>     unsigned char x;
>  
>     /* Write low and high byte of register number.
> */
>     p = (base + reg);
> printf(" IOW(%d, %d) P=%08lx\n", reg, val, p);
>     x = (val & 0xff);
>     *p = x;
>     p++;
>     x = ((val >> 8) & 0xff);
>     *p = x;
> printf(" done\n");
> }
> 
> /* Read data from a CS8900A I/O register. */
> static unsigned short
> lan_ior(unsigned char *base, int reg)
> {
>     unsigned char *p;
>     unsigned char x;
>     unsigned short val;
>  
>     p = (base + reg);
> printf(" IOR(%d) P=%08lx\n", reg, p);
>     x = *p;
> printf(" IOR(%d) P=%08lx L=%02x\n", reg, p, x);
>     val = x;
>     x = *(p + 1);
>     val |= (x << 8);
> printf(" IOR(%d) XXX P=%08lx VAL=%04x\n", reg, p,
> val);
>     return(val);
> }
> 
> /* Write a value to one of the CS8900A PacketPage
> registers. */
> static void
> lan_ppw(unsigned char *base, int reg, unsigned short
> val)
> {
>     /* Write low and high byte of register number.
> */
>     lan_iow(base, CSIO_PPTR, (unsigned short)reg);
>  
>     /* Write low and high byte of value. */
>     lan_iow(base, CSIO_PDATA0, val);
> }
> 
> /* Read data from one of the CS8900A PacketPage
> registers. */
> static unsigned short
> lan_ppr(unsigned char *base, int reg)
> {
> printf("PPR(%d)\n", reg);
>     /* Write low and high byte of register number.
> */
>     lan_iow(base, CSIO_PPTR, (unsigned short)reg);
> printf(" IOW done\n");
>  
>     /* Read the low and high bytes of the value. */
>     return(lan_ior(base, CSIO_PDATA0));
> }
>  
> This is basically a set of routines to write data
> from and to the I/O mode
> registers of the CS8900A ethernet chip, which is
> connected to the CPU
> over the EMC interface, in 8-bit mode.  The EMC bank
> is configured as
> follows:
>  
>     /*
>      * Put the CS8900A bank in 8-bit mode.
>      *
>      * IDCY = 1+1 ~ 33ns
>      * WST1 = 8+3 (read)  ~183ns
>      * WST2 = 6+1 (write) ~ 117ns
>      * RBLE = 1 (enable byte lane mode)
>      * WP = 0, BM = 0
>      */
>     BCFG2_bit.MW = 0;
>     BCFG2_bit.IDCY = 1;
>     BCFG2_bit.WST1 = 8;
>     BCFG2_bit.WST2 = 6;
>     BCFG2_bit.RBLE = 1;
>     BCFG2_bit.WP = 0;
>     BCFG2_bit.BM = 0;
>  
>     /* Enable the A0 line for this (CS2) bank (P3.0
> / A0). */
>     PINSEL2 |= 0x00804000;
>  
> which I believe is correct.
>  
> The above code works fine when compiled with the IAR
> compiler (which
> I normally use, by the way).  However, when trying
> to make this package
> suitable for a friend's use (who uses the GNUARM
> environment) I found
> that things are NOT working.
>  
> Basically, the driver *hangs*.  It hangs at the
> lines doing:
>  
> printf(" IOR(%d) P=%08lx\n", reg, p);
>     x = *p;
> 
> right after printing the IOR(12) P=8200000C
>  
> line.  Meaning, it's hanging in the "x = *p" line
> (whatever is generated by
> GCC for that).  Assembler output is useless; the
> function has been
> optimized out (even with -O0.)
>  
> I checked the schematics, and since there is no
> IORDY line, the ARM
> basically never knows when a memory READ is
> finished, so it would not
> WAIT for it, either....
>  
> Does anyone know what could cause this ?
>  
> I *do* have DABORT etc traps installed, and they
> don't fire.  They do if I
> specify "bad" memory addresses above, and the above
> code also works
> OK if I use "real" (RAM) memory.  So its just the
> dealing with the memory-
> mapped range at CS2 that gets messed up....
>  
> Heeeeelp!
>  
> --fred
>  
> 
> __________________________________________________
> Do You Yahoo!?
> Tired of spam?  Yahoo! Mail has the best spam
> protection around 
> http://mail.yahoo.com 
> 
> [Non-text portions of this message have been
> removed]
> 
> 



		
____________________________________________________
Start your day with Yahoo! - make it your home page 
http://www.yahoo.com/r/hs

SOLVED! Re: [lpc2000] GNUARM weirdness ?

2005-07-20 by DECwiz (Fred van Kempen)

All,
 
The problem has been solved.  As Michael suggested:

> Compare the assembly code generated by both IAR & gcc
> around that piece of code that's causing this or email
> me.

this is exactly what I did most of last night.  The assembler

output looked similar, and, to me, with only x86/PDP11/VAX

assembler knowledge, looked sane.  Indeed, LDRB instructions

were used, so that was fine.

I still don't have JTAG debugging working, so debugging at that

level is kinda hard.  I decided to just write handlers for the

various exceptions, and then use carefully-placed .word 0xdeadbeef

opcodes to cause an unknown-opcode trap.  This proved that it was,

indeed, HANGING at the "ldrb  r3, [r3, #0]" instruction, aka the

"val = *p" line in the example posted earlier.

 

Since the registers looked fine, and the assembler code was very

similar, this could therefore NOT be the cause of the problem.

 

Further checking revealed, that something else was wrong: I was

using bitfield structures to reference (and initialize) the BCFG2 register.  A printf() on its contents (both in the GNUARM and IAR

versions) showed a major difference.  I changed that code to just

do something like:

 

BCFG2 = 0x00003501;

 

(which is what the value ended up as in the IAR code) and YAY, that

did the trick.  

 

So... the bitfield structures don't seem to work with GCC, which I can live with now I know it...

 

Problem resolved!

 
> And also do you have enaugh stack to handle printf?
Yes, I use my own C library which has a very good _doprnt(),
printf() and sprintf() trio, using very little space, including
stack.
 
Cheers,
 
Fred

--- "DECwiz (Fred van Kempen)" <decwiz@...>
wrote:

> Hi All,
>  
> I've stumbled into something very weird this
> weekend, and I can't seem
> to figure out what the problem is.  Here is a
> snippet of code:
>  
> /* Write a value to a CS8900A I/O register. */
> static void
> lan_iow(unsigned char *base, int reg, unsigned short
> val)
> {
>     unsigned char *p;
>     unsigned char x;
>  
>     /* Write low and high byte of register number.
> */
>     p = (base + reg);
> printf(" IOW(%d, %d) P=%08lx\n", reg, val, p);
>     x = (val & 0xff);
>     *p = x;
>     p++;
>     x = ((val >> 8) & 0xff);
>     *p = x;
> printf(" done\n");
> }
> 
> /* Read data from a CS8900A I/O register. */
> static unsigned short
> lan_ior(unsigned char *base, int reg)
> {
>     unsigned char *p;
>     unsigned char x;
>     unsigned short val;
>  
>     p = (base + reg);
> printf(" IOR(%d) P=%08lx\n", reg, p);
>     x = *p;
> printf(" IOR(%d) P=%08lx L=%02x\n", reg, p, x);
>     val = x;
>     x = *(p + 1);
>     val |= (x << 8);
> printf(" IOR(%d) XXX P=%08lx VAL=%04x\n", reg, p,
> val);
>     return(val);
> }
> 
> /* Write a value to one of the CS8900A PacketPage
> registers. */
> static void
> lan_ppw(unsigned char *base, int reg, unsigned short
> val)
> {
>     /* Write low and high byte of register number.
> */
>     lan_iow(base, CSIO_PPTR, (unsigned short)reg);
>  
>     /* Write low and high byte of value. */
>     lan_iow(base, CSIO_PDATA0, val);
> }
> 
> /* Read data from one of the CS8900A PacketPage
> registers. */
> static unsigned short
> lan_ppr(unsigned char *base, int reg)
> {
> printf("PPR(%d)\n", reg);
>     /* Write low and high byte of register number.
> */
>     lan_iow(base, CSIO_PPTR, (unsigned short)reg);
> printf(" IOW done\n");
>  
>     /* Read the low and high bytes of the value. */
>     return(lan_ior(base, CSIO_PDATA0));
> }
>  
> This is basically a set of routines to write data
> from and to the I/O mode
> registers of the CS8900A ethernet chip, which is
> connected to the CPU
> over the EMC interface, in 8-bit mode.  The EMC bank
> is configured as
> follows:
>  
>     /*
>      * Put the CS8900A bank in 8-bit mode.
>      *
>      * IDCY = 1+1 ~ 33ns
>      * WST1 = 8+3 (read)  ~183ns
>      * WST2 = 6+1 (write) ~ 117ns
>      * RBLE = 1 (enable byte lane mode)
>      * WP = 0, BM = 0
>      */
>     BCFG2_bit.MW = 0;
>     BCFG2_bit.IDCY = 1;
>     BCFG2_bit.WST1 = 8;
>     BCFG2_bit.WST2 = 6;
>     BCFG2_bit.RBLE = 1;
>     BCFG2_bit.WP = 0;
>     BCFG2_bit.BM = 0;
>  
>     /* Enable the A0 line for this (CS2) bank (P3.0
> / A0). */
>     PINSEL2 |= 0x00804000;
>  
> which I believe is correct.
>  
> The above code works fine when compiled with the IAR
> compiler (which
> I normally use, by the way).  However, when trying
> to make this package
> suitable for a friend's use (who uses the GNUARM
> environment) I found
> that things are NOT working.
>  
> Basically, the driver *hangs*.  It hangs at the
> lines doing:
>  
> printf(" IOR(%d) P=%08lx\n", reg, p);
>     x = *p;
> 
> right after printing the IOR(12) P=8200000C
>  
> line.  Meaning, it's hanging in the "x = *p" line
> (whatever is generated by
> GCC for that).  Assembler output is useless; the
> function has been
> optimized out (even with -O0.)
>  
> I checked the schematics, and since there is no
> IORDY line, the ARM
> basically never knows when a memory READ is
> finished, so it would not
> WAIT for it, either....
>  
> Does anyone know what could cause this ?
>  
> I *do* have DABORT etc traps installed, and they
> don't fire.  They do if I
> specify "bad" memory addresses above, and the above
> code also works
> OK if I use "real" (RAM) memory.  So its just the
> dealing with the memory-
> mapped range at CS2 that gets messed up....
>  
> Heeeeelp!
>  
> --fred
>  
> 
> __________________________________________________
> Do You Yahoo!?
> Tired of spam?  Yahoo! Mail has the best spam
> protection around 
> http://mail.yahoo.com 
> 
> [Non-text portions of this message have been
> removed]
> 
> 



            
____________________________________________________
Start your day with Yahoo! - make it your home page 
http://www.yahoo.com/r/hs 




SPONSORED LINKS 

Microcontrollers Microprocessor Intel microprocessors Pic microcontrollers 



---------------------------------
YAHOO! GROUPS LINKS 




    Visit your group "lpc2000" on the web.
  
    To unsubscribe from this group, send an email to:
 lpc2000-unsubscribe@yahoogroups.com
  
    Your use of Yahoo! Groups is subject to the Yahoo! Terms of Service. 


---------------------------------



		
---------------------------------
 Start your day with Yahoo! - make it your home page 

[Non-text portions of this message have been removed]

Re: SOLVED! Re: [lpc2000] GNUARM weirdness ?

2005-07-21 by 42Bastian Schick

DECwiz (Fred van Kempen) <decwiz@...> schrieb am Wed, 20 Jul 2005 
14:26:01 -0700 (PDT):


> Further checking revealed, that something else was wrong: I was
>
> using bitfield structures to reference (and initialize) the BCFG2 
> register.  A printf() on its contents (both in the GNUARM and IAR
> versions) showed a major difference.  I changed that code to just
> ...
>
> So... the bitfield structures don't seem to work with GCC, which I can 
> live with now I know it...

The order how the bits are stored in a bitfield is not defined by standard.
This might be the reason, why gcc writes a different value than IAR.

-- 
42Bastian Schick

Re: SOLVED! Re: [lpc2000] GNUARM weirdness ?

2005-07-21 by Arie de Muynck

> > DECwiz (Fred van Kempen) :
> > Further checking revealed, that something else was wrong: I was
> >
> > using bitfield structures to reference (and initialize) the BCFG2
> > register.  A printf() on its contents (both in the GNUARM and IAR
> > versions) showed a major difference.  I changed that code to just
> > ...
> >
> > So... the bitfield structures don't seem to work with GCC, which I can
> > live with now I know it...
>
> The order how the bits are stored in a bitfield is not defined by
standard.
> This might be the reason, why gcc writes a different value than IAR.
>
> -- 
> 42Bastian Schick


No, it is a different (and known) problem.

The GCC compiler will use a byte or word16 access to set/clear a small field
in the word32: and that will fail on an I/O register that can only be read
or written 32 bits at a time.
You could do the bitfield operations on a copy in RAM, then write the
complete value to the register.

Bit me too (pun intended).

Arie de Muynck

Re: SOLVED! Re: [lpc2000] GNUARM weirdness ?

2005-07-21 by 42Bastian Schick

Arie de Muynck <mygroups@...> schrieb am Thu, 21 Jul 2005 07:14:08 
+0200:
>
> No, it is a different (and known) problem.

Not to me, thank you

>
> The GCC compiler will use a byte or word16 access to set/clear a small 
> field
> in the word32: and that will fail on an I/O register that can only be 
> read
> or written 32 bits at a time.
> You could do the bitfield operations on a copy in RAM, then write the
> complete value to the register.

I'll keep an eye on it (have some legacy code which
still uses bitfields).
-- 
42Bastian Schick

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.