FreeRTOS源码分析-4 SysTick系统时钟详解

这篇具有很好参考价值的文章主要介绍了FreeRTOS源码分析-4 SysTick系统时钟详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

1 SysTick初始化

2 SysTick中断服务函数

3 SysTick任务调度


1 SysTick初始化

初始化流程

  • 配置SysTick装载值
  • 使能SysTick时钟源 使能SysTick中断 使能SysTick

其中装载值1ms、10ms、100ms都可以,但是不要小于1ms

//main.c //--->
    osKernelStart(); //--->
        xPortStartScheduler(); //--->
            vPortSetupTimerInterrupt(); //--->

系统节拍初始化源码

在vPortSetupTimerInterrupt中

void vPortSetupTimerInterrupt( void )
{

	/*
        1、操作系统,时针对寄存器操作---效率搞
        2、首先赋值装载寄存器值 = (CPU频率/配置的周期)-1
            2.1 SystemClock_Config()
                       HAL_RCC_ClockConfig() CPU频率在硬件启动时就已经获取了
            2.2 configTICK_RATE_HZ = 1000 由cubemx配置而得
        3、配置控制寄存器
            3.1、开启时钟源
            3.2、使能中断
            3.3、使能systick
        4、可以参考M4权威指南 9.5章节---systick定时器
    */
	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 );
}

FreeRTOS源码分析-4 SysTick系统时钟详解,FreeRTOS源码分析,单片机,嵌入式硬件

2 SysTick中断服务函数

中断服务函数流程:

  • 关闭中断
  • Tick值增加SysTick任务调度
  • 启动PendSV
  • 开启中断

系统节拍中断服务函数

void xPortSysTickHandler( void )
{
	/* 1、配置中断屏蔽寄存器
       2、不让中断打断,SysTick中断服务
       3、其实就是进入临界段
     */
	vPortRaiseBASEPRI();
	{
		/* 
            操作系统调度接口
            如果调度器返回true,触发pendSV异常
         */
		if( xTaskIncrementTick() != pdFALSE )
		{
			/* A context switch is required.  Context switching is performed in
			the PendSV interrupt.  Pend the PendSV interrupt. */
			portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
		}
	}
    // 清楚可屏蔽中断,就是打开全部中断---》PendSV就执行
	vPortClearBASEPRIFromISR();
}

问:如何与操作系统内核联系起来?

3 SysTick任务调度

SysTick调度流程文章来源地址https://www.toymoban.com/news/detail-602759.html

  • 系统节拍数加1,判断是否溢出溢出更新任务锁定时间
  • 判断是否有任务需要解除阻塞,获取延时列表第一个任务控制块(时间排序),获取状态列表值判断时间是否到达,未到达退出
  • 任务阻塞事件到达,从延时列表中删除,从事件列表中删除,添加到就绪列表
  • 如果使用抢占内核,判断任务优先级是否大于当前任务,开启任务调度
  • 如果使用时间片调度,判断当前优先级下是否还有其他任务,开启任务调度器
//SysTick任务调度
BaseType_t xTaskIncrementTick( void )
{
    TCB_t * pxTCB;
    TickType_t xItemValue;
    // 返回值,表示是否进行上下文切换
    BaseType_t xSwitchRequired = pdFALSE;

	/* uxSchedulerSuspended  表示内核是否挂起,pdFalse 内核没有挂起*/
	if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
	{
		/* tick计数增加1 */
		const TickType_t xConstTickCount = xTickCount + 1;

		xTickCount = xConstTickCount;
        /* 判断tick是否溢出 */
		if( xConstTickCount == ( TickType_t ) 0U )
		{
            //如果溢出,更新延时列表
			taskSWITCH_DELAYED_LISTS();
		}
		else
		{
			mtCOVERAGE_TEST_MARKER();
		}

		/* 
            1、如果当前节拍大于时间片的锁定时间
            2、说明有任务需要进行调度了,时间片用完了
        */
		if( xConstTickCount >= xNextTaskUnblockTime )
		{
			for( ;; )//会一直遍历整个任务延时列表,主要目的是,找到时间片最短的任务,进行调度
			{
                //判断任务延时列表中,是否为空,也就是说,有没有任务在等待调度
				if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
				{
					//如果没有任务等待,把时间片赋值为最大值,不再调度
					xNextTaskUnblockTime = portMAX_DELAY; 
					break;
				} //延时列表不为空
				else
				{
					/* 
                        1、从任务延时列表中,获取第一个任务控制块
                            1.1 延时列表,插入永远是把时间片最短的任务,放在第一个
                        2、获取任务控制块的延时时间
                     */
					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 )
					{
						/* 
                            1、判断优先级是否大于当前优先级
                                1.1、大于则进行调度
                         */
						if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
						{
							xSwitchRequired = pdTRUE;
						}
						else
						{
							mtCOVERAGE_TEST_MARKER();
						}
					}
					#endif /* configUSE_PREEMPTION */
				}
			}
		}

		/* 时间片处理机制 */
		#if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) )
		{
            /*1、获取就绪列表的长度
                1.1就绪列表指的是,当前任务优先级的列表
                1.2如果其他任务在就绪列表中,就凯斯调度
			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;
}

到了这里,关于FreeRTOS源码分析-4 SysTick系统时钟详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • FreeRTOS源码分析-7 消息队列

    目录 1 消息队列的概念和作用 2 应用 2.1功能需求 2.2接口函数API 2.3 功能实现 3 消息队列源码分析 3.1消息队列控制块 3.2消息队列创建 3.3消息队列删除 3.4消息队列在任务中发送 3.5消息队列在中断中发送 3.6消息队列在任务中接收 3.7消息队列在中断中接收  消息队列(queue),可

    2024年02月14日
    浏览(39)
  • FreeRTOS源码分析-12 低功耗管理

    目录 1 STM32低功耗管理概念及应用 1.1睡眠模式       1.2 停止模式 1.3 待机模式       2 Tickless低功耗管理 2.1 Tickless低功耗模式介绍 2.2 FreeRTOS低功耗模式配置 2.3 FreeRTOS低功耗模式应用  3 低功耗管理实际项目开发 3.1 低功耗设计必须要掌握的硬件知识 3.2 开发板电路低功耗分析

    2024年02月13日
    浏览(40)
  • FreeRTOS源码分析-9 互斥信号量

    目录 1 优先级翻转问题 2 互斥信号量概念及其应用 2.2FreeRTOS互斥信号量介绍 2.3FreeRTOS互斥信号量工作原理 3 互斥信号量函数应用 3.1功能分析 3.2API详解 3.3功能实现 4 递归互斥信号量函数应用 4.1死锁现象 ​编辑 4.2API详解 4.3解决死锁 5 互斥信号量实现原理 5.1互斥信号量创建

    2024年02月14日
    浏览(42)
  • FreeRTOS源码分析-10 互斥信号量

    目录   1 事件标志组概念及其应用 1.1 事件标志组定义 1.2 FreeRTOS事件标志组介绍 1.3 FreeRTOS事件标志组工作原理 2 事件标志组应用 2.1 功能需求 2.2 API  2.3 功能实现 3 事件标志组原理 3.1 事件标志组控制块 3.2 事件标志组获取标志位 3.3 等待事件标志触发 3.4 事件标志组设置标志

    2024年02月14日
    浏览(43)
  • 测试、获取单片机STM32系统时钟值方法

          有时候,做一个项目出了问题,第一个要怀疑的是系统时钟,本篇是说明如何监控项目的系统 频率的。      在STM32标准库项目中,可以通过以下步骤来获取系统时钟: 打开项目的主文件(通常为main.c或stm32fxxx_it.c)。 在文件顶部,找到包含STM32的头文件,例如\\\"stm32

    2024年02月20日
    浏览(43)
  • 51单片机的数字时钟系统【含仿真+程序+报告+原理图】

    该系统由AT89C51单片机+DS1302时钟模块+按键模块+LCD显示模块构成。 利用51单片机实现电子时钟的功能。使用DS1302芯片作为计时设备,用LCD1602作为显示设备,按键按下可修改当前时间,按下的时候蜂鸣器会di一声。 可实现基本功能: 1、实时显示当前时间和日期 按键功能: 1、点

    2024年02月06日
    浏览(57)
  • RTC实时时钟源码分析

    1.先来看一下RTC的配置过程  2.RTC源码讲解 我们的工程中加入了 rtc.c 源文件和 rtc.h头文件,同时,引入了 stm32f10x_rtc.c 和 stm32f10x_bkp.c 库文件。 说明,首先是 RTC_Init,其代码如下: 该函数用来初始化 RTC 时钟,但是只在第一次的时候设置时间,以后如果重新上电/复位都不会再

    2024年02月05日
    浏览(52)
  • 毕业设计 基于STM32与wifi的天气预报网时钟系统 - 物联网 单片机

    文章目录 0 前言 1 设计内容 2 软件设计 3 关键代码 4 最后 🔥 这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往往达不到毕业答辩的要求,这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师的要求。 为了大家能够顺利以及

    2024年02月06日
    浏览(83)
  • 97、基于stm32单片机智能药箱药盒温湿度体温光照时钟wifi手机APP监控(程序+原理图+PCB源文件+手机APP源码+硬件设计资料+元器件清单等)

    单片机类型选择 方案一:可以使用现在比较主流的单片机STC89C5单片机进行数据处理。这款单片机具有的特点是内存和51的单片机相比多了4KB内存,但是价格和51单片机一样。并且支持数据串行下载和调试助手。此款单片机是有ATMEL公司生产,可用5V电压编程,而且擦写时间仅需

    2024年02月13日
    浏览(52)
  • CesiumJS 源码杂谈 - 时间与时钟系统

    目录 1. 时间的“诞生” 2. 时间的推进 3. Entity API 与 Property API 的更新动力源 4. 简单应用 4.1. 使用原生 JS Date 对象创建 JulianDate 4.2. 使用时间字符串(ISO8601标准的时间字符串或 UTC 时间字符串)创建 JulianDate 4.3. 为时钟设置起止时间和速率 4.4. 调整时钟的循环情况 你知道吗?

    2024年02月08日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包