Skip to content

Commit

Permalink
mimxrt/bootloader: Add support for a UF2 bootlaoder.
Browse files Browse the repository at this point in the history
Allowing to use e.g. the Adafruit bootloaders with MicroPython.
The .uf2 file is created in addition to the .bin and .hex files
allowing to use the latter ones without the bootloader for
debugging and testing.
The bootloader has to be installed as a preparation step using the
board specific methods, but then the firmware's .uf2 file version
can be installed using the bootloader. The bootloader can be invoked
with:

- double reset
- calling machine.bootloader()
- Using the touch1200 method

Loader scripts adapted for MIMXRT1011 and MIMXRT1021.

Signed-off-by: robert-hh <robert@hammelrath.com>
  • Loading branch information
robert-hh committed Oct 3, 2024
1 parent 17d8234 commit 71d4597
Show file tree
Hide file tree
Showing 7 changed files with 53 additions and 11 deletions.
15 changes: 14 additions & 1 deletion ports/mimxrt/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,14 @@ SRC_HAL_IMX_C += \
$(MCU_DIR)/drivers/fsl_romapi.c
endif

# If not empty, then it is 10xx.
ifneq ($(findstring MIMXRT10, $(MCU_SERIES)),)
BOOTLOADER_SIZE := 0x6000C000
else
CFLAGS += -DIMXRT11XX=1 -DIMXRT10XX=0
BOOTLOADER_SIZE := 0x3000C000
endif

ifeq ($(MCU_SERIES), MIMXRT1176)
INC += -I$(TOP)/$(MCU_DIR)/drivers/cm7

Expand Down Expand Up @@ -467,7 +475,7 @@ $(BUILD)/lib/tinyusb/src/device/usbd.o: CFLAGS += -Wno-missing-braces
# Build targets
# =============================================================================

all: $(BUILD)/firmware.hex $(BUILD)/firmware.bin
all: $(BUILD)/firmware.hex $(BUILD)/firmware.bin $(BUILD)/firmware.uf2

# Process linker scripts with C preprocessor to exchange LDDEFINES and
# aggregate output of preprocessor in a single linker script `link.ld`
Expand All @@ -484,6 +492,11 @@ $(BUILD)/firmware.bin: $(BUILD)/firmware.elf
$(BUILD)/firmware.hex: $(BUILD)/firmware.elf
$(Q)$(OBJCOPY) -O ihex -R .eeprom $< $@

$(BUILD)/firmware.uf2: $(BUILD)/firmware.elf
$(Q)$(OBJCOPY) -O binary -R .stack -R .dtcm_bss -R .ivt -R .flash_config $^ $@-binpart
$(Q)$(PYTHON) $(TOP)/tools/uf2conv.py -b $(BOOTLOADER_SIZE) -f MIMXRT10XX -c -o $@ $@-binpart
$(Q)rm $@-binpart

# Making OBJ use an order-only dependency on the generated pins.h file
# has the side effect of making the pins.h file before we actually compile
# any of the objects. The normal dependency generation will deal with the
Expand Down
4 changes: 2 additions & 2 deletions ports/mimxrt/boards/MIMXRT1011.ld
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ flash_config_start = flash_start + 0x00000400;
flash_config_size = 0x00000C00;
ivt_start = flash_start + 0x00001000;
ivt_size = 0x00001000;
interrupts_start = flash_start + 0x00002000;
interrupts_start = flash_start + 0x0000C000;
interrupts_size = 0x00000400;
text_start = flash_start + 0x00002400;
text_start = flash_start + 0x0000C400;
vfs_start = flash_start + 0x00100000;
text_size = ((vfs_start) - (text_start));
vfs_size = ((flash_end) - (vfs_start));
Expand Down
4 changes: 2 additions & 2 deletions ports/mimxrt/boards/MIMXRT1021.ld
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ flash_config_start = flash_start;
flash_config_size = 0x00001000;
ivt_start = flash_start + 0x00001000;
ivt_size = 0x00001000;
interrupts_start = flash_start + 0x00002000;
interrupts_start = flash_start + 0x0000C000;
interrupts_size = 0x00000400;
text_start = flash_start + 0x00002400;
text_start = flash_start + 0x0000C400;
vfs_start = flash_start + 0x00100000;
text_size = ((vfs_start) - (text_start));
vfs_size = ((flash_end) - (vfs_start));
Expand Down
11 changes: 6 additions & 5 deletions ports/mimxrt/boards/common.ld
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ MEMORY
m_vfs (RX) : ORIGIN = vfs_start, LENGTH = vfs_size
/* Teensy uses the last bit of flash for recovery. */
m_reserved (RX) : ORIGIN = (vfs_start + vfs_size), LENGTH = reserved_size
m_itcm (RX) : ORIGIN = itcm_start, LENGTH = itcm_size
m_isr (RX) : ORIGIN = itcm_start, LENGTH = 0x400
m_itcm (RX) : ORIGIN = itcm_start + 0x400, LENGTH = itcm_size - 0x400
m_dtcm (RW) : ORIGIN = dtcm_start, LENGTH = dtcm_size
m_ocrm (RW) : ORIGIN = ocrm_start, LENGTH = ocrm_size

Expand Down Expand Up @@ -80,7 +81,8 @@ SECTIONS
. = ALIGN(4);
} > m_ivt

/* The startup code goes first into internal RAM */
/* ISR Vector table in flash. Copied to ITCM by ResetHandler(). */

.interrupts :
{
__Vectors = .;
Expand All @@ -90,10 +92,9 @@ SECTIONS
. = ALIGN(4);
} > m_interrupts

__VECTOR_RAM = __Vectors;
__RAM_VECTOR_TABLE_SIZE_BYTES = 0x0;
__Vectors_RAM = itcm_start;

/* The program code and other data goes into internal RAM */
/* Some program code and other data goes into internal RAM */
.text :
{
. = ALIGN(4);
Expand Down
13 changes: 13 additions & 0 deletions ports/mimxrt/hal/resethandler_MIMXRT10xx.S
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,19 @@ Reset_Handler:
* __ram_function_start__/__ram_function_end__ : ramfunction region
* copied to. Both must be aligned to 4 bytes boundary. */

/* Copy the ISR Vector table to the start of ITCM to be available when the
.uf2 bootlaoder is used */

ldr r1, = __Vectors
ldr r2, = __Vectors_RAM
movs r3, 1024

.LC_ISR:
subs r3, #4
ldr r0, [r1, r3]
str r0, [r2, r3]
bgt .LC_ISR

ldr r1, =__etext
ldr r2, =__data_start__
ldr r3, =__data_end__
Expand Down
15 changes: 14 additions & 1 deletion ports/mimxrt/modmachine.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,11 @@ typedef enum {
MP_SOFT_RESET
} reset_reason_t;

// Copied from inc/uf2.h in https://github.com/Microsoft/uf2-samd21
#define DBL_TAP_REG SNVS->LPGPR[3]
#define DBL_TAP_MAGIC 0xf01669ef // Randomly selected, adjusted to have first and last bit set
#define DBL_TAP_MAGIC_QUICK_BOOT 0xf02669ef

static mp_obj_t mp_machine_unique_id(void) {
unsigned char id[8];
mp_hal_get_unique_id(id);
Expand Down Expand Up @@ -154,6 +159,10 @@ NORETURN static void mp_machine_deepsleep(size_t n_args, const mp_obj_t *args) {
}
}

// static bool uf2_bootloader_available(void) {
// return SNVS->LPGPR[0] != 0;
// }

NORETURN void mp_machine_bootloader(size_t n_args, const mp_obj_t *args) {
#if defined(MICROPY_BOARD_ENTER_BOOTLOADER)
// If a board has a custom bootloader, call it first.
Expand All @@ -163,7 +172,11 @@ NORETURN void mp_machine_bootloader(size_t n_args, const mp_obj_t *args) {
uint32_t arg = 0xEB110000;
ROM_RunBootloader(&arg);
#else
// No custom bootloader, or run bootloader API, then just reset.
// No custom bootloader, or run bootloader API, the set
// the flag for the UF2 bootloader
// Pretend to be the first of the two reset presses needed to enter the
// bootloader. That way one reset will end in the bootloader.
DBL_TAP_REG = DBL_TAP_MAGIC;
WDOG_TriggerSystemSoftwareReset(WDOG1);
#endif
while (1) {
Expand Down
2 changes: 2 additions & 0 deletions ports/mimxrt/mpconfigport.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ uint32_t trng_random_u32(void);
#define MICROPY_PY_MACHINE_UART_SENDBREAK (1)
#define MICROPY_PY_MACHINE_UART_IRQ (1)
#define MICROPY_PY_ONEWIRE (1)
#define MICROPY_PY_MACHINE_BOOTLOADER (1)

// fatfs configuration used in ffconf.h
#define MICROPY_FATFS_ENABLE_LFN (1)
Expand Down Expand Up @@ -150,6 +151,7 @@ uint32_t trng_random_u32(void);

#define MICROPY_HW_ENABLE_USBDEV (1)
#define MICROPY_HW_USB_CDC (1)
#define MICROPY_HW_USB_CDC_1200BPS_TOUCH (1)

// Hooks to add builtins

Expand Down

0 comments on commit 71d4597

Please sign in to comment.