Skip to content

Commit

Permalink
Add some missing pio functions (#2074)
Browse files Browse the repository at this point in the history
Adds some 64 versions to work with rp2350b and more than 32 pins.
Change cyw43 code to use the new function.

Fixes #1834
  • Loading branch information
peterharperuk authored Nov 20, 2024
1 parent 46283dd commit 54d4f3a
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 7 deletions.
56 changes: 56 additions & 0 deletions src/rp2_common/hardware_pio/include/hardware/pio.h
Original file line number Diff line number Diff line change
Expand Up @@ -708,6 +708,15 @@ static inline uint pio_get_gpio_base(PIO pio) {
#endif
}

static inline void check_pio_pin_mask64(__unused PIO pio, __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);
#else
valid_params_if(HARDWARE_PIO, (pinmask & ~0xffffffffull) == 0);
#endif
}

/*! \brief Apply a state machine configuration to a state machine
* \ingroup hardware_pio
*
Expand Down Expand Up @@ -1717,20 +1726,36 @@ static inline void pio_sm_clear_fifos(PIO pio, uint sm) {
* before restoring the state machine's pin configuration to what it was.
*
* This method is provided as a convenience to set initial pin states, and should not be used against a state machine that is enabled.
* Note: This method only works for pins < 32. To use with pins >= 32 call pio_sm_set_pins64
*
* \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
*/
void pio_sm_set_pins(PIO pio, uint sm, uint32_t pin_values);

/*! \brief Use a state machine to set a value on all pins for the PIO instance
* \ingroup hardware_pio
*
* This method repeatedly reconfigures the target state machine's pin configuration and executes 'set' instructions to set values on all 32 pins,
* before restoring the state machine's pin configuration to what it was.
*
* This method is provided as a convenience to set initial pin states, and should not be used against a state machine that is enabled.
*
* \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
*/
void pio_sm_set_pins64(PIO pio, uint sm, uint64_t pin_values);

/*! \brief Use a state machine to set a value on multiple pins for the PIO instance
* \ingroup hardware_pio
*
* This method repeatedly reconfigures the target state machine's pin configuration and executes 'set' instructions to set values on up to 32 pins,
* before restoring the state machine's pin configuration to what it was.
*
* This method is provided as a convenience to set initial pin states, and should not be used against a state machine that is enabled.
* Note: This method only works for pins < 32. To use with pins >= 32 call pio_sm_set_pins_with_mask64
*
* \param pio The PIO instance; e.g. \ref pio0 or \ref pio1
* \param sm State machine index (0..3) to use
Expand All @@ -1739,13 +1764,29 @@ void pio_sm_set_pins(PIO pio, uint sm, uint32_t pin_values);
*/
void pio_sm_set_pins_with_mask(PIO pio, uint sm, uint32_t pin_values, uint32_t pin_mask);

/*! \brief Use a state machine to set a value on multiple pins for the PIO instance
* \ingroup hardware_pio
*
* This method repeatedly reconfigures the target state machine's pin configuration and executes 'set' instructions to set values on up to 32 pins,
* before restoring the state machine's pin configuration to what it was.
*
* This method is provided as a convenience to set initial pin states, and should not be used against a state machine that is enabled.
*
* \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.
*/
void pio_sm_set_pins_with_mask64(PIO pio, uint sm, uint64_t pin_values, uint64_t pin_mask);

/*! \brief Use a state machine to set the pin directions for multiple pins for the PIO instance
* \ingroup hardware_pio
*
* This method repeatedly reconfigures the target state machine's pin configuration and executes 'set' instructions to set pin directions on up to 32 pins,
* before restoring the state machine's pin configuration to what it was.
*
* This method is provided as a convenience to set initial pin directions, and should not be used against a state machine that is enabled.
* Note: This method only works for pins < 32. To use with pins >= 32 call pio_sm_set_pindirs_with_mask64
*
* \param pio The PIO instance; e.g. \ref pio0 or \ref pio1
* \param sm State machine index (0..3) to use
Expand All @@ -1754,6 +1795,21 @@ void pio_sm_set_pins_with_mask(PIO pio, uint sm, uint32_t pin_values, uint32_t p
*/
void pio_sm_set_pindirs_with_mask(PIO pio, uint sm, uint32_t pin_dirs, uint32_t pin_mask);

/*! \brief Use a state machine to set the pin directions for multiple pins for the PIO instance
* \ingroup hardware_pio
*
* This method repeatedly reconfigures the target state machine's pin configuration and executes 'set' instructions to set pin directions on up to 32 pins,
* before restoring the state machine's pin configuration to what it was.
*
* This method is provided as a convenience to set initial pin directions, and should not be used against a state machine that is enabled.
*
* \param pio The PIO instance; e.g. \ref pio0 or \ref pio1
* \param sm State machine index (0..3) to use
* \param pin_dirs the pin directions to set - 1 = out, 0 = in (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.
*/
void pio_sm_set_pindirs_with_mask64(PIO pio, uint sm, uint64_t pin_dirs, uint64_t pin_mask);

/*! \brief Use a state machine to set the same pin direction for multiple consecutive pins for the PIO instance
* \ingroup hardware_pio
*
Expand Down
29 changes: 28 additions & 1 deletion src/rp2_common/hardware_pio/pio.c
Original file line number Diff line number Diff line change
Expand Up @@ -205,13 +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);
}

// 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_pins(PIO pio, uint sm, uint32_t pins) {
void pio_sm_set_pins64(PIO pio, uint sm, uint64_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);
Expand All @@ -232,8 +241,17 @@ void pio_sm_set_pins(PIO pio, uint sm, uint32_t pins) {
}

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);
}

void pio_sm_set_pins_with_mask64(PIO pio, uint sm, uint64_t pinvals, uint64_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);
Expand All @@ -250,8 +268,17 @@ void pio_sm_set_pins_with_mask(PIO pio, uint sm, uint32_t pinvals, uint32_t pin_
}

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);
#if PICO_PIO_USE_GPIO_BASE
pindirs >>= 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);
Expand Down
8 changes: 2 additions & 6 deletions src/rp2_common/pico_cyw43_driver/cyw43_bus_pio_spi.c
Original file line number Diff line number Diff line change
Expand Up @@ -250,9 +250,7 @@ int cyw43_spi_transfer(cyw43_int_t *self, const uint8_t *tx, size_t tx_length, u
pio_sm_set_enabled(bus_data->pio, bus_data->pio_sm, false);
pio_sm_set_wrap(bus_data->pio, bus_data->pio_sm, bus_data->pio_offset, bus_data->pio_offset + SPI_OFFSET_END - 1);
pio_sm_clear_fifos(bus_data->pio, bus_data->pio_sm);
pio_sm_set_pindirs_with_mask(bus_data->pio, bus_data->pio_sm,
1u << (CYW43_PIN_WL_DATA_OUT - pio_get_gpio_base(bus_data->pio)),
1u << (CYW43_PIN_WL_DATA_OUT - pio_get_gpio_base(bus_data->pio)));
pio_sm_set_pindirs_with_mask64(bus_data->pio, bus_data->pio_sm, 1ull << CYW43_PIN_WL_DATA_OUT, 1ull << CYW43_PIN_WL_DATA_OUT);
pio_sm_restart(bus_data->pio, bus_data->pio_sm);
pio_sm_clkdiv_restart(bus_data->pio, bus_data->pio_sm);
pio_sm_put(bus_data->pio, bus_data->pio_sm, tx_length * 8 - 1);
Expand Down Expand Up @@ -294,9 +292,7 @@ int cyw43_spi_transfer(cyw43_int_t *self, const uint8_t *tx, size_t tx_length, u
pio_sm_set_enabled(bus_data->pio, bus_data->pio_sm, false);
pio_sm_set_wrap(bus_data->pio, bus_data->pio_sm, bus_data->pio_offset, bus_data->pio_offset + SPI_OFFSET_LP1_END - 1);
pio_sm_clear_fifos(bus_data->pio, bus_data->pio_sm);
pio_sm_set_pindirs_with_mask(bus_data->pio, bus_data->pio_sm,
1u << (CYW43_PIN_WL_DATA_OUT - pio_get_gpio_base(bus_data->pio)),
1u << (CYW43_PIN_WL_DATA_OUT - pio_get_gpio_base(bus_data->pio)));
pio_sm_set_pindirs_with_mask64(bus_data->pio, bus_data->pio_sm, 1ull << CYW43_PIN_WL_DATA_OUT, 1ull << CYW43_PIN_WL_DATA_OUT);
pio_sm_restart(bus_data->pio, bus_data->pio_sm);
pio_sm_clkdiv_restart(bus_data->pio, bus_data->pio_sm);
pio_sm_put(bus_data->pio, bus_data->pio_sm, tx_length * 8 - 1);
Expand Down

0 comments on commit 54d4f3a

Please sign in to comment.