Page 1 of 2

Communication between two tasks

Posted: Wed Mar 22, 2017 8:11 am
by cschopges
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?

Re: Communication between two tasks

Posted: Wed Mar 22, 2017 9:21 am
by peter
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).

Re: Communication between two tasks

Posted: Wed Mar 22, 2017 9:27 am
by cschopges
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?

Re: Communication between two tasks

Posted: Wed Mar 22, 2017 9:29 am
by peter
Are the cores on the same tile? You could send a pointer to the 15 bytes.

Re: Communication between two tasks

Posted: Wed Mar 22, 2017 9:38 am
by cschopges
They are on the same tile.
So you suggest sending a pointer through a streaming channel?

Re: Communication between two tasks

Posted: Wed Mar 22, 2017 9:43 am
by peter
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.

Re: Communication between two tasks

Posted: Wed Mar 22, 2017 2:20 pm
by cschopges
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...

Re: Communication between two tasks

Posted: Wed Mar 22, 2017 2:46 pm
by cschopges
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?

Re: Communication between two tasks

Posted: Wed Mar 22, 2017 3:17 pm
by peter
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.

Re: Communication between two tasks

Posted: Wed Mar 22, 2017 3:44 pm
by cschopges
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?