Cleanup/clarification of PIO behavior with >32 pins (#2085)

This commit is contained in:
Graham Sanderson 2024-11-22 13:13:15 -06:00 committed by GitHub
parent 3dce58f21b
commit 39a7f97116
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 169 additions and 61 deletions

View File

@ -69,6 +69,31 @@
* Full details of the PIO can be found in the appropriate RP-series datasheet. Note that there are
* additional features in the RP2350 PIO implementation that mean care should be taken when writing PIO
* code that needs to run on both the RP2040 and the RP2350.
*
* \anchor pio_sm_pins
* \if rp2040_specific
* On RP2040, pin numbers may always be specified from 0-31
* \endif
*
* \if rp2350_specific
* On RP2350A, pin numbers may always be specified from 0-31.
*
* On RP2350B, there are 48 pins but each PIO instance can only address 32 pins (the PIO
* instance either addresses pins 0-31 or 16-47 based on \ref pio_set_gpio_base). The
* `pio_sm_` methods that directly affect the hardware always take _real_ pin numbers in the full range, however:
*
* * If `PICO_PIO_USE_GPIO_BASE != 1` then the 5th bit of the pin number is ignored. This is done so
* that programs compiled for boards with RP2350A do not incur the extra overhead of dealing with higher pins that don't exist.
* Effectively these functions behave exactly like RP2040 in this case.
* Note that `PICO_PIO_USE_GPIO_BASE` is defaulted to 0 if `PICO_RP2350A` is 1
* * If `PICO_PIO_USE_GPIO_BASE == 1` then the passed pin numbers are adjusted internally by subtracting
* the GPIO base to give a pin number in the range 0-31 from the PIO's perspective
*
* You can set `PARAM_ASSERTIONS_ENABLED_HARDWARE_PIO = 1` to enable parameter checking to debug pin (or other) issues with
* hardware_pio methods.
*
* Note that pin masks follow the same rules as individual pins; bit N of a 32-bit or 64-bit mask always refers to pin N.
* \endif
*/
#ifdef __cplusplus
@ -212,6 +237,37 @@ static_assert(DREQ_PIO1_RX0 == DREQ_PIO1_TX0 + NUM_PIO_STATE_MACHINES, "");
* A PIO block needs to be configured, these functions provide helpers to set up configuration
* structures. See \ref pio_sm_set_config
*
* \anchor sm_config_pins
* \if rp2040_specific
* On RP2040, pin numbers may always be specified from 0-31
* \endif
*
* \if rp2350_specific
* On RP2350A, pin numbers may always be specified from 0-31.
*
* On RP2350B, there are 48 pins but each PIO instance can only address 32 pins (the PIO
* instance either addresses pins 0-31 or 16-47 based on \ref pio_set_gpio_base). The
* `sm_config_` state machine configuration always take _real_ pin numbers in the full range, however:
*
* * If `PICO_PIO_USE_GPIO_BASE != 1` then the 5th bit of the pin number is ignored. This is done so
* that programs compiled for boards with RP2350A do not incur the extra overhead of dealing with higher pins that don't exist.
* Effectively these functions behave exactly like RP2040 in this case.
* Note that `PICO_PIO_USE_GPIO_BASE` is defaulted to 0 if `PICO_RP2350A` is 1
* * If `PICO_PIO_USE_GPIO_BASE == 1` then the state machine configuration stores the actual pin numbers in the range 0-47.
* Of course in this scenario, it is possible to make an invalid configuration (one which uses pins in both the ranges
* 0-15 and 32-47).
*
* \ref pio_sm_set_config (or \ref pio_sm_init which calls it) attempts to apply the configuration to a particular PIO's state machine,
* and will return PICO_ERROR_BAD_ALIGNMENT if the configuration cannot be applied due to the above problem,
* or if the PIO's GPIO base (see \ref pio_set_gpio_base) does not allow access to the required pins.
*
* To be clear, \ref pio_sm_set_config does not change the PIO's GPIO base for you; you must configre the PIO's
* GPIO base before calling the method, however you can use \ref pio_claim_free_sm_and_add_program_for_gpio_range
* to find/configure a PIO instance suitable for a partiular GPIO range.
*
* You can set `PARAM_ASSERTIONS_ENABLED_HARDWARE_PIO = 1` to enable parameter checking to debug pin (or other) issues with
* hardware_pio methods.
* \endif
*/
/** \brief PIO Configuration structure
@ -228,9 +284,10 @@ typedef struct {
#if PICO_PIO_USE_GPIO_BASE
#define PINHI_ALL_PINCTRL_LSBS ((1u << PIO_SM0_PINCTRL_IN_BASE_LSB) | (1u << PIO_SM0_PINCTRL_OUT_BASE_LSB) | \
(1u << PIO_SM0_PINCTRL_SET_BASE_LSB) | (1u << PIO_SM0_PINCTRL_SIDESET_BASE_LSB))
static_assert( 0 == (0xff000000u & (PINHI_ALL_PINCTRL_LSBS * 0x1f)), "");
// note we put the jmp_ctrl pin starting at bit 24
#define PINHI_ALL_PIN_LSBS ((1u << 24) | (1u << PIO_SM0_PINCTRL_IN_BASE_LSB) | (1u << PIO_SM0_PINCTRL_OUT_BASE_LSB) | \
// note we put the out_special pin starting at bit 20
#define PINHI_EXECCTRL_LSB 20
static_assert( (1u << PINHI_EXECCTRL_LSB) > (PINHI_ALL_PINCTRL_LSBS * 0x1f), "");
#define PINHI_ALL_PIN_LSBS ((1u << PINHI_EXECCTRL_LSB) |(1u << PIO_SM0_PINCTRL_IN_BASE_LSB) | (1u << PIO_SM0_PINCTRL_OUT_BASE_LSB) | \
(1u << PIO_SM0_PINCTRL_SET_BASE_LSB) | (1u << PIO_SM0_PINCTRL_SIDESET_BASE_LSB))
// each 5-bit field which would usually be used for the pin_base in pin_ctrl, is used for:
// 0b11111 - corresponding field not specified
@ -272,7 +329,7 @@ static inline void check_pio_pin_param(__unused uint pin) {
* 'out' pins can overlap with the 'in', 'set' and 'sideset' pins
*
* \param c Pointer to the configuration structure to modify
* \param out_base 0-31 First pin to set as output
* \param out_base First pin to set as output. See \ref sm_config_pins "sm_config_ pins" for more detail on pin arguments
*/
static inline void sm_config_set_out_pin_base(pio_sm_config *c, uint out_base) {
check_pio_pin_param(out_base);
@ -304,7 +361,7 @@ static inline void sm_config_set_out_pin_count(pio_sm_config *c, uint out_count)
* 'out' pins can overlap with the 'in', 'set' and 'sideset' pins
*
* \param c Pointer to the configuration structure to modify
* \param out_base 0-31 First pin to set as output
* \param out_base First pin to set as output. See \ref sm_config_pins "sm_config_ pins" for more detail on pin arguments
* \param out_count 0-32 Number of pins to set.
*/
static inline void sm_config_set_out_pins(pio_sm_config *c, uint out_base, uint out_count) {
@ -318,7 +375,7 @@ static inline void sm_config_set_out_pins(pio_sm_config *c, uint out_base, uint
* 'set' pins can overlap with the 'in', 'out' and 'sideset' pins
*
* \param c Pointer to the configuration structure to modify
* \param set_base 0-31 First pin to set as
* \param set_base First pin to use as 'set'. See \ref sm_config_pins "sm_config_ pins" for more detail on pin arguments
*/
static inline void sm_config_set_set_pin_base(pio_sm_config *c, uint set_base) {
check_pio_pin_param(set_base);
@ -350,7 +407,7 @@ static inline void sm_config_set_set_pin_count(pio_sm_config *c, uint set_count)
* 'set' pins can overlap with the 'in', 'out' and 'sideset' pins
*
* \param c Pointer to the configuration structure to modify
* \param set_base 0-31 First pin to set as
* \param set_base First pin to use as 'set'. See \ref sm_config_pins "sm_config_ pins" for more detail on pin arguments
* \param set_count 0-5 Number of pins to set.
*/
static inline void sm_config_set_set_pins(pio_sm_config *c, uint set_base, uint set_count) {
@ -364,7 +421,7 @@ static inline void sm_config_set_set_pins(pio_sm_config *c, uint set_base, uint
* 'in' pins can overlap with the 'out', 'set' and 'sideset' pins
*
* \param c Pointer to the configuration structure to modify
* \param in_base 0-31 First pin to use as input
* \param in_base First pin to use as input. See \ref sm_config_pins "sm_config_ pins" for more detail on pin arguments
*/
static inline void sm_config_set_in_pin_base(pio_sm_config *c, uint in_base) {
check_pio_pin_param(in_base);
@ -382,7 +439,7 @@ static inline void sm_config_set_in_pin_base(pio_sm_config *c, uint in_base) {
* 'in' pins can overlap with the 'out', 'set' and 'sideset' pins
*
* \param c Pointer to the configuration structure to modify
* \param in_base 0-31 First pin to use as input
* \param in_base First pin to use as input. See \ref sm_config_pins "sm_config_ pins" for more detail on pin arguments
*/
static inline void sm_config_set_in_pins(pio_sm_config *c, uint in_base) {
sm_config_set_in_pin_base(c, in_base);
@ -419,7 +476,7 @@ static inline void sm_config_set_in_pin_count(pio_sm_config *c, uint in_count) {
* 'sideset' pins can overlap with the 'in', 'out' and 'set' pins
*
* \param c Pointer to the configuration structure to modify
* \param sideset_base 0-31 base pin for 'side set'
* \param sideset_base First pin to use for 'side set'. See \ref sm_config_pins "sm_config_ pins" for more detail on pin arguments
*/
static inline void sm_config_set_sideset_pin_base(pio_sm_config *c, uint sideset_base) {
check_pio_pin_param(sideset_base);
@ -440,7 +497,7 @@ static inline void sm_config_set_sideset_pin_base(pio_sm_config *c, uint sideset
* 'sideset' pins can overlap with the 'in', 'out' and 'set' pins
*
* \param c Pointer to the configuration structure to modify
* \param sideset_base 0-31 base pin for 'side set'
* \param sideset_base First pin to use for 'side set'. See \ref sm_config_pins "sm_config_ pins" for more detail on pin arguments
*/
static inline void sm_config_set_sideset_pins(pio_sm_config *c, uint sideset_base) {
sm_config_set_sideset_pin_base(c, sideset_base);
@ -558,15 +615,15 @@ static inline void sm_config_set_wrap(pio_sm_config *c, uint wrap_target, uint w
* \ingroup sm_config
*
* \param c Pointer to the configuration structure to modify
* \param pin The raw GPIO pin number to use as the source for a `jmp pin` instruction
* \param pin The raw GPIO pin number to use as the source for a `jmp pin` instruction. See \ref sm_config_pins "sm_config_ pins" for more detail on pin arguments
*/
static inline void sm_config_set_jmp_pin(pio_sm_config *c, uint pin) {
check_pio_pin_param(pin);
c->execctrl = (c->execctrl & ~PIO_SM0_EXECCTRL_JMP_PIN_BITS) |
((pin & 31) << PIO_SM0_EXECCTRL_JMP_PIN_LSB);
#if PICO_PIO_USE_GPIO_BASE
c->pinhi = (c->pinhi & ~(31u << 24)) |
((pin >> 4) << 24);
c->pinhi = (c->pinhi & ~(31u << 20)) |
((pin >> 4) << 20);
#endif
}
@ -637,15 +694,15 @@ static inline void sm_config_set_fifo_join(pio_sm_config *c, enum pio_fifo_join
* \param c Pointer to the configuration structure to modify
* \param sticky to enable 'sticky' output (i.e. re-asserting most recent OUT/SET pin values on subsequent cycles)
* \param has_enable_pin true to enable auxiliary OUT enable pin
* \param enable_pin_index pin index for auxiliary OUT enable
*/
static inline void sm_config_set_out_special(pio_sm_config *c, bool sticky, bool has_enable_pin, uint enable_pin_index) {
* \param enable_bit_index Data bit index for auxiliary OUT enable.
*/
static inline void sm_config_set_out_special(pio_sm_config *c, bool sticky, bool has_enable_pin, uint enable_bit_index) {
c->execctrl = (c->execctrl &
(uint)~(PIO_SM0_EXECCTRL_OUT_STICKY_BITS | PIO_SM0_EXECCTRL_INLINE_OUT_EN_BITS |
PIO_SM0_EXECCTRL_OUT_EN_SEL_BITS)) |
(bool_to_bit(sticky) << PIO_SM0_EXECCTRL_OUT_STICKY_LSB) |
(bool_to_bit(has_enable_pin) << PIO_SM0_EXECCTRL_INLINE_OUT_EN_LSB) |
((enable_pin_index << PIO_SM0_EXECCTRL_OUT_EN_SEL_LSB) & PIO_SM0_EXECCTRL_OUT_EN_SEL_BITS);
((enable_bit_index << PIO_SM0_EXECCTRL_OUT_EN_SEL_LSB) & PIO_SM0_EXECCTRL_OUT_EN_SEL_BITS);
}
/*! \brief Set source for 'mov status' in a state machine configuration
@ -718,7 +775,7 @@ static inline uint pio_get_gpio_base(PIO pio) {
#endif
}
static inline void check_pio_pin_mask64(__unused PIO pio, __unused uint64_t pinmask) {
static inline void check_pio_pin_mask64(__unused PIO pio, __unused uint sm, __unused uint64_t pinmask) {
// check no pins are set in the mask which are incompatible with the pio
#if PICO_PIO_USE_GPIO_BASE
valid_params_if(HARDWARE_PIO, (pinmask & ~(0xffffffffull << pio_get_gpio_base(pio))) == 0);
@ -730,6 +787,9 @@ static inline void check_pio_pin_mask64(__unused PIO pio, __unused uint64_t pinm
/*! \brief Apply a state machine configuration to a state machine
* \ingroup hardware_pio
*
* \if rp2350_specific
* See \ref sm_config_pins "sm_config_ pins" for more detail on why this method might fail on RP2350B
* \endif
* \param pio Handle to PIO instance; e.g. \ref pio0 or \ref pio1
* \param sm State machine index (0..3)
* \param config the configuration to apply
@ -739,7 +799,6 @@ static inline int pio_sm_set_config(PIO pio, uint sm, const pio_sm_config *confi
check_pio_param(pio);
check_sm_param(sm);
pio->sm[sm].clkdiv = config->clkdiv;
pio->sm[sm].execctrl = config->execctrl;
pio->sm[sm].shiftctrl = config->shiftctrl;
#if PICO_PIO_USE_GPIO_BASE
uint used = (~config->pinhi >> 4) & PINHI_ALL_PIN_LSBS;
@ -750,11 +809,14 @@ static inline int pio_sm_set_config(PIO pio, uint sm, const pio_sm_config *confi
uint gpio_base = pio_get_gpio_base(pio);
invalid_params_if_and_return(PIO, gpio_under_16 && gpio_base, PICO_ERROR_BAD_ALIGNMENT);
invalid_params_if_and_return(PIO, gpio_over_32 && !gpio_base, PICO_ERROR_BAD_ALIGNMENT);
// flip the top bit of any used (pinctrl) values to turn:
// flip the top bit of any used (execctrl/pinctrl) values to turn:
// bit6(32) + 0-15 -> base(16) + 16-31
// bit6(0) + 16-31 -> base(16) + 0-15
static_assert(PINHI_EXECCTRL_LSB == 20, ""); // we use shifts to mask off bits below
pio->sm[sm].execctrl = config->execctrl ^ (gpio_base ? ((used >> 20) << (PIO_SM0_EXECCTRL_JMP_PIN_LSB + 4)) : 0);
pio->sm[sm].pinctrl = config->pinctrl ^ (gpio_base ? ((used << 12) >> 8) : 0);
#else
pio->sm[sm].execctrl = config->execctrl;
pio->sm[sm].pinctrl = config->pinctrl;
#endif
return PICO_OK;
@ -842,6 +904,9 @@ typedef struct pio_program {
* instance must specify a base GPIO where the instance's "pin 0" maps. For RP2350 the valid
* values are 0 and 16, indicating the PIO instance has access to pins 0-31, or 16-47 respectively.
*
* NOTE: This method simply changes the underlying PIO register, it does not detect or attempt
* to prevent any side effects this change will have on in use state machines on this PIO.
*
* \param pio The PIO instance; e.g. \ref pio0 or \ref pio1
* \param gpio_base the GPIO base (either 0 or 16)
* \return PICO_OK (0) on success, error code otherwise
@ -853,7 +918,8 @@ int pio_set_gpio_base(PIO pio, uint gpio_base);
*
* \param pio The PIO instance; e.g. \ref pio0 or \ref pio1
* \param program the program definition
* \return true if the program can be loaded; false if there is not suitable space in the instruction memory
* \return true if the program can be loaded;
* false if not, e.g. if there is not suitable space in the instruction memory
*/
bool pio_can_add_program(PIO pio, const pio_program_t *program);
@ -863,7 +929,8 @@ bool pio_can_add_program(PIO pio, const pio_program_t *program);
* \param pio The PIO instance; e.g. \ref pio0 or \ref pio1
* \param program the program definition
* \param offset the instruction memory offset wanted for the start of the program
* \return true if the program can be loaded at that location; false if there is not space in the instruction memory
* \return true if the program can be loaded at that location;
* false if not, e.g. if there is not space in the instruction memory
*/
bool pio_can_add_program_at_offset(PIO pio, const pio_program_t *program, uint offset);
@ -920,6 +987,10 @@ void pio_clear_instruction_memory(PIO pio);
*
* The state machine is left disabled on return from this call.
*
* * \if rp2350_specific
* See \ref sm_config_pins "sm_config_ pins" for more detail on why this method might fail on RP2350B
* \endif
*
* \param pio The PIO instance; e.g. \ref pio0 or \ref pio1
* \param sm State machine index (0..3)
* \param initial_pc the initial program memory offset to run from
@ -1409,7 +1480,7 @@ static inline void pio_sm_set_wrap(PIO pio, uint sm, uint wrap_target, uint wrap
*
* \param pio The PIO instance; e.g. \ref pio0 or \ref pio1
* \param sm State machine index (0..3)
* \param out_base 0-31 First pin to set as output
* \param out_base First pin to set as output. See \ref pio_sm_pins "pio_sm_ pins" for more detail on pin arguments
* \param out_count 0-32 Number of pins to set.
*/
static inline void pio_sm_set_out_pins(PIO pio, uint sm, uint out_base, uint out_count) {
@ -1433,7 +1504,7 @@ static inline void pio_sm_set_out_pins(PIO pio, uint sm, uint out_base, uint out
*
* \param pio The PIO instance; e.g. \ref pio0 or \ref pio1
* \param sm State machine index (0..3)
* \param set_base 0-31 First pin to set as
* \param set_base First pin to set as 'set'. See \ref pio_sm_pins "pio_sm_ pins" for more detail on pin arguments
* \param set_count 0-5 Number of pins to set.
*/
static inline void pio_sm_set_set_pins(PIO pio, uint sm, uint set_base, uint set_count) {
@ -1456,7 +1527,7 @@ static inline void pio_sm_set_set_pins(PIO pio, uint sm, uint set_base, uint set
*
* \param pio The PIO instance; e.g. \ref pio0 or \ref pio1
* \param sm State machine index (0..3)
* \param in_base 0-31 First pin to use as input
* \param in_base First pin to use as input. See \ref pio_sm_pins "pio_sm_ pins" for more detail on pin arguments
*/
static inline void pio_sm_set_in_pins(PIO pio, uint sm, uint in_base) {
check_pio_param(pio);
@ -1476,7 +1547,7 @@ static inline void pio_sm_set_in_pins(PIO pio, uint sm, uint in_base) {
*
* \param pio The PIO instance; e.g. \ref pio0 or \ref pio1
* \param sm State machine index (0..3)
* \param sideset_base 0-31 base pin for 'side set'
* \param sideset_base Base pin for 'side set'. See \ref pio_sm_pins "pio_sm_ pins" for more detail on pin arguments
*/
static inline void pio_sm_set_sideset_pins(PIO pio, uint sm, uint sideset_base) {
check_pio_param(pio);
@ -1494,7 +1565,7 @@ static inline void pio_sm_set_sideset_pins(PIO pio, uint sm, uint sideset_base)
*
* \param pio The PIO instance; e.g. \ref pio0 or \ref pio1
* \param sm State machine index (0..3)
* \param pin The raw GPIO pin number to use as the source for a `jmp pin` instruction
* \param pin The pin number to use as the source for a `jmp pin` instruction. See \ref pio_sm_pins "pio_sm_ pins" for more detail on pin arguments
*/
static inline void pio_sm_set_jmp_pin(PIO pio, uint sm, uint pin) {
@ -1740,7 +1811,7 @@ static inline void pio_sm_clear_fifos(PIO pio, uint sm) {
*
* \param pio The PIO instance; e.g. \ref pio0 or \ref pio1
* \param sm State machine index (0..3) to use
* \param pin_values the pin values to set
* \param pin_values the pin values to set. See \ref pio_sm_pins "pio_sm_ pins" for more detail on pin arguments
*/
void pio_sm_set_pins(PIO pio, uint sm, uint32_t pin_values);
@ -1754,7 +1825,7 @@ void pio_sm_set_pins(PIO pio, uint sm, uint32_t pin_values);
*
* \param pio The PIO instance; e.g. \ref pio0 or \ref pio1
* \param sm State machine index (0..3) to use
* \param pin_values the pin values to set
* \param pin_values the pin values to set. See \ref pio_sm_pins "pio_sm_ pins" for more detail on pin arguments
*/
void pio_sm_set_pins64(PIO pio, uint sm, uint64_t pin_values);
@ -1770,7 +1841,7 @@ void pio_sm_set_pins64(PIO pio, uint sm, uint64_t pin_values);
* \param pio The PIO instance; e.g. \ref pio0 or \ref pio1
* \param sm State machine index (0..3) to use
* \param pin_values the pin values to set (if the corresponding bit in pin_mask is set)
* \param pin_mask a bit for each pin to indicate whether the corresponding pin_value for that pin should be applied.
* \param pin_mask a bit for each pin to indicate whether the corresponding pin_value for that pin should be applied. See \ref pio_sm_pins "pio_sm_ pins" for more detail on pin arguments
*/
void pio_sm_set_pins_with_mask(PIO pio, uint sm, uint32_t pin_values, uint32_t pin_mask);
@ -1785,7 +1856,7 @@ void pio_sm_set_pins_with_mask(PIO pio, uint sm, uint32_t pin_values, uint32_t p
* \param pio The PIO instance; e.g. \ref pio0 or \ref pio1
* \param sm State machine index (0..3) to use
* \param pin_values the pin values to set (if the corresponding bit in pin_mask is set)
* \param pin_mask a bit for each pin to indicate whether the corresponding pin_value for that pin should be applied.
* \param pin_mask a bit for each pin to indicate whether the corresponding pin_value for that pin should be applied. See \ref pio_sm_pins "pio_sm_ pins" for more detail on pin arguments
*/
void pio_sm_set_pins_with_mask64(PIO pio, uint sm, uint64_t pin_values, uint64_t pin_mask);
@ -1830,7 +1901,7 @@ void pio_sm_set_pindirs_with_mask64(PIO pio, uint sm, uint64_t pin_dirs, uint64_
*
* \param pio The PIO instance; e.g. \ref pio0 or \ref pio1
* \param sm State machine index (0..3) to use
* \param pins_base the first pin to set a direction for
* \param pins_base the first pin to set a direction for. See \ref pio_sm_pins "pio_sm_ pins" for more detail on pin arguments
* \param pin_count the count of consecutive pins to set the direction for
* \param is_out the direction to set; true = out, false = in
* \return PICO_OK (0) on success, error code otherwise
@ -1918,7 +1989,7 @@ bool pio_claim_free_sm_and_add_program(const pio_program_t *program, PIO *pio, u
* \param pio Returns the PIO hardware instance or NULL if no PIO is available
* \param sm Returns the index of the PIO state machine that was claimed
* \param offset Returns the instruction memory offset of the start of the program
* \param gpio_base the lowest GPIO number required
* \param gpio_base the lowest GPIO number required (0-47 on RP2350B, 0-31 otherwise)
* \param gpio_count the count of GPIOs required
* \param set_gpio_base if there is no free SM on a PIO instance with the right GPIO base, and there IS an unused PIO
* instance, then that PIO will be reconfigured so that this method can succeed

View File

@ -205,22 +205,22 @@ void pio_clear_instruction_memory(PIO pio) {
hw_claim_unlock(save);
}
void pio_sm_set_pins(PIO pio, uint sm, uint32_t pins) {
pio_sm_set_pins64(pio, sm, pins);
}
#if !PICO_PIO_USE_GPIO_BASE
// the 32 pin APIs are the same as the internal method, so collapse them
#define pio_sm_set_pins_internal pio_sm_set_pins
#define pio_sm_set_pins_with_mask_internal pio_sm_set_pins_with_mask
#define pio_sm_set_pindirs_with_mask_internal pio_sm_set_pindirs_with_mask
#endif
// Set the value of all PIO pins. This is done by forcibly executing
// instructions on a "victim" state machine, sm. Ideally you should choose one
// which is not currently running a program. This is intended for one-time
// setup of initial pin states.
void pio_sm_set_pins64(PIO pio, uint sm, uint64_t pins) {
//
// note pin mask bit 0 is relative to current GPIO_BASE
void pio_sm_set_pins_internal(PIO pio, uint sm, uint32_t pins) {
check_pio_param(pio);
check_sm_param(sm);
check_pio_pin_mask64(pio, pins);
#if PICO_PIO_USE_GPIO_BASE
pins >>= pio_get_gpio_base(pio);
#endif
uint32_t pinctrl_saved = pio->sm[sm].pinctrl;
uint32_t execctrl_saved = pio->sm[sm].execctrl;
hw_clear_bits(&pio->sm[sm].execctrl, 1u << PIO_SM0_EXECCTRL_OUT_STICKY_LSB);
@ -240,18 +240,27 @@ void pio_sm_set_pins64(PIO pio, uint sm, uint64_t pins) {
pio->sm[sm].execctrl = execctrl_saved;
}
void pio_sm_set_pins_with_mask(PIO pio, uint sm, uint32_t pinvals, uint32_t pin_mask) {
pio_sm_set_pins_with_mask64(pio, sm, pinvals, pin_mask);
#ifndef pio_sm_set_pins_internal
void pio_sm_set_pins(PIO pio, uint sm, uint32_t pins) {
#if PICO_PIO_USE_GPIO_BASE
pins >>= pio_get_gpio_base(pio);
#endif
pio_sm_set_pins_internal(pio, sm, pins);
}
#endif
void pio_sm_set_pins64(PIO pio, uint sm, uint64_t pins) {
check_pio_pin_mask64(pio, sm, pins);
#if PICO_PIO_USE_GPIO_BASE
pins >>= pio_get_gpio_base(pio);
#endif
pio_sm_set_pins_internal(pio, sm, (uint32_t)pins);
}
void pio_sm_set_pins_with_mask64(PIO pio, uint sm, uint64_t pinvals, uint64_t pin_mask) {
// note pin values/mask bit 0 is relative to current GPIO_BASE
void pio_sm_set_pins_with_mask_internal(PIO pio, uint sm, uint32_t pin_values, uint32_t pin_mask) {
check_pio_param(pio);
check_sm_param(sm);
check_pio_pin_mask64(pio, pin_mask);
#if PICO_PIO_USE_GPIO_BASE
pinvals >>= pio_get_gpio_base(pio);
pin_mask >>= pio_get_gpio_base(pio);
#endif
uint32_t pinctrl_saved = pio->sm[sm].pinctrl;
uint32_t execctrl_saved = pio->sm[sm].execctrl;
hw_clear_bits(&pio->sm[sm].execctrl, 1u << PIO_SM0_EXECCTRL_OUT_STICKY_LSB);
@ -260,25 +269,35 @@ void pio_sm_set_pins_with_mask64(PIO pio, uint sm, uint64_t pinvals, uint64_t pi
pio->sm[sm].pinctrl =
(1u << PIO_SM0_PINCTRL_SET_COUNT_LSB) |
(base << PIO_SM0_PINCTRL_SET_BASE_LSB);
pio_sm_exec(pio, sm, pio_encode_set(pio_pins, (pinvals >> base) & 0x1u));
pio_sm_exec(pio, sm, pio_encode_set(pio_pins, (pin_values >> base) & 0x1u));
pin_mask &= pin_mask - 1;
}
pio->sm[sm].pinctrl = pinctrl_saved;
pio->sm[sm].execctrl = execctrl_saved;
}
void pio_sm_set_pindirs_with_mask(PIO pio, uint sm, uint32_t pindirs, uint32_t pin_mask) {
pio_sm_set_pindirs_with_mask64(pio, sm, pindirs, pin_mask);
}
void pio_sm_set_pindirs_with_mask64(PIO pio, uint sm, uint64_t pindirs, uint64_t pin_mask) {
check_pio_param(pio);
check_sm_param(sm);
check_pio_pin_mask64(pio, pin_mask);
#ifndef pio_sm_set_pins_with_mask_internal
void pio_sm_set_pins_with_mask(PIO pio, uint sm, uint32_t pin_values, uint32_t pin_mask) {
#if PICO_PIO_USE_GPIO_BASE
pindirs >>= pio_get_gpio_base(pio);
pin_values >>= pio_get_gpio_base(pio);
pin_mask >>= pio_get_gpio_base(pio);
#endif
pio_sm_set_pins_with_mask_internal(pio, sm, pin_values, pin_mask);
}
#endif
void pio_sm_set_pins_with_mask64(PIO pio, uint sm, uint64_t pin_values, uint64_t pin_mask) {
check_pio_pin_mask64(pio, sm, pin_mask);
#if PICO_PIO_USE_GPIO_BASE
pin_values >>= pio_get_gpio_base(pio);
pin_mask >>= pio_get_gpio_base(pio);
#endif
pio_sm_set_pins_with_mask_internal(pio, sm, pin_values, pin_mask);
}
void pio_sm_set_pindirs_with_mask_internal(PIO pio, uint sm, uint32_t pindirs, uint32_t pin_mask) {
check_pio_param(pio);
check_sm_param(sm);
uint32_t pinctrl_saved = pio->sm[sm].pinctrl;
uint32_t execctrl_saved = pio->sm[sm].execctrl;
hw_clear_bits(&pio->sm[sm].execctrl, 1u << PIO_SM0_EXECCTRL_OUT_STICKY_LSB);
@ -294,6 +313,24 @@ void pio_sm_set_pindirs_with_mask64(PIO pio, uint sm, uint64_t pindirs, uint64_t
pio->sm[sm].execctrl = execctrl_saved;
}
#ifndef pio_sm_set_pindirs_with_mask_internal
void pio_sm_set_pindirs_with_mask(PIO pio, uint sm, uint32_t pindirs, uint32_t pin_mask) {
#if PICO_PIO_USE_GPIO_BASE
pindirs >>= pio_get_gpio_base(pio);
pin_mask >>= pio_get_gpio_base(pio);
#endif
pio_sm_set_pindirs_with_mask_internal(pio, sm, pindirs, pin_mask);
}
#endif
void pio_sm_set_pindirs_with_mask64(PIO pio, uint sm, uint64_t pindirs, uint64_t pin_mask) {
#if PICO_PIO_USE_GPIO_BASE
pindirs >>= pio_get_gpio_base(pio);
pin_mask >>= pio_get_gpio_base(pio);
#endif
pio_sm_set_pindirs_with_mask_internal(pio, sm, (uint32_t)pindirs, (uint32_t)pin_mask);
}
int pio_sm_set_consecutive_pindirs(PIO pio, uint sm, uint pin, uint count, bool is_out) {
check_pio_param(pio);
check_sm_param(sm);