Cast functions into function pointers in c program

I'm trying to understand the software for a tire pressure monitoring system, but I don't know much about the C language. One of the header files has definitions like this:

#define TPMS_RESET         gu16AddressToFn = u16fnDALLinkFmw(gu8Derivative, FN_RESET);\
                       ((void(*)(void))(gu16AddressToFn))

/* UINT8 TPMS_READ_VOLTAGE(UINT16 *u16UUMA) */
#define  TPMS_READ_VOLTAGE  ((UINT8(*)(UINT16*))(u16fnDALLinkFmw(gu8Derivative, FN_READ_VOLT)))

/* UINT8 TPMS_COMP_VOLTAGE(UINT8 *u8CompVoltage, *UINT16 u16UUMA) */
#define  TPMS_COMP_VOLTAGE  ((UINT8(*)(UINT8*, UINT16*))(u16fnDALLinkFmw(gu8Derivative, FN_COMP_V)))

/* UINT8 TPMS_READ_TEMPERATURE(UINT16 *u16UUMA) */
#define  TPMS_READ_TEMPERATURE  ((UINT8(*)(UINT16*))(u16fnDALLinkFmw(gu8Derivative, FN_READ_T)))

/* UINT8 TPMS_COMP_TEMPERATURE(UINT8 *u8Temp, UINT16 *u16UUMA) */
#define  TPMS_COMP_TEMPERATURE   ((UINT8(*)(UINT8*, UINT16*))(u16fnDALLinkFmw(gu8Derivative, FN_COMP_T)))

/* UINT8 TPMS_READ_PRESSURE(UINT16 *u16UUMA, UINT8 u8Avg) */
#define  TPMS_READ_PRESSURE    ((UINT8(*)(UINT16*, UINT8))(u16fnDALLinkFmw(gu8Derivative, FN_READ_P)))

/* UINT8 TPMS_COMP_PRESSURE(UINT16 *u16CompPressure, UINT16 *u16UUMA) */
#define  TPMS_COMP_PRESSURE    ((UINT8(*)(UINT16*, UINT16*))(u16fnDALLinkFmw(gu8Derivative, FN_COMP_P)))    

/* UINT8 TPMS_READ_ACCEL_X(UINT16 *u16UUMA, UINT8 u8Avg, UINT8 u8FiltSelect, UINT8 u8DynamicOffset) */
#define  TPMS_READ_ACCEL_X  ((UINT8(*)(UINT16*, UINT8, UINT8, UINT8))(u16fnDALLinkFmw(gu8Derivative, FN_READ_X)))

/* UINT8 TPMS_READ_ACCEL_Z(UINT16 *u16UUMA, UINT8 u8Avg, UINT8 u8FiltSelect, UINT8 u8DynamicOffset) */
#define  TPMS_READ_ACCEL_Z ((UINT8(*)(UINT16*, UINT8, UINT8, UINT8))(u16fnDALLinkFmw(gu8Derivative, FN_READ_Z)))

      

I don't understand this trick in other functions. Do you have an idea?

+3


source to share


2 answers


Casting function pointers is a way of converting non-C firmware memory addresses into valid function declarations in C. This is usually done in embedded systems when you access firmware functions (possibly written in languages ​​or non-C assembly) without the firmware API exposed like API C.

For example, in your case, the firmware provides a list of addresses for the firmware functions in gu8Derivative

(the table of transition to the firmware code). Using u16fnDALLinkFmw(gu8Derivative, X)

, you can get the function jump address X

in firmware, which is equivalent to a function pointer in C. Now, since the function declaration in firmware is not known directly in C, it is provided as a function pointer with an accompanying comment describing the API of the corresponding firmware function.



This NXP community post gives more details on this exact firmware you are trying to use.

+5


source


Macros that you represent is ultimately defined in terms of function (likely) or maybe another macro (unlikely) u16fnDALLinkFmw()

. I believe this is a function. However, you are not quite sure what is happening here: the code in the macro replacement texts does not perform this function; rather, they discard the return value.

What seems to be happening here is a variation on dynamic dispatch. The macros ensure that each desired function is searched in a specified table using offset / id, and since the lookup functions for different identifiers may have different signatures, the macros map the returned function pointer to a function pointer type of the correct signature.



You would use it something like this:

uint16_t argument = 1;
uint8_t  result = TPMS_READ_VOLTAGE(&argument);

      

0


source







All Articles