[rtems commit] bsp/atsam: Fix SPI CS change support

Sebastian Huber sebh at rtems.org
Wed Mar 6 12:07:32 UTC 2019


Module:    rtems
Branch:    master
Commit:    847638af35486147880b803fc6f2c9b5dd17d6ec
Changeset: http://git.rtems.org/rtems/commit/?id=847638af35486147880b803fc6f2c9b5dd17d6ec

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Wed Mar  6 12:48:31 2019 +0100

bsp/atsam: Fix SPI CS change support

The previous approach contained a severe bug which disabled the SPI
module in some cases leading to a blocked SPI bus.

---

 bsps/arm/atsam/spi/atsam_spi_bus.c | 52 +++++++++-----------------------------
 1 file changed, 12 insertions(+), 40 deletions(-)

diff --git a/bsps/arm/atsam/spi/atsam_spi_bus.c b/bsps/arm/atsam/spi/atsam_spi_bus.c
index 20cba79..a9d1366 100644
--- a/bsps/arm/atsam/spi/atsam_spi_bus.c
+++ b/bsps/arm/atsam/spi/atsam_spi_bus.c
@@ -56,9 +56,7 @@ struct atsam_spi_xdma_buf {
 typedef struct {
   spi_bus base;
   rtems_binary_semaphore sem;
-  bool msg_cs_change;
   const spi_ioc_transfer *msg_current;
-  const spi_ioc_transfer *msg_next;
   uint32_t msg_todo;
   int msg_error;
   Spi *spi_regs;
@@ -68,7 +66,6 @@ typedef struct {
   size_t leadbuf_rx_buffered_len;
   size_t trailbuf_rx_buffered_len;
   int transfer_in_progress;
-  bool chip_select_active;
   bool chip_select_decode;
   uint8_t spi_id;
   uint32_t peripheral_clk_per_us;
@@ -320,27 +317,6 @@ static void atsam_spi_start_dma_transfer(
   XDMAC_StartTransfer(pXdmac, bus->dma_tx_channel);
 }
 
-static void atsam_spi_do_transfer(
-  atsam_spi_bus *bus,
-  const spi_ioc_transfer *msg
-)
-{
-  if (!bus->chip_select_active){
-    Spi *spi_regs = bus->spi_regs;
-
-    bus->chip_select_active = true;
-
-    if (bus->chip_select_decode) {
-      spi_regs->SPI_MR = (spi_regs->SPI_MR & ~SPI_MR_PCS_Msk) | SPI_MR_PCS(msg->cs);
-    } else {
-      SPI_ChipSelect(spi_regs, 1 << msg->cs);
-    }
-    SPI_Enable(spi_regs);
-  }
-
-  atsam_spi_start_dma_transfer(bus, msg);
-}
-
 static int atsam_check_configure_spi(atsam_spi_bus *bus, const spi_ioc_transfer *msg)
 {
   if (
@@ -374,24 +350,14 @@ static void atsam_spi_setup_transfer(atsam_spi_bus *bus)
 
   bus->transfer_in_progress = 2;
 
-  if (bus->msg_cs_change) {
-    bus->chip_select_active = false;
-    SPI_ReleaseCS(bus->spi_regs);
-    SPI_Disable(bus->spi_regs);
-  }
-
   if (msg_todo > 0) {
-    const spi_ioc_transfer *msg = bus->msg_next;
+    const spi_ioc_transfer *msg;
     int error;
 
-    bus->msg_cs_change = msg->cs_change;
-    bus->msg_next = msg + 1;
-    bus->msg_current = msg;
-    bus->msg_todo = msg_todo - 1;
-
+    msg = bus->msg_current;
     error = atsam_check_configure_spi(bus, msg);
     if (error == 0) {
-      atsam_spi_do_transfer(bus, msg);
+      atsam_spi_start_dma_transfer(bus, msg);
     } else {
       bus->msg_error = error;
       atsam_spi_wakeup_task(bus);
@@ -424,7 +390,15 @@ static void atsam_spi_dma_callback(uint32_t channel, void *arg)
       bus->spi_regs->SPI_MR = mr;
     }
 
+    if (msg->cs_change) {
+      bus->spi_regs->SPI_CR = SPI_CR_LASTXFER;
+    }
+
     atsam_spi_copy_back_rx_after_dma_transfer(bus);
+
+    bus->msg_current = msg + 1;
+    --bus->msg_todo;
+
     atsam_spi_setup_transfer(bus);
   }
 }
@@ -437,9 +411,7 @@ static int atsam_spi_transfer(
 {
   atsam_spi_bus *bus = (atsam_spi_bus *)base;
 
-  bus->msg_cs_change = false;
-  bus->msg_next = &msgs[0];
-  bus->msg_current = NULL;
+  bus->msg_current = msgs;
   bus->msg_todo = msg_count;
   bus->msg_error = 0;
   atsam_spi_setup_transfer(bus);




More information about the vc mailing list