STM32 uc/OS-III多任务程序

目录

一、项目创建

二、代码移植 

1、uC/OS-III源码处理

2、KEIL文件配置

​编辑3、文件修改

启动文件

​编辑app_cfg.h

includes.h

bsp.c和bsp.h

main.c

lib_ cfg.h

 app.c和app.h

三、总结 


学习目标:

学习嵌入式实时操作系统(RTOS),以uc/OS为例,将其移植到STM32F103上。 

一、项目创建

仍然是使用STM32CubeMX建立新的项目,如何选择STM32相关型号请见之前的博客,避免过多叙述影响内容,下面直接跳到项目配置。(之前的操作步骤不了解的请参考下例博客:https://blog.csdn.net/weixin_74345079/article/details/139183523?utm_source=miniapp_weixin)

首先选择PC13为GPIO_Output,再根据下面指示的操作进行配置RCC、SYS等。

 基本配置完成后,点击右上角 " GENERATE CODE " ,进入以下界面,跟随操作并生成代码。

二、代码移植 

1、uC/OS-III源码处理

移植之前我们要获取uC/OS-III源码,获取方法:进入官网链接(Micrium Software and Documentation - Silicon Labs)进行下载。

再建一个新的文件夹 " UCOSIII " ,将uC-CPU、uC-LIB、uCOS-III三个文件复制到该文件夹。

 在Src文件夹下新建一个OS文件夹,然后将下载的源码中\EvalBoards\Micrium\uC-Eval-STM32F107\uCOS-III下的文件app.c app_cfg.h cpu_cfg.hincludes.h lib_cfg.h os_app_hooks.c os_app_hook.hos_cfg.hos_cfg_app.h复制到该文件夹中。

然后再新建三个空白文件: bsp.cbsp.happ.h 

2、KEIL文件配置

在工程下添加如下文件;

将Src/OS中的bsp.c 和 bsp.h文件添加至 bsp 组中;

app.c 添加进 Application/User/Core 组中;

将UCOSIII/uC-CPU中的cpu_core.c、cpu_core.h、cpu_def.h添加进uCOSIII_CPU组中,以及UCOSIII/uC-CPU/ARM-Cortex-M3/RealView中的三个文件添加到该组;

UCOSIII/uC-LIB中的9个文件添加到uCOSIII-LIB组中,同时将UCOSIII/uC-LIB/Ports/ARM-Cortex-M3/Realview中的lib_mem_a.asm添加到该组中;

UCOSIII/UcosIII/Ports/ARM-Cortex-M3/Generic/RealView中的3个文件添加的uCOSIII_Ports组中;

UCOSIII/UcosIII/Source中的20个文件添加到uCOSIII_Source组中;

将Core/Src/OS中的app_cfg.h、cpu_cfg.h、includes.h、lib_cfg.h、os_appa_hooks.c、os_app_hooks.h、os_cfg.h、os_cfg_app.h添加到OS_cfg组中。

 下面是配置好过后的keil工程:

随后点击魔法棒,再配置头文件路径:

3、文件修改

启动文件

app_cfg.h

#define APP_CFG_SERIAL_EN DEF_ENABLED修改为#define APP_CFG_SERIAL_EN DEF_DISABLED

#define APP_TRACE BSP_Ser_Printf修改为#define APP_TRACE (void)

includes.h

添加三个头文件:#include "gpio.h"#include "app_cfg.h"#include "app.h"

bsp.c和bsp.h

bsp.c:

// bsp.c
#include "includes.h"#define  DWT_CR      *(CPU_REG32 *)0xE0001000
#define  DWT_CYCCNT  *(CPU_REG32 *)0xE0001004
#define  DEM_CR      *(CPU_REG32 *)0xE000EDFC
#define  DBGMCU_CR   *(CPU_REG32 *)0xE0042004#define  DEM_CR_TRCENA                   (1 << 24)
#define  DWT_CR_CYCCNTENA                (1 <<  0)CPU_INT32U  BSP_CPU_ClkFreq (void)
{return HAL_RCC_GetHCLKFreq();
}void BSP_Tick_Init(void)
{CPU_INT32U cpu_clk_freq;CPU_INT32U cnts;cpu_clk_freq = BSP_CPU_ClkFreq();#if(OS_VERSION>=3000u)cnts = cpu_clk_freq/(CPU_INT32U)OSCfg_TickRate_Hz;#elsecnts = cpu_clk_freq/(CPU_INT32U)OS_TICKS_PER_SEC;#endifOS_CPU_SysTickInit(cnts);
}void BSP_Init(void)
{BSP_Tick_Init();MX_GPIO_Init();
}#if (CPU_CFG_TS_TMR_EN == DEF_ENABLED)
void  CPU_TS_TmrInit (void)
{CPU_INT32U  cpu_clk_freq_hz;DEM_CR         |= (CPU_INT32U)DEM_CR_TRCENA;                /* Enable Cortex-M3's DWT CYCCNT reg.                   */DWT_CYCCNT      = (CPU_INT32U)0u;DWT_CR         |= (CPU_INT32U)DWT_CR_CYCCNTENA;cpu_clk_freq_hz = BSP_CPU_ClkFreq();CPU_TS_TmrFreqSet(cpu_clk_freq_hz);
}
#endif#if (CPU_CFG_TS_TMR_EN == DEF_ENABLED)
CPU_TS_TMR  CPU_TS_TmrRd (void)
{return ((CPU_TS_TMR)DWT_CYCCNT);
}
#endif#if (CPU_CFG_TS_32_EN == DEF_ENABLED)
CPU_INT64U  CPU_TS32_to_uSec (CPU_TS32  ts_cnts)
{CPU_INT64U  ts_us;CPU_INT64U  fclk_freq;fclk_freq = BSP_CPU_ClkFreq();ts_us     = ts_cnts / (fclk_freq / DEF_TIME_NBR_uS_PER_SEC);return (ts_us);
}
#endif#if (CPU_CFG_TS_64_EN == DEF_ENABLED)
CPU_INT64U  CPU_TS64_to_uSec (CPU_TS64  ts_cnts)
{CPU_INT64U  ts_us;CPU_INT64U  fclk_freq;fclk_freq = BSP_CPU_ClkFreq();ts_us     = ts_cnts / (fclk_freq / DEF_TIME_NBR_uS_PER_SEC);return (ts_us);
}
#endif

bsp.h:

// bsp.h
#ifndef  __BSP_H__
#define  __BSP_H__#include "stm32f1xx_hal.h"void BSP_Init(void);#endif

main.c

/* USER CODE BEGIN Header */
/********************************************************************************* @file           : main.c* @brief          : Main program body******************************************************************************* @attention** Copyright (c) 2024 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "gpio.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <includes.h>
/* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD *//* USER CODE END PTD *//* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* 任务优先级 */
#define APP_TASK_START_PRIO		2
#define MyTask_LED1_PRIO		3
#define MyTask_LED2_PRIO		3/* 任务堆栈大小	*/
#define APP_TASK_START_STK_SIZE 128
#define MyTask_LED1_STK_SIZE 	512
#define MyTask_LED2_STK_SIZE	512/* 任务控制块 */
static OS_TCB AppTaskStartTCB;
static OS_TCB MyTask_LED1TCB;
static OS_TCB MyTask_LED2TCB;/* 任务栈 */	
static CPU_STK AppTaskStartStk[APP_TASK_START_STK_SIZE];
static CPU_STK TASK_LED1STK[MyTask_LED1_STK_SIZE];
static CPU_STK TASK_LED2STK[MyTask_LED2_STK_SIZE];/* 声明用户任务 */	
static void AppTaskStart  (void *p_arg);
static void MyTask_LED1  (void *p_arg);
static void MyTask_LED2  (void *p_arg);/* USER CODE END PD *//* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM *//* USER CODE END PM *//* Private variables ---------------------------------------------------------*//* USER CODE BEGIN PV */
/* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP *//* USER CODE END PFP *//* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
static void AppTaskStart (void *p_arg)
{CPU_INT32U cpu_clk_freq;CPU_INT32U cnts;OS_ERR  err;(void)p_arg;BSP_Init();CPU_Init();cpu_clk_freq=BSP_CPU_ClkFreq();cnts=cpu_clk_freq/(CPU_INT32U)OSCfg_TickRate_Hz;OS_CPU_SysTickInit(cnts);Mem_Init();#if OS_CFG_STAT_TASK_EN>0uOSStatTaskCPUUsageInit(&err);#endifCPU_IntDisMeasMaxCurReset();OSTaskCreate((OS_TCB *)&MyTask_LED1TCB,                /* Create the start task                                */(CPU_CHAR   *)"LED1",(OS_TASK_PTR ) MyTask_LED1,(void       *) 0,(OS_PRIO     ) MyTask_LED1_PRIO,(CPU_STK    *)&TASK_LED1STK[0],(CPU_STK_SIZE) MyTask_LED1_STK_SIZE/10,(CPU_STK_SIZE) MyTask_LED1_STK_SIZE,(OS_MSG_QTY  ) 0,(OS_TICK     ) 0,(void       *) 0,(OS_OPT      )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),(OS_ERR     *)&err);OSTaskCreate((OS_TCB *)&MyTask_LED2TCB,                /* Create the start task                                */(CPU_CHAR   *)"LED2",(OS_TASK_PTR ) MyTask_LED2,(void       *) 0,(OS_PRIO     ) MyTask_LED2_PRIO,(CPU_STK    *)&TASK_LED2STK[0],(CPU_STK_SIZE) MyTask_LED2_STK_SIZE/10,(CPU_STK_SIZE) MyTask_LED2_STK_SIZE,(OS_MSG_QTY  ) 0,(OS_TICK     ) 0,(void       *) 0,(OS_OPT      )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),(OS_ERR     *)&err);}static void MyTask_LED1(void *p_arg)
{OS_ERR err;(void)p_arg;while(1){OSTimeDlyHMSM(0,0,0,500,OS_OPT_TIME_HMSM_STRICT,&err);HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_8);}
}static void MyTask_LED2(void *p_arg)
{OS_ERR err;(void)p_arg;while(1){OSTimeDlyHMSM(0,0,1,500,OS_OPT_TIME_HMSM_STRICT,&err);HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_9);}
}
/* USER CODE END 0 *//*** @brief  The application entry point.* @retval int*/
int main(void)
{/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();/* USER CODE BEGIN 2 */OS_ERR  err;OSInit(&err);/* 创建任务 */OSTaskCreate((OS_TCB *)&AppTaskStartTCB,                /* Create the start task                                */(CPU_CHAR   *)"App Task Start",(OS_TASK_PTR ) AppTaskStart,(void       *) 0,(OS_PRIO     ) APP_TASK_START_PRIO,(CPU_STK    *)&AppTaskStartStk[0],(CPU_STK_SIZE) APP_TASK_START_STK_SIZE/10,(CPU_STK_SIZE) APP_TASK_START_STK_SIZE,(OS_MSG_QTY  ) 5u,(OS_TICK     ) 0u,(void       *) 0,(OS_OPT      )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),(OS_ERR     *)&err);/* 启动多任务系统,控制权交给uC/OS-III */OSStart(&err);
}/*** @brief System Clock Configuration* @retval None*/
void SystemClock_Config(void)
{RCC_OscInitTypeDef RCC_OscInitStruct = {0};RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};/** Initializes the RCC Oscillators according to the specified parameters* in the RCC_OscInitTypeDef structure.*/RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;RCC_OscInitStruct.HSEState = RCC_HSE_ON;RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;RCC_OscInitStruct.HSIState = RCC_HSI_ON;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){Error_Handler();}/** Initializes the CPU, AHB and APB buses clocks*/RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK){Error_Handler();}
}/* USER CODE BEGIN 4 */
/* USER CODE END 4 *//*** @brief  This function is executed in case of error occurrence.* @retval None*/
void Error_Handler(void)
{/* USER CODE BEGIN Error_Handler_Debug *//* User can add his own implementation to report the HAL error return state */__disable_irq();while (1){}/* USER CODE END Error_Handler_Debug */
}#ifdef  USE_FULL_ASSERT
/*** @brief  Reports the name of the source file and the source line number*         where the assert_param error has occurred.* @param  file: pointer to the source file name* @param  line: assert_param error line source number* @retval None*/
void assert_failed(uint8_t *file, uint32_t line)
{/* USER CODE BEGIN 6 *//* User can add his own implementation to report the file name and line number,ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) *//* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

lib_ cfg.h

加入宏定义:#define LIB_MEM_CFG_HEAP_SIZE 10u * 1024u

 app.c和app.h

app.c:

#include "includes.h"

app.h

// app.h
#ifndef  __APP_H__
#define  __APP_H__#include <includes.h>#endif /* __APP_H__ */

全部配置、修改完成即成功移植,后面可以再根据开发板进行实物验证。

三、总结 

在探索STM32微控制器与uc/OS-III多任务程序的学习过程中,我对嵌入式实时操作系统的运作原理有了更清晰的认识。通过将uc/OS-III移植到STM32F103微控制器上的实践,我深入理解了RTOS如何与特定硬件平台交互。这个过程中,我学会了如何编写多任务程序,并使用uc/OS-III提供的API进行任务管理和通信。除了提升了我的编程技能,这个学习经历还加深了我对实时系统和嵌入式开发的理解。同时对于KEIL、STM32CubeMX的使用也更加熟练,对于遇到的问题也能更好解决。

参考链接:

https://blog.csdn.net/YangMax1/article/details/121617909

https://blog.csdn.net/weixin_46628481/article/details/121561800?spm=1001.2014.3001.5501

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

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

相关文章

三端植物大战僵尸杂交版来了

Hi&#xff0c;好久不见&#xff0c;最近植物大战僵尸杂交版蛮火的 那今天苏音整理给大家三端的植物大战僵尸杂交版包括【苹果端、电脑端、安卓端】 想要下载的直接划到最下方即可下载。 植物大战僵尸&#xff0c;作为一款古老的单机游戏&#xff0c;近期随着B站一位UP主潜艇…

【数据结构初阶】栈和队列

1. 栈 1.1 栈的概念及结构 栈&#xff1a;一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶&#xff0c;另一端称为栈底。栈中的数据元素遵守后进先出LIFO&#xff08;Last In First Out&#xff09;&#xf…

HTML开发 Vue2.x + Element-UI 动态生成表单项并添加表单校验

基于vue2.x 和element-ui 动态生成表单项并添加表单校验&#xff1b; 1、需求问题 如下图&#xff0c;项目有个需求&#xff0c;点击添加按钮&#xff0c;新增一行设备信息&#xff0c;且每项信息必填&#xff1b; 2、代码 看到这个需求&#xff0c;首先想到要使用v-for的形…

springboot集成uid-generator生成分布式id

一、简介 uid-generator是由百度技术部开发,GitHub地址 UidGenerator是Java实现的, 基于Snowflake算法的唯一ID生成器 Snowflake算法 Snowflake算法描述&#xff1a;指定机器 & 同一时刻 & 某一并发序列&#xff0c;是唯一的。据此可生成一个64 bits的唯一ID&#x…

Windows 宿主机访问 VirtualBox 虚拟机中创建的 docker 容器中的 mysql8.0 的数据

一、场景需求 在开发环境中&#xff0c;一般使用 windows 系统进行开发&#xff0c;但需要在 linux 系统中创建运行 mysql8.0 的 docker 容器中进行测试&#xff08;win10特定版本或win11才能安装 docker&#xff09;&#xff0c;为了方便还需要在 windows 系统中通过 SQLyog …

Python轻量级嵌入式关系数据库之apsw使用详解

概要 在现代应用开发中,数据库是一个非常重要的组成部分。SQLite 是一个轻量级的嵌入式关系数据库管理系统,被广泛应用于各种应用程序中。APSW(Another Python SQLite Wrapper)库是一个专门用于访问 SQLite 数据库的 Python 包,它提供了 SQLite 所有的功能,并且比标准库…

【教学类-40-01】20240607类似MJ的免费AI绘画工具——文心一格与通义万相

背景需求&#xff1a; 风变的AI对话大师一年到期了&#xff0c;也没有看到续费的按钮。不能使用它写代码了。 MJ早就用完了&#xff0c;最后480次&#xff0c;我担心信息课题会用到它生图&#xff0c;所以不敢用。 最近探索其他类似MJ的免费出图工具 一、文心一格&#xff08;…

各种空气能热泵安装图

空气能热泵安装图 循环式空气能热泵安装图 直热循环式空气能热泵安装图 泳池空气能热泵安装图 循环式水源热泵热安装系统原理图 直热循环式水源热泵安装系统图 空气水源热泵安装图

XUbuntu24.04之ch9344(usb转串口芯片)安装驱动(二百四十五)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

如何将本地项目上传到GitHub

在软件开发过程中&#xff0c;将本地项目上传到GitHub是一个非常重要的步骤。它不仅可以帮助你备份代码&#xff0c;还可以让你与团队成员共享和协作开发。本文将详细介绍如何将本地项目上传到GitHub。 前提条件 已安装Git。如果还没有安装&#xff0c;请参考Git官网进行下载…

【linux】信号(三)

本章节将会围绕信号处理进行展开讲解 目录 回顾一下&#xff1a;历史问题&#xff1a;地址空间&#xff1a;键盘的输出如何被检测到&#xff1a;持续更新... 回顾一下&#xff1a; 信号处理也就是信号递达 我们说过递达时一种有3种行为 默认行为忽略行为自定义行为 历史问…

JVM之【字节码/Class文件/ClassFile 内容解析】

说在前面的话 字节码/Class文件/ClassFile 均为同一概念 Java语言:跨平台的语言(write once,run anywhere) 当Java源代码成功编译成字节码后&#xff0c;如果想在不同的平台上面运行&#xff0c;则无须再次编译这个优势不再那么吸引人了。Python、PHP、Perl、Ruby、Lisp等有…

28-LINUX--I/O复用-epoll

一.epoll概述 epoll 是 Linux 特有的 I/O 复用函数。它在实现和使用上与 select、poll 有很大差异。首 先&#xff0c;epoll 使用一组函数来完成任务&#xff0c;而不是单个函数。其次&#xff0c;epoll 把用户关心的文件描述 符上的事件放在内核里的一个事件表中。从而无需像…

xshell远程无法链接上VM的centos7

1、现象如下&#xff0c; 2.解决办法&#xff1a;查证后发现这个默认的设置为vmnet0 3.参考文章&#xff1a;Xshell连接不上虚拟机centos7_centos7的nat模式可以ping通网络,但是用xshell连不上是什么原因-CSDN博客

QT C++(QT控件 QPushButton,QRadioButton,QCheckBox)

文章目录 1. QPushButton 普通按钮2. QRadioButton 单选按钮3. QCheckBox 复选按钮 1. QPushButton 普通按钮 QPushButton中的重要属性 text&#xff1a;按钮中的文本icon&#xff1a;按钮的图标iconSize&#xff1a;按钮中图标的尺寸shortCut&#xff1a;按钮对应的快捷键&a…

STM32编程:实现LED灯闪烁(基于手写SDK的方式)

项目结构 stm32f10x.h 文件 //寄存器的值常常是芯片外设自动更改的&#xff0c;即使CPU没有执行程序&#xff0c;也有可能发生变化 //编译器有可能会对没有执行程序的变量进行优化//volatile表示易变的变量&#xff0c;防止编译器优化&#xff0c; #define __IO volati…

53.ReentrantLock原理

ReentrantLock使用 ReentrantLock 实现了Lock接口&#xff0c; 内置了Sync同步器继承了AbstractQueuedSynchronizer。 Sync是抽象类&#xff0c;有两个实现NonfairSync非公平&#xff0c;FairSync公平。 所以ReentrantLock有公平锁和非公平锁。默认是非公平锁。 public sta…

我的编程语言学习记录:一段不断探索的旅程

目录 我的编程语言学习记录&#xff1a;一段不断探索的旅程 1.引言 2.我的编程之旅开始 第一站&#xff1a;Python — 简洁之美 第二站&#xff1a;JavaScript — 网页的魔法 第三站&#xff1a;Java — 企业级的力量 3.学习过程中的挑战与克服 1.理解概念 3.记忆语法…

读书笔记:左耳听风

程序员如何用技术变现 我完全没有必要通过打工听人安排而活着&#xff0c;而是反过来通过在公司工作提高自己的技能&#xff0c;让自己可以更为独立和自由地生活。 因而&#xff0c;在工作当中&#xff0c;对于那些没什么技术含量的工作&#xff0c;我基本上就像是在学生时代那…