Initial Release
This commit is contained in:
29
pio/spi/CMakeLists.txt
Normal file
29
pio/spi/CMakeLists.txt
Normal file
@@ -0,0 +1,29 @@
|
||||
add_executable(pio_spi_flash)
|
||||
|
||||
pico_generate_pio_header(pio_spi_flash ${CMAKE_CURRENT_LIST_DIR}/spi.pio)
|
||||
|
||||
target_sources(pio_spi_flash PRIVATE
|
||||
spi_flash.c
|
||||
pio_spi.c
|
||||
pio_spi.h
|
||||
)
|
||||
|
||||
target_link_libraries(pio_spi_flash PRIVATE pico_stdlib hardware_pio)
|
||||
pico_add_extra_outputs(pio_spi_flash)
|
||||
|
||||
example_auto_set_url(pio_spi_flash)
|
||||
|
||||
add_executable(pio_spi_loopback)
|
||||
|
||||
pico_generate_pio_header(pio_spi_loopback ${CMAKE_CURRENT_LIST_DIR}/spi.pio)
|
||||
|
||||
target_sources(pio_spi_loopback PRIVATE
|
||||
spi_loopback.c
|
||||
pio_spi.c
|
||||
pio_spi.h
|
||||
)
|
||||
|
||||
target_link_libraries(pio_spi_loopback PRIVATE pico_stdlib hardware_pio)
|
||||
pico_add_extra_outputs(pio_spi_loopback)
|
||||
|
||||
example_auto_set_url(pio_spi_loopback)
|
||||
68
pio/spi/pio_spi.c
Normal file
68
pio/spi/pio_spi.c
Normal file
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include "pio_spi.h"
|
||||
|
||||
// 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 :)
|
||||
//
|
||||
// Likewise we only provide MSB-first here. To do LSB-first, you need to
|
||||
// - Do shifts when reading from the FIFO, for general case n != 8, 16, 32
|
||||
// - Do a narrow read at a one halfword or 3 byte offset for n == 16, 8
|
||||
// in order to get the read data correctly justified.
|
||||
|
||||
void __time_critical_func(pio_spi_write8_blocking)(const pio_spi_inst_t *spi, const uint8_t *src, size_t len) {
|
||||
size_t tx_remain = len, rx_remain = len;
|
||||
// Do 8 bit accesses on FIFO, so that write data is byte-replicated. This
|
||||
// gets us the left-justification for free (for MSB-first shift-out)
|
||||
io_rw_8 *txfifo = (io_rw_8 *) &spi->pio->txf[spi->sm];
|
||||
io_rw_8 *rxfifo = (io_rw_8 *) &spi->pio->rxf[spi->sm];
|
||||
while (tx_remain || rx_remain) {
|
||||
if (tx_remain && !pio_sm_is_tx_fifo_full(spi->pio, spi->sm)) {
|
||||
*txfifo = *src++;
|
||||
--tx_remain;
|
||||
}
|
||||
if (rx_remain && !pio_sm_is_rx_fifo_empty(spi->pio, spi->sm)) {
|
||||
(void) *rxfifo;
|
||||
--rx_remain;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void __time_critical_func(pio_spi_read8_blocking)(const pio_spi_inst_t *spi, uint8_t *dst, size_t len) {
|
||||
size_t tx_remain = len, rx_remain = len;
|
||||
io_rw_8 *txfifo = (io_rw_8 *) &spi->pio->txf[spi->sm];
|
||||
io_rw_8 *rxfifo = (io_rw_8 *) &spi->pio->rxf[spi->sm];
|
||||
while (tx_remain || rx_remain) {
|
||||
if (tx_remain && !pio_sm_is_tx_fifo_full(spi->pio, spi->sm)) {
|
||||
*txfifo = 0;
|
||||
--tx_remain;
|
||||
}
|
||||
if (rx_remain && !pio_sm_is_rx_fifo_empty(spi->pio, spi->sm)) {
|
||||
*dst++ = *rxfifo;
|
||||
--rx_remain;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void __time_critical_func(pio_spi_write8_read8_blocking)(const pio_spi_inst_t *spi, uint8_t *src, uint8_t *dst,
|
||||
size_t len) {
|
||||
size_t tx_remain = len, rx_remain = len;
|
||||
io_rw_8 *txfifo = (io_rw_8 *) &spi->pio->txf[spi->sm];
|
||||
io_rw_8 *rxfifo = (io_rw_8 *) &spi->pio->rxf[spi->sm];
|
||||
while (tx_remain || rx_remain) {
|
||||
if (tx_remain && !pio_sm_is_tx_fifo_full(spi->pio, spi->sm)) {
|
||||
*txfifo = *src++;
|
||||
--tx_remain;
|
||||
}
|
||||
if (rx_remain && !pio_sm_is_rx_fifo_empty(spi->pio, spi->sm)) {
|
||||
*dst++ = *rxfifo;
|
||||
--rx_remain;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
24
pio/spi/pio_spi.h
Normal file
24
pio/spi/pio_spi.h
Normal file
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#ifndef _PIO_SPI_H
|
||||
#define _PIO_SPI_H
|
||||
|
||||
#include "hardware/pio.h"
|
||||
#include "spi.pio.h"
|
||||
|
||||
typedef struct pio_spi_inst {
|
||||
PIO pio;
|
||||
uint sm;
|
||||
uint cs_pin;
|
||||
} pio_spi_inst_t;
|
||||
|
||||
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);
|
||||
|
||||
#endif
|
||||
168
pio/spi/spi.pio
Normal file
168
pio/spi/spi.pio
Normal file
@@ -0,0 +1,168 @@
|
||||
;
|
||||
; Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
||||
;
|
||||
; SPDX-License-Identifier: BSD-3-Clause
|
||||
;
|
||||
|
||||
; These programs implement full-duplex SPI, with a SCK period of 4 clock
|
||||
; cycles. A different program is provided for each value of CPHA, and CPOL is
|
||||
; achieved using the hardware GPIO inversion available in the IO controls.
|
||||
;
|
||||
; Transmit-only SPI can go twice as fast -- see the ST7789 example!
|
||||
|
||||
|
||||
.program spi_cpha0
|
||||
.side_set 1
|
||||
|
||||
; Pin assignments:
|
||||
; - SCK is side-set pin 0
|
||||
; - MOSI is OUT pin 0
|
||||
; - MISO is IN pin 0
|
||||
;
|
||||
; Autopush and autopull must be enabled, and the serial frame size is set by
|
||||
; configuring the push/pull threshold. Shift left/right is fine, but you must
|
||||
; justify the data yourself. This is done most conveniently for frame sizes of
|
||||
; 8 or 16 bits by using the narrow store replication and narrow load byte
|
||||
; picking behaviour of RP2040's IO fabric.
|
||||
|
||||
; Clock phase = 0: data is captured on the leading edge of each SCK pulse, and
|
||||
; transitions on the trailing edge, or some time before the first leading edge.
|
||||
|
||||
out pins, 1 side 0 [1] ; Stall here on empty (sideset proceeds even if
|
||||
in pins, 1 side 1 [1] ; instruction stalls, so we stall with SCK low)
|
||||
|
||||
.program spi_cpha1
|
||||
.side_set 1
|
||||
|
||||
; Clock phase = 1: data transitions on the leading edge of each SCK pulse, and
|
||||
; is captured on the trailing edge.
|
||||
|
||||
out x, 1 side 0 ; Stall here on empty (keep SCK deasserted)
|
||||
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
|
||||
; -----------------------------------------------------------------------------
|
||||
;
|
||||
; For your amusement, here are some SPI programs with an automatic chip select
|
||||
; (asserted once data appears in TX FIFO, deasserts when FIFO bottoms out, has
|
||||
; a nice front/back porch).
|
||||
;
|
||||
; The number of bits per FIFO entry is configured via the Y register
|
||||
; and the autopush/pull threshold. From 2 to 32 bits.
|
||||
;
|
||||
; Pin assignments:
|
||||
; - SCK is side-set bit 0
|
||||
; - CSn is side-set bit 1
|
||||
; - MOSI is OUT bit 0 (host-to-device)
|
||||
; - MISO is IN bit 0 (device-to-host)
|
||||
;
|
||||
; This program only supports one chip select -- use GPIO if more are needed
|
||||
;
|
||||
; Provide a variation for each possibility of CPHA; for CPOL we can just
|
||||
; invert SCK in the IO muxing controls (downstream from PIO)
|
||||
|
||||
|
||||
; CPHA=0: data is captured on the leading edge of each SCK pulse (including
|
||||
; the first pulse), and transitions on the trailing edge
|
||||
|
||||
.program spi_cpha0_cs
|
||||
.side_set 2
|
||||
|
||||
.wrap_target
|
||||
bitloop:
|
||||
out pins, 1 side 0x0 [1]
|
||||
in pins, 1 side 0x1
|
||||
jmp x-- bitloop side 0x1
|
||||
|
||||
out pins, 1 side 0x0
|
||||
mov x, y side 0x0 ; Reload bit counter from Y
|
||||
in pins, 1 side 0x1
|
||||
jmp !osre bitloop side 0x1 ; Fall-through if TXF empties
|
||||
|
||||
nop side 0x0 [1] ; CSn back porch
|
||||
public entry_point: ; Must set X,Y to n-2 before starting!
|
||||
pull ifempty side 0x2 [1] ; Block with CSn high (minimum 2 cycles)
|
||||
.wrap ; Note ifempty to avoid time-of-check race
|
||||
|
||||
; CPHA=1: data transitions on the leading edge of each SCK pulse, and is
|
||||
; captured on the trailing edge
|
||||
|
||||
.program spi_cpha1_cs
|
||||
.side_set 2
|
||||
|
||||
.wrap_target
|
||||
bitloop:
|
||||
out pins, 1 side 0x1 [1]
|
||||
in pins, 1 side 0x0
|
||||
jmp x-- bitloop side 0x0
|
||||
|
||||
out pins, 1 side 0x1
|
||||
mov x, y side 0x1
|
||||
in pins, 1 side 0x0
|
||||
jmp !osre bitloop side 0x0
|
||||
|
||||
public entry_point: ; Must set X,Y to n-2 before starting!
|
||||
pull ifempty side 0x2 [1] ; Block with CSn high (minimum 2 cycles)
|
||||
nop side 0x0 [1]; CSn front porch
|
||||
.wrap
|
||||
|
||||
% c-sdk {
|
||||
#include "hardware/gpio.h"
|
||||
static inline void pio_spi_cs_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_cs_program_get_default_config(prog_offs) : spi_cpha0_cs_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);
|
||||
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);
|
||||
|
||||
pio_sm_set_pins_with_mask(pio, sm, (2u << pin_sck), (3u << pin_sck) | (1u << pin_mosi));
|
||||
pio_sm_set_pindirs_with_mask(pio, sm, (3u << pin_sck) | (1u << pin_mosi), (3u << 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);
|
||||
pio_gpio_init(pio, pin_sck + 1);
|
||||
gpio_set_outover(pin_sck, cpol ? GPIO_OVERRIDE_INVERT : GPIO_OVERRIDE_NORMAL);
|
||||
hw_set_bits(&pio->input_sync_bypass, 1u << pin_miso);
|
||||
|
||||
uint entry_point = prog_offs + (cpha ? spi_cpha1_cs_offset_entry_point : spi_cpha0_cs_offset_entry_point);
|
||||
pio_sm_init(pio, sm, entry_point, &c);
|
||||
pio_sm_exec(pio, sm, pio_encode_set(pio_x, n_bits - 2));
|
||||
pio_sm_exec(pio, sm, pio_encode_set(pio_y, n_bits - 2));
|
||||
pio_sm_set_enabled(pio, sm, true);
|
||||
}
|
||||
%}
|
||||
155
pio/spi/spi_flash.c
Normal file
155
pio/spi/spi_flash.c
Normal file
@@ -0,0 +1,155 @@
|
||||
/**
|
||||
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "pico/stdlib.h"
|
||||
#include "pio_spi.h"
|
||||
|
||||
// This example uses PIO to erase, program and read back a SPI serial flash
|
||||
// memory.
|
||||
|
||||
#define PIN_MISO 16
|
||||
#define PIN_MOSI 17
|
||||
#define PIN_SCK 18
|
||||
#define PIN_CS 19
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Generic serial flash code
|
||||
|
||||
#define FLASH_PAGE_SIZE 256
|
||||
#define FLASH_SECTOR_SIZE 4096
|
||||
|
||||
#define FLASH_CMD_PAGE_PROGRAM 0x02
|
||||
#define FLASH_CMD_READ 0x03
|
||||
#define FLASH_CMD_STATUS 0x05
|
||||
#define FLASH_CMD_WRITE_EN 0x06
|
||||
#define FLASH_CMD_SECTOR_ERASE 0x20
|
||||
|
||||
#define FLASH_STATUS_BUSY_MASK 0x01
|
||||
|
||||
void flash_read(const pio_spi_inst_t *spi, uint32_t addr, uint8_t *buf, size_t len) {
|
||||
uint8_t cmd[4] = {
|
||||
FLASH_CMD_READ,
|
||||
addr >> 16,
|
||||
addr >> 8,
|
||||
addr
|
||||
};
|
||||
gpio_put(spi->cs_pin, 0);
|
||||
pio_spi_write8_blocking(spi, cmd, 4);
|
||||
pio_spi_read8_blocking(spi, buf, len);
|
||||
gpio_put(spi->cs_pin, 1);
|
||||
}
|
||||
|
||||
|
||||
void flash_write_enable(const pio_spi_inst_t *spi) {
|
||||
uint8_t cmd = FLASH_CMD_WRITE_EN;
|
||||
gpio_put(spi->cs_pin, 0);
|
||||
pio_spi_write8_blocking(spi, &cmd, 1);
|
||||
gpio_put(spi->cs_pin, 1);
|
||||
}
|
||||
|
||||
void flash_wait_done(const pio_spi_inst_t *spi) {
|
||||
uint8_t status;
|
||||
do {
|
||||
gpio_put(spi->cs_pin, 0);
|
||||
uint8_t cmd = FLASH_CMD_STATUS;
|
||||
pio_spi_write8_blocking(spi, &cmd, 1);
|
||||
pio_spi_read8_blocking(spi, &status, 1);
|
||||
gpio_put(spi->cs_pin, 1);
|
||||
} while (status & FLASH_STATUS_BUSY_MASK);
|
||||
}
|
||||
|
||||
void flash_sector_erase(const pio_spi_inst_t *spi, uint32_t addr) {
|
||||
uint8_t cmd[4] = {
|
||||
FLASH_CMD_SECTOR_ERASE,
|
||||
addr >> 16,
|
||||
addr >> 8,
|
||||
addr
|
||||
};
|
||||
flash_write_enable(spi);
|
||||
gpio_put(spi->cs_pin, 0);
|
||||
pio_spi_write8_blocking(spi, cmd, 4);
|
||||
gpio_put(spi->cs_pin, 1);
|
||||
flash_wait_done(spi);
|
||||
}
|
||||
|
||||
void flash_page_program(const pio_spi_inst_t *spi, uint32_t addr, uint8_t data[]) {
|
||||
flash_write_enable(spi);
|
||||
uint8_t cmd[4] = {
|
||||
FLASH_CMD_PAGE_PROGRAM,
|
||||
addr >> 16,
|
||||
addr >> 8,
|
||||
addr
|
||||
};
|
||||
gpio_put(spi->cs_pin, 0);
|
||||
pio_spi_write8_blocking(spi, cmd, 4);
|
||||
pio_spi_write8_blocking(spi, data, FLASH_PAGE_SIZE);
|
||||
gpio_put(spi->cs_pin, 1);
|
||||
flash_wait_done(spi);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Example program
|
||||
|
||||
void printbuf(const uint8_t buf[FLASH_PAGE_SIZE]) {
|
||||
for (int i = 0; i < FLASH_PAGE_SIZE; ++i)
|
||||
printf("%02x%c", buf[i], i % 16 == 15 ? '\n' : ' ');
|
||||
}
|
||||
|
||||
int main() {
|
||||
stdio_init_all();
|
||||
puts("PIO SPI Example");
|
||||
|
||||
pio_spi_inst_t spi = {
|
||||
.pio = pio0,
|
||||
.sm = 0,
|
||||
.cs_pin = PIN_CS
|
||||
};
|
||||
|
||||
gpio_init(PIN_CS);
|
||||
gpio_put(PIN_CS, 1);
|
||||
gpio_set_dir(PIN_CS, GPIO_OUT);
|
||||
|
||||
uint offset = pio_add_program(spi.pio, &spi_cpha0_program);
|
||||
printf("Loaded program at %d\n", offset);
|
||||
|
||||
pio_spi_init(spi.pio, spi.sm, offset,
|
||||
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
|
||||
);
|
||||
|
||||
uint8_t page_buf[FLASH_PAGE_SIZE];
|
||||
|
||||
const uint32_t target_addr = 0;
|
||||
|
||||
flash_sector_erase(&spi, target_addr);
|
||||
flash_read(&spi, target_addr, page_buf, FLASH_PAGE_SIZE);
|
||||
|
||||
puts("After erase:");
|
||||
printbuf(page_buf);
|
||||
|
||||
for (int i = 0; i < FLASH_PAGE_SIZE; ++i)
|
||||
page_buf[i] = i;
|
||||
flash_page_program(&spi, target_addr, page_buf);
|
||||
flash_read(&spi, target_addr, page_buf, FLASH_PAGE_SIZE);
|
||||
|
||||
puts("After program:");
|
||||
printbuf(page_buf);
|
||||
|
||||
flash_sector_erase(&spi, target_addr);
|
||||
flash_read(&spi, target_addr, page_buf, FLASH_PAGE_SIZE);
|
||||
|
||||
puts("Erase again:");
|
||||
printbuf(page_buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
77
pio/spi/spi_loopback.c
Normal file
77
pio/spi/spi_loopback.c
Normal file
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "pico/stdlib.h"
|
||||
#include "pio_spi.h"
|
||||
|
||||
// This program instantiates a PIO SPI with each of the four possible
|
||||
// CPOL/CPHA combinations, with the serial input and output pin mapped to the
|
||||
// same GPIO. Any data written into the state machine's TX FIFO should then be
|
||||
// serialised, deserialised, and reappear in the state machine's RX FIFO.
|
||||
|
||||
#define PIN_SCK 18
|
||||
#define PIN_MOSI 16
|
||||
#define PIN_MISO 16 // same as MOSI, so we get loopback
|
||||
|
||||
#define BUF_SIZE 20
|
||||
|
||||
void test(const pio_spi_inst_t *spi) {
|
||||
static uint8_t txbuf[BUF_SIZE];
|
||||
static uint8_t rxbuf[BUF_SIZE];
|
||||
printf("TX:");
|
||||
for (int i = 0; i < BUF_SIZE; ++i) {
|
||||
txbuf[i] = rand() >> 16;
|
||||
rxbuf[i] = 0;
|
||||
printf(" %02x", (int) txbuf[i]);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
pio_spi_write8_read8_blocking(spi, txbuf, rxbuf, BUF_SIZE);
|
||||
|
||||
printf("RX:");
|
||||
bool mismatch = false;
|
||||
for (int i = 0; i < BUF_SIZE; ++i) {
|
||||
printf(" %02x", (int) rxbuf[i]);
|
||||
mismatch = mismatch || rxbuf[i] != txbuf[i];
|
||||
}
|
||||
if (mismatch)
|
||||
printf("\nNope\n");
|
||||
else
|
||||
printf("\nOK\n");
|
||||
}
|
||||
|
||||
int main() {
|
||||
stdio_init_all();
|
||||
|
||||
pio_spi_inst_t spi = {
|
||||
.pio = pio0,
|
||||
.sm = 0
|
||||
};
|
||||
float clkdiv = 31.25f; // 1 MHz @ 125 clk_sys
|
||||
uint cpha0_prog_offs = pio_add_program(spi.pio, &spi_cpha0_program);
|
||||
uint cpha1_prog_offs = pio_add_program(spi.pio, &spi_cpha1_program);
|
||||
|
||||
for (int cpha = 0; cpha <= 1; ++cpha) {
|
||||
for (int cpol = 0; cpol <= 1; ++cpol) {
|
||||
printf("CPHA = %d, CPOL = %d\n", cpha, cpol);
|
||||
pio_spi_init(spi.pio, spi.sm,
|
||||
cpha ? cpha1_prog_offs : cpha0_prog_offs,
|
||||
8, // 8 bits per SPI frame
|
||||
clkdiv,
|
||||
cpha,
|
||||
cpol,
|
||||
PIN_SCK,
|
||||
PIN_MOSI,
|
||||
PIN_MISO
|
||||
);
|
||||
test(&spi);
|
||||
sleep_ms(10);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user