专用接口
串口
本节主要介绍了 DSP 上串口的专用接口。
在官方板卡上,DSP6678 只有一个串口,SylixOS 将其用于调试终端,支持 Xmodem 文件传输。在此基础上,还支持通过“chuart”指令,将串口切换到对应的核上,从而实现串口在核间的共用。
网络
本节主要介绍了 DSP 上的网络配置。
SylixOS 支持标准的 socket 通信接口,整个网络协议栈针对嵌入式平台进行细致优化,同时,提供 AF_PACKET 协议域和网卡 poll 接收模式,能够满足强实时性需求。SylixOS 网络架构如图所示:
SylixOS 网络协议栈支持 AF_INET/AF_INET6、AF_UNIX、AF_PACKET 等丰富的协议域,满足众多复杂应用的需求。 在网络功能上,为 DSP 支持核间虚拟网卡通信,解决了业界存在多年的 DSP 多核之间相互通信和 DSP 与外界通信同时共存的问题,极大的方便了用户在 DSP 上实现复杂的组网的需求。
PC 与 DSP 间的物理网络通信配置
物理网卡默认 IP 地址是 0.0.0.0 ,用户在进入系统之后,需要首先配置好 IP 地址,或者也可以在加载系统之前,预先通过 BSP 的 XML或者 ifparam.ini 指定物理网卡的 IP 地址。
在 DSP6678 官方板卡中,除了物理网卡,每个核都拥有自己的虚拟网卡,从核网络数据经由 0 核的物理网络转发。刚开始虚拟网卡是无法直接与外部 PC 通信的,需要先在 PC 端配置好路由,才能实现与 PC 端的交互,配置方法如下:
指令:route -p add 虚拟网络网段 mask 网络掩码 核 0 物理网卡的 IP metric 3
示例:route -p add 192.168.3.0 mask 255.255.255.0 192.168.1.230 metric 3
PC及多块DSP之间的组网通信配置
两块及以上 DSP 板卡的情况下,为避免 IP 地址冲突,所有网卡都需要不同的 IP 地址。虚拟网络的 IP 和 MAC 会自动根据用户配置的板卡 ID 生成不同的值,从而避免网络 IP、MAC 地址冲突问题。PC 及两块 DSP 之间的组网通信的配置如下:
首先需要为 DSP 分配不同的 DSP 编号,从而为 DSP 生成不同的 IP 地址和 MAC 地址:在 BSP 中,为用户提供了 bspBoardIpAddr 函数接口,系统会根据该接口的返回值生成不同的物理网络和虚拟网络的 IP 地址和 MAC 地址。DSP 编号取决于硬件的编号规则,在以往项目中,有用户曾经通过 FPGA 或 GPIO 来为每个 DSP 编号,供参考。这里假设 DSP0 编号为 0,DSP1 编号为 1,物理网络 IP 地址初始配置为 192.168.1.230,那么两块板卡各核的默认 IP 地址会生成如下:
网卡 DSP0 的 IP地址 DSP1 的 IP 地址 物理网络 IP-0 核 192.168.1.230 192.168.1.231 虚拟网络 IP-0 核 192.168.3.200 192.168.4.200 虚拟网络 IP-1 核 192.168.3.201 192.168.4.201 虚拟网络 IP-2 核 192.168.3.202 192.168.4.202 虚拟网络 IP-3 核 192.168.3.203 192.168.4.203 虚拟网络 IP-4 核 192.168.3.204 192.168.4.204 虚拟网络 IP-5 核 192.168.3.205 192.168.4.205 虚拟网络 IP-6 核 192.168.3.206 192.168.4.206 虚拟网络 IP-7 核 192.168.3.207 192.168.4.207 完成该步骤后,网络的地址环境已经配置完成,此时 PC 及两块 DSP 之间的物理网络能够互相通信。
配置 PC 端的路由,配置的目的是使 PC 端能与两块 DSP 的虚拟网络之间通信,与单 DSP 时的 PC 路由配置方法相同。
示例:route -p add 192.168.3.0 mask 255.255.255.0 192.168.1.230 metric 3
route -p add 192.168.4.0 mask 255.255.255.0 192.168.1.231 metric 3
配置 DSP0 及 DSP1 的路由,配置的目的是使 DSP0 和 DSP1 的虚拟网络之间能够相互通信。
指令:route add -net 对端虚拟网络的网段 mask 网络掩码 对端物理网络 IP 地址 metric 3
示例:DSP0 中 : route add -net 192.168.4.0 mask 255.255.255.0 10.9.0.231 metric 3
DSP1 中 : route add -net 192.168.3.0 mask 255.255.255.0 10.9.0.230 metric 3
以上步骤配置完成后,PC 以及两块 DSP 各核之间的网络都能够相互通信。
存储
本节主要介绍了 DSP 上的文件系统。
SylixOS 提供丰富的文件系统,包括:rootfs、procfs 、fatfs、yaffs、nfs、romfs、ramfs、TpsFs(掉电安全),同时支持如下组件:
- 磁盘分区工具:为磁盘分区功能提供丰富的工具集。
- 高速磁盘缓冲器:支持并行多管线技术,能够完全利用高速存储介质的多通道功能,实现高速存储。
- 磁盘自动挂载:实现磁盘挂载无人化操作,提高系统易用性。
- 通用存储适配:支持 flash、SD、MMC、NVMe、磁盘阵列等丰富的存储介质。
TpsFs 是 SylixOS 针对大容量存储设备集成的文件管理系统,在异常掉电情况下,保证文件完整无损,非常适合对存储系统有高可靠性要求的场合。
多核 DSP 存储管理
文件系统支持
官方板卡的存储设备主要是 NandFlash、Spi Norflash、EMIF Norflash,SylixOS 为其挂载了 Yaffs 文件系统,用户可以通过访问 /yaffs2/ 目录下各目录空间来使用对应的 Flash 资源。历史项目中,曾经也为用户自研板卡适配过 PCIE NVME,挂接了 FAT32 和 Tpsfs 文件系统,本章主要介绍官方板卡的存储支持,此处暂时不对 NVME 做进一步描述。
存储介质 文件系统 NandFlash Yaffs2 Spi-NorFlash Yaffs2 Emif-NorFlash Yaffs2 内存 Ramfs 文件系统多核共享-分布式存储
分布式存储通过 NFS 使文件系统在多核间共享,DSP 上的 8 个核心能够以统一的文件接口方式访问存储介质,同时保证数据的完整性,不导致冲突,打破传统 DSP 软件系统仅允许一个核心访问存储介质的应用局限性。
高速总线
本节主要介绍了 DSP 上 RapidIO 的接口,包括 DMA 和 PIO 两种模式的使用,Message 模式暂不进一步描述。
RapidIO 网络主要由两种器件,终端器件(End Point)和交换器件(Switch)组成。终端器件是数据包的源或目的地,不同的终端器件以器件 ID 来区分。RapidIO 支持 8 bits 或 16 bits 器件 ID,因此一个 RapidIO 网络最多可容纳 256 或 65536 个终端器件。与以太网类似,RapidIO 也支持广播或组播,每个终端器件除了独有的器件 ID 外,还可配置广播或组播 ID。交换器件根据包的目地器件 ID 进行包的转发,交换器件本身没有器件 ID。RapidIO 的互连拓扑结构非常灵活,除了通过交换器件外,两个终端器件也可直接互连。
RapidIO 的地址概念
设备 ID
RapidIO 支持 8 位地址和 16 位地址,设备 ID 的配置方式有多种,如可以通过 BSP 的 XML 指定默认设备 ID,或者可通过 srioDevIdSet 函数接口指定设备 ID。注意:有些 DSP 不支持主机设备 ID 锁,并且不支持额外设备 ID 0xFF,所以这类处理器不支持枚举功能。
AXI 地址与 RIO 地址
SylixOS 将 RIO 地址与 AXI 地址做了一一对应,用户在使用时,可以直接使用对端地址进行数据传输。
DMA 模式的使用
SylixOS 为 DMA 模式封装成字符设备,用户可以通过 POSIX 接口对设备进行访问实现数据收发,每个字符设备都代表了一个对端设备,使用步骤如下:
配置设备 ID
设置本地设备 ID 为 0:srioDevIdSet(0, 0)
设置远端设备 ID 为 1:srioDevIdSet(0, 1)
注意:本节末尾的附录中描述了 srioDevIdSet 的函数原型。
创建设备
创建设备:rioadd 0 1 1
注意:可以通过 help 指令查看 rioadd 的用法,如下图中的操作:
数据收发
- 打开设备:
fd = open("/dev/rio0.1", O_RDWR);
- 配置模式:
mode = RIO_DIO_MODE_NWRITE; ioctl(fd, RIO_DIO_MODE_SET, &mode);
- 设置基址:
ioctl(fd, RIO_DIO_BASE_SET, &_G_ucRioDstAddr);
//该步骤指定了传输到对端的目的地址 - 发送数据:
write(fd, _G_ucRioSrc, TEST_SIZE);
//将 _G_ucRioSrc 中的数据发送到对端目的地址中 - 读取数据:
read(fd, _G_ucRioSrc, TEST_SIZE);
//从对端目的地址中,将数据读取到 _G_ucRioSrc 中 - 关闭设备:
close(fd);
- 打开设备:
门铃收发
- 注册回调:
registerDBellCB(dbCallBack1);
//向驱动注册门铃回调函数 dbCallBack1,下方附录中提供了函数的定义和描述 - 打开设备:
fd = open("/dev/rio0.1", O_RDWR);
- 发送门铃:
ioctl(fd, RIO_DIO_DBELL_TX, &uiDbVal);
// 下方附录中提供了 ioctl 的指令及描述 - 关闭设备:
close(fd);
- 注册回调:
PIO 模式的使用
SylixOS 为 PIO 模式提供一套配置接口,配置完成后,即可通过地址窗口进行数据收发。配置参考步骤如下:
- 窗口映射:通过 srioAPIOWindow 配置 PIO 的窗口参数;
- 数据收发:通过对 PIO 窗口读写来实现数据收发。
注意:
函数原型及用法参考下面的附录。
通过 memcpy 进行数据收发也是可以的,但性能会慢很多,而 EDMA 可以大幅度提升性能。
附录-接口函数说明
接口一:
VOID registerDBellCB (VOID (*fun)(UINT32 uiInst, UINT32 uiSrcId, UINT32 uiDbInfo));
功能:用于注册门铃的接收回调函数,可以传递当前控制器号,源设备 ID,以及门铃信息
参数:
uiInst 当前的控制器号
uiSrcId 门铃的源设备 ID
uiDbInfo 门铃的内容
接口二:
VOID srioAPIOWindow (UINT32 uiInst, UINT32 uiWinId, UINT32 uiWInType, UINT32 uiDstId, UINT32 uiAXIBase, UINT64 uiRioBase, UINT32 uiWinSize, UINT32 uiHopCount);
功能:用于映射窗口
参数:
uiInst:针对的控制器号
uiWinId:选择哪个映射单元,总共 32 个
uiWInType:映射的类型。
- 0 - Maintenance Read 和 Maintenance Write
- 1 - NREAD 和 NWRITE
- 2 - NREAD 和 NWRITE_R
- 3 - NREAD 和 SWRITE
uiDstId:目的设备 ID
uiAXIBase:AXI 基址,控制器 0:0x02980000 - 0x02980000 + 0x40000
控制器 1:0x029C0000 - 0x029C0000 + 0x40000
uiRioBase:对端的存储地址(已在 RPIO 中将 RIO 地址与地址空间对应,所以只需要对方的存储地址即可)
uiWinSize:该窗口的大小
uiHopCount:跳数,主要用于与 switch 通信
接口三:
VOID srioDevIdSet (UINT32 uiInst, UINT32 uiDevid);
功能:配置设备 ID
参数:
uiInst 针对的控制器号
uiDevid 设备 ID
ioctl:DMA 模式的字符设备,在使用 ioctl 接口时的指令:
#define RIO_DIO_BASE_SET _IOR('R', 0, ULONG)
/* 设置当前远端操作内存基地址 */#define RIO_DIO_BASE_GET _IOW('R', 1, ULONG)
/* 获取当前远端操作内存基地址 */#define RIO_DIO_MODE_SET _IOR('R', 2, INT)
/* 设置当前 DIO 操作模式 */#define RIO_DIO_MODE_GET _IOW('R', 3, INT)
/* 获取当前 DIO 操作模式 */#define RIO_DIO_DBELL_TX _IOW('R', 4, INT)
/* 发送门铃 */
核间通信
本节主要介绍了 DSP 上核间通信的接口。
通信方式 | 特点描述 |
---|---|
共享内存 | 芯片固有特性,多核可共享使用片内和片外内存,需要注意 Cache 需要手动回写和作废,同时要注意避免伪共享。 |
核间 IPC | 芯片固有特性,用于快速小消息通信 |
硬件信号量 | 芯片固有特性,用于核间互斥访问 |
核间 barrier | SylixOS 支持,用于多核间的同步 |
虚拟网卡 | SylixOS 支持,用于核间、片间、板间的组网通信 |
共享内存
由于 DSP6678 的特殊性,其 Cache 一致性需要手动维护,但在手动维护过程中,需要注意内存位置、Cache 行长度边界等问题,稍有不甚就可能引起数据错误。SylixOS 为用户提供统一接口,屏蔽底层细节,降低 Cache 操作的风险。操作接口如下:
- Cache 回写
INT API_CacheFlush (LW_CACHE_TYPE cachetype, PVOID pvAdrs, size_t stBytes);
- Cache 无效
INT API_CacheInvalidate (LW_CACHE_TYPE cachetype, PVOID pvAdrs, size_t stBytes);
- Cache 清空
INT API_CacheClear (LW_CACHE_TYPE cachetype, PVOID pvAdrs, size_t stBytes);
核间 IPC
IPC 用于核间消息传递,附带消息的长度有限且数据寄存器是共享的。SylixOS 对 IPC 数据进行规划,每次附带的数据限制在 2 位,使 IPC 可以在任意核间同时收发,并能够将消息标识为 4 种类型。其中消息 0 和消息 1 已经用于虚拟网卡和串口切换,消息 2 和消息 3 供用户自定义使用。
操作接口如下:
- 结构定义:
typedef struct {
PVOID_IPC_CALLBACK IPC_EXE_pfuncCallback;
PVOID IPC_EXE_pvArg;
BOOL IPC_EXE_bInUse;
} IPC_EXE_CB, *PIPC_EXE_CB;
- 回调函数:
typedef VOID (*PVOID_IPC_CALLBACK)(PVOID pvArg, UINT8 ucSrcId);
- 注册回调:
INT ipcCallBackIntall (PIPC_EXE_CB pIpcExeCb, UINT32 uiFlag);
- IPC 发送:
VOID ipcSend (UINT32 uiCoreId, UINT32 uiFlag);
硬件信号量
DSP6678 拥有 64 个硬件信号量,SylixOS 已经将其中的一部分用于系统以及 OpenMp,剩余的硬件信号量供用户使用,用户可以通过 bspSpinlockAlloc 接口分配信号量,而不用关注具体的编号。操作接口如下:
- 结构定义:
typedef struct {
UINT SPLOCK_uiVal;
} BSP_SPINLOCK_T;
- 分配信号量:
BSP_SPINLOCK_T *bspSpinlockAlloc (VOID);
- 释放信号量:
bspSpinlockFree (BSP_SPINLOCK_T *spinlock);
- 信号量加锁:
VOID bspSpinlockAcquire (BSP_SPINLOCK_T *lock);
- 信号量解锁:
VOID bspSpinlockRelease (BSP_SPINLOCK_T *spinlock);
- 尝试加锁:
UINT bspSpinlockTry (BSP_SPINLOCK_T *spinlock);
- 加锁状态:
UINT bspSpinlockTest (BSP_SPINLOCK_T *spinlock);
- 消耗数量:
UINT32 bspSpinlockUsed (VOID);
核间barrier
核间 barrier 是 SylixOS 专为核间同步而实现的,接口通过共享内存来实现,支持片内任意核间的同步,且可以反复使用。
多核屏障:VOID bspBarrier (UINT32 uiMask);
参数说明:uiMask 代表核的掩码,bit0 代表核 0,bit1 代表核 1,以此类推,bit7 代表核 7。
虚拟网卡
虚拟网卡解决了多核共享网络资源的问题,底层基于共享内存和 IPC,不占用硬件信号量,支持核间、片间、板间统一通过网络进行通信。使用方法与物理网络编程一致,可以参考 IDE 中附带的《SylixOS 应用开发手册》,开发自己的网络应用。
DSP 库
本节主要介绍了 DSP 上,SylixOS 对 TI 库的支持。
TI 库 | 版本 | 功能描述 |
---|---|---|
dsplib_c66x_3_4_0_3 | V3.4.0.3 | 主要包括自适应滤波器、相关运算、快速傅里叶变换、滤波和卷积运算、数学类、矩阵运算等 |
imglib_c66x_3_1_1_0 | V3.1.1.0 | 主要包括图像压缩/解压缩、图像分析、图像处理、图像格式转换等 |
mathlib_c66x_3_1_2_3 | V3.1.2.3 | 包括目前在现有实时支持库中提供的所有浮点数学例程 |
openmp_dsp_c667x_2_06_02_01 | V2.6.2.1 | 用于 OpenMp 并行运算,支持 OpenMp3.0 并行规范 |
fftlib_3_1_0_0 | V3.1.0.0 | 支持单精度和双精度浮点数;支持复杂输入和实输入;支持 1D, 2D 和 3D FFT;支持单核和多核 |
在以上支持的库列表中,dsplib、imglib、mathlib 和 fftlib 的用法,与 SysBios 基本一致,不再进一步描述。
OpenMp 库
OpenMp 库底层通过共享内存、硬件信号量、队列、软屏障等部件和机制,向上层提供了 OpenMp3.0 并行规范。该库在初始化过程中需要 write through 功能的支持,这样在全局作废的时候,就不用回写操作。SylixOS 完整支持 OpenMp 库的所有功能,在此基础上,SylixOS 还支持摆脱对 write through 的依赖,在合理利用内存的情况下,可实现 OpenMp 性能的进一步挖掘。