From 5715e241837445334c9ee021e25889bc36d349bf Mon Sep 17 00:00:00 2001 From: Peter Harper Date: Thu, 15 Aug 2024 16:08:53 +0100 Subject: [PATCH] Support dynamic configuration of cyw43 gpio pins Add CYW43_PIN_WL_DYNAMIC that means cyw43 gpio pins can be changed at runtime. Then CYW43_PIN_WL_* calls cyw43_get_pin_wl to get the gpio out of the array. cyw43_set_pins_wl can be used to change the cyw43 gpio pins although care is needed when calling this? --- .../pico_cyw43_driver/cyw43_bus_pio_spi.c | 49 +++++++++++++++++++ .../include/cyw43_configport.h | 27 ++++++++++ .../include/pico/cyw43_driver.h | 19 +++++++ 3 files changed, 95 insertions(+) diff --git a/src/rp2_common/pico_cyw43_driver/cyw43_bus_pio_spi.c b/src/rp2_common/pico_cyw43_driver/cyw43_bus_pio_spi.c index e451b210e..bbf03d6ea 100644 --- a/src/rp2_common/pico_cyw43_driver/cyw43_bus_pio_spi.c +++ b/src/rp2_common/pico_cyw43_driver/cyw43_bus_pio_spi.c @@ -24,9 +24,11 @@ #define IRQ_SAMPLE_DELAY_NS 100 +#if !CYW43_PIN_WL_DYNAMIC // The pins should all work in the same gpio base static_assert((CYW43_PIN_WL_DATA_OUT < 32 && CYW43_PIN_WL_DATA_IN < 32 && CYW43_PIN_WL_CLOCK < 32) || (CYW43_PIN_WL_DATA_OUT >= 16 && CYW43_PIN_WL_DATA_IN >= 16 && CYW43_PIN_WL_CLOCK >= 16), ""); +#endif #ifdef CYW43_SPI_PROGRAM_NAME #define SPI_PROGRAM_NAME CYW43_SPI_PROGRAM_NAME @@ -540,3 +542,50 @@ int cyw43_write_bytes(cyw43_int_t *self, uint32_t fn, uint32_t addr, size_t len, } } #endif + +#if CYW43_PIN_WL_DYNAMIC + +// storage for cyw43 pins +static uint cyw43_pin_array[CYW43_PIN_INDEX_WL_COUNT] = { + CYW43_DEFAULT_PIN_WL_REG_ON, + CYW43_DEFAULT_PIN_WL_DATA_OUT, + CYW43_DEFAULT_PIN_WL_DATA_IN, + CYW43_DEFAULT_PIN_WL_HOST_WAKE, + CYW43_DEFAULT_PIN_WL_CLOCK, + CYW43_DEFAULT_PIN_WL_CS +}; + +// Check the cyw43 gpio pin array is valid +static bool cyw43_pins_valid(uint pins[CYW43_PIN_INDEX_WL_COUNT]) { + // check the gpios are valid + for(int i = 0; i < CYW43_PIN_INDEX_WL_COUNT; i++) { + if (pins[i] >= NUM_BANK0_GPIOS) { + return false; + } + } + // These pins should use the same gpio base + return (pins[CYW43_PIN_INDEX_WL_DATA_OUT] < 32 && pins[CYW43_PIN_INDEX_WL_DATA_IN] < 32 && pins[CYW43_PIN_INDEX_WL_CLOCK] < 32) || + (pins[CYW43_PIN_INDEX_WL_DATA_OUT] >= 16 && pins[CYW43_PIN_INDEX_WL_DATA_IN] >= 16 && pins[CYW43_PIN_INDEX_WL_CLOCK] >= 16); +} + +// Set the gpio pin array +int cyw43_set_pins_wl(uint pins[CYW43_PIN_INDEX_WL_COUNT]) { + assert(!bus_data_instance.pio); + if (bus_data_instance.pio) { + return PICO_ERROR_RESOURCE_IN_USE; + } + assert(cyw43_pins_valid(pins)); + if (!cyw43_pins_valid(pins)) { + return PICO_ERROR_INVALID_ARG; + } + memcpy(cyw43_pin_array, pins, sizeof(cyw43_pin_array)); + return PICO_OK; +} + +// Get a gpio pin +uint cyw43_get_pin_wl(cyw43_pin_index_t pin_id) { + assert(pin_id < CYW43_PIN_INDEX_WL_COUNT); + assert(cyw43_pin_array[pin_id] < NUM_BANK0_GPIOS); + return cyw43_pin_array[pin_id]; +} +#endif // CYW43_PIN_WL_DYNAMIC \ No newline at end of file diff --git a/src/rp2_common/pico_cyw43_driver/include/cyw43_configport.h b/src/rp2_common/pico_cyw43_driver/include/cyw43_configport.h index 2d39caf4a..110678b19 100644 --- a/src/rp2_common/pico_cyw43_driver/include/cyw43_configport.h +++ b/src/rp2_common/pico_cyw43_driver/include/cyw43_configport.h @@ -120,12 +120,39 @@ static inline uint32_t cyw43_hal_ticks_ms(void) { #define CYW43_DEFAULT_PIN_WL_CS 25u #endif +// PICO_CONFIG: CYW43_PIN_WL_DYNAMIC, flag to indicate if cyw43 SPI pins can be changed at runtime, type=bool, default=false, advanced=true, group=pico_cyw43_driver +#ifndef CYW43_PIN_WL_DYNAMIC +#define CYW43_PIN_WL_DYNAMIC 0 +#endif + +#if CYW43_PIN_WL_DYNAMIC +// these are just an index into an array +typedef enum cyw43_pin_index_t { + CYW43_PIN_INDEX_WL_REG_ON, + CYW43_PIN_INDEX_WL_DATA_OUT, + CYW43_PIN_INDEX_WL_DATA_IN, + CYW43_PIN_INDEX_WL_HOST_WAKE, + CYW43_PIN_INDEX_WL_CLOCK, + CYW43_PIN_INDEX_WL_CS, + CYW43_PIN_INDEX_WL_COUNT // last +} cyw43_pin_index_t; +#define CYW43_PIN_WL_REG_ON cyw43_get_pin_wl(CYW43_PIN_INDEX_WL_REG_ON) +#define CYW43_PIN_WL_DATA_OUT cyw43_get_pin_wl(CYW43_PIN_INDEX_WL_DATA_OUT) +#define CYW43_PIN_WL_DATA_IN cyw43_get_pin_wl(CYW43_PIN_INDEX_WL_DATA_IN) +#define CYW43_PIN_WL_HOST_WAKE cyw43_get_pin_wl(CYW43_PIN_INDEX_WL_HOST_WAKE) +#define CYW43_PIN_WL_CLOCK cyw43_get_pin_wl(CYW43_PIN_INDEX_WL_CLOCK) +#define CYW43_PIN_WL_CS cyw43_get_pin_wl(CYW43_PIN_INDEX_WL_CS) +// Lookup the gpio value in an array +uint cyw43_get_pin_wl(cyw43_pin_index_t pin_id); +#else +// Just return the gpio number configured at build time #define CYW43_PIN_WL_REG_ON CYW43_DEFAULT_PIN_WL_REG_ON #define CYW43_PIN_WL_DATA_OUT CYW43_DEFAULT_PIN_WL_DATA_OUT #define CYW43_PIN_WL_DATA_IN CYW43_DEFAULT_PIN_WL_DATA_IN #define CYW43_PIN_WL_HOST_WAKE CYW43_DEFAULT_PIN_WL_HOST_WAKE #define CYW43_PIN_WL_CLOCK CYW43_DEFAULT_PIN_WL_CLOCK #define CYW43_PIN_WL_CS CYW43_DEFAULT_PIN_WL_CS +#endif // !CYW43_PIN_WL_DYNAMIC static inline int cyw43_hal_pin_read(cyw43_hal_pin_obj_t pin) { return gpio_get(pin); diff --git a/src/rp2_common/pico_cyw43_driver/include/pico/cyw43_driver.h b/src/rp2_common/pico_cyw43_driver/include/pico/cyw43_driver.h index 6de110b5b..633c7ad1f 100644 --- a/src/rp2_common/pico_cyw43_driver/include/pico/cyw43_driver.h +++ b/src/rp2_common/pico_cyw43_driver/include/pico/cyw43_driver.h @@ -16,6 +16,10 @@ #include "pico.h" +#if CYW43_PIN_WL_DYNAMIC +#include "cyw43_configport.h" +#endif + #ifdef __cplusplus extern "C" { #endif @@ -73,6 +77,21 @@ void cyw43_driver_deinit(struct async_context *context); void cyw43_set_pio_clock_divisor(uint16_t clock_div_int, uint8_t clock_div_frac); #endif +#if CYW43_PIN_WL_DYNAMIC +/*! \brief Set the gpio pins for the communication with the cyw43 device + * \ingroup pico_cyw43_driver + * + * Set or change the pins used to communicate with the cyw43 device + * This function is only available if \ref CYW43_PIN_WL_DYNAMIC is true + * + * \note The cyw43 driver should not be de-initialised before this function is called or else the behaviour is undefined. + * + * \param pins An array containing the gpio pins to use + * \return PICO_OK if the pin configuration could be changed and is valid +*/ +int cyw43_set_pins_wl(uint pins[CYW43_PIN_INDEX_WL_COUNT]); +#endif + #ifdef __cplusplus } #endif