Teensy 4.0 Support

Showing results for 
Search instead for 
Did you mean: 

Teensy 4.0 Support

Specialist V

Hi All

The uTasker project now supports also the popular Teensy 4.0 (i.MX RT 1062).

The following is a boot loader that can be installed on the Teensy 4.0:
to allows it to load new code via USB-MSD, serial SREC (on LPUART3), using NXP's Kboot USB-HID tool or from an SD card.

It is AES256 encrypted in QSPI flash and also the new code loaded via the loading methods can be AES256 encrypted so that no one can reverse engineer it by reading it from the QSP flash.

There is a reference application that can be tested (in plain text and AES256 encrypted forms, whereby the loader accepts both) that demonstrates USB-MSD and USB-CDC composite HW USB device and SD card operation (when there is an SD card socket mounted) allowing the Teensy 4 to operate as a pen drive to a USB host with access to the SD card. Furthermore it always appears as a second hard drive to the PC with emulated FAT content that shows snap shots of the complete QSPI flash content, the instruction RAM content and the data RAM content.
On the USB-CDC interface (and on LPUART3 at 115'200Baud) there is a command line menu which supports various commands, such as a DOS like command line interface to the SD card, commands to view, write and erase data in the QSPI flash, command ports and save parameters to an area of QSPI flash. It allows commanding a LPUART3 to USB-CDC bridge, etc. etc.

The loader is usable with Teensyduino or SDK projects by linking the project code to the address 0x00000300 (for execution in instruction RAM) - interrupt vectors are to be copied by the code to the instruction RAM area beginning at 0x00000000. The image can be optionally AES256 encrypted by using the uTaskerConvert utility at https://www.utasker.com/forum/index.php?topic=1445.0 to securely protect it when distributing new firmware versions.

The boot loader also dynamically partitions the FlexRAM in the i.MX RT 1062 to suit the application size (allocating just enough banks to fit the application in instruction memory and allocating all remaining ones to data memory). This achieves maximum performance since code and data are accessed at full speed without wait states. The QSPI flash is powered down when not used by parameters or file system and so optimal power consumption, with no radiation due to external QSPI code accesses once running.


[uTasker project developer for Kinetis and i.MX RT]

Labels (1)
0 Kudos
4 Replies

Contributor I

Hi Mark

Many thanks for access to the dev repo. We're having a little difficulty using with the Teensy 4.0 that you might be able to shed some light on.

TLDR; Cannot load a regular teensy file to the bootloader


Background: The project is using two i.MX RTs - one a the main control and user interface processor and the second controlling four TI DSPs. The design goal for uTasker if to provide bootloader with highly secure field upgradeability - first processor with USB HOST capability, the second bootloader running over i2c. For test and prototyping purposes, we're using two teensy 4.0s.

We have successfully built all parts of the repo but as we encountered difficulties we have simplified until the problem is resolved. Setup is now a single teensy 4.0, programmed with the bootloader linked in your post above, using the USB-MSD to 'drag&drop' a compiled teensy hex file (Blinky of course!). From the code and docs, we believe this is a valid use case. Obviously, the real aim is for target id and encryption - baby steps!

The teensy code is linked with the following script:

VITCM (rwx): ORIGIN = 0x0, LENGTH = 0x2FF
ITCM (rwx): ORIGIN = 0x300, LENGTH = 0x80000-0x300
DTCM (rwx): ORIGIN = 0x20000000, LENGTH = 512K
RAM (rwx): ORIGIN = 0x20200000, LENGTH = 512K
FLASH (rwx): ORIGIN = 0x60000000, LENGTH = 1984K


.vectorsram : {
. = ALIGN(1024);

.text.progmem : {
. = ORIGIN(FLASH) + 0x1000;
. = ALIGN(4);
__preinit_array_start = .;
KEEP (*(.preinit_array))
__preinit_array_end = .;
__init_array_start = .;
KEEP (*(.init_array))
__init_array_end = .;
. = ALIGN(16);

.text.itcm : {
. = . + 32; /* MPU to trap NULL pointer deref */
. = ALIGN(16);

.ARM.exidx : {
__exidx_start = .;
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
__exidx_end = .;

.text.itcm.padding (NOLOAD) : {
. = ALIGN(32768);
} > ITCM

.data : {
. = ALIGN(16);

.bss ALIGN(4) : {
. = ALIGN(32);
. = . + 32; /* MPU to trap stack overflow */
} > DTCM

.bss.dma (NOLOAD) : {
. = ALIGN(32);
} > RAM

_stext = ADDR(.text.itcm);
_etext = ADDR(.text.itcm) + SIZEOF(.text.itcm) + SIZEOF(.ARM.exidx);
_stextload = LOADADDR(.text.itcm);

_sdata = ADDR(.data);
_edata = ADDR(.data) + SIZEOF(.data);
_sdataload = LOADADDR(.data);

_sbss = ADDR(.bss);
_ebss = ADDR(.bss) + SIZEOF(.bss);

_heap_start = ADDR(.bss.dma) + SIZEOF(.bss.dma);
_heap_end = ORIGIN(RAM) + LENGTH(RAM);

_itcm_block_count = (SIZEOF(.text.itcm) + SIZEOF(.ARM.exidx) + 0x7FFF) >> 15;
_flexram_bank_config = 0xAAAAAAAA | ((1 << (_itcm_block_count * 2)) - 1);
_estack = ORIGIN(DTCM) + ((16 - _itcm_block_count) << 15);

_flashimagelen = SIZEOF(.text.progmem) + SIZEOF(.text.itcm) + SIZEOF(.ARM.exidx) + SIZEOF(.data);
_teensy_model_identifier = 0x24;

.debug_info 0 : { *(.debug_info) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }


This places code from 0x300 and the ram interrupt vector table at 0x00 - the startup code then copies the ivt from flash to ram. We think this is what you were indicating in your post above.

Link output:

'Building target: Blink'
'Printing size:'
"C:/Program Files (x86)/Arduino/hardware/teensy/../tools/arm/bin/arm-none-eabi-size" -A Blink.elf
Blink.elf :
section                        size             addr
.vectorsram                704                   0
.text.progmem          5920           1610612736
.text.itcm                   5136           768     <== 0x300
.fini                                4            5904
.text.itcm.padding    26860         5908
.data                            800          536870912
.bss                            8096         536871712
.bss.dma                  12384         538968064
.ARM.attributes              46         0
.comment                      110        0
.debug_info               92343        0
.debug_abbrev          12628        0
.debug_line               14508         0
.debug_frame              3532        0
.debug_str                 22807        0
.debug_loc                17327         0
.debug_aranges         1544         0
.debug_ranges           2008         0

Total 226757

Top of memory map:

.vectorsram    0x00000000            0x2c0
                       0x00000000            . = ALIGN (0x400)
.vectorsram    0x00000000            0x2c0 /arduino.ar(startup.c.o)
                       0x00000000           _VectorsRam

.text.progmem 0x60000000          0x1720
.flashconfig      0x60000000          0x200 /arduino.ar(bootdata.c.o)
                        0x60000000          FlexSPI_NOR_Config
FILL mask 0xff
                        0x60001000          . = (ORIGIN (FLASH) + 0x1000)
*fill*                 0x60000200           0xe00 ff
.ivt                  0x60001000            0x20 /arduino.ar(bootdata.c.o)
                       0x60001000            ImageVectorTable
.bootdata        0x60001020            0xc  /arduino.ar(bootdata.c.o)
                       0x60001020            BootData
.vectors           0x6000102c            0x8 /arduino.ar(bootdata.c.o)
                        0x6000102c            vector_table
.startup            0x60001034            0x234 /arduino.ar(startup.c.o)
                        0x60001034            ResetHandler

.text.itcm          0x00000300            0x1410 load address 0x60001720
                        0x00000320            . = (. + 0x20)
*fill*                  0x00000300            0x20
.text                 0x00000320             0x5c /armv7e-m/fpu/fpv5-d16/crtbegin.o


So the questions: Have we correctly setup the linker to comply with the uTasker bootloader requirements. When we try to upload the code (dropping it onto the upload 'drive') it just sits there and is ignored by the loader. The code, if prgrammed as usual, runs perfectly. We have tried outputting srec and then using the uTaskerConvert tool to tag the file with application magic number and key but no joy.

Any advice gratefully received. We'd like to see this work prior to licencing to confirm it will meet our needs.


Many thanks


0 Kudos

Specialist V

Hi Pablo

I see that you want to run your code in XiP mode (directly from QSPI flash) but I see that you are linking it to the start of the QSPI flash, where the boot loader resides. Since this is an illegal address the code that you copy is being ignored.

Therefore you need to link the code to 0x60020200 rather than 0x60000000 to resolve this issue.

Use the linker script file \Applications\uTaskerV1.4\GNU_iMX\iMX_RT_10XX_FlexSPI_NOR_XIP.ld as a general reference to this setup.
Also use \Applications\uTaskerV1.4\GNU_iMX\Build_iMX_RT.bat as a reference to creating authentication headers, encrypting your application and combining your application with the loaders for single-step production programming (just remove the call to make and adjust paths to suit).
Note that the step of interest for non-encrypted XiP is

uTaskerConvert.exe uTaskerV1.4.bin Objects/uTaskerV1.4_XiP_%iMX_RT%.bin +boot_header.txt -0x2%MAGIC% -%AUTHENTICATION%
(replacing with a Teensy reference and expanded it is something like uTaskerConvert.exe TeensyApplication.bin Objects/TeensyApp_Uploadable.bin +boot_header.txt -0x2234 -a748b6531124)

I would use the loaders that you built with the latest repository since the linked ones are older versions that don't support full features and may not be fully compatible with the latest guides. They work with the references application that go with them but are not maintained as the repository is.

For full details use https://www.utasker.com/docs/iMX/MCUXpresso.pdf and https://www.utasker.com/docs/iMX/GCC.pdf which both are GCC based, as is TeenysDuino.
Use a copy of \Applications\uTaskerV1.4\GNU_iMX\boot_header.txt (it is used to ensure that code is padded correctly to allow correct operation with all GCC libraries and applications, irrespective of their use of interrupt vectors and code alignments).

Good luck





0 Kudos

NXP TechSupport
NXP TechSupport

Thanks for your sharing!

0 Kudos

Specialist V

Hi All

Also the Teensy 4.1 (adding SD card and Ethernet, via Ethernet Kit, to the Teensy 4.0) is now supported:


The demonstration hex file allows USB and Ethernet operations (Telnet, FTP, Web server, IGMP, etc.) and includes secure OTA (Ethernet) and serial loading (USB-MSD) and Teens 4.1 users can simply make use of the loader concept for reliable field uploading, with clone and IP protection to simply run existing Teensy 4.1 project code in XiP or on-the-fly decrypted XiP with no additional effort.


[uTasker project developer for Kinetis and i.MX RT]
Contact me by personal message or on the uTasker web site to discuss professional training, solutions to problems or rapid product development requirements

For professionals searching for faster, problem-free Kinetis and i.MX RT 10xx developments the uTasker project holds the key: https://www.utasker.com/Teensy_4_1.html

0 Kudos