This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

DMA transfer triggered from timer

Other Parts Discussed in Thread: CC3200

  I am trying to get an application driver working on the CC3200.  It requires that a DMA transfer be triggered from a timer operating in PWM mode.  I have got the timer operating properly, but I cannot get the DMA to trigger.  I can trigger it manually by issuing a software request, but it will not initiate from the timer.   The application requires that a new timer match value be loaded every PWM cycle, and the DMA is set up to do this, but nothing happens.  The code is summarized below.

UDMAInit();

MAP_PRCMPeripheralClkEnable(PRCM_TIMERA3, PRCM_RUN_MODE_CLK);

MAP_TimerDisable(TIMERA3_BASE,TIMER_B);

MAP_TimerConfigure(TIMERA3_BASE,(TIMER_CFG_SPLIT_PAIR | TIMER_CFG_B_PWM));

MAP_TimerPrescaleSet(TIMERA3_BASE,TIMER_B,0);

MAP_TimerControlLevel(TIMERA3_BASE,TIMER_B,0);

MAP_TimerControlEvent(TIMERA3_BASE,TIMER_B,TIMER_EVENT_POS_EDGE);

MAP_TimerLoadSet(TIMERA3_BASE,TIMER_B,TIMER_INTERVAL_RELOAD);

MAP_TimerEnable(TIMERA3_BASE,TIMER_B);

MAP_uDMAChannelDisable(7);

MAP_uDMAChannelAssign(UDMA_CH7_TIMERA3_B);

SetupTransfer(UDMA_CH7_TIMERA3_B, UDMA_MODE_BASIC, (STRIPLENGTH * 3)-1,

UDMA_SIZE_16, UDMA_ARB_1,(void *)(&DMABuffer), UDMA_SRC_INC_16,

(void *)(TIMERA3_BASE + 0x34),UDMA_DST_INC_NONE);

MAP_uDMAChannelAttributeDisable(UDMA_CH7_TIMERA3_B,UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST | UDMA_ATTR_REQMASK);

MAP_uDMAChannelAttributeEnable(UDMA_CH7_TIMERA3_B,UDMA_ATTR_HIGH_PRIORITY);

MAP_uDMAChannelAssign(UDMA_CH7_TIMERA3_B);

MAP_uDMAChannelEnable(7);

MAP_TimerDMAEventSet(TIMERA3_BASE,TIMER_DMA_TIMEOUT_B);

 

 

  After this is run, all visible registers are set up correctly, and the PWM timer is running fine and generating the expected pulse waveform,  but the DMA does not run, (unless I issue software requests).  What am I missing here?


Thanks in advance for any help.

  • Hi Mike,

    I will check and get back to you on this issue.

    Thanks and Regards,

    Praveen

  • Hi Mike,

    Referring to TRM section 9.3.2.4 PWM Mode you will see to get a DMA event in PWM mode you will need to set an additional bit in TnPWMIE bit in the GPTMTnMR register.

    You can do it like this

    HWREG(TIMERA3_BASE + 0x08)  |= (1<<9);

    Also you will need to change the DMA trigger event

    MAP_TimerDMAEventSet(TIMERA3_BASE,TIMER_DMA_TIMEOUT_B); 

    To

    MAP_TimerDMAEventSet(TIMERA3_BASE,TIMER_DMA_CAPEVENT_B);

    Here is the modified code

        MAP_PRCMPeripheralClkEnable(PRCM_TIMERA3, PRCM_RUN_MODE_CLK);
        MAP_PRCMPeripheralReset(PRCM_TIMERA3);

        MAP_TimerDisable(TIMERA3_BASE,TIMER_B);

        MAP_TimerConfigure(TIMERA3_BASE,(TIMER_CFG_SPLIT_PAIR | TIMER_CFG_B_PWM));

        MAP_TimerPrescaleSet(TIMERA3_BASE,TIMER_B,0);

        MAP_TimerControlLevel(TIMERA3_BASE,TIMER_B,0);

        MAP_TimerControlEvent(TIMERA3_BASE,TIMER_B,TIMER_EVENT_POS_EDGE);

        MAP_TimerLoadSet(TIMERA3_BASE,TIMER_B,0xFFFF);

        HWREG(0x40033008) |= (1<<9);

        MAP_uDMAChannelDisable(7);

        MAP_uDMAChannelAssign(UDMA_CH7_TIMERA3_B);

        SetupTransfer(UDMA_CH7_TIMERA3_B, UDMA_MODE_BASIC, 1,

        UDMA_SIZE_16, UDMA_ARB_1,(void *)(&DMABuffer), UDMA_SRC_INC_16,

        (void *)(TIMERA3_BASE + 0x34),UDMA_DST_INC_NONE);

        MAP_uDMAChannelAttributeDisable(UDMA_CH7_TIMERA3_B,UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST | UDMA_ATTR_REQMASK);

        MAP_uDMAChannelAttributeEnable(UDMA_CH7_TIMERA3_B,UDMA_ATTR_HIGH_PRIORITY);

        MAP_uDMAChannelAssign(UDMA_CH7_TIMERA3_B);

        MAP_uDMAChannelEnable(7);

        MAP_TimerDMAEventSet(TIMERA3_BASE,TIMER_DMA_CAPEVENT_B);

        MAP_TimerEnable(TIMERA3_BASE,TIMER_B);

    Pls try out this and let me know if this solves your issue.

    Thanks and Regards,

    Praveen

  • Praveen,

    Thank you much for your answer to my question, it was a big help.  I now have our PWM application code running successfully using Ping-Pong DMA and interrupts. 

    I do have another question, however.  I am using tables containing 16-bits for each match-register update, but they get rather large.  Since the actual values I need to write to the Timer match registers only range up to 99, it would seem possible to reduce their size to 8-bits, and only transfer a single byte at a time with the DMA in order to control the PWM pulse width  (since the MS byte is always zero).  This would cut the memory requirement in half.  So I gave it a try - unfortunately, it did not work as hoped.  What I see is that each byte ends up doubled, that is written twice to the Timer register.  In other words, if I have the value 0x42 in memory to be written to the timer,  after the DMA has performed the transfer, the register reads 0x4242, rather than 0x0042 !  Can you explain why this is so and whether there is something simple that I can change to let the DMA operate as desired, with 0x0042 ending up in the register?

    Thanks again Praveen,

    Mike Collender