9
9
any redistribution
10
10
*********************************************************************/
11
11
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
+ */
12
28
13
29
/* This example demonstrates use of Host Serial (CDC). SerialHost (declared below) is
14
30
* an object to manage an CDC peripheral connected to our USB Host connector. This example
15
31
* 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"
26
32
*/
27
33
28
- #ifdef ARDUINO_ARCH_RP2040
29
- // pio-usb is required for rp2040 host
30
- #include " pio_usb.h"
31
-
32
- // Pin D+ for host, D- = D+ + 1
33
- #ifndef PIN_USB_HOST_DP
34
- #define PIN_USB_HOST_DP 16
35
- #endif
36
-
37
- // Pin for enabling Host VBUS. comment out if not used
38
- #ifndef PIN_5V_EN
39
- #define PIN_5V_EN 18
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
40
39
#endif
41
40
42
- #ifndef PIN_5V_EN_STATE
43
- #define PIN_5V_EN_STATE 1
44
- #endif
45
- #endif
46
-
47
- #include " Adafruit_TinyUSB.h"
48
-
49
- #if defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421
50
- #include " SPI.h"
51
- // USB Host using MAX3421E: SPI, CS, INT
52
- Adafruit_USBH_Host USBHost (&SPI, 10 , 9 );
53
- #else
54
- Adafruit_USBH_Host USBHost;
55
- #endif
41
+ // USBHost is defined in usbh_helper.h
42
+ #include " usbh_helper.h"
56
43
57
44
// CDC Host object
58
- Adafruit_USBH_CDC SerialHost;
59
-
45
+ Adafruit_USBH_CDC SerialHost;
60
46
61
- void host_loop ()
62
- {
63
- USBHost. task () ;
47
+ // forward Seral <-> SerialHost
48
+ void forward_serial ( void ) {
49
+ uint8_t buf[ 64 ] ;
64
50
65
- // periodically flush SerialHost if connected
66
- if ( SerialHost && SerialHost.connected () ) {
67
- SerialHost.flush ();
51
+ // Serial -> SerialHost
52
+ if (Serial.available ()) {
53
+ size_t count = Serial.read (buf, sizeof (buf));
54
+ if (SerialHost && SerialHost.connected ()) {
55
+ SerialHost.write (buf, count);
56
+ SerialHost.flush ();
57
+ }
68
58
}
69
59
70
- Serial.flush ();
60
+ // SerialHost -> Serial
61
+ if (SerialHost.connected () && SerialHost.available ()) {
62
+ size_t count = SerialHost.read (buf, sizeof (buf));
63
+ Serial.write (buf, count);
64
+ Serial.flush ();
65
+ }
71
66
}
72
67
73
68
#if defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421
74
69
// --------------------------------------------------------------------+
75
70
// Using Host shield MAX3421E controller
76
71
// --------------------------------------------------------------------+
72
+
73
+ #ifdef USE_FREERTOS
74
+ void usbhost_rtos_task (void *param) {
75
+ (void ) param;
76
+ while (1 ) {
77
+ USBHost.task ();
78
+ }
79
+ }
80
+
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
86
+
77
87
void setup () {
78
88
Serial.begin (115200 );
79
89
80
90
// init host stack on controller (rhport) 1
81
91
USBHost.begin (1 );
82
92
93
+ // Initialize SerialHost
94
+ SerialHost.begin (115200 );
95
+
96
+ #ifdef USE_FREERTOS
97
+ create_usbhost_rtos_task ();
98
+ #endif
99
+
83
100
// while ( !Serial ) delay(10); // wait for native usb
84
101
Serial.println (" TinyUSB Host Serial Echo Example" );
85
102
}
86
103
87
104
void loop () {
88
- host_loop ();
105
+ #ifndef USE_FREERTOS
106
+ USBHost.task ();
107
+ #endif
108
+
109
+ forward_serial ();
89
110
}
90
111
91
112
#elif defined(ARDUINO_ARCH_RP2040)
@@ -97,86 +118,29 @@ void loop() {
97
118
void setup () {
98
119
Serial.begin (115200 );
99
120
// while ( !Serial ) delay(10); // wait for native usb
100
-
101
121
Serial.println (" TinyUSB Host Serial Echo Example" );
102
122
}
103
123
104
124
void loop () {
105
- uint8_t buf[64 ];
106
-
107
- // Serial -> SerialHost
108
- if (Serial.available ()) {
109
- size_t count = Serial.read (buf, sizeof (buf));
110
- if ( SerialHost && SerialHost.connected () ) {
111
- SerialHost.write (buf, count);
112
- SerialHost.flush ();
113
- }
114
- }
115
-
116
- // SerialHost -> Serial
117
- if ( SerialHost.connected () && SerialHost.available () ) {
118
- size_t count = SerialHost.read (buf, sizeof (buf));
119
- Serial.write (buf, count);
120
- }
125
+ forward_serial ();
121
126
}
122
127
123
128
// ------------- Core1 -------------//
124
129
void setup1 () {
125
- // while ( !Serial ) delay(10); // wait for native usb
126
- Serial.println (" Core1 setup to run TinyUSB host with pio-usb" );
127
-
128
- // Check for CPU frequency, must be multiple of 120Mhz for bit-banging USB
129
- uint32_t cpu_hz = clock_get_hz (clk_sys);
130
- if ( cpu_hz != 120000000UL && cpu_hz != 240000000UL ) {
131
- while ( !Serial ) {
132
- delay (10 ); // wait for native usb
133
- }
134
- Serial.printf (" Error: CPU Clock = %lu, PIO USB require CPU clock must be multiple of 120 Mhz\r\n " , cpu_hz);
135
- Serial.printf (" Change your CPU Clock to either 120 or 240 Mhz in Menu->CPU Speed \r\n " );
136
- while (1 ) {
137
- delay (1 );
138
- }
139
- }
140
-
141
- #ifdef PIN_5V_EN
142
- pinMode (PIN_5V_EN, OUTPUT);
143
-
144
- // power off first
145
- digitalWrite (PIN_5V_EN, 1 -PIN_5V_EN_STATE);
146
- delay (1 );
147
-
148
- // power on
149
- digitalWrite (PIN_5V_EN, PIN_5V_EN_STATE);
150
- delay (10 );
151
- #endif
152
-
153
- pio_usb_configuration_t pio_cfg = PIO_USB_DEFAULT_CONFIG;
154
- pio_cfg.pin_dp = PIN_USB_HOST_DP;
155
-
156
- #if defined(ARDUINO_RASPBERRY_PI_PICO_W)
157
- // For pico-w, PIO is also used to communicate with cyw43
158
- // Therefore we need to alternate the pio-usb configuration
159
- // details https://github.com/sekigon-gonnoc/Pico-PIO-USB/issues/46
160
- pio_cfg.sm_tx = 3 ;
161
- pio_cfg.sm_rx = 2 ;
162
- pio_cfg.sm_eop = 3 ;
163
- pio_cfg.pio_rx_num = 0 ;
164
- pio_cfg.pio_tx_num = 1 ;
165
- pio_cfg.tx_ch = 9 ;
166
- #endif
167
-
168
- USBHost.configure_pio_usb (1 , &pio_cfg);
130
+ // configure pio-usb: defined in usbh_helper.h
131
+ rp2040_configure_pio_usb ();
169
132
170
133
// run host stack on controller (rhport) 1
171
134
// Note: For rp2040 pico-pio-usb, calling USBHost.begin() on core1 will have most of the
172
135
// host bit-banging processing works done in core1 to free up core0 for other works
173
136
USBHost.begin (1 );
174
137
138
+ // Initialize SerialHost
175
139
SerialHost.begin (115200 );
176
140
}
177
141
178
142
void loop1 () {
179
- host_loop ();
143
+ USBHost. task ();
180
144
}
181
145
182
146
#endif
0 commit comments