mirror of
				https://github.com/FreeRTOS/FreeRTOS-Kernel.git
				synced 2025-11-04 11:09:01 +01:00 
			
		
		
		
	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>
This commit is contained in:
		
							parent
							
								
									455df7a07a
								
							
						
					
					
						commit
						81d15dc550
					
				@ -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. */
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -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:
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user