资源描述
基于ARM内核的嵌入式系统开发
报告提纲:
一、 硬件
1) ARM的内核简介
2) 指令结构
3) ARM的异常中断处理
二、 软件
1) 操作系统的软件
2) 映射方式
3) 编译调试的方法
三、 操作系统移植例子
ARM的全称是Advanced RISC Machine,这个公司不生产芯片也不销售芯片,它只是出售芯片技术授权。
ARM技术IP核的微处理器遍及汽车、消费电子、成像、工业控制、海量存储、网络、安保和无线等各类产品市场。
目前世界上前5大半导体公司全部使用了ARM的技术授权,而前10大半导体公司有9家,前25大半导体公司中有23家采用了ARM的技术授权。
ARM内核结构芯片具有RISC体系的一般特点
l 具有大量寄存器
l 绝大多数操作都是在寄存器中进行,寄存器与内存打交道的唯一是通过Load/Store的体系结构在内存和寄存器之间传递数据
l 寻址方式简单
l 采用固定长度的指令
除了这些之外,ARM体系采用了一些特别的技术,在保证高性能的同时尽量减少芯片体积,减少芯片的功耗,这些技术包括
l 在一条数据处理指令中包含算术逻辑处理单元和以为处理
ADD Rd, Rx, Rx, LSL #n :Rd=Rx+Rx*2 n
l 使用地址自动增加(减少)来优化程序中循环处理
l Load/store指令可以批量传输数据,从而提高数据传输的效率
LDMFD r13! , {r0-r12}
l 所有指令都可以根据前面指令的执行结果,决定是否执行,以提高指令的执行效率。
所有的指令都是有条件指令
ARM处理器的内核结构有以下几个系列:
l ARM7
l ARM9
l ARM9E
l ARM10E
l SecurCore
l Intel的xscale
l Intel 的StrongARM
ARM处理器共有7种处理模式
处理器模式
描述
用户模式(User,usr)
快速中断模式(FIQ,fiq)
外部中断模式(IRQ,irq)
特权模式(Supervisor, Sve)
数据访问中止模式(Abort,abt)
未定义指令中止模式(Undefined,und)
系统模式(System,sys)
正常程序执行的模式
用于高速数据传输和通道处理
用于通常的中断处理
供操作系统使用的一种保护模式
用于虚拟存储及存储保护
用于支持通过软件仿真硬件的协处理器
用于运行特权级的操作系统任务
除了用户模式之外其它的6种处理器模式称为特权模式。在这些模式下,程序可以访问所有的系统资源,也可以任意的进行处理器模式的切换,其中除了系统模式外,其它5种特权模式又称为异常模式。
处理器模式可以通过软件控制来进行切换,也可以通过外部中断或异常处理过程进行切换。大多数的用户程序可以运行在用户模式下,这时,应用程序不能够访问一些受应用程序保护的系统资源。应用程序不能直接进行处理器模式的切换。当需要处理器的模式切换的时候,应用程序可以产生异常处理,在异常处理过程种进行处理器模式的切换,这种体系结构可以使整个操作系统控制整个系统的资源。
当应用程序发生异常中断时,处理器进入相应的异常模式,在每一种异常模式种都有一组寄存器,供相应的异常处理程序使用,这样就保证在进入异常模式的时候,用户模式下的寄存器(保存了程序的运行的状态)不被破坏。
寄存器:
l 未备份寄存器R0~R7
l 备份寄存器R8~R14(R13在ARM中经常用作栈指针,R14经常用作连接寄存器)
l 程序寄存器R15
l 程序状态寄存器
在异常中断中
软件中断是用户自定义的中断指令。可用于用户模式下的程序调用特权操作指令。在实时操作系统RTOS中可以通过该机制实现系统功能调用。
ARM的指令集:
一、 跳转指令
一种是跳转指令,一种是直接指向PC寄存器R15中写入目标地址的值。
l B
l BL
l BLX
l BX
二、 数据处理指令
数据传送指令,算术逻辑指令
三、 乘法指令
一种是32位乘法指令,一种是64位乘法指令
四、状态寄存器访问指令
通常修改状态寄存器是通过“读取-修改-写回”的操作序列来实现的
五 Load/Store内存访问指令
六、批量Load/Store内存访问指令
七、信号量操作指令
信号量用于进程间的同步和互斥。对信号量的操作要求是一个原子的操作,即在一条指令中完成信号量的读取和修改操作。
信号量用于实现对临界区数据访问的同步
l SWP 交换指令
l SWPB字节交换指令
SWP R1,R2,[R3] ;将内存单元(R3)中的字数据读取到R1寄存器中,同时将R2寄存器的数据写入内存单元(R3)中
SWP R1,R1,[R2];将R1寄存器内容和内存单元(R2)的内容互换
八、异常中断产生指令
l SWI 软中断指令
软中断指令SWI用于产生SWI异常中断,ARM正是通过这种机制实现用户模式对操作系统中特权模式的程序的调用
l BKPT 断点中断指令
九、ARM协处理器指令
在程序执行过程中,每个协处理器忽略属于ARM处理器和其它协处理器的指令。
ARM存储系统
ARM存储系统体系结构适应不通的嵌入式应用系统的差别很大。最简单的存储系统使用的是平板式的地址映射机制,就像一些简单的单片机系统一样,地址空间分配是固定的,系统中各部分都是用物理地址。
l 系统中可能包含多种类型的存储器件
l 通过CACHE及WRITE BUFFER技术缩小处理器和存储系统速度的差别,从而提高系统的总体性能。
l 内存的从映射过程。通常嵌入式系统的程序存放在ROM/FLASH中,这样系统断电后程序能够得到保存,但是通常ROM/FLASH与SDRAM相比,速度要慢很多,而且嵌入式系统通常把异常向量表放在RAM中,利用内存映射机制可以解决这种需要。在系统加电时,将ROM/FLASH映射为0,这样可以进行一些初始化处理,当这些初始化处理完成之后将SDRAM映射为地址0,并把系统加载到SDRAM中运行,这样就很好的解决了嵌入式系统的需求。
地址重映射,就是存储空间的重新分配,又被称为Remap。地址空间的重新分配,与处理器的硬件结构紧密相关。总体来说32位系统中的地址重映射机制可以分为两类情况,一类是处理器内部有专门的寄存器可以完成Remap,这种只需将Remap寄存器的相应位置1,由硬件逻辑来完成地址的重新映射,如Atmel AT91xx系列,另一类则没有专门的Remap控制寄存器,需要重新改写处理器内部用于控制Memory起止地址的Bank寄存器来实现Remap
过程。
REMAP映射实现方法
列举处理器
第一种映射方式
处理器内部有专门的寄存器可以完成Remap,这种只需将Remap寄存器的相应位置1,由硬件逻辑来完成地址的重新映射
ATM9140800
ATM9155800
第二种映射方式
没有专门的Remap控制寄存器,需要重新改写处理器内部用于控制Memory起止地址的Bank寄存器来实现Remap
S3C4510B
当ARM处理器上电或者Reset之后,处理器从0x0取指令。因此保证系统上电时,0x0处有指令可以执行。所以上电的时候,0x0地址处必定是ROM或者Flash(NOR)。为了加快启动速度,也方便可以更改异常向量表,加快中断响应速度,往往把异常向量表映射到到更快、更宽(32bit/16bit)的RAM中,但是异常向量表的开始地址是由ARM架构决定的,必须位于0x0处,因此,必须把RAM映射到0x0。
操作系统软件:
嵌入式操作系统,有比较多,有商用的嵌入式操作系统,vxworks,pSOS,QNX,但是商用的实时多任务的操作系统源码是不公开的。
UcosII是源码公开的实时多任务的嵌入式操作系统。
uCOSII实际上可以简单的看作是一个多任务调度器,在这个任务调度器上完善并添加了和多任务操作系统相关的一些系统服务,如信号量、邮箱等。它的90%的代码都是C语言写的,因此只要有相应的C语言编译器,基本上可以直接移植到特定处理器上,这也是uCOSII具有良好可移植性的原因。移植工作的绝大部分都集中在多任务切换的实现上,这部分代码主要是用来保存和恢复处理器现场(即相关寄存器),因此不能用C语言,只能用特定的处理器汇编完成。
uCOSII的全部源代码量大约是6000-7000行,一共15个文件。将uCOSII移植到ARM处理器上,只需要修改三个和ARM体系结构相关的文件,代码量大约是500行。
1. OS_CPU.H文件
l 数据类型定义
这部分修改是和所用的编译器相关的,不通的编译器会使用不同字节来表示同一数据。
l 堆栈单位
因为处理器现场的寄存器在任务切换时都将会保存在当前运行任务的堆栈中,所以OS_STK数据类型应该是和处理器的寄存器长度一致的。
l 堆栈增长方向
堆栈有高地址向低地址增长,这个也是和编译器有关的,当进行函数调用时,入口参数和返回地址一般都会保存任务的堆栈中,编译器的编译选项和由此生成的堆栈指令就会决定堆栈增长方向。
l 宏定义
包括开关中断的宏定义,以及进行任务切换的宏定义
2、OS_CPU_C.C文件
uCOSII的移植范例要求用户编写10盖简单的C函数。
OSTaskStkInit();
OSTaskCreateHook();
OSTaskDelHook();
OSTaskSwHook();
OSTaskIdleHook();
OSTaskStartHook();
OSTimeTickHook();
OSInitHookBegin();
OSInitHookEnd();
OSTCBInitHook();
l 任务堆栈初始化
这里涉及到任务初始化时的一个堆栈设计,也就是在堆栈增长方向上如何定义每个需要保存的寄存器位置,这样在ARM体系结构下,任务堆栈空间由高至低依次将保存着PC,Lr,r12,r11,…….r1,r0,CPSR、SPSR,这里需要说明两点,一是当前任务初始化完成后,OSTaskStkInit返回新的堆栈指针stk,在OSTaskCreate()执行的时候会调用OSTaskStkInit的初始化过程,然后通过OSTCSInit()函数调用将返回的SP指针保存到该任务的TCB块中。
l 系统的hook函数
没有特殊要求,则只需简单的将它们都实现为空函数就可以了。
3、OS_CPU_A.S文件
l OSStatHighRdy()
此函数是在OSStart()多任务启动之后,负责从最高优先级任务的TCB控制块中获得该任务的堆栈指针SP,通过SP依次将CPU现场恢复,这时系统就将控制权交给用户创建的该任务进程,直到该任务被阻塞或者被其它更高优先级的任务抢占CPU。该函数仅仅在多任务启动时被执行一次,用来启动第一个,也就是最高优先级的任务执行,之后多任务的电镀和切换就是有下面的函数来实现。
l OSCtxSw
任务级的上下文切换,它是当任务因为被阻塞而主动请求CPU调度时被执行,由于此时的任务切换都是在异常模式下进行的,因为区别于中断级别的任务切换。它的工作是先将当前任务的CPU现场保存到该任务堆栈中,然后获得最高优先级任务的堆栈指针,从该堆栈中回复任务的CPU现场,使之继续执行,这样就完成一次任务的切换。
l OSIntCtxSw()
中断级的任务切换,它是在时钟中断ISR(中断服务例程)中发现高优先级任务等待的时钟信号到来,则需要在中断退出后并不返回中断服务,而是直接调度就绪的高优先级任务执行。这样做的目的是为了能够尽快让高优先级的任务得到响应,保证系统的实时性。它的原理基本上与任务级的切换相同,但是由于进入中断时已经保存了被中断任务的CPU现场,因此这里就不用再进行类似的操作,只需要对堆栈指针做相应的调整,原因是函数的嵌套。
l OSTickISR
时钟中断处理函数,它的主要任务是负责处理时钟中断,调用系统实现OSTimeTick函数,如果有等待时钟信号的高优先级任务,则需要在中断级别上调度执行。其它相关的两个函数OSIntEnter()和OSIntExit(),都需要在ISR中执行。
每个任务都是一个无限的循环,都可能处在5种状态之一:休眠态、就绪态、运行态、等待态、中断态。
可重入函数可以被一个以上的任务调用,而不必担心数据被破坏。
给任务分配优先级不是件简单的事,因为实时系统相当复杂。软实时系统只是要求任务执行的尽量快,并不要求在某一特定时间内完成;硬实时系统重,任务不但要执行无误,还要准时完成。
uClinux是Linux2.0版本地一个分支,它被设计用来应用微控制领域,同标准的linux相比,uClinux最大的特征就是没有MMU,但是它仍然保持了Linux操作系统的特点,如稳定性、强大的网络功能和出色的文件系统支持,uClinux包含了Linux常用的API,并且有一个完整的TCP/IP协议栈,同时对于其它许多网络协议都提供支持操作系统所有的代码加起来<900k。
(1) 设置入口指针
(2) 设置中断向量表
(3) 初始化堆栈和寄存器
(4) 初始化存储器系统
(5) 改变处理器模式、状态
(6) 初始化C语言所需要的存储空间
(7) 呼叫C程序
关中断的时间是实时内核才发商应该提供的最重要的指标之一,因为这个指标影响用户系统对实时事件的相应特性。
uCOSII定义了2个宏来关中断和开中断,以便不通的C编译器厂商选择不同的方法来处理关中断和开中断。
这一段是ARM中从ROM中拷贝到SDRAM中的代码
LDR r0, =0x2000 rom地址
LDR r1, =0xc300000 sdram起始地址
LDR r3, =0xc302000 sdram结束地址
loop
CMP r1, r3
LDRCC r2, [r0], #4
STRCC r2, [r1], #4
BCC loop
LDR PC, =0xc300000
ROM2DRAM_COPY_START
LDR r0, =|Image$$RO$$Base| ; Get pointer to ROM data
LDR r1, =|Image$$RW$$Limit| ; and RAM copy
LDR r2, =DRAM_BASE ; Copy DRAM area base
SUB r1, r1, r0 ; [r1] is loop count
ADD r1, r1, #4; [r1] is loop count
ROM2DRAM_COPY_LOOP
LDR r3, [r0], #4
STR r3, [r2], #4
SUBS r1, r1, #4; Down Count
BNE ROM2DRAM_COPY_LOOP
不复杂的小系统设计,可以作为一种前/后台系统。但是这种情况下的任务级响应时间取决于整个循环的执行时间。因为循环的执行时间不是常数,程序经过某一特定部分的准确时间是不能确定的。
uCOSII需要先关中断,再处置临界代码,并且在处置完毕后重新开中断,这就使得uCOSII能够保护临界代码免受多任务或中断服务子程序的破坏。
ARM体系结构的调试方法:
在嵌入式应用系统中,通常将运行目标长须的计算机系统称为目标机。由于目标机系统中常常没有进行输入输出处理的必要的人机接口,就需要在另外一台计算机上进行调试。
调试代理(debug agent)通常运行在目标机上,它接收主机上调试器发来的命令,可以在目标机上设置断点,单步执行目标程序,显示程序断点处的运行状态。
² ARMulator是一种比较特殊的调试器
² 基于JTAG 的ICE类型的调试器
² Angel 调试监控程序
² 调试网关
使用的是基于JTAG的ICE类型的调试代理
² 实时的设置基于指令地址或者基于指令或者基于数据值的断点
² 控制程序单步执行
² 访问并且可以控制ARM处理器的内核
² 访问ASIC系统
² 访问系统的存储器
² 访问IO口
展开阅读全文