Library 63- DMA for STM32F4xx
Having each stream on separate bits for checking flags has really annoying for me! I had to made a library for DMA which will handle all that stuff any maybe a little more for me because it is really stressfull, when I have to change DMA stream. Then you have to change interrupt handler function name, all flag bit locations and so on. Too much work for easily fail and bug is here!
To enable/disable interrupts, get/clear flags, you have to pass only which stream and which flag for transfer complete, error, half complete….
Library
Features
- Easy checking and clearing DMA interrupt flags
- Easy interrupt handling for DMA stream
- Enable/Disable interrupts
Dependencies
- CMSIS
- STM32F4xx
- STM32F4xx DMA
- STM32F4xx MISC
- TM
- defines.h
- attributes.h
- defines.h
Interrupt handling
Library has implemented all DMA stream interrupt handlers for easy interrupt handling for user. The problem happen when some libraries from me also uses interrupt handler internally.
One example is FATFS library. DMA for SDIO is DMA2_Stream3 and function DMA2_Stream3_IRQHandler() is also implemented in my DMA and FATFS library. If you use both libs, error will happen. To prevent this errors I’ve added support to disable interrupt handler inside DMA library from me. To disable it, open defines.h file and add defines:
1 2 3 4 5 6 |
/* Disable DMAx_STREAMy IRQ handler function and use custom */ /* Change x with 1 or 2 and y to 0 to 7 */ #define DMAx_STREAMy_DISABLE_IRQHANDLER /* Example for FATFS would be */ #define DMA2_STREAM3_DISABLE_IRQHANDLER |
Functions and enumerations
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
/** * @defgroup TM_DMA_Functions * @brief Library Functions * @{ */ /** * @brief Clears all flags for selected DMA stream * @param *DMA_Stream: Pointer to @ref DMA_Stream_TypeDef DMA stream where you want to clear flags * @retval None */ void TM_DMA_ClearFlags(DMA_Stream_TypeDef* DMA_Stream); /** * @brief Clears selected DMA interrupt flag * @param *DMA_Stream: Pointer to @ref DMA_Stream_TypeDef DMA stream where you want to clear flags * @param flags: Flag(s) which you wanna clear: * - DMA_FLAG_TCIF: Transfer complete interrupt flag * - DMA_FLAG HITF: Hafl-transfer complete interrupt flag * - DMA_FLAG_TEIF: Transfer error interrupt flag * - DMA_FLAG_DMEIF: Direct mode error interrupt flag * - DMA_FLAG_FEIF: FIFO error interrupt flag * - DMA_FLAG_ALL: All flags * @retval None */ void TM_DMA_ClearFlag(DMA_Stream_TypeDef* DMA_Stream, uint32_t flags); /** * @brief Enables interrupts for DMA stream * @note It adds IRQ to NVIC and enables all possible DMA STREAM interrupts * @param *DMA_Stream: Pointer to DMA stream where to enable interrupts * @retval None */ void TM_DMA_EnableInterrupts(DMA_Stream_TypeDef* DMA_Stream); /** * @brief Disables interrupts for DMA stream * @note It adds IRQ to NVIC and enables all possible DMA STREAM interrupts * @param *DMA_Stream: Pointer to DMA stream where to disable interrupts * @retval None */ void TM_DMA_DisableInterrupts(DMA_Stream_TypeDef* DMA_Stream); /** * @brief Transfer complete callback * @note This function is called when interrupt for specific stream happens * @param *DMA_Stream: Pointer to DMA stream where interrupt happens * @retval None * @note With __weak parameter to prevent link errors if not defined by user */ void TM_DMA_TransferCompleteHandler(DMA_Stream_TypeDef* DMA_Stream); /** * @brief Half transfer complete callback * @note This function is called when interrupt for specific stream happens * @param *DMA_Stream: Pointer to DMA stream where interrupt happens * @retval None * @note With __weak parameter to prevent link errors if not defined by user */ void TM_DMA_HalfTransferCompleteHandler(DMA_Stream_TypeDef* DMA_Stream); /** * @brief Transfer error callback * @note This function is called when interrupt for specific stream happens * @param *DMA_Stream: Pointer to DMA stream where interrupt happens * @retval None * @note With __weak parameter to prevent link errors if not defined by user */ void TM_DMA_TransferErrorHandler(DMA_Stream_TypeDef* DMA_Stream); /** * @brief Direct mode error callback * @note This function is called when interrupt for specific stream happens * @param *DMA_Stream: Pointer to DMA stream where interrupt happens * @retval None * @note With __weak parameter to prevent link errors if not defined by user */ void TM_DMA_DirectModeErrorHandler(DMA_Stream_TypeDef* DMA_Stream); /** * @brief FIFO error error callback * @note This function is called when interrupt for specific stream happens * @param *DMA_Stream: Pointer to DMA stream where interrupt happens * @retval None * @note With __weak parameter to prevent link errors if not defined by user */ void TM_DMA_FIFOErrorHandler(DMA_Stream_TypeDef* DMA_Stream); /** * @} */ |
Example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
/** * Keil project for DMA * * Before you start, select your target, on the right of the "Load" button * * @author Tilen Majerle * @email tilen@majerle.eu * @website http://stm32f4-discovery.net * @ide Keil uVision 5 * @conf PLL parameters are set in "Options for Target" -> "C/C++" -> "Defines" * @packs STM32F4xx Keil packs version 2.4.0 or greater required * @stdperiph STM32F4xx Standard peripheral drivers version 1.5.0 or greater required */ /* Include core modules */ #include "stm32f4xx.h" /* Include my libraries here */ #include "defines.h" #include "tm_stm32f4_usart.h" #include "tm_stm32f4_usart_dma.h" #include "string.h" /* Create USART working buffer */ char USART_Buffer[100] = "Hello via USART2 with TX DMA before interrupt happens\n"; int main(void) { /* Initialize system */ SystemInit(); /* Init USART2 on pins TX = PA2, RX = PA3 */ /* This pins are used on Nucleo boards for USB to UART via ST-Link */ TM_USART_Init(USART2, TM_USART_PinsPack_1, 115200); /* Say string without DMA */ TM_USART_Puts(USART2, "Hello via USART2 without DMA\n"); /* Init TX DMA for USART2 */ /* Interrupts for USART2 DMA TX stream are also enabled */ TM_USART_DMA_Init(USART2); /* Enable USART DMA interrupts */ TM_USART_DMA_EnableInterrupts(USART2); /* Send data with DMA */ TM_USART_DMA_Send(USART2, (uint8_t *)USART_Buffer, strlen(USART_Buffer)); /* Wait till DMA works */ /* You can do other stuff here instead of waiting for DMA to end */ while (TM_USART_DMA_Sending(USART2)); while (1) { /* If any string arrived over USART */ /* Expecting "\n" at the end of string from USART terminal or any other source */ if (TM_USART_Gets(USART2, USART_Buffer, sizeof(USART_Buffer))) { /* Send it back over DMA */ TM_USART_DMA_Send(USART2, (uint8_t *)USART_Buffer, strlen(USART_Buffer)); /* Wait till DMA works */ /* You can do other stuff here instead of waiting for DMA to end */ while (TM_USART_DMA_Sending(USART2)); } } } /* Called when transfer is completed for specific stream */ void TM_DMA_TransferCompleteHandler(DMA_Stream_TypeDef* DMA_Stream) { /* Check if interrupt is for correct stream */ if (DMA_Stream == TM_USART_DMA_GetStream(USART2)) { TM_USART_Puts(USART2, "Stream has finished with transfer\n"); } } /* Called when half transfer is completed for specific stream */ void TM_DMA_HalfTransferCompleteHandler(DMA_Stream_TypeDef* DMA_Stream) { /* Check if interrupt is for correct stream */ if (DMA_Stream == TM_USART_DMA_GetStream(USART2)) { /* Do stuff here */ //TM_USART_Puts(USART2, "Stream has finished with half transfer\n"); } } /* Called when transfer error occurs for specific stream */ void TM_DMA_TransferErrorHandler(DMA_Stream_TypeDef* DMA_Stream) { /* Check if interrupt is for correct stream */ if (DMA_Stream == TM_USART_DMA_GetStream(USART2)) { /* Do stuff here */ //TM_USART_Puts(USART2, "Stream transfer error occured\n"); } } |
Project is available on my Github, download library below.
Recent comments