CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

setjmp/longjmp or work-arounds
Goto page Previous  1, 2
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
gustnado



Joined: 23 Apr 2005
Posts: 21
Location: Phoenix,AZ

View user's profile Send private message Visit poster's website AIM Address

PostPosted: Tue May 03, 2005 12:40 pm     Reply with quote

Yeah, I was afraid of that. I can't make a short program that fails! But the big one does. It is, of course, possible that the big one is clobbering the jump environment, but it is unlikely - I am not using any dynamic variables (no malloc, etc).

Anyway, thanks for your help. Since setjmp seems to be buggy, I am currently trying to write a simple setjmp/longjmp in assembly language, but I am not very familiar with PIC assembly and it is a bit odd (RAM in banks, no address registers but powerful FSR functions). Right now I am trying to figure out how to read the top of stack registers. My approach is to call my own setjmp from the mainline, save away the TOS, and in longjmp restore TOS, set _RETURN_ and return. But I don't know how to get at TOS. It cannot be written using MOVFF, although it would seem to be readable that way (except my experiment doesn't work).

Here's my code... any help would be appreciated:

Code:

#byte TOSU=       0xFFF
#byte TOSH=       0xFFE
#byte TOSL=       0xFFD
#byte STKPTR=     0xFFC
#byte FSR0H=      0xFEA
#byte FSR0L=      0xFE9
#byte POSTINC0=   0xFEE
#separate
int tvsenv_addr[3];
tvssetjmp() {
    disable_interrupts(global);
    #asm
    lfsr   0,TOSU
    movff  POSTINC0,tvsenv_addr
    movff  POSTINC0,tvsenv_addr+1
    movff  POSTINC0,tvsenv_addr+2
    #endasm
    enable_interrupts(global);
    return 0;
}


Unfortunately, this code puts a value in tvsenv_addr that is not the return address from which tvssetjmp was called.

Any clues to either problem? How to get the calling off the TOS and how to put it back (or to put it into the PC directly) when MOVFF cannot use PCL, or any TOS register as a destination?

As an aside, the compiler originally generated a branch to the code rather than a call. I had to trick it into doing a call by adding another use of setjmp that couldn't actually happen.
_________________
The best weather is bad weather
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue May 03, 2005 1:15 pm     Reply with quote

You said you can't make a short program that fails.

One way to make a large program is with floating point code.
This little program below, uses 34% of an 18F452 when compiled
with PCH vs. 3.188.

Could you use a program like this, and add setjmp code to it
and make it fail ?

Code:
#include <18F452.h>
#fuses XT, NOWDT, NOPROTECT,PUT,BROWNOUT,NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)

#include <math.h>
//========================================
void main()
{
float a;
float b;
float result;

a = 123.456789;
b = 456.789012;

result = a + b;
result = a - b;
result = a * b;
result = a / b;
result = floor(a);
result = pow(a, b);
result = cos(a);
result = asin(a);
result = atan(a);
result = atan2(a, b);
result = log(a);
result = sqrt(a);
printf("%f ", result);

while(1);
}
gustnado



Joined: 23 Apr 2005
Posts: 21
Location: Phoenix,AZ

View user's profile Send private message Visit poster's website AIM Address

PostPosted: Tue May 03, 2005 1:57 pm     Reply with quote

I think it takes a complex program to fail. I believe I have created one, after analyzing the longjmp code, which fails to save the contents of the top of stack, only saving the stack pointer.

The following program will continuously restart. Here is the output
Code:

Start
B: i = 0
C
before longjmp
Start
B: i = 0
C
before longjmp
Start
B: i = 0
C
before longjmp
Start

etc...

Here is the program. Do you see anything wrong with it?
Code:

#include <18f452.h>
#device ICD=TRUE
#fuses HS,NOLVP,NOWDT,PUT
#use delay(clock=20000000)
#use rs232 (baud=9600, xmit=PIN_C6, rcv=PIN_C7)

#include<setjmp.h>
jmp_buf env;

two() {
    printf("before longjmp\r\n");
    longjmp(env, 2);
}

one() {
    two();
}

C() {
    printf("C\r\n");
}

B() {
    int i;
    i = setjmp(env);
    printf("B: i = %d\n\r", i);
    return i;
}

A() {
    if ( 0 == B() ) {
        C();
        one();
    }
}

main()
{
    printf("Start\n\r");
    A();
    printf("Done\n\r");
    while(1);
}

_________________
The best weather is bad weather
gustnado



Joined: 23 Apr 2005
Posts: 21
Location: Phoenix,AZ

View user's profile Send private message Visit poster's website AIM Address

PostPosted: Tue May 03, 2005 3:11 pm     Reply with quote

Sigh. A friend reminds me that the code above should not work. longjmp must be at a call level below (or maybe the same) as the setjmp, not in another call tree.
_________________
The best weather is bad weather
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue May 03, 2005 3:25 pm     Reply with quote

Near the end of this page, it gives some warnings about using longjmp.
http://publibn.boulder.ibm.com/doc_link/en_US/a_doc_lib/libs/basetrf2/setjmp.htm
It says:
Quote:
if the subroutine that made the corresponding call to the setjmp
subroutine has already returned, then the results of the longjmp
subroutine are undefined.

I think that's what you're doing. Subroutine B() has already returned
when you call longjmp in subroutine two().

Also, CCS doesn't have the longjmperror() routine that is referred to
in that page.
gustnado



Joined: 23 Apr 2005
Posts: 21
Location: Phoenix,AZ

View user's profile Send private message Visit poster's website AIM Address

PostPosted: Tue May 03, 2005 4:58 pm     Reply with quote

That is true in the example, but not in the actual application, where the setjmp call is from the mainline and the longjmp call is from a few subroutines down from the mainline.

This is sure frustrating. The only way I think my program could cause this would be if the memory used by the setjmp is being clobbered, but I am not using dynamic memory and only one array that I don't think is overflowing. I wonder if there is an optimization problem.
_________________
The best weather is bad weather
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page Previous  1, 2
Page 2 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group