Embedded 我可以将哪些Cortex-M3中断用于通用工作?

Embedded 我可以将哪些Cortex-M3中断用于通用工作?,embedded,interrupt,cortex-m3,Embedded,Interrupt,Cortex M3,我有一些代码需要作为特定中断的结果运行 我不希望在中断本身的上下文中执行它,但我也不希望它在线程模式下执行 我希望它的运行优先级低于导致其运行的高级别中断,但也高于线程级别(以及其他一些中断) 我想我需要使用另一个中断处理程序 哪些是最好的使用方法,以及调用它们的最佳方式是什么 目前,我正计划对一些我不使用的外围设备使用中断处理程序,并通过NVIC直接设置位来调用它们,但我希望有一种更好、更正式的方法 谢谢,您正在使用RTOS吗?一般来说,这类事情可以通过一个高优先级线程来处理,该线程通过中断得

我有一些代码需要作为特定中断的结果运行

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

我希望它的运行优先级低于导致其运行的高级别中断,但也高于线程级别(以及其他一些中断)

我想我需要使用另一个中断处理程序

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

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


谢谢,

您正在使用RTOS吗?一般来说,这类事情可以通过一个高优先级线程来处理,该线程通过中断得到执行某些工作的信号

如果您没有使用RTOS,那么您只有几个任务,并且由中断启动的工作不会占用太多资源,在中断处理程序的上下文中完成高优先级的工作可能是最简单的。如果这些条件不成立,那么实现你所说的将是一个基本的多任务操作系统本身的开始。这可能是一个有趣的项目,但如果你只是想完成工作,你可能想考虑一个简单的RTOS。 既然你提到了你正在做的工作的一些细节,下面是我过去如何处理类似问题的概述:

对于通过UART处理接收到的数据,我在处理一个不完全支持任务分配的简单系统时使用的一种方法(即,任务是循环的,而不是简单的
循环),就是为从UART接收到的数据创建一个共享队列。当UART中断触发时,数据从UART的RDR(接收数据寄存器)读取并放入队列。处理这个问题的诀窍是确保队列指针不会损坏,小心地使队列指针不稳定,并确保只有中断处理程序修改尾部指针,只有从队列读取数据的“前台”任务修改头部指针。高级别概述:

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

  • queue.head
    queue.tail
    读入局部变量
  • 增加本地尾部指针(不是实际的
    queue.tail
    指针)。如果增量超过队列缓冲区的末尾,则将其包装到队列缓冲区的开头
  • 比较
    local.tail
    local.head
    ——如果它们相等,则队列已满,您必须执行任何适当的错误处理
  • 否则,您可以将新数据写入where
    local.tail
  • 只有现在才能设置queue.tail==local.tail
  • 从中断返回(或处理其他UART相关任务,如适当,如从传输队列读取)
  • 消费者(前台的“任务”)

  • queue.head
    queue.tail
    读入局部变量
  • 如果
    local.head
    ==
    local.tail
    队列为空;返回以让下一个任务完成一些工作
  • 读取
    local.head所指向的字节
  • 增加
    local.head
    ,必要时将其包裹起来
  • 设置
    queue.head
    =
    local.head
  • 转到步骤1
确保
queue.head
queue.tail
volatile
(或在汇编中写入这些位),以确保没有顺序问题


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

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

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中,通过执行u asm(“cpsid i”)禁用中断,通过u asm(“cpsie i”)启用中断。(大多数C编译器为此提供内置的内在函数或宏。)

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

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