We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
Hi,all
I have succeeded in runing ucos (v2.52) in the keil simulator environment, and still confused about the reentrant functions though I searched it here. reentrant stack is also called simulator stack,right? My OS is xp sp2. Keil is C51.EXE V8.06 My project is complied in large mode.
And the quetions are:
1, Does every reentrant function have Its own reentrant stack? Are there the same number of ?C_XBP as the reentrant functions.
2, For all the reentrant functions, Arguments and local variable are stored in the simulator stack,right? If all the functions in my project are reentrant. is there no hardware stack wanted? if not what is it for?
3,How can I know each or the total simulator stack size ?Can I get it from the map file? or other ways.
Thanks
I can help you with #2 The Hardware stack for Keil C51 gets return address only. They do not push parameters on the stack.
Neil Kurzman, Thanks for your attentions.
Well I got this point, The hardware stack is only for the return address,yeah,I think so. In fact there'll be a lot of internal ram left. right?
Really hope someone can help me the others.
1. There is only one stack and one ?C_XBP shared by all the reentrant functions.
2a. If the reentrant functions need to spill parameters, temporaries, and/or locals into the stack, they will use the software stack. It is possible to have a reentrant function that happens not to need stack (that is, all the parameters fit into registers).
2b. The hardware stack (core SP register pointing into idata) is always used for return addresses, and for very little else. (I've seen a few bits of code that will push a temporary value.) Parameters/locals/temps are either assigned fixed memory addresses by the call tree overlay analysis for non-reentrant, or else copied to the stack dynamically for reentrant functions.
3. The linker outputs an HTML document that shows the stack depth. For reentrant functions, you'll have to know how many times the function could potentially be called. (Potentially this is once per context, unless the reentrant function is also recursive, in which case only you, the programmer, can really know the maximum depth of recursion at run time.)
The traditional way to measure stack usage is to fill the stack area with a known pattern, run your system through its test suite, and then examine the stack to see where the pattern remains. That is, you can see the part of the stack that was overwritten in use. If your test suite actually forces the code down its maximum depth path, this will give you the right answer.
Thanks Drew Davis very much. Your answers really help me a lot.I believe that I understand what hardware stack is used for and something about the total reentrant stack size. but a little confused about how reentrant stack works, Let me clarify the things.
1: There are only one hardware stack and one fixed idata_space for ?C_XBP which is depend on the complie tools(KeilC). Yes,Actually, I think what ?C_XBP stands for is different by the kinds of reentrant functions,am I right? pls see the following examples. The Xdata area is from 0x00000 to 0x7ffff.
void FuncA(void) reentrant { unsigned char x[10]; }
void FuncB(void) reentrant { unsigned char x[10]; }
---- ----------------- 0x7ffff Top of reentrant stack | | | | ---- --------- A | | AB is the reentrant stack size of FuncA | | ---- --------- B .... .... ---- --------- C | | CD is the reentrant stack size of FuncB | | ---- ----------D | | .... | | ---- ---------C' | | C'D' is another reentrant stack of FuncB. Bcs | | FuncB is called by another function. ---- ---------D' | |
------------------------- 0x00000
When FuncA is supposed to run, the ?C_XBP will be the value of B ( ?C_XBP = B)Which is done by KeilC. While It turns to be FuncB, the ?C_XBP will be the value of D. And How many AB ,CD are there? They are all depends the times the function could be called. Like C'D'.
2,The tranditional ways to caculate the hardware stack size (SP register pointing into) is useful. But It's not good for simulator stack. Bcs I found It's not a continuous changed space like hardware stack. what's more It looks like "random" changed. Is it possible for me to count it from the top to the end?
Thanks for all your patience again!
The different reentrant functions doesn't have their own pre-allocated stack areas. When a reentrant function is called, it will crow the software stack from it's current position. When it returns, it will release this space, so a completely different reentrant function may use the same space.
If two reentrant functions are called at the same time - or one reentrant function is recursively called, the sw stack will contain the data for all these calls - in the orther that they where called. They will always have to end in the reverse order, so when they return, the stack will shrink correspondingly.
Per Westermark The different reentrant functions doesn't have their own pre-allocated stack areas. When a reentrant function is called, it will crow the software stack from it's current position. When it returns, it will release this space, so a completely different reentrant function may use the same space.
Hi,thanks very much!
I think I made a mistake. The reentrant stack belongs to the call-chain, not to a single function. right?
And, In my project with ucos(v2.52) as the os in large mode. For the concept of mutiple tasks, There will never be a chance for "return". Then all the reentrant functions including the reentrant task should share the same simulator stack (0x7ffff~~)? That's why It only save the hardware stack and the ?C_XBP when context switch ocurred. When It's one task's turn again, It restore the ?C_XBP from the user stack, Then every things go well.
If There's some things wrong pls let me know. Thanks all you kind-heart guys!
When running with a preemptive OS, the different tasks need individual stacks, since one task can be preempted in the middle of a call chain.
When running without a OS, individual calls to reentrant functions will just add stack frames on the stack - each popped when the function returns.
Which is why the architecture of the '51 does not in any way lend itself to the use of an OS. If you believe (for a '51 project is must be 'belief' not 'fact') you need an OS, switch to a processor capable of running an OS without jumping through hoops. Today, you can get an ARM for much less than "an arm and a leg" - sorry, could not help that one - less than $5 so, if you have a legitimate NEED for an OS switch to the ARM.
In the olden days, when the king of diamonds were still just a jack, the price differential between a '51 and something else was so dramatic that jumping through hoops to 'make do' with a '51 might have been justified, but today, use the wonderful '51 for what it is wonderful at which is NOT running an OS.
Erik
The software stack for reentrant functions works just like you would expect a "normal" stack for "normal" C to work. That is, there's a stack pointer, and values get pushed and popped on the stack as the call chain goes up and down. It's only called a "software stack" or "simulated stack" because the 8051 doesn't have much in the way of pointer registers, and Keil wants a clear distinction between this stack and the "hardware" stack that uses the SP register. The stack pointer is a variable, not a register, which means there's more code to manipulate that pointer than is usual with other architectures.
Different memory models change the names slightly.
As was mentioned, every task will need its own stack (as is usual with a preemptive OS). The task-switching code for your OS will need to be aware of the software stack implementation, and will have to store ?C_XBP in the task control block and change it out on task switches as it does with all the other registers. Since the stack implementation is unique to Keil, your uCOS code may or may not already have support for this. (Someone may have done the Keil-specific port already; if not, you get to learn about the internals of the uCOS kernal.)
Thanks all you guys!
I think it's very clearly about this point. you all gave me a great help. thanks.
About the OS and C51,I start a new topic about this, http://www.keil.com/forum/docs/thread10068.asp#msg47684. It's "Why It is not recommended porting a OS to C51?", if you have some idea and It's convenient for you,pls, Do me a favor to let me know, I'll greatly appreciate it.