Shop OBEX P1 Docs P2 Docs Learn Events
cogstart error in C++ — Parallax Forums

cogstart error in C++

EnriqueEnrique Posts: 90
edited 2012-07-29 22:16 in Propeller 1
I am getting the following error

"invalid conversion from 'void(*)()' to 'void(*)(void*)'"

on the line

int cogID=cogstart((&Blinker), NULL, &cogStack, sizeof(cogStack));

of the following program

/*
* This is a simple example of a method running in its own cog. This class will toggle the indicated pin
* at the frequency received as the second argument, the toggling method runs in its own cog.
*/

#include <propeller.h>
#include "pin.h"

#define LMM_STACK_AREA 40 // Number of int locations for the cog method to work
#define NUMBER_OF_INT_LOCAL_VARIABLES 0 //

class Toggler
{
static int waitTime; // Time interval between blinks
static int ledPin; // The pin for the LED we will blink
static int cogStack[LMM_STACK_AREA + NUMBER_OF_INT_LOCAL_VARIABLES]; // Stack area used by the cog

public:
Toggler(int ledPinArg, int timesPerSecondArg) // Starts toggling ledPinArg at a frequency of timePerSecondArg
{
// Prepare things
waitTime=CLKFREQ/timesPerSecondArg;
ledPin=ledPinArg;

// Start the cog
int cogID=cogstart((&Blinker), NULL, &cogStack, sizeof(cogStack));
}

private:
static void Blinker() // Does the actual blinking, it will run in a different cog
{
// Set the pin for output
pinOutput(ledPin);

while(1)
{
// Turn the LED on and wait
pinHigh(ledPin);
waitcnt(CNT+waitTime);

// Turn the LED off and wait
pinLow(ledPin);
waitcnt(CNT+waitTime);
}
}
};


What am I doing wrong?


Thanks,
Enrique

Comments

  • David BetzDavid Betz Posts: 14,516
    edited 2012-07-26 13:50
    Try changing this:
    static void Blinker() // Does the actual blinking, it will run in a different cog
    

    to this:
    static void Blinker(void *arg) // Does the actual blinking, it will run in a different cog
    

    cogstart will pass its second parameter to Blinker in the 'arg' parameter. You can use this parameter to communicate information between the main program and the program you're starting on another COG.
  • EnriqueEnrique Posts: 90
    edited 2012-07-27 01:43
    David,

    Thanks for the reply

    Your suggestion got rid of the previous error and I am now getting a new one

    'lvalue required as unary & operand'

    on the line

    int cogID=cogstart((&Toggler::Blinker(NULL)), NULL, &cogStack, sizeof(cogStack));

    This is what the code looks like now

    /*
    * This is a simple example of a method running in its own cog. This class will toggle the indicated pin
    * at the frequency received as the second argument, the toggling method runs in its own cog.
    */

    #include <propeller.h>
    #include "pin.h"

    #define LMM_STACK_AREA 40 // Number of int locations for the cog method to work
    #define NUMBER_OF_INT_LOCAL_VARIABLES 0 //

    class Toggler
    {
    int waitTime; // Time interval between blinks
    int ledPin; // The pin for the LED we will blink
    int cogStack[LMM_STACK_AREA + NUMBER_OF_INT_LOCAL_VARIABLES]; // Stack area used by the cog

    public:
    Toggler(int ledPinArg, int timesPerSecondArg);
    private:
    void Blinker(void *arg);
    };
    Toggler::Toggler(int ledPinArg, int timesPerSecondArg) // Starts toggling ledPinArg at a frequency of timePerSecondArg
    {
    // Prepare things
    waitTime=CLKFREQ/timesPerSecondArg;
    ledPin=ledPinArg;

    // Start the cog
    int cogID=cogstart((&Toggler::Blinker(NULL)), NULL, &cogStack, sizeof(cogStack));
    }

    void Toggler::Blinker(void *arg) // Does the actual blinking, it will run in a different cog
    {
    // Set the pin for output
    pinOutput(ledPin);

    while(1)
    {
    // Turn the LED on and wait
    pinHigh(ledPin);
    waitcnt(CNT+waitTime);

    // Turn the LED off and wait
    pinLow(ledPin);
    waitcnt(CNT+waitTime);
    }
    }
  • Heater.Heater. Posts: 21,230
    edited 2012-07-27 07:29
    Enrique,

    I would suggest that you do not do this is C++.
    Even if the bulk of your program is C++ I would define the function to be loaded to COG as C function. If it needs parameters passed into par I would use a regular struct.
  • David BetzDavid Betz Posts: 14,516
    edited 2012-07-27 08:05
    I'm afraid I haven't done much with taking the address of C++ member functions. First of all, I would think you would need to make this a static member function. Second, I doubt that the parameter list is needed when taking the address of a member function. I would think that "&Toggler::Blinker" would be sufficient as long as you make Blinker a static member function. Hopefully, some C++ guru will jump in and give you some real expert advice! :-)
  • ersmithersmith Posts: 6,096
    edited 2012-07-27 08:50
    Heater's right, starting a C++ function in a COG is going to be hard. As David suggested, at the minimum the function needs to be a static member function. Non-static member functions have an "invisible" first argument (the "this" pointer), which cogstart does not know about.

    Also, you should not try to pass an argument to the function. "&func(NULL)" means "the address of the result of func(NULL)", whereas "&func" just means "the address of func". The second one, namely the address of the function itself, is what you want to pass to cogstart,
  • EnriqueEnrique Posts: 90
    edited 2012-07-29 21:43
    Just to let you know, I asked in a C++ forum and the answer is that pointers can only point to static functions or C style functions. It will probably be better to develop the whole project in C.

    Thanks,
    Enrique
  • jazzedjazzed Posts: 11,803
    edited 2012-07-29 22:16
    Enrique wrote: »
    Just to let you know, I asked in a C++ forum and the answer is that pointers can only point to static functions or C style functions. It will probably be better to develop the whole project in C.

    Thanks,
    Enrique

    You should be able to use a function with a global namespace. For example ::do_toggle below works fine for me. The start function is slightly different, but it shouldn't matter. The example is a small modification for the toggle/lmm_c_toggle demo.
    /**
     * @file toggle.c
     * This program demonstrates starting another COG running
     * LMM code.
     * The cog makes all IO except 28..31 toggle.
     *
     * Copyright (c) 2011 Parallax, Inc.
     * MIT Licensed (see at end of file for exact terms)
     */
    
    
    #include <stdio.h>
    #include <propeller.h>
    #include <sys/thread.h>
    
    
    #define STACK_SIZE 16
    
    
    /* stack for cog 1 */
    static int cog1_stack[STACK_SIZE];
    
    
    /* per-thread library variables ("Thread Local Storage") */
    static _thread_state_t thread_data;
    
    
    /* variables that we share between cogs */
    volatile unsigned int wait_time;
    volatile unsigned int pins;
    
    
    /*
     * here's the toggle code that runs in another cog
     */
    
    
    void
    do_toggle(void *arg __attribute__((unused)) )
    {
      unsigned int nextcnt;
    
    
      /* get a half second delay from parameters */
      _DIRA = pins;
    
    
      /* figure out how long to wait the first time */
      nextcnt = _CNT + wait_time;
    
    
      /* loop forever, updating the wait time from the mailbox */
      for(;;) {
        _OUTA ^= pins; /* update the pins */
    
    
        /* sleep until _CNT == nextcnt, and return the new _CNT + wait_time */
        nextcnt = __builtin_propeller_waitcnt(nextcnt, wait_time);
      }
    }
    
    
    /*
     * main code
     * This is the code running in the LMM cog (cog 0).
     * It launches another cog to actually run the 
     * toggling code
     */
    #define MIN_GAP 400000
    
    
    class Toggle
    {
    public:
    int start (void)
    {
        int n;
        int result;
        unsigned int startTime;
        unsigned int endTime;
        unsigned int executionTime;
        unsigned int rawTime;
    
    
        printf("hello, world!\n");
    
    
        /* set up the parameters for the C cog */
        pins = 0xfffffff;
        wait_time = _clkfreq;  /* start by waiting for 1 second */
    
    
        /* start the new cog */
        n = _start_cog_thread(cog1_stack + STACK_SIZE, ::do_toggle, NULL, &thread_data);
        printf("toggle cog %d has started\n", n);
    
    
        /* every 2 seconds update the flashing frequency so the
           light blinks faster and faster */
        while(1) {
          waitcnt(CNT+CLKFREQ/2);
          wait_time =  wait_time >> 1;
          if (wait_time < MIN_GAP)
            wait_time = _clkfreq;
        }
        return 0;
    }
    };
    
    
    int main (void)
    {
        Toggle t;
        t.start();
        while(1);
    }
    
    
    /* +--------------------------------------------------------------------
     * ¦  TERMS OF USE: MIT License
     * +--------------------------------------------------------------------
     * Permission is hereby granted, free of charge, to any person obtaining
     * a copy of this software and associated documentation files
     * (the "Software"), to deal in the Software without restriction,
     * including without limitation the rights to use, copy, modify, merge,
     * publish, distribute, sublicense, and/or sell copies of the Software,
     * and to permit persons to whom the Software is furnished to do so,
     * subject to the following conditions:
     *
     * The above copyright notice and this permission notice shall be
     * included in all copies or substantial portions of the Software.
     *
     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
     * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     * +--------------------------------------------------------------------
     */
    
Sign In or Register to comment.