产品 求购 供应 文章 问题

0431-81702023
LED
嵌入式技术和CPLD 技术在LED 显示屏设计中的实现

摘要:目前,大部分LED 显示屏采用的是8 位或准16 位的微控制器,其运算速度、内存容量、存储空间和通讯方式等方面存在着很大的局限性,对于高难度图文动态特技显示和灰度显示,LED 显示屏很难实现在信息容量和处理速度上要求很高的显示技术。为解决上述问题,作者采用了一套先进的嵌入式技术和CPLD技术,主要完成以下工作内容:

1. 研究大屏幕LED 显示系统的结构和工作原理,分析传统LED 显示控制器的主要不足。

2. 完成基于32 ARM 微处理器的大屏幕LED 显示系统的总体设计,对系统中使用的主要芯片进行选型,并分析了芯片的结构和使用方法。

3. 介绍了嵌入式实时操作系统μC/OS-II, 在该系统中引入TCP/IP 协议栈,以支持嵌入式设备接入网络,这种方式已成为嵌入式领域中重要的研究方向。

4. 设计了基于ARM 微处理器S3C4510B 系统的电源电路、晶振电路和复位电路;对基于S3C4510B 的系统进行了扩展设计,主要包括存储器的接口电路、串行接口电路以及JTAG 接口电路的设计,并初步设计了l0M/100M 以太网接口电路,为以太网提供了接入通道。

5. 对ARM处理器进行嵌入式实时操作系统μC/OS-II 的移植,并提出了移植过程中可能出现的问题。

6. 讨论了复杂可编程逻辑器件CPLD 技术和硬件描述语言VHDLCPLD 器件具有很好的逻辑和时序功能。因此LED 的控制器件选用CPLD,并利用VHDL 开发了LED 显示板的时序功能,实现了对显示屏的灰度控制。

关键词:LED 显示屏, ARMCPLDVHDL,μC/OS-IILwIP

1 章绪论

LED 显示屏是八十年代后期在全球迅速发展起来的新型信息显示媒体,是集微电子技术、光电子技术、计算机技术、信息处理技术于一体的大型显示系统。它以其色彩鲜艳,动态范围广,亮度高,寿命长,工作性能稳定而日渐成为显示媒体中的佼佼者,广泛应用于广告、证券、信息传播、新闻发布等方面,是目前国际上极为先进的显示媒体。

技术的进步推动着人类对需求的不断提高,人类对需求的提高又不断促进着技术的进步。沿着需求和技术发展的方向,本文把嵌入式和CPLD 技术引入到点阵显示项目中,以此实现功能多样、系统强壮、维护方便、面向网络的新型LED 点阵显示系统。

1.1 LED 显示屏开发中存在的问题

在以往的 LED 点阵系统中,采用单板控制系统。整个系统的控制核心是单片机,单片机负责数据的读取、传输和显示。控制过程如图1-1 所示[5]。

这种方案在对显示画面不多、显示画面不大时是方便可行的。但是由于单片机执行指令受时间的限制,当显示画面较大时(画面的点阵数据较多),单片机的速度往往难以满足要求。在传统的方案中,显示画面的数据预先已经存贮在ROM 中;当程序运行时,CPU 依序将ROM 中存储的画面数据输出。当用户希望增加或改动画面时,要重新编写程序,改动不方便。除此之外,LED 显示屏开发中还存在以下几个问题:

1.信息的传送问题

LED 显示屏的通讯传输控制有通讯传输和视频传输两种。通讯传输采用标准的RS232 或RS485 计算机数据串行通讯方式,通过串口按一定的通讯协议接收来自计算机串口或其它设备串口的信号,经过处理后按一定的规律传送到显示屏上显示。这种控制方式的显示屏的功能比较单一,适用于简单文字、图形显示,主要是单色及双基色显示屏控制使用,并且当显示的信息量比较大的时候,需要比较高的数据传输速率,而串行传输的速率是有一定的限制的,最大为1Mbit/s,当距离增大的时候速率会降得更低。视频传输方式则是把LED 显示屏与多媒体技术结合起来,采用成对的专用长线传输接口电路,实现了在LED显示屏上实时显示计算机监视器上的内容,但是对传输线的要求很高,而且接口电路设计比较复杂。

2. LED 显示屏的驱动问题

实现系统图像显示需要对红、绿、蓝LED 器件进行灰度调节。如果三色都能实现8 位灰度可调,就可以形成256×256×256 共16.8 百万种颜色。控制LED

的灰度主要是采用占空比法,将显示一帧的时间分为不同的时间长度子帧,8位共有256 个灰度等级,把时间分8 个不相等的时间区。如此复杂的时序逻辑功能只能由大规模集成电路来实现,通常LED 显示屏使用的是CPLD/FPGA,也有采用专用的芯片,能够完成LED 显示屏的数据传输控制、灰度控制,系统控制等等[1]。

通过一段时间调研发现很多的厂商使用的是开发专用集成芯片的方法,把数据的传输与显示控制集成在一起,但这种方法有几个不足之处,首先,开发难度大,模块化不强,其次,缺乏灵活性,势必延长产品的开发周期。

因此,我们想设计一种具有通信功能、可以受 PC 控制、可以组网的点阵显示系统。这样实现高显示频率和灵活的显示方式。

1.2 新的系统设计方案

1.2.1 系统结构图

点阵显示系统结构如图1-2 所示,点阵显示板通过串口和TCP/IP 协议实现与PC 机的通信及调试。PC 机通过通信端口可以对点阵显示板进行配置,包括显示模式的更改和显示画面的更新。多块点阵显示板还可以组成网络,实现局域网的拓扑结构。多块点阵显示板可以利用TCP/IP 协议或者专门开发的基于串口的协议进行通信[5]。

点阵显示板提供与 LED 显示屏相匹配的接口,包括数据总线、同步脉冲、行选信号线。点阵显示板实现画面点阵的搜索、显示画面点阵的缓存、显示画面点阵移位、LED 行动态扫描等功能。

1.2.2 系统的硬件总体设计

系统硬件以嵌入式芯片S3C4510B 为核心,拥有串口模块、网络模块、LED驱动模块、时钟模块等部分。CPLD 中固化的数字逻辑负责产生屏幕显示控制信号:串行移位时钟、行信号、行选通信号、消影信号等,同时从SDRAM 中读取图像数据,并将其输出到相应颜色的信号数据总线上,同时与微控制器异步通信实现双 SDRAM 读写数据区的切换。如图1-3 所示,是点阵显示系统控制板的主体硬件设计概要。

1.2.3 系统的软件总体构架

系统软件由三部分组成:运行在 LED 控制器上的嵌入式操作系统(Embedded Operating System)μC/OS-II、在该操作系统上运行的应用程序以及运行在远端PC 上的控制与通信程序,基于μC/OS-II 嵌入式系统框图如图1-4 所示:

1.3 课题的主要研究内容

1 章:指出了当前LED 显示屏设计中存在的问题,并提出了新的解决案。

第 2 章:介绍了LED 显示屏系统原理。

第 3 章:阐述了嵌入式实时操作系统μC/OS-II 并进行TCP/IP 协议栈的移植。

第4 章:移植μC/OS-II 到ARM 微处理器。

第 5 章:实现了CPLD 技术在LED 显示屏设计中的应用。

第 6 章:对论文进行了总结与展望。

2 章 大屏幕LED 显示系统原理

2.1 LED 器件发光的基本原理

发光二极管(light emitting diode, LED),是一种把电能变成光能的特种器件,当电流(如图2-1 所示)通过它的时候,可以产生可视的光[16]。

发光二极管的结构主要由 PN 结芯片、电极和光学系统构成。我们知道,发光是一种能量转化现象。当系统受到外界激发后,会从稳定的低能态跃迁到不稳定的高能态,当系统由不稳定的高能态重新回到稳定的低能态时,能量差以光的形式辐射出来,就会产生发光现象。当在PN 结上加以正向电压之后,P区的空穴注入至N 区,N 区的电子注入至P 区,相互注入的电子与空穴相遇后即产生复合,这些少数载流子在结的注入和复合中产生辐射而发光。它是自发辐射发光,不需要较高的注入电流产生粒子数反转分布,也不需要光学谐振腔,发射的是非相干光。

2.2 LED 器件的驱动

从LED 器件的发光机理可以知道,当向LED 器件施加正向电压时,流过器件的正向电流使其发光。因此LED 的驱动就是要使它的PN 结处于正偏置,同时为了控制它的发光强度,还要解决正向电流的调节问题。具体的驱动方式有直流驱动、恒流驱动、脉冲驱动和扫描驱动等。

1.直流驱动

直流驱动是最简单的驱动方法,由电阻R 与发光二极管LED 串联后直接连接到电源Vcc 上,连接时令LED 的阴极接电源的负极方向,阳极接正极方向。只要保证LED 处于正向偏置,发光二极管与电阻的位置可以互换的。直流驱动时LED 的工作点由电源电压Vcc、串联电阻R LED 器件的伏安特性共同决定。对应于工作点的电压电流分别为Vf和If。改变Vcc 的值或R 的值,可以调节If的值,从而调节节LED 的发光强度。如图2-2 所示,这种驱动方式适合于LED器件比较少,发光强度比较恒定的情况,例如目前有的公交车上用于固定显示的“XX 路”字样的显示器上,就可以使用直流驱动。一方面显示的字数很少,另一方面它的显示内容固定不变,因此只要在需要显示的字样的笔画上排列LED发光灯就行了,这样一块屏上大约有100 只管子。采用直流驱动可以简化电路降低造价。直流驱动电路的电源电压和电阻应该仔细选择,以便在满足发光强度的情况下尽量节约电能。

2.恒流驱动

由于LED 器件的正向特性比较陡,加上器件的分散性,使得同样电压和同样的限流电阻的情况下,各器件的正向电流并不相同,引起发光强度的差异。如果能够对LED 正向电流直接进行恒流驱动,只要恒流值相同,发光强度就比较接近(同样存在着发光强度与正向电流之伺各个器件的分散性,但是这种分散性没有伏安特性那么陡,所以影响也就小得多了)。我们知道,晶体管的输出特性具有恒流性质,所以可以用晶体管驱动LED

可以将晶体管与LED 器件串联在一起,这时LED 的正向电流就等于晶体管的集电极电流,如图23 所示,如果直接使用晶体管基极电流控制集电极电流的话,由于晶体管放大倍数的分散性,同样的基极电流,会产生不同的集电极电流。因此应该采用基极电压控制方式,即在发射极中串联电阻Re,这时有Ic≈Ie=(Vb-Vbe)/Re,式中,Vb 为外加基极电压,Vbe 为基极发射极电压,由于晶体管Vbe 的分散性比放大倍数β的分散性要小,所以各LED 器件的正向电流在其Vb 与Re 相同的情况下,基本上可以保证是一致的。此外电压控制方式比电流控制方式更加方便。

3.脉冲驱动

利用人眼的视觉暂留特性,采用向LED 器件重复通断供电的方法使之点燃,就是通常所说的脉冲驱动方式。采用这种方式时应该注意两个问题:脉冲电流幅值的确定和重复频率的选择。首先,要想获得与直流驱动方式相当的发光强度,脉冲驱动电流的平均值I0 就应该与直流驱动的电流值相同。如图2-4 所示,平均电流Ia 是瞬时电流i 的时间积分,对于矩形波来说,有如下表达式:Ia=IF(ton/T)。

其中ton/T 就是占空比的一种描述,为了使脉冲驱动方式下的平均电流1a与直流驱动电流Io 相同,就需要使它的脉冲电流幅值满足IF=(T/ton)Ia=(T/ton)Io

可见脉冲驱动时,脉冲电流的幅值应该比直流驱动电流大T/ton 倍。

其次是脉冲重复频率的问题,通过视觉暂留特性的分析,己经知道脉冲重复频率必须高于24Hz,否则会产生闪烁现象。在实际应用当中,往往采用更高的频率,例如,50HZ60HZ120HZ,甚至高达1920HZ。选择重复频率时,不仅考虑避免闪烁问题,有时还要考虑电路设计方案,重复频率的上限受器件响应速度的限制,无论是LED 器件还是驱动器件,当频率高到一定程度,达到器件无法正常导通和关断的时候,就不能正常工作了,LED 器件的上限工作频率大约在十兆赫到数百兆赫范围内。

脉冲驱动的主要有应用有两个方面:扫描驱动和占空比控制,扫描驱动主要目的是节约驱动电路,简化电路;占空比控制的目的是调节器件的发光强度,多用于图像显示中的灰度级控制。实际应用中,有时脉冲驱动仅反映在扫描驱动方面(偶尔反映在占空比控制方面),而在很多情况下扫描驱动电路与占空比电路两者兼而有之。

采用脉冲驱动方式,就需要有脉冲源,用数字电路提供脉冲源是非常方便的。目前普通TTL 电路的驱动能力,在输出低电平Vol 时约在8~20mA 范围可以直接驱动普通LED 器件,在输出高电平Voh 时约在-200~-400μA 范围。因此采用集成电路直接驱动LED 器件时,可以选择图2-5 所示的高电平和低电平驱动方式,即并串驱动。不难看出,并联驱动实际上是一个电流切换器,当集成电路输出高电平时流过R 的电流通过LED 返回电源;而当输出低电平时流过R 的电流通过集成电路返回电源,这样当然可以控制LED 的通断,但是R中始终有电流流过,增加了耗电量。低电平驱动方式比较合理,只有当集成电路输出低电平进LED 导通,而当输出高电平时LED 既不导通,R 中也没有电流,因而电能的消耗比较合理。

在实际应用中往往 LED 所需要的驱动电流较大,集成电路的输出能力显得不足,这时可以外加晶体管进行驱动,如图所示,外加晶体管与LED 器件的连接同样可以区分为并联与串联两种方式,同样的原因,以采用串联的方式为好.

由于选用PNP 晶体管和NPN 晶体管的不同,还有采用集电极输出与发射极输

出的不同,串联驱动的具体电路又可以分成如图2-6 所示的四种情况:(a)NPN

晶体管集电极输出,(b) NPN 晶体管发射极输出,(c) PNP 晶体管集电极输出,

(d) PNP 晶体管发射极输出。

(a)和(b)两种情况都是输入高电平控制LED 导通,(c) (d)为输入低电平控制LED 导通;考虑到集成电路输出高电平时驱动能力较弱,因此采用PNP 晶体管,在集成电路输出低电平时控制LED 导通比较台适,对于PNP 晶体管驱动的集电极输出与发射极输出两种情况,也可以进行比较。电路(c)为集电极输出,输出电流的大小受放大倍数的影响,不容易一致;而电路(d)的发射极输出可以比较稳定地控制在 LED 的工作电流,因此推荐采用电路(d)。

4.扫描驱动

扫描驱动通过数字逻辑电路,使若干LED 器件轮流导通,用以节省控制驱动电路。

图 2-7 所示为用于对n 个LED 器件进行扫描驱动的电路,假定切换电路在切换过程中没有时间延迟,且每个LED 的导通时间Ton 是相等的,则占空比Ton/T=1/n,此时的驱动电流幅值IF 应该等于相当直流驱动电流I0 的n 倍,才能达到与相当直流驱动一样的效果,当然,IF 之值必须小于该器件的最大允许脉冲幅值电流这样,n 的值就不可能取得太大,否则要不然显示亮度不够,要不然电流超过极限值。一般n 最大值为16,这时的显示亮度大约是直流驱动下能够显示的最大亮度的1/4,这个亮度对于室内的使用,一般能够满足要求,但对于室外应用就不行了,室外应用时,n 可选择为4。

为了说明扫描驱动的具体形式,常用1/n 作为参数进行描述,例如常说采用1/4, 1/8, 1/16 扫描方式等等,图2-8 给出了1/16 扫描电路的原理图,计数器对时钟产生的计数脉冲进行4bit 二进制计数,其输出从0000 到1111 有16 种取值。再通过4/16 译码器进行译码,译码的结果由16 个输出端输出,选择输出低低有效的译码器,译码输出就可以直接点燃相应的LED 了(有足够的驱动能力的话)。

5.占空比控制

在设计扫描驱动方式时,一旦 n 值确定了之后,就由电路保证按1/n 的方式使LED 轮流导通,电路制成后n 值就不能再改变了,也就是其占空比是固定的,这与扫描驱动方式的目的是减少驱动电路有关,在需要进行灰度级显示的情况下,要求随时调整占空比以使LED 达到相当的发光强度。

灰度级控制的具体实现步骤是,首先给定所需要的灰度级,根据灰度级控制占空比,在控制周期T 固定的前提下,就是控制Ton 的大小,能够控制灰度级的多少,是由表示灰度的二进制的位数说明的,例如常用8bit 二进制来表示灰度级,这样就可以显示256 级灰度。如何根据灰度级的值控制Ton 时间的长短,是占空比控制的关键。由于是对时间的控制,所以很自然地就会想到采用定时器来实现。可以用一个8 位二进制计数器对标准时钟进行计数的方法,实现8位灰度级的控制。当给定的灰度级在00HFFH 之间变化时,占空比Ton /T 在00H/FFH(0)~FFH/FFH(1)之间调节。在灰度级为00H 时,一个周期T 内的Ton时间为0;当灰度级为FF 时,Ton=T。8 位计数器对标准时钟CLK 进行计数时,计数器输出的8bit 编码从00H 到FFH 之间变化,反映了所计CLK 脉冲的个数,也就反映了从开始计数到计数器输出为某一值的时间。8bit 计数器每计满 256个CLK 就完成了一个控制周期,之后又从0 开始下一个周期的控制。所以对应于某一灰度级的计数器输出端编码值与计数器计满时的编码(第256 个编码)之比,就是占空比Ton/T。

如何用灰度级的值对计数器的输出进行控制,从而调节显示器导通的时间,是实现灰度级控制的另一个重要问题。常用的方法有两个,一个是使用比较器的方案,另一个是采用具有输入预置功能的计数器的方法。比较器方案对灰度级锁存器中锁存的灰度值与计数输出进行比较,当两者不等时,比较器输出为低(Vol),使LED 点燃;当两者相等时比较器输出为高,使LED 媳灭。这样,从计数器开始计数起,LED 导通直到计数值等于灰度值为止。因而LED的导通时间正好是灰度值乘以CLK 时钟周期。图2-9 中电路只是原理框图的梗概,还有一些辅助部分未能全部表示出来,例如比较器的触发功能(比较相等产生翻转后,不再进行比较,直至下一周期开始再恢复比较)电路复位信号、灰度级锁存器打入信号等。

灰度级控制的另一实现方案,是采用具有输入预置数功能的计数器。这种计数器可以在开始计数之前,先向计数器输入端预置一个数据,然后计数器就从预置数开始向下计数。我们可以把灰度值的补码预置入计数器,从开始计数到计满为止,恰好计了灰度值原码个数的CLK 脉冲,再利用计数器的溢出端作为输出信号控制LED 的关断,就能够实现灰度级控制了。

第二种方案看似简单,实际上却很少应用。原因有二,其一是该方案需要对灰度值求补,因而增加了相应的电路;其二是该方案不便于电路的共用,这是更为重要的原因。方案二的关键部件是可预置数计数器,由于各个LED 器件所需显示的灰度级不同,因此预置的数据就不同,所以必须为每一个LED 器件配备一个可预置数计数器,而无法共用。对比之下,第一种方案的可共用电路较多。首先,计数器是完全可以共用的,因为多个LED 器件尽管显示的灰度级不同,但是计数都是从0 计到FFH,都使用相同的CLK 时钟。如果用一个计数器对多个比较器输出,各个比较器分别对自己的灰度级输入与公共的计数器进行比较,是完全可行的。此外,比较器也可以共用,例如灰度级显示时一个CLK时钟周期大约是2μs,而普通TTL 比较器电路的响应在几十毫微秒范围,因此采用多路器用一个比较器进行多路灰度级比较是可能的。

3 章嵌入式实时操作系统概述

3.1 实时操作系统的特点

实时操作系统(Real Time Operation System RTOS )区别于一般操作系统的是一般操作系统不仅向用户提供开发应用程序的各种API,而且还必须以命令行的形式或图形的形式提供一个界面。但是实时操作系统只有API而没有通常意义下的界面,亦即只有一个核心。在核心里只有操作系统的一些基本功能如任务(线程)调度、存储管理、同步机制、中断管理和API等,而这些功能又可以根据不同的应用系统裁剪或扩充,以便以最小的代码量满足嵌入式系统的需求。实时操作系统的特点是:如果逻辑和时序出现偏差将会引起严重后果。目前有两种类型的实时系统:软实时操作系统和硬实时操作系统。软实时操作系统的宗旨是使各个任务运行的越快越好,并不要求限定某一进程必须在多长时间内完成。硬实时操作系统要求各任务不仅要执行无误而且要做到准时。

实时操作系统是嵌入式应用软件的基础和开发平台。目前大多数嵌入式开发还是在单片机上直接进行,没有RTOS,但仍要有一个主程序负责调度各个任务。RTOS 是一段嵌入在目标代码中的程序,系统复位后先初始化各个任务,然后在RTOS 的调度下,将CPU 时间、中断、I/O、定时器等资源分片的分配给各个任务。从而使系统资源得到很好的利用,并使各任务对事件有更好的响应。

μC/OS-II 读做“Micro COS2",意为“微控制器操作系统版本2",是一个实时内核,主要提供任务管理功能。它是由μC/OS 升级而来的,并且做了很大的改进。μC/OS-II 的使用对象是嵌入式系统,并且很容易移植到不同构架的微处理器上。下面简单介绍一下它的特点:

?? 公开源代码 源代码清晰易读且结构协调,注解详尽,组织有序。

?? 可移植性 绝大部分μC/OS-II 的源代码使用移植性很强的ANSIC 写的,和微处理器硬件相关部分采用汇编写,并且压到了最低限度。只要该处理器有堆栈指针,有CPU 内部寄存器入栈出栈指令就可以移植μC/OS-II。目前uC/OS-II 已经移植到8位、16 位、32 位以及64 位微处理器上。

?? 可裁剪 可以只使用μC/OS-II 中应用程序需要的那些系统服务。这种可裁剪性是靠条件编译实现的。

?? 占先式 μC/OS-II 完全是占先式实时内核,即总是运行就绪条件下优先级最高的任务。

?? 多任务性 可以管理64 个任务,但系统保留了8 个任务,应用程序最多可以有56 个任务。赋予每个任务的优先级必须是不相同的。

?? 可确定性 全部μC/OS-II 的函数调用和服务的执行时间具有可确定性,即它们的执行时间是可知的,进而言之,μC/OS-II系统服务的执行时间不依赖于应用程序任务的多少。

?? 任务栈 每个任务有自己单独的栈,μC/OS-II 允许每个任务有不同的栈空间。

?? 系统服务 μC/OS-II 提供多种系统服务,如邮箱、消息队列、信号量、块大小固定的内存的申请与释放、时间相关函数等。

?? 中断管理 中断可以使正在执行的任务暂时挂起,中断嵌套层数可达255

?? 稳定性与可靠性 μC/OS-II 是基于μC/OS 的,μC/OS 1992年以来己经有好几百个商业应用。μC/OS-II 与μC/OS 的内核是一样的,只不过提供了更多的其他功能。

3.2 实时操作系统μC/OS-II 内核分析

这一节描述μC/OS-II 的主要结构概貌,有以下一些内容[11]:

?? 什么是任务

?? 任务的状态

?? 任务的调度

?? 中断处理

?? 什么是时钟节拍,μC/OS-II 是怎样处理时钟节拍的

?? μC/OS-II 是怎样初始化和启动的

3.2.1 任务

μC/OS-II 可以管理多达64 个任务,但目前版本的μC/OS-II 2 个任务已经被系统占用了。建议用户不要使用优先级为0123 的任务,以及OS_LOWEST_PRIO-3, OS_LOWEST_PRIO-2, OS_LOWEST_PRIO-1,OS_LOWEST_PRIO,因为未来μC/OS-II 版本中,可能会用到这些任务。

必须给每个任务赋以不同的优先级。优先级可以为0OS_LOWEST_PRIO-2。优先级编号越低,任务的优先级越高。μC/OS-II 总是运行进入就绪态的优先级最高的任务。

为了使μC/OS-II 能管理用户任务,必须在建立任务时,将任务的起始地址与其他参数一起传递给下面的2 个函数之一: OSTaskCreate ( ) 或OSTaskCreateExt()。

3.2.2 任务状态

如图3-1 所示:是μC/OS-II 控制下的任务状态转换图。在任一给定的时刻,任务的状态一定是在一下5 种状态之一。

?? 休眠态:任务驻留在程序空间中,还没有交给uC/OS II 管理;

?? 就绪态:任务本身具备运行条件,等待CPU

?? 运行态:任务占有CPU,正在运行;

?? 等待态:等待除CPU 之外的其他资源或条件(如信号量),不能运行;

?? 中断态:正在运行的任务被中断,进入中断服务子程序;

操作系统对任务的管理包括:建立任务、删除任务、改变任务的优先级、挂起和恢复任务,以及获得有关任务的信息。

在μC/OS-II 系统中用户可以通过传递任务地址和其他参数到以下两个函数之一来建立任务OSTaskCreate()或OSTaskCreateExt()。任务可以在多任务调度开始前建立,也可以在其他任务的执行过程中被建立。注意在开始多任务调度(即调用OSStart())前,用户必须建立至少一个任务。任务不能由中断服务程序(ISR)来建立。

动态改变任务的优先级在μC/OS - II 中是允许的,系统是通过调用OSTaskChangePrio()来实现的。注意用户不能改变空闲任务的优先级,但用户可以改变调用本函数的任务或者其他任务的优先级。

删除任务,是指将任务返回并处于休眠状态,只是任务的代码不再被μC/OS-II 调用。在μC/OS-II 中通过调用OSTaskDel()就可以完成删除任务的功能。

挂起和恢复任务是μC/OS-II 的一个附加功能,通过函数OSTaskSuspend()和OSTaskResume()来实现。

3.2.3 就绪表

每个任务被赋予不同的优先级,从0 级到最低优先级0S_LOWEST_PRIO,包括0 OS_LOWEST_PRIO 在内。当μC/OS-II 初始化时, 最低优先级OS_LOWEST_PRIO 总是被赋予空闲任务idle task

每个就绪的任务都放在就绪表(ready list)中,就绪表有两个变量,OSRdyGrp OSRdyTbl[]。在OSRdyGrp 中,任务按优先级分组,8 个任务为一组。OSRdyGrp 中的每一位表示8 组任务中每一组是否有进入就绪态的任务。任务进入就绪态时,就绪表OSRdyTbl[]中的相应元素的相应位也置为1OSRdyGrpOSRdyGrp OSRdyTbl[]之间的关系见图3-2,是按以下规则给出的:

就绪表OSRdyTbl[]数组的大小取决于OS_LOWEST_PRIO。当应用程序中任务数目比较小时,这种安排可以减小OS_LOWEST_PRIO 的值,可以降低μC/OS-IIRAM(数据空间)的需求量。

为确定下一次该哪个优先级的任务运行了,μC/OS-II 中的调度器总是将最低优先级的任务在就绪表中相应字节的相应位置1

3.2.4 任务调度

μC/OS-II 总是运行进入就绪态任务中优先级最高的任务。确定哪个任务优先级最高,下面该哪个任务运行了,这一工作是由调度器(scheduler)完成的。任务级的调度是由函数OSSched()完成的。中断级的调度是由另一个函数OSIntExt()完成的。μC/OS-II 任务调度(task scheduling)的执行时间是常数,与应用程序建立了多少个任务没有关系。

OS_Sched()的所有代码都属临界段代码。在寻找进入就绪态的优先级任务过程中,为防止中断服务子程序把一个或几个任务的就绪位置位,中断是关掉的。为缩短切换时间,OS_Sched()全部代码都可以用汇编语言编写。

3.2.5 任务级的任务切换

调度器确定更重要的任务该运行了,于是调用OS_TASK_SW()进行任务切换。切换的context,其实就是CPU 中的全部寄存器内容,context-switch 就是任务切换。任务切换代码必须恢复该任务在CPU 使用权被剥夺时保存下来的全部寄存器的值,以便让这个任务能继续运行。

OS_TASK_SW()是宏调用,通常含有微处理器的软中断指令,因为μC/OS-II假定任务切换是靠中断级代码完成的。μC/OS-II 需要的是一条处理器指令,其行为就像是硬件中断(所以称为软中断)。μC/OS-II 使用宏定义,将与实际处理器相关的软中断机制封装起来,使之可以在多种处理器开发平台上移植。

3.2.6 μC/OS-II 中的中断

μC/OS-II 中的中断服务程序最好用汇编语言来写,以减少时间上的开销。

1) 中断到来,但还不能被 CPU 识别。也许是因为中断被μC/OS-II 或用户应用程序关了,或者是因为CPU 还没执行完当前指令。

2)(3)一旦CPU 响应了这个中断,CPU 的中断向量(至少大多数微处理器如此)跳转到中断服务子程序。

4) 中断服务子程序保存CPU 的全部寄存器(也叫做CPU context)。

5) 保存完CPU 寄存器之后,中断服务子程序通知μC/OS-II 进入中断服务子程序。做法是调用OSIntEnter(),或者给OSIntNesting 1。还应将堆栈指针保存到当前任务控制块0S_TCB 中。

6) 用户中断服务代码开始执行。中断服务子程序通知某任务去做事的手段是调用以下函数之一: OSFlagPost()OSMboxPost(),OSQPost(),OSQPostFront(),或者OSSemPost()。中断发生并由上述函数发出消息时,接收消息的任务可能是,也可能不是挂起在邮箱、队列或信号量上的任务。

7)中断服务完成后,须调用OSIntExit()。从时序图上可以看出,对被中断了的任务来说,如果没有高优先级的任务被中断服务子程序激活而进入就绪态,那么OSIntExit()只占用很短的运行时间。

8)(9)在这种情况下,CPU 寄存器只是简单地恢复并执行中断返回指令。

10) 如果中断服务子程序使一个高优先级的任务进入了就绪态,则OSIntExit()将占用较长的运行时间,因为这时要做任务切换。

11)(12)新任务的CPU 寄存器内容要被重新装入,并执行中断返回指令。

3.3 μC/OS-II LwIP 协议栈的移植

随着嵌入式系统与网络的日益结合,在嵌入式实时操作系统中引入TCP/IP 协议栈,以支持嵌入式设备接入网络,成为嵌入式领域重要的研究方向。μC/OS-II 是近年来发展迅速的一个开放源码实时操作系统,但它只提供一个实时的任务调度及通信内核,缺少对外围设备和接口的支持,如没有用户接口、文件系统、网络协议、图形界面。作者以开放源代码的嵌入式TCP/IP 协议栈LwIP 为基础,给μC/OS-II 加上了网络支持。图3-4 是μC/OS-II +LwIP 的体系结构。

3.3.1 TCP/IP 概述

目前TCP/IP 己经成为标准的通信协议,广泛应用于网络通信中的TCP/IP 具有如下特点:

1.开发的协议标准、可免费使用以及独立于特定计算机硬件和操作系统的开放方式;

2.独立于特定的物理网络硬件。TCP/IP 可以集成很多不同类型的网络,运行在多种物理传输介质上;

3.地址规划方案使得整个网络中的任务TCP/IP 设备都具有唯一地址;

4.标准化的高层协议提供了多种可靠的用户服务。如表3-1 所示,TCP/IP 协议采用分层结构,每一层负责不同的通信功能,并且每一层都是多个协议的组合。

3.3.2 嵌入式TCP/IP 的特点

传统的TCP/IP 协议的实现过于复杂,需要占用大量系统资源,而嵌入式应用的系统资源往往很有限,并且复杂,传统TCP/IP 并不能满足实时要求。因此需要把传统的TCP/IP 在不违背协议标准的前提下加以改进实现,使其实时性得以提高,占用的资源尽可能少,从而满足嵌入式应用的要求。这种用于嵌入式系统联网的TCP/IP 称为嵌入式TCP/IP,其主要特点是具有实时性、简单性和灵活性。总之,为嵌入式系统提供的网络支持的TCP/IP 协议,为了满足嵌入式系统实时、资源有限和规模可大可小的特点,应具有很好的实时性和一定的可剪裁性,并且代码尽可能精简。

LwIP 是瑞士计算机科学院(Swedish Institute of Computer Science)Adam DunkelS 等开发的一套用于嵌入式系统的开放源代码TCP/IP 协议栈。LwIP 的含义是Light Weight(轻型))IP 协议。LwIP 可以移植到操作系统上,也可以在无操作系统的情况下独立运行。LwIP TCP/IP 实现的重点是在保持TCP 协议主要功能的基础上减少对RAM 的占用,一般它只需要几十K RAM 40K 左右的ROM 就可以运行,这使1wIP 协议适合在低端嵌入式系统中使用。

LwIP 的特性如下:

?? 支持多网络接口下的IP 转发:

?? 支持ICMP 协议;

?? 包括实验性扩展的UDP(用户数据报协议)

?? 包括阻塞控制,RTI,估算和快速恢复和快速转发的TCP(传输控制协议;

?? 提供专门的内部回调接口(Raw API)用于提高应用程序性能;

?? 可选择的Berkeley 接口API(多线程情况下)

3.3.3 移植LwIP 到μC/OS-II 的接口实现

LwIP 协议栈在设计时就考虑到了将来的移植问题,因此把所有与操作系统、硬件及编译器、函数库相关的部份独立出来,放在/src/arch 目录下。因此LwIP 在μC/OS-II 上的实现就是修改这个目录下的文件,其它的文件一般不应该修改。下面分别详述与编译器相关部分、操作系统相关部分和与函数库相关部分的实现原理和过程,具体的代码限于篇幅没有给出。

1.与编译器相关的include 文件

为了实现在μC/OS-II 上运行LwIP,需要修改与编译器和CPU 相关的定义,如数据长度,字的高低位顺序等。这些应该与本文移植μC/OS-II 时定义的数据长度等参数是一致的。如下所示:

#define BYTE_ORDER LITTLE_ENDIAN //ARM7 默认为小端存储系统

//数据类型长度的定义

typedef unsigned char u8_t;

typedef signed char s8_t;

typedef unsigned short u16_t;

typedef signed short s16_t;

typedef unsigned int u32_t;

typedef signed int s32_t;

此外还有一点需要说明:一般情况下C 语言的结构体struct 4 字节对齐的,但是在处理数据包的时候,LwIP 使用的是通过结构体中不同数据的长度来读取相应的数据的,所以,一定要在定义struct 的时候使用_packed 关键字,让编译器放弃struct 的字节对齐。LwIP 也考虑到了这个问题,所以,在它的结构体定义中有几个PACKED_ FIELD_xxx 宏,默认的时候这几个宏都是空的,可以在移植的时候添加不同的编译器所对应的_packed 关键字。比如在LPC2214ARM7 上对应ADS1.2 编译器的定义:

#define PACK STRUCT_FIELD(x)_packed x

#define PACK STRUCT_STRUCT

#define PACK STRUCT_BEGIN

#define PACK STRUCT_END

2. 操作系统相关部份的实现

(1) LwIP 的操作系统封装层((operating system emulation layer)

LwIP 为了适应不同的操作系统,在代码中没有使用和特定操作系统相关的系统调用和数据结构。而是在LwIP 和操作系统之间增加了一个操作系统封装层。操作系统封装层为操作系统服务(定时、进程同步、消息传递)提供了一个统一的接口。操作系统封装层的源代码在lwip/src/core/sys 目录中。而和具体的操作系统相关的代码在lwip/src/arch/sys_arch.c 中。操作系统封装层的主要函数如表32:

LwIP 中进程同步使用信号量(semaphone)和消息传递采用“mbox"(其实在μC/OS-II 的实现中我们使用的是Message Queue 来实现lwip 中的“mbox",后面再对此作详细介绍)

(2) 操作系统封装层接口的实现

sys_arch 中的内容是与操作系统封装层相关的一些结构和函数,主要可以分为以下四个部份:

(1)sys_mem 一信号量

LwIP 中需要使用到信号量机制,所以在sys_arch.c 中应实现信号量结构体struct sys_mem_t 和相关的处理函数,如下所示:

Sys_sem_t sys_sem_new(u8_t count)//创建一个信号量

void sys_sem_free(sys_sem_t sem)//释放并删除一个信号量

void sys_sem_signal(sys_sem_t sem) //发送一个信号量

由于u C/OS-II 己经实现了信号量OS_ EVENT 的各种操作,并且功能和LwIP 上面几个函数的目的功能是完全一样的,所以只要把ucos.h 的函数重新包装成上面的函数,就可以直接使用了。需要注意的是由于μC/OS-II LwIP的时延"timeout”所用的单位不一样,因此要实现相关的转换。

(2)sys_mbox 信箱

LwIP 使用消息队列来缓冲、传递数据报文,因此要在sys_arch.c 中实现消息队列结构sys_mbox_t,以及相应的操作函数:

sys_mbox_t sys_mbox_new(void) //建一个邮箱

void sys_mbox_free(sys_mbox_t mbox) //释放并删除一个邮箱

void sys_mbox_post(sys_mbox_t mbox, void *data)//发送一个消息到箱

void sys_mbox_fetch(sys_mbox_t mbox, void **msg)//等待邮箱中的消息