Skip to content
This repository has been archived by the owner on Feb 9, 2024. It is now read-only.

SPI CS fix from Zephyr patch #53

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
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
123 changes: 76 additions & 47 deletions fw/src/app/spi.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,63 +12,77 @@ static pi_to_hat_t pi_to_hat;
static hat_to_pi_t hat_to_pi;

typedef struct fifo_item_t {
void *fifo_reserved; /* 1st word reserved for use by fifo */
pi_to_hat_t msg;
void *fifo_reserved; /* 1st word reserved for use by fifo */
pi_to_hat_t msg;
} fifo_item_t;

fifo_item_t fifo_rx_queue;

K_FIFO_DEFINE(my_fifo);

// Read message received from the pi out of the FIFO
// Call not thread safe. Run from one thread at a time.
// Returned message buffer must be freed after processing is done.
int wait_for_pi_message(pi_to_hat_t* msg, int32_t timeout)
{
fifo_item_t *rx_data = k_fifo_get(&my_fifo, timeout);
if (rx_data == NULL)
return -1;
if (rx_data == NULL)
return -1;

// shallow copy ok?
*msg = rx_data->msg;
*msg = rx_data->msg;
k_free(rx_data);
return 0;
return 0;
}

void spi_task(void)
// Zephyr thread to read and write data over the
// SPI bus to/from the pi.
void spi_task(void)
{
struct device *spi;
struct spi_config spi_cfg;
struct spi_cs_control spi_cs;

spi = device_get_binding("SPI_1");
if (!spi)
{
LOG_ERR("Could not find SPI driver\n");
return;
}

spi_cfg.operation = SPI_WORD_SET(8) | SPI_OP_MODE_SLAVE;
spi_cfg.frequency = 25000000;

spi_cs.gpio_dev = device_get_binding(DT_INST_0_ST_STM32_SPI_CS_GPIOS_CONTROLLER);
spi_cs.gpio_pin = DT_INST_0_ST_STM32_SPI_CS_GPIOS_PIN;
spi_cs.delay = 0;
spi_cfg.cs = &spi_cs;

LOG_INF("SPI interface listening");

const struct spi_buf tx_buf = {
.buf = &hat_to_pi,
.len = sizeof(hat_to_pi)
};
const struct spi_buf rx_buf =
{
.buf = &pi_to_hat,
.len = sizeof(pi_to_hat)
};
const struct spi_buf_set tx = { .buffers = &tx_buf, .count = 1 };
const struct spi_buf_set rx = { .buffers = &rx_buf, .count = 1 };

while(true)
{
struct device *spi;
struct spi_config spi_cfg;
struct spi_cs_control spi_cs;
int spi_trancieve_ret = 0;

// Get SPI device binding from Zephyr device tree
spi = device_get_binding("SPI_1");
if (!spi)
{
LOG_ERR("Could not find SPI driver\n");
return;
}

// Set-up config struct for SPI
// Note: using custom patch for Zephyr 2.1 SPI driver to correct operation
// in slave mode. OS upgrades will need the patch implemented in spi_ll_stm32.c
// and spi_context.h. spi_cfg.cs must be set for patch to work correctly.
spi_cfg.operation = SPI_WORD_SET(8) | SPI_OP_MODE_SLAVE;
spi_cfg.frequency = 25000000;

spi_cs.gpio_dev = device_get_binding(DT_INST_0_ST_STM32_SPI_CS_GPIOS_CONTROLLER);
spi_cs.gpio_pin = DT_INST_0_ST_STM32_SPI_CS_GPIOS_PIN;
spi_cs.delay = 0;
spi_cfg.cs = &spi_cs;

LOG_INF("SPI interface listening");

// Init Rx and Tx buffers
const struct spi_buf tx_buf = {
.buf = &hat_to_pi,
.len = sizeof(hat_to_pi)
};
const struct spi_buf rx_buf =
{
.buf = &pi_to_hat,
.len = sizeof(pi_to_hat)
};
const struct spi_buf_set tx = { .buffers = &tx_buf, .count = 1 };
const struct spi_buf_set rx = { .buffers = &rx_buf, .count = 1 };

// Infinite loop in dedicated thread to transfer data over SPI bus
while(true)
{
// Fill Tx buff with message for PI
memset(&pi_to_hat, 0, sizeof(pi_to_hat)); // 8 bytes from Raspberry Pi (Tx)
memset(&hat_to_pi, 0, sizeof(hat_to_pi)); // 8 bytes to Raspberry Pi (Rx)

Expand All @@ -80,18 +94,33 @@ void spi_task(void)
// tx: outbound (button state and joystick positions)
// rx: incoming (command verbs)

if (spi_transceive(spi, &spi_cfg, &tx, &rx) > 0)
{
// Send and recieve data from the Pi. No limit on wait length.
spi_trancieve_ret = spi_transceive(spi, &spi_cfg, &tx, &rx);

// Process transfer results
if(spi_trancieve_ret != sizeof(pi_to_hat))
{
// did not recieve full length packet or an error was encountered
// in the SPI driver during the transfer

if(spi_trancieve_ret >= 0) // was the data the wrong length?
LOG_INF("Recieved %d bytes from pi but expected %d.", spi_trancieve_ret, sizeof(pi_to_hat));
else // Internal SPI driver error
LOG_ERR("Pi-Hat spi_transceive() returned with error: %d", spi_trancieve_ret);
}
else
{
// Valid packet was recieved. Put on FIFO queue for later processing.
size_t size = sizeof(fifo_item_t);
fifo_item_t *ptr = (fifo_item_t *) k_malloc(size);
__ASSERT_NO_MSG(ptr != 0);

ptr->fifo_reserved = 0x0; // don't care
memcpy(&ptr->msg, &pi_to_hat, sizeof(pi_to_hat));

k_fifo_put(&my_fifo, ptr);
}
}
k_fifo_put(&my_fifo, ptr);
}
}
}

K_THREAD_DEFINE(spi_task_id, STACKSIZE, spi_task, NULL, NULL, NULL, PRIORITY, 0, K_NO_WAIT);
1 change: 1 addition & 0 deletions fw/src/doit
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ install() {

echo "Installing $DEST/$FN on moab"
scp "$DEST/$FN" moab:$FN || echo "scp copy to moab failed"
sleep 5
ssh moab "sudo moab/bin/flash /home/pi/$FN"
fi
}
Expand Down
2 changes: 1 addition & 1 deletion fw/src/prj.conf
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ CONFIG_SPI_INIT_PRIORITY=70
CONFIG_SPI_0=y
CONFIG_SPI_0_OP_MODES=1
CONFIG_SPI_1=y
CONFIG_SPI_1_OP_MODES=1
CONFIG_SPI_1_OP_MODES=2
CONFIG_SPI_2=y
CONFIG_SPI_2_OP_MODES=1
CONFIG_SPI_STM32_INTERRUPT=y
Expand Down