配置SourceTrail以使用@语法接受嵌入式c / c ++头文件

问题描述

我正在尝试使用Sourcetrail(https://www.sourcetrail.com/快速进入pic18系列微控制器的一些旧的嵌入式c / c ++源代码

导入硬件包含文件时出现错误,该文件使用奇异的方法定义可位寻址的硬件寄存器的硬件地址,例如const uniqueDates = [...new Set(sortbydate)]; console.log(uniqueDates); const arr1 = []; const arr2 = []; function FindDateObje() { for (let i = 0; i < sortbydate.length; i++) { if (sortbydate[i] == uniqueDates[0]) { arr1.push(data[i]); } else { arr2.push(data[i]); } } return [arr1,arr2]; } console.log(FindDateObje()); 中的以下内容

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感到困惑,并且期望只是一个分号。嵌入式系统的许多其他c / c ++编译器都使用该方法,因此我认为存在一个简单的修复方法

编辑:

首先,要弄清楚:@用于将volatile变量作为位或字节地址放置在内存映射中的特定位置。 (与8086 cpu具有内存和IO寻址系统的方式略有相似)。在这种情况下,MPLab c / c ++编译器附带了全局包含(用于数百个不同的微控制器)。为了便于分析,我可以复制全局包含文件,并在SourceTrail中设置到全局包含的其他路径-以便可以根据需要进行修改。我希望不要触摸项目文件,因为它们仍需要在原始设置中进行编译。

在尝试@Antti Haapala回答时,我发现需要考虑以下类型的用法

@ 0xF38

我找不到在任何地方定义的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 ,但这是一个特殊的结构,用于保存该位的位地址(而不是字节地址)。

解决方法

@在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当然并不完全相同,但具有足够接近的语义行为,也许对此有用。

,

因此,@令牌的目的是使变量位于特定地址?那么为什么没有像宏这样的变量通过硬编码指针访问内存呢?

#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"?