You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by gn...@apache.org on 2020/04/02 15:06:19 UTC
[incubator-nuttx] branch master updated: Check return from
nxsem_wait_uninterruptible() This commit is for all DMA drivers under
arch/.
This is an automated email from the ASF dual-hosted git repository.
gnutt pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new 4d771c2 Check return from nxsem_wait_uninterruptible() This commit is for all DMA drivers under arch/.
4d771c2 is described below
commit 4d771c2bcf8df2b7e84830e4ac5a1aafe78855af
Author: Ouss4 <ab...@gmail.com>
AuthorDate: Wed Apr 1 20:58:06 2020 +0100
Check return from nxsem_wait_uninterruptible()
This commit is for all DMA drivers under arch/.
---
arch/arm/src/efm32/efm32_dma.c | 44 ++++--
arch/arm/src/imxrt/imxrt_edma.c | 102 ++++++++------
arch/arm/src/lpc17xx_40xx/lpc17_40_gpdma.c | 33 +++--
arch/arm/src/lpc43xx/lpc43_gpdma.c | 17 ++-
arch/arm/src/sam34/sam_dmac.c | 171 ++++++++++++++---------
arch/arm/src/sama5/sam_dmac.c | 208 +++++++++++++++++-----------
arch/arm/src/samd2l2/sam_dmac.c | 90 +++++++-----
arch/arm/src/samd5e5/sam_dmac.c | 109 +++++++++------
arch/arm/src/samv7/sam_xdmac.c | 118 ++++++++++------
arch/arm/src/stm32/stm32_dma_v1.c | 117 ++++++++++------
arch/arm/src/stm32/stm32_dma_v2.c | 212 +++++++++++++++++------------
arch/arm/src/stm32f0l0g0/stm32_dma_v1.c | 26 ++--
arch/arm/src/stm32f7/stm32_dma.c | 211 ++++++++++++++++------------
arch/mips/src/pic32mz/pic32mz-dma.c | 26 ++--
14 files changed, 910 insertions(+), 574 deletions(-)
diff --git a/arch/arm/src/efm32/efm32_dma.c b/arch/arm/src/efm32/efm32_dma.c
index 64db22d..a6d62bd 100644
--- a/arch/arm/src/efm32/efm32_dma.c
+++ b/arch/arm/src/efm32/efm32_dma.c
@@ -125,7 +125,8 @@ static struct dma_channel_s g_dmach[EFM32_DMA_NCHANNELS];
#endif
#ifdef CONFIG_EFM32_DMA_ALTDSEC
-static struct dma_descriptor_s g_descriptors[DESC_TABLE_SIZE + EFM32_DMA_NCHANNELS]
+static struct dma_descriptor_s
+ g_descriptors[DESC_TABLE_SIZE + EFM32_DMA_NCHANNELS]
__attribute__((aligned(DESC_TABLE_ALIGN)));
#else
static struct dma_descriptor_s g_descriptors[EFM32_DMA_NCHANNELS]
@@ -148,15 +149,18 @@ static struct dma_descriptor_s g_descriptors[EFM32_DMA_NCHANNELS]
*
****************************************************************************/
-static void efm32_set_chctrl(struct dma_channel_s *dmach, dma_config_t config)
+static void efm32_set_chctrl(struct dma_channel_s *dmach,
+ dma_config_t config)
{
uintptr_t regaddr;
uint32_t decoded;
uint32_t regval;
- decoded = (uint32_t)(config & EFM32_DMA_SIGSEL_MASK) >> EFM32_DMA_SIGSEL_SHIFT;
+ decoded = (uint32_t)(config & EFM32_DMA_SIGSEL_MASK) >>
+ EFM32_DMA_SIGSEL_SHIFT;
regval = (decoded << _DMA_CH_CTRL_SIGSEL_SHIFT);
- decoded = (uint32_t)(config & EFM32_DMA_SOURCSEL_MASK) >> EFM32_DMA_SOURCSEL_SHIFT;
+ decoded = (uint32_t)(config & EFM32_DMA_SOURCSEL_MASK) >>
+ EFM32_DMA_SOURCSEL_SHIFT;
regval |= (decoded << _DMA_CH_CTRL_SOURCESEL_SHIFT);
regaddr = EFM32_DMA_CHn_CTRL(dmach->chan);
@@ -337,6 +341,7 @@ DMA_HANDLE efm32_dmachannel(void)
struct dma_channel_s *dmach;
unsigned int chndx;
uint32_t bit;
+ int ret;
/* Take a count from the channel counting semaphore. We may block
* if there are no free channels. When we get the count, then we can
@@ -344,11 +349,20 @@ DMA_HANDLE efm32_dmachannel(void)
* reserved for us.
*/
- nxsem_wait_uninterruptible(&g_dmac.chansem);
+ ret = nxsem_wait_uninterruptible(&g_dmac.chansem);
+ if (ret < 0)
+ {
+ return NULL;
+ }
/* Get exclusive access to the DMA channel list */
- nxsem_wait_uninterruptible(&g_dmac.exclsem);
+ ret = nxsem_wait_uninterruptible(&g_dmac.exclsem);
+ if (ret < 0)
+ {
+ nxsem_post(&g_dmac.chansem);
+ return NULL;
+ }
/* Search for an available DMA channel */
@@ -387,7 +401,7 @@ DMA_HANDLE efm32_dmachannel(void)
* Name: efm32_dmafree
*
* Description:
- * Release a DMA channel. If another thread is waiting for this DMA channel
+ * Release a DMA channel. If another thread is waiting for this DMA channel
* in a call to efm32_dmachannel, then this function will re-assign the
* DMA channel to that thread and wake it up. NOTE: The 'handle' used
* in this argument must NEVER be used again until efm32_dmachannel() is
@@ -413,8 +427,8 @@ void efm32_dmafree(DMA_HANDLE handle)
putreg32(1 << dmach->chan, EFM32_DMA_CHENC);
- /* Mark the channel no longer in use. Clearing the in-use flag is an atomic
- * operation and so should be safe.
+ /* Mark the channel no longer in use. Clearing the in-use flag is an
+ * atomic operation and so should be safe.
*/
dmach->inuse = false;
@@ -459,8 +473,8 @@ void efm32_rxdmasetup(DMA_HANDLE handle, uintptr_t paddr, uintptr_t maddr,
shift = efm32_align_shift(config);
mask = ALIGN_MASK(shift);
- /* Make sure that the number of bytes we are asked to transfer is a multiple
- * of the transfer size.
+ /* Make sure that the number of bytes we are asked to transfer is a
+ * multiple of the transfer size.
*/
xfersize = (1 << shift);
@@ -556,8 +570,8 @@ void efm32_txdmasetup(DMA_HANDLE handle, uintptr_t paddr, uintptr_t maddr,
shift = efm32_align_shift(config);
mask = ALIGN_MASK(shift);
- /* Make sure that the number of bytes we are asked to transfer is a multiple
- * of the transfer size.
+ /* Make sure that the number of bytes we are asked to transfer is a
+ * multiple of the transfer size.
*/
xfersize = (1 << shift);
@@ -651,8 +665,8 @@ void efm32_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg)
bit = 1 << dmach->chan;
if ((dmach->config & EFM32_DMA_SINGLE_MASK) == EFM32_DMA_BUFFER_FULL)
{
- /* Disable the single requests for the channel (i.e. do not react to data
- * available, wait for buffer full)
+ /* Disable the single requests for the channel (i.e. do not react to
+ * data available, wait for buffer full)
*/
putreg32(bit, EFM32_DMA_CHUSEBURSTS);
diff --git a/arch/arm/src/imxrt/imxrt_edma.c b/arch/arm/src/imxrt/imxrt_edma.c
index d4e2ec6..2b59999 100644
--- a/arch/arm/src/imxrt/imxrt_edma.c
+++ b/arch/arm/src/imxrt/imxrt_edma.c
@@ -4,8 +4,8 @@
* Copyright (C) 2018 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gn...@nuttx.org>
*
- * Portions of the eDMA logic derive from NXP sample code which has a compatible
- * BSD 3-clause license:
+ * Portions of the eDMA logic derive from NXP sample code which has a
+ * compatible BSD 3-clause license:
*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
@@ -126,8 +126,8 @@ struct imxrt_dmach_s
#if CONFIG_IMXRT_EDMA_NTCD > 0
/* That TCD list is linked through the DLAST SGA field. The first transfer
- * to be performed is at the head of the list. Subsequent TCDs are added at
- * the tail of the list.
+ * to be performed is at the head of the list. Subsequent TCDs are added
+ * at the tail of the list.
*/
struct imxrt_edmatcd_s *head; /* First TCD in the list */
@@ -183,9 +183,9 @@ static struct imxrt_edmatcd_s g_tcd_pool[CONFIG_IMXRT_EDMA_NTCD]
*
****************************************************************************/
-static void imxrt_takechsem(void)
+static int imxrt_takechsem(void)
{
- nxsem_wait_uninterruptible(&g_edma.chsem);
+ return nxsem_wait_uninterruptible(&g_edma.chsem);
}
static inline void imxrt_givechsem(void)
@@ -302,13 +302,14 @@ static inline void imxrt_tcd_initialize(void)
}
#endif
-/************************************************************************************
+/****************************************************************************
* Name: imxrt_tcd_chanlink
*
* Description:
- * This function configures either a minor link or a major link. The minor link
- * means the channel link is triggered every time CITER decreases by 1. The major
- * link means that the channel link is triggered when the CITER is exhausted.
+ * This function configures either a minor link or a major link. The minor
+ * link means the channel link is triggered every time CITER decreases by 1
+ * The major link means that the channel link is triggered when the CITER
+ * is exhausted.
*
* NOTE: Users should ensure that DONE flag is cleared before calling this
* interface, or the configuration is invalid.
@@ -321,10 +322,11 @@ static inline void imxrt_tcd_initialize(void)
* Returned Value:
* None
*
- ************************************************************************************/
+ ****************************************************************************/
#ifdef CONFIG_IMXRT_EDMA_ELINK
-static inline void imxrt_tcd_chanlink(uint8_t flags, struct imxrt_dmach_s *linkch,
+static inline void imxrt_tcd_chanlink(uint8_t flags,
+ struct imxrt_dmach_s *linkch,
struct imxrt_edmatcd_s *tcd)
{
uint16_t regval16;
@@ -392,7 +394,7 @@ static inline void imxrt_tcd_chanlink(uint8_t flags, struct imxrt_dmach_s *linkc
****************************************************************************/
static inline void imxrt_tcd_configure(struct imxrt_edmatcd_s *tcd,
- const struct imxrt_edma_xfrconfig_s *config)
+ const struct imxrt_edma_xfrconfig_s *config)
{
tcd->saddr = config->saddr;
tcd->soff = config->soff;
@@ -858,7 +860,8 @@ void weak_function up_dma_initialize(void)
*
* Input Parameters:
* dmamux - DMAMUX configuration see DMAMUX channel configuration register
- * bit-field definitions in hardware/imxrt_dmamux.h. Settings include:
+ * bit-field definitions in hardware/imxrt_dmamux.h.
+ * Settings include:
*
* DMAMUX_CHCFG_SOURCE Chip-specific DMA source (required)
* DMAMUX_CHCFG_AON DMA Channel Always Enable (optional)
@@ -886,11 +889,17 @@ DMACH_HANDLE imxrt_dmach_alloc(uint32_t dmamux, uint8_t dchpri)
{
struct imxrt_dmach_s *dmach;
unsigned int chndx;
+ int ret;
/* Search for an available DMA channel */
dmach = NULL;
- imxrt_takechsem();
+ ret = imxrt_takechsem();
+ if (ret < 0)
+ {
+ return NULL;
+ }
+
for (chndx = 0; chndx < IMXRT_EDMA_NCHANNELS; chndx++)
{
struct imxrt_dmach_s *candidate = &g_edma.dmach[chndx];
@@ -958,7 +967,8 @@ void imxrt_dmach_free(DMACH_HANDLE handle)
uint8_t regval8;
dmainfo("dmach: %p\n", dmach);
- DEBUGASSERT(dmach != NULL && dmach->inuse && dmach->state != IMXRT_DMA_ACTIVE);
+ DEBUGASSERT(dmach != NULL && dmach->inuse &&
+ dmach->state != IMXRT_DMA_ACTIVE);
/* Mark the channel no longer in use. Clearing the inuse flag is an atomic
* operation and so should be safe.
@@ -988,7 +998,8 @@ void imxrt_dmach_free(DMACH_HANDLE handle)
* structure. For "normal" DMA, imxrt_dmach_xfrsetup is called only once.
* Scatter/gather DMA is accomplished by calling this function repeatedly,
* once for each transfer in the sequence. Scatter/gather DMA processing
- * is enabled automatically when the second transfer configuration is received.
+ * is enabled automatically when the second transfer configuration is
+ * received.
*
* This function may be called multiple times to handle multiple,
* discontinuous transfers (scatter-gather)
@@ -1020,6 +1031,7 @@ int imxrt_dmach_xfrsetup(DMACH_HANDLE *handle,
#if CONFIG_IMXRT_EDMA_NTCD > 0
/* Scatter/gather DMA is supported */
+
/* Allocate a TCD, waiting if necessary */
tcd = imxrt_tcd_alloc();
@@ -1063,6 +1075,7 @@ int imxrt_dmach_xfrsetup(DMACH_HANDLE *handle,
}
/* Chain from previous descriptor in the list. */
+
/* Enable scatter/gather feature in the previous TCD. */
prev = dmach->tail;
@@ -1120,8 +1133,8 @@ int imxrt_dmach_xfrsetup(DMACH_HANDLE *handle,
/* Configure channel TCD registers to the values specified in config. */
- imxrt_tcd_configure((struct imxrt_edmatcd_s *)IMXRT_EDMA_TCD_BASE(dmach->chan),
- config);
+ imxrt_tcd_configure((struct imxrt_edmatcd_s *)
+ IMXRT_EDMA_TCD_BASE(dmach->chan), config);
/* Enable the DONE interrupt when the major iteration count completes. */
@@ -1162,38 +1175,41 @@ int imxrt_dmach_xfrsetup(DMACH_HANDLE *handle,
return OK;
}
-/************************************************************************************
+/****************************************************************************
* Name: imxrt_dmach_start
*
* Description:
- * Start the DMA transfer. This function should be called after the final call
- * to imxrt_dmach_xfrsetup() in order to avoid race conditions.
+ * Start the DMA transfer. This function should be called after the final
+ * call to imxrt_dmach_xfrsetup() in order to avoid race conditions.
*
- * At the conclusion of each major DMA loop, a callback to the user-provided
- * function is made: |For "normal" DMAs, this will correspond to the DMA DONE
- * interrupt; for scatter gather DMAs, multiple interrupts will be generated
- * with the final being the DONE interrupt.
+ * At the conclusion of each major DMA loop a callback to the user-provided
+ * function is made: |For "normal" DMAs, this will correspond to the DMA
+ * DONE interrupt; for scatter gather DMAs, multiple interrupts will be
+ * generated with the final being the DONE interrupt.
*
- * At the conclusion of the DMA, the DMA channel is reset, all TCDs are freed, and
- * the callback function is called with the the success/fail result of the DMA.
+ * At the conclusion of the DMA, the DMA channel is reset, all TCDs are
+ * freed, and the callback function is called with the the success/fail
+ * result of the DMA.
*
- * NOTE: On Rx DMAs (peripheral-to-memory or memory-to-memory), it is necessary
- * to invalidate the destination memory. That is not done automatically by the
- * DMA module. Invalidation of the destination memory regions is the
- * responsibility of the caller.
+ * NOTE: On Rx DMAs (peripheral-to-memory or memory-to-memory), it is
+ * necessary to invalidate the destination memory. That is not done
+ * automatically by the DMA module. Invalidation of the destination memory
+ * regions is the responsibility of the caller.
*
* Input Parameters:
* handle - DMA channel handle created by imxrt_dmach_alloc()
- * callback - The callback to be invoked when the DMA is completes or is aborted.
+ * callback - The callback to be invoked when the DMA is completes or is
+ * aborted.
* arg - An argument that accompanies the callback
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned on
* any failure.
*
- ************************************************************************************/
+ ****************************************************************************/
-int imxrt_dmach_start(DMACH_HANDLE handle, edma_callback_t callback, void *arg)
+int imxrt_dmach_start(DMACH_HANDLE handle, edma_callback_t callback,
+ void *arg)
{
struct imxrt_dmach_s *dmach = (struct imxrt_dmach_s *)handle;
irqstate_t flags;
@@ -1212,8 +1228,8 @@ int imxrt_dmach_start(DMACH_HANDLE handle, edma_callback_t callback, void *arg)
dmach->state = IMXRT_DMA_ACTIVE;
#if CONFIG_IMXRT_EDMA_NTCD > 0
- /* Although it is not recommended, it might be possible to call this function multiple times
- * while adding TCDs on the fly.
+ /* Although it is not recommended, it might be possible to call this
+ * function multiple times while adding TCDs on the fly.
*/
if (dmach->state != IMXRT_DMA_ACTIVE)
@@ -1234,13 +1250,13 @@ int imxrt_dmach_start(DMACH_HANDLE handle, edma_callback_t callback, void *arg)
return OK;
}
-/************************************************************************************
+/****************************************************************************
* Name: imxrt_dmach_stop
*
* Description:
- * Cancel the DMA. After imxrt_dmach_stop() is called, the DMA channel is reset,
- * all TCDs are freed, and imxrt_dmarx/txsetup() must be called before
- * imxrt_dmach_start() can be called again
+ * Cancel the DMA. After imxrt_dmach_stop() is called, the DMA channel is
+ * reset, all TCDs are freed, and imxrt_dmarx/txsetup() must be called
+ * before imxrt_dmach_start() can be called again
*
* Input Parameters:
* handle - DMA channel handle created by imxrt_dmach_alloc()
@@ -1248,7 +1264,7 @@ int imxrt_dmach_start(DMACH_HANDLE handle, edma_callback_t callback, void *arg)
* Returned Value:
* None.
*
- ************************************************************************************/
+ ****************************************************************************/
void imxrt_dmach_stop(DMACH_HANDLE handle)
{
@@ -1286,7 +1302,7 @@ void imxrt_dmach_stop(DMACH_HANDLE handle)
* initial value of NBYTES (for example copied before enabling the channel)
* is needed. The formula to calculate it is shown below:
*
- * RemainingBytes = RemainingMajorLoopCount * NBYTES(initially configured)
+ * RemainingBytes = RemainingMajorLoopCount * NBYTES(initially configured)
*
* Input Parameters:
* handle - DMA channel handle created by imxrt_dmach_alloc()
diff --git a/arch/arm/src/lpc17xx_40xx/lpc17_40_gpdma.c b/arch/arm/src/lpc17xx_40xx/lpc17_40_gpdma.c
index 15c69b0..77cfef3 100644
--- a/arch/arm/src/lpc17xx_40xx/lpc17_40_gpdma.c
+++ b/arch/arm/src/lpc17xx_40xx/lpc17_40_gpdma.c
@@ -67,6 +67,7 @@
/****************************************************************************
* Private Types
****************************************************************************/
+
/* This structure represents the state of one DMA channel */
struct lpc17_40_dmach_s
@@ -97,6 +98,7 @@ struct lpc17_40_gpdma_s
/****************************************************************************
* Private Data
****************************************************************************/
+
/* The state of the LPC17 DMA block */
static struct lpc17_40_gpdma_s g_gpdma;
@@ -150,8 +152,8 @@ static void lpc17_40_dmainprogress(struct lpc17_40_dmach_s *dmach)
* Description:
* A DMA has completed. Decrement the g_dma_inprogress counter.
*
- * This function is called only from lpc17_40_dmastop which, in turn, will be
- * called either by the user directly, by the user indirectly via
+ * This function is called only from lpc17_40_dmastop which, in turn, will
+ * be called either by the user directly, by the user indirectly via
* lpc17_40_dmafree(), or from gpdma_interrupt when the transfer completes.
*
* NOTE: In the first two cases, we must be able to handle the case where
@@ -272,8 +274,8 @@ static int gpdma_interrupt(int irq, FAR void *context, FAR void *arg)
* Name: up_dma_initialize
*
* Description:
- * Initialize the GPDMA subsystem. Called from up_initialize() early in the
- * boot-up sequence. Prototyped in up_internal.h.
+ * Initialize the GPDMA subsystem. Called from up_initialize() early in
+ * the boot-up sequence. Prototyped in up_internal.h.
*
* Returned Value:
* None
@@ -390,10 +392,15 @@ DMA_HANDLE lpc17_40_dmachannel(void)
{
struct lpc17_40_dmach_s *dmach = NULL;
int i;
+ int ret;
/* Get exclusive access to the GPDMA state structure */
- nxsem_wait_uninterruptible(&g_gpdma.exclsem);
+ ret = nxsem_wait_uninterruptible(&g_gpdma.exclsem);
+ if (ret < 0)
+ {
+ return NULL;
+ }
/* Find an available DMA channel */
@@ -420,8 +427,8 @@ DMA_HANDLE lpc17_40_dmachannel(void)
*
* Description:
* Release a DMA channel. NOTE: The 'handle' used in this argument must
- * NEVER be used again until lpc17_40_dmachannel() is called again to re-gain
- * a valid handle.
+ * NEVER be used again until lpc17_40_dmachannel() is called again to
+ * re-gain a valid handle.
*
* Returned Value:
* None
@@ -582,7 +589,8 @@ int lpc17_40_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg)
base = LPC17_40_DMACH_BASE((uint32_t)dmach->chn);
regval = getreg32(base + LPC17_40_DMACH_CONTROL_OFFSET);
regval &= ~DMACH_CONTROL_XFRSIZE_MASK;
- regval |= (DMACH_CONTROL_I | ((uint32_t)dmach->nxfrs << DMACH_CONTROL_XFRSIZE_SHIFT));
+ regval |= (DMACH_CONTROL_I |
+ ((uint32_t)dmach->nxfrs << DMACH_CONTROL_XFRSIZE_SHIFT));
putreg32(regval, base + LPC17_40_DMACH_CONTROL_OFFSET);
/* Enable the channel and unmask terminal count and error interrupts.
@@ -602,8 +610,8 @@ int lpc17_40_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg)
*
* Description:
* Cancel the DMA. After lpc17_40_dmastop() is called, the DMA channel is
- * reset and lpc17_40_dmasetup() must be called before lpc17_40_dmastart() can be
- * called again
+ * reset and lpc17_40_dmasetup() must be called before lpc17_40_dmastart()
+ * can be called again
*
* This function will be called either by the user directly, by the user
* indirectly via lpc17_40_dmafree(), or from gpdma_interrupt when the
@@ -692,8 +700,9 @@ void lpc17_40_dmasample(DMA_HANDLE handle, struct lpc17_40_dmaregs_s *regs)
****************************************************************************/
#ifdef CONFIG__DEBUG_DMA_INFO
-void lpc17_40_dmadump(DMA_HANDLE handle, const struct lpc17_40_dmaregs_s *regs,
- const char *msg)
+void lpc17_40_dmadump(DMA_HANDLE handle,
+ const struct lpc17_40_dmaregs_s *regs,
+ const char *msg)
{
struct lpc17_40_dmach_s *dmach = (DMA_HANDLE)handle;
uint32_t base;
diff --git a/arch/arm/src/lpc43xx/lpc43_gpdma.c b/arch/arm/src/lpc43xx/lpc43_gpdma.c
index 784dca3..5ef6d00 100644
--- a/arch/arm/src/lpc43xx/lpc43_gpdma.c
+++ b/arch/arm/src/lpc43xx/lpc43_gpdma.c
@@ -272,8 +272,8 @@ static int gpdma_interrupt(int irq, FAR void *context, FAR void *arg)
* Name: up_dma_initialize
*
* Description:
- * Initialize the GPDMA subsystem. Called from up_initialize() early in the
- * boot-up sequence. Prototyped in up_internal.h.
+ * Initialize the GPDMA subsystem. Called from up_initialize() early in
+ * the boot-up sequence. Prototyped in up_internal.h.
*
* Returned Value:
* None
@@ -391,10 +391,15 @@ DMA_HANDLE lpc43_dmachannel(void)
{
struct lpc43_dmach_s *dmach = NULL;
int i;
+ int ret;
/* Get exclusive access to the GPDMA state structure */
- nxsem_wait_uninterruptible(&g_gpdma.exclsem);
+ ret = nxsem_wait_uninterruptible(&g_gpdma.exclsem);
+ if (ret < 0)
+ {
+ return NULL;
+ }
/* Find an available DMA channel */
@@ -584,7 +589,8 @@ int lpc43_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg)
base = LPC43_GPDMA_CHANNEL((uint32_t)dmach->chn);
regval = getreg32(base + LPC43_GPDMA_CONTROL_CHOFFSET);
regval &= ~GPDMA_CONTROL_XFRSIZE_MASK;
- regval |= (GPDMA_CONTROL_IE | ((uint32_t)dmach->nxfrs << GPDMA_CONTROL_XFRSIZE_SHIFT));
+ regval |= (GPDMA_CONTROL_IE |
+ ((uint32_t)dmach->nxfrs << GPDMA_CONTROL_XFRSIZE_SHIFT));
putreg32(regval, base + LPC43_GPDMA_CONTROL_CHOFFSET);
/* Enable the channel and unmask terminal count and error interrupts.
@@ -694,7 +700,8 @@ void lpc43_dmasample(DMA_HANDLE handle, struct lpc43_dmaregs_s *regs)
****************************************************************************/
#ifdef CONFIG_DEBUG_DMA
-void lpc43_dmadump(DMA_HANDLE handle, const struct lpc43_dmaregs_s *regs, const char *msg)
+void lpc43_dmadump(DMA_HANDLE handle, const struct lpc43_dmaregs_s *regs,
+ const char *msg)
{
struct lpc43_dmach_s *dmach = (DMA_HANDLE)handle;
uint32_t base;
diff --git a/arch/arm/src/sam34/sam_dmac.c b/arch/arm/src/sam34/sam_dmac.c
index 50ea405..cee2d4a 100644
--- a/arch/arm/src/sam34/sam_dmac.c
+++ b/arch/arm/src/sam34/sam_dmac.c
@@ -273,9 +273,9 @@ static struct sam_dma_s g_dma[SAM34_NDMACHAN] =
*
****************************************************************************/
-static void sam_takechsem(void)
+static int sam_takechsem(void)
{
- nxsem_wait_uninterruptible(&g_chsem);
+ return nxsem_wait_uninterruptible(&g_chsem);
}
static inline void sam_givechsem(void)
@@ -332,7 +332,9 @@ static unsigned int sam_fifosize(uint8_t chflags)
static inline uint32_t sam_fifocfg(struct sam_dma_s *dmach)
{
- unsigned int ndx = (dmach->flags & DMACH_FLAG_FIFOCFG_MASK) >> DMACH_FLAG_FIFOCFG_SHIFT;
+ unsigned int ndx;
+
+ ndx = (dmach->flags & DMACH_FLAG_FIFOCFG_MASK) >> DMACH_FLAG_FIFOCFG_SHIFT;
DEBUGASSERT(ndx < 3);
return g_fifocfg[ndx];
}
@@ -353,10 +355,14 @@ static inline uint32_t sam_txcfg(struct sam_dma_s *dmach)
/* Set transfer (memory to peripheral) DMA channel configuration register */
regval = DMACHAN_CFG_SOD;
- regval |= (((dmach->flags & DMACH_FLAG_MEMPID_MASK) >> DMACH_FLAG_MEMPID_SHIFT) << DMACHAN_CFG_SRCPER_SHIFT);
- regval |= (dmach->flags & DMACH_FLAG_MEMH2SEL) != 0 ? DMACHAN_CFG_SRCH2SEL : 0;
- regval |= (((dmach->flags & DMACH_FLAG_PERIPHPID_MASK) >> DMACH_FLAG_PERIPHPID_SHIFT) << DMACHAN_CFG_DSTPER_SHIFT);
- regval |= (dmach->flags & DMACH_FLAG_PERIPHH2SEL) != 0 ? DMACHAN_CFG_DSTH2SEL : 0;
+ regval |= (((dmach->flags & DMACH_FLAG_MEMPID_MASK) >>
+ DMACH_FLAG_MEMPID_SHIFT) << DMACHAN_CFG_SRCPER_SHIFT);
+ regval |= (dmach->flags & DMACH_FLAG_MEMH2SEL) != 0 ?
+ DMACHAN_CFG_SRCH2SEL : 0;
+ regval |= (((dmach->flags & DMACH_FLAG_PERIPHPID_MASK) >>
+ DMACH_FLAG_PERIPHPID_SHIFT) << DMACHAN_CFG_DSTPER_SHIFT);
+ regval |= (dmach->flags & DMACH_FLAG_PERIPHH2SEL) != 0 ?
+ DMACHAN_CFG_DSTH2SEL : 0;
regval |= sam_fifocfg(dmach);
return regval;
}
@@ -377,10 +383,14 @@ static inline uint32_t sam_rxcfg(struct sam_dma_s *dmach)
/* Set received (peripheral to memory) DMA channel config */
regval = DMACHAN_CFG_SOD;
- regval |= (((dmach->flags & DMACH_FLAG_PERIPHPID_MASK) >> DMACH_FLAG_PERIPHPID_SHIFT) << DMACHAN_CFG_SRCPER_SHIFT);
- regval |= (dmach->flags & DMACH_FLAG_PERIPHH2SEL) != 0 ? DMACHAN_CFG_SRCH2SEL : 0;
- regval |= (((dmach->flags & DMACH_FLAG_MEMPID_MASK) >> DMACH_FLAG_MEMPID_SHIFT) << DMACHAN_CFG_DSTPER_SHIFT);
- regval |= (dmach->flags & DMACH_FLAG_MEMH2SEL) != 0 ? DMACHAN_CFG_DSTH2SEL : 0;
+ regval |= (((dmach->flags & DMACH_FLAG_PERIPHPID_MASK) >>
+ DMACH_FLAG_PERIPHPID_SHIFT) << DMACHAN_CFG_SRCPER_SHIFT);
+ regval |= (dmach->flags & DMACH_FLAG_PERIPHH2SEL) != 0 ?
+ DMACHAN_CFG_SRCH2SEL : 0;
+ regval |= (((dmach->flags & DMACH_FLAG_MEMPID_MASK) >>
+ DMACH_FLAG_MEMPID_SHIFT) << DMACHAN_CFG_DSTPER_SHIFT);
+ regval |= (dmach->flags & DMACH_FLAG_MEMH2SEL) != 0 ?
+ DMACHAN_CFG_DSTH2SEL : 0;
regval |= sam_fifocfg(dmach);
return regval;
}
@@ -404,11 +414,12 @@ sam_txctrlabits(struct sam_dma_s *dmach)
DEBUGASSERT(dmach);
- /* Since this is a transmit, the source is described by the memory selections.
- * Set the source width (memory width).
+ /* Since this is a transmit, the source is described by the memory
+ * selection. Set the source width (memory width).
*/
- ndx = (dmach->flags & DMACH_FLAG_MEMWIDTH_MASK) >> DMACH_FLAG_MEMWIDTH_SHIFT;
+ ndx = (dmach->flags & DMACH_FLAG_MEMWIDTH_MASK) >>
+ DMACH_FLAG_MEMWIDTH_SHIFT;
DEBUGASSERT(ndx < 3);
regval = g_srcwidth[ndx];
@@ -428,11 +439,12 @@ sam_txctrlabits(struct sam_dma_s *dmach)
#endif
#endif
- /* Since this is a transmit, the destination is described by the peripheral selections.
- * Set the destination width (peripheral width).
+ /* Since this is a transmit, the destination is described by the peripheral
+ * selections. Set the destination width (peripheral width).
*/
- ndx = (dmach->flags & DMACH_FLAG_PERIPHWIDTH_MASK) >> DMACH_FLAG_PERIPHWIDTH_SHIFT;
+ ndx = (dmach->flags & DMACH_FLAG_PERIPHWIDTH_MASK) >>
+ DMACH_FLAG_PERIPHWIDTH_SHIFT;
DEBUGASSERT(ndx < 3);
regval |= g_destwidth[ndx];
@@ -440,7 +452,8 @@ sam_txctrlabits(struct sam_dma_s *dmach)
defined(CONFIG_ARCH_CHIP_SAM3A)
/* Set the destination chunk size (peripheral chunk size) */
- if ((dmach->flags & DMACH_FLAG_PERIPHCHUNKSIZE) == DMACH_FLAG_PERIPHCHUNKSIZE_4)
+ if ((dmach->flags & DMACH_FLAG_PERIPHCHUNKSIZE) ==
+ DMACH_FLAG_PERIPHCHUNKSIZE_4)
{
regval |= DMACHAN_CTRLA_DCSIZE_4;
}
@@ -559,7 +572,8 @@ static inline uint32_t sam_rxctrlabits(struct sam_dma_s *dmach)
* selections. Set the source width (peripheral width).
*/
- ndx = (dmach->flags & DMACH_FLAG_PERIPHWIDTH_MASK) >> DMACH_FLAG_PERIPHWIDTH_SHIFT;
+ ndx = (dmach->flags & DMACH_FLAG_PERIPHWIDTH_MASK) >>
+ DMACH_FLAG_PERIPHWIDTH_SHIFT;
DEBUGASSERT(ndx < 3);
regval = g_srcwidth[ndx];
@@ -567,7 +581,8 @@ static inline uint32_t sam_rxctrlabits(struct sam_dma_s *dmach)
defined(CONFIG_ARCH_CHIP_SAM3A)
/* Set the source chunk size (peripheral chunk size) */
- if ((dmach->flags & DMACH_FLAG_PERIPHCHUNKSIZE) == DMACH_FLAG_PERIPHCHUNKSIZE_4)
+ if ((dmach->flags & DMACH_FLAG_PERIPHCHUNKSIZE) ==
+ DMACH_FLAG_PERIPHCHUNKSIZE_4)
{
regval |= DMACHAN_CTRLA_SCSIZE_4;
}
@@ -579,11 +594,12 @@ static inline uint32_t sam_rxctrlabits(struct sam_dma_s *dmach)
#endif
#endif
- /* Since this is a receive, the destination is described by the memory selections.
- * Set the destination width (memory width).
+ /* Since this is a receive, the destination is described by the memory
+ * selections. Set the destination width (memory width).
*/
- ndx = (dmach->flags & DMACH_FLAG_MEMWIDTH_MASK) >> DMACH_FLAG_MEMWIDTH_SHIFT;
+ ndx = (dmach->flags & DMACH_FLAG_MEMWIDTH_MASK) >>
+ DMACH_FLAG_MEMWIDTH_SHIFT;
DEBUGASSERT(ndx < 3);
regval |= g_destwidth[ndx];
@@ -764,6 +780,7 @@ static inline uint32_t sam_txctrlb(struct sam_dma_s *dmach)
{
regval |= DMACHAN_CTRLB_DSTINCR_FIXED;
}
+
return regval;
}
@@ -780,8 +797,8 @@ static inline uint32_t sam_rxctrlb(struct sam_dma_s *dmach)
{
uint32_t regval;
- /* Assume that we will not be using the link list and disable the source and
- * destination descriptors. The default will be single transfer mode.
+ /* Assume that we will not be using the link list and disable the source
+ * and destination descriptors. The default will be single transfer mode.
*/
regval = DMACHAN_CTRLB_BOTHDSCR;
@@ -867,6 +884,7 @@ sam_allocdesc(struct sam_dma_s *dmach, struct dma_linklist_s *prev,
{
struct dma_linklist_s *desc = NULL;
int i;
+ int ret;
/* Sanity check -- src == 0 is the indication that the link is unused.
* Obviously setting it to zero would break that usage.
@@ -876,8 +894,8 @@ sam_allocdesc(struct sam_dma_s *dmach, struct dma_linklist_s *prev,
if (src != 0)
#endif
{
- /* Table a descriptor table semaphore count. When we get one, then there
- * is at least one free descriptor in the table and it is ours.
+ /* Table a descriptor table semaphore count. When we get one, then
+ * there is at least one free descriptor in the table and it is ours.
*/
sam_takedsem();
@@ -888,7 +906,12 @@ sam_allocdesc(struct sam_dma_s *dmach, struct dma_linklist_s *prev,
* that is an atomic operation.
*/
- sam_takechsem();
+ ret = sam_takechsem();
+ if (ret < 0)
+ {
+ return NULL;
+ }
+
for (i = 0; i < CONFIG_SAM34_NLLDESC; i++)
{
if (g_linklist[i].src == 0)
@@ -910,12 +933,14 @@ sam_allocdesc(struct sam_dma_s *dmach, struct dma_linklist_s *prev,
* the list
*/
- DEBUGASSERT(dmach->llhead == NULL && dmach->lltail == NULL);
+ DEBUGASSERT(dmach->llhead == NULL &&
+ dmach->lltail == NULL);
dmach->llhead = desc;
}
else
{
- DEBUGASSERT(dmach->llhead != NULL && dmach->lltail == prev);
+ DEBUGASSERT(dmach->llhead != NULL &&
+ dmach->lltail == prev);
/* When the second link is added to the list, that is the
* cue that we are going to do the link list transfer.
@@ -934,8 +959,9 @@ sam_allocdesc(struct sam_dma_s *dmach, struct dma_linklist_s *prev,
}
/* In any event, this is the new tail of the list. The source
- * and destination descriptors must be disabled for the last entry
- * in the link list. */
+ * and destination descriptors must be disabled for the last
+ * entry in the link list.
+ */
desc->ctrlb |= DMACHAN_CTRLB_BOTHDSCR;
dmach->lltail = desc;
@@ -1070,7 +1096,7 @@ static int sam_rxbuffer(struct sam_dma_s *dmach, uint32_t paddr,
ctrlb = sam_rxctrlb(dmach);
}
- ctrla = sam_rxctrla(dmach, regval, nbytes);
+ ctrla = sam_rxctrla(dmach, regval, nbytes);
/* Add the new link list entry */
@@ -1131,7 +1157,8 @@ static inline int sam_single(struct sam_dma_s *dmach)
/* Both the DST and SRC DSCR bits should be '1' in CTRLB */
- DEBUGASSERT((llhead->ctrlb & DMACHAN_CTRLB_BOTHDSCR) == DMACHAN_CTRLB_BOTHDSCR);
+ DEBUGASSERT((llhead->ctrlb & DMACHAN_CTRLB_BOTHDSCR) ==
+ DMACHAN_CTRLB_BOTHDSCR);
/* Set up the CFG register */
@@ -1142,8 +1169,8 @@ static inline int sam_single(struct sam_dma_s *dmach)
putreg32(DMAC_CHER_ENA(dmach->chan), SAM_DMAC_CHER);
/* The DMA has been started. Once the transfer completes, hardware sets the
- * interrupts and disables the channel. We will received buffer complete and
- * transfer complete interrupts.
+ * interrupts and disables the channel. We will received buffer complete
+ * and transfer complete interrupts.
*
* Enable error, buffer complete and transfer complete interrupts.
* (Since there is only a single buffer, we don't need the buffer complete
@@ -1171,10 +1198,11 @@ static inline int sam_multiple(struct sam_dma_s *dmach)
/* Check the first and last CTRLB values */
DEBUGASSERT((llhead->ctrlb & DMACHAN_CTRLB_BOTHDSCR) == 0);
- DEBUGASSERT((dmach->lltail->ctrlb & DMACHAN_CTRLB_BOTHDSCR) == DMACHAN_CTRLB_BOTHDSCR);
+ DEBUGASSERT((dmach->lltail->ctrlb & DMACHAN_CTRLB_BOTHDSCR) ==
+ DMACHAN_CTRLB_BOTHDSCR);
- /* Clear any pending interrupts from any previous DMAC transfer by reading the
- * status register
+ /* Clear any pending interrupts from any previous DMAC transfer by reading
+ * the status register
*
* REVISIT: If DMAC interrupts are disabled at the NVIKC, then reading the
* EBCISR register could cause a loss of interrupts!
@@ -1202,12 +1230,13 @@ static inline int sam_multiple(struct sam_dma_s *dmach)
putreg32(DMAC_CHER_ENA(dmach->chan), SAM_DMAC_CHER);
- /* As each buffer of data is transferred, the CTRLA register is written back
- * into the link list entry. The CTRLA contains updated BTSIZE and DONE bits.
- * Additionally, the CTRLA DONE bit is asserted when the buffer transfer has completed.
+ /* As each buffer of data is transferred, the CTRLA register is written
+ * back into the link list entry. The CTRLA contains updated BTSIZE and
+ * DONE bits. Additionally, the CTRLA DONE bit is asserted when the buffer
+ * transfer has completed.
*
- * The DMAC transfer continues until the CTRLB register disables the descriptor
- * (DSCR bits) registers at the final buffer transfer.
+ * The DMAC transfer continues until the CTRLB register disables the
+ * descriptor (DSCR bits) registers at the final buffer transfer.
*
* Enable error, buffer complete and transfer complete interrupts. We
* don't really need the buffer complete interrupts, but we will take them
@@ -1394,6 +1423,7 @@ DMA_HANDLE sam_dmachannel(uint32_t chflags)
struct sam_dma_s *dmach;
unsigned int fifosize;
unsigned int chndx;
+ int ret;
/* Get the search parameters */
@@ -1404,7 +1434,11 @@ DMA_HANDLE sam_dmachannel(uint32_t chflags)
*/
dmach = NULL;
- sam_takechsem();
+ ret = sam_takechsem();
+ if (ret < 0)
+ {
+ return NULL;
+ }
for (chndx = 0; chndx < SAM34_NDMACHAN; chndx++)
{
@@ -1447,13 +1481,14 @@ DMA_HANDLE sam_dmachannel(uint32_t chflags)
return (DMA_HANDLE)dmach;
}
-/************************************************************************************
+/****************************************************************************
* Name: sam_dmaconfig
*
* Description:
- * There are two channel usage models: (1) The channel is allocated and configured
- * in one step. This is the typical case where a DMA channel performs a constant
- * role. The alternative is (2) where the DMA channel is reconfigured on the fly.
+ * There are two channel usage models: (1) The channel is allocated and
+ * configured in one step. This is the typical case where a DMA channel
+ * performs a constant role. The alternative is (2) where the DMA channel
+ * is reconfigured on the fly.
* In this case, the chflags provided to sam_dmachannel are not used and
* sam_dmaconfig() is called before each DMA to configure the DMA channel
* appropriately.
@@ -1461,7 +1496,7 @@ DMA_HANDLE sam_dmachannel(uint32_t chflags)
* Returned Value:
* None
*
- ************************************************************************************/
+ ****************************************************************************/
void sam_dmaconfig(DMA_HANDLE handle, uint32_t chflags)
{
@@ -1512,7 +1547,8 @@ void sam_dmafree(DMA_HANDLE handle)
*
****************************************************************************/
-int sam_dmatxsetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr, size_t nbytes)
+int sam_dmatxsetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr,
+ size_t nbytes)
{
struct sam_dma_s *dmach = (struct sam_dma_s *)handle;
ssize_t remaining = (ssize_t)nbytes;
@@ -1543,8 +1579,8 @@ int sam_dmatxsetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr, size_t nby
remaining -= maxtransfer;
- /* Increment the memory & peripheral address (if it is appropriate to
- * do do).
+ /* Increment the memory & peripheral address (if it is appropriate
+ * to do).
*/
if ((dmach->flags & DMACH_FLAG_PERIPHINCREMENT) != 0)
@@ -1580,7 +1616,8 @@ int sam_dmatxsetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr, size_t nby
*
****************************************************************************/
-int sam_dmarxsetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr, size_t nbytes)
+int sam_dmarxsetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr,
+ size_t nbytes)
{
struct sam_dma_s *dmach = (struct sam_dma_s *)handle;
ssize_t remaining = (ssize_t)nbytes;
@@ -1611,8 +1648,8 @@ int sam_dmarxsetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr, size_t nby
remaining -= maxtransfer;
- /* Increment the memory & peripheral address (if it is appropriate to
- * do do).
+ /* Increment the memory & peripheral address (if it is appropriate
+ * to do).
*/
if ((dmach->flags & DMACH_FLAG_PERIPHINCREMENT) != 0)
@@ -1684,8 +1721,8 @@ int sam_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg)
*
* Description:
* Cancel the DMA. After sam_dmastop() is called, the DMA channel is
- * reset and sam_dmarx/txsetup() must be called before sam_dmastart() can be
- * called again
+ * reset and sam_dmarx/txsetup() must be called before sam_dmastart() can
+ * be called again
*
****************************************************************************/
@@ -1773,12 +1810,18 @@ void sam_dmadump(DMA_HANDLE handle, const struct sam_dmaregs_s *regs,
dmainfo(" EBCIMR[%08x]: %08x\n", SAM_DMAC_EBCIMR, regs->ebcimr);
dmainfo(" CHSR[%08x]: %08x\n", SAM_DMAC_CHSR, regs->chsr);
dmainfo(" DMA Channel Registers:\n");
- dmainfo(" SADDR[%08x]: %08x\n", dmach->base + SAM_DMACHAN_SADDR_OFFSET, regs->saddr);
- dmainfo(" DADDR[%08x]: %08x\n", dmach->base + SAM_DMACHAN_DADDR_OFFSET, regs->daddr);
- dmainfo(" DSCR[%08x]: %08x\n", dmach->base + SAM_DMACHAN_DSCR_OFFSET, regs->dscr);
- dmainfo(" CTRLA[%08x]: %08x\n", dmach->base + SAM_DMACHAN_CTRLA_OFFSET, regs->ctrla);
- dmainfo(" CTRLB[%08x]: %08x\n", dmach->base + SAM_DMACHAN_CTRLB_OFFSET, regs->ctrlb);
- dmainfo(" CFG[%08x]: %08x\n", dmach->base + SAM_DMACHAN_CFG_OFFSET, regs->cfg);
+ dmainfo(" SADDR[%08x]: %08x\n",
+ dmach->base + SAM_DMACHAN_SADDR_OFFSET, regs->saddr);
+ dmainfo(" DADDR[%08x]: %08x\n",
+ dmach->base + SAM_DMACHAN_DADDR_OFFSET, regs->daddr);
+ dmainfo(" DSCR[%08x]: %08x\n",
+ dmach->base + SAM_DMACHAN_DSCR_OFFSET, regs->dscr);
+ dmainfo(" CTRLA[%08x]: %08x\n",
+ dmach->base + SAM_DMACHAN_CTRLA_OFFSET, regs->ctrla);
+ dmainfo(" CTRLB[%08x]: %08x\n",
+ dmach->base + SAM_DMACHAN_CTRLB_OFFSET, regs->ctrlb);
+ dmainfo(" CFG[%08x]: %08x\n",
+ dmach->base + SAM_DMACHAN_CFG_OFFSET, regs->cfg);
}
#endif /* CONFIG_DEBUG_DMA_INFO */
#endif /* CONFIG_SAM34_DMAC0 */
diff --git a/arch/arm/src/sama5/sam_dmac.c b/arch/arm/src/sama5/sam_dmac.c
index 23d8418..59b3b6d 100644
--- a/arch/arm/src/sama5/sam_dmac.c
+++ b/arch/arm/src/sama5/sam_dmac.c
@@ -110,6 +110,7 @@
/****************************************************************************
* Private Types
****************************************************************************/
+
/* This structure maps a peripheral ID to an DMA channel */
struct sam_pidmap_s
@@ -484,9 +485,9 @@ static struct sam_dmac_s g_dmac1 =
*
****************************************************************************/
-static void sam_takechsem(struct sam_dmac_s *dmac)
+static int sam_takechsem(struct sam_dmac_s *dmac)
{
- nxsem_wait_uninterruptible(&dmac->chsem);
+ return nxsem_wait_uninterruptible(&dmac->chsem);
}
static inline void sam_givechsem(struct sam_dmac_s *dmac)
@@ -502,9 +503,9 @@ static inline void sam_givechsem(struct sam_dmac_s *dmac)
*
****************************************************************************/
-static void sam_takedsem(struct sam_dmac_s *dmac)
+static int sam_takedsem(struct sam_dmac_s *dmac)
{
- nxsem_wait_uninterruptible(&dmac->dsem);
+ return nxsem_wait_uninterruptible(&dmac->dsem);
}
static inline void sam_givedsem(struct sam_dmac_s *dmac)
@@ -605,7 +606,6 @@ static inline uint32_t sam_fifocfg(struct sam_dmach_s *dmach)
return g_fifocfg[ndx];
}
-
/****************************************************************************
* Name: sam_channel, sam_source_channel, and sam_sink_channel
*
@@ -745,21 +745,25 @@ static inline uint32_t sam_txcfg(struct sam_dmach_s *dmach)
regval = DMAC_CH_CFG_SOD;
- pid = (dmach->flags & DMACH_FLAG_MEMPID_MASK) >> DMACH_FLAG_MEMPID_SHIFT;
+ pid = (dmach->flags & DMACH_FLAG_MEMPID_MASK) >>
+ DMACH_FLAG_MEMPID_SHIFT;
isperiph = ((dmach->flags & DMACH_FLAG_MEMISPERIPH) != 0);
pchan = sam_source_channel(dmach, pid, isperiph);
regval |= ((pchan & 0x0f) << DMAC_CH_CFG_SRCPER_SHIFT);
- regval |= ((pchan & 0x30) << (DMAC_CH_CFG_SRCPERMSB_SHIFT-4));
- regval |= (dmach->flags & DMACH_FLAG_MEMH2SEL) != 0 ? DMAC_CH_CFG_SRCH2SEL : 0;
+ regval |= ((pchan & 0x30) << (DMAC_CH_CFG_SRCPERMSB_SHIFT - 4));
+ regval |= (dmach->flags & DMACH_FLAG_MEMH2SEL) != 0 ?
+ DMAC_CH_CFG_SRCH2SEL : 0;
- pid = (dmach->flags & DMACH_FLAG_PERIPHPID_MASK) >> DMACH_FLAG_PERIPHPID_SHIFT;
+ pid = (dmach->flags & DMACH_FLAG_PERIPHPID_MASK) >>
+ DMACH_FLAG_PERIPHPID_SHIFT;
isperiph = ((dmach->flags & DMACH_FLAG_PERIPHISPERIPH) != 0);
pchan = sam_sink_channel(dmach, pid, isperiph);
regval |= ((pchan & 0x0f) << DMAC_CH_CFG_DSTPER_SHIFT);
- regval |= ((pchan & 0x30) << (DMAC_CH_CFG_DSTPERMSB_SHIFT-4));
- regval |= (dmach->flags & DMACH_FLAG_PERIPHH2SEL) != 0 ? DMAC_CH_CFG_DSTH2SEL : 0;
+ regval |= ((pchan & 0x30) << (DMAC_CH_CFG_DSTPERMSB_SHIFT - 4));
+ regval |= (dmach->flags & DMACH_FLAG_PERIPHH2SEL) != 0 ?
+ DMAC_CH_CFG_DSTH2SEL : 0;
regval |= sam_fifocfg(dmach);
return regval;
@@ -785,21 +789,25 @@ static inline uint32_t sam_rxcfg(struct sam_dmach_s *dmach)
regval = DMAC_CH_CFG_SOD;
- pid = (dmach->flags & DMACH_FLAG_PERIPHPID_MASK) >> DMACH_FLAG_PERIPHPID_SHIFT;
+ pid = (dmach->flags & DMACH_FLAG_PERIPHPID_MASK) >>
+ DMACH_FLAG_PERIPHPID_SHIFT;
isperiph = ((dmach->flags & DMACH_FLAG_PERIPHISPERIPH) != 0);
pchan = sam_source_channel(dmach, pid, isperiph);
regval |= ((pchan & 0x0f) << DMAC_CH_CFG_SRCPER_SHIFT);
- regval |= ((pchan & 0x30) << (DMAC_CH_CFG_SRCPERMSB_SHIFT-4));
- regval |= (dmach->flags & DMACH_FLAG_PERIPHH2SEL) != 0 ? DMAC_CH_CFG_SRCH2SEL : 0;
+ regval |= ((pchan & 0x30) << (DMAC_CH_CFG_SRCPERMSB_SHIFT - 4));
+ regval |= (dmach->flags & DMACH_FLAG_PERIPHH2SEL) != 0 ?
+ DMAC_CH_CFG_SRCH2SEL : 0;
- pid = (dmach->flags & DMACH_FLAG_MEMPID_MASK) >> DMACH_FLAG_MEMPID_SHIFT;
+ pid = (dmach->flags & DMACH_FLAG_MEMPID_MASK) >>
+ DMACH_FLAG_MEMPID_SHIFT;
isperiph = ((dmach->flags & DMACH_FLAG_MEMISPERIPH) != 0);
pchan = sam_sink_channel(dmach, pid, isperiph);
regval |= ((pchan & 0x0f) << DMAC_CH_CFG_DSTPER_SHIFT);
- regval |= ((pchan & 0x30) << (DMAC_CH_CFG_DSTPERMSB_SHIFT-4));
- regval |= (dmach->flags & DMACH_FLAG_MEMH2SEL) != 0 ? DMAC_CH_CFG_DSTH2SEL : 0;
+ regval |= ((pchan & 0x30) << (DMAC_CH_CFG_DSTPERMSB_SHIFT - 4));
+ regval |= (dmach->flags & DMACH_FLAG_MEMH2SEL) != 0 ?
+ DMAC_CH_CFG_DSTH2SEL : 0;
regval |= sam_fifocfg(dmach);
return regval;
@@ -824,11 +832,12 @@ static inline uint32_t sam_txctrlabits(struct sam_dmach_s *dmach)
DEBUGASSERT(dmach);
- /* Since this is a transmit, the source is described by the memory selections.
- * Set the source width (memory width).
+ /* Since this is a transmit, the source is described by the memory
+ * selections. Set the source width (memory width).
*/
- ndx = (dmach->flags & DMACH_FLAG_MEMWIDTH_MASK) >> DMACH_FLAG_MEMWIDTH_SHIFT;
+ ndx = (dmach->flags & DMACH_FLAG_MEMWIDTH_MASK) >>
+ DMACH_FLAG_MEMWIDTH_SHIFT;
DEBUGASSERT(ndx < 4);
regval = g_srcwidth[ndx];
@@ -838,11 +847,12 @@ static inline uint32_t sam_txctrlabits(struct sam_dmach_s *dmach)
>> DMACH_FLAG_MEMCHUNKSIZE_SHIFT;
regval |= chunksize << DMAC_CH_CTRLA_SCSIZE_SHIFT;
- /* Since this is a transmit, the destination is described by the peripheral selections.
- * Set the destination width (peripheral width).
+ /* Since this is a transmit, the destination is described by the peripheral
+ * selections. Set the destination width (peripheral width).
*/
- ndx = (dmach->flags & DMACH_FLAG_PERIPHWIDTH_MASK) >> DMACH_FLAG_PERIPHWIDTH_SHIFT;
+ ndx = (dmach->flags & DMACH_FLAG_PERIPHWIDTH_MASK) >>
+ DMACH_FLAG_PERIPHWIDTH_SHIFT;
DEBUGASSERT(ndx < 4);
regval |= g_destwidth[ndx];
@@ -1215,7 +1225,8 @@ static inline uint32_t sam_txctrlb(struct sam_dmach_s *dmach)
/* Destination ABH layer */
- ahbif = (dmach->flags & DMACH_FLAG_PERIPHAHB_MASK) >> DMACH_FLAG_PERIPHAHB_SHIFT;
+ ahbif = (dmach->flags & DMACH_FLAG_PERIPHAHB_MASK) >>
+ DMACH_FLAG_PERIPHAHB_SHIFT;
regval |= (ahbif << DMAC_CH_CTRLB_DIF_SHIFT);
/* Select destination address incrementing */
@@ -1294,7 +1305,8 @@ static inline uint32_t sam_rxctrlb(struct sam_dmach_s *dmach)
/* Source ABH layer */
- ahbif = (dmach->flags & DMACH_FLAG_PERIPHAHB_MASK) >> DMACH_FLAG_PERIPHAHB_SHIFT;
+ ahbif = (dmach->flags & DMACH_FLAG_PERIPHAHB_MASK) >>
+ DMACH_FLAG_PERIPHAHB_SHIFT;
regval |= (ahbif << DMAC_CH_CTRLB_SIF_SHIFT);
/* Select source address incrementing */
@@ -1340,6 +1352,7 @@ sam_allocdesc(struct sam_dmach_s *dmach, struct dma_linklist_s *prev,
struct sam_dmac_s *dmac = sam_controller(dmach);
struct dma_linklist_s *desc = NULL;
int i;
+ int ret;
/* Sanity check -- saddr == 0 is the indication that the link is unused.
* Obviously setting it to zero would break that usage.
@@ -1349,19 +1362,29 @@ sam_allocdesc(struct sam_dmach_s *dmach, struct dma_linklist_s *prev,
if (saddr != 0)
#endif
{
- /* Table a descriptor table semaphore count. When we get one, then there
- * is at least one free descriptor in the table and it is ours.
+ /* Table a descriptor table semaphore count. When we get one, then
+ * there is at least one free descriptor in the table and it is ours.
*/
- sam_takedsem(dmac);
+ ret = sam_takedsem(dmac);
+ if (ret < 0)
+ {
+ return NULL;
+ }
/* Examine each link list entry to find an available one -- i.e., one
- * with saddr == 0. That saddr field is set to zero by the DMA transfer
- * complete interrupt handler. The following should be safe because
- * that is an atomic operation.
+ * with saddr == 0. That saddr field is set to zero by the DMA
+ * transfer complete interrupt handler. The following should be safe
+ * because that is an atomic operation.
*/
- sam_takechsem(dmac);
+ ret = sam_takechsem(dmac);
+ if (ret < 0)
+ {
+ sam_givedsem(dmac);
+ return NULL;
+ }
+
for (i = 0; i < CONFIG_SAMA5_NLLDESC; i++)
{
if (dmac->desc[i].saddr == 0)
@@ -1383,12 +1406,14 @@ sam_allocdesc(struct sam_dmach_s *dmach, struct dma_linklist_s *prev,
* the list
*/
- DEBUGASSERT(dmach->llhead == NULL && dmach->lltail == NULL);
+ DEBUGASSERT(dmach->llhead == NULL &&
+ dmach->lltail == NULL);
dmach->llhead = desc;
}
else
{
- DEBUGASSERT(dmach->llhead != NULL && dmach->lltail == prev);
+ DEBUGASSERT(dmach->llhead != NULL &&
+ dmach->lltail == prev);
/* When the second link is added to the list, that is the
* cue that we are going to do the link list transfer.
@@ -1402,26 +1427,28 @@ sam_allocdesc(struct sam_dmach_s *dmach, struct dma_linklist_s *prev,
prev->ctrlb &= ~DMAC_CH_CTRLB_BOTHDSCR;
/* Link the previous tail to the new tail.
- * REVISIT: This assumes that the next description is fetched
- * via AHB IF0.
+ * REVISIT: This assumes that the next description is
+ * fetched via AHB IF0.
*/
prev->dscr = (uint32_t)sam_physramaddr((uintptr_t)desc);
}
/* In any event, this is the new tail of the list. The source
- * and destination descriptors must be disabled for the last entry
- * in the link list. */
+ * and destination descriptors must be disabled for the last
+ * entry in the link list.
+ */
desc->ctrlb |= DMAC_CH_CTRLB_BOTHDSCR;
dmach->lltail = desc;
- /* Assume that we will be doing multiple buffer transfers and that
+ /* Assume that we will be doing multiple buffer transfers and
* that hardware will be accessing the descriptor via DMA.
*/
up_clean_dcache((uintptr_t)desc,
- (uintptr_t)desc + sizeof(struct dma_linklist_s));
+ (uintptr_t)desc +
+ sizeof(struct dma_linklist_s));
break;
}
}
@@ -1565,7 +1592,7 @@ static int sam_rxbuffer(struct sam_dmach_s *dmach, uint32_t paddr,
ctrlb = sam_rxctrlb(dmach);
}
- ctrla = sam_rxctrla(dmach, regval, nbytes);
+ ctrla = sam_rxctrla(dmach, regval, nbytes);
/* Add the new link list entry */
@@ -1800,10 +1827,10 @@ static int sam_dmac_interrupt(int irq, void *context, FAR void *arg)
if ((regval & DMAC_EBC_ERR(chndx)) != 0)
{
- /* Yes... Terminate the transfer with an error? */
+ /* Yes... Terminate the transfer with an error? */
- dmaerr("ERROR: DMA failed: %08x\n", regval);
- sam_dmaterminate(dmach, -EIO);
+ dmaerr("ERROR: DMA failed: %08x\n", regval);
+ sam_dmaterminate(dmach, -EIO);
}
/* Is the transfer complete? */
@@ -1944,6 +1971,7 @@ DMA_HANDLE sam_dmachannel(uint8_t dmacno, uint32_t chflags)
struct sam_dmac_s *dmac;
struct sam_dmach_s *dmach;
unsigned int chndx;
+ int ret;
/* Pick the DMA controller */
@@ -1974,7 +2002,12 @@ DMA_HANDLE sam_dmachannel(uint8_t dmacno, uint32_t chflags)
*/
dmach = NULL;
- sam_takechsem(dmac);
+ ret = sam_takechsem(dmac);
+ if (ret < 0)
+ {
+ return NULL;
+ }
+
for (chndx = 0; chndx < SAM_NDMACHAN; chndx++)
{
struct sam_dmach_s *candidate = &dmac->dmach[chndx];
@@ -2019,21 +2052,21 @@ DMA_HANDLE sam_dmachannel(uint8_t dmacno, uint32_t chflags)
return (DMA_HANDLE)dmach;
}
-/************************************************************************************
+/****************************************************************************
* Name: sam_dmaconfig
*
* Description:
- * There are two channel usage models: (1) The channel is allocated and configured
- * in one step. This is the typical case where a DMA channel performs a constant
- * role. The alternative is (2) where the DMA channel is reconfigured on the fly.
- * In this case, the chflags provided to sam_dmachannel are not used and
- * sam_dmaconfig() is called before each DMA to configure the DMA channel
- * appropriately.
+ * There are two channel usage models: (1) The channel is allocated and
+ * configured in one step. This is the typical case where a DMA channel
+ * performs a constant role. The alternative is (2) where the DMA channel
+ * is reconfigured on the fly. In this case, the chflags provided to
+ * sam_dmachannel are not used and sam_dmaconfig() is called before each
+ * DMA to configure the DMA channel appropriately.
*
* Returned Value:
* None
*
- ************************************************************************************/
+ ****************************************************************************/
void sam_dmaconfig(DMA_HANDLE handle, uint32_t chflags)
{
@@ -2127,8 +2160,8 @@ int sam_dmatxsetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr,
remaining -= maxtransfer;
- /* Increment the memory & peripheral address (if it is appropriate to
- * do so).
+ /* Increment the memory & peripheral address (if it is appropriate
+ * to do so).
*/
if ((dmach->flags & DMACH_FLAG_PERIPHINCREMENT) != 0)
@@ -2206,8 +2239,8 @@ int sam_dmarxsetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr,
remaining -= maxtransfer;
- /* Increment the memory & peripheral address (if it is appropriate to
- * do so).
+ /* Increment the memory & peripheral address (if it is appropriate
+ * to do so).
*/
if ((dmach->flags & DMACH_FLAG_PERIPHINCREMENT) != 0)
@@ -2235,7 +2268,8 @@ int sam_dmarxsetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr,
dmach->rx = true;
dmach->rxaddr = maddr;
- dmach->rxsize = (dmach->flags & DMACH_FLAG_MEMINCREMENT) != 0 ? nbytes : sizeof(uint32_t);
+ dmach->rxsize = (dmach->flags & DMACH_FLAG_MEMINCREMENT) != 0 ?
+ nbytes : sizeof(uint32_t);
/* Clean caches associated with the DMA memory */
@@ -2290,8 +2324,8 @@ int sam_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg)
*
* Description:
* Cancel the DMA. After sam_dmastop() is called, the DMA channel is
- * reset and sam_dmarx/txsetup() must be called before sam_dmastart() can be
- * called again
+ * reset and sam_dmarx/txsetup() must be called before sam_dmastart() can
+ * be called again
*
****************************************************************************/
@@ -2378,25 +2412,43 @@ void sam_dmadump(DMA_HANDLE handle, const struct sam_dmaregs_s *regs,
dmainfo("%s\n", msg);
dmainfo(" DMA Global Registers:\n");
- dmainfo(" GCFG[%08x]: %08x\n", dmac->base + SAM_DMAC_GCFG_OFFSET, regs->gcfg);
- dmainfo(" EN[%08x]: %08x\n", dmac->base + SAM_DMAC_EN_OFFSET, regs->en);
- dmainfo(" SREQ[%08x]: %08x\n", dmac->base + SAM_DMAC_SREQ_OFFSET, regs->sreq);
- dmainfo(" CREQ[%08x]: %08x\n", dmac->base + SAM_DMAC_CREQ_OFFSET, regs->creq);
- dmainfo(" LAST[%08x]: %08x\n", dmac->base + SAM_DMAC_LAST_OFFSET, regs->last);
- dmainfo(" EBCIMR[%08x]: %08x\n", dmac->base + SAM_DMAC_EBCIMR_OFFSET, regs->ebcimr);
- dmainfo(" EBCISR[%08x]: %08x\n", dmac->base + SAM_DMAC_EBCISR_OFFSET, regs->ebcisr);
- dmainfo(" CHSR[%08x]: %08x\n", dmac->base + SAM_DMAC_CHSR_OFFSET, regs->chsr);
- dmainfo(" WPMR[%08x]: %08x\n", dmac->base + SAM_DMAC_WPMR_OFFSET, regs->wpmr);
- dmainfo(" WPSR[%08x]: %08x\n", dmac->base + SAM_DMAC_WPSR_OFFSET, regs->wpsr);
+ dmainfo(" GCFG[%08x]: %08x\n",
+ dmac->base + SAM_DMAC_GCFG_OFFSET, regs->gcfg);
+ dmainfo(" EN[%08x]: %08x\n",
+ dmac->base + SAM_DMAC_EN_OFFSET, regs->en);
+ dmainfo(" SREQ[%08x]: %08x\n",
+ dmac->base + SAM_DMAC_SREQ_OFFSET, regs->sreq);
+ dmainfo(" CREQ[%08x]: %08x\n",
+ dmac->base + SAM_DMAC_CREQ_OFFSET, regs->creq);
+ dmainfo(" LAST[%08x]: %08x\n",
+ dmac->base + SAM_DMAC_LAST_OFFSET, regs->last);
+ dmainfo(" EBCIMR[%08x]: %08x\n",
+ dmac->base + SAM_DMAC_EBCIMR_OFFSET, regs->ebcimr);
+ dmainfo(" EBCISR[%08x]: %08x\n",
+ dmac->base + SAM_DMAC_EBCISR_OFFSET, regs->ebcisr);
+ dmainfo(" CHSR[%08x]: %08x\n",
+ dmac->base + SAM_DMAC_CHSR_OFFSET, regs->chsr);
+ dmainfo(" WPMR[%08x]: %08x\n",
+ dmac->base + SAM_DMAC_WPMR_OFFSET, regs->wpmr);
+ dmainfo(" WPSR[%08x]: %08x\n",
+ dmac->base + SAM_DMAC_WPSR_OFFSET, regs->wpsr);
dmainfo(" DMA Channel Registers:\n");
- dmainfo(" SADDR[%08x]: %08x\n", dmach->base + SAM_DMAC_CH_SADDR_OFFSET, regs->saddr);
- dmainfo(" DADDR[%08x]: %08x\n", dmach->base + SAM_DMAC_CH_DADDR_OFFSET, regs->daddr);
- dmainfo(" DSCR[%08x]: %08x\n", dmach->base + SAM_DMAC_CH_DSCR_OFFSET, regs->dscr);
- dmainfo(" CTRLA[%08x]: %08x\n", dmach->base + SAM_DMAC_CH_CTRLA_OFFSET, regs->ctrla);
- dmainfo(" CTRLB[%08x]: %08x\n", dmach->base + SAM_DMAC_CH_CTRLB_OFFSET, regs->ctrlb);
- dmainfo(" CFG[%08x]: %08x\n", dmach->base + SAM_DMAC_CH_CFG_OFFSET, regs->cfg);
- dmainfo(" SPIP[%08x]: %08x\n", dmach->base + SAM_DMAC_CH_SPIP_OFFSET, regs->spip);
- dmainfo(" DPIP[%08x]: %08x\n", dmach->base + SAM_DMAC_CH_DPIP_OFFSET, regs->dpip);
+ dmainfo(" SADDR[%08x]: %08x\n",
+ dmach->base + SAM_DMAC_CH_SADDR_OFFSET, regs->saddr);
+ dmainfo(" DADDR[%08x]: %08x\n",
+ dmach->base + SAM_DMAC_CH_DADDR_OFFSET, regs->daddr);
+ dmainfo(" DSCR[%08x]: %08x\n",
+ dmach->base + SAM_DMAC_CH_DSCR_OFFSET, regs->dscr);
+ dmainfo(" CTRLA[%08x]: %08x\n",
+ dmach->base + SAM_DMAC_CH_CTRLA_OFFSET, regs->ctrla);
+ dmainfo(" CTRLB[%08x]: %08x\n",
+ dmach->base + SAM_DMAC_CH_CTRLB_OFFSET, regs->ctrlb);
+ dmainfo(" CFG[%08x]: %08x\n",
+ dmach->base + SAM_DMAC_CH_CFG_OFFSET, regs->cfg);
+ dmainfo(" SPIP[%08x]: %08x\n",
+ dmach->base + SAM_DMAC_CH_SPIP_OFFSET, regs->spip);
+ dmainfo(" DPIP[%08x]: %08x\n",
+ dmach->base + SAM_DMAC_CH_DPIP_OFFSET, regs->dpip);
}
#endif /* CONFIG_DEBUG_DMA */
#endif /* CONFIG_SAMA5_DMAC0 || CONFIG_SAMA5_DMAC1 */
diff --git a/arch/arm/src/samd2l2/sam_dmac.c b/arch/arm/src/samd2l2/sam_dmac.c
index 5ee49f9..67fe988 100644
--- a/arch/arm/src/samd2l2/sam_dmac.c
+++ b/arch/arm/src/samd2l2/sam_dmac.c
@@ -60,7 +60,9 @@
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
+
/* Configuration ************************************************************/
+
/* Condition out the whole file unless DMA is selected in the configuration */
#ifdef CONFIG_SAMD2L2_DMAC
@@ -80,6 +82,7 @@
/****************************************************************************
* Private Types
****************************************************************************/
+
/* The direction of the transfer */
enum sam_dmadir_e
@@ -145,10 +148,10 @@ static sem_t g_dsem;
static struct sam_dmach_s g_dmach[SAMD2L2_NDMACHAN];
-/* NOTE: Using the same address as the base descriptors for writeback descriptors
- * causes TERR and FERR interrupts to be raised immediately after starting DMA.
- * This was tested on SAMD21G18A, and it would appear that the writeback
- * buffer must be located at a different memory address.
+/* NOTE: Using the same address as the base descriptors for writeback
+ * descriptors causes TERR and FERR interrupts to be raised immediately after
+ * starting DMA. This was tested on SAMD21G18A, and it would appear that the
+ * writeback buffer must be located at a different memory address.
*
* - Matt Thompson
*/
@@ -179,9 +182,9 @@ static struct dma_desc_s g_dma_desc[CONFIG_SAMD2L2_DMAC_NDESC]
*
****************************************************************************/
-static void sam_takechsem(void)
+static int sam_takechsem(void)
{
- nxsem_wait_uninterruptible(&g_chsem);
+ return nxsem_wait_uninterruptible(&g_chsem);
}
static inline void sam_givechsem(void)
@@ -308,6 +311,7 @@ static int sam_dmainterrupt(int irq, void *context, FAR void *arg)
else if ((intpend & DMAC_INTPEND_SUSP) != 0)
{
dmaerr("Channel suspended. Channel %d\n", chndx);
+
/* REVISIT: Do we want to do anything here? */
}
}
@@ -626,17 +630,18 @@ static int sam_txbuffer(struct sam_dmach_s *dmach, uint32_t paddr,
*
* Other settings come from the channel configuration:
*
- * LPSRAM_BTCTRL_BEATSIZE - Determined by DMACH_FLAG_BEATSIZE
- * LPSRAM_BTCTRL_SRCINC - Determined by DMACH_FLAG_MEM_INCREMENT
- * LPSRAM_BTCTRL_DSTINC - Determined by DMACH_FLAG_PERIPH_INCREMENT
- * LPSRAM_BTCTRL_STEPSEL - Determined by DMACH_FLAG_STEPSEL
- * LPSRAM_BTCTRL_STEPSIZE - Determined by DMACH_FLAG_STEPSIZE
+ * LPSRAM_BTCTRL_BEATSIZE - Determined by DMACH_FLAG_BEATSIZE
+ * LPSRAM_BTCTRL_SRCINC - Determined by DMACH_FLAG_MEM_INCREMENT
+ * LPSRAM_BTCTRL_DSTINC - Determined by DMACH_FLAG_PERIPH_INCREMENT
+ * LPSRAM_BTCTRL_STEPSEL - Determined by DMACH_FLAG_STEPSEL
+ * LPSRAM_BTCTRL_STEPSIZE - Determined by DMACH_FLAG_STEPSIZE
*/
btctrl = LPSRAM_BTCTRL_VALID | LPSRAM_BTCTRL_EVOSEL_DISABLE |
LPSRAM_BTCTRL_BLOCKACT_INT;
- tmp = (dmach->dc_flags & DMACH_FLAG_BEATSIZE_MASK) >> DMACH_FLAG_BEATSIZE_SHIFT;
+ tmp = (dmach->dc_flags & DMACH_FLAG_BEATSIZE_MASK) >>
+ DMACH_FLAG_BEATSIZE_SHIFT;
btctrl |= tmp << LPSRAM_BTCTRL_BEATSIZE_SHIFT;
/* See Addressing on page 264 of the datasheet.
@@ -665,7 +670,8 @@ static int sam_txbuffer(struct sam_dmach_s *dmach, uint32_t paddr,
btctrl |= LPSRAM_BTCTRL_STEPSEL;
}
- tmp = (dmach->dc_flags & DMACH_FLAG_STEPSIZE_MASK) >> LPSRAM_BTCTRL_STEPSIZE_SHIFT;
+ tmp = (dmach->dc_flags & DMACH_FLAG_STEPSIZE_MASK) >>
+ LPSRAM_BTCTRL_STEPSIZE_SHIFT;
btctrl |= tmp << LPSRAM_BTCTRL_STEPSIZE_SHIFT;
/* Add the new descriptor list entry */
@@ -709,17 +715,18 @@ static int sam_rxbuffer(struct sam_dmach_s *dmach, uint32_t paddr,
*
* Other settings come from the channel configuration:
*
- * LPSRAM_BTCTRL_BEATSIZE - Determined by DMACH_FLAG_BEATSIZE
- * LPSRAM_BTCTRL_SRCINC - Determined by DMACH_FLAG_PERIPH_INCREMENT
- * LPSRAM_BTCTRL_DSTINC - Determined by DMACH_FLAG_MEM_INCREMENT
- * LPSRAM_BTCTRL_STEPSEL - Determined by DMACH_FLAG_STEPSEL
- * LPSRAM_BTCTRL_STEPSIZE - Determined by DMACH_FLAG_STEPSIZE
+ * LPSRAM_BTCTRL_BEATSIZE - Determined by DMACH_FLAG_BEATSIZE
+ * LPSRAM_BTCTRL_SRCINC - Determined by DMACH_FLAG_PERIPH_INCREMENT
+ * LPSRAM_BTCTRL_DSTINC - Determined by DMACH_FLAG_MEM_INCREMENT
+ * LPSRAM_BTCTRL_STEPSEL - Determined by DMACH_FLAG_STEPSEL
+ * LPSRAM_BTCTRL_STEPSIZE - Determined by DMACH_FLAG_STEPSIZE
*/
btctrl = LPSRAM_BTCTRL_VALID | LPSRAM_BTCTRL_EVOSEL_DISABLE |
LPSRAM_BTCTRL_BLOCKACT_INT;
- tmp = (dmach->dc_flags & DMACH_FLAG_BEATSIZE_MASK) >> DMACH_FLAG_BEATSIZE_SHIFT;
+ tmp = (dmach->dc_flags & DMACH_FLAG_BEATSIZE_MASK) >>
+ DMACH_FLAG_BEATSIZE_SHIFT;
btctrl |= tmp << LPSRAM_BTCTRL_BEATSIZE_SHIFT;
/* Set up the Block Transfer Count Register configuration */
@@ -743,7 +750,8 @@ static int sam_rxbuffer(struct sam_dmach_s *dmach, uint32_t paddr,
btctrl |= LPSRAM_BTCTRL_STEPSEL;
}
- tmp = (dmach->dc_flags & DMACH_FLAG_STEPSIZE_MASK) >> LPSRAM_BTCTRL_STEPSIZE_SHIFT;
+ tmp = (dmach->dc_flags & DMACH_FLAG_STEPSIZE_MASK) >>
+ LPSRAM_BTCTRL_STEPSIZE_SHIFT;
btctrl |= tmp << LPSRAM_BTCTRL_STEPSIZE_SHIFT;
/* Add the new descriptor list entry */
@@ -855,11 +863,16 @@ DMA_HANDLE sam_dmachannel(uint32_t chflags)
struct sam_dmach_s *dmach;
irqstate_t flags;
unsigned int chndx;
+ int ret;
/* Search for an available DMA channel */
dmach = NULL;
- sam_takechsem();
+ ret = sam_takechsem();
+ if (ret < 0)
+ {
+ return NULL;
+ }
for (chndx = 0; chndx < SAMD2L2_NDMACHAN; chndx++)
{
@@ -897,21 +910,21 @@ DMA_HANDLE sam_dmachannel(uint32_t chflags)
return (DMA_HANDLE)dmach;
}
-/************************************************************************************
+/****************************************************************************
* Name: sam_dmaconfig
*
* Description:
* There are two channel usage models: (1) The channel is allocated and
- * configured in one step. This is the typical case where a DMA channel performs
- * a constant role. The alternative is (2) where the DMA channel is reconfigured
- * on the fly. In this case, the chflags provided to sam_dmachannel are not used
- * and sam_dmaconfig() is called before each DMA to configure the DMA channel
- * appropriately.
+ * configured in one step. This is the typical case where a DMA channel
+ * performs a constant role. The alternative is (2) where the DMA channel
+ * is reconfigured on the fly. In this case, the chflags provided to
+ * sam_dmachannel are not used and sam_dmaconfig() is called before each
+ * DMA to configure the DMA channel appropriately.
*
* Returned Value:
* None
*
- ************************************************************************************/
+ ****************************************************************************/
void sam_dmaconfig(DMA_HANDLE handle, uint32_t chflags)
{
@@ -997,7 +1010,7 @@ int sam_dmatxsetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr,
remaining -= maxtransfer;
- /* Increment the memory & peripheral address (if it is appropriate to
+ /* Increment the memory & peripheral address (if it is appropriate
* do do).
*
* REVISIT: What if stepsize is not 1?
@@ -1183,8 +1196,8 @@ int sam_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg)
/* Setup the Quality of Service Control Register
*
* DMAC_QOSCTRL_WRBQOS_DISABLE - Background
- * DMAC_QOSCTRL_FQOS, DMAC_QOSCTRL_DQOS - Depend on DMACH_FLAG_PERIPH_QOS
- * and DMACH_FLAG_MEM_QOS
+ * DMAC_QOSCTRL_FQOS, DMAC_QOSCTRL_DQOS - Depend on
+ * DMACH_FLAG_PERIPH_QOS and DMACH_FLAG_MEM_QOS
*/
periphqos = (dmach->dc_flags & DMACH_FLAG_PERIPH_QOS_MASK) >>
@@ -1321,15 +1334,20 @@ void sam_dmadump(DMA_HANDLE handle, const struct sam_dmaregs_s *regs,
dmainfo("%s\n", msg);
dmainfo(" DMAC Registers:\n");
- dmainfo(" CTRL: %04x CRCCTRL: %04x CRCDATAIN: %08x CRCCHKSUM: %08x\n",
+ dmainfo(" CTRL: %04x CRCCTRL: %04x"
+ " CRCDATAIN: %08x CRCCHKSUM: %08x\n",
regs->ctrl, regs->crcctrl, regs->crcdatain, regs->crcchksum);
- dmainfo(" CRCSTATUS: %02x DBGCTRL: %02x QOSCTRL: %02x SWTRIGCTRL: %08x\n",
+ dmainfo(" CRCSTATUS: %02x DBGCTRL: %02x"
+ " QOSCTRL: %02x SWTRIGCTRL: %08x\n",
regs->crcstatus, regs->dbgctrl, regs->qosctrl, regs->swtrigctrl);
- dmainfo(" PRICTRL0: %08x INTPEND: %04x INTSTATUS: %08x BUSYCH: %08x\n",
+ dmainfo(" PRICTRL0: %08x INTPEND: %04x"
+ " INTSTATUS: %08x BUSYCH: %08x\n",
regs->prictrl0, regs->intpend, regs->intstatus, regs->busych);
- dmainfo(" PENDCH: %08x ACTIVE: %08x BASEADDR: %08x WRBADDR: %08x\n",
+ dmainfo(" PENDCH: %08x ACTIVE: %08x"
+ " BASEADDR: %08x WRBADDR: %08x\n",
regs->pendch, regs->active, regs->baseaddr, regs->wrbaddr);
- dmainfo(" CHID: %02x CHCRTRLA: %02x CHCRTRLB: %08x CHINFLAG: %02x\n",
+ dmainfo(" CHID: %02x CHCRTRLA: %02x"
+ " CHCRTRLB: %08x CHINFLAG: %02x\n",
regs->chid, regs->chctrla, regs->chctrlb, regs->chintflag);
dmainfo(" CHSTATUS: %02x\n",
regs->chstatus);
diff --git a/arch/arm/src/samd5e5/sam_dmac.c b/arch/arm/src/samd5e5/sam_dmac.c
index cdbf6fe..d02cc6a 100644
--- a/arch/arm/src/samd5e5/sam_dmac.c
+++ b/arch/arm/src/samd5e5/sam_dmac.c
@@ -60,7 +60,9 @@
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
+
/* Configuration ************************************************************/
+
/* Condition out the whole file unless DMA is selected in the configuration */
#ifdef CONFIG_SAMD5E5_DMAC
@@ -80,6 +82,7 @@
/****************************************************************************
* Private Types
****************************************************************************/
+
/* The direction of the transfer */
enum sam_dmadir_e
@@ -111,7 +114,7 @@ struct sam_dmach_s
* Private Function Prototypes
****************************************************************************/
-static void sam_takechsem(void);
+static int sam_takechsem(void);
static inline void sam_givechsem(void);
#if CONFIG_SAMD5E5_DMAC_NDESC > 0
static void sam_takedsem(void);
@@ -147,8 +150,9 @@ static sem_t g_dsem;
static struct sam_dmach_s g_dmach[SAMD5E5_NDMACHAN];
-/* NOTE: Using the same address as the base descriptors for writeback descriptors
- * causes TERR and FERR interrupts to be raised immediately after starting DMA.
+/* NOTE: Using the same address as the base descriptors for writeback
+ * descriptors causes TERR and FERR interrupts to be raised immediately after
+ * starting DMA.
*/
static struct dma_desc_s g_base_desc[SAMD5E5_NDMACHAN]
@@ -177,9 +181,9 @@ static struct dma_desc_s g_dma_desc[CONFIG_SAMD5E5_DMAC_NDESC]
*
****************************************************************************/
-static void sam_takechsem(void)
+static int sam_takechsem(void)
{
- nxsem_wait_uninterruptible(&g_chsem);
+ return nxsem_wait_uninterruptible(&g_chsem);
}
static inline void sam_givechsem(void)
@@ -310,6 +314,7 @@ static int sam_dmainterrupt(int irq, void *context, FAR void *arg)
else if ((intpend & DMAC_INTPEND_SUSP) != 0)
{
dmaerr("Channel suspended. Channel %d\n", chndx);
+
/* REVISIT: Do we want to do anything here? */
}
}
@@ -532,7 +537,8 @@ static size_t sam_maxtransfer(struct sam_dmach_s *dmach, uint32_t dmaflags)
/* The number of bytes per beat is 2**BEATSIZE */
- beatsize = (dmaflags & DMACH_FLAG_BEATSIZE_MASK) >> LPSRAM_BTCTRL_STEPSIZE_SHIFT;
+ beatsize = (dmaflags & DMACH_FLAG_BEATSIZE_MASK) >>
+ LPSRAM_BTCTRL_STEPSIZE_SHIFT;
/* Maximum beats is UINT16_MAX */
@@ -556,7 +562,8 @@ static uint16_t sam_bytes2beats(struct sam_dmach_s *dmach, uint32_t dmaflags,
/* The number of bytes per beat is 2**BEATSIZE */
- beatsize = (dmaflags & DMACH_FLAG_BEATSIZE_MASK) >> LPSRAM_BTCTRL_STEPSIZE_SHIFT;
+ beatsize = (dmaflags & DMACH_FLAG_BEATSIZE_MASK) >>
+ LPSRAM_BTCTRL_STEPSIZE_SHIFT;
/* The number of beats is then the ceiling of the division */
@@ -596,17 +603,18 @@ static int sam_txbuffer(struct sam_dmach_s *dmach, uint32_t paddr,
*
* Other settings come from the channel configuration:
*
- * LPSRAM_BTCTRL_BEATSIZE - Determined by DMACH_FLAG_BEATSIZE
- * LPSRAM_BTCTRL_SRCINC - Determined by DMACH_FLAG_MEM_INCREMENT
- * LPSRAM_BTCTRL_DSTINC - Determined by DMACH_FLAG_PERIPH_INCREMENT
- * LPSRAM_BTCTRL_STEPSEL - Determined by DMACH_FLAG_STEPSEL
- * LPSRAM_BTCTRL_STEPSIZE - Determined by DMACH_FLAG_STEPSIZE
+ * LPSRAM_BTCTRL_BEATSIZE - Determined by DMACH_FLAG_BEATSIZE
+ * LPSRAM_BTCTRL_SRCINC - Determined by DMACH_FLAG_MEM_INCREMENT
+ * LPSRAM_BTCTRL_DSTINC - Determined by DMACH_FLAG_PERIPH_INCREMENT
+ * LPSRAM_BTCTRL_STEPSEL - Determined by DMACH_FLAG_STEPSEL
+ * LPSRAM_BTCTRL_STEPSIZE - Determined by DMACH_FLAG_STEPSIZE
*/
btctrl = LPSRAM_BTCTRL_VALID | LPSRAM_BTCTRL_EVOSEL_DISABLE |
LPSRAM_BTCTRL_BLOCKACT_INT;
- tmp = (dmaflags & DMACH_FLAG_BEATSIZE_MASK) >> DMACH_FLAG_BEATSIZE_SHIFT;
+ tmp = (dmaflags & DMACH_FLAG_BEATSIZE_MASK) >>
+ DMACH_FLAG_BEATSIZE_SHIFT;
btctrl |= tmp << LPSRAM_BTCTRL_BEATSIZE_SHIFT;
/* See Addressing on page 264 of the datasheet.
@@ -635,7 +643,8 @@ static int sam_txbuffer(struct sam_dmach_s *dmach, uint32_t paddr,
btctrl |= LPSRAM_BTCTRL_STEPSEL;
}
- tmp = (dmaflags & DMACH_FLAG_STEPSIZE_MASK) >> LPSRAM_BTCTRL_STEPSIZE_SHIFT;
+ tmp = (dmaflags & DMACH_FLAG_STEPSIZE_MASK) >>
+ LPSRAM_BTCTRL_STEPSIZE_SHIFT;
btctrl |= tmp << LPSRAM_BTCTRL_STEPSIZE_SHIFT;
/* Add the new descriptor list entry */
@@ -679,17 +688,18 @@ static int sam_rxbuffer(struct sam_dmach_s *dmach, uint32_t paddr,
*
* Other settings come from the channel configuration:
*
- * LPSRAM_BTCTRL_BEATSIZE - Determined by DMACH_FLAG_BEATSIZE
- * LPSRAM_BTCTRL_SRCINC - Determined by DMACH_FLAG_PERIPH_INCREMENT
- * LPSRAM_BTCTRL_DSTINC - Determined by DMACH_FLAG_MEM_INCREMENT
- * LPSRAM_BTCTRL_STEPSEL - Determined by DMACH_FLAG_STEPSEL
- * LPSRAM_BTCTRL_STEPSIZE - Determined by DMACH_FLAG_STEPSIZE
+ * LPSRAM_BTCTRL_BEATSIZE - Determined by DMACH_FLAG_BEATSIZE
+ * LPSRAM_BTCTRL_SRCINC - Determined by DMACH_FLAG_PERIPH_INCREMENT
+ * LPSRAM_BTCTRL_DSTINC - Determined by DMACH_FLAG_MEM_INCREMENT
+ * LPSRAM_BTCTRL_STEPSEL - Determined by DMACH_FLAG_STEPSEL
+ * LPSRAM_BTCTRL_STEPSIZE - Determined by DMACH_FLAG_STEPSIZE
*/
btctrl = LPSRAM_BTCTRL_VALID | LPSRAM_BTCTRL_EVOSEL_DISABLE |
LPSRAM_BTCTRL_BLOCKACT_INT;
- tmp = (dmaflags & DMACH_FLAG_BEATSIZE_MASK) >> DMACH_FLAG_BEATSIZE_SHIFT;
+ tmp = (dmaflags & DMACH_FLAG_BEATSIZE_MASK) >>
+ DMACH_FLAG_BEATSIZE_SHIFT;
btctrl |= tmp << LPSRAM_BTCTRL_BEATSIZE_SHIFT;
/* Set up the Block Transfer Count Register configuration */
@@ -713,7 +723,8 @@ static int sam_rxbuffer(struct sam_dmach_s *dmach, uint32_t paddr,
btctrl |= LPSRAM_BTCTRL_STEPSEL;
}
- tmp = (dmaflags & DMACH_FLAG_STEPSIZE_MASK) >> LPSRAM_BTCTRL_STEPSIZE_SHIFT;
+ tmp = (dmaflags & DMACH_FLAG_STEPSIZE_MASK) >>
+ LPSRAM_BTCTRL_STEPSIZE_SHIFT;
btctrl |= tmp << LPSRAM_BTCTRL_STEPSIZE_SHIFT;
/* Add the new descriptor list entry */
@@ -836,11 +847,16 @@ DMA_HANDLE sam_dmachannel(uint32_t txflags, uint32_t rxflags)
struct sam_dmach_s *dmach;
irqstate_t flags;
unsigned int chndx;
+ int ret;
/* Search for an available DMA channel */
dmach = NULL;
- sam_takechsem();
+ ret = sam_takechsem();
+ if (ret < 0)
+ {
+ return NULL;
+ }
for (chndx = 0; chndx < SAMD5E5_NDMACHAN; chndx++)
{
@@ -878,21 +894,21 @@ DMA_HANDLE sam_dmachannel(uint32_t txflags, uint32_t rxflags)
return (DMA_HANDLE)dmach;
}
-/************************************************************************************
+/****************************************************************************
* Name: sam_dmaconfig
*
* Description:
* There are two channel usage models: (1) The channel is allocated and
- * configured in one step. This is the typical case where a DMA channel performs
- * a constant role. The alternative is (2) where the DMA channel is reconfigured
- * on the fly. In this case, the chflags provided to sam_dmachannel are not used
- * and sam_dmaconfig() is called before each DMA to configure the DMA channel
- * appropriately.
+ * configured in one step. This is the typical case where a DMA channel
+ * performs a constant role. The alternative is (2) where the DMA channel
+ * is reconfigured on the fly. In this case, the chflags provided to
+ * sam_dmachannel are not usedand sam_dmaconfig() is called before each DMA
+ * to configure the DMA channel appropriately.
*
* Returned Value:
* None
*
- ************************************************************************************/
+ ****************************************************************************/
void sam_dmaconfig(DMA_HANDLE handle, uint32_t txflags, uint32_t rxflags)
{
@@ -975,14 +991,15 @@ int sam_dmatxsetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr,
{
/* Set up the maximum size transfer */
- ret = sam_txbuffer(dmach, paddr, maddr, dmach->dc_txflags, maxtransfer);
+ ret = sam_txbuffer(dmach, paddr, maddr, dmach->dc_txflags,
+ maxtransfer);
if (ret == OK)
{
/* Decrement the number of bytes left to transfer */
remaining -= maxtransfer;
- /* Increment the memory & peripheral address (if it is appropriate to
+ /* Increment the memory & peripheral address (if it is appropriate
* do do).
*
* REVISIT: What if stepsize is not 1?
@@ -1049,7 +1066,8 @@ int sam_dmarxsetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr,
{
/* Set up the maximum size transfer */
- ret = sam_rxbuffer(dmach, paddr, maddr, dmach->dc_rxflags, maxtransfer);
+ ret = sam_rxbuffer(dmach, paddr, maddr, dmach->dc_rxflags,
+ maxtransfer);
if (ret == OK)
{
/* Decrement the number of bytes left to transfer */
@@ -1161,22 +1179,26 @@ int sam_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg)
/* Trigger source */
- regval32 = (dmaflags & DMACH_FLAG_PERIPH_TRIGSRC_MASK) >> DMACH_FLAG_PERIPH_TRIGSRC_SHIFT;
+ regval32 = (dmaflags & DMACH_FLAG_PERIPH_TRIGSRC_MASK) >>
+ DMACH_FLAG_PERIPH_TRIGSRC_SHIFT;
ctrla |= DMAC_CHCTRLA_TRIGSRC(regval32) ;
/* Trigger action */
- regval32 = (dmaflags & DMAC_CHCTRLA_TRIGACT_MASK) >> DMAC_CHCTRLA_TRIGACT_SHIFT;
+ regval32 = (dmaflags & DMAC_CHCTRLA_TRIGACT_MASK) >>
+ DMAC_CHCTRLA_TRIGACT_SHIFT;
ctrla |= DMAC_CHCTRLA_TRIGACT(regval32) ;
/* Burst length */
- regval32 = ((dmaflags & DMACH_FLAG_BURSTLEN_MASK) >> DMACH_FLAG_BURSTLEN_SHIFT) + 1;
+ regval32 = ((dmaflags & DMACH_FLAG_BURSTLEN_MASK) >>
+ DMACH_FLAG_BURSTLEN_SHIFT) + 1;
ctrla |= DMAC_CHCTRLA_BURSTLEN(regval32) ;
/* Threshold */
- regval32 = ((dmaflags & DMACH_FLAG_BURSTLEN_MASK) >> DMACH_FLAG_BURSTLEN_SHIFT) + 1;
+ regval32 = ((dmaflags & DMACH_FLAG_BURSTLEN_MASK) >>
+ DMACH_FLAG_BURSTLEN_SHIFT) + 1;
ctrla |= DMAC_CHCTRLA_THRESHOLD(regval32) ;
putreg32(ctrla, SAM_DMAC_CHCTRLA(chan));
@@ -1193,7 +1215,8 @@ int sam_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg)
/* Set up the channel priority register */
- regval8 = (dmaflags & DMACH_FLAG_PRIORITY_MASK) >> DMACH_FLAG_PRIORITY_SHIFT;
+ regval8 = (dmaflags & DMACH_FLAG_PRIORITY_MASK) >>
+ DMACH_FLAG_PRIORITY_SHIFT;
putreg8(DMAC_CHPRILVL(regval8), SAM_DMAC_CHPRILVL(chan));
/* Setup channel event control register
@@ -1320,17 +1343,21 @@ void sam_dmadump(DMA_HANDLE handle, const struct sam_dmaregs_s *regs,
flags = enter_critical_section();
dmainfo("%s\n", msg);
dmainfo(" DMAC Global Registers:\n");
- dmainfo(" CTRL: %04x CRCCTRL: %04x CRCDATAIN: %08x CRCCHKSUM: %08x\n",
+ dmainfo(" CTRL: %04x CRCCTRL: %04x "
+ "CRCDATAIN: %08x CRCCHKSUM: %08x\n",
regs->ctrl, regs->crcctrl, regs->crcdatain, regs->crcchksum);
- dmainfo(" CRCSTATUS: %02x DBGCTRL: %02x SWTRIGCTRL: %08x PRICTRL0: %08x\n",
+ dmainfo(" CRCSTATUS: %02x DBGCTRL: %02x "
+ "SWTRIGCTRL: %08x PRICTRL0: %08x\n",
regs->crcstatus, regs->dbgctrl, regs->swtrigctrl, regs->prictrl0);
- dmainfo(" INTPEND: %04x INTSTATUS: %08x BUSYCH: %08x PENDCH: %08x\n",
+ dmainfo(" INTPEND: %04x INTSTATUS: %08x "
+ "BUSYCH: %08x PENDCH: %08x\n",
regs->intpend, regs->intstatus, regs->busych, regs->pendch);
dmainfo(" ACTIVE: %08x BASEADDR: %08x WRBADDR: %08x\n",
regs->active, regs->baseaddr, regs->wrbaddr);
dmainfo(" DMAC Channel %u Registers:\n", regs->chan);
- dmainfo(" CHCRTRLA: %08x CHCRTRLB: %02x CHPRILVL: %02x CHPRILVL: %02x\n",
+ dmainfo(" CHCRTRLA: %08x CHCRTRLB: %02x "
+ "CHPRILVL: %02x CHPRILVL: %02x\n",
regs->chctrla, regs->chctrlb, regs->chprilvl, priv->chprilvl);
dmainfo(" CHINFLAG: %02x CHSTATUS: %02x\n",
regs->chintflag, regs->chstatus);
diff --git a/arch/arm/src/samv7/sam_xdmac.c b/arch/arm/src/samv7/sam_xdmac.c
index 65537cb..d1082df 100644
--- a/arch/arm/src/samv7/sam_xdmac.c
+++ b/arch/arm/src/samv7/sam_xdmac.c
@@ -93,6 +93,7 @@
/****************************************************************************
* Private Types
****************************************************************************/
+
/* This structure maps a peripheral ID to an DMA channel */
struct sam_pidmap_s
@@ -168,6 +169,7 @@ static const struct sam_pidmap_s g_xdmac_rxchan[] =
{ SAM_PID_TC2, XDMACH_TC2_RX }, /* TC2 Receive */
{ SAM_PID_TC3, XDMACH_TC3_RX } /* TC3 Receive */
};
+
#define NXDMAC_RXCHANNELS (sizeof(g_xdmac_rxchan) / sizeof(struct sam_pidmap_s))
/* TX DMA: */
@@ -195,6 +197,7 @@ static const struct sam_pidmap_s g_xdmac_txchan[] =
{ SAM_PID_AES, XDMACH_AES_TX }, /* AES Transmit */
{ SAM_PID_PWM1, XDMACH_PWM1_TX } /* PWM01Transmit */
};
+
#define NXDMAC_TXCHANNELS (sizeof(g_xdmac_txchan) / sizeof(struct sam_pidmap_s))
/* This array describes the available link list descriptors */
@@ -367,9 +370,9 @@ static struct sam_xdmac_s g_xdmac;
*
****************************************************************************/
-static void sam_takechsem(struct sam_xdmac_s *xdmac)
+static int sam_takechsem(struct sam_xdmac_s *xdmac)
{
- nxsem_wait_uninterruptible(&xdmac->chsem);
+ return nxsem_wait_uninterruptible(&xdmac->chsem);
}
static inline void sam_givechsem(struct sam_xdmac_s *xdmac)
@@ -385,9 +388,9 @@ static inline void sam_givechsem(struct sam_xdmac_s *xdmac)
*
****************************************************************************/
-static void sam_takedsem(struct sam_xdmac_s *xdmac)
+static int sam_takedsem(struct sam_xdmac_s *xdmac)
{
- nxsem_wait_uninterruptible(&xdmac->dsem);
+ return nxsem_wait_uninterruptible(&xdmac->dsem);
}
static inline void sam_givedsem(struct sam_xdmac_s *xdmac)
@@ -773,7 +776,8 @@ static inline uint32_t sam_txcc(struct sam_xdmach_s *xdmach)
/* TX -> Destination is peripheral */
- if ((xdmach->flags & DMACH_FLAG_PERIPHAHB_MASK) == DMACH_FLAG_PERIPHAHB_AHB_IF1)
+ if ((xdmach->flags & DMACH_FLAG_PERIPHAHB_MASK) ==
+ DMACH_FLAG_PERIPHAHB_AHB_IF1)
{
regval |= XDMACH_CC_DIF;
}
@@ -924,7 +928,8 @@ static inline uint32_t sam_rxcc(struct sam_xdmach_s *xdmach)
* RX -> Source is peripheral
*/
- if ((xdmach->flags & DMACH_FLAG_PERIPHAHB_MASK) == DMACH_FLAG_PERIPHAHB_AHB_IF1)
+ if ((xdmach->flags & DMACH_FLAG_PERIPHAHB_MASK) ==
+ DMACH_FLAG_PERIPHAHB_AHB_IF1)
{
regval |= XDMACH_CC_SIF;
}
@@ -987,6 +992,7 @@ sam_allocdesc(struct sam_xdmach_s *xdmach, struct chnext_view1_s *prev,
struct sam_xdmac_s *xdmac = sam_controller(xdmach);
struct chnext_view1_s *descr = NULL;
int i;
+ int ret;
/* Sanity check -- csa == 0 is the indication that the link is unused.
* Obviously setting it to zero would break that usage.
@@ -996,11 +1002,15 @@ sam_allocdesc(struct sam_xdmach_s *xdmach, struct chnext_view1_s *prev,
if (csa != 0)
#endif
{
- /* Table a descriptor table semaphore count. When we get one, then there
- * is at least one free descriptor in the table and it is ours.
+ /* Table a descriptor table semaphore count. When we get one, then
+ * there is at least one free descriptor in the table and it is ours.
*/
- sam_takedsem(xdmac);
+ ret = sam_takedsem(xdmac);
+ if (ret < 0)
+ {
+ return NULL;
+ }
/* Examine each link list entry to find an available one -- i.e., one
* with csa == 0. That csa field is set to zero by the DMA transfer
@@ -1008,7 +1018,13 @@ sam_allocdesc(struct sam_xdmach_s *xdmach, struct chnext_view1_s *prev,
* that is an atomic operation.
*/
- sam_takechsem(xdmac);
+ ret = sam_takechsem(xdmac);
+ if (ret < 0)
+ {
+ sam_givedsem(xdmac);
+ return NULL;
+ }
+
for (i = 0; i < CONFIG_SAMV7_NLLDESC; i++)
{
if (g_lldesc[i].csa == 0)
@@ -1029,12 +1045,14 @@ sam_allocdesc(struct sam_xdmach_s *xdmach, struct chnext_view1_s *prev,
* the list
*/
- DEBUGASSERT(xdmach->llhead == NULL && xdmach->lltail == NULL);
+ DEBUGASSERT(xdmach->llhead == NULL &&
+ xdmach->lltail == NULL);
xdmach->llhead = descr;
}
else
{
- DEBUGASSERT(xdmach->llhead != NULL && xdmach->lltail == prev);
+ DEBUGASSERT(xdmach->llhead != NULL &&
+ xdmach->lltail == prev);
/* When the second link is added to the list, that is the
* cue that we are going to do the link list transfer.
@@ -1046,8 +1064,8 @@ sam_allocdesc(struct sam_xdmach_s *xdmach, struct chnext_view1_s *prev,
prev->cubc |= CHNEXT_UBC_NDE;
/* Link the previous tail to the new tail.
- * REVISIT: This assumes that the next description is fetched
- * via AHB IF0.
+ * REVISIT: This assumes that the next description is
+ * fetched via AHB IF0.
*/
prev->cnda = (uint32_t)sam_physramaddr((uintptr_t)descr);
@@ -1057,12 +1075,13 @@ sam_allocdesc(struct sam_xdmach_s *xdmach, struct chnext_view1_s *prev,
xdmach->lltail = descr;
- /* Assume that we will be doing multiple buffer transfers and that
+ /* Assume that we will be doing multiple buffer transfers and
* that hardware will be accessing the descriptor via DMA.
*/
up_clean_dcache((uintptr_t)descr,
- (uintptr_t)descr + sizeof(struct chnext_view1_s));
+ (uintptr_t)descr +
+ sizeof(struct chnext_view1_s));
break;
}
}
@@ -1635,13 +1654,19 @@ DMA_HANDLE sam_dmachannel(uint8_t dmacno, uint32_t chflags)
struct sam_xdmac_s *xdmac = &g_xdmac;
struct sam_xdmach_s *xdmach;
unsigned int chndx;
+ int ret;
/* Search for an available DMA channel with at least the requested FIFO
* size.
*/
xdmach = NULL;
- sam_takechsem(xdmac);
+ ret = sam_takechsem(xdmac);
+ if (ret < 0)
+ {
+ return NULL;
+ }
+
for (chndx = 0; chndx < SAMV7_NDMACHAN; chndx++)
{
struct sam_xdmach_s *candidate = &g_xdmach[chndx];
@@ -1686,13 +1711,14 @@ DMA_HANDLE sam_dmachannel(uint8_t dmacno, uint32_t chflags)
return (DMA_HANDLE)xdmach;
}
-/************************************************************************************
+/****************************************************************************
* Name: sam_dmaconfig
*
* Description:
- * There are two channel usage models: (1) The channel is allocated and configured
- * in one step. This is the typical case where a DMA channel performs a constant
- * role. The alternative is (2) where the DMA channel is reconfigured on the fly.
+ * There are two channel usage models: (1) The channel is allocated and
+ * configured in one step. This is the typical case where a DMA channel
+ * performs a constant role. The alternative is (2) where the DMA channel
+ * is reconfigured on the fly.
* In this case, the chflags provided to sam_dmachannel are not used and
* sam_dmaconfig() is called before each DMA to configure the DMA channel
* appropriately.
@@ -1700,7 +1726,7 @@ DMA_HANDLE sam_dmachannel(uint8_t dmacno, uint32_t chflags)
* Returned Value:
* None
*
- ************************************************************************************/
+ ****************************************************************************/
void sam_dmaconfig(DMA_HANDLE handle, uint32_t chflags)
{
@@ -1793,8 +1819,8 @@ int sam_dmatxsetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr,
remaining -= maxtransfer;
- /* Increment the memory & peripheral address (if it is appropriate to
- * do so).
+ /* Increment the memory & peripheral address (if it is appropriate
+ * to do so).
*/
if ((xdmach->flags & DMACH_FLAG_PERIPHINCREMENT) != 0)
@@ -1872,8 +1898,8 @@ int sam_dmarxsetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr,
remaining -= maxtransfer;
- /* Increment the memory & peripheral address (if it is appropriate to
- * do so).
+ /* Increment the memory & peripheral address (if it is appropriate
+ * to do so).
*/
if ((xdmach->flags & DMACH_FLAG_PERIPHINCREMENT) != 0)
@@ -1901,7 +1927,8 @@ int sam_dmarxsetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr,
xdmach->rx = true;
xdmach->rxaddr = maddr;
- xdmach->rxsize = (xdmach->flags & DMACH_FLAG_MEMINCREMENT) != 0 ? nbytes : sizeof(uint32_t);
+ xdmach->rxsize = (xdmach->flags & DMACH_FLAG_MEMINCREMENT) != 0 ?
+ nbytes : sizeof(uint32_t);
/* Clean caches associated with the DMA memory */
@@ -1966,8 +1993,8 @@ int sam_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg)
*
* Description:
* Cancel the DMA. After sam_dmastop() is called, the DMA channel is
- * reset and sam_dmarx/txsetup() must be called before sam_dmastart() can be
- * called again
+ * reset and sam_dmarx/txsetup() must be called before sam_dmastart() can
+ * be called again.
*
****************************************************************************/
@@ -2065,17 +2092,28 @@ void sam_dmadump(DMA_HANDLE handle, const struct sam_dmaregs_s *regs,
dmainfo(" GWS[%08x]: %08x\n", SAM_XDMAC_GWS, regs->gws);
dmainfo(" GSWS[%08x]: %08x\n", SAM_XDMAC_GSWS, regs->gsws);
dmainfo(" DMA Channel Registers:\n");
- dmainfo(" CIM[%08x]: %08x\n", xdmach->base + SAM_XDMACH_CIM_OFFSET, regs->cim);
- dmainfo(" CSA[%08x]: %08x\n", xdmach->base + SAM_XDMACH_CSA_OFFSET, regs->csa);
- dmainfo(" CDA[%08x]: %08x\n", xdmach->base + SAM_XDMACH_CDA_OFFSET, regs->cda);
- dmainfo(" CNDA[%08x]: %08x\n", xdmach->base + SAM_XDMACH_CNDA_OFFSET, regs->cnda);
- dmainfo(" CNDC[%08x]: %08x\n", xdmach->base + SAM_XDMACH_CNDC_OFFSET, regs->cndc);
- dmainfo(" CUBC[%08x]: %08x\n", xdmach->base + SAM_XDMACH_CUBC_OFFSET, regs->cubc);
- dmainfo(" CBC[%08x]: %08x\n", xdmach->base + SAM_XDMACH_CBC_OFFSET, regs->cbc);
- dmainfo(" CC[%08x]: %08x\n", xdmach->base + SAM_XDMACH_CC_OFFSET, regs->cc);
- dmainfo(" CDSMSP[%08x]: %08x\n", xdmach->base + SAM_XDMACH_CDSMSP_OFFSET, regs->cdsmsp);
- dmainfo(" CSUS[%08x]: %08x\n", xdmach->base + SAM_XDMACH_CSUS_OFFSET, regs->csus);
- dmainfo(" CDUS[%08x]: %08x\n", xdmach->base + SAM_XDMACH_CDUS_OFFSET, regs->cdus);
+ dmainfo(" CIM[%08x]: %08x\n",
+ xdmach->base + SAM_XDMACH_CIM_OFFSET, regs->cim);
+ dmainfo(" CSA[%08x]: %08x\n",
+ xdmach->base + SAM_XDMACH_CSA_OFFSET, regs->csa);
+ dmainfo(" CDA[%08x]: %08x\n",
+ xdmach->base + SAM_XDMACH_CDA_OFFSET, regs->cda);
+ dmainfo(" CNDA[%08x]: %08x\n",
+ xdmach->base + SAM_XDMACH_CNDA_OFFSET, regs->cnda);
+ dmainfo(" CNDC[%08x]: %08x\n",
+ xdmach->base + SAM_XDMACH_CNDC_OFFSET, regs->cndc);
+ dmainfo(" CUBC[%08x]: %08x\n",
+ xdmach->base + SAM_XDMACH_CUBC_OFFSET, regs->cubc);
+ dmainfo(" CBC[%08x]: %08x\n",
+ xdmach->base + SAM_XDMACH_CBC_OFFSET, regs->cbc);
+ dmainfo(" CC[%08x]: %08x\n",
+ xdmach->base + SAM_XDMACH_CC_OFFSET, regs->cc);
+ dmainfo(" CDSMSP[%08x]: %08x\n",
+ xdmach->base + SAM_XDMACH_CDSMSP_OFFSET, regs->cdsmsp);
+ dmainfo(" CSUS[%08x]: %08x\n",
+ xdmach->base + SAM_XDMACH_CSUS_OFFSET, regs->csus);
+ dmainfo(" CDUS[%08x]: %08x\n",
+ xdmach->base + SAM_XDMACH_CDUS_OFFSET, regs->cdus);
}
#endif /* CONFIG_DEBUG_DMA_INFO */
#endif /* CONFIG_SAMV7_XDMAC */
diff --git a/arch/arm/src/stm32/stm32_dma_v1.c b/arch/arm/src/stm32/stm32_dma_v1.c
index d6f4a0b..25fa5fc 100644
--- a/arch/arm/src/stm32/stm32_dma_v1.c
+++ b/arch/arm/src/stm32/stm32_dma_v1.c
@@ -1,7 +1,8 @@
/****************************************************************************
* arch/arm/src/stm32/stm32_dma_v1.c
*
- * Copyright (C) 2009, 2011-2013, 2016-2017 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2009, 2011-2013, 2016-2017 Gregory Nutt.
+ * All rights reserved.
* Author: Gregory Nutt <gn...@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -55,7 +56,8 @@
#include "stm32_dma.h"
#include "stm32.h"
-/* This file supports the STM32 DMA IP core version 1 - F0, F1, F3, L0, L1, L4
+/* This file supports the STM32 DMA IP core version 1 - F0, F1, F3, L0, L1,
+ * L4.
*
* F0, L0 and L4 have the additional CSELR register which is used to remap
* the DMA requests for each channel.
@@ -157,7 +159,8 @@ static struct stm32_dma_s g_dma[DMA_NCHANNELS] =
},
{
.chan = 3,
-#if defined(CONFIG_STM32_CONNECTIVITYLINE) || defined(CONFIG_STM32_STM32F30XX) || \
+#if defined(CONFIG_STM32_CONNECTIVITYLINE) || \
+ defined(CONFIG_STM32_STM32F30XX) || \
defined(CONFIG_STM32_STM32F37XX) || defined(CONFIG_STM32_STM32L15XX)
.irq = STM32_IRQ_DMA2CH4,
#else
@@ -167,7 +170,8 @@ static struct stm32_dma_s g_dma[DMA_NCHANNELS] =
},
{
.chan = 4,
-#if defined(CONFIG_STM32_CONNECTIVITYLINE) || defined(CONFIG_STM32_STM32F30XX) || \
+#if defined(CONFIG_STM32_CONNECTIVITYLINE) || \
+ defined(CONFIG_STM32_STM32F30XX) || \
defined(CONFIG_STM32_STM32F37XX) || defined(CONFIG_STM32_STM32L15XX)
.irq = STM32_IRQ_DMA2CH5,
#else
@@ -188,43 +192,47 @@ static struct stm32_dma_s g_dma[DMA_NCHANNELS] =
/* Get non-channel register from DMA1 or DMA2 */
-static inline uint32_t dmabase_getreg(struct stm32_dma_s *dmach, uint32_t offset)
+static inline uint32_t dmabase_getreg(struct stm32_dma_s *dmach,
+ uint32_t offset)
{
return getreg32(DMA_BASE(dmach->base) + offset);
}
/* Write to non-channel register in DMA1 or DMA2 */
-static inline void dmabase_putreg(struct stm32_dma_s *dmach, uint32_t offset, uint32_t value)
+static inline void dmabase_putreg(struct stm32_dma_s *dmach,
+ uint32_t offset, uint32_t value)
{
putreg32(value, DMA_BASE(dmach->base) + offset);
}
/* Get channel register from DMA1 or DMA2 */
-static inline uint32_t dmachan_getreg(struct stm32_dma_s *dmach, uint32_t offset)
+static inline uint32_t dmachan_getreg(struct stm32_dma_s *dmach,
+ uint32_t offset)
{
return getreg32(dmach->base + offset);
}
/* Write to channel register in DMA1 or DMA2 */
-static inline void dmachan_putreg(struct stm32_dma_s *dmach, uint32_t offset, uint32_t value)
+static inline void dmachan_putreg(struct stm32_dma_s *dmach,
+ uint32_t offset, uint32_t value)
{
putreg32(value, dmach->base + offset);
}
-/************************************************************************************
+/****************************************************************************
* Name: stm32_dmatake() and stm32_dmagive()
*
* Description:
* Used to get exclusive access to a DMA channel.
*
- ************************************************************************************/
+ ****************************************************************************/
-static void stm32_dmatake(FAR struct stm32_dma_s *dmach)
+static int stm32_dmatake(FAR struct stm32_dma_s *dmach)
{
- nxsem_wait_uninterruptible(&dmach->sem);
+ return nxsem_wait_uninterruptible(&dmach->sem);
}
static inline void stm32_dmagive(FAR struct stm32_dma_s *dmach)
@@ -232,13 +240,13 @@ static inline void stm32_dmagive(FAR struct stm32_dma_s *dmach)
nxsem_post(&dmach->sem);
}
-/************************************************************************************
+/****************************************************************************
* Name: stm32_dmachandisable
*
* Description:
* Disable the DMA channel
*
- ************************************************************************************/
+ ****************************************************************************/
static void stm32_dmachandisable(struct stm32_dma_s *dmach)
{
@@ -256,16 +264,17 @@ static void stm32_dmachandisable(struct stm32_dma_s *dmach)
/* Clear pending channel interrupts */
- dmabase_putreg(dmach, STM32_DMA_IFCR_OFFSET, DMA_ISR_CHAN_MASK(dmach->chan));
+ dmabase_putreg(dmach, STM32_DMA_IFCR_OFFSET,
+ DMA_ISR_CHAN_MASK(dmach->chan));
}
-/************************************************************************************
+/****************************************************************************
* Name: stm32_dmainterrupt
*
* Description:
* DMA interrupt handler
*
- ************************************************************************************/
+ ****************************************************************************/
static int stm32_dmainterrupt(int irq, void *context, FAR void *arg)
{
@@ -295,11 +304,13 @@ static int stm32_dmainterrupt(int irq, void *context, FAR void *arg)
{
DEBUGPANIC();
}
+
dmach = &g_dma[chndx];
/* Get the interrupt status (for this channel only) */
- isr = dmabase_getreg(dmach, STM32_DMA_ISR_OFFSET) & DMA_ISR_CHAN_MASK(dmach->chan);
+ isr = dmabase_getreg(dmach, STM32_DMA_ISR_OFFSET) &
+ DMA_ISR_CHAN_MASK(dmach->chan);
/* Clear the interrupts we are handling */
@@ -309,8 +320,10 @@ static int stm32_dmainterrupt(int irq, void *context, FAR void *arg)
if (dmach->callback)
{
- dmach->callback(dmach, isr >> DMA_ISR_CHAN_SHIFT(dmach->chan), dmach->arg);
+ dmach->callback(dmach, isr >> DMA_ISR_CHAN_SHIFT(dmach->chan),
+ dmach->arg);
}
+
return OK;
}
@@ -396,6 +409,7 @@ DMA_HANDLE stm32_dmachannel(unsigned int chndef)
{
int chndx = 0;
struct stm32_dma_s *dmach = NULL;
+ int ret;
#ifdef DMA_HAVE_CSELR
chndx = (chndef & DMACHAN_SETTING_CHANNEL_MASK) >>
@@ -412,7 +426,11 @@ DMA_HANDLE stm32_dmachannel(unsigned int chndef)
* is available if it is currently being used by another driver
*/
- stm32_dmatake(dmach);
+ ret = stm32_dmatake(dmach);
+ if (ret < 0)
+ {
+ return NULL;
+ }
/* The caller now has exclusive use of the DMA channel */
@@ -432,7 +450,7 @@ DMA_HANDLE stm32_dmachannel(unsigned int chndef)
* Name: stm32_dmafree
*
* Description:
- * Release a DMA channel. If another thread is waiting for this DMA channel
+ * Release a DMA channel. If another thread is waiting for this DMA channel
* in a call to stm32_dmachannel, then this function will re-assign the
* DMA channel to that thread and wake it up. NOTE: The 'handle' used
* in this argument must NEVER be used again until stm32_dmachannel() is
@@ -500,18 +518,18 @@ void stm32_dmasetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr,
dmachan_putreg(dmach, STM32_DMACHAN_CNDTR_OFFSET, ntransfers);
/* Configure the channel priority using the PL[1:0] bits in the DMA_CCRx
- * register. Configure data transfer direction, circular mode, peripheral & memory
- * incremented mode, peripheral & memory data size, and interrupt after
- * half and/or full transfer in the DMA_CCRx register.
+ * register. Configure data transfer direction, circular mode,
+ * peripheral & memory incremented mode, peripheral & memory data size,
+ * and interrupt after half and/or full transfer in the DMA_CCRx register.
*/
regval = dmachan_getreg(dmach, STM32_DMACHAN_CCR_OFFSET);
regval &= ~(DMA_CCR_MEM2MEM | DMA_CCR_PL_MASK | DMA_CCR_MSIZE_MASK |
- DMA_CCR_PSIZE_MASK | DMA_CCR_MINC | DMA_CCR_PINC | DMA_CCR_CIRC |
- DMA_CCR_DIR);
+ DMA_CCR_PSIZE_MASK | DMA_CCR_MINC | DMA_CCR_PINC |
+ DMA_CCR_CIRC | DMA_CCR_DIR);
ccr &= (DMA_CCR_MEM2MEM | DMA_CCR_PL_MASK | DMA_CCR_MSIZE_MASK |
- DMA_CCR_PSIZE_MASK | DMA_CCR_MINC | DMA_CCR_PINC | DMA_CCR_CIRC |
- DMA_CCR_DIR);
+ DMA_CCR_PSIZE_MASK | DMA_CCR_MINC | DMA_CCR_PINC |
+ DMA_CCR_CIRC | DMA_CCR_DIR);
regval |= ccr;
dmachan_putreg(dmach, STM32_DMACHAN_CCR_OFFSET, regval);
@@ -558,27 +576,29 @@ void stm32_dmastart(DMA_HANDLE handle, dma_callback_t callback,
ccr = dmachan_getreg(dmach, STM32_DMACHAN_CCR_OFFSET);
ccr |= DMA_CCR_EN;
- /* In normal mode, interrupt at either half or full completion. In circular mode,
- * always interrupt on buffer wrap, and optionally interrupt at the halfway point.
+ /* In normal mode, interrupt at either half or full completion. In circular
+ * mode, always interrupt on buffer wrap, and optionally interrupt at the
+ * halfway point.
*/
if ((ccr & DMA_CCR_CIRC) == 0)
{
- /* Once half of the bytes are transferred, the half-transfer flag (HTIF) is
- * set and an interrupt is generated if the Half-Transfer Interrupt Enable
- * bit (HTIE) is set. At the end of the transfer, the Transfer Complete Flag
- * (TCIF) is set and an interrupt is generated if the Transfer Complete
- * Interrupt Enable bit (TCIE) is set.
+ /* Once half of the bytes are transferred, the half-transfer flag
+ * (HTIF) is set and an interrupt is generated if the Half-Transfer
+ * Interrupt Enable bit (HTIE) is set. At the end of the transfer, the
+ * Transfer Complete Flag (TCIF) is set and an interrupt is generated
+ * if the Transfer Complete Interrupt Enable bit (TCIE) is set.
*/
- ccr |= (half ? (DMA_CCR_HTIE | DMA_CCR_TEIE) : (DMA_CCR_TCIE | DMA_CCR_TEIE));
+ ccr |= (half ?
+ (DMA_CCR_HTIE | DMA_CCR_TEIE) : (DMA_CCR_TCIE | DMA_CCR_TEIE));
}
else
{
/* In nonstop mode, when the transfer completes it immediately resets
* and starts again. The transfer-complete interrupt is thus always
* enabled, and the half-complete interrupt can be used in circular
- * mode to determine when the buffer is half-full, or in double-buffered
+ * mode to determine when the buffer is half-full or in double-buffered
* mode to determine when one of the two buffers is full.
*/
@@ -698,11 +718,13 @@ bool stm32_dmacapable(uint32_t maddr, uint32_t count, uint32_t ccr)
#endif
case STM32_SRAM_BASE:
case STM32_CODE_BASE:
+
/* All RAM and flash is supported */
return true;
default:
+
/* Everything else is unsupported by DMA */
return false;
@@ -759,14 +781,20 @@ void stm32_dmadump(DMA_HANDLE handle, const struct stm32_dmaregs_s *regs,
uint32_t dmabase = DMA_BASE(dmach->base);
dmainfo("DMA Registers: %s\n", msg);
- dmainfo(" ISRC[%08x]: %08x\n", dmabase + STM32_DMA_ISR_OFFSET, regs->isr);
+ dmainfo(" ISRC[%08x]: %08x\n",
+ dmabase + STM32_DMA_ISR_OFFSET, regs->isr);
#ifdef DMA_HAVE_CSELR
- dmainfo(" CSELR[%08x]: %08x\n", dmabase + STM32_DMA_CSELR_OFFSET, regs->cselr);
+ dmainfo(" CSELR[%08x]: %08x\n",
+ dmabase + STM32_DMA_CSELR_OFFSET, regs->cselr);
#endif
- dmainfo(" CCR[%08x]: %08x\n", dmach->base + STM32_DMACHAN_CCR_OFFSET, regs->ccr);
- dmainfo(" CNDTR[%08x]: %08x\n", dmach->base + STM32_DMACHAN_CNDTR_OFFSET, regs->cndtr);
- dmainfo(" CPAR[%08x]: %08x\n", dmach->base + STM32_DMACHAN_CPAR_OFFSET, regs->cpar);
- dmainfo(" CMAR[%08x]: %08x\n", dmach->base + STM32_DMACHAN_CMAR_OFFSET, regs->cmar);
+ dmainfo(" CCR[%08x]: %08x\n",
+ dmach->base + STM32_DMACHAN_CCR_OFFSET, regs->ccr);
+ dmainfo(" CNDTR[%08x]: %08x\n",
+ dmach->base + STM32_DMACHAN_CNDTR_OFFSET, regs->cndtr);
+ dmainfo(" CPAR[%08x]: %08x\n",
+ dmach->base + STM32_DMACHAN_CPAR_OFFSET, regs->cpar);
+ dmainfo(" CMAR[%08x]: %08x\n",
+ dmach->base + STM32_DMACHAN_CMAR_OFFSET, regs->cmar);
}
#endif
@@ -799,6 +827,7 @@ uint32_t stm32_dma_intget(unsigned int chndx)
{
struct stm32_dma_s *dmach = &g_dma[chndx];
- return dmabase_getreg(dmach, STM32_DMA_ISR_OFFSET) & DMA_ISR_CHAN_MASK(dmach->chan);
+ return dmabase_getreg(dmach, STM32_DMA_ISR_OFFSET) &
+ DMA_ISR_CHAN_MASK(dmach->chan);
}
#endif /* CONFIG_ARCH_HIPRI_INTERRUPT */
diff --git a/arch/arm/src/stm32/stm32_dma_v2.c b/arch/arm/src/stm32/stm32_dma_v2.c
index 903faac..14c82d3 100644
--- a/arch/arm/src/stm32/stm32_dma_v2.c
+++ b/arch/arm/src/stm32/stm32_dma_v2.c
@@ -211,43 +211,47 @@ static struct stm32_dma_s g_dma[DMA_NSTREAMS] =
/* Get non-channel register from DMA1 or DMA2 */
-static inline uint32_t dmabase_getreg(struct stm32_dma_s *dmast, uint32_t offset)
+static inline uint32_t dmabase_getreg(struct stm32_dma_s *dmast,
+ uint32_t offset)
{
return getreg32(DMA_BASE(dmast->base) + offset);
}
/* Write to non-channel register in DMA1 or DMA2 */
-static inline void dmabase_putreg(struct stm32_dma_s *dmast, uint32_t offset, uint32_t value)
+static inline void dmabase_putreg(struct stm32_dma_s *dmast, uint32_t offset,
+ uint32_t value)
{
putreg32(value, DMA_BASE(dmast->base) + offset);
}
/* Get channel register from DMA1 or DMA2 */
-static inline uint32_t dmast_getreg(struct stm32_dma_s *dmast, uint32_t offset)
+static inline uint32_t dmast_getreg(struct stm32_dma_s *dmast,
+ uint32_t offset)
{
return getreg32(dmast->base + offset);
}
/* Write to channel register in DMA1 or DMA2 */
-static inline void dmast_putreg(struct stm32_dma_s *dmast, uint32_t offset, uint32_t value)
+static inline void dmast_putreg(struct stm32_dma_s *dmast, uint32_t offset,
+ uint32_t value)
{
putreg32(value, dmast->base + offset);
}
-/************************************************************************************
+/****************************************************************************
* Name: stm32_dmatake() and stm32_dmagive()
*
* Description:
* Used to get exclusive access to a DMA channel.
*
- ************************************************************************************/
+ ****************************************************************************/
-static void stm32_dmatake(FAR struct stm32_dma_s *dmast)
+static int stm32_dmatake(FAR struct stm32_dma_s *dmast)
{
- nxsem_wait_uninterruptible(&dmast->sem);
+ return nxsem_wait_uninterruptible(&dmast->sem);
}
static inline void stm32_dmagive(FAR struct stm32_dma_s *dmast)
@@ -255,23 +259,24 @@ static inline void stm32_dmagive(FAR struct stm32_dma_s *dmast)
nxsem_post(&dmast->sem);
}
-/************************************************************************************
+/****************************************************************************
* Name: stm32_dmastream
*
* Description:
- * Get the g_dma table entry associated with a DMA controller and a stream number
+ * Get the g_dma table entry associated with a DMA controller and a stream
+ * number
*
- ************************************************************************************/
+ ****************************************************************************/
static inline FAR struct stm32_dma_s *stm32_dmastream(unsigned int stream,
- unsigned int controller)
+ unsigned int controller)
{
int index;
DEBUGASSERT(stream < DMA_NSTREAMS && controller < STM32_NDMA);
- /* Convert the controller + stream based on the fact that there are 8 streams
- * per controller.
+ /* Convert the controller + stream based on the fact that there are
+ * 8 streams per controller.
*/
#if STM32_NDMA > 1
@@ -285,13 +290,13 @@ static inline FAR struct stm32_dma_s *stm32_dmastream(unsigned int stream,
return &g_dma[index];
}
-/************************************************************************************
+/****************************************************************************
* Name: stm32_dmamap
*
* Description:
* Get the g_dma table entry associated with a bit-encoded DMA selection
*
- ************************************************************************************/
+ ****************************************************************************/
static inline FAR struct stm32_dma_s *stm32_dmamap(unsigned long dmamap)
{
@@ -308,13 +313,13 @@ static inline FAR struct stm32_dma_s *stm32_dmamap(unsigned long dmamap)
return stm32_dmastream(stream, controller);
}
-/************************************************************************************
+/****************************************************************************
* Name: stm32_dmastreamdisable
*
* Description:
* Disable the DMA stream
*
- ************************************************************************************/
+ ****************************************************************************/
static void stm32_dmastreamdisable(struct stm32_dma_s *dmast)
{
@@ -331,8 +336,8 @@ static void stm32_dmastreamdisable(struct stm32_dma_s *dmast)
regval &= ~DMA_SCR_EN;
dmast_putreg(dmast, STM32_DMA_SCR_OFFSET, regval);
- /* Clear pending stream interrupts by setting bits in the upper or lower IFCR
- * register
+ /* Clear pending stream interrupts by setting bits in the upper or lower
+ * IFCR register.
*/
if (dmast->stream < 4)
@@ -347,13 +352,13 @@ static void stm32_dmastreamdisable(struct stm32_dma_s *dmast)
dmabase_putreg(dmast, regoffset, (DMA_STREAM_MASK << dmast->shift));
}
-/************************************************************************************
+/****************************************************************************
* Name: stm32_dmainterrupt
*
* Description:
* DMA interrupt handler
*
- ************************************************************************************/
+ ****************************************************************************/
static int stm32_dmainterrupt(int irq, void *context, void *arg)
{
@@ -412,10 +417,11 @@ static int stm32_dmainterrupt(int irq, void *context, void *arg)
/* Get the interrupt status for this stream */
- status = (dmabase_getreg(dmast, regoffset) >> dmast->shift) & DMA_STREAM_MASK;
+ status = (dmabase_getreg(dmast, regoffset) >> dmast->shift) &
+ DMA_STREAM_MASK;
- /* Clear fetched stream interrupts by setting bits in the upper or lower IFCR
- * register
+ /* Clear fetched stream interrupts by setting bits in the upper or lower
+ * IFCR register.
*/
if (stream < 4)
@@ -435,6 +441,7 @@ static int stm32_dmainterrupt(int irq, void *context, void *arg)
{
dmast->callback(dmast, status, dmast->arg);
}
+
return OK;
}
@@ -505,7 +512,7 @@ void weak_function up_dma_initialize(void)
* in chip/stm32f40xxx_dma.h
*
* Returned Value:
- * Provided that 'dmamap' is valid, this function ALWAYS returns a non-NULL,
+ * Provided that 'dmamap' is valid, this function ALWAYS returns a non-NULL
* void* DMA channel handle. (If 'dmamap' is invalid, the function will
* assert if debug is enabled or do something ignorant otherwise).
*
@@ -519,6 +526,7 @@ void weak_function up_dma_initialize(void)
DMA_HANDLE stm32_dmachannel(unsigned int dmamap)
{
FAR struct stm32_dma_s *dmast;
+ int ret;
/* Get the stream index from the bit-encoded channel value */
@@ -529,7 +537,11 @@ DMA_HANDLE stm32_dmachannel(unsigned int dmamap)
* is available if it is currently being used by another driver
*/
- stm32_dmatake(dmast);
+ ret = stm32_dmatake(dmast);
+ if (ret < 0)
+ {
+ return NULL;
+ }
/* The caller now has exclusive use of the DMA channel. Assign the
* channel to the stream and return an opaque reference to the stream
@@ -544,9 +556,9 @@ DMA_HANDLE stm32_dmachannel(unsigned int dmamap)
* Name: stm32_dmafree
*
* Description:
- * Release a DMA channel. If another thread is waiting for this DMA channel
- * in a call to stm32_dmachannel, then this function will re-assign the
- * DMA channel to that thread and wake it up. NOTE: The 'handle' used
+ * Release a DMA channel. If another thread is waiting for this DMA
+ * channel in a call to stm32_dmachannel, then this function will re-assign
+ * the DMA channel to that thread and wake it up. NOTE: The 'handle' used
* in this argument must NEVER be used again until stm32_dmachannel() is
* called again to re-gain access to the channel.
*
@@ -593,22 +605,23 @@ void stm32_dmasetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr,
#endif
/* "If the stream is enabled, disable it by resetting the EN bit in the
- * DMA_SxCR register, then read this bit in order to confirm that there is no
- * ongoing stream operation. Writing this bit to 0 is not immediately
- * effective since it is actually written to 0 once all the current transfers
- * have finished. When the EN bit is read as 0, this means that the stream is
- * ready to be configured. It is therefore necessary to wait for the EN bit
- * to be cleared before starting any stream configuration. ..."
+ * DMA_SxCR register, then read this bit in order to confirm that there is
+ * no ongoing stream operation. Writing this bit to 0 is not immediately
+ * effective since it is actually written to 0 once all the current
+ * transfers have finished. When the EN bit is read as 0, this means that
+ * the stream is ready to be configured. It is therefore necessary to wait
+ * for the EN bit to be cleared before starting any stream
+ * configuration. ..."
*/
while ((dmast_getreg(dmast, STM32_DMA_SCR_OFFSET) & DMA_SCR_EN) != 0);
/* "... All the stream dedicated bits set in the status register (DMA_LISR
- * and DMA_HISR) from the previous data block DMA transfer should be cleared
- * before the stream can be re-enabled."
+ * and DMA_HISR) from the previous data block DMA transfer should be
+ * cleared before the stream can be re-enabled."
*
- * Clear pending stream interrupts by setting bits in the upper or lower IFCR
- * register
+ * Clear pending stream interrupts by setting bits in the upper or lower
+ * IFCR register.
*/
if (dmast->stream < 4)
@@ -632,8 +645,8 @@ void stm32_dmasetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr,
/* "Set the memory address in the DMA_SM0ARx ... register. The data will be
* written to or read from this memory after the peripheral event."
*
- * Note that in double-buffered mode it is explicitly assumed that the second
- * buffer immediately follows the first.
+ * Note that in double-buffered mode it is explicitly assumed that the
+ * second buffer immediately follows the first.
*/
dmast_putreg(dmast, STM32_DMA_SM0AR_OFFSET, maddr);
@@ -646,15 +659,16 @@ void stm32_dmasetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr,
* DMA_SNDTRx register. After each peripheral event, this value will be
* decremented."
*
- * "When the peripheral flow controller is used for a given stream, the value
- * written into the DMA_SxNDTR has no effect on the DMA transfer. Actually,
- * whatever the value written, it will be forced by hardware to 0xFFFF as soon
- * as the stream is enabled..."
+ * "When the peripheral flow controller is used for a given stream,
+ * the value written into the DMA_SxNDTR has no effect on the DMA
+ * transfer. Actually, whatever the value written, it will be forced by
+ * hardware to 0xFFFF as soon as the stream is enabled..."
*/
dmast_putreg(dmast, STM32_DMA_SNDTR_OFFSET, ntransfers);
- /* "Select the DMA channel (request) using CHSEL[2:0] in the DMA_SxCR register."
+ /* "Select the DMA channel (request) using CHSEL[2:0] in the DMA_SxCR
+ * register."
*
* "Configure the stream priority using the PL[1:0] bits in the DMA_SCRx"
* register."
@@ -666,33 +680,36 @@ void stm32_dmasetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr,
regval |= (uint32_t)dmast->channel << DMA_SCR_CHSEL_SHIFT;
dmast_putreg(dmast, STM32_DMA_SCR_OFFSET, regval);
- /* "Configure the FIFO usage (enable or disable, threshold in transmission and
- * reception)"
+ /* "Configure the FIFO usage (enable or disable, threshold in transmission
+ * and reception)"
*
- * "Caution is required when choosing the FIFO threshold (bits FTH[1:0] of the
- * DMA_SxFCR register) and the size of the memory burst (MBURST[1:0] of the
- * DMA_SxCR register): The content pointed by the FIFO threshold must exactly
- * match to an integer number of memory burst transfers. If this is not in the
- * case, a FIFO error (flag FEIFx of the DMA_HISR or DMA_LISR register) will be
- * generated when the stream is enabled, then the stream will be automatically
- * disabled."
+ * "Caution is required when choosing the FIFO threshold (bits FTH[1:0] of
+ * the DMA_SxFCR register) and the size of the memory burst (MBURST[1:0]
+ * of the DMA_SxCR register): The content pointed by the FIFO threshold
+ * must exactly match to an integer number of memory burst transfers.
+ * If this is not in the case, a FIFO error (flag FEIFx of the DMA_HISR
+ * or DMA_LISR register) will be generated when the stream is enabled,
+ * then the stream will be automatically disabled."
*
* The FIFO is disabled in circular mode when transferring data from a
- * peripheral to memory, as in this case it is usually desirable to know that
- * every byte from the peripheral is transferred immediately to memory. It is
- * not practical to flush the DMA FIFO, as this requires disabling the channel
- * which triggers the transfer-complete interrupt.
+ * peripheral to memory, as in this case it is usually desirable to know
+ * that every byte from the peripheral is transferred immediately to memory
+ * It is not practical to flush the DMA FIFO, as this requires disabling
+ * the channel which triggers the transfer-complete interrupt.
*
- * NOTE: The FEIFx error interrupt is not enabled because the FEIFx seems to
- * be reported spuriously causing good transfers to be marked as failures.
+ * NOTE: The FEIFx error interrupt is not enabled because the FEIFx seems
+ * to be reported spuriously causing good transfers to be marked as
+ * failures.
*/
regval = dmast_getreg(dmast, STM32_DMA_SFCR_OFFSET);
regval &= ~(DMA_SFCR_FTH_MASK | DMA_SFCR_FS_MASK | DMA_SFCR_FEIE);
- if (!((scr & (DMA_SCR_CIRC | DMA_SCR_DIR_MASK)) == (DMA_SCR_CIRC | DMA_SCR_DIR_P2M)))
+ if (!((scr & (DMA_SCR_CIRC | DMA_SCR_DIR_MASK)) ==
+ (DMA_SCR_CIRC | DMA_SCR_DIR_P2M)))
{
regval |= (DMA_SFCR_FTH_FULL | DMA_SFCR_DMDIS);
}
+
dmast_putreg(dmast, STM32_DMA_SFCR_OFFSET, regval);
/* "Configure data transfer direction, circular mode, peripheral & memory
@@ -703,13 +720,13 @@ void stm32_dmasetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr,
*/
regval = dmast_getreg(dmast, STM32_DMA_SCR_OFFSET);
- regval &= ~(DMA_SCR_PFCTRL | DMA_SCR_DIR_MASK | DMA_SCR_PINC | DMA_SCR_MINC |
- DMA_SCR_PSIZE_MASK | DMA_SCR_MSIZE_MASK | DMA_SCR_PINCOS |
- DMA_SCR_CIRC | DMA_SCR_DBM | DMA_SCR_CT |
+ regval &= ~(DMA_SCR_PFCTRL | DMA_SCR_DIR_MASK | DMA_SCR_PINC |
+ DMA_SCR_MINC | DMA_SCR_PSIZE_MASK | DMA_SCR_MSIZE_MASK |
+ DMA_SCR_PINCOS | DMA_SCR_CIRC | DMA_SCR_DBM | DMA_SCR_CT |
DMA_SCR_PBURST_MASK | DMA_SCR_MBURST_MASK);
- scr &= (DMA_SCR_PFCTRL | DMA_SCR_DIR_MASK | DMA_SCR_PINC | DMA_SCR_MINC |
- DMA_SCR_PSIZE_MASK | DMA_SCR_MSIZE_MASK | DMA_SCR_PINCOS |
- DMA_SCR_DBM | DMA_SCR_CIRC |
+ scr &= (DMA_SCR_PFCTRL | DMA_SCR_DIR_MASK | DMA_SCR_PINC |
+ DMA_SCR_MINC | DMA_SCR_PSIZE_MASK | DMA_SCR_MSIZE_MASK |
+ DMA_SCR_PINCOS | DMA_SCR_DBM | DMA_SCR_CIRC |
DMA_SCR_PBURST_MASK | DMA_SCR_MBURST_MASK);
regval |= scr;
dmast_putreg(dmast, STM32_DMA_SCR_OFFSET, regval);
@@ -727,7 +744,8 @@ void stm32_dmasetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr,
*
****************************************************************************/
-void stm32_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg, bool half)
+void stm32_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg,
+ bool half)
{
struct stm32_dma_s *dmast = (struct stm32_dma_s *)handle;
uint32_t scr;
@@ -748,27 +766,29 @@ void stm32_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg, bool
scr |= DMA_SCR_EN;
/* In normal mode, interrupt at either half or full completion. In circular
- * and double-buffered modes, always interrupt on buffer wrap, and optionally
- * interrupt at the halfway point.
+ * and double-buffered modes, always interrupt on buffer wrap, and
+ * optionally interrupt at the halfway point.
*/
if ((scr & (DMA_SCR_DBM | DMA_SCR_CIRC)) == 0)
{
- /* Once half of the bytes are transferred, the half-transfer flag (HTIF) is
- * set and an interrupt is generated if the Half-Transfer Interrupt Enable
- * bit (HTIE) is set. At the end of the transfer, the Transfer Complete Flag
- * (TCIF) is set and an interrupt is generated if the Transfer Complete
- * Interrupt Enable bit (TCIE) is set.
+ /* Once half of the bytes are transferred, the half-transfer flag
+ * (HTIF) is set and an interrupt is generated if the Half-Transfer
+ * Interrupt Enable bit (HTIE) is set. At the end of the transfer,
+ * the Transfer Complete Flag (TCIF) is set and an interrupt is
+ * generated if the Transfer Complete Interrupt Enable bit (TCIE)
+ * is set.
*/
- scr |= (half ? (DMA_SCR_HTIE | DMA_SCR_TEIE) : (DMA_SCR_TCIE | DMA_SCR_TEIE));
+ scr |= (half ?
+ (DMA_SCR_HTIE | DMA_SCR_TEIE) : (DMA_SCR_TCIE | DMA_SCR_TEIE));
}
else
{
/* In non-stop modes, when the transfer completes it immediately resets
* and starts again. The transfer-complete interrupt is thus always
* enabled, and the half-complete interrupt can be used in circular
- * mode to determine when the buffer is half-full, or in double-buffered
+ * mode to determine when the buffer is half-full or in double-buffered
* mode to determine when one of the two buffers is full.
*/
@@ -846,7 +866,8 @@ size_t stm32_dmaresidual(DMA_HANDLE handle)
#ifdef CONFIG_STM32_DMACAPABLE
bool stm32_dmacapable(uint32_t maddr, uint32_t count, uint32_t ccr)
{
- uint32_t transfer_size, burst_length;
+ uint32_t transfer_size;
+ uint32_t burst_length;
uint32_t mend;
dmainfo("stm32_dmacapable: 0x%08x/%u 0x%08x\n", maddr, count, ccr);
@@ -943,11 +964,13 @@ bool stm32_dmacapable(uint32_t maddr, uint32_t count, uint32_t ccr)
case STM32_FSMC_BANK3:
case STM32_FSMC_BANK4:
case STM32_SRAM_BASE:
+
/* All RAM is supported */
break;
case STM32_CODE_BASE:
+
/* Everything except the CCM ram is supported */
if (maddr >= STM32_CCMRAM_BASE &&
@@ -956,12 +979,15 @@ bool stm32_dmacapable(uint32_t maddr, uint32_t count, uint32_t ccr)
dmainfo("stm32_dmacapable: transfer targets CCMRAM\n");
return false;
}
+
break;
default:
+
/* Everything else is unsupported by DMA */
- dmainfo("stm32_dmacapable: transfer targets unknown/unsupported region\n");
+ dmainfo("stm32_dmacapable:"
+ " transfer targets unknown/unsupported region\n");
return false;
}
@@ -1019,14 +1045,22 @@ void stm32_dmadump(DMA_HANDLE handle, const struct stm32_dmaregs_s *regs,
uint32_t dmabase = DMA_BASE(dmast->base);
dmainfo("DMA Registers: %s\n", msg);
- dmainfo(" LISR[%08x]: %08x\n", dmabase + STM32_DMA_LISR_OFFSET, regs->lisr);
- dmainfo(" HISR[%08x]: %08x\n", dmabase + STM32_DMA_HISR_OFFSET, regs->hisr);
- dmainfo(" SCR[%08x]: %08x\n", dmast->base + STM32_DMA_SCR_OFFSET, regs->scr);
- dmainfo(" SNDTR[%08x]: %08x\n", dmast->base + STM32_DMA_SNDTR_OFFSET, regs->sndtr);
- dmainfo(" SPAR[%08x]: %08x\n", dmast->base + STM32_DMA_SPAR_OFFSET, regs->spar);
- dmainfo(" SM0AR[%08x]: %08x\n", dmast->base + STM32_DMA_SM0AR_OFFSET, regs->sm0ar);
- dmainfo(" SM1AR[%08x]: %08x\n", dmast->base + STM32_DMA_SM1AR_OFFSET, regs->sm1ar);
- dmainfo(" SFCR[%08x]: %08x\n", dmast->base + STM32_DMA_SFCR_OFFSET, regs->sfcr);
+ dmainfo(" LISR[%08x]: %08x\n",
+ dmabase + STM32_DMA_LISR_OFFSET, regs->lisr);
+ dmainfo(" HISR[%08x]: %08x\n",
+ dmabase + STM32_DMA_HISR_OFFSET, regs->hisr);
+ dmainfo(" SCR[%08x]: %08x\n",
+ dmast->base + STM32_DMA_SCR_OFFSET, regs->scr);
+ dmainfo(" SNDTR[%08x]: %08x\n",
+ dmast->base + STM32_DMA_SNDTR_OFFSET, regs->sndtr);
+ dmainfo(" SPAR[%08x]: %08x\n",
+ dmast->base + STM32_DMA_SPAR_OFFSET, regs->spar);
+ dmainfo(" SM0AR[%08x]: %08x\n",
+ dmast->base + STM32_DMA_SM0AR_OFFSET, regs->sm0ar);
+ dmainfo(" SM1AR[%08x]: %08x\n",
+ dmast->base + STM32_DMA_SM1AR_OFFSET, regs->sm1ar);
+ dmainfo(" SFCR[%08x]: %08x\n",
+ dmast->base + STM32_DMA_SFCR_OFFSET, regs->sfcr);
}
#endif
diff --git a/arch/arm/src/stm32f0l0g0/stm32_dma_v1.c b/arch/arm/src/stm32f0l0g0/stm32_dma_v1.c
index 0beac4f..e48fc2b 100644
--- a/arch/arm/src/stm32f0l0g0/stm32_dma_v1.c
+++ b/arch/arm/src/stm32f0l0g0/stm32_dma_v1.c
@@ -58,7 +58,8 @@
#include "stm32_dma.h"
#include "stm32.h"
-/* This file supports the STM32 DMA IP core version 1 - F0, F1, F3, L0, L1, L4
+/* This file supports the STM32 DMA IP core version 1 - F0, F1, F3, L0, L1,
+ * L4
*
* F0, L0 and L4 have the additional CSELR register which is used to remap
* the DMA requests for each channel.
@@ -224,9 +225,9 @@ static inline void dmachan_putreg(struct stm32_dma_s *dmach,
*
****************************************************************************/
-static void stm32_dmatake(FAR struct stm32_dma_s *dmach)
+static int stm32_dmatake(FAR struct stm32_dma_s *dmach)
{
- nxsem_wait_uninterruptible(&dmach->sem);
+ return nxsem_wait_uninterruptible(&dmach->sem);
}
static inline void stm32_dmagive(FAR struct stm32_dma_s *dmach)
@@ -293,6 +294,7 @@ static int stm32_dmainterrupt(int irq, void *context, FAR void *arg)
{
DEBUGPANIC();
}
+
dmach = &g_dma[chndx];
/* Get the interrupt status (for this channel only) */
@@ -311,6 +313,7 @@ static int stm32_dmainterrupt(int irq, void *context, FAR void *arg)
dmach->callback(dmach, isr >> DMA_ISR_CHAN_SHIFT(dmach->chan),
dmach->arg);
}
+
return OK;
}
@@ -396,6 +399,7 @@ DMA_HANDLE stm32_dmachannel(unsigned int chndef)
{
int chndx = 0;
struct stm32_dma_s *dmach = NULL;
+ int ret;
#ifdef DMA_HAVE_CSELR
chndx = (chndef & DMACHAN_SETTING_CHANNEL_MASK) >>
@@ -412,7 +416,11 @@ DMA_HANDLE stm32_dmachannel(unsigned int chndef)
* is available if it is currently being used by another driver
*/
- stm32_dmatake(dmach);
+ ret = stm32_dmatake(dmach);
+ if (ret < 0)
+ {
+ return NULL;
+ }
/* The caller now has exclusive use of the DMA channel */
@@ -432,9 +440,9 @@ DMA_HANDLE stm32_dmachannel(unsigned int chndef)
* Name: stm32_dmafree
*
* Description:
- * Release a DMA channel. If another thread is waiting for this DMA channel
- * in a call to stm32_dmachannel, then this function will re-assign the
- * DMA channel to that thread and wake it up. NOTE: The 'handle' used
+ * Release a DMA channel. If another thread is waiting for this DMA
+ * channel in a call to stm32_dmachannel, then this function will re-assign
+ * the DMA channel to that thread and wake it up. NOTE: The 'handle' used
* in this argument must NEVER be used again until stm32_dmachannel() is
* called again to re-gain access to the channel.
*
@@ -580,7 +588,7 @@ void stm32_dmastart(DMA_HANDLE handle, dma_callback_t callback,
/* In nonstop mode, when the transfer completes it immediately resets
* and starts again. The transfer-complete interrupt is thus always
* enabled, and the half-complete interrupt can be used in circular
- * mode to determine when the buffer is half-full, or in double-buffered
+ * mode to determine when the buffer is half-full or in double-buffered
* mode to determine when one of the two buffers is full.
*/
@@ -694,11 +702,13 @@ bool stm32_dmacapable(uint32_t maddr, uint32_t count, uint32_t ccr)
{
case STM32_SRAM_BASE:
case STM32_CODE_BASE:
+
/* All RAM and flash is supported */
return true;
default:
+
/* Everything else is unsupported by DMA */
return false;
diff --git a/arch/arm/src/stm32f7/stm32_dma.c b/arch/arm/src/stm32f7/stm32_dma.c
index 46a7d5e..63b1994 100644
--- a/arch/arm/src/stm32f7/stm32_dma.c
+++ b/arch/arm/src/stm32f7/stm32_dma.c
@@ -83,6 +83,7 @@
/****************************************************************************
* Private Types
****************************************************************************/
+
/* This structure describes one DMA channel */
struct stm32_dma_s
@@ -214,43 +215,47 @@ static struct stm32_dma_s g_dma[DMA_NSTREAMS] =
/* Get non-channel register from DMA1 or DMA2 */
-static inline uint32_t dmabase_getreg(struct stm32_dma_s *dmast, uint32_t offset)
+static inline uint32_t dmabase_getreg(struct stm32_dma_s *dmast,
+ uint32_t offset)
{
return getreg32(DMA_BASE(dmast->base) + offset);
}
/* Write to non-channel register in DMA1 or DMA2 */
-static inline void dmabase_putreg(struct stm32_dma_s *dmast, uint32_t offset, uint32_t value)
+static inline void dmabase_putreg(struct stm32_dma_s *dmast, uint32_t offset,
+ uint32_t value)
{
putreg32(value, DMA_BASE(dmast->base) + offset);
}
/* Get channel register from DMA1 or DMA2 */
-static inline uint32_t dmast_getreg(struct stm32_dma_s *dmast, uint32_t offset)
+static inline uint32_t dmast_getreg(struct stm32_dma_s *dmast,
+ uint32_t offset)
{
return getreg32(dmast->base + offset);
}
/* Write to channel register in DMA1 or DMA2 */
-static inline void dmast_putreg(struct stm32_dma_s *dmast, uint32_t offset, uint32_t value)
+static inline void dmast_putreg(struct stm32_dma_s *dmast, uint32_t offset,
+ uint32_t value)
{
putreg32(value, dmast->base + offset);
}
-/************************************************************************************
+/****************************************************************************
* Name: stm32_dmatake() and stm32_dmagive()
*
* Description:
* Used to get exclusive access to a DMA channel.
*
- ************************************************************************************/
+ ****************************************************************************/
-static void stm32_dmatake(FAR struct stm32_dma_s *dmast)
+static int stm32_dmatake(FAR struct stm32_dma_s *dmast)
{
- nxsem_wait_uninterruptible(&dmast->sem);
+ return nxsem_wait_uninterruptible(&dmast->sem);
}
static inline void stm32_dmagive(FAR struct stm32_dma_s *dmast)
@@ -258,23 +263,24 @@ static inline void stm32_dmagive(FAR struct stm32_dma_s *dmast)
nxsem_post(&dmast->sem);
}
-/************************************************************************************
+/****************************************************************************
* Name: stm32_dmastream
*
* Description:
- * Get the g_dma table entry associated with a DMA controller and a stream number
+ * Get the g_dma table entry associated with a DMA controller and a stream
+ * number
*
- ************************************************************************************/
+ ****************************************************************************/
static inline FAR struct stm32_dma_s *stm32_dmastream(unsigned int stream,
- unsigned int controller)
+ unsigned int controller)
{
int index;
DEBUGASSERT(stream < DMA_NSTREAMS && controller < STM32F7_NDMA);
- /* Convert the controller + stream based on the fact that there are 8 streams
- * per controller.
+ /* Convert the controller + stream based on the fact that there are
+ * 8 streams per controller.
*/
#if STM32F7_NDMA > 1
@@ -288,13 +294,13 @@ static inline FAR struct stm32_dma_s *stm32_dmastream(unsigned int stream,
return &g_dma[index];
}
-/************************************************************************************
+/****************************************************************************
* Name: stm32_dmamap
*
* Description:
* Get the g_dma table entry associated with a bit-encoded DMA selection
*
- ************************************************************************************/
+ ****************************************************************************/
static inline FAR struct stm32_dma_s *stm32_dmamap(unsigned long dmamap)
{
@@ -311,13 +317,13 @@ static inline FAR struct stm32_dma_s *stm32_dmamap(unsigned long dmamap)
return stm32_dmastream(stream, controller);
}
-/************************************************************************************
+/****************************************************************************
* Name: stm32_dmastreamdisable
*
* Description:
* Disable the DMA stream
*
- ************************************************************************************/
+ ****************************************************************************/
static void stm32_dmastreamdisable(struct stm32_dma_s *dmast)
{
@@ -334,8 +340,8 @@ static void stm32_dmastreamdisable(struct stm32_dma_s *dmast)
regval &= ~DMA_SCR_EN;
dmast_putreg(dmast, STM32_DMA_SCR_OFFSET, regval);
- /* Clear pending stream interrupts by setting bits in the upper or lower IFCR
- * register
+ /* Clear pending stream interrupts by setting bits in the upper or lower
+ * IFCR register
*/
if (dmast->stream < 4)
@@ -350,13 +356,13 @@ static void stm32_dmastreamdisable(struct stm32_dma_s *dmast)
dmabase_putreg(dmast, regoffset, (DMA_STREAM_MASK << dmast->shift));
}
-/************************************************************************************
+/****************************************************************************
* Name: stm32_dmainterrupt
*
* Description:
* DMA interrupt handler
*
- ************************************************************************************/
+ ****************************************************************************/
static int stm32_dmainterrupt(int irq, void *context, FAR void *arg)
{
@@ -415,10 +421,11 @@ static int stm32_dmainterrupt(int irq, void *context, FAR void *arg)
/* Get the interrupt status for this stream */
- status = (dmabase_getreg(dmast, regoffset) >> dmast->shift) & DMA_STREAM_MASK;
+ status = (dmabase_getreg(dmast, regoffset) >> dmast->shift) &
+ DMA_STREAM_MASK;
- /* Clear fetched stream interrupts by setting bits in the upper or lower IFCR
- * register
+ /* Clear fetched stream interrupts by setting bits in the upper or lower
+ * IFCR register
*/
if (stream < 4)
@@ -509,7 +516,7 @@ void weak_function up_dma_initialize(void)
* in chip/stm32f7xxxxxxx_dma.h
*
* Returned Value:
- * Provided that 'dmamap' is valid, this function ALWAYS returns a non-NULL,
+ * Provided that 'dmamap' is valid, this function ALWAYS returns a non-NULL
* void* DMA channel handle. (If 'dmamap' is invalid, the function will
* assert if debug is enabled or do something ignorant otherwise).
*
@@ -523,6 +530,7 @@ void weak_function up_dma_initialize(void)
DMA_HANDLE stm32_dmachannel(unsigned int dmamap)
{
FAR struct stm32_dma_s *dmast;
+ int ret;
/* Get the stream index from the bit-encoded channel value */
@@ -533,7 +541,11 @@ DMA_HANDLE stm32_dmachannel(unsigned int dmamap)
* is available if it is currently being used by another driver
*/
- stm32_dmatake(dmast);
+ ret = stm32_dmatake(dmast);
+ if (ret < 0)
+ {
+ return NULL;
+ }
/* The caller now has exclusive use of the DMA channel. Assign the
* channel to the stream and return an opaque reference to the stream
@@ -548,7 +560,7 @@ DMA_HANDLE stm32_dmachannel(unsigned int dmamap)
* Name: stm32_dmafree
*
* Description:
- * Release a DMA channel. If another thread is waiting for this DMA channel
+ * Release a DMA channel. If another thread is waiting for this DMA channel
* in a call to stm32_dmachannel, then this function will re-assign the
* DMA channel to that thread and wake it up. NOTE: The 'handle' used
* in this argument must NEVER be used again until stm32_dmachannel() is
@@ -597,22 +609,23 @@ void stm32_dmasetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr,
#endif
/* "If the stream is enabled, disable it by resetting the EN bit in the
- * DMA_SxCR register, then read this bit in order to confirm that there is no
- * ongoing stream operation. Writing this bit to 0 is not immediately
- * effective since it is actually written to 0 once all the current transfers
- * have finished. When the EN bit is read as 0, this means that the stream is
- * ready to be configured. It is therefore necessary to wait for the EN bit
- * to be cleared before starting any stream configuration. ..."
+ * DMA_SxCR register, then read this bit in order to confirm that there
+ * is no ongoing stream operation. Writing this bit to 0 is not immediately
+ * effective since it is actually written to 0 once all the current
+ * transfers have finished. When the EN bit is read as 0, this means that
+ * the stream is ready to be configured. It is therefore necessary to wait
+ * for the EN bit to be cleared before starting any stream
+ * configuration..."
*/
while ((dmast_getreg(dmast, STM32_DMA_SCR_OFFSET) & DMA_SCR_EN) != 0);
/* "... All the stream dedicated bits set in the status register (DMA_LISR
- * and DMA_HISR) from the previous data block DMA transfer should be cleared
- * before the stream can be re-enabled."
+ * and DMA_HISR) from the previous data block DMA transfer should be
+ * cleared before the stream can be re-enabled."
*
- * Clear pending stream interrupts by setting bits in the upper or lower IFCR
- * register
+ * Clear pending stream interrupts by setting bits in the upper or lower
+ * IFCR register
*/
if (dmast->stream < 4)
@@ -636,8 +649,8 @@ void stm32_dmasetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr,
/* "Set the memory address in the DMA_SM0ARx ... register. The data will be
* written to or read from this memory after the peripheral event."
*
- * Note that in double-buffered mode it is explicitly assumed that the second
- * buffer immediately follows the first.
+ * Note that in double-buffered mode it is explicitly assumed that the
+ * second buffer immediately follows the first.
*/
dmast_putreg(dmast, STM32_DMA_SM0AR_OFFSET, maddr);
@@ -650,15 +663,16 @@ void stm32_dmasetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr,
* DMA_SNDTRx register. After each peripheral event, this value will be
* decremented."
*
- * "When the peripheral flow controller is used for a given stream, the value
- * written into the DMA_SxNDTR has no effect on the DMA transfer. Actually,
- * whatever the value written, it will be forced by hardware to 0xFFFF as soon
- * as the stream is enabled..."
+ * "When the peripheral flow controller is used for a given stream, the
+ * value written into the DMA_SxNDTR has no effect on the DMA transfer.
+ * Actually, whatever the value written, it will be forced by hardware
+ * to 0xFFFF as soon as the stream is enabled..."
*/
dmast_putreg(dmast, STM32_DMA_SNDTR_OFFSET, ntransfers);
- /* "Select the DMA channel (request) using CHSEL[2:0] in the DMA_SxCR register."
+ /* "Select the DMA channel (request) using CHSEL[2:0] in the DMA_SxCR
+ * register."
*
* "Configure the stream priority using the PL[1:0] bits in the DMA_SCRx"
* register."
@@ -670,30 +684,32 @@ void stm32_dmasetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr,
regval |= (uint32_t)dmast->channel << DMA_SCR_CHSEL_SHIFT;
dmast_putreg(dmast, STM32_DMA_SCR_OFFSET, regval);
- /* "Configure the FIFO usage (enable or disable, threshold in transmission and
- * reception)"
+ /* "Configure the FIFO usage (enable or disable, threshold in transmission
+ * and reception)"
*
- * "Caution is required when choosing the FIFO threshold (bits FTH[1:0] of the
- * DMA_SxFCR register) and the size of the memory burst (MBURST[1:0] of the
- * DMA_SxCR register): The content pointed by the FIFO threshold must exactly
- * match to an integer number of memory burst transfers. If this is not in the
- * case, a FIFO error (flag FEIFx of the DMA_HISR or DMA_LISR register) will be
- * generated when the stream is enabled, then the stream will be automatically
- * disabled."
+ * "Caution is required when choosing the FIFO threshold (bits FTH[1:0]
+ * of the DMA_SxFCR register) and the size of the memory burst
+ * (MBURST[1:0] of the DMA_SxCR register): The content pointed by the FIFO
+ * threshold must exactly match to an integer number of memory burst
+ * transfers. If this is not in the case, a FIFO error (flag FEIFx of the
+ * DMA_HISR or DMA_LISR register) will be generated when the stream is
+ * enabled, then the stream will be automatically disabled."
*
* The FIFO is disabled in circular mode when transferring data from a
- * peripheral to memory, as in this case it is usually desirable to know that
- * every byte from the peripheral is transferred immediately to memory. It is
- * not practical to flush the DMA FIFO, as this requires disabling the channel
- * which triggers the transfer-complete interrupt.
+ * peripheral to memory, as in this case it is usually desirable to know
+ * that every byte from the peripheral is transferred immediately to
+ * memory. It is not practical to flush the DMA FIFO, as this requires
+ * disabling the channel which triggers the transfer-complete interrupt.
*
- * NOTE: The FEIFx error interrupt is not enabled because the FEIFx seems to
- * be reported spuriously causing good transfers to be marked as failures.
+ * NOTE: The FEIFx error interrupt is not enabled because the FEIFx seems
+ * to be reported spuriously causing good transfers to be marked as
+ * failures.
*/
regval = dmast_getreg(dmast, STM32_DMA_SFCR_OFFSET);
regval &= ~(DMA_SFCR_FTH_MASK | DMA_SFCR_FS_MASK | DMA_SFCR_FEIE);
- if (!((scr & (DMA_SCR_CIRC | DMA_SCR_DIR_MASK)) == (DMA_SCR_CIRC | DMA_SCR_DIR_P2M)))
+ if (!((scr & (DMA_SCR_CIRC | DMA_SCR_DIR_MASK)) ==
+ (DMA_SCR_CIRC | DMA_SCR_DIR_P2M)))
{
regval |= (DMA_SFCR_FTH_FULL | DMA_SFCR_DMDIS);
}
@@ -708,13 +724,13 @@ void stm32_dmasetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr,
*/
regval = dmast_getreg(dmast, STM32_DMA_SCR_OFFSET);
- regval &= ~(DMA_SCR_PFCTRL | DMA_SCR_DIR_MASK | DMA_SCR_PINC | DMA_SCR_MINC |
- DMA_SCR_PSIZE_MASK | DMA_SCR_MSIZE_MASK | DMA_SCR_PINCOS |
- DMA_SCR_CIRC | DMA_SCR_DBM | DMA_SCR_CT |
+ regval &= ~(DMA_SCR_PFCTRL | DMA_SCR_DIR_MASK | DMA_SCR_PINC |
+ DMA_SCR_MINC | DMA_SCR_PSIZE_MASK | DMA_SCR_MSIZE_MASK |
+ DMA_SCR_PINCOS | DMA_SCR_CIRC | DMA_SCR_DBM | DMA_SCR_CT |
DMA_SCR_PBURST_MASK | DMA_SCR_MBURST_MASK);
- scr &= (DMA_SCR_PFCTRL | DMA_SCR_DIR_MASK | DMA_SCR_PINC | DMA_SCR_MINC |
- DMA_SCR_PSIZE_MASK | DMA_SCR_MSIZE_MASK | DMA_SCR_PINCOS |
- DMA_SCR_DBM | DMA_SCR_CIRC |
+ scr &= (DMA_SCR_PFCTRL | DMA_SCR_DIR_MASK | DMA_SCR_PINC |
+ DMA_SCR_MINC | DMA_SCR_PSIZE_MASK | DMA_SCR_MSIZE_MASK |
+ DMA_SCR_PINCOS | DMA_SCR_DBM | DMA_SCR_CIRC |
DMA_SCR_PBURST_MASK | DMA_SCR_MBURST_MASK);
regval |= scr;
dmast_putreg(dmast, STM32_DMA_SCR_OFFSET, regval);
@@ -732,7 +748,8 @@ void stm32_dmasetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr,
*
****************************************************************************/
-void stm32_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg, bool half)
+void stm32_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg,
+ bool half)
{
struct stm32_dma_s *dmast = (struct stm32_dma_s *)handle;
uint32_t scr;
@@ -753,27 +770,29 @@ void stm32_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg, bool
scr |= DMA_SCR_EN;
/* In normal mode, interrupt at either half or full completion. In circular
- * and double-buffered modes, always interrupt on buffer wrap, and optionally
- * interrupt at the halfway point.
+ * and double-buffered modes, always interrupt on buffer wrap, and
+ * optionally interrupt at the halfway point.
*/
if ((scr & (DMA_SCR_DBM | DMA_SCR_CIRC)) == 0)
{
- /* Once half of the bytes are transferred, the half-transfer flag (HTIF) is
- * set and an interrupt is generated if the Half-Transfer Interrupt Enable
- * bit (HTIE) is set. At the end of the transfer, the Transfer Complete Flag
- * (TCIF) is set and an interrupt is generated if the Transfer Complete
- * Interrupt Enable bit (TCIE) is set.
+ /* Once half of the bytes are transferred, the half-transfer flag
+ * (HTIF) is set and an interrupt is generated if the Half-Transfer
+ * Interrupt Enable bit (HTIE) is set. At the end of the transfer,
+ * the Transfer Complete Flag (TCIF) is set and an interrupt is
+ * generated if the Transfer Complete Interrupt Enable bit (TCIE)
+ * is set.
*/
- scr |= (half ? (DMA_SCR_HTIE | DMA_SCR_TEIE) : (DMA_SCR_TCIE | DMA_SCR_TEIE));
+ scr |= (half ?
+ (DMA_SCR_HTIE | DMA_SCR_TEIE) : (DMA_SCR_TCIE | DMA_SCR_TEIE));
}
else
{
/* In non-stop modes, when the transfer completes it immediately resets
* and starts again. The transfer-complete interrupt is thus always
* enabled, and the half-complete interrupt can be used in circular
- * mode to determine when the buffer is half-full, or in double-buffered
+ * mode to determine when the buffer is half-full or in double-buffered
* mode to determine when one of the two buffers is full.
*/
@@ -858,7 +877,8 @@ size_t stm32_dmaresidual(DMA_HANDLE handle)
#ifdef CONFIG_STM32F7_DMACAPABLE
bool stm32_dmacapable(uint32_t maddr, uint32_t count, uint32_t ccr)
{
- uint32_t transfer_size, burst_length;
+ uint32_t transfer_size;
+ uint32_t burst_length;
uint32_t mend;
dmainfo("stm32_dmacapable: 0x%08x/%u 0x%08x\n", maddr, count, ccr);
@@ -910,10 +930,11 @@ bool stm32_dmacapable(uint32_t maddr, uint32_t count, uint32_t ccr)
* ARMV7M_DCACHE_LINESIZE boundaries.
*/
- if ((maddr & (ARMV7M_DCACHE_LINESIZE-1)) != 0 ||
- ((mend + 1) & (ARMV7M_DCACHE_LINESIZE-1)) != 0)
+ if ((maddr & (ARMV7M_DCACHE_LINESIZE - 1)) != 0 ||
+ ((mend + 1) & (ARMV7M_DCACHE_LINESIZE - 1)) != 0)
{
- dmainfo("stm32_dmacapable: dcache unaligned maddr:0x%08x mend:0x%08x\n",
+ dmainfo("stm32_dmacapable:"
+ " dcache unaligned maddr:0x%08x mend:0x%08x\n",
maddr, mend);
return false;
}
@@ -997,7 +1018,9 @@ bool stm32_dmacapable(uint32_t maddr, uint32_t count, uint32_t ccr)
/* Everything else is unsupported by DMA */
- dmainfo("stm32_dmacapable: transfer targets unknown/unsupported region\n");
+ dmainfo("stm32_dmacapable: transfer targets unknown/unsupported"
+ " region\n");
+
return false;
}
@@ -1055,14 +1078,22 @@ void stm32_dmadump(DMA_HANDLE handle, const struct stm32_dmaregs_s *regs,
uint32_t dmabase = DMA_BASE(dmast->base);
dmainfo("DMA Registers: %s\n", msg);
- dmainfo(" LISR[%08x]: %08x\n", dmabase + STM32_DMA_LISR_OFFSET, regs->lisr);
- dmainfo(" HISR[%08x]: %08x\n", dmabase + STM32_DMA_HISR_OFFSET, regs->hisr);
- dmainfo(" SCR[%08x]: %08x\n", dmast->base + STM32_DMA_SCR_OFFSET, regs->scr);
- dmainfo(" SNDTR[%08x]: %08x\n", dmast->base + STM32_DMA_SNDTR_OFFSET, regs->sndtr);
- dmainfo(" SPAR[%08x]: %08x\n", dmast->base + STM32_DMA_SPAR_OFFSET, regs->spar);
- dmainfo(" SM0AR[%08x]: %08x\n", dmast->base + STM32_DMA_SM0AR_OFFSET, regs->sm0ar);
- dmainfo(" SM1AR[%08x]: %08x\n", dmast->base + STM32_DMA_SM1AR_OFFSET, regs->sm1ar);
- dmainfo(" SFCR[%08x]: %08x\n", dmast->base + STM32_DMA_SFCR_OFFSET, regs->sfcr);
+ dmainfo(" LISR[%08x]: %08x\n",
+ dmabase + STM32_DMA_LISR_OFFSET, regs->lisr);
+ dmainfo(" HISR[%08x]: %08x\n",
+ dmabase + STM32_DMA_HISR_OFFSET, regs->hisr);
+ dmainfo(" SCR[%08x]: %08x\n",
+ dmast->base + STM32_DMA_SCR_OFFSET, regs->scr);
+ dmainfo(" SNDTR[%08x]: %08x\n",
+ dmast->base + STM32_DMA_SNDTR_OFFSET, regs->sndtr);
+ dmainfo(" SPAR[%08x]: %08x\n",
+ dmast->base + STM32_DMA_SPAR_OFFSET, regs->spar);
+ dmainfo(" SM0AR[%08x]: %08x\n",
+ dmast->base + STM32_DMA_SM0AR_OFFSET, regs->sm0ar);
+ dmainfo(" SM1AR[%08x]: %08x\n",
+ dmast->base + STM32_DMA_SM1AR_OFFSET, regs->sm1ar);
+ dmainfo(" SFCR[%08x]: %08x\n",
+ dmast->base + STM32_DMA_SFCR_OFFSET, regs->sfcr);
}
#endif
diff --git a/arch/mips/src/pic32mz/pic32mz-dma.c b/arch/mips/src/pic32mz/pic32mz-dma.c
index be4da4c..f97e86e 100644
--- a/arch/mips/src/pic32mz/pic32mz-dma.c
+++ b/arch/mips/src/pic32mz/pic32mz-dma.c
@@ -102,7 +102,7 @@ struct pic32mz_dmac_s
* Private Function Prototypes
****************************************************************************/
-static void pic32mz_dma_takesem(struct pic32mz_dmac_s *dmac);
+static int pic32mz_dma_takesem(struct pic32mz_dmac_s *dmac);
static inline void pic32mz_dma_givesem(struct pic32mz_dmac_s *dmac);
static inline uint32_t pic32mz_dma_getreg(FAR struct pic32mz_dmach_s *dmach,
@@ -211,9 +211,9 @@ static struct pic32mz_dmac_s g_dmac =
*
****************************************************************************/
-static void pic32mz_dma_takesem(struct pic32mz_dmac_s *dmac)
+static int pic32mz_dma_takesem(struct pic32mz_dmac_s *dmac)
{
- nxsem_wait_uninterruptible(&dmac->chsem);
+ return nxsem_wait_uninterruptible(&dmac->chsem);
}
/****************************************************************************
@@ -582,7 +582,8 @@ static void pic32mz_dma_mode(FAR struct pic32mz_dmach_s *dmach,
if (mode & PIC32MZ_DMA_MODE_AUTOEN)
{
- pic32mz_dma_putreg(dmach, PIC32MZ_DMACH_CONSET_OFFSET, DMACH_CON_CHAEN);
+ pic32mz_dma_putreg(dmach, PIC32MZ_DMACH_CONSET_OFFSET,
+ DMACH_CON_CHAEN);
}
}
@@ -690,8 +691,9 @@ void pic32mz_dma_sample(DMA_HANDLE handle, struct pic32mz_dmaregs_s *regs)
****************************************************************************/
#ifdef CONFIG_DEBUG_DMA
-void pic32mz_dma_dump(DMA_HANDLE handle, const struct pic32mz_dmaregs_s *regs,
- const char *msg)
+void pic32mz_dma_dump(DMA_HANDLE handle,
+ const struct pic32mz_dmaregs_s *regs,
+ const char *msg)
{
struct pic32mz_dmach_s *dmach = (struct pic32mz_dmach_s *)handle;
@@ -790,8 +792,8 @@ void weak_function up_dma_initialize(void)
* Name: pic32mz_dma_alloc
*
* Description:
- * Allocate a DMA channel. This function sets aside a DMA channel and gives
- * the caller exclusive access to the DMA channel.
+ * Allocate a DMA channel. This function sets aside a DMA channel and
+ * gives the caller exclusive access to the DMA channel.
*
* Returned Value:
* On success, this function returns a non-NULL, void* DMA channel handle.
@@ -804,10 +806,16 @@ DMA_HANDLE pic32mz_dma_alloc(const struct pic32mz_dma_chcfg_s *cfg)
{
struct pic32mz_dmach_s *dmach = NULL;
unsigned int chndx;
+ int ret;
/* Search for an available DMA channel */
- pic32mz_dma_takesem(&g_dmac);
+ ret = pic32mz_dma_takesem(&g_dmac);
+ if (ret < 0)
+ {
+ return NULL;
+ }
+
for (chndx = 0; chndx < CHIP_NDMACH; chndx++)
{
struct pic32mz_dmach_s *candidate = &g_dmac.dmachs[chndx];