Loopback strobe buffered serialized ports shift data by 1bit

Technical discussions around xCORE processors (e.g. xcore-200 & xcore.ai).
Post Reply
User avatar
Julien
Member++
Posts: 16
Joined: Mon Feb 22, 2010 4:43 pm
Location: France
Contact:

Loopback strobe buffered serialized ports shift data by 1bit

Post by Julien »

Hello all,

I am still experimenting with XMOS devices. Today, I have a question about ports.

My goal is simple: Set-up a loopback communication between 2 threads via pins connected together. The hidden goal is to learn how XMOS ports are working to connect to other devices in the future.

So my first guess was to connect 2 1-bit ports together (dataOut and dataIn) and 2 others for the clockOut and clockIn signals. I discovered that the clock was permanently running even without data (already explained in this forum) which makes my receiving thread a bit confused, so I added a strobe signal (in and out).

Here I am with my setup (running on XK-1 board as well as on Sparkfun XS1-L1-64 board):
  • 6 x 1-bit ports connected by pair: dataIn - dataOut, clockIn - clockOut and readyIn - readyOut.
  • 2 threads, one sending data on the buffered port once a second, the other reading that data and sending it up through UART.
The sending thread always sends the same data: 0xA7712002. This is a "random" value easy to catch on my oscilloscope. Unfortunately, the reading thread do not receive that value, but 0x4ee24004 the first time, followed by 0x4ee24005. If you look carefully at the received value, it is simply the sent value left-shifted by 1bit. The MSb is found on the following received LSb.

Looking at the signals on my oscilloscope, I can see that data, clock and strobe signals are perfectly in accordance with documentation: Strobe signal goes high on clock's falling edge, data starts at the same time. Data is stable on clock's rising edges (when inPort is supposed to read). Finally strobe goes low on the last clock's falling edge.

So I wonder where I am wrong, and what should I do to make this very simple experiment works on my boards... Any help is welcome!

Here is the main part of the code (the complete code is attached) for easier understanding:
ioport.zip
The complete code for Sparkfun XS1-L1-64 board. Use your xn file to compile it. E.g.: xcc -O0 -g -Wall ioport.xc -o ioport.xe XC-5.xn
It seems that xc files are not allowed as attachments, so the file is zipped!
(1.03 KiB) Downloaded 295 times
ioport.zip
The complete code for Sparkfun XS1-L1-64 board. Use your xn file to compile it. E.g.: xcc -O0 -g -Wall ioport.xc -o ioport.xe XC-5.xn
It seems that xc files are not allowed as attachments, so the file is zipped!
(1.03 KiB) Downloaded 295 times

Code: Select all

int main(void)
{
    unsigned int my_data = 0xA7712002;

    in_config(inP, inClock, inReady, inClk);
    out_config(outP, outClock, outReady, outClk, 100);

    par {
        output(my_data, outP);
        input(inP);
    }
    
    return 0;
}
The ports configuration follows:

Code: Select all

void out_config(out buffered port:32 outP, out port outClock, 
                out port outR, clock clk, unsigned clkrate)
{
    configure_clock_rate(clk, 100, clkrate);
    configure_out_port_strobed_master(outP, outR, clk, 0);
    configure_port_clock_output(outClock, clk);
    start_clock(clk);
}

void in_config(in buffered port:32 inP, in port inClock, 
               in port inR, clock clk)
{
    configure_clock_src(clk, inClock);
    configure_in_port_strobed_slave(inP, inR, clk);
    start_clock(clk);
}
And finally the 2 threads (DELAY is 100000000 => 1 second delay)

Code: Select all

void output(unsigned int data, out buffered port:32 tx)
{
    timer t;
    unsigned time;

    t :> time;

    while (1) {
        time += DELAY;
        t when timerafter (time) :> void;
        tx <: data;
    }
}

void input(in buffered port:32 inP)
{
    unsigned int data = 0;

    while (1) {
        inP :> data;
        print_hex(data);        
    }
}
Thanks for your help!
Julien


User avatar
Andy
Respected Member
Posts: 279
Joined: Fri Dec 11, 2009 1:34 pm

Post by Andy »

I've had a quick look and I think the problem might be with your transmitByte().

I'm not 100% sure how the sparkfun board works but if it uses the standard USB programming dongle you should be able to replace your print_hex() function with the built in printhexln() in print.h.

If it works with the built in printhexln() then I suspect you're going wrong somewhere in your UART. Have you tried the new UART reference code on xmos.com?
User avatar
Julien
Member++
Posts: 16
Joined: Mon Feb 22, 2010 4:43 pm
Location: France
Contact:

Post by Julien »

Hello Andy, thanks for your answer,
Andy wrote:I've had a quick look and I think the problem might be with your transmitByte().

[...]you should be able to replace your print_hex() function with the built in printhexln() in print.h

If it works with the built in printhexln() then I suspect you're going wrong somewhere in your UART. Have you tried the new UART reference code on xmos.com?
Well, I also suspected that and made a smaller program with the receiving thread expecting the sent value and light a LED if it receives it, and another one if it doesn't and I've got the same behavior: the "error" LED is always ON. That why I used UART (which, by the way, works perfectly in my other programs) to "see" the received value.

I'll send the smaller program for XK-1 today. In the meantime, thanks for your answer. If somebody has other ideas, feel free to answer!
Andy wrote:I'm not 100% sure how the sparkfun board works but if it uses the standard USB programming dongle[...]
Actually the Sparkfun board use a standard FTDI chip for UART/USB communication. It uses two 1-bit ports (RX/TX) and can go as fast as 3Mbps. I don't really like the xrun --uart myprog.xe thingy: Can not set the baudrate, can't use my standard terminal program, ...

Regards,
Julien
User avatar
Julien
Member++
Posts: 16
Joined: Mon Feb 22, 2010 4:43 pm
Location: France
Contact:

Post by Julien »

Andy wrote: If it works with the built in printhexln() then I suspect you're going wrong somewhere in your UART. Have you tried the new UART reference code on xmos.com?
OK, I just tried with Andy's suggestion and I've got exactly the same behavior as described above: sending 0xA7712002, receiving 0x4EE24005.

Attached is the xk1 code of this example, using <print.h>.
ioport-xk1.zip
XK-1 board port loopback test program. Compile using XK-1.xn file
e.g.: xcc -O0 -g -Wall ioport.xc -o ioport.xe XK-1.xn
xrun --uart ioport.xe
(701 Bytes) Downloaded 263 times
ioport-xk1.zip
XK-1 board port loopback test program. Compile using XK-1.xn file
e.g.: xcc -O0 -g -Wall ioport.xc -o ioport.xe XK-1.xn
xrun --uart ioport.xe
(701 Bytes) Downloaded 263 times
Feel free to try it on your own XK-1 board. You have to connect XD0-XD1 (clock); XD10-XD11 (strobe); XD13-XD14 (data) with 3 jumpers to make it works.

Any feedback is welcome!
Regards,
Julien
User avatar
Julien
Member++
Posts: 16
Joined: Mon Feb 22, 2010 4:43 pm
Location: France
Contact:

Post by Julien »

Hello again,

More news about my problem. To sum up the problem, I send once a second 0xA7712002 on a 1-bit buffered port and read one 0x4EE24004 followed by many 0x4EE24005. Looking carefully at my waveforms and reading the documentation, it seems that the input port starts to sample data 1-bit too early (i.e. one clock rising edge too soon).
The first time, input pin is in zero state, thus the first bit read is '0' (Least significant bit) and then the data bits are read: '0', '1', '0', '0' ... which should be 0x2 (as in 0xA7712002) but makes 0x4 because of the first "phantom" bit. The MSb of my data is '1', so the output pin stays in state 1 at the end of the first transmission. Similarly, the next read starts one bit too soon and '1' is read first, then the data bit ... which makes 0x5 (0b0101) instead of 0x2 (0b0010) because of the extra bit read.

Now comes the strange thing. In my desperate seek of the truth, I dug in the online doc provided by the tools at file:///$HOME/path/to/xmos/tools/DesktopTools/9.9.1/doc/libs/html/index.html and found the function call set_port_sample_delay(). This causes the port to sample input data on the falling edge of its clock. As I already said, the data on my oscilloscope is stable on clock's rising edge. But anyway, I added the call for set_port_sample_delay() in my input port config and it MAGICALLY works now! :shock:

There is something wrong here. It works either because of luck, the output port is outputting data just before the input port is reading it, on clock's falling edge; or because documentation is wrong and set_port_sample_delay() makes the input port to sample data on clock's rising edge as expected.

Anyone to confirm my guesses?
Sorry for the lengthy messages, now I'll wait for your ideas!

Cheers,
Julien
User avatar
Andy
Respected Member
Posts: 279
Joined: Fri Dec 11, 2009 1:34 pm

Post by Andy »

Hey Julien,

Sorry I called it wrong originally... I've had a closer look and have replicated this behaviour in the simulator. I'm not sure why set_port_sample_delay() works but the waveform looks fine without it so I was surprised that the wrong value was being read.

I concluded that the value in the shift register was wrong (for reasons unknown) and added a clearbuf() to your config functions:

Code: Select all

void out_config(out buffered port:32 outP, out port outClock, 
                out port outR, clock clk, unsigned clkrate)
{
    configure_clock_rate(clk, 100, clkrate);
    configure_out_port_strobed_master(outP, outR, clk, 0);
    configure_port_clock_output(outClock, clk);
    clearbuf(outP);
    start_clock(clk);
}

void in_config(in buffered port:32 inP, in port inClock, 
               in port inR, clock clk)
{
    configure_clock_src(clk, inClock);
    configure_in_port_strobed_slave(inP, inR, clk);
    clearbuf(inP);
    start_clock(clk);
}
This seems to fix the problem. Perhaps someone at XMOS could explain why this is? I'd certainly like to know as it doesn't appear in many (any?) of the documentation or tutorials as a necessity.
User avatar
Julien
Member++
Posts: 16
Joined: Mon Feb 22, 2010 4:43 pm
Location: France
Contact:

Post by Julien »

Hi Andy, hello all,
Andy wrote:Hey Julien,

Sorry I called it wrong originally... I've had a closer look and have replicated this behaviour in the simulator. I'm not sure why set_port_sample_delay() works but the waveform looks fine without it so I was surprised that the wrong value was being read.
No worries. I was in the same situation with my oscilloscope...
Andy wrote: I concluded that the value in the shift register was wrong (for reasons unknown) and added a clearbuf() to your config functions:
[...]
This seems to fix the problem. Perhaps someone at XMOS could explain why this is? I'd certainly like to know as it doesn't appear in many (any?) of the documentation or tutorials as a necessity.
That's exactly the conclusion I came to last night! I use clearbuf() only for the output port and it works like a charm.
I would also be glad to get some more information from XMOS about this "behavior" too...

So the final guess is that the output port emits a "phantom" bit at the beginning of the program and the input port gets shifted for the rest of the execution. The clearbuf() doc says that any data output by the processor which has not been driven by the port is discarded, which seems to solve the problem.

Thanks Andy to confirm the problem and for your solution. I'll keep the clearbuf() but I think we need more explanation from XMOS.

Cheers,
Julien
richard
Respected Member
Posts: 318
Joined: Tue Dec 15, 2009 12:46 am

Post by richard »

This is a tools bug. It is the same issue discussed in this thread:

http://xcore.com/forum/viewtopic.php?f=10&t=232

You can get a glitch on the ready signal when configure_out_port_strobed_master() or configure_out_port_strobed_handshake() is used. This is enough to misalign the data. A clearbuf() will clear the ready out signal or alternatively you can use the function in the thread above.

The configure_out_port_strobed_master() and configure_out_port_handshake() functions will be fixed in the next tools release.
User avatar
Andy
Respected Member
Posts: 279
Joined: Fri Dec 11, 2009 1:34 pm

Post by Andy »

richard wrote:This is a tools bug. It is the same issue discussed in this thread:

http://xcore.com/forum/viewtopic.php?f=10&t=232.
I thought it sounded familiar :lol:
User avatar
Julien
Member++
Posts: 16
Joined: Mon Feb 22, 2010 4:43 pm
Location: France
Contact:

Post by Julien »

Thanks Richard for the full explanation. Hopefully the new tool release will come soon :)

Anyway, I'll stick with the clearbuf() trick.

Regards,
Julien
Post Reply