Using array of functions

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Using array of functions

4,930 Views
CJH
Contributor I
I've created a function pointer array in FLASH as follows:
 
#pragma CONST_SEG ROM_TABLES MyConst
typedef void (* FunctionType)(void);
const FunctionType jumptable[64] = {
  mstate_00,  mstate_01,  mstate_02, ...  mstate_63 };  // states 00-63
I'm calling the funcition as follows:
 
   (*jumptable[mstate])(); 
 
and the compiler is generating:
 
 4349:     (*jumptable[mstate])(); // got to the appropriate subroutine
 01c0 be00     [3]             LDX   mstate
 01c2 58       [1]             LSLX 
 01c3 8c       [1]             CLRH 
 01c4 e600     [3]             LDA   @jumptable,X
 01c6 ee01     [3]             LDX   @jumptable:1,X
 01c8 87       [2]             PSHA 
 01c9 8a       [2]             PULH 
 01ca fd       [4]             JSR   ,X
 
This causes a link error because it's generating the indexed 8-bit offset loads (e600 & ee00) rather than the indexed 16-bit offset loads (d60000de0000) I need.  How do I convince the compiler it must treat jumptable as a "far" entity?  I've tried adding the "far" qualifier without success.
 
Thanks,
Carlos
Labels (1)
0 Kudos
Reply
9 Replies

2,150 Views
Geezer
Contributor I
How did you declare all the 'mstate_xx' stuff?

You should have something like 64 functions of the form 'void mstate_xx(void) {}', right? Which confuses me... why did your program even compile, the heck with the linking! A statement in which *jumptable[mstate_xx] appears should have croaked, you're feeding a pointer into an index [] field. Unless you have all kinds of warnings/errors disabled...

Al
0 Kudos
Reply

2,150 Views
CJH
Contributor I
Al,
 
Yes, the functions are declared like:
 
void mstate_00(void) { ... }
 
I think you're mistaking the "mstate_xx()" functions with a byte variable "mstate" which I'm using in the function call:
  ( * jumptable [ mstate ]) ( );
Carlos
0 Kudos
Reply

2,150 Views
Geezer
Contributor I
Absolutely right, I got your names confused. Sorry.

VOID x_0(void);
VOID x_1(void);
VOID x_2(void);

#pragma CONST_SEG ROM
typedef void (* FunctionType)(void);
const FunctionType jumptable[64] = {
x_0, x_1, x_2}; // states 00-63

VOID x_0(void)
{ ERROR_NUM = 0;
}
VOID x_1(void)
{ERROR_NUM = 1;
}
VOID x_2(void)
{ERROR_NUM = 2;
}
//*****************************************************************************
//*****************************************************************************
VOID main(VOID) {

(*jumptable[1])();

GENERATES THE FOLLOWING ASM (CW5, GT32A):

58: (*jumptable[1])();
0009 320002 [5] LDHX jumptable:2
000c fd [5] JSR ,X

It sims just fine. Don't know what else to say.
0 Kudos
Reply

2,150 Views
CompilerGuru
NXP Employee
NXP Employee
Which memory model are you using?
In the tiny, far (this includes flash) objects have to be explicitly declared as such as the default access size is direct.
This is done by using the __FAR_SEG qualifier in the #pragma

#pragma CONST_SEG __FAR_SEG ROM
...

Daniel
0 Kudos
Reply

2,150 Views
CJH
Contributor I
Daniel,
 
Yes, I'm using the TINY model, and I've added the __FAR_SEG qualifier to my #pragma:
 
#pragma CONST_SEG __FAR_SEG ROM_TABLES MyConst
I'm still getting the result:
 
 01c0 be00     [3]             LDX   mstate
 01c2 58       [1]             LSLX 
 01c3 8c       [1]             CLRH 
 01c4 e600     [3]             LDA   @jumptable,X
 01c6 ee01     [3]             LDX   @jumptable:1,X
 01c8 87       [2]             PSHA 
 01c9 8a       [2]             PULH 
 01ca fd       [4]             JSR   ,X
Thanks,
Carlos
0 Kudos
Reply

2,150 Views
CompilerGuru
NXP Employee
NXP Employee
Strange, it works for me.

ANSI-C/cC++ Compiler for HC08 V-5.0.21 Build 6124, May  5 2006

    1:  #include "hidef.h"
    2:  #include "derivative.h"
    3: 
    4:  char index;
    5:  #pragma CONST_SEG __FAR_SEG ROM
    6:  typedef void (* FunctionType)(void);
    7:  const FunctionType jumptable[64];
    8: 
    9:  void main(void) {

Function: main
Source  : main.c
Options : ... -Mt

   10:    jumptable[index]();
  0000 be00     [3]             LDX   index
  0002 58       [1]             LSLX 
  0003 8c       [1]             CLRH 
  0004 d60000   [4]             LDA   @jumptable,X
  0007 de0001   [4]             LDX   @jumptable:1,X
  000a 87       [2]             PSHA 
  000b 8a       [2]             PULH 
  000c fc       [2]             JMP   ,X
   11:  }
   12: 
0 Kudos
Reply

2,150 Views
CompilerGuru
NXP Employee
NXP Employee
#pragma CONST_SEG __FAR_SEG ROM_TABLES MyConst


What's ROM_TABLES? Maybe some preprocessor magic, maybe some bug in your code.
Check that you don't get any warnings about illegal pragmas.

Daniel
0 Kudos
Reply

2,150 Views
CJH
Contributor I
Daniel,
 
You're right, I was getting an error for the #pragma - it scrolled off the window and I hadn't noticed it.
 
I've changed it to
 
#pragma CONST_SEG __FAR_SEG MyConst
and now it no longer generates an error, and it also works right!  I get:
 
 4349:     (*jumptable[mstate])(); // got to the appropriate subroutine
 01c0 be00     [3]             LDX   mstate
 01c2 58       [1]             LSLX 
 01c3 8c       [1]             CLRH 
 01c4 d60000   [4]             LDA   @jumptable,X
 01c7 de0001   [4]             LDX   @jumptable:1,X
 01ca 87       [2]             PSHA 
 01cb 8a       [2]             PULH 
 01cc fd       [4]             JSR   ,X
ROM_TABLES is a "SECTION" in my .PRM file that I've defined to keep the data areas separate from the code, but that name did not belong in the #pragma.  I have a line in the .PRM that says:
 
PLACEMENT
   MyConst                             INTO  ROM_TABLES;
 
Guess I was confused on the syntax of the #pragma.
 
Thanks to all for the help!
 
Carlos
0 Kudos
Reply

2,150 Views
CJH
Contributor I
OK - I figured out the difference.
 
I copied your code and compiled and got
 
  30:  (*jumptable[1])();
 0003 5502     [4]             LDHX  jumptable:2
 0005 fd       [4]             JSR   ,X

 
Apparently, the difference is that I have selected the TINY memory model, while you had the SMALL model.  When I change to SMALL, I do get
 
  37:  (*jumptable[1])();
 0012 ce0002   [4]             LDX   jumptable:2
 0015 89       [2]             PSHX 
 0016 8a       [2]             PULH 
 0017 ce0003   [4]             LDX   jumptable:3
 001a fd       [4]             JSR   ,X
which is what I want.
 
This is what I find in the help file under "TINY memory model":
 

In the TINY memory model, all data including stack must fit into the zero page. Data pointers are assumed to have 8-bit addresses if not explicitly specified with the keyword __far. The code address space is still 64 kB and function pointers are still 16-bit large. The TINY memory model is selected with the -Mt compiler option.

Can't I force the 16-bit address for array jumptable?  I haven't figured out how, but I would think I should be able to...
 
Otherwise, I'll have to figure out what other effects changing to "SMALL" would have on the rest of my code.
 
Carlos
 
0 Kudos
Reply