




已阅读5页,还剩12页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
移植UCOSII到ARM7笔记(一) 2009-07-19 11:09:49 分类: 嵌入式 2009-7-191 头文件includes.h和config.h UCOSII要求所有.c文件都必须包含includes.h。在本移植中另外增加了一个config.h,要求所有用户程序必须包含config.h,在config.h中包含includes.h和特定的头文件和配置项。2 OS_CPU.H(1)根据ADS编译器的特性,不依赖于编译器的数据类型的程序清单如下:Typedef unsigned char BOOLEAN;Typedef unsigned char INT8U;Typedef signed char INT8S;Typedef unsigned short INT16U;Typedef signed short INT16S;Typedef unsigned int INT32U;Typedef signed int INT32S;Typedef float FP32;Typedef double FP64; Typedef INT32U OS_STK;(2)使用软中断做为底层接口带T变量的ARM7处理器核具有两个指令集,用户任务还可以使用两种不同的处理器模式:用户模式与系统模式(别的模式都不是太适合),组合起来就有四种方式,四种方式对系统资源有不同的访问控制权限。为了让底层接口函数与处理器状态无关,同时在任务调度时相应的函数不需要知道函数位置,本移植中使用SWI做为底层接口,不同的功能号用来区分不同的函数。软中断功能号的分配列表如下:_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(0x80) void ChangeToSYSMode(void); /* 任务切换到系统模式 */_swi(0x81) void ChangeToUSRMode(void); /* 任务切换到用户模式 */_swi(0x82) void TaskIsARM(INT8U prio); /* 任务代码是ARM代码 */_swi(0x83) void TaskIsTHUMB(INT8U prio); /* 任务代码是THUMB */ 这里的_swi,是ADS的一个关键字,用它来声明一个不存在的函数,则调用这个函数就在调用这个函数的地方插入一条SWI指令,并且可以指定功能号。其具体使用规则可见下面的英文注释:This declares a SWI function taking up to four integer-like arguments and returning up to four results in a value_in_regs structure. This causes function invocations to be compiled inline as an ATPCS compliant SWI that behaves similarly to a normal call to a function.For a SWI returning no results use:void _swi(swi_num) swi_name(int arg1, int argn);For example: void _swi(42) terminate_proc(int procnum);For a SWI returning one result, use:int _swi(swi_num) swi_name(int arg1, int argn);For a SWI returning more than 1 result use:typedef struct res_type int res1,resn; res_type;res_type _value_in_regs _swi(swi_num) swi_name( int arg1,int argn);The _value_in_regs qualifier is used to specify that a small structure of up to four words (16 bytes) is returned in registers, rather than by the usual structure-passing mechanism defined in the ATPCS.See the chapter on Handling Processor Exceptions in the ADS Developer Guide for detailed information通过上文可知,其大致的用法就是:无返回形式:void _swi(swi_num) swi_name(arguments);返回一个结果到R0中int _swi(swi_num) swi_name(arguments);最多可以返回四个结果R0-R3到一个结构struct type int a,b,c,d中type(返回类型) _value_in_regs(返回多个结果的修饰符) _swi(swi_num) swi_name(arguments);简单的说就是:一个SWI调用允许带14个字型参数和14个字型返回值,触发SWI调用时四个参数依次保存在R0R3中,返回值也存于R0R3内。所以在软中断服务程序中应函数所需要的参数按顺序保存到R0R3中。因为这里涉及到软中断这个问题,先当列一章,摘抄下别人对软中断的理解:(3)软中断的理解与应用(a)软中断的概念SWI(software interrupt)软件中断,由用户定义的中断指令.可以用于用户模式下的程序调用特权操作指令.在实时操作系统中可以通过该机制实现系统调用.一个 SWI 所做的一切就是把模式改变成超级用户并设置 PC 来执行在地址 &08 处的下一个指令!编程异常通常叫做软中断.软中断是通讯进程之间用来模拟硬中断的一种信号通讯方式。中断源发中断请求或软中断信号后,CPU或接收进程在适当的时机自动进行中断处理或完成软中断信号对应的功能.软中断是软件实现的中断,也就是程序运行时其他程序对它的中断;而硬中断是硬件实现的中断,是程序运行时设备对它的中断。1.软中断发生的时间是由程序控制的,而硬中断发生的时间是随机的2.软中断是由程序调用发生的,而硬中断是由外设引发的3.硬件中断处理程序要确保它能快速地完成它的任务,这样程序执行时才不会等待较长时间。软件的上层应用,有时需要对系统进行一些底层操作,但是上层应用所使用的 C 语言又无法进行这样的操作。所以,需要有一个接口,利用这个接口才能碰触到系统的底层,而这个接口就是-SWI 。SWI 就像一个中间人,负责上层应用 和 操作系统底层之间传递一些命令与数据。 (b)软中断的理解于应用 关于软中断的理解可见这两篇文章:/panqihe/archive/2007/05/18/1615574.aspx原文内容摘抄在下,方便自己查阅:SWI,即software interrupt软件中断。该指令产生一个SWI异常。意思就是处理器模式改变为超级用户模式,CPSR寄存器保存到超级用户模式下的SPSR寄存器,并且跳转到SWI向量。其ARM指令格式如下:SWIcond immed_24Cond域:是可选的条件码 (参见 ARM汇编指令条件执行详解).immed_24域:范围从 0 到 224-1 的表达式, (即0-16777215)。用户程序可以使用该常数来进入不同的处理流程。一、方法1:获取immed_24操作数。为了能实现根据指令中immed_24操作数的不同,跳转到不同的处理程序,所以我们往往需要在SWI异常处理子程序中去获得immed_24操作数的实际内容。获得该操作数内容的方法是在异常处理函数中使用下面指令:LDR R0,LR,#-4该指令将链接寄存器LR的内容减去4后所获得的值作为一个地址,然后把该地址的内容装载进R0。此时再使用下面指令,immed_24操作数的内容就保存到了R0:BIC R0,R0,#0xFF000000该指令将R0的高8位清零,并把结果保存到R0,意思就是取R0的低24位。可能还是有人会问:为什么在SWI异常处理子程序中执行这两条指令后,immed_24操作数的内容就保存到了R0寄存器呢?之所以会有这样的疑问,基本都是因为对LR寄存器的作用没了解清楚。下面介绍一下链接寄存器LR(R14)的作用。寄存器R14(LR寄存器)有两种特殊功能:在任何一种处理器模式下,该模式对应的R14寄存器用来保存子程序的返回地址。当执行BL或BLX指令进行子程序调用时,子程序的返回地址被放置在R14中。这样,只要把R14内容拷贝到PC中,就实现了子程序的返回(具体的子程序返回操作,这里不作详细介绍)。当某异常发生时,相应异常模式下的R14被设置成异常返回的地址(对于某些异常,可能是一个偏移量,一个较小的常量)。异常返回类似于子程序返回,但有小小的不同(这里不作详细介绍)。所谓的子程序的返回地址,实际就是调用指令的下一条指令的地址,也就是BL或BLX指令的下一条指令的地址。所谓的异常的返回的地址,就是异常发生前,CPU执行的最后一条指令的下一条指令的地址。例如:(子程序返回地址示例)指令 指令所在地址ADD R2,R1,R3 ;0x300000BL subC ;0x300004MOV R1,#2 ;0x300008BL指令执行后,R14中保存的子程序subC的返回地址是0x300008。再例如:(异常返回地址示例)指令 指令所在地址ADD R2,R1,R3 ;0x300000SWI 0x98 ;0x300004MOV R1,#2 ;0x300008SWI指令执行后,进入SWI异常处理程序,此时R14中保存的返回地址为0x300008。所以,在SWI异常处理子程序中执行 LDR R0,LR,#-4语句,实际就是把产生本次SWI异常的SWI指令的内容(如:SWI 0x98)装进R0寄存器。又因为SWI指令的低24位保存了指令的操作数(如:0x98),所以再执行BIC R0,R0,#0xFF000000语句,就可以获得immed_24操作数的实际内容。二、方法2:使用参数寄存器。 实际上,在SWI异常处理子程序的实现时,还可以绕开immed_24操作数的获取操作,这就是说,我们可以不去获取immed_24操作数的实际内容,也能实现SWI异常的分支处理。这就需要使用R0-R4寄存器,其中R0-R4可任意选择其中一个,一般选择R0,遵从ATPCS原则。 具体方法就是,在执行SWI指令之前,给R0赋予某个数值,然后在SWI异常处理子程序中根据R0值实现不同的分支处理。例如:指令 指令所在地址MOV R0,#1 ; #1给R0SWI 0x98 ; 产生SWI中断,执行异常处理程序SoftwareInterruptADD R2,R1,R3 ; ;SWI异常处理子程序如下SoftwareInterrupt CMP R0, #6 ; if R0 6 LDRLO PC, PC, R0, LSL #2 ; if R0 6,PC = PC + R0*4,else next MOVS PC, LRSwiFunction DCD function0 ;0 DCD function1 ;1 DCD function2 ;2 DCD function3 ;3 DCD function4 ;4 DCD function5 ;5Function0 异常处理分支0代码Function1 异常处理分支1代码function2 异常处理分支2代码function3 异常处理分支3代码function4 异常处理分支4代码function5 异常处理分支5代码 在ARM体系结构中,当正确读取了PC的值时,该值为当前指令地址值加8字节,也就是说,对于ARM指令集来说,读出的PC值指向当前指令的下两条指令的地址,本例中就是指向SwiFunction 表头DCD function0 这个地址,在该地址中保存了异常处理子分支function0的入口地址。所以,当进入SWI异常处理子程序SoftwareInterrupt时,如果R0=0,执行LDRLO PC, PC, R0, LSL #2语句后,PC的内容即为function0的入口地址,即程序跳转到了function0执行。在本例中,因为R0=1,所以,实际程序是跳转到了function1执行。R0左移2位(LDRLO PC, PC, R0, LSL #2),即R0*4,是因为ARM指令是字(4个字节)对齐的DCD function0等伪指令也是按4字节对齐的。 在本方法的实现中,实际指令中的24位立即数(immed_24域)被忽略了, 就是说immed_24域可以为任意合法的值。如在本例中,不一定使用SWI 0x98,还可以为SWI 0x00或者SWI 0x01等等,程序还是会进入SWI异常处理子程序SoftwareInterrupt,然后根据R0的内容跳转到相应的子分支。 /BelindaBen/archive/2008/03/24/2212302.aspx原文内容也摘抄如下,方便自己查阅:SWI 表示 Software Interrupt。在 RISC OS 中使用 SWI 来访问操作系统例程或第三方生产的模块。许多应用使用模块来给其他应用提供低层外部访问。 当 SWI 处理程序得到对特定的例程编号的一个请求的时候,它找到这个例程的位置并执行它,并传递(有关的)任何数据。 它是如何工作的?首先查看一下如何使用它。一个 SWI 指令(汇编语言)看起来如下: SWI &02或 SWI OS_Write0这些指令实际上是相同的,将被汇编成相同的指令。唯一的不同是第二个指令使用一个字符串来表示 SWI 编号 &02。在使用采用了字符串编号的程序的时候,在执行之前首先查找这个字符串。 在这里我们不想处理字符串,因为它不能给出它要进行什么的一个真实表示。它们通常用于增进一个程序的清晰程度,但不是实际执行的指令。 让我们再次看一下第一个指令: SWI &02这是什么意思? 字面的意思是进入 SWI 处理程序并传递值 &02。在 RISC OS 中这意味着执行编号是 &02 的例程。 它是如何这么作的? 它如何传递 SWI 编号和进入 SWI 处理程序? 如果你查看内存的开始 32 字节(位于 0-&1C)并反汇编它们(查开实际的 ARM 指令)你将见到如下: 地址 内容 反汇编00000000 : 0. : E5000030 : STR R0,R0,#-4800000004 : . : E59FF31C : LDR PC,&0000032800000008 : . : E59FF31C : LDR PC,&0000032C0000000C : . : E59FF31C : LDR PC,&0000033000000010 : . : E59FF31C : LDR PC,&0000033400000014 : . : E59FF31C : LDR PC,&0000033800000018 : . : E59FF31C : LDR PC,&0000033C0000001C : 2? : E3A0A632 : MOV R10,#&3200000让我们仔细看一下。 除了第一个和最后一个指令之外(它们是特殊情况)你见到的都是把一个新值装载到 PC (程序计数器)的指令,它们告诉计算机到哪里去执行下一个指令。还展示了这个值是从内存中的一个地址接受来的。(你可以在 !Zap 主菜单上使用“Read Memory”选项去自己查看一下。) 这看起来好象与 SWI 没多少关系,下面做进一步的说明。 一个 SWI 所做的一切就是把模式改变成超级用户并设置 PC 来执行在地址 &08 处的下一个指令! 把处理器转换到超级用户模式会切换掉两个寄存器 r13 和 r14 并用 r13_svc 和 r14_svc 替换它们。 在进入超级用户模式的时候,还把 r14_svc 设置为在这个 SWI 指令之后的地址。 这个实际上就象一个连接到地址 &08 的分支指令(BL &08),但带有用于一些数据(SWI 编号)的空间。象我说过的那样,地址 &08 包含跳转到另一个地址的一个指令,就是实际的 SWI 程序的地址! 此时你可能会想“稍等一会! 还有 SWI 编号呢?”。实际上处理器忽略这个值本身。SWI 处理程序使用传递来的 r14_svc 的值来获取它。 下面是完成它的步骤(在存储寄存器 r0-r12 之后): (1)它从 r14 中减去 4 来获得 SWI 指令的地址。 (2)把这个指令装载到一个寄存器。 (3)清除这个指令的高端 8 位,去掉了 OpCode 而只剩下的 SWI 编号。 (4)使用这个值来找到要被执行的代码的例程的地址(使用查找表等)。 (5)恢复寄存器 r0-r12。 (6)使处理器离开超级用户模式。 (7)跳转到这个例程的地址。 (4)UCOSII移植中软中断的理解与应用再回到我们的ARM7的移植中,网上有篇文章写的已经很好了,在这里摘录下,原文地址:/user1/4663/archives/2008/48268.html原文内容:ARM的移植代码吧首先定义了一堆软中断的中断号,其中0和1的中断服务子程序是用汇编编写的,其他的都是在c语言编写的中断服务子程序SWI_Exception中。_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(0x40) void *GetOSAddr(int Index);/* 获取系统服务函数入口 */_swi(0x41) void *GetUsrAddr(int Index);/* 获取自定义服务函数入口 */_swi(0x42) void OSISRBegin(void);/* 中断开始处理 */_swi(0x43) int OSISRNeedSwap(void);/* 判断中断是否需要切换 */_swi(0x80) void ChangeToSYSMode(void);/* 任务切换到系统模式 */_swi(0x81) void ChangeToUSRMode(void);/* 任务切换到用户模式 */_swi(0x82) void TaskIsARM(INT8U prio);/* 任务代码是ARM代码 */_swi(0x83) void TaskIsTHUMB(INT8U prio);/* 任务代码是THUMB */ 比如在程序运行到调用OS_TASK_SW(void)函数时,就产生软件中断,然后就进入中断服务子程序,按照什么指令走呢?恩,就按照下面这个代码,这个代码是将软件中断异常处理程序挂接到内核的作用的,是在启动代码中实现的:LDR PC,SWI_Addr SWI_Addr DCD SoftwareInterrupt因此当产生软中断之后PC就跳到了SoftwareInterrupt,这时就算真正进入了软件异常中断处理部分了,然后就是执行下面的汇编代码SoftwareInterruptLDR SP, StackSvc/*重新设置堆栈指针*/STMFD SP!, R0-R3, R12, LR/*保存 R0,R1,R2,R3,R12,LR(R14),注意为什么只保存这几个寄存器呢,因为R4-R11存储局部变量,编译器自动保护他们*/MOV R1, SP /* R1指向参数存储位置 */MRS R3, SPSR /*保存管理模式的状态寄存器*/TST R3, #T_bit /* 中断前是否是Thumb状态 */LDRNEH R0, LR,#-2 /* 若是,取得Thumb状态SWI号*/BICNE R0, R0, #0xff00 /*THUMB指令SWI功能号为8位 */LDREQ R0, LR,#-4 /* 为零即ARM指令取得SWI号 */BICEQ R0, R0, #0xFF000000/*在ARM指令集中SWI功能号为24位所以高8位清零r0=SWI号*/CMP R0, #1 /*LDRLO PC, =OSIntCtxSw /* 疑惑ing */* 功能号为0到OSIntCtxSw执行中断任务切换函数 */LDREQ PC, =_OSStartHighRdy/*SWI为1第一次任务切换*/BL SWI_Exception /*否则进入c编写的中断函数 */LDMFD SP!, R0-R3, R12, PC/*R0-R3,R12,LR出栈 */StackSvc DCD (SvcStackSpace + SVC_STACK_LEGTH * 4 - 4) 怎么进入c编写的中断服务子程序SWI_Exception呢?通过下面的申明 IMPORT SWI_Exception ;软中断异常处理程序表示将c程序中的该函数挂接到此段汇编代码中,同样的道理EXPORT _OSStartHighRdyEXPORT OSIntCtxSw ;中断退出时的入口参见startup.s中的IRQ_HandlerEXPORT SoftwareInterrupt ;软中断入口上面的申明是将该段汇编代码挂接到外面,因此在外部可以直接调用函数名继续看OS_CPU_A.S的其他部分代码,就是两个软件异常中断处理函数OSIntCtxSw和OSStarHighRdyOSIntCtxSw代码是中断服务子程序使得更高优先级的任务进入就绪状态后,中断返回后需要切换到该任务时调用的,这是被切换的任务的CPU寄存器的值已经在响应中断后存入了堆栈中,因此,这里不需要重复保存了直接切换任务即可,具体过程看代码OSIntCtxSw ;下面为保存任务环境 ;当响应软件异常中断后进入了系统模式,在上面的代码中我们可以看到,进入系统模式时保存的堆栈结构从顶到底依次是:R0,R1,R2,R3,R12,LR,而在用户模式中任务的堆栈结构应该是:OsEnterSum,CPSR,RO-12,LR,PC,所以在进行软件中断任务切换之前先要保存原来任务的堆栈结构。 LDR R2, SP, #20 ;获取PC LDR R12, SP, #16 ;获取R12 MRS R0, CPSR MSR CPSR_c, #(NoInt | SYS32Mode) MOV R1, LR STMFD SP!, R1-R2 ;保存LR,PC STMFD SP!, R4-R12 ;保存R4-R12 MSR CPSR_c, R0 LDMFD SP!, R4-R7 ;获取R0-R3 ADD SP, SP, #8 ;出栈R12,PC MSR CPSR_c, #(NoInt | SYS32Mode) STMFD SP!, R4-R7 ;保存R0-R3 LDR R1, =OsEnterSum ;获取OsEnterSum LDR R2, R1 STMFD SP!, R2, R3 ;保存CPSR,OsEnterSum ;保存当前任务堆栈指针到当前任务的TCB LDR R1, =OSTCBCur LDR R1, R1 STR SP, R1 BL OSTaskSwHook ;调用钩子函数 ;OSPrioCur = OSPrioHighRdy LDR R4, =OSPrioCur LDR R5, =OSPrioHighRdy LDRB R6, R5 STRB R6, R4 ;OSTCBCur = OSTCBHighRdy LDR R6, =OSTCBHighRdy LDR R6, R6 LDR R4, =OSTCBCur STR R6, R4OSIntCtxSw_1 ;获取新任务堆栈指针 LDR R4, R6 ADD SP, R4, #68 ;17寄存器CPSR,OsEnterSum,R0-R12,LR,SP LDR LR, SP, #-8 MSR CPSR_c, #(NoInt | SVC32Mode) ;进入管理模式 MOV SP, R4 ;设置堆栈指针 LDMFD SP!, R4, R5 ;CPSR,OsEnterSum ;恢复新任务的OsEnterSum LDR R3, =OsEnterSum STR R4, R3 MSR SPSR_cxsf, R5 ;恢复CPSR LDMFD SP!, R0-R12, LR, PC ;运行新任务 _OSStartHighRdy MSR CPSR_c, #(NoInt | SYS32Mode) ;调整到管理模式 ;告诉uC/OS-II自身已经运行 LDR R4, =OSRunning MOV R5, #1 STRB R5, R4 ;标记多任务运行标记为真 BL OSTaskSwHook ;调用钩子函数,可以运行用户自定义的函数 LDR R6, =OSTCBHighRdy ;R6存有最高优先级的就绪任务的控制块地址 LDR R6, R6 B OSIntCtxSw_1 ;转到前面编写的中断返回函数块的任务跳转部分的代码,因为这两个函数都要用到这部分代码,进入这段代码之前高优先级的就绪任务的任务控制快地址存在R6中。 AREA SWIStacks, DATA, NOINIT,ALIGN=2SvcStackSpace SPACE SVC_STACK_LEGTH * 4 ;管理模式堆栈空间 OSIntCtxSw_1的代码:OSIntCtxSw_1 ;获取新任务堆栈指针 LDR R4, R6 ;任务控制块的堆栈指针放在R6中,现在放在R4中 ADD SP, R4, #68 ;17寄存器CPSR,OsEnterSum,R0-R12,LR,SP LDR LR, SP, #-8 MSR CPSR_c, #(NoInt | SVC32Mode) ;进入管理模式 MOV SP, R4 ;设置堆栈指针,R4存有没有改动过的堆栈指针 LDMFD SP!, R4, R5 ;CPSR,OsEnterSum ;恢复新任务的OsEnterSum LDR R3, =OsEnterSum STR R4, R3 MSR SPSR_cxsf, R5 ;恢复CPSR LDMFD SP!, R0-R12, LR, PC ;运行新任务,恢复现场,异常处理返回;中断返回指令的寄存器列表其中必须包括PC后的符号,表示这是一条特殊形式的指令。这条指令在从存储器中装载PC的同时,CPSR也得到恢复。这里使用的堆栈指针SP是属于异常模式的寄存器,每个异常模式有自己的堆栈指针。SoftwareInterrupt LDR SP, StackSvc ; 重新设置堆栈指针 STMFD SP!, R0-R3, R12, LR ;保存寄存器 MOV R1, SP ; R1指向参数存储位置 MRS R3, SPSR TST R3, #T_bit ; 中断前是否是Thumb状态 LDRNEH R0, LR,#-2 ; 是: 取得Thumb状态SWI号 BICNE R0, R0, #0xff00 LDREQ R0, LR,#-4 ; 否: 取得arm状态SWI号 BICEQ R0, R0, #0xFF000000 ; r0 = SWI号,R1指向参数存储位置 CMP R0, #1 LDRLO PC, =OSIntCtxSw LDREQ PC, =_OSStartHighRdy ; SWI 0x01为第一次任务切换 BL SWI_Exception LDMFD SP!, R0-R3, R12, PCStackSvc DCD (SvcStackSpace + SVC_STACK_LEGTH * 4 - 4)OSIntCtxSw ;下面为保存任务环境 LDR R2, SP, #20 ;获取PC(LR) LDR R12, SP, #16 ;获取R12 MRS R0, CPSR MSR CPSR_c, #(NoInt | SYS32Mode) MOV R1, LR STMFD SP!, R1-R2 ;保存LR,PC STMFD SP!, R4-R12 ;保存R4-R12 MSR CPSR_c, R0 LDMFD SP!, R4-R7 ;获取R0-R3 ADD SP, SP, #8 ;出栈R12,PC MSR CPSR_c, #(NoInt | SYS32Mode) STMFD SP!, R4-R7 ;保存R0-R3 LDR R1, =OsEnterSum ;获取OsEnterSum LDR R2, R1 STMFD SP!, R2, R3 ;保存CPSR,OsEnterSum ;保存当前任务堆栈指针到当前任务的TCB LDR R1, =OSTCBCur LDR R1, R1 STR SP, R1 BL OSTaskSwHook ;调用钩子函数 ;OSPrioCur = OSPrioHighRdy LDR R4, =OSPrioCur LDR R5, =OSPrioHighRdy LDRB R6, R5 STRB R6, R4 ;把OSPrioHighRdy最高优先级的就绪任务传给OSPrioCur ;OSTCBCur = OSTCBHighRdy LDR R6, =OSTCBHighRdy LDR R6, R6 LDR R4, =OSTCBCur STR R6, R4 ;将最高优先级的任务控制块指针传给当前任务控制块指针 关于中断和时钟节拍,UCOS-II对于ARM7通用的中断服务程序的汇编与c函数接口如下:MACRO和MEND伪指令用于宏定义,MACRO标识宏定义的开始,MEND标识宏定义的结束。定义之后在程序中就可以通过宏指令多次调用该段代码MACRO$IRQ_Label HANDLER $IRQ_Exception_ EXPORT $IRQ_Label ; 输出的标号 IMPORT $IRQ_Exception_ ; 引用的外部标号$IRQ_Label SUB LR, LR, #4 ; 计算返回地址 STMFD SP!, R0-R3, R12, LR ; 保存任务环境 MRS R3, SPSR ; 保存状态 STMFD SP, R3, SP, LR ; 保存用户状态的R3,SP,LR,注意不能回写 ; 如果回写的是用户的SP,所以后面要调整SP LDR R2, =
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 委托服务合同 代购机票合同委托安排出差合同5篇
- 辽源二店合同7篇
- 房屋折建合同7篇
- 工程机械租赁合同范本
- 小学语文经典课文的深度教学设计研究
- 代理合同风险及防范
- 2025年品牌保护与品牌营销策略可行性研究报告
- 2025年无人零售店盈利模式可行性研究报告
- 贸易政策变动对2025年国际贸易规则改革影响可行性分析报告
- 2025年户外用品市场渠道研究报告
- 七上语文月考必考名著《朝花夕拾》高频考点简答70道
- 2025榆林镁业(集团)有限公司招聘(9人)考试参考试题及答案解析
- GB/T 10454-2025包装非危险货物用柔性中型散装容器
- 2025年秋统编版九年级上册道德与法治全册知识点复习提纲
- 2025年秋青岛版三年级数学上册第一二单元学业质量检测试题
- 铝材厂跟单员培训课件
- 硫酸安全培训与防范课件
- BIM概述课件教学课件
- 农作物施肥精准手册
- 医疗机构医疗质量安全专项整治行动自查自纠报告
- 中建土建劳务招标标准清单编制参考
评论
0/150
提交评论