fix(trainer): SBUS trainer context ownership - #7699
Open
raphaelcoeffic wants to merge 2 commits into
Open
Conversation
The SBUS trainer receiver is a single consumer (trainerInput[]), so only one source can feed it at a time. Which one is decided by the trainer mode, but the two sources used to register on completely different lifecycles: the external module claimed the context when the trainer mode selected it, while an AUX serial port claimed it at port configuration time, from serialSetCallBacks(). That asymmetry let both be registered at once and left dangling contexts behind: - trainer_stop_module_sbus() never released the context, so after modulePortDeInit() zeroed the serial state the receiver was left pointing at a freed driver context. - conversely, re-configuring an AUX port that is in SBUS trainer mode cleared the context even when the external module trainer was the current owner, silently killing trainer input. Make the trainer own the context for both sources: sbusTrainerAcquire() claims it and arms the IDLE callback, sbusTrainerRelease() disarms and drops it, and both are driven from checkTrainerSettings()/stopTrainer(). Ordering is arm-last / disarm-first, so no callback can start once release() returns. Serial port teardown revokes via sbusTrainerReleaseCtx(), which only releases if that port is the current owner, and checkTrainerSettings() re-acquires when the port becomes usable again, so no caller of serialInit() needs to know about the trainer. Also: - stm32_usart_deinit(): NVIC_DisableIRQ() alone leaves an already latched IRQ pending, which would then be taken against a de-initialised, clock-gated peripheral. Add the barrier and clear the pending bit. - stm32_serial_deinit(): make de-init idempotent. - isTrainerModeAvailable(): TRAINER_MODE_MASTER_SERIAL ignored UART_MODE_SBUS_TRAINER_INV, so the mode was reported unavailable on radios using an inverted SBUS trainer port.
raphaelcoeffic
force-pushed
the
sbus-trainer-ownership
branch
from
August 23, 2026 10:11
52ce0f0 to
f9585a1
Compare
UART_MODE_SBUS_TRAINER_INV drives the USART into inverting RX itself, for ports that have no hardware inverter. That only exists on H5/H7, as stm32_serial_init() already reflects: elsewhere the polarity request is silently dropped and the port receives plain, non-inverted data. The mode is hidden from the port selection on such targets, but a configuration written on another radio still selects it, and the port was then offered as trainer input even though it cannot decode the signal. Restrict serialGetSbusTrainerPort() to the families that can actually invert, so the trainer and isTrainerModeAvailable() agree and no context is claimed on a port that cannot work.
Member
|
It looks like this overlaps #7696 ??? |
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.
The SBUS trainer receiver is a single consumer (
trainerInput[]), so only one source can feed it at a time. Which one is decided by the trainer mode, but the two sources used to register on completely different lifecycles: the external module claimed the context when the trainer mode selected it, while an AUX serial port claimed it at port configuration time, from serialSetCallBacks().That asymmetry let both be registered at once and left dangling contexts behind:
trainer_stop_module_sbus()never released the context, so aftermodulePortDeInit()zeroed the serial state the receiver was left pointing at a freed driver context.conversely, re-configuring an AUX port that is in SBUS trainer mode cleared the context even when the external module trainer was the current owner, silently killing trainer input.
Make the trainer own the context for both sources:
sbusTrainerAcquire()claims it and arms the IDLE callback,sbusTrainerRelease()disarms and drops it, and both are driven fromcheckTrainerSettings()/stopTrainer(). Ordering is arm-last / disarm-first, so no callback can start oncerelease()returns.Serial port teardown revokes via
sbusTrainerReleaseCtx(), which only releases if that port is the current owner, andcheckTrainerSettings()re-acquires when the port becomes usable again, so no caller ofserialInit()needs to know about the trainer.Also:
stm32_usart_deinit():NVIC_DisableIRQ()alone leaves an already latched IRQ pending, which would then be taken against a de-initialised, clock-gated peripheral. Add the barrier and clear the pending bit.stm32_serial_deinit(): make de-init idempotent.isTrainerModeAvailable():TRAINER_MODE_MASTER_SERIALignoredUART_MODE_SBUS_TRAINER_INV, so the mode was reported unavailable on radios using an inverted SBUS trainer port.Fixes #7644