From 45ebd15b09ce94fc6f4f6c47fbd0bdddb09ebbc2 Mon Sep 17 00:00:00 2001 From: Dan Corneanu Date: Sat, 24 Dec 2022 23:47:05 +1300 Subject: [PATCH 1/4] Implement S_CMD_S_PIN_STATE command --- main.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/main.c b/main.c index d29a486..c45d332 100644 --- a/main.c +++ b/main.c @@ -16,6 +16,7 @@ #include "pio/pio_spi.h" #include "spi.h" +#define PIN_CRESET 5 #define PIN_MISO 4 #define PIN_MOSI 3 #define PIN_SCK 2 @@ -144,10 +145,18 @@ void process(pio_spi_inst_t *spi, int command) { putchar(0x0); break; case S_CMD_S_PIN_STATE: - //TODO: - getchar(); + { + int pin_state = getchar(); + if(pin_state == 0) { + // Disable pin drivers + gpio_put(PIN_CRESET, 1); + } else { + // Enable pin drivers + gpio_put(PIN_CRESET, 0); + } putchar(S_ACK); - break; + } + break; default: putchar(S_NAK); } @@ -164,7 +173,11 @@ int main() { gpio_put(PIN_CS, 1); gpio_set_dir(PIN_CS, GPIO_OUT); - + // Initialize CRESET + gpio_init(PIN_CRESET); + gpio_put(PIN_CRESET, 1); + gpio_set_dir(PIN_CRESET, GPIO_OUT); + // We use PIO 1 pio_spi_inst_t spi = { .pio = pio1, From 26ccb290e7dc27179d7d42eeb5663d984590bf63 Mon Sep 17 00:00:00 2001 From: Dan Corneanu Date: Sun, 2 Jul 2023 14:02:59 +1200 Subject: [PATCH 2/4] Move all spi initialization code into its own function --- README.md | 1 + main.c | 16 +++++++--------- pio/pio_spi.c | 28 ++++++++++++++++++++++++++++ pio/pio_spi.h | 8 +++++++- pio/spi.pio | 31 ------------------------------- 5 files changed, 43 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index fe7589a..288f2e2 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ The default pin-out is: | 2 | 4 | SCK | | 3 | 5 | MOSI | | 4 | 6 | MISO | +| 5 | 7 | CRESET | ## Usage diff --git a/main.c b/main.c index 038a412..cf2e86c 100644 --- a/main.c +++ b/main.c @@ -166,6 +166,7 @@ void process(pio_spi_inst_t *spi, int command) { // Enable pin drivers gpio_put(PIN_CRESET, 0); } + asm volatile("nop \n nop \n nop"); // FIXME putchar(S_ACK); } break; @@ -188,7 +189,6 @@ int main() { stdio_set_translate_crlf(&stdio_usb, false); - // Initialize CS gpio_init(PIN_CS); gpio_put(PIN_CS, 1); @@ -203,19 +203,17 @@ int main() { pio_spi_inst_t spi = { .pio = pio1, .sm = 0, - .cs_pin = PIN_CS + .pin_cs = PIN_CS, + .pin_sck = PIN_SCK, + .pin_mosi = PIN_MOSI, + .pin_miso = PIN_MISO }; - uint offset = pio_add_program(spi.pio, &spi_cpha0_program); - - pio_spi_init(spi.pio, spi.sm, offset, + pio_spi_init(&spi, 8, // 8 bits per SPI frame 31.25f, // 1 MHz @ 125 clk_sys false, // CPHA = 0 - false, // CPOL = 0 - PIN_SCK, - PIN_MOSI, - PIN_MISO); + false); // CPOL = 0 gpio_init(PIN_LED); gpio_set_dir(PIN_LED, GPIO_OUT); diff --git a/pio/pio_spi.c b/pio/pio_spi.c index 6306b7d..dada743 100644 --- a/pio/pio_spi.c +++ b/pio/pio_spi.c @@ -6,6 +6,34 @@ #include "pio_spi.h" +void pio_spi_init(pio_spi_inst_t *spi, uint n_bits, float clkdiv, bool cpha, bool cpol) { + spi->prog_offs = pio_add_program(spi->pio, cpha ? &spi_cpha1_program : &spi_cpha0_program); + pio_sm_config c = cpha ? spi_cpha1_program_get_default_config(spi->prog_offs) : spi_cpha0_program_get_default_config(spi->prog_offs); + sm_config_set_out_pins(&c, spi->pin_mosi, 1); + sm_config_set_in_pins(&c, spi->pin_miso); + sm_config_set_sideset_pins(&c, spi->pin_sck); + // Only support MSB-first in this example code (shift to left, auto push/pull, threshold=nbits) + sm_config_set_out_shift(&c, false, true, n_bits); + sm_config_set_in_shift(&c, false, true, n_bits); + sm_config_set_clkdiv(&c, clkdiv); + + // MOSI, SCK output are low, MISO is input + pio_sm_set_pins_with_mask(spi->pio, spi->sm, 0, (1u << spi->pin_sck) | (1u << spi->pin_mosi)); + pio_sm_set_pindirs_with_mask(spi->pio, spi->sm, (1u << spi->pin_sck) | (1u << spi->pin_mosi), (1u << spi->pin_sck) | (1u << spi->pin_mosi) | (1u << spi->pin_miso)); + pio_gpio_init(spi->pio, spi->pin_mosi); + pio_gpio_init(spi->pio, spi->pin_miso); + pio_gpio_init(spi->pio, spi->pin_sck); + + // The pin muxes can be configured to invert the output (among other things + // and this is a cheesy way to get CPOL=1 + gpio_set_outover(spi->pin_sck, cpol ? GPIO_OVERRIDE_INVERT : GPIO_OVERRIDE_NORMAL); + // SPI is synchronous, so bypass input synchroniser to reduce input delay. + hw_set_bits(&spi->pio->input_sync_bypass, 1u << spi->pin_miso); + + pio_sm_init(spi->pio, spi->sm, spi->prog_offs, &c); + pio_sm_set_enabled(spi->pio, spi->sm, true); +} + // Just 8 bit functions provided here. The PIO program supports any frame size // 1...32, but the software to do the necessary FIFO shuffling is left as an // exercise for the reader :) diff --git a/pio/pio_spi.h b/pio/pio_spi.h index dfa929d..173c56d 100644 --- a/pio/pio_spi.h +++ b/pio/pio_spi.h @@ -12,7 +12,11 @@ typedef struct pio_spi_inst { PIO pio; uint sm; - uint cs_pin; + uint pin_cs; + uint pin_sck; + uint pin_mosi; + uint pin_miso; + uint prog_offs; } pio_spi_inst_t; void pio_spi_write8_blocking(const pio_spi_inst_t *spi, const uint8_t *src, size_t len); @@ -21,4 +25,6 @@ void pio_spi_read8_blocking(const pio_spi_inst_t *spi, uint8_t *dst, size_t len) void pio_spi_write8_read8_blocking(const pio_spi_inst_t *spi, uint8_t *src, uint8_t *dst, size_t len); +void pio_spi_init(pio_spi_inst_t *spi, uint n_bits, float clkdiv, bool cpha, bool cpol); + #endif diff --git a/pio/spi.pio b/pio/spi.pio index eba785e..9252f26 100644 --- a/pio/spi.pio +++ b/pio/spi.pio @@ -41,37 +41,6 @@ mov pins, x side 1 [1] ; Output data, assert SCK (mov pins uses OUT mapping) in pins, 1 side 0 ; Input data, deassert SCK -% c-sdk { -#include "hardware/gpio.h" -static inline void pio_spi_init(PIO pio, uint sm, uint prog_offs, uint n_bits, - float clkdiv, bool cpha, bool cpol, uint pin_sck, uint pin_mosi, uint pin_miso) { - pio_sm_config c = cpha ? spi_cpha1_program_get_default_config(prog_offs) : spi_cpha0_program_get_default_config(prog_offs); - sm_config_set_out_pins(&c, pin_mosi, 1); - sm_config_set_in_pins(&c, pin_miso); - sm_config_set_sideset_pins(&c, pin_sck); - // Only support MSB-first in this example code (shift to left, auto push/pull, threshold=nbits) - sm_config_set_out_shift(&c, false, true, n_bits); - sm_config_set_in_shift(&c, false, true, n_bits); - sm_config_set_clkdiv(&c, clkdiv); - - // MOSI, SCK output are low, MISO is input - pio_sm_set_pins_with_mask(pio, sm, 0, (1u << pin_sck) | (1u << pin_mosi)); - pio_sm_set_pindirs_with_mask(pio, sm, (1u << pin_sck) | (1u << pin_mosi), (1u << pin_sck) | (1u << pin_mosi) | (1u << pin_miso)); - pio_gpio_init(pio, pin_mosi); - pio_gpio_init(pio, pin_miso); - pio_gpio_init(pio, pin_sck); - - // The pin muxes can be configured to invert the output (among other things - // and this is a cheesy way to get CPOL=1 - gpio_set_outover(pin_sck, cpol ? GPIO_OVERRIDE_INVERT : GPIO_OVERRIDE_NORMAL); - // SPI is synchronous, so bypass input synchroniser to reduce input delay. - hw_set_bits(&pio->input_sync_bypass, 1u << pin_miso); - - pio_sm_init(pio, sm, prog_offs, &c); - pio_sm_set_enabled(pio, sm, true); -} -%} - ; SPI with Chip Select ; ----------------------------------------------------------------------------- ; From 7ecb67d09ad7cd64ebd72e555a4f905f02e3e546 Mon Sep 17 00:00:00 2001 From: Dan Corneanu Date: Sun, 2 Jul 2023 20:48:07 +1200 Subject: [PATCH 3/4] Implement pio_spi_enable/disable --- main.c | 41 +++++++++++++++++++++++++---------------- pio/pio_spi.c | 22 ++++++++++++++++++---- pio/pio_spi.h | 9 ++++++--- 3 files changed, 49 insertions(+), 23 deletions(-) diff --git a/main.c b/main.c index cf2e86c..4dbd98f 100644 --- a/main.c +++ b/main.c @@ -39,6 +39,14 @@ (1 << S_CMD_S_PIN_STATE) \ ) +// We use PIO 1 +pio_spi_inst_t spi = { + .pio = pio1, + .sm = 0, + .pin_sck = PIN_SCK, + .pin_mosi = PIN_MOSI, + .pin_miso = PIN_MISO +}; static inline void cs_select(uint cs_pin) { asm volatile("nop \n nop \n nop"); // FIXME @@ -52,6 +60,18 @@ static inline void cs_deselect(uint cs_pin) { asm volatile("nop \n nop \n nop"); // FIXME } +static inline void output_drivers_enable() { + pio_spi_enable(&spi); + gpio_put(PIN_CRESET, 0); + asm volatile("nop \n nop \n nop"); // FIXME +} + +static inline void output_drivers_disable() { + gpio_put(PIN_CRESET, 1); + pio_spi_disable(&spi); + asm volatile("nop \n nop \n nop"); // FIXME +} + uint32_t getu24() { uint32_t c1 = getchar(); uint32_t c2 = getchar(); @@ -141,7 +161,6 @@ void process(pio_spi_inst_t *spi, int command) { pio_spi_read8_blocking(spi, &buf, 1); putchar(buf); } - cs_deselect(PIN_CS); } @@ -160,13 +179,10 @@ void process(pio_spi_inst_t *spi, int command) { { int pin_state = getchar(); if(pin_state == 0) { - // Disable pin drivers - gpio_put(PIN_CRESET, 1); + output_drivers_disable(); } else { - // Enable pin drivers - gpio_put(PIN_CRESET, 0); + output_drivers_enable(); } - asm volatile("nop \n nop \n nop"); // FIXME putchar(S_ACK); } break; @@ -175,6 +191,8 @@ void process(pio_spi_inst_t *spi, int command) { } } + + int main() { // Metadata for picotool bi_decl(bi_program_description("Flashrom/serprog compatible firmware for the Raspberry Pi Pico")); @@ -184,6 +202,7 @@ int main() { bi_decl(bi_1pin_with_name(PIN_MOSI, "MOSI")); bi_decl(bi_1pin_with_name(PIN_SCK, "SCK")); bi_decl(bi_1pin_with_name(PIN_CS, "CS#")); + bi_decl(bi_1pin_with_name(PIN_CRESET, "CRESET")); stdio_init_all(); @@ -199,16 +218,6 @@ int main() { gpio_put(PIN_CRESET, 1); gpio_set_dir(PIN_CRESET, GPIO_OUT); - // We use PIO 1 - pio_spi_inst_t spi = { - .pio = pio1, - .sm = 0, - .pin_cs = PIN_CS, - .pin_sck = PIN_SCK, - .pin_mosi = PIN_MOSI, - .pin_miso = PIN_MISO - }; - pio_spi_init(&spi, 8, // 8 bits per SPI frame 31.25f, // 1 MHz @ 125 clk_sys diff --git a/pio/pio_spi.c b/pio/pio_spi.c index dada743..953f73e 100644 --- a/pio/pio_spi.c +++ b/pio/pio_spi.c @@ -17,9 +17,7 @@ void pio_spi_init(pio_spi_inst_t *spi, uint n_bits, float clkdiv, bool cpha, boo sm_config_set_in_shift(&c, false, true, n_bits); sm_config_set_clkdiv(&c, clkdiv); - // MOSI, SCK output are low, MISO is input - pio_sm_set_pins_with_mask(spi->pio, spi->sm, 0, (1u << spi->pin_sck) | (1u << spi->pin_mosi)); - pio_sm_set_pindirs_with_mask(spi->pio, spi->sm, (1u << spi->pin_sck) | (1u << spi->pin_mosi), (1u << spi->pin_sck) | (1u << spi->pin_mosi) | (1u << spi->pin_miso)); + // Set these pins to be used by PIO. pio_gpio_init(spi->pio, spi->pin_mosi); pio_gpio_init(spi->pio, spi->pin_miso); pio_gpio_init(spi->pio, spi->pin_sck); @@ -31,7 +29,23 @@ void pio_spi_init(pio_spi_inst_t *spi, uint n_bits, float clkdiv, bool cpha, boo hw_set_bits(&spi->pio->input_sync_bypass, 1u << spi->pin_miso); pio_sm_init(spi->pio, spi->sm, spi->prog_offs, &c); - pio_sm_set_enabled(spi->pio, spi->sm, true); +} + +void pio_spi_enable(pio_spi_inst_t *spi) { + // MOSI, SCK output are low, MISO is input + pio_sm_set_pins_with_mask(spi->pio, spi->sm, 0, (1u << spi->pin_sck) | (1u << spi->pin_mosi)); + pio_sm_set_pindirs_with_mask(spi->pio, spi->sm, (1u << spi->pin_sck) | (1u << spi->pin_mosi), (1u << spi->pin_sck) | (1u << spi->pin_mosi) | (1u << spi->pin_miso)); + + pio_sm_set_enabled(spi->pio, spi->sm, true); + pio_sm_restart(spi->pio, spi->sm); +} + +void pio_spi_disable(pio_spi_inst_t *spi) { + pio_sm_set_enabled(spi->pio, spi->sm, false); + + // Set these pins to INPUT. This way we allow them to be driven by + // someone else. + pio_sm_set_pindirs_with_mask(spi->pio, spi->sm, 0u, (1u << spi->pin_sck) | (1u << spi->pin_mosi) | (1u << spi->pin_miso)); } // Just 8 bit functions provided here. The PIO program supports any frame size diff --git a/pio/pio_spi.h b/pio/pio_spi.h index 173c56d..49f6b81 100644 --- a/pio/pio_spi.h +++ b/pio/pio_spi.h @@ -12,19 +12,22 @@ typedef struct pio_spi_inst { PIO pio; uint sm; - uint pin_cs; uint pin_sck; uint pin_mosi; uint pin_miso; uint prog_offs; } pio_spi_inst_t; +void pio_spi_init(pio_spi_inst_t *spi, uint n_bits, float clkdiv, bool cpha, bool cpol); + +void pio_spi_enable(pio_spi_inst_t *spi); + +void pio_spi_disable(pio_spi_inst_t *spi); + void pio_spi_write8_blocking(const pio_spi_inst_t *spi, const uint8_t *src, size_t len); void pio_spi_read8_blocking(const pio_spi_inst_t *spi, uint8_t *dst, size_t len); void pio_spi_write8_read8_blocking(const pio_spi_inst_t *spi, uint8_t *src, uint8_t *dst, size_t len); -void pio_spi_init(pio_spi_inst_t *spi, uint n_bits, float clkdiv, bool cpha, bool cpol); - #endif From 2aa5091c78300096da7d07975a0d8d92a783404f Mon Sep 17 00:00:00 2001 From: Dan Corneanu Date: Mon, 3 Jul 2023 20:35:03 +1200 Subject: [PATCH 4/4] Remove unnecessary delays --- main.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/main.c b/main.c index 4dbd98f..2725bf8 100644 --- a/main.c +++ b/main.c @@ -63,13 +63,11 @@ static inline void cs_deselect(uint cs_pin) { static inline void output_drivers_enable() { pio_spi_enable(&spi); gpio_put(PIN_CRESET, 0); - asm volatile("nop \n nop \n nop"); // FIXME } static inline void output_drivers_disable() { gpio_put(PIN_CRESET, 1); pio_spi_disable(&spi); - asm volatile("nop \n nop \n nop"); // FIXME } uint32_t getu24() {