加入收藏 在线留言 联系我们
关注微信
手机扫一扫 立刻联系商家
全国服务热线15915421161

SIEMENS山东省济南市 西门子代理商——西门子华北一级总代理

更新时间
2024-06-30 07:00:00
价格
请来电询价
西门子总代理
PLC
西门子一级代
驱动
西门子代理商
伺服电机
联系电话
15903418770
联系手机
15915421161
联系人
张经理
立即询价

详细介绍
5.2.2 任务切换

















#define portNVIC_PENDSVSET_BIT      ( 1UL << 28UL ) //PendSV的悬起位(第28位)
#ifndef portYIELD_WITHIN_API    #define portYIELD_WITHIN_API portYIELD#endif
/* Scheduler utilities. */#define portYIELD()                                                             \{                                                                               \    /* Set a PendSV to request a context switch. */                             \    portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;                             \                                                                                \    /* 触发PendSV,产生上下文切换 */                      \    __dsb( portSY_FULL_READ_WRITE );                                            \    __isb( portSY_FULL_READ_WRITE );                                            \}

portYIELD()任务切换函数,主要就是将PendSV的悬起位置1,在没有其它中断运行时执行PendSV中断服务函数,在这个中断函数中实现任务切换。

5.2.3 PendSV中断服务函数

PendSV中断服务函数是一段汇编代码,可能不太容易看懂,该函数需要先了解如下:

外部变量pxCurrentTCB是当前正在运行的任务的任务控制块

当进入PendSV中断服务函数时,上一任务的运行环境为:xPSR,PC(任务入口地址),R14,R12,R3,R2,R1,R0(任务的形参),这些CPU寄存器的值会自动保存到任务的栈中,剩下的R4~R11需要手动保存。

总的来说,该函数实现3部分功能:上文保存,下文切换,中间调用了一个C函数vTaskSwitchContext,用于寻找要运行的任务。





























































__asm void xPortPendSVHandler( void ){    extern uxCriticalNesting;    extern pxCurrentTCB;    extern vTaskSwitchContext;
   PRESERVE8
   mrs r0, psp       /* 保存当前任务PSP地址到R0中 */    isb
   ldr r3, =pxCurrentTCB  /* 获取pxCurrentTCBConst指针地址 */    ldr r2, [r3]           /* R2被赋予当前TCB地址 */
   /* Is the task using the FPU context?  If so, push high vfp registers. */    tst r14, #0x10    it eq    vstmdbeq r0!, {s16-s31}
   /* Save the core registers. */    stmdb r0!, {r4-r11, r14}
   /* Save the new top of stack into the first member of the TCB. */    str r0, [r2]
   stmdb sp!, {r3}    mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY    msr basepri, r0  /*屏蔽中断*/    dsb    isb    bl vTaskSwitchContext  /*调用vTaskSwitchContext*/    mov r0, #0    msr basepri, r0  /*打开中断*/    ldmia sp!, {r3}
   /* The first item in pxCurrentTCB is the task top of stack. */    ldr r1, [r3] /* R3依然是pxCurrentTCBConst指针地址,R1变为新TCB地址 */    ldr r0, [r1] /* R0值成为新TCB的栈地址(该TCB发生上一次调度的PSP值) */
   /* Pop the core registers. */    ldmia r0!, {r4-r11, r14}
   /* Is the task using the FPU context?  If so, pop the high vfp registers    too. */    tst r14, #0x10    it eq    vldmiaeq r0!, {s16-s31}
   msr psp, r0    isb    #ifdef WORKAROUND_PMU_CM001 /* XMC4000 specific errata */        #if WORKAROUND_PMU_CM001 == 1            push { r14 }            pop { pc }            nop        #endif    #endif
   bx r14}


相关产品

联系方式

  • 电  话:15903418770
  • 联系人:张经理
  • 手  机:15915421161
  • 微  信:15915421161