MCF51AC256 - Problems copying flash routine to RAM

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

MCF51AC256 - Problems copying flash routine to RAM

1,200 Views
Kaare
Contributor III

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?

Labels (1)
0 Kudos
Reply
5 Replies

731 Views
Kaare
Contributor III

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?!?

0 Kudos
Reply

731 Views
kef
Specialist I
  •  // Wait for the command buffer to be ready
  •  while(!FSTAT_FCBEF)
  •  
  •  FSTAT = 0x30;  /* Clear FACCERR & PVIOL flags, if set */
     

^^ here you are waiting for FCBEF resetting FACCERR and PVIOL on each iteration. In case FCBEF==1 you are not clearing FACCERR abd PVIOL!

 

  •     while ((FSTAT & 0x40) == 0)  /* wait for command to complete */
  •    EnableInterrupts;

^^ 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.

0 Kudos
Reply

731 Views
Kaare
Contributor III

Souch an obvious mistake!! :smileysurprised:

 

Never noticed that i forgot the ";"

 

 

It now runs if i run it through the debugger.

0 Kudos
Reply

731 Views
Kaare
Contributor III

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??

0 Kudos
Reply

731 Views
PEGE
Contributor I

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

 

0 Kudos
Reply