Shop OBEX P1 Docs P2 Docs Learn Events
P2 COG Start!! — Parallax Forums

P2 COG Start!!

Hi All,

I am coding in Catalina Geany and utterly confused by this:

_cogstart_C(void (*func)(void *), void *arg, void *stack_base, uint32_t stack_size);

How do a put in a standard function and start the cog? I have lets say this function:

void foo_function(void)

How do I create the pointer for the non-pointer function to start the cog for Propeller 2?

Also, what is *arg and what does it mean or do? I understand it is an argument but what is the purpose?

Can stack_base be zero? and stack size be an arbitrary value?

Comments

  • JonnyMacJonnyMac Posts: 8,927
    edited 2023-04-14 18:26

    From the docs:

    This function starts a C void function that accepts a void * argument in a new cog. The stack parameter must point to the start of an array of size bytes that will be used for the function's program stack. The arg will be passed to the new function on startup. The C function and the stack must be in Hub RAM. The C function will be started using a nonthreaded kernel in any spare cog. The actual cog number used will be returned by the function, or -1 on any error.

    Also, what is *arg and what does it mean or do? I understand it is an argument but what is the purpose?

    The usual thing to do is pass a hub address in this argument that the cog code can make use of -- some people call this the mailbox. If you need access to more than one value in the hub you would put a list of same size variables and send a pointer to the first; the other variables are offset from that by their size.

    Can stack_base be zero? and stack size be an arbitrary value?

    No (see comment in docs). In Spin, this is a pointer to an array that is used as a stack for cog you're starting. It seems to be the same here.

    FTR: I'm not much of a C programmer, and I don't use C on the Propeller. That said, I do write a lot of code that instantiates other cogs, running Spin or PASM.

  • @JonnyMac said:
    From the docs:

    This function starts a C void function that accepts a void * argument in a new cog. The stack parameter must point to the start of an array of size bytes that will be used for the function's program stack. The arg will be passed to the new function on startup. The C function and the stack must be in Hub RAM. The C function will be started using a nonthreaded kernel in any spare cog. The actual cog number used will be returned by the function, or -1 on any error.

    Also, what is *arg and what does it mean or do? I understand it is an argument but what is the purpose?

    The usual thing to do is pass a hub address in this argument that the cog code can make use of -- some people call this the mailbox. If you need access to more than one value in the hub you would put a list of same size variables and send a pointer to the first; the other variables are offset from that by their size.

    Can stack_base be zero? and stack size be an arbitrary value?

    No (see comment in docs). In Spin, this is a pointer to an array that is used as a stack for cog you're starting. It seems to be the same here.

    FTR: I'm not much of a C programmer, and I don't use C on the Propeller. That said, I do write a lot of code that instantiates other cogs, running Spin or PASM.

    Thanks for this :-). After pulling my hair out, I figured out how to get it going :-). Time to tinker and see what kind of cool stuff I can do with an extra processor :smiley

  • Now the real fun begins....

  • RossHRossH Posts: 5,346
    edited 2023-04-15 01:44

    This seems to have been answered well by JonnyMac, but to expand a little ...

    By convention in C the type "void *" (aka "void pointer" or "pointer to void") is often used to represent an argument that can be any type that is the same size or smaller than a pointer (so that it can also be a pointer to an argument, if required) - the actual argument has to be "cast" (aka "coerced") to be a void * to be passed, and cast back again before it is used - so you have to know what the actual original type was.

    C syntax for pointers to functions is a bit obscure. I often have to look it up myself. Here, "void (*func)(void *)" means the argument (called 'func') is a pointer to a function that takes a void pointer as argument, and the function returns void (i.e. it does not return anything). Also, note that the name of the function when used as a parameter is actually a pointer to the function, so if your function is called 'C_function' you don't need to pass &C_function as your parameter, you just pass C_function (actually, both will work!).

    Here is an actual Catalina example:

    /*
     * This program uses _cogstart_C() to load a new kernel to execute a C function.
     */
    #include <catalina_cog.h>
    
    #define STACK_SIZE 200
    
    void C_function(void *arg) {   // <-- the argument is defined as a void *
       printf("Hello, from C_function, my argument is 0x%X!\n", (int)arg);    // <-- the argument is actually an int, so cast it to be an int
       while(1); // loop forever
    } 
    
    static long stack[STACK_SIZE];
    
    void main(void) {
       printf("Starting new Kernel\n");
    
       if (_cogstart_C(C_function, (void *)0x12345, stack, STACK_SIZE) == -1) {   // <-- the argument must be cast to be a void *
         printf("Failed to start new Kernel\n");
       }
       else {
         printf("Kernel started ok\n");
       }
    
       while(1); // loop forever
    }
    

    This produces:

    Starting new Kernel
    Hello, from C_function, my argument is 0x12345!
    Kernel started ok
    
  • @RossH said:
    This seems to have been answered well by JonnyMac, but to expand a little ...

    By convention in C the type "void *" (aka "void pointer" or "pointer to void") is often used to represent an argument that can be any type that is the same size or smaller than a pointer (so that it can also be a pointer to an argument, if required) - the actual argument has to be "cast" (aka "coerced") to be a void * to be passed, and cast back again before it is used - so you have to know what the actual original type was.

    C syntax for pointers to functions is a bit obscure. I often have to look it up myself. Here, "void (*func)(void *)" means the argument (called 'func') is a pointer to a function that takes a void pointer as argument, and the function returns void (i.e. it does not return anything). Also, note that the name of the function when used as a parameter is actually a pointer to the function, so if your function is called 'C_function' you don't need to pass &C_function as your parameter, you just pass C_function (actually, both will work!).

    Here is an actual Catalina example:

    /*
     * This program uses _cogstart_C() to load a new kernel to execute a C function.
     */
    #include <catalina_cog.h>
    
    #define STACK_SIZE 200
    
    void C_function(void *arg) {   // <-- the argument is defined as a void *
       printf("Hello, from C_function, my argument is 0x%X!\n", (int)arg);    // <-- the argument is actually an int, so cast it to be an int
       while(1); // loop forever
    } 
    
    static long stack[STACK_SIZE];
    
    void main(void) {
       printf("Starting new Kernel\n");
    
       if (_cogstart_C(C_function, (void *)0x12345, stack, STACK_SIZE) == -1) {   // <-- the argument must be cast to be a void *
         printf("Failed to start new Kernel\n");
       }
       else {
         printf("Kernel started ok\n");
       }
    
       while(1); // loop forever
    }
    

    This produces:

    Starting new Kernel
    Hello, from C_function, my argument is 0x12345!
    Kernel started ok
    

    Ahh ok this makes more sense and is how I did it, well not exactly but the same idea. Thanks for letting me know :-)

Sign In or Register to comment.