Ilegal opcode when runing code in RAM (MCF52233)

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

Ilegal opcode when runing code in RAM (MCF52233)

2,260 Views
RubenV
Contributor I
Hi all.
After a few days searching on Internet, I have succesfully learned how to copy functions from ROM to RAM using the directive __declspec. It seems to do its work fine, since it defines a seccion of RAM to place the functions and copy them there.
The problem comes when I execute the functions. It starts fine, but after a while, executes opcodes that are invalid.
I don't know where is the problem, if in the .lcf or in the program. I show you the interesting part of both:
-The LCF:
 
Code:
    .text :    {        . = ALIGN(0x10);        mcf52235_vectors.s (.text)        *(.text)        *(.rodata)     . = ALIGN(0x10);        ___DATA_ROM     = .;    } > rom        .data_bss : AT(___DATA_ROM)    {        ___DATA_RAM     = .;        *(.data)        *(.sdata)                . = ALIGN (0x10);        *(.boot)        . = ALIGN (0x10);                ___DATA_END     = .;        .               = ALIGN(0x10);        ___BSS_START    = .;        *(.sbss)        *(SCOMMON)        *(.bss)        *(COMMON)        ___BSS_END      = .;                .               = ALIGN(0x10);        ___SP_END       = .;        .               = . + (0x800);        ___SP_INIT      = .;        .               = . + (4);        ___HEAP_START   = .;        ___HEAP_END     = ___SRAM + ___SRAM_SIZE;    } > ram

 The boot section is where I have all the functions I want to execute from RAM. I put it between __DATA_RAM and __DATA_END, so the function common_startup copies it from ROM to RAM for me.
 
-The Program Code:
 
Code:
#pragma define_section bootloader ".boot" far_code__declspec(bootloader) void flash_update_i2c(){ /*Some variable declarations*/        uint32 addr;        uint8 i;        /*Code*/
       ....
 addr=0; i=0;
        ....}

 When It executes the line addr=0 (although it is not the first command it executes in RAM) it fails due to an illegal operator:
 
-Code mixed C and Assembler:
Code:
        ... addr=0;20000528: 00042D40        ori.b    #0x40,d42000052C: FEF8            dc.w     0xfef8                  ; Invalid opcode  i=0;2000052E: 7000            moveq    #0,d020000530: 2D40FEE8        move.l   d0,-280(a6)        ...

 There are some code lines that it executes fine (the lines before addr, i=0, etc) and there are others that it don't execute fine (addr=0, between others).
 
Why can it be? Bad allignment in the .LCF? It is alligned to 16, like in ROM...
 
I'm completely lost...
 
Thanks in advance,
Rubén Valls

Labels (1)
0 Kudos
6 Replies

830 Views
SimonMarsden_de
Contributor II
Hello Rubén

I'm interested by the disassmbly listing:

Code:
        ...
 addr=0;
20000528: 00042D40        ori.b    #0x40,d4
2000052C: FEF8            dc.w     0xfef8                  ; Invalid opcode

 i=0;
2000052E: 7000            moveq    #0,d0
20000530: 2D40FEE8        move.l   d0,-280(a6)
        ...


I think that what the compiler produced was probably:

Code:
        ...
 addr=0;
20000528: 7000            moveq    #0,d0
2000052A: 2D40FEF8        move.l   d0,-264(a6)
 i=0;
2000052E: 7000            moveq    #0,d0
20000530: 2D40FEE8        move.l   d0,-280(a6)
        ...

If you compare the opcodes you will see that I came up with this by changing the two bytes at address 0x20000528 from 0x0004 back to 0x7000.

In other words, my guess is that either the first two bytes are not being copied from ROM to RAM correctly, or (more likely?) the value is being changed before the code executes.

You could verify this hypothesis using the debugger.

Hope this helps


Simon

0 Kudos

830 Views
RubenV
Contributor I
Hi again.
 
Thanks Simon for pointing me to the right direction :smileyvery-happy:. But the problem is not solved.
 
I have made some (insignificant) changes, and the result has been the same. Then, I have followed the copy of each byte from ROM  to RAM, and realized that some bytes are not copied (the ones wich cause the errors), but the others are.
I show you a part of memory where this happens (at 0x193de, the underlined part):
 
Code:
Source (ROM):000193ce:   66 a0 22 2e fe e8 20 2e fe f0 b2 80 65 00 fe 94 |f."... .....e...000193de:   10 3c 00 80 13 c0 40 11 00 00 60 fe 4e 71       |.<....@...`.NqDestination (RAM):20000ade:   66 a0 22 2e fe e8 20 2e fe f0 b2 80 65 00 fe 94 |f."... .....e...20000aee:   00 04 00 80 13 c0 40 11 00 00 60 fe 4e 71       |......@...`.Nq           
 And this is the function used to copy them:
 
Code:
void boot_copy(void){    extern char __START_COPY_TO_RAM[];    extern char __END_COPY_TO_RAM[];    extern char __START_COPY_ROM[];    uint32 n;    uint8 *dp, *sp;     dp = (uint8 *)__START_COPY_TO_RAM;    sp = (uint8 *)__START_COPY_ROM;    n = __END_COPY_TO_RAM - __START_COPY_TO_RAM;    while (n--)    {      *dp = *sp;      dp++;      sp++;    }}

About the question of being modified after copy them, I have all interrupts disabled. After calling that function, I execute the next orders:

Code:
asm {move.w #0x7700,sr}MCF_INTC0_IMRL |= MCF_INTC_IMRL_MASKALL;

What is happening has no sense... I don't know why almost all the bytes are copied OK, but there are some bytes that aren't... and not always are the same, now they are at 0x200 0AEE, and in the previous post, they where at 0x2000 0528...

Thanks in advance,

Rubén
 
Edit: I have tried to write directly my own values and the result is that they have not been copied. I used the easiest way to do this:
 
Code:
uint8 *x;x=(uint8 *)0x20000AEE;*x=10;*x=20;*x=30;

The result is that the value 0x00 is never replaced. Can the RAM memory be damaged anyway? Just in a few bytes? Or I'm addressing some reserved bytes?
This does NOT happen with the address of the first message... What is happening?
I'm completely missed...
I'm going to try with another board (and other project) to check it...


Message Edited by RubenV on 2008-12-19 09:43 AM
0 Kudos

830 Views
SimonMarsden_de
Contributor II
Hi Rubén

I notice that the altered value is the same: 0x0004. Any clue in that?

Two other suggestions:

(1) I suggest you disable interrupts before copying the data from ROM to RAM, just to completely exclude the possibility of the change being caused by an interrupt

(2) Have you seen the MCF5223X Device Errata? The link is:

http://www.freescale.com/files/32bit/doc/errata/MCF52235DE.pdf

It describes a problem with speculative reads from Flash at the same time as writing to SRAM, together with a solution involving the FLASHBAR register. Have you seen / tried that?


Cheers


Simon
0 Kudos

830 Views
RubenV
Contributor I
Hi again.
 
Jeje, I write "after" when I want to say "before" :smileyvery-happy:, so sugestion (1) was already checked.
 
About sugestion (2), I read about it, but in the init of the program the bit 6 of the FLASHBAR was already set. Anyway, I inserted a few nops between easier operations (use x=*sp, *dp=x instead of *dp=*sp) and the result is the same.
 
I'm going to surrender and try another way to do the bootloader: executing it from a single page of ROM and don't updating it. If anytime I could do the copy correctly, then I will include the good bootloader in the new image, they will coexist during one release (although the old will not be used) and the old will be deleted in the next update, so it is not a great lose.
 
Thanks for the help,
Rubén
0 Kudos

830 Views
CrasyCat
Specialist III
Hello
 
Did you look at FAQ 27860 on www.freescale.com?
This should explain how to achieve what you are looking for.
 
The .lcf file you are showing is missing some important WRITEW commands.
 
CrasyCat
0 Kudos

830 Views
RubenV
Contributor I
Hi, thanks for the quick reply.
 
I have already seen the WRITEW commands, but what I have understood is that this commands are usefull to copy from ROM to RAM. I have replaced the use of this commands by the use of the function common_startup, in startup.c (something like the second method in the FAQ page tells). This function already copies the code at the begining of the executation:
 
Code:
    if (__DATA_ROM != __DATA_RAM)    {        dp = (uint8 *)__DATA_RAM;        sp = (uint8 *)__DATA_ROM;        n = __DATA_END - __DATA_RAM;        while (n--)            *dp++ = *sp++;    }

 It should work, because I inserted my section ".boot" between __DATA_RAM and __DATA_END, so automatically this function will copy it without modifying anymore the .lcf.
 
And about the WRITEW commands, I try with them, but I really don't know how to use the S_romp table, nor what it is exactly, and when I compile I get the error that _romp_at doesn't exists...
 
Thanks,
Rubén Valls


Message Edited by RubenV on 2008-12-18 11:17 AM
0 Kudos