This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

LPC2387 IAP Flash Erase

Hey everyone, was hoping someone could help me with something.

I'm developing an RTX application for a LPC2387 (currently using the MCB2300) and need to write a char array to flash memory. Learned a lot about using IAP commands but I think I'm missing something still.

I'm using function inspired by the supplied algorithms for the LPC2387 (found under C:\Keil\ARM\Flash). I can write to flash and read it back fine but once I try to erase, I get a data abort exception. My code is below:

This works:

    flash_write(0x00058000, protocol_buf1);
    flash_read(0x00058000, 5, protocol_buf2);
    // Code that prints out protocol_buf2

}

This doesn't work:

    flash_erase(0x00058000);
    flash_write(0x00058000, protocol_buf1);
    flash_read(0x00058000, 5, protocol_buf2);
    // Code that prints out protocol_buf2
}

Where the flash functions are defined:

#define CCLK        4000
#define PAGE_SIZE   1024

struct sIAP {                  // IAP Structure
  U32 cmd;           // Command
  U32 par[4];        // Parameters
  U32 stat;          // Status
  U32 res;           // Result
} IAP;

void    IAP_Execute (struct sIAP *pIAP);

U32 get_sect_num(U32 address) {
    U32 sector;

    // Calculate sector number
    sector = (address >> 12) & 0x7F;
    if (sector >= 0x78) sector -= 0x62;
    else if (sector >= 0x08) sector  = 0x07 + (sector >> 3);
    return sector;
}

U8 flash_write(U32 address, U8 *buffer) {
    U32 sector;

    // Get the sector number
    sector = get_sect_num(address);

    // Prepare sector for write
    IAP.cmd = 50;               // Command code
    IAP.par[0] = sector;        // Start sector
    IAP.par[1] = sector;        // End Sector
    IAP_Execute(&IAP);          // Execute IAP Command
    if (IAP.stat) return 1;     // Command Failed

    // Copy RAM to FLASH
    IAP.cmd = 51;               // Command Code
    IAP.par[0] = address;       // Destination Flash Address
    IAP.par[1] = (U32)buffer;   // Source RAM Address
    IAP.par[2] = PAGE_SIZE;     // Fixed Page Size
    IAP.par[3] = CCLK;          // CCLK in kHz
    IAP_Execute(&IAP);          // Execute IAP Command
    if (IAP.stat) return 1;     // Command Failed

    return 0;
}

U8 flash_read(U32 address, U32 size, U8 *buffer) {
    U32 i;

    for (i=0; i<size; i++) buffer[i] = *((U8*)address+i);

    return 0;
}


U8 flash_erase(U32 address) {
unsigned long n;

  n = (unsigned long)get_sect_num(address);                          // Get Sector Number

  IAP.cmd    = 50;                             // Prepare Sector for Erase
  IAP.par[0] = n;                              // Start Sector
  IAP.par[1] = n;                              // End Sector
  IAP_Execute (&IAP);                          // Execute IAP Command
  if (IAP.stat) return (1);                    // Command Failed

  IAP.cmd    = 52;                             // Erase Sector
  IAP.par[0] = n;                              // Start Sector
  IAP.par[1] = n;                              // End Sector
  IAP.par[2] = CCLK;                           // CCLK in kHz
  IAP_Execute(&IAP);                           // Execute IAP Command
  if (IAP.stat) return (1);                    // Command Failed

  return (0);                                  // Finished without Errors
}


assembly IAP execution

                AREA    IAPEXE, CODE, READONLY



;void IAP_Execute (struct sIAP *pIAP); EXPORT IAP_Execute
IAP_Execute STMFD SP!,{LR} ; Save Return Address ADD R1,R0,#0x14 ; R0 = &IAP.cmd, R1 = &IAP.stat ADR LR,IAP_Exit ; Return Address LDR R2,=0x7FFFFFF1 ; IAP Entry (Thumb Mode) BX R2 ; Execute IAP Command
IAP_Exit LDMFD SP!,{LR} ; Restore Return Address BX LR ; Return
END

Parents
  • So I figured out what I was doing wrong.

    I tried disabling interrupts, but I wasn't calling any in my test code, so that wasn't the problem (I added that to my main code though since it's a must have).

    I eventually found this yahoo group that has a lot of example code:
    tech.groups.yahoo.com/.../

    They have an example that uses the flash as an EEPROM which ended up being quite useful. In the end I realized I made a dumb mistake and didn't give the correct clock rate to the IAP erase and write functions. I didn't remember to take into account the PLL multiplier. Added that in and now it works splendidly.

Reply
  • So I figured out what I was doing wrong.

    I tried disabling interrupts, but I wasn't calling any in my test code, so that wasn't the problem (I added that to my main code though since it's a must have).

    I eventually found this yahoo group that has a lot of example code:
    tech.groups.yahoo.com/.../

    They have an example that uses the flash as an EEPROM which ended up being quite useful. In the end I realized I made a dumb mistake and didn't give the correct clock rate to the IAP erase and write functions. I didn't remember to take into account the PLL multiplier. Added that in and now it works splendidly.

Children