voidflash_upgrade(void){ uint32 *addr; uint32 *data; uint32 nwords; uint32 npages; uint32 *backdoor_addr; // N.B. this code generates no relocations so we can run it from RAM!!! // erase the firmware code addr = NULL; npages = FLASH_BYTES/2/FLASH_PAGE_SIZE; while (npages) { assert(MCF_CFM_CFMCLKD & MCF_CFM_CFMCLKD_DIVLD); assert(MCF_CFM_CFMUSTAT & MCF_CFM_CFMUSTAT_CBEIF); assert(! (MCF_CFM_CFMUSTAT & (MCF_CFM_CFMUSTAT_PVIOL|MCF_CFM_CFMUSTAT_ACCERR))); backdoor_addr = (uint32 *)(__IPSBAR+0x04000000+(int)addr); *backdoor_addr = 0; MCF_CFM_CFMCMD = MCF_CFM_CFMCMD_PAGE_ERASE; MCF_CFM_CFMUSTAT = MCF_CFM_CFMUSTAT_CBEIF; while (! (MCF_CFM_CFMUSTAT & MCF_CFM_CFMUSTAT_CBEIF)) { assert(! (MCF_CFM_CFMUSTAT & (MCF_CFM_CFMUSTAT_PVIOL|MCF_CFM_CFMUSTAT_ACCERR))); } npages--; addr += FLASH_PAGE_SIZE/sizeof(uint32); } while(! (MCF_CFM_CFMUSTAT & MCF_CFM_CFMUSTAT_CCIF)) { }; // and re-flash it from the staging area addr = NULL; data = (uint32 *)(FLASH_BYTES/2); nwords = FLASH_BYTES/2/sizeof(uint32); while (nwords) { assert(MCF_CFM_CFMCLKD & MCF_CFM_CFMCLKD_DIVLD); assert(MCF_CFM_CFMUSTAT & MCF_CFM_CFMUSTAT_CBEIF); assert(! (MCF_CFM_CFMUSTAT & (MCF_CFM_CFMUSTAT_PVIOL|MCF_CFM_CFMUSTAT_ACCERR))); backdoor_addr = (uint32 *)(__IPSBAR+0x04000000+(int)addr); *backdoor_addr = *data; MCF_CFM_CFMCMD = MCF_CFM_CFMCMD_WORD_PROGRAM; MCF_CFM_CFMUSTAT = MCF_CFM_CFMUSTAT_CBEIF; while (! (MCF_CFM_CFMUSTAT & MCF_CFM_CFMUSTAT_CBEIF)) { assert(! (MCF_CFM_CFMUSTAT & (MCF_CFM_CFMUSTAT_PVIOL|MCF_CFM_CFMUSTAT_ACCERR))); } nwords--; addr++; data++; } while(! (MCF_CFM_CFMUSTAT & MCF_CFM_CFMUSTAT_CCIF)) { }; // erase the staging area addr = (uint32 *)(FLASH_BYTES/2); npages = FLASH_BYTES/2/FLASH_PAGE_SIZE; while (npages) { assert(MCF_CFM_CFMCLKD & MCF_CFM_CFMCLKD_DIVLD); assert(MCF_CFM_CFMUSTAT & MCF_CFM_CFMUSTAT_CBEIF); assert(! (MCF_CFM_CFMUSTAT & (MCF_CFM_CFMUSTAT_PVIOL|MCF_CFM_CFMUSTAT_ACCERR))); backdoor_addr = (uint32 *)(__IPSBAR+0x04000000+(int)addr); *backdoor_addr = 0; MCF_CFM_CFMCMD = MCF_CFM_CFMCMD_PAGE_ERASE; MCF_CFM_CFMUSTAT = MCF_CFM_CFMUSTAT_CBEIF; while (! (MCF_CFM_CFMUSTAT & MCF_CFM_CFMUSTAT_CBEIF)) { assert(! (MCF_CFM_CFMUSTAT & (MCF_CFM_CFMUSTAT_PVIOL|MCF_CFM_CFMUSTAT_ACCERR))); } npages--; addr += FLASH_PAGE_SIZE/sizeof(uint32); } while(! (MCF_CFM_CFMUSTAT & MCF_CFM_CFMUSTAT_CCIF)) { }; // reset the CPU MCF_RCM_RCR = MCF_RCM_RCR_SOFTRST; asm { halt }}voidflash_upgrade_end(void){ // NULL}
// disable interrupts x = splx(7); // copy our flash upgrade routine to RAM memcpy(RAM_CODE_PAGE, flash_upgrade, (int)flash_upgrade_end - (int)flash_upgrade); // and run it! fn = (void *)RAM_CODE_PAGE; fn(); // we should not come back! assert(0); splx(x);
#define FLASH_PAGE_SIZE 2048#define FLASH_BYTES (128*1024)
Hi Rich !
Im trying to implement the bootloader that you post. Im very new in this technology (coldfire) so I have a little problems trying to understand some part of the code and I need you help, I hope you can help me with my doubts.
The problems are:
1.- In the RM of the MCF52223 say: "Prior to issuing any command, it is necessary to write the CFMCLKD register to divide the input clock to within the 150 KHz to 200 KHz range." In your code, there isn't anything like that.... So, I have to do it before call the flash_upgrade function??
2.- I don't understand how the erase page and program page command take the direction that it should be the one in the backdoor_addr, How it happens?
3.- The function splx and memcpy ... Where is declare or what it does?
4.- The "RAM_CODE_PAGE" what it is? It is a part of a linker file or what? How I declare a correct RAM_CODE_PAGE ??
5.- How I should declare the "fn"
6.- And the last one is... On the function "flash_upgrade_end" what I should do??
I will very thankful if you can help me to solve this doubts ! Thanks in advance for your time !!
PS. Sorry for my bad english.
#define assert(x) if (! (x)) { asm { halt } }