There is a decent Flash erase/write routine in the example bootloader code for the 52259, we use a modified version for our own bootloader. Some of our code is below, but I strongly suggest you download the M52259 bootloader as this is not 100% complete for what you need (and my code is probably not a great example of the art). There are a few comments / changes which may help you though.
There are some problems/risks with using the MCU flash you are running from, we actually use I2C or SPI EEPROM/Flash chips to store settings as it means if the device loses power, crashes, or corrupts for some reason you do not affect the code burned into the MCU. We actually use two SPI flash chips, one stores two firmware images (update & last-known-good) used by the bootloader and one for settings data. Slight overkill, but it makes for a very resilient product for a little extra cost, in our case reliability is more important than saving every penny.
/********************************************************************* Flash subroutines********************************************************************/uint8 Flash_Cmd(uint8 Cmd) // Universal routine, loads (cmd) and lights blue touchpaper (should run from RAM){ MCF_CFM_CFMCMD = Cmd; MCF_CFM_CFMUSTAT = 0x80; // launch command if(MCF_CFM_CFMUSTAT&0x30) { return (MCF_CFM_CFMUSTAT&0x30); } // This is pointless as it's just while !0x80 //while(!MCF_CFM_CFMUSTAT_CCIF){} // CCIF == All done //while(!MCF_CFM_CFMUSTAT_CBEIF); // CBEIF == Cmd buffer empty // So THIS is how it's supposed to be done... while(!(MCF_CFM_CFMUSTAT & MCF_CFM_CFMUSTAT_CBEIF)) { nop(); // Wait for cmd buffer empty } /*// Old method while(!(MCF_CFM_CFMUSTAT & MCF_CFM_CFMUSTAT_CCIF)) // Waits for all cmds to finish - not charge-pump friendly { nop(); // Wait for cmd buffer empty } */ return 0x01;}// sector erase (2k bytes)uint8 Flash_Erase(uint32 addr){ FnCmdInRam = (void*)((uint32)&CmdInRam); // Create alias function in RAM CmdInRam = *(CmdInRam_t *)(Flash_Cmd); // Copy Flash_Cmd to function in ram MCF_CFM_CFMUSTAT = 0x30; *(uint32 *)addr = 0x55; // Write dummy data to address return(FnCmdInRam(0x40));}// dword(32bit) programminguint8 Flash_Prog(uint32 flash_addr, uint32 data_addr, uint32 number){ // Addresses are bytes, number is count of 32-bit words written, // So number = (bytes/4) or (bytes>>2) // uint32 i; flash_addr += FLASH_ADDR_OFFSET; // Backdoor to write data FnCmdInRam = (void*)((uint32)&CmdInRam); CmdInRam = *(CmdInRam_t *)(Flash_Cmd); MCF_CFM_CFMUSTAT = 0x30; for(i=0;i<number;i++) { //while(!(MCF_CFM_CFMUSTAT & MCF_CFM_CFMUSTAT_CBEIF)); // wait for CFM to be ready for new command // Now in flash_cmd() /* while(!(MCF_CFM_CFMUSTAT & MCF_CFM_CFMUSTAT_CBEIF)) { nop(); // Wait for cmd buffer empty } */ *(uint32 *)flash_addr = *(uint32 *)data_addr; result = FnCmdInRam(0x20); // Run cmd from RAM if(result & 0x30) // 0x10 = Access violation, 0x20 = Protection violation return 0xFF; flash_addr +=4; data_addr +=4; } return result;} /********************************************************** Name: EraseFlash** Desc: Erases all unprotected pages of flash** Parameter: None** Return: None* **********************************************************/void EraseFlash(void){ volatile uint32 addr; unsigned char temp; // erase each page of flash for(addr=MIN_FLASH1_ADDRESS;addr<=MAX_FLASH1_ADDRESS;addr+=FLASH_PAGE_SIZE) { if(addr > FLASH_PROTECTED_ADDRESS) { // OK go temp = (uint8) Flash_Erase(addr + FLASH_ADDR_OFFSET); if(gFlashError == temp) { // Error Erasing Flash BootloaderStatus = BootloaderFlashError; return; } } } // WSL addition - wait for all cmds to finish before returning while(!(MCF_CFM_CFMUSTAT & MCF_CFM_CFMUSTAT_CCIF)); // wait for CFM to completely finish}
//
//
// Calling these functions looks a bit like...
//
//
// If flash not erased, erase flash
if(!FlashErased)
{
EraseFlash();
if(BootloaderStatus == BootloaderFlashError)
{
return;
}
FlashErased = TRUE;
}
// Now read data from SPI and save to FLASH
while(address <= MAX_FLASH1_ADDRESS)
{
// Read a page's worth of data from SPI into buf, referenced by bufp
// <code removed>
// Write buffered data to Flash
if((address > FLASH_PROTECTED_ADDRESS) && (address <= MAX_FLASH1_ADDRESS))
{
// call flash program
temp = (unsigned char) Flash_Prog(address, bufp, (i >> 2));
if(gFlashError == temp)
{
BootloaderStatus = BootloaderFlashError;
return;
}
}
address += i;
}
// WSL addition - wait for all cmds to finish before returning
while(!(MCF_CFM_CFMUSTAT & MCF_CFM_CFMUSTAT_CCIF))
{
nop(); // wait for CFM to completely finish (all commands complete)
}