(学习日记)2024.03.05:UCOSIII第七节:SysTick+任务时间片

news2024/12/24 11:34:59

写在前面:
由于时间的不足与学习的碎片化,写博客变得有些奢侈。
但是对于记录学习(忘了以后能快速复习)的渴望一天天变得强烈。
既然如此
不如以天为单位,以时间为顺序,仅仅将博客当做一个知识学习的目录,记录笔者认为最通俗、最有帮助的资料,并尽量总结几句话指明本质,以便于日后搜索起来更加容易。


标题的结构如下:“类型”:“知识点”——“简短的解释”
部分内容由于保密协议无法上传。


点击此处进入学习日记的总目录

2024.03.05

  • 十六、UCOSIII:介绍SysTick
    • 1、SysTick简介
    • 2、初始化SysTick
    • 3、SysTick中断服务函数
  • 十七、UCOSIII:任务时间片运行
    • 1、对main()函数修改
    • 2、关闭中断函数CPU_IntDis()
    • 3、仿真测试

十六、UCOSIII:介绍SysTick

1、SysTick简介

RTOS需要一个时基来驱动,系统任务调度的频率等于该时基的频率。
通常该时基由一个定时器来提供,也可以从其他周期性的信号源获得。 刚好Cortex-M内核中有一个系统定时器SysTick,它内嵌在NVIC中,是一个24位的递减的计数器,计数器每计数一次的时间为1/SYSCLK。
当重装载数值寄存器的值递减到0的时候,系统定时器就产生一次中断,以此循环往复。

因为SysTick是嵌套在内核中的, 所以使得OS在Cortex-M器件中编写的定时器代码不必修改,使移植工作一下子变得简单很多。
所以SysTick是最适合给操作系统提供时基, 用于维护系统心跳的定时器。

SysTick寄存器汇总如下:

寄存器名称寄存器描述
CTRLSysTick控制及状态寄存器
LOADSysTick重装载数值寄存器
VALSysTick当前数值寄存器

SysTick控制及状态寄存器如下:

位段名称类型复位值描述
16COUNTFLAGR/W0如果在上次读取本寄存器后, SysTick 已经计到了 0,则该位为 1。
2CLKSOURCER/W0时钟源选择位,0=AHB/8,1=处理器时钟AHB
1TICKINTR/W01=SysTick倒数计数到 0时产生 SysTick异常请求,0=数到 0 时无动作。也可以通过读取COUNTFLAG标志位来确定计数器是否递减到0
0ENABLER/W0SysTick 定时器的启用位

SysTick 重装载数值寄存器如下:

位段名称类型复位值描述
23:0RELOADR/W0当倒数计数至零时,将被重装载的值

SysTick当前数值寄存器如下:

位段名称类型复位值描述
23:0CURRENTR/W0读取时返回当前倒计数的值,写它则使之清零,同时还会清除在SysTick控制及状态寄存器中的COUNTFLAG 标志

2、初始化SysTick

使用SysTick非常简单,只需一个初始化函数搞定,OS_CPU_SysTickInit函数在os_cpu_c.c中定义

我使用的是野火的教材,SysTick初始化函数野火没有使用μC/OS-III官方的,野火是自己另外编写了一个。
区别是uC/OS-III官方的OS_CPU_SysTickInit函数里面涉及 SysTick寄存器都是重新在cpu.h中定义,
而野火自己编写的则是使用ARMCM3.h(记得在os_cpu_c.c的开头包含ARMCM3.h这个头文件) 这个固件库文件里面定义的寄存器,仅此区别而已。

#include "ARMCM3.h"


#if 0 /* 不用μC/OS-III自带的 */
void  OS_CPU_SysTickInit (CPU_INT32U  cnts)
{
    CPU_INT32U  prio;

    /* 填写 SysTick 的重载计数值 */
    CPU_REG_NVIC_ST_RELOAD = cnts - 1u;

    /* 设置 SysTick 中断优先级 */
    prio  = CPU_REG_NVIC_SHPRI3;
    prio &= DEF_BIT_FIELD(24, 0);
    prio |= DEF_BIT_MASK(OS_CPU_CFG_SYSTICK_PRIO, 24);

    CPU_REG_NVIC_SHPRI3 = prio;

    /* 启用 SysTick 的时钟源和启动计数器 */
    CPU_REG_NVIC_ST_CTRL |= CPU_REG_NVIC_ST_CTRL_CLKSOURCE |
                            CPU_REG_NVIC_ST_CTRL_ENABLE;
    /* 启用 SysTick 的定时中断 */
    CPU_REG_NVIC_ST_CTRL |= CPU_REG_NVIC_ST_CTRL_TICKINT;
}

#else /* 直接使用头文件ARMCM3.h里面现有的寄存器定义和函数来实现 */
void  OS_CPU_SysTickInit (CPU_INT32U  ms)
{
    /* 设置重装载寄存器的值 */
    SysTick->LOAD  = ms * SystemCoreClock / 1000 - 1;

    /* 配置中断优先级为最低 */
    NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);

    /* 复位当前计数器的值 */
    SysTick->VAL   = 0;

    /* 选择时钟源、启用中断、启用计数器 */
    SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |
                    SysTick_CTRL_TICKINT_Msk   |
                    SysTick_CTRL_ENABLE_Msk;
}
#endif
  • SysTick->LOAD = ms * SystemCoreClock / 1000 - 1;
    配置重装载寄存器的值,我们配合函数形参ms来配置,如果需要配置为10ms产生一次中断,形参设置为10即可。

  • NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);
    配置SysTick的优先级,这里配置为15,即最低。

3、SysTick中断服务函数

SysTick中断服务函数也是在os_cpu_c.c中定义

/* SysTick 中断服务函数 */
void SysTick_Handler(void)
{
    OSTimeTick();
}

SysTick中断服务函数很简单,里面仅调用了函数OSTimeTick()。
OSTimeTick()是与时间相关的函数, 在os_time.c文件中定义。

#include "os.h"

void  OSTimeTick (void)
{
	/* 任务调度 */
	OSSched();
}

OSTimeTick()很简单,里面仅调用了函数OSSched,OSSched函数暂时没有修改,还是手动切换任务
在这里插入图片描述

十七、UCOSIII:任务时间片运行

1、对main()函数修改

main()函数与之前区别不大

  1. 加入了SysTick相关的内容
    在这里插入图片描述
  2. 注释掉任务里的OSSched()函数
    在这里插入图片描述
/*
************************************************************************************************************************
*                                                 包含的头文件
************************************************************************************************************************
*/
#include "os.h"
#include "ARMCM3.h"

/*
************************************************************************************************************************
*                                                   宏定义
************************************************************************************************************************
*/


/*
************************************************************************************************************************
*                                                  全局变量
************************************************************************************************************************
*/

uint32_t flag1;
uint32_t flag2;

/*
************************************************************************************************************************
*                                                  TCB & STACK & 任务声明
************************************************************************************************************************
*/
#define  TASK1_STK_SIZE       20
#define  TASK2_STK_SIZE       20

static   CPU_STK   Task1Stk[TASK1_STK_SIZE];
static   CPU_STK   Task2Stk[TASK2_STK_SIZE];

static   OS_TCB    Task1TCB;
static   OS_TCB    Task2TCB;

void     Task1( void *p_arg );
void     Task2( void *p_arg );

/*
************************************************************************************************************************
*                                                  函数声明
************************************************************************************************************************
*/
void delay(uint32_t count);

/*
************************************************************************************************************************
*                                                    main函数
************************************************************************************************************************
*/
/*
* 注意事项:1、该工程使用软件仿真,debug需选择 Ude Simulator
*           2、在Target选项卡里面把晶振Xtal(Mhz)的值改为25,默认是12,
*              改成25是为了跟system_ARMCM3.c中定义的__SYSTEM_CLOCK相同,确保仿真的时候时钟一致
*/
int main(void)
{	
	OS_ERR err;
	
	/* 关闭中断 */
    CPU_IntDis();

  /* 配置SysTick 10ms 中断一次 */
  OS_CPU_SysTickInit(10);
	
	/* 初始化相关的全局变量 */
	OSInit(&err);
	
	/* 创建任务 */
	OSTaskCreate ((OS_TCB*)      &Task1TCB, 
	              (OS_TASK_PTR ) Task1, 
	              (void *)       0,
	              (CPU_STK*)     &Task1Stk[0],
	              (CPU_STK_SIZE) TASK1_STK_SIZE,
	              (OS_ERR *)     &err);

	OSTaskCreate ((OS_TCB*)      &Task2TCB, 
	              (OS_TASK_PTR ) Task2, 
	              (void *)       0,
	              (CPU_STK*)     &Task2Stk[0],
	              (CPU_STK_SIZE) TASK2_STK_SIZE,
	              (OS_ERR *)     &err);
				  
	/* 将任务加入到就绪列表 */
	OSRdyList[0].HeadPtr = &Task1TCB;
	OSRdyList[1].HeadPtr = &Task2TCB;
	
	/* 启动OS,将不再返回 */				
	OSStart(&err);
}

/*
************************************************************************************************************************
*                                                    函数实现
************************************************************************************************************************
*/
/* 软件延时 */
void delay (volatile uint32_t count)
{
	for(; count!=0; count--);
}



/* 任务1 */
void Task1( void *p_arg )
{
	for( ;; )
	{
		flag1 = 1;
		delay( 100 );		
		flag1 = 0;
		delay( 100 );
		
		/* 任务切换,这里是手动切换 */		
		//OSSched();
	}
}

/* 任务2 */
void Task2( void *p_arg )
{
	for( ;; )
	{
		flag2 = 1;
		delay( 100 );		
		flag2 = 0;
		delay( 100 );
		
		/* 任务切换,这里是手动切换 */
		//OSSched();
	}
}

2、关闭中断函数CPU_IntDis()

在这里插入图片描述
关闭中断。
因为在OS系统初始化之前我们启用了SysTick定时器产生10ms的中断,在中断里面触发任务调度。
如果一开始我们不关闭中断,就会在OS还有启动之前就进入SysTick中断,然后发生任务调度,既然OS都还没启动,那调度是不允许发生的, 所以先关闭中断。
系统启动后,中断由OSStart()函数里面的OSStartHighRdy()重新开启。

CPU_IntDis()在cpu.c中被声明
在这里插入图片描述
一个关闭中断,一个开启中断
代码在cpu_a.asm中被定义
在这里插入图片描述

3、仿真测试

在这里插入图片描述

从图可以看到,两个任务轮流的占有CPU,享有相同的时间片。
其实目前的实验现象与上一章的实验现象还没有本质上的区别, 加入SysTick只是为了后续章节做准备。
上一章两个任务也是轮流的占有CPU,也是享有相同的时间片,该时间片是任务单次运行的时间。
不同的是本章任务的时间片等于SysTick定时器的时基,是很多个任务单次运行时间的综合。即在这个时间片里面任务运行了非常多次, 如果我们把波形放大,就会发现大波形里面包含了很多小波形
在这里插入图片描述

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

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

相关文章

【外汇天眼】外汇投资策略:区间突破交易系统

RangeBreak系统介绍 RangeBreak区间突破交易系统被市场广泛用于日内交易&#xff0c;曾经连续多年在《美国期货杂志》盈利交易系统排行榜中位居前十。 目前该交易系统也仍旧被很多专业机构和个人投资者所推崇。 交易者可根据自己的交易习惯和性格特点进行改进&#xff0c;并不…

Jmeter 命令启动 —— 动态参数化!

Jmeter命令行参数 1、在Linux中&#xff0c;使用非GUI的方式执行Jmeter。若需更改参数&#xff0c;必须先编辑jmx文件&#xff0c;找到对应变量进行修改&#xff0c;比较麻烦。 因此&#xff0c;可以参数化一些常用的变量&#xff0c;直接在Jmeter命令行进行设置 2、参数 -J…

根据核磁共振推出的分子结构式

核磁共振仪器实验报告 实验项目名称&#xff1a; 根据核磁共振推出 的分子结构式 实验目的 了解核磁共振的基本原理掌握核磁共振波谱仪的使用方法学习利用核磁共振测定化合物的结构式实验设备 核磁共振波谱仪&#xff08;Bruker 500&#xff09; 主要规格及技术指标&#x…

【数据结构】实现队列

大家好&#xff0c;我是苏貝&#xff0c;本篇博客带大家了解队列&#xff0c;如果你觉得我写的还不错的话&#xff0c;可以给我一个赞&#x1f44d;吗&#xff0c;感谢❤️ 目录 一. 队列的概念及结构二. 队列的实现队列的结构体初始化销毁队尾插入队头删除显示第一个节点的值…

盘点Java爬虫框架

盘点Java爬虫框架 Java 爬虫框架提供了许多功能丰富的工具和库&#xff0c;用于从网页抓取数据、解析HTML、处理HTTP请求等任务。以下是一些常用的 Java 爬虫框架&#xff1a; 1. **Jsoup**&#xff1a; - Jsoup 是一个用于解析HTML的Java库&#xff0c;它提供了简洁的API&am…

python自学3

第一节第六章 数据的列表 列表也是支持嵌套的 列表的下标索引 反向也可以 嵌套也可以 列表的常用操作 什么是列表的方法 学习到的第一个方法&#xff0c;index&#xff0c;查询元素在列表中的下标索引值 index查询方法 修改表功能的方法 插入方法 追加元素 单个元素追加 多…

C语言-两数组元素互换

#include <stdio.h> #include <string.h>//两数组元素互换 void swap(int ch1[],int ch2[],int sz) {int i 0;char ch 0;for(i 0;i < sz;i){ch ch1[i];ch1[i] ch2[i];ch2[i] ch;} } //打印数组元素 void print(int ch[],int sz) {int i 0;for(i 0;i <…

Git分布式管理-头歌实验日志和版本回退

在Git使用过程中&#xff0c;一种很常见的情况是&#xff1a;发现某个已经提交到仓库里的代码文件有致命的bug&#xff0c;必须将代码回滚到上一个版本&#xff0c;在这种情况下就显示出了Git的强大。Git为每次提交&#xff0c;都保留了日志&#xff0c;根据提交日志&#xff0…

前端开发中,并发请求工具的实现<多文件上传,数据切片>

前端开发中涉及到并发的业务中&#xff0c;如何优雅的实现一个并发工具 1.涉及并发的业务场景 1.> 多文件上传&#xff0c;支持过程中的进度展示&#xff0c;暂停&#xff0c;删除业务 2.> 多数据源的无参静态数据分片获取&#xff0c;如地图业务中海量静态点位的获取分…

centos7升级openssl_3

1、查看当前openssl版本 openssl version #一般都是1.几的版本2、下载openssl_3的包 wget --no-check-certificate https://www.openssl.org/source/old/3.0/openssl-3.0.3.tar.gz#解压 tar zxf openssl-3.0.3.tar.gz#进入指定的目录 cd openssl-3.0.33、编译安装遇到问题缺…

激活函数Swish(ICLR 2018)

paper&#xff1a;Searching for Activation Functions 背景 深度网络中激活函数的选择对训练和任务表现有显著的影响。目前&#xff0c;最成功和最广泛使用的激活函数是校正线性单元&#xff08;ReLU&#xff09;。虽然各种手工设计的ReLU替代方案被提出&#xff0c;但由于在…

机器学习入门-小白必看

机器学习 1. 机器学习的基本概念与背景2. 机器学习的常用方法3.是否需要学习机器学习&#xff0c;机器学习已经过时了&#xff1f;&#xff1f;4. 如何在机器学习上进行创新&#xff1f;5. 我该用哪种机器学习方法&#xff0c;如何定下来呢&#xff1f;总结&#xff08;对小白的…

gazebo平衡车模拟

gazebo和Ros中的平衡车模拟&#xff08;Noetic&#xff09; 控制原理 使用说明 在URDF模型中使用gazebo的 imu 插件获取平衡车姿态从 /joint_state 话题消息获取两轮的速度&#xff0c;相当于电机编码器速度环和直立环使用 串级PID 控制&#xff0c;框图如下&#xff1a;转向环…

02.变量

02.变量 01.变量 变量的概念&#xff1a; 1.变量的作用&#xff1a; 计算机中的存储空间&#xff0c;用于保存数据 2.定义变量的格式 变量名 值 注意&#xff1a; 是赋值运算符&#xff0c;左右两边打上空格是为了代码的规范性&#xff0c;美观性。 num1 3 #num1就是…

零基础学VR全景制作,新手制作流程有哪些?

VR全景技术可以应用于旅游、房地产、教育、娱乐等多个领域&#xff0c;可以为观众提供更加真实、更具沉浸感的体验。可以说&#xff0c;VR全景技术已经逐渐深入到各个领域中&#xff0c;那么对于新手来说&#xff0c;该如何制作VR全景呢&#xff1f; VR全景制作也是需要一定的技…

基于springboot的抗疫物资管理系统论文

目 录 摘 要 1 前 言 2 第1章 概述 2 1.1 研究背景 3 1.2 研究目的 3 1.3 研究内容 4 第二章 开发技术介绍 5 2.1相关技术 5 2.2 Java技术 6 2.3 MySQL数据库 6 2.4 Tomcat介绍 7 2.5 Spring Boot框架 8 第三章 系统分析 9 3.1 可行性分析 9 3.1.1 技术可行性 9 3.1.2 经济可行…

金三银四,程序员如何备战面试季

金三银四&#xff0c;程序员如何备战面试季 一个人简介二前言三面试技巧分享3.1 自我介绍 四技术问题回答4.1 团队协作经验展示 五职业规划建议5.1 短期目标5.2 中长期目标 六后记 一个人简介 &#x1f3d8;️&#x1f3d8;️个人主页&#xff1a;以山河作礼。 &#x1f396;️…

HarmonyOS—开启AOT编译模式

AOT&#xff08;Ahead Of Time&#xff09;即提前编译&#xff0c;能够在Host端&#xff08;即运行DevEco Studio的电脑&#xff09;将字节码提前编译成Target端&#xff08;即运行应用的设备&#xff09;可运行的机器码&#xff0c;这样字节码可以获得充分编译优化&#xff0c…

【AI视野·今日Sound 声学论文速览 第五十期】Fri, 1 Mar 2024

AI视野今日CS.Sound 声学论文速览 Fri, 1 Mar 2024 Totally 9 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Sound Papers Probing the Information Encoded in Neural-based Acoustic Models of Automatic Speech Recognition Systems Authors Quentin Raymondau…

SpringCloud--Sentinel使用

一、快速开始 Sentinel 的使用可以分为两个部分&#xff1a; 核心库&#xff08;Java 客户端&#xff09;&#xff1a;不依赖任何框架/库&#xff0c;能够运行于 Java 8 及以上的版本的运行时环境&#xff0c;同时对 Dubbo / Spring Cloud 等框架也有较好的支持。控制台&…