Conversation
Multi band receivers such as the ZED-F9P report two to three signals per satellite, so numSigs regularly exceeds UBLOX_MAX_SIGNALS and the payload grows past MAX_UBLOX_PAYLOAD_SIZE. The parser discarded the whole frame, counted an error and then rescanned the payload for the next sync pattern, so the error counter kept climbing while the satellite list stayed empty, because UBX-NAV-SAT is not enabled on M9 and later. UBX-NAV-SIG and UBX-NAV-SAT payloads that do not fit are now read to the end and checksummed, only the signals beyond UBLOX_MAX_SIGNALS are dropped. The parser stays byte aligned and does not have to resync. Fixes iNavFlight#10941
|
ⓘ Qodo reviews are paused because the subscription is no longer active. Ask your workspace admin to reactivate the subscription to resume reviews. Manage billing |
PR Summary by QodoPreserve oversized UBX-NAV-SIG and NAV-SAT frames
AI Description
Diagram
High-Level Assessment
Files changed (2)
|
Code Review by Qodo
1.
|
|
RAM / Flash usage vs. base commit
See RAM/flash optimization guide for techniques to reduce usage. |
|
Test firmware build ready — commit Download firmware for PR #11921 251 targets built. Find your board's
|
The NAV-SIG handler loops already stop at UBLOX_MAX_SIGNALS, so the rewrite of that block changed nothing; restore the original code. Drop the sizeof(ubx_nav_sig) assert, which only restates the buffer definition, shorten the new comments to one line each, and restore the executable bit of gps_ublox.c that the previous commit cleared. No functional change: a host harness feeding NAV-SIG/NAV-SAT frames of 40 to 255 records into gpsNewFrameUBLOX() gives identical results before and after this commit.
|
Moved to milestone 10.1 because it changes how the u-blox parser consumes bytes. Please let us know when it has been tested with different types of real GPS receivers (for example M8, M9/M10 and a multi-band F9P). Thank you! |
Problem
With a u-blox ZED-F9P on INAV 8.0.0 the Configurator GPS tab shows the
Errorscounter climbing (342 of 654 messages in the reporter's screenshot) whileSatsshows 32, and the CLI shows no satellite information (gpssatsis empty). Disabling UBX-NAV-SIG on the receiver makes the errors disappear. Reported in #10941. Fixes #10941.Cause
src/main/io/gps_ublox.c:900-904on maintenance-10.x: any frame whose declared payload length exceedsMAX_UBLOX_PAYLOAD_SIZEis dropped,gpsStats.errorsis incremented and the parser resyncs.MAX_UBLOX_PAYLOAD_SIZEisUBLOX_MAX_SIGNALS * 16 + 8= 1032 bytes (src/main/io/gps_ublox.h:35-38), so the buffer holds 64 NAV-SIG signals. A multi-band receiver reports two or three signals per satellite, so NAV-SIG regularly carries more than 64 signals and every such frame is discarded. On receivers with protocol version above 23.01 INAV enables NAV-SIG and disables NAV-SAT (gps_ublox.c:1069-1077), sosatelites[]is never filled andgpssatsstays empty. The code is identical on maintenance-11.x.Change
UBLOX_MAX_ACCEPTED_PAYLOAD_SIZE(255 * 16 + 8 bytes, the most a U1 record count can declare) are received to the end and checksummed. Only the firstMAX_UBLOX_PAYLOAD_SIZEbytes are stored, so records beyond the buffer are dropped and the parser stays byte aligned. The existing handlers already stop atUBLOX_MAX_SIGNALS.8 + count * record size; otherwise the frame is counted as an error and the parser resyncs at once, so a corrupt length cannot swallow the following frames._payload_lengthis clamped toMAX_UBLOX_PAYLOAD_SIZEbefore the frame handlers run.No buffer size changes; RAM use is unchanged.
Test
Host harness that compiles the real
gps_ublox.cand feeds synthetic frames byte by byte intogpsNewFrameUBLOX(), built with ASan/UBSan, run against maintenance-10.x and this branch:Known limit, inherent to UBX framing (last two table rows): a frame with a consistent header that loses bytes consumes the following data up to its declared length before the checksum fails. maintenance-10.x already has this for every frame up to 1032 bytes (9 of 20 PVT lost above); for NAV-SIG/NAV-SAT the window grows to at most 4088 bytes (14 of 20 PVT lost above).
The likely source of lost bytes is the UART receive ring: it is 256 bytes (
src/main/drivers/serial_uart.h:28-42) and the RX interrupt overwrites it without an overflow check (serial_uart_stm32f7xx.c:264-265,serial_uart_stm32f4xx.c:222-223,serial_uart_at32f43x.c:366-367). The GPS task runs at 50 Hz (src/main/fc/fc_tasks.c:589), so at 230400 baud about 460 bytes arrive between two runs, more than the ring holds; at 115200 it is about 230 bytes.Bound: 4088 bytes take about 355 ms at 115200 baud (710 ms at 57600), below
GPS_TIMEOUTof 1000 ms (src/main/io/gps_private.h:27), so a damaged frame cannot cause a GPS timeout at 57600 baud or faster. #12001 (512-byte GPS receive buffer, lower NAV-SIG rate) reduces the exposure further.Existing unit tests
gps_ublox_unittest,gps_null_port_unittestandgps_heartbeat_unittestpass. Not tested on hardware: a comparison of maintenance-10.x and this PR with a ZED-F9P at 115200 and 230400 baud (PVT rate andgpsStats.errors) is still open.Flash / RAM
arm-none-eabi-size, maintenance-10.x (3931fcd) vs. this PR:Docs
No documentation change: no setting, CLI command or documented limit changes, and
UBLOX_MAX_SIGNALSis a build-time define that is not mentioned under docs/.