Skip to content

Commit debde4c

Browse files
committed
response with request safe5v, get passed PS_READY
1 parent bb4fb05 commit debde4c

File tree

5 files changed

+180
-18
lines changed

5 files changed

+180
-18
lines changed

src/common/tusb_types.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -562,6 +562,16 @@ enum {
562562
TUSB_PD_REV30 = 0x2,
563563
};
564564

565+
enum {
566+
TUSB_PD_DATA_ROLE_UFP = 0x0,
567+
TUSB_PD_DATA_ROLE_DFP = 0x1,
568+
};
569+
570+
enum {
571+
TUSB_PD_POWER_ROLE_SINK = 0x0,
572+
TUSB_PD_POWER_ROLE_SOURCE = 0x1,
573+
};
574+
565575
typedef struct TU_ATTR_PACKED {
566576
uint16_t msg_type : 5; // [0:4]
567577
uint16_t data_role : 1; // [5] SOP only: 0 UFP, 1 DFP

src/portable/st/typec/typec_stm32.c

Lines changed: 62 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ enum {
6363

6464

6565
static uint8_t const* _rx_buf;
66+
static uint8_t const* _tx_pending_buf;
67+
static uint16_t _tx_pending_bytes;
68+
static uint16_t _tx_xferring_bytes;
6669

6770
static tusb_pd_header_t _good_crc = {
6871
.msg_type = TUSB_PD_CTRL_GOOD_CRC,
@@ -141,10 +144,21 @@ TU_ATTR_ALWAYS_INLINE static inline void dma_stop(uint8_t rhport, bool is_rx) {
141144
dma_ch->CCR &= ~DMA_CCR_EN;
142145
}
143146

147+
TU_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;
150+
}
151+
152+
144153
TU_ATTR_ALWAYS_INLINE static inline void dma_tx_start(uint8_t rhport, void const* buf, uint16_t len) {
145154
UCPD1->TX_ORDSET = PHY_ORDERED_SET_SOP;
146155
UCPD1->TX_PAYSZ = len;
147156
dma_start(rhport, false, buf, len);
157+
UCPD1->CR |= UCPD_CR_TXSEND;
158+
}
159+
160+
TU_ATTR_ALWAYS_INLINE static inline void dma_tx_stop(uint8_t rhport) {
161+
dma_stop(rhport, false);
148162
}
149163

150164
//--------------------------------------------------------------------+
@@ -203,11 +217,23 @@ bool tcd_rx_start(uint8_t rhport, uint8_t* buffer, uint16_t total_bytes) {
203217
return true;
204218
}
205219

206-
bool tcd_tx_start(uint8_t rhport, uint8_t const* buffer, uint16_t total_bytes) {
220+
bool tcd_msg_send(uint8_t rhport, uint8_t const* buffer, uint16_t total_bytes) {
207221
(void) rhport;
208-
(void) buffer;
209-
(void) total_bytes;
210-
return false;
222+
223+
if (dma_enabled(rhport, false)) {
224+
// DMA is busy, probably sending GoodCRC, save as pending TX
225+
_tx_pending_buf = buffer;
226+
_tx_pending_bytes = total_bytes;
227+
}else {
228+
// DMA is free, start sending
229+
_tx_pending_buf = NULL;
230+
_tx_pending_bytes = 0;
231+
232+
_tx_xferring_bytes = total_bytes;
233+
dma_tx_start(rhport, buffer, total_bytes);
234+
}
235+
236+
return true;
211237
}
212238

213239
void tcd_int_handler(uint8_t rhport) {
@@ -275,6 +301,8 @@ void tcd_int_handler(uint8_t rhport) {
275301
// Received full message
276302
if (sr & UCPD_SR_RXMSGEND) {
277303
TU_LOG3("RX MSG END\n");
304+
305+
// stop TX
278306
dma_stop(rhport, true);
279307

280308
uint8_t result;
@@ -283,7 +311,6 @@ void tcd_int_handler(uint8_t rhport) {
283311
// response with good crc
284312
_good_crc.msg_id = ((tusb_pd_header_t const*) _rx_buf)->msg_id;
285313
dma_tx_start(rhport, &_good_crc, 2);
286-
UCPD1->CR |= UCPD_CR_TXSEND;
287314

288315
result = XFER_RESULT_SUCCESS;
289316
}else {
@@ -305,19 +332,38 @@ void tcd_int_handler(uint8_t rhport) {
305332
}
306333

307334
//------------- TX -------------//
308-
if (sr & UCPD_SR_TXMSGSENT) {
309-
TU_LOG3("TX MSG SENT\n");
310-
// all byte sent
311-
dma_stop(rhport, false);
335+
// All tx events: complete and error
336+
if (sr & (UCPD_SR_TXMSGSENT | (UCPD_SR_TXMSGDISC | UCPD_SR_TXMSGABT | UCPD_SR_TXUND))) {
337+
// force TX stop
338+
dma_tx_stop(rhport);
312339

313-
// ack
314-
UCPD1->ICR = UCPD_ICR_TXMSGSENTCF;
315-
}
340+
uint16_t const xferred_bytes = _tx_xferring_bytes - UCPD1->TX_PAYSZ;
341+
uint8_t result;
316342

317-
if (sr & (UCPD_SR_TXMSGDISC | UCPD_SR_TXMSGABT | UCPD_SR_TXUND)) {
318-
TU_LOG3("TX Error\n");
319-
dma_stop(rhport, false);
320-
UCPD1->ICR = UCPD_SR_TXMSGDISC | UCPD_SR_TXMSGABT | UCPD_SR_TXUND;
343+
if ( sr & UCPD_SR_TXMSGSENT ) {
344+
TU_LOG3("TX MSG SENT\n");
345+
result = XFER_RESULT_SUCCESS;
346+
// ack
347+
UCPD1->ICR = UCPD_ICR_TXMSGSENTCF;
348+
}else {
349+
TU_LOG3("TX Error\n");
350+
result = XFER_RESULT_FAILED;
351+
// ack
352+
UCPD1->ICR = UCPD_SR_TXMSGDISC | UCPD_SR_TXMSGABT | UCPD_SR_TXUND;
353+
}
354+
355+
// start pending TX if any
356+
if (_tx_pending_buf && _tx_pending_bytes ) {
357+
// Start the pending TX
358+
dma_tx_start(rhport, _tx_pending_buf, _tx_pending_bytes);
359+
360+
// clear pending
361+
_tx_pending_buf = NULL;
362+
_tx_pending_bytes = 0;
363+
}
364+
365+
// notify stack
366+
tcd_event_tx_complete(rhport, xferred_bytes, result, true);
321367
}
322368
}
323369

src/typec/tcd.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ enum {
4343
TCD_EVENT_INVALID = 0,
4444
TCD_EVENT_CC_CHANGED,
4545
TCD_EVENT_RX_COMPLETE,
46+
TCD_EVENT_TX_COMPLETE,
4647
};
4748

4849

@@ -84,7 +85,7 @@ void tcd_int_handler(uint8_t rhport);
8485
//--------------------------------------------------------------------+
8586

8687
bool tcd_rx_start(uint8_t rhport, uint8_t* buffer, uint16_t total_bytes);
87-
bool tcd_tx_start(uint8_t rhport, uint8_t const* buffer, uint16_t total_bytes);
88+
bool tcd_msg_send(uint8_t rhport, uint8_t const* buffer, uint16_t total_bytes);
8889

8990
//--------------------------------------------------------------------+
9091
// Event API (implemented by stack)
@@ -120,4 +121,18 @@ void tcd_event_rx_complete(uint8_t rhport, uint16_t xferred_bytes, uint8_t resul
120121
tcd_event_handler(&event, in_isr);
121122
}
122123

124+
TU_ATTR_ALWAYS_INLINE static inline
125+
void tcd_event_tx_complete(uint8_t rhport, uint16_t xferred_bytes, uint8_t result, bool in_isr) {
126+
tcd_event_t event = {
127+
.rhport = rhport,
128+
.event_id = TCD_EVENT_TX_COMPLETE,
129+
.rx_complete = {
130+
.xferred_bytes = xferred_bytes,
131+
.result = result
132+
}
133+
};
134+
135+
tcd_event_handler(&event, in_isr);
136+
}
137+
123138
#endif

src/typec/utcd.c

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ static bool _port_inited[TUP_TYPEC_RHPORTS_NUM];
5353

5454
// Max possible PD size is 262 bytes
5555
static uint8_t _rx_buf[262] TU_ATTR_ALIGNED(4);
56+
static uint8_t _tx_buf[100] TU_ATTR_ALIGNED(4);
5657

5758
//--------------------------------------------------------------------+
5859
//
@@ -90,6 +91,19 @@ bool tuc_init(uint8_t rhport, tusb_typec_port_type_t port_type) {
9091
//
9192
//--------------------------------------------------------------------+
9293

94+
bool utcd_msg_send(uint8_t rhport, tusb_pd_header_t const* header, void const* data) {
95+
// copy header
96+
memcpy(_tx_buf, header, sizeof(tusb_pd_header_t));
97+
98+
// copy data objcet if available
99+
uint16_t const n_data_obj = header->n_data_obj;
100+
if (n_data_obj > 0) {
101+
memcpy(_tx_buf + sizeof(tusb_pd_header_t), data, n_data_obj * 4);
102+
}
103+
104+
return tcd_msg_send(rhport, _tx_buf, sizeof(tusb_pd_header_t) + n_data_obj * 4);
105+
}
106+
93107
bool parse_message(uint8_t rhport, uint8_t const* buf, uint16_t len) {
94108
(void) rhport;
95109
uint8_t const* p_end = buf + len;
@@ -98,10 +112,28 @@ bool parse_message(uint8_t rhport, uint8_t const* buf, uint16_t len) {
98112

99113
if (header->n_data_obj == 0) {
100114
// control message
115+
switch (header->msg_type) {
116+
case TUSB_PD_CTRL_GOOD_CRC:
117+
break;
118+
119+
case TUSB_PD_CTRL_ACCEPT:
120+
break;
121+
122+
case TUSB_PD_CTRL_REJECT:
123+
break;
124+
125+
case TUSB_PD_CTRL_PS_RDY:
126+
break;
127+
128+
default: break;
129+
}
101130
} else {
102131
// data message
103132
switch (header->msg_type) {
104133
case TUSB_PD_DATA_SOURCE_CAP: {
134+
// Examine source capability and select a suitable PDO (starting from 1 with safe5v)
135+
uint8_t obj_pos = 1;
136+
105137
for(size_t i=0; i<header->n_data_obj; i++) {
106138
TU_VERIFY(ptr < p_end);
107139
uint32_t const pdo = tu_le32toh(tu_unaligned_read32(ptr));
@@ -125,6 +157,33 @@ bool parse_message(uint8_t rhport, uint8_t const* buf, uint16_t len) {
125157

126158
ptr += 4;
127159
}
160+
161+
// Send request with selected PDO position as response to Source Cap
162+
pd_rdo_fixed_variable_t rdo = {
163+
.current_extremum_10ma = 50, // max 500mA
164+
.current_operate_10ma = 30, // 300mA
165+
.reserved = 0,
166+
.epr_mode_capable = 0,
167+
.unchunked_ext_msg_support = 0,
168+
.no_usb_suspend = 0,
169+
.usb_comm_capable = 1,
170+
.capability_mismatch = 0,
171+
.give_back_flag = 0, // exteremum is max
172+
.object_position = obj_pos,
173+
};
174+
175+
tusb_pd_header_t const req_header = {
176+
.msg_type = TUSB_PD_DATA_REQUEST,
177+
.data_role = TUSB_PD_DATA_ROLE_UFP,
178+
.specs_rev = TUSB_PD_REV20,
179+
.power_role = TUSB_PD_POWER_ROLE_SINK,
180+
.msg_id = 0,
181+
.n_data_obj = 1,
182+
.extended = 0,
183+
};
184+
185+
utcd_msg_send(rhport, &req_header, &rdo);
186+
128187
break;
129188
}
130189

src/typec/utcd.h

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ extern "C" {
4242
#endif
4343

4444
//--------------------------------------------------------------------+
45-
//
45+
// Source Capability
4646
//--------------------------------------------------------------------+
4747

4848
// All table references are from USBPD Specification rev3.1 version 1.8
@@ -102,6 +102,38 @@ typedef struct TU_ATTR_PACKED {
102102
} pd_pdo_apdo_t;
103103
TU_VERIFY_STATIC(sizeof(pd_pdo_apdo_t) == 4, "Invalid size");
104104

105+
//--------------------------------------------------------------------+
106+
// Request
107+
//--------------------------------------------------------------------+
108+
109+
typedef struct TU_ATTR_PACKED {
110+
uint32_t current_extremum_10ma : 10; // [9..0] Max (give back = 0) or Min (give back = 1) current in 10mA unit
111+
uint32_t current_operate_10ma : 10; // [19..10] Operating current in 10mA unit
112+
uint32_t reserved : 2; // [21..20] Reserved
113+
uint32_t epr_mode_capable : 1; // [22] EPR mode capable
114+
uint32_t unchunked_ext_msg_support : 1; // [23] UnChunked Extended Message Supported
115+
uint32_t no_usb_suspend : 1; // [24] No USB Suspend
116+
uint32_t usb_comm_capable : 1; // [25] USB Communications Capable
117+
uint32_t capability_mismatch : 1; // [26] Capability Mismatch
118+
uint32_t give_back_flag : 1; // [27] GiveBack Flag: 0 = Max, 1 = Min
119+
uint32_t object_position : 4; // [31..28] Object Position
120+
} pd_rdo_fixed_variable_t;
121+
TU_VERIFY_STATIC(sizeof(pd_rdo_fixed_variable_t) == 4, "Invalid size");
122+
123+
typedef struct TU_ATTR_PACKED {
124+
uint32_t power_extremum_250mw : 10; // [9..0] Max (give back = 0) or Min (give back = 1) operating power in 250mW unit
125+
uint32_t power_operate_250mw : 10; // [19..10] Operating power in 250mW unit
126+
uint32_t reserved : 2; // [21..20] Reserved
127+
uint32_t epr_mode_capable : 1; // [22] EPR mode capable
128+
uint32_t unchunked_ext_msg_support : 1; // [23] UnChunked Extended Message Supported
129+
uint32_t no_usb_suspend : 1; // [24] No USB Suspend
130+
uint32_t usb_comm_capable : 1; // [25] USB Communications Capable
131+
uint32_t capability_mismatch : 1; // [26] Capability Mismatch
132+
uint32_t give_back_flag : 1; // [27] GiveBack Flag: 0 = Max, 1 = Min
133+
uint32_t object_position : 4; // [31..28] Object Position
134+
} pd_rdo_battery_t;
135+
TU_VERIFY_STATIC(sizeof(pd_rdo_battery_t) == 4, "Invalid size");
136+
105137
//--------------------------------------------------------------------+
106138
// Application API
107139
//--------------------------------------------------------------------+

0 commit comments

Comments
 (0)