99 any redistribution
1010*********************************************************************/
1111
12+ /* This example demonstrates use of both device and host, where
13+ * - Device run on native usb controller (roothub port0)
14+ * - Host depending on MCUs run on either:
15+ * - rp2040: bit-banging 2 GPIOs with the help of Pico-PIO-USB library (roothub port1)
16+ * - samd21/51, nrf52840, esp32: using MAX3421e controller (host shield)
17+ *
18+ * Requirements:
19+ * - For rp2040:
20+ * - [Pico-PIO-USB](https://github.com/sekigon-gonnoc/Pico-PIO-USB) library
21+ * - 2 consecutive GPIOs: D+ is defined by PIN_USB_HOST_DP, D- = D+ +1
22+ * - Provide VBus (5v) and GND for peripheral
23+ * - CPU Speed must be either 120 or 240 Mhz. Selected via "Menu -> CPU Speed"
24+ * - For samd21/51, nrf52840, esp32:
25+ * - Additional MAX2341e USB Host shield or featherwing is required
26+ * - SPI instance, CS pin, INT pin are correctly configured in usbh_helper.h
27+ */
1228
1329/* This example demonstrates use of Host Serial (CDC). SerialHost (declared below) is
1430 * an object to manage an CDC peripheral connected to our USB Host connector. This example
1531 * will forward all characters from Serial to SerialHost and vice versa.
16- *
17- * Note:
18- * - Device run on native usb controller (controller0)
19- * - Host run on bit-banging 2 GPIOs with the help of Pico-PIO-USB library (controller1)
20-
21- * Requirements:
22- * - [Pico-PIO-USB](https://github.com/sekigon-gonnoc/Pico-PIO-USB) library
23- * - 2 consecutive GPIOs: D+ is defined by PIN_USB_HOST_DP, D- = D+ +1
24- * - Provide VBus (5v) and GND for peripheral
25- * - CPU Speed must be either 120 or 240 Mhz. Selected via "Menu -> CPU Speed"
2632 */
2733
28- // pio-usb is required for rp2040 host
29- #include " pio_usb.h"
30-
31- // TinyUSB lib
32- #include " Adafruit_TinyUSB.h"
33-
34- // Pin D+ for host, D- = D+ + 1
35- #ifndef PIN_USB_HOST_DP
36- #define PIN_USB_HOST_DP 16
34+ // nRF52 and ESP32 use freeRTOS, we may need to run USBhost.task() in its own rtos's thread.
35+ // Since USBHost.task() will put loop() into dormant state and prevent followed code from running
36+ // until there is USB host event.
37+ #if defined(ARDUINO_NRF52_ADAFRUIT) || defined(ARDUINO_ARCH_ESP32)
38+ #define USE_FREERTOS
3739#endif
3840
39- // Pin for enabling Host VBUS. comment out if not used
40- #ifndef PIN_5V_EN
41- #define PIN_5V_EN 18
42- #endif
43-
44- #ifndef PIN_5V_EN_STATE
45- #define PIN_5V_EN_STATE 1
46- #endif
47-
48- // USB Host object
49- Adafruit_USBH_Host USBHost;
41+ // USBHost is defined in usbh_helper.h
42+ #include " usbh_helper.h"
5043
5144// CDC Host object
52- Adafruit_USBH_CDC SerialHost;
53-
54- // --------------------------------------------------------------------+
55- // Setup and Loop on Core0
56- // --------------------------------------------------------------------+
45+ Adafruit_USBH_CDC SerialHost;
5746
58- void setup () {
59- Serial.begin (115200 );
60- // while ( !Serial ) delay(10); // wait for native usb
61-
62- Serial.println (" TinyUSB Host Serial Echo Example" );
63- }
64-
65- void loop ()
66- {
47+ // forward Seral <-> SerialHost
48+ void forward_serial (void ) {
6749 uint8_t buf[64 ];
6850
6951 // Serial -> SerialHost
7052 if (Serial.available ()) {
7153 size_t count = Serial.read (buf, sizeof (buf));
72- if ( SerialHost && SerialHost.connected () ) {
54+ if (SerialHost && SerialHost.connected ()) {
7355 SerialHost.write (buf, count);
7456 SerialHost.flush ();
7557 }
7658 }
7759
7860 // SerialHost -> Serial
79- if ( SerialHost.connected () && SerialHost.available () ) {
61+ if (SerialHost.connected () && SerialHost.available ()) {
8062 size_t count = SerialHost.read (buf, sizeof (buf));
8163 Serial.write (buf, count);
64+ Serial.flush ();
8265 }
8366}
8467
68+ #if defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421
8569// --------------------------------------------------------------------+
86- // Setup and Loop on Core1
70+ // Using Host shield MAX3421E controller
8771// --------------------------------------------------------------------+
8872
89- void setup1 () {
90- // while ( !Serial ) delay(10); // wait for native usb
91- Serial.println (" Core1 setup to run TinyUSB host with pio-usb" );
92-
93- // Check for CPU frequency, must be multiple of 120Mhz for bit-banging USB
94- uint32_t cpu_hz = clock_get_hz (clk_sys);
95- if ( cpu_hz != 120000000UL && cpu_hz != 240000000UL ) {
96- while ( !Serial ) {
97- delay (10 ); // wait for native usb
98- }
99- Serial.printf (" Error: CPU Clock = %lu, PIO USB require CPU clock must be multiple of 120 Mhz\r\n " , cpu_hz);
100- Serial.printf (" Change your CPU Clock to either 120 or 240 Mhz in Menu->CPU Speed \r\n " );
101- while (1 ) {
102- delay (1 );
103- }
73+ #ifdef USE_FREERTOS
74+ void usbhost_rtos_task (void *param) {
75+ (void ) param;
76+ while (1 ) {
77+ USBHost.task ();
10478 }
79+ }
10580
106- #ifdef PIN_5V_EN
107- pinMode (PIN_5V_EN, OUTPUT);
81+ void create_usbhost_rtos_task (void ) {
82+ const uint32_t usbh_stack_size = 200 ;
83+ xTaskCreate (usbhost_rtos_task, " usbh" , usbh_stack_size, NULL , TASK_PRIO_HIGH, NULL );
84+ }
85+ #endif
10886
109- // power off first
110- digitalWrite (PIN_5V_EN, 1 -PIN_5V_EN_STATE);
111- delay (1 );
87+ void setup () {
88+ Serial.begin (115200 );
89+
90+ // init host stack on controller (rhport) 1
91+ USBHost.begin (1 );
11292
113- // power on
114- digitalWrite (PIN_5V_EN, PIN_5V_EN_STATE);
115- delay (10 );
93+ // Initialize SerialHost
94+ SerialHost.begin (115200 );
95+
96+ #ifdef USE_FREERTOS
97+ create_usbhost_rtos_task ();
11698#endif
11799
118- pio_usb_configuration_t pio_cfg = PIO_USB_DEFAULT_CONFIG;
119- pio_cfg.pin_dp = PIN_USB_HOST_DP;
120-
121- #if defined(ARDUINO_RASPBERRY_PI_PICO_W)
122- // For pico-w, PIO is also used to communicate with cyw43
123- // Therefore we need to alternate the pio-usb configuration
124- // details https://github.com/sekigon-gonnoc/Pico-PIO-USB/issues/46
125- pio_cfg.sm_tx = 3 ;
126- pio_cfg.sm_rx = 2 ;
127- pio_cfg.sm_eop = 3 ;
128- pio_cfg.pio_rx_num = 0 ;
129- pio_cfg.pio_tx_num = 1 ;
130- pio_cfg.tx_ch = 9 ;
100+ // while ( !Serial ) delay(10); // wait for native usb
101+ Serial.println (" TinyUSB Host Serial Echo Example" );
102+ }
103+
104+ void loop () {
105+ #ifndef USE_FREERTOS
106+ USBHost.task ();
131107#endif
132108
133- USBHost.configure_pio_usb (1 , &pio_cfg);
109+ forward_serial ();
110+ }
111+
112+ #elif defined(ARDUINO_ARCH_RP2040)
113+ // --------------------------------------------------------------------+
114+ // For RP2040 use both core0 for device stack, core1 for host stack
115+ // --------------------------------------------------------------------+
116+
117+ // ------------- Core0 -------------//
118+ void setup () {
119+ Serial.begin (115200 );
120+ // while ( !Serial ) delay(10); // wait for native usb
121+ Serial.println (" TinyUSB Host Serial Echo Example" );
122+ }
123+
124+ void loop () {
125+ forward_serial ();
126+ }
127+
128+ // ------------- Core1 -------------//
129+ void setup1 () {
130+ // configure pio-usb: defined in usbh_helper.h
131+ rp2040_configure_pio_usb ();
134132
135133 // run host stack on controller (rhport) 1
136134 // Note: For rp2040 pico-pio-usb, calling USBHost.begin() on core1 will have most of the
137135 // host bit-banging processing works done in core1 to free up core0 for other works
138136 USBHost.begin (1 );
139137
138+ // Initialize SerialHost
140139 SerialHost.begin (115200 );
141140}
142141
143- void loop1 ()
144- {
142+ void loop1 () {
145143 USBHost.task ();
146-
147- // periodically flush SerialHost if connected
148- if ( SerialHost && SerialHost.connected () ) {
149- SerialHost.flush ();
150- }
151144}
152145
146+ #endif
147+
153148// --------------------------------------------------------------------+
154149// TinyUSB Host callbacks
155150// --------------------------------------------------------------------+
@@ -169,4 +164,4 @@ void tuh_cdc_umount_cb(uint8_t idx) {
169164 Serial.println (" SerialHost is disconnected" );
170165}
171166
172- }
167+ }
0 commit comments