View previous topic :: View next topic |
Author |
Message |
gustnado
Joined: 23 Apr 2005 Posts: 21 Location: Phoenix,AZ
|
setjmp/longjmp or work-arounds |
Posted: Sat Apr 23, 2005 3:21 pm |
|
|
I have an application where I wait for user input at many places in the code. I want a built-in timeout that takes me back to a spot in my mainline.
setjmp/longjmp are used for this in standard C, but I found a thread indicating that they may not work in PCH. I need to work with both 16F and 18F series processors.
Do they work in both compilers?
If not, is there a workaround using embedded assembler?
If I can't find this sort of solution, I have to return an impossible value (0, for example) and then test for it every place I go to read a character, which would greatly increase the size of the code!
Advice sought. I am new to PIC and new to CCS.
Thanks _________________ The best weather is bad weather |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Apr 24, 2005 1:01 am |
|
|
Can you provide a link to the thread that says they don't work in PCH ? |
|
|
gustnado
Joined: 23 Apr 2005 Posts: 21 Location: Phoenix,AZ
|
|
|
gustnado
Joined: 23 Apr 2005 Posts: 21 Location: Phoenix,AZ
|
setjmp/longjmp - do they work? And how to use on 14 bit part |
Posted: Sun Apr 24, 2005 9:37 am |
|
|
I found this since my last response:
http://www.ccsinfo.com/forum/viewtopic.php?t=19923&highlight=setjmp
An answer by "guest" says:
---------------
r = setjmp(env); Standard C function (requires setjmp.h)
longjmp(env,val); Standard C function (requires setjmp.h)
Use these functions with GREAT caution. Note as well that setjmp and
longjmp do not clean up the stack on 12 and 14 bit parts.
----------------
This is a bit alarming, as I plan to use this capability on both 14 and 16 bit parts. If it does not "clean up the stack," what do I do?
Traditional C compilers maintain a runtime stack with local variables on it, so "cleaning the stack" involves backup up that pointer. I believe these CCS compilers, since they use a compile-time function tree, simply hard allocate those variables in RAM, sharing those that cannot (according to the tree) be active at the same time. In that case, resetting the CPU stack pointer to the top should be adequate (assuming setjmp was called from the top level), since there is no local variable stack.
Is this the case? What would the code look like? _________________ The best weather is bad weather |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Apr 24, 2005 4:29 pm |
|
|
CCS doesn't have any example programs for the setjmp.h file.
Normally, CCS would have something like EX_SETJMP.C, but
I don't see one.
I went to this guy's page and modified his "if-else.c" setjmp
example slightly, so it would work with CCS.
http://linuxgazette.net/issue90/raghu.html
It appears to work OK with PCM vs. 3.223 with a 16F877, but
it did not work with PCH vs. 3.188 with a 18F458. I don't have
the latest version of PCH, to test it.
If CCS doesn't have a EX_SETJMP.C file to test it, how do
they know if SETJMP.H works ? |
|
|
gustnado
Joined: 23 Apr 2005 Posts: 21 Location: Phoenix,AZ
|
|
Posted: Sun Apr 24, 2005 5:08 pm |
|
|
I have it working okay on a 18F452.
It's in the middle of a bunch of code, so I'll just post snippets:
#include "setjmp.h"
jmp_buf set_jmp_env;
main() {
....
if(!setjmp(set_jmp_env)) {
printf(sendChar,"Going for getTimedChar\r\n");
c = getTimedChar();
printf(sendChar,"Got %c\r\n", c);
...
} else {
printf("longjump happened\r\n");
}
.....
}
int getTimedChar() {
....
if (input_timer_setting_secs && !input_timer_countdown_secs) {
longjmp(set_jmp_env, 0xa5);
}
.....
}
Now if I could just get interrupt driven USART receive working, I would be happy
_________________ The best weather is bad weather |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Apr 24, 2005 5:20 pm |
|
|
Quote: | I have it working okay on a 18F452. |
What version of PCH are you using ?
Quote: | Now if I could just get interrupt driven USART receive working, I would be happy |
We know how to make that work. There are many people on this
board who can help you with this. Post a short test program that
shows your complete #int_rda routine. Also post code that shows
how you test if the receive fifo has characters in it, and how you get
the characters from the fifo. Show all variable declarations, etc. |
|
|
gustnado
Joined: 23 Apr 2005 Posts: 21 Location: Phoenix,AZ
|
|
Posted: Sun Apr 24, 2005 5:28 pm |
|
|
I am running PCH Version 3.223.
I have no idea if longjmp/setjmp will work with PCM. If not, I've got a big problem. Unfortunately, I have no way to test it - all I have is a little test board that came with the PCH development kit, and it has an 18F452 on it.
Regarding interrupts, maybe you can point me to an example. I'll put a separate post here with my code.
Thanks _________________ The best weather is bad weather |
|
|
gustnado
Joined: 23 Apr 2005 Posts: 21 Location: Phoenix,AZ
|
|
Posted: Sun Apr 24, 2005 5:49 pm |
|
|
FYI, I got the interrupt routine working, so no help needed.
It helps to read the data register with a "*" in front of the address of the input data fsf _________________ The best weather is bad weather |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Apr 24, 2005 6:07 pm |
|
|
Quote: |
I have no idea if longjmp/setjmp will work with PCM. If not, I've got a big
problem. Unfortunately, I have no way to test it - all I have is a little test
board that came with the PCH development kit, and it has an 18F452 on it. |
I guess you must have this mini 18F452 board.
http://www.ccsinfo.com/evalkit452.shtml#18f452
The PIC is soldered to the board, so there's no way you can buy
another PIC and use it on that board. You probably need to buy
their 16F877A board to test your PCM compiler. There are many
methods of making a test board.
Below, I have posted the modified "if-else.c" program from that guy's
web page, at http://linuxgazette.net/issue90/raghu.html
It produces the following output on the terminal window.
So according to his description, it is working. This was tested with
PCM vs. 3.223.
Quote: |
Start
i = 0
I am in if ..
i = 2
I am in else too...
Done |
Code: | #include <16F877.H>
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#include<setjmp.h>
main()
{
jmp_buf env;
int i;
printf("Start\n\r");
i = setjmp(env);
printf("i = %d\n\r", i);
if(i == 0)
printf("I am in if ..\n\r");
else
{
printf("I am in else too...\n\r");
goto done;
}
longjmp(env, 2);
printf("Grrr... why am i not getting printed\n\r");
done:
printf("Done\n\r");
while(1);
} |
|
|
|
gustnado
Joined: 23 Apr 2005 Posts: 21 Location: Phoenix,AZ
|
|
Posted: Sun Apr 24, 2005 6:11 pm |
|
|
Thanks. It looks like it should do the job, then. _________________ The best weather is bad weather |
|
|
gustnado
Joined: 23 Apr 2005 Posts: 21 Location: Phoenix,AZ
|
|
Posted: Tue May 03, 2005 10:13 am |
|
|
The example works fine in PCH/18F452, but in my application, where things are more complex and the longjmp takes place well down in a subroutine call hierarchy, it doesn't work right - it causes restarts sometimes and other times does not - all to the same input!
Because longjmp uses a stack, which makes it complex and the assembly code hard to follow, I am going to give up on it, assume there is a good reason that it is not in the compiler book and examples, and write my own simple one in assembly language.
My tentative conclusion, after a lot of fiddling, is that setjmp/longjmp is possibly flawed in a subtle way. With the code slightly different it would always go to the right place but setjmp always returned 0, even when a longjmp(jmp_buf, 2) was taken. The code around it now looks like:
Code: |
c = setjmp(jmp_env);
if ( 0 == c ) {
printf("---setjmp returns OK: %d\r\n", c);
do_burst_or_poll() ;
} else {
printf("---setjmp returns timeout: %d\r\n", c);
|
|
The longjmp code:
Code: |
// If timed out, jump to mainline
if (0 >= --input_timer_countdown_secs) {
longjmp(jmp_env, 2);
}
|
The buffer declaration:
Code: |
// Set jump buffer
jmp_buf jmp_env;
|
I am new to the PIC and CCS. Does anyone know CCS's position on setjmp/longjmp? They are not listed in my compiler manual or the list of supported C library methods on the web site. Since it isn't in the compiler book, does that mean it is not a supported feature? Do I report this as a bug or is there a place to look for known bugs, or is it just not supported (I expect the latter)? _________________ The best weather is bad weather |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue May 03, 2005 10:37 am |
|
|
It is in the manual. Download the Feb. 2005 manual. Use the
search engine of Acrobat Reader to search for: setjmp
It's in there, in several places. |
|
|
gustnado
Joined: 23 Apr 2005 Posts: 21 Location: Phoenix,AZ
|
|
Posted: Tue May 03, 2005 11:34 am |
|
|
You are correct, although it is not in the expected location - the alphabetical list of functions with descriptions. I missed it because I was using the printed version of the same manual. Thanks for the pointer.
However, there is my experience and that of the other person's where longjmp apparently frequently causes restarts on the 18f series.
Should I report this as a possible bug? _________________ The best weather is bad weather |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue May 03, 2005 11:42 am |
|
|
Sure. If you can give CCS a complete (but short) test program
that allows them to easily see the problem, then your chances
of getting them to fix it are much better. Also give them your
compiler version. |
|
|
|