A way to create a binary that is copied to RAM from the ROM bootloader in RT1050

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

A way to create a binary that is copied to RAM from the ROM bootloader in RT1050

7,419 Views
mastupristi
Senior Contributor I

Hello, everyone,
in the last few days I have been looking for a way for the ROM bootloader to copy to DTC RAM the binary I was building. In this regard you have probably seen some posts of mine and a colleague of mine. (http://tiny.cc/c8p90y and http://tiny.cc/l8p90y)
We have succeeded in the task, and here I want to explain how we did it. I know that probably there will be better and more direct ways, but this one is definitely a working one.

First of all, I'll start by describing our scenario, which involves having a project independent of MCUXpresso. The binary must be able to be built by makefile with the least possible use of external tools (hopefully none). Our Micro is i.MX RT1051

The reference manual

There are clues in the reference manual, but they are not conclusive.

For example:

qspi-flowchart.png

Given what is written it might seem that the copy can only be made to OCRAM, but I believe that it can really happen in any destination. In fact here http://tiny.cc/22q90y there is an example to copy in SDRAM.

BOOT Header

One of the things that is unclear is the position of the BOOT Header.

ivt-mem.png

If you examine this image you will see that it seems that the entire Boot Header should be copied to the target memory. I haven't done much testing. I just saw that if it is not mapped to the target memory (and therefore not copied) it doesn't work, otherwise it does. Actually I still have several ideas for ways to try. I will do it in the future.

HowTo

To simplify, we will start from an example provided by the SDK: led_blinky.

I imported the example keeping all the default settings:

import-example1.png

import-example2.png

Actually, for what we're going to do, it doesn't matter neither the library used, nor, for example, if the SDRAM is present or not (in my board there's no SDRAM), nor if the size of the flash is different.

Once you have imported the project, you need to change a linker setting.

plainLoadImage.png

This setting allows MCUXpresso to automatically create a linker script as similar as possible to the one we need.

So just build (Ctrl+B)

Once the building's over, you will find the created linker script in Debug directory:

DebugFolder.png

you will need to edit this script to edit the line as shown in the following figure:

boot_hdr.png

This causes the boot header to be mapped to RAM.

And another line to edit is:

linker_script_image_size.png

You have to replace LOADADDR(.text) with LOADADDR(.boot_hdr). This is used to calculate the correct size of the image.

Then go back to the linker settings to uncheck Manage linker script

UnmanageLinkerScript.png

This makes MCUXpresso use the linker script just edited instead of overwriting it with a new one.

The last steps are more tricky: there is the need to edit a file provided by the SDK, which, in my opinion, is wrong.

The file is xip/fsl_flexspi_nor_boot.c

xip_nor_boot.png

It's contents is:

nor_boot1.png

And here is the IVT format:

ivt.png

if you try to follow the IMAGE_ENTRY_ADDRESS symbol you will see that it is defined as the address of the interrupt vectors. In my opinion this is wrong. According to the description of IVT format it should be the address of the ResetISR function.

Here is the Boot Data format:

bootData.png

In the fsl_flexspi_nor_boot.c Boot Data is populated with the address of the flash and the size of the flash. In my opinion this is wrong. Start field sould be in DTCM and length should be the actual size of the image.

Since I wanted to copy also boot header I modified the file as follows:

nor_boot2.png

That's it.
I repeat that there are probably cleaner ways, where maybe you don't waste 8KB of the target memory for the boot header. However, this is a starting point.

Please let me know your feedback, comments, corrections and improvements.

best regards

Max

7 Replies

4,777 Views
Mr-Bossman
Contributor II

Hello world,

If you are using the imxrt1060 you need to set GPR_FLEXRAM_BANK_CFG to 0xaaaaaaaa so it uses the DTCM on the 1050 it is not cleared by the boot-loader. I have tried using the OCRAM on the 1050 and 1060 but cant seem to get it to work as the boot-loader seems to use the DTCM.

To configure ram banking I used the DCD. Although it is weird that the 1050 has the BANK_CFG set to 0x55555555 after the boot-loader exits and the 1060 sets it to 0.

Mabey some one can figure out how to boot into OCRAM and not DTC

0 Kudos
Reply

5,530 Views
Mr-Bossman
Contributor II

Hi i cant seem to get this to work, could some one point me to an example git repo. 
here is the ivt...

0001000 00d1 4120 231d 2000 0000 0000 0000 0000
0001010 5040 2000 1000 2000 0000 0000 0000 0000
0001020 ffff ffff ffff ffff ffff ffff ffff ffff

which is obviously wrong

0 Kudos
Reply

6,240 Views
victorjimenez
NXP TechSupport
NXP TechSupport

Hello Massimiliano Cialdi

Thanks for sharing this it is really helpful! Just one thing as heads-up for anyone who's using this approach. The modifications made to the linkerscript didn't take into consideration the initialized global variables, so if you have an initialized global variable you won't see the correct value on it. As a workaround, you can declare global variables but don't initialize them until you are on the main of your application. 

I hope it helps! 

Victor 

0 Kudos
Reply

3,590 Views
GiulioDallaVecchia
Contributor I

Hi @victorjimenez,

yes it's true, you have to add the boot_hdr size as offset as below:

/* MAIN TEXT SECTION */
.text : ALIGN(4)
{
FILL(0xff)
__vectors_start__ = ABSOLUTE(.) ;
KEEP(*(.isr_vector))
/* Global Section Table */
. = ALIGN(4) ;
__section_table_start = .;
__data_section_table = .;
LONG((LOADADDR(.data) - LOADADDR(.text) + 0x2000) + __base_SRAM_ITC);
LONG( ADDR(.data));
LONG( SIZEOF(.data));
LONG((LOADADDR(.data_RAM2) - LOADADDR(.text) + 0x2000) + __base_SRAM_ITC);
LONG( ADDR(.data_RAM2));
LONG( SIZEOF(.data_RAM2));
LONG((LOADADDR(.data_RAM3) - LOADADDR(.text) + 0x2000) + __base_SRAM_ITC);
LONG( ADDR(.data_RAM3));
LONG( SIZEOF(.data_RAM3));
LONG((LOADADDR(.data_RAM4) - LOADADDR(.text) + 0x2000) + __base_SRAM_ITC);
LONG( ADDR(.data_RAM4));
LONG( SIZEOF(.data_RAM4));
__data_section_table_end = .;
__bss_section_table = .;
LONG( ADDR(.bss));
LONG( SIZEOF(.bss));
LONG( ADDR(.bss_RAM2));
LONG( SIZEOF(.bss_RAM2));
LONG( ADDR(.bss_RAM3));
LONG( SIZEOF(.bss_RAM3));
LONG( ADDR(.bss_RAM4));
LONG( SIZEOF(.bss_RAM4));
__bss_section_table_end = .;
__section_table_end = . ;
/* End of Global Section Table */

*(.after_vectors*)

*(.text*)
KEEP(*freertos*/tasks.o(.rodata*)) /* FreeRTOS Debug Config */
*(.rodata .rodata.* .constdata .constdata.*)
. = ALIGN(4);
} > SRAM_ITC AT> PROGRAM_FLASH

 

0 Kudos
Reply

6,240 Views
richarddonkin
Contributor III

What an incredibly helpful post!

An additional thing that I needed to do to get it working was to add some linker flags:

-Wl,--undefined=hyperflash_config

-Wl,--undefined=image_vector_table

-Wl,--undefined=dcd_data

Without these flags, the linker was discarding all the boot info. (This was because the boot info was not referenced from 'main' and also was being compiled into some '.a' archive before being linked together into the binary.)

A good explanation is at cmake - GCC - how to tell linker not to skip unused sections - Stack Overflow .

As a side note, I didn't need to change the IVT's entry point to 'ResetISR' as described by Massimiliano. Booting worked both when I left it pointing at the interrupt vectors or changed it 'ResetISR'.

0 Kudos
Reply

6,240 Views
jay_heng
NXP Employee
NXP Employee

You can also try this tool, with this tool, You can flash bare image into various boot devices easily and don't need to care about headers (ivt, boot data...)

GitHub - JayHeng/nxp-sec-boot-ui: A one-stop GUI tool to work with NXP MCU (Kinetis, i.MXRT, LPC) RO... 

0 Kudos
Reply

6,240 Views
giuseppescarpi
Contributor III

Great work, Max!

Just one caveat: if you plan to execute from QSPI, you also need to modify the flexspi_nor_config.c file with the correct decoration.

Moreover, the default project adds a DCD block. It is important to ensure that the commands inside are what you need.

0 Kudos
Reply