Skip to content

Commit e574f68

Browse files
robert-hhdpgeorge
authored andcommitted
mimxrt: Add support for a UF2 bootloader.
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. Changes: - Set the location of the ISR Vector and .text segment to 0x6000C000 and 0x6000C400. - Reserve an area at the start of ITCM for a copy of the interrupt vector table and copy the table on reset to this place. - Extend `machine.bootloader()` by setting the magic number to enable the bootloader on reset. - Create a .uf2 file which skips the segments below 0x6000C000. 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 Double reset is hard to achieve on MIMXRT boards, since there is no clean reset pin. Some MIMXRT boards provide it by switching the power. Some boards are excluded from the .uf2 build: - MIMXRT1050_EVK: The uf2 bootloader is built for the QSPI version of the board. MicroPython supports the Hyperflash version. - MIMXRT1176_EVK: No support for this board yet, but it should be possible. Signed-off-by: robert-hh <[email protected]>
1 parent b2ce9b6 commit e574f68

File tree

22 files changed

+87
-20
lines changed

22 files changed

+87
-20
lines changed

ports/mimxrt/Makefile

+21
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ BUILD ?= build-$(BOARD)
2121
PORT ?= /dev/ttyACM0
2222
CROSS_COMPILE ?= arm-none-eabi-
2323
GIT_SUBMODULES += lib/tinyusb lib/nxp_driver
24+
UF2CONV ?= $(TOP)/tools/uf2conv.py
2425

2526
# MicroPython feature configurations
2627
MICROPY_VFS_LFS2 ?= 1
@@ -162,6 +163,13 @@ SRC_HAL_IMX_C += \
162163
$(MCU_DIR)/drivers/fsl_romapi.c
163164
endif
164165

166+
# If not empty, then it is 10xx.
167+
ifneq ($(findstring MIMXRT10, $(MCU_SERIES)),)
168+
APPLICATION_ADDR := 0x6000C000
169+
else
170+
APPLICATION_ADDR := 0x3000C000
171+
endif
172+
165173
ifeq ($(MCU_SERIES), MIMXRT1176)
166174
INC += -I$(TOP)/$(MCU_DIR)/drivers/cm7
167175

@@ -253,6 +261,11 @@ else
253261
$(error Error: Unknown board flash type $(MICROPY_HW_FLASH_TYPE))
254262
endif
255263

264+
# Set a flag if the UF2 bootloader is used
265+
ifeq ($(USE_UF2_BOOTLOADER),1)
266+
CFLAGS += -DMICROPY_MACHINE_UF2_BOOTLOADER=1
267+
endif
268+
256269
# Add sources for respective board flash type
257270
# Add hal/flexspi_nor_flash.c or hal/flashspi_hyper_flash.c respectively
258271
SRC_HAL_C += hal/flexspi_$(subst qspi_,,$(FLEXSPI_FLASH_TYPE)).c
@@ -470,7 +483,11 @@ $(BUILD)/lib/tinyusb/src/device/usbd.o: CFLAGS += -Wno-missing-braces
470483
# Build targets
471484
# =============================================================================
472485

486+
ifeq ($(USE_UF2_BOOTLOADER),1)
487+
all: $(BUILD)/firmware.hex $(BUILD)/firmware.bin $(BUILD)/firmware.uf2
488+
else
473489
all: $(BUILD)/firmware.hex $(BUILD)/firmware.bin
490+
endif
474491

475492
# Process linker scripts with C preprocessor to exchange LDDEFINES and
476493
# aggregate output of preprocessor in a single linker script `link.ld`
@@ -487,6 +504,10 @@ $(BUILD)/firmware.bin: $(BUILD)/firmware.elf
487504
$(BUILD)/firmware.hex: $(BUILD)/firmware.elf
488505
$(Q)$(OBJCOPY) -O ihex -R .eeprom $< $@
489506

507+
$(BUILD)/firmware.uf2: $(BUILD)/firmware.elf
508+
$(Q)$(OBJCOPY) -O binary -R .stack -R .ivt -R .flash_config $^ $@-binpart
509+
$(Q)$(PYTHON) $(UF2CONV) -b $(APPLICATION_ADDR) -f MIMXRT10XX -c -o $@ $@-binpart
510+
490511
# Making OBJ use an order-only dependency on the generated pins.h file
491512
# has the side effect of making the pins.h file before we actually compile
492513
# any of the objects. The normal dependency generation will deal with the

ports/mimxrt/boards/ADAFRUIT_METRO_M7/mpconfigboard.mk

+2
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,5 @@ MICROPY_HW_FLASH_SIZE ?= 0x800000 # 8MB
88
MICROPY_PY_NETWORK_NINAW10 ?= 1
99
MICROPY_PY_SSL ?= 1
1010
MICROPY_SSL_MBEDTLS ?= 1
11+
12+
USE_UF2_BOOTLOADER = 1

ports/mimxrt/boards/MIMXRT1010_EVK/mpconfigboard.mk

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ MICROPY_FLOAT_IMPL = single
55
MICROPY_HW_FLASH_TYPE = qspi_nor_flash
66
MICROPY_HW_FLASH_SIZE = 0x1000000 # 16MB
77

8+
USE_UF2_BOOTLOADER = 1
9+
810
JLINK_PATH ?= /media/RT1010-EVK/
911
JLINK_COMMANDER_SCRIPT = $(BUILD)/script.jlink
1012

ports/mimxrt/boards/MIMXRT1011.ld

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ flash_config_start = flash_start + 0x00000400;
1414
flash_config_size = 0x00000C00;
1515
ivt_start = flash_start + 0x00001000;
1616
ivt_size = 0x00001000;
17-
interrupts_start = flash_start + 0x00002000;
17+
interrupts_start = flash_start + 0x0000C000;
1818
interrupts_size = 0x00000400;
19-
text_start = flash_start + 0x00002400;
19+
text_start = flash_start + 0x0000C400;
2020
vfs_start = flash_start + 0x00100000;
2121
text_size = ((vfs_start) - (text_start));
2222
vfs_size = ((flash_end) - (vfs_start));

ports/mimxrt/boards/MIMXRT1015.ld

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ flash_config_start = flash_start;
1414
flash_config_size = 0x00001000;
1515
ivt_start = flash_start + 0x00001000;
1616
ivt_size = 0x00001000;
17-
interrupts_start = flash_start + 0x00002000;
17+
interrupts_start = flash_start + 0x0000C000;
1818
interrupts_size = 0x00000400;
19-
text_start = flash_start + 0x00002400;
19+
text_start = flash_start + 0x0000C400;
2020
vfs_start = flash_start + 0x00100000;
2121
text_size = ((vfs_start) - (text_start));
2222
vfs_size = ((flash_end) - (vfs_start));

ports/mimxrt/boards/MIMXRT1015_EVK/mpconfigboard.mk

+2
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,5 @@ MICROPY_HW_FLASH_TYPE = qspi_nor_flash
66
MICROPY_HW_FLASH_SIZE = 0x1000000 # 16MB
77

88
MICROPY_BOOT_BUFFER_SIZE = (32 * 1024)
9+
10+
USE_UF2_BOOTLOADER = 1

ports/mimxrt/boards/MIMXRT1020_EVK/mpconfigboard.mk

+2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ MICROPY_PY_LWIP = 1
1212
MICROPY_PY_SSL = 1
1313
MICROPY_SSL_MBEDTLS = 1
1414

15+
USE_UF2_BOOTLOADER = 1
16+
1517
FROZEN_MANIFEST ?= $(BOARD_DIR)/manifest.py
1618

1719
JLINK_PATH ?= /media/RT1020-EVK/

ports/mimxrt/boards/MIMXRT1021.ld

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ flash_config_start = flash_start;
1414
flash_config_size = 0x00001000;
1515
ivt_start = flash_start + 0x00001000;
1616
ivt_size = 0x00001000;
17-
interrupts_start = flash_start + 0x00002000;
17+
interrupts_start = flash_start + 0x0000C000;
1818
interrupts_size = 0x00000400;
19-
text_start = flash_start + 0x00002400;
19+
text_start = flash_start + 0x0000C400;
2020
vfs_start = flash_start + 0x00100000;
2121
text_size = ((vfs_start) - (text_start));
2222
vfs_size = ((flash_end) - (vfs_start));

ports/mimxrt/boards/MIMXRT1052.ld

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ flash_config_start = flash_start;
1616
flash_config_size = 0x00001000;
1717
ivt_start = flash_start + 0x00001000;
1818
ivt_size = 0x00001000;
19-
interrupts_start = flash_start + 0x00002000;
19+
interrupts_start = flash_start + 0x0000C000;
2020
interrupts_size = 0x00000400;
21-
text_start = flash_start + 0x00002400;
21+
text_start = flash_start + 0x0000C400;
2222
vfs_start = flash_start + 0x00200000;
2323
text_size = ((vfs_start) - (text_start));
2424
vfs_size = ((flash_end) - (vfs_start));

ports/mimxrt/boards/MIMXRT1060_EVK/mpconfigboard.mk

+2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ MICROPY_PY_LWIP = 1
1212
MICROPY_PY_SSL = 1
1313
MICROPY_SSL_MBEDTLS = 1
1414

15+
USE_UF2_BOOTLOADER = 1
16+
1517
FROZEN_MANIFEST ?= $(BOARD_DIR)/manifest.py
1618

1719
JLINK_PATH ?= /media/RT1060-EVK/

ports/mimxrt/boards/MIMXRT1062.ld

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ flash_config_start = flash_start;
1616
flash_config_size = 0x00001000;
1717
ivt_start = flash_start + 0x00001000;
1818
ivt_size = 0x00001000;
19-
interrupts_start = flash_start + 0x00002000;
19+
interrupts_start = flash_start + 0x0000C000;
2020
interrupts_size = 0x00000400;
21-
text_start = flash_start + 0x00002400;
21+
text_start = flash_start + 0x0000C400;
2222
vfs_start = flash_start + 0x00100000;
2323
text_size = ((vfs_start) - (text_start));
2424
vfs_size = ((flash_end) - (vfs_start));

ports/mimxrt/boards/MIMXRT1064.ld

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ flash_config_start = flash_start;
1010
flash_config_size = 0x00001000;
1111
ivt_start = flash_start + 0x00001000;
1212
ivt_size = 0x00001000;
13-
interrupts_start = flash_start + 0x00002000;
13+
interrupts_start = flash_start + 0x0000C000;
1414
interrupts_size = 0x00000400;
15-
text_start = flash_start + 0x00002400;
15+
text_start = flash_start + 0x0000C400;
1616
vfs_start = flash_start + 0x00100000;
1717
text_size = ((vfs_start) - (text_start));
1818
vfs_size = ((flash_end) - (vfs_start));

ports/mimxrt/boards/MIMXRT1064_EVK/mpconfigboard.mk

+2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ MICROPY_PY_LWIP = 1
1212
MICROPY_PY_SSL = 1
1313
MICROPY_SSL_MBEDTLS = 1
1414

15+
USE_UF2_BOOTLOADER = 1
16+
1517
FROZEN_MANIFEST ?= $(BOARD_DIR)/manifest.py
1618

1719
JLINK_PATH ?= /media/RT1064-EVK/

ports/mimxrt/boards/OLIMEX_RT1010/mpconfigboard.mk

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ MICROPY_HW_FLASH_TYPE = qspi_nor_flash
66
MICROPY_HW_FLASH_SIZE = 0x200000 # 2MB
77
MICROPY_HW_FLASH_RESERVED ?= 0x1000 # 4KB
88

9+
USE_UF2_BOOTLOADER = 1
10+
911
CFLAGS += -DMICROPY_HW_FLASH_DQS=kFlexSPIReadSampleClk_LoopbackInternally
1012

1113
SRC_C += \

ports/mimxrt/boards/SEEED_ARCH_MIX/mpconfigboard.mk

+2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ MICROPY_PY_LWIP = 1
1212
MICROPY_PY_SSL = 1
1313
MICROPY_SSL_MBEDTLS = 1
1414

15+
USE_UF2_BOOTLOADER = 1
16+
1517
FROZEN_MANIFEST ?= $(BOARD_DIR)/manifest.py
1618

1719
CFLAGS += -DSPI_RETRY_TIMES=1000000

ports/mimxrt/boards/TEENSY40/mpconfigboard.mk

+2
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,7 @@ MICROPY_HW_FLASH_TYPE = qspi_nor_flash
66
MICROPY_HW_FLASH_SIZE = 0x200000 # 2MB
77
MICROPY_HW_FLASH_RESERVED ?= 0x1000 # 4KB
88

9+
USE_UF2_BOOTLOADER = 1
10+
911
deploy: $(BUILD)/firmware.hex
1012
teensy_loader_cli --mcu=imxrt1062 -v -w $<

ports/mimxrt/boards/TEENSY41/mpconfigboard.mk

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ MICROPY_PY_LWIP = 1
1010
MICROPY_PY_SSL = 1
1111
MICROPY_SSL_MBEDTLS = 1
1212

13+
USE_UF2_BOOTLOADER = 1
14+
1315
FROZEN_MANIFEST ?= $(BOARD_DIR)/manifest.py
1416

1517
deploy: $(BUILD)/firmware.hex

ports/mimxrt/boards/common.ld

+6-5
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ MEMORY
4242
m_vfs (RX) : ORIGIN = vfs_start, LENGTH = vfs_size
4343
/* Teensy uses the last bit of flash for recovery. */
4444
m_reserved (RX) : ORIGIN = (vfs_start + vfs_size), LENGTH = reserved_size
45-
m_itcm (RX) : ORIGIN = itcm_start, LENGTH = itcm_size
45+
m_isr (RX) : ORIGIN = itcm_start, LENGTH = 0x400
46+
m_itcm (RX) : ORIGIN = itcm_start + 0x400, LENGTH = itcm_size - 0x400
4647
m_dtcm (RW) : ORIGIN = dtcm_start, LENGTH = dtcm_size
4748
m_ocrm (RW) : ORIGIN = ocrm_start, LENGTH = ocrm_size
4849

@@ -80,7 +81,8 @@ SECTIONS
8081
. = ALIGN(4);
8182
} > m_ivt
8283

83-
/* The startup code goes first into internal RAM */
84+
/* ISR Vector table in flash. Copied to ITCM by ResetHandler(). */
85+
8486
.interrupts :
8587
{
8688
__Vectors = .;
@@ -90,10 +92,9 @@ SECTIONS
9092
. = ALIGN(4);
9193
} > m_interrupts
9294

93-
__VECTOR_RAM = __Vectors;
94-
__RAM_VECTOR_TABLE_SIZE_BYTES = 0x0;
95+
__Vectors_RAM = ORIGIN(m_isr);
9596

96-
/* The program code and other data goes into internal RAM */
97+
/* Some program code and other data goes into internal RAM */
9798
.text :
9899
{
99100
. = ALIGN(4);

ports/mimxrt/hal/resethandler_MIMXRT10xx.S

+13
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,19 @@ Reset_Handler:
6464
* __ram_function_start__/__ram_function_end__ : ramfunction region
6565
* copied to. Both must be aligned to 4 bytes boundary. */
6666

67+
/* Copy the ISR Vector table to the start of ITCM to be available when the
68+
.uf2 bootloader is used */
69+
70+
ldr r1, = __Vectors
71+
ldr r2, = __Vectors_RAM
72+
movs r3, 1024
73+
74+
.LC_ISR:
75+
subs r3, #4
76+
ldr r0, [r1, r3]
77+
str r0, [r2, r3]
78+
bgt .LC_ISR
79+
6780
ldr r1, =__etext
6881
ldr r2, =__data_start__
6982
ldr r3, =__data_end__

ports/mimxrt/modmachine.c

+12-2
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,11 @@ typedef enum {
7676
MP_SOFT_RESET
7777
} reset_reason_t;
7878

79+
// Copied from inc/uf2.h in https://github.com/Microsoft/uf2-samd21
80+
#define DBL_TAP_REG SNVS->LPGPR[3]
81+
#define DBL_TAP_MAGIC 0xf01669ef // Randomly selected, adjusted to have first and last bit set
82+
#define DBL_TAP_MAGIC_QUICK_BOOT 0xf02669ef
83+
7984
static mp_obj_t mp_machine_unique_id(void) {
8085
unsigned char id[8];
8186
mp_hal_get_unique_id(id);
@@ -158,12 +163,17 @@ NORETURN void mp_machine_bootloader(size_t n_args, const mp_obj_t *args) {
158163
#if defined(MICROPY_BOARD_ENTER_BOOTLOADER)
159164
// If a board has a custom bootloader, call it first.
160165
MICROPY_BOARD_ENTER_BOOTLOADER(n_args, args);
161-
#elif FSL_ROM_HAS_RUNBOOTLOADER_API
166+
#elif FSL_ROM_HAS_RUNBOOTLOADER_API && !MICROPY_MACHINE_UF2_BOOTLOADER
162167
// If not, enter ROM bootloader in serial downloader / USB mode.
168+
// Skip that in case of the UF2 bootloader being available.
163169
uint32_t arg = 0xEB110000;
164170
ROM_RunBootloader(&arg);
165171
#else
166-
// No custom bootloader, or run bootloader API, then just reset.
172+
// No custom bootloader, or run bootloader API, the set
173+
// the flag for the UF2 bootloader
174+
// Pretend to be the first of the two reset presses needed to enter the
175+
// bootloader. That way one reset will end in the bootloader.
176+
DBL_TAP_REG = DBL_TAP_MAGIC;
167177
WDOG_TriggerSystemSoftwareReset(WDOG1);
168178
#endif
169179
while (1) {

ports/mimxrt/mpconfigport.h

+2
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ uint32_t trng_random_u32(void);
115115
#define MICROPY_PY_MACHINE_UART_SENDBREAK (1)
116116
#define MICROPY_PY_MACHINE_UART_IRQ (1)
117117
#define MICROPY_PY_ONEWIRE (1)
118+
#define MICROPY_PY_MACHINE_BOOTLOADER (1)
118119

119120
// fatfs configuration used in ffconf.h
120121
#define MICROPY_FATFS_ENABLE_LFN (2)
@@ -151,6 +152,7 @@ uint32_t trng_random_u32(void);
151152

152153
#define MICROPY_HW_ENABLE_USBDEV (1)
153154
#define MICROPY_HW_USB_CDC (1)
155+
#define MICROPY_HW_USB_CDC_1200BPS_TOUCH (1)
154156

155157
// Hooks to add builtins
156158

tools/autobuild/build-boards.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ function build_esp8266_boards {
9999
}
100100

101101
function build_mimxrt_boards {
102-
build_boards modmimxrt.c $1 $2 bin hex
102+
build_boards modmimxrt.c $1 $2 bin hex uf2
103103
}
104104

105105
function build_nrf_boards {

0 commit comments

Comments
 (0)