我也是刚刚接触嵌入式Linux开发,感觉这门技术相对而言需要软件知识(操作系统、C编程)比硬件知识更多些。所以这几个星期来,作为一个自动化专业的学生,我深深感觉到自己软件知识的匮乏。但毕设又不能不按时完成,为了更快掌握嵌入式开发的知识,同时记录下自己学习的历程,我把读过的这本书摘要记录下来。一方面便于自己对知识的整理回顾,另一方面也方便和大家学习交流。
这本书由孙天泽、袁文菊、张海峰编著。虽称不上经典,但电子工业出版社(我最信赖的出版社)的字号摆在那。而且,我把这份笔记贴出来,并不是想以一个老鸟的身份现身说法,而是希望和大家创造一个写读书笔记的氛围,对初学者(包括我自己)的入门以及大家选择图书有所帮助。
《嵌入式设计及Linux驱动开发指南--基于ARM9处理器》
读书笔记
第一章嵌入式系统基础
1、 嵌入式系统定义:
"嵌入式系统是用来控制或者监视机器、装置、工厂等大规模系统的设备。"
--电气工程师协会
"嵌入到对象体系中的专用计算机系统"
--北京航空航天大学何立民教授
"嵌入性"、"专用性"与"计算机系统"是嵌入式系统的三个基本要素。
2、 嵌入式操作系统:
硬实时系统有一个刚性的、不可改变的时间限制,它不允许任何超出时限的错误超时错误会带来损害甚至导致系统失败、或者导致系统不能实现它的预期目标。
软实时系统的时限是柔性灵活的,它可以容忍偶然的超时错误。失败造成的后果并不严重,仅仅是轻微地降低了系统的吞吐量。
我们可以认为至少嵌入式系统都是软实时系统,所有的嵌入式系统都是实时系统,但并不是所有的实时系统都是嵌入式系统。
常用的嵌入式操作系统有:Linux, uC/OS, Windows CE, VxWorks, Palm OS, QNX等。
3、 选择Embedded OS的原则:
* 系统成本;
* 市场进入时间及技术支持;
* 可移植性;
* 可利用资源;
* 系统定制能力。
第二章 基于ARM9处理器的硬件开发平台
1、 ARM的历史:
ARM(Advanced RISC Machine)公司于1990年11月在英国剑桥成立。
1991年,ARM推出第一个嵌入式RISC核心--ARM6系列处理器,VLSI、夏普、GEC Plessey、德州仪器、Cirrus Logic等公司相继同ARM公司签署了授权协议。
1998年4月,ARM在伦敦证券交易所和纳斯达克交易所上市。
ARM中国安谋咨询上海有限公司于2002年7月在中国上海成立。
目前基于ARM核的处理器有以下几类:
* ARM7家族;
* ARM9家族;
* ARM9E家族;
* ARM10E家族;
* ARM11家族;
* SecurCore家族;
* OptimoDE数据引擎内核;
* MPCore多处理器家族;
* Intel公司的StrongARM/XScale。
2、ARM7和ARM9处理器的主要区别:
指令流水线:
ARM7:三级,(取指令,译码,执行);
ARM9:五级,(取指,译码,执行,缓冲/数据,回写)。
3、三星S3C2410X处理器:
基于ARM920T核(由ARM9TDMI、存储管理单元MMU和高速缓存三部分组成),片上资源包括:
* 1个LCD控制器(支持STN和TFT带有触摸屏的液晶显示屏);
* SDRAM控制器;
* 3个通道的UART;
* 4个通道的DMA;
* 4个具有PWM功能的计时器和1个内部时钟;
* 8通道的10位ADC;
* 触摸屏接口;
* I2S总线接口;
* 2个USB主机接口,1个USB设备接口;
* 2个SPI接口;
* SD接口和MMC卡接口;
* 看门狗计数器;
* 117位通用I/O口和24位外部中断源;
第三章 调试嵌入式系统程序
1、 嵌入式系统调试方法:
1) 实时在线仿真(In-Circuit Emulator, ICE)
* 优点:功能非常强大,软硬件均可做到完全实时在线调试。
* 缺点:价格昂贵。
2) 模拟调试
* 优点:简单方便,不需要目标板,成本低。
* 缺点:功能非常有限,无法实时调试。
3) 软件调试
* 优点:纯软件,价格较低,简单,软件调试能力较强。
* 缺点:需要事先烧制监控程序(Monitor)(往往需多次实验才能成功)且目标板工作正常,功能有限,特别是硬件调试能力较差。
4) JTAG调试
* 优点:方便、简单,无需制作Monitor,软硬件均可调适。
* 缺点:需要工作基本正常(至少CPU工作正常)的目标板,仅适用于有调试接口的芯片。
2、 ARM仿真器工作原理:
利用高速JTAG(Joint Test Action Group)串行扫描链,通过调试通信通道(Debug Communication Channel, DCC)连接ARM核心内嵌的名为"Embedded-ICE"的调试逻辑,调试逻辑实时监测ARM核心的寄存器、数据总线和地址总线。调试器设置Breakpoint及Watchpoint后,程序在ARM内核全速运行,调试程序实时监测地址与数据总线并与预设值比较,在吻合时产生异常中断通知内核并把控制权交给调试器。这样,在程序全速运行时,可以在断点处停止,可以设置条件断点、条件观测断点等,而又不占用CPU时间及内存资源。
3、 JTAG接口:
1985年制定的检测PCB和IC的一个标准,1990年被修改后成为IEEE的一个标准,及IEEE1149.1-1990。通过这个标准,可对具有JTAG接口芯片的电路进行边界扫描和故障检测。
第四章 创建嵌入式系统开发环境
1、交叉编译步骤:
(1) 创建编译环境。在这个过程中,将设置一些环境变量,创建安装目录,安装内核源代码和头文件等。
(2) 创建binutils。这个过程结束后,会创建类似arm-linux-ld等工具。
Binutils是一组开发工具,包括链接器、汇编器以及其他用于目标文件和档案的工具
首先要安装的软件包使binutils。这非常重要,因为glibc和gcc会针对可用的连接器和汇编器进行多种测试,以决定打开某些特性。
(3) 创建一个交叉编译版本的gcc。注意:在这个过程中只能编译C程序,而不能编译C++程序。
创建交叉编译版本的gcc,需要交叉编译版本的glibc及其头文件,而交叉编译版本的glibc是通过交叉编译版本的gcc创建的。面对这个先有鸡还是先有蛋的问题,解决办法是先只编译对C语言的支持,并禁止支持线程。
(4) 创建一个交叉编译版本的glibc。这里最容易出现问题。
glibc是一个提供系统调用和基本函数的C语言库,比如open,malloc和printf等,所有动态链接的程序都要用到它。创建glibc需要的时间更长。
(5) 创建一个交叉编译版本的gdb。在这个过程结束后,会创建ARM-Linux-gdb。
(6) 重新创建gcc。前面创建gcc的过程没有编译C++编译器,现在glibc已经准备好了,所以这个步骤将完善gcc的交叉编译。
(7) 重新创建glibc。如果成功执行了这个过程,那么你就拥有了一套属于自己的交叉编译工具链。
2、如果在交叉编译过程中出现错误,那么请检查:
* 版本选择是否正确,以及是否安装了相应的补丁;
* 库文件路径是否正确;
* 系统环境变量是否设置正确。
第五章 Bootloader
1、 Bootloader(引导加载程序)是系统加电后运行的第一段代码。一般它只在系统启动时运行非常短的一段时间,但对于嵌入式系统来说,这是一个非常重要的系统组成部分。
2、 嵌入式Linux系统从软件的角度看通常可以分成4个层次:
(1) 引导加载程序。包括固化在固件(Firmware)中的启动代码(可选)和Bootloader两大部分。
(2) 内核。特定于嵌入式板子的定制内核以及控制内核引导系统的参数。
(3) 文件系统。包括根文件系统和建立于Flash内存设备之上的文件系统。通常用Ramdisk作为根文件系统。它是提供管理系统的各种配置文件以及系统执行用户应用程序的良好的运行环境的载体。
(4) 用户应用程序。特定于用户的应用程序。有时在用户应用程序和内核层之间可能还会包括一个嵌入式图形用户界面。
3、 Bootloader包含两种不同的操作模式:
1) 启动加载(Bootloading)模式;
2) 下载(Downloading)模式。
4、 Bootloader的启动流程:
第一阶段:主要包含依赖于CPU的体系结构硬件初始化的代码,通常都用汇编实现。这个阶段的任务有:
* 基本的硬件设备初始化(屏蔽所有的中断、关闭处理器内部指令/数据Cache等)
* 为第二阶段准备RAM空间
* 如果是从某个固态存储媒质中,则复制Bootloader的第二段代码到RAM
* 设置堆栈
* 跳转到第二阶段的程序入口点
第二阶段:通常用C语言完成,以便实现更复杂的功能,也使程序有更好的可读性和可移植性。这个阶段的任务有:
* 初始化本阶段要使用到的硬件设备
* 检测系统内存映射
* 将内核映像和根文件系统映像从FLASH读到RAM
* 为内核设置启动参数
* 调用内核
5、 常用U-Boot命令:
命令名
功能
help / ?
帮助命令。用于查询U-Boot支持的命令并列出简单说明,和"?"是同一个命令
bdinfo
察看目标系统参数和变量、目标板的硬件配置、各种变量参数
setenv
设置环境变量。比较常用的有:
setenv ipaddr *.*.*.*
setenv severip *.*.*.*
setenv gatewayip *.*.*.*
setenv ethaddr *.*.*.*.*.*
printenv
查看环境变量
saveenv
保存设置的环境变量到Flash
mw
写内存
md
察看内存
mm
修改内存
flinfo
察看Flash的信息
erase [起始地址 结束地址]
搽除Flash内容,必须以扇区为单位进行搽除
cp [源地址 目标地址 大小]
内存复制,可以在Flash和ram中交换数据
imi [起始地址]
察看内核映像文件
bootm [起始地址]
从某个地址启动内核
tftpboot [起始地址 镜像名]
通过ftp从主机系统下载内核映像文件
reset
复位
第六章 Linux系统在ARM平台的移植
1、 使某一个平台的代码运行在其它平台上的过程就叫做移植。
2、 Linux内核结构:
* /arch包含了所有硬件结构特定的内核代码。
Linux系统能支持如此多平台的部分原因是因为内河把原程序代码清晰的划分为体系结构无关部分和体系结构相关部分。对于任何平台,都必须包含以下几个目录:
* boot:包括启动内核所使用的部分或全部平台特有代码。
* kernel:存放支持体系结构特有的(如信号处理和SMP)特征的实现。
* lib:存放高速体系结构特有的(如strlen和memcpy)同用函数的实现。
* mm:存放体系结构特有的内存管理程序的实现。
* math-emu:模拟FPU的代码。对于ARM处理器来说,此目录用mach-xxx代替。
显然,移植工作的重点就是移植arch目录下的文件。
* /drivers包含了内核中所有的设备驱动程序。
* /fs包含了所有的文件系统的代码。
* /include包含了建立内核代码时所需的大部分库文件,这个模块利用其他模块重建内核。该目录也包含了不同平台需要的库文件。比如,asm-arm是arm平台需要的库文件。
* /init包含了内核的初始化代码,内核从此处工作。
不是系统的引导代码,由main.c和version.c两个文件。这是研究核心如何工作的好起点。
* /ipc包含了进程间通信代码。
* /kernel包含了主内核代码。
* /mm包含了所有内存管理代码。
* /net包含了和网络相关的代码。
3、 在移植过程中,定时器、中断、CACHE管理、MMU等和硬件密切相关的地方都是要相关平台的底层代码支持的,要特别注意。
4、 编译内核:
1) 配置内核
make ARCH=arm CROSS_COMPILE=arm-Linux- menuconfig
2) 创建内核依赖关系
make dep
3) 创建内核镜像文件
make zImage
4) 创建内核模块
make modules