8

由于特定中断发生,我需要运行一些代码。

我不想在中断本身的上下文中执行它,但我也不希望它在线程模式下执行。

我想以低于促使其运行的高级中断但也高于线程级别(以及其他一些中断)的优先级运行它。

我想我需要使用其他中断处理程序之一。

哪些是最好的使用,以及调用它们的最佳方式是什么?

目前,我计划只对一些我不使用的外围设备使用中断处理程序,并通过直接通过 NVIC 设置位来调用它们,但我希望有更好、更正式的方式。

谢谢,

4

5 回答 5

16

ARM Cortex 支持一种非常特殊的异常,称为 PendSV。您似乎可以完全使用此异常来完成您的工作。几乎所有用于 ARM Cortex 的抢占式 RTOS 都使用 PendSV 来实现上下文切换。

为了使其工作,您需要优先考虑 PendSV 低(将 0xFF 写入 NVIC 中的 PRI_14 寄存器)。您还应该优先考虑 PendSV 之上的所有 IRQ(在 NVIC 中的相应优先级寄存器中写入较低的数字)。当您准备好处理整个消息时,从高优先级 ISR 触发 PendSV:

*((uint32_t volatile *)0xE000ED04) = 0x10000000; // trigger PendSV

然后,ARM Cortex CPU 将完成您的 ISR 和所有其他可能被它抢占的 ISR,最终它将尾链到 PendSV 异常。这是您用于解析消息的代码所在的位置。

请注意,PendSV 可能会被其他 ISR 抢占。这一切都很好,但是您显然需要记住通过代码的关键部分(简要禁用和启用中断)来保护所有共享资源。在 ARM Cortex 中,通过执行 __asm("cpsid i") 禁用中断,并通过 __asm("cpsie i") 启用中断。(大多数 C 编译器为此提供了内置的内在函数或宏。)

于 2010-05-02T22:31:32.267 回答
3

你在使用 RTOS 吗?通常,这种类型的事情将通过具有高优先级的线程来处理,该线程会通过中断发出信号以执行某些工作。

如果您不使用 RTOS,您只有几个任务,并且由中断启动的工作不会占用太多资源,在中断处理程序的上下文中完成高优先级工作可能是最简单的。如果这些条件不成立,那么实现您所说的将是基本多任务操作系统本身的开始。这本身就是一个有趣的项目,但如果您只想完成工作,您可能需要考虑一个简单的 RTOS。

由于您提到了有关您正在做的工作的一些细节,以下是我过去如何处理类似问题的概述:

为了通过 UART 处理接收到的数据,我在处理不完全支持任务的更简单系统(即,任务在简单while循环中循环)时使用的一种方法是拥有一个共享队列对于从 UART 接收到的数据。当 UART 中断触发时,数据从 UART 的 RDR(接收数据寄存器)中读取并放入队列中。以不损坏队列指针的方式处理此问题的技巧是小心地使队列指针易失,并确保只有中断处理程序修改尾指针,并且只有正在读取数据的“前台”任务离队修改了头指针。高级概述:

  • 生产者(UART中断处理程序):

    1. 阅读queue.headqueue.tail融入当地人;
    2. 增加本地尾指针(不是实际queue.tail指针)。如果您的增量超过队列缓冲区的末尾,则将其包装到队列缓冲区的开头。
    3. 比较local.taillocal.head- 如果它们相等,则队列已满,您必须执行任何适当的错误处理。
    4. 否则你可以将新数据写入 wherelocal.tail
    5. 现在才可以设置 queue.tail == local.tail
    6. 从中断返回(或处理其他与 UART 相关的任务,如果合适,例如从发送队列中读取)
  • 消费者(前台“任务”)

    1. 阅读queue.headqueue.tail融入当地人;
    2. if local.head==local.tail队列为空;返回让下一个任务做一些工作
    3. 读取指向的字节local.head
    4. local.head如有必要,增加并包装它;
    5. 设置queue.head=local.head
    6. 转到第 1 步

确保queue.headqueue.tailvolatile(或在汇编中写入这些位)以确保没有排序问题。

现在只需确保您的 UART 接收的数据队列足够大,以便在前台任务有机会运行之前保存所有可以接收的字节。前台任务需要将队列中的数据拉到它自己的缓冲区中,以构建消息以提供给“消息处理器”任务。

于 2010-05-02T01:28:32.227 回答
1

您所要求的在 Cortex-M3 上非常简单。您需要启用 STIR 寄存器,以便您可以使用软件触发低优先级 ISR。当高优先级 ISR 处理完关键内容后,它只会触发低优先级中断并退出。如果没有更重要的事情发生,NVIC 然后将尾链到低优先级处理程序。

于 2010-11-24T00:20:32.953 回答
0

“更正式的方式”或者更确切地说是传统的方法是使用基于优先级的抢占式多任务调度程序和“延迟中断处理程序”模式。

于 2010-05-02T10:50:40.963 回答
0

检查您的处理器文档。如果您写入通常必须在中断内清除的位,某些处理器将中断。我目前正在使用 SiLabs c8051F344 并在规格表第 9.3.1 节中:

“软件可以通过将任何中断挂起标志设置为逻辑 1 来模拟中断。如果为该标志启用中断,将产生中断请求,CPU 将转向与中断挂起标志相关的 ISR 地址。”

于 2010-05-04T16:01:29.680 回答