OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4045|回复: 9

uC/OS任务切换问题 STM32F4

[复制链接]

17

主题

84

帖子

0

精华

初级会员

Rank: 2

积分
108
金钱
108
注册时间
2015-11-30
在线时间
22 小时
发表于 2016-8-7 01:38:05 | 显示全部楼层 |阅读模式
30金钱
下面是任务站的初始化程序,对于该程序我有一个疑问,希望知道的同学可以帮助我(假设所有的预编条件都满足)

疑问用红的写出

OS_STK *OSTaskStkInit (void (*task)(void *p_arg), void *p_arg, OS_STK *ptos, INT16U opt)
{
    OS_STK *stk;


    (void)opt;                                   /* 'opt' is not used, prevent warning                 */
    stk       = ptos;                            /* Load stack pointer                                 */

#if (__FPU_PRESENT==1)&&(__FPU_USED==1)       
        *(--stk) = (INT32U)0x00000000L; //No Name Register   
        *(--stk) = (INT32U)0x00001000L; //FPSCR                                    
        *(--stk) = (INT32U)0x00000015L; //s15                                         
        *(--stk) = (INT32U)0x00000014L; //s14
        *(--stk) = (INT32U)0x00000013L; //s13
        *(--stk) = (INT32U)0x00000012L; //s12
        *(--stk) = (INT32U)0x00000011L; //s11
        *(--stk) = (INT32U)0x00000010L; //s10
        *(--stk) = (INT32U)0x00000009L; //s9
        *(--stk) = (INT32U)0x00000008L; //s8
        *(--stk) = (INT32U)0x00000007L; //s7
        *(--stk) = (INT32U)0x00000006L; //s6
        *(--stk) = (INT32U)0x00000005L; //s5
        *(--stk) = (INT32U)0x00000004L; //s4
        *(--stk) = (INT32U)0x00000003L; //s3
        *(--stk) = (INT32U)0x00000002L; //s2
        *(--stk) = (INT32U)0x00000001L; //s1
        *(--stk) = (INT32U)0x00000000L; //s0   
#endif
                                                 /* Registers stacked as if auto-saved on exception    */
    *(stk)    = (INT32U)0x01000000L;             /* xPSR                                               */               
请问该数据是否覆盖s0的数据,*(--stk) 应该是先减1,然后向该地址存入数据,那么相邻的这两句不就是使用同一个地址吗。
    *(--stk)  = (INT32U)task;                    /* Entry Point                                        */                     
    *(--stk)  = (INT32U)OS_TaskReturn;           /* R14 (LR) (init value will cause fault if ever used)*/
    *(--stk)  = (INT32U)0x12121212L;             /* R12                                                */
    *(--stk)  = (INT32U)0x03030303L;             /* R3                                                 */
    *(--stk)  = (INT32U)0x02020202L;             /* R2                                                 */
    *(--stk)  = (INT32U)0x01010101L;             /* R1                                                 */
    *(--stk)  = (INT32U)p_arg;                   /* R0 : argument                                      */

#if (__FPU_PRESENT==1)&&(__FPU_USED==1)       
        *(--stk) = (INT32U)0x00000031L; //s31
        *(--stk) = (INT32U)0x00000030L; //s30
        *(--stk) = (INT32U)0x00000029L; //s29
        *(--stk) = (INT32U)0x00000028L; //s28
        *(--stk) = (INT32U)0x00000027L; //s27
        *(--stk) = (INT32U)0x00000026L; //s26
        *(--stk) = (INT32U)0x00000025L; //s25
        *(--stk) = (INT32U)0x00000024L; //s24
        *(--stk) = (INT32U)0x00000023L; //s23
        *(--stk) = (INT32U)0x00000022L; //s22
        *(--stk) = (INT32U)0x00000021L; //s21
        *(--stk) = (INT32U)0x00000020L; //s20
        *(--stk) = (INT32U)0x00000019L; //s19
        *(--stk) = (INT32U)0x00000018L; //s18
        *(--stk) = (INT32U)0x00000017L; //s17
        *(--stk) = (INT32U)0x00000016L; //s16
#endif
               
                                                /* Remaining registers saved on process stack         */
    *(--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                                                 */

    return (stk);
}


下面的函数存在PenSV中断中,该函数就是任务切换的根本
PendSV_Handler
    CPSID   I                                                   ; Prevent interruption during context switch
    MRS     R0, PSP                                           ; PSP is process stack pointer
    CBZ     R0, PendSV_Handler_Nosave                    ; Skip register save the first time
       
        ;Is the task using the FPU context? If so, push high vfp registers.
        TST         R14, #0x10
        IT                 EQ
        VSTMDBEQ R0!, {S16-S31}
       
    SUBS    R0, R0, #0x20                                       ; Save remaining regs r4-11 on process stack
    STM     R0, {R4-R11}

    LDR     R1, =OSTCBCur                                       ; OSTCBCur->OSTCBStkPtr = SP;
    LDR     R1, [R1]
    STR     R0, [R1]                                            ; R0 is SP of process being switched out

在此为什么要保存上一个任务的PSP到R0中

PendSV_Handler_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, =OSTCBCur                                       ; OSTCBCur  = OSTCBHighRdy;
    LDR     R1, =OSTCBHighRdy
    LDR     R2, [R1]
    STR     R2, [R0]                                               
上面我可以看懂,是通过全局变量得到一个任务的堆栈段,然后把SP指针放在R0寄存其中,现在的R0就是上面OS_STK *OSTaskStkInit (void (*task)(void *p_arg), void *p_arg, OS_STK *ptos, INT16U opt)函数返回的stk(最后一个语句 return(stk);
    LDR     R0, [R2]                                            ; R0 is new process SP; SP = OSTCBHighRdy->OSTCBStkPtr;
    LDM     R0, {R4-R11}                                     ; Restore r4-11 from new process stack
该指令执行完成之后R0的内容应该保持不变,这样才可以保证后面FPU寄存器数据恢复正确(问 分析的是否正确)
    ADDS    R0, R0, #0x20

        ;Is the task using the FPU context? If so, push high vfp registers.
        TST         R14, #0x10
        IT                 EQ
        VLDMIAEQ R0!, {S16-S31}
该指令执行完成之后R0的内容应该变化,R0应该指向堆栈段中任务上次R0寄存器中的内容(问 分析的是否正确)
               
    MSR     PSP, R0                                             ; Load PSP with new process SP
uC/OS II在STM32F4上使不使用双堆栈?堆栈指针不是在中断返回指令下自动恢复吗?此处为什么还要手动恢复?
    ORR     LR, LR, #0x04                                       ; Ensure exception return uses process stack
    CPSIE   I
    BX      LR                                                  ; Exception return will restore remaining context

此处不是该使用中断返回指令吗,M4内核的中断返回指令和跳转指令一样吗?该指令会自动恢复R0-R4、S0-S16、PC、SP、xPSR吗?

最佳答案

查看完整内容[请看2#楼]

我只能回答这几个问题. 在此为什么要保存上一个任务的PSP到R0中: PendSV_Handler是中断服务程序,在中断时内核使用的SP是MSP不能用PSP. uC/OS II在STM32F4上使不使用双堆栈?:我也纳闷 既然出现了PSP就应该是使用双堆栈的但是我看遍整个汇编部分也没看到切换堆栈指针的语句. 堆栈指针不是在中断返回指令下自动恢复吗? 不能自动回复的. 此处不是该使用中断返回指令吗,M4内核的中断返回指令和跳转指令一样吗?该指令会自动恢复R ...
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

27

主题

58

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
484
金钱
484
注册时间
2014-12-25
在线时间
83 小时
发表于 2016-8-7 01:38:06 | 显示全部楼层
我只能回答这几个问题.
在此为什么要保存上一个任务的PSP到R0中: PendSV_Handler是中断服务程序,在中断时内核使用的SP是MSP不能用PSP.
uC/OS II在STM32F4上使不使用双堆栈?:我也纳闷 既然出现了PSP就应该是使用双堆栈的但是我看遍整个汇编部分也没看到切换堆栈指针的语句.
堆栈指针不是在中断返回指令下自动恢复吗? 不能自动回复的.
此处不是该使用中断返回指令吗,M4内核的中断返回指令和跳转指令一样吗?该指令会自动恢复R0-R4、S0-S16、PC、SP、xPSR吗?:一样的,在中断状态这几个寄存器是自动回复的.建议你去看<<ARM CortexM3和M4权威指南>>
回复

使用道具 举报

17

主题

84

帖子

0

精华

初级会员

Rank: 2

积分
108
金钱
108
注册时间
2015-11-30
在线时间
22 小时
 楼主| 发表于 2016-8-7 13:58:42 | 显示全部楼层
在线等、、、、、
回复

使用道具 举报

17

主题

84

帖子

0

精华

初级会员

Rank: 2

积分
108
金钱
108
注册时间
2015-11-30
在线时间
22 小时
 楼主| 发表于 2016-8-7 14:38:09 | 显示全部楼层
灼灼其华 发表于 2016-8-7 14:31
我只能回答这几个问题.
在此为什么要保存上一个任务的PSP到R0中: PendSV_Handler是中断服务程序,在中断时 ...

谢谢指教,其实我最不可以理解的是第一个问题,那个数据覆盖会导致FPU数据丢失导致出错、、、
回复

使用道具 举报

17

主题

84

帖子

0

精华

初级会员

Rank: 2

积分
108
金钱
108
注册时间
2015-11-30
在线时间
22 小时
 楼主| 发表于 2016-8-8 08:23:40 | 显示全部楼层
每天上来看看    、、、、、、、、自己帮自己顶帖子、、、、、、、希望知道的同学来解决!
回复

使用道具 举报

16

主题

173

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2441
金钱
2441
注册时间
2014-11-5
在线时间
348 小时
发表于 2016-8-8 09:32:00 | 显示全部楼层
初学ucos,我想问楼主一个问题,每次任务切换都是运行最高优先级的任务,那低优先级的任务怎样才能得到运行,或者是我理解错了,那到底是怎么一回事?
回复

使用道具 举报

17

主题

84

帖子

0

精华

初级会员

Rank: 2

积分
108
金钱
108
注册时间
2015-11-30
在线时间
22 小时
 楼主| 发表于 2016-8-8 11:13:33 | 显示全部楼层
hello_galaxy 发表于 2016-8-8 09:32
初学ucos,我想问楼主一个问题,每次任务切换都是运行最高优先级的任务,那低优先级的任务怎样才能得到运行 ...

uC/OS的最高任务必须有延时,这样在延时最高任务的时候回发生任务切换,切换到比较低的任务。如果最高任务没有延时,或者没有被挂起、等待信号量的的任务,那么低级任务不会得到CPU的使用权。
回复

使用道具 举报

16

主题

173

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2441
金钱
2441
注册时间
2014-11-5
在线时间
348 小时
发表于 2016-8-8 12:32:38 | 显示全部楼层
brave_dancing 发表于 2016-8-8 11:13
uC/OS的最高任务必须有延时,这样在延时最高任务的时候回发生任务切换,切换到比较低的任务。如果最高任 ...

谢谢了,豁然开朗!!
回复

使用道具 举报

17

主题

84

帖子

0

精华

初级会员

Rank: 2

积分
108
金钱
108
注册时间
2015-11-30
在线时间
22 小时
 楼主| 发表于 2016-8-20 11:21:20 | 显示全部楼层
我在这正式的回答我自己提出的问题,这是我自己经过日日夜夜努力得到的,分享给大家,希望对有同样疑问的同学以帮助。
回复

使用道具 举报

17

主题

84

帖子

0

精华

初级会员

Rank: 2

积分
108
金钱
108
注册时间
2015-11-30
在线时间
22 小时
 楼主| 发表于 2016-8-20 11:42:04 | 显示全部楼层
       在源程序里,堆栈的初始化会使得两个数据存放在相同的地址中,这一点从C和C的汇编我都确认过了。堆栈初始化是在任务建立的时候才会初始化一次,目的是仿造出一个中断过后的堆栈接口段,这样通过改变堆栈指针和中断返回,这样就可以实现中断切换。这些事基础,说完任务切换我们再来说说数据覆盖的问题,如果堆栈接口不正确的话,严重时会导致整个系统崩溃。所以我对那个数据覆盖相当不理解,最后我想想了,堆栈初始化里面的数据只有一个比较重要,那就是任务的地址,只要它被正确装入PC寄存器,那么堆栈初始化就应该完成了任务,其他的数据再怎么覆盖,也是无用的。从程序看,数据覆盖发生在任务指针入栈之前,这样会使得任务指针相对偏移4个字节,可是,在中断返回时,数据是从下向上出栈的,所以这个错误不会影响任务指针推入PC寄存器,这样任务就会正确开始,其他寄存器会放入什么值都无所谓。而任务一旦开始后的任务堆栈接口就不再是由人为的设置,是系统内核响应中断所决定的,其实还有一部分代码 在CPU的汇编文件的Pendvc中断里体现,这里不细说了、、、

        最后再说说,这些文件应该是STM32官方移植时候写的,难道他们没有察觉这个错误吗,答案肯定是肯定的,他们知道,但是他们为什么还要让这样的错误出现在程序里,我看了几遍代码后明白,这样可以在兼容M3内核和M4内核不使用FPU的同时,节省4字节的RAM空间,这样的解决使我觉得    、、、、,全世界的工程师也许都有强迫症吧、、、、
       但是我觉他们是不是该把这样的错误注明在程序里呢、、、、,也许他们觉得我们应该足够聪明,不会被这点小问题难道、、、、、
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-2-28 03:26

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表