Repository navigation
STM32F769I-DISCO Ethernet: libttak over real hardware, plus sync I/O leak fix - #108
Merged
Merged
Conversation
ttak_io_sync_read()/_write() stage data in a detachable buffer from the default context, which retires every free to the epoch, and nothing reclaims it unless the application drives the epoch GC. Every call leaked its buffer: 42 MB per 20000 hosted round trips, and an STM32F769's heap within a few hundred, after which the poller's malloc() failed. Staging buffers and zero-copy regions have a single owner that frees them, so they now come from an I/O context that frees at once. The detachable quarantine (frees held back while alloc/free churns) was capped at 1 MiB, more than an MCU's whole heap. Bare-metal builds now cap it at 8 KiB; TTAK_DETACHABLE_QUARANTINE_BYTE_LIMIT overrides it. test_net_tcp runs 1000 sync round trips and checks the heap: it failed with 6.3 MB of growth on the host and an exhausted heap on QEMU before this change.
A FreeRTOS + lwIP service on the board's Ethernet (ST HAL ETH driver, LAN8742A PHY, DHCP) built entirely on libttak: one ttak_net_poller task serves every client, a ttak_thread_pool upper-cases each chunk, and ttak_io_sync_write() sends it back. A second port reports libttak, newlib and FreeRTOS memory counters. scripts/baremetal/stm32_eth_demo.py flashes the board and checks ping, echo correctness, throughput, parallel clients, connection churn and that memory returns to its baseline. On the board 6 of 6 runs passed: 19.4 Mbit/s each way, 0.12 ms ping, no growth over 205 connections. The README records what bring-up took: the RMII receive phase that came up wrong on half the boots (detected and recovered by restarting the MAC), the HAL presetting hardware checksum insertion, HAL handle state surviving HAL_ETH_Init(), unseeded DHCP xids, and sizing zero-copy RX buffers. CI builds the example.
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.
Summary
This PR runs libttak on the real Ethernet of the STM32F769I-DISCO: ST HAL ETH driver, LAN8742A PHY, DHCP. It verifies the result over the network and documents it. On top of #104's lwIP backend, a network service runs on the board entirely through libttak. Bringing it up exposed a memory leak in libttak itself, which this PR also fixes.
fix(io)ttak_io_sync_read()/_write()take a staging buffer from the default detachable context. That context retires every free to the epoch, and nothing reclaims it, so every call leaked its buffer: +42 MB per 20,000 round trips on the host, and the board ran out of heap within a few hundred calls. The I/O buffers now use a context that frees immediately. Also, on bare metal the detachable quarantine cap was 1 MiB, larger than the MCU's whole heap; it is now 8 KiB (TTAK_DETACHABLE_QUARANTINE_BYTE_LIMIT).docs(examples)examples/stm32f769i-disco-lwip(driver, FreeRTOS/lwIP config, service), the host test scriptscripts/baremetal/stm32_eth_demo.py, its README, and a CI build job.What the service does
ttak_net_pollertask serves all clients.ttak_thread_pooltask (submit, then wait on the future) and sent back withttak_io_sync_write().ttak_mem_usage_bytes(),ttak_mem_buddy_get_stats(), newlib heap and FreeRTOS heap.Board results (6 of 6 runs, 7/7 checks each)
One STM32F769I-DISCO on a 100 Mbit/s home LAN, with a Linux host on the same switch. Each run reflashed and rebooted the board.
Problems found during bring-up (details in the example README)
HAL_ETH_Init()presets every TX descriptor to full hardware checksum insertion, so the MAC overwrote lwIP's software checksum. The example now uses hardware checksums in both directions.HAL_ETH_Init()doesn't reset the handle's TX/RX bookkeeping, so every transmit returned BUSY while the link task held the tcpip core lock. The restart path now clears that state, the TX wait has a timeout, and RX/restart are serialised by a mutex.rand()).rand()is now seeded from the hardware RNG.Testing
stm32_eth_demo.py)test_net_tcpadds a check that the heap does not grow over 1000 sync round trips. Before the fix it failed with +6.3 MB on the host and an out-of-memory failure on QEMU.Limits
ttak_net_poller_wait()calls malloc on every call.