嘉定企业网站制作,河南省住房建设厅网站首页,网站推广的技术有哪些,绵阳集团网站建设FreeRTOS学习——接口宏portmacro.h#xff0c;仅用于记录自己阅读与学习源码 FreeRTOS Kernel V10.5.1 port #xff1a;GCC/ARM_CM7 文章目录 Systick源码触发方式 SVC源码触发方式 PendSV源码触发方式 相关汇编指令 Systick
源码
在Systick中断xPortSysTickHandler中仅用于记录自己阅读与学习源码 FreeRTOS Kernel V10.5.1 port GCC/ARM_CM7 文章目录 Systick源码触发方式 SVC源码触发方式 PendSV源码触发方式 相关汇编指令 Systick
源码
在Systick中断xPortSysTickHandler中只做了一件事那就是挂起PendSV中断。 所以其实切换任务是在PendSV中断执行的。
void xPortSysTickHandler( void )
{/* SysTick以最低的中断优先级运行 */portDISABLE_INTERRUPTS();{/* Increment the RTOS tick. */if( xTaskIncrementTick() ! pdFALSE ){/* 上下文切换在 PendSV 中断 中执行* 挂起 PendSV 中断. */portNVIC_INT_CTRL_REG portNVIC_PENDSVSET_BIT;}}portENABLE_INTERRUPTS();
}触发方式
在开启调度器时会调用定时器中断设置函数vPortSetupTimerInterrupt以生成 tick 中断如下 vTaskStartScheduler → xPortStartScheduler → vPortSetupTimerInterrupt 配置系统的滴答定时器以允许操作系统根据配置的频率生成定时中断从而支持任务的调度和管理
__attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void )
{/* 低功耗模式这里先不做分析. */#if ( configUSE_TICKLESS_IDLE 1 ){ulTimerCountsForOneTick ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );xMaximumPossibleSuppressedTicks portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;ulStoppedTimerCompensation portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );}#endif /* configUSE_TICKLESS_IDLE *//* 停止和清除SysTick. */portNVIC_SYSTICK_CTRL_REG 0UL;/*将控制寄存器设置为0停止SysTick*/portNVIC_SYSTICK_CURRENT_VALUE_REG 0UL;/*将当前值寄存器清零。*//* 配置SysTick. *//* 设置加载寄存器将SysTick的计数重加载为目标计数值*/portNVIC_SYSTICK_LOAD_REG ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;/* 设置SysTick的控制寄存器以启用时钟、启用中断和使能SysTick*/portNVIC_SYSTICK_CTRL_REG ( portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT );
}这几个值分别是
#define configSYSTICK_CLOCK_HZ ( configCPU_CLOCK_HZ )
/* Ensure the SysTick is clocked at the same frequency as the core. */
#define portNVIC_SYSTICK_CLK_BIT_CONFIG ( portNVIC_SYSTICK_CLK_BIT )#define configCPU_CLOCK_HZ ( SystemCoreClock )
#define configTICK_RATE_HZ ( 1000 )#define portNVIC_SYSTICK_CLK_BIT ( 1UL 2UL )
#define portNVIC_SYSTICK_INT_BIT ( 1UL 1UL )
#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL 0UL )然后就会按照设定的时间默认1ms周期性的触发Systick中断 SVC
源码
void vPortSVCHandler( void )
{__asm volatile ( /* volatile表示不能移除或重排序这段代码. */ ldr r3, pxCurrentTCBConst2 \n/* 将pxCurrentTCB的地址加载到r3中. */ ldr r1, [r3] \n/* 从r3指向的位置读取当前任务控制块TCB的地址并将其存储在r1中. */ ldr r0, [r1] \n/* 从r1指向的位置读取数据即当前任务控制块中的第一个元素所以r0中保存的就是当前任务栈的栈顶地址. */ ldmia r0!, {r4-r11, r14} \n/* 栈中弹出寄存器r4到r11和r14链接寄存器这里使用ldmia指令加载多寄存器!表示更新指针r0指向下一个数据. */ msr psp, r0 \n/* 将恢复后的任务栈指针r0存入psp这样就恢复了当前任务的执行上下文. */ isb \n/* 指令同步屏障确保之前的指令在接下来的指令执行之前完成*/ mov r0, #0 \n/* 将寄存器r0清零准备设置中断优先级屏蔽*/ msr basepri, r0 \n/* 将basepri设置为0意味着没有设置优先级屏蔽允许所有中断*/ bx r14 \n/* 通过bx指令跳转到r14寄存器中保存的地址通常是返回到被中断的任务执行*/ \n .align 4 \n/* 确保下一条指令或数据在4字节边界对齐*/pxCurrentTCBConst2: .word pxCurrentTCB \n/* 定义一个标签pxCurrentTCBConst2并将pxCurrentTCB的地址存储到这个标签中以便在前面的ldr指令中使用*/);
}获取当前任务控制块pxCurrentTCB的栈顶地址将r4-r11, r14手动出栈将当前栈顶指针存入psp开中断
ldr r3, pxCurrentTCBConst2将pxCurrentTCBConst2的值即pxCurrentTCB的地址加载到寄存器r3中。 ldr r1, [r3]从r3指向的内存地址加载当前任务控制块TCB的地址到r1中。 ldr r0, [r1]从r1指向的TCB地址加载当前任务栈的栈顶地址到r0中。 ldmia r0!, {r4-r11, r14}从r0指向的栈中弹出寄存器r4到r11和r14!表示更新r0的值指向下一个数据。 msr psp, r0将恢复后的任务栈指针r0存入PSP进程栈指针。 mov r0, #0将寄存器r0清零。 msr basepri, r0将basepri寄存器设置为0允许所有中断。 bx r14跳转到返回地址。 pxCurrentTCBConst2: .word pxCurrentTCB定义标签pxCurrentTCBConst2并将pxCurrentTCB的地址存储在该位置
触发方式
SVCSupervisor Call中断是通过软件触发的中断
SVC指令软件通过执行 SVC 指令显式地请求中断svc 0 当SVC指令被执行后处理器会根据中断向量表中的信息跳转到相应的SVC中断处理函数执行SVC指令时处理器会自动保存当前的上下文并将处理器的模式切换为特权模式从而允许执行受限的操作
在开启调度器时会调用开始第一个任务函数如下 vTaskStartScheduler → xPortStartScheduler → prvPortStartFirstTask
static void prvPortStartFirstTask( void )
{/* 开始第一个任务。这也清除了指示FPU正在使用的位以防FPU在调度器启动之前被使用* 否则会导致SVC堆栈中不必要的空间留下以延迟保存FPU寄存器。 */__asm volatile ( ldr r0, 0xE000ED08 \n/* 加载NVIC偏移寄存器的地址到r0寄存器这个寄存器用于访问系统控制块SCB的基地址. */ ldr r0, [r0] \n ldr r0, [r0] \n/* 读取两次从SCB中加载系统栈指针MSP的值到r0寄存器*/ msr msp, r0 \n/* 将r0中的值设置为主栈指针(MSP)这标志着栈的开始. */ mov r0, #0 \n/* 清除控制寄存器中指示FPU正在使用的位以确保不保留之前的状态. */ msr control, r0 \n cpsie i \n/* 开中断. */ cpsie f \n dsb \n isb \n svc 0 \n/* 触发SVC异常. */ nop \n .ltorg \n);
}获取系统堆栈指针MSP清除FPU正在使用的位开中断触发SVC异常 PendSV
源码
void xPortPendSVHandler( void )
{/* This is a naked function. */__asm volatile( mrs r0, psp \n/* 读取当前进程的栈指针Process Stack Pointer将其值存入寄存器 r0*/ isb \n/* 指令同步屏障*/ \n ldr r3, pxCurrentTCBConst \n/* 将pxCurrentTCB的地址加载到寄存器 r3. */ ldr r2, [r3] \n/* 从r3指向的位置读取当前任务控制块TCB的地址并将其存储在r2中. */ \n tst r14, #0x10 \n/* 测试链接寄存器 r14 的第 4 位判断当前任务是否使用浮点单元FPU. */ it eq \n/* 如果第 4 位为 1即使用 FPU 上下文则执行接下来的语句*/ vstmdbeq r0!, {s16-s31} \n/* 如果使用 FPU 上下文则将 FPU 的高寄存器s16 到 s31压入栈中*/ \n stmdb r0!, {r4-r11, r14} \n/* 将寄存器 r4 到 r11 及 r14 压入栈中. */ str r0, [r2] \n/* 将新的栈顶指针值保存到 TCB 中. */ \n stmdb sp!, {r0, r3} \n/* 将目前的栈指针和 TCB 地址压入主栈以便恢复这里入栈是 MSP*/ mov r0, %0 \n/* 将最大可用优先级configMAX_SYSCALL_INTERRUPT_PRIORITY加载到 r0 中*/ cpsid i \n/* 禁止中断. */ msr basepri, r0 \n/* 设置优先级屏蔽寄存器Base Priority关中断*/ dsb \n/* 数据同步屏障*/ isb \n/* 指令同步屏障*/ cpsie i \n/* 启用中断 */ bl vTaskSwitchContext \n/* 调用任务切换的上下文切换函数*/ mov r0, #0 \n msr basepri, r0 \n/* 恢复 Base Priority 为 0开中断*/ ldmia sp!, {r0, r3} \n/* 从主栈中恢复之前保存的 r0 和 r3*/ \n ldr r1, [r3] \n/* 从r3指向的位置读取当前任务控制块已经更新过了的地址并将其存储在r1中. */ ldr r0, [r1] \n/* 从r1指向的位置读取数据即当前任务控制块中的第一个元素所以r0中保存的就是当前任务栈的栈顶地址*/ \n ldmia r0!, {r4-r11, r14} \n/* 从栈中弹出保存的核心寄存器r4-r11 和 r14. */ \n tst r14, #0x10 \n/* 再次判断是否使用 FPU 上下文. */ it eq \n/* 如果使用 FPU上下文则执行下一条指令*/ vldmiaeq r0!, {s16-s31} \n/* 如果使用 FPU则从栈中弹出高寄存器s16 到 s31*/ \n msr psp, r0 \n/* 将恢复后的栈指针值写入PSP以便切换到新的任务的栈中. */ isb \n/* 指令同步屏障*/ \n#ifdef WORKAROUND_PMU_CM001 /* XMC4000特定勘误表解决方法. 这里不用管*/#if WORKAROUND_PMU_CM001 1 push { r14 } \n pop { pc } \n#endif#endif \n bx r14 \n/* 返回到调用该处理程序的位置*/ \n/* 将后面的数据对齐到 4 字节*/ .align 4 \npxCurrentTCBConst: .word pxCurrentTCB \n::i ( configMAX_SYSCALL_INTERRUPT_PRIORITY ));
}在PendSV中干了两件事 一是保存当前任务的现场
获取当前任务控制块pxCurrentTCB的栈顶地址将核心寄存器入栈其他寄存器在进入中断之前已经自动入栈保存栈顶指针
二是恢复最新任务的现场
调用任务切换的上下文切换函数然后pxCurrentTCBConst中指向的值就已经变成了新的TCB的地址但是pxCurrentTCBConst本身的内存地址是不变得获取最新任务控制块pxCurrentTCB的栈顶地址将核心寄存器出栈其他寄存器在退出中断之后会自动出栈将栈顶指针值写入PSP
这样就完成了上下文的切换 在进入中断前后堆栈指针的变化是
进入中断前使用PSPPSP指向旧任务的栈顶在中断中使用MSP退出中断后使用PSPPSP指向新任务的栈顶
任务切换函数vTaskSwitchContext → taskSELECT_HIGHEST_PRIORITY_TASK → listGET_OWNER_OF_NEXT_ENTRY 经过此函数后pxCurrentTCBConst已经指向了新的TCB
触发方式
1 在Systick handle中触发
/* 上下文切换在 PendSV 中断 中执行* 挂起 PendSV 中断. */portNVIC_INT_CTRL_REG portNVIC_PENDSVSET_BIT;2 taskYIELD(); 通过调用taskYIELD来触发
#define portYIELD() \{ \/* Set a PendSV to request a context switch. */ \portNVIC_INT_CTRL_REG portNVIC_PENDSVSET_BIT; \\/* Barriers are normally not required but do ensure the code is completely \* within the specified behaviour for the architecture. */ \__asm volatile ( dsb ::: memory ); \__asm volatile ( isb ); \}相关汇编指令
ldr加载寄存器指令用于从内存中加载数据到寄存器中。ldmia加载多寄存器指令可以一次性将多个内存单元的数据加载到多个寄存器中。msr移动至特权寄存器的指令用于设置某些特定的寄存器。isb指令同步屏障用于确保指令执行的顺序确保之前的指令在接下来的指令执行之前完成dsb数据同步屏障该指令确保所有之前的读写操作在继续执行后续指令之前完成mov数据传送指令用于将一个常数值或寄存器的值移动到另一个寄存器。bx分支和交换指令用于跳转到r14寄存器中保存的地址。.align伪指令用于确保下一条指令或数据在指定的字节边界对齐。.word伪指令定义一个字4字节并将值存储到该位置。nop用于在代码中占用一个执行周期但不进行任何操作常常针对时序和代码结构进行调整.ltorg用于生成字面量池为代码中使用的常量提供存储空间。通过将常量放置在易于访问的位置它提高了程序的整体性能。开关中断指令 CPSID I ;PRIMASK1 ;关中断 硬件错误异常 不关 CPSIE I ;PRIMASK0 ;开中断 CPSID F ;FAULTMASK1 ;关异常硬件错误异常 也关 CPSIE F ;FAULTMASK0 ;开异常 本人菜鸟欢迎大佬们甄误
文章转载自: http://www.morning.rsdm.cn.gov.cn.rsdm.cn http://www.morning.cmzcp.cn.gov.cn.cmzcp.cn http://www.morning.nqmkr.cn.gov.cn.nqmkr.cn http://www.morning.trfrl.cn.gov.cn.trfrl.cn http://www.morning.skbkq.cn.gov.cn.skbkq.cn http://www.morning.zthln.cn.gov.cn.zthln.cn http://www.morning.qmwzr.cn.gov.cn.qmwzr.cn http://www.morning.drwpn.cn.gov.cn.drwpn.cn http://www.morning.sgbk.cn.gov.cn.sgbk.cn http://www.morning.nmhpq.cn.gov.cn.nmhpq.cn http://www.morning.csnch.cn.gov.cn.csnch.cn http://www.morning.gmnmh.cn.gov.cn.gmnmh.cn http://www.morning.sjpbh.cn.gov.cn.sjpbh.cn http://www.morning.lekbiao.com.gov.cn.lekbiao.com http://www.morning.trkhx.cn.gov.cn.trkhx.cn http://www.morning.mqwnp.cn.gov.cn.mqwnp.cn http://www.morning.tdcql.cn.gov.cn.tdcql.cn http://www.morning.ntqgz.cn.gov.cn.ntqgz.cn http://www.morning.ycpnm.cn.gov.cn.ycpnm.cn http://www.morning.llqch.cn.gov.cn.llqch.cn http://www.morning.fllfz.cn.gov.cn.fllfz.cn http://www.morning.xjqrn.cn.gov.cn.xjqrn.cn http://www.morning.mqfhy.cn.gov.cn.mqfhy.cn http://www.morning.mjjty.cn.gov.cn.mjjty.cn http://www.morning.jpmcb.cn.gov.cn.jpmcb.cn http://www.morning.rgxn.cn.gov.cn.rgxn.cn http://www.morning.kpbq.cn.gov.cn.kpbq.cn http://www.morning.mqghs.cn.gov.cn.mqghs.cn http://www.morning.krnzm.cn.gov.cn.krnzm.cn http://www.morning.dkgtr.cn.gov.cn.dkgtr.cn http://www.morning.mgtmm.cn.gov.cn.mgtmm.cn http://www.morning.bojkosvit.com.gov.cn.bojkosvit.com http://www.morning.zpqk.cn.gov.cn.zpqk.cn http://www.morning.nrwr.cn.gov.cn.nrwr.cn http://www.morning.rwmq.cn.gov.cn.rwmq.cn http://www.morning.bpmdz.cn.gov.cn.bpmdz.cn http://www.morning.yswxq.cn.gov.cn.yswxq.cn http://www.morning.tnzwm.cn.gov.cn.tnzwm.cn http://www.morning.qsmdd.cn.gov.cn.qsmdd.cn http://www.morning.zxrtt.cn.gov.cn.zxrtt.cn http://www.morning.bplqh.cn.gov.cn.bplqh.cn http://www.morning.neletea.com.gov.cn.neletea.com http://www.morning.ccffs.cn.gov.cn.ccffs.cn http://www.morning.khclr.cn.gov.cn.khclr.cn http://www.morning.ysjjr.cn.gov.cn.ysjjr.cn http://www.morning.qxdrw.cn.gov.cn.qxdrw.cn http://www.morning.shprz.cn.gov.cn.shprz.cn http://www.morning.tgfsr.cn.gov.cn.tgfsr.cn http://www.morning.qbgff.cn.gov.cn.qbgff.cn http://www.morning.pjbhk.cn.gov.cn.pjbhk.cn http://www.morning.xprzq.cn.gov.cn.xprzq.cn http://www.morning.ryyjw.cn.gov.cn.ryyjw.cn http://www.morning.rdng.cn.gov.cn.rdng.cn http://www.morning.lhygbh.com.gov.cn.lhygbh.com http://www.morning.pdmsj.cn.gov.cn.pdmsj.cn http://www.morning.xcszl.cn.gov.cn.xcszl.cn http://www.morning.kfhm.cn.gov.cn.kfhm.cn http://www.morning.ysgnb.cn.gov.cn.ysgnb.cn http://www.morning.kphyl.cn.gov.cn.kphyl.cn http://www.morning.lbcfj.cn.gov.cn.lbcfj.cn http://www.morning.shxmr.cn.gov.cn.shxmr.cn http://www.morning.mjgxl.cn.gov.cn.mjgxl.cn http://www.morning.pwxkn.cn.gov.cn.pwxkn.cn http://www.morning.wzwpz.cn.gov.cn.wzwpz.cn http://www.morning.dmtwz.cn.gov.cn.dmtwz.cn http://www.morning.rdfq.cn.gov.cn.rdfq.cn http://www.morning.qbtkg.cn.gov.cn.qbtkg.cn http://www.morning.pwgzh.cn.gov.cn.pwgzh.cn http://www.morning.nyqb.cn.gov.cn.nyqb.cn http://www.morning.qrsrs.cn.gov.cn.qrsrs.cn http://www.morning.srgsb.cn.gov.cn.srgsb.cn http://www.morning.mrkbz.cn.gov.cn.mrkbz.cn http://www.morning.nzdks.cn.gov.cn.nzdks.cn http://www.morning.frtt.cn.gov.cn.frtt.cn http://www.morning.yrddl.cn.gov.cn.yrddl.cn http://www.morning.xcdph.cn.gov.cn.xcdph.cn http://www.morning.c7507.cn.gov.cn.c7507.cn http://www.morning.tkrwm.cn.gov.cn.tkrwm.cn http://www.morning.mqxrx.cn.gov.cn.mqxrx.cn http://www.morning.rmryl.cn.gov.cn.rmryl.cn