[FEATURE] STM32: detect DMA stream oversubscription at build time

未关闭
#20,244 1 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

维护者通常 1 天内回复

还没有人认领这个 Issue。

评估

难度
4/5
预计耗时
3-5 天
新手友好度
45/100
Issue 类型
功能
描述清晰度
描述清楚
活跃度
活跃
技术栈
c

调研方向

The issue is in arch/arm/src/stm32 and common/stm32. Start by reading stm32_dmachannel() in stm32_dma.c and the DMAMUX allocators. Understand how CONFIG_* DMA enables and DMAMAP_* values are defined in board configurations. The goal is to add a compile-time check that sums enabled streams per DMA controller and errors if over capacity. Look at the H5 serial driver for the -EBUSY pattern. Done means the build fails with a clear error when streams are oversubscribed.

由索引模型根据 Issue 内容生成。

描述

Is your feature request related to a problem? Please describe.

On STM32H7, stm32_dmachannel() hands out the first free stream on the requested controller and returns NULL when none are left. The DMAMUX allocators in common/stm32 and the H5 GPDMA driver work the same way. Nothing checks at build time how many streams a configuration can hold at once, so a board that enables DMA on more peripherals than a controller has streams builds cleanly and fails at run time, depending on start order:

  • Of the serial drivers on these parts, only H5's checks the handle (it returns -EBUSY). On H7, up_dma_setup() passes it straight to stm32_dmasetup(), which dereferences it.
  • The H7 SPI driver only DEBUGASSERTs the handle. Its comment says stm32_dmachannel() blocks until a stream is free, which is F4/F7 behavior.
  • Whichever driver asks last loses. A UART that is opened only in some configurations (a telemetry or GPS port) can take the last stream and break a driver that worked on the bench.

Downstream in PX4 this has shown up as a board boot-looping with DMA on three UARTs, and as RC input dying once DShot telemetry took a stream (PX4/PX4-Autopilot#26112, PX4/PX4-Autopilot#24573, PX4/PX4-Autopilot#24920). Each time, the fix was turning off UART DMA by hand. Boards track the budget in comments, and the comments drift.

Describe the solution you'd like
  1. A compile-time budget per DMA controller. Every input is already an integer macro: the CONFIG_* DMA enables, the board's DMAMAP_* values, and DMAMAP_CONTROLLER(). A per-family header can sum the streams each enabled driver holds (serial RX/TX, SPI RX/TX, ADC, DAC, QSPI) per controller and #error when a sum exceeds the controller's stream count. No runtime cost and no API change.
  2. A board.h hook, e.g. BOARD_DMA1_NRESERVED, for streams allocated by board or out-of-tree code, and the per-controller sums exported as macros so out-of-tree code can add its own consumers to the check. PX4 allocates DMA outside NuttX for DShot and for its IO coprocessor link.
  3. Drivers return -EBUSY from setup when stm32_dmachannel() returns NULL, as the H5 serial driver already does, instead of dereferencing it. This is independent of 1 and 2 and can land first.

The count is conservative: a UART with DMA enabled counts even if nothing opens it, because whether it opens is usually runtime configuration. A board that deliberately overcommits needs an opt-out, so a Kconfig option could make the check a warning instead of an error.

I can do the H7 implementation if this direction is acceptable. The same approach applies to the other DMAMUX families and would fit in arch/arm/src/common/stm32 alongside the STM32 port unification (#19004).

Describe alternatives you've considered
  • Recording the owner in stm32_dmachannel() and dumping per-controller usage through procfs. Useful for debugging, but it still finds the problem only at run time.
  • Encoding a fixed stream in DMAMAP_* on DMAMUX parts, as on F4/F7. This makes allocation deterministic, but changes the map encoding and the allocator, and still needs a check that no two consumers share a stream.
  • Falling back to interrupt-driven I/O when allocation fails. The H7 serial DMA ops assume a valid handle and the per-port DMA channel fields are const, so this is a larger change than failing the open.
Verification
  • I have verified before submitting the report.
主要语言
C
星标
4.1k
派生
1.8k
平均合并
1 天 3 小时
30 天内合并 PR
833

环境准备

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

apache/nuttx 的其他 Issue

查看 apache/nuttx 的全部 Issue

相似的 Issue

更多 C Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。