1 /*
2  * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include "hardware/claim.h"
8 #include "hardware/pio.h"
9 #include "hardware/pio_instructions.h"
10 
11 // sanity check
12 check_hw_layout(pio_hw_t, sm[0].clkdiv, PIO_SM0_CLKDIV_OFFSET);
13 check_hw_layout(pio_hw_t, sm[1].clkdiv, PIO_SM1_CLKDIV_OFFSET);
14 check_hw_layout(pio_hw_t, instr_mem[0], PIO_INSTR_MEM0_OFFSET);
15 check_hw_layout(pio_hw_t, inte0, PIO_IRQ0_INTE_OFFSET);
16 check_hw_layout(pio_hw_t, irq_ctrl[0].inte, PIO_IRQ0_INTE_OFFSET);
17 check_hw_layout(pio_hw_t, txf[1], PIO_TXF1_OFFSET);
18 check_hw_layout(pio_hw_t, rxf[3], PIO_RXF3_OFFSET);
19 check_hw_layout(pio_hw_t, ints1, PIO_IRQ1_INTS_OFFSET);
20 check_hw_layout(pio_hw_t, irq_ctrl[1].ints, PIO_IRQ1_INTS_OFFSET);
21 
22 static uint8_t claimed[(NUM_PIO_STATE_MACHINES * NUM_PIOS + 7) >> 3];
23 
pio_sm_claim(PIO pio,uint sm)24 void pio_sm_claim(PIO pio, uint sm) {
25     check_sm_param(sm);
26     uint which = pio_get_index(pio);
27     const char *msg =
28 #if PICO_PIO_VERSION > 0
29         which == 2 ? "PIO 2 SM (%d - 8) already claimed" :
30 #endif
31         which == 1 ? "PIO 1 SM (%d - 4) already claimed" :
32                      "PIO 0 SM %d already claimed";
33     hw_claim_or_assert(&claimed[0], which * NUM_PIO_STATE_MACHINES + sm, msg);
34 }
35 
pio_claim_sm_mask(PIO pio,uint sm_mask)36 void pio_claim_sm_mask(PIO pio, uint sm_mask) {
37     for(uint i = 0; sm_mask; i++, sm_mask >>= 1u) {
38         if (sm_mask & 1u) pio_sm_claim(pio, i);
39     }
40 }
41 
pio_sm_unclaim(PIO pio,uint sm)42 void pio_sm_unclaim(PIO pio, uint sm) {
43     check_sm_param(sm);
44     uint which = pio_get_index(pio);
45     hw_claim_clear(&claimed[0], which * NUM_PIO_STATE_MACHINES + sm);
46 }
47 
pio_claim_unused_sm(PIO pio,bool required)48 int pio_claim_unused_sm(PIO pio, bool required) {
49     // PIO index ranges from 0 to NUM_PIOS - 1.
50     uint which = pio_get_index(pio);
51     uint base = which * NUM_PIO_STATE_MACHINES;
52     int index = hw_claim_unused_from_range((uint8_t*)&claimed[0], required, base,
53                                       base + NUM_PIO_STATE_MACHINES - 1, "No PIO state machines are available");
54     return index >= (int)base ? index - (int)base : -1;
55 }
56 
pio_sm_is_claimed(PIO pio,uint sm)57 bool pio_sm_is_claimed(PIO pio, uint sm) {
58     check_sm_param(sm);
59     uint which = pio_get_index(pio);
60     return hw_is_claimed(&claimed[0], which * NUM_PIO_STATE_MACHINES + sm);
61 }
62 
63 static_assert(PIO_INSTRUCTION_COUNT <= 32, "");
64 static uint32_t _used_instruction_space[NUM_PIOS];
65 
find_offset_for_program(PIO pio,const pio_program_t * program)66 static int find_offset_for_program(PIO pio, const pio_program_t *program) {
67     assert(program->length <= PIO_INSTRUCTION_COUNT);
68     uint32_t used_mask = _used_instruction_space[pio_get_index(pio)];
69     uint32_t program_mask = (1u << program->length) - 1;
70     if (program->origin >= 0) {
71         if (program->origin > 32 - program->length) return PICO_ERROR_GENERIC;
72         return used_mask & (program_mask << program->origin) ? -1 : program->origin;
73     } else {
74         // work down from the top always
75         for (int i = 32 - program->length; i >= 0; i--) {
76             if (!(used_mask & (program_mask << (uint) i))) {
77                 return i;
78             }
79         }
80         return PICO_ERROR_INSUFFICIENT_RESOURCES;
81     }
82 }
83 
pio_set_gpio_base_unsafe(PIO pio,uint gpio_base)84 static int pio_set_gpio_base_unsafe(PIO pio, uint gpio_base) {
85     invalid_params_if_and_return(PIO, gpio_base != 0 && (!PICO_PIO_VERSION || gpio_base != 16), PICO_ERROR_BAD_ALIGNMENT);
86 #if PICO_PIO_VERSION > 0
87     uint32_t used_mask = _used_instruction_space[pio_get_index(pio)];
88     invalid_params_if_and_return(PIO, used_mask, PICO_ERROR_INVALID_STATE);
89     pio->gpiobase = gpio_base;
90 #else
91     ((void)pio);
92     ((void)gpio_base);
93 #endif
94     return PICO_OK;
95 }
96 
pio_set_gpio_base(PIO pio,uint gpio_base)97 int pio_set_gpio_base(PIO pio, uint gpio_base) {
98     int rc = PICO_OK;
99 #if PICO_PIO_VERSION > 0
100     uint32_t save = hw_claim_lock();
101     rc = pio_set_gpio_base_unsafe(pio, gpio_base);
102     hw_claim_unlock(save);
103 #else
104     ((void)pio);
105     ((void)gpio_base);
106 #endif
107     return rc;
108 }
109 
is_gpio_compatible(PIO pio,uint32_t used_gpio_ranges)110 static bool is_gpio_compatible(PIO pio, uint32_t used_gpio_ranges) {
111 #if PICO_PIO_VERSION > 0
112     bool gpio_base = pio_get_gpio_base(pio);
113     return !((gpio_base && (used_gpio_ranges & 1)) ||
114              (!gpio_base && (used_gpio_ranges & 4)));
115 #else
116     ((void)pio);
117     ((void)used_gpio_ranges);
118     return true;
119 #endif
120 }
121 
is_program_gpio_compatible(PIO pio,const pio_program_t * program)122 static bool is_program_gpio_compatible(PIO pio, const pio_program_t *program) {
123 #if PICO_PIO_VERSION > 0
124     return is_gpio_compatible(pio, program->used_gpio_ranges);
125 #else
126     ((void)pio);
127     ((void)program);
128     return true;
129 #endif
130 }
131 
add_program_at_offset_check(PIO pio,const pio_program_t * program,uint offset)132 static int add_program_at_offset_check(PIO pio, const pio_program_t *program, uint offset) {
133     valid_params_if(HARDWARE_PIO, offset < PIO_INSTRUCTION_COUNT);
134     valid_params_if(HARDWARE_PIO, offset + program->length <= PIO_INSTRUCTION_COUNT);
135 #if PICO_PIO_VERSION == 0
136     if (program->pio_version) return PICO_ERROR_VERSION_MISMATCH;
137 #endif
138     if (!is_program_gpio_compatible(pio, program)) return PICO_ERROR_BAD_ALIGNMENT; // todo better error?
139     if (program->origin >= 0 && (uint)program->origin != offset) return PICO_ERROR_BAD_ALIGNMENT; // todo better error?
140     uint32_t used_mask = _used_instruction_space[pio_get_index(pio)];
141     uint32_t program_mask = (1u << program->length) - 1;
142     return (used_mask & (program_mask << offset)) ? PICO_ERROR_INSUFFICIENT_RESOURCES : PICO_OK;
143 }
144 
pio_can_add_program(PIO pio,const pio_program_t * program)145 bool pio_can_add_program(PIO pio, const pio_program_t *program) {
146     uint32_t save = hw_claim_lock();
147     int rc = find_offset_for_program(pio, program);
148     if (rc >= 0) rc = add_program_at_offset_check(pio, program, (uint)rc);
149     hw_claim_unlock(save);
150     return rc == 0;
151 }
152 
pio_can_add_program_at_offset(PIO pio,const pio_program_t * program,uint offset)153 bool pio_can_add_program_at_offset(PIO pio, const pio_program_t *program, uint offset) {
154     uint32_t save = hw_claim_lock();
155     bool rc = add_program_at_offset_check(pio, program, offset) == 0;
156     hw_claim_unlock(save);
157     return rc;
158 }
159 
add_program_at_offset(PIO pio,const pio_program_t * program,uint offset)160 static int add_program_at_offset(PIO pio, const pio_program_t *program, uint offset) {
161     int rc = add_program_at_offset_check(pio, program, offset);
162     if (rc != 0) return rc;
163     for (uint i = 0; i < program->length; ++i) {
164         uint16_t instr = program->instructions[i];
165         pio->instr_mem[offset + i] = pio_instr_bits_jmp != _pio_major_instr_bits(instr) ? instr : instr + offset;
166     }
167     uint32_t program_mask = (1u << program->length) - 1;
168     _used_instruction_space[pio_get_index(pio)] |= program_mask << offset;
169     return (int)offset;
170 }
171 
172 // these assert if unable
pio_add_program(PIO pio,const pio_program_t * program)173 int pio_add_program(PIO pio, const pio_program_t *program) {
174     uint32_t save = hw_claim_lock();
175     int offset = find_offset_for_program(pio, program);
176     if (offset >= 0) {
177         offset = add_program_at_offset(pio, program, (uint) offset);
178     }
179     hw_claim_unlock(save);
180     return offset;
181 }
182 
pio_add_program_at_offset(PIO pio,const pio_program_t * program,uint offset)183 int pio_add_program_at_offset(PIO pio, const pio_program_t *program, uint offset) {
184     uint32_t save = hw_claim_lock();
185     int rc = add_program_at_offset(pio, program, offset);
186     hw_claim_unlock(save);
187     return rc;
188 }
189 
pio_remove_program(PIO pio,const pio_program_t * program,uint loaded_offset)190 void pio_remove_program(PIO pio, const pio_program_t *program, uint loaded_offset) {
191     uint32_t program_mask = (1u << program->length) - 1;
192     program_mask <<= loaded_offset;
193     uint32_t save = hw_claim_lock();
194     assert(program_mask == (_used_instruction_space[pio_get_index(pio)] & program_mask));
195     _used_instruction_space[pio_get_index(pio)] &= ~program_mask;
196     hw_claim_unlock(save);
197 }
198 
pio_clear_instruction_memory(PIO pio)199 void pio_clear_instruction_memory(PIO pio) {
200     uint32_t save = hw_claim_lock();
201     _used_instruction_space[pio_get_index(pio)] = 0;
202     for(uint i=0;i<PIO_INSTRUCTION_COUNT;i++) {
203         pio->instr_mem[i] = pio_encode_jmp(i);
204     }
205     hw_claim_unlock(save);
206 }
207 
208 #if !PICO_PIO_USE_GPIO_BASE
209 // the 32 pin APIs are the same as the internal method, so collapse them
210 #define pio_sm_set_pins_internal pio_sm_set_pins
211 #define pio_sm_set_pins_with_mask_internal pio_sm_set_pins_with_mask
212 #define pio_sm_set_pindirs_with_mask_internal pio_sm_set_pindirs_with_mask
213 #endif
214 
215 // Set the value of all PIO pins. This is done by forcibly executing
216 // instructions on a "victim" state machine, sm. Ideally you should choose one
217 // which is not currently running a program. This is intended for one-time
218 // setup of initial pin states.
219 //
220 // note pin mask bit 0 is relative to current GPIO_BASE
pio_sm_set_pins_internal(PIO pio,uint sm,uint32_t pins)221 void pio_sm_set_pins_internal(PIO pio, uint sm, uint32_t pins) {
222     check_pio_param(pio);
223     check_sm_param(sm);
224     uint32_t pinctrl_saved = pio->sm[sm].pinctrl;
225     uint32_t execctrl_saved = pio->sm[sm].execctrl;
226     hw_clear_bits(&pio->sm[sm].execctrl, 1u << PIO_SM0_EXECCTRL_OUT_STICKY_LSB);
227     uint remaining = 32;
228     uint base = 0;
229     while (remaining) {
230         uint decrement = remaining > 5 ? 5 : remaining;
231         pio->sm[sm].pinctrl =
232                 (decrement << PIO_SM0_PINCTRL_SET_COUNT_LSB) |
233                 (base << PIO_SM0_PINCTRL_SET_BASE_LSB);
234         pio_sm_exec(pio, sm, pio_encode_set(pio_pins, pins & 0x1fu));
235         remaining -= decrement;
236         base += decrement;
237         pins >>= 5;
238     }
239     pio->sm[sm].pinctrl = pinctrl_saved;
240     pio->sm[sm].execctrl = execctrl_saved;
241 }
242 
243 #ifndef pio_sm_set_pins_internal
pio_sm_set_pins(PIO pio,uint sm,uint32_t pins)244 void pio_sm_set_pins(PIO pio, uint sm, uint32_t pins) {
245 #if PICO_PIO_USE_GPIO_BASE
246     pins >>= pio_get_gpio_base(pio);
247 #endif
248     pio_sm_set_pins_internal(pio, sm, pins);
249 }
250 #endif
251 
pio_sm_set_pins64(PIO pio,uint sm,uint64_t pins)252 void pio_sm_set_pins64(PIO pio, uint sm, uint64_t pins) {
253     check_pio_pin_mask64(pio, sm, pins);
254 #if PICO_PIO_USE_GPIO_BASE
255     pins >>= pio_get_gpio_base(pio);
256 #endif
257     pio_sm_set_pins_internal(pio, sm, (uint32_t)pins);
258 }
259 
260 // note pin values/mask bit 0 is relative to current GPIO_BASE
pio_sm_set_pins_with_mask_internal(PIO pio,uint sm,uint32_t pin_values,uint32_t pin_mask)261 void pio_sm_set_pins_with_mask_internal(PIO pio, uint sm, uint32_t pin_values, uint32_t pin_mask) {
262     check_pio_param(pio);
263     check_sm_param(sm);
264     uint32_t pinctrl_saved = pio->sm[sm].pinctrl;
265     uint32_t execctrl_saved = pio->sm[sm].execctrl;
266     hw_clear_bits(&pio->sm[sm].execctrl, 1u << PIO_SM0_EXECCTRL_OUT_STICKY_LSB);
267     while (pin_mask) {
268         uint base = (uint)__builtin_ctz(pin_mask);
269         pio->sm[sm].pinctrl =
270                 (1u << PIO_SM0_PINCTRL_SET_COUNT_LSB) |
271                 (base << PIO_SM0_PINCTRL_SET_BASE_LSB);
272         pio_sm_exec(pio, sm, pio_encode_set(pio_pins, (pin_values >> base) & 0x1u));
273         pin_mask &= pin_mask - 1;
274     }
275     pio->sm[sm].pinctrl = pinctrl_saved;
276     pio->sm[sm].execctrl = execctrl_saved;
277 }
278 
279 #ifndef pio_sm_set_pins_with_mask_internal
pio_sm_set_pins_with_mask(PIO pio,uint sm,uint32_t pin_values,uint32_t pin_mask)280 void pio_sm_set_pins_with_mask(PIO pio, uint sm, uint32_t pin_values, uint32_t pin_mask) {
281 #if PICO_PIO_USE_GPIO_BASE
282     pin_values >>= pio_get_gpio_base(pio);
283     pin_mask >>= pio_get_gpio_base(pio);
284 #endif
285     pio_sm_set_pins_with_mask_internal(pio, sm, pin_values, pin_mask);
286 }
287 #endif
288 
pio_sm_set_pins_with_mask64(PIO pio,uint sm,uint64_t pin_values,uint64_t pin_mask)289 void pio_sm_set_pins_with_mask64(PIO pio, uint sm, uint64_t pin_values, uint64_t pin_mask) {
290     check_pio_pin_mask64(pio, sm, pin_mask);
291 #if PICO_PIO_USE_GPIO_BASE
292     pin_values >>= pio_get_gpio_base(pio);
293     pin_mask >>= pio_get_gpio_base(pio);
294 #endif
295     pio_sm_set_pins_with_mask_internal(pio, sm, (uint32_t)pin_values, (uint32_t)pin_mask);
296 }
297 
pio_sm_set_pindirs_with_mask_internal(PIO pio,uint sm,uint32_t pindirs,uint32_t pin_mask)298 void pio_sm_set_pindirs_with_mask_internal(PIO pio, uint sm, uint32_t pindirs, uint32_t pin_mask) {
299     check_pio_param(pio);
300     check_sm_param(sm);
301     uint32_t pinctrl_saved = pio->sm[sm].pinctrl;
302     uint32_t execctrl_saved = pio->sm[sm].execctrl;
303     hw_clear_bits(&pio->sm[sm].execctrl, 1u << PIO_SM0_EXECCTRL_OUT_STICKY_LSB);
304     while (pin_mask) {
305         uint base = (uint)__builtin_ctz(pin_mask);
306         pio->sm[sm].pinctrl =
307                 (1u << PIO_SM0_PINCTRL_SET_COUNT_LSB) |
308                 (base << PIO_SM0_PINCTRL_SET_BASE_LSB);
309         pio_sm_exec(pio, sm, pio_encode_set(pio_pindirs, (pindirs >> base) & 0x1u));
310         pin_mask &= pin_mask - 1;
311     }
312     pio->sm[sm].pinctrl = pinctrl_saved;
313     pio->sm[sm].execctrl = execctrl_saved;
314 }
315 
316 #ifndef pio_sm_set_pindirs_with_mask_internal
pio_sm_set_pindirs_with_mask(PIO pio,uint sm,uint32_t pindirs,uint32_t pin_mask)317 void pio_sm_set_pindirs_with_mask(PIO pio, uint sm, uint32_t pindirs, uint32_t pin_mask) {
318 #if PICO_PIO_USE_GPIO_BASE
319     pindirs >>= pio_get_gpio_base(pio);
320     pin_mask >>= pio_get_gpio_base(pio);
321 #endif
322     pio_sm_set_pindirs_with_mask_internal(pio, sm, pindirs, pin_mask);
323 }
324 #endif
325 
pio_sm_set_pindirs_with_mask64(PIO pio,uint sm,uint64_t pindirs,uint64_t pin_mask)326 void pio_sm_set_pindirs_with_mask64(PIO pio, uint sm, uint64_t pindirs, uint64_t pin_mask) {
327 #if PICO_PIO_USE_GPIO_BASE
328     pindirs >>= pio_get_gpio_base(pio);
329     pin_mask >>= pio_get_gpio_base(pio);
330 #endif
331     pio_sm_set_pindirs_with_mask_internal(pio, sm, (uint32_t)pindirs, (uint32_t)pin_mask);
332 }
333 
pio_sm_set_consecutive_pindirs(PIO pio,uint sm,uint pin,uint count,bool is_out)334 int pio_sm_set_consecutive_pindirs(PIO pio, uint sm, uint pin, uint count, bool is_out) {
335     check_pio_param(pio);
336     check_sm_param(sm);
337     pin -= pio_get_gpio_base(pio);
338     invalid_params_if_and_return(PIO, pin >= 32u, PICO_ERROR_INVALID_ARG);
339     uint32_t pinctrl_saved = pio->sm[sm].pinctrl;
340     uint32_t execctrl_saved = pio->sm[sm].execctrl;
341     hw_clear_bits(&pio->sm[sm].execctrl, 1u << PIO_SM0_EXECCTRL_OUT_STICKY_LSB);
342     uint pindir_val = is_out ? 0x1f : 0;
343     while (count > 5) {
344         pio->sm[sm].pinctrl = (5u << PIO_SM0_PINCTRL_SET_COUNT_LSB) | (pin << PIO_SM0_PINCTRL_SET_BASE_LSB);
345         pio_sm_exec(pio, sm, pio_encode_set(pio_pindirs, pindir_val));
346         count -= 5;
347         pin = (pin + 5) & 0x1f;
348     }
349     pio->sm[sm].pinctrl = (count << PIO_SM0_PINCTRL_SET_COUNT_LSB) | (pin << PIO_SM0_PINCTRL_SET_BASE_LSB);
350     pio_sm_exec(pio, sm, pio_encode_set(pio_pindirs, pindir_val));
351     pio->sm[sm].pinctrl = pinctrl_saved;
352     pio->sm[sm].execctrl = execctrl_saved;
353     return PICO_OK;
354 }
355 
pio_sm_init(PIO pio,uint sm,uint initial_pc,const pio_sm_config * config)356 int pio_sm_init(PIO pio, uint sm, uint initial_pc, const pio_sm_config *config) {
357     valid_params_if(HARDWARE_PIO, initial_pc < PIO_INSTRUCTION_COUNT);
358     // Halt the machine, set some sensible defaults
359     pio_sm_set_enabled(pio, sm, false);
360 
361     int rc;
362     if (config) {
363         rc = pio_sm_set_config(pio, sm, config);
364     } else {
365         pio_sm_config c = pio_get_default_sm_config();
366         rc = pio_sm_set_config(pio, sm, &c);
367     }
368     if (rc) return rc;
369 
370     pio_sm_clear_fifos(pio, sm);
371 
372     // Clear FIFO debug flags
373     const uint32_t fdebug_sm_mask =
374             (1u << PIO_FDEBUG_TXOVER_LSB) |
375             (1u << PIO_FDEBUG_RXUNDER_LSB) |
376             (1u << PIO_FDEBUG_TXSTALL_LSB) |
377             (1u << PIO_FDEBUG_RXSTALL_LSB);
378     pio->fdebug = fdebug_sm_mask << sm;
379 
380     // Finally, clear some internal SM state
381     pio_sm_restart(pio, sm);
382     pio_sm_clkdiv_restart(pio, sm);
383     pio_sm_exec(pio, sm, pio_encode_jmp(initial_pc));
384     return PICO_OK;
385 }
386 
pio_sm_drain_tx_fifo(PIO pio,uint sm)387 void pio_sm_drain_tx_fifo(PIO pio, uint sm) {
388     uint instr = (pio->sm[sm].shiftctrl & PIO_SM0_SHIFTCTRL_AUTOPULL_BITS) ? pio_encode_out(pio_null, 32) :
389                  pio_encode_pull(false, false);
390     while (!pio_sm_is_tx_fifo_empty(pio, sm)) {
391         pio_sm_exec(pio, sm, instr);
392     }
393 }
394 
pio_claim_free_sm_and_add_program(const pio_program_t * program,PIO * pio,uint * sm,uint * offset)395 bool pio_claim_free_sm_and_add_program(const pio_program_t *program, PIO *pio, uint *sm, uint *offset) {
396     return pio_claim_free_sm_and_add_program_for_gpio_range(program, pio, sm, offset, 0, 0, false);
397 }
398 
pio_claim_free_sm_and_add_program_for_gpio_range(const pio_program_t * program,PIO * pio,uint * sm,uint * offset,uint gpio_base,uint gpio_count,bool set_gpio_base)399 bool pio_claim_free_sm_and_add_program_for_gpio_range(const pio_program_t *program, PIO *pio, uint *sm, uint *offset, uint gpio_base, uint gpio_count, bool set_gpio_base) {
400     invalid_params_if(HARDWARE_PIO, (gpio_base + gpio_count) > NUM_BANK0_GPIOS);
401 
402 #if !PICO_PIO_USE_GPIO_BASE
403     // short-circuit some logic when not using GIO_BASE
404     set_gpio_base = 0;
405     gpio_count = 0;
406 #endif
407 
408     // note if we gpio_count == 0, we don't care about GPIOs so use a zero mask for what we require
409     // if gpio_count > 0, then we just set used mask for the ends, since that is all that is checked at the moment
410     uint32_t required_gpio_ranges;
411     if (gpio_count) required_gpio_ranges = (1u << (gpio_base >> 4)) | (1u << ((gpio_base + gpio_count - 1) >> 4));
412     else            required_gpio_ranges = 0;
413     int passes = set_gpio_base ? 2 : 1;
414 
415     for(int pass = 0; pass < passes; pass++) {
416         int pio_num = NUM_PIOS;
417         while (pio_num--) {
418             *pio = pio_get_instance((uint)pio_num);
419             // We need to claim an SM on the PIO
420             int8_t sm_index[NUM_PIO_STATE_MACHINES];
421             // on second pass, if there is one, we try and claim all the state machines so that we can change the GPIO base
422             uint num_claimed;
423             for(num_claimed = 0; num_claimed < (pass ? NUM_PIO_STATE_MACHINES : 1u) ; num_claimed++) {
424                 sm_index[num_claimed] = (int8_t)pio_claim_unused_sm(*pio, false);
425                 if (sm_index[num_claimed] < 0) break;
426             }
427             if (num_claimed && (!pass || num_claimed == NUM_PIO_STATE_MACHINES)) {
428                 uint32_t save = hw_claim_lock();
429                 if (pass) {
430                     pio_set_gpio_base_unsafe(*pio, required_gpio_ranges & 4 ? 16 : 0);
431                 }
432                 int rc = is_gpio_compatible(*pio, required_gpio_ranges) ? PICO_OK : PICO_ERROR_BAD_ALIGNMENT;
433                 if (rc == PICO_OK) rc = find_offset_for_program(*pio, program);
434                 if (rc >= 0) rc = add_program_at_offset(*pio, program, (uint)rc);
435                 if (rc >= 0) {
436                     *sm = (uint) sm_index[0];
437                     *offset = (uint) rc;
438                 }
439                 hw_claim_unlock(save);
440                 // always un-claim all SMs other than the one we need (array index 0),
441                 // or all of them if we had an error
442                 for (uint i = (rc >= 0); i < num_claimed; i++) {
443                     pio_sm_unclaim(*pio, (uint) sm_index[i]);
444                 }
445                 if (rc >= 0) {
446                     return true;
447                 }
448             }
449         }
450     }
451     *pio = NULL;
452     return false;
453 }
454 
pio_remove_program_and_unclaim_sm(const pio_program_t * program,PIO pio,uint sm,uint offset)455 void pio_remove_program_and_unclaim_sm(const pio_program_t *program, PIO pio, uint sm, uint offset) {
456     check_pio_param(pio);
457     check_sm_param(sm);
458     pio_remove_program(pio, program, offset);
459     pio_sm_unclaim(pio, sm);
460 }
461