struct containing channels

Technical discussions related to any XMOS development kit or reference design. Eg XK-1A, sliceKIT, etc.
extremeRider
Member++
Posts: 19
Joined: Tue Jun 16, 2015 10:50 pm

struct containing channels

Post by extremeRider »

Hi,
I'm developing a software interface for a gps breakout board.
The GPS provides a uart port for tx/rx.

I would like to use the serial library for XMOs devices on https://github.com/xcore?utf8=%E2%9C%93&query=uart

I was thinking to organize all the stuffs about serial communication in a struct like this:

Code: Select all

typedef struct {
    in port  rx;
    out port tx;
    int baudrate;
    chan crx;
    chan ctx;
} uart_com;
But when I try to compile, I get a couple of errors saying


error: field `crx' has resource type
error: field `ctx' has resource type


Is it possible to include channels into a structure?
User avatar
Ross
Verified
XCore Legend
Posts: 1077
Joined: Thu Dec 10, 2009 9:20 pm
Location: Bristol, UK

Post by Ross »

What about a pointer to a channel? I've not tried it myself to be honest..
Endre
Active Member
Posts: 38
Joined: Fri Jan 01, 2016 10:13 am

Post by Endre »

It's very annoying that in xC it is impossible to group stuff (variables, resources, etc.), which logically belongs together, into structs.
The lack of this ability can result ugly codes.

E.g. I'd like to implement some packet based USB communication code for more endpoints. I'd use a structure like this for storing all the info required for handling an endpoint:

Code: Select all

typedef struct {
    chanend ch;
    XUD_ep outEp;
    PtrBuffer freeBuf;
    PtrBuffer usedBuf;
    server interface ComRxIf rxIf;
} RxDesc;
Unfortunately I cannot place the "chanend" and the "interface" into the struct.
Than what can I do?
1. Don't use structs, just pass every related variables and resources to every handler functions. -> This is ugly and bloated.
2. Implement as much as possible in C and provide xC callouts for the XMOS specific stuff. -> Even more ugly and bloated.
3. ?

I'd rather like to be able to write well structured xC code, than to expect extra safety from the compiler.
Maybe the code safety shouldn't be a compile time issue. The source also could be compiled in some debug mode which would add some run-time safety checkers (of course this approach would require deep testing which is an extra job).
Endre
Active Member
Posts: 38
Joined: Fri Jan 01, 2016 10:13 am

Post by Endre »

Sorry for the loud thinking, I just have an idea to group stuff together without using structs.
In my example before I attempted to handle more USB endpoints in one task, and I attempted to group all stuff of an endpoint into a struct (which is not possible).
Maybe it is possible to make a combinable task which handles only one endpoint and instantiate this task for each endpoint on the same core. Communication between the task instances could be handled by a distributable task. I don't know the feasibility of this, I haven't tried it out yet.
User avatar
ers35
Active Member
Posts: 62
Joined: Mon Jun 10, 2013 2:14 pm

Post by ers35 »

As Ross indicated, movable pointers make this possible. See the following example:

Code: Select all

// xcc -target=XCORE-200-EXPLORER struct-res-pointers.xc -o struct-res-pointers.xe

interface bar
{
  void test();
};

struct foo {
  chanend *movable cptr;
  server interface bar *movable bar_if;
};

select handler(struct foo &f)
{
  case *f.cptr :> unsigned:
  {
    break;
  }
  
  // A bug in tools 14.1.2 prevents this from working.
  // I reported the bug.
  /*
  case *f.bar_if.test():
  {
    break;
  }
  */
}

void loop(chanend c, server interface bar bar_if)
{
  struct foo f;
  chanend *movable cptr = &c;
  f.cptr = move(cptr);
  server interface bar *movable barptr = &bar_if;
  f.bar_if = move(barptr);
  
  while (1)
  {
    select
    {
      case handler(f);
    }
  }
  
  // move back to original value
  cptr = move(f.cptr);
  barptr = move(f.bar_if);
}

int main()
{
  chan c;
  interface bar bar_if;
  loop(c, bar_if);
  
  return 0;
}
Endre
Active Member
Posts: 38
Joined: Fri Jan 01, 2016 10:13 am

Post by Endre »

Thanks for the hint. I have only tried with unsafe pointer before.
User avatar
lukehatpadl
Member++
Posts: 28
Joined: Sat Jul 08, 2023 5:15 am

Post by lukehatpadl »

I'm trying this to group two client interfaces together like follows:

Code: Select all

typedef struct tx_if_handle {
#ifdef __XC__
    client interface ethernet_tx_if *movable i_eth;
    client interface uart_tx_buffered_if ?*movable i_uart;
#else
    unsigned *i_eth;
    unsigned *i_uart;
#endif
} tx_if_handle;
but I'm seeing the following compiler error:

Code: Select all

xcc1: internal compiler error
Failed in /jenkins/workspace/_int_xc_compiler_combined_master/tools_xcc1_c_llvm/FrontEnd/PreCompAnalysis/pre_comp_analysis.cpp, line 68
	o->interfaceImplementations
For bug reporting instructions, please see:
https://www.xmos.ai/support
xmake[1]: *** [.build/_l_tsn/src/1722_1/avb_1722_1.xc.pca.xml.decouple] Error 1
Does this ring any bells?
User avatar
lukehatpadl
Member++
Posts: 28
Joined: Sat Jul 08, 2023 5:15 am

Post by lukehatpadl »

Initialising the structure as follows:

Code: Select all

static inline void
init_tx_if_handle(client interface ethernet_tx_if i_eth_tx,
                  client interface uart_tx_buffered_if ?i_uart_tx,
                  tx_if_handle &i_tx) {
#pragma warning disable
    client interface ethernet_tx_if *movable i_eth_tx_movable = &i_eth_tx;
#pragma warning enable
    i_tx.i_eth = move(i_eth_tx_movable);

    if (!isnull(i_uart_tx)) {
#pragma warning disable
        client interface uart_tx_buffered_if ?*movable i_uart_tx_movable = &i_uart_tx;
#pragma warning enable
        i_tx.i_uart = move(i_uart_tx_movable);
    } else {
        i_tx.i_uart = null;
    }
}
User avatar
lukehatpadl
Member++
Posts: 28
Joined: Sat Jul 08, 2023 5:15 am

Post by lukehatpadl »

Replacing the struct with distinct arguments for i_eth_tx / i_uart_tx works. Less ergonomic though.