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.

CCS/TMS320F28379D: EPWM CTRMODE Initialization Problem

Part Number: TMS320F28379D
Other Parts Discussed in Thread: POWERSUITE, TIDM-1000

Tool/software: Code Composer Studio

Hi, I am writing the code by modifying the existing PowerSuite library.

However, although setupIH_PWM that sets CTRMODE was performed in the main statement as shown below, the CTRMODE of HIGH_FREQ_PWM4_BASE_IH(EPWM5) was initialized to EPWM_COUNTER_MODE_UP (0), not EPWM_COUNTER_MODE_UP_DOWN.

To solve this problem, I inserted EPWM_setTimeBaseCounterMode(HIGH_FREQ_PWM4_BASE_IH,EPWM_COUNTER_MODE_UP_DOWN); in Interrupt Statement.

But, I want to know why CTRMODE of HIGH_FREQ_PWM4_BASE_IH(EPWM5) wasn't initialized in main statement.
It has been confirmed that only HIGH_FREQ_PWM4_BASE_IH(EPWM5) is initialized as UP MODE, while the remaining PWM is initialized as it was initialized as UP DOWN MODE.

In addition, EPWM5 was operated well in another normal operating code. Therefore, it is judged that it is not a hardware problem.


void setupIH_PWM(uint32_t base1, uint32_t base2, uint32_t base3, uint16_t pwm_period_ticks, uint16_t pwm_period_ticks1)
{
    EPWM_setPeriodLoadMode(base1,EPWM_PERIOD_SHADOW_LOAD);
    EPWM_setTimeBasePeriod(base1,pwm_period_ticks1>>1);
    EPWM_setTimeBaseCounter(base1,0);
    EPWM_setPhaseShift(base1,0);
    EPWM_setTimeBaseCounterMode(base1,EPWM_COUNTER_MODE_UP_DOWN);
    EPWM_setClockPrescaler(base1,EPWM_CLOCK_DIVIDER_1,EPWM_HSCLOCK_DIVIDER_1);

    EPWM_setPeriodLoadMode(base3,EPWM_PERIOD_SHADOW_LOAD);
    EPWM_setTimeBasePeriod(base3,pwm_period_ticks>>1);
    EPWM_setTimeBaseCounter(base3,0);
    EPWM_setPhaseShift(base3,0);
    EPWM_setTimeBaseCounterMode(base3,EPWM_COUNTER_MODE_UP_DOWN);
    EPWM_setClockPrescaler(base3,EPWM_CLOCK_DIVIDER_1,EPWM_HSCLOCK_DIVIDER_1);

    EPWM_setCounterCompareShadowLoadMode(base1,EPWM_COUNTER_COMPARE_A,EPWM_COMP_LOAD_ON_CNTR_ZERO);
    EPWM_setCounterCompareShadowLoadMode(base1,EPWM_COUNTER_COMPARE_B,EPWM_COMP_LOAD_ON_CNTR_ZERO);

    // CTR = CMPA@UP , set to 1
    EPWM_setActionQualifierAction(base1, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
    EPWM_setActionQualifierAction(base1, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPB);

    EPWM_setActionQualifierAction(base1, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPB);
    EPWM_setActionQualifierAction(base1, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);
}



Interrupt Statement
if(GPIO_readPin(62) == 0)
    {
        DISABLE_AQ_SW_FRC(HIGH_FREQ_PWM4_BASE_IH);
        DISABLE_AQ_FRC(HIGH_FREQ_PWM4_BASE_IH);

        AQ_SW_FORCE_PWMxA_HIGH_PWMxB_LOW(HIGH_FREQ_PWM5_BASE_IH_FORCE);
        SINGLE_OUT_MODE(HIGH_FREQ_PWM4_BASE_IH);//DBCTL[OUT_MODE]=0


        Pwm_Duty_Frontend = 0.06;
        Pwm_Duty_Backend = 0.94;

        EPWM_setTimeBaseCounterMode(HIGH_FREQ_PWM4_BASE_IH,EPWM_COUNTER_MODE_UP_DOWN);
        EPWM_setTimeBasePeriod(HIGH_FREQ_PWM4_BASE_IH,IH_Switching_Period>>1);

        EPWM_setCounterCompareValue(HIGH_FREQ_PWM4_BASE_IH,
                                   EPWM_COUNTER_COMPARE_A,
                                   (uint32_t)((float32_t)IH_Switching_Period*Pwm_Duty_Frontend)>>1);
        EPWM_setCounterCompareValue(HIGH_FREQ_PWM4_BASE_IH,
                                    EPWM_COUNTER_COMPARE_B,
                                    (uint32_t)((float32_t)IH_Switching_Period*Pwm_Duty_Backend)>>1);

    }

The difference between a normal working code and a problematic code is the memory map. Memory map was modified due to the memory problem of code that had a problem.

MEMORY
{
PAGE 0 :
/* Program Memory */
/* Memory (RAM/FLASH) blocks can be moved to PAGE1 for data allocation */
/* BEGIN is used for the "boot to Flash" bootloader mode   */

   BEGIN           	: origin = 0x080000, length = 0x000002 //Flash begin origin:0x080000 RAM begin origin:0x000000
   RAMM0           	: origin = 0x000122, length = 0x0002DE

   RAMLS2LS3LS4LS5  : origin = 0x009000, length = 0x002000//100kHz,length 0x001000=4K*16, length 0x000800=2K*16, 0X002000=8K*16

   RAMD0            : origin = 0x00B000, length = 0x000800

   RAMGS0GS1GS2     : origin = 0x00C000, length = 0x003000//ramfunc(10kHz Interrupt) 12K*16

   RESET           	: origin = 0x3FFFC0, length = 0x000002
   
   /* Flash sectors */
   FLASHA           : origin = 0x080002, length = 0x001FFE	/* on-chip Flash */
   FLASHB           : origin = 0x082000, length = 0x002000	/* on-chip Flash */
   FLASHC           : origin = 0x084000, length = 0x002000	/* on-chip Flash */
   FLASHD           : origin = 0x086000, length = 0x002000	/* on-chip Flash */
   FLASHE           : origin = 0x088000, length = 0x008000	/* on-chip Flash */
   FLASHF           : origin = 0x090000, length = 0x008000	/* on-chip Flash */
   FLASHG           : origin = 0x098000, length = 0x008000	/* on-chip Flash */
   FLASHH           : origin = 0x0A0000, length = 0x008000	/* on-chip Flash */
   FLASHI           : origin = 0x0A8000, length = 0x008000	/* on-chip Flash */
   FLASHJ           : origin = 0x0B0000, length = 0x008000	/* on-chip Flash */
   FLASHK           : origin = 0x0B8000, length = 0x002000	/* on-chip Flash */
   FLASHL           : origin = 0x0BA000, length = 0x002000	/* on-chip Flash */
   FLASHM           : origin = 0x0BC000, length = 0x002000	/* on-chip Flash */
   FLASHN           : origin = 0x0BE000, length = 0x002000	/* on-chip Flash */   

PAGE 1 :
/* Data Memory */
/* Memory (RAM/FLASH) blocks can be moved to PAGE0 for program allocation */

   BOOT_RSVD       : origin = 0x000002, length = 0x000120

   RAMM1           : origin = 0x000400, length = 0x000400

   RAMLS0LS1       : origin = 0x008000, length = 0x001000

   RAMD1           : origin = 0x00B800, length = 0x000800

// RAMGS2      : origin = 0x00E000, length = 0x001000
   RAMGS3      : origin = 0x00F000, length = 0x001000
   RAMGS4      : origin = 0x010000, length = 0x001000
   RAMGS5GS6GS7GS8GS9      : origin = 0x011000, length = 0x005000
// RAMGS6      : origin = 0x012000, length = 0x001000
// RAMGS7      : origin = 0x013000, length = 0x001000
// RAMGS8      : origin = 0x014000, length = 0x001000
// RAMGS9      : origin = 0x015000, length = 0x001000
   RAMGS10     : origin = 0x016000, length = 0x001000
   RAMGS11     : origin = 0x017000, length = 0x001000
   RAMGS12     : origin = 0x018000, length = 0x001000
   RAMGS13     : origin = 0x019000, length = 0x001000
   RAMGS14     : origin = 0x01A000, length = 0x001000
   RAMGS15     : origin = 0x01B000, length = 0x001000

   
   CPU2TOCPU1RAM   : origin = 0x03F800, length = 0x000400
   CPU1TOCPU2RAM   : origin = 0x03FC00, length = 0x000400
}


SECTIONS
{//.cinit              : > FLASHB,.init_array              : > FLASHB,.text               : >> FLASHB|FLASHC|FLASHD|FLASHE
   /* Allocate program areas: */
   .cinit              : > FLASHB      PAGE = 0, ALIGN(4) 
   .init_array              : > FLASHB,     PAGE = 0, ALIGN(4)
   .text               : >> FLASHG PAGE = 0, ALIGN(4) 
   codestart           : > BEGIN       PAGE = 0, ALIGN(4)

   /* Allocate uninitalized data sections: */
   .stack              : > RAMM1        PAGE = 1
   .data               : > RAMM1        PAGE = 1
   .bss               : >> RAMGS5GS6GS7GS8GS9      PAGE = 1
   .sysmem            : > RAMGS3       PAGE = 1

   /* Initalized sections go in Flash */
   .const             : >> FLASHF | FLASHG | FLASHH      PAGE = 0, ALIGN(4) 
   .switch             : > FLASHB      PAGE = 0, ALIGN(4) 
   
   .reset              : > RESET,     PAGE = 0, TYPE = DSECT /* not used, */

   GROUP 
   {
       .TI.ramfunc
       {
       }
       ramfuncs //10kHz 인터럽트

   } LOAD = FLASHD,
	 RUN =  RAMGS0GS1GS2,//8K*16
	 LOAD_START(RamfuncsLoadStart),
	 LOAD_SIZE(RamfuncsLoadSize),
	 LOAD_END(RamfuncsLoadEnd),
	 RUN_START(RamfuncsRunStart),
	 RUN_SIZE(RamfuncsRunSize),
	 RUN_END(RamfuncsRunEnd),
	 PAGE = 0, ALIGN(4)



   
   /* The following section definitions are required when using the IPC API Drivers */ 
    GROUP : > CPU1TOCPU2RAM, PAGE = 1 //Dual Core Group
    {
        PUTBUFFER 
        PUTWRITEIDX 
        GETREADIDX 
    }
    
    GROUP : > CPU2TOCPU1RAM, PAGE = 1 //Dual Core Group
    {
        GETBUFFER :    TYPE = DSECT
        GETWRITEIDX :  TYPE = DSECT
        PUTREADIDX :   TYPE = DSECT
    }  
    
    SFRA_F32_Data		: > RAMGS3, ALIGN = 64, PAGE = 1

 	SFRA_Data		: > RAMGS3, ALIGN = 64, PAGE=1

 	FPUmathTables	: > RAMGS4, PAGE =1

   .scratchpad      : > RAMLS0LS1,           PAGE = 1
   .bss_cla         : > RAMLS0LS1,           PAGE = 1
   controlVariables : > RAMGS5GS6GS7GS8GS9,           PAGE = 1 

   .const_cla       :  LOAD = FLASHH,
                       RUN = RAMLS2LS3LS4LS5,
                       RUN_START(Cla1ConstRunStart),
                       LOAD_START(Cla1ConstLoadStart),
                       LOAD_SIZE(Cla1ConstLoadSize),
                       PAGE = 0

     GROUP
    {
        isrcodefuncs 
        dclfuncs
    }    LOAD = FLASHH,
         RUN =  RAMLS2LS3LS4LS5,
         LOAD_START(isrcodefuncsLoadStart),
         LOAD_SIZE(isrcodefuncsLoadSize),
         LOAD_END(isrcodefuncsLoadEnd),
         RUN_START(isrcodefuncsRunStart),
         RUN_SIZE(isrcodefuncsRunSize),
         RUN_END(isrcodefuncsRunEnd),
         PAGE = 0, ALIGN(4)

                       /* CLA specific sections */
    Cla1Prog        : LOAD = FLASHH,
                      RUN = RAMLS2LS3LS4LS5,
                      LOAD_START(Cla1ProgLoadStart),
                      RUN_START(Cla1ProgRunStart),
                      LOAD_SIZE(Cla1ProgLoadSize),
                      PAGE = 0, ALIGN(4)

    
}

/*
//===========================================================================
// End of file.
//===========================================================================
*/

Thank you.

 

  • Kyung, I will have a Power Suite expert look at this for you.

    Nima

  • Hi Kyung,

    Can you please suggest which example / reference design did you use as base for the modified code?

    Normally the PWM counter mode should not need to be modified in each ISR. It should be set in the initialization code.

    Han

  • Dear Han Zhang,

    I modified TIDM-1000 configuration.

    But I changed the initialization PWM code.

    Today, I found a problem in my code.

    In the interrupt statement, 

    SINGLE_OUT_MODE(HIGH_FREQ_PWM4_BASE_IH); was a problem.

    To set the out_mode of PWM, I used HWREGH(HIGH_FREQ_PWM4_BASE_IH + EPWM_CMPCTL_LOADMODE_S) in SINGLE_OUT_MODE(base).

    but, EPWM_TBCTL_CTRMODE_S is also same address with 0U as EPWM_CMPCTL_LOADMODE_S.

    I just wanted to change each register bit by using HWREGH().

    Is there a way to combine the existing method with the driver library?

    Driver library :  EPWM_setTimeBaseCounterMode(base1,EPWM_COUNTER_MODE_UP_DOWN);

    existing method : EPwm5Regs.TBCTL.bit.CTRMODE = 2;

    Thank you.

  • Hi,

    I am still confused about why you need to use your own code instead of using driverlib. Is there a bit that you cannot find a driverlib function?

    Yes, you can write your own function to setup each bit by using HWREGH. That should work with driverlib function. 

    Regards,

    Chen