Special question to multiple Thread initialisation

Technical questions regarding the XTC tools and programming with XMOS.
Mahagon
Member++
Posts: 24
Joined: Thu Mar 07, 2013 4:24 pm

Special question to multiple Thread initialisation

Post by Mahagon »

Hello xCore community, its me again!

Today i have a very special question to the par{} statement.

Following situation (i try to explain it as easy as i can, it's quiet complex in real):

I have a main task that is doing some really cool stuff! (haha :P)
At one special point in my program (and that program is really really huge), i want to initalize 2 other tasks. Lets take for example the UART Rx and Tx modules from xSOFTip library. They shall run on two other Threads, but on the same tile (to avoid that "you have to do it in main function"-answer :-D). Now, as some of you may know, that 2 UART functions will never return (they got an endless loop inside for UART receiving/transmitting).

1. Question: The par statement that calls the UART functions, will also never return right? Because the 2 other Threads never gonna end.

2. Question: Is there any possibilty to return back to my main task, but still letting the UART Threads run concurrently?

I ask that because at the moment i have the problem, that i cannot call back into the function, that originally calls the par{} statement, if one of the Threads includes an endless loop (that means i have to init another function inside the par{}, that goes on on the calling thread. But I dont like that for many reasons.). Please notice, that i know about the option, to initialise all that stuff at the very start of my program (so the par statement doesnt need to return anyway). But for the moment just let say i cant do so ;-). Maybe it's impossible to avoid that for the future, i know :)

I'll hope my question is not too stupid and i was able to explain my problem.

Greetings :-)


User avatar
xsamc
Active Member
Posts: 55
Joined: Fri Mar 04, 2011 3:38 pm

Post by xsamc »

Hi Mahagon,
Mahagon wrote:1. Question: The par statement that calls the UART functions, will also never return right? Because the 2 other Threads never gonna end.
Correct, the parent function of the par will wait for all the tasks in the par to complete, before continuing. If the tasks in the par never complete, the parent will never continue past the end of the par statement.
Mahagon wrote:2. Question: Is there any possibilty to return back to my main task, but still letting the UART Threads run concurrently?
This is possible yes, but not from xC (which enforces fork-join behaviour of pars). If this really is the route you want to go in, I'd suggest familiarising yourself with the XS1 architecture manual and assembly programming manual to begin with.
Mahagon wrote:I ask that because at the moment i have the problem, that i cannot call back into the function, that originally calls the par{} statement, if one of the Threads includes an endless loop (that means i have to init another function inside the par{}, that goes on on the calling thread. But I dont like that for many reasons.). Please notice, that i know about the option, to initialise all that stuff at the very start of my program (so the par statement doesnt need to return anyway). But for the moment just let say i cant do so ;-). Maybe it's impossible to avoid that for the future, i know :)
If you're writing this application in xC, I would have thought the structure would be something like:

Code: Select all

int main()
{
    initiation_stuff();
    pre_uart_really_cool_stuff();
    par
    {
        uart_rx();
        uart_tx();
        really_cool_stuff();
    }
    
    return 0; //Won't be getting to here, the UART never stops!
}
But it sounds like this is the very approach you're trying to avoid...

Is the behaviour of the program before UART is required different to after the UART has performed its useful operation?
If not, you could stop the UART tasks once you know that all the required data has been sent/received. How about modifying the UART to either know when it has completed and stop itself, or run a third task in parallel to signal to the UARTs to let them know when they should stop?

Cheers,
Sam
Mahagon
Member++
Posts: 24
Joined: Thu Mar 07, 2013 4:24 pm

Post by Mahagon »

Hi XSAMC,

Thank you very much, im quiet happy that i was able to explain my problem sucessfully. The program structure you've admitted is like the exact way its working right now ;)

I awaited such an answer. Well, so i have an acknowledgement for my thoughts.

But honestly i really like the idea to modificate the UART processing itself, maybe thats easiest way to fix it. So i can start and end UART just on the fly. Well, performance wont be the best, but thats not the point atm.

And if i have a lot of time, maybe i'll try to get more familiar with assembly programming.

Thanks again.
User avatar
xsamc
Active Member
Posts: 55
Joined: Fri Mar 04, 2011 3:38 pm

Post by xsamc »

Hi Mahagon,

No problem :)

I guess if you modify the UART to stop itself when done, the structure might look more like this:

Code: Select all

void really_cool_stuff()
{
    while (1) // This is the main application task, which never completes
    {
        ... // doing stuff

        if (special_case) // When special_case is true, we need to enable UART
        {
            ... // special case initialisation
            par
            {
                uart_rx(); // UART rx task will stop itself when it has completed useful operation
                uart_tx(); // UART tx task will stop itself when it has completed useful operation
            }
            ... // special case tidy up
        }
        ... // doing other stuff
    }
}

int main()
{
    initiation_stuff();
    really_cool_stuff();
    
    return 0; //Won't be getting to here, we never run out of cool stuff to do!
}
Best of luck with the rest of your project!
Cheers,
Sam
User avatar
segher
XCore Expert
Posts: 844
Joined: Sun Jul 11, 2010 1:31 am

Post by segher »

If you're wondering why XC has this restriction, ponder this:
where will you put the stack for these threads? That will also
tell you how to implement this behaviour manually (with a
little bit of assembler code :-) ).