2014-09-02 10:15 PM
Hello,
i was thinking about, if it would be possible to write to one peripherie register (for example the CCR1 of a Timer) with two different DMA-Channels. For sure not at the same time, but at different points in time. I have tried it a while on my own, but now i am not sure if it is possible at all. Thanks for helping in advance. Best regards Michael Mayer #dma2014-09-03 01:33 AM
I would think it's viable provided you use the correct combination of unit/channel/stream and triggers.
2014-09-03 10:47 AM
Hello,
Thanks for your answer! It works if I only write one variable to the CCR1 register. But if I write two variables to CCR1 and to CCR2 it goes wrong (increasing DMA_BufferSize to 2). CCR1 is written one time, afterwards only CCR2 is updated. Can you find the failure in my DMA-inits?
void DMA_Timer
1
_up_ini(void)
{
DMA_InitTypeDef DMA_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA
1
, ENABLE);
DMA_InitStructure.DMA_BufferSize =
2
;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_M
2
M = DMA_M
2
M_Disable;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint
32
_t)&(pwm_aktuell.up);
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint
32
_t)&(TIM
1
->CCR
1
);
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_Init(DMA
1
_Channel
6
, &DMA_InitStructure);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = DMA
1
_Channel
6
_IRQn ;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =
1
;
NVIC_InitStructure.NVIC_IRQChannelSubPriority =
1
;
NVIC_Init(&NVIC_InitStructure);
DMA_ITConfig(DMA
1
_Channel
6
, DMA_IT_TC, ENABLE);
DMA_Cmd(DMA
1
_Channel
6
, ENABLE);
}
void DMA_Timer
1
_down_ini(void)
{
DMA_InitTypeDef DMA_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA
1
, ENABLE);
DMA_InitStructure.DMA_BufferSize =
2
;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_M
2
M = DMA_M
2
M_Disable;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint
32
_t)&(pwm_aktuell.down);
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint
32
_t)&(TIM
1
->CCR
1
);
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_Init(DMA
1
_Channel
2
, &DMA_InitStructure);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = DMA
1
_Channel
2
_IRQn ;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =
1
;
NVIC_InitStructure.NVIC_IRQChannelSubPriority =
1
;
NVIC_Init(&NVIC_InitStructure);
DMA_ITConfig(DMA
1
_Channel
2
, DMA_IT_TC, ENABLE);
DMA_Cmd(DMA
1
_Channel
2
, ENABLE);
}
Best regards Michael
2014-09-03 11:53 AM
I'd expect the address to toggle at each trigger event.
2014-09-04 11:40 AM
hello,
unfortunately I do not understand exactly what yout mean. Could you explain it to me again?
Regards Michael
2014-09-04 12:12 PM
The DMA unit does not block-transfer at each trigger event, it just does one transfer. You have configured two transfers and circular. It's going to therefore ping-pong between two addresses alternately.
2014-09-05 12:22 AM
The general-purpose and the advanced timers have a DMA burst feature, controlled by the TIMx_DCR register. Besides the brief description in RM at the related registers' chapter, it is mentioned also in AN4507.
Never tried personally, though. JW