Skip to content

Commit d402b7a

Browse files
Properly map IO and PAD register offsets for QSPI
In the UART bootloader example the QSPI pins are used for normal IO and a `qspi_gpio_set_function()` function is used locally to setup the pins. This function didn't take into account that the IO and PAD register banks for the QSPI IOs are not in the same order. We correct this by adding a lookup table to map between the two.
1 parent 4c3a3dc commit d402b7a

File tree

1 file changed

+28
-7
lines changed

1 file changed

+28
-7
lines changed

bootloaders/uart/uart_binary.c

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
#endif
1515

1616
// Initialize the GPIO for the LED
17-
void pico_led_init(void) {
17+
static void pico_led_init(void) {
1818
#ifdef PICO_DEFAULT_LED_PIN
1919
// A device like Pico that uses a GPIO for the LED will define PICO_DEFAULT_LED_PIN
2020
// so we can use normal GPIO functionality to turn the led on and off
@@ -24,23 +24,44 @@ void pico_led_init(void) {
2424
}
2525

2626
// Turn the LED on or off
27-
void pico_set_led(bool led_on) {
27+
static void pico_set_led(bool led_on) {
2828
#if defined(PICO_DEFAULT_LED_PIN)
2929
// Just set the GPIO on or off
3030
gpio_put(PICO_DEFAULT_LED_PIN, led_on);
3131
#endif
3232
}
3333

34+
enum qspi_gpio {
35+
// arbitrarily choose PAD register bank to set the order
36+
QSPI_GPIO_SCLK = 0,
37+
QSPI_GPIO_SD0 = 1,
38+
QSPI_GPIO_SD1 = 2,
39+
QSPI_GPIO_SD2 = 3,
40+
QSPI_GPIO_SD3 = 4,
41+
QSPI_GPIO_SS = 5,
42+
};
43+
44+
// curiously the IO and PAD register banks for the QSPI GPIOs are not in the same order
45+
// This look up table will map the PAD offset to the IO offset for the same pin
46+
static const uint QSPI_GPIO_PAD_TO_IO_OFFSET[] = {
47+
0, // SCLK
48+
2, // SD0
49+
3, // SD1
50+
4, // SD2
51+
5, // SD3
52+
1, // SS
53+
};
54+
3455
// Set function for QSPI GPIO pin
35-
void qspi_gpio_set_function(uint gpio, gpio_function_t fn) {
56+
static void qspi_gpio_set_function(enum qspi_gpio gpio, gpio_function_t fn) {
3657
// Set input enable on, output disable off
3758
hw_write_masked(&pads_qspi_hw->io[gpio],
3859
PADS_QSPI_GPIO_QSPI_SD2_IE_BITS,
3960
PADS_QSPI_GPIO_QSPI_SD2_IE_BITS | PADS_QSPI_GPIO_QSPI_SD2_OD_BITS
4061
);
4162
// Zero all fields apart from fsel; we want this IO to do what the peripheral tells it.
4263
// This doesn't affect e.g. pullup/pulldown, as these are in pad controls.
43-
io_qspi_hw->io[gpio].ctrl = fn << IO_QSPI_GPIO_QSPI_SD2_CTRL_FUNCSEL_LSB;
64+
io_qspi_hw->io[QSPI_GPIO_PAD_TO_IO_OFFSET[gpio]].ctrl = fn << IO_QSPI_GPIO_QSPI_SD2_CTRL_FUNCSEL_LSB;
4465

4566
// Remove pad isolation now that the correct peripheral is in control of the pad
4667
hw_clear_bits(&pads_qspi_hw->io[gpio], PADS_QSPI_GPIO_QSPI_SD2_ISO_BITS);
@@ -49,9 +70,9 @@ void qspi_gpio_set_function(uint gpio, gpio_function_t fn) {
4970
int main() {
5071
pico_led_init();
5172

52-
// SD2 is QSPI GPIO 3, SD3 is QSPI GPIO 4
53-
qspi_gpio_set_function(3, GPIO_FUNC_UART_AUX);
54-
qspi_gpio_set_function(4, GPIO_FUNC_UART_AUX);
73+
// SD2 is UART0 TX, SD3 is UART0 RX (same as the ROM UART bootloader)
74+
qspi_gpio_set_function(QSPI_GPIO_SD2, GPIO_FUNC_UART_AUX);
75+
qspi_gpio_set_function(QSPI_GPIO_SD3, GPIO_FUNC_UART_AUX);
5576

5677
uart_init(uart0, 1000000);
5778

0 commit comments

Comments
 (0)