Rust嵌入式编程---panic处理和异常处理

news/2024/3/29 18:16:01/文章来源:https://blog.csdn.net/phthon1997/article/details/127101677

panic处理

我们之前学习过panic,这个部分对于Rust是非常重要的,例如索引等内置操作在运行时进行内存安全检查,当尝试超出边界索引时,这会导致恐慌。在标准库(Std)中,panic有一个定义的行为:它展开 panic 线程的堆栈,除非用户选择在 panic 时中止程序,否则会进行错误位置的一个堆栈定位。
但是,在没有标准库的程序中,恐慌行为是未定义的。可以通过声明函数来选择行为。此函数必须在程序的依赖关系图中只出现一次,并且必须具有以下签名:,其中 PanicInfo 是包含有关 panic 位置的信息的结构。#[panic_handler] fn(&PanicInfo) -> !
对于panic,有如下的一些常用种类:
1.panic_halt:死机会导致程序或当前线程通过进入无限循环而停止。
2.panic_abort:紧急导致中止指令被执行。
3.panic_itm:使用 ITM(一种特定于 ARM cortex-M 的外设)记录死机消息。
4.panic_semihosting:使用半主机技术将死机消息记录到主机,这个常用在qemu中,可以打印出错误信息。
这些panic的使用方法如下:
use panic_halt as _
use panic_semihosting as _
如果不重命名,编译器会警告说你有一个未使用的导入,当然不是错误,可以编译通过。
下面通过一个例子来理解一下,panic的使用方法,是一个数组访问越界的一个错误。

#![no_main]
#![no_std]use panic_semihosting as _;
use cortex_m_rt::entry;
#[entry]
fn main() -> ! {let xs = [0, 1, 2];let i = xs.len() + 1;let _y = xs[i]; //访问越界,加下划线变量就是说未使用不警告。loop {}
}

出现以下运行结果,用的是semihosting,会打印输出在这里插入图片描述
这里可以看到,对于panic,是程序运行时自动判断的,整个代码也就加了个semihosting的处理,使用起来很方便。你也可以试试其他类型的panic,观察结果的不同,其实也就是不同的panic处理方式。

异常处理

异常和中断是处理器处理异步事件和致命错误(例如执行无效指令)的硬件机制。异常意味着抢占,并涉及异常处理程序,即响应触发事件的信号而执行的子例程,这就是和。是硬件上的,而panic理解成软件上的,比如访问文件不存在啊、访问越界啊、除0操作等等,而且panic一般没有那么多处理方式,没有抢占和触发panic处理程序等等。cortex-m-rt crate 库提供了一个异常属性标志#[exception]用来声明一个异常处理。
SysTick是系统定时器,能产生周期性的中断。每当中断产生时,就执行处理函数SysTick()。系统定时器要能够产生定时中断,就要先初始化,设置时钟源,设置计数值,启动计数器,开启中断。
详细代码如下:

#![deny(unsafe_code)]
#![no_main]
#![no_std]use panic_halt as _;
use core::fmt::Write;use cortex_m::peripheral::syst::SystClkSource;
use cortex_m_rt::{entry, exception};
use cortex_m_semihosting::{debug,hio::{self, HStdout},
};#[entry]
fn main() -> ! {let p = cortex_m::Peripherals::take().unwrap();let mut syst = p.SYST;//将系统计时器配置为每秒触发一次SysTick异常syst.set_clock_source(SystClkSource::Core);syst.set_reload(12_000_000);//周期 = 1ssyst.clear_current();syst.enable_counter();//使能systick计数器syst.enable_interrupt();//使能中断loop {}
}#[exception]
fn SysTick() {static mut COUNT: u32 = 0;static mut STDOUT: Option<HStdout> = None;*COUNT += 1;// Lazy initializationif STDOUT.is_none() {*STDOUT = hio::hstdout().ok();}if let Some(hstdout) = STDOUT.as_mut() {write!(hstdout, "{}", *COUNT).ok();}if *COUNT == 9 {//qemu中运行到第九秒暂停退出debug::exit(debug::EXIT_SUCCESS);}
}

终端打印123456789后退出。

默认异常处理程序

该属性的实际作用是覆盖特定异常的默认异常处理程序。如果不重写特定异常的处理程序,则该函数将由函数处理,该函数默认为:exceptionDefaultHandler

fn DefaultHandler() {loop {}
}

你可以在“默认处理程序”上放置断点并捕获未处理的异常,当然也可以重写和覆盖。

硬故障处理程序

当程序进入无效状态时,将触发此异常,因此其处理程序无法返回,因为这可能导致未定义的行为。此外,运行时crate在调用用户定义的处理程序之前会执行一些工作,以提高可调试性。处理程序的参数是指向由异常推送到堆栈中的寄存器的指针。这些寄存器是触发异常时处理器状态的快照,可用于诊断硬故障。HardFaultfn(&ExceptionFrame) -> !
下面是一个执行非法操作的示例:读取不存在的内存位置。该程序在QEMU上不起作用,即它不会崩溃,因为不会检查内存负载,并且会在读取无效内存时返回。

#![no_main]
#![no_std]use panic_halt as _;
use core::fmt::Write;
use core::ptr;
use cortex_m_rt::{entry, exception, ExceptionFrame};
use cortex_m_semihosting::hio;#[entry]
fn main() -> ! {// 读取不存在的内存地址,注意写法unsafe {ptr::read_volatile(0x3FFF_FFFE as *const u32);}loop {}
}#[exception]
fn HardFault(ef: &ExceptionFrame) -> ! {if let Ok(mut hstdout) = hio::hstdout() {writeln!(hstdout, "{:#?}", ef).ok();}loop {}
}

处理程序打印值。如果运行此命令,您将在 OpenOCD 控制台上看到类似的内容。
在这里插入图片描述
该值是发生异常时程序计数器的值,它指向触发异常的指令,所以可以看一下pc的值指向的指令就是错误的地方。
在这里插入图片描述
这里可以看到,是因为ldr指令出现错误,也就是加载读取指令。

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

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

相关文章

有想去做的事,早早去做

心中有爱意&#xff0c;日子有活力 生命本质&#xff0c;在于更新 而美好人生&#xff0c;就是不断更新自己 人生的最好境界&#xff0c;就是苦尽甘来 疫情教会我的最大的道理就是&#xff1a;“有想去做的事&#xff0c;一定要早去&#xff0c;你永远不知道以后会怎样。 …

Redis(五)主从复制、集群

第一章 Redis 主从复制 1.1 主从复制是什么 主机数据更新后根据配置和策略, 自动同步到备机的master/slaver机制,Master以写为主,Slave以读为主 1.2 主从复制能干嘛读写分离,性能扩展 容灾快速恢复1.3 怎么玩:主从复制 拷贝多个redis.conf(redis配置文件)文件include(写…

Oralce ORA-00018超出最大会话数处理记录

项目场景&#xff1a; 线上系统JBOSS异常报错,信息如下 018-07-18 10:55:12,851 WARN [org.jboss.resource.connectionmanager.JBossManagedConnectionPool] Throwable while attempting to get a new connection: null org.jboss.resource.JBossResourceException: Could n…

基于Python-django-spider的影视演员影评爬虫与检索系统

目录 影视爬虫与检索系统 设计文档 1 一、 功能介绍展示 1 二、 性能统计信息 8 1、爬虫数据量统计 8 2、查询时间统计 8 三、 各个功能涉及的技术和实现方式 9 1、爬虫 9 2、django 10 3、html 10 4、css 10 一、功能介绍展示 1、影视列表页 为系统主页&#xff0c;通过分页方…

Dinky,让 Flink SQL 纵享丝滑

大家好&#xff0c;我是脚丫先生 流批一体&#xff0c;越来越流行了&#xff0c;牛逼一体。 之前用java封装flink-sql-client提交脚本文件&#xff0c;很是摩擦。 不过&#xff0c;在研发流批一体平台的时候发现了Dinky&#xff0c;终于丝滑了。 今天就给小伙伴们推荐下低调…

SkipList(跳表)

SkipList(跳表) 文章目录SkipList(跳表)参考前言跳表的原理跳表的插入和删除插入操作删除操作跳表的时间空间复杂度分析时间复杂度空间复杂度调表的基本操作插入数据删除数据Go 实现小结参考 https://juejin.cn/post/6844903955831619597#heading-2https://blog.csdn.net/qq_5…

C# ZBar解码测试(QRCode、一维码条码)并记录里面隐藏的坑

实现效果(文中含源码): C# ZBar解码演示 使用提醒(解码能力下降,甚至解错) C# ZXing解码介绍请查看下面文章: C# ZXing.net解码测试(QRCode、DataMatrix、1D-Barcode一维码条码)_Color Space的博客-CSDN博客 实现步骤: 1、需要的包及对应版本: ① ZXing.Net v0.16.8…

基于html+JavaScript+css的飞机射击小游戏网页设计与实现

目录 一、概述 1 1.1项目内容 1 1.2项目开发 5 1.3项目组员 5 1.4组员分工 5 1.5验收标准 5 二、项目介绍 5 2.1 目标 5 2.2 用户的特点 6 2.3 假定和约束 6 2.3.1 开发期限&#xff1a; 6 2.3.2 技术约束&#xff1a; 6 2.4 确定系统运行的要求 6 2.5飞机大作战的整理思路 6 三…

MySQL三种存储引擎的区别

文章目录一、引言二、三个存储引擎的介绍1&#xff0c;InnoDB介绍特点&#xff08;1&#xff09;事务处理、回滚、崩溃修复能力和多版本并发控制的事务安全&#xff08;2&#xff09;支持主键自增&#xff08;3&#xff09;支持外键&#xff08;4&#xff09;支持事务和事务相关…

jar包运行报错jar中没有主清单属性、springGateway访问接口报错302,跳转login接口

此处记录三个错误&#xff1a; 一、jar中没有主清单属性&#xff0c;打包以后运行报错&#xff1a; 这是一个gateway模块&#xff0c;包含了启动类&#xff0c;因为在pom文件中没有指定&#xff0c;所以报错&#xff1a;在该模块的pom文件中加入如下代码&#xff1a;com.xxxx…

Spring中IOC容器的基本配置使用

实例化bean对象 为外部定义的bean起别名 基于set方法的依赖注入 使用构造函数进行依赖注入 使用内部注入的方式注入bean对象 使用list集合依赖注入和使用map集合依赖注入 测试类 使用depends-on控制bean的加载顺序 使用懒加载lazy-init 默认为false 使用单例或者多例(原型)…

C#中对象与JSON字符串互相转换的三种方式

JSON(JavaScriptObject Notation, JS 对象标记) 是一种轻量级的数据交换格式。 关于内存对象和JSON字符串的相互转换,在实际项目中应比较广泛,经过一番搜索,找到如下三种方法来解决此问题 分别是使用Newtonsoft.Json.dll、DataContractJsonSerializer、JavaScriptSerializer…

【老板要你啥都会系列】| 前端晋升全栈--项目日志

目录 1.开篇 2.nodejs文件操作 3.stream 4.stream演示 5.写日志 6.拆分日志 7.分析日志介绍 8.readline 1.开篇 日志包含什么访问人数啊、峰值啊、bug 啊什么的&#xff0c;如果没有日志那么很容易失控。 访问日志可以参考我们 http-server&#xff0c;每次访问都会有这…

谐振波导光栅的严格分析

摘要 谐振波导光栅(RWG)由于其在波长、相位和偏振等方面的可调谐性&#xff0c;在研究和工业中有着广泛的应用。RWG的结构包含一个薄的高折射率波导薄膜&#xff0c;该薄膜与光栅接触。波导支持多种导模&#xff0c;并且根据厚度的不同&#xff0c;模式的数量也不同。在这个…

javaFx打包exe程序

文章目录将代码打成jar包准备工作下载exe4j定制jre检测jar包用到jre的哪些jmods生成jre准备exe图标使用exe4j将jar转换成exe程序将代码打成jar包 打jar之前&#xff0c;把那些用不到的依赖统统删除&#xff0c;以免包含一些无用的内容&#xff0c;比如用不上的一些依赖jar&…

特征工程之特征降维-特征选择-PCA/LDA

特征降维之特征选择 特征选择是建模中常用的降维手段&#xff0c;比较暴力&#xff0c;直接将不重要特征删除。 缺点&#xff1a;造成信息丢失&#xff0c;不利于模型精度。【与之形成对比的是PCA、LDA等降维方式。】 主要标准有两个&#xff1a; 特征是否发散。特征与目标的…

简单组件讲解

在编程阶段,会遇到有些页面的某一区域的布局或数据显示类似;那么我们就可以复用这一段代码;在使用原生JS编程时,我们习惯是将代码抽出来自成一个文件,需要时引入即可。而在vue中也存在这样一个模块,可以简便的将可复用的代码抽成一个模块,这个就是组件。在很多人看来,组…

产品-如何让用户“更愿意“付费

学院课程 文章目录学院课程前言如何提高用户体验,吸引用户付费关于程序员等级的划分基础免费试看优质博客内容转化为视频用户关于短视频内容的生成关于利用用户的碎片化时间怎么差异化竞品&#xff1f;短视频赛道理解学院现状分析总结前言 学院地址 今天下午公司组织了一场需求…

线性回归

线性回归 导入库 import numpy as np import pandas as pd import matplotlib.pyplot as plt人工数据集n = 100 true_theta = np.array([[1], [1]]) X = np.insert(np.random.normal(5, 1, size=(n, 1)), 0, 1, 1) y = X @ true_theta + np.random.normal(0, 0.04, size=(n, …

Azure | AZ-204 认证之旅-应用服务(二)

theme: orange 我正在参加「掘金启航计划」 Web应用是构建在PaaS层的服务&#xff0c;它是支持托管的&#xff0c;并且是可缩放的&#xff0c;极大提高了工程效率&#xff0c;并且减少了在运营的层面的消耗&#xff0c;这篇文章介绍如何创建应用程序服务。 创建Web应用程序服务…