ARM Technical Support Knowledge Articles

FAR FUNCTION POINTERS FOR PHILIPS MX

Applies to: CX51 C Compiler

Answer


Information in this article applies to:


QUESTION

How do I create a function table with 24-bit function pointers on the Philips MX architecture?

The following code generates only 16-bit function pointers:

#define abs_fct1  0x901000
#define abs_fct2  0x902000

code void (code *fp_tab[]) (void) = { abs_fct1, abs_fct2 };

When I compile this code I get:

*** WARNING C196: mspace probably invalid

Is there a way to avoid this warning message?

I also need to generate ECALL instructions to reach this memory location. However, my application is using the ROM(LARGE) model and I want to avoid using the ROM(HUGE) model. Is there a way to get ECALL instructions when using ROM(LARGE)?

ANSWER

To get 3-byte function pointers, you need to use far pointers in your function pointer definition as shown in the following example. It is also possible to omit the 'far' memory type, since the compiler then defaults to 3-byte generic pointers which are identical to the 'far' pointers.

#define abs_fct1  ((void far *) 0x901000)
#define abs_fct2  ((void far *) 0x902000)

code void (far *fp_tab[]) (void) = { abs_fct1, abs_fct2 };

void main (void)  {
  fp_tab[0] ();
}

The program code above compiles without warnings and generates correct calls when using the ROM(HUGE) model.

To stay in the ROM(LARGE) model, call the following assembler interface function that generates the ECALL instruction:

PUBLIC _farcall

?PR?_farcall?farcall SEGMENT CODE
RSEG ?PR?_farcall?farcall

ACC  DATA 0E0H

_farcall:   MOV  A,R1
            PUSH ACC
            MOV  A,R2
            PUSH ACC
            MOV  A,R3
            PUSH ACC
            ERET         ; indirect ECALL

            RET
            END

Call the function farcall from your C code as follows:

extern void _farcall (void far *);

void main (void)  {
  farcall (fp_tab[0]);
}

If you need to call functions that get function parameters, you need to use the following method. The difference is in using a global variable to store the function pointer. This allows parameter passing via different function prototypes that are all using the same entry address in the assembly interface.

PUBLIC _fcall1, _fcall2, farfunc

?DT?_farcall SEGMENT DATA
RSEG ?DT?_farcall
farfunc:    DS   3

?PR?_fcall1?farcall SEGMENT CODE
RSEG ?PR?_fcall1?farcall

_fcall1:
_fcall2:    PUSH farfunc+2
            PUSH farfunc+1
            PUSH farfunc
            ERET         ; indirect ECALL

            RET
            END

Call the function farcall from your C code as follows:

extern void _fcall (int void far *);

extern char *fcall1 (long l1);
extern char *fcall1 (char *p, int i1);
char *p;


void main (void)  {
  farfunc = fp_tab[0];
  p = fcall1 (0x12345678);
  fcall2 (p, 0x8000);
}

MORE INFORMATION

Article last edited on: 2006-10-23 16:30:16

Rate this article

[Bad]
|
|
[Good]
Disagree? Move your mouse over the bar and click

Did you find this article helpful? Yes No

How can we improve this article?

Link to this article
Copyright © 2011 ARM Limited. All rights reserved. External (Open), Non-Confidential