使用 googletest 测试嵌入式C++代码时处理外设寄存器的重复符号



我正在开发一个使用C++进行MSP430F5529爱好项目,并使用googletest进行测试。我是C/C++,微控制器/嵌入式和googletest的真正初学者。

MSP 上的外设通过寄存器控制,TI 提供了一个标头<msp430.h>,其中包括处理器特定的标头,在我的情况下msp5529.h,该标头定义了大量位等常量,但它也声明了微控制器上可用的寄存器,例如UCA1CTL1用于设置串行通信。

例如,当我为构建编译时,<msp430.h>包含在UART.h中,一切都按预期工作。但是,在测试时,我想包括一个可测试的<msp430.h>版本,我们可以称之为testable_msp430.h

所以基本上我们有以下内容:

UART.h

#ifndef TESTING
#include <msp430.h>
#else 
#include "testable_msp430.h"
#endif

testable_msp430.h

int UCA1CTL1;
*A bunch of other declarations*

test_UART.cpp

#include UART.h
*A bunch of tests*

UART

.cpp
#include UART.h
*A bunch of source*

问题是,当通过运行g++ -std=c++11 src/UART.cpp test/test_UART.cpp -lgtest -lgtest_main -pthread -o testOutput -DTESTING编译它进行测试时,我收到一个链接错误,指出

duplicate symbol _UCA1CTL1 in:
/var/folders/yr/mkwg3mhs1nl93l35x6t55vz80000gn/T/UART-772fab.o
/var/folders/yr/mkwg3mhs1nl93l35x6t55vz80000gn/T/test_UART-2e1a90.o

这是有道理的,因为UCA1CTL1是在UART.cpptest_UART.cpp的编译单元中定义的。因此,我的问题是通常如何处理内存映射寄存器以便能够测试/使用它们?

提前感谢!

您在 testable_msp430.h 中有定义而不是声明。 而不是:

int UCA1CTL1;

您应该具备:

extern int UCA1CTL1;

然后在另一个仅链接到测试或包装在#ifndef TESTING中的翻译单元中,或者在test_UART.cpp中,您将UCA1CTL1人的单个测试定义放置。

有几件事:

  • 使用标头护罩。 testable_msp430.h 应如下所示

    #ifndef TESTABLE_MSP430_H
    #define TESTABLE_MSP430_H
    /* contents */
    #endif
    
  • 不要在标头中声明变量。如果需要在多个文件之间共享它们,则应extern标头中的所有变量,并且应在与标头同名的 .c 文件中分配它们。

  • 寄存器int UCA1CTL1;是无稽之谈。如果链接器在正确的内存位置为您分配此变量,则应将其volatile uint8_t UCA1CTL1;(假设有 8 位寄存器(。如果链接器未将其链接到特定的正确内存位置,则可以考虑使用可移植宏而不是变量:

    #define UCA1CTL1 (*(volatile uint8_t*)0x1234u)
    

    其中0x1234是寄存器的地址。这还解决了在头文件中分配变量时出现的链接器问题。

    像这样的宏是跨多个编译器获得完全可移植的寄存器映射的唯一方法。缺点是你不会在传递给调试器的文件中获得实际对象,所以你不能像使用变量那样观察宏。

    但是,任何半体面的微控制器调试器都附带对所有外设的硬件支持,允许您从那里查看寄存器,因此只要您不打算使用垃圾质量调试器,就不是问题。

最新更新