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系列|时间管理 的相关文章

  • FreeRTOS内核配置说明---FreeRTOS Kernel V10.2.1

    FreeRTOS内核是高度可定制的 使用配置文件FreeRTOSConfig h进行定制 每个FreeRTOS应用都必须包含这个头文件 用户根据实际应用来裁剪定制FreeRTOS内核 这个配置文件是针对用户程序的 而非内核 因此配置文件一般
  • FreeRTOS学习(八) 延时函数

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

    本文主要介绍如何在任务或中断中向队列发送消息或者从队列中接收消息 使用STM32CubeMX将FreeRTOS移植到工程中 创建两个任务以及两个消息队列 并开启两个中断 两个任务 Keyscan Task 读取按键的键值 并将键值发送到队列
  • Freertos中vTaskDelay()是怎么用的

    1 常见的使用场景 void vLED Task void pvParameters while 1 Heartbeat LED vTaskDelay 1000 portTICK RATE MS 说明 上面这段代码的意思是 led翻转后经过
  • freertos---软定时器

    一 软件定时器介绍 freeRTOS软件定时器的时基是基于系统时钟节拍实现的 可以创建很多个 在硬件定时器资源不充足的情况下非常有用 软件定时器一般用作周期性地执行函数 在创建软件定时器时指定软件定时器的回调函数 在回调函数中实现相应的功能
  • FreeRTOS系列

    1 RTOS简介 RTOS全称为 Real Time Operation System 即实时操作系统 RTOS强调的是实时性 又分为硬实时和软实时 硬实时要求在规定的时间内必须完成操作 不允许超时 而软实时里对处理过程超时的要求则没有很严
  • ZYNQ中FreeRTOS中使用定时器

    使用普通的Timer中断方式时 Timer中断可以正常运行 但是UDP通信进程无法启动 其中TimerIntrHandler是中断服务程序 打印程序运行时间与从BRAM中读取的数据 void SetupInterruptSystem XSc
  • FreeRTOS打印任务对CPU的占有率

    1 配置RTOS 1 打开RTOS Config Parameter 找到Run Time And Task States gathering related definitions 使能GENERATE RUN TIME STATS US
  • FreeRTOS临界区

    FreeRTOS临界区是指那些必须完整运行 不能被打断的代码段 比如有的外设的初始化需要严格的时序 初始化过程中不能被打断 FreeRTOS 在进入临界区代码的时候需要关闭中断 当处理完临界区代码以后再打开中断 FreeRTOS 系统本身就
  • freeRTOS使用uxTaskGetStackHighWaterMark函数查看任务堆栈空间的使用情况

    摘要 每个任务都有自己的堆栈 堆栈的总大小在创建任务的时候就确定了 此函数用于检查任务从创建好到现在的历史剩余最小值 这个值越小说明任务堆栈溢出的可能性就越大 FreeRTOS 把这个历史剩余最小值叫做 高水位线 此函数相对来说会多耗费一点
  • FreeRTOS_中断

    传送门 博客汇总帖 传送门 Cortex M3 中断 异常 传送门 Cortex M3笔记 基础 笔记内容参考 正点原子的FreeRTOS开发手册 cortex m3权威指南 Cortex M3和Cortex M4权威指南等 文中stm32
  • FreeRTOS:中断配置

    目录 一 Cortex M 中断 1 1中断简介 1 2中断管理简介 1 3优先级分组定义 1 4优先级设置 1 5用于中断屏蔽的特殊寄存器 1 5 1PRIMASK 和 FAULTMASK 寄存器 1 5 2BASEPRI 寄存器 二 F
  • 基于HAL库的FREERTOS-----------三.队列

    一 队列简介 在实际的应用中 常常会遇到一个任务或者中断服务需要和另外一个任务进行 沟通交流 这个 沟通交流 的过程其实就是消息传递的过程 在没有操作系统的时候两个应用程序进行消息传递一般使用全局变量的方式 但是如果在使用操作系统的应用中用
  • FreeRTOS,串口中断接收中使用xQueueOverwriteFromISR()函数,程序卡死在configASSERT

    原因 UART的中断优先级设置的太高 高于了configMAX SYSCALL INTERRUPT PRIORITY宏定义的安全中断等级 UART的中断等级小于等于宏定义的优先等级即可
  • FreeRTOS笔记(一)简介

    这个笔记主要依据韦东山freertos快速入门系列记录 感谢韦东山老师的总结 什么是实时操作系统 操作系统是一个控制程序 负责协调分配计算资源和内存资源给不同的应用程序使用 并防止系统出现故障 操作系统通过一个调度算法和内存管理算法尽可能把
  • FreeRTOS学习笔记(8)---- 软件定时器

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

    定时器的使用步骤 1 定义一个handle xTimerCreate创建 2 启动定时器 在Task1中调用 通过队列通知守护任务来执行定时器任务 要再config头文件中定义守护任务相关配置 虽然定时器是在task1中启动 但是定时器的任
  • 单片机通信数据延迟问题排查

    1 问题说明 笔者在最近的项目中 发现系统的响应延迟较高 经过排查 排除了单片机运行卡死的问题 2 原因分析 具体排查过程这里就不细致说明了 直接给出排查后原因 任务执行周期规划不合理 导致freertos队列发送接收到的命令有延迟 为了便
  • FreeRTOS 配置TICK_RATE_HZ

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

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

随机推荐

  • 【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 直到延时完