@@ -226,39 +226,107 @@ int __no_inline_not_in_flash_func(pio_usb_bus_receive_packet_and_handshake)(
226226 return -1 ;
227227}
228228
229- static __always_inline void add_pio_host_rx_program (PIO pio ,
229+ static __always_inline int try_add_pio_host_rx_program (PIO pio ,
230230 const pio_program_t * program ,
231231 const pio_program_t * debug_program ,
232- uint * offset , int debug_pin ) {
233- if (debug_pin < 0 ) {
234- * offset = pio_add_program (pio , program );
235- } else {
236- * offset = pio_add_program (pio , debug_program );
232+ int * offset , int debug_pin ) {
233+ const pio_program_t * prog ;
234+
235+ if (debug_pin < 0 )
236+ prog = program ;
237+ else
238+ prog = debug_program ;
239+
240+ if (pio_can_add_program (pio , prog )) {
241+ * offset = pio_add_program (pio , prog );
242+ return prog -> length ;
237243 }
244+
245+ return -1 ;
238246}
239247
240- static void __no_inline_not_in_flash_func (initialize_host_programs )(
241- pio_port_t * pp , const pio_usb_configuration_t * c , root_port_t * port ) {
248+ static __always_inline void remove_pio_host_rx_program (PIO pio ,
249+ const pio_program_t * program ,
250+ const pio_program_t * debug_program ,
251+ int offset , int debug_pin ) {
252+ if (debug_pin < 0 ) {
253+ pio_remove_program (pio , program , offset );
254+ } else {
255+ pio_remove_program (pio , debug_program , offset );
256+ }
257+ }
258+
259+ static bool __no_inline_not_in_flash_func (try_initialize_host_programs )(
260+ pio_port_t * pp , const pio_usb_configuration_t * c , root_port_t * port ,
261+ uint * tx_inst_count , uint * rx_inst_count ) {
262+ int offset_tx = -1 , offset_rx = -1 , offset_eop = -1 ;
263+ int sm_tx = -1 , sm_rx = -1 , sm_eop = -1 ;
264+ int ret ;
265+
242266 // TX program should be placed at address 0
243- pio_add_program_at_offset (pp -> pio_usb_tx , pp -> fs_tx_program , 0 );
244- pp -> offset_tx = 0 ;
267+ if (pio_can_add_program_at_offset (pp -> pio_usb_tx , pp -> fs_tx_program , 0 )) {
268+ offset_tx = pio_add_program_at_offset (pp -> pio_usb_tx , pp -> fs_tx_program , 0 );
269+ if (tx_inst_count )
270+ * tx_inst_count = pp -> fs_tx_program -> length ;
271+ } else {
272+ goto err_out ;
273+ }
274+ ret = try_add_pio_host_rx_program (pp -> pio_usb_rx , & usb_nrzi_decoder_program ,
275+ & usb_nrzi_decoder_debug_program , & offset_rx , c -> debug_pin_rx );
276+ if (ret <= 0 )
277+ goto err_out ;
278+ if (rx_inst_count )
279+ * rx_inst_count = ret ;
280+ ret = try_add_pio_host_rx_program (pp -> pio_usb_rx , & usb_edge_detector_program ,
281+ & usb_edge_detector_debug_program , & offset_eop , c -> debug_pin_eop );
282+ if (ret <= 0 )
283+ goto err_out ;
284+ if (rx_inst_count )
285+ * rx_inst_count += ret ;
286+ if (c -> sm_tx < 0 ) {
287+ sm_tx = pio_claim_unused_sm (pp -> pio_usb_tx , false);
288+ if (sm_tx < 0 )
289+ goto err_out ;
290+ } else {
291+ pp -> sm_tx = c -> sm_tx ;
292+ pio_sm_claim (pp -> pio_usb_tx , pp -> sm_tx );
293+ }
294+ if (c -> sm_rx < 0 ) {
295+ sm_rx = pio_claim_unused_sm (pp -> pio_usb_rx , false);
296+ if (sm_rx < 0 )
297+ goto err_out ;
298+ } else {
299+ pp -> sm_rx = c -> sm_rx ;
300+ pio_sm_claim (pp -> pio_usb_rx , pp -> sm_rx );
301+ }
302+ if (c -> sm_eop < 0 ) {
303+ sm_eop = pio_claim_unused_sm (pp -> pio_usb_rx , false);
304+ if (sm_eop < 0 )
305+ goto err_out ;
306+ } else {
307+ pp -> sm_eop = c -> sm_eop ;
308+ pio_sm_claim (pp -> pio_usb_rx , pp -> sm_eop );
309+ }
310+ pp -> offset_tx = offset_tx ;
311+ pp -> offset_rx = offset_rx ;
312+ pp -> offset_eop = offset_eop ;
313+ if (c -> sm_rx < 0 )
314+ pp -> sm_rx = sm_rx ;
315+ if (c -> sm_tx < 0 )
316+ pp -> sm_tx = sm_tx ;
317+ if (c -> sm_eop < 0 )
318+ pp -> sm_eop = sm_eop ;
245319 usb_tx_fs_program_init (pp -> pio_usb_tx , pp -> sm_tx , pp -> offset_tx , port -> pin_dp ,
246320 port -> pin_dm );
247321 pp -> tx_start_instr = pio_encode_jmp (pp -> offset_tx + 4 );
248322 pp -> tx_reset_instr = pio_encode_jmp (pp -> offset_tx + 2 );
249323
250- add_pio_host_rx_program (pp -> pio_usb_rx , & usb_nrzi_decoder_program ,
251- & usb_nrzi_decoder_debug_program , & pp -> offset_rx ,
252- c -> debug_pin_rx );
253324 usb_rx_fs_program_init (pp -> pio_usb_rx , pp -> sm_rx , pp -> offset_rx , port -> pin_dp ,
254325 port -> pin_dm , c -> debug_pin_rx );
255326 pp -> rx_reset_instr = pio_encode_jmp (pp -> offset_rx );
256327 pp -> rx_reset_instr2 = pio_encode_set (pio_x , 0 );
257328
258- add_pio_host_rx_program (pp -> pio_usb_rx , & usb_edge_detector_program ,
259- & usb_edge_detector_debug_program , & pp -> offset_eop ,
260- c -> debug_pin_eop );
261- eop_detect_fs_program_init (pp -> pio_usb_rx , c -> sm_eop , pp -> offset_eop ,
329+ eop_detect_fs_program_init (pp -> pio_usb_rx , pp -> sm_eop , pp -> offset_eop ,
262330 port -> pin_dp , port -> pin_dm , true,
263331 c -> debug_pin_eop );
264332
@@ -267,6 +335,25 @@ static void __no_inline_not_in_flash_func(initialize_host_programs)(
267335 pio_sm_set_jmp_pin (pp -> pio_usb_rx , pp -> sm_rx , port -> pin_dp );
268336 pio_sm_set_jmp_pin (pp -> pio_usb_rx , pp -> sm_eop , port -> pin_dm );
269337 pio_sm_set_in_pins (pp -> pio_usb_rx , pp -> sm_eop , port -> pin_dp );
338+
339+ return true;
340+
341+ err_out :
342+ if (offset_tx >= 0 )
343+ pio_remove_program (pp -> pio_usb_tx , pp -> fs_tx_program , offset_tx );
344+ if (offset_rx >= 0 )
345+ remove_pio_host_rx_program (pp -> pio_usb_rx , & usb_nrzi_decoder_program ,
346+ & usb_nrzi_decoder_debug_program , offset_rx , c -> debug_pin_rx );
347+ if (offset_eop >= 0 )
348+ remove_pio_host_rx_program (pp -> pio_usb_rx , & usb_edge_detector_program ,
349+ & usb_edge_detector_debug_program , offset_eop , c -> debug_pin_eop );
350+ if (sm_tx >= 0 )
351+ pio_sm_unclaim (pp -> pio_usb_tx , sm_tx );
352+ if (sm_rx >= 0 )
353+ pio_sm_unclaim (pp -> pio_usb_rx , sm_rx );
354+ if (sm_eop >= 0 )
355+ pio_sm_unclaim (pp -> pio_usb_rx , sm_eop );
356+ return false;
270357}
271358
272359static void configure_tx_channel (uint8_t ch , PIO pio , uint sm ) {
@@ -281,15 +368,43 @@ static void configure_tx_channel(uint8_t ch, PIO pio, uint sm) {
281368 dma_channel_set_write_addr (ch , & pio -> txf [sm ], false);
282369}
283370
371+ static bool init_host_programs (
372+ pio_port_t * pp , const pio_usb_configuration_t * c , root_port_t * port ,
373+ uint * tx_inst_count , uint * rx_inst_count ) {
374+ bool pio_rx_auto = false, pio_tx_auto = false;
375+
376+ if (!pp -> pio_usb_tx ) {
377+ pio_tx_auto = true;
378+ pp -> pio_usb_tx = pio0 ;
379+ }
380+ if (!pp -> pio_usb_rx ) {
381+ pio_rx_auto = true;
382+ pp -> pio_usb_rx = pio1 ;
383+ }
384+ if (try_initialize_host_programs (pp , c , port , tx_inst_count , rx_inst_count ))
385+ return true;
386+ if (!pio_tx_auto && !pio_rx_auto )
387+ return false;
388+ if (pio_tx_auto )
389+ pp -> pio_usb_tx = pio1 ;
390+ if (pio_rx_auto )
391+ pp -> pio_usb_rx = pio0 ;
392+ return try_initialize_host_programs (pp , c , port , tx_inst_count , rx_inst_count );
393+ }
394+
284395static void apply_config (pio_port_t * pp , const pio_usb_configuration_t * c ,
285396 root_port_t * port ) {
286- pp -> pio_usb_tx = pio_get_instance (c -> pio_tx_num );
287- pp -> sm_tx = c -> sm_tx ;
288- pp -> tx_ch = c -> tx_ch ;
289- pp -> pio_usb_rx = pio_get_instance (c -> pio_rx_num );
290- pp -> sm_rx = c -> sm_rx ;
291- pp -> sm_eop = c -> sm_eop ;
292- port -> pin_dp = c -> pin_dp ;
397+ if (c -> pio_tx_num >= 0 )
398+ pp -> pio_usb_tx = pio_get_instance (c -> pio_tx_num );
399+ else
400+ pp -> pio_usb_tx = NULL ;
401+
402+ if (c -> pio_rx_num >=-0 )
403+ pp -> pio_usb_rx = pio_get_instance (c -> pio_rx_num );
404+ else
405+ pp -> pio_usb_tx = NULL ;
406+
407+ port -> pin_dp = c -> pin_dp ;
293408
294409 uint highest_pin ;
295410 if (c -> pinout == PIO_USB_PINOUT_DPDM ) {
@@ -319,10 +434,6 @@ static void apply_config(pio_port_t *pp, const pio_usb_configuration_t *c,
319434
320435 pp -> debug_pin_rx = c -> debug_pin_rx ;
321436 pp -> debug_pin_eop = c -> debug_pin_eop ;
322-
323- pio_sm_claim (pp -> pio_usb_tx , pp -> sm_tx );
324- pio_sm_claim (pp -> pio_usb_rx , pp -> sm_rx );
325- pio_sm_claim (pp -> pio_usb_rx , pp -> sm_eop );
326437}
327438
328439static void port_pin_drive_setting (const root_port_t * port ) {
@@ -332,16 +443,36 @@ static void port_pin_drive_setting(const root_port_t *port) {
332443 gpio_set_drive_strength (port -> pin_dm , GPIO_DRIVE_STRENGTH_12MA );
333444}
334445
446+ static void get_dma_channel (pio_port_t * pp , const pio_usb_configuration_t * c ) {
447+ if (c -> tx_ch < 0 ) {
448+ pp -> tx_ch = dma_claim_unused_channel (true);
449+ } else {
450+ pp -> tx_ch = c -> tx_ch ;
451+ dma_channel_claim (pp -> tx_ch + 1 );
452+ }
453+ }
454+
455+ static void dump_allocated_hw_resources (
456+ const pio_port_t * pp , uint tx_inst_count , uint rx_inst_count ) {
457+ printf ("pio-usb is using:\n" );
458+ printf ("\tUSB transmitter: %d instructions @ PIO %d, State Machine %d, DMA %d\n" ,
459+ tx_inst_count , pp -> pio_usb_tx == pio1 ? 1 : 0 , pp -> sm_tx , pp -> tx_ch );
460+ printf ("\tUSB receiver: %d instructions @ PIO %d, State Machines %d and %d\n" ,
461+ rx_inst_count , pp -> pio_usb_rx == pio1 ? 1 : 0 , pp -> sm_rx , pp -> sm_eop );
462+ }
463+
335464void pio_usb_bus_init (pio_port_t * pp , const pio_usb_configuration_t * c ,
336465 root_port_t * root ) {
337- memset ( root , 0 , sizeof ( root_port_t )) ;
466+ uint tx_inst_count = 0 , rx_inst_count = 0 ;
338467
339- pp -> pio_usb_tx = pio_get_instance (c -> pio_tx_num );
340- dma_claim_mask (1 <<c -> tx_ch );
341- configure_tx_channel (c -> tx_ch , pp -> pio_usb_tx , c -> sm_tx );
468+ memset (root , 0 , sizeof (root_port_t ));
469+ get_dma_channel (pp , c );
342470
343471 apply_config (pp , c , root );
344- initialize_host_programs (pp , c , root );
472+ if (!init_host_programs (pp , c , root , & tx_inst_count , & rx_inst_count ))
473+ panic ("pio-usb: Not enough hardware resources - State Machines and instructions" );
474+ configure_tx_channel (pp -> tx_ch , pp -> pio_usb_tx , pp -> sm_tx );
475+
345476 port_pin_drive_setting (root );
346477 root -> initialized = true;
347478 root -> dev_addr = 0 ;
@@ -355,6 +486,8 @@ void pio_usb_bus_init(pio_port_t *pp, const pio_usb_configuration_t *c,
355486 pio_usb_ll_encode_tx_data (raw_packet , 2 , stall_encoded );
356487 raw_packet [1 ] = USB_PID_PRE ;
357488 pio_usb_ll_encode_tx_data (raw_packet , 2 , pre_encoded );
489+
490+ dump_allocated_hw_resources (pp , tx_inst_count , rx_inst_count );
358491}
359492
360493//--------------------------------------------------------------------+
0 commit comments