通过XN文件定义芯片
XMOS平台通过软件来定义芯片的硬件特性,您可以通过修改XN文件来定义其功能。每个XN文件都为XMOS编译工具链提供了目标硬件的详细信息,包括但不限于XMOS设备、端口、闪存以及振荡器等。
通过读取XN文件中的数据,XTC工具链能够生成用于特定平台的头文件——<platform.h>,并在多节点程序的编译、启动和调试过程中使用它。
.xn文件包含了哪些内容?
即使您需要自定义XMOS芯片的功能,您也不需要从头开始编写.xn文件。所有的应用项目中都包含了.xn,并且包含了常用的配置默认值。
但如果您对于配置的设计与实现方式有更深的了解,会对深入开发很有帮助。
XN的高级层次结构可以分为:
关于XN中每个字段的详细信息和默认配置,请查阅XN规范说明。
XN文件通常位于sw_usb_audio/app_usb_aud_xxx/src/core目录中,下面我们将以XU316-1024-QF60B-PP24.xn文件为例,说明如何进行常见的配置操作。
总体配置
以下代码片段描述了XMOS芯片的封装方式与节点:
<Packages>
<Package id="0" Type="XS3-UnA-1024-FB265">
<Nodes>
<Node Id="0" InPackageId="0" Type="XS3-L16A-1024" Oscillator="24MHz" SystemFrequency="600MHz" referencefrequency="100MHz">
让我们说明其中的关键部分:
Package
Package主要定义了从xCORE端口到封装引脚的映射关系。当你更换芯片封装时,可能需要对此进行修改。值得注意的是,大封装的pkg文件能够兼容小封装的芯片,比如在使用XU316-1024-QF60B-PP24时,可以采用XS3-UnA-1024-FB265的封装信息。这些封装信息可以在XTC安装目录下的configs文件夹中查找。
Type="XS3-UnA-1024-FB265":此处指定的是XML封装的名称。XTC工具链会在XCC_DEVICE_PATH所指定的路径中查找<type>.pkg文件。
Node
Node元素定义了网络中连接到xCONNECT的一组xCORE Tiles。可以通过修改此元素来调整参考时钟频率和每个tile的系统主频,从而影响芯片的运行速度、功耗以及硬件定时器。
具体参数说明如下:
Type="XS3-L16A-1024":此处定义了描述节点的XML文件名,XTC工具链会在XCC_DEVICE_PATH指定的路径中搜索<type>.xml文件。Oscillator="24MHz":此项设置了该节点使用的晶振或时钟源频率为24MHz。SystemFrequency="600MHz":此项设置了该节点的系统频率为600MHz。在更改此项时,通常以100MHz为步进。referencefrequency="100MHz":此项设置了时钟的参考频率为100MHz,这将影响硬件定时器的ticks。
端口(引脚)配置
在XN文件中,每个<Tile>元素会定义一个或多个端口。端口是与外部设备交互的接口,XMOS芯片通过这些端口进行输入/输出操作。以下的代码片段展示了如何配置一组QSPI引脚:
<Tile Number="0" Reference="tile[0]">
<Port Location="XS1_PORT_1B" Name="PORT_SQI_CS"/>
<Port Location="XS1_PORT_1C" Name="PORT_SQI_SCLK"/>
<Port Location="XS1_PORT_4B" Name="PORT_SQI_SIO"/>
<!-- ... -->
</Tile>
<Tile Number="1" Reference="tile[1]">
<!-- ... -->
</Tile>
在使用端口资源之前,你需要定义它们所在的<Tile>元素:
Number:Tile在节点中的唯一编号,取值范围为0到n-1,其中n是在节点XML文件中定义的Tile数量。Reference:将 Tile 与在Declaration中以tile[n]形式表达的标识符关联起来。
另外,<Port>元素定义了一个端口,并指定了该端口的引脚位置和用途名称。lib_xua库中的代码与此处的Name命名有关系,所以你需要使用规范的命名来快速定义引脚。关于常用的引脚定义,请参考常用的引脚定义。
Location
Location属性定义了该端口在xCore tile中的位置,这是由标准头文件<xs1.h>中的端口标识符指定的。例如,"XS1_PORT_1B"表示该端口位于1B位置。更多关于端口的描述可以在XC编程指南中查阅。
Name
Name属性为端口设定了一个名称或别名,这使得程序员在进行编程时能够更容易识别和使用各个端口。例如"PORT_SQI_CS"就是这个端口的名称。如需了解关于端口使用的更多信息,请参考XC编程语言。
在上述代码片段中,我们定义了三个位于XS1_PORT_1B、XS1_PORT_1C和XS1_PORT_4B的端口,并分别命名为PORT_SQI_CS、PORT_SQI_SCLK和PORT_SQI_SIO。
你可以根据实际需求,按照同样的方式修改或增加端口配置。
示例:点亮LED灯
<Tile Number="0" Reference="tile[0]">
<Port Location="XS1_PORT_1A" Name="PORT_LED"/>
<!-- ... -->
</Tile>
#include <platform.h>
on tile[0]: out port p_leds = PORT_LED;
p_leds <: 0x1;//点亮LED
Flash配置
下面的代码段展示了如何描述连接到XMOS Tile[0]的Flash的硬件配置信息,这里以UC25HQ16B为例:
<ExternalDevices>
<Device NodeId="0" Tile="0" Class="SQIFlash" Name="bootFlash" PageSize="256" SectorSize="4096" NumPages="8192">
<Attribute Name="PORT_SQI_CS" Value="PORT_SQI_CS"/>
<Attribute Name="PORT_SQI_SCLK" Value="PORT_SQI_SCLK"/>
<Attribute Name="PORT_SQI_SIO" Value="PORT_SQI_SIO"/>
<Attribute Name="QE_REGISTER" Value="flash_qe_location_status_reg_1"/>
<Attribute Name="QE_BIT" Value="flash_qe_bit_1"/>
</Device>
</ExternalDevices>
Devices
Device元素描述了一个连接到xCORE Tile的Flash设备。定义该元素需要以下必备信息:
-
NodeId:设备所连接节点的标识符 -
Tile:设备所连接的节点内的tile -
Name:命名设备的标识符
为正确配置上述项目,你需要参考Flash的datasheet。相关信息可以在UC25HQ16B的第四页找到:
-
Class:描述了设备的类型,可选值有SPIFlash(对应SPI)和QSIFlash(对应QSPI) -
PageSize:设备的页面大小,此处为 256 bytes -
SectorSize:设备的擦除扇区大小,此处为 4096 bits -
NumPages:设备的总页数,需要根据总容量计算,此处为 -
Attribute
PORT_SQI_CS:表示QuadSPI的芯片选择信号。PORT_SQI_SCLK:表示QuadSPI的时钟信号。PORT_SQI_SIO:表示QuadSPI的输入/输出信号。

根据UC25HQ16B第9页的表4,我们得知QE状态位是第2组寄存器(即S8-S15)的第2个bit(即S9),因此可以按照如下方式配置:
QE_REGISTER:此项为可选,此处需要配置为flash_qe_location_status_reg_1QE_BIT:此项为可选,此处需要配置为flash_qe_bit_1
常用的引脚定义
在lib_xua中,XMOS预定义了一系列端口,并在代码中使用这些名称。
当你使用lib_xua中的功能或接口(例如I2S/TDM,或者Mixer时),你需要按照约定好的命名将这些名称 Name 映射到硬件设计的端口位置 Location 中。这种方式的优势在于,你可以灵活地改变接口所在的引脚位置,以适配不同的产品应用。
I2S/TDM接口
I2S/TDM接口定义了使用I2S/TDM协议传输数据时,连接到XMOS的时钟与数据的引脚。为保证低延迟的音频传输,减少代码开销,尽量在1bit 端口上定义这些引脚,下面的代码定义了至高8通道I2S,32 通道TDM的音频I/O接口,支持DSD格式。
<Tile Number="0" Reference="tile[0]">
<!-- Audio Ports: I2S -->
<Port Location="XS1_PORT_1L" Name="PORT_MCLK_IN"/>
<Port Location="XS1_PORT_1M" Name="PORT_I2S_BCLK"/>
<Port Location="XS1_PORT_1N" Name="PORT_I2S_LRCLK"/>
<Port Location="XS1_PORT_1O" Name="PORT_I2S_DAC0"/>
<Port Location="XS1_PORT_1D" Name="PORT_I2S_DAC1"/>
<Port Location="XS1_PORT_1P" Name="PORT_I2S_DAC2"/>
<Port Location="XS1_PORT_1A" Name="PORT_I2S_DAC3"/>
<Port Location="XS1_PORT_8D" Name="PORT_I2S_ADC0"/>
<Port Location="XS1_PORT_4D" Name="PORT_I2S_ADC1"/>
<Port Location="XS1_PORT_1C" Name="PORT_I2S_ADC2"/>
<Port Location="XS1_PORT_1B" Name="PORT_I2S_ADC3"/>
<!-- Audio Ports: DSD -->
<Port Location="XS1_PORT_1M" Name="PORT_DSD_CLK"/>
<Port Location="XS1_PORT_1O" Name="PORT_DSD_DAC0"/>
<port Location="XS1_PORT_1D" Name="PORT_DSD_DAC1"/>
</Tile>
-
PORT_MCLK_IN、PORT_I2S_LRCLK、PORT_I2S_BCLK:这一组名称定义 了音频的主时钟(MCLK)、位时钟(BCLK)以及采样率时钟(LRCLK),这些引脚通常与Codec或DSP的对应的时钟引脚相连。 -
PORT_I2S_DACn:这一组名称定义了由XMOS输出到DAC的数据引脚,其中n为序列号。 -
PORT_I2S_ADCn:这一组名称定义了由ADC输入到XMOS的数据引脚,其中n为序列号。
设备需要使用DSD/Dop功能时,定义以下引脚:
PORT_DSD_CLK、PORT_DSD_DACn:这一组名称定义了DSD的时钟(CLK)以及数据引脚(Data)。DSD相关引脚的定义与I2S的引脚定义保持一致,以兼容DSD/Dop格式音频的播放。
S/PDIF&ADAT接口
接口定义了使用S/PDIF协议传输数据流时,连接到XMOS的引脚。与I2S类似,尽量在1bit 端口上定义这些引脚。下面代码定义了2通道S/PDIF I/O接口,以及ADAT I/O接口:
<Tile Number="0" Reference="tile[0]">
<Port Location="XS1_PORT_1O" Name="PORT_ADAT_IN"/>
<Port Location="XS1_PORT_1E" Name="PORT_ADAT_OUT"/>
<Port Location="XS1_PORT_1P" Name="PORT_SPDIF_IN"/>
<Port Location="XS1_PORT_1D" Name="PORT_SPDIF_OUT"/>
</Tile>
PORT_ADAT_IN、PORT_ADAT_OUT:定义了ADAT的I/O流接口PORT_SPDIF_IN、PORT_SPDIF_OUT:定义了S/PDIF的I/O流接口
USB接口
XMOS芯片内置了USB PHY,当你使用lib_xua或lib_xud库时,你需要在tile[0]或tile[1]上定义这些引脚,以使用USB PHY的功能。
<Tile Number="1" Reference="tile[1]">
<Port Location="XS1_PORT_1E" Name="PORT_USB_FLAG0"/>
<Port Location="XS1_PORT_1F" Name="PORT_USB_FLAG1"/>
<Port Location="XS1_PORT_1G" Name="PORT_USB_FLAG2"/>
<Port Location="XS1_PORT_1H" Name="PORT_USB_TX_READYIN"/>
<Port Location="XS1_PORT_1I" Name="PORT_USB_RX_READY"/>
<Port Location="XS1_PORT_1J" Name="PORT_USB_CLK"/>
<Port Location="XS1_PORT_1K" Name="PORT_USB_TX_READYOUT"/>
<Port Location="XS1_PORT_8A" Name="PORT_USB_TXD"/>
<Port Location="XS1_PORT_8B" Name="PORT_USB_RXD"/>
<!-- Ports for USB feedback calculation -->
<Port Location="XS1_PORT_16B" Name="PORT_MCLK_COUNT"/>
<Port Location="XS1_PORT_1G" Name="PORT_MCLK_IN_USB"/>
</Tile>
对于QFN封装的XU316(例如:XU316-1024-QF60B-PP24),有以下几点需注意:
- 当USB功能定义在Tile[0]上时:USB使用的全部是未引出的引脚,不会占用任何GPIO。
- 当USB功能定义在Tile[1]上时:在封装内部,USB会占用Tile[1]上的
XS1_PORT_1F和XS1_PORT_1K引脚。此时,这两个GPIO不应连接到任何外设。