ImageVerifierCode 换一换
格式:DOCX , 页数:9 ,大小:18.49KB ,
资源ID:5519872      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/5519872.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(综述+任务堆栈初始化过程分析.docx)为本站会员(b****3)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

综述+任务堆栈初始化过程分析.docx

1、综述+任务堆栈初始化过程分析 窗体顶端 综述+任务堆栈初始化过程分析2010-10-27 03:40转载自 likunyuan最终编辑 chiefsniper首先在看本文时有以下几个知识点需要了解:1、为什么我要把工作模式切换在管理模式呢?答:根据第二版的ARM体系结构参考手册,我们可以查看到在用户模式和系统模式下,使用LDM指令时,会导致对不可预知的错误。但是在IAREWARM环境下,对系统初始化时,是默认将ARM切换到系统模式的,因此在uCOS-II启动时,我们默认的将系统切换到管理模式下工作。这样就可以避免了在使用LDM指令时产生不可预知的错误了。2、着重强调一下在OS_CPU_A.A中

2、汇编指令中的BX指令,为什么要强调呢?答:根据第二版的ARM体系结构参考手册,在ARM体系的T变种版本4、ARM体系版本5及其以上版本。BX指令把通用寄存器Rm中的值拷贝到PC,同时判断拷贝后的PC寄存器的第0位值是否是1,如果第0位的值是1,则将当前处理器切换到Thumd指令集下进行执行。3、此处再讲解一下向PC寄存器写操作的注意事项,为什么要强调呢?答:根据第二版的ARM体系结构参考手册,我们可知,在向该寄存器进行写操作时会导致程序跳转到写入PC寄存器的地址处进行执行。在ARM指令集必须要求是字对齐的,那么写入PC寄存器的值得最低2位就必须为0;在Thumd指令集下必须是半字对齐的,那么写

3、入PC寄存器的值得最低1位就必须是0;ARM体系的版本较多,在ARM体系版本3及其以下版本,在ARM指令下写入PC寄存器的最低2位是被忽略了的(也就是说是由硬件实现PC = PC&0xFFFFFFFC操作)在ARM体系版本4及其以上版本,在ARM指令下写入PC寄存器的最低2位值是必须为0的,这部分是必须软件完成的,即:在将地址写入PC之前,必须将地址的值与0xFFFFFFFC进行与操作,再将操作的结果传递给PC寄存去。在Thumd指令集下要求所有指令为半字对齐,因此写入PC寄存器的值必须先与0xFFFFFFFE进行与操作,然后再将与操作的结果传递给PC寄存器。4、特别提到大家注意一下LDM指令

4、。为什么呢?答:该指令只能在ARM指令集中,在Thumd指令集中是没有该指令的。在查看到ARM+Architecture+Reference+Manual(2nd+Edition)手册后,会发现对于LDM的操作有如下操作,用示意性代码表示如下:If 条件满足Address = start_addressFor( I = 0 ; I = 14 ; i+)If (register_list = 1)Ri = Memoryaddress,4;Address += 4 ;If(register_list15 = 1)value = memoryaddress,4;If( ARM体系5版本及其以上版本)

5、PC = value & 0xFFFFFFFET bit = Value0 ;ElsePC = value&0xFFFFFFFCAddress = address + 4 ;上面的示意性代码意思就是说,如果LDM的目的操作数包含PC寄存器的话,写入PC寄存器的值得最后一位路过时1的话,执行完毕LDM指令后,处理器就会切换到Thumd模式。本次分析所使用到的资料或书籍如下:1、ARM+Architecture+Reference+Manual(2nd+Edition)2、ARM体系结构与编程-杜春蕾3、嵌入式实时操作系统COS-II(第二版)-邵贝贝翻译4、ARM IAR Assembler R

6、eference Guide5、IAR Embedded Workbench IDE User Guide6、IAR C/C+ Development Guide Compiling and linking 7、LPC2103的datasheet8、ARM and Thumb-2 Instruction Set Quick Reference Card9、Thumb 16-bit Instruction Set Quick Reference Card10、ARM7TDMI-S Technical Reference Manual转自Tony嵌入式论坛,地址:文中所示代码下载:(稍后提供)下面

7、先探讨一下LPC2103这个芯片的堆栈空间。我们在建立该项目之前,就对编译器设置了该工程的endian mode为little。Endian模式不清楚的就去查查ARM体系结构与编程,这里就不多说了。在以ARM7TDMI-S为内核的ARM芯片,其堆栈增长方向是由高地址向低地址增长。因此我们给每个任务分配的堆栈也必须按照这样的方式进行“push”和“pop”操作。即可这样理解:1、当我们在任务堆栈上执行类似的“push”操作时,首先将所需保存的数据压入到堆栈中,然后再对“任务的SP寄存器的值“-4。(这里-4的偏移量是因为我的整个移植代码都是在ARM指令集下进行的所以偏移量的设置是4);2、当我们

8、在任务堆栈上执行类似的“pop“操作时,首先将堆栈中的数据弹出堆栈,然后再对”任务的SP寄存器的值“+4。(这里+4的偏移量是因为我的整个移植代码都是放在ARM指令集下进行的,所以偏移量的设置是4);任务堆栈的初始化过程分析一、OSTaskStkInit函数好了,现在就可以进行我们的代码移植分析了。首先是对任务堆栈的初始化工作,代码如下:#define ARM_MODE_ARM 0x00000000#define ARM_MODE_THUMB 0x00000020#define ARM_SVC_MODE_THUMB (0x00000013L + ARM_MODE_THUMB)#define A

9、RM_SVC_MODE_ARM (0x00000013L + ARM_MODE_ARM)OS_STK *OSTaskStkInit (void (*task)(void *p_arg), void *p_arg, OS_STK *ptos, INT16U opt)OS_STK *stk;INT32U task_addr;opt= opt;stk= ptos;task_addr = (INT32U)task & 1;*(stk)= (INT32U)task_addr;/PC*(-stk)= (INT32U)0x14141414L;/R14*(-stk)= (INT32U)0x12121212L;

10、/R12*(-stk)= (INT32U)0x11111111L;/R11*(-stk)= (INT32U)0x10101010L;/R10*(-stk)= (INT32U)0x09090909L;/R9*(-stk)= (INT32U)0x08080808L;/R8*(-stk)= (INT32U)0x07070707L;/R7*(-stk)= (INT32U)0x06060606L;/R6*(-stk)= (INT32U)0x05050505L;/R5*(-stk)= (INT32U)0x04040404L;/R4*(-stk)= (INT32U)0x03030303L;/R3*(-stk

11、)= (INT32U)0x02020202L;/R2*(-stk)= (INT32U)0x01010101L;/R1*(-stk)= (INT32U)p_arg;/R0if (INT32U)task & 0x01) *(-stk) = (INT32U)ARM_SVC_MODE_THUMB; else *(-stk) = (INT32U)ARM_SVC_MODE_ARM;return (stk);现在一句一句来分析:1、opt= opt;stk= ptos;这两句放到这里是没有任何实际意义,只是为了防止编译器报警;2、task_addr = (INT32U)task & 1;这一句可能很多人都不

12、理解,干嘛还要对任务的地址&1呢?答:实际上任务的地址(就是调用函数的起始地址)是要在LDMFD写入到PC的,而对于LDM的操作,写入PC的最后1bit会影响到处理器是否切换到Thumd模式下的,我在这里将任务地址的最后1bit清0,是为了保证任务在ARM模式下进行工作的。因为在部分ARM指令和Thumd指令混合编译的情况下,可能会导致整个uCOS系统崩溃的。加上这一句就能很好的保证系统在进行任务切换的时候,所有指令均能在ARM指令系统下工作。我说了是不是大家就很清楚了呢?3、*(-stk)= (INT32U)0x14141414L;/R14很多朋友可能会在这一句上有非常大的疑问了,R14寄存

13、器不是LR寄存器么?这个可以存储子程序的返回地址或者是存储分子语句的返回地址啊?怎么这里会对R14赋值成(INT32U)0x14141414L。这样做会不会让整个系统工作不正常啊?答:回答这个问题,就要用uCOS对于任务的定义了,在uCOS处理机制中,所有的任务都是一个包含死循环的函数,死循环中是根本就不会有返回地址的了,所以这里随便写入一个值都不会影响到任务的正常运行的。4、对R12和R1的初始化,大家可能又要问了,干嘛这样赋值啊?答:实际上对任务的初始化时在任务运行之前进行的,一个任务都还没有运行,他有怎么可能有影响R1到R12的值了,对于这点大家可以想象一下一个前后台的系统在程序刚开始执

14、行的时候是否会需要使用到这些寄存器呢?所以初始化这些寄存器根本就不会对任务运行有任何影响。5、*(-stk)= (INT32U)p_arg;这个是对R0寄存器的初始化。为什么要这样做呢?相信熟悉IAREWARM的朋友可能会知道(当然不知道的话,建议去做一个简单的测试程序),所有函数的第一个形式参数都是传递给R0的。P_arg就是我们建立的任务的第一个形参,尽管很多朋友在这个形参的设计上没有使用到。注意:实际上MDK也是用R0作为函数的第一个形参压栈处理的。6、对于最后的最后一个参数的初始化时对当前任务运行的异常模式和ARM或Thumd模式的一个压入堆栈的操作。7、还有的朋友可能会问道,怎么没有

15、看到对SP寄存器的保存呢?答:SP寄存器的保存实际是将SP寄存器的值保存到TCB的数据结构中了,所以这里就不再需要对SP进行重复保存了。在这个函数完成以后,任务的任务堆栈就像下面的方式建立了:低地址CPSRARM_SVC_MODE_ARM|R0(INT32U)p_argR10x01010101LR20x02020202LR30x03030303LR40x04040404LR50X05050505LR60X06060606LR70X07070707LR80X08080808LR90X09090909LR100X10101010LR110X11111111LR120X12121212LLR0X14141414L高地址PC(INT32U)task & 1转自Tony嵌入式论坛,地址:

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1