Kwabena/network halow - #147
Draft
kwagyeman wants to merge 15 commits into
Draft
Conversation
Some drivers need to register a GPIO interrupt from C rather than through the machine.Pin.irq() Python method -- for example a network driver that wakes on a transceiver's IRQ line. Add mp_hal_pin_interrupt(), matching the stm32 and rp2 ports, plus mp_hal_pin_interrupt_enable() to mask and unmask an already-registered interrupt, which is useful for interrupt coalescing. The registered interrupt is given the lowest priority, as eth.c already does for the Ethernet IRQs: it only schedules work and must not preempt USB or DMA. Signed-off-by: Kwabena W. Agyeman <kwagyeman@live.com>
Some drivers need to register a GPIO interrupt from C rather than through the machine.Pin.irq() Python method. Factor the IRQ-object allocation out of machine_pin_irq() into a shared helper, then build mp_hal_pin_interrupt() and mp_hal_pin_interrupt_enable() on top of it. The latter masks and unmasks an already-registered interrupt, which is useful for interrupt coalescing. The registered interrupt is given the same low priority this port already uses for the cyw43 host-wake IRQ, since it only schedules work. Signed-off-by: Kwabena W. Agyeman <kwagyeman@live.com>
Add mp_hal_pin_interrupt_enable() to mask and unmask an already-registered pin interrupt, matching the mimxrt and alif ports. A driver can use it for interrupt coalescing: mask on the edge, unmask once the work is done. It wraps the port's existing extint_enable() / extint_disable(). Signed-off-by: Kwabena W. Agyeman <kwagyeman@live.com>
Carries morselib -- the vendor's prebuilt WLAN library -- and the transceiver firmware that the 802.11ah driver is built on. Pinned at release 2.12.3. morselib is distributed as a prebuilt archive under the Morse Micro Binary License; the rest of the SDK is Apache-2.0. Signed-off-by: Kwabena W. Agyeman <kwagyeman@live.com>
The portable core that the network.HALOW binding is built on, sitting between morselib and the MicroPython runtime: - a cooperative scheduler that runs morselib's tasks on their own stacks, pumped from the network poll; - an OSAL providing the RTOS primitives morselib expects -- tasks, mutexes, semaphores, queues and timers -- on top of that scheduler; - a HAL driving the transceiver over SPI, with an optional pin interrupt for low-latency receive; - packet memory and the lwIP interface, allocated from the MicroPython heap so the driver keeps no static pool of its own; - build rules that link the prebuilt morselib archive and the firmware blobs. Scheduler and allocator come with qemu and host unit tests. Signed-off-by: Kwabena W. Agyeman <kwagyeman@live.com>
The MicroPython network interface on top of the drivers/halow core: a station-mode network.HALOW class with connect/disconnect, scan, config and status accessors, and an ioctl passthrough for certification tooling, plus the SEC_/TWT_/DUTY_CYCLE_/PM_/STAT_ constants. The constants are fixed to literals and static-asserted against the morselib enums, so a future SDK renumbering fails the build here rather than silently changing what a user's stored value means. Signed-off-by: Kwabena W. Agyeman <kwagyeman@live.com>
Documents the network.HALOW 802.11ah station interface: its methods, the config and status parameters, the security/power/duty-cycle/TWT constants and the link states, with notes on the ways 802.11ah differs from 2.4GHz Wi-Fi -- no WPA2-PSK, a mandatory country/channel plan, and a transmit-only power-save mode. Signed-off-by: Kwabena W. Agyeman <kwagyeman@live.com>
Two hardware suites for the network.HALOW interface. network_halow.py needs only the transceiver: it checks the constants, active() cycling, config validation and out-of-range rejection, scan, and that use-after-deinit and config-after-deactivate are refused rather than fatal. network_halow_sta.py needs a HaLow access point and credentials in a halow_config module, and covers association, a socket round trip, and the association-only settings. Signed-off-by: Kwabena W. Agyeman <kwagyeman@live.com>
Wire the drivers/halow driver into the alif port: include its build rules, tear it down on soft reset, and service it. The transceiver is polled from a dedicated 1ms soft timer -- more often than lwIP's 64ms tick, because morselib always has timers due and this poll is what notices a received frame -- and halow_schedule_poll() raises a PendSV dispatch so a queued transmit does not wait for the next tick. Signed-off-by: Kwabena W. Agyeman <kwagyeman@live.com>
Wire the drivers/halow driver into the mimxrt port: include its build rules, tear it down on soft reset, and service the transceiver from the network poll each systick, with halow_schedule_poll() raising a PendSV dispatch so a queued transmit does not wait for the next tick. Signed-off-by: Kwabena W. Agyeman <kwagyeman@live.com>
Wire the drivers/halow driver into the stm32 port: include its build rules, tear it down on soft reset, and service the transceiver from the network poll each systick, with halow_schedule_poll() raising a PendSV dispatch so a queued transmit does not wait for the next tick. Signed-off-by: Kwabena W. Agyeman <kwagyeman@live.com>
At the port's 16K MEM_SIZE, sustained TCP exhausts the lwIP heap: it returns ENOMEM and throughput collapses, recovers, and collapses again in a repeating pattern. Raise it to 64K, matching the stm32 port, which holds steady. Measured on an AE3 driving a HaLow uplink: tens of ENOMEM failures per 20-minute soak at 16K, none at 64K. Signed-off-by: Kwabena W. Agyeman <kwagyeman@live.com>
Enable the Morse Micro MM8108 802.11ah shield on the N6: SPI2 on P0/P1/P2, the shield's control lines on the expansion header, and the pin interrupt for low-latency receive. Signed-off-by: Kwabena W. Agyeman <kwagyeman@live.com>
Enable the Morse Micro MM8108 802.11ah shield on the AE3's HP core: SPI0 on P0/P1/P2, with the shield's control lines sharing the JTAG pins on the header. The transceiver is polled -- the IRQ line is mapped but the pin interrupt is left off, as it gives no throughput gain on this port. Signed-off-by: Kwabena W. Agyeman <kwagyeman@live.com>
Enable the Morse Micro MM8108 802.11ah shield on the RT1060: LPSPI3 (logical SPI 1) on P0/P1/P2, the shield's control lines on the header, and the pin interrupt for low-latency receive. morselib is linked from its Cortex-M7 build. Signed-off-by: Kwabena W. Agyeman <kwagyeman@live.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This is a draft PR that tracks micropython#19617 and will be updated to match. Only commit mimxrt/boards/OPENMV_RT1060: Enable HaLow. is unique for our micropython fork since the RT1062 board support files aren't upstream.
Summary
This PR adds
network.HALOW, a MicroPython network interface for the Morse Micro MM6108/MM8108 802.11ah (Wi-Fi HaLow) sub-GHz Wi-Fi transceivers, and wires it into the stm32, alif and mimxrt ports.HaLow trades raw throughput for range and power, so the API follows the existing
network.WLAN/cyw43 station model —active(),connect(),isconnected(),ifconfig(),config(),status()— plus the HaLow-specific pieces: regulatorynetwork.country(), S1G channel/bandwidth reporting, OPEN/OWE/SAE (WPA3) security, and TWT-based power save.What's included:
drivers/halow/— the driver core: the SPI/SDIO transport to the transceiver, an lwIP netif, a packet-memory pool, and a small OSAL/scheduler shim so the vendor library runs cooperatively off the MicroPython scheduler + a PendSV dispatch (no vendor RTOS), mirroring how the cyw43 driver is integrated.extmod/network_halow.c— thenetwork.HALOWPython binding.lib/mm-iot-sdk— the Morse Micro MM-IoT-SDK as a submodule, providing the prebuiltmorseliband the transceiver firmware/board-config blobs.mp_hal_pin_interruptC-level IRQ-registration helper), docs, and hardware tests undertests/extmod_hardware/.OPENMV_N6andOPENMV_AE3.The driver is only compiled when a board sets
MICROPY_PY_NETWORK_HALOW=1; it has zero impact on other boards.Testing
Tested on hardware against a HaLow AP — association plus 20-minute TCP/UDP throughput soaks (hundreds of connect/transfer cycles, no leaks or asserts). All three integrated ports (stm32/alif/mimxrt) compile.
Throughput (bench soak means, station→AP, channel 28, 2 MHz bandwidth):
UDP-up is the cleanest capability figure (no retransmit/pacing); ~8 Mbit/s on the N6 is close to the practical ceiling for 2 MHz bandwidth. TCP is lower across the board due to link-level loss/retransmit behaviour.
OPENMV_N6 and OPENMV_AE3 are enabled in this PR. The mimxrt port integration is included and compiles; it's exercised on hardware by an out-of-tree board (the OpenMV RT1060, an i.MX RT1062, numbers above), but no in-tree board enables HaLow on mimxrt yet.
Trade-offs and Alternatives
morselibis a prebuilt binary (Morse Micro Binary Distribution Licence), added via thelib/mm-iot-sdksubmodule — the same model as other vendor Wi-Fi stacks (cyw43, NINA-W10). Building it from source (HALOW_MORSELIB_SOURCE=1) is supported for debugging, but those sources are GPL-3.0 and incompatible with the rest of the firmware, so the prebuilt library is the default.morselibis compiled against newlib, so on-nostdlibports the driver links the target's libc/libm and ships weak newlib syscall stubs to satisfy it (a failing_sbrk, so the C library never touches MicroPython's heap). This is contained entirely within the driver and costs nothing when HaLow is disabled.Generative AI
I used generative AI tools when creating this PR, but a human has checked the code and is responsible for the code and the description above.