From 81d15dc5507f6da94b3815ad876e68a634a75522 Mon Sep 17 00:00:00 2001 From: leona <49851862+LShiode@users.noreply.github.com> Date: Wed, 29 Dec 2021 02:54:23 +0900 Subject: [PATCH] Fix: Interrut Handler Register Function and Exception Process (#41) Signed-off-by: shiode Co-authored-by: Cobus van Eeden <35851496+cobusve@users.noreply.github.com> Co-authored-by: David Chalco <59750547+dachalco@users.noreply.github.com> Co-authored-by: Joseph Julicher --- portable/GCC/NiosII/port.c | 21 ++++++++++------ portable/GCC/NiosII/port_asm.S | 45 +++++++++++++--------------------- 2 files changed, 30 insertions(+), 36 deletions(-) diff --git a/portable/GCC/NiosII/port.c b/portable/GCC/NiosII/port.c index 7dc6f81f1..cc68ed032 100644 --- a/portable/GCC/NiosII/port.c +++ b/portable/GCC/NiosII/port.c @@ -36,6 +36,7 @@ /* Altera includes. */ #include "sys/alt_irq.h" +#include "sys/alt_exceptions.h" #include "altera_avalon_timer_regs.h" #include "priv/alt_irq_table.h" @@ -46,6 +47,8 @@ /* Interrupts are enabled. */ #define portINITIAL_ESTATUS ( StackType_t ) 0x01 +int _alt_ic_isr_register(alt_u32 ic_id, alt_u32 irq, alt_isr_func isr, + void *isr_context, void *flags); /*-----------------------------------------------------------*/ /* @@ -56,7 +59,7 @@ static void prvSetupTimerInterrupt( void ); /* * Call back for the alarm function. */ -void vPortSysTickHandler( void * context, alt_u32 id ); +void vPortSysTickHandler( void * context); /*-----------------------------------------------------------*/ @@ -137,7 +140,7 @@ void vPortEndScheduler( void ) void prvSetupTimerInterrupt( void ) { /* Try to register the interrupt handler. */ - if ( -EINVAL == alt_irq_register( SYS_CLK_IRQ, 0x0, vPortSysTickHandler ) ) + if ( -EINVAL == _alt_ic_isr_register( SYS_CLK_IRQ_INTERRUPT_CONTROLLER_ID, SYS_CLK_IRQ, vPortSysTickHandler, 0x0, 0x0 ) ) { /* Failed to install the Interrupt Handler. */ asm( "break" ); @@ -156,7 +159,7 @@ void prvSetupTimerInterrupt( void ) } /*-----------------------------------------------------------*/ -void vPortSysTickHandler( void * context, alt_u32 id ) +void vPortSysTickHandler( void * context) { /* Increment the kernel tick. */ if( xTaskIncrementTick() != pdFALSE ) @@ -175,25 +178,27 @@ void vPortSysTickHandler( void * context, alt_u32 id ) * kernel has its scheduler started so that contexts are saved and switched * correctly. */ -int alt_irq_register( alt_u32 id, void* context, void (*handler)(void*, alt_u32) ) +int _alt_ic_isr_register(alt_u32 ic_id, alt_u32 irq, alt_isr_func isr, + void *isr_context, void *flags) { int rc = -EINVAL; alt_irq_context status; + int id = irq; /* IRQ interpreted as the interrupt ID. */ if (id < ALT_NIRQ) { /* * interrupts are disabled while the handler tables are updated to ensure - * that an interrupt doesn't occur while the tables are in an inconsistent + * that an interrupt doesn't occur while the tables are in an inconsistant * state. */ status = alt_irq_disable_all (); - alt_irq[id].handler = handler; - alt_irq[id].context = context; + alt_irq[id].handler = isr; + alt_irq[id].context = isr_context; - rc = (handler) ? alt_irq_enable (id): alt_irq_disable (id); + rc = (isr) ? alt_ic_irq_enable(ic_id, id) : alt_ic_irq_disable(ic_id, id); /* alt_irq_enable_all(status); This line is removed to prevent the interrupt from being immediately enabled. */ } diff --git a/portable/GCC/NiosII/port_asm.S b/portable/GCC/NiosII/port_asm.S index 9fd299899..06cf5d287 100644 --- a/portable/GCC/NiosII/port_asm.S +++ b/portable/GCC/NiosII/port_asm.S @@ -34,11 +34,10 @@ .globl restore_sp_from_pxCurrentTCB # Entry point for exceptions. -.section .exceptions.entry, "xa" +.section .exceptions.entry.user, "xa" # Save the entire context of a task. save_context: - addi ea, ea, -4 # Point to the next instruction. addi sp, sp, -116 # Create space on the stack. stw ra, 0(sp) # Leave a gap for muldiv 0 @@ -59,7 +58,8 @@ save_context: stw r15, 64(sp) rdctl r5, estatus # Save the eStatus stw r5, 68(sp) - stw ea, 72(sp) # Save the PC + addi r15, ea, -4 # Instruction that caused exception + stw r15, 72(sp) # Save as EA stw r16, 76(sp) # Save the remaining registers stw r17, 80(sp) stw r18, 84(sp) @@ -75,24 +75,13 @@ save_sp_to_pxCurrentTCB: movia et, pxCurrentTCB # Load the address of the pxCurrentTCB pointer ldw et, (et) # Load the value of the pxCurrentTCB pointer stw sp, (et) # Store the stack pointer into the top of the TCB - - .section .exceptions.irqtest, "xa" -hw_irq_test: - /* - * Test to see if the exception was a software exception or caused - * by an external interrupt, and vector accordingly. - */ - rdctl r4, ipending # Load the Pending Interrupts indication - rdctl r5, estatus # Load the eStatus (enabled interrupts). - andi r2, r5, 1 # Are interrupts enabled globally. - beq r2, zero, soft_exceptions # Interrupts are not enabled. - beq r4, zero, soft_exceptions # There are no interrupts triggered. - .section .exceptions.irqhandler, "xa" -hw_irq_handler: - call alt_irq_handler # Call the alt_irq_handler to deliver to the registered interrupt handler. + br irq_test_user # skip the section .exceptions.entry - .section .exceptions.irqreturn, "xa" + .section .exceptions.irqtest, "xa" +irq_test_user: + + .section .exceptions.exit.user, "xa" restore_sp_from_pxCurrentTCB: movia et, pxCurrentTCB # Load the address of the pxCurrentTCB pointer ldw et, (et) # Load the value of the pxCurrentTCB pointer @@ -135,16 +124,16 @@ restore_context: .section .exceptions.soft, "xa" soft_exceptions: - ldw et, 0(ea) # Load the instruction where the interrupt occured. - movhi at, %hi(0x003B683A) # Load the registers with the trap instruction code - ori at, at, %lo(0x003B683A) - cmpne et, et, at # Compare the trap instruction code to the last excuted instruction - beq et, r0, call_scheduler # its a trap so switchcontext - break # This is an un-implemented instruction or muldiv problem. - br restore_context # its something else + movhi r3, 0x003b /* upper half of trap opcode */ + ori r3, r3, 0x683a /* lower half of trap opcode */ + beq r2, r3, call_scheduler + br exceptions_unknown_user # its something else call_scheduler: - addi ea, ea, 4 # A trap was called, increment the program counter so it is not called again. - stw ea, 72(sp) # Save the new program counter to the context. + stw ea, 72(sp) # EA is PC+4 so will skip over instruction causing exception call vTaskSwitchContext # Pick the next context. br restore_sp_from_pxCurrentTCB # Switch in the task context and restore. + + .section .exceptions.unknown.user +exceptions_unknown_user: +