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!
Defining ports outside an .xc File
-
- Member++
- Posts: 24
- Joined: Thu Mar 07, 2013 4:24 pm
-
- Respected Member
- Posts: 318
- Joined: Tue Dec 15, 2009 12:46 am
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.
-
- XCore Addict
- Posts: 161
- Joined: Sun Jun 12, 2011 11:47 am
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.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?
Pls correct me if I'm wrong chaps.
-
- Member++
- Posts: 24
- Joined: Thu Mar 07, 2013 4:24 pm
richard wrote:When you declare a port in XC the compiler will add a constructor that does the following before the start of main():
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.
- 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.
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
-
- XCore Expert
- Posts: 754
- Joined: Thu Dec 10, 2009 6:56 pm
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)pstnotpd wrote: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.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?
Pls correct me if I'm wrong chaps.
-
- XCore Addict
- Posts: 161
- Joined: Sun Jun 12, 2011 11:47 am
Ok. Have to give that a try.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)
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?
-
- Member++
- Posts: 24
- Joined: Thu Mar 07, 2013 4:24 pm
Good morning,richard wrote:When you declare a port in XC the compiler will add a constructor that does the following before the start of main():
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.
- 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.
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
-
- Respected Member
- Posts: 318
- Joined: Tue Dec 15, 2009 12:46 am
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.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
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));
}
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.
-
- Member++
- Posts: 24
- Joined: Thu Mar 07, 2013 4:24 pm
richard wrote: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.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
If you want to turn on a port from C you can use inline assembly:
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.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)); }
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