我想知道任何微处理器中FIQ和IRQ中断系统之间的区别,例如:ARM926EJ.
基于各种参考文献,我在Linux中对信号的主观定义是"用于通知进程有关特定事件发生的触发器.此处的事件可能涉及软件异常.此外,信号也可用于IPC机制. " 我的问题是
我正在看一个学校项目中的一些旧代码,并试图在我的笔记本电脑上编译它时遇到了一些问题.它最初是为旧的32位版本的gcc编写的.无论如何,我试图将一些程序集转换为64位兼容代码并遇到一些障碍.
这是原始代码:
pusha
pushl %ds
pushl %es
pushl %fs
pushl %gs
pushl %ss
Run Code Online (Sandbox Code Playgroud)
pusha在64位模式下无效.那么在64位模式下,在x86_64汇编中执行此操作的正确方法是什么?
必须有一个原因,为什么pusha在64位模式下无效,所以我有一种感觉手动推送所有寄存器可能不是一个好主意.
我已经看到了这些问题的一些风格,也看到了不同的答案,但仍然不确定它们是否是最新的并完全适用于我的用例,所以我会在这里提问。如果它是重复的,请告诉我!
鉴于我正在使用 C++17 和 gcc-arm-none-eabi-9 工具链为 STM32 微控制器(裸机)开发:
我还需要使用volatile用于在 ISR 和 之间共享数据main()吗?
volatile std::int32_t flag = 0;
extern "C" void ISR()
{
flag = 1;
}
int main()
{
while (!flag) { ... }
}
Run Code Online (Sandbox Code Playgroud)
我很清楚,我应该始终volatile用于访问内存映射的硬件寄存器。
但是对于 ISR 用例,我不知道它是否可以被视为“多线程”的情况。在这种情况下,人们建议使用 C++11 的新线程特性(例如std::atomic)。我知道volatile(不优化)和atomic(安全访问)之间的区别,所以建议的答案std::atomic在这里让我感到困惑。
对于 x86 系统上“真正的”多线程的情况,我没有看到需要使用volatile.
换句话说:编译器flag可以知道可以在 ISR 内部更改吗?如果没有,它如何在常规多线程应用程序中知道它?
谢谢!
我应该先分享我所知道的一切 - 那就是完全混乱.关于这个主题有几个不同的问题,所以请不要生气:).
1)为了找到ISR,CPU具有中断号.在x86机器(286/386及以上)中,有一个带有ISR的IVT; 每个4字节大小的条目.所以我们需要将中断数乘以4才能找到ISR.所以第一堆问题是 - 我完全混淆了CPU接收中断的机制.为了引发中断,首先设备应该探测IRQ - 然后是什么?中断号在"IRQ"上向CPU传输?我还读过像数据总线上设置ISR地址的设备; 什么呢?覆盖ISR的设备的概念是什么?有人可以告诉我几个CPU轮询中断的示例设备吗?它在哪里找到它们的ISR?
2)如果两个设备共享IRQ(这是非常可能的),它们之间的CPU有何不同?如果两个设备同时引发相同优先级的中断怎么办 我知道会有相同类型和低优先级中断的屏蔽 - 但这种通信是如何在CPU和设备控制器之间发生的?我研究了PIC和APIC在这个问题上的作用,但是无法理解.
谢谢阅读.非常感谢您的回答.
我正在使用AVR-GCC 4.9.2,我想知道如果我在AVR的ISR中过早返回会发生什么?
ISR(USART_RXC_vect)
{
...
if(idx == BUFSIZE)
return;
...
}
Run Code Online (Sandbox Code Playgroud)
会return被翻译成reti指令吗?或者我需要reti()自己加入?
我正在寻找幕后发生的事情的详细解释.
我读到我需要将 ICACHE_RAM_ATTR 宏添加到中断服务例程 (ISR) 以及在我的 ESP8266 Arduino 代码中从那里调用的每个函数,以防止随机崩溃。我还找到了对宏 ICACHE_RAM_ATTR 的作用的解释,尽管我不确定该解释是否适用于 Espressif ESP8266 SDK,也适用于 ESP8266 上的 Arduino。我不明白为什么我需要将宏添加到 ISR。
第一个问题:为什么我需要将 ICACHE_RAM_ATTR 宏添加到 ISR 以及从那里调用的所有函数?
下一个问题是,如果我强制内联从 ISR 调用的函数会发生什么:
inline void doStuff() __attribute__((__always_inline__)) { // <-- necessary to add ICACHE_RAM_ATTR here?
// no more function calls here
}
void ICACHE_RAM_ATTR handleInterrupt() {
doStuff();
}
Run Code Online (Sandbox Code Playgroud)
第二个问题:我是否需要将 ICACHE_RAM_ATTR 宏添加到强制内联的函数中?
通过“原子访问防护”或“中断防护”强制对与 ISR 共享的易失性变量进行原子访问的标准技术,特别是在没有操作系统的情况下运行裸机、单线程协作多任务应用程序时,如下所示:
// 1. save interrupt state
// 2. disable only the interrupts necessary
// You get atomic access to volatile variables shared with ISRs here,
// since ISRs are the only other "context" or running "thread" which
// might attempt to modify a shared memory block or variable.
// 3. restore interrupt state
Run Code Online (Sandbox Code Playgroud)
另请参阅我在这里详细描述的地方,包括最佳实践(在短时间内保持中断关闭)以及如何通过我的doAtomicRead()重复读取循环函数进行原子读取而不首先禁用中断:读取 64 位变量,即由 ISR 更新。
我之前已经记录过如何对 AVR 微控制器/Arduino 执行此操作:How do I Forceatomity in Atmel AVR mcus/Arduino? …
有没有好的68k组装程序员在那里?我正在为摩托罗拉68040使用商业Green Hills编译器,我从代码中看到一些非常奇怪的行为.有时,代码会执行if/else比较,并采用错误的分支.例如:
float a = 1, b = 2;
if (a < b)
do c;
else
do d;
Run Code Online (Sandbox Code Playgroud)
代码有时会d !? 我发现,当发生此错误时,总会有一个特定的ISR中断比较.我看了一下ISR生成的程序集,看到了一些对我没有意义的事情.首先,看起来浮点状态寄存器FPSR,FPCR和FPIAR不会保存在ISR中.这可以解释为什么if/elses采取了错误的分支.FPSR寄存器用于确定比较结果,如果该寄存器在ISR中被覆盖,则分支可能采用错误的路径.以下是编译器生成的入口和出口程序集:
isr_function:
FSAVE -(%SP)
LINK %A6,#-192
MOVEM.L %D0/%D1/%D2/%A0/%A1,-(%SP)
FMOVEM %FP0/%FP1/%FP2/%FP3/%FP4/%FP5/%FP6/%FP7,-(%SP)
; isr code ...
FMOVEM -308(%A6),%FP0/%FP1/%FP2/%FP3/%FP4/%FP5/%FP6/%FP7
MOVEM.L -212(%A6),%D0/%D1/%D2/%A0/%A1
UNLK %A6
FRESTORE (%SP)+
RTE
Run Code Online (Sandbox Code Playgroud)
我查看了程序员参考手册,但我找不到任何暗示FSAVE或FMOVEM保存FP状态寄存器的内容.实际上,我看到一条评论表明它没有,"FSAVE不会保存程序员的浮点单元的模型寄存器;它只保存用户不可见的机器部分." 所以我添加了一些我自己的程序集以在ISR开始时保存寄存器,并在最后恢复它们,这大大提高了性能,但我仍然看到一些问题.以下是我的补充; 备份变量在C代码中键入为unsigned long:
isr_function:
FSAVE -(%SP)
LINK %A6,#-192
MOVEM.L %D0/%D1/%D2/%A0/%A1,-(%SP)
FMOVEM %FP0/%FP1/%FP2/%FP3/%FP4/%FP5/%FP6/%FP7,-(%SP)
FMOVE %FPIAR,fpiar_backup
FMOVE %FPSR,fpsr_backup
FMOVE %FPCR,fpcr_backup
; isr code ...
FMOVE fpiar_backup,%FPIAR
FMOVE fpsr_backup,%FPSR
FMOVE fpcr_backup,%FPCR
FMOVEM -308(%A6),%FP0/%FP1/%FP2/%FP3/%FP4/%FP5/%FP6/%FP7
MOVEM.L -212(%A6),%D0/%D1/%D2/%A0/%A1
UNLK %A6
FRESTORE (%SP)+ …Run Code Online (Sandbox Code Playgroud) 我想了解ISR(中断服务程序)和函数调用之间的区别.
从硬件的角度来看,我觉得函数调用和ISR都是一样的.如果我错了,请纠正我.我所能找到的有关ISR和函数调用的内容如下:
ISR:
在程序执行期间可能发生的异步事件
将PC,标志和寄存器保存在堆栈中并禁用所有中断并加载ISR的地址
ISR不能有可传递给它的参数
功能:
在有函数调用时发生
将PC和寄存器保存在堆栈中
可以有参数
可以返回值
对执行的大小和持续时间没有限制
除此之外还有什么区别吗?请告诉我.我还读过关于从ISR进行函数调用的方法.请突出显示它.
embedded operating-system function-calls computer-architecture isr