首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

基于Nios软核CPU的uC/OS-II和LwIP移植 01

基于Nios软核CPU的uC/OS-II和LwIP移植 01

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网络交换信息,就必须支持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的设计分为与处理器类型无关的代码、与处理器类型相关的代码和与应用程序有关的配置代码三部分。这也是uC/OS-II具有良好的可移植性的原因。移植工作主要集中在多任务切换的实现上。这部分代码主要是用来保存和恢复处理器现场(即相关寄存器),因此不能用c语言,只能使用特定处理器的汇编语言完成。在Nios上移植uC/OS-II非常简单,只需修改三个和Nios体系结构相关的文件即可。下面分别介绍这三个文件的移植工作。

       1.1 OS_CPU.H文件
  
       数据类型定义 这部分的移植是和所用的编译器相关的,我们使用的编译器是nios-elf-gcc。需要定义的数据类型包括无符号和有符号的8位、16位和32位整型变量等。
  
       堆栈单位 因为处理器现场的寄存器在任务切换时都将被保存在当前运行任务的堆栈中,所以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() OSCtxSw
       1.2 OS_CPU_C.C文件
  
       该文件必须实现任务初始化时的堆栈设计,也就是在堆栈增长方向上如何定义每个需要保存的寄存器的位置。我们将堆栈空间设计为按任务堆栈空间由高至低依次保存寄存器ra、ISTATUS、r1~r31。

        该文件还需要实现几个操作系统规定的hook函数。通常都实现为空函数。
        1.3 OS_CPU A.S文件(由汇编语言实现)
  
        (1)OSStartHighRdy()函数 此函数是在OSStart()多任务启动后,负责从最高优先级任务的TCB控制块中获得该任务的堆栈指针sp,通过sp依次将CPU现场恢复。这时系统就将控制权交给用户创建的该任务进程,直到该任务被阻塞或者被其他更高优先级的任务抢占CPU。该函数仅仅在多任务启动时被执行一次,用来启动优先级最高的任务执行,以后多任务的调度和切换就由下面的函数来实现。
  
       (2)OSCtxSw()函数 任务级的上下文切换。它是当任务因被阻塞而主动请求CPU调度时被执行的。它的工作是先将当前任务的CPU现场保存到该任务堆栈中,然后获得最高优先级任务的堆栈指针,从该堆栈中恢复此任务的CPU现场,使之继续执行。
  
       (3)OSIntCtxSw()函数 中断级的任务切换,它是在ISR(中断服务例程)中执行任务切换。当发现有高优先级任务就绪,则在中断退出后并不返回被中断任务,而是直接调度就绪的最高优先级任务执行。这样做的目的是能够尽快地让高优先级的任务得到响应,保证系统的实时性。它的原理基本上与任务级的切换相同,但是由于进入中断时已经保存过被中断任务的CPU现场,因此这里就不用再保存。
  
       (4)OSTickISR()函数 时钟中断处理函数。它的主要任务是负责处理时钟中断,调用系统实现的OSTimeTick函数,如果有等待时钟信号的高优先级任务,则需要在中断级别上调度其执行。
  
        (5)OS_ENTER_CRITICAL()函数和OS_EXIT_CRITICAL()函数 分别是进入临界区和退出临界区的宏指令。主要用于在进入临界区之前关中断,在退出临界区的时候恢复原来的中断状态。
         2 LwIP
  
        LwIP是Light-weight Internet 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协议栈通讯。对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上的实现就是修改这个目录下的文件。下面分别说明相应文件的实现。
返回列表