@@ -203,22 +203,6 @@ static pio_pinmask_t _check_pins_free(const mcu_pin_obj_t *first_pin, uint8_t pi
203203 return pins_we_use ;
204204}
205205
206- static bool can_add_program (PIO pio , const pio_program_t * program , int offset ) {
207- if (offset == -1 ) {
208- return pio_can_add_program (pio , program );
209- }
210- return pio_can_add_program_at_offset (pio , program , offset );
211- }
212-
213- static uint add_program (PIO pio , const pio_program_t * program , int offset ) {
214- if (offset == -1 ) {
215- return pio_add_program (pio , program );
216- } else {
217- pio_add_program_at_offset (pio , program , offset );
218- return offset ;
219- }
220- }
221-
222206static enum pio_fifo_join compute_fifo_type (int fifo_type_in , bool rx_fifo , bool tx_fifo ) {
223207 if (fifo_type_in != PIO_FIFO_JOIN_AUTO ) {
224208 return fifo_type_in ;
@@ -246,6 +230,50 @@ static int compute_fifo_depth(enum pio_fifo_join join) {
246230 return 4 ;
247231}
248232
233+
234+ // from pico-sdk/src/rp2_common/hardware_pio/pio.c
235+ static bool is_gpio_compatible (PIO pio , uint32_t used_gpio_ranges ) {
236+ #if PICO_PIO_VERSION > 0
237+ bool gpio_base = pio_get_gpio_base (pio );
238+ return !((gpio_base && (used_gpio_ranges & 1 )) ||
239+ (!gpio_base && (used_gpio_ranges & 4 )));
240+ #else
241+ ((void )pio );
242+ ((void )used_gpio_ranges );
243+ return true;
244+ #endif
245+ }
246+
247+ static bool use_existing_program (PIO * pio_out , uint * sm_out , int * offset_inout , uint32_t program_id , size_t program_len , uint gpio_base , uint gpio_count ) {
248+ uint32_t required_gpio_ranges ;
249+ if (gpio_count ) {
250+ required_gpio_ranges = (1u << (gpio_base >> 4 )) |
251+ (1u << ((gpio_base + gpio_count - 1 ) >> 4 ));
252+ } else {
253+ required_gpio_ranges = 0 ;
254+ }
255+
256+ for (size_t i = 0 ; i < NUM_PIOS ; i ++ ) {
257+ PIO pio = pio_instances [i ];
258+ if (!is_gpio_compatible (pio , required_gpio_ranges )) {
259+ continue ;
260+ }
261+ for (size_t j = 0 ; j < NUM_PIO_STATE_MACHINES ; j ++ ) {
262+ if (_current_program_id [i ][j ] == program_id &&
263+ _current_program_len [i ][j ] == program_len &&
264+ (* offset_inout == -1 || * offset_inout == _current_program_offset [i ][j ])) {
265+ * pio_out = pio ;
266+ * sm_out = j ;
267+ * offset_inout = _current_program_offset [i ][j ];
268+ mp_printf (& mp_plat_print , "use existing program pio=%i offset=%u\n" ,
269+ i , _current_program_offset [i ][j ]);
270+ return true;
271+ }
272+ }
273+ }
274+ return false;
275+ }
276+
249277bool rp2pio_statemachine_construct (rp2pio_statemachine_obj_t * self ,
250278 const uint16_t * program , size_t program_len ,
251279 size_t frequency ,
@@ -272,88 +300,80 @@ bool rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self,
272300 // Create a program id that isn't the pointer so we can store it without storing the original object.
273301 uint32_t program_id = ~((uint32_t )program );
274302
275- int pio_gpio_offset = 0 ;
303+ mp_printf ( & mp_plat_print , "construct\n" ) ;
276304
305+ uint gpio_base = 0 , gpio_count = 0 ;
277306 #if NUM_BANK0_GPIOS > 32
278307 PIO_PINMASK_PRINT (pins_we_use );
279308 if (PIO_PINMASK_VALUE (pins_we_use ) >> 32 ) {
280- pio_gpio_offset = 16 ;
281309 if (PIO_PINMASK_VALUE (pins_we_use ) & 0xffff ) {
282310 mp_printf (& mp_plat_print , "Uses pins from 0-15 and 32-47. not possible\n" );
283311 return false;
284312 }
285313 }
314+
315+ pio_pinmask_value_t v = PIO_PINMASK_VALUE (pins_we_use );
316+ if (v ) {
317+ while (!(v & 1 )) {
318+ gpio_base ++ ;
319+ v >>= 1 ;
320+ }
321+ while (v ) {
322+ gpio_count ++ ;
323+ v >>= 1 ;
324+ }
325+ }
286326 #endif
287327
288328 // Next, find a PIO and state machine to use.
289- size_t pio_index = NUM_PIOS ;
290- uint8_t program_offset = 32 ;
291329 pio_program_t program_struct = {
292330 .instructions = (uint16_t * )program ,
293331 .length = program_len ,
294332 .origin = -1
295333 };
296- for (size_t i = 0 ; i < NUM_PIOS ; i ++ ) {
297- PIO pio = pio_instances [i ];
298- uint8_t free_count = 0 ;
299- for (size_t j = 0 ; j < NUM_PIO_STATE_MACHINES ; j ++ ) {
300- if (_current_program_id [i ][j ] == program_id &&
301- _current_program_len [i ][j ] == program_len &&
302- (offset == -1 || offset == _current_program_offset [i ][j ])) {
303- program_offset = _current_program_offset [i ][j ];
304- }
305- if (!pio_sm_is_claimed (pio , j )) {
306- free_count ++ ;
307- }
308- }
309- if (free_count > 0 && (program_offset < 32 || can_add_program (pio , & program_struct , offset ))) {
310- pio_index = i ;
311- if (program_offset < 32 ) {
312- break ;
313- }
334+ PIO pio ;
335+ uint state_machine ;
336+ bool added = false;
337+
338+ if (!use_existing_program (& pio , & state_machine , & offset , program_id , program_len , gpio_base , gpio_count )) {
339+ uint program_offset ;
340+ mp_printf (& mp_plat_print , "gpio_base = %d gpio_count = %d\n" , gpio_base , gpio_count );
341+ bool r = pio_claim_free_sm_and_add_program_for_gpio_range (& program_struct , & pio , & state_machine , & program_offset , gpio_base , gpio_count , true);
342+ if (!r ) {
343+ return false;
314344 }
315- // Reset program offset if we weren't able to find a free state machine
316- // on that PIO. (We would have broken the loop otherwise.)
317- program_offset = 32 ;
345+ offset = program_offset ;
346+ added = true;
318347 }
319348
320- size_t state_machine = NUM_PIO_STATE_MACHINES ;
321- if (pio_index < NUM_PIOS ) {
322- PIO pio = pio_instances [pio_index ];
323- for (size_t i = 0 ; i < NUM_PIOS ; i ++ ) {
324- if (i == pio_index ) {
325- continue ;
326- }
327- pio_pinmask_t intersection = PIO_PINMASK_AND (_current_pins [i ], pins_we_use );
328- if (PIO_PINMASK_VALUE (intersection ) != 0 ) {
329- // Pin in use by another PIO already.
330- return false;
349+ size_t pio_index = pio_get_index (pio );
350+ for (size_t i = 0 ; i < NUM_PIOS ; i ++ ) {
351+ if (i == pio_index ) {
352+ continue ;
353+ }
354+ pio_pinmask_t intersection = PIO_PINMASK_AND (_current_pins [i ], pins_we_use );
355+ if (PIO_PINMASK_VALUE (intersection ) != 0 ) {
356+ if (added ) {
357+ pio_remove_program (pio , & program_struct , offset );
331358 }
359+ pio_sm_unclaim (pio , state_machine );
360+ // Pin in use by another PIO already.
361+ return false;
332362 }
333- state_machine = pio_claim_unused_sm (pio , false);
334- }
335- if (pio_index == NUM_PIOS || state_machine < 0 || state_machine >= NUM_PIO_STATE_MACHINES ) {
336- return false;
337363 }
338364
339- self -> pio = pio_instances [ pio_index ] ;
365+ self -> pio = pio ;
340366 self -> state_machine = state_machine ;
341- if (program_offset == 32 ) {
342- program_offset = add_program (self -> pio , & program_struct , offset );
343- }
344- self -> offset = program_offset ;
367+ self -> offset = offset ;
345368 _current_program_id [pio_index ][state_machine ] = program_id ;
346369 _current_program_len [pio_index ][state_machine ] = program_len ;
347- _current_program_offset [pio_index ][state_machine ] = program_offset ;
370+ _current_program_offset [pio_index ][state_machine ] = offset ;
348371 _current_sm_pins [pio_index ][state_machine ] = pins_we_use ;
349372 PIO_PINMASK_MERGE (_current_pins [pio_index ], pins_we_use );
350373
351- pio_sm_set_pins_with_mask (self -> pio , state_machine , PIO_PINMASK_VALUE (initial_pin_state ) >> pio_gpio_offset , PIO_PINMASK_VALUE (pins_we_use ) >> pio_gpio_offset );
352- pio_sm_set_pindirs_with_mask (self -> pio , state_machine , PIO_PINMASK_VALUE (initial_pin_direction ) >> pio_gpio_offset , PIO_PINMASK_VALUE (pins_we_use ) >> pio_gpio_offset );
374+ pio_sm_set_pins_with_mask64 (self -> pio , state_machine , PIO_PINMASK_VALUE (initial_pin_state ), PIO_PINMASK_VALUE (pins_we_use ));
375+ pio_sm_set_pindirs_with_mask64 (self -> pio , state_machine , PIO_PINMASK_VALUE (initial_pin_direction ), PIO_PINMASK_VALUE (pins_we_use ));
353376 rp2pio_statemachine_set_pull (pull_pin_up , pull_pin_down , pins_we_use );
354- #if NUM_BANK0_GPIOS > 32
355- self -> pio_gpio_offset = pio_gpio_offset ;
356- #endif
357377 self -> initial_pin_state = initial_pin_state ;
358378 self -> initial_pin_direction = initial_pin_direction ;
359379 self -> pull_pin_up = pull_pin_up ;
@@ -423,8 +443,8 @@ bool rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self,
423443
424444 mp_arg_validate_int_range (wrap_target , 0 , program_len - 1 , MP_QSTR_wrap_target );
425445
426- wrap += program_offset ;
427- wrap_target += program_offset ;
446+ wrap += offset ;
447+ wrap_target += offset ;
428448
429449 sm_config_set_wrap (& c , wrap_target , wrap );
430450 sm_config_set_in_shift (& c , in_shift_right , auto_push , push_threshold );
@@ -478,7 +498,7 @@ bool rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self,
478498 SM_DMA_CLEAR_CHANNEL_READ (pio_index , state_machine );
479499 SM_DMA_CLEAR_CHANNEL_WRITE (pio_index , state_machine );
480500
481- pio_sm_init (self -> pio , self -> state_machine , program_offset , & c );
501+ pio_sm_init (self -> pio , self -> state_machine , offset , & c );
482502 common_hal_rp2pio_statemachine_run (self , init , init_len );
483503
484504 common_hal_rp2pio_statemachine_set_frequency (self , frequency );
0 commit comments