One file to revert. The other changes look good.
#circuitpython-dev
1 messages · Page 95 of 1
Yup! You got it. Looks good to me.
Looks fine. My only gripe is that audiotools is vague and likely to have other stuff thrown into it. I'd prefer something more specific like audiospeed (which better matches audiodelays). Are you ok with that change? Claude should make quick work of it.
Right now it's impossible to use the Stage library, because it always throws a validation error.
I made a second pull request against 10.1.x here: https://github.com/adafruit/circuitpython/pull/10909
I wouldn't mind if both of them were merged, so I'm not closing this one.
[adafruit/circuitpython] New comment on issue #10888: Update CI actions to versions that use Node.24
@carlosperate and @ETSells Thanks!
- Fixes #10888.
Update GitHub CI actions to latest major versions, to update Node.24.
https://github.com/carlosperate/arm-none-eabi-gcc-action/issues/86 updated a non-github action we also use: no version bump was required.
I'll ask for a review after I see the builds work :)
It is more annoying than helpful. We can set up an auto-updater later on when they get out of date.
Maybe this could be a pre-commit check later, or is that too strict?
What is the circumstance where you want to push without updating?
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.
- Fix flash writing with more than 32 filesystem blocks per erase page and add a test for it.
- Fix Feather UF2 to place code in the right spot (the code partition).
I want to make it easier for other folks with a non-zephyr setup to add modules. I'd expect my zephyr PRs to update these. The updates are kinda noisy too so I think separate auto-update PRs could be more manageable (just like weblate updates.)
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 ...
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...
I cannot for the life of me find support for Circuitpython and Seeed Studio's nRF52840 Sense PLUS board. The Circuitpython for the nRF52840 Sense loads to the board, but when I try to use pins D11 or higher, it tells me the board module has no D11 or higher. Is support for the Sense Plus' additional IO coming?
Thanks,
circuitcameron
Seeed boards are community maintained so you could make one. Instructions are here: https://learn.adafruit.com/how-to-add-a-new-board-to-circuitpython/
You can also access all pins with microcontroller.pin.
I thought that might be the case, thank you for your reply and the tip! I've learned something new!
I don't think I have the knowledge to fix this properly. I'm going to close this.
Since https://forums.adafruit.com/viewtopic.php?p=1078149 is locked, I'm replying (much delayed) here. I have a bunch of Seeedstudio ESP32-C3 exhibiting the web workflow failures, but have also seen this on an Adafruit Feather (forget which one) in teaching CPy.
Images automagically compressed by Calibre's image-actions ✨
Compression reduced images by 18.6%, saving 497.0 KB.
| Filename | Before | After | Improvement |
|---|---|---|---|
| assets/images/boards/original/adafruit_tinychad_rp2350.jpg | 376.3 KB | 306.7 KB | 18.5% |
| assets/images/boards/original/nxp_frdm_mcxn947.jpg | 352.0 KB | 303.3 KB | 13.8% |
| assets/images/boards/original/... |
Nice generalizations in the cache flashing. I guess if everything is zephyr this would not need to be back-ported to other ports' flash implementations, but would it make sense to factor it out as port-independent, or is there too much zephyr-only stuff there (I'm not sure, but it looks like not).
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...
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...
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...
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)
I don't think we need to factor it out because my hope is to migrate everything to Zephyr eventually.
Relies on added SDL audio emulation.
Are we violating the bluetooth spec or just confusing these pedals?
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...
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...
Implement nvm.ByteArray using Zephyr flash_area API, auto-detect NVM partition size from device tree, and add 8KB NVM partition to feather nrf52840 matching the non-Zephyr Nordic port layout.
Looks fine.
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.
@IrregularShed Your comment is worth preserving as its own issue, if you'd like.
[adafruit/circuitpython] Pull request review submitted: #10646 Added Board WeAct Studio RP2350B Core
Sorry for the delay; I thought there was some change left to do do.
Looks fine.
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.
These per-board
.confand.overlayfiles: 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 ...
Has anyone taken a video of this?
I am tangerinescream from the adafruit forum post- https://forums.adafruit.com/viewtopic.php?p=1085060#p1085060
Here is a video showing the issue (unlisted youtube) https://www.youtube.com/watch?v=rvGJf9F1d8Q
@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...
This is related to #10914.
This matches the setting for adafruit_qtpy_esp32c3
The Feathers all have larger antennas.
The only difference between the QT Py ESP32-S3 8/0 and 4/2 boards is the (multi-die) chip: the antenna components are all identical. Why you don't see the problem on the 4/2 boards, I don't know, but I'd be inclined to set the same power for both. Perhaps it is a date-of-production variation.
@tannewt,
I have an example, however it is 14MB. How do I get it to you?
Bruce
@b-blake - A link to google drive would be helpful.
As mentioned in https://github.com/adafruit/circuitpython/issues/10914#issuecomment-4178881022, I am kind of inclined to do this for both ESP32-S3 QT Py's, but others may disagree.
@dhalbert Added it for adafruit_qtpy_esp32s3_4mbflash_2mbpsram as well.
Would you be willing to revise this to be against the 10.1.x branch instead of main?
Unfortunately does not work to just change the base, because you'll drag in a lot of commits. You may need to close this and reopen a new one.
@dhalbert My bad - CircuitPython contributor noob. Please stand by :smiley:
This is related to #10914.
This matches the setting for adafruit_qtpy_esp32c3
@jesseadams Not your bad. The choice of branch here has more to do with the expected arrival of 10.2.0 vs the next 10.1.x.
- Arduino ESP32 BSP 3.1.2 = no flicker; 3.1.3+ introduces it (suspected IDF5 timing change)
Does this mean it is an IDF bug? What versions of the IDF does Arduino use?
I've got a branch to update to IDF6. We can test with that and fix there if needed.
Please approve again. I forgot to update zephyr with a fix for USB. (It's harder to remember because it isn't a submodule.)
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.
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
such a shame that set is already a keyword ;-)
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
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...
I'm somewhat tempted to move the espressif port to the same setup as the zephyr port, cmake calling into async python.
would it use any of the esp-idf cmake stuff?
Remember i already added supervisor.get_setting() to do a parsed os.getenv(). Could have supervisor.get_settings() that returns a dict of them all. Or it could be a dict-like object that is mutable. Or we could implement os.environ that is the string-only values. But the current impl is tiny and does parsing of the .toml on the fly for code-space reasons.
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?
I'd be interested if it worked similar to zephyr. Pass in compiler and flags, we create a library and then it links it all together. Yesterday I was fighting the annoying -u linker stuff.
is it worth it if we are moving esp-idf to zephyr in the same time frame?
I like the idea of a separate module because we can only enable it on certain ports that have room. I also like the idea of being interactive so you can discover settings that my not be in settings.toml yet. (However we could also put those in a dict we return.)
LLMs throw a wrench in that question because it could be straightforward for an LLM to do.
Please see my repo for an example project using the Qualia board, the 320x960 display. Platform.io, GFX, and LVGL:
QualiaTestingProject
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.
could you also use an LLM to maintain the current setup?
I'm trying
I liked the os environment comparison
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)
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
agree with that -- but if they eventually put zephyr into esp-idf, that is a new ballgame. But I don't know if that is in the works, or whether it will always be separate
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)
I'm sure they are still ahead of freertos. not sure how though
so what do we think about settings?
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.
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.
Here are test builds based on IDF 6: https://github.com/adafruit/circuitpython/actions/runs/23958506278
I've verified WiFi comes up and used web workflow briefly on the C6.
I want it to modify settings.toml. I'm using it to setup a new board essentially.
I think that could be not so easy, since it can have comments, etc.
I have found a working solution so far. I have changed my platform to this:
platform = https://github.com/pioarduino/platform-espressif32/releases/download/stable/platform-espressif32.zip
in my platform.ini
Also affected: Adafruit Feather STM32F405 Express with CircuitPython 10.1.4.
Symptoms: board boots into safe mode with CIRCUITPY drive could not be found or created. storage.getmount('/') throws OSError: [Errno 22] Invalid argument from the REPL. Mass-erasing and reflashing via dfu-util does not help.
Downgrading to 9.2.9 resolves the issue immediately.
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.
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...
I do have an Metro M4 Express board setup I can use to test changes on the mixer. if you need a setup to test.
Btw. I build CP 10.1.4 with the mixer changes you proposed but sadly audio is still distorted.
hi, i made a new port for circuitpython, anything i should know before making a PR :>
a new board or a new port?
https://learn.adafruit.com/contribute-to-circuitpython-with-git-and-github for general github info
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.
oops sorry, board definition -w-
good to know , ty!!
@CoolDom Thank you for testing the build and verifying the results!
I have prepared a build environment and checked out 10.1.X. Unfortunately, when building for the Feather ESP32C6 I found two issues:
- The Makefile appears to disable debugging with -DNDEBUG and -Os but only for riscv (like the C6).
- 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...
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.
<@&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.
@JonNelson Turn off ulab: CIRCUITPY_ULAB = 0 in the board's mpconfigboard.mk (or in mpconfigport.mk). That will free up a lot of space. There are many other things to turn off as well.
If your board has more than 4MB, it'll have two OTA partitions. You can change the partition csv so OTA1 takes up the space for both to gain a bunch of space.
[adafruit/circuitpython] Pull request opened: #10923 Add Zephyr build for the Feather nrf52840 Sense
Allow for name override in circuitpython.toml. Zephyr has weird names for these boards because they have one board definition for two "variants". Our override allows us to clean that up.
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
Google Docs
CircuitPython Weekly Meeting for April 13, 2026 Welcome to the CircuitPython Weekly meeting notes! Feel free to add your Hug Reports and Status Updates before the meeting, alphabetically by your username. During the meeting, we go through them in order. If you can’t make the meeting and would st...
Addition
Adding guardian-agent-prompts - 49 production-tested AI agent system prompts for Claude Code multi-agent orchestration.
- 49 specialized agents for orchestration, coding, security, trading, and automation
- Production-tested across 10,000+ tasks, MIT licensed
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 ...
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 aftercheck_pins(), which setsself->sck.mark_deinitthen NULLedself->sck, and the immediately followingself->sck->altfn_indexdereference 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.
Thanks for finding this!!
I would have asked you to submit this against 10.1.x instead of main, but we are planning to release 10.2.0 within a week or two. If you would like to see this in a numbered release really really soon, you can resubmit against 10.1.x and I'll make a release within a couple of days.
I've tested this build successfully on various simpletests that include: displayio, i2cbusdisplay, fourwire, busdisplay, seesaw, and nvm
Move mark_deinit() before check_pins() so that self->sck is not NULLed after check_pins sets it. The previous ordering caused a NULL dereference of self->sck->altfn_index, crashing all STM32 boards that use SPI (including STM32F405 boards whose CIRCUITPY filesystem lives on external SPI flash).
Fixes adafruit/circuitpython#10866
Amazing! I Created a new PR
https://github.com/adafruit/circuitpython/pull/10926
Closing this one
FYI, I put a few other synthio discussion points in a recent post, Adafruit Forums: synthio: adjusting envelope, monophony, current amplitude of Note, note number vs frequency, osc sync, filter envelopes .
Fixes #470. Using Claude Code, I went through and added OSHWA Certification as a feature of the board. This went through not only Adafruit Boards, but any boards listed that a match was found in the OSHWA database.
I had Claude Code search for information about the hidden boards. The CP32-M4 had enough info to unhide, which increases the board count by 1. For the others, the updated information will make it easier to find info about the boards in the future.
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...
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 ...
I'm wondering if there is something else I need to do to get the rest of the autogen files to update?
I usually run make all (there is make clean-all too.)
do not guarantee the evaluation order of function arguments.
Whoa! I did not know that. Python does left-to-right: https://docs.python.org/3/reference/expressions.html#evaluation-order
@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?
yup, native sim needs the 32-bit version. works on arch ok. what distro are you on?
Ubuntu 24.04
the CI had trouble installing it until I pinned...... python iirc
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.
eeesh, I'm not sure
you could try building the 64 bit version but that'll mess up the pointer sizes
I will look into getting a container set up
and probably add a warning note to the readme to try to save someone else.
works for me! sorry for the trouble
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.
ubuntu 26.04 final is two weeks away; would be interesting if it didn't have the problem you described
After running this by @ladyada in one of the meetings, we decided not to do this.
I'm going to close this. It's a bit complicated, we don't want to hide these boards, and provides little benefit for most people.
The Processor family, which was granularized in #1748, works with MCU searchability.
Board definition for Pimoroni Badger2350
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 ...
This si fine but I wonder about the double-reset thing @FoamyGuy mentioned. That could be opened as a new issue.
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...
This si fine but I wonder about the double-reset thing @FoamyGuy mentioned. That could be opened as a new issue.
Two small things. Thanks for the PR!
[adafruit/circuitpython] New branch created: zephyr_aesio
[adafruit/circuitpython] New branch created: zephyr_aesio_
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.
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 ...
@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?
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?
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
Merge MicroPython v1.27. This merge includes v1.26 as well.
- Upstream
extmod/modre.cincludes support forposandendposarguments inmatch()andsearch(). This replaces our own implementation with upstream. - time epoch handling is now more like our own, also removing some differences.
MP_NORETURNis now used everywhere instead ofNORETURN.- I fixed things related to
ports/unix/coveragecpp.cppso it is more like upstream. ports/unix/main.cis now more like ups...
PR includes the following changes:
- Ran
make allzephyr boards to get their autogen files updated for msgpack and other resent changes - Added
DISABLED_MODULESlist 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...
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...
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 ...
Ok, let's get this in to start. :-)
Thanks for picking this up! One question before we merge.
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...
@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.
Confirmed testing results for #10423
Config: M4 I2C Controller writing large packets to an M4 I2C Target and a RP2350 I2C Target. RP2350 I2C Target now reads successfully. Thanks FoamyGuy !
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
mainor against (if it exists) the branch for the current stable release or an upcoming minor release. The branch will be namedi.j.x, for example,9.2.x. Bug fixes and minor enhancements can be submitted against the stable release b...
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...
@todbot @relic-se Curious as to your two thoughts on this as you are two of the people closer to the audio areas.
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...
For visual UI, it could just be a checkbox. Then for filtering, instead of <condition 1> and <condition 2> and <condition 3>, it could be inverted with not <condition 1> or not <condition 2> or not <condition 3>.
It would be nice if the internal timers on the micro:bit v2 could be used with CircuitPython (for the display so it can be multiplexed correctly)
I am not sure what you mean by the "internal timers". Could you elaborate? Since this is an nRF52840 (albeit without USB connections), whatever we support on nRF52840 in general would be supported here.
I mean the timers like TIMER0, 1, 2, 3, and 4. This should provide more of an explanation https://docs.rs/microbit-v2/latest/microbit/display/nonblocking/index.html
I would love to see a solution for this long standing issue. Does anybody know if this works with IDF?
What's your use case for the timers? CircuitPython doesn't provide interrupt routines, but it does implement asyncio. See https://learn.adafruit.com/cooperative-multitasking-in-circuitpython for a tutorial and many examples.
This is probably a good idea. Although, I know some areas where floating point math is required such as audiofilters.Distortion (using audiofilters.DistortionMode.OVERDRIVE. But those are really far and few between.
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
<@&356864093652516868> The weekly public CircuitPython meeting will be at 2pm US Eastern time, in just over two hours. Add your notes to https://docs.google.com/document/d/1VHGPs23KrEB_xy1HJ36wwLifFg8WdTYGw5IRndSnBVs/edit?usp=sharing
Sorry I didn't suggest this sooner. I think we just need to add watchdog to this test:
https://github.com/adafruit/circuitpython/blob/2a4ccc2d19d2b42296bb2d49c82cc10cddffc1c3/supervisor/shared/web_workflow/web_workflow.c#L340-L348
Ok, thanks for the fix!
I bet we're missing the pin alarm reset reason here:
https://github.com/adafruit/circuitpython/blob/1eb34d0f91b81d2919dab65549cc08a1c511f1a1/supervisor/shared/bluetooth/bluetooth.c#L188-L196
The blue blink is waiting for a button press to enter the BLE workflow (which IIRC we added to ESP in 10.x).
There is way too much going on in this PR. Please review it yourself before opening it up and keep the PRs small and focused. (One for the board addition only for example.) Don't delete a whole port.
@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.
thanks!
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.
I reproduced the zephyr errors on the mp merge branch locally and claude is looking into it
@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
trying to reproduce now doesn't cause the problem. there are many web post re "choppy audio" in OBS. I'm looking at those
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.
@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.
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.
@slender iron thanks!
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```
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
@tulip sleet this is waiting for final approval: https://github.com/adafruit/circuitpython/pull/10923/
thank you!
i missed the review dismissal
np
And add native_sim tests that validate their behavior compared to cpython implementations.
all set - thanks!
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
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...
Support for Pimoroni Badger2350 was added with https://github.com/adafruit/circuitpython/pull/10929
The target directories for images were missing the /boards/ directory component.
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...
One follow up question that we don't need to answer now.
@tulip sleet I reviewed the merge and it looks good. Will leave merging up to you
Great! I just finished doing some more extensive testing on each port.
CircuitPython 10.1.1 and later on Adafruit Feather STM32F405.
CIRCUITPY is not available. Board comes up in safe mode. storage.erase_filesystem() does not help. When firmware is reverted to 10.0.3 or earlier, it works.
I tried this on two different Feather STM32F405's.
I tested as follows:
espressifMagTag: tested deep sleepPinAlarm, and separately, a portal weather application.atmel-samdPyPortal - tested a PyPortal application that uses the Internet. Also did blink on SAMD21.nordicFeather nRF52840 - tested BLE UARTraspberrypiFruit 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.- ...
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.
How can I build a version with those features turned on? Also, the version you built does not launch CircuitPython.
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.
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...
The microbit_v2 build is quite minimal. It is a CIRCUITPY_FULL_BUILD = 0 build because it's an nRF52833, with about 278kB of available firmware space for CircuitPython. There is more room for some features, such as asyncio. Try improving the functionality.
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...
Closing — changes will be submitted from the maintainer's fork instead.
Merge latest changes from 10.1.x into main, in preparation for 10.2.0. Also update frozen libraries, including updates for asyncio from the MicroPython v1.27 merge.
Updates the adabot submodule from d047729 to 2665096 (13 commits behind main).
Notable changes included:
- adafruit/adabot#405 — Add
days_openfield to issues inlibraries.v2.jsonoutput - 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...
from time.monotonic_ns(): "Return the time of the monotonic clock, which cannot go backward, in nanoseconds. Not available on boards without long integer support. Only use it to compare against other values from time.monotonic() during a single code run." Should say from time.monotonic_ns()?
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...
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... |
I tried async with asyncio. I got OSError 28 while copying asyncio (out of storage)
@slender iron if you can review https://github.com/adafruit/circuitpython/pull/10945, then that is the last thing for 10.2.0-rc.0.
@tulip sleet want to bug bash tomorrow or friday morning?
sure, either is fine. You can let me know when you're free.
i have no work-time interruptions scheduled
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
wherever is convenient for you, probably depends on the wifi, noise, etc.
👍 I can do friday morning otherwise
which will be close to lunch for me 🙂
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...
I think there is only about 50kB of space on CIRCUITPY, due to the limited flash size and the lack of an external flash chip on the microbit:v2.
@mikeysklar
The
.. important::note inSDCard.__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.
[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/...
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.
@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 ...
It's fine to rewrite this again to clarify.
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).
@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...
[adafruit/circuitpython-org] Pull request opened: #1759 update GitHub CI action versions for Node.24
Updated actions/checkout, actions/setup-python for Node.24.
Also updated peter-evans/create-pull-request from @v4 to @v8. This is a big jump. Let's see if it works.
No code changes required to enable it. I tested successfully on feather rp2040. New native_sim test validates the behavior.
@tulip sleet done with the car and back to my desk if you want to peer claude some issues
we could go over them and maybe mark some for possible LLM resolution. I did just start to look at them.
Running into the same issue with version 10.1.4 on multiple M5 Stack AtomS3U usb sticks.
Summary
- The docstring for
time.monotonic_ns()said to compare against other values fromtime.monotonic(), but those two functions return different units (seconds vs. nanoseconds). Fixed it to referencetime.monotonic_ns()instead.
Fixes #10946
Test plan
- [x] Docstring-only change; no behavior impact.
@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...
With
"Adafruit CircuitPython 10.2.0-rc.0 on 2026-04-16; stm32f411ce-blackpill-with-flash with STM32F411CE
Board ID:stm32f411ce_blackpill_with_flash
UID:210037000451353031363535"
it works perfectly again.
Here is the board information:
CircuitPython Release : 10.2.0
CircuitPython Version : 10.2.0-rc.0 on 2026-04-16
Board ID : st...
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...
@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....
I think this test should be in tests/. It is not port-specific, and does not need to be tested under zephyr.
Seems to have not resolved the issue according to https://github.com/adafruit/circuitpython/issues/10054#issuecomment-4262771676
Added a native_sim test to validate the decoding.
Also updated the jpegio docstrings example to contain the remaining steps to show the jpeg on a display.
@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
I'm ok having them both places because the native sim tests will be able to mimic an actual test on hardware too.
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.
the harness is different because the native sim one builds an external flash image to run on instead of doing raw repl
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?
I would say we have redundant tests now, e.g.: https://github.com/adafruit/circuitpython/pull/10939/changes#diff-ddf15076623abb977b33b242b0048124a8eeaa41973f5d07b3c35f5e62aec315 and tests/extmod/hashlib*.py
yes, they are testing the same thing in a different way
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
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.
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
I'm assuming I'd generally go around the uf2 bootloader
i don't think you have to, or it's difficult (atmel-samd in particular). RP2 could use picotool
I'm planning to start with ESP anyway
and many of the zephyr dev kits have built in debuggers
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?
if you power-cycle the board when 10.2.0-rc.0 is loaded does it help?
it should not be necessary to reload an old version. There is no state that is kept.
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.
Thanks. Looks good and it seems to be passing the checks when you submitted this.
And I have to admit I've never been very good at the timing to set safe mode which might help now.
Since it's the same code as #10054, only worse, go ahead and add another comment there. We may not consider this a blocker to the release, since you can roll back. In "normal" use it might be ok. If you have a simpler example to run that would be interesting to try
since your current test case is highly unusual
(doesn't mean it's wrong, just unusual 🙂 )
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.
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
...
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...
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...
@FoamyGuy The raw logs show a flash overflow, but the regular log does not, which is weird.
Raw logs:
https://productionresultssa15.blob.core.windows.net/actions-results/86f7c0d3-3cc5-4099-b92d-588dee8c10d5/workflow-job-run-3fd48b21-331f-5635-9318-2e85f1a54eaf/logs/job/job-logs.txt?rsct=text%2Fplain&se=2026-04-17T15%3A04%3A47Z&sig=%2BFoRUWattfgSeOQokQlhh20MKWwnNM2aDI8QmgOq2%2Fs%3D&ske=2026-04-17T16%3A49%3A12Z&skoid=ca7593d4-ee42-46cd-af88-8b886a2f84eb&sks=b&skt=2026-04-17T12%3A49%3A12Z&skti...
Why do you want to do this? IIRC I didn't implement deinit because TinyUSB didn't have a way to stop host functionality.
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...
Ahh, thank you, I disabled jpegio for nordic_nrf54h20dk in latest commits.
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 boardis 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.
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...
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...
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_I2Cand_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__.cor 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!
what is the microcontroller you're using?
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.
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.
I don't see that you can do UART on GP21 and GP20, based on what can be assigned to those pins.
<>
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
rp2040 datasheet and my code disagree 🙂
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 😕
awesome, that's probably it, i'll give it a try. not sure how many hours i would have searched before finding that.
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
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!
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.
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.
you're very welcome - making computers easier to use is very gratifying, and making physical computing easier to use is part of that
This issue appears to still be happening with CP 10.1.4.
I'm kind of surprised this issue is still open 3.5 years after it was raised.
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...
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...
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 ...
I tried 10.2.0-rc.0 again with another card, and I was able to reproduce the problem, fortunately. #10956 should fix it. If you have time to test the build from there I would be grateful. It's exactly what you did, but just want to make sure it works for you.
@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)
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...
M5Stack has a new microcontroller called the StickS3, but it does not support CircuitPython yet. It would be nice if it could. There is documentation for it here
[adafruit/circuitpython] Pull request opened: #10959 Added board ESP32-S3 N16R8 Wroom with espcamera
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-...
Great, thanks! I will test this on Monday.
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.
I have tested with the build artifact and it also works for my setup. Thanks again!
Tested by me and @bablokb. It fixes the problem.
Reopening so it will be closed when the fix is merged.
When someone has a moment this screenshot tool PR could use a review. It's in circuitpython org so I can't request from the librarians team. https://github.com/circuitpython/CircuitPython_Library_Screenshot_Maker/pull/36
<@&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!
Google Docs
CircuitPython Weekly Meeting for April 20, 2026 Welcome to the CircuitPython Weekly meeting notes! Feel free to add your Hug Reports and Status Updates before the meeting, alphabetically by your username. During the meeting, we go through them in order. If you can’t make the meeting and would st...
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...
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
thanks! 👋
Thanks for hosting Liz, have a great week everyone 👋
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
Google Docs
CircuitPython Weekly Meeting for April 27, 2026 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 a...
Please post a picture of this board. I'm a little wary that it is an official espressif board.
If it is, please use a USB PID from here: https://github.com/espressif/usb-pids/blob/main/allocated-pids-espressif-devboards.txt
Us Adafruit-funded folks don't typically add third-party boards. So, please create a board definition for it, test it and make a PR. We'd be happy to merge it in. Instructions are here: https://learn.adafruit.com/how-to-add-a-new-board-to-circuitpython/
Moved! Please take another look
@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?
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.
do you see this in 10.1.4 also?
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.
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.
@tulip sleet sounds good to me
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.
I am going to hold off a bit merging this until 10.2.0 release is resolved.
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.
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
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.
it seems to be critical that CIRCUITPY_WEB_API_PASSWORD="whatever" is present. When It's commented out, I don't see new behavior in 10.2.0.rc0.
import microcontroller
import time
time.sleep(5)
print("resetting in 5 seconds")
time.sleep(5)
microcontroller.reset()
<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...
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.
The Feather RPP2350 is broken out by pins also.
Settings.toml or custom "No USB Host" Build both satisfy the issue. I agree that deinit would not be a good solution.
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...
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...
@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.
I do not have a boot.py at all.
Ok, well I wish I could reproduce your behavior. Do you have four lines in your settings.toml?
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
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 🙂
@dhalbert I found that a QtPy ESP32-S3 N4R2 doesn't need the boot.py I need with my TinyS2 to trigger the error. With the QtPY S3 I get your exact behavior, Dan. Yay!
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.
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...
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...
If you're planning to make a new PR soon with better doc, just go ahead so we don't have two merge builds.
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 onsdcardio.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...
Closing per @dhalbert's suggestion — folded the revert and the rewrite into #10962 so we don't run two merge builds.
If this slight clarification is fine with you, you or I can just apply the suggestion, and then I'll approve and merge.
Thanks for the clarification and rewrite.
the SPI bus can be corrupted
Maybe this is nitpicking, but is this really true? I don't think the SPI bus cares about the data. I think the core problem is that a floating CS might fool a peripheral into thinking that data on the bus is for itself, thus corrupting the device state because most probably it receives wrong commands.
Thank you! Sorry I missed this.
Thank you for the picture! That board isn't designed by Espressif so please change the manufacturer. You can request a PID from Espressif for it still though and then we'll merge it. I just want it to be clear who made, and (theoretically) supports the board.
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:
- 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...
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?
Tested locally and it is behaving as expected. Actually, a bit better because new boards are now at the end of the list.
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... |
Adds Blinka board pages for boards added to Adafruit_Blinka since PR #1006 (Jetson Thor, Sept 2025).
New boards:
| Board | Blinka Release | date_added |
|---|---|---|
| LuckyFox Pico Ultra | 8.68.0 | 2025-11-20 |
| Banana Pi BPI-P2 Pro | 8.69.0 | 2025-12-31 |
| Orange Pi 5 Ultra | 8.70.0 | 2026-03-02 |
| Raspberry Pi Pico W | 8.70.0 | 2026-03-02 |
| Raspberry Pi Pico 2 | 8.70.0 | 2026-03-02 |
| Raspberry Pi Pico 2 W | 8.70.0 | 2026-03-02 |
| ... |
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 | ❌... |
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...
Follow-up to #1765. Adds board_usage to the 6 boards that were added in #1763:
- Linux: banana_pi_bpi_p2_pro, luckyfox_pico_ultra, orange_pi_5_ultra
- MicroPython: raspberry_pi_pico2, raspberry_pi_pico2_w, raspberry_pi_pico_w
Also makes board_usage a required field in check-boards.py validation. All Blinka boards now have board_usage set.
Follow-up to #1765. Adds board_usage to the 6 boards added in #1763:
- Linux: banana_pi_bpi_p2_pro, luckyfox_pico_ultra, orange_pi_5_ultra
- MicroPython: raspberry_pi_pico2, raspberry_pi_pico2_w, raspberry_pi_pico_w
Also makes board_usage a required field in check-boards.py validation. All Blinka boards now have board_usage set.
The Raspberry Pi Pico boards support both MicroPython and U2IF (Attached) usage modes. This adds Attached to their board_usage field:
- raspberry_pi_pico
- raspberry_pi_pico_w
- raspberry_pi_pico2
- raspberry_pi_pico2_w
All four now have:
board_usage:
- MicroPython
- Attached
Ok, most of this is done. PRs #1765, #1767, and #1768 added a data field reflecting their usage. Additionally, a learn guide page goes into more detail: https://learn.adafruit.com/adding-a-single-board-computer-to-blinka/types-of-boards.
- 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 checkingcb->prevforNULL, for reasons that I don't believe made sense.- The web workflow background callback was being zero'd out in
supervisor/shared/workflow.cbefore it was added as a background callback. This meant that if it...
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-linkclasses). Links point to/blinka?features=...to filter the Blinka listing page. - Board Usage section: Maps each
board_usagefront matter value to a descriptive label with a link to t...
Ok, with #1769, this is now complete.
Tests might be a little late for me sent DM with more info
Making some changes pointed out by an LLM code review, so draft for now.
No RAM cost for RP2350 boards or non-SD RP2040 boards.
In py/circuitpy_mpconfig.mk you have: CIRCUITPY_SDCARDIO ?= $(CIRCUITPY_FULL_BUILD), so this will by default turn on CIRCUITPY_SDCARDIO unless it was explicitly disabled. And currently I see no RPxxxx board explicitly disabling this.
automount_sd_card() is protected in supervisor/shared/usb/usb_msc_flash.c: it is only called if there is a LUN for the SD-card. Which can be disabled by CIRCUITPY_SDCARD_USB.
So I suggest that you also test CIRCUITPY_SDCARD_USB in your #ifdef
Four out of four boards I tested that failed under rc0 succeeded under 10966. I only found the earlier artifacts on 31aab5f I wasn't able to find artifacts for the LLM changes you made later as ed14186.
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.
@grgrant For some reason my second push did not force a rebuild, so there were no artifacts! I pushed a comment-only commit and was able to get all the jobs to re-run. Here are the new artifacts: https://github.com/adafruit/circuitpython/actions/runs/24775236913?pr=10966
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...
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...
All four boards I tested passed using the latest artifacts -- no bug seen.
Feather ESP32-S3 N4R2
ESP32-S2 TFT
QtPy N4R2
Unexpected Maker TinyS2
@grgrant thank you for the quick testing!
You don't need to determine the manufacturer. You could commit it as unknown. I just don't want it incorrectly attributed to a manufacturer.
You may be able to get a PID from Espressif or pid.codes (I need to do a review pass).
I pinged @hathach internally to look at the root cause. I'd rather fix the root issue than use 15k more RAM.
Thank you! I'll be happy to move to a proper RTOS.
@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?
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
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
Discussion here: a new board may not be needed: #help-with-circuitpython message
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
Automated website update for release 10.2.0 by Blinka.
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.
🎯 Root cause found. Thanks @dhalbert for the #6555 pointer.
Reading hathach's 2022 description of #6555:
response to
SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVALas 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...
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
sounds good to me
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_initso 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...
If you mount it in code.py (not boot.py), it should show up. The mount in boot.py only lasts while boot.py is running, because the SDCard object's lifetime is limited to the VM used for boot.py.
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.pyis a no-op;code.pydoes thesdcardio.SDCard+storage.mountand thenwhile 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....
Hi! help me with this. This PR fixes the board filename by removing the unintended space between v2 and pico.
cytron_edu_v2 _pico_2w.md to cytron_edu_v2_pico_2w.md
I have another question: why is my board not included in Thonny’s CircuitPython installation options? The board is already listed on CircuitPython.org (cytron_edu_v2_pico_2w).
Enabled core modules storage and gifio in the zephyr port and added native sim tests for both.
gifio and jpegio moved to depend on displayio instead of being in the DEFAULT_MODULES list.
Enabling storage resolves the issue mentioned in #10960 about needing flash nuke UF2. I tested storage.erase_filesystem() on a feather rp2040 successfully.
Thanks for the fix!
I'm not sure how the list of devices inside Thonny is generated, sorry.
You're right, thanks — simplifying to apply the unsupported reply to all LUNs.
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...
It would be good to test on Windows as well, and also on boards that are not RP2xxx, such as a PyPortal, and a Metro ESP32-S3 (onboard SD socket), etc. I'm assuming you don't have a Windows box or you would have done so. I could test some of these on Windows.
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).
I don't think that reporting
/savesas removable is a good idea.
I agree with this.
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...
I'm sorry to say this bug (Watch Dog Reset causing Web Workflow unreachable) is still present with 10.2.0. Tested on 3 ESP32-Sx boards all with bug.
For anyone running into this there is a workaround above: https://github.com/adafruit/circuitpython/issues/10054#issuecomment-4231892771
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?
- Has the actual root cause problem been definitely identified?
- Has a verified fix been created?
- In what version of CircuitPython will the fix be included?
- Is that version of CircuitPython able to be downloaded now?
Thanks for any information!
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.
@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
It is changed with idf6 too. I don't want us to use the mp copy. I'd prefer to toolchain one or the ROM one.
do you know which implementation you are using?
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
do you have a backtrace? it can tell where it is
I have considerable detail on that
I think there might be a wrapper for the idf
maybe mbedtls isn't being built with it
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
I'm at home and ari is watching cars. (he's home sick)
ah ok 🙂
I'm on my laptop
in the above aa is the dest and bb is the source (yes, those are really the variable names 🙂
it might be worth trying my idf6 branch because it switches to picolibc
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
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...
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.
@Sporking this is not yet fixed. Someone who might be able to fix it is ordering hardware for testing.
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...
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...
@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...
@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... |
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.
@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.
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
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
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
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.
Nice, I've been using Dash to Panel for a while. I like its behavior compared to the stock ubunty system bar thing.
now they put the menus on the window's title bar
I do agree the name is very generic though. I wouldn't remember it if not for being bookmarked in my setup notes file.
I just made a new Gnome extension called "Race To Conference" that does that same thing but is even more confusingly named
Sorry, missed the i386 part before. The easiest test is installing the things needed to build the native sim. The container file here has the requirements: https://github.com/adafruit/circuitpython/blob/ca4636c285f86a09c98f10d03bc7cf11b0aa1efa/ports/zephyr-cp/native_sim_build_Containerfile#L5-L12 I'm not certain of the entire culprit but I believe the i386 SDL one at least was involved.
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.
The libsdl2 packages are also installed on 26.04, so I think the problem is going to be the same. I wonder why the native sim needs the i386 packages in the first place.
I think it has to do with the displayio tests. It simulates a display that can output screenshots like these: https://github.com/adafruit/circuitpython/tree/main/ports/zephyr-cp/tests/zephyr_display/golden.
I think maybe you can run it in a standalone window too but not certain.
I think the package manager should let you install both versions. I've done this before for other reasons, years ago. one search result (there are many): https://www.reddit.com/r/debian/comments/9e73h2/both_amd64_and_i386_version_of_the_same_package/
gotta be out for a while, but I'll look more
I did sudo dpkg --add-architecture i386 and then did sudo apt install --dry-run gcc-multilib g++-multilib libc6-dev-i386 libsdl2-dev:i386 libsdl2-image-dev:i386 to see if it would want to uninstall anything, and it did not.
was it west that did the installs, or did you basically what the container does on your own machine?
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.
I did basically https://github.com/adafruit/circuitpython/blob/ca4636c285f86a09c98f10d03bc7cf11b0aa1efa/ports/zephyr-cp/native_sim_build_Containerfile#L5-L12, carefully, and not reinstalling some things that were already there (just so they would not be marked as manually installed). Nothing was removed.
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.
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?
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.
The special build works great! If it's ok, a settings.toml version would be fabulous. I'll hhelp with documentation if you like.
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
make BOARD=native_native_sim
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...
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
i386 is needed because native_sim is built 32bit by default
so the code behaves more closely to the code on a 32bit micro
<@&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!
Google Docs
CircuitPython Weekly Meeting for April 27, 2026 Welcome to the CircuitPython Weekly meeting notes! Feel free to add your Hug Reports and Status Updates before the meeting, alphabetically by your username. During the meeting, we go through them in order. If you can’t make the meeting and would st...
@tulip sleet want to video about this memcpy bug?
I am on a new track, might have a fix
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?
@mikeysklar I feel like you are slopping me. (aka just copying and pasting from an LLM) Please use a Beagle or other USB sniffer to prove the behavior from the host OS and that disabling the removable change is the only way to fix it. I don't trust your benchmark numbers because they appear to be from an LLM and your benchmarking setup isn't clear to me.
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.
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!
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.
We're on pre-4.4.0 main
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
as you can see above, I did get it to work, after installing the adm64 versions of libsdl2. so it needs those to build, but it needs the i386 versions to run, i guess
good! that's weird
multilib support is probably bitrotting in general
since we're well past the core CPU to 64bit transition
A combination of python and circuitpython scripts to transfer mouse and keyboard of your computer to another computer. Raspberry Pi Pico is used as USB HID Mouse/Keyboard.
You can refer the detailed project description here :
https://www.hackster.io/RVLAD/jumping-jerboa-transfer-mouse-keyboard-to-other-computer-68a134
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
Google Docs
CircuitPython Weekly Meeting for May 4th, 2026 Welcome to the CircuitPython Weekly meeting notes! Feel free to add your Hug Reports and Status Updates before the meeting, alphabetically by your username. During the meeting, we go through them in order. If you can’t make the meeting and would st...
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...
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.
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...
@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).
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...
I don't think openclaw included it, but this was on a CLUE board running CP 10.2.0.
[adafruit/circuitpython] New comment on pull request #10973: Translations update from Hosted Weblate
@andibing Just to confirm, is "dma" typically lower case in British English?
Thanks - will merge for 10.3.0 alpha.
Closing for now due to no response. Fine to reopen if you continue on this.
I think I addressed this as part of #10887. Thanks for bringing it up.
Closing for now. We can certainly reopen on request.
I'm going to close this for now, since it's so old and appears stalled. We can always reopen. @FoamyGuy is working on I2Sin, but not bidirectional, if I understand correclty.
@ericbaril72 Are you still interested in working on this? Thanks.
Never mind, I read the change backwards from what it actually does. Thanks!
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
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...
Thank you! working on raspberrypi next this will be a great reference.
audiocore support would be awesome. Agree I2SIn should be able to support it eventually as well.
Automated website update for release 10.3.0-alpha.1 by Blinka.
Images automagically compressed by Calibre's image-actions ✨
Compression reduced images by 31.5%, saving 2.1 MB.
| Filename | Before | After | Improvement |
|---|---|---|---|
| assets/images/boards/original/nodemcu.jpg | 2.7 MB | 1.8 MB | 34.0% |
| assets/images/boards/original/weact_studio_rp2350b_core.jpg | 1.1 MB | 790.5 KB | 31.4% |
| assets/images/boards/original/cp32-m4.jpg | 56... |
https://blog.adafruit.com/2026/04/30/circuitpython-10-3-0-alpha-1-released/
Highlights of this release:
- Improve SD card USB presentation on macOS.
- Prefer
foo.pyoverfoo/package when importing, like CPython. - Pin fixes.
- Enable
gifioandstoragein Zephyr port.
math.nan, math.inf, math.tau are in MicroPython as EXTRA_FEATURES but are not in our shared-bindings/math.
tau is just 2*math.pi.
This is more complicated than I realized. #354 copied py/modmath.c into shared-bindings and added documentation. But all the improvements to math from upstream since then have not been incorporated.
I think we should undo #354 and figure out how to point to the existing math documentation. In the process let's also turn on the MICROPY_PY_MATH_CONSTANTS.
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...
<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 ...
Summary
- First
audioio.AudioOutfor the STM32 port. STM32F4 boards (Feather STM32F405 Express, etc.) previously had noaudioiosupport. - 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 viaPA05/A1 (DAC2), with both DAC channels triggered off the same timer so L/R stay sample-aligned. - Cooperates with the existing
analogio.AnalogOuton this p...
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! 🙏
A precompiled firmware file is in the releases folder , incase someone wants to try
<@&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.
Google Docs
CircuitPython Weekly Meeting for May 4th, 2026 Welcome to the CircuitPython Weekly meeting notes! Feel free to add your Hug Reports and Status Updates before the meeting, alphabetically by your username. During the meeting, we go through them in order. If you can’t make the meeting and would st...
Neat! I've always assumed we'd match an API that is available in CPython. What sort of functionality can you get out of these models?
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() ...
Here is a first pass. Thanks for looking into this! I'd love to see Zephyr support for this too because I'd love to deprecate this STM port in favor of Zephyr. I know the Zephyr STM support is good.
This looks fine to me.
Would you mind adding Zephyr native_sim tests? It should be able to test this.
Do we all agree we should allow ejecting CIRCUITPY and SAVES? Dan pointed out the reason for the delay with an SD card.
Do we all agree we should allow ejecting CIRCUITPY and SAVES? Dan pointed out the reason for the delay with an SD card.
I didn't realize this would prevent host-side ejects. It seems OK with me to have that, for flush reasons an device removal reasons.
am going to add a settings.toml to allow turning off the SD card USB auto-presentation.
Yes, I agree with the allow for ejecting CIRCUITPY and SAVES as the default and Dan's settings.toml opt-out.
I'd like grab the pcap for Ubuntu / Windows just to see how those host OS interactions work. I can post those shortly.
Would you mind adding Zephyr native_sim tests? It should be able to test this.
I will add this in another PR, but definitely will do it.
https://www.techzine.eu/news/security/140826/malicious-python-package-poses-new-supply-chain-threat/
risc-v ROM
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-cpdoesn't currently list any STM32F4 board, so there's no hardware-tested path to validate against. Several foundatio...
Thanks folks, have a great week everyone 👋
you too!
Thanks @lone axle for hosting!
I would prefer a compile time opt-out (in addition?!). I don't want my users to tinker with their settings.toml and change the behavior.
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
Google Docs
CircuitPython Weekly Meeting for May 11th, 2026 Welcome to the CircuitPython Weekly meeting notes! Feel free to add your Hug Reports and Status Updates before the meeting, alphabetically by your username. During the meeting, we go through them in order. If you can’t make the meeting and would st...
I would prefer a compile time opt-out (in addition?!). I don't want my users to tinker with their settings.toml and change the behavior.
CIRCUITPY_SDCARD_USB already exists and controls whether SD cards are presented as USB. It is a .h option, so control it in mpconfigport.h or mpconfiboard.h; there is not a corresponding .mk option (though there could be).
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) |...
CIRCUITPY_SDCARD_USBalready exists and controls whether SD cards are presented as USB. It is a.hoption, so control it inmpconfigport.hormpconfiboard.h; there is not a corresponding.mkoption (though there could be).
I am already using this to prevent SD-card presentation. But the code in the current PR does not use this define. So it does not help.
Hi Scott,
I'm not on board with this approach. Without interrupts, what is there to call the callback?
I can't implement something I don't understand.
@bablokb - I can update the PR to include the check.
@dhalbert It is not clear to me if you will be introducing any flags that I should be considering here as well.
#if CIRCUITPY_SDCARD_USB
tud_msc_set_sense(lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00);
return false;
@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...
@bablokb Could you test the current state of this PR with what you are doing?
Yes, tomorrow
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...
Totally fine to get this in before moving STM Zephyr. You can test with this zephyr board def: https://docs.zephyrproject.org/latest/boards/adafruit/feather_stm32f405/doc/index.html if you want to try it in a follow up.
@modern sundial want to chat about async when you have a chance?
Interrupts are used internally to set the completion flag. That will then unblock the asyncio task.
This week is pretty crazy for me, but I at least wanted to tell you I didn’t understand and don’t know how to proceed
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
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.
@DaveXanatos We have not seen this problem with I2C, and the specific problem is related to SPIM3 in particular.
Ask with details, like your code and your board, on https://forums.adafruit.com/viewforum.php?f=60 or https://adafru.it/discord .
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
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...
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 ...
One more small thing. I've poked the CI too.
What sort of frequency do you want to do this in? Both micropython and circuitpython could end up doing a garbage collection when running Python code to do it.
It feels like it might be better served by a native module for that specific purpose.
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...
I just saw your feedback on this.
I have not played with this platform for a while now, and never used the "filters" so some functionnality
might not get tested.
I just created a new board ID pull-request.
Hopefully, it'll work on the first build and flash
@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...
@bablokb Thanks for your detailed testing. It should not crash, so we need to investigate that. Since this PR does not affect things for the worse, we can merge it.
What is the OS that your host computer is using?
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-...
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...
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...
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...
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.
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...
Successfully tested on Raspberry Pi Pico with PCM5102 I2S DAC.
This issue is now fixed within #10906! 🥳 Just waiting for CI and review.
Did you test this on the SAMD? I see you did it on the Pico. I don't have my h/w around to test at the moment but trust your tests.
Code looks good, good catch that was hidden!
Once I see the CI pass and confirm the SAMD test I can approve.
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...
Did you test this on the SAMD? I see you did it on the Pico. I don't have my h/w around to test at the moment but trust your tests.
Yes, I tested on a Metro M4 Express as well as the aforementioned Pico. The details of my testing on the M4 are described here: https://github.com/adafruit/circuitpython/issues/10867#issuecomment-4392288890.
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.
thanks, good to know. i now see the file listing in the boot code. will rework
sorry, self induced, was trying to do fs ops in both boot and code, consolidating in code resolved the issue
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...
Looks good, great catch. I knew I should have only said I was 99% sure.
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?
Thank you @relic-se, and thanks @gamblor21 for testing!
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.
@tannewt You mind re-running CI?
Opened to review performance issues related to exposing microSD cards through the mass storage controller. Related to a PR #10967 that was added to enable macOS support and marked all LUNs as removable.
@bablokb @dhalbert @tannewt
@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...
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...
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).
That is what I basically did. As a baseline, I also used 9.2.9.
Note that we already have a similar issue #10733. The title of that issue is now misleading.
@bablokb: @mikeysklar and I were thinking of closing this in favor of #10983. If there are some nuggets of interest here, they could be summarized and transferred over.
Support pin IO41 (aka ANTENNA_SWITCH), which allows a user to switch from the built-in antenna to the uFL antenna. This pin is only on the "D" series of Unexpected Maker S3 series of boards.
https://unexpectedmaker.com/shop.html#!/FeatherS3-D/p/759221736
I am trying to match your testing framekwork. You have shown that PR #10967 does not have a significant effect on performance.
I'd like to show that there are best practices for optimization and pitfalls to avoid. It might be clearer if just run a round of benchmarks and post up a short summary.
It's not clear how one might differentiate among "D" and non-"D" series at build time, or if there is value in doing so.
While I have one of these devices (and a uFL antenna), it's not clear how I might comprehensively test this.
We don't have a way to sync two things really and I'm not sure how you'd express that in Python. I'd love to get us towards asyncio but it doesn't really have that concept either.
[adafruit/circuitpython] Pull request review submitted: #10984 Support pin IO41 (aka ANTENNA_SWITCH)
This is fine with me. I'm ok having it on the non-D version.
I had tried an earlier version of this on ESP32-C6 and saw the web workflow webserver working properly. I did that to test memcpy().
As another test, I ran the weather demo on a MagTag, which does WiFi and display operations and a lot of other stuff. It's working fine.
I'll merge this now to get it out for further testing.
I am not ignoring this but would want to try it with some more conventional BLE devices as well.
Here are the results.
Board: Metro RP2040, firmware todays main @ 13a8fb9f7b
| Firmware | SD format | Host OS | Slow-window (s) | Peak cpu (ms) |
|---|---|---|---|---|
| usb-on | FAT32 | macOS | ~17 | 492 |
| usb-on | FAT32 | Linux | ~8.4 | 492 |
| usb-on | FAT32 | Windows | never settled | 465 |
| usb-on | FAT16 | macOS | ~0.6 | 335 |
| ... |
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...
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...
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...
A new SSD1680 panel variant (FPC-7519rev.b, User ID first byte 0xca) is
shipping in current MagTag 2.9 units and requires colstart=8, the same
as FPC-7619rev.b. Adds one case to the detection switch in board.c.
No regression on my Mid-2025 Magtag
Thank you for testing and the confirmation that I didn't break an earlier version.
@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...
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
0xCAand selectcolstart=8.
💡 Add C...
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...
@lzrd Thanks! We're merging this in to main for now, and it should be in 10.3.0-alpha.2, which will be released soon. If you could test the artifacts here or test the alpha, that would be great. We updated to ESP-IDF v6.0.1, so it would be good to retest.
One file to revert. The other changes look good.
I missed that this was against 10.1.x. I'll do a merge from 10.1.x to main.
@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.
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...
@slender iron I think there are no such chips right now
This adapts #10899, which was against 10.1.x, to main.
Since #10899, there was conditional compilation code added for Espressif chips without RTC memory. (I don't see that there actually are any such chips.) This PR merges #10899, and incorporates that new #if check.
FYI @lzrd
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...
Yes, that is the slowdown I would expect to see with FAT32. Would you mind running the same test to confirm the 1.5s or less delay with FAT16?
Also tested on QtPY ESP32-S3 NOPSRAM with same crash importing wifi.
@tulip sleet sorry for not getting back. At a kids doctor checkup this morning
np - i should have just put the q in the PR
@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.
Hm, how would I do that? The filesystem is not visible to the host until I mount it and then it is readonly.
Looks like C2 and C61 don't have it. H4 is commented out
i missed those - thanks
If it's going to be an open issue, yes. You can mention it in the closed PR to provide a cross-ref, and give more details in the new issue.
An open issue is a trackable thing that must be closed. Something mentioned in a closed PR or issue might get lost
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 ...
Closing to rebase on current upstream main — fork was out of sync with #10987.
FPC-7519rev.b (User ID `0xca`) shows a dark gray background with the default VCOM=`0x28`. Setting VCOM=`0x20` gives a light gray background with solid black text.
Surgical fix: adds a dedicated `ssd1680_vcom20_display_start_sequence` and `DISPLAY_SSD1680_COLSTART_8_VCOM20` type routed to `case 0xca:` only. The 0x44 and 0x00 panels are untouched.
Image for testing on new MagTag 7519rev.b with this patch.
We don't use the
VARIANT=standardbuild; we only useVARIANT=coverage, so that we can run tests. So we haven't tried to maintain thestandardvariant at all, and never build it. (In fact just plainmakeinports/unixdefaults tocoverage.)There are a number of other things missing from the
unixport, likesupervisor, that make it not a very good CircuitPython port for actual use. What is your use case for building thestandardvariant?
Goal was just to test python c...
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...
Sure, no problem, it's not obvious!
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...
Aha, so you have a board with a "7619" ribbon cable. I have not seen one of these in person or in photos.
I only have two MagTags.
Both SSD1680 based:
- FPC-A005
- FPC-7519rev.b
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.
Regardless of ribbon label there are 0x44 and 0xca variants. Both require the coloffset=8 and have some blur / contrast needs.
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="...
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. 😡
that's as detailed as it gets. I'd say use a venv and use gmake. That should be closest to the Linux way.
But consider use a Linux VM or a Linux dev machine if you want to save some effort.
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
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.