首页 > 解决方案 > 在老式嵌入式 c/c++ 代码上启用现代代码分析工具

问题描述

如何在老式嵌入式 c/c++ 源代码上使用现代代码分析工具,例如SourceTrail,最初用于 Hi-Tech C、PIC C、IAR Workbench 等编译器,用于许多微控制器,不仅限于 PIC、PIC16、和 Microchip 的 PIC18 系列。

为了支持微型微控制器的有限架构,嵌入式编译器的供应商不得不提出对 c/c++ 语言的扩展,这些扩展已经(或尚未)在 c 语言规范中。

这会导致微控制器特定的头文件包含以下内容:

// Register: ANSELA
extern volatile unsigned char           ANSELA              @ 0xF38;
#ifndef _LIB_BUILD
asm("ANSELA equ 0F38h");
#endif

typedef union {
    struct {
        unsigned ANSB0                  :1;
        unsigned ANSB1                  :1;
        unsigned ANSB2                  :1;
        unsigned ANSB3                  :1;
        unsigned ANSB4                  :1;
        unsigned ANSB5                  :1;
    };
} ANSELBbits_t;
extern volatile ANSELBbits_t ANSELBbits @ 0xF39;

extern volatile unsigned short long     TBLPTR              @ 0xFF6;

extern volatile __bit                   ABDEN1              @ (((unsigned) &BAUDCON1)*8) + 0;

和代码文件包括这样的东西:

void interrupt high_priority InterruptVectorHigh(void) 
{
}

void interrupt low_priority InterruptVectorLow(void)
{
}

用现代工具支持这个源代码的最简单方法是什么,同时确保源代码仍然可以与原始编译器一起使用?

编辑:

下面给出了答案。

标签: c++cembeddedmplab

解决方案


下面的修复将使任何支持 C18 或 C2x 规范的编译器都能理解 c 代码。我(还)没有机会用 C++ 进行测试,所以它们可能不完全符合任何 C++ 规范。

感谢@Antti Haapala、@Clifford 和@anastaciu 等人 在这里这里回答了我的相关问题并启用了这个更完整的答案。

short long类型_

首先,24 位short long类型是个问题,因为在 c 规范中不存在等价物,而且该类型的两个字不能用#define. 起初,我使用 Perl 将字符串简单地修改short longlong所有特定于供应商的头文件,如下所示:

perl -pi -e "s/(short long)/long/g" .h

注意,对于 Windows 上的 Microchip MPLAB CX8 编译器,头文件位于以下文件夹和子文件夹中:c:\Program Files (x86)\Microchip\xc8\v1.33\include

但后来我意识到该short类型永远不会单独使用,所以我决定简单地short使用#define short. 请注意,这会影响任何使用short,所以我在这个答案中留下了这两种方法。

用@定义的寄存器位和字节地址

@-signs 是一个特定的问题,因为它们无法使用 重新定义#define,所以 perl 再次进行救援,这次使用两次传递来解决两种不同的语法:

perl -pi -e "s/@\s*([0-9a-fA-FxX]+)/AT($1)/g" .h
perl -pi -e "s/[@] ?+([^;]*)/AT($1)/g" .h

这些本质上包装了@in之后的任何内容AT(),允许正常的定义对其进行操作。

额外的关键字

最后一点是在编译器供应商提供的每个头文件中插入一个宏头文件。我最终得到了以下宏标头:

// Hack to allow SourceTrail to be used on this source
#if defined __XC8
  #define AT(address) @ address
#else
  #define AT(address)
  #define __bit _Bool
  #define asm(assembly)
  #define interrupt
  #define short
  #define high_priority
  #define low_priority
#endif

可以看出,除了 MPLAB XC8 编译器使用头文件时,任何非标准的内容都会被简单地删除。唯一的例外是__bit类型,它被重新定义为_Bool类型 - 它似乎工作。

作为在 Windows 上运行的批处理脚本的完整修复

当我在 Windows 上运行所有这些时,Perl 单行程序并不像在 Linux 上那样真正工作,所以为了处理每个头文件,我不得不将 Perl 命令包装在一个批处理 for 循环中,这很慢。为了弥补这一点,我将所有内容合并到一个名为 的批处理中fix.cmd,该批处理位于包含文件夹中(请参见上面的路径):

:: Fix to allow SourceTrail to analyze MPLAB CX8 source code.
@echo off
setlocal enabledelayedexpansion

:: Run in the folder where the script exists.
pushd "%~dp0"

echo:Fixing MPLAB global include files to be used by SourceTrail and other analysis tools.

:: Loop each directory recrusively
set DirCounter=0
set FileCounter=0
for /r %%d in (.) do (
    set /A DirCounter=DirCounter+1
    pushd %%d
    echo | set /p=Processing:
    cd
    
    for %%f in (*.h) do (
        set /A FileCounter=FileCounter+1
        set /A ModValue=FileCounter%%25
        if !ModValue!==0 ( echo | set /p=* )
        call :ProcessFile %%f
    )
    
    popd
    echo *
)
echo:Processed %FileCounter% files in %DirCounter% folders.
echo Done   
exit /b 0


:ProcessFile
:: filename is in %1
    
:: Remove short from short long. (Done with a define instead)
::  perl -pi -e "s/(short long)/long/g" %1

:: Replace the simple @ lines with AT().
    perl -pi -e "s/@\s*([0-9a-fA-FxX]+)/AT($1)/g" %1

:: Exchange @ and wrap in parenthesis for any substring starting with @ and ending with ; in each header file.
    perl -pi -e "s/[@] ?+([^;]*)/AT($1)/g" %1

:: Insert defines before first line in each header files:
    perl -pi -e "print \"// Hack to allow SourceTrail to be used on this source\n#if defined __XC8\n  #define AT(address) @ address\n#else\n  #define AT(address)\n  #define __bit _Bool\n  #define asm(assembly)\n  #define interrupt\n  #define short\n#define high_priority\n  #define low_priority\n#endif\n\n\" if $. == 1" %1

::Exit subroutine   
exit /b

要执行修改,请打开提升的提示符,cd 到包含文件,然后执行fix.cmd

先决条件

Perl 必须安装在 Windows 计算机上。我使用StrawberryPerl

编辑:主要是固定的错别字。澄清了如何处理有两种选择short long


推荐阅读