当前位置: 首页 > news >正文

【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.mrgr.cn/news/69389.html

相关文章:

  • 【Fermat】费马小定理
  • IDC 报告:百度智能云 VectorDB 优势数量 TOP 1
  • 如何处理 iOS 客户端内 Webview H5 中后台播放的音视频问题
  • 嵌入式硬件实战基础篇(一)-STM32+DAC0832 可调信号发生器-产生方波-三角波-正弦波
  • Leetcode:118. 杨辉三角——Java数学法求解
  • 大数据学习14之Scala面向对象--至简原则
  • github高分项目 WGCLOUD - 运维实时管理工具
  • 通过代码复习回忆 DiffusionDet: DiffusionTracker——代码解析
  • 产品经理晋级-Axure中继器制作美观表格
  • 『VUE』22. 组件传递数据props(详细图文注释)
  • 从截图到代码:screenshot-to-code开源项目实践指南
  • 游戏开发--C#面试题
  • 找工作就上万码优才,海量技术岗位等你来
  • 二分答案-整型二分—愤怒的牛-P1676 [USACO05FEB] Aggressive cows G
  • 如何借助AI 来提高开发效率
  • 《操作系统 - 清华大学》2 -2:中断、异常和系统调用
  • C++20 概念与约束(2)—— 初识概念与约束
  • 记一次文件包含刷题(伪协议篇)
  • Python操作系统交互:subprocess库的基本应用
  • 【MySQL基础知识】内置的系统函数(5)
  • Python实现扩展卡尔曼滤波(EKF)
  • Scikit-learn:数据科学中的瑞士军刀
  • 详解overlay网络和underlay网络
  • 一文详解java的数据类型
  • Python脚本模拟远程网络探测
  • 2-149 基于matlab的LDPC译码性能分析