Skip to content

Commit e7f8c5e

Browse files
committed
reduce code size, use state to replace active + pending
1 parent 9ac343a commit e7f8c5e

File tree

4 files changed

+83
-97
lines changed

4 files changed

+83
-97
lines changed

src/portable/raspberrypi/rp2040/dcd_rp2040.c

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,6 @@ static void hw_endpoint_open(uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t t
111111
// double buffered Bulk endpoint
112112
if (transfer_type == TUSB_XFER_BULK) {
113113
size *= 2u;
114-
115114
#if CFG_TUSB_RP2_ERRATA_E15
116115
if (dir == TUSB_DIR_IN) {
117116
ep->e15_bulk_in = true;
@@ -195,7 +194,7 @@ TU_ATTR_ALWAYS_INLINE static inline void reset_ep0(void) {
195194
for (uint8_t dir = 0; dir < 2; dir++) {
196195
struct hw_endpoint *ep = hw_endpoint_get(0, dir);
197196
ep->next_pid = 1u;
198-
if (ep->active) {
197+
if (ep->state == EPSTATE_ACTIVE) {
199198
hw_endpoint_abort_xfer(ep); // Abort any pending transfer per USB specs
200199
}
201200
}
@@ -254,12 +253,12 @@ static void __tusb_irq_path_func(dcd_rp2040_irq)(void) {
254253
struct hw_endpoint *ep = hw_endpoint_get(i, TUSB_DIR_IN);
255254

256255
// Active Bulk IN endpoint requires SOF
257-
if (ep->e15_bulk_in && ep->active) {
256+
if (ep->e15_bulk_in && ep->state == EPSTATE_ACTIVE) {
258257
keep_sof_alive = true;
259258
hw_endpoint_lock_update(ep, 1);
260259

261-
if (ep->pending) {
262-
ep->pending = 0;
260+
if (ep->state == EPSTATE_PENDING) {
261+
ep->state = EPSTATE_ACTIVE;
263262

264263
io_rw_32 *buf_reg32 = get_buf_ctrl(i, TUSB_DIR_IN);
265264
io_rw_16 *buf_reg16 = (io_rw_16 *)buf_reg32;
@@ -501,7 +500,7 @@ bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *ep_desc)
501500
struct hw_endpoint *ep = hw_endpoint_get(epnum, dir);
502501
TU_ASSERT(ep->dpram_buf != NULL); // must be inited and allocated previously
503502

504-
if (ep->active) {
503+
if (ep->state == EPSTATE_ACTIVE) {
505504
hw_endpoint_abort_xfer(ep); // abort any pending transfer
506505
}
507506
ep->max_packet_size = ep_desc->wMaxPacketSize;

src/portable/raspberrypi/rp2040/hcd_rp2040.c

Lines changed: 40 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ enum {
6666
SIE_CTRL_SPEED_FULL = 2,
6767
};
6868

69+
enum {
70+
EPX_CTRL_DEFAULT = EP_CTRL_ENABLE_BITS | EP_CTRL_INTERRUPT_PER_BUFFER | offsetof(usb_host_dpram_t, epx_data)
71+
};
72+
6973
//--------------------------------------------------------------------+
7074
//
7175
//--------------------------------------------------------------------+
@@ -123,7 +127,7 @@ TU_ATTR_ALWAYS_INLINE static inline void sie_stop_xfer(void) {
123127
while (usb_hw->sie_ctrl & USB_SIE_CTRL_STOP_TRANS_BITS) {}
124128
}
125129

126-
TU_ATTR_ALWAYS_INLINE static inline void sie_start_xfer(bool send_setup, bool is_rx, bool need_pre) {
130+
static void __tusb_irq_path_func(sie_start_xfer)(bool send_setup, bool is_rx, bool need_pre) {
127131
uint32_t sie_ctrl = usb_hw->sie_ctrl & SIE_CTRL_BASE_MASK; // preserve base bits
128132
if (send_setup) {
129133
sie_ctrl |= USB_SIE_CTRL_SEND_SETUP_BITS;
@@ -135,31 +139,16 @@ TU_ATTR_ALWAYS_INLINE static inline void sie_start_xfer(bool send_setup, bool is
135139
}
136140

137141
// START_TRANS bit on SIE_CTRL has the same behavior as the AVAILABLE bit
138-
// described in RP2040 Datasheet, release 2.1, section "4.1.2.5.1. Concurrent access".
142+
// described in RP2040 Datasheet, release 2.1, section "4.1.2.5.1. Concurrent access".!
139143
// We write everything except the START_TRANS bit first, then wait some cycles.
140144
usb_hw->sie_ctrl = sie_ctrl;
141145
busy_wait_at_least_cycles(12);
142146
usb_hw->sie_ctrl = sie_ctrl | USB_SIE_CTRL_START_TRANS_BITS;
143147
}
144148

145-
TU_ATTR_ALWAYS_INLINE static inline void epx_start_xfer(hw_endpoint_t *ep, bool is_setup) {
146-
usb_hw->dev_addr_ctrl = (uint32_t)(ep->dev_addr | (tu_edpt_number(ep->ep_addr) << USB_ADDR_ENDP_ENDPOINT_LSB));
147-
sie_start_xfer(is_setup, tu_edpt_dir(ep->ep_addr) == TUSB_DIR_IN, ep->need_pre);
148-
}
149-
150149
// prepare epx_ctrl register for new endpoint
151-
TU_ATTR_ALWAYS_INLINE static inline void epx_ctrl_prepare(hw_endpoint_t *ep) {
152-
// RP2040-E4: USB host writes status to the upper half of buffer control in single buffered mode.
153-
// The buffer selector toggles even in single-buffered mode, so the previous transfer's status
154-
// may have been written to BUF1 half, leaving BUF0 with a stale AVAILABLE bit. Clear it here.
155-
#if defined(PICO_RP2040) && PICO_RP2040 == 1
156-
usbh_dpram->epx_buf_ctrl = 0;
157-
#endif
158-
159-
// ep control
160-
const uint32_t ep_ctrl = EP_CTRL_ENABLE_BITS | EP_CTRL_INTERRUPT_PER_BUFFER |
161-
((uint32_t)ep->transfer_type << EP_CTRL_BUFFER_TYPE_LSB) | hw_data_offset(ep->dpram_buf);
162-
usbh_dpram->epx_ctrl = ep_ctrl;
150+
TU_ATTR_ALWAYS_INLINE static inline void epx_ctrl_prepare(uint8_t transfer_type) {
151+
usbh_dpram->epx_ctrl = EPX_CTRL_DEFAULT | ((uint32_t)transfer_type << EP_CTRL_BUFFER_TYPE_LSB);
163152
}
164153

165154
// Save buffer context for EPX preemption (called after STOP_TRANS).
@@ -196,44 +185,43 @@ static void __tusb_irq_path_func(epx_save_context)(hw_endpoint_t *ep) {
196185

197186
usbh_dpram->epx_buf_ctrl = 0;
198187

199-
ep->pending = 1;
200-
ep->active = false;
188+
ep->state = EPSTATE_PENDING;
201189
}
202190

203-
// All non-interrupt endpoints use shared EPX.
204-
// Save the current EPX context, mark pending, switch to ep
191+
// switch epx to new endpoint and start the transfer
205192
static void __tusb_irq_path_func(epx_switch_ep)(hw_endpoint_t *ep) {
206-
const bool is_setup = (ep->pending == 2);
193+
const bool is_setup = (ep->state == EPSTATE_PENDING_SETUP);
207194

208-
epx = ep; // switch pointer
209-
ep->pending = 0;
210-
ep->active = true;
195+
epx = ep; // switch pointer
196+
ep->state = EPSTATE_ACTIVE;
211197

212198
if (is_setup) {
213199
// panic("new setup \n");
214-
epx_start_xfer(ep, true);
200+
usb_hw->dev_addr_ctrl = ep->dev_addr;
201+
sie_start_xfer(true, false, ep->need_pre);
215202
} else {
216-
io_rw_32 *ep_reg = &usbh_dpram->epx_ctrl;
203+
const bool is_rx = (tu_edpt_dir(ep->ep_addr) == TUSB_DIR_IN);
204+
io_rw_32 *ep_reg = &usbh_dpram->epx_ctrl;
217205
io_rw_32 *buf_reg = &usbh_dpram->epx_buf_ctrl;
218206

219-
epx_ctrl_prepare(ep);
220-
rp2usb_buffer_start(ep, ep_reg, buf_reg, tu_edpt_dir(ep->ep_addr) == TUSB_DIR_IN,
221-
ep->transfer_type == TUSB_XFER_INTERRUPT);
207+
epx_ctrl_prepare(ep->transfer_type);
208+
rp2usb_buffer_start(ep, ep_reg, buf_reg, is_rx, false);
222209

223-
epx_start_xfer(ep, false);
210+
usb_hw->dev_addr_ctrl = (uint32_t)(ep->dev_addr | (tu_edpt_number(ep->ep_addr) << USB_ADDR_ENDP_ENDPOINT_LSB));
211+
sie_start_xfer(is_setup, is_rx, ep->need_pre);
224212
}
225213
}
226214

227215
// Round-robin find next pending ep after current epx
228216
static hw_endpoint_t *__tusb_irq_path_func(epx_next_pending)(hw_endpoint_t *cur_ep) {
229217
const uint cur_idx = (uint)(cur_ep - &ep_pool[0]);
230218
for (uint i = cur_idx + 1; i < TU_ARRAY_SIZE(ep_pool); i++) {
231-
if (ep_pool[i].pending) {
219+
if (ep_pool[i].state >= EPSTATE_PENDING) {
232220
return &ep_pool[i];
233221
}
234222
}
235223
for (uint i = 0; i < cur_idx; i++) {
236-
if (ep_pool[i].pending) {
224+
if (ep_pool[i].state >= EPSTATE_PENDING) {
237225
return &ep_pool[i];
238226
}
239227
}
@@ -246,7 +234,7 @@ static hw_endpoint_t *__tusb_irq_path_func(epx_next_pending)(hw_endpoint_t *cur_
246234
//--------------------------------------------------------------------+
247235
static void __tusb_irq_path_func(xfer_complete_isr)(hw_endpoint_t *ep, xfer_result_t xfer_result, bool is_more) {
248236
// Mark transfer as done before we tell the tinyusb stack
249-
uint xferred_len = ep->xferred_len;
237+
uint32_t xferred_len = ep->xferred_len;
250238
rp2usb_reset_transfer(ep);
251239
hcd_event_xfer_complete(ep->dev_addr, ep->ep_addr, xferred_len, xfer_result, true);
252240

@@ -345,7 +333,7 @@ static void __tusb_irq_path_func(hcd_rp2040_irq)(void) {
345333

346334
// Even if STOP_TRANS bit is clear, controller maybe in middle of retrying and may re-raise timeout once extra time
347335
// Only handle if epx is active, don't carry more epx transfer since STOP_TRANS is raced and not safe.
348-
if (epx->active) {
336+
if (epx->state == EPSTATE_ACTIVE) {
349337
xfer_complete_isr(epx, XFER_RESULT_FAILED, false);
350338
}
351339
}
@@ -392,7 +380,7 @@ static void __tusb_irq_path_func(hcd_rp2040_irq)(void) {
392380
usb_hw_clear->inte = USB_INTE_HOST_SOF_BITS;
393381
usb_hw->nak_poll = USB_NAK_POLL_RESET;
394382
epx_switch_request = false;
395-
} else if (epx->active) {
383+
} else if (epx->state == EPSTATE_ACTIVE) {
396384
if (epx_switch_request) {
397385
// Second SOF with no transfer completion: endpoint is NAK-retrying, safe to switch.
398386
epx_switch_request = false;
@@ -498,7 +486,7 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr) {
498486

499487
// reset epx if it is currently active with unplugged device
500488
if (epx->max_packet_size > 0 && epx->dev_addr == dev_addr) {
501-
// if (epx->active) {
489+
// if (epx->state == EPSTATE_ACTIVE) {
502490
// // need to abort transfer
503491
// }
504492
epx->max_packet_size = 0;
@@ -507,7 +495,7 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr) {
507495
for (size_t i = 0; i < TU_ARRAY_SIZE(ep_pool); i++) {
508496
hw_endpoint_t *ep = &ep_pool[i];
509497
if (ep->dev_addr == dev_addr && ep->max_packet_size > 0) {
510-
ep->pending = 0; // clear any pending transfer
498+
ep->state = EPSTATE_IDLE; // clear any pending transfer
511499

512500
if (ep->interrupt_num) {
513501
// disable interrupt endpoint
@@ -642,10 +630,10 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *b
642630

643631
// If EPX is busy with another transfer, mark as pending
644632
rp2usb_critical_enter();
645-
if (epx->active) {
633+
if (epx->state == EPSTATE_ACTIVE) {
646634
ep->user_buf = buffer;
647635
ep->remaining_len = buflen;
648-
ep->pending = 1;
636+
ep->state = EPSTATE_PENDING;
649637

650638
#ifdef HAS_STOP_EPX_ON_NAK
651639
usb_hw_set->nak_poll = USB_NAK_POLL_STOP_EPX_ON_NAK_BITS;
@@ -660,9 +648,10 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *b
660648

661649
epx = ep;
662650

663-
epx_ctrl_prepare(ep);
651+
epx_ctrl_prepare(ep->transfer_type);
664652
rp2usb_xfer_start(ep, ep_reg, buf_reg, buffer, NULL, buflen); // prepare bufctrl
665-
epx_start_xfer(ep, false);
653+
usb_hw->dev_addr_ctrl = (uint32_t)(ep->dev_addr | (tu_edpt_number(ep->ep_addr) << USB_ADDR_ENDP_ENDPOINT_LSB));
654+
sie_start_xfer(false, tu_edpt_dir(ep->ep_addr) == TUSB_DIR_IN, ep->need_pre);
666655
}
667656
rp2usb_critical_exit();
668657
}
@@ -688,18 +677,20 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, const uint8_t setup_packet
688677
ep->xferred_len = 0;
689678

690679
// If EPX is busy, mark as pending setup (DPRAM already has the packet)
691-
if (epx->active) {
692-
ep->pending = 2; // setup
680+
if (epx->state == EPSTATE_ACTIVE) {
681+
ep->state = EPSTATE_PENDING_SETUP;
693682
#ifdef HAS_STOP_EPX_ON_NAK
694683
usb_hw_set->nak_poll = USB_NAK_POLL_STOP_EPX_ON_NAK_BITS;
695684
#else
696685
usb_hw->nak_poll = (300 << USB_NAK_POLL_DELAY_FS_LSB) | (300 << USB_NAK_POLL_DELAY_LS_LSB);
697686
usb_hw_set->inte = USB_INTE_HOST_SOF_BITS;
698687
#endif
699688
} else {
700-
epx = ep;
701-
ep->active = true;
702-
epx_start_xfer(ep, true);
689+
epx = ep;
690+
ep->state = EPSTATE_ACTIVE;
691+
692+
usb_hw->dev_addr_ctrl = ep->dev_addr;
693+
sie_start_xfer(true, tu_edpt_dir(ep->ep_addr) == TUSB_DIR_IN, ep->need_pre);
703694
}
704695

705696
rp2usb_critical_exit();

src/portable/raspberrypi/rp2040/rp2040_usb.c

Lines changed: 25 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -101,12 +101,13 @@ void rp2usb_init(void) {
101101
}
102102

103103
void __tusb_irq_path_func(rp2usb_reset_transfer)(hw_endpoint_t *ep) {
104-
ep->active = false;
105-
ep->pending = 0;
104+
ep->state = EPSTATE_IDLE;
106105
ep->remaining_len = 0;
107106
ep->xferred_len = 0;
108107
ep->user_buf = 0;
108+
#if CFG_TUD_EDPT_DEDICATED_HWFIFO
109109
ep->is_xfer_fifo = false;
110+
#endif
110111
}
111112

112113
void __tusb_irq_path_func(bufctrl_write32)(io_rw_32 *buf_reg, uint32_t value) {
@@ -211,16 +212,15 @@ void rp2usb_xfer_start(hw_endpoint_t *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg, u
211212
(void)ff;
212213
hw_endpoint_lock_update(ep, 1);
213214

214-
if (ep->active) {
215-
// TODO: Is this acceptable for interrupt packets?
215+
if (ep->state == EPSTATE_ACTIVE) {
216216
TU_LOG(1, "WARN: starting new transfer on already active ep %02X\r\n", ep->ep_addr);
217217
rp2usb_reset_transfer(ep);
218218
}
219219

220220
// Fill in info now that we're kicking off the hw
221221
ep->remaining_len = total_len;
222222
ep->xferred_len = 0;
223-
ep->active = true;
223+
ep->state = EPSTATE_ACTIVE;
224224

225225
#if CFG_TUD_EDPT_DEDICATED_HWFIFO
226226
if (ff != NULL) {
@@ -229,59 +229,50 @@ void rp2usb_xfer_start(hw_endpoint_t *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg, u
229229
} else
230230
#endif
231231
{
232-
ep->user_buf = buffer;
232+
ep->user_buf = buffer;
233+
#if CFG_TUD_EDPT_DEDICATED_HWFIFO
233234
ep->is_xfer_fifo = false;
235+
#endif
234236
}
235237

236238
const bool is_host = rp2usb_is_host_mode();
239+
const bool is_rx = (is_host == (tu_edpt_dir(ep->ep_addr) == TUSB_DIR_IN));
237240

238-
if (ep->future_len > 0) {
239-
// only on rx endpoint
241+
#if CFG_TUD_ENABLED
242+
if (!is_host && ep->future_len > 0) {
243+
// Device only: previous short-packet abort saved data from the other buffer
240244
const uint8_t future_len = ep->future_len;
241245
memcpy(ep->user_buf, ep->dpram_buf + (ep->future_bufid << 6), future_len);
242246
ep->xferred_len += future_len;
243247
ep->remaining_len -= future_len;
244248
ep->user_buf += future_len;
245-
246249
ep->future_len = 0;
247250
ep->future_bufid = 0;
248251

249252
if (ep->remaining_len == 0) {
250-
// all data has been received, no need to start hw transfer
251-
ep->active = false;
252253
const uint16_t xferred_len = ep->xferred_len;
253254
rp2usb_reset_transfer(ep);
254-
255-
#if CFG_TUH_ENABLED
256-
if (is_host) {
257-
hcd_event_xfer_complete(0, ep->ep_addr, xferred_len, XFER_RESULT_SUCCESS, false);
258-
}
259-
#endif
260-
#if CFG_TUD_ENABLED
261-
if (!is_host) {
262-
dcd_event_xfer_complete(0, ep->ep_addr, xferred_len, XFER_RESULT_SUCCESS, false);
263-
}
264-
#endif
265-
255+
dcd_event_xfer_complete(0, ep->ep_addr, xferred_len, XFER_RESULT_SUCCESS, false);
266256
hw_endpoint_lock_update(ep, -1);
267257
return;
268258
}
269259
}
270260

271-
#if CFG_TUSB_RP2_ERRATA_E15
261+
#if CFG_TUSB_RP2_ERRATA_E15
272262
if (ep->e15_bulk_in) {
273263
usb_hw_set->inte = USB_INTS_DEV_SOF_BITS;
274264

275265
// skip transfer if we are in critical frame period
276266
if (e15_is_critical_frame_period()) {
277-
ep->pending = 1;
267+
ep->state = EPSTATE_PENDING;
278268
hw_endpoint_lock_update(ep, -1);
279269
return;
280270
}
281271
}
282-
#endif
272+
#endif // CFG_TUSB_RP2_ERRATA_E15
273+
#endif // CFG_TUD_ENABLED
274+
283275

284-
const bool is_rx = (is_host == (tu_edpt_dir(ep->ep_addr) == TUSB_DIR_IN));
285276
#if CFG_TUH_ENABLED
286277
const bool force_single = (is_host && ep->transfer_type == TUSB_XFER_INTERRUPT);
287278
#else
@@ -333,7 +324,7 @@ bool __tusb_irq_path_func(rp2usb_xfer_continue)(hw_endpoint_t *ep, io_rw_32 *ep_
333324
bool is_rx) {
334325
hw_endpoint_lock_update(ep, 1);
335326

336-
if (!ep->active) {
327+
if (ep->state != EPSTATE_ACTIVE) {
337328
// probably land here due to short packet on rx with double buffered
338329
hw_endpoint_lock_update(ep, -1);
339330
return false;
@@ -394,12 +385,12 @@ bool __tusb_irq_path_func(rp2usb_xfer_continue)(hw_endpoint_t *ep, io_rw_32 *ep_
394385
if (buf_ctrl16_other & USB_BUF_CTRL_FULL) {
395386
// Data already sent into this buffer. Save it for the next transfer.
396387
// buff_status will be clear by the next run
397-
if (is_host) {
398-
// host put future_len pointer at end of epx_data
399-
} else {
388+
#if CFG_TUD_ENABLED
389+
if (!is_host) {
400390
ep->future_len = (uint8_t)(buf_ctrl16_other & USB_BUF_CTRL_LEN_MASK);
391+
ep->future_bufid = buf_id ^ 1;
401392
}
402-
ep->future_bufid = buf_id ^ 1;
393+
#endif
403394
} else {
404395
ep->next_pid ^= 1u; // roll back pid if aborted
405396
}
@@ -424,8 +415,8 @@ bool __tusb_irq_path_func(rp2usb_xfer_continue)(hw_endpoint_t *ep, io_rw_32 *ep_
424415
#if CFG_TUSB_RP2_ERRATA_E15
425416
if (ep->e15_bulk_in && e15_is_critical_frame_period()) {
426417
// mark as pending if matches E15 condition
427-
ep->pending = 1;
428-
} else if (ep->e15_bulk_in && ep->pending) {
418+
ep->state = EPSTATE_PENDING;
419+
} else if (ep->e15_bulk_in && ep->state == EPSTATE_PENDING) {
429420
// if already pending, meaning the other buf completes first, don't arm buffer, let SOF handle it
430421
// do nothing
431422
} else

0 commit comments

Comments
 (0)