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]Message
GNUARM weirdness ?
2005-07-19 by DECwiz (Fred van Kempen)
Attachments
- No local attachments were found for this message.