31
31
32
32
#if CFG_TUSB_MCU == OPT_MCU_STM32G4
33
33
#include "stm32g4xx.h"
34
- #include "stm32g4xx_ll_dma.h" // for UCLP REQID
34
+ #include "stm32g4xx_ll_dma.h" // for UCPD REQID
35
35
#else
36
36
#error "Unsupported STM32 family"
37
37
#endif
@@ -62,9 +62,17 @@ enum {
62
62
#define PHY_ORDERED_SET_SOP_PP_DEBUG (PHY_SYNC1 | (PHY_RST2<<5u) | (PHY_SYNC3<<10u) | (PHY_SYNC2<<15u)) // SOP'' Debug Ordered set coding
63
63
64
64
65
- static uint8_t rx_buf [262 ] TU_ATTR_ALIGNED (4 );
66
- static uint8_t tx_buf [262 ] TU_ATTR_ALIGNED (4 );
67
- static uint32_t tx_index ;
65
+ static uint8_t const * _rx_buf ;
66
+
67
+ static tusb_pd_header_t _good_crc = {
68
+ .msg_type = TUSB_PD_CTRL_GOOD_CRC ,
69
+ .data_role = 0 , // UFP
70
+ .specs_rev = TUSB_PD_REV20 ,
71
+ .power_role = 0 , // Sink
72
+ .msg_id = 0 ,
73
+ .n_data_obj = 0 ,
74
+ .extended = 0
75
+ };
68
76
69
77
// address of DMA channel rx, tx for each port
70
78
#define CFG_TUC_STM32_DMA { { DMA1_Channel1_BASE, DMA1_Channel2_BASE } }
@@ -73,10 +81,10 @@ static uint32_t tx_index;
73
81
// DMA
74
82
//--------------------------------------------------------------------+
75
83
76
- static const uint32_t dma_addr_arr [TUP_TYPEC_RHPORTS_NUM ][2 ] = CFG_TUC_STM32_DMA ;
84
+ static const uint32_t _dma_addr_arr [TUP_TYPEC_RHPORTS_NUM ][2 ] = CFG_TUC_STM32_DMA ;
77
85
78
86
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 ];
87
+ return _dma_addr_arr [rhport ][is_rx ? 0 : 1 ];
80
88
}
81
89
82
90
static void dma_init (uint8_t rhport , bool is_rx ) {
@@ -133,10 +141,6 @@ TU_ATTR_ALWAYS_INLINE static inline void dma_stop(uint8_t rhport, bool is_rx) {
133
141
dma_ch -> CCR &= ~DMA_CCR_EN ;
134
142
}
135
143
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
144
TU_ATTR_ALWAYS_INLINE static inline void dma_tx_start (uint8_t rhport , void const * buf , uint16_t len ) {
141
145
UCPD1 -> TX_ORDSET = PHY_ORDERED_SET_SOP ;
142
146
UCPD1 -> TX_PAYSZ = len ;
@@ -147,35 +151,37 @@ TU_ATTR_ALWAYS_INLINE static inline void dma_tx_start(uint8_t rhport, void const
147
151
//
148
152
//--------------------------------------------------------------------+
149
153
150
-
151
154
bool tcd_init (uint8_t rhport , tusb_typec_port_type_t port_type ) {
152
155
(void ) rhport ;
153
156
154
157
// Init DMA for RX, TX
155
158
dma_init (rhport , true);
156
159
dma_init (rhport , false);
157
160
158
- // Initialization phase: CFG1
161
+ // Initialization phase: CFG1, detect all SOPs
159
162
UCPD1 -> CFG1 = (0x0d << UCPD_CFG1_HBITCLKDIV_Pos ) | (0x10 << UCPD_CFG1_IFRGAP_Pos ) | (0x07 << UCPD_CFG1_TRANSWIN_Pos ) |
160
163
(0x01 << UCPD_CFG1_PSC_UCPDCLK_Pos ) | (0x1f << UCPD_CFG1_RXORDSETEN_Pos );
161
164
UCPD1 -> CFG1 |= UCPD_CFG1_UCPDEN ;
162
165
163
166
// General programming sequence (with UCPD configured then enabled)
164
167
if (port_type == TUSB_TYPEC_PORT_SNK ) {
165
- // Enable both CC Phy
166
- UCPD1 -> CR = (0x01 << UCPD_CR_ANAMODE_Pos ) | UCPD_CR_CCENABLE_0 | UCPD_CR_CCENABLE_1 ;
168
+ // Set analog mode enable both CC Phy
169
+ UCPD1 -> CR = (0x01 << UCPD_CR_ANAMODE_Pos ) | ( UCPD_CR_CCENABLE_0 | UCPD_CR_CCENABLE_1 ) ;
167
170
168
171
// Read Voltage State on CC1 & CC2 fore initial state
169
- uint32_t vstate_cc [2 ];
170
- vstate_cc [0 ] = (UCPD1 -> SR >> UCPD_SR_TYPEC_VSTATE_CC1_Pos ) & 0x03 ;
171
- vstate_cc [1 ] = (UCPD1 -> SR >> UCPD_SR_TYPEC_VSTATE_CC2_Pos ) & 0x03 ;
172
+ uint32_t v_cc [2 ];
173
+ v_cc [0 ] = (UCPD1 -> SR >> UCPD_SR_TYPEC_VSTATE_CC1_Pos ) & 0x03 ;
174
+ v_cc [1 ] = (UCPD1 -> SR >> UCPD_SR_TYPEC_VSTATE_CC2_Pos ) & 0x03 ;
172
175
173
- TU_LOG1 ("Initial VState CC1 = %u, CC2 = %u\r\n" , vstate_cc [0 ], vstate_cc [1 ]);
176
+ TU_LOG1 ("Initial VState CC1 = %u, CC2 = %u\r\n" , v_cc [0 ], v_cc [1 ]);
174
177
175
178
// Enable CC1 & CC2 Interrupt
176
179
UCPD1 -> IMR = UCPD_IMR_TYPECEVT1IE | UCPD_IMR_TYPECEVT2IE ;
177
180
}
178
181
182
+ // Disable dead battery in PWR's CR3
183
+ PWR -> CR3 |= PWR_CR3_UCPD_DBDIS ;
184
+
179
185
return true;
180
186
}
181
187
@@ -192,9 +198,8 @@ void tcd_int_disable(uint8_t rhport) {
192
198
}
193
199
194
200
bool tcd_rx_start (uint8_t rhport , uint8_t * buffer , uint16_t total_bytes ) {
195
- (void ) rhport ;
196
- (void ) buffer ;
197
- (void ) total_bytes ;
201
+ _rx_buf = buffer ;
202
+ dma_start (rhport , true, buffer , total_bytes );
198
203
return true;
199
204
}
200
205
@@ -212,27 +217,28 @@ void tcd_int_handler(uint8_t rhport) {
212
217
sr &= UCPD1 -> IMR ;
213
218
214
219
if (sr & (UCPD_SR_TYPECEVT1 | UCPD_SR_TYPECEVT2 )) {
215
- uint32_t vstate_cc [2 ];
216
- vstate_cc [0 ] = (UCPD1 -> SR >> UCPD_SR_TYPEC_VSTATE_CC1_Pos ) & 0x03 ;
217
- vstate_cc [1 ] = (UCPD1 -> SR >> UCPD_SR_TYPEC_VSTATE_CC2_Pos ) & 0x03 ;
220
+ uint32_t v_cc [2 ];
221
+ v_cc [0 ] = (UCPD1 -> SR >> UCPD_SR_TYPEC_VSTATE_CC1_Pos ) & 0x03 ;
222
+ v_cc [1 ] = (UCPD1 -> SR >> UCPD_SR_TYPEC_VSTATE_CC2_Pos ) & 0x03 ;
218
223
219
- TU_LOG1 ("VState CC1 = %u, CC2 = %u\n" , vstate_cc [0 ], vstate_cc [1 ]);
224
+ TU_LOG3 ("VState CC1 = %u, CC2 = %u\n" , v_cc [0 ], v_cc [1 ]);
220
225
221
226
uint32_t cr = UCPD1 -> CR ;
222
227
223
228
// TODO only support SNK for now, required highest voltage for now
224
- // Enable PHY on correct CC and disable Rd on other CC
225
- if ((sr & UCPD_SR_TYPECEVT1 ) && (vstate_cc [0 ] == 3 )) {
226
- TU_LOG1 ("Attach CC1\n" );
227
-
229
+ // Enable PHY on active CC and disable Rd on other CC
230
+ // FIXME somehow CC2 is vstate is not correct, always 1 even not attached.
231
+ // on DPOW1 board, it is connected to PA10 (USBPD_DBCC2), we probably miss something.
232
+ if ((sr & UCPD_SR_TYPECEVT1 ) && (v_cc [0 ] == 3 )) {
233
+ TU_LOG3 ("Attach CC1\n" );
228
234
cr &= ~(UCPD_CR_PHYCCSEL | UCPD_CR_CCENABLE );
229
235
cr |= UCPD_CR_PHYRXEN | UCPD_CR_CCENABLE_0 ;
230
- } else if ((sr & UCPD_SR_TYPECEVT2 ) && (vstate_cc [1 ] == 3 )) {
231
- TU_LOG1 ("Attach CC2\n" );
236
+ } else if ((sr & UCPD_SR_TYPECEVT2 ) && (v_cc [1 ] == 3 )) {
237
+ TU_LOG3 ("Attach CC2\n" );
232
238
cr &= ~UCPD_CR_CCENABLE ;
233
239
cr |= (UCPD_CR_PHYCCSEL | UCPD_CR_PHYRXEN | UCPD_CR_CCENABLE_1 );
234
240
} else {
235
- TU_LOG1 ("Detach\n" );
241
+ TU_LOG3 ("Detach\n" );
236
242
cr &= ~UCPD_CR_PHYRXEN ;
237
243
cr |= UCPD_CR_CCENABLE_0 | UCPD_CR_CCENABLE_1 ;
238
244
}
@@ -241,14 +247,15 @@ void tcd_int_handler(uint8_t rhport) {
241
247
// Attached
242
248
UCPD1 -> IMR |= IMR_ATTACHED ;
243
249
UCPD1 -> CFG1 |= UCPD_CFG1_RXDMAEN | UCPD_CFG1_TXDMAEN ;
244
-
245
- dma_rx_start (rhport );
246
250
}else {
247
251
// Detached
248
252
UCPD1 -> CFG1 &= ~(UCPD_CFG1_RXDMAEN | UCPD_CFG1_TXDMAEN );
249
253
UCPD1 -> IMR &= ~IMR_ATTACHED ;
250
254
}
251
255
256
+ // notify stack
257
+ tcd_event_cc_changed (rhport , v_cc [0 ], v_cc [1 ], true);
258
+
252
259
UCPD1 -> CR = cr ;
253
260
254
261
// ack
@@ -258,6 +265,7 @@ void tcd_int_handler(uint8_t rhport) {
258
265
//------------- RX -------------//
259
266
if (sr & UCPD_SR_RXORDDET ) {
260
267
// SOP: Start of Packet.
268
+ TU_LOG3 ("SOP\n" );
261
269
// UCPD1->RX_ORDSET & UCPD_RX_ORDSET_RXORDSET_Msk;
262
270
263
271
// ack
@@ -266,48 +274,39 @@ void tcd_int_handler(uint8_t rhport) {
266
274
267
275
// Received full message
268
276
if (sr & UCPD_SR_RXMSGEND ) {
269
-
277
+ TU_LOG3 ( "RX MSG END\n" );
270
278
dma_stop (rhport , true);
271
279
272
- // Skip if CRC failed
273
- if (!(sr & UCPD_SR_RXERR )) {
274
- uint32_t payload_size = UCPD1 -> RX_PAYSZ ;
275
- // TU_LOG1("RXMSGEND: payload_size = %u, rx count = %u\n", payload_size, pd_rx_count);
276
-
277
- tusb_pd_header_t const * rx_header = (tusb_pd_header_t const * ) rx_buf ;
278
- (* (tusb_pd_header_t * ) tx_buf ) = (tusb_pd_header_t ) {
279
- .msg_type = TUSB_PD_CTRL_GOOD_CRC ,
280
- .data_role = 0 , // UFP
281
- .specs_rev = TUSB_PD_REV20 ,
282
- .power_role = 0 , // Sink
283
- .msg_id = rx_header -> msg_id ,
284
- .n_data_obj = 0 ,
285
- .extended = 0
286
- };
280
+ uint8_t result ;
287
281
282
+ if (!(sr & UCPD_SR_RXERR )) {
288
283
// response with good crc
289
- dma_tx_start ( rhport , tx_buf , 2 ) ;
290
-
284
+ _good_crc . msg_id = (( tusb_pd_header_t const * ) _rx_buf ) -> msg_id ;
285
+ dma_tx_start ( rhport , & _good_crc , 2 );
291
286
UCPD1 -> CR |= UCPD_CR_TXSEND ;
292
287
293
- // notify stack
288
+ result = XFER_RESULT_SUCCESS ;
289
+ }else {
290
+ // CRC failed
291
+ result = XFER_RESULT_FAILED ;
294
292
}
295
293
296
- // prepare next receive
297
- dma_rx_start (rhport );
294
+ // notify stack
295
+ tcd_event_rx_complete (rhport , UCPD1 -> RX_PAYSZ , result , true );
298
296
299
297
// ack
300
298
UCPD1 -> ICR = UCPD_ICR_RXMSGENDCF ;
301
299
}
302
300
303
301
if (sr & UCPD_SR_RXOVR ) {
304
- TU_LOG1 ("RXOVR\n" );
302
+ TU_LOG3 ("RXOVR\n" );
305
303
// ack
306
304
UCPD1 -> ICR = UCPD_ICR_RXOVRCF ;
307
305
}
308
306
309
307
//------------- TX -------------//
310
308
if (sr & UCPD_SR_TXMSGSENT ) {
309
+ TU_LOG3 ("TX MSG SENT\n" );
311
310
// all byte sent
312
311
dma_stop (rhport , false);
313
312
@@ -316,7 +315,7 @@ void tcd_int_handler(uint8_t rhport) {
316
315
}
317
316
318
317
if (sr & (UCPD_SR_TXMSGDISC | UCPD_SR_TXMSGABT | UCPD_SR_TXUND )) {
319
- TU_LOG1 ("TX Error\n" );
318
+ TU_LOG3 ("TX Error\n" );
320
319
dma_stop (rhport , false);
321
320
UCPD1 -> ICR = UCPD_SR_TXMSGDISC | UCPD_SR_TXMSGABT | UCPD_SR_TXUND ;
322
321
}
0 commit comments