前提条件
Xtensa 仿真器 (xt-run
) 是用于运行 Xtensa ELF 可执行文件的专有 Xtensa 工具。这份指南假设你已经正确地安装了它及你的平台的核。它描述如何使用 xt-run
。
为你的平台运行仿真,需要通过 XTENSA_CORE 环境变量设置你的核(就像其它的 Xtensa 工具,如 xt-xcc
、xt-clang
、xt-make
和 xt-gdb
一样)。如果没有设置 XTENSA_CORE 环境变量,则需要为这些工具加上 --xtensa-core=xxxxxx 参数。如果你可以通过 xt-xcc
/xt-clang
编译器成功构建固件,则所有的配置应该都已经准备好了。
xt-run
可执行程序调用 RI-2022.10-linux/XtensaTools/lib/iss 目录下的 iss
程序运行仿真,ISS 即 Xtensa Instruction Set Simulator。
独立程序
使用 xt-xcc
/xt-clang
和 xt-run
开发程序与常见的 *nix 程序开发类似。
我们从一个 "Hello World!" 示例开始。把如下的代码片段保存为 test.c:
#include <stdio.h>
int main() {
printf("Hello World!\n");
return 0;
}
要运行这个程序,首先通过 xt-xcc
/xt-clang
构建 Xtensa ELF:
xt-clang --xtensa-core=ABCDE_ADSP_1027 test.c -o test
默认情况下,用 xt-xcc
/xt-clang
编译程序将链接标准 C 库。接下来,通过 xt-run
运行输出的二进制文件:
sof$ xt-run --xtensa-core=ABCDE_ADSP_1027 test
Hello, world!
通过 printf()
向标准输出打印的消息,将显示在控制台。你可以像这样独立运行任何代码,例如测试某些算法。
在 xt-run
中运行的程序还支持 stdlib
(在通常的 FW 中不可用),因此你可以使用 stdio
来打印输出。xt-run
还支持所有的核特有特性,因而你可以在你的 C 程序中使用 intrinsics(比如 HiFi3)。
通常的 FW 为了方便在没有操作系统加载的裸机环境运行,在编译链接时会加上 "-nostdlib" 标记,以移除对标准 C 库的依赖,如 SoF 在 sof/src/arch/xtensa/CMakeLists.txt 文件中加了这个标记:
if(BUILD_UNIT_TESTS)
set(stdlib_flag "")
else()
set(stdlib_flag "-nostdlib")
endif()
stdlib
对于通常的 FW 中不可用,也就很难通过 printf()
之类的函数打印消息来调试通常的 FW。Xtensa 工具链中包含了 xt-gdb
,可以用来调试 Xtensa ELF 可执行程序,包括通常的 FW。
用 xt-gdb
调试上面的 test
程序,和用 gdb 调试 PC 平台的程序基本没什么区别,如:
sof$ xt-gdb --xtensa-core=ABCDE_ADSP_1027 test
GNU gdb (GDB) 10.1 Xtensa Tools 14.10
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "--host=x86_64-pc-linux-gnu --target=xtensa-elf".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from test...
(xt-gdb) break main
Breakpoint 1 at 0x80000f4f
(xt-gdb) r
Starting program: /media/data/sof/test
Starting the ISS simulator.
Switching to remote protocol
Remote debugging using localhost:59226
_ResetVector () at /home/abc/RI-2022.10/ib/tools/swtools-x86_64-linux/xtensa-elf/src/xtos/xea2/reset-vector-xea2.S:81
81 /home/abc/RI-2022.10/ib/tools/swtools-x86_64-linux/xtensa-elf/src/xtos/xea2/reset-vector-xea2.S: 没有那个文件或目录.
Breakpoint 1, 0x80000f4f in main ()
(xt-gdb)
xt-gdb
可以启动 xt-run
/iss
来运行 Xtensa ELF。在 xt-gdb
中,可以使用一般的 gdb 调试可用的断点等各种命令。
对于那些通常的 FW,xt-gdb
和 xt-run
/iss
可以分开运行来调试。首先运行 xt-run
/iss
:
$ xt-run --xtensa-core=ABCDE_ADSP_1027 --xtensa-system=/media/data/xtensa/XtDevTools/install/tools/RI-2022.10-linux/XtensaTools/config --xtensa-params= --console --gdbserve=0 --vector=0 dsp0.elf
SOCKET:53497
xt-run
/iss
开启一个调试端口,如上面的 53497。然后运行 xt-gdb
,如:
$ xt-gdb --xtensa-core=ABCDE_ADSP_1027 dsp0.elf
GNU gdb (GDB) 10.1 Xtensa Tools 14.10
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "--host=x86_64-pc-linux-gnu --target=xtensa-elf".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from dsp0.elf...
(xt-gdb) target remote localhost:53497
Remote debugging using localhost:53497
_ResetVector () at /home/abc/RI-2022.10/ib/tools/swtools-x86_64-linux/xtensa-elf/src/xtos/xea2/reset-vector-xea2.S:81
81 /home/abc/RI-2022.10/ib/tools/swtools-x86_64-linux/xtensa-elf/src/xtos/xea2/reset-vector-xea2.S: 没有那个文件或目录.
(xt-gdb) break main
Breakpoint 1 at 0x800665ff: file top/src/main/main.c, line 108.
(xt-gdb) r
The "remote" target does not support "run". Try "help target" or "continue".
(xt-gdb) c
Continuing.
Breakpoint 1, main (argc=1, argv=0x80440004) at top/src/main/main.c:108
在 xt-gdb
中通过 target remote localhost:53497
命令连接 xt-run
/iss
。之后在 xt-gdb
中可以使用 gdb 的各种调试命令来调试 FW。
Xtensa 提供的基于 Eclipse 的 IDE 工具 Xtensa Xplorer 使用相同的 xt-run
/iss
和 xt-gdb
工具来调试程序。
单元测试
在 SOF 项目中,xt-run
被用作单元测试的执行者。
下面的示例演示了,如何为示例函数添加简单的单元测试用例:math
模块中的 my_add
。
首先,添加一个将成为单元测试主题的函数:
Code Block 8 src/include/sof/math/numbers.h
int my_add(int a, int b);
Code Block 9 src/math/numbers.c
int my_add(int a, int b)
{
return a + b;
}
接下来,添加单元测试实现:
Code Block 10 test/cmocka/src/math/numbers/my_add.c
// header with function that we test
#include <sof/math/numbers.h>
// standard headers that have to be included in every cmocka's unit test
#include <stdarg.h>
#include <stddef.h>
#include <setjmp.h>
#include <stdint.h>
#include <cmocka.h>
// one of test cases
static void my_add_2_plus_3_equals_5(void **state)
{
int result;
(void)state;
result = my_add(2, 3);
assert_int_equal(result, 5);
}
int main(void)
{
// list of all test cases, here we have just 1
const struct CMUnitTest tests[] = {
cmocka_unit_test(my_add_2_plus_3_equals_5),
};
cmocka_set_message_output(CM_OUTPUT_TAP);
return cmocka_run_group_tests(tests, NULL, NULL);
}
对每个进行单元测试的函数使用一个单独的文件;这也就是我们把代码放进 test/cmocka/src/math/numbers 目录下的 my_add.c 文件中的原因。
最后,让 CMake 知道单元测试的存在。
Code Block 11 test/cmocka/src/math/numbers/CMakeLists.txt
cmocka_test(my_add
my_add.c
${PROJECT_SOURCE_DIR}/src/math/numbers.c
)
要运行单元测试,可以按照 单元测试 一文中的说明进行。
如果你只想运行你的测试用例 (而不是所有的测试),你可以把如下的命令:
make -j4 && ctest -j8
替换为:
make my_add && ctest -R my_add
在 Testing/Temporary/LastTest.log 可以找到运行 ctest 时产生的日志。
参考文档
Xtensa Simulator (xt-run)
Done.