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.

Hercules Board RM48L952ZWT Configuring HalCoGen for NHET/PWM and TI LED Demo Example Code

Other Parts Discussed in Thread: HALCOGEN, RM48L952

Hello.  We are using the Hercules Board RM48L952ZWT, and we received the demo software for the board. We had a question on how to configure NHET/PWM using HalCoGen along with the TI code.  In the TI sample code we can see that various NHET pins (i.e., 0,2,4,5,25,...] are set up to generate varying hardcoded  pulse widths to blink the Hercules Board's associated LEDs via a manual while loop in the TI code. (code from TI further below)

When we generated a new driver library with HalCoGen (and then the TI demo is run off of this driver library), then going to i.e., HET1 interface . It seems the hardcoded TI code overrides  the default HalCoGen configuration anyhow, so it is touch to understand how to apply to our requirements. is it possible just using HalCoGen to configure the same as the hardcoded  TI while loop?

We are trying to understand how to use HalCoGen to configure our PWMs with the different tabs using the black box model   (HETx Global Timing Configuration, PWM0-7, PWM Interrupts, Edge 0-7, Edge Interrupts, Cap0-7) according to our requirements (and if using the black box model is feasible for NHETx PWM).   Thank you. 

(from TI sample project for NHET LED demo)

pwm = 0;

count = 0;

/** - Do the LED Demo Toggle, until another task selected

* - The below loop generates a varying pulse width at

* HET pins[0,2,4,5,15,16,17,18,20,27,29,31]

* which helps in blinking LED demo */

while(toggleLoop > 0)

{

/** - Set NHET Pins 29,31,0,17,18,25

* - Set NHET Pins 20,5,2,16,27,4

* - This turns the white LEDs on and the RGB LEDs off*/

hetREG1->DOUT = 0xAA170035;

for(temp=0;temp<pwm;temp++);

if((pwm == 0x800))

{

for(temp=0;temp<0x100000;temp++);

}

delay1sec();

/** - Clr all NHETs (turns on RGB LEDs) */

hetREG1->DOUT = 0x00000000;

for(temp=0;temp<(0x800 - pwm);temp++);

if((pwm == 0x00))

{

for(temp=0;temp<0x100000;temp++);

}

if(pwm == 0x800)

{

count = 1;

}

if(pwm == 0)

{

count = 0;

}

if(count != 0)

{

pwm--;

}

else

{

pwm++;

}

toggleLoop --;

delay1sec();

}

/** - Clear HET pins end of the demo */

hetREG1->DOUT = 0; //0x08110034;

  • Hi Tammy,

    I have copied one of our NHET experts so that they can provide answers to your questions on this example code. They should reply to you soon.

    In the mean time, I am assuming this investigation is in relation to the thread on the 1-wire EEPROM interface. Please have a look at these posts on using the N2HET for SCI and I2C to get an idea of what is involved in using N2HET to emulate communication IPs.

    For SCI please see: http://e2e.ti.com/support/microcontrollers/hercules/f/312/t/295723

    For I2C please see: http://e2e.ti.com/group/launchyourdesign/m/boosterpackcontest/665692

    These links should give you some idea of what can be done with the N2HET.
  • Hi Tammy,

    Is the issue that the demo is confusing you because instead of using the N2HET to blink the LEDs it's blinking them through a software loop?   (thus, it's not a good program to use in order to evaluate the PWM capability?)

    I did a quick test of the PWCNT based PWM in the black box driver with this very simple program:

    /* USER CODE BEGIN (1) */
    #include "het.h"
    /* USER CODE END */
    
    /** @fn void main(void)
    *   @brief Application main function
    *   @note This function is empty by default.
    *
    *   This function is called after startup.
    *   The user can use this function to implement the application.
    */
    
    /* USER CODE BEGIN (2) */
    /* USER CODE END */
    
    uint8	emacAddress[6U] = 	{0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU};
    uint32 	emacPhyAddress	=	0U;
    
    void main(void)
    {
    /* USER CODE BEGIN (3) */
    	int dc = 50;
    	hetInit();
    	pwmStart(hetRAM1, pwm3);
    	while(1) {
    		pwmSetDuty(hetRAM1, pwm3, dc);
    	}
    /* USER CODE END */
    }

    --- of course I had configured PWM3 to go to a pin that was convenient to attach a scope probe to, you could change the pin.

    notice that I didn't even wait for an interrupt to change the duty cycle.   the 'pwmSetDuty()' call writes to the MOV64 instruction, which is a buffer register for the compare value (so, you can write to it asynchronously and it is only copied into the active PWCNT instruction at the next duty cycle event).   Since the call writes to this buffer register, I just put the call in a while(1) loop and I put the duty cycle value in a variable that can be changed between 0 and 100 (%)
     with the debugger - default is 50%.

    I just ran this code and changed the dc value from 50% to 99% to 1% to 0% to 100% and back to 0% , using a scope to monitor the output.

    Maybe some simple test program like this will give you an idea as to whether you can use the black box driver or not.

    My finding was that there is a problem going from 100% to 0%  (gets stuck at 100% if you try to jump directly) but I have yet to simulate the program to understand why.   I can confirm though that if this is  a limitation it's in the simple black box driver, not the N2HET itself as we do have more complex programs that can make this jump correctly.

  • Hi Thank you.

    We are using the Hercules RM48L952ZWT board from TI. Is it possible to configure PWM3 (or any other PWM) to go to a pin that is convenient to attach a scope probe to without asking the hardware team to make major modifications to the Hercules board?

    It is both for the 1-wire EEPROM requirement later, as well ass we have a requirement for 16 PWMs.. With the potential limitation you found it would be important to know if the black box approach is not an option. What we hope to also be able to do:

    a. pwm1 Hard Mode: 5Hz, 8Hz, 10Hz, 12Hz, 15Hz, 20Hz, 25Hz, 30Hz, 40Hz, 50Hz, 75Hz 100Hz, fixed 3mS (duty cycle)
    Soft Mode: 5Hz, 8Hz, 10Hz, 12Hz, 15Hz, 20Hz, 25Hz, 30Hz, 40Hz, 50Hz, fixed 4mS (duty cycle)

    b. pwm2. Frequency synchronized with PWM1, variable duty cycle (range 0 - 100%)

    c. pwm3. (100%) on or (0%) off but need to have the option of 100Hz, 0% to 100% duty cycle, 100 steps controllable
  • Hi Tammy,

    Yes, if you flip the board over on J11 you'll notice a box labeled "N2HET" I think that the encoding 100, 101, 102 etc... means N2HET1[0], N2HET1[1], N2HET1[2] etc... just abbreviated because of space limitations.

    You can pretty easily probe one or two signals here although you might need to insert a pin into the receptacle if your probe tip doesn't fit.

    For a large group of signals we have plans here http://processors.wiki.ti.com/index.php/HerculesHdkExperimenter for a breakout board that you could order from gerbers or modify as desired.

    I haven't followed the 1-wire EEPROM example but I don't think you will be able to interface to a 1 wire EEPROM with the black box N2HET program. However, you could probably add 1-wire code to the black box program w.o. starting completely from scratch.

    Regarding the limitation - I don't see any issue w. your requirements a,b,c, for the PWMs *aside from the limitation* of a transition from 100% immediately to 0% doesn't work w. the blackbox example. And we'd need to leave it up to you to determine whether or not this 100% -> 0% in one step is a requirement or not.
    (100% -> 1% -> 0% will work as far as I can tell ..)
  • Hi Thank you. Will you still verify what you wrote above that the BlackBox driver for PWM will not work for going from 100% to 0%?

    "My finding was that there is a problem going from 100% to 0% (gets stuck at 100% if you try to jump directly) but I have yet to simulate the program to understand why. I can confirm though that if this is a limitation it's in the simple black box driver, not the N2HET itself as we do have more complex programs that can make this jump correctly."
  • Hi Tammy,

    Yes, planning to do this. First step actually is to translate the binary format code that's in HalCoGen back into source that can be assembled and simulated w. the HET IDE. Not quite done with this step yet.
  • Hi Thank you. Oscilloscope connected now Ok. What configuration did you have set up on the scope to monitor output?
  • Tammy,

    I just had an edge trigger set for the channel in question, and ran continually for the most part.

    To capture the transition from 100% to 0% I did the following:

     1) have the PWM set to 100%

     2) have the scope set on an auto-trigger and confirm the pin is 'high'.

     3) change the scope to falling edge trigger

     4) change the scope for a 'Single Sequence'  (run once not repetitively).

     5) change DC value in the code to 0%.

    I'd expect to see a trigger but don't.   You can change back to auto and see that the pin is still high.

    You can do the reverse to see that 0% to 100% does work:

     1) have the PWM set to 0%

     2) have the scope set on an auto-trigger and confirm the pin is 'low'.

     3) change the scope to rising edge trigger

     4) change the scope for a 'Single Sequence'  (run once not repetitively).

     5) change DC value in the code to 100%.


    This does trigger for me.  And I can see that the initial pulse is a full 100% -- no short glitch during the transition.

  • Hi Thank you. We set up this test, and we wanted to double check we did not miss anything. In HalCoGen, PWM3 had been assigned to NHET1 Pin 25 (HET1 Menu -> PWM-7), so connected scope to HET 125 on the back of Hercules board. Default voltage low (0) after board boot up but before running your code test. After starting code test of dc=50 and looping, sample code did not show any changes to pin over scope (rising edge). Tried also PWM 7 Pin 5 (HET 105 on back of Hercules board) as an alternative, default is HIGH after board boot up but before running code test. After code test (falling edge), scope shows no changes. Are there any other settings that should have been done in HalCoGen or in the scope (what was your volts/div configuration on your scope?) to be able to run this test, and see control of this of any of these PWM/HET pins?
  • Tammy,

    You might try setting the switches in S2 all off as a quick test - in case you have picked a HET pin that's muxed with another function like USB or EMIF. (Sorry I didn't check these particular pins in the schematic to see if they are affected by S2 but I think it's very quick to just turn the switches all to off..).

    If turning the switches all to OFF doesn't help, then you could try to just write to the pins as GIO. You can open the register window in CCS and poke values into the GIO registers, you should see the changes there appear on the scope. If they do, then the problem would trace back to something in software - perhaps the pinmux or some other HET setting (like the DIR bit in the port tab...)
  • Hi. Thank you. Is there an equivalent of pwmSetPeriod function to the pwmSetDuty function you used in example? (from HalCoGen autogenerated driver) i.e., if we needed to change the period on the same PWM pin at runtime like we can change the duty cycle at runtime? I was looking into the het.c file HalCoGen autogenerated file, and I only say the pwmSetDuty. Also, what if hardware team needed to have Duty Cycles be fractional ? i.e., 1.5%, 2.4%, etc. I saw pwmSetPeriod function had a uint (not float) for pwmDuty. Would we have to create our own function where this argument was changed to a float? Is there a reason why TI di dnot allow fractional for the %duty cycle?
  • Tammy Noergaard said:
    Is there an equivalent of pwmSetPeriod function to the pwmSetDuty function you used in example? (from HalCoGen autogenerated driver) i.e., if we needed to change the period on the same PWM pin at runtime like we can change the duty cycle at runtime? I was looking into the het.c file HalCoGen autogenerated file, and I only say the pwmSetDuty.

    Tammy, I think this is the pwmSetSignal function.  Although it takes both duty cycle and period as inputs and sets both.

    Tammy Noergaard said:
    Also, what if hardware team needed to have Duty Cycles be fractional ? i.e., 1.5%, 2.4%, etc. I saw pwmSetPeriod function had a uint (not float) for pwmDuty. Would we have to create our own function where this argument was changed to a float? Is there a reason why TI did not allow fractional for the %duty cycle?

    I honestly don't know the why part but I think you are correct about the fractional % not being supported by the function as-is other than to say that the intention of the black box code is towards the 'simple demo' side and fractional numbers can be difficult if you don't have an FPU.  (We have some parts in the Hercules family with HET but no FPU).    Now I don't think it has to be difficult but let me say not-obvious.   For example you could change the code below to '/200' and still pass in an integer, but then the integer range would be between 0 and 200 in steps of 1/2 % which wouldn't be simple for newbies.. 

    Anyway - you could make a custom version of the function by copying the entire function and just changing the formula

    hetRAM->Instruction[(pwm << 1U) + 41U].Data = (((pwmPeriod * pwmDuty) / 100U) << 7U) + 128U;

    Although, you probably need to put your custom version down in the

    /* USER CODE BEGIN (4) */
    /* USER CODE END */

    area if you want to keep it in the same het.c file.

  • Hi. Thank You. We are using the RM48L952ZWT processor, is there FPU support for this on Hercules within the RM48L952ZWT CPU?

    So, if we used the blackbox model, we would have to create custom version of pwmSetSignal function to manage float type for duty cycle. Does it still mean blackbox is recommended for implementing our PWMs even with creating our own custom function based on HalCoGen code (and simply changing uint value to float)? 

  • Hi Tammy,

    Tammy Noergaard said:
    We are using the RM48L952ZWT processor, is there FPU support for this on Hercules within the RM48L952ZWT CPU

    Yes you have an FPU.   Only the RM42xx parts do not have an FPU.   But HalCoGen's HET driver is designed to work across the family - which may be one reason floating point isn't used.

    Tammy Noergaard said:
    So, if we used the blackbox model, we would have to create custom version of pwmSetSignal function to manage float type for duty cycle.

    Yes, given that you need more than ~6.6 bits of resolution.

    You don't necessarily need to use floating point for this.   I brought up floating point because it's the only 'simple' way to express 1.5%.

    But you could decide that for your custom function you are going to take inputs between 0 and 200 and call them units of 1/2 % .. or 0 to 400 in units of 0.25%, etc...     It's up to you whether this works better or float works better.

    The caveat I would put out there regarding float is that if you are using float in both your application code and your ISR's then you will need to save the FPUs registers as part of the context switch when you go into an ISR that uses float.  Since you might be changing the PWM duty cycle or period in an ISR - this is probably worth considering.  Saving the FPU registers of course will add to the overhead of the ISR context switch and for that reason it might be best to avoid it.

    On the other hand it sure would be simpler to understand the code if you pass it a float ...

    Tammy Noergaard said:
    blackbox is recommended for implementing our PWMs

    I'm not sure I'd ever go as far as 'recommend' the blackbox driver.  I don't particularly like the way the the PWMs are implemented with the PWCNT instruction.  The issue of 100%->0% not working is one reason.     I can certainly understand how sticking w. the black box driver in the short run is desirable though ... when you're trying to get up and running quickly.    But if you get the bandwidth to learn the HET IDE I think it'll become preferable to customize that driver.   And certainly if you need to do something special for a 1-wire EEPROM in the HET, you'll need to at least add code to the end of the blackbox driver...

  • "The caveat I would put out there regarding float is that if you are using float in both your application code and your ISR's then you will need to save the FPUs registers as part of the context switch when you go into an ISR that uses float. Since you might be changing the PWM duty cycle or period in an ISR - this is probably worth considering. Saving the FPU registers of course will add to the overhead of the ISR context switch and for that reason it might be best to avoid it."

    The reason for concern is if we create our own version where a float is passed as a parameter instead of a uint32 for pwmDuty i.e.,


    hetRAM->Instruction[(pwm << 1U) + 41U].Data = (((pwmPeriod * pwmDuty) / 100U) << 7U) + 128U;
    = (((pwmPeriod * pwmDuty) / 100U) << 7U) + 128U;



    What about the math calculation that puts the result into "hetRAM->Instruction[(pwm << 1U) + 41U].Data" this is still a uint32. Do the hardware engineers lose the preciseness they need, because of data conversion back to uint32 here, if the math calcalulation results in a float but we are forcing the result back into a uint32. What the hardware engineers need is for control of PWM as follows i.e., pwm = 5Hz, 8Hz, 10Hz, 12Hz, 15Hz, 20Hz, 25Hz, 30Hz, 40Hz, 50Hz, 75Hz 100Hz, fixed 3mS (duty cycle)...

    Can you explain what you mean by "But you could decide that for your custom function you are going to take inputs between 0 and 200 and call them units of 1/2 % .. or 0 to 400 in units of 0.25%, etc...    " approach? Thank you again.
     
    so, i.e., for 5Hz, 200 msec period with a 3msec duty cycle = duty cycle of 1.5% and so on... (i.e., they have to have a duty cycle of 3msec at 5MHz) -- is there a better way to accomplish this minus looking at modifying the blackbox driver with the other programming model?

    he reason also I ask is for some of our other PWMs, our hardware engineers need us to go between 0% to 100% and back 0%, so this is also a problem given 100%-0% not working with blackbox.

  • Hi Tammy,

    Short answer is no - your hardware team won't lose resolution.

    Long winded answer is:

    The value that is written by the HET driver is stored in a uint32 type but in reality it is a fixed point number that is treated by the N2HET as being in a fixed point 25.7 format and measured in terms of the loop resolution period.  

    So the representation of 1 loop resolution period is 0x00000080 actually (one of the things I don't like about N2HET :) why didn't we pick 24.8 to make reading the values easier :))

    Instructions that use the hr_lr = ON can make use of the hi-res structure,  and with a loop resolution period of 128 hi-res clocks, you get to use all 7 of the fractional bits of the 25.7 number and can specify timing down to the hr clock.  

    But the black-box driver as far as I can tell is implemented with only loop resolution instructions, another reason to not like the black box driver as a long term solution.

    But let's look at your example.    Start with the assumption that the N2HET loop resolution period is set to 128 hr clocks,   and that the HET is running at 110MHz (since you have the 952).

    This translates to a loop resolution period of 1.16 us.

    Now I am just assuming that

    Tammy Noergaard said:
    3msec at 5MHz
    is a typo since 5Hz has been what we've been discussing... 


    Ok given that it's 5Hz not 5MHz your fastest frequency is 100Hz for a period of 10ms. 

    The low-res PWCNT running on a 110MHz N2HET and loop resolution of /128 is was 1.16us.
    So each count (0x0000 00080, 0x0000 0010, 0x0000 0018) corresponds to 1.16us which means that your 0% value is of course 0x00000000 but your 100% value is 8593 (decimal) or 0x2191 hex - in fixed point 32.0 format.

    In the HET's 25.7 format though the full scale value becomes 0x0010 C8E0 (pls. check my math) ... this is why you see the << 7 in the equation.

    Now,  I have glossed over the quantization *time axis* error here.   Since the blackbox driver uses the loop resolution form of PWCNT, the error is going to be 1 part in 8593 whereas it could be reduced to 1 part in 1,110,000 if you were to re-code the driver to use the hi-res instruction.    1 part in 8593 might be pretty good especially if you don't need exactly 100Hz but just something in that range - and it's the duty cycle that is critical.  But if you're going to be accumulating the error over multiple periods then maybe it's not good enough.  (In that case even 10ns resolution might not be good enough but it would be a lot *better* meaning you'd need to correct for the error less often..) 

    Hope that's not too long winded of an answer... 

  • Hi Thank you.  Yes, forgive the typo it was Hz not MHz.

    1. What about if in addition to above PWM, we also have to configure other NHET/PWM  to go between 0% to 100% and back 0%.  Do you have a solution in black box to this  this problem given 100%-0% not working with blackbox. Or does that mean we must rule blackbox completely out for implanting our PWMs because of this issue then?

    2. Results first on modifying code in passing float pwmDuty to hetRAM->Instruction[(pwm << 1U) + 41U].Data = (((pwmPeriod * pwmDuty) / 100U) << 7U) + 128U; The TI Compiler will not allow a float in this calculation. When we tried  just this simple weak, compile error

    "../Drivers/Biolase/source/hetBiolase.c", line 70: error #31: expression must have integral type

    So, this is not an option to rewrite function to process a duty cycle that is not a whole number in this direct way, without additional significant changesto the black box driver.  What do you think?

    So, if we were going to look at implementing the PWMs with the other model (not blackbox), where can we read/look to begin? Are there any code examples? 

  • Hi Tammy,

    Tammy Noergaard said:
    1. What about if in addition to above PWM, we also have to configure other NHET/PWM  to go between 0% to 100% and back 0%.  Do you have a solution in black box to this  this problem given 100%-0% not working with blackbox. Or does that mean we must rule blackbox completely out for implanting our PWMs because of this issue then?

    I guess I don't understand the question.  The BlackBox driver has 3 functions:  PWM, Edge Detection, and Input Capture, and as far as I know it's only the PWM section that can 'output'.   All the PWMs are implemented the same way so they would all have the same issue with 100%->0%.   

    I haven't actually gotten as far as I need to in terms of understanding the PWM function of the black box driver.

    I can post what I do have if you want to look in parallel at it, and it could also be something for you to use to get started with the HET IDE.


    And a "Middle Ground" that could exist between the black box driver and your own custom driver would be to take the black box driver, and modify it slightly while not changing anything really important to the APIs (or at least, preserving as much compatibility with the APIs as possible.)     The starting point for this would be to take the source of the black box driver and work with it in the HET IDE ... so that would be another motivating factor towards HET IDE...

    Tammy Noergaard said:

    2. Results first on modifying code in passing float pwmDuty to hetRAM->Instruction[(pwm << 1U) + 41U].Data = (((pwmPeriod * pwmDuty) / 100U) << 7U) + 128U; The TI Compiler will not allow a float in this calculation. When we tried  just this simple weak, compile error

    "../Drivers/Biolase/source/hetBiolase.c", line 70: error #31: expression must have integral type

    So, this is not an option to rewrite function to process a duty cycle that is not a whole number in this direct way, without additional significant changesto the black box driver.  What do you think?

    I believe you are winding up with a result that is floating point type on the right hand side of the expression due to the way that C handles type promotion.   I don't have my C standard book handy but found a good picture on this page:  http://www.tutorialspoint.com/cprogramming/c_type_casting.htm

    You need to add another step to the equation that converts the floating point result of the right hand side back to a unit32 before you can write it back to the hardware register.

    I think you could just use a type-cast for this purpose, but it might be better to use the function:

    int __aeabi_f2iz(float)

    This is documented as part of the ARM EABI standard, chapter 4 of ARM's document IHI0043D_rtabi.

    I would probably try to avoid using a standard C library function because you might get a conversion to double precision in the process which would be a wasted step...

    EDIT:  Tammy - chatting with one of our compiler experts - he recommends the type casting approach over the call to the EABI function.   My main concern with this was just knowing where to find a document that nails down how the type cast from float to int is supposed to be carried out  [for example is it rounding, truncating, etc. and is it converting or just copying the raw binary value and calling it an int.]   I'm sure he's right - but I just don't know off hand which document to point you to in order to have a standard backing you.    But you might be able to find the answer to this or post the question to the compiler forum.

    Tammy Noergaard said:
    So, if we were going to look at implementing the PWMs with the other model (not blackbox), where can we read/look to begin? Are there any code examples? 

    The HET IDE includes a pallette ('algorithm library') that you can use to insert fragments of HET code for common input and output functions.   There are also examples on this forum.

  • Hi. Thank you.

    On #1. I was referring to the scope test results from you yesterday. You wrote
    "...I just ran this code and changed the dc value from 50% to 99% to 1% to 0% to 100% and back to 0% , using a scope to monitor the output....My finding was that there is a problem going from 100% to 0% (gets stuck at 100% if you try to jump directly) but I have yet to simulate the program to understand why. I can confirm though that if this is a limitation it's in the simple black box driver, not the N2HET itself as we do have more complex programs that can make this jump correctly....for the PWMs *aside from the limitation* of a transition from 100% immediately to 0% doesn't work w. the blackbox example. And we'd need to leave it up to you to determine whether or not this 100% -> 0% in one step is a requirement or not...."

    I was just confirming yes, this is a requirement for a few of the PWMs to go from 100% to 0%. I was just asking if you had determined root cause (hardware or black box driver software). And if it could be solved in software or if this meant the black box driver was not feasible for this model or what is a work around if blackbox is our only option if our requirement from hardware engineers is PWM from 100% to 0%? Or is this impossible given the root cause?

    On #2. Yes, That is why I asked about precision higher up and asked about including a float value in a math calculation that goes into a uint. I think the test was run because I gave a general Ok to team try this approach, so I should have explained better what needed to be tweaked in code to them. The HW engineers are insisting that for the given period, a duty cycle cannot be rounded up or down (or truncated in a type case) of 1.2% vs. 3.6% vs 6.3% for PWM requirements. They can only have +- 5% off on pwm so that is why the calculation of the duty cycle that isn't a whole number and the approach TI recommends. At some point the fraction must be truncated with a type conversion. We have a scope attached as well to take measurements. I will go back to them with the int __aeabi_f2iz(float) function. It is the same as #1 (what I asked later what are options other then as-is blackbox driver generated by HalCoGen). Were the (assumed) ramifications what you further described above on precision? Should I create 2 tables with the math calculations (and results of the formula that duty cycle is used in) to help clarify and post here? One table with fractional and results, and one table with a type cast to uint is done to help clarify?
  • Hi Tammy,

    I'm still working on the answer to the blackbox question. Going through the code right now that is reverse engineered bit by bit (well, 32-bit hex by 32-bit hex) comparing the HET IDE memory window to the memory window on the silicon to confirm that they are equivalent. There is probably going to be a simple workaround and we definitely will be able to explain what is going on.

    Regarding the type conversion - this really should only affect +/-1 LSB of the 25 bit result that is written to the HET memory. And for your fastest PWM (100Hz) I think we calculated that the period should be a count of 8593. So +/-1 LSB error due to rounding type would only be an error of 0.012%. If you need to be within 5% then I would assume that the conversion mode (round, truncate, etc.) is a don't care.

    If there's more to it - then I am probably just being dense and not seeing it; and in that case if you think that making a table to show the problem would be easier to understand then this would be much appreciated.

    PS. Also pls. note - I added an EDIT to the previous reply. One of our compiler experts has recommended the cast to (uint_32t) rather than the function call to int __aeabi_f2iz(float)..
  • Hi Thank you. No you are not dense, just tough to communicate over text if we are not all sitting in the lab with the whole team. We will run the scope tests first then after code is tweaked properly (thank you, saw the edit to reply now and will go back to unint32 typecast).
  • Hi. Thank You. We wanted to double check. The original equation from HalCoGen in the pwmSetSignal does the shift left of 7 ( <<7 which is essentially a multiply by 128). You had written before it was because that some of the other CPUs did not have FPUs, etc. When we look at where to put typecast, we can gain more precision if we can change the <<7 portion to *128 and do the typecast at the end versus before the <<7. Is there another purpose/consequence to the <<7 in this equation other then a multiplication that TI intends? Or is it safe to replace the <<7 with the * 128?  You had written:

    "In the HET's 25.7 format though the full scale value becomes 0x0010 C8E0 (pls. check my math) ... this is why you see the << 7 in the equation."  Can you expand more on this? If we do *128 won't the result be the same?
     
    original equations in function
    hetRAM->Instruction[(pwm << 1U) + 41U].Data = (((pwmPeriod * signal.duty) / 100U) << 7U ) + 128U;
    hetRAM->Instruction[(pwm << 1U) + 42U].Data = (uint32)((pwmPeriod <<7U) - 128U);

    new equations in function
    hetRAM->Instruction[(pwm << 1U) + 41U].Data = (uint32)((((pwmPeriod * signal.duty) / 100U) * 128U ) + 128U);
    hetRAM->Instruction[(pwm << 1U) + 42U].Data = (uint32)((pwmPeriod *128U) - 128U);


    (original Halcogen)
    void pwmSetSignal(hetRAMBASE_t * hetRAM, uint32 pwm, hetSIGNAL_t signal)
    {
    uint32 action;
    uint32 pwmPolarity = 0U;
    float64 pwmPeriod = 0.0F;

    if(hetRAM == hetRAM1)
    {
    pwmPeriod = (signal.period * 1000.0F) / 1163.636F;
    pwmPolarity = s_het1pwmPolarity[pwm];
    }
    else
    {
    pwmPeriod = (signal.period * 1000.0F) / 1163.636F;
    pwmPolarity = s_het2pwmPolarity[pwm];
    }
    if (signal.duty == 0U)
    {
    action = (pwmPolarity == 3U) ? 0U : 2U;
    }
    else if (signal.duty >= 100U)
    {
    action = (pwmPolarity == 3U) ? 2U : 0U;
    }
    else
    {
    action = pwmPolarity;
    }

    hetRAM->Instruction[(pwm << 1U) + 41U].Control = ((hetRAM->Instruction[(pwm << 1U) + 41U].Control) & (~(uint32)(0x00000018U))) | (action << 3U);
    hetRAM->Instruction[(pwm << 1U) + 41U].Data = (((pwmPeriod * signal.duty) / 100U) << 7U ) + 128U;
    hetRAM->Instruction[(pwm << 1U) + 42U].Data = (uint32)((pwmPeriod << 7U) - 128U);

    }

    (Float Percision support version for fractional duty cycle)
    void pwmSetSignalFloat(hetRAMBASE_t * hetRAM, uint32 pwm, hetSIGNALFLOAT_t signal)
    {
    uint32 action;
    uint32 pwmPolarity = 0U;
    float64 pwmPeriod = 0.0F;

    if(hetRAM == hetRAM1)
    {
    pwmPeriod = (signal.period * 1000.0F) / 1163.636F;
    pwmPolarity = s_het1pwmPolarity[pwm];
    }
    else
    {
    pwmPeriod = (signal.period * 1000.0F) / 1163.636F;
    pwmPolarity = s_het2pwmPolarity[pwm];
    }
    if (signal.duty == 0U)
    {
    action = (pwmPolarity == 3U) ? 0U : 2U;
    }
    else if (signal.duty >= 100U)
    {
    action = (pwmPolarity == 3U) ? 2U : 0U;
    }
    else
    {
    action = pwmPolarity;
    }

    hetRAM->Instruction[(pwm << 1U) + 41U].Control = ((hetRAM->Instruction[(pwm << 1U) + 41U].Control) & (~(uint32)(0x00000018U))) | (action << 3U);
    hetRAM->Instruction[(pwm << 1U) + 41U].Data = (uint32)((((pwmPeriod * signal.duty) / 100U) * 128U ) + 128U);
    hetRAM->Instruction[(pwm << 1U) + 42U].Data = (uint32)((pwmPeriod *128U) - 128U);

    }

  • Hi Tammy,

    By *128 do you mean *128.0f, i.e. perform the multiplication as float * float then convert to integer?

    Thanks and Best Regards,
    Anthony
  • Hi. Thank you. No. What I mean is the "<< 7" is literally replaced with "* 128" so the equation is as follows:

    hetRAM->Instruction[(pwm << 1U) + 41U].Data = (uint32)((((pwmPeriod * signal.duty) / 100U) * 128U ) + 128U);

    instead of the HalCoGen generated

    hetRAM->Instruction[(pwm << 1U) + 41U].Data = (((pwmPeriod * signal.duty) / 100U) << 7U) + 128U;

    The reason we are asking is when we did calculation of one of our requirements to support from hardware engineers:
    duty cycle =1.5%
    period (usec) = 200000

    Calculation pwmPeriod = 171875.05 ( (period * 1000.0F) / 1163.636F)
     
    dry math calculation of ((((pwmPeriod * signal.duty) / 100U) * 128) + 128U) =  330128.09 -- with typecast around the entire = 330128

    equation since we have replaced the <<7 with *128 allowed, we only lose less than 1% precision (dropping after the decimal point .09)
    if we keep the <<7 the typecast has to executed prior to the <<7U which means the result is larger loss of precision (end result is then 330112 rather than 330128 if we rplace with *128)

    from the original dry calculation.

    ** What do you think?

    ** The HalCoGen code does not comment the actual code. What is the equation hetRAM->Instruction[(pwm << 1U) + 41U].Data = (((pwmPeriod * signal.duty) / 100U) << 7U) + 128U;  actually doing?

    ** What is the pwmPeriod = (period * 1000.0F) / 1163.636F; actually doing?  

    ** what is hetRAM->Instruction[(pwm << 1U) + 42U].Data = ((uint32)pwmPeriod << 7U) - 128U; doing?

  • Hi Tammy,

    Ah I think I see now. So basically if you change the <<7 to *128U the reason for more precision is that the compiler can either merge or re-order the /100 and the *128 for better precision? If so then I think it's fine and actually pretty darn smart / something we should analyze further for inclusion into HalCoGen.

    Regarding the last couple of equations, I think this is just to adjust for the way that the PWCNT instruction works. Prathap tried to answer this question in the post from July 31 in this thread:
    http://e2e.ti.com/support/microcontrollers/hercules/f/312/p/344034/1204662#1204662

    And you'd compare against the pseudo-code for the PWCNT instruction. It may have to do with the fact that the compare value triggers on a count of '1' not 0, but I'm not clear on this.
  • Hi. Thank you. Well the only reason we could see to try this was you had the patience to give such a good explanation on everything so thank you again for great support.

    I went to the link. Yes, I see how he explains the specific parameters in the equation, but may be I missed it where did he discuss what the end result represents in both equations? I have the manual open now chapter 20 NHET. Which sections are these two equations discussed. We just wanted to know what the end result represented. Is there a specific section or registers  we should look up in this chapter? I am scrolling through now, but have not found it yet.

  • Hi Tammy,

    This is actually a pretty interesting detail.

    Cody Addison who is one of our compiler leads answered my question about where you can reference if you want to be confident about how the cast from float back to int is performed:

    "Section 6.3.1.4 of the ISO/IEC 9899:1999(E) standard says

    When a finite value of real floating type is converted to an integer type other than _Bool,

    the fractional part is discarded (i.e., the value is truncated toward zero). If the value of

    the integral part cannot be represented by the integer type, the behavior is undefined."

    I don't have the ISO doc myself as it's expensive but you can find the same text in the draft doc from the working group page: http://www.open-std.org/jtc1/sc22/wg14/www/projects

    EDIT:  Updated the link above - most recent draft is N1570 but our compiler folks suggested N1256.

    Regarding the N2HET chapter,  for each instruction we have 'pseudo-code' representing the way that the instruction executes.

    So for example in the PWCNT instruction description the details of it's execution are given like this:

    I'm assuming at the moment that the + 128 referred to in the other post is related to the case where {Data Field Value == 1} is tested.

    Data Field in this pseudo-code is the upper 25 bits of the 32-bit data field.  The lower 7 bits would be referred to as 'HR DATA" or the like.
    That's how a +1 would in the pseudo code would translate to a +128 in a formula.

    I got started simulating the HET program and but it's a bit complicated because the host-side driver changes the pin action type when you set the duty cycle to 0% or 100% as opposed to other values.    Will let you know once I can explain more.

  • A few updates that might be of interest.  

    1st:  Just realized that the Cortex R4F has an instruction called 'VCVT' which supports direct conversion from floating point to fixed point with a (specified) radix.    So the entire calculation could be carried out in float,  and 'VCVT'd to a 25.7 fixed point number which then could be written directly to the N2HET's RAM.    Haven't tried this.  We currently do not have a compiler intrinsic for VCVT so it would need to be include as inline assembly or the function would be written in assembly.   We've requested that an intrinsic for VCVT get added to the compiler though, and would be interesting to experiment with this.

    2nd:  Got a little further along with an explanation of the HalCoGen black box program's PWM generation.

    I started with an 'equivalent' program but then stripped it down to just one PWM, one EDGE, one CAP operation so that the program would simulate faster and be easier to see on the waveform screen.    Additionally I added outputs of the PWCNT and DJZ data field so they would show up on the waveform.

    Hopefully the entire project is ready to go in the .zip file with the waveform screen setup as I have it shown in the image below.

    Anyway here is the project:  3146.test_pwcnt_2.zip

    And here is a picture of it being simulated:

    I believe that you can directly view the .VCD file and .btim that is stored in the .zip file above, and it will contain the trace data which is the source of the image above, in case you wanted to study and be able to zoom in/out.    You should be able to open these by launching Synapticad directly rather than through the HET IDE.   The file is small enough that it can be viewed with the free waveform viewer version.

    An explanation of the picture.

    First preliminaries:

       a. PWM period is set to a value of 3 and the duty cycle is set to a value of 4.      By this I mean that the
    25.7 fixed point numbers that are written into the MOV64 buffer instructions have values of 3.0 and 4.0 respectively.
       (The 32-bit hex values would be 3 <<7 and 4<<7 )

      b.  The program is very small, only 9 instructions, so I shortened the # of address bits displayed to just 4 so that the address can be seen more easily;  although in the image above it's still too small to read.  (But in the VCD it will be readable at a higher zoom level than if all 32-bits were displayed).

     c) I also shortened the loop resolution period from /128 to /16, again in the interest of visibility.


    Ok so here are some comments against the #'s super imposed on the image:

    (1) This is the first loop that is executed.  In this loop, both the PWCNT and DJZ values are 0 initially.  [although they show up in the waveform viewer as uninitialized .. this is a bug in the way the HET IDE displays waveforms, it drops the initial state from the VCD file.  But you can confirm the initial state by looking at the memory window.]

         During this loop the DJZ causes a branch to the MOV64 instructions.  You can see that a few instructions into the loop, first the PWCNT data field which
     is represented by the line labeled 'het.mem_0x10_data[15:7]' is initialized to a value of 003 and then the DJZ instruction's data field, represented by the next line of trace, is initialized to a value of 004.    (I also chose to not display the upper 16 bits for readability.. but they are zero).

    (2) you can see if you look closely that there are 8 or so 'toggles' on the address row of the trace.  This shows that all of the instructions including the buffer instructions (MOV64's) are executed during this loop.

    (3) for comparison, if you look *really* closely at the next loop you can see fewer instructions are executed.  This is because the DJZ does not branch to the buffer instructions in this loop  and all the loops up until point (6).

    (4) one might wonder why the PWM pin (#8) does not go high at this point.   The reason is that during the previous loop,  the PWCNT executed with a value of 0.  And if you remember from the PWCNT instruction pseudo-code in the previous posting, there is no pin action taken when PWCNT has a value of 0.
      The PWCNT data field is updated to a value of 003 during the previous loop, but this occurs *after* the PWCNT was executed..

         So near point (4) you can see that the current loop begins with a PWCNT value of 003.   When the PWCNT executes this time two things happen:

          a) since this result is not 0 and is not 1,  the PWCNT takes the pin action 'set high' and schedules this for the start of the next loop resolution period

          b) it's value is decremented from 003 to 002.

      You can see clearly in the waveform that the pin goes high but it's delayed until the start of the next loop resolution period.

    Also, if you watch the DJZ instruction it decrements here, but nothing happens because of this until it reaches 0 (at point (6).)


    (5) during this cycle PWCNT's value is 1. 

            a) this causes the opposite pin action (pin going low) to be scheduled for the start of the next loop resolution period.

            b) the value of PWCNT is decremented from 1 to 0,  and will stay 0 until it is re-initialized by the MOV64 buffer instruction.


    (6) at point 6, the DJZ instruction has counted down to 0 triggering another execution of the two mov64 instructions.  you can see how during this loop again more instructions are executed compared to other loops,  and how during this loop the PWCNT and DJZ instruction's data fields are re-initialized to the values 003 and 004.

    Pattern then repeats.

    So looking at this execution - you can see where the +1 comes from  (aka +128U).

    For the PWCNT instruction, an initial duty cycle count of 003 results in PWCNT executing 2 times with a count that is > 1,  so the high time lasts for 2 loop resolution periods.   Duty Cycle of 2 Periods requires that a count of 3 be written to PWCNT.

    For the DJZ instruction (period) there is also a +1 (aka +128U) as an initial value of 4 means that the pattern executes 5 times:  counts 4,3,2,1,0 before repeating..

    Next step is to program the stimulus to simulate how the HET IDE will also change the pin action field when values of 0 and 100% duty cycle are written.  I think we'll then see clearly why the 100%->0% immediate transition breaks down.

  • Hi Thank you. Will read through your reply carefully and will let you know if any questions. Were you ever able to get any info on what hetRAM->Instruction[(pwm << 1U) + 41U].Control , hetRAM->Instruction[(pwm << 1U) + 41U].Data , hetRAM->Instruction[(pwm << 1U) + 42U].Data were respresenting exactly? (from the earlier equations from HalCogen we had been discussing last week below)

    hetRAM->Instruction[(pwm << 1U) + 41U].Control = ((hetRAM->Instruction[(pwm << 1U) + 41U].Control) & (~(uint32)(0x00000018U))) | (action << 3U);
    hetRAM->Instruction[(pwm << 1U) + 41U].Data = (uint32)((((pwmPeriod * dutyCycle) / 100U) << 7U ) + 128U);
    hetRAM->Instruction[(pwm << 1U) + 42U].Data = ....

    Thank you again, and I hope you can get us a solution to the PWM 100%->0% transition requirement.
  • Hi Tammy,

    Do you mean what are the left hand sides representing?  

    hetRAM->Instruction[(pwm << 1U) + 41U].Control     -   Control field of MOV64 instruction which updates the PWM's PWCNT instruction

    hetRAM->Instruction[(pwm << 1U) + 41U].Data           -  Data Field of "

    hetRAM->Instruction[(pwm << 1U) + 42U].Data           -  Data Field of MOV64 instruction which updates the PWM's DJZ instruction

     

    When you build the program with the HET IDE (or het assembler) you don't need to do this funny math because one of the outputs is a header file which can be included by your host-side API and which allows you to refer to each instruction based on the label that you place on it in your HET assembly code.

    But the HalCoGen black-box demo isn't created with this flow, it was hand coded, and so the math is done based on the fixed program structure.

    If one were to add instructions between the PWCNT and DJZ,  this would mean the the hard-coded 41U offset would no longer be valid.  (you'd need to adjust for each instruction added.)  

    And the math also relies on all of the PWMs being grouped together and all the MOV64's being grouped together.
    For PWM0 the MOV64's are at address 41 and 42.   For PWM1 they are at 43 and 44.  For PWM2 they are at 45 and 46, and so on. This is where the (pwm << 1u) + 41u expression comes from.  

    If you're asking about the right hand sides,  then this:

    ((hetRAM->Instruction[(pwm << 1U) + 41U].Control) & (~(uint32)(0x00000018U))) | (action << 3U);

    Is basically an expression that reads the current control field, clears the 'pin action' bits, and then sets them to their new value.
    The pin action bits of the instruction control field determine what type of action the instruction schedules when it is triggered.

    For the other expression:

    (uint32)((((pwmPeriod * dutyCycle) / 100U) << 7U ) + 128U);

    This one we've talked about,  but just to repeat,  the compare value needs to be set to the duty cycle + 1 loop resolution period, because of how PWCNT operates, as described in the previous post.    The << 7U is just taking this whole number of loop resolution periods,  and positioning it so that it is in the 25.7 fixed point format that the N2HET uses internally. 

    It may have been clearer to write the expression like this:

    (uint32) ( ( (pwmPeriod * dutyCycle) / 100U) + 1U) << 7U );

    Since you're adding 1 count to the computed duty cycle compare value, then aligning to 25.7 format as a last step.

    Hope I answered the right question somewhere in there.  If not just let me know.    

     

  • Hi Thank you. Yes the left side of the "=" that the final value is placed. (You had sent me the link on the right side, but thank you for the explanation again). Thank you. We will wait to hear from you on the 100%-> 0% PWM problem and the work around for this requirement.
  • Hi Tammy,

    One step closer to the explanation.  Here is a simulation that you can run (if you want to) and it should reproduce the steps of the 0% to 100% transition.   Mainly posting because it's interesting,  and also shows how you can simulate some of the effect of the host side API's by using the Memory Trigger window of the HET GUI.

    Just need to analyze now and suggest a fix/workaround.

    8664.test_pwcnt_2.zip

    Above is a link to the project file.

    The simulation run shows the problem in the waveform view:

    And here you can see the memory trigger window setup to simulate the behavior of calls to the pwmSetSignal function.  (assuming period is kept constant and only duty cycle is changed.. I actually didn't bother to keep re-writing the same value back to period, although this would have been more accurate it has no effect.)

  • Hi Thankyou.

    - What software tool is that a screen shot of? Is it free or we have to purchase from TI? I didnot see it in Code Composer as a tool option(right now we have an actual Tektronix scope connected and we read that display).

    - You wrote that hetRAM->Instruction[(pwm << 1U) + 41U].Data is the Data Field of PWM's PWCNT instruction. pg 782 of TI reference manual

    "20.2.5.12 Pulse Measurement Example (in HR Mode)

    The PCNT instruction captures HR measurement of the high/low pulse time or periods of the input. As

    shown in Figure 20-21, at marker (1) the input goes HIGH and the HR counter immediately begins to

    count. The counter increments and rolls over until the falling edge on the input pin, where it captures the

    counter value into the HR capture register (marker (2)). The PCNT instruction begins counting when the

    synchronized input signal goes HIGH and captures both the 25-bit data field and the HR capture register

    into RAM when the synchronized input falls (marker (3))."

    So, for i.e., duty cycle  = 12 % and period = 25000 usec. if hetRAM->Instruction[(pwm << 1U) + 41U].Data = 330128, what does the value 330128 that do exactly in this process of capturing  HR measurement of the high/low pulse time or periods of the input? 

    - you wrote that hetRAM->Instruction[(pwm << 1U) + 42U].Data is data field of PWM's DJZ instructions

    on pg. 852 of reference manual

    "20.5.3.10 DJZ (Decrement and Jump if Zero)" is the DJZ. So i.e., for duty cycle = 12% and period = 25000 usec, pwmperiod = 21484.38 ((period * 1000)/1163.636 in code). Then hetRAM->Instruction[(pwm << 1U) + 42U].Data = 2749872.  So when is this field actually decremented and where does the CPU Jump to when this value hits "0"?

  • Tammy,

    The tool is free HET IDE: http://www.ti.com/tool/het_ide
    It is currently a standalone tool not integrated with CCS.

    Looking at the other questions that you asked in the previous post, I think there might be some confusion between PCNT and PWCNT.

    PCNT is used in the blackbox program for the capture section. It counts the number of cycles between two edges on the same input signal.

    PWCNT is a one-shot pulse generator. You program it with some width 'N' measured in loop resolution periods and as it counts down from N, N-1, N-2 .... 0 for all counts that are not 0 or 1, the PWCNT will schedule the pin 'action' to occur at the next loop boundary. For the count of '1' the 'opposite action' is scheduled. For a count of 0, the PWCNT basically stops.

    The DJZ also decrements but doesn't take any pin action. Instead once the DJZ reaches a count of 0 it will jump to the MOV64 instructions that 'reset' both the DJZ and the PWCNT instructions. This has the effect of retriggering the PWCNT.

    So to answer your last question, the HET CPU jumps to the MOV64 instruction for the corresponding PWM channel when the DJZ reaches 0.

    The 'working' counter for both the PWCNT and DJZ is held in the data field of the respective instructions. So if you watch DJZ's data field in the simulator you will see that it counts down.
    Think about this as a hardware down counter.

    Then the MOV64 register acts like the counter preload register, and the copy from this register to the counter only occurs when the MOV64 executes. The preload value is held in the data field of the MOV64 instruction. A MOV32 instruction would do the same as my simplistic example of a down counter 'preload'. But MOV64 does a little more, because it not only updates the DATA field of PWCNT it also updates the control field of PWCNT.
    So think about it as a preload register that also affects the action or settings of what occurs when the counter reaches 0. Our example code changes the pin action for the special cases of duty cycle 0% and 100% for example.
  • This link is only good for another week: https://txn.box.com/het-patches
    So if possible you might want to grab the files now. I can reset the link but I can't keep it alive more than a week at a time.

    In this folder we've got patched executables for the HET IDE, you might need to drop them in as replacements for the exe files in the official distribution. It depends on your PC configuration, but the official distribution uses a TCP/IP port 4245 to communicate between the front-end process of the IDE (GUI) and the simulator process. Recently there have been more and more conflicts with port 4245. So the patched files just ask the OS for the 'next open port' and use that port # for communication.
  • Hi Thank you. We have downloaded both files (HET.exe and Simulator.exe) now. Will try to run and let you know if there are any questions. Will also wait to hear from you on the 100%->0% PWM issue. Thank you again.
  • Ok - thanks Tammy.

    Just want to clarify, these .exe files are just patches that need to be dropped into an existing install of the HET IDE.
    So you have to download and install first from HET IDE: http://www.ti.com/tool/het_ide and then replace the two .exe files.

    Also, please make sure to note that HET.exe goes in the top level folder
    (ex. C:\Program Files (x86)\Texas Instruments\Hercules\HET)

    But the new Simulator.exe goes in the 'bin' subdirectory (ex. C:\Program Files (x86)\Texas Instruments\Hercules\HET\bin)

    Sorry I forgot to mention this before.

    EDIT:

    One more thing I forgot to mention is that the .prj file in the example I uploaded has hard-coded paths to the working folder on my PC.

    Since the .prj file in this case also contains the  <MemoryTriggers> section which took some time to setup,  I don't think you want to start a new .prj file.

    Unfortunately, you will need to open the .prj file in a text editor  (it is XML formatted) and change these entries;

    <HETProject ProjectName="test_pwcnt_2" ProjectPath="C:/Users/a0321811/home/work/hetproj" StimuliVCD="">


    and

     <SourceFile Path="C:/Users/a0321811/home/work/hetproj/test_pwcnt_2" Breakpoints="" Name="test_pwcnt_2.het"/>


    to paths that match the location you choose to work in on your PC.    Then I think you'll be able to open the .prj file and run it locally.

    If you try to open it without making these changes, I think you'll get errors (source file isn't found).

  • Hi Thank you. We are meeting with our hardware engineers today.

    1- Did you get any further having any work around/solution for requirement of PWM 100% -> 0%?
    2- In HalCoGen, if we wanted one PWM to trigger another is that configured via the HalCoGen GUI, or manually in the driver code?
  • Hi Tammy,

    1) Not yet, sorry. I got called into jury duty last week and am now getting caught up on things.

    2) No the PWMs in the black-box as far as I understand don't support that.
    It would be easy enough to modify the black box driver code to do something like this.
    You can already see how the MOV64 instructions re-trigger the same PWM at the end of it's period.
    So you could add 2 more MOV64 instructions to a chain of events such that they trigger a 2nd PWM
    but only when the 1st one finishes a period.
  • Hi Thank you. I will let them know more time is needed for investigation for #1. On #2 So what you mean is just doing another function call for the 2nd pwm after we have called the first function. How can we known for certain that the 1st one's period has completed with 100% certainty?
  • Tammy,

    For #2 I would suggest adding another pair of instructions similar to these two:

    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};
    

    These two instructions re-trigger PWM 0 after PWM 0's period has finished.  (As the DJZ instruction branches to BUF0_D on result 0).

    So let's say that you want to retrigger PWM0 so it's continuous, but also trigger another PWM to start at the completion of PWM0.

    You could add two more instructions

    BUF0_D1   similar to above

    BUF0_P1   similar to above

    And instead of 'next=PWM_1D' for BUF0_P, you could change BUF0_P to 'next=BUF0_D1'.  

    So the execution flow on DJZ=0 for PWM0 could be:

     PWM_P0:    DJZ = 0 for PWM0, branch to BUF0_D

     BUF0_D   -> retrigger pulse on PWM0

     BUF0_P   -> retrigger period on PWM0

     BUF0_D1 -> trigger pulse on some other PWM pin

     BUF0_P1  -> trigger period on some other PWM pin, branch back to PWM_D1

     PWM_D1....

    Of course you may just want to trigger a pulse on another PWM pin as a one-shot.  That's doable too,  just disable it's own retrigger capability so that the only way it's triggered is from PWM0.

    Also note that for all instructions in N2HET you can specify the next instruction address with the 'next=' parameter.

    So you could add BUF0_D1 and BUF0_P1 to the END of the blackbox program.  This would mean your customized program could use most all of the same existing host-side drivers as come with the HalCoGen blackbox program...  because you wouldn't need to change the equation for the index into the HET RAM that the pwmSetSignal function uses if you don't move the location of the existing "BUF" instructions.

    Further if you always wanted PWM1 to be triggered by PWM0 and never retrigger itself, then you could just use the BUF1_P and BUF1_D locations as is to specify the period and duty.  But the path to execute these would be modified so that they occur only at the end of the period of PWM0, and you would disable the DJZ instruction in PWM_P1 from jumping to BUF1_P.

    There's probably a million other ways to handle the same task though,  above suggestions are just to minimize changes to the blackbox driver.

  • Hi. Thank you. Is there any news on the 100% to 0% issue and work around (our requirement that some of PWMs can do). Our hardware engineers have to make decision by tomorrow morning if we can use the RM48L952 PWM or if we have to find an off-chip PWM solution. We would like to stay using the RML952ZWT PWM module if possible. What do you suggest?
  • Hi Tammy,

    No, unfortunately not.

    The HET can definitely handle your requirements though, so I wouldn't recommend using an off-chip PWM solution.
    I just can't give you an easy fix for the HalCoGen driver at the moment other than to avoid 100%->0%.

    The HET program posted here: e2e.ti.com/.../1002667
    can handle these type of corner cases if you want to try it just to confirm that it can be done. It generates 6 PWMs
    (3 complementary pairs) and both the period and duty cycle are specifiable with 1 HR-Clock (~10ns) resolution.
    So you could consider using this program (with modifications to suit your app) as a contingency plan in case it's too much trouble
    to fix the blackbox driver.
  • Hi Thankyou. I will let the team know we need to give TI some more time. The hardware engineers originally said no when I asked them to consider the 100% -> 1% -> 0%, but I will discuss with them this as a temporary solution until we hear back from you. Do you have a root cause yet on why 100%->0% doesn't work? Thank you again.
  • Tammy,
    I think that the opposite action may never occur when you set the PWM to 100% because you can see that the PWCNT value is set > the DJZ value. But that's just a guess. So a workaround would need to detect 100% -> 0% in one jump and handle this differently.
  • Hi. Thank you. Let me know if you have root cause and something for us to try as workaround.