中断中的数据分享
侧边栏壁纸
  • 累计撰写 10 篇文章
  • 累计收到 1 条评论

中断中的数据分享

Logiase
2020-12-18 / 0 评论 / 3 阅读 / 正在检测是否收录...

在这篇文章中会简单介绍什么是中断和它在 Rust 中如何工作.

还有简单的防止脏数据,竞态的讲解.

处理中断

中断

中断是一种硬件处理,用来让嵌入式系统对识别到的特殊事件作出反应,暂时中断正常的程序,并对引起中断的事件作出反应。

这不仅仅是嵌入式处理器所独有的,它也存在于常规 CPU 上。在 CPU 上,中断常常用来处理外部设备,例如 PCI ,他们通过生成特别的中断信号来通知系统事件. 当然中断不仅仅能够由外部设备所引起,也可以由处理器内部引起,例如,发生了内存访问错误,定时器到期等等。

为了在一个系统上使用中断,会有一个名叫 interrupt conrtoller 的特殊硬件,在 STM32 中叫做 NVIC (Nested Vectored Interrupt Controller (内嵌向量中断控制器)),可以通过对它进行控制来启用中断,配置中断的优先级. 高优先级的中断可以像打断正常程序一样打断低优先级中断.

中断处理

中断函数是一种特殊的函数,当中断发生时,系统便会中断当前程序进入相应的中断处理函数之中。许多中断控制器都是嵌套设计的,即上面所说的,可以进行中断嵌套。当发生中断时,系统通常会把所有的处理资源都给中断函数。

这就引起了一个问题,当我们的正常程序或一个低优先级的中断函数在使用一项系统资源,突然发生了一个高优先级中断,打断了当前正在进行的资源调用,并很有可能使用同一项系统资源,通常会导致一个竞态。

很容易想象,发生这种问题会有多严重. 不过有很多种方法可以解决这种问题,对一个单核系统来说(多核系统可以并行执行代码,这会带来额外的问题),最简单的操作就是:

  • 将所有中断设为同一优先级,中断之间没有抢占,也就不会有竞态,也就安全了
  • 暂时禁用中断. 又叫临界区 Critical Section

分享资源

正常情况下,大概率你都会在正常程序和中断函数中共享同一项资源,所以正确的管理程序不同部分对资源的访问是很重要的。

资源类型

我们通常情况下要考虑两种资源:

数据

数据可以是任何在 RAM 中的结构. 在我们所写的应用中,数据大多数是一个简单的变量或是一个 Buffer 。

外设

在经典的微控制器中,所有的外设都可以通过内存映射地址来访问和操作.

访问管理

有三种基本机制来管理对这些资源的访问

单例

每个函数,中断处理函数,内存地址等等都只能存在一个,在大多数情况下,Rust 都保证这一点,但是Rust并不能对原始的内存地址指针做安全处理,所以直接将内存地址解引用是 unsafe 的. 但是我们实际上往往需要对这些内存地址进行访问,但还想让 Rust 来保护安全,那么该怎么做?

方法是,我们将这些内存地址映射到一个能够为我们提供安全使用它们的抽象方法的一个类型中,然后把它包装成一个单例,这样就可以安全的操作这些内存地址,安全问题就由 Rust 来保证。

共享

在 Rust 中共享资源非常简单,你只需要传递他们的引用,Rust 的安全规则便会自动的保证生命周期与变量是否可变。

然而,如果因为存在中断而涉及到非线性程序流,上面的做法在实际中会变得非常麻烦. 一旦有中断或是线程调度这种外部控制干扰了单向的程序流,那所有需要共享的资源就需要一层可以对它进行保护的包装了. 对线程来说,我们有 Sync Trait 来保证并发访问,但这实际上需要一个高层次的监督者来保证,在嵌入式系统中基本是不可用的。

转移所有权

与共享类似,Rust 没法追踪到进入到中断处理函数的资源的所有者与生命周期. 因为在 Rust 眼中,这些甚至都不是程序的一部分,而是一段存在的,但是没有被调用的函数.

因此,需要一个对资源的预防措施,让这部分资源在“正常”的函数中初始化,然后又假定它被移动到一个“不存在”的函数中。

0

评论 (0)

取消