2. 位元組對齊及基礎資料型別定義
協議堆疊原始碼(碼云/github)port/include/port/datatype.h中根據目標系統架構(16位 or 32位)及所使用的編譯器定義基礎資料型別及位元組對齊方法,這個檔案中最重要的移植作業就是依據目標編譯器手冊定義位元組對齊方法,因為網路協議堆疊最關鍵的地方就是底層通訊報文結構必須位元組對齊,而不是通常情形下的預設四位元組對齊,
#define PACKED __attribute__((packed)) //* 預設提供了gcc編譯器的位元組對齊方法
#define PACKED_FIELD(x) PACKED x
#define PACKED_BEGIN
#define PACKED_END
協議堆疊原始碼提供了常用的gcc編譯器的位元組對齊方法,PACKED宏及PACKED_BEGIN/PACKET_END組合體宏通常用于結構體位元組對齊定義,二者選其一實作即可,PACKED_FIELD宏用于定義單個變數位元組對齊,注意,位元組對齊定義是整個協議堆疊能否正常運轉的關鍵,所以,必須確保該定義能正常作業,
協議堆疊原始碼提供了32位系統下的基礎資料型別定義樣例,具體移植時可參考該樣例進行調整:
//* 系統常用資料型別定義(不同的編譯器版本,各資料型別的位寬亦不同,請根據后面注釋選擇相同位寬的型別定義)
typedef unsigned long long ULONGLONG; //* 64位無符號長整型
typedef long long LONGLONG; //* 64位有符號長整型
typedef signed long LONG; //* 32位的有符號長整型
typedef unsigned long ULONG; //* 32位的無符號長整型
typedef float FLOAT; //* 32位的浮點型
typedef double DOUBLE; //* 64位的雙精度浮點型
typedef signed int INT; //* 32位的有符號整型
typedef unsigned int UINT; //* 32位的無符號整型
typedef signed short SHORT; //* 16位的有符號短整型
typedef unsigned short USHORT; //* 16位的無符號短整型
typedef char CHAR; //* 8位有符號位元組型
typedef unsigned char UCHAR; //* 8位無符號位元組型
typedef unsigned int in_addr_t; //* internet地址型別
其中in_addr_t比較特殊,用于socket編程,其為IPv4地址型別,其必須是無符號4位元組整型數,
3. OS適配層
對于 os 適配層,主要的移植作業就幾塊:1)提供多任務(執行緒)建立函式;2)提供系統級的秒級、毫秒級延時函式及運行時長統計函式;3)提供同步(互斥)鎖相關操作函式;4)提供信號量操作函式;5)提供一組臨界區保護也就是中斷禁止/使能函式,os 適配層的移植作業涉及 os_datatype.h、os_adapter.h、os_adapter.c 三個檔案,
3.1 os_datatype.h
這個檔案負責完成與目標作業系統相關的資料型別定義,主要就是互斥鎖、信號量、tty這三種資料型別的定義,互斥鎖用于執行緒同步,信號量用于執行緒間通訊,tty則用于ppp模塊,我們需要在這個檔案里定義能夠唯一的標識它們的訪問句柄供協議堆疊使用,
typedef INT HMUTEX; //* 執行緒互斥(同步)鎖句柄
#define INVALID_HMUTEX -1 //* 無效的執行緒互斥(同步)鎖句柄
#if SUPPORT_PPP
typedef INT HTTY; //* tty終端句柄
#define INVALID_HTTY -1 //* 無效的tty終端句柄
#endif
typedef INT HSEM; //* 信號量,適用與不同執行緒間通訊
#define INVALID_HSEM -1 //* 無效的信號量句柄
注意,上面給出的只是一般性定義,使用時請依據目標os的實際情形進行調整,另外,如果你的目標系統不需要ppp模塊,HTTY及INVALID_HTTY無須定義,
原始碼工程提供的os_datatype.h檔案為樣例檔案,基于協議堆疊的通用性考慮,樣例檔案提供的與os相關的資料型別定義存在冗余,除上述三種資料型別必須定義外,其它預留的型別如目標系統已提供,建議直接使用目標系統的定義,os_datatype.h檔案中的冗余定義直接注釋掉即可;如不存在,則直接使用樣例檔案中的通用定義即可,
3.2 os_adapter.h
協議堆疊業務邏輯的完成離不開os的支持,這個檔案的主要作用就是提供與os相關的介面函式宣告,然后在os_adapter.c中實作這些函式,所以,這個檔案中要調整的地方并不多,只有兩處,一個是協議堆疊內部作業執行緒控制塊:
typedef struct _STCB_PSTACKTHREAD_ { //* 協議堆疊內部作業執行緒控制塊,其用于執行緒建立
void(*pfunThread)(void *pvParam); //* 執行緒入口函式
void *pvParam; //* 傳遞給入口函式的用戶引數
} STCB_PSTACKTHREAD, *PSTCB_PSTACKTHREAD;
這個結構體與目標os高度相關,其用于保存協議堆疊內部作業執行緒串列,協議堆疊內部設計了一個one-shot定時器,該定時器被用于一些需要等待一小段時間才能進行后續處理或定期執行的業務模塊,這個定時器是以執行緒的方式實作的,協議堆疊的核心業務邏輯均與這個one-shot定時器執行緒有關,協議堆疊被目標系統加載時該執行緒將由os_thread_onpstack_start()函式自動啟動,這個函式要啟動的執行緒串列就被保存在STCB_PSTACKTHREAD結構體陣列中,這個陣列是一個靜態存盤時期的變數,變數名為lr_stcbaPStackThread,在os_adapter.c中定義,STCB_PSTACKTHREAD結構體需要定義哪些成員變數由目標os提供的執行緒啟動函式的入口引數決定,我們會將執行緒啟動用到的入口引數值定義在lr_stcbaPStackThread陣列中,然后由os_thread_onpstack_start()將這些引數值傳遞給執行緒啟動函式啟動相應作業執行緒,
另外一個地方是臨界區保護函式:
#define os_critical_init() //* 臨界區初始化
#define os_enter_critical() //* 進入臨界區(關中斷)
#define os_exit_critical() //* 退出臨界區(開中斷)
一般的os臨界區保護函式基本都是進入臨界區關中斷,離開臨界區開中斷,代碼非常簡單,所以這里直接給出了三個函式宏原型,移植時請依據目標系統具體情形添加對應的開、關中斷代碼即可,
3.3 os_adapter.c
這個檔案的核心作業就是編碼實作 os_adapter.h 檔案宣告的所有與 os 相關的介面函式,os_adapter.h中有這些函式的詳細功能說明,移植時按照說明實作具體功能即可,不再贅述,
//* 當前執行緒休眠指定的秒數,引數 unSecs 指定要休眠的秒數
OS_ADAPTER_EXT void os_sleep_secs(UINT unSecs);
//* 當前執行緒休眠指定的毫秒數,單位:毫秒
OS_ADAPTER_EXT void os_sleep_ms(UINT unMSecs);
//* 獲取系統啟動以來已運行的秒數(從 0 開始)
OS_ADAPTER_EXT UINT os_get_system_secs(void);
//* 執行緒同步鎖初始化,成功回傳同步鎖句柄,失敗則回傳INVALID_HMUTEX
OS_ADAPTER_EXT HMUTEX os_thread_mutex_init(void);
//* 執行緒同步區加鎖
OS_ADAPTER_EXT void os_thread_mutex_lock(HMUTEX hMutex);
//* 執行緒同步區解鎖
OS_ADAPTER_EXT void os_thread_mutex_unlock(HMUTEX hMutex);
//* 洗掉執行緒同步鎖,釋放該資源
OS_ADAPTER_EXT void os_thread_mutex_uninit(HMUTEX hMutex);
//* 信號量初始化,引數unInitVal指定初始信號量值, unCount指定信號量最大數值
OS_ADAPTER_EXT HSEM os_thread_sem_init(UINT unInitVal, UINT unCount);
//* 投遞信號量
OS_ADAPTER_EXT void os_thread_sem_post(HSEM hSem);
//* 等待信號量到達,引數unWaitSecs指定要等待的超時時間(單位為秒):
//* 0,一直等下去直至信號量到達,收到信號則回傳值為0,出錯則回傳值為-1;
//* 大于0,等待指定時間,如果指定時間內信號量到達,則回傳值為0,超時則回傳值為1,出錯則回傳值為-1
OS_ADAPTER_EXT INT os_thread_sem_pend(HSEM hSem, INT nWaitSecs);
//* 信號量去初始化,釋放該資源
OS_ADAPTER_EXT void os_thread_sem_uninit(HSEM hSem);
//* 啟動協議堆疊內部作業執行緒
OS_ADAPTER_EXT void os_thread_onpstack_start(void *pvParam);
#if SUPPORT_PPP
//* 打開 tty 設備,回傳 tty 設備句柄,引數 pszTTYName 指定要打開的 tty 設備的名稱
OS_ADAPTER_EXT HTTY os_open_tty(const CHAR *pszTTYName);
//* 關閉 tty 設備,引數 hTTY 為要關閉的 tty 設備的句柄
OS_ADAPTER_EXT void os_close_tty(HTTY hTTY);
//* 向 hTTY 指定的 tty 設備發送資料,回傳實際發送的資料長度
//* hTTY:設備句柄
//* pubData:指標,指向要發送的資料的指標
//* nDataLen:要發送的資料長度
OS_ADAPTER_EXT INT os_tty_send(HTTY hTTY, UCHAR *pubData, INT nDataLen);
//* 從引數 hTTY 指定的 tty 設備等待接收資料,阻塞型
//* hTTY:設備句柄
//* pubRcvBuf:指標,指向資料接識訓沖區的指標,用于保存收到的資料
//* nRcvBufLen:接識訓沖區的長度
//* nWaitSecs:等待的時長,單位:秒,0 一直等待;直至收到資料或報錯,大于 0,等待指定秒數;小于 0,不支持
OS_ADAPTER_EXT INT os_tty_recv(HTTY hTTY, UCHAR *pubRcvBuf, INT nRcvBufLen, INT nWaitSecs);
//* 復位 tty 設備,這個函式名稱體現了 4g 模塊作為 tty 設備的特殊性,其功能從本質上看就是一個 modem,modem 設備出現通訊
//* 故障時,最好的修復故障的方式就是直接復位,復位可以修復絕大部分的因軟體問題產生的故障
OS_ADAPTER_EXT void os_modem_reset(HTTY hTTY);
#endif
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/527963.html
標籤:其他
上一篇:表驅動法在STM32中的應用
