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.

ADM32 Instruction Behavior in N2HET on RM46

Consider the following N2HET program.

PWM_PERIOD		.equ 10
PWM_PIN_U		.equ 0
PWM_PIN_U_BAR		.equ 3
PWM_PIN_V		.equ 1
PWM_PIN_V_BAR		.equ 4
PWM_PIN_W		.equ 2
PWM_PIN_W_BAR		.equ 5
INIT_COMPARE		.equ 5
INIT_HR_DELAY		.equ 0

L00:	CNT{next=L01, reqnum=0, request=GENREQ, reg=A, irq=OFF, max=PWM_PERIOD};
L01:	ECMP{next=L03, hr_lr=HIGH, en_pin_action=ON, cond_addr=L02, pin=PWM_PIN_U, action=PULSELO, reg=A, irq=OFF, data=INIT_COMPARE, hr_data=INIT_HR_DELAY};
L02:	MOV32{remote=L01,type=IMTOREG&REM,reg=NONE,data=INIT_COMPARE,hr_data=INIT_HR_DELAY};
L03:	BR{next=L04, cond_addr=L04, event=Z, reqnum=1, request=GENREQ}
L04:	ECMP{next=L06, hr_lr=HIGH, en_pin_action=ON, cond_addr=L05, pin=PWM_PIN_V, action=PULSELO, reg=A, irq=OFF, data=INIT_COMPARE, hr_data=INIT_HR_DELAY};
L05:	MOV32{remote=L04,type=IMTOREG&REM,reg=NONE,data=INIT_COMPARE,hr_data=INIT_HR_DELAY};
L06:	BR{next=L07, cond_addr=L07, event=Z, reqnum=2, request=GENREQ}
L07:	ECMP{next=L09, hr_lr=HIGH, en_pin_action=ON, cond_addr=L08, pin=PWM_PIN_W, action=PULSELO, reg=A, irq=OFF, data=INIT_COMPARE, hr_data=INIT_HR_DELAY};
L08:	MOV32{remote=L07,type=IMTOREG&REM,reg=NONE,data=INIT_COMPARE,hr_data=INIT_HR_DELAY};
L09:	MOV32{remote=L02,type=REMTOREG,reg=B};
L10:	ADM32{type=IM&REGTOREM, remote=L11, reg=B, data=10};
L11:	ECMP{next=L12, hr_lr=HIGH, en_pin_action=ON, cond_addr=L12, pin=PWM_PIN_U_BAR, action=PULSEHI, reg=A, irq=OFF, data=INIT_COMPARE, hr_data=INIT_HR_DELAY};
L12:	MOV32{remote=L05,type=REMTOREG,reg=B};
L13:	ADM32{type=IM&REGTOREM, remote=L14, reg=B, data=10};
L14:	ECMP{next=L15, hr_lr=HIGH, en_pin_action=ON, cond_addr=L15, pin=PWM_PIN_V_BAR, action=PULSEHI, reg=A, irq=OFF, data=INIT_COMPARE, hr_data=INIT_HR_DELAY};
L15:	MOV32{remote=L08,type=REMTOREG,reg=B};
L16:	ADM32{type=IM&REGTOREM, remote=L17, reg=B, data=10};
L17:	ECMP{next=L18, hr_lr=HIGH, en_pin_action=ON, cond_addr=L18, pin=PWM_PIN_W_BAR, action=PULSEHI, reg=A, irq=OFF, data=INIT_COMPARE, hr_data=INIT_HR_DELAY};
L18:	BR{next=L00, cond_addr=L00, event=NOCOND}

The rationale behind the program is to restrict the HTU channel usage to just three. the first part Generates the High side sinoside by getting the compare values from the HTU. the second part loads the compare value from the high side instructions, add a deadband time (10 cycles) and generate the Low side sinoside.

I am able to generate the sinosides perfectly, But the deadband does not work as intended. On the increasing values of the sinoside the dead band works fine, but on the decreasing values, it seems to subtract from the compare value, resulting in the pulse overlap instead of a deadband. 

  • Safiullah,

    The ADM32 instruction adds, it doesn't subtract.

    Have you tried to reproduce your problem in the HET IDE? I'd do that because then you can step through and see what the register and memory values are doing.

    We have a post e2e.ti.com/.../1004426 that has a good implementation of a center aligned 3 phase PWM w. deadband. It has one latent issue that you should try to fix before deploying (it's described in the post) but it's an issue on the counter overflow so you can go a long way with this code as-is.
  • About the issue, I have tried it in the HET IDE and it works out fine there. I am looking at the oscilloscope waveforms and they seem to be this way.

    I will check out the code. Thanks.
  • Is there an associated host-side program with HTU that you have for this?
  • No - no host side code. Wouldn't be that much different from what you're doing now though - except I think you won't have trouble w. the deadband and with 0% to 100% duty cycle like you will likely have with the simpler program.
  • I went through your code, and boy it is extensive. I had no idea the N2HET module could do this much. My programs look like hello world examples.

    I dont see you using the HTU to call the compare values from an (or multiple) LUTs. I was hoping to do that so the I can run the more higher level code in peace on the host side and not worry about interrupts and next value updates.

    I have been able to resolve one issue in my old code but I traded that with another. When running both code with the HTU modification, it seems that some HTU requests get lost. I need a mechanism (feedforward with maybe instruction padding or constant wait cycles or something, or a feedback mechanism like the request complete trigger, or a control tranfer in between) to ensure that my compare values from the LUTs for all three phases are in.
  • Hi Safiullah,

    You're right - this program doesn't use the HTU. It was written for a motor control application where the ADC would be triggered in the mid of each PWM period, then the CPU would execute the motor ISR and write new values back to the HET. Since the CPU is always doing computation for each PWM the HTU could be used but may be a bit of diminishing returns.

    I've always (personally) been concerned about the lack of handshake between HTU and HET - there's nothing automatic. So when the HET makes the request - your code either a) assumes that during the next loop, new values for period etc. have been updated by the HTU, or b) does something to check this first.

    To do b) you pretty much have to implement your own handshake. You might do something like reserve a 'valid' bit in one of the words that the HTU transfers, and clear this valid bit with the HET when the HET consumes the data. Or you could instead of transferring 3 values, add a 4th value to the HTU transfer which is a 'sequence count'. The HET could check the count to see if the data is updated or is stale.

    For reads -- HTU reads data from HET RAM and writes to CPU RAM, there is a flag in some of the instructions which causes the data field to be cleared to zero on a read .. I think it's called the 'control' flag. I haven't tried this but it may be a simpler way to create a handshake for transfers from HET to CPU RAM.

    Best Regards,
    Anthony
  • Anthony,

    One other thing I 'd like to ask is some behavior of the ECMP instruction when the pin action is enabled. Unless a ECMP instruction (and in some cases the CNT instruction executes in every loop, the pins dont get updated. This restricts the possibility of writing a very complex program that has some(or any flow control aspects involved. like for example:

    -> Update count -> reg A till MAX

    -> If reg A is 0 request 0 and goto LOOP

    -> If reg A is 1 request 1 and goto LOOP

    ...

    -> Compares here

    -> LOOP

    What's the deal with that?

    Regards,

    Safi

  • Safiullah,

    I don't think I understand the question well (or at least the example.. I understand the question about ECMP just not the example..)

    So for ECMP this is a timing function - like a capture compare register. As such it needs to run continuously in most cases - just like a hardware compare register continually monitors a counter.
    (NB.. it actually doesn't need to run continously, but if you don't run the compare continuously then if the count matches during a loop where the compare *isn't* run - then you'll miss that '==' event - and in most cases that's not OK).

    There is an MCMP instruction that you might consider instead of ECMP for this use case, because it's compare is >= not == so if it happens to miss the cycle where the counter matches exactly - it may trigger on a subsequent cycle.

    Or you can use the SHFT instruction with "Always" as the condition if you want to shift a value out onto a pin during a particular cycle. You can use this to set a pin high or low.
  • (NB.. it actually doesn't need to run continously, but if you don't run the compare continuously then if the count matches during a loop where the compare *isn't* run - then you'll miss that '==' event - and in most cases that's not OK). 

    Ah, that pretty much answers it.

    The other things which I have noticed, at least in Waveform viewer, is that if one ECMP instruction turns the en_pin_action field OFF for a particular pin (the intent is that since ECMP instruction only compiles with a pin field, I give it a pin but I dont want the action to be reflected onto the pin, at least from this instruction), and another turns it ON. the pin action is not reflected on the waveform. moving to another pin solves the issue.

  • Hi Safiullah,

    There is actually a restriction that only one ECMP per loop can operate on a given pin. It should be one ECMP with 'hr' mode but I think there is an errata that says it's basically just one ECMP.
    This is because for each pin there is one dedicated 'hr' structure which is a fixed 7 bit timer to give high resolution for scheduling and timestamping events within the loop resolution period.

    If you need to use two ECMP on the same pin, what you have to do is to take a pair of pins, say 0 & 1, and use one of the AND/XOR share modes to combine the logical pins 0,1 into an output on physical pin 0. Each pair of adjacent HR structures can be combined this way.

    Same applies to hi-res inputs but you use the HRSHARE function to measure the same physical pin on two adjacent timer channels.