裸机编程的几种模式、架构、缺陷

目录

裸机编程模式/架构 1:初始化代码的编写

裸机编程模式/架构 2:轮询模式

裸机编程模式/架构 3:轮询加中断执行模式

裸机编程模式/架构 4:中断+定时器+主循环的前后台架构

裸机编程模式/架构 5:前后台 + 状态机架构 

嵌入式常见的操作系统


绝大多数嵌入式初学者都从裸机编程开始,因为它更加直观、简单。通过裸机编程,你能够直接操作硬件,代码所见即所得,调试也非常方便。相比使用操作系统,裸机编程无需掌握大量的操作系统基础知识和调度机制的常识,也不需要考虑资源共享和竞争等概念。此外,裸机编程的调试过程也更加直观。

下面是裸机编程中常见的模式和架构:

1. 引脚配置和外设初始化:裸机编程的第一步是配置芯片的引脚和初始化外设。通过配置引脚的功能和模式,你可以连接和配置各种外设,如串口、定时器等。

2. 中断处理:中断是裸机编程中处理外部事件的常见方式,如定时器溢出、串口接收等。通过设置中断向量表和编写中断服务函数,你可以对外部事件进行及时响应和处理。

3. 状态机:裸机编程中经常使用状态机来处理复杂的任务。状态机将任务拆分为不同的状态,并根据当前状态和外部事件的触发来进行状态转移和处理。

4. 轮询方式:对于较简单的任务,裸机编程可以使用轮询方式来实现。也就是不断地查询和检测外部事件的状态,并根据需要做出相应的响应和处理。

5. 低功耗模式:裸机编程中可以通过设置芯片的低功耗模式来降低系统功耗。这可以通过配置和操作控制器状态机来实现。

 6. 调试和测试:裸机编程具有直观性和简单性的特点,因此在调试和测试方面也相对容易。你可以使用调试器、示波器等工具来查看寄存器的值和程序的执行流程,以便定位问题并进行调试。 这些是裸机编程中常见的模式和架构。

对于初学者来说,裸机编程在一些相对简单的项目上具有一定的优势。然而,对于复杂的应用场景,使用操作系统和软件抽象层会更具优势。

裸机编程模式/架构 1:初始化代码的编写

裸机编程模式/架构 2:轮询模式

这些函数依次执行,全部执行完毕后再次从 第一个逻辑开始,以此不断循环。

这种模式是最简单也是最初级的模式,但其也存在很多问题。由于上述的每一个逻辑会依次执行,那么就会相互影响,因为是裸机嘛, 代码是串行执行的, 就会出现实行性不好的情况。

比如后续逻辑中存在一些交互行为,Key_Task()会判断一个按键的按下状态并做出响应,而此时还在 RTc_Task()中执行延时指令,那么整体运行就会显得非常卡顿,甚至还会因为错过用户按键的时机而导致即使按下了按键,也没有执行对应的反馈。这个实行性的问题也就是裸机的最大缺陷!

裸机编程模式/架构 3:轮询加中断执行模式

/* 按键中断的ISR */
void Key_Isr(void)
{do_c();
}void main()
{/* 初始化 *//*...*/while(1) {do_a();do_b();}}

如上图所示, 当程序中出现交互的设计的时候, 采用外部中断确实很好的解决了按键按下立马得到响应, 这种模式其实在很多简单的应用场景下已经够用了, 那我们接下来来挑一下这种模式的缺陷。

假设现在我有这样的一个需求, 需要在while(1)的轮询模式中, do_a()和do_b()每隔一定的时间调用一次, 是不是相当于这样。

/* 按键中断的ISR */
void Key_Isr(void)
{do_c();
}void d0_a()
{delay(100);
}void d0_b()
{delay(200);
}void main()
{/* 初始化 *//*...*/while(1) {do_a();do_b();}}

最初的想法是do_a()这个函数每隔100ms调用一次, 如果while(1)只有这个任务, 且不产生中断的情况, 是可以达到我们设想的要求的。但是有了中断和while(1)中不只执行一个函数的时候, 这种设计就是失败的。

裸机编程模式/架构 4:中断+定时器+主循环的前后台架构

__IO uint32_t a_tick, b_tick;/* 按键中断的ISR */
void Key_Isr(void)
{do_c();
}void d0_a()
{if(uwTick - a_tick < 100)return;a_tick = uwTick ;/*..*/
}void d0_b()
{if(uwTick - b_tick < 200)return;b_tick = uwTick ;/*..*/
}void main()
{/* 初始化 *//*...*/while(1) {do_a();do_b();}}

上述代码使用的system timer, 每隔1ms将uwTick这个全局变量加1, 使用定时器来辅助确定调用函数的时间间隔。这样, 就能保证在这种模式下while(1)中的每一个任务每隔一定的时间调用一次。

由于去掉了每个逻辑中的延时,取而代之的是标志位的判断,其执行速度是非常快的,如上图所示 ,灰色的块表示在运行判断逻辑并且没有满足运行要求。这种情况下每个逻辑都能在其指定的周期内得到执行。

这种架构在裸机编程中可以算得上一种中高级的架构,能够满足大多数不是特别复杂的需求。当然,在上图中我们可以看到 do_a 和 do_b 一个为 100 毫秒,一个为 50 毫秒,存在公倍数情况,也就是说在某一时刻,如这里的 0 毫秒和 100 毫秒,就会出现两个逻辑同时运行的场景。实际在项目中如果要求比较严格,会对这个周期进行一个控制和计算,尽量减少各逻辑同时执行的概率,避免由于同时执行的逻辑过多且过于频繁,执行时间的总和仍然会太长,从而影响整体运行稳定性的问题。

到这里请思考一下,假如 do_a 逻辑本身的执行时间就很长,比如进行一个非常复杂的运算,或者需要读取一个 G 级别的文件,导致单一逻辑的执行时间就超过了最小周期(如例子中的 50 毫秒),那即使 50 毫秒的周期到了,由于 do_a 还没运行完,do_c 也无法得到运行,这时候时间标志已经形同虚设,甚至由于此处是取余判断,假如 do_a 运行了 51 毫秒结束,do_b 在判断的时候已经是 52 毫秒,52%50 不为零,do_b 直接无法执行,时间标志甚至产生了负面影响!

虽说将 “通过取余运算判断是否可以执行的逻辑” 修改为 “设置多个时间标志(如 50ms_flag、100ms_flag等),在中断中判断满足时间就将这些标志置位,主循环中直接对这些标志进行判断的逻辑” 可以避免由于时间后延导致的无法触发逻辑执行问题,但仍然无法解决周期被影响的本质。

裸机编程模式/架构 5:前后台 + 状态机架构 

void do_a(void) {static unsigned char step = 0;if (tick % 100 == 0) {switch (step) {case 0:// 执行第一步step++;break;case 1:// 执行第二步step++;break;case 2:// 执行第三步step = 0;break;default://  未知步骤,归零重来step = 0;break;}} else {return;}
}

可以观察到原先的执行方式do_a,我们将其视为一个不可拆分的逻辑,直到完整执行完成才会退出。而现在,我们将其分解为三个步骤,在执行完一个步骤后就会退出do_a函数,在下一次进入时执行下一个步骤。这样一来,能够有效缩短每次执行do_a所需的时间,大大降低了执行时间超过最小周期的可能性。主循环中的其他应用逻辑也采用了类似的状态机模式,以加快主循环的响应效率,进一步提高了裸机编程的稳定性和时间可控性。 状态机的引入使裸机编程达到了其终极形态,使其能够处理更复杂的逻辑和应用。同时,代码量和复杂度也急剧增加,特别是当主循环中存在十几个甚至几十个任务逻辑时,面对的编程难度就变得非常高。 当然,即使你能够应对极高的挑战,最终仍会遇到一个问题——随着应用逻辑的增加,同时执行大量状态机分支步骤的时间总和很难再人工进行分解,而且不幸的是,它们的执行时间总和超过了预定的周期,导致了各种问题的出现。

此时恭喜你,已经达到了裸机编程的巅峰,也是裸机编程的极限。是时候迈开脚步,进入操作系统编程的领域了!

嵌入式常见的操作系统

类Unix操作系统

物联网操作系统/实时操作系统

以及uc/os, 华为的lite os等等, 大家都可以去学习学习其操作系统提供给我们的机制, 为什么使得我们的编程, 提升了上限。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

初次实战SQL注入

目录 1.判断漏洞是否存在 2.判断注入类型&#xff08;数字型/字符型&#xff09; 3.猜列数 4.联合查询判断回显位 6.获取数据库表明 此实验为本人学习内容&#xff0c;从未攻击任何网站&#xff01;&#xff01;&#xff01;请伙伴们同样遵纪守法&#xff01;&#xff01;…

24计算机考研深大经验分享(计算机专业考研综合安排)

文章目录 背景科目选择高数选课一轮二轮冲刺阶段 线代一轮二轮 概率论计算机学科专业基础408数据结构计算机组成原理操作系统计算机网络总结 英语政治 末言 背景 首先贴一下初试成绩。这篇分享主要是给零基础的同学使用的&#xff0c;基础好的同学可以自行了解补充一下&#xf…

CTP-API开发系列之柜台系统简介

CTP-API开发系列之柜台系统简介 CTP-API开发系列之柜台系统简介中国金融市场结构---交易所柜台系统通用柜台系统极速柜台系统主席与次席 CTP柜台系统CTP组件名称对照表CTP柜台系统程序包CTP柜台系统架构图 CTP-API开发系列之柜台系统简介 中国金融市场结构—交易所 我们知道提…

【Flink入门修炼】2-2 Flink State 状态

什么是状态&#xff1f;状态有什么作用&#xff1f;如果你来设计&#xff0c;对于一个流式服务&#xff0c;如何根据不断输入的数据计算呢&#xff1f;又如何做故障恢复呢&#xff1f; 一、为什么要管理状态 流计算不像批计算&#xff0c;数据是持续流入的&#xff0c;而不是…

网络编程(3/4)

广播 ​ #include<myhead.h>int main(int argc, const char *argv[]) {//1、创建套接字int sfd socket(AF_INET, SOCK_DGRAM, 0);if(sfd -1){perror("socket error");return -1;}//2、将套接字设置成允许广播int broadcast 1;if(setsockopt(sfd, SOL_SOC…

javascript基础入门

1.第一个javascript程序 javascript程序不能够独立的运行&#xff0c;必须依赖于HTML文件&#xff0c;type属性值用来说明脚本的类型&#xff0c;这里 是指使用javascript编写的文本文件&#xff1b; 2.alert警告框 alert&#xff08;&#xff09;函数显示一条指定的信息&am…

Vue router文件中本地路由配置使用i18n【解决tab名称出现undefined,导致i18n没有实现问题】

问题 点击按钮 跳转详情页后 tab名称出现错误&#xff0c;报 undefined ## 需求 点击工单详情按钮&#xff0c;跳转详情页面&#xff08;新页面&#xff09;&#xff0c;新页面tab栏名称 还是为 工单出库&#xff0c;但要求工单出库文字配置为多语言&#xff0c;使用i18n来配置…

[云原生] K8s之pod控制器详解

Pod 是 Kubernetes 集群中能够被创建和管理的最小部署单元。所以需要有工具去操作和管理它们的生命周期,这里就需要用到控制器了。 Pod 控制器由 master 的 kube-controller-manager 组件提供&#xff0c;常见的此类控制器有 Replication Controller、ReplicaSet、Deployment、…

SQOOP安装与使用

SQOOP安装及使用 文章目录 SQOOP安装及使用SQOOP安装1、上传并解压2、修改配置文件3、修改环境变量4、添加MySQL连接驱动5、测试 准备MySQL数据登录MySQL数据库创建student数据库切换数据库并导入数据另外一种导入数据的方式使用Navicat运行SQL文件导出MySQL数据库 importMySQL…

购买使用静态住宅代理IP前,你需要测试的5件事

静态住宅代理IP&#xff0c;是一种在网络通信过程中提供固定IP地址的代理服务。与动态代理IP相比&#xff0c;静态代理IP提供的是持久且不变的IP地址。这种稳定性使得静态代理IP在需要长期稳定网络身份的场景中&#xff0c;如跨境电商/社媒养号、网络监控、品牌保护、长期数据爬…

安卓使用ExoPlayer出现膨胀类异常

1.导包 implementation com.google.android.exoplayer:exoplayer-core:2.15.1implementation com.google.android.exoplayer:exoplayer-ui:2.15.1 2.在Androidifest.xml加入权限&#xff0c;我这里加了网络与读写权限 <uses-permission android:name"android.permissio…

windows中使用nnUNet的nnUNet_convert_decathlon_task提示路径不对

找到问题并且解决解决办法 报错时候的指令 nnUNet_convert_decathlon_task -i D:\桌面\nnUNet\DATASET\nnUNet_raw\nnUNet_raw_data\Task05_Prostate 修改为 nnUNet_convert_decathlon_task -i D:/桌面/nnUNet/DATASET/nnUNet_raw/nnUNet_raw_data/Task05_Prostate 修改点&…

H5双人五子棋小游戏

H5小游戏源码、JS开发网页小游戏开源源码大合集。无需运行环境,解压后浏览器直接打开。有需要的,私信本人,发演示地址,可以后再订阅,发源码,含60+小游戏源码。如五子棋、象棋、植物大战僵尸、开心消消乐、扑鱼达人、飞机大战等等 <!DOCTYPE html> <html> <…

移动开发:网格视图

一、在新建GridView模块下添加图片以及创建cell.xml文件 1.粘贴图片时选择红框中的路径&#xff0c;点击“OK” 2.在路径后添加-mdpi后缀,再点击“OK” 二、相关代码块 1.MainActivity.java文件代码 package com.example.gridview;import androidx.appcompat.app.AppCompatAc…

备考2024年北京高考数学:20114~2023十年选择题练习和解析

距离2024年高考还有三个月的时间&#xff0c;如何用三个月的时间再提高北京数学高考的成绩&#xff1f;吃透历年真题以及背后的知识点是行之有效的方法 之一。 今天我们来看一下2014-2023年的北京市高考数学的选择题&#xff0c;从过去十年&#xff08;2014-2023&#xff09;的…

面试问答总结之并发编程

文章目录 &#x1f412;个人主页&#xff1a;信计2102罗铠威&#x1f3c5;JavaEE系列专栏&#x1f4d6;前言&#xff1a;&#x1f380;多线程的优点、缺点&#x1f415;并发编程的核心问题 &#xff1a;不可见性、乱序性、非原子性&#x1fa80;不可见性&#x1fa80;乱序性&am…

【真机Bug】异步加载资源未完成访问单例导致资源创建失败

1.错误表现描述 抽卡时&#xff0c;10抽展示界面为A。抽取内容可能是整卡或者碎片&#xff0c;抽到整卡&#xff0c;会有立绘展示和点击详情的按钮。点击详情后出现详情页B。【此时界面A预制体被销毁&#xff0c;卡片数据进入数据缓存池】点击页面B的返回按钮&#xff0c;单例…

刚刚,OpenAI官方发文驳斥马斯克,自曝8年间邮件往来截图

文章开篇表示&#xff1a;「OpenAI 的使命是确保 AGI 惠及全人类&#xff0c;这意味着既要构建安全、有益的 AGI&#xff0c;又要帮助创造广泛的利益。我们正在分享我们在实现使命方面所学到的知识&#xff0c;以及有关我们与马斯克关系的一些事实。我们打算驳回马斯克的所有主…

回归啦!!!

消失的日子在实习&#xff0c;今天最后一天了来看看自己的学习日志&#xff0c;有没有可以和小伙伴交流的部分吧&#xff01; 目录 一、产品one ①简介 ②底层原理 ③知识点一 作用一&#xff1a;日志采集 作用二&#xff1a;实时监测 作用三&#xff1a;规则匹配 作用…

Word中Endnote加载项不见了怎么处理?

打开word-①文件-②选项-③加载项 勾选endnote cite while you write 完成上述操作后&#xff0c;endnote便出现在菜单栏中。