【uC/OS-III篇】uC/OS-III 创建第一个任务(For STM32)

uC/OS-III 创建第一个任务(For STM32)

日期:2024-3-30 23:55,结尾总结了今天学习的一些小收获

本博客对应的项目源码工程
源码项目工程


1. 首先定义错误码变量

// 用于使用uC/OS函数时返回错误码
OS_ERR err;  

2. 定义任务控制块

// 定义任务控制块,用于描述一个任务
OS_TCB p_tcb;

3. 初始化OS,如果有错误则通过 err 判断

// 初始化 uC/OS-III 中的内部变量和数据结构
OSInit(&err);
  • OSInit() 会初始化 uC/OS-III 的内部变量和数据结构,并创建2~5个系统任务。例如至少会创建空闲任务(OS_IdleTask)和时钟节拍任务

  • 空闲任务主要在其他任务不运行的时候运行,空闲任务优先级最低,默认为63(uC/OS的优先级规则是数字越小优先级越高,默认0~63)

  • 还可能创建统计任务(OS_StackTask())、定时任务(OS_TmrTask())、中断处理队列管理任务(OS_IntQTask())

  • OSInit() 函数注释

/*注释者:晨少日期:2024年3月29日地点:宿舍
*/void  OSInit (OS_ERR  *p_err)
{
#if (OS_CFG_ISR_STK_SIZE > 0u)CPU_STK      *p_stk;   // CPU_STK:     unsigned int 的宏定义CPU_STK_SIZE  size;    // CPU_STK_SIZE:unsigned int 的宏定义
#endif#ifdef OS_SAFETY_CRITICAL   // 系统是否需要符合安全关键(Safety Critical)的需求,在航天、医疗、核电等领域需要用到// 开启安全关键后,会自动检查栈溢出、检查系统各个地方是否有出现错误的可能if (p_err == (OS_ERR *)0) {OS_SAFETY_CRITICAL_EXCEPTION();return;}
#endif// 在系统初始化时可插入一些自定义操作OSInitHook();                                               /* Call port specific initialization code */// 清除中断嵌套计数器OSIntNestingCtr       =           0u;                       /* Clear the interrupt nesting counter */// 初始化系统运行状态,当前未启动多任务OSRunning             =  OS_STATE_OS_STOPPED;               /* Indicate that multitasking has not started           */// 清除锁嵌套计数OSSchedLockNestingCtr =           0u;                       /* Clear the scheduling lock counter*/// 初始化两个指针,一个是指向当前正在运行的TCB的指针,一个是指向当前最高优先级的TCB的指针OSTCBCurPtr           = (OS_TCB *)0;                        /* Initialize OS_TCB pointers to a known state          */OSTCBHighRdyPtr       = (OS_TCB *)0;// 初始化当前运行任务的优先级 & 最高优先级任务的优先级OSPrioCur             =           0u;                    /* Initialize priority variables to a known state       */OSPrioHighRdy         =           0u;#if (OS_CFG_SCHED_LOCK_TIME_MEAS_EN > 0u)OSSchedLockTimeBegin  =           0u;OSSchedLockTimeMax    =           0u;OSSchedLockTimeMaxCur =           0u;
#endif#ifdef OS_SAFETY_CRITICAL_IEC61508OSSafetyCriticalStartFlag = OS_FALSE;
#endif#if (OS_CFG_SCHED_ROUND_ROBIN_EN > 0u)// 禁用/启动循环调度OSSchedRoundRobinEn             = OS_FALSE;// OSCfg_TickRate_Hz默认值1000u,即1s有1000个节拍,一个节拍是1ms// 那么时间片轮转时长就是 1000u/10u = 100u ,即100msOSSchedRoundRobinDfltTimeQuanta = OSCfg_TickRate_Hz / 10u;  
#endif#if (OS_CFG_ISR_STK_SIZE > 0u)// 清除异常堆栈,进行堆栈检查// 将p_stk设为ISR栈的基地址p_stk = OSCfg_ISRStkBasePtr;                             /* Clear exception stack for stack checking. */// 如果p_stk为空,说明没有分配ISR栈空间;// 反之如果不为空,说明分配了ISR栈空间,则需要对ISR栈空间清零初始化if (p_stk != (CPU_STK *)0) {size  = OSCfg_ISRStkSize;while (size > 0u) {size--;*p_stk = 0u;p_stk++;}}// 检查任务堆栈溢出功能// 根据栈的生长方向,将栈底的8个字节初始化为特定值0x5432DCBAABCD2345UL// 该区域叫做红区,通过判断红区数据是否被修改,来判断栈是否溢出
#if (OS_CFG_TASK_STK_REDZONE_EN > 0u)                           /* Initialize Redzoned ISR stack */OS_TaskStkRedzoneInit(OSCfg_ISRStkBasePtr, OSCfg_ISRStkSize);
#endif
#endif......// 初始化优先级位表,将空闲任务插入到优先级列表中OS_PrioInit();                                              /* Initialize the priority bitmap table */// 初始化就绪优先级链表,链表结构体见 OS_RDY_LISTOS_RdyListInit();                                           /* Initialize the Ready List  */......// 系统配置初始化,例如空闲任务、中断ISR、消息队列等OSCfg_Init();// 系统初始化完成OSInitialized = OS_TRUE;                                    /* Kernel is initialized  */
}

4. 使用 OSTaskCreate 创建第一个任务,使用 OSStart 开始运行系统

.../* 定义栈区域 */
#define		TASK_START_STK_SIZE		100    // 栈深度,单位4字节,最小 64 * 4字节
CPU_STK  MyTask1_StartStk[TASK_START_STK_SIZE];/* 任务函数 */
void MyTask1(void *p_arg);    int main(void)
{......// 创建第一个uC/OS任务OSTaskCreate ((OS_TCB      *)&p_tcb,         	// 任务控制块地址(CPU_CHAR     *)"MyTask1", 			// 任务名(OS_TASK_PTR  )MyTask1,				// 任务函数地址(void        *)0,								// 参数(OS_PRIO      )3,								// 任务优先级(CPU_STK     *)&MyTask1_StartStk[0],   // 任务栈空间基地址(CPU_STK_SIZE )TASK_START_STK_SIZE/10, // 代表栈溢出警告之前栈内应该剩余的空间,即栈极限深度(CPU_STK_SIZE )TASK_START_STK_SIZE,    // 任务栈深度,单位4字节(OS_MSG_QTY   )0,(OS_TICK      )0,(void        *)0,// 任务可选项,创建任务时清空栈空间,运行时检查任务栈的使用情况(OS_OPT       )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),(OS_ERR      *)&err);// 启动OSOSStart(&err);
}

5. 第一个任务,先使用不精确的演示来做

//微秒级的延时
void delay_us(uint32_t delay_us)
{    volatile unsigned int num;volatile unsigned int t;for (num = 0; num < delay_us; num++){t = 11;while (t != 0){t--;}}
}
//毫秒级的延时
void delay_ms(uint16_t delay_ms)
{    volatile unsigned int num;for (num = 0; num < delay_ms; num++){delay_us(1000);}
}/*uC/OS 任务
*/
char flag1 = 0;   // 需要定义成全局变量才能添加到仿真中的逻辑分析仪
void MyTask1(void *p_arg)
{while(1){flag1 = 0;delay_ms(200);flag1 = 1;delay_ms(200);}
}

6. 使用仿真,使用逻辑分析仪来看变量的变化

需要先改几个地方

(1)设置频率为8MHz

在这里插入图片描述

 (2)勾选仿真

在这里插入图片描述

​ (3)将原本的DCM.DLL改成 DARMSTM.DLL ,Parameter 修改为自己的板子型号,例如 -pSTM32F103C8

在这里插入图片描述

​ (4)将 flag1 变量添加到逻辑分析仪中

在这里插入图片描述
在这里插入图片描述

​ (5)一键运行,观察逻辑分析仪

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

可以观察到 flag1 变量的变化,由于延时不是很精确,可以看到跳变周期为约为 0.3925s

​ (6)将flag1改为LED闪烁功能

void MyTask1(void *p_arg)
{while(1){LED(ON);delay_ms(200);LED(OFF);delay_ms(200);}
}

在这里插入图片描述


PS:

收获1:局部变量和 static 类型的变量不能添加到仿真中的逻辑分析仪

收获2:UCOS-III 的任务栈有最小显示,单位不是字,而是4个字节

// 在 os_cfg.h 中// 最小任务栈大小(单位4字节)
#define OS_CFG_STK_SIZE_MIN                       64u           /* Minimum allowable task stack size   

收获3:了解到任务栈的深度标记,代表栈溢出警告之前栈内应该剩余的空间,即栈极限深度,在本例中,当剩余栈空间小于任务栈空间的10%时,就达到了栈极限深度。

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

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

相关文章

Golang | Leetcode Golang题解之第2题两数相加

题目&#xff1a; 题解&#xff1a; func addTwoNumbers(l1, l2 *ListNode) (head *ListNode) {var tail *ListNodecarry : 0for l1 ! nil || l2 ! nil {n1, n2 : 0, 0if l1 ! nil {n1 l1.Vall1 l1.Next}if l2 ! nil {n2 l2.Vall2 l2.Next}sum : n1 n2 carrysum, carry …

Vue ElementPlus Input输入框

Input 输入框 通过鼠标或键盘输入字符 input 为受控组件&#xff0c;它总会显示 Vue 绑定值。 通常情况下&#xff0c;应当处理 input 事件&#xff0c;并更新组件的绑定值&#xff08;或使用v-model&#xff09;。否则&#xff0c;输入框内显示的值将不会改变。不支持 v-mode…

【面试经典150 | 动态规划】最小路径和

文章目录 写在前面Tag题目来源解题思路方法一&#xff1a;动态规划方法二&#xff1a;空间优化 写在最后 写在前面 本专栏专注于分析与讲解【面试经典150】算法&#xff0c;两到三天更新一篇文章&#xff0c;欢迎催更…… 专栏内容以分析题目为主&#xff0c;并附带一些对于本题…

MCGS学习——水位控制

要求 插入一个水罐&#xff0c;液位最大值为37插入一个滑动输入器&#xff0c;用来调节水罐水位&#xff0c;滑动输入器最大调节为液位最大值&#xff0c;并能清楚的显示出液位情况用仪表显示水位变化情况&#xff0c;仪表最大显示设置直观清楚方便读数&#xff0c;主划线为小…

设计模式-结构型-享元模式Flyweight

享元模式的特点&#xff1a; 享元模式可以共享相同的对象&#xff0c;避免创建过多的对象实例&#xff0c;从而节省内存资源 使用场景&#xff1a; 常用于需要创建大量相似的对象的情况 享元接口类 public interface Flyweight { void operate(String extrinsicState); } 享…

如何使用极狐GitLab 自定义 Pages 根域名

本文作者&#xff1a;徐晓伟 GitLab 是一个全球知名的一体化 DevOps 平台&#xff0c;很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab 是 GitLab 在中国的发行版&#xff0c;专门为中国程序员服务。可以一键式部署极狐GitLab。 本文主要讲述了极狐GitLab Pages …

普发Pfeiffer 真空TCP120-TCP380-TCP035-TCP600 使用手侧

普发Pfeiffer 真空TCP120-TCP380-TCP035-TCP600 使用手侧

C++进阶:多态(笔记)

目录 1. 多态相关概念1.1 简述&#xff1a;多态1.2 概念汇总与补充 2. 多态重写的底层原理2.1 虚函数存储的结构与位置2.2 重写覆盖 1. 多态相关概念 1.1 简述&#xff1a;多态 1. 什么是多态 不同的对象去做同一个行为时&#xff0c;得到的结果不同。反应到编程语言中&#…

Go语言HTTP服务实现GET和POST请求的同时支持

引言 在现代的Web开发中&#xff0c;HTTP服务是构建网络应用程序的基础。而支持GET和POST请求是其中最基本、最常见的功能之一。GET请求用于从服务器获取数据&#xff0c;而POST请求则用于向服务器提交数据。在Go语言中&#xff0c;通过标准库中的net/http包&#xff0c;我们可…

实景三维技术:开启自然资源管理的新篇章

随着科技的不断进步&#xff0c;实景三维技术已经在多个领域得到了广泛的应用。而在自然资源管理领域&#xff0c;实景三维技术更是发挥着越来越重要的作用。本文将介绍实景三维在自然资源管理领域的应用&#xff0c;探讨其带来的优势和变革。一、什么是实景三维技术&#xff1…

开源一款剪贴板跨设备共享工具

shigen坚持更新文章的博客写手&#xff0c;擅长Java、python、vue、shell等编程语言和各种应用程序、脚本的开发。记录成长&#xff0c;分享认知&#xff0c;留住感动。 个人IP&#xff1a;shigen 昨天遇到了一个很棘手的问题&#xff1a;我的手机剪贴板需要同步到另外的两台设…

HarmonyOS实战开发-一次开发,多端部署-音乐专辑

简介 基于自适应和响应式布局&#xff0c;实现一次开发、多端部署音乐专辑页面。 相关概念 一次开发&#xff0c;多端部署&#xff1a;一套代码工程&#xff0c;一次开发上架&#xff0c;多端按需部署。支撑开发者快速高效的开发支持多种终端设备形态的应用&#xff0c;实现对…

Chatgpt掘金之旅—有爱AI商业实战篇(二)

演示站点&#xff1a; https://ai.uaai.cn 对话模块 官方论坛&#xff1a; www.jingyuai.com 京娱AI 一、前言&#xff1a; 成为一名商业作者是一个蕴含着无限可能的职业选择。在当下数字化的时代&#xff0c;作家们有着众多的平台可以展示和推广自己的作品。无论您是对写书、文…

商业开源MES+源码+可拖拽式数据大屏

商业开源的一套超有价值的JAVA制造执行MES系统源码 带本地部署搭建教程 教你如何在本地运行运行起来。 开发环境&#xff1a;jdk11tomcatmysql8springbootmaven 需要源码&#xff0c;私信我付费获取。 一、系统概述&#xff1a; 万界星空科技免费试用MES、开源MES、商业开…

PP-YOLOE: An evolved version of YOLO

摘要 我们在之前 PP-YOLOv2 的基础上进行了优化&#xff0c;使用 无锚 范式&#xff0c;更强大的主干和颈部配备了 CSPRepResStage 。 ET-head 和动态标签分配算法 TAL 。 1 、介绍 受 YOLOX 的启发&#xff0c;我们进一步优化了之前的工作 PP-YOLOv2 。 PP-YOLOv2 是一款高…

PHP在线客服系统源码修复版

源码简介 在线客服系统网站源码https://www.888host.cn/330.html 新增消息预知&#xff0c;消息撤回&#xff0c;消息已读未读&#xff0c; 修复需要刷新才能收到消息 修复客户来源地址 修复消息提示音 修复桌面推送提醒 搭建环境 宝塔面板 &#xff0c;Nginx1.16-1.18 …

MySQL 之 数据库操作 及 表操作

&#x1f389;欢迎大家观看AUGENSTERN_dc的文章(o゜▽゜)o☆✨✨ &#x1f389;感谢各位读者在百忙之中抽出时间来垂阅我的文章&#xff0c;我会尽我所能向的大家分享我的知识和经验&#x1f4d6; &#x1f389;希望我们在一篇篇的文章中能够共同进步&#xff01;&#xff01;&…

Qt QWebSocket讲解

QWebSocket 是 Qt 框架中用于处理 WebSocket 通信的类。WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议。这使得客户端和服务器之间可以进行实时交互&#xff0c;而无需频繁地建立和关闭连接。 QWebSocket 的基本使用 创建 QWebSocket 对象&#xff1a; 你可以创建一个…

【跟着CHATGPT学习硬件外设 | 01】SPI

文章目录 &#x1f680; 概念揭秘关键精华&#x1f31f; 秒懂案例生活类比实战演练 &#x1f50d; 原理与工作流程探秘步骤1&#xff1a;初始化SPI接口步骤2&#xff1a;主设备启动通信步骤3&#xff1a;主设备发送数据步骤4&#xff1a;从设备接收数据步骤5&#xff1a;从设备…

一文彻底搞懂 TSL 流程

文章目录 1. 什么是 TSL2. TSL 流程3. CA 签发流程 1. 什么是 TSL HTTPS&#xff08;Hyper Text Transfer Protocol Secure&#xff09;是基于 HTTP 协议之上的安全通信协议&#xff0c;它使用 TLS 或 SSL 加密协议来保护网络通信的安全性和隐私性。 TLS&#xff08;Transpor…