STM32L011 DMA read from const variable (flash)
Controller: STM32L011G4U
Libraries: CMSIS
Compiler: arm-none-eabi-gcc version 13.2.1
In order to change Capture Compare Register of TIM2 automatically every time when TIM2 updates, I want to use DMA to get the current CCR values from a const array.
const uint16_t source[5] = { 1, 2, 3, 4, 5 };
RCC->AHBENR |= RCC_AHBENR_DMA1EN; // enable DMA1 clock
// DMA TIM2_UP
DMA1_CSELR->CSELR |= (0b1000 << DMA_CSELR_C2S_Pos); // put TIM2_UP on DMA1 channel 2
DMA1_Channel2->CCR = DMA_CCR_MINC; // memory address pointer is incremented
DMA1_Channel2->CCR |= DMA_CCR_DIR; // direction is memory to peripheral
DMA1_Channel2->CCR |= DMA_CCR_CIRC; // circular mode
DMA1_Channel2->CCR |= (0b01 << DMA_CCR_MSIZE_Pos); // size of memory data is 16 Bit
DMA1_Channel2->CCR |= (0b01 << DMA_CCR_PSIZE_Pos); // size of peripheral data is 16 Bit
DMA1_Channel2->CPAR = (uint32_t) &TIM2->CCR4; // peripheral address
DMA1_Channel2->CMAR = (uint32_t) &source; // memory address
DMA1_Channel2->CNDTR = 5; // number of data to transfer
// TIM2
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN; // enable clock
TIM2->PSC = 0;
TIM2->ARR = 0xFFFF;
TIM2->CR1 = TIM_CR1_ARPE; // ARR register is buffered
TIM2->DIER = TIM_DIER_UDE; // enable DMA for timer update
TIM2->CCMR2 |= (0b110 << TIM_CCMR2_OC4M_Pos); // PWM mode 1
TIM2->CCMR2 |= TIM_CCMR2_OC4PE; // output compare preload enable
TIM2->CCR4 = 0; // reset output compare register
TIM2->CCER |= TIM_CCER_CC4E; // enable output
TIM2->EGR |= TIM_EGR_UG;
TIM2->CR1 |= TIM_CR1_CEN; // enable counter
DMA1_Channel2->CCR |= DMA_CCR_EN; // enable DMA
This code works as long as source is not defined as const variable. If source is defined as const variable, DMA sends random values to CCR4.
Is there anything to consider if DMA source data is located in flash memory?
