3434#include  < pico/usb_reset_interface.h> 
3535#include  < hardware/watchdog.h> 
3636
37+ #ifdef  __FREERTOS
38+ #include  " FreeRTOS.h" 
39+ #include  " task.h" 
40+ #include  " timers.h" 
41+ #include  " semphr.h" 
42+ #endif 
43+ 
44+ RP2040USB USB;
45+ 
3746//  Big, global USB mutex, shared with all USB devices to make sure we don't
3847//  have multiple cores updating the TUSB state in parallel
3948mutex_t  __usb_mutex;
4049
4150//  USB processing will be a periodic timer task
4251#define  USB_TASK_INTERVAL  1000 
43- static  int  __usb_task_irq;
4452
4553#ifndef  USBD_VID
4654#define  USBD_VID  (0x2E8A ) //  Raspberry Pi
@@ -108,7 +116,7 @@ static int ffs(uint32_t v) {
108116    return  0 ;
109117}
110118
111- uint8_t  usbRegisterEndpointIn () {
119+ uint8_t  RP2040USB::registerEndpointIn () {
112120    if  (!_endpointIn) {
113121        return  0 ; //  ERROR, out of EPs
114122    }
@@ -117,11 +125,11 @@ uint8_t usbRegisterEndpointIn() {
117125    return  0x80  + firstFree;
118126}
119127
120- void  usbUnregisterEndpointIn (int  ep) {
128+ void  RP2040USB::unregisterEndpointIn (int  ep) {
121129    _endpointIn |= 1  << ep;
122130}
123131
124- uint8_t  usbRegisterEndpointOut () {
132+ uint8_t  RP2040USB::registerEndpointOut () {
125133    if  (!_endpointOut) {
126134        return  0 ; //  ERROR, out of EPs
127135    }
@@ -130,7 +138,7 @@ uint8_t usbRegisterEndpointOut() {
130138    return  firstFree;
131139}
132140
133- void  usbUnregisterEndpointOut (int  ep) {
141+ void  RP2040USB::unregisterEndpointOut (int  ep) {
134142    _endpointOut |= (1  << (ep - 0x80 ));
135143}
136144
@@ -198,33 +206,33 @@ static unsigned int usbFindID(Entry *head, unsigned int localid) {
198206    return  x;
199207}
200208
201- uint8_t  usbFindHIDReportID (unsigned  int  localid) {
209+ uint8_t  RP2040USB::findHIDReportID (unsigned  int  localid) {
202210    return  usbFindID (_hids, localid) + 1 ; //  HID reports start at 1
203211}
204212
205- uint8_t  usbFindInterfaceID (unsigned  int  localid) {
213+ uint8_t  RP2040USB::findInterfaceID (unsigned  int  localid) {
206214    return  usbFindID (_interfaces, localid);
207215}
208216
209217//  Called by a HID device to register a report.  Returns the *local* ID which must be mapped to the HID report ID
210- uint8_t  usbRegisterHIDDevice (const  uint8_t  *descriptor, size_t  len, int  ordering, uint32_t  vidMask) {
218+ uint8_t  RP2040USB::registerHIDDevice (const  uint8_t  *descriptor, size_t  len, int  ordering, uint32_t  vidMask) {
211219    return  AddEntry (&_hids, 0 , descriptor, len, ordering, vidMask);
212220}
213221
214- void  usbUnregisterHIDDevice (unsigned  int  localid) {
222+ void  RP2040USB::unregisterHIDDevice (unsigned  int  localid) {
215223    RemoveEntry (&_hids, localid);
216224}
217225
218226//  Called by an object at global init time to add a new interface (non-HID, like CDC or Picotool)
219- uint8_t  usbRegisterInterface (int  interfaces, const  uint8_t  *descriptor, size_t  len, int  ordering, uint32_t  vidMask) {
227+ uint8_t  RP2040USB::registerInterface (int  interfaces, const  uint8_t  *descriptor, size_t  len, int  ordering, uint32_t  vidMask) {
220228    return  AddEntry (&_interfaces, interfaces, descriptor, len, ordering, vidMask);
221229}
222230
223- void  usbUnregisterInterface (unsigned  int  localid) {
231+ void  RP2040USB::unregisterInterface (unsigned  int  localid) {
224232    RemoveEntry (&_interfaces, localid);
225233}
226234
227- uint8_t  usbRegisterString (const  char  *str) {
235+ uint8_t  RP2040USB::registerString (const  char  *str) {
228236    if  (usbd_desc_str_alloc <= usbd_desc_str_cnt) {
229237        usbd_desc_str_alloc += 4 ;
230238        usbd_desc_str = (const  char  **)realloc (usbd_desc_str, usbd_desc_str_alloc * sizeof (usbd_desc_str[0 ]));
@@ -246,22 +254,22 @@ uint8_t usbRegisterString(const char *str) {
246254
247255static  uint16_t  _forceVID = 0 ;
248256static  uint16_t  _forcePID = 0 ;
249- void  usbSetVIDPID (uint16_t  vid, uint16_t  pid) {
257+ void  RP2040USB::setVIDPID (uint16_t  vid, uint16_t  pid) {
250258    _forceVID = vid;
251259    _forcePID = pid;
252260}
253261
254262static  uint8_t  _forceManuf = 0 ;
255263static  uint8_t  _forceProd = 0 ;
256264static  uint8_t  _forceSerial = 0 ;
257- void  usbSetManufacturer (const  char  *str) {
258-     _forceManuf = usbRegisterString (str);
265+ void  RP2040USB::setManufacturer (const  char  *str) {
266+     _forceManuf = USB. registerString (str);
259267}
260- void  usbSetProduct (const  char  *str) {
261-     _forceProd = usbRegisterString (str);
268+ void  RP2040USB::setProduct (const  char  *str) {
269+     _forceProd = USB. registerString (str);
262270}
263- void  usbSetSerialNumber (const  char  *str) {
264-     _forceSerial = usbRegisterString (str);
271+ void  RP2040USB::setSerialNumber (const  char  *str) {
272+     _forceSerial = USB. registerString (str);
265273}
266274
267275static  tusb_desc_device_t  usbd_desc_device;
@@ -282,9 +290,9 @@ const uint8_t *tud_descriptor_device_cb(void) {
282290        .idVendor  = _forceVID ? _forceVID : (uint16_t )USBD_VID,
283291        .idProduct  = _forcePID ? _forcePID : (uint16_t )USBD_PID,
284292        .bcdDevice  = 0x0100 ,
285-         .iManufacturer  = _forceManuf ? _forceManuf : usbRegisterString (USB_MANUFACTURER),
286-         .iProduct  = _forceProd ? _forceProd : usbRegisterString (USB_PRODUCT),
287-         .iSerialNumber  = _forceSerial ? _forceSerial : usbRegisterString (idString),
293+         .iManufacturer  = _forceManuf ? _forceManuf : USB. registerString (USB_MANUFACTURER),
294+         .iProduct  = _forceProd ? _forceProd : USB. registerString (USB_PRODUCT),
295+         .iSerialNumber  = _forceSerial ? _forceSerial : USB. registerString (idString),
288296        .bNumConfigurations  = 1 
289297    };
290298
@@ -373,14 +381,14 @@ void __SetupUSBDescriptor() {
373381    if  (GetDescHIDReport (&hid_report_len)) {
374382        uint8_t  hid_desc[TUD_HID_DESC_LEN] = {
375383            //  Interface number, string index, protocol, report descriptor len, EP In & Out address, size & polling interval
376-             TUD_HID_DESCRIPTOR (1  /*  placeholder*/  , 0 , HID_ITF_PROTOCOL_NONE, hid_report_len, __hid_endpoint = usbRegisterEndpointIn (), CFG_TUD_HID_EP_BUFSIZE, (uint8_t )usb_hid_poll_interval)
384+             TUD_HID_DESCRIPTOR (1  /*  placeholder*/  , 0 , HID_ITF_PROTOCOL_NONE, hid_report_len, __hid_endpoint = USB. registerEndpointIn (), CFG_TUD_HID_EP_BUFSIZE, (uint8_t )usb_hid_poll_interval)
377385        };
378-         __hid_interface = usbRegisterInterface (1 , hid_desc, sizeof (hid_desc), 10 , 0 );
386+         __hid_interface = USB. registerInterface (1 , hid_desc, sizeof (hid_desc), 10 , 0 );
379387    }
380388
381389#ifdef  ENABLE_PICOTOOL_USB
382-     uint8_t  picotool_desc[] = { TUD_RPI_RESET_DESCRIPTOR (1 , usbRegisterString (" Reset"  )) };
383-     usbRegisterInterface (1 , picotool_desc, sizeof (picotool_desc), 100 , 0 );
390+     uint8_t  picotool_desc[] = { TUD_RPI_RESET_DESCRIPTOR (1 , USB. registerString (" Reset"  )) };
391+     USB. registerInterface (1 , picotool_desc, sizeof (picotool_desc), 100 , 0 );
384392#endif 
385393
386394    usbd_desc_cfg_len = TUD_CONFIG_DESC_LEN; //  Always have a config descriptor
@@ -393,7 +401,7 @@ void __SetupUSBDescriptor() {
393401
394402    uint8_t  tud_cfg_desc[TUD_CONFIG_DESC_LEN] = {
395403        //  Config number, interface count, string index, total length, attribute, power in mA
396-         TUD_CONFIG_DESCRIPTOR (1 , interface_count, usbRegisterString (" "  ), usbd_desc_cfg_len, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, USBD_MAX_POWER_MA)
404+         TUD_CONFIG_DESCRIPTOR (1 , interface_count, USB. registerString (" "  ), usbd_desc_cfg_len, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, USBD_MAX_POWER_MA)
397405    };
398406
399407    //  Allocate the "real" HID report descriptor
@@ -441,7 +449,28 @@ const uint16_t *tud_descriptor_string_cb(uint8_t index, uint16_t langid) {
441449    return  desc_str;
442450}
443451
452+ #ifdef  __FREERTOS
453+ void  __freertos_usb_task (void  *param) {
454+     (void ) param;
455+ 
456+     Serial.begin (115200 );
457+ 
458+     USB.initted  = true ;
444459
460+     while  (true ) {
461+         BaseType_t ss = xTaskGetSchedulerState ();
462+         if  (ss != taskSCHEDULER_SUSPENDED) {
463+             auto  m = __get_freertos_mutex_for_ptr (&__usb_mutex);
464+             if  (xSemaphoreTake (m, 0 )) {
465+                 tud_task ();
466+                 xSemaphoreGive (m);
467+             }
468+         }
469+         vTaskDelay (1  / portTICK_PERIOD_MS);
470+     }
471+ }
472+ #else 
473+ static  int  __usb_task_irq;
445474static  void  usb_irq () {
446475    //  if the mutex is already owned, then we are in user code
447476    //  in this file which will do a tud_task itself, so we'll just do nothing
@@ -456,34 +485,40 @@ static int64_t timer_task(__unused alarm_id_t id, __unused void *user_data) {
456485    irq_set_pending (__usb_task_irq);
457486    return  USB_TASK_INTERVAL;
458487}
488+ #endif 
459489
460- void  usbDisconnect () {
490+ void  RP2040USB::disconnect () {
491+     bool  wasConnected = tud_connected ();
461492#ifdef  __FREERTOS
462493    auto  m = __get_freertos_mutex_for_ptr (&__usb_mutex);
463494    xSemaphoreTake (m, portMAX_DELAY);
464495    tud_disconnect ();
465-     vTaskDelay (500  / portTICK_PERIOD_MS);
496+     if  (wasConnected) {
497+         vTaskDelay (500  / portTICK_PERIOD_MS);
498+     }
466499    xSemaphoreGive (m);
467500#else 
468501    mutex_enter_blocking (&__usb_mutex);
469502    tud_disconnect ();
470-     sleep_ms (500 );
503+     if  (wasConnected) {
504+         sleep_ms (500 );
505+     }
471506    mutex_exit (&__usb_mutex);
472507#endif 
473508    //  Ensure when we reconnect we make the new descriptor
474509    free (usbd_desc_cfg);
475510    usbd_desc_cfg = nullptr ;
476511    usbd_desc_cfg_len = 0 ;
477512    if  (__hid_report) {
478-         usbUnregisterInterface (__hid_interface);
479-         usbUnregisterEndpointIn (__hid_endpoint);
513+         unregisterInterface (__hid_interface);
514+         unregisterEndpointIn (__hid_endpoint);
480515    }
481516    free (__hid_report);
482517    __hid_report = nullptr ;
483518    __hid_report_len = 0 ;
484519}
485520
486- void  usbConnect ()  {
521+ void  RP2040USB::connect ()  {
487522    __SetupDescHIDReport ();
488523    __SetupUSBDescriptor ();
489524
@@ -499,9 +534,12 @@ void usbConnect()  {
499534#endif 
500535}
501536
502- void  __USBStart () __attribute__((weak));
503537
504- void  __USBStart () {
538+ 
539+ 
540+ 
541+ 
542+ void  RP2040USB::begin () {
505543    if  (tusb_inited ()) {
506544        //  Already called
507545        return ;
@@ -514,15 +552,21 @@ void __USBStart() {
514552
515553    tusb_init ();
516554
555+ #ifdef  __FREERTOS
556+     //  Make high prio and locked to core 0
557+     TaskHandle_t usbTask;
558+     xTaskCreate (__freertos_usb_task, " USB"  , 256 , 0 , configMAX_PRIORITIES - 2 , &usbTask);
559+     vTaskCoreAffinitySet (usbTask, 1  << 0 );
560+ #else 
517561    __usb_task_irq = user_irq_claim_unused (true );
518562    irq_set_exclusive_handler (__usb_task_irq, usb_irq);
519563    irq_set_enabled (__usb_task_irq, true );
520- 
521564    add_alarm_in_us (USB_TASK_INTERVAL, timer_task, nullptr , true );
565+ #endif 
522566}
523567
524568
525- bool  __USBHIDReady () {
569+ bool  RP2040USB::HIDReady () {
526570    uint32_t  start = millis ();
527571    const  uint32_t  timeout = 500 ;
528572
0 commit comments