Repository navigation
Conversation
Each Drop impl loaded drop_not_ready and then stored it in a separate step. If the two parts were dropped at the same time from different priority levels, both could see true, and neither disabled the peripheral, its clock and its interrupt. Read and clear the flag in one atomic step with AtomicClear::clear(), which falls back to a critical section on thumbv6m (G0), where there is no atomic swap.
CR holds settings of both driver parts: the pull resistors and CC enables written by CcPhy::set_pull(), and PHYRXEN, TXMODE, TXSEND and TXHRST written by PdPhy. All of them used a plain modify(). With the two parts in executors of different priority, one could preempt the other between the read and the write and then write back stale bits, e.g. set_pull() turning PHYRXEN back on after PdPhy was dropped. TXSEND, TXHRST and FRSTX are also commands that the hardware clears once it acts on them. A modify() that read CR while TXSEND was still set and wrote it back after the hardware had cleared it would start the same transmission again, and likewise for a Hard Reset. Making the access atomic does not help against that, since the hardware, not software, changes the bit in between. Do every CR update through modify_cr(), which runs in a critical section and writes the command bits as 0 unless the caller sets them. Writing 0 to a command bit has no effect.
split_pd_phy() consumes the Ucpd and enables PD on one CC line for good. To go back after a detach, both halves have to be dropped, which turns UCPD off and removes the CC terminations, and Ucpd::new() has to be called again for the next attach. The partner sees that as an unplug, and the peripheral tokens have to be reborrowed or stolen. Add Ucpd::split_idle_pd_phy(), which splits the driver the same way but leaves PD disabled. IdlePdPhy::activate() selects the CC line and enables PD reception, and returns an ActivePdPhy guard that derefs to PdPhy for receive/transmit and disables reception again when dropped. The CC terminations are not touched by either. activate() also discards what a previous activation left behind (a received Hard Reset or message, and a byte left in RXDR), so the first reception after an attach doesn't return stale data. split_pd_phy() keeps its behavior; it now uses the same helpers. The drop and refcount logic is unchanged, as IdlePdPhy owns a PdPhy.
Runs on a NUCLEO-G474RE with the X-NUCLEO-DRP1M1 expansion board, which connects the USB-C port to UCPD1 through a TCPP03-M20. The example enables the TCPP03 over I2C, then detects attach and detach in a loop and enables PD on every attach with Ucpd::split_idle_pd_phy() and IdlePdPhy::activate(), without recreating the Ucpd.
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.
Depends on #7471 (uses
modify_cr).This PR contains the changes from #7471. See the individual commits for what is actually added by this PR. I will rebase and edit this message once #7471 is merged.
Adds a way to keep the UCPD driver alive across attach/detach cycles.
Today
split_pd_phyconsumes theUcpdand enables PD on one CC line for good. To go back after a detach, both halves have to be dropped, which disables UCPD and removes the CC terminations (the partner sees an unplug), andUcpd::newhas to be called again, requiring the peripheral tokens to be reborrowed or stolen.This PR adds:
Ucpd::split_idle_pd_phy(rx_dma, tx_dma, irqs) -> (CcPhy, IdlePdPhy): splits likesplit_pd_phy, but leaves PD disabled.IdlePdPhy::activate(&mut self, cc_sel) -> ActivePdPhy: selects the CC line and enables PD reception.ActivePdPhyderefs toPdPhyforreceive/transmit, and disables reception again when dropped. Stale RX state from a previous activation is discarded first.The CC terminations are never touched by enabling or disabling PD. The change is purely additive:
split_pd_phy,PdPhy,CcPhyand the error types are unchanged, and the drop/refcount behavior is the same, asIdlePdPhyowns aPdPhy. The guard follows the same pattern asResumablePeripheralGuard.A new example,
examples/stm32g474/src/bin/usb_c_pd.rs, runs CC detection and PD reception across repeated attach/detach cycles without recreatingUcpd. It targets a NUCLEO-G474RE with the X-NUCLEO-DRP1M1 expansion board, whose TCPP03-M20 is enabled over I2C at startup.Tested on a NUCLEO-G474RE with an X-NUCLEO-DRP1M1: PD reception in both cable orientations across repeated attach/detach cycles without recreating
Ucpd, including a PD session that ends before the detach (receive_messagesreturning after one message). Built for G0, G4, H5, U5, L5, H7RS and N6.