GitHub

Fox Red Labs / Builds / Tools and languages

Type Python at a prompt on a TI chip

MicroPython's own Zephyr port builds with one config file and runs on the CC2340R5 and the MSPM33 C321A: a prompt on the probe's serial port and Pin from Python.

HardNo wiring

Parts and steps

Your board

You need

Set up your computer once: 1 step. Done already? Start at step 2.
  1. Install the Zephyr 4.4.2 workspace, the compiler and the west environment; NO_FLASH=1 stops the script after its build so it does not touch a board.TERMINAL

    Then clone MicroPython v1.29.0 (commit 0fd6c573e); nothing in it is edited.

    Replace <repository folder> and <MP> before you run this.

    NO_FLASH=1 <repository folder>/cc2340r5/zephyr/setup-intel-mac.sh git clone --depth 1 --branch v1.29.0 https://github.com/micropython/micropython.git <MP>

    You should see: The script ends with NO_FLASH set. Built, not flashed. and <MP> holds MicroPython.

  1. Copy prj_cc2340r5.conf and lp_em_cc2340r5.overlay from ports/micropython/zephyr-cc2340r5 into a folder <proj>, then build.TERMINAL

    The conf replaces MicroPython's own prj.conf, which overflows the chip's RAM by 46.8 kB; the overlay adds the ADC channels.

    Replace <zephyr workspace>, <toolchain>, <MP>, <build> and <proj> before you run this.

    . <zephyr workspace>/.venv/bin/activate export ZEPHYR_TOOLCHAIN_VARIANT=cross-compile CROSS_COMPILE=<toolchain>/arm-zephyr-eabi/bin/arm-zephyr-eabi- cd <zephyr workspace>/zephyr west build -p always -b lp_em_cc2340r5 <MP>/ports/zephyr -d <build> -- -DCONF_FILE=<proj>/prj_cc2340r5.conf -DEXTRA_DTC_OVERLAY_FILE=<proj>/lp_em_cc2340r5.overlay

    You should see: About 3 minutes later the build ends with zero errors: 174.9 kB of flash (34.15 %) and 29.9 kB of RAM (82.99 %). The image is <build>/zephyr/zephyr_crc32.hex.

  2. Clip the LP-XDS110ET onto the board and plug it into the Mac with its USB-C cable; the board has no USB port of its own.BENCH

    Read the probe serial with /Applications/ti/ccs2101/ccs/ccs_base/common/uscif/xds110/xdsdfu -e.

    You should see: The probe shows up as an XDS110 and xdsdfu -e prints its serial number.

  3. Back up the main flash and the CCFG before the first write, then flash the _crc32 image, which carries the boot checksums.TERMINAL

    Restore later with the same flash command on restore.hex.

    Replace <UniFlash folder>, <backup folder outside the repo> and <build> before you run this.

    DSLITE=<UniFlash folder>/deskdb/content/TICloudAgent/osx/ccs_base/DebugServer/bin/DSLite; CCXML=cc2340r5/CC2340R5.ccxml; BK=<backup folder outside the repo> $DSLITE memory -c $CCXML -r 0x0,0x20000 -o $BK/main_flash.bin $DSLITE memory -c $CCXML -r 0x4E020000,0x200 -o $BK/ccfg.bin python3 cc2340r5/oad/images.py merge $BK/restore.hex $BK/main_flash.bin@0x0 $BK/ccfg.bin@0x4E020000 $DSLITE flash -c $CCXML -e -f -u <build>/zephyr/zephyr_crc32.hex

    You should see: DSLite writes the image and reports success; the restore hex reads back byte for byte against the backup.

  4. Open the REPL with the helper that holds the serial port open and sends lines (115200 baud, /dev/cu.usbmodem<your-probe-serial>1).TERMINAL

    Replace <your-probe-serial> before you run this.

    python3 ports/micropython/zephyr-cc2340r5/repl.py /dev/cu.usbmodem<your-probe-serial>1 out.log --reset -- 'print(1+1)'

    You should see: out.log holds the banner MicroPython v1.29.0 on 2026-10-24; zephyr-lp_em_cc2340r5 with cc2340r5, then the line 2.

  5. Drive DIO15, the green LED pin, and read an ADC pin from Python.TERMINAL

    Pins are named by Zephyr devicetree label and number; the ADC number is the channel from the overlay, not the DIO number.

    Replace <your-probe-serial> before you run this.

    python3 ports/micropython/zephyr-cc2340r5/repl.py /dev/cu.usbmodem<your-probe-serial>1 out.log -- 'import machine' 'led = machine.Pin(("gpio0", 15), machine.Pin.OUT)' 'led.on(); print(led.value())' 'led.off(); print(led.value())' 'print(machine.ADC(("adc0", 2)).read_u16())'

    You should see: out.log shows 1 after led.on(), 0 after led.off(), then an ADC number (about 42,000 to 48,000 on a floating pin). The LED itself was not watched; the state is known from the read-back.

Or hand it to a coding assistant

Paste this in a terminal. It hands off to an AI assistant.

git clone --depth 1 --filter=blob:none https://github.com/Fox-Red-Labs/fox-red-labs.git && cd fox-red-labs ./start.sh cc2340r5 micropython --assistant claude

It runs the steps above and reports what it saw.

Not Claude Code? Copy this prompt instead.
Clone https://github.com/Fox-Red-Labs/fox-red-labs and read ports/micropython/zephyr-cc2340r5/AGENTS.md first. Then run Program a TI chip in Python (MicroPython) on my LP-EM-CC2340R5, following docs/builds/micropython.md. Tell me when to plug in a board and what you saw at each step.

If something goes wrong

A download failsRerun the script; it keeps what it already fetched.
The link stops with `region RAM' overflowed by 46.8 kB``The build used MicroPython's own prj.conf: pass -DCONF_FILE as shown.
It stops with relocation truncated to fit: R_ARM_THM_JUMP11 ... nlr_push_tailKeep CONFIG_MICROPY_CONFIGFILE="mpconfigport.h" and do not use the minimal conf.
xdsdfu -e lists nothingCheck the clip-on connection and use a data cable.
The flash failsClose CCStudio or any other program that holds the probe, and rerun it.
More troubleshooting
Nothing appearsCheck that the port is the probe's second serial port and that no other program holds it.
AttributeError: 'Pin' object has no attribute 'toggle'Use led.value(1 - led.value()). After a Ctrl-D soft reboot a pad you made an output stays one: use machine.reset().

Every fix for this board: the FAQ.

What to build next

Every build. The code for all of them is in the GitHub repository.

Evidence and limitsMicroPython 1.29.0 runs on the CC2340R5 and the MSPM33 C321A through its own Zephyr port: a prompt at 115200 baud and Pin from Python on both, ADC, interrupts, PWM, SPI and I2C calls on the CC2340R5. Ran on 2 boards. Results, sources, timing and limits.

MicroPython on the LP-EM-CC2340R5

Expected result: MicroPython 1.29.0 runs on the CC2340R5: a prompt at 115200 baud, DIO15 driven from Python, and the ADC read.

What this shows

  • MicroPython's own Zephyr port runs unmodified on a chip with 36 kB of RAM, once its prj.conf is replaced by one file that drops networking, sensors and file systems.
  • The image is 174.8 kB of flash and 29.9 kB of RAM with a 20 kB Python heap (19.1 kB free after boot).
  • Pin.irq (10 of 10 edges), PWM with duty_ns, SPI and I2C calls ran from the REPL.
What this does not establish, and limits

What this does not establish

  • That the LED blinked to the eye: the pin read-back changed and the LED was not watched.
  • That SPI data is right: the loopback wire was not fitted; the HDC2080 read and I2C.scan() did not work.
  • That the duty_u16 form of PWM is right in MicroPython 1.29.0: it overflows at 1 kHz; use duty_ns or apply the one-cast patch in the folder.
  • That it works on Windows or Linux: only an Intel Mac was used.

Limits to keep in mind

  • There is no file system, so scripts are typed or pasted at the prompt and re-sent after each reset.
  • Pin.irq loses its edge when Pin.init() is called on the same pin; call irq() again after init().
  • An empty Python loop takes 0.63 microseconds a pass at 48 MHz.

Sources

Versions, sizes and timing

MicroPythonv1.29.0, commit 0fd6c573e, unmodifiedREADME notes
Zephyr4.4.2, Zephyr SDK 0.17.4 GCC 12.2.0 as a cross compilerREADME notes
Image174.8 kB of flash (34.2 % of 512 kB), 29.9 kB of RAM (83.0 % of 36 kB), 20 kB heap
Free heap after boot19.1 kB of the 20 kB heap
Python speed10,000 empty loop passes in 6,323 microseconds; ADC.read_u16() about 7.2 microseconds

Evidence

  • 2026-10-24: the banner MicroPython v1.29.0 ... zephyr-lp_em_cc2340r5 with cc2340r5 appeared on the first flash of the first image; print(1+1) printed 2.
  • led.on() read back 1 and led.off() read back 0 on DIO15; machine.ADC(('adc0', 2)).read_u16() read 65,471 with the pin pulled up and 16 pulled down.
  • 2026-10-25: Pin.irq ran its handler 10 of 10 expected times; PWM with duty_ns, SPI and I2C calls ran.
  • Built from a copy of only the conf and the overlay outside the repository, about 3 minutes, zero errors: 174.9 kB flash (34.15 % of 512 kB) and 29.9 kB RAM (82.99 % of 36 kB). README notes

Other boards

What the status words mean

Works ran here and did what it shouldCould work some of it ran; real porting effort is left; hover for whatNot for this chip the chip or its vendor software cannot; hover for why

MicroPython on the LP-MSPM33C321A

Expected result: MicroPython 1.29.0 prints its banner and a >>> prompt at 115200 baud on the MSPM33 C321A, pulled-up and pulled-down inputs read 1 and 0, and float math works.

What this shows

  • MicroPython's own Zephyr port runs unmodified, with its own prj.conf as shipped, on the Cortex-M33 chip.
  • The image is 292.3 kB of flash and 83.6 kB of RAM with a 48 kB Python heap (47.1 kB free after boot).
  • machine.Pin and float math run from the REPL on the KIND=uart image; machine.SPI calls ran from the KIND=spi image.
What this does not establish, and limits

What this does not establish

  • That machine.I2C works: it opens and writes return, but every read hangs until a hardware reset.
  • That machine.ADC or machine.PWM work: Zephyr has no driver for this chip's ADC or PWM.
  • That the LED blinked to the eye: the pin state is known from the output register and the LED was not watched.
  • That the image from the fresh-folder build ran: it produced an image that was not flashed.

Limits to keep in mind

  • Zephyr's released lp_mspm33c321a board has no serial port, GPIO, I2C or SPI driver; this port needs Zephyr main plus TI's open pull requests, and pull requests move.
  • I2C and SPI cannot be in one image: pull requests 110526 and 119347 carry different copies of the UNICOMM driver, so each gets its own build (KIND=i2c, KIND=spi).
  • Pin.value() reads 0 right after led.on(); read the output register instead.
  • An empty Python loop costs 803 CPU cycles a pass at 160 MHz (5.0 microseconds); the cause is not found.

Sources

Versions, sizes and timing

MicroPythonv1.29.0, commit 0fd6c573e, unmodifiedREADME notes
Zephyrmain 1405adc9a604 plus open pull requests 116768 and 118511 (UART console and GPIO; 110526 for I2C and 119347 for SPI, each with 118511), GCC 12.2.0 from Zephyr SDK 0.17.4README notes
Image292.3 kB of flash (28.5 % of 1 MB), 83.6 kB of RAM (32.7 % of 256 kB), 48 kB heap
Free heap after boot47.1 of 48 kB after gc.collect()
Python speed10,000 empty loop passes in 50,182 microseconds

Evidence

  • 2026-10-25: the banner MicroPython v1.29.0 ... zephyr-lp_mspm33c321a with mspm33c321a appeared and print(1+1) printed 2.
  • A pin with PULL_UP read 1 and with PULL_DOWN read 0; 2**0.5*1000 printed 1414.2135.
  • The same steps were run from a scratch copy of only the listed files and produced an image (the image from that build was not flashed).

Other boards

What the status words mean

Works ran here and did what it shouldCould work some of it ran; real porting effort is left; hover for whatNot for this chip the chip or its vendor software cannot; hover for why

Result grid

Project
LP-MSPM0G3507MSPM0G3507 chip
LP-MSPM0L1306MSPM0L1306 chip
LP-EM-CC2340R5CC2340R52 chip
LAUNCHXL-F2800137TMS320F2800137 chip
Program a TI chip in Python (MicroPython)
LP-MSPM0G3507Should workA minimal 73 kB build with no floating point links; it was not flashed, and the full build does not fit the 128 kB MicroPython on the TI MSPM0G3519 and MSPM0G3507
LP-MSPM0L1306
LP-EM-CC2340R5WorksPrompt at 115200 baud; Pin, ADC, Pin.irq (10 of 10 edges), PWM, SPI and I2C calls run. 174.8 kB of flash, 29.9 kB of RAM MicroPython on Zephyr for the LP-EM-CC2340R5
LAUNCHXL-F2800137

Works ran here and did what it shouldShould work it builds; only naming, packaging or build glue is in the way; hover for whichCould work some of it ran; real porting effort is left; hover for whatNot for this chip the chip or its vendor software cannot; hover for why

Experiments (1)

StatusWhat was triedResult
Could workDoes MicroPython beat C to a first blink on the Pico 2, and by how much on the second change?
Raspberry Pi Pico 2 H, 2026-10-11
MicroPython: 65 s from download to a changed blink; C: 87 s including a build, with the tools already installed. A timing from a fresh Mac was not done.

Source files

Code brought from elsewhere

This project uses code that was written for other chips or tools. Each links to how to get it running.

Start with your code, and the prompt to port your own

Get the code and tell us how it wentThe clone command, the board folder with its AGENTS.md, reports from others, and the three report forms.

Get the code

Clone the repository and open the board's folder below. AGENTS.md is a plain text file of notes for AI coding assistants, and llms.txt at the root indexes the site for one.

git clone https://github.com/Fox-Red-Labs/fox-red-labs.git

Code is BSD-3-Clause, writing is CC BY 4.0; third-party folders keep their own licenses.

Built it? Tell us

Built this, or got stuck? Report it on GitHub with a few short answers. Your report shows here in your words, marked as yours. A failure that repeats on the bench gets its fix here.