View previous topic :: View next topic |
Author |
Message |
Twain Guest
|
Function returns to the wrong place.... |
Posted: Thu Aug 23, 2007 10:33 am |
|
|
Hello
I've the following situation in a programm for the PIC18F87J10:
int function_a(void)
{
...;
...;
} // End function_a
int function_b(void)
{
int b;
b=function_a();
} // End function_b
int function_c(void)
{
int c;
c=function_a();
} // End function_c
void Main(void)
{
int blabla, blublu;
if(...)
blabla=function_b();
else
blublu=function_c();
} // End main
to
The problem now is, that the subcall to function_a in function_c returns to function_b where it is also called! Why?
Thanks!
Urs |
|
|
Twain Guest
|
|
Posted: Thu Aug 23, 2007 10:36 am |
|
|
Forgot to mention my lst files shows these numbers:
CCS PCH C Compiler, Version 4.053, 39879 23-Aug-07 17:48
Filename: C:\Test 1WB Driver CCS\Test APP - Find Type\1WBTest.lst
ROM used: 12886 bytes (10%)
Largest free fragment is 65528
RAM used: 830 (22%) at main() level
893 (23%) worst case
Stack: 11 worst case (9 in main + 2 for interrupts) |
|
|
zilog
Joined: 17 Aug 2007 Posts: 19
|
|
Posted: Thu Aug 23, 2007 11:18 am |
|
|
We suspect a similar problem with our code - could you please post your code, LST and SYM files, either here or to gnuffelREMOVE (at) gmail.com ? (unspam the adress)
/Daniel |
|
|
Ttelmah Guest
|
|
Posted: Thu Aug 23, 2007 2:09 pm |
|
|
Does it actually call function_a first?. As shown, since you do nothing with the values, and variables can be 'reused' in other functions, you can just generate 'function_c', by jumping to 'function_b'. The optimiser will know the code is the same, and just do this.
Best Wishes |
|
|
Twain Guest
|
|
Posted: Fri Aug 24, 2007 12:49 am |
|
|
Function_c and function_c do completely differ one from each other.
The example code is simplified for display purpose. In real the code is much more complex. Function_c is called sometimes before function_c but not always. This happens depending on the decission path in the code.
So the behavior makes no sense at all, am I right? |
|
|
Twain Guest
|
|
Posted: Fri Aug 24, 2007 12:59 am |
|
|
"Function_a":
int owBlock(int portnum, int do_reset, unsigned char *tran_buf, int tran_len)
{
static unsigned char sendpacket_owBlock[150];
int sendlen_owBlock=0;
int place=0;
int i_owBlock=0;
sendlen_owBlock=0;
// check for a block too big
if (tran_len > 64)
return FALSE;
// check if need to do a owTouchReset first
if (do_reset)
{
if (!owTouchReset(portnum))
return FALSE;
}
// construct the packet to send to the DS2480
// check if correct mode
if (UMode[portnum] != MODSEL_DATA)
{
UMode[portnum] = MODSEL_DATA;
sendpacket_owBlock[sendlen_owBlock++] = MODE_DATA;
}
// add the bytes to send
place = sendlen_owBlock;
for (i_owBlock = 0; i_owBlock < tran_len; i_owBlock++)
{
sendpacket_owBlock[sendlen_owBlock++] = tran_buf[i_owBlock];
// check for duplication of data that looks like COMMAND mode
if (tran_buf[i_owBlock] == MODE_COMMAND)
sendpacket_owBlock[sendlen_owBlock++] = tran_buf[i_owBlock];
}
// flush the buffers
FlushCOM(portnum);
// send the packet
if (WriteCOM(portnum,sendlen_owBlock,sendpacket_owBlock))
{
// read back the response
if (ReadCOM(portnum,tran_len,tran_buf) == tran_len)
return TRUE;
}
// an error occured so re-sync with DS2480
DS2480Detect(portnum);
return FALSE;
}
"Function_b":
int owAccess(int portnum)
{
static unsigned char sendpacket_owAccess[9];
int i_owAccess;
// reset the 1-wire
if (owTouchReset(portnum))
{
// create a buffer to use with block function
// match Serial Number command 0x55
sendpacket_owAccess[0] = 0x55;
// Serial Number
for (i_owAccess = 1; i_owAccess < 9; i_owAccess++)
sendpacket_owAccess[i_owAccess] = SerialNum[portnum][i_owAccess-1];
// send/receive the transfer buffer
if (owBlock(portnum,FALSE,sendpacket_owAccess,9))
{
// verify that the echo of the writes was correct
for (i_owAccess = 1; i_owAccess < 9; i_owAccess++)
if (sendpacket_owAccess[i_owAccess] != SerialNum[portnum][i_owAccess-1])
return FALSE;
if (sendpacket_owAccess[0] != 0x55)
return FALSE;
else
return TRUE;
}
}
// reset or match echo failed
return FALSE;
}
"Function_c"
int owOverdriveAccess(int portnum)
{
static unsigned char sendpacket_ODA[8];
int i_ODA;
int bad_echo = FALSE;
// make sure normal level
owLevel(portnum,MODE_NORMAL);
// force to normal communication speed
owSpeed(portnum,MODE_NORMAL);
// call the 1-Wire Net reset function
if (owTouchReset(portnum))
{
// send the match command 0x69
if (owWriteByte(portnum,0x69))
{
// switch to overdrive communication speed
owSpeed(portnum,MODE_OVERDRIVE);
// create a buffer to use with block function
// Serial Number
for (i_ODA = 0; i_ODA < 8; i_ODA++)
sendpacket_ODA[i_ODA] = SerialNum[portnum][i_ODA];
// send/receive the transfer buffer
if (owBlock(portnum,FALSE,sendpacket_ODA,8))
{
// verify that the echo of the writes was correct
for (i_ODA = 0; i_ODA < 8; i_ODA++)
if (sendpacket_ODA[i_ODA] != SerialNum[portnum][i_ODA])
bad_echo = TRUE;
// if echo ok then success
if (!bad_echo)
return TRUE;
}
}
}
// failure, force back to normal communication speed
owSpeed(portnum,MODE_NORMAL);
return FALSE;
}
The "danger-zone" is the function call to owBlock(). in owOverdriveAccess. After processing owBlock jumps back to the owAccess function. This only happens to owBlock, the functions before which are also called in b and c are not affected.
[/b] |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Aug 24, 2007 1:00 am |
|
|
Since there seems to be some question about the J-series, either with
the chip or the compiler, I suggest that people who have problems with
it should test their code on a "non J-series" PIC chip. Re-compile for
the new chip and see if you still have the problems. |
|
|
Twain Guest
|
|
Posted: Fri Aug 24, 2007 1:21 am |
|
|
Recompiling sounds good but unfortunately i don't have the proper hardware for that. I have a demoboard with a 18F8722 but without the necessary peripherals (1-wire bus transceiver and 1-wire bus net). |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Aug 24, 2007 2:24 am |
|
|
The 18F87J10 and 18F8722 have nearly the same pinout. There are a
few differences. It may not matter if you're not using those pins.
Ideally you would use an 18F87J10 board without the PIC installed,
and then solder some short jumper wires over to the 18F8722 board
to connect the 1-wire chips to the 18F8722 (and power and ground as
well). |
|
|
Twain Guest
|
|
Posted: Fri Aug 24, 2007 8:36 am |
|
|
I tested the 1-wire circuitry together with the 8722 demoboard. I found the exact same behavior as found in the original 87J10 design. |
|
|
Twain Guest
|
|
Posted: Fri Aug 24, 2007 9:20 am |
|
|
I tested some further measures and have now the feeling that everything is as it should be. I obviously put the debug cursor at a position within owBlock where the program counter went not to in the current owBlock call from owOverdriveAccess but in the next done from owAccess.
Shame on me...
Thanks for your inputs anyway. |
|
|
Ttelmah Guest
|
|
Posted: Fri Aug 24, 2007 9:58 am |
|
|
One question.
Are you using the external memory bus?.
There is a hardware erratum, on these chips, when using the tblrd instruction, with the external memory bus, with wait states enabled, that can result in the stack being incremented, which _will_ give a return to the wrong location...
Best Wishes |
|
|
Twain Guest
|
|
Posted: Fri Aug 24, 2007 10:40 am |
|
|
I use the external memory bus indeed. But with no wait states.
Thanks anyway for this useful input. |
|
|
Ttelmah Guest
|
|
Posted: Fri Aug 24, 2007 12:18 pm |
|
|
I'd double check that the bits controlling the wait states, are being configured correctly, or try setting them deliberately to the faulty state!. I have known the erratas to be 'wrong', and the behaviour is suspiciously like what is being described.
Best Wishes |
|
|
|