配置 SourceTrail 以接受带有 @ 语法的嵌入式 c/c++ 头文件
Configure SourceTrail to accept embedded c/c++ header files with @ syntax
我正在尝试使用 Sourcetrail (https://www.sourcetrail.com/) 快速进入一些旧的嵌入式 c/c++ pic18 系列微控制器的源代码。
我在导入硬件包含文件时遇到错误,它使用一种奇特的方法来定义位可寻址硬件寄存器的硬件地址,例如下面来自 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++ 嵌入式系统编译器都使用该方法,因此我假设存在一个简单的修复方法。
编辑:
首先,澄清一下:@用于将易失性变量放置在内存映射中的特定位置,可以是位地址也可以是字节地址。 (与 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()/g' *.c *.h
如果这个 @
语法在 vendor-provided 头文件中按原样使用,那就丢脸了。
所以,@
令牌的目的是让变量位于特定地址?那么为什么不使用像宏这样的变量来通过硬编码指针访问内存呢?
#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"?
对于 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
未定义时它将 pre-process 到:
extern volatile _Bool ABDEN1;
_Bool
当然与 __bit
不完全相同,但具有足够接近的语义行为,也许可用于此目的。
我正在尝试使用 Sourcetrail (https://www.sourcetrail.com/) 快速进入一些旧的嵌入式 c/c++ pic18 系列微控制器的源代码。
我在导入硬件包含文件时遇到错误,它使用一种奇特的方法来定义位可寻址硬件寄存器的硬件地址,例如下面来自 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++ 嵌入式系统编译器都使用该方法,因此我假设存在一个简单的修复方法。
编辑:
首先,澄清一下:@用于将易失性变量放置在内存映射中的特定位置,可以是位地址也可以是字节地址。 (与 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()/g' *.c *.h
如果这个 @
语法在 vendor-provided 头文件中按原样使用,那就丢脸了。
所以,@
令牌的目的是让变量位于特定地址?那么为什么不使用像宏这样的变量来通过硬编码指针访问内存呢?
#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"?
对于 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
未定义时它将 pre-process 到:
extern volatile _Bool ABDEN1;
_Bool
当然与 __bit
不完全相同,但具有足够接近的语义行为,也许可用于此目的。