原创 (转)ARM经典300问--4

2008-11-23 22:50 2087 4 4 分类: MCU/ 嵌入式
第 126 问:
Q:新旧任务级的切换是不是必须在管理模式下切换   切换后新任务的运行是不是必须在管理模式下

A:在配套《ARM 微控制器基础与实战》里的任务切换是通过 SWI 实现的.SWI 会使 CPU 进入管理模式.同时 CPU 自动将任务的 CPSR 保存到管理模式的 SPSR 中.   SWI 程序还保存了一些寄存器到管理模式的堆栈中.然后任务切换程序会在管理模式和系统模式间来回切换,目的是把保存在管理模式堆栈的寄存器内容拷贝到任务的堆栈中(注意:任务是运   行在用户模式或系统模式的,这两个模式使用同一个 SP,这时的系统模式的 SP 指向的就是任务的堆栈),也会将管理模式的 SPSR 拷贝到任务堆栈(注意管理模式的 SPSR 就是在执行 SWI 时 CPU 自动保存的任务运行时的 CPSR,它记录了任务运行的 CPU 模式和其他的运行状态信息).最后把任务模式 SP 保存到任务的任务控制块中(注意此时 CPU 已经是运行在系统模式下的了).以上大致就是 uC/OS-II 中所说的保存任务运行环境的工作. 

 任务的恢复运行就比较好理解了. 

接着前面的说,CPU 还在系统模式下.程序从任务控制块中得到任务的堆栈指针.   (OSIntCtxSw_1 的第一句)将这个指针的值加上一定的偏移量保存到 SP 中.为什么要加上一定 的偏移量呢  因为这时任务的堆栈中除了保存任务运行时的数据外还保存了任务的上下文,即任   务切换时保存的 CPU 寄存器等内容.而我们恢复任务等一下是在管理模式下进行的,用的是管理模式的堆栈指针.等恢复任务后 CPU 就开始执行任务代码了.我们已经没有机会再修改系统模式下的 SP 值了.所以在这个时候就应该对 SP 进行调整.调整的大小就应该是所保存的上下文占用的大小.从堆栈中恢复 LR 的值.同样的道理,管理模式和系统模式使用不同的 LR,在切换到管理模式之前,必须先在系统模式下恢复任务运行时的 LR.(OSIntCtxSw_1 的第三句)接下来就切换到管理模式了.

(OSIntCtxSw_1 的第四句)使管理模式 SP 指向任务堆栈(第五句)注意这是没调整过的任务 SP,也就是保存了上下文环境的 SP. 

接下来的事情就真的很简单了.从堆栈中恢复出保存的东西.先是 OSEnterSum,然后是任务的 CPSR (注意任务的 CPSR 就是进入 SWI 时由 CPU 自动保存到管理模式的 SPSR 中的,所以此时也是恢复到管理模式的 SPSR 中)最后一句就是典型的中断返回语句了. 恢复寄存器,恢复 PC,加了一个^号意味着同时将 SPSR 拷贝到 CPSR 中.  

现在是回答你的问题的时候了.  切换前任务是运行在什么环境下的(包括 CPU 模式,所有的寄存器),任务切换后任务就是运行在    什么环境下的.对任务来说,什么也没改变.只有 PC 值指向了下一条指令, 哈哈. 

第 127 问: 

Q:请教:在 rtos51 解释的概念里的"信号量"比较难懂,"消息队列"可以理解为任务之间互相传递的参数,但"信号量"怎样理解呢具体一点,谢谢! 

A:信号量是60 年代中期 Edgser dijkstra 发明的,它实际上是一种程序间的约定机制, 这种约定决定那个程序(任务)可以执行.在多任务内核中普遍使用信号量用于: 

1.控制共享资源的使用权(满足互斥条件); 

2.标志某事件的发生; 

3.使两个任务的行为同步. 

信号量像是通行证,且通行证的数目是有限的.任务要运行下去,要先拿到通行证.如果信号量    已被别的任务占用,该任务只得被挂起,直到信号量被当前使用者释放掉. 信号量的值可以是 0 到 255 或 0 到 65535,或 0 到 4294967295,取决于信号量规约机制使用的是 8 位,16 位还是 32 位.到底是几位,实际上是取决于用的那种内核.根据信号量的值,内核跟踪那些等待信号量的任务. 

 一般地说,对信号量只能实施三种操作:初始化,也可称作建立;等信号也可称作挂起; 给信号或发信号.信号量初始化时要给信号量赋初值,等待信号量的任务表应清为空. 想要得到信号量的任务执行等待操作.如果该信号量有效(即信号量值大于 0),则信号量值减 1,任务得以继续运行.如果信号量的值为 0,等待信号量的任务就被列入等待信号量任务表.多数内核允许用户定义等待超时,如果等待时间超过了某一设定值时,该信号量还是无效,则等待信号量的任务进入就绪态准备运行,并返回出错代码(指出发生了等待超时错误).任务以发信号操作释放信号量.如果没有任务在等待信号量,信号量的值仅仅是简单地加 1.如果有任务在等待该信号量,那么就会有一个任务进入就绪态,信号量的值也就不加 1.于是通行证给了等待信号量的诸任务中的一个任务.至于给了那个任务,要看内核是如何调度的.收到信号量的任务可能是以下两者之一: 

1.等待信号量任务中优先级最高的任务; 

2.最早开始等待信号量的那个任务,即按先进先出的原则(FIFO). 

有的内核有选择项,允许用户在信号量初始化时选定上述两种方法中的一种.但 SmallRTOS51 只   支持优先级法.如果进入就绪态的任务比当前运行的任务优先级高(假设, 是当前任务释放的信号量激活了比自己优先级高的任务).则内核做任务切换(假设,使用的是占先式内核),高优先级的任务开始运行.当前任务被挂起.直到又变成就绪态中优先级最高任务. 

第 128 问: 

Q:我用了两个串口,但当我把程序做大的时候,发现在这个任务里所建立的邮箱失败,  我只用一个串口时是没有这种事情的. 

Uart0ReviceMbox = OSMboxCreate((void *)0 );  

if (Uart0ReviceMbox == NULL) 



while (1); 



 我想问一下有几种可能会造成这种分配失败我的程序存储器用量如下: 

Total R0 size 22168 

Total RW size 7956 

Total ROM size 22168 

A:在 OS_CFG.H 中定义最大事件数,太小的话,分配会失败的. 

第 129 问: 

Q:在周立功的原例子中,系统代码事先烧到 ROM 中,应用代码在 RAM 中运行.我想知道, (RAM)应用代码调用系统函数,那么 2104 是如何把 ROM 中的系统函数的地址传递给 RAM, 也就是应用代码和系统代码是如何关联在一起的 我猜是通过 swi(软中断),应用代码通过 swi 调用系统代码,但是 swi 中断程序中,是如何获得烧到 RAM 中的系统函数的地址哪百思不得其解. 

A:您看一看 romcode 工程中 swi 的 0x40 和 0x41 功能, 

及 Os_call.c,Os_call_arm.s,Usr_call_arm.s. 

 

第 130 问: 

Q:16k 的 RAM,128 的 FLASH ROM 跑 uc/os-II 够吗再跑点应用程序够吗

A:取决于您的应用程序对 RAM 的需求,及代码量.一般程序可以.

第 131 问: 

Q:利用 lpc2104 开发应用程序时,在 Os_call_arm.s,Os_call.c 两个文件中,那几个函数

需要在汇编中实现,哪几个需要在.c  文件中实现,为什么谢谢各位大虾  ! 

A:4 个以上参数用 c 实现.因为通过寄存器只能传递 4 个参数. 

第 132 问: 

Q:如果禁止 SmallRTOS51 进行中断嵌套管理(#define EN_OS_INT_ENTER 0),是否还需要设置中断优先级寄存器 IP,使得所有中断的优先级都相同(全高或全低) 

A:受 SmallRTOS51 管理的设置为最低优先级,不受 SmallRTOS51 管理的设置其它优先级较好. 

 第 133 问: 

Q:在 OS_CPU_S.s 文件中有如下一段代码,其中有两句代码的作用不是很明白,请解说一下. 

OSIntCtxSw_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 }^ ;运行新任务

A:这两条指令是在系统模式下恢复用户模式下的 LR;可以参考配套《ARM 微控制器基础与实战》6.4.9 节. 

  第 134 问: 

Q:我将《ARM 微控制器基础与实战》上 uC/OS-II 的第一章例 2 移植例在 ARM2104 开发版上实现例 2 中的 TEST.C 中的"#define TASK_STK_SIZE 512"改为"...256",程序编译后,数据量低于 16K,能正常运行,但运行时"Total Stack"不是 256 全是 1024.另UC/OS-II 书上,第一章例 2 每一个任务的堆栈都是 512,为什么书上 11 页"Total Stack" 是"624,1024,1024,1024,1024,1024,1024",请老师指点,万分感谢! 

A:显示的是字节而定义的是字. 

 第 135 问: 

Q:可不可以把所有的任务和相关信号量(二值)在一个任务里面一起创建呢    我现在是这样做的,  不知是不是这方面的原因而且全部信号量是这样创建的: 

XX1 = OSSemCreate(0); 

XX2 = OSSemCreate(0); 

XX3 = OSSemCreate(0); 

一共创建了十个信号量,以前程序代码版本是分开写的执行起来没有问题,不知现在为什么这样写就会出现小问题呢这样的问题和我的任务和信号里书写位置有关系吗

A:必须在使用信号量前创建信号量. 

 第 136 问: 

Q:UCOS 在中断处理完后调用  OSIntExit(),该函数将判断是不是要进行任务切换,如果是则调用  OSIntCtxSw()切换任务,  然后才恢复寄存器,中断返回.这样说来,在中断返回前,已经切换到别的任务去了,在再次回到被中断的任务前,是不是一直没有中断返回

A:如果进行任务调度,则不会执行 OSIntCtxSw()后的语句,相当于中断已退出. 

第 137 问: 

Q:最近我在学习使用 SMALL RTOS  时发现一个  BUG. 

任务在调用系统等待函数  OSWait(K_TMO | K_SIG,x)  后,不能在延时  x  个  ticks  后被唤醒. 

我分析了一下原因如下: 

在  OS_CORE.C uint8 OSWait(uint8 typ, uint8 ticks) small  中, 

case (K_TMO | K_SIG):  中执行了函数  OSTaskSuspend(OSTaskID); 

( OS_CORE.C  第 549 行)而此函数将延时值改为了  0! 

 解决办法:将此函数改用另一个函数  OS_TaskSuspend(TaskID); 

并在其后加入任务切换函数  OSSched();  便能工作正常. 

A:对,这是疏忽,谢谢.您的更改是对的. 

 第 138 问: 

Q:在文件 Os_cpu_a.s 中的函数 OSIntCtxSw 中有如下语句: 

…… 

(1) LDR R4, [R6] 

(2) ADD SP, R4, #68 

;17 寄存器  CPSR,OsEnterSum,R0-R12,LR,SP 

(3) LDR LR, [SP, # --8] 

(4) MSR CPSR_c, #(NoInt | SVC32Mode) ;进入管理模式

(5) MOV SP, R4 

…… 

(6) LDMFD SP!, {R0-R12, LR, PC }^ ;运行新任务

 《ARM 微控制器基础与实战》404 页中解释:只所以要(1)(2)是因为"OSTCBHighRdy

—>OSTCBStkPtr 保存的是任务栈位置,而寄存器恢复后堆栈指针并不指向这,所以要调整新任务堆栈指针."  可是将堆栈指针调整到  "新任务入栈的其它数据(见《ARM 微控制器基础与实战》图 6.3)"处后,除了取出了 LR 以外并没有做 什么,而当执行了(4) 后又重新将堆栈指针指向了栈顶(即第(5)句).我认为可以将(2)省去,直接将(3)改为LDR LR, [SP, # 60]",而当执行完(6)后,堆栈指针就自动指向了"新任务入栈的其它数据"处.这样修改后我运行了 EX1_arm 例子,正常. 

请问这利用(3)进行堆栈指针调整的原因是什么不调整可以吗   谢谢. 

A:注意不同模式有不同的 SP 指针.您这样做会造成内存泄漏,长时间运行会耗尽堆栈而使程序崩溃. 

 第 139 问: 

Q:不明白在光盘上 ROMCODE/SRC/下的 os_call.c 做什么用. 

A:是应用程序与事先固化到 flash 中的 ucosii 接口的一些代码.在本例中为应用程序如何调用事先    固化到 flash 中的 ucosii 的 OSFlagPend 等函数的接口代码.请看配套《ARM 微控制器基础与实战》的 7.4.3 节的第 10 点. 

 第 140 问: 

Q:请问在 OS_CORE.C 中的常数数组 OSUnMapTbl[]是做什么用的

A:用来计算优先级的,查表计算比较快.   

第 141 问: 

Q:ucos 的中断嵌套层数是否受到初始化时分配的 IRQ 堆栈大小的限制我的理解是每一次中断需入栈的寄存器有 R0-R3,R12,LR,SPSR,共 7 个,如果想达到 8 层嵌套的话,堆栈长度 IRQ_STACK_LEGTH 应设为 56,不知这样理解对不对. 

A:是,但中断至少占用 8 个字,因为 c 语言的中断处理函数会将一些数据压入堆栈.   要达到 8 级嵌套需要的堆栈长度与具体的代码有关. 

(编者注:新移植代码已有改变) 

 第 142 问: 

Q:请问:核心定时器中断不进入可能因为……

我的程序在运行一段时间以后,核心定时器中断即操作系统用的 Timer0 不能进入,查发现 CPSR 的 I 位为 1,请教这可能是哪个原因

A:估计为开关中断次数不匹配造成. 

 第 143 问: 

Q:请问:GetOSPprioCur()函数应怎样调用它是一个内核函数吗

为什么我在内核和任务分别编译时正常,而合到一起编译时它告警为未定义呢

同时我已给您发了一个邮件,请教如何将分别编译的程序合在一起编译的方法,请指教! 

A:这是我自己编写的函数,其实就是返回 OSPrioCur 的值,请参考 MyFunction.c. 

 第 144 问: 

Q:关于不受 uc/os 控制的中断:在 ARM 板中,非屏蔽中断可以挂起正在执行的 uc/os 任务, 除了不能使用 uc/os  中的函数外,它的执行工序是不是和受管理的中断一样,先挂起当前任务,再保存 CPU 寄存,然后再执行中断 ISR,完成后,内核脱离,寄存器恢复,最后任务调度. 

另外,《ARM 微控制器基础与实战》中提到不受管理的中断,它的工作是否和非屏蔽中断一样,也可以在 uc/os 正执行时发生中断.如果不同,它们是怎样工作

最好是象受管理中断一样说明一下它的工作时序! 

A:必须比受管理的中断的优先级高,编写方法与没有 OS 时中断的编写方法一样. 

 第 145 问: 

Q:不受 uc/os-ii 管理的中断和受管理的中断是否具有相同的响应方式,即不受管理的中断在中断  uc/os 正执行的任务后,是不是也是先挂起当前的任务,保存 CPU 寄存器,再执行中断子程序,恢复 CPU 寄存器,进行最优先级任务的调度. 

A:不受 uc/os-ii 管理,uc/os-ii 都不知道,还有什么任务调度

Q:我知道不受管理的中断不能调用 uc/os 的函数,但《ARM 微控制器基础与实战》上说: FIQ 不受 uc/os 管理,但可以用来执行紧急任务,就是说在 uc/os 运行时,不受 uc/os管理的中断还是可以发生的,它是把整个 uc/os 操作系统中止,还是只是中止 uc/os 正在执行的任务.不受管理的中断完成后,接着执行什么

A:可以发生,中断整个 RTOS. 

Q:我看了您在 lpc210x 上的移植代码,你在说明中说:"如果您想通过软件仿真,请将target.c 中的第  51 行屏蔽,  这样就可以看到任务逐个切换,最后将进入空闲任务." 我照这做了,但是在单步或者设断点执行时会产生异常,原因是未定义指令

OS_ENTER_CRITICAL()引起的,经过编译的函数都会变成蓝色,但这个函数还是黑色,因为它实际上是一个软中断,请教您如何调试才能看到任务逐个切换    谢谢! 

A:1.屏蔽的那一行是死等锁相环锁定,软件仿真时是没有锁相环的. 

2.黑色是正常的,因为没有定义成函数. 

3.因为你的  AXD -> OPTION -> 配置处理器中的  VECTOR CATCH  中的  S  选中了,所以  AXD 将你的软件中断当成了异常给捕捉了,取消即可. 

 第 146 问: 

Q:请教 ucos2 的源代码中经常碰到:return((void*)0)是什么意思

A:返回空指针. 

 第 147 问: 

Q:这是个什么错误,怎么改啊

OsMemPut  是个函数名称

Error : L6200E: Symbol OSMemPut multiply defined (by uCOS_II.o and 

Os_mem.o). 

A:这是重复定义错误.请不要把 uCOS_II.C 添加到你的工程中. 

第 148 问: 

Q:我想请教一下在配套光盘中有没有 ucosII.h 文件,怎么我总是找不到的

如没有能否提供下载地方谢谢! 

A:北航出版的<>第 2 版就带有 uC/OS 2.52 源代码, 

还可以到其它网站上找找. 

 第 149 问: 

Q:我想问一下一个任务中的子函数的局部变量算不算进堆栈的容量. 

我发现我在用邮箱传递一个较大的值时,是在一个任务的函数中声明了 uint8 

byte[500],可在传递时值发送了变化,只好用的外部变量了,最后搞得邮箱只起了信号量的作用,所以我觉得局部变量虽然是从堆栈中取得数据,最后在任务切换时,把局部变量也保存到堆栈中,不知道我这种理解是否正确

A:算.局部变量在函数退出后(不管任务是否却换过)被释放. 

 第 150 问: 

Q:我用 UCOS 在 EASYARM 上的一个程序内编写了 5 个任务,前 4 个任务调试后工作正常,在编译第 5 个任务时,提示为: 

Execution region ER_RO overlaps with Execution region ER_ZI. 

编译还提示: 

TOTAL ROM SIZE (CODE +RO DATA +RW DATA ) 8624 

我曾经试图修改"#define TASK_STK_SIZE 64 "也不管用,请问,如何解决

A:问题已找到,代码超过 16K.上面的信息会在 zi 段或者 rw 段与 ro 段(代码段)发生重叠时发生. 

 第 151 问: 

Q:请教 uc/os 移植问题

在 2104 上面能进行移植吗如果不行的话,需要买 2106 

A:你要在 os_cfg.h 中把不用的内部调用都裁减掉,就可以做一个很小的内核,就是不裁减你就是 14k 左右,写在 FLASH 里一样也能运行. 

 第 152 问: 

Q:请教信号量的概念问题. 

我准备用信号量来编写一个 ARM 程序,但我没有完全理解信号量的概念. 

例如:现在有 4 个任务:TASK1,TASK2,TASK3 和 TASK4,任务的要求是:TASK1 和 TASK2 之间需有信号量传递信息;TASK3 和 TASK4 之间需也有信号量传递信息.   假定 TASK1 和 TASK2 之中已建立了一个信号量为

RandomSem = OSSemCreate(1); 

我要问的问题是:TASK3 和 TASK4 之中的信号量是否需重新建立一个例如,加一条RandomSem1 = OSSemCreate(1); 

换一个问法:即若 TASK1 和 TASK2 之间需有信号量传递信息; 

TASK3 和 TASK4 之间需也有信号量传递信息,我只需在运行这 4 个任务之前的初始化程序中有一条指令即可:RandomSem = OSSemCreate(1); 

A:用两个信号量,你第一个说法对了. 

 第 153 问: 

Q:各位:在 UCOS 多任务中有一个任务结构如下: 

void TASK(*pdata) 



uint8 i; 

任务循环前的一些指令集 A; 

while(1) 


PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
4
关闭 站长推荐上一条 /3 下一条