HELP

Abraham vd Merwe
2001-06-07T08:58:42Z

[-- Attachment #1: Type: text/plain, Size: 7661 bytes --]

Hi!

I'm busy debugging my chip driver for 28Fxx... chips in LART and I got this
problem with one of my tests:

------------< snip <------< snip <------< snip <------------
root@tinystor:~# ./mtd_debug write 2 6 /dev/zero
MTD_open
MTD_write
flash_write(to = 0x00000002, len = 6)
write_dword(): 0x00000000 <- 0x0000ffff
mtd_debug: Unaligned memory access at pc=0xca005644, lr=0xc001dc08 (bad
address=0xc0135d82, cod)
Internal error: alignment exception: 0
CPU: 0
pc : [<ca005644>] lr : [<c001dc08>]
sp : c9635f10 ip : c9635f54 fp : c9635f44
r10: c0135d82 r9 : 00000000 r8 : 00000004
r7 : c0135d82 r6 : 00000002 r5 : 00000004 r4 : 00000000
r3 : 00000002 r2 : 00000004 r1 : ca005adc r0 : ca005ac0
Flags: nzCv IRQs on FIQs on Mode SVC_32 Segment user
Control: C075117F Table: C075117F DAC: 00000015
Process mtd_debug (pid: 273, stackpage=c9635000)
Code: e59f10c0 e1a02008 (e49a3004) e2455004 eb00020f
Stack:
c9635f00: c001dc08 ca005644 20000013 ffffffff 00000002 00000000 0000ffff
00000006
c9635f20: c0135d80 00000000 00000006 c00116e0 c011bec0 0200d800 c9635f80
c9635f48
c9635f40: ca002648 ca0054b0 c9635f54 c0135d80 00000000 00000002 c00116c0
ffffffea
c9635f60: 00000000 00000006 0200d800 00000004 bfffff30 c9635fac c9635f84
c003f48c
c9635f80: ca0024e4 c00180bc c003ee5c 0200d800 0200d810 20000010 00000002
c0012804
c9635fa0: 00000000 c9635fb0 c0012680 c003f3bc 0200d800 c0018690 00000003
0200d800
c9635fc0: 00000006 ffffffff 0200d800 0200d810 00000006 00000002 00000003
400fe248
c9635fe0: bfffff30 bffffdcc 400abaa0 bffffda8 02000b48 400abaa4 20000010
00000003
Backtrace:
Function entered at [<ca0054a4>] from [<ca002648>]
Function entered at [<ca0024d8>] from [<c003f48c>]
Function entered at [<c003f3b0>] from [<c0012680>]
r8 = C0012804 r7 = 00000002 r6 = 20000010 r5 = 0200D810
r4 = 0200D800
Segmentation fault
root@tinystor:~#
------------< snip <------< snip <------< snip <------------

All that the test program in this case is doing is writing 6 bytes starting
at offset 2 in /dev/mtd0 to /dev/mtd0 (damn, this sounds confusing). Here is
the test procedure:

------------< snip <------< snip <------< snip <------------
void file_to_flash (int fd,u_int32_t offset,u_int32_t len,const char
*filename)
{
u_int8_t *buf;
FILE *fp;
int err;
if (offset != lseek (fd,offset,SEEK_SET))
{
perror ("lseek()");
return;
}
if ((buf = (u_int8_t *) malloc (len * sizeof (u_int8_t))) == NULL)
{
perror ("malloc()");
return;
}
if ((fp = fopen (filename,"r")) == NULL)
{
perror ("fopen()");
free (buf);
return;
}
if (fread (buf,len,1,fp) != 1 || ferror (fp))
{
perror ("fread()");
free (buf);
fclose (fp);
return;
}
err = write (fd,buf,len);
if (err < 0)
{
perror ("write()");
free (buf);
fclose (fp);
return;
}
free (buf);
fclose (fp);
printf ("Copied %d bytes from %s to address 0x%.8x in
flash\n",len,filename,offset);
}
------------< snip <------< snip <------< snip <------------

Above function is called with an open file descriptor to /dev/mtd0, offset =
2, len = 6, and the source file is /dev/zero

As you can see from the fault that occurred, above function obviously
reached the write(), so I doubt there's anything wrong with the function
above (after I can't see anything that might be unaligned in there)

Now the chip driver which is used by /dev/mtd0 is a dummy driver which fakes
the write and just shows you what it would do (hence the write_dword():
0x00000000 <- 0x0000ffff)

Below is the relevant module code:

------------< snip <------< snip <------< snip <------------
static int flash_write (struct mtd_info *mtd,loff_t to,size_t len,size_t
*retlen,const u_char *buf)
{
__u8 tmp[4];
int i,n;

#ifdef LART_DEBUG
printk (KERN_DEBUG "%s(to = 0x%.8x, len = %d)\n",__FUNCTION__,(__u32)
to,len);
#endif

*retlen = 0;

/* sanity checks */
if (!len) return (0);
if (to + len > mtd->size) return (-EINVAL);

/* first, we write a 0xFF.... padded byte until we reach a dword boundary
*/
if (to & (BUSWIDTH - 1))
{
__u32 aligned = to & ~(BUSWIDTH - 1);
int gap = to - aligned;

i = n = 0;

while (gap--) tmp[i++] = 0xFF;
while (len && i < BUSWIDTH) tmp[i++] = buf[n++], len--;
while (i < BUSWIDTH) tmp[i++] = 0xFF;

if (!write_dword (aligned,*((__u32 *) tmp))) return (-EIO);

to += n;
buf += n;
*retlen += n;
}

/* now we write dwords until we reach a non-dword boundary */
while (len >= BUSWIDTH)
{
if (!write_dword (to,*((__u32 *) buf))) return (-EIO);

to += BUSWIDTH;
buf += BUSWIDTH;
*retlen += BUSWIDTH;
len -= BUSWIDTH;
}

/* top up the last unaligned bytes, padded with 0xFF.... */
if (len & (BUSWIDTH - 1))
{
i = n = 0;

while (len--) tmp[i++] = buf[n++];
while (i < BUSWIDTH) tmp[i++] = 0xFF;

if (!write_dword (to,*((__u32 *) tmp))) return (-EIO);

*retlen += n;
}

return (0);
}

static inline int write_dword (__u32 offset,__u32 x)
{
#ifndef LART_DEBUG
__u32 status;

/* setup writing */
write32 (data_to_flash (PGM_SETUP),offset);

/* write the data */
write32 (x,offset);

/* wait for the write to finish */
do
{
write32 (data_to_flash (STATUS_READ),offset);
status = flash_to_data (read32 (offset));
}
while ((~status & STATUS_BUSY) != 0);

/* put the flash back into command mode */
write32 (data_to_flash (READ_ARRAY),offset);

/* was the write successfull? */
if ((status & STATUS_PGM_ERR) || read32 (x) != x)
{
printk (KERN_WARNING "%s: write error at address
0x%.8x.\n",module_name,offset);
return (0);
}
#else
printk (KERN_DEBUG "%s(): 0x%.8x <- 0x%.8x\n",__FUNCTION__,offset,x);
#endif

return (1);
}
------------< snip <------< snip <------< snip <------------

LART_DEBUG is of course defined. As you can see from the output, the first
if() was executed successfully and then it crashed in the while loop (at
offset 2, there's a padded word and a dword that needs to be written. The
dword get's caught be the while loop).

What I don't get is why I get an "Unaligned memory access" since all the
data I'm using should be aligned correctly by the compiler. Also a similar
test that tests the dword while loop works perfectly:

------------< snip <------< snip <------< snip <------------
root@tinystor:~# ./mtd_debug write 4 6 /dev/zero
MTD_open
MTD_write
flash_write(to = 0x00000004, len = 6)
write_dword(): 0x00000004 <- 0x00000000
write_dword(): 0x00000008 <- 0xffff0000
Copied 6 MTD_close
bytes from /dev/zero to address 0x00000004 in flash
root@tinystor:~#
------------< snip <------< snip <------< snip <------------

Any help would really be appreciated.

--

Regards
Abraham

Love is never asking why?

__________________________________________________________
Abraham vd Merwe - 2d3D, Inc.

Device Driver Development, Outsourcing, Embedded Systems

Cell: +27 82 565 4451 Snailmail:
Tel: +27 21 761 7549 Block C, Antree Park
Fax: +27 21 761 7648 Doncaster Road
Email: abraham@2d3d.co.za Kenilworth, 7700
Http: http://www.2d3d.com South Africa

[-- Attachment #2: Type: application/pgp-signature, Size: 232 bytes --]