AnsweredAssumed Answered

Why I can't generate an TPM overflow  request to DMA?

Question asked by Abraham Rosas on Nov 25, 2019
Latest reply on Dec 4, 2019 by Abraham Rosas

Hi everybody.

 

I'm using the FRDM-KL46z with MCUXpresso and I want to control a NEO-Pixel LED but I need to use the TPM and DMA.

I configure the DMA with config-tools as follow.

 

  And the TPM is the same and as follow.

 

#include <stdio.h>
#include "board.h"
#include "peripherals.h"
#include "pin_mux.h"
#include "clock_config.h"
#include "fsl_gpio.h"
#include "fsl_port.h"
#include "MKL46Z4.h"
/* TODO: insert other include files here. */
#define LOGIC_LED_ON 0U
#define LOGIC_LED_OFF 1U
#ifndef BOARD_LED_RED_GPIO
#define BOARD_LED_RED_GPIO GPIOE
#endif
#ifndef BOARD_LED_RED_GPIO_PIN
#define BOARD_LED_RED_GPIO_PIN 29U
#endif
#define BOARD_TPM_CHANNEL 5U
#ifndef TPM_LED_ON_LEVEL
#define TPM_LED_ON_LEVEL kTPM_LowTrue
#endif
uint16_t Val_Cn = 10000; //the Value of duty cycle
tpm_status_flags_t flag_t = 0; //the flag of TPM status
dma_transfer_config_t TPM_CONF; //struct to config the DMA transfer to TPM
uint32_t flag_dma = 0; //the flag of DMA status.

/* TODO: insert other definitions and declarations here. */
void DMA_Callback(dma_handle_t * handle, void* param)
{
__asm volatile ("nop"); //only for a breakpoint
}
void DMA_1_DMA_CH_INT_DONE_0_IRQHANDLER()
{
__asm volatile ("nop"); //only for a breakpoint
flag_t = TPM_GetStatusFlags(TPM0);
flag_dma = DMA_GetChannelStatusFlags(DMA0, DMA_1_DMA_TPM_DMA_CHANNEL);
DMA_ClearChannelStatusFlags(DMA0, DMA_1_DMA_TPM_DMA_CHANNEL, flag_dma);
}

/*
* @brief Application entry point.
*/

int main(void) {
/* Init board hardware. */
BOARD_InitBootPins();
BOARD_InitBootClocks();
BOARD_InitBootPeripherals();


TPM0->SC |= TPM_SC_DMA(1); //Enable the DMA on TPM
TPM0->CONTROLS[5].CnSC |= TPM_CnSC_DMA(1); //Enable the DMA transfer on TPM channel 5

DMA0->DMA[0].DCR |= DMA_DCR_ERQ_MASK; //enable the peripheral request

DMA_PrepareTransfer(&TPM_CONF, &Val_Cn, sizeof(uint16_t),
&(TPM0->CONTROLS[5].CnV), sizeof(uint16_t), 2, kDMA_MemoryToPeripheral); //prepare the struct transfer

DMA_SubmitTransfer(&DMA_1_DMA_TPM_Handle, &TPM_CONF, kDMA_EnableInterrupt);//prepare the handle DMA_TPM

//DMA_StartTransfer(&DMA_1_DMA_TPM_Handle);

TPM_StartTimer(TPM0, kTPM_SystemClock); //Init the timer without interrupt request

/* Enter an infinite loop, just incrementing a counter. */
while(1) {

__asm volatile ("nop");//only for a breakpoint

flag_dma = DMA_GetChannelStatusFlags(DMA0, DMA_1_DMA_TPM_DMA_CHANNEL); //I check the status flag DMA
flag_t = TPM_GetStatusFlags(TPM0); //I check the status flag TPM

if(flag_t == (kTPM_TimeOverflowFlag | kTPM_Chnl5Flag)){
GPIO_PortToggle(BOARD_LED_RED_GPIO, 1U <<
BOARD_LED_RED_GPIO_PIN);

TPM_ClearStatusFlags(TPM0, kTPM_TimeOverflowFlag | kTPM_Chnl5Flag); //I clean the status flags
}
}
return 0 ;
}

 

But the overflow in TPM don't generate the request DMA to send the data to cnV counter of TPM only if I just not comment the Line 60 "DMA_StartTransfer" the counter register refresh it but this only execution it a once and I want to refresh the Counter register channel every time that an overflow occurs.

 

Thanks.

Best regards.

Outcomes