[SOLVED] 3 channel PWM generator using timer-triggered DMA

ted
Tue Jul 03, 2018 12:10 am
Hi
To learn the timers I am trying to add to 2 channel generator the third one, but I have nothing on pin PB1.
What I am doing wrong ?

#define SAMPLES 100
#include <libmaple/dma.h>
dma_tube_config dma_cfg, dma_cfg2, dma_cfg3 ;

int flag1 = 0;
int flag2 = 0;
int flag3 = 0;

int out1 = PB7;
int out2 = PA8;
int out3 = PB1;
//int out3 = PA7;

int val1[SAMPLES];
int val2[SAMPLES];
int val3[SAMPLES];

int16 shift = 0;

int amp = 35;
int cnt = 0;
int time_track = 0;
float stp = 6.2831 / SAMPLES;
//120 deg = stp/3
int ret = 17;

timer_dev *dev1 = PIN_MAP[out1].timer_device;
timer_dev *dev2 = PIN_MAP[out2].timer_device;
timer_dev *dev3 = PIN_MAP[out3].timer_device;
uint8 cc_channel1 = PIN_MAP[out1].timer_channel;
uint8 cc_channel2 = PIN_MAP[out2].timer_channel;
uint8 cc_channel4 = PIN_MAP[out3].timer_channel;

void fun()
{
flag1++;
}

void fun2()
{
flag2++;
}

void fun3()
{
flag3++;
}
//////////////////////////////////////////////////////////
void timer_conf()
{

timer_dma_set_base_addr(dev1, TIMER_DMA_BASE_CCR2);
timer_dma_set_burst_len(dev1, 1);
timer_dma_enable_req(dev1, cc_channel1);
timer_set_reload(dev1, 102);
timer_set_prescaler(dev1, 0);

timer_dma_set_base_addr(dev2, TIMER_DMA_BASE_CCR1);
timer_dma_set_burst_len(dev2, 1);
timer_dma_enable_req(dev2, cc_channel2);
timer_set_reload(dev2, 102);
timer_set_prescaler(dev2, 0);
// 3 channel
///////////////////////////////////////////////////////////////////
timer_dma_set_base_addr(dev3, TIMER_DMA_BASE_CCR1);
/////////////////////////////////////////////////////////////////
timer_dma_set_burst_len(dev3, 1);
timer_dma_enable_req(dev3, cc_channel4);
timer_set_reload(dev3, 102);
timer_set_prescaler(dev3, 0);

}

void dma_conf()
{
dma_init(DMA1);
/* T4C2 DMA C4 */
dma_cfg.tube_dst = &(dev1->regs.gen->DMAR);
dma_cfg.tube_dst_size = DMA_SIZE_32BITS;
dma_cfg.tube_src = val1;
dma_cfg.tube_src_size = DMA_SIZE_32BITS;

dma_cfg.tube_nr_xfers = SAMPLES;
dma_cfg.tube_flags = DMA_CFG_SRC_INC | DMA_CFG_CIRC | DMA_CFG_CMPLT_IE;

dma_cfg.tube_req_src = DMA_REQ_SRC_TIM4_CH2;
dma_cfg.target_data = 0;

ret = dma_tube_cfg(DMA1, DMA_CH4, &dma_cfg);

/* T1C1 DMA C2 */
dma_cfg.tube_dst = &(dev2->regs.gen->DMAR);
dma_cfg.tube_dst_size = DMA_SIZE_32BITS;
dma_cfg.tube_src = val2;
dma_cfg.tube_src_size = DMA_SIZE_32BITS;

dma_cfg.tube_nr_xfers = SAMPLES;
dma_cfg.tube_flags = DMA_CFG_SRC_INC | DMA_CFG_CIRC | DMA_CFG_CMPLT_IE;
dma_cfg.tube_req_src = DMA_REQ_SRC_TIM1_CH1;
dma_cfg.target_data = 0;

ret = dma_tube_cfg(DMA1, DMA_CH2, &dma_cfg);

/////////////////////////////////////////

/* T3C3 DMA C3 */

dma_cfg.tube_dst = &(dev3->regs.gen->DMAR);
dma_cfg.tube_dst_size = DMA_SIZE_32BITS;
dma_cfg.tube_src = val3;
dma_cfg.tube_src_size = DMA_SIZE_32BITS;

dma_cfg.tube_nr_xfers = SAMPLES;
dma_cfg.tube_flags = DMA_CFG_SRC_INC | DMA_CFG_CIRC | DMA_CFG_CMPLT_IE;
dma_cfg.tube_req_src = DMA_REQ_SRC_TIM1_CH2;
dma_cfg.target_data = 0;
////////////////////////////////////////////

}

void dma_start()
{
dma_attach_interrupt(DMA1, DMA_CH4, fun);

dma_enable(DMA1, DMA_CH4);
timer_resume(dev1);

dma_attach_interrupt(DMA1, DMA_CH2, fun2);

dma_enable(DMA1, DMA_CH2);
timer_resume(dev2);

//////////////////////////////////////////////
dma_attach_interrupt(DMA1, DMA_CH4, fun3);

dma_enable(DMA1, DMA_CH4);
timer_resume(dev3);
///////////////////////////////////////////

}

void init_wave()
{
int i;
for (i = 0; i < SAMPLES; i++)
{
val1[i] = 50 + amp * sin(stp * i);
val2[i] = 50 + amp * cos(stp * i);
val3[i] = 50 + amp * sin(stp * i);

}
}

void get_wave(int16 shift)
{
int i;
for (i = 0; i < SAMPLES; i++)
{
val2[i] = 50 + amp * sin( stp * i + shift * 0.1 * 6.2831 / 360);
}
}
*/
void setup() {
int i;
pinMode(out1, PWM);
pinMode(out2, PWM);
pinMode(out3, PWM);

Serial.begin(9600);

timer_conf();
dma_conf();
dma_start();

init_wave();

// get_wave(shift);

}

void loop() {

}


stevestrong
Tue Jul 03, 2018 7:10 am
Which board?
Which core?
Which IDE? Screenshot?
Which upload method?

ted
Tue Jul 03, 2018 9:29 am
ARM Cortex M3 STM32F103, Blue Pill.

stevestrong
Tue Jul 03, 2018 9:45 am
You set wrong base address for DMA and DMA req src is also wrong for PB1.
PB1 is T3C4, DMA_C3. Check you code.

ted
Tue Jul 03, 2018 11:07 am
I fixed the first part, the second I do not have certainty.

#define SAMPLES 100
#include <libmaple/dma.h>
dma_tube_config dma_cfg, dma_cfg2, dma_cfg3 ;

int flag1 = 0;
int flag2 = 0;
int flag3 = 0;

int out1 = PB7;
int out2 = PA8;
int out3 = PB1;
//int out3 = PA7;

int val1[SAMPLES];
int val2[SAMPLES];
int val3[SAMPLES];

int16 shift = 0;

int amp = 35;
int cnt = 0;
int time_track = 0;
float stp = 6.2831 / SAMPLES;
//120 deg = stp/3
int ret = 17;

timer_dev *dev1 = PIN_MAP[out1].timer_device;
timer_dev *dev2 = PIN_MAP[out2].timer_device;
timer_dev *dev3 = PIN_MAP[out3].timer_device;
uint8 cc_channel1 = PIN_MAP[out1].timer_channel;
uint8 cc_channel2 = PIN_MAP[out2].timer_channel;
uint8 cc_channel4 = PIN_MAP[out3].timer_channel;

void fun()
{
flag1++;
}

void fun2()
{
flag2++;
}

void fun3()
{
flag3++;
}
//////////////////////////////////////////////////////////
void timer_conf()
{

timer_dma_set_base_addr(dev1, TIMER_DMA_BASE_CCR2);
timer_dma_set_burst_len(dev1, 1);
timer_dma_enable_req(dev1, cc_channel1);
timer_set_reload(dev1, 102);
timer_set_prescaler(dev1, 0);

timer_dma_set_base_addr(dev2, TIMER_DMA_BASE_CCR1);
timer_dma_set_burst_len(dev2, 1);
timer_dma_enable_req(dev2, cc_channel2);
timer_set_reload(dev2, 102);
timer_set_prescaler(dev2, 0);
// 3 channel
///////////////////////////////////////////////////////////////////
timer_dma_set_base_addr(dev3, TIMER_DMA_BASE_CCR1);
/////////////////////////////////////////////////////////////////
timer_dma_set_burst_len(dev3, 1);
timer_dma_enable_req(dev3, cc_channel4);
timer_set_reload(dev3, 102);
timer_set_prescaler(dev3, 0);

}

void dma_conf()
{
dma_init(DMA1);
/* T4C2 DMA C4 */
dma_cfg.tube_dst = &(dev1->regs.gen->DMAR);
dma_cfg.tube_dst_size = DMA_SIZE_32BITS;
dma_cfg.tube_src = val1;
dma_cfg.tube_src_size = DMA_SIZE_32BITS;

dma_cfg.tube_nr_xfers = SAMPLES;
dma_cfg.tube_flags = DMA_CFG_SRC_INC | DMA_CFG_CIRC | DMA_CFG_CMPLT_IE;

dma_cfg.tube_req_src = DMA_REQ_SRC_TIM4_CH2;
dma_cfg.target_data = 0;

ret = dma_tube_cfg(DMA1, DMA_CH4, &dma_cfg);

/* T1C1 DMA C2 */
dma_cfg.tube_dst = &(dev2->regs.gen->DMAR);
dma_cfg.tube_dst_size = DMA_SIZE_32BITS;
dma_cfg.tube_src = val2;
dma_cfg.tube_src_size = DMA_SIZE_32BITS;

dma_cfg.tube_nr_xfers = SAMPLES;
dma_cfg.tube_flags = DMA_CFG_SRC_INC | DMA_CFG_CIRC | DMA_CFG_CMPLT_IE;
dma_cfg.tube_req_src = DMA_REQ_SRC_TIM1_CH1;
dma_cfg.target_data = 0;

ret = dma_tube_cfg(DMA1, DMA_CH2, &dma_cfg);

/////////////////////////////////////////

/* T3C3 DMA C3 */

dma_cfg.tube_dst = &(dev3->regs.gen->DMAR);
dma_cfg.tube_dst_size = DMA_SIZE_32BITS;
dma_cfg.tube_src = val3;
dma_cfg.tube_src_size = DMA_SIZE_32BITS;

dma_cfg.tube_nr_xfers = SAMPLES;
dma_cfg.tube_flags = DMA_CFG_SRC_INC | DMA_CFG_CIRC | DMA_CFG_CMPLT_IE;
// dma_cfg.tube_req_src = DMA_REQ_SRC_TIM1_CH2;
dma_cfg.tube_req_src = DMA_REQ_SRC_TIM1_CH4;

dma_cfg.target_data = 0;
////////////////////////////////////////////

}

void dma_start()
{
dma_attach_interrupt(DMA1, DMA_CH4, fun);

dma_enable(DMA1, DMA_CH4);
timer_resume(dev1);

dma_attach_interrupt(DMA1, DMA_CH2, fun2);

dma_enable(DMA1, DMA_CH2);
timer_resume(dev2);

//////////////////////////////////////////////
dma_attach_interrupt(DMA1, DMA_CH4, fun3);

dma_enable(DMA1, DMA_CH4);
timer_resume(dev3);
///////////////////////////////////////////

}

void init_wave()
{
int i;
for (i = 0; i < SAMPLES; i++)
{
val1[i] = 50 + amp * sin(stp * i);
val2[i] = 50 + amp * cos(stp * i);
val3[i] = 50 + amp * sin(stp * i);

}
}

void get_wave(int16 shift)

{
int i;
for (i = 0; i < SAMPLES; i++)
{
val2[i] = 50 + amp * sin( stp * i + shift * 0.1 * 6.2831 / 360);
}
}

void setup() {
int i;
pinMode(out1, PWM);
pinMode(out2, PWM);
pinMode(out3, PWM);

Serial.begin(9600);

timer_conf();
dma_conf();
dma_start();

init_wave();

// get_wave(shift);

}

void loop() {

}


stevestrong
Tue Jul 03, 2018 12:24 pm
timer_dma_set_base_addr(dev3, TIMER_DMA_BASE_CCR4); // T3 channel 4

ted
Tue Jul 03, 2018 12:52 pm
Thanks
I made those changes, but must be something else, no signal on PB1

#define SAMPLES 100
#include <libmaple/dma.h>
dma_tube_config dma_cfg, dma_cfg2, dma_cfg3 ;

int flag1 = 0;
int flag2 = 0;
int flag3 = 0;

int out1 = PB7;
int out2 = PA8;
int out3 = PB1;
//int out3 = PA7;

int val1[SAMPLES];
int val2[SAMPLES];
int val3[SAMPLES];

int16 shift = 0;

int amp = 35;
int cnt = 0;
int time_track = 0;
float stp = 6.2831 / SAMPLES;
//120 deg = stp/3
int ret = 17;

timer_dev *dev1 = PIN_MAP[out1].timer_device;
timer_dev *dev2 = PIN_MAP[out2].timer_device;
timer_dev *dev3 = PIN_MAP[out3].timer_device;
uint8 cc_channel1 = PIN_MAP[out1].timer_channel;
uint8 cc_channel2 = PIN_MAP[out2].timer_channel;
uint8 cc_channel4 = PIN_MAP[out3].timer_channel;

void fun()
{
flag1++;
}

void fun2()
{
flag2++;
}

void fun3()
{
flag3++;
}
//////////////////////////////////////////////////////////
void timer_conf()
{

timer_dma_set_base_addr(dev1, TIMER_DMA_BASE_CCR2);
timer_dma_set_burst_len(dev1, 1);
timer_dma_enable_req(dev1, cc_channel1);
timer_set_reload(dev1, 102);
timer_set_prescaler(dev1, 0);

timer_dma_set_base_addr(dev2, TIMER_DMA_BASE_CCR1);
timer_dma_set_burst_len(dev2, 1);
timer_dma_enable_req(dev2, cc_channel2);
timer_set_reload(dev2, 102);
timer_set_prescaler(dev2, 0);
// 3 channel
///////////////////////////////////////////////////////////////////
//timer_dma_set_base_addr(dev3, TIMER_DMA_BASE_CCR1);
//timer_dma_set_base_addr(dev3, TIMER_DMA_BASE_CCR3);
timer_dma_set_base_addr(dev3, TIMER_DMA_BASE_CCR4); // T3 channel 4
/////////////////////////////////////////////////////////////////
timer_dma_set_burst_len(dev3, 1);
timer_dma_enable_req(dev3, cc_channel4);
timer_set_reload(dev3, 102);
timer_set_prescaler(dev3, 0);

}

void dma_conf()
{
dma_init(DMA1);
/* T4C2 DMA C4 */
dma_cfg.tube_dst = &(dev1->regs.gen->DMAR);
dma_cfg.tube_dst_size = DMA_SIZE_32BITS;
dma_cfg.tube_src = val1;
dma_cfg.tube_src_size = DMA_SIZE_32BITS;

dma_cfg.tube_nr_xfers = SAMPLES;
dma_cfg.tube_flags = DMA_CFG_SRC_INC | DMA_CFG_CIRC | DMA_CFG_CMPLT_IE;

dma_cfg.tube_req_src = DMA_REQ_SRC_TIM4_CH2;
dma_cfg.target_data = 0;

ret = dma_tube_cfg(DMA1, DMA_CH4, &dma_cfg);

/* T1C1 DMA C2 */
dma_cfg.tube_dst = &(dev2->regs.gen->DMAR);
dma_cfg.tube_dst_size = DMA_SIZE_32BITS;
dma_cfg.tube_src = val2;
dma_cfg.tube_src_size = DMA_SIZE_32BITS;

dma_cfg.tube_nr_xfers = SAMPLES;
dma_cfg.tube_flags = DMA_CFG_SRC_INC | DMA_CFG_CIRC | DMA_CFG_CMPLT_IE;
dma_cfg.tube_req_src = DMA_REQ_SRC_TIM1_CH1;
dma_cfg.target_data = 0;

ret = dma_tube_cfg(DMA1, DMA_CH2, &dma_cfg);

/////////////////////////////////////////

/* T3C3 DMA C3 */

dma_cfg.tube_dst = &(dev3->regs.gen->DMAR);
dma_cfg.tube_dst_size = DMA_SIZE_32BITS;
dma_cfg.tube_src = val3;
dma_cfg.tube_src_size = DMA_SIZE_32BITS;

dma_cfg.tube_nr_xfers = SAMPLES;
dma_cfg.tube_flags = DMA_CFG_SRC_INC | DMA_CFG_CIRC | DMA_CFG_CMPLT_IE;
// dma_cfg.tube_req_src = DMA_REQ_SRC_TIM1_CH4;
dma_cfg.tube_req_src = DMA_REQ_SRC_TIM3_CH4; // T3 channel 4
dma_cfg.target_data = 0;
////////////////////////////////////////////

}

void dma_start()
{
dma_attach_interrupt(DMA1, DMA_CH4, fun);

dma_enable(DMA1, DMA_CH4);
timer_resume(dev1);

dma_attach_interrupt(DMA1, DMA_CH2, fun2);

dma_enable(DMA1, DMA_CH2);
timer_resume(dev2);

//////////////////////////////////////////////
dma_attach_interrupt(DMA1, DMA_CH4, fun3);

dma_enable(DMA1, DMA_CH4);
timer_resume(dev3);
///////////////////////////////////////////

}

void init_wave()
{
int i;
for (i = 0; i < SAMPLES; i++)
{
val1[i] = 50 + amp * sin(stp * i);
val2[i] = 50 + amp * cos(stp * i);
val3[i] = 50 + amp * sin(stp * i);

}
}

void setup() {
int i;
pinMode(out1, PWM);
pinMode(out2, PWM);
pinMode(out3, PWM);

Serial.begin(9600);

timer_conf();
dma_conf();
dma_start();

init_wave();

// get_wave(shift);

}

void loop() {

}


ted
Tue Jul 03, 2018 1:01 pm
I think something is not correct here.
fun and fun 3 are identical

void dma_start()
{
dma_attach_interrupt(DMA1, DMA_CH4, fun);

dma_enable(DMA1, DMA_CH4);
timer_resume(dev1);

dma_attach_interrupt(DMA1, DMA_CH2, fun2);

dma_enable(DMA1, DMA_CH2);
timer_resume(dev2);

//////////////////////////////////////////////
dma_attach_interrupt(DMA1, DMA_CH4, fun3);

dma_enable(DMA1, DMA_CH4);
timer_resume(dev3);
///////////////////////////////////////////


ted
Tue Jul 03, 2018 1:22 pm
To avoid confusion, I changed Timer 3 to channel 3 = PB0, didn’t help.

#define SAMPLES 100
#include <libmaple/dma.h>
dma_tube_config dma_cfg, dma_cfg2, dma_cfg3 ;

int flag1 = 0;
int flag2 = 0;
int flag3 = 0;

int out1 = PB7;
int out2 = PA8;
//int out3 = PB1;
//int out3 = PA7;
int out3 = PB0;

int val1[SAMPLES];
int val2[SAMPLES];
int val3[SAMPLES];

int16 shift = 0;

int amp = 35;
int cnt = 0;
int time_track = 0;
float stp = 6.2831 / SAMPLES;
//120 deg = stp/3
int ret = 17;

timer_dev *dev1 = PIN_MAP[out1].timer_device;
timer_dev *dev2 = PIN_MAP[out2].timer_device;
timer_dev *dev3 = PIN_MAP[out3].timer_device;
uint8 cc_channel1 = PIN_MAP[out1].timer_channel;
uint8 cc_channel2 = PIN_MAP[out2].timer_channel;
//uint8 cc_channel4 = PIN_MAP[out3].timer_channel;
uint8 cc_channel3 = PIN_MAP[out3].timer_channel;

void fun()
{
flag1++;
}

void fun2()
{
flag2++;
}

void fun3()
{
flag3++;
}
//////////////////////////////////////////////////////////
void timer_conf()
{

timer_dma_set_base_addr(dev1, TIMER_DMA_BASE_CCR2);
timer_dma_set_burst_len(dev1, 1);
timer_dma_enable_req(dev1, cc_channel1);
timer_set_reload(dev1, 102);
timer_set_prescaler(dev1, 0);

timer_dma_set_base_addr(dev2, TIMER_DMA_BASE_CCR1);
timer_dma_set_burst_len(dev2, 1);
timer_dma_enable_req(dev2, cc_channel2);
timer_set_reload(dev2, 102);
timer_set_prescaler(dev2, 0);
// 3 channel
///////////////////////////////////////////////////////////////////
//timer_dma_set_base_addr(dev3, TIMER_DMA_BASE_CCR1);
//timer_dma_set_base_addr(dev3, TIMER_DMA_BASE_CCR3);

// timer_dma_set_base_addr(dev3, TIMER_DMA_BASE_CCR4); // T3 channel 4
timer_dma_set_base_addr(dev3, TIMER_DMA_BASE_CCR3);

/////////////////////////////////////////////////////////////////
timer_dma_set_burst_len(dev3, 1);
//timer_dma_enable_req(dev3, cc_channel4);
timer_dma_enable_req(dev3, cc_channel3);

timer_set_reload(dev3, 102);
timer_set_prescaler(dev3, 0);

}

void dma_conf()
{
dma_init(DMA1);
/* T4C2 DMA C4 */
dma_cfg.tube_dst = &(dev1->regs.gen->DMAR);
dma_cfg.tube_dst_size = DMA_SIZE_32BITS;
dma_cfg.tube_src = val1;
dma_cfg.tube_src_size = DMA_SIZE_32BITS;

dma_cfg.tube_nr_xfers = SAMPLES;
dma_cfg.tube_flags = DMA_CFG_SRC_INC | DMA_CFG_CIRC | DMA_CFG_CMPLT_IE;

dma_cfg.tube_req_src = DMA_REQ_SRC_TIM4_CH2;
dma_cfg.target_data = 0;

ret = dma_tube_cfg(DMA1, DMA_CH4, &dma_cfg);

/* T1C1 DMA C2 */
dma_cfg.tube_dst = &(dev2->regs.gen->DMAR);
dma_cfg.tube_dst_size = DMA_SIZE_32BITS;
dma_cfg.tube_src = val2;
dma_cfg.tube_src_size = DMA_SIZE_32BITS;

dma_cfg.tube_nr_xfers = SAMPLES;
dma_cfg.tube_flags = DMA_CFG_SRC_INC | DMA_CFG_CIRC | DMA_CFG_CMPLT_IE;
dma_cfg.tube_req_src = DMA_REQ_SRC_TIM1_CH1;
dma_cfg.target_data = 0;

ret = dma_tube_cfg(DMA1, DMA_CH2, &dma_cfg);

/////////////////////////////////////////

/* T3C3 DMA C3 */

dma_cfg.tube_dst = &(dev3->regs.gen->DMAR);
dma_cfg.tube_dst_size = DMA_SIZE_32BITS;
dma_cfg.tube_src = val3;
dma_cfg.tube_src_size = DMA_SIZE_32BITS;

dma_cfg.tube_nr_xfers = SAMPLES;
dma_cfg.tube_flags = DMA_CFG_SRC_INC | DMA_CFG_CIRC | DMA_CFG_CMPLT_IE;
// dma_cfg.tube_req_src = DMA_REQ_SRC_TIM1_CH4;

dma_cfg.tube_req_src = DMA_REQ_SRC_TIM3_CH4; // T3 channel 4
dma_cfg.tube_req_src = DMA_REQ_SRC_TIM3_CH3; // T3 channel 3
dma_cfg.target_data = 0;
////////////////////////////////////////////

}

void dma_start()
{
dma_attach_interrupt(DMA1, DMA_CH4, fun);

dma_enable(DMA1, DMA_CH4);
timer_resume(dev1);

dma_attach_interrupt(DMA1, DMA_CH2, fun2);

dma_enable(DMA1, DMA_CH2);
timer_resume(dev2);

//////////////////////////////////////////////
dma_attach_interrupt(DMA1, DMA_CH4, fun3);

//dma_enable(DMA1, DMA_CH4);
dma_enable(DMA1, DMA_CH3);

timer_resume(dev3);
///////////////////////////////////////////

}

void init_wave()
{
int i;
for (i = 0; i < SAMPLES; i++)
{
val1[i] = 50 + amp * sin(stp * i);
val2[i] = 50 + amp * cos(stp * i);
val3[i] = 50 + amp * sin(stp * i);

}
}

void setup() {
int i;
pinMode(out1, PWM);
pinMode(out2, PWM);
pinMode(out3, PWM);

Serial.begin(9600);

timer_conf();
dma_conf();
dma_start();

init_wave();

// get_wave(shift);

}

void loop() {

}


stevestrong
Tue Jul 03, 2018 2:24 pm
Your original setup used:

PB7 = T4C2 -> DMA_ch4
PA8 = T1C1 -> DMA_ch2
PB1 = T3C4 -> DMA_ch3

So why do you use DMA_ch4 for PB1? It should be DMA_ch3.
Please pay attention to this and setup the DMA accordingly.


ted
Tue Jul 03, 2018 2:59 pm
PB1 it is a channel 4 ?
I tried both lines.

dma_cfg.tube_nr_xfers = SAMPLES;
dma_cfg.tube_flags = DMA_CFG_SRC_INC | DMA_CFG_CIRC | DMA_CFG_CMPLT_IE;
// dma_cfg.tube_req_src = DMA_REQ_SRC_TIM1_CH4; // T3 channel 4
dma_cfg.tube_req_src = DMA_REQ_SRC_TIM3_CH3; // T3 channel 3


ted
Tue Jul 03, 2018 3:16 pm
This is for PB0, channel 3.

#define SAMPLES 100
#include <libmaple/dma.h>
dma_tube_config dma_cfg, dma_cfg2, dma_cfg3 ;

int flag1 = 0;
int flag2 = 0;
int flag3 = 0;

int out1 = PB7;
int out2 = PA8;
//int out3 = PB1;
//int out3 = PA7;
int out3 = PB0;

int val1[SAMPLES];
int val2[SAMPLES];
int val3[SAMPLES];

int16 shift = 0;

int amp = 35;
int cnt = 0;
int time_track = 0;
float stp = 6.2831 / SAMPLES;
//120 deg = stp/3
int ret = 17;

timer_dev *dev1 = PIN_MAP[out1].timer_device;
timer_dev *dev2 = PIN_MAP[out2].timer_device;
timer_dev *dev3 = PIN_MAP[out3].timer_device;
uint8 cc_channel1 = PIN_MAP[out1].timer_channel;
uint8 cc_channel2 = PIN_MAP[out2].timer_channel;
uint8 cc_channel3 = PIN_MAP[out3].timer_channel;

void fun()
{
flag1++;
}

void fun2()
{
flag2++;
}

void fun3()
{
flag3++;
}
//////////////////////////////////////////////////////////
void timer_conf()
{

timer_dma_set_base_addr(dev1, TIMER_DMA_BASE_CCR2);
timer_dma_set_burst_len(dev1, 1);
timer_dma_enable_req(dev1, cc_channel1);
timer_set_reload(dev1, 102);
timer_set_prescaler(dev1, 0);

timer_dma_set_base_addr(dev2, TIMER_DMA_BASE_CCR1);
timer_dma_set_burst_len(dev2, 1);
timer_dma_enable_req(dev2, cc_channel2);
timer_set_reload(dev2, 102);
timer_set_prescaler(dev2, 0);
// 3 channel
/*
///////////////////////////////////////////////////////////////////
//timer_dma_set_base_addr(dev3, TIMER_DMA_BASE_CCR1);
//timer_dma_set_base_addr(dev3, TIMER_DMA_BASE_CCR3);
timer_dma_set_base_addr(dev3, TIMER_DMA_BASE_CCR4); // T3 channel 4
/////////////////////////////////////////////////////////////////

*/

// channel 3
timer_dma_set_base_addr(dev3, TIMER_DMA_BASE_CCR3);
timer_dma_set_burst_len(dev3, 1);
timer_dma_enable_req(dev3, cc_channel3);
timer_set_reload(dev3, 102);
timer_set_prescaler(dev3, 0);

}

void dma_conf()
{
dma_init(DMA1);
/* T4C2 DMA C4 */
dma_cfg.tube_dst = &(dev1->regs.gen->DMAR);
dma_cfg.tube_dst_size = DMA_SIZE_32BITS;
dma_cfg.tube_src = val1;
dma_cfg.tube_src_size = DMA_SIZE_32BITS;

dma_cfg.tube_nr_xfers = SAMPLES;
dma_cfg.tube_flags = DMA_CFG_SRC_INC | DMA_CFG_CIRC | DMA_CFG_CMPLT_IE;

dma_cfg.tube_req_src = DMA_REQ_SRC_TIM4_CH2;
dma_cfg.target_data = 0;

ret = dma_tube_cfg(DMA1, DMA_CH4, &dma_cfg);

/* T1C1 DMA C2 */
dma_cfg.tube_dst = &(dev2->regs.gen->DMAR);
dma_cfg.tube_dst_size = DMA_SIZE_32BITS;
dma_cfg.tube_src = val2;
dma_cfg.tube_src_size = DMA_SIZE_32BITS;

dma_cfg.tube_nr_xfers = SAMPLES;
dma_cfg.tube_flags = DMA_CFG_SRC_INC | DMA_CFG_CIRC | DMA_CFG_CMPLT_IE;
dma_cfg.tube_req_src = DMA_REQ_SRC_TIM1_CH1;
dma_cfg.target_data = 0;

ret = dma_tube_cfg(DMA1, DMA_CH2, &dma_cfg);

/////////////////////////////////////////

/* T3C3 DMA C3 */

dma_cfg.tube_dst = &(dev3->regs.gen->DMAR);
dma_cfg.tube_dst_size = DMA_SIZE_32BITS;
dma_cfg.tube_src = val3;
dma_cfg.tube_src_size = DMA_SIZE_32BITS;

dma_cfg.tube_nr_xfers = SAMPLES;
dma_cfg.tube_flags = DMA_CFG_SRC_INC | DMA_CFG_CIRC | DMA_CFG_CMPLT_IE;
// dma_cfg.tube_req_src = DMA_REQ_SRC_TIM1_CH4; // T3 channel 4
dma_cfg.tube_req_src = DMA_REQ_SRC_TIM3_CH3; // T3 channel 3

ret = dma_tube_cfg(DMA1, DMA_CH3, &dma_cfg);
dma_cfg.target_data = 0;
////////////////////////////////////////////

}

void dma_start()
{
dma_attach_interrupt(DMA1, DMA_CH4, fun);

dma_enable(DMA1, DMA_CH4);
timer_resume(dev1);

dma_attach_interrupt(DMA1, DMA_CH2, fun2);

dma_enable(DMA1, DMA_CH2);
timer_resume(dev2);
/*
//////////////////////////////////////////////
dma_attach_interrupt(DMA1, DMA_CH4, fun3);

dma_enable(DMA1, DMA_CH4);
timer_resume(dev3);
///////////////////////////////////////////
*/
dma_attach_interrupt(DMA1, DMA_CH3, fun3);

dma_enable(DMA1, DMA_CH3);
timer_resume(dev3);

}

void init_wave()
{
int i;
for (i = 0; i < SAMPLES; i++)
{
val1[i] = 50 + amp * sin(stp * i);
val2[i] = 50 + amp * cos(stp * i);
val3[i] = 50 + amp * sin(stp * i);

}
}

void setup() {
int i;
pinMode(out1, PWM);
pinMode(out2, PWM);
pinMode(out3, PWM);

Serial.begin(9600);

timer_conf();
dma_conf();
dma_start();

init_wave();

// get_wave(shift);

}

void loop() {

}


stevestrong
Tue Jul 03, 2018 6:02 pm
See here the pin mapping to timer channels: https://github.com/rogerclarkmelbourne/ … pp#L58-L84
For DMA channel mapping see RM0008 chapter 13.3.7, page 281, figure 50.

ted
Tue Jul 03, 2018 8:17 pm
I am not familiar with that, I always use this one.
Image

ted
Tue Jul 03, 2018 9:20 pm
I am trying to use Timer 2, PA3 is working with another program.

#define SAMPLES 100
#include <libmaple/dma.h>
dma_tube_config dma_cfg, dma_cfg2, dma_cfg3;

int flag1 = 0;
int flag2 = 0;
int flag3 = 0;

int out1 = PB7;
int out2 = PA8;
//int out3 = PA2; // Timer #2, Channel #3
int out3 = PA3; // Timer #2, Channel #4

int val1[SAMPLES];
int val2[SAMPLES];
int val3[SAMPLES];

int16 shift = 0;

int amp = 35;
int cnt = 0;
int time_track = 0;
float stp = 6.2831 / SAMPLES;
int ret = 17;

timer_dev *dev1 = PIN_MAP[out1].timer_device;
timer_dev *dev2 = PIN_MAP[out2].timer_device;
timer_dev *dev3 = PIN_MAP[out3].timer_device;
uint8 cc_channel1 = PIN_MAP[out1].timer_channel;
uint8 cc_channel2 = PIN_MAP[out2].timer_channel;
uint8 cc_channel4 = PIN_MAP[out3].timer_channel;

void fun()
{
flag1++;
}

void fun2()
{
flag2++;
}
void fun3()
{
flag3++;
}

void timer_conf()
{

timer_dma_set_base_addr(dev1, TIMER_DMA_BASE_CCR2);
timer_dma_set_burst_len(dev1, 1);
timer_dma_enable_req(dev1, cc_channel1);
timer_set_reload(dev1, 102);
timer_set_prescaler(dev1, 0);

timer_dma_set_base_addr(dev2, TIMER_DMA_BASE_CCR1);
timer_dma_set_burst_len(dev2, 1);
timer_dma_enable_req(dev2, cc_channel2);
timer_set_reload(dev2, 102);
timer_set_prescaler(dev2, 0);
//////////////////////////////
//timer_dma_set_base_addr(dev3, TIMER_DMA_BASE_CCR1); // ?????????
timer_dma_set_base_addr(dev3, TIMER_DMA_BASE_CCR1);
timer_dma_set_burst_len(dev3, 1);
timer_dma_enable_req(dev3, cc_channel4); //
timer_set_reload(dev3, 102);
timer_set_prescaler(dev3, 0);
//////////////////////////////

}

void dma_conf()
{
dma_init(DMA1);
/* T4C2 DMA C4 , timer #4*/
dma_cfg.tube_dst = &(dev1->regs.gen->DMAR);
dma_cfg.tube_dst_size = DMA_SIZE_32BITS;
dma_cfg.tube_src = val1;
dma_cfg.tube_src_size = DMA_SIZE_32BITS;

dma_cfg.tube_nr_xfers = SAMPLES;
dma_cfg.tube_flags = DMA_CFG_SRC_INC | DMA_CFG_CIRC | DMA_CFG_CMPLT_IE;

dma_cfg.tube_req_src = DMA_REQ_SRC_TIM4_CH2;
dma_cfg.target_data = 0;

ret = dma_tube_cfg(DMA1, DMA_CH4, &dma_cfg);

/* T1C1 DMA C2, Timer #1*/
dma_cfg.tube_dst = &(dev2->regs.gen->DMAR);
dma_cfg.tube_dst_size = DMA_SIZE_32BITS;
dma_cfg.tube_src = val2;
dma_cfg.tube_src_size = DMA_SIZE_32BITS;

dma_cfg.tube_nr_xfers = SAMPLES;
dma_cfg.tube_flags = DMA_CFG_SRC_INC | DMA_CFG_CIRC | DMA_CFG_CMPLT_IE;

dma_cfg.tube_req_src = DMA_REQ_SRC_TIM1_CH1;
dma_cfg.target_data = 0;

ret = dma_tube_cfg(DMA1, DMA_CH2, &dma_cfg);
///////////////////////////////////
/* T2C1 DMA C3, Timer #2*/
dma_cfg.tube_dst = &(dev3->regs.gen->DMAR);
dma_cfg.tube_dst_size = DMA_SIZE_32BITS;
dma_cfg.tube_src = val3;
dma_cfg.tube_src_size = DMA_SIZE_32BITS;

dma_cfg.tube_nr_xfers = SAMPLES;
dma_cfg.tube_flags = DMA_CFG_SRC_INC | DMA_CFG_CIRC | DMA_CFG_CMPLT_IE;

dma_cfg.tube_req_src = DMA_REQ_SRC_TIM2_CH4; //
dma_cfg.target_data = 0;

ret = dma_tube_cfg(DMA1, DMA_CH4, &dma_cfg); //
////////////////////////////////////////

}

void dma_start()
{
dma_attach_interrupt(DMA1, DMA_CH4, fun);

dma_enable(DMA1, DMA_CH4);
timer_resume(dev1);

dma_attach_interrupt(DMA1, DMA_CH2, fun2);

dma_enable(DMA1, DMA_CH2);
timer_resume(dev2);
////////////////////////////////
dma_attach_interrupt(DMA1, DMA_CH4, fun3); //

dma_enable(DMA1, DMA_CH4); //
timer_resume(dev3);
////////////////////////////////
}

void init_wave()
{
int i;
for (i = 0; i < SAMPLES; i++)
{
val1[i] = 50 + amp * sin(stp * i);
val2[i] = 50 + amp * cos(stp * i);
val3[i] = 50 + amp * sin(stp * i);

}
}

void setup() {
int i;
pinMode(out1, PWM);
pinMode(out2, PWM);
pinMode(out3, PWM);

timer_conf();
dma_conf();
dma_start();

init_wave();

}

void loop()
{
}


Col68
Wed Jul 04, 2018 12:06 am
Hello dear ted, wanting to help you, i use the words “timer 2 and PA3” i’m falling on this table that may interest you.

Image

Thank you for your sharing and I thank the experienced volunteers who help and bring their support.

I wish you success for your project.


ted
Wed Jul 04, 2018 12:43 am
Thanks for table, can you give the link to it, maybe I will find the solution to my problem ?

Rick Kimball
Wed Jul 04, 2018 4:12 am
Can you have two different timers using the same dma channel? I don’t see how that would work.

Also why are you using 32 bits, aren’t the timer ccrx registers 16 bit?


ted
Wed Jul 04, 2018 10:52 am
[ted – Tue Jul 03, 2018 1:01 pm] –
I think something is not correct here.
fun and fun 3 are identical

void dma_start()
{
dma_attach_interrupt(DMA1, DMA_CH4, fun);

dma_enable(DMA1, DMA_CH4);
timer_resume(dev1);

dma_attach_interrupt(DMA1, DMA_CH2, fun2);

dma_enable(DMA1, DMA_CH2);
timer_resume(dev2);

//////////////////////////////////////////////
dma_attach_interrupt(DMA1, DMA_CH4, fun3);

dma_enable(DMA1, DMA_CH4);
timer_resume(dev3);
///////////////////////////////////////////


ted
Wed Jul 04, 2018 10:56 am
So I am trying to use DMA2 but I have an error.

C:\Users\OWNER\Desktop\DMA_2_3_CH\DMA_2_3_CH.ino: In function 'void dma_conf()':

DMA_2_3_CH:104: error: 'DMA2' was not declared in this scope

dma_init(DMA2);

^

C:\Users\OWNER\Desktop\DMA_2_3_CH\DMA_2_3_CH.ino: In function 'void dma_start()':

DMA_2_3_CH:135: error: 'DMA2' was not declared in this scope

dma_attach_interrupt(DMA2, DMA_CH4, fun3); //

^

exit status 1
'DMA2' was not declared in this scope


Rick Kimball
Wed Jul 04, 2018 3:32 pm
PB6 Tim4_Channel1 might be a good choice as it uses DMA1_Channel1 and wouldn’t conflict with the other pins.

ted
Wed Jul 04, 2018 3:46 pm
Timer 4 is already used by – out1 = PB7;

Rick Kimball
Wed Jul 04, 2018 4:12 pm
PB6 uses TIM4_CH1 .. and that uses DMA1_CHANNEL1
PB7 using TIM4_CH2 .. and that uses DMA1_CHANNEL4

dma1_chan_map.png
dma1_chan_map.png (62.56 KiB) Viewed 316 times

ted
Wed Jul 04, 2018 4:49 pm
Thanks
But Timer 4 is already used by first output – val #1, I want to add independent third timer.

Col68
Thu Jul 05, 2018 12:51 pm
[ted – Wed Jul 04, 2018 12:43 am] –
Thanks for table, can you give the link to it, maybe I will find the solution to my problem ?

Of course is a cover of a book on this subject.

https://books.google.fr/books?id=UYteDw … A3&f=false


ted
Fri Jul 06, 2018 2:40 pm
To avoid any conflicts I am trying to make a single sine wave generator using Timer #3 on base of working generator build onTimer # 4.

What I am dooing wrong ?

Square wave generator Timer #3 is working with pin PB0, so should sine.

HardwareTimer pwmtimer3(3);

void setup() {
//T3CH3
//pinMode(PA7, PWM);
pinMode(PB0, PWM);
pwmtimer3.pause();
pwmtimer3.setPrescaleFactor(1); // Timer input clock Prescaler = 1 (= 72MHz input ?)
pwmtimer3.setOverflow(1000-1); // PWM Period width for 720kHz ?
pwmtimer3.setCompare(TIMER_CH3, 500); // PWM High Pulse width is 50% duty (1:1)
pwmtimer3.refresh();
pwmtimer3.resume();

}

void loop() {
}


Rick Kimball
Fri Jul 06, 2018 5:35 pm
I added some defines to make it easy to test with a different pins:

PB0 using TIM3_CH3 which works with DMA ch2

This outputs a SIN wave on PB0:
//#define SAMPLES 1000
#include <libmaple/dma.h>
#define F_TIMER 72000000
#define FREQ 7200 // 7kHz
#define SAMPLES ((int)sqrt(F_TIMER / FREQ))
#define T_CNT ((F_TIMER/FREQ)/SAMPLES)

dma_tube_config dma_cfg ;

int flag1 = 0;
int out1 = PB0;
// PB0 TIM3 CH3 uses DMA CH2
#define DMA_REQ_SRC_TIMX_CHX DMA_REQ_SRC_TIM3_CH3
#define TIMER_DMA_BASE_CCRX TIMER_DMA_BASE_CCR3
#define DMA_CHX DMA_CH2

int val1[SAMPLES];

int16 shift = 30;

int amp = 50;
int cnt = 0;
int time_track = 0;
float stp = 6.2831 / SAMPLES;
int ret = 17;

timer_dev *dev1 = PIN_MAP[out1].timer_device;
uint8 cc_channel1 = PIN_MAP[out1].timer_channel;

void fun()
{
flag1++;
}

void timer_conf()
{
timer_dma_set_base_addr(dev1, TIMER_DMA_BASE_CCRX); //
timer_dma_set_burst_len(dev1, 1);
timer_dma_enable_req(dev1, cc_channel1);//
timer_set_reload(dev1, 102);
timer_set_prescaler(dev1, 0);

}

void dma_conf()
{
dma_init(DMA1);
/* T3C3 DMA C2 */
dma_cfg.tube_dst = &(dev1->regs.gen->DMAR);
dma_cfg.tube_dst_size = DMA_SIZE_32BITS;
dma_cfg.tube_src = val1;
dma_cfg.tube_src_size = DMA_SIZE_32BITS;

dma_cfg.tube_nr_xfers = SAMPLES;
dma_cfg.tube_flags = DMA_CFG_SRC_INC | DMA_CFG_CIRC | DMA_CFG_CMPLT_IE;

dma_cfg.tube_req_src = DMA_REQ_SRC_TIMX_CHX; //
dma_cfg.target_data = 0;

ret = dma_tube_cfg(DMA1, DMA_CHX, &dma_cfg);
}

void dma_start()
{
dma_attach_interrupt(DMA1, DMA_CHX, fun);
dma_enable(DMA1, DMA_CHX);
timer_resume(dev1);
}

void init_wave()
{
int i;
for (i = 0; i < SAMPLES; i++)
{
val1[i] = 50 + amp * sin(stp * i);

}
}

void setup() {
int i;
pinMode(out1, PWM);
timer_conf();
dma_conf();
dma_start();
init_wave();

}
void loop()
{
}


ted
Fri Jul 06, 2018 6:28 pm
GREAT !!!
THANKS !!!
Finally I can put things together.
The question.
The original 2 channel generator has some phase shift when both are set for sine, how to eliminate this ? – Phase correction ?

void init_wave()
{
int i;
for (i = 0; i < SAMPLES; i++)
{
val1[i] = 50 + amp * sin(stp * i);
val2[i] = 50 + amp * sin(stp * i);

}
}


ted
Fri Jul 06, 2018 8:18 pm
I changed some names, so they will be different than in 2 channel generator ( = #1) and is working ok, however adding it to #1 generator I have 2 conflicts. When I activate conflict #1 the signal on PA8 is 50% smaler and not sinhronizated with signal on PB7, when #2 the signal on PA8 is gone.

void timer_conf() = conflict #1, void dma_conf() = conflict #2

Your modified, ok

//#define SAMPLES 1000
#include <libmaple/dma.h>
#define F_TIMER 72000000
#define FREQ 7200 // 7kHz
#define SAMPLES ((int)sqrt(F_TIMER / FREQ))
#define T_CNT ((F_TIMER/FREQ)/SAMPLES)

dma_tube_config dma_cfg ;

int flag3 = 0;
int out3 = PB0;
// PB0 TIM3 CH3 uses DMA CH2
#define DMA_REQ_SRC_TIMX_CHX DMA_REQ_SRC_TIM3_CH3
#define TIMER_DMA_BASE_CCRX TIMER_DMA_BASE_CCR3
#define DMA_CHX DMA_CH2

int val3[SAMPLES];

int16 shift = 30;

int amp = 50;
int cnt = 0;
int time_track = 0;
float stp = 6.2831 / SAMPLES;
int ret = 17;

timer_dev *dev3 = PIN_MAP[out3].timer_device;
uint8 cc_channel3 = PIN_MAP[out3].timer_channel;

void fun3()
{
flag3++;
}

void timer_conf()
{
timer_dma_set_base_addr(dev3, TIMER_DMA_BASE_CCRX); //
timer_dma_set_burst_len(dev3, 1);
timer_dma_enable_req(dev3, cc_channel3);//
timer_set_reload(dev3, 102);
timer_set_prescaler(dev3, 0);

}

void dma_conf()
{
dma_init(DMA1);
/* T3C3 DMA C2 */
dma_cfg.tube_dst = &(dev3->regs.gen->DMAR);
dma_cfg.tube_dst_size = DMA_SIZE_32BITS;
dma_cfg.tube_src = val3;
dma_cfg.tube_src_size = DMA_SIZE_32BITS;

dma_cfg.tube_nr_xfers = SAMPLES;
dma_cfg.tube_flags = DMA_CFG_SRC_INC | DMA_CFG_CIRC | DMA_CFG_CMPLT_IE;

dma_cfg.tube_req_src = DMA_REQ_SRC_TIMX_CHX; //
dma_cfg.target_data = 0;

ret = dma_tube_cfg(DMA1, DMA_CHX, &dma_cfg);
}

void dma_start()
{
dma_attach_interrupt(DMA1, DMA_CHX, fun3);
dma_enable(DMA1, DMA_CHX);
timer_resume(dev3);
}

void init_wave()
{
int i;
for (i = 0; i < SAMPLES; i++)
{
val3[i] = 50 + amp * sin(stp * i);

}
}

void setup() {
int i;
pinMode(out3, PWM);
timer_conf();
dma_conf();
dma_start();
init_wave();

}
void loop()
{
}


Rick Kimball
Fri Jul 06, 2018 8:48 pm
I successfully tried each pin by itself:
#if 0
static const int WS281X_PIN = PB0;
#define DMA_REQ_SRC_TIMX_CHNX DMA_REQ_SRC_TIM3_CH3
#define TIMER_DMA_BASE_CCRX TIMER_DMA_BASE_CCR3
#define DMA_CHX DMA_CH2
#elif 1
static const int WS281X_PIN = PB7;
#define DMA_REQ_SRC_TIMX_CHNX DMA_REQ_SRC_TIM4_CH2
#define TIMER_DMA_BASE_CCRX TIMER_DMA_BASE_CCR2
#define DMA_CHX DMA_CH4
#elif 0
static const int WS281X_PIN = PA8;
#define DMA_REQ_SRC_TIMX_CHNX DMA_REQ_SRC_TIM1_CH1
#define TIMER_DMA_BASE_CCRX TIMER_DMA_BASE_CCR1
#define DMA_CHX DMA_CH2
#endif

ted
Fri Jul 06, 2018 8:51 pm
This two lines are causing the problems.

//timer_dma_enable_req(dev3, cc_channel3);//


Rick Kimball
Fri Jul 06, 2018 9:01 pm
@stevestrong gave you the answer on which pins to use back here:

viewtopic.php?f=19&t=3820#p46900

#if 1
static const int WS281X_PIN = PB1;
#define DMA_REQ_SRC_TIMX_CHNX DMA_REQ_SRC_TIM3_CH4
#define TIMER_DMA_BASE_CCRX TIMER_DMA_BASE_CCR4
#define DMA_CHX DMA_CH3

#elif 0
static const int WS281X_PIN = PB7;
#define DMA_REQ_SRC_TIMX_CHNX DMA_REQ_SRC_TIM4_CH2
#define TIMER_DMA_BASE_CCRX TIMER_DMA_BASE_CCR2
#define DMA_CHX DMA_CH4

#elif 0
static const int WS281X_PIN = PA8;
#define DMA_REQ_SRC_TIMX_CHNX DMA_REQ_SRC_TIM1_CH1
#define TIMER_DMA_BASE_CCRX TIMER_DMA_BASE_CCR1
#define DMA_CHX DMA_CH2

#elif 0
static const int WS281X_PIN = PB0;
#define DMA_REQ_SRC_TIMX_CHNX DMA_REQ_SRC_TIM3_CH3
#define TIMER_DMA_BASE_CCRX TIMER_DMA_BASE_CCR3
#define DMA_CHX DMA_CH2
#endif


ted
Fri Jul 06, 2018 10:32 pm
I changed to PB1, no conflicts and no signal on PB1.

#define SAMPLES 100
#include <libmaple/dma.h>
dma_tube_config dma_cfg, dma_cfg2, dma_cfg3;
/*
///////////////
// PB0 TIM3 CH3 uses DMA CH2
#define DMA_REQ_SRC_TIMX_CHX DMA_REQ_SRC_TIM3_CH3
#define TIMER_DMA_BASE_CCRX TIMER_DMA_BASE_CCR3
#define DMA_CHX DMA_CH2
/////////////////
*/

////////////////////////
//static const int WS281X_PIN = PB1;
#define DMA_REQ_SRC_TIMX_CHNX DMA_REQ_SRC_TIM3_CH4
#define TIMER_DMA_BASE_CCRX TIMER_DMA_BASE_CCR4
#define DMA_CHX DMA_CH3
////////////////////////
int flag1 = 0;
int flag2 = 0;
int flag3 = 0;

int out1 = PB7;
int out2 = PA8;
int out3 = PB1;

int val1[SAMPLES];
int val2[SAMPLES];
int val3[SAMPLES];

int16 shift = 0;

int amp = 35;
int cnt = 0;
int time_track = 0;
float stp = 6.2831 / SAMPLES;
int ret = 17;

timer_dev *dev1 = PIN_MAP[out1].timer_device;
timer_dev *dev2 = PIN_MAP[out2].timer_device;
uint8 cc_channel1 = PIN_MAP[out1].timer_channel;
uint8 cc_channel2 = PIN_MAP[out2].timer_channel;

///////////////////////////////
timer_dev *dev3 = PIN_MAP[out3].timer_device;
uint8 cc_channel3 = PIN_MAP[out3].timer_channel;
//////////////////////////

void fun()
{
flag1++;
}

void fun2()
{
flag2++;
}
void fun3()
{
flag3++;
}

void timer_conf()
{
//T4
timer_dma_set_base_addr(dev1, TIMER_DMA_BASE_CCR2);
timer_dma_set_burst_len(dev1, 1);
timer_dma_enable_req(dev1, cc_channel1);
timer_set_reload(dev1, 102);
timer_set_prescaler(dev1, 0);
//T2
timer_dma_set_base_addr(dev2, TIMER_DMA_BASE_CCR1);
timer_dma_set_burst_len(dev2, 1);
timer_dma_enable_req(dev2, cc_channel2);
timer_set_reload(dev2, 102);
timer_set_prescaler(dev2, 0);

////////////////////////////////////
timer_dma_set_base_addr(dev3, TIMER_DMA_BASE_CCR4); //
timer_dma_set_burst_len(dev3, 1);

// conflict #1
timer_dma_enable_req(dev3, cc_channel3);//

timer_set_reload(dev3, 102);
timer_set_prescaler(dev3, 0);
///////////////////////////////////

}

void dma_conf()
{
dma_init(DMA1);
/* T4C2 DMA C4 */
dma_cfg.tube_dst = &(dev1->regs.gen->DMAR);
dma_cfg.tube_dst_size = DMA_SIZE_32BITS;
dma_cfg.tube_src = val1;
dma_cfg.tube_src_size = DMA_SIZE_32BITS;

dma_cfg.tube_nr_xfers = SAMPLES;
dma_cfg.tube_flags = DMA_CFG_SRC_INC | DMA_CFG_CIRC | DMA_CFG_CMPLT_IE;

dma_cfg.tube_req_src = DMA_REQ_SRC_TIM4_CH2;
dma_cfg.target_data = 0;

ret = dma_tube_cfg(DMA1, DMA_CH4, &dma_cfg);

/* T1C1 DMA C2 */
dma_cfg.tube_dst = &(dev2->regs.gen->DMAR);
dma_cfg.tube_dst_size = DMA_SIZE_32BITS;
dma_cfg.tube_src = val2;
dma_cfg.tube_src_size = DMA_SIZE_32BITS;

dma_cfg.tube_nr_xfers = SAMPLES;
dma_cfg.tube_flags = DMA_CFG_SRC_INC | DMA_CFG_CIRC | DMA_CFG_CMPLT_IE;

dma_cfg.tube_req_src = DMA_REQ_SRC_TIM1_CH1;
dma_cfg.target_data = 0;

ret = dma_tube_cfg(DMA1, DMA_CH2, &dma_cfg);

///////////////////////
/* T3C3 DMA C2 */

dma_cfg.tube_dst = &(dev3->regs.gen->DMAR);
dma_cfg.tube_dst_size = DMA_SIZE_32BITS;
dma_cfg.tube_src = val3;
dma_cfg.tube_src_size = DMA_SIZE_32BITS;

dma_cfg.tube_nr_xfers = SAMPLES;
dma_cfg.tube_flags = DMA_CFG_SRC_INC | DMA_CFG_CIRC | DMA_CFG_CMPLT_IE;

//dma_cfg.tube_req_src = DMA_REQ_SRC_TIMX_CHX; //
dma_cfg.tube_req_src = DMA_REQ_SRC_TIM3_CH4; //
dma_cfg.target_data = 0;
// conflict #2
ret = dma_tube_cfg(DMA1, DMA_CH3, &dma_cfg);

//////////////////////

}

void dma_start()
{
dma_attach_interrupt(DMA1, DMA_CH4, fun);

dma_enable(DMA1, DMA_CH4);
timer_resume(dev1);

dma_attach_interrupt(DMA1, DMA_CH2, fun2);

dma_enable(DMA1, DMA_CH2);
timer_resume(dev2);

////////////////////////////
dma_attach_interrupt(DMA1, DMA_CH3, fun3);
dma_enable(DMA1, DMA_CH4);
timer_resume(dev3);
////////////////////////////

}

void init_wave()
{
int i;
for (i = 0; i < SAMPLES; i++)
{
val1[i] = 50 + amp * sin(stp * i);
val2[i] = val1[i];
val3[i] = val1[i];
}
}

void setup() {
int i;
pinMode(out1, PWM);
pinMode(out2, PWM);
pinMode(out3, PWM);

timer_conf();
dma_conf();
dma_start();

init_wave();

}

void loop() {

}


Rick Kimball
Fri Jul 06, 2018 10:33 pm
I don’t think we can help you … we have explained it 6 ways from Sunday

ted
Fri Jul 06, 2018 10:40 pm
Thanks Rick for your help, I will try to solve that problem.
Regards
Ted

ted
Fri Jul 06, 2018 10:41 pm
Thanks all of you

Rick Kimball
Fri Jul 06, 2018 10:59 pm
Tested and works:
#define SAMPLES 100
#include <libmaple/dma.h>

dma_tube_config dma_cfg, dma_cfg2, dma_cfg3;

int val1[SAMPLES];
int val2[SAMPLES];
int val3[SAMPLES];

int amp = 35;
int cnt = 0;
int time_track = 0;
float stp = 6.2831 / SAMPLES;
int ret = 17;

int out1 = PB7; // TIM4_CH2 DMA_CH4
timer_dev *dev1 = PIN_MAP[out1].timer_device;

int out2 = PA8; // TIM1_CH1 DMA_CH2
timer_dev *dev2 = PIN_MAP[out2].timer_device;

int out3 = PB1; // TIM3_CH4 DMA CH3
timer_dev *dev3 = PIN_MAP[out3].timer_device;

void timer_conf()
{
// PB7 TIM4_CH2 DMA_CH4
timer_dma_set_base_addr(dev1, TIMER_DMA_BASE_CCR2);
timer_dma_set_burst_len(dev1, 1);
timer_dma_enable_req(dev1, PIN_MAP[out1].timer_channel);
timer_set_reload(dev1, 102);
timer_set_prescaler(dev1, 0);

// PA8 TIM1_CH1 DMA_CH2
timer_dma_set_base_addr(dev2, TIMER_DMA_BASE_CCR1);
timer_dma_set_burst_len(dev2, 1);
timer_dma_enable_req(dev2, PIN_MAP[out2].timer_channel);
timer_set_reload(dev2, 102);
timer_set_prescaler(dev2, 0);

// PB1 TIM3_CH4 DMA CH3
timer_dma_set_base_addr(dev3, TIMER_DMA_BASE_CCR4); //
timer_dma_set_burst_len(dev3, 1);
timer_dma_enable_req(dev3, PIN_MAP[out3].timer_channel);//
timer_set_reload(dev3, 102);
timer_set_prescaler(dev3, 0);
}

void dma_conf()
{
dma_init(DMA1);

// PB7 TIM4_CH2 DMA_CH4
dma_cfg.tube_dst = &(dev1->regs.gen->DMAR);
dma_cfg.tube_dst_size = DMA_SIZE_32BITS;
dma_cfg.tube_src = val1;
dma_cfg.tube_src_size = DMA_SIZE_32BITS;
dma_cfg.tube_nr_xfers = SAMPLES;
dma_cfg.tube_flags = DMA_CFG_SRC_INC | DMA_CFG_CIRC;
dma_cfg.tube_req_src = DMA_REQ_SRC_TIM4_CH2;
dma_cfg.target_data = 0;
ret = dma_tube_cfg(DMA1, DMA_CH4, &dma_cfg);

// PA8 TIM1_CH1 DMA_CH2
dma_cfg.tube_dst = &(dev2->regs.gen->DMAR);
dma_cfg.tube_dst_size = DMA_SIZE_32BITS;
dma_cfg.tube_src = val2;
dma_cfg.tube_src_size = DMA_SIZE_32BITS;
dma_cfg.tube_nr_xfers = SAMPLES;
dma_cfg.tube_flags = DMA_CFG_SRC_INC | DMA_CFG_CIRC;
dma_cfg.tube_req_src = DMA_REQ_SRC_TIM1_CH1;
dma_cfg.target_data = 0;
ret = dma_tube_cfg(DMA1, DMA_CH2, &dma_cfg);

// PB1 TIM3_CH4 DMA CH3
dma_cfg.tube_dst = &(dev3->regs.gen->DMAR);
dma_cfg.tube_dst_size = DMA_SIZE_32BITS;
dma_cfg.tube_src = val3;
dma_cfg.tube_src_size = DMA_SIZE_32BITS;
dma_cfg.tube_nr_xfers = SAMPLES;
dma_cfg.tube_flags = DMA_CFG_SRC_INC | DMA_CFG_CIRC;
dma_cfg.tube_req_src = DMA_REQ_SRC_TIM3_CH4; //
dma_cfg.target_data = 0;
ret = dma_tube_cfg(DMA1, DMA_CH3, &dma_cfg);
}

void dma_start()
{
// PB7 TIM4_CH2 DMA_CH4
dma_enable(DMA1, DMA_CH4);
timer_resume(dev1);

// PA8 TIM1_CH1 DMA_CH2
dma_enable(DMA1, DMA_CH2);
timer_resume(dev2);

// PB1 TIM3_CH4 DMA CH3
dma_enable(DMA1, DMA_CH3);
timer_resume(dev3);
}

void init_wave()
{
int i;

for (i = 0; i < SAMPLES; i++)
{
val1[i] = 50 + amp * sin(stp * i);
val2[i] = val1[i];
val3[i] = 50 + amp * sin(stp * i);
}
}

void setup() {
pinMode(out1, PWM);
pinMode(out2, PWM);
pinMode(out3, PWM);

timer_conf();
dma_conf();
dma_start();

init_wave();

}

void loop() {
}


ted
Fri Jul 06, 2018 11:44 pm
Thanks Rick, you are the best.
There is small issue with phase correction,comparing to PB7, PB1 is shifted approximately 10 deg. and PA8 60 deg, I think I can manage this.
Thanks again.

I did this – no changes.

{
val1[i] = 50 + amp * sin(stp * i);
//val2[i] = val1[i];
val2[i] = 50 + amp * sin(stp * i);
val3[i] = 50 + amp * sin(stp * i);
}


ted
Sat Jul 07, 2018 12:29 am
Solved by Mr. Rick

Col68
Sun Jul 08, 2018 4:14 pm
[ted – Sat Jul 07, 2018 12:29 am] – Solved by Mr. Rick

Congratulations and good luck :)

when i saw Rick assist you, i thought “he will succeed” because Rick is too strong.

Respect for ☆ Rick ☆


Leave a Reply

Your email address will not be published. Required fields are marked *