Skip to content

Commit 8181d47

Browse files
committed
enable DMA for both pd rx, tx
1 parent 9c2a849 commit 8181d47

File tree

1 file changed

+108
-99
lines changed

1 file changed

+108
-99
lines changed

src/portable/st/typec/typec_stm32.c

Lines changed: 108 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131

3232
#if CFG_TUSB_MCU == OPT_MCU_STM32G4
3333
#include "stm32g4xx.h"
34-
#include "stm32g4xx_hal_dma.h"
34+
#include "stm32g4xx_ll_dma.h" // for UCLP REQID
3535
#else
3636
#error "Unsupported STM32 family"
3737
#endif
@@ -40,6 +40,12 @@
4040
//
4141
//--------------------------------------------------------------------+
4242

43+
enum {
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
47+
};
48+
4349
#define PHY_SYNC1 0x18u
4450
#define PHY_SYNC2 0x11u
4551
#define PHY_SYNC3 0x06u
@@ -57,55 +63,101 @@
5763

5864

5965
static uint8_t rx_buf[262] TU_ATTR_ALIGNED(4);
60-
static uint32_t rx_count = 0;
61-
6266
static uint8_t tx_buf[262] TU_ATTR_ALIGNED(4);
63-
static uint32_t tx_count;
67+
static uint32_t tx_index;
6468

65-
#define CFG_TUC_STM32_DMA_RX { DMA1_Channel1 }
66-
//#define CFG_TUC_STM32_DMA_TX { DMA1_Channel2 }
69+
// address of DMA channel rx, tx for each port
70+
#define CFG_TUC_STM32_DMA { { DMA1_Channel1_BASE, DMA1_Channel2_BASE } }
6771

68-
#ifdef CFG_TUC_STM32_DMA_RX
69-
static DMA_Channel_TypeDef* dma_rx_arr[TUP_TYPEC_RHPORTS_NUM] = CFG_TUC_STM32_DMA_RX;
72+
//--------------------------------------------------------------------+
73+
// DMA
74+
//--------------------------------------------------------------------+
7075

71-
TU_ATTR_ALWAYS_INLINE static inline
72-
void dma_rx_start(uint8_t rhport)
73-
{
74-
DMA_Channel_TypeDef* dma_rx_ch = dma_rx_arr[rhport];
76+
static const uint32_t dma_addr_arr[TUP_TYPEC_RHPORTS_NUM][2] = CFG_TUC_STM32_DMA;
7577

76-
dma_rx_ch->CMAR = (uint32_t) rx_buf;
77-
dma_rx_ch->CNDTR = sizeof(rx_buf);
78-
dma_rx_ch->CCR |= DMA_CCR_EN;
78+
TU_ATTR_ALWAYS_INLINE static inline uint32_t dma_get_addr(uint8_t rhport, bool is_rx) {
79+
return dma_addr_arr[rhport][is_rx ? 0 : 1];
7980
}
80-
#endif
8181

82-
#ifdef CFG_TUC_STM32_DMA_TX
83-
static DMA_Channel_TypeDef* dma_tx_arr[TUP_TYPEC_RHPORTS_NUM] = CFG_TUC_STM32_DMA_TX;
84-
#endif
82+
static void dma_init(uint8_t rhport, bool is_rx) {
83+
uint32_t dma_addr = dma_get_addr(rhport, is_rx);
84+
DMA_Channel_TypeDef* dma_ch = (DMA_Channel_TypeDef*) dma_addr;
85+
uint32_t req_id;
86+
87+
if (is_rx) {
88+
// Peripheral -> Memory, Memory inc, 8-bit, High priority
89+
dma_ch->CCR = DMA_CCR_MINC | DMA_CCR_PL_1;
90+
dma_ch->CPAR = (uint32_t) &UCPD1->RXDR;
91+
92+
req_id = LL_DMAMUX_REQ_UCPD1_RX;
93+
} else {
94+
// Memory -> Peripheral, Memory inc, 8-bit, High priority
95+
dma_ch->CCR = DMA_CCR_MINC | DMA_CCR_PL_1 | DMA_CCR_DIR;
96+
dma_ch->CPAR = (uint32_t) &UCPD1->TXDR;
97+
98+
req_id = LL_DMAMUX_REQ_UCPD1_TX;
99+
}
100+
101+
// find and set up mux channel TODO support mcu with multiple DMAMUXs
102+
enum {
103+
CH_DIFF = DMA1_Channel2_BASE - DMA1_Channel1_BASE
104+
};
105+
uint32_t mux_ch_num;
106+
107+
#ifdef DMA2_BASE
108+
if (dma_addr > DMA2_BASE) {
109+
mux_ch_num = 8 * ((dma_addr - DMA2_Channel1_BASE) / CH_DIFF);
110+
} else
111+
#endif
112+
{
113+
mux_ch_num = (dma_addr - DMA1_Channel1_BASE) / CH_DIFF;
114+
}
115+
116+
DMAMUX_Channel_TypeDef* mux_ch = DMAMUX1_Channel0 + mux_ch_num;
117+
118+
uint32_t mux_ccr = mux_ch->CCR & ~(DMAMUX_CxCR_DMAREQ_ID);
119+
mux_ccr |= req_id;
120+
mux_ch->CCR = mux_ccr;
121+
}
122+
123+
TU_ATTR_ALWAYS_INLINE static inline void dma_start(uint8_t rhport, bool is_rx, void const* buf, uint16_t len) {
124+
DMA_Channel_TypeDef* dma_ch = (DMA_Channel_TypeDef*) dma_get_addr(rhport, is_rx);
125+
126+
dma_ch->CMAR = (uint32_t) buf;
127+
dma_ch->CNDTR = len;
128+
dma_ch->CCR |= DMA_CCR_EN;
129+
}
130+
131+
TU_ATTR_ALWAYS_INLINE static inline void dma_stop(uint8_t rhport, bool is_rx) {
132+
DMA_Channel_TypeDef* dma_ch = (DMA_Channel_TypeDef*) dma_get_addr(rhport, is_rx);
133+
dma_ch->CCR &= ~DMA_CCR_EN;
134+
}
135+
136+
TU_ATTR_ALWAYS_INLINE static inline void dma_rx_start(uint8_t rhport) {
137+
dma_start(rhport, true, rx_buf, sizeof(rx_buf));
138+
}
139+
140+
TU_ATTR_ALWAYS_INLINE static inline void dma_tx_start(uint8_t rhport, void const* buf, uint16_t len) {
141+
UCPD1->TX_ORDSET = PHY_ORDERED_SET_SOP;
142+
UCPD1->TX_PAYSZ = len;
143+
dma_start(rhport, false, buf, len);
144+
}
85145

86146
//--------------------------------------------------------------------+
87147
//
88148
//--------------------------------------------------------------------+
89-
#include "stm32g4xx_ll_dma.h"
149+
90150

91151
bool tcd_init(uint8_t rhport, tusb_typec_port_type_t port_type) {
92152
(void) rhport;
93153

94-
#ifdef CFG_TUC_STM32_DMA_RX
95-
// Init DMA
96-
DMA_Channel_TypeDef* dma_rx_ch = dma_rx_arr[rhport];
97-
98-
// Peripheral -> Memory, Memory inc, 8-bit, High priority
99-
dma_rx_ch->CCR = DMA_CCR_MINC | DMA_CCR_PL_1;
100-
dma_rx_ch->CPAR = (uint32_t) &UCPD1->RXDR;
101-
102-
LL_DMA_SetPeriphRequest(DMA1, LL_DMA_CHANNEL_1, LL_DMAMUX_REQ_UCPD1_RX);
103-
#endif
154+
// Init DMA for RX, TX
155+
dma_init(rhport, true);
156+
dma_init(rhport, false);
104157

105158
// Initialization phase: CFG1
106159
UCPD1->CFG1 = (0x0d << UCPD_CFG1_HBITCLKDIV_Pos) | (0x10 << UCPD_CFG1_IFRGAP_Pos) | (0x07 << UCPD_CFG1_TRANSWIN_Pos) |
107-
(0x01 << UCPD_CFG1_PSC_UCPDCLK_Pos) | (0x1f << UCPD_CFG1_RXORDSETEN_Pos) |
108-
(0 << UCPD_CFG1_TXDMAEN_Pos) | (0 << UCPD_CFG1_RXDMAEN_Pos);
160+
(0x01 << UCPD_CFG1_PSC_UCPDCLK_Pos) | (0x1f << UCPD_CFG1_RXORDSETEN_Pos);
109161
UCPD1->CFG1 |= UCPD_CFG1_UCPDEN;
110162

111163
// General programming sequence (with UCPD configured then enabled)
@@ -118,8 +170,7 @@ bool tcd_init(uint8_t rhport, tusb_typec_port_type_t port_type) {
118170
vstate_cc[0] = (UCPD1->SR >> UCPD_SR_TYPEC_VSTATE_CC1_Pos) & 0x03;
119171
vstate_cc[1] = (UCPD1->SR >> UCPD_SR_TYPEC_VSTATE_CC2_Pos) & 0x03;
120172

121-
TU_LOG1_INT(vstate_cc[0]);
122-
TU_LOG1_INT(vstate_cc[1]);
173+
TU_LOG1("Initial VState CC1 = %u, CC2 = %u\r\n", vstate_cc[0], vstate_cc[1]);
123174

124175
// Enable CC1 & CC2 Interrupt
125176
UCPD1->IMR = UCPD_IMR_TYPECEVT1IE | UCPD_IMR_TYPECEVT2IE;
@@ -142,7 +193,8 @@ void tcd_int_disable(uint8_t rhport) {
142193

143194
bool tcd_rx_start(uint8_t rhport, uint8_t* buffer, uint16_t total_bytes) {
144195
(void) rhport;
145-
196+
(void) buffer;
197+
(void) total_bytes;
146198
return true;
147199
}
148200

@@ -159,8 +211,6 @@ void tcd_int_handler(uint8_t rhport) {
159211
uint32_t sr = UCPD1->SR;
160212
sr &= UCPD1->IMR;
161213

162-
// TU_LOG1("UCPD1_IRQHandler: sr = 0x%08X\n", sr);
163-
164214
if (sr & (UCPD_SR_TYPECEVT1 | UCPD_SR_TYPECEVT2)) {
165215
uint32_t vstate_cc[2];
166216
vstate_cc[0] = (UCPD1->SR >> UCPD_SR_TYPEC_VSTATE_CC1_Pos) & 0x03;
@@ -169,7 +219,6 @@ void tcd_int_handler(uint8_t rhport) {
169219
TU_LOG1("VState CC1 = %u, CC2 = %u\n", vstate_cc[0], vstate_cc[1]);
170220

171221
uint32_t cr = UCPD1->CR;
172-
uint32_t cfg1 = UCPD1->CFG1;
173222

174223
// TODO only support SNK for now, required highest voltage for now
175224
// Enable PHY on correct CC and disable Rd on other CC
@@ -189,28 +238,18 @@ void tcd_int_handler(uint8_t rhport) {
189238
}
190239

191240
if (cr & UCPD_CR_PHYRXEN) {
192-
// Enable Interrupt
193-
uint32_t imr = UCPD1->IMR;
194-
imr |= UCPD_IMR_TXMSGDISCIE | UCPD_IMR_TXMSGSENTIE | UCPD_IMR_TXMSGABTIE | UCPD_IMR_TXUNDIE |
195-
UCPD_IMR_RXHRSTDETIE | UCPD_IMR_RXOVRIE | UCPD_IMR_RXMSGENDIE | UCPD_IMR_RXORDDETIE |
196-
UCPD_IMR_HRSTDISCIE | UCPD_IMR_HRSTSENTIE | UCPD_IMR_FRSEVTIE;
197-
198-
#ifdef CFG_TUC_STM32_DMA_RX
199-
cfg1 |= UCPD_CFG1_RXDMAEN;
200-
dma_rx_start(rhport);
201-
#else
202-
imr |= UCPD_IMR_RXNEIE | UCPD_IMR_RXORDDETIE;
203-
#endif
241+
// Attached
242+
UCPD1->IMR |= IMR_ATTACHED;
243+
UCPD1->CFG1 |= UCPD_CFG1_RXDMAEN | UCPD_CFG1_TXDMAEN;
204244

205-
#ifndef CFG_TUC_STM32_DMA_TX
206-
imr |= UCPD_IMR_TXISIE;
207-
#endif
208-
209-
UCPD1->IMR = imr;
245+
dma_rx_start(rhport);
246+
}else {
247+
// Detached
248+
UCPD1->CFG1 &= ~(UCPD_CFG1_RXDMAEN | UCPD_CFG1_TXDMAEN);
249+
UCPD1->IMR &= ~IMR_ATTACHED;
210250
}
211251

212252
UCPD1->CR = cr;
213-
UCPD1->CFG1 = cfg1;
214253

215254
// ack
216255
UCPD1->ICR = UCPD_ICR_TYPECEVT1CF | UCPD_ICR_TYPECEVT2CF;
@@ -221,27 +260,15 @@ void tcd_int_handler(uint8_t rhport) {
221260
// SOP: Start of Packet.
222261
// UCPD1->RX_ORDSET & UCPD_RX_ORDSET_RXORDSET_Msk;
223262

224-
// reset count when received SOP
225-
rx_count = 0;
226-
227263
// ack
228264
UCPD1->ICR = UCPD_ICR_RXORDDETCF;
229265
}
230266

231-
#ifndef CFG_TUC_STM32_DMA_RX
232-
if (sr & UCPD_SR_RXNE) {
233-
// TODO DMA later
234-
do {
235-
rx_buf[rx_count++] = UCPD1->RXDR;
236-
} while (UCPD1->SR & UCPD_SR_RXNE);
237-
238-
// no ack needed
239-
}
240-
#endif
241-
242267
// Received full message
243268
if (sr & UCPD_SR_RXMSGEND) {
244269

270+
dma_stop(rhport, true);
271+
245272
// Skip if CRC failed
246273
if (!(sr & UCPD_SR_RXERR)) {
247274
uint32_t payload_size = UCPD1->RX_PAYSZ;
@@ -251,26 +278,23 @@ void tcd_int_handler(uint8_t rhport) {
251278
(*(tusb_pd_header_t*) tx_buf) = (tusb_pd_header_t) {
252279
.msg_type = TUSB_PD_CTRL_GOOD_CRC,
253280
.data_role = 0, // UFP
254-
.specs_rev = TUSB_PD_REV30,
281+
.specs_rev = TUSB_PD_REV20,
255282
.power_role = 0, // Sink
256283
.msg_id = rx_header->msg_id,
257284
.n_data_obj = 0,
258285
.extended = 0
259286
};
260-
tx_count = 0;
261287

262288
// response with good crc
263-
UCPD1->TX_ORDSET = PHY_ORDERED_SET_SOP;
264-
UCPD1->TX_PAYSZ = 2;
265-
UCPD1->CR |= UCPD_CR_TXSEND; // will trigger TXIS interrupt
289+
dma_tx_start(rhport, tx_buf, 2);
290+
291+
UCPD1->CR |= UCPD_CR_TXSEND;
266292

267-
// notify stack after good crc ?
293+
// notify stack
268294
}
269295

270-
#ifdef CFG_TUC_STM32_DMA_RX
271296
// prepare next receive
272297
dma_rx_start(rhport);
273-
#endif
274298

275299
// ack
276300
UCPD1->ICR = UCPD_ICR_RXMSGENDCF;
@@ -283,34 +307,19 @@ void tcd_int_handler(uint8_t rhport) {
283307
}
284308

285309
//------------- TX -------------//
286-
if (sr & UCPD_SR_TXIS) {
287-
// TU_LOG1("TXIS\n");
288-
289-
// TODO DMA later
290-
do {
291-
UCPD1->TXDR = tx_buf[tx_count++];
292-
} while (UCPD1->SR & UCPD_SR_TXIS);
293-
294-
// no ack needed
295-
}
296-
297310
if (sr & UCPD_SR_TXMSGSENT) {
298311
// all byte sent
299-
TU_LOG1("TXMSGSENT\n");
312+
dma_stop(rhport, false);
300313

301314
// ack
302315
UCPD1->ICR = UCPD_ICR_TXMSGSENTCF;
303316
}
304317

305-
// if (sr & UCPD_SR_RXNE) {
306-
// uint8_t data = UCPD1->RXDR;
307-
// pd_rx_buf[pd_rx_count++] = data;
308-
// TU_LOG1_HEX(data);
309-
// }
310-
311-
// else {
312-
// TU_LOG_LOCATION();
313-
// }
318+
if (sr & (UCPD_SR_TXMSGDISC | UCPD_SR_TXMSGABT | UCPD_SR_TXUND)) {
319+
TU_LOG1("TX Error\n");
320+
dma_stop(rhport, false);
321+
UCPD1->ICR = UCPD_SR_TXMSGDISC | UCPD_SR_TXMSGABT | UCPD_SR_TXUND;
322+
}
314323
}
315324

316325
#endif

0 commit comments

Comments
 (0)