super epic SPI
This commit is contained in:
@@ -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)
|
||||
|
||||
21
Makefile
21
Makefile
@@ -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/
|
||||
|
||||
63
boards/nrf52840dk_nrf52840.overlay
Normal file
63
boards/nrf52840dk_nrf52840.overlay
Normal 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";
|
||||
};
|
||||
6
prj.conf
6
prj.conf
@@ -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
|
||||
|
||||
199
src/main.c
199
src/main.c
@@ -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
1743
zephyr.hex
Normal file
File diff suppressed because it is too large
Load Diff
BIN
zephyr.uf2
BIN
zephyr.uf2
Binary file not shown.
Reference in New Issue
Block a user