2017-03-31 62 views
3

我想了解一個輪胎壓力監測系統的軟件,但我對C語言知之甚少。 在頭文件中的一個有這幾樣定義:將函數強制轉換爲c程序中的函數指針

#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))) 

我不真正瞭解鑄造成其他功能的這一招。你有什麼想法嗎?

+0

什麼是'u16fnDALLinkFmw'?什麼是'gu8Derivative'? –

+0

這是一個很好的例子,使用'typedef'會導致更多可理解的代碼。 –

回答

5

函數指針鑄造是將非C固件內存地址轉換成C.有效的函數聲明這是在嵌入式系統中正常完成,當你訪問固件功能的方法(可能是寫在非C語言/彙編)沒有將固件的API作爲C API公開。

例如,在您的情況下,固件提供了gu8Derivative(固件代碼中的跳轉表)中固件功能的地址列表。使用u16fnDALLinkFmw(gu8Derivative, X)你可以得到跳地址固件的功能X這相當於在C函數指針現在,由於在固件的函數聲明不是在C直接知道,它是作爲一個函數指針投用提供描述相應固件功能的API的附帶評論。

This NXP community post提供有關您正在嘗試使用這個確切的固件的更多細節。

+0

在「gu16AddressToFn」中,gu8代表全局無符號8位? –

+0

'u16'和'u8'通常代表'unsigned' 16位或8位,但我不確定'g'在這裏的含義是什麼 - 'global'似乎是可能的,但是如果不仔細查看,碼。 – iVoid

0

你現在都最終在功能方面(可能)或者是另一個宏(不太可能),u16fnDALLinkFmw()定義的宏。我會認爲這是一個功能。然而,你並不完全明白這裏發生了什麼:宏代替文本中的代碼並不是,它的功能是;相反,他們正在鑄造它的返回值

什麼似乎是這裏發生了,因此,這是動態調度的變化。這些宏提供了通過offset/id在指定表中查找每個需要的函數,並且由於不同ID的查找函數可能具有不同的簽名,所以宏將返回的函數指針轉換爲正確簽名函數指針類型。

你可以使用這些東西是這樣的:

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