pio.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#ifndef _HARDWARE_PIO_H_
8#define _HARDWARE_PIO_H_
9
10#include "pico.h"
12#include "hardware/structs/pio.h"
13#include "hardware/gpio.h"
14#include "hardware/regs/dreq.h"
15#include "hardware/pio_instructions.h"
16
17// PICO_CONFIG: PARAM_ASSERTIONS_ENABLED_PIO, Enable/disable assertions in the PIO module, type=bool, default=0, group=hardware_pio
18#ifndef PARAM_ASSERTIONS_ENABLED_PIO
19#define PARAM_ASSERTIONS_ENABLED_PIO 0
20#endif
21
46#ifdef __cplusplus
47extern "C" {
48#endif
49
50static_assert(PIO_SM0_SHIFTCTRL_FJOIN_RX_LSB == PIO_SM0_SHIFTCTRL_FJOIN_TX_LSB + 1, "");
51
56 PIO_FIFO_JOIN_NONE = 0,
57 PIO_FIFO_JOIN_TX = 1,
58 PIO_FIFO_JOIN_RX = 2,
59};
60
65 STATUS_TX_LESSTHAN = 0,
66 STATUS_RX_LESSTHAN = 1
67};
68
69typedef pio_hw_t *PIO;
70
78#define pio0 pio0_hw
88#define pio1 pio1_hw
103typedef struct {
104 uint32_t clkdiv;
105 uint32_t execctrl;
106 uint32_t shiftctrl;
107 uint32_t pinctrl;
109
110static inline void check_sm_param(__unused uint sm) {
111 valid_params_if(PIO, sm < NUM_PIO_STATE_MACHINES);
112}
113
114static inline void check_sm_mask(__unused uint mask) {
115 valid_params_if(PIO, mask < (1u << NUM_PIO_STATE_MACHINES));
116}
117
118
119static inline void check_pio_param(__unused PIO pio) {
120 valid_params_if(PIO, pio == pio0 || pio == pio1);
121}
122
132static inline void sm_config_set_out_pins(pio_sm_config *c, uint out_base, uint out_count) {
133 valid_params_if(PIO, out_base < 32);
134 valid_params_if(PIO, out_count <= 32);
135 c->pinctrl = (c->pinctrl & ~(PIO_SM0_PINCTRL_OUT_BASE_BITS | PIO_SM0_PINCTRL_OUT_COUNT_BITS)) |
136 (out_base << PIO_SM0_PINCTRL_OUT_BASE_LSB) |
137 (out_count << PIO_SM0_PINCTRL_OUT_COUNT_LSB);
138}
139
149static inline void sm_config_set_set_pins(pio_sm_config *c, uint set_base, uint set_count) {
150 valid_params_if(PIO, set_base < 32);
151 valid_params_if(PIO, set_count <= 5);
152 c->pinctrl = (c->pinctrl & ~(PIO_SM0_PINCTRL_SET_BASE_BITS | PIO_SM0_PINCTRL_SET_COUNT_BITS)) |
153 (set_base << PIO_SM0_PINCTRL_SET_BASE_LSB) |
154 (set_count << PIO_SM0_PINCTRL_SET_COUNT_LSB);
155}
156
165static inline void sm_config_set_in_pins(pio_sm_config *c, uint in_base) {
166 valid_params_if(PIO, in_base < 32);
167 c->pinctrl = (c->pinctrl & ~PIO_SM0_PINCTRL_IN_BASE_BITS) |
168 (in_base << PIO_SM0_PINCTRL_IN_BASE_LSB);
169}
170
179static inline void sm_config_set_sideset_pins(pio_sm_config *c, uint sideset_base) {
180 valid_params_if(PIO, sideset_base < 32);
181 c->pinctrl = (c->pinctrl & ~PIO_SM0_PINCTRL_SIDESET_BASE_BITS) |
182 (sideset_base << PIO_SM0_PINCTRL_SIDESET_BASE_LSB);
183}
184
193static inline void sm_config_set_sideset(pio_sm_config *c, uint bit_count, bool optional, bool pindirs) {
194 valid_params_if(PIO, bit_count <= 5);
195 valid_params_if(PIO, !optional || bit_count >= 1);
196 c->pinctrl = (c->pinctrl & ~PIO_SM0_PINCTRL_SIDESET_COUNT_BITS) |
197 (bit_count << PIO_SM0_PINCTRL_SIDESET_COUNT_LSB);
198
199 c->execctrl = (c->execctrl & ~(PIO_SM0_EXECCTRL_SIDE_EN_BITS | PIO_SM0_EXECCTRL_SIDE_PINDIR_BITS)) |
200 (bool_to_bit(optional) << PIO_SM0_EXECCTRL_SIDE_EN_LSB) |
201 (bool_to_bit(pindirs) << PIO_SM0_EXECCTRL_SIDE_PINDIR_LSB);
202}
203
217static inline void sm_config_set_clkdiv_int_frac(pio_sm_config *c, uint16_t div_int, uint8_t div_frac) {
218 c->clkdiv =
219 (((uint)div_frac) << PIO_SM0_CLKDIV_FRAC_LSB) |
220 (((uint)div_int) << PIO_SM0_CLKDIV_INT_LSB);
221}
222
223static inline void pio_calculate_clkdiv_from_float(float div, uint16_t *div_int, uint8_t *div_frac) {
224 valid_params_if(PIO, div >= 1 && div <= 65536);
225 *div_int = (uint16_t)div;
226 if (*div_int == 0) {
227 *div_frac = 0;
228 } else {
229 *div_frac = (uint8_t)((div - (float)*div_int) * (1u << 8u));
230 }
231}
232
248static inline void sm_config_set_clkdiv(pio_sm_config *c, float div) {
249 uint16_t div_int;
250 uint8_t div_frac;
251 pio_calculate_clkdiv_from_float(div, &div_int, &div_frac);
252 sm_config_set_clkdiv_int_frac(c, div_int, div_frac);
253}
254
263static inline void sm_config_set_wrap(pio_sm_config *c, uint wrap_target, uint wrap) {
264 valid_params_if(PIO, wrap < PIO_INSTRUCTION_COUNT);
265 valid_params_if(PIO, wrap_target < PIO_INSTRUCTION_COUNT);
266 c->execctrl = (c->execctrl & ~(PIO_SM0_EXECCTRL_WRAP_TOP_BITS | PIO_SM0_EXECCTRL_WRAP_BOTTOM_BITS)) |
267 (wrap_target << PIO_SM0_EXECCTRL_WRAP_BOTTOM_LSB) |
268 (wrap << PIO_SM0_EXECCTRL_WRAP_TOP_LSB);
269}
270
277static inline void sm_config_set_jmp_pin(pio_sm_config *c, uint pin) {
278 valid_params_if(PIO, pin < 32);
279 c->execctrl = (c->execctrl & ~PIO_SM0_EXECCTRL_JMP_PIN_BITS) |
280 (pin << PIO_SM0_EXECCTRL_JMP_PIN_LSB);
281}
282
291static inline void sm_config_set_in_shift(pio_sm_config *c, bool shift_right, bool autopush, uint push_threshold) {
292 valid_params_if(PIO, push_threshold <= 32);
293 c->shiftctrl = (c->shiftctrl &
294 ~(PIO_SM0_SHIFTCTRL_IN_SHIFTDIR_BITS |
295 PIO_SM0_SHIFTCTRL_AUTOPUSH_BITS |
296 PIO_SM0_SHIFTCTRL_PUSH_THRESH_BITS)) |
297 (bool_to_bit(shift_right) << PIO_SM0_SHIFTCTRL_IN_SHIFTDIR_LSB) |
298 (bool_to_bit(autopush) << PIO_SM0_SHIFTCTRL_AUTOPUSH_LSB) |
299 ((push_threshold & 0x1fu) << PIO_SM0_SHIFTCTRL_PUSH_THRESH_LSB);
300}
301
310static inline void sm_config_set_out_shift(pio_sm_config *c, bool shift_right, bool autopull, uint pull_threshold) {
311 valid_params_if(PIO, pull_threshold <= 32);
312 c->shiftctrl = (c->shiftctrl &
313 ~(PIO_SM0_SHIFTCTRL_OUT_SHIFTDIR_BITS |
314 PIO_SM0_SHIFTCTRL_AUTOPULL_BITS |
315 PIO_SM0_SHIFTCTRL_PULL_THRESH_BITS)) |
316 (bool_to_bit(shift_right) << PIO_SM0_SHIFTCTRL_OUT_SHIFTDIR_LSB) |
317 (bool_to_bit(autopull) << PIO_SM0_SHIFTCTRL_AUTOPULL_LSB) |
318 ((pull_threshold & 0x1fu) << PIO_SM0_SHIFTCTRL_PULL_THRESH_LSB);
319}
320
327static inline void sm_config_set_fifo_join(pio_sm_config *c, enum pio_fifo_join join) {
328 valid_params_if(PIO, join == PIO_FIFO_JOIN_NONE || join == PIO_FIFO_JOIN_TX || join == PIO_FIFO_JOIN_RX);
329 c->shiftctrl = (c->shiftctrl & (uint)~(PIO_SM0_SHIFTCTRL_FJOIN_TX_BITS | PIO_SM0_SHIFTCTRL_FJOIN_RX_BITS)) |
330 (((uint)join) << PIO_SM0_SHIFTCTRL_FJOIN_TX_LSB);
331}
332
341static inline void sm_config_set_out_special(pio_sm_config *c, bool sticky, bool has_enable_pin, uint enable_pin_index) {
342 c->execctrl = (c->execctrl &
343 (uint)~(PIO_SM0_EXECCTRL_OUT_STICKY_BITS | PIO_SM0_EXECCTRL_INLINE_OUT_EN_BITS |
344 PIO_SM0_EXECCTRL_OUT_EN_SEL_BITS)) |
345 (bool_to_bit(sticky) << PIO_SM0_EXECCTRL_OUT_STICKY_LSB) |
346 (bool_to_bit(has_enable_pin) << PIO_SM0_EXECCTRL_INLINE_OUT_EN_LSB) |
347 ((enable_pin_index << PIO_SM0_EXECCTRL_OUT_EN_SEL_LSB) & PIO_SM0_EXECCTRL_OUT_EN_SEL_BITS);
348}
349
357static inline void sm_config_set_mov_status(pio_sm_config *c, enum pio_mov_status_type status_sel, uint status_n) {
358 valid_params_if(PIO, status_sel == STATUS_TX_LESSTHAN || status_sel == STATUS_RX_LESSTHAN);
359 c->execctrl = (c->execctrl
360 & ~(PIO_SM0_EXECCTRL_STATUS_SEL_BITS | PIO_SM0_EXECCTRL_STATUS_N_BITS))
361 | ((((uint)status_sel) << PIO_SM0_EXECCTRL_STATUS_SEL_LSB) & PIO_SM0_EXECCTRL_STATUS_SEL_BITS)
362 | ((status_n << PIO_SM0_EXECCTRL_STATUS_N_LSB) & PIO_SM0_EXECCTRL_STATUS_N_BITS);
363}
364
365
386 pio_sm_config c = {0, 0, 0, 0};
388 sm_config_set_wrap(&c, 0, 31);
389 sm_config_set_in_shift(&c, true, false, 32);
390 sm_config_set_out_shift(&c, true, false, 32);
391 return c;
392}
393
401static inline void pio_sm_set_config(PIO pio, uint sm, const pio_sm_config *config) {
402 check_pio_param(pio);
403 check_sm_param(sm);
404 pio->sm[sm].clkdiv = config->clkdiv;
405 pio->sm[sm].execctrl = config->execctrl;
406 pio->sm[sm].shiftctrl = config->shiftctrl;
407 pio->sm[sm].pinctrl = config->pinctrl;
408}
409
416static inline uint pio_get_index(PIO pio) {
417 check_pio_param(pio);
418 return pio == pio1 ? 1 : 0;
419}
420
433static inline void pio_gpio_init(PIO pio, uint pin) {
434 check_pio_param(pio);
435 valid_params_if(PIO, pin < 32);
436 gpio_set_function(pin, pio == pio0 ? GPIO_FUNC_PIO0 : GPIO_FUNC_PIO1);
437}
438
446static inline uint pio_get_dreq(PIO pio, uint sm, bool is_tx) {
447 static_assert(DREQ_PIO0_TX1 == DREQ_PIO0_TX0 + 1, "");
448 static_assert(DREQ_PIO0_TX2 == DREQ_PIO0_TX0 + 2, "");
449 static_assert(DREQ_PIO0_TX3 == DREQ_PIO0_TX0 + 3, "");
450 static_assert(DREQ_PIO0_RX0 == DREQ_PIO0_TX0 + NUM_PIO_STATE_MACHINES, "");
451 static_assert(DREQ_PIO1_RX0 == DREQ_PIO1_TX0 + NUM_PIO_STATE_MACHINES, "");
452 check_pio_param(pio);
453 check_sm_param(sm);
454 return sm + (is_tx ? 0 : NUM_PIO_STATE_MACHINES) + (pio == pio0 ? DREQ_PIO0_TX0 : DREQ_PIO1_TX0);
455}
456
457typedef struct pio_program {
458 const uint16_t *instructions;
459 uint8_t length;
460 int8_t origin; // required instruction memory origin or -1
461} __packed pio_program_t;
462
470bool pio_can_add_program(PIO pio, const pio_program_t *program);
471
480bool pio_can_add_program_at_offset(PIO pio, const pio_program_t *program, uint offset);
481
491uint pio_add_program(PIO pio, const pio_program_t *program);
492
502void pio_add_program_at_offset(PIO pio, const pio_program_t *program, uint offset);
503
511void pio_remove_program(PIO pio, const pio_program_t *program, uint loaded_offset);
512
519
537void pio_sm_init(PIO pio, uint sm, uint initial_pc, const pio_sm_config *config);
538
546static inline void pio_sm_set_enabled(PIO pio, uint sm, bool enabled) {
547 check_pio_param(pio);
548 check_sm_param(sm);
549 pio->ctrl = (pio->ctrl & ~(1u << sm)) | (bool_to_bit(enabled) << sm);
550}
551
565static inline void pio_set_sm_mask_enabled(PIO pio, uint32_t mask, bool enabled) {
566 check_pio_param(pio);
567 check_sm_mask(mask);
568 pio->ctrl = (pio->ctrl & ~mask) | (enabled ? mask : 0u);
569}
570
580static inline void pio_sm_restart(PIO pio, uint sm) {
581 check_pio_param(pio);
582 check_sm_param(sm);
583 pio->ctrl |= 1u << (PIO_CTRL_SM_RESTART_LSB + sm);
584}
585
595static inline void pio_restart_sm_mask(PIO pio, uint32_t mask) {
596 check_pio_param(pio);
597 check_sm_mask(mask);
598 pio->ctrl |= (mask << PIO_CTRL_SM_RESTART_LSB) & PIO_CTRL_SM_RESTART_BITS;
599}
600
622static inline void pio_sm_clkdiv_restart(PIO pio, uint sm) {
623 check_pio_param(pio);
624 check_sm_param(sm);
625 pio->ctrl |= 1u << (PIO_CTRL_CLKDIV_RESTART_LSB + sm);
626}
627
657static inline void pio_clkdiv_restart_sm_mask(PIO pio, uint32_t mask) {
658 check_pio_param(pio);
659 check_sm_mask(mask);
660 pio->ctrl |= (mask << PIO_CTRL_CLKDIV_RESTART_LSB) & PIO_CTRL_CLKDIV_RESTART_BITS;
661}
662
674static inline void pio_enable_sm_mask_in_sync(PIO pio, uint32_t mask) {
675 check_pio_param(pio);
676 check_sm_mask(mask);
677 pio->ctrl |= ((mask << PIO_CTRL_CLKDIV_RESTART_LSB) & PIO_CTRL_CLKDIV_RESTART_BITS) |
678 ((mask << PIO_CTRL_SM_ENABLE_LSB) & PIO_CTRL_SM_ENABLE_BITS);
679}
680
685 pis_interrupt0 = PIO_INTR_SM0_LSB,
686 pis_interrupt1 = PIO_INTR_SM1_LSB,
687 pis_interrupt2 = PIO_INTR_SM2_LSB,
688 pis_interrupt3 = PIO_INTR_SM3_LSB,
689 pis_sm0_tx_fifo_not_full = PIO_INTR_SM0_TXNFULL_LSB,
690 pis_sm1_tx_fifo_not_full = PIO_INTR_SM1_TXNFULL_LSB,
691 pis_sm2_tx_fifo_not_full = PIO_INTR_SM2_TXNFULL_LSB,
692 pis_sm3_tx_fifo_not_full = PIO_INTR_SM3_TXNFULL_LSB,
693 pis_sm0_rx_fifo_not_empty = PIO_INTR_SM0_RXNEMPTY_LSB,
694 pis_sm1_rx_fifo_not_empty = PIO_INTR_SM1_RXNEMPTY_LSB,
695 pis_sm2_rx_fifo_not_empty = PIO_INTR_SM2_RXNEMPTY_LSB,
696 pis_sm3_rx_fifo_not_empty = PIO_INTR_SM3_RXNEMPTY_LSB,
697};
698
706static inline void pio_set_irq0_source_enabled(PIO pio, enum pio_interrupt_source source, bool enabled) {
707 check_pio_param(pio);
708 invalid_params_if(PIO, source >= 12);
709 if (enabled)
710 hw_set_bits(&pio->inte0, 1u << source);
711 else
712 hw_clear_bits(&pio->inte0, 1u << source);
713}
714
722static inline void pio_set_irq1_source_enabled(PIO pio, enum pio_interrupt_source source, bool enabled) {
723 check_pio_param(pio);
724 invalid_params_if(PIO, source >= 12);
725 if (enabled)
726 hw_set_bits(&pio->inte1, 1u << source);
727 else
728 hw_clear_bits(&pio->inte1, 1u << source);
729}
730
738static inline void pio_set_irq0_source_mask_enabled(PIO pio, uint32_t source_mask, bool enabled) {
739 check_pio_param(pio);
740 invalid_params_if(PIO, source_mask > PIO_INTR_BITS);
741 if (enabled) {
742 hw_set_bits(&pio->inte0, source_mask);
743 } else {
744 hw_clear_bits(&pio->inte0, source_mask);
745 }
746}
747
755static inline void pio_set_irq1_source_mask_enabled(PIO pio, uint32_t source_mask, bool enabled) {
756 check_pio_param(pio);
757 invalid_params_if(PIO, source_mask > PIO_INTR_BITS);
758 if (enabled) {
759 hw_set_bits(&pio->inte1, source_mask);
760 } else {
761 hw_clear_bits(&pio->inte1, source_mask);
762 }
763}
764
773static inline void pio_set_irqn_source_enabled(PIO pio, uint irq_index, enum pio_interrupt_source source, bool enabled) {
774 invalid_params_if(PIO, irq_index > 1);
775 if (irq_index) {
776 pio_set_irq1_source_enabled(pio, source, enabled);
777 } else {
778 pio_set_irq0_source_enabled(pio, source, enabled);
779 }
780}
781
790static inline void pio_set_irqn_source_mask_enabled(PIO pio, uint irq_index, uint32_t source_mask, bool enabled) {
791 invalid_params_if(PIO, irq_index > 1);
792 if (irq_index) {
793 pio_set_irq0_source_mask_enabled(pio, source_mask, enabled);
794 } else {
795 pio_set_irq1_source_mask_enabled(pio, source_mask, enabled);
796 }
797}
798
806static inline bool pio_interrupt_get(PIO pio, uint pio_interrupt_num) {
807 check_pio_param(pio);
808 invalid_params_if(PIO, pio_interrupt_num >= 8);
809 return pio->irq & (1u << pio_interrupt_num);
810}
811
818static inline void pio_interrupt_clear(PIO pio, uint pio_interrupt_num) {
819 check_pio_param(pio);
820 invalid_params_if(PIO, pio_interrupt_num >= 8);
821 hw_set_bits(&pio->irq, (1u << pio_interrupt_num));
822}
823
831static inline uint8_t pio_sm_get_pc(PIO pio, uint sm) {
832 check_pio_param(pio);
833 check_sm_param(sm);
834 return (uint8_t) pio->sm[sm].addr;
835}
836
849inline static void pio_sm_exec(PIO pio, uint sm, uint instr) {
850 check_pio_param(pio);
851 check_sm_param(sm);
852 pio->sm[sm].instr = instr;
853}
854
862static inline bool pio_sm_is_exec_stalled(PIO pio, uint sm) {
863 check_pio_param(pio);
864 check_sm_param(sm);
865 return !!(pio->sm[sm].execctrl & PIO_SM0_EXECCTRL_EXEC_STALLED_BITS);
866}
867
880static inline void pio_sm_exec_wait_blocking(PIO pio, uint sm, uint instr) {
881 check_pio_param(pio);
882 check_sm_param(sm);
883 pio_sm_exec(pio, sm, instr);
885}
886
896static inline void pio_sm_set_wrap(PIO pio, uint sm, uint wrap_target, uint wrap) {
897 check_pio_param(pio);
898 check_sm_param(sm);
899 valid_params_if(PIO, wrap < PIO_INSTRUCTION_COUNT);
900 valid_params_if(PIO, wrap_target < PIO_INSTRUCTION_COUNT);
901 pio->sm[sm].execctrl =
902 (pio->sm[sm].execctrl & ~(PIO_SM0_EXECCTRL_WRAP_TOP_BITS | PIO_SM0_EXECCTRL_WRAP_BOTTOM_BITS)) |
903 (wrap_target << PIO_SM0_EXECCTRL_WRAP_BOTTOM_LSB) |
904 (wrap << PIO_SM0_EXECCTRL_WRAP_TOP_LSB);
905}
906
917static inline void pio_sm_set_out_pins(PIO pio, uint sm, uint out_base, uint out_count) {
918 check_pio_param(pio);
919 check_sm_param(sm);
920 valid_params_if(PIO, out_base < 32);
921 valid_params_if(PIO, out_count <= 32);
922 pio->sm[sm].pinctrl = (pio->sm[sm].pinctrl & ~(PIO_SM0_PINCTRL_OUT_BASE_BITS | PIO_SM0_PINCTRL_OUT_COUNT_BITS)) |
923 (out_base << PIO_SM0_PINCTRL_OUT_BASE_LSB) |
924 (out_count << PIO_SM0_PINCTRL_OUT_COUNT_LSB);
925}
926
927
938static inline void pio_sm_set_set_pins(PIO pio, uint sm, uint set_base, uint set_count) {
939 check_pio_param(pio);
940 check_sm_param(sm);
941 valid_params_if(PIO, set_base < 32);
942 valid_params_if(PIO, set_count <= 5);
943 pio->sm[sm].pinctrl = (pio->sm[sm].pinctrl & ~(PIO_SM0_PINCTRL_SET_BASE_BITS | PIO_SM0_PINCTRL_SET_COUNT_BITS)) |
944 (set_base << PIO_SM0_PINCTRL_SET_BASE_LSB) |
945 (set_count << PIO_SM0_PINCTRL_SET_COUNT_LSB);
946}
947
957static inline void pio_sm_set_in_pins(PIO pio, uint sm, uint in_base) {
958 check_pio_param(pio);
959 check_sm_param(sm);
960 valid_params_if(PIO, in_base < 32);
961 pio->sm[sm].pinctrl = (pio->sm[sm].pinctrl & ~PIO_SM0_PINCTRL_IN_BASE_BITS) |
962 (in_base << PIO_SM0_PINCTRL_IN_BASE_LSB);
963}
964
974static inline void pio_sm_set_sideset_pins(PIO pio, uint sm, uint sideset_base) {
975 check_pio_param(pio);
976 check_sm_param(sm);
977 valid_params_if(PIO, sideset_base < 32);
978 pio->sm[sm].pinctrl = (pio->sm[sm].pinctrl & ~PIO_SM0_PINCTRL_SIDESET_BASE_BITS) |
979 (sideset_base << PIO_SM0_PINCTRL_SIDESET_BASE_LSB);
980}
981
996static inline void pio_sm_put(PIO pio, uint sm, uint32_t data) {
997 check_pio_param(pio);
998 check_sm_param(sm);
999 pio->txf[sm] = data;
1000}
1001
1017static inline uint32_t pio_sm_get(PIO pio, uint sm) {
1018 check_pio_param(pio);
1019 check_sm_param(sm);
1020 return pio->rxf[sm];
1021}
1022
1030static inline bool pio_sm_is_rx_fifo_full(PIO pio, uint sm) {
1031 check_pio_param(pio);
1032 check_sm_param(sm);
1033 return (pio->fstat & (1u << (PIO_FSTAT_RXFULL_LSB + sm))) != 0;
1034}
1035
1043static inline bool pio_sm_is_rx_fifo_empty(PIO pio, uint sm) {
1044 check_pio_param(pio);
1045 check_sm_param(sm);
1046 return (pio->fstat & (1u << (PIO_FSTAT_RXEMPTY_LSB + sm))) != 0;
1047}
1048
1056static inline uint pio_sm_get_rx_fifo_level(PIO pio, uint sm) {
1057 check_pio_param(pio);
1058 check_sm_param(sm);
1059 uint bitoffs = PIO_FLEVEL_RX0_LSB + sm * (PIO_FLEVEL_RX1_LSB - PIO_FLEVEL_RX0_LSB);
1060 const uint32_t mask = PIO_FLEVEL_RX0_BITS >> PIO_FLEVEL_RX0_LSB;
1061 return (pio->flevel >> bitoffs) & mask;
1062}
1063
1071static inline bool pio_sm_is_tx_fifo_full(PIO pio, uint sm) {
1072 check_pio_param(pio);
1073 check_sm_param(sm);
1074 return (pio->fstat & (1u << (PIO_FSTAT_TXFULL_LSB + sm))) != 0;
1075}
1076
1084static inline bool pio_sm_is_tx_fifo_empty(PIO pio, uint sm) {
1085 check_pio_param(pio);
1086 check_sm_param(sm);
1087 return (pio->fstat & (1u << (PIO_FSTAT_TXEMPTY_LSB + sm))) != 0;
1088}
1089
1097static inline uint pio_sm_get_tx_fifo_level(PIO pio, uint sm) {
1098 check_pio_param(pio);
1099 check_sm_param(sm);
1100 unsigned int bitoffs = PIO_FLEVEL_TX0_LSB + sm * (PIO_FLEVEL_TX1_LSB - PIO_FLEVEL_TX0_LSB);
1101 const uint32_t mask = PIO_FLEVEL_TX0_BITS >> PIO_FLEVEL_TX0_LSB;
1102 return (pio->flevel >> bitoffs) & mask;
1103}
1104
1112static inline void pio_sm_put_blocking(PIO pio, uint sm, uint32_t data) {
1113 check_pio_param(pio);
1114 check_sm_param(sm);
1116 pio_sm_put(pio, sm, data);
1117}
1118
1125static inline uint32_t pio_sm_get_blocking(PIO pio, uint sm) {
1126 check_pio_param(pio);
1127 check_sm_param(sm);
1129 return pio_sm_get(pio, sm);
1130}
1131
1145void pio_sm_drain_tx_fifo(PIO pio, uint sm);
1146
1155static inline void pio_sm_set_clkdiv_int_frac(PIO pio, uint sm, uint16_t div_int, uint8_t div_frac) {
1156 check_pio_param(pio);
1157 check_sm_param(sm);
1158 pio->sm[sm].clkdiv =
1159 (((uint)div_frac) << PIO_SM0_CLKDIV_FRAC_LSB) |
1160 (((uint)div_int) << PIO_SM0_CLKDIV_INT_LSB);
1161}
1162
1170static inline void pio_sm_set_clkdiv(PIO pio, uint sm, float div) {
1171 check_pio_param(pio);
1172 check_sm_param(sm);
1173 uint16_t div_int;
1174 uint8_t div_frac;
1175 pio_calculate_clkdiv_from_float(div, &div_int, &div_frac);
1176 pio_sm_set_clkdiv_int_frac(pio, sm, div_int, div_frac);
1177}
1178
1185static inline void pio_sm_clear_fifos(PIO pio, uint sm) {
1186 // changing the FIFO join state clears the fifo
1187 check_pio_param(pio);
1188 check_sm_param(sm);
1189 hw_xor_bits(&pio->sm[sm].shiftctrl, PIO_SM0_SHIFTCTRL_FJOIN_RX_BITS);
1190 hw_xor_bits(&pio->sm[sm].shiftctrl, PIO_SM0_SHIFTCTRL_FJOIN_RX_BITS);
1191}
1192
1205void pio_sm_set_pins(PIO pio, uint sm, uint32_t pin_values);
1206
1220void pio_sm_set_pins_with_mask(PIO pio, uint sm, uint32_t pin_values, uint32_t pin_mask);
1221
1235void pio_sm_set_pindirs_with_mask(PIO pio, uint sm, uint32_t pin_dirs, uint32_t pin_mask);
1236
1251void pio_sm_set_consecutive_pindirs(PIO pio, uint sm, uint pin_base, uint pin_count, bool is_out);
1252
1263void pio_sm_claim(PIO pio, uint sm);
1264
1275void pio_claim_sm_mask(PIO pio, uint sm_mask);
1276
1285void pio_sm_unclaim(PIO pio, uint sm);
1286
1294int pio_claim_unused_sm(PIO pio, bool required);
1295
1305bool pio_sm_is_claimed(PIO pio, uint sm);
1306
1307#ifdef __cplusplus
1308}
1309#endif
1310
1311#endif // _PIO_H_
static __force_inline void hw_set_bits(io_rw_32 *addr, uint32_t mask)
Atomically set the specified bits to 1 in a HW register.
Definition: address_mapped.h:121
static __force_inline void hw_xor_bits(io_rw_32 *addr, uint32_t mask)
Atomically flip the specified bits in a HW register.
Definition: address_mapped.h:141
static __force_inline void hw_clear_bits(io_rw_32 *addr, uint32_t mask)
Atomically clear the specified bits to 0 in a HW register.
Definition: address_mapped.h:131
void gpio_set_function(uint gpio, enum gpio_function fn)
Select GPIO function.
Definition: gpio.c:10
static uint pio_sm_get_tx_fifo_level(PIO pio, uint sm)
Return the number of elements currently in a state machine's TX FIFO.
Definition: pio.h:1097
static void pio_sm_set_config(PIO pio, uint sm, const pio_sm_config *config)
Apply a state machine configuration to a state machine.
Definition: pio.h:401
pio_interrupt_source
PIO interrupt source numbers for pio related IRQs.
Definition: pio.h:684
static uint32_t pio_sm_get_blocking(PIO pio, uint sm)
Read a word of data from a state machine's RX FIFO, blocking if the FIFO is empty.
Definition: pio.h:1125
void pio_sm_set_pins(PIO pio, uint sm, uint32_t pin_values)
Use a state machine to set a value on all pins for the PIO instance.
Definition: pio.c:156
static void pio_sm_exec_wait_blocking(PIO pio, uint sm, uint instr)
Immediately execute an instruction on a state machine and wait for it to complete.
Definition: pio.h:880
pio_mov_status_type
MOV status types.
Definition: pio.h:64
uint pio_add_program(PIO pio, const pio_program_t *program)
Attempt to load the program, panicking if not possible.
Definition: pio.c:117
static void pio_set_irqn_source_enabled(PIO pio, uint irq_index, enum pio_interrupt_source source, bool enabled)
Enable/Disable a single source on a PIO's specified (0/1) IRQ index.
Definition: pio.h:773
static bool pio_sm_is_tx_fifo_full(PIO pio, uint sm)
Determine if a state machine's TX FIFO is full.
Definition: pio.h:1071
static uint pio_get_dreq(PIO pio, uint sm, bool is_tx)
Return the DREQ to use for pacing transfers to/from a particular state machine FIFO.
Definition: pio.h:446
void pio_sm_drain_tx_fifo(PIO pio, uint sm)
Empty out a state machine's TX FIFO.
Definition: pio.c:250
void pio_claim_sm_mask(PIO pio, uint sm_mask)
Mark multiple state machines as used.
Definition: pio.c:33
void pio_sm_set_consecutive_pindirs(PIO pio, uint sm, uint pin_base, uint pin_count, bool is_out)
Use a state machine to set the same pin direction for multiple consecutive pins for the PIO instance.
Definition: pio.c:205
void pio_add_program_at_offset(PIO pio, const pio_program_t *program, uint offset)
Attempt to load the program at the specified instruction memory offset, panicking if not possible.
Definition: pio.c:128
int pio_claim_unused_sm(PIO pio, bool required)
Claim a free state machine on a PIO instance.
Definition: pio.c:45
void pio_sm_unclaim(PIO pio, uint sm)
Mark a state machine as no longer used.
Definition: pio.c:39
static void pio_clkdiv_restart_sm_mask(PIO pio, uint32_t mask)
Restart multiple state machines' clock dividers from a phase of 0.
Definition: pio.h:657
bool pio_sm_is_claimed(PIO pio, uint sm)
Determine if a PIO state machine is claimed.
Definition: pio.c:54
static void pio_set_irq1_source_enabled(PIO pio, enum pio_interrupt_source source, bool enabled)
Enable/Disable a single source on a PIO's IRQ 1.
Definition: pio.h:722
static void pio_interrupt_clear(PIO pio, uint pio_interrupt_num)
Clear a particular PIO interrupt.
Definition: pio.h:818
static uint32_t pio_sm_get(PIO pio, uint sm)
Read a word of data from a state machine's RX FIFO.
Definition: pio.h:1017
static bool pio_sm_is_rx_fifo_full(PIO pio, uint sm)
Determine if a state machine's RX FIFO is full.
Definition: pio.h:1030
static void pio_sm_set_wrap(PIO pio, uint sm, uint wrap_target, uint wrap)
Set the current wrap configuration for a state machine.
Definition: pio.h:896
static void pio_sm_restart(PIO pio, uint sm)
Restart a state machine with a known state.
Definition: pio.h:580
pio_fifo_join
FIFO join states.
Definition: pio.h:55
static void pio_sm_exec(PIO pio, uint sm, uint instr)
Immediately execute an instruction on a state machine.
Definition: pio.h:849
static void pio_set_irq0_source_mask_enabled(PIO pio, uint32_t source_mask, bool enabled)
Enable/Disable multiple sources on a PIO's IRQ 0.
Definition: pio.h:738
void pio_remove_program(PIO pio, const pio_program_t *program, uint loaded_offset)
Remove a program from a PIO instance's instruction memory.
Definition: pio.c:134
void pio_sm_set_pindirs_with_mask(PIO pio, uint sm, uint32_t pin_dirs, uint32_t pin_mask)
Use a state machine to set the pin directions for multiple pins for the PIO instance.
Definition: pio.c:190
void pio_clear_instruction_memory(PIO pio)
Clears all of a PIO instance's instruction memory.
Definition: pio.c:143
static void pio_sm_set_clkdiv(PIO pio, uint sm, float div)
set the current clock divider for a state machine
Definition: pio.h:1170
static uint pio_sm_get_rx_fifo_level(PIO pio, uint sm)
Return the number of elements currently in a state machine's RX FIFO.
Definition: pio.h:1056
#define pio0
Identifier for the first (PIO 0) hardware PIO instance (for use in PIO functions).
Definition: pio.h:78
#define pio1
Identifier for the second (PIO 1) hardware PIO instance (for use in PIO functions).
Definition: pio.h:88
void pio_sm_set_pins_with_mask(PIO pio, uint sm, uint32_t pin_values, uint32_t pin_mask)
Use a state machine to set a value on multiple pins for the PIO instance.
Definition: pio.c:175
static uint8_t pio_sm_get_pc(PIO pio, uint sm)
Return the current program counter for a state machine.
Definition: pio.h:831
static void pio_sm_set_enabled(PIO pio, uint sm, bool enabled)
Enable or disable a PIO state machine.
Definition: pio.h:546
void pio_sm_claim(PIO pio, uint sm)
Mark a state machine as used.
Definition: pio.c:23
bool pio_can_add_program(PIO pio, const pio_program_t *program)
Determine whether the given program can (at the time of the call) be loaded onto the PIO instance.
Definition: pio.c:81
static void pio_set_irq0_source_enabled(PIO pio, enum pio_interrupt_source source, bool enabled)
Enable/Disable a single source on a PIO's IRQ 0.
Definition: pio.h:706
static bool pio_interrupt_get(PIO pio, uint pio_interrupt_num)
Determine if a particular PIO interrupt is set.
Definition: pio.h:806
static void pio_sm_set_clkdiv_int_frac(PIO pio, uint sm, uint16_t div_int, uint8_t div_frac)
set the current clock divider for a state machine using a 16:8 fraction
Definition: pio.h:1155
static bool pio_sm_is_exec_stalled(PIO pio, uint sm)
Determine if an instruction set by pio_sm_exec() is stalled executing.
Definition: pio.h:862
bool pio_can_add_program_at_offset(PIO pio, const pio_program_t *program, uint offset)
Determine whether the given program can (at the time of the call) be loaded onto the PIO instance sta...
Definition: pio.c:97
void pio_sm_init(PIO pio, uint sm, uint initial_pc, const pio_sm_config *config)
Resets the state machine to a consistent state, and configures it.
Definition: pio.c:222
static void pio_sm_put(PIO pio, uint sm, uint32_t data)
Write a word of data to a state machine's TX FIFO.
Definition: pio.h:996
static void pio_sm_clear_fifos(PIO pio, uint sm)
Clear a state machine's TX and RX FIFOs.
Definition: pio.h:1185
static void pio_enable_sm_mask_in_sync(PIO pio, uint32_t mask)
Enable multiple PIO state machines synchronizing their clock dividers.
Definition: pio.h:674
static void pio_sm_clkdiv_restart(PIO pio, uint sm)
Restart a state machine's clock divider from a phase of 0.
Definition: pio.h:622
static bool pio_sm_is_rx_fifo_empty(PIO pio, uint sm)
Determine if a state machine's RX FIFO is empty.
Definition: pio.h:1043
static bool pio_sm_is_tx_fifo_empty(PIO pio, uint sm)
Determine if a state machine's TX FIFO is empty.
Definition: pio.h:1084
static void pio_set_irq1_source_mask_enabled(PIO pio, uint32_t source_mask, bool enabled)
Enable/Disable multiple sources on a PIO's IRQ 1.
Definition: pio.h:755
static void pio_restart_sm_mask(PIO pio, uint32_t mask)
Restart multiple state machine with a known state.
Definition: pio.h:595
static uint pio_get_index(PIO pio)
Return the instance number of a PIO instance.
Definition: pio.h:416
static void pio_sm_put_blocking(PIO pio, uint sm, uint32_t data)
Write a word of data to a state machine's TX FIFO, blocking if the FIFO is full.
Definition: pio.h:1112
static void pio_set_sm_mask_enabled(PIO pio, uint32_t mask, bool enabled)
Enable or disable multiple PIO state machines.
Definition: pio.h:565
static void pio_gpio_init(PIO pio, uint pin)
Setup the function select for a GPIO to use output from the given PIO instance.
Definition: pio.h:433
static void pio_set_irqn_source_mask_enabled(PIO pio, uint irq_index, uint32_t source_mask, bool enabled)
Enable/Disable multiple sources on a PIO's specified (0/1) IRQ index.
Definition: pio.h:790
static __always_inline void tight_loop_contents(void)
No-op function for the body of tight loops.
Definition: platform.h:347
static void sm_config_set_clkdiv_int_frac(pio_sm_config *c, uint16_t div_int, uint8_t div_frac)
Set the state machine clock divider (from integer and fractional parts - 16:8) in a state machine con...
Definition: pio.h:217
static void sm_config_set_out_shift(pio_sm_config *c, bool shift_right, bool autopull, uint pull_threshold)
Setup 'out' shifting parameters in a state machine configuration.
Definition: pio.h:310
static void pio_sm_set_out_pins(PIO pio, uint sm, uint out_base, uint out_count)
Set the current 'out' pins for a state machine.
Definition: pio.h:917
static void pio_sm_set_sideset_pins(PIO pio, uint sm, uint sideset_base)
Set the current 'sideset' pins for a state machine.
Definition: pio.h:974
static void sm_config_set_out_special(pio_sm_config *c, bool sticky, bool has_enable_pin, uint enable_pin_index)
Set special 'out' operations in a state machine configuration.
Definition: pio.h:341
static void sm_config_set_in_pins(pio_sm_config *c, uint in_base)
Set the 'in' pins in a state machine configuration.
Definition: pio.h:165
static void pio_sm_set_set_pins(PIO pio, uint sm, uint set_base, uint set_count)
Set the current 'set' pins for a state machine.
Definition: pio.h:938
static void sm_config_set_mov_status(pio_sm_config *c, enum pio_mov_status_type status_sel, uint status_n)
Set source for 'mov status' in a state machine configuration.
Definition: pio.h:357
static void sm_config_set_sideset_pins(pio_sm_config *c, uint sideset_base)
Set the 'sideset' pins in a state machine configuration.
Definition: pio.h:179
static void sm_config_set_set_pins(pio_sm_config *c, uint set_base, uint set_count)
Set the 'set' pins in a state machine configuration.
Definition: pio.h:149
static void sm_config_set_clkdiv(pio_sm_config *c, float div)
Set the state machine clock divider (from a floating point value) in a state machine configuration.
Definition: pio.h:248
static void sm_config_set_in_shift(pio_sm_config *c, bool shift_right, bool autopush, uint push_threshold)
Setup 'in' shifting parameters in a state machine configuration.
Definition: pio.h:291
static void pio_sm_set_in_pins(PIO pio, uint sm, uint in_base)
Set the current 'in' pins for a state machine.
Definition: pio.h:957
static void sm_config_set_jmp_pin(pio_sm_config *c, uint pin)
Set the 'jmp' pin in a state machine configuration.
Definition: pio.h:277
static pio_sm_config pio_get_default_sm_config(void)
Get the default state machine configuration.
Definition: pio.h:385
static void sm_config_set_out_pins(pio_sm_config *c, uint out_base, uint out_count)
Set the 'out' pins in a state machine configuration.
Definition: pio.h:132
static void sm_config_set_sideset(pio_sm_config *c, uint bit_count, bool optional, bool pindirs)
Set the 'sideset' options in a state machine configuration.
Definition: pio.h:193
static void sm_config_set_wrap(pio_sm_config *c, uint wrap_target, uint wrap)
Set the wrap addresses in a state machine configuration.
Definition: pio.h:263
static void sm_config_set_fifo_join(pio_sm_config *c, enum pio_fifo_join join)
Setup the FIFO joining in a state machine configuration.
Definition: pio.h:327
Definition: pio.h:79
Definition: pio.h:457
PIO Configuration structure.
Definition: pio.h:103