跳至主要内容

【转】嵌入式系统设计

一直想写操作系统软件设计,可是总是觉得无从下手。嵌入系统不像PC机,硬件是固定的,所以只是考虑软件结构就可以了。
而嵌入系统的软件、操作系统和硬件都有很多选择的余地。
硬件是软件的基础,应用是软件的目的。确定好应用才能决定软件和操作系统的选择,最后才是硬件的选择。
而嵌入系统实现的过程是则必须先完成硬件设计,操作系统移植(或者无操作系统的裸奔),最才是应用软件。
在硬件实现的过程中,操作系统和软件可以同步进行,方法式使用模拟器和开发板,提前把操作系统和软件中通用部分做好,等硬件组工作完成后就可以直接调试了。优点是并行工作,很大程度的加快工作速度,缺点是增加了一些工作量,毕竟,开发板、模拟器和真实的最终硬件是有差别的。
我们当时设计某替代型时,主要考虑该型号的兼容以及成本和工艺简单这几个方面。
我们当时对比了能找到的所有的嵌入CPU,最终,确定以下几种:
1. INTEL pxa255 INTEL pxa270
255是我们一直用的,比较熟悉,270性能好适合多媒体类。
缺点是BGA封装,调试比较麻烦。串口2个。
2. AMD au1200
支持usb2.0高速,含多媒体加速模块,速度极快。缺点是新品,工作量较大。串口少,BGA封装。
3. Cirrus Logical cl93xx
BGA,TQFP均有,串口两个,有网络接口。
4. At91rm9200
BGA,TQFP封装,串口5个,有网络,支持串口启动,IC卡,价格稍高。
5. Winbond arm7
串口多,有网络和IC卡接口。价格便宜,但是,当时连样品都没有。如果当时有现货的话,或许是最好的选择。
当时的原机的是带控制器的LCD,带不带lcd控制器无所谓。最适合替代的是at91rm9200。
至于intel,amd,cl93xx系列有一个多媒体方案,也进行的对比和测试。
Cl93xx性能不足,最先出局。Amd/intel系列作了很长时间的对比。Amd已经停止,主要是没有足够的时间,intel有时间就做,没空就放着。
我们投入力量最大的是at91rm9200,至今已经做了很多款。
第一版的包含了很多测试的硬件所以,但最终软件实现的是我们需要的硬件。其他部分作为备用。
版本一的软件修改包括:
1. boot/loader
这是硬件复位后最初始的程序,主要是完成sdram,flash和其他硬件寄存器的初始化工作。
1) crt0.S 的修改
修正的是一个代码搬移错误不能启动的缺陷,是通过multi-ice发现的。
2) entry.S
加上了启动指示灯,调试用。
3) Makefile/load script
我们的编译器比较新,针对编译器的修改。
4) FLASH/SDRAM的修改
我们使用的是intel flash,单片sdram(虽然硬件是两片)。
这些原来都讲过,具体可以看代码,每个改动都是以patch方式提供的。而且,这些改动需要很清楚硬件手册。
2. u-boot
这个程序相当于pc机的BIOS.
这些修改包括配置、flash支持、sdram、网络PHY。
所有的修改都是针对我们的硬件改动的。
3. kernel/driver
这就是所谓的操作系统,是应用程序和硬件的中间层接口。
修改包括配置、flash支持、sdram、网络PHY, RTC,键盘,MAC错误加密卡支持。
同样,这些修改也是和我们的硬件相关。
4. 键盘、lcd
采用的硬件地址物理映射用户态程序的实现方式,使得ADS调试程序和这个程序一致,便于程序移植。
这些程序也可以用kernel 的driver形式提供,但是,每次这部分的改动都需要改动kernel,这也是改动比较多的地方。
所以用硬件物理地址映射,在用户层实现更合适。
具体实现可以看我们的测试代码:io/lcd19264
Io/scankey
5. 应用程序
我们只是提供了一些例子程序,都在IO目录下。

gztest
工装的所有测试程序
lcd19264
19264 LCD的测试程序
rtc
实时时钟的测试程序
scankey
扫描键盘的测试程序
sed133x
5寸屏的测试程序
usbkey
卡测试程序
vfd-led
VFD led测试程序。

Linux系统移植的一般步骤
Linux是一个开源的世界,绝大多数工作都有前人的基础,工作前,最好找到参考的例子。
Windows基本是封闭的,所以,很多工作需要从头开始,但是只要有钱,很多还是可以买到的。
Linux很容易找到参考的源码,windows可以找到很多容易使用的工具。各有优点。
通常,linux这些参考代码的获得基本都是通过网络。Linux起源于网络,发展也靠网络,我们获取linux的资源也是靠网络。
这是几个常用的网络地址:
www.linuxforum.net 注意是.net,这是国内人气比较好的linux学习网站。
http://freshmeat.net/ 各种开源项目的聚集区,应该是最大的项目网站
www.redhat.com 最大的linux发行版网站。
http://www.ipbx.ru/rm9200/ AT91RM9200 Patches and Utilities
maxim.org.za/at91_26.html AT91RM9200 Linux 2.6 Patches
http://www.at91.com/ atmel arm的各种资料和开发讨论
http://www.atmel.com atmel 的网站
http://bbs.21ic.com/club/bbs/list.asp?boardid=35
arm的硬件讨论区,虽然不是很好,但是是国内我找到的最好的了。
http://bbs.21ic.com/club/bbs/list.asp?boardid=8
嵌入系统硬件讨论区,软件讨论请到前面提到的www.linuxforum.net
作为linux嵌入系统的入门,这几个网站最好多转转。有空多看看,常问的问题经常很可能就是最容易碰到的。
作一套嵌入系统的步骤:
1) 到www.google.com或者www.google.cn中搜索,看看别人对这个cpu的评价和碰到的问题,避免自己重蹈别人的覆辙。
这里有个技巧,很多开发社区,都别封了,不管啥原因吧,反正看不到你所需要的资料。
尤其有些资料是自己急需的,咋办?用代理服务器。
建议安装TOR套件,这个很重要,我很多时候就是靠tor突破网络封锁,看到了很多重要的东西。
用TOR套件可以突破所有的网络封锁,包括我们公司自己的。缺点就是速度慢,但是总比没有好。
Tor支持Socks5,并且支持动态代理链(通过Tor访 问一个地址时,所经过的节点在Tor节点群中随机挑选,动态变化,由于兼顾速度与安全性,节点数目通常为2-5个),因此难于追踪,有效地保证了安全性。 另一方面,Tor 的服务器可以自动获取,因此省却了搜寻代理服务器的精力。
  将Tor和SocksCap32(SocksCap32可以用FreeCap替代)联合使用,将得到一个永远有效的支持Socks5的代理。由于Socks5的代理实在太难找了,所以Tor实在是一大福音。
  这个软件使用起来也很简单。Tor的下载地址是 http://tor.eff.org,先去下载最新版本的TOR和SOCKSCAP32,下载完毕后我们安装TOR,然后我们就可以运行Sockscap32,设置服务器地址为,Socks5:127.0.0.1:9050,然后把你的IE浏览器拉入Sockscap,双击后打开IE,即可通过TOR上网。
不过,我还是建议使用firefox+switchproxy插件,这样更换代理服务器特别容易。随用随换。
关于tor,firefox,switch proxy的具体使用请到google中搜索。
2) 碰到问题,例如编译不通过啦,把关键词 拷贝下来,然后到google中搜索,一般都能找到解决方案,如果该方案看不到,请用tor代理。
如果根本找不到这个问题的答案,一般是这个问题较难,说明开发者里高手距离不远了。
这时候,需要看源码,没办法,只能是用printf把怀疑有问题的地方打印出来。看看系统死在了哪里。
技巧:
printf("%s %s %d\n",__FILE__,__func__,__LINE__) //your name,date
用vi 的yy复制这行,然后p复制,大量复制,这样,程序运行时,就可以直接看到程序运行的位置了。
当然,用GDB软件或者multi-ice,bdi2000等调试工具更好,只是配置起来麻烦,而且硬件的调试器也很贵。(现在有macriagor 的仿真器了,价格便宜很多性能也不错)
支持linux的bdi2000等高档仿真器价格太高,我们也没有。
用printf是没有办法的办法,一般用仿真器搞定问题需要几个小时,而用printf的方法需要1,2个星期。
这主要是程序问题定位的难度,printf只能靠猜测,这就看开发者的水平了,对linux不是很了解的很难找到。而仿真器可以直接跟踪,只要有源码很容易找到故障点。
我们公司有些系统是有调试工具的,如果能用,最好花些功夫熟悉,磨刀不误砍柴工。
我们调试9200曾经碰到过一个问题,就是loader始终不能启动,一直找不到原因(一个多星期),最后就是靠multi-ice跟踪发现问题,很快就改正了。如果没有multi-ice估计工作量还得加上2-3周。但是,multi-ice 不能用到linux环境。
还有,用arm-linux-objdump 可以把各种可执行文件反汇编,甚至包含原程序方式的反汇编。条件是你有源码。不过,有时候我反汇编看不到源码,我一直没找到原因,可能是目录位置的问题。如果谁用功夫可以研究研究。
这样,很多不能用调试工具源码级调试的,用汇编级调试,然后对比用arm-linux-objdump反汇编的代码,就能大致找到问题了。
嵌入系统的开发和调试,很大程度上是各种工具的灵活运用和自身对linux系统的了解。
还有另外一个常用的调试工具:KGDB,这个是内核调试工具,需要给内核打补丁,在嵌入系统上理论上是可用的。不过,原来主要针对的是sgi的系统和x86系统。
所以要针对我们的at91rm9200这类cpu的内核调试,还要就行大量的修改。如果有兴趣可以作为自己学习提高的一个练习题,不过难度很大。需要对内核很清楚才能改好。
KGDB是软件工具,如果有bdi2000之类的仿真器,当然就用不到了。KGDB这类工具就是以时间换金钱,比较适合个人和小公司,很多小公司的项目不到10万,让他花十几万买个仿真器,那赔本大了。
3)驱动程序的编写
找一个类似的驱动,然后修改,一般不需要重写。
例子可以看我们的专用加密卡驱动,这个就是参考的打印机驱动改写的。
linux-2.6.15-20061128-15-usbkey.patch
drivers/usb/class/Kconfig
+config USB_KEY_AERO
+ tristate "AeroSpace USB KEY CARD"
+ depends on USB
+ help
+ Say Y here if you want to connect a USB KEY CARD to your computer's
+ USB port.
+
+ To compile this driver as a module, choose M here: the
+ module will be called usbkey.
+
增加的这部分代码是在make menuconfig中看到卡的配置选项,具体的写法照抄其他部分的,不过,别忘了修改。

/drivers/usb/class/Makefile
+obj-$(CONFIG_USB_KEY_AERO) += usbkey.o
没有这项,你编写的代码就白费了,makefile 就靠这个编译的。

drivers/usb/class/usbkey.c
这是驱动程序的核心,编写是参考其他驱动和具体的硬件设计。关于驱动的具体书写可以从网络搜索或者找本书看看。
4) 驱动程序的调试
驱动调试时一般需要示波器,万用表等硬件工具。还需要能看得懂原理图,pcb图。最好能自己画电路图和pcb图,能熟练使用示波器万用表。所以驱动这块是软件硬件结合的一个部分,难度确实较大。当然对程序也必须很了解,一般最好是作者自己调试。
调试者一定要清楚,这不是单纯的软件,软件执行的步骤对对应硬件的动作。如果出现了你不希望的现象,就要用仿真调试工具(gdb,kgdb,bdi2000)和示波器逻辑分析仪万用表等看看执行你的程序的时候是不是信号如你所愿。然后分析现象,作出合理的判断和修改。
5)完后后的归档
把原文件和修改后的文件对比,制作补丁并说明修改目的。项目不能完全依靠个人,你的补丁,只要能让你的同事看懂就达到要求了。
命令:diff �urN oldcoddir/ newcodedir/ >number-whymodify-date.patch
当然用我们公司的项目管理工具更好,我用这个是因为我比较熟悉而已,毕竟学习一个新东西,需要花功夫,其中要会遇到麻烦。


嵌入系统的发展
这只是个人的一些看法。
恐怕最开始的嵌入系统可能是单片机吧,那时候还不叫嵌入式系统。一般从业者的收入较低,系统简单,通常一个就能搞定。
后来有arm/mips/ppc等,这就是我们现在用的。现在这个家族很庞大。也是主流,从业者的收入较好。主要是因为系统复杂,分工较多,技术含量较高。我们现在就处于这个阶段。这类产品中高端为主,核心芯片叫做SOC(system on chip)。
现在出现了一个新的系统,叫做SOPC。我们这里没有人用过。我做一个简单介绍。
SOPC(System-on-a-Programmable-Chip)是在FPGA/PLD上实现SOC,FPGA的可编程性使SOPC的设计和实现非常方便。用户可以灵活地进行系统硬件和软件设计,还可以在现场进行系统修改。FPGA性能的不断提高,也使SOPC的性能越来越高。
SOPC 包括可定制的cpu(软核)和各种外设。
如果我们用sopc实现,
1) Cpu: NIOSII,arm,minimips,avr,LEON3(spac32) cpu可变的。
2) Sdram控制器:同时可以支持sram,sdram,ddr,ddrII,ddrIII
3) Falsh:nand/nor nand可以支持硬件纠错。
4) 显示屏:可以支持带控制器或者不带控制器的,甚至可以模拟sed133x的时序。
5)串口 数量不限
6)usb、网络 采用外接phy方式实现。这里有一个软解码的网络实现:http://www.fpga4fun.com/10BASE-T.html
其高度灵活性是有优点也是其缺点,灵活则需要更高的技术水平,入门门坎要比arm一类高很多。
成本问题和具体应用有关,不适合特别高性能和特别底成本的场合,这是和FPGA本身的工艺有关的。
现在开源的cpu有很多,高性能的有sun sparc系列,特别考虑成本的甚至有4位的开源cpu,我还找到过一个1位的cpu,真不知道这些作者哪里来的动力。最高端的是sun 的ultra-T1系列,支持8核心,每个核心4个超线程,在系统看来是32个cpu,需要fpga是几百万门。而我见过的1位cpu也就是需要几百门电路而已。
单片机,soc,sopc定位不同,互为补充和竞争,一直会共存。发展潜力不同。对公司来讲,挣钱就行。对个人而言,最好离单片机远点,钱途不好,钱不是万能的,没钱是万万不能的。 至于soc,sopc就看个人能力了。这里面sopc最难,有soc的基础才能深入了解sopc系统。Sopc就是soc加上硬件核心设计。当然,如果想了解sopc的硬件,只用vhdl语言也就可以了。

评论

此博客中的热门博文

【转】VxWorks中的地址映射

在运用嵌入式系统VxWorks和MPC860进行通信系统设计开发时,会遇到一个映射地址不能访问的问题。 缺省情况下,VxWorks系统已经进行了如下地址的映射:   memory地址、bcsr(Board Control and Status)地址、PC_BASE_ADRS(PCMCIA)地址、Internal Memory地址、rom(Flach memory)地址等,但是当你的硬件开发中要加上别的外设时,如(falsh、dsp、FPGA等),对这些外设的访问也是通过地址形式进行读写,如果你没有加相应的地址映射,那么是无法访问这些外设的。   和VxWorks缺省地址映射类似,你也可以进行相应的地址映射。   如下是地址映射原理及实现:   1、 地址映射结构 在Tornado\target\h\vmLib.h文件中 typedef struct phys_mem_desc { void *virtualAddr; void *physicalAddr; UINT len; UINT initialStateMask; /* mask parameter to vmStateSet */ UINT initialState; /* state parameter to vmStateSet */ } PHYS_MEM_DESC; virtualAddr:你要映射的虚拟地址 physicalAddr:硬件设计时定义的实际物理地址 len;要进行映射的地址长度 initialStateMask:可以初始化的地址状态: 有如下状态: #define VM_STATE_MASK_VALID 0x03 #define VM_STATE_MASK_WRITABLE 0x0c #define VM_STATE_MASK_CACHEABLE 0x30 #define VM_STATE_MASK_MEM_COHERENCY 0x40 #define VM_STATE_MASK_GUARDED 0x80 不同的CPU芯片类型还有其特殊状态 initialState:实际初始化的地址状态: 有如下状态: #define VM_STATE_VALID 0x01 #define VM_STATE_VALID_NOT 0x00 #define VM_STATE_WRITA

【转】cs8900网卡的移植至基于linux2.6内核的s3c2410平台

cs8900网卡的移植至基于linux2.6内核的s3c2410平台(转) 2008-03-11 20:58 硬件环境:SBC-2410X开发板(CPU:S3C2410X) 内核版本:2.6.11.1 运行环境:Debian2.6.8 交叉编译环境:gcc-3.3.4-glibc-2.3.3 第一部分 网卡CS8900A驱动程序的移植 一、从网上将Linux内核源代码下载到本机上,并将其解压: #tar jxf linux-2.6.11.1.tar.bz2 二、打开内核顶层目录中的Makefile文件,这个文件中需要修改的内容包括以下两个方面。 (1)指定目标平台。 移植前:         ARCH?= $(SUBARCH) 移植后: ARCH            :=arm (2)指定交叉编译器。 移植前: CROSS_COMPILE ?= 移植后: CROSS_COMPILE   :=/opt/crosstool/arm-s3c2410-linux-gnu/gcc-3.3.4-glibc-2.3.3/bin/arm-s3c2410-linux-gnu- 注:这里假设编译器就放在本机的那个目录下。 三、添加驱动程序源代码,这涉及到以下几个方面。(1)、从网上下载了cs8900.c和cs8900.h两个针对2.6.7的内核的驱动程序源代码,将其放在drivers/net/arm/目录下面。 #cp cs8900.c ./drivers/net/arm/ #cp cs8900.h ./drivers/net/arm/ 并在cs8900_probe()函数中,memset (&priv,0,sizeof (cs8900_t));函数之后添加如下两条语句: __raw_writel(0x2211d110,S3C2410_BWSCON); __raw_writel(0x1f7c,S3C2410_BANKCON3); 注:其原因在"第二部分"解释。 (2)、修改drivers/net/arm/目录下的Kconfig文件,在最后添加如下内容: Config ARM_CS8900    tristate "CS8900 support" depends on NET_ETHERNET && A

【转】多迷人Gtkmm啊

前边已经说过用glade设计界面然后动态装载,接下来再来看看怎么改变程序的皮肤(主题)     首先从 http://art.gnome.org/themes/gtk2 下载喜欢的主题,从压缩包里提取gtk-2.0文件夹让它和我们下边代码生成的可执行文件放在同一个目录下,这里我下载的的 http://art.gnome.org/download/themes/gtk2/1317/GTK2-CillopMidnite.tar.gz     然后用glade设计界面,命名为main.glade,一会让它和我们下边代码生成的可执行程序放在同一个目录下边     然后开始写代码如下: //main.cc #include <gtkmm.h> #include <libglademm/xml.h> int main(int argc, char *argv[]) {     Gtk::Main kit(argc,argv);         Gtk::Window *pWnd;        gtk_rc_parse("E:\\theme-viewer\\themes\\gtk-2.0\\gtkrc");       Glib::RefPtr<Gnome::Glade::Xml> refXml;     try     {         refXml = Gnome::Glade::Xml::create("main.glade");     }     catch(const Gnome::Glade::XmlError& ex)     {         Gtk::MessageDialog dialog("Load glade file failed!", false,       \                                   Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK);         dialog.run();               return 1;     }         refXml->get_widget("main", pWnd);     if(pW