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;
@@ -108,7 +117,7 @@ static int ffs(uint32_t v) {
108117 return 0 ;
109118}
110119
111- uint8_t usbRegisterEndpointIn () {
120+ uint8_t RP2040USB::registerEndpointIn () {
112121 if (!_endpointIn) {
113122 return 0 ; // ERROR, out of EPs
114123 }
@@ -117,11 +126,11 @@ uint8_t usbRegisterEndpointIn() {
117126 return 0x80 + firstFree;
118127}
119128
120- void usbUnregisterEndpointIn (int ep) {
129+ void RP2040USB::unregisterEndpointIn (int ep) {
121130 _endpointIn |= 1 << ep;
122131}
123132
124- uint8_t usbRegisterEndpointOut () {
133+ uint8_t RP2040USB::registerEndpointOut () {
125134 if (!_endpointOut) {
126135 return 0 ; // ERROR, out of EPs
127136 }
@@ -130,7 +139,7 @@ uint8_t usbRegisterEndpointOut() {
130139 return firstFree;
131140}
132141
133- void usbUnregisterEndpointOut (int ep) {
142+ void RP2040USB::unregisterEndpointOut (int ep) {
134143 _endpointOut |= (1 << (ep - 0x80 ));
135144}
136145
@@ -198,33 +207,33 @@ static unsigned int usbFindID(Entry *head, unsigned int localid) {
198207 return x;
199208}
200209
201- uint8_t usbFindHIDReportID (unsigned int localid) {
210+ uint8_t RP2040USB::findHIDReportID (unsigned int localid) {
202211 return usbFindID (_hids, localid) + 1 ; // HID reports start at 1
203212}
204213
205- uint8_t usbFindInterfaceID (unsigned int localid) {
214+ uint8_t RP2040USB::findInterfaceID (unsigned int localid) {
206215 return usbFindID (_interfaces, localid);
207216}
208217
209218// 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) {
219+ uint8_t RP2040USB::registerHIDDevice (const uint8_t *descriptor, size_t len, int ordering, uint32_t vidMask) {
211220 return AddEntry (&_hids, 0 , descriptor, len, ordering, vidMask);
212221}
213222
214- void usbUnregisterHIDDevice (unsigned int localid) {
223+ void RP2040USB::unregisterHIDDevice (unsigned int localid) {
215224 RemoveEntry (&_hids, localid);
216225}
217226
218227// 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) {
228+ uint8_t RP2040USB::registerInterface (int interfaces, const uint8_t *descriptor, size_t len, int ordering, uint32_t vidMask) {
220229 return AddEntry (&_interfaces, interfaces, descriptor, len, ordering, vidMask);
221230}
222231
223- void usbUnregisterInterface (unsigned int localid) {
232+ void RP2040USB::unregisterInterface (unsigned int localid) {
224233 RemoveEntry (&_interfaces, localid);
225234}
226235
227- uint8_t usbRegisterString (const char *str) {
236+ uint8_t RP2040USB::registerString (const char *str) {
228237 if (usbd_desc_str_alloc <= usbd_desc_str_cnt) {
229238 usbd_desc_str_alloc += 4 ;
230239 usbd_desc_str = (const char **)realloc (usbd_desc_str, usbd_desc_str_alloc * sizeof (usbd_desc_str[0 ]));
@@ -246,22 +255,22 @@ uint8_t usbRegisterString(const char *str) {
246255
247256static uint16_t _forceVID = 0 ;
248257static uint16_t _forcePID = 0 ;
249- void usbSetVIDPID (uint16_t vid, uint16_t pid) {
258+ void RP2040USB::setVIDPID (uint16_t vid, uint16_t pid) {
250259 _forceVID = vid;
251260 _forcePID = pid;
252261}
253262
254263static uint8_t _forceManuf = 0 ;
255264static uint8_t _forceProd = 0 ;
256265static uint8_t _forceSerial = 0 ;
257- void usbSetManufacturer (const char *str) {
258- _forceManuf = usbRegisterString (str);
266+ void RP2040USB::setManufacturer (const char *str) {
267+ _forceManuf = USB. registerString (str);
259268}
260- void usbSetProduct (const char *str) {
261- _forceProd = usbRegisterString (str);
269+ void RP2040USB::setProduct (const char *str) {
270+ _forceProd = USB. registerString (str);
262271}
263- void usbSetSerialNumber (const char *str) {
264- _forceSerial = usbRegisterString (str);
272+ void RP2040USB::setSerialNumber (const char *str) {
273+ _forceSerial = USB. registerString (str);
265274}
266275
267276static tusb_desc_device_t usbd_desc_device;
@@ -282,9 +291,9 @@ const uint8_t *tud_descriptor_device_cb(void) {
282291 .idVendor = _forceVID ? _forceVID : (uint16_t )USBD_VID,
283292 .idProduct = _forcePID ? _forcePID : (uint16_t )USBD_PID,
284293 .bcdDevice = 0x0100 ,
285- .iManufacturer = _forceManuf ? _forceManuf : usbRegisterString (USB_MANUFACTURER),
286- .iProduct = _forceProd ? _forceProd : usbRegisterString (USB_PRODUCT),
287- .iSerialNumber = _forceSerial ? _forceSerial : usbRegisterString (idString),
294+ .iManufacturer = _forceManuf ? _forceManuf : USB. registerString (USB_MANUFACTURER),
295+ .iProduct = _forceProd ? _forceProd : USB. registerString (USB_PRODUCT),
296+ .iSerialNumber = _forceSerial ? _forceSerial : USB. registerString (idString),
288297 .bNumConfigurations = 1
289298 };
290299
@@ -373,14 +382,14 @@ void __SetupUSBDescriptor() {
373382 if (GetDescHIDReport (&hid_report_len)) {
374383 uint8_t hid_desc[TUD_HID_DESC_LEN] = {
375384 // 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)
385+ 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)
377386 };
378- __hid_interface = usbRegisterInterface (1 , hid_desc, sizeof (hid_desc), 10 , 0 );
387+ __hid_interface = USB. registerInterface (1 , hid_desc, sizeof (hid_desc), 10 , 0 );
379388 }
380389
381390#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 );
391+ uint8_t picotool_desc[] = { TUD_RPI_RESET_DESCRIPTOR (1 , USB. registerString (" Reset" )) };
392+ USB. registerInterface (1 , picotool_desc, sizeof (picotool_desc), 100 , 0 );
384393#endif
385394
386395 usbd_desc_cfg_len = TUD_CONFIG_DESC_LEN; // Always have a config descriptor
@@ -393,7 +402,7 @@ void __SetupUSBDescriptor() {
393402
394403 uint8_t tud_cfg_desc[TUD_CONFIG_DESC_LEN] = {
395404 // 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)
405+ TUD_CONFIG_DESCRIPTOR (1 , interface_count, USB. registerString (" " ), usbd_desc_cfg_len, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, USBD_MAX_POWER_MA)
397406 };
398407
399408 // Allocate the "real" HID report descriptor
@@ -441,6 +450,27 @@ const uint16_t *tud_descriptor_string_cb(uint8_t index, uint16_t langid) {
441450 return desc_str;
442451}
443452
453+ #ifdef __FREERTOS
454+ void __freertos_usb_task (void *param) {
455+ (void ) param;
456+
457+ Serial.begin (115200 );
458+
459+ USB.initted = true ;
460+
461+ while (true ) {
462+ BaseType_t ss = xTaskGetSchedulerState ();
463+ if (ss != taskSCHEDULER_SUSPENDED) {
464+ auto m = __get_freertos_mutex_for_ptr (&__usb_mutex);
465+ if (xSemaphoreTake (m, 0 )) {
466+ tud_task ();
467+ xSemaphoreGive (m);
468+ }
469+ }
470+ vTaskDelay (1 / portTICK_PERIOD_MS);
471+ }
472+ }
473+ #else
444474
445475static void usb_irq () {
446476 // if the mutex is already owned, then we are in user code
@@ -456,34 +486,40 @@ static int64_t timer_task(__unused alarm_id_t id, __unused void *user_data) {
456486 irq_set_pending (__usb_task_irq);
457487 return USB_TASK_INTERVAL;
458488}
489+ #endif
459490
460- void usbDisconnect () {
491+ void RP2040USB::disconnect () {
492+ bool wasConnected = tud_connected ();
461493#ifdef __FREERTOS
462494 auto m = __get_freertos_mutex_for_ptr (&__usb_mutex);
463495 xSemaphoreTake (m, portMAX_DELAY);
464496 tud_disconnect ();
465- vTaskDelay (500 / portTICK_PERIOD_MS);
497+ if (wasConnected) {
498+ vTaskDelay (500 / portTICK_PERIOD_MS);
499+ }
466500 xSemaphoreGive (m);
467501#else
468502 mutex_enter_blocking (&__usb_mutex);
469503 tud_disconnect ();
470- sleep_ms (500 );
504+ if (wasConnected) {
505+ sleep_ms (500 );
506+ }
471507 mutex_exit (&__usb_mutex);
472508#endif
473509 // Ensure when we reconnect we make the new descriptor
474510 free (usbd_desc_cfg);
475511 usbd_desc_cfg = nullptr ;
476512 usbd_desc_cfg_len = 0 ;
477513 if (__hid_report) {
478- usbUnregisterInterface (__hid_interface);
479- usbUnregisterEndpointIn (__hid_endpoint);
514+ unregisterInterface (__hid_interface);
515+ unregisterEndpointIn (__hid_endpoint);
480516 }
481517 free (__hid_report);
482518 __hid_report = nullptr ;
483519 __hid_report_len = 0 ;
484520}
485521
486- void usbConnect () {
522+ void RP2040USB::connect () {
487523 __SetupDescHIDReport ();
488524 __SetupUSBDescriptor ();
489525
@@ -499,9 +535,12 @@ void usbConnect() {
499535#endif
500536}
501537
502- void __USBStart () __attribute__((weak));
503538
504- void __USBStart () {
539+
540+
541+
542+
543+ void RP2040USB::begin () {
505544 if (tusb_inited ()) {
506545 // Already called
507546 return ;
@@ -514,15 +553,21 @@ void __USBStart() {
514553
515554 tusb_init ();
516555
556+ #ifdef __FREERTOS
557+ // Make high prio and locked to core 0
558+ TaskHandle_t usbTask;
559+ xTaskCreate (__freertos_usb_task, " USB" , 256 , 0 , configMAX_PRIORITIES - 2 , &usbTask);
560+ vTaskCoreAffinitySet (usbTask, 1 << 0 );
561+ #else
517562 __usb_task_irq = user_irq_claim_unused (true );
518563 irq_set_exclusive_handler (__usb_task_irq, usb_irq);
519564 irq_set_enabled (__usb_task_irq, true );
520-
521565 add_alarm_in_us (USB_TASK_INTERVAL, timer_task, nullptr , true );
566+ #endif
522567}
523568
524569
525- bool __USBHIDReady () {
570+ bool RP2040USB::HIDReady () {
526571 uint32_t start = millis ();
527572 const uint32_t timeout = 500 ;
528573
0 commit comments