feat(cli): warn when a UART's configured dmaopt loses its DMA claim - #1400
Conversation
serialUART() silently falls back to IRQ-driven mode when uartDmaClaim() loses a stream/channel to another peripheral, leaving no CLI or log signal. Cross-checks a resolved dmaopt against dmaGetOwner()'s live ownership state at both get/list time (printDmaoptEntry) and set time (cliDmaopt), printing a warning on mismatch. Closes emuflight#1388.
|
Important Review skippedAuto incremental reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
Included review availability: Your plan provides up to 4 included reviews per hour; 3 remain after this review. 📜 Recent review details⏰ Context from checks skipped due to timeout. (1)
🔇 Additional comments (2)
📝 WalkthroughWalkthroughThe CLI now checks live DMA ownership for UART DMA options. It ignores free streams and reports ownership mismatches that cause IRQ-driven fallback when listing or setting options. ChangesUART DMA diagnostics
Estimated code review effort: 2 (Simple) | ~10 minutes Merge Risk: ⚪ Minimal · up to This localized CLI change adds diagnostics for DMA claim conflicts without introducing an actionable merge-blocking risk. It is merge-ready after normal checks and review. Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@coderabbitai, AI generated comment Requesting analysis (not a full review) on two specific points in
|
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
echo '== Target file outlines =='
ast-grep outline src/main/interface/cli.c --match 'printDmaoptClaimStatus|printDmaoptEntry|cliDmaopt' --view expanded || true
ast-grep outline src/main/drivers/dma_stm32f4xx.c --items all --view expanded || true
ast-grep outline src/main/drivers/dma_stm32f7xx.c --items all --view expanded || true
ast-grep outline src/main/drivers/dma_stm32h7xx.c --items all --view expanded || true
echo '== CLI implementation and DMA status call sites =='
rg -n -C 12 'printDmaoptClaimStatus|dmaGetOwner\s*\(|dmaGetResourceIndex\s*\(|dmaGetIdentifier\s*\(' \
src/main/interface/cli.c src/main 2>/dev/null || true
echo '== UART initialization and DMA claim paths =='
rg -n -C 15 'serialUART\s*\(|uartDmaClaim\s*\(|dmaAllocate\s*\(|dmaEnable\s*\(' src/main \
-g '*.[ch]' 2>/dev/null || true
echo '== DMA function definitions and identifier validation =='
rg -n -C 10 'dmaGetIdentifier\s*\(|dmaGetOwner\s*\(|dmaGetResourceIndex\s*\(|dmaIdentifierIsValid\s*\(' \
src/main/drivers/dma_stm32f4xx.c \
src/main/drivers/dma_stm32f7xx.c \
src/main/drivers/dma_stm32h7xx.c \
src/main/drivers/dma_impl.h \
src/main/drivers/dma.h 2>/dev/null || trueLength of output: 192925 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo '== DMA request-map declarations, resolver, and macros =='
ast-grep outline src/main/drivers/dma_reqmap.c src/main/drivers/dma_reqmap_mcu.c src/main/drivers/dma_reqmap.h --items all --view expanded 2>/dev/null || true
rg -n -C 14 'dmaGetChannelSpecByPeripheral|dmaChannelSpec_t|DMA\(|dmaChannelSpec' \
src/main/drivers/dma_reqmap.c \
src/main/drivers/dma_reqmap_mcu.c \
src/main/drivers/dma_reqmap.h \
src/main/drivers/dma.h 2>/dev/null || true
echo '== Complete target DMA descriptor definitions =='
sed -n '30,76p' src/main/drivers/dma_stm32f4xx.c
sed -n '34,75p' src/main/drivers/dma_stm32f7xx.c
sed -n '37,76p' src/main/drivers/dma_stm32h7xx.c
echo '== UART request-map entries and relevant conditionals =='
rg -n -C 5 'DMA_PERIPH_UART_(RX|TX)' src/main/drivers/dma_reqmap_mcu.c 2>/dev/null || true
echo '== Exact DMA allocation return paths =='
sed -n '77,105p' src/main/drivers/dma_stm32f4xx.c
sed -n '87,115p' src/main/drivers/dma_stm32f7xx.c
sed -n '84,130p' src/main/drivers/dma_stm32h7xx.cLength of output: 35222
Conclusion: I found no issue in either point. The 🧠 Learnings usedYou are interacting with an AI system. |
dmaGetIdentifier() returning DMA_NONE means a reqmap table entry points at a stream missing from dmaDescriptors[]. It read identically to the benign OWNER_FREE case. Adds a distinct DMA MAP ERROR line for it. Collapses the two CLAIMED BY message branches into one shared format string, cutting duplicate string literals from flash. Closes emuflight#1388.
…stic (#1404) * test(cli): add host unit-test coverage for dmaopt claim-status diagnostic cli_unittest previously never compiled the STM32F4/F7/H7-gated dmaopt subsystem (cli_unittest_DEFINES had no MCU-family macro), so printDmaoptClaimStatus() (added by #1400) had zero host coverage. Add STM32F4 + USE_RESOURCE_MGMT to cli_unittest_DEFINES and drivers/resource.c to cli_unittest_SRC (real ownerNames table). Mark findDmaoptEntry()/printDmaoptClaimStatus() STATIC_UNIT_TESTED and cover its 5 branches: own-claim, OWNER_FREE, conflict with/without a resourceIndex suffix, and DMA_NONE/invalid identifier. Fix ioTag_t ioTagDefault = NULL in printResource(), unreachable via any existing target build but a host-clang pointer-to-integer error once USE_RESOURCE_MGMT compiles on host for the first time. * fix(test): use vsnprintf in tfp_sprintf stub for macOS CI macOS SDK marks vsprintf() deprecated under -Werror (-Wdeprecated-declarations), failing the test-macos.yml job. * test(cli): assert exact empty output for dmaopt no-warning branches OwnClaimPrintsNothing and FreeOwnerPrintsNothing only checked for absence of specific substrings, which would miss unexpected output. printDmaoptClaimStatus() returns before any print call on both early paths, so the captured output is exactly empty.
feat(cli): warn when a resource pin loses its timer claim (#1423) resourceTable/PG state on `resource` shows configured intent, not whether timerAllocate() actually won the pin at boot -- a losing driver returns before ever calling IOInit(), so `resource show` still displays the losing assignment as if it were live. Mirrors dmaopt's printDmaoptClaimStatus() (#1400): adds timerGetOwner()/ timerGetOwnerResourceIndex() to read timer_common.c's per-pin timerOwners[] state, and cross-checks it against each resourceTable entry at both `resource` (bare) and after a `resource <owner> <index> <pin>` set, printing a warning on mismatch. CodeRabbit analysis (2 passes) caught one real gap: the original owner-only match hid a same-owner/different-instance collision (e.g. two motor slots misconfigured to the same pin). Fixed by tracking resourceIndex alongside owner, mirroring dmaopt's dmaGetOwner()/ dmaGetResourceIndex() split. EF-original diagnostic, not a BF port -- BF has no equivalent for dmaopt, resource, or timer. Closes #1412.
AI Generated pull-request
Summary
serialUART()silently falls back to IRQ-driven mode when its DMA claim(
uartDmaClaim()/dmaAllocate()) loses a stream/channel to another peripheral at boot — no CLImessage, log entry, or other diagnostic exists anywhere (EF or BF, inherited design). PR #1384's
new
dmaCLI setter increased real user exposure to this by making it easy to configure admaoptvalue that collides with another peripheral's claim.Adds
printDmaoptClaimStatus()insrc/main/interface/cli.c, which cross-checks a resolveddmaoptstream againstdmaGetOwner()/dmaGetResourceIndex()— the same live bookkeepingdmaAllocate()/uartDmaClaim()already populate — and prints a# ... WARNING ...line onmismatch. Wired into both:
printDmaoptEntry()— thedma <device> <index>get path anddma <device> list/ baredma listdisplay pathcliDmaopt()— the set path, so adma UART_TX 1 <n>set gets an immediate proactive warningif the target stream is already held by something else
OWNER_FREE(stream never claimed by anyone) is treated as a no-op rather than a warning, sinceit's indistinguishable from "this UART slot isn't opened as a serial port this boot" — the
overwhelmingly common state for any board with unused UART indices.
Closes #1388.
Test plan
make test(unit tests) — 47 suites, 0 failuresmake HELIOSPRING TUNERCF405 SKYSTARSF405AIO PYRODRONEF7 FOXEERF722V4 FOXEERF405 APEXF7 TMOTORF7 STELLARH7DEV SITL— all succeed, 0 new warningsinvestigated, confirmed false positive — cited a SITL-only file never compiled where this
feature runs)
dd9d2b8, EmuFlight 0.4.3, MSP API 1.54), all threecode paths through
printDmaoptClaimStatus()exercised live via CLI:dma UART_TX 3 0(only option, resolves to DMA1 Stream 3, already held bySPI_SDI 2) →# UART_TX 3: WARNING stream held by SPI_SDI 2, not this UART -- expect IRQ-driven fallbackon both set and getOWNER_FREE(non-NONEvalue resolving to a genuinely-unclaimed stream):dma UART_TX 2 0(resolves to DMA1 Stream 6,
FREE) → no warningNONE:dma UART_TX 3 none→ no warningsaverun at any point; flash-persisted defaults untouchedSummary by CodeRabbit