@@ -202,43 +202,154 @@ int __no_inline_not_in_flash_func(pio_usb_bus_receive_packet_and_handshake)(
202202 return -1 ;
203203}
204204
205- static __always_inline void add_pio_host_rx_program (PIO pio ,
205+ static __always_inline int try_add_pio_host_rx_program (PIO pio ,
206206 const pio_program_t * program ,
207207 const pio_program_t * debug_program ,
208- uint * offset , int debug_pin ) {
208+ int * offset , int debug_pin ) {
209+ const pio_program_t * prog ;
210+
211+ if (debug_pin < 0 )
212+ prog = program ;
213+ else
214+ prog = debug_program ;
215+
216+ if (pio_can_add_program (pio , prog )) {
217+ * offset = pio_add_program (pio , prog );
218+ return prog -> length ;
219+ }
220+
221+ return -1 ;
222+ }
223+
224+ static __always_inline void remove_pio_host_rx_program (PIO pio ,
225+ const pio_program_t * program ,
226+ const pio_program_t * debug_program ,
227+ int offset , int debug_pin ) {
209228 if (debug_pin < 0 ) {
210- * offset = pio_add_program (pio , program );
229+ pio_remove_program (pio , program , offset );
211230 } else {
212- * offset = pio_add_program (pio , debug_program );
231+ pio_remove_program (pio , debug_program , offset );
213232 }
214233}
215234
216- static void __no_inline_not_in_flash_func (initialize_host_programs )(
217- pio_port_t * pp , const pio_usb_configuration_t * c , root_port_t * port ) {
218- pp -> offset_tx = pio_add_program (pp -> pio_usb_tx , pp -> fs_tx_program );
235+ static bool __no_inline_not_in_flash_func (try_initialize_host_programs )(
236+ pio_port_t * pp , const pio_usb_configuration_t * c , root_port_t * port ,
237+ uint * tx_inst_count , uint * rx_inst_count ) {
238+ int offset_tx = -1 , offset_rx = -1 , offset_eop = -1 ;
239+ int sm_tx = -1 , sm_rx = -1 , sm_eop = -1 ;
240+ int ret ;
241+
242+ if (pio_can_add_program (pp -> pio_usb_tx , pp -> fs_tx_program )) {
243+ offset_tx = pio_add_program (pp -> pio_usb_tx , pp -> fs_tx_program );
244+ if (tx_inst_count )
245+ * tx_inst_count = pp -> fs_tx_program -> length ;
246+ } else {
247+ goto err_out ;
248+ }
249+ ret = try_add_pio_host_rx_program (pp -> pio_usb_rx , & usb_nrzi_decoder_program ,
250+ & usb_nrzi_decoder_debug_program , & offset_rx , c -> debug_pin_rx );
251+ if (ret <= 0 )
252+ goto err_out ;
253+ if (rx_inst_count )
254+ * rx_inst_count = ret ;
255+ ret = try_add_pio_host_rx_program (pp -> pio_usb_rx , & usb_edge_detector_program ,
256+ & usb_edge_detector_debug_program , & offset_eop , c -> debug_pin_eop );
257+ if (ret <= 0 )
258+ goto err_out ;
259+ if (rx_inst_count )
260+ * rx_inst_count += ret ;
261+ if (c -> sm_tx < 0 ) {
262+ sm_tx = pio_claim_unused_sm (pp -> pio_usb_tx , false);
263+ if (sm_tx < 0 )
264+ goto err_out ;
265+ } else {
266+ pp -> sm_tx = c -> sm_tx ;
267+ pio_sm_claim (pp -> pio_usb_tx , pp -> sm_tx );
268+ }
269+
270+ if (c -> sm_rx < 0 ) {
271+ sm_rx = pio_claim_unused_sm (pp -> pio_usb_rx , false);
272+ if (sm_rx < 0 )
273+ goto err_out ;
274+ } else {
275+ pp -> sm_rx = c -> sm_rx ;
276+ pio_sm_claim (pp -> pio_usb_rx , pp -> sm_rx );
277+ }
278+ if (c -> sm_eop < 0 ) {
279+ sm_eop = pio_claim_unused_sm (pp -> pio_usb_rx , false);
280+ if (sm_eop < 0 )
281+ goto err_out ;
282+ } else {
283+ pp -> sm_eop = c -> sm_eop ;
284+ pio_sm_claim (pp -> pio_usb_rx , pp -> sm_eop );
285+ }
286+
287+ pp -> offset_tx = offset_tx ;
288+ pp -> offset_rx = offset_rx ;
289+ pp -> offset_eop = offset_eop ;
290+ if (c -> sm_rx < 0 )
291+ pp -> sm_rx = sm_rx ;
292+ if (c -> sm_tx < 0 )
293+ pp -> sm_tx = sm_tx ;
294+ if (c -> sm_eop < 0 )
295+ pp -> sm_eop = sm_eop ;
219296 usb_tx_fs_program_init (pp -> pio_usb_tx , pp -> sm_tx , pp -> offset_tx ,
220297 port -> pin_dp , port -> pin_dm );
221-
222- add_pio_host_rx_program (pp -> pio_usb_rx , & usb_nrzi_decoder_program ,
223- & usb_nrzi_decoder_debug_program , & pp -> offset_rx ,
224- c -> debug_pin_rx );
225298 usb_rx_fs_program_init (pp -> pio_usb_rx , pp -> sm_rx , pp -> offset_rx , port -> pin_dp ,
226299 port -> pin_dm , c -> debug_pin_rx );
227- pp -> rx_reset_instr = pio_encode_jmp (pp -> offset_rx );
228- pp -> rx_reset_instr2 = pio_encode_set (pio_x , 0 );
229-
230- add_pio_host_rx_program (pp -> pio_usb_rx , & usb_edge_detector_program ,
231- & usb_edge_detector_debug_program , & pp -> offset_eop ,
232- c -> debug_pin_eop );
233- eop_detect_fs_program_init (pp -> pio_usb_rx , c -> sm_eop , pp -> offset_eop ,
300+ eop_detect_fs_program_init (pp -> pio_usb_rx , pp -> sm_eop , pp -> offset_eop ,
234301 port -> pin_dp , port -> pin_dm , true,
235302 c -> debug_pin_eop );
303+ pp -> rx_reset_instr = pio_encode_jmp (pp -> offset_rx );
304+ pp -> rx_reset_instr2 = pio_encode_set (pio_x , 0 );
236305
237306 usb_tx_configure_pins (pp -> pio_usb_tx , pp -> sm_tx , port -> pin_dp , port -> pin_dm );
238-
239307 pio_sm_set_jmp_pin (pp -> pio_usb_rx , pp -> sm_rx , port -> pin_dp );
240308 pio_sm_set_jmp_pin (pp -> pio_usb_rx , pp -> sm_eop , port -> pin_dm );
241309 pio_sm_set_in_pins (pp -> pio_usb_rx , pp -> sm_eop , port -> pin_dp );
310+
311+ return true;
312+
313+ err_out :
314+ if (offset_tx >= 0 )
315+ pio_remove_program (pp -> pio_usb_tx , pp -> fs_tx_program , offset_tx );
316+ if (offset_rx >= 0 )
317+ remove_pio_host_rx_program (pp -> pio_usb_rx , & usb_nrzi_decoder_program ,
318+ & usb_nrzi_decoder_debug_program , offset_rx , c -> debug_pin_rx );
319+ if (offset_eop >= 0 )
320+ remove_pio_host_rx_program (pp -> pio_usb_rx , & usb_edge_detector_program ,
321+ & usb_edge_detector_debug_program , offset_eop , c -> debug_pin_eop );
322+ if (sm_tx >= 0 )
323+ pio_sm_unclaim (pp -> pio_usb_tx , sm_tx );
324+ if (sm_rx >= 0 )
325+ pio_sm_unclaim (pp -> pio_usb_rx , sm_rx );
326+ if (sm_eop >= 0 )
327+ pio_sm_unclaim (pp -> pio_usb_rx , sm_eop );
328+ return false;
329+ }
330+
331+ static bool init_host_programs (
332+ pio_port_t * pp , const pio_usb_configuration_t * c , root_port_t * port ,
333+ uint * tx_inst_count , uint * rx_inst_count ) {
334+ bool pio_rx_auto = false, pio_tx_auto = false;
335+
336+ if (!pp -> pio_usb_tx ) {
337+ pio_tx_auto = true;
338+ pp -> pio_usb_tx = pio0 ;
339+ }
340+ if (!pp -> pio_usb_rx ) {
341+ pio_rx_auto = true;
342+ pp -> pio_usb_rx = pio1 ;
343+ }
344+ if (try_initialize_host_programs (pp , c , port , tx_inst_count , rx_inst_count ))
345+ return true;
346+ if (!pio_tx_auto && !pio_rx_auto )
347+ return false;
348+ if (pio_tx_auto )
349+ pp -> pio_usb_tx = pio1 ;
350+ if (pio_rx_auto )
351+ pp -> pio_usb_rx = pio0 ;
352+ return try_initialize_host_programs (pp , c , port , tx_inst_count , rx_inst_count );
242353}
243354
244355static void configure_tx_channel (uint8_t ch , PIO pio , uint sm ) {
@@ -255,12 +366,14 @@ static void configure_tx_channel(uint8_t ch, PIO pio, uint sm) {
255366
256367static void apply_config (pio_port_t * pp , const pio_usb_configuration_t * c ,
257368 root_port_t * port ) {
258- pp -> pio_usb_tx = c -> pio_tx_num == 0 ? pio0 : pio1 ;
259- pp -> sm_tx = c -> sm_tx ;
260- pp -> tx_ch = c -> tx_ch ;
261- pp -> pio_usb_rx = c -> pio_rx_num == 0 ? pio0 : pio1 ;
262- pp -> sm_rx = c -> sm_rx ;
263- pp -> sm_eop = c -> sm_eop ;
369+ if (c -> pio_tx_num >= 0 )
370+ pp -> pio_usb_tx = c -> pio_tx_num == 0 ? pio0 : pio1 ;
371+ else
372+ pp -> pio_usb_tx = NULL ;
373+ if (c -> pio_rx_num >=-0 )
374+ pp -> pio_usb_rx = c -> pio_rx_num == 0 ? pio0 : pio1 ;
375+ else
376+ pp -> pio_usb_tx = NULL ;
264377 port -> pin_dp = c -> pin_dp ;
265378
266379 if (c -> pinout == PIO_USB_PINOUT_DPDM ) {
@@ -277,10 +390,24 @@ static void apply_config(pio_port_t *pp, const pio_usb_configuration_t *c,
277390
278391 pp -> debug_pin_rx = c -> debug_pin_rx ;
279392 pp -> debug_pin_eop = c -> debug_pin_eop ;
393+ }
280394
281- pio_sm_claim (pp -> pio_usb_tx , pp -> sm_tx );
282- pio_sm_claim (pp -> pio_usb_rx , pp -> sm_rx );
283- pio_sm_claim (pp -> pio_usb_rx , pp -> sm_eop );
395+ static void get_dma_channel (pio_port_t * pp , const pio_usb_configuration_t * c ) {
396+ if (c -> tx_ch < 0 ) {
397+ pp -> tx_ch = dma_claim_unused_channel (true);
398+ } else {
399+ pp -> tx_ch = c -> tx_ch ;
400+ dma_channel_claim (pp -> tx_ch + 1 );
401+ }
402+ }
403+
404+ static void dump_allocated_hw_resources (
405+ const pio_port_t * pp , uint tx_inst_count , uint rx_inst_count ) {
406+ printf ("pio-usb is using:\n" );
407+ printf ("\tUSB transmitter: %d instructions @ PIO %d, State Machine %d, DMA %d\n" ,
408+ tx_inst_count , pp -> pio_usb_tx == pio1 ? 1 : 0 , pp -> sm_tx , pp -> tx_ch );
409+ printf ("\tUSB receiver: %d instructions @ PIO %d, State Machines %d and %d\n" ,
410+ rx_inst_count , pp -> pio_usb_rx == pio1 ? 1 : 0 , pp -> sm_rx , pp -> sm_eop );
284411}
285412
286413static void port_pin_drive_setting (const root_port_t * port ) {
@@ -292,17 +419,18 @@ static void port_pin_drive_setting(const root_port_t *port) {
292419
293420void pio_usb_bus_init (pio_port_t * pp , const pio_usb_configuration_t * c ,
294421 root_port_t * root ) {
295- memset (root , 0 , sizeof (root_port_t ));
296-
297- pp -> pio_usb_tx = c -> pio_tx_num == 0 ? pio0 : pio1 ;
298- dma_claim_mask (1 <<c -> tx_ch );
299- configure_tx_channel (c -> tx_ch , pp -> pio_usb_tx , c -> sm_tx );
422+ uint tx_inst_count = 0 , rx_inst_count = 0 ;
300423
424+ memset (root , 0 , sizeof (root_port_t ));
425+ get_dma_channel (pp , c );
301426 apply_config (pp , c , root );
302- initialize_host_programs (pp , c , root );
427+ if (!init_host_programs (pp , c , root , & tx_inst_count , & rx_inst_count ))
428+ panic ("pio-usb: Not enough hardware resources - State Machines and instructions" );
429+ configure_tx_channel (pp -> tx_ch , pp -> pio_usb_tx , pp -> sm_tx );
303430 port_pin_drive_setting (root );
304431 root -> initialized = true;
305432 root -> dev_addr = 0 ;
433+ dump_allocated_hw_resources (pp , tx_inst_count , rx_inst_count );
306434}
307435
308436//--------------------------------------------------------------------+
0 commit comments