当前位置: 首页 > article >正文

freertos 源码分析五 任务调度一

vTaskStartScheduler
创建空闲进程, 调用适配xPortStartScheduler();

void vTaskStartScheduler( void )
{
        xReturn = xTaskCreate( prvIdleTask,
                               configIDLE_TASK_NAME,
                               configMINIMAL_STACK_SIZE,
                               ( void * ) NULL,
                               portPRIVILEGE_BIT,
                               &xIdleTaskHandle );

   if( xReturn == pdPASS )
    {
        portDISABLE_INTERRUPTS();
        xNextTaskUnblockTime = portMAX_DELAY;
        xSchedulerRunning = pdTRUE;
        xTickCount = ( TickType_t ) configINITIAL_TICK_COUNT;

        xPortStartScheduler();
    }
    else
    {
        configASSERT( xReturn != errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY );
    }
}

stm32,适配不同有差异

设置挂起中断和系统定时中断优先级,设置定时中断

BaseType_t xPortStartScheduler( void )                                                                                                             
{

    portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;   //pendsv 优先级
    portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;  // systick 优先级

    vPortSetupTimerInterrupt();

    uxCriticalNesting = 0;

    prvPortStartFirstTask();

    vTaskSwitchContext();
    prvTaskExitError();

    return 0;
}

设置系统定时中断

__attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void )                                                                                    
{

    portNVIC_SYSTICK_CTRL_REG = 0UL;
    portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;

    portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
    portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT );
}

portNVIC_SYSTICK_LOAD_REG 系统定时计数器重载时间
portNVIC_SYSTICK_CTRL_REG

[2]CLKSOURCE 1 = core clock.
[1]TICKINT 1 = counting down to 0 pends the SysTick handler.
[0]ENABLE 1

prvPortStartFirstTask,调用svc中断

static void prvPortStartFirstTask( void )                                                                                                          
{
    __asm volatile (
        " ldr r0, =0xE000ED08   \n"  
        " ldr r0, [r0]          \n"                //中断向量表偏移
        " ldr r0, [r0]          \n"				// 取出中断向量表第一个数据 即栈顶指针
        " msr msp, r0           \n"			//设置msp指向栈顶
        " cpsie i               \n"					// 开中断
        " cpsie f               \n"					//开异常
        " dsb                   \n"					//数据同步屏障
        " isb                   \n"						//清空流水线
        " svc 0                 \n"					//svc中断
        " nop                   \n"
        " .ltorg                \n"   			// 数据缓冲池
        );
}

恢复任务context

void vPortSVCHandler( void )
{
    __asm volatile (
        "   ldr r3, pxCurrentTCBConst2      \n"     //当前任务块
        "   ldr r1, [r3]                    \n"							
        "   ldr r0, [r1]                    \n"						 //第一个数据为任务块栈顶指针
        "   ldmia r0!, {r4-r11}             \n" 			 	// 恢复r4-r11
        "   msr psp, r0                     \n"					//恢复栈
        "   isb                             \n"                              //清空流水线                                                                      
        "   mov r0, #0                      \n"					
        "   msr basepri, r0                 \n"
        "   orr r14, #0xd                   \n"
        "   bx r14                          \n"					//从中断返回
        "                                   \n"
        "   .align 4                        \n"
        "pxCurrentTCBConst2: .word pxCurrentTCB             \n"
        );
}

就绪链表查找最高优先级,赋值给当前任务

void vTaskSwitchContext( void )
{
    if( uxSchedulerSuspended != ( UBaseType_t ) pdFALSE )
    {
        xYieldPending = pdTRUE;
    }
    else
    {
        xYieldPending = pdFALSE;

        taskSELECT_HIGHEST_PRIORITY_TASK();
    }
}
#define taskSELECT_HIGHEST_PRIORITY_TASK()                                \
{                                                                         \
    UBaseType_t uxTopPriority = uxTopReadyPriority;                       \
                                                                          \
          \
    while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopPriority ] ) ) ) \
    {                                                                     \
        configASSERT( uxTopPriority );                                    \
        --uxTopPriority;                                                  \
    }                                                                     \
                                                                          \
                        \
    listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) ); \
    uxTopReadyPriority = uxTopPriority;                                                   \
}

http://www.kler.cn/a/231895.html

相关文章:

  • 1 设计模式原则之开闭原则
  • vuex和pinia的区别
  • 针对股票评论的情感分类器
  • 7.高可用集群架构Keepalived双主热备原理
  • Cuda和Pytorch的兼容性
  • jenkins用户在执行scp的时候如何做免密登录
  • Linux大集合
  • 使用python实现:判断任意坐标点在STL几何模型的内部或外部
  • go 内存二进制数据操作
  • Redis——缓存设计与优化
  • Python面试题13-18
  • vue3 mathjax2.7.7 数学公式
  • Chrome 沙箱逃逸 -- Plaid CTF 2020 mojo
  • 服务器运存使用率多少正常?
  • Spring Cloud Netflix Eureka的参数调优
  • 在windows的控制台实现贪吃蛇小游戏
  • 预测模型:MATLAB线性回归
  • 【芯片设计- RTL 数字逻辑设计入门 11.1 -- 状态机实现 移位运算与乘法 1】
  • 8.0 Zookeeper 四字命令教程详解
  • ruoyi-nbcio中xxl-job的安装与使用
  • C# async/await的使用
  • Java微服务学习Day1
  • facebook广告投流有几种方式
  • XSS攻击 - 不要再硬背了
  • svg基础(五)滤镜-高斯模糊,混合模式,偏移,颜色变换
  • [C/C++] -- JSON for Modern C++