Code Debugging
本文中,我们针对代码编译过程中出现的一些报错,进行记录并提供参考的解决思路。
fl_copySpec未引用
执行cmake -B build -DCMAKE_TOOLCHAIN_FILE=xmos_cmake_toolchain/xs3a.cmake 时,出现如下错误。
Error: Undefined reference to 'fl_copySpec'
解决思路:
请使用最新的XTC软件版本(>= 15.2.1),该问题由sfdp 所引起,需要XTC对SFDP启用泛型支持。
xscope 环境变量为空
安装时,打印出现如下错误:
Set runtime path of "/opt/xmos/bin/xscope_host_endpoint" to ""
如下图:

当你在linux类系统的root user权限下,执行make install 时,会出现环境变量无法配置的情况,所以为空(to " ")
解决思路:
-
思路1:退出root mode,重新执行
make install -
思路2:手动添加环境变量
-
使用编辑器(如
nano)将配置添加进环境变量文件中。例如,使用以下命令打开.bashrc文件:nano ~/.bashrc -
在文件的末尾添加环境变量:
export PATH="/opt/xmos/bin:$PATH"这将在每次登录时将
/opt/xmos/bin添加到PATH环境变量中。保存并关闭文件(在nano编辑器中,按下Ctrl+X,然后按Y确认保存,最后按Enter键关闭)。 -
重启终端或执行以下命令以使配置文件生效:
source ~/.bashrc现在,无论何时登录到系统,/opt/xmos/bin目录都会自动添加到PATH环境变量中。 使用
echo $PATH命令查看环境变量PATH,以验证更改已正确应用。
-
malloc_lock_object
malloc_lock_object 具体报错如下图:

解决思路: 在编译时添加-mcmodel=<model>选项
-
选择 memory model:
small,large,或hybrid。 -
在这里,我们进入项目的Makefile,向
BUILD_FLAGS选项中添加-mcmodel=large。 -
如果添加
-mcmodel=large后仍有问题,在定义数组前一行添加预处理器指令:#pragma large_arrays。
SetSampleRate -> OxEF000011
在驱动面板切换采样率时, 出现SaveSelectedSampleRate: TUSBAUDIO_SetSampleRate -> OxEF000011

解决思路: 由于Audio线程没有及时的切换,在Audio中存在过多的延时。
- 例如在
AudioHwConfig()长时间delay就会出现此报错,应当减小延迟,以避免线程阻塞
no '<' before the end of file
执行命令:xburn --read --target-file XXX.xn
报错update.xml: error: no '<' before the end of file
解决思路: 在XN文件中存在网址,网址连接问题;将网络断开或修改最新的XMOS网址,再执行xburn命令即可。
FL_QUADDEVICE_DEFAULT
报错use of undeclared identifier 'FL_QUADDEVICE_DEFAULT'
解决思路: 版本检查只适用于XTC软件版本(>= 15.2.1),请使用最新的XTC软件版本。
大小端序问题
-
XCORE内存的存储方式是小端序(least significant byte at lowest address)
-
通道 Channel的传输方式可以看作大端序 big endian(most significant byte sent first over the the channel)
-
通过XTC编译器中包含的
byterev()指令,可以翻转一个word内的bytes,从而允许高效地访问存储为big endian的数据。
使用extends时,提示无需在外部提供定义
在使用lib_i2c,自行添加extends api(例如extends client interface i2c_master_if)时,编译时出现找不到添加的extends api
Error: Undefined reference to '__i_i2c_master_if_user_init' (possible inline definition without external definition)
解决思路:
需要在i2c.h文件的最后,添加extends api所在的文件(如: #include"i2c_config_extends.h")
同时extern extends api到i2c_master_ext.xc文件当中,参考如下
extends client interface i2c_master_if :
{
extern inline void i2c_config_user_init(client interface i2c_master_if i2c);
}
'clock'重新定义为不同类型的符号
错误:将'clock'重新定义为不同类型的符号clock_t _EXFUN(clock, (void));
具体重定义报错如下
/opt/xTIMEcomposer_14.3.3/target/include/time.h:47:19: error: redefinition of 'clock' as different kind of symbol
clock_t _EXFUN(clock, (void));
^
/opt/xTIMEcomposer_14.3.3/target/include/_ansi.h:75:30: note: expanded from macro '_EXFUN'
#define _EXFUN(name, proto) name proto
^
/opt/xTIMEcomposer_14.3.3/target/include/xccompat.h:198:18: note: previous definition is here
typedef unsigned clock;
^
1 error generated.
情况说明:当在USB-Audio-v6.15.2(原sw_usb_audio-[sw]_6.15.2)代码中,添加并使用某些最新的lib, 且使用旧的Community_14.x.x编译代码时,会出现如上报错。
路径:xTIMEcomposer_14.x.x/target/include/xccompat.h
需要人为修改xccompat.h文件,修改项如下
#ifndef _clock_defined
#define _clock_defined
typedef unsigned clock;
#endif /* _clock_defined */
修改后
#ifndef _clock_defined
#define _clock_defined
typedef unsigned xcore_clock_t;
#ifdef XCORE_USE_LEGACY_CLOCK_NAMING
typedef xcore_clock_t clock;
#endif // XCORE_USE_LEGACY_CLOCK_NAMING
#endif /* _clock_defined */
0x00080e10 fl_getNumSectors()
报错详情:
xrun: Program received signal ET_ARITHMETIC, Arithmetic exception.
0x00080e10 in fl_getNumSectors ()
使用情况:
- 在对Flash进行读写操作(QSPI Mode)的时候,需要连接设备,并设定boot分区大小,连接Flash异常会出现上述的错误
连接Flash,并设定boot分区示例
#include <xs1.h>
#include <platform.h>
#include "quadflash.h"
#include "quadflashlib.h"
#define FLASH_PARTITION_SIZE (65536 /* 64K */ * 24) // Boot Partition size
#define FL_QUADDEVICE_UC25HQ16 \
{ \
0, /* UC25HQ16B_QSPI - Just specify 0 as flash_id */\
256, /* page size */\
8192, /* num pages */\
3, /* address size */\
4, /* log2 clock divider */\
0x9F, /* QSPI_RDID */\
0, /* id dummy bytes */\
3, /* id size in bytes */\
0xB36013, /* device id */\
0x20, /* QSPI_SE */\
4096, /* Sector erase is always 4KB */\
0x06, /* QSPI_WREN */\
0x04, /* QSPI_WRDI */\
PROT_TYPE_SR, /* Protection via SR */\
{{0x3C,0x00},{0,0}}, /* QSPI_SP, QSPI_SU */\
0x02, /* QSPI_PP */\
0xEB, /* QSPI_READ_FAST */\
1, /* 1 read dummy byte */\
SECTOR_LAYOUT_REGULAR, /* mad sectors */\
{4096,{0,{0}}}, /* regular sector sizes */\
0x05, /* QSPI_RDSR */\
0x01, /* QSPI_WRSR */\
0x01, /* QSPI_WIP_BIT_MASK */\
}
on tile[0]: fl_QSPIPorts QspiPort =
{
PORT_SQI_CS, /* XS1_PORT_1B */
PORT_SQI_SCLK, /* XS1_PORT_1C */
PORT_SQI_SIO, /* XS1_PORT_4B */
XS1_CLKBLK_1
};
fl_QuadDeviceSpec flash_devices0[1] = {FL_QUADDEVICE_UC25HQ16};
fl_connectToDevice(QspiPort, flash_devices0, 1); /* 连接Flash */
fl_setBootPartitionSize(FLASH_PARTITION_SIZE); /* 设定 Boot分区的大小,其余的是 Data分区 */
问题点: 运行例程时,Flash描述文件spec中,device id与实际的器件不匹配;
解决方式:
- 通过以下命令获取正确的device id
xflash --spi-read-id 0x9f --target=XCORE-AI-EXPLORER
打印结果
Response to SPI ID command on tile[0]: 0xb3, 0x60, 0x15, 0x0.
将示例的FL_QUADDEVICE_UC25HQ16宏,修改设定的device id,0xB36013修改为0xB36015,就可以正常连接到设备并设定Boot分区
未定义'fl_connectToDevice'
报错详情:
Error: Undefined reference to 'fl_connectToDevice'
Error: Undefined reference to 'fl_getDataPartitionSize'
Error: Undefined reference to 'fl_setBootPartitionSize'
使用情况:
-
通过QSPI Mode,对Flash进行读写操作
在XC或C文件中添加了
#include "quadflash.h"和#include "quadflashlib.h",实际调用fl_connectToDevice出现了未定义的错误
解决方式: 在Makefile文件,找到BUILD_FLAGS或XCC_FLAGS变量定义,在变量的值中添加-lquadflash参数
这个参数是用来链接quadflash库,它可能包含了操作quad SPI flash的函数和定义。添加这个参数后,编译器会在链接时包含这个库,使得项目能够使用库中定义的资源。
BUILD_FLAGS += -lquadflash
// XCC_FLAGS += -lquadflash
I2C 控制:计时器数值越界问题
在修改了 lib_i2c 库的行为后,观察到以下不正确的行为,如图所示:
- 在标识 (1)-(2) 之间,时间间隔为 21 秒,I2C_CLK 和 I2C_SDA 被强制置为 "0"(或出现不可控的行为)。
- 在标识 (2)-(3) 之间,时间间隔为 21 秒,I2C 时钟和数据线正常工作,且 I2C 正常运作的时间也为 21 秒。
如下图所示,这两种行为轮替交替出现:

现象分析
-
timerafter函数将计时器的计数值视为具有两个不同的范围,如下图所示:
所有在范围 之间的值都被视为在 time 之前发生,而范围 之间的值则被视为之后发生。如果两个输入的值之间的间隔可以在 31 位数值内表示,则可以保证
timerafter函数的正确行为。否则,可能由于数值溢出而导致不正确的行为。也就是说,计时器可以用来测量的最长时间为 秒,即 21 秒。一个常见的编程错误是在输入新的时间时,没有将其转换为无符号类型,而是忽略了类型,如下所示:
t when timerafter(time) :> time;由于处理器并不是在时间到达后立即完成输入,这个操作实际上会在 time 上增加一小段额外的时间。这个小的增量在循环中累积,最终导致信号偏移,并与接收器不同步。time 的时间越界不符合要求,因此每次需要将 time 重新赋值为 0。
解决方案
- 在 I2C 的 start_bit 中,存在对
fall_time重新赋值的操作。将这段代码恢复即可解决问题;或者,在使用 I2C 之前,调用以下的time_init函数来初始化时间:
static void time_init(unsigned &fall_time)
{
timer tmr;
tmr :> fall_time;
}