Reputation: 604
I am trying to understand a software for a Tire Pressure Monitoring System but I know little about C language. In one of the header files there is these kind of definitions :
#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 really understand this trick of casting into other functions. Have you got any idea?
Upvotes: 3
Views: 94
Reputation: 180388
The macros you present are all ultimately defined in terms of a function (likely) or perhaps another macro (unlikely), u16fnDALLinkFmw()
. I'll suppose it is a function. You haven't quite understood what is going on here, however: the code in the macros' replacement texts are not casting that function; rather, they are casting its return value.
What seems to be going on here, therefore, is a variation on dynamic dispatch. The macros provide for looking up each desired function in a specified table, by offset / id, and since the looked-up functions for different IDs may have different signatures, the macros cast the returned function pointer to the correct-signature function pointer type.
You would use these something like this:
uint16_t argument = 1;
uint8_t result = TPMS_READ_VOLTAGE(&argument);
Upvotes: 0
Reputation: 721
Function pointer casting is a way to convert non-C firmware memory addresses into valid function declarations in C. This is normally done in embedded systems when you're accessing firmware functions (probably written in non-C languages / assembly) without the firmware's API exposed as a C API.
For example, in your case, the firmware provides a list of addresses to firmware functions in gu8Derivative
(a jump-table in the firmware code). Using u16fnDALLinkFmw(gu8Derivative, X)
you can get the jump-address of function 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 cast with an accompanying comment describing the API of the corresponding firmware function.
This NXP community post gives some more details about this exact firmware you're trying to use.
Upvotes: 5