super epic SPI

This commit is contained in:
Ben Kyd
2023-06-02 21:27:52 +01:00
parent 5f5dc5be2b
commit 2e07a22f41
8 changed files with 209558 additions and 32 deletions

View File

@@ -1,5 +1,9 @@
cmake_minimum_required(VERSION 3.20.0)
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${BOARD}.overlay")
set(mcuboot_DTC_OVERLAY_FILE "${CMAKE_CURRENT_SOURCE_DIR}/${BOARD}.overlay")
endif()
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
project(passr)

View File

@@ -1,12 +1,12 @@
.ONESHELL:
TARGET=rpi_pico
TARGET=nrf52840dk_nrf52840
CMAKE_ZEPHYR_PATH=../zephyrproject/zephyr
CMAKE_ZEPHYR_COMMAND=west build
CMAKE_ZEPHYR_FLAGS=-b $(TARGET)
all: compile flash_pico
all: compile flash
setup:
west init
@@ -14,18 +14,15 @@ setup:
compile:
$(CMAKE_ZEPHYR_COMMAND) $(CMAKE_ZEPHYR_FLAGS)
cp build/zephyr/zephyr.uf2 ./zephyr.uf2
echo "Copied zephyr.uf2 to project root"
flash_pico:
# mount then copy the uf2
sudo mount -L RPI-RP2 /mnt
sudo cp zephyr.uf2 /mnt
echo "Copied zephyr.uf2 to pico"
flash: compile
cp build/zephyr/zephyr.hex ./zephyr.hex
echo "Copied zephyr.hex to project root"
nrfjprog -f nrf52 --program zephyr.hex --sectorerase --verify --log --reset
minicom -D /dev/ttyACM0 -b 115200
# FIXME: This is entirely board specific, for example the pi pico will vibe differently
flash:
west flash
listen:
minicom -D /dev/ttyACM0 -b 115200
clean:
rm -rf build/

View File

@@ -0,0 +1,63 @@
&pinctrl {
spi_master_default: spi_master_default {
group1 {
psels = <NRF_PSEL(SPIM_SCK, 0, 31)>,
<NRF_PSEL(SPIM_MOSI, 0, 30)>,
<NRF_PSEL(SPIM_MISO, 0, 29)>;
};
};
spi_master_sleep: spi_master_sleep {
group1 {
psels = <NRF_PSEL(SPIM_SCK, 0, 31)>,
<NRF_PSEL(SPIM_MOSI, 0, 30)>,
<NRF_PSEL(SPIM_MISO, 0, 29)>;
low-power-enable;
};
};
spi_slave_default: spi_slave_default {
group1 {
psels = <NRF_PSEL(SPIS_SCK, 1, 1)>,
<NRF_PSEL(SPIS_MOSI, 1, 2)>,
<NRF_PSEL(SPIS_MISO, 1, 3)>,
<NRF_PSEL(SPIS_CSN, 1, 4)>;
};
};
spi_slave_sleep: spi_slave_sleep {
group1 {
psels = <NRF_PSEL(SPIS_SCK, 1, 1)>,
<NRF_PSEL(SPIS_MOSI, 1, 2)>,
<NRF_PSEL(SPIS_MISO, 1, 3)>,
<NRF_PSEL(SPIS_CSN, 1, 4)>;
low-power-enable;
};
};
};
my_spi_master: &spi3 {
compatible = "nordic,nrf-spim";
status = "okay";
pinctrl-0 = <&spi_master_default>;
pinctrl-1 = <&spi_master_sleep>;
pinctrl-names = "default", "sleep";
cs-gpios = <&gpio0 28 GPIO_ACTIVE_LOW>;
reg_my_spi_master: spi-dev-a@0 {
reg = <0>;
};
};
my_spi_slave: &spi1 {
compatible = "nordic,nrf-spis";
status = "okay";
pinctrl-0 = <&spi_slave_default>;
pinctrl-1 = <&spi_slave_sleep>;
pinctrl-names = "default", "sleep";
def-char = <0x00>;
};
// By default uart1 will occupy P1.01 and P1.02. In order to make these pins available, disable uart1
&uart1 {
status="disabled";
};

207554
log.log Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,6 @@
CONFIG_BUILD_OUTPUT_UF2=y
CONFIG_GPIO=y
CONFIG_SPI=y
CONFIG_SPI_ASYNC=y
CONFIG_SPI_PL022_INTERRUPT=y
CONFIG_SPI_SLAVE=y

View File

@@ -1,44 +1,207 @@
#include <zephyr/kernel.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/spi.h>
#include <zephyr/sys/printk.h>
// SPI Master Interface on SPI1 of the rp2040
const struct device* spi1_dev = DEVICE_DT_GET(DT_NODELABEL(spi1));
/* 1000 msec = 1 sec */
#define SLEEP_TIME_MS 1000
// SPI but broken out
#define EPD_RST_PIN = 12;
#define EEPD_DC_PIN = 8;
#define EEPD_BUSY_PIN = 13;
#define EEPD_CS_PIN = 9;
#define EEPD_CLK_PIN = 10;
#define EEPD_MOSI_PIN = 11;
// GPIO - so we can have a status LED
/* The devicetree node identifier for the "led0" alias. */
#define LED0_NODE DT_ALIAS(led0)
#define MY_SPI_MASTER DT_NODELABEL(my_spi_master)
#define MY_SPI_SLAVE DT_NODELABEL(my_spi_slave)
// SPI master functionality
const struct device *spi_dev;
static struct k_poll_signal spi_done_sig = K_POLL_SIGNAL_INITIALIZER(spi_done_sig);
struct spi_cs_control spim_cs = {
.gpio = SPI_CS_GPIOS_DT_SPEC_GET(DT_NODELABEL(reg_my_spi_master)),
.delay = 0,
};
static void spi_init(void)
{
spi_dev = DEVICE_DT_GET(MY_SPI_MASTER);
if(!device_is_ready(spi_dev)) {
printk("SPI master device not ready!\n");
}
if(!device_is_ready(spim_cs.gpio.port)){
printk("SPI master chip select device not ready!\n");
}
}
static const struct spi_config spi_cfg = {
.operation = SPI_WORD_SET(8) | SPI_TRANSFER_MSB |
SPI_MODE_CPOL | SPI_MODE_CPHA,
.frequency = 4000000,
.slave = 0,
.cs = &spim_cs,
};
static int spi_write_test_msg(void)
{
static uint8_t counter = 0;
static uint8_t tx_buffer[2];
static uint8_t rx_buffer[2];
const struct spi_buf tx_buf = {
.buf = tx_buffer,
.len = sizeof(tx_buffer)
};
const struct spi_buf_set tx = {
.buffers = &tx_buf,
.count = 1
};
struct spi_buf rx_buf = {
.buf = rx_buffer,
.len = sizeof(rx_buffer),
};
const struct spi_buf_set rx = {
.buffers = &rx_buf,
.count = 1
};
// Update the TX buffer with a rolling counter
tx_buffer[0] = counter++;
printk("SPI TX: 0x%.2x, 0x%.2x\n", tx_buffer[0], tx_buffer[1]);
// Reset signal
k_poll_signal_reset(&spi_done_sig);
// Start transaction
int error = spi_transceive_async(spi_dev, &spi_cfg, &tx, &rx, &spi_done_sig);
if(error != 0){
printk("SPI transceive error: %i\n", error);
return error;
}
// Wait for the done signal to be raised and log the rx buffer
int spi_signaled, spi_result;
do{
k_poll_signal_check(&spi_done_sig, &spi_signaled, &spi_result);
} while(spi_signaled == 0);
printk("SPI RX: 0x%.2x, 0x%.2x\n", rx_buffer[0], rx_buffer[1]);
return 0;
}
// SPI slave functionality
const struct device *spi_slave_dev;
static struct k_poll_signal spi_slave_done_sig = K_POLL_SIGNAL_INITIALIZER(spi_slave_done_sig);
static const struct spi_config spi_slave_cfg = {
.operation = SPI_WORD_SET(8) | SPI_TRANSFER_MSB |
SPI_MODE_CPOL | SPI_MODE_CPHA | SPI_OP_MODE_SLAVE,
.frequency = 4000000,
.slave = 0,
};
static void spi_slave_init(void)
{
spi_slave_dev = DEVICE_DT_GET(MY_SPI_SLAVE);
if(!device_is_ready(spi_dev)) {
printk("SPI slave device not ready!\n");
}
}
static uint8_t slave_tx_buffer[2];
static uint8_t slave_rx_buffer[2];
static int spi_slave_write_test_msg(void)
{
static uint8_t counter = 0;
const struct spi_buf s_tx_buf = {
.buf = slave_tx_buffer,
.len = sizeof(slave_tx_buffer)
};
const struct spi_buf_set s_tx = {
.buffers = &s_tx_buf,
.count = 1
};
struct spi_buf s_rx_buf = {
.buf = slave_rx_buffer,
.len = sizeof(slave_rx_buffer),
};
const struct spi_buf_set s_rx = {
.buffers = &s_rx_buf,
.count = 1
};
// Update the TX buffer with a rolling counter
slave_tx_buffer[1] = counter++;
printk("SPI SLAVE TX: 0x%.2x, 0x%.2x\n", slave_tx_buffer[0], slave_tx_buffer[1]);
// Reset signal
k_poll_signal_reset(&spi_slave_done_sig);
// Start transaction
int error = spi_transceive_async(spi_slave_dev, &spi_slave_cfg, &s_tx, &s_rx, &spi_slave_done_sig);
if(error != 0){
printk("SPI slave transceive error: %i\n", error);
return error;
}
return 0;
}
static int spi_slave_check_for_message(void)
{
int signaled, result;
k_poll_signal_check(&spi_slave_done_sig, &signaled, &result);
if(signaled != 0){
return 0;
}
else return -1;
}
/*
* A build error on this line means your board is unsupported.
* See the sample documentation for information on how to fix this.
*/
static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(LED0_NODE, gpios);
void main(void)
{
while (!device_is_ready(spi1_dev)) {
}
int ret;
if (!device_is_ready(led.port)) {
return;
}
int ret = gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE);
ret = gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE);
if (ret < 0) {
return;
}
spi_init();
spi_slave_init();
printk("SPI master/slave example started\n");
spi_slave_write_test_msg();
while (1) {
spi_write_test_msg();
ret = gpio_pin_toggle_dt(&led);
if (ret < 0) {
printk("Error toggling LED pin\n");
return;
}
k_msleep(500);
}
}
k_msleep(SLEEP_TIME_MS);
if(spi_slave_check_for_message() == 0){
// Print the last received data
printk("SPI SLAVE RX: 0x%.2x, 0x%.2x\n", slave_rx_buffer[0], slave_rx_buffer[1]);
// Prepare the next SPI slave transaction
spi_slave_write_test_msg();
}
}
printk("SPI master/slave example finished\n");
}

1743
zephyr.hex Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.