【STM32开发】-FreeRTOS开发入手学习

一、什么是FreeRTOS?

        FreeRTOS 是 RTOS 系统的一种,FreeRTOS 十分的小巧,可以在资源有限的微控制器中运行;

        1、 FreeRTOS是免费的。

        2、许多其他半导体厂商产品的 SDK 包就使用 FreeRTOS 作为其操作系统,尤其是 WIFI、
蓝牙这些带协议栈的芯片或模块。

        3、FreeRTOS 被移植到了很多不同的微处理器上。

        4、FreeRTOS 的内核支持抢占式,合作式和时间片调度。

        5、FreeRTOS 系统简单、小巧、易用,通常情况下内核占用 4k-9k 字节的空间。

二、FreeRTOS移植

1、创建基础文件,添加FreeRTOS源码

        

  portable 文件夹,需要留下 keil、MemMang 和 RVDS这三个文件夹:

最后创建基础工程,新建分组 FreeRTOS_CORE 和 FreeRTOS_PORTABLE:

2、修改SYSTEM文件

①修改sys.h文件

在 sys.h 文件里面用宏 SYSTEM_SUPPORT_OS 来定义是否使用 OS,我们使用了 FreeRTOS

#define SYSTEM_SUPPORT_OS    1    //定义系统文件夹是否支持 OS

②修改usart.c文件

添加 FreeRTOS.h 头文件:

#include "FreeRTOS.h"    //os 使用

使用 FreeRTOS 不需要OSIntEnter()和 OSIntExit()中断函数,将对应的代码删除:

void USART1_IRQHandler(void)                	
{u8 Res;if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {Res =USART_ReceiveData(USART1);	if((USART_RX_STA&0x8000)==0){if(USART_RX_STA&0x4000){if(Res!=0x0a)USART_RX_STA=0;else USART_RX_STA|=0x8000;	 }else {	if(Res==0x0d)USART_RX_STA|=0x4000;else{USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;USART_RX_STA++;if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;	  }		 }}   		 } 
} 

3、修改delay.c文件

//systick 中断服务函数,使用 OS 时用到
void SysTick_Handler(void)
{
if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//系统已经运行
{
xPortSysTickHandler();
}
//初始化延迟函数
//SYSTICK 的时钟固定为 AHB 时钟,基础例程里面 SYSTICK 时钟频率为 AHB/8
//SYSCLK:系统时钟频率
{ void delay_init()
u32 reload;
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);//选择外部时钟 HCLK
fac_us=SystemCoreClock/1000000;
//不论是否使用 OS,fac_us 都需要使用
reload=SystemCoreClock/1000000;
//每秒钟的计数次数 单位为 M
reload*=1000000/configTICK_RATE_HZ;
//根据 configTICK_RATE_HZ 设定溢出
//时间 reload 为 24 位寄存器,最大值:
//16777216,在 72M 下,约合 0.233s 左右
fac_ms=1000/configTICK_RATE_HZ;
//代表 OS 可以延时的最少单位
SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk; //开启 SYSTICK 中断
SysTick->LOAD=reload;
//每 1/configTICK_RATE_HZ 秒中断
//一次
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk; //开启 SYSTICK
}

修改延时函数:

//延时 nus
//nus:要延时的 us 数.
//nus:0~204522252(最大值即 2^32/fac_us@fac_us=168)
void delay_us(u32 nus)
{u32 ticks;u32 told,tnow,tcnt=0;u32 reload=SysTick->LOAD;    //LOAD 的值ticks=nus*fac_us;//需要的节拍数told=SysTick->VAL;//刚进入时的计数器值while(1){tnow=SysTick->VAL;if(tnow!=told){//这里注意一下 SYSTICK 是一个递减的计数器就可以了.if(tnow<told)tcnt+=told-tnow;else tcnt+=reload-tnow+told;told=tnow;if(tcnt>=ticks)break;//时间超过/等于要延迟的时间,则退出.}};
}
/延时 nms,会引起任务调度
//nms:要延时的 ms 数
//nms:0~65535
void delay_ms(u32 nms)
{if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//系统已经运行{if(nms>=fac_ms)//延时的时间大于 OS 的最少时间周期{vTaskDelay(nms/fac_ms);//FreeRTOS 延时}nms%=fac_ms;//OS 已经无法提供这么小的延时了,//采用普通方式延时}delay_us((u32)(nms*1000));//普通方式延时
}
//延时 nms,不会引起任务调度
//nms:要延时的 ms 数
void delay_xms(u32 nms)
{u32 i;for(i=0;i<nms;i++) delay_us(1000);
}

修改完编译。

三、关于FreeRTOS 任务

        RTOS 系统的核心就是任务管理。

1、创建任务

使用函数 xTaskCreate()或 xTaskCreateStatic()来创建任务,

任务模版:

void vATaskFunction(void *pvParameters)
{
for( ; ; )
{--任务应用程序--vTaskDelay();
}
/* 不 能 从 任 务 函 数 中 返 回 或 者 退 出 , 从 任 务 函 数 中 返 回 或 退 出 的 话 就 会 调 用
configASSERT(),前提是你定义了 configASSERT()。如果一定要从任务函数中退出的话那一定
要调用函数 vTaskDelete(NULL)来删除此任务。*/vTaskDelete(NULL);
}

常用函数:

1、xTaxkCreate()函数

BaseType_t xTaskCreate(TaskFunction_t        pxTaskCode,const char * const    pcName,const uint16_t        usStackDepth,void * const          pvParameters,UBaseType_t           uxPriority,TaskHandle_t * const  pxCreatedTask )

参数:
pxTaskCode:任务函数。
pcName:任务名字,一般用于追踪和调试,任务名字长度不能超过。
                configMAX_TASK_NAME_LEN。
usStackDepth:任务堆栈大小,注意实际申请到的堆栈是 usStackDepth 的 4 倍。其中空闲任
务的任务堆栈大小为 configMINIMAL_STACK_SIZE。
pvParameters:传递给任务函数的参数。
uxPriotiry:任务优先级,范围 0~ configMAX_PRIORITIES-1。
pxCreatedTask: 任务句柄,任务创建成功以后会返回此任务的任务句柄,这个句柄其实就是
                          任务的任务堆栈。此参数就用来保存这个任务句柄。其他 API 函数可能会使用                           到这个句柄。
返回值:
pdPASS:        任务创建成功。
errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY: 任务创建失败,因为堆内存不足!

2、xTaskCreateStatic()函数

TaskHandle_t xTaskCreateStatic( TaskFunction_t        pxTaskCode,const char * const    pcName,const uint32_t        ulStackDepth,void * const          pvParameters,UBaseType_t           uxPriority,StackType_t * const   puxStackBuffer,StaticTask_t * const  pxTaskBuffer )

参数:
pxTaskCode:任务函数。
pcName:任务名字,一般用于追踪和调试,任务名字长度不能超过。
                configMAX_TASK_NAME_LEN。
usStackDepth:任务堆栈大小,由于本函数是静态方法创建任务,所以任务堆栈由用户给出,
                        一般是个数组,此参数就是这个数组的大小。
pvParameters:传递给任务函数的参数。
uxPriotiry:任务优先级,范围 0~ configMAX_PRIORITIES-1。
puxStackBuffer: 任务堆栈,一般为数组,数组类型要为 StackType_t 类型。
pxTaskBuffer:任务控制块。
返回值:
NULL:
任务创建失败,puxStackBuffer 或 pxTaskBuffer 为 NULL 的时候会导致这个错误的发生。
其他值:
任务创建成功,返回任务的任务句柄。

3、 xTaskCreateRestricted()函数

BaseType_t xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition,TaskHandle_t *               pxCreatedTask )

 参数:
pxTaskDefinition:指向一个结构体 TaskParameters_t,这个结构体描述了任务的任务函数、
                        堆栈大小、优先级等。此结构体在文件 task.h 中有定义。
pxCreatedTask:任务句柄。
返回值:
pdPASS:任务创建成功。
其他值:任务未创建成功,很有可能是因为 FreeRTOS 的堆太小了

4、  vTaskDelete()函数

vTaskDelete( TaskHandle_t xTaskToDelete )
参数:
xTaskToDelete:要删除的任务的任务句柄。
返回值:

四、FreeRTOS列表和列表项

1、什么是列表?

列表概念上和链表很相似,列表用来跟踪FreeRTOS中的任务。与列表相关的全部东西都在文件list.c 和 list.h 中。结构体如下:

typedef struct xLIST
{listFIRST_LIST_INTEGRITY_CHECK_VALUEconfigLIST_VOLATILE UBaseType_t    uxNumberOfItems;ListItem_t * configLIST_VOLATILE   pxIndex;MiniListItem_t                     xListEnd;listSECOND_LIST_INTEGRITY_CHECK_VALUE
} List_t;

2、列表项

列表项就是存放在列表中的项目,FreeRTOS 提供了两种列表项:列表项和迷你列表项。

struct xLIST_ITEM
{listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUEconfigLIST_VOLATILE TickType_t            xItemValue;struct xLIST_ITEM * configLIST_VOLATILE   pxNext;struct xLIST_ITEM * configLIST_VOLATILE   pxPrevious;void *                                    pvOwner;void * configLIST_VOLATILE                pvContainer;listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE
};
typedef struct xLIST_ITEM ListItem_t;

3、迷你列表项

struct xMINI_LIST_ITEM
{listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUEconfigLIST_VOLATILE TickType_t        xItemValue;struct xLIST_ITEM * configLIST_VOLATILE pxNext;struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;
};
typedef struct xMINI_LIST_ITEM MiniListItem_t;

其他初始化看管方文档。

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

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

相关文章

【软考】系统分析师第二版 新增章节 第20章微服务系统分析与设计

微服务系统是一类基于微服务架构风格的分布式系统&#xff0c;它将应用程序拆分成多个独立的小型服务&#xff0c;每个服务都运行在独立的进程中&#xff0c;并采用轻量级通信协议进行通信。这些服务可以由不同的团队开发、不同的编程语言编写&#xff0c;并且可以按需部署。微…

【笔记】自动驾驶预测与决策规划_Part6_不确定性感知的决策过程

文章目录 0. 前言1. 部分观测的马尔可夫决策过程1.1 POMDP的思想以及与MDP的联系1.1.1 MDP的过程回顾1.1.2 POMDP定义1.1.3 与MDP的联系及区别POMDP 视角MDP 视角决策次数对最优解的影响 1.2 POMDP的3种常规解法1.2.1 连续状态的“Belief MDP”方法1. 信念状态的定义2. Belief …

【SpringBoot】 黑马大事件笔记-day2

目录 用户部分 实体类属性的参数校验 更新用户密码 文章部分 规定josn日期输出格式 分组校验 上期回顾&#xff1a;【SpringBoot】 黑马大事件笔记-day1 用户部分 实体类属性的参数校验 对应的接口文档&#xff1a; 基本信息 请求路径&#xff1a;/user/update 请求方式&#…

HarmonyOS入门 : 获取网络数据,并渲染到界面上

1. 环境搭建 开发HarmonyOS需要安装DevEco Studio&#xff0c;下载地址 : https://developer.huawei.com/consumer/cn/deveco-studio/ 2. 如何入门 入门HarmonyOS我们可以从一个实际的小例子入手&#xff0c;比如获取网络数据&#xff0c;并将其渲染到界面上。 本文就是基于…

AndroidStudio-视图基础

一、设置视图的宽高 1.在XML文件中设置视图宽高 视图宽度通过属性android:layout_width表达&#xff0c;视图高度通过属性android:layout_height表达&#xff0c;宽高的取值主要有下列三种: &#xff08;1&#xff09;wrap_content:表示与内容自适应。对于文本视图来说&…

三菱QD77MS定位模块紧急停止功能

“紧急停止功能” 是通过简单运动模块的外部输入连接用连接器上连接的紧急停止输入&#xff0c;对同服放大器的全部轴进行批量停止的功能。(初始值为“0:有效”。)通过“[r.82]紧急停止有效/无效设置”可以选择紧急停止输入的有效/无效。 [1]控制内容 将“[r82]紧急停止有效/无…

Android JNI 技术入门指南

引言 在Android开发中&#xff0c;Java是一种主要的编程语言&#xff0c;然而&#xff0c;对于一些性能要求较高的场景&#xff08;如音视频处理、图像处理、计算密集型任务等&#xff09;&#xff0c;我们可能需要使用到C或C等语言来编写底层的高效代码。为了实现Java代码与C…

Js — 定时器

有两种&#xff1a;setInterval 和 setTimeout 间隔时间单位为毫秒 setInterval 每隔指定的毫秒数重复执行一个函数或代码 开启定时器&#xff1a;setInterval(函数&#xff0c;间隔时间) 作用&#xff1a;每隔一段时间调用这个函数 注意&#xff1a;它不是立即执行&#x…

H5播放器EasyPlayer.js 流媒体播放器是否支持npm(yarn) install 安装?

EasyPlayer.js H5播放器是一款功能强大的H5视频播放器&#xff0c;它支持多种流媒体协议播放&#xff0c;包括WebSocket-FLV、HTTP-FLV、HLS&#xff08;m3u8&#xff09;、WebRTC等格式的视频流。它不仅支持H.264和H.265编码格式&#xff0c;还具备实时录像、低延时直播等功能…

前端刺客系列----Vue 3 入门介绍

目录 一.什么是 Vue 3&#xff1f; 二.Vue 3 的主要特性 三,Vue3项目实战 四.总结 在前端开发的世界里&#xff0c;Vue.js 作为一款渐进式的 JavaScript 框架&#xff0c;已成为许多开发者的首选工具。自从 Vue 3 发布以来&#xff0c;它带来了许多重要的改进和新特性&…

【论文复现】MSA+抑郁症模型总结(三)

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀MSA抑郁症模型 热门研究领域&#xff1a;情感计算的横向发展1. 概述2. 论文地址3. 研究背景4. 主要贡献5. 模型结构和代码6. 数据集介绍7. 性…

Linux 实验:日志的备份与恢复 xfs文件系统

添加一个新的硬盘&#xff0c;创建硬盘分区sdc1 设置文件系统格式xfs&#xff0c;提示安装xfsprogs&#xff0c;如果安装失败&#xff0c;在后缀加上--fix-missing直到安装完成为止 mkdir创建空目录data&#xff0c;将sdc1挂载到data&#xff0c;data是根目录下新建的目录&…

应对AI与机器学习的安全与授权管理新挑战,CodeMeter不断创新引领保护方案

人工智能&#xff08;AI&#xff09;和机器学习&#xff08;ML&#xff09;技术正在快速发展&#xff0c;逐渐应用到全球各类主流系统、设备及关键应用场景中&#xff0c;尤其是在政府、商业和工业组织不断加深互联的情况下&#xff0c;AI和ML技术的影响日益广泛。虽然AI技术的…

证书学习(六)TSA 时间戳服务器原理 + 7 个免费时间戳服务器地址

目录 一、简介1.1 什么是时间戳服务器1.2 名词扩展1.3 用时间戳标记顺序1.4 7 个免费TSA时间戳服务器地址(亲测可用)1.5 RFC 3161 标准二、时间戳原理2.1 时间戳服务工作流程2.2 验证工作流程2.3 举个例子2.4 时间戳原理总结三、代码实现3.1 curl 命令请求时间戳3.2 java 代码…

一文快速预览经典深度学习模型(一)——CNN、RNN、LSTM、Transformer、ViT

Hi&#xff0c;大家好&#xff0c;我是半亩花海。本文主要简要并通俗地介绍了几种经典的深度学习模型&#xff0c;如CNN、RNN、LSTM、Transformer、ViT&#xff08;Vision Transformer&#xff09;等&#xff0c;便于大家初探深度学习的相关知识&#xff0c;并更好地理解深度学…

如何运营Github Org

目录 前言 正文 关于分支保护 特别说明 如何在Windows环境下配置GitHub Desktop GPG签名&#xff1f; 推荐分支保护选择 关于good first issue 如何设置good first issue&#xff1f; 关于Project 尾声 &#x1f52d; Hi,I’m Pleasure1234&#x1f331; I’m currently learni…

接收nVisual中rabbitmq数据不成功问题排查

rabbitmq服务部署成功的情况下&#xff0c;消息对接不成功一般原因为消息发送失败&#xff0c;发送失败大多数可能为global_settings表配置错误。下面从两个方面解决消息对接不成功问题。 1.数据是否成功发送 检查global_settings表中rabbitmq发送消息配置信息是否正确 #MQS…

二叉树的实现

一.树 1.1树的概念与结构 树是一种非线性数据结构&#xff0c;由有限个结点组成的具有层次关系的集合。树的根部位置就叫根结点&#xff0c;除根结点以外&#xff0c;其余的树被分为各个互不相交的集合。树的根系只能向下延伸不能向左右延伸。除根结点以外每个结点有且仅有一…

Python基础学习-03逻辑分支语句、循环

目录 1、记住逻辑关系 2、逻辑分支语句 3、for-loop循环 4、while-loop 5、break 和 continue 6、本节总结 1、记住逻辑关系 • 逻辑关系 1&#xff09; True&#xff08;真&#xff09; 和 False&#xff08;假&#xff09; 2&#xff09;逻辑关系有 and&#xff08;与…

Spark中给读取到的数据 的列 重命名的几种方式!

目录 一、第一种 (withColumnRenamed) 二、第二种&#xff08;toDF&#xff09; 三、第三种&#xff08; toDF(*tuple1) &#xff09; 四、 第四种(schema) 五、假如文件里自带有列名的情况&#xff08;option&#xff09; 一、第一种 (withColumnRenamed) 假设要把如下…