Forum Discussion
Altera_Forum
Honored Contributor
19 years agointerupt disabled in ISR
In the Nios II Software developer's handbook:
"the HAL system library disables interupts when it dispatches an ISR". I've examine the file alt_irq_entry.S and alt_irq_handler.c but no presence of interupts disabling. Could anybody tell me where are disabled interupts? thank u in advance.5 Replies
- Altera_Forum
Honored Contributor
When an exception is generated, the processor performs the following
steps automatically: ■ Copies the contents of the status register (ctl0) to the estatus register (ctl1), saving the pre-exception status of the processor ■ Clears the PIE bit of the status register, disabling further hardware interrupts ■ Stores the address of the instruction after the exception to the ea register (r29), providing the return address for the exception handler to return to ■ Vectors to the exception address - Altera_Forum
Honored Contributor
thank u for the answer David_Cai.
This is the code of alt_irq_entry.S: /* * This is the interrupt exception entry point code, which saves all the * registers and calls the interrupt handler. It should be pulled in using * a .globl from alt_irq_register.c. This scheme is used so that if an * interrupt is never registered, then this code will not appear in the * generated executable, thereby improving code footprint. */ /* * Explicitly allow the use of r1 (the assembler temporary register) * within this code. This register is normally reserved for the use of * the compiler. */ .set noat /* * Pull in the exception handler register save code. */ .globl alt_exception .globl alt_irq_entry .section .exceptions.entry.label, "xa" alt_irq_entry: /* * Section .exceptions.entry is in alt_exception_entry.S * This saves all the caller saved registers and reads estatus into r5 */ .section .exceptions.irqtest, "xa" # ifdef ALT_CI_EXCEPTION_VECTOR_N /* * Use the exception vector custom instruction if present to accelerate * this code. * If the exception vector custom instruction returns a negative * value, there are no interrupts active (estatus.pie is 0 * or ipending is 0) so assume it is a software exception. */ custom ALT_CI_EXCEPTION_VECTOR_N, et, r0, r0 blt et, r0, .Lnot_irq# else /* * Test to see if the exception was a software exception or caused * by an external interrupt, and vector accordingly. */ rdctl r4, ipending andi r2, r5, 1 beq r2, zero, .Lnot_irq beq r4, zero, .Lnot_irq# endif /* ALT_CI_EXCEPTION_VECTOR_N */ .section .exceptions.irqhandler, "xa" /* * Now that all necessary registers have been preserved, call * alt_irq_handler() to process the interrupts. */ call alt_irq_handler .section .exceptions.irqreturn, "xa" br .Lexception_exit .section .exceptions.notirq.label, "xa" .Lnot_irq: /* * Section .exceptions.exit is in alt_exception_entry.S * This restores all the caller saved registers */ .section .exceptions.exit.label .Lexception_exit: Which are the instruction that save registers and clears PIE bit? Probably I miss something. Thank u - Altera_Forum
Honored Contributor
--- Quote Start --- originally posted by soin@Sep 13 2006, 02:21 AM which are the instruction that save registers and clears pie bit?probably i miss something.
thank u
<div align='right'><{post_snapback}> (index.php?act=findpost&pid=18247)
--- quote end ---
--- Quote End --- As David Cai wrote this is automatically done by the processor, not the software. If you want nested interrupts you have to explicitly re-enable interrupts in your ISR.
- Altera_Forum
Honored Contributor
ok, perfect. I didn't understood clearly that.
thank u all - Altera_Forum
Honored Contributor
and just to be crystal clear, presumably all that needs to be done is something like the following:
#include <io.h># include <system.h># include "sys/alt_irq.h" // ---------------------------------------------------------------------------- alt_irq_context IRQ_ALLOW_ESSENTIAL_START (alt_u32 id, alt_u32* pActive) { alt_irq_context Ctrl0; alt_u32 irq_mask; //mask out own IRQ and all others having lower priority level irq_mask = ~(0x0FFFFFFFF << id); // alternatively, mask out self and IRQs 32-29, 28-26 irq_mask = (~(1 << id)) & 0x01FFFFFFF; *pActive = alt_irq_active; alt_irq_active &= irq_mask; NIOS2_WRITE_IENABLE (alt_irq_active); /* alternatively...... alt_irq_disable (id); //Prevent re-entry alt_irq_disable (<a lower priority interrupt that can wait>); alt_irq_disable (<another lower priority interrupt that can wait>); alt_irq_disable (<yet another lower priority interrupt that can wait>); */ NIOS2_READ_STATUS (Ctrl0); Ctrl0 |= NIOS2_STATUS_PIE_MSK; NIOS2_WRITE_STATUS (Ctrl0); return (Ctrl0); } // ---------------------------------------------------------------------------- void IRQ_ALLOW_ESSENTIAL_FINISH (alt_irq_context Ctrl0, alt_u32 id, alt_u32 Active) { Ctrl0 &= ~NIOS2_STATUS_PIE_MSK; NIOS2_WRITE_STATUS (Ctrl0); /* alt_irq_enable (<yet another lower priority interrupt that can wait>); alt_irq_enable (<another lower priority interrupt that can wait>); alt_irq_enable (<a lower priority interrupt that can wait>); alt_irq_enable (id); */ alt_irq_active = Active; NIOS2_WRITE_IENABLE (Active); } // ---------------------------------------------------------------------------- static void MyInterruptibleISR (void* context, alt_u32 id) { alt_irq_context Ctrl0; alt_u32 Active; <time-critical section, e.g. reading registers> Ctrl0 = IRQ_ALLOW_ESSENTIAL_START (id, &Active); <non-time-critical section, e.g. stuffing in buffers> IRQ_ALLOW_ESSENTIAL_FINISH (Ctrl0, id, Active); } // ----------------------------------------------------------------------------