Check return from nxsem_wait_uninterruptible()

Resolution of Issue 619 will require multiple steps, this part of the first step in that resolution:  Every call to nxsem_wait_uninterruptible() must handle the return value from nxsem_wait_uninterruptible properly.  This commit is for all SPI drivers under arch/.
This commit is contained in:
Gregory Nutt
2020-04-02 08:45:32 -06:00
committed by Abdelatif Guettouche
parent 4d771c2bcf
commit 4892c27b4a
12 changed files with 473 additions and 393 deletions
+15 -29
View File
@@ -1,35 +1,20 @@
/****************************************************************************
* arch/arm/src/imx1/imx_spi.c
*
* Copyright (C) 2009-2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
* 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
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* http://www.apache.org/licenses/LICENSE-2.0
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* 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.
*
****************************************************************************/
@@ -567,7 +552,7 @@ static int spi_transfer(struct imx_spidev_s *priv, const void *txbuffer,
/* Wait to be signaled from the interrupt handler */
nxsem_wait_uninterruptible(&priv->waitsem);
return nxsem_wait_uninterruptible(&priv->waitsem);
#else
/* Perform the transfer using polling logic. This will totally
@@ -597,8 +582,9 @@ static int spi_transfer(struct imx_spidev_s *priv, const void *txbuffer,
sched_yield();
}
while (priv->nrxwords < priv->nwords);
#endif
return OK;
#endif
}
/****************************************************************************
+15 -34
View File
@@ -1,40 +1,20 @@
/****************************************************************************
* arch/arm/src/imx6/imx_ecspi.c
*
* Copyright (C) 2016-2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
* 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
*
* Derives from the i.MX1 CSPI driver:
* http://www.apache.org/licenses/LICENSE-2.0
*
* Copyright (C) 2009-2010, 2013, 2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* 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.
*
****************************************************************************/
@@ -688,7 +668,7 @@ static int spi_transfer(struct imx_spidev_s *priv, const void *txbuffer,
/* Wait to be signaled from the interrupt handler */
nxsem_wait_uninterruptible(&priv->waitsem);
return nxsem_wait_uninterruptible(&priv->waitsem);
#else
/* Perform the transfer using polling logic. This will totally
@@ -718,8 +698,9 @@ static int spi_transfer(struct imx_spidev_s *priv, const void *txbuffer,
sched_yield();
}
while (priv->nrxwords < priv->nwords);
#endif
return OK;
#endif
}
/****************************************************************************
+18 -32
View File
@@ -1,42 +1,28 @@
/****************************************************************************
* arch/arm/src/samd2l2/sam_spi.c
*
* Copyright (C) 2014-2018 Gregory Nutt. All rights reserved.
* Authors: Gregory Nutt <gnutt@nuttx.org>
* 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
*
* References:
* 1. "Atmel SAM D20J / SAM D20G / SAM D20E ARM-Based Microcontroller
* Datasheet", 42129JSAM12/2013
* http://www.apache.org/licenses/LICENSE-2.0
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* 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.
*
****************************************************************************/
/* References:
* 1. "Atmel SAM D20J / SAM D20G / SAM D20E ARM-Based Microcontroller
* Datasheet", 42129JSAM12/2013
*/
/****************************************************************************
* Included Files
****************************************************************************/
@@ -1154,7 +1140,7 @@ static void spi_dma_callback(DMA_HANDLE dma, void *arg, int result)
****************************************************************************/
static void spi_exchange(struct spi_dev_s *dev, const void *txbuffer,
void *rxbuffer, size_t nwords)
void *rxbuffer, size_t nwords)
{
struct sam_spidev_s *priv = (struct sam_spidev_s *)dev;
+13 -28
View File
@@ -1,35 +1,20 @@
/****************************************************************************
* arch/arm/src/samd5e5/sam_spi.c
*
* Copyright (C) 2018 Gregory Nutt. All rights reserved.
* Authors: Gregory Nutt <gnutt@nuttx.org>
* 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
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* http://www.apache.org/licenses/LICENSE-2.0
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* 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.
*
****************************************************************************/
@@ -1249,7 +1234,7 @@ static void spi_dma_callback(DMA_HANDLE dma, void *arg, int result)
****************************************************************************/
static void spi_exchange(struct spi_dev_s *dev, const void *txbuffer,
void *rxbuffer, size_t nwords)
void *rxbuffer, size_t nwords)
{
struct sam_spidev_s *priv = (struct sam_spidev_s *)dev;
+88 -45
View File
@@ -1,35 +1,20 @@
/****************************************************************************
* arch/arm/src/samv7/sam_spi_slave.c
*
* Copyright (C) 2015, 2017 Gregory Nutt. All rights reserved.
* Authors: Gregory Nutt <gnutt@nuttx.org>
* 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
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* http://www.apache.org/licenses/LICENSE-2.0
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* 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.
*
****************************************************************************/
@@ -68,6 +53,7 @@
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Configuration ************************************************************/
#ifndef CONFIG_SAMV7_SPI_SLAVE_QSIZE
@@ -110,10 +96,10 @@ struct sam_spidev_s
/* Debug stuff */
#ifdef CONFIG_SAMV7_SPI_REGDEBUG
bool wrlast; /* Last was a write */
uint32_t addresslast; /* Last address */
uint32_t valuelast; /* Last value */
int ntimes; /* Number of times */
bool wrlast; /* Last was a write */
uint32_t addresslast; /* Last address */
uint32_t valuelast; /* Last value */
int ntimes; /* Number of times */
#endif
};
@@ -141,7 +127,8 @@ static void spi_dumpregs(struct sam_spidev_s *priv, const char *msg);
# define spi_dumpregs(priv,msg)
#endif
static void spi_semtake(struct sam_spidev_s *priv);
static int spi_semtake(struct sam_spidev_s *priv);
static void spi_semtake_uninterruptible(struct sam_spidev_s *priv);
#define spi_semgive(priv) (nxsem_post(&(priv)->spisem))
/* Interrupt Handling */
@@ -348,7 +335,7 @@ static void spi_dumpregs(struct sam_spidev_s *priv, const char *msg)
*
* Description:
* Take the semaphore that enforces mutually exclusive access to SPI
* resources, handling any exceptional conditions
* resources. May return ECANCELED if the calling thread was canceled.
*
* Input Parameters:
* priv - A reference to the MCAN peripheral state
@@ -358,9 +345,39 @@ static void spi_dumpregs(struct sam_spidev_s *priv, const char *msg)
*
****************************************************************************/
static void spi_semtake(struct sam_spidev_s *priv)
static int spi_semtake(struct sam_spidev_s *priv)
{
nxsem_wait_uninterruptible(&priv->spisem);
return nxsem_wait_uninterruptible(&priv->spisem);
}
/****************************************************************************
* Name: spi_semtake_uninterruptible
*
* Description:
* Take the semaphore that enforces mutually exclusive access to SPI
* resources, handling any exceptional conditions. Always successful.
*
* Input Parameters:
* priv - A reference to the MCAN peripheral state
*
* Returned Value:
* None
*
****************************************************************************/
static void spi_semtake_uninterruptible(struct sam_spidev_s *priv)
{
int ret;
do
{
ret = nxsem_wait_uninterruptible(&priv->spisem);
/* ECANCELED is the only error expected here */
DEBUGASSERT(ret == OK || ret == -ECANCELED);
}
while (ret < 0);
}
/****************************************************************************
@@ -458,7 +475,8 @@ static int spi_interrupt(int irq, void *context, FAR void *arg)
*/
regval = spi_getreg(priv, SAM_SPI_RDR_OFFSET);
data = (uint16_t)((regval & SPI_RDR_RD_MASK) >> SPI_RDR_RD_SHIFT);
data = (uint16_t)
((regval & SPI_RDR_RD_MASK) >> SPI_RDR_RD_SHIFT);
/* Enable TXDR/OVRE interrupts */
@@ -482,7 +500,8 @@ static int spi_interrupt(int irq, void *context, FAR void *arg)
* i.e., NSS falls and there is a valid clock on the SPCK pin. When
* the transfer occurs, the last data written in the SPI_TDR is
* transferred in the Shift register and the TDRE flag rises. This
* enables frequent updates of critical variables with single transfers.
* enables frequent updates of critical variables with single
* transfers.
*
* Then, new data is loaded in the Shift register from the SPI_TDR. If
* no character is ready to be transmitted, i.e., no character has been
@@ -743,6 +762,7 @@ static void spi_bind(struct spi_sctrlr_s *sctrlr,
{
struct sam_spidev_s *priv = (struct sam_spidev_s *)sctrlr;
uint32_t regval;
int ret;
spiinfo("sdev=%p mode=%d nbits=%d\n", sdv, mode, nbits);
@@ -750,7 +770,16 @@ static void spi_bind(struct spi_sctrlr_s *sctrlr,
/* Get exclusive access to the SPI device */
spi_semtake(priv);
ret = spi_semtake(priv);
if (ret < 0)
{
/* REVISIT: No mechanism to report error. This error should only
* occur if the calling task was canceled.
*/
spierr("RROR: spi_semtake failed: %d\n", ret);
return;
}
/* Bind the SPI slave device interface instance to the SPI slave
* controller interface.
@@ -852,7 +881,7 @@ static void spi_unbind(struct spi_sctrlr_s *sctrlr)
/* Get exclusive access to the SPI device */
spi_semtake(priv);
spi_semtake_uninterruptible(priv);
/* Disable SPI interrupts (still enabled at the NVIC) */
@@ -908,7 +937,11 @@ static int spi_enqueue(struct spi_sctrlr_s *sctrlr, uint16_t data)
/* Get exclusive access to the SPI device */
spi_semtake(priv);
ret = spi_semtake(priv);
if (ret < 0)
{
return ret;
}
/* Check if this word would overflow the circular buffer
*
@@ -972,14 +1005,24 @@ static bool spi_qfull(struct spi_sctrlr_s *sctrlr)
{
struct sam_spidev_s *priv = (struct sam_spidev_s *)sctrlr;
irqstate_t flags;
bool bret;
int ret;
int next;
bool ret;
DEBUGASSERT(priv != NULL && priv->sdev != NULL);
/* Get exclusive access to the SPI device */
spi_semtake(priv);
ret = spi_semtake(priv);
if (ret < 0)
{
/* REVISIT: No mechanism to report error. This error should only
* occurr if the calling task was canceled.
*/
spierr("RROR: spi_semtake failed: %d\n", ret);
return true;
}
/* Check if another word would overflow the circular buffer
*
@@ -993,10 +1036,10 @@ static bool spi_qfull(struct spi_sctrlr_s *sctrlr)
next = 0;
}
ret = (next == priv->tail);
bret = (next == priv->tail);
leave_critical_section(flags);
spi_semgive(priv);
return ret;
return bret;
}
/****************************************************************************
@@ -1026,7 +1069,7 @@ static void spi_qflush(struct spi_sctrlr_s *sctrlr)
/* Get exclusive access to the SPI device */
spi_semtake(priv);
spi_semtake_uninterruptible(priv);
/* Mark the buffer empty, momentarily disabling interrupts */
+99 -72
View File
@@ -1,35 +1,20 @@
/****************************************************************************
* arch/arm/src/samv7/sam_ssc.c
*
* Copyright (C) 2015-2017 Gregory Nutt. All rights reserved.
* Authors: Gregory Nutt <gnutt@nuttx.org>
* 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
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* http://www.apache.org/licenses/LICENSE-2.0
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* 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.
*
****************************************************************************/
@@ -76,6 +61,7 @@
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Configuration ************************************************************/
#ifndef CONFIG_SCHED_WORKQUEUE
@@ -368,7 +354,8 @@
#define DMA_TIMEOUT_MS (800)
#define DMA_TIMEOUT_TICKS MSEC2TICK(DMA_TIMEOUT_MS)
/* Debug *******************************************************************/
/* Debug ********************************************************************/
/* Check if SSC debug is enabled */
#ifndef CONFIG_DEBUG_I2S_INFO
@@ -393,6 +380,7 @@
/****************************************************************************
* Private Types
****************************************************************************/
/* I2S buffer container */
struct sam_buffer_s
@@ -466,10 +454,10 @@ struct sam_ssc_s
/* Debug stuff */
#ifdef CONFIG_SAMV7_SSC_REGDEBUG
bool wr; /* Last was a write */
uint32_t regaddr; /* Last address */
uint32_t regval; /* Last value */
int count; /* Number of times */
bool wr; /* Last was a write */
uint32_t regaddr; /* Last address */
uint32_t regval; /* Last value */
int count; /* Number of times */
#endif /* CONFIG_SAMV7_SSC_REGDEBUG */
};
@@ -480,13 +468,14 @@ struct sam_ssc_s
/* Register helpers */
#ifdef CONFIG_SAMV7_SSC_REGDEBUG
static bool ssc_checkreg(struct sam_ssc_s *priv, bool wr, uint32_t regval,
uint32_t regaddr);
static bool ssc_checkreg(struct sam_ssc_s *priv, bool wr,
uint32_t regval, uint32_t regaddr);
#else
# define ssc_checkreg(priv,wr,regval,regaddr) (false)
#endif
static inline uint32_t ssc_getreg(struct sam_ssc_s *priv, unsigned int offset);
static inline uint32_t ssc_getreg(struct sam_ssc_s *priv,
unsigned int offset);
static inline void ssc_putreg(struct sam_ssc_s *priv, unsigned int offset,
uint32_t regval);
static inline uintptr_t ssc_regaddr(struct sam_ssc_s *priv,
@@ -518,10 +507,10 @@ static void ssc_dump_queues(struct sam_transport_s *xpt,
/* Semaphore helpers */
static void ssc_exclsem_take(struct sam_ssc_s *priv);
static int ssc_exclsem_take(struct sam_ssc_s *priv);
#define ssc_exclsem_give(priv) nxsem_post(&priv->exclsem)
static void ssc_bufsem_take(struct sam_ssc_s *priv);
static int ssc_bufsem_take(struct sam_ssc_s *priv);
#define ssc_bufsem_give(priv) nxsem_post(&priv->bufsem)
/* Buffer container helpers */
@@ -615,6 +604,7 @@ static void ssc1_configure(struct sam_ssc_s *priv);
/****************************************************************************
* Private Data
****************************************************************************/
/* I2S device operations */
static const struct i2s_ops_s g_sscops =
@@ -749,7 +739,8 @@ static inline void ssc_putreg(struct sam_ssc_s *priv, unsigned int offset,
*
****************************************************************************/
static inline uintptr_t ssc_regaddr(struct sam_ssc_s *priv, unsigned int offset)
static inline uintptr_t ssc_regaddr(struct sam_ssc_s *priv,
unsigned int offset)
{
return priv->base + offset;
}
@@ -860,9 +851,9 @@ static void ssc_dump_queues(struct sam_transport_s *xpt, const char *msg)
*
****************************************************************************/
static void ssc_exclsem_take(struct sam_ssc_s *priv)
static int ssc_exclsem_take(struct sam_ssc_s *priv)
{
nxsem_wait_uninterruptible(&priv->exclsem);
return nxsem_wait_uninterruptible(&priv->exclsem);
}
/****************************************************************************
@@ -879,9 +870,9 @@ static void ssc_exclsem_take(struct sam_ssc_s *priv)
*
****************************************************************************/
static void ssc_bufsem_take(struct sam_ssc_s *priv)
static int ssc_bufsem_take(struct sam_ssc_s *priv)
{
nxsem_wait_uninterruptible(&priv->bufsem);
return nxsem_wait_uninterruptible(&priv->bufsem);
}
/****************************************************************************
@@ -908,12 +899,17 @@ static struct sam_buffer_s *ssc_buf_allocate(struct sam_ssc_s *priv)
{
struct sam_buffer_s *bfcontainer;
irqstate_t flags;
int ret;
/* Set aside a buffer container. By doing this, we guarantee that we will
* have at least one free buffer container.
*/
ssc_bufsem_take(priv);
ret = ssc_bufsem_take(priv);
if (ret < 0)
{
return NULL;
}
/* Get the buffer from the head of the free list */
@@ -946,7 +942,8 @@ static struct sam_buffer_s *ssc_buf_allocate(struct sam_ssc_s *priv)
*
****************************************************************************/
static void ssc_buf_free(struct sam_ssc_s *priv, struct sam_buffer_s *bfcontainer)
static void ssc_buf_free(struct sam_ssc_s *priv,
struct sam_buffer_s *bfcontainer)
{
irqstate_t flags;
@@ -1046,6 +1043,7 @@ static void ssc_rxdma_sampledone(struct sam_ssc_s *priv, int result)
sam_dmasample(priv->rx.dma, &priv->rx.dmaregs[DMA_END_TRANSFER]);
/* Then dump the sampled DMA registers */
/* Initial register values */
sam_dmadump(priv->rx.dma, &priv->rx.dmaregs[DMA_INITIAL],
@@ -1111,6 +1109,7 @@ static void ssc_txdma_sampledone(struct sam_ssc_s *priv, int result)
sam_dmasample(priv->tx.dma, &priv->tx.dmaregs[DMA_END_TRANSFER]);
/* Then dump the sampled DMA registers */
/* Initial register values */
sam_dmadump(priv->tx.dma, &priv->tx.dmaregs[DMA_INITIAL],
@@ -1360,10 +1359,10 @@ static void ssc_rx_worker(void *arg)
DEBUGASSERT(priv);
/* When the transfer was started, the active buffer containers were removed
* from the rx.pend queue and saved in the rx.act queue. We get here when the
* DMA is finished... either successfully, with a DMA error, or with a DMA
* timeout.
/* When the transfer was started, the active buffer containers were
* removed from the rx.pend queue and saved in the rx.act queue. We get
* here when the DMA is finished... either successfully, with a DMA
* error, or with a DMA timeout.
*
* In any case, the buffer containers in rx.act will be moved to the end
* of the rx.done queue and rx.act queue will be emptied before this worker
@@ -1776,10 +1775,10 @@ static void ssc_tx_worker(void *arg)
DEBUGASSERT(priv);
/* When the transfer was started, the active buffer containers were removed
* from the tx.pend queue and saved in the tx.act queue. We get here when the
* DMA is finished... either successfully, with a DMA error, or with a DMA
* timeout.
/* When the transfer was started, the active buffer containers were
* removed from the tx.pend queue and saved in the tx.act queue. We get
* here when the DMA is finished... either successfully, with a DMA
* error, or with a DMA timeout.
*
* In any case, the buffer containers in tx.act will be moved to the end
* of the tx.done queue and tx.act will be emptied before this worker is
@@ -2176,11 +2175,18 @@ static int ssc_receive(struct i2s_dev_s *dev, struct ap_buffer_s *apb,
/* Allocate a buffer container in advance */
bfcontainer = ssc_buf_allocate(priv);
DEBUGASSERT(bfcontainer);
if (bfcontainer == NULL)
{
return -ENOMEM;
}
/* Get exclusive access to the SSC driver data */
ssc_exclsem_take(priv);
ret = ssc_exclsem_take(priv);
if (ret < 0)
{
goto errout_with_buf;
}
/* Has the RX channel been enabled? */
@@ -2209,8 +2215,8 @@ static int ssc_receive(struct i2s_dev_s *dev, struct ap_buffer_s *apb,
sq_addlast((sq_entry_t *)bfcontainer, &priv->rx.pend);
ssc_dump_rxqueues(priv, "Receiving");
/* Then start the next transfer. If there is already a transfer in progress,
* then this will do nothing.
/* Then start the next transfer. If there is already a transfer in
* progress, then this will do nothing.
*/
ret = ssc_rxdma_setup(priv);
@@ -2221,6 +2227,8 @@ static int ssc_receive(struct i2s_dev_s *dev, struct ap_buffer_s *apb,
errout_with_exclsem:
ssc_exclsem_give(priv);
errout_with_buf:
ssc_buf_free(priv, bfcontainer);
return ret;
@@ -2393,11 +2401,18 @@ static int ssc_send(struct i2s_dev_s *dev, struct ap_buffer_s *apb,
/* Allocate a buffer container in advance */
bfcontainer = ssc_buf_allocate(priv);
DEBUGASSERT(bfcontainer);
if (bfcontainer == NULL)
{
return -ENOMEM;
}
/* Get exclusive access to the SSC driver data */
ssc_exclsem_take(priv);
ret = ssc_exclsem_take(priv);
if (ret < 0)
{
goto errout_with_buf;
}
/* Has the TX channel been enabled? */
@@ -2426,8 +2441,8 @@ static int ssc_send(struct i2s_dev_s *dev, struct ap_buffer_s *apb,
sq_addlast((sq_entry_t *)bfcontainer, &priv->tx.pend);
ssc_dump_txqueues(priv, "Transmitting");
/* Then start the next transfer. If there is already a transfer in progress,
* then this will do nothing.
/* Then start the next transfer. If there is already a transfer in
* progress, then this will do nothing.
*/
ret = ssc_txdma_setup(priv);
@@ -2438,6 +2453,8 @@ static int ssc_send(struct i2s_dev_s *dev, struct ap_buffer_s *apb,
errout_with_exclsem:
ssc_exclsem_give(priv);
errout_with_buf:
ssc_buf_free(priv, bfcontainer);
return ret;
@@ -2458,7 +2475,8 @@ errout_with_exclsem:
* priv - Fully initialized SSC device structure.
*
* Returned Value:
* OK is returned on failure. A negated errno value is returned on failure.
* OK is returned on failure. A negated errno value is returned on
* failure.
*
****************************************************************************/
@@ -2474,6 +2492,7 @@ static int ssc_rx_configure(struct sam_ssc_s *priv)
fslen = priv->rxfslen - 1;
/* RCMR settings */
/* Configure the receiver input clock */
regval = 0;
@@ -2539,15 +2558,16 @@ static int ssc_rx_configure(struct sam_ssc_s *priv)
SSC_RCMR_STTDLY(priv->rxsttdly) | SSC_RCMR_PERIOD(0));
ssc_putreg(priv, SAM_SSC_RCMR_OFFSET, regval);
/* RFMR settings. Some of these settings will need to be configurable as well.
* Currently hardcoded to:
/* RFMR settings. Some of these settings will need to be configurable as
* well. Currently hardcoded to:
*
* SSC_RFMR_DATLEN(n) 'n' determined by configuration
* SSC_RFMR_LOOP Determined by configuration
* SSC_RFMR_MSBF Most significant bit first
* SSC_RFMR_DATNB(n) Data number 'n' per frame (hard-coded)
* SSC_RFMR_FSLEN Set to LS 4 bits of (CONFIG_SSCx_RX_FSLEN-1)
* SSC_RFMR_FSLEN(1) Pulse length = FSLEN + (FSLEN_EXT * 16) + 1 = 2 clocks
* SSC_RFMR_FSLEN(1) Pulse length = FSLEN + (FSLEN_EXT * 16) + 1 =
* 2 clocks
* SSC_RFMR_FSOS_NONE RF pin is always in input
* SSC_RFMR_FSEDGE_POS Positive frame sync edge detection
* SSC_RFMR_FSLENEXT I Set to MS 4 bits of (CONFIG_SSCx_TX_FSLEN-1)
@@ -2558,7 +2578,8 @@ static int ssc_rx_configure(struct sam_ssc_s *priv)
/* Set the RX frame synch */
regval |= (SSC_RFMR_FSLEN(fslen & 0x0f) | SSC_RFMR_FSLENEXT((fslen >> 4) & 0x0f));
regval |= (SSC_RFMR_FSLEN(fslen & 0x0f) |
SSC_RFMR_FSLENEXT((fslen >> 4) & 0x0f));
/* Loopback mode? */
@@ -2599,6 +2620,7 @@ static int ssc_tx_configure(struct sam_ssc_s *priv)
period = SCC_PERIOD(priv->txsttdly, priv->datalen);
/* TCMR settings */
/* Configure the transmitter input clock */
regval = 0;
@@ -2668,26 +2690,30 @@ static int ssc_tx_configure(struct sam_ssc_s *priv)
if (priv->txclk == SSC_CLKSRC_MCKDIV)
{
regval |= (SSC_TCMR_CKG_CONT | SSC_TCMR_START_CONT |
SSC_TCMR_STTDLY(priv->txsttdly) | SSC_TCMR_PERIOD(period / 2 - 1));
SSC_TCMR_STTDLY(priv->txsttdly) |
SSC_TCMR_PERIOD(period / 2 - 1));
}
else
{
regval |= (SSC_TCMR_CKG_CONT | SSC_TCMR_START_EDGE |
SSC_TCMR_STTDLY(priv->txsttdly) | SSC_TCMR_PERIOD(0));
SSC_TCMR_STTDLY(priv->txsttdly) |
SSC_TCMR_PERIOD(0));
}
ssc_putreg(priv, SAM_SSC_TCMR_OFFSET, regval);
/* TFMR settings. Some of these settings will need to be configurable as well.
* Currently set to:
/* TFMR settings. Some of these settings will need to be configurable as
* well. Currently set to:
*
* SSC_TFMR_DATLEN(n) 'n' determined by configuration
* SSC_TFMR_DATDEF Data default = 0
* SSC_TFMR_MSBF Most significant bit first
* SSC_TFMR_DATNB(n) Data number 'n' per frame (hard-coded)
* SSC_TFMR_FSDEN Enabled if CONFIG_SSCx_TX_FSLEN > 0
* SSC_TFMR_FSLEN If enabled, set to LS 4 bits of (CONFIG_SSCx_TX_FSLEN-1)
* SSC_TFMR_FSLENEXT If enabled, set to MS 4 bits of (CONFIG_SSCx_TX_FSLEN-1)
* SSC_TFMR_FSLEN If enabled, set to LS 4 bits of
* (CONFIG_SSCx_TX_FSLEN-1)
* SSC_TFMR_FSLENEXT If enabled, set to MS 4 bits of
* (CONFIG_SSCx_TX_FSLEN-1)
*
* If master (i.e., provides clocking):
* SSC_TFMR_FSOS_NEGATIVE Negative pulse TF output
@@ -2852,7 +2878,8 @@ static void ssc_clocking(struct sam_ssc_s *priv)
/* Reset, disable receiver & transmitter */
ssc_putreg(priv, SAM_SSC_CR_OFFSET, SSC_CR_RXDIS | SSC_CR_TXDIS | SSC_CR_SWRST);
ssc_putreg(priv, SAM_SSC_CR_OFFSET,
SSC_CR_RXDIS | SSC_CR_TXDIS | SSC_CR_SWRST);
/* Configure MCK/2 divider */
+37 -12
View File
@@ -247,8 +247,8 @@ static inline void spi_writeword(FAR struct stm32_spidev_s *priv, uint16_t byte)
/* DMA support */
#ifdef CONFIG_STM32_SPI_DMA
static void spi_dmarxwait(FAR struct stm32_spidev_s *priv);
static void spi_dmatxwait(FAR struct stm32_spidev_s *priv);
static int spi_dmarxwait(FAR struct stm32_spidev_s *priv);
static int spi_dmatxwait(FAR struct stm32_spidev_s *priv);
static inline void spi_dmarxwakeup(FAR struct stm32_spidev_s *priv);
static inline void spi_dmatxwakeup(FAR struct stm32_spidev_s *priv);
static void spi_dmarxcallback(DMA_HANDLE handle, uint8_t isr, void *arg);
@@ -889,17 +889,27 @@ static inline void spi_writeword(FAR struct stm32_spidev_s *priv, uint16_t word)
************************************************************************************/
#ifdef CONFIG_STM32_SPI_DMA
static void spi_dmarxwait(FAR struct stm32_spidev_s *priv)
static int spi_dmarxwait(FAR struct stm32_spidev_s *priv)
{
int ret;
/* Take the semaphore (perhaps waiting). If the result is zero, then the DMA
* must not really have completed???
*/
do
{
nxsem_wait_uninterruptible(&priv->rxsem);
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);
while (priv->rxresult == 0 && ret == OK);
return ret;
}
#endif
@@ -912,17 +922,27 @@ static void spi_dmarxwait(FAR struct stm32_spidev_s *priv)
************************************************************************************/
#ifdef CONFIG_STM32_SPI_DMA
static void spi_dmatxwait(FAR struct stm32_spidev_s *priv)
static int spi_dmatxwait(FAR struct stm32_spidev_s *priv)
{
int ret;
/* Take the semaphore (perhaps waiting). If the result is zero, then the DMA
* must not really have completed???
*/
do
{
nxsem_wait_uninterruptible(&priv->txsem);
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);
while (priv->txresult == 0 && ret == OK);
return ret;
}
#endif
@@ -1745,7 +1765,9 @@ static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer,
FAR void *rxbuffer, size_t nwords)
{
FAR struct stm32_spidev_s *priv = (FAR struct stm32_spidev_s *)dev;
FAR void * xbuffer = rxbuffer;
FAR void *xbuffer = rxbuffer;
int ret;
DEBUGASSERT(priv != NULL);
/* Convert the number of word to a number of bytes */
@@ -1843,10 +1865,13 @@ static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer,
/* Then wait for each to complete */
spi_dmarxwait(priv);
spi_dmatxwait(priv);
ret = spi_dmarxwait(priv);
if (ret < 0)
{
ret = spi_dmatxwait(priv);
}
if (rxbuffer && priv->rxbuf)
if (rxbuffer != NULL && priv->rxbuf != NULL && ret >= 0)
{
memcpy(xbuffer, priv->rxbuf, nbytes);
}
+47 -38
View File
@@ -2,35 +2,20 @@
* arch/arm/src/stm32f0l0g0/stm32_spi.c
* copied from arch/arm/src/stm32
*
* Copyright (C) 2009-2013, 2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
* 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
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* http://www.apache.org/licenses/LICENSE-2.0
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* 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.
*
****************************************************************************/
@@ -198,8 +183,8 @@ static inline bool spi_16bitmode(FAR struct stm32_spidev_s *priv);
/* DMA support */
#ifdef CONFIG_STM32F0L0G0_SPI_DMA
static void spi_dmarxwait(FAR struct stm32_spidev_s *priv);
static void spi_dmatxwait(FAR struct stm32_spidev_s *priv);
static int spi_dmarxwait(FAR struct stm32_spidev_s *priv);
static int spi_dmatxwait(FAR struct stm32_spidev_s *priv);
static inline void spi_dmarxwakeup(FAR struct stm32_spidev_s *priv);
static inline void spi_dmatxwakeup(FAR struct stm32_spidev_s *priv);
static void spi_dmarxcallback(DMA_HANDLE handle, uint8_t isr,
@@ -581,7 +566,7 @@ static inline bool spi_16bitmode(FAR struct stm32_spidev_s *priv)
}
/****************************************************************************
* Name: spi_dmarxwaitw
* Name: spi_dmarxwait
*
* Description:
* Wait for DMA to complete.
@@ -589,17 +574,27 @@ static inline bool spi_16bitmode(FAR struct stm32_spidev_s *priv)
****************************************************************************/
#ifdef CONFIG_STM32F0L0G0_SPI_DMA
static void spi_dmarxwait(FAR struct stm32_spidev_s *priv)
static int spi_dmarxwait(FAR struct stm32_spidev_s *priv)
{
int ret;
/* Take the semaphore (perhaps waiting). If the result is zero, then the
* DMA must not really have completed???
*/
do
{
nxsem_wait_uninterruptible(&priv->rxsem);
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);
while (priv->rxresult == 0 && ret == OK);
return ret;
}
#endif
@@ -612,17 +607,27 @@ static void spi_dmarxwait(FAR struct stm32_spidev_s *priv)
****************************************************************************/
#ifdef CONFIG_STM32F0L0G0_SPI_DMA
static void spi_dmatxwait(FAR struct stm32_spidev_s *priv)
static int spi_dmatxwait(FAR struct stm32_spidev_s *priv)
{
int ret;
/* Take the semaphore (perhaps waiting). If the result is zero, then the
* DMA must not really have completed???
*/
do
{
nxsem_wait_uninterruptible(&priv->txsem);
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);
while (priv->txresult == 0 && ret == OK);
return ret;
}
#endif
@@ -1446,8 +1451,12 @@ static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer,
/* Then wait for each to complete */
spi_dmarxwait(priv);
spi_dmatxwait(priv);
ret = spi_dmarxwait(priv);
if (ret >= 0)
{
ret = spi_dmatxwait(priv);
UNUSED(ret);
}
#ifdef CONFIG_SPI_TRIGGER
priv->trigarmed = false;
+34 -11
View File
@@ -230,8 +230,8 @@ static inline void spi_writeword(FAR struct stm32_spidev_s *priv,
/* DMA support */
#ifdef CONFIG_STM32F7_SPI_DMA
static void spi_dmarxwait(FAR struct stm32_spidev_s *priv);
static void spi_dmatxwait(FAR struct stm32_spidev_s *priv);
static int spi_dmarxwait(FAR struct stm32_spidev_s *priv);
static int spi_dmatxwait(FAR struct stm32_spidev_s *priv);
static inline void spi_dmarxwakeup(FAR struct stm32_spidev_s *priv);
static inline void spi_dmatxwakeup(FAR struct stm32_spidev_s *priv);
static void spi_dmarxcallback(DMA_HANDLE handle, uint8_t isr,
@@ -897,17 +897,27 @@ static inline void spi_writebyte(FAR struct stm32_spidev_s *priv,
****************************************************************************/
#ifdef CONFIG_STM32F7_SPI_DMA
static void spi_dmarxwait(FAR struct stm32_spidev_s *priv)
static int spi_dmarxwait(FAR struct stm32_spidev_s *priv)
{
int ret;
/* Take the semaphore (perhaps waiting). If the result is zero, then the
* DMA must not really have completed???
*/
do
{
nxsem_wait_uninterruptible(&priv->rxsem);
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);
while (priv->rxresult == 0 && ret == OK);
return ret;
}
#endif
@@ -920,17 +930,27 @@ static void spi_dmarxwait(FAR struct stm32_spidev_s *priv)
****************************************************************************/
#ifdef CONFIG_STM32F7_SPI_DMA
static void spi_dmatxwait(FAR struct stm32_spidev_s *priv)
static int spi_dmatxwait(FAR struct stm32_spidev_s *priv)
{
int ret;
/* Take the semaphore (perhaps waiting). If the result is zero, then the
* DMA must not really have completed???
*/
do
{
nxsem_wait_uninterruptible(&priv->txsem);
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);
while (priv->txresult == 0 && ret == OK);
return ret;
}
#endif
@@ -1878,8 +1898,11 @@ static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer,
/* Then wait for each to complete */
spi_dmarxwait(priv);
spi_dmatxwait(priv);
ret = spi_dmarxwait(priv);
if (ret >= 0)
{
ret = spi_dmatxwait(priv);
}
#ifdef CONFIG_SPI_TRIGGER
priv->trigarmed = false;
@@ -1887,7 +1910,7 @@ static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer,
/* Force RAM re-read */
if (rxbuffer)
if (rxbuffer != NULL && ret >= 0)
{
up_invalidate_dcache((uintptr_t)rxbuffer,
(uintptr_t)rxbuffer + nbytes);
+35 -11
View File
@@ -226,8 +226,8 @@ static inline void spi_dumpregs(FAR struct stm32_spidev_s *priv);
/* DMA support */
#ifdef CONFIG_STM32H7_SPI_DMA
static void spi_dmarxwait(FAR struct stm32_spidev_s *priv);
static void spi_dmatxwait(FAR struct stm32_spidev_s *priv);
static int spi_dmarxwait(FAR struct stm32_spidev_s *priv);
static int spi_dmatxwait(FAR struct stm32_spidev_s *priv);
static inline void spi_dmarxwakeup(FAR struct stm32_spidev_s *priv);
static inline void spi_dmatxwakeup(FAR struct stm32_spidev_s *priv);
static void spi_dmarxcallback(DMA_HANDLE handle, uint8_t isr,
@@ -844,17 +844,27 @@ static inline bool spi_9to16bitmode(FAR struct stm32_spidev_s *priv)
****************************************************************************/
#ifdef CONFIG_STM32H7_SPI_DMA
static void spi_dmarxwait(FAR struct stm32_spidev_s *priv)
static int spi_dmarxwait(FAR struct stm32_spidev_s *priv)
{
int ret;
/* Take the semaphore (perhaps waiting). If the result is zero, then the
* DMA must not really have completed???
*/
do
{
nxsem_wait_uninterruptible(&priv->rxsem);
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);
while (priv->rxresult == 0 && ret == OK);
return ret;
}
#endif
@@ -867,17 +877,27 @@ static void spi_dmarxwait(FAR struct stm32_spidev_s *priv)
****************************************************************************/
#ifdef CONFIG_STM32H7_SPI_DMA
static void spi_dmatxwait(FAR struct stm32_spidev_s *priv)
static int spi_dmatxwait(FAR struct stm32_spidev_s *priv)
{
int ret;
/* Take the semaphore (perhaps waiting). If the result is zero, then the
* DMA must not really have completed???
*/
do
{
nxsem_wait_uninterruptible(&priv->txsem);
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);
while (priv->txresult == 0 && ret == OK);
return ret;
}
#endif
@@ -1828,8 +1848,12 @@ static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer,
/* Then wait for each to complete */
spi_dmarxwait(priv);
spi_dmatxwait(priv);
ret = spi_dmarxwait(priv);
if (ret >= 0)
{
ret = spi_dmatxwait(priv);
UNUSED(ret);
}
#ifdef CONFIG_SPI_TRIGGER
priv->trigarmed = false;
@@ -1837,7 +1861,7 @@ static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer,
/* Force RAM re-read */
if (rxbuffer)
if (rxbuffer != NULL)
{
up_invalidate_dcache((uintptr_t)rxbuffer,
(uintptr_t)rxbuffer + buflen);
+46 -37
View File
@@ -1,35 +1,20 @@
/****************************************************************************
* arch/arm/src/stm32l4/stm32l4_spi.c
*
* Copyright (C) 2009-2013, 2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
* 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
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* http://www.apache.org/licenses/LICENSE-2.0
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* 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.
*
****************************************************************************/
@@ -199,8 +184,8 @@ static inline bool spi_16bitmode(FAR struct stm32l4_spidev_s *priv);
/* DMA support */
#ifdef CONFIG_STM32L4_SPI_DMA
static void spi_dmarxwait(FAR struct stm32l4_spidev_s *priv);
static void spi_dmatxwait(FAR struct stm32l4_spidev_s *priv);
static int spi_dmarxwait(FAR struct stm32l4_spidev_s *priv);
static int spi_dmatxwait(FAR struct stm32l4_spidev_s *priv);
static inline void spi_dmarxwakeup(FAR struct stm32l4_spidev_s *priv);
static inline void spi_dmatxwakeup(FAR struct stm32l4_spidev_s *priv);
static void spi_dmarxcallback(DMA_HANDLE handle, uint8_t isr,
@@ -640,17 +625,27 @@ static inline bool spi_16bitmode(FAR struct stm32l4_spidev_s *priv)
****************************************************************************/
#ifdef CONFIG_STM32L4_SPI_DMA
static void spi_dmarxwait(FAR struct stm32l4_spidev_s *priv)
static int spi_dmarxwait(FAR struct stm32l4_spidev_s *priv)
{
int ret;
/* Take the semaphore (perhaps waiting). If the result is zero, then the
* DMA must not really have completed???
*/
do
{
nxsem_wait_uninterruptible(&priv->rxsem);
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);
while (priv->rxresult == 0 && ret == OK);
return ret;
}
#endif
@@ -663,17 +658,27 @@ static void spi_dmarxwait(FAR struct stm32l4_spidev_s *priv)
****************************************************************************/
#ifdef CONFIG_STM32L4_SPI_DMA
static void spi_dmatxwait(FAR struct stm32l4_spidev_s *priv)
static int spi_dmatxwait(FAR struct stm32l4_spidev_s *priv)
{
int ret;
/* Take the semaphore (perhaps waiting). If the result is zero, then the
* DMA must not really have completed???
*/
do
{
nxsem_wait_uninterruptible(&priv->txsem);
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);
while (priv->txresult == 0 && ret == OK);
return ret;
}
#endif
@@ -1496,8 +1501,12 @@ static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer,
/* Then wait for each to complete */
spi_dmarxwait(priv);
spi_dmatxwait(priv);
ret = spi_dmarxwait(priv);
if (ret >= 0)
{
ret = spi_dmatxwait(priv);
UNUSED(ret);
}
#ifdef CONFIG_SPI_TRIGGER
priv->trigarmed = false;
+26 -44
View File
@@ -1,35 +1,20 @@
/****************************************************************************
* arch/arm/src/tiva/common/tiva_ssi.c
*
* Copyright (C) 2009-2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
* 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
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* http://www.apache.org/licenses/LICENSE-2.0
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* 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.
*
****************************************************************************/
@@ -239,7 +224,7 @@ static uint32_t ssi_disable(struct tiva_ssidev_s *priv);
static void ssi_enable(struct tiva_ssidev_s *priv, uint32_t enable);
#ifndef CONFIG_SSI_POLLWAIT
static void ssi_semtake(sem_t *sem);
static int ssi_semtake(sem_t *sem);
#define ssi_semgive(s) nxsem_post(s);
#endif
@@ -501,9 +486,9 @@ static void ssi_enable(struct tiva_ssidev_s *priv, uint32_t enable)
****************************************************************************/
#ifndef CONFIG_SSI_POLLWAIT
static void ssi_semtake(sem_t *sem)
static int ssi_semtake(sem_t *sem)
{
nxsem_wait_uninterruptible(sem);
return nxsem_wait_uninterruptible(sem);
}
#endif
@@ -842,9 +827,9 @@ static int ssi_transfer(struct tiva_ssidev_s *priv, const void *txbuffer,
priv->txbuffer = (uint8_t *)txbuffer; /* Source buffer */
priv->rxbuffer = (uint8_t *)rxbuffer; /* Destination buffer */
priv->ntxwords = nwords; /* Number of words left to send */
priv->nrxwords = 0; /* Number of words received */
priv->nwords = nwords; /* Total number of exchanges */
priv->ntxwords = nwords; /* Number of words left to send */
priv->nrxwords = 0; /* Number of words received */
priv->nwords = nwords; /* Total number of exchanges */
/* Set up the low-level data transfer function pointers */
@@ -905,9 +890,10 @@ static int ssi_transfer(struct tiva_ssidev_s *priv, const void *txbuffer,
leave_critical_section(flags);
do
{
ssi_semtake(&priv->xfrsem);
ret = ssi_semtake(&priv->xfrsem);
}
while (priv->nrxwords < priv->nwords);
while (priv->nrxwords < priv->nwords && ret >= 0);
spiinfo("Transfer complete\n");
#else
@@ -1527,12 +1513,11 @@ FAR struct spi_dev_s *tiva_ssibus_initialize(int port)
tiva_ssi0_enablepwr();
tiva_ssi0_enableclk();
/* Configure SSI0 GPIOs (NOTE that SS is not initialized here, the
* logic in this file makes no assumptions about chip select)
/* Configure SSI0 GPIOs (NOTE that SSI0Fss is not initialized here,
* the logic in this file makes no assumptions about chip select).
*/
tiva_configgpio(GPIO_SSI0_CLK); /* PA2: SSI0 clock (SSI0Clk) */
/* tiva_configgpio(GPIO_SSI0_FSS); PA3: SSI0 frame (SSI0Fss) */
tiva_configgpio(GPIO_SSI0_RX); /* PA4: SSI0 receive (SSI0Rx) */
tiva_configgpio(GPIO_SSI0_TX); /* PA5: SSI0 transmit (SSI0Tx) */
break;
@@ -1559,10 +1544,9 @@ FAR struct spi_dev_s *tiva_ssibus_initialize(int port)
tiva_ssi1_enablepwr();
tiva_ssi1_enableclk();
/* Configure SSI1 GPIOs */
/* Configure SSI1 GPIOs (except for SSI1Fss) */
tiva_configgpio(GPIO_SSI1_CLK); /* PE0: SSI1 clock (SSI1Clk) */
/* tiva_configgpio(GPIO_SSI1_FSS); PE1: SSI1 frame (SSI1Fss) */
tiva_configgpio(GPIO_SSI1_RX); /* PE2: SSI1 receive (SSI1Rx) */
tiva_configgpio(GPIO_SSI1_TX); /* PE3: SSI1 transmit (SSI1Tx) */
break;
@@ -1589,10 +1573,9 @@ FAR struct spi_dev_s *tiva_ssibus_initialize(int port)
tiva_ssi2_enablepwr();
tiva_ssi2_enableclk();
/* Configure SSI2 GPIOs */
/* Configure SSI2 GPIOs (except for SSI2Fss) */
tiva_configgpio(GPIO_SSI2_CLK); /* PE0: SSI2 clock (SSI2Clk) */
/* tiva_configgpio(GPIO_SSI2_FSS); PE1: SSI2 frame (SSI2Fss) */
tiva_configgpio(GPIO_SSI2_RX); /* PE2: SSI2 receive (SSI2Rx) */
tiva_configgpio(GPIO_SSI2_TX); /* PE3: SSI2 transmit (SSI2Tx) */
break;
@@ -1619,10 +1602,9 @@ FAR struct spi_dev_s *tiva_ssibus_initialize(int port)
tiva_ssi3_enablepwr();
tiva_ssi3_enableclk();
/* Configure SSI3 GPIOs */
/* Configure SSI3 GPIOs (except for SSI3Fss) */
tiva_configgpio(GPIO_SSI3_CLK); /* PE0: SSI3 clock (SSI3Clk) */
/* tiva_configgpio(GPIO_SSI3_FSS); PE1: SSI3 frame (SSI3Fss) */
tiva_configgpio(GPIO_SSI3_RX); /* PE2: SSI3 receive (SSI3Rx) */
tiva_configgpio(GPIO_SSI3_TX); /* PE3: SSI3 transmit (SSI3Tx) */
break;