DMA problem using two timers

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Not applicable
Hello,

I´m using two timers to generate two separate pwms providing the dutycycles via dma. So I have the following init code:

uint32_t i;
for(i=0;i {
dutyCycles0=i;
dutyCycles1=i;
}


DMA_CH_InitStructure0.block_size = DMA_PERIOD_COUNT;
DMA_CH_InitStructure0.src_addr = (uint32_t)&dutyCycles0[0];
DMA_CH_InitStructure0.dst_addr = (uint32_t)&CCU80_CC80->CR2S;
DMA_CH_InitStructure0.src_transfer_width = XMC_DMA_CH_TRANSFER_WIDTH_32;
DMA_CH_InitStructure0.dst_transfer_width = XMC_DMA_CH_TRANSFER_WIDTH_32;
DMA_CH_InitStructure0.src_address_count_mode = XMC_DMA_CH_ADDRESS_COUNT_MODE_INCREMENT;
DMA_CH_InitStructure0.dst_address_count_mode = XMC_DMA_CH_ADDRESS_COUNT_MODE_NO_CHANGE;
DMA_CH_InitStructure0.src_burst_length = XMC_DMA_CH_BURST_LENGTH_1;
DMA_CH_InitStructure0.dst_burst_length = XMC_DMA_CH_BURST_LENGTH_1;
DMA_CH_InitStructure0.transfer_flow = XMC_DMA_CH_TRANSFER_FLOW_M2P_DMA;
DMA_CH_InitStructure0.transfer_type = XMC_DMA_CH_TRANSFER_TYPE_MULTI_BLOCK_SRCADR_RELOAD_DSTADR_RELOAD;
DMA_CH_InitStructure0.src_handshaking = XMC_DMA_CH_SRC_HANDSHAKING_SOFTWARE;
DMA_CH_InitStructure0.dst_handshaking = XMC_DMA_CH_DST_HANDSHAKING_HARDWARE;
DMA_CH_InitStructure0.dst_peripheral_request = DMA0_PERIPHERAL_REQUEST_CCU80_SR0_0;
DMA_CH_InitStructure0.priority = 0;

DMA_CH_InitStructure1.block_size = DMA_PERIOD_COUNT;
DMA_CH_InitStructure1.src_addr = (uint32_t)&shadow_transfer_enableU;
DMA_CH_InitStructure1.dst_addr = (uint32_t)&CCU80->GCSS;
DMA_CH_InitStructure1.src_transfer_width = XMC_DMA_CH_TRANSFER_WIDTH_32;
DMA_CH_InitStructure1.dst_transfer_width = XMC_DMA_CH_TRANSFER_WIDTH_32;
DMA_CH_InitStructure1.src_address_count_mode = XMC_DMA_CH_ADDRESS_COUNT_MODE_NO_CHANGE;
DMA_CH_InitStructure1.dst_address_count_mode = XMC_DMA_CH_ADDRESS_COUNT_MODE_NO_CHANGE;
DMA_CH_InitStructure1.src_burst_length = XMC_DMA_CH_BURST_LENGTH_1;
DMA_CH_InitStructure1.dst_burst_length = XMC_DMA_CH_BURST_LENGTH_1;
DMA_CH_InitStructure1.transfer_flow = XMC_DMA_CH_TRANSFER_FLOW_M2P_DMA;
DMA_CH_InitStructure1.transfer_type = XMC_DMA_CH_TRANSFER_TYPE_MULTI_BLOCK_SRCADR_RELOAD_DSTADR_RELOAD;
DMA_CH_InitStructure1.src_handshaking = XMC_DMA_CH_SRC_HANDSHAKING_SOFTWARE;
DMA_CH_InitStructure1.dst_handshaking = XMC_DMA_CH_DST_HANDSHAKING_HARDWARE;
DMA_CH_InitStructure1.dst_peripheral_request = DMA0_PERIPHERAL_REQUEST_CCU80_SR0_0;
DMA_CH_InitStructure1.priority = 1;

// DMA_CH_InitStructure2.block_size = DMA_PERIOD_COUNT;
// DMA_CH_InitStructure2.src_addr = (uint32_t)&dutyCycles1[0];
// DMA_CH_InitStructure2.dst_addr = (uint32_t)&CCU80_CC81->CR2S;
// DMA_CH_InitStructure2.src_transfer_width = XMC_DMA_CH_TRANSFER_WIDTH_32;
// DMA_CH_InitStructure2.dst_transfer_width = XMC_DMA_CH_TRANSFER_WIDTH_32;
// DMA_CH_InitStructure2.src_address_count_mode = XMC_DMA_CH_ADDRESS_COUNT_MODE_INCREMENT;
// DMA_CH_InitStructure2.dst_address_count_mode = XMC_DMA_CH_ADDRESS_COUNT_MODE_NO_CHANGE;
// DMA_CH_InitStructure2.src_burst_length = XMC_DMA_CH_BURST_LENGTH_1;
// DMA_CH_InitStructure2.dst_burst_length = XMC_DMA_CH_BURST_LENGTH_1;
// DMA_CH_InitStructure2.transfer_flow = XMC_DMA_CH_TRANSFER_FLOW_M2P_DMA;
// DMA_CH_InitStructure2.transfer_type = XMC_DMA_CH_TRANSFER_TYPE_MULTI_BLOCK_SRCADR_RELOAD_DSTADR_RELOAD;
// DMA_CH_InitStructure2.src_handshaking = XMC_DMA_CH_SRC_HANDSHAKING_SOFTWARE;
// DMA_CH_InitStructure2.dst_handshaking = XMC_DMA_CH_DST_HANDSHAKING_HARDWARE;
// DMA_CH_InitStructure2.dst_peripheral_request = DMA0_PERIPHERAL_REQUEST_CCU80_SR0_0;
// DMA_CH_InitStructure2.priority = 0;
//
// DMA_CH_InitStructure3.block_size = DMA_PERIOD_COUNT;
// DMA_CH_InitStructure3.src_addr = (uint32_t)&shadow_transfer_enableV;
// DMA_CH_InitStructure3.dst_addr = (uint32_t)&CCU80->GCSS;
// DMA_CH_InitStructure3.src_transfer_width = XMC_DMA_CH_TRANSFER_WIDTH_32;
// DMA_CH_InitStructure3.dst_transfer_width = XMC_DMA_CH_TRANSFER_WIDTH_32;
// DMA_CH_InitStructure3.src_address_count_mode = XMC_DMA_CH_ADDRESS_COUNT_MODE_NO_CHANGE;
// DMA_CH_InitStructure3.dst_address_count_mode = XMC_DMA_CH_ADDRESS_COUNT_MODE_NO_CHANGE;
// DMA_CH_InitStructure3.src_burst_length = XMC_DMA_CH_BURST_LENGTH_1;
// DMA_CH_InitStructure3.dst_burst_length = XMC_DMA_CH_BURST_LENGTH_1;
// DMA_CH_InitStructure3.transfer_flow = XMC_DMA_CH_TRANSFER_FLOW_M2P_DMA;
// DMA_CH_InitStructure3.transfer_type = XMC_DMA_CH_TRANSFER_TYPE_MULTI_BLOCK_SRCADR_RELOAD_DSTADR_RELOAD;
// DMA_CH_InitStructure3.src_handshaking = XMC_DMA_CH_SRC_HANDSHAKING_SOFTWARE;
// DMA_CH_InitStructure3.dst_handshaking = XMC_DMA_CH_DST_HANDSHAKING_HARDWARE;
// DMA_CH_InitStructure3.dst_peripheral_request = DMA0_PERIPHERAL_REQUEST_CCU80_SR0_0;
// DMA_CH_InitStructure3.priority = 1;

shadow_transfer_enableU = XMC_CCU8_SHADOW_TRANSFER_SLICE_0;
// shadow_transfer_enableV = XMC_CCU8_SHADOW_TRANSFER_SLICE_1;

XMC_CCU8_SLICE_SetTimerCompareMatch(CCU80_CC80, XMC_CCU8_SLICE_COMPARE_CHANNEL_1, 0);
// XMC_CCU8_SLICE_SetTimerCompareMatch(CCU80_CC81, XMC_CCU8_SLICE_COMPARE_CHANNEL_1, 0);

XMC_DMA_Init(XMC_DMA0);
XMC_DMA_CH_Init(XMC_DMA0, 0, &DMA_CH_InitStructure0);
XMC_DMA_CH_Init(XMC_DMA0, 1, &DMA_CH_InitStructure1);
// XMC_DMA_CH_Init(XMC_DMA0, 2, &DMA_CH_InitStructure2);
// XMC_DMA_CH_Init(XMC_DMA0, 3, &DMA_CH_InitStructure3);

XMC_DMA_CH_Enable(XMC_DMA0, 0);
XMC_DMA_CH_Enable(XMC_DMA0, 1);
// XMC_DMA_CH_Enable(XMC_DMA0, 2);
// XMC_DMA_CH_Enable(XMC_DMA0, 3);

XMC_CCU8_SLICE_StartTimer(CCU80_CC80);
// XMC_CCU8_SLICE_StartTimer(CCU80_CC81);

The rest of the timer configuration is done in another module. This example (only CCU80_CC80) works and a pwm is generated based on a predefined array of duty cycle values. But when I want to generate two pwms (CCU80_CC80
and CCU80_CC81) I cannot make it work correctly. It seems that only the pwm channel works via dma which was configured first.

Have you got an idea how to get it work so that I can expand the dma functionality to 6 independent pwms?

Kind regards!
0 Likes
3 Replies
jferreira
Employee
Employee
10 sign-ins 5 sign-ins First like received
Hi,

I guess the problem is that the DMA channel 1 and DMA channel3 are competing trying to set the shadow transfer enable of the two PWMs.
Instead just use one DMA channel and set the shadow_transfer_enable to enable shadow transfer on both.
For this to work you should use the period match event to trigger the transfer instead of the compare match, assuming both PWMs has the same period.

Regards,
Jesus
0 Likes
Not applicable
Hi,

thank you for the tip with the shadow register transfer for all channels, but I think that´s not the problem. I found out that in my configuration the dma transfer for a timer register (CR2S) and the shadow register is only possible using channel 0 and 1
of dma0. I tested these two channels for the combinations (CCU80_CC80->CR2S and CCU80->GCSS) , (CCU80_CC81->CR2S and CCU80->GCSS) and (CCU80_CC82->CR2S and CCU80->GCSS) and it works. In every case I get one pwm via dma.
Why am I not able to get three pwms at the same time with the channel 0 (CCU80->GCSS), 1 (CCU80_CC80->CR2S), 2 (CCU80_CC81->CR2S), 3 (CCU80_CC82->CR2S). I changed the dma configuration of the channel 2 and 3 from M2P
to M2M transfering one array content to another to test whether the dma is working and it succeed. But in case of four M2P transfers on channel 2 and 3 only the last array value can be observed on the corresponding CR2S register.
It looks like these channels only do one dma action while the channel 0 and 1 are triggered continously.
I don´t know what the problem is, when I want to use dma transfer for all 3 pwms. Here is my simply code.

static XMC_DMA_CH_CONFIG_t DMA_CH_InitStructure0;
static XMC_DMA_CH_CONFIG_t DMA_CH_InitStructure1;
static XMC_DMA_CH_CONFIG_t DMA_CH_InitStructure2;
static XMC_DMA_CH_CONFIG_t DMA_CH_InitStructure3;

#define DMA_PERIOD_COUNT 1000
#define pwmShadowDmaChannel 0

#define pwmUhsDmaChannel 1
#define pwmVhsDmaChannel 2
#define pwmWhsDmaChannel 3

#define DMA_U_REG (&(CCU80_CC82->CR2S))
#define DMA_V_REG (&(CCU80_CC81->CR2S))
#define DMA_W_REG (&(CCU80_CC80->CR2S))
/***************************************************************************************
* Declaration of variables (scope: module-local)
***************************************************************************************/
static uint32_t dutyCycles_U_HS[DMA_PERIOD_COUNT];
static uint32_t dutyCycles_V_HS[DMA_PERIOD_COUNT];
static uint32_t dutyCycles_W_HS[DMA_PERIOD_COUNT];
static uint32_t shadow_transfer_enable;

void dma_InitPWM_U_HS(void);
void dma_InitPWM_V_HS(void);
void dma_InitPWM_W_HS(void);
void dma_InitPWM_TIMER(void);
void dma_InitShadowTransfer(void);
/***************************************************************************************
* Implementation exported funcations (scope: global)
***************************************************************************************/
void dma_Init(void){
uint32_t i;
for(i=0;i {
dutyCycles_U_HS=i;
dutyCycles_W_HS=i;
dutyCycles_V_HS=i;
}
shadow_transfer_enable = XMC_CCU8_SHADOW_TRANSFER_SLICE_0 | XMC_CCU8_SHADOW_TRANSFER_SLICE_1 | XMC_CCU8_SHADOW_TRANSFER_SLICE_2;
//############
XMC_DMA_Init(XMC_DMA0);
//############
dma_InitShadowTransfer();
//############
dma_InitPWM_U_HS();
dma_InitPWM_V_HS();
dma_InitPWM_W_HS();
//############
XMC_DMA_CH_Enable(XMC_DMA0, pwmShadowDmaChannel);
XMC_DMA_CH_Enable(XMC_DMA0, pwmUhsDmaChannel);
XMC_DMA_CH_Enable(XMC_DMA0, pwmVhsDmaChannel);
XMC_DMA_CH_Enable(XMC_DMA0, pwmWhsDmaChannel);
//############
dma_InitPWM_TIMER();
}

void dma_InitShadowTransfer(void)
{
DMA_CH_InitStructure0.block_size = DMA_PERIOD_COUNT;
DMA_CH_InitStructure0.src_addr = (uint32_t)&shadow_transfer_enable;
DMA_CH_InitStructure0.dst_addr = (uint32_t)&CCU80->GCSS;
DMA_CH_InitStructure0.src_transfer_width = XMC_DMA_CH_TRANSFER_WIDTH_32;
DMA_CH_InitStructure0.dst_transfer_width = XMC_DMA_CH_TRANSFER_WIDTH_32;
DMA_CH_InitStructure0.src_address_count_mode = XMC_DMA_CH_ADDRESS_COUNT_MODE_NO_CHANGE;
DMA_CH_InitStructure0.dst_address_count_mode = XMC_DMA_CH_ADDRESS_COUNT_MODE_NO_CHANGE;
DMA_CH_InitStructure0.src_burst_length = XMC_DMA_CH_BURST_LENGTH_1;
DMA_CH_InitStructure0.dst_burst_length = XMC_DMA_CH_BURST_LENGTH_1;
DMA_CH_InitStructure0.transfer_flow = XMC_DMA_CH_TRANSFER_FLOW_M2P_DMA;
DMA_CH_InitStructure0.transfer_type = XMC_DMA_CH_TRANSFER_TYPE_MULTI_BLOCK_SRCADR_RELOAD_DSTADR_RELOAD;
DMA_CH_InitStructure0.src_handshaking = XMC_DMA_CH_SRC_HANDSHAKING_SOFTWARE;
DMA_CH_InitStructure0.dst_handshaking = XMC_DMA_CH_DST_HANDSHAKING_HARDWARE;
DMA_CH_InitStructure0.dst_peripheral_request = DMA0_PERIPHERAL_REQUEST_CCU80_SR0_0;
DMA_CH_InitStructure0.priority = XMC_DMA_CH_PRIORITY_0;
XMC_DMA_CH_Init(XMC_DMA0, pwmShadowDmaChannel, &DMA_CH_InitStructure0);
}

void dma_InitPWM_U_HS(void)
{
DMA_CH_InitStructure1.block_size = DMA_PERIOD_COUNT;
DMA_CH_InitStructure1.src_addr = (uint32_t)&dutyCycles_U_HS[0];
DMA_CH_InitStructure1.dst_addr = (uint32_t)DMA_U_REG;
DMA_CH_InitStructure1.src_transfer_width = XMC_DMA_CH_TRANSFER_WIDTH_32;
DMA_CH_InitStructure1.dst_transfer_width = XMC_DMA_CH_TRANSFER_WIDTH_32;
DMA_CH_InitStructure1.src_address_count_mode = XMC_DMA_CH_ADDRESS_COUNT_MODE_INCREMENT;
DMA_CH_InitStructure1.dst_address_count_mode = XMC_DMA_CH_ADDRESS_COUNT_MODE_NO_CHANGE;
DMA_CH_InitStructure1.src_burst_length = XMC_DMA_CH_BURST_LENGTH_1;
DMA_CH_InitStructure1.dst_burst_length = XMC_DMA_CH_BURST_LENGTH_1;
DMA_CH_InitStructure1.transfer_flow = XMC_DMA_CH_TRANSFER_FLOW_M2P_DMA;
DMA_CH_InitStructure1.transfer_type = XMC_DMA_CH_TRANSFER_TYPE_MULTI_BLOCK_SRCADR_RELOAD_DSTADR_RELOAD;
DMA_CH_InitStructure1.src_handshaking = XMC_DMA_CH_SRC_HANDSHAKING_SOFTWARE;
DMA_CH_InitStructure1.dst_handshaking = XMC_DMA_CH_DST_HANDSHAKING_HARDWARE;
DMA_CH_InitStructure1.dst_peripheral_request = DMA0_PERIPHERAL_REQUEST_CCU80_SR0_0;
DMA_CH_InitStructure1.priority = XMC_DMA_CH_PRIORITY_7;
XMC_DMA_CH_Init(XMC_DMA0, pwmUhsDmaChannel, &DMA_CH_InitStructure1);
}

void dma_InitPWM_V_HS(void)
{
DMA_CH_InitStructure2.block_size = DMA_PERIOD_COUNT;
DMA_CH_InitStructure2.src_addr = (uint32_t)&dutyCycles_V_HS[0];
DMA_CH_InitStructure2.dst_addr = (uint32_t)DMA_V_REG;
DMA_CH_InitStructure2.src_transfer_width = XMC_DMA_CH_TRANSFER_WIDTH_32;
DMA_CH_InitStructure2.dst_transfer_width = XMC_DMA_CH_TRANSFER_WIDTH_32;
DMA_CH_InitStructure2.src_address_count_mode = XMC_DMA_CH_ADDRESS_COUNT_MODE_INCREMENT;
DMA_CH_InitStructure2.dst_address_count_mode = XMC_DMA_CH_ADDRESS_COUNT_MODE_NO_CHANGE;
DMA_CH_InitStructure2.src_burst_length = XMC_DMA_CH_BURST_LENGTH_1;
DMA_CH_InitStructure2.dst_burst_length = XMC_DMA_CH_BURST_LENGTH_1;
DMA_CH_InitStructure2.transfer_flow = XMC_DMA_CH_TRANSFER_FLOW_M2P_DMA;
DMA_CH_InitStructure2.transfer_type = XMC_DMA_CH_TRANSFER_TYPE_MULTI_BLOCK_SRCADR_RELOAD_DSTADR_RELOAD;
DMA_CH_InitStructure2.src_handshaking = XMC_DMA_CH_SRC_HANDSHAKING_SOFTWARE;
DMA_CH_InitStructure2.dst_handshaking = XMC_DMA_CH_DST_HANDSHAKING_HARDWARE;
DMA_CH_InitStructure2.dst_peripheral_request = DMA0_PERIPHERAL_REQUEST_CCU80_SR0_0;
DMA_CH_InitStructure2.priority = XMC_DMA_CH_PRIORITY_7;
XMC_DMA_CH_Init(XMC_DMA0, pwmVhsDmaChannel, &DMA_CH_InitStructure2);
}

void dma_InitPWM_W_HS(void)
{
DMA_CH_InitStructure3.block_size = DMA_PERIOD_COUNT;
DMA_CH_InitStructure3.src_addr = (uint32_t)&dutyCycles_W_HS[0];
DMA_CH_InitStructure3.dst_addr = (uint32_t)DMA_W_REG;
DMA_CH_InitStructure3.src_transfer_width = XMC_DMA_CH_TRANSFER_WIDTH_32;
DMA_CH_InitStructure3.dst_transfer_width = XMC_DMA_CH_TRANSFER_WIDTH_32;
DMA_CH_InitStructure3.src_address_count_mode = XMC_DMA_CH_ADDRESS_COUNT_MODE_INCREMENT;
DMA_CH_InitStructure3.dst_address_count_mode = XMC_DMA_CH_ADDRESS_COUNT_MODE_NO_CHANGE;
DMA_CH_InitStructure3.src_burst_length = XMC_DMA_CH_BURST_LENGTH_1;
DMA_CH_InitStructure3.dst_burst_length = XMC_DMA_CH_BURST_LENGTH_1;
DMA_CH_InitStructure3.transfer_flow = XMC_DMA_CH_TRANSFER_FLOW_M2P_DMA;
DMA_CH_InitStructure3.transfer_type = XMC_DMA_CH_TRANSFER_TYPE_MULTI_BLOCK_SRCADR_RELOAD_DSTADR_RELOAD;
DMA_CH_InitStructure3.src_handshaking = XMC_DMA_CH_SRC_HANDSHAKING_SOFTWARE;
DMA_CH_InitStructure3.dst_handshaking = XMC_DMA_CH_DST_HANDSHAKING_HARDWARE;
DMA_CH_InitStructure3.dst_peripheral_request = DMA0_PERIPHERAL_REQUEST_CCU80_SR0_0;
DMA_CH_InitStructure3.priority =XMC_DMA_CH_PRIORITY_7;
XMC_DMA_CH_Init(XMC_DMA0, pwmWhsDmaChannel, &DMA_CH_InitStructure3);
}

void dma_InitPWM_TIMER(void)
{
XMC_CCU8_SLICE_EnableEvent(CCU80_CC80, XMC_CCU8_SLICE_IRQ_ID_PERIOD_MATCH);
XMC_CCU8_SLICE_SetInterruptNode(CCU80_CC80, XMC_CCU8_SLICE_IRQ_ID_PERIOD_MATCH, XMC_CCU8_SLICE_SR_ID_0);

XMC_CCU8_SLICE_SetTimerCompareMatch(CCU80_CC80, XMC_CCU8_SLICE_COMPARE_CHANNEL_1, 0);
XMC_CCU8_SLICE_SetTimerCompareMatch(CCU80_CC81, XMC_CCU8_SLICE_COMPARE_CHANNEL_1, 0);
XMC_CCU8_SLICE_SetTimerCompareMatch(CCU80_CC82, XMC_CCU8_SLICE_COMPARE_CHANNEL_1, 0);
}

Can you give an advice? I`m despairing...
Kind regards
Sandro
0 Likes
Not applicable
HI Jesus,

can you please give me some further support on that topic?

Kind regards
Sandro
0 Likes