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
@@ -457,33 +466,38 @@ static int64_t timer_task(__unused alarm_id_t id, __unused void *user_data) {
457466 return USB_TASK_INTERVAL;
458467}
459468
460- void usbDisconnect () {
469+ void RP2040USB::disconnect () {
470+ bool wasConnected = tud_connected ();
461471#ifdef __FREERTOS
462472 auto m = __get_freertos_mutex_for_ptr (&__usb_mutex);
463473 xSemaphoreTake (m, portMAX_DELAY);
464474 tud_disconnect ();
465- vTaskDelay (500 / portTICK_PERIOD_MS);
475+ if (wasConnected) {
476+ vTaskDelay (500 / portTICK_PERIOD_MS);
477+ }
466478 xSemaphoreGive (m);
467479#else
468480 mutex_enter_blocking (&__usb_mutex);
469481 tud_disconnect ();
470- sleep_ms (500 );
482+ if (wasConnected) {
483+ sleep_ms (500 );
484+ }
471485 mutex_exit (&__usb_mutex);
472486#endif
473487 // Ensure when we reconnect we make the new descriptor
474488 free (usbd_desc_cfg);
475489 usbd_desc_cfg = nullptr ;
476490 usbd_desc_cfg_len = 0 ;
477491 if (__hid_report) {
478- usbUnregisterInterface (__hid_interface);
479- usbUnregisterEndpointIn (__hid_endpoint);
492+ unregisterInterface (__hid_interface);
493+ unregisterEndpointIn (__hid_endpoint);
480494 }
481495 free (__hid_report);
482496 __hid_report = nullptr ;
483497 __hid_report_len = 0 ;
484498}
485499
486- void usbConnect () {
500+ void RP2040USB::connect () {
487501 __SetupDescHIDReport ();
488502 __SetupUSBDescriptor ();
489503
@@ -499,9 +513,33 @@ void usbConnect() {
499513#endif
500514}
501515
502- void __USBStart () __attribute__((weak));
503516
504- void __USBStart () {
517+
518+
519+
520+ #ifdef __FREERTOS
521+ void __freertos_usb_task (void *param) {
522+ (void ) param;
523+
524+ Serial.begin (115200 );
525+
526+ USB.initted = true ;
527+
528+ while (true ) {
529+ BaseType_t ss = xTaskGetSchedulerState ();
530+ if (ss != taskSCHEDULER_SUSPENDED) {
531+ auto m = __get_freertos_mutex_for_ptr (&__usb_mutex);
532+ if (xSemaphoreTake (m, 0 )) {
533+ tud_task ();
534+ xSemaphoreGive (m);
535+ }
536+ }
537+ vTaskDelay (1 / portTICK_PERIOD_MS);
538+ }
539+ }
540+ #endif
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