asm in select (custom "case" statement)

Technical questions regarding the XTC tools and programming with XMOS.
User avatar
BBenj
Member++
Posts: 21
Joined: Fri Sep 13, 2013 3:00 pm

asm in select (custom "case" statement)

Post by BBenj »

Hello

I'm using inline asm to create and use "custom" chanend in a task (to have many-to-one/one-to-many links and save resources) with an event. It works fine, but I would like to use it with a conventional XC select-case statement to handle other events like timers or ports.

By taking a look to the disassembly of some basic xc task code, I saw that there is a clre instruction at the beginning of the select implementation, so:
- I can't setup my event before the select
- I need to add my event setup code in the setup part of the select implementation

But how to add custom asm code in that part of the code ?

And is it possible to create a custom case block to handle the event (in a "clean" way) ? I found a possible working solution by using a label just before the select and branching to it after the execution of my code. It's not very clean, but it should work if I find a way to enable the chanend event.

Any solution is welcome !
Thanks !

Some code for illustration...

Code: Select all

void task()
{
    // Setup
    // inline asm to setup chanend

    while (1) {
    asm("selectsetup:");
    select {   // insert custom asm to setup my chanend event
        case custom:    // Custom case statement to handle chanend event
        {
            // Handle chanend event
        }
        case t when timerafter(time) :> void:    // Juste for example
        {
            // Code
        }
    }}

    // Code to process chanend event
    asm("chanendvector:");
    ... // Custom code
    asm("bu selectsetup");
}


User avatar
BBenj
Member++
Posts: 21
Joined: Fri Sep 13, 2013 3:00 pm

Post by BBenj »

Found a way, finally... was not easy, I'm still learning how to properly use inline asm...
Next step: put my code in a separate asm file and (find how to) use it inside my .xc file.

Another suggestions are still welcome !

Code: Select all

void task()
{
    unsigned Chanend;

    // Setup
    // inline asm to setup chanend
    Chanend = GETR_CHANEND();

    while (1) {
    asm("setupevent:");
    // inline asm to setup event:
    asm("mov r3, %0" :: "r"(Chanend) : "r3");
    asm("clre	\n"
           "ldap r11, chanendvector	\n"
           "setv res[r3], r11	\n"
           "eeu res[r3]	\n");

    asm("bu 1");  // Skip the clre instruction of the select

    select {
        case t when timerafter(time) :> void:    // Juste for example
        {
            // Code
        }
        case p_button_0 when pinseq(0) :> void:
        {
            /*PORT HANDLER*/
            break;
	}
    }}

    // Code to process chanend event
    asm("chanendvector:");
    asm("chkct res[%0], 0x1" :: "r"(Chanend));
    asm("in r2,res[%0] " :: "r"(Chanend));
    asm("setd res[%0],r2" ::"r"(Chanend));
    asm("outct res[%0], 0x1" :: "r"(Chanend));
    ...
    asm("bu setupevent");
}
User avatar
Ross
XCore Expert
Posts: 972
Joined: Thu Dec 10, 2009 9:20 pm
Location: Bristol, UK

Post by Ross »

Is it good enough to write a select handler function in asm? Below is an example based on the USB codebase:

E.g. example.h (note the #pragma)

Code: Select all

#pragma select handler
void XUD_SetData_Select(chanend c, unsigned &tmp);

Code: Select all

Example.S:
//void XUD_SetData_Select(chan c, unsigned &x);
//                        r0,     r1         r2
.globl   XUD_SetData_Select
.globl   XUD_SetData_Select.nstackwords
.linkset XUD_SetData_Select.nstackwords, 4

XUD_SetData_Select:
    entsp       4
    // Some ASM code....
    retsp        4
You can then write:

Code: Select all

void test_select(chanend c)
{
  unsigned x;
  select
  {
     case XUD_SetData_Select(c, x):
        //...
        break;

     // More cases..
  }
}
User avatar
BBenj
Member++
Posts: 21
Joined: Fri Sep 13, 2013 3:00 pm

Post by BBenj »

Thanks for that example.
I just tried, but there is a problem: the first argument of a select handler must be a chanend (or any "transmissive" type, port/timer/chanend I guess).
But in my code I don't use a chanend explicitly, I use asm to get the resource and save it to an unsigned variable. And so I have the error "incompatible type for argument 1" if I pass an unsigned instead of a chanend… and reinterpretation/cast to resource type is disallowed (of course).

Maybe there is a turnaround ?