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?
I have two simple "blink the LED" projects for a FRDM-KL27Z that are identical in every way except for the .ld map.
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
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.)
I can summarize my questions as follows:
Project files attached...
Original Attachment has been moved to: blinky-8000.zip
Original Attachment has been moved to: blinky-0000.zip
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:
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:
and the debug configuration startup as follows
(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
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,
then search it on your project,
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!
-----------------------------------------------------------------------------------------------------------------------
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..
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.
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!
-----------------------------------------------------------------------------------------------------------------------
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.