Communication between two tasks

If you have a simple question and just want an answer.
cschopges
Member++
Posts: 28
Joined: Mon Jul 25, 2016 2:03 pm

Communication between two tasks

Postby cschopges » Wed Mar 22, 2017 8:11 am

Hey everybody,

I have a program with two tasks which are performing real-time operations on output ports where they read some incoming data. Moreover I want these two tasks to communicate together without being blocked since they might miss infos on the bus otherwise.
Thus task1 needs to send data to task 2 and receive data from task 2. The same applies for task 2.

What is the best way to implement the communication?
I've thought about using two channels, once for each communication direction. The main problem is that one task will always be blocking waiting for the other one. What time does it take to send a byte over the channel?
I've also thought about inserting a third task between the two tasks which would act as a buffer. But then, should I use channels or iterfaces? How much channels/interfaces do I need?
peter
XCore Addict
Posts: 230
Joined: Wed Mar 10, 2010 12:46 pm

Postby peter » Wed Mar 22, 2017 9:21 am

You could use streaming channels in both directions as in that case the data is simply posted to the channel by the producer instead of having to be synchronised with the receiver. The only things to be aware of are that there is only two words of buffering in a channel end receive buffer (so the producer will block if it sends more than that before the consumer has taken some out). The other thing to note is that there are a maximum of 4 streaming channels between tiles (no limit beyond total number of channels when using cores on the same tile).
cschopges
Member++
Posts: 28
Joined: Mon Jul 25, 2016 2:03 pm

Postby cschopges » Wed Mar 22, 2017 9:27 am

Thanks for the reply,

I've thought of that, the only problem is that I am sending 15 bytes at a time... So it will always be blocking right?
peter
XCore Addict
Posts: 230
Joined: Wed Mar 10, 2010 12:46 pm

Postby peter » Wed Mar 22, 2017 9:29 am

Are the cores on the same tile? You could send a pointer to the 15 bytes.
cschopges
Member++
Posts: 28
Joined: Mon Jul 25, 2016 2:03 pm

Postby cschopges » Wed Mar 22, 2017 9:38 am

They are on the same tile.
So you suggest sending a pointer through a streaming channel?
peter
XCore Addict
Posts: 230
Joined: Wed Mar 10, 2010 12:46 pm

Postby peter » Wed Mar 22, 2017 9:43 am

It all depends on how much you are looking for the optimal solution to this problem or whether you are looking to create a generic and scalable solution that will work regardless of where the cores are in the system. If you want a generic solution then I would recommend using a decoupling core which both cores interact with.

However, if you are looking for a low-overhead version which only has to run on a single tile, then personally I'd pass a pointer between the cores - remembering that you're going to be needing the double-buffering to ensure that once the pointer is passed the ownership has been handed over to the other core so a new block of memory is required to write data into.
cschopges
Member++
Posts: 28
Joined: Mon Jul 25, 2016 2:03 pm

Postby cschopges » Wed Mar 22, 2017 2:20 pm

Two more questions:
If I use a decoupling core, should it communicate with the other two cores via channels or interfaces?

If I use the streaming channels, do you know where I can find an example of a structure passed via pointer on a channel? I'm having some trouble doing it...
cschopges
Member++
Posts: 28
Joined: Mon Jul 25, 2016 2:03 pm

Postby cschopges » Wed Mar 22, 2017 2:46 pm

A quick example:

Code: Select all

#include <print.h>

typedef struct my_struct {
  unsigned id1;
  unsigned id2;
  unsigned id3;
  unsigned id4;
  char data[8];
} my_struct;

void print_msg(my_struct f, char prepend[]){
  printstr(prepend);
  printhex(f.id3);
  printstr("\t");
  if(f.id2)
    printstr(" : Ext\t");
  else
    printstr(" : Std\t");
  if(f.id1)
    printstr(" : R \t");
  else
    printstr(" : D \t");
  printint(f.id4);
  printstr("\t");
  if(!f.id1)
    for(unsigned i=0;i<f.id4;i++){
      printhex(f.data[i]);
      printstr("\t");
    }
  printstrln("");
}

void task1(streaming chanend c_to)
    my_struct * unsafe test;
    unsafe{
        c_to :> test;
        print_msg(*test, "received: ");
    }

}

void task2(streaming chanend c_to){
    my_struct rx_buff;
    unsafe{
        my_struct * unsafe test = &rx_buff;

        test->id1 = 0;
        test->id2 = 1;
        test->id3 = 0x18da29F1;
        test->id4 = 3;
        test->data[0] = 0x02  ;
        test->data[1] = 0x21;
        test->data[2] = 0x01;
        test->data[3] = 0x0;
        test->data[4] = 0x0;
        test->data[5] = 0x0;
        test->data[6] = 0x0;
        test->data[7] = 0x0;

        //print_msg(*test, "send: ");
        c_to <: test;
    }
}

int main(){
    streaming chan c_to;
    par{
        task1(c_to);
        task2(c_to);
    }
    return 0;
}


If I uncomment //print_msg(*test, "send: "); it works, otherwise not. Why? I can't figure it out.
Moreover, does everything needs to be in an unsafe region?
peter
XCore Addict
Posts: 230
Joined: Wed Mar 10, 2010 12:46 pm

Postby peter » Wed Mar 22, 2017 3:17 pm

It is working for me with/without the print uncommented. I've added a loop so that the pointer gets sent back and forth and the message gets changed. All seems to work.
cschopges
Member++
Posts: 28
Joined: Mon Jul 25, 2016 2:03 pm

Postby cschopges » Wed Mar 22, 2017 3:44 pm

Without the print it is not working for me... I don't get the correct data back.
Attached the two different results I get:
Image

Image
Any ideas?

Who is online

Users browsing this forum: No registered users and 18 guests