基于µC/OS-Ⅱ与NiosⅡ的以太网接口软件设计

2013-07-05 16:31胡青
声学与电子工程 2013年2期
关键词:调用中断以太网

胡青

(第七一五研究所,杭州,310012)

基于µC/OS-Ⅱ与NiosⅡ的以太网接口软件设计

胡青

(第七一五研究所,杭州,310012)

介绍了用户如何基于µC/OS-Ⅱ多任务实时操作系统和NiosⅡ处理器并运用NicheStack TCP/IP协议栈的标准套接字接口,进行以太网接口的底层逻辑与应用程序设计,实现数据传输及与上位机通讯的功能。为在FPGA片上实现网络应用服务提供一种解决方法。

µC/OS-Ⅱ;NiosⅡ;以太网;NicheStack TCP/IP;接口软件

随着CPU芯片性能的提高,多任务实时操作系统(RTOS)在嵌入式系统中得广泛应用。为能将RTOS应用于FPGA片上系统中,Altera 公司开发出了NiosⅡ软核处理器,使得在µC/OS-Ⅱ实时操作系统下,利用高级语言及TCP/IP标准套接字接口,完成多任务以太网通信软件开发。这种设计思路增加了系统设计的灵活性,可以大大缩短产品研发和上市的时间,已成为一种嵌入式系统设计的潮流。

1 µC/OS-Ⅱ与NiosⅡ简介

µC/OS-Ⅱ是一个完整的、可移植、固化、裁剪的占先式实时多任务内核。它是美国Jean Labrosse 于1992 年开始编写的,是一种适合于小型、微控制器的多任务、可剥夺实时操作系统[1]。主要特点:(1)可移植性。源代码绝大部分是用移植性很强的ANSI C编写的,与微处理器硬件相关的部分是用汇编语言编写的。汇编语言写的部分已经压到最低限度,以使其便于移植到其他微处理器上。(2)可剪裁。可根据用户需求,依靠条件编译选择在应用程序中定义需要的系统服务,从而减少存储空间的占用。(3)可剥夺性。完全可剥夺型的实时内核,即总是运行就绪条件下优先级最高的任务。(4)多任务。可以管理64个任务,其中8个由系统直接管理,用户的应用程序最多可有56个任务。不支持时间片轮转调度法(round-robin scheduling),赋予每个任务的优先级必须是不相同的。每个任务都有自己单独的栈。(5)系统服务。提供信号量、互斥型信号量、事件标志、消息邮箱、消息队列、信号量、固定大小的内存申请与释放及时间管理函数等系统服务。(6)中断管理。中断可以使正在执行的任务暂时挂起,且支持中断嵌套,嵌套层数可达255层。

NiosⅡ处理器是Altera 公司开发出的一种采用流水线技术的32位精简指令集、可配置软核处理器,具有超过250 DMIPS的性能,并专门针对可编程逻辑器件进行了优化,包含32个内部通用寄存器,最多可支持32个外部中断源,支持各种片上以及片外存储器和外设[2]。它拥有自己的汇编语言指令集,可以完成各种算数与逻辑运算、数据传输、流程控制以及按位操作。软件开发环境为Nios ⅡIDE,采用GNU编译器,支持C/C++的编译、链接,可以产生重入代码,允许在C语言中嵌入汇编语言[3]。在Altera 公司的SOPC Builder中加载NiosⅡ软核处理器以及相应的外围接口和各种自定义指令,可构成完整、功能强大的SOC系统,利用FPGA设计软件进行综合,下载到FPGA中就可以实现一个特定功能的嵌入式系统。

2 硬件与片上系统设计

2.1 硬件设计

硬件设计框图如图1所示。FPGA选用Altera公司CycloneⅢ系列的EP3C120F780C芯片,完成片上系统的全部底层硬件逻辑。该芯片拥有119088个逻辑单元、532个I/O管脚、3.79 Mbits的片上存储单元、576个乘法器以及4个PLL,是一款适用于多种应用场合、低价格、高性能的FPGA芯片。

图1 硬件框图

以太网PHY芯片选用Marvell公司的88E1111型芯片。该芯片需要25 MHz参考时钟进行驱动,并且提供32个内部的管理寄存器,可通过MIDO接口进行访问、配置。

外部存储器选用2 MBytes的Cypress CY7C1380 SSRAM芯片,完成运行程序与数据存储;主动串行配置芯片选用Altera公司的EPCS64,完成FPGA硬件逻辑与应用程序的上电加载。其中,以太网的MAC控制器与PHY芯片采用RGMII的接口进行网络数据的交换。

2.2 片上系统设计

Altera公司的SOPC Builder构建的以NiosⅡ处理器为核心的片上系统,主要功能是完成采集数据的网络传输。该系统选用并配置Triple Speed Ethernet MegaCore的IP组件作为千兆以太网MAC;主时钟(50 MHz)与以太网接收时钟(125 MHz)分别通过多个PLL产生硬件电路所需的各种时钟;利用FPGA的片上存储资源,构建各种片上存储器,如FIFO、以太网数据缓存区以及紧耦合数据/指令存储器等;利用SGDMA组件完成FIFO与数据缓存区,以及数据缓存区与MAC间的数据传输,降低传输对CPU资源的占用率;三态口组件实现SSRAM控制组件与外部SSRAM的数据接口,可以提供足够的程序运行和数据堆栈资源;SPI组件实现与采集模块其它控制器的通讯;PIO组件实现对外围通用IO口的控制。最后,通过Avalon总线完成各IP组件之间的互连,并分配组件地址空间与中断优先级,并生成SOPC系统。

3 软件设计

3.1 软件模型

软件模型是一种“洋葱”式分层关系,每一层都对该层的实现细节进行了封装,为外层提供数据交换,如图2所示。

图2 软件分层模型

(1) NiosⅡ处理器硬件系统层:以NiosⅡ软核处理器为核心的FPGA片上系统,包含了NiosⅡ及其它硬件外设。(2) 设备驱动层:操作硬件资源的软件函数库,抽象化了外设的运行细节。(3) HAL API函数库:提供了应用程序与底层硬件交互的设备驱动接口,硬件配置与HAL系统库会始终保持同步,大大提高了应用程序的可复用性,使得应用程序不受底层硬件变化的影响。(4)µC/OS-Ⅱ操作系统:为应用程序提供多任务调度与任务间通讯服务。(5)NicheStack TCP/IP Stack:利用套接字的API函数,为用户程序系提供网络服务。这是一款专为低存储资源嵌入式系统设计的网络协议套件,在提供完整TCP/IP网络协议功能的同时减少了资源利用,非常适用于NiosⅡ处理器系统。(6)应用程序系统初始化层:从main()函数中调用µC/OS-Ⅱ操作系统和NicheStack TCP/IP网络协议栈软件组件的初始化函数,同时建立所有的应用任务与信号量、队列、事件标志等实时操作系统内部通讯资源。(7)应用层:位于最外层直接面向用户,供用户实现网络服务功能。

3.2 µC/OS-Ⅱ的移植

与处理器相关代码,主要是对OS_CPU.H、OS_CPU _C.C、OS_CPU_ASM.ASM这三个与处理器相关的文件进行修改。NiosⅡ处理器的C编译器允许在C语言中直接嵌套汇编语言,所以可以将所需的汇编语言代码直接放到OS_CPU_C.C文件中去。与应用相关的代码,OS_CFG.H 用来配置内核,用户根据需要对内核进行定制,设置系统的基本情况;INCLUDES.H 为系统头文件,包括了整个实时系统所需要的内核以及用户的头文件。

茶染艺术的染色方法主要分为直接染色法、同浴媒染法和后媒染色法[8]。其中采用直接染色法可染棕色,采用绿矾同浴媒染法可得皂色,分别用绿矾、铁浆后媒染色法可得莲子褐色和砖褐色。虽然茶叶分为了绿、黄、黑、红、青和白六种,但是每一种下又有多样的品种,不同的品种,其茶色都会有微妙的差别。甚至同一品种下,不同的制作工艺都会造成不同的茶色。除此之外,染色的手法、环境、时间、温度均是影响茶染效果的因素。所以,经过茶染出的成品总是带有独一无二的特性。

(1) 移植OS_CPU.H文件

µC/OS-Ⅱ使用的是可移植的无符号数和有符号数。对于NiosⅡ处理器,在OS_CPU.H中必须定义一系列数据类型以确保移植的正确性,如typedef unsigned short INT16U等。

定义了两个宏OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()来关/开中断,以保护临界代码;定义宏OS_STK_GROWTH来指定堆栈的方向(置0表示堆栈从下往上递增,置1表示堆栈从上往下递减); 定义宏OS_TASK_SW()来模仿中断的产生,以在任务调度时从任务堆栈中恢复处理器的所有寄存器,并执行中断返回指令。

(2) 移植OS_CPU_C.C文件

在OS_CPU_C.C文件中,通过用汇编语言编写OSStartHighRdy()、OSCtxSw()、OSIntCtxSw()、OSTickISR()四个函数,实现对处理器寄存器的操作。

OSStartHighRdy()在多任务系统启动函数OSStart()中调用,功能是让进入就绪态的优先级最高的任务运行;OSCtxSw()是一个任务级的切换函数,切换是通过执行软中断或TRAP(陷阱)来实现的,中断服务子程序、陷阱或异常处理的向量地址必须指向OSCtxSw();OSIntCtxSw()是中断级的任务切换函数,被OSIntExit()调用,在中断服务程序中执行任务切换功能,将默认CPU寄存器保存在被中断了的任务的堆栈中;OSTickISR()是系统时钟节拍中断服务函数,这是一个周期性中断,为内核提供时钟节拍,其周期大小决定了内核所能给应用软件系统提供的最小时间间隔服务。

3.3 以太网接口程序设计

首先读取经过复解调的前端采集数据,然后将数据按固定格式打包,最后通过以太网发送至上位机。同时,通过以太网接收上位机分发的命令参数报文,将命令参数按一定格式传输至采集模块其它控制器,实现上位机对采集模块的实时控制。主要包括NESStackInitialTask()、NESTCPClientServerTask()和NESUDPClientServerTask()三个用户任务。程序流程如图3所示。

图3 TCP/IP或UDP网络数据包

该任务为系统初始化任务,最先在main()函数中创建,初始化NicheStack TCP/IP Stack,并创建操作系统数据结构和其他任务,在三个用户任务中优先级最高。任务完成之后,调用OSTaskDel()使其进入休眠态,不再被操作系统调用。

在任务中,按先后顺序来调用alt_iniche_init() 和netmain()两个函数,其中前者用来初始化协议栈,后者用来初始化和发起NicheStack系统级任务。在此过程中,tk_netmain与tk_nettick两个NicheStack系统级任务会被创建并赋予它们高优先级,前者是网络栈的核心任务,优先级为2;后者是网络栈的时钟管理任务,优先级为3。

此外,NicheStack TCP/IP Stack系统代码在初始化过程中会调用get_mac_addr()和get_ip_addr()函数获得MAC和IP地址。这部分代码必须由程序员亲自编写,可以非常灵活的选择将MAC和IP地址存储在任何地方。我们选择将其写入flash存储器中,上电后直接从flash的指定区域读出。

NicheStack TCP/IP Stack初始化完成后全局变量iniche_net_ready置为真,此时可创建NES_ TCPClientServerTask()和NES_UDPClientServerTask()两个应用NicheStack网络服务的任务。在此之前,需完成一些声明。宏TK_OBJECT用于创建静态任务对象,宏TK_ENTRY定义了任务名称,结构体inet_taskinfo则用于指定任务名、任务优先级和堆栈大小。例如:

TK_NEWTASK()用来创建应用NicheStack网络服务的新任务,是NicheStack TCP/IP Stack与µC/OS-Ⅱ接口的一部分。它通过调用µC/OS-Ⅱ的OSTaskCreate()函数来创建一个新线程,还执行一些NicheStack TCP/IP Stack所需特殊的代码。

最后,在main()函数中调用OSStart()来启动µC/OS-Ⅱ的任务调度程序,完成系统初始化。

(2)NESTCPClientServerTask()

该任务为TCP客户端网络服务任务,实现整个应用程序的关键功能,在三个用户任务优先级中居其次。我们将经过复解调的前端采集数据写入FIFO存储器,利用SGDMA组件从FIFO读出固定大小的数据至片上缓冲区,同样利用SGDMA组件将缓冲区数据送至Triple Speed Ethernet组件,最后按TCP/IP协议发送至以太网。

在NESStackInitialTask()中调用OSSemCreate()创建一个二值信号量NESDataSendSem。在网络传输空闲阶段,本任务调用OSSemPend()将自身挂起,进入等待状态,等待信号量被释放。

设定FIFO的半满标记为中断标志位,当前端数据累计超过FIFO一半存储容量时,产生中断跳转至中断服务程序,调用函数alt_avalon_sgdma_do_ async_transfer()发起DMA传输,然后调用OSSemPost()释放信号量,使本任务进入就绪态。由于该任务优先级较NESUDPClientServerTask()高,因此获得CPU的使用权进入运行态。DMA传输结束后,即可调用标准TCP/IP套接字函数send()发起网络数据传输。传输结束后,本任务再次调用OSSemPend(),进入等待状态,等待下一次网络数据传输的发起。

(3)NESUDPClientServerTask()

该任务为UDP客户端网络服务任务,是接收上位机分发的命令参数报文,任务优先级最低。由于整个采集系统由多个采集模块组成,因此上位机采用UDP协议进行组播。

本任务一直处于运行态,我们用FD_SET()将一个套接字句柄加入到集合中,用select()编写非阻塞方式工作的程序,并用FD_ISSET()进行轮询。当上位机发来命令参数时,FD_ISSET()检查到该句柄可读,于是调用recvfrom()来接收,并调用sendto()返回一条确认报文给上位机,同时发起SPI传输。

4 测试验证

我们对设计开发完毕的以太网接口在TCP/IP协议下的网速及传输可靠性进行了测试。通过网线与一台测试计算机连接,在测试计算机上利用VC++6.0开发测试程序,测试网速和保存数据文件,利用Matlab处理数据并显示结果。

(1) 网速测试

测试发送网速时,接收测试程序调用QueryPerformanceFrequency()函数获取计数器的时钟频率,在以太网接口向测试计算机的发送固定大小的数据包前后,两次调用QueryPerformanceCounter()函数获得计数器的当前计数值,利用recv()接收并返回接收字节数,最终测试1000次后平均发送网速为72.3 Mb/s,满足系统每秒数据量10 Mb的要求。程序如下:

测试接收网速的方法与之相同,只不过是在以太网接口用户程序中分别调用alt_timestamp_freq() 和alt_timestamp()来获取系统计数器的时钟频率和当前计数值。最终测试1000次后平均接收网速为62.4 Mb/s,满足系统需求。

(2)以太网接口可靠性测试

向采集模块输入端注入一定(如26 kHz)频率的连续正弦信号,通过以太网接口传输任意量的数据(如10 GB)至测试计算机,并用Matlab分多批对复解调(移频至1.75 kHz)后的信号做频谱分析,发现数据未出现断点,信号频率保持不变,证明以太网接口可靠,满足设计要求。图4(a)、(b)为随机抽取两个通道的测试结果。

图4(a) 信号频谱图

图4(b) 信号时-频谱图

5 结束语

事实证明,µC/OS-Ⅱ和NiosⅡ相结合,可以构成一种基于可配置片上系统的嵌入式开发平台。该平台软、硬件均可根据用户需求进行剪裁配置,同时方便的利用C语言和TCP/IP标准套接字接口实现了以太网接口功能,具有很好的推广应用价值。

[1] JEAN J LABROSSE . 嵌入式实时操作系统μC/OS-Ⅱ[M]. 2版. 邵贝贝, 译. 北京: 北京航空航天大学出版社, 2003.

[2] ALTERA CORPORATION. Nios II processor reference handbook[M]. 9.0 ed. 2009.

[3] 蔡伟纲. NiosⅡ软件架构解析[M]. 西安: 西安电子科技大学出版社, 2007.

[4] ALTERA CORPORATION. NiosⅡ software developer’s handbook[M]. 9.0 ed. 2009.

[5]多纳霍, 卡尔弗特. TCP/IP Sockets编程(C语言实现)[M]. 2版. 陈宗斌, 译. 北京: 清华大学出版社, 2009.

[6] 罗军舟, 黎波. TCP/IP协议及网络编程技术[M]. 北京:清华大学出版社, 2004.

猜你喜欢
调用中断以太网
基于1500以太网养猪场的智能饲喂控制系统的设计与实现
核电项目物项调用管理的应用研究
LabWindows/CVI下基于ActiveX技术的Excel调用
跟踪导练(二)(5)
千里移防,卫勤保障不中断
谈实时以太网EtherCAT技术在变电站自动化中的应用
基于系统调用的恶意软件检测技术研究
一种90W高功率以太网供电系统的设计
浅谈EPON与工业以太网在贵遵高速公路中的应用
利用RFC技术实现SAP系统接口通信