在完成业务裸机的过程中,会用到freertos的任务通知和队列这两个内容
回顾下我们一开始的项目需求:
现在来看这个需求,在上了前面的课程后,相信大家心里已经有了实现它的方法脉络了
我们对于mini开发板和阿里云服务器的MQTT设备建立通信,有两种方案来实现:单任务和多任务

在只使用一个任务的这个情况下,代码逻辑和裸机其实差不多了
而多任务方案,就是将控制的外设都各自分配一个任务来控制


这两个方案的优缺点是基于我们这次的项目需求而言的。比如按键,我们只需要判断是否按下即可,所以可以改进到和MQTT任务合成一个任务

但是如果我们面临一个需求:需要判断按键的长按、短按、短按次数、长按次数
那是不是将这样一个对按键复杂分析的业务,独立分配一个任务来执行是更好的方案。
所以我们可以看到,虽然用一个任务也可以完成我们这次项目的业务需求,但那是因为我们的业务需求实在太简单了
既然一个任务就可以实现业务逻辑,为何不用裸机模式而要用RTOS模式?
在常见的物联网系统中,通常都是对多传感器的数据进行传输处理,用FreeRTOS的多任务调度、多任务消息传递机制,才能更好的应对物联网系统中的复杂需求

我在视频中,创建多任务的时候,一开始随意分配了三个任务的栈大小,导致了堆栈溢出。


算一算我创建这三个任务且开启任务调度后,实际上FreeRTOS会占用多少的内存?

我们在之前应该提到过,创建任务
这个分配给任务的栈深度 stackdepth,单位是字,也就是4个字节
而且我们开启任务调度的时候,会创建一个空闲任务

分配给空闲任务的栈大小是我们在FreeRTOSConfig.h里面设置的configMINIMAL_STACK_SIZE

所以如果我那样创建任务分配栈空间的话,实际FreeRTOS会占用的内存就是(2048 + 128 + 512 + 128)*4 bytes

11264个bytes

但是我们在FreeRTOSConfig.h设置的给FreeRTOS使用的最大堆空间是 10240


明显超出了,而且在创建按键任务分配512 stack depth的时候就超出了

所以创建按键任务的时候就会失败

所以,我们在使用FreeRTOS的时候,一定要对自己的内存分配进行精打细算才行

其实也不能这么说

应该是在我们实际工作的开发中,都要对内存空间进行精打细算的分配

至少在单片机开发中是需要的

像跑Linux系统的那些设备,一般都会外接DDR等内存设备,内存贼大……

我们的内存通常都会被分成几个区:


对于这几个区的作用,非常喜欢在面试题中出现

freertos管理内存有5种算法

heap1现在基本很少用了

常用的是heap 4/5

我们在成功创建任务后,第一步去做的还是我们最熟悉的,点灯

点灯的控制是在MQTT的订阅消息处理回调函数中,通过判断topic和payload,发送通知给LED任务去控制LED亮灭的


使用的任务通知API是:

对于单任务控制LED和读取按键我没有多说,因为和裸机控制差不多,比较简单

我想给大家讲的是FreeRTOS下多任务消息、数据互通的机制以及我在调试过程中因为疏漏遇到的bug

发出任务通知的API,其参数的解释我给大家翻译成中文放到表里面了

我们认为控制LED,只需要让LED任务能够获取到一个具体确切的控制通知即可,不需要复杂的置位、递增等

而且,即便led任务漏掉一次通知,也无所谓,所以采用了覆盖写任务通知的那个动作

但是我们可以完善,我们可以在上层发出控制LED指令后,去读取LED的状态,看LED是否真的根据控制指令做出了对应的响应

这就需要给LED加一个能读取状态的底层驱动以及在上层平台层做对应封装了

而且也要考虑我们是否可以用【不过滤写任务通知 】来规避下这种情况

获取任务通知值的API:



相比于

总是能获取到一个任务通知值,我们更倾向于使用

函数来等待获取一个新的任务通知值
既可以让我们获取到一个更新后的任务通知值,又可以顺便让任务进入阻塞状态,在大多数场合下,效果更佳

我在写完MQTT通知LED任务控制LED时,遇到了一个问题:LED任务根本没有被调度执行
这是由于我们在创建任务的时候:

我在MQTT任务和按键任务中没有做任何让步动作,又我们在FreeRTOSConfig.h中使能了抢占调度算法:

就导致最高优先级任务MQTT任务在一直运行

低优先级的任务根本没有机会被调度

所以我在MQTT任务的while(1)中加了一个vTaskDelay

按键任务的while(1)中也加了个延时

这样这个bug就解决了

然后是去写按键的控制任务

按键我们的做法是将按键信息读取到之后写入到队列中,MQTT任务的while(1)中读取队列消息,然后publish给服务器

队列的使用有三个动作:创建队列、写队列和读队列


创建队列,队列的单位可以是一个结构体大小,也可以是常规数据类型大小

我们任务中要创建的队列大小就是按键事件结构体的大小

写队列有三个API供我们使用


当前版本的FreeRTOS已经不推荐使用了
它的效果和是一样的

这两个API的接口,功能差异就是绿色注释所说的了
我们在任务中的使用:
其实这个还可以优化下
没有读到我们才调用延时让步调度,如果读取到按键了就通过写队列的API进入延时让步

我们是从ringbuffer里面读取出来放到队列里面,通过队列传输到另外个任务
读取队列的API:

我们现在用的这些API都是在非硬件中断中调用的

如果是在硬件中断中调用FreeRTOS的API,有另外的API

如果支持在硬件中断服务函数中调用,那么这些API的后缀都会有FromISR

要注意区分使用

对于读取按键任务的队列,我一开是在MQTT任务中这样使用的:
但是调试程序发现,欸,hardfault了
还是任务优先级导致的
我们是在按键任务中创建了队列,使得队列xKeyQueue这个句柄不是NULL;
但是MQTT任务的优先级比按键任务要高
他会先执行到自己的while(1)那里,在没开始调度按键任务的时候就先去对一个为NULL的xKeyQueue队列进行了读
也就是去访问了一个空指针
那肯定就会导致一个hardfault了
所以我的处理方式是:

先来判断下队列是否创建好了,如果没有就让步,让按键任务去执行创建好队列了来

那LED通过任务通知控制,按键通过队列传递发布这样一个业务逻辑我们基本就实现好了

我就顺势去阿里云物联网平台新建了一个mobile设备

想要一次性搞定设备和设备之间的发布订阅

创建设备、连接设备、订阅主题这些已经没啥好说的了

需要关注下的就是阿里云的云流转规则

我们需要做的是mobile设备发送led控制指令给mini板子,mini板子发送按键信息给mobile设备

但是mqtt协议中,一个确切的clientID只能共一个设备使用

当有两个设备使用同一个cliendID进行连接时,先连接的那个设备会被后一个挤下线

所以如果我们妄想两个设备都使用一个clientID连接服务器,然后进行自我转发,那是行不通的

需要建立两个设备,得到两个clientID,然后设置一套topic转发规则:
我们需要将mobile的ledCmd这样一个topic转发给MiniBoard的getLedCmd这个topic

将MiniBoard的keyInfo topic转发给Mobile的getKeyInfo topic

当我们创建好一个规则之后,切记要去启动它,使其生效


在应用复杂情况下,创建的规则就更多了

弄好云流转规则后,尝试用MQTT X连接mobile设备,往MiniBoard发送控制LED的指令的时候,发现开发板会漏指令

录完视频调试后发现是读取网络数据那里有bug
读取网络接收数据实际调用的接口就是

我们在这里面调用的是
底层用了HAL库的延时
这就导致,我们从mobile发送指令到服务器,服务器再转发给开发板的时候可能会导致我们在
这个地方阻塞了某次接收

我们在HAL_Delay做超时的时候,freertos的systick也是在运行的,那么在
这里超时的时候,
这个timeout也会在计数的
当我们的
因为超时退出后或者占用太多时间的时候,也有可能已经计数递减到了0

退出

这个函数的时候,返回一个为0的接收长度值

导致MQTT这个库在后面的流程中不会将我们读取出来的
这个buffer放到外面在MQTT任务一开始初始化客户端的时候定义的那个readbuf中
那我们的MQTTYeild
就会在这次尝试读之后直接返回一个0
不管是在哪一步被阻塞返回一个0值,都是有可能会使得我们读不到一个完整的订阅消息的
所以我将底层读取网络数据的驱动改了下

我不在底层超时堵塞了

我直接返回实际读到的长度

如果实际读到的长度不等于预期想要读取到的长度,那就返回实际读到的长度

如果两者等于,我就返回预期想要读取的长度,将那个记录实际读到的长度清零,等待下一次开启读取
在那三个步骤过程中任意地方xTimeout已经计数成0了的话


就会随时中断读取消息,从而导致漏掉消息,进入不了消息处理回调函数中去处理消息了。

其实消息还是保存到最底层的ringbuffer里面的

只是因为在下层堵塞导致上面的软件定时器的超时计数xTimeout提前被计数到0了

导致MQTT没有继续读取,超时退出了

才导致的漏掉一次消息,没有得到处理

解决了这个bug后,我们本期的物联网智能家居就算是完成了

但是还有其它的小问题,比如,我们频繁复位然后去连接阿里云服务器的mqtt设备,是容易出问题的,需要我们在程序中去做异常处理

以上内容均来自百问网7天物联网智能家居训练营

【百问网7天物联网智能家居】训练营学习笔记(七)相关推荐

  1. 【百问网7天物联网智能家居】训练营学习笔记(二)(需求分析,框架建立)

    构建一个项目的大致流程: 1,负责拉项目的同时,就叫市场部的同事吧,他们在外面和别的公司或者企业的人进行交流协商,得到一个项目: 2.然后再将这个项目交由研发部的负责人评估怎么做,研发部负责人召集手下 ...

  2. 百问网7天物联网智能家居 学习心得

    2020/2/12 打卡第一天 首先早上9点半黄老师准时开了,基础班第一节的培训. 主要讲的内容是:嵌入式的学习路线和职业规划.接下来我归类总结一下. 1.什么是嵌入式:电脑不属于嵌入式,以我的理解嵌 ...

  3. 百问网7天物联网智能家居 学习心得 打卡第五天

    打卡第五天. 2022/2/27基础班第五节培训. 主要讲的内容是:AT指令.网络基础.程序框架. 1.WiFi模块是用乐鑫的处理器,可以在百度上搜索乐鑫ESP8266.网站ESP8266 Wi-Fi ...

  4. 百问网7天物联网智能家居 学习心得 打卡第四天

    打卡第三天. 2022/2/16 基础班第三节培训. 主要讲的内容是:中断流程图.中断有那些(概括).中断优先级.GPIO中断. 1.中断流程图,程序开始时先执行主程序,这个时候如果发生中断了,暂停主 ...

  5. 百问网7天物联网记录(二)

    FreeRTOSConfig.h参数理解 ①调度算法 #define configUSE_PREEMPTION 1 //可抢占 #define configUSE_TIME_SLICING 1 //时 ...

  6. 7天物联网智能家居实战训练营(百问网)-day1

    目录 前言 一.学习路线 1.什么是嵌入式? 2.怎么学习嵌入式? 3.学习的基础内功? 二.基本概念 1.什么是arm? 2.arm架构的分类. 三.开发流程 1.交叉开发, 2.调试下载 前言 学 ...

  7. 【百问网】七天智能家居实战

    以下是我在百问网7天物联网智能家居学习中的一些心得体会 一.GPIO GPIO口有八钟工作模式:推挽输出.开漏输出.复用推挽输出.复用开漏输出.浮空输入.模拟输入.上拉输入.下拉输入. 推挽输出:控制 ...

  8. 单片机学习笔记1--资料下载、环境搭建(基于百问网STM32F103系列教程)

    第1篇 资料下载.环境搭建 第一章 百问网视频体系及学习路线 1.1课程视频变化 2011-2020:百问网录制了10年的Linux视频. 2021: 1.首次进入单片机领域,发布单片机课程! 2.重 ...

  9. 7天物联网智能家居实战-DAY7

    本课程时长七天 共计七次更新 文章目录 前言 1.课程内容 前言 这是七天物联网智能家居训练营的最后一节课了,整个课程可以说是从零开始,稳扎稳打,在七天这样一个很短的时间尺度上,确实能从毫无概念,到搭 ...

最新文章

  1. 【C++】clipp 一个命令行参数解析器
  2. 翻译 | 2015年的最佳Material Design集锦 【上篇】
  3. 神器!微软发布 Python 的 JIT 编译器:Pyjion!
  4. jquery实现上线翻滚效果公告
  5. 借助 CORS 从 JavaScript 使用 API 应用
  6. LNAMP 中的PHP探针
  7. TIMESTAMP与DATETIME的区别
  8. 摄影测量学之共线方程的应用
  9. 腾讯专访 | 子芽:代码疫苗技术,赋能数字化应用内生安全自免疫
  10. 定向士官学计算机网络技术可以吗,山东信息职业技术学院2016年定向培养士官招生问答...
  11. 威伦触摸屏入门布局提升题
  12. ubuntu虚拟机传文件到当前主机
  13. java 图片 pdf_Java 添加图片到PDF
  14. 高防CDN为什么会被TTCDN取代的?
  15. 【绘制矩形】已知二维平面矩形的对角线两点坐标,如何确定四个点的坐标
  16. 平面几何----向量证明欧拉线
  17. 山东标梵讲解APP开发与技术公司之间的联系
  18. 苹果显示未找到服务器,苹果浏览器找不到服务器是怎么回事
  19. mysql去重汇总_Mysql常用SQL汇总
  20. 名帖184 黄庭坚 行书《寄岳云帖》

热门文章

  1. GoldenGate—日常管理
  2. @Component和@ComponentScan
  3. 长江水质的评价和预测——主要污染地区
  4. USB-详解/sys/kernel/debug/usb/devices
  5. UI层自动化测试框架(三):基础层
  6. “双碳”背景下 数据中心气体灭火技术演进方向
  7. nodejs chalk 不起作用
  8. 有关数据包拓展基础知识
  9. Tomcat中设计模式
  10. 2022年华中科技大学计算机考研复试分数线