嵌入式系统设计大学教程 - 习题与解答(4)

2019-03-09 19:42

memset(dev->priv, 0, sizeof(struct net_local)); }

dev->base_addr = ioaddr;

lp = (struct net_local *)dev->priv; ??

/* 取得芯片类型*/

rev_type = readreg(dev, PRODUCT_ID_ADD); lp->chip_type = rev_type &~ REVISON_BITS; lp->chip_revision = ((rev_type & REVISON_BITS) >> 8) + 'A'; lp->send_cmd = TX_AFTER_ALL; ??

/*注册接口方法*/

dev->open = net_open; dev->stop = net_close;

dev->hard_start_xmit = net_send_packet; dev->get_stats = net_get_stats;

dev->set_multicast_list = &set_multicast_list; dev->set_mac_address = &set_mac_address; ??

ether_setup(dev); }

(2)编写设备打开函数与关闭函数

打开和关闭一个网络接口是由ifconfig命令来完成的。当使用ifconfig为一个接口赋地址时,它完成两项工作。第一,它通过ioctl(SIOCSIFADDR)(即Socket I/O Control Set InterFace ADDRess)来赋地址;第二,它通过ioctl(SIOCSIFFLAGS)(即Socket I/O Control Set InterFace FLAGS)对dev->flag中的IFF_UP置位来打开接口。

CS8900A是一个ISA设备,不支持共享中断,但是这在嵌入式系统外设比较少的情况下对系统的性能没什么影响。另外,在接口可以和外界通信以前,还需要将芯片上的硬件地址复制到dev->dev_addr指针指向的空间上,这个工作也可以在初始化函数cs89x0_probe1中完成。

设备打开函数net_open的基本流程如下:

① 没有在初始化函数中注册中断号和I/O地址,则在设备打开时要进行注册;

② 将该设备挂到irq2dev_map中。若使用基于中断的数据接收方式,以后就可以通过中断号和irq2dev_map数组直接查找相应的设备了;

③ 初始化物理设备的寄存器;

④ 设置接口相应的dev的私有数据结构(dev->priv)中的一些字段; ⑤ 设置dev中的tbusy,interrupt和start等字段。 设备关闭函数net_close()与打开函数动作相反。 (3)数据包发送/接收函数的编写

在CS8900A芯片的I/O模式下,数据包的发送流程

① 发送一个传输命令到TxCMD端口(I/O base + 0004h),使芯片进入发送状态; ② 将要发送数据帧的长度发送到TxLength端口(I/O base + 0006h);

③ 通过信息包指针端口(I/O base +000Ch)读取Burst寄存器(寄存器18),判断Rdy4TxNOW位(第8位)的值。如果Rdy4TxNOW值为1,则跳到第4步;如果Rdy4TxNOW

位的值为0,驱动程序将等待一段时间,再判断Rdy4TxNOW的值,直到它为1为止。另外,如果程序中Rdy4TxiE(寄存器BufCFG的第8位)被置为1,当CS8900A的发送缓冲区可写时,Rdy4Tx(寄存器BufEvent的第8位)将被置为1,并触发一个中断,这时候就不需要判断Rdy4TxNOW了;

④ 程序发送函数将反复执行写指令,将数据发送到接收/发送数据端口(I/O base +0000h)。

net_rx()函数的操作流程如下:

① 申请skb缓存区存储新的数据包; ② 从硬件中读取新到达的数据;

③ 调用函数netif_rx(),将新的数据包向网络协议的上一层传送; ④ 修改接口的统计函数。 4)中断处理函数的编写

一般的中断服务程序的基本流程如下: ① 确定发生中断的具体网络接口

② 打开标志位dev->interrupt,表示本服务程序正在被使用;

③ 读取中断状态寄存器,根据寄存器判断中断发生的原因。有两种可能,一种是有新数据包到达;另一种是上次的数据传输已完成。

④ 若是因为有新数据包到达,则调用接收数据包的子函数net_rx();

⑤ 如果中断是上次传输引起,则通知协议的上一层,修改接口的统计信息,关闭标志位tbusy,为下次传输做准备;

⑥ 关闭标志位interrupt。

CS8900A驱动程序的中断处理函数的实现代码如下:

void cs8900_interrupt(int irq, void *dev_id, struct pt_regs * regs) {

struct device *dev = (struct device *)(irq2dev_map[/* FIXME */0]); struct net_local *lp; int ioaddr, status; dev = irq2dev_map[0]; dev->interrupt = 1;

ioaddr = dev->base_addr;

lp = (struct net_local *)dev->priv; while((status = readword(dev,ISQ_PORT))){ switch(status & ISQ_EVENT_MASK){ /*判断中断类型*/ case ISQ_RECEIVER_EVENT: net_rx(dev); /*获取信息包*/ break;

case ISQ_TRANSMITTER_EVENT: lp->stats.tx_packets++; dev->tbusy = 0;

mark_bh(NET_BH); /*通知上层*/ if((status & TX_OK) == 0) lp->stats.tx_errors++;

if(status & TX_LOST_CRS) lp->stats.tx_carrier_errors++; if(status & TX_SQE_ERROR) lp->stats.tx_heartbeat_errors++; if(status & TX_LATE_COL) lp->stats.tx_window_errors++;

if(status & TX_16_COL) lp->stats.tx_aborted_errors++; break;

case ISQ_BUFFER_EVENT:

if(status & READY_FOR_TX){ dev->tbusy = 0;

mark_bh(NET_BH); /*通知上层*/ }

if(status & TX_UNDERRUN){ lp->send_underrun++;

if(lp->send_underrun > 3) lp->send_cmd = TX_AFTER_ALL; }

break;

case ISQ_RX_MISS_EVENT:

lp->stats.rx_missed_errors += (status >>6); break;

case ISQ_TX_COL_EVENT:

lp->stats.collisions += (status >>6); break; } }

dev->interrupt = 0; return;}

第8章 用户图形接口GUI

1、简述嵌入式系统对GUI的基本要求。(P206)

答:GUI在嵌入式系统或者实时系统中的地位将越来越重要,这些系统对GUI的基本要求包括:轻型、占用资源少、高性能、高可靠性、可配置、可移植等特点。

? 体积小 谈到“嵌入”,真的是除了小还是小,现在PC的存储器动辄就是以GB论,对于嵌入式的硬件来说根本是不可能的奢求,大部分的嵌入式系统用的Flash大都以16MB或者32MB为主,与PC简直是天壤之别,所以这样苛刻的环境底下只有尽量减小软件的体积了。

? 消耗系统资源少

对于手持式设备如PDA、手机等,最注重的就是系统资源及省电功能,在省电的前提下CPU速度就不能太高,运算速度越快越耗电,而且散热也会成为很大的问题。对于非手持式设备如Set Top Box、部份WebPAD等,这类系统主要考虑的是硬件的成本,所以嵌入式系统的CPU速度不如PC机,存储容量也小得多,因此GUI系统面临着另一种挑战,必须谨慎使用系统资源,不能有任何无谓的浪费。

? 系统独立

嵌入式系统的一大特色就是硬件差异很大,不像PC机全部都是X86架构。尽管底层硬件差异很大,上层的GUI系统仍然需要表现出统一的界面,所以嵌入式GUI系统必须尽量与硬件划清界限,最好的设计是在GUI系统与硬件中间有一层系统负责隔离,在这方面,Linux Kernel已经可以扮演这个角色。

? 可配置、可移植

嵌入式系统往往是一种定制设备,它们对GUI的需求也各不相同。举个简单的例子,有的系统只要求一些图形功能,而有些系统要求完备的GUI支持。因此,GUI自身也必须是可定制的。

2、简述目前常见的嵌入式GUI系统的特点。(P207~210)

答:目前主流的嵌入式GUI系统主要有MicroWindows、Qt/Embedded、Tiny-X Windows、OpenGUI和MiniGUI等。由于嵌入式系统之间在特定应用环境下的差异,这些GUI系统在其结构、实现方法、使用方法、应用范围等方面也都有各自的特点。

(1)MicroWindows

MicroWindows是一个著名的开源嵌入式GUI软件,目的是把现代图形视窗环境引入到运行Linux的小型设备和平台上,作为X Windows的替代品。它支持多线程,但必须使用PThread库。MicroWindows是一个典型的基于Client/Server体系结构的GUI系统,采用分层结构。

(2)OpenGUI

OpenGUI分为三层:最低层是由汇编编写的快速图形引擎;中间层提供了图形绘制API,包括线条、矩形、圆弧等,并且兼容于Borland的BGI API;第三层用C++编写,提供完整的GUI对象集。OpenGUI采用LGPL条款发布。OpenGUI比较适合于基于x86平台的实时系统,可移植性稍差,目前的发展也基本停滞。 (3)Tiny-X Windows

以X Windows System搭配Tiny-X Server架构来说,最大的优点就是弹性与开发速度。因为与桌面的X Windows架构相同,因此相对于很多以Qt、GTK+、FLTK等开发的软件来说,移植更容易。但因为X Windows系统的运行还需要其他程序和库的支持,包括X Windows管理器、XLib、建立在XLib之上的GTK和Qt等函数库,因此,即使是Tiny-X Windows系统,在运行期间所占用的系统资源也很多,国外使用Tiny-X Windows的环境也多是比较高端的平台。此外,Tiny-X Windows是一个多进程的GUI,它无法运行在很多仅支持多任务(线程)的RTOS上,因此它对于操作系统的兼容性较差,实时性不高。 (4)Qt/Embedded

Qt/Embedded延续了Qt在X上的强大功能,但在底层摒弃了XLib,仅采用FrameBuffer作为底层图形接口。同时,将外部输入设备抽象为keyboard和mouse等输入事件,底层接口支持键盘、鼠标、触摸屏以及用户自定义的设备等。 (5)MiniGUI

MiniGUI是由北京飞漫软件技术有限公司主持的自由软件,遵循GPL条款发布(1.2.6及之前的版本以LGPL条款发布),其目标是为实时嵌入式Linux系统建立一个快速、稳定和轻量级的图形用户界面支持系统。

3、比较MicroWindows、Qt/Embedded和MiniGUI的功能特性。(P210) 答:见表8-1。[略]

4、Qt/Embedded的图形引擎实现基础是什么,其实现结构是怎样的?(P214)

答:Qt/Embedded的底层图形引擎是基于FrameBuffer之上的。FrameBuffer是在Linux内核架构版本2.2以后推出的标准显示设备驱动接口。采用mmap系统调用,可以将FrameBuffer的显示缓存映射为可以连续访问的一段内存指针。 FrameBuffer驱动程序的实现分为两个方面:一方面是对LCD以及其相关部件的初始化,包括画面缓冲区的创建和对DMA通道的设置;另一方面是对画面缓冲区的读写,具体的代

码为read、write、lseek等系统调用接口函数。至于将画面缓冲区的内容输入到LCD显示屏上,则是由硬件自动完成的,对于软件来说是透明的。

5、简述Qt/Embedded窗口系统的工作原理。(P215)

答:Qt/Embedded的窗口系统采用一种客户/服务器体系结构。一个典型的嵌入式Qt窗口系统一般包括:一个服务器进程、一个或多个客户进程。服务器进程负责为客户和其本身分配显示区域、生成鼠标和键盘事件,它通常包含那些启动客户的用户界面,例如应用程序发射台。而客户进程则通过与服务器通信来申请显示区域,接收鼠标和键盘事件。客户可以直接访问所分配的显示区域,以便为用户提供GUI服务。

服务器和客户通过共享内存的方式来传递所有分配显示区域上的信息,如果需要的话还可以维护一个软光标。

6、Qt/Embedded中信号和槽的概念分别是什么?(P216)

答:信号(signal)和槽(slot)是一种高级接口,应用于对象之间的通信,它是QT的核心特性,也是QT区别于其它工具包的重要地方。

当对象改变其状态时,信号就由该对象发射(emit)出去,这就是对象所要做的全部事情,对象并不知道另一端是谁在接收这个信号。这是真正的信息封装,它确保对象被当作一个真正的软件组件来使用。

槽用于接收信号,但它们是普通的对象成员函数。一个槽并不知道是否有任何信号与自己相连接。而且,对象并不了解具体的通信机制。

7、举例说明信号和槽是如何连接的。(P217~218)

答:信号与槽的连接模型如下图所示:

Object1signal1signal2connect(Object1, signal1, Object2, slot1)Connect(Object1, signal1, Object2, slot2)Object2signal1slot1slot2Object3signal1slot1connect(Object1, signal2, Object4, slot1)Object4slot1slot2slot3 通过调用QObject对象的connect函数来将某个对象的信号与另外一个对象的槽函数相关联,这样当发射者发射信号时,接收者的槽函数将被调用。这个函数的作用就是将发射者sender对象中的信号signal与接收者receiver中的member槽函数联系起来。

8、自己动手建立QT/E开发环境(2.x或3.x系列)。(P220~222) 答:[略]

connect(Object3, signal1, Object4, slot3)


嵌入式系统设计大学教程 - 习题与解答(4).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:赢在单词必知:每个人一生必知的英语后缀大全

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: