mirror of
https://github.com/apache/nuttx.git
synced 2026-06-06 16:50:55 +08:00
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:
committed by
Abdelatif Guettouche
parent
4d771c2bcf
commit
4892c27b4a
+15
-29
@@ -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
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
@@ -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", 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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user