Using DMA to vary PWM duty cycle

Development environment specific, Arduino, Eclipse, VS2013, Em::Blocks etc
Post Reply
nr4ps
Posts: 8
Joined: Sun Oct 30, 2022 7:20 pm

Using DMA to vary PWM duty cycle

Post by nr4ps »

Hello,

I am trying to understand how to use DMA to vary PWM duty cycle so that I could put it through a low-pass filter to create a sine wave. I am using the rogerclarkmelbourne core. I tried doing it with dma_setup_transfer (commented out) and with dma_tube_config (which is evidently the preferred way of doing DMA now), but I'm not understanding how they're supposed to work. In either case I get a compiler error on the DMA_CCR_CIRC | DMA_CCR_MINC portion:

Compilation error: invalid conversion from 'const void*' to 'volatile void*' [-fpermissive]

Can anyone tell me what I'm doing wrong?

Code: Select all

#include "libmaple/dma.h"
#define filteredPWMpin PB0

// sinewave = round(512/2*(sin(dt:dt:2*pi)+1))
#define SINSIZE 64
const uint16_t Sinewave[SINSIZE] = 
{  281,  306,  330,  354,  377,  398,  418,  437,  454,  469,  482,  493,  501,  507,  511,  512,
   511,  507,  501,  493,  482,  469,  454,  437,  418,  398,  377,  354,  330,  306,  281,  256,
   231,  206,  182,  158,  135,  114,   94,   75,   58,   43,   30,   19,   11,    5,    1,    0,
     1,    5,   11,   19,   30,   43,   58,   75,   94,  114,  135,  158,  182,  206,  231,  256 };

#include <libmaple/timer.h>
timer_dev *timerdev;
uint8 cc_channel;
void pwmSetup (uint8 pin, uint16 duty_cycle) {
    if (pin >= BOARD_NR_GPIO_PINS) {
        return;
    }
    timerdev = PIN_MAP[pin].timer_device;
    cc_channel = PIN_MAP[pin].timer_channel;
    ASSERT(timerdev && cc_channel);
    timer_set_reload(timerdev, 512);
    timer_set_compare(timerdev, cc_channel, duty_cycle);
    dma_init(DMA1);
    __IO uint32 *ccr = &(timerdev->regs).gen->CCR1 + (cc_channel - 1);
    // dma_setup_transfer is deprecated in favor of dma_tube_config
    /*
    dma_setup_transfer( DMA1, DMA_CH1, Sinewave, DMA_SIZE_16BITS,
       ccr, 
       DMA_SIZE_16BITS,
       DMA_CCR_CIRC | DMA_CCR_MINC );
    dma_set_num_transfers(DMA1, DMA_CH1, SINSIZE);
    dma_enable(DMA1, DMA_CH1);
    */
    struct dma_tube_config myconfig;
    myconfig.tube_dst = ccr;
    myconfig.tube_dst_size = DMA_SIZE_16BITS;
    myconfig.tube_src = Sinewave;
    myconfig.tube_src_size = DMA_SIZE_16BITS;
    myconfig.tube_nr_xfers = SINSIZE;
    myconfig.tube_flags = DMA_CCR_CIRC | DMA_CCR_MINC;
    myconfig.tube_req_src = DMA_REQ_SRC_TIM4_CH2; //?
}

void setup() {
  // put your setup code here, to run once:
  pinMode(filteredPWMpin, PWM);
  pwmSetup(filteredPWMpin, 1);
}

void loop() {
  // put your main code here, to run repeatedly:

}
User avatar
Bakisha
Posts: 140
Joined: Fri Dec 20, 2019 6:50 pm
Answers: 5
Contact:

Re: Using DMA to vary PWM duty cycle

Post by Bakisha »

Replace

Code: Select all

const uint16_t Sinewave[SINSIZE] = 
with

Code: Select all

uint16_t Sinewave[SINSIZE] = 
I can't say will it work (i'm not familiar with dma functions in rogers core), but at least it will compile.
nr4ps
Posts: 8
Joined: Sun Oct 30, 2022 7:20 pm

Re: Using DMA to vary PWM duty cycle

Post by nr4ps »

Thank you! I must've misread which line was producing the error!
Post Reply

Return to “IDE's”