Basic Task Communication via Channel / LED Blink Topic is solved

Technical questions regarding the XTC tools and programming with XMOS.
maxmatteo
Member++
Posts: 20
Joined: Wed Dec 30, 2020 8:11 pm
Location: Hamburg

Basic Task Communication via Channel / LED Blink

Post by maxmatteo »

I am trying to wrap my head around doing communication across tasks.

this is a simple led blink example, which unfortunately hangs and does not work:

one tasks blinks via a timer, the other should update the delay value. (btw: is there something to get proper milliseconds?)

Code: Select all

#include <platform.h>
#include <xs1.h>
#include <stdio.h>

port led = XS1_PORT_1F;

void blink_led(chanend c) {
    timer t; 
    unsigned time_now;
    unsigned time_last = 0;

    int delay = 1000000;
    
    led <: 0;
    
    int state = 0;

    while (1) {

        select {
            case c :> delay:
                printf("Updated delay: %d\n", delay);
                break;
            default:
                continue;
        }
        
        t :> time_now;

        if (time_now - time_last >= delay){
            time_last = time_now;
            state = state^1; // toggle
            led <: state;
        }
    }
}

void read_delay(chanend c) {
    int delay;
    while (1) {
        printf("Enter delay: ");
        scanf("%d", &delay);
        c <: delay;
    }
}

int main( void ) {

    chan c;

    par {
        blink_led(c);
        read_delay(c);
    }
    
    return 0;
}
View Solution
danielp
Active Member
Posts: 33
Joined: Tue Jul 16, 2024 9:52 am
Location: Bristol, UK

Post by danielp »

maxmatteo wrote: Wed Feb 05, 2025 2:26 pm (btw: is there something to get proper milliseconds?)
timer.h contains delay_milliseconds (and similar for seconds and microseconds) which blocks on the thread for that period of time.
XMOS, Senior Software Engineer
maxmatteo
Member++
Posts: 20
Joined: Wed Dec 30, 2020 8:11 pm
Location: Hamburg

Post by maxmatteo »

thanks for the fast reply, but my problem is the "hanging" select block here,

how am i able to pass in the the delay value via the channel into the blink_led task?

tried this, but it does not work:

Code: Select all

        select {
            case c :> delay:
                printf("Updated delay: %d\n", delay);
                break;
            default:
                continue;
        }
danielp
Active Member
Posts: 33
Joined: Tue Jul 16, 2024 9:52 am
Location: Bristol, UK

Post by danielp »

In your select block, the continue in

Code: Select all

            default:
                continue;
applies to the while loop, not the select, so if there is nothing to read on the channel, execution will go to the next iteration of the while loop, and so the code below the select will only run on the iteration where you take an input from the channel. I think this is what gives the appearance of a "hang" in the select block, so you could change the continue to a break so that execution always continues to the time check below.
XMOS, Senior Software Engineer
maxmatteo
Member++
Posts: 20
Joined: Wed Dec 30, 2020 8:11 pm
Location: Hamburg

Post by maxmatteo »

thanks for the input.

it seems to me that the whole blinking task hangs due to it being a normal channel as mentioned in the docs.

using a `streaming chanend` sounds like the solution as its async, but does not work :/

Code: Select all


#include <platform.h>
#include <xs1.h>
#include <stdio.h>

port led = XS1_PORT_1F;

void blink_led(streaming chanend c) {
    timer t; 
    unsigned time_now;
    unsigned time_last = 0;

    int delay = 10000;
    
    led <: 0;
    
    int state = 0;

    printf("started blink");

    while (1) {

        t :> time_now;

        printf("loop start\n");

        select {
            case c :> delay:
                printf("Updated delay: %d\n", delay);
                break;
            default:
                printf("default\n");
                break;
        }

        if (time_now - time_last >= delay){
            time_last = time_now;
            state = state^1; // toggle
            led <: state;
        }

        printf("looped\n");
    }
}

void read_delay(streaming chanend c) {
    int delay;
    while (1) {
        printf("Enter delay: ");
        scanf("%d", &delay);
        c <: delay;
    }
}

int main( void ) {

    streaming chan c;

    par {
        blink_led(c);
        read_delay(c);
    }
    
    return 0;
}

danielp
Active Member
Posts: 33
Joined: Tue Jul 16, 2024 9:52 am
Location: Bristol, UK

Post by danielp »

A streaming channel isn't necessary; your channel communications look fine to me. I removed the debug prints and changed the read_delay loop to periodically send changes to the delay rather than taking an input with scanf and I saw these delay updates communicated over the channel and the LEDs were flashing at the expected frequencies.

I've never used scanf to read input into a running program, so I would suggest looking into that as the source of the problem, as the rest of the code looks good to me.
XMOS, Senior Software Engineer