嵌入式系统设计课程

《嵌入式系统设计》概述

前言

这是《嵌入式系统设计》这本书籍的内容小结,主要介绍了嵌入式系统架构中的系统部分。

书籍内容小结摘要

分为两个部分介绍:

  • 嵌入式系统设计部分:ARM架构部分
  • 嵌入式系统设计部分

嵌入式系统的定义

以应用为中心、以计算机技术为基础、软硬件可裁剪、适应应用系统对功能、可靠性、成本、体积、功耗严格要求的专用计算机系统。“嵌入”、“专用”、“计算机”

嵌入式系统的软、硬件组成?以及主要特点?

  • 软件:从底层到上层:bootloader等系统初始化引导程序、设备驱动层(包括驱动程序、板级支持包BSP等)、操作系统、用户应用程序。(底层为上层提供服务)
  • 开发软件:即集成开发环境(asemmbler&&compiler&&linker&&debugger&&loader)
  • 硬件组成:核心板+外围板+外设(核心板:微控制器(CPU和外设接口、外设控制器)、电源、时钟、复位、SDRAM、flash。外围板面向外围设备,一般是引脚的集合、电平转换电路。外围设备。),当然也可以将核心板和外围板放在一起。
  • 硬件特点:通常由嵌入式处理器和嵌入式外围设备组成,高度集成,常采用SOC设计方法,对功耗、体积等有严格要求,定制性决定了它的可裁剪性,没有像计算机领域的垄断,解决方案不唯一。
  • 软件特点:采用交叉开发方式,系统软件层次分明,操作系统为用户程序提供标准API,提供图形接口和文件系统。用户调用系统服务,系统调用设备驱动从而操纵硬件。

嵌入式系统产品设计的基本流程?

  • 需求分析:

    • 功能性需求是系统的基本功能,如输入输出信号、操作方式等;
    • 非功能性需求包括系统性能、成本、功耗、体积、重量等因素。
  • 规格说明:精确地反映客户的需求并且作为设计时必须明确遵循的要求。

  • 体系结构设计:描述系统如何实现所述的功能和非功能需求,包括对硬件、软件和执行装置的功能划分以及系统的软件、硬件选型等。

  • 软硬件设计:基于体系结构,对系统的软件、硬件进行详细设计。

  • 系统集成:把系统的软件、硬件和执行装置集成在一起,进行调试,发现并改进单元设计过程中的错误。

  • 系统测试:对设计好的系统进行测试,看其是否满足规格说明书中给定的功能要求。

处理器及操作系统的选型主要考虑哪些方面?

  • 操作系统本身所提供的开发工具。
  • 操作系统向硬件接口移植难度。
  • 操作系统的内存要求。
  • 开发人员是否熟悉此操作系统及其提供的系统API。
  • 操作系统是否提供硬件的驱动程序,如网卡驱动程序等。
  • 操作系统的是否具有可剪裁性。
  • 操作系统是否具有实时性能。

交叉开发、交叉开发环境?为何需要交叉开发环境?

交叉开发是指在一台通用计算机(宿主机)上进行软件的编辑编译,然后下载到嵌入式设备(目标机)中运行调试的开发方式

交叉开发环境一般由运行于宿主机上的交叉开发软件(assembler&&compiler&&linker&&debugger&&loader)、宿主机到目标机的调试通道组成

需要交叉开发环境是因为目标机一般对体积、功耗等有严格限制,资源也面向应用,较为紧张,要求仅仅能流畅运行代码即可,而将用户开发软件(包括各种库、工具)放置在主机上,而且现在的集成开发环境提供了各种修改好的功能库,用起来也方便。

嵌入式集成开发环境的主要功能?

这是由其组成决定的。Assembler将.c源代码汇编,compiler形成目标文件,linker根据链接描述文件将各个目标代码链接定位生成可执行代码。Debugger有些交叉开发工具提供了仿真调试通道。Loader可以将目标文件烧录进设备中(有时需要内部引导代码的配合)

嵌入式Linux 开发主要流程?

搭建开发环境–烧写bootloader–烧写内核–烧写根文件系统–烧写应用程序。

  • 开发环境:REDHAT-LINUX、下载相应的GCC 交叉编译器进行安装、配置开发主机(配置MINICOM和配置网络,MINICOM 软件的作用是作为调试嵌入式开发板信息输出的监视器和键盘输入的工具,配置网络主要是配置IP地址、NFS网络文件系统,需要关闭防火墙)

  • 烧写bootloader:下载一些公开源代码的BOOTLOADER根据自己具体芯片进行移植修改。 注:下载时,有些芯片没有内置引导装载程序,比如三星的ARM7、ARM9系列芯片,这样就需要编写烧写开发板上flash 的烧写程序。或者网络上有免费下载的WINDOWS 下通过JTAG 并口简易仿真器烧写ARM 外围flash芯片的程序。也有LINUX 下公开源代码的J-FLASH 程序。

  • 下载内核:如果有专门针对你所使用的CPU 移植好的LINUX 操作系统那是再好不过,下载后再添加自己的特定硬件的驱动程序,进行调试修改。

  • 下载根文件系统:从www.busybox.net 下载使用BUSYBOX软件进行功能裁减,产生一个最基本的根文件系统。根文件系统在嵌入式系统中一般设为只读,需要使用mkcramfs、genromfs 等工具产生烧写映象文件。

文件系统就是把你硬盘上数据按照一定格式组织成一棵树。数据块对应名称。删了它就相当于把硬盘格式化了。根文件系统就是出了内核以外,所有的系统文件存储的地方。之所以成为根,是因为有根才能成生长成树,是其它文件的最终挂载点。我们要明白根文件系统和内核是完全独立的两个部分,它是内核启动时所mount的第一个文件系统,里面有内核启动所必须的数据,不然就退出启动文件系统这种机制有利于用户和操作系统的交互。数据块对应名称。尽管内核是Linux 的核心,但文件却是用户与操作系统交互所采用的主要工具,尤其是LINUX。

下载用户程序:可以下载到根文件系统中,有的应用程序不使用根文件系统,而是直接将应用程序和内核设计在一起,这有点类似于UCOS-II的方式。

嵌入式Linux 开发环境中配置NFS服务的目的?

可以使不同机器、不同操作系统之间通过网络共享文件,像访问本地文件一样访问远端系统上的文件,在开发阶段,主机制作基于NFS的文件系统,制定开放目录,开放对象的IP范围,将目录挂载到嵌入式设备后,嵌入式设备可以方便地访问、修改主机主机文件。

什么是硬件重定向?

上课的老师举得printf()是个很好的例子,重定向程序是面向编译环境中的连接器的,是用户自己定义的C库函数,有了它,在程序连接时连接器会连接用户自己编写的C库中的功能函数而不是标准C库。相当于将标准C库进行了一次移植。从主机环境到实际运行环境的移植。

比如:本来库函数fputc()是把字符输出到调试器控制窗口中去的,但用户把输出设备改成了UART端口,这样一来,所有基于fputc()函数的printf()系列函数输出都被重定向到UART端口上去了。相当于实现类似的功能,但是底层的驱动变了。


ARM体系结构部分

ARM硬件电路最小系统组成?

  • 微控制器(例如2410,CPU+外设接口/外设控制器)电源、时钟、复位、存储器(SDRAM/FLASH(NOR8位、NAND8 16 32位))
  • FLASH:存放操作系统、用户程序等需要掉电后保存的数据
  • SDRAM:系统运行的主要区域,系统及用户数据及堆栈,都在这个区域。有时启动模式选择 有时需要JTAG:对芯片内所有部件进行访问,通过该接口对系统调试、编程

ARM处理器的主要工作模式?

ARM的7种处理器模式(不同的模式下有自己的行为准则)

  • USR;正常程序执行模式
  • FIQ;支持高速数据传送和通道处理
  • IRQ;用于通用中断的处理。
  • 管理(SVC);操作系统保护模式
  • 中止
  • 未定义
  • 系统

除了USR之外,其它6种又称为特权模式。6中种除了系统模式又称为异常模式(即处理异常时的工作模式)。

在软件控制下可以改变模式(即改变CPSR相应),外部中断或异常处理也引起模式变化,用户模式下不能改变模式。

核心寄存器的作用:

R13通常用作堆栈指针,称为SP,被初始化为多个模式下的堆栈。R14用作子程序连接寄存器LR,中断异常或执行BL时得到PC即R15的备份。

Cpsr程序状态寄存器,32位只用12位,所有模式下均可见。

Spsr保存程序状态寄存器,即发生异常时对CPSR进行保存,保存当前状态。5个异常模式下均有各自的SPSR。

ARM处理器的启动过程?

首先,看一下,ARM启动时的硬件机制,上电产生复位异常,CPU强制PC为0x00000000,执行复位异常处理函数,接下来就相当于执行了STRARTUP.S的功能。是给用户程序执行给以合适的工作环境,设置中断向量表、堆栈、时钟、完成内存拷贝等,相当于STARTUP.S或者bootloader的前端代码,是开机执行的程序。.拿2410的启动代码举例,它启动CPU的过程是:

在起始地址分配中断向量表即中断处理函数(CPU要求的),以为向量空间只有4字节,所以一般只是一个跳转指令,去别处执行。在跳到复位异常之后,关闭中断,关闭看门狗。

  • 之后初始化存储器系统
  • 初始多个模式下的堆栈(模式切换时,硬件给SP置位)
  • 初始化有特殊要求的外围设备,如LED灯、看门狗
  • 初始化用户的执行环境(在FLASH中运行太慢了,把代码整体搬迁到RAM中)
  • 切换处理器的工作模式
  • 调用主程序
  • 异常处理

当正常的程序执行流程发生暂时的停止时,称之为异常。对异常的处理有优先级,处理异常需要跳转至异常模式。并根据异常向量跳转至响应的子程序(执行之前必须保存现场),即异常出现后强制跳转至固定的存储器地址执行。异常是比中断更大的概念。

异常处理

ARM有7种异常。包括:

  • 复位 管理模式 0x00000000
  • 软中断SWI 管理模式 0x00000008
  • IRQ IRQ模式 0x00000018
  • FIQ FIQ模式 0x0000001c
  • 还包括预取中止、数据中止、未定义

异常出现时,异常模式分组的R14和SPSR用于保存下一条程序地址和CPSR。异常返回时,SPSR->CPSR,R14->PC

在启动代码中首先就是设置所谓的异常向量表,也就是在指定的位置放置异常处理程序(一般是跳转指令)。异常发生时,CPU会根据规定强制置PC,恰好去执行我们设置好的跳转指令,接着执行服务程序。

异常处理流程:(硬件机制,只做这些,跟代码无关)

  • 根据异常类型,强制设置CPSR的运行模式位
  • 在切换到的异常模式下,在当前的链接寄存器LR(r14)中保存上个模式的PC值-4,以便程序在处理异常返回时能从正确的位置重新开始执行
  • 将上一个模式的CPSR复制到当前异常模式的SPSR中(注意1与2、3的矛盾,不能独立执行,但是是硬件实现的,无关代码)
  • 强制PC。然后就到了执行代码的时候从相关的异常向量地址取下一条指令执行,从而跳转到相应的异常处理程序处。

异常返回流程:(有指令)

  • 将LR寄存器中的值减去相应的偏移量(对于IRQ/FIQ是4)送到PC中
  • 将 SPSR 复制回 CPSR(注意1与2的矛盾,不能独立执行,用一条带∧的指令执行,怎么着都是一条)
  • 清除禁止中断标志,如果它被设置成使能
  • 所有修改过的用户寄存器必须从处理程序的保护堆栈中恢复(即出栈)。

对中断嵌套的处理(注意):

保存在LR中的PC值,和该值返回时的处理过程。 当IRQ异常中断产生时,程序计数器pc的值已经更新,它指向当前指令后面第3条指令(对于ARM指令,它指向当前指令地址加12字节的位置;当IRQ异常中断产生时,处理器将值(pc-4)保存到IRQ异常模式下的寄存器lr_irq中,它指向当前指令之后的第2条指令,因此返回操作可以通过下面指令实现:subs pc, lr, \#4

有两种返回机制:

当返回地址保存在当前异常模式的r14时使用其中一种机制 当返回地址保存在堆栈时使用另一种机制(进中断的时候保存的)。 访问机制 SUBS PC,R14_fiq ,\#4 (不同模式有不同的指令,返回PC的同时返回CPSR,一条指令实现)

SUB LR,LR,\#4``
STMFD R13!,{R0,R4-R12,LR}

将寄存器列表中的寄存器R0,R4到R12,LR存入堆栈。

LDMFD R13!,{R0,R4-R12,PC} ∧

将堆栈内容恢复到寄存器R0,R4到R12,PC,同时SPSR复制到CPSR。{∧}为可选后缀,当指令为LDM且寄存器列表中包含R15,选用该后缀时表示:除了正常的数据传送之外,还将SPSR复制到CPSR,一条指令实现。

代码指令分析:

AREA Init,CODE,READONLY;代码段Init、只读
     ……
     CODE32 ;32位ARM指令集
     LDR R0,=NEXT+1 ;给R0赋地址值
     BX R0 ;程序跳,并将处理器切换到Thumb工作状态
     ……
     CODE16 ; 16位thumb指令集

NEXT LDR R3,=0x3FF 给R3赋值
     ……
     END

高级语言和汇编语言函数间的相互调用: 汇编调用C:

IMPORT Main ;通知编译器该标号为一个外部标号
AREA Init,CODE,READONLY ;定义一个代码段
ENTRY ;定义程序的入口点
LDR R0,=0x3FF0000 ;初始化系统配置寄存器
LDR R1,=0xE7FFFF80
STR R1,[R0]
LDR SP,=0x3FE1000 ;初始化用户堆栈
BL Main ;**跳转到Main()函数处的C/C++代码执行**
END ;**标识汇编程序的结束**
以上的程序段完成一些简单的初始化,然后跳转到Main()函数所标识的C/C ++代码处执行主要的任务,此处的Main仅为一个标号,也可使用其他名称。

AREA Init , CODE , READONLY ;已定义代码段
ENTRY;程序入口
LDR R0, =0x3ff5000;R0赋寄存器地址值
LDR R1, 0x;要给寄存器赋的值
STR R1,[R0];赋值
LDR R0, =0x3ff5008
LDR R1, 0x01
STR R1,[R0];给另一个寄存器赋值的过程
BL PROC;跳转至标号为PROC的程序出执行
:
:
:
:
PROC
:
:
MOV PC, LR //将LR保存的程序指针返回,即**跳到BL下一句接着执行**
:
:
END

ARM 2410设计相关

CPU、外设、外设控制器、时序、寄存器的相互关系?

CPU与外设控制器构成微处理器,微处理器在核心板(最小系统)上发挥作用,将引脚集合成外设接口加上电平转换等就是外围板,外设通过外围板连接至外设控制器。CPU通过寄存器编程控制外设控制器产生时序控制外设。若是没有外设控制器,则需要CPU自己产生时序来与外设交互,这种时序相当于一种约定好的意思表示,相当于“语言”或者“通信协议”,

例如:若是2410与一个带有IIC接口的器件通信,只需要连接起来,对IIC进行寄存器编程,控制它们之间的工作模式,可能收发数据就变成了在中断中读写寄存器操作,屏蔽了IIC规定的通信细节。若是51单片机要与IIC通信的话,就复杂多了,首先要仔细阅读IIC的协议,不容丝毫差错,然后用IO口模拟时序,CPU的工作量很大。

寄存器编程的本质?如何获取寄存器的配置?

寄存器编程的本质是CPU控制外设寄存器工作模式的方法。可以想象寄存器的每一位肯定是外设控制器功能模块中的一个个“开关”,给某一位赋值0或者1,就相当于使能或关闭某一个功能。

2410最小电路设计?(晶振选择、启动选择、数据宽度)

与一般的ARM系统相同,都需要微处理器、电源、晶振、复位、存储器(flash、SDRAM)、JTAG接口等,具体情况如下:(需要对OM0和OM1配置电平以决定启动方式,对OM2和OM3配置电平以决定时钟源。)

  • 电源设计:处理器用1.8V,RTC给时钟模块供电1.8V,存储器和普通IO用3.3V,ADC模块用3.3V,可见最小系统最少要用3.3和1.8两种直流稳压。课程实验中电源电压5V,分别用LM1085稳压3.3V,用AS1117稳压1.8V。
  • 晶振设计: 2410的时钟控制逻辑可以产生系统所需要的时钟,包括CPU的FCLK,和AHB总线的HCLK,APB的PCLK。内部有两个锁相环PLL,MPLL提供前三个,UPLL给USB提供48MHZ的时钟。
  • 主时钟源(UPLL和MPLL的时钟源)可以选择是来自外部时钟还是外部晶振,这是由OM2和OM3的管脚确定的,可以OM2和OM3同时接低电平,选择外部晶振,晶振加上15pF起振电容(经过锁相环倍频可以达到)。
  • 复位电路设计:可以在nRESET端设计像51单片机那样的阻容复位电路,但为了稳定,可以使用复位芯片如MAX811或IMP811。
  • JTAG接口设计: 有20针和14针两种JTAG接口。
  • 存储器设计: 2410有自己的存储器控制器,并且规定了哪些bank空间是RAM哪些是FLASH,存储器芯片严格按照DATASHEET上的要求和标明的引脚连接方式与存储器控制器的存储器接口相连就可以,控制器会根据地址产生读写存储器芯片的时序,完成存取数据的操作。

2410nor和nand启动过程分析?

NOR flash:读取速度高、而擦写速度低,容量小,价格高,地址线和数据线分开,采用SRAM接口。 NAND flash:读速度不如NORflash 但是擦写速度高,容量大,价格低,有取代硬盘的趋势,但是地址线和数据复用,需要程序配合才能读写数据。可以通过跳线设置时从NAND FLASH启动还是从NOR FLASH启动。

NAND启动的优势:便宜、容量大。但是读写逻辑不能用硬件产生,也就是没办法接到BANK空间里,必须有程序配合才能读写(有专门的控制器接口,肯定要寄存器编程加上程序配合才能读写,没有PC的根正苗红),所以理论上它是不可以用来启动系统的,因为那之前什么程序都没有,要想读写它必须是系统装载完了而且有程序了。但是三星采用了SRAM映射解决了这个问题,下面就是这个过程:

电路中使OM1OM0都接低电平,从NAND FLASH中启动。(2410有NAND FLASH控制器,连接NAND Flash芯片,产生读写时序)

在该模式下,2410的前4KB地址空间对应一个名字叫做“起步石”的SRAM,系统启动时,自动将NAND FLASH的前4KB数据加载到起步石中,然后系统自动执行这些启动引导代码,CPU从内部RAM的0x00000000位置开始启动。这个过程不需要程序干涉。也就是类似于STARTUP.S的功能,初始化异常向量表、堆栈、将NAND FLASH中的代码(有代码支持喽)拷贝到SDRAM中运行。

NOR FLASH

采用的的是SRAM接口,可以直接到存储器控制器上,ARM内核产生的时序能对其读写。将bank0上接上NORflash芯片。上电产生复位异常后会自动从NOR flash中启动。

2410的中断处理流程?

首先应该明确2410与ARM内核的异常处理系统的角色,根据之前的ARM异常处理流程,我们清楚明了了哪些是CPU的硬件机制。2410通过中断控制器允许以优先级的方式将几十个中断源共同用一个IRQ。一个中断申请提出后,IRQ异常发生,切换模式、保存CPSR、保存PC,然后跳转到handleIRQ函数,然后跳转到ISRIRQ(这只是一个大概流程,也许会定义更多的跳转)根据中断源向量表的首地址和偏移量寄存器找出到底是哪个中断发生了。然后跳转到相应的中断处理函数,比如跳到串口中断,还可以根据挂起位(即中断标志位)再次判断到底是接收中断还是发送完成中断。也就是说2410处理流程除了ARM对异常的响应是硬件机制外,其余的都是代码实现的。我们在编程的时候没有写的话,那也是编译器加进去的。

2410对嵌套的处理

比起2410的处理流程不同的是,因为有了中断控制器,这就是实现高优先级嵌套的硬件基础,因为每一次进入异常模式用户都会保存环境,这就是中断嵌套的软件基础。CPU的异常处理机制总是那些,很明确的。我正在执行一个中断服务程序,然后再次发生异常,保存,跳转(CPU)、再次判断是哪个中断,进去之后压栈,运行另一个中断的服务程序,运行完返回,这是就是返回到上一个中断了。上一个中断运行完,一返回就是返回发生异常前的状态。

S3C2410的串口、端口、外部中断、AD等及寄存器的编程能力(会读datasheet、会编程、作业、实验的相关代码) 寄存器的赋值指令

LDR R0,=GPHCON
LDR R1,=0X2AFAAA
STR R1,[R0]

时钟、看门狗的相关概念

  • 时钟: 整个系统提供同步脉冲,像人的脉搏一样。
  • 看门狗:其实是一个计数器,当它计数溢出的时候,会使系统复位,所以它的作用是防止系统死机。打开看门狗之后,当代码跑飞或者陷入死循环之后,就不能喂狗,也就是不能清除计数值,那么它就会使系统重启。
  • VIVI

什么是bootloader

Bootloader,为引导加载程序,是嵌入式系统加电后运行的第一段代码,相当于PC机的BIOS。 Bootloader在系统中的位置: 通常固化在硬件上的某个固态存储设备上,加电后自启动。

Bootloader功能: 初始化,给CPU合适的工作环境(相当于STARTUP.S),以便为最终调用操作系统内核或用户应用程序境。加载内核,下载内核或者根文件系统。

Bootloader操作模式

有启动加载和下载两种模式。

  • 启动加载模式是Bootloader的正常工作模式,在嵌入式产品发布的时侯,Bootloader必须工作在这种模式下。即初始化CPU的工作环境之后,将内核如RAM执行。
  • 下载模式:目标机上的Bootloader将通过串口连接或网络连接等通信手段从主机下载文件。主要是下载内核映像和根文件系统映像等。从主机下载的文件通常首先被Bootloader保存到目标机的RAM中,然后再被Bootloader写到目标机上的FLASH类固态存储设备中。Bootloader的这种模式通常在第一次安装内核与根文件系统时被使用;此外,以后的系统更新也会使用到这种工作模式。

Bootloader启动过程

上电之后,先启动CPU即执行startup.s类似功能代码(配置中断、初始化堆栈、拷贝代码等),然后进行加载内核的准备至少初始化一个串口,以便向终端用户反馈数据。检测系统内存映射,哪些是可用的RAM?在这一步之后,将检测外部按键,有按键按下将进入下载模式,没有按键的话将执行下面的步骤,加载内核:

  • 将kenel和根文件系统从flash调入RAM
  • 为内核启动设置参数
  • 调用内核。
Terry Tang
Terry Tang
Software Development Engineer

My research interests include distributed robotics, mobile computing and programmable matter.

comments powered by Disqus

Related