DMA on STM32L011F4
I'm trying to program an STM32L011F4 to transmit data through USART2 by way of the DMA controller. My code compiles but the IRQ handler for DMA is never called. Either I have not correctly initialized the DMA controller or there is another problem I am overlooking. Can anyone provide suggestions?
//-----------------------------------------------------------------------------
#include <stdio.h>
#include "stm32l0xx.h"
//-----------------------------------------------------------------------------
#define USART_TX_PIN GPIO_PIN_2
#define DMA_BUFFER_SIZE 64
uint8_t dma_buffer[ DMA_BUFFER_SIZE ] = "String to send through USART2 by DMA!\r\n";
//-----------------------------------------------------------------------------
void SystemClock_Config(void);
void USART2_Init(void);
void DMA_Init(void);
void Start_DMA_Transmission(void);
//-----------------------------------------------------------------------------
int main( void ) {
SystemClock_Config(); // Configure system clock
USART2_Init(); // Initialize USART2
DMA_Init(); // Initialize DMA
Start_DMA_Transmission(); // Start data transmission over DMA
while (1) { __asm__( "NOP" ); };
}; // end main
//-----------------------------------------------------------------------------
void SystemClock_Config( void ) {
// Configure the system clock to use HSI at 16 MHz
RCC->CR |= RCC_CR_HSION; // Enable HSI
while ( !( RCC->CR & RCC_CR_HSIRDY ) ){ __asm__( "NOP" ); }; // Wait for HSI
RCC->CFGR = 0; // System clock source is HSI
SystemCoreClockUpdate(); // Update SystemCoreClock variable
}; // end SystemClock_Config
//-----------------------------------------------------------------------------
void USART2_Init( void ) {
// Enable GPIOA and USART2 clocks
RCC->IOPENR |= RCC_IOPENR_GPIOAEN;
RCC->APB1ENR |= RCC_APB1ENR_USART2EN;
// Configure PA2 as USART2 TX
GPIOA->MODER &= ~GPIO_MODER_MODE2; // Clear mode bits
GPIOA->MODER |= GPIO_MODER_MODE2_1; // Set PA2 to alternate function mode
GPIOA->AFR[0] |= ( 4 << GPIO_AFRL_AFSEL2_Pos ); // Set PA2 to AF4 (USART2)
// Configure USART2 baud rate, enable TX, enable USART
USART2->BRR = SystemCoreClock / 9600; // Set baud rate to 9600 (assuming 16 MHz clock)
USART2->CR1 = USART_CR1_TE | USART_CR1_UE; // Enable TX and USART
}; // end USART2_Init
//-----------------------------------------------------------------------------
void DMA_Init(void) {
RCC->AHBENR |= RCC_AHBENR_DMA1EN; // Enable DMA clock
DMA1_Channel2->CCR &= ~DMA_CCR_EN; // Disable channel before configuration
DMA1_Channel2->CCR &= ~( DMA_CCR_MSIZE_0 | DMA_CCR_MSIZE_1 ); // Set size to 8 bits
DMA1_Channel2->CCR &= ~( DMA_CCR_PSIZE_0 | DMA_CCR_PSIZE_1 ); // Set USART to 8 bits
DMA1_Channel2->CCR =
DMA_CCR_MINC | // Enable memory increment
DMA_CCR_DIR | // Read from memory
DMA_CCR_TEIE | // Transfer error flag
DMA_CCR_HTIE | // Half transfer flag
DMA_CCR_TCIE; // Enable transfer complete interrupt
// Configure DMA for USART2 TX (Channel 2)
DMA1_Channel2->CPAR = (uint32_t)(&(USART2->TDR)); // Set peripheral address to USART2 TDR
DMA1_Channel2->CMAR = (uint32_t)dma_buffer; // Set memory address to dma_buffer
DMA1_Channel2->CNDTR = sizeof(dma_buffer) - 1; // Set number of data items to transfer
DMA1_Channel2->CCR &= ~( DMA_CCR_PL_0 | DMA_CCR_PL_1 ); // Set priority to low
// Enable DMA interrupt in NVIC
NVIC_SetPriority( DMA1_Channel2_3_IRQn, 0x0 );
NVIC_EnableIRQ( DMA1_Channel2_3_IRQn );
}; // DMA_Init
//-----------------------------------------------------------------------------
void Start_DMA_Transmission( void ) {
USART2->CR3 |= USART_CR3_DMAT; // Enable DMA for USART2 TX
while ( ( USART2->ISR & USART_ISR_TC ) != USART_ISR_TC ) { __asm__( "NOP" ); };
USART2->ICR = USART_ICR_TCCF; // Clear TC Flag
DMA1_Channel2->CCR |= DMA_CCR_EN; // Enable DMA Channel 2
}; // end Start_DMA_Transmission
//-----------------------------------------------------------------------------
void DMA1_Channel2_3_IRQHandler( void ) {
if ( DMA1->ISR & DMA_ISR_TCIF2 ) { // Check for transfer complete interrupt flag
DMA1->IFCR = DMA_IFCR_CTCIF2; // Clear transfer complete interrupt flag
DMA1_Channel2->CCR &= ~DMA_CCR_EN; // Disable DMA Channel 4 after transfer
return;
}; // end TCIF2
}; // end DMA1_Channel2_3_IRQHandler

