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
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ Dump a flashchip:
flashrom -p serprog:dev=/dev/ttyACM0:115200,spispeed=12M -r foo.bin
```

pico-serprog only switches the pins to output when requested by flashrom. This
means that you can leave your pico-serprog programmer attached to the flash;
you don't have to detach it before booting the board that you're programming.


## License

The project is based on the spi_flash example by Raspberry Pi (Trading) Ltd. which is licensed under BSD-3-Clause.
Expand Down
14 changes: 11 additions & 3 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,14 @@ void putu32(uint32_t d) {

unsigned char write_buffer[4096];

void apply_pin_state(const pio_spi_inst_t *spi, bool state) {
pio_spi_enable_outputs(spi->pio, spi->sm, state, PIN_SCK, PIN_MOSI, PIN_MISO);
gpio_set_dir(PIN_CS, state? GPIO_OUT : GPIO_IN);
}

void process(const pio_spi_inst_t *spi, int command) {
static bool pin_state = false;

switch(command) {
case S_CMD_NOP:
putchar(S_ACK);
Expand Down Expand Up @@ -155,14 +162,15 @@ void process(const pio_spi_inst_t *spi, int command) {
if (freq >= 1) {
putchar(S_ACK);
putu32(serprog_spi_init(freq));
apply_pin_state(spi, pin_state);
} else {
putchar(S_NAK);
}
}
break;
case S_CMD_S_PIN_STATE:
//TODO:
getchar();
pin_state = !!getchar();
apply_pin_state(spi, pin_state);
putchar(S_ACK);
break;
default:
Expand Down Expand Up @@ -227,7 +235,7 @@ int main() {
// Initialize CS
gpio_init(PIN_CS);
gpio_put(PIN_CS, 1);
gpio_set_dir(PIN_CS, GPIO_OUT);
gpio_set_dir(PIN_CS, GPIO_IN); // switch to output on S_CMD_S_PIN_STATE

spi_offset = pio_add_program(spi.pio, &spi_cpha0_program);
serprog_spi_init(1000000); // 1 MHz
Expand Down
10 changes: 8 additions & 2 deletions pio/spi.pio
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,9 @@ static inline void pio_spi_init(PIO pio, uint sm, uint prog_offs, uint 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
// MOSI, SCK output are low, MISO is input -- but we start in input mode
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_sm_set_pindirs_with_mask(pio, sm, 0, (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);
Expand All @@ -70,6 +70,12 @@ static inline void pio_spi_init(PIO pio, uint sm, uint prog_offs, uint n_bits,
pio_sm_init(pio, sm, prog_offs, &c);
pio_sm_set_enabled(pio, sm, true);
}

static inline void pio_spi_enable_outputs(PIO pio, uint sm, bool output, uint pin_sck, uint pin_mosi, uint pin_miso) {
uint mask = output? (1u << pin_sck) | (1u << pin_mosi) : 0;
pio_sm_set_pindirs_with_mask(pio, sm, mask, (1u << pin_sck) | (1u << pin_mosi) | (1u << pin_miso));
}

%}

; SPI with Chip Select
Expand Down