onegray commented on code in PR #6492:
URL: https://github.com/apache/incubator-nuttx/pull/6492#discussion_r905411368


##########
arch/arm/src/stm32wl5/stm32wl5_spi.c:
##########
@@ -0,0 +1,1858 @@
+/****************************************************************************
+ * arch/arm/src/stm32wl5/stm32wl5_spi.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * The external functions, stm32wl5_spi1/2select and stm32wl5_spi1/2status
+ * must be provided by board-specific logic.  They are implementations of the
+ * select and status methods of the SPI interface defined by struct spi_ops_s
+ * (see include/nuttx/spi/spi.h).
+ * All other methods (including stm32wl5_spibus_initialize())  are provided
+ * by common STM32 logic.  To use this common SPI logic on your board:
+ *
+ *   1. Provide logic in stm32wl5_boardinitialize() to configure SPI chip
+ *      select pins.
+ *   2. Provide stm32wl5_spi1/2select() and stm32wl5_spi1/2() functions
+ *      in your board-specific logic.  These functions will perform chip
+ *      selection and status operations using GPIOs in the way your board is
+ *      configured.
+ *   3. Add a calls to stm32wl5_spibus_initialize() in your low level
+ *      application initialization logic
+ *   4. The handle returned by stm32wl5_spibus_initialize() may then be used
+ *      to bind the SPI driver to higher level logic (e.g., calling
+ *      mmcsd_spislotinitialize(), for example, will bind the SPI driver to
+ *      the SPI MMC/SD driver).
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/irq.h>
+#include <nuttx/arch.h>
+#include <nuttx/semaphore.h>
+#include <nuttx/spi/spi.h>
+
+#include <arch/board/board.h>
+
+#include "arm_internal.h"
+#include "chip.h"
+#include "stm32wl5.h"
+#include "stm32wl5_gpio.h"
+#ifdef CONFIG_STM32WL5_SPI_DMA
+#include "stm32wl5_dma.h"
+#endif
+#include "stm32wl5_spi.h"
+
+#if defined(CONFIG_STM32WL5_SPI1) || defined(CONFIG_STM32WL5_SPI2S2)
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Configuration ************************************************************/
+
+/* SPI interrupts */
+
+#ifdef CONFIG_STM32WL5_SPI_INTERRUPTS
+#  error "Interrupt driven SPI not yet supported"
+#endif
+
+#ifdef CONFIG_STM32WL5_SPI_DMA
+#  error "DMA driven SPI not yet supported"
+#endif
+
+/* Can't have both interrupt driven SPI and SPI DMA */
+
+#if defined(CONFIG_STM32WL5_SPI_INTERRUPTS) && defined(CONFIG_STM32WL5_SPI_DMA)
+#  error "Cannot enable both interrupt mode and DMA mode for SPI"
+#endif
+
+/* SPI DMA priority */
+
+#ifdef CONFIG_STM32WL5_SPI_DMA
+
+#  if defined(CONFIG_SPI_DMAPRIO)
+#    define SPI_DMA_PRIO  CONFIG_SPI_DMAPRIO
+#  elif defined(CONFIG_STM32WL5_STM32WL5XXX_CPU1
+#warning "Verify, read doc and Implement"
+#    define SPI_DMA_PRIO  DMA_CCR_PRIMED
+#  else
+#    error "Unknown STM32WL5 DMA"
+#  endif
+
+#  if defined(CONFIG_STM32WL5_STM32WL5XXX_CPU1)
+#    if (SPI_DMA_PRIO & ~DMA_CCR_PL_MASK) != 0
+#      error "Illegal value for CONFIG_SPI_DMAPRIO"
+#    endif
+#  else
+#    error "Unknown STM32 DMA"
+#  endif
+
+/* DMA channel configuration */
+
+#if defined(CONFIG_STM32WL5_STM32WL5XXX_CPU1)
+#  define SPI_RXDMA16_CONFIG        
(SPI_DMA_PRIO|DMA_CCR_MSIZE_16BITS|DMA_CCR_PSIZE_16BITS|DMA_CCR_MINC            
)
+#  define SPI_RXDMA8_CONFIG         (SPI_DMA_PRIO|DMA_CCR_MSIZE_8BITS 
|DMA_CCR_PSIZE_8BITS |DMA_CCR_MINC            )
+#  define SPI_RXDMA16NULL_CONFIG    (SPI_DMA_PRIO|DMA_CCR_MSIZE_8BITS 
|DMA_CCR_PSIZE_16BITS                         )
+#  define SPI_RXDMA8NULL_CONFIG     (SPI_DMA_PRIO|DMA_CCR_MSIZE_8BITS 
|DMA_CCR_PSIZE_8BITS                          )
+#  define SPI_TXDMA16_CONFIG        
(SPI_DMA_PRIO|DMA_CCR_MSIZE_16BITS|DMA_CCR_PSIZE_16BITS|DMA_CCR_MINC|DMA_CCR_DIR)
+#  define SPI_TXDMA8_CONFIG         (SPI_DMA_PRIO|DMA_CCR_MSIZE_8BITS 
|DMA_CCR_PSIZE_8BITS |DMA_CCR_MINC|DMA_CCR_DIR)
+#  define SPI_TXDMA16NULL_CONFIG    (SPI_DMA_PRIO|DMA_CCR_MSIZE_8BITS 
|DMA_CCR_PSIZE_16BITS             |DMA_CCR_DIR)
+#  define SPI_TXDMA8NULL_CONFIG     (SPI_DMA_PRIO|DMA_CCR_MSIZE_8BITS 
|DMA_CCR_PSIZE_8BITS              |DMA_CCR_DIR)
+#else
+#  error "Unknown STM32WL5 DMA"
+#endif
+
+#  define SPIDMA_BUFFER_MASK   (4 - 1)
+#  define SPIDMA_SIZE(b) (((b) + SPIDMA_BUFFER_MASK) & ~SPIDMA_BUFFER_MASK)
+#  define SPIDMA_BUF_ALIGN   aligned_data(4)
+
+#  if defined(CONFIG_STM32WL5_SPI1_DMA_BUFFER) && \
+            CONFIG_STM32WL5_SPI1_DMA_BUFFER > 0
+#    define SPI1_DMABUFSIZE_ADJUSTED 
SPIDMA_SIZE(CONFIG_STM32WL5_SPI1_DMA_BUFFER)
+#    define SPI1_DMABUFSIZE_ALGN SPIDMA_BUF_ALIGN
+#  endif
+
+#  if defined(CONFIG_STM32WL5_SPI2S2_DMA_BUFFER) && \
+            CONFIG_STM32WL5_SPI2S2_DMA_BUFFER > 0
+#    define SPI2S2_DMABUFSIZE_ADJUSTED 
SPIDMA_SIZE(CONFIG_STM32WL5_SPI2S2_DMA_BUFFER)
+#    define SPI2S2_DMABUFSIZE_ALGN SPIDMA_BUF_ALIGN
+#  endif
+
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct stm32wl5_spidev_s
+{
+  struct spi_dev_s spidev;       /* Externally visible part of the SPI 
interface */
+  uint32_t         spibase;      /* SPIn base address */
+  uint32_t         spiclock;     /* Clocking for the SPI module */
+#ifdef CONFIG_STM32WL5_SPI_INTERRUPTS
+  uint8_t          spiirq;       /* SPI IRQ number */
+#endif
+#ifdef CONFIG_STM32WL5_SPI_DMA
+  volatile uint8_t rxresult;     /* Result of the RX DMA */
+  volatile uint8_t txresult;     /* Result of the RX DMA */
+#ifdef CONFIG_SPI_TRIGGER
+  bool             defertrig;    /* Flag indicating that trigger should be 
deferred */
+  bool             trigarmed;    /* Flag indicating that the trigger is armed 
*/
+#endif
+  uint8_t          rxch;         /* The RX DMA channel number */
+  uint8_t          txch;         /* The TX DMA channel number */
+  uint8_t          *rxbuf;       /* The RX DMA buffer */
+  uint8_t          *txbuf;       /* The TX DMA buffer */
+  size_t           buflen;       /* The DMA buffer length */
+  DMA_HANDLE       rxdma;        /* DMA channel handle for RX transfers */
+  DMA_HANDLE       txdma;        /* DMA channel handle for TX transfers */
+  sem_t            rxsem;        /* Wait for RX DMA to complete */
+  sem_t            txsem;        /* Wait for TX DMA to complete */
+  uint32_t         txccr;        /* DMA control register for TX transfers */
+  uint32_t         rxccr;        /* DMA control register for RX transfers */
+#endif
+  bool             initialized;  /* Has SPI interface been initialized */
+  sem_t            exclsem;      /* Held while chip is selected for mutual 
exclusion */
+  uint32_t         frequency;    /* Requested clock frequency */
+  uint32_t         actual;       /* Actual clock frequency */
+  uint8_t          nbits;        /* Width of word in bits (4 through 16) */
+  uint8_t          mode;         /* Mode 0,1,2,3 */
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* Helpers */
+
+static inline uint16_t spi_getreg(struct stm32wl5_spidev_s *priv,
+                                  uint8_t offset);
+
+static inline uint8_t spi_getreg8(struct stm32wl5_spidev_s *priv,
+                                  uint8_t offset);
+
+static inline void spi_putreg(struct stm32wl5_spidev_s *priv,
+                              uint8_t offset,
+                              uint16_t value);
+
+static inline void spi_putreg8(struct stm32wl5_spidev_s *priv,
+                              uint8_t offset,
+                              uint8_t value);
+
+static inline uint16_t spi_readword(struct stm32wl5_spidev_s *priv);
+static inline void spi_writeword(struct stm32wl5_spidev_s *priv,
+                                 uint16_t byte);
+
+/* DMA support */
+
+#ifdef CONFIG_STM32WL5_SPI_DMA
+static int         spi_dmarxwait(struct stm32wl5_spidev_s *priv);
+static int         spi_dmatxwait(struct stm32wl5_spidev_s *priv);
+static inline void spi_dmarxwakeup(struct stm32wl5_spidev_s *priv);
+static inline void spi_dmatxwakeup(struct stm32wl5_spidev_s *priv);
+static void        spi_dmarxcallback(DMA_HANDLE handle, uint8_t isr,
+                                     void *arg);
+static void        spi_dmatxcallback(DMA_HANDLE handle, uint8_t isr,
+                                     void *arg);
+static void        spi_dmarxsetup(struct stm32wl5_spidev_s *priv,
+                                  void *rxbuffer,
+                                  void *rxdummy,
+                                  size_t nwords);
+static void        spi_dmatxsetup(struct stm32wl5_spidev_s *priv,
+                                  const void *txbuffer,
+                                  const void *txdummy,
+                                  size_t nwords);
+static inline void spi_dmarxstart(struct stm32wl5_spidev_s *priv);
+static inline void spi_dmatxstart(struct stm32wl5_spidev_s *priv);
+#endif
+
+/* SPI methods */
+
+static int         spi_lock(struct spi_dev_s *dev, bool lock);
+static uint32_t    spi_setfrequency(struct spi_dev_s *dev,
+                                    uint32_t frequency);
+static void        spi_setmode(struct spi_dev_s *dev,
+                               enum spi_mode_e mode);
+static void        spi_setbits(struct spi_dev_s *dev, int nbits);
+#ifdef CONFIG_SPI_HWFEATURES
+static int         spi_hwfeatures(struct spi_dev_s *dev,
+                                  spi_hwfeatures_t features);
+#endif
+static uint32_t    spi_send(struct spi_dev_s *dev, uint32_t wd);
+static void        spi_exchange(struct spi_dev_s *dev,
+                                const void *txbuffer,
+                                void *rxbuffer, size_t nwords);
+#ifdef CONFIG_SPI_TRIGGER
+static int         spi_trigger(struct spi_dev_s *dev);
+#endif
+#ifndef CONFIG_SPI_EXCHANGE
+static void        spi_sndblock(struct spi_dev_s *dev,
+                                const void *txbuffer,
+                                size_t nwords);
+static void        spi_recvblock(struct spi_dev_s *dev,
+                                 void *rxbuffer,
+                                 size_t nwords);
+#endif
+
+/* Initialization */
+
+static void        spi_bus_initialize(struct stm32wl5_spidev_s *priv);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+#ifdef CONFIG_STM32WL5_SPI1
+static const struct spi_ops_s g_sp1iops =
+{
+  .lock              = spi_lock,
+  .select            = stm32wl5_spi1select,
+  .setfrequency      = spi_setfrequency,
+  .setmode           = spi_setmode,
+  .setbits           = spi_setbits,
+#ifdef CONFIG_SPI_HWFEATURES
+  .hwfeatures        = spi_hwfeatures,
+#endif
+  .status            = stm32wl5_spi1status,
+#ifdef CONFIG_SPI_CMDDATA
+  .cmddata           = stm32wl5_spi1cmddata,
+#endif
+  .send              = spi_send,
+#ifdef CONFIG_SPI_EXCHANGE
+  .exchange          = spi_exchange,
+#else
+  .sndblock          = spi_sndblock,
+  .recvblock         = spi_recvblock,
+#endif
+#ifdef CONFIG_SPI_TRIGGER
+  .trigger           = spi_trigger,
+#endif
+#ifdef CONFIG_SPI_CALLBACK
+  .registercallback  = stm32wl5_spi1register,  /* Provided externally */
+#else
+  .registercallback  = 0,                   /* Not implemented */
+#endif
+};
+
+#if defined(SPI1_DMABUFSIZE_ADJUSTED)
+static uint8_t g_spi1_txbuf[SPI1_DMABUFSIZE_ADJUSTED] SPI1_DMABUFSIZE_ALGN;
+static uint8_t g_spi1_rxbuf[SPI1_DMABUFSIZE_ADJUSTED] SPI1_DMABUFSIZE_ALGN;
+#endif
+
+static struct stm32wl5_spidev_s g_spi1dev =
+{
+  .spidev   =
+              {
+               &g_sp1iops
+              },
+  .spibase  = STM32WL5_SPI1_BASE,
+  .spiclock = STM32WL5_PCLK2_FREQUENCY,
+#ifdef CONFIG_STM32WL5_SPI_INTERRUPTS
+  .spiirq   = STM32WL5_IRQ_SPI1,
+#endif
+#ifdef CONFIG_STM32WL5_SPI_DMA
+#  ifdef CONFIG_STM32WL5_SPI1_DMA
+  .rxch     = DMACHAN_SPI1_RX,
+  .txch     = DMACHAN_SPI1_TX,
+#if defined(SPI1_DMABUFSIZE_ADJUSTED)
+  .rxbuf    = g_spi1_rxbuf,
+  .txbuf    = g_spi1_txbuf,
+  .buflen   = SPI1_DMABUFSIZE_ADJUSTED,
+#    endif
+#  else
+  .rxch     = 0,
+  .txch     = 0,
+#  endif
+#endif
+};
+#endif
+
+#ifdef CONFIG_STM32WL5_SPI2S2
+static const struct spi_ops_s g_sp2iops =
+{
+  .lock              = spi_lock,
+  .select            = stm32wl5_spi2s2select,
+  .setfrequency      = spi_setfrequency,
+  .setmode           = spi_setmode,
+  .setbits           = spi_setbits,
+#ifdef CONFIG_SPI_HWFEATURES
+  .hwfeatures        = spi_hwfeatures,
+#endif
+  .status            = stm32wl5_spi2s2status,
+#ifdef CONFIG_SPI_CMDDATA
+  .cmddata           = stm32wl5_spi2s2cmddata,
+#endif
+  .send              = spi_send,
+#ifdef CONFIG_SPI_EXCHANGE
+  .exchange          = spi_exchange,
+#else
+  .sndblock          = spi_sndblock,
+  .recvblock         = spi_recvblock,
+#endif
+#ifdef CONFIG_SPI_TRIGGER
+  .trigger           = spi_trigger,
+#endif
+#ifdef CONFIG_SPI_CALLBACK
+  .registercallback  = stm32wl5_s2register,  /* provided externally */
+#else
+  .registercallback  = 0,                   /* not implemented */
+#endif
+};
+
+#if defined(SPI2S2_DMABUFSIZE_ADJUSTED)
+static uint8_t g_spi2s2_txbuf[SPI2S2_DMABUFSIZE_ADJUSTED]
+  SPI2S2_DMABUFSIZE_ALGN;
+static uint8_t g_spi2s2_rxbuf[SPI2S2_DMABUFSIZE_ADJUSTED]
+  SPI2S2_DMABUFSIZE_ALGN;
+#endif
+
+static struct stm32wl5_spidev_s g_spi2s2dev =
+{
+  .spidev   =
+              {
+               &g_sp2iops
+              },
+  .spibase  = STM32WL5_SPI2S2_BASE,
+  .spiclock = STM32WL5_PCLK1_FREQUENCY,
+#ifdef CONFIG_STM32WL5_SPI_INTERRUPTS
+  .spiirq   = STM32WL5_IRQ_SPI2S2,
+#endif
+#ifdef CONFIG_STM32WL5_SPI_DMA
+#  ifdef CONFIG_STM32WL5_SPI2S2_DMA
+  .rxch     = DMACHAN_SPI2S2_RX,
+  .txch     = DMACHAN_SPI2S2_TX,
+#if defined(SPI2S2_DMABUFSIZE_ADJUSTED)
+  .rxbuf    = g_spi2s2_rxbuf,
+  .txbuf    = g_spi2s2_txbuf,
+  .buflen   = SPI2S2_DMABUFSIZE_ADJUSTED,
+#    endif
+#  else
+  .rxch     = 0,
+  .txch     = 0,
+#  endif
+#endif
+};
+#endif
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: spi_getreg8
+ *
+ * Description:
+ *   Get the contents of the SPI register at offset
+ *
+ * Input Parameters:
+ *   priv   - private SPI device structure
+ *   offset - offset to the register of interest
+ *
+ * Returned Value:
+ *   The contents of the 16-bit register
+ *
+ ****************************************************************************/
+
+static inline uint8_t spi_getreg8(struct stm32wl5_spidev_s *priv,
+                                  uint8_t offset)
+{
+  return getreg8(priv->spibase + offset);
+}
+
+/****************************************************************************
+ * Name: spi_getreg
+ *
+ * Description:
+ *   Get the contents of the SPI register at offset
+ *
+ * Input Parameters:
+ *   priv   - private SPI device structure
+ *   offset - offset to the register of interest
+ *
+ * Returned Value:
+ *   The contents of the 16-bit register
+ *
+ ****************************************************************************/
+
+static inline uint16_t spi_getreg(struct stm32wl5_spidev_s *priv,
+                                  uint8_t offset)
+{
+  return getreg16(priv->spibase + offset);
+}
+
+/****************************************************************************
+ * Name: spi_putreg
+ *
+ * Description:
+ *   Write a 16-bit value to the SPI register at offset
+ *
+ * Input Parameters:
+ *   priv   - private SPI device structure
+ *   offset - offset to the register of interest
+ *   value  - the 16-bit value to be written
+ *
+ * Returned Value:
+ *   The contents of the 16-bit register
+ *
+ ****************************************************************************/
+
+static inline void spi_putreg(struct stm32wl5_spidev_s *priv,
+                              uint8_t offset,
+                              uint16_t value)
+{
+  putreg16(value, priv->spibase + offset);
+}
+
+/****************************************************************************
+ * Name: spi_putreg8
+ *
+ * Description:
+ *   Write an 8-bit value to the SPI register at offset
+ *
+ * Input Parameters:
+ *   priv   - private SPI device structure
+ *   offset - offset to the register of interest
+ *   value  - the 16-bit value to be written
+ *
+ * Returned Value:
+ *   The contents of the 16-bit register
+ *
+ ****************************************************************************/
+
+static inline void spi_putreg8(struct stm32wl5_spidev_s *priv,
+                               uint8_t offset,
+                               uint8_t value)
+{
+  putreg8(value, priv->spibase + offset);
+}
+
+/****************************************************************************
+ * Name: spi_readword
+ *
+ * Description:
+ *   Read one byte from SPI
+ *
+ * Input Parameters:
+ *   priv - Device-specific state data
+ *
+ * Returned Value:
+ *   Byte as read
+ *
+ ****************************************************************************/
+
+static inline uint16_t spi_readword(struct stm32wl5_spidev_s *priv)
+{
+  /* Wait until the receive buffer is not empty */
+
+  while ((spi_getreg(priv, STM32WL5_SPI_SR_OFFSET) & SPI_SR_RXNE) == 0)
+    {
+    }
+
+  /* Then return the received byte */
+
+  /* "When the data frame size fits into one byte
+   * (less than or equal to 8 bits),
+   *  data packing is used automatically when any read or write 16-bit access
+   *  is performed on the SPIx_DR register. The double data frame pattern is
+   *  handled in parallel in this case. At first, the SPI operates using the
+   *  pattern stored in the LSB of the accessed word, then with the other
+   *  half stored in the MSB.... The receiver then has to access both data
+   *  frames by a single 16-bit read of SPIx_DR as a response to this single
+   *  RXNE event. The RxFIFO threshold setting and the following read access
+   *  must be always kept aligned at the receiver side, as data can be lost
+   *  if it is not in line."
+   */
+
+  if (priv->nbits < 9)
+    {
+      return (uint16_t)spi_getreg8(priv, STM32WL5_SPI_DR_OFFSET);
+    }
+  else
+    {
+      return spi_getreg(priv, STM32WL5_SPI_DR_OFFSET);
+    }
+}
+
+/****************************************************************************
+ * Name: spi_writeword
+ *
+ * Description:
+ *   Write one word or byte to SPI. If the frame size is 8 bit or lower
+ *   a byte is written. In other case a word is written.
+ *
+ * Input Parameters:
+ *   priv - Device-specific state data
+ *   word - word to send
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static inline void spi_writeword(struct stm32wl5_spidev_s *priv,
+                                 uint16_t word)
+{
+  /* Wait until the transmit buffer is empty */
+
+  while ((spi_getreg(priv, STM32WL5_SPI_SR_OFFSET) & SPI_SR_TXE) == 0)
+    {
+    }
+
+  /* Then send the word */
+
+  if (priv->nbits < 9)
+    {
+      spi_putreg8(priv, STM32WL5_SPI_DR_OFFSET, (uint8_t)word);
+    }
+  else
+    {
+      spi_putreg(priv, STM32WL5_SPI_DR_OFFSET, word);
+    }
+}
+
+/****************************************************************************
+ * Name: spi_dmarxwait
+ *
+ * Description:
+ *   Wait for DMA to complete.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_STM32WL5_SPI_DMA
+static int spi_dmarxwait(struct stm32wl5_spidev_s *priv)
+{
+  int ret;
+
+  /* Take the semaphore (perhaps waiting).  If the result is zero, then the
+   * DMA must not really have completed???
+   */
+
+  do
+    {
+      ret = nxsem_wait_uninterruptible(&priv->rxsem);
+
+      /* The only expected error is ECANCELED which would occur if the
+       * calling thread were canceled.
+       */
+
+      DEBUGASSERT(ret == OK || ret == -ECANCELED);
+    }
+  while (priv->rxresult == 0 && ret == OK);
+
+  return ret;
+}
+#endif
+
+/****************************************************************************
+ * Name: spi_dmatxwait
+ *
+ * Description:
+ *   Wait for DMA to complete.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_STM32WL5_SPI_DMA
+static int spi_dmatxwait(struct stm32wl5_spidev_s *priv)
+{
+  int ret;
+
+  /* Take the semaphore (perhaps waiting).  If the result is zero, then the
+   * DMA must not really have completed???
+   */
+
+  do
+    {
+      ret = nxsem_wait_uninterruptible(&priv->txsem);
+
+      /* The only expected error is ECANCELED which would occur if the
+       * calling thread were canceled.
+       */
+
+      DEBUGASSERT(ret == OK || ret == -ECANCELED);
+    }
+  while (priv->txresult == 0 && ret == OK);

Review Comment:
   @pkarashchenko 
   There is a [Cancellation 
Points](https://cwiki.apache.org/confluence/display/NUTTX/Cancellation+Points) 
notes where the case is described. So the condition `while (priv->txresult == 0 
&& ret == OK);` looks correct for me.
   



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscr...@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org

Reply via email to