STM32N6 Ethernet / lwIP
Follow frames from the MAC through DMA descriptors and lwIP; distinguish receive pressure, wire errors and stack drops.
Download domain JSON · GitHub source · Domain catalog
Probe sampled · Descriptor com.bkpt.stm32-ethernet · version 0.9.0 · domain API 1.
Purpose and prerequisites
Targets the STM32N6570-DK Ethernet/lwIP demo, using STM32N657 secure SVD names ETH_S and RCC_S. Requires the exact ELF/layout: four RX descriptors with 24-byte stride, ownership at +12, and 16-bit lwIP statistics at the offsets listed below. It is not a generic pack for every STM32 Ethernet controller. The Ethernet clock guard must pass. Firmware statistics must be enabled and the debug view of memory must be coherent.
Engineering interpretation
Compare MAC arrivals, software-owned descriptors and lwIP counters to locate receive pressure. MAC packets advancing while IP progress stops suggests the receive path is not keeping up, but cache visibility and different traffic populations must be considered. FIFO overflow, descriptor backlog and UDP drops identify different layers. A quiet receive counter is not necessarily failure when no peer sends traffic. This firmware keeps DMA descriptors in non-cacheable AXISRAM while lwip_stats can lag through cache write-back. The two clear-on-read inputs consume counts that another reader would otherwise see; this is a meaningful observation side effect.
Acquisition and validity
The descriptor declares 21 inputs and 13 derived channels, with a requested default of 100 Hz per input. Unsupported/unsafe rows remain unavailable. The achieved poll rate depends on the probe and selected inputs.
Global guard: (RCC_S.RCC_AHB5ENR & 0x02000000) = 0x02000000. ETH1 clock disabled (RCC_AHB5ENR.ETH1EN clear): the block is unclocked and reads return zeros, not data
SVD device: STM32N657. Target prefix: STM32N65.
Inputs are sampled separately while firmware runs. DWARF paths require the exact Debug ELF; unresolved or null pointers produce unavailable values. A readable object is not proof that it has finished initialization. Firmware can update or reuse it between reads. Missing observations propagate to dependent fields and checks.
Cards with a capacity reference show value / capacity, not a percentage. Both readings must be available, capacity must be positive, and the value must lie between zero and capacity. Otherwise the card is unavailable. Individual fields retain their raw values in traces. Saved observations describe their acquisition time, not fresh target state.
Cards and tables
Traffic
MAC counter observations and derived rates. Host polling can miss brief state transitions.
| CARD OR ROW | READING AND SIGNIFICANCE | UNIT |
|---|---|---|
MAC receive rate · eth.rx_rate | Interval average of good unicast MAC receive-counter changes. Broadcast/multicast traffic is excluded. | pkts/s |
MAC transmit rate · eth.tx_rate | Interval average of good MAC transmit-counter changes. It is packet rate, not bit rate. | pkts/s |
Received good frames · eth.rx_good | Good received unicast packets only. Broadcast and multicast have separate hardware counters and are not included here. | pkts |
Transmitted good frames · eth.tx_good | Good transmitted MAC packets, a wrapping 32-bit counter. It records MAC activity, not delivery acknowledged by the remote application. | pkts |
Receive path
Descriptor occupancy and queue/state snapshots describe the instant sampled. A brief stall can occur between observations.
| CARD OR ROW | READING AND SIGNIFICANCE | UNIT |
|---|---|---|
Descriptors awaiting the application · eth.rx_ring | Count of four RX descriptors whose OWN bit is clear: DMA has handed ownership to software. It is an instantaneous backlog indicator, not total traffic or proof every descriptor holds a valid packet. | desc |
Queued receive packets · eth.rxq_packets | Packet count in the receive MTL queue at that instant. Distinct from descriptors awaiting software in RAM. | pkts |
Receive queue fill state · eth.rxq_fill | Receive queue fill category: empty, below threshold, above threshold or full. It is not a percentage. Values. | Raw value / decoded state |
DMA / Receive DMA state · eth.rx_dma_state | Receive DMA process-state code. Suspension can accompany descriptor starvation, but one sampled state cannot establish duration or root cause. Values. | Raw value / decoded state |
DMA / Current receive descriptor address · eth.rx_ring_cur | Current RX descriptor address. Compare movement with backlog; it is a pointer, not a packet count. | Raw value / decoded state |
Queue / Receive queue read state · eth.rxq_read_state | Receive queue read-controller state. Compare with fill and DMA activity. Values. | Raw value / decoded state |
MAC / MAC receive state · eth.mac_rx_state | Receive MAC state-machine code at the poll instant; short transitions may never be sampled. Values. | Raw value / decoded state |
Transmit path
Decoded controller states from the sampled status registers.
| CARD OR ROW | READING AND SIGNIFICANCE | UNIT |
|---|---|---|
Transmit DMA state · eth.tx_dma_state | Transmit DMA process-state code. Compare with TX demand/rate; waiting or suspension can be normal without work. Values. | Raw value / decoded state |
Transmit queue read state · eth.txq_read_state | Transmit queue read-controller state. Interpret with demand, not as a standalone error. Values. | Raw value / decoded state |
MAC transmit state · eth.mac_tx_state | Transmit MAC state-machine code at the poll instant; it is not a utilization percentage. Values. | Raw value / decoded state |
Errors and drops
Missed-frame and overflow fields come from consuming counters and describe read intervals. CRC/alignment and stack drops are cumulative.
| CARD OR ROW | READING AND SIGNIFICANCE | UNIT |
|---|---|---|
Wire / CRC errors · eth.rx_crc_err | Cumulative received CRC-error packets. Increases direct investigation toward physical-link integrity; they do not uniquely identify cable, PHY or EMI as the cause. | pkts |
Wire / Alignment errors · eth.rx_align_err | Cumulative alignment-error packets; compare with CRC errors and MAC configuration when investigating wire-side corruption. | pkts |
Receive / Frames missed in this read interval · eth.rx_missed_frames | Missed-packet field of the consuming MTL read. Positive means receive loss in that read interval; compare queue, FIFO and descriptors before assigning a cause. | frames |
Receive / FIFO overflow count in this read interval · eth.rx_fifo_overflow | FIFO overflow count in the consuming MTL read interval. Points to receive buffering/drain pressure, not necessarily wire corruption. | frames |
DMA / DMA misses in this read interval · eth.dma_missed_frames | DMA missed-frame count in the read interval. Counter saturation and other firmware readers can limit observed totals. | frames |
Stack / IP packets dropped · lwip.ip_drop | 16-bit IP drop statistic. Inspect alongside IP receive progress; it represents stack-layer drops, not a MAC error counter. | Raw value / decoded state |
Stack / UDP datagrams dropped · lwip.udp_drop | 16-bit UDP drop statistic. No listener/PCB or receive-resource pressure can explain growth; compare socket behavior and memory use. | Raw value / decoded state |
Network stack
Application-owned lwIP counters. Offsets and widths must match this exact N6 demo ELF and its lwIP configuration.
| CARD OR ROW | READING AND SIGNIFICANCE | UNIT |
|---|---|---|
IP packets accepted · lwip.ip_recv | 16-bit lwIP IP receive statistic at this exact build offset. Compare its progress with MAC unicast arrivals; cache write-back can delay what the probe sees. | Raw value / decoded state |
UDP datagrams accepted · lwip.udp_recv | 16-bit UDP receive statistic. It tracks the stack receive path, not guaranteed application consumption. | Raw value / decoded state |
Heap bytes in use · lwip.mem_used | lwIP heap bytes currently used, a level rather than a lifetime allocation counter. The exact field width/offset depends on this lwIP configuration. | B |
Raw registers and access limits
Registers, addresses and packed fields are kept out of graphs by default. PHY MDIO access remains unsafe and unavailable; grouping does not authorize a read.
| CARD OR ROW | READING AND SIGNIFICANCE | UNIT |
|---|---|---|
MAC / MMC control · eth.mmc_control | MMC counter control word. RSTONRD bit 2 must be clear before polling the cumulative MMC counters. | Raw value / decoded state |
MAC / MAC configuration · eth.mac_config | MAC configuration programmed by the driver, including speed/duplex and RX/TX enables. This is not a direct PHY link observation. | Raw value / decoded state |
MAC / MAC debug · eth.mac_debug | Raw MAC receive/transmit state-machine snapshot; decoded states below describe one sampled instant. | Raw value / decoded state |
Queues / Transmit queue debug · eth.mtl_txq_dbg | Raw MTL transmit-queue debug snapshot. Decoding extracts its read-controller state. | Raw value / decoded state |
Queues / Receive queue debug · eth.mtl_rxq_dbg | Raw MTL receive-queue debug snapshot. Decoding extracts packet count, fill classification and read state. | Raw value / decoded state |
Consuming counters / Packed MTL missed/overflow sample · eth.rx_missed | Packed MTL missed-packet/FIFO-overflow counters. Reading consumes them; do not graph the packed word as a simple packet total. | pkts |
Consuming counters / Packed DMA missed sample · eth.dma_missed | Packed DMA missed-frame counter, consumed by a read. The derived field isolates its count bits. | pkts |
DMA / DMA debug · eth.dma_debug | Raw DMA debug word. Receive and transmit process states are decoded separately. | Raw value / decoded state |
DMA / DMA channel status · eth.dma_ch0 | DMA channel 0 status, with write-one-to-clear flags. A read does not acknowledge these flags. | Raw value / decoded state |
Access limits / PHY link access (not sampled) · eth.phy_link | Unavailable by design. Direct MDIO transactions through the MAC would race the firmware driver; no physical link state is measured. | Raw value / decoded state |
Every sampled input
All paths below come from the downloadable definition. Integer types specify width and signedness. No scaling is applied to a raw read. A field without a declared unit is a code, count, address or raw register; its engineering meaning is explained above or below.
| INPUT | SOURCE / ADDRESS PATH | TYPE | INTERPRETATION / ACCESS |
|---|---|---|---|
eth.tx_good | ETH_S.ETH_TX_PACKET_COUNT_GOOD | u32 | See its card/table above. Counter policy: wrapping. Guard: (ETH_S.ETH_MMC_CONTROL & 0x4) = 0x0. MMC_CONTROL.RSTONRD is set: counter reads self-clear, sampling would destroy the values it reports |
eth.rx_good | ETH_S.ETH_RX_UNICAST_PACKETS_GOOD | u32 | See its card/table above. Counter policy: wrapping. Guard: (ETH_S.ETH_MMC_CONTROL & 0x4) = 0x0. MMC_CONTROL.RSTONRD is set: counter reads self-clear, sampling would destroy the values it reports |
eth.rx_crc_err | ETH_S.ETH_RX_CRC_ERROR_PACKETS | u32 | See its card/table above. Counter policy: wrapping. Guard: (ETH_S.ETH_MMC_CONTROL & 0x4) = 0x0. MMC_CONTROL.RSTONRD is set: counter reads self-clear, sampling would destroy the values it reports |
eth.rx_align_err | ETH_S.ETH_RX_ALIGNMENT_ERROR_PACKETS | u32 | See its card/table above. Counter policy: wrapping. Guard: (ETH_S.ETH_MMC_CONTROL & 0x4) = 0x0. MMC_CONTROL.RSTONRD is set: counter reads self-clear, sampling would destroy the values it reports |
eth.mmc_control | ETH_S.ETH_MMC_CONTROL | u32 | See its card/table above. |
eth.mac_config | ETH_S.ETH_MACCR | u32 | See its card/table above. |
eth.mac_debug | ETH_S.ETH_MACDR | u32 | See its card/table above. |
eth.mtl_txq_dbg | ETH_S.ETH_MTLTXQ0DR | u32 | See its card/table above. |
eth.mtl_rxq_dbg | ETH_S.ETH_MTLRXQ0DR | u32 | See its card/table above. |
eth.rx_missed | ETH_S.ETH_MTLRXQ0MPOCR | u32 | See its card/table above. Counter policy: clear_on_read. |
eth.dma_debug | ETH_S.ETH_DMADSR | u32 | See its card/table above. |
eth.dma_ch0 | ETH_S.ETH_DMAC0SR | u32 | See its card/table above. |
eth.rx_ring_cur | ETH_S.ETH_DMAC0CARXDR | u32 | See its card/table above. |
eth.dma_missed | ETH_S.ETH_DMAC0MFCR | u32 | See its card/table above. Counter policy: clear_on_read. |
eth.phy_link | PHY registers go through MDIO (MACMDIOAR/MACMDIODR) and a debug-port transaction races the driver's own use of the address register; link speed is shown from ETH_MACCR instead | u32 | See its card/table above. PHY registers go through MDIO (MACMDIOAR/MACMDIODR) and a debug-port transaction races the driver's own use of the address register; link speed is shown from ETH_MACCR instead |
eth.rx_ring | DMARxDscrTab: 4 entries, 24-byte stride; 32-bit ownership word at +12, mask 0x80000000; count clear ownership bits. | u32 | See its card/table above. |
lwip.ip_recv | lwip_stats + 74 bytes | u16 | See its card/table above. Counter policy: wrapping. |
lwip.ip_drop | lwip_stats + 78 bytes | u16 | See its card/table above. Counter policy: wrapping. |
lwip.udp_recv | lwip_stats + 122 bytes | u16 | See its card/table above. Counter policy: wrapping. |
lwip.udp_drop | lwip_stats + 126 bytes | u16 | See its card/table above. Counter policy: wrapping. |
lwip.mem_used | lwip_stats + 172 bytes | u16 | See its card/table above. |
wrapping tells analysis to account for rollover at the declared integer width; a reset can look like a wrap, and multiple wraps between samples cannot be recovered. monotonic uses sampled increases without inventing a reset/wrap delta. clear_on_read reports a consuming read interval, not a lifetime total. A display styled as a counter does not itself establish any of these policies.
Derived fields and rates
| CHANNEL | CALCULATION | MEANING | UNIT |
|---|---|---|---|
eth.rx_dma_state | (eth.dma_debug >> 8) & 0xF | Receive DMA process-state code. Suspension can accompany descriptor starvation, but one sampled state cannot establish duration or root cause. Values. | Code / state |
eth.tx_dma_state | (eth.dma_debug >> 12) & 0xF | Transmit DMA process-state code. Compare with TX demand/rate; waiting or suspension can be normal without work. Values. | Code / state |
eth.rx_rate | max(0, change in eth.rx_good / elapsed seconds) | Interval average of good unicast MAC receive-counter changes. Broadcast/multicast traffic is excluded. | pkts/s |
eth.tx_rate | max(0, change in eth.tx_good / elapsed seconds) | Interval average of good MAC transmit-counter changes. It is packet rate, not bit rate. | pkts/s |
eth.mac_tx_state | (eth.mac_debug >> 17) & 0x3 | Transmit MAC state-machine code at the poll instant; it is not a utilization percentage. Values. | Code / state |
eth.mac_rx_state | (eth.mac_debug >> 1) & 0x3 | Receive MAC state-machine code at the poll instant; short transitions may never be sampled. Values. | Code / state |
eth.txq_read_state | (eth.mtl_txq_dbg >> 1) & 0x3 | Transmit queue read-controller state. Interpret with demand, not as a standalone error. Values. | Code / state |
eth.rxq_read_state | (eth.mtl_rxq_dbg >> 1) & 0x3 | Receive queue read-controller state. Compare with fill and DMA activity. Values. | Code / state |
eth.rxq_fill | (eth.mtl_rxq_dbg >> 4) & 0x3 | Receive queue fill category: empty, below threshold, above threshold or full. It is not a percentage. Values. | Code / state |
eth.rxq_packets | (eth.mtl_rxq_dbg >> 16) & 0x3FFF | Packet count in the receive MTL queue at that instant. Distinct from descriptors awaiting software in RAM. | Code / state |
eth.rx_missed_frames | (eth.rx_missed >> 16) & 0x7FF | Missed-packet field of the consuming MTL read. Positive means receive loss in that read interval; compare queue, FIFO and descriptors before assigning a cause. | Code / state |
eth.rx_fifo_overflow | (eth.rx_missed >> 0) & 0x7FF | FIFO overflow count in the consuming MTL read interval. Points to receive buffering/drain pressure, not necessarily wire corruption. | Code / state |
eth.dma_missed_frames | (eth.dma_missed >> 0) & 0x7FF | DMA missed-frame count in the read interval. Counter saturation and other firmware readers can limit observed totals. | Code / state |
Rates need two valid samples at increasing timestamps and are interval averages. Gaps break the calculation. A negative raw delta is clamped to zero by the rate calculation; do not infer an instantaneous event rate from a reset. Unknown map keys pass through numerically; an unmapped code is not a validated physical measurement.
Findings
Application not draining
warning · app-not-draining. lwip.ip_recv does not increase over 250 ms while eth.rx_good advances by at least 50.
Good MAC unicast frames advance while the sampled IP receive counter does not. Check driver scheduling, buffers and the application consumer, but also account for cached statistics and traffic that never reaches IP.
Evidence: lwip.ip_recv, eth.rx_good, eth.rx_ring, eth.rx_dma_state, eth.rx_missed_frames, lwip.mem_used.
RX frames missed by the MAC
error · rx-frames-missed. eth.rx_missed_frames ≥ 1 at a valid sample.
The MTL missed-packet field is positive in a consuming read interval. This establishes reported receive loss, not a unique descriptor-starvation diagnosis. Compare FIFO overflow, queue fill, DMA state and ring ownership.
Evidence: eth.rx_missed_frames, eth.rx_fifo_overflow, eth.rx_ring, eth.rx_dma_state, lwip.ip_recv.
CRC errors on the wire
error · rx-crc-errors. eth.rx_crc_err increases between valid samples.
The CRC counter advanced. Investigate cable/connector, PHY configuration and electrical integrity alongside alignment errors; this observation alone cannot identify a unique cause.
Evidence: eth.rx_crc_err, eth.rx_align_err, eth.mac_config.
RX stopped while TX continues
warning · rx-stopped. eth.rx_good does not increase over 1000 ms while eth.tx_good advances by at least 1.
The MAC keeps transmitting but nothing is being received. Suspect the receive path specifically: RX DMA state, buffer availability, or the peer no longer sending.
Evidence: eth.rx_rate, eth.tx_rate, eth.rx_dma_state, eth.tx_dma_state.
RX FIFO overflowed
error · rx-fifo-overflow. eth.rx_fifo_overflow ≥ 1 at a valid sample.
Frames were lost inside the MAC's receive FIFO: the MTL queue filled faster than the DMA drained it into memory. Unlike missed frames (no descriptor), this points at bus/DMA throughput or a burst above what the queue depth absorbs. Value is frames lost in one poll interval (clear-on-read).
Evidence: eth.rx_fifo_overflow, eth.rxq_fill, eth.rxq_packets, eth.rx_missed_frames, eth.rx_ring.
RX descriptor ring saturated
suspicious · rx-ring-saturated. eth.rx_ring ≥ 3 for 100 ms of observations.
At least three of four descriptors stayed software-owned across 100 ms of sampled evidence. This is a high-backlog threshold, not literally four-of-four fullness; brief saturation can occur between polls.
Evidence: eth.rx_ring, eth.rx_ring_cur, eth.rx_dma_state, eth.rx_missed_frames.
Datagrams dropped by the stack
warning · stack-dropping. lwip.udp_drop increases between valid samples.
The stack received datagrams and threw them away: no PCB is bound for that port, or the receive queue of a socket nobody is reading is full. Loss above the MAC, so the Ethernet counters stay clean.
Evidence: lwip.udp_drop, lwip.udp_recv, lwip.mem_used, eth.rx_good.
Value dictionaries
These are the exact value mappings in this version of the descriptor. Unlisted status codes remain numeric; they are not implicitly success. Decode a value in the context of its field and validity.
Value map 1
| RAW VALUE | DECODED LABEL / MAPPED VALUE |
|---|---|
0 | EMPTY |
1 | BELOW_THRESH |
2 | ABOVE_THRESH |
3 | FULL |
Value map 2
| RAW VALUE | DECODED LABEL / MAPPED VALUE |
|---|---|
0 | STOPPED |
1 | FETCHING |
3 | WAITING |
4 | SUSPENDED |
5 | CLOSING |
6 | TIMESTAMP_WR |
7 | TRANSFERRING |
Value map 3
| RAW VALUE | DECODED LABEL / MAPPED VALUE |
|---|---|
0 | IDLE |
1 | READING |
2 | STATUS |
3 | FLUSHING |
Value map 4
| RAW VALUE | DECODED LABEL / MAPPED VALUE |
|---|---|
0 | STOPPED |
1 | FETCHING |
2 | WAITING |
3 | READING |
4 | TIMESTAMP_WR |
6 | SUSPENDED |
7 | CLOSING |
Value map 5
| RAW VALUE | DECODED LABEL / MAPPED VALUE |
|---|---|
0 | IDLE |
1 | READ |
2 | WAITING |
3 | FLUSHING |
Value map 6
| RAW VALUE | DECODED LABEL / MAPPED VALUE |
|---|---|
0 | IDLE |
1 | WAITING |
2 | PAUSE |
3 | TRANSFERRING |
Definition and contribution
Checked against the N6 demo main.c, ethernetif.c, lwipopts.h, lwIP stats.h, the STM32N657 CMSIS Ethernet register definitions and the domain rate/counter/finding decoder. Firmware layout and SVD compatibility must be rechecked for any adapted build.
View or propose changes to the canonical JSON. Contribution guide.
Download SHA-256: 5df29bdc78a799741cdb3ad76d7b6555bbc44c84319dea64547d10d2dfa7c170.