View previous topic :: View next topic |
Author |
Message |
barbiani
Joined: 02 Feb 2013 Posts: 7
|
"Recursion not permitted" Error message |
Posted: Sat Feb 02, 2013 12:07 pm |
|
|
Hi everybody,
I am was writing a firmware that was not compiling so I made the smallest version of it that still shows the error.
I think that the compiler is not doing the job right...
Thank you for any tips!
Code: | #include <18f4620.h>
typedef void (*task_entry_t)(void); // pointer the thread function
void task_PARENT(void);
task_entry_t PARENT = &task_PARENT;
void task_CHILD(void);
task_entry_t CHILD = &task_CHILD;
void task_CHILD (void) {}
void task_PARENT (void) { CHILD(); }
void main(void) { CHILD(); }
|
|
|
![](templates/subSilver/images/spacer.gif) |
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Sat Feb 02, 2013 12:30 pm |
|
|
what are you trying to accomplish ? |
|
![](templates/subSilver/images/spacer.gif) |
barbiani
Joined: 02 Feb 2013 Posts: 7
|
|
Posted: Sat Feb 02, 2013 12:33 pm |
|
|
Pseudo multitasking... The code was bigger but I removed most of it.
The portion I've posted does not even compile. |
|
![](templates/subSilver/images/spacer.gif) |
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Sat Feb 02, 2013 12:44 pm |
|
|
Quote: |
typedef void (*task_entry_t)(void); // pointer the thread function
|
makes my head spin - redefining "void" in terms of a dereferenced pointer
TO(?) the value of "void" ??
WTF ???? is that about ?? |
|
![](templates/subSilver/images/spacer.gif) |
barbiani
Joined: 02 Feb 2013 Posts: 7
|
|
Posted: Sat Feb 02, 2013 12:48 pm |
|
|
no... that is a pointer to a void function. |
|
![](templates/subSilver/images/spacer.gif) |
jeremiah
Joined: 20 Jul 2010 Posts: 1328
|
|
Posted: Sat Feb 02, 2013 2:19 pm |
|
|
And you are using correct syntax for it. I use that syntax a lot as well.
I believe the problem is this:
Function pointers are very difficult to handle in the PIC series chip due to hardware limitations, but they are doable. In order to have them work, the CCS compiler calls an internal function (you can see this in the LST file) that takes the address in the function pointer and runs it withing that routine. Trying to run a function pointer within a function pointer requires that you execute that special internal function within another copy of the special internal function, which would be recursion, and the compiler does not do recursion to my knowledge. In short, your function pointers cannot call function pointers if what I understand is correct. You'll probably have to work out a method to keep your function pointers one level deep. |
|
![](templates/subSilver/images/spacer.gif) |
barbiani
Joined: 02 Feb 2013 Posts: 7
|
|
Posted: Sat Feb 02, 2013 2:29 pm |
|
|
Yes. But can you see that the only thing this program does is to call task_CHILD and this function does nothing? I think there is no recursion.
What do you mean by 'one level deep'? |
|
![](templates/subSilver/images/spacer.gif) |
jeremiah
Joined: 20 Jul 2010 Posts: 1328
|
|
Posted: Sat Feb 02, 2013 3:21 pm |
|
|
barbiani wrote: | Yes. But can you see that the only thing this program does is to call task_CHILD and this function does nothing? I think there is no recursion.
What do you mean by 'one level deep'? |
Yes, but with function pointers, unlike normal functions, CCS will look at creating the code for task_PARENT() since it is assigned to a variable, even if that variable is never ever used.
When it creates PARENT, it will create the code for task_PARENT(), which calls CHILD() which is linked to task_CHILD();
So even though you are not calling PARENT yet, the compiler will go ahead and assume you will in order to create the function pointer and assign the task to it.
The process for the PARENT variable IF it were to be called is thus (pseudo code):
Code: |
call CCS_Internal_Function_Pointer_Caller(PARENT){
load task_Parent() address;
run PARENT(){
call CCS_Internal_Function_Pointer_Caller(CHILD){
load task_Child() address;
run CHILD(){
//child code here
}
}
}
}
|
Notice that CCS_Internal_Function_Pointer_Caller() is called within itself (recursion).
Even though you don't call it in the main, by making the function pointer for PARENT and assigning it to task_PARENT(), you are causing the compiler to attempt recursion internally.
EDIT: "one level deep": Notice in my pseudo code how there are 2 "levels" of CCS_Internal_Function_Pointer_Caller()? I refer to that as 2 levels deep. One level deep basically means don't call function pointers within function pointer functions. |
|
![](templates/subSilver/images/spacer.gif) |
barbiani
Joined: 02 Feb 2013 Posts: 7
|
|
Posted: Sat Feb 02, 2013 3:39 pm |
|
|
Now I understand! Thank you for your time and sharing this .
One function calling another was a feature that would simplify the final application a lot. |
|
![](templates/subSilver/images/spacer.gif) |
|