Streaming Channels and Blocking mechanism

New to XMOS and XCore? Get started here.
Post Reply
dimitris
Active Member
Posts: 37
Joined: Tue Feb 19, 2013 5:07 pm

Streaming Channels and Blocking mechanism

Post by dimitris »

Hi all,

I have a question about a weird reaction of the XMOS.
I have a simple code with a function that reads an I2C digital sensor and one tat prints those values. They both run on different threads. sense() sends the values to print() through a streaming channel. Since that is the case, I expect sense() not to block while print() prints.

Below you can find my code and a series of pics. I run this code two times with one small difference. The printintln() line was first active and then commented out.

Code: Select all

#include <platform.h>
#include <print.h>
#include <xs1.h>
#include "i2c.h"

#define GE_ADDR 0x68
#define GE_PIX_LOW 0x80
#define GE_PIX_HIGH 0x81

r_i2c i2cOne = {on tile[1]:XS1_PORT_1F, on tile[1]:XS1_PORT_1B, 1000};

void sense(streaming chanend pix_temp_chan){

	int adc_value;
	int i=0;
	unsigned char pix_temp_low[1];
	unsigned char pix_temp_high[1];
	int pix_temp[64];
/************************************************
 * PANASONIC GRID-EYE
 ************************************************/
	while(1){
		pix_temp_low[0]=0;pix_temp_high[0]=0;
		for(i=0;i<64;i++){
			i2c_master_read_reg(GE_ADDR, GE_PIX_LOW, pix_temp_low, 1, i2cOne);
			i2c_master_read_reg(GE_ADDR, GE_PIX_HIGH, pix_temp_high, 1, i2cOne);
			pix_temp[i] = (pix_temp_high[0] << 8) | pix_temp_low[0];
			if(pix_temp_high[0] != 0){
				pix_temp[i] = - (2048 - pix_temp[i]);
			}
			pix_temp_chan <: pix_temp[i];
		}
	}
}

void print(streaming chanend pix_temp_data){
	int data;
	while(1){
		pix_temp_data :> data;
		printintln(data);
	}
}

int main() {
	streaming chan pix_temp_chan;
	par {
		on tile[1]: sense(pix_temp_chan);
		on tile[1]: print(pix_temp_chan);
	}
	return 0;
}
Moreover I am posting a couple of pics taken from my scope. Those pics show the clock and data signals of the I2C protocol. The first one is with printinln() active and the second with printintln()commented out.
In the first picture you can see that the I2C clock only works for a short period. The rest of the time it is dead (i assume that the sense() function is blocked while the print() function prints).
If I comment the printintln() line, then the scope gives the second picture. There you can see that the I2C clock is really dense, meaning that there is no blocking.
My question is, since I am using two parallel cores, with a streaming channel, shouldn't both functions work without blocking?

Kind regards,
Dimitris
Attachments
20120922_382427.jpg
(118.34 KiB) Not downloaded yet
20120922_382427.jpg
(118.34 KiB) Not downloaded yet
20120922_382345.jpg
(120.64 KiB) Not downloaded yet
20120922_382345.jpg
(120.64 KiB) Not downloaded yet


User avatar
lilltroll
XCore Expert
Posts: 956
Joined: Fri Dec 11, 2009 3:53 am
Location: Sweden, Eskilstuna

Post by lilltroll »

I do not know if this will answer your quastion but I give it a try.
The standard print.h uses the JTAG chain to send a message from any tile to the XTAG2 and finally to the computer. It is a simple but slow method, and it destroy all type of realtime on that tile.

If you have a board that connects a 2 wire XLINKS to the XTAG2 or 2 UART pins you can use them instead of using the JTAG chain.
Using the UART you need a thread running a small UARTserver on the tile connected to the XTAG2.

I'm not updated with the status of the latest code for this, and it was a year since I played with this. (I wrote a graphical console to my XDK instead, that I could print text to over channels)
User avatar
Bianco
XCore Expert
Posts: 754
Joined: Thu Dec 10, 2009 6:56 pm
Contact:

Post by Bianco »

Printing using JTAG may halt the complete core and thus may mess up your timing.
You can use the XMOS xScope functionality, a real UART or something else.
I prefer to buffer the values that I want to print and print them at a later time.
User avatar
segher
XCore Expert
Posts: 844
Joined: Sun Jul 11, 2010 1:31 am
Contact:

Post by segher »

A streaming channel is not non-blocking.

A "normal" XC channel does a little synchronisation dance before and
after every transaction, so that the transaction is only done when both
sides of the channel are ready for it (each side waits until the other is
ready). This isn't done for streaming channels.

But streaming channels can still block. If your channel goes via an
external link, it will block when credits run out (so you have e.g.
64 bytes written that are not sent out yet -- external links are
quite slow compared to internal links). It's even easier to block an
internal link: the buffer is only 8 bytes (IIRC). So if the other end
isn't currently reading from the channel, your writes to it will soon
block.

The usual solution to this is to have a separate thread that constantly
reads from the channel, writing the data to some buffer; and another
thread that reads from the buffer, writing it to your debug device.
You can of course multiplex these threads using events (XC "select",
etc.)
dimitris
Active Member
Posts: 37
Joined: Tue Feb 19, 2013 5:07 pm

Post by dimitris »

Dear segher,
I like your idea more. I now have three routines, sense(), buf() and print(), but still I can't find a way that this won't block! Please excuse my "newbieness" and offer me some more context on how to solve these problems.
How can I read and print 64 integers and without blocking the reading process?

By internal link you mean the buffer used between two threads right?
User avatar
lilltroll
XCore Expert
Posts: 956
Joined: Fri Dec 11, 2009 3:53 am
Location: Sweden, Eskilstuna

Post by lilltroll »

After verifying that each core was working by it's own it was easy to make things work.

Now I am Streaming 6250 (32-bit) ksamples/s from a L1-64 through a L1-128 to a L1-64, passing 2 steps of isolators, so far without any problem.
User avatar
segher
XCore Expert
Posts: 844
Joined: Sun Jul 11, 2010 1:31 am
Contact:

Post by segher »

Hi Dimitris,

I'm not sure where your misunderstanding is. Maybe post your current
code?
dimitris wrote:By internal link you mean the buffer used between two threads right?
Yes, sorry. The buffers in the channel ends themselves.
Post Reply