FreeRTOS任务创建、删除、挂起、恢复源码分析

2023-05-16

目录

1.任务控制块(结构体TCB_t)

2.FreeRTOS任务创建源码分析

3.FreeRTOS任务删除源码分析

4.FreeRTOS任务挂起源码分析

5.FreeRTOS任务恢复源码分析

6.任务API总结(部分)


1.任务控制块(结构体TCB_t)

typedef struct tskTaskControlBlock 			/* The old naming convention is used to prevent breaking kernel aware debuggers. */
{
    //任务堆栈栈顶
	volatile StackType_t	*pxTopOfStack;	/*< Points to the location of the last item placed on the tasks stack.  THIS MUST BE THE FIRST MEMBER OF THE TCB STRUCT. */
    //状态列表项
	ListItem_t			xStateListItem;	/*< The list that the state list item of a task is reference from denotes the state of that task (Ready, Blocked, Suspended ). */
	//事件列表项
    ListItem_t			xEventListItem;		/*< Used to reference a task from an event list. */
	//任务优先级
    UBaseType_t			uxPriority;			/*< The priority of the task.  0 is the lowest priority. */
	//任务栈起始地址
    StackType_t			*pxStack;			/*< Points to the start of the stack. */
	//任务名称
    char				pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created.  Facilitates debugging only. */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
} tskTCB;

typedef tskTCB TCB_t;

2.FreeRTOS任务创建源码分析

        2.1.分配任务堆栈空间分配任务控制块内存空间

                先申请任务栈再申请TCB,任务栈地址<TCB地址,这种情况下,随着程序运行,任务栈栈顶地址往低地址方向走,即使任务栈空间不足,也不会触碰到TCB区域,这样相对安全一些。

        2.2.初始化任务控制块初始化任务堆栈

        2.3.添加任务到就绪列表

在这里插入图片描述

 

	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;
        
        //指硬件平台栈增长方式
        //Cortex-M4权威指南4.4.3
        //Cortex-M处理器使用的栈模型被称为“满递减”
        //#define portSTACK_GROWTH			( -1 )表示满减栈
		/* 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 )
		{
		}
		#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 )    //任务控制块内存分配成功
				{
                    //TCB中存储栈地址
					/* Store the stack location in the TCB. */
					pxNewTCB->pxStack = pxStack;
				}
				else
				{
                    //TCB创建失败,释放栈空间
					/* 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 )        //任务控制块内存分配成功
		{
            //新建任务初始化,具体函数实现见下一个代码段
			prvInitialiseNewTask( pxTaskCode, pcName, ( uint32_t ) usStackDepth, pvParameters, uxPriority, pxCreatedTask, pxNewTCB, NULL );
            //把任务添加到就绪列表中
			prvAddNewTaskToReadyList( pxNewTCB );
			xReturn = pdPASS;
		}
		else
		{
			xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
		}

		return xReturn;
	}
static void prvInitialiseNewTask( 	TaskFunction_t pxTaskCode,
									const char * const pcName,		/*lint !e971 Unqualified char types are allowed for strings and single characters only. */
									const uint32_t ulStackDepth,
									void * const pvParameters,
									UBaseType_t uxPriority,
									TaskHandle_t * const pxCreatedTask,
									TCB_t *pxNewTCB,
									const MemoryRegion_t * const xRegions )
{
StackType_t *pxTopOfStack;
UBaseType_t x;

    //计算栈顶的地址
	/* Calculate the top of stack address.  This depends on whether the stack
	grows from high memory to low (as per the 80x86) or vice versa.
	portSTACK_GROWTH is used to make the result positive or negative as required
	by the port. */
	#if( portSTACK_GROWTH < 0 )
	{
        //把栈空间的高地址分配给栈顶
		pxTopOfStack = &( pxNewTCB->pxStack[ ulStackDepth - ( uint32_t ) 1 ] );
        //栈对齐,栈要8字节对齐
		pxTopOfStack = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) ); /*lint !e923 !e9033 !e9078 MISRA exception.  Avoiding casts between pointers and integers is not practical.  Size differences accounted for using portPOINTER_SIZE_TYPE type.  Checked by assert(). */
          
        //检查是否有错误
		/* Check the alignment of the calculated top of stack is correct. */
		configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );

	}
	#else /* portSTACK_GROWTH */
	{
	}
	#endif /* portSTACK_GROWTH */
    
    //在TCB中存储任务名称
	/* Store the task name in the TCB. */
	if( pcName != NULL )
	{
		for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ )
		{
			pxNewTCB->pcTaskName[ x ] = pcName[ x ];

			/* Don't copy all configMAX_TASK_NAME_LEN if the string is shorter than
			configMAX_TASK_NAME_LEN characters just in case the memory after the
			string is not accessible (extremely unlikely). */
			if( pcName[ x ] == ( char ) 0x00 )
			{
				break;
			}
			else
			{
				mtCOVERAGE_TEST_MARKER();
			}
		}

		/* Ensure the name string is terminated in the case that the string length
		was greater or equal to configMAX_TASK_NAME_LEN. */
		pxNewTCB->pcTaskName[ configMAX_TASK_NAME_LEN - 1 ] = '\0';
	}
	else
	{
		/* The task has not been given a name, so just ensure there is a NULL
		terminator when it is read out. */
		pxNewTCB->pcTaskName[ 0 ] = 0x00;
	}
    
    //判断任务分配的优先级是否大于最大值
	/* This is used as an array index so must ensure it's not too large.  First
	remove the privilege bit if one is present. */
	if( uxPriority >= ( UBaseType_t ) configMAX_PRIORITIES )
	{
		uxPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;
	}
	else
	{
		mtCOVERAGE_TEST_MARKER();
	}
    
    //在TCB中存储任务优先级
	pxNewTCB->uxPriority = uxPriority;

    //任务状态表、事件表初始化
	vListInitialiseItem( &( pxNewTCB->xStateListItem ) );
	vListInitialiseItem( &( pxNewTCB->xEventListItem ) );

    //任务控制块链接到任务状态表中
	/* Set the pxNewTCB as a link back from the ListItem_t.  This is so we can get
	back to	the containing TCB from a generic item in a list. */
	listSET_LIST_ITEM_OWNER( &( pxNewTCB->xStateListItem ), pxNewTCB );
    
    //任务控制块链接到任务事件表中
	/* Event lists are always in priority order. */
	listSET_LIST_ITEM_VALUE( &( pxNewTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
	listSET_LIST_ITEM_OWNER( &( pxNewTCB->xEventListItem ), pxNewTCB );


    
	/* Initialize the TCB stack to look as if the task was already running,
	but had been interrupted by the scheduler.  The return address is set
	to the start of the task function. Once the stack has been initialised
	the top of stack variable is updated. */
    //#define portUSING_MPU_WRAPPERS 0
	#if( portUSING_MPU_WRAPPERS == 1 )
	{
	}
	#else /* portUSING_MPU_WRAPPERS */
	{
        //任务堆栈初始化,之后返回任务栈顶
	    pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters );

	}
	#endif /* portUSING_MPU_WRAPPERS */

	if( pxCreatedTask != NULL )
	{
        //赋值任务句柄(就是TCB)
		/* Pass the handle out in an anonymous way.  The handle can be used to
		change the created task's priority, delete the created task, etc.*/
		*pxCreatedTask = ( TaskHandle_t ) pxNewTCB;
	}
	else
	{
		mtCOVERAGE_TEST_MARKER();
	}
}
//M4权威指南第八章节,分析异常处理
//任务调度其实就是通过CPU内核异常处理实现的
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
{
	/* Simulate the stack frame as it would be created by a context switch
	interrupt. */

	/* Offset added to account for the way the MCU uses the stack on entry/exit
	of interrupts, and to ensure alignment. */
	pxTopOfStack--;
    //入栈程序状态寄存器
	*pxTopOfStack = portINITIAL_XPSR;	/* xPSR */
	pxTopOfStack--;
    //入栈PC指针
	*pxTopOfStack = ( ( StackType_t ) pxCode ) & portSTART_ADDRESS_MASK;	/* PC */
	pxTopOfStack--;
    //入栈LR链接寄存器
	*pxTopOfStack = ( StackType_t ) prvTaskExitError;	/* LR */
    
    //R1,R2,R3,R12不需要初始化
	/* Save code space by skipping register initialisation. */
	pxTopOfStack -= 5;	/* R12, R3, R2 and R1. */
    //R0作为传参入栈
	*pxTopOfStack = ( StackType_t ) pvParameters;	/* R0 */

	/* A save method is being used that requires each task to maintain its
	own exec return value. */
	pxTopOfStack--;
    //异常返回值入栈    返回值是确定程序使用的栈地址是哪一个  MSP还是PSP
	*pxTopOfStack = portINITIAL_EXC_RETURN;
    //R4-R11不初始化
	pxTopOfStack -= 8;	/* R11, R10, R9, R8, R7, R6, R5 and R4. */
    //最终返回栈顶值
	return pxTopOfStack;
}

3.FreeRTOS任务删除源码分析

        3.1.从就绪表中删除

        3.2.从事件表中删除

        3.3.释放任务控制块释放任务堆栈内存

        3.4.开始任务调度

	void vTaskDelete( TaskHandle_t xTaskToDelete )
	{
	TCB_t *pxTCB;
        //进入临界段
		taskENTER_CRITICAL();
		{
            //获取任务控制块————参数传入的是任务句柄
            //判断是任务本身还是其他任务
            //如果是当前任务,传入的参数为NULL
			/* If null is passed in here then it is the calling task that is
			being deleted. */
			pxTCB = prvGetTCBFromHandle( xTaskToDelete );
            
            //从就绪列表中移除
			/* Remove task from the ready/delayed list. */
			if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
			{
				taskRESET_READY_PRIORITY( pxTCB->uxPriority );
			}
			else
			{
				mtCOVERAGE_TEST_MARKER();
			}
            
            //从事件列表中移除
			/* Is the task waiting on an event also? */
			if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
			{
				( void ) uxListRemove( &( pxTCB->xEventListItem ) );
			}
			else
			{
				mtCOVERAGE_TEST_MARKER();
			}

			/* Increment the uxTaskNumber also so kernel aware debuggers can
			detect that the task lists need re-generating.  This is done before
			portPRE_TASK_DELETE_HOOK() as in the Windows port that macro will
			not return. */
			uxTaskNumber++;
            
            //如果删除的是当前任务
			if( pxTCB == pxCurrentTCB )
			{
                //不能在此删除,要在空闲任务中删除
                //把任务添加到等待删除的任务列表中
				/* A task is deleting itself.  This cannot complete within the
				task itself, as a context switch to another task is required.
				Place the task in the termination list.  The idle task will
				check the termination list and free up any memory allocated by
				the scheduler for the TCB and stack of the deleted task. */
				vListInsertEnd( &xTasksWaitingTermination, &( pxTCB->xStateListItem ) );
                
                //给空闲任务一个标记
				/* Increment the ucTasksDeleted variable so the idle task knows
				there is a task that has been deleted and that it should therefore
				check the xTasksWaitingTermination list. */
				++uxDeletedTasksWaitingCleanUp;
                
                //钩子函数,需要用户自己实现
				/* Call the delete hook before portPRE_TASK_DELETE_HOOK() as
				portPRE_TASK_DELETE_HOOK() does not return in the Win32 port. */
				traceTASK_DELETE( pxTCB );

				/* The pre-delete hook is primarily for the Windows simulator,
				in which Windows specific clean up operations are performed,
				after which it is not possible to yield away from this task -
				hence xYieldPending is used to latch that a context switch is
				required. */
				portPRE_TASK_DELETE_HOOK( pxTCB, &xYieldPending );
			}
			else    //如果删除的不是当前任务
			{
                //直接删除任务控制块
				--uxCurrentNumberOfTasks;
				traceTASK_DELETE( pxTCB );
                //复位任务锁定时间
                //操作系统根据最新的时间进行调度,所以删除任务后,要更新锁定时间
				prvDeleteTCB( pxTCB );

				/* Reset the next expected unblock time in case it referred to
				the task that has just been deleted. */
				prvResetNextTaskUnblockTime();
			}
		}
        //退出临界段
		taskEXIT_CRITICAL();
        
        //判断调度器是否开启
		/* Force a reschedule if it is the currently running task that has just
		been deleted. */
		if( xSchedulerRunning != pdFALSE )    //调度器开启中
		{
			if( pxTCB == pxCurrentTCB )    //如果是删除任务本身
			{
                //马上进行任务调度(释放CPU的使用权)
				configASSERT( uxSchedulerSuspended == 0 );
				portYIELD_WITHIN_API();
			}
			else
			{
				mtCOVERAGE_TEST_MARKER();
			}
		}
	}

4.FreeRTOS任务挂起源码分析

        4.1.从就绪表中删除

        4.2.从事件表中删除

        4.3.添加任务到挂起列表中

        4.4.开始任务调度

    void vTaskSuspend( TaskHandle_t xTaskToSuspend )
	{
	TCB_t *pxTCB;
        //进入临界段
		taskENTER_CRITICAL();
		{
            //获取任务控制块
			/* If null is passed in here then it is the running task that is
			being suspended. */
			pxTCB = prvGetTCBFromHandle( xTaskToSuspend );

            //从就绪列表中移除
			/* Remove task from the ready/delayed list and place in the
			suspended list. */
			if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
			{
				taskRESET_READY_PRIORITY( pxTCB->uxPriority );
			}
			else
			{
				mtCOVERAGE_TEST_MARKER();
			}
            
            //从事件列表中移除
			/* Is the task waiting on an event also? */
			if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
			{
				( void ) uxListRemove( &( pxTCB->xEventListItem ) );
			}
			else
			{
				mtCOVERAGE_TEST_MARKER();
			}
            
            //把任务添加到挂起列表中
			vListInsertEnd( &xSuspendedTaskList, &( pxTCB->xStateListItem ) );
		}
        //退出临界段
		taskEXIT_CRITICAL();
        
        //判断调度器是否开启
		if( xSchedulerRunning != pdFALSE )
		{
            //更新下个任务的锁定时间
			/* Reset the next expected unblock time in case it referred to the
			task that is now in the Suspended state. */
			taskENTER_CRITICAL();
			{
				prvResetNextTaskUnblockTime();
			}
			taskEXIT_CRITICAL();
		}
		else
		{
			mtCOVERAGE_TEST_MARKER();
		}

		if( pxTCB == pxCurrentTCB )        //如果是当前任务
		{
			if( xSchedulerRunning != pdFALSE )    //如果调度器已开启
			{
                //直接开始任务调度,释放CPU的使用权
				/* The current task has just been suspended. */
				configASSERT( uxSchedulerSuspended == 0 );
				portYIELD_WITHIN_API();
			}
			else        //如果调度器没有开启
			{
                //读取当前任务挂起列表的长度
				/* The scheduler is not running, but the task that was pointed
				to by pxCurrentTCB has just been suspended and pxCurrentTCB
				must be adjusted to point to a different task. */
				if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == uxCurrentNumberOfTasks ) /*lint !e931 Right has no side effect, just volatile. */
				{
                    //如果挂起列表已经把所有任务挂起,把当前任务控制块赋值为NULL,不让任务控制块再使用了
					/* No other tasks are ready, so set pxCurrentTCB back to
					NULL so when the next task is created pxCurrentTCB will
					be set to point to it no matter what its relative priority
					is. */
					pxCurrentTCB = NULL;
				}
				else
				{
                    //任务上下文切换
                    //即在就绪列表中找到优先级最高的任务进行调度
					vTaskSwitchContext();
				}
			}
		}
		else
		{
			mtCOVERAGE_TEST_MARKER();
		}
	}

5.FreeRTOS任务恢复源码分析

        5.1.从挂起表中删除

        5.2.添加任务到就绪列表中

        5.3.开始任务调度

	void vTaskResume( TaskHandle_t xTaskToResume )
	{
    //获取要恢复的任务控制块
	TCB_t * const pxTCB = xTaskToResume;
        
        //检查
		/* It does not make sense to resume the calling task. */
		configASSERT( xTaskToResume );

        //既然要使用任务控制块,肯定不能是NULL,也不能是当前的任务
		/* The parameter cannot be NULL as it is impossible to resume the
		currently executing task. */
		if( ( pxTCB != pxCurrentTCB ) && ( pxTCB != NULL ) )
		{
            //进入临界段
			taskENTER_CRITICAL();
			{
                //判断任务是否已经挂起
				if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE )
				{
                    //从挂起列表中移除
					/* The ready list can be accessed even if the scheduler is
					suspended because this is inside a critical section. */
					( void ) uxListRemove(  &( pxTCB->xStateListItem ) );
                    //添加任务到就绪列表
					prvAddTaskToReadyList( pxTCB );
                
                    //判断要恢复的任务是否大于当前任务的优先级
                    //如果大于,释放CPU的使用权,开始内核调度
                    //前提条件是已经使能了抢占式调度器
					/* A higher priority task may have just been resumed. */
					if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
					{
						/* This yield may not cause the task just resumed to run,
						but will leave the lists in the correct state for the
						next yield. */
						taskYIELD_IF_USING_PREEMPTION();
					}
					else
					{
						mtCOVERAGE_TEST_MARKER();
					}
				}
				else
				{
					mtCOVERAGE_TEST_MARKER();
				}
			}
            //退出临界段
			taskEXIT_CRITICAL();
		}
		else
		{
			mtCOVERAGE_TEST_MARKER();
		}
	}

6.任务API总结(部分)

API名称API说明
xTaskCreate动态创建任务
xTaskCreateStatic静态创建任务
vTaskDelete删除任务
vTaskSuspend挂起任务
vTaskResume恢复任务
xTaskResumeFromISR在中断中恢复任务
uxTaskPriorityGet获取任务优先级
vTaskPrioritySet设置任务优先级
vTaskDelay

延时任务

Functions are prefixed with both the type they return and the file they are defined in. For example:
1.vTaskPrioritySet() returns a void and is defined within task.c.
2.xQueueReceive() returns a variable of type BaseType_t and is defined within queue.c.
3.vSemaphoreCreateBinary() returns a void and is defined within semphr.h.
File scope (private) functions are prefixed with ‘prv’.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

FreeRTOS任务创建、删除、挂起、恢复源码分析 的相关文章

  • 详解FreeRTOS中的软件定时器

    软件定时器用于让某个任务定时执行 或者周期性执行 比如设定某个时间后执行某个函数 或者每隔一段时间执行某个函数 由软件定时器执行的函数称为软件定时器的回调函数 参考资料 Mastering the FreeRTOS Real Time Ke
  • FreeRTOS内核配置说明---FreeRTOS Kernel V10.2.1

    FreeRTOS内核是高度可定制的 使用配置文件FreeRTOSConfig h进行定制 每个FreeRTOS应用都必须包含这个头文件 用户根据实际应用来裁剪定制FreeRTOS内核 这个配置文件是针对用户程序的 而非内核 因此配置文件一般
  • FreeRTOS快速上手

    FreeRTOS使用 一 源码下载和移植文件提取 1 1 源码下载 在网站https sourceforge net projects freertos 可以找到freertos最新的源码 1 2 移植文件提取 根据第一步 我们会得到一个f
  • FreeRTOS 软件定时器的使用

    FreeRTOS中加入了软件定时器这个功能组件 是一个可选的 不属于freeRTOS内核的功能 由定时器服务任务 其实就是一个定时器任务 来提供 软件定时器是当设定一个定时时间 当达到设定的时间之后就会执行指定的功能函数 而这个功能函数就叫
  • FreeRTOS学习笔记(3、信号量、互斥量的使用)

    FreeRTOS学习笔记 3 信号量 互斥量的使用 前言 往期学习笔记链接 学习工程 信号量 semaphore 两种信号量的对比 信号量的使用 1 创建信号量 2 give 3 take 4 删除信号量 使用计数型信号量实现同步功能 使用
  • 【FreeRTOS】多任务创建

    作者主页 凉开水白菜 作者简介 共同学习 互相监督 热于分享 多加讨论 一起进步 专栏资料 https pan baidu com s 1nc1rfyLiMyw6ZhxiZ1Cumg pwd free 点赞 收藏 再看 养成习惯 订阅的粉丝
  • FreeRTOS学习(八) 延时函数

    声明及感谢 跟随正点原子资料学习 在此作为学习的记录和总结 环境 keil stm32f103 FreeRTOS延时函数有两个 分别是 vTaskDelay vTaskDelayUntil 1 vTaskDelay 任务相对延时 函数原型
  • 【FreeRTOS开发问题】FreeRTOS内存溢出

    FreeRTOS内存溢出 如下图所示 FreeRTOS编译完成后可以看到 系统提示无法分配内存到堆 Objects Template axf Error L6406E No space in execution regions with A
  • 【FreeRTOS】队列的使用

    作者主页 凉开水白菜 作者简介 共同学习 互相监督 热于分享 多加讨论 一起进步 专栏资料 https pan baidu com s 1nc1rfyLiMyw6ZhxiZ1Cumg pwd free 点赞 收藏 再看 养成习惯 订阅的粉丝
  • FreeRTOS临界区

    FreeRTOS临界区是指那些必须完整运行 不能被打断的代码段 比如有的外设的初始化需要严格的时序 初始化过程中不能被打断 FreeRTOS 在进入临界区代码的时候需要关闭中断 当处理完临界区代码以后再打开中断 FreeRTOS 系统本身就
  • 【FreeRTOS(三)】任务状态

    文章目录 任务状态 任务挂起 vTaskSuspend 取消任务挂起 vTaskResume 挂起任务调度器 vTaskSuspendAll 取消挂起任务调度器 xTaskResumeAll 代码示例 任务挂起 取消任务挂起 代码示例 挂起
  • FreeRTOS_中断

    传送门 博客汇总帖 传送门 Cortex M3 中断 异常 传送门 Cortex M3笔记 基础 笔记内容参考 正点原子的FreeRTOS开发手册 cortex m3权威指南 Cortex M3和Cortex M4权威指南等 文中stm32
  • Error: L6218E: Undefined symbol vApplicationGetIdleTaskMemory (referred from tasks.o).

    我用的是F103ZET6的板子 移植成功后 编译出现两个错误是关于stm32f10x it c 里 void SVC Handler void void PendSV Handler void 两个函数的占用问题 随后编译出现以下两个问题
  • Arduino IDE将FreeRTOS用于STM32

    介绍 适用于STM32F103C8的FreeRTOS STM32F103C是一种能够使用FreeRTOS的ARM Cortex M3处理器 我们直接在Arduino IDE中开始使用STM32F103C8的FreeRTOS 我们也可以使用K
  • FreeRTOS轻量级同步--任务通知

    1 简介 在FreeRTOS的配置参数中的configUSE TASK NOTIFICATIONS宏打开 一般RTOS会默认打开 如图1所示 图1 notify宏开关 RTOS在创建任务时 会创建一个32位的通知值ulNotifiedVal
  • FreeRTOSConfig.h 配置优化及深入

    本篇目标 基于上一篇的移植freertos stm32f4 freertos 上 修改 FreeRTOSConfig h 文件的相关配置来优化辅助 FreeRtos 的使用 并且建立一些基本功能 信号量 消息地列等 的简单应用位于 stm3
  • FreeRTOS 配置TICK_RATE_HZ

    我使用的是带有 5 4 版 FreeRTOS 的 MSP430f5438 我有一个有趣的问题 我无法弄清楚 基本上 当我将 configTICK RATE HZ 设置为不同的值时 LED 闪烁得更快或更慢 它应该保持相同的速率 我将 con
  • FreeRTOS 匈牙利表示法 [重复]

    这个问题在这里已经有答案了 我是 RTOS 和 C 编程的新手 而且我仍在习惯 C 的良好实践 因此 我打开了一个使用 FreeRTOS 的项目 我注意到操作系统文件使用匈牙利表示法 我知道一点符号 但面临一些新的 标准 FreeRTOS
  • C++ freeRTOS任务,非静态成员函数的无效使用

    哪里有问题 void MyClass task void pvParameter while 1 this gt update void MyClass startTask xTaskCreate this gt task Task 204
  • GNU Arm Cortex m4 上的 C++ 异常处理程序与 freertos

    2016 年 12 月更新现在还有一个关于此行为的最小示例 https community nxp com message 862676 https community nxp com message 862676 我正在使用带有 free

随机推荐

  • Windows+COLMAP三维重建教程【exe安装】

    一 步骤 1 下载COLMAP COLMAP COLMAP 2 解压并运行COLMAP 3 稀疏三维重建 xff0c 生成稀疏图 4 稠密图三维重建 xff0c 生成稠密图 二 可能出现的问题 1 Dense stereo reconstr
  • 程序基础:正则表达式

    一 正则表达式元字符 1 匹配字符 xff1a xff1a 任意一个字符 abc xff1a 表示匹配一个字符 xff0c 这个字符必须是abc中的一个 a zA Z xff1a 表示匹配一个字符 xff0c 这个字符必须是a z或A Z这
  • 【Ubuntu版】CMake安装教程

    一 参考资料 Windows版 CMake安装教程 二 具体步骤 1 离线安装 1 1 Ubuntu系统 官网下载CMake软件包 CMake官网 解压软件包 cmake可执行性文件 home yoyo 360Downloads cmake
  • Jetson TX2刷机教程

    一 参考资料 Jetson TX2官方文档 Jetpack开发者文档 Jetson官方安装教程 jetson tx2刷机 TX2 NVIDIA Jetson Tx2刷机指南 xff08 JetPack 4 4 SDK manager 1 4
  • FFmpeg教程(超级详细版)

    一 参考资料 通过ffmpeg把图片转换成视频 FFmpeg命令 一 使用filter complex命令拼接视频 FFmpeg 视频处理入门教程给新手的 20 多个 FFmpeg 命令示例 FFmpeg命令行转码 ffmpeg 翻译文档
  • yolov5+Deepsort实现目标跟踪

    一 参考资料 项目源码 pytorch yolo5 43 Deepsort实现目标检测和跟踪 工程落地 YoloV5 43 deepsort 43 Fast ReID 完整行人重识别系统 xff08 三 xff09 yolov5 deeps
  • Jetson Xaiver NX相关教程(详细版)

    一 参考资料 Jetson nano NX 部署Yolo v5过程记录 二 相关介绍 三 软件安装 2 1 jetson stats 2 1 1 相关介绍 jetson stats是一个开源软件包 xff0c 用于监测和控制Nvidia J
  • 编译C++程序(经验版)

    一 g 43 43 编译 span class token comment 编译 span g 43 43 文件名 g 43 43 helloWorld cpp g 43 43 文件名 o 输出文件名 g 43 43 open video
  • 【WSL2教程】WSL迁移到非系统盘

    一 问题引入 默认情况下 xff0c WSL会安装在C盘 xff08 系统盘 xff09 xff0c 而C盘空间有限 xff0c 随着WSL子系统的使用 xff0c C盘空间越来越少 xff0c 最后有可能出现C盘不足导致WSL系统崩溃 有
  • 华为Ascend昇腾适配PyTorch框架

    一 参考资料 PyTorch用户文档 PyTorch网络模型移植 amp 训练指南 AscendPyTorch 第三方框架适配 二 重要说明 CPU架构为ARM架构时 xff0c 由于社区未提供ARM架构CPU版本的torch包 xff0c
  • 提高工作效率的宝藏网站和宝藏工具

    一 好用的网站 面包多 面包多 创作者在面包多 xff0c 通过出售课程 xff0c 文章 xff0c 绘画 xff0c 创意作品 xff0c 软件 xff0c 电子书 xff0c 音乐 xff0c 游戏 xff0c 咨询服务 xff0c
  • ubuntu服务器相关教程

    二 常用操作 1 ssh相关 span class token comment 安装ssh服务 span span class token function sudo span span class token function apt g
  • Qt学习:Qt5.9.2+vs2017移植usb第三方库

    第三方库Hidapi用于实现usb通信 xff0c 将它移植成功以用来实现qt做一个usb通信的上位机 首先是下载hidapi 0 7 0源码 xff1a http www signal11 us oss hidapi 源码文件夹截图如下
  • 超级实用的C++学习网站

    重要说明 xff1a 该博客长期更新 xff0c 方便读者查阅 xff01 一 参考资料 学习C 43 43 这几个网站足矣 二 C 43 43 学习网站 C 43 43 中文网 cppreference 当之无愧的C 43 43 学习第一
  • 目标检测中NMS(非极大抑制)的概念理解

    参考博客 物体检测中常用的几个概念迁移学习 IOU NMS理解 目标定位和检测系列 xff08 3 xff09 xff1a 交并比 xff08 IOU xff09 和非极大值抑制 xff08 NMS xff09 的python实现 一 NM
  • VMware虚拟机上不能使用CUDA/CUDNN

    参考博客 VMware虚拟机上不能使用CUDA Linux Ubuntu 系统查看显卡型号 一 综述 虚拟机的显卡是虚拟的 xff0c 不能使用CUDA 虚拟机上装Nvidia显卡驱动会导致其他驱动全都不能用 xff0c 所以不能在虚拟机上
  • CUDA、CUDNN在windows下的安装及配置

    参考文章 全网最详细 Windows 安装 TensorFlow2 0 GPU 详细教程 Wind10安装anaonda 43 cuda10 1 43 cudnn 43 pytorch 43 tensorflow gpu win10 43
  • windows下CUDA的卸载以及安装

    参考博客 windows 7 下cuda 9 0 卸载 cuda8 0 安装 一 前言 对于一个刚玩CUDA菜鸟来说 xff0c 安装问题就是一个巨大的坑 xff0c 安装过程里面有很多需要注意的细节 xff0c 很多自定义的选项 xff0
  • 算法高级(35)-最优路径选择-导航软件是怎么选择最佳路线的?

    前面我们学习了图算法中的最短路径算法 xff0c 可以参考我的这篇博文常用的图算法 xff1a 最短路径 Shortest Path xff0c 解决最短路的问题有以下算法 xff0c Dijkstra算法 xff0c Bellman Fo
  • FreeRTOS任务创建、删除、挂起、恢复源码分析

    目录 1 任务控制块 结构体TCB t 2 FreeRTOS任务创建源码分析 3 FreeRTOS任务删除源码分析 4 FreeRTOS任务挂起源码分析 5 FreeRTOS任务恢复源码分析 6 任务API总结 xff08 部分 xff09