Hi, does anyone know if Keil has added support for calls through a function pointer table, or if they are about to do so? Right now it is a bomb, especially when using banked memory. /Christian
This should help: http://www.keil.com/support/docs/2486.htm
Thanks, I should have got a status from my colleagues first. The function pointer table calling works correctly, but they have problems with overlaying. Maybe the problem is related to interfacing an assembler mask and a C application, or perhaps the overlaying problem exits because of the function pointer table. The problem is that local variables are not overlayed. The compiler seems to treat each function totally idependant of the rest, and does not remember which variables that can be overlayed. /Christian
If you had taken even a cursory look into the manual before posting here, you should have found the relevant information faster than you could possibly have written the two posts.
"If you had taken even a cursory look into the manual..." Take a very careful look at the Note at the foot of the page: http://www.keil.com/support/man/docs/c51/c51_xf_funcptr.asp You must also read the following: Application Note 129 - Function Pointers in C51: http://www.keil.com/appnotes/docs/apnt_129.asp C51: PROBLEMS WITH FUNCTION POINTERS OVERWRITING VARIABLES: http://www.keil.com/support/docs/210.htm
Take a very careful look at the Note at the foot of the page Which, in very polite words, say: "if you use function pointers you are screwed". Why, oh why, does so many insist on coding the '51 as if it was a "mini PC"?. The '51 is a beautiful little chip when used as a '51 It is darn ugly when used as a "mini PC". Would you expect a gasoline car to run well on diesel? Erik
"Which, in very polite words, say: 'if you use function pointers you are screwed'." Not at all. It says, "you can certainly use function pointers provided you understand what's going on, and observe the precautions"
Which, in very polite words, say: "if you use function pointers you are screwed". It's not quite that bad. It's more like: "Function pointers on your '51 are armed and dangerous. To be handled only by properly trained personnel. Thou hast been warned."
Ok, if you have a program that is so small that it does not use many variables, you can use function pointers. That beg the question: why would you use function pointers in a program that small. Anyhow, this all relates to the whines "why is the '51 not like a PC" Erik
The sheer number of variables is a problem only if function pointers are used irresponsibly, without following the docs closely. The real problem is that you have to use function pointers in a disciplined fashion, so you can tell the linker what exactly that fashion looks like. It's lack of this discipline that kills projects. Even with this complication, function pointers IMHO beat most alternatives hands-down for the typical use cases, like a state machine implemented by calls to "transition" functions found in the state table, or cooperative multi-tasking systems where each task is one function. It's a classic case of "sharp knife syndrom". The same thing that would be a public menace in the hands of the clueless is an indispensable tool if wielded by a surgeon.
"The real problem is that you have to use function pointers in a disciplined fashion, so you can tell the linker what exactly that fashion looks like. It's lack of this discipline that kills projects." In fact, there are certain cases where the Linker can deduce the call tree itself - but, again, you have to play strictly by the rules. See the above-mentioned documents for details. "... function pointers IMHO beat most alternatives hands-down for the typical use cases, like a state machine ... " Absolutely! http://www.8052.com/forum/read.phtml?id=47543 http://www.8052.com/forum/read.phtml?id=47549 "It's a classic case of 'sharp knife syndrome'" Definitely!
Running the risk of getting flamed for poor style here, let me run this one by you. I recently used function pointers in a program for (I think) good reason, but in a manner where the call tree was deduced properly. It seems as long as the name of the function pointed to appears in the function it's being called from then the call tree is constructed correctly. My problem was this: I have a product that has to read data from a sensor. We made a modification to the hardware that required using different pins to read this sensor in newer revision boards. So, I read a hardware revision code from the board (usual resistor code, etc.) and want to use the appropriate lines based on that. I have a function, let's call it "GetValue" that performs several reads of the sensor and returns an average value. I also have two functions sensor_read_old and sensor_read_new that read an individual value from the sensor, using either the old or new set of data lines. So, at this point I have a few options. One is to write two separate GetValue functions--one for each sensor acquisition function. The other is to do a comparison within GetValue before every sensor acquisition and call the correct function. This seemed wasteful to me, so I used a function pointer within GetValue and at the top did something like.
unsigned short (* sensorreadfunc)(void); if (hwrev > someval) sensorreadfunc = sensor_read_new; else sensorreadfunc = sensor_read_old;
So long as the Linker can tell at Link time what calls what, you're safe; If the Linker can't tell for itself, but you can, you can be safe - but it's all on your head; If it's all entirely run-time dependent, you're doomed - you will either have to disable all overlaying, or make your functions reentrant (but if that's OK in your application - there's no problem!)
What a thread I have started ;-) I can see that others have had the same problem as I, but some don't seem to really understand the problem. Sentences like "If you had taken even a cursory look into the manual before posting here" only tells me that either the problem hasn't been understood or the solution hasn't been deducted... (I am probably going to hear for this... or killed...) It doesn't get better at all when I read: "Why, oh why, does so many insist on coding the '51 as if it was a "mini PC"?." Now, I wont go into the term "PC" and what it actually stands for, as it goes without saying. Let us just say that in colloquial English the term is used and even more mis-used... To cut things a little clearer. The problem is with the creation of the function calling tree (as I see it). Yes, there are some limitations to the use of function pointers (which the compiler/linker should be able to warn you about if you try to exceed the limits.) for the 8051, but I see no reason to why it should pose such a problem to use them. Let me explain. Right now the Keil compiler 'prefers' to handle all functions/subtrees called through a function pointer table as reentrant or not overlayed. If you either setting things work fine, but your RAM consumption EXPLODES even though it need not to. From one of the Keil notes we have: "When you use a function pointer, the linker cannot correctly create a call tree for your program" My question is why? Why, why, why doesn't the Keil compiler analyze all subtrees, even though called through a function pointer? It is the linker that looks up all cross-references and does the final allocation of data (overlaying). The linker knows whereto the function pointers point, so why doesn't it construct a function calling tree to optimize data overlaying? It has all the information it needs! That is the real question! If two subtrees do not connect to each other, then overlaying is obvious. Other compilers do this so why not Keil? Ok, I am compiling for a different target, but the problem and complexity is the same for all targets. That being a Z80, 8051, AVR, ARM or Pentium for that matter. It is just a matter of what the limitations are.
Why, why, why doesn't the Keil compiler analyze all subtrees, even though called through a function pointer? Because you're underestimating the scope of the problem. Static call tree analysis of a C program involving function pointers is, ultimately, an impossible mission, because of the Halting Problem --- you would have to be able to predict the complete behaviour of the program (and all its inputs, i.e. The World), to know for certain which possible call paths will actually be taken, and which won't. So at some point, the tools just have to give up trying. There might be some truth in your claim that Keil have given up a tad bit early. The "function pointer tables in code space" trick is IMHO a very useful extension of the realm of correctly analyzed usages of function pointers. It covers the majority of cases where function pointers provide enough benefit to outweigh the problems they create. OTOH the 8051 platform is quite severely limited itself, so enormous efforts spent on allowing limitless use of function pointers would arguably be a bad use of Keil's time and your money.
It doesn't get better at all when I read: "Why, oh why, does so many insist on coding the '51 as if it was a "mini PC"?." My question is why? Why, why, why doesn't the Keil compiler analyze all subtrees, even though called through a function pointer? Ok, I am compiling for a different target, but the problem and complexity is the same for all targets. That being a Z80, 8051, AVR, ARM or Pentium for that matter. It is just a matter of what the limitations are. OK, I'll rephrase, your question is "why does Keil not make the '51 behave in a way the architecture were never designed for" You are asking Keil to make software that changes the hardware. You can overcome your problem by switching to a less efficient common base compiler which use the traditional C method of transferring variables on the stack, instead of gaining magnitudes of efficiency by adapting to the unique architecture of the '51 by overlaying. By doing so you will lose some advantages, but your beloved function pointers will be possible. If you want to use the '51 do not complain that it is what it is. Erik