主机测试具有硬编码内存地址的 C 程序
Host testing C program with hard coded memory addresses
我们将为 C 代码编写 functional/unit 测试。此 C 程序将 运行 作为嵌入式软件。但是,我们需要在 Linux 环境中 运行 进行测试。
问题是部分被测代码如下所示:
my_addresses.h:
#define MY_BASE_ADDRESS (0x00600000)
#define MY_OFFSET_ADDRESS (0x108)
my_code.c
#include "my_addresses.h"
static const My_Type* my_ptr =
(My_Type*)(MY_BASE_ADDRESS + MY_OFFSET_ADDRESS);
/* my_ptr is dereferenced and used ... */
显然,这在 Linux 主机环境中不会 运行 很好。
我们有什么办法可以在测试期间解决这个问题吗?我们能否以某种方式 "redirect" 程序使用其他地址,这些地址是在测试过程中分配的内存的有效地址?
我们的第一次尝试是在测试期间用另一个头文件替换 "my_addresses.h",它(外部)声明变量而不是硬定义 - 然后将 malloc 的内存分配给 MY_BASE_ADDRESS,等等。问题是 c 文件中的 "static const" 声明。当然你不能将变量分配给静态常量类型。
最好不要修改被测代码(尽管在最坏的情况下可能会变成那样)。
您可以检查例如__linux__
宏并使用条件编译。启用时 Linux 使用数组作为基础,并使其足够大以在其中保存所有需要的数据。
例如
#ifdef __linux__
int8_t array[1024];
# define MY_BASE_ADDRESS array
#else
# define MY_BASE_ADDRESS 0x00600000
#endif
在Linux环境中你可以定义一个全局数组,然后使用它的地址作为你的基指针。
const char my_buffer[1024];
#define my_base_addr (&my_buff)
假设
- 您的嵌入式内存布局足够小,可以在 Linux、
上完全(或几个块)进行建模
- 您的编译器对下面的常量内存地址表达式很满意,并且
My_Type
在您的示例中被定义为 typedef My_Type1_t * My_Type;
您可以 (1) 将嵌入式内存布局的定义与决定其放置方式分开,并且也许 (2) 如果您为布局声明 struct
,则可以获得一些类型安全:
#pragma (essential: stuff to force structs to contain no extra padding)
typedef struct {
char pad0[0x108];
My_Type1_t foo;
char pad1[0x210];
My_Type2_t bar;
...
} Memory_Layout_t;
#pragma (preferably: something to revert to previous struct layout options)
(如果您不喜欢计算 pad1
的大小,请使用 union
。)
然后制作变体:
#ifdef __linux__
Memory_Layout_t Embedded_Memory;
# define Embedded_Memory_P (& Embedded_Memory)
#else
# define Embedded_Memory_P ((Memory_Layout_t *) (0x00600000))
#endif
并用
引用它
static const My_Type my_ptr = & Embedded_Memory_P->foo;
我们将为 C 代码编写 functional/unit 测试。此 C 程序将 运行 作为嵌入式软件。但是,我们需要在 Linux 环境中 运行 进行测试。
问题是部分被测代码如下所示:
my_addresses.h:
#define MY_BASE_ADDRESS (0x00600000)
#define MY_OFFSET_ADDRESS (0x108)
my_code.c
#include "my_addresses.h"
static const My_Type* my_ptr =
(My_Type*)(MY_BASE_ADDRESS + MY_OFFSET_ADDRESS);
/* my_ptr is dereferenced and used ... */
显然,这在 Linux 主机环境中不会 运行 很好。
我们有什么办法可以在测试期间解决这个问题吗?我们能否以某种方式 "redirect" 程序使用其他地址,这些地址是在测试过程中分配的内存的有效地址?
我们的第一次尝试是在测试期间用另一个头文件替换 "my_addresses.h",它(外部)声明变量而不是硬定义 - 然后将 malloc 的内存分配给 MY_BASE_ADDRESS,等等。问题是 c 文件中的 "static const" 声明。当然你不能将变量分配给静态常量类型。
最好不要修改被测代码(尽管在最坏的情况下可能会变成那样)。
您可以检查例如__linux__
宏并使用条件编译。启用时 Linux 使用数组作为基础,并使其足够大以在其中保存所有需要的数据。
例如
#ifdef __linux__
int8_t array[1024];
# define MY_BASE_ADDRESS array
#else
# define MY_BASE_ADDRESS 0x00600000
#endif
在Linux环境中你可以定义一个全局数组,然后使用它的地址作为你的基指针。
const char my_buffer[1024];
#define my_base_addr (&my_buff)
假设
- 您的嵌入式内存布局足够小,可以在 Linux、 上完全(或几个块)进行建模
- 您的编译器对下面的常量内存地址表达式很满意,并且
My_Type
在您的示例中被定义为typedef My_Type1_t * My_Type;
您可以 (1) 将嵌入式内存布局的定义与决定其放置方式分开,并且也许 (2) 如果您为布局声明 struct
,则可以获得一些类型安全:
#pragma (essential: stuff to force structs to contain no extra padding)
typedef struct {
char pad0[0x108];
My_Type1_t foo;
char pad1[0x210];
My_Type2_t bar;
...
} Memory_Layout_t;
#pragma (preferably: something to revert to previous struct layout options)
(如果您不喜欢计算 pad1
的大小,请使用 union
。)
然后制作变体:
#ifdef __linux__
Memory_Layout_t Embedded_Memory;
# define Embedded_Memory_P (& Embedded_Memory)
#else
# define Embedded_Memory_P ((Memory_Layout_t *) (0x00600000))
#endif
并用
引用它static const My_Type my_ptr = & Embedded_Memory_P->foo;