【问题标题】:ARM IRQ handler doesn't work properly in GCCARM IRQ 处理程序在 GCC 中无法正常工作
【发布时间】:2016-08-06 14:22:10
【问题描述】:

我正在使用 LPC2138 soc 开发一个裸机 ARM 项目。我为 I2C 编写了一个 IRQ 中断处理程序。但它不能正确返回。处理程序被重复调用一次中断。

我已经对这个问题做了详细的调试分析。

在 ARM7TDMI 参考手册中明确提到了以下内容。

但是当我反汇编代码时,发现GCC生成的代码并没有恢复CPSR寄存器。最后也是一个未知值。

我已经像下面这样声明了 IRQ 处理程序

void I2C0_IRQ_handler(void) __attribute__ ((interrupt("IRQ")));

这是 GCC 中的错误还是我做错了什么?

我用于构建项目的编译器、汇编器和链接器标志是:

CFLAGS := -mcpu=arm7tdmi-s -g3 -Wall -I. -gdwarf-2
AS_FLAGS := -mcpu=arm7tdmi-s -g3 -gdwarf-2
LD_FLAGS := -Wl,-Map,$(TARGET:%.hex=%).map -nostartfiles

【问题讨论】:

  • 在什么情况下不能正常工作;与您的预期相比,您看到了什么行为?假设 VICVectAddr = 0; 正在清除中断,那么这段代码正在正确执行所有 3 个引用步骤(提示:阅读 subs pc,... 的实际作用)
  • @Notlikethat 当发送 I2C 启动条件时应该产生中断。它的工作。但是在中断例程之后,控制不会返回到被中断的代码。汇编代码中缺少第 2 步。
  • 正如我所说,第 2 步 正在subs pc... 在该代码中执行。离开并找到 LPC213x 手册后,我看到该写入确实确认了 VIC 处的中断,但该中断显然是电平触发的,并且您没有做任何事情来在 I2C 控制器端取消断言它(参见第 13.9 节)。因此,当您返回时,您只是立即再次接受相同的中断,无限循环。
  • 将文本发布为文本,而不是图像!
  • IDK 这个特定设备,但VICVectAddr 可能是错误的(外围寄存器名称通常全大写)或不足。 OP 应该阅读参考手册。

标签: c gcc arm


【解决方案1】:

你的分析有两个致命的缺陷:一是从CPU核心的角度来看,二是错误的。

首先是第二个缺陷,我不确定为什么 ARM7TDMI 手册有如此奇怪的过于具体的措辞(无论如何,你实际上不能单独做所有这些事情),但所有 3 个方面都是由subs pc, lr, #4 行中的你的代码。 subs pc, lr is specifically an exception return instruction - 它从 SPSR 原子地恢复 CPSR 并返回到固定的 LR 地址。由于 CPU 的中断禁用标志位于 CPSR 中,因此假设该 SPSR 值中的 I 位是明确的(您可以预料到,因为您使用了一个 IRQ 来到达这里......),IRQ 也将被自动取消屏蔽在这个过程中。

因此,从 CPU 内核的角度来看,您的代码已经(凭借其最终指令)执行异常处理程序所需的所有操作,即它在同一时间点恢复执行与 IRQ 发生时相同的状态 - 编译器肯定没有问题。但是,它没有做的是任何关于核心之外的外围方式仍在断言其中断的事实,因此从 IRQ 返回后你要做的下一件事就是愉快地接受立即再次使用相同的 IRQ。无限重复。

你至少已经超越了核心,达到了中断控制器;写信给VICVectAddracknowledges the interrupt at the VIC,但这只会让 VIC 本身释放出任何未决中断的优先级并传递下一个中断,因为外部源仍然被断言(并且假设没有更高优先级的 IRQ 来自其他地方) , 还是一样的。

要真正处理中断并取得任何进展,您需要为 I2C 外围设备提供服务以提升它。 the LPC213x manual 的第 13.9 节概述了每个中断条件需要做什么,但在清除断言中断方面,您需要写入 I2C0CONCLR 的 SIC 字段。

【讨论】:

  • 这确实帮助我解决了我的问题并学习了新事物。从您的回答中,我可以理解您为回答我的问题所付出的努力和时间。非常感谢 :) 当然还有我的赞成票。
猜你喜欢
  • 2012-11-26
  • 2014-10-23
  • 1970-01-01
  • 1970-01-01
  • 2014-07-27
  • 2013-03-25
  • 1970-01-01
  • 2022-07-22
  • 1970-01-01
相关资源
最近更新 更多