[英]Configure SourceTrail to accept embedded c/c++ header files with @ syntax
我正在嘗試使用 Sourcetrail ( https://www.sourcetrail.com/ ) 快速進入 pic18 系列微控制器的一些舊的嵌入式 c/c++ 源代碼。
導入硬件包含文件時出現錯誤,該文件使用一種奇特的方法來定義位可尋址硬件寄存器的硬件地址,例如以下來自pic18f26k22.h
。
typedef union {
struct {
unsigned ANSA0 :1;
unsigned ANSA1 :1;
unsigned ANSA2 :1;
unsigned ANSA3 :1;
unsigned :1;
unsigned ANSA5 :1;
};
} ANSELAbits_t;
extern volatile ANSELAbits_t ANSELAbits @ 0xF38;
正如您可能猜到的那樣,SourceTrail 被@ 0xF38
部分弄糊塗了,只需要一個分號。 該方法被許多其他用於嵌入式系統的 c/c++ 編譯器使用,因此我假設存在一個簡單的修復程序。
編輯:
首先,澄清一下:@ 用於將 volatile 變量放置在內存映射中的特定位置,可以是位地址,也可以是字節地址。 (有點類似於 8086 CPU 的內存和 IO 尋址系統)。 它用於全局包含(用於數百個不同的微控制器),在這種情況下,它與 MPLab c/c++ 編譯器一起提供。 出於分析目的,我可以復制全局包含文件,並在 SourceTrail 中設置全局包含的不同路徑 - 因此可以根據需要對其進行修改。 我不想接觸項目文件,因為它們仍然需要在原始設置中編譯。
在嘗試@Antti Haapala 回答時,我發現需要考慮以下使用類型:
extern volatile unsigned char BAUDCON1 @ 0xFB8;
#ifndef BANKMASK
#define BANKMASK(addr) ((addr)&0FFh)
#endif
extern volatile __bit ABDEN1 @ (((unsigned) &BAUDCON1)*8) + 0;
#define ABDEN1_bit BANKMASK(BAUDCON1), 0
我在任何地方都找不到__bit
定義,但它是一個特殊的結構,用於保存位的位地址(不是字節地址)。
@ 不是 C 中的有效標記,因此您也不能將其用作宏標識符。 最簡單的解決方案是用宏處理@地址,即
#ifdef somethingsomething
#define AT(address) @ address
#else
#define AT(address)
#endif
extern volatile ANSELAbits_t ANSELAbits AT(0xF38);
第一個定義應由僅在目標上使用的宏保護。 使用簡單的 Perl 腳本進行更改應該很容易,例如
perl -pi -e 's/@\s*([0-9a-fA-FxX]+)/AT($1)/g' *.c *.h
如果在供應商提供的頭文件中按原樣使用此@
語法,那么對它們感到羞恥。
對於 Microchip C18 編譯器:
#if defined MCHP_C18
#define AT(address) @ address
#else
#define AT(address)
#define __bit _Bool
#endif
然后如果重寫:
extern volatile __bit ABDEN1 @ (((unsigned) &BAUDCON1)*8) + 0;
作為
extern volatile __bit ABDEN1 AT((((unsigned) &BAUDCON1)*8) + 0);
然后當MCHP_C18
未定義時,它將預處理為:
extern volatile _Bool ABDEN1;
_Bool
當然與__bit
不__bit
,但具有足夠接近的語義行為,可能用於此目的。
那么, @
令牌的目的是讓變量位於特定地址? 那么為什么不用像宏這樣的變量通過硬編碼指針訪問內存呢?
#define ANSELAbits (* (ANSELAbits_t *) 0xF38)
或者,如果您不介意在源代碼中添加*
運算符,則可以去掉宏:
static ANSELAbits_t * const ANSELAbits_ptr = (ANSELAbits_t *) 0xF38;
在有人抱怨UB之前。 是的,將整數轉換為指針是不可移植的,但應該適用於讀取特定內存地址有意義的大多數架構。
我個人更喜歡指針變體。 *
和->
運算符明確表明您正在訪問特定內存位置的內容:
// This is in my humble opinion clearer code:
ANSELAbits_ptr->ANSA0 = 1;
// or
(* ANSELAbits_ptr).ANSA0 = 1;
// ...rather than this:
ANSELAbits.ANSA0 = 1; // How do we know that ANSELAbits is "Magic"?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.