@@ -96,6 +96,20 @@ static bool _has_program_room(uint8_t pio_index, uint8_t program_size) {
9696 return pio_can_add_program (pio , & program_struct );
9797}
9898
99+ // from pico-sdk/src/rp2_common/hardware_pio/pio.c
100+ static bool is_gpio_compatible (PIO pio , uint32_t used_gpio_ranges ) {
101+ #if PICO_PIO_VERSION > 0
102+ bool gpio_base = pio_get_gpio_base (pio );
103+ return !((gpio_base && (used_gpio_ranges & 1 )) ||
104+ (!gpio_base && (used_gpio_ranges & 4 )));
105+ #else
106+ ((void )pio );
107+ ((void )used_gpio_ranges );
108+ return true;
109+ #endif
110+ }
111+
112+
99113usb_host_port_obj_t * common_hal_usb_host_port_construct (const mcu_pin_obj_t * dp , const mcu_pin_obj_t * dm ) {
100114 if (dp -> number + 1 != dm -> number ) {
101115 raise_ValueError_invalid_pins ();
@@ -113,15 +127,31 @@ usb_host_port_obj_t *common_hal_usb_host_port_construct(const mcu_pin_obj_t *dp,
113127 assert_pin_free (dp );
114128 assert_pin_free (dm );
115129
130+ #if PICO_PIO_VERSION > 0
131+ uint32_t used_gpio_ranges = 0 ;
132+ #else
133+ uint gpio_base = dm -> number ;
134+ uint gpio_count = 2 ;
135+ uint32_t required_gpio_ranges = (1u << (gpio_base >> 4 )) |
136+ (1u << ((gpio_base + gpio_count - 1 ) >> 4 ));
137+ #endif
138+
116139 pio_usb_configuration_t pio_cfg = PIO_USB_DEFAULT_CONFIG ;
117140 pio_cfg .skip_alarm_pool = true;
118141 pio_cfg .pin_dp = dp -> number ;
119142 // Allocating the peripherals like this works on Pico W, where the
120143 // "preferred PIO" for the cyw43 wifi chip is PIO 1.
121144 pio_cfg .pio_tx_num = 1 ; // uses 22 instructions and 1 SM
122145 pio_cfg .pio_rx_num = 0 ; // uses 31 instructions and 2 SM.
123- if (!_has_program_room (pio_cfg .pio_tx_num , 22 ) || _sm_free_count (pio_cfg .pio_tx_num ) < 1 ||
124- !_has_program_room (pio_cfg .pio_rx_num , 31 ) || _sm_free_count (pio_cfg .pio_rx_num ) < 2 ) {
146+ uint8_t tx_sm_free = _sm_free_count (pio_cfg .pio_tx_num );
147+ uint8_t rx_sm_free = _sm_free_count (pio_cfg .pio_rx_num );
148+ PIO pio_tx = pio_instances [pio_cfg .pio_tx_num ];
149+ PIO pio_rx = pio_instances [pio_cfg .pio_rx_num ];
150+
151+ if (!_has_program_room (pio_cfg .pio_tx_num , 22 ) || tx_sm_free < 1 ||
152+ !(tx_sm_free == 4 || is_gpio_compatible (pio_tx , used_gpio_ranges )) ||
153+ !_has_program_room (pio_cfg .pio_rx_num , 31 ) || rx_sm_free < 2 ||
154+ !(rx_sm_free == 4 || is_gpio_compatible (pio_rx , used_gpio_ranges ))) {
125155 mp_raise_RuntimeError (MP_ERROR_TEXT ("All state machines in use" ));
126156 }
127157 pio_cfg .tx_ch = dma_claim_unused_channel (false); // DMA channel
0 commit comments