kaiyun官方注册
您所在的位置: 首页> 嵌入式技术> 设计应用> 基于μC/OS-II操作平台的嵌入式电网监测仪的研制
基于μC/OS-II操作平台的嵌入式电网监测仪的研制
刘冬明,刘军良
常州轻工职业技术学院 电子与电气工程系,江苏 常州213164
摘要:μC/OS-II是一种适用于嵌入式系统的源码开放的占先式实时多任务操作系统。本文讨论了基于μC/OS-II嵌入式系统的网络通信实现,包括μC/OS-II实时操作系统、LwIP协议栈的移植和网络设备驱动程序的建立以及系统任务的调度。
Abstract:
Key words :

摘 要:μC/OS-II是一种适用于嵌入式系统的源码开放的占先式实时多任务操作系统。本文讨论了基于μC/OS-II嵌入式系统的网络通信实现,包括μC/OS-II实时操作系统、LwIP协议栈的移植和网络设备驱动程序的建立以及系统任务的调度。
关键词:μC/OS-II操作系统 LwIP协议栈RTL8019AS驱动程序 系统任务

  嵌入式电网监测仪使用了嵌入式实时操作系统μC/OS-II和 LwIP协议栈,并成功运行在由S3C44BOX微处理器和RTL8019AS以太网控制器组成的硬件平台。在实时操作系统和LwIP协议栈的驱动下,由微处理器实现数据采集、数据处理和采集模块的控制功能,而以太网控制器通过以太网接收远程主机的命令和向远程主机发送采集数据及当前状态信息。
1 μC/OS-II的移植
  μC/OS-II是一种源码公开且被广泛应用、结构小巧、具有可剥夺实时内核的免费嵌入式操作系统。其内核提供任务调度与管理、时间管理、任务间同步与通信、内存管理和中断服务等功能。它适合小型控制系统,具有执行效率高、占用空间小、实时性能优良和可扩展性强等特点,最小内核可编译至2KB。
  移植μC/OS-II时,系统可以运行于用户模式(User Mode),也可以运行于管理模式(Supervision Mode),大部分的移植都运行于管理模式。如果需要,也可以设置为在用户模式运行,但进行处理模式的切换时必须由异常处理完成,这样操作要复杂一些。
  下面介绍在本系统中进行μC/OS-II移植时需要解决的主要问题。
  (1)OS_CPU.H修改
此修改主要是改变与处理器、编译器有关的数据类型和宏定义,S3C44BOX为32位微处理器,使用armcc编译器。Char类型长度8位,Short类型长度16位,Int和Long类型长度32位。ARM 寄存器都是32 位的,所以将堆栈数据类型OS_STK 声明为32位。所有的堆栈都必须使用OS_STK 声明。
  将开关中断的宏OS_ENTER_CRITICAL和OS_EXIT_CRITICAL定义为OS_CPU_ASM.S中的函数ARMDisableINT和ARMEnableINT,用于屏蔽中断和开中断。
  (2)OSTaskStkInit( )
  OSTaskCreate( )和OSTaskCreateExt( )通过调用OSTask-StkInit( )来初始化任务的堆栈结构,因此,堆栈看起来就像刚发生过中断并将所有的寄存器保存到堆栈中的情形一样。
  μC/OS-II为每个任务建立堆栈,用于保存处理器的寄存器。其结构体定义OS_STK[17],任务堆栈空间由高至低依次保存着处理器工作模式(SVC模式)的pc、lr、r12、r11、r10……r1、r0、CPSR、SPSR。
  μC/OS-II在OS_CPU_C.C中由任务堆栈初始化函数OSTaskStkInit,需要将任务栈内的CPSR 和SPSR 设为SVC 模式。
  (3)OSCtxsw( )
  用于任务级的上下文切换。当任务因为被阻塞而主动请求CPU调度时OSCtxsw( )被执行,此时的任务切换在非异常模式下进行。它的工作是先将当前任务的CPU现场保存到该任务堆栈中,然后获得最高优先级任务的堆栈指针,从该堆栈中恢复此任务的CPU现场,使之继续执行。这样就完成了一次任务切换。
  (4)OSIntCtxSW( )
  用于中断级的任务切换。若在时钟中断ISR中发现有高优先级任务等待的时钟信号到来,则在中断退出后并不返回被中断任务,而是直接调度就绪的高优先级任务执行,从而能够尽快地使高优先级的任务得到响应,保证系统的实时性能。
  OSIntCtxSW( )完成的工作为:向S3C44BOX的INTCON寄存器写入值,将IRQ栈内保存的中断CPU寄存器的值写入被中断的任务栈,将就绪的高优先级的任务栈内容写入对应的CPU 寄存器。
  (5)OSTickISR( )
  时钟中断处理函数。其主要任务是负责处理时钟中断,调用系统实现OSTimeTick( )函数,如果有等待时钟信号的高优先级任务,则需要在中断级别上调度其执行。
  OSTickISR( )是标准的中断服务程序,函数的入口写入ISR的中断向量表。其实现的过程是:向S3C44BOX 的0x18写入任意的数(0x18在ARM中是IRQ的中断入口地址),读取S3C44BOX的状态寄存器清除中断,保护CPU寄存器入栈,调用OSIntEnter( )对中断嵌套标志加1。调用中断服务程序OSTimeTick( ),调用OSIntExit( )判断是否需要任务切换,如果需要则调用OSIntCtxSW( )来进行任务切换。若没有调用任务切换函数OSCtxsw( ),则说明CPU寄存器入栈的工作已经在进入中断时完成。
2 LwIP协议栈的移植
  LwIP是瑞士计算机科学院的Adam Dunkels等开发的一套用于嵌人式系统的开放源代码TCP/IP协议栈。LwIP的含义是Light Weight(轻型)IP协议,包括带IP和ICMP的TCP和UDP传输层,一个可选的BSD套接字API,还有一个零拷贝API。 LwIP实现的重点是在保持TCP协议主要功能的基础上,减少对RAM的占用。一般它只需要几十KB的RAM和40KB左右的ROM就可以运行,这使LwIP协议栈适合在低端嵌入式系统中使用。
  下面介绍在μC/OS-II操作平台上移植LwIP的主要步骤。
2.1 与CPU或编译器相关的include文件
  /src/arch/include/arch目录下cc.h、cpu.h、perf.h中,有一些与CPU或编译器相关的定义,如数据长度、字的高低位顺序等,这些参数应该与实现μC/OS-II时定义的数据长度等参数是一致的。
2.2 改写操作系统相关的函数
  sys_arch.c中具有与操作系统相关的一些结构和函数,主要可以分为三个部分。
  (1)进程间通信的函数
  函数sys_sem_new( )、sys_sem_free( )、sys_sem_signal( )、sys_arch_sem_wait( )、sys_mbox_new( )、sys_mbox_free( )、sys_mbox_post( )、sys_arch_mbox_fetch( )的功能在μC/OS-II中基本都有,但要注意这里的mbox要用μC/OS-II中的消息队列实现。但是,μC/OS-II没有对消息队列中的消息进行管理,因此不能直接使用,必须在μC/OS-II的基础上重新实现。而有一些mbox只可能有一个消息,可以用邮箱实现。另外函数sys_sem_free( )和sys_mbox_free( )不易实现,可以采用从空闲队列中动态分配和回收的方法。
  (2)sys_arch_timeout( )
  LwIP中每个与外界网络连接的线程都有自己的timeout属性,即等待超时时间。这个属性表现为:每个线程都对应一个sys_timeout结构体队列,包括这个线程的timeout时间长度以及超时后应调用的timeout函数,该函数可以做一些释放连接和回收资源的工作。如果一个线程对应的sys_timeout为空(NULL),说明该线程会对连接做永久的等待。
  (3)sys_thread_new( )
  LwIP可以是单线程运行,即只有一个tcpip线程(tcpip_thread),负责处理所有的tcp/ucp连接,各种网络程序都通过tcpip线程与网络交互。但LwIP也可以多线程运行,以提高效率,降低编程复杂度。
  创建新线程的函数为:
  void sys_thread_new(void(*thread)(void*arg),void*arg)
  在μC/OS-II中,没有线程(thread)的概念,只有任务(task)。它已经提供了创建新任务的系统API调用OSTask-Create。因此,只要把OSTaskCreate封装一下,就可以实现sys_thread_new。需要注意的是:LwIP中的thread并没有μC/OS-II中优先级的概念,实现时要由用户事先为LwIP中创建的线程分配好优先级。
2.3 lib_arch中库函数的实现
  在ARM SDT 2.开发环境下,gcc编译器的lib库里已经有了LwIP协议栈中系统CPU或编辑器有关的外部函数:strlen( )、strcmp( )、bcopy( )、bzero( ),只需要编写htons( )、ntohs( )、htonl( )、ntohl( )即可。
3 网络设备驱动程序
  基于RTL8019AS网络芯片驱动的编写,主要是进行相关寄存器的设置。以太网控制器RTL8019AS通过MAC引擎实现接收、装配发送物理帧,并能与系统微处理器通过ISA总线交换数据。LwIP协议栈中,网络接口层负责接收上层的IP数据报,装配成不完整的物理帧后复制到控制器片内RAM中,并通过控制器发送到传输介质上,发送时由控制器装配成完整的物理帧;或者将控制器中缓存的接收到的物理帧先复制到系统内存,然后抽出IP数据报,交给IP层进行处理。修改ethernetif.c文件,实现底层的输入输出。
3.1 网卡初始化函数
  void ethernetif_init(struct netif*netif)用于初始化网卡,在程序启动之初被调用。这里主要完成网卡的复位操作以及通过对各个寄存器赋值,确定网卡的工作方式等。
3.2 网卡发送函数
  函数err_t ethernetif_output(struct netif*netif,struct pbuf*p,struct ip_addr*ipaddr)为IP层传来的IP报文加上以太网包头并通过网络接口发送。RTL8019AS使用远端DMA将封装好的以太网包写到RTL8019AS内部的双口RAM的发送缓冲环中,然后启动本地DMA,网卡自动发送缓冲环里的数据到以太网。
  发送过程有三个步骤:数据包的封装;通过远程DMA将数据包送到数据发送缓冲区;通过RTL8019的本地DMA将数据送入FIFO进行发送。
3.3 网卡接收函数
  函数void ethernetif_input(struct netif*netif)从网络接口接收以太网数据包并把其中的IP报文向IP层发送。网卡对于以太网上目的地为该网卡的包会自动启动本地DMA接收数据,并存放在RTL8019AS芯片内部RAM的接收缓冲环中,然后以中断的方式通知CPU。此时该函数使用远端DMA接收数据到系统的RAM当中。
3.4 中断处理函数
  void ethernetif_isr(void)处理网卡相关的中断,RTL8019AS接收到数据后,就通过中断入口把接收数据的工作交给函数ethernetif_input()来处理。
  在实时多任务环境中,一般采用中断方式处理RTL8019AS的收发。图1是一个典型中断处理程序(ISR)的流程。当主程序响应RTL8019AS的中断时,ISR的入口将根据读取的中断状态寄存器(ISR)的值来确定程序的走向。

4 系统任务
  图2是基于μC/OS-II的嵌入式系统的框架结构。按电网监测系统所要实现的功能,整个系统划分为二个中断程序和五个并行存在的任务层。

  中断程序按其优先级从高到低分别是网络通信和数据采集。将系统的任务按其优先级从高到低顺序排列的次序是:系统监控任务,键盘扫描任务,任务之间的通信,数据运算统计处理任务,液晶显示任务。
  在该电网远程监测系统软件中,系统监视任务优先权最高,最先进入运行态。该任务分别查询每一个被监视的任务是否向其发送消息。如果没有,则该任务进入挂起态。按优先权级别顺序,键盘扫描任务将由就绪态转为运行态。在该任务将要执行完毕时,向系统监视任务发送消息,然后执行延时函数将自身转为挂起态,交出CPU使用权,让其他任务得以执行。此时系统监视任务得到消息转为运行态,继续查询其他被监视任务的运行消息。如果没有,则进入挂起态,再次等待其他被监视任务的运行消息。系统按任务优先级继续执行优先级高的就绪态任务,依次类推。
  中断发生时,系统将强行剥夺运行态任务时CPU的使用权,将它转入中断态并保存相关数据到堆栈区之后,执行中断服务程序。在中断返回时,系统返回函数将重新进行任务调度,将优先权最高的就绪态任务转为运行态。
5 结束语
  本系统应用于某电网监测中,实现电网参数的远程网络监控。系统各项指标完全达到设计要求,并可做到现场无人值守。
参考文献
1 LABROSSE J J(美),邵贝贝.μC/OS-II——源码公开的实时嵌入式操作系统.北京:中国电力出版社,2003
2 Dunkels A.Design and Implementation of the lwIP TCP/IP Stack.Swedish Institute of Computer Science,2001;(2)
3 历宝中,王剑,胡珂.μC/OS-II在配电监测终端仪表中的应用.单片机与嵌入式系统应用,2003;(7)

此内容为AET网站原创,未经授权禁止转载。
Baidu
map