diff --git a/arch/arm/src/imx1/imx_spi.c b/arch/arm/src/imx1/imx_spi.c index 388ae8a6027..a3c589515df 100644 --- a/arch/arm/src/imx1/imx_spi.c +++ b/arch/arm/src/imx1/imx_spi.c @@ -1,35 +1,20 @@ /**************************************************************************** * arch/arm/src/imx1/imx_spi.c * - * Copyright (C) 2009-2017 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt + * 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 } /**************************************************************************** diff --git a/arch/arm/src/imx6/imx_ecspi.c b/arch/arm/src/imx6/imx_ecspi.c index 8bcc0d8a371..d767f18903d 100644 --- a/arch/arm/src/imx6/imx_ecspi.c +++ b/arch/arm/src/imx6/imx_ecspi.c @@ -1,40 +1,20 @@ /**************************************************************************** * arch/arm/src/imx6/imx_ecspi.c * - * Copyright (C) 2016-2017 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt + * 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 - * - * 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 } /**************************************************************************** diff --git a/arch/arm/src/samd2l2/sam_spi.c b/arch/arm/src/samd2l2/sam_spi.c index 74fd9ccf74e..c9185013e26 100644 --- a/arch/arm/src/samd2l2/sam_spi.c +++ b/arch/arm/src/samd2l2/sam_spi.c @@ -1,42 +1,28 @@ /**************************************************************************** * arch/arm/src/samd2l2/sam_spi.c * - * Copyright (C) 2014-2018 Gregory Nutt. All rights reserved. - * Authors: Gregory Nutt + * 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", 42129J–SAM–12/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", 42129J–SAM–12/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; diff --git a/arch/arm/src/samd5e5/sam_spi.c b/arch/arm/src/samd5e5/sam_spi.c index 0a8fd7c0473..e75ad2245e1 100644 --- a/arch/arm/src/samd5e5/sam_spi.c +++ b/arch/arm/src/samd5e5/sam_spi.c @@ -1,35 +1,20 @@ /**************************************************************************** * arch/arm/src/samd5e5/sam_spi.c * - * Copyright (C) 2018 Gregory Nutt. All rights reserved. - * Authors: Gregory Nutt + * 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; diff --git a/arch/arm/src/samv7/sam_spi_slave.c b/arch/arm/src/samv7/sam_spi_slave.c index b4780edd0ed..169ea1adc5e 100644 --- a/arch/arm/src/samv7/sam_spi_slave.c +++ b/arch/arm/src/samv7/sam_spi_slave.c @@ -1,35 +1,20 @@ /**************************************************************************** * arch/arm/src/samv7/sam_spi_slave.c * - * Copyright (C) 2015, 2017 Gregory Nutt. All rights reserved. - * Authors: Gregory Nutt + * 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 */ diff --git a/arch/arm/src/samv7/sam_ssc.c b/arch/arm/src/samv7/sam_ssc.c index 2e7a1fc2f37..113278d3dfd 100644 --- a/arch/arm/src/samv7/sam_ssc.c +++ b/arch/arm/src/samv7/sam_ssc.c @@ -1,35 +1,20 @@ /**************************************************************************** * arch/arm/src/samv7/sam_ssc.c * - * Copyright (C) 2015-2017 Gregory Nutt. All rights reserved. - * Authors: Gregory Nutt + * 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 */ diff --git a/arch/arm/src/stm32/stm32_spi.c b/arch/arm/src/stm32/stm32_spi.c index 160e2778b21..e6d3f736c67 100644 --- a/arch/arm/src/stm32/stm32_spi.c +++ b/arch/arm/src/stm32/stm32_spi.c @@ -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); } diff --git a/arch/arm/src/stm32f0l0g0/stm32_spi.c b/arch/arm/src/stm32f0l0g0/stm32_spi.c index c035785ecae..d7a11d46b70 100644 --- a/arch/arm/src/stm32f0l0g0/stm32_spi.c +++ b/arch/arm/src/stm32f0l0g0/stm32_spi.c @@ -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 + * 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; diff --git a/arch/arm/src/stm32f7/stm32_spi.c b/arch/arm/src/stm32f7/stm32_spi.c index 9d82b48d4a7..31c70b6da5f 100644 --- a/arch/arm/src/stm32f7/stm32_spi.c +++ b/arch/arm/src/stm32f7/stm32_spi.c @@ -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); diff --git a/arch/arm/src/stm32h7/stm32_spi.c b/arch/arm/src/stm32h7/stm32_spi.c index a9251bb9d4e..c071585a91c 100644 --- a/arch/arm/src/stm32h7/stm32_spi.c +++ b/arch/arm/src/stm32h7/stm32_spi.c @@ -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); diff --git a/arch/arm/src/stm32l4/stm32l4_spi.c b/arch/arm/src/stm32l4/stm32l4_spi.c index e264758f076..0771a1b710f 100644 --- a/arch/arm/src/stm32l4/stm32l4_spi.c +++ b/arch/arm/src/stm32l4/stm32l4_spi.c @@ -1,35 +1,20 @@ /**************************************************************************** * arch/arm/src/stm32l4/stm32l4_spi.c * - * Copyright (C) 2009-2013, 2016 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt + * 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; diff --git a/arch/arm/src/tiva/common/tiva_ssi.c b/arch/arm/src/tiva/common/tiva_ssi.c index 7a10329e8d2..3eab257c52c 100644 --- a/arch/arm/src/tiva/common/tiva_ssi.c +++ b/arch/arm/src/tiva/common/tiva_ssi.c @@ -1,35 +1,20 @@ /**************************************************************************** * arch/arm/src/tiva/common/tiva_ssi.c * - * Copyright (C) 2009-2017 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt + * 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;