freertos的基本框架如下

  

注意有三点很重要:

  1.任务的资源

    (1)任务优先级:freertos 能够调度的任务优先级在freertosConfig.h中的configMAX_PRIORITIES中定义,每一个任务的优先级都在0~configMAX_PRIORITIES -1 中取值 优先级是数值越小,优先级越小,空闲任务的优先级为0.高优先级的任务必须有延时,低优先级的任务才能获得人物使用权。

      任务优先级在定义时,可参考以下的规则:

         ① IRQ 任务:IRQ 任务是指通过中断服务程序进行触发的任务,此类任务应该设置为所有任务里面优先级最高的。

      ② 高优先级后台任务:比如按键检测,触摸检测,USB 消息处理,串口消息处理等,都可以归为这一类任务。

      ③ 低优先级的时间片调度任务:比如 emWin 的界面显示,LED 数码管的显示等不需要实时执行的都可以归为这一类任务。 实际应用中用户不必拘泥于将这些任务都设置为优先级 1 的同优先级任务,可以设置多个优先级,只需注意这类任务不需要高实时性。

(2)任务栈的大小:在freertosConfig.h中定义了一个总的堆栈的大小configTOTAL_HEAP_SIZE。如何这个值不够使用的话可以增大这个值。每个任务的栈都是特别要注意的。如果任务出现不运行,很大可能是任务栈不够用了。在freertos中有一个API可以获取在程序运行到现在,栈的接近历史最高水平线的值。我们需要在配置头文件将宏configCHECK_FOR_STACK_OVERFLOW 打开,这宏可定义为两个值1或者2,这两个值有着不同的检测方法,这两个方法不在赘叙。我们还需要调用任务栈溢出的时候,将溢出的任务的名字打印出来,或者进行其他处理。

    2.线程间的通讯

  (1)信号量 :二值信号量、计数信号量、互斥信号量。在多个任务等待同一个信号量来进行同步时,当这些任务优先级相等时,他们依次交叉获取 ,当这些任务优先级不同时,就会只有高优先级的任务会获取。

  (2)队列:注意取队列的速度和发送队列的速度,与他们的等待时长。注意判断返回值

  (3)事件组:事件组相当于一个软件寄存器,每一位都有一个标志。常用于当一个任务同时满足多个条件(与的关系)或者满足多个条件的某一个条件(或的关系)时使用。

   3.所有的API都要注意是不是在中断中调用。

其他:软件定时器:本质上就是队列,需要自己注册定时到后的回调函数。

 #include "mytask.h"
#include "task.h"
#include "timers.h" /* TASK HANDLERS */
TaskHandle_t startHandle;
TaskHandle_t ledHandle;
TaskHandle_t printfHandle;
TaskHandle_t writeQueueHandle;
TaskHandle_t SemaphoreBinaryHandle;
TaskHandle_t eventgrupHandle;
TimerHandle_t timer;
/* TASK INPUT VARIABLES */
u32 led_params = ;
char *databuf = "hello world";
u8 queue_buff[];
u8 TIMER_ID = ;
/* thread commutication variables */
xQueueHandle myqueue;
xSemaphoreHandle semphorebinary;
EventGroupHandle_t eventgroup;
/* task status */
portBASE_TYPE status; void start_task(void *param)
{
printf("start task\r\n"); myqueue = xQueueCreate(,*sizeof(char)); vSemaphoreCreateBinary(semphorebinary);
timer = xTimerCreate("timer test",/portTICK_PERIOD_MS,pdTRUE,(void*)&TIMER_ID,AutoReloadTimer_Handle_callback);
eventgroup = xEventGroupCreate(); taskENTER_CRITICAL();
xTaskCreate(led_task,"led task",START_STA_SIZE,(void*)&led_params,LED_TASK_PRTO,ledHandle);
xTaskCreate(printf_task,"printf task",PRINTF_STA_SIZE,(void *)databuf,PRTINF_TASK_PRIO,printfHandle);
xTaskCreate(writeQueue_task,"write queue task",WRITEQUEUE_STA_SIZE,NULL,WRITEQUEUE_TASK_PRIO,writeQueueHandle);
xTaskCreate(SemaphoreBinary_task,"xsemphorebinary task",BINARY_STA_SIZE,NULL,PRTINF_TASK_PRIO,SemaphoreBinaryHandle);
xTaskCreate(eventgrup_task,"eventgrup task",EVENT_STA_SIZE,NULL,EVENT_TASK_PRIO,eventgroup);
taskEXIT_CRITICAL();
//xTimerStart(timer,0);
vTaskDelete(NULL);
} void led_task(void*param)
{ while()
{ HAL_GPIO_WritePin(GPIOJ,GPIO_PIN_13,GPIO_PIN_SET); //PB1置1
HAL_GPIO_WritePin(GPIOJ,GPIO_PIN_5, GPIO_PIN_RESET); //PB1置1
vTaskDelay(*(u32*)param);
HAL_GPIO_WritePin(GPIOJ,GPIO_PIN_13,GPIO_PIN_RESET); //PB1置1
HAL_GPIO_WritePin(GPIOJ,GPIO_PIN_5, GPIO_PIN_SET); //PB1置1
vTaskDelay(*(u32*)param);
xEventGroupSetBits(eventgroup,0x1);
} } void printf_task(void*param)
{
while()
{
status = xQueueReceive(myqueue,queue_buff,portMAX_DELAY);
if(status == pdPASS)
{
taskENTER_CRITICAL();
printf("%s\r\n",queue_buff); taskEXIT_CRITICAL();
}
else printf("queue null \r\n");
vTaskDelay();
}
} void writeQueue_task(void *param)
{
u8 i =;
while()
{
status = xQueueSend(myqueue,queue_buff,);
if(status!= pdPASS) printf("queue full\r\n");
i++;
if(!(i%))
{
// xSemaphoreTake(semphorebinary,portMAX_DELAY);
// printf("get once baniry\r\n");
xEventGroupSetBits(eventgroup,0x4);
}
vTaskDelay();
}
} void SemaphoreBinary_task(void*param)
{
u8 i =;
while()
{
i++;
if(!(i%))
{
xSemaphoreGive(semphorebinary); }
vTaskDelay();
xEventGroupSetBits(eventgroup,0x2);
} } void eventgrup_task(void*param)
{
while()
{
xEventGroupWaitBits(eventgroup,0x7,pdTRUE,pdFALSE,portMAX_DELAY);
printf(" event groups test!!! \r\n");
} } void vApplicationStackOverflowHook( TaskHandle_t xTask, char *pcTaskName )
{
printf("task overflow name :%s\r\n",pcTaskName); }
void AutoReloadTimer_Handle_callback(TimerHandle_t xTimer)
{
static u32 count = ;
count++;
if(count>)
{
// xTimerReset(timer,0);
xTimerStop(timer,);
}
printf("timer count: %d\r\n",count);
} void print_high_stack_mark_value(void)
{
if(STACK_DEBUG)
{
u8 num =;
num = uxTaskGetStackHighWaterMark(ledHandle);
printf("%s : %d\r\n",pcTaskGetTaskName(ledHandle),num);
num = uxTaskGetStackHighWaterMark(ledHandle);
printf("%s : %d\r\n",pcTaskGetTaskName(ledHandle),num);
num = uxTaskGetStackHighWaterMark(ledHandle);
printf("%s : %d\r\n",pcTaskGetTaskName(ledHandle),num); } }

freertos test code

freertos学习的更多相关文章

  1. 【FreeRTOS学习05】深度解剖FreeRTOSConfig.h实现对系统的自定义剪裁

    ROM/RAM太小,因此要对系统进行剪裁: 相关文章 [FreeRTOS实战汇总]小白博主的RTOS学习实战快速进阶之路(持续更新) 文章目录 相关文章 1 系统的剪裁 2 FreeRTOSConfi ...

  2. FreeRTOS学习及移植笔记之一:开始FreeRTOS之旅

    1.必要的准备工作 工欲善其事,必先利其器,在开始学习和移植之前,相应的准备工作必不可少.所以在开始我们写要准备如下: 测试环境:我准备在STM32F103平台上移植和测试FreeRTOS系统 准备F ...

  3. FreeRTOS学习笔记——任务间使用队列同步数据

    1.前言 在嵌入式操作系统中队列是任务间数据交换的常用手段,队列是生产者消费者模型的重要组成部分.FreeRTOS的队列简单易用,下面结合一个具体例子说明FreeRTOS中的队列如何使用. 2.参考代 ...

  4. FREERTOS学习笔记

    2012-02-25 21:43:40 为提升自己对实时操作系统(RTOS)的认识,我学习了freeRTOS. 理解了OS任务的状态.优先级的概念.信号量的概念.互斥的概念.队列.内存管理.这都是和R ...

  5. 020 - FreeRTOS学习路线总结

    零.为什么写? 在H7-tools预售群里,有位朋友提出如何学习FreeRTOS这类的问题,便由此总结下自己的学习路线.最近又打算接触RTT,和FreeRTOS做个对比. 文章分两步来讲,学习路线和学 ...

  6. 【FreeRTOS学习06】深度解剖中断与任务之间同步的具体使用场景

    嵌入式系统中中断是必不可少的一部分: [FreeRTOS实战汇总]小白博主的RTOS学习实战快速进阶之路(持续更新) 文章目录 1 前言 2 中断特点 3 延迟中断处理 3.1 信号量的使用 3.2 ...

  7. 【FreeRTOS学习04】小白都能懂的 Queue Management 消息队列使用详解

    消息队列作为任务间同步扮演着必不可少的角色: 相关文章 [FreeRTOS实战汇总]小白博主的RTOS学习实战快速进阶之路(持续更新) 文章目录 相关文章 1 前言 2 xQUEUE 3 相关概念 3 ...

  8. 【FreeRTOS学习02】源码结构/数据类型/命名规则总结

    个人不是很喜欢FreeRTOS的编程风格,但是没办法,白嫖人家的东西,只能忍了,这里先简单总结一下: 相关文章 [FreeRTOS实战汇总]小白博主的RTOS学习实战快速进阶之路(持续更新) 文章目录 ...

  9. 【FreeRTOS学习03】小白都能懂的Task Management 任务管理基本概念介绍

    在FreeRTOS中,线程的术语又可以被称之为任务,或许这样更加合适,本文将介绍任务的创建/删除,任务参数的使用,以及任务优先级: 1 软实时和硬实时 硬实时系统的任务运行正确性与响应时限是紧密相关的 ...

  10. 【FreeRTOS学习01】CubeIDE快速整合FreeRTOS创建第一个任务

    整个专栏主要是博主结合自身对FreeRTOS的实战学习以及源码分析,基于STM32F767 Nucleo-144平台,在CubeIDE下进行开发,结合官方的HAL库,将硬件环节的问题减少到最小,将精力 ...

随机推荐

  1. SqlServer Left、Right、CharIndex函数

    LEFT 函数:返回字符串中从左边开始指定个数字符 RIGT.H 函数:返回字符串从右边开始指定个数字符 len函数:LEN 函数返回文本字段中值的长度. CHARINDEX函数:CHARINDEX ...

  2. [C++] 类的设计(2)——拷贝控制(1)

    1.一个类通过定义五种特殊的成员函数来控制此类型对象的拷贝.移动.赋值和销毁:拷贝构造函数.拷贝赋值运算符.移动构造函数.移动赋值运算符和析构函数.(拷贝.移动.析构)   2.拷贝和移动构造函数定义 ...

  3. Java 从入门到进阶之路(六)

    之前的文章我们介绍了 Java 的数组,本章我们来看一下 Java 的对象和类. Java 是一种面向对象语言,那什么是对象呢,对象在编程语言中属于一个很宽泛的概念,我们可以认为万事万物都是对象,每个 ...

  4. 不fq安装 golang tools

    go get -u -v github.com/golang/tools/go/buildutil ln -s $GOPATH/src/github.com/golang/tools $GOPATH/ ...

  5. 原来python如此神奇

    一.优缺点分析 1.缺点: ① 数学问题的生成中只考虑了消除乘除法加括号的无效情况(例如3*(4+5)或(6*5)/2这样的计算),但没有去掉加减法加括号的无效情况(例如(4+(7+8))或(3-(2 ...

  6. 通过python代码对域名ssl证书进行监控

    根据公司要求,要求用zabbix对域名的ssl证书进行到期监控 直接上代码 #!/usr/bin/env python3 from urllib3.contrib import pyopenssl f ...

  7. 完美激活Pycharm2019.2.3专业版

    完美激活Pycharm2019.2.3专业版 Pycharm官网自9月11更新到pycharm2019.2.2版本后,在短短的2周时间与9月25又带来新版本2019.2.3,不可说更新不快,侧面可以看 ...

  8. SpringBootSecurity学习(06)网页版登录方法级别的权限

    用户授权 前面讨论过,Web应用的安全管理,主要包括两个方面的内容,一个是用户身份的认证,即用户登录的设计,二是用户授权,即一个用户在一个应用系统中能够执行哪些操作的权限管理.前面介绍了登录,下面简单 ...

  9. 使用path监听指定文件系统的变化

    在以前的JAVA版本中,如果程序需要检测文件的变化,那么需要开辟一个线程每隔一段时间去遍历一次指定的目录,如果发现此次遍历结果和上次不同,那么就认为文件变动了 ,这样的方式非常繁琐,JAVA 7之后的 ...

  10. 【IT技术概念】什么是webservice?

    WebService是一个SOA(面向服务的编程)的架构,它是不依赖于语言,不依赖于平台,可以实现不同的语言间的相互调用,通过Internet进行基于Http协议的网络应用间的交互. WebServi ...