Cognew?
Jack Buffington
Posts: 115
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.
This is encoder.cogc
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
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!!
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:
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
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?
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.