freeRtos源码解析(一)--RTOS概念以及任务创建

本文介绍了RTOS的基本概念,特别是FreeRTOS中的任务定义,并详细阐述了在STM32环境下如何创建任务,包括任务栈空间申请、TCB初始化、栈指针初始化和任务加入就绪列表的过程。内容参考了《FreeRTOS 内核实现与应用开发实战》和《Cortex-M3与Cortex-M4权威指南》等资料。
摘要由CSDN通过智能技术生成

freeRtos源码解析(一)–RTOS概念以及任务创建

一、简介
  1.1 代码来源及版本

  代码来源于STM32CubeIDE工具一键生成功能,对应freeRtos版本为 FreeRTOS Kernel V10.2.1。对应MCU型号为STM32MP157D cortex-M4
   生成的中间层代码以及源码目录如下:
在这里插入图片描述

  1.2 学习参考
  [野火®]《FreeRTOS 内核实现与应用开发实战—基于STM32》
《Cortex-M3权威指南(中文版)》或《Cortex-M3与Cortex-M4权威指南(中文版)》——寄存器组、MPU,中断与异常、双堆栈机制以及汇编语言基础部分。

   RTOS的设计和MCU内核的设计是紧密相关的,因此学习RTOS需要对Cortex-M3/M4内核的特性有相应的认识。在国内学习freeRtos的资料非常多,大家可以很容易找到进行学习,彼此交流。

二、相关概念
  2.1 任务的概念
   在RTOS里面,任务指一个个具有独立栈空间,无限循环且不能返回的函数(LR指针默认压0或者异常,不能返回)。一般也称为线程(与linux内核中的线程实现不完全一致)。
  freeRtos的核心,就是多任务 (包括任务创建,任务调度,任务通信)。

  2.2 freeRtos与linux操作系统的区别
  freeRtos仅涉及多任务系统以及任务通信机制,和简单的堆内存管理。如果需要TCP/IP和文件系统,还需要另外移植。
  嵌入式linux系统时,属于全特性OS。其概念包括线程进程调度,文件系统,网络,内存管理等,属于集大成者。(Cortex-M系列处理器无法运行linux或windows等全特性OS,因为M系列处理器没有MMU。只有A系列才能支持

  2.3 何时使用嵌入式RTOS
   根据《Cortex-M3与Cortex-M4权威指南(中文版)》中表述,RTOS的关键在于实时性,而linux由于MMU的管理,无法保证实时响应。
在这里插入图片描述
   当前基于Cortex-M3/M4的应用越来越复杂,RTOS可以方便多任务的处理。同时在某些必要中间件,如lwip协议栈中,就抽象出任务来管理内核,需要搭配OS使用。

三、任务创建
  下面介绍freeRtos内核是如何定义和创建任务的。 创建任务的函数定义:

#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )

	BaseType_t xTaskCreate(	TaskFunction_t pxTaskCode,
							const char * const pcName,		/*lint !e971 Unqualified char types are allowed for strings and single characters only. */
							const configSTACK_DEPTH_TYPE usStackDepth,
							void * const pvParameters,
							UBaseType_t uxPriority,
							TaskHandle_t * const pxCreatedTask )
	{
   
	TCB_t *pxNewTCB;
	BaseType_t xReturn;

		/* If the stack grows down then allocate the stack then the TCB so the stack
		does not grow into the TCB.  Likewise if the stack grows up then allocate
		the TCB then the stack. */
		#if( portSTACK_GROWTH > 0 )
		{
   
			/* Allocate space for the TCB.  Where the memory comes from depends on
			the implementation of the port malloc function and whether or not static
			allocation is being used. */
			pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );

			if( pxNewTCB != NULL )
			{
   
				/* Allocate space for the stack used by the task being created.
				The base of the stack memory stored in the TCB so the task can
				be deleted later if required. */
				pxNewTCB->pxStack = ( StackType_t * ) pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */

				if( pxNewTCB->pxStack == NULL )
				{
   
					/* Could not allocate the stack.  Delete the allocated TCB. */
					vPortFree( pxNewTCB );
					pxNewTCB = NULL;
				}
			}
		}
		#else /* portSTACK_GROWTH */
		{
   
		StackType_t *pxStack;

			/* Allocate space for the stack used by the task being created. */
			pxStack = pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack and this allocation is the stack. */

			if( pxStack != NULL )
			{
   
				/* Allocate space for the TCB. */
				pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) ); /*lint !e9087 !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack, and the first member of TCB_t is always a pointer to the task's stack. */

				if( pxNewTCB != NULL )
				{
   
					/* Store the stack location in the TCB. */
					pxNewTCB->pxStack = pxStack;
				}
				else
				{
   
					/* The stack cannot be used as the TCB was not created.  Free
					it again. */
					vPortFree( pxStack );
				}
			}
			else
			{
   
				pxNewTCB = NULL;
			}
		}
		#endif /* portSTACK_GROWTH */

		if( pxNewTCB != NULL )
		{
   
			#if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e9029 !e731 Macro has been consolidated for readability reasons. */
			{
   
				/* Tasks can be created statically or dynamically, so note this
				task was created dynamically in case it is later deleted. */
				pxNewTCB->ucStaticallyAllocated = tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB;
			}
			#endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */

			prvInitialiseNewTask( pxTaskCode, pcName, ( uint32_t ) usStackDepth, pvParameters, uxPriority, pxCreatedTask, pxNewTCB, NULL );
			prvAddNewTaskToReadyList( pxNewTCB );
			xReturn = pdPASS;
		}
		else
		{
   
			xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
		}

		return xReturn;
	}

#endif /* configSUPPORT_DYNAMIC_ALLOCATION */

  创建任务的流程依次做了如下步骤:
  1)申请堆空间。
  当portSTACK_GROWTH大于0时,先申请TCB控制块再申请栈空间ÿ

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

同人与野

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值