FreeRTOS时间片调度

article/2025/9/12 14:41:14

一、FreeRTOS时间片调度概述

FreeRTOS支持多个任务同时拥有一个优先级,这些任务的调度就可以使用时间片来进行调度。在FreeRTOS中允许一个任务允许一个时间片(一个时钟节拍的长度)后让出CPU的使用权,让拥有同优先级的下个任务运行。下图展示了运行在同一优先级的执行时间图。其中的task1、task2、task3是同一优先级N就绪的任务
在这里插入图片描述

  • 1、任务3正在运行。
  • 2、这时一个时钟节拍中断(滴答定时器中断)发生,任务3的时间片用完,但是任务3还没有执行完。
  • 3、FreeRTOS将任务切换到任务1,任务1是优先级N下的下一个就绪任务。
  • 4、任务1连续运行至时间片用完。
  • 5、任务3再次获取到CPU使用权,接着运行。
  • 6、任务3运行完成,调用任务切换函数portYIELD()强行进行任务切换放弃剩余的时间片,从而使优先级N下的下一个就绪的任务运行。
  • 7、FreeRTOS切换到任务1。
  • 8、任务1执行完其时间片。

二、开启时间片调度

要使用时间片调度的话宏configUSE_PREEMPTION和宏configUSE_TIME_SLICING必须为1。时间片的长度由宏configTICK_RATE_HZ来确定,一个时间片的长度就是滴答定时器的
中断周期,比如configTICK_RATE_HZ为1000,那么一个时间片的长度就是1ms。时间片调度发生在滴答定时器的中断服务函数中,前面讲解滴答定时器中断服务函数的时候说了在中断服务函数SysTick_Handler()中会调用FreeRTOS的API函数xPortSysTickHandler(),而函数xPortSysTickHandler()会引发任务调度,但是这个任务调度是有条件的,函数xPortSysTickHandler()如下:

void xPortSysTickHandler( void )
{vPortRaiseBASEPRI();{/* Increment the RTOS tick. */if( xTaskIncrementTick() != pdFALSE ){portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;}}vPortClearBASEPRIFromISR();
}

上述代码中只有函数xTaskIncrementTick()的返回值不为pdFALSE的时候就会进行任务调度!其中xTaskIncrementTick()函数代码如下:

BaseType_t xTaskIncrementTick( void )
{
TCB_t * pxTCB;
TickType_t xItemValue;
BaseType_t xSwitchRequired = pdFALSE;traceTASK_INCREMENT_TICK( xTickCount );if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE ){#if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) )                                                      (1){if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB->uxPriority ] ) ) > ( UBaseType_t ) 1 )           (2){xSwitchRequired = pdTRUE;                      (3)}else{mtCOVERAGE_TEST_MARKER();}}#endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) */#if ( configUSE_TICK_HOOK == 1 ){if( uxPendedTicks == ( UBaseType_t ) 0U ){vApplicationTickHook();}else{mtCOVERAGE_TEST_MARKER();}}#endif /* configUSE_TICK_HOOK */}else{++uxPendedTicks;/* The tick hook gets called at regular intervals, even if thescheduler is locked. */#if ( configUSE_TICK_HOOK == 1 ){vApplicationTickHook();}#endif}#if ( configUSE_PREEMPTION == 1 ){if( xYieldPending != pdFALSE ){xSwitchRequired = pdTRUE;}else{mtCOVERAGE_TEST_MARKER();}}#endif /* configUSE_PREEMPTION */return xSwitchRequired;
}
  • (1)、当宏configUSE_PREEMPTION和宏configUSE_PREEMPTION都为1的时候下面的代码才会编译。所以要想使用时间片调度的话这这两个宏都必须为1,缺一不可!
  • (2)、判断当前任务所对应的优先级下是否还有其他的任务。
  • (3)、如果当前任务所对应的任务优先级下还有其他的任务那么就返回pdTRUE。从上面的代码可以看出,如果当前任务所对应的优先级下有其他的任务存在,那么函数xTaskIncrementTick0就会返回pdTURE,由于函数返回值为pdTURE,因此函数xPortSysTickHandler()就会进行一次任务切换。
    三、实验程序展示
int main(void)
{ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4delay_init(168);		//初始化延时函数uart_init(115200);     	//初始化串口LED_Init();		        //初始化LED端口LCD_Init();POINT_COLOR = RED;LCD_ShowString(30,10,200,16,16,"LIU YI NIU BI");LCD_ShowString(30,40,200,16,16,"2021/10/18");//创建开始任务xTaskCreate((TaskFunction_t )start_task,            //任务函数(const char*    )"start_task",          //任务名称(uint16_t       )START_STK_SIZE,        //任务堆栈大小(void*          )NULL,                  //传递给任务函数的参数(UBaseType_t    )START_TASK_PRIO,       //任务优先级(TaskHandle_t*  )&StartTask_Handler);   //任务句柄              vTaskStartScheduler();          //开启任务调度
}
//开始任务任务函数
void start_task(void *pvParameters)
{taskENTER_CRITICAL();           //进入临界区//创建task1任务xTaskCreate((TaskFunction_t )task1_task,     	(const char*    )"task1_task",   	(uint16_t       )TASK1_STK_SIZE, (void*          )NULL,				(UBaseType_t    )TASK1_TASK_PRIO,	(TaskHandle_t*  )&TASK1Task_Handler);   //创建LED1任务xTaskCreate((TaskFunction_t )task2_task,     (const char*    )"task2_task",   (uint16_t       )TASK2_STK_SIZE, (void*          )NULL,(UBaseType_t    )TASK2_TASK_PRIO,(TaskHandle_t*  )&TASK2Task_Handler);        vTaskDelete(StartTask_Handler); //删除开始任务taskEXIT_CRITICAL();            //退出临界区
}
//TASK1任务函数
void task1_task(void *pvParameters){u8 task1_num=0;while(1){task1_num++;LED0=!LED0;taskENTER_CRITICAL();//进入临界区printf("任务1已经执行:%d次\r\n",task1_num);taskEXIT_CRITICAL();//退出临界区
//		delay_xms(10);}
}
//TASK2任务函数
void task2_task(void *pvParameters){u8 task2_num=0;while(1){task2_num++;LED1=!LED1;taskENTER_CRITICAL();//进入临界区printf("任务2已经执行:%d次\r\n",task2_num);taskEXIT_CRITICAL();//退出临界区
//		delay_xms(10);}
}

通过串口调试助手可以看到打印的信息,就知道执行的过程。在这里插入图片描述
不管是task1_task还是task2_task都是连续执行4、5次,和前面程序设计的一样,说明在一个时间片内一直在运行一个任务,当时间片用完后就切换到下一个任务运行。


http://chatgpt.dhexx.cn/article/yNvGC1RY.shtml

相关文章

MongoDB 分片集群技术

在了解分片集群之前,务必要先了解复制集技术! 1.1 MongoDB复制集简介 一组Mongodb复制集,就是一组mongod进程,这些进程维护同一个数据集合。复制集提供了数据冗余和高等级的可靠性,这是生产部署的基础。 1.1.1 复制集的…

片偏移怎么计算_计算机网络学习笔记(四)之网络层

点击蓝字关注我吧 越努力越幸运!!! 1 网络层的功能 1.1异构网络互联 网络的互联:指将两个以上的计算机网络,通过一定的方法, 用一种或多种通信处理设备(即中间设备)相互联接起来,以构成更大的网络系统。中间设备又称为中间系统或中继系统。根据中继系统所在…

IP分片浅析

一、IP分片原理 IP分片是网络上传输IP报文的一种技术手段。 IP协议在传输数据包时,将数据报文分为若干分片进行传输,并在目标系统中进行重组。 不同的链路类型规定有不同最大长度的链路层数据帧,称为链路层MTU(最大传输单元&#…

硅钢片知识点

文章目录 一、电工钢为什么选硅钢二、为什么要用硅钢“片”三、为什么电机用无取向,变压器用有取向硅钢片四、其他关于硅钢片应该了解的4.1 热轧和冷轧4.2 厚度4.3 牌号4.4 叠片系数4.5 冲片性 一、电工钢为什么选硅钢 电机和变压器的内部主要组成是铜绕组&#xf…

wireshark捕获IP分片数据包实践

一 简介 如果一个数据包超过1500个字节,就需要将该包进行分片发送。通常情况下,是不会出现这种情况的。 下面通过使用ICMP包,来产生IP分片数据包。 使用ICMP包进行测试时,如果不指定包的大小,可能无法查看被分片的数据…

mongo分片

分片 在Mongodb里面存在另一种集群,就是分片技术,可以满足MongoDB数据量大量增长的需求。 当MongoDB存储海量的数据时,一台机器可能不足以存储数据,也可能不足以提供可接受的读写吞吐量。这时,我们就可以通过在多台机器上分割数据…

IP分片报文的接收与重组

对于长度超过接口MTU的数据包,需要进行分片处理,IP报头中与分片相关的字段有如下几个: Identification - 用来确认不同的分片是否属于同一个IP报文; Flags - 其中IP_MF表示还有分片,此分片为…

数据 分片

背景 传统的将数据集中存储至单一节点的解决方案,在性能、可用性和运维成本这三方面已经难于满足海量数据的场景。 从性能方面来说,由于关系型数据库大多采用 B 树类型的索引,在数据量超过阈值的情况下,索引深度的增加也将使得磁…

MongoDB:海量存储基础-分片架构

文章目录 1.分片架构2.分片策略3.读写策略4.数据迁移 1.分片架构 分片是数据库中常用的提升存储容量的方式,它基于水平拓展的思想,将大量的数据按一定规则分配到不同的服务器中存储,比如MySQL集群可以借助Sharding-JDBC等外部框架对数据进行…

SpringBoot文件分片上传

背景 最近好几个项目在运行过程中客户都提出文件上传大小的限制能否设置的大一些,用户经常需要上传好几个G的资料文件,如图纸,视频等,并且需要在上传大文件过程中进行优化实时展现进度条,进行技术评估后针对框架文件上…

芯片的设计流程和流片成本

每天都在用,但你知道芯片的设计流程和流片成本吗? 2017-05-10 06:10 来源:半导行业观察 芯片,是无数设计工程师们烧死很多脑细胞后产生的作品,完全可以称得上是当代的艺术品。无论是电工们,还是科技小白…

华为防火墙分片缓存

分片缓存 分片缓存功能用来缓存先于首片分片报文到达的后续分片报文,避免分片报文被防火墙丢弃。 网络设备在传输报文时,如果设备上配置的MTU(Maximum Transfer Unit)小于报文长度,则会将报文分片后继续发送。 我们知道…

二三层报头及IP分片详解

一、报文数据格式 二、二层数据格式 二层以太帧格式 DMAC(6字节)SMAC(6字节)type(2字节)DATA(46-1500字节)CRC(4字节) 字段长度含义DMAC6字节目的MAC地址&am…

哈希分片总结

主要参考: 《大数据日知录》 https://zhuanlan.zhihu.com/p/34985026 什么是哈希分片 后台随着数据规约的越来越大,单机明显无法存储着庞大的数据量,只能依靠大规模集群在对数据进行存储和处理,所以系统的可扩展性也成为了很重要…

MongoDB 分片

分片 sharding 分片是指将数据拆分,将起分散到不同服务器的过程.,将数据分散到不同的服务器上,可以存储更多的数据,处理更大的负载 MongoDB分片机制允许你创建一个包含许多服务器(分片)的集群,将子数据分散在集群中.每个分片维护着一个数据集合的子集,相比单服务器和副本集&…

LaTeX制作幻灯片

LaTeX \LaTeX LATE​X幻灯片制作采用的是beamer类。beamer类默认使用sans serif family,和article不同,article默认是roman font family。所以如果我要实现幻灯片的标题和正文字体的设置可以通过下面的命令: \setsansfont{TeX Gyre Termes} …

MySQL的分片

前言 从开发人员的角度来说,为什么要了解和掌握MySQL分片? 第一,了解MySQL分片可以更合理地定制分片策略,选分片字段是要讲科学的。 第二,了解MySQL分片以后如果出现故障报错,也有助于问题的排查。 第三…

外汇天眼:新手如何模拟炒外汇?模拟炒外汇的一点心得分享

模拟炒外汇通常是在没有进行外汇交易之前利用外汇交易软件的模拟账户进行无风险的外汇交易。是刚入门的投资者为熟悉外汇交易软件和外汇市场而经常使用的方法。 新手如何模拟炒外汇? 外汇市场的火热让不少投资者纷纷加入,很多高手也都是从新手走过来的…

外汇套利原理及策略EA

外汇套利,通俗解释就是当相同货币对或相关货币对之间的价差偏离正常范围时进行买卖,当价差回归正常范围时获利平仓的一种交易策略。 外汇套利分为三类 单品种的跨平台套利两相关品种的对冲套利三相关品种的三角套利 如何开发三角套利策略 “三角” 是…

外汇平台怎么选择?玩外汇又有那些优势呢?

外汇平台怎么选择?玩外汇又有那些优势呢? 怎么选择好的外汇平台呢? 第一个 是优先选择大炒外汇的交易平台,虽然也不排除一些小平台是优质的,不过对于新手投资者来说在判断上是很难下决断的。选大平台的主要原因是可以搜索相关的口碑&…