4040
4141#include "device/dcd.h"
4242#include "dwc2_common.h"
43+ #include "dwc2_critical.h"
4344
4445//--------------------------------------------------------------------+
4546// MACRO TYPEDEF CONSTANT ENUM
@@ -52,6 +53,9 @@ typedef struct {
5253 uint8_t interval ;
5354} xfer_ctl_t ;
5455
56+ /*
57+ This variable is modified from ISR context, so it must be protected by critical section
58+ */
5559static xfer_ctl_t xfer_status [DWC2_EP_MAX ][2 ];
5660#define XFER_CTL_BASE (_ep , _dir ) (&xfer_status[_ep][_dir])
5761
@@ -321,6 +325,9 @@ static void edpt_disable(uint8_t rhport, uint8_t ep_addr, bool stall) {
321325 }
322326}
323327
328+ // Since this function returns void, it is not possible to return a boolean success message
329+ // We must make sure that this function is not called when the EP is disabled
330+ // Must be called from critical section
324331static void edpt_schedule_packets (uint8_t rhport , const uint8_t epnum , const uint8_t dir ) {
325332 dwc2_regs_t * dwc2 = DWC2_REG (rhport );
326333 xfer_ctl_t * const xfer = XFER_CTL_BASE (epnum , dir );
@@ -531,6 +538,7 @@ void dcd_edpt_close_all(uint8_t rhport) {
531538 dwc2_regs_t * dwc2 = DWC2_REG (rhport );
532539 uint8_t const ep_count = _dwc2_controller [rhport ].ep_count ;
533540
541+ DCD_ENTER_CRITICAL ();
534542 _dcd_data .allocated_epin_count = 0 ;
535543
536544 // Disable non-control interrupt
@@ -550,6 +558,7 @@ void dcd_edpt_close_all(uint8_t rhport) {
550558 dfifo_flush_rx (dwc2 );
551559
552560 dfifo_device_init (rhport ); // re-init dfifo
561+ DCD_EXIT_CRITICAL ();
553562}
554563
555564bool dcd_edpt_iso_alloc (uint8_t rhport , uint8_t ep_addr , uint16_t largest_packet_size ) {
@@ -568,7 +577,12 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to
568577 uint8_t const epnum = tu_edpt_number (ep_addr );
569578 uint8_t const dir = tu_edpt_dir (ep_addr );
570579
580+ DCD_ENTER_CRITICAL ();
571581 xfer_ctl_t * xfer = XFER_CTL_BASE (epnum , dir );
582+ if (xfer -> max_size == 0 ) {
583+ DCD_EXIT_CRITICAL ();
584+ return false; // Endpoint is closed
585+ }
572586 xfer -> buffer = buffer ;
573587 xfer -> ff = NULL ;
574588 xfer -> total_len = total_bytes ;
@@ -580,6 +594,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to
580594
581595 // Schedule packets to be sent within interrupt
582596 edpt_schedule_packets (rhport , epnum , dir );
597+ DCD_EXIT_CRITICAL ();
583598
584599 return true;
585600}
@@ -595,14 +610,20 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t
595610 uint8_t const epnum = tu_edpt_number (ep_addr );
596611 uint8_t const dir = tu_edpt_dir (ep_addr );
597612
613+ DCD_ENTER_CRITICAL ();
598614 xfer_ctl_t * xfer = XFER_CTL_BASE (epnum , dir );
615+ if (xfer -> max_size == 0 ) {
616+ DCD_EXIT_CRITICAL ();
617+ return false; // Endpoint is closed
618+ }
599619 xfer -> buffer = NULL ;
600620 xfer -> ff = ff ;
601621 xfer -> total_len = total_bytes ;
602622
603623 // Schedule packets to be sent within interrupt
604624 // TODO xfer fifo may only available for slave mode
605625 edpt_schedule_packets (rhport , epnum , dir );
626+ DCD_EXIT_CRITICAL ();
606627
607628 return true;
608629}
@@ -631,6 +652,7 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) {
631652//--------------------------------------------------------------------
632653
633654// 7.4.1 Initialization on USB Reset
655+ // Must be called from critical section
634656static void handle_bus_reset (uint8_t rhport ) {
635657 dwc2_regs_t * dwc2 = DWC2_REG (rhport );
636658 const uint8_t ep_count = dwc2_ep_count (dwc2 );
@@ -989,8 +1011,10 @@ void dcd_int_handler(uint8_t rhport) {
9891011
9901012 if (gintsts & GINTSTS_USBRST ) {
9911013 // USBRST is start of reset.
1014+ DCD_ENTER_CRITICAL ();
9921015 dwc2 -> gintsts = GINTSTS_USBRST ;
9931016 handle_bus_reset (rhport );
1017+ DCD_EXIT_CRITICAL ();
9941018 }
9951019
9961020 if (gintsts & GINTSTS_ENUMDNE ) {
0 commit comments