大连建站费用,吉林网站制作,网站建设售后协议,科技公司网站案例本书的原著为#xff1a;《Design Patterns for Embedded Systems in C ——An Embedded Software Engineering Toolkit 》#xff0c;讲解的是嵌入式系统设计模式#xff0c;是一本不可多得的好书。
本系列描述我对书中内容的理解。本文章描述访问硬件的设计模式之六…本书的原著为《Design Patterns for Embedded Systems in C ——An Embedded Software Engineering Toolkit 》讲解的是嵌入式系统设计模式是一本不可多得的好书。
本系列描述我对书中内容的理解。本文章描述访问硬件的设计模式之六中断模式。
物理世界本质上是并发和异步的。 并发 是指在同一时刻有多个活动通常是任务或进程正在发生或进行。在单线程环境中并发通常是通过时间片轮转等机制模拟出来的而在多线程或多核处理器环境中多个任务可以同时进行。 并发编程的目标是最大限度地利用计算资源提高程序的响应性和吞吐量。为了实现并发开发者通常会使用多线程、多进程、异步I/O等技术。异步操作 是指程序的某个部分可以在不等待其他部分完成的情况下继续执行。在异步编程中任务的执行不会阻塞当前线程或进程而是会立即返回并在后台继续执行。当任务完成时通常会通过回调函数、事件、Promise等方式通知程序的其他部分。 异步编程的主要好处是提高程序的响应性和性能因为它允许程序在等待资源如I/O操作时继续执行其他任务。 在嵌入式系统和低级系统编程中中断 是一种强大的机制用于响应和处理外部事件或内部状态变化。中断处理程序是与特定中断类型相关联的代码段当该类型的中断发生时处理器会自动跳转到该代码段执行。由于中断可以打断正在执行的程序因此它们提供了一种并发和异步处理事件的方式。这对于实时系统和嵌入式系统来说尤为重要因为这些系统需要能够及时响应和处理外部事件以确保系统的正确性和可靠性。此外中断处理程序还可以用于实现诸如定时器、串行通信、输入/输出等操作从而提高了系统的功能和性能。
摘要
中断模式在嵌入式系统和实时系统中非常常见因为这些系统需要能够及时响应和处理外部事件。为了实现中断模式开发人员需要利用处理器和编译器提供的中断服务例程ISR机制。ISR是与特定中断源相关联的代码段当中断发生时处理器会自动跳转到该代码段执行。在ISR中开发人员可以编写用于处理中断事件的逻辑代码。处理完中断事件后处理器会返回到被中断的程序继续执行。
问题
中断模式是一种强大且有效的机制用于处理紧急和高频事件。与轮询模式相比中断模式能够确保及时响应和处理这些事件从而提高系统的实时性和可靠性。在中断模式中当紧急事件发生时处理器会立即暂停当前任务跳转到与该事件相关联的中断服务例程ISR进行处理。处理完成后处理器会返回到被中断的任务继续执行。这种机制确保了紧急事件能够得到优先处理而不会被其他低优先级的任务所阻塞。
模式结构
模式结构图如下所示
模式详情
中断处理
中断向量是一个指向中断服务例程ISR的指针或地址当中断发生时系统会查找对应的中断向量并跳转到该向量指向的中断服务例程去执行。因此通过修改中断向量表我们可以控制哪个中断服务例程响应特定的中断。
中断处理 的 install() 和 deinstall() 函数提供了一种机制来动态地修改中断向量表。这使得我们可以在运行时安装或卸载中断服务例程从而灵活地处理不同的中断事件。
每个 handleInterrupt_x() 函数都处理一个特定的中断并以“从中断返回”Return From InterruptRTI语句结束。这条语句依赖于编译器和处理器。如前所述至关重要的是中断服务例程不能有参数这就是原因。否则当它们尝试返回时将会从CPU堆栈中弹出错误的值。
中断向量表
InterruptVectorTable中断向量表实际上就是一个包含中断服务例程地址的数组。它位于处理器特定的内存位置。当中断号x发生时CPU会暂停当前的处理并间接调用该表中与第x个索引对应的地址。在RTI从中断返回指令执行后CPU会恢复被暂停的任务。
效果
中断处理模式在嵌入式系统、操作系统和实时系统中非常常见因为这些系统需要快速响应外部事件或内部状态变化。通过中断系统可以在不等待当前任务完成的情况下立即处理紧急事件从而提高系统的响应性和实时性。
然而由于中断会打断正常的程序流程因此在使用中断时需要特别小心。如果中断服务例程执行时间过长或者频繁触发中断可能会导致系统性能下降或任务延迟。通常当中断服务例程正在执行时会禁用中断(不允许中断嵌套)这意味着中断服务例程必须执行得非常快以确保不会错过其他中断。
由于中断服务例程ISR必须简短因此如果在中断服务例程中调用其它系统服务时必须小心。例如为了共享由中断发出的数据中断服务例程可能需要将数据排入队列并快速返回在将来的某个时刻应用软件会在队列中发现这些数据。当数据的实际获取比其处理更为紧急时这种机制非常有用。通过这种方式可以将一个长时间的中断处理程序分解成两个部分紧急部分通过中断服务例程本身完成处理部分通过第二个函数完成该函数定期检查数据或信号。
如果中断服务例程处理时间过长会延迟系统对其他中断的响应可能导致实时任务错过截止时间或系统性能下降。这通常发生在中断服务例程执行了不必要的复杂操作或者等待了某些不可用的资源。实现错误导致中断被禁用也是一个常见问题。当中断被禁用时系统无法响应外部事件可能导致重要任务被延迟或错过。这种错误通常是由于程序员对中断管理的不当理解或疏忽造成的。然而共享资源上的竞争状态和死锁可能是最为棘手的问题。当多个中断服务例程或任务需要访问共享资源时如果没有采取适当的同步措施就可能出现竞争状态。这可能导致数据不一致、系统崩溃或其他不可预测的行为。死锁是竞争状态的一种极端情况它发生在两个或多个中断服务例程或任务相互等待对方释放资源时导致系统无法继续执行。
为了避免这些问题需要采取一系列措施。首先中断服务例程应该尽可能简短和高效避免执行复杂操作或等待不可用资源。其次需要确保中断管理代码的正确性避免由于实现错误导致中断被禁用。最后对共享资源的访问需要采取适当的同步措施如使用锁、信号量或互斥量等机制来避免竞争状态和死锁的发生。 竞争状态Race Condition和死锁Deadlock都是并发编程中常见的问题: 竞争状态 指的是当两个或多个进程在没有适当同步的情况下访问共享的数据或资源并且至少有一个进程在修改这些数据或资源时最终的结果将取决于这些线程或进程的执行顺序。由于进程调度的不确定性这可能导致不可预测和不可重复的结果。竞争状态通常是由于缺乏适当的同步机制如互斥锁、信号量等来确保对共享数据的互斥访问而引起的。死锁 则是指两个或多个进程在等待对方释放资源时陷入无限等待的状态导致系统无法继续执行。这通常是由于每个进程都持有一个资源并请求另一个进程持有的资源从而形成了一个循环等待的情况。如果没有外部干预死锁将导致系统停滞不前无法完成任何有用的工作。 如果中断服务例程和应用程序服务之间共享变量或数据结构如队列则访问这些资源构成了潜在竞争状态和死锁条件因为你永远无法准确知道何时会执行中断服务例程。
下图展示了一种典型结构其中中断服务例程与正常应用程序都访问同一共享资源该共享资源是一个复杂数据结构。当应用程序正在访问共享资源时发生中断就会出现竞争状态。想象一下如果应用程序在读取数据的过程中该读取操作不是原子操作发生了中断中断服务例程将会暂停应用程序的读取操作转而执行中断服务例程在此期间修改数据然后返回到应用程序。这样应用程序将会看到损坏的数据——部分是新的数据部分是旧的数据。 对于这个问题有多种解决方案但它们都涉及到对共享资源的序列化访问。一种方法是在应用程序读取数据之前禁用中断并在访问完成后重新启用中断。另一种方法是使用互斥信号量来保护数据如下图所示。 在这张图中共享资源 是受互斥信号量保护的当调用 getData() 或 setData() 函数时会给资源 加锁 。当函数完成时会给资源 解锁 。如果 中断服务例程 在尝试访问数据时等待信号量锁就可能发生死锁。由于中断服务例程已经中断了拥有锁的 应用程序假如中断服务程序一直等待信号量锁则应用程序永远没有机会移除锁因为它得不到运行无法释放锁。当然解决方案是中断服务例程不能等待锁。新数据可以被丢弃或者可以创建两个共享资源但规定中断服务例程或应用程序一次只能锁定其中一个资源。后一种解决方案有时被称为“双缓冲区”。双缓冲区方案比较复杂如果你不希望这么做那么唯一的选项是应用程序读取数据之前禁用中断通常这是简单又常用的方案。