FreeRTOS 正点原子教程学习笔记

2023-05-16

正点原子视频教程
FreeRTOS(教程非常详细)

小知识

如果创建了任务却完全空着,没有while(1){延时}的话,整个程序会卡住,其他正常的任务无法运行。如果任务里单单有赋值之类的操作也会卡死在这个任务,一定要记得加延时vTaskDelay(10);。
任务调度周期是1ms,能改,但是别改。

FreeRTOS中的变量,函数命名规则(u.v.x.p什么意思)
前面的字母是返回值的缩写
u :代表unsigned。

s :代表short。

c :char。 所以类似uc,us类的变量就是unsigned char,unsigned
short,分别对应uint8_t,uint16_t。

x :为用户自定义的数据类型,比如结构体,队列等。
常看到ux开头的函数,就是unsigned且用户自定义的类型。需要注意的是size_t变量前缀也是ux。

e :枚举变量

p :指针变量 类似(uint16_t *)变量前缀为pus。

prv :static函数

v: void函数

1、c语言中%x的意思是16进制输出。
2、c语言中符合%#的意思是带格式输出。比如,%#x的意思是在输出前面加上0x,%#b的意思是在输出前面加上0b。
用来输出地址

各种函数

  • vTaskList()能一次性看所有任务的状态、优先级、堆栈剩余大小和编号
  • vTaskGetRunTimeStates()用来统计各任务运行时间及其占比【很有用的】如果哪个太耗时就可以拆分。不过要用的话得专门弄个定时器。正点原子官网视频第13.2讲会详细讲,我用到再学吧。
  • 调用taskYIELD(),主动让出cpu,让同优先级的其他task获得cpu
  • vTaskDelay(1000);延时一秒,可被调度

FreeRTOSConfig.h
使用“INCLUDE_”开头的宏用来表示使能或除能 FreeRTOS 中相应的 API 函数,作用就 是用来配置 FreeRTOS 中的可选 API 函数的
“config”开始的宏和“INCLUDE_”开始的宏一样,都是用来完成 FreeRTOS 的配置和裁剪的
有些宏定义有默认值,是用#ifndef实现的

中断

关闭中断函数只能关掉大于等于5【5这个值是宏定义的,下图第一行】的中断优先级的事件【优先级数值比较小的比较高】
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
临界段代码也叫做临界区,是指那些必须完整运行,不能被打断的代码段。
#define taskENTER_CRITICAL() portENTER_CRITICAL()
#define taskENTER_CRITICAL_FROM_ISR() portSET_INTERRUPT_MASK_FROM_ISR()
#define taskEXIT_CRITICAL() portEXIT_CRITICAL()
#define taskEXIT_CRITICAL_FROM_ISR( x ) portCLEAR_INTERRUPT_MASK_FROM_ISR( x )
没有_FROM_ISR的是任务级的临界段代码保护,另外俩是中断级的临界段代码保护。

void start_task(void *pvParameters)
{
	taskENTER_CRITICAL(); //进入临界区
	xTaskCreate((TaskFunction_t)led0_task,
		(const char*)"led0_task",
		(uint16_t)LED0_STK_SIZE,
		(void*)NULL,
		(UBaseType_t)LED0_TASK_PRIO,
		(TaskHandle_t*)&LED0Task_Handler);
	vTaskDelete(StartTask_Handler);				//删除任务
	taskEXIT_CRITICAL();									//退出临界区

}

在这里插入图片描述
中断里的临界区出入函数有返回值和传入参数

任务堆栈

用来存被中断时的保存现场的指针以及函数内部定义的内部变量、数组等。 如果堆栈开得太小运行时会卡。当堆内存不够的时候 这个函数的返回值会返回错误信息
在这里插入图片描述

堆栈开的大小是都要定的,两种函数都要定,用宏定义自己定,上面的代码里是LED0_STK_SIZE 开辟的大小是LED0_STK_SIZE*4 字节
截图里说的是堆栈所在的首地址,它下面的那个传入参数是任务控制块的首地址。如果不是静态创建而是动态创建的话,就不用这俩参数,而是要一个句柄。
欸,任务删除的传入参数是句柄啊,那静态创建的任务的句柄在哪啊?? 啊知道了,静态任务创建函数的返回值是任务句柄,句柄要先自己定义,类型是TaskHandle_t

删除任务

假设现在正在编写的子函数是一个任务,并且要在这个函数执行完成之后就删除任务,那就在最后一句写 vTaskDelete(StartTask_Handler); 删除掉任务。传入参数可以是这个函数创建时的句柄,也可以是NULL。
不过删除任务的时候要先判断那个句柄是否已经是NULL了,免得把已经删除的任务再删几次。【人是不能死两次的,任务也不能】
但是删除自身的时候.要是这个任务有返回值,又只运行这一次就删掉,return是最后一句,vTaskDelete(NULL); 是倒数第二句。这样没问题嘛??

任务优先级

0级最低。
这里说的是线程里面的函数调用的优先级,范围是 0~(configMAX_PRIORITIES-1) ,空闲任务的优先级为0,一般都是自己创建任务的时候自己写个宏定义然后传入对应的参数,比如上面的LED0_TASK_PRIO。
上面说的是中断优先级,反正不一样,哼。
乱来的,UCOS的任务优先级里0就是最高级,而且前面几个都是系统用的,我们自己创的任务直接10起步。

在这里插入图片描述
视频第20讲,文章第14.6章提到【优先级翻转】
优先级翻转是指同样要插队运行,较低优先级的插队到高优先级前面去了。
原因是
高优先级的任务需要等一个信号量,这个信号量交给优先级最低的任务处理了,中优先级的任务就跑来插最低优先级的任务 它做完再让最低优先级任务继续处理信号量,然后等最低优先级处理完、释放信号量之后 最高优先级才能继续任务。

创建静态任务

首先说明一下,静态任务并不比动态好什么东西,又麻烦。以后的教程也只会用动态不会用静态。
官网讲解优缺点
FreeRTOS的软件结构 //大佬
FreeRTOS动态内存管理

静态任务创建的函数的定义在tasks.c文件里,刚移植好的时候是不支持创建静态任务的
在这里插入图片描述
上面的宏定义要跳转过去修改【这个系统原本给它的默认值是0】

当我们把这个开关打开的时候,麻烦来了
我们之前关着的时候调用 vTaskStartScheduler(); 开启任务调度。它在不被支持静态创建的时候会动态创建空闲函数,但是支持静态的时候就会创建静态的空闲函数了,然而它要创建却少条件,还得自己写函数写堆栈,把空闲任务和定时器任务所需的内存定义上。正点原子有教,静态和动态所创建的堆栈大小是一样的。我嘛,直接把宏定义再加个条件,仍然让它创建动态的。

记录一下自己作死的地方,免得忘了
我在main函数上面定义了 #define STATIC_MAFAN 0 然后在下面两个地方 &&了这么个条件
在这里插入图片描述在这里插入图片描述

话说为什么开启任务调度函数里创建函数的时候 那些传入参数都不用强制类型转换的??

静态和动态不一样的参数就最后两个,一个是堆栈,应该创建一个数组,另一个是控制块,创建一个结构体变量
StackType_t StackBuffer[START_STK_SIZE];
StaticTask_t TaskBuffer_TCB;

任务挂起和恢复

挂起就是暂停
在这里插入图片描述

  • 可以重复挂起任务很多次,恢复只要调用一次就能恢复 【任务调度器也能挂起和恢复,但是如果挂起它两次就得调用恢复两次】
  • 挂起自身任务的时候传入参数可以是NULL
  • 挂起时,函数内的局部变量的内存不会被释放。
  • 中断的恢复函数有返回值

在这里插入图片描述

在这里插入图片描述
(1)优先级设置成5也正常,但是4就不行了。定时器中断、串口中断的优先级也要小于等于5
(3)这条函数就是任务重新调度的

按正点原子的教程做,KEY0按键中断的时候程序会卡在xEventGroupSetBitsFromISR()这个函数。解决方法是HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_2);//这个中断优先级分组要改成NVIC_PRIORITYGROUP_4 总共的优先级分为16个等级 //如果分组用第二组的话就只有4个优先级,没办法把按键中断优先级设为6.

第0组:所有4位用于指定响应优先级
第1组:最高1位用于指定抢占式优先级,最低3位用于指定响应优先级
第2组:最高2位用于指定抢占式优先级,最低2位用于指定响应优先级
第3组:最高3位用于指定抢占式优先级,最低1位用于指定响应优先级
第4组:所有4位用于指定抢占式优先级

程序是正常运行了,但是我怎么证明这中断里的恢复有重新安排优先级更高的程序呢??
我先复述一下在这个任务挂起和恢复里的程序效果:
两个灯,4个按键,两个按键负责挂起,两个按键负责恢复,其中按键KEY0是外部中断 负责LED1的恢复。两个灯在正常情况下会不断闪烁。
我在任务函数里用delay_xms(500);给灯做延时,这个函数不能被任务调度打断,所以运行时只有一个任务优先级比较高的那个灯会闪【任务创建时给定的宏,数字大的优先级高】,中断时也只能帮优先级高的任务抢回闪灯权,否则就只能等高优先级的任务挂起了才能让低优先级的灯闪。

列表与列表项

1.先定义一个列表 List_t 和三个列表项 ListItem_t
2.在一个任务里进行初始化。调用vListInitialise()和vListInitialiseItem()函数,传入第一步定义的变量的地址就好
3.然后给列表项的.xItemValue值赋值,用来排序
在这里插入图片描述
现在就是一个空的TestList和三个独立的列表项
4.vListInsert(&列表,&列表项);往列表里自动按从小到大的顺序插入那个输入的列表项
在这里插入图片描述

在这里插入图片描述
5.删除列表项 uxListRemove(&列表项);
6.在末尾添加列表项 vListInsertEnd(&列表,&列表项);

在这里插入图片描述

队列

先进先出,值传递(数据量大的时候可以把指针当作值来传递啊!)【UCOS是引用传递,源数据在消息传到之前不能删改】

  1. 动态创建队列
    返回句柄 xQueueGenericCreate(队列可容纳的消息数量,单个消息的长度,队列类型)
    在这里插入图片描述
    if(Key_Queue!=NULL) //在用队列之前都先问问这个队列是不是创建成功
    //二值信号量和互斥信号量的队列长度都是1 ,单个消息的长度都是0.只用看是有信号还是没信号就行,不用存具体消息。
    在哪创建啊??删除任务之后队列会被删掉吗??
    句柄是全局变量 要跨任务传消息
    创建队列是和创建一大批任务的时候一起创的,返回值已经赋值给全局的句柄所以删掉任务没事。

  2. 向队列发送消息
    在这里插入图片描述

xQueueSend( 目标队列句柄, 消息内容的变量的地址, 阻塞时间 )
中断级入队函数的参数里有一个pxHigherPriorityTaskWoken 它要我们在这个子函数里新建一个变量,然后把地址给它当传入参数。整好之后要用portYIELD_FROM_ISR(变量名);重新按任务优先级选择要运行的任务。

  1. 从队列中读取消息
    在这里插入图片描述
    xQueueReceive(key_queue,&key,0);
    //从key_queue队列中取出消息存到新建u8变量里去,等0ms,要是没拿到消息就返回0 拿到就返回1

信号量

要#include “semphr.h”

  • 情景要求是电脑发数据,串口接收,任务获取数据并处理
    如果在串口中断把消息内容直接传给任务,就用队列传消息
    如果在串口中断做个标记,任务里查询标记然后从串口缓冲区拿消息,就用信号量做标记

信号量其实就是队列,创建信号量的函数调用的就是创建队列的函数。
多个任务同时要读取某一个信号量时,最高优先级的任务能读到,其他的进入阻塞态
这个文章适合复习操作

  1. 二值信号量
    只有一个队列项 而且只用判断是满的还是空的 不用看内容
    give函数是任务发出信号量给队列,take函数是任务从队列里取出信号量。初始化、发消息和收消息的流程和队列一样,函数也分任务级和中断级,就是函数名不一样,在不同的头文件里。
    //创建二值信号量
    BinarySemaphore=xSemaphorecreateBinary ();
    //二值信号量创建成功以后要先释放一下才能给别的任务使用
    if(BinarySemaphore!=NULL)xSemaphoreGive(BinarySemaphore) ;

    在什么情况下用?
    【串口收到消息时,要避免在串口中断里进行文本处理以及显示反馈】串口助手里发送消息之后会标记二值信号量,定时器中断里查到二值信号量被标记时会在LCD和串口助手里显示收到的字符串。【串口的优先级是7,定时器的优先级是8】

  2. 计数型信号量/数值信号量
    反正就是帮忙计数的,可以设最大值和初值。一般用来看资源使用量或者剩余量
    xSemaphoreCreateCounting()创建
    后面任务里每调用一次xSemaphoreGive(句柄); 就会有个变量加1.
    semavalue=uxSemaphoreGetCount(句柄);读那个变量
    xSemaphoreTake(句柄,portMAX_DELAY); 变量减1.

  3. 互斥信号量

互斥信号量拥有优先级继承机制,二值信号量没有优先级继承。
因此二值信号量更适合用于同步(任务与任务或任务与中断的同步),而互斥信号量适合用于简单的互斥访问

定时器中断和按键中断这些中断能迅速插入一段新任务运行,但是如果要在程序运行过程中某个变量置1时插入新任务的话,在裸机写代码的时候只能等程序运行到那去检查那个变量,现在有操作系统就能实时检查信号量并在拿到信号时运行新任务。

创建 xSemaphoreCreateMutex(),//创建之后不用特地释放
发信号和读信号的函数跟二值信号量一样

不同的地方是
1 当高优先级的任务向低优先级的任务请求互斥信号量的时候,如果高优先级任务要等着,就会把那个低优先级任务的优先级拉高,让它快点处理好所需要的信号量【这就叫优先级继承】
2 互斥信号量不能用在中断函数里。中断里也不能用长时间的阻塞态等信号量来着,所以没必要

//文档里讲互斥信号量和递归互斥信号量比视频里讲的要多很多

释放互斥信号量的时候和二值信号量、计数型信号量一样,都是用的函数 xSemaphoreGive()(实际上完成信号量释放的是函数
xQueueGenericSend())。不过由于互斥信号量 涉及到优先级继承的问题,所以具体处理过程会有点区别。使用函数
xSemaphoreGive()释放信 号 量 最 重 要 的 一 步 就 是 将 uxMessagesWaiting 加 一 , 而 这
一 步 就 是 通 过 函 数 prvCopyDataToQueue() 来 完 成 的 , 释 放 信 号 量 的 函 数
xQueueGenericSend() 会调用 prvCopyDataToQueue()。互斥信号量的优先级继承也是在函数
prvCopyDataToQueue()中完成的

  1. 递归互斥信号量
    已经获取了互斥信号量的任务就不能 再次获取这个互斥信号量,但是递归互斥信号量不同,已经获取了递归互斥信号量的任务可以 再次获取这个递归互斥信号量,而且次数不限!一个任务使用函数 xSemaphoreTakeRecursive()成功的获取了多少次递归互斥信号量就得使用函数 xSemaphoreGiveRecursive()释放多少次
    同互斥信号量一样,递归互斥信号量的获取和释放要在同一个任务中完成!如果当前正在运行的任务不是递归互斥信号量的拥有者就不能释放!
    创建 xSemaphoreCreateRecursiveMutex()

软件定时器

硬件定时器时间准 但是资源不多,拿软件定时器凑合用。回调函数里不能有延时或者阻塞
可以设置成 周期定时器 或者 单次定时器
有创建、开启、复位、停止 函数
可以用于LCD背光每按下一次按键就亮5秒的应用

事件标志组

要#include “event_groups.h”
使用信号量来同步的话任务只能与单个的事件或任务进行同步。要是某个任务可能会需要与多个事件或任务进行同步就要用事件标志组。【例程里就是:两个按键各自管一个标志位,另一个任务等待指定的事件位,达成的条件可以自己设置为 两个标志位都要为1/其中有一个置1就行/达成条件后要不要清除标志位/等多久】

实际使用时可以
● 事件标志组的 bit0 表示队列中的消息是否处理掉。
● 事件标志组的 bit1 表示是否有消息需要从网络中发送出去。
● 事件标志组的 bit2 表示现在是否需要向网络发送心跳信息。
//跟手册里的寄存器说明差不多。
在代码里用的时候是
#define EVENTBIT_0 (1<<0) //事件位
#define EVENTBIT_1 (1<<1)
#define EVENTBIT_2 (1<<2)
#define EVENTBIT_ALL (EVENTBIT_0|EVENTBIT_1|EVENTBIT_2)

句柄类型 EventGroupHandle_t
创建 xEventGroupCreate()
清零 xEventGroupClearBits(句柄,要清零的事件位)
xEventGroupClearBitsFromISR(同上)
置1 xEventGroupSetBits(同上) //说是有检查任务状况,清零没有。没听懂,文档里没写
xEventGroupSetBitsFromISR(同上)
获取标志 xEventGroupGetBits()
xEventGroupGetBitsFromISR()

要清零的事件位:比如要清除 bit3 的话就设置为 0X08。可以同时清除多个bit,如设置为 0X09 的话就是同时清除 bit3 和 bit0。//一个字节8个位,8421 8421
通过宏定义可以选择事件标志组是有8位还是24位

等待指定的事件位 //这个常用
在这里插入图片描述
xEventGroup: 指定要等待的事件标志组。
uxBitsToWaitFord: 指定要等待的事件位,比如要等待bit0和(或)bit2的时候此参数就是0X05
xClearOnExit: 此参数要是为pdTRUE的话,那么在退出此函数之前由参数uxBitsToWaitFor 所设置的这些事件位就会清零。如果设置位 pdFALSE 的话这些事件位就不会改变。
xWaitForAllBits: 此参数如果设置为 pdTRUE 的话,当 uxBitsToWaitFor 所设置的这些事件位都置 1,或者指定的阻塞时间到的时候函数 xEventGroupWaitBits()才会返回。当此函数为 pdFALSE 的话,只要 uxBitsToWaitFor 所设置的这些事 件位其中的任意一个置 1,或者指定的阻塞时间到的话函数 xEventGroupWaitBits()就会返回。
xTicksToWait: 设置阻塞时间,单位为节拍数。
返回值 返回当所等待的事件位置 1 以后的事件标志组的值,或者阻塞时间到。根据这个值我们就知道哪些事件位置 1 了。如果函数因为阻塞时间到而返回的话那么这个返回值就不代表任何的含义。

任务通知

可以使用任务通知来代替信号量、消息队列、事件标志组等这些东西。使用任务通知的话效率会更高。以前是创建对应的结构体存信号量信息,现在是直接往任务的句柄里存那些信息。
但是任务通知只能单个任务对单个任务进行通信,要一对多的时候还是要用那些功能。
而且任务通知只有出队阻塞没有入队阻塞【接收任务时可能阻塞,但是如果发送失败就不会阻塞】
在这里插入图片描述
在这里插入图片描述

  1. 代替二值信号量
    删掉二值信号量的创建和信号量的NULL检测。要检测任务句柄是不是NULL。
    释放/发送信号量
    原先 xSemaphoreGiveFromISR(二值信号量句柄,任务切换变量)
    现在 vTaskNotifyGiveFromISR(目标任务句柄,任务切换变量)//我要把这个信号量给多个任务的话,我再写一句不就好了??
    等待/获取信号量
    原先 xSemaphoreTake(二值信号量句柄,阻塞时间)
    现在 ulTaskNotifyTake(要清零还是减一,阻塞时间) //参数为 pdFALSE 模拟计数型信号量;参数为 pdTRUE 模拟二值信号量。

  2. 代替数值信号量
    数值信号量原本有计数和资源管理两个功能。但是资源管理涉及多个任务,所以这个功能代替不了,只能代替它计数。
    获取信号量的函数的返回值是执行那个函数之前的信号量的数值。简单讲就是 把原本的值另外存起来,函数运行的时候会减一,返回值返回的是原本的值。
    函数的替换操作和二值一样

  3. 代替队列 实现消息内容的传递//内容也可以是指针
    1、只能发送 32 位的数据值。//强制类型转换
    2、消息被保存为任务的任务通知值,而且一次只能保存一个任务通知值,相当于队列长度为 1。
    释放/发送信号量
    原先 xQueueSend(队列句柄,消息内容变量的地址,阻塞时间)//任务通知就没这个入队阻塞
    现在 xTaskNotify(目标任务句柄,消息内容变量,要不要覆写)//第三个参数为 eSetValueWithOverwrite 的话不管接收任务的通知值是否已经被处理,这个通知值都会被更新;为 eSetValueWithoutOverwrite 的话如果上一个任务通知值话还没有被处理,那么新的任务通知值就不会更新。
    等待/获取信号量
    原先 xQueueReceive(队列句柄,保存消息内容变量的地址,阻塞时间)
    现在 xTaskNotifyWait(没有接收到任务通知时 是否清空消息,接收到了任务通知并处理好内容后 是否清空消息,保存消息内容变量的地址,阻塞时间) /前面两个参数 如果填0就不清空,填ULONG_MAX就清空。//这个宏要加一个头文件limits.h才能用

  4. 代替事件标志组
    释放/发送信号量
    原先 xEventGroupSetBits(事件句柄,要设置的事件位)
    现在 xTaskNotify(目标任务句柄,要设置的事件位,eSetBits)//第三个参数选择要修改指定的位//对,上面写的是要不要覆写,其实第三个参数总共有5个选项可以选。
    等待/获取信号量
    原先 xEventGroupWaitBits(事件组,事件位,退出是否清零,与/或,阻塞时间)
    现在 xTaskNotifyWait(没有接收到任务通知时 是否清空消息,接收到了任务通知并处理好内容后 是否清空消息,保存消息内容变量的地址,阻塞时间) //填ULONG_MAX就清空,要清除指定的位就对应位置1换成十六进制传入。
    在这个任务通知里,获取信号量的函数里没有与/或的功能选项,所以接到一个位的信号后如果选择清零,那就是跟二值信号量一样的用法;如果不清零,那这个与的事件真正达成之后怎么触发第二次??要不自己另外清零?

低功耗模式 //Tickless模式

任务处理函数的运行时间很少,大部分时间都是在运行空闲任务。所以空闲任务的耗电量一定要想办法降低。所以,要在空闲任务阶段进入低功耗模式。【进入低功耗模式前还可以关掉时钟,降低系统主频等等 出来的时候记得恢复】
如果关定时器是要自己操作,那低功耗模式究竟做了什么事能让功耗下降啊??
进入低功耗模式的要求

  • 空闲任务是唯一可运行的任务,其他所有的任务都处于阻塞态或者挂起态。
  • 系统处于低功耗模式的时间至少大于2

进入低功耗模式时

  • 要维持滴答定时器的运行【心跳时钟】
  • 要在下次任务需要运行时退出低功耗模式【中断任务本身就能打断低功耗模式】//居然有一个变量直接就存着’距离下一个任务需要开始运行的时间还有多久‘
  • 低功耗模式有最大运行时长,在这里是93ms。要维持更久的话就出去重新进一次低功耗模式

空闲任务的工作内容
1、释放内存
2、检查是否使用抢占内核,如果没使用,调用taskYIELD
3、如果使用抢占式内核,而且configIDLE_SHOULD_YIELD等于1,那么空闲任务就把CPU使用权让给同优先级的其他任务
4、是否使能钩子函数,使能的话就调用
5、是否使能Tickless模式,使能的话就做相应的处理工

钩子函数

Freertos的钩子函数

在任务里给指针赋内存不可以用malloc() 和free ()要用pvPortMalloc()和vPortFree()
而且使用的时候要判断NULL,释放之后要赋值NULL

任务调度器源码讲解

  1. 创建空闲任务
  2. 【可选】打开软件定时器
  3. 关中断
  4. 初始化一些静态全局变量【获取下一次任务要开始的时间,任务调度器开始,freertos整个系统的时钟节拍计数器清零】
  5. 时基定时器初始化

艾玛,一直在讲汇编。遭不住了。溜了溜了

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

FreeRTOS 正点原子教程学习笔记 的相关文章

  • FreeRTOS快速上手

    FreeRTOS使用 一 源码下载和移植文件提取 1 1 源码下载 在网站https sourceforge net projects freertos 可以找到freertos最新的源码 1 2 移植文件提取 根据第一步 我们会得到一个f
  • 解决错误“ #error “include FreeRTOS.h“ must appear in source files before “include event_groups.““例子分享

    今天来给大家分享一下 关于之前自己在学习FreeRTOS过程中遇到的一个错误提示 话不多说 我们直接来看 错误分析 首先 我们看一下错误的提示 error 35 error directive include FreeRTOS h must
  • FreeRTOS简述和移植文档

    FreeRTOS简述和移植文档 文章目录 FreeRTOS简述和移植文档 1 前言 2 FreeRTOS简述 1 概述 2 实现 3 主要特色 4 支持平台 3 移植FreeRTOS 4 最后 1 前言 目前由于IOT的飞速发展 针对单片机
  • 一文教你学会keil软件仿真

    仿真在我们调试代码中是非常重要的 通过仿真 我们可以快速定位到错误代码 或者错误逻辑的地方 这里我就以上一篇博客为例 教大家如何软件仿真 软件仿真不需要单片机 直接通过keil软件进行代码调试 一 打开工具 二 选择软件仿真 三 开始仿真
  • Freertos中vTaskDelay()是怎么用的

    1 常见的使用场景 void vLED Task void pvParameters while 1 Heartbeat LED vTaskDelay 1000 portTICK RATE MS 说明 上面这段代码的意思是 led翻转后经过
  • freertos---软定时器

    一 软件定时器介绍 freeRTOS软件定时器的时基是基于系统时钟节拍实现的 可以创建很多个 在硬件定时器资源不充足的情况下非常有用 软件定时器一般用作周期性地执行函数 在创建软件定时器时指定软件定时器的回调函数 在回调函数中实现相应的功能
  • FreeRTOS系列

    1 RTOS简介 RTOS全称为 Real Time Operation System 即实时操作系统 RTOS强调的是实时性 又分为硬实时和软实时 硬实时要求在规定的时间内必须完成操作 不允许超时 而软实时里对处理过程超时的要求则没有很严
  • 【FreeRTOS】队列的使用

    作者主页 凉开水白菜 作者简介 共同学习 互相监督 热于分享 多加讨论 一起进步 专栏资料 https pan baidu com s 1nc1rfyLiMyw6ZhxiZ1Cumg pwd free 点赞 收藏 再看 养成习惯 订阅的粉丝
  • FreeRTOS学习笔记<中断>

    中断概念 Cortex M的NVIC最多支持240个IRQ 中断请求 1个不可屏蔽中断 NMI 1个Systick 滴答定时器 定时器中断和多个系统异常 Cortex M处理器有多个用于管中断和异常的可编程寄存器 这些寄存器大多数都在 NV
  • 基于HAL库的FREERTOS----------一.任务

    FreeROTS 就是一个免费的 RTOS 类系统 这里要注意 RTOS 不是指某一个确定的系统 而是指一类系统 比如 UCOS FreeRTOS RTX RT Thread 等这些都是 RTOS 类操作系统 FreeRTOS 是 RTOS
  • FreeRTOS记录(九、一个裸机工程转FreeRTOS的实例)

    记录一下一个实际项目由裸机程序改成FreeRTOS 以前产品的平台还是C8051单片机上面的程序 硬件平台改成了STM32L051 同时使用STM32CubeMX生成的工程 使用FreeRTOS系统 EEPROM数据存储读取函数修改更新 2
  • 【FreeRTOS(三)】任务状态

    文章目录 任务状态 任务挂起 vTaskSuspend 取消任务挂起 vTaskResume 挂起任务调度器 vTaskSuspendAll 取消挂起任务调度器 xTaskResumeAll 代码示例 任务挂起 取消任务挂起 代码示例 挂起
  • FreeRTOS基础五:软件定时器

    软件定时器简介 软件定时器的作用 在指定的时间到来时执行指定的函数 或者以某个频率周期性地执行某个函数 被执行的函数叫做软件定时器回调函数 软件定时器由FreeRTOS内核实现 不需要硬件支持 软件定时器只有在软件定时器回调函数被调用时才需
  • stm32f103zet6移植标准库的sdio驱动

    sdio移植 st官网给的标准库有给一个用于st出的评估板的sdio外设实现 但一是文件结构有点复杂 二是相比于国内正点原子和野火的板子也有点不同 因此还是需要移植下才能使用 当然也可以直接使用正点原子或野火提供的实例 但为了熟悉下sdio
  • 基于STM32的FreeRTOS学习之中断测试实验(五)

    记录一下 方便以后翻阅 本章内容是接着上一章节进行的实际演练 1 实验目的 FreeRTOS可以屏蔽优先级低于configMAX SYSCALL INTERRUPT PRIORITY的中断 不会屏蔽高于其的中断 本次实验就是验证这个说法 本
  • FreeRTOS学习笔记(8)---- 软件定时器

    使用FreeRTOS软件定时器需要在文件FreeRTOSConfig h先做如下配置 1 configUSE TIMERS 使能软件定时器 2 configTIMER TASK PRIORITY 定时器任务优先级 3 configTIMER
  • FreeRTOS临界段

    1 临界段 在访问共享资源时不希望被其他任务或者中断打断的代码 这段要执行的代码称为临界段代码 2 设置临界段的目的 保护共享资源 例如 全局变量 公共函数 不可重入函数 函数里面使用 了一些静态全局变量 malloc 等 保护外设的实时性
  • FreeRTOS之系统配置

    1 FreeRTOS的系统配置文件为FreeRTOSConfig h 在此配置文件中可以完成FreeRTOS的裁剪和配置 在官方的demo中 每个工程都有一个该文件 2 先说一下 INCLUDE 开始的宏 使用 INCLUDE 开头的宏用来
  • 防止GCC LTO删除函数

    我使用 GCC ARM Embedded 和 FreeRTOS FreeRTOS具有的功能vTaskSwitchContext 仅在某些情况下使用 内联汇编代码 问题是 当我使用LTO时 GCC不考虑内联汇编代码并认为该函数没有被使用 因此
  • 哪些变量类型/大小在 STM32 微控制器上是原子的?

    以下是 STM32 微控制器上的数据类型 http www keil com support man docs armcc armcc chr1359125009502 htm http www keil com support man d

随机推荐

  • 大津阈值法(OTSU)功能实现

    具体的公式推导参见冈萨雷斯 数字图像处理 Otsu方法又称最大类间方差法 xff0c 通过把像素分配为两类或多类 xff0c 计算类间方差 xff0c 当方差达到最大值时 xff0c 类分割线 xff08 即灰度值 xff09 就作为图像分
  • cas-server服务端搭建

    1 下载cas服务代码 xff0c https github com apereo cas overlay template tree 5 3 2 使用idea工具打开cas overlay template 5 3包 xff0c 使用ma
  • 自适应阈值canny边缘检测(功能实现)

    学习记录 1 概述 canny边缘检测是一种特别常用且性能优秀的边缘检测算法 xff0c 相比于普通的边缘检测算法 xff0c canny获得的边缘较细且具有连续的边缘轮廓 xff0c 为之后的一系列图像处理带来极大的便利 canny边缘检
  • OpenCV实现图像基础频率域滤波

    写在前面 xff1a 刚开始接触数字图像处理频率域滤波时 xff0c 很是陌生 xff0c 感觉这个技术使用范围很窄 xff0c 不如空域直接处理来的实在 xff0c 最近看书发现有些情况又不得不在频率域中进行操作 xff0c 个人感觉图像
  • OpenCV实现同态滤波

    同态滤波是属于图像增强的一个小算法 xff0c 其原理和代码实现在众多博客中均有提及 xff0c 再此 xff0c 只对学习中一些自认为有用的知识点进行总结 实现和学习过程中的一些总结 xff1a 同态滤波类似于灰度变换 xff0c 都是对
  • OpenCV实现击中击不中变换和形态学细化

    1 击中击不中变换 1 1 HMT概述 形态学Hit or Miss是形状检测基本工具 xff0c 只要结构元设置得当 xff0c 就可以检测一些基本的形状图案 xff0c HMT变换只能作用于二值图像 xff0c 结构元 xff08 核
  • OpenCV综合练习1——水瓶水位线合格检测

    数字图像处理综合练习 水瓶水位线合格检测 马上就要转到学习深度学习的主干线了 xff0c 这也是大势所趋 xff0c 但不能忘本 xff0c 传统图像处理的知识也是非常重要的 xff0c 特此记录一下之前学习时做过的小练习 整个项目的资源放
  • 目标检测学习1——iou计算与非极大值抑制NMS

    刚开始学习目标检测 xff0c 都是在学习一些经典的目标检测框架 xff0c 个人认为在大量阅读和理解别人现成的代码时 xff0c 也要懂得去动手模仿 xff0c 尝试着去修改别人的代码 xff0c 即使是自己抄一遍别人的代码 xff0c
  • OpenCV实现按指定间隔抽取视频中的图像帧

    习惯了C 43 43 语言的OpenCV突然用Python语言OpenCV还是感觉有点不适应 xff0c 但是慢慢在写的过程中 xff0c 觉得Python语言的风格也挺美的 但自己的写的还是很丑 xff0c 晚上回宿舍的剩余时间 xff0
  • 深度估计berHu损失函数和语义分割带权值交叉熵损失函数

    深度估计berHu损失函数和语义分割带权值交叉熵损失函数 最近在做联合深度估计和语义分割的深度学习算法 xff0c 深度估计默认使用的是L1 loss xff0c 语义分割使用的是普通的交叉熵损失函数 xff0c 继续改进模型对于指标的提升
  • 游览器是如何工作的

    游览器是如何工作的 浏览器的主要功能浏览器的主要构成一次网络请求浏览器发生了什么 xff1a 如果请求使用了HTTPS那么流程会有什么不同 xff1f 总结 浏览器的主要功能 浏览器的主要功能是将用户选择得web资源呈现出来 xff0c 它
  • OSG QT 完整附加依赖项(.lib)

    OSG QT 完整附加依赖项 lib 可在VS等需要添加附加依赖项的环境使用 注 xff1a OSG版本 xff1a 3 6 4 xff1b QT版本 xff1a 5 9 8 带d的为debug xff0c 不带d的release省掉了Qt
  • Ubuntu登陆账户后自动运行VNCserver

    问题 xff1a 远程桌面时 xff0c 如果重启远程Ubuntu xff0c 则VNC会话失效 解决 xff1a 一个解决的方法就是用putty将重启的Ubuntu登陆入账户后 xff0c 再开启VNC会话 为了方便 xff0c 可以设置
  • RAP与RARP原理

    ARP与RARP都属于网络层协议 xff0c 但是他们是为了解决链路层的帧转发问题 xff0c ARP的功能是将IP解析成MAC地址 xff0c 而RARP则相反 ARP 地址解析协议 xff08 Address Resolution Pr
  • eyeshot官方样例说明

    Eyeshot 12 例子 1 wings拖动按钮改变机翼的尺寸参数 xff0c 并导出到step文件 2 snaptogrid鼠标画平面 xff0c 类似于CATIA的多段线功能 3 sceneeditor控制灯光点和变换位置 xff0c
  • Python爬虫实现获取股票信息并保存到文件(亲测可运行)

    主要参考了北京理工大学嵩天老师的视频 xff0c 因老师所讲的网址已做更改 xff0c 将获取股票列表信息和股票价格的网站做了更改 xff0c 用到了beautiful soup库 xff0c re库 xff0c requests库 xff
  • 为什么要内存对齐?

    CPU访问非对齐的内存时为何需要多次读取再拼接 xff1f 首先简单说一下何为内存对齐 例如 xff0c 当cpu需要取4个连续的字节时 xff0c 若内存起始位置的地址可以被4整除 xff0c 那么我们称其对齐访问 反之 xff0c 则为
  • 读AQS源码-关于shouldParkAfterFailedAcquire函数的返回值

    先上源码 final boolean acquireQueued final Node node int arg boolean failed 61 true try boolean interrupted 61 false for fin
  • 读AQS源码-关于同步队列与锁的公平性

    先上部分源码 xff1a public final void acquire span class token punctuation span int arg span class token punctuation span span
  • FreeRTOS 正点原子教程学习笔记

    正点原子视频教程 FreeRTOS 教程非常详细 xff09 小知识 如果创建了任务却完全空着 xff0c 没有while xff08 1 xff09 延时 的话 xff0c 整个程序会卡住 xff0c 其他正常的任务无法运行 如果任务里单