C3 and threads(cognew)
Rsadeika
Posts: 3,837
Below is a rough interpretation of a spin2cpp --ccode conversion of a Spin program that basically starts a couple of cognew methods with the associated stack. The program below compiles, but I do not see printf("This is job_2\n") from job_2(). Anybody have any ideas as to why that is happening?
What I am trying to do is have a program that has a separate cognew for an LED1, LED2, and IR detector. Plus have access to writing to the SD card, and access to the softRTC program. Essentially, it would work like this, using an IR remote I can light up either LED1, or LED2; once it gets lit, I would like to have it time stamped, and recorded on the SD card. I might call this an intermediate level C programming, which should provide information as to how to start a separate and new cog, plus do some data logging. I guess the question is, am I on the right track? Any suggestions would be appreciated.
Ray
What I am trying to do is have a program that has a separate cognew for an LED1, LED2, and IR detector. Plus have access to writing to the SD card, and access to the softRTC program. Essentially, it would work like this, using an IR remote I can light up either LED1, or LED2; once it gets lit, I would like to have it time stamped, and recorded on the SD card. I might call this an intermediate level C programming, which should provide information as to how to start a separate and new cog, plus do some data logging. I guess the question is, am I on the right track? Any suggestions would be appreciated.
Ray
/** * @file MasterN.c * This is the main MasterN program start point. */ #include <propeller.h> #include <unistd.h> #include <stdint.h> typedef struct MasterN { int32_t Job_1stack[40]; int32_t Job_2stack[40]; char dummy__; } MasterN; static MasterN thisobj; int MasterN_Job_1(void) { printf("This is job_1\n"); while(1) { usleep(50000); } } int MasterN_Job_2(void) { printf("This is job_2\n"); while(1) { usleep(50000); } } /** * Main program function. */ int main(void) { waitcnt(CLKFREQ + CNT); printf("This is main\n"); cognew(MasterN_Job_1(), (&thisobj.Job_1stack)); cognew(MasterN_Job_2(), (&thisobj.Job_2stack)); while(1) { usleep(50000); } return 0; }
Comments
You can't run a C function with a cognew. You have to use a pthread instead. I haven't used pthreads myself, but I looked at your "What is a pthread?" thread, and I was able to get your program running with the code shown below. I'm not sure how the stack is handle. It's either part of the pthread_t pointer that is passed to the pthread_create or it is malloc'ed when the thread starts up. There probably a way to control the size of the stack, but I don't know how to do that offhand. I would suggest finding out more about pthreads.
https://sites.google.com/site/propellergcc/documentation/libraries/propeller-h-library#TOC-cogstart
The general rule is that we use waitcnt with cogstart and usleep with pthreads. Try changing that.
Thanks for the update. These various print things having caveats is a pain. I've found in many cases (especially with files and floating point) that the standard printf is often smaller than __simple_printf. Maybe we should retire that option since we have the tiny library in the release. Of course the tiny library has it's own limits.
The latest tinkering has me thinking, the great thing about the Propeller are the cogs, and when using Spin, you can get a cog(s) to function like its own little processor without being affected by the other running cog(s). So, in C what is the code to achieve the equivalent result? I know this question has been asked before, lets try an apples to apples answer, if possible.
Ray
Yes. The default state of a serial port output is high. If two COGs are using the same serial port then neither one can ever output, because the other will leave the pin high and so any attempt to drive it low is fruitless.
This could be worked around by having SimpleSerial switch the pin to input in COGs that aren't using it at the moment, except that on the QuickStart board this results in garbage as the pin floats around.
I didn't see any good solution to this, but perhaps someone else will have an idea?
Also, you don't need to use malloc for the stack, simple arrays will work.
What you are attempting with cogstart will produce the equivalent result. It should be practically the same as cognew in spin except that the arguments are different.
This is why I wanted to drive it low at the end of the function. If the stupid Quickstart board had a pull up, this wouldn't be a problem because we could let it float.
Leaving it low results in a break condition. I don't know how terminal programs will respond to that -- some of them will probably be OK, but I don't know in general.
Ray
Please use a separate stack for each cog function as previously suggested. It's the right thing to do. What you have now is working "as expected" by accident rather than by safe design. The functions are running at the same time, but they are mutually exclusive because one does work with lednum == 0 and the other with lednum == 1.
Ray
Have you tried the CMM mode? That will allow you to run more code versus the LMM mode.
So, if their are limitations with using cogstart and XMMC, then I guess I have to concentrate on the cognew thing. Some examples would be nice, maybe something that starts a couple of threads, blinking some LEDs, and some I/O in main().
Ray
It is correct that XMMC can not run multiple COG functions.
There are many examples where PASM and COGC programs are used to good effect.
I'm attaching a very simple example and nicely structured example of using a COGC program for you. It is a button demo. That example uses C++, but can easily be converted to C. The _C_LOCK statement is a work-around for a bug in an old propeller-gcc version, it can be ignored/removed now.
There is an 8 COG COGC LED demo in the repository and propeller-gcc-demos.zip.
There is also a COGC toggle demo in the repository and propeller-gcc-demos.zip.
I was just looking at the cog_c example that is in your toggle series. On the C3 board, I loaded up the program, and ran it in LMM, it works as advertised. When I switched it to run in XMMC, it ran, but not as expected, the LEDs flashed, at the same rate, forever. Not sure where the problem is.
Boy, this learning curve for C on the Propeller, is very steep, and I can not see the plateau, if there is one.
Ray
The demo tries to be generic, but in this case it fails because the pins is interfering with the C3 xmmc hardware.
Please change toggle_fw.cogc:
static _COGMEM unsigned int pins = 0xfffffff; /* all pins except Serial IO and I2C */
to
static _COGMEM unsigned int pins = 0x8000; /* all pins except Serial IO and I2C */
Ray