@@ -203,22 +203,6 @@ static pio_pinmask_t _check_pins_free(const mcu_pin_obj_t *first_pin, uint8_t pi
203
203
return pins_we_use ;
204
204
}
205
205
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
-
222
206
static enum pio_fifo_join compute_fifo_type (int fifo_type_in , bool rx_fifo , bool tx_fifo ) {
223
207
if (fifo_type_in != PIO_FIFO_JOIN_AUTO ) {
224
208
return fifo_type_in ;
@@ -246,6 +230,50 @@ static int compute_fifo_depth(enum pio_fifo_join join) {
246
230
return 4 ;
247
231
}
248
232
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
+
249
277
bool rp2pio_statemachine_construct (rp2pio_statemachine_obj_t * self ,
250
278
const uint16_t * program , size_t program_len ,
251
279
size_t frequency ,
@@ -272,88 +300,80 @@ bool rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self,
272
300
// Create a program id that isn't the pointer so we can store it without storing the original object.
273
301
uint32_t program_id = ~((uint32_t )program );
274
302
275
- int pio_gpio_offset = 0 ;
303
+ mp_printf ( & mp_plat_print , "construct\n" ) ;
276
304
305
+ uint gpio_base = 0 , gpio_count = 0 ;
277
306
#if NUM_BANK0_GPIOS > 32
278
307
PIO_PINMASK_PRINT (pins_we_use );
279
308
if (PIO_PINMASK_VALUE (pins_we_use ) >> 32 ) {
280
- pio_gpio_offset = 16 ;
281
309
if (PIO_PINMASK_VALUE (pins_we_use ) & 0xffff ) {
282
310
mp_printf (& mp_plat_print , "Uses pins from 0-15 and 32-47. not possible\n" );
283
311
return false;
284
312
}
285
313
}
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
+ }
286
326
#endif
287
327
288
328
// Next, find a PIO and state machine to use.
289
- size_t pio_index = NUM_PIOS ;
290
- uint8_t program_offset = 32 ;
291
329
pio_program_t program_struct = {
292
330
.instructions = (uint16_t * )program ,
293
331
.length = program_len ,
294
332
.origin = -1
295
333
};
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;
314
344
}
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;
318
347
}
319
348
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 );
331
358
}
359
+ pio_sm_unclaim (pio , state_machine );
360
+ // Pin in use by another PIO already.
361
+ return false;
332
362
}
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;
337
363
}
338
364
339
- self -> pio = pio_instances [ pio_index ] ;
365
+ self -> pio = pio ;
340
366
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 ;
345
368
_current_program_id [pio_index ][state_machine ] = program_id ;
346
369
_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 ;
348
371
_current_sm_pins [pio_index ][state_machine ] = pins_we_use ;
349
372
PIO_PINMASK_MERGE (_current_pins [pio_index ], pins_we_use );
350
373
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 ));
353
376
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
357
377
self -> initial_pin_state = initial_pin_state ;
358
378
self -> initial_pin_direction = initial_pin_direction ;
359
379
self -> pull_pin_up = pull_pin_up ;
@@ -423,8 +443,8 @@ bool rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self,
423
443
424
444
mp_arg_validate_int_range (wrap_target , 0 , program_len - 1 , MP_QSTR_wrap_target );
425
445
426
- wrap += program_offset ;
427
- wrap_target += program_offset ;
446
+ wrap += offset ;
447
+ wrap_target += offset ;
428
448
429
449
sm_config_set_wrap (& c , wrap_target , wrap );
430
450
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,
478
498
SM_DMA_CLEAR_CHANNEL_READ (pio_index , state_machine );
479
499
SM_DMA_CLEAR_CHANNEL_WRITE (pio_index , state_machine );
480
500
481
- pio_sm_init (self -> pio , self -> state_machine , program_offset , & c );
501
+ pio_sm_init (self -> pio , self -> state_machine , offset , & c );
482
502
common_hal_rp2pio_statemachine_run (self , init , init_len );
483
503
484
504
common_hal_rp2pio_statemachine_set_frequency (self , frequency );
0 commit comments