Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ports/zephyr-cp/boards/board_aliases.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,4 @@ cp_board_alias(raspberrypi_rpi_pico_w_zephyr rpi_pico/rp2040/w)
cp_board_alias(raspberrypi_rpi_pico2_zephyr rpi_pico2/rp2350a/m33)
cp_board_alias(raspberrypi_rpi_pico2_w_zephyr rpi_pico2/rp2350a/m33/w)
cp_board_alias(st_nucleo_n657x0_q nucleo_n657x0_q/stm32n657xx)
cp_board_alias(silabs_siwx917_dk2605a siwx917_dk2605a)
123 changes: 123 additions & 0 deletions ports/zephyr-cp/boards/silabs/siwx917_dk2605a/autogen_board_info.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
# This file is autogenerated when a board is built. Do not edit. Do commit it to git. Other scripts use its info.
name = "Dev Kits and Thunderboards SiWx917 Wi-Fi 6 and Bluetooth LE SoC Dev Kit (BRD2605A)"

[modules]
__future__ = true
_bleio = true # Zephyr board has _bleio
_eve = false
_pew = false
_pixelmap = false
_stage = false
adafruit_bus_device = true
adafruit_pixelbuf = false
aesio = true
alarm = false
analogbufio = false
analogio = false
atexit = false
audiobusio = false
audiocore = false
audiodelays = false
audiofilewriter = false
audiofilters = false
audiofreeverb = false
audioi2sin = false
audioio = false
audiomixer = false
audiomp3 = false
audiopwmio = false
audiospeed = false
aurora_epaper = false
bitbangio = false
bitmapfilter = true # Zephyr board has busio
bitmaptools = true # Zephyr board has busio
bitops = false
board = false
busdisplay = true # Zephyr board has busio
busio = true # Zephyr board has busio
camera = false
canio = false
codeop = false
countio = false
digitalio = true
displayio = true # Zephyr board has busio
dotclockframebuffer = false
dualbank = false
epaperdisplay = true # Zephyr board has busio
floppyio = false
fontio = true # Zephyr board has busio
fourwire = true # Zephyr board has busio
framebufferio = true # Zephyr board has busio
frequencyio = false
getpass = true
gifio = true # Zephyr board has busio
gnss = false
hashlib = true # Zephyr networking enabled
hostnetwork = false
i2cdisplaybus = true # Zephyr board has busio
i2cioexpander = false
i2ctarget = false
imagecapture = false
ipaddress = true # Zephyr networking enabled
is31fl3741 = false
jpegio = true # Zephyr board has busio
keypad = false
keypad_demux = false
locale = false
lvfontio = true # Zephyr board has busio
math = true
max3421e = false
mcp4822 = false
mdns = false
memorymap = false
memorymonitor = false
microcontroller = true
mipidsi = false
msgpack = true
neopixel_write = false
nvm = false
onewireio = false
os = true
paralleldisplaybus = false
ps2io = false
pulseio = false
pwmio = false
qrio = false
qspibus = false
rainbowio = true
random = true
rclcpy = false
rgbmatrix = false
rotaryio = true # Zephyr board has rotaryio
rtc = false
sdcardio = true # Zephyr board has busio
sdioio = false
sharpdisplay = true # Zephyr board has busio
socketpool = true # Zephyr networking enabled
spitarget = false
ssl = true # Zephyr networking enabled
storage = true
struct = true
supervisor = true
synthio = false
terminalio = true # Zephyr board has busio
tilepalettemapper = true # Zephyr board has busio
time = true
touchio = false
traceback = true
uheap = false
usb = false
usb_audio = false
usb_cdc = false
usb_hid = false
usb_host = false
usb_midi = false
usb_video = false
ustack = false
vectorio = true # Zephyr board has busio
warnings = true
watchdog = false
wifi = true # Zephyr board has wifi
zephyr_display = false
zephyr_kernel = false
zlib = true
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
CIRCUITPY_BUILD_EXTENSIONS = ["elf", "hex"]
CIRCUITPY_ULAB = true
81 changes: 81 additions & 0 deletions ports/zephyr-cp/boards/siwx917_dk2605a.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# The upstream board defconfig does not enable GPIO, so no gpio device structs
# are instantiated and CircuitPython's generated board.c fails to link with
# "undefined reference to __device_dts_ord_NN" for every pin.
CONFIG_GPIO=y

# The siwx91x SoC family Kconfig (zephyr/soc/silabs/silabs_siwx91x/Kconfig)
# never selects BUILD_OUTPUT_HEX, unlike Silicon Labs' other SoC families
# (silabs_s0/s1/s2/sim3, which all select it). The port's Makefile
# unconditionally copies zephyr.hex to firmware.hex for release artifacts, so
# without this every release build fails with "cannot stat
# .../zephyr.hex: No such file or directory" even though the .elf/.rps
# linked and flashed fine.
CONFIG_BUILD_OUTPUT_HEX=y

# getaddrinfo() calls k_calloc(), which is compiled out when the kernel heap is
# zero-sized. prj.conf also enables CONFIG_DYNAMIC_THREAD_ALLOC, which draws
# thread stacks from this same heap.
CONFIG_HEAP_MEM_POOL_SIZE=16384

CONFIG_NETWORKING=y
CONFIG_NET_IPV4=y
CONFIG_NET_DHCPV4=y
CONFIG_NET_SOCKETS=y

# TCP is not enabled by any of the options above, and the siwx91x driver
# defaults to the native network stack. Wi-Fi association and DHCP still work
# because DHCP is UDP, so the board looks healthy while every SOCK_STREAM
# socket fails: the web workflow listener never opens and socketpool raises
# "Out of sockets" from Python.
CONFIG_NET_TCP=y

# Every Zephyr socket also takes a zvfs file descriptor, which defaults to 0.
CONFIG_ZVFS_OPEN_MAX=8

# Zephyr's console (printk, boot banner, driver logs) goes to SEGGER RTT over
# the existing SWD connection instead of sharing the UART with the REPL.
# CircuitPython's REPL is unaffected: supervisor/serial.c takes the device from
# DT_CHOSEN(zephyr_console) and drives it with busio directly, so it keeps
# ulpuart and the J-Link VCOM regardless of this Kconfig.
#
# Without this, every net event printk interleaves with the REPL and corrupts
# the raw REPL handshake that test tooling depends on.
CONFIG_USE_SEGGER_RTT=y
CONFIG_RTT_CONSOLE=y
CONFIG_UART_CONSOLE=n

CONFIG_WIFI=y
CONFIG_NET_L2_WIFI_MGMT=y
CONFIG_NET_MGMT_EVENT=y
CONFIG_NET_MGMT_EVENT_INFO=y

CONFIG_NET_HOSTNAME_ENABLE=y
CONFIG_NET_HOSTNAME_DYNAMIC=y
CONFIG_NET_HOSTNAME="circuitpython"

CONFIG_MBEDTLS=y
CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y
CONFIG_MBEDTLS_CIPHERSUITE_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256=y
CONFIG_MBEDTLS_ENTROPY_C=y
CONFIG_MBEDTLS_CTR_DRBG_C=y

CONFIG_BT=y
CONFIG_BT_PERIPHERAL=y
CONFIG_BT_CENTRAL=y
CONFIG_BT_BROADCASTER=y
CONFIG_BT_OBSERVER=y
CONFIG_BT_EXT_ADV=y

CONFIG_BT_DEVICE_APPEARANCE_DYNAMIC=y
CONFIG_BT_DEVICE_NAME_DYNAMIC=y
CONFIG_BT_DEVICE_NAME_MAX=28
CONFIG_BT_L2CAP_TX_MTU=253

# BT Buffers
CONFIG_BT_BUF_CMD_TX_SIZE=255
CONFIG_BT_BUF_EVT_RX_COUNT=16
CONFIG_BT_BUF_EVT_RX_SIZE=255
CONFIG_BT_BUF_ACL_TX_COUNT=8
CONFIG_BT_BUF_ACL_TX_SIZE=251
CONFIG_BT_BUF_ACL_RX_COUNT_EXTRA=1
CONFIG_BT_BUF_ACL_RX_SIZE=255
92 changes: 92 additions & 0 deletions ports/zephyr-cp/boards/siwx917_dk2605a.overlay
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// Replaces the port's app.overlay, which cannot be used here: it does
// `&zephyr_udc0 { ... }` to add the CDC-ACM console, and the SiWG917 has no USB
// device controller. The CircuitPython console falls back to the Zephyr console
// on &ulpuart, reaching the host over the on-board J-Link VCOM.

// CIRCUITPY filesystem.
//
// supervisor/flash.c looks for a partition node labeled `circuitpy_partition`
// (#define CIRCUITPY_PARTITION circuitpy_partition). Without it the port falls
// back to scanning for a flash device not covered by any partition, finds none
// on this board, prints "no flash found for filesystem" and boots into safe
// mode with "CIRCUITPY drive could not be found or created".
//
// The whole 8 MB is already partitioned by siwg917m111mgtba.dtsi, so there is
// no unallocated space to claim:
// 0x000000..0x011000 mbr_nwp (do not touch)
// 0x011000..0x1f0000 code_nwp - NWP firmware (do not touch)
// 0x1f0000..0x202000 mbr + hdr (do not touch)
// 0x202000..0x3f8000 code_partition - our M4 app
// 0x3f8000..0x400000 storage - only 32 KB, unusable as CIRCUITPY
// 0x400000..0x800000 ota_swap_partition
// 0x7cf000..0x800000 storage_nwp, storage_shared, backup_bootloader
//
// Placing CIRCUITPY in the upper region (0x400000..0x7cf000, inside ota_swap)
// opens and reads fine but every write fails:
//
// flash write failed: -5 (-EIO)
// address 0 length 512
//
// In common-flash mode the M4 cannot write flash itself; the driver calls
// sl_si91x_command_to_write_common_flash() to have the NWP do it, and the NWP
// refuses writes in the OTA-swap/NWP-owned upper area.
//
// So carve CIRCUITPY out of the M4's own code_partition instead, which is
// definitely writable - it is where our firmware is flashed. code_partition is
// shrunk from 2008K to 1M (the image currently uses ~703K, so there is room;
// if it ever overflows the build fails loudly at link time rather than
// silently corrupting the filesystem).
//
// 0x202000 + 1M code_partition -> ends 0x302000
// 0x302000 + 984K circuitpy -> ends 0x3f8000
// 0x3f8000 + 32K storage (unchanged)
// PSRAM is kept OUT of the CircuitPython heap until it is understood.
//
// The 8 MB PSRAM at 0xa000000 works as memory: sparse writes across a 64 KB
// buffer verify correctly and a 64 KB allocation succeeds. But using it as the
// Python heap corrupts objects under sustained allocation, and the failure is
// not about large buffers - a plain `for i in range(200000): s = s + i` with no
// buffer at all hangs the board. Symptoms are corrupted objects: an int that
// became a function, a bytearray with a wrong length, and an MPU fault calling
// a garbage pointer read from PSRAM:
//
// ***** MPU FAULT ***** Instruction Access Violation
// r0/a1: 0x0a0012c0 r12/ip: 0x0a0031ac <- PSRAM pointers
// PC: 0x410e29c8 <- called through r3, garbage
//
// Not a timing problem: identical at fast-freq 144 MHz and 33 MHz. Not the
// NWP-reserved/DMA pools either; excluding those (supervisor/port.c minimum
// region size) did not help.
//
// ROOT CAUSE FOUND 2026-08-01, and the node is enabled again.
//
// The SoC has a 16 KB data cache dedicated to PSRAM (family RM rev 1.2 section
// 5.4.5) at 0x44040000, on the QSPI2 path. The bootloader leaves it enabled and
// half-configured, and nothing in this build maintains it - see the long
// comment in supervisor/port.c, which disables it in port_heap_init() before
// any TLSF pool exists.
//
// Note what did NOT work, so it is not retried: setting ATTR_MPU_RAM_NOCACHE on
// this node changes nothing. That is an MPU attribute governing the Cortex-M
// architectural cache, and CPU_HAS_DCACHE is never selected, so there is
// nothing there for it to govern. The cache that matters is a separate
// peripheral and an MPU attribute does not reach it.
&psram {
status = "okay";
};

&flash0 {
partitions {
code_partition: partition@202000 {
compatible = "zephyr,mapped-partition";
reg = <0x00202000 0x00100000>;
label = "code_partition";
};

circuitpy_partition: partition@302000 {
compatible = "zephyr,mapped-partition";
reg = <0x00302000 0x000f6000>;
label = "circuitpy";
};
};
};
5 changes: 4 additions & 1 deletion ports/zephyr-cp/cptools/zephyr2cp.py
Original file line number Diff line number Diff line change
Expand Up @@ -677,7 +677,10 @@ def zephyr_dts_to_cp_board(board_id, portdir, builddir, zephyrbuilddir, mpconfig

if (ioport, num) not in board_names:
board_names[(ioport, num)] = []
board_names[(ioport, num)].append(props["label"].to_string())
# `label` is optional and deprecated on gpio-keys; modern boards
# identify keys with `zephyr,code` instead.
if "label" in props:
board_names[(ioport, num)].append(props["label"].to_string())
if key in node2alias:
if "sw0" in node2alias[key]:
board_names[(ioport, num)].append("BUTTON")
Expand Down
7 changes: 7 additions & 0 deletions tools/ci_changes_per_commit.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,13 @@ def get_commit_depth_and_check_suite(query_commits):
check_suites = commit["checkSuites"]
if check_suites["totalCount"] > 0:
for check_suite in check_suites["nodes"]:
# workflowRun is null for check suites that aren't
# attached to a workflow run (e.g. one that was
# deleted or belongs to an app integration), which
# crashed this loop with a TypeError on this fork's
# PR history.
if check_suite["workflowRun"] is None:
continue
if check_suite["workflowRun"]["workflow"]["name"] == "Build CI":
return [
{"sha": commit_sha, "depth": commit_depth},
Expand Down
Loading