📄 stm32f2xx_dma.c
字号:
/* Check the parameters */
assert_param(IS_DMA_ALL_PERIPH(DMAy_Streamx));
/* Return the number of remaining data units for DMAy Streamx */
return ((uint16_t)(DMAy_Streamx->NDTR));
}
/**
* @}
*/
/** @defgroup DMA_Group3 Double Buffer mode functions
* @brief Double Buffer mode functions
*
@verbatim
===============================================================================
Double Buffer mode functions
===============================================================================
This subsection provides function allowing to configure and control the double
buffer mode parameters.
The Double Buffer mode can be used only when Circular mode is enabled.
The Double Buffer mode cannot be used when transferring data from Memory to Memory.
The Double Buffer mode allows to set two different Memory addresses from/to which
the DMA controller will access alternatively (after completing transfer to/from target
memory 0, it will start transfer to/from target memory 1).
This allows to reduce software overhead for double buffering and reduce the CPU
access time.
Two functions must be called before calling the DMA_Init() function:
- void DMA_DoubleBufferModeConfig(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t Memory1BaseAddr,
uint32_t DMA_CurrentMemory);
- void DMA_DoubleBufferModeCmd(DMA_Stream_TypeDef* DMAy_Streamx, FunctionalState NewState);
DMA_DoubleBufferModeConfig() is called to configure the Memory 1 base address and the first
Memory target from/to which the transfer will start after enabling the DMA Stream.
Then DMA_DoubleBufferModeCmd() must be called to enable the Double Buffer mode (or disable
it when it should not be used).
Two functions can be called dynamically when the transfer is ongoing (or when the DMA Stream is
stopped) to modify on of the target Memories addresses or to check wich Memory target is currently
used:
- void DMA_MemoryTargetConfig(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t MemoryBaseAddr,
uint32_t DMA_MemoryTarget);
- uint32_t DMA_GetCurrentMemoryTarget(DMA_Stream_TypeDef* DMAy_Streamx);
DMA_MemoryTargetConfig() can be called to modify the base address of one of the two target Memories.
The Memory of which the base address will be modified must not be currently be used by the DMA Stream
(ie. if the DMA Stream is currently transferring from Memory 1 then you can only modify base address
of target Memory 0 and vice versa).
To check this condition, it is recommended to use the function DMA_GetCurrentMemoryTarget() which
returns the index of the Memory target currently in use by the DMA Stream.
@endverbatim
* @{
*/
/**
* @brief Configures, when the DMAy Streamx is disabled, the double buffer mode
* and the current memory target.
* @param DMAy_Streamx: where y can be 1 or 2 to select the DMA and x can be 0
* to 7 to select the DMA Stream.
* @param Memory1BaseAddr: the base address of the second buffer (Memory 1)
* @param DMA_CurrentMemory: specifies which memory will be first buffer for
* the transactions when the Stream will be enabled.
* This parameter can be one of the following values:
* @arg DMA_Memory_0: Memory 0 is the current buffer.
* @arg DMA_Memory_1: Memory 1 is the current buffer.
*
* @note Memory0BaseAddr is set by the DMA structure configuration in DMA_Init().
*
* @retval None
*/
void DMA_DoubleBufferModeConfig(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t Memory1BaseAddr,
uint32_t DMA_CurrentMemory)
{
/* Check the parameters */
assert_param(IS_DMA_ALL_PERIPH(DMAy_Streamx));
assert_param(IS_DMA_CURRENT_MEM(DMA_CurrentMemory));
if (DMA_CurrentMemory != DMA_Memory_0)
{
/* Set Memory 1 as current memory address */
DMAy_Streamx->CR |= (uint32_t)(DMA_SxCR_CT);
}
else
{
/* Set Memory 0 as current memory address */
DMAy_Streamx->CR &= ~(uint32_t)(DMA_SxCR_CT);
}
/* Write to DMAy Streamx M1AR */
DMAy_Streamx->M1AR = Memory1BaseAddr;
}
/**
* @brief Enables or disables the double buffer mode for the selected DMA stream.
* @note This function can be called only when the DMA Stream is disabled.
* @param DMAy_Streamx: where y can be 1 or 2 to select the DMA and x can be 0
* to 7 to select the DMA Stream.
* @param NewState: new state of the DMAy Streamx double buffer mode.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void DMA_DoubleBufferModeCmd(DMA_Stream_TypeDef* DMAy_Streamx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_DMA_ALL_PERIPH(DMAy_Streamx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
/* Configure the Double Buffer mode */
if (NewState != DISABLE)
{
/* Enable the Double buffer mode */
DMAy_Streamx->CR |= (uint32_t)DMA_SxCR_DBM;
}
else
{
/* Disable the Double buffer mode */
DMAy_Streamx->CR &= ~(uint32_t)DMA_SxCR_DBM;
}
}
/**
* @brief Configures the Memory address for the next buffer transfer in double
* buffer mode (for dynamic use). This function can be called when the
* DMA Stream is enabled and when the transfer is ongoing.
* @param DMAy_Streamx: where y can be 1 or 2 to select the DMA and x can be 0
* to 7 to select the DMA Stream.
* @param MemoryBaseAddr: The base address of the target memory buffer
* @param DMA_MemoryTarget: Next memory target to be used.
* This parameter can be one of the following values:
* @arg DMA_Memory_0: To use the memory address 0
* @arg DMA_Memory_1: To use the memory address 1
*
* @note It is not allowed to modify the Base Address of a target Memory when
* this target is involved in the current transfer. ie. If the DMA Stream
* is currently transferring to/from Memory 1, then it not possible to
* modify Base address of Memory 1, but it is possible to modify Base
* address of Memory 0.
* To know which Memory is currently used, you can use the function
* DMA_GetCurrentMemoryTarget().
*
* @retval None
*/
void DMA_MemoryTargetConfig(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t MemoryBaseAddr,
uint32_t DMA_MemoryTarget)
{
/* Check the parameters */
assert_param(IS_DMA_ALL_PERIPH(DMAy_Streamx));
assert_param(IS_DMA_CURRENT_MEM(DMA_MemoryTarget));
/* Check the Memory target to be configured */
if (DMA_MemoryTarget != DMA_Memory_0)
{
/* Write to DMAy Streamx M1AR */
DMAy_Streamx->M1AR = MemoryBaseAddr;
}
else
{
/* Write to DMAy Streamx M0AR */
DMAy_Streamx->M0AR = MemoryBaseAddr;
}
}
/**
* @brief Returns the current memory target used by double buffer transfer.
* @param DMAy_Streamx: where y can be 1 or 2 to select the DMA and x can be 0
* to 7 to select the DMA Stream.
* @retval The memory target number: 0 for Memory0 or 1 for Memory1.
*/
uint32_t DMA_GetCurrentMemoryTarget(DMA_Stream_TypeDef* DMAy_Streamx)
{
uint32_t tmp = 0;
/* Check the parameters */
assert_param(IS_DMA_ALL_PERIPH(DMAy_Streamx));
/* Get the current memory target */
if ((DMAy_Streamx->CR & DMA_SxCR_CT) != 0)
{
/* Current memory buffer used is Memory 1 */
tmp = 1;
}
else
{
/* Current memory buffer used is Memory 0 */
tmp = 0;
}
return tmp;
}
/**
* @}
*/
/** @defgroup DMA_Group4 Interrupts and flags management functions
* @brief Interrupts and flags management functions
*
@verbatim
===============================================================================
Interrupts and flags management functions
===============================================================================
This subsection provides functions allowing to
- Check the DMA enable status
- Check the FIFO status
- Configure the DMA Interrupts sources and check or clear the flags or pending bits status.
1. DMA Enable status:
After configuring the DMA Stream (DMA_Init() function) and enabling the stream,
it is recommended to check (or wait until) the DMA Stream is effectively enabled.
A Stream may remain disabled if a configuration parameter is wrong.
After disabling a DMA Stream, it is also recommended to check (or wait until) the DMA
Stream is effectively disabled. If a Stream is disabled while a data transfer is ongoing,
the current data will be transferred and the Stream will be effectively disabled only after
this data transfer completion.
To monitor this state it is possible to use the following function:
- FunctionalState DMA_GetCmdStatus(DMA_Stream_TypeDef* DMAy_Streamx);
2. FIFO Status:
It is possible to monitor the FIFO status when a transfer is ongoing using the following
function:
- uint32_t DMA_GetFIFOStatus(DMA_Stream_TypeDef* DMAy_Streamx);
3. DMA Interrupts and Flags:
The user should identify which mode will be used in his application to manage the
DMA controller events: Polling mode or Interrupt mode.
Polling Mode
=============
Each DMA stream can be managed through 4 event Flags:
(x : DMA Stream number )
1. DMA_FLAG_FEIFx : to indicate that a FIFO Mode Transfer Error event occurred.
2. DMA_FLAG_DMEIFx : to indicate that a Direct Mode Transfer Error event occurred.
3. DMA_FLAG_TEIFx : to indicate that a Transfer Error event occurred.
4. DMA_FLAG_HTIFx : to indicate that a Half-Transfer Complete event occurred.
5. DMA_FLAG_TCIFx : to indicate that a Transfer Complete event occurred .
In this Mode it is advised to use the following functions:
- FlagStatus DMA_GetFlagStatus(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t DMA_FLAG);
- void DMA_ClearFlag(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t DMA_FLAG);
Interrupt Mode
===============
Each DMA Stream can be managed through 4 Interrupts:
Interrupt Source
----------------
1. DMA_IT_FEIFx : specifies the interrupt source for the FIFO Mode Transfer Error event.
2. DMA_IT_DMEIFx : specifies the interrupt source for the Direct Mode Transfer Error event.
3. DMA_IT_TEIFx : specifies the interrupt source for the Transfer Error event.
4. DMA_IT_HTIFx : specifies the interrupt source for the Half-Transfer Complete event.
5. DMA_IT_TCIFx : specifies the interrupt source for the a Transfer Complete event.
In this Mode it is advised to use the following functions:
- void DMA_ITConfig(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t DMA_IT, FunctionalState NewState);
- ITStatus DMA_GetITStatus(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t DMA_IT);
- void DMA_ClearITPendingBit(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t DMA_IT);
@endverbatim
* @{
*/
/**
* @brief Returns the status of EN bit for the specified DMAy Streamx.
* @param DMAy_Streamx: where y can be 1 or 2 to select the DMA and x can be 0
* to 7 to select the DMA Stream.
*
* @note After configuring the DMA Stream (DMA_Init() function) and enabling
* the stream, it is recommended to check (or wait until) the DMA Stream
* is effectively enabled. A Stream may remain disabled if a configuration
* parameter is wrong.
* After disabling a DMA Stream, it is also recommended to check (or wait
* until) the DMA Stream is effectively disabled. If a Stream is disabled
* while a data transfer is ongoing, the current data will be transferred
* and the Stream will be effectively disabled only after the transfer
* of this single data is finished.
*
* @retval Current state of the DMAy Streamx (ENABLE or DISABLE).
*/
FunctionalState DMA_GetCmdStatus(DMA_Stream_TypeDef* DMAy_Streamx)
{
FunctionalState state = DISABLE;
/* Check the parameters */
assert_param(IS_DMA_ALL_PERIPH(DMAy_Streamx));
if ((DMAy_Streamx->CR & (uint32_t)DMA_SxCR_EN) != 0)
{
/* The selected DMAy Streamx EN bit is set (DMA is still transferring) */
state = ENABLE;
}
else
{
/* The selected DMAy Streamx EN bit is cleared (DMA is disabled and
all transfers are complete) */
state = DISABLE;
}
return state;
}
/**
* @brief Returns the current DMAy Streamx FIFO filled level.
* @param DMAy_Streamx: where y can be 1 or 2 to select the DMA and x can be 0
* to 7 to select the DMA Stream.
* @retval The FIFO filling state.
* - DMA_FIFOStatus_Less1QuarterFull: when FIFO is less than 1 quarter-full
* and not empty.
* - DMA_FIFOStatus_1QuarterFull: if more than 1 quarter-full.
* - DMA_FIFOStatus_HalfFull: if more than 1 half-full.
* - DMA_FIFOStatus_3QuartersFull: if more than 3 quarters-full.
* - DMA_FIFOStatus_Empty: when FIFO is empty
* - DMA_FIFOStatus_Full: when FIFO is full
*/
uint32_t DMA_GetFIFOStatus(DMA_Stream_TypeDef* DMAy_Streamx)
{
uint32_t tmpreg = 0;
/* Check the parameters */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -