Add stm32_dmacapable interface to determine is it is possible to perform DMA from a given address.
This commit is contained in:
parent
56045e0dde
commit
1c3116c91e
@ -1128,6 +1128,17 @@ config STM32_CCMEXCLUDE
|
||||
and (2) it appears to be impossible to execute ELF modules from CCM
|
||||
RAM.
|
||||
|
||||
config STM32_DMACAPABLE
|
||||
bool "Workaround non-DMA capable memory"
|
||||
depends on ARCH_DMA
|
||||
default y if STM32_STM32F40XX && !STM32_CCMEXCLUDE
|
||||
default n if !STM32_STM32F40XX || STM32_CCMEXCLUDE
|
||||
---help---
|
||||
This option enables the DMA interface stm32_dmacapable that can be
|
||||
used to check if it is possible to do DMA from the selected address.
|
||||
Drivers then may use this information to determine if they should
|
||||
attempt the DMA or fall back to a different transfer method.
|
||||
|
||||
config STM32_FSMC_SRAM
|
||||
bool "External SRAM on FSMC"
|
||||
default n
|
||||
|
@ -42,6 +42,7 @@
|
||||
|
||||
/* FLASH and SRAM *******************************************************************/
|
||||
|
||||
#define STM32_CODE_BASE 0x00000000 /* 0x00000000-0x1fffffff: 512Mb code block */
|
||||
#define STM32_FLASH_BASE 0x08000000 /* 0x08000000 - Up to 512Kb */
|
||||
#define STM32_SRAM_BASE 0x20000000 /* 0x20000000 - 64Kb SRAM */
|
||||
#define STM32_SRAMBB_BASE 0x22000000
|
||||
|
@ -146,7 +146,6 @@ extern "C" {
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
|
||||
/************************************************************************************
|
||||
* Public Functions
|
||||
************************************************************************************/
|
||||
@ -211,7 +210,7 @@ EXTERN DMA_HANDLE stm32_dmachannel(unsigned int chan);
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN void stm32_dmafree(DMA_HANDLE handle);
|
||||
void stm32_dmafree(DMA_HANDLE handle);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32_dmasetup
|
||||
@ -221,8 +220,8 @@ EXTERN void stm32_dmafree(DMA_HANDLE handle);
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN void stm32_dmasetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr,
|
||||
size_t ntransfers, uint32_t ccr);
|
||||
void stm32_dmasetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr,
|
||||
size_t ntransfers, uint32_t ccr);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32_dmastart
|
||||
@ -236,8 +235,8 @@ EXTERN void stm32_dmasetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr,
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN 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);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32_dmastop
|
||||
@ -252,7 +251,7 @@ EXTERN void stm32_dmastart(DMA_HANDLE handle, dma_callback_t callback,
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN void stm32_dmastop(DMA_HANDLE handle);
|
||||
void stm32_dmastop(DMA_HANDLE handle);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32_dmaresidual
|
||||
@ -265,7 +264,27 @@ EXTERN void stm32_dmastop(DMA_HANDLE handle);
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN size_t stm32_dmaresidual(DMA_HANDLE handle);
|
||||
size_t stm32_dmaresidual(DMA_HANDLE handle);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32_dmacapable
|
||||
*
|
||||
* Description:
|
||||
* Check if the DMA controller can transfer data to/from given memory
|
||||
* address. This depends on the internal connections in the ARM bus matrix
|
||||
* of the processor. Note that this only applies to memory addresses, it
|
||||
* will return false for any peripheral address.
|
||||
*
|
||||
* Returned value:
|
||||
* True, if transfer is possible.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_STM32_DMACAPABLE
|
||||
bool stm32_dmacapable(uintptr_t maddr);
|
||||
#else
|
||||
# define stm32_dmacapable(maddr) (true)
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32_dmasample
|
||||
@ -279,7 +298,7 @@ EXTERN size_t stm32_dmaresidual(DMA_HANDLE handle);
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_DEBUG_DMA
|
||||
EXTERN void stm32_dmasample(DMA_HANDLE handle, struct stm32_dmaregs_s *regs);
|
||||
void stm32_dmasample(DMA_HANDLE handle, struct stm32_dmaregs_s *regs);
|
||||
#else
|
||||
# define stm32_dmasample(handle,regs)
|
||||
#endif
|
||||
@ -296,8 +315,8 @@ EXTERN void stm32_dmasample(DMA_HANDLE handle, struct stm32_dmaregs_s *regs);
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_DEBUG_DMA
|
||||
EXTERN void stm32_dmadump(DMA_HANDLE handle, const struct stm32_dmaregs_s *regs,
|
||||
const char *msg);
|
||||
void stm32_dmadump(DMA_HANDLE handle, const struct stm32_dmaregs_s *regs,
|
||||
const char *msg);
|
||||
#else
|
||||
# define stm32_dmadump(handle,regs,msg)
|
||||
#endif
|
||||
|
@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/stm32/stm32f10xxx_dma.c
|
||||
*
|
||||
* Copyright (C) 2009, 2011-2012 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2009, 2011-2013 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -77,7 +77,7 @@
|
||||
#endif
|
||||
|
||||
/* Convert the DMA channel base address to the DMA register block address */
|
||||
|
||||
|
||||
#define DMA_BASE(ch) (ch & 0xfffffc00)
|
||||
|
||||
/****************************************************************************
|
||||
@ -358,7 +358,7 @@ void weak_function up_dmainitialize(void)
|
||||
/* Enable the IRQ at the NVIC (still disabled at the DMA controller) */
|
||||
|
||||
up_enable_irq(dmach->irq);
|
||||
|
||||
|
||||
/* Set the interrrupt priority */
|
||||
|
||||
up_prioritize_irq(dmach->irq, CONFIG_DMA_PRI);
|
||||
@ -548,7 +548,7 @@ void stm32_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg, bool
|
||||
{
|
||||
/* 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
|
||||
* 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 one of the two buffers is full.
|
||||
*/
|
||||
@ -596,6 +596,41 @@ size_t stm32_dmaresidual(DMA_HANDLE handle)
|
||||
return dmachan_getreg(dmach, STM32_DMACHAN_CNDTR_OFFSET);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32_dmacapable
|
||||
*
|
||||
* Description:
|
||||
* Check if the DMA controller can transfer data to/from given memory
|
||||
* address. This depends on the internal connections in the ARM bus matrix
|
||||
* of the processor. Note that this only applies to memory addresses, it
|
||||
* will return false for any peripheral address.
|
||||
*
|
||||
* Returned value:
|
||||
* True, if transfer is possible.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_STM32_DMACAPABLE
|
||||
bool stm32_dmacapable(uint32_t maddr)
|
||||
{
|
||||
switch (maddr & STM32_REGION_MASK)
|
||||
{
|
||||
case STM32_FSMC_BANK1:
|
||||
case STM32_FSMC_BANK2:
|
||||
case STM32_FSMC_BANK3:
|
||||
case STM32_FSMC_BANK4:
|
||||
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;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32_dmasample
|
||||
*
|
||||
|
@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/stm32/stm32f20xxx_dma.c
|
||||
*
|
||||
* Copyright (C) 2012 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2012-2013 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -773,7 +773,7 @@ void stm32_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg, bool
|
||||
* 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
|
||||
{
|
||||
@ -841,6 +841,41 @@ size_t stm32_dmaresidual(DMA_HANDLE handle)
|
||||
return (size_t)residual;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32_dmacapable
|
||||
*
|
||||
* Description:
|
||||
* Check if the DMA controller can transfer data to/from given memory
|
||||
* address. This depends on the internal connections in the ARM bus matrix
|
||||
* of the processor. Note that this only applies to memory addresses, it
|
||||
* will return false for any peripheral address.
|
||||
*
|
||||
* Returned value:
|
||||
* True, if transfer is possible.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_STM32_DMACAPABLE
|
||||
bool stm32_dmacapable(uint32_t maddr)
|
||||
{
|
||||
switch (maddr & STM32_REGION_MASK)
|
||||
{
|
||||
case STM32_FSMC_BANK1:
|
||||
case STM32_FSMC_BANK2:
|
||||
case STM32_FSMC_BANK3:
|
||||
case STM32_FSMC_BANK4:
|
||||
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;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32_dmasample
|
||||
*
|
||||
|
@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/stm32/stm32f40xxx_dma.c
|
||||
*
|
||||
* Copyright (C) 2011-2012 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2011-2013 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -79,7 +79,7 @@
|
||||
#endif
|
||||
|
||||
/* Convert the DMA stream base address to the DMA register block address */
|
||||
|
||||
|
||||
#define DMA_BASE(ch) (ch & 0xfffffc00)
|
||||
|
||||
/****************************************************************************
|
||||
@ -358,7 +358,7 @@ static void stm32_dmastreamdisable(struct stm32_dma_s *dmast)
|
||||
{
|
||||
regoffset = STM32_DMA_HIFCR_OFFSET;
|
||||
}
|
||||
|
||||
|
||||
dmabase_putreg(dmast, regoffset, (DMA_STREAM_MASK << dmast->shift));
|
||||
}
|
||||
|
||||
@ -491,7 +491,7 @@ void weak_function up_dmainitialize(void)
|
||||
/* Enable the IRQ at the NVIC (still disabled at the DMA controller) */
|
||||
|
||||
up_enable_irq(dmast->irq);
|
||||
|
||||
|
||||
/* Set the interrrupt priority */
|
||||
|
||||
up_prioritize_irq(dmast->irq, CONFIG_DMA_PRI);
|
||||
@ -634,7 +634,7 @@ void stm32_dmasetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr,
|
||||
{
|
||||
regoffset = STM32_DMA_HIFCR_OFFSET;
|
||||
}
|
||||
|
||||
|
||||
dmabase_putreg(dmast, regoffset, (DMA_STREAM_MASK << dmast->shift));
|
||||
|
||||
/* "Set the peripheral register address in the DMA_SPARx register. The data
|
||||
@ -692,7 +692,7 @@ void stm32_dmasetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr,
|
||||
* 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
|
||||
* 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
|
||||
@ -776,13 +776,13 @@ void stm32_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg, bool
|
||||
* 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
|
||||
* 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 one of the two buffers is full.
|
||||
*/
|
||||
@ -828,7 +828,7 @@ size_t stm32_dmaresidual(DMA_HANDLE handle)
|
||||
struct stm32_dma_s *dmast = (struct stm32_dma_s *)handle;
|
||||
uint32_t residual;
|
||||
|
||||
/* Fetch the count of bytes remaining to be transferred.
|
||||
/* Fetch the count of bytes remaining to be transferred.
|
||||
*
|
||||
* If the FIFO is enabled, this count may be inaccurate. ST don't
|
||||
* appear to document whether this counts the peripheral or the memory
|
||||
@ -844,6 +844,49 @@ size_t stm32_dmaresidual(DMA_HANDLE handle)
|
||||
return (size_t)residual;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32_dmacapable
|
||||
*
|
||||
* Description:
|
||||
* Check if the DMA controller can transfer data to/from given memory
|
||||
* address. This depends on the internal connections in the ARM bus matrix
|
||||
* of the processor. Note that this only applies to memory addresses, it
|
||||
* will return false for any peripheral address.
|
||||
*
|
||||
* Returned value:
|
||||
* True, if transfer is possible.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_STM32_DMACAPABLE
|
||||
bool stm32_dmacapable(uint32_t maddr)
|
||||
{
|
||||
switch (maddr & STM32_REGION_MASK)
|
||||
{
|
||||
case STM32_FSMC_BANK1:
|
||||
case STM32_FSMC_BANK2:
|
||||
case STM32_FSMC_BANK3:
|
||||
case STM32_FSMC_BANK4:
|
||||
case STM32_SRAM_BASE:
|
||||
/* All RAM is supported */
|
||||
return true;
|
||||
|
||||
case STM32_CODE_BASE:
|
||||
/* Everything except the CCM ram is supported */
|
||||
if (maddr >= STM32_CCMRAM_BASE &&
|
||||
(maddr - STM32_CCMRAM_BASE) < 65536)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
default:
|
||||
/* Everything else is unsupported by DMA */
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32_dmasample
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user