基于nios软核cpu的ucos-ii和lwip移植

上传人:F****n 文档编号:98813551 上传时间:2019-09-14 格式:DOC 页数:11 大小:96KB
返回 下载 相关 举报
基于nios软核cpu的ucos-ii和lwip移植_第1页
第1页 / 共11页
基于nios软核cpu的ucos-ii和lwip移植_第2页
第2页 / 共11页
基于nios软核cpu的ucos-ii和lwip移植_第3页
第3页 / 共11页
基于nios软核cpu的ucos-ii和lwip移植_第4页
第4页 / 共11页
基于nios软核cpu的ucos-ii和lwip移植_第5页
第5页 / 共11页
点击查看更多>>
资源描述

《基于nios软核cpu的ucos-ii和lwip移植》由会员分享,可在线阅读,更多相关《基于nios软核cpu的ucos-ii和lwip移植(11页珍藏版)》请在金锄头文库上搜索。

1、Altera公司推出的Nios软核CPU是一种可配置的通用精简指令集计算RISC(Reduced Instruction Set Computing)嵌入式处理器。它可以与各种外设相结合,构成一个定制的可编程片上系统SOPC(System on Programable Chip)。 嵌入式实时操作系统uC/OS-II是一个非常优秀的实时操作系统RTOS(Real Time Operating System),其性能已得到广泛认可。uC/OS-II的特点有:公开的源代码、可移植、可裁剪、可固化、抢占式内核。TCP/IP是Interenet的基本协议。嵌入式设备要与Internet网络交换信息,就

2、必须支持TCP/IP协议。 尽管uC/OS-II是一个开放源码的RTOS,但是目前它的第三方TCP/IP支持都是商业化的,很少给出源代码。用户需要付费才能获得。通过在Nios上移植uC/OS-II和开放源码的TCP/IP协议栈-LwIP轻量级网络协议(Light-weight Internet Protocol),就可以实现uC/OS-II的网络功能,并建立一套嵌入式网络开发平台。该系统模型示于图1。 uC/OS-II在Nios上的移植 uC/OS-II可以看作是一个多任务的调度器,在这个任务调度器上添加了和多任务操作系统相关的一些系统服务,如信号量、邮箱、消息队列等。uC/OS-II的设计分

3、为与处理器类型无关的代码、与处理器类型相关的代码和与应用程序有关的配置代码三部分。这也是uC/OS-II具有良好的可移植性的原因。移植工作主要集中在多任务切换的实现上。这部分代码主要是用来保存和恢复处理器现场(即相关寄存器),因此不能用c语言,只能使用特定处理器的汇编语言完成。在Nios上移植uC/OS-II非常简单,只需修改三个和Nios体系结构相关的文件即可。下面分别介绍这三个文件的移植工作。1.1 OS_CPU.H文件 数据类型定义 这部分的移植是和所用的编译器相关的,我们使用的编译器是nios-elf-gcc。需要定义的数据类型包括无符号和有符号的8位、16位和32位整型变量等。 堆栈

4、单位 因为处理器现场的寄存器在任务切换时都将被保存在当前运行任务的堆栈中,所以OS_STK数据类型应该与处理器的寄存器长度一致。 typedef unsigned int OS_STK; 堆栈增长方向 堆栈由高地址向低地址增长,这和选择的编译器有关。 #define OS_STK_GROWTH 1 宏定义(包括开、关中断的宏定义,以及进行任务切换的宏定义) #define OS_ENTER_CRITICAL() disable_interrupt(); #define OS_EXIT_CRITICAL() enable_interrupt() #define OS_TASK_SW() OSCt

5、xSw 1.2 OS_CPU_C.C文件 该文件必须实现任务初始化时的堆栈设计,也就是在堆栈增长方向上如何定义每个需要保存的寄存器的位置。我们将堆栈空间设计为按任务堆栈空间由高至低依次保存寄存器ra、ISTATUS、r1r31。 该文件还需要实现几个操作系统规定的hook函数。通常都实现为空函数。 1.3 OS_CPU A.S文件(由汇编语言实现) (1)OSStartHighRdy()函数 此函数是在OSStart()多任务启动后,负责从最高优先级任务的TCB控制块中获得该任务的堆栈指针sp,通过sp依次将CPU现场恢复。这时系统就将控制权交给用户创建的该任务进程,直到该任务被阻塞或者被其他

6、更高优先级的任务抢占CPU。该函数仅仅在多任务启动时被执行一次,用来启动优先级最高的任务执行,以后多任务的调度和切换就由下面的函数来实现。 (2)OSCtxSw()函数 任务级的上下文切换。它是当任务因被阻塞而主动请求CPU调度时被执行的。它的工作是先将当前任务的CPU现场保存到该任务堆栈中,然后获得最高优先级任务的堆栈指针,从该堆栈中恢复此任务的CPU现场,使之继续执行。 (3)OSIntCtxSw()函数 中断级的任务切换,它是在ISR(中断服务例程)中执行任务切换。当发现有高优先级任务就绪,则在中断退出后并不返回被中断任务,而是直接调度就绪的最高优先级任务执行。这样做的目的是能够尽快地让

7、高优先级的任务得到响应,保证系统的实时性。它的原理基本上与任务级的切换相同,但是由于进入中断时已经保存过被中断任务的CPU现场,因此这里就不用再保存。 (4)OSTickISR()函数 时钟中断处理函数。它的主要任务是负责处理时钟中断,调用系统实现的OSTimeTick函数,如果有等待时钟信号的高优先级任务,则需要在中断级别上调度其执行。 (5)OS_ENTER_CRITICAL()函数和OS_EXIT_CRITICAL()函数 分别是进入临界区和退出临界区的宏指令。主要用于在进入临界区之前关中断,在退出临界区的时候恢复原来的中断状态。 2 LwIP LwIP是Light-weight Int

8、ernet Protocol的缩写,即轻量级网络协议。LwIP是瑞典计算机科学院的Adam Dunkels等开发的用于嵌入式系统的TCP/IP协议栈。LwIP实现的重点是在保持TCP/IP协议主要功能的基础上减少对RAM的占用,一般它只需要几十KByte的RAM和40K左右的ROM就可以运行,适于在嵌入式系统中使用。 在LwIP中,所有TCP/IP协议栈都在一个进程当中。应用层程序既可以是单独的进程,也可以驻留在TCP/IP进程中。如果是单独的进程,可以通过操作系统的邮箱、消息队列等和TCP/IP进程进行通讯;如果驻留TCP/IP进程中,那么利用内部回调函数接口(Raw API)和TCP/IP

9、协议栈通讯。对uC/OS-II来说,进程就是一个任务。LwIP的进程模型 (Process Model)示于图2。在图2中,整个TCP/IP协议栈都在同一个任务(tcpip_thread)中。应用层程序既可以是独立的任务(图中的tftp_thread和cpecho_thread),也可以在tcpip_thread中利用内部回调函数接口和TCP/IP协议栈通讯。 3 LwIP在uC/OS-II上的移植 在设计LwIP时,就考虑到移植问题,所有与操作系统、编译器相关的部分被独立出来,放在/src/arch目录下。因此,LwIP在uC/OS-II上的实现就是修改这个目录下的文件。下面分别说明相应文件

10、的实现。 3.1 与CPU或编译器相关的include文件 在LwIP/src/arch/include/arch目录下,cc.h、cpu.h、perf.h中有一些与CPU或编译器相关的定义,如数据长度、字的高低位顺序等。这应该与用户实现uC/OS-II时定义的参数一致。通常,c语言的结构体(struct)是4字节对齐的,但是在处理数据包的时候,LwIP是通过结构体中不同数据的长度来读取相应的数据的,所以,一定要在定义struct的时候使用_packed关键字,让编译器放弃struct的字节对齐。LwIP也考虑到了这个问题,所以,在它的结构体定义中有几个PACK_STRUCT_xxx宏,在移植

11、的时候添加编译器所对应的_packed关键字。比如在nios-eft-gcc上对应的定义为: #define PACK_STRUCT_FIELD(x) x_attribute_(packed) #define PACK_STRUCT_STRUCT _attribute_(packed) 3.2 sys_arch操作系统相关部分 sys_arch.hc中的内容是与OS相关的一些结构和函数,主要可以分为四个部分: 3.2.1 sys_sem_t 信号量 LwIP中需要使用信号量进行通信,所以在sys_arch中应实现信号量结构体和处理函数: struct sys_sem_t sys_sem_new

12、() /创建一个信号量结构 sys_sem_free() /释放一个信号量结构 sys_sem_signal() /发送信号量 sys_arch_sem_wait() /请求信号量 由于uC/OS-II已经实现了信号量OS_EVENT的各种操作,并且功能和LwIP上面几个函数的功能是完全一样的,所以只要把uC/OS-II的函数重新封装成上面的函数就可以了。 3.2.2 sys_mbox_t消息 LwIP使用消息队列来缓冲、传递数据报文,因此要在sys_arch中实现消息队列结构 sys_mbox_t以及相应的操作函数: sys_mbox_new() /创建一个消息队列 sys_mbox_fre

13、e() /释放一个消息队列 sys_mbox_post() /向消息队列发送消息 sys_arch_mbox_fetch() /从消息队列中获取消息 uC/OS-II虽然实现了消息队列结构OS_Q及其操作,但是uC/OS-II没有对消息队列中的消息进行管理,因此不能直接使用,必须在uC/OS-II的基础上重新实现。为了实现对消息的管理,我们定义了以下结构: typedef struct OS_EVENT *pQ: void *pvQEntriesMAX_QUEUE_ENTRIES; sys_mbox_t; typedef PQ_DESCR sys_mbox_t; /LwIP中的mbox是UCO

14、S的消息队列 该结构包括OS_EVENT类型的队列指针(pQ)和队列内的消息(pvQEntries)两部分,对队列本身的管理利用uC/OS-II自己的消息队列相关函数来完成,然后使用uC/OS-II中的内存管理模块实现对消息的创建、使用和删除,两部分综合起来便实现了LwIP的消息队列功能。 3.2.3 sys_arch_timeout函数 LwIP中每个与外界网络连接的线程都有自己的timeout属性,即等待超时时间。这个属性表现为每个线程都对应一个sys_timeout结构体队列,它包括这个线程的timeout时间长度,以及超时后应调用的timeout函数,该函数会做一些释放连接、回收资源的

15、工作。timeout结构体已经在sys.h中定义好了,而且对结构体队列的数据操作也由LwIP负责,我们所要实现的是如下函数: struct sys_timeouts *sys_arch_timeouts(void) 这个函数的功能是返回目前正处于运行状态的线程所对应的timeout队列指针。timeout队列属于线程的属性,因此是与操作系统相关的函数,只能由用户实现。 3.2.4 sys_thread_new创建新线程函数 LwIP可以是单线程运行,即只有一个tcpip线程(tcpip_thread),负责处理所有的TCP(Transmission Control Protocol:传输控制协议)或UDP(User Datagram Protocol:用户数据报协议)连接,各种网络程序都通过tcpip线程与网络交互。它也可以多线程运行,以提高效率。这时就需要用户实现创建新线程的函数: void sys_thread_new(void(*thread)(void *arg),void *arg); 在uC/OS-II中,没有线程(thread)的概念,只有任务(Task)。它提供了创建新任务的系统调用OSTaskCreate,因此只要把OSTaskCreate封装一下,就可以实现sys_

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 办公文档 > 教学/培训

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号