在PROTEUS中使用ARM处理器及uC_第1页
在PROTEUS中使用ARM处理器及uC_第2页
在PROTEUS中使用ARM处理器及uC_第3页
已阅读5页,还剩5页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、LPC2124是基于一个支持实时仿真和跟踪的 16/32 位 ARM7TDMI-SC PU的微处理器,并带有 256k 的嵌入的高速 Flash 存储器和 16k 的片那静态 RAM。128 位宽度的存储器接口和独特的加速结 构使得 32 位代码能够在最大的时钟速率下运行。对代码规模有严格控制的应用可使用 16 位 Thumb模式,将使得代码规模降低超过30,而性能的损失却很小。LPC2124片那 Boot 装载程序实现在系统编程( ISP)和在应用编程( IAP)。1ms可以编程 512 字节。整片擦除只需要 400ms。此外还有 4路 A/D转换器,转换时间低于 2.24us ;2个 32

2、位 定时器, 6路 PWM输出、 RTC、看门狗和多个串行接口。 LPC系列微处理器的抗干扰能力强, 在很多应用中得到了使用。三软件分析1 LPC的 Memory Map、 Remap和 LPC2124的 Bootblock 程序Memory Map是把芯片中、芯片外的 Flash 、 RAM、外设、 BootBlock 等进行统一编址,用地址 来表示对象。 LPC系列 ARM处理器的这个地址是出厂时,由厂家规定的,用户只能访问,而 不能进行更改。Remap和 Boot ,个人理解如下:在 Reset 信号周期内, LPC2124 运行芯片内部自带的 Bootblock 程序,复位信号过后才是

3、运 行用户的程序。LPC 系列 ARM 处理器的 Bootblock 被固化在最高的 Flash 块中,运行时是被映射到 0x7FFFE0000x7FFFFFFF区域,这个程序是厂家写入的,它由任何复位硬件激活,在任何复 位后都会先执行 Boot 装载程序。之所以要把 BootBlock 程序放在 Flash 块的顶端, 是因为各 芯片的 Flash 大小不一致, 厂家为了 BootBlock 在芯片中的位置固定, 在编址的 2G靠前的位 置虚拟划分一个区域作为 BootBlock 区域。这就是 Remap。BootBlock 的工作如下:1 判断 P0.14 是否为低,如果为低,进入 ISP

4、 模式。2 若 P0.14 不为低,要判断 Boot(1:0)这两个脚,如果为 11,要设置 MEMAP=,1 即运行 内部 Flash 。否则设 MEMAP 3,运行外部 Flash 。3 如果是运行外部 Flash ,那需要把外部 Flash 的起始地址重新映射到 0x00000000 ,以便 复位信号过后就开始运行用户程序。个人理解 BootBlock 相当于 PC 中的 BIOS,由厂家固化,上电后首先完成映射,即把它的地 址映射到 0x00000000 处,当初始化完成后, 就运行内部 Flash 或者外部 Flash 的程序, 通常 要以向量表开头,这个过程就是Remap,也就是把

5、内部 ROM或者外部 Flash 的地址映射到0x00000000 处。2启动代码分析运行完 BootBlock 程序之后就是要运行用户自己编写的启动代码了。启动代码中最重要的是 异常向量表。这个表包括复位、未定义指令、软中断、预取指中止、数据中止、 IRQ 中断和 FIQ 中断。ResetLDRPC, ResetAddrLDRPC, UndefinedAddrLDRPC, SWI_AddrLDRPC, PrefetchAddrLDRPC, DataAbortAddrDCD0xb9205f80 ;插入用户代码有效签名LDRPC, PC, #-0xff0 ;从 VIC 处取得 IRQ 入口地址L

6、DRPC, FIQ_AddrResetAddr DCD ResetInitUndefinedAddr DCD UndefinedSWI_Addr DCD SoftwareInterruptPrefetchAddr DCD PrefetchAbortDataAbortAddr DCD DataAbortNouse DCD 0IRQ_Addr DCD 0FIQ_Addr DCD FIQ_HandlerUndefinedB Undefined ; 未定义指令PrefetchAbortB PrefetchAbort ; 取指令中止; 取数据中止DataAbortB DataAbort ; 快速中断未定

7、义指令、 取指令中止、 快速中断使得 PC不跳转, 进入死循环, 等待看门狗复位用户程序。 对于 ARM,9 有 MMU单元,应该在 PrefetchAbort 和 DataAbort 处进行处理,然后返回到发生 异常的指令处重新执行一次。FIQ_HandlerSTMFD SP!, R0-R3, LR ;ADS 编译器会自动保存 R4-R11IMPORT FIQ_Exception ; 也可以在 startup.s 的开头引入BL FIQ_Exception ; 调用 C语言中的中断服务程序LDMFD SP!, R0-R3, LR ; 出栈SUBS PC, LR, #4如果在 CPSR中没有禁

8、止中断, 那么每执行一条指令, 处理器会检查是否有 FIQ 或者 IRQ 中断 发生。 若有中断发生, 当且仅当 PC指更新后, 即处理器对下一条指令进行取指发生后,处理器才会进入到中断的服务程序中。因此保存在 LR 中的指是 PC-4,此处的 PC是更新后的 PC, 由于 ARM处理器是三级流水线的结构,因此返回地址是LR-4,返回到的地址是将要执行,但是被中断了指令。LDR只能实现当前 PC 4KB范围内的跳转,而在 LDR的不远处用 DCD定义一个字,而在这个字 里存放最终的异常服务程序的入口地址,可以实现在4GB范围内的全范围跳转。要求整个向量表的累加和为 0 。_user_initi

9、al_stackheap函数是对用户的堆栈进行初始化, 对它的调用是在 _main 中完成的,对编程人员不可见。 _main 是 ADS编译系统提供的一个库函数, 使用_main 标号引导系 统时,必须将应用程序的入口定义为 main() 。 _main 完成代码和数据的复制,并且把 ZI 数 据区清零。这一步当代码和数据区在存储和运行时处于不同的存储器位置时有意义。_main保证了系统在进入用户的应用程序前自动完成了系统调用。但是如果所有的初始化过程都已 经被用户代码显式地被完成,如堆栈初始化、加载映象、执行映象、RW、 ZI 数据的复制等,那么用户应用程序的入口函数可以任意定义 any_n

10、ame() ,完成初始化后,直接 B any_name即可。个人建议使用 B _main 的方式,防止疏忽出现不必要的错误,比如出现程序中的全局 变量没有被正确的初始化等错误。3.IRQ.S 分析 通过定义宏: $IRQ_Label HANDLER $IRQ_Exception_Function 来实现 LPC 2124 的多个中断源共用一段异 常处理代码的目的。SUB LR, LR, #4 ; 计算返回地址STMFD SP!, R0-R3, R12, LR ; 保存任务环境进入 IRQ中断,首先计算中断的返回地址,将LR减4,然后将 R0-R3,R12,LR 压入堆栈。由于进入了 IRQ 中

11、断,因此堆栈指针是 SP_IRQ,和用户代码运行的 SP_SYS不是同一个寄存器。 至于只保存 R0-R3,R12,是因为程序在正常运行过程中,R4-R11 中装载的是局部变量,在中断跳转是 ADS编译器会自动将 R4-R11 入栈保护。保存状态 保存用户状态的 R3,SP,LR, 注意不能回写PC,的作用是保存用户模式下的寄存器。此操作的目的是用进行了堆栈保护后, 要保存进入中断之前的 CPSR寄存器, 以保证完成中断处理后, 使处理器 状态和没有发生中断一样。MRS R3, SPSR ; STMFD SP, R3, SP, LR ; 若 STM的寄存器列表中不包含ADS编译器会给出响应的警

12、告。; 切换到系统模式调用 c 语言的中断处理程序C 语言中定义的中断复位函数,才能达到中断嵌在 uC/OS-II 的环境下考虑, 因为 IRQ 中断发生之于中断嵌套。通过定义 IRQ 模式的堆栈深度,可以控制中断嵌套的深度。分析整段代码,一 次中断响应需要占用 8个 32bit 的堆栈,定义堆栈深度为 n*8 ,可以允许 n 级中断嵌套。 此处 操作符不允许回写,经过 AXD仿真验证,回写操作会写入 sp_usr 而不是 sp_irq ,此操 作属于不安全的操作,并且编译之后, MSR CPSR_c, #(NoInt | SYS32Mode) CMP R1, #1 LDREQ SP, =St

13、ackUsr BL $IRQ_Exception_Function ; 堆栈操作完成之后,切换到系统模式下运行 套的目的。 当中断服务函数执行完毕之后, 退出中断。后,会改变任务就绪列表,因此需要在中断退出时确定是否需要进行任务切换。这点在下面 的 OS_cpu_a.s 中会涉及到。4 OS_cpu_a.s 分析移植 uC/OS-II ,需要改写 os_cpu.h , OS_cpu_a.s , OS_cpu_a.c , includes.h 几个文件。在 LPC 系列的平台,任务级的任务切换和中断级的任务切换是通过软中断(SWI, SoftwareInterrupt )来完成的。OS_CPU_

14、A.S中包括 SoftwareInterrupt 、OSIntCtxSw 、 OSIntCtxSw_1 和 _OSStartHighRdy 四个函数。 SoftwareInterrupt 定义了软件中断处理方法, OSIntCtxSw 对应于中断级任务切 换和任务级任务切换。而 _OSStartHighRdy 是 uC/OS-II 启动时调用的,调用新建的优先级 最高的任务。这四个函数的编写需要很好的了解ARM7的内核结构和完全了解 uC/OS-II 内核运行的原理。在 SoftwareInterrupt 主要完成寄存器 R0-R3,R12,LR 在 SVC模式( Supervisor )的堆

15、栈中的 保存、取得软件中断号并调用相应的处理过程。在 OS_CPU.H中可以找到关于几个函数的软件中断定义。任务级任务切换函数 */ 运行优先级最高的任务 */ 关中断 */ 开中断 */_swi(0x00) void OS_TASK_SW(void); /*_swi(0x01) void _OSStartHighRdy(void); /*_swi(0x02) void OS_ENTER_CRITICAL(void) /*_swi(0x03) void OS_EXIT_CRITICAL(void); /*由于 SWI中断是由指令本身引起的,因此发生中断时,PC值并没有更新,所以计算中断返回地址

16、,并不需要将 LR 减 4,LR 指向的就是发生中断指令的下一条指令。SWI中断下堆栈的操作如下指令所示:LDR SP, StackSvc ; 重新设置堆栈指针STMFD SP!, R0-R3, R12, LR ; 寄存器入栈 ; 软件中断处理LDMFD SP!, R0-R3, R12, PC ; 寄存器出栈,返回OS_TASK_SW是任务级任务切换函数, 引起 0x00 号软中断, 并最终会跳转到 OSIntCtxSw 执行, OSIntCtxSw 也是中断级任务切换的函数。对 OSIntCtxSw 的理解, 实际上是要理解各个任务的堆栈设置。 一个任务正常运行, 是运行在 user 模式下

17、, 根据 ARM7的体系结构, user 模式的所有寄存器和 system 模式下的所有寄存器 使用同一个物理地址。其他模式R13, R14不同物理地址, FIQ 模式 R8-R14 不同物理地址。其他模式相比 user/sys 模式,多一个 SPSR寄存器,用于保存发生中断时的 CPSR的备份。 因 此,当发生任务切换,需要保存当前任务的所有寄存器,即R0-R14。OSIntCtxSwLDR R2, SP, #20 ;获取 PC (LR_SVC)LDR R12, SP, #16 ; 获取 R12MRS R0, CPSR ; 保存当前 SVC模式到 R0MSR CPSR_c, #(NoInt

18、| SYS32Mode) ; 切换到系统模式MOV R1, LR ; 保存 LR_sysSTMFD SP!, R1-R2; 保存 LR_sys, PC (LR_SVC)STMFD SP!, R4-R12; 保存 R4-R12MSR CPSR_c, R0 ; 从 R0 中恢复到 SVC模式LDMFD SP!, R4-R7;获取 R0-R3,SVC堆栈ADD SP, SP, #8 ;出栈 R12,PC,计算 SP_SVCMSR CPSR_c, #(NoInt | SYS32Mode) ; 切换到系统模式STMFD SP!, R4-R7; 保存 R0-R3需要注意,执行 MSR CPSR_c, #(

19、NoInt | SYS32Mode) 之前的 SP 是指 SP_SVC,而模式切换之 后, SP对应于 SP_user 。注意 ADS采用的是满递减堆栈。此段代码的作用是在系统模式下,依次入栈PC,(即 LR_SVC),LR( LR_SYS)R12,R11,R4。然后切换回 SVC模式下出栈 R0-R3,在切换回 SYSTEM模式下入栈 R3,R2, R1,R0。 当以上入栈工作完成之后,再保存 OSEnterSum和 CPSR即可完成当前任务的上下文环境的保 存。LDR R1, =OsEnterSum ; 获取 OsEnterSumLDR R2, R1STMFD SP!, R2, R3 ;

20、保存 CPSR,OsEnterSum 从上述程序分析可以看出,一个任务的上下文环境入栈如下图所示:当任务的入栈工作完成之后,需要把当前的SP_SYS保存到当前任务 TCB块的栈顶指针。LDR R1, =OSTCBCurLDR R1, R1STR SP, R1 至此,任务的上下文保存工作完成,下面需要进行任务切换。第一步是把就绪列表中最高优 先级 OSPrioHighRdy 赋值给 OSPrioCur ,然后把最高优先级任务对应的TCBO STCBHighRdy赋值给当前任务 TCBO STCBCu。r 之后运行到 OSIntCtxSw_1 ,进行新任务的数据出栈,切换到新 任务的运行。这里值得

21、一提的是以下两条语句:ADD SP, R4, #68LDR LR, SP, #-8之所以对于 SP进行加 68 的操作,是因为此处的 SP处理器在系统模式下的堆栈指针, 也就是 uC/OS-II 的用户程序运行的任务堆栈指针。 即将运行的任务的数据在这两条语句之后会通过 设置 SVC模式下的堆栈出栈, 然后就将 PC设置到新任务的入口处开始运行任务代码了。 这样, 我们没有机会再修改即将运行的任务的堆栈指针了。若在恢复任务之前,不修改SP_SYS,会导致有数据压栈,有数据出栈,但是堆栈指针却一直向栈底方向运动,没有往栈顶方向运动 的情况出现,任务长期运行,被切换,那么任务的堆栈会溢出,出现了内

22、存泄漏。那么之所 以是 68,是因为任务的上下文切换是 17 个寄存器的内容,每个寄存器是 32bit ,所以是 68=17*4 。那么 LDR LR, SP, #-8 的原因又是什么呢?为什么在没有恢复待运行任务的数据之前, 要先恢复系统模式下的 LR寄存器呢?原因同上, 当新任务运行后, 程序再没有机会修改系统 模式下的 LR 寄存器了,这样会导致任务跑飞。 OSIntCtxSw_1 的最后一句: LDMFD SP!, R0-R12, LR, PC ,恢复了新任务。当时仔细调试程序会发现, MSR SPSR_cxsf, R5 , 恢复处理器模式是在把堆栈的数据恢复到 PC 之后才会改变到系

23、统模式下,因此可以得出结 论, 这里出栈的倒数第二个数据, 就是寄存器列表中的 LR,是 SVC模式下的 LR,并不是系统 模式下的 LR。所以,需要在任务数据出栈之前先恢复LR_SYS。至此,关于 uC/OS-II 的移植部分的分析全部完毕。至于 OS_CPU_A.C中的一个函数是初始化 任务堆栈。值得注意的地方是, ADS 使用的是满递减堆栈。因此需要在OS_CPU.H中把OS_STK_GROW设TH置为 1。四 uC/OS-II 的使用 通过全部阅读 uC/OS-II 的代码,个人总结了一下 uC/OS-II 的核心算法。主要是通过对OSUnMapTbl这张表的读取,才能确定优先级最高的

24、就绪任务。这张表的编码规则是:对应偏移量的数值中, 出现第一个二进制” 1”的位置。 由于算出优先级最高的任务是通过查表完成的,因此任务个数的多少对于任务的调度没有影响。同样的道理,对于事件的管理,也是一样通过 OSUnMapTbl 来完成的。只要理解了这张表,也就理解了OSRdyGrp、OSRdyTbl 和OSEventGrp、OSEventTbl 的使用。 唯一的一点不同在于, 新建任务的状态是: OS_STAT_RD,Y 任务处于就绪态。 而新建事件之后, 比如邮箱: 新建一个邮箱调用 OSMboxCreate 完成, 返回OSMboxPend,通过从对应的 uC/OS-II 的书籍上都会介绍,这

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论