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.

PWM generation and readback using N2HET

Other Parts Discussed in Thread: HALCOGEN

Hello,

I am using TI570LS0432 controller.

I have been able to generate PWM signal of 1KHz using NHET instructions CNT and MCMP on NHET[31].

Now, i want to readback the same generated signal from another NHET[22] in below manner:

1. I have used one PCNT instruction with hr_lr = 0 (HIGH) for reading the ON-PULSE(i.e.type=01'b) of the signal on pin NHET[22].

2. Another PCNT instruction with hr_lr = 1 (LOW) for reading the count period between HIGH-to-HIGH edge (i.e.type=11'b) of the signal on pin NHET[22+1]. Taken reference from HALCOGEN

My Query:

1. Does it mean - that to read ON-time and PERIOD from NHET[22], an internal HR Share will be used of  NHET[23] (input type) too. And in practical NHET[23] could still be used for GPIO purpose.

2. I want to configure the HETINTENAS register for PCNT based interrupt generation on NHET[22]. Could anyone explain the exact bit meaning of HETINTENAS in case of above stated example.

I will really be thankful if my query could be addressed.

Regards,

Rahul

  • Rahul,

    Rahul Joshi said:
    1. Does it mean - that to read ON-time and PERIOD from NHET[22], an internal HR Share will be used of  NHET[23] (input type) too. And in practical NHET[23] could still be used for GPIO purpose.

    Yes this is right.  You do need to program the HETHRSH register to enable HR sharing of inputs though.  Its' not automatic.   Also I should caution you that while the TRM says that PCNT can be used twice on the same pin, once in HR mode and once in LR mode - there is an errata on this and it's actually not true on current silicon.  If you try it you'll get corrupt results at the HR level for both measurements.   But that applies to trying to use PCNT twice on pin 22.  You're good if you use one PCNT on 22 and one PCNT on 23 in the HRSHARE mode.  That works.

    Rahul Joshi said:
    2. I want to configure the HETINTENAS register for PCNT based interrupt generation on NHET[22]. Could anyone explain the exact bit meaning of HETINTENAS in case of above stated example.

    The PCNT instruction has a field (irq=OFF|ON) that you can set to generate an IRQ request when the 'specified capture edge [is] detected on selected pin'  (See the psuedo-code for PCNT in the TRM).
     
    The N2HET has 32 different interrupt levels internally that can be enabled / disabled and these are mapped to two different levels of the CPU's interrupt controller (high or low priority).

    The 32 different internal levels are mapped to the address of instructions in the HET RAM.

    So let's say that the PCNT which you use to generate interrupts (IRQ=ON) is at HET RAM address 0x24.
    In this example - the PCNT being at address 0x24 means that the interrupt channel used will be on internal channel 4 (address modulo 32 or 0x20).   So to enable the PCNT to generate an IRQ out of the module you also need to enable channel 4 in HETINTENAS and you should probably refrain from putting an interrupt generating instruction at address 0x04 or 0x44 etc. unless you want aliasing for some reason.
     
    This sounds awkward and at some level it is, but you can take all your interrupt generating instructions and put them in one place - for example the first 32 instructions of your HET program - so they dont' move when you add/remove instructions.

    The HET has a 'next' address field in every instruction, so there is no need for a HET program to actually execute linearly through the address space.  You can use this feature to keep your interrupt generating instructions in a stable location and at a stable channel # inside the HET.
     
  • I am using HALCOgen code, and configured it to generate PWM signal of 1KHz with 50% duty cycle and hr=(/1) and lr=(/64) settings. Such configured PWM signal is made to generate at NHET[31]. And it is working fine.

    Now, i have used CAP0 module at NHET[22] with HRSHARE=Set at bit.11 (i.e.NHET[22] HR structure will be used for PWM duty read and NHET[23] HR structure will be used for PWM period read).

    So, in NHET RAM, - following instructions were used to read PWM signal

    1. PCNT instruction (to read PWM Duty) at NHET Add.25 - Without Interrupt, Without Auto-Read Clear Data field, With Type-Select as 0x01 i.e. RISE-2-FALL pulse

    2. PCNT instruction (to read PWM Period) at NHET Add.26 - Without Interrupt, Without Auto-Read Clear Data field, With Type-select as 0x01 i.e. RISE-2-FALL pulse

    It is observed that HALCo provided function "capGetSignal( )" captures Data-field of this two PCNT instruction.

    HALCO-specific - HET Queries:

    1. How can two PCNT instruction give different Data-field value even though both are configured for same TYPE-select i.e.0x01 (RISE-2-FALL - pulse)?


    2. I have tried to enable AUTO-READ Clear Data-field feature for both PCNT instruction, and during debug - i can see that while debugging function "capGetSignal( )" - the moment i read Data-field of PCNT instruction, the Data field does not clear. Surprising.....


    3. I have tried to enable interrupt for both PCNT instruction - each instruction with same TYPE-select (ie.0x01), and written ISR for this. ISR is working but only for one PCNT instuction located at NHET address 26 (i.e.period). It is not working for NHET address.25 (i.e.duty).

    --------------------------------------------------------------------------------------------------------------------------------------------------------

    I have written my way of generating PWM (not used HALCO code - instead used CNT, MCMP, MOV64) and read the PWM (using two PCNT instuction with different TYPE-selects (RISE-2-FALL pulse and FALL-2-FALLL period) using Interrupt method.


    PWM is generating correctly. And My ISR is also executing for both PCNT instruction with AUTO-READ Clear Data feature. Query: In my case, Problem statement is - to catch interrupt and execute ISR, i have re-apply PWM signal every time (i.e.manually remove and apply again). Don't know what could be the reason behind. PWM signal keeps on generating correctly with proper edges.


    Please assist. If required i could share my NHET instructions and configurations.

  • Rahul,

    You can't have 2 different PCNT checking the same pin.  I suspect this is why you are seeing most of the issues.

    Not sure about your PWM generation and why you need to reapply (I assume this is with the CPU) the input.  Probably I need more details on this - but certainly the N2HET is capable of generating PWMs that auto update and can even ramp it's own frequency or duty cycle without any CPU intervention.  So I think this just an issue in understanding what the instructions do - don't worry you should get through this with a little more work.

    The AUTO-READ Clear applies to the CPU reading data from the N2HET RAM, not one instruction in the N2HET reading another instruction's ram.  And it may be blocked by debugger reads - I'd need to check this - but we have a signal to differentiate between a read from the debugger and a read from the CPU running code -- most peripherals will use this to disable the 'read-clear' type side-effect feature so that you don't distrurb the peripehral when inspecting it through the debugger.  This means you would need to step over an instruction that actually reads the RAM of the HET in order to see the read clear.

    Also the HET defaults to keep running when you break the CPU.  So it may be hard to see the read clear because by the time the screen refreshes and updates the HET memory window, the HET likely will have written new data to that address.  You need to be careful about how you run this experiment if you want to actually observe the read-clear.

  • Hello Anthony....First i would thanks for your continued support.

    Let me again put all things in simple & categorized way. I have attached my code which does following things:

    1. Generated PWM of 1KHz with 50% duty-cycle (HR_Resolution = Disable) at NHET[31]

    2. Read PWM signal: Used two PCNT instruction - each to capture Duty and Period from respective NHET[22] and NHET[23]. Additional configurations: HR_Resolution = Enable, AUTO-READ-CLEAR = Enable, HR_SHARE = Enable, Interrupts (Duty & Period): Enabled


    3. And in ISR, User-Code is reading HETOFF1 to identify the source interrupt and reading respective PCNT instruction followed by AUTO-CLEAR the Data field of the same PCNT instruction. And insuring that respective HETFLAG bit is cleared on successful interrupt service.

    ========================== ATTACHMENT: NHET SOURCE ==================================

    static const hetINSTRUCTION_t het1PROGRAM[6U] =
    {
    /* CNT: Timebase 0 (Timer)
    * - Instruction = 0
    * - Next instruction = 1
    * - Conditional next instruction = na
    * - Interrupt = OFF
    * - Pin = na
    * - Reg = T
    */
    {
    /* Program */
    0x00002C80U,
    /* Control */
    0x0000000U | (0x04E1), // for 1ms cnt timer - lr: /64 and hr: /1
    /* Data */
    0x00000000U,
    /* Reserved */
    0x00000000U,
    },

    /* MCMP: PWM 0 -> 50% Duty Cycle

    * - Instruction = 1
    * - Next instruction = 3
    * - Conditional next instruction = 2
    * - Interrupt = ON
    * - Pin = 31
    * - Reg = T
    */
    {
    /* Program : | NEXT ADD | HR_LR */
    (0x00000000U | (0U << 13U) | (1U << 8U)),
    /* Control :| EN_PIN | CONDL ADD | PIN_SELECT | PIN_ACTION | INT_EN */
    (0x00000044U | (1U << 22U) | (2U << 13U) | (31U << 8U) | (3U << 3U) | (1U << 0U)), // If Reg >= Data -> Z-flag set \\ PULSE-HIGH pin action
    /* Data */
    0x00013880U, // HR-Delay=0 and LR Delay = (1000us/800ns i.e.1250) * 0.5 = 625'd * 800 ns = 500 us i.e.50% of 1ms
    /* Reserved */
    0x00000000U
    },

    /* MOV64: PWM 0 -> Duty Cycle Update
    * - Instruction = 2
    * - Next instruction = 3
    * - Remote Address = 1
    * - Conditional next instruction = 2
    * - Interrupt = ON
    * - Pin = 31
    */
    {
    /* Program : | Next Add | Reserved | Remote Add */
    (0x00000000U | (3U << 13U) | (1U << 9U) | (1U << 0U) ),
    /* Control :| EN_PIN | CONDL ADD | PIN_SELECT | PIN_ACTION | INT_EN */
    (0x00000044U | (1U << 22U) | (2U << 13U) | (31U << 8U) | (3U << 3U) | (1U << 0U)), // If Reg >= Data -> Z-flag set \\ PULSE-HIGH pin action
    /* Data */
    0x00013880U, // HR-Delay=0 and LR Delay = (1000us/800ns i.e.1250) * 0.5 = 625'd * 800 ns = 500 us i.e.50% of 1ms
    /* Reserved */
    0x00000000U
    },

    /* PCNT: Capture Duty 0 (count high pulse i.e.rise-to-fall pulse)
    * - Instruction = 3
    * - Next instruction = 4
    * - Conditional next instruction = na
    * - Interrupt = na
    * - Pin = 22
    */
    {
    /* Program : Next Add | RESERVED | INT-ENABLE | TYPE-SELECT | Hr_Lr | PIN-SELECT */
    0x00000000U | (4U << 13U) | (7U << 9U) | (0U << 8U) | (1U << 6U) | (0U << 5U) | (22U << 0U),
    /* Control : CONTROL: AUTOREAD-CLEAR */
    0x00000000U | (1U << 26U),
    /* Data */
    0x00000000U,
    /* Reserved */
    0x00000000U
    },

    /* PCNT: Capture Period 0 (consecutive falling edges)
    * - Instruction = 4
    * - Next instruction = 5
    * - Conditional next instruction = na
    * - Interrupt = na
    * - Pin = 22 +1
    */
    {
    /* Program : Next Add | RESERVED | INT-ENABLE | TYPE-SELECT | Hr_Lr | PIN-SELECT */
    0x00000000U | (5U << 13U) | (7U << 9U) | (0U << 8U) | (2U << 6U) | (0U << 5U) | (23U << 0U),
    /* Control : AUTOREAD-CLEAR */
    0x00000000U | (1U << 26U),
    /* Data */
    0x00000000U,
    /* Reserved */
    0x00000000U
    },

    /* WCAP: Capture timestamp
    * - Instruction = 5
    * - Next instruction = 0
    * - Conditional next instruction = 0
    * - Interrupt = na
    * - Pin = na
    * - Reg = T
    */
    {
    /* Program */
    0x00001600U,
    /* Control */
    (0x00000004U),
    /* Data */
    0x00000000U,
    /* Reserved */
    0x00000000U
    }
    };

    I could see that AUTO_READ Clear feature is working fine in my case. Able to generate PWM signal.

    And also able to read the PWM signal provided i have to remove and reconnect the jumper from one NHET[31] to NHET[22].

    In case of HALCO code, if i write ISR to read PWM signal then i am not sure if my Captured Data is updated since AUTO-READ CLEAR is not getting enabled even if enable it explicitly in instruction.

    Let me know if my point is understood and have a look over my source. Correct me if something wrong i have kept in NHET source.

  • Rahul Joshi said:

    Hello Anthony....First i would thanks for your continued support.

    Let me again put all things in simple & categorized way. I have attached my code which does following things:

    1. Generated PWM of 1KHz with 50% duty-cycle (HR_Resolution = Disable) at NHET[31]

    2. Read PWM signal: Used two PCNT instruction - each to capture Duty and Period from respective NHET[22] and NHET[23]. Additional configurations: HR_Resolution = Enable, AUTO-READ-CLEAR = Enable, HR_SHARE = Enable, Interrupts (Duty & Period): Enabled


    3. And in ISR, User-Code is reading HETOFF1 to identify the source interrupt and reading respective PCNT instruction followed by AUTO-CLEAR the Data field of the same PCNT instruction. And insuring that respective HETFLAG bit is cleared on successful interrupt service.

    ========================== ATTACHMENT: NHET SOURCE ==================================

    static const hetINSTRUCTION_t het1PROGRAM[6U] =
    {
    /* CNT: Timebase 0 (Timer)
    * - Instruction = 0
    * - Next instruction = 1
    * - Conditional next instruction = na
    * - Interrupt = OFF
    * - Pin = na
    * - Reg = T
    */
    {
    /* Program */
    0x00002C80U,
    /* Control */
    0x0000000U | (0x04E1), // for 1ms cnt timer - lr: /64 and hr: /1
    /* Data */
    0x00000000U,
    /* Reserved */
    0x00000000U,
    },

    /* MCMP: PWM 0 -> 50% Duty Cycle

    * - Instruction = 1
    * - Next instruction = 3
    * - Conditional next instruction = 2
    * - Interrupt = ON
    * - Pin = 31
    * - Reg = T
    */
    {
    /* Program : | NEXT ADD | HR_LR */
    (0x00000000U | (0U << 13U) | (1U << 8U)),
    /* Control :| EN_PIN | CONDL ADD | PIN_SELECT | PIN_ACTION | INT_EN */
    (0x00000044U | (1U << 22U) | (2U << 13U) | (31U << 8U) | (3U << 3U) | (1U << 0U)), // If Reg >= Data -> Z-flag set \\ PULSE-HIGH pin action
    /* Data */
    0x00013880U, // HR-Delay=0 and LR Delay = (1000us/800ns i.e.1250) * 0.5 = 625'd * 800 ns = 500 us i.e.50% of 1ms
    /* Reserved */
    0x00000000U
    },

    /* MOV64: PWM 0 -> Duty Cycle Update
    * - Instruction = 2
    * - Next instruction = 3
    * - Remote Address = 1
    * - Conditional next instruction = 2
    * - Interrupt = ON
    * - Pin = 31
    */
    {
    /* Program : | Next Add | Reserved | Remote Add */
    (0x00000000U | (3U << 13U) | (1U << 9U) | (1U << 0U) ),
    /* Control :| EN_PIN | CONDL ADD | PIN_SELECT | PIN_ACTION | INT_EN */
    (0x00000044U | (1U << 22U) | (2U << 13U) | (31U << 8U) | (3U << 3U) | (1U << 0U)), // If Reg >= Data -> Z-flag set \\ PULSE-HIGH pin action
    /* Data */
    0x00013880U, // HR-Delay=0 and LR Delay = (1000us/800ns i.e.1250) * 0.5 = 625'd * 800 ns = 500 us i.e.50% of 1ms
    /* Reserved */
    0x00000000U
    },

    /* PCNT: Capture Duty 0 (count high pulse i.e.rise-to-fall pulse)
    * - Instruction = 3
    * - Next instruction = 4
    * - Conditional next instruction = na
    * - Interrupt = na
    * - Pin = 22
    */
    {
    /* Program : Next Add | RESERVED | INT-ENABLE | TYPE-SELECT | Hr_Lr | PIN-SELECT */
    0x00000000U | (4U << 13U) | (7U << 9U) | (0U << 8U) | (1U << 6U) | (0U << 5U) | (22U << 0U),
    /* Control : CONTROL: AUTOREAD-CLEAR */
    0x00000000U | (1U << 26U),
    /* Data */
    0x00000000U,
    /* Reserved */
    0x00000000U
    },

    /* PCNT: Capture Period 0 (consecutive falling edges)
    * - Instruction = 4
    * - Next instruction = 5
    * - Conditional next instruction = na
    * - Interrupt = na
    * - Pin = 22 +1
    */
    {
    /* Program : Next Add | RESERVED | INT-ENABLE | TYPE-SELECT | Hr_Lr | PIN-SELECT */
    0x00000000U | (5U << 13U) | (7U << 9U) | (0U << 8U) | (2U << 6U) | (0U << 5U) | (23U << 0U),
    /* Control : AUTOREAD-CLEAR */
    0x00000000U | (1U << 26U),
    /* Data */
    0x00000000U,
    /* Reserved */
    0x00000000U
    },

    /* WCAP: Capture timestamp
    * - Instruction = 5
    * - Next instruction = 0
    * - Conditional next instruction = 0
    * - Interrupt = na
    * - Pin = na
    * - Reg = T
    */
    {
    /* Program */
    0x00001600U,
    /* Control */
    (0x00000004U),
    /* Data */
    0x00000000U,
    /* Reserved */
    0x00000000U
    }
    };

    I could see that AUTO_READ Clear feature is working fine in my case. Able to generate PWM signal.

    And also able to read the PWM signal provided i have to remove and reconnect the jumper from one NHET[31] to NHET[22].

    In case of HALCO code, if i write ISR to read PWM signal then i am not sure if my Captured Data is updated since AUTO-READ CLEAR is not getting enabled even if enable it explicitly in instruction.

    Let me know if my point is understood and have a look over my source. Correct me if something wrong i have kept in NHET source.

    Hi Rahul,

    Do you have the HET assembler source / did you use the HET assembler?  I don't recommend at all trying to modify the default HalCoGen driver code (which does not build through HET assembler) as this is like writing machine code. If you're working this way a very simple error in how bit fields are converted [manually] to the hex # could be the problem - way to error prone.

    I think if you don't have HET assembler then next step would be to get the HET IDE and write your code in there.  Then you can ensure the machine code that is generated matches what you want to do, and you can also simulate it which might show you what you're looking for.

    But back to the problem statement - most of what I read int he posts sounded correct, but:

       1) I'm not cleare on exactly what the problems are - so maybe you could make the problem statement again.

      2) I didn't understand the auto-read clear, since you mention that you can see it working fine, but later that it is not getting enabled.

     

  • Anthony,

    I am posting on-behalf of my colleague "Rahul" who initiated this thread.

    There was a small mistake made by us in the execution flow of HET instructions. Now, it is working fine. Actually, we have not used HET Assembler and written HET machine code.

    We have also read the detailed HET thread available on link initiated by <Stefan Steinmann> and the discussion was really helpful.

    http://e2e.ti.com/support/microcontrollers/hercules/f/312/p/288214/1013232.aspx#1013232

    Thanks for your support.