MCF52259 - Save nonvolatile Data

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

MCF52259 - Save nonvolatile Data

899 Views
Patrick_123
Contributor I

Hi everybody

 

I'm new on Coldfire and now want to save data to the internal flash of the MCF52259.After reading a lot documents and Application Notes, i don't really understand if it's really possible and how it would work. Has anyone already used the internal flash for non-volatile data? Are there some functions online which can be used?

 

I'm using CW V10+.

 

Thanks for help.

 

Patrick

Labels (1)
0 Kudos
4 Replies

472 Views
thillainathan_k
Contributor I

Hi,

 

I am using ColdfireV2 MCF52259 controller with MQX RTOS in my application. My application really needs to save some of the configuration data in the Flash memory itself and I want to protect that location too. while run time I need to unprotect those locations and update the configuration data then protect it. Please help me how to do the protection and unprotection technique while run time.  If anybody implemented this before please share any example code for the same.

 

KTN

0 Kudos

472 Views
FridgeFreezer
Senior Contributor I

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)
    }



 

0 Kudos

472 Views
boogy
Contributor III

Its actually pretty simple.

 flash_hdl = fopen("flashx:",NULL);    /* Enable sector cache */ _io_ioctl(flash_hdl, FLASH_IOCTL_DISABLE_SECTOR_CACHE, NULL);   fseek(flash_hdl,ROM_SETUP,IO_SEEK_SET); read(flash_hdl,&flash_data, sizeof(flash_data));..........    fseek(flash_hdl,ROM_SETUP,IO_SEEK_SET);   i=write(flash_hdl, &flash_data, sizeof(flash_data));   _time_delay(2000);   fclose(flash_hdl);

 Its like using a hard drive.

0 Kudos

472 Views
Obetz
Contributor III

 


boogy wrote:

Its actually pretty simple[...] like using a hard drive.


 

I think your answer is too simple. Maybe the OP uses a different compiler, or he doesn't want to use a bloated library not being under his control?

 

Erasing a flash sector and programming a word is described in the manual.

 

What's not clearly stated: In the 5225x, you don't need to execute the flash programming code from RAM, since the 5225x halts the execution as long as the flash memory is inaccessible. But since it's not ducumented, do it at your own risk.

 

If you need to serve interrupts during erase/program, you need to move vectors and service routines to RAM, of course.

 

Oliver

0 Kudos