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

news2024/11/27 21:57:31

目录

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 );
}

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调度流程

  • 系统节拍数加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;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/780089.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vue开源基础框架之岗位管理配置及使用

JVS是面向软件开发团队可以快速实现应用的基础开发脚手架&#xff0c;主要定位于企业信息化通用底座&#xff0c;采用微服务分布式框架&#xff0c;提供丰富的基础功能&#xff0c;集成众多业务引擎&#xff0c;它灵活性强&#xff0c;界面化配置对开发者友好&#xff0c;底层容…

机器视觉:工业自动化和智能化的核心技术

机器视觉作为实现工业自动化和智能化的关键核心技术&#xff0c;是人工智能领域发展最迅速的分支之一。它包括四个关键构件&#xff1a;光源、摄像机、图像采集卡和视觉处理软件&#xff08;集成了AI算法&#xff09;。其中&#xff0c;图像采集卡是工厂自动化中常用的外购组件…

Java多线程基础复习

文章目录 多线程1.进程进程属性并发和并行虚拟地址空间 2.线程概念线程的创建方式 3.Thread类常见构造方法和属性线程的状态优先级后台线程线程是否存活start和run 4. 线程的一些基本操作线程中断(interrupted)线程等待joincurrentThread&#xff08;获取当前线程引用&#xff…

安全开发-JS应用原生开发JQuery库Ajax技术加密编码库断点调试逆向分析元素属性操作

文章目录 JS原生开发-文件上传-变量&对象&函数&事件JS导入库开发-登录验证-JQuery库&Ajax技术JS导入库开发-编码加密-逆向调试 JS原生开发-文件上传-变量&对象&函数&事件 1、布置前端页面 2、JS获取提交数据 3、JS对上传格式判断 <script>…

Spring MVC 详解(2)

目录 3. 返回数据的功能 3.1 返回静态页面 3.2 请求转发 VS 请求重定向 前言 上一篇文章已经介绍了 Spring MVC 框架的两个功能&#xff0c;和前端建立连接的功能和从前端获取参数的功能&#xff0c;还有最后一个功能就是 输出数据的功能。 3. 返回数据的功能 返回的数据大致…

2min搞定 mac pycharm新建导入python项目

mac pycharm新建和导入python项目&虚拟环境配置&下载类库 一、通用设置step1 、通过自定义配置&#xff0c;指定默认虚拟环境变量step2、设置虚拟环境和指定默认工作空间step3 、导入或者新建python项目 二、pycharm新建python项目step1、点击新建【file->newProjec…

appscan 应用

HCL appscan是个常见的web app DAST 扫描工具 有企业版和standalone 版本。大家常用的都是单机版本。企业版平台&#xff0c;集成了IAST。 appscan 使用比较简单&#xff0c;基本输入url 账号密码就开扫了。 用了一段时间几点体验 1 还是需要手动explore的&#xff0c;他自…

ShardingSphere分库分表实战之读写分离原理解析

&#x1f680; ShardingSphere &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&…

MFC第十九天 记事本项目功能完善和开发、CTabCtrl类与分页模式开发

文章目录 记事本项目功能完善和开发查找界面的记忆功能 、使用F3快捷键自动向下查找功能 的开发单次替换的算法研究 CFileDialog 构造函数详解 应用另存为时选择编码 &#xff08;三种方案&#xff09;vista 样式文件对话框 bVistaStyle 为TRUE时 1pch.hCApp NotePad.cpp 对编码…

《Docker与持续集成/持续部署:构建高效交付流程,打造敏捷软件交付链》

&#x1f337;&#x1f341; 博主 libin9iOak带您 Go to New World.✨&#x1f341; &#x1f984; 个人主页——libin9iOak的博客&#x1f390; &#x1f433; 《面试题大全》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33…

【算法基础:搜索与图论】3.5 求最小生成树算法(PrimKruskal)

文章目录 最小生成树介绍朴素Prim算法算法思路⭐例题&#xff1a;858. Prim算法求最小生成树 Kruskal算法算法思路⭐例题&#xff1a;859. Kruskal算法求最小生成树 最小生成树介绍 最小生成树 有关树的定义 生成子图&#xff1a;生成子图是从原图中选取部分节点以及这些节点…

16.喝水

喝水 html部分 <h1>Goal: 2 Liters</h1> <div class"cup cupbig"><div class"remained"><span id"liters">2L</span><small>Remained</small></div><div class"percentage&quo…

欧姆龙cp1h-e串口以太网连接怎么设置欧姆龙CX系列

捷米特JM-ETH-CX串口转以太网通讯处理器是为满足日益增多的工厂设备信息化需求&#xff08;设备网络监控和生产管理&#xff09;而设计&#xff0c;用于欧姆龙 CPM、CQM、C200、C1000、C2000 等多个系列 PLC 的以太网数据采集&#xff0c; 非常方便构建生产管理系统。 捷米特J…

【字符流】案例:文件到集合(改进版)

案例&#xff1a;文件到集合&#xff08;改进版&#xff09; 1.需求&#xff1a; 把文本文件中的数据读取到集合中&#xff0c;并遍历集合。要求&#xff1a;文件中每一行数据是一个学生对象的成员变量值 ​ 举例&#xff1a;001,郝佳乐,20,西安 2.思路&#xff1a; 定义学…

Vue第六篇:电商网站图片放大镜功能

本文参考&#xff1a;https://blog.csdn.net/liushi21/article/details/127497487 效果如下&#xff1a; 功能实现分解如下&#xff1a; &#xff08;1&#xff09;商品图区域&#xff1a;主要是浏览图片&#xff0c;根据图片的url显示图片。当鼠标离开此区域时"放大镜区…

HTTP中GET请求和POST请求的区别

前言 HTTP&#xff08;超文本传输协议&#xff09;是用于在 Web 浏览器和 Web 服务器之间传输数据的协议。在 HTTP 中&#xff0c;GET 和 POST 是两种常见的请求方法。一般我们在浏览器输入一个网址访问网站都是 GET 请求&#xff1b;在 FORM 表单中&#xff0c;可以通过设置 …

Mac端简单好用的程序创建工具:VMware InstallBuilder Enterprise

VMware InstallBuilder Enterprise for Mac是一款用于为台式机和服务器软件构建跨平台安装程序的开发工具。使用InstallBuilder&#xff0c;您可以从单个项目文件和构建环境中为Linux&#xff0c;Windows&#xff0c;Mac OS X&#xff0c;Solaris和其他平台快速创建动态&#x…

Windows下mosquitto服务端和MQTT.fx客户端搭建模拟环境

第一部分 Mosquitto安装测试 一、概念梳理 1、Mosquitto是一款实现了消息推送协议MQTT 3.1的开源消息代理软件&#xff0c;提供轻量级的、支持可订阅/可发布的消息推送模式&#xff0c;是设备与设备之间的短消息通信变得简单&#xff0c;广泛应用于低功耗传感器、手机&#xff…

django跨域设置

1.安装 (venv) ***\data_analyse_web>pip install django-cors-headers 2.添加应用 :在settings.py中添加应用,放到任意位置都行 INSTALLED_APPS {# ...corsheaders,# ... } 3. 设置中间层&#xff0c;在settings.py中添加中间层&#xff0c;放到最前面 MIDDLEWARE [c…

【设计模式】23种设计模式——原型模式Prototype(原理讲解+应用场景介绍+案例介绍+Java代码实现)

原型模式 介绍 原型模式指用通过拷贝原型实例创建新的实例&#xff0c;新实例和原型实例的属性完全一致原型模式是一种创建型设计模式工作原理是通过调用原型实例的 clone()方法来完成克隆&#xff0c;原型实例需要实现Cloneable接口&#xff0c;并重写clone()方法需要为每个…