Build Micropython for the Teensy 4.0/4.1

Micropython on the Teensy!

Finally, some minimal support for the Teensy 4.x processor was added in the 1.16 version of Micropython. Daily binaries are provided at https://micropython.org/download/all/, but these won't contain features under construction. This article will show you how to compile the mimxrt port from source, and will be useful for those who want to experiment with other people's branches or attempt to implement a feature themselves.

Setting up the dependencies

These instructions were performed using a fresh install of Ubuntu 20.04 Focal-fossa.

Clone the Micropython repo.

git clone https://github.com/micropython/micropython.git
cd micropython

Ensure core micropython dependencies are installed on your system.

sudo apt-get install build-essential libffi-dev git pkg-config

Installing the ARM Developer Toolchain

Since the Teensy is an ARM processor we will need to install the GNU Arm Embedded Toolchain.

The easier way

There are some older packages you can still install from the package archives, but recent tools will have to come from the toolchain maintainer’s website. See the next section for manual install instructions.

sudo apt install libnewlib-arm-none-eabi binutils-arm-none-eabi gcc-arm-none-eabi

The new "harder" way

There is no maintained PPA anymore for the ARM embedded toolchain, you have to install it manually from the Arm Developer website. The binaries provided by the three older packages listed above were all present in the bin directory of the provided archive.

Download the latest Linux x86_64 tarball, check the md5, and untar into a directory. You can add that directory to your PATH and be done, or you can do something like below.

sudo tar xjf <your tarball> -C /usr/share/ 

Create symlinks for all the binaries to make them accessible system-wide.

GCC_ARM_VERSION = <gcc-arm-none-eabi-your-version>

sudo ln -s /usr/share/${GCC_ARM_VERSION}/bin/arm-none-eabi-gcc /usr/bin/arm-none-eabi-gcc 
sudo ln -s /usr/share/${GCC_ARM_VERSION}/bin/arm-none-eabi-g++ /usr/bin/arm-none-eabi-g++
sudo ln -s /usr/share/${GCC_ARM_VERSION}/bin/arm-none-eabi-gdb /usr/bin/arm-none-eabi-gdb
sudo ln -s /usr/share/${GCC_ARM_VERSION}/bin/arm-none-eabi-size /usr/bin/arm-none-eabi-size
...

There may be some dependencies missing after install. If you encounter issues this should resolve them.

sudo apt install libncurses-dev
sudo ln -s /usr/lib/x86_64-linux-gnu/libncurses.so.6 /usr/lib/x86_64-linux-gnu/libncurses.so.5
sudo ln -s /usr/lib/x86_64-linux-gnu/libtinfo.so.6 /usr/lib/x86_64-linux-gnu/libtinfo.so.5

With that, the following commands should now work.

arm-none-eabi-gcc --version
arm-none-eabi-g++ --version
arm-none-eabi-gdb --version
arm-none-eabi-size --version
...

Build the Micropython cross-compiler

From the micropython top-level directory.

cd mpy-cross
make

We are now ready to build.

Building the Teensy port

Back at the micropython top-level directory, head over to the mimxrt port and run the make magic.

cd ./ports/mimxrt/
make submodules
make

If it succeeds you should see something like this:

LINK build-TEENSY40/firmware.elf
Memory region         Used Size  Region Size  %age Used
  m_flash_config:         512 B         4 KB     12.50%
           m_ivt:          48 B         4 KB      1.17%
    m_interrupts:          1 KB         1 KB    100.00%
          m_text:      266424 B      1015 KB     25.63%
           m_vfs:          0 GB      1020 KB      0.00%
      m_reserved:          0 GB         4 KB      0.00%
          m_itcm:        1872 B       128 KB      1.43%
          m_dtcm:       42952 B       128 KB     32.77%
          m_ocrm:          0 GB       768 KB      0.00%
   text    data     bss     dec     hex filename
 269880     292   40904  311076   4bf24 build-TEENSY40/firmware.elf

Flashing your sweet new binary

We can use the teensy_loader_cli tool to upload our .hex file to our Teensy 4.x board.

First, let's install its dependencies.

sudo apt install libusb-dev

Clone the teensy_loader_cli repo to a workspace, build, and copy the binary somewhere in your path.

git clone https://github.com/PaulStoffregen/teensy_loader_cli.git
cd teensy_loader_cli
make 
sudo cp teensy_loader_cli /usr/local/bin

Check to make sure it works and supports our target board.

teensy_loader_cli --list-mcus 

To avoid having to use sudo to flash a teensy we can update our udev rules.

cd ~
wget https://www.pjrc.com/teensy/00-teensy.rules
sudo cp 00-teensy.rules /etc/udev/rules.d/
sudo udevadm control --reload-rules

Finally! We can flash the board. Go back to your build folder.

cd micropython/ports/mimxrt/build-TEENSY40

Kick off the teensy loader. The -w flag will wait for a teensy in bootloader mode to connect.

teensy_loader_cli --mcu=TEENSY40 -w firmware.hex

Now press the button on the teensy. Once it's done loading we can use a program like minicom to connect to the REPL.

minicom -D /dev/ttyACM0 -b 115200

Excellent, let's go for a Hello world:

import utime
from machine import Pin

p13 = Pin(13, Pin.OUT)
while True:
    p13.on()
    utime.sleep(1)
    p13.off()
    utime.sleep(1)

You should now see the onboard LED blinking on you board! Alright, but we aren't done yet. We have to upload code to our board. Personally, I prefer a cli tool and the ampy program foot's the bill. In a python virtualenv let's install ampy, copy our blinking code into a main.py, then upload it to the Teensy.

python3 -m venv env
source env/bin/activate
pip install adafruit-ampy
# Copy your code to a main.py file
ampy -p /dev/ttyACM0 -b 115200 put main.py
ampy -p /dev/ttyACM0 -b 115200 ls

Now reset your board.

In closing

We have done the whole round trip on this one. We have built a micropython port from source, flashed it to our teensy board, confirmed it was working with a blinky program in the REPL, then uploaded a main.py file so it will always blink when powered. The world is now yours. Go forth and do great things.

Resources