Saving variable in Flash with MCF52235

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

Saving variable in Flash with MCF52235

2,939 Views
cmag
Contributor I
Howdy,
 
I'm trying to store a variable in Flash that can be accessible and writeable, even after a reboot.  For example, I have a device with an address that needs to be configurable by the user and saved.  I've got the entire system done except this one thing, so I'd prefer not to have to integrate uTasker at this point.  It doesn't really seem like it should be that hard.  Can someone point me in the right direction?
 
Thanks,
cmag


Message Edited by cmag on 2008-04-15 04:27 AM
Labels (1)
0 Kudos
6 Replies

376 Views
RichTestardi
Senior Contributor II
Hi,
 
I write flash parameters (and code as well) on the MCF52221 and was surprised to find I did not have to be running from RAM.  I typically run in the low half of flash (below 0x10000) and write the high half (above 0x10000).  My code is below.  You can try erasing the page in the other half of flash where you are running and see if it works for you -- I expect it will (you have twice the flash I have, though).  Remember, you have to write 4 bytes at a time (and erase an entire 2k page at a time), which is why the APIs are set up to use uint32 pointers.
 
Good luck!
 
-- Rich
 
Code:
#define FLASH_PAGE_SIZE  2048#define FSYS  48000000  // frequency of M52221DEMO boardstaticvoidflash_command(uint8 cmd, uint32 *addr, uint32 data){    uint32 *backdoor_addr;    // assert we're initialized    assert(MCF_CFM_CFMCLKD & MCF_CFM_CFMCLKD_DIVLD);    // assert we're ready    assert(MCF_CFM_CFMUSTAT & MCF_CFM_CFMUSTAT_CBEIF);    // assert no errors    assert(! (MCF_CFM_CFMUSTAT & (MCF_CFM_CFMUSTAT_PVIOL|MCF_CFM_CFMUSTAT_ACCERR)));    // write the flash thru the backdoor address    backdoor_addr = (uint32 *)(__IPSBAR+0x04000000+(int)addr);    *backdoor_addr = data;    // write the command    MCF_CFM_CFMCMD = cmd;    // launch the command (N.B. this clears CBEIF!)    MCF_CFM_CFMUSTAT = MCF_CFM_CFMUSTAT_CBEIF;    // wait for command buffer empty    while (! (MCF_CFM_CFMUSTAT & MCF_CFM_CFMUSTAT_CBEIF)) {        // assert no errors        assert(! (MCF_CFM_CFMUSTAT & (MCF_CFM_CFMUSTAT_PVIOL|MCF_CFM_CFMUSTAT_ACCERR)));    }}voidflash_erase_pages(uint32 *addr, uint32 npages){    while (npages) {        flash_command(MCF_CFM_CFMCMD_PAGE_ERASE, addr, 0);        npages--;        addr += FLASH_PAGE_SIZE/sizeof(uint32);    }    // wait for flash command complete    while(! (MCF_CFM_CFMUSTAT & MCF_CFM_CFMUSTAT_CCIF)) {        // NULL    };}voidflash_write_words(uint32 *addr, uint32 *data, uint32 nwords){    while (nwords) {        flash_command(MCF_CFM_CFMCMD_WORD_PROGRAM, addr, *data);        nwords--;        addr++;        data++;    }    // wait for flash command complete    while(! (MCF_CFM_CFMUSTAT & MCF_CFM_CFMUSTAT_CCIF)) {        // NULL    };        assert(! memcmp(addr, data, nwords*sizeof(uint32)));}voidflash_initialize(void){    if (FSYS > 25600000) {        MCF_CFM_CFMCLKD = MCF_CFM_CFMCLKD_PRDIV8|MCF_CFM_CFMCLKD_DIV((FSYS-1)/2/8/200000);    } else {        MCF_CFM_CFMCLKD = MCF_CFM_CFMCLKD_DIV((FSYS-1)/2/200000);    }    MCF_CFM_CFMPROT = 0;    MCF_CFM_CFMSACC = 0;    MCF_CFM_CFMDACC = 0;    MCF_CFM_CFMMCR = 0;}

 
0 Kudos

376 Views
alager
Contributor II
I'm trying these flash routines on the 52235evb.  The flash_initialize() function works fine, but then when I call flash_erase_pages(), the debugger dies, and the console starts spewing something about:
Unimplemented F line instruction.

I've gotten the code size down, so that it ends at 0x1a0f0
I'm using tcp lite by internich, rev 2.0
I'm using the following function to test the flash routines:

Code:
void save_myflash(){ uint32 address=0x3f7ff; char foo[]="somedata";  flash_initialize(); flash_erase_pages(&address, 1); flash_write_words(&address,(uint32 *)foo, 2);}

 
What am I missing?

Thanks,
Aaron



Message Edited by alager on 2008-06-18 11:45 PM
0 Kudos

376 Views
RichTestardi
Senior Contributor II
I must have totally missed this post when it came out, sorry, but just in case, I thought I'd add I think you want address to be the address of a page, and you want to pass that number by value (not the address of that number) to the flash routines, like:
 
uint32 *address=(uint32 *)0x3f800;
char foo[]="somedata";

flash_initialize();
flash_erase_pages(address, 1);
flash_write_words(address,(uint32 *)foo, 2);
I tried that here and it works.
 
-- Rich
0 Kudos

376 Views
alager
Contributor II
I should have followed up on this too.  It appears that there is an issue on the internich software, where if you start printing to the uart first, then imeadiatly start the flash routines it crashes.  Once I changed the order, it worked fine.

Aaron
0 Kudos

376 Views
cmag
Contributor I
Thanks guys, I'll try these out.  Right now I've got bigger problems pertaining to memory but I'll drop them in a new thread.  I'll be glad when this project is over.  I don' t know this system well enough for the time constraints I'm under:smileysad:
 
Thanks again,
cmag
0 Kudos

376 Views
mjbcswitzerland
Specialist V
Hi

The most important things to know are the following:

1. You need to run the write/delete routines from RAM since the FLASH can not be accessed when being modified.
2. You can write bits from '1' to '0' on a long word basis.
3. To set any bits from '0' to '1' you need to delete the 2k sector it is in.
4. Accesses to FLASH when programming is via their backdoor access address (study users' manual carefully for this)

You can use the following 2 routines from the uTasker project:
int fnWriteBytesFlash(unsigned char *ucDestination, unsigned char *ucData, MAX_FILE_LENGTH Length);
this will write a buffer (ucData) of size Length (can also be one byte) to the address in internal FLASH (ucDestination). It handles long word alignment automatically.

int fnEraseFlashSector(unsigned char *ptrSector, MAX_FILE_LENGTH Length);
This deletes the sectors occupied by the address ptrSector (can be anywhere in the first sector to delete) and over the length (Length). To delete the sector that an address is in set Length to 1 or to delete multiple sectros from the address set it to be a multiple 2k value.

These are all that you need (plus their subroutines which do the detailed work). The uTasker implements a parameter system which uses a swap buffer to allow a backup of old data to be restored if needed and also to ensure that parameter changes can not be corrupted if there is a power down during programming or deleting. If you have specific requirements for security it may be best to look at this but otherwise simply delete and write each time your parameter(s) change(s).

Regards

Mark

www.uTasker.com


0 Kudos