40
40
41
41
#include "device/dcd.h"
42
42
#include "dwc2_common.h"
43
+ #include "dwc2_critical.h"
43
44
44
45
#if TU_CHECK_MCU (OPT_MCU_GD32VF103 )
45
46
#define DWC2_EP_COUNT (_dwc2 ) DWC2_EP_MAX
@@ -58,6 +59,9 @@ typedef struct {
58
59
uint8_t interval ;
59
60
} xfer_ctl_t ;
60
61
62
+ /*
63
+ This variable is modified from ISR context, so it must be protected by critical section
64
+ */
61
65
static xfer_ctl_t xfer_status [DWC2_EP_MAX ][2 ];
62
66
#define XFER_CTL_BASE (_ep , _dir ) (&xfer_status[_ep][_dir])
63
67
@@ -321,6 +325,9 @@ static void edpt_disable(uint8_t rhport, uint8_t ep_addr, bool stall) {
321
325
}
322
326
}
323
327
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
324
331
static void edpt_schedule_packets (uint8_t rhport , const uint8_t epnum , const uint8_t dir ) {
325
332
dwc2_regs_t * dwc2 = DWC2_REG (rhport );
326
333
xfer_ctl_t * const xfer = XFER_CTL_BASE (epnum , dir );
@@ -540,6 +547,7 @@ void dcd_edpt_close_all(uint8_t rhport) {
540
547
dwc2_regs_t * dwc2 = DWC2_REG (rhport );
541
548
uint8_t const ep_count = _dwc2_controller [rhport ].ep_count ;
542
549
550
+ DCD_ENTER_CRITICAL ();
543
551
_dcd_data .allocated_epin_count = 0 ;
544
552
545
553
// Disable non-control interrupt
@@ -559,6 +567,7 @@ void dcd_edpt_close_all(uint8_t rhport) {
559
567
dfifo_flush_rx (dwc2 );
560
568
561
569
dfifo_device_init (rhport ); // re-init dfifo
570
+ DCD_EXIT_CRITICAL ();
562
571
}
563
572
564
573
bool dcd_edpt_iso_alloc (uint8_t rhport , uint8_t ep_addr , uint16_t largest_packet_size ) {
@@ -577,7 +586,12 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to
577
586
uint8_t const epnum = tu_edpt_number (ep_addr );
578
587
uint8_t const dir = tu_edpt_dir (ep_addr );
579
588
589
+ DCD_ENTER_CRITICAL ();
580
590
xfer_ctl_t * xfer = XFER_CTL_BASE (epnum , dir );
591
+ if (xfer -> max_size == 0 ) {
592
+ DCD_EXIT_CRITICAL ();
593
+ return false; // Endpoint is closed
594
+ }
581
595
xfer -> buffer = buffer ;
582
596
xfer -> ff = NULL ;
583
597
xfer -> total_len = total_bytes ;
@@ -589,6 +603,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to
589
603
590
604
// Schedule packets to be sent within interrupt
591
605
edpt_schedule_packets (rhport , epnum , dir );
606
+ DCD_EXIT_CRITICAL ();
592
607
593
608
return true;
594
609
}
@@ -604,14 +619,20 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t
604
619
uint8_t const epnum = tu_edpt_number (ep_addr );
605
620
uint8_t const dir = tu_edpt_dir (ep_addr );
606
621
622
+ DCD_ENTER_CRITICAL ();
607
623
xfer_ctl_t * xfer = XFER_CTL_BASE (epnum , dir );
624
+ if (xfer -> max_size == 0 ) {
625
+ DCD_EXIT_CRITICAL ();
626
+ return false; // Endpoint is closed
627
+ }
608
628
xfer -> buffer = NULL ;
609
629
xfer -> ff = ff ;
610
630
xfer -> total_len = total_bytes ;
611
631
612
632
// Schedule packets to be sent within interrupt
613
633
// TODO xfer fifo may only available for slave mode
614
634
edpt_schedule_packets (rhport , epnum , dir );
635
+ DCD_EXIT_CRITICAL ();
615
636
616
637
return true;
617
638
}
@@ -640,6 +661,7 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) {
640
661
//--------------------------------------------------------------------
641
662
642
663
// 7.4.1 Initialization on USB Reset
664
+ // Must be called from critical section
643
665
static void handle_bus_reset (uint8_t rhport ) {
644
666
dwc2_regs_t * dwc2 = DWC2_REG (rhport );
645
667
const uint8_t ep_count = DWC2_EP_COUNT (dwc2 );
@@ -990,8 +1012,10 @@ void dcd_int_handler(uint8_t rhport) {
990
1012
991
1013
if (gintsts & GINTSTS_USBRST ) {
992
1014
// USBRST is start of reset.
1015
+ DCD_ENTER_CRITICAL ();
993
1016
dwc2 -> gintsts = GINTSTS_USBRST ;
994
1017
handle_bus_reset (rhport );
1018
+ DCD_EXIT_CRITICAL ();
995
1019
}
996
1020
997
1021
if (gintsts & GINTSTS_ENUMDNE ) {
0 commit comments