共2条
1/1 1 跳转至页
ucosII,OSIntCtxSw ucosII 的函数OSIntCtxSw看不懂的几个地方,请教周公
问
OSIntCtxSw
;下面为保存任务环境
1 LDR R2, [SP, #20] ;获取PC
2 LDR R12, [SP, #16] ;获取R12
3 MRS R0, CPSR
4 MSR CPSR_c, #(NoInt | SYS32Mode)
5 MOV R1, LR
6 STMFD SP!, {R1-R2} ;保存LR,PC
7 STMFD SP!, {R4-R12} ;保存R4-R12
8 MSR CPSR_c, R0
9 LDMFD SP!, {R4-R7} ;获取R0-R3
10 ADD SP, SP, #8 ;出栈R12,PC
11 MSR CPSR_c, #(NoInt | SYS32Mode)
12 STMFD SP!, {R4-R7} ;保存R0-R3
13 LDR R1, =OsEnterSum ;获取OsEnterSum
14 LDR R2, [R1]
15 STMFD SP!, {R2, R3} ;保存CPSR,OsEnterSum
;保存当前任务堆栈指针到当前任务的TCB
16 LDR R1, =OSTCBCur
17 LDR R1, [R1]
18 STR SP, [R1]
19 BL OSTaskSwHook ;调用钩子函数
;OSPrioCur <= OSPrioHighRdy
20 LDR R4, =OSPrioCur
21 LDR R5, =OSPrioHighRdy
22 LDRB R6, [R5]
23 STRB R6, [R4]
;OSTCBCur <= OSTCBHighRdy
24 LDR R6, =OSTCBHighRdy
25 LDR R6, [R6]
26 LDR R4, =OSTCBCur
27 STR R6, [R4]
OSIntCtxSw_1
;获取新任务堆栈指针
28 LDR R4, [R6]
29 ADD SP, R4, #68 ;17寄存器CPSR,OsEnterSum,R0-R12,LR,SP
30 LDR LR, [SP, #-8]
31 MSR CPSR_c, #(NoInt | SVC32Mode) ;进入管理模式
MOV SP, R4 ;设置堆栈指针
32 LDMFD SP!, {R4, R5} ;CPSR,OsEnterSum
;恢复新任务的OsEnterSum
LDR R3, =OsEnterSum
STR R4, [R3]
MSR SPSR_cxsf, R5 ;恢复CPSR
LDMFD SP!, {R0-R12, LR, PC }^ ;运行新任务
问1:前三行代码是不是运行在管理模式下,sp是不是管理模式下的堆栈指针?
2:第31行为什么要进入管理模式,新任务的环境不是保存在用户模式下的任务堆栈吗?那接下来的MOV SP, R4,R4的值为系统模式下的任务堆栈的指针,而sp为管理模式下的堆栈指针,那这两个堆栈不是重叠了?
3:第28行,29行 ,30行作用是什么,好像没有什么目的,
4:第32行,为什么r5为cpsr呢?狂看晕了.....
答 1: Re:xianfei5201:前三行代码是不是运行在管理模式下,sp是不是管理模式下的堆栈指针?
Ans: 周公的移植代码调用关系为:IRQ HANDLER(IRQ.inc文件中)->OSIntExit->OSIntCtxSw
我把IRQ.inc中的代码贴出来就清楚了:
MSR CPSR_c, #(NoInt | SYS32Mode) ; 切换到系统模式
LDR R2, =OsEnterSum ; OsEnterSum,使OSIntExit退出时中断关闭
MOV R1, #1
STR R1, [R2]
BL OSIntExit
答 2: 4:第32行,为什么r5为cpsr呢?Ans:29 ADD SP, R4, #68 ;17寄存器CPSR,OsEnterSum,R0-R12,LR,SP
29行的注释说该段代码的堆栈结构如:CPSR,OsEnterSum,R0-R12,LR,SP
经过LDMFD SP!, {R4, R5} ;CPSR,OsEnterSum
R4里面OsEnterSum
R5里面CPSR
答 3: 3:第28行,29行 ,30行作用是什么,好像没有什么目的,Ans:用作是访问堆栈成员,很多编译器生成的代码喜欢用SP+offset,即SP为基址外加偏移量的方式来访问堆栈里面的数据成员,这样有点类似于数组的下标索引,当访问第5个元素时,就不需要先把前四个元素Pop了。
偶觉得 ADD SP, R4, #68
LDR LR, [SP, #-8]
看起来很混乱,若直接用LDR LR, [SP, #-60],就可以了,真是很难理解为什么要先ADD 答 4: 2:第31行为什么要进入管理模式Ans:因为SWI会使ARM进入管理模式,这些操作可能跟SWI函数有关,楼主可以研究下zlg code的SWI部分 答 5: 非常感谢terrence的解答。还有些疑问,请教下;以下是在OS_CPU_s.s中的函数softwareinterrupt程序
;SoftwareInterrupt
1) LDR SP, StackSvc ;
2) STMFD SP!, {R0-R3, R12, LR}
3) MOV R1, SP ;
MRS R3, SPSR
TST R3, #T_bit ;
LDRNEH R0, [LR,#-2] ;
BICNE R0, R0, #0xff00
LDREQ R0, [LR,#-4] ;
BICEQ R0, R0, #0xFF000000
;
CMP R0, #1
LDRLO PC, =OSIntCtxSw
LDREQ PC, =__OSStartHighRdy ;
BL SWI_Exception
LDMFD SP!, {R0-R3, R12, PC}^
StackSvc DCD (SvcStackSpace + SVC_STACK_LEGTH * 4 - 4)
问题是:第一行中 LDR SP, StackSvc ,表示将StackSvc堆栈栈顶指针给三sp,这在什么模式下给的。。我估计是应该是在svc模式下,可是没有看到 MSR CPSR_c, #(NoInt | SVC32Mode)的语句啊。。。
答 6: SWI使处理器进入SVC状态...正如IRQ使处理器进入IRQ状态一样 答 7: re 答 8: re:terrence:我今天调试了半天自己写的uc/os-ii的程序,
对于上面的知识有了直观的了解。。但是,对于uc/os-ii从main函数开始执行的顺序。今天郁闷惨了。。。。什么时候能求教一二不,,非常感谢老兄 答 9: 不错原来这里这么多ucOS高手!~ 答 10: re:terrence 兄。。 答 11: re:"3:第28行,29行 ,30行作用是什么,好像没有什么目的,
Ans:用作是访问堆栈成员,很多编译器生成的代码喜欢用SP+offset,即SP为基址外加偏移量的方式来访问堆栈里面的数据成员,这样有点类似于数组的下标索引,当访问第5个元素时,就不需要先把前四个元素Pop了。
偶觉得 ADD SP, R4, #68
LDR LR, [SP, #-8]
看起来很混乱,若直接用LDR LR, [SP, #-60],就可以了,真是很难理解为什么要先ADD"
使用ADD SP, R4, #68
LDR LR, [SP, #-8]
这两句是为了将sp指向pc+1之前的位置,这样的话,就不要会有资源浪费了。。
老兄可以把ostaskstkinit()确定的任务栈好好看看就知道了。。
;下面为保存任务环境
1 LDR R2, [SP, #20] ;获取PC
2 LDR R12, [SP, #16] ;获取R12
3 MRS R0, CPSR
4 MSR CPSR_c, #(NoInt | SYS32Mode)
5 MOV R1, LR
6 STMFD SP!, {R1-R2} ;保存LR,PC
7 STMFD SP!, {R4-R12} ;保存R4-R12
8 MSR CPSR_c, R0
9 LDMFD SP!, {R4-R7} ;获取R0-R3
10 ADD SP, SP, #8 ;出栈R12,PC
11 MSR CPSR_c, #(NoInt | SYS32Mode)
12 STMFD SP!, {R4-R7} ;保存R0-R3
13 LDR R1, =OsEnterSum ;获取OsEnterSum
14 LDR R2, [R1]
15 STMFD SP!, {R2, R3} ;保存CPSR,OsEnterSum
;保存当前任务堆栈指针到当前任务的TCB
16 LDR R1, =OSTCBCur
17 LDR R1, [R1]
18 STR SP, [R1]
19 BL OSTaskSwHook ;调用钩子函数
;OSPrioCur <= OSPrioHighRdy
20 LDR R4, =OSPrioCur
21 LDR R5, =OSPrioHighRdy
22 LDRB R6, [R5]
23 STRB R6, [R4]
;OSTCBCur <= OSTCBHighRdy
24 LDR R6, =OSTCBHighRdy
25 LDR R6, [R6]
26 LDR R4, =OSTCBCur
27 STR R6, [R4]
OSIntCtxSw_1
;获取新任务堆栈指针
28 LDR R4, [R6]
29 ADD SP, R4, #68 ;17寄存器CPSR,OsEnterSum,R0-R12,LR,SP
30 LDR LR, [SP, #-8]
31 MSR CPSR_c, #(NoInt | SVC32Mode) ;进入管理模式
MOV SP, R4 ;设置堆栈指针
32 LDMFD SP!, {R4, R5} ;CPSR,OsEnterSum
;恢复新任务的OsEnterSum
LDR R3, =OsEnterSum
STR R4, [R3]
MSR SPSR_cxsf, R5 ;恢复CPSR
LDMFD SP!, {R0-R12, LR, PC }^ ;运行新任务
问1:前三行代码是不是运行在管理模式下,sp是不是管理模式下的堆栈指针?
2:第31行为什么要进入管理模式,新任务的环境不是保存在用户模式下的任务堆栈吗?那接下来的MOV SP, R4,R4的值为系统模式下的任务堆栈的指针,而sp为管理模式下的堆栈指针,那这两个堆栈不是重叠了?
3:第28行,29行 ,30行作用是什么,好像没有什么目的,
4:第32行,为什么r5为cpsr呢?狂看晕了.....
答 1: Re:xianfei5201:前三行代码是不是运行在管理模式下,sp是不是管理模式下的堆栈指针?
Ans: 周公的移植代码调用关系为:IRQ HANDLER(IRQ.inc文件中)->OSIntExit->OSIntCtxSw
我把IRQ.inc中的代码贴出来就清楚了:
MSR CPSR_c, #(NoInt | SYS32Mode) ; 切换到系统模式
LDR R2, =OsEnterSum ; OsEnterSum,使OSIntExit退出时中断关闭
MOV R1, #1
STR R1, [R2]
BL OSIntExit
答 2: 4:第32行,为什么r5为cpsr呢?Ans:29 ADD SP, R4, #68 ;17寄存器CPSR,OsEnterSum,R0-R12,LR,SP
29行的注释说该段代码的堆栈结构如:CPSR,OsEnterSum,R0-R12,LR,SP
经过LDMFD SP!, {R4, R5} ;CPSR,OsEnterSum
R4里面OsEnterSum
R5里面CPSR
答 3: 3:第28行,29行 ,30行作用是什么,好像没有什么目的,Ans:用作是访问堆栈成员,很多编译器生成的代码喜欢用SP+offset,即SP为基址外加偏移量的方式来访问堆栈里面的数据成员,这样有点类似于数组的下标索引,当访问第5个元素时,就不需要先把前四个元素Pop了。
偶觉得 ADD SP, R4, #68
LDR LR, [SP, #-8]
看起来很混乱,若直接用LDR LR, [SP, #-60],就可以了,真是很难理解为什么要先ADD 答 4: 2:第31行为什么要进入管理模式Ans:因为SWI会使ARM进入管理模式,这些操作可能跟SWI函数有关,楼主可以研究下zlg code的SWI部分 答 5: 非常感谢terrence的解答。还有些疑问,请教下;以下是在OS_CPU_s.s中的函数softwareinterrupt程序
;SoftwareInterrupt
1) LDR SP, StackSvc ;
2) STMFD SP!, {R0-R3, R12, LR}
3) MOV R1, SP ;
MRS R3, SPSR
TST R3, #T_bit ;
LDRNEH R0, [LR,#-2] ;
BICNE R0, R0, #0xff00
LDREQ R0, [LR,#-4] ;
BICEQ R0, R0, #0xFF000000
;
CMP R0, #1
LDRLO PC, =OSIntCtxSw
LDREQ PC, =__OSStartHighRdy ;
BL SWI_Exception
LDMFD SP!, {R0-R3, R12, PC}^
StackSvc DCD (SvcStackSpace + SVC_STACK_LEGTH * 4 - 4)
问题是:第一行中 LDR SP, StackSvc ,表示将StackSvc堆栈栈顶指针给三sp,这在什么模式下给的。。我估计是应该是在svc模式下,可是没有看到 MSR CPSR_c, #(NoInt | SVC32Mode)的语句啊。。。
答 6: SWI使处理器进入SVC状态...正如IRQ使处理器进入IRQ状态一样 答 7: re 答 8: re:terrence:我今天调试了半天自己写的uc/os-ii的程序,
对于上面的知识有了直观的了解。。但是,对于uc/os-ii从main函数开始执行的顺序。今天郁闷惨了。。。。什么时候能求教一二不,,非常感谢老兄 答 9: 不错原来这里这么多ucOS高手!~ 答 10: re:terrence 兄。。 答 11: re:"3:第28行,29行 ,30行作用是什么,好像没有什么目的,
Ans:用作是访问堆栈成员,很多编译器生成的代码喜欢用SP+offset,即SP为基址外加偏移量的方式来访问堆栈里面的数据成员,这样有点类似于数组的下标索引,当访问第5个元素时,就不需要先把前四个元素Pop了。
偶觉得 ADD SP, R4, #68
LDR LR, [SP, #-8]
看起来很混乱,若直接用LDR LR, [SP, #-60],就可以了,真是很难理解为什么要先ADD"
使用ADD SP, R4, #68
LDR LR, [SP, #-8]
这两句是为了将sp指向pc+1之前的位置,这样的话,就不要会有资源浪费了。。
老兄可以把ostaskstkinit()确定的任务栈好好看看就知道了。。
共2条
1/1 1 跳转至页
回复
有奖活动 | |
---|---|
【有奖活动】分享技术经验,兑换京东卡 | |
话不多说,快进群! | |
请大声喊出:我要开发板! | |
【有奖活动】EEPW网站征稿正在进行时,欢迎踊跃投稿啦 | |
奖!发布技术笔记,技术评测贴换取您心仪的礼品 | |
打赏了!打赏了!打赏了! |
打赏帖 | |
---|---|
vscode+cmake搭建雅特力AT32L021开发环境被打赏30分 | |
【换取逻辑分析仪】自制底板并驱动ArduinoNanoRP2040ConnectLCD扩展板被打赏47分 | |
【分享评测,赢取加热台】RISC-V GCC 内嵌汇编使用被打赏38分 | |
【换取逻辑分析仪】-基于ADI单片机MAX78000的简易MP3音乐播放器被打赏48分 | |
我想要一部加热台+树莓派PICO驱动AHT10被打赏38分 | |
【换取逻辑分析仪】-硬件SPI驱动OLED屏幕被打赏36分 | |
换逻辑分析仪+上下拉与多路选择器被打赏29分 | |
Let'sdo第3期任务合集被打赏50分 | |
换逻辑分析仪+Verilog三态门被打赏27分 | |
换逻辑分析仪+Verilog多输出门被打赏24分 |