Fix: Interrut Handler Register Function and Exception Process (#41)

Signed-off-by: shiode <shiode@aptpod.co.jp>

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 <jjulicher@mac.com>
diff --git a/portable/GCC/NiosII/port.c b/portable/GCC/NiosII/port.c
index 7dc6f81..cc68ed0 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 @@
 /*

  * Call back for the alarm function.

  */

-void vPortSysTickHandler( void * context, alt_u32 id );

+void vPortSysTickHandler( void * context);

 

 /*-----------------------------------------------------------*/

 

@@ -137,7 +140,7 @@
 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 vPortSysTickHandler( void * context, alt_u32 id )

+void vPortSysTickHandler( void * context)

 {

 	/* Increment the kernel tick. */

 	if( xTaskIncrementTick() != pdFALSE )

@@ -175,25 +178,27 @@
  * 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 9fd2998..06cf5d2 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 @@
 	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 @@
 	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 @@
    

 	.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:

+