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

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


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


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

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       20static   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.hqwc.cn/news/513741.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算机网络 网络原理之Http

目录 1 前言2 什么是http的一次交互&#xff1f;3 理解“协议”二字4 认识URL4.1 简介4.2 URL的编码和解码(urlencode和urldecode) 5 抓包工具 fiddler6 http和https的区别7 http 头8 HTTP 状态码9 常见的 Http 服务器 1 前言 为什么要了解Http原理呢&#xff1f;因为http原理…

gitlab的安装

1、下载rpm 安装包 (1)直接命令下载 wget https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/gitlab-ce-11.6.10-ce.0.el7.x86_64.rpm&#xff08;2&#xff09;直接去服务器上下载包 Index of /gitlab-ce/yum/el7/ | 清华大学开源软件镜像站 | Tsinghua Open Source…

安卓SDK dx工具生成dex文件命令

目录 前言一、添加到环境变量二、命令示例 前言 在Android SDK 工具中&#xff0c;dx命令用于将Java字节码文件转换为Dalvik Executable&#xff08;dex&#xff09;文件&#xff0c;以便在Android设备上运行。 一、添加到环境变量 找到想要使用的SDK版本&#xff0c;将dx.b…

基于“xxx” Androidx平台的驱动及系统开发 之 触摸板篇

目录 一、基于全志 A133 Android10平台&#xff0c;适配1366x768 - ilitek2511触摸1、原理图分析2、驱动移植与适配3、补丁和资源文件 二、基于瑞芯微 RK3566 Android11平台&#xff0c;适配GT9XX触摸1、原理图分析2、补丁及资源文件 三、遇到的问题与解决1、基于amlogic Andro…

【软件工程】浅谈讲解单元测试

&#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a;软件工程 ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 前言 正文 1. 单元测试的定义和作用 2. 单元测试的快速反馈 3. 单元测试对定位问题的帮助 4. 单元测试对代码设计的影响 5. 单元测试…

Tomcat实现java博客项目、状态页及常见配置介绍

目录 一、自建博客 1. 项目背景 2. 操作示例 二、状态页 1. 概述 2. server status 信息状态页 3. manager app 项目管理状态页 4. host manger 虚拟主机管理状态页 三、常见配置 1. 端口8005/tcp安全配置管理 2. tomcat端口号 3. 虚拟主机设置 4. Context配置 一…

每日汇评:在美国关键数据公布前,黄金保持“逢低买入”的交易模式

金价从周二早间2120美元的三个月高点回落&#xff1b; 由于对中国的担忧&#xff0c;美元试图反弹&#xff0c;尽管美债收益率低迷&#xff1b; 在看涨的每日技术面设置中&#xff0c;黄金价格回落是一个很好的买入机会&#xff1b; 金价正在复制周一亚洲交易时段的修正走势&am…

Linux内核内存管理架构详解

内存管理子系统可能是linux内核中最为复杂的一个子系统&#xff0c;其支持的功能需求众多&#xff0c;如页面映射、页面分配、页面回收、页面交换、冷热页面、紧急页面、页面碎片管理、页面缓存、页面统计等&#xff0c;而且对性能也有很高的要求。本文从内存管理硬件架构、地址…

VScode+Live Service+Five Service实现php实时调试

VScodeLive ServiceFive Service实现php实时调试 一、VScode插件安装及配置 1.Code Runner settings.json设置&#xff08;打开方式&#xff1a;ctrlp&#xff0c;搜索settings.json&#xff09; 设置php为绝对路径&#xff08;注意路径分隔符为\\或/&#xff09; 2. Live S…

HUAWEI 华为交换机 配置 MAC 防漂移 防MAC伪造示例

组网需求 某企业网络中&#xff0c;用户需要访问企业的服务器。如果某些非法用户从其他接口假冒服务器的MAC 地址发送报文&#xff0c;则服务器的 MAC 地址将在其他接口学习到。这样用户发往服务器的报文就会发往非法用户&#xff0c;不仅会导致用户与服务器不能正常通信&…

B端设计:如何让UI组件库成为助力,而不是阻力。

Hi&#xff0c;我是大千UI工场&#xff0c;网上的UI组件库琳琅满目&#xff0c;比如elementUI、antdesign、iview等等&#xff0c;甚至很多前端框架&#xff0c;也出了很多UI组件&#xff0c;如若依、Layui、bootstrap等等&#xff0c;作为UI设计师该如何面对他们呢。 一、UI组…