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

Commit

Permalink
v3.0.30 (#54)
Browse files Browse the repository at this point in the history
Fixes intermittent firmware crash due to SPI controller/peripheral
problem. Specifically SPI chip select (CS) isn't working in Zephyr 2.1
for devices set to peripheral mode, only controller mode.

So both Raspberry Pi and the STM32 Moab Hat were both asserting the CS
bus, causing an intermittent and difficult bug to track down.

Co-authored-by: Peter Cornwell <[email protected]>
  • Loading branch information
scotstan and Solheim86 authored Apr 7, 2021
1 parent 12ec182 commit 8f5b50c
Show file tree
Hide file tree
Showing 7 changed files with 42 additions and 10 deletions.
35 changes: 33 additions & 2 deletions fw/src/app/spi.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ 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);
Expand All @@ -32,24 +35,33 @@ int wait_for_pi_message(pi_to_hat_t* msg, int32_t timeout)
return 0;
}

// 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;
int spi_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_cfg.cs = NULL;

LOG_INF("SPI interface CS hardware mode");

// Init Rx and Tx buffers
const struct spi_buf tx_buf = {
.buf = &hat_to_pi,
.len = sizeof(hat_to_pi)
Expand All @@ -62,9 +74,11 @@ void spi_task(void)
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)
{
memset(&pi_to_hat, 0, sizeof(pi_to_hat)); // 8 bytes from Raspberry Pi (Tx)
// 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)

hat_to_pi.menu_button = atomic_get(&g_btn_menu);
Expand All @@ -75,8 +89,25 @@ 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_ret >= 0 is number of bytes received, else
// spi_ret will be a negative errno code
spi_ret = spi_transceive(spi, &spi_cfg, &tx, &rx);

// Process transfer results
if(spi_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_ret >= 0) // was the data the wrong length?
LOG_INF("Got %d bytes from pi but expected %d.", spi_ret, sizeof(pi_to_hat));
else // Internal SPI driver error
LOG_ERR("spi_transceive() error: %d", spi_ret);
}
else
{
// Valid packet was received. 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);
Expand Down
7 changes: 5 additions & 2 deletions fw/src/doit
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,11 @@ exec 2> >(tee "/tmp/stderr.log")
# 3.0.25: Possible fix for critical SPI chip-select contention (controller vs peripheral)
# 3.0.27: applying peter's CS fix
# 3.0.28: spi_cfg.cs = NULL attempt
# 3.0.29: skip
# 3.0.30: Zephyr 2.1 patch for SPI CS peripheral mode
# " ": compile against Zephyr 2.1 from this fork: https://github.com/scotstan/zephyr/tree/Moabian_SPI_v3_fixes

VERSION="3.0.28"
VERSION="3.0.30"

# YRDDDHR: 2103908. 2021, 39th day of the year, 08th hour (PDT)
TIMESTAMP=$(TZ='America/Los_Angeles' date +"%j%H%M")
Expand Down Expand Up @@ -82,7 +85,7 @@ install() {

echo "Installing $DEST/$FN on moab"
scp "$DEST/$FN" moab:$FN || echo "scp copy to moab failed"
sleep 1
sleep 5
ssh moab "sudo moab/bin/flash /home/pi/$FN"
fi
}
Expand Down
4 changes: 1 addition & 3 deletions fw/src/prj.conf
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,8 @@ CONFIG_SPI=y
CONFIG_SPI_STM32=y
CONFIG_SPI_SLAVE=y
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
Binary file modified fw/v3.bin
Binary file not shown.
2 changes: 1 addition & 1 deletion os/files/etc/environment
Original file line number Diff line number Diff line change
@@ -1 +1 @@
MOABIAN=3.0.28
MOABIAN=3.0.30
2 changes: 1 addition & 1 deletion os/services/menu.service
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ DefaultDependencies=false
After=dhcpd.service

[Service]
Environment="MOABIAN=3.0.28"
Environment="MOABIAN=3.0.30"
Environment="PYTHONUNBUFFERED=1"
WorkingDirectory=/home/pi/moab/sw
ExecStart=/usr/bin/python3 menu.py --debug --verbose --reset
Expand Down
2 changes: 1 addition & 1 deletion sw/menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ def _handle_debug(ctx, param, debug):


@click.command()
@click.version_option(version="3.0.28")
@click.version_option(version="3.0.30")
@click.option(
"-c",
"--cont",
Expand Down

0 comments on commit 8f5b50c

Please sign in to comment.