feat(dronecan): on-demand GetNodeInfo, GetSet, ExecuteOpcode, RestartNode via async slot - #11683
Draft
daijoubu wants to merge 60 commits into
Draft
feat(dronecan): on-demand GetNodeInfo, GetSet, ExecuteOpcode, RestartNode via async slot#11683daijoubu wants to merge 60 commits into
daijoubu wants to merge 60 commits into
Conversation
SJW=8 was overly conservative (80% of bit time at 1Mbps with 10 quanta). SJW=3 is the standard value also used by the F7 driver. Tested with 6037 arm/disarm cycles at 500kbps: TEC=0, REC=0, zero errors.
…DCAN PLL2Q was 3 (266 MHz, invalid for FDCAN ≤ 80 MHz). Fix to 10 (80 MHz). Extend PLL2 guard from USE_SDCARD_SDIO to USE_SDCARD_SDIO || USE_DRONECAN so H7 boards with CAN but no SD card get PLL2 configured. Adopt upstream PLL2M/N formula (VCI=1.6 MHz, VCO=800 MHz) and error check on HAL_RCCEx_PeriphCLKConfig.
…pport Remove redundant PeriphClkInitStruct clock config from canardSTM32CAN1_Init. system_stm32h7xx.c already configures FDCAN to use PLL2Q (80 MHz) when USE_DRONECAN is defined; duplicating it in the driver overwrites with PLL1. Also add CAN1 pin definitions and USE_DRONECAN to KAKUTEH7WING target (PD0/PD1, CAN1_STANDBY PD3 disabled by default).
Use HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_FDCAN) instead of HAL_RCC_GetPCLK1Freq() for bit timing calculation. FDCAN is clocked from PLL2Q (80 MHz) configured in system_stm32h7xx.c; using PCLK1 (100 MHz) produced a ~25% baud rate error causing immediate bus-off. Restore SJW to 3 for better synchronisation tolerance.
Remove high-frequency LOG_DEBUG messages from GNSS Fix/Fix2/Auxiliary handlers, onTransferReceived, dronecanInit, and gps_dronecan HDOP path that fired at 25 Hz and flooded the log. Fix PLL2 VCO input to target 1.6 MHz (PLL2M = HSE/1600000, PLL2N = 500) rather than 2.0 MHz, keeping the operating point clearly within VCIRANGE_0 (1-2 MHz) as the original SDCARD-only code did with PLL2M=5. VCO output remains 800 MHz; FDCAN (80 MHz via PLL2Q=10) and SDMMC (200 MHz via PLL2R=4) outputs are unchanged.
Drop high-frequency and verbose-but-low-value LOG_DEBUG(CAN messages: - dronecan.c: Battery Info (x2), GetNodeInfo, NodeStatus, TX success, RX loop, commented-out debug blocks - canard_stm32h7xx_driver.c: timing computation intermediates (Baudrate, Max Quanta, Prescaler BS, Prescaler, Timings summary) - canard_stm32f7xx_driver.c: same timing intermediates, TX success, In CAN Init, commented-out clock and RX blocks Retain error-path messages (decode failed, TX/RX error, init failures) and the single-line Prescaler/SJW/BS summary logged at init.
… operation Tested at 1 Mbps on KAKUTEH7WING hardware and confirmed bus operational.
…ivers Remove CubeMX boilerplate markers, commented-out dead code, and development-time question comments from both drivers.
Fix: DroneCAN GNSS messages were being applied to gpsSolDRV regardless of the configured GPS provider. Guard added in gps_dronecan.c where it belongs, keeping CAN transport layer unaware of GPS config.
…g difference F7 bxCAN HAL writes SJW directly to BTR register where hardware adds 1, so stored value 3 gives 4 tq. This wider SJW is needed for reliable bus operation on F7 targets and is different from H7 where SJW=1 is actual tq.
Prevents state machine from continuing in INIT state when the CAN peripheral fails to initialize.
Prevents out-of-bounds access when STATE_DRONECAN_FAILED is active.
Prevents stale pre-bus-off frames from storming the bus on recovery.
With AutoRetransmission=ENABLE, frames that fail on a degraded bus occupy FIFO slots indefinitely. All 32 slots fill, HAL_FDCAN_AddMessage returns HAL_ERROR, and all outgoing traffic stalls permanently with no indication until full bus-off. DroneCAN reliability is handled at the application layer via periodic republishing.
Matches the H7 driver pattern. Previously the return value was silently discarded; if timing computation failed, uninitialized stack bytes were passed to HAL_CAN_Init.
The H7 FDCAN 128x11 recessive-bit recovery sequence takes up to 11.264ms at 125kbps. The 1ms delay was restarting the counter before it could complete, preventing the node from ever exiting bus-off. 20ms gives safe margin above worst-case and allows time to detect immediate re-entry.
Guard against non-DroneCAN GPS provider at the transport boundary (handle_GNSS* functions) rather than in each leaf function in gps_dronecan.c. Also adds the guard to handle_GNSSRCTMStream which had none. Removes stale UNUSED(pgnssAux) and placeholder comment from dronecanGPSReceiveGNSSAuxiliary.
canardSTM32GetProtocolStatus() was called on every dronecanUpdate() invocation (~500Hz) to detect bus-off. Moved into the existing 1Hz task block — bus-off detection latency of up to 1s is acceptable. Adds LOG_DEBUG to report BusOff and ErrorPassive flags each second for bench diagnostics.
AutoBusOff=ENABLE handles the 128x11 recovery sequence automatically, but ESR.BOFF is a sticky read-only flag that is NOT cleared when hardware recovery completes. GetProtocolStatus() reads this flag, so the state machine was permanently stuck in STATE_DRONECAN_BUS_OFF after any bus-off event on F7 targets. Stop/Start re-enters init mode which clears ESR.BOFF, allowing recovery detection to work correctly.
Comment incorrectly stated '25MHz' as a supported HSE value — 25MHz fails the assert. CMake always provides HSE_VALUE per-target via -DHSE_VALUE=<n> so the stm32h7xx_hal_conf.h fallback of 25MHz is never used. Current targets use 8MHz (default) or 16MHz (KAKUTEH7WING).
…adence GetProtocolStatus() was called every dronecanUpdate() cycle (~500Hz) in BUS_OFF state. Moved inside the 20ms recovery timer block so it runs at the same cadence as RecoverFromBusOff() — still detects recovery within 20ms but reduces MMIO reads from ~500/sec to ~50/sec.
HAL_CAN_Stop/Start called from the scheduler context with CAN interrupts active caused a full FC lockup. Reverted to empty stub pending investigation of a safe mechanism to clear the sticky ESR.BOFF flag on F7.
Unconditional 1Hz LOG_DEBUG was flooding the bootlog with healthy status messages. Now only logs when an error condition is actually present.
HAL_CAN_AddTxMessage returns non-OK when all mailboxes are busy — a normal transient condition at startup. The log was noise. Matches the H7 driver which already handles this path silently.
DroneCAN float16 optional fields encode NaN when unpopulated. Without a guard, NaN * 100 converts to 0 on Cortex-M (ARM VCVT saturation), permanently blocking the HDOP fallback path. Also passes values through gpsConstrainHDOP() to prevent uint16_t overflow for extreme DOP values.
…ompatible gpsSolDRV has hdop but no vdop field. VDOP and EPV are not interchangeable (different units, conversion requires receiver UERE). lastVDOP was a dead store with no valid consumer.
…ames size Guards the CLI state name array against future enum additions — if a new state is added without updating the array, the build fails immediately.
…onecan Phase 2 of the combined DroneCAN driver rework (folds in iNavFlight#11560 content): F7 bxCAN ISR-driven TX refill: - Add NVIC_PRIO_CAN=4 to nvic.h (shared by H7 and F7) - Enable CAN_IT_TX_MAILBOX_EMPTY and CAN1_TX_IRQn at NVIC_PRIO_CAN - Add HAL_CAN_TxMailbox{0,1,2}CompleteCallback ISR pumps in dronecan.c - Wire dronecanMaskTxISR/UnmaskTxISR to NVIC_DisableIRQ/EnableIRQ(CAN1_TX_IRQn) - Add #else branch for SITL/AT32 (was missing, would break SITL build) TEC/REC/LEC error counters: - Extend canardProtocolStatus_t with tec, rec, lec fields - F7: populate from ESR register (bits 23:16, 31:24, 6:4) - H7: populate from ECR register (bits 22:16, 14:8) + PSR.LastErrorCode Typo fix: canardSTM32Recieve -> canardSTM32Receive across all drivers and call sites Other: - Add canardSTM32GetTxQueueFillLevel() to all three drivers (returns 0; no SW queue) - Make canard and memory_pool static in dronecan.c - Add cliDronecan CLI command showing bus health (BusOff, ErrorPassive, TEC, REC, LEC, fill levels)
Fix H7 ISR pump (was completely non-functional): - FDCAN_IT_TX_COMPLETE routes to LINE0 by default (ILS=0); enable FDCAN1_IT0_IRQn at NVIC_PRIO_CAN and add FDCAN1_IT0_IRQHandler - Change dronecanMaskTxISR from FDCAN1_IT1_IRQn to FDCAN1_IT0_IRQn Fix H7 TEC extraction from ECR register: - ECR[7:0]=TEC, ECR[14:8]=REC, ECR[23:16]=CEL (not TEC) - Previous code read CEL and labelled it tec Narrow ISR mask window in processCanardTxQueueSafe: - Mask only covers canardPeekTxQueue/canardPopTxQueue (linked-list ops) - HAL transmit call now runs with ISR unmasked - Re-peek after transmit to detect if ISR already popped the frame F7 RxBuffer ISR safety: - writeIndex/readIndex now volatile to prevent compiler caching - Remove unused file-scope rxMsg variable - rxBufferPushFrame/PopFrame now int8_t and static - Log warning on RX buffer full instead of silently dropping Remove redundant lec & 0x7 mask in cliDronecan (already masked at population)
Move public canardSTM32* functions above static helpers in H7 and F7 drivers. Move dronecanInit/Update/Get* to the top of dronecan.c with forward declarations for internal callbacks. Mark rxBufferNumMessages static in F7 driver. Add ISR-context warning comment to processCanardTxQueue.
- processCanardTxQueueSafe: simplify by holding NVIC mask across transmit call, eliminating the pointer-identity ABA assumption - F7 rxBuffer: add __DMB() barriers between data write and index advance to satisfy C99 memory ordering between ISR and main loop - F7 ComputeTimings: align max_quanta_per_bit with H7 (17, not 18) per Koppe reference recommendation - H7 GetProtocolStatus: document why ECR is read directly vs HAL - H7 RecoverFromBusOff: clarify CCCR.INIT clear is defensive no-op - dronecanUpdate: replace dead STATE_DRONECAN_COUNT case with default - cli: use PRId32 for int32_t format specifiers; add <inttypes.h> - SITL: remove Doxygen blocks from private static helpers
- Make processCanardTxQueue, shouldAcceptTransfer, onTransferReceived static - Replace ISR LOG calls with volatile counters (txErrCount, rxDropCount); log and clear at 1Hz from main loop via canardSTM32GetAndClearRxDropCount() - Add canardSTM32GetAndClearRxDropCount() to driver interface; F7 implements ring-buffer drop counter, H7/SITL return 0 (no SW ring buffer) - Check canardBroadcast/canardRequestOrRespond return values; log on OOM - H7: set RxBuffersNbr=0 (dedicated buffer was unused, wasted message RAM) - H7: reject unmatched standard-ID frames (FDCAN_REJECT for NonMatchingStd) - F7: move NVIC_EnableIRQ calls after all ActivateNotification calls succeed - Fix F7 bxCAN Doxygen: correct @brief, remove wrong @PARAM, fix @RetVal - Fix all @RetVal docs: ret==0 is OK (CANARD_OK), not ret==1 - Cast pid_t to uint32_t before bit-shifting in SITL unique ID generation
- Wrap processCanardTxQueue in #if STM32H7||STM32F7 — function is ISR-only and has no callers in SITL builds; static + no callers caused -Werror=unused-function on CI - Atomic read-clear of txErrCount: hold dronecanMaskTxISR across snapshot+zero to prevent ISR increment being silently dropped - Atomic read-clear of rxDropCount: disable CAN1_RX0_IRQn across snapshot+zero in canardSTM32GetAndClearRxDropCount (F7) - Make all eight file-local handler functions static: send_NodeStatus, handle_NodeStatus, handle_GNSSAuxiliary, handle_GNSSFix, handle_GNSSFix2, handle_GNSSRCTMStream, handle_BatteryInfo, handle_GetNodeInfo - H7 global filter: FDCAN_REJECT_REMOTE for both RTR frame params (was FDCAN_FILTER_REMOTE which passed RTR frames to normal filter) - H7 Receive: add comment that DataLength==byte count holds only in FDCAN_FRAME_CLASSIC mode (FDCAN_DLC_BYTES_0..8 equal 0..8) - F7 ring buffer: use local index snapshots in push/pop to avoid double volatile re-reads of writeIndex/readIndex
- H7 Transmit: add FDCAN_FRAME_CLASSIC comment on DataLength assignment matching the comment already on the receive path - F7 init: add comment explaining pre-shifted timing register values - SITL: map RTR flag in sitlCANFrameToLinux/FromLinux, consistent with hardware drivers - SITL canardSTM32Transmit: add ERR frame guard matching hardware drivers - handle_GNSSRCTMStream: remove dead decode, add comment that RTCM forwarding is not yet implemented - dronecanInit: add default case to bitrate switch for EEPROM corruption - vendor_specific_status_code: explicit (uint16_t) cast with comment acknowledging bits 16-30 of armingFlags are not transmitted - fport.c: remove dead static volatile frameErrors counter (written but never read; triggered -Werror=unused-but-set-variable on GCC 16)
- H7 Receive: add bounds guard on DataLength before assignment to data_len (uint8_t); mirrors existing TX path guard; safe no-op in FDCAN_FRAME_CLASSIC mode but prevents silent truncation if DLC ever exceeds 8 - F7: fix stale comment hfdcan->ErrorCode -> hcan1.ErrorCode - dronecanInit: fix mixed tab/space indentation in canardInit() call - dronecanGetBitrateKbps: return 500 for DRONECAN_BITRATE_COUNT and default cases, matching what dronecanInit actually selects - Fix typo: incremeneted -> incremented - SITL GetRxFifoFillLevel: add comment explaining FIONREAD on SOCK_RAW returns next-datagram size only, so result is 0 or 1
FDCAN_FILTER_DUAL with FilterID1=0x0, FilterID2=0x1FFFFFFF only matched those two exact IDs. Replace with FDCAN_FILTER_MASK (pattern=0, mask=0) which accepts any extended ID. Also fix stale comments in H7 driver and dronecanInit.
…on bxCan (F7) targets. Set max quanta per bit to 18 unconditionally to fix 1MBps on bxCan.
17 tests covering canardSTM32ComputeTimings() algorithm at standard bitrates (125k/250k/500k/1M) for PCLK 54 MHz and 48 MHz. Includes an 18-quanta regression test that would fail against the old 10-quanta limit (prescaler=6, 9 tq/bit) and passes with the new unconditional 18-quanta path (prescaler=3, 18 tq/bit at 1 Mbps / 54 MHz).
- Wrap canard.c with USE_DRONECAN guard via platform.h include so the libcanard protocol engine is excluded from non-CAN targets (e.g. F722). Add comment noting both lines must be preserved on library updates. - Replace USE_GPS_PROTO_DRONECAN with USE_DRONECAN in gps.c and gps_dronecan.c; remove the define from common.h. GPS DroneCAN callbacks only make sense when CAN hardware is present. - Add IOCFG_AF_PP_FAST_UP (VERY_HIGH speed + PULLUP) to io.h for F7/H7, matching ST CubeF7 example recommendation for CAN GPIO pins. - Use IOCFG_AF_PP_FAST_UP for CAN1_TX and CAN1_RX in both the F7 bxCAN and H7 FDCAN drivers, replacing the previous LOW speed / no-pull config. - Add bus-off counter and canard pool allocator stats to dronecan driver and expose both in the CLI dronecan command.
Adds #include "platform.h" + #ifdef USE_DRONECAN to both canard_stm32f7xx_driver.c and canard_stm32h7xx_driver.c, preventing CAN1_RX0_IRQHandler and related code from linking into non-CAN targets.
|
Test firmware build ready — commit Download firmware for PR #11683 244 targets built. Find your board's
|
2 tasks
Contributor
Author
|
Companion configurator PR: iNavFlight/inav-configurator#2671 (draft) — adds the DroneCAN node tab UI for GetNodeInfo, GetSet, ExecuteOpcode, and RestartNode. The two should be reviewed/merged together. |
…sembly too Replace hand-rolled NVIC_DisableIRQ/EnableIRQ pairs with the existing ATOMIC_BLOCK(NVIC_PRIO_CAN) macro, which saves/restores the actual prior BASEPRI value instead of a manual counter, so nested critical sections (e.g. handle_GetNodeInfo's own masking, reached synchronously from within canardHandleRxFrame) compose correctly without risk of leaving the TX interrupt permanently masked. Also wrap canardHandleRxFrame() itself, which was previously unmasked and could race the TX-complete ISR's freeBlock() calls on the shared canard pool allocator during multi-frame RX reassembly.
canardSTM32ComputeTimings() was duplicated verbatim (aside from the PCLK source, SJW value, and BS1/BS2 register-offset convention) between the F7 bxCAN and H7 FDCAN drivers. Extract the HAL-free quanta/prescaler solve into canard_stm32_timing.c, shared by both; each driver now applies only its own peripheral-specific glue on top. bxcan_timing_unittest.cc previously hand-copied this algorithm into the test file, hardcoding max_quanta_per_bit=18 with a "keep in sync" comment. It drifted from the driver's real (target_bitrate >= 1000000) ? 10 : 17 within days of being written and was never updated. Rewritten to call the real, now-shared canardComputeCanTimingSolution() directly, so there's no separate copy to keep in sync.
Previously only checked that crcAddByte() changed its input at all (!= 0xFFFF, != 0x0000), which a subtly wrong polynomial or bit order would still satisfy. Assert the actual CRC-16/CCITT-FALSE value for a single byte instead.
# Conflicts: # src/main/io/gps.c # src/main/target/common.h
daijoubu
force-pushed
the
feature/dronecan-param-getset
branch
from
August 10, 2026 22:57
b2f2507 to
8f3f0d7
Compare
Add on-demand GetNodeInfo support: request a target node's software/ hardware version and name over DroneCAN, decode the response into the node table, and expose it to the configurator/CLI via MSP (MSP2_INAV_DRONECAN_NODE_INFO). This is the first on-demand (as opposed to broadcast-only) DroneCAN service request INAV makes - GetNodeInfo uses canardRequestOrRespond() under ATOMIC_BLOCK(NVIC_PRIO_CAN), matching the ISR masking the H7/F7 driver rework established for TX. MSP2_INAV_DRONECAN_NODE_INFO response grew to 71 bytes to carry the decoded version/name fields (docs/msp regenerated to match; MSP2_DRONECAN_NODE_INFO_SIZE replaces an inline field-count literal wherever the response size was checked, including the msp_protocol_v2_inav.h constant's own location, which moved out of fc_msp.c). Also: per-node transfer_id (rather than one shared counter across all nodes) so concurrent/overlapping GetNodeInfo requests to different nodes don't cross-contaminate; node name storage extended to 80 bytes with overflow logging; dronecanGetNodeByID() added to eliminate node-table lookups duplicated across handlers; bus-off recovery now gives up after 50 attempts and enters STATE_DRONECAN_FAILED instead of retrying forever. Full unit test suite passes: GetNodeInfo/SoftwareVersion/HardwareVersion/ RTCMStream response decode, shouldAcceptTransfer dispatch (GAP-S1/S2), and node-table tests. Squashed from the original feature/dronecan-getnodeinfo commit sequence (24 commits - the initial multi-phase implementation, several rounds of code-review fixups, and one rebase-artifact cleanup, "fixup: remove orphaned TX loop and duplicate process1HzTasks from rebase artifact" - into this single commit for a clean PR diff. No functional changes from the squash itself.
…ed async slot Extend on-demand DroneCAN service requests beyond GetNodeInfo to param GetSet, ExecuteOpcode, and RestartNode. All four services now share a single in-flight async request slot (dronecanAsyncSlot) rather than per-service state, since only one on-demand request is ever outstanding at a time in practice: dronecanAsyncRequest() encodes and sends whichever service's request (masked under ATOMIC_BLOCK against the CAN TX ISR), and one response handler decodes whichever service's response arrives, guarded by service_id/node_id/transfer_id matching so a stale or mismatched response can't be misattributed to the wrong in-flight request. A timeout (DRONECAN_ASYNC_TIMEOUT_MS) expires a request that never gets a response, so the slot can't wedge waiting forever. GetSet: full int/float/bool/string value union plus min/max NumericValue range, exposed through MSP so the configurator can read/write a remote node's parameters and see their valid range. ExecuteOpcode/RestartNode: simple ok/fail response, for triggering a remote node's save/erase opcodes or a restart. Full unit test suite passes: response-decode coverage for GetSet (int/float/bool/string/empty), ExecuteOpcode, and RestartNode, plus the async-slot dispatch tests (GAP-S2) updated for the new shared-slot architecture. Squashed from the original feature/dronecan-param-getset commit sequence (20 commits - the initial async-slot/GetSet/ExecuteOpcode/RestartNode implementation plus several rounds of code-review fixups) into this single commit for a clean PR diff. No functional changes from the squash itself.
…odule Split dronecanAsyncRequest() and the response handler (GetNodeInfo, ParamGetSet, ExecuteOpcode, RestartNode - a single shared slot serialising all on-demand service requests) out of dronecan.c into dronecan_async.c/.h. dronecanAsyncSlot's definition and the response handler move too; dronecan.h keeps declaring dronecanAsyncRequest()/ dronecanAsyncSlot since fc_msp.c is an external caller of both. dronecan.c's onTransferReceived() now calls dronecanAsyncHandleServiceResponse() (renamed from the static handle_AsyncServiceResponse for external linkage), and STATE_DRONECAN_NORMAL calls the new dronecanAsyncCheckTimeout() instead of carrying the timeout-expiry check inline. Also flips the file-scope `canard` CanardInstance from static to plain external linkage, since dronecan_async.c needs `extern CanardInstance canard` to reach it. (On the branch this was originally authored on, that linkage change had already landed earlier, as part of the DNA server work - rebasing this extraction back to sit directly on param-getset instead means picking it up here.) Cherry-picked from feature/dronecan-actuator-control (original commit e577393) onto feature/dronecan-param-getset: this is general dronecan.c restructuring in async-request/GetNodeInfo/ParamGetSet/ ExecuteOpcode/RestartNode territory - this branch's own scope - not actuator-control-specific, so it belongs here rather than riding along with unrelated actuator-output work. Full unit test suite (29 tests in dronecan_application_unittest, full suite otherwise unchanged) passes. SITL builds clean with -Werror.
daijoubu
force-pushed
the
feature/dronecan-param-getset
branch
from
August 17, 2026 02:10
f29d605 to
74a9d21
Compare
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
dronecanAsyncSlot) that serialises GetNodeInfo, param GetSet, ExecuteOpcode, and RestartNode requests through a single IDLE→PENDING→READY/ERROR state machine, avoiding per-service response queuesMSP2_INAV_DRONECAN_ASYNC_REQUEST/MSP2_INAV_DRONECAN_ASYNC_RESULT) so the configurator can read/write node parameters and trigger node restarts without custom DroneCAN toolingelapsed_ms(time since last NodeStatus)shouldAcceptTransferfilter, all four guard-rejection paths, all fiveparam.Valuetypes (INT/FLOAT/BOOL/STRING/EMPTY) with min/max range fields, ExecuteOpcode ok/fail, RestartNode, and the re-entry guardDependencies
42dabdc1a.Configurator branch:
daijoubu:feature/dronecan-configurator-tabcovers the UI for GetNodeInfo and param GetSet.Test plan
Scope note: this PR is stacked on unmerged #11607 (
fix/h7-dronecan-driver); driver-levelFDCAN/bxCAN changes are tested and tracked there. Below covers only what's new in this PR:
the GetSet parameter pending-slot mechanism.
Tooling note: the pending-slot state (IDLE/PENDING/READY/ERROR) is only exposed via raw
MSP2_INAV_DRONECAN_ASYNC_RESULT(0x2044) — the configurator UI hides these transitions andonly shows the final result. Items marked (raw MSP) require a scripted MSP client
(e.g. mspapi2), not the configurator.
Protocol note (found during hardware testing): writes require the parameter
namefieldalongside
index, not index alone — this node (and DroneCAN param.GetSet nodes generally)treats name-based addressing as required for writes even though index-only addressing is
accepted for reads. This matches the configurator's own encoder (
tabs/dronecan.js,buildParamGetSetPayload()), which always includesnamefor writes. This is DroneCAN/nodeprotocol behavior, not an INAV-specific quirk — noting it here since it isn't obvious from
the MSP message schema notes alone, and a future tester sending an index-only write could
easily mistake a silently-ignored write for a firmware bug (as happened during this PR's
own hardware testing).
b2f2507ca): F4 (MATEKF405), F7 (MATEKF765SE), H7 (KAKUTEH7WING), AT32 (IFLIGHT_BLITZ_ATF435), SITL (-DWARNINGS_AS_ERRORS=ON) — all pass, zero warningsFORMAT_VERSION=2 INT,BATT_CAPACITY=2200 INT)ExecuteOpcode(SAVE)to persistaccepted=1(busy) on the second, using an absent node ID to guarantee a real PENDING windowstate=READY; read it once, then poll RESULT again with no new REQUEST — confirmedstate=IDLE(post-read reset)state=IDLE(timeout-driven reset via absent node, no response ever arrived)