Defining ports outside an .xc File

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

Defining ports outside an .xc File

Post by Mahagon »

Hi guys! It's me again!

On my long road to get pure .c Code on an XMOS, im getting ahead. My last steps were, to implement my own C functions that call XC functionalities (e.g. setting port values; getting timers; starting multiple threads). And wow, it's working! Im quiet happy about that. But there are still some issues i want to discuss:

First: I've included the xccompat.h to use things like "port" and "timer" in my .c files - basically that works fine (for function calls and so on). But: If i try to define a port in my .c file i'll gonna get a runtime error AFTER compiling:

xrun: Program received signal ET_ILLEGAL_RESOURCE, Resource exception.
set_port_value (p=263424, val=15) at ../src/XCandC.xc:27


If i don't change anything beside defining the port in the .xc file everything works fine! In my opinion its quiet obvious that the hardware ressources are not set correctly, if defined elsewhere than the .xc file. Am i correct with this? Are there maybe other solutions for that prob? Well, i dont think so, but maybe you got any ideas.


Second: I want to call the par(){} function. Well, that function uses functions itself. Theres my prob: to deliver functions to a function when calling, i need function pointers (if i'm right). Well, XC no pointers and so on ... how could i handle that? I've already read the tutorial at the tutorials page here at xcore (https://www.xcore.com/wiki/index.php/Ca ... _arguments). But i don't get it working.

Well, so far, Greetings and already thank you for answering!


richard
Respected Member
Posts: 318
Joined: Tue Dec 15, 2009 12:46 am

Post by richard »

When you declare a port in XC the compiler will add a constructor that does the following before the start of main():
  • Turns on the port (SETC_INUSE_ON)
  • Sets the clock to the value of the __default_clkblk symbol (this is so that the the default clock block can be overridden at link time using the -default-clkblk option).
  • If the port is declared as a buffered port set the mode to buffered (XS1_SETC_BUF_BUFFERS) and set the transfer width using the settw instruction.
If you declare the port in C or assembly you must do the necessary port configuration before the first use of the port. I suspect you are getting a illegal resource exception because the port is turned off when you try to use it.
User avatar
pstnotpd
XCore Addict
Posts: 161
Joined: Sun Jun 12, 2011 11:47 am

Post by pstnotpd »

Mahagon wrote:Second: I want to call the par(){} function. Well, that function uses functions itself. Theres my prob: to deliver functions to a function when calling, i need function pointers (if i'm right). Well, XC no pointers and so on ... how could i handle that?
I wonder if that's possible at all. Passing function pointers around implies i.m.o. that the runtime code of the function is available in the same memory space. As I understand it a core is only aware of the 64K associated to the tile and inter-thread memory sharing like that is not allowed.

Pls correct me if I'm wrong chaps.
Mahagon
Member++
Posts: 24
Joined: Thu Mar 07, 2013 4:24 pm

Post by Mahagon »

richard wrote:When you declare a port in XC the compiler will add a constructor that does the following before the start of main():
  • Turns on the port (SETC_INUSE_ON)
  • Sets the clock to the value of the __default_clkblk symbol (this is so that the the default clock block can be overridden at link time using the -default-clkblk option).
  • If the port is declared as a buffered port set the mode to buffered (XS1_SETC_BUF_BUFFERS) and set the transfer width using the settw instruction.
If you declare the port in C or assembly you must do the necessary port configuration before the first use of the port. I suspect you are getting a illegal resource exception because the port is turned off when you try to use it.

Hi!

Thanks for that idea! I tried it immediately with the functions declared in xs1.h ... i always get that error:

xs1.xc: Error: Type of symbol start_port has mismatch with previous definition:
xs1.xc: Error: found: void start_port( void port )
../src/main.c: Error: previous: signed int start_port()

... i have no idea where that "previous" definition is from. I have no xs1.xc file, just the header and inside of the header the function start_port() is type void? :O hmmm
User avatar
Bianco
XCore Expert
Posts: 754
Joined: Thu Dec 10, 2009 6:56 pm

Post by Bianco »

pstnotpd wrote:
Mahagon wrote:Second: I want to call the par(){} function. Well, that function uses functions itself. Theres my prob: to deliver functions to a function when calling, i need function pointers (if i'm right). Well, XC no pointers and so on ... how could i handle that?
I wonder if that's possible at all. Passing function pointers around implies i.m.o. that the runtime code of the function is available in the same memory space. As I understand it a core is only aware of the 64K associated to the tile and inter-thread memory sharing like that is not allowed.

Pls correct me if I'm wrong chaps.
This is correct for the par statement in the main function and trying to run statements in parallel on multiple tiles. However it can work if it is reduced to a par statement starting threads on a single tile (Tile 0) or par statements outside main (you can use par elsewhere, but in that case you cannot define the tile to run on of course)
User avatar
pstnotpd
XCore Addict
Posts: 161
Joined: Sun Jun 12, 2011 11:47 am

Post by pstnotpd »

Bianco wrote:[This is correct for the par statement in the main function and trying to run statements in parallel on multiple tiles. However it can work if it is reduced to a par statement starting threads on a single tile (Tile 0) or par statements outside main (you can use par elsewhere, but in that case you cannot define the tile to run on of course)
Ok. Have to give that a try.

But back to Mahagons original question, is there any way to use function pointers in this case? According to the calling convention the parameter is converted to a reference in XC, but how would any parameters to the function be passed and used then?
Mahagon
Member++
Posts: 24
Joined: Thu Mar 07, 2013 4:24 pm

Post by Mahagon »

richard wrote:When you declare a port in XC the compiler will add a constructor that does the following before the start of main():
  • Turns on the port (SETC_INUSE_ON)
  • Sets the clock to the value of the __default_clkblk symbol (this is so that the the default clock block can be overridden at link time using the -default-clkblk option).
  • If the port is declared as a buffered port set the mode to buffered (XS1_SETC_BUF_BUFFERS) and set the transfer width using the settw instruction.
If you declare the port in C or assembly you must do the necessary port configuration before the first use of the port. I suspect you are getting a illegal resource exception because the port is turned off when you try to use it.
Good morning,

ahhh im a bit angry at the moment^^ i just dont get it working xD
i've founded some functions to activate ports and so on (in xs1.h) and also founded the values u've talken about (XS1_SETC_INUSE_ON ...). but i still don't get a port working with defining it in c. the functions are not usable, cause before main() u can just do prototyping with a function, not getting it "working" .... u know what i mean.

well, actually i don't have to do that, i know, i can define ports in xc and just call then any functions and so on over c, thats no prob .... but i want to get it working now just for pride! xD

any ideas/hints? :D
richard
Respected Member
Posts: 318
Joined: Tue Dec 15, 2009 12:46 am

Post by richard »

Mahagon wrote:Hi!

Thanks for that idea! I tried it immediately with the functions declared in xs1.h ... i always get that error:

xs1.xc: Error: Type of symbol start_port has mismatch with previous definition:
xs1.xc: Error: found: void start_port( void port )
../src/main.c: Error: previous: signed int start_port()

... i have no idea where that "previous" definition is from. I have no xs1.xc file, just the header and inside of the header the function start_port() is type void? :O hmmm
There a number of functions in xs1.h that are only available in XC as they translated to builtin functions that are only supported by the XC compiler. If you try and call one of these you will get a warning about an implicit declaration of the function followed by a link time error.

If you want to turn on a port from C you can use inline assembly:

Code: Select all

static inline void turn_on_unbuffered_port(port p)
{
  asm volatile("setc res[%0],8" :: "r" (p)); // SETC_IN_USE_ON
}

static inline void turn_on_buffered_port(port p, unsigned transfer_width)
{
  asm volatile("setc res[%0],8" :: "r" (p)); // SETC_IN_USE_ON
  asm volatile("setc res[%0],0x200f" :: "r" (p)); // SETC_BUF_BUFFERS
  asm volatile("settw res[%0],%1" :: "r" (p), "r" (transfer_width));
}
Alternatively you could define XC functions that use the builtins in xs1.h to turn on the port and call these wrapper functions from C.

I'm still a bit confused as to why you want to do this. Is there a particular reason you are limiting yourself to pure C? It is typical for applications to use a mixture of C and XC and call between the two languages. Things like port I/O will be easier to use in XC due the support in the language.
Mahagon
Member++
Posts: 24
Joined: Thu Mar 07, 2013 4:24 pm

Post by Mahagon »

richard wrote:
Mahagon wrote:Hi!

Thanks for that idea! I tried it immediately with the functions declared in xs1.h ... i always get that error:

xs1.xc: Error: Type of symbol start_port has mismatch with previous definition:
xs1.xc: Error: found: void start_port( void port )
../src/main.c: Error: previous: signed int start_port()

... i have no idea where that "previous" definition is from. I have no xs1.xc file, just the header and inside of the header the function start_port() is type void? :O hmmm
There a number of functions in xs1.h that are only available in XC as they translated to builtin functions that are only supported by the XC compiler. If you try and call one of these you will get a warning about an implicit declaration of the function followed by a link time error.

If you want to turn on a port from C you can use inline assembly:

Code: Select all

static inline void turn_on_unbuffered_port(port p)
{
  asm volatile("setc res[%0],8" :: "r" (p)); // SETC_IN_USE_ON
}

static inline void turn_on_buffered_port(port p, unsigned transfer_width)
{
  asm volatile("setc res[%0],8" :: "r" (p)); // SETC_IN_USE_ON
  asm volatile("setc res[%0],0x200f" :: "r" (p)); // SETC_BUF_BUFFERS
  asm volatile("settw res[%0],%1" :: "r" (p), "r" (transfer_width));
}
Alternatively you could define XC functions that use the builtins in xs1.h to turn on the port and call these wrapper functions from C.

I'm still a bit confused as to why you want to do this. Is there a particular reason you are limiting yourself to pure C? It is typical for applications to use a mixture of C and XC and call between the two languages. Things like port I/O will be easier to use in XC due the support in the language.

Hiho,

No, theres no reason for my last question :) I just wanted to get it work you know ;D
I've already created c functions that call .xc functionalities, thats the best way i think. Main reaon is, that i have got proper code here in c that should not be changed you know ;)
And im also quiet sure now, that i cannot totally avoid xc, thats not usef, especially not for I/O, timers and so on.

But still thanks for your answers.

Greetings