adafruit / tinyuf2

UF2 bootloader based on TinyUSB for embedded devices such as ESP32S2, STM32F4 and iMX RT10xx
MIT License
326 stars 178 forks source link

MIMXRT1021 - Incorrect fcfb origin #204

Closed ehughes closed 2 years ago

ehughes commented 2 years ago

Operating System

Windows 10

INFO_UF2.TXT

N/A

What happened ?

I am working on a port of tinyuf2 to an MIMXRT1021 based board. I saw in MIMXRT1021_ram.ld, I saw

_fcfb_origin = 0x0400;

I believe this is incorrect and should be 0x0000 based upon the 1020 user manual and my experience w/ the part. I noticed this after programming tinyuf2 to RAM and watching it copy to flash via RTT debug messasges. After a power cycle, the part would always enter ROM DFU boot mode.

I did try to change this symbol, however I saw flash write/erase errors from the RTT terminal when using an offset of 0x0000 (0x60000000 FlexSPI base address). What is interesting is if I change the origin to anything else (0x0004, 0x0x0080, 0x1000 etc). The flash operation works OK. It just doesn't want to program when the FCFB at offset 0x0000 (0x60000000).

The NXP tools (MCUXpresso) can certainly program boot header to 0x60000000 so I am not sure what is going on.

I am going to keep digging to see what the issue is. Please let me know if you have any ideas.

Thanks!

How to reproduce ?

_fcfb_origin = 0x0400;

Debug Log

N/A

Screenshots

N/A

nxf58843 commented 2 years ago

Good catch on the FCFB offset. There is a note in the reference manual that you cannot use ITCM address 0x0 for load to RAM images (section 9.6.1.2), so I moved the image to 0x1000 to keep the IVT header 4K aligned. Please try this fix: https://github.com/nxf58843/tinyuf2/tree/hotfix-rt1020ld

ehughes commented 2 years ago

So, I think having the FCFB offset at 0x1000 would still have the issue of the resultant image not being bootable after write_tinyuf2_to_flash() is called. Once the RAM version runs the 1st time, copies itself to the the QSPI flash. However, we need the boot header to be at a zero offset from the base of flexspi base address (0x60000000) per statement 1 in 9.6.1.2

Also, from the manual (9.7.1), It sounds IVT structure must be at 0x1000 when using FlexSPI NOR. From my understanding, it cannot be relocated as the boot ROM needs to know where to find it.

I had noticed that the while tinyuf2 would run when I 1st programmed the RAM image, a power cycle would result in the ROM bootloader starting in DFU mode as the bootheader is not at 0x60000000

Is there a reason for linking to RAM and them copying vs linking .text section, boot header, etc to 0x60000000 like the MCU SDK projects?

In the end, I am trying to get something that can boot using normal QSPI boot and work post power cycle.

I will be experimenting w/ the 1020EVK later this evening and will post any results.

Thanks!

nxf58843 commented 2 years ago

Please note the image runs from RAM not XIP. 0x1000 is the location in ITCM where the image will be running from. The location in flash is adjusted based on the IVT offset so that it will be placed at the correct location in flash. As long as the difference between _fcfb_origin and _ivt_origin is correct, the FCFB will be located at the correct location. From ports/mimxrt10xx/boards.h:

// _ivt_origin is defined in linker script
// The FCFB has different offsets, but the IVT is consistent within the family
extern uint32_t _ivt_origin[];
#define BOARD_BOOT_START        (((uint32_t) _ivt_origin) - 0x1000)

The RT106x linker scripts already use this offset.

nxf58843 commented 2 years ago

Configuring the image to run from RAM allows it to be loaded and run with only sdphost. The internal ROM is not able to load flash directly so we simply load a RAM image and it copies itself to flash. TinyUF2 is its own flashloader. This also allows TinyUF2 to update itself with a .UF2 file.

ehughes commented 2 years ago

Thank you for the explanation of the Non-XIP boot, etc. Makes sense. I appreciate you taking the time!

I was able to verify that moving the fcfb_origin to 0x1000 and ivt_origin to 0x2000 works.

One piece that I overlooked when studying the code was the mask operation:

define FCFB_START_ADDRESS (FLEXSPI_FLASH_BASE + (((uint32_t) &qspiflash_config) & 0xFFF))

I kept seeing 0xFFFF instead of 0xFFF and couldn't figure out how it could ever work. :-)

Everything looks good now. I was able program a bootloader self update, etc. on the RT1021.

Would you like me to make the patch and submit a PR?

hathach commented 2 years ago

fixed by #207, thank you @ehughes and @nxf58843 for the solution

ehughes commented 2 years ago

Verified fix