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.

HTU from CPU to N2HET

Other Parts Discussed in Thread: HALCOGEN, TMS570LS3137

Hi all

I’m sentenced to implement a IO-driver for a Hercules Microcontroller. I want to use N2HET (TMS570LS3137) to generate some PWM-Signals. Some of the outputs belong together, some are independent, but all of them handle high resolution and XORing of outputs and everything must be managed in the same N2HET program because the pins are only supported by N2HET1. Also because I have to deal with dead times and symmetrical PWM, the black box-NHET-program generated by HalCoGen is no option for my application. (The LR should not exceed 32 HR because of the speed and resolutions constraints I have to fulfil. Therefore I wiped out my first attempts with complicated angle calculations or the use of MOV64 to fill the data-field of PWCNT-statements and the use of Interrupts to keep the transaction consistent.) To keep the access to the buffer atomic, I decided to use HTU with double buffered transfers. In total I need four independent DCP-channels and frame sizes from 3 to 10 values. My Current N2HET-program is 24 statements long which mean that every little change in concept is likely to break my 32-statement barrier.

 My N2HET-program looks somewhat like this:

 (Simplified to 1 channel with 2 pwm-signals)


; Output1

; routed to Pin15 on TMS570LS3137PGN

Output1a .equ 22 ; N2HET1[30] has to be XORed with N2HET1[31]

Output1b .equ 23

 

; Output2

; routed to Pin139 on TMS570LS3137PGN

Output2a .equ 16 ; N2HET1[16] has to be XORed with N2HET1[17]

Output2b .equ 17

 

L00 DJZ   {next=L01,reqnum=1,request=GENREQ,control=OFF,cond_addr=B01, reg=NONE,data=0 }; sets period for PWM

L01 PWCNT {next=L02,reqnum=1,request=NOREQ ,hr_lr=HIGH,control=OFF,cond_addr=L02,en_pin_action=ON ,pin=Output1a ,action=SET, reg=NONE,data=0,hr_data=0}; Output1a on

L02 PWCNT {next=L03,reqnum=1,request=NOREQ ,hr_lr=HIGH,control=OFF,cond_addr=L03,en_pin_action=ON ,pin=Output1b ,action=SET, reg=NONE,data=0,hr_data=0}; Output1b off

L03 PWCNT {next=L04,reqnum=1,request=NOREQ ,hr_lr=HIGH,control=OFF,cond_addr=L04,en_pin_action=ON ,pin=Output2a ,action=SET, reg=NONE,data=0,hr_data=0}; Output2a on

L04 PWCNT {next=L00,reqnum=1,request=NOREQ ,hr_lr=HIGH,control=OFF,cond_addr=L00,en_pin_action=ON ,pin=Output2b ,action=SET, reg=NONE,data=0,hr_data=0}; Output2b off

 


 

For every DCP-Channel I defined two buffers, something like:

 


typedef struct

{

      unsigned int      tPwmPeriod;

      unsigned int      tPwm1on;

      unsigned int      tPwm1off;

      unsigned int      tPwm2on;

      unsigned int      tPwm2off;

} PwmSet_t;

 

PwmSet_t PwmSetA;

PwmSet_t PwmSetB;

 

And the Setup for HTU is like (also simplified)

 

void htuInit(void){

unsigned char channel = 1;

 

#define MAIN2NHET 0x008F0000 /* DCP[Channel] CPx

                                               DIR = MainMemory to NHET memory

                                               SIZE = 32-bit

                                               ADDMH = 16 bytes

                                               ADDFM = post-increment main memory

                                               TMBA = auto switch buffer A

                                               TMBB = auto switch buffer B

                                               IHADDR = (LINE1_of_DCP[Channel]NHET_ProgPart)*4+2)<<2 data field */

 

#define LINE1_NHET_PWM 1

 

#define IHADDR_PWM (LINE1_NHET_PWM-1)*4+2 //(Only valid for position of DATA-Field)

 

// PWM-Signals

      htuCPRAM ->DCP[channel].ITCOUNT = 0x00000001 + sizeof(PwmSet_t)<<4;

      htuCPRAM ->DCP[channel].IHADDRCT = MAIN2NHET + (IHADDR_PWM)<<2;

      htuCPRAM ->DCP[channel].IFADDRA = (unsigned int) &PwmSetA;   /* DCP[Channel] CPA start address of destination buffer */

      htuCPRAM ->DCP[channel].IFADDRB = (unsigned int) &PwmSetB;    /* DCP[Channel] CPB start address of destination buffer */

      htuREG ->BFINTC = 0x00000000 + (3 << (channel * 2));         /* disable buffer full interrupt for DCP[channel] - CPA and CPB*/

      // Global enable of HTU

      htuREG ->GC = 0x00010000;                /* enable HTU */

}

 


(In my main Program I switch CPENA, but I also tried it with single buffering to get a first result. No success...)

Can somebody provide me a working example of how to set up HTU with direction CPU to N2HET-RAM or suggest a way to debug code like this?

I based my code on spna130a from TI and read a lot about HTU and N2HET but it’s very hard to see where I stuck. I changed me approach several times in the last days and I’m also open to totally different approaches.

Regards, Matthias

  • Matthias,

    Your question has been forwarded to our NHET/HTU expert.

    I will be back to you as soon as I have an answer.

    Best Regards,

    Jean-Marc

  • Matthias,

    Please find the following application note and CCS project to explain the NHET/HTU/DMA interaction to improve the performance on Hercules™ ARM® Safety
    MCUs.

    Application Note: spna130a.pdf
    CCS Projects: spna130a.zip

    Please let me know if I've answered your question by marking this reply as "Verified Answer"

    Thanks and Regards,

    Jean-Marc

  • Thank you Jean-Marc

    Jean-Marc Mifsud said:

    Application Note: spna130a.pdf
    CCS Projects: spna130a.zip

    Please let me know if I've answered

    As I wrote in my post, my code is already based on this example. It shows the opposite direction with a single buffer and a beginning approach for double buffering. It's good to have that, but in my case it hasn't brought a breakthrough.
    My problem is, that I had to write too many lines of code without a chance to test them in portions. Therefore the most is written with some doubt remaining. Every questionmark in my code doubles the effort needed for debugging; at least. How is TI working with this Unit? Even writing Code for N2HET is a very complicated task. So many exceptions have to be taken  in account and it seems to be a new kind of BrainF***. I promise to post my solution here as soon as I've got it - given it is before I retire, of course. ;-)
    Best regards and thanks again,
    Matthias

  • Hello Matthias,

    Please forgive my late question on this subject.  Perhaps your NHET coding skills are already beyond what this tool could provide, but have you been / are you using the the www.ti.com/tool/het_ide tool? 

  • Hello Brian

    Thanks, yes I use it and find it quite helpful. It has some issues but I worked out now,  how to navigate around them. 

    NHET in Combination is HTU is my actual problem. The data values that have to be changed dynamically from the CPU and that have to be consistent against each other.

    About the IDE: Sometimes It modifies my code in a way I dont' expect. My example in this post is based on N2HET-Code written in the IDE. When I doubleclick one line, the wizard opens, which is very helpful.  Unfortunately it stores the command in a different way  afterwards: Comments and placeholders e.g. (.equ) for PIN-Numbers get lost. I also found fields marked as mandatory, which may be ignored in some constellations. Of course, I see the problem of not having metadata in the textfield. (There is no third state meaning <greyed out> in the end, when the statement is compiled to a bitfield for the N2HET-RAM. This makes reverse engineering very hard and therefore not easy to take the essential from examples. But nevertheless the tool is great and by the fact that its probably made for a small group of users it takes a little longer to become ripe. After realizing that fact, it was even more helpful. Think I have not found all the options yet, e.g. a way to export the register settings to something c-code-like. Also the behaviour when I try to modify a value that is intended to be modified by a seaparate Set- and Clear- register looks a little opaque. Perhaps there is a way to modify a third register that guides out of the deadlock, but I stopped playing around with, before I found it. The code templates are fine. They look like from different sources, but this is no disadvantage but shows different ways to work with the tool. My main problem is, that there are only a few commands but many of them can be used in different ways for similar things. It’s amazing was N2HET can do but its really hard to become an overview and compared to conventional timers. It seems to me that there is a field that is not covered by HalCoGen but not that complex that N2HET is really needed with all its possibilities. In this field, developing software for conventional Timers is still ways faster. I see what you guys have made here and Its just great! for me it’s a little bit too much to be fast in programming without a working sample.

    Thanks again and regards

    Matthias

  • Did you map the DMA request to htu? sth like:

    hetREG1 -> REQDS &= 0xFFFCFFFC;

    /* Set bits TDBS0 and TDS0 to 0 */

    hetREG1 -> REQENS |= 0x00000003;

    /* Enable request HTUREQ[1] */

    This code enables the mapping for channel 0 and channel 1.

  • Hi

     I mapped to HTU instead of DMA.

    hetREG1 -> REQDS  |= ~0x000f000f;

    hetREG1 -> REQENS |= 0x0000000f;

    (in fact, I use 4 DCP but  simplyfied the example)

    but one thing that i can do is read  hetREG1 -> REQENS back to see if really made it like this.

    Will test that on monday. Thanks in between!

    BR, Matthias

  • It's monday and as I expected, this seems not to be the fault in my code.

    Can you perhaps provide me some sample code showing the initialisation of CFADDRA, CFADDRB, CFTCTA, CFTCTB? (I2, CPU Clears current DCP)

    BR, Matthias

  • 7457.htu.c6012.htu.h3326.het.c8510.HET1_C2000LV_2Motor.chttp://e2e.ti.com/cfs-file.ashx/__key/CommunityServer-Discussions-Components-Files/312/8585.HET1_5F00_C2000LV_5F00_2Motor.het

    in main.c:
    hetInit();

    hetREG1 -> REQDS &= 0xFFFCFFFC;  /* Set bits TDBS0 and TDS0 to 0  */
      hetREG1 -> REQENS |= 0x00000003;  /* Enable request HTUREQ[1]  */
      htuInit();

    This is part of a motor control project (controling two motors). The htu updates the pwm everthing LRP (0.1ms). As you can see, I disabled the het in init. It is actually enabled through SCI communication.

    It is complicated project and requires a special target board.  I will send the whole project to our European term. You can discuss with them what is going on.

    ALL CONTENT AND MATERIALS OF THIS POST ARE PROVIDED "AS IS". TI AND ITS RESPECTIVE SUPPLIERS MAKE NO REPRESENTATIONS ABOUT THE SUITABILITY OF THESE MATERIALS FOR ANY PURPOSE AND DISCLAIM ALL WARRANTIES AND CONDITIONS WITH REGARD TO THESE MATERIALS, INCLUDING BUT NOT LIMITED TO, ALL IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT OF ANY THIRD PARTY INTELLECTUAL PROPERTY RIGHT. NO LICENSE, EITHER EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, IS GRANTED BY TI.

    Regards,

    Haixiao

  • Hello Haixiao

    Thanks a lot. this helps for sure to review my HET-Setup. Your examle uses single buffering. Is this the reason for the use of MOV32-Instructions? 

    In my case the maximum HR per LR is 32. This limits me to a maximum program length, which is exceeded when I use single buffering with MOV32-instructions to keep my signals of  each PWM-block synchronous. Do you see a problem in my approach of the HET-Program below:


    ;PWM Block one Data-Field of each Instruction comes from CPU through HET-DCP0

    A00 DJZ   {next=A01,reqnum=0,request=GENREQ           ,control=OFF,cond_addr=A01,                                         reg=NONE,data=0          }; preiod (data set byCPU thru HET)

    A01 PWCNT {next=A02,reqnum=0,request=NOREQ ,hr_lr=HIGH,control=OFF,cond_addr=A02,en_pin_action=OFF,pin=dummy,             reg=NONE,data=0,hr_data=0};Sample  ADC (data set by CPU thru HET)  
    A02 PWCNT {next=A03,reqnum=0,request=NOREQ ,hr_lr=HIGH,control=OFF,cond_addr=A03,en_pin_action=ON ,pin=S1a   ,action=SET, reg=NONE,data=0,hr_data=0}; S1a     (data set by CPU thru HET)  

    A03 PWCNT {next=A04,reqnum=0,request=NOREQ ,hr_lr=HIGH,control=OFF,cond_addr=A04,en_pin_action=ON ,pin=S1b   ,action=SET, reg=NONE,data=0,hr_data=0}; S1b    (data set by CPU thru HET)     
    A04 PWCNT {next=A05,reqnum=0,request=NOREQ ,hr_lr=HIGH,control=OFF,cond_addr=A05,en_pin_action=ON ,pin=S1Na  ,action=SET, reg=NONE,data=0,hr_data=0}; S1Na      
    A05 PWCNT {next=A06,reqnum=0,request=NOREQ ,hr_lr=HIGH,control=OFF,cond_addr=A06,en_pin_action=ON ,pin=S1Nb  ,action=SET, reg=NONE,data=0,hr_data=0}; S1Nb      
    A06 PWCNT {next=A07,reqnum=0,request=NOREQ ,hr_lr=HIGH,control=OFF,cond_addr=A07,en_pin_action=ON ,pin=S2a   ,action=SET, reg=NONE,data=0,hr_data=0}; S2a       
    A07 PWCNT {next=A08,reqnum=0,request=NOREQ ,hr_lr=HIGH,control=OFF,cond_addr=A08,en_pin_action=ON ,pin=S2b   ,action=SET, reg=NONE,data=0,hr_data=0}; S2b       
    A08 PWCNT {next=A09,reqnum=0,request=NOREQ ,hr_lr=HIGH,control=OFF,cond_addr=A09,en_pin_action=ON ,pin=S2Na  ,action=SET, reg=NONE,data=0,hr_data=0}; S2Na      
    A09 PWCNT {next=B00,reqnum=0,request=NOREQ ,hr_lr=HIGH,control=OFF,cond_addr=B00,en_pin_action=ON ,pin=S2Nb  ,action=SET, reg=NONE,data=0,hr_data=0}; S2Nb      

    ;PWM Block two Data-Field of each Instruction comes from CPU through HET-DCP1

                                                                                                                                                                    
    B00 DJZ   {next=B01,reqnum=1,request=GENREQ           ,control=OFF,cond_addr=B01,                                         reg=NONE,data=0          }; f AC-Relais
    B01 PWCNT {next=B02,reqnum=1,request=NOREQ ,hr_lr=HIGH,control=OFF,cond_addr=B02,en_pin_action=ON ,pin=REL1a ,action=SET, reg=NONE,data=0,hr_data=0}; REL1a     
    B02 PWCNT {next=B03,reqnum=1,request=NOREQ ,hr_lr=HIGH,control=OFF,cond_addr=B03,en_pin_action=ON ,pin=REL1b ,action=SET, reg=NONE,data=0,hr_data=0}; REL1b     
    B03 PWCNT {next=B04,reqnum=1,request=NOREQ ,hr_lr=HIGH,control=OFF,cond_addr=B04,en_pin_action=ON ,pin=REL2a ,action=SET, reg=NONE,data=0,hr_data=0}; REL2a     
    B04 PWCNT {next=C00,reqnum=1,request=NOREQ ,hr_lr=HIGH,control=OFF,cond_addr=C00,en_pin_action=ON ,pin=REL2b ,action=SET, reg=NONE,data=0,hr_data=0}; REL2b      
                                                                                                                                                                    

    ;PWM Block tree Data-Field of each Instruction comes from CPU through HET-DCP2

    C00 DJZ   {next=C01,reqnum=2,request=GENREQ           ,control=OFF,cond_addr=C01,                                         reg=NONE,data=0          }; f Fan     
    C01 PWCNT {next=C02,reqnum=2,request=NOREQ ,hr_lr=HIGH,control=OFF,cond_addr=C02,en_pin_action=ON ,pin=FAN1a ,action=SET, reg=NONE,data=0,hr_data=0}; FAN1a     
    C02 PWCNT {next=D00,reqnum=2,request=NOREQ ,hr_lr=HIGH,control=OFF,cond_addr=D00,en_pin_action=ON ,pin=FAN1b ,action=SET, reg=NONE,data=0,hr_data=0}; FAN1b      
                                                                                                                                                                    

    ;PWM Block four Data-Field of each Instruction comes from CPU through HET-DCP3

    D00 DJZ   {next=D01,reqnum=3,request=GENREQ           ,control=OFF,cond_addr=D01,                                         reg=NONE,data=0          }; f I-Ref   
    D01 PWCNT {next=D02,reqnum=3,request=NOREQ ,hr_lr=HIGH,control=OFF,cond_addr=D02,en_pin_action=ON ,pin=IB1a  ,action=SET, reg=NONE,data=0,hr_data=0};; IB1a     
    D02 PWCNT {next=D03,reqnum=3,request=NOREQ ,hr_lr=HIGH,control=OFF,cond_addr=D03,en_pin_action=ON ,pin=IB1b  ,action=SET, reg=NONE,data=0,hr_data=0};; IB1b     
    D03 PWCNT {next=D04,reqnum=3,request=NOREQ ,hr_lr=HIGH,control=OFF,cond_addr=D04,en_pin_action=ON ,pin=IB2a  ,action=SET, reg=NONE,data=0,hr_data=0};; IB2a     
    D04 PWCNT {next=A00,reqnum=3,request=NOREQ ,hr_lr=HIGH,control=OFF,cond_addr=A00,en_pin_action=ON ,pin=IB2b  ,action=SET, reg=NONE,data=0,hr_data=0};; IB2b     

     

    Thanks again

    regards,

    Matthias

     

  • Hello Haixiao

    Turned the thing to a working solution. Thanks for your input. Will come with some more questions for sure, but for now, I'm fine. Thanks again for assistance and sample code.

    best regards

    Matthias