|
|
View previous topic :: View next topic |
Author |
Message |
epitalon Guest
|
longjmp on 18F series |
Posted: Tue Nov 03, 2009 7:40 am |
|
|
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
|
|
Posted: Tue Nov 03, 2009 12:43 pm |
|
|
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
|
|
Posted: Tue Nov 03, 2009 2:48 pm |
|
|
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
|
|
Posted: Wed Nov 04, 2009 11:36 am |
|
|
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
|
|
Posted: Wed Nov 04, 2009 12:54 pm |
|
|
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
|
|
Posted: Wed Nov 04, 2009 3:22 pm |
|
|
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
|
|
Posted: Wed Nov 04, 2009 3:32 pm |
|
|
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
|
|
Posted: Wed Nov 04, 2009 5:57 pm |
|
|
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
|
|
Posted: Thu Nov 05, 2009 3:16 am |
|
|
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
|
|
Posted: Thu Nov 05, 2009 3:46 am |
|
|
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
|
|
Posted: Thu Nov 05, 2009 10:36 am |
|
|
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. |
|
|
|
|
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
|