01 FreeRTOS 初识

1、freeRTOS

1.1 什么是FreeRTOS

        Free就是免费的,RTOS全称是real time operating system,即实时操作系统。FreeRTOS是一个迷你的实时操作系统内核,作为一个轻量级的操作系统,功能包括:任务管理、时间管理、信号量、消息队列、内存管理、记录功能、软件定时器、协程等,可满足较小系统的需要。

        严格上来说,FreeRTOS并不是一个实时操作系统,因为它是分时复用的,系统将时间分割成很多时间片,然后轮流执行各个任务。每个任务都是独立运行的,互不影响,由于切块的频率很快,感觉就像是同时运行的一样。

1.2 为什么选择FreeRTOS

        第一是其是免费的,源码公开,具有可移植。可裁剪。调度灵活等特点,可以方便地移植到各种单片机上运行;其二是很多半导体厂商产品的SDk(Software Development Kit)软件开发工具包,就是使用FreeRTOS作为其操作系统,尤其是WIFI、蓝牙这些带有协议栈的芯片或模块;其三是因为FreeRTOS的文件数量很少,移植简单。

1.3 FreeRTOS资料与源码下载

        最好的地方就是官网:FreeRTOS - Market leading RTOS (Real Time Operating System) for embedded systems with Internet of Things extensions

2、堆/栈

2.1 堆

        堆就是一块空闲的内存,我们可以管理这块内存,从这块内存中取出一部分使用,使用完再释放回去。

//heap_buf就是我们开辟的堆
char heap_buf[1024];
int pos = 0;

void *my_malloc(int size)
{
	int old_pos = pos;
	pos += size;
	return &heap_buf[old_pos];
}

void my_free(void *buf)
{
	/* err */
}

int main(void)
{
	char ch = 65; // char ch = 'A';
	int i;
	char *buf = my_malloc(100);
	
	unsigned char uch = 200;
	
	for (i = 0; i < 26; i++)
		buf[i] = 'A' + i;
	
	
	return 0;
}

2.2 栈

        在编写代码中,我们可能感觉不到栈的存在,但是它确实一直在默默存在。

void c_fun(void)
{
}


void b_fun(void)
{
}


int a_fun(int val)
{
	int a = 8;
	a += val;
	
	b_fun();
	
	c_fun();
	
	return a;
}


int main(void)
{
	
	a_fun(46);
	
	return 0;
}

        在上面的程序中,main函数调用了a_fun,在a_fun中调用了b_fun和c_fun。main函数在调用a_fun之前,会将返回的地址保存在LR(Link Register)中,然后调用a_fun,在main中返回的地址就是return 0语句所在的位置。

        a_fun函数在调用b_fun和c_fun时也是类似的,在调用之前要先将返回的地址保存在LR(Link Register)中,然后去调用,而在a_fun中调用b_fun的返回地址是c_fun所在的语句。那么此时main和a_fun函数的返回值的地址都保存在LR中,LR会不会被覆盖了?

        在a_fun函数内部,它会将LR的值存入栈中,然后再来保存本身的返回值地址,这样就不怕LR会被覆盖了,因此函数返回值的地址是被存入栈中的。栈也是一块空闲的内存。在main函数执行时,它会给main函数开辟一部分的栈空间,里面存放LR等寄存器和局部变量的值。

2.3 堆和栈的区别

        管理方式不同:栈由操作系统自动分配释放,无需我们手动控制;堆的申请和释放工作由程序员控制,容易产生内存泄漏。

        分配方式不同:堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。

        空间大小不同:栈的大小要远远小于堆的大小。

        生长方向不同:堆的生长方向向上,内存地址由低到高;栈的生长方向向下,内存地址由高到低。

        数据结构不同:堆可以看成一棵树,如堆排序;栈是一种先进后出的结构。

        作用域的不同:堆的作用域是在全局,栈的作用域是在函数局部。

3、从官方源码精简出第一个freeRTOS

3.1 从官网下载

FreeRTOS - Free RTOS Source Code Downloads, the official FreeRTOS zip file release download

解压之后打开的目录

        FreeRTOS-Plus里面是FreeRTOS生态的文件,非必需,tools里面是亚马逊相关的文件,也不需要。文件夹只需要保留FreeRTOS。

        进入FreeRTOS-Demo文件夹,选择我们的目标文件夹,例如CORTEX_STM32F103_Keil,其余的就可以删掉了,在Demo中的文件夹的命名规则是指令集+芯片+编译器或者芯片+编译器。

        在FreeRTOS-Source文件夹中,里面的目录结构如下所示,在portable文件夹中,我们保留RVDS和MemMang,这里的命名规则是编译器/架构,在RVDS文件夹中,我们可以只保存ARM_CM3。

        至此,从官网下载的文件中,我们暂时不需要的文件都已经清除,文件大小从455MB降到了8.28MB。

3.2 打开工程

        这个工程是用Keil4来编写的,我们要将其更新成Keil5

        点击 Migrate to Device Pack 即可,更新完之后关掉再重新打开。

        打开之后会出现一些错误,然后根据提示更改。嫌麻烦可以将FreeRTOS-Demo中的Common文件夹保留,就不会报错了。

3.3 添加串口打印功能

3.3.1 去掉无关的代码

        System中的lcd.c,Demo files中的ParTest.c timertest.c spi_test.c semtest.c BlockQ.c blocktim.c comtest.c death.c flash.c integer.c  PollQ.c

        然后编译,根据错误提示,来进行修改。

3.3.2 添加串口打印功能

        第一步要初始化串口

        第二步要实现fputc功能,因为printf函数是标准库写好的,里面用到了fputc函数,我们要用串口将其打印出来就要对其进行改写。

3.3.3 使用Keil自带模拟器运行

        点击魔法棒-Debug,勾选Use Simulator

        然后点击debug,运行查看结果。

4、自己的第一个freeRTOS程序

4.1 创建两个打印任务

//参数:
    //函数指针,任务函数
    //任务的名字
    //栈大小,单位为word,10代表40字节
    //调用任务函数时传入的参数
    //优先级
    //任务句柄,以后使用它来操作这个函数
BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
                            const char * const pcName, 
                            const configSTACK_DEPTH_TYPE usStackDepth,
                            void * const pvParameters,
                            UBaseType_t uxPriority,
                            TaskHandle_t * const pxCreatedTask )
//关键代码
void Task1Function( void * param)
{
	while(1){
		printf("1");
	}
}

void Task2Function( void * param)
{
	while(1){
		printf("2");
	}
}


xTaskCreate(Task1Function, "Task1", 100, NULL, 1, &xHandleTask1);
xTaskCreate(Task2Function, "Task2", 100, NULL, 1, NULL);    //这样写也可以

        该程序运行结果会发现1和2交替打印。       

        既可以仿真查看结果,也可以上传到开发板查看结果。

        在开发板上直接调试,要保证开发板上电,开发板要连接调试器,并且在Keil中要选择真实的调试器。

        如果在keil中无法在源文件中设置断点,要确保调试器接好,并且将(魔术棒-Debug-调试器Settings-Debug)Debug中的“Verify Code Download”和“Download to flash”去掉勾选。

        如果要在keil中重新使用模拟器运行代码,要在Device中选择模拟的设备,Debug中选择“Use Simulator”,指定DLL:DARMSTM.DLL,指定参数:-STM32Fxxxx

4.2 freeRTOS源码结构

        以Keil工具下STM32F103芯片为例,它的FreeRTOS的目录如下:

        主要涉及2个目录:

                Demo:

                        Demo目录下是工程文件,以"芯片和编译器"组合成一个名字,比如:CORTEX_STM32F103_Keil

                Source:

                        根目录下是核心文件,这些文件是通用的

                        portable目录下是移植时需要实现的文件

                                目录名为:[compiler]/[architecture]

                                比如:RVDS/ARM_CM3,这表示cortexM3架构在RVDS工具上的移植文件

4.2.1 核心文件

        freeRTOS的最核心文件只有两个:

                FreeRTOS/Source/task.c

                FreeRTOS/Source/list.c

                其它文件的作用:

FreeRTOS/Source/下的文件作用
task.c必需,任务操作
list.c必需,列表操作
queue.c基本必需,提供队列操作、信号量(semaphore)操作
timer.c可选,software timer
event_groups.c可选,提供event group功能
croutine.c可选,过时了

4.2.2 移植时涉及的文件

        移植FreeRTOS时涉及的文件放在FreeRToS/Source/portable/[compiler]/[architecture]目录下,比如:RVDS/ARM_CM3,这表示cortexM3架构在RVDS或Keil工具上的移植文件。

        里面有两个文件:port.c和portmacro.h

4.2.3 头文件相关

        FreeRTOS需要3个头文件目录:

                FreeRTOS本身的头文件:FreeRTOS/Source/linclude

                移植时用到的头文件:FreeRTOS/Source/portable/[compiler]/[architecture]

                含有配置文件FreeRTOSConfig.h的目录(Demo/目标文件夹)

        头文件列表:

头文件作用
FreeRTOSConfig.h
FreeRTOS 的配置文件,比如选择调度算法: configUSE_PREEMPTION
每个 demo 都必定含有 FreeRTOSConfig.h
建议去修改 demo 中的 FreeRTOSConfig.h ,而不是从头写一个
FreeRTOS.h
使用 FreeRTOS API 函数时,必须包含此文件。
FreeRTOS.h 之后,再去包含其他头文件,比如:
task.h queue.h semphr.h event_group.h

4.2.4 内存管理

        文件在FreeRTOS/Source/portable/MemMang下,它也是放在portable目录下,表示你可以提供自己的函数。

        源码中默认提供了5个文件,对应内存管理的5种方法:

文件优点缺点
heap_1.c
分配简单,时间确定
只分配、不回收
heap_2.c
动态分配、最佳匹配
碎片、时间不定
heap_3.c
调用标准库函数
速度慢、时间不定
heap_4.c
相邻空闲内存可合并
可解决碎片问题、时间不定
heap_5.c
heap_4 基础上支持分隔的内存块
可解决碎片问题、时间不定

4.2.5 Demo

        Demo目录下是预先配置好的、没有编译错误的工程。目的是让你可以基于它进行修改,以适配你的单板。

        这些Demo还可以继续精简:

                Demo/ common中的文件可以完全删除

                main函数中只需要保留2个函数:

                        prvSetupHardware()

                        vTaskStartScheduler()

                        如下图所示:


4.3 freeRTOS数据类型和编程规范

4.3.1 数据类型

        每个移植的版本都含有自己的portmacro.h头文件,里面定义了2个数据类型:

        TickType_t:

                FreeRTOS配置了一个周期性的时钟中断:Tick Interrupt

                每发生一次中断,中断次数累加,这被称为tick counto

                tick count这个变量的类型就是TickType_t

                TickType_t可以是16位的,也可以是32位的

                FreeRTOSConfig.h中定义configUSE_16_BIT_TICKS时,TickType_t就是uint16_t

                否则TickType_t就是uint32_t

                对于32位架构,建议把TickType_t配置为uint32_t

        BaseType_t:

                这是该架构最高效的数据类型

                32位架构中,它就是uint32_t

                16位架构中,它就是uint16_t

                8位架构中,它就是uint8_t

                BaseType_t通常用作简单的返回值的类型,还有逻辑值,比如pdTRUE/pdFALSE

4.3.2 变量名

        在FreeRTOS的源码中,其变量名通常带有小写字母的前缀:

变量名前缀
含义
c
char
s
int16_t short
l
int32_t long
x
BaseType_t
其他非标准的类型:结构体、 task handle queue handle
u
unsigned
p
指针
uc
uint8_t unsigned char
pc
char 指针

4.3.3 函数名

        在FreeRTOS的源码中,函数名的前缀有2部分:返回值类型、在哪个文件定义。

函数名前缀
含义
vTaskPrioritySet
返回值类型: void
task.c 中定义
xQueueReceive
返回值类型: BaseType_t
queue.c 中定义
pvTimerGetTimerID
返回值类型: pointer to void
tmer.c 中定义

4.3.2 宏的名

        在FreeRTOS的源码中,宏的名字是大小,可以添加小写的前缀。前缀是用来表示:宏在哪个文件中定义。

宏的前缀
含义:在哪个文件里定义
port ( 比如 portMAX_DELAY)
portable.h portmacro.h
task ( 比如 taskENTER_CRITICAL())
task.h
pd ( 比如 pdTRUE)
projdefs.h
config ( 比如 configUSE_PREEMPTION)
FreeRTOSConfig.h
err ( 比如 errQUEUE_FULL)
projdefs.h

        通用的宏定义:

pdTRUE
1
pdFALSE
0
pdPASS
1
pdFAIL
0



 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【AI基础】反向传播

文章目录 1. 先写出第一步2.将其封装成函数3. pytorch版 1. 先写出第一步 # 定义输入值和期望输出 x_1 40.0 x_2 80.0 expected_output 60.0 初始化# 定义权重 w_1_11 0.5 w_1_12 0.5 w_1_13 0.5 w_1_21 0.5 w_1_22 0.5 w_1_23 0.5w_2_11 1.0 w_2_21 1.0 w_2_31 1…

RocketMQ实战教程之RocketMQ安装(含Docker安装,建议收藏!)

RocketMQ实战教程之RocketMQ安装 这里实例采用centos系统天翼云为例,分别采用传统安装以及Docker安装的方式来进行RocketMQ的安装.JDK8我这边已经安装配置好了,这里就不在赘述.直接进入正题: 传统安装包安装 系统要求 64位操作系统&#xff0c;推荐 Linux/Unix/macOS64位 JDK…

Java 对外API接口开发 java开发api接口如何编写

Java API API&#xff08;Application Programming Interface&#xff09;是指应用程序编程接口&#xff0c;的JavaAPI是指JDK提供的各种功能的Java类 String类 String类的初始化&#xff1a; &#xff08;1&#xff09;使用字符串常量直接初始化 初始化&#xff1a;String s…

第11章 集合与迭代器

目录 目录 目录 11.1 Collection集合 11.1.1 集合的概念 11.1.2 Collection接口 1、添加元素 2、删除元素 3、查询与获取元素 11.2 List 有序集合 11.2.1 新增方法 11.2.2 ArrayList 11.2.3 LinkedList 1、单向链表 2、双向链表 3、删除元素 11.3 Set 无序集合 …

深度学习-转置卷积

转置卷积 转置卷积&#xff08;Transposed Convolution&#xff09;&#xff0c;也被称为反卷积&#xff08;Deconvolution&#xff09;&#xff0c;是深度学习中的一种操作&#xff0c;特别是在卷积神经网络&#xff08;CNN&#xff09;中。它可以将一个低维度的特征图&#x…

深入 Rust 标准库,Rust标准库源代码系统分析

系列文章目录 送书第一期 《用户画像&#xff1a;平台构建与业务实践》 送书活动之抽奖工具的打造 《获取博客评论用户抽取幸运中奖者》 送书第二期 《Spring Cloud Alibaba核心技术与实战案例》 送书第三期 《深入浅出Java虚拟机》 送书第四期 《AI时代项目经理成长之道》 …

智能猫眼锁核心解决方案以及芯片简介SSD222

书接上回&#xff0c;前篇文章我们诠释了IP 网络摄像系统的定义以及组成部分的功能&#xff0c;也大概的讲了一下所针对的市场以及举例介绍了一款相关芯片&#xff0c;详情可点击下面卡片浏览高集成IP摄像SOC处理方案简介https://blog.csdn.net/Chipsupply/article/details/139…

PDF Reader Pro for Mac 直装激活版:专业PDF阅读编辑软件

在数字化时代&#xff0c;PDF文件已成为我们日常工作和学习中不可或缺的一部分。然而&#xff0c;如何高效、便捷地阅读、编辑和管理这些PDF文件&#xff0c;却一直是许多人面临的难题。现在&#xff0c;有了PDF Reader Pro for Mac&#xff0c;这些难题将迎刃而解。 PDF Reade…

谷歌快速收录怎么做?

快速收录顾名思义&#xff0c;就是让新的的网页内容能够迅速被谷歌搜索引擎抓取、索引和显示在搜索结果中&#xff0c;这对于做seo来说非常重要&#xff0c;因为它有助于新发布的内容尽快出现在谷歌的搜索结果中&#xff0c;从而增加网站的流量 想做谷歌快速收录谷歌推荐了几种…

AD162A低功耗语音解码芯片,助眠耳机方案推荐—云信通讯

睡眠一直是很多人所追寻的目标&#xff0c;无论是因为工作压力过大&#xff0c;还是日常烦扰的思绪&#xff0c;一个好的睡眠质量对每个人来说都至关重要。为了解决这个问题&#xff0c;一些科技公司开发了高品质的助眠耳机&#xff0c;通过音乐和声音来帮助入睡&#xff0c;为…

华为大咖说 | 企业应用AI大模型的“道、法、术” ——道:认知篇

本文作者&#xff1a;郑岩&#xff08;华为云AI变革首席专家&#xff09;全文约3313字&#xff0c;阅读约需8分钟&#xff0c;请仔细看看哦~ 前阵子&#xff0c;我在公司内部发了一篇Sora的科普贴&#xff0c;本来只是个简单的技术总结&#xff0c;但让我意外的是&#xff0c;…

linux系统安全加固

目录 1、账户安全基本措施 1&#xff09;系统账户清理 2&#xff09;密码安全控制 3&#xff09;命令历史限制 2、用户切换及提权 1&#xff09;使用 su命令切换用户 2&#xff09;使用sudo机制提升权限 3、系统引导和安全登录控制 1&#xff09;开机安全控制 2&…

docker如何拉取nginx最新镜像并运行

要拉取Docker Hub上的最新Nginx镜像&#xff0c;您可以使用以下命令&#xff1a; docker pull nginx 这个命令会从Docker Hub下载最新版本的Nginx镜像。如果您想要拉取特定版本的Nginx镜像&#xff0c;可以指定版本号&#xff0c;例如&#xff1a; docker pull nginx:1.18.0 拉…

实在智能签约世界机械500强特变电工 ,加速能源装备巨头智能化升级

近日&#xff0c;世界机械500强、中国企业500强特变电工集团正式与实在智能达成战略合作&#xff0c;由实在智能为其部署RPA数字员工解决方案&#xff0c;助力集团公司各级财务部门提升自动化水平&#xff0c;进一步实现集团内降本增效目标。 关于特变电工 特变电工是国家级高…

AI工具推荐:提升工作效率与生活质量

有哪些好用&#xff0c;且国内可用的AI工具&#xff1f; 副本 在AI大发展的年代&#xff0c;还有人在工作、生活中没有使用过AI吗&#xff1f; 今天为大家推荐几款国内可用、好用的AI工具&#xff0c;不论是自媒体文案写作、打工人汇报PPT、还是论文、公文写作&#xff0c;总…

Centos7离线安装RabbitMQ教程

目录 安装包准备开始安装1. 创建目录2. 上传文件3. 安装erlang语言4. 安装socat5. 安装rabbitmq6. 启动、停止rabbitmq7. 设置开机启动8. 开启web界面管理工具9. 开启防火墙(root)10. 访问页面11. 附录 安装包准备 &#xff08;1&#xff09;准备RabbitMQ的安装包&#xff08;…

使用中心点检测进行对象检测、3D 检测和姿态估计:

检测将对象识别为图像中轴对齐的框。大多数成功的物体检测器都枚举了几乎详尽的潜在物体位置列表&#xff0c;并对每个位置进行分类。这是浪费、低效的&#xff0c;并且需要额外的后处理。在本文中&#xff0c;我们采用了不同的方法。我们将一个对象建模为一个点&#xff0c;即…

张驰咨询:告别杂乱无章,让精益生产培训帮你搞定一切!

在当今快速变化和竞争激烈的市场环境中&#xff0c;企业要想持续发展&#xff0c;提升生产效率和降低成本是关键。精益生产培训作为一种高效的生产方式和管理哲学&#xff0c;为企业提供了实现这些目标的有效途径。以下是张驰咨询对精益生产培训核心理念、实践方法及其对企业持…

关于光照模型

关于光照模型 早期学习笔记&#xff0c;转载自早期Excel。 存在大量格式错误、可读性非常低&#xff0c;建议等待作者修复后阅读、或者作为查找性材料使用。 中文名英文名/缩写说明长什么样兰伯特光照模型Lambert Lighting1.兰伯特反射(Lambert)是最常见的一种漫反射&#x…

C++ const_cast学习

语法&#xff0c; const_cast<type_name>(expression) type_name是转换的类型&#xff0c;expression是被转换的对象或者表达式&#xff1b; const_case有两个功能&#xff0c;分别是去掉const和加上const&#xff0c;更多用于去掉const&#xff0c;修改被const修…