How to relocate code in flash to a non-standard starting point?

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

How to relocate code in flash to a non-standard starting point?

3,556 Views
robertpoor
Senior Contributor I

General question: What's the right way to relocate the code in a project so as to leave room in "low flash" for a flash-based bootloader?  And how do I tell KDS that the code has been relocated?

Details:

 

I have two simple "blink the LED" projects for a FRDM-KL27Z that are identical in every way except for the .ld map.

blinky-0000

The "standard" blinky-0000 uses the default .ld map as created by the KDS 2.x project builder, so the MKL27Z64xxx4_flash.ld file contains:

/* Specify the memory areas */
MEMORY
{
  m_interrupts          (RX)  : ORIGIN = 0x00000000, LENGTH = 0x00000200
  m_flash_config        (RX)  : ORIGIN = 0x00000400, LENGTH = 0x00000010
  m_text                (RX)  : ORIGIN = 0x00000410, LENGTH = 0x0000FBF0
  m_usb_sram            (RW)  : ORIGIN = 0x040FE000, LENGTH = 0x00000200
  m_data                (RW)  : ORIGIN = 0x1FFFF000, LENGTH = 0x00004000
}

And it loads (via Segger J-Link / JTAG) and executes properly.  Just to double check, I disassembled 0x0410 and found the expected code:

__do_global_dtors_aux:
00000410: push {r4, lr}
00000412: ldr r4, [pc, #24] ; (0x42c <__do_global_dtors_aux+28>)
00000414: ldrb r3, [r4, #0]
00000416: cmp r3, #0
00000418: bne.n 0x42a <__do_global_dtors_aux+26>
0000041a: ldr r3, [pc, #20] ; (0x430 <__do_global_dtors_aux+32>)
... etc

blinky-8000

I also created a blinky-8000 project, where the *only* difference is that I modified the memory map to offset each section by 0x8000, so my MKL27Z64xxx4_flash.ld file contains:

/* Specify the memory areas */
MEMORY
{
  m_interrupts          (RX)  : ORIGIN = 0x00008000, LENGTH = 0x00000200
  m_flash_config        (RX)  : ORIGIN = 0x00008400, LENGTH = 0x00000010
  m_text                (RX)  : ORIGIN = 0x00008410, LENGTH = 0x0000FBF0
  m_usb_sram            (RW)  : ORIGIN = 0x040FE000, LENGTH = 0x00000200
  m_data                (RW)  : ORIGIN = 0x1FFFF000, LENGTH = 0x00004000
}

When I load this via the Segger J-Link and attempt to run it, it ends up running the original blinky-0000 code.  And it doesn't know how to find the source code associated with the current PC, which isn't surprising since it's running at the "low" pc values.

But I do know the blinky-8000 code HAS been loaded, since I can disassemble it at the expected 0x8410 address:

__do_global_dtors_aux:
00008410: push {r4, lr}
00008412: ldr r4, [pc, #24] ; (0x842c <__do_global_dtors_aux+28>)
00008414: ldrb r3, [r4, #0]
00008416: cmp r3, #0
00008418: bne.n 0x842a <__do_global_dtors_aux+26>
0000841a: ldr r3, [pc, #20] ; (0x8430 <__do_global_dtors_aux+32>)
... etc

 

In the Debug Configurations, I set ["Set program counter at (hex):] to 8410, but that didn't seem have any effect.  (I also tried setting the [Executable offset (hex):] to 8000, but that had no apparent effect either.)

194295_194295.pngScreen Shot 2017-09-18 at 7.45.16 PM.png

In conclusion:

I can summarize my questions as follows:

  • Is simply adding an offset (e.g. 0x8000) to the memory sections in the .ld file necessary and sufficient for relocating the code, e.g. above a piece of flash that I wish to preserve?
  • How do I arrange things so the code starts at 0x8410 rather than at 0x0410?
  • How do I tell KDS_v3 how to find the relocated code?

 

Project files attached...

Original Attachment has been moved to: blinky-8000.zip

Original Attachment has been moved to: blinky-0000.zip

Labels (1)
6 Replies

2,908 Views
robertpoor
Senior Contributor I

I may have solved it, but I'd like a complete explanation on why this works.  In the blinky-8000 .ld file, I reverted m_interrupts and m_flash_config to their original low memory values (0x0000 and 0x0400, respectively):

/* Specify the memory areas */
MEMORY
{
  m_interrupts          (RX)  : ORIGIN = 0x00000000, LENGTH = 0x00000200
  m_flash_config        (RX)  : ORIGIN = 0x00000400, LENGTH = 0x00000010
  m_text                (RX)  : ORIGIN = 0x00008410, LENGTH = 0x0000FBF0
  m_usb_sram            (RW)  : ORIGIN = 0x040FE000, LENGTH = 0x00000200
  m_data                (RW)  : ORIGIN = 0x1FFFF000, LENGTH = 0x00004000
}

And now after flashing the FRDM-KL27Z, it executes blinky-8000 properly.  And KDS-v3 properly associates the PC with the correct source code.

So my lingering questions are:

  • Where can I learn more about the m_interrupts section of memory and what goes there?
  • Where can I learn more about the m_flash_config section of memory and what goes there?
  • Is there any documentation on the format of a .ld file?

2,905 Views
baldurthorgilss
Contributor III

Hi Robert

Have you tried this on MCUXpresso? I'm fighting the same thing (and have for months) with KL46z. I don't know how to move just the interrupts to 0x00 in MCUXpresso as you did.

My plan was to use a ready bootloader like MCUBOOT but I never got it right (the KL46z is not supported in the package so I tried to build it myself). I have managed to make a bootloader and to my best knowledge the code is written correct in the flash. For simplicity the bootloder is in the lower 128k and application in the upper 128k - this way there is not a problem with writing to flash (later I must learn to do this from RAM so that I dont wate all this memory space). But when running the program something goes wrong - and in spite posts saying that the debug information should be possible to get - I have not managed that. My blink application runs fine from 0x00. I would now try to debug-run my code at the offset address of 0x20000 but this fails when the address is as follows:

pastedImage_2.png

and the debug configuration startup as follows

pastedImage_1.png

(also tried executable offset of 20000). 200d5 is the second 32-bit number in my flash s19 file (the PC).

A strange thing happened. I had newly run the bootloader application so the vectors at 0x00 where filled in. In this case the configuration above ran my application. But when I erased the flash and programmed my application again - it did not work. Somehow I think MCUXpresso does not move the VTOR to 0x20000 even when the offset is set to 0x20000. 

I wold be happy for any comment.

Baldur

0 Kudos
Reply

2,905 Views
Alice_Yang
NXP TechSupport
NXP TechSupport

Hello Robert,

- There is a DOC about linker Command filer for CodeWarrior, while you refer to it to analyse .ld file on KDS.

https://cache.nxp.com/docs/en/application-note/AN4498.pdf?fsrch=1&sr=1&pageNum=1  

-For the m_interrupts as example, please check the below, it save the .isr_vector part,

pastedImage_2.png

then search it on your project,

pastedImage_4.png

so the the interrupt vectors are placed into m_interrupts .

Other parts is the same. So if you want to relocate the whole m_text, yes, you are right, only need

configure the m_text address.

- BTW, if you want to relocate one function or one variable to a special address, please refer to

Relocating Code and Data Using the KDS GCC Linker File for Kinetis 

Hope it helps


Have a great day,
TIC

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos
Reply

2,905 Views
robertpoor
Senior Contributor I

Thanks in part to Erich Styger's wonderful blog, this post gives a summary of what happens upon reboot, which explains the role that m_flash_config plays during in the startup sequence.   A little more digging and I may have figured out the rest..

2,908 Views
Alice_Yang
NXP TechSupport
NXP TechSupport

Hello Robert,

This device supports two booting methods: boot from internal flash and from ROM.

The address for booting flash is 0x0000. So , at power on chip, it run from 0x0000,

then you can use Vector Table Offset Register(VTOR) to relocate vector table.

For example, in the bootloader code , use VTOR relocate vector table to 0x8000,

    // relocate vector table
    SCB_VTOR = RELOCATED_VECTORS;   ‍‍

in application project (blinky) configure the linker file as you mentioned.

pastedImage_3.png

There is a bootloader and APP KL26, I think you can review that DOC to understand your question.

Hope it helps
Have a great day,
TIC

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos
Reply

2,905 Views
robertpoor
Senior Contributor I

Alice:

My question doesn't involve any bootloader (that will come next!).

What I need to understand is, after downloading blinky-8000 using the Segger J-Link, what must I do to make the program start executing?  As it stands now, it appears to always jump to 0x410 on startup and not to 0x8410.

0 Kudos
Reply