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.

using HET as an event timer

Other Parts Discussed in Thread: HALCOGEN, TMS470MF06607

I'm looking to implement a software event timer within the TMS470M HET. I know this is like cracking a nut with a sledgehammer, but alas I've already got the RTI tied up on another job...

This is about as noddy as they come: my application code needs to periodically call StartTimer(ticks) or CancelTimer(), with the HET generating an interrupt when the timer fires. This is purely internal: no external IO needed.

Does anyone know of any example code which I can use to jump-start the development?

cheers

Mat

  • Mat,

    Couple questions ..

    1st - the RTI has 4 compare functions, so you can do something like implement 2 ticks of different rates plus 2 interval timers, or 1 tick / 3 interval timers, etc. etc. etc. with the RTI.

    Just want to confirm you've used up all the RTI compare resources when you say it's tied up because if not the simplest approach might be to use another RTI compare.

    2nd - if you have tied up the RTI, have you tried using the PWM tab in HalCoGen to generate your interval. This isn't ideal but it would work and give you some starting point from which you could further refine. Note that on the PWM Interrupts tab you can set an interrupt for the end of period, and you could use the APIs to enable and disable the PWM for starting and stopping this timer. The biggest downside is that it'd use a PIN but I think you could be sneaky and select one of the pins that isn't bonded out on the package so you're not using a real physical device pin. Or it might be helpful to see the PWM on the pin during debug...
  • Thanks Anthony.

    If I was developing this from scratch, then I could share the RTI across the application. Problem is that I've got a big chunk of code which was written in the belief the RTI was exclusive to it. Trying to find another solution that doesn't involve re-writing that code (no matter how much it may need it!)

    Using the PWM is an inspired idea. I've actually got plenty of spare I/O, so this isn't a problem.

    Unfortunately where things have fallen down is in the implementation and getting the interrupt to fire. I've setup the PWM in HALCoGen, enabled the HET interrupts, then use the following functions to act as timer:

    void evtTimerStart(uint32_t time_ms)
    {
    hetSIGNAL_t sig;
    sig.duty = 100;
    sig.period = (float64) time_ms * 1000.0;
    pwmSetSignal(pwm0, sig);
    pwmEnableNotification(pwm0, pwmEND_OF_PERIOD);
    pwmStart(pwm0);
    }
    //-----------------------------------------------------------------------------
    void evtTimerStop()
    {
    pwmStop(pwm0);
    }
    //-----------------------------------------------------------------------------
    void pwmNotification(uint32 pwm, uint32 notification)
    {
    FlagTimer = 1;
    }

    Unfortunately I never receive an interrupt. Do you know how mature the HALCoGen code is for the TMS470M? Sorry to ask but a lot of the other code is quite buggy, unfortunately the HET is very complex to spot any errors.

    Mat
  • Hi Mat,

    Have you checked the boxes in the  PWM Interrupts tab for the EO Duty or EO Period interupts on the PWM that you want to use for your timer interrupt?

     

  • Hi Antony,

    Yes, both Duty and Period are set, and pointing to High Level (using PWM0).

    Mat

    P.S. Apologies for the delay in responding.
  • Hi Mat,

    Looking back through some history - we had a bug in HalCoGen 3.05.00 and earlier for TMS470M but it's marked as fixed in version 3.0.7 as of 12/2013.

    The bug was that the control field of the MOV64 instructions that update the PWM PWCNT and BR instructions was not setting the correct bit for interrupt enable in the instruction.

    Maybe you can confirm that this isn't what's happening for you.

    I think if you halt the program somewhat after the call to pwmStart() --- you should let the code run long enough after this that a PWM period / duty is observed... then check the HET RAM with the debugger.
    This RAM begins at address 0xFF460000 on the TMS470MF06607 if that's the part you're using. If you're using a different TMS470M then we'd need to check the memory map in the datasheet...

    To generate an interrupt request, bit 0 of the control field of the PWCNT and BR instructions need to be set (for duty cycle and period interrupts respectively). I believe the way that the HET Program works is that these instructions are initially set with a value of 0 in the Interrupt enable but the update that occurs (MOV64 instruction initializes them). I think I started looking at this before the holiday and didn't see them set in code, but would be good if you can confirm you don't see the bits set in your hardware.
  • Hi Anthony,

    Please let me know if theres an easier way to view HET instruction disassembly, but in the mean time...

    Setup for both duty cycle and period interrupts to fire on PWM0. I enabled the pwmStart() then hit the break after about 1 second. This is enough time for an interrupt to supposedly fire. Disassembly reads:

    PWCNT:
    00002AE0 00102217 014133D7

    If I'm reading this right, then I need to look for bit 0 in the middle, control, field. This is set to 1 = OK

    Afraid I've not been able to locate the BR instruction: either in the memory disassembly nor HALCoGen generated instructions. But, following on from this is the DJZ command, which from what I can figure out enables the interrupt on the period countdown:

    DJZ:
    00003A40 00029006 00000000

    As you can see, bit 0 is set to 0, this looks suspect as I should have both interrupts enabled (but should stop the one above firing). Just for a quick test, I changed this bit to 1 in the initial setup code and now get permanently firing HET interrupts! It's not right still, but at least we can clarify the VIM and application software are correctly responding to interrupts!

    I think it confirms this is where the problem lies, just need to dig a little deeper to locate the cause. What do you think?

    Mat
  • Hi Mat,

    There isn't an easy way to *dis* assemble the HET program.

    {EDIT: Actually there is a disassembler in the HET IDE, but it works only after you have the program loaded into the simulator.  So at the moment this isn't useful until you have something that you can load into the simulator.   Which means having the source.  That's one reason why I'm starting below to try to reverse engineer the output back into source...  but its also more to get us something to simulate in HET IDE that corresponds to the HalCoGen black box driver...  you can answer a lot of questions with the simulator because of the visibility it gives }

    I've actually just been trying to convert the binary format that is embedded into the C source from the HalCoGen template back into something that we can simulate.

    This is being done for N2HET (not HET which you have on TMS470M) but I think it's probably similar enough

    that it's worth posting:  (caveat though this is a work in progress).

    - You are correct - it is a pair of PWCNT/DJZ instructions that create each PWM not a PWCNT/BR...

    - My understanding (may be imperfect) is that when interrupts are enabled, the INTENA bit in the MOV64 instruction down at labels BUF0_D and BUF0_P  will be where the interrupt is enabled, and not in the actual PWCNT or DJZ instruction.

    I'm not sure where the repetitive interrupt comes from.     Anyway please try setting the INTENA bit in the MOV64 instruction and see if that helps the code behave properly...

    PIN_PWM0	.equ	8
    INIT_PWM0_D	.equ	432
    INIT_PWM0_P	.equ	859
    		.asg    "PULSEHI", PWM0_POLARITY
    		.asg    "ON", PWM0_ENABLE
    		.asg    "OFF", PWM0_D_IRQ
    		.asg    "OFF", PWM0_P_IRQ
    
    PIN_PWM1	.equ    10
    INIT_PWM1_D	.equ	432
    INIT_PWM1_P	.equ	859
    		.asg    "PULSEHI", PWM1_POLARITY
    		.asg    "ON", PWM1_ENABLE
    		.asg    "OFF", PWM1_D_IRQ
    		.asg    "OFF", PWM1_P_IRQ
    
    PIN_PWM2        .equ    12
    INIT_PWM2_D	.equ	432
    INIT_PWM2_P	.equ	859
    		.asg    "PULSEHI", PWM2_POLARITY
    		.asg    "ON", PWM2_ENABLE
    		.asg    "OFF", PWM2_D_IRQ
    		.asg    "OFF", PWM2_P_IRQ
    
    PIN_PWM3	.equ    14
    INIT_PWM3_D	.equ	432
    INIT_PWM3_P	.equ	859
    		.asg    "PULSEHI", PWM3_POLARITY
    		.asg    "ON", PWM3_ENABLE
    		.asg    "OFF", PWM3_D_IRQ
    		.asg    "OFF", PWM3_P_IRQ
    
    PIN_PWM4        .equ    16
    INIT_PWM4_D	.equ	432
    INIT_PWM4_P	.equ	859
    		.asg    "PULSEHI", PWM4_POLARITY
    		.asg    "ON", PWM4_ENABLE
    		.asg    "OFF", PWM4_D_IRQ
    		.asg    "OFF", PWM4_P_IRQ
    
    PIN_PWM5	.equ    17
    INIT_PWM5_D	.equ	432
    INIT_PWM5_P	.equ	859
    		.asg    "PULSEHI", PWM5_POLARITY
    		.asg    "ON", PWM5_ENABLE
    		.asg    "OFF", PWM5_D_IRQ
    		.asg    "OFF", PWM5_P_IRQ
    
    PIN_PWM6        .equ    18
    INIT_PWM6_D	.equ	432
    INIT_PWM6_P	.equ	859
    		.asg    "PULSEHI", PWM6_POLARITY
    		.asg    "ON", PWM6_ENABLE
    		.asg    "OFF", PWM6_D_IRQ
    		.asg    "OFF", PWM6_P_IRQ
    
    PIN_PWM7	.equ    19
    INIT_PWM7_D	.equ	432
    INIT_PWM7_P	.equ	859
    		.asg    "PULSEHI", PWM7_POLARITY
    		.asg    "ON", PWM7_ENABLE
    		.asg    "OFF", PWM7_D_IRQ
    		.asg    "OFF", PWM7_P_IRQ
    
    PIN_EDGE0	.equ	9
    		.asg	"FALL", EDGE0_POLARITY
    		.asg    "OFF",  EDGE0_IRQ
    
    PIN_EDGE1	.equ    11
    		.asg	"FALL", EDGE1_POLARITY
    		.asg    "OFF",  EDGE1_IRQ
    
    PIN_EDGE2       .equ    13
    		.asg	"FALL", EDGE2_POLARITY
    		.asg    "OFF",  EDGE2_IRQ
    
    PIN_EDGE3	.equ    15
    		.asg	"FALL", EDGE3_POLARITY
    		.asg    "OFF",  EDGE3_IRQ
    
    PIN_EDGE4       .equ    20
    		.asg	"FALL", EDGE4_POLARITY
    		.asg    "OFF",  EDGE4_IRQ
    
    PIN_EDGE5	.equ    21
    		.asg	"FALL", EDGE5_POLARITY
    		.asg    "OFF",  EDGE5_IRQ
    
    PIN_EDGE6       .equ    22
    		.asg	"FALL", EDGE6_POLARITY
    		.asg    "OFF",  EDGE6_IRQ
    
    PIN_EDGE7	.equ    23
    		.asg	"FALL", EDGE7_POLARITY
    		.asg    "OFF",  EDGE7_IRQ
    
    PIN_CAP0	.equ	0
    PIN_CAP1	.equ	2
    PIN_CAP2	.equ    4
    PIN_CAP3	.equ    6
    PIN_CAP4	.equ    24
    PIN_CAP5	.equ    26
    PIN_CAP6	.equ    28
    PIN_CAP7	.equ    30
    
    PIN_CAP0_H	.equ	PIN_CAP0 + 1
    PIN_CAP1_H	.equ	PIN_CAP1 + 1
    PIN_CAP2_H	.equ	PIN_CAP2 + 1
    PIN_CAP3_H	.equ	PIN_CAP3 + 1
    PIN_CAP4_H	.equ	PIN_CAP4 + 1
    PIN_CAP5_H	.equ	PIN_CAP5 + 1
    PIN_CAP6_H	.equ	PIN_CAP6 + 1
    PIN_CAP7_H	.equ	PIN_CAP7 + 1
    
    
    START   CNT { reg=T,comp=EQ,max=0x1FFFFFF,data=0x1FFFFFF};
    
    PWM0_D   PWCNT { hr_lr=LOW,en_pin_action=OFF,pin=PIN_PWM0,action=PWM0_POLARITY,reg=NONE,irq=OFF,data=0};
    PWM0_P   DJZ { cond_addr=BUF0_D,reg=NONE};
    
    PWM1_D   PWCNT { hr_lr=LOW,en_pin_action=OFF,pin=PIN_PWM1,action=PWM1_POLARITY,,reg=NONE,irq=OFF,data=0};
    PWM1_P   DJZ { cond_addr=BUF1_D,reg=NONE};
    
    PWM2_D   PWCNT { hr_lr=LOW,en_pin_action=OFF,pin=PIN_PWM2,action=PWM2_POLARITY,,reg=NONE,irq=OFF,data=0};
    PWM2_P   DJZ { cond_addr=BUF2_D,reg=NONE};
    
    PWM3_D   PWCNT { hr_lr=LOW,en_pin_action=OFF,pin=PIN_PWM3,action=PWM3_POLARITY,,reg=NONE,irq=OFF,data=0};
    PWM3_P   DJZ { cond_addr=BUF3_D,reg=NONE};
    
    PWM4_D   PWCNT { hr_lr=LOW,en_pin_action=OFF,pin=PIN_PWM4,action=PWM4_POLARITY,,reg=NONE,irq=OFF,data=0};
    PWM4_P   DJZ { cond_addr=BUF4_D,reg=NONE};
    
    PWM5_D   PWCNT { hr_lr=LOW,en_pin_action=OFF,pin=PIN_PWM5,action=PWM5_POLARITY,,reg=NONE,irq=OFF,data=0};
    PWM5_P   DJZ { cond_addr=BUF5_D,reg=NONE};
    
    PWM6_D   PWCNT { hr_lr=LOW,en_pin_action=OFF,pin=PIN_PWM6,action=PWM6_POLARITY,,reg=NONE,irq=OFF,data=0};
    PWM6_P   DJZ { cond_addr=BUF6_D,reg=NONE};
    
    PWM7_D   PWCNT { hr_lr=LOW,en_pin_action=OFF,pin=PIN_PWM7,action=PWM7_POLARITY,,reg=NONE,irq=OFF,data=0};
    PWM7_P   DJZ { cond_addr=BUF7_D,reg=NONE};
    
    
    EDGE0   ECNT { pin=PIN_EDGE0, event=EDGE0_POLARITY,reg=NONE,irq=EDGE0_IRQ,data=0};
    EDGE1   ECNT { pin=PIN_EDGE1,event=EDGE1_POLARITY,reg=NONE,irq=EDGE1_IRQ,data=0};
    EDGE2   ECNT { pin=PIN_EDGE2,event=EDGE2_POLARITY,reg=NONE,irq=EDGE2_IRQ,data=0};
    EDGE3   ECNT { pin=PIN_EDGE3,event=EDGE3_POLARITY,reg=NONE,irq=EDGE3_IRQ,data=0};
    EDGE4   ECNT { pin=PIN_EDGE4,event=EDGE4_POLARITY,reg=NONE,irq=EDGE4_IRQ,data=0};
    EDGE5   ECNT { pin=PIN_EDGE5,event=EDGE5_POLARITY,reg=NONE,irq=EDGE5_IRQ,data=0};
    EDGE6   ECNT { pin=PIN_EDGE6,event=EDGE6_POLARITY,reg=NONE,irq=EDGE6_IRQ,data=0};
    EDGE7   ECNT { pin=PIN_EDGE7,event=EDGE7_POLARITY,reg=NONE,irq=EDGE7_IRQ,data=0};
    
    
    CAP0_D   PCNT { hr_lr=HIGH,type=FALL2RISE,pin=PIN_CAP0};
    CAP0_P   PCNT { hr_lr=HIGH,irq=OFF,type=FALL2FALL, pin=PIN_CAP0_H};
    
    CAP1_D   PCNT { hr_lr=HIGH,type=FALL2RISE,pin=PIN_CAP1};
    CAP1_P   PCNT { hr_lr=HIGH,irq=OFF,type=FALL2FALL, pin=PIN_CAP1_H};
    
    CAP2_D   PCNT { hr_lr=HIGH,type=FALL2RISE,pin=PIN_CAP2};
    CAP2_P   PCNT { hr_lr=HIGH,irq=OFF,type=FALL2FALL, pin=PIN_CAP2_H};
    
    CAP3_D   PCNT { hr_lr=HIGH,type=FALL2RISE,pin=PIN_CAP3};
    CAP3_P   PCNT { hr_lr=HIGH,irq=OFF,type=FALL2FALL, pin=PIN_CAP3_H};
    
    CAP4_D   PCNT { hr_lr=HIGH,type=FALL2RISE,pin=PIN_CAP4};
    CAP4_P   PCNT { hr_lr=HIGH,irq=OFF,type=FALL2FALL, pin=PIN_CAP4_H};
    
    CAP5_D   PCNT { hr_lr=HIGH,type=FALL2RISE,pin=PIN_CAP5};
    CAP5_P   PCNT { hr_lr=HIGH,irq=OFF,type=FALL2FALL, pin=PIN_CAP5_H};
    
    CAP6_D   PCNT { hr_lr=HIGH,type=FALL2RISE,pin=PIN_CAP6};
    CAP6_P   PCNT { hr_lr=HIGH,irq=OFF,type=FALL2FALL, pin=PIN_CAP6_H};
    
    CAP7_D   PCNT { hr_lr=HIGH,type=FALL2RISE,pin=PIN_CAP7};
    CAP7_P   PCNT { hr_lr=HIGH,irq=OFF,type=FALL2FALL, pin=PIN_CAP7_H, next=TSTMP};
    
    BUF0_D	MOV64 {remote=PWM0_D,comp_mode=ECMP,en_pin_action=PWM0_ENABLE, cond_addr=PWM0_P,pin=PIN_PWM0,action=PWM0_POLARITY,reg=NONE,irq=PWM0_D_IRQ,data=INIT_PWM0_D};
    BUF0_P  MOV64 {remote=PWM0_P,comp_mode=ECMP,en_pin_action=OFF,cond_addr=BUF0_D,reg=NONE,irq=PWM0_P_IRQ,data=INIT_PWM0_P,next=PWM1_D};
    
    BUF1_D	MOV64 {remote=PWM1_D,comp_mode=ECMP,en_pin_action=PWM1_ENABLE, cond_addr=PWM1_P,pin=PIN_PWM1,action=PWM1_POLARITY,reg=NONE,irq=PWM1_D_IRQ,data=INIT_PWM1_D};
    BUF1_P  MOV64 {remote=PWM1_P,comp_mode=ECMP,en_pin_action=OFF,cond_addr=BUF1_D,reg=NONE,irq=PWM1_P_IRQ,data=INIT_PWM1_P,next=PWM2_D};
    
    BUF2_D	MOV64 {remote=PWM2_D,comp_mode=ECMP,en_pin_action=PWM2_ENABLE, cond_addr=PWM2_P,pin=PIN_PWM2,action=PWM2_POLARITY,reg=NONE,irq=PWM2_D_IRQ,data=INIT_PWM2_D};
    BUF2_P  MOV64 {remote=PWM2_P,comp_mode=ECMP,en_pin_action=OFF,cond_addr=BUF2_D,reg=NONE,irq=PWM2_P_IRQ,data=INIT_PWM2_P,next=PWM3_D};
    
    BUF3_D	MOV64 {remote=PWM3_D,comp_mode=ECMP,en_pin_action=PWM3_ENABLE, cond_addr=PWM3_P,pin=PIN_PWM3,action=PWM3_POLARITY,reg=NONE,irq=PWM3_D_IRQ,data=INIT_PWM3_D};
    BUF3_P  MOV64 {remote=PWM3_P,comp_mode=ECMP,en_pin_action=OFF,cond_addr=BUF3_D,reg=NONE,irq=PWM3_P_IRQ,data=INIT_PWM3_P,next=PWM4_D};
    
    BUF4_D	MOV64 {remote=PWM4_D,comp_mode=ECMP,en_pin_action=PWM4_ENABLE, cond_addr=PWM4_P,pin=PIN_PWM4,action=PWM4_POLARITY,reg=NONE,irq=PWM4_D_IRQ,data=INIT_PWM4_D};
    BUF4_P  MOV64 {remote=PWM4_P,comp_mode=ECMP,en_pin_action=OFF,cond_addr=BUF4_D,reg=NONE,irq=PWM4_P_IRQ,data=INIT_PWM4_P,next=PWM5_D};
    
    BUF5_D	MOV64 {remote=PWM5_D,comp_mode=ECMP,en_pin_action=PWM5_ENABLE, cond_addr=PWM5_P,pin=PIN_PWM5,action=PWM5_POLARITY,reg=NONE,irq=PWM5_D_IRQ,data=INIT_PWM5_D};
    BUF5_P  MOV64 {remote=PWM5_P,comp_mode=ECMP,en_pin_action=OFF,cond_addr=BUF5_D,reg=NONE,irq=PWM5_P_IRQ,data=INIT_PWM5_P,next=PWM6_D};
    
    BUF6_D	MOV64 {remote=PWM6_D,comp_mode=ECMP,en_pin_action=PWM6_ENABLE, cond_addr=PWM6_P,pin=PIN_PWM6,action=PWM6_POLARITY,reg=NONE,irq=PWM6_D_IRQ,data=INIT_PWM6_D};
    BUF6_P  MOV64 {remote=PWM6_P,comp_mode=ECMP,en_pin_action=OFF,cond_addr=BUF6_D,reg=NONE,irq=PWM6_P_IRQ,data=INIT_PWM6_P,next=PWM7_D};
    
    BUF7_D	MOV64 {remote=PWM7_D,comp_mode=ECMP,en_pin_action=PWM7_ENABLE, cond_addr=PWM7_P,pin=PIN_PWM7,action=PWM7_POLARITY,reg=NONE,irq=PWM7_D_IRQ,data=INIT_PWM7_D};
    BUF7_P  MOV64 {remote=PWM7_P,comp_mode=ECMP,en_pin_action=OFF,cond_addr=BUF7_D,reg=NONE,irq=PWM7_P_IRQ,data=INIT_PWM7_P,next=EDGE0};
    
    TSTMP   WCAP { next=START,cond_addr=START,pin=0,event=NOCOND,reg=T,data=0};
    

  • Hi Anthony,

    Afraid this one's already set. If you look in the het.c source, the following code is present:

     

       /* MOV64: PWM 0 -> Duty Cycle Update
        *         - Instruction                  = 41
        *         - Next instruction             = 42
        *         - Conditional next instruction = 2
        *         - Interrupt                    = 1
        *         - Pin                          = 4
        */
        {
            /* Program */
            0x0002A101U,
            /* Control */
            (0x00002006U | (0x00000001U) | (1U << 20U) | (4U << 7U) | (3U << 3U)),
            /* Data */
            32000032U,
    		/* Reserved */
    		0x00000000U
        },
        /* MOV64: PWM 0 -> Period Update
        *         - Instruction                  = 42
        *         - Next instruction             = 3
        *         - Conditional next instruction = 41
        *         - Interrupt                    = 2
        *         - Pin                          = na
        */
        {
            /* Program */
            0x00003102U,
            /* Control */
            (0x00029006U | 0x00000001U),
            /* Data */
            127999968U,
    		/* Reserved */
    		0x00000000U
        },

    This is confirmed from the disassembly:

    0002A101 00102217 014133F7 00000000
    00003102 00029007 01D08FE0 00000000

    Will carry on hunting...

     

    Mat