Keil Logo

In a RAM Variable

When a function pointer is assigned to a global variable that is stored in RAM (DATA, IDATA, PDATA, or XDATA), the call tree generated by the linker is inaccurate. For example, given the following example program:

int direct_func (int a, int b, int c)
{
volatile int total = a+b+c;
return (total);
}

int indirect_func (int a, int b, int c)
{
volatile int total = a+b+c;
return (total);
}

int (*fp) (int, int, int) = indirect_func;

int caller (void)
{
int retval;

retval = direct_func(4,5,6);
retval += (*fp) (1,2,3);
return (retval);
}

void main (void)
{
int value;

value = caller();

while (1);
}

The correct Call Tree is illustrated by the following flow chart.

Correct Call Tree

However, indirect_func is referenced only by the initialization code (initseg) that assigns values to variables (fp, the function pointer, in this case). It is not referenced in the caller function. Therefore, the linker generates the following Call Tree and Overlay Map.

Incorrect Call Tree

FUNCTION/MODULE                       BIT_GROUP   DATA_GROUP
--> CALLED FUNCTION/MODULE           START  STOP  START  STOP
=============================================================
?C_C251STARTUP                        ----- -----  ----- -----
  +--> ?PR?MAIN?MAIN
  +--> ?C_INITSEG

MAIN/MAIN                            ----- -----  0008H 0009H
  +--> ?PR?CALLER?MAIN

CALLER/MAIN                          ----- -----  000AH 000BH
  +--> ?PR?_DIRECT_FUNC?MAIN

_DIRECT_FUNC/MAIN                    ----- -----  000CH 000DH

?C_INITSEG                           ----- -----  ----- -----
  +--> ?PR?_INDIRECT_FUNC?MAIN

_INDIRECT_FUNC/MAIN                  ----- -----  0008H 0009H

The linker call tree must be adjusted by removing the reference from initseg to indirect_func and adding a reference from caller to indirect_func using the following overlay command:

... OVERLAY(?C_INITSEG ~ indirect_func, caller ! indirect_func) ...

After adjusting the call tree, the Overlay Map appears as follows:

FUNCTION/MODULE                       BIT_GROUP   DATA_GROUP
--> CALLED FUNCTION/MODULE           START  STOP  START  STOP
=============================================================
?C_C251STARTUP                        ----- -----  ----- -----
  +--> ?PR?MAIN?MAIN
  +--> ?C_INITSEG

MAIN/MAIN                            ----- -----  0008H 0009H
  +--> ?PR?CALLER?MAIN

CALLER/MAIN                          ----- -----  000AH 000BH
  +--> ?PR?_DIRECT_FUNC?MAIN
  +--> ?PR?_INDIRECT_FUNC?MAIN

_DIRECT_FUNC/MAIN                    ----- -----  000CH 000DH

_INDIRECT_FUNC/MAIN                  ----- -----  000CH 000DH

?C_INITSEG                           ----- -----  ----- -----

Note

  • Since the fp variable is assigned its value in its definition, the initialization references the indirect_func function. However, if fp was initialized by code in the main function, there would be a reference from the main function to the indirect_func function.
  • In this example, there is a reference from the initialization code to indirect_func only because the fp variable is actually initialized. This is going to be the case with all function pointers stored in RAM. If the memory type of fp is changed to code (so that the pointer is stored in ROM), there would be no reference from the initialization code. Instead, there would be a reference from the code segment of the source file (?CO?filename). There are subtle differences to note when a function pointer is stored In a ROM Variable.
  Arm logo
Important information

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies.

Change Settings

Privacy Policy Update

Arm’s Privacy Policy has been updated. By continuing to use our site, you consent to Arm’s Privacy Policy. Please review our Privacy Policy to learn more about our collection, use and transfers
of your data.