#circuitpython-dev

1 messages · Page 95 of 1

manic glacierBOT
manic glacierBOT
#

Yeah audiospeed is fine, if a bit fine-grained. I can make the change.
I was struggling for a good top-level name to indicate what SpeedChanger was just one of: a class of audio stream wrappers that weren't effects but low-cost transformers or utilities. Like stereo<->mono swapper, L-R center-cut, phase invert. I'm not sure how useful those would be in CircuitPython, so I don't have a strong hold on audiotools.

manic glacierBOT
#

Thinking out loud a bit here. I don't see anything wrong in your change, but I'm not sure the distortion would be fixed by just a speed up of what amounts to a basic bit copy (but it may).

Okay, that makes sense. I was unsure if there might be some issues with bitwise C operations on that platform that I wasn't aware of. I was able to test the pkhbt and pkhtb operands in an emulator with the desired result, so it probably won't hurt to keep that in.

I think there is an issue in ...

manic glacierBOT
#

Even the sound files included by default for the Feather M0 Express (laugh.wav and rimshot.wav) show this behavior.

@Sporking Did you test this issue on the M0 (ATSAMD21) itself? Or were the files just pulled from the M0 and tested on the Feather M4 Express?

The files were just pulled from the M0 and tested on the Feather M4 Express. When I received my brand new Feather M4's, the default (CircuitPython version 5?) CIRCUITPY virtual drive was not detect...

manic glacierBOT
manic glacierBOT
manic glacierBOT
orchid basinBOT
manic glacierBOT
#

CircuitPython version and board name

Adafruit CircuitPython 10.1.4 on 2026-03-09; Adafruit QT Py ESP32-S3 no psram with ESP32S3
Board ID:adafruit_qtpy_esp32s3_nopsram

Code/REPL

from os import getenv
import ipaddress
import wifi
import socketpool

# Get WiFi details, ensure these are setup in settings.toml
ssid = getenv("CIRCUITPY_WIFI_SSID")
password = getenv("CIRCUITPY_WIFI_PASSWORD")

if None in [ssid, password]:
    raise RuntimeError(
        "WiFi setti...
manic glacierBOT
#

Thank you Jesse for submitting the report. The board I had this problem on was a QtPy ESP32-S3 4M Flash 2M PSRAM. So I believe it is happening on both QtPy ESP32-S3 versions.

And this would be great to somehow be added into the wifi library because even if you fix the problem in the boot.py and then later shutdown wifi to save power in your code, when you restart it later it defaults back to 20 so there is no way to permanently set a lower TX power as the default for WiFi. Additionally, de...

manic glacierBOT
#

I haven't tested backporting this against released versions, will try to backport if devs agree it makes sense

I'm building a circuitpython library to talk with commercial "guitar" pedals (Valeton GP-5, Sonicake Smart Box so far) over BLE, to control them with cpy pedalboards. With both I get disconnect errors while trying to pair with them.

This patch changes the order, so that SMP security is initiated before MTU exchange, this allows the devices to pair properly.

Tested only in es...

manic glacierBOT
#

On the other hand, we don't know how many people would be affected if the default wifi power was changed. It may depend on chip or board variations, and it may depend on local user wifi environment. For example, I have never seen this problem across dozens of Adafruit, Espressif, and other manufacturer ESP32-S3 boards since the ESP32-S3 became available. So if there is to be a core or library change that kicks in automatically every time wifi is (re-)started, it should be something user-confi...

#

These are the espressif boards that currently have non-default tx power settings on startup:

boards/01space_lcd042_esp32c3/mpconfigboard.h:23:#define CIRCUITPY_WIFI_DEFAULT_TX_POWER   (11.0)
boards/adafruit_qtpy_esp32c3/mpconfigboard.h:30:#define CIRCUITPY_WIFI_DEFAULT_TX_POWER   (15)
boards/lolin_c3_mini/mpconfigboard.h:31:#define CIRCUITPY_WIFI_DEFAULT_TX_POWER   (11.0)
boards/makergo_esp32c3_supermini/mpconfigboard.h:27:#define CIRCUITPY_WIFI_DEFAULT_TX_POWER   (11.0)
manic glacierBOT
manic glacierBOT
#

My opinion is it would be best to have a default that would work for the majority of boards even if there might be variances in how they operate. For what it's worth the default operation of the CP wifi stack seems to be to use the max power even if the RSSI from the AP (in my case within 20 feet and no walls between) is high. This does seem to cause issues with my QtPy ES32-S3 devices. In comparison the TinyS2 from UM currently on sale at Adafruit has a probably 4x larger chip antenna and...

manic glacierBOT
#

Add board defs for rpi_pico_zephyr, rpi_pico_w_zephyr, rpi_pico2_zephyr, and rpi_pico2_w_zephyr. Flash partitions (NVM at 0x180000, CircuitPy at 0x181000) match the native raspberrypi port so users can switch between ports without reformatting.

Also enable MICROPY_NLR_THUMB_USE_LONG_JUMP for the Zephyr port to fix Cortex-M0+ linker relocation errors in nlr_push.

Devices should enumerate but may have bugs after that. These board definitions are meant to make it easier to test the current...

manic glacierBOT
manic glacierBOT
manic glacierBOT
#

These per-board .conf and .overlay files: is there a way to factor out the common parts? If, say, we wanted to change the partition stuff on all the RP2350 boards, there would be many to change.

.overlay is pretty easy because we can #include other files. .conf is trickier I think because we'd need to add some CMake code to do it.

I'm planning to follow up with a bootloader and partition scheme that can do this factoring out for partitions. I may actually do it in a separate repo ...

manic glacierBOT
manic glacierBOT
#

@anecdata In my testing so far with the same wifi router, sitting from the same chair in my living room, with the following boards, the default settings work just fine.

3x - Adafruit ESP32-S3 Feather with 4MB Flash
1x - Adafruit Matrix Portal S3
1x - Adafruit QT Py ESP32-S3 with 2MB PSRAM
1x - Adafruit ESP32-S3 Reverse TFT Feather - 4MB Flash, 2MB PSRAM
1x - Adafruit ESP32-S3 TFT Feather - 4MB Flash, 2MB PSRAM

These boards consistently do not work without the boot.py hack menbtioned previo...

manic glacierBOT
manic glacierBOT
manic glacierBOT
#

I don't know enough about ble spec to know if it was currently broken. I think this patch can be described as a compatibility workaround for these devices, or as a parity patch, in the sense that the Chocotone which is a similar pedal-control software but based in c++ (arduino esp32 code v3.1.2) does negotiation in this way, which is what I used to understand and sniff why circuitpython wasn't connecting with this devices.

slender iron
#

would it be weird to have a native settings module with a change() function that walks you through known keys and current values?

#

I'm provisioning ssid and password on a bunch of stuff

stuck elbow
#

such a shame that set is already a keyword ;-)

slender iron
#

I'm thinking you call settings.change() and then it lists all keys and their current values with a number next to each one.

#

you pick the number and give it a new value

manic glacierBOT
#

I came across this issue looking for kind of same problems with ESP32-C6 (seed xiao). And I can confirm: I found much better stability / reliability from the wifi system with circuitpython 10.0.3.
I've tried so much already and encountered following issue regularly:

  • Even with 78 KB of free ram, wifi can't connect after microcontroller.reset(). Reason "Network that ssid is not found". This persists even after wifi.radio.enable False/True with sleep(2) between calls and in a loop where I als...
slender iron
#

I'm somewhat tempted to move the espressif port to the same setup as the zephyr port, cmake calling into async python.

tulip sleet
tulip sleet
#

or you could write a tool that changes all the settings.toml's. Not sure it needs to be a CircuitPython API.

#

The only reason we have settings.toml instead of boot.py (or a settings.py) to set values is persistence, I think.

#

it's a bit of a question we need a separate language for settings, when we can already parse Python?

#

in MicroPython, boot.py runs in the same VM as code.py, if I remember right

slender iron
tulip sleet
#

is it worth it if we are moving esp-idf to zephyr in the same time frame?

slender iron
slender iron
manic glacierBOT
tulip sleet
# slender iron I like the idea of a separate module because we can only enable it on certain po...

I am not sure weactually need settings.toml. We just need a persistent dict we can get/set in boot.py. The evolution of this is tortured. There is a long discussion in https://github.com/adafruit/circuitpython/issues/7274. I think we said we could not at that time run Python code before starting the web workflow, but I think that may not be true anymore due to our better port_ storage management.

CPython does not provide a good precedent for this kind of settings thing.

tulip sleet
slender iron
#

I'm fighting the fact that the idf cmake uses -u to pull in the correct impls of things

#

(I think I just got it)

#

I'm not exactly sure when the ESP zephyr work will be done at the same time as the idf. The IDF seems to get chip support first now. Not sure how far behind it actually is though. (It doesn't matter if we can't get chips)

tulip sleet
#

os environment is actually kinda poor because it's just strings -- you have to set up a parsing convention, which is where toml comes in

tulip sleet
slender iron
#

I got wifi working just now. I think I'll make a draft PR so others can start to try it

#

I haven't heard plans to move the IDF to zephyr. I think their version of freertos still does SMP better than Zephyr

#

(which I think they upstreamed to freertos)

tulip sleet
#

it does it better than vanilla FreeRTOS, right?

#

crossed...

slender iron
#

I'm sure they are still ahead of freertos. not sure how though

#

so what do we think about settings?

manic glacierBOT
#

I may also be seeing this, as I'm also using asyncio. I'm guessing the crash causes it to disconnect from USB serial so I'm missing where in my code it's hitting the crash.

While I'm not using adafruit_rfm in my code, I am just minimally using wifi to connect to a network. The same code and library set was running without issue on a Sparkfun Thing Plus RP2350, but now is crashing on an Adafruit Feather ESP32S3 4MB Flash 2MB PSRAM.

tulip sleet
# slender iron so what do we think about settings?

supervisor.settings could return a dict-like object that could be updated at run-time. The initial value would come from settings.toml. Updates would not be written back to settings.toml.
If you don't want it in supervisor, it could be in settings.settings, with a Settings class.

#

a dict-like object lets you iterate over the keys, etc.

#

the values could be stored in a real dict, but you look in settings.toml if the key isn't found, and then cache it in the dict

#

IF you want changes to persist over VM's, then the dict and its object need to be port_malloc'd.

manic glacierBOT
slender iron
tulip sleet
manic glacierBOT
manic glacierBOT
manic glacierBOT
#

Thanks tannewt,

ESP IDF 6.0 makes no difference to me. After cold boot all 3 (10, 15 and 20 dBm) connection attempts yield "no wifi with that ssid". After soft reboot, the second attempt is successful.
Going back to 10.0.3 second (sometimes first) attempt is successful after cold boot. First attempt might also fail on soft-reboot. Thus with 10 dBm tx power I'm on the edge due to my setup, which is fine. But the 15 dBm results are reproducible.

manic glacierBOT
#

I wish I were experienced enough with Circuit Python development to work on this but I don't even know where to start.

The reason this would be so helpful is that (to the best of my knowledge) there is no way to get custom hostnames from DHCP and have them stick for attaching to web workflow -- I'm already using static DHCP assignments but it doesn't help. Thus one either has to know/remember the cpy-feathers3-02d3a1c7 (made up) unique name or always remember what bare IP goes with what MC...

verbal pivot
#

hi, i made a new port for circuitpython, anything i should know before making a PR :>

tulip sleet
#

if you PR against 10.1.x, it may go in the next 10.1.x release. If you PR against main, it will go in 10.2.x.

verbal pivot
#

good to know , ty!!

manic glacierBOT
manic glacierBOT
#

I have prepared a build environment and checked out 10.1.X. Unfortunately, when building for the Feather ESP32C6 I found two issues:

  1. The Makefile appears to disable debugging with -DNDEBUG and -Os but only for riscv (like the C6).
  2. If I manually tweak the Makefile to use -DDEBUG (and either -Os or -Og) the resulting image is too lage:
2169328 bytes used,  -72176 bytes free in flash firmware space out of 2097152 bytes (2048.0kB).
   4220 bytes used,   12164 bytes free in 'LP SRAM' o...
manic glacierBOT
#

Agree this would be useful. Currently the wifi.radio.hostname and MDNS server hostname are both set to the cpy-feathers3-02d3a1c74bec-type name ending in the wifi MAC address. MDNS hostname is used for access to web workflow. wifi.radio.hostname is used with DHCP and shows up on the router. They could potentially be different. From what I've seen though, direct IP address is more robust than MDNS (cpy-feathers3-02d3a1c74bec.local. or circuitpython.local.) to access web workflow.

lone axle
#

<@&356864093652516868> the weekly meeting will be ocurring here on discord at the usual time of 2pm US Eastern / 11am US Pacific, about 1 hour from now. Add your hug reports and notes to the document in the pinned messages. We look forward to hearing from all who can attend.

manic glacierBOT
manic glacierBOT
lone axle
#

Thanks everyone, have a great week 👋

#

Here is the notes document for next Monday’s CircuitPython Weekly Meeting. It is at the normal time of 11am Pacific / 2pm US Eastern here on Discord. Add your hug reports and status updates to the document before the meeting. If you are unable to attend but would still like to contribute, feel free to add your notes and we’ll read them off during the meeting. Hope to see you there! <@&356864093652516868> https://docs.google.com/document/d/1VHGPs23KrEB_xy1HJ36wwLifFg8WdTYGw5IRndSnBVs/edit?usp=sharing

lone sandalBOT
manic glacierBOT
#

Given what the sound is described as, it sounds like clipping in fixed-point math. I may have a potential reason.

int16_t panning = synthio_block_slot_get_scaled(&voice->panning, -ALMOST_ONE, ALMOST_ONE);

If panning is 1.0 then this returns 32768, which overflows.

So what isn't ideal is the SAMD51 code keeps with fixed point math, while the other code does floating point. I have a feeling that converting back to a float is potentially hiding the problem, while the SAMD code is ...

manic glacierBOT
#

Summary

  • Fixes a NULL pointer dereference in common_hal_busio_spi_construct() on the STM32 port that crashed all STM32 boards using SPI (including STM32F405 boards whose CIRCUITPY filesystem lives on external SPI flash).
  • The common_hal_busio_spi_mark_deinit(self) call (added in 6b458a907e) was placed after check_pins(), which sets self->sck. mark_deinit then NULLed self->sck, and the immediately following self->sck->altfn_index dereference caused a crash.
  • The fix mov...
#

Fix submitted in #10924 — the root cause is a NULL pointer dereference in the STM32 SPI construct function. The mark_deinit() call (added in 6b458a907e) was placed after check_pins(), which NULLed self->sck right before it was dereferenced. This crashes all STM32 boards that use SPI, including all STM32F405 boards whose CIRCUITPY filesystem is on external SPI flash. Verified the fix on a Feather STM32F405 Express — board boots and CIRCUITPY mounts correctly.

manic glacierBOT
manic glacierBOT
manic glacierBOT
orchid basinBOT
orchid basinBOT
orchid basinBOT
#

Bumps addressable from 2.8.7 to 2.9.0.

Changelog
Sourced from addressable's changelog.

Addressable 2.9.0

fixes ReDoS vulnerability in Addressable::Template#match (fixes incomplete
remediation in 2.8.10)

Addressable 2.8.10

fixes ReDoS vulnerability in Addressable::Template#match

Addressable 2.8.9

Reduce gem size by excluding test files (#569)
No need for bundler as development dependency (#571, 5fc1d93)
idna/pure: stop building the useles...

manic glacierBOT
#

I ended up having to change CIRCUITPY_4MB_FLASH_LARGE_USER_FS_LAYOUT in ports/espressif/boards/adafruit_feather_esp32c6_4mbflash_nopsram/mpconfigboard.mk to read:

CIRCUITPY_4MB_FLASH_LARGE_USER_FS_LAYOUT ?= 1

(in addition to changing OPTIMIZATION_FLAGS to -Og and CFLAGS to -Og in ports/espressif/Makefile).

Then I was able to build with:
make BOARD=adafruit_feather_esp32c6_4mbflash_nopsram DEBUG=1 CIRCUITPY_4MB_FLASH_LARGE_USER_FS_LAYOUT=0 (and other inconsequential ...

manic glacierBOT
lone axle
#

@slender iron I've found that building the native_sim board requires libsdl2-dev:i386 but installing that directly on my system wrecked some things because I have 64bit already and there were conflicts with my existing display manager and network manager. Do you have the same issue building the native_sim? If so, have you worked around it somehow? build in container exclusively or something?

slender iron
#

yup, native sim needs the 32-bit version. works on arch ok. what distro are you on?

lone axle
#

Ubuntu 24.04

slender iron
#

the CI had trouble installing it until I pinned...... python iirc

lone axle
#

it worked to make some builds successfully but installing the required components broke things. After my next reboot my computer came back up to terminal only, I had to repair network access manually and then re-install desktop manager and network manager after removing all of the 32bit things that I installed to make the build.

slender iron
#

eeesh, I'm not sure

#

you could try building the 64 bit version but that'll mess up the pointer sizes

lone axle
#

I will look into getting a container set up

#

and probably add a warning note to the readme to try to save someone else.

slender iron
#

works for me! sorry for the trouble

lone axle
#

No worries. I wasn't paying close enough attention to what all of the apt installs were doing. Luckily claude was able to get me through the repair and help diagnose the cause.

tulip sleet
#

ubuntu 26.04 final is two weeks away; would be interesting if it didn't have the problem you described

orchid basinBOT
manic glacierBOT
manic glacierBOT
#

I confirmed on hardware that this boots and I can access REPL and modify code.py and it runs. Only minimal hello world code tested so far.

One thing I noticed was after copying the zephyr.uf2 file to FTHRSNSBOOT drive the device seems to reset but it doesn't successfully come back up and reconnect to the computer as CIRCUITPY or serial. After pressing the reset button once then it comes up as normal and connects CIRCUITPY and serial.

With the standard non-zephyr UF2 file after copying ...

#

Originally mentioned in #10923.

When the Feather Sense zephyr.uf2 file is copyied to FTHRSNSBOOT the device does seem to reset afterwards but does not come back up successfully. It does not connect to the computer as CIRCUITPY or serial.

After pressing the reset button then the device reboots and comes up all the way connecting as both CIRCUITPY and serial.

The standard non-zephyr circuitpython UF2 does not have the same issue. After copying the file device reboots, comes up, and connects...

lone sandalBOT
manic glacierBOT
manic glacierBOT
#
[adafruit/circuitpython] New branch created: zephyr_aesio
#
[adafruit/circuitpython] New branch created: zephyr_aesio_
orchid basinBOT
#

So most of the boards are made by the community and the boards are added with information that they provide (either published on their site or through PRs) and it really is up to the maintainer of the board to provide these details in the board description.

Most of the items on the list are really impractical for the circuitpython.org maintainers to know all the caveats of each boards. That said, we could probably do 4 and 5 fairly easily because that data is readily available for each board.

manic glacierBOT
#

I'm still seeing this issue with CP 10.1.4 on QtPy ESP32-S3 N4R2, Feather ESP32-S3 N4R2 and UM TinyS2.

When a watchdog reset occurs the Web Workflow does not respond until either the reset button is pushed or microcontroller.reset() is entered from the USB attached REPL.

I'm not sure what different code path microcontroller.reset() and Watchdog timer expiration reset and I realize the microcontroller.reset() is the second reset but somehow that one brings back Web Workflow and the watchdog ...

tulip sleet
#

@lone axle I'm updating the asyncio library. It failed CI, I think due to old stuff in .pre-commit-config.yaml and elsewhere.
I looked in cookiecutter, because I thought its version choices would be canonical and up to date. But interestingly it does not include a ruff-pre-commit entry in .pre-commit-config.yaml. should it, or is that wrong now?

lone axle
# tulip sleet <@382939733107408897> I'm updating the asyncio library. It failed CI, I think du...

I think the versions aren't necessarily the issue. It appears to fail some of the ruff checks in the log here: https://github.com/adafruit/Adafruit_CircuitPython_asyncio/actions/runs/24217090441/job/70700112418#step:2:1011

The cookiecutter one that you linked is for the cookiecutter repo itself. Not the templates that it creates new libraries from. That one is here. https://github.com/adafruit/cookiecutter-adafruit-circuitpython/blob/main/{{ cookiecutter.__dirname }}/.pre-commit-config.yaml

It does have a newer version of ruff in here than the libraries currently do. The next patch that I am intending to run will update the libraries to match cookiecutter. The changes from here will help facilitate: https://github.com/adafruit/adabot/pull/415

#

If you run pre-commit locally does it also fail?

tulip sleet
#

Thanks; I was indeed looking in the wrong place. ruff-pre-commit is up to v0.15.10 now. There was a new release just hours ago.

#

pre-commit runs locally.

#

... there are errors I have to fix

manic glacierBOT
#

Merge MicroPython v1.27. This merge includes v1.26 as well.

  • Upstream extmod/modre.c includes support for pos and endpos arguments in match() and search(). This replaces our own implementation with upstream.
  • time epoch handling is now more like our own, also removing some differences.
  • MP_NORETURN is now used everywhere instead of NORETURN.
  • I fixed things related to ports/unix/coveragecpp.cpp so it is more like upstream.
  • ports/unix/main.c is now more like ups...
manic glacierBOT
#

PR includes the following changes:

  • Ran make all zephyr boards to get their autogen files updated for msgpack and other resent changes
  • Added DISABLED_MODULES list to board circuitpython.toml file in zephyr port to turn core modules off on devices with limited flash. Needed this because nrf7002dk overflowed.
  • Added native_sim_build_Containerfile and two scripts that set up a suitable container to build the native_sim inside of. Documented container usage in the zephyr port readme fi...
manic glacierBOT
#

I can give it a try and add it as an alternative option. I wasn't familiar with devcontainer but have read up a little. I think personally I'd still opt to use these scripts over devcontainer in order to not have to bring node.js into the mix.

I think it would be nice to have support for it though. It seems to be well supported in VSCode, and it's a standardized structure that people may already be familiar with so they can kind of get a jumpstart on cp-zephyr dev if they already know/use...

manic glacierBOT
#

This supercedes #10474. It contains the original commit from 10474 and a new commit that resolves the changes that were requested on that PR.

This also resolves #10423. While looking into this and testing the refactored fix I found this issue and the reproducer code in it and took a quick shot at resolving it with help from claude.

The root cause of 10423 is read_byte was checking the RX FIFO status (RFNE) once and returning 0 immediately if empty. At I2C bus speeds (even 400kHz), the ...

manic glacierBOT
#

CircuitPython version and board name

Adafruit CircuitPython 10.1.4 on 2025-04-01; Adafruit QT Py ESP32-S3 no psram with ESP32S3

Code/REPL

# sleep is initiated with:
pin_alarm = alarm.pin.PinAlarm(pin=TX, value=False, pull=True)
alarm.exit_and_deep_sleep_until_alarms(pin_alarm)

Behavior

With Adafruit CircuitPython 9.2.7 on the adafruit_qtpy_esp32s3_nopsram, when exiting deepsleep from a pin alarm the boot time is about 450ms, while the 10.x series t...

manic glacierBOT
#

@tannewt could you take a look at the zephyr test failures? I am not sure what is going wrong here. Certainly there is something but maybe you recognize the issue right away.

I merge from main last night so this includes the latest zephyr code.

I wonder if the zephyr tests should be run on a separate track by the scheduler. This would allow the non-zephyr builds to run to completion instead of being blocked by failing zephyr tests.

manic glacierBOT
manic glacierBOT
#

Thanks for submitting a pull request to CircuitPython! Remove these instructions before submitting.

See https://learn.adafruit.com/contribute-to-circuitpython-with-git-and-github for detailed instructions.

  • Consider whether to submit this PR against main or against (if it exists) the branch for the current stable release or an upcoming minor release. The branch will be named i.j.x, for example, 9.2.x. Bug fixes and minor enhancements can be submitted against the stable release b...
manic glacierBOT
#

I was thinking about this after issue #10867 and what appears to be an error in the SAMD vs other CPU code. In a few places in synth, audioeffects and audiomixer (and likely others) values are converted from float to do fixed point math or vice versa. It may be better to standardize on one way and if we need exceptions for some advanced processing in an effect or similar have that as a one off.

If this sounds like a good idea it does not have to be an immediate change for everything but a go...

manic glacierBOT
#

I just wanted to record a workaround (kludge) for anyone suffering from the issue where the watchdog reset (at least on the ESP32-S2/3 models) causes Web Workflow to be unavailable even though WiFi is still working for outgoing communication. Since microcontroller.reset() apparently does a different code path and does re-enable Web Workflow I've found the following code to work.

import microcontroller

...
# Currently a bug Circuit Python issue #10054 causes web workflow to not re...
orchid basinBOT
manic glacierBOT
manic glacierBOT
manic glacierBOT
lone sandalBOT
manic glacierBOT
manic glacierBOT
manic glacierBOT
#

The refresh rate for 4 panels in a chain is too slow, flicker is a problem, especially if there is much daylight.

Is the core speed of the 2350 at maximum speed? I found no way to increase clock speed.
Is the driver in circuitpython optimized for the pico2 W?

one single panel 64x32 works really good, with four panels would a higher refresh rate be nice ...
one single 64x64 is still ok.

the reason for flicker is clear, but higher refresh rates would solve the problem.

Thank you

tulip sleet
manic glacierBOT
lone axle
#

@tulip sleet I added a containerfile and a few scripts for building the native sim. There are basic instructions to use it here: https://github.com/adafruit/circuitpython/tree/main/ports/zephyr-cp#native-simulator-build-container The issue I found was that some of the i386 requirements from here: https://github.com/adafruit/circuitpython/blob/1eb34d0f91b81d2919dab65549cc08a1c511f1a1/ports/zephyr-cp/native_sim_build_Containerfile#L9-L10 I was able to install on my main system, but I wasn't watching close enough and they had conflicts with existing packages used by my 64bit OS. So upon next reboot my display manager and network manager and a few other things were gone (removed due to those conflicts).

With the containerfile and scripts I can now make the sim builds successfully inside the container without any issues on my main OS.

lone axle
#

It could possibly be another symtom of the adaobt/bundle issue. I'll check in on it after the next run.

#

Ahh, okay cool. thank you!

#

Thanks for hosting Dan, have a great week everyone.

slender iron
#

I reproduced the zephyr errors on the mp merge branch locally and claude is looking into it

tulip sleet
#

@lone axle once again, I have erratic audio, which is strange, because it sounded OK live. If you have a backup recording, I would be grateful for an upload. there are very short interruptions in the audio, as if it's a bad connection, but that isn't true if you didn't hear me that way.

#

short clip with the problem; don't know what this is

tulip sleet
#

trying to reproduce now doesn't cause the problem. there are many web post re "choppy audio" in OBS. I'm looking at those

lone axle
#

I will check my recording. I did hear some gaps in the audio too though during parts. Went out for a walk but will be back in a bit

#

okay, mine is better than that clip at that section. Uploading now. There are still some spots where it seems like there are short clips of audio cut out. Those are what I heard live as well, the test before was clear but during the meeting I started to hear them.

slender iron
#

@tulip sleet :

Root cause: The MicroPython v1.27 merge added MICROPY_PYEXEC_ENABLE_EXIT_CODE_HANDLING, a new feature for the unix port that changes how pyexec.c return codes work. When
this feature is disabled (CircuitPython's case), the #else branch defined:

  • PYEXEC_NORMAL_EXIT as 1 (was effectively 0)
  • PYEXEC_UNHANDLED_EXCEPTION as 0 (was effectively PYEXEC_EXCEPTION = 0x200)

This swapped the meaning of success and failure. CircuitPython's main.c checks _exec_result.return_code == 0 to detect successful execution and uses the PYEXEC_EXCEPTION
(0x200) bit flag for exceptions. With the wrong values, every successful code.py run was treated as an error, breaking the run loop and preventing the process from exiting
cleanly via --vm-runs.

Fix: Changed the #else branch in shared/runtime/pyexec.h so that PYEXEC_NORMAL_EXIT is 0 and PYEXEC_UNHANDLED_EXCEPTION is PYEXEC_EXCEPTION (0x200), matching
CircuitPython's existing conventions.

lone axle
#

Interestingly some parts of what are gaps in my recording are not gaps is yours. And the glitchyness from yours is not in my recording. "time" in "that time of the week..." at the begining is the first gap in my recording. In yours it's got some other artifacts going on but I do hear "time" in there unlike from my recording.

tulip sleet
#

@slender iron thanks!

slender iron
#

it passes all my tests locally after that

#
diff --git a/shared/runtime/pyexec.h b/shared/runtime/pyexec.h
index 9d1ef2a3cb..97ddfad238 100644
--- a/shared/runtime/pyexec.h
+++ b/shared/runtime/pyexec.h
@@ -57,8 +57,10 @@ extern pyexec_mode_kind_t pyexec_mode_kind;
 #define PYEXEC_KEYBOARD_INTERRUPT (128 + 2) // same as SIG INT exit code
 #define PYEXEC_ABORT (128 + 9)              // same as SIG KILL exit code
 #else
-#define PYEXEC_NORMAL_EXIT (1)
-#define PYEXEC_UNHANDLED_EXCEPTION (0)
+// CIRCUITPY-CHANGE: CircuitPython uses bit-flag return codes.
+// Normal exit must be 0, and unhandled exceptions use the PYEXEC_EXCEPTION flag.
+#define PYEXEC_NORMAL_EXIT (0)
+#define PYEXEC_UNHANDLED_EXCEPTION PYEXEC_EXCEPTION
 #define PYEXEC_ABORT PYEXEC_FORCED_EXIT
 #endif```
tulip sleet
#

Here is the notes document for next Monday’s CircuitPython Weekly Meeting. It is at the normal time of 11am Pacific / 2pm US Eastern here on Discord. Add your hug reports and status updates to the document before the meeting. If you are unable to attend but would still like to contribute, feel free to add your notes and we’ll read them off during the meeting. Hope to see you there! <@&356864093652516868>
https://docs.google.com/document/d/1ioxfUHg7Gfp9VHqaWesxemzBYuxDOkT9S4miuQOiqSc/edit?usp=sharing

slender iron
slender iron
#

thank you!

tulip sleet
#

i missed the review dismissal

slender iron
#

np

manic glacierBOT
tulip sleet
#

next time I think I will set up a recording on a second computer. I'm trying to figure out if this is the headset/mic combo, but I'm not sure at all. I have a Monoprice headset/mic, which seems fine otherwise.

#

but i've had trouble twice now with it.

#

upgrading to 26.04 when it stops being beta, and assuming that works, will try again then as well

manic glacierBOT
#

It says invalid syntax when I try to create an async task. I don't think the micro:bit supports it. The MICROPHONE_ENABLE pin on the micro:bit triggers its mic LED

# SPDX-FileCopyrightText: 2022 Dan Halbert for Adafruit Industries
#
# SPDX-License-Identifier: MIT

import asyncio
import board
import digitalio


async def blink(pin, interval, count):  # Don't forget the async!
    with digitalio.DigitalInOut(pin) as led:
        led.switch_to_output(value=False)
        for _ in range(cou...
orchid basinBOT
manic glacierBOT
#

Ah, sorry, async is normally turned off for micro:bit, because there's only about 278kB of flash available, since it's an nRF52833, not an nRF52840.

I've built a version with async turned on: firmware.hex.zip if you'd like to try it. (Untested by me.) It has a number of other things turned off because they won't fit. But we can make the micro:bit build more usable. There is little use of it so we haven't spent time tr...

manic glacierBOT
slender iron
#

@tulip sleet I reviewed the merge and it looks good. Will leave merging up to you

tulip sleet
manic glacierBOT
manic glacierBOT
#

I tested as follows:

  • espressif MagTag: tested deep sleep PinAlarm, and separately, a portal weather application.
  • atmel-samd PyPortal - tested a PyPortal application that uses the Internet. Also did blink on SAMD21.
  • nordic Feather nRF52840 - tested BLE UART
  • raspberrypi Fruit Jam: tested Fruit Jam OS. There was some flakiness with the SD card at one point, but it went anyway. It is not clear me this is a new problem. It may have to do with the USB SD card presentation.
  • ...
manic glacierBOT
#

The only code change required was using a broader path in the glob statement to pickup subdirectories like adafruit_bus_device/i2cdevice/ instead of just things in the root of the module.

I tested the core implementation of adafruit_bus_device successfully on a feather RP2040 with a register/bus_device based driver. The native_sim tests use the same AT24 EEPROM from the i2c tests to validate behavior.

Make all has been run to update all autogen files.

manic glacierBOT
manic glacierBOT
manic glacierBOT
#

Sorry, I uploaded the wrong .hex file. I've updated the link above. Unzip before copying.

Our build guide is here: https://learn.adafruit.com/building-circuitpython

For this particular build I made this change:

diff --git a/ports/nordic/mpconfigport.mk b/ports/nordic/mpconfigport.mk
index 48536ec2ac..502a6ac6f9 100644
--- a/ports/nordic/mpconfigport.mk
+++ b/ports/nordic/mpconfigport.mk
@@ -108,6 +108,8 @@ OPTIMIZATION_FLAGS ?= -Os
 CIRCUITPY_LTO = 1
 CIRCUITPY_LTO_PARTITION = one
 ifeq...
orchid basinBOT
#

Summary

Adds a Sort by dropdown to the /contributing/open-issues page, allowing users to sort open issues by age.

Sort options:

  • Default — server-rendered order (alphabetical by library name)
  • Newest first — issues with the fewest open days appear first
  • Oldest first — issues with the most open days appear first

Sorting is parsed from the (Open X days) text already present in each issue title from the librari...

manic glacierBOT
orchid basinBOT
#

Updates the adabot submodule from d047729 to 2665096 (13 commits behind main).

Notable changes included:

  • adafruit/adabot#405 — Add days_open field to issues in libraries.v2.json output
  • adafruit/adabot#406 — Reuse/license updates
  • adafruit/adabot#409 — RTD checking improvements
  • adafruit/adabot#410 — Pre-commit license patch
  • adafruit/adabot#411 — Fix stray slash
  • adafruit/adabot#413 — Update CI actions to Node 24

The days_open field is needed for upcoming sort function...

manic glacierBOT
#

The existing .. important:: note in the SDCard.__init__ docstring states that the SD card must always be initialized before any other SPI peripheral. This is correct in the general case, but is misleading for boards where another SPI peripheral has a floating CS pin with no hardware pull-up (e.g. the Feather RP2040 RFM, where the RFM95 CS floats low at boot).

On those boards, the floating CS corrupts the SPI bus during SD card initialization, causing the SD card to fail to be recognize...

orchid basinBOT
#

Summary

Adds a link to the Adafruit WebSerial ESPTool in the Absolute Newest section on board download pages. The link only appears for boards where bootloader_info.installer == true (ESP32 variants).

This gives users a convenient way to flash .bin files downloaded from the S3 bucket onto their ESP32-based boards.

Changes

File What changed
_includes/download/board.html Added conditi...
manic glacierBOT
tulip sleet
slender iron
#

@tulip sleet want to bug bash tomorrow or friday morning?

tulip sleet
#

i have no work-time interruptions scheduled

slender iron
#

kk, I'm taking the car in tomorrow morning so I'm not sure how long that'll keep me away from my desk. I will have my laptop though

tulip sleet
#

wherever is convenient for you, probably depends on the wifi, noise, etc.

slender iron
#

👍 I can do friday morning otherwise

tulip sleet
#

which will be close to lunch for me 🙂

manic glacierBOT
#
[adafruit/circuitpython] New tag created: 10.2.0-rc.0
orchid basinBOT
#

Automated website update for release 10.2.0-rc.0 by Blinka.

New boards:

  • adafruit_feather_nrf52840_sense_zephyr
  • adafruit_feather_nrf52840_zephyr
  • adafruit_feather_rp2040_zephyr
  • native_nrf5340bsim
  • nxp_frdm_rw612
  • pimoroni_badger2350
  • pimoroni_explorer2350
  • raspberrypi_rpi_pico2_w_zephyr
  • raspberrypi_rpi_pico2_zephyr
  • raspberrypi_rpi_pico_w_zephyr
  • raspberrypi_rpi_pico_zephyr
  • renesas_da14695_dk_usb
  • st_stm32h750b_dk
  • st_stm32wba65i_dk1
  • tinycircuits_thumby
  • tinycircuits_thu...
manic glacierBOT
manic glacierBOT
#

@mikeysklar

The .. important:: note in SDCard.__init__ says to always initialize the SD card before other SPI peripherals. This is correct in most cases

I never understood this note, can you give some reasoning why "this is correct"? Driving the CS of the SD card high, initialize a different device first and then the SD-card should also work. The floating CS is a general problem of shared busses, irrespective of an SD-card present or not.

lone sandalBOT
manic glacierBOT
#
[adafruit/circuitpython] New branch created: webworkflow-20260416
#

I’m not currently in a position to build my own CP branch. If someone makes this change available on some test branch, I’d be happy to test on multiple boards with the issue.

@grgrant have a look in an hour or two (CI jobs take 1.5hrs) and there should be some assets for download in this job (ensure logged in to see assets), matching pull request is #10948

[https://github.com/adafruit/circuitpython/actions/runs/24508273149#:~:text=Produced during runtime](https://github.com/adafruit/...

tulip sleet
#

CircuitPython 10.2.0-rc.0 is released! Please try it so we can release 10.2.0 final.
https://blog.adafruit.com/2026/04/16/circuitpython-10-2-0-rc0-released/
Highlights:

  • New audiotools.SpeedChanger.
  • New qspibus support for displayio.
  • Stability improvements to USB SD card handling.
  • Merge of MicroPython v1.27.
  • Update to ESP-IDF v5.5.3.
  • Many additions to the Zephyr port.
  • Simulated hardware testing is now being done in the Zephyr port.
manic glacierBOT
#

@bablokb You're right, and it's a good point. The "SD first" rule was never really about SD cards being special — it was implicitly relying on hardware pull-ups on all other CS pins doing the work of keeping the bus clean at boot. On most boards that assumption holds, so the rule works fine as a shorthand. But it never said that out loud.

The floating CS on the Feather RP2040 RFM just exposed what the real invariant actually is: before any SPI transaction, every CS line on the bus must be ...

manic glacierBOT
#

I actually fell over this a few years ago when my e-ink was wildly flashing while initializing the SD-card. One thing that would really simplify things if fourwire would accept a DigitalInOut in addition to a microcontroller.Pin. Because currently, you have to create a DIO, pull it high, then later deinit it to pass the pin to the fourwire-constructor. The same hold true for the sdcard-constructor (and maybe other places).

manic glacierBOT
#

@bablokb
Both constructors do this:

    common_hal_digitalio_digitalinout_switch_to_output(&self->cs, true, DRIVE_MODE_PUSH_PULL);

So the CS pins are pulled high in the constructor. For FourWire, this happens at the end of the constructor.

But for FourWire, no SPI transaction happens during the constructor, whereas for SDCard, the constructor does some initialization. Maybe the solution is for SDCard (and anything else that takes an SPI bus) to avoid doing any SPI op...

#

Before adjusting the comments the original forum issue isn't entirely resolved. I'll work with the user and what I believe is the same hardware setup today before changing the comments to something like:

Before initializing the SD card, make sure every CS pin on the shared SPI bus is HIGH — either via a hardware pull-up or driven HIGH in software. The old "SD first" rule only held because pull-ups were assumed. Init order is secondary...

orchid basinBOT
manic glacierBOT
slender iron
#

@tulip sleet done with the car and back to my desk if you want to peer claude some issues

tulip sleet
#

we could go over them and maybe mark some for possible LLM resolution. I did just start to look at them.

manic glacierBOT
#

@bablokb Both constructors do this:

    common_hal_digitalio_digitalinout_switch_to_output(&self->cs, true, DRIVE_MODE_PUSH_PULL);

So the CS pins are pulled high in the constructor. For FourWire, this happens at the end of the constructor.

I think my comment above is only true for 9.x. If I read the code correctly, it is possible now to pass a pin or dio to the Fourwire constructor.

Splitting Fourwire-construction and display construction is a valid...

#

When both foo/ (no init.py) and foo.py existed on the filesystem, import foo silently imported the empty namespace package and skipped foo.py. CPython picks the .py in this case, and the docs define that precedence: regular package > module > namespace package.

stat_module now probes for __init__.py/.mpy inside the directory first, then falls back to .py/.mpy, and only treats the bare directory as a namespace package when neither exists.

Adds a native_sim regressio...

manic glacierBOT
#

@tyeth Thank you for doing this.

I'm sorry to say this change does not fix the Watchdog reset issue with Web Workflow and in fact seems to regress other behaviors. When connecting via the web after a watchdog reset previously one would get an error:

Looks like there's a problem with this site
Firefox can't connect to the server at 192.168.x.y

Now Firefox just hangs indefinitely. I did some troubleshooting using nmap and found that in the earlier behavior port 80 showed closed....

manic glacierBOT
tulip sleet
#

@lone axle @slender iron Hi Tim - re the tests you are adding for these zephyr features being turned on: in some cases (e.g. hashlib, binascii, the modules already have tests in tests/. I don't think we need zephyr-cp-specific tests for these, since the port build should run the regular tests. And if there aren't general tests, then they should be added in tests/.

Another example is https://github.com/adafruit/circuitpython/pull/10951#pullrequestreview-4124462314

slender iron
#

I'm ok having them both places because the native sim tests will be able to mimic an actual test on hardware too.

tulip sleet
#

if we ran tests/ on the native sim implementation, that would be the same thing, I think? So we don't really need a second set of tests. If the tests/ tests are inadequate in some way, of course they could be improved.

slender iron
#

the harness is different because the native sim one builds an external flash image to run on instead of doing raw repl

tulip sleet
#

but is it true that, say, the hashlib test is testing the same functionality? If we added a new API to hashlib, then we'd need to add a test for that in two places? I would like to the see the test part factored out of the harness part.

#

or am i confused about what the zephyr-cp hashlib test is doing?

slender iron
#

yes, they are testing the same thing in a different way

tulip sleet
#

it is certainly true the MicroPython test framework is this bespoke thing with its own specific mechanisms and a lot of special cases built in. (I just spent time in there for https://github.com/micropython/micropython/pull/19073). Having tests in a more standard test framework (pytest) is a laudable goal too. It's diversion from upstream vs the advantages of standardization

slender iron
#

I was thinking about how to do the HIL testing too. I think I settled on flashing the CIRCUITPY portion of flash for every test. That way a test can have multiple files associated with it.

tulip sleet
#

The UF2 bootloaders may or may not allow overwriting CIRCUITPY? Maybe that's possible on the atmel-samd and the RP2 ones. But the TinyUF2 ones know the partition layout, and might forbid that.

#

and the nRF52 one is yet another

slender iron
#

I'm assuming I'd generally go around the uf2 bootloader

tulip sleet
#

i don't think you have to, or it's difficult (atmel-samd in particular). RP2 could use picotool

slender iron
#

I'm planning to start with ESP anyway

#

and many of the zephyr dev kits have built in debuggers

surreal perch
# tulip sleet CircuitPython **10.2.0-rc.0** is released! Please try it so we can release 10.2....

Dan, I'm finding some troublesome behavior with 10.2.0-rc.0. I can manage to get it in a state that requires reloading 10.1.4 uf2 via uf2 bootloader to get it to respond again. Essentially my test code for issue https://github.com/adafruit/circuitpython/issues/10054#issuecomment-4217819826 with two watchdog resets followed by a microcontroller reset cause two different boards (Feather and QtPy ESP32-S3) running 10.2.0-rc.0 to become unresponsive (including powercycles) and going back to 10.1.4 and then back to 10.2.0-rc.0 allow them to run again. I suspect you'll want me to log an issue -- do I put it against main or the releease candidate?

tulip sleet
#

it should not be necessary to reload an old version. There is no state that is kept.

surreal perch
#

The serial console remains unresponsive (or my code.py causes it to not respond). I don't have CIRCUITPY available boot.py is disabling USB. So I can't rename code.py (no REPL) and have to reload 10.1.4. However my code.py has a bunch of neopixel status lights and they aren't showing either so I think a power cycle is still leaving the board wedged.

surreal perch
#

And I have to admit I've never been very good at the timing to set safe mode which might help now.

tulip sleet
#

since your current test case is highly unusual

#

(doesn't mean it's wrong, just unusual 🙂 )

surreal perch
#

I'm going to see if from repl I can do two watchdog resets and a microcontroller reset once I remove my code.py with the test. I mean if it is as simple as that sequence won't that be concerning.

#

I'll document my findings on 10054.

#

Oh and just to complete the thought, on 10.1.4 my test code can run indefinitely WDR, WDR, MCR without hanging or any issue.

manic glacierBOT
#

CircuitPython version:
Adafruit CircuitPython 10.1.4 on 2026-03-09; Adafruit Metro RP2350 with rp2350b

Board: adafruit_metro_rp2350

Code/REPL

boot.py (attempt to release pins):

import usb_host, board
port = usb_host.Port(board.USB_HOST_DATA_PLUS, board.USB_HOST_DATA_MINUS)
port.deinit()

code.py (attempt to use GPIO32/33 with PIO):

import board, rp2pio, adafruit_pioasm

prog = adafruit_pioasm.assemble("""
.pio_version 1
.program test_q
    nop
   ...
manic glacierBOT
#

This is related in that my code above demonstrating the Web Workflow Watchdog Reset will cause the following issue with 10.2.0-rc.0 but the issue is actually new behavior with this release. With a fresh install and my above program, boot.py with storage.disable_usb() and a settings.toml enabling WiFi and Web Workflow but without even connecting to Web Workflow via browser after a couple of loops the program hangs -- no more lights, usb serial is unresponsive, and even a power cycle doesn't b...

manic glacierBOT
#

Not sure why the nordic_nrf54h20dk build shows failing now. The tail end of the log (https://github.com/adafruit/circuitpython/actions/runs/24542014373/job/71836502949?pr=10952#step:10:22451) looks like a pretty normal successful build to my eye but shows Error: Process completed with exit code 2. with no other error info that I could find.

I am able to successfully build the nordic_nrf54h20dk locally. Though I do notice the end of the output has a bit different numbers inside the squar...

manic glacierBOT
#

CircuitPython version and board name

10.2.0-rc
Pico2

Code/REPL

import sdcardio
import storage
import busio
SD_MOSI = board.GP19
SD_SCK  = board.GP18
SD_MISO = board.GP16
SD_CS   = board.GP17

spi0 = busio.SPI(SD_SCK,SD_MOSI,SD_MISO)
sdcard = sdcardio.SDCard(spi0,SD_CS,1_000_000)
vfs    = storage.VfsFat(sdcard)
storage.mount(vfs, "/sd")

Behavior

Fails with "timeout waiting for v2 card"

Description

Reverting the timeout CMD_TIMEOUT_MS back to...

manic glacierBOT
#

I'm trying to reproduce this, so far unsuccessfully. The only SanDisk card I I have is an Ultra Plus 16GB. I had tested this with a bunch of Micro Center cards and the really small (e.g. 64MB) Adafruit cards.

In the sample code above,

  • import board is missing, so maybe this is not the whole program?
  • Why did you set the SPI baudrate to 1 MHz? The default is 8 MHz. (Maybe you were trying to get it to work?)

Thanks.

manic glacierBOT
#

CircuitPython version and board name

10.1.4 S3 rev-TFT feather

Code/REPL

See files in "Behavior" section.

Behavior

Scanning for devices shows the Feather advertising it's name.
Connect to device via OS (shows device name), says connecting, fails slowly and device reverts to advertising again.
Repeat.

At some point this fails to send advertised name any more.

Connect to NRF Connect on mobile. Guess device by RSSI / MAC. BOND the connection. Discon...

manic glacierBOT
#

I did a bisect and it does indeed seem to be the ESP-IDF 5.5.1 update that's the problem. I tested 10.2.0-rc.0 on ESP32-S3 with and without PSRAM, and on QT Py ESP32-C3. All those worked.

An easty test is to load settings.toml with WiFi settings, and specify a CIRCUITPY_WEB_API_PASSWORD. Then do

curl http://192.168.x.x/cp/version.json

where the IP address is the board's IP address. On C6, this will cause a crash. On the other boards I mentioned, the curl works. Thanks @JonNelso...

#

Thanks for asking @tannewt - I have a project using a great deal of pins. I needed GPIOs in the 30s and between SPI and USB host I can get 6. together. Other GPIO are spoken for.

There is no way to tell CircuitPython "I don't plan to use USB host, please give me back the D+ and D- pins.

If deinit isn't the right way to accomplish this, then I'm open to ideas. Trying other methods failed because the pins are attached very early. Maybe a boot.py line that says "No USB host will be used in the...

pallid swallow
#

howdy. I'm trying to add support for a board that uses 2 UARTs. intuition tells me i should:

#define CIRCUITPY_BOARD_UART        (2)
#define CIRCUITPY_BOARD_UART_PIN    {{.tx = &pin_GPIO16, .rx = &pin_GPIO17}, \
                                     {.tx = &pin_GPIO20, .rx = &pin_GPIO21}}

This does create a UART and UART1, however they both seem to use the UART pins and point to the same underlying uart. I shorted UART's GPIO16&17 and left 20&21 open. I tried a bunch of stuff, but most concisely:

>>> import board
>>> board.UART().write("hello") and board.UART().read()
b'hello'
>>> board.UART1().write("hello") and board.UART1().read()
b'hello'

When i disconnect 16&17 and connect 20&21, nothing comes through.

  • I looked through the other boards and see while some boards have CIRCUITPY_BOARD_I2C and _SPI >1, none have _UART >1
  • I looked through the code, and while i don't understand all of it, i didn't see any differences to how _I2C, _SPI, and _UART pin lists were handled in shared-module/board/__init__.c or elsewhere

So - Am I expecting the wrong thing? Or is there some flaw with UARTs that there can be only one? Or is this how it's supposed to work and i'm misunderstanding. Thx!

tulip sleet
#

what happens if you just create the UARTs with busio.UART(tx=..., rx=...). Do they function? The point of the board mechanism is to provide convenient defaults.

pallid swallow
#

rp2040. If i busio.UART the pins directly, either pair of uart pins works fine

#

and IIRC if i swap the pin pairs in the array, it uses gpio 20 and 21 all the time. I'll double check that though.

tulip sleet
#

I don't see that you can do UART on GP21 and GP20, based on what can be assigned to those pins.

#

<>

pallid swallow
#

i just switched to:

#define CIRCUITPY_BOARD_UART        (2)
#define CIRCUITPY_BOARD_UART_PIN    {{.tx = &pin_GPIO20, .rx = &pin_GPIO21}, \
                                     {.tx = &pin_GPIO16, .rx = &pin_GPIO17}}

and now it works fine on those pins using either uart or uart0, but not 16/17

pallid swallow
tulip sleet
#

you must also create a new CIRCUITPY_BOARD_BUS_SINGLETON . See ports/raspberrypi/boards/adafruit_qtpy_rp2040/pins.c for an example (for a second I2C)

#

what are the lines for your UARTs in pins.c

#

that is the standard pinout diagram, I wonder why they were omitted 😕

pallid swallow
#

awesome, that's probably it, i'll give it a try. not sure how many hours i would have searched before finding that.

tulip sleet
#

e.g. from that pins.c:

CIRCUITPY_BOARD_BUS_SINGLETON(stemma_i2c, i2c, 1)
...
    { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
...
    { MP_ROM_QSTR(MP_QSTR_STEMMA_I2C), MP_ROM_PTR(&board_stemma_i2c_obj) },
#

note that the 1 in the first line is referring to the second element of the I2C_PIN array (elements are 0 and 1)

#

this pinout diagram bug is weird, i'll look further

pallid swallow
#

yay! thanks @tulip sleet it works!

#

root cause, pins.c was the first thing i edited before i knew what i was doing and had:

    { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
    { MP_ROM_QSTR(MP_QSTR_UART1), MP_ROM_PTR(&board_uart_obj) },

so of course they were both using uart.

adding

CIRCUITPY_BOARD_BUS_SINGLETON(uart1, uart, 1)

up top and fixing it to

    { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
    { MP_ROM_QSTR(MP_QSTR_UART1), MP_ROM_PTR(&board_uart1_obj) },

and it all works as expected. Thanks!

tulip sleet
#

you're welcome! it is a little tricky.

#

i think I will annotate that pinout diagram. I already edited when it was originally posted to make it narrower

#

or maybe I will make one of our style pinout diagrams instead. We have some sw to do that.

pallid swallow
#

I gotta say - circuitpython changed the way i think about microcontrollers. As someone who's always hated toolchains, it's great. I'm in the process of moving all my class labs away from arduino. So thanks to you and all the devs.

tulip sleet
#

you're very welcome - making computers easier to use is very gratifying, and making physical computing easier to use is part of that

manic glacierBOT
manic glacierBOT
#

I have experienced that the ability to toggle a digital output pin depends on whether the board has been hard-reset since the last time a deep sleep alarm was used with preserve_dios.

I am using AIO over wifi.

This is with a Qt Py ESP32-S2, CP 10.1.4, where the pins I've tried to use are MOSI and MISO.

The board wakes up, reads sensors and reports the data to several AIO feeds, then goes to deep sleep using a time alarm.
Using this line of code gives inconsistent performance of the digit...

manic glacierBOT
#

This is not the complete program. I only copied the relevant part to show that I am not doing anything extra-ordinary. I honestly don't remember why the baudrate is 1MHz, the program is rather old.

One thing I noted: after a hard reset it fails. When I then use CTRL-D in the REPL to restart immediately, it works.

Another thing I noticed: the title of the commit 236dec0 states "remove RUN_BACKGROUND_TASKS in SDCard". But the code for init_card_v2() (that is where the error is triggered) us...

manic glacierBOT
#

The SDCard bus frequency doesn't matter for init anyway, because that's done at a fixed lower rate. But you might remove that from your own code to speed up SD card access.

I don't remember exactly why I wrote that comment on 236dec0, but I think that maybe the "RUN_BACKGROUND_TASKS in SDCard" was about the calls being redundant once I added the mp_hal_delay_ms(). I was definitely not trying to avoid running background tasks. They are vital to keeping USB going and keeping the display up ...

manic glacierBOT
surreal perch
#

@tulip sleet I'm logging a new issue against rc0. It is dead simple:

  • have storage.disable_usb_drive() in boot.py
  • Enable WiFi and Web workflow in settings.toml (tested with two different APs) and didn't need to use web workflow to trigger
  • simply execute microcontroller.reset() in code.py one line plus import

Result:

  • TFT display stopping at 'boot.py output:' and never showing code.py output: line
  • Tested on a TinyS2 brand new install with no other files
  • Also tested on AF Feather ESP32-S2 TFT (to see the diag output when USB not available).
  • Cannot recover USB access or go beyond boot.py output display on TFT with either reset button or power off/on (unplugging USB and plugging back in).
  • Safe mode or downgrading UF2 is required to get access back
  • In safe mode you must restart with the boot.py renamed to enable usb and have a normal start before clearing error.

Anyway since I have to find the right page and provide more information in the bug report I thought I'd report it here.
(Not actually related to the WDT Reset Web Workflow problem as this is actually a microcontroller.reset issue)

manic glacierBOT
#

CircuitPython version and board name

Adafruit CircuitPython 10.2.0-rc.0 on 2026-04-16; Adafruit Feather ESP32-S2 TFT with ESP32S2
Adafruit CircuitPython 10.2.0-rc.0 on 2026-04-16; TinyS2 with ESP32S

Code/REPL

import microcontroller
microcontroller.reset()

Behavior

Behavior

Upon execution the board resets and then hangs at the boot.py execution before code.py is executed. The last thing shown on the TFT display is 'boot.py output:'. Subsequentl...

manic glacierBOT
manic glacierBOT
#

I followed the official guide and created a fork.
Built circuitpython and my board defintion.
Flashed the board with the new firmware.
Used the pre-commit automatic checks.

Added code.py and deepsleep.py scripts to test the following functionalilties.

  • connecting to wifi network
  • board.LED blinking
  • initialize OV3660 and OV5640 camera
  • capture image with both cameras
  • send image via TCP Socket connection to a testserver. Images were sent correctly.
  • tested deep- and light-...
manic glacierBOT
#

I've done some additional troubleshooting and found that boot.py finishes but code.py does not start. I put some print statements before and after the storage.disable_usb_drive() and they print on my TFT display.

However usually the boot.py output: line is followed by REPL instructions and then a 'code.py output:' line. Neither of those show after the microcontroller.reset() has wedged the board. Stuck in this condition even after power cycle so some state is saved by the processor in NVM.

lone axle
candid sun
#

<@&356864093652516868> We'll have our weekly meeting in about 60 minutes from now in this text channel and in the circuitpython voice channel. Please take the time to add your notes in advance to the document: https://docs.google.com/document/d/1ioxfUHg7Gfp9VHqaWesxemzBYuxDOkT9S4miuQOiqSc/edit?tab=t.0 -- I look forward to everyone's updates!

lone axle
lone axle
#

The current GitHub build with code, animation files, and wiring diagram, plus a parts list, can be found at:
https://github.com/gallaugher/accessible-catch-with-hub75-displays
Look for a full build video in the future, posted on this channel.

Shoutout to my former students Gage Condon & Daniel Flores who inspired this work with their own projec...

▶ Play video
manic glacierBOT
#

I don't think this is something we need an API for because this is a very rare case. Usually the USB host pins are connected to an actual USB plug. In the metro case, they are pin headers marked as USB Host. We auto-enable it so that it just works.

My suggestion is to do a custom board build with these lines commented out:
https://github.com/adafruit/circuitpython/blob/b8e4fc6bd47d7615324ce1ef7862335b850aedb7/ports/raspberrypi/boards/adafruit_metro_rp2350/mpconfigboard.h#L25-L27

tidal kiln
#

thanks! 👋

lone axle
#

Thanks for hosting Liz, have a great week everyone 👋

candid sun
#

Here is the notes document for next Monday’s CircuitPython Weekly meeting. It is at the normal time of 11am Pacific / 2pm Eastern here on Discord. Everyone is encouraged to attend! Please add your hug reports and status updates even if you’ll be attending the meeting - it’s super helpful! If you are unable to attend but would still like to include updates, feel free to include them in the notes and we’ll read them off during the meeting. Hope to see you there! <@&356864093652516868>
https://docs.google.com/document/d/1Fb4ClW5vcVsv4jzQ-ZAkH4k4HBK1CpD4PxZjpD7Y-Gk/edit?tab=t.0

manic glacierBOT
tulip sleet
#

@slender iron ok, so my plan is to release 10.2.0 final now with the SD Card fix (and a doc fix and getpass in zephyr). Then I'll make the 10.2.x branch and we'll move on from there, doing important bugfixes on the branch, as usual. Sound fine to you?

surreal perch
#

I don't want to be a pain so apologies in advance but unless others have tried and not reproduced #10957 I think it is going to cause a lot of people to come to support with wedged boards. It is not an edge case to be running disable_usb_drive and standard WiFi Webflow settings.toml and do a microcontroller.reset. I can cause the problem 100% of the time with ESP32-S2 and ESP32-S3 boards with 10.2.0-rc0.

tulip sleet
surreal perch
#

Nope. 10.1.4 had the WDT issue but not this issue. I mentioned in the bug report that the same code in the bug report just loops resetting the microcontroller without wedging the board when running 10.1.4.

tulip sleet
#

ok, thanks, I misunderstood. A regression is worth looking at, though in this case, we might tell people to just go back to 10.1.4. I will spend some time on this.

slender iron
#

@tulip sleet sounds good to me

surreal perch
#

Also @pale arch saw a similar problem discussed yesterday in #help-with-circuitpython where his custom CP build for a new board based on main was also not getting to execute code.py. Can't guarantee it is the same bug but it has similar behavior.

manic glacierBOT
surreal perch
#

Oh and @tulip sleet I perhaps don't understand the release process. I was thinking if 10.2.0 became the listed stable release it would cause many more problems as fewer people probably load development vs release version thus causing this issue to become more widespread.

tulip sleet
#

i misunderstood this particular bug and didn't realize it was a significant regression. There are plenty of bugs that haven't been fixed yet, but if they were already present, the new release is no worse. This is worse.

#

I am reproducing without boot.py at all.

#

it is a problem that many fewer people test dev releases. We expect some quick bug fixes to be necessary after a new stable release with significant changes

surreal perch
#

I'm glad I mentioned it. What makes it even worse in my case is that (at least when the boot.py is in place) the board is unresponsive and needs a safe mode restart to get out of it's hanging loop.

tulip sleet
#

I have no boot.py, and this is my code.py (so I can see printing on the serial terminal)

#
import microcontroller
import time

time.sleep(5)
print("resetting in 5 seconds")
time.sleep(5)
microcontroller.reset()
manic glacierBOT
#

<img width="1364" height="2425" alt="esp32s3_n16r8" src="https://github.com/user-attachments/assets/62d1dfdf-73f8-4b6b-a4c9-e5a2a202c8ad" />

This is one of the boards. I used the Get Board Info from Arduino IDE.
I got three of these in one delivery.

One of them reports PID:0x1001 and two of them report PID:0x7003.
All of them report as VID:0x303a with BN: ESP32 Family Device

All of them work with this firmware.

I am new to microcontroller programming and these were my first boar...

surreal perch
# tulip sleet ``` import microcontroller import time time.sleep(5) print("resetting in 5 seco...

This is not crucial but, I just tried on two different ESP32-S2s and an S3 and without boot.py but with CIRCUITPY_WEB_API_PASSWORD and CIRCUITPY_WEB_API_PORT set it just loops reseting with no hang. BTW I do have SSID and PASS also set as I suspect you do. I'm not sure what in my configuration is causing the difference. I'm running Mac OSX Tahoe and using TIO to do the USB Serial. And @pale arch also didn't have a boot.py. For the life of me I can't figure out how to trigger without using the boot.py on my end. Also, all my boards are using the latest TinyUF2 bootloader 0.35.0.

manic glacierBOT
manic glacierBOT
#

I did a bisect on this. Troubles start appearing at the update to ESP-IDF v.5.5.3: #10840. I was testing on a Metro ESP32-S3 with this simple test. CIRCUITPY_WIFI_SSID and CIRCUITPY_WIFI_PASSWORD are set to the local WLAN in settings.toml.
code.py

import microcontroller
import time

time.sleep(5)
print("resetting in 5 seconds")
time.sleep(5)
microcontroller.reset()

It appears that with 10.2.0-rc.0, things are worse when CIRCUITPY_WEB_API_PASSWORD is enabled, but the test...

manic glacierBOT
#

Ok, just documenting very strange behavior. I was testing on three boards that needed boot.py disable_usb_drive and that didn't exhibit the error without. On my TinyS2 I even did a storage.erase_filesystem and the bug behavior would not exhibit. I then rewrote the 0.35.0 tiny uf2 bootloader and then loaded rc0 and copied back the code.py and settings.toml and I can now trigger without boot.py. Crazy...

surreal perch
#

@tulip sleet When you said you didn't have a boot.py did you not even have the file. I'm back to needing a boot.py to trigger the problem but it only has to exist. It is empty in my tests so I guess the supervisor.disable_usb_drive() was not the culprit. I can repeatedly cause the problem by having an empty boot.py and repeatedly loop resets without hanging the board with the empty file renamed to boot_dis.py. I'm not touching the settings.toml or the code.py that you used.

tulip sleet
#

I do not have a boot.py at all.

surreal perch
#

Ok, well I wish I could reproduce your behavior. Do you have four lines in your settings.toml?

tulip sleet
#

i have replicated your problem, but I see signs of it beginning as far back as the update to ESP-IDF v5.5.3.

#

I have:

CIRCUITPY_WIFI_SSID = "MySSID"
CIRCUITPY_WIFI_PASSWORD = "mypassword"
CIRCUITPY_WEB_API_PASSWORD="something"
#

plus more. I comment out the last line or not. The port is not needed if it's the default one

surreal perch
#

I got rid of the port -- it was the default but it is in all my duplicated from previous use settings.toml. I don't have any other lines. Since I copied your exact code.py I can't figure out any other differences. Still same behavior of not failing without an empty boot.py. I suppose maybe the board. I'm using tinyuf2 0.35.0 and uf2 not bin rc0 from the CP webpage. Anyway, not important to solving the bug just bugging me 🙂

manic glacierBOT
manic glacierBOT
#

I am on the trail of this. I reconfirmed it is the ESP-IDF v5.5.3 transition, though why is not clear. I extended the wait to 15 seconds with a variant of the program above, so I could see more clearly what is happening. WiFi use is necessary. The board does not crash hard,. CIRCUITPY is still available. Debug logging shows the WiFi is starting up. I'm now tracking down exactly where it's hanging when attempting to run code.py.

manic glacierBOT
#

I mostly copied the original feather rp2040 board def from rpi pico and did not adjust the flash amount.

My understanding is upstream zephyr uses (DT_SIZE_M(8) for this device here: https://github.com/zephyrproject-rtos/zephyr/blob/d67ec272cc6f86250e6e29eadc4590f865d76c2b/boards/adafruit/feather_rp2040/adafruit_feather_rp2040.dts#L73

With this change my OS reports ~6.8mb total size of the drive as compared to under 2mb like it is without the change.

One tricky bit with this is that...

manic glacierBOT
#

Reverts adafruit/circuitpython#10947.

After further reproduction on the same hardware (Feather RP2040 RFM + Adalogger FeatherWing, CircuitPython 10.1.4 and 10.2.0-rc.0, SPI bauds 400 kHz through 8 MHz, with the RFM CS driven HIGH and floating), constructor order is not a factor in the forum-reported symptom. Both orderings succeed and both orderings fail depending on unrelated variables.

The real invariant — as @bablokb pointed out on the original PR thread — is that every CS pin on...

#

Supersedes #10947 and #10961. Per @dhalbert's note on #10961, folding the revert and the rewrite into one PR so we don't run two merge builds.

What this does

  • First commit reverts #10947 (the "SD-first with an exception for floating CS" framing).
  • Second commit rewrites the existing .. important:: note on sdcardio.SDCard.__init__ to describe the actual invariant on a shared SPI bus.

Why

The previous note said the SD card must be initialized before any other peripheral on a s...

manic glacierBOT
manic glacierBOT
orchid basinBOT
#

Problem

Sorting boards on the downloads page by date (newest/oldest first) produces unexpected results, as reported in #1760.

Root Cause

The sort comparator in downloads.js had several issues:

  1. Tag match overrides all sort modes: The exact tag match promotion (return -2) ran before the sort-type switch statement for all sort modes, so when a search term was active, matching boards were always pushed to the top — even when the user explicitly selected date or alphabetical...
manic glacierBOT
orchid basinBOT
#

Adds board pages for all 15 boards currently reported as missing by tools/missing-boards.py.

Boards Added

Zephyr port boards (12):

Board Image Family
adafruit_feather_nrf52840_zephyr Reuses feather_nrf52840_express.jpg zephyr
adafruit_feather_nrf52840_sense_zephyr Reuses feather_bluefruit_sense.jpg zephyr
adafruit_feather_rp2040_zephyr Reuses adafruit_feather_rp2040.jpg zephyr
raspberrypi_rpi_pico_zephyr Reuses raspberry_pi_pico.jpg...
orchid basinBOT
manic glacierBOT
#

Mount SD card at filesystem init so macOS can see it via USB MSC

What this changes

CircuitPython has a nice feature where if your board has an SD card, it shows up to the host computer as a second USB drive. The problem is the SD card currently gets mounted lazily — it only gets initialized when macOS actually asks for it over USB. On some setups, macOS gives up waiting before the SD card is ready, and the drive never appears.

This PR moves the SD card mount to happen during normal fi...

#

RP2040 + SD-over-USB-MSC: bump bulk-IN buffer to 16 KB as a macOS workaround

What this changes

On RP2040 boards that expose an SD card as a second USB drive, macOS stalls the bulk-IN endpoint during multi-sector READ(10) probes when the MSC buffer is the default 1024 bytes. The SD card never mounts on macOS (Linux is fine). Bumping CFG_TUD_MSC_EP_BUFSIZE to 16384 clears it up reliably.

This PR bumps the buffer only for builds where both:

  • the target MCU is RP2040, AND
  • `CIRC...
#

On the Adafruit Metro RP2040 with an SD card, macOS mounts CIRCUITPY fine but the SD card never appears. Firmware instrumentation shows macOS never sends any SCSI command to LUN 1 — probe stops after LUN 0. The same CircuitPython build works on every other RP2350 board tested.

Tested

Board Chip CP version LUN 1 (SD) appears on macOS?
Metro RP2040 RP2040 10.1.4 stable ❌...
orchid basinBOT
#

Summary

Adds a board_usage array field to all Blinka board markdown files in _blinka/, categorizing each board by how it's used with Blinka:

  • Linux (151 boards) — Single-board computers running Linux (Raspberry Pi, Jetson, BeagleBone, Orange Pi, etc.)
  • Attached (16 boards) — USB bridge devices that attach to a host computer (FT232H, FT4232H, MCP2221, Binho Nova, GreatFET One, and U2IF RP2040 boards)
  • MicroPython (7 boards) — Boards running MicroPython firmware (Pyboard...
#

Summary

Adds a board_usage array field to all Blinka board markdown files in _blinka/, categorizing each board by how it's used with Blinka:

  • Linux (154 boards) — Single-board computers running Linux (Raspberry Pi, Jetson, BeagleBone, Orange Pi, etc.)
  • Attached (16 boards) — USB bridge devices that attach to a host computer (FT232H, FT4232H, MCP2221, Binho Nova, GreatFET One, and U2IF RP2040 boards)
  • MicroPython (8 boards) — Boards running MicroPython firmware (Pyboard...
orchid basinBOT
manic glacierBOT
#
  • Fixes #10957

@grgrant could you test? Thanks.

There were two issues here:

  • background_callback_add_core() was not checking the whole list of callbacks to see if the one being added was a duplicate. It was only checking the first one. It was also checking cb->prev for NULL, for reasons that I don't believe made sense.
  • The web workflow background callback was being zero'd out in supervisor/shared/workflow.c before it was added as a background callback. This meant that if it...
orchid basinBOT
#

Adds features list and board usage links to individual Blinka board download pages, displayed just below the Installation Instructions button.

Changes

_includes/download/blinka.html

  • Features section: Uses the same markup/style as non-Blinka board pages (features-list + library-link classes). Links point to /blinka?features=... to filter the Blinka listing page.
  • Board Usage section: Maps each board_usage front matter value to a descriptive label with a link to t...
manic glacierBOT
manic glacierBOT
manic glacierBOT
manic glacierBOT
manic glacierBOT
manic glacierBOT
#

I will see if I can find the manufacturer and can request a PID.

I assume if the seller cannot provide the manufacturer we will not be able to merge, right? But I could still use the boards using one of the other builds and do a manual PIN mapping in the code.py itself, right?

Answered my own question. None of the boards currently have the OV3660 or OV5640 sdkconfig options enabled. So it seems I will need to build my own firmware to use it.

manic glacierBOT
manic glacierBOT
#

Good catch — you're right that CIRCUITPY_SDCARD_USB is the matching precondition. The call site in usb_msc_flash.c gates on SDCARD_LUN, which only exists when CIRCUITPY_SDCARD_USB=1, so tying the new call site to the same condition keeps the two aligned.

Updated in the latest commit: #if defined(DEFAULT_SD_CARD_DETECT) && CIRCUITPY_SDCARD_USB. Verified locally on a Feather RP2040 Adalogger — SD still mounts via MSC on macOS first try. Thanks!

#

You're right — my claim of "no RAM cost for non-SD RP2040 boards" was wrong. With CIRCUITPY_SDCARDIO ?= $(CIRCUITPY_FULL_BUILD) defaulting on, my previous Makefile gate would have bumped the buffer by 15 KB on basically every RP2040 board including ones with no SD hardware (Pico, QT Py, KB2040, etc.). Not OK.

I've pivoted to a per-board opt-in: boards that actually expose an SD card over USB MSC set CIRCUITPY_USB_MSC_LARGE_BUFFER = 1 in their mpconfigboard.mk, and the port Makefile g...

manic glacierBOT
#

See ports/espressif/esp-camera/Kconfig. Most cameras are enabled by default.

The sdkconfig entries for a board are confusing. If the camera is not mentioned at all, but if it's default y in ports/espressif/esp-camera/Kconfig, then it is enabled, unless there are one of two things in the board `sdkconfig:

something like:

CONFIG_OV2640_SUPPORT=n

Setting to n is very rare.
OR
there is a comment like:

# CONFIG_OV3660_SUPPORT is not set

Despite the fac...

manic glacierBOT
tulip sleet
#

@slender iron the background callback PR I felt was a showstopper for 10.2.0 final. We could also include the macOS USB card fix. Do you think an rc.1 with these is in order, or go straight to final?

slender iron
#

I wouldn't worry about getting the macos stuff in. I think I'd lean final. Otherwise we'll need to wait until next week for it

tulip sleet
#

I just merged the background callback, so I'll use that as final. the macos fix is not a regression, the other one was

#

it has the zephyr jpegio you merged too but that doesn't matter

manic glacierBOT
#

Yes — definitively enabled. Verified at three layers on a clean adafruit/circuitpython main + PR 10963/10964 tree:

Makefile (make -n on adafruit_metro_rp2040 and adafruit_feather_rp2040):

CIRCUITPY_SDCARDIO=1
CIRCUITPY_USB_MSC=1

py/circuitpy_mpconfig.h then computes CIRCUITPY_SDCARD_USB = (SDCARDIO && USB_MSC) = 1.

Compiled ELF (Metro RP2040 firmware.elf, arm-none-eabi-objdump):

<tud_msc_get_maxlun_cb>:
    movs  r0, #2     ; LUN_COUNT = 2
    bx    lr
`...
#

I can confirm a new board is not needed.
The yd_esp32_s3_n16r8 works perfectly using the below custom pin mapping.
Tested with OV3660 and OV5640 cams.

# ─── PINS ────────────────────────────────────────────────────
LED         = board.GPIO2
I2C         = busio.I2C(scl=board.GPIO5, sda=board.GPIO4)    
CAM_DATA    = [board.GPIO11,board.GPIO9,board.GPIO8,board.GPIO10,board.GPIO12,board.GPIO18,board.GPIO17,board.GPIO16]
CAM_XCLK    = board.GPIO15
CAM_PCLK    = board.GPIO13
...
#

Fresh OS-host comparison just now — same Metro RP2040, same firmware, same 32 GB microSD, moved the USB cable from a macOS 26.x Apple Silicon host to an Ubuntu 24.04 (kernel 6.17) x86_64 host.

Linux's usb-storage driver polled TUR on LUN 1 persistently until the SD became ready; [MSC] debug trace captured every call:

[MSC] TUR ready lun=1 calls=145
[MSC] TUR ready lun=1 calls=146
[MSC] TUR ready lun=1 calls=147
[MSC] capacity lun=1 count=60579840 size=512 vfs=0x20014ef0

Onc...

#
[adafruit/circuitpython] New tag created: 10.2.0
#
[adafruit/circuitpython] New branch created: 10.2.x
orchid basinBOT
manic glacierBOT
#

Narrowed the bug out of tinyusb's rp2 DCD.

Built tinyusb's own examples/device/msc_dual_lun (pure tinyusb, zero CircuitPython — two 128 KB RAM-disk LUNs, no CDC, no HID, no Audio, no MIDI), flashed to the Feather RP2040 Adalogger on the same macOS 26.x Apple Silicon host, same USB cable, same hub.

Both LUNs mount cleanly on macOS:

$ diskutil list external
/dev/disk4 (external, physical):
   #:      TYPE    NAME          SIZE      IDENTIFIER
   0:              TinyUSB 0    *...
#
    • get_vfs() NULL behavior on LUN 1. If the SD isn't mounted when macOS sends the first TUR, CP returns NOT_READY and macOS stops polling (we saw Linux polling 145+ times before giving up, so macOS's retry budget is much smaller).

I think I saw something like this in the past. macOS was more prone to give up when early tries at talking to the drive didn't work.

Also there is some older work and comments in #6555 on this, before it got incorporated.

manic glacierBOT
#

🎯 Root cause found. Thanks @dhalbert for the #6555 pointer.

Reading hathach's 2022 description of #6555:

response to SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL as unsupported request in all msc examples. This is required for macos to send TEST_UNIT_READY regularly for "SDCard reader" application. Response OK to this request for non-removal device such as ram/flash disk can be beneficial since **macos will skip TEST_UNIT_READY com...

tulip sleet
#

CircuitPython 10.2.0 is released!
https://blog.adafruit.com/2026/04/22/circuitpython-10-2-0-released/
Highlights:

  • New audiotools.SpeedChanger.
  • New qspibus support for displayio.
  • Stability improvements to USB SD card handling.
  • Merge of MicroPython v1.27.
  • Update to ESP-IDF v5.5.3.
  • Many additions to the Zephyr port.
  • Simulated hardware testing is now being done in the Zephyr port.
#

@slender iron i will merge a few things and make 10.3.0-alpha.0 soon

#

if I tag 10.2.0 as 10.3.0-alpha.0 also it can cause some build funnies since they share the same commit, so a little ahead is better

slender iron
#

sounds good to me

manic glacierBOT
#

Why

On macOS, the SD card exposed as a second USB MSC LUN doesn't mount. The probe stops at IOBlockStorageDriver and no IOMedia is ever published. Linux and Windows handle the same firmware fine.

Root cause: CP responds OK to PREVENT_ALLOW_MEDIUM_REMOVAL for every LUN, which tells macOS "this medium is always present, skip TEST_UNIT_READY polling." When the medium isn't actually ready at the single enumeration probe, macOS never re-checks and gives up on the LUN. Linux ignores th...

#

Why

Both boards have onboard microSD slots but their mpconfigboard.h files don't declare DEFAULT_SD_* pin defines. Without these, CircuitPython's native SD automount can't fire and users fall back to mounting SD from boot.py — which hits the VM-heap race in get_vfs() and doesn't expose the card reliably over USB MSC on macOS.

Adding the pin defines lets the native automount path take over (SD is set up before USB enumerates, off-heap, stable across resets) and makes SD-over-MSC "...

#

Superseded by #10967 (per-LUN PREVENT_ALLOW_MEDIUM_REMOVAL response) + #10963 (automount at filesystem_init) + #10968 (SD pin defines for Metro RP2040 and Feather RP2040 Adalogger). That stack fixes the macOS SD-over-MSC probe without any RAM bump.

Root cause was: CP's OK response to PREVENT_ALLOW on every LUN told macOS to skip TEST_UNIT_READY polling for the SD, so if the SD wasn't ready at the single enumeration probe, macOS never retried. Confirmed by the tinyusb-only msc_dual_lun exampl...

#

Full fix stack filed

Three PRs, zero RAM cost, no workarounds:

  • #10967 — per-LUN response to PREVENT_ALLOW_MEDIUM_REMOVAL. The actual macOS root cause.
  • #10963 — mount SD at filesystem_init so it's ready before USB enumerates. Closes the timing race.
  • #10968 — add DEFAULT_SD_* pin defines for Metro RP2040 and Feather RP2040 Adalogger. Lets the native automount path cover those boards.

#10964 closed (the 16 KB buffer workaround is no longer needed).

What's fi...

#

The scenario

A very common Adafruit setup: take a Feather that doesn't have onboard SD storage and add SD via an Adalogger FeatherWing or a Stemma microSD breakout. The user then mounts the SD in boot.py, and expects it to show up on the host computer as a second USB drive alongside CIRCUITPY — the same way the dedicated Feather RP2040 Adalogger or Metro boards do after #10963 + [#10967](https://github.com/adafruit/circuitpython/pu...

manic glacierBOT
manic glacierBOT
#

Confirmed — moving the mount to code.py fixes it on Linux.

Repro:

  • Feather RP2040 + Adalogger FeatherWing, 8 GB SD
  • Firmware: clean 10.2.0-rc.0 + #10963 + #10967, no DEFAULT_SD_* defines
  • boot.py is a no-op; code.py does the sdcardio.SDCard + storage.mount and then while True: time.sleep(60) to hold the VM

Linux before (mount was in boot.py):

sdd   7M   CIRCUITPY
sdf   0B

Linux after (mount moved to code.py):

sdd   7M    CIRCUITPY
sdf   7.3G

Not a bug....

orchid basinBOT
manic glacierBOT
manic glacierBOT
#

Quick cross-board regression test of this PR combined with #10963 on main (which already has #10968 merged as a37aaafe93).

Board Arch LUNs enumerated CIRCUITPY mounts SD mounts Readable Regression?
Metro RP2040 + Adalogger FeatherWing + 8 GB SD RP2040 2 ✅ (ADALOGGER) None
Metro RP2350 (onboard SD) + 8 GB SD RP2350 2 ✅ (ADALOGGER) None

Notes:

  • Host: macOS 26.x (M2 mini)
  • Stack built from `adafruit/circu...
manic glacierBOT
#

I don't think that reporting /saves as removable is a good idea. Host polling seems to considerable slow down CircuitPython (see #10733). This is why I usually disable CIRCUITPY_SDCARD_USB. I never had problems with the saves-partition though. And from a logical perspective, I don't think it should be removable (of course you can umount it, but there are better ways to shoot yourself in the foot).

manic glacierBOT
#

Thanks both.

On /saves: agreed. CPSAVES is a partition of the onboard QSPI flash (same chip as CIRCUITPY, just carved at offset 0), not physically removable — TUR polling on it is wasted traffic, and #10733 is a real concern I don't want to aggravate.

Comparing the two versions for the 3-LUN case (Fruit Jam: CIRCUITPY + SAVES + SD):

Current PR (all LUNs reply ILLEGAL_REQUEST):
  CIRCUITPY : TUR TUR TUR TUR TUR TUR ...   ← wasted (can't be re-inserted)
  SAVES     : TUR TUR TUR TU...
manic glacierBOT
manic glacierBOT
#

Hi, folks!

It is very difficult to tell from the above conversation whether a verified fix has been created or not.

What is the current status on this bug?

  1. Has the actual root cause problem been definitely identified?
  2. Has a verified fix been created?
  3. In what version of CircuitPython will the fix be included?
  4. Is that version of CircuitPython able to be downloaded now?

Thanks for any information!

manic glacierBOT
#

I believe this problem is due to a change made in the ESP-IDF 5.5.1 update that switched to using the memcpy() supplied in the ESP-IDF instead of the one in shared-ibc/string0.c. There is nothing wrong with the ESP-IDF one, except that the way it's being compiled assumes that unaligned accesses to full 32-bit words is possible, which is not true. It is getting a memory fault when trying to make a 32-bit access on an "odd" 16-bit boundary.

I can get a partial backtrace at the fault.

tulip sleet
#

@slender iron I have a discussion topic for when you are around: memcpy on C6 is failing with what looks like an alignment error (32 bit read on an "odd" 16-bit boundary. Weirdly, the same code works fine on C3, and the conditional compilation tests are the same on that platform. However, we treat newlib/nano differently on C6 than C3. I wonder if you have any recollection of this: it was when you updated to ESP-IDF v5.5.1 and moved to the ESP-IDF memcpy instead of the MicroPython string0 one.

I am going to try a simple test program with idf.py. I did spend time with an LLM for several hours on this, and helped with the testing, but its theories were not great. I will try again after furthering targeting.
from Makefile:

# Most current ESPs have nano versions of newlib in ROM so we use them.
ifneq ($(IDF_TARGET),esp32c6)
    CFLAGS += --specs=nano.specs
else
    LDFLAGS += -T$(IDF_TARGET).rom.newlib-normal.ld
endif

thanks

slender iron
#

do you know which implementation you are using?

tulip sleet
#

i am trying to reproduce the problem outside of CircuitPython.

#

I am using memcpy.c in the esp-idf. I have instrumented it various ways to get the bug details.

#

I actually am using a copy of it inside lwip, because it's only provoked by a string copy when the web workflow returns its version info as json

slender iron
#

do you have a backtrace? it can tell where it is

tulip sleet
#

I have considerable detail on that

slender iron
#

I think there might be a wrapper for the idf

#

maybe mbedtls isn't being built with it

tulip sleet
#

let's video if you are available; i can explain

#

i think this may have to do with unaligned fault handling (software recovery is possible), but I'm not sure.

#

it is definitely in the ESP-IDF memcpy, else I wouldn't be getting logging from there

#

backtrace:

0x40804e7c: memcpy at /home/halbert/repos/circuitpython/ports/espressif/esp-idf/components/newlib/src/port/riscv/memcpy.c:75
0x42088c0e: tcp_write at /home/halbert/repos/circuitpython/ports/espressif/esp-idf/components/lwip/lwip/src/core/tcp_out.c:721
#

that is a partial backtrace. The backtrace script is not really correct. this is via looking at the PC and the RP

#

as suggested by Espressif

#

this is a typical crash:

W (10147) memcpy2: aa: 0x40848bcc, bb: 0x42175486, as string: ", "mcu_name": "ESP32C6", "board_id": "adafruit_feather_esp32c6_4mbflash_nopsram", "creator_id": %u, "creation_id": %u, "hostname": "%s", "port": %d,
W (10166) memcpy2: b0 lb: 0x42175486
Guru Meditation Error: Core  0 panic'ed (Load access fault). Exception was unhandled.
#

memcpy2 is just a copy of the memcpy code so I can call it from tcp_out.c directly and not see other memcpy's that are happening

slender iron
#

I'm at home and ari is watching cars. (he's home sick)

tulip sleet
#

ah ok 🙂

slender iron
#

I'm on my laptop

tulip sleet
#

in the above aa is the dest and bb is the source (yes, those are really the variable names 🙂

slender iron
#

it might be worth trying my idf6 branch because it switches to picolibc

tulip sleet
#

bb is not on a 32-bit boundary.

#

There is this code in memcpy:

#if __riscv_misaligned_slow || __riscv_misaligned_fast
    if (n < sizeof(long))
#else
    if (unlikely((((uintptr_t)a & msk) != ((uintptr_t)b & msk))
                 || n < sizeof(long)))
#endif
#

__riscv_misaligned_slow is true, though that seems strange to me. The slow means that there's software ("M mode") that does the misaligned access "manually". If I make that #if 0, the bug goes aaway

#

this code does not break in the C3 build, but it does in the C6 build. Per the above:

# Most current ESPs have nano versions of newlib in ROM so we use them.
ifneq ($(IDF_TARGET),esp32c6)
    CFLAGS += --specs=nano.specs
else
    LDFLAGS += -T$(IDF_TARGET).rom.newlib-normal.ld
endif
#

is in the Makefile, which is weird. Do you have any memory of why you did that? Something special about the C6 vs the C3?

#

If i undo that, it has linking problems. I'm trying to track that down. I can certainly try with 6.0.0.

#

mostly I'm asking you because you did the memcpy switchover and made some special exceptions for C6 only.

#

maybe it was just empirical, but the --specs=nano.specs is unusual

manic glacierBOT
#

I don't think the polling cost issue has been proven out. The linked issue says it occurs even when a host isn't connected. When I've looked at traces from Linux it only queried the drive state once a second. That'd shouldn't be too much overhead.

Although the flash can't be physically removed it is advantageous to "eject" it. The host flushes before doing this and then sends a signal to the device to eject. We have to remember this state so it doesn't immediately pop up again. Now, we can...

tulip sleet
#

no problem if you don't remember; I will continue on the track I'm on, and also try 6.0.0. in master, memcpy is rewritten to use some asm, though I tried that new code and it didn't fix the problem.

manic glacierBOT
manic glacierBOT
#

Ran bablokb's chaos benchmark on a Metro RP2040 to check the polling overhead question. 5 passes each, SD auto-mounted by firmware, USB host connected (macOS):

Firmware chaos avg (5 passes)
All-removable (this PR, current) 0.225s
Per-LUN (SD-only removable) 0.212s

~6% difference, ~13ms absolute. The 3–4x slowdown in #10733 appears to be a separate CP9→CP10 regression unrelated to the removable fl...

manic glacierBOT
#

Tested 4 boards across 2 architectures with firmware built from 10.2.0-4-g834be2c430 (main + #10963 + #10967). No user code — SD mounted via automount_sd_card() defaults on every board.

Board Arch macOS 26.x Ubuntu 24.04
Metro RP2040 RP2040
Metro RP2350 RP2350
Memento ESP32-S3
PyPortal SAMD51

macOS: both CIRCUITPY and SD appear as separate volumes, eject/reinsert works cleanly. Linux: both mount read-onl...

#

Tested 4 boards across 4 architectures with firmware built from 10.2.0-4-g834be2c430 (main + #10963 + #10967). No user code — SD mounted via automount_sd_card() defaults on every board.

Board Arch macOS 26.x Ubuntu 24.04
Metro RP2040 RP2040
Metro RP2350 RP2350
Memento ESP32-S3
PyPortal SAMD51

macOS: both CIRCUITPY and SD appear as separate volumes, eject/reinsert works cleanly. Linux: both mount read-onl...

manic glacierBOT
#

@mikeysklar

Ran bablokb's chaos benchmark on a Metro RP2040 to check the polling overhead question. 5 passes each, SD auto-mounted by firmware, USB host connected (macOS):

Did you average from POR or did you run 5 iterations in one go? In the latter case, averaging 5 passes is not necessarily relevant. Many use-cases for microcontrollers use a "startup-work-deepsleep" scenario. So the results for the first pass are m...

manic glacierBOT
#

@bablokb — you were right on both counts.

Methodology: the 5 passes were in-loop from a single soft-reset, not power-cycled. That captured steady state only. Re-ran with physical power cycles (unplug/replug → full USB re-enumeration) on the same Metro RP2040:

Condition chaos.bm_run timing iter-to-iter gap
Soft-reset (USB persistent) 0.210s flat 0.8s
Power cycle, iters 1–8 (~t=5–20s post-boot) 0.596–0.604s 2.0s
Power cycle, iters 9–10 (~t=2...
manic glacierBOT
#

Hello! This only changes the naming of a single pin on the Waveshare ESP32-S3-Matrix: When I tried did something simple like:

import board
help(board.IO1)

I would get an error like:

AttributeError: 'module' object has no attribute 'IO1'

I eventually figured out that this pin is misnamed I01 (that is, I zero one), rather than IO1 (like input/output 1).

This PR corrects that mistake. This is the only pin on this board that appears incorrectly named like this.

tulip sleet
#

@lone axle I did a clean install of Ubuntu 26.04 on Friday and set it up for development, and am using it successfully. I updated the "Building CircuitPython" guide a bit to acknowledge its existence. The setup was pretty much exactly the same as 24.04. I have not tried to test whether your i386 package issues are still present. If there's an easy way to test for that, let me know and I'll try.

#

A bigger change for me is that I'm trying GNOME with "Dash to Panel" instead of Ubuntu Cinnamon. Cinnamon is behind on incorporating some of the new utilities. But that has no effect on the core stuff I need in any case.

devout jolt
# tulip sleet A bigger change for me is that I'm trying GNOME with "Dash to Panel" instead of ...

Ahahaha, I just spent several minutes trying to parse "Dash to Panel" , searching on the web, trying to figure out what the heck it is and why it's named that. Why is it dashing and why towards a panel? Which panel? So, "Dash to Panel" is a Windows-like taskbar at the bottom of the screen, and it combines app launchers and system tray into a "dashboard" and moves to the main Gnome panel, which is I guess the root window of Gnome. I think. Not a good name, but perhaps "Gnome taskbar" was taken

tulip sleet
# devout jolt Ahahaha, I just spent several minutes trying to parse "Dash to Panel" , searchin...

I had to bookmark it just to remember the name. There is also "Dash to Dock", which is now a part of regular Ubuntu. Dash, dock, taskbar, panel -- hard to tell these apart.
Regular Ubuntu GNOME has a dock and a top bar, which I think is a remnant of Unity. I hadn't used that for years. I switched to Cinnamon a few years ago because I could have a thin bottom bar with launcher icons, status info, and a list of windows. But it had idiosyncrasies, including have to do ctrl-C twice often when copying between applications. So now i'm back to to Windows-11-like setup, not because i love it, but because it's usable enough.

#

at the bottom, and no top bar (seemed like a waste of space to me, so that's why I went looking for something and ended up with Dash to Panel

#

it has a zillion settings

devout jolt
#

I assume new Ubuntu follows this wacky GNOME3 way of doing things that Cinnamon is a reaction to? Seems like whenever I'm in an Ubuntu GUI it's confusing

tulip sleet
#

i think some of the wackiness is lessened from the "Unity" days, which were very Mac-like, and I gave up on that quickly. (App menus at the top of the screen instead of the top of the app menu are not my favorite, but that's gone.

lone axle
#

Nice, I've been using Dash to Panel for a while. I like its behavior compared to the stock ubunty system bar thing.

stuck elbow
#

now they put the menus on the window's title bar

lone axle
#

I do agree the name is very generic though. I wouldn't remember it if not for being bookmarked in my setup notes file.

devout jolt
#

I just made a new Gnome extension called "Race To Conference" that does that same thing but is even more confusingly named

lone axle
#

If I understand correctly, some of those packages conflicted with 64bit ones that were already installed and used by display manager. So during the install I likely agreed to uninstall the existing ones without realizing the consequences.

#

But if you can make it thru a successful native sim build on the local machine instead of inside the container and then reboot and it comes back up to the normal GUI then it would mean that 26.04 doesn't have the same issue.

tulip sleet
lone axle
#

I think maybe you can run it in a standalone window too but not certain.

tulip sleet
#

gotta be out for a while, but I'll look more

tulip sleet
#

was it west that did the installs, or did you basically what the container does on your own machine?

lone axle
#

I believe it was basically what the container does. I don't think it was west install thing that broke it. But I also didn't go back to isolate it.

tulip sleet
manic glacierBOT
#

As a very funny anecdote, I was trying to setup BLE Workflow on a QtPY S3 N4R2 today and searched for information about why I couldn't connect and Lo and Behold, I had submitted a bug report in January and then completely forgot.

I'm pretty sure this is still an issue as of 10.2.0 release but I'm having an issue even pairing using either my laptop or iPadOS Tablet runing Bluefruit Connect. Seems to just hang connecting without a pairing popup.

tulip sleet
#

it did not remove the 64-bit libsdl2 stuff:

$ dpkg -l |grep libsdl
ii  libsdl2-2.0-0:amd64                        2.32.10+dfsg-6                             amd64        Simple DirectMedia Layer
ii  libsdl2-2.0-0:i386                         2.32.10+dfsg-6                             i386         Simple DirectMedia Layer
ii  libsdl2-classic:amd64                      2.32.10+dfsg-6                             amd64        Simple DirectMedia Layer - "classic" implementation as non-default
ii  libsdl2-classic:i386                       2.32.10+dfsg-6                             i386         Simple DirectMedia Layer - "classic" implementation as non-default
ii  libsdl2-dev:i386                           2.32.10+dfsg-6                             i386         Simple DirectMedia Layer development files
ii  libsdl2-image-2.0-0:i386                   2.8.8+dfsg-2                               i386         Image loading library for Simple DirectMedia Layer 2, libraries
ii  libsdl2-image-dev:i386                     2.8.8+dfsg-2                               i386         Image loading library for Simple DirectMedia Layer 2, development files
ii  libsdl3-0:amd64                            3.4.2+ds-1ubuntu1                          amd64        Simple DirectMedia Layer, version 3
#

i am now a bit stuck on pip install -r zephyr/scripts/requirements.txt. It needed libusb-1.0.0-dev, but is now stuck on building hidapi with

/usr/bin/x86_64-linux-gnu-ld.bfd: cannot find -ludev: No such file or directory
#

I haven't found a libudev*to install yet

#

but in any case, I didn't have the package removal problems that you did. Did you replicate that on a fresh 24.04 in a container or anything like that?

lone axle
#

I didn't. I have done the build exclusively inside a container since then, I haven't checked into the display manager inside the container or tried to replicate my setup in one.

manic glacierBOT
tulip sleet
#

ok, fixed that. only the i386 version libudev-dev was installed. I iinstalled the regular one:sudo apt install libudev-dev

#

there is some tussling between the zephyr requirements*.txt and the CPy ones in terms of dueling versions. Also grpcio-tools pulls protobuf back by quite a few versions

#

all set to try a native sim build, but I forget the command I need for that

lone axle
#

make BOARD=native_native_sim

manic glacierBOT
#

I have the code doing a nine stage pipeline to try to keep two SMs in sync with one DMA pipeline but it still drifts a tiny bit, adding up over 30-60 seconds or more. Chaining DMA is a valid RP2xxx construct and the amount of code is not large. I hope it can be considered for the next release. I have a partial solution with a "9-stage pipeline" of events but the drift is significant after 30+ seconds. The methodology is proven in PicoDVI, I'm just hoping it can be brought into our favorite Py...

tulip sleet
# lone axle `make BOARD=native_native_sim`

hmm

-- Found PkgConfig: /usr/bin/pkg-config (found version "2.5.1")
-- Checking for one of the modules 'sdl2'
CMake Error at /usr/share/cmake-4.2/Modules/FindPkgConfig.cmake:1203 (message):
  None of the required 'sdl2' found
Call Stack (most recent call first):
  zephyr/boards/native/common/sdl/CMakeLists.txt:6 (pkg_search_module)
#

they ARE installed, as I pasted above

#

there are other problems. I can't do a regular board build either

#

ok, fixed, the container had (commented out) # west sdk install -t x86_64-zephyr-elf. I did west sdk install without the -t .... (I guess that installs all possible toolchains) Now a nordic board builds

#

native_native_sim still does not build

slender iron
#

i386 is needed because native_sim is built 32bit by default

#

so the code behaves more closely to the code on a 32bit micro

slender iron
#

<@&356864093652516868> We'll have our weekly meeting in about n hour from now in this text channel and in the circuitpython voice channel. Please take the time to add your notes in advance to the document: https://docs.google.com/document/d/1Fb4ClW5vcVsv4jzQ-ZAkH4k4HBK1CpD4PxZjpD7Y-Gk/edit?usp=sharing Talk with you soon!

#

@tulip sleet want to video about this memcpy bug?

tulip sleet
#

i would like to know why my native_sim build is failing

#

given that i have the right i386 packages installed

#

i'll try again right now, because i've rebooted for other reasons

#

None of the required 'SDL2_image' found still getting that

#

is this moved up to 4.something.0 on zephyr yet?

#

or main, you were going to use main?

manic glacierBOT
lone axle
# tulip sleet ` None of the required 'SDL2_image' found ` still getting that

I searched back through my history while working on the first native_sim build I did. I got the error __ also. Here was the advice from claude that I followed at the time.

2. The actual failure is missing SDL2 dev libraries. The real error is here:

  -- Checking for one of the modules 'sdl2'
  CMake Error ... None of the required 'sdl2' found
  ... zephyr/boards/native/common/sdl/CMakeLists.txt:6 (pkg_search_module)
  -- Checking for one of the modules 'SDL2_image'
  CMake Error ... None of the required 'SDL2_image' found

  native_sim links against SDL2 (and SDL2_image) to provide a simulated display/input window. pkg-config can't find them, so
  CMake configuration fails. On Debian/Ubuntu/Raspberry Pi OS:

  sudo apt install libsdl2-dev libsdl2-image-dev pkg-config

  Then wipe the stale build dir and retry (the failed configure leaves a half-written cache that can confuse the next run):

  rm -rf build-native_native_sim
  make BOARD=native_native_sim
#

you can use make BOARD=native_native_sim clean instead of rm. Do try after deleting the old build dir if you haven't

#

ah, actually the above output wasn't helpful I think

#

This one was the one that ended up working.

native_sim is compiled as a 32-bit binary (note the -m32 -msse2 flags in the failing gcc command). That requires the 32-bit
  glibc headers/libs, which aren't installed — hence:

  /usr/include/stdint.h:26:10: fatal error: bits/libc-header-start.h: No such file or directory

  Install the multilib packages:

  sudo apt install gcc-multilib g++-multilib libsdl2-dev:i386 libsdl2-image-dev:i386

  If apt complains about :i386, enable it first:

  sudo dpkg --add-architecture i386
  sudo apt update
  sudo apt install gcc-multilib g++-multilib libsdl2-dev:i386 libsdl2-image-dev:i386

  Then rerun make BOARD=native_native_sim. The 32-bit SDL2 packages are needed because the 64-bit ones you installed earlier
  won't link against the -m32 build.
tulip sleet
#

i did clean builds ... but, turns out I had installed the i386 versions of the libsdl-*dev libraries, but not the x64 versions.

#

so I installed those and now it works

#

so both versions need to be installed. Thanks!

manic glacierBOT
#

Well, the benchmark is part of the CircuitPython distribution. Probably a part from MicroPython. You can find it in tests/perf_bench/bm_chaos.py. I just wrapped it in an easy to use CircuitPython program and as @mikeysklar document he just used it. In the relevant issue, Dan did a different hand-crafted test and I am pretty sure you will be seeing the same type of results.

slender iron
#

so past 4.3.0 but not post-4.4

#

I mean to update past 4.4 but I've been distracted in hardware land

tulip sleet
slender iron
#

good! that's weird

#

multilib support is probably bitrotting in general

#

since we're well past the core CPU to 64bit transition

lone axle
slender iron
#

Here is the notes document for next Monday’s CircuitPython Weekly Meeting. It is at the normal time of 11am Pacific / 2pm US Eastern here on Discord. Add your hug reports and status updates to the document before the meeting. If you are unable to attend but would still like to contribute, feel free to add your notes and we’ll read them off during the meeting. Hope to see you there! <@&356864093652516868> https://docs.google.com/document/d/1rxc6oxuwxAusZ5PpKh_zTZvbefkZWOKUuNJSZOJSQPw/edit?usp=sharing

manic glacierBOT
#

I'll test with a USB analyzer later this week. That is a good suggestion.

Linux looked good compared to macOS in software testing.

Linux testing (usbmon / tcpdump / picocom):

SD card mounts fine with the fix. No slow startup window, no performance impact.

Decoded pcap showing PREVENT_ALLOW response across three builds:

baseline (shipping):
  LUN0  PREVENT_ALLOW → GOOD
  LUN1  PREVENT_ALLOW → GOOD       ← host stops checking, SD never mounts

SD-only fix:
  LUN0  P...
manic glacierBOT
#

There's a ~20 second slow window after plugging in where performance is roughly 3× slower.

It would be great if the root cause of this slow window is fixed. If not, I would still opt for a compile time option to prevent this. I don't think it makes sense to provide a solution for users that eject a fixed builtin device at the cost of punishing users that don't shoot themselves in the foot.

manic glacierBOT
#

There's a ~20 second slow window after plugging in where performance is roughly 3× slower.

I believe this is caused by the host computer doing a lot of reads of the SD card drive as it's mounting it. I see large variances in this time (on Linux) correlated with the size of the SD card filesystem and perhaps also how many files are in the top-level directory. 64MB cards are much faster, for example.

I plan to add the ability to add something like CIRCUITPY_SDCARD_USB=false in `settin...

tulip sleet
#

@slender iron I now have part of the cause of the memcpy issue, but not the whole thing. I have a very simple reproducer program. If CONFIG_LIBC_OPTIMIZED_MISALIGNED_ACCESS=y is set in the reproducer (which is not the default) or in CircuitPython (it's set in sdkconfig.defaults), then the crash occurs. However, when it's set to n, the reproducer runs and completes, but CircuitPython fails early in esp startup, before main(), with a cache error.

I've been comparing sdkconfig.h etc., and haven't tracked down what else is different about our config that would cause the crash. A video chat might be helpful, especially if you remember whey you did end up setting CONFIG_LIBC_OPTIMIZED_MISALIGNED_ACCESS=y (this was last October in an ESP-IDF update PR).

manic glacierBOT
#

What CircuitPython version are you using?

Latest main (verified against current adafruit/circuitpython source).

Code/REPL

import supervisor
print(supervisor.runtime.usb_connected)   # False (no host attached)

import storage
print(storage.getmount("/").readonly)     # (see note below)

Behavior

On a board powered only from a wall adapter (no USB host anywhere on the line), any BLE File Transfer write op (write/move/mkdir/delete) is rejected by the firmwar...

manic glacierBOT
manic glacierBOT
manic glacierBOT
manic glacierBOT
#

thank you for accepting this issue.

i think, power consumption because of higher clock rates is no problem. If the pico2w is used to drive hub75 panels, power of the pico is the least important problem ...

I think, the pico2w is actually the fastest option for hub75? There are faster ESP32 but with less support of HUB75 in circuitpython, Matrixportal S3 with circuitpython is slower too (at the refresh rates ...)

Optimizing the pico2w would be the best option. Thank you

manic glacierBOT
#

I am totally good with this, @dhalbert. I was mostly keeping this here for reference for future development since I made some good headway, but it was too far behind with all of the major developments to the audiocore API and DMA handling since then.

I have been following @FoamyGuy's recent work on I2SIn, and I think it's in the right direction. If guidance is needed in the implementation of I2SIn on RP2xxx devices, https://github.com/relic-se/CircuitPython_PIO_I2S might be a good referenc...

manic glacierBOT
manic glacierBOT
#
[adafruit/circuitpython] New tag created: 10.3.0-alpha.1
orchid basinBOT
orchid basinBOT
tulip sleet
manic glacierBOT
manic glacierBOT
manic glacierBOT
#

Add float support for settings.toml, so we can add several new controls for startup values, such as safe-mode delay, BLE startup delay, etc.

This code was developed with careful guiding of Claude Code using the Sonnet 4.6 model. Because this code must be allocation-free, there is some extra code for doing signed numbers beyond calling the basic float number parser.

Because ports/unix does not implement supervisor, a manual test was developed. I ran it and tested it. The original gen...

manic glacierBOT
#

<img width="480" height="403" alt="IMG_0280" src="https://github.com/user-attachments/assets/7cd9a447-d812-4d53-b085-b1bc406a3e46" />

Captured USB data with a Cynthion USB analyzer + Metro RP2040 on macOS Tahoe across three microSD cards:

  • 64 MB FAT16
  • 8 GB FAT32
  • 32 GB FAT32

Both 10.3.0-alpha.1 (main) and this PR rebased on top of it were tested. This PR works as intended with all media being marked removable by default. You can see ...

manic glacierBOT
#

Summary

  • First audioio.AudioOut for the STM32 port. STM32F4 boards (Feather STM32F405 Express, etc.) previously had no audioio support.
  • Drives the on-chip 12-bit DAC via TIM6 + DMA1 — true analog out, like the atmel-samd port, instead of the PWM-based approach used by raspberrypi and nrf. Mono on PA04/A0 (DAC1); stereo via PA05/A1 (DAC2), with both DAC channels triggered off the same timer so L/R stay sample-aligned.
  • Cooperates with the existing analogio.AnalogOut on this p...
runic loom
#

Hey everyone 👋

I've been tinkering for a while and finally put together something I'd love feedback on — a native CircuitPython module called cnn_helper that lets you run tiny CNN and dense neural network inference directly on the Raspberry Pi Pico.

It's built on top of a small C engine called tiny_inference and compiled into CircuitPython 10.2.0 as a native module. I'm releasing a pre-built .uf2 so you don't need to compile anything to try it.

What it can do right now:
→ Run Conv2d, MaxPool, ReLU, Flatten, Linear layers
→ Load float32 models from the CIRCUITPY filesystem
→ Tiny dense models fit in well under 10KB RAM

The repo also has Python tools to convert any compatible ONNX model to the .bin format the Pico expects.

🔗 https://github.com/code2k13/cp-cnn-extension

This is v0.1.0 and very much a first cut — I'd genuinely love to hear if it works for you, what breaks, and what you'd find useful next. Any feedback welcome! 🙏

GitHub

Convolutional Neural Network extension for Circuit Python - code2k13/cp-cnn-extension

#

A precompiled firmware file is in the releases folder , incase someone wants to try

lone axle
#

<@&356864093652516868> the weekly meeting will occur here on discord today at 2pm US Eastern / 11am Pacific about 90 minutes from now. Add your hug reports and status updates to the notes doc https://docs.google.com/document/d/1rxc6oxuwxAusZ5PpKh_zTZvbefkZWOKUuNJSZOJSQPw/edit?usp=sharing. We look forward to hearing from all who can participate.

slender iron
manic glacierBOT
#

CONFIG_LIBC_OPTIMIZED_MISALIGNED_ACCESS=y is currently set in esp-idf-config/sdkconfig.defaults. Removing this causes the C6 build to fail early in startup, before it gets to main() due to a cache error.

I wrote a simple test program for ESP-IDF that is the essence of the crash above. With CONFIG_LIBC_OPTIMIZED_MISALIGNED_ACCESS=y, it fails. With it not set, it succeeds, and does not get the cache error I mentioned above.

In ESP-IDF v5.5.4 and later, the ESP-IDF-provided memcpy() ...

manic glacierBOT
manic glacierBOT
slender iron
tulip sleet
slender iron
#

risc-v ROM

manic glacierBOT
#

Thanks! On Zephyr — I'm interested but want to flag scope.

A Zephyr port of audioio would live in ports/zephyr-cp/, not as a refactor of ports/stm/, and it's a much bigger effort than the audioio module alone:

  • Zephyr DAC + DMA + devicetree APIs are completely different surface from the STM32 HAL — basically a from-scratch implementation, not a port.
  • ports/zephyr-cp doesn't currently list any STM32F4 board, so there's no hardware-tested path to validate against. Several foundatio...
lone axle
#

Thanks folks, have a great week everyone 👋

slender iron
#

you too!

tulip sleet
#

Thanks @lone axle for hosting!

manic glacierBOT
lone axle
#

Here is the notes document for next Monday’s CircuitPython Weekly Meeting. It is at the normal time of 11am Pacific / 2pm US Eastern here on Discord. Add your hug reports and status updates to the document before the meeting. If you are unable to attend but would still like to contribute, feel free to add your notes and we’ll read them off during the meeting. Hope to see you there! <@&356864093652516868> https://docs.google.com/document/d/1ULRoSo-Bgd8pGDqk-g8L2p2BHvVmc_lU8HrvpRA3okU/edit?usp=sharing

manic glacierBOT
manic glacierBOT
#

Tested on macOS, Windows, and Linux using a Metro RP2040 with 32 GB, 8 GB, and 64 MB microSD cards.

The PR fixes SD card mounting on macOS as intended. Windows and Linux both mounted the SD card correctly on the PR firmware with no regressions — they were unaffected by the change either way.

Full pcaps and SCSI command logs for all three platforms.

| OS | Version | SD Mounts (main) | SD Mounts (PR) |...

manic glacierBOT
manic glacierBOT
manic glacierBOT
manic glacierBOT
#

@dhalbert It is not clear to me if you will be introducing any flags that I should be considering here as well.

I am testing a PR for that. Right now my code is all in tud_msc_test_unit_ready_cb(), so that the SD card LUN reports as not ready. I'm not even sure it would get to your new code in that case. We can merge this first and I can change my PR as needed to deal with your new code.

(BTW, in my PR, I think I may name the flag CIRCUITPY_SD_CARD_USB, and change the internal com...

manic glacierBOT
manic glacierBOT
#

Gate tud_msc_prevent_allow_medium_removal_cb on CIRCUITPY_SDCARD_USB so boards that compile with SD card USB disabled revert to the old non-removable behavior (no TUR polling overhead):

bool tud_msc_prevent_allow_medium_removal_cb(uint8_t lun, uint8_t prohibit_removal, uint8_t control) {
    (void)prohibit_removal;
    (void)control;
#if CIRCUITPY_SDCARD_USB
    tud_msc_set_sense(lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00);
    return false;
#else
    (void)lun;
    return true;
#e...
slender iron
#

@modern sundial want to chat about async when you have a chance?

manic glacierBOT
modern sundial
slender iron
#

when you have time feel free to ping me here and we can talk in a higher bandwidth way than PR comments 🙂

#

I appreciate you circling back to it

manic glacierBOT
#

Is there any possibility that some of this issue could affect anything else, like I2C? I'm having an issue on the nRF52840 with my data stream dropping out ONLY on battery after a very short time, but runs fine on USB power. All of my sensors are on the I2C bus. WHen I remove them and use only the on-board sensors, the problem still happens. Apologies if this is unrelated.

#

Summary

  • Adds board definition files for the NHB Systems L401-S3 datalogger board. (Not yet released)
  • Uses ESP32-S3-Mini-1 module (4MB Flash, 2MB PSRAM) with native USB-C
  • On-board peripherals include an AD7124-4 24 bit ADC, PCA9546A I2C mux, MCP7940N RTC, LSM6DSO IMU, and uSD slot

Testing

  • Firmware builds and runs successfully on board
  • All peripherals tested individually
  • Long running script that utilizes all peripherals, records to file, and publishes data via MQTT
lone sandalBOT
manic glacierBOT
#

Is there any sanctioned way in Circuitpython to sample an ADC coincident another periodic action? For example, is there any way to output a PWM signal and start ADC sampling with analogbufio, with some assurance that the two will actually be phase-locked?

I'm teaching an instrumentation class, and my use case is a beam-block sensor where you pulse an LED and collect analog samples from a photodiode some distance away. The right way to do this is to collect two analog samples for each cycle...

manic glacierBOT
#

I developed some code for CIRCUITPY_USB_HOST = false in settings.toml. However, internally it is not completely satisfactory; the compile-time option is cleaner and safer. The Metro RP2350B board is the only I see that really has the pins available on a header. Given that, I will not add a settings.toml flag and instead would just suggest a custom build. So I'll close this for now.

Making it easier to do custom builds is a future goal. Various people have already made that possible in ...

manic glacierBOT
#

The teaching goal is not related to the data themselves, but rather the measurement techniques (like differential measurements), so wrapping it up in a sort of black box wouldn't be helpful.

Fortunately, for a lab exercise the frequency could be quite low. I suppose an endless loop may be the best we can do. Although after looking at micropython APIs it seems that a timer instance with "hard=True" would avoid the GC delay problem.

My hunch is this is only of interest to circuitpython inso...

manic glacierBOT
manic glacierBOT
#

@dhalbert
Here are my test results: I tested using Linux with a Raspberry Pi Pico W and four different versions of CircuitPython. All versions were configured with a small (200K) /saves partition (but unused by the code). "main" is the main branch up to commit 545fcc5ce7628c2df3d99c29f63232f2a9f5db7a. The test-code is a sensor-sampling program, in this example using a BME280. The crash described below happens after reading the sensor and during writing of the results to the console. Up to t...

#

gc.disable() and gc.disable() can be used to turn off garbage collection temporarily. Given your use case, I think you could do this inside the kind of loop you described or judiciously with asyncio tasks.

I'm not sure, but maybe keypad or countio would be usefl The keypad module does transition detection, and records transitions with a timestamp.

Re MicroPython, I'm guessing you have read https://docs.micropython.org/en/latest/reference/isr_rules.html. Note that CircuitPython use...

manic glacierBOT
#

I believe I am having the same or similar issue. Here is a summary.....

Adding an ESP32-S3 data point to issue #10892.

We have a fleet of seven Adafruit Feather ESP32-S3 (4MB Flash / 2MB PSRAM) units running on CircuitPython 9.2.9 (2025-09-07) that have been rock solid for weeks doing a deep-sleep / WiFi / MQTT cycle every 20 minutes — wake, connect to a Ubiquiti AP, publish SHT45 readings to a local Mosquitto broker, deep sleep. Two development units, one on the same plain Feather ESP32-...

manic glacierBOT
#

CircuitPython version

Adafruit CircuitPython 10.2.0 on 2026-04-22; Adafruit Feather ESP32 V2 with ESP32
Board ID: adafruit_feather_esp32_v2

Code/REPL

boot.py mounts a 16 GB FAT32 microSD card via the Adalogger FeatherWing on SPI:

import board, busio, digitalio, storage
import adafruit_sdcard

spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
cs = digitalio.DigitalInOut(board.D33)
sdcard = adafruit_sdcard.SDCard(spi, cs)
vfs = storage.VfsFat(sdcard)
storage.mount...
#

"""Minimal reproducer for CircuitPython os.statvfs / storage.getmount bug.

Deploy as code.py to a Feather ESP32 V2 with the Adalogger FeatherWing
SD card mounted at /sd via boot.py. Output should be pasted into the
GitHub issue body.

Expected behaviour: statvfs("/sd") returns the FAT32 SD card stats.
Actual behaviour: statvfs("/sd") returns the root LittleFS stats.

storage.getmount("/sd") returns the same Python object as
storage.getmount("/") — proof that the path resolver is broken a...

manic glacierBOT
#

I'm able to replicate the issue running on a Adafruit Metro M4 Express with the current state of the branch on PR #10906.

🐍REPL | 10.1.0-beta.1-81-g8fcd82385b\
Adafruit CircuitPython 10.1.0-beta.1-81-g8fcd82385b on 2026-05-06; Adafruit Metro M4 Express with samd51j19

Here's the simplified test script I'm working with:

import array, math
import board
import audiocore, audioio

MIXER = False
MIXER_LEVEL = 1.0

# Audio Properties
SAMPLE_RATE = 22050 
CHANNEL_COUNT = 1
BUFFE...
manic glacierBOT
#

Given what the sound is described as, it sounds like clipping in fixed-point math. I may have a potential reason.
int16_t panning = synthio_block_slot_get_scaled(&voice->panning, -ALMOST_ONE, ALMOST_ONE);
If panning is 1.0 then this returns 32768, which overflows.

There may be an issue here, but panning is only applied if channel_count == 2. In the provided examples, we're dealing with a mono chain, yet the error still occurs in this state. I'm continuing research now to iden...

#

Removing the loudness multiplication altogether does indeed "fix" the problem, although level is nonfunctional. The problem is definitely within mult16signed or the application of int32_t loudness[2] = { level, level };

if (!voices_active) {
    if (MP_LIKELY(self->base.bits_per_sample == 16)) {
        if (MP_LIKELY(self->base.samples_signed)) {
            if (MP_LIKELY(self->base.channel_count == sample->channel_count)) {
                for (uint32_t i = 0; i < n; i++)...
#

Further testing here: If you remove the architecture specific optimizations in mult16signed, the error no longer occurs and level functions properly. So, something is awry with the ARM assembly.

__attribute__((always_inline))
static inline uint32_t mult16signed(uint32_t val, int32_t mul[2]) {
    /*
    #if (defined(__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1))
    mul[0] <<= 16;
    mul[1] <<= 16;
    int32_t hi, lo;
    enum { bits = 16 }; // saturate to 16 bits
    en...
manic glacierBOT
#

I believe I am having the same or similar issue. Here is a summary.....

Adding an ESP32-S3 data point to issue #10892.

We have a fleet of seven Adafruit Feather ESP32-S3 (4MB Flash / 2MB PSRAM) units running on CircuitPython 9.2.9 (2025-09-07) that have been rock solid for weeks doing a deep-sleep / WiFi / MQTT cycle every 20 minutes — wake, connect to a Ubiquiti AP, publish SHT45 readings to a local Mosquitto broker, deep ...

#

Given what you posted in the issue 100% this is a fixed point issue (I've seen it before). The non-ARM specific flips back to float to removes any fixed point issues too.

From what I remember before we had at least one part where we did 16 bit * 32 bit into 32 bit... which has an issue of course. The key is to always take the two 16 bit values to 32 bit and then back to the 16 bit before any further processing.

If you get stuck shoot me a message too I can take a look.

manic glacierBOT
#

Given what you posted in the issue 100% this is a fixed point issue (I've seen it before). The non-ARM specific flips back to float to removes any fixed point issues too.

I hate to break it to you, but that's not actually the case. 😆

My mind must have been stuck in Python land, because when I changed static inline uint32_t mult16signed(uint32_t val, int32_t mul) { to static inline uint32_t mult16signed(uint32_t val, int32_t mul[2]) { in order to allow stereo level control, I didn...

#

CircuitPython version and board name

Adafruit CircuitPython 10.2.0 on 2026-04-22; Adafruit Feather ESP32 V2 with ESP32
Board ID: adafruit_feather_esp32_v2

Code/REPL

`boot.py` mounts a FAT32 microSD card at `/sd` (Adalogger FeatherWing, SPI, CS on `board.D33`). The reproducer then writes a file whose name begins with a `.`:


import os

# Confirm /sd is mounted and writable
with open("/sd/normal_file.txt", "w") as f:
    f.write("hello\n")
    f.flush()

# Wr...
manic glacierBOT
manic glacierBOT
#

The mount in boot.py only lasts as long as boot.py is running. The SDCard object in boot.py will be deinited when boot.py finishes. boot.py and code.py run in separate, consecutive Python VMs.

When you write to /sd in code.py, it will write the file into the mount point directory itself, not the SD card itself.

Try moving the mount code from boot.py to code.py.

manic glacierBOT
#

Bug

The unix port fails to build on tag 10.2.0 (and current main). py/objringio.c calls the old MicroPython ringbuf API, but CircuitPython reworked py/ringbuf.h — renamed functions, changed struct fields — and objringio.c was never updated.

Since objringio.c is gated behind MICROPY_PY_MICROPYTHON_RINGIO (only enabled by the unix port), this bug is invisible to all hardware board builds.

Error

py/objringio.c:54:46: error: no member named 'iput' in 'struct _ringbuf_t...
manic glacierBOT
#

We don't use the VARIANT=standard build; we only use VARIANT=coverage, so that we can run tests. So we haven't tried to maintain the standard variant at all, and never build it.

There are a number of other things missing from the unix port, like supervisor, that make it not a very good CircuitPython port for actual use. What is your use case for building the standard variant?

manic glacierBOT
#

What is the OS that your host computer is using?

@dhalbert: I am using Linux, kernel 5.14.21

I did some more tests. Slow down and crashes are definitely related to the SD-card in use. My tests above were with a Transcend 8GB class 10 card. Swapping in a SanDisk 16GB class 10 not only speeds up things, but also prevents crashing. Runtimes are still significantly slower compared to 9.2.9 (or to 10.3.0 with disabled SD-card presentation), but not as bad as documented above.

manic glacierBOT
manic glacierBOT
#

@bablokb -

During earlier testing I saw Linux showing the best host OS behavior. macOS had a long cold plug delay and windows just hammered away on a microSD disk with read(10) for over 40 minutes.

I'd like to run the tests again with todays main branch. One build in default mode and the other compiled with CIRCUITPY_SDCARD_USB=0 (off).

  • Metro RP2040
  • 16GB SanDisk class 10 (FAT32)
  • 64MB (FAT16)

Running this [benchmark code.py](https://github.com/mikeysklar/circuitpython-pr10967-testda...

manic glacierBOT
#

A more thorough treatise for this issue and paths to resolution"

rp2pio: hardware-chained DMA for background_write(loop=)

Fixes #10871

Summary

Replaces the IRQ-based DMA loop-restart path in background_write with a hardware-chained two-DMA-channel pattern for the pure-loop case (loop= set, once= and loop2= empty). Restart latency drops from ≈2.5 µs (worst case observed via fifo_type="tx" test) to a handful of DMA bus cycles (~20–40 ns at 252 MHz), eliminating PIO TX FIF...

manic glacierBOT
manic glacierBOT
manic glacierBOT
manic glacierBOT
#

I can't confirm the "slow-window", at least not in this size. With my 8GB card (which leads to a crash), there is nothing like that up to the crash. The crash is 122s after POR and the print statements just before crashing take about 1.5s each. But my test does much more than "cpu-only": it dynamically loads code, uses I2C, connects to WLAN, does a request and so on. Especially the networking should add load to background processing and will probably compete with tiny-usb.

BTW: the card itse...

manic glacierBOT
#

The pin was always available as microcontroller.pin.GPIO41 but this is a nice shortcut so thanks @JonNelson

I tested the new release and it correctly aliases pin GPIO41.

Adafruit CircuitPython 10.3.0-alpha.1-7-gb9305fc290 on 2026-05-07; FeatherS3 with ESP32S3
>>> import board
>>> import microcontroller
>>> dir(board)
['__class__', '__name__', 'A0', 'A1', 'A10', 'A11', 'A12', 'A2', 'A3', 'A4', 'A5', 'A6', 'A7', 'A8', 'A9', 
'AMB', 'ANTENNA_SWITCH', 'BATTERY', 
'D0', 'D1', 'D1...
manic glacierBOT
#

On a Feather ESP32S3 N4R2 with a freshly formatted drive simply typing import wifi at REPL causes a safemode crash.

Adafruit CircuitPython 10.3.0-alpha.1-6-g45fecd285a on 2026-05-07; Adafruit Feather ESP32S3 4MB Flash 2MB PSRAM with ESP32S3
>>>
>>>
>>> import wifi

[14:58:03.339] Disconnected
[14:58:04.351] Warning: Could not open  (No such file or directory)
[14:58:04.352] Waiting for tty device..
[14:58:06.394] Connected to /dev/tty.usbmodem8B8F267DF7841

You are in safe m...
manic glacierBOT
manic glacierBOT
#

@mikeysklar
I ran your cpu-only benchmark with minor changes (actually mounting the SD-card and printing each iteration). It crashes again after about two minutes. The first iteration seems ok, but already the second one is really slow.

[10:51:49.343] mounting SD...
[10:51:53.178] SD-card mounted on /sd
[10:51:53.178] done
[10:51:53.420] iter001: t+  0.00s  cpu= 239ms
[10:53:43.654] iter002: t+  0.24s  cpu=109731ms
[10:54:03.469] Wi-Fi: aus | Fertig | 10.3.0-main-10967
Automatisches Neu...
manic glacierBOT
#

Pull request overview

Adds support for a newly shipping SSD1680-based MagTag ePaper panel variant (FPC-7519rev.b) by extending the board-level panel detection logic to apply the correct column start offset, matching existing handling for a prior SSD1680 revision.

Changes:

  • Document the SSD1680 half-duplex USER ID read behavior and add notes for a third observed panel type.
  • Extend the USER ID first-byte detection switch to recognize 0xCA and select colstart=8.

💡 Add C...

manic glacierBOT
#

Related logs from journalctl:

May 08 10:51:47 canopus kernel: usb 1-2: new full-speed USB device number 61 using xhci_hcd
May 08 10:51:48 canopus kernel: usb 1-2: New USB device found, idVendor=239a, idProduct=8120, bcdDevice= 1.00
May 08 10:51:48 canopus kernel: usb 1-2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
May 08 10:51:48 canopus kernel: usb 1-2: Product: Pico W
May 08 10:51:48 canopus kernel: usb 1-2: Manufacturer: Raspberry Pi
May 08 10:51:48 canopus kernel: usb 1...
manic glacierBOT
tulip sleet
#

@slender iron Claude added (or you?) in the ESP-IDF v6.0.1 PR:

#if defined(CONFIG_SOC_RTC_FAST_MEM_SUPPORTED) || defined(CONFIG_SOC_RTC_SLOW_MEM_SUPPORTED)
...
// Chips without RTC memory can't persist SleepMemory across deep sleep.
...
#

in common-hal/alarm/SleepMemory.c. Are there are any Espressif chips you know of that don't actually have RTC memory, either fast or slow?

#

I am asking just to add a warning in the shared-bindings doc if that is a real case.

manic glacierBOT
#

On a Feather ESP32S3 N4R2 with a freshly formatted drive simply typing import wifi at REPL causes a safemode crash. No issues on 10.3.0-alpha.1. Of the S3 releases published for this board between Alpha.1 and PR10922 none of the others crash importing wifi. However PR10984 for UM F3D new pin definition does crash in the same way -- perhaps includes code in 10922.

Checked this release on a Feather ESP32S2 TFT and didn't see the crash so perhaps a difference between S2 and S3 codebases (m...

tulip sleet
#

@slender iron I think there are no such chips right now

manic glacierBOT
#

Here is the test with the XTSD (1GBit, i.e. 128MB). Slowdown is for about 15s. So this is clearly hardware (and host) dependent.

[16:21:27.995] mounting SD...
[16:21:33.209] SD-card mounted on /sd
[16:21:33.209] done
[16:21:33.443] iter001: t+  0.00s  cpu= 229ms
[16:21:33.727] iter002: t+  0.23s  cpu= 278ms
[16:21:34.365] iter003: t+  0.52s  cpu= 632ms
[16:21:35.042] iter004: t+  1.16s  cpu= 667ms
[16:21:35.678] iter005: t+  1.83s  cpu= 629ms
[16:21:36.312] iter006: t+  2.47s  cpu= 626ms...
manic glacierBOT
slender iron
#

@tulip sleet sorry for not getting back. At a kids doctor checkup this morning

tulip sleet
#

np - i should have just put the q in the PR

surreal perch
#

@tulip sleet Would it be preferable in the future if I put an issue like the wifi import crash in a new issue rather than reply to the merged/closed #10922? Just trying to figure out how best to contribute.

manic glacierBOT
slender iron
tulip sleet
tulip sleet
#

An open issue is a trackable thing that must be closed. Something mentioned in a closed PR or issue might get lost

manic glacierBOT
#

The FPC-7519rev.b panel (User ID byte `0xca`, batch W42972-E, same batch fixed for colstart in #10987) produces a dark gray background when driven with the default VCOM=`0x28` (-2.0V).

Root cause

`ssd1680_display_start_sequence` is shared by all SSD1680 variants. The 0x44 panel works correctly at VCOM=0x28, but the 0xca panel needs a lower VCOM to achieve proper white-state voltage.

Testing

Swept VCOM from 0x18 to 0x28 in steps on a live 0xca panel using the CircuitPython ...

manic glacierBOT
#

We don't use the VARIANT=standard build; we only use VARIANT=coverage, so that we can run tests. So we haven't tried to maintain the standard variant at all, and never build it. (In fact just plain make in ports/unix defaults to coverage.)

There are a number of other things missing from the unix port, like supervisor, that make it not a very good CircuitPython port for actual use. What is your use case for building the standard variant?

Goal was just to test python c...

manic glacierBOT
#

The comment mentions a 7619rev.b instead of a 7519rev.b. However, I don't recollect any 7619's. I think that might be a typo. The pictures in the threads and in #10831 (superceded by #10836) only have 7519's, unless I missed one.

I tried this patch on my 7519 0x44 board. I'm not sure it's lighter but I would say it's still "blurry". I think the blurriness is easier to see on the weather demo: https://learn.adafruit.com/magtag-weather.

Here are a couple of pictures
First is original Ma...

#

Thanks for testing Dan on the 0x44. I find this PR is only marginally better than the defaults. Not nearly as crisp as the original SSD1680 or ILI0373.

I did discover the display has an OTP register which holds the recommended VCOM value and went with that.

// VCOM=0x14 (-1.0V) confirmed by reading the panel's OTP register (cmd 0x2D, byte 1 = 0x14).

Just to make sure I also did a brute-force version with a webcam and let claude cycle through other VCOM / border / etc. settings jus...

#

I don't know if the label FPC-7619rev.b even truly exists, but that is what is the original board.c before I started mucking with it this week.

I think that is just a typo that should be fixed. I think they are all 7519's.

There is something about the newer panels that is apparently not as good as the older ones. The gray cloud is nice and uniform on the old displays, and speckled on the new ones. This is not a photo artificact; it is how it looks:
<img width="199" height="177" alt="...

glossy pecan
#

Is there a more detailed guide to building CircuitPython from source than the Adafruit web pages, especially on macOS?
Have been fighting with the process and keep getting tangled up venv vs conda vs implicit environments, make vs gmake, etc., etc. 😡

tulip sleet
tame creek
#

my recollections (maybe a bit out of date) of setting up macOS to build CircuitPython: use Homebrew to install as much of a GNU build environment as necessary to make it work. i think gmake and maybe autotools? though you should probably use the official ARM compiler distributions. also use Homebrew to install a modern python, and use a venv

glossy pecan
#

Thanks🙏🏻, folks, for the quick response. Linux VM is a great idea. My Mac environment is old and full of historical cruft. Keeping the dev environment clean is especially valuable since I'm working up to porting CP to a new Nordic DK.
By the way, Nordic boards appear in both the Nordic and zephyr port folders. I presume the former are "bare metal" and the latter are built on top of a minimal zephyr os. Correct?
And while I'm asking questions, what's the approved bootloader solution for Nordic boards: leave them with the stock Nordic bootloader or migrate to UF2(? and how?). I have all the Nordic tools.