mirror of
https://github.com/rvtr/ctr_firmware.git
synced 2025-10-31 07:51:08 -04:00
割り込みハンドラのマージ。
git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-09-30%20-%20paladin.7z/paladin/ctr_firmware@133 b871894f-2f95-9b40-918c-086798483c85
This commit is contained in:
parent
48bd2a2dc2
commit
bf0f695510
@ -1,234 +0,0 @@
|
|||||||
/*---------------------------------------------------------------------------*
|
|
||||||
Project: CtrBrom - libraries - OS
|
|
||||||
File: os_irqHandler.c
|
|
||||||
|
|
||||||
Copyright 2008 Nintendo. All rights reserved.
|
|
||||||
|
|
||||||
These coded instructions, statements, and computer programs contain
|
|
||||||
proprietary information of Nintendo of America Inc. and/or Nintendo
|
|
||||||
Company Ltd., and are protected by Federal copyright law. They may
|
|
||||||
not be disclosed to third parties or copied or duplicated in any form,
|
|
||||||
in whole or in part, without the prior written consent of Nintendo.
|
|
||||||
|
|
||||||
$Date:: $
|
|
||||||
$Rev$
|
|
||||||
$Author$
|
|
||||||
*---------------------------------------------------------------------------*/
|
|
||||||
#include <brom/code32.h>
|
|
||||||
#include <brom/os.h>
|
|
||||||
|
|
||||||
//#define BROM_ENABLE_THREAD
|
|
||||||
|
|
||||||
extern OSIntrFunction osIntrTable[OS_INTR_ID_NUM];
|
|
||||||
|
|
||||||
//---- thread queue for interrupt
|
|
||||||
OSThreadQueue i_osIrqThreadQueue;
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*
|
|
||||||
Name: osIrqHandler
|
|
||||||
|
|
||||||
Description: IRQ handler. call handler according to OS_InterruptTable
|
|
||||||
|
|
||||||
Arguments: None
|
|
||||||
|
|
||||||
Returns: None
|
|
||||||
*---------------------------------------------------------------------------*/
|
|
||||||
asm void osIrqHandler( void )
|
|
||||||
{
|
|
||||||
PRESERVE8
|
|
||||||
|
|
||||||
INASM_EXTERN( osIntrTable )
|
|
||||||
|
|
||||||
// 不正確データアボート有効化(clear HW_PSR_IMPRECISE_ABORT)
|
|
||||||
msr cpsr_fsxc, #(HW_PSR_IRQ_MODE | HW_PSR_IRQ_DISABLE | HW_PSR_FIQ_DISABLE)
|
|
||||||
|
|
||||||
stmfd sp!, { r0-r4,r12,lr }
|
|
||||||
|
|
||||||
// 割り込み要因の判定.
|
|
||||||
|
|
||||||
// Interrupt Acknowledge Register
|
|
||||||
ldr lr, =REG_CPUI_ACK_ADDR
|
|
||||||
ldr lr, [lr]
|
|
||||||
ldr r1, =REG_OS_CPUI_ACK_ID_MASK
|
|
||||||
and r4, r1, lr // r4に割り込み要因番号が入ってる
|
|
||||||
cmp r4, #__cpp(OS_INTR_ID_NUM)
|
|
||||||
bge my_undefined_interrupt_1
|
|
||||||
|
|
||||||
// get jump vector
|
|
||||||
ldr r1, =osIntrTable
|
|
||||||
ldr r0, [ r1, r4, LSL #2 ]
|
|
||||||
|
|
||||||
blx r0 // set return address for thread rescheduling
|
|
||||||
|
|
||||||
// End of Interrupt Register
|
|
||||||
ldr lr, =REG_CPUI_EOI_ADDR
|
|
||||||
str r4, [lr]
|
|
||||||
|
|
||||||
#ifdef BROM_ENABLE_THREAD
|
|
||||||
bl osIrqHandler_ThreadSwitch
|
|
||||||
#endif // BROM_ENABLE_THREAD
|
|
||||||
|
|
||||||
my_undefined_interrupt_1
|
|
||||||
ldmfd sp!, { r0-r4,r12,lr } // return to interrupted address
|
|
||||||
subs pc, lr, #4
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef BROM_ENABLE_THREAD
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*
|
|
||||||
Name: OS_IRQHandler_ThreadSwitch
|
|
||||||
|
|
||||||
Description: 割り込み分岐処理(テーブル OS_InterruptTable 引き)
|
|
||||||
|
|
||||||
Arguments: なし
|
|
||||||
|
|
||||||
Returns: なし
|
|
||||||
*---------------------------------------------------------------------------*/
|
|
||||||
asm void osIrqHandler_ThreadSwitch(void)
|
|
||||||
{
|
|
||||||
INASM_EXTERN( i_osIrqThreadQueue )
|
|
||||||
INASM_EXTERN( i_osThreadInfo )
|
|
||||||
|
|
||||||
//--------------------------------------------------
|
|
||||||
// wakeup threads in i_osIrqThreadQueue
|
|
||||||
//--------------------------------------------------
|
|
||||||
ldr r12, =i_osIrqThreadQueue
|
|
||||||
mov r3, #0 // avoid stall
|
|
||||||
ldr r12, [r12, #__cpp(offsetof(OSThreadQueue,head))] // r12 = i_osIrqThreadQueue.head
|
|
||||||
mov r2, #__cpp(OS_THREAD_STATE_READY) // avoid stall
|
|
||||||
cmp r12, #0
|
|
||||||
|
|
||||||
beq thread_switch // if r12 == 0 exit
|
|
||||||
|
|
||||||
LSYM(1) str r2, [r12, #__cpp(offsetof(OSThread,state))]
|
|
||||||
str r3, [r12, #__cpp(offsetof(OSThread,queue))]
|
|
||||||
str r3, [r12, #__cpp(offsetof(OSThread,link.prev))]
|
|
||||||
ldr r0, [r12, #__cpp(offsetof(OSThread,link.next))]
|
|
||||||
str r3, [r12, #__cpp(offsetof(OSThread,link.next))]
|
|
||||||
mov r12, r0
|
|
||||||
|
|
||||||
cmp r12, #0
|
|
||||||
bne BSYM(1)
|
|
||||||
|
|
||||||
ldr r12, =i_osIrqThreadQueue
|
|
||||||
str r3, [r12, #__cpp(offsetof(OSThreadQueue,head))] // clear i_osIrqThreadQueue.head
|
|
||||||
str r3, [r12, #__cpp(offsetof(OSThreadQueue,tail))] // clear i_osIrqThreadQueue.tail
|
|
||||||
|
|
||||||
ldr r12, =i_osThreadInfo // need to do scheduling
|
|
||||||
mov r1, #1
|
|
||||||
strh r1, [ r12, #OS_THREADINFO_OFFSET_ISNEEDRESCHEDULING ]
|
|
||||||
|
|
||||||
|
|
||||||
thread_switch
|
|
||||||
//--------------------------------------------------
|
|
||||||
// THREAD SWITCH
|
|
||||||
//--------------------------------------------------
|
|
||||||
// pseudo code
|
|
||||||
//
|
|
||||||
// if ( isNeedRescheduling == FALSE ) return;
|
|
||||||
// isNeedRescheduling = FALSE;
|
|
||||||
//
|
|
||||||
// // OS_SelectThread
|
|
||||||
// OSThread* t = i_osThreadInfo.list;
|
|
||||||
// while( t && ! OS_IsThreadRunnable( t ) ){ t = t->next; }
|
|
||||||
// return t;
|
|
||||||
//
|
|
||||||
// select:
|
|
||||||
// current = CurrentThread;
|
|
||||||
// if ( next == current ) return;
|
|
||||||
// CurrentThread = next;
|
|
||||||
// OS_SaveContext( current );
|
|
||||||
// OS_LoadContext( next );
|
|
||||||
//
|
|
||||||
|
|
||||||
// [[[ new OS_SelectThread ]]]
|
|
||||||
ldr r12, =i_osThreadInfo
|
|
||||||
ldrh r1, [ r12, #OS_THREADINFO_OFFSET_ISNEEDRESCHEDULING ]
|
|
||||||
cmp r1, #0
|
|
||||||
beq _dont_switched_ // return if i_osIsNeedResceduling == 0
|
|
||||||
|
|
||||||
mov r1, #0
|
|
||||||
strh r1, [ r12, #OS_THREADINFO_OFFSET_ISNEEDRESCHEDULING ]
|
|
||||||
|
|
||||||
// ---- OS_SelectThread (disable FIQ to support IS-Debugger snooping thread information)
|
|
||||||
mov r3, #HW_PSR_IRQ_MODE|HW_PSR_FIQ_DISABLE|HW_PSR_IRQ_DISABLE|HW_PSR_ARM_STATE
|
|
||||||
msr cpsr_c, r3
|
|
||||||
|
|
||||||
add r2, r12, #OS_THREADINFO_OFFSET_LIST // r2 = &i_osThreadInfo.list
|
|
||||||
ldr r1, [r2] // r1 = *r2 = TopOfList
|
|
||||||
LSYM(11)
|
|
||||||
cmp r1, #0
|
|
||||||
ldrneh r0, [ r1, #__cpp(OS_THREAD_OFFSET_STATE) ] // r0 = t->state
|
|
||||||
cmpne r0, #__cpp(OS_THREAD_STATE_READY)
|
|
||||||
ldrne r1, [ r1, #__cpp(OS_THREAD_OFFSET_NEXT) ]
|
|
||||||
bne BSYM(11)
|
|
||||||
|
|
||||||
cmp r1, #0
|
|
||||||
bne FSYM(12)
|
|
||||||
|
|
||||||
_dont_switched_
|
|
||||||
mov r3, #HW_PSR_IRQ_MODE|HW_PSR_IRQ_DISABLE|HW_PSR_ARM_STATE
|
|
||||||
msr cpsr_c, r3
|
|
||||||
|
|
||||||
bx lr
|
|
||||||
// ldmfd sp!, { lr }
|
|
||||||
// ldmfd sp!, { r0-r3,r12,pc } // return to interrupted address
|
|
||||||
// not reach here
|
|
||||||
|
|
||||||
|
|
||||||
LSYM(12)
|
|
||||||
// ---- OS_GetCurrentThread
|
|
||||||
ldr r0, [ r12, #OS_THREADINFO_OFFSET_CURRENT ]
|
|
||||||
cmp r1, r0
|
|
||||||
beq _dont_switched_ // return if no thread switching
|
|
||||||
|
|
||||||
// call thread switch callback (need to save register r0, r1, r12)
|
|
||||||
ldr r3, [ r12, #OS_THREADINFO_OFFSET_SWITCHCALLBACK ]
|
|
||||||
cmp r3, #0
|
|
||||||
beq FSYM(13) // skip calling callback when callback == 0
|
|
||||||
stmfd sp!, { r0, r1, r12 }
|
|
||||||
mov lr, pc
|
|
||||||
bx r3
|
|
||||||
ldmfd sp!, { r0, r1, r12 }
|
|
||||||
|
|
||||||
LSYM(13)
|
|
||||||
// ---- OS_SetCurrentThread
|
|
||||||
str r1, [ r12, #OS_THREADINFO_OFFSET_CURRENT ]
|
|
||||||
|
|
||||||
// ---- OS_SaveContext
|
|
||||||
// r0=currentThread r1=nextThread
|
|
||||||
// stack=Lo[LR,R0,R1,R2,R3,R12,LR]Hi
|
|
||||||
mrs r2, SPSR
|
|
||||||
str r2, [ r0, #OS_THREAD_OFFSET_CONTEXT ]! // *r0=context:CPSR
|
|
||||||
|
|
||||||
ldmib sp!, { r2,r3 } // Get R0,R1 // *sp=stack:R1
|
|
||||||
stmib r0!, { r2,r3 } // Put R0,R1 // *r0=context:R1
|
|
||||||
|
|
||||||
ldmib sp!, { r2,r3,r12,r14 } // Get R2,R3,R12,LR / *sp=stack:LR
|
|
||||||
stmib r0!, { r2-r14 }^ // Put R2-R14^ // *r0=context:R14
|
|
||||||
stmib r0!, { r14 } // Put R14_irq // *r0=context:R15+4
|
|
||||||
#ifdef SDK_CONTEXT_HAS_SP_SVC
|
|
||||||
mov r3, #HW_PSR_SVC_MODE|HW_PSR_FIQ_DISABLE|HW_PSR_IRQ_DISABLE|HW_PSR_ARM_STATE
|
|
||||||
msr cpsr_c, r3
|
|
||||||
stmib r0!, { sp }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// ---- OS_LoadContext
|
|
||||||
#ifdef SDK_CONTEXT_HAS_SP_SVC
|
|
||||||
ldr sp, [ r1, #OS_THREAD_OFFSET_CONTEXT+OS_CONTEXT_SP_SVC ]
|
|
||||||
mov r3, #HW_PSR_IRQ_MODE|HW_PSR_FIQ_DISABLE|HW_PSR_IRQ_DISABLE|HW_PSR_ARM_STATE
|
|
||||||
msr cpsr_c, r3
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ldr r2, [ r1, #OS_THREAD_OFFSET_CONTEXT ]! // *r1=context:CPSR
|
|
||||||
msr SPSR_cxsf, r2 // Put SPSR
|
|
||||||
|
|
||||||
ldr r14, [ r1, #OS_CONTEXT_PC_PLUS4 - OS_CONTEXT_CPSR ] // Get R15
|
|
||||||
ldmib r1, { r0-r14 }^ // Get R0-R14^ // *r1=over written
|
|
||||||
nop
|
|
||||||
stmda sp!, { r0-r3,r12,r14 } // Put R0-R3,R12,LR / *sp=stack:LR
|
|
||||||
|
|
||||||
ldmfd sp!, { pc } // return to irq master handler
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // BROM_ENABLE_THREAD
|
|
||||||
@ -48,10 +48,24 @@ asm void osIrqHandler( void )
|
|||||||
|
|
||||||
INASM_EXTERN( osIntrTable )
|
INASM_EXTERN( osIntrTable )
|
||||||
|
|
||||||
sub lr, lr, #4 // •œ‹AƒAƒhƒŒƒX’²<E28099>®
|
#ifdef SDK_ARM11
|
||||||
stmfd sp!, { r0-r3,r12,lr }
|
// 不正確データアボート有効化(clear HW_PSR_IMPRECISE_ABORT)
|
||||||
stmfd sp!, { lr } // save LR
|
msr cpsr_fsxc, #(HW_PSR_IRQ_MODE | HW_PSR_IRQ_DISABLE | HW_PSR_FIQ_DISABLE)
|
||||||
|
#endif // SDK_ARM11
|
||||||
|
|
||||||
|
stmfd sp!, { r0-r4,r12,lr }
|
||||||
|
|
||||||
|
// 割り込み要因の判定.
|
||||||
|
#ifdef SDK_ARM11
|
||||||
|
// Interrupt Acknowledge Register
|
||||||
|
ldr lr, =REG_CPUI_ACK_ADDR
|
||||||
|
ldr lr, [lr]
|
||||||
|
ldr r1, =REG_OS_CPUI_ACK_ID_MASK
|
||||||
|
and r4, r1, lr // r4に割り込み要因番号が入ってる
|
||||||
|
cmp r4, #__cpp(OS_INTR_ID_NUM)
|
||||||
|
bge my_undefined_interrupt_1
|
||||||
|
|
||||||
|
#else // SDK_ARM9
|
||||||
// get IE address
|
// get IE address
|
||||||
mov r12, #HW_REG_BASE
|
mov r12, #HW_REG_BASE
|
||||||
add r12, r12, #REG_IE_OFFSET // r12: REG_IE address
|
add r12, r12, #REG_IE_OFFSET // r12: REG_IE address
|
||||||
@ -60,11 +74,6 @@ asm void osIrqHandler( void )
|
|||||||
ldmia r12, { r1-r2 } // r1: IE, r2: IF
|
ldmia r12, { r1-r2 } // r1: IE, r2: IF
|
||||||
ands r1, r1, r2 // r1: IE & IF
|
ands r1, r1, r2 // r1: IE & IF
|
||||||
|
|
||||||
// if IE&IF==0 then return (without changing IF)
|
|
||||||
ldmeqfd sp!, { lr }
|
|
||||||
ldmeqfd sp!, { r0-r3,r12,pc }
|
|
||||||
|
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// IRQ HANDLING CODE for ARCHITECTURE VERSION 5
|
// IRQ HANDLING CODE for ARCHITECTURE VERSION 5
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
@ -79,20 +88,29 @@ LSYM(1) clz r0, r1 // count zero of high bit
|
|||||||
mov r1, r3, LSR r0
|
mov r1, r3, LSR r0
|
||||||
str r1, [ r12, #REG_IF_ADDR - REG_IE_ADDR ]
|
str r1, [ r12, #REG_IF_ADDR - REG_IE_ADDR ]
|
||||||
|
|
||||||
rsbs r0, r0, #31
|
rsbs r4, r0, #31
|
||||||
|
|
||||||
|
#endif // SDK_ARM9
|
||||||
|
|
||||||
// get jump vector
|
// get jump vector
|
||||||
ldr r1, =osIntrTable
|
ldr r1, =osIntrTable
|
||||||
ldr r0, [ r1, r0, LSL #2 ]
|
ldr r0, [ r1, r4, LSL #2 ]
|
||||||
|
|
||||||
blx r0 // set return address for thread rescheduling
|
blx r0 // set return address for thread rescheduling
|
||||||
|
|
||||||
|
#ifdef SDK_ARM11
|
||||||
|
// End of Interrupt Register
|
||||||
|
ldr lr, =REG_CPUI_EOI_ADDR
|
||||||
|
str r4, [lr]
|
||||||
|
#endif // SDK_ARM11
|
||||||
|
|
||||||
#ifdef BROM_ENABLE_THREAD
|
#ifdef BROM_ENABLE_THREAD
|
||||||
bl osIrqHandler_ThreadSwitch
|
bl osIrqHandler_ThreadSwitch
|
||||||
#endif // BROM_ENABLE_THREAD
|
#endif // BROM_ENABLE_THREAD
|
||||||
|
|
||||||
ldmfd sp!, { lr }
|
my_undefined_interrupt_1
|
||||||
ldmfd sp!, { r0-r3,r12,pc } // return to interrupted address
|
ldmfd sp!, { r0-r4,r12,lr } // return to interrupted address
|
||||||
|
subs pc, lr, #4
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef BROM_ENABLE_THREAD
|
#ifdef BROM_ENABLE_THREAD
|
||||||
@ -192,9 +210,9 @@ _dont_switched_
|
|||||||
mov r3, #HW_PSR_IRQ_MODE|HW_PSR_IRQ_DISABLE|HW_PSR_ARM_STATE
|
mov r3, #HW_PSR_IRQ_MODE|HW_PSR_IRQ_DISABLE|HW_PSR_ARM_STATE
|
||||||
msr cpsr_c, r3
|
msr cpsr_c, r3
|
||||||
|
|
||||||
ldmfd sp!, { lr }
|
|
||||||
ldmfd sp!, { r0-r3,r12,lr } // return to interrupted address
|
|
||||||
bx lr
|
bx lr
|
||||||
|
// ldmfd sp!, { lr }
|
||||||
|
// ldmfd sp!, { r0-r3,r12,pc } // return to interrupted address
|
||||||
// not reach here
|
// not reach here
|
||||||
|
|
||||||
|
|
||||||
Loading…
Reference in New Issue
Block a user