I tried following FAQ-27860 which describes how to copy code from ROM to RAM. I need to do this so that i can program the FLASH in my device.
I got it to copy the flash program function, but it adds dc.w 0x000 statements in front of the function at the adress in RAM where it is supposed to be:
0x0080003c <Flash_Cmd>: dc.w 0x00000x0080003e <Flash_Cmd+2>: addq.l #7,(-128,a4,d0.w)0x00800042 <Flash_Cmd+6>: dc.w 0x00000x00800044 <Flash_Cmd+8>: dc.w 0x00000x00800046 <Flash_Cmd+10>: dc.w 0x00980x00800048 <Flash_Cmd+12>: dc.w 0x0000 //DisableInterrupts; FSTAT = 0x30; /* Clear FACCERR & PVIOL flags, if set */0x0080004a <Flash_Cmd+14>: dc.w 0x00000x0080004c <Flash_Cmd+16>: dc.w 0x00000x0080004e <Flash_Cmd+18>: dc.w 0x0000 if (FCommand == FLASH_PROGRAM_CMD) {0x00800050 <Flash_Cmd+20>: dc.w 0x00000x00800052 <Flash_Cmd+22>: dc.w 0x00000x00800054 <Flash_Cmd+24>: lea -12(a7),a7 /* Write data to flash location */ (*((volatile byte *)(FAddr))) = *pFDataPtr;0x00800058 <Flash_Cmd+28>: move.w d0,(a7)0x0080005a <Flash_Cmd+30>: move.l a0,4(a7) } else (*((volatile byte *)(FAddr))) = 0xFF;0x0080005e <Flash_Cmd+34>: move.b d1,8(a7)0x00800062 <Flash_Cmd+38>: moveq #48,d20x00800064 <Flash_Cmd+40>: move.b d2,0xFFFF9825 (0xffff9825) FCMD = FCommand; /* Enter command */0x00800068 <Flash_Cmd+44>: cmpi.b #32,d10x0080006c <Flash_Cmd+48>: bne.s Flash_Cmd+0x3a (0x800076); 0x00800076 FSTAT = 0x80; /* Set FCBEF bit */0x0080006e <Flash_Cmd+50>: mvz.w d0,d10x00800070 <Flash_Cmd+52>: movea.l d1,a10x00800072 <Flash_Cmd+54>: move.b (a0),(a1) /* Wait min. 4 cycles before reading flags */ __asm { NOP0x00800074 <Flash_Cmd+56>: bra.s Flash_Cmd+0x42 (0x80007e); 0x0080007e NOP0x00800076 <Flash_Cmd+58>: mvz.w d0,d1 NOP0x00800078 <Flash_Cmd+60>: movea.l d1,a0 NOP0x0080007a <Flash_Cmd+62>: move.b #-1,(a0) } while ((FSTAT & 0x40) == 0) /* wait for command to complete */ //EnableInterrupts; return (FSTAT & 0x30); /* Return FACCERR & PVIOL error status */0x0080007e <Flash_Cmd+66>: move.b 8(a7),d10x00800082 <Flash_Cmd+70>: move.b d1,0xFFFF9826 (0xffff9826)0x00800086 <Flash_Cmd+74>: moveq #-128,d10x00800088 <Flash_Cmd+76>: move.b d1,0xFFFF9825 (0xffff9825)0x0080008c <Flash_Cmd+80>: nop 0x0080008e <Flash_Cmd+82>: nop }0x00800090 <Flash_Cmd+84>: nop 0x00800092 <Flash_Cmd+86>: nop 0x00800094 <Flash_Cmd+88>: bra.s 0x008000A0 (0x8000a0) ; 0x008000a0
Here is the function code:
/*****************************************************************************///#pragma CODE_SEG __FAR_SEG CopyToRAM #pragma define_section CopyToRAM "CopyToRAM" far_code__declspec (CopyToRAM) byte Flash_Cmd( word FAddr, byte* pFDataPtr, byte FCommand){ //DisableInterrupts; FSTAT = 0x30; /* Clear FACCERR & PVIOL flags, if set */ if (FCommand == FLASH_PROGRAM_CMD) { /* Write data to flash location */ (*((volatile byte *)(FAddr))) = *pFDataPtr; } else (*((volatile byte *)(FAddr))) = 0xFF; FCMD = FCommand; /* Enter command */ FSTAT = 0x80; /* Set FCBEF bit */ /* Wait min. 4 cycles before reading flags */ __asm { NOP NOP NOP NOP } while ((FSTAT & 0x40) == 0) /* wait for command to complete */ //EnableInterrupts; return (FSTAT & 0x30); /* Return FACCERR & PVIOL error status */}#pragma CODE_SEG DEFAULT
And at last, my project.lcf file:
MEMORY { code (RX) : ORIGIN = 0x00000410, LENGTH = 0x0003FBF0 userram (RWX) : ORIGIN = 0x00800000, LENGTH = 0x00008000}SECTIONS {# Heap and Stack sizes definition ___heap_size = 0x0400; ___stack_size = 0x0400;# MCF51AC256A Derivative Memory map definitions from linker command files:# ___RAM_ADDRESS, ___RAM_SIZE, ___FLASH_ADDRESS, ___FLASH_SIZE linker# symbols must be defined in the linker command file.# 32 Kbytes Internal SRAM ___RAM_ADDRESS = 0x00800000; ___RAM_SIZE = 0x00008000;# 256 KByte Internal Flash Memory ___FLASH_ADDRESS = 0x00000000; ___FLASH_SIZE = 0x00040000; .userram : {} > userram .code : {} > code .text : { *(.text) . = ALIGN (0x4); *(.rodata) . = ALIGN (0x4); ___ROM_AT = .; ___DATA_ROM = .; } >> code .data : AT(___ROM_AT) { ___DATA_RAM = .; . = ALIGN(0x4); *(.exception) . = ALIGN(0x4); __exception_table_start__ = .; EXCEPTION __exception_table_end__ = .; ___sinit__ = .; STATICINIT __START_DATA = .; *(.data) . = ALIGN (0x4); __END_DATA = .; __START_SDATA = .; *(.sdata) . = ALIGN (0x4); __END_SDATA = .; ___DATA_END = .; __SDA_BASE = .; . = ALIGN (0x4); } >> userram .copyToRAM : AT(___DATA_ROM + SIZEOF(.data)) { . = ALIGN (0x4); __START_COPYTORAM = .; *(CopyToRAM) __END_COPYTORAM = .; . = ALIGN (0x4); } >> userram .bss : { ___BSS_START = .; __START_SBSS = .; *(.sbss) . = ALIGN (0x4); *(SCOMMON) __END_SBSS = .; __START_BSS = .; *(.bss) . = ALIGN (0x4); *(COMMON) __END_BSS = .; ___BSS_END = .; . = ALIGN(0x4); } >> userram .custom : { ___HEAP_START = .; ___heap_addr = ___HEAP_START; ___HEAP_END = ___HEAP_START + ___heap_size; ___SP_END = ___HEAP_END; ___SP_INIT = ___SP_END + ___stack_size; ___mem_limit = ___HEAP_END; ___stack_safety = 16; . = ALIGN (0x4); } >> userram __SP_INIT = ___SP_INIT; ___SP_AFTER_RESET = __SP_INIT; _romp_at = ___ROM_AT + SIZEOF(.data); .romp : AT(_romp_at) { __S_romp = _romp_at; WRITEW(___ROM_AT); WRITEW(ADDR(.data)); WRITEW(SIZEOF(.data) + SIZEOF(.copyToRAM)); WRITEW(0); WRITEW(0); WRITEW(0); }}
Any clues why this is happening?
Now i "solved" the copying issue.
I did this by following example 2 in the faq and implemented a custom copy function instead of using the one in startup.c:
extern char far ROMCodeToCopy[], _START_COPYTORAM[], _END_COPYTORAM[];void CopyCode(void){ char *src, *dest; long size; src=(char *)ROMCodeToCopy; dest = (char *)_START_COPYTORAM; size = _END_COPYTORAM - _START_COPYTORAM; if (dest != src) while (size--) *dest++ = *src++;}
This however wasn't enough to make it copy the correct data. I needed to change the project.lcf file and add an offset of 38 to get it to work:
_ROMCodeToCopy = ___DATA_ROM + SIZEOF(.data) + 38; .copyToRAM: AT(_ROMCodeToCopy) { __START_COPYTORAM = .; *(CopyToRAM) __END_COPYTORAM = .; . = ALIGN (0x4); } >> userram_romp_at = ___ROM_AT + SIZEOF(.data); .romp : AT(_romp_at) { __S_romp = _romp_at; WRITEW(___ROM_AT); WRITEW(ADDR(.data)); WRITEW(SIZEOF(.data) + SIZEOF(.copyToRAM)); WRITEW(0); WRITEW(0); WRITEW(0); }
I don't know why i need to add an offset of 38?!?
Also, i changed the flash programming routine a bit to reflect the fact that you need to write 32 bit values on a Coldfire v1 core:
#pragma define_section CopyToRAM "CopyToRAM" far_code__declspec (CopyToRAM) byte Flash_Cmd( word FAddr, int* pFDataPtr, byte FCommand){ DisableInterrupts; __asm { NOP NOP } // Wait for the command buffer to be ready while(!FSTAT_FCBEF) FSTAT = 0x30; /* Clear FACCERR & PVIOL flags, if set */ if (FCommand == FLASH_PROGRAM_CMD) { /* Write data to flash location */ (*((volatile int *)(FAddr))) = *pFDataPtr; } else { (*((volatile int *)(FAddr))) = 0xFFFFFFFF; } FCMD = FCommand; /* Enter command */ FSTAT = 0x80; /* Set FCBEF bit */ /* Wait min. 4 cycles before reading flags */ __asm { NOP NOP NOP NOP } while ((FSTAT & 0x40) == 0) /* wait for command to complete */ EnableInterrupts; return (FSTAT & 0x30); /* Return FACCERR & PVIOL error status */}
Now if i step through this in the debugger, it sometimes works, sometimes not. Sometimes it suddenly, at a random position within the above code, jumps to an invalid position in memory and therefore crashes on the next debug step.
As said, this only happens sometimes and at random position within the flash program routine if i debug. If i run the software on target, then it always restarts.
I have disabled watchdog and as you can see, i also disable interrupts when entering the flash programming routine.
Any clues what im doing wrong here?!?
^^ here you are waiting for FCBEF resetting FACCERR and PVIOL on each iteration. In case FCBEF==1 you are not clearing FACCERR abd PVIOL!
^^ the same here. You are waiting for flash command complete enabling interrupts on each iteration. Yes, it should runaway, because flash is not readable while erase or program takes place, so CPU will fetch wrong vector and bad things will happen if you have some interrupts enabled.
Souch an obvious mistake!!
Never noticed that i forgot the ";"
It now runs if i run it through the debugger.
I have now figured out the "offset" bug i had that i mentioned earlier in the project.lcf file. It was due to a missing info in the FAQ. Heres the working code for the lcf file:
.copyToRAM: AT(___DATA_ROM + SIZEOF(.data)) { __START_COPYTORAM = .; *(CopyToRAM) __END_COPYTORAM = .; . = ALIGN (0x4); } >> userram _romp_at = ___ROM_AT + SIZEOF(.data) + SIZEOF(.copyToRAM); .romp : AT(_romp_at) { __S_romp = _romp_at; WRITEW(___ROM_AT); WRITEW(ADDR(.data)); WRITEW(SIZEOF(.data) + SIZEOF(.copyToRAM)); WRITEW(0); WRITEW(0); WRITEW(0); }
Now it copies the code to RAM perfectly and everything just works perfectly - as long as i run my code through the BDM debugger! If i start the debugger and press 'Run', it just works.
If i program the MCU and let it run on it self, it resets as soon as it runs any flash write/erase operation.
As i this only happens when im not debugging, how should i proceed to find the problem??
replace
.copyToRAM : AT(___DATA_ROM + SIZEOF(.data)) { . = ALIGN (0x4); __START_COPYTORAM = .; *(CopyToRAM) __END_COPYTORAM = .; . = ALIGN (0x4); } >> userram
with
.copyToRAM : AT(___DATA_ROM + SIZEOF(.data)) { . = ALIGN (0x4); __START_copyToRAM = .; *(CopyToRAM) __END_copyToRAM = .; . = ALIGN (0x4); } >> userram