I'm porting some code onto the 9S12 for handling CANOpen Object Dictionaries. One of the fields is either a pointer to a rom constant, eerom location, a ram variable or a function. Depending on one of the other fields the application either reads from the ram, rom or calls the eerom code with the eerom address or calls the function.
I'm having trouble getting the compiler to generate what I want (rather than what I tell i.)
// First the function that returns nothing with no parameters.
void MyFunc(void);
typedef union _DICT_PTRS /* Pointers to objects */
{
unsigned char * pRam;
const unsigned char * pRom;
unsigned int EEAdr;
void __far * (* pFunc)(void);
}DICT_PTRS;
// Then the variable that will hold the data. The initializer flags a compiler error
// that the sizes don't match.
DICT_OBJECT_TEMPLATE _db_device[3] = {
{0x1000,0x00,CONST,4,(unsigned char *)&rCO_DevType},
{0x1001,0x00,RO,1,(unsigned char *)&uCO_DevErrReg},
{0x1002,0x00,RO,4,(unsigned char *)&uCO_DevManufacturerStatReg}
// {0x1005,0x00,FUNC | RW,6,(void __far *)&_CO_COMM_SYNC_COBIDAccessEvent}
};
// So for now I try to load the variable directly.
_db_device[0].p.pFunc = (void *)MyFunc;
(_db_device[0].p.pFunc)();
Breaking at the code where the function is assigned it's always the same. The wrong value is stored in the stucture and the call picks yet another location relative to the PC. I can work with the non function variables without any problems. I've tried the various permuations of __far and * etc. but the code generated is the same every time and the funtion is not called because what's stored in the structure isn't correct.
Solved! Go to Solution.
I finally solved it in a manner that fits in with the processor architecture. By making each a __far pointer the space is correctly reserved and the code generated sets up the page register correctly. A lot of the other attempts compiled but would not set up the page register or program counter. It pays here to understand the processor architecture.
Now with the two structures declared it's easy to create a ROM based table that has both values and or pointers to data.
Example below.
DICT_OBJECT_TEMPLATE _db_pdo1_rx_comm[] = {
{0x1400,0x00,CONST,1,(unsigned char *)&rMaxIndex1},
{0x1400,0x01,RW | FUNC,4,(void __far *)&CO_COMM_RPDO1_COBIDAccessEvent}
};
The function is called like this:
_db_device[1].p.pFunc();
Setting a breakpoint at the call shows how the processor does the load and indirect call to get to the actual function.
void CO_COMM_RPDO1_COBIDAccessEvent(void) {
...
}
Thanks for your feedback.
John Dammeyer
typedef union _DICT_PTRS /* Pointers to objects */
{
const unsigned char * __far pRom;
unsigned char * __far pRam;
unsigned int * __far EEAdr;
void (* pFunc)(void);
}DICT_PTRS;
// This is the scalar equivelant of a portion of the DICT_OBJ
typedef struct _DICTIONARY_OBJECT_TEMPLATE
{
unsigned int index;
unsigned char subindex;
unsigned char ctl;
unsigned int len;
DICT_PTRS p;
}DICT_OBJECT_TEMPLATE;
Initializer inits fisrt union member. It may be easier to use long int instead (long enough to hold largest union member), and convert data when writing/reading this field.
What did you meant here:
void __far * (* pFunc)(void);
Did you want to declare far pointer to void foo(void) or pointer to function, which returns far pointer to void? In Codewarrior we have this
void (*pFunc)(void); //pointer to void foo(void)
void (* far pFunc)(void); // pointer to banked void foo(void). Far is not
//necessary in banked and large memory models
void * far (*pFunc)(void); // pointer to function, which returns void* to far data
I finally solved it in a manner that fits in with the processor architecture. By making each a __far pointer the space is correctly reserved and the code generated sets up the page register correctly. A lot of the other attempts compiled but would not set up the page register or program counter. It pays here to understand the processor architecture.
Now with the two structures declared it's easy to create a ROM based table that has both values and or pointers to data.
Example below.
DICT_OBJECT_TEMPLATE _db_pdo1_rx_comm[] = {
{0x1400,0x00,CONST,1,(unsigned char *)&rMaxIndex1},
{0x1400,0x01,RW | FUNC,4,(void __far *)&CO_COMM_RPDO1_COBIDAccessEvent}
};
The function is called like this:
_db_device[1].p.pFunc();
Setting a breakpoint at the call shows how the processor does the load and indirect call to get to the actual function.
void CO_COMM_RPDO1_COBIDAccessEvent(void) {
...
}
Thanks for your feedback.
John Dammeyer
typedef union _DICT_PTRS /* Pointers to objects */
{
const unsigned char * __far pRom;
unsigned char * __far pRam;
unsigned int * __far EEAdr;
void (* pFunc)(void);
}DICT_PTRS;
// This is the scalar equivelant of a portion of the DICT_OBJ
typedef struct _DICTIONARY_OBJECT_TEMPLATE
{
unsigned int index;
unsigned char subindex;
unsigned char ctl;
unsigned int len;
DICT_PTRS p;
}DICT_OBJECT_TEMPLATE;