How to copy from ROM to RAM?

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

How to copy from ROM to RAM?

4,093 Views
PW_CTL
Contributor III
Hi,
I am trying to do an i2c flash programmer, and I need to allocate some functions (i2c and flash controllers) on RAM while flash is being upgraded.
I´ve found this FAQ:

http://www.freescale.com/webapp/sps/utils/SingleFaq.jsp?FAQ-27860.xml

which is exactly what I need, but I can´t make the CopyCode function work. Any idea?


Labels (1)
0 Kudos
22 Replies

1,210 Views
CompilerGuru
NXP Employee
NXP Employee
What did not work for you?
How does it fail?
Can you share your attempt?
Does your code use runtime routines (check the disassembled code)?

BTW, CopyCode is a section there, not a function.

Daniel
0 Kudos

1,210 Views
PW_CTL
Contributor III
Hi CompilerGuru, and thank you for your fast reply.

I am following the second method of the 
FAQ-27860, and this is the function CopyCode:

void CopyCode(void) {
char *src, *dest;
long size;
src=(char *)ROMCodeToCopy;
dest = (char *)_START_CopiedToRAM;
size = _END_CopiedToRAM - _START_CopiedToRAM;
if (dest != src)
while (size--)
*dest++ = *src++;
}


The problem is that this function uses next variables (should be defined as "far" to write in RAM):

extern char far ROMCodeToCopy[];
extern char far  _START_CopiedToRAM[];
extern char far  _END_CopiedToRAM[];
extern unsigned long far SizeCodeToCopy[];

but that variables causes a link error: "L1822: Symbol
ROMCodeToCopy in file ... is undefined" (they aren´t!)


Is there any other method to run code from RAM?
How can I see if my code uses runtime routines?
I am using Codewarrior Version 6.2.
0 Kudos

1,210 Views
CompilerGuru
NXP Employee
NXP Employee
Which chip are you targeting?
out of FAQ-27860:
> With CodeWarrior's Coldfire ...
so this FAQ targets coldfire. However you asked this question in the 8-Bit MCU forum. CF has a few more bits :smileyhappy:.

If you are targeting an HC08/S08/HC12, then follow bigmacs suggestions.
For CF, the identifier have to be defined in the lcf file, so make sure you did all the modifications in there as described in the FAQ.

Daniel

0 Kudos

1,210 Views
PW_CTL
Contributor III
Thanks, Mac and Daniel.

I´m using a MC9SO8SH8. 
0 Kudos

1,210 Views
PW_CTL
Contributor III
BigMac, only a question about your code:

void CopyInRAM(void)
{
   char *srcPtr, *dstPtr;
   int count;

   srcPtr = (char *)Start_data;
   dstPtr = (char *)(void *)&Flash_Cmd;
   for (count = 0; count < (int)Size_data; count++) {
      *dstPtr = *srcPtr;
      dstPtr++;
      srcPtr++;
   }
}

What is Flash_Cmd? This way, you are copying one function into RAM, but are you running the code from RAM?.

Thank you for your help.
0 Kudos

1,210 Views
bigmac
Specialist III
Hello,

The function flash_Cmd() is the RAM based function code that is copied from flash, and is run from RAM.  As indicated in my previous post, to place the code at the required flash location, the function code must be preceeded by -
#pragma CODE_SEG FLASH_ROUTINES

Regards,
Mac




Message Edited by bigmac on 2009-02-06 09:22 AM
0 Kudos

1,210 Views
PW_CTL
Contributor III
Hi again. Finally, the functions seems to be working, but when I execute a flash erase (it executes from RAM), I lost my variables stored in RAM.

I tried to define a new sector in RAM to allocate my variables, but it causes a compilation error. Have you ever hear that error? Is it possible to allocate a variable on a specific sector of the RAM?
0 Kudos

1,210 Views
bigmac
Specialist III
Hello,

Which variables are being over-written?  Are they local variables on the stack, or global/static variables?

Have you allowed a sufficient block size within the .PRM file to fully accommodate the RAM function without too much excess?  What is the RELOCATE_TO address in RAM?  If using a method similar to my previous post, the whole block size will be copied to RAM, independent of the size of the actual function code.

Do you have any large array variables declared within main()?  These will permanently occupy stack space and will cause downward stack growth.  If they are large, it may be better to handle these as globals.

I suspect that the variables are probably being over-written during the copy process.  Perhaps post your PRM file contents to give a better idea of your problem and its solution.

Regards,
Mac

0 Kudos

1,210 Views
PW_CTL
Contributor III

You said

"Are they local variables on the stack, or global/static variables?"

I think here is the key, because I have changed this variables (local) to static ones (global) and the program is working now!

Thanks for your help.


0 Kudos

1,210 Views
bigmac
Specialist III
Hello,

There may still be a potential problem if the copy function is over-writing a portion of the stack, and the stack size is not sufficiently large.

Regards,
Mac

0 Kudos

1,210 Views
PW_CTL
Contributor III
Yes, I´ve checked it, and the stack is big enough.

Finally, my program is allocated in three memory blocks. One of them is for the general code (main function...), a second one is for the i2c functions and the last one is for the flash functions, which are also allocated in ram.

I need the i2c functions working while I am programming the first block, but this functions are too big to be allocated in ram. Could it suppose a problem? It there any restriction on that?. Can I erase one sector of the flash and after that execute the code of other sector?

Thanks for your help.
0 Kudos

1,210 Views
bigmac
Specialist III
Hello,

The 'SH8 device has only a single flash array, so the entire flash memory is not accessible at the point where programming (or erase) occurs, when the internal charge pump is operative.  The IIC peripheral hardware should remain operative, however the data cannot be accessed using flash based code, until the programming process is completed.

I would suggest that you do not use burst programming mode, but program a single byte at a time.  This way IIC operations can possibly be interleaved between the programming of each byte.

Regards,
Mac



0 Kudos

1,210 Views
PW_CTL
Contributor III
I can´t program byte by byte because it´s too unsecure (there are other devices on my board using iic). I send the .s19 file line by line, and only if the checksum is correct this line is writed.

Anyway, I have put a long delay (about 5 seconds) after a flash writing, and the program fails as soon as I try to run a function located on flash (IIC functions to send an ack, this functions are located at the end of the flash, and i have written only in the first sector).

Should I have to do something after a flash writing to return to "normal mode" after running flash functions (flash functions are executed from ram) ?
0 Kudos

1,210 Views
bigmac
Specialist III
Hello,

I do not know why you believe that byte by byte flash programming is more "unsecure" than burst programming.  The only difference that I am aware of is a marginally shorter duration for burst programming.

Does the MCU operate as the IIC master or slave device?  If a master, the delays associated with programming/erase operations should be readily accommodated since the master has complete control over IIC operation.

An IIC slave would be more problematic.  However, slave operation would also appear incompatible with the presence of more than one external IIC device.

Regards,
Mac

0 Kudos

1,210 Views
PW_CTL
Contributor III
Hi, bigmac.

I have been doing some test and here are the results.

Right now, I have been programming in flash strings of bytes, but I have been doing it byte by byte always. After your last message, I have modified my code to read a byte via IIC and move it to the flash. Here is the function to  program a byte on the flash:

#pragma CODE_SEG FLASH_ROUTINES
unsigned char Flash_Cmd(unsigned int FlashAddress, unsigned int FlashDataCounter, unsigned char* pFlashDataPtr, unsigned char FlashCommand)
{
    /* Check to see if FACCERR or PVIOL is set */
    if (FSTAT&0x30) 
    {        
        /* Clear Flags if set*/
        FSTAT = FSTAT | 0x30; 
    }

    if (FlashDataCounter)
    {
      do
      {
          /* Wait for the Last Busrt Command to complete */
          while(!(FSTAT&0x80));
         
          /* Write Data into Flash*/
          (*((volatile unsigned char *)(FlashAddress++))) = *pFlashDataPtr;
          pFlashDataPtr++;
          /* Write Command */
          FCMD = FlashCommand;
          _asm NOP;
          _asm NOP;
          _asm NOP;
          _asm NOP;
         
          /* Put FCBEF at 1 */
          FSTAT = 0x80;
          /* Check if Flash Access Error or Protection Violation Error are Set */
          if (FSTAT&0x30)
          {    
            /* If so, finish the function returning 1 to indicate error */
            return (1);
          }
      }while (--FlashDataCounter);
    }
    /* wait for the last command to complete */
    while ((FSTAT&0x40)==0);
 
    /* Return zero to indicate that the function executed Ok */
    return (0);
}

#pragma CODE_SEG DEFAULT

  #define Flash_Program(Address, Data) \
          Flash_Cmd((unsigned int)Address, (unsigned int)1, (unsigned char*)&Data, FLASH_PROGRAM_CMD)


My MCU is the slave, and the master does not support holding the scl line to make a pause. 

I tried next code:

DisableInterrupts;
Flash_Erase(0xC000);

for (tmp4=0;tmp4<0xff;tmp4++)
        Flash_Program(0xC000 + tmp4, tmp4);
tmp4=0;      
EnableInterrupts;

And it works succesfully, but when I tried:
        while (!I2C1_GetCharsInRxBuf()){}
        if(I2C1_RecvChar(&tmp4)==ERR_OK) {  //Numero de bytes que se van a recibir
        I2C1_ClearRxBuf();
        DisableInterrupts;
        Flash_Erase(0xC000);
        EnableInterrupts;
        for (tmp5=0;tmp5<tmp4;tmp5++){    //Bucle a esos bytes
          while (!I2C1_GetCharsInRxBuf()){}
          if(I2C1_RecvChar(&tmp3)==ERR_OK) {
            if(I2C1_RecvChar(&tmp3));  
            I2C1_ClearRxBuf();
            DisableInterrupts;
            Flash_Program(0xC000 + tmp5, tmp3);
            EnableInterrupts;

          }
        }

It is basically the same code reading data via IIC and waiting for every byte. This code fails, and disconnects the debugger after erasing the rom. It´s needed to reprogram again. Each IIC byte has a delay of 1 second. Right now, I have no idea about what´s wrong...
IIC functions are located on a specific "partition" of the ROM, which is never flashed.

Any suggestion?





0 Kudos

1,210 Views
bigmac
Specialist III
Hello,

I suspect that the COP timer is timing out whilst waiting to receive an IIC data byte.  The COP timer will need to be cleared within the wait loop.

Regards,
Mac

0 Kudos

1,209 Views
PW_CTL
Contributor III
Finally, I get the program working. I have divided the program in two steps, the first one copy the new flash to a empty partition writing it byte by byte. After that, if the checksum is passed, I write the whole block to the "program" zone in the flash.

This way, I can replace my program, but what to do after that?. If I execute the next command after replacing the program, it causes an error. How to reboot the MCU to use the new program after flashing?
0 Kudos

1,209 Views
bigmac
Specialist III
Hello,

From within the boot loader program you will need to jump directly to the start of the application program, e.g. __asm jmp main;

This would be done after the boot loader determines that a valid application program is present, and the conditions required to enter boot load mode do not currently exist.

For all vectors, other than the reset vector, you will need to take into account the vector redirection location, assuming you have block protected the boot loader program.

Regards,
Mac



Message Edited by bigmac on 2009-02-18 11:02 AM
0 Kudos

1,209 Views
PW_CTL
Contributor III
Thanks for your help. Finally, I have the IIC flash programmer done and succesfully tested. Thanks again!
0 Kudos

1,210 Views
CompilerGuru
NXP Employee
NXP Employee
For the S08, only part of the referenced FAQ applies, especially the S08 does not use lcf's but prm's for the layout definition.

The topic how to execute code from ram got discussed in this forum quite a few times, for example:

http://forums.freescale.com/freescale/board/message?board.id=8BITCOMM&message.id=3483&query.id=9333#...

(I searched for CopyInRAM appears to be a commonly used name for this task :smileyhappy:.

Daniel
0 Kudos