Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ The default pin-out is:
| 2 | 4 | SCK |
| 3 | 5 | MOSI |
| 4 | 6 | MISO |
| 5 | 7 | CRESET |

## Usage

Expand Down
58 changes: 38 additions & 20 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "pio/pio_spi.h"
#include "spi.h"

#define PIN_CRESET 5
#define PIN_LED PICO_DEFAULT_LED_PIN
#define PIN_MISO 4
#define PIN_MOSI 3
Expand All @@ -38,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
Expand All @@ -51,6 +60,16 @@ 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);
}

static inline void output_drivers_disable() {
gpio_put(PIN_CRESET, 1);
pio_spi_disable(&spi);
}

uint32_t getu24() {
uint32_t c1 = getchar();
uint32_t c2 = getchar();
Expand Down Expand Up @@ -140,7 +159,6 @@ void process(pio_spi_inst_t *spi, int command) {
pio_spi_read8_blocking(spi, &buf, 1);
putchar(buf);
}


cs_deselect(PIN_CS);
}
Expand All @@ -156,15 +174,23 @@ 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) {
output_drivers_disable();
} else {
output_drivers_enable();
}
putchar(S_ACK);
break;
}
break;
default:
putchar(S_NAK);
}
}



int main() {
// Metadata for picotool
bi_decl(bi_program_description("Flashrom/serprog compatible firmware for the Raspberry Pi Pico"));
Expand All @@ -174,35 +200,27 @@ 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();

stdio_set_translate_crlf(&stdio_usb, false);


// Initialize CS
gpio_init(PIN_CS);
gpio_put(PIN_CS, 1);
gpio_set_dir(PIN_CS, GPIO_OUT);


// We use PIO 1
pio_spi_inst_t spi = {
.pio = pio1,
.sm = 0,
.cs_pin = PIN_CS
};

uint offset = pio_add_program(spi.pio, &spi_cpha0_program);

pio_spi_init(spi.pio, spi.sm, offset,
// Initialize CRESET
gpio_init(PIN_CRESET);
gpio_put(PIN_CRESET, 1);
gpio_set_dir(PIN_CRESET, GPIO_OUT);

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);
Expand Down
42 changes: 42 additions & 0 deletions pio/pio_spi.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,48 @@

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

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

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

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
// 1...32, but the software to do the necessary FIFO shuffling is left as an
// exercise for the reader :)
Expand Down
11 changes: 10 additions & 1 deletion pio/pio_spi.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,18 @@
typedef struct pio_spi_inst {
PIO pio;
uint sm;
uint cs_pin;
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);
Expand Down
31 changes: 0 additions & 31 deletions pio/spi.pio
Original file line number Diff line number Diff line change
Expand Up @@ -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
; -----------------------------------------------------------------------------
;
Expand Down