Add some missing pio functions (#2074)

Adds some 64 versions to work with rp2350b and more than 32 pins.
Change cyw43 code to use the new function.

Fixes #1834
This commit is contained in:
Peter Harper 2024-11-20 22:38:05 +00:00 committed by GitHub
parent 46283dd00f
commit 54d4f3a8f7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 88 additions and 9 deletions

View file

@ -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
*
@ -1717,6 +1726,7 @@ 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
@ -1724,6 +1734,36 @@ static inline void pio_sm_clear_fifos(PIO pio, uint sm) {
*/
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
* \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_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
*
@ -1737,7 +1777,23 @@ void pio_sm_set_pins(PIO pio, uint sm, uint32_t pin_values);
* \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_mask(PIO pio, uint sm, uint32_t pin_values, uint32_t pin_mask);
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
* \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_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
@ -1752,7 +1808,7 @@ void pio_sm_set_pins_with_mask(PIO pio, uint sm, uint32_t pin_values, uint32_t p
* \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_mask(PIO pio, uint sm, uint32_t pin_dirs, uint32_t pin_mask);
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

View file

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

View file

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