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/TMS320F280049C: Constant Cycle assembly routine issue

Part Number: TMS320F280049C


Tool/software: Code Composer Studio

 Hello, 

    I need to produce a specific startup sequence on a PWM, so I am trying to create a simple assembly file that makes the waveform by forcing action qualifiers, then I free the lines and fire the PWM in counter UP mode.

    I located the routine in RAM memory for execution. I placed the function on a separate C file, and disabled optimizations. The issue I have is that 97% pecent of time it executes with a fixed number of cycles, but remaining three percent of time there are 9 extra cycles that are added and affects my timing. Could you kindly provide some light where this sporadic 9 cycles may be coming from?

    I am measuring by debugging session, I add a break point on the LCR instruction that calls the function, and run up to another breakpoint on the instruction just below the LCR. This routine is called with interrupts disabled, for that I am using _disable_interrupts(); / _enable_interrupts() directives:

void func Enable_PWM(){

_disable_interrupts(); 

    /* configure registers on PWM */

    /* ...  */

   /* perform start sequence */

  Pwm_StartSequence();

  /*  PWM is fired and running here, I do some other activities and I am done */

_enable_interrupts();

}

 

Thanks in advance and best regards,

Alberto Peyro

Here is the assembly code being called from C file above. Before this function, basically the PWM is set for forcing action qualifier, CNTR is loaded with start count of 40 out of a maximum of PRD= 285 (count up mode). Pwm_LLCMgr.h contains just some additional #define labels...  I am using compiler TI v16.9.4.LTS

    .def _Pwm_StartSequence

    .cdecls   C,LIST,"Pwm_LLCMgr.h"


TBCTL_reg		.set	0x00		;register offset
TBCTR_reg		.set	0x04		;register offset
AQSFRC_reg		.set	0x47		;register offset
AQCSFRC_reg	.set	0x49		;register offset
DBCTL_reg		.set	0x0C	;register offset
DBCTL2_reg		.set	0x0D	;register offset
DBRED_reg		.set	0x51		;register offset
DBFED_reg		.set	0x53		;register offset

Pulse_High_20percent1	.set 	57-2-1
Pulse_High_20percent2	.set 	57-2-1
Pulse_Low_30percent1	.set 	86-2-1
Pulse_Low_30percent2	.set 	4

OutA_Low_OutB_Low		.set	5
OutA_High_OutB_Low		.set	6
OutA_Low_OutB_High		.set	9

DisableSoftwareForcing	.set	0
EnableCountUP			.set	0xFFFC
LoadOnCNT_PRD			.set	0x0040
TwoCycleDelay			.set	2


      .sect ".TI.ramfunc"

_Pwm_StartSequence:

	;; set pointers to registers
	MOV		ACC,@AR4		;;pointer to TBCTL
	NOP
	NOP
	ADD		ACC,#DBCTL_reg
	MOVL	XAR5,ACC		;;pointer to DBCTL
	ADD		ACC,#(AQSFRC_reg-DBCTL_reg)
	MOVL	XAR6,ACC		;;pointer to AQSFRC
	ADD		ACC,#(AQCSFRC_reg-AQSFRC_reg)
	MOVL	XAR7,ACC		;;pointer to AQCSFRC
	MOV	ACC,@AR4		;;pointer to TBCTL
	RPT		#TwoCycleDelay || NOP
	ADD		ACC,#DBRED_reg
	MOVL	XAR1,ACC		;;pointer to DBRED
	RPT		#TwoCycleDelay || NOP

	MOV	ACC,@AR4		;;pointer to TBCTL
	RPT		#TwoCycleDelay || NOP
	ADD		ACC,#DBFED_reg
	MOVL	XAR2,ACC		;;pointer to DBFED
	RPT		#TwoCycleDelay || NOP

	;;set LOW
	MOV	   *+XAR7[0], #OutA_Low_OutB_Low
	RPT 	#TwoCycleDelay || NOP

        ;;20% pulse in A
	MOV	   *+XAR7[0], #OutA_High_OutB_Low
        RPT 	#Pulse_High_20percent1 || NOP
	MOV	   *+XAR7[0], #OutA_Low_OutB_Low

;;Wait 30% low RPT #Pulse_Low_30percent1 || NOP
;;20% pulse in B MOV *+XAR7[0], #OutA_Low_OutB_High RPT #Pulse_High_20percent2 || NOP MOV *+XAR7[0], #OutA_Low_OutB_Low EALLOW ;;Set DBCTL MOV *+XAR5[0], #DEADBAND_REG_PRE_DISABLE RPT #TwoCycleDelay || NOP MOV *+XAR7[0], #9 RPT #TwoCycleDelay || NOP MOV *+XAR5[0], #DEADBAND_REG_ENABLE RPT #TwoCycleDelay || NOP ;;free software forcing on period MOV *+XAR6[0], #LoadOnCNT_PRD RPT #TwoCycleDelay || NOP ;;disable software forcing MOV *+XAR7[0], #DisableSoftwareForcing RPT #TwoCycleDelay || NOP ;;fire counter / assume counter is freeze AND *+XAR4[0], #EnableCountUP RPT #TwoCycleDelay || NOP EDIS LRETR

  • Alberto,

    When you say "...I add a break point on the LCR instruction that calls the function...", which function do you mean?

    Enable_PWM() or Pwm_StartSequence()?

    If the former, interrupts will be enabled on entry so it's possible you may be taking an interrupt occasionally before the program reaches the line _disable_interrupts();  Same on exit. 

    I have your code running with interrupts fully disabled and I am not seeing any variation in execution time.  I am using a CPU timer to capture the cycle difference between two points in the code.  Something like this:

    volatile unsigned long t1, t2, td, tmax;

    ...

    t1 = CpuTimer0Regs.TIM.all;

    Enable_PWM();t2 = CpuTimer0Regs.TIM.all;

    td = t1 - t2;
    tmax = ((td > tmax) && (td < 1000)) ? td : tmax;

    Can you try this and let me know if you still see the variation?

    Regards,

    Richard

  • Hello Richard,

      Thanks after all for the prompt answer and support.  I meant the breakpoint is on the LCR Pwm_StartSequence()  opcode on the disassembly view, so I manually reset the cycle clock, I add another breakpoint on the instruction just below that LCR, and press resume so execution can continue all over the assembly routine. Then it is stopped again on the second breakpoint and I check the code composer cycle clock. There is where I see the sporadic 9 clock cycles. That is the way I am debugging this, what do you think?  I will try using the CPU counter which is a nice idea!

     In the mid time, I want to share with you a snapshot of the registers before  Pwm_StartSequence() and after  Pwm_StartSequence() so you can quickly check if there is something wrong. I will be out of the office tomorrow, but will be checking the forum.

      By the way there are two labels in the assembly code, that are on one of the header files included. These labels are:

    #define DEADBAND_REG_PRE_DISABLE                    (0x1C2B)
    #define DEADBAND_REG_ENABLE                         (0x0C2B)

    Thanks again and regards,

    Alberto Peyro

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

    PWM REGISTERS BEFORE Pwm_StartSequence()

    R EPwm1Regs_TBCTL 0x0000000F 0x8033
    R EPwm1Regs_TBCTL2 0x0000000F 0x0000
    R EPwm1Regs_TBCTR 0x0000000F 0x00FC
    R EPwm1Regs_TBSTS 0x0000000F 0x0000
    R EPwm1Regs_CMPCTL 0x0000000F 0x0000
    R EPwm1Regs_CMPCTL2 0x0000000F 0x0000
    R EPwm1Regs_DBCTL 0x0000000F 0x0000
    R EPwm1Regs_DBCTL2 0x0000000F 0x0000
    R EPwm1Regs_AQCTL 0x0000000F 0x0000
    R EPwm1Regs_AQTSRCSEL 0x0000000F 0x0000
    R EPwm1Regs_PCCTL 0x0000000F 0x0000
    R EPwm1Regs_HRCNFG 0x0000000F 0x0000
    R EPwm1Regs_HRPWR 0x0000000F 0x0000
    R EPwm1Regs_HRMSTEP 0x0000000F 0x0000
    R EPwm1Regs_HRCNFG2 0x0000000F 0x0000
    R EPwm1Regs_HRPCTL 0x0000000F 0x0001
    R EPwm1Regs_TRREM 0x0000000F 0x0000
    R EPwm1Regs_GLDCTL 0x0000000F 0x0000
    R EPwm1Regs_GLDCFG 0x0000000F 0x0000
    R EPwm1Regs_EPWMXLINK 0x0000000B 0x00000000
    R EPwm1Regs_AQCTLA 0x0000000F 0x0012
    R EPwm1Regs_AQCTLA2 0x0000000F 0x0000
    R EPwm1Regs_AQCTLB 0x0000000F 0x0012
    R EPwm1Regs_AQCTLB2 0x0000000F 0x0000
    R EPwm1Regs_AQSFRC 0x0000000F 0x00C0
    R EPwm1Regs_AQCSFRC 0x0000000F 0x0005
    R EPwm1Regs_DBREDHR 0x0000000F 0x0000
    R EPwm1Regs_DBRED 0x0000000F 0x0014
    R EPwm1Regs_DBFEDHR 0x0000000F 0x0000
    R EPwm1Regs_DBFED 0x0000000F 0x0014
    R EPwm1Regs_TBPHS 0x0000000B 0x00000000
    R EPwm1Regs_TBPRDHR 0x0000000F 0x0000
    R EPwm1Regs_TBPRD 0x0000000F 0x011D
    R EPwm1Regs_CMPA 0x0000000B 0x008E0000
    R EPwm1Regs_CMPB 0x0000000B 0x002F0000
    R EPwm1Regs_CMPC 0x0000000F 0x0014
    R EPwm1Regs_CMPD 0x0000000F 0x0014
    R EPwm1Regs_GLDCTL2 0x0000000F 0x0000
    R EPwm1Regs_TZSEL 0x0000000F 0x4000
    R EPwm1Regs_TZDCSEL 0x0000000F 0x0002
    R EPwm1Regs_TZCTL 0x0000000F 0x000F
    R EPwm1Regs_TZCTL2 0x0000000F 0x0000
    R EPwm1Regs_TZCTLDCA 0x0000000F 0x0000
    R EPwm1Regs_TZCTLDCB 0x0000000F 0x0000
    R EPwm1Regs_TZEINT 0x0000000F 0x0004
    R EPwm1Regs_TZFLG 0x0000000F 0x0009
    R EPwm1Regs_TZCBCFLG 0x0000000F 0x0000
    R EPwm1Regs_TZOSTFLG 0x0000000F 0x0040
    R EPwm1Regs_TZCLR 0x0000000F 0x0000
    R EPwm1Regs_TZCBCCLR 0x0000000F 0x0000
    R EPwm1Regs_TZOSTCLR 0x0000000F 0x0000
    R EPwm1Regs_TZFRC 0x0000000F 0x0000
    R EPwm1Regs_ETSEL 0x0000000F 0xCE20
    R EPwm1Regs_ETPS 0x0000000F 0x1100
    R EPwm1Regs_ETFLG 0x0000000F 0x000C
    R EPwm1Regs_ETCLR 0x0000000F 0x0000
    R EPwm1Regs_ETFRC 0x0000000F 0x0000
    R EPwm1Regs_ETINTPS 0x0000000F 0x0000
    R EPwm1Regs_ETSOCPS 0x0000000F 0x0000
    R EPwm1Regs_ETCNTINITCTL 0x0000000F 0x0000
    R EPwm1Regs_ETCNTINIT 0x0000000F 0x0000
    R EPwm1Regs_DCTRIPSEL 0x0000000F 0x000F
    R EPwm1Regs_DCACTL 0x0000000F 0x0000
    R EPwm1Regs_DCBCTL 0x0000000F 0x0000
    R EPwm1Regs_DCFCTL 0x0000000F 0x0000
    R EPwm1Regs_DCCAPCTL 0x0000000F 0x0000
    R EPwm1Regs_DCFOFFSET 0x0000000F 0x0000
    R EPwm1Regs_DCFOFFSETCNT 0x0000000F 0x0000
    R EPwm1Regs_DCFWINDOW 0x0000000F 0x0000
    R EPwm1Regs_DCFWINDOWCNT 0x0000000F 0x0000
    R EPwm1Regs_DCCAP 0x0000000F 0x0000
    R EPwm1Regs_DCAHTRIPSEL 0x0000000F 0x0008
    R EPwm1Regs_DCALTRIPSEL 0x0000000F 0x0000
    R EPwm1Regs_DCBHTRIPSEL 0x0000000F 0x0000
    R EPwm1Regs_DCBLTRIPSEL 0x0000000F 0x0000
    R EPwm1Regs_EPWMLOCK 0x0000000B 0x00000000

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

    PWM REGISTERS AFTER  Pwm_StartSequence()

    R EPwm1Regs_TBCTL 0x0000000F 0x8030
    R EPwm1Regs_TBCTL2 0x0000000F 0x0000
    R EPwm1Regs_TBCTR 0x0000000F 0x00EA
    R EPwm1Regs_TBSTS 0x0000000F 0x0001
    R EPwm1Regs_CMPCTL 0x0000000F 0x0000
    R EPwm1Regs_CMPCTL2 0x0000000F 0x0000
    R EPwm1Regs_DBCTL 0x0000000F 0x0C2B
    R EPwm1Regs_DBCTL2 0x0000000F 0x0000
    R EPwm1Regs_AQCTL 0x0000000F 0x0000
    R EPwm1Regs_AQTSRCSEL 0x0000000F 0x0000
    R EPwm1Regs_PCCTL 0x0000000F 0x0000
    R EPwm1Regs_HRCNFG 0x0000000F 0x0000
    R EPwm1Regs_HRPWR 0x0000000F 0x0000
    R EPwm1Regs_HRMSTEP 0x0000000F 0x0000
    R EPwm1Regs_HRCNFG2 0x0000000F 0x0000
    R EPwm1Regs_HRPCTL 0x0000000F 0x0001
    R EPwm1Regs_TRREM 0x0000000F 0x0000
    R EPwm1Regs_GLDCTL 0x0000000F 0x0000
    R EPwm1Regs_GLDCFG 0x0000000F 0x0000
    R EPwm1Regs_EPWMXLINK 0x0000000B 0x00000000
    R EPwm1Regs_AQCTLA 0x0000000F 0x0012
    R EPwm1Regs_AQCTLA2 0x0000000F 0x0000
    R EPwm1Regs_AQCTLB 0x0000000F 0x0012
    R EPwm1Regs_AQCTLB2 0x0000000F 0x0000
    R EPwm1Regs_AQSFRC 0x0000000F 0x0040
    R EPwm1Regs_AQCSFRC 0x0000000F 0x0000
    R EPwm1Regs_DBREDHR 0x0000000F 0x0000
    R EPwm1Regs_DBRED 0x0000000F 0x0014
    R EPwm1Regs_DBFEDHR 0x0000000F 0x0000
    R EPwm1Regs_DBFED 0x0000000F 0x0014
    R EPwm1Regs_TBPHS 0x0000000B 0x00000000
    R EPwm1Regs_TBPRDHR 0x0000000F 0x0000
    R EPwm1Regs_TBPRD 0x0000000F 0x011D
    R EPwm1Regs_CMPA 0x0000000B 0x008E0000
    R EPwm1Regs_CMPB 0x0000000B 0x002F0000
    R EPwm1Regs_CMPC 0x0000000F 0x0014
    R EPwm1Regs_CMPD 0x0000000F 0x0014
    R EPwm1Regs_GLDCTL2 0x0000000F 0x0000
    R EPwm1Regs_TZSEL 0x0000000F 0x4000
    R EPwm1Regs_TZDCSEL 0x0000000F 0x0002
    R EPwm1Regs_TZCTL 0x0000000F 0x000F
    R EPwm1Regs_TZCTL2 0x0000000F 0x0000
    R EPwm1Regs_TZCTLDCA 0x0000000F 0x0000
    R EPwm1Regs_TZCTLDCB 0x0000000F 0x0000
    R EPwm1Regs_TZEINT 0x0000000F 0x0004
    R EPwm1Regs_TZFLG 0x0000000F 0x0009
    R EPwm1Regs_TZCBCFLG 0x0000000F 0x0000
    R EPwm1Regs_TZOSTFLG 0x0000000F 0x0040
    R EPwm1Regs_TZCLR 0x0000000F 0x0000
    R EPwm1Regs_TZCBCCLR 0x0000000F 0x0000
    R EPwm1Regs_TZOSTCLR 0x0000000F 0x0000
    R EPwm1Regs_TZFRC 0x0000000F 0x0000
    R EPwm1Regs_ETSEL 0x0000000F 0xCE20
    R EPwm1Regs_ETPS 0x0000000F 0x1100
    R EPwm1Regs_ETFLG 0x0000000F 0x000C
    R EPwm1Regs_ETCLR 0x0000000F 0x0000
    R EPwm1Regs_ETFRC 0x0000000F 0x0000
    R EPwm1Regs_ETINTPS 0x0000000F 0x0000
    R EPwm1Regs_ETSOCPS 0x0000000F 0x0000
    R EPwm1Regs_ETCNTINITCTL 0x0000000F 0x0000
    R EPwm1Regs_ETCNTINIT 0x0000000F 0x0000
    R EPwm1Regs_DCTRIPSEL 0x0000000F 0x000F
    R EPwm1Regs_DCACTL 0x0000000F 0x0000
    R EPwm1Regs_DCBCTL 0x0000000F 0x0000
    R EPwm1Regs_DCFCTL 0x0000000F 0x0000
    R EPwm1Regs_DCCAPCTL 0x0000000F 0x0000
    R EPwm1Regs_DCFOFFSET 0x0000000F 0x0000
    R EPwm1Regs_DCFOFFSETCNT 0x0000000F 0x0000
    R EPwm1Regs_DCFWINDOW 0x0000000F 0x0000
    R EPwm1Regs_DCFWINDOWCNT 0x0000000F 0x0000
    R EPwm1Regs_DCCAP 0x0000000F 0x0000
    R EPwm1Regs_DCAHTRIPSEL 0x0000000F 0x0008
    R EPwm1Regs_DCALTRIPSEL 0x0000000F 0x0000
    R EPwm1Regs_DCBHTRIPSEL 0x0000000F 0x0000
    R EPwm1Regs_DCBLTRIPSEL 0x0000000F 0x0000
    R EPwm1Regs_EPWMLOCK 0x0000000B 0x00000000

  • Hello Alberto,

    Thank you for the DB register definitions - I had already assumed values just to get it running.

    I'm not seeing even one cycle variation over many millions of calls to the function. Perhaps it is stepping through with the debugger which is causing the difference, but I don't know what the mechanism could be. Anyway, please do try the CPU timer method and let me know how you get along. Register loads should not cause any difference in cycle count so I don't think the actual values are related to this issue.

    Regards,

    Richard
  • Alberto,

    It's probably not related to this issue, but I notice you have this in the assembly function:

    TwoCycleDelay .set 2
    ...
    RPT #TwoCycleDelay || NOP

    The RPT instruction executes the following instruction (N+1) times so this would actually take three cycles, not two. Just wanted to make you aware.

    Regards,

    Richard
  • Alberto,

    Just checking in - were you able to make progress using the CPU timer method?

    Regards,

    Richard
  • Hello Richard, thanks for your message. I already did and find no variations, so the issue should come from other part of the application. After doing some more research, I finally decided to use EPWM interrupt to produce different start up sequence shapes needed, and is working fine now. I gave nesting priority to this interrupt vector as well to prevent other interrupts jumping in.
  • Thanks for the support Richard!
  • Alberto,

    Glad to know you found the solution.  Thanks for letting us know.

    Regards,

    Richard