Example MPC5744P CTU triggered by eTimer0 GSH614

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Example MPC5744P CTU triggered by eTimer0 GSH614

Example MPC5744P CTU triggered by eTimer0 GSH614

********************************************************************************

* Detailed Description:

* This example shows how to use the CTU module triggered from eTimer0 module channel 2.

*

* For closer details on how CTU works I suggest you to check application note

* MPC5643LPWM_ADC_concept

* https://community.freescale.com/docs/DOC-102559

*

* This example sets eTimer0 channel2 for PWM signal generation.

* This signal is than used to send MSR trigger to CTU module

* Example contains also simple CTU module driver initialization

* CTU scheduler submodule is toggling with external pin based on CTU triggers

*

* ------------------------------------------------------------------------------

* Test HW:  MPC57xx Motherboard + MPC5744PE257DC minimodule, MPC5744P,

* silicon mask set 1N65H

* Target :  internal_FLASH*

********************************************************************************

Original Attachment has been moved to: Example-MPC5744P-CTU-eTimer-v1_1-GHS614.zip

Comments

Hi,

I have an issue with the CTU for the MPC5744P, I have setup 3 syncronized PWM signals on FlexPWM_0 for controlling an PMSM motor.

To control this motor I also need to measure the currents at a specific place in the PWM cycle.

I have tried to setup PWM submodule 0 to generate OUT_TRIG0 and configured the CTU to start dual conversions on the ADC, but as I need to convert more analog signals in my design i have created a list of commands that the CTU should send to the ADC.

When the 6 commands are completed a dma transfer shall move the data into my array.

But something is wrong, I can sometimes see that the first command is executed by the ADC and the result moved back to the CTU FIFO, but after that all seems to stop and the ADC_OE and ERRCMP flags are set in the CTU.

Any tips on what has gone wrong in my code?

See below for my code, could not find a way of attaching it.

Best Regards Linus

#include "mpc55xx.h"

#include "pwm_driver.h"

/* ************************************************************************** *

* Global declarations                                                        *

* ************************************************************************** */

uint32_t ADC_results[16];

/**

* @brief setPwmDutyCycle

* @param chn1       unsigned value containing duty cycle in 0 to 1000 for channel 1

* @param chn2       unsigned value containing duty cycle in 0 to 1000 for channel 2

* @param chn3       unsigned value containing duty cycle in 0 to 1000 for channel 3

* @return boolean value, 1 = Success, 0 = Could not set duty

*

* @details The function is called when we need to set the duty cycle

*/

boolean Pwm_SetDutyCycle (uint16 chn1, uint16 chn2, uint16 chn3)

{

  if (chn1 > 950) chn1 = 950;

  if (chn1 < 50) chn1 = 50;

  if (chn2 > 950) chn2 = 950;

  if (chn2 < 50) chn2 = 50;

  if (chn3 > 950) chn3 = 950;

  if (chn3 < 50) chn3 = 50;

  if (FLEXPWM_0.MCTRL.B.LDOK == 0)

  {

  FLEXPWM_0.SUB[0].VAL[2].B.VAL = 5000 - (chn1*5);

  FLEXPWM_0.SUB[0].VAL[3].B.VAL = 5000 + (chn1*5);

  FLEXPWM_0.SUB[1].VAL[2].B.VAL = 5000 - (chn2*5);

  FLEXPWM_0.SUB[1].VAL[3].B.VAL = 5000 + (chn2*5);

  FLEXPWM_0.SUB[2].VAL[2].B.VAL = 5000 - (chn3*5);

  FLEXPWM_0.SUB[2].VAL[3].B.VAL = 5000 + (chn3*5);

  /* latch values into pwm modules */

  FLEXPWM_0.MCTRL.B.LDOK |= 7;

  return 1;

  } else

  {

  return 0;

  }

}

/**

* @brief pwm_Init

*

* @details The function is called to setup the pwm outputs for controlling the motor

*/

void pwm_Init(void)

{

  SIUL2.PCR[46].R = 0x30000000 | 0x02000000 | 0x2; // CTU0 External Trigger Output (on EVB it is PG[13])

  // clear LDOK to be able to modify register settings

  FLEXPWM_0.MCTRL.B.CLDOK |= 1 << 0;

  FLEXPWM_0.MCTRL.B.CLDOK |= 1 << 1;

  FLEXPWM_0.MCTRL.B.CLDOK |= 1 << 2;

  FLEXPWM_0.SUB[0].CTRL.B.PRSC = 5;

  FLEXPWM_0.SUB[1].CTRL.B.PRSC = 0;

  FLEXPWM_0.SUB[2].CTRL.B.PRSC = 0;

  FLEXPWM_0.SUB[0].CTRL2.B.RELOAD_SEL = 0;

  FLEXPWM_0.SUB[1].CTRL2.B.RELOAD_SEL = 1; /* RELOAD signal from submodule 0 is used to reload registers*/

  FLEXPWM_0.SUB[2].CTRL2.B.RELOAD_SEL = 1; /* RELOAD signal from submodule 0 is used to reload registers*/

  FLEXPWM_0.SUB[0].CTRL2.B.CLK_SEL = 0; /* The peripheral clock is used as the clock for the local prescaler and counter. */

  FLEXPWM_0.SUB[1].CTRL2.B.CLK_SEL = 2; /* Submodule 0's clock (AUX_CLK) is used as the source clock for the local prescaler and counter. */

  FLEXPWM_0.SUB[2].CTRL2.B.CLK_SEL = 2; /* Submodule 0's clock (AUX_CLK) is used as the source clock for the local prescaler and counter. */

// FLEXPWM_0.SUB[0].CTRL2.B.FORCE_SEL = 0; /* The peripheral clock is used as the clock for the local prescaler and counter. */

// FLEXPWM_0.SUB[1].CTRL2.B.FORCE_SEL = 1; /* Submodule 0's clock (AUX_CLK) is used as the source clock for the local prescaler and counter. */

// FLEXPWM_0.SUB[2].CTRL2.B.FORCE_SEL = 1; /* Submodule 0's clock (AUX_CLK) is used as the source clock for the local prescaler and counter. */

// FLEXPWM_0.SUB[0].CTRL2.B.INIT_SEL = 0; /* The peripheral clock is used as the clock for the local prescaler and counter. */

// FLEXPWM_0.SUB[1].CTRL2.B.INIT_SEL = 1; /* Submodule 0's clock (AUX_CLK) is used as the source clock for the local prescaler and counter. */

// FLEXPWM_0.SUB[2].CTRL2.B.INIT_SEL = 1; /* Submodule 0's clock (AUX_CLK) is used as the source clock for the local prescaler and counter. */

  FLEXPWM_0.SUB[0].DISMAP.R   = 0x0000; /* disable fault pin condition */

  FLEXPWM_0.SUB[1].DISMAP.R   = 0x0000; /* disable fault pin condition */

  FLEXPWM_0.SUB[2].DISMAP.R   = 0x0000; /* disable fault pin condition */

  FLEXPWM_0.SUB[0].INIT.B.INIT = 0;

  FLEXPWM_0.SUB[0].VAL[0].B.VAL = 20;

  FLEXPWM_0.SUB[0].VAL[1].B.VAL = 10000;

  FLEXPWM_0.SUB[0].VAL[2].B.VAL = 5000;

  FLEXPWM_0.SUB[0].VAL[3].B.VAL = 5000;

  FLEXPWM_0.SUB[0].TCTRL.B.OUT_TRIG_EN = 1; /* OUT_TRIG0 will set when the counter value matches the VAL0 value. */

  FLEXPWM_0.SUB[1].INIT.B.INIT = 0;

  FLEXPWM_0.SUB[1].VAL[0].B.VAL = 20;

  FLEXPWM_0.SUB[1].VAL[1].B.VAL = 10000;

  FLEXPWM_0.SUB[1].VAL[2].B.VAL = 5000;

  FLEXPWM_0.SUB[1].VAL[3].B.VAL = 5000;

  FLEXPWM_0.SUB[2].INIT.B.INIT = 0;

  FLEXPWM_0.SUB[2].VAL[0].B.VAL = 20;

  FLEXPWM_0.SUB[2].VAL[1].B.VAL = 10000;

  FLEXPWM_0.SUB[2].VAL[2].B.VAL = 5000;

  FLEXPWM_0.SUB[2].VAL[3].B.VAL = 5000;

/*

  FLEXPWM_0.SUB[0].DTCNT0.B.DTCNT0 = 0x0078;

  FLEXPWM_0.SUB[0].DTCNT1.B.DTCNT1 = 0x0078;

  FLEXPWM_0.SUB[1].DTCNT0.B.DTCNT0 = 0x0078;

  FLEXPWM_0.SUB[1].DTCNT1.B.DTCNT1 = 0x0078;

  FLEXPWM_0.SUB[2].DTCNT0.B.DTCNT0 = 0x0078;

  FLEXPWM_0.SUB[2].DTCNT1.B.DTCNT1 = 0x0078;

*/

  FLEXPWM_0.SUB[0].DTCNT0.B.DTCNT0 = 0x0;

  FLEXPWM_0.SUB[0].DTCNT1.B.DTCNT1 = 0x0;

  FLEXPWM_0.SUB[1].DTCNT0.B.DTCNT0 = 0x0;

  FLEXPWM_0.SUB[1].DTCNT1.B.DTCNT1 = 0x0;

  FLEXPWM_0.SUB[2].DTCNT0.B.DTCNT0 = 0x0;

  FLEXPWM_0.SUB[2].DTCNT1.B.DTCNT1 = 0x0;

  FLEXPWM_0.OUTEN.B.PWMA_EN |= 1 << 0;

  FLEXPWM_0.OUTEN.B.PWMA_EN |= 1 << 1;

  FLEXPWM_0.OUTEN.B.PWMA_EN |= 1 << 2;

  FLEXPWM_0.OUTEN.B.PWMB_EN |= 1 << 0;

  FLEXPWM_0.OUTEN.B.PWMB_EN |= 1 << 1;

  FLEXPWM_0.OUTEN.B.PWMB_EN |= 1 << 2;

  FLEXPWM_0.MCTRL.B.LDOK |= 1 << 0;

  FLEXPWM_0.MCTRL.B.LDOK |= 1 << 1;

  FLEXPWM_0.MCTRL.B.LDOK |= 1 << 2;

  FLEXPWM_0.MCTRL.B.RUN |= 1 << 0;

  FLEXPWM_0.MCTRL.B.RUN |= 1 << 1;

  FLEXPWM_0.MCTRL.B.RUN |= 1 << 2;

  /** enable pwm */

  Enable_pwm();

}

/***********************************************************************/

/* CTU_Init                                                            */

/***********************************************************************/

void CTU_Init (void)

{

  CTU_0.TGSISR.B.I1_RE = 0x1;   /* Select the MRS for CTU - PWM ch0 odd  - period 50usec */

  CTU_0.CR.B.TGSISR_RE = 0x1; /* TGS Input Selection Register Reload Enable */

  CTU_0.TGSCR.B.PRES = 0x4;     /* CTU prescaler is set to 1 */

  CTU_0.TCR[0].R = 0x10;         /* CTU Timer compare register 0 value */

  CTU_0.TGSCCR.R = 0xFFFF;      /* TGS Counter Compare Register */

  CTU_0.TGSCRR.R = 0;           /* TGS Counter Reload Register */

  CTU_0.TGSCR.B.TGS_M = 0;

  CTU_0.TGSCR.B.ET_TM = 0;

  CTU_0.THCR1.B.T0_E = 1;        /* Trigger 0 output enable */

  CTU_0.THCR1.B.T0_ADCE = 1;     /* Trigger 0 ADC Command output enable */

  CTU_0.CLCR1.B.T0_INDEX = 0;    /* Trigger 0 command list - first command address */

  //(*(volatile uint16_t *)0xFFE0C06C) = 1; /* CTU_0.FDCR = 1  - ebable DMA on FIFO (missing in header file!)*/

  CTU_0.FDCR.B.DE0 = 1;

  CTU_0.FCR.R = 0;              /* FIFO control register */

  /* CTU triggers ADC -  ADC command list */

  /* SU : ADC command list */

  //CTU_0.CLR[0].R = 14;  /* First command - CTU starts sending commands to ADC after this command */

  //CTU_0.CLR[0].A.B.CH = 5;     /* ADC_0 module, channel 11 */

  //CTU_0.CLR[0].B.B.CMS = 0;

  //CTU_0.CLR[0].B.B.LC = 1;

  CTU_0.CLR[0].B.B.CH_A = 11;     /* ADC_0 module, channel 11 */

  CTU_0.CLR[0].B.B.CH_B = 12;     /* ADC_1 module, channel 12 */

  CTU_0.CLR[0].B.B.CMS = 1;

  CTU_0.CLR[1].B.B.CH_A = 13;     /* ADC_0 module, channel 13 */

  CTU_0.CLR[1].B.B.CH_B = 1;      /* ADC_1 module, channel 1 */

  CTU_0.CLR[1].B.B.CMS = 1;

  //CTU_0.CLR[1].B.B.LC = 1;

  CTU_0.CLR[2].B.B.CH_A = 5;      /* ADC_0 module, channel 5 */

  CTU_0.CLR[2].B.B.CH_B = 0; /* ADC_1 module, channel 0 */

  CTU_0.CLR[2].B.B.CMS = 1;

  CTU_0.CLR[3].B.B.CH_A = 14;     /* ADC_0 module, channel 14 */

  CTU_0.CLR[3].B.B.CH_B = 2;      /* ADC_1 module, channel 2 */

  CTU_0.CLR[3].B.B.CMS = 1;

  CTU_0.CLR[4].B.B.CH_A = 10;     /* ADC_0 module, channel 10 */

  CTU_0.CLR[4].B.B.CH_B = 15;     /* ADC_1 module, channel 15 */

  CTU_0.CLR[4].B.B.CMS = 1;

  CTU_0.CLR[5].B.B.CH_A = 15;     /* ADC_0 module, channel 15 */

  CTU_0.CLR[5].B.B.CH_B = 10;     /* ADC_1 module, channel 10 */

  CTU_0.CLR[5].B.B.CMS = 1;

  CTU_0.CLR[6].A.R = 0x4000;   /* Last command - this command is not send to ADC */

  CTU_0.FTH.B.TH0 = 5;

  //CTU_0.FTH.B.TH0 = 5;

  //CTU_0.TH1.B.THRESHOLD0 = 0xE;        /* FIFO 0 Threshold. Maximum value of 15, as the threshold value must be less than the number of FIFO 0 entries. */

  //CTU_0.FCR.B.FIFO_OVERFLOW_EN0 = 1;  /* FIFO 0 threshold Overflow interrupt enable - read FIFO 0 in this interrupt */

  CTU_0.EFR.R = 0x0400; /*Clear flags before start */

  CTU_0.IFR.R = 0x01FE;

  CTU_0.CR.B.GRE = 1;              /* General Reload Enable */

}//CTU_Init

/***********************************************************************/

/* ADC_Init                                                            */

/***********************************************************************/

void ADC_Init (void)

{

  /* USE_ADC */

  ADC_0.MCR.B.PWDN = 0;      // Enable ADC0

    /* 1 */

  ADC_0.MCR.B.CTUEN = 1;     // CTU mode

    /* 2 */

  ADC_0.NCMR[0].R = 0xFFFF;  // ADC_0 channel 0

  ADC_0.MCR.B.MODE = 1;      // One-shot mode

  ADC_1.MCR.B.PWDN = 0;      // Enable ADC1

  /* 1 */

  ADC_1.MCR.B.CTUEN = 1;     // CTU mode

  /* 2 */

  ADC_1.NCMR[0].R = 0xFFFF;  // ADC_1 channel 0

  ADC_1.MCR.B.MODE = 1;      // One-shot mode

} //ADC_Init

/***********************************************************************/

/* DMA_Init                                                            */

/***********************************************************************/

void DMA_Init (void)

{

    DMA_0.CR.R   = 0x00000002; /* Enable debug mode */

  DMA_0.EEI.R = 0x0000; /* Error Interrupt disabled for all channels  */

  DMA_0.ERQ.B.ERQ0 = 1 << 2; /*Use channel 2 *//* Enable eDMA request 2 -> CTU FIFO_0 trigger */

}//DMA_Init

/***********************************************************************/

/* DMA_MUX_Init                                                        */

/***********************************************************************/

void DMA_MUX_Init(void)

{

  DMAMUX_0.CHCFG[2].R = 0x0000; /* Clear channel config register 2*/

  DMAMUX_0.CHCFG[2].B.SOURCE = 6; /* Select MUX source for channel 2 -> CTU FIFO_1 */

  DMAMUX_0.CHCFG[2].B.ENBL = 1; /* DMA Channel Enable */

}//DMA_MUX_Init

/***********************************************************************/

/* DMA_TCD_2                                                           */

/***********************************************************************/

void DMA_TCD_2(void)

{

    (*(volatile uint16 *)&DMA_0.TCD[2]) = 0x0; //Clear DMA.TCD[0]0.WORD7

    //DMA_0.TCD[2] = 0x0;

    DMA_0.TCD[2].SADDR.B.SADDR = &CTU_0.FR[0];  /* Source Address - CTU FIFO_0 */

    DMA_0.TCD[2].DADDR.B.DADDR = (uint32_t) &ADC_results[0];  /* Destination Address - SRAM */

  DMA_0.TCD[2].ATTR.B.SMOD = 0x0;   /* Source Address Modulo      */

    DMA_0.TCD[2].ATTR.B.DMOD = 0x0;   /* Destination Address Modulo */

    DMA_0.TCD[2].ATTR.B.SSIZE = 0x2;  /* Source Transfer Size: 32 bits*/

    DMA_0.TCD[2].ATTR.B.DSIZE = 0x2;  /* Destination Transfer Size: 32 bits*/

    DMA_0.TCD[2].SOFF.B.SOFF =  0x0;  /* Signed Source Addr Offset adjustment*/

    DMA_0.TCD[2].NBYTES.MLOFFNO.B.NBYTES = 0x40; /* Inner 'minor' byte count   */

    DMA_0.TCD[2].SLAST.B.SLAST = 0x0;  /* Last signed Source Address Adjust */

    DMA_0.TCD[2].DOFF.B.DOFF = 0x4;   /* Signed Destination Address Offset  */

    DMA_0.TCD[2].DLASTSGA.B.DLASTSGA = 0xFFFFFFC0; /* Signed Destination Address Offset -64  */

    DMA_0.TCD[2].BITER.ELINKNO.B.ELINK  = 0x0;  /* Channel-to-channel linking on Minor Loop Complete: Disabled*/

    DMA_0.TCD[2].BITER.ELINKNO.B.BITER  = 0x1;  /* Current Major Iteration Count or Link Channel Number  */

    DMA_0.TCD[2].CITER.ELINKYES.B.ELINK  = 0x0;  /* Channel-to-channel linking on Minor Loop Complete: Disabled*/

    DMA_0.TCD[2].CITER.ELINKYES.B.LINKCH  = 0x0;  /* Channel Number for Channel-to-Channel Linking on Minor Loop : Not Complete*/

    DMA_0.TCD[2].CITER.ELINKYES.B.ELINK  = 0x0001;  /* Current Major Iteration Count or Link Channel Number  */

    DMA_0.TCD[2].CSR.B.BWC  = 0x00;  /* Bandwidth control */

    DMA_0.TCD[2].CSR.B.MAJORLINKCH = 0x00;  /* Major Channel number */

    DMA_0.TCD[2].CSR.B.MAJORELINK  = 0x00;  /*Channel-to-channel Linking on Major Loop Complete: Disabled*/

    DMA_0.TCD[2].CSR.B.DONE  = 0x00;  /* Channel Done bit */

    DMA_0.TCD[2].CSR.B.ACTIVE = 0x00;  /* Channel Active bit */

    DMA_0.TCD[2].CSR.B.ESG  = 0x00;  /* Enable Scatter/Gather: Disabled*/

    DMA_0.TCD[2].CSR.B.DREQ   = 0x00;  /* Disable the DMA channel when Done: Disabled*/

    DMA_0.TCD[2].CSR.B.INTHALF   = 0x00;  /* Interrupt on Half Major Count completion: Disabled*/

    DMA_0.TCD[2].CSR.B.INTMAJOR = 0x01;  /* Interrupt on major loop completion: Disabled*/

    DMA_0.TCD[2].CSR.B.START = 0x00;  /* Explicit Channel Start bit  */

}//DMA_0

[Peter] – Hmm, the ADC_OE flag (ADC command generation Overrun Error) is set if an ADC command is issued when there is a command already being processed.

Seems to me, that you have a timing issue with CTU command list. You wrote “ I can sometimes see that the first command is executed by the ADC”. What does it means sometimes? It is when Duty cycle is changed or what is different when this situation happens.

Hi Linuxz

We do experience similar problem recently, have you solved this issue? May you give us some feedback about this issue? 

Thanks in advance.

Hi,

We experience the similar problem, too. Any recommend solutions?

Thanks a lot! 

No ratings
Version history
Last update:
‎01-20-2015 02:43 AM
Updated by: