1
\$\begingroup\$

My C code has an ISR, where a decision has to be made to execute a particular function "A". Now I know that its not good to run a function in an ISR. But in this case of my application, I do not see another way out. After calling the function "A", I noticed a sudden jump in the Data Consumed size and the sudden WARNING L15 explained in KEIL EXPLANATION OF WARNING.

I am certain that function "A" is not executed in a reentrant fashion, but it sure uses up physical memory; both function "A" as well as functions it calls. (This I believe refers to the variables declared in the functions).

Firstly, is there any way I can work around avoiding that shoot in data memory space?

Secondly, I want to apply the method 2 as shown in the keil explanation. But I do not know how & where exactly to insert the OVERLAY directive in my code. At initialization? At function Declaration? Before Function definition? Where exactly?

WARNING EXAMPLE in my Code

*** WARNING L15: MULTIPLE CALL TO FUNCTION
NAME:    _IECLOC_FUN/DATA_ACCESS
CALLER1: ?C_C51STARTUP
CALLER2: TIMER_ISR/TIMER

WARNING MEANING

Corrections, suggestions, Code examples and links will be appreciated. I hope this question is clear.

Thanks all.

\$\endgroup\$
2
\$\begingroup\$

Please understand that with Keil on 8051 cores that the subroutine's local variables and any entry arguments beyond what would fit into registers the compiler allocates RAM for the placement of these. The linker then has a complicated job that it does to analyze the full calling tree structure of your program and optimize the pool of memory allocated for these purposes so as to minimize the amount of RAM required. This minimization uses mutual exclusion between code calling sequences to determine what parts of the memory pool can be shared between code paths that do not overlap in the execution flow.

When you inject an ISR call into the mix of the code calling tree the linker cannot determine from what point the interrupt may come into play. It could come at any time during any one of the mutual exclusion paths that the linker found in the normal mainline code. This means that the linker has to pull the subroutine out of the shared usage pool and allocate data space specifically for the subroutine local variables and maybe even some of its entry arguments. Without this the shared memory pools from other mutually exclusive code execution paths would get polluted and the program would crash in blazing glory.

The challenge when coding on an 8051 core is try to steer away from designs that use lots of local variables, have lots of entry arguments and have calling contexts that are shared between mainline code and interrupts. You really have to limit the freedoms that you get with other architectures that have a stack that gets used for subroutine argument passing and local variables. Keil chose to not implement everything on the stack and thus produced a tool set that offers performance and optimization that is first class in the industry for 8051 architecture. And for that reason it is important to adapt a coding style that plays into the Keil scheme.

In your case I really recommend that you reconsider your determination that this subroutine has to be called from both the mainline context and the interrupt context. Try to find a design technique that avoids this and your life will be a lot simpler.

\$\endgroup\$
  • \$\begingroup\$ @Micheal Karas..........any design technique suggestions? \$\endgroup\$ – Paul A. Apr 11 '13 at 11:41
  • \$\begingroup\$ I gave them already. Stop calling functions from interrupts. If you absolutely cannot do that then minimize or better eliminate local variables in subroutines called from the interrupt context. Minimize or better yet get rid of calling arguments in routines called from interrupt context. Make the called subroutine flat in that it does not call other subroutines or library functions. \$\endgroup\$ – Michael Karas Apr 11 '13 at 11:52
1
\$\begingroup\$

The OVERLAY directive is a command to the linker, and it does not go into your source code at all. You can place directives on the BL51 command line, but for anything nontrivial, it is usually better to put then into a separate linker command file and pass that file to the linker using the BL51 @<commandfile> syntax on the command line.

See the command-line reference for BL51 here.

\$\endgroup\$
  • \$\begingroup\$ hum! This is going deeper than I thought! \$\endgroup\$ – Paul A. Apr 11 '13 at 11:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.