1
完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
1.在学习ucos-iii时,看到资料的工程---SYSTEM文件夹---usatr.c中的串口中断中断服务程序void USART1_IRQHandler(void) 如下:
void USART1_IRQHandler(void) //串口1中断服务程序 { …… OSIntEnter(); ………………//省略了串口的代码。 OSIntExit(); …… } 在这个程序中,体现了ucos-iii中断的编写模板。 对于Cortex-M3内核的异常来说,进入异常自动保存SRPCR12R0~R3,那剩下的R4~R11寄存器的保存怎么在如上的“串口1中断服务程序”找不到相关代码呢?查看了一下OSIntEnter()中确实没有啊。源代码如下: void OSIntEnter (void) { if (OSRunning != OS_STATE_OS_RUNNING) { /* Is OS running? */ return; /* No */ } if (OSIntNestingCtr >= (OS_NESTING_CTR)250u) { /* Have we nested past 250 levels? */ return; /* Yes */ } OSIntNestingCtr++; /* Increment ISR nesting level */ } 为什么? |
|
相关推荐
4个回答
|
|
问题已经解决。详见cortex-M3权威指南的136页
|
|
|
|
剩下的R4~R11是手动不保存的,典型的看资料不认真!我们的UCOS教程对这个有非常详细的讲解!
|
|
|
|
对于初始化阶段OSStartHighRdy和任务级调度器OSCtxSw、中断级调度器OSIntCtxSw来说都是通过挂起PendSV异常实现的任务切换。因此重点在PendSV异常的编写。
由于OSStartHighRdy之前已经使用C语言编写的OSTaskStkInit()函数(位于cpu_core.c)将现场初始化完毕,因此进入PendSV后执行执行PendSVHandler_nosave 之后的代码。而任务级调度器OSCtxSw、中断级调度器OSIntCtxSw将会执行PendSV异常所有的代码。 我的疑问如下: 除PendSV异常之外的其他异常的模型和初始化阶段OSStartHighRdy和任务级调度器OSCtxSw、中断级调度器OSIntCtxSw稍稍有些不同,不难发现PendSV一开始就赶紧保存R4~R11,但为什么其他异常刚进入后却不需要先保存R4~R11,而仅在最后才使用OSIntExit()在确定会发生调度时才保存R4~R11。 Void xxxxx_xxxHandler(void) //除endSV异常之外的其他异常的“C代码”模型 {OSIntEnter(); 中断服务代码; OSIntExit(); } 在进入异常时切换为handler mode,这种模式下是“privileged LEVEL特权模式”,所有的通用寄存器R0~R7(Low registers)+R8~R12(high registers)都可以使用。对于使用C编写的中断服务函数(如上模型),编译为机器码后难道只使用R0~R3、R12而不会对R4~R11造成破坏? 版主大人,怎么看? ;//////////////////////////////////os_cpu_a.s/////////////////////////////////////////// OSStartHighRdy LDR R0, =NVIC_SYSPRI4 ; Set the endSV exception priority LDR R1, =NVIC_PENDSV_PRI STRB R1, [R0] ;NVIC_SYSPRI4是配置PendSV优先级的寄存器的物理地址。NVIC_PENDSV_PRI是将要配置的PendSV的优先级别,通过宏定义可知, ;要将PendSV的优先级设置为255.注:这是cortex-M3的最低优先级。 ;Cortex-M3内核提供了两个堆栈指针MSP和PSP。在《Cortex-M3 Devices Generic User Guide.pdf》的2.13节的介绍如下 ;//////////////////////////// ;Stack ointer ;The Stack ointer (SP) is register R13. In Thread mode, bit[1] of the CONTROL register ;indicates the stack pointer to use: ; 0 = Main Stack ointer (MSP). This is the reset value. ; 1 = rocess Stack ointer (PSP). ;On reset, the processor loads the MSP with the value from address 0x00000000. ;/////////////////////////////////// ;下面5句话的作用:将PSR清零+将“异常的堆栈基地址赋”给MSP。 MOVS R0, #0 ; Set the SP to 0 for initial context switch call MSR  SP, R0 LDR R0, =OS_CPU_ExceptStkBase ; Initialize the MSP to the OS_CPU_ExceptStkBase LDR R1, [R0] MSR MSP, R1 ;uC/OS-III专门为异常提供了一个堆栈空间,其基地址为OS_CPU_ExceptStkBase ;如上3句话的作用:将异常的堆栈的基地址给堆栈指针MSP. LDR R0, =NVIC_INT_CTRL ; Trigger the endSV exception (causes context switch) LDR R1, =NVIC_PENDSVSET STR R1, [R0] ;上边的三句汇编完成了对PendSV的挂起(触发)。挂起PendSV的唯一方法就是置位ICSR的bit[28]位。 ;NVIC_INT_CTRL就是ICSR寄存器的地址。NVIC_PENDSVSET=0x10000000。都是宏定义。 ;第1句: 将ICSR寄存器的地址NVIC_INT_CTRL放在R0中。 ;第2句: 将NVIC_PENDSVSET放在R1中。 ;第3句: 将R1放进R0所指向的存储器地址。也就是说向存储器的NVIC_INT_CTRL处(即ICSR寄存器)写入NVIC_PENDSVSET。 ;说白了,这3句的作用就是将0x10000000写入到ICSR寄存器。这样一来,ICSR的bit[28]位被置位,即将PendSV挂起了。 CPSIE I ; Enable interrupts at processor level ;/////////// OSStartHang B OSStartHang ; Should never get here ;///////// OSCtxSw LDR R0, =NVIC_INT_CTRL ; Trigger the endSV exception (causes context switch) LDR R1, =NVIC_PENDSVSET STR R1, [R0] BX LR ;////////////// OSIntCtxSw LDR R0, =NVIC_INT_CTRL ; Trigger the PendSV exception (causes context switch) LDR R1, =NVIC_PENDSVSET STR R1, [R0] BX LR ;///////////////////// PendSV_Handler CPSID I ; Prevent interruption during context switch;关中断 MRS R0, PSP ; PSP is process stack pointer;将PSP的值写入到R0中。 CBZ R0, PendSVHandler_nosave ; Skip register save the first time ;如果R0=0则跳转到PendSVHandler_nosave处执行。PendSVHandler_nosave是个汇编编写的子函数。 ;c代码的等价转化: if(R0==0)PendSVHandler_nosave(); SUBS R0, R0, #0x20 ; Save remaining regs r4-11 on process stack STM R0, {R4-R11} LDR R1, =OSTCBCurPtr ; OSTCBCurPtr->OSTCBStkPtr = SP; LDR R1, [R1] STR R0, [R1] ; R0 is SP of process being switched out ; At this point, entire context of process has been saved PendSVHandler_nosave PUSH {R14} ; Save LR exc_return value LDR R0, =OSTaskSwHook ; OSTaskSwHook(); BLX R0 POP {R14} LDR R0, =OSPrioCur ; OSPrioCur = OSPrioHighRdy; LDR R1, =OSPrioHighRdy LDRB R2, [R1] STRB R2, [R0] LDR R0, =OSTCBCurPtr ; OSTCBCurPtr = OSTCBHighRdyPtr; LDR R1, =OSTCBHighRdyPtr LDR R2, [R1] STR R2, [R0] LDR R0, [R2] ; R0 is new process SP; SP = OSTCBHighRdyPtr->StkPtr; LDM R0, {R4-R11} ; Restore r4-11 from new process stack ADDS R0, R0, #0x20 MSR PSP, R0 ; Load PSP with new process SP ORR LR, LR, #0x04 ; Ensure exception return uses process stack CPSIE I BX LR ; Exception return will restore remaining context END |
|
|
|
以本为本还是有道理的,学习了
|
|
|
|
只有小组成员才能发言,加入小组>>
795 浏览 0 评论
1154 浏览 1 评论
2530 浏览 5 评论
2863 浏览 9 评论
移植了freeRTOS到STMf103之后显示没有定义的原因?
2713 浏览 6 评论
keil5中manage run-time environment怎么是灰色,不可以操作吗?
1075浏览 3评论
195浏览 2评论
461浏览 2评论
374浏览 2评论
M0518 PWM的电压输出只有2V左右,没有3.3V是怎么回事?
455浏览 1评论
小黑屋| 手机版| Archiver| 德赢Vwin官网 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-23 13:21 , Processed in 1.143807 second(s), Total 54, Slave 45 queries .
Powered by 德赢Vwin官网 网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
德赢Vwin官网 观察
版权所有 © 湖南华秋数字科技有限公司
德赢Vwin官网 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号