/* ---------------------------------------------------------------------- * Copyright (C) 2015 ARM Limited. All rights reserved. * * $Date: 27. August 2013 * $Revision: V1.2 * * Project: DMA Driver for ST STM32F10x * -------------------------------------------------------------------- */ /* History: * Version 1.2 * DMAx_Channel variable is checked for initialized channels in DMA_ChannelUninitialize function * Version 1.1 * DMA2 peripheral added to build when HD, XL, HD_VL or CL device is used * Version 1.0 * Initial release */ #include "DMA_STM32F10x.h" #if defined(STM32F10X_HD) || defined(STM32F10X_XL) || \ defined(STM32F10X_HD_VL) || defined(STM32F10X_CL) /* DMA2 peripheral exists on HD, XL, HD_VL and CL devices */ #define STM32F10X_ENABLE_DMA2 #endif /// DMA Variables static uint8_t DMA1_Channel; // Used DMA1 Channels #if defined (STM32F10X_ENABLE_DMA2) static uint8_t DMA2_Channel; // Used DMA2 Channels #endif /// DMA Functions /** \fn void DMA_ChannelInitialize (uint32_t dma, uint32_t channel) \brief Initialize DMA Channel \param[in] dma DMA number \param[in] channel DMA channel number */ void DMA_ChannelInitialize (uint32_t dma, uint32_t channel) { switch (dma) { case 1: RCC->AHBENR |= RCC_AHBENR_DMA1EN; switch (channel) { case 1: DMA1_Channel1->CCR = 0; DMA1->IFCR = DMA_IFCR_CGIF1 | DMA_IFCR_CTEIF1 | DMA_IFCR_CHTIF1 | DMA_IFCR_CTCIF1; NVIC_ClearPendingIRQ(DMA1_Channel1_IRQn); NVIC_EnableIRQ(DMA1_Channel1_IRQn); break; case 2: DMA1_Channel2->CCR = 0; DMA1->IFCR = DMA_IFCR_CGIF2 | DMA_IFCR_CTEIF2 | DMA_IFCR_CHTIF2 | DMA_IFCR_CTCIF2; NVIC_ClearPendingIRQ(DMA1_Channel2_IRQn); NVIC_EnableIRQ(DMA1_Channel2_IRQn); break; case 3: DMA1_Channel3->CCR = 0; DMA1->IFCR = DMA_IFCR_CGIF3 | DMA_IFCR_CTEIF3 | DMA_IFCR_CHTIF3 | DMA_IFCR_CTCIF3; NVIC_ClearPendingIRQ(DMA1_Channel3_IRQn); NVIC_EnableIRQ(DMA1_Channel3_IRQn); break; case 4: DMA1_Channel4->CCR = 0; DMA1->IFCR = DMA_IFCR_CGIF4 | DMA_IFCR_CTEIF4 | DMA_IFCR_CHTIF4 | DMA_IFCR_CTCIF4; NVIC_ClearPendingIRQ(DMA1_Channel4_IRQn); NVIC_EnableIRQ(DMA1_Channel4_IRQn); break; case 5: DMA1_Channel5->CCR = 0; DMA1->IFCR = DMA_IFCR_CGIF5 | DMA_IFCR_CTEIF5 | DMA_IFCR_CHTIF5 | DMA_IFCR_CTCIF5; NVIC_ClearPendingIRQ(DMA1_Channel5_IRQn); NVIC_EnableIRQ(DMA1_Channel5_IRQn); break; case 6: DMA1_Channel6->CCR = 0; DMA1->IFCR = DMA_IFCR_CGIF6 | DMA_IFCR_CTEIF6 | DMA_IFCR_CHTIF6 | DMA_IFCR_CTCIF6; NVIC_ClearPendingIRQ(DMA1_Channel6_IRQn); NVIC_EnableIRQ(DMA1_Channel6_IRQn); break; case 7: DMA1_Channel7->CCR = 0; DMA1->IFCR = DMA_IFCR_CGIF7 | DMA_IFCR_CTEIF7 | DMA_IFCR_CHTIF7 | DMA_IFCR_CTCIF7; NVIC_ClearPendingIRQ(DMA1_Channel7_IRQn); NVIC_EnableIRQ(DMA1_Channel7_IRQn); break; } DMA1_Channel |= 1 << channel; break; #if defined (STM32F10X_ENABLE_DMA2) case 2: RCC->AHBENR |= RCC_AHBENR_DMA2EN; switch (channel) { case 1: DMA2_Channel1->CCR = 0; DMA2->IFCR = DMA_IFCR_CGIF1 | DMA_IFCR_CTEIF1 | DMA_IFCR_CHTIF1 | DMA_IFCR_CTCIF1; NVIC_ClearPendingIRQ(DMA2_Channel1_IRQn); NVIC_EnableIRQ(DMA2_Channel1_IRQn); break; case 2: DMA2_Channel2->CCR = 0; DMA2->IFCR = DMA_IFCR_CGIF2 | DMA_IFCR_CTEIF2 | DMA_IFCR_CHTIF2 | DMA_IFCR_CTCIF2; NVIC_ClearPendingIRQ(DMA2_Channel2_IRQn); NVIC_EnableIRQ(DMA2_Channel2_IRQn); break; case 3: DMA2_Channel3->CCR = 0; DMA2->IFCR = DMA_IFCR_CGIF3 | DMA_IFCR_CTEIF3 | DMA_IFCR_CHTIF3 | DMA_IFCR_CTCIF3; NVIC_ClearPendingIRQ(DMA2_Channel3_IRQn); NVIC_EnableIRQ(DMA2_Channel3_IRQn); break; case 4: DMA2_Channel4->CCR = 0; DMA2->IFCR = DMA_IFCR_CGIF4 | DMA_IFCR_CTEIF4 | DMA_IFCR_CHTIF4 | DMA_IFCR_CTCIF4; #if defined (STM32F10X_CL) NVIC_ClearPendingIRQ(DMA2_Channel4_IRQn); NVIC_EnableIRQ(DMA2_Channel4_IRQn); #else NVIC_ClearPendingIRQ(DMA2_Channel4_5_IRQn); NVIC_EnableIRQ(DMA2_Channel4_5_IRQn); #endif break; case 5: DMA2_Channel5->CCR = 0; DMA2->IFCR = DMA_IFCR_CGIF5 | DMA_IFCR_CTEIF5 | DMA_IFCR_CHTIF5 | DMA_IFCR_CTCIF5; #if defined (STM32F10X_CL) NVIC_ClearPendingIRQ(DMA2_Channel5_IRQn); NVIC_EnableIRQ(DMA2_Channel5_IRQn); #elif defined (STM32F10X_HD_VL) if (AFIO->MAPR2 & AFIO_MAPR2_MISC_REMAP) { /* DMA2 Channel 5 mapped at position 60 */ NVIC_ClearPendingIRQ(DMA2_Channel5_IRQn); NVIC_EnableIRQ(DMA2_Channel5_IRQn); } else { NVIC_ClearPendingIRQ(DMA2_Channel4_5_IRQn); NVIC_EnableIRQ(DMA2_Channel4_5_IRQn); } #else NVIC_ClearPendingIRQ(DMA2_Channel4_5_IRQn); NVIC_EnableIRQ(DMA2_Channel4_5_IRQn); #endif break; } DMA2_Channel |= 1 << channel; break; #endif } } /** \fn void DMA_ChannelUninitialize (uint32_t dma, uint32_t channel) \brief Uninitialize DMA Channel \param[in] dma DMA number \param[in] channel DMA channel number */ void DMA_ChannelUninitialize (uint32_t dma, uint32_t channel) { switch (dma) { case 1: if (DMA1_Channel == 0) { // All DMA1 Channels are uninitialized return; } switch (channel) { case 1: NVIC_DisableIRQ(DMA1_Channel1_IRQn); DMA1_Channel1->CCR = 0; break; case 2: NVIC_DisableIRQ(DMA1_Channel2_IRQn); DMA1_Channel2->CCR = 0; break; case 3: NVIC_DisableIRQ(DMA1_Channel3_IRQn); DMA1_Channel3->CCR = 0; break; case 4: NVIC_DisableIRQ(DMA1_Channel4_IRQn); DMA1_Channel4->CCR = 0; break; case 5: NVIC_DisableIRQ(DMA1_Channel5_IRQn); DMA1_Channel5->CCR = 0; break; case 6: NVIC_DisableIRQ(DMA1_Channel6_IRQn); DMA1_Channel6->CCR = 0; break; case 7: NVIC_DisableIRQ(DMA1_Channel7_IRQn); DMA1_Channel7->CCR = 0; break; } DMA1_Channel &= ~(1 << channel); if (DMA1_Channel == 0){ RCC->AHBENR &= ~RCC_AHBENR_DMA1EN; } break; #if defined (STM32F10X_ENABLE_DMA2) case 2: if (DMA2_Channel == 0) { // All DMA2 Channels are uninitialized return; } switch (channel) { case 1: NVIC_DisableIRQ(DMA2_Channel1_IRQn); DMA2_Channel1->CCR = 0; break; case 2: NVIC_DisableIRQ(DMA2_Channel2_IRQn); DMA2_Channel2->CCR = 0; break; case 3: NVIC_DisableIRQ(DMA2_Channel3_IRQn); DMA2_Channel3->CCR = 0; break; case 4: #if defined (STM32F10X_CL) NVIC_DisableIRQ(DMA2_Channel4_IRQn); #else /* If Channel 5 disabled, disable also Channel 4 */ if (!(DMA2_Channel & (1 << 5))) { NVIC_DisableIRQ(DMA2_Channel4_5_IRQn); } #endif DMA2_Channel4->CCR = 0; break; case 5: #if defined (STM32F10X_CL) NVIC_DisableIRQ(DMA2_Channel5_IRQn); #elif defined (STM32F10X_HD_VL) if (AFIO->MAPR2 & AFIO_MAPR2_MISC_REMAP) { /* DMA2 Channel 5 mapped at position 60 */ NVIC_DisableIRQ(DMA2_Channel5_IRQn); } else { /* If Channel 4 disabled, disable also Channel 5 */ if (!(DMA2_Channel & (1 << 4))) { NVIC_DisableIRQ(DMA2_Channel4_5_IRQn); } } #else /* If Channel 4 disabled, disable also Channel 5 */ if (!(DMA2_Channel & (1 << 4))) { NVIC_DisableIRQ(DMA2_Channel4_5_IRQn); } #endif DMA2_Channel5->CCR = 0; break; } DMA2_Channel &= ~(1 << channel); if (DMA2_Channel == 0){ RCC->AHBENR &= ~RCC_AHBENR_DMA2EN; } break; #endif } } /// DMA1 Channel Events __weak void DMA1_Channel1_Event (uint32_t event) {;} __weak void DMA1_Channel2_Event (uint32_t event) {;} __weak void DMA1_Channel3_Event (uint32_t event) {;} __weak void DMA1_Channel4_Event (uint32_t event) {;} __weak void DMA1_Channel5_Event (uint32_t event) {;} __weak void DMA1_Channel6_Event (uint32_t event) {;} __weak void DMA1_Channel7_Event (uint32_t event) {;} #if defined (STM32F10X_ENABLE_DMA2) /// DMA2 Channel Events __weak void DMA2_Channel1_Event (uint32_t event) {;} __weak void DMA2_Channel2_Event (uint32_t event) {;} __weak void DMA2_Channel3_Event (uint32_t event) {;} __weak void DMA2_Channel4_Event (uint32_t event) {;} __weak void DMA2_Channel5_Event (uint32_t event) {;} #endif /** \fn void DMA1_Channel1_IRQHandler (void) \brief DMA1 Channel0 interrupt handler */ void DMA1_Channel1_IRQHandler (void) { uint32_t events; events = (DMA1->ISR >> 0) & DMA_CHANNEL_FLAGS; DMA1->IFCR = events << 0; DMA1_Channel1_Event(events); } /** \fn void DMA1_Channel2_IRQHandler (void) \brief DMA1 Channel2 interrupt handler */ void DMA1_Channel2_IRQHandler (void) { uint32_t events; events = (DMA1->ISR >> 4) & DMA_CHANNEL_FLAGS; DMA1->IFCR = events << 4; DMA1_Channel2_Event(events); } /** \fn void DMA1_Channel3_IRQHandler (void) \brief DMA1 Channel3 interrupt handler */ void DMA1_Channel3_IRQHandler (void) { uint32_t events; events = (DMA1->ISR >> 8) & DMA_CHANNEL_FLAGS; DMA1->IFCR = events << 8; DMA1_Channel3_Event(events); } /** \fn void DMA1_Channel4_IRQHandler (void) \brief DMA1 Channel4 interrupt handler */ void DMA1_Channel4_IRQHandler (void) { uint32_t events; events = (DMA1->ISR >> 12) & DMA_CHANNEL_FLAGS; DMA1->IFCR = events << 12; DMA1_Channel4_Event(events); } /** \fn void DMA1_Channel5_IRQHandler (void) \brief DMA1 Channel5 interrupt handler */ void DMA1_Channel5_IRQHandler (void) { uint32_t events; events = (DMA1->ISR >> 16) & DMA_CHANNEL_FLAGS; DMA1->IFCR = events << 16; DMA1_Channel5_Event(events); } /** \fn void DMA1_Channel6_IRQHandler (void) \brief DMA1 Channel6 interrupt handler */ void DMA1_Channel6_IRQHandler (void) { uint32_t events; events = (DMA1->ISR >> 20) & DMA_CHANNEL_FLAGS; DMA1->IFCR = events << 20; DMA1_Channel6_Event(events); } /** \fn void DMA1_Channel7_IRQHandler (void) \brief DMA1 Channel7 interrupt handler */ void DMA1_Channel7_IRQHandler (void) { uint32_t events; events = (DMA1->ISR >> 24) & DMA_CHANNEL_FLAGS; DMA1->IFCR = events << 24; DMA1_Channel7_Event(events); } #if defined (STM32F10X_ENABLE_DMA2) /** \fn void DMA2_Channel1_IRQHandler (void) \brief DMA2 Channel1 interrupt handler */ void DMA2_Channel1_IRQHandler (void) { uint32_t events; events = (DMA2->ISR >> 0) & DMA_CHANNEL_FLAGS; DMA2->IFCR = events << 0; DMA2_Channel1_Event(events); } /** \fn void DMA2_Channel2_IRQHandler (void) \brief DMA2 Channel2 interrupt handler */ void DMA2_Channel2_IRQHandler (void) { uint32_t events; events = (DMA2->ISR >> 4) & DMA_CHANNEL_FLAGS; DMA2->IFCR = events << 4; DMA2_Channel2_Event(events); } /** \fn void DMA2_Channel3_IRQHandler (void) \brief DMA2 Channel3 interrupt handler */ void DMA2_Channel3_IRQHandler (void) { uint32_t events; events = (DMA2->ISR >> 8) & DMA_CHANNEL_FLAGS; DMA2->IFCR = events << 8; DMA2_Channel3_Event(events); } #if !defined(STM32F10X_CL) /** \fn void DMA2_Channel4_IRQHandler (void) \brief DMA2 Channel4 interrupt handler */ void DMA2_Channel4_IRQHandler (void) { uint32_t events; events = (DMA2->ISR >> 12) & DMA_CHANNEL_FLAGS; DMA2->IFCR = events << 12; DMA2_Channel4_Event(events); } #endif #if defined(STM32F10X_HD_VL) || defined (STM32F10X_CL) /** \fn void DMA2_Channel5_IRQHandler (void) \brief DMA2 Channel5 interrupt handler */ void DMA2_Channel5_IRQHandler (void) { uint32_t events; events = (DMA2->ISR >> 16) & DMA_CHANNEL_FLAGS; DMA2->IFCR = events << 16; DMA2_Channel5_Event(events); } #endif /** \fn void DMA2_Channel4_5_IRQHandler (void) \brief DMA2 Channel 4 and 5 interrupt handler */ void DMA2_Channel4_5_IRQHandler (void) { uint32_t events; events = (DMA2->ISR >> 12) & DMA_CHANNEL_FLAGS; if (events) { /* Channel 4 events */ DMA2->IFCR = events << 12; DMA2_Channel4_Event(events); } events = (DMA2->ISR >> 16) & DMA_CHANNEL_FLAGS; if (events) { /* Channel 5 events */ DMA2->IFCR = events << 16; DMA2_Channel5_Event(events); } } #endif