• 【FreeRTOS】【STM32】06.1 FreeRTOS的使用1(对06的补充)


    前后台系统(裸机)

    裸机又称前后台系统,在一个while中不停循环处理各个task。
    中断服务函数作为前台程序
    大循环while(1)作为后台程序
    裸机

    多任务系统

    通过任务调度的方式,执行各个任务,优先级高的先执行,执行完了释放CPU使用权,交予优先级低的。优先级低的执行完了之后,释放使用权到优先级更低的。
    在这里插入图片描述

    任务调度器职责

    1.RTOS任务 调度器来决定具体运行哪个任务RTOS 调度器会重复的开启、关闭每个任务。
    2.RTOS 调度器需要确保当一个任务开始执行的时候其上下文环境(寄存器值,堆栈内容等)和任务上一次退出的时候相同。(每个任务都必须有个堆栈,当任务切换的时候将上下文环境保存在堆栈中,这样当任务再次执行的时候就可以从堆栈中取出上下文环境,任务恢复运行

    任务控制块

    FreeRTOS 的每个任务都有一些属性需要存储,FreeRTOS 把这些属性集合到一起用一个结构体来表示,这个结构体叫做任务控制块.此结构体在文件 tasks.c 中有定义。

    typedef struct tskTaskControlBlock
    {
    	volatile StackType_t *pxTopOfStack; //任务堆栈栈顶
    #if ( portUSING_MPU_WRAPPERS == 1 )
    		xMPU_SETTINGSxMPUSettings; //MPU 相关设置
    #endif
    	ListItem_t xStateListItem; //状态列表项
    	ListItem_t xEventListItem; //事件列表项
    	UBaseType_t uxPriority; //任务优先级
    	StackType_t *pxStack; //任务堆栈起始地址
    	
    	char pcTaskName[ configMAX_TASK_NAME_LEN ];//任务名字
    #if ( portSTACK_GROWTH > 0 )
    	StackType_t *pxEndOfStack; //任务堆栈栈底
    #endif
    #if ( portCRITICAL_NESTING_IN_TCB == 1 )
    	UBaseType_t uxCriticalNesting; //临界区嵌套深度
    #endif
    #if ( configUSE_TRACE_FACILITY == 1 ) //trace 或到 debug 的时候用到
    	UBaseType_t uxTCBNumber;
    	UBaseType_t uxTaskNumber;
    #endif
    #if ( configUSE_MUTEXES == 1 )
    	UBaseType_t uxBasePriority; //任务基础优先级,优先级反转的时候用到
    	UBaseType_t uxMutexesHeld; //任务获取到的互斥信号量个数
    #endif
    #if ( configUSE_APPLICATION_TASK_TAG == 1 )
    	TaskHookFunction_t pxTaskTag;
    #endif
    #if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 ) //与本地存储有关
    	void 
    	*pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];
    #endif
    #if( configGENERATE_RUN_TIME_STATS == 1 )
    	uint32_t ulRunTimeCounter; //用来记录任务运行总时间
    #endif
    #if ( configUSE_NEWLIB_REENTRANT == 1 )
    	struct _reent xNewLib_reent; //定义一个 newlib 结构体变量
    #endif
    #if( configUSE_TASK_NOTIFICATIONS == 1 )//任务通知相关变量
    	volatile uint32_t ulNotifiedValue; //任务通知值
    	volatile uint8_t ucNotifyState; //任务通知状态
    #endif
    #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
    	//用来标记任务是动态创建的还是静态创建的,如果是静态创建的此变量就为 pdTURE,
    	//如果是动态创建的就为 pdFALSE
    	uint8_t ucStaticallyAllocated; 
    #endif
    #if( INCLUDE_xTaskAbortDelay == 1 )
    	uint8_t ucDelayAborted;
    #endif
    } tskTCB;
    	//新版本的 FreeRTOS 任务控制块重命名为 TCB_t,但是本质上还是 tskTCB,主要是为了兼容
    	//旧版本的应用。
    typedef tskTCB TCB_t;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55

    任务堆栈

    FreeRTOS 之所以能正确的恢复一个任务的运行就是因为有任务堆栈.,每一个任务都有自己的堆栈。

    任务调度器在进行任务切换的时候会将当前任务的现场(CPU 寄存器值等)保存在此任务的任务堆栈中,等到此任务下次运行的时候就会先用堆栈中保存的值来恢复现场,恢复现场以后任务就会接着从上次中断的地方开始运行。

    创建任务的时候需要给任务指定堆栈:
    使用的函数 xTaskCreate()创建任务(动态方法)的话那么任务堆栈就会由函数 xTaskCreate()自动创建.

    使用函数 xTaskCreateStatic()创建任务(静态方法)的话就需要程序员自行定义任务堆栈,然后堆栈首地址作为函数的参数 puxStackBuffer 传递给函数。
    静态方法创建任务:

    TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode,
    	 const char * const pcName,
    	const uint32_t ulStackDepth,
    	void * const pvParameters,
    	UBaseType_t uxPriority,
    	StackType_t * const puxStackBuffer, (1)//堆栈首地址 puxStackBuffer
    	StaticTask_t * const pxTaskBuffer )
    	//(1)、任务堆栈,静态方法下需要用户定义,然后将堆栈首地址传递给这个参数
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    堆栈首地址 puxStackBuffer类型为StackType_t *

    堆栈大小

    不管是使用函数 xTaskCreate()动态还是 xTaskCreateStatic()静态建任务都需要指定任务堆栈大小。

    任务堆栈的数据类型为StackType_t,StackType_t 本质上是 uint32_t,在 portmacro.h 中有定
    义:

    #define portSTACK_TYPE uint32_t
    #define portBASE_TYPE long
    typedef portSTACK_TYPE StackType_t;
    
    typedef long BaseType_t;
    typedef unsigned long UBaseType_t;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
  • 相关阅读:
    采用 Phi-3 小型模型和 Elastic 的智能订购系统
    Dockerfile 语法教程
    uniapp报错:Cannot find module ‘@babel/parser‘
    笔试强训第十九天 (最长公共子串+汽水瓶)
    集合是否存在交集的判断方法分享
    Flutter高仿微信-第30篇-单聊-文本
    c++ day 4
    如何理解CRC循环冗余校验——图解CRC算法模型和C语言实现
    软件设计开发笔记3:基于QT的Modbus RTU主站
    Python---函数
  • 原文地址:https://blog.csdn.net/apythonlearner/article/details/133744590