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
Good of you to post the resolution to the problem, since no one here have access to enough information to catch that one.