Saving variable in Flash with MCF52235

キャンセル
次の結果を表示 
表示  限定  | 次の代わりに検索 
もしかして: 

Saving variable in Flash with MCF52235

3,940件の閲覧回数
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
ラベル(1)
0 件の賞賛
返信
6 返答(返信)

1,377件の閲覧回数
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 件の賞賛
返信

1,377件の閲覧回数
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 件の賞賛
返信

1,377件の閲覧回数
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 件の賞賛
返信

1,377件の閲覧回数
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 件の賞賛
返信

1,377件の閲覧回数
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 件の賞賛
返信

1,377件の閲覧回数
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 件の賞賛
返信