2727#if defined ARDUINO_ARCH_RP2040 & TUSB_OPT_DEVICE_ENABLED
2828
2929#include " Arduino.h"
30- #include " arduino/Adafruit_USBD_Device.h"
31-
3230#include " pico/bootrom.h"
31+ #include " pico/time.h"
32+ #include " hardware/irq.h"
33+ #include " pico/mutex.h"
3334#include " pico/unique_id.h"
3435
36+ #include " tusb.h"
37+ #include " arduino/Adafruit_TinyUSB_API.h"
38+
3539// --------------------------------------------------------------------+
3640// Forward USB interrupt events to TinyUSB IRQ Handler
3741// rp2040 implementation will install approriate handler when initializing
4246// Porting API
4347// --------------------------------------------------------------------+
4448
49+ // USB processing will be a periodic timer task
50+ #define USB_TASK_INTERVAL 1000
51+ #define USB_TASK_IRQ 31
52+
53+ // Big, global USB mutex, shared with all USB devices to make sure we don't
54+ // have multiple cores updating the TUSB state in parallel
55+ mutex_t __usb_mutex;
56+
57+ static void usb_irq () {
58+ // if the mutex is already owned, then we are in user code
59+ // in this file which will do a tud_task itself, so we'll just do nothing
60+ // until the next tick; we won't starve
61+ if (mutex_try_enter (&__usb_mutex, NULL )) {
62+ tud_task ();
63+ mutex_exit (&__usb_mutex);
64+ }
65+ }
66+
67+ static int64_t timer_task (__unused alarm_id_t id, __unused void *user_data) {
68+ irq_set_pending (USB_TASK_IRQ);
69+ return USB_TASK_INTERVAL;
70+ }
71+
4572void TinyUSB_Port_InitDevice (uint8_t rhport)
4673{
4774 (void ) rhport;
4875
49- // no specific hardware initialization
50- // TOOD maybe set up sdtio usb
76+ mutex_init (&__usb_mutex);
77+ tusb_init ();
78+
79+ irq_set_exclusive_handler (USB_TASK_IRQ, usb_irq);
80+ irq_set_enabled (USB_TASK_IRQ, true );
81+
82+ add_alarm_in_us (USB_TASK_INTERVAL, timer_task, NULL , true );
5183}
5284
5385void TinyUSB_Port_EnterDFU (void )
@@ -62,4 +94,25 @@ uint8_t TinyUSB_Port_GetSerialNumber(uint8_t serial_id[16])
6294 return PICO_UNIQUE_BOARD_ID_SIZE_BYTES;
6395}
6496
97+ // --------------------------------------------------------------------+
98+ // Core API
99+ // Implement Core API since rp2040 need mutex for calling tud_task in
100+ // IRQ context
101+ // --------------------------------------------------------------------+
102+
103+ extern " C"
104+ {
105+
106+ void TinyUSB_Device_Task (void )
107+ {
108+ // Since tud_task() is also invoked in ISR, we need to get the mutex first
109+ if (mutex_try_enter (&__usb_mutex, NULL ))
110+ {
111+ tud_task ();
112+ mutex_exit (&__usb_mutex);
113+ }
114+ }
115+
116+ }
117+
65118#endif // USE_TINYUSB
0 commit comments