usbhs_device.c
Go to the documentation of this file.
1 
33 /*
34  * Support and FAQ: visit <a href="https://www.microchip.com/support/">Microchip Support</a>
35  */
36 
37 #include "conf_usb.h"
38 #include "sysclk.h"
39 #include "udd.h"
40 #include "usbhs_otg.h"
41 #include "usbhs_device.h"
42 #include <string.h>
43 
44 #ifndef UDD_NO_SLEEP_MGR
45 # include "sleep.h"
46 # include "sleepmgr.h"
47 #endif
48 
49 #if !(SAMV71 || SAMV70 || SAME70 || SAMS70)
50 # error The current USBHS Device Driver supports only SAMV71, SAMV70, SAME70 and SAMS70.
51 #endif
52 #ifndef UDD_USB_INT_FUN
53 # define UDD_USB_INT_FUN USBHS_Handler
54 #endif
55 
56 #ifndef UDD_USB_INT_LEVEL
57 # define UDD_USB_INT_LEVEL 5 // By default USB interrupt have low priority
58 #endif
59 
60 #define UDD_EP_USED(ep) (USB_DEVICE_MAX_EP >= ep)
61 
62 #if ( (UDD_EP_USED( 1) && Is_udd_endpoint_dma_supported( 1)) \
63  ||(UDD_EP_USED( 2) && Is_udd_endpoint_dma_supported( 2)) \
64  ||(UDD_EP_USED( 3) && Is_udd_endpoint_dma_supported( 3)) \
65  ||(UDD_EP_USED( 4) && Is_udd_endpoint_dma_supported( 4)) \
66  ||(UDD_EP_USED( 5) && Is_udd_endpoint_dma_supported( 5)) \
67  ||(UDD_EP_USED( 6) && Is_udd_endpoint_dma_supported( 6)) \
68  ||(UDD_EP_USED( 7) && Is_udd_endpoint_dma_supported( 7)) \
69  ||(UDD_EP_USED( 8) && Is_udd_endpoint_dma_supported( 8)) \
70  ||(UDD_EP_USED( 9) && Is_udd_endpoint_dma_supported( 9)) \
71  ||(UDD_EP_USED(10) && Is_udd_endpoint_dma_supported(10)) \
72  ||(UDD_EP_USED(11) && Is_udd_endpoint_dma_supported(11)) \
73  ||(UDD_EP_USED(12) && Is_udd_endpoint_dma_supported(12)) \
74  ||(UDD_EP_USED(13) && Is_udd_endpoint_dma_supported(13)) \
75  ||(UDD_EP_USED(14) && Is_udd_endpoint_dma_supported(14)) \
76  ||(UDD_EP_USED(15) && Is_udd_endpoint_dma_supported(15)) \
77  )
78 # define UDD_EP_DMA_SUPPORTED
79 #endif
80 
81 #if ( (UDD_EP_USED( 1) && !Is_udd_endpoint_dma_supported( 1)) \
82  ||(UDD_EP_USED( 2) && !Is_udd_endpoint_dma_supported( 2)) \
83  ||(UDD_EP_USED( 3) && !Is_udd_endpoint_dma_supported( 3)) \
84  ||(UDD_EP_USED( 4) && !Is_udd_endpoint_dma_supported( 4)) \
85  ||(UDD_EP_USED( 5) && !Is_udd_endpoint_dma_supported( 5)) \
86  ||(UDD_EP_USED( 6) && !Is_udd_endpoint_dma_supported( 6)) \
87  ||(UDD_EP_USED( 7) && !Is_udd_endpoint_dma_supported( 7)) \
88  ||(UDD_EP_USED( 8) && !Is_udd_endpoint_dma_supported( 8)) \
89  ||(UDD_EP_USED( 9) && !Is_udd_endpoint_dma_supported( 9)) \
90  ||(UDD_EP_USED(10) && !Is_udd_endpoint_dma_supported(10)) \
91  ||(UDD_EP_USED(11) && !Is_udd_endpoint_dma_supported(11)) \
92  ||(UDD_EP_USED(12) && !Is_udd_endpoint_dma_supported(12)) \
93  ||(UDD_EP_USED(13) && !Is_udd_endpoint_dma_supported(13)) \
94  ||(UDD_EP_USED(14) && !Is_udd_endpoint_dma_supported(14)) \
95  ||(UDD_EP_USED(15) && !Is_udd_endpoint_dma_supported(15)) \
96  )
97 # define UDD_EP_FIFO_SUPPORTED
98 #endif
99 
100 // for debug text
101 //#define dbg_print printf
102 #define dbg_print(...)
103 
104 #ifdef UDD_EP_DMA_SUPPORTED
105 // for DCache
111 static void _dcache_flush(void *addr, uint32_t dsize)
112 {
113 #ifdef CONF_BOARD_ENABLE_CACHE_AT_INIT
114  int32_t op_size = dsize;
115  uint32_t op_addr = (uint32_t) addr;
116  int32_t linesize = 32U; // in Cortex-M7 size of cache line is fixed to 8 words (32 bytes)
117  if (op_addr & (linesize - 1)) {
118  op_size += op_addr & (linesize - 1);
119  op_addr &= ~(linesize - 1);
120  }
121  __ISB();
122  __DSB();
123 
124  while (op_size > 0) {
125  SCB->DCCMVAC = op_addr;
126  op_addr += linesize;
127  op_size -= linesize;
128  }
129 
130  __DSB();
131  __ISB();
132 #endif
133 }
134 
140 static void _dcache_invalidate_prepare(void *addr, uint32_t dsize)
141 {
142 #ifdef CONF_BOARD_ENABLE_CACHE_AT_INIT
143  int32_t op_size = dsize;
144  uint32_t op_addr = (uint32_t) addr;
145  int32_t linesize = 32U; // in Cortex-M7 size of cache line is fixed to 8 words (32 bytes)
146  uint32_t addr1 = op_addr;
147  uint32_t addr2 = op_addr + op_size;
148  if (addr1 & (linesize - 1) || addr2 & (linesize - 1)) {
149  addr1 &= ~(linesize - 1);
150  addr2 &= ~(linesize - 1);
151  __ISB();
152  __DSB();
153  SCB->DCCIMVAC = addr1;
154  SCB->DCCIMVAC = addr2;
155  __DSB();
156  __ISB();
157  }
158 #endif
159 }
160 
166 static void _dcache_invalidate(void *addr, uint32_t dsize)
167 {
168 #ifdef CONF_BOARD_ENABLE_CACHE_AT_INIT
169  int32_t op_size = dsize;
170  uint32_t op_addr = (uint32_t)addr;
171  int32_t linesize = 32U; // in Cortex-M7 size of cache line is fixed to 8 words (32 bytes)
172  if (op_addr & (linesize - 1)) {
173  op_size += op_addr & (linesize - 1);
174  op_addr &= ~(linesize - 1);
175  }
176  __ISB();
177  __DSB();
178 
179  while (op_size > 0) {
180  /* D-Cache Invalidate by MVA to PoC */
181  *(volatile uint32_t *)(0xE000EF5C) = op_addr;
182  op_addr += linesize;
183  op_size -= linesize;
184  }
185 
186  __DSB();
187  __ISB();
188 #endif
189 }
190 #endif
191 
254 // Check USB Device configuration
255 #ifndef USB_DEVICE_EP_CTRL_SIZE
256 # error USB_DEVICE_EP_CTRL_SIZE not defined
257 #endif
258 #ifndef USB_DEVICE_MAX_EP
259 # error USB_DEVICE_MAX_EP not defined
260 #endif
261 
262 // Note: USB_DEVICE_MAX_EP does not include control endpoint
263 #if USB_DEVICE_MAX_EP > (UDD_MAX_PEP_NB-1)
264 # error USB_DEVICE_MAX_EP is too high and not supported by this part
265 #endif
266 
267 #define UDD_EP_ISO_NBANK_ERROR(ep) \
268  ( (UDD_ISOCHRONOUS_NB_BANK(ep) < 1) \
269  || (UDD_ISOCHRONOUS_NB_BANK(ep) > 3) )
270 #define UDD_EP_BULK_NBANK_ERROR(ep) \
271  ( (UDD_BULK_NB_BANK(ep) < 1) || (UDD_BULK_NB_BANK(ep) > 2) )
272 #define UDD_EP_INT_NBANK_ERROR(ep) \
273  ( (UDD_INTERRUPT_NB_BANK(ep) < 1) || (UDD_INTERRUPT_NB_BANK(ep) > 2) )
274 
275 #define UDD_EP_ISO_NB_BANK_ERROR(ep) \
276  (UDD_EP_USED(ep) && UDD_EP_ISO_NBANK_ERROR(ep))
277 #define UDD_EP_BULK_NB_BANK_ERROR(ep) \
278  (UDD_EP_USED(ep) && UDD_EP_ISO_NBANK_ERROR(ep))
279 #define UDD_EP_INT_NB_BANK_ERROR(ep) \
280  (UDD_EP_USED(ep) && UDD_EP_ISO_NBANK_ERROR(ep))
281 
282 #define UDD_EP_NB_BANK_ERROR(ep, type) \
283  (ATPASTE3(UDD_EP_, type, _NB_BANK_ERROR(ep)))
284 
285 #define UDD_ISO_NB_BANK_ERROR \
286  ( UDD_EP_NB_BANK_ERROR( 1, ISO) \
287  || UDD_EP_NB_BANK_ERROR( 2, ISO) \
288  || UDD_EP_NB_BANK_ERROR( 3, ISO) \
289  || UDD_EP_NB_BANK_ERROR( 4, ISO) \
290  || UDD_EP_NB_BANK_ERROR( 5, ISO) \
291  || UDD_EP_NB_BANK_ERROR( 6, ISO) \
292  || UDD_EP_NB_BANK_ERROR( 7, ISO) \
293  || UDD_EP_NB_BANK_ERROR( 8, ISO) \
294  || UDD_EP_NB_BANK_ERROR( 9, ISO) \
295  || UDD_EP_NB_BANK_ERROR(10, ISO) \
296  || UDD_EP_NB_BANK_ERROR(11, ISO) \
297  || UDD_EP_NB_BANK_ERROR(12, ISO) \
298  || UDD_EP_NB_BANK_ERROR(13, ISO) \
299  || UDD_EP_NB_BANK_ERROR(14, ISO) \
300  || UDD_EP_NB_BANK_ERROR(15, ISO) )
301 #define UDD_BULK_NB_BANK_ERROR \
302  ( UDD_EP_NB_BANK_ERROR( 1, BULK) \
303  || UDD_EP_NB_BANK_ERROR( 2, BULK) \
304  || UDD_EP_NB_BANK_ERROR( 3, BULK) \
305  || UDD_EP_NB_BANK_ERROR( 4, BULK) \
306  || UDD_EP_NB_BANK_ERROR( 5, BULK) \
307  || UDD_EP_NB_BANK_ERROR( 6, BULK) \
308  || UDD_EP_NB_BANK_ERROR( 7, BULK) \
309  || UDD_EP_NB_BANK_ERROR( 8, BULK) \
310  || UDD_EP_NB_BANK_ERROR( 9, BULK) \
311  || UDD_EP_NB_BANK_ERROR(10, BULK) \
312  || UDD_EP_NB_BANK_ERROR(11, BULK) \
313  || UDD_EP_NB_BANK_ERROR(12, BULK) \
314  || UDD_EP_NB_BANK_ERROR(13, BULK) \
315  || UDD_EP_NB_BANK_ERROR(14, BULK) \
316  || UDD_EP_NB_BANK_ERROR(15, BULK) )
317 #define UDD_INTERRUPT_NB_BANK_ERROR \
318  ( UDD_EP_NB_BANK_ERROR( 1, INT) \
319  || UDD_EP_NB_BANK_ERROR( 2, INT) \
320  || UDD_EP_NB_BANK_ERROR( 3, INT) \
321  || UDD_EP_NB_BANK_ERROR( 4, INT) \
322  || UDD_EP_NB_BANK_ERROR( 5, INT) \
323  || UDD_EP_NB_BANK_ERROR( 6, INT) \
324  || UDD_EP_NB_BANK_ERROR( 7, INT) \
325  || UDD_EP_NB_BANK_ERROR( 8, INT) \
326  || UDD_EP_NB_BANK_ERROR( 9, INT) \
327  || UDD_EP_NB_BANK_ERROR(10, INT) \
328  || UDD_EP_NB_BANK_ERROR(11, INT) \
329  || UDD_EP_NB_BANK_ERROR(12, INT) \
330  || UDD_EP_NB_BANK_ERROR(13, INT) \
331  || UDD_EP_NB_BANK_ERROR(14, INT) \
332  || UDD_EP_NB_BANK_ERROR(15, INT) )
333 
334 #ifndef UDD_ISOCHRONOUS_NB_BANK
335 # define UDD_ISOCHRONOUS_NB_BANK(ep) 2
336 #else
337 # if UDD_ISO_NB_BANK_ERROR
338 # error UDD_ISOCHRONOUS_NB_BANK(ep) must be define within 1 to 3.
339 # endif
340 #endif
341 
342 #ifndef UDD_BULK_NB_BANK
343 # define UDD_BULK_NB_BANK(ep) 2
344 #else
345 # if UDD_BULK_NB_BANK_ERROR
346 # error UDD_BULK_NB_BANK must be define with 1 or 2.
347 # endif
348 #endif
349 
350 #ifndef UDD_INTERRUPT_NB_BANK
351 # define UDD_INTERRUPT_NB_BANK(ep) 1
352 #else
353 # if UDD_INTERRUPT_NB_BANK_ERROR
354 # error UDD_INTERRUPT_NB_BANK must be define with 1 or 2.
355 # endif
356 #endif
357 
358 
363 
364 #ifndef UDD_NO_SLEEP_MGR
365 
367 #define USBHS_SLEEP_MODE_USB_SUSPEND SLEEPMGR_WAIT_FAST
368 #define USBHS_SLEEP_MODE_USB_IDLE SLEEPMGR_SLEEP_WFI
369 
371 static bool udd_b_idle;
373 static bool udd_b_sleep_initialized = false;
374 
375 
380 static void udd_sleep_mode(bool b_idle)
381 {
382  if (!b_idle && udd_b_idle) {
383  dbg_print("_S ");
385  }
386  if (b_idle && !udd_b_idle) {
387  dbg_print("_W ");
389  }
390  udd_b_idle = b_idle;
391 }
392 #else
393 
394 static void udd_sleep_mode(bool b_idle)
395 {
396  b_idle = b_idle;
397 }
398 
399 #endif // UDD_NO_SLEEP_MGR
400 
402 
407 #if OTG_VBUS_IO
408 
409 # if !defined(UDD_NO_SLEEP_MGR) && !defined(USB_VBUS_WKUP)
410 /* Lock to SLEEPMGR_SLEEP_WFI if VBus not connected */
411 static bool b_vbus_sleep_lock = false;
415 static void udd_vbus_monitor_sleep_mode(bool b_lock)
416 {
417  if (b_lock && !b_vbus_sleep_lock) {
418  b_vbus_sleep_lock = true;
420  }
421  if (!b_lock && b_vbus_sleep_lock) {
422  b_vbus_sleep_lock = false;
424  }
425 }
426 # else
427 # define udd_vbus_monitor_sleep_mode(lock)
428 # endif
429 
433 static void udd_vbus_handler(uint32_t id, uint32_t mask)
434 {
435  /* PIO interrupt status has been cleared, just detect level */
436  bool b_vbus_high = Is_otg_vbus_high();
437  if (b_vbus_high) {
439  udd_attach();
440  } else {
442  udd_detach();
443  }
444  UDC_VBUS_EVENT(b_vbus_high);
445 }
446 
447 #endif
448 
449 
457 
459 COMPILER_WORD_ALIGNED udd_ctrl_request_t udd_g_ctrlreq;
460 
462 typedef enum {
470 
473 
476 
478 static uint16_t udd_ctrl_payload_buf_cnt;
479 
485 static void udd_reset_ep_ctrl(void);
486 
492 static void udd_ctrl_init(void);
493 
495 static void udd_ctrl_setup_received(void);
496 
498 static void udd_ctrl_in_sent(void);
499 
501 static void udd_ctrl_out_received(void);
502 
504 static void udd_ctrl_underflow(void);
505 
507 static void udd_ctrl_overflow(void);
508 
510 static void udd_ctrl_stall_data(void);
511 
513 static void udd_ctrl_send_zlp_in(void);
514 
516 static void udd_ctrl_send_zlp_out(void);
517 
519 static void udd_ctrl_endofrequest(void);
520 
521 
529 static bool udd_ctrl_interrupt(void);
530 
532 
533 
544 #if (0!=USB_DEVICE_MAX_EP)
545 
547 typedef struct {
548  union {
550  udd_callback_trans_t call_trans;
551 
553  udd_callback_halt_cleared_t call_nohalt;
554  };
556  uint8_t *buf;
558  iram_size_t buf_size;
560  iram_size_t buf_cnt;
562  iram_size_t buf_load;
564  uint8_t busy:1;
566  uint8_t b_shortpacket:1;
568  uint8_t stall_requested:1;
569 } udd_ep_job_t;
570 
571 
573 static udd_ep_job_t udd_ep_job[USB_DEVICE_MAX_EP];
574 
576 static void udd_ep_job_table_reset(void);
577 
579 static void udd_ep_job_table_kill(void);
580 
581 #ifdef UDD_EP_FIFO_SUPPORTED
582 
587  static void udd_ep_in_sent(udd_ep_id_t ep);
588 
594  static void udd_ep_out_received(udd_ep_id_t ep);
595 #endif
596 
602 static void udd_ep_abort_job(udd_ep_id_t ep);
603 
610 static void udd_ep_finish_job(udd_ep_job_t * ptr_job, bool b_abort, uint8_t ep_num);
611 
612 #ifdef UDD_EP_DMA_SUPPORTED
613 
618  static void udd_ep_trans_done(udd_ep_id_t ep);
619 #endif
620 
628 static bool udd_ep_interrupt(void);
629 
630 #endif // (0!=USB_DEVICE_MAX_EP)
631 
632 
633 
634 //--------------------------------------------------------
635 //--- INTERNAL ROUTINES TO MANAGED GLOBAL EVENTS
636 
651 #ifdef UHD_ENABLE
652 void udd_interrupt(void);
653 void udd_interrupt(void)
654 #else
656 #endif
657 {
658 #ifndef UDD_NO_SLEEP_MGR
659  /* For fast wakeup clocks restore
660  * In WAIT mode, clocks are switched to FASTRC.
661  * After wakeup clocks should be restored, before that ISR should not
662  * be served.
663  */
664  if (!pmc_is_wakeup_clocks_restored() && !Is_udd_suspend()) {
665  cpu_irq_disable();
666  return;
667  }
668 #endif
669  if (Is_udd_sof()) {
670  udd_ack_sof();
671  if (Is_udd_full_speed_mode()) {
672  udc_sof_notify();
673  }
674 #ifdef UDC_SOF_EVENT
675  UDC_SOF_EVENT();
676 #endif
677  goto udd_interrupt_sof_end;
678  }
679 
680  if (Is_udd_msof()) {
681  udd_ack_msof();
682  udc_sof_notify();
683  goto udd_interrupt_sof_end;
684  }
685 
686  dbg_print("%c ", udd_is_high_speed() ? 'H' : 'F');
687 
689  goto udd_interrupt_end; // Interrupt acked by control endpoint managed
690  }
691 
692 #if (0 != USB_DEVICE_MAX_EP)
693  if (udd_ep_interrupt()) {
694  goto udd_interrupt_end; // Interrupt acked by bulk/interrupt/isochronous endpoint managed
695  }
696 #endif
697 
698  // USB bus reset detection
699  if (Is_udd_reset()) {
700  udd_ack_reset();
701  dbg_print("RST ");
702  // Abort all jobs on-going
703 #if (USB_DEVICE_MAX_EP != 0)
704  udd_ep_job_table_kill();
705 #endif
706  // Reset USB Device Stack Core
707  udc_reset();
708  // Reset endpoint control
710  // Reset endpoint control management
711  udd_ctrl_init();
712  goto udd_interrupt_end;
713  }
714 
717  // The suspend interrupt is automatic acked when a wakeup occur
720  otg_freeze_clock(); // Mandatory to exit of sleep mode after a wakeup event
721  udd_sleep_mode(false); // Enter in SUSPEND mode
722 #ifdef UDC_SUSPEND_EVENT
723  UDC_SUSPEND_EVENT();
724 #endif
725  goto udd_interrupt_end;
726  }
727 
729  // Ack wakeup interrupt and enable suspend interrupt
731  // Check USB clock ready after suspend and eventually sleep USB clock
732  while (!Is_otg_clock_usable()) {
733  if (Is_udd_suspend()) {
734  break; // In case of USB state change in HS
735  }
736  };
737  // The wakeup interrupt is automatic acked when a suspend occur
740  udd_sleep_mode(true); // Enter in IDLE mode
741 #ifdef UDC_RESUME_EVENT
742  UDC_RESUME_EVENT();
743 #endif
744  goto udd_interrupt_end;
745  }
746 
747 udd_interrupt_end:
748  dbg_print("\n\r");
749 udd_interrupt_sof_end:
750  return;
751 }
752 
753 
755 {
756 #if OTG_VBUS_IO
757  return true;
758 #else
759  return false;
760 #endif
761 }
762 
763 
764 void udd_enable(void)
765 {
766  irqflags_t flags;
767 
768  flags = cpu_irq_save();
769 
770 #ifdef UHD_ENABLE
771  // DUAL ROLE INITIALIZATION
772  if (otg_dual_enable()) {
773  // The current mode has been started by otg_dual_enable()
774  cpu_irq_restore(flags);
775  return;
776  }
777 #else
778  // SINGLE DEVICE MODE INITIALIZATION
779  /* Enable peripheral clock for USBHS */
781 
783 
784  // Here, only the device mode is possible, then link USBHS interrupt to UDD interrupt
786  NVIC_EnableIRQ((IRQn_Type) ID_USBHS);
787 
788  // Always authorize asynchrone USB interrupts to exit of sleep mode
789  // For SAM USB wake up device except BACKUP mode
791 #endif
792 
793 #if (OTG_ID_IO) && (defined UHD_ENABLE)
794  // Check that the device mode is selected by ID pin
795  if (!Is_otg_id_device()) {
796  cpu_irq_restore(flags);
797  return; // Device is not the current mode
798  }
799 #else
800  // ID pin not used then force device mode
801  USBHS->USBHS_CTRL = USBHS_CTRL_UIMOD_DEVICE;
802 #endif
803  // Enable USB hardware
804  otg_enable();
805 
806  // Set the USB speed requested by configuration file
807 #ifdef USB_DEVICE_LOW_SPEED
809 #else
811 #ifdef USB_DEVICE_HS_SUPPORT
813 #else
815 #endif
816 #endif // USB_DEVICE_LOW_SPEED
817 
819  // Check USB clock
820  while (!Is_otg_clock_usable());
821 
822  // Reset internal variables
823 #if (0!=USB_DEVICE_MAX_EP)
824  udd_ep_job_table_reset();
825 #endif
826 
828 
829 #ifndef UDD_NO_SLEEP_MGR
832  // Initialize the sleep mode authorized for the USB suspend mode
833  udd_b_idle = false;
835  } else {
836  udd_sleep_mode(false); // Enter idle mode
837  }
838 #endif
839 
840 #if OTG_VBUS_IO
841  /* Initialize VBus monitor */
844  /* Force VBus interrupt when VBus is always high
845  * This is possible due to a short timing between a Host mode stop/start.
846  */
847  if (Is_otg_vbus_high()) {
848  udd_vbus_handler(USB_VBUS_PIO_ID, USB_VBUS_PIO_MASK);
849  }
850 #else
851  udd_attach();
852 #endif
853 
854  cpu_irq_restore(flags);
855 }
856 
857 
858 void udd_disable(void)
859 {
860  irqflags_t flags;
861 
862 #ifdef UHD_ENABLE
863 # if OTG_ID_IO
864  if (Is_otg_id_host()) {
865  // Freeze clock to switch mode
867  udd_detach();
868  otg_disable();
869  return; // Host mode running, ignore UDD disable
870  }
871 # else
872  if (Is_otg_host_mode_forced()) {
873  return; // Host mode running, ignore UDD disable
874  }
875 #endif
876 #endif
877 
878  flags = cpu_irq_save();
880  udd_detach();
881 #ifndef UDD_NO_SLEEP_MGR
883  udd_b_sleep_initialized = false;
885  }
886 #endif
887 
888 #ifndef UHD_ENABLE
889  otg_disable();
892  // Else the USB clock disable is done by UHC which manage USB dual role
893 #endif
894  cpu_irq_restore(flags);
895 }
896 
897 
898 void udd_attach(void)
899 {
900  irqflags_t flags;
901  flags = cpu_irq_save();
902 
903  // At startup the USB bus state is unknown,
904  // therefore the state is considered IDLE to not miss any USB event
905  udd_sleep_mode(true);
907 
908  // This section of clock check can be improved with a chek of
909  // USB clock source via sysclk()
910  // Check USB clock because the source can be a PLL
911  while (!Is_otg_clock_usable());
912 
913  // Authorize attach if Vbus is present
915 
916  // Enable USB line events
921 #ifdef USB_DEVICE_HS_SUPPORT
923 #endif
924  // Reset following interupts flag
925  udd_ack_reset();
926  udd_ack_sof();
927  udd_ack_msof();
928 
929  // The first suspend interrupt must be forced
930  // The first suspend interrupt is not detected else raise it
932 
933  udd_ack_wake_up();
935  cpu_irq_restore(flags);
936 }
937 
938 
939 void udd_detach(void)
940 {
942 
943  // Detach device from the bus
946  udd_sleep_mode(false);
947 }
948 
949 
951 {
952 #ifdef USB_DEVICE_HS_SUPPORT
953  return !Is_udd_full_speed_mode();
954 #else
955  return false;
956 #endif
957 }
958 
959 
960 void udd_set_address(uint8_t address)
961 {
963  udd_configure_address(address);
965 }
966 
967 
968 uint8_t udd_getaddress(void)
969 {
971 }
972 
973 
974 uint16_t udd_get_frame_number(void)
975 {
976  return udd_frame_number();
977 }
978 
980 {
981  return udd_micro_frame_number();
982 }
983 
985 {
986 #ifndef UDD_NO_SLEEP_MGR
987  if (!udd_b_idle)
988 #endif
989  {
990  udd_sleep_mode(true); // Enter in IDLE mode
993  }
994 }
995 
996 
997 void udd_set_setup_payload(uint8_t *payload, uint16_t payload_size)
998 {
999  udd_g_ctrlreq.payload = payload;
1000  udd_g_ctrlreq.payload_size = payload_size;
1001 }
1002 
1003 
1004 #if (0 != USB_DEVICE_MAX_EP)
1005 bool udd_ep_alloc(udd_ep_id_t ep, uint8_t bmAttributes,
1006  uint16_t MaxEndpointSize)
1007 {
1008  bool b_dir_in;
1009  uint16_t ep_allocated;
1010  uint8_t nb_bank, bank, i;
1011 
1012  b_dir_in = ep & USB_EP_DIR_IN;
1013  ep = ep & USB_EP_ADDR_MASK;
1014 
1015  if (ep > USB_DEVICE_MAX_EP) {
1016  return false;
1017  }
1018  if (Is_udd_endpoint_enabled(ep)) {
1019  return false;
1020  }
1021  dbg_print("alloc(%x, %d) ", ep, MaxEndpointSize);
1022 
1023  // Bank choise
1024  switch (bmAttributes & USB_EP_TYPE_MASK) {
1026  nb_bank = UDD_ISOCHRONOUS_NB_BANK(ep);
1027  break;
1028  case USB_EP_TYPE_INTERRUPT:
1029  nb_bank = UDD_INTERRUPT_NB_BANK(ep);
1030  break;
1031  case USB_EP_TYPE_BULK:
1032  nb_bank = UDD_BULK_NB_BANK(ep);
1033  break;
1034  default:
1035  Assert(false);
1036  return false;
1037  }
1038  switch (nb_bank) {
1039  case 1:
1040  bank = USBHS_DEVEPTCFG_EPBK_1_BANK >>
1042  break;
1043  case 2:
1044  bank = USBHS_DEVEPTCFG_EPBK_2_BANK >>
1046  break;
1047  case 3:
1048  bank = USBHS_DEVEPTCFG_EPBK_3_BANK >>
1050  break;
1051  default:
1052  Assert(false);
1053  return false;
1054  }
1055 
1056  // Check if endpoint size is 8,16,32,64,128,256,512 or 1023
1057  Assert(MaxEndpointSize < 1024);
1058  Assert((MaxEndpointSize == 1023)
1059  || !(MaxEndpointSize & (MaxEndpointSize - 1)));
1060  Assert(MaxEndpointSize >= 8);
1061 
1062  // Set configuration of new endpoint
1063  udd_configure_endpoint(ep, bmAttributes, (b_dir_in ? 1 : 0),
1064  MaxEndpointSize, bank);
1065  ep_allocated = 1 << ep;
1066 
1067  // Unalloc endpoints superior
1068  for (i = USB_DEVICE_MAX_EP; i > ep; i--) {
1069  if (Is_udd_endpoint_enabled(i)) {
1070  ep_allocated |= 1 << i;
1073  }
1074  }
1075 
1076  // Realloc/Enable endpoints
1077  for (i = ep; i <= USB_DEVICE_MAX_EP; i++) {
1078  if (ep_allocated & (1 << i)) {
1079  udd_ep_job_t *ptr_job = &udd_ep_job[i - 1];
1080  bool b_restart = ptr_job->busy;
1081  // Restart running job because
1082  // memory window slides up and its data is lost
1083  ptr_job->busy = false;
1084  // Re-allocate memory
1087  if (!Is_udd_endpoint_configured(i)) {
1088  dbg_print("ErrRealloc%d ", i);
1089  if (NULL == ptr_job->call_trans) {
1090  return false;
1091  }
1092  if (Is_udd_endpoint_in(i)) {
1093  i |= USB_EP_DIR_IN;
1094  }
1095  ptr_job->call_trans(UDD_EP_TRANSFER_ABORT,
1096  ptr_job->buf_cnt, i);
1097  return false;
1098  }
1100  if (b_restart) {
1101  // Re-run the job remaining part
1102 # ifdef UDD_EP_FIFO_SUPPORTED
1104  && !Is_udd_endpoint_in(i)) {
1105  ptr_job->buf_cnt -= ptr_job->buf_load;
1106  }
1107 # else
1108  ptr_job->buf_cnt -= ptr_job->buf_load;
1109 # endif
1110  b_restart = udd_ep_run(Is_udd_endpoint_in(i) ?
1111  (i | USB_EP_DIR_IN) : i,
1112  ptr_job->b_shortpacket,
1113  &ptr_job->buf[ptr_job->buf_cnt],
1114  ptr_job->buf_size
1115  - ptr_job->buf_cnt,
1116  ptr_job->call_trans);
1117  if (!b_restart) {
1118  dbg_print("ErrReRun%d ", i);
1119  return false;
1120  }
1121  }
1122  }
1123  }
1124  return true;
1125 }
1126 
1127 
1128 void udd_ep_free(udd_ep_id_t ep)
1129 {
1130  uint8_t ep_index = ep & USB_EP_ADDR_MASK;
1131  if (USB_DEVICE_MAX_EP < ep_index) {
1132  return;
1133  }
1134  udd_disable_endpoint(ep_index);
1135  udd_unallocate_memory(ep_index);
1136  udd_ep_abort_job(ep);
1137  udd_ep_job[ep_index - 1].stall_requested = false;
1138 }
1139 
1140 
1141 bool udd_ep_is_halted(udd_ep_id_t ep)
1142 {
1143  uint8_t ep_index = ep & USB_EP_ADDR_MASK;
1144  return Is_udd_endpoint_stall_requested(ep_index);
1145 }
1146 
1147 
1148 bool udd_ep_set_halt(udd_ep_id_t ep)
1149 {
1150  uint8_t ep_index = ep & USB_EP_ADDR_MASK;
1151  udd_ep_job_t *ptr_job = &udd_ep_job[ep_index - 1];
1152  irqflags_t flags;
1153 
1154  if (USB_DEVICE_MAX_EP < ep_index) {
1155  return false;
1156  }
1157 
1158  if (Is_udd_endpoint_stall_requested(ep_index) // Endpoint stalled
1159  || ptr_job->stall_requested) { // Endpoint stall is requested
1160  return true; // Already STALL
1161  }
1162 
1163  if (ptr_job->busy == true) {
1164  return false; // Job on going, stall impossible
1165  }
1166 
1167  flags = cpu_irq_save();
1168  if ((ep & USB_EP_DIR_IN) && (0 != udd_nb_busy_bank(ep_index))) {
1169  // Delay the stall after the end of IN transfer on USB line
1170  ptr_job->stall_requested = true;
1171 #ifdef UDD_EP_FIFO_SUPPORTED
1174 #endif
1175  udd_enable_bank_interrupt(ep_index);
1177  cpu_irq_restore(flags);
1178  return true;
1179  }
1180  // Stall endpoint immediately
1182  udd_ack_stall(ep_index);
1183  udd_enable_stall_handshake(ep_index);
1184  cpu_irq_restore(flags);
1185  return true;
1186 }
1187 
1188 
1189 bool udd_ep_clear_halt(udd_ep_id_t ep)
1190 {
1191  uint8_t ep_index = ep & USB_EP_ADDR_MASK;
1192  udd_ep_job_t *ptr_job = &udd_ep_job[ep_index - 1];
1193  bool b_stall_cleared = false;
1194 
1195  if (USB_DEVICE_MAX_EP < ep_index)
1196  return false;
1197 
1198  if (ptr_job->stall_requested) {
1199  // Endpoint stall has been requested but not done
1200  // Remove stall request
1201  ptr_job->stall_requested = false;
1202  udd_disable_bank_interrupt(ep_index);
1204  b_stall_cleared = true;
1205  }
1206  if (Is_udd_endpoint_stall_requested(ep_index)) {
1207  if (Is_udd_stall(ep_index)) {
1208  udd_ack_stall(ep_index);
1209  // A packet has been stalled
1210  // then reset datatoggle
1211  udd_reset_data_toggle(ep_index);
1212  }
1213  // Disable stall
1214  udd_disable_stall_handshake(ep_index);
1216  b_stall_cleared = true;
1217  }
1218  if (b_stall_cleared) {
1219  // If a job is register on clear halt action
1220  // then execute callback
1221  if (ptr_job->busy == true) {
1222  ptr_job->busy = false;
1223  ptr_job->call_nohalt();
1224  }
1225  }
1226  return true;
1227 }
1228 
1229 
1230 bool udd_ep_run(udd_ep_id_t ep, bool b_shortpacket,
1231  uint8_t * buf, iram_size_t buf_size,
1232  udd_callback_trans_t callback)
1233 {
1234  bool b_dir_in = Is_udd_endpoint_in(ep & USB_EP_ADDR_MASK);
1235  udd_ep_job_t *ptr_job;
1236  irqflags_t flags;
1237 
1238  ep &= USB_EP_ADDR_MASK;
1239  if (USB_DEVICE_MAX_EP < ep) {
1240  return false;
1241  }
1242 
1243  // Get job about endpoint
1244  ptr_job = &udd_ep_job[ep - 1];
1245 
1246  if ((!Is_udd_endpoint_enabled(ep))
1248  || ptr_job->stall_requested) {
1249  return false; // Endpoint is halted
1250  }
1251 
1252  flags = cpu_irq_save();
1253  if (ptr_job->busy == true) {
1254  cpu_irq_restore(flags);
1255  return false; // Job already on going
1256  }
1257  ptr_job->busy = true;
1258  cpu_irq_restore(flags);
1259 
1260  // No job running. Let's setup a new one.
1261  ptr_job->buf = buf;
1262  ptr_job->buf_size = buf_size;
1263  ptr_job->buf_cnt = 0;
1264  ptr_job->buf_load = 0;
1265  ptr_job->call_trans = callback;
1266  ptr_job->b_shortpacket = b_shortpacket || (buf_size == 0);
1267 
1268 #ifdef UDD_EP_FIFO_SUPPORTED
1269  // No DMA support
1270  if (!Is_udd_endpoint_dma_supported(ep)) {
1271  dbg_print("ex%x.%c%d\n\r", ep, b_dir_in ? 'i':'o', buf_size);
1272  flags = cpu_irq_save();
1274  if (b_dir_in) {
1277  } else {
1280  }
1281  cpu_irq_restore(flags);
1282  return true;
1283  }
1284 #endif // UDD_EP_FIFO_SUPPORTED
1285 
1286 #ifdef UDD_EP_DMA_SUPPORTED
1287  // Request first DMA transfer
1288  dbg_print("(exDMA%x) ", ep);
1289  if (buf && buf_size) {
1290  if (!b_dir_in) {
1291  _dcache_invalidate_prepare(buf, buf_size);
1292  } else {
1293  _dcache_flush(buf, buf_size);
1294  }
1295  }
1296  udd_ep_trans_done(ep);
1297  return true;
1298 #endif
1299 }
1300 
1301 
1302 void udd_ep_abort(udd_ep_id_t ep)
1303 {
1304  uint8_t ep_index = ep & USB_EP_ADDR_MASK;
1305 
1306 #ifdef UDD_EP_FIFO_SUPPORTED
1307  if (!Is_udd_endpoint_dma_supported(ep_index)) {
1308  // Disable interrupts
1312  } else
1313 #endif
1314  {
1315  // Stop DMA transfer
1317  udd_endpoint_dma_set_control(ep_index, 0);
1318  }
1320  // Kill IN banks
1321  __DSB();
1322  __ISB();
1323  if (ep & USB_EP_DIR_IN) {
1324  while(udd_nb_busy_bank(ep_index)) {
1325  udd_kill_last_in_bank(ep_index);
1326  while(Is_udd_kill_last(ep_index));
1327  }
1328  }
1329  udd_ep_abort_job(ep);
1330 }
1331 
1332 
1333 bool udd_ep_wait_stall_clear(udd_ep_id_t ep,
1334  udd_callback_halt_cleared_t callback)
1335 {
1336  udd_ep_job_t *ptr_job;
1337 
1338  ep &= USB_EP_ADDR_MASK;
1339  if (USB_DEVICE_MAX_EP < ep) {
1340  return false;
1341  }
1342 
1343  ptr_job = &udd_ep_job[ep - 1];
1344 
1345  if (!Is_udd_endpoint_enabled(ep)) {
1346  return false; // Endpoint not enabled
1347  }
1348 
1349  // Wait clear halt endpoint
1350  if (ptr_job->busy == true) {
1351  return false; // Job already on going
1352  }
1353 
1355  || ptr_job->stall_requested) {
1356  // Endpoint halted then registes the callback
1357  ptr_job->busy = true;
1358  ptr_job->call_nohalt = callback;
1359  } else {
1360  // endpoint not halted then call directly callback
1361  callback();
1362  }
1363  return true;
1364 }
1365 #endif // (0 != USB_DEVICE_MAX_EP)
1366 
1367 
1368 #ifdef USB_DEVICE_HS_SUPPORT
1369 
1370 void udd_test_mode_j(void)
1371 {
1372  udd_enable_hs_test_mode();
1373  udd_enable_hs_test_mode_j();
1374 }
1375 
1376 
1377 void udd_test_mode_k(void)
1378 {
1379  udd_enable_hs_test_mode();
1380  udd_enable_hs_test_mode_k();
1381 }
1382 
1383 
1384 void udd_test_mode_se0_nak(void)
1385 {
1386  udd_enable_hs_test_mode();
1387 }
1388 
1389 
1390 void udd_test_mode_packet(void)
1391 {
1392  uint8_t i;
1393  uint8_t *ptr_dest;
1394  const uint8_t *ptr_src;
1395 
1396  const uint8_t test_packet[] = {
1397  // 00000000 * 9
1398  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1399  // 01010101 * 8
1400  0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
1401  // 01110111 * 8
1402  0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE,
1403  // 0, {111111S * 15}, 111111
1404  0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
1405  0xFF, 0xFF,
1406  // S, 111111S, {0111111S * 7}
1407  0x7F, 0xBF, 0xDF, 0xEF, 0xF7, 0xFB, 0xFD,
1408  // 00111111, {S0111111 * 9}, S0
1409  0xFC, 0x7E, 0xBF, 0xDF, 0xEF, 0xF7, 0xFB, 0xFD, 0x7E
1410  };
1411 
1412  // Reconfigure control endpoint to bulk IN endpoint
1418 
1419  udd_enable_hs_test_mode();
1420  udd_enable_hs_test_mode_packet();
1421 
1422  // Send packet on endpoint 0
1423  ptr_dest = (uint8_t *) & udd_get_endpoint_fifo_access(0, 8);
1424  ptr_src = test_packet;
1425 
1426  for (i = 0; i < sizeof(test_packet); i++) {
1427  *ptr_dest++ = *ptr_src++;
1428  }
1429  udd_ack_fifocon(0);
1430 }
1431 #endif // USB_DEVICE_HS_SUPPORT
1432 
1433 
1434 
1435 //--------------------------------------------------------
1436 //--- INTERNAL ROUTINES TO MANAGED THE CONTROL ENDPOINT
1437 
1438 static void udd_reset_ep_ctrl(void)
1439 {
1440  irqflags_t flags;
1441 
1442  // Reset USB address to 0
1445 
1446  // Alloc and configure control endpoint
1449  0,
1452 
1455  flags = cpu_irq_save();
1459  cpu_irq_restore(flags);
1460 }
1461 
1462 static void udd_ctrl_init(void)
1463 {
1464  irqflags_t flags;
1465  flags = cpu_irq_save();
1466 
1467  // In case of abort of IN Data Phase:
1468  // No need to abort IN transfer (rise TXINI),
1469  // because it is automatically done by hardware when a Setup packet is received.
1470  // But the interrupt must be disabled to don't generate interrupt TXINI
1471  // after SETUP reception.
1473  cpu_irq_restore(flags);
1474 
1475  // In case of OUT ZLP event is no processed before Setup event occurs
1477 
1482 }
1483 
1484 
1485 static void udd_ctrl_setup_received(void)
1486 {
1487  irqflags_t flags;
1488  uint8_t i;
1489 
1491  // May be a hidden DATA or ZLP phase or protocol abort
1493 
1494  // Reinitializes control endpoint management
1495  udd_ctrl_init();
1496  }
1497  // Fill setup request structure
1498  if (8 != udd_byte_count(0)) {
1501  return; // Error data number doesn't correspond to SETUP packet
1502  }
1503 
1504  uint16_t nb_data = udd_byte_count(0);
1505  volatile uint8_t *ptr = (uint8_t *) & udd_get_endpoint_fifo_access(0,8);
1506  for (i = 0; i < nb_data; i++) {
1507  ((uint8_t*) &udd_g_ctrlreq.req)[i] = *ptr++;
1508  }
1509  // Manage LSB/MSB to fit with CPU usage
1513 
1514  // Decode setup request
1515  if (udc_process_setup() == false) {
1516  // Setup request unknow then stall it
1519  return;
1520  }
1522 
1523  if (Udd_setup_is_in()) {
1524  // IN data phase requested
1528  udd_ctrl_in_sent(); // Send first data transfer
1529  } else {
1530  if (0 == udd_g_ctrlreq.req.wLength) {
1531  // No data phase requested
1532  // Send IN ZLP to ACK setup request
1534  return;
1535  }
1536  // OUT data phase requested
1540  // To detect a protocol error, enable nak interrupt on data IN phase
1541  udd_ack_nak_in(0);
1542  flags = cpu_irq_save();
1544  cpu_irq_restore(flags);
1545  }
1546 }
1547 
1548 
1549 static void udd_ctrl_in_sent(void)
1550 {
1551  static bool b_shortpacket = false;
1552  uint16_t nb_remain;
1553  uint8_t i;
1554  volatile uint8_t *ptr_dest;
1555  volatile uint8_t *ptr_src;
1556  irqflags_t flags;
1557 
1558  flags = cpu_irq_save();
1560  cpu_irq_restore(flags);
1561 
1563  // ZLP on IN is sent, then valid end of setup request
1565  // Reinitializes control endpoint management
1566  udd_ctrl_init();
1567  return;
1568  }
1570 
1572  if (0 == nb_remain) {
1573  // All content of current buffer payload are sent
1574  // Update number of total data sending by previous playlaod buffer
1577  || b_shortpacket) {
1578  // All data requested are transfered or a short packet has been sent
1579  // then it is the end of data phase.
1580  // Generate an OUT ZLP for handshake phase.
1582  return;
1583  }
1584  // Need of new buffer because the data phase is not complete
1586  || (!udd_g_ctrlreq.over_under_run())) {
1587  // Underrun then send zlp on IN
1588  // Here nb_remain=0 and allows to send a IN ZLP
1589  } else {
1590  // A new payload buffer is given
1592  nb_remain = udd_g_ctrlreq.payload_size;
1593  }
1594  }
1595  // Continue transfer and send next data
1596  if (nb_remain >= USB_DEVICE_EP_CTRL_SIZE) {
1597  nb_remain = USB_DEVICE_EP_CTRL_SIZE;
1598  b_shortpacket = false;
1599  } else {
1600  b_shortpacket = true;
1601  }
1602  // Fill buffer of endpoint control
1603  ptr_dest = (uint8_t *) & udd_get_endpoint_fifo_access(0, 8);
1605  // Critical section
1606  // Only in case of DATA IN phase abort without USB Reset signal after.
1607  // The IN data don't must be written in endpoint 0 DPRAM during
1608  // a next setup reception in same endpoint 0 DPRAM.
1609  // Thereby, an OUT ZLP reception must check before IN data write
1610  // and if no OUT ZLP is recevied the data must be written quickly (800us)
1611  // before an eventually ZLP OUT and SETUP reception
1612  flags = cpu_irq_save();
1613  if (Is_udd_out_received(0)) {
1614  // IN DATA phase aborted by OUT ZLP
1615  cpu_irq_restore(flags);
1617  return; // Exit of IN DATA phase
1618  }
1619  // Write quickly the IN data
1620  for (i = 0; i < nb_remain; i++) {
1621  *ptr_dest++ = *ptr_src++;
1622  }
1623  udd_ctrl_payload_buf_cnt += nb_remain;
1624 
1625  // Validate and send the data available in the control endpoint buffer
1626  __DSB();
1627  __ISB();
1628  udd_ack_in_send(0);
1630  // In case of abort of DATA IN phase, no need to enable nak OUT interrupt
1631  // because OUT endpoint is already free and ZLP OUT accepted.
1632  cpu_irq_restore(flags);
1633 }
1634 
1635 
1636 static void udd_ctrl_out_received(void)
1637 {
1638  irqflags_t flags;
1639  uint8_t i;
1640  uint16_t nb_data;
1641 
1646  // End of SETUP request:
1647  // - Data IN Phase aborted,
1648  // - or last Data IN Phase hidden by ZLP OUT sending quiclky,
1649  // - or ZLP OUT received normaly.
1651  } else {
1652  // Protocol error during SETUP request
1654  }
1655  // Reinitializes control endpoint management
1656  udd_ctrl_init();
1657  return;
1658  }
1659  // Read data received during OUT phase
1660  nb_data = udd_byte_count(0);
1662  // Payload buffer too small
1664  }
1665  volatile uint8_t *ptr_src = (uint8_t *) & udd_get_endpoint_fifo_access(0, 8);
1666  volatile uint8_t *ptr_dest = udd_g_ctrlreq.payload + udd_ctrl_payload_buf_cnt;
1667  for (i = 0; i < nb_data; i++) {
1668  *ptr_dest++ = *ptr_src++;
1669  }
1670  udd_ctrl_payload_buf_cnt += nb_data;
1671 
1672  if ((USB_DEVICE_EP_CTRL_SIZE != nb_data)
1673  || (udd_g_ctrlreq.req.wLength <=
1676  // End of reception because it is a short packet
1677  // Before send ZLP, call intermediat calback
1678  // in case of data receiv generate a stall
1681  if (!udd_g_ctrlreq.over_under_run()) {
1682  // Stall ZLP
1684  // Ack reception of OUT to replace NAK by a STALL
1686  return;
1687  }
1688  }
1689  // Send IN ZLP to ACK setup request
1692  return;
1693  }
1694 
1696  // Overrun then request a new payload buffer
1698  // No callback availabled to request a new payload buffer
1700  // Ack reception of OUT to replace NAK by a STALL
1702  return;
1703  }
1704  if (!udd_g_ctrlreq.over_under_run()) {
1705  // No new payload buffer delivered
1707  // Ack reception of OUT to replace NAK by a STALL
1709  return;
1710  }
1711  // New payload buffer available
1712  // Update number of total data received
1714  // Reinit reception on payload buffer
1716  }
1717  // Free buffer of control endpoint to authorize next reception
1719  // To detect a protocol error, enable nak interrupt on data IN phase
1720  udd_ack_nak_in(0);
1721  flags = cpu_irq_save();
1723  cpu_irq_restore(flags);
1724 }
1725 
1726 
1727 static void udd_ctrl_underflow(void)
1728 {
1729  if (Is_udd_out_received(0))
1730  return; // Underflow ignored if OUT data is received
1731 
1733  // Host want to stop OUT transaction
1734  // then stop to wait OUT data phase and wait IN ZLP handshake
1737  // A OUT handshake is waiting by device,
1738  // but host want extra IN data then stall extra IN data
1740  }
1741 }
1742 
1743 
1744 static void udd_ctrl_overflow(void)
1745 {
1746  if (Is_udd_in_send(0))
1747  return; // Overflow ignored if IN data is received
1748 
1749  // The case of UDD_EPCTRL_DATA_IN is not managed
1750  // because the OUT endpoint is already free and OUT ZLP accepted
1751 
1753  // A IN handshake is waiting by device,
1754  // but host want extra OUT data then stall extra OUT data
1756  }
1757 }
1758 
1759 
1760 static void udd_ctrl_stall_data(void)
1761 {
1762  // Stall all packets on IN & OUT control endpoint
1765 }
1766 
1767 
1768 static void udd_ctrl_send_zlp_in(void)
1769 {
1770  irqflags_t flags;
1771 
1773 
1774  // Validate and send empty IN packet on control endpoint
1775  flags = cpu_irq_save();
1776  // Send ZLP on IN endpoint
1777  udd_ack_in_send(0);
1779  // To detect a protocol error, enable nak interrupt on data OUT phase
1780  udd_ack_nak_out(0);
1782  cpu_irq_restore(flags);
1783 }
1784 
1785 
1786 static void udd_ctrl_send_zlp_out(void)
1787 {
1788  irqflags_t flags;
1789 
1791  // No action is necessary to accept OUT ZLP
1792  // because the buffer of control endpoint is already free
1793 
1794  // To detect a protocol error, enable nak interrupt on data IN phase
1795  flags = cpu_irq_save();
1796  udd_ack_nak_in(0);
1798  cpu_irq_restore(flags);
1799 }
1800 
1801 
1802 static void udd_ctrl_endofrequest(void)
1803 {
1804  // If a callback is registered then call it
1805  if (udd_g_ctrlreq.callback) {
1807  }
1808 }
1809 
1810 
1811 static bool udd_ctrl_interrupt(void)
1812 {
1813 
1814  if (!Is_udd_endpoint_interrupt(0)) {
1815  return false; // No interrupt events on control endpoint
1816  }
1817 
1818  dbg_print("0: ");
1819 
1820  // By default disable overflow and underflow interrupt
1823 
1824  // Search event on control endpoint
1825  if (Is_udd_setup_received(0)) {
1826  dbg_print("stup ");
1827  // SETUP packet received
1829  return true;
1830  }
1832  dbg_print("in ");
1833  // IN packet sent
1834  udd_ctrl_in_sent();
1835  return true;
1836  }
1837  if (Is_udd_out_received(0)) {
1838  dbg_print("out ");
1839  // OUT packet received
1841  return true;
1842  }
1843  if (Is_udd_nak_out(0)) {
1844  dbg_print("nako ");
1845  // Overflow on OUT packet
1846  udd_ack_nak_out(0);
1848  return true;
1849  }
1850  if (Is_udd_nak_in(0)) {
1851  dbg_print("naki ");
1852  // Underflow on IN packet
1853  udd_ack_nak_in(0);
1855  return true;
1856  }
1857  dbg_print("n%x ", USBHS_ARRAY(USBHS_DEVEPTISR[0], 0));
1858  return false;
1859 }
1860 
1861 
1862 //--------------------------------------------------------
1863 //--- INTERNAL ROUTINES TO MANAGED THE BULK/INTERRUPT/ISOCHRONOUS ENDPOINTS
1864 
1865 #if (0 != USB_DEVICE_MAX_EP)
1866 
1867 static void udd_ep_job_table_reset(void)
1868 {
1869  uint8_t i;
1870  for (i = 0; i < USB_DEVICE_MAX_EP; i++) {
1871  udd_ep_job[i].busy = false;
1872  udd_ep_job[i].stall_requested = false;
1873  }
1874 }
1875 
1876 
1877 static void udd_ep_job_table_kill(void)
1878 {
1879  uint8_t i;
1880 
1881  // For each endpoint, kill job
1882  for (i = 0; i < USB_DEVICE_MAX_EP; i++) {
1883  udd_ep_finish_job(&udd_ep_job[i], true, i + 1);
1884  }
1885 }
1886 
1887 
1888 static void udd_ep_abort_job(udd_ep_id_t ep)
1889 {
1890  ep &= USB_EP_ADDR_MASK;
1891 
1892  // Abort job on endpoint
1893  udd_ep_finish_job(&udd_ep_job[ep - 1], true, ep);
1894 }
1895 
1896 
1897 static void udd_ep_finish_job(udd_ep_job_t * ptr_job, bool b_abort, uint8_t ep_num)
1898 {
1899  if (ptr_job->busy == false) {
1900  return; // No on-going job
1901  }
1902  dbg_print("(JobE%x:%d) ", (ptr_job-udd_ep_job)+1, b_abort);
1903  ptr_job->busy = false;
1904  if (NULL == ptr_job->call_trans) {
1905  return; // No callback linked to job
1906  }
1907  if (Is_udd_endpoint_in(ep_num)) {
1908  ep_num |= USB_EP_DIR_IN;
1909  }
1910  ptr_job->call_trans((b_abort) ? UDD_EP_TRANSFER_ABORT :
1911  UDD_EP_TRANSFER_OK, ptr_job->buf_size, ep_num);
1912 }
1913 
1914 #ifdef UDD_EP_DMA_SUPPORTED
1915 static void udd_ep_trans_done(udd_ep_id_t ep)
1916 {
1917  uint32_t udd_dma_ctrl = 0;
1918  udd_ep_job_t *ptr_job;
1919  iram_size_t next_trans;
1920  irqflags_t flags;
1921 
1922  // Get job corresponding at endpoint
1923  ptr_job = &udd_ep_job[ep - 1];
1924 
1925  if (!ptr_job->busy) {
1926  return; // No job is running, then ignore it (system error)
1927  }
1928 
1929  if (ptr_job->buf_cnt != ptr_job->buf_size) {
1930  // Need to send or receiv other data
1931  next_trans = ptr_job->buf_size - ptr_job->buf_cnt;
1932 
1933  if (UDD_ENDPOINT_MAX_TRANS < next_trans) {
1934  // The USB hardware support a maximum
1935  // transfer size of UDD_ENDPOINT_MAX_TRANS Bytes
1936  next_trans = UDD_ENDPOINT_MAX_TRANS;
1937 
1938  // Set 0 to tranfer the maximum
1939  udd_dma_ctrl = USBHS_DEVDMACONTROL_BUFF_LENGTH(0);
1940  } else {
1941  udd_dma_ctrl = USBHS_DEVDMACONTROL_BUFF_LENGTH(next_trans);
1942  }
1943  if (Is_udd_endpoint_in(ep)) {
1944  if (0 != (next_trans % udd_get_endpoint_size(ep))) {
1945  // Enable short packet option
1946  // else the DMA transfer is accepted
1947  // and interrupt DMA valid but nothing is sent.
1948  udd_dma_ctrl |= USBHS_DEVDMACONTROL_END_B_EN;
1949  // No need to request another ZLP
1950  ptr_job->b_shortpacket = false;
1951  }
1952  } else {
1954  || (next_trans <= (iram_size_t) udd_get_endpoint_size(ep))) {
1955 
1956  // Enable short packet reception
1957  udd_dma_ctrl |= USBHS_DEVDMACONTROL_END_TR_IT
1959  }
1960  }
1961 
1962  // Start USB DMA to fill or read fifo of the selected endpoint
1963  udd_endpoint_dma_set_addr(ep, (uint32_t) & ptr_job->buf[ptr_job->buf_cnt]);
1964  udd_dma_ctrl |= USBHS_DEVDMACONTROL_END_BUFFIT |
1966 
1967 
1968  // Disable IRQs to have a short sequence
1969  // between read of EOT_STA and DMA enable
1970  flags = cpu_irq_save();
1971  if (!(udd_endpoint_dma_get_status(ep)
1973  dbg_print("dmaS%x ", ep);
1974  udd_endpoint_dma_set_control(ep, udd_dma_ctrl);
1975  ptr_job->buf_cnt += next_trans;
1976  ptr_job->buf_load = next_trans;
1978  cpu_irq_restore(flags);
1979  return;
1980  }
1981  cpu_irq_restore(flags);
1982 
1983  // Here a ZLP has been recieved
1984  // and the DMA transfer must be not started.
1985  // It is the end of transfer
1986  ptr_job->buf_size = ptr_job->buf_cnt;
1987  }
1988  if (Is_udd_endpoint_in(ep)) {
1989  if (ptr_job->b_shortpacket) {
1990  dbg_print("zlpS%x ", ep);
1991  // Need to send a ZLP (No possible with USB DMA)
1992  // enable interrupt to wait a free bank to sent ZLP
1993  udd_ack_in_send(ep);
1994  if (Is_udd_write_enabled(ep)) {
1995  // Force interrupt in case of ep already free
1996  udd_raise_in_send(ep);
1997  }
2000  return;
2001  }
2002  } else {
2003  _dcache_invalidate_prepare(ptr_job->buf, ptr_job->buf_size);
2004  _dcache_invalidate(ptr_job->buf, ptr_job->buf_size);
2005  }
2006  dbg_print("dmaE ");
2007  // Call callback to signal end of transfer
2008  udd_ep_finish_job(ptr_job, false, ep);
2009 }
2010 #endif
2011 
2012 #ifdef UDD_EP_FIFO_SUPPORTED
2013 static void udd_ep_in_sent(udd_ep_id_t ep)
2014 {
2015  udd_ep_job_t *ptr_job = &udd_ep_job[ep - 1];
2016  uint8_t *ptr_src = &ptr_job->buf[ptr_job->buf_cnt];
2017  uint8_t *ptr_dst = (uint8_t *) & udd_get_endpoint_fifo_access(ep, 8);
2018  uint32_t pkt_size = udd_get_endpoint_size(ep);
2019  uint32_t nb_data = 0, i;
2020  uint32_t nb_remain;
2021  irqflags_t flags;
2022 
2023  // All transfer done, including ZLP, Finish Job
2024  if (ptr_job->buf_cnt >= ptr_job->buf_size && !ptr_job->b_shortpacket) {
2025  flags = cpu_irq_save();
2028  cpu_irq_restore(flags);
2029 
2030  ptr_job->buf_size = ptr_job->buf_cnt; // buf_size is passed to callback as XFR count
2031  udd_ep_finish_job(ptr_job, false, ep);
2032  return;
2033  } else {
2034  // ACK TXINI
2035  udd_ack_in_send(ep);
2036  // Fill FIFO
2037  ptr_dst = (uint8_t *) & udd_get_endpoint_fifo_access(ep, 8);
2038  ptr_src = &ptr_job->buf[ptr_job->buf_cnt];
2039  nb_remain = ptr_job->buf_size - ptr_job->buf_cnt;
2040  // Fill a bank even if no data (ZLP)
2041  nb_data = min(nb_remain, pkt_size);
2042  // Modify job information
2043  ptr_job->buf_cnt += nb_data;
2044  ptr_job->buf_load = nb_data;
2045 
2046  // Copy buffer to FIFO
2047  for (i = 0; i < nb_data; i++) {
2048  *ptr_dst++ = *ptr_src++;
2049  }
2050  // Switch to next bank
2051  __DSB();
2052  __ISB();
2053  udd_ack_fifocon(ep);
2054  // ZLP?
2055  if (nb_data < pkt_size) {
2056  ptr_job->b_shortpacket = false;
2057  }
2058  }
2059 }
2060 
2061 static void udd_ep_out_received(udd_ep_id_t ep)
2062 {
2063  udd_ep_job_t *ptr_job = &udd_ep_job[ep - 1];
2064  uint32_t nb_data = 0, i;
2065  uint32_t nb_remain = ptr_job->buf_size - ptr_job->buf_cnt;
2066  uint32_t pkt_size = udd_get_endpoint_size(ep);
2067  uint8_t *ptr_src = (uint8_t *) & udd_get_endpoint_fifo_access(ep, 8);
2068  uint8_t *ptr_dst = &ptr_job->buf[ptr_job->buf_cnt];
2069  bool b_full = false, b_short = false;
2070 
2071  // Clear RX OUT
2073 
2074  // Read byte count
2075  nb_data = udd_byte_count(ep);
2076  if (nb_data < pkt_size) {
2077  b_short = true;
2078  }
2079  //dbg_print("o%d ", ep);
2080  //dbg_print("%d ", nb_data);
2081  // Copy data if there is
2082  if (nb_data > 0) {
2083  if (nb_data >= nb_remain) {
2084  nb_data = nb_remain;
2085  b_full = true;
2086  }
2087  // Modify job information
2088  ptr_job->buf_cnt += nb_data;
2089  ptr_job->buf_load = nb_data;
2090  // Copy FIFO to buffer
2091  for (i = 0; i < nb_data; i++) {
2092  *ptr_dst++ = *ptr_src++;
2093  }
2094  __DSB();
2095  __ISB();
2096  }
2097  // Clear FIFO Status
2098  udd_ack_fifocon(ep);
2099  // Finish job on error or short packet
2100  if (b_full || b_short) {
2101  //dbg_print("EoO%d\n\r", ep);
2104  ptr_job->buf_size = ptr_job->buf_cnt; // buf_size is passed to callback as XFR count
2105  udd_ep_finish_job(ptr_job, false, ep);
2106  }
2107 }
2108 #endif // #ifdef UDD_EP_FIFO_SUPPORTED
2109 
2110 static bool udd_ep_interrupt(void)
2111 {
2112  udd_ep_id_t ep;
2113  udd_ep_job_t *ptr_job;
2114 
2115  // For each endpoint different of control endpoint (0)
2116  for (ep = 1; ep <= USB_DEVICE_MAX_EP; ep++) {
2117  // Get job corresponding at endpoint
2118  ptr_job = &udd_ep_job[ep - 1];
2119 
2120 #ifdef UDD_EP_DMA_SUPPORTED
2121  // Check DMA event
2124  uint32_t nb_remaining;
2127  return true; // Ignore EOT_STA interrupt
2128  }
2129  dbg_print("dma%x: ", ep);
2131  // Save number of data no transfered
2132  nb_remaining = (udd_endpoint_dma_get_status(ep) &
2135  if (nb_remaining) {
2136  // Transfer no complete (short packet or ZLP) then:
2137  // Update number of data transfered
2138  ptr_job->buf_cnt -= nb_remaining;
2139  // Set transfer complete to stop the transfer
2140  ptr_job->buf_size = ptr_job->buf_cnt;
2141  }
2142  udd_ep_trans_done(ep);
2143  return true;
2144  }
2145 #endif
2146 #ifdef UDD_EP_FIFO_SUPPORTED
2147  // Check RXRDY and TXEMPTY event for none DMA endpoints
2150  dbg_print("ep%x: ", ep);
2151  // RXOUT: Full packet received
2152  if (Is_udd_out_received(ep)
2154  dbg_print("Out ");
2155  udd_ep_out_received(ep);
2156  return true;
2157  }
2158  // TXIN: packet sent
2159  if (Is_udd_in_send(ep)
2161  dbg_print("In ");
2162  udd_ep_in_sent(ep);
2163  return true;
2164  }
2165  // Errors: Abort?
2166  if (Is_udd_overflow(ep)
2167  || Is_udd_underflow(ep)
2168  || Is_udd_crc_error(ep)) {
2169  dbg_print("Err ");
2170  udd_ep_abort(ep);
2171  return true;
2172  }
2173  }
2174 #endif // UDD_EP_FIFO_SUPPORTED
2175  // Check empty bank interrupt event
2177  dbg_print("bg%x: ", ep);
2179  && Is_udd_in_send(ep)) {
2180  dbg_print("I ");
2182  // One bank is free then send a ZLP
2183  udd_ack_in_send(ep);
2184  udd_ack_fifocon(ep);
2185  udd_ep_finish_job(ptr_job, false, ep);
2186  return true;
2187  }
2189  && (0 == udd_nb_busy_bank(ep))) {
2190  dbg_print("EoT ");
2191  // End of background transfer on IN endpoint
2194 
2195  Assert(ptr_job->stall_requested);
2196  // A stall has been requested during backgound transfer
2197  ptr_job->stall_requested = false;
2201  return true;
2202  }
2203  }
2204  }
2205  return false;
2206 }
2207 #endif // (0 != USB_DEVICE_MAX_EP)
2208 
#define cpu_irq_disable()
Disable interrupts globally.
#define udd_get_configured_address()
gets the currently configured USB device address
Definition: usbhs_device.h:228
#define udd_enable_endpoint(ep)
enables the selected endpoint
Definition: usbhs_device.h:244
#define USB_DEVICE_EP_CTRL_SIZE
Control endpoint size (Endpoint 0)
Definition: udi_cdc_conf.h:57
#define udd_enable_sof_interrupt()
Definition: usbhs_device.h:183
#define Is_otg_host_mode_forced()
Test if host mode is forced.
Definition: usbhs_otg.h:125
#define Is_udd_write_enabled(ep)
Tests if endpoint write allowed.
Definition: usbhs_device.h:433
void udd_test_mode_packet(void)
#define Is_udd_endpoint_interrupt_enabled(ep)
Tests if the selected endpoint interrupt is enabled.
Definition: usbhs_device.h:327
Common API for USB Device Drivers (UDD)
USB configuration file for CDC application.
#define Is_udd_endpoint_in(ep)
Definition: usbhs_device.h:271
#define udd_high_speed_enable()
Definition: usbhs_device.h:98
Wait a OUT ZLP packet.
Definition: usbhs_device.c:467
#define udd_configure_address(addr)
configures the USB device address
Definition: usbhs_device.h:226
#define USBHS_CTRL_UIMOD_DEVICE
(USBHS_CTRL) The module is in USB Device mode.
#define USBHS_DEVDMACONTROL_CHANN_ENB
(USBHS_DEVDMACONTROL) Channel Enable Command
USB Device Driver for USBHS. Compliant with common UDD driver.
#define USBHS_DEVDMACONTROL_END_TR_EN
(USBHS_DEVDMACONTROL) End of Transfer Enable Control (OUT transfers only)
#define USBHS_DEVEPTCFG_EPBK_3_BANK
(USBHS_DEVEPTCFG[10]) Triple-bank endpoint
#define USBHS_DEVDMACONTROL_END_B_EN
(USBHS_DEVDMACONTROL) End of Buffer Enable Control
#define Is_udd_endpoint_dma_interrupt_enabled(ep)
Tests if the selected endpoint DMA channel interrupt is enabled.
Definition: usbhs_device.h:551
#define USBHS_SLEEP_MODE_USB_IDLE
Definition: usbhs_device.c:368
#define udd_nb_busy_bank(ep)
Returns the number of busy banks.
Definition: usbhs_device.h:443
#define Is_udd_suspend_interrupt_enabled()
Definition: usbhs_device.h:209
#define Is_udd_endpoint_stall_requested(ep)
Tests if STALL handshake request is running.
Definition: usbhs_device.h:346
#define udd_ack_msof()
Definition: usbhs_device.h:198
#define Is_otg_id_device()
Definition: usbhs_otg.h:115
#define UDD_BULK_NB_BANK(ep)
Definition: usbhs_device.c:343
#define USBHS_DEVDMACONTROL_END_TR_IT
(USBHS_DEVDMACONTROL) End of Transfer Interrupt Enable
#define udd_disable_nak_out_interrupt(ep)
Disables NAK OUT interrupt.
Definition: usbhs_device.h:369
#define udd_ack_nak_in(ep)
ACKs NAK IN received.
Definition: usbhs_device.h:376
#define udd_attach_device()
Attaches to USB bus.
Definition: usbhs_device.h:121
#define udd_ack_reset()
Definition: usbhs_device.h:176
#define Is_udd_endpoint_dma_supported(ep)
Get DMA support of endpoints.
Definition: usbhs_device.h:77
#define Is_udd_wake_up()
Definition: usbhs_device.h:167
void udd_disable(void)
Disables the USB Device mode.
Definition: usbhs_device.c:858
#define Is_udd_nak_in(ep)
Tests if NAK IN received.
Definition: usbhs_device.h:374
#define USBHS_DEVEPTCFG_EPBK_1_BANK
(USBHS_DEVEPTCFG[10]) Single-bank endpoint
#define udd_reset_data_toggle(ep)
Resets the data toggle sequence.
Definition: usbhs_device.h:307
#define udd_disable_endpoint_bank_autoswitch(ep)
Disables the bank autoswitch for the selected endpoint.
Definition: usbhs_device.h:265
#define udd_low_speed_disable()
Definition: usbhs_device.h:86
#define PMC_FSMR_USBAL
(PMC_FSMR) USB Alarm Enable
#define USBHS_ARRAY(reg, index)
Definition: usbhs_device.h:238
void udd_test_mode_se0_nak(void)
static irqflags_t cpu_irq_save(void)
Get and clear the global interrupt flags.
static void udd_ctrl_send_zlp_in(void)
Send a ZLP IN on control endpoint.
void udd_send_remotewakeup(void)
The USB driver sends a resume signal called Upstream Resume.
Definition: usbhs_device.c:984
#define udd_endpoint_dma_set_control(ep, desc)
Set control desc to selected endpoint DMA channel.
Definition: usbhs_device.h:621
#define udd_byte_count(ep)
Returns the byte count.
Definition: usbhs_device.h:436
#define udd_ack_sof()
Definition: usbhs_device.h:186
void udd_set_setup_payload(uint8_t *payload, uint16_t payload_size)
Load setup payload.
Definition: usbhs_device.c:997
#define USB_EP_ADDR_MASK
Mask selecting the index part of an endpoint address.
Definition: usb_protocol.h:266
uint16_t udd_get_frame_number(void)
Returns the current start of frame number.
Definition: usbhs_device.c:974
#define otg_freeze_clock()
Stop (freeze) internal USB clock.
Definition: usbhs_otg.h:176
__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
Set Interrupt Priority.
Definition: core_cm7.h:1766
#define udd_endpoint_dma_set_addr(ep, add)
Set RAM address to selected endpoint DMA channel.
Definition: usbhs_device.h:625
#define udd_disable_endpoint_interrupt(ep)
Disables the selected endpoint interrupt.
Definition: usbhs_device.h:325
#define udd_disable_suspend_interrupt()
Definition: usbhs_device.h:208
static void udd_ctrl_send_zlp_out(void)
Send a ZLP OUT on control endpoint.
#define ID_USBHS
USB Host / Device Controller (USBHS)
Definition: same70j19.h:432
uint32_t pmc_disable_periph_clk(uint32_t ul_id)
Disable the specified peripheral clock.
Definition: pmc.c:722
#define udd_disable_bank_interrupt(ep)
Disables all banks full (OUT) or free (IN) interrupt.
Definition: usbhs_device.h:458
#define Is_udd_endpoint_interrupt(ep)
Tests if an interrupt is triggered by the selected endpoint.
Definition: usbhs_device.h:329
Global variable to give and record information of the setup request management.
Definition: udd.h:74
#define Is_otg_clock_usable()
For parts with HS feature, this one corresponding at UTMI clock.
Definition: usbhs_otg.h:173
#define USBHS_DEVDMASTATUS_CHANN_ENB
(USBHS_DEVDMASTATUS) Channel Enable Status
#define Is_udd_crc_error(ep)
Tests if CRC ERROR ISO OUT detected.
Definition: usbhs_device.h:413
static void udd_ctrl_out_received(void)
Managed reception of OUT packet on control endpoint.
uint32_t pmc_enable_periph_clk(uint32_t ul_id)
Enable the specified peripheral clock.
Definition: pmc.c:682
void udd_test_mode_k(void)
#define NULL
Definition: nm_bsp.h:52
#define min(a, b)
Takes the minimal value of a and b.
Definition: compiler.h:812
void(* callback)(void)
Callback called after reception of ZLP from setup request.
Definition: udd.h:87
static bool udd_b_sleep_initialized
State of sleep manager.
Definition: usbhs_device.c:373
#define Udd_setup_is_in()
Return true if the setup request udd_g_ctrlreq indicates IN data transfer.
Definition: udd.h:96
#define Is_otg_id_host()
Definition: usbhs_otg.h:116
#define Is_otg_vbus_high()
Definition: usbhs_otg.h:148
#define udd_disable_stall_handshake(ep)
Disables the STALL handshake.
Definition: usbhs_device.h:344
#define Is_udd_kill_last(ep)
Definition: usbhs_device.h:448
#define udd_get_endpoint_type(ep)
Gets the configured selected endpoint type.
Definition: usbhs_device.h:261
#define udd_ack_fifocon(ep)
Clears FIFOCON bit.
Definition: usbhs_device.h:438
#define Is_udd_reset()
Definition: usbhs_device.h:178
#define udd_enable_reset_interrupt()
Definition: usbhs_device.h:173
#define udd_disable_endpoint_dma_interrupt(ep)
Disables the selected endpoint DMA channel interrupt.
Definition: usbhs_device.h:549
static udd_ctrl_ep_state_t udd_ep_control_state
State of the endpoint control management.
Definition: usbhs_device.c:472
#define udd_ack_out_received(ep)
ACKs OUT received.
Definition: usbhs_device.h:491
#define udd_enable_msof_interrupt()
Definition: usbhs_device.h:195
uint8_t * payload
Definition: udd.h:81
static void cpu_irq_restore(irqflags_t flags)
Restore global interrupt flags.
#define Is_udd_nak_out(ep)
Tests if NAK OUT received.
Definition: usbhs_device.h:361
#define ISR(func)
Define service routine.
#define Is_udd_out_received(ep)
Tests if OUT received.
Definition: usbhs_device.h:489
static uint16_t udd_ctrl_prev_payload_buf_cnt
Total number of data received/sent during data packet phase with previous payload buffers...
Definition: usbhs_device.c:475
void udd_set_address(uint8_t address)
Changes the USB address of device.
Definition: usbhs_device.c:960
#define SCB
Definition: core_cm7.h:1599
#define udd_disable_nak_in_interrupt(ep)
Disables NAK IN interrupt.
Definition: usbhs_device.h:382
Wait a SETUP packet.
Definition: usbhs_device.c:463
#define UDD_ENDPOINT_MAX_TRANS
Maximum transfer size on USB DMA.
Definition: usbhs_device.h:532
static void udd_ctrl_setup_received(void)
Managed reception of SETUP packet on control endpoint.
static void udd_ctrl_stall_data(void)
Managed stall event of IN/OUT packet on control endpoint.
void pmc_set_fast_startup_input(uint32_t ul_inputs)
Set the wake-up inputs for fast startup mode registers (event generation).
Definition: pmc.c:1296
#define USBHS
(USBHS ) Base Address
Definition: same70j19.h:508
#define udd_enable_bank_interrupt(ep)
Enables all banks full (OUT) or free (IN) interrupt.
Definition: usbhs_device.h:456
#define udd_ack_in_send(ep)
ACKs IN sending.
Definition: usbhs_device.h:504
__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn)
Enable External Interrupt.
Definition: core_cm7.h:1683
#define UDD_USB_INT_FUN
Definition: usbhs_device.c:53
#define udd_ack_nak_out(ep)
ACKs NAK OUT received.
Definition: usbhs_device.h:363
uint8_t udd_getaddress(void)
Returns the USB address of device.
Definition: usbhs_device.c:968
static void udd_sleep_mode(bool b_idle)
Authorize or not the CPU powerdown mode.
Definition: usbhs_device.c:380
#define udd_disable_endpoint(ep)
disables the selected endpoint
Definition: usbhs_device.h:246
#define udd_low_speed_enable()
Enable/disable device low-speed mode.
Definition: usbhs_device.h:85
#define udd_disable_out_received_interrupt(ep)
Disables OUT received interrupt.
Definition: usbhs_device.h:497
#define Is_udd_overflow(ep)
Tests if an overflow occurs.
Definition: usbhs_device.h:391
#define Is_udd_wake_up_interrupt_enabled()
Definition: usbhs_device.h:164
bool udd_include_vbus_monitoring(void)
Authorizes the VBUS event.
Definition: usbhs_device.c:754
#define udd_disable_in_send_interrupt(ep)
Disables IN sending interrupt.
Definition: usbhs_device.h:510
#define udd_disable_address()
disables USB device address
Definition: usbhs_device.h:223
static void udd_reset_ep_ctrl(void)
Reset control endpoint.
#define Is_udd_suspend()
Definition: usbhs_device.h:212
void udd_enable(void)
Enables the USB Device mode.
Definition: usbhs_device.c:764
static void udd_ctrl_endofrequest(void)
Call callback associated to setup request.
#define Is_udd_msof()
Definition: usbhs_device.h:200
uint8_t udd_ep_id_t
Endpoint identifier.
Definition: udd.h:59
static void udd_ctrl_overflow(void)
Managed overflow event of OUT packet on control endpoint.
#define udd_ack_stall(ep)
ACKs STALL sent.
Definition: usbhs_device.h:350
#define USBHS_DEVDMASTATUS_END_TR_ST
(USBHS_DEVDMASTATUS) End of Channel Transfer Status
void sysclk_enable_usb(void)
#define USB_EP_DIR_IN
Endpoint transfer direction is IN.
Definition: usb_protocol.h:274
#define udd_enable_endpoint_bank_autoswitch(ep)
Enables the bank autoswitch for the selected endpoint.
Definition: usbhs_device.h:263
#define udd_ack_wake_up()
Definition: usbhs_device.h:165
#define udd_enable_out_received_interrupt(ep)
Enables OUT received interrupt.
Definition: usbhs_device.h:495
#define udd_enable_in_send_interrupt(ep)
Enables IN sending interrupt.
Definition: usbhs_device.h:508
static uint16_t udd_ctrl_payload_buf_cnt
Number of data received/sent to/from udd_g_ctrlreq.payload buffer.
Definition: usbhs_device.c:478
#define Is_udd_underflow(ep)
Tests if an underflow occurs.
Definition: usbhs_device.h:404
#define UDD_USB_INT_LEVEL
Definition: usbhs_device.c:57
Wait a IN data packet.
Definition: usbhs_device.c:465
COMPILER_WORD_ALIGNED udd_ctrl_request_t udd_g_ctrlreq
Global variable to give and record information about setup request management.
Definition: usbhs_device.c:459
Wait a OUT data packet.
Definition: usbhs_device.c:464
#define udd_high_speed_disable()
Definition: usbhs_device.h:99
#define USB_DEVICE_MAX_EP
3 endpoints used per CDC interface
Definition: udi_cdc_conf.h:116
#define Is_udd_full_speed_mode()
Definition: usbhs_device.h:100
void(* udd_callback_trans_t)(udd_ep_status_t status, iram_size_t nb_transfered, udd_ep_id_t ep)
End of transfer callback function type. Registered by routine udd_ep_run() Callback called by USB int...
Definition: udd.h:127
#define udd_enable_nak_in_interrupt(ep)
Enables NAK IN interrupt.
Definition: usbhs_device.h:380
#define USBHS_DEVDMACONTROL_END_BUFFIT
(USBHS_DEVDMACONTROL) End of Buffer Interrupt Enable
#define udd_disable_wake_up_interrupt()
Definition: usbhs_device.h:163
#define otg_vbus_init(handler)
Definition: usbhs_otg.h:146
#define udd_raise_suspend()
Definition: usbhs_device.h:211
#define Is_udd_in_send_interrupt_enabled(ep)
Tests if IN sending interrupt is enabled.
Definition: usbhs_device.h:512
static void udd_ctrl_in_sent(void)
Managed reception of IN packet on control endpoint.
#define udd_raise_in_send(ep)
Raises IN sending.
Definition: usbhs_device.h:506
#define udd_get_endpoint_fifo_access(ep, scale)
Definition: usbhs_device.h:524
#define udd_unallocate_memory(ep)
un-allocates the configuration selected endpoint in DPRAM memory
Definition: usbhs_device.h:287
#define USBHS_DEVEPTCFG_EPBK_2_BANK
(USBHS_DEVEPTCFG[10]) Double-bank endpoint
void sysclk_disable_usb(void)
#define USBHS_SLEEP_MODE_USB_SUSPEND
Definition of sleep levels.
Definition: usbhs_device.c:367
#define Is_udd_out_received_interrupt_enabled(ep)
Tests if OUT received interrupt is enabled.
Definition: usbhs_device.h:499
bool udc_process_setup(void)
Main routine to manage the USB SETUP request.
Definition: udc.c:1092
void(* udd_callback_halt_cleared_t)(void)
End of halt callback function type. Registered by routine udd_ep_wait_stall_clear() Callback called w...
Definition: udd.h:116
#define dbg_print(...)
Definition: usbhs_device.c:102
#define udd_enable_nak_out_interrupt(ep)
Enables NAK OUT interrupt.
Definition: usbhs_device.h:367
static bool udd_ctrl_interrupt(void)
Main interrupt routine for control endpoint.
uint32_t iram_size_t
Definition: compiler.h:260
bool udd_is_high_speed(void)
Test whether the USB Device Controller is running at high speed or not.
Definition: usbhs_device.c:950
enum IRQn IRQn_Type
#define udd_micro_frame_number()
Definition: usbhs_device.h:201
#define udd_enable_endpoint_interrupt(ep)
Enables the selected endpoint interrupt.
Definition: usbhs_device.h:323
#define udd_allocate_memory(ep)
Allocates the configuration selected endpoint in DPRAM memory.
Definition: usbhs_device.h:285
#define udd_detach_device()
Detaches from USB bus.
Definition: usbhs_device.h:119
#define udd_initiate_remote_wake_up()
Definition: usbhs_device.h:133
void udd_detach(void)
Detaches the device from the bus.
Definition: usbhs_device.c:939
void udd_attach(void)
Attach device to the bus when possible.
Definition: usbhs_device.c:898
#define Is_udd_setup_received(ep)
Tests if SETUP received.
Definition: usbhs_device.h:476
usb_setup_req_t req
Definition: udd.h:77
#define udd_frame_number()
Definition: usbhs_device.h:189
bool otg_dual_enable(void)
Initialize the dual role This function is implemented in usbhs_host.c file.
#define le16_to_cpu(x)
Definition: compiler.h:892
#define Is_udd_endpoint_dma_interrupt(ep)
Tests if an interrupt is triggered by the selected endpoint DMA channel.
Definition: usbhs_device.h:545
#define UDD_ISOCHRONOUS_NB_BANK(ep)
Definition: usbhs_device.c:335
#define udd_enable_setup_received_interrupt(ep)
Enables SETUP received interrupt.
Definition: usbhs_device.h:482
#define Is_udd_endpoint_enabled(ep)
tests if the selected endpoint is enabled
Definition: usbhs_device.h:248
#define udd_ack_setup_received(ep)
ACKs SETUP received.
Definition: usbhs_device.h:478
#define otg_unfreeze_clock()
Definition: usbhs_otg.h:177
#define Is_udd_stall(ep)
Tests if STALL sent.
Definition: usbhs_device.h:348
#define Is_udd_sof()
Definition: usbhs_device.h:188
#define Is_udd_bank_interrupt_enabled(ep)
Tests if all banks full (OUT) or free (IN) interrupt enabled.
Definition: usbhs_device.h:460
#define Is_udd_in_send(ep)
Tests if IN sending.
Definition: usbhs_device.h:502
#define udd_endpoint_dma_get_status(ep)
Get status to selected endpoint DMA channel.
Definition: usbhs_device.h:627
uint16_t udd_get_micro_frame_number(void)
Returns the current micro start of frame number.
Definition: usbhs_device.c:979
#define udd_enable_address()
enables USB device address
Definition: usbhs_device.h:221
static void udd_vbus_handler(uint32_t id, uint32_t mask)
Definition: usbhs_device.c:433
uint32_t irqflags_t
Type used for holding state of interrupt flag.
#define udd_kill_last_in_bank(ep)
Kills last bank.
Definition: usbhs_device.h:447
static void udd_ctrl_underflow(void)
Managed underflow event of IN packet on control endpoint.
STALL enabled on IN & OUT packet.
Definition: usbhs_device.c:468
bool(* over_under_run)(void)
Definition: udd.h:91
#define USBHS_DEVDMASTATUS_BUFF_COUNT_Msk
(USBHS_DEVDMASTATUS) Buffer Byte Count
void udc_sof_notify(void)
To signal that a SOF is occurred.
Definition: udc.c:395
static bool udd_b_idle
State of USB line.
Definition: usbhs_device.c:371
Wait a IN ZLP packet.
Definition: usbhs_device.c:466
#define udd_enable_stall_handshake(ep)
Enables the STALL handshake.
Definition: usbhs_device.h:342
static void sleepmgr_lock_mode(enum sleepmgr_mode mode)
Increase lock count for a sleep mode.
Definition: sleepmgr.h:137
uint16_t payload_size
Size of buffer to send or fill, and content the number of byte transfered.
Definition: udd.h:84
#define otg_enable()
Enable USB macro.
Definition: usbhs_otg.h:166
#define UDD_INTERRUPT_NB_BANK(ep)
Definition: usbhs_device.c:351
#define Assert(expr)
This macro is used to test fatal errors.
Definition: compiler.h:196
#define Is_udd_endpoint_configured(ep)
Tests if current endpoint is configured.
Definition: usbhs_device.h:302
#define udd_vbus_monitor_sleep_mode(lock)
Definition: usbhs_device.c:427
#define udd_enable_endpoint_dma_interrupt(ep)
Enables the selected endpoint DMA channel interrupt.
Definition: usbhs_device.h:547
static void sleepmgr_unlock_mode(enum sleepmgr_mode mode)
Decrease lock count for a sleep mode.
Definition: sleepmgr.h:169
udd_ctrl_ep_state_t
Bit definitions about endpoint control state machine for udd_ep_control_state.
Definition: usbhs_device.c:462
#define udd_enable_wake_up_interrupt()
Definition: usbhs_device.h:162
#define udd_enable_suspend_interrupt()
Definition: usbhs_device.h:207
USB OTG Driver for USBHS.
void udd_test_mode_j(void)
static void udd_ctrl_init(void)
Reset control endpoint management.
void udc_reset(void)
Reset the current configuration of the USB device, This routines can be called by UDD when a RESET on...
Definition: udc.c:368
#define udd_get_endpoint_size(ep)
Gets the configured selected endpoint size.
Definition: usbhs_device.h:279
#define otg_disable()
Disable USB macro.
Definition: usbhs_otg.h:168
#define udd_configure_endpoint(ep, type, dir, size, bank)
Configures selected endpoint in one step.
Definition: usbhs_device.h:291
uint8_t bmAttributes
Sleep mode access.


inertial_sense_ros
Author(s):
autogenerated on Sun Feb 28 2021 03:17:58