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.

TMS570 HTU to main CPU memory transfer in dual buffer mode



Hi there,

To receive an asynchronous serial data stream from a NHET pin (1 Mpbs), I'm setting up the HTU in dual-buffer mode to transfer data from the NHET to the main memory with auto-switch mode turned ON, let say, with 10 elements in each buffer.

During normal operation there is no problem:

  • BufferA full: interrupt to main CPU and next HTU transfer to BufferB automatically set
  • BufferB full: interrupt to main CPU and next HTU transfer to BufferA automatically set
  • In both cases, the CPU reads 10 elements at a time

However, given the asynchronous serial data nature, there is a case when the data stream stops for an indetermined lap of time (possibly will resume later but I don't know when) and I want to read and empty the buffer being written (to minimize delay and other performance reasons).

In the TMS570 reference manual (June 2010 Edition), page 1390, para. 19.2.1.4, it suggests that:

 

There could be a case where the CPU wants to do main memory operations, but does not want the HTU modifying the main memory. It could happen that a request was already active, but the frame transfer hasn’t started yet when the application disabled the control packets. The timing diagram in Figure 19-8 shows this scenario.

Since the request for the transfer was already received before the DCPx is disabled, the HTU will still start the frame transfer. The application would poll the BUSYx bit during the time the DCPx was disabled and before the frame was started and would read a non-busy information. It then would start the main memory operations thinking all transfers have completed, however after some time the HTU will start the outstanding frame transfer and corrupt the main memory.

To avoid this, the application can set the VBUSHOLD bit to disable all transactions between the HTU and the main memory. It has to poll the BUSBUSY bit to ensure that no outstanding transactions on the bus are pending. The HTU will still receive all transfer requests from the NHET, but it will not be able to transfer any data to or from the main memory, while the VBUSHOLD bit is set.


 Questions:

  1. It is not clear on the suggested order of operations here. Should I set VBUSHOLD or poll the BUSBUSY bit first?
  2. If setting VBUSHOLD first, does this operation interrupt the currently transfer frame immediately, if any? This is a problem because it is a data loss condition.
  3. If polling the BUSBUSY bit first, how can I ensure that between the polling of BUSBUSY and setting of VBUSHOLD there is no new initiated frame transfer?

  • Chuck,

    We have received your question, and one of our expert will be back to you.

  • Bonjour Jean-Marc,

    Thank you very much!

    Chuck.

  • Chuck,

    Assume that you have a system level mechanism to detect the time out condition of the data input to NHET. Assume that the current buffer is for control packet A. In your time out processing, you can simply switch to control packet B so that HTU will transfer the new data to buffer for control packet B. Then CPU can process the data in the buffer for control packet A. 

    In order to process data left in control packet A buffer, you need to determine the number of data in the buffer. You need to first poll the busbusy bit for control packet A to make sure that the transfer is complete in case there is a pending transfer when you switch the control packet. Then you can read the transfer count field in the old control packet to decide how many data has been transferred.

    Please let me know if the above answers your question.

    Thanks and regards,

    Zhaohong

  • Thank you Zhaohong,

    Yes I am going to implement a timeout mechanism using the same signal inputting to another NHET pin. The NHET processing of this signal will obviously use a different register than the one used for the timestamp and signal edge detection.

    Since I'm really new to the wonderful NHET world, can you suggest the instructions that I should use for the timeout detection?

    Another question: If all buffers A+B are cleared (or set to all 0xF) after reading by the CPU, can I discard the part of checking the OLD Current Buffer Count that you've suggested (check the buffer values instead)? Just want to confirm my understanding.

    Thanks again.

  • Zhaohong,

    I figured out that maybe I should use the DJZ instruction coupled with the MOV32 instruction. Is the following sounds?

     

    L00         CNT    { next=L01, reg=A, comp=EQ, irq=OFF, max=0x1FFFFFF }

    L01         WCAP   { next=L02, reg=A, pin=CC0, irq=OFF, event=BOTH, reqnum=0, hr_lr=HIGH, data=0, hr_data=0 }

    The logic should continue to:

    L02     If WCAP detects an edge: next=L03; otherwise: next=L04

    L03     Reprogram the register used by the DJZ by using the MOVE32 instruction: next=L04

    L04     Execute the DJZ instruction (interrupt will be generated if register reaches zero): next=L00

     

    My problem is I don't know how to implement L02, L03 and L04 using NHET instructions.

    Any help would be highly appreciated.

  • Chuck,

    There are many ways to check the time out condition. The following is just one idea for you to consider.

    Assume that in normal operation, HTU generates interrupt every 10 ms worst case. Assume that you have another timer interrupt happening every 30 ms. In the timer interrupt service routine, you check and set a flag saved in RAM. In the HTU interrupt, you clear this flag. If you see this flag is set in timer interrupt service routine, it shows that the HTU interrupt has been inactive for the past 30 ms. You may want to declare timeout for this condition.

    As you said in you message, you do not know when the data will come in. There are chances that a HTU transfer is triggered when you switch the control packet. Depending on the timing of the request, this transfer could be handled by the control packet before switching. You need to make sure that you do not miss any data. Be sure to follow the following sequence..

    (1) Switch control packet.

    (2) Poll the bus busy flag for the control packet before switching to make sure that there is no pending transfer.

    (3) Read the control packet before switching to determine the number of data have been transferred to the buffer.

    (4) Process the data.

    Please let me know if your question is answered.

    Thanks and regards,

    Zhaohong

  • Chuck,

    Would you please explain what functionality you want to achieve with the NHET code you posted?

    Thanks and regards,

    Zhaohong

  • Sure Zhaohong,

    We're building a software decoder for an 1 Mpbs Manchester data stream (clock and data are mixed into the same analog signal). The signal of the stream is variable with different duty cycle in the waveform. The shortest transition changes are every 500 ns (0.5 us) and the longest are 1 us (averaging ~1.5 million transitions/second). To decode this signal with software, one of the solutions is to capture a timestamp and the direction of the transition (failling or rising edge) then analysis it. We expect two words of some 1600 bits each every 10 ms.

    It is almost unthinkable to get the CPU interrupted every 500 ns, since the CPU would have other tasks to perform. This is why I want to use the HTU for the transfer between the NHET and the CPU.

    We will clock the CPU at 100 MHz, leaving the NHET's peripheral bus VBUS2 running at 50 MHz, and I want to configure the NHET HR=1 (only 20 ns) per HR and the LR will be configured in function of the number of instructions required to do what has to be done.

    Implementation wise, I plan to have the same Manchester signal fed into two different NHET pins, one for the actual signal decoder and the other (with the same signal), to the timeout reset mechanism that will be implemented within the NHET. I think that I can handle the algorithm side of the design, but since I'm really new to the TMS570, I lack the knowledge on the implementation using the NHET, hence my support request to your knowledgeable guys (I hope not to spend 2 months to understand all the NHET).

    Here is what I want to translated into NHET code:

     

    L00: Start a free-running timer for timestamp capturing purpose (REG_A), goto L01

    L01: Search for an edge in pin #1. When found, trigger the HTU to transfer the contents of CF and DF into one of the double buffers in RAM (the HTU will trigger interrupt to CPU once buffer full), goto L02

    L02: Start a second timer with predefine counter value for the timeout mechanism (REG_B), goto L03 (obviously, I can't restart this on every loop cycle, how to do that)

    L03: Search for an edge in pin #2. When found, reset timeout register REG_B, goto L00

    L04: Execute DZJ, when =0, request CPU interrupt, reset timeout register REG_B, goto L00

     

    Your proposed solution is perfectly valid, I believe, but because of the tight timing, I really want to use the NHET to detect timeout.

     

    Can you help?

  • Hi Zhaohong,

    I was wondering whether I should expect further posts from you to help me out ...

    Thanks.

     

  • Chuck,

    You can try the following in your application.

    L00         CNT    { next=L01, reg=A, comp=EQ, irq=OFF, max=0x1FFFFFF }
    L01         WCAP   { next=L02, reg=A, pin=CC0, irq=OFF, event=BOTH, reqnum=0, hr_lr=HIGH, data=0, hr_data=0 }
    L02         CNT    { next=L03, reg=A, irq=ON, max=0x1FF }
    L03         WCAP   { next=L01, reg=A, cond_addr=L04, pin=CC1, event=BOTH, data=0}
    L04         MOV32  { next=L01, remote=L02, reg=NONE, type=IMTOREG&REM, data=1}

    Instructions L01 and L02 are for the capture of the input signal from pin0. L02, L03, L04 is for checking the timeout condition. An interrupt is generated when the count is reset to zero after reaching the max value. Any rising or falling edge on pin 1 (assume that pin1 is connected to pin 0) will set the count value in L02 to 1. You can adjust the max value in L02 for the time suitable for your application. Since NHET is constantly running, you may see the interrupt from L02 for multiple times if the input is inactive for some long time.

    When using NHET to capture a pulse, please make sure that the minimum period of the pulse has to be larger than 2xLRP time. The HR field only adds more accuracy of reading. in other words, the rise-to-rise and fall-to-fall time has to be larger than 2xLRP. On the current devices, WCAP sometimes cannot capture HR field correctly for some timing condition. This issue will be fixed in new revision of silicon.

    I hope that you have all the information you need for this question.

    Thanks and regards,

    Zhaohong

  • Zhaohong,

    Thank you for all the insights and that looks very good. I just need a couple of clarifications:

    1. Should L02 and L03 use "reg=B" instead?
    2. Will jumping from L01 to L02 result in the reset of REG_B=0x1FF (if question 1 above is taken) at each LR? ... I must missed something?
    3. L00 is executed only once at the beginning (no jumping back because L03 and L04 jump to L01) but will nonetheless decrement REG_A on every LR, is this correct?

    Basically I'm getting confuse on points 2 and 3 above.

    Suppose that response to point 2 above is negative and I can add cond_addr=Lxx to the WCAP instruction (so I can use only one signal pin for both edge detection and timeout mechanism), is my code below correct (one instruction faster than using two pins)?

    L00    CNT     { next=L01, reg=A, comp=EQ, irq=OFF, max=0x1FFFFFF }       ; counter for timestamp
    L01    CNT     { next=L02, reg=B, comp=EQ, irq=ON, max=0x1F }      ; counter for timeout mechanism
    L02    WCAP    { next=L00, reg=A, pin=CC0, irq=OFF, event=BOTH, reqnum=0, hr_lr=HIGH, data=0, hr_data=0, cond_addr=L03 }       ; edge detection to trigger HTU line 0
    L03    MOV32    { next=L00, reg=B, remote=L01, type=IMTOREG&REM, data=0x1F }       ; reset timeout counter at both register B and data field of L01 CNT

    Regards,

    Chuck.

    Edited: L03 MOV32 data field should be "data=1", as Zhaohong has pointed out.

  • Chuck,

    I have a typo in my post. the next address for L02 and L03 should be L00. For the CNT instruction, the count value is updated before execution from the data field.  The data field is updated after execution. The register can be reused when the value is no longer needed. I think that your code should work. I think there is one typo. the data field for L03 should be 1.

    Please click the verify button if you think that this question is answered.

    Thanks and regards,

    Zhaohong

  • Sorry Zhaohong,

    Just one point: in L03 data=0x1F, I meant to reset both REG_B and data field of L01 CNT instruction to 0x1F (reset the timeout counter when edge is found). Is there a problem in my understanding?

    To reduce interrupts generated by L01 after timeout (on every LR after frist timeout), can I reprogram L01 to irq=OFF, then re-turning irq=ON once an edge is detected again? (I will write more lines of code).

    Thanks again.

    Chuck.

  • Chuck,

    CNT is counting up. When the register value reaches max, it will be reset to zero. If interrupt is enabled , NHET will generate an interrupt request to CPU. In your case, the max value is 0x1f. If the data field has a value of 0x1f, the interrupt will be generated in next LRP. You can check TRM to see how CNT instruction work in more detail.

    Thanks and regards,

    Zhaohong

  • I got it now. Thank you very much.

    Chuck.