📄 stm32f2xx_dma.c
字号:
/**
******************************************************************************
* @file stm32f2xx_dma.c
* @author MCD Application Team
* @version V1.0.0
* @date 18-April-2011
* @brief This file provides firmware functions to manage the following
* functionalities of the Direct Memory Access controller (DMA):
* - Initialization and Configuration
* - Data Counter
* - Double Buffer mode configuration and command
* - Interrupts and flags management
*
* @verbatim
*
* ===================================================================
* How to use this driver
* ===================================================================
* 1. Enable The DMA controller clock using RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_DMA1, ENABLE)
* function for DMA1 or using RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_DMA2, ENABLE)
* function for DMA2.
*
* 2. Enable and configure the peripheral to be connected to the DMA Stream
* (except for internal SRAM / FLASH memories: no initialization is
* necessary).
*
* 3. For a given Stream, program the required configuration through following parameters:
* Source and Destination addresses, Transfer Direction, Transfer size, Source and Destination
* data formats, Circular or Normal mode, Stream Priority level, Source and Destination
* Incrementation mode, FIFO mode and its Threshold (if needed), Burst mode for Source and/or
* Destination (if needed) using the DMA_Init() function.
* To avoid filling un-nesecessary fields, you can call DMA_StructInit() function
* to initialize a given structure with default values (reset values), the modify
* only necessary fields (ie. Source and Destination addresses, Transfer size and Data Formats).
*
* 4. Enable the NVIC and the corresponding interrupt(s) using the function
* DMA_ITConfig() if you need to use DMA interrupts.
*
* 5. Optionally, if the Circular mode is enabled, you can use the Double buffer mode by configuring
* the second Memory address and the first Memory to be used through the function
* DMA_DoubleBufferModeConfig(). Then enable the Double buffer mode through the function
* DMA_DoubleBufferModeCmd(). These operations must be done before step 6.
*
* 6. Enable the DMA stream using the DMA_Cmd() function.
*
* 7. Activate the needed Stream Request using PPP_DMACmd() function for
* any PPP peripheral except internal SRAM and FLASH (ie. SPI, USART ...)
* The function allowing this operation is provided in each PPP peripheral
* driver (ie. SPI_DMACmd for SPI peripheral).
* Once the Stream is enabled, it is not possible to modify its configuration
* unless the stream is stopped and disabled.
* After enabling the Stream, it is advised to monitor the EN bit status using
* the function DMA_GetCmdStatus(). In case of configuration errors or bus errors
* this bit will remain reset and all transfers on this Stream will remain on hold.
*
* 8. Optionally, you can configure the number of data to be transferred
* when the Stream is disabled (ie. after each Transfer Complete event
* or when a Transfer Error occurs) using the function DMA_SetCurrDataCounter().
* And you can get the number of remaining data to be transferred using
* the function DMA_GetCurrDataCounter() at run time (when the DMA Stream is
* enabled and running).
*
* 9. To control DMA events you can use one of the following
* two methods:
* a- Check on DMA Stream flags using the function DMA_GetFlagStatus().
* b- Use DMA interrupts through the function DMA_ITConfig() at initialization
* phase and DMA_GetITStatus() function into interrupt routines in
* communication phase.
* After checking on a flag you should clear it using DMA_ClearFlag()
* function. And after checking on an interrupt event you should
* clear it using DMA_ClearITPendingBit() function.
*
* 10. Optionally, if Circular mode and Double Buffer mode are enabled, you can modify
* the Memory Addresses using the function DMA_MemoryTargetConfig(). Make sure that
* the Memory Address to be modified is not the one currently in use by DMA Stream.
* This condition can be monitored using the function DMA_GetCurrentMemoryTarget().
*
* 11. Optionally, Pause-Resume operations may be performed:
* The DMA_Cmd() function may be used to perform Pause-Resume operation. When a
* transfer is ongoing, calling this function to disable the Stream will cause the
* transfer to be paused. All configuration registers and the number of remaining
* data will be preserved. When calling again this function to re-enable the Stream,
* the transfer will be resumed from the point where it was paused.
*
* @note Memory-to-Memory transfer is possible by setting the address of the memory into
* the Peripheral registers. In this mode, Circular mode and Double Buffer mode
* are not allowed.
*
* @note The FIFO is used mainly to reduce bus usage and to allow data packing/unpacking: it is
* possible to set different Data Sizes for the Peripheral and the Memory (ie. you can set
* Half-Word data size for the peripheral to access its data register and set Word data size
* for the Memory to gain in access time. Each two Half-words will be packed and written in
* a single access to a Word in the Memory).
*
* @note When FIFO is disabled, it is not allowed to configure different Data Sizes for Source
* and Destination. In this case the Peripheral Data Size will be applied to both Source
* and Destination.
*
* @endverbatim
*
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>© COPYRIGHT 2011 STMicroelectronics</center></h2>
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32f2xx_dma.h"
#include "stm32f2xx_rcc.h"
/** @addtogroup STM32F2xx_StdPeriph_Driver
* @{
*/
/** @defgroup DMA
* @brief DMA driver modules
* @{
*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Masks Definition */
#define TRANSFER_IT_ENABLE_MASK (uint32_t)(DMA_SxCR_TCIE | DMA_SxCR_HTIE | \
DMA_SxCR_TEIE | DMA_SxCR_DMEIE)
#define DMA_Stream0_IT_MASK (uint32_t)(DMA_LISR_FEIF0 | DMA_LISR_DMEIF0 | \
DMA_LISR_TEIF0 | DMA_LISR_HTIF0 | \
DMA_LISR_TCIF0)
#define DMA_Stream1_IT_MASK (uint32_t)(DMA_Stream0_IT_MASK << 6)
#define DMA_Stream2_IT_MASK (uint32_t)(DMA_Stream0_IT_MASK << 16)
#define DMA_Stream3_IT_MASK (uint32_t)(DMA_Stream0_IT_MASK << 22)
#define DMA_Stream4_IT_MASK (uint32_t)(DMA_Stream0_IT_MASK | (uint32_t)0x20000000)
#define DMA_Stream5_IT_MASK (uint32_t)(DMA_Stream1_IT_MASK | (uint32_t)0x20000000)
#define DMA_Stream6_IT_MASK (uint32_t)(DMA_Stream2_IT_MASK | (uint32_t)0x20000000)
#define DMA_Stream7_IT_MASK (uint32_t)(DMA_Stream3_IT_MASK | (uint32_t)0x20000000)
#define TRANSFER_IT_MASK (uint32_t)0x0F3C0F3C
#define HIGH_ISR_MASK (uint32_t)0x20000000
#define RESERVED_MASK (uint32_t)0x0F7D0F7D
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/** @defgroup DMA_Private_Functions
* @{
*/
/** @defgroup DMA_Group1 Initialization and Configuration functions
* @brief Initialization and Configuration functions
*
@verbatim
===============================================================================
Initialization and Configuration functions
===============================================================================
This subsection provides functions allowing to initialize the DMA Stream source
and destination addresses, incrementation and data sizes, transfer direction,
buffer size, circular/normal mode selection, memory-to-memory mode selection
and Stream priority value.
The DMA_Init() function follows the DMA configuration procedures as described in
reference manual (RM0033) except the first point: waiting on EN bit to be reset.
This condition should be checked by user application using the function DMA_GetCmdStatus()
before calling the DMA_Init() function.
@endverbatim
* @{
*/
/**
* @brief Deinitialize the DMAy Streamx registers to their default reset values.
* @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 None
*/
void DMA_DeInit(DMA_Stream_TypeDef* DMAy_Streamx)
{
/* Check the parameters */
assert_param(IS_DMA_ALL_PERIPH(DMAy_Streamx));
/* Disable the selected DMAy Streamx */
DMAy_Streamx->CR &= ~((uint32_t)DMA_SxCR_EN);
/* Reset DMAy Streamx control register */
DMAy_Streamx->CR = 0;
/* Reset DMAy Streamx Number of Data to Transfer register */
DMAy_Streamx->NDTR = 0;
/* Reset DMAy Streamx peripheral address register */
DMAy_Streamx->PAR = 0;
/* Reset DMAy Streamx memory 0 address register */
DMAy_Streamx->M0AR = 0;
/* Reset DMAy Streamx memory 1 address register */
DMAy_Streamx->M1AR = 0;
/* Reset DMAy Streamx FIFO control register */
DMAy_Streamx->FCR = (uint32_t)0x00000021;
/* Reset interrupt pending bits for the selected stream */
if (DMAy_Streamx == DMA1_Stream0)
{
/* Reset interrupt pending bits for DMA1 Stream0 */
DMA1->LIFCR = DMA_Stream0_IT_MASK;
}
else if (DMAy_Streamx == DMA1_Stream1)
{
/* Reset interrupt pending bits for DMA1 Stream1 */
DMA1->LIFCR = DMA_Stream1_IT_MASK;
}
else if (DMAy_Streamx == DMA1_Stream2)
{
/* Reset interrupt pending bits for DMA1 Stream2 */
DMA1->LIFCR = DMA_Stream2_IT_MASK;
}
else if (DMAy_Streamx == DMA1_Stream3)
{
/* Reset interrupt pending bits for DMA1 Stream3 */
DMA1->LIFCR = DMA_Stream3_IT_MASK;
}
else if (DMAy_Streamx == DMA1_Stream4)
{
/* Reset interrupt pending bits for DMA1 Stream4 */
DMA1->HIFCR = DMA_Stream4_IT_MASK;
}
else if (DMAy_Streamx == DMA1_Stream5)
{
/* Reset interrupt pending bits for DMA1 Stream5 */
DMA1->HIFCR = DMA_Stream5_IT_MASK;
}
else if (DMAy_Streamx == DMA1_Stream6)
{
/* Reset interrupt pending bits for DMA1 Stream6 */
DMA1->HIFCR = (uint32_t)DMA_Stream6_IT_MASK;
}
else if (DMAy_Streamx == DMA1_Stream7)
{
/* Reset interrupt pending bits for DMA1 Stream7 */
DMA1->HIFCR = DMA_Stream7_IT_MASK;
}
else if (DMAy_Streamx == DMA2_Stream0)
{
/* Reset interrupt pending bits for DMA2 Stream0 */
DMA2->LIFCR = DMA_Stream0_IT_MASK;
}
else if (DMAy_Streamx == DMA2_Stream1)
{
/* Reset interrupt pending bits for DMA2 Stream1 */
DMA2->LIFCR = DMA_Stream1_IT_MASK;
}
else if (DMAy_Streamx == DMA2_Stream2)
{
/* Reset interrupt pending bits for DMA2 Stream2 */
DMA2->LIFCR = DMA_Stream2_IT_MASK;
}
else if (DMAy_Streamx == DMA2_Stream3)
{
/* Reset interrupt pending bits for DMA2 Stream3 */
DMA2->LIFCR = DMA_Stream3_IT_MASK;
}
else if (DMAy_Streamx == DMA2_Stream4)
{
/* Reset interrupt pending bits for DMA2 Stream4 */
DMA2->HIFCR = DMA_Stream4_IT_MASK;
}
else if (DMAy_Streamx == DMA2_Stream5)
{
/* Reset interrupt pending bits for DMA2 Stream5 */
DMA2->HIFCR = DMA_Stream5_IT_MASK;
}
else if (DMAy_Streamx == DMA2_Stream6)
{
/* Reset interrupt pending bits for DMA2 Stream6 */
DMA2->HIFCR = DMA_Stream6_IT_MASK;
}
else
{
if (DMAy_Streamx == DMA2_Stream7)
{
/* Reset interrupt pending bits for DMA2 Stream7 */
DMA2->HIFCR = DMA_Stream7_IT_MASK;
}
}
}
/**
* @brief Initializes the DMAy Streamx according to the specified parameters in
* the DMA_InitStruct structure.
* @note Before calling this function, it is recommended to check that the Stream
* is actually disabled using the function DMA_GetCmdStatus().
* @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 DMA_InitStruct: pointer to a DMA_InitTypeDef structure that contains
* the configuration information for the specified DMA Stream.
* @retval None
*/
void DMA_Init(DMA_Stream_TypeDef* DMAy_Streamx, DMA_InitTypeDef* DMA_InitStruct)
{
uint32_t tmpreg = 0;
/* Check the parameters */
assert_param(IS_DMA_ALL_PERIPH(DMAy_Streamx));
assert_param(IS_DMA_CHANNEL(DMA_InitStruct->DMA_Channel));
assert_param(IS_DMA_DIRECTION(DMA_InitStruct->DMA_DIR));
assert_param(IS_DMA_BUFFER_SIZE(DMA_InitStruct->DMA_BufferSize));
assert_param(IS_DMA_PERIPHERAL_INC_STATE(DMA_InitStruct->DMA_PeripheralInc));
assert_param(IS_DMA_MEMORY_INC_STATE(DMA_InitStruct->DMA_MemoryInc));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -