Skip to main content
Associate
May 22, 2024
Question

Use DMAR to update CCR1~4 registers

  • May 22, 2024
  • 3 replies
  • 2355 views

I now need to update the CCR1~CCR3 register at the same time with DMA with DMAR register, I use STM32F103C8T6, I use STM32F10x_StdPeriph_Lib_V3.6.0\Project\STM32F10x_StdPeriph_Examples\TIM\DMABurst example, in the example DMA is Normal mode, I need to keep updating the CCRx registers, so I changed the DMA to Circular mode, but the CCRx registers are not updated as I expected, they are misaligned

 

#define TIM1_DMAR_ADDRESS ((uint32_t)0x40012C4C) /* TIM ARR (Auto Reload Register) address */

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
GPIO_InitTypeDef GPIO_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
uint16_t SRC_Buffer[6] = {0x1234, 0x5678, 0xABCD};

int main(void)
{
 /* TIM1 and GPIOA clock enable */
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1 | RCC_APB2Periph_GPIOA, ENABLE);

 /* DMA clock enable */
 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
 
 /* GPIOA Configuration: Channel 1 as alternate function push-pull */
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 GPIO_Init(GPIOA, &GPIO_InitStructure); 

 /* TIM1 DeInit */
 TIM_DeInit(TIM1);

 /* DMA1 Channel5 Config */
 DMA_DeInit(DMA1_Channel5);

 DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)TIM1_DMAR_ADDRESS; 
 DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)SRC_Buffer; 
 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
 DMA_InitStructure.DMA_BufferSize = 3;
 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
 DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
 DMA_InitStructure.DMA_Priority = DMA_Priority_High;
 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
 DMA_Init(DMA1_Channel5, &DMA_InitStructure);
 
 TIM_TimeBaseStructure.TIM_Period = 0xFFFF; 
 TIM_TimeBaseStructure.TIM_Prescaler = (uint16_t) (SystemCoreClock / 24000000) - 1; 
 TIM_TimeBaseStructure.TIM_ClockDivision = 0x0; 
 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; 
 TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);

 /* TIM Configuration in PWM Mode */
 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; 
 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; 
 TIM_OCInitStructure.TIM_Pulse = 0xFFF; 
 TIM_OC1Init(TIM1, &TIM_OCInitStructure); 

 /* TIM1 DMAR Base register and DMA Burst Length Config */
 TIM_DMAConfig(TIM1, TIM_DMABase_CCR1, TIM_DMABurstLength_3Transfers);

 /* TIM1 DMA Update enable */
 TIM_DMACmd(TIM1, TIM_DMA_Update, ENABLE);

 /* TIM1 enable */
 TIM_Cmd(TIM1, ENABLE);
 
 /* TIM1 PWM Outputs Enable */
 TIM_CtrlPWMOutputs(TIM1, ENABLE);

 /* DMA1 Channel5 enable */
 DMA_Cmd(DMA1_Channel5, ENABLE);

 /* Wait until DMA1 Channel5 end of Transfer */
 while (!DMA_GetFlagStatus(DMA1_FLAG_TC5))
 {
 }

 /* Infinite loop */ 
 while(1)
 {
 }
}

 

 

    3 replies

    waclawek.jan
    Super User
    May 22, 2024

    What do you mean by "misaligned"?

    Read out and check/post content of TIM and DMA registers.

    JW

    Associate
    May 22, 2024

    "misaligned" is

    first time

    CCR1=0x1234

    CCR2=0x5678

    CCR3=0xABCD

    but second

    CCR1=0xABCD

    CCR2=0x1234

    CCR3=0x5678

    And then

    CCR1=0x5678

    CCR2=0xABCD

    CCR3=0x1234

     

    waclawek.jan
    Super User
    May 22, 2024

    I don't use SPL.

    What happens, if you use

    TIM_DMAConfig(TIM1, TIM_DMABase_CCR1, TIM_DMABurstLength_2Transfers);

    ?

    JW

    HMoens
    Graduate
    September 18, 2024

    I'm noticing the same issue in my project. It seems to only happen in the debugger mode when I'm live viewing the CCR changes. Maybe your code works as intended when you aren't checking on it. 

    I attached a screen recording to show what I mean. I'm basically changing rapidly between 50% duty cycle and 100%. This should look like a stable 75% on the scope. It also does before I go into the live view. Then when I go to live view it starts messing up

    waclawek.jan
    Super User
    September 18, 2024

    Nice catch!

    Yes, debugging is intrusive - but I did not guess that that might be the case in the original post.

    JW