28#if CFG_TUC_ENABLED && defined(TUP_USBIP_TYPEC_STM32)
32#if CFG_TUSB_MCU == OPT_MCU_STM32G4
33 #include "stm32g4xx.h"
34 #include "stm32g4xx_ll_dma.h"
36 #error "Unsupported STM32 family"
44 IMR_ATTACHED = UCPD_IMR_TXMSGDISCIE | UCPD_IMR_TXMSGSENTIE | UCPD_IMR_TXMSGABTIE | UCPD_IMR_TXUNDIE |
45 UCPD_IMR_RXHRSTDETIE | UCPD_IMR_RXOVRIE | UCPD_IMR_RXMSGENDIE | UCPD_IMR_RXORDDETIE |
46 UCPD_IMR_HRSTDISCIE | UCPD_IMR_HRSTSENTIE | UCPD_IMR_FRSEVTIE
49#define PHY_SYNC1 0x18u
50#define PHY_SYNC2 0x11u
51#define PHY_SYNC3 0x06u
56#define PHY_ORDERED_SET_SOP (PHY_SYNC1 | (PHY_SYNC1<<5u) | (PHY_SYNC1<<10u) | (PHY_SYNC2<<15u))
57#define PHY_ORDERED_SET_SOP_P (PHY_SYNC1 | (PHY_SYNC1<<5u) | (PHY_SYNC3<<10u) | (PHY_SYNC3<<15u))
58#define PHY_ORDERED_SET_SOP_PP (PHY_SYNC1 | (PHY_SYNC3<<5u) | (PHY_SYNC1<<10u) | (PHY_SYNC3<<15u))
59#define PHY_ORDERED_SET_HARD_RESET (PHY_RST1 | (PHY_RST1<<5u) | (PHY_RST1<<10u) | (PHY_RST2<<15u ))
60#define PHY_ORDERED_SET_CABLE_RESET (PHY_RST1 | (PHY_SYNC1<<5u) | (PHY_RST1<<10u) | (PHY_SYNC3<<15u))
61#define PHY_ORDERED_SET_SOP_P_DEBUG (PHY_SYNC1 | (PHY_RST2<<5u) | (PHY_RST2<<10u) | (PHY_SYNC3<<15u))
62#define PHY_ORDERED_SET_SOP_PP_DEBUG (PHY_SYNC1 | (PHY_RST2<<5u) | (PHY_SYNC3<<10u) | (PHY_SYNC2<<15u))
81#define CFG_TUC_STM32_DMA { { DMA1_Channel1_BASE, DMA1_Channel2_BASE } }
87static const uint32_t
_dma_addr_arr[TUP_TYPEC_RHPORTS_NUM][2] = CFG_TUC_STM32_DMA;
89TU_ATTR_ALWAYS_INLINE
static inline uint32_t
dma_get_addr(uint8_t rhport,
bool is_rx) {
93static void dma_init(uint8_t rhport,
bool is_rx) {
95 DMA_Channel_TypeDef* dma_ch = (DMA_Channel_TypeDef*) dma_addr;
100 dma_ch->CCR = DMA_CCR_MINC | DMA_CCR_PL_1;
101 dma_ch->CPAR = (uint32_t) &UCPD1->RXDR;
103 req_id = LL_DMAMUX_REQ_UCPD1_RX;
106 dma_ch->CCR = DMA_CCR_MINC | DMA_CCR_PL_1 | DMA_CCR_DIR;
107 dma_ch->CPAR = (uint32_t) &UCPD1->TXDR;
109 req_id = LL_DMAMUX_REQ_UCPD1_TX;
114 CH_DIFF = DMA1_Channel2_BASE - DMA1_Channel1_BASE
119 if (dma_addr > DMA2_BASE) {
120 mux_ch_num = 8 * ((dma_addr - DMA2_Channel1_BASE) / CH_DIFF);
124 mux_ch_num = (dma_addr - DMA1_Channel1_BASE) / CH_DIFF;
127 DMAMUX_Channel_TypeDef* mux_ch = DMAMUX1_Channel0 + mux_ch_num;
129 uint32_t mux_ccr = mux_ch->CCR & ~(DMAMUX_CxCR_DMAREQ_ID);
131 mux_ch->CCR = mux_ccr;
134TU_ATTR_ALWAYS_INLINE
static inline void dma_start(uint8_t rhport,
bool is_rx,
void const* buf, uint16_t len) {
135 DMA_Channel_TypeDef* dma_ch = (DMA_Channel_TypeDef*)
dma_get_addr(rhport, is_rx);
137 dma_ch->CMAR = (uint32_t) buf;
139 dma_ch->CCR |= DMA_CCR_EN;
142TU_ATTR_ALWAYS_INLINE
static inline void dma_stop(uint8_t rhport,
bool is_rx) {
143 DMA_Channel_TypeDef* dma_ch = (DMA_Channel_TypeDef*)
dma_get_addr(rhport, is_rx);
144 dma_ch->CCR &= ~DMA_CCR_EN;
147TU_ATTR_ALWAYS_INLINE
static inline bool dma_enabled(uint8_t rhport,
bool is_rx) {
148 DMA_Channel_TypeDef* dma_ch = (DMA_Channel_TypeDef*)
dma_get_addr(rhport, is_rx);
149 return dma_ch->CCR & DMA_CCR_EN;
152TU_ATTR_ALWAYS_INLINE
static inline void dma_tx_start(uint8_t rhport,
void const* buf, uint16_t len) {
153 UCPD1->TX_ORDSET = PHY_ORDERED_SET_SOP;
154 UCPD1->TX_PAYSZ = len;
156 UCPD1->CR |= UCPD_CR_TXSEND;
159TU_ATTR_ALWAYS_INLINE
static inline void dma_tx_stop(uint8_t rhport) {
175 UCPD1->CFG1 = (0x0d << UCPD_CFG1_HBITCLKDIV_Pos) | (0x10 << UCPD_CFG1_IFRGAP_Pos) | (0x07 << UCPD_CFG1_TRANSWIN_Pos) |
176 (0x01 << UCPD_CFG1_PSC_UCPDCLK_Pos) | (0x1f << UCPD_CFG1_RXORDSETEN_Pos);
177 UCPD1->CFG1 |= UCPD_CFG1_UCPDEN;
182 UCPD1->CR = (0x01 << UCPD_CR_ANAMODE_Pos) | (UCPD_CR_CCENABLE_0 | UCPD_CR_CCENABLE_1);
187 v_cc[0] = (UCPD1->SR >> UCPD_SR_TYPEC_VSTATE_CC1_Pos) & 0x03;
188 v_cc[1] = (UCPD1->SR >> UCPD_SR_TYPEC_VSTATE_CC2_Pos) & 0x03;
189 TU_LOG1(
"Initial VState CC1 = %lu, CC2 = %lu\r\n", v_cc[0], v_cc[1]);
192 UCPD1->IMR = UCPD_IMR_TYPECEVT1IE | UCPD_IMR_TYPECEVT2IE;
196 PWR->CR3 |= PWR_CR3_UCPD_DBDIS;
204 NVIC_EnableIRQ(UCPD1_IRQn);
210 NVIC_DisableIRQ(UCPD1_IRQn);
241 uint32_t sr = UCPD1->SR;
244 if (sr & (UCPD_SR_TYPECEVT1 | UCPD_SR_TYPECEVT2)) {
246 v_cc[0] = (UCPD1->SR >> UCPD_SR_TYPEC_VSTATE_CC1_Pos) & 0x03;
247 v_cc[1] = (UCPD1->SR >> UCPD_SR_TYPEC_VSTATE_CC2_Pos) & 0x03;
249 TU_LOG3(
"VState CC1 = %lu, CC2 = %lu\r\n", v_cc[0], v_cc[1]);
251 uint32_t cr = UCPD1->CR;
257 if ((sr & UCPD_SR_TYPECEVT1) && (v_cc[0] == 3)) {
258 TU_LOG3(
"Attach CC1\r\n");
259 cr &= ~(UCPD_CR_PHYCCSEL | UCPD_CR_CCENABLE);
260 cr |= UCPD_CR_PHYRXEN | UCPD_CR_CCENABLE_0;
261 }
else if ((sr & UCPD_SR_TYPECEVT2) && (v_cc[1] == 3)) {
262 TU_LOG3(
"Attach CC2\r\n");
263 cr &= ~UCPD_CR_CCENABLE;
264 cr |= (UCPD_CR_PHYCCSEL | UCPD_CR_PHYRXEN | UCPD_CR_CCENABLE_1);
266 TU_LOG3(
"Detach\r\n");
267 cr &= ~UCPD_CR_PHYRXEN;
268 cr |= UCPD_CR_CCENABLE_0 | UCPD_CR_CCENABLE_1;
271 if (cr & UCPD_CR_PHYRXEN) {
274 UCPD1->CFG1 |= UCPD_CFG1_RXDMAEN | UCPD_CFG1_TXDMAEN;
277 UCPD1->CFG1 &= ~(UCPD_CFG1_RXDMAEN | UCPD_CFG1_TXDMAEN);
278 UCPD1->IMR &= ~IMR_ATTACHED;
287 UCPD1->ICR = UCPD_ICR_TYPECEVT1CF | UCPD_ICR_TYPECEVT2CF;
291 if (sr & UCPD_SR_RXORDDET) {
297 UCPD1->ICR = UCPD_ICR_RXORDDETCF;
301 if (sr & UCPD_SR_RXMSGEND) {
302 TU_LOG3(
"RX MSG END\r\n");
309 if (!(sr & UCPD_SR_RXERR)) {
327 UCPD1->ICR = UCPD_ICR_RXMSGENDCF;
330 if (sr & UCPD_SR_RXOVR) {
331 TU_LOG3(
"RXOVR\r\n");
333 UCPD1->ICR = UCPD_ICR_RXOVRCF;
338 if (sr & (UCPD_SR_TXMSGSENT | (UCPD_SR_TXMSGDISC | UCPD_SR_TXMSGABT | UCPD_SR_TXUND))) {
345 if ( sr & UCPD_SR_TXMSGSENT ) {
346 TU_LOG3(
"TX MSG SENT\r\n");
349 UCPD1->ICR = UCPD_ICR_TXMSGSENTCF;
351 TU_LOG3(
"TX Error\r\n");
354 UCPD1->ICR = UCPD_SR_TXMSGDISC | UCPD_SR_TXMSGABT | UCPD_SR_TXUND;
AUDIO Channel Cluster Descriptor (4.1)
static TU_ATTR_ALWAYS_INLINE void tcd_event_tx_complete(uint8_t rhport, uint16_t xferred_bytes, uint8_t result, bool in_isr)
static TU_ATTR_ALWAYS_INLINE void tcd_event_cc_changed(uint8_t rhport, uint8_t cc1, uint8_t cc2, bool in_isr)
static TU_ATTR_ALWAYS_INLINE void tcd_event_rx_complete(uint8_t rhport, uint16_t xferred_bytes, uint8_t result, bool in_isr)
static TU_ATTR_ALWAYS_INLINE void dma_tx_stop(uint8_t rhport)
void tcd_int_handler(uint8_t rhport)
void tcd_int_disable(uint8_t rhport)
static uint16_t _tx_pending_bytes
static void dma_init(uint8_t rhport, bool is_rx)
static TU_ATTR_ALWAYS_INLINE void dma_start(uint8_t rhport, bool is_rx, void const *buf, uint16_t len)
static uint8_t const * _rx_buf
static TU_ATTR_ALWAYS_INLINE bool dma_enabled(uint8_t rhport, bool is_rx)
bool tcd_init(uint8_t rhport, uint32_t port_type)
static uint16_t _tx_xferring_bytes
static const uint32_t _dma_addr_arr[TUP_TYPEC_RHPORTS_NUM][2]
bool tcd_msg_receive(uint8_t rhport, uint8_t *buffer, uint16_t total_bytes)
static TU_ATTR_ALWAYS_INLINE uint32_t dma_get_addr(uint8_t rhport, bool is_rx)
void tcd_int_enable(uint8_t rhport)
static pd_header_t _good_crc
static uint8_t const * _tx_pending_buf
static TU_ATTR_ALWAYS_INLINE void dma_stop(uint8_t rhport, bool is_rx)
bool tcd_msg_send(uint8_t rhport, uint8_t const *buffer, uint16_t total_bytes)
static TU_ATTR_ALWAYS_INLINE void dma_tx_start(uint8_t rhport, void const *buf, uint16_t len)