Shop OBEX P1 Docs P2 Docs Learn Events
Cognew? — Parallax Forums

Cognew?

Jack BuffingtonJack Buffington Posts: 115
edited 2012-11-16 10:45 in Propeller 1
I'm finally starting to dig into C for the propeller and have had some success with running things on a single processor. Now I am about to jump into doing things on multiple COGs but am having a problem, which is probably really simply solved but is eluding me. The jist of what I am trying to do right now is to have one COG count upwards and store that value in its mailbox. The main COG will look at that variable periodically and spit it out of the serial port. I am basing things on one of the toggle demos but am hitting a problem. I am getting an error message:

EncoderDevice.c:26:4: error: '_load_start_encoder_cog' was not declared in this scope

I have the file encoder.cogc in the same directory as my main file, have added it to the project, I have tried setting the workspace folder to the folder where the files are located but that doesn't seem to help.

What am I missing? I have included my code below.

This is the main file.
#include <stdio.h>
#include <propeller.h>
#define STACK_SIZE 16
struct encoder_mailbox 
   {
   unsigned int encoderPos; 
   };
struct 
   {
   unsigned stack[STACK_SIZE];
   struct encoder_mailbox m;
   } par;
volatile int togglecount = 0;
int main (int argc,  char* argv[])
   {
   printf("Lens Encoder Device 0.1\n");
   
   par.m.encoderPos = 32000;
   cognew(_load_start_encoder_cog, &par.m);
   printf("Started the encoder cog\n");
   unsigned int nextcnt; 
   nextcnt = _CNT + _CLKFREQ/5;
   while(1) 
      {
      nextcnt = waitcnt2(nextcnt, _CLKFREQ/5);
      printf("encoder position = %d\n", par.m.encoderPos);
      }
   return 0;
   }


This is encoder.cogc
#include <propeller.h>
struct encoder_mailbox 
   {
   unsigned int encoderPos; 
   };
static _COGMEM unsigned int waitdelay;
static _COGMEM unsigned int nextcnt;
extern int togglecount;
_NATIVE
void main (volatile struct encoder_mailbox *m)
   {
   nextcnt = _CNT + 100000;
   waitdelay = 100000;
   while(1)
      {
      m->encoderPos++;
      nextcnt = waitcnt2(nextcnt, waitdelay);
      }
   }

Comments

  • mindrobotsmindrobots Posts: 6,506
    edited 2012-11-15 23:32
    Jack,

    Did you check out the toggle example/demo programs? There's one for starting an LMM cog from and LMM main program which is what I believe you are attempting to do.

    If this doesn't help, real help should be along later in the day!

    Glad to see you are jumping into C!!
  • jac_goudsmitjac_goudsmit Posts: 418
    edited 2012-11-16 06:28
    [QUOTE=Jack Buffington;1142455
    EncoderDevice.c:26:4: error: '_load_start_encoder_cog' was not declared in this scope
    [/QUOTE]

    You forgot to put the following line in your EncoderDevice.c:
    extern int _load_start_encoder_cog[ ];
    

    The "_load_start_XXX_cog" symbol is automatically generated in an object file as a public symbol when the .cogc module is compiled, but the compiler doesn't know about it when it compiles EncoderDevice.c unless you add the line shown above. It tells the compiler: "Look, I promise I will put an array of int in memory somehow, I don't know where it is but it'll be there". When you use a pointer to it, the compiler puts a placeholder in the object file ("Look, Jack promised he'd have this array somewhere, and he needs the address, but I don't know where it is, okay?"). When the linker builds your executable, it replaces the placeholder in the EncoderDevice.o file with the value that's generated automatically from the encoder.cogc module.

    ===Jac
  • Jack BuffingtonJack Buffington Posts: 115
    edited 2012-11-16 10:30
    That is really bizarre. I originally had that line in the program since it was in the toggle demo program. Since the program wasn't working, one of the last things that I did was to take it out since I didn't see a line like that in any of the documentation pages that I looked at. For example, http://code.google.com/p/propgcc/wiki/PropGccInDepth has no mention of a line like that.

    In any case, the program is now running and I am seeing what I am expecting. Thank you!

    As a follow up question, what exactly is that line saying? I haven't programmed in C for a few years and haven't ever used the extern keyword. My understanding of it is that it allows me to use a variable that was declared in a different file but I haven't declared it and certainly haven't as an array. Is this a Propeller-specific thing? Also, going back to the toggle demo program, that variable had been an unsigned int and you made it an int. Both are compiling for me. What, if anything would I use that variable for?
  • jazzedjazzed Posts: 11,803
    edited 2012-11-16 10:45
    As a follow up question, what exactly is that line saying? I haven't programmed in C for a few years and haven't ever used the extern keyword. My understanding of it is that it allows me to use a variable that was declared in a different file but I haven't declared it and certainly haven't as an array. Is this a Propeller-specific thing? Also, going back to the toggle demo program, that variable had been an unsigned int and you made it an int. Both are compiling for me. What, if anything would I use that variable for?

    The extern line says to the GCC compiler that _load_start_encoder_cog is in a separate module and that GCC should not throw an error. Since the code lives in a separate module and the file being compiled is the main file, you must to use the extern array (int or unsigned int is fine). This is common in C for projects having more than one source file and is not propeller specific.

    When you defined the encoder.cogc file and added it to the build, the compiler generated the _load_start_encoder_cog symbol for you. Having a symbol like _load_start_encoder_cog for code that actually runs uninterpreted in the cog is propeller specific.
Sign In or Register to comment.