FreeRTOS系列|时间管理

2023-05-16

FreeRTOS时间管理

1. FreeRTOS延时函数

在使用FreeRTOS的过程中经常会在一个任务中使用延时函数对该任务延时,当执行延时函数的时候就会进行任务切换,并且此任务就会进入阻塞态,直到延时完成,任务重新进入就绪态

1.1 相对延时函数

相对延时函数vTaskDelay()在文件task.c中定义,功能是使任务进入阻塞态,根据传入的参数延时多少个tick(系统节拍),其函数原型如下:

函数原型:void vTaskDelay(TickType_t xTicksToDelay)
传 入 值:xTicksToDelay 延时周期
		 系统节拍周期为1000Hz,延时周期时基就是1ms;
		 系统节拍周期为100Hz,延时周期时基就是10ms;

函数实现的源码如下:

//宏INCLUDE_vTaskDelay须置1
void vTaskDelay(const TickType_t xTicksToDelay){
  /* xAlreadyYielded:已经调度的状态,初始赋值为0 */
  BaseType_t xAlreadyYielded = pdFALSE;
  /* 延时周期要大于0,否则就相当于直接调用portYIELD()进行任务切换 */
  if(xTicksToDelay > (TickType_t) 0U){
	configASSERT( uxSchedulerSuspended == 0 );
	/* 挂起调度器 */
	vTaskSuspendAll();
	{
	  traceTASK_DELAY();
      /* 将要延时的任务添加到延时列表中 */
	  prvAddCurrentTaskToDelayedList( xTicksToDelay, pdFALSE );
	}
	  /* 恢复任务调度器 */
	  xAlreadyYielded = xTaskResumeAll();
  }
  else{
	mtCOVERAGE_TEST_MARKER();
  }
  /* xAlreadyYielded 等于FALSE,表示在恢复调度器的时候,没有进行任务切换 */
  if(xAlreadyYielded == pdFALSE){
	/* 进行一次任务调度,内部就是触发PendSV异常 */
	portYIELD_WITHIN_API();
  }
  else{
	mtCOVERAGE_TEST_MARKER();
  }
}

prvAddCurrentTaskToDelayedList()函数用于将当前任务添加到等待列表中,文件task.c中定义,其源码如下:

/* 添加任务到延时列表中
** 传入两个参数:
** xTicksToWait 延时周期
** xCanBlockIndefinitely 延时的确定状态 */
static void prvAddCurrentTaskToDelayedList(TickType_t xTicksToWait, 
										   const BaseType_t xCanBlockIndefinitely){
  /* 延时周期,表示下次唤醒的时间 */
  TickType_t xTimeToWake;
  /* 获取进入函数的时间点并保存在xConstTickCount中 */
  const TickType_t xConstTickCount = xTickCount;
  /* 把当前任务从就绪列表中移除 */
  if(uxListRemove( &( pxCurrentTCB->xStateListItem ) ) == ( UBaseType_t ) 0){
	/* 取消任务在uxTopReadyPriority中的就绪标记 */
	portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
  }
  else{
	mtCOVERAGE_TEST_MARKER();
  }
  /* 是否使用了任务挂起的功能 */
  #if ( INCLUDE_vTaskSuspend == 1 )
  {
	/* portMAX_DELAY=0XFFFFFFFF表示延时是一直持续的,即让任务一直阻塞 */
	if( ( xTicksToWait == portMAX_DELAY ) && ( xCanBlockIndefinitely != pdFALSE ) ){
	  /* 把任务添加到,挂起列表中去*/
	  vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xStateListItem ) );
	}
	else{
	  /* 计算任务唤醒的tick值 */
	  xTimeToWake = xConstTickCount + xTicksToWait;
      /* 将计算到的任务唤醒时间点写入到任务列表中状态列表项的相应字段中 */
	  listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake );
	  /* 计算得到的任务唤醒时间点小于xConstTickCount,说明发生了溢出 */
	  if( xTimeToWake < xConstTickCount){
		/* 若溢出,就把任务添加到延时溢出列表里 */
		vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
	  }
	  else{
		/* 若没有溢出,把任务添加到延时列表中,让内核进行处理 */
		vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
		/* 更新系统时间片,因为系统时间片永远保存最小的延时周期 */
		if( xTimeToWake < xNextTaskUnblockTime ){
		  xNextTaskUnblockTime = xTimeToWake;
		}
		else{
		  mtCOVERAGE_TEST_MARKER();
		}
	  }
    }
  }
  #else /* INCLUDE_vTaskSuspend */
  {
	/* 计算下次唤醒的系统节拍值 */
	xTimeToWake = xConstTickCount + xTicksToWait;
	/* 赋值到任务控制块里 */
	listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake );
	if( xTimeToWake < xConstTickCount ){
	  /* 溢出,添加到延时溢出列表中 */
	  vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
	}
	else{
	  /* 没有溢出,添加到延时列表中 */
	  vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
      /* 更新时间片 */
	  if( xTimeToWake < xNextTaskUnblockTime ){
	    xNextTaskUnblockTime = xTimeToWake;
	  }
	  else{
		mtCOVERAGE_TEST_MARKER();
	  }
	}
	/* Avoid compiler warning when INCLUDE_vTaskSuspend is not 1. */
	( void ) xCanBlockIndefinitely;
  }
  #endif /* INCLUDE_vTaskSuspend */
}
1.2 绝对延时函数

绝对延时函数vTaskDelayUntil()在文件task.c中定义,功能是使任务进入阻塞态,直到一个绝对延时时间到达,其函数原型如下:

函数原型:void vTaskDelayUntil(TickType_t *pxPreviousWakeTime,TickType_t xTimeIncrement)
传 入 值:pxPreviousWakeTime 记录任务上一次唤醒系统节拍值
		 xTimeIncrement 相对于pxPreviousWakeTime,本次延时的节拍数

函数实现的源码如下:

void vTaskDelayUntil(TickType_t * const pxPreviousWakeTime, 
					 const TickType_t xTimeIncrement){
  /* 下次任务要唤醒的系统节拍值 */
  TickType_t xTimeToWake;
  /* xAlreadyYielded:表示是否已经进行了任务切换 */
  /* xShouldDelay:表示是否需要进行延时处理 */
  BaseType_t xAlreadyYielded, xShouldDelay = pdFALSE;
  /* 挂起调度器 */
  vTaskSuspendAll();
  {
	/* 获取系统节拍值 */
	const TickType_t xConstTickCount = xTickCount;
	/* 计算任务下次唤醒的系统节拍值 */
	xTimeToWake = *pxPreviousWakeTime + xTimeIncrement;
	/* pxPreviousWakeTime表示上一次任务的唤醒节拍值,若该值大于xConstTickCount表示:
	   延时周期以及到达,或者xConstTickCount已经溢出了 */
	if( xConstTickCount < *pxPreviousWakeTime){
	  /* 下一次要唤醒的系统节拍值小于上次要唤醒节拍值(即系统节拍值计数溢出) 
	     下一次要唤醒的系统节拍值大于当前的系统节拍值(表示需要延时) */
	  if((xTimeToWake < *pxPreviousWakeTime)&&(xTimeToWake > xConstTickCount)){
		/* 标记允许延时 */
		xShouldDelay = pdTRUE;
	  }
	  else{
		mtCOVERAGE_TEST_MARKER();
	  }
	}
	else{
	  /* 下一次要唤醒的系统节拍值小于上次要唤醒节拍值(即系统节拍值计数溢出)
	     下一次要唤醒的系统节拍值大于当前的系统节拍值(表示需要延时) */
	  if((xTimeToWake < *pxPreviousWakeTime)||(xTimeToWake > xConstTickCount)){
		/* 标记允许延时 */
		xShouldDelay = pdTRUE;
	  }
	  else{
		mtCOVERAGE_TEST_MARKER();
	  }
	}
	/* 保存下次唤醒的节拍值,为下一次执行做准备 */
	*pxPreviousWakeTime = xTimeToWake;
	/* 判断是否需要延时 */
	if( xShouldDelay != pdFALSE ){
	  traceTASK_DELAY_UNTIL( xTimeToWake );
      /* 添加任务到延时列表中去 */
	  prvAddCurrentTaskToDelayedList( xTimeToWake - xConstTickCount, pdFALSE );
	}
	else{
	  mtCOVERAGE_TEST_MARKER();
	}
  }
  /* 恢复任务调度器,若任务调度器内部进行了任务切换,返回true */
  xAlreadyYielded = xTaskResumeAll();
  /* 若调度器没有进行任务切换,那么要进行任务切换*/
  if( xAlreadyYielded == pdFALSE ){
	/* 进行PendSV异常触发 */
	portYIELD_WITHIN_API();
  }
  else{
	mtCOVERAGE_TEST_MARKER();
  }
}
1.3 调度器挂起和恢复

调度器挂起函数vTaskSuspendAll()源码如下:

void vTaskSuspendAll(void){
  /* 调取记录值++ */
  ++uxSchedulerSuspended;
}

调度器恢复函数xTaskResumeAll()源码如下:

BaseType_t xTaskResumeAll(void){
  TCB_t *pxTCB = NULL;
  BaseType_t xAlreadyYielded = pdFALSE;
  /* 进入临界段 */
  taskENTER_CRITICAL();
  {
	/* 调度器记录值减一 */
	--uxSchedulerSuspended;
	/* 如果调度器需要恢复了 */
	if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE ){
	  /* 判断当前任务数量大于0 */
	  if( uxCurrentNumberOfTasks > ( UBaseType_t ) 0U ){
		/* 从挂起的就绪列表中遍历 */
		while( listLIST_IS_EMPTY( &xPendingReadyList ) == pdFALSE ){
		  /* 获取任务控制块 */
		  pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xPendingReadyList ) );
		  /* 移除挂起就绪列表,移除事件列表 */
		  ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
		  ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
		  /* 添加到就绪列表中 */
		  prvAddTaskToReadyList( pxTCB );
          /* 如果优先级大于当前任务优先级,则进行任务切换 */
		  if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority ){
			xYieldPending = pdTRUE;
		  }
		  else{
			mtCOVERAGE_TEST_MARKER();
		  }
		}
		/* 获取到任务控制块不为空 */
		if( pxTCB != NULL ){
		  /* 需要更新系统的时间片 */
		  prvResetNextTaskUnblockTime();
		}
		/* 获取在调度器挂起时,systick挂起记录值 */
		{
          UBaseType_t uxPendedCounts = uxPendedTicks; /* Non-volatile copy. */
		  /* 如果记录值大于0 */
		  if( uxPendedCounts > ( UBaseType_t ) 0U ){
			do
			{
			  /* 进行systick调度处理,遍历阻塞列表,如果需要任务切换,返回true */
			  if( xTaskIncrementTick() != pdFALSE ){
			    /* 标记任务需要切换 */
				xYieldPending = pdTRUE;
			  }
			  else{
				mtCOVERAGE_TEST_MARKER();
			  }
			  --uxPendedCounts;
			  /* 一直遍历,直到uxPendedCounts = 0 */
			} while( uxPendedCounts > ( UBaseType_t ) 0U );
			/* 赋值为0 */
			uxPendedTicks = 0;
		  }
		  else{
			mtCOVERAGE_TEST_MARKER();
		  }
		}
		/* 如果需要进行任务切换 */
		if( xYieldPending != pdFALSE ){
		  /* 判断是否内核是抢占式 */
		  #if( configUSE_PREEMPTION != 0 )
		  {
			/* 标记已经调度的状态 */
			xAlreadyYielded = pdTRUE;
		  }
		  #endif
		  /* 进行调度 */
		  taskYIELD_IF_USING_PREEMPTION();
		}
		else{
		  mtCOVERAGE_TEST_MARKER();
		}
	  }
	}
	else{
	  mtCOVERAGE_TEST_MARKER();
	}
  }
  /* 退出临界段 */
  taskEXIT_CRITICAL();
  /* 返回调度的状态值 */
  return xAlreadyYielded;
}

2. FreeRTOS系统时钟节拍

不管是什么系统,运行都需要系统时钟节拍,xTickCount就是FreeRTOS的系统时钟节拍计数器。每个滴答定时器中断中xTickCount会加一,xTickCount的具体操作过程是在函数xTaskIncrementTick()中进行的

2.1 SysTick初始化

系统节拍初始化函数vPortSetupTimerInterrupt(),在port.c文件中定义,其源码如下:

void vPortSetupTimerInterrupt( void ){
  portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
  portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT );
}
2.2 SysTick中断服务函数

系统节拍中断服务函数xPortSysTickHandler(),其源码如下:

void xPortSysTickHandler( void ){
  /* 配置中断屏蔽寄存器,不让IRQ打断systick中断服务,即进入临街段	*/
  vPortRaiseBASEPRI();
  {
	/* 操作系统调度接口,若调度器返回true,触发pendSV异常 */
	if( xTaskIncrementTick() != pdFALSE ){
	  /* 触发pendSV */
	  portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
	}
  }
  /* 清除可屏蔽中断,即打开全部中断 */
  vPortClearBASEPRIFromISR();
}
2.3 SysTick任务调度

系统节拍任务调度函数xTaskIncrementTick(),其源码如下:

BaseType_t xTaskIncrementTick( void ){
  TCB_t * pxTCB;
  TickType_t xItemValue;
  /* 返回值,表示是否进行上下文切换 */
  BaseType_t xSwitchRequired = pdFALSE;
  /* uxSchedulerSuspended表示任务调度器是否挂起,,pdFALSE表示没有被挂起 */
  if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE ){
	/* 时钟节拍计数器增加1 */
	const TickType_t xConstTickCount = xTickCount + 1;
	xTickCount = xConstTickCount;
	/* 判断tick是否溢出越界,为0说明发生了溢出 */
	if( xConstTickCount == ( TickType_t ) 0U ){
	  /* 若溢出,要更新延时列表 */
  	  taskSWITCH_DELAYED_LISTS();
    }
    else{
	mtCOVERAGE_TEST_MARKER();
    }
    /* xNextTaskUnblockTime保存着下一个要解除阻塞的任务的时间点 */
    if( xConstTickCount >= xNextTaskUnblockTime ){
	  /* 会一直遍历整个任务延时列表,主要目的是,找到时间片最短的任务,进行切换 */
	  for( ;; ){
	    /* 判断任务延时列表是否为空,即有没有任务在等待调度 */
	    if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE ){
		  /* 如果没有任务等待,把时间片赋值为最大值,不再调度 */
		  xNextTaskUnblockTime = portMAX_DELAY; 
		  break;
	    }
 	    else{
		  /* 若有任务等待,获取延时列表第一个列表项对应的任务控制块*/
		  pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );
		  /* 获取上面任务控制块的状态列表项值 */
		  xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xStateListItem ) );
		  /* 再次判断这个任务的时间片是否到达 */
		  if( xConstTickCount < xItemValue ){
		    /* 若没有到达,把此任务的时间片更新为当前系统的时间片 */
		    xNextTaskUnblockTime = xItemValue;
		    /* 直接退出,不用调度 */
		    break;
		  }
		  else{
		    mtCOVERAGE_TEST_MARKER();
		  }

		  /* 任务延时时间到,把任务从延时列表中移除 */
		  ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
		  /* 再把任务从事件列表中移除 */
		  if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ){
		    ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
		  }
		  else{
		    mtCOVERAGE_TEST_MARKER();
		  }
		  /* 把任务添加到就绪列表中 */
		  prvAddTaskToReadyList( pxTCB );
		  /* 抢占式内核 */
		  #if (  configUSE_PREEMPTION == 1 )
		  {
		    /* 判断解除阻塞的任务的优先级是否高于当前任务的优先级 */
		    if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority ){
			  /* 如果是的话,就需要进行一次任务切换 */
			  xSwitchRequired = pdTRUE;	
		    }
		    else{
			  mtCOVERAGE_TEST_MARKER();
		    }
		  }
		  #endif /* configUSE_PREEMPTION */
	    }
	  }
    }

    /* 若使能了时间片处理机制,还需要处理同优先级下任务之间的调度 */
    #if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) )
    {
	  /* 获取就绪列表长度, 若有其他任务在就绪列表中,就开始调度*/
  	  if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB->uxPriority ] ) ) > ( UBaseType_t ) 1 ){
	    xSwitchRequired = pdTRUE;
	  }
	  else{
	    mtCOVERAGE_TEST_MARKER();
	  }
    }
    #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) */
  }
  else{ /* 任务调度器挂起 */
  	/* 挂起的tick+1 */
	++uxPendedTicks;
  }
  /* 如果是抢占模式,要开启调度 */
  #if ( configUSE_PREEMPTION == 1 )
  {
	if( xYieldPending != pdFALSE ){
	  xSwitchRequired = pdTRUE;
	}
	else{
	  mtCOVERAGE_TEST_MARKER();
	}
  }
  #endif /* configUSE_PREEMPTION */
  /* 返回调度器状态 */
  return xSwitchRequired;
}

在这里插入图片描述

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

FreeRTOS系列|时间管理 的相关文章

  • STM32CubeMX+FreeRTOS学习笔记(一)

    嵌入式实时操作系统FreeRTOS 基本概述 在嵌入式领域当中 实时操作系统的应用越来越广泛了 目前嵌入式操作系统种类很多 例如 Clinux C OS II C OS III FreeRTOS RT Thread等等 这篇文章所记录的就是
  • 【FreeRTOS开发问题】FreeRTOS内存溢出

    FreeRTOS内存溢出 如下图所示 FreeRTOS编译完成后可以看到 系统提示无法分配内存到堆 Objects Template axf Error L6406E No space in execution regions with A
  • 基于HAL库的FREERTOS----------一.任务

    FreeROTS 就是一个免费的 RTOS 类系统 这里要注意 RTOS 不是指某一个确定的系统 而是指一类系统 比如 UCOS FreeRTOS RTX RT Thread 等这些都是 RTOS 类操作系统 FreeRTOS 是 RTOS
  • FreeRTOS记录(九、一个裸机工程转FreeRTOS的实例)

    记录一下一个实际项目由裸机程序改成FreeRTOS 以前产品的平台还是C8051单片机上面的程序 硬件平台改成了STM32L051 同时使用STM32CubeMX生成的工程 使用FreeRTOS系统 EEPROM数据存储读取函数修改更新 2
  • 关于《时间管理》

    01 为什么需要时间管理 我们 多数人不是富二代 也不是官二代 如何比得过白富美和高富帅 在万千的不公平中 还有这唯一公平的资源 时间 好好把你的时间加以管理 以弥补并创造出其他的资源 人的一生两个最大的财富是 你的才华和你的时间 才华越来
  • Error: L6218E: Undefined symbol vApplicationGetIdleTaskMemory (referred from tasks.o).

    我用的是F103ZET6的板子 移植成功后 编译出现两个错误是关于stm32f10x it c 里 void SVC Handler void void PendSV Handler void 两个函数的占用问题 随后编译出现以下两个问题
  • STM32F103移植FreeRTOS必须搞明白的系列知识---2(FreeRTOS任务优先级)

    STM32F103移植FreeRTOS必须搞明白的系列知识 1 Cortex CM3中断优先级 STM32F103移植FreeRTOS必须搞明白的系列知识 2 FreeRTOS任务优先级 STM32F103移植FreeRTOS必须搞明白的系
  • 啊哈C的简单使用

    打开啊哈C 新建一个程序输出hello world include
  • Arduino IDE将FreeRTOS用于STM32

    介绍 适用于STM32F103C8的FreeRTOS STM32F103C是一种能够使用FreeRTOS的ARM Cortex M3处理器 我们直接在Arduino IDE中开始使用STM32F103C8的FreeRTOS 我们也可以使用K
  • FreeRTOS学习笔记(8)---- 软件定时器

    使用FreeRTOS软件定时器需要在文件FreeRTOSConfig h先做如下配置 1 configUSE TIMERS 使能软件定时器 2 configTIMER TASK PRIORITY 定时器任务优先级 3 configTIMER
  • [FreeRTOS入门学习笔记]定时器

    定时器的使用步骤 1 定义一个handle xTimerCreate创建 2 启动定时器 在Task1中调用 通过队列通知守护任务来执行定时器任务 要再config头文件中定义守护任务相关配置 虽然定时器是在task1中启动 但是定时器的任
  • freeRTOS出现任务卡死的情况。

    最近在做一个产品二代升级的项目 代码是上一任工程师留下的 很多BUG 而且融合了HAL库和LL库 以及github上下载的GSM源码 很不好用 我这边是将2G模块换成了4G 且添加了单独的BLE模块 因此只在源码的基础上 去除2G和BLE代
  • FreeRTOS临界段

    1 临界段 在访问共享资源时不希望被其他任务或者中断打断的代码 这段要执行的代码称为临界段代码 2 设置临界段的目的 保护共享资源 例如 全局变量 公共函数 不可重入函数 函数里面使用 了一些静态全局变量 malloc 等 保护外设的实时性
  • STM32 Freertos 添加 外部sram heap_5.c

    1 添加外部SRAM 初始化 2 添加heap 5 c 3 初始化heap 5 c 外部堆栈 Define the start address and size of the two RAM regions not used by the
  • FreeRTOS之系统配置

    1 FreeRTOS的系统配置文件为FreeRTOSConfig h 在此配置文件中可以完成FreeRTOS的裁剪和配置 在官方的demo中 每个工程都有一个该文件 2 先说一下 INCLUDE 开始的宏 使用 INCLUDE 开头的宏用来
  • FreeRTOSConfig.h 配置优化及深入

    本篇目标 基于上一篇的移植freertos stm32f4 freertos 上 修改 FreeRTOSConfig h 文件的相关配置来优化辅助 FreeRtos 的使用 并且建立一些基本功能 信号量 消息地列等 的简单应用位于 stm3
  • 使用 GCC 编译器的 ARM 内核的堆栈回溯(当存在 MSP 到 PSP 切换时)

    核心 ARM Cortex M4 编译器 GCC 5 3 0 ARM EABI 操作系统 免费 RTOS 我正在使用 gcc 库函数 Unwind Reason Code Unwind Backtrace Unwind Trace Fn v
  • 当一个任务写入变量而其他任务读取该变量时,我们是否需要信号量?

    我正在研究 freeRtos 并且我有一个名为 x 的变量 现在 每秒只有一个任务正在写入该变量 而其他任务正在读取该变量值 我需要用互斥锁来保护变量吗 如果变量为 32 位或更小 并且其值是独立的并且不与任何其他变量一起解释 则不需要互斥
  • 如何将 void* 转换为函数指针?

    我在 FreeRTOS 中使用 xTaskCreate 其第四个参数 void const 是传递给新线程调用的函数的参数 void connect to foo void const task params void on connect
  • GNU Arm Cortex m4 上的 C++ 异常处理程序与 freertos

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

随机推荐

  • 【SBUS】一文看懂SBUS协议

    STM32 STM32单片机总目录 1 简介 S BUS是一个串行通信协议 xff0c S BUS是FUTABA提出的舵机控制总线 xff0c S bus使用RS232C串口的硬件协议作为自己的硬件运行基础 使用TTL电平 xff0c 即3
  • 【ubuntu】ubuntu14.04、16.04、18.04 LTS版本支持时间

    0 历史版本下载地址 http old releases ubuntu com releases http mirrors 163 com ubuntu releases 1 官网说明 https wiki ubuntu com Kerne
  • 树莓派,tx2硬件对比

    具体参考以下链接 http www exuehao com article detail 14
  • Gazebo中的平面运动 (urdf+控制器设置)及所遇见的问题

    这里有个视频 xff0c 介绍怎么让机器人在平面运动 xff08 在x和y方向上进行平移 xff09 xff1a https www youtube com watch v 61 mtSpqObg9X4 如果你们看不了视频也没关系 xff0
  • 2014年年终总结:写书成长,承载收获

    雪花纷飞 xff0c 任你飘落凝成魅力的雪域之城 美丽的守候 xff0c 望长城内外惟余莽莽 数着北国春夏秋冬的每一天 xff0c 2014 的日历天天换新装 xff0c 消瘦了你的时光 但丰盈了我的渴望 2014 年 xff0c 在你的身
  • 漫步数学分析三十五——乘法法则与梯度

    微分中另一个有名的法则是乘法法则或莱布尼兹法则 定 理 6 令 A R n 是开集 xff0c f A R m g A R 是可微函数 xff0c 那么 g f 是可微的并且对于 x A D g f x R n R m 为 D
  • CAN总线标准及协议分析

    目录 1 简介 2 CAN总线标准 2 1 物理层 2 1 1 CAN总线网络 2 1 2 CAN收发器 2 1 3 CAN信号表示 2 1 4 CAN信号传输 2 2 数据链路层 2 2 1 数据帧 2 2 1 1 帧起始与结束帧 2 2
  • Eclipse中Python开发环境搭建详细图文教程(Windows环境)

    转载请注明出处 Eclipse可便捷的集成开发Python xff0c 这里我们为了更好地使用Python进行机器学习 xff0c 首先进行Eclipse中Python开发环境的搭建 一 下载EclipseIDE 下载地址 xff1a ht
  • FreeRTOS系列|多任务调度

    多任务调度 1 多任务启动流程 多任务启动流程如下表所示 启动后以下各函数由上至下依次执行含义osKernelStart 启动内核vTaskStartScheduler 启动任务调度器xPortStartScheduler 启动调度器prv
  • Realsense d435i驱动安装、配置及校准

    写在前面 本文是在ubuntu20 04下安装 xff0c 其它版本大同小异 可能出现的问题 xff0c 主要由各自安装相关库版本不一致导致 xff0c 故问题不一 xff0c 但一般很好解决 xff0c 正常情况下不会出现 Intel R
  • Realsense d435i内参、外参标定

    使用工具code utils imu utils kalibr对Realsense d435i 内参 外参标定 本文介绍上述工具的安装 xff0c 及标定方法 一 code utils安装 1 建立工作空间 mkdir p calibrat
  • 从零完成slam实战,以Vins-Fusion为例

    写在前面 1 本文以vins fusion为例 xff0c 是因为其框架正统 简单清晰 xff0c 易于调试和后续改进 xff1b camera imu外参及同步时间td可实时估计 xff1b 已有融合gps方案且较为容易可添加融合其它传感
  • Vins-Fusion整体框架,数据流分析

    一 VINS Fusion VINS Fusion是一种基于优化的多传感器状态估计器 xff0c 可实现自主应用 xff08 无人机 汽车和AR VR xff09 的精确自我定位 VINS Fusion是VINS Mono的扩展 xff0c
  • Vins-Fusion初始化位姿——3D-2D:PNP求解当前帧位姿

    继上一篇博文Vins Fusion 外参camera imu 标定 xff0c 本文继续介绍Vins Fusion初始化时 xff0c 通过PNP求解当前帧位姿 一 3D 2D xff1a PNP PnP是求解3D到2D点对运动的估计 xf
  • ORB_SLAM3启动流程以stereo_inertial_realsense_D435i为例

    概述 ORB SLAM3 是第一个同时具备纯视觉 xff08 visual xff09 数据处理 视觉 43 惯性 xff08 visual inertial xff09 数据处理 和构建多地图 xff08 multi map xff09
  • BoW(词袋)模型详细介绍

    最近学习BoW模型 xff0c 将自己网上看到的资料及对论文的理解 xff0c 将BoW模型总结如下 xff01 BoW模型 Bag of words model BoW model 最早出现在自然语言处理 xff08 Natural La
  • Win10 VS Code + CMake STM32开发环境

    Win10 VS Code 43 CMake STM32开发环境 软件 软件安装与环境变量的配置不多讲 xff0c 这步都搞不定还是老老实实用MDK把 VS Codecmake 插件 c c 43 43 插件mingwgcc arm non
  • makefile 转 cmake STM32工程

    makefile 转 cmake STM32工程 STM32开发由MDK转到 vscode好久了 每次新建工程 xff0c stm32cubemx生成代码都要手动把makefile转到cmake xff0c 好烦 xff0c 特别一下小的频
  • STM32使用FreeRtos + C++

    编译环境 MDK5 25 gcc arm7 2 C文件不可包含CPP的头文件 C调用C 43 43 函数 在CPP文件内编写C函数 xff0c 头文件声明 头文件不可出现C 43 43 关键字 在main中调用此函数作为程序入口即可 voi
  • FreeRTOS系列|时间管理

    FreeRTOS时间管理 1 FreeRTOS延时函数 在使用FreeRTOS的过程中经常会在一个任务中使用延时函数对该任务延时 xff0c 当执行延时函数的时候就会进行任务切换 xff0c 并且此任务就会进入阻塞态 xff0c 直到延时完