Said parameters being either the pin numbers or baud rate. In Ray's case, he's trying to change the baud rate. Isn't freopen more appropriate than fopen in this case?
At some level, all else being equal, such a decision is a matter of style. I'm open to different perspectives of course.
I think I just solved my problem with SSER thing. This is what I had in the program:
FILE *port = fopen(serdevice, "+r");
This line compiled without any errors or warnings. As soon as I changed the "+r" to "r+" then everything started to work as expected. I would of thought that the compiler would of picked up on that. This would of been a horrible thing to try to find if it was in a two or three hundred line program, and the program compiled without any complaints.
Ray,
Some errors can only be caught at run time. In theory, a "+r" parameter to fopen could be caught at compile time, but I don't think the compiler checks for this. What value did the fopen return. It should have returned a NULL, and you could have tested the value of port to see if it was zero. If it didn't return a zero there might be a bug in our stdio library code.
At some level, all else being equal, such a decision is a matter of style. I'm open to different perspectives of course.
True, given unlimited resources. Probably true in most cases.
Things to consider:
Using fopen leaves the old stdin and stdout around, which on the Propeller uses an extra two of your 5 remaining file slots. This may not be a concern if you don't need the file slots, but why keep the zombie stdin and stdout around if you don't need them and they don't function properly?
In a typical UNIX system, this would also typically leave unused buffers allocated - ostensibly this could cause trouble if you're running out of Propeller memory space. However, I just checked the code, and the PropGCC library does not allocate buffers for serial devices, so the buffer memory leak that I was worried about does not exist if you use fopen() instead of freopen(). (Note here that I mean any extra memory allocated with malloc(), not the extra two file slots in the limited file descriptor pool, which *are* wasted).
Note this inconsistency: the default stdin uses a static 80 character buffer (statically allocated in init_io.c); however any fopen or freopen of a serial stream appears to use only an 8 character buffer (native to the fp). This means two things: (1) you can call ungetc on the original stdin more than you can ungetc on a reopened stdin, and (2) if you reopen, then you have just stranded an 80-character buffer that serves no further purpose. After noticing this, I'm thinking about filing an issue on it (though this is a very minor, low priority issue).
Last, if you leave the old stdin and stdout lying around at the wrong baud rate, then printf(...) and fprintf(newFpThatStandsForStdout, ...) have different results (ditto getchar() and fgetc(newFpThatStandsForStdin). So, while using freopen instead of fopen be a stylistic, a style that reduces errors is worthy of consideration.
Ray:
I think opening/reopening with "r+" shouldn't be necessary, because you're not going to write on stdin; therefore, using "r" alone should be sufficient.
In the program below, when I press 'a' I get the case 'a' statements and the case 's' statements displayed, at the same time. I was expecting just the case 'a' statements to be displayed when you pressed 'a'.
In this particular program I used the form of 'void main(void)' which seems to run just fine, how many different forms of main() can be used in PropGCC? If 'void main(void)' works just fine, why would you want to use something like 'int main()'?
Ray
/*
* fds3.c
*/
#include <stdio.h>
#include <propeller.h>
#include "misc.h"
void main(void)
{
int byte;
waitMS(150);
printf("Hello. World! I'm a Propeller programmed with PropGCC!\n");
while(byte = fgetc(stdin))
{
switch(byte)
{
case 'a':
printf("You pressed 'a'\n");
high(16);
printf("LED 16 is ON\n");
case 's':
printf("You pressed 's'\n");
low(16);
printf("LED 16 is OFF\n");
default:
break;
}
}
}
The main function is required to return an int, indicating status, even if the function does not terminate. It's part of the C standard. Many C compilers generate a warning if it is omitted. Just use return 0.
I think I resolved the problem with the previous program. The proper form of the case statement is:
case 'x':
.
.
.
break;
You need a 'break' for every case statement. I noticed in some of the docs online 'break' does not appear in the 'case' statement, so different versions of C handle 'case' in a different manner?
Unless you explicitly break out of a case, the switch statement continues on to the next case. The break ends the current block of code and in the case of a switch goes to the end of the switch statement. Add the break statements as indicated below.
switch(byte)
{
case 'a':
printf("You pressed 'a'\n");
high(16);
printf("LED 16 is ON\n");
break; // ADD THIS
case 's':
printf("You pressed 's'\n");
low(16);
printf("LED 16 is OFF\n");
break; // ADD THIS
default:
break;
}
I think I resolved the problem with the previous program. The proper form of the case statement is:
case 'x':
.
.
.
break;
You need a 'break' for every case statement. I noticed in some of the docs online 'break' does not appear in the 'case' statement, so different versions of C handle 'case' in a different manner?
Ray
More a matter of the quality of the documentation than the way C handles it. I would think the switch/case/break operation goes way back into the C standard.
In the program below, for some odd reason, do_toogle3(), is not working. I thought we had up to eight threads that could be run?
What do you mean by "not working"? Most of the time the LEDs will be off. That's because you turn them each on for only 10 milliseconds and then turn them off (and leave them off while you go on to the other pins). So thread 3 will do the following:
turn pin 20 on for 10 milliseconds
turn pin 20 off
turn pin 21 on for 10 milliseconds
turn pin 21 off
etc...
I doubt you'll be able to visually notice that activity -- most people's eyes are probably not that sensitive. If you hook the pins up to a scope you should see them being briefly toggled though. As Steve noted, if you change the usleep to a longer value you'll be able to see them.
I got do_toggle3() working(visible) again, and I added a 'q' command. I looked at the pthread.h file and did not find any commands to kill a pthread. Below I used pthread_detach(), but that did not accomplish what I want to do. Is there a way to kill the pthreads when you want to exit the program?
Ray
/*
* thread1.c
*/
#include <stdio.h>
#include <propeller.h>
#include <pthread.h>
#include <unistd.h>
#include "misc.h"
void *do_toggle1(void *argv)
{
pthread_set_affinity_thiscog_np();
while(1)
{
high(18);
usleep(500000);
low(18);
usleep(500000);
}
}
void *do_toggle2(void *argv)
{
pthread_set_affinity_thiscog_np();
while(1)
{
high(19);
usleep(35000);
low(19);
usleep(35000);
}
}
void *do_toggle3(void *argv)
{
int y;
pthread_set_affinity_thiscog_np();
while(1)
{
for (y = 20; y <= 23; y++)
{
high(y);
usleep(87000);
low(y);
usleep(87000);
}
for (y = 23; y >= 20; y--)
{
high(y);
usleep(87000);
low(y);
usleep(87000);
}
}
}
int main(int argc, char* argv[])
{
int byte;
pthread_t thr;
pthread_t thr1;
pthread_t thr2;
pthread_create(&thr, NULL, do_toggle1, NULL);
pthread_create(&thr1, NULL, do_toggle2, NULL);
pthread_create(&thr2, NULL, do_toggle3, NULL);
usleep(150000);
printf("Hello, World! I'm a Propeller programmed with PropGCC!\n");
while (byte = getchar())
{
switch(byte)
{
case 'a':
high(16);
printf("LED 16 is ON.\n");
break;
case 's':
low(16);
printf("LED 16 is OFF.\n");
break;
case 'z':
high(17);
printf("LED 17 is ON.\n");
break;
case 'x':
low(17);
printf("LED 17 is OFF.\n");
break;
case 'q':
pthread_detach(&thr),
pthread_detach(&thr1),
pthread_detach(&thr2);
return 0;
default:
break;
}
}
return 0;
}
In my thread1.c program I was playing around with using different variations of sleep(), and usleep(). For my msleep() I was using:
void msleep( int ms)
{
usleep(ms*1000);
}
I did notice that there is a difference from usleep(), in timing, from a conversion of msleep() as it pertains to a pthread(). Same thing occurs when I use:
void msleep(int ms)
{
sleep(ms/1000);
}
I thought the timing would be more equivalent, even as you did the conversions?
The other thing that I noticed was that if you start to increase the usleep() values in do_toggle1() or do_toggle2, it has an affect on do_toogle3(), makes it non visible.
I guess there is a lot of consideration that has to be calculated before attempting any serious pthread() usage. Also, you have to consider if you really want to do any conversions of usleep(), or sleep().
This program is a variation of the previous program, I am starting a pthread() from a command. The program works almost as expected, except that when I start the pthread() both LED 18, and LED 19 are flashing, that is not expected. I am not sure what is triggering LED 19 to start flashing.
With this program I am hoping that I can learn how to start and stop a pthread from a command. Still have not figured out how to kill a pthread().
Normally one would pthread_create a thread, let it do it's job then and then pthread_exit, then collect thread status with pthread_join. A good example is in the toggle/pthread_toggle demo. There is a cancel function defined in linux pthreads, but it is not supported in propeller GCC.
I want to revisit this again, not sure if this was ever resolved. With the program below, I am using PST, and I am not getting anything in the PST window. The program compiles without any complaints.
Ray
/*
* fds2.c
*/
#include <stdio.h>
#include <propeller.h>
#include <unistd.h>
int main()
{
char *serdevice = "SSER:9600,31,30";
FILE *port = fopen(serdevice, "r");
sleep(3);
fprintf(port,"This is some texrt.\n");
while(1)
{
fprintf(port, "Again, and again.\n");
sleep(2);
}
fclose(port);
return 0;
}
I thought I would try something different, integration of .spin code to make a functional C program. I thought I would go with the simplest form, the assembly example from the Propeller Manual. Of course when I compile the program below, it throws up an error:
... (.text+0xc): undefined reference to `_start'.
After looking at some of the examples, I am still missing the point as to how the .spin gets linked to blink16.c? In other words, what am I missing, in terms of code, to get access to 'PUB start' in the .spin program?
''blink16.spin
CON
_clkmode = xtal1 + pll16x
_xinfreq = 5_000_000
'ipin = 17
VAR
PUB start
cognew(@Toggle, 0)
'cognew(@Toggle, ipin)
DAT
org 0
Toggle mov dira, Pin
mov Time, cnt
add Time, #9
:loop waitcnt Time, Delay
xor outa, Pin
jmp #:loop
Pin long |< 16
'Pin long |< ipin
Delay long 6_000_000
Time res 1
After looking at some of the examples, I am still missing the point as to how the .spin gets linked to blink16.c? In other words, what am I missing, in terms of code, to get access to 'PUB start' in the .spin program?
Hi Ray,
The IDE transforms the Spin PASM code into an object for C by running some tools.
You'll have to provide a start function in C to start the COG. Something like this:
/*
* C stub function to start the PASM routine.
* Any PAR control variable must be declared as volatile
*/
void start(void)
{
extern unsigned int *binary_blink16_dat_start;
cognew(&binary_blink16_dat_start, 0);
}
The key variable is: binary_blink16_dat_start. Notice that it contains your Spin program name blink16 - without .spin of course. The PASM symbol will always be binary_*_dat_start.
What happens is that the spin compiler bstc or Roy's Spin converts blink16.spin to blink16.dat, and propgcc converts blink16.dat to a C object with the name blink16_firmware.o. Then everything gets compiled and linked together.
Now it works. When the compiler runs the code it creates a blink16.dat file, and the 'extern unsigned int *binary_blink16_dat_start;' makes that available for 'cognew(&binary_blink16_dat_start,0);' to run the blink16.spin program. For some reason I thought that it would be more involved than this. I guess from this point on it will get very complicated.
Ray
/*
* blink16.c
*/
#include <propeller.h>
void start(void)
{
extern unsigned int *binary_blink16_dat_start;
cognew(&binary_blink16_dat_start,0);
}
int main(void)
{
start();
}
I just got a uSD card reader from Parallax, and I connected it on the Demoboard, does anybody have a functional program that will run on the Demoboard. I can not find Dave Hine SD program anymore, but I am not sure if it was setup to be run on a Demoboard. I am not ready or able to make fsrw.spin run with a C program.
I provided an example of using filetest.c with the Spinneret card. Look for "#ifdef SPINNERET_CARD" in the main routine in filetest.c. Change this to "#if 1" and change the pin numbers to match the ones that you will be using. I've only tested this on the Spinneret card, so I'll be interested in seeing how it works for you with the Parallax uSD card reader on the demo board.
The program compiled, but when I typed in 'ls' I did not get anything. Below is what I changed it to, not sure about MISO, and MOSI. My connections are:
DO - p0
SCLK - p1
DI - p2
CS - p3
CD - p4
Ray
#ifdef __PROPELLER_LMM__
/*#ifdef SPINNERET_CARD
// Mount file system on a Spinneret card */
#ifdef DEMOBOARD
buffer[0] = 0; // SD MISO PIN
buffer[1] = 1; // SD CLK PIN
buffer[2] = 2; // SD MOSI PIN
buffer[3] = 3; // SD CS PIN
LoadSDDriver(buffer);
#else
// Mount file system on a C3 card
LoadSDDriver(0);
#endif
#endif
Yes, that worked. I had #ifdef 1, which came back with an error. What can be done with 'CD - p4', is that a card detector? Since the card reader does not have an LED that shows that the card is in, maybe the CD should be implemented.
I'm glad you got it to work. I don't think CD is a standard signal, but the documentation for the uSD card reader says it's a chip detect signal. Based on the schematic, it's probably a switch in the connector that is enabled when a card is in. You could add your own code to detect whether a card is in, such as
The card detect code does not work as expected. The way it is below, it shows "Card Detected." when I have the card in and out. When I inverse the logic, it shows "No Card Detected." when I have the card in or out.
I am not following the logic of "#if 1", is that some kind of designation for the DEMOBOARD? Also, having a little problem with (INA & (1 < 4)). What does that 1 refer to?
Ray
#ifdef __PROPELLER_LMM__
/* Mount file system on a Parallax uSD card. */
#if 1
buffer[0] = 0; // DO
buffer[1] = 1; // SCLK
buffer[2] = 2; // DI
buffer[3] = 3; // CS
LoadSDDriver(buffer);
#else
// Mount file system on a C3 card
LoadSDDriver(0);
#endif
#endif
/* Let the terminal catch up. */
sleep(1);
/* Check for chip select. */
if (INA & (1 < 4))
printf("Card Detected.\n");
else
printf("No Card Detected.\n");
dfs_mount();
/* printf("\n"); */
Help();
Sorry, I meant (1 << 4), which would be 0x10. It would be used to mask off bit 4 in INA. (1 < 4) would produce a value of 1, which would incorrectly mask off bit 0. Sorry about that.
#if and #ifdef are pre-processor directives that will conditionally include lines of code. #if uses a logical argument, so that "#if 1" means to include the following code up to an #else or #endif. #ifdef means to include the following staments if the argument is defined. Since DEMOBOARD is not defined the lines that set up the pin numbers and called LoadSDDriver(buffer) were not used, and LoadSDDriver(0) was used instead. This would have set the SD driver up for the C3 card.
Note, you could have used the "#ifdef DEMOBOARD" if you did a '#define DEMOBOARD" in an earlier line. You could also define DEMOBOARD on the command line at compile time by using the -D option. At this point it's easier for you to just use "#if 1" until you are more familiar with the pre-processor.
I created a function for checking the state of pin 4, I am not sure why it works, but it works as expected. When I have the card in, "Card Detected.", when I have the card out, "Card Not Detected.". I guess I got lucky?
When the program gets compiled it shows "Writing 31048 bytes to Propeller RAM.". I guess that does not leave a whole lot of RAM left to play with.
A thought occurred to me, maybe the CheckCD() function should be placed in its own thread, that way it would always be checking the state of the card reader. But, now I am not sure if there is enough room do it, and how would I create a global variable for the state, and have that variable be read in a function like 'list' while the thread is running in the background?
Comments
At some level, all else being equal, such a decision is a matter of style. I'm open to different perspectives of course.
Some errors can only be caught at run time. In theory, a "+r" parameter to fopen could be caught at compile time, but I don't think the compiler checks for this. What value did the fopen return. It should have returned a NULL, and you could have tested the value of port to see if it was zero. If it didn't return a zero there might be a bug in our stdio library code.
Dave
True, given unlimited resources. Probably true in most cases.
Things to consider:
Using fopen leaves the old stdin and stdout around, which on the Propeller uses an extra two of your 5 remaining file slots. This may not be a concern if you don't need the file slots, but why keep the zombie stdin and stdout around if you don't need them and they don't function properly?
In a typical UNIX system, this would also typically leave unused buffers allocated - ostensibly this could cause trouble if you're running out of Propeller memory space. However, I just checked the code, and the PropGCC library does not allocate buffers for serial devices, so the buffer memory leak that I was worried about does not exist if you use fopen() instead of freopen(). (Note here that I mean any extra memory allocated with malloc(), not the extra two file slots in the limited file descriptor pool, which *are* wasted).
Note this inconsistency: the default stdin uses a static 80 character buffer (statically allocated in init_io.c); however any fopen or freopen of a serial stream appears to use only an 8 character buffer (native to the fp). This means two things: (1) you can call ungetc on the original stdin more than you can ungetc on a reopened stdin, and (2) if you reopen, then you have just stranded an 80-character buffer that serves no further purpose. After noticing this, I'm thinking about filing an issue on it (though this is a very minor, low priority issue).
Last, if you leave the old stdin and stdout lying around at the wrong baud rate, then printf(...) and fprintf(newFpThatStandsForStdout, ...) have different results (ditto getchar() and fgetc(newFpThatStandsForStdin). So, while using freopen instead of fopen be a stylistic, a style that reduces errors is worthy of consideration.
Ray:
I think opening/reopening with "r+" shouldn't be necessary, because you're not going to write on stdin; therefore, using "r" alone should be sufficient.
I did mention this constraint before in different words.
Thanks for digging in on the buffer stuff. That's good info.
A smaller buffer other than on stdin/stdout is a reasonable trade.
So we only have 5 slots? Gee, so much for my 8 port terminal server plan :<
Cheers.
--Steve
In this particular program I used the form of 'void main(void)' which seems to run just fine, how many different forms of main() can be used in PropGCC? If 'void main(void)' works just fine, why would you want to use something like 'int main()'?
Ray
case 'x':
.
.
.
break;
You need a 'break' for every case statement. I noticed in some of the docs online 'break' does not appear in the 'case' statement, so different versions of C handle 'case' in a different manner?
Ray
Unless you explicitly break out of a case, the switch statement continues on to the next case. The break ends the current block of code and in the case of a switch goes to the end of the switch statement. Add the break statements as indicated below.
More a matter of the quality of the documentation than the way C handles it. I would think the switch/case/break operation goes way back into the C standard.
Ray
This is a little disturbing. Eric or someone else please check this too
I changed the do_toggle3 first usleep(10000); to usleep(100000); and it worked. No idea why though.
You can run as many threads as you have room for in memory. The pthreads_toggle demo runs 30 threads - one per pin.
What do you mean by "not working"? Most of the time the LEDs will be off. That's because you turn them each on for only 10 milliseconds and then turn them off (and leave them off while you go on to the other pins). So thread 3 will do the following: I doubt you'll be able to visually notice that activity -- most people's eyes are probably not that sensitive. If you hook the pins up to a scope you should see them being briefly toggled though. As Steve noted, if you change the usleep to a longer value you'll be able to see them.
Eric
Ray
I did notice that there is a difference from usleep(), in timing, from a conversion of msleep() as it pertains to a pthread(). Same thing occurs when I use:
I thought the timing would be more equivalent, even as you did the conversions?
The other thing that I noticed was that if you start to increase the usleep() values in do_toggle1() or do_toggle2, it has an affect on do_toogle3(), makes it non visible.
I guess there is a lot of consideration that has to be calculated before attempting any serious pthread() usage. Also, you have to consider if you really want to do any conversions of usleep(), or sleep().
Ray
With this program I am hoping that I can learn how to start and stop a pthread from a command. Still have not figured out how to kill a pthread().
Ray
Normally one would pthread_create a thread, let it do it's job then and then pthread_exit, then collect thread status with pthread_join. A good example is in the toggle/pthread_toggle demo. There is a cancel function defined in linux pthreads, but it is not supported in propeller GCC.
A Good resources for pthread functions is here:
http://www.kernel.org/doc/man-pages/online/pages/man3/pthread_create.3.html
The example given is for a full implementation of pthreads - Propeller GCC's implementation is "pthread lite".
Thanks,
--Steve
Ray
... (.text+0xc): undefined reference to `_start'.
After looking at some of the examples, I am still missing the point as to how the .spin gets linked to blink16.c? In other words, what am I missing, in terms of code, to get access to 'PUB start' in the .spin program?
Ray
Hi Ray,
The IDE transforms the Spin PASM code into an object for C by running some tools.
You'll have to provide a start function in C to start the COG. Something like this:
The key variable is: binary_blink16_dat_start. Notice that it contains your Spin program name blink16 - without .spin of course. The PASM symbol will always be binary_*_dat_start.
What happens is that the spin compiler bstc or Roy's Spin converts blink16.spin to blink16.dat, and propgcc converts blink16.dat to a C object with the name blink16_firmware.o. Then everything gets compiled and linked together.
Ray
Ray
I provided an example of using filetest.c with the Spinneret card. Look for "#ifdef SPINNERET_CARD" in the main routine in filetest.c. Change this to "#if 1" and change the pin numbers to match the ones that you will be using. I've only tested this on the Spinneret card, so I'll be interested in seeing how it works for you with the Parallax uSD card reader on the demo board.
DO - p0
SCLK - p1
DI - p2
CS - p3
CD - p4
Ray
Ray
I am not following the logic of "#if 1", is that some kind of designation for the DEMOBOARD? Also, having a little problem with (INA & (1 < 4)). What does that 1 refer to?
Ray
#if and #ifdef are pre-processor directives that will conditionally include lines of code. #if uses a logical argument, so that "#if 1" means to include the following code up to an #else or #endif. #ifdef means to include the following staments if the argument is defined. Since DEMOBOARD is not defined the lines that set up the pin numbers and called LoadSDDriver(buffer) were not used, and LoadSDDriver(0) was used instead. This would have set the SD driver up for the C3 card.
Note, you could have used the "#ifdef DEMOBOARD" if you did a '#define DEMOBOARD" in an earlier line. You could also define DEMOBOARD on the command line at compile time by using the -D option. At this point it's easier for you to just use "#if 1" until you are more familiar with the pre-processor.
When the program gets compiled it shows "Writing 31048 bytes to Propeller RAM.". I guess that does not leave a whole lot of RAM left to play with.
A thought occurred to me, maybe the CheckCD() function should be placed in its own thread, that way it would always be checking the state of the card reader. But, now I am not sure if there is enough room do it, and how would I create a global variable for the state, and have that variable be read in a function like 'list' while the thread is running in the background?
Ray