|
|
View previous topic :: View next topic |
Author |
Message |
kda406
Joined: 17 Sep 2003 Posts: 97 Location: Atlanta, GA, USA
|
Multiple main() functions/Pointer to function/Lost s...Help! |
Posted: Thu Jul 06, 2006 7:45 am |
|
|
I will spare you from the details of why my program needs this and simply ask for how to do this with CCS. I do REQUIRE this functionality. The job I need this most for is using a PIC18F8722 with 3.249 of PCWH.
Let's say my program looks at a jumper when it boots. This jumper determines the personality of the program. On the PIC, if the input is low it runs one program, and if it is high, it runs another. The programs are not related. The programs must reside in different program memory segments.
The main() can be simple, read the pin, and run one function or the other. But this permanently uses stack space for a call that will never return.
A pointer to a function would solve the problem, but according to their documentation, CCS does not support this standard C feature. They claim they cannot do pointers to functions because there is no way to pass parameters, but they completely overlooked the obvious usefulness of a pointer to a function that does not need parameters. So let us forget CCS' shortcomings and see if there is an alternate approach.
I tried a trick I found on the forum. The code snippet below illustrates it. The point was to go to the main(), call the personality function, and clear the stack:
Code: | #byte STKPTR=0xFFC
#define clear_stack() STKPTR=0
void main(void) {
Real_Main();
}
void Real_Main(void) {
clear_stack();
... |
It sort of works, but I found that somehow it “corrupts” my ISRs, and cannot be used because of this.
I tried “goto” but that doesn't work either. Since the function is jumped to directly and there is no call to it, the code optimizer doesn't compile the personality programs or any of their subs, or their ISRs. Basically, it only compiles a main() with a few lines in it! I have tried this in many ways and combinations using labels and direct addressing with no success.
Are there any other options have I overlooked? Or perhaps is there a way to make one of these options work? All constructive suggestions will be appreciated!
-Kyle |
|
|
Ttelmah Guest
|
|
Posted: Thu Jul 06, 2006 8:44 am |
|
|
CCS, does support pointers to functions. Look at the example 'qsort', for how this is done. However this will still leave you with a call on the stack. At 'heart', what you are describing, is almost the code needed in bootloader type programs. #ORG, will allow you to specify that a program re-uses RAM (with the auto=0 directive), so no memory is wasted, and the 'pop' assembler instruction, or the bodge you have already found, will allow you to pop the return address so this is not lost.
Look at the 'goto_address' command. These allow you to jump to a function elsewhere.
There is no reason for what you post to corrupt the ISR's, unless the system is restarting from a stack overflow, or the routines are returning. Remember that _you_ must ensure this never happens. For the normal 'main', CCS adds a hidden sleep instruction off the end, but with a jump/call to another routine, this protection is lost. Check just how much stack is being used.
Best Wishes |
|
|
Neutone
Joined: 08 Sep 2003 Posts: 839 Location: Houston
|
Re: Multiple main() functions/Pointer to function/Lost s...H |
Posted: Thu Jul 06, 2006 8:52 am |
|
|
kda406 wrote: | The main() can be simple, read the pin, and run one function or the other. But this permanently uses stack space for a call that will never return.
-Kyle |
Within main you can switch for the jumper. Just be sure both functions are declared as inline. There will be no stack space used. A function that is only called once will not use stack space usually. If declared inline a function can not use stack space.
So basicly you don't REQUIRE the functionality you thought you need.
-Neutone |
|
|
kda406
Joined: 17 Sep 2003 Posts: 97 Location: Atlanta, GA, USA
|
|
Posted: Thu Jul 06, 2006 9:16 am |
|
|
Thanks for your reply, but it brings up more questions. Firstly, according to CCS, they do NOT support pointers to functions. Here is an excerpt from their most recent manual:
Quote: | How do I make a pointer to a function?
The compiler does not permit pointers to functions so that the compiler can know at compile time the complete call tree. |
I am using many #ORG statements. On the auto=0 directive you mentioned, which function gets this parameter? The main() that is never returned to, or one of the personality programs it calls? I have reviewed the CCS documentation on #ORG hundreds of times and am always left wondering what the hell they are talking about in the last paragraph which mentions this directive. Also, there is no example of this directive as far as I have found. Since CCS leaves me in the dark on this, can you explain it to me (and the forum) in more detail?
I mentioned about goto(_address). This didn't work for me because the code optimizer did not compile the personality programs because there were no calls to them. The compiler sees them as unused functions and no code is generated for them.
I have not tried 'pop' yet. Perhaps this will work better than clearing the stack the way I showed earlier.
Many thanks for your help, “Ttelmah”.
-Kyle |
|
|
kda406
Joined: 17 Sep 2003 Posts: 97 Location: Atlanta, GA, USA
|
Re: Multiple main() functions/Pointer to function/Lost s...H |
Posted: Thu Jul 06, 2006 9:19 am |
|
|
Neutone wrote: | ...Just be sure both functions are declared as inline. There will be no stack space used. A function that is only called once will not use stack space usually. If declared inline a function can not use stack space.
So basicly you don't REQUIRE the functionality you thought you need.... |
Thanks Neutone, but as I said, the personality programs must reside in different segments of memory. Is there a way to compile them inline and also in different, discrete segments of memory?
Thanks,
Kyle |
|
|
Ttelmah Guest
|
|
Posted: Thu Jul 06, 2006 9:53 am |
|
|
Pop, will be no 'better'. What you are doing, should not fail, unless one of the problems I refer to is occuring. Find out _why_ your code is failing....
Auto, allows two programs to have RAM using the same area. Applies to your two 'main' programs, since these should be able to use the same RAM areas.
The lack of 'pointers to functions', was fixed for specific types of operations a while ago. A lot of the manual is old.
There are two different 'goto' commands. Goto, can only go to a _local_ address. Goto_address, can go _anywhere_. However remember you need to generate the address yourself. If you declare the routine with a #org, then you can just goto_address this location, and arrive at the routine. The optimiser should not remove the routines. For example, the following code:
Code: |
Goto_address(0x2000);
//With the following declaration:
#org 0x2000,0x3000 auto=0 default
#separate
void demo(void) {
int8 ctr;
ctr=0;
printf("Testing");
for (ctr=0;ctr<10;ctr++);
while(true);
}
//generates the following assembler:
.................... Goto_address(0x2000);
00194: GOTO 2000
.................... #org 0x2000,0x3000 auto=0 default
.................... #separate
.................... void demo(void) {
.................... int8 ctr;
.................... ctr=0;
*
0201C: CLRF 26
.................... printf("Testing");
0201E: CLRF 27
02020: MOVF 27,W
02022: RCALL 2000
02024: IORLW 00
02026: BZ 2032
02028: INCF 27,F
0202A: MOVWF 28
0202C: GOTO 0008
02030: BRA 2020
.................... for (ctr=0;ctr<10;ctr++);
02032: CLRF 26
02034: MOVF 26,W
02036: SUBLW 09
02038: BNC 203E
0203A: INCF 26,F
0203C: BRA 2034
.................... while(true);
0203E: BRA 203E
.................... }
02040: RETLW 00
|
The key here, is that 'ctr', can end up using RAM space that has already been used in 'main'.
Best Wishes |
|
|
kda406
Joined: 17 Sep 2003 Posts: 97 Location: Atlanta, GA, USA
|
|
Posted: Thu Jul 06, 2006 1:50 pm |
|
|
First of all, many thanks for your help so far.
I am quite positive my personality functions disappeared when trying goto_address previously. I tried to illustrate this, but with my current, tiny program to illustrate the problem, I cannot get it to occur. However, I can show the optimizer not working correctly when using #ORG statements. Knowing this, perhaps you will believe me when I say the personality programs disappear from the compiled code under certain circumstances. Let's hope it is my mistake because it will be far quicker to fix!
Here is a sample program using some of the points we have discussed:
Code: | #include "18F8722.h"
#use delay(clock=11059200) //11.0592 MHz Oscillator
#fuses EC_IO,NOPROTECT,NOIESO,NOBROWNOUT,NOWDT,PUT,NOCPD, NOSTVREN,NODEBUG,NOLVP,NOWRT,NOCPB,NOEBTRB,NOEBTR,CCP2C1, NOWRTD,NOWRTC,NOWRTB,NOFCMEN,NOLPT1OSC,MCLR,NOXINST,MCU, NOWAIT
// This shouldn't end up in the code because nothing calls it.
void Nothing (void) { output_high(PIN_J3); }
#org 0x10000,0x1FFFF auto=0 default
///////// APPLICATION /////////
void main_Palm(void) {
unsigned int8 i=0;
while(1) if(i++>250) output_high(PIN_J2); else output_low(PIN_J2);
}
///////// PERSONALITY CHOOSER /////////
#org 0x00024, 0x00FFE default
void main(void) {
output_high(PIN_J1); // Turn on an LED
goto_address(0x10000); // Try it using a discrete address
}
// This also shouldn't end up in the code because nothing calls it.
void Nothing2 (void) { output_high(PIN_J3); } |
I think we all agree the code optimizer should not include Nothing and Nothing2 in the compiled output since they are not called. I think it is important to show the whole list file here (sorry for the length):
Code: | 00000: GOTO 002A
.................... #include "18F8722.h"
.................... //////// Standard Header file for the PIC18F8722 device ////////////////
.................... #device PIC18F8722
.................... #list
....................
....................
.................... #use delay(clock=11059200) //11.0592 MHz Oscillator
.................... #fuses EC_IO,NOPROTECT,NOIESO,NOBROWNOUT,NOWDT,PUT,NOCPD, NOSTVREN,NODEBUG,NOLVP,NOWRT,NOCPB,NOEBTRB,NOEBTR,CCP2C1, NOWRTD,NOWRTC,NOWRTB,NOFCMEN,NOLPT1OSC,MCLR,NOXINST,MCU, NOWAIT
....................
.................... // This shouldn't end up in the code because nothing calls it.
.................... void Nothing (void) { output_high(PIN_J3); }
....................
.................... #org 0x10000,0x1FFFF auto=0 default
.................... ///////// APPLICATION /////////
.................... void main_Palm(void) {
.................... unsigned int8 i=0;
*
10000: CLRF 06
.................... while(1) if(i++>250) output_high(PIN_J2); else output_low(PIN_J2);
10002: MOVF 06,W
10004: INCF 06,F
10006: SUBLW FA
10008: BTFSC FD8.0
1000A: GOTO 10016
1000E: BCF F9A.2
10010: BSF F91.2
10012: GOTO 1001A
10016: BCF F9A.2
10018: BCF F91.2
1001A: GOTO 10002
.................... }
1001E: RETLW 00
....................
.................... ///////// PERSONALITY CHOOSER /////////
.................... #org 0x00024, 0x00FFE default
.................... void main(void) {
*
0002A: CLRF FF8
0002C: BCF FD0.7
0002E: CLRF FEA
00030: CLRF FE9
00032: MOVF FC1,W
00034: ANDLW C0
00036: IORLW 0F
00038: MOVWF FC1
0003A: MOVLW 07
0003C: MOVWF FB4
.................... output_high(PIN_J1); // Turn on an LED
0003E: BCF F9A.1
00040: BSF F91.1
.................... goto_address(0x10000); // Try it using a discrete address
00042: GOTO 10000
.................... }
....................
.................... // This also shouldn't end up in the code because nothing calls it.
.................... void Nothing2 (void) { output_high(PIN_J3); }
00024: BCF F9A.3
00026: BSF F91.3
00028: RETLW 00
00046: SLEEP |
As you can see, Nothing2() gets compiled in even though nothing calls it! Nothing() is ignored, as it should be. Under certain circumstances, main_Palm() gets ignored and disappears from the code like Nothing() does.
Is the fact that Nothing2() gets compiled in when it is not called indicative of a bug?
Perhaps if we can solve the mystery to Nothing2() we can get to the root of why my personality programs sometimes disappear when I use this approach to the original problem. Remember, I had initially dismissed the use of goto_address for this requirement because the personality programs weren't ending up in the compiled code and I thought it was the optimizer taking them out because they weren't called.
Thanks,
Kyle |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Jul 06, 2006 2:09 pm |
|
|
As you can see, Nothing2() gets compiled in even though nothing calls it! Nothing() is ignored, as it should be.
Do you realize your sentence above is like a "Who's on First" routine ?
(Abott and Costello comedy routine). |
|
|
kda406
Joined: 17 Sep 2003 Posts: 97 Location: Atlanta, GA, USA
|
|
Posted: Thu Jul 06, 2006 2:16 pm |
|
|
PCM programmer wrote: | Do you realize your sentence above is like a "Who's on First" routine ?
(Abott and Costello comedy routine). |
That's why I used the parenthesis. I did think it was humorous when I wrote it though.
-Kyle |
|
|
Ttelmah Guest
|
|
Posted: Fri Jul 07, 2006 4:05 am |
|
|
First, don't fix the address of your 'personality chooser' this low in memory. You are in the area the compiler will expect to use for the interrupt handler. This is probably why it is stopping your interrupts working...
'Nothing2', gets compiled, because your ORG override is still in force. You can make any routine compile, by giving it an ORG, and an ORG with 'default', remains in force, till another ORG is met (or a #ORG default, switches 'back' to normal operation). This is exactly how you can make your routines be compiled, even if not 'called'.
If you add #ORG default, after the 'main', then Nothing2, will not be compiled.
Best Wishes |
|
|
kda406
Joined: 17 Sep 2003 Posts: 97 Location: Atlanta, GA, USA
|
|
Posted: Fri Jul 07, 2006 8:52 am |
|
|
Ttelmah,
Adding an #ORG default does allow the optimizer to ignore Nothing2(). I think with the help you have given me here, I can get this running without losing a stack entry permanently.
The goto and ISR problems were two separate issues. Much like a bootloader, I have the ISRs relocated in memory. I removed them to shorten the example. They work flawlessly until I call the personality program and do a 'pop'. I think the goto will be an easier option, so I am not going to spend time further investigating the ISR/pop problem.
Thanks for your help!
-Kyle |
|
|
|
|
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
|