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 support@ccsinfo.com

longjmp on 18F series

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
epitalon
Guest







longjmp on 18F series
PostPosted: Tue Nov 03, 2009 7:40 am     Reply with quote

Hello,

In my program, using a 18F4550, I use calls to longjmp/setjmp.

The call to longjmp does not work. It resets the program instead.
I disabled interrupts before call to longjmp. Not better.

Looking at CCS forum, I can see that many people experienced the same problem.
Has anyone attempted to fix this ?
Is anyone close enough to CCS staff in order to convince them that there is a problem ?

Thanks in advance
Jean-Marie
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Tue Nov 03, 2009 12:43 pm     Reply with quote

What is your compiler version number?
Have you looked at the generated source code in the list file (*.lst)? Does it make sense?

Post a small program demonstrating your problem. The program should be complete and not larger than about 25 lines.
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Tue Nov 03, 2009 2:48 pm     Reply with quote

It seems to me, that setjmp/longjmp is basically working with PCH/PIC18. But I don't know, if it worked by chance only.
It's not working (not restoring the stack) with PCD however.

To clarify the issue, you should show a test code as suggested.
epitalon
Guest







PostPosted: Wed Nov 04, 2009 11:36 am     Reply with quote

My compiler version is 4.085
I checked the assembly code : it seems OK.

From what I read in this forum from users that experienced problems with longjmp, small programs do work.

So, I won't try to make a sample test program that fails.
My program is too complex to be posted here. Plus, it involves communications on a I2C bus with slaves microcontrollers.

I'll try to search a solution a different way :
First, I will check if the jump buffer was corrupted at longjmp time.
I don't see why it would. My program seems to work correctly before adding the setjmp/longjmp.
But who knows ?....

second, er....
I accept any suggestion ...
Is it possible that the bank number be wrong at the time of the longjmp ?


Jean-Marie Epitalon
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Wed Nov 04, 2009 12:54 pm     Reply with quote

I agree, that there may be various reasons, why a problem only apears in particular application enviroment.
I experienced similar issues from time to time. It's also a fact, that the ultimate resaon isn't always what it
seemed, often it's an apparently unrelated application code problem. But before revealing it in the specific case,
there isn't much use in guessing.

I also reviewed the existing forum discussion about the topic. I see exactly one person, who reported
a similar problem of setjmp basically working, but failing in a complex PIC18 application. As in your case,
it couldn't be reproduced. A test program, that has been presented revealed as inappropriate later on.

Another point is setjmp with PIC16. Although not explicitely mentioned in the compiler manual, setjmp can't
work across subroutine levels with this processor, because it has no accessible stack pointer. So the discussion
should be limited to PIC18.

As a good thing, setjmp/longjmp is plain C code, so it can be checked (and modified, if necessary) without
involving CCS. Looking at the code, it's immediately obvious, why it doesn't work with PCD, the code simply
doesn't consider this processor and compiles a PCM/PIC16 variant, which can't work. You can also see, that
setjmp.h is basically unchanged since V3.223, that has been the recent version in the said previous forum discussion.

You asked, if there's possibly a problem with access banks? I would expect the access bank to be restored
after a function call as setjmp/longjmp, so it shouldn't be. But a problem of this kind must be present, if your
observations are correct.

If you have a place in your code, where longjmp fails repeatable, can't you recognize the problem with MPLAB
debugger on the assembly level?
epitalon
Guest







PostPosted: Wed Nov 04, 2009 3:22 pm     Reply with quote

Actually, there is a bug in setjmp/longjmp with compiler version 4.085
The problem is in the "call" (inline call) to
Code:

#inline
int setjmp(jmp_buf env) ;

The compiler passes only the low order byte of address of parameter "env".
While the inline called function expects two bytes.

See example below :
Code:

....................     int8 err;
....................     
.................... 
....................    err = setjmp ( &test[0]);
002A:  MOVLW  06
002C:  MOVWF  0C
*
005C:  MOVFF  01,0B


.................... #inline
.................... int setjmp(jmp_buf env)
.................... {
....................    ((__jmp_environ*)env)->address = label_address(callback);
*
002E:  MOVFF  0C,FE9
0032:  MOVFF  0D,FEA
0036:  MOVLW  00
0038:  MOVWF  03
003A:  MOVLW  58
003C:  MOVWF  FEF
003E:  MOVFF  03,FEC
( ....)

I fixed the problem by replacing
Code:

int setjmp(jmp_buf env)

by
Code:

int setjmp(int8 * env)
   in file <setjmp.h>

Jean-Marie
EPITALON
Guest







PostPosted: Wed Nov 04, 2009 3:32 pm     Reply with quote

Still, I wonder if one must disable interrupts before calls to longjmp and setjmp....
I am not a specialist of PIC internals. So I am asking one of you, who could know for sure what is required.

After thoughts, I don't believe there is any need to do so...

Jean-Marie
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Wed Nov 04, 2009 5:57 pm     Reply with quote

Quote:
The compiler passes only the low order byte of address of parameter "env" while the inline called function expects two bytes.

I don't see the problem, using the provided type definition jmp_buf env, also with a nonzero highbyte address, either in PCh V4.099 or V4.084.
Code:
jmp_buf env;
#locate env = 0x234

Can it be a problem of your variable definition?

I also didn't yet see a reason, why longjmp shouldn't be interrupt-save.
epitalon
Guest







PostPosted: Thu Nov 05, 2009 3:16 am     Reply with quote

Quote:

I don't see the problem, using the provided type definition jmp_buf env, also with a nonzero highbyte address, either in PCh V4.099 or V4.084.


The problem in the example that I gave is :
The address of varaible jmpbuf test is 0006H
When passing the address to the inline function setjmp, the compiler should set :
- byte at address 0C to 06, the low order byte of the address
- byte at address 0D to 00, the high order byte

It does not. It simply set adr 0CH to 06.

The program will fail if, by chance, content of address 0DH is not 0.
On small programs, it is likely that the unset byte (at address 0DH) is left unchanged since reset, and its value is zero. Then the setjmp will not fail.

On large programs, it is likely that the byte at address 0DH has been used in another part of the program for a local variable and, as such, its value is random. The setjmp call will fail to fill in the setjmp buffer.

If you don't understand, I will try to design a reasonably small program that will fail
.
Jean-Marie
epitalon
Guest







PostPosted: Thu Nov 05, 2009 3:46 am     Reply with quote

I designed a small program that will fail.
Here it is.
Code:

#include <18f4550.h>
#include <setjmp.h>
#fuses HSPLL, PLL2, USBDIV, CPUDIV1,NOPROTECT,NOWDT,NOLVP,NOPUT, NODEBUG,VREGEN
#use delay(clock = 48 000 000)
#use rs232(baud=38400, xmit=PIN_C6, rcv=PIN_C7, bits=8)

jmp_buf test;

int32 long_data[450];

int32 first_fct (int32 p1, int32 p2, int32 p3, int32 p4, int32 p5, int32 p6, int32 p7, int32 p8, int32 p9, int32 p10);
void second_fct (void);

void main()
{
   int8 err;
   
   first_fct (0x5501, 2, 3, 4, 5, 6, 7, 8, 9, 10);
   err = setjmp (test);
   if (err != 0)
   {
      puts ("return from longjmp");
   }
   second_fct ();

}


int32 first_fct (int32 p1, int32 p2, int32 p3, int32 p4, int32 p5, int32 p6, int32 p7, int32 p8, int32 p9, int32 p10)
{
    return 1;
}

void second_fct (void)
{
    longjmp (test, 1);
}


With my compiler version, v4.085 :
In the call to first_fct(), the first parameter occupies the same address as the parameter "test" in the subsequent call to setjmp().
Then, when calling setjmp(), the unset high order byte has a non-zero value.
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Thu Nov 05, 2009 10:36 am     Reply with quote

It works O.K. in V4.093 and later, but fails in V4.087 and previous. The reason is, as you reported correctly, the processing of
err = setjmp (test);
In my previous test, I forgot to erase the jumpbuf memory when changing to the old version, so I missed the bug.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
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