PLASH REMAPPING ISSUE FOR MPC5748G

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

PLASH REMAPPING ISSUE FOR MPC5748G

Jump to solution
965 Views
FAISAL0323
Contributor II

Dear Expert,

I am working on flash remapping for MPC5748G, but I am unable to remap physical address to the desired logical address. 

I have checked through debugging and found that all registers which are responsible for flash remapping has been written correctly as shown below.

FAISAL0323_0-1677032910409.png

since all registers has been written correctly but still, I cannot remap physical address to my desired logical address. 

my code is as follows.

__attribute__ ((section(".func1")))void memoryremapa ();

__attribute__ ((section(".func2")))void memoryremapb ();

void Overlay(uint32_t word0, uint32_t word1, uint32_t word2, uint32_t descriptor);

int main()

{

  Overlay(0x013c0000, 0x09200000, 0xFFFF0012, 0);

while(1)

  {

    memoryremapa();

    memoryremapb();

  }

}

__attribute__ ((section(".func1")))void memoryremapa ()

{

  for (uint32_t i = 0; i < 500000; i++) {}

  LED2_TOGGLE;

}

__attribute__ ((section(".func2")))void memoryremapb ()

{

  for (uint32_t i = 0; i < 500000; i++) {}

  LED0_TOGGLE;

}

void Overlay(uint32_t word0, uint32_t word1, uint32_t word2, uint32_t descriptor)

{

       PFLASH_Type*const base = PFLASH;

       base->PFCRD[descriptor].Word2 = word2;/* Enable remapping for individual masters, size of page */

       base->PFCRD[descriptor].Word0 = word0;/* Logical address */

       base->PFCRD[descriptor].Word1 = word1;/* Physical address */

       base->PFCRDE|= (uint32_t)0x80000000 >> descriptor;    /* Enable descriptor */

 

       base->PFCRCR = PFLASH_PFCRCR_GRMEN(1);

       base->PFCRCR |= PFLASH_PFCRCR_IRMEN(1);

}

 

This is how my linker file looks like.

FAISAL0323_1-1677033920182.png

 

according to code, physical address 0x013c0000 memoryremapb() function has been remapped to logical address 0x09200000 which is mirrored of physical address so memoryremapb() function should be executing instead of memoryremapa() function, but I found both functions they are executing. Please let me know what the problem is. 

Regards

Muhammad Faisal Khan

 

Tags (1)
0 Kudos
1 Solution
927 Views
lukaszadrapa
NXP TechSupport
NXP TechSupport

Attached is working example.

Function test() is forced to 0x0110_0000 by linker file but it's compiled for address 0x0930_0000 (using AT directive).

This is default state - function at 0x0x0110_0000 is simply mirrored to 0x0910_0000 as expected (no remapping yet):

lukaszadrapa_0-1677147566470.png

This is a state after remapping - after execution of Overlay() function. I remapped it to 0x0930_0000:

lukaszadrapa_1-1677147616487.png

And once stepping into test(), I can see that the code is successfully executing from this address:

lukaszadrapa_2-1677147663150.png

And one more important thing which you can see in the example - it is necessary to allow instruction fetching from remapped space by:

PFLASH.PFCRCR.B.IRMEN = 1; /* Allow instruction fetches */

Regards,

Lukas

View solution in original post

0 Kudos
6 Replies
943 Views
lukaszadrapa
NXP TechSupport
NXP TechSupport

Hi @FAISAL0323 

First thing is that you mismatched logical and physical address.

Overlay(0x013c0000, 0x09200000, 0xFFFF0012, 0);
void Overlay(uint32_t word0, uint32_t word1, uint32_t word2, uint32_t descriptor)
base->PFCRD[descriptor].Word0 = word0;/* Logical address */
base->PFCRD[descriptor].Word1 = word1;/* Physical address */

According to this, you are trying to remap normal flash by mirrored flash. But it works in opposite way. You can remap only mirrored space.

Regardless of that, the idea is also different. You simply forced one function to 0x138000 and second to 0x13C000. So, anytime you call these functions, those will be executed from this normal flash. This is expected behavior. It doesn't matter if you enabled the overlay feature or not. The only thing that will happen is that the code will be visible also at desired address in mirrored address space.
If you want to execute a function from remapped/mirrored address, you need to compile the function for this address space, so it will be stored in normal flash but compiled for remapped addresses. Just an example:

m_text1 : org = 0x1100000, len = 1K
m_text1_mirror : org = 0x9100000, len = 1K

.func1 :
{
KEEP(*(.func1))
} > m_text1_mirror AT>m_text1

If you call a function from .func1 section now, it will jump to remapped/mirrored address.

Regards,
Lukas

0 Kudos
932 Views
FAISAL0323
Contributor II

Dear Lukas,

Thanks for the detailed reply, I tried the solution given by you but still I am unable to get my desired results. I still have problem. Please have a look at my code and linker file to let me know what the problem is.  

#include "derivative.h" /* include peripheral declarations */

extern void xcptn_xmpl(void);

__attribute__ ((section(".func1"))) void memoryremapa();
__attribute__ ((section(".func2"))) void memoryremapb();

int main(void)
{
volatile int counter = 0;

xcptn_xmpl (); /* Configure and Enable Interrupts */

// Setup the remap logic and physical addresses,
// per-master enable, and region size.
PFLASH.PFCRD[0].Word0.R = 0x09200000; // logical address
PFLASH.PFCRD[0].Word1.R = 0x01200000; // physical address
PFLASH.PFCRD[0].Word2.R = 0xffff0012; // 256KB region

// Enable remap descriptor 0.
PFLASH.PFCRDE.R = 0xffff0000;

// Enable instruction remap.
PFLASH.PFCRCR.B.IRMEN = 1;

// Enable flash remap.
PFLASH.PFCRCR.B.GRMEN = 1;

memoryremapa();

while (1);

/* Loop forever */
for(;;) {
counter++;
}
}


__attribute__ ((section(".func1"))) void memoryremapa()
{
uint8_t b = 1;
uint8_t c = 0;

if(b ==1)
{
c = 9;
}
else
{c = 10;}

}

__attribute__ ((section(".func2"))) void memoryremapb()
{
uint8_t b = 1;
uint8_t c = 0;

if(b ==1)
{
c = 9;
}
else
{c = 10;}


}

memoryremapb() function which is placed at 0x01200000 physical address has been remapped to 0x09200000 logical address but when I try to execute a function from remapped/mirrored address, after compile the function for 0x09200000 logical address but still I am unable to execute that, infect still when I call memoryremapa() function, it still executes memoryremapa() function definition only. but i want, remapped function should be executing which is memoryremapb().

 

Lastly, I would like to know how we can see contents of logical address through debugging to make it sure remapping has been done successfully?

Here is linker file. 

/* Entry Point */
ENTRY(_start)

/* define heap and stack size */
__HEAP_SIZE = 0 ;
__STACK_SIZE = 4096 ;

SRAM_SIZE = 256K;
/* Define SRAM Base Address */
SRAM_BASE_ADDR = 0x40000000;

MEMORY
{

flash_rchw : org = 0x00FA0000, len = 0x4
cpu0_reset_vec : org = 0x00FA0000+0x10, len = 0x4
cpu1_reset_vec : org = 0x00FA0000+0x14, len = 0x4
cpu2_reset_vec : org = 0x00FA0000+0x04, len = 0x4

m_text : org = 0x1000000, len = 256K

m_text1 : org = 0x01100000, len = 256K
m_text2 : org = 0x01200000, len = 256K

m_text2_mirror : org = 0x09200000, len = 256K

m_data : org = 0x40000000, len = 256K
}


SECTIONS
{
.func1 :
{
KEEP*(.func1)
} > m_text2_mirror AT>m_text2

.func2 :
{
KEEP*(.func2)
} > m_text2

.rchw :
{
KEEP(*(.rchw))
} > flash_rchw

.cpu0_reset_vector :
{
KEEP(*(.cpu0_reset_vector))
} > cpu0_reset_vec

.cpu1_reset_vector :
{
KEEP(*(.cpu1_reset_vector))
} > cpu1_reset_vec

.cpu2_reset_vector :
{
KEEP(*(.cpu2_reset_vector))
} > cpu2_reset_vec

/* Note: if you move the 'startup' section shall modify the RCHW2_0 value for the corresponding core in the flashrchw.c file. */
.startup : ALIGN(0x400)
{
__start = . ;
*(.startup)
} > m_text

.core_exceptions_table : ALIGN(4096)
{
__IVPR_VALUE = . ;
KEEP(*(.core_exceptions_table))
} > m_text

.intc_vector_table : ALIGN(4096)
{
KEEP(*(.intc_vector_table))
} > m_text

.text :
{
*(.text.startup)
*(.text)
*(.text.*)
KEEP (*(.init))
KEEP (*(.fini))
. = ALIGN(16);
} > m_text

.ctors :
{
__CTOR_LIST__ = .;
/* gcc uses crtbegin.o to find the start of
the constructors, so we make sure it is
first. Because this is a wildcard, it
doesn't matter if the user does not
actually link against crtbegin.o; the
linker won't look for a file to match a
wildcard. The wildcard also means that it
doesn't matter which directory crtbegin.o
is in. */
KEEP (*crtbegin.o(.ctors))
KEEP (*crtbegin?.o(.ctors))
/* We don't want to include the .ctor section from
from the crtend.o file until after the sorted ctors.
The .ctor section from the crtend file contains the
end of ctors marker and it must be last */
KEEP (*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
__CTOR_END__ = .;
} > m_text

.dtors :
{
__DTOR_LIST__ = .;
KEEP (*crtbegin.o(.dtors))
KEEP (*crtbegin?.o(.dtors))
KEEP (*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
__DTOR_END__ = .;
} > m_text

.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array*))
PROVIDE_HIDDEN (__preinit_array_end = .);
} > m_text

.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array*))
PROVIDE_HIDDEN (__init_array_end = .);
} > m_text

.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT(.fini_array.*)))
KEEP (*(.fini_array*))
PROVIDE_HIDDEN (__fini_array_end = .);
} > m_text

.rodata :
{
*(.rodata)
*(.rodata.*)
*(.got1)
} > m_text

.eh_frame_hdr : { *(.eh_frame_hdr) } > m_text
.eh_frame : { KEEP (*(.eh_frame)) } > m_text

.data :
{
*(.data)
*(.data.*)
*(.got.plt)
*(.got)
*(.got2)
*(.dynamic)
*(.fixup)
. = ALIGN(4);
} > m_data AT>m_text

.sdata2 :
{
*(.sdata2)
*(.sdata2.*)
} > m_data AT>m_text

.sbss2 (NOLOAD) :
{
/* _SDA2_BASE_ = .; */
*(.sbss2)
*(.sbss2.*)
} > m_data

.sdata :
{
*(.sdata)
*(.sdata.*)
} > m_data AT>m_text

.bss (NOLOAD) :
{
__BSS_START = .;
*(.sbss)
*(.sbss.*)
*(.bss)
*(.bss.*)
*(COMMON)
__BSS_END = .;
} > m_data

.stack (NOLOAD) : ALIGN(16)
{
__HEAP = . ;
PROVIDE (_end = . );
PROVIDE (end = . );
. += __HEAP_SIZE ;
__HEAP_END = . ;
_stack_end = . ;
. += __STACK_SIZE ;
_stack_addr = . ;
__SP_INIT = . ;
. += 4;
} > m_data

/*-------- LABELS USED IN CODE -------------------------------*/

/* Labels for Copying Initialised Data from Flash to RAM */
__DATA_SRAM_ADDR = ADDR(.data);
__SDATA_SRAM_ADDR = ADDR(.sdata);

__DATA_SIZE = SIZEOF(.data);
__SDATA_SIZE = SIZEOF(.sdata);

__DATA_ROM_ADDR = LOADADDR(.data);
__SDATA_ROM_ADDR = LOADADDR(.sdata);

/* Labels Used for Initialising SRAM ECC */
__SRAM_SIZE = SRAM_SIZE;
__SRAM_BASE_ADDR = SRAM_BASE_ADDR;

__BSS_SIZE = __BSS_END - __BSS_START;

}

Thanks for your time.

Best Regards

Muhammad Faisal Khan

 

0 Kudos
928 Views
lukaszadrapa
NXP TechSupport
NXP TechSupport

Attached is working example.

Function test() is forced to 0x0110_0000 by linker file but it's compiled for address 0x0930_0000 (using AT directive).

This is default state - function at 0x0x0110_0000 is simply mirrored to 0x0910_0000 as expected (no remapping yet):

lukaszadrapa_0-1677147566470.png

This is a state after remapping - after execution of Overlay() function. I remapped it to 0x0930_0000:

lukaszadrapa_1-1677147616487.png

And once stepping into test(), I can see that the code is successfully executing from this address:

lukaszadrapa_2-1677147663150.png

And one more important thing which you can see in the example - it is necessary to allow instruction fetching from remapped space by:

PFLASH.PFCRCR.B.IRMEN = 1; /* Allow instruction fetches */

Regards,

Lukas

0 Kudos
895 Views
FAISAL0323
Contributor II

Dear Lukas,

Thank you for that. it really helps to understand concept of remapping, but I still have ambiguities which need to be cleared. 

1. I can see in default state, physical address is already mirrored to logical address, then why there is need to use PLFASH registers, to do remapping?

2. Which statement actually makes that mirror address?

3. What is difference between remapping and mirroring?

4. Can we use mirror address for remapping? just like in your example, can I use 0x0910_0000 which is mirror address in default state for remapping?

5. Can we execute our code from mirror address? if yes then why there is need of remapping?

 

Thanks for your time. 

Best regards

Muhammad Faisal Khan

 

0 Kudos
872 Views
lukaszadrapa
NXP TechSupport
NXP TechSupport

There are two typical use-cases why to use remapping.

  1. For calibration - if an application use some kind of data that needs to be tuned in runtime or which you need to switch under some conditions. Idea: compile the application that it reads the data from mirrored address space. Without remapping, there could be some default data mirrored from normal flash. Now, if you need to tune the data in runtime, you can remap/overlay RAM over that mirrored space. Then you can write to RAM as needed. The application still reads from the same addresses, no changes in the application are needed. Once the tuning is done, you can program those data to normal flash. And if you want to use the new data, you can simply remap them over default data.
  2. Second use case is for OTA A/B swap bootloader - when you have two blocks for two applications in flash and you are switching between them. This allows you to load new application in runtime on background. Old application can still run during this update. If no remapping is used, it would be necessary to have an application compiled for the right block. For example, if you have application compiled for address/block A, you can’t run it from B. To avoid this need, it is possible to compile the code to be executed from mirrored address space. Then you can easily remap application A or B to the same logical address space, so it doesn’t matter if an application sits in flash block A or B.

Regards,

Lukas

0 Kudos
859 Views
FAISAL0323
Contributor II

Dear Lukas,

Thanks for detailed explanation. 

Regards

Muhammad Faisal Khan

0 Kudos