簡體   English   中英

配置 SourceTrail 以接受帶有 @ 語法的嵌入式 c/c++ 頭文件

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM