【RTOS】RTOS实时操作系统随笔(结合UCOSII相关移植)

2023-05-16

目录

无操作系统下的程序结构及缺陷

有操作系统下的解决方案及CPU工作原理

操作系统调度策略及时间片轮转策略

操作系统TICK及进程切换

UCOSII介绍

UCOSII进程任务切换原理:

UCOS进程的堆栈:

时钟TICK及源代码结构:

实现移植过程:

跟着需求学习才能学的更好,所以学习操作系统应当知道为什么要用到操作系统,当你的主函数while()循环中执行的任务过多时,难免会出现这样或那样的问题。那么引入操作系统可能会帮你解决这样的问题。

无操作系统下的程序结构及缺陷

无操作系统的程序主要是从主函数开始执行:

以上一期小车程序为例,它的程序执行流程如下:

主函数:

int main(void)
{
	delay_init(); //外设配置初始化
	GPIOInit();
	LCD1602Init();
	IRCtrolInit();
	TIM2_Init();
	MotorInit();  //驱动层
 while(1)           //死循环
 {	
//子函数
}
}

 子函数处理比如:

void CarMove(void) //子函数1

{

}

void LCD1602WriteCommand(char comm) //子函数2

{

}

然后将子函数的代入主函数中

while(1)           //死循环
 {	
CarMove()
LCD1602Write(ctrl_comm)
//子函数
}

没有操作系统下的单片机运行结构中,我们主要的程序设计思路是将我们的需求分成很多子函数,通过主循环依次调用子函数。在执行程序的时候,程序的执行顺序为,先执行相关资源的初始化,执行完毕后所配置的外设资源都已启动,然后进入while循环,先执行CarMove()这个函数,执行完毕之后回到主函数继续执行LCD1602Write()这个函数,如此循环。我们将相关外设资源的初始化称之为驱动层。然后在相关驱动完备的基础上,进入主循环调用相关的功能函数完成用户的需要的功能。我们对这种程序运行机制称之为单线程

但是在单线程机制下,主函数中的各个函数之间在程序运行时容易受到上一个函数的影响,如果上一个函数运行时间长,就会导致下面的函数无法执行。当进入一个函数时,必须要等这个函数执行完毕才能够退处再执行下一个函数,如果该函数执行时间过长,则会导致其他的函数都无法执行陷入“罢工”状态。可能大家会说采用中断可以解决这种问题,但是中断机制也仅仅是解决了程序运行的及时性问题,但是没有解决时间问题,因为当子程序中的中断触发,该子程序暂停执行,转而执行中断服务函数,中断服务函数执行完毕,又回到开始的中断点继续执行该子程序。因此中断的引入并没有改变其单线程的本质,中断事件类比于插队事件,一群人排队买票,中断事件就是突然有急事,要求插队先处理它的购票事件。处理完大家依旧按照原先的方式排队购票。(只有单片机的外设中断可以暂时打断子函数的执行。)

在没有操作系统下的单线程运行机制有两个问题,一个是每一个函数顺次调用,后面的函数总是要等前面的函数完成后才能执行,但是如果该函数执行时间较长,后面的函数都要等前面的函数执行完才能执行,好比堵车,前面的车不往前走,后面的车都在后面等着;二是每个函数运行时,只要程序从主循环里转到任何一个函数,这个函数在运行时又转到更底层的函数,在进行这一过程时只能等到调用的程序自然结束,方可执行完毕。

我们运用单片机的本质就是操作芯片的相关资源去实现某种功能应用,但是一个项目通常不仅仅是需要单片机的某一个或者两个硬件资源,往往是操作多个硬件资源构成的函数事件相结合。这有可能造成的问题就是单个功能模块测试时功能正常,但多个功能模块合在一起交给单片机处理时就可能会导致原本功能正常的函数合在一起之后就不能正常工作了。究其原因就是不理解单线程的运行机制,很粗糙的将多个函数一股脑以串联的方式放进了主程序,子函数在主程序中堆砌的越长,主函数的执行效率越低。

因此我们要解决的主要问题是如何让含有多个子函数的主循环快速执行,各函数在执行各自程序时不受其他子函数的影响,引入操作系统就是解决上述问题。注:状态机也可以。

操作系统的引入

操作系统可以视为第三方力量来管理各子函数的执行,比如操作系统让某一子函数执行相应的时间,如果该函数在操作系统给定的时间下没有执行完毕,则暂停转而运行下一个函数。

有操作系统下的解决方案及CPU工作原理

操作系统是一套程序,这套程序可以对每个子函数的进程进行合理的干预,最常规的干预是让每一个进程按照某一节奏运行。

操作系统的基本原理CPU的结构:(寄存器R0-R15\PC\CPSR、运算器)

单片机核心器件是CPU,CPU里面核心的是运算器ALU,运算的数据存放在16个寄存器里,程序放在单片机ROM,ROM也有地址,单片机是通过PC程序计数器来存放CPU即将到ROM读取的程序的地址,利用CPSR当前程序状态寄存器,用来存放当前程序运算的状态。

时间片:是一个计时单位;时钟节拍Tick:也是一个计时单位,是操作系统最小的计时单位;一个时间片=n*Tick。

操作系统调度策略及时间片轮转策略

有了操作系统,每个功能都是自行封闭的函数,函数上加上了while(1)循环,也叫每一个进程都变成的死循环,故主函数中的while(1)中就不能在写程序了。那么在操作系统中如何将某个进程结束呢?操作系统采用的是任务调度,意思是由操作系统按照特定的调度策略在后台对进程进行切换。从C语言角度叫函数,但是在操作系统中叫进程。

操作系统的调度策略:最基本的调度策略是基于时间片轮转。

如果操作系统给某一进程一定的时间,就会出现三种情况,进程运行完毕若干周期,进程刚好运行完,进程没运行完毕。如果每个进程分配10毫秒,系统由三个进程,则一个系统运行周期是30毫秒,那么在第40毫秒则会继续第一个进程未完成的位置继续运行,也就是上次进程切换点的位置继续向后执行10毫秒。但每个进程运行完毕所用的时间是不一样的,有些进程可能都不需要10毫秒的时间,那么这个10毫秒的进程分配时间就没有必要了,因此操作系统应该对即将运行的进程有一个判断,即有没有运行的必要,故纯粹的时间片轮转是不实用的。

如果前一个进程在分配的时间内提前结束进程,那么操作系统需要采用调度算法从众多进程中挑选一个进程送进CPU进行。切换到哪个进程的依据,是把每一个进程当前所处的状态分为5种状态(操作系统休眠态、就绪态‘运行条件具备,但操作系统未切换’、运行态、挂起‘运行条件不具备,需要进程间通信通知’、删除),根据进程将要执行的必要性对其进行切换。操作系统的功能类似一个多路器,如上图所示。任何操作系统在运行时都离不开硬件定时器,这是操作系统与硬件唯一的关系,剩下的就只有软件问题。

操作系统TICK及进程切换

操作系统的Tick是由处理器硬件上的一个定时器产生的固定周期,一般为10毫秒。对操作系统的相关函数进行一次调用。所以应当配置定时器中断,在中断处理函数中调用操作系统里的函数,其目的是通知操作系统客观事物发生了改变,操作系统会在每一个Tick周期对每个进程的状态进行统计和修正,作为下次进程调度的依据。

如果多个进程都已就绪,为了使操作系统有序执行,采用基于优先级的进程调度,故操作系统调度之前各进程应具备以下条件:操作系统需要管理的进程个数以及进程的优先级。

UCOSII介绍

UCOSII工程文件下载网站

UCOSII进程任务切换原理:

CPU的寄存器有统用寄存器,程序状态寄存器,程序计数器。哪个进程切换运算,就自动把哪个进程的数据调入到寄存器中。故切换前应对当前数据进行备份(也称现场保存),以便下一次运行时可继续运行。

UCOS进程的堆栈:

UCOSII为了实现进程切换,在每一个进程创建的时候,必须要为每一个进程在单片机的RAM空间留下一段RAM空间,下次再运行到该进程时,再从RAM空间的数据拷贝到寄存器中进行运算。我们将用于保存进程切换时的RAM空间称为进程堆栈,进程堆栈是用于进程切换时备份或保存CPU寄存器的值,理论上多少寄存器就需要多少RAM空间,同时操作系统需要定时器来对操作进程进行刷新。

时钟TICK及源代码结构:

其代码有两个部分,一是与CPU无关的部分(C语言实现),另一个时与CPU有关的部分(由汇编实现主要应用于寄存器操作,另一部分用C语言实现)。

实现移植过程:

1 准备裸机程序

2 移植要用得到的外设驱动

3 拷贝UCOS源码到工程下

4 向工程添加UCOS源码

程序植入系统应当将外设在裸机条件下调试好,再引入操作系统,否则容易出错。

(注:将程序中的delay()函数删除)

将UCOS文件添加到工程中去,建三个分组,一个存放始终不修改的代码(UCOS源码);一个存放跟CPU相关的汇编代码跟C代码;一个存放UCOS的库。

 

5 头文件不需要添加,编译器会自己寻找,但要添加头文件的搜索路径。

6 编译0错误,0警告

7 添加UCOS的tick

8 tick函数的异常向量入口地址

同时注意,tick函数是用c语言写的,在汇编语言中调用C函数应当在汇编文件中进行申明。申明如下:

9  添加头文件*include “includes.h”,在主函数上应当初始化OSInit();

10  建立分组存放用户编写的APP

11 准备用户任务代码

在app.c中创建两个进程

#include "app.h"
#include "includes.h"
#include "led.h"
void LE0_task(void *p)
{
	LED_Init();
	//....
  while(1)
	{
	 LED0_OFF;
	 OSTimeDlyHMSM(0, 0, 0, 1000);
	 LED0_ON;	
	 OSTimeDlyHMSM(0, 0, 0, 1000);
	}
}


void LE1_task(void *p)
{
  while(1)
	{
		LED1_OFF;
		OSTimeDlyHMSM(0, 0, 0, 500);
	  LED1_ON;	
		OSTimeDlyHMSM(0, 0, 0, 500);
	}
}

在main.c中管理进程函数

#include "stm32f10x_conf.h"
#include "Led.h"
#include "includes.h"
#include "app.h"

extern void  OS_CPU_SysTickInit(void);
OS_STK LD0stk[64];//LED0进程的堆栈
OS_STK LD1stk[64];//LED1进程的堆栈

int main()
{
	
	OSInit();     //    进程代码              参数        进程堆栈            优先级
  OSTaskCreate((void (*) (void *))LE0_task, (void *) 0,(OS_STK *)&LD0stk[63],  3);
	OSTaskCreate((void (*) (void *))LE1_task, (void *) 0,(OS_STK *)&LD1stk[63],  4);
	OS_CPU_SysTickInit();
	OSStart(); 
//
  while(1)
	{
  		
	}
}

往期回顾:

 红外遥控小车程序分析(下)——红外传输数据程序分析

一文看懂Modbus通信协议(上)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【RTOS】RTOS实时操作系统随笔(结合UCOSII相关移植) 的相关文章

  • 多线程如何实现高性能计数器(无锁)

    多线程协作免不了使用计数器 xff0c 通常的代码 xff0c c 43 43 一般会使用锁 xff0c 或者原子变量操作 xff1a std mutex mutexCounter int count void add std lock g
  • ubuntu18/20 下如何生成core文件

    ubuntu18 20 下如何生成core文件 一 设置 原理 xff1a https blog csdn net Sunnyside article details 118439302 原来在ubuntu14 ubuntu16上只需要一步
  • c++的字节序与符号位的问题

    看这样一道题 xff1a include lt stdio h gt int main void int w h int i 61 0xa1b2c3d4 char p 61 char amp i for int j 61 0 j lt 4
  • docker镜像之带vnc的ubuntu

    docker镜像 之 带vnc图形界面ubuntu 前言 xff1a 为了在图形界面中使用firefox xff0c 需要找一个带rdp或者vnc的ubuntu xff0c 最好是gnome的界面 xff0c 折腾了3天 xff0c 终于找
  • STM32中,关于中断函数调用全局变量的问题

    xfeff xfeff https blog csdn net leo liu006 article details 79334905 首先是问题的描述 xff1a 硬件单片机型号 xff0c STM32F103VET6 xff0c IDE
  • python使用selenium以及selenium-wire做质量与性能检测

    python天生就是适合用来做爬虫 xff0c 结合selenium真是如虎添翼 xff1b 1 安装库 pip install selenium pip install selenium wire 2 xff09 添加驱动 xff0c 比
  • 编写http workshop脚本从网页缓存里解析音乐

    前一篇文章 编写http workshop脚本从网站下载音乐 示范了如何使用HttpClient访问API 以及Json数据的解析 今天我们通过解析一个网页展示如何使用内置的LibXml2的功能解析HTML 提取我们关心的内容 这里随便搜了
  • pytorch环境搭建若干

    备注 xff1a 不要使用python3 11不支持 xff0c pip会说找不到合适的版本 xff1b python官网不提供旧版的下载了 xff0c 说是win7以后无法使用 xff0c 都是扯淡 xff0c 有其他地方可以下载pyth
  • ffmpeg常用方法

    FFmpeg 是一款开源的音视频处理工具 xff0c 可以处理各种格式的音视频文件 xff0c 并且可以进行格式转换 剪切 合并 添加水印等多种操作 下面是 FFmpeg 的一些常用命令及其用法 xff1a 视频转码 将一个视频文件转换为另
  • RFC2152 UTF-7 中文

    RFC2152 UTF 7 中文 翻译 xff1a 李静南 时间 xff1a 2006 03 29 EMAIL xff1a robin fox 64 sohu com 版权 xff1a 可以用于非商业用途自由转载 xff0c 但请保留本文档
  • 第九章0.4的CMakeLists.txt结构

    最开始看这一章的时候 xff0c 将CMakeLists txt部分跳过了 xff0c 没有看 后来看高博RGBD SLAM时候 xff0c 第一讲降到了cmake的用法 xff0c 发现有新的东西 xff0c 又回头看 xff1a 最原始
  • ROS 中setup.bash

    好久没写了 xff0c 最近搞了辆小车 xff0c 瞅了瞅ROS的相关内容 xff0c 没有写ROS的内容 xff0c 刚开始看 xff0c 写的话基本就成了书本粘贴 不过最近由ROS引出来的一些Linux相关的东西 xff0c 然后又回头
  • ros_hostname与ros_ip

    在ROS的环境变量中 xff0c 需要在 bashrc中设置的并不多 xff08 此处是指在wiki的基本教程中出现的 xff0c 大牛请无视 xff09 xff0c 大概只有三个 xff1a ROS MASTER URI ROS HOST
  • git图形化代码冲突处理

    当代码量少的时候使用 xff0c 使用vimdiff或者手动处理冲突 xff0c 都很方便 xff0c 但是当代码量大还是图形化处理更方便 xff0c 这里推荐使用kdiff3 首先下载kdiff3 xff0c 网上不好找的话 xff0c
  • Apache httpd 目录列表禁用配置(options indexes)

    Apache httpd服务器在缺省的情况下 xff0c 开启了基于目录列表的访问 xff0c 这是一个存在安全隐患的问题 xff0c 因此可以关闭这个功能 在Apache 2 4的版本中 xff0c 不在支持使用 indexes来配置 x
  • cmake学习笔记6-catkin的CmakeList.txt讲解

    https www jianshu com p 551d6949b49d 引用 cmake学习笔记 cmakelist txt创建项目示例 cmake的介绍和使用 Cmake实践 推荐cmake手册详解 严重推荐CMake构建系统的骨架 c
  • ROS中使用Intel RealSense D455或L515深度相机

    目的 在ROS平台上 xff0c 使用深度相机作为传感器设计自主避障机器人 1 安装驱动 测试环境 软件 xff1a Ubuntu 16 04 ROS Kinetic 硬件 xff1a Intel RealSense D455 或 L515
  • ROS机器人操作系统底层原理及代码剖析

    0 目的 本文介绍ROS机器人操作系统 xff08 Robot Operating System xff09 的实现原理 xff0c 从最底层分析ROS代码是如何实现的 1 序列化 把通信的内容 xff08 也就是消息message xff
  • RS232,RS485波形分析

    通过观察波形可以确定以下情况 xff1a 是否有数据接收或发送 xff1b 数据是否正确 xff1b 波特率是否正确 xff1b 一 串行数据的格式 异步串行数据的一般格式是 xff1a 起始位 43 数据位 43 停止位 xff0c 其中
  • GPU渲染管线之旅|05 图元处理、Clip/Cull, 投影和视图变换

    上一篇中我们讨论了关于 纹理和采样 xff0c 这一篇我们回到3D管线的前端 在执行完顶点着色之后 xff0c 就可以实际的渲染东西了 xff0c 对吗 xff1f 暂时还不行 xff0c 因为在我们实际开始光栅化图元之前 xff0c 仍然

随机推荐

  • 谈谈OpenCV中的四边形

    首先抛出一个问题 xff0c 给定一系列二维平面上的的点 xff0c 这些点是可以组成一个封闭的二维图形 因为这些点是矩形区域拍摄图像后识别得到的图形的边界点 xff0c 所以我们要抽象出来这个矩形 xff0c 也就是我们要反映出这个矩形
  • GPU渲染管线之旅|07 深度处理、模板处理

    在这一篇中 xff0c 我们来讨论Z pipline的前端部分 简称它为early Z 以及它是在光栅化中怎么起作用的 和上一篇一样 xff0c 本篇也不会按实际的管道顺序进行讨论 xff1b 我将首先描述基础算法 xff0c 然后再补充管
  • GPU渲染管线之旅|08 Pixel Shader

    在这一部分中 xff0c 我们来谈谈像素处理的前半部分 dispatch和实际的像素着色 事实上 xff0c 这部分是大多数图形开发者在谈到PS stage时所关心的内容 有关alpha blend和Late Z的内容则会下一篇文章中去探讨
  • MFC基于CSplitterWnd类的多窗口分割

    使用平台 xff1a win7 64bit 使用环境 xff1a VS2012 1 CSplitterWnd介绍 上图是从MSDN中截取的类的继承图表 xff0c CSplitterWnd类继承自CWnd类 这个类主要就是提供窗口分割的功能
  • OpenCV - 区域生长算法

    1 理论基础 区域生长算法的基本思想是将有相似性质的像素点合并到一起 对每一个区域要先指定一个种子点作为生长的起点 xff0c 然后将种子点周围领域的像素点和种子点进行对比 xff0c 将具有相似性质的点合并起来继续向外生长 xff0c 直
  • 不规则Contours内部像素的操作

    在findContours函数使用了之后 xff0c 有时候就会面临对Contours内部区域的访问 由于contours不一定是凸图形 xff0c 所以使用循环操作的时候总感觉不那么方便 比如在下图中 xff0c 已经使用findCont
  • ros代码中添加使用opencv库,cv::Mat和ros image之间的相互转换

    https blog csdn net sunyoop article details 78630024 ros中很多时候要用到图形处理 xff0c 这时就需要使用opencv库 xff0c 本篇主要将怎么在ros现成node上使用open
  • Ubuntu 16.04 使用

    这篇博客用来专门记录尝试搬迁工作环境到Linux下的使用笔记 xff0c 主要包含有常用软件的安装 xff0c 配置 1 安装输入法 ubuntu 16 04中支持ibus输入系统 1 系统 gt 首选项 gt IBus设置 在弹出的IBu
  • 牛顿迭代法求解方程

    说明 xff1a 该篇博客源于博主的早些时候的一个csdn博客中的一篇 xff0c 由于近期使用到了 xff0c 所以再次作一总结 原文地址 概述 牛顿迭代法 xff08 Newton s method xff09 又称为牛顿 拉夫逊 xf
  • OpenCV - 均值迭代分割

    题外话 之前在博客中写过一篇 区域生长 的博客 xff0c 区域生长在平时经常用到 xff0c 也比较容易理解和代码实现 xff0c 所以在很多情况下大家会选择这种方法 但是区域生长有一个最致命的点就是需要选取一个生长的种子点 为了交流学习
  • IMU原理及姿态融合算法详解

    IMU原理及姿态融合算法详解 一 组成 IMU全称是惯性导航系统 xff0c 主要元件有陀螺仪 加速度计和磁力计 其中陀螺仪可以得到各个轴的加速度 xff0c 而加速度计能得到x xff0c y xff0c z方向的加速度 xff0c 而磁
  • FrankMocap win10安装指导

    本文是相当于将github上frankmocap的安装指导进行了翻译 xff0c 增加了一下windows下安装遇到的坑以及注意事项 如果是linux系统应该安装官方的安装指导安装就可以 xff0c 可以直接参考官方安装指导 安装所有模块
  • ADRC学习(1)系统在调节过程中安排过渡过程的作用

    1 二阶系统的调节过程 考虑对于如下所示的二阶系统 x
  • 笔记本更换SSD后卡顿、假死、失去响应问题探究

    某些笔记本电脑将HDD更换为SSD后 xff0c 系统运行过程中会随机产生半分钟到一分钟的卡顿 xff08 假死 xff09 期间鼠标指针可以运动 xff0c 但所有程序均失去响应 xff0c 也无法打开新的程序 HDD硬盘指示灯常亮 xf
  • 机器人 齐次变换矩阵 位姿变换矩阵(RT矩阵) Matlab参数公式计算

    对于齐次位姿变换 xff08 RT矩阵 xff09 xff0c 有的时候手动计算公式参数太多比较麻烦 xff0c 因此利用matlab参量syms xff0c 可以方便一些 xff0c 可以用于计算机器人正运动学位姿矩阵的参数表示 xff0
  • UART串口校验方式(无校验、奇偶校验、固定校验)

    UART串口校验方式 xff08 奇偶校验 固定校验 无校验 xff09 串口通信校验方式奇偶校验位固定校验位 Stick 无校验位 校验位 xff1a 串口通信中的检错方式 串口在接收数据时 xff0c 如果无检验位 xff0c 则只要检
  • 更改LXDE的语言为中文

    之前给旧笔记本安装了Debian8 43 LXDE嘛 xff0c 运行比较流畅 安装过程中本想选择中文的 xff0c 但是安装界面中旧有中文乱码 xff0c 所以还是选了英语 等装好了系统 xff0c 把apt update 43 upgr
  • 干掉Nouveau安装Linux Nvidia显卡驱动

    https blog csdn net misiter article details 7652731 干掉Nouveau安装Linux Nvidia显卡驱动 首先说明下什么是Nouveau xff0c 为什么有些系统安装N卡驱动的时候会提
  • 【C应用】红外遥控小车程序分析(上)——四轮马达方向控制程序分析

    目录 驱动原理分析 L293D功能分析 代码分析 驱动原理分析 小车采用两片L293D芯片控制四个车轮 xff0c 原理图如下 xff1a 因为L293D可分别控制两路电机 xff0c 为了方便理解L293D芯片的工作原理 xff0c 拿L
  • 【RTOS】RTOS实时操作系统随笔(结合UCOSII相关移植)

    目录 无操作系统下的程序结构及缺陷 有操作系统下的解决方案及CPU工作原理 操作系统调度策略及时间片轮转策略 操作系统TICK及进程切换 UCOSII介绍 UCOSII进程任务切换原理 xff1a UCOS进程的堆栈 xff1a 时钟TIC