EmbeddedRelated.com
Forums

flash access for arm7

Started by julvr February 8, 2009
I'm having a problem accessing flash on my arm7 processor, and I can't
figure out what I'm doing wrong.  I have the following code:

   OUT1("FEEPRO ", GETREG32(FEEPRO));
   OUT1("FEEHIDE ", GETREG32(FEEHIDE));

   //SETREG32(FEEHIDE, 0xFFFFFFFF);
   //SETREG32(FEEPRO, 0xFFFFFFFF);

   // trying single erase:
   SETREG16(FEEADR, 0x800);
   SETREG8(FEECON, 0x05);
   while (((result = GETREG16(FEESTA)) & 0x03) == 0) {}
   if (result & 0x02)
   {
      OUT(" Single erase failed!");
   }
   else
   {
      OUT(" single erase done!");
   }

according to the first OUT commands, FEEPRO and FEEHIDE are both
0xffffffff, which would indicate no write protection.  But all
attempts to erase a section of flash fails.  I also tried to do a mass
erase, which seems to work (FEESTA gets set to 0x01), BUT, it
completes in less than a tenth of a second...  Does anyone have any
ideas what I'm doing wrong?

Thanks,

John

"julvr" <nospam@ulvr.com> wrote in message 
news:c1bb93e2-574d-4c9a-95fa-a41a887993c7@13g2000yql.googlegroups.com...
> I'm having a problem accessing flash on my arm7 processor, and I can't > figure out what I'm doing wrong. I have the following code: > > OUT1("FEEPRO ", GETREG32(FEEPRO)); > OUT1("FEEHIDE ", GETREG32(FEEHIDE)); > > //SETREG32(FEEHIDE, 0xFFFFFFFF); > //SETREG32(FEEPRO, 0xFFFFFFFF); > > // trying single erase: > SETREG16(FEEADR, 0x800); > SETREG8(FEECON, 0x05); > while (((result = GETREG16(FEESTA)) & 0x03) == 0) {} > if (result & 0x02) > { > OUT(" Single erase failed!"); > } > else > { > OUT(" single erase done!"); > } > > according to the first OUT commands, FEEPRO and FEEHIDE are both > 0xffffffff, which would indicate no write protection. But all > attempts to erase a section of flash fails. I also tried to do a mass > erase, which seems to work (FEESTA gets set to 0x01), BUT, it > completes in less than a tenth of a second... Does anyone have any > ideas what I'm doing wrong?
There are lots of different vendors of ARM7 processors, and lots of different vendors of Flash memory, and lots of possible implementations of the macros you are using. Therefore I have no idea what you are doing or what you might be doing wrong. -- Regards, Richard. + http://www.FreeRTOS.org Designed for microcontrollers. More than 7000 downloads per month. + http://www.FreeRTOS.org/Documentation FreeRTOS eBook - a step by step guide to using an RTOS.
On Feb 9, 4:27=A0am, "FreeRTOS.org" <noem...@given.com> wrote:
> "julvr" <nos...@ulvr.com> wrote in message > > news:c1bb93e2-574d-4c9a-95fa-a41a887993c7@13g2000yql.googlegroups.com... > > > > > I'm having a problem accessing flash on my arm7 processor, and I can't > > figure out what I'm doing wrong. =A0I have the following code: > > > =A0 OUT1("FEEPRO ", GETREG32(FEEPRO)); > > =A0 OUT1("FEEHIDE ", GETREG32(FEEHIDE)); > > > =A0 //SETREG32(FEEHIDE, 0xFFFFFFFF); > > =A0 //SETREG32(FEEPRO, 0xFFFFFFFF); > > > =A0 // trying single erase: > > =A0 SETREG16(FEEADR, 0x800); > > =A0 SETREG8(FEECON, 0x05); > > =A0 while (((result =3D GETREG16(FEESTA)) & 0x03) =3D=3D 0) {} > > =A0 if (result & 0x02) > > =A0 { > > =A0 =A0 =A0OUT(" Single erase failed!"); > > =A0 } > > =A0 else > > =A0 { > > =A0 =A0 =A0OUT(" single erase done!"); > > =A0 } > > > according to the first OUT commands, FEEPRO and FEEHIDE are both > > 0xffffffff, which would indicate no write protection. =A0But all > > attempts to erase a section of flash fails. =A0I also tried to do a mas=
s
> > erase, which seems to work (FEESTA gets set to 0x01), BUT, it > > completes in less than a tenth of a second... =A0Does anyone have any > > ideas what I'm doing wrong? > > There are lots of different vendors of ARM7 processors, and lots of > different vendors of Flash memory, and lots of possible implementations o=
f
> the macros you are using. =A0Therefore I have no idea what you are doing =
or
> what you might be doing wrong. > > -- > Regards, > Richard. > > +http://www.FreeRTOS.org > Designed for microcontrollers. =A0More than 7000 downloads per month. > > +http://www.FreeRTOS.org/Documentation > FreeRTOS eBook - a step by step guide to using an RTOS.
I am using an ADuC7021 (TDMI). It has 62k of on-chip flash, which I am trying to write. The first step is of course to erase a block, but I can't get that working. John
On Mon, 9 Feb 2009 05:10:52 -0800 (PST)
julvr <nospam@ulvr.com> wrote:

> On Feb 9, 4:27=A0am, "FreeRTOS.org" <noem...@given.com> wrote: > > "julvr" <nos...@ulvr.com> wrote in message > > > > news:c1bb93e2-574d-4c9a-95fa-a41a887993c7@13g2000yql.googlegroups.com... > > > > > > > > > I'm having a problem accessing flash on my arm7 processor, and I > > > can't figure out what I'm doing wrong. =A0I have the following code: > > > > > =A0 OUT1("FEEPRO ", GETREG32(FEEPRO)); > > > =A0 OUT1("FEEHIDE ", GETREG32(FEEHIDE)); > > > > > =A0 //SETREG32(FEEHIDE, 0xFFFFFFFF); > > > =A0 //SETREG32(FEEPRO, 0xFFFFFFFF); > > > > > =A0 // trying single erase: > > > =A0 SETREG16(FEEADR, 0x800); > > > =A0 SETREG8(FEECON, 0x05); > > > =A0 while (((result =3D GETREG16(FEESTA)) & 0x03) =3D=3D 0) {} > > > =A0 if (result & 0x02) > > > =A0 { > > > =A0 =A0 =A0OUT(" Single erase failed!"); > > > =A0 } > > > =A0 else > > > =A0 { > > > =A0 =A0 =A0OUT(" single erase done!"); > > > =A0 } > > > > > according to the first OUT commands, FEEPRO and FEEHIDE are both > > > 0xffffffff, which would indicate no write protection. =A0But all > > > attempts to erase a section of flash fails. =A0I also tried to do a > > > mass erase, which seems to work (FEESTA gets set to 0x01), BUT, it > > > completes in less than a tenth of a second... =A0Does anyone have > > > any ideas what I'm doing wrong? > > > > There are lots of different vendors of ARM7 processors, and lots of > > different vendors of Flash memory, and lots of possible > > implementations of the macros you are using. =A0Therefore I have no > > idea what you are doing or what you might be doing wrong. > > > > -- > > Regards, > > Richard. > > > > +http://www.FreeRTOS.org > > Designed for microcontrollers. =A0More than 7000 downloads per month. > > > > +http://www.FreeRTOS.org/Documentation > > FreeRTOS eBook - a step by step guide to using an RTOS. >=20 >=20 > I am using an ADuC7021 (TDMI). It has 62k of on-chip flash, which I > am trying to write. The first step is of course to erase a block, but > I can't get that working. >=20 > John
And Richard's comment about not knowing what toolchain (compiler, etc.) you're using, and therefore having no idea what the macros you're calling actually do, still applies. --=20 Rob Gaddi, Highland Technology Email address is currently out of order
I don't think there's anything wrong with the macros -- I use the same
macros to set up the serial port and the timer, and both those seem to
work fine.  I'm using arm-elf-gcc in case that makes a difference.
The following are the macros I'm using:


#define SETREG8(reg, val)      do { *((volatile char *)(reg)) =
(val); } while(0)
#define GETREG8(reg)           (*((volatile char *)(reg)))
#define SETREG16(reg, val)      do { *((volatile short *)(reg)) =
(val); } while(0)
#define GETREG16(reg)           (*((volatile short *)(reg)))
#define SETREG32(reg, val)      do { *((volatile long *)(reg)) =
(val); } while(0)
#define GETREG32(reg)           (*(volatile long *)(reg))

#define  FEESTA   ((volatile unsigned long *)  0XFFFFF800)
#define  FEEMOD   ((volatile unsigned long *)  0XFFFFF804)
#define  FEECON   ((volatile unsigned long *)  0XFFFFF808)
#define  FEEDAT   ((volatile unsigned long *)  0XFFFFF80C)
#define  FEEADR   ((volatile unsigned long *)  0XFFFFF810)
#define  FEESIGN  ((volatile unsigned long *)  0XFFFFF818)
#define  FEEPRO   ((volatile unsigned long *)  0XFFFFF81C)
#define  FEEHIDE  ((volatile unsigned long *)  0XFFFFF820)


I'm again suspecting FEEPRO, as I dumped this after a reset, and it
returned 0.  (It seems it sometimes returns 0, and other times
0xffffffff???)

I appreciate any help anyone can give me, as I'm now completely
stumped on this issue.


John



On 9 Feb, 21:04, julvr <nos...@ulvr.com> wrote:
> I don't think there's anything wrong with the macros -- I use the same > macros to set up the serial port and the timer, and both those seem to > work fine. =A0I'm using arm-elf-gcc in case that makes a difference. > The following are the macros I'm using: > > #define SETREG8(reg, val) =A0 =A0 =A0do { *((volatile char *)(reg)) =3D > (val); } while(0) > #define GETREG8(reg) =A0 =A0 =A0 =A0 =A0 (*((volatile char *)(reg))) > #define SETREG16(reg, val) =A0 =A0 =A0do { *((volatile short *)(reg)) =3D > (val); } while(0) > #define GETREG16(reg) =A0 =A0 =A0 =A0 =A0 (*((volatile short *)(reg))) > #define SETREG32(reg, val) =A0 =A0 =A0do { *((volatile long *)(reg)) =3D > (val); } while(0) > #define GETREG32(reg) =A0 =A0 =A0 =A0 =A0 (*(volatile long *)(reg)) > > #define =A0FEESTA =A0 ((volatile unsigned long *) =A00XFFFFF800) > #define =A0FEEMOD =A0 ((volatile unsigned long *) =A00XFFFFF804) > #define =A0FEECON =A0 ((volatile unsigned long *) =A00XFFFFF808) > #define =A0FEEDAT =A0 ((volatile unsigned long *) =A00XFFFFF80C) > #define =A0FEEADR =A0 ((volatile unsigned long *) =A00XFFFFF810) > #define =A0FEESIGN =A0((volatile unsigned long *) =A00XFFFFF818) > #define =A0FEEPRO =A0 ((volatile unsigned long *) =A00XFFFFF81C) > #define =A0FEEHIDE =A0((volatile unsigned long *) =A00XFFFFF820) > > I'm again suspecting FEEPRO, as I dumped this after a reset, and it > returned 0. =A0(It seems it sometimes returns 0, and other times > 0xffffffff???) > > I appreciate any help anyone can give me, as I'm now completely > stumped on this issue. > > John
Did you set bit 3 of FEEMOD?
On Feb 10, 9:03=A0am, Hans Odeberg <hans_odeb...@yahoo.com> wrote:
> On 9 Feb, 21:04, julvr <nos...@ulvr.com> wrote: > > > > > I don't think there's anything wrong with the macros -- I use the same > > macros to set up the serial port and the timer, and both those seem to > > work fine. =A0I'm using arm-elf-gcc in case that makes a difference. > > The following are the macros I'm using: > > > #define SETREG8(reg, val) =A0 =A0 =A0do { *((volatile char *)(reg)) =3D > > (val); } while(0) > > #define GETREG8(reg) =A0 =A0 =A0 =A0 =A0 (*((volatile char *)(reg))) > > #define SETREG16(reg, val) =A0 =A0 =A0do { *((volatile short *)(reg)) =
=3D
> > (val); } while(0) > > #define GETREG16(reg) =A0 =A0 =A0 =A0 =A0 (*((volatile short *)(reg))) > > #define SETREG32(reg, val) =A0 =A0 =A0do { *((volatile long *)(reg)) =
=3D
> > (val); } while(0) > > #define GETREG32(reg) =A0 =A0 =A0 =A0 =A0 (*(volatile long *)(reg)) > > > #define =A0FEESTA =A0 ((volatile unsigned long *) =A00XFFFFF800) > > #define =A0FEEMOD =A0 ((volatile unsigned long *) =A00XFFFFF804) > > #define =A0FEECON =A0 ((volatile unsigned long *) =A00XFFFFF808) > > #define =A0FEEDAT =A0 ((volatile unsigned long *) =A00XFFFFF80C) > > #define =A0FEEADR =A0 ((volatile unsigned long *) =A00XFFFFF810) > > #define =A0FEESIGN =A0((volatile unsigned long *) =A00XFFFFF818) > > #define =A0FEEPRO =A0 ((volatile unsigned long *) =A00XFFFFF81C) > > #define =A0FEEHIDE =A0((volatile unsigned long *) =A00XFFFFF820) > > > I'm again suspecting FEEPRO, as I dumped this after a reset, and it > > returned 0. =A0(It seems it sometimes returns 0, and other times > > 0xffffffff???) > > > I appreciate any help anyone can give me, as I'm now completely > > stumped on this issue. > > > John > > Did you set bit 3 of FEEMOD?
I did not set that register either way during the single erases, but when I tried a mass erase, I explicitly set that register to 0xF0, and then back to 0 (which means bit 3 is unset). A single erase after this point also failed. I do not have an interrupt vector table loaded at the moment, so I would assume that this bit should remain unset. John
julvr <nospam@ulvr.com> writes:

> I don't think there's anything wrong with the macros -- I use the same > macros to set up the serial port and the timer, and both those seem to > work fine. I'm using arm-elf-gcc in case that makes a difference. > The following are the macros I'm using: > > > #define SETREG8(reg, val) do { *((volatile char *)(reg)) = > (val); } while(0) > #define GETREG8(reg) (*((volatile char *)(reg))) > #define SETREG16(reg, val) do { *((volatile short *)(reg)) = > (val); } while(0) > #define GETREG16(reg) (*((volatile short *)(reg))) > #define SETREG32(reg, val) do { *((volatile long *)(reg)) = > (val); } while(0) > #define GETREG32(reg) (*(volatile long *)(reg)) > > #define FEESTA ((volatile unsigned long *) 0XFFFFF800) > #define FEEMOD ((volatile unsigned long *) 0XFFFFF804) > #define FEECON ((volatile unsigned long *) 0XFFFFF808) > #define FEEDAT ((volatile unsigned long *) 0XFFFFF80C) > #define FEEADR ((volatile unsigned long *) 0XFFFFF810) > #define FEESIGN ((volatile unsigned long *) 0XFFFFF818) > #define FEEPRO ((volatile unsigned long *) 0XFFFFF81C) > #define FEEHIDE ((volatile unsigned long *) 0XFFFFF820) > > > I'm again suspecting FEEPRO, as I dumped this after a reset, and it > returned 0. (It seems it sometimes returns 0, and other times > 0xffffffff???) > > I appreciate any help anyone can give me, as I'm now completely > stumped on this issue. > > > John > > >
Hi, I use this device. I have not looked at your code, but here is some of mine that works OK (for gcc). John Devereux ====================================================================== struct aduc7000_flash { volatile unsigned char sta __attribute__((aligned(4))) ; volatile unsigned char mod __attribute__((aligned(4))) ; volatile unsigned char con __attribute__((aligned(4))) ; volatile unsigned short dat __attribute__((aligned(4))) ; volatile unsigned short adr __attribute__((aligned(4))) ; volatile unsigned long dummy1 __attribute__((aligned(4))) ; volatile unsigned long sign __attribute__((aligned(4))) ; volatile unsigned long pro __attribute__((aligned(4))) ; volatile unsigned long hide __attribute__((aligned(4))) ; } ; enum { FLASH_SECTOR_SIZE=0x200 }; enum { CMD_NULL, CMD_SINGLE_READ, CMD_SINGLE_WRITE, CMD_ERASE_WRITE, CMD_SINGLE_VERIFY, CMD_SINGLE_ERASE, CMD_MASS_ERASE, CMD_BURST_READ, CMD_BURST_READ_WRITE, CMD_ERASE_BURST_READ_WRITE, CMD_RESERVED_1, CMD_SIGNATURE, CMD_PROTECT, CMD_RESERVED_2, CMD_RESERED_3, CMD_PING, } COMMANDS; /* declare pointer to flash controller registers */ static struct aduc7000_flash* const flash = (struct aduc7000_flash*) 0xFFFFF800; /* Erase flash memory blocks starting at "address". A *minimum* of n-1 bytes is erased, i.e. up to the end of the physical flash erase block containing the (n-1)'th byte. We write erase commands at the erase block interval throughout the region requiring erasure. */ static void erase(void* address, unsigned long n) { /* force hword alignment */ address = (void*) ((unsigned long)address & -2); /* sector erase unlock sequence */ flash->mod |= (1<<3); /* enable write/erase */ volatile unsigned short* a; for(a=address; (void*)a < address + n; a = (void*)a + FLASH_SECTOR_SIZE) { flash->adr = (unsigned int)a; flash->con = CMD_SINGLE_ERASE; /* wait for successful completion */ while(!(flash->sta & (1<<0))) ; } flash->mod &= ~(1<<3); /* disable write/erase */ } /* prog() - helper function to program a *single* 16 bit location. Must be an even address! Chip must already be in programming mode. Can only program bits from 1 to 0, not 0 to 1. Therefore, must not be any "1" bits in source, where there are "0" bits in destination. If we get an assert here it probably means that the destination has not been erased. Flash address register is only 16 bits, so addresses are modulo 65536. */ static void prog(void *dst, unsigned data) { volatile unsigned short* d = (volatile unsigned short*) dst; assert(((unsigned long)d & 1) == 0); /* alignment OK */ assert((data & ~*d) == 0); /* can't program 0's back to 1's */ flash->mod |= (1<<3); /* enable write */ flash->adr = (unsigned)d; /* setup address */ flash->dat = data; flash->con = CMD_SINGLE_WRITE; while(!(flash->sta & (1<<0))); /* wait for success */ flash->mod &= ~(1<<3); /* disable writes again */ } /* Our flash chip is a 16 bit device. The writing process requires that we write data 16 bits at a time, to even flash addresses. So we proceed in three steps: - write any initial odd address - write even addresses 16 bits at a time - write any final odd address */ static int write(void *dst, void *src, size_t n) { /* convert to char*, use these thoughout */ unsigned char* s = src; unsigned char* d = dst; unsigned data; /* program first byte if at odd address */ if((unsigned long)d & 1 && n!=0) { /* read even byte of existing 16 bit data */ data = *(d-1); /* fill in high byte from src block */ data |= *s << 8; /* program 16 bit data value at even address */ prog(d-1, data); /* adjustments to account for single byte programmed */ d += 1; s += 1; n -= 1; } while(n>1) /* may have byte left over */ { unsigned short data; data = *s + (*(s+1) << 8); prog(d, data); s += 2; d += 2; n -= 2; } /* program last byte if one left over. If this is the case, we have to program one byte (*s) to an even address (d), leaving the high-order byte at the next address (d+1) unchanged */ if(n==1) { /* read even byte of existing 16 bit data */ data = *(d+1) << 8; /* fill in low byte from src block */ data |= *s; /* program 16 bit data value at even address */ prog(d, data); /* adjustments to account for single byte programmed */ d += 1; s += 1; n -= 1; } assert(n==0); return 0; /* success */ } /* external interface */ /** flashErase(address, n) - erase flash region. Entire block containing address+n-1 will get erased. We check for erasure and repeat if not erased, hopefully this will improve reliablity in event of erasure getting interrupted. */ void flashErase(void* address, unsigned long n) { do { erase(address, n); } while(!flashErased(address, n)); } void flashWrite(void *dst, void *src, size_t n) { write(dst, src, n); } void flashRead(void *dst, void *src, size_t n) { memcpy(dst, src, n); } /** return true if blank */ int flashErased(void* address, size_t n) { int is_blank = 1; int i; unsigned char* a = (unsigned char*)address; for(i=0;i<n;i++) { if(a[i]!=0xff) { is_blank = 0; break; } } return is_blank; } void flashTest(void) { unsigned char test[]= { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 }; erase((void*)0x8F000, 0x400); write((void*)0x8F000, test, sizeof test); } ====================================================================== -- John Devereux
<snip>

Thank you very much.  I will give this a try.


John