twl_wrapsdk/build/libraries/os/common/os_exception.c
nakasima a8f3113969 add HW_MAIN_MEM_HI and move HW_MAIN_MEM_SYSTEM.
fix interrupt func.

git-svn-id: file:///Users/lillianskinner/Downloads/platinum/twl/twl_wrapsdk/trunk@10 4ee2a332-4b2b-5046-8439-1ba90f034370
2007-04-04 11:58:10 +00:00

524 lines
15 KiB
C

/*---------------------------------------------------------------------------*
Project: NitroSDK - OS
File: os_exception.c
Copyright 2003-2006 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.
$Log: os_exception.c,v $
Revision 1.38 2006/05/24 07:54:06 kitase_hirotake
例外ハンドラの設定条件の変更
Revision 1.37 2006/05/08 09:26:16 okubata_ryoma
FINALROMの場合はデバッガ上でもOS_CONSOLE_NITROを返すことに関する修正
Revision 1.36 2006/04/04 06:05:53 yosizaki
コールスタックの8バイト整合に関する修正.
Revision 1.35 2006/01/18 02:11:30 kitase_hirotake
do-indent
Revision 1.34 2005/02/28 05:26:28 yosizaki
do-indent.
Revision 1.33 2004/11/02 10:35:45 yada
just fix comment
Revision 1.32 2004/10/03 09:59:16 yasu
Avoid sdkindent in inline-asm{}
Revision 1.31 2004/09/02 02:53:42 yada
only change comment
Revision 1.30 2004/08/26 00:20:10 yada
change method to distinguish running on debugger
Revision 1.29 2004/06/11 06:24:43 yada
close SDK_BB support
Revision 1.28 2004/06/10 06:25:06 yada
consider for occurring exception in THUMB mode
Revision 1.27 2004/06/07 10:56:35 yada
make difference to set handler according to exec environment
Revision 1.26 2004/05/12 11:00:48 yada
OSi_ExPrintf always uses OS_Printf
Revision 1.25 2004/05/12 05:34:29 yada
some fix
Revision 1.24 2004/05/12 05:31:46 yada
modification for DEBUGGER
Revision 1.23 2004/05/07 02:11:06 takano_makoto
Change OSiExContext offset definition.
Revision 1.22 2004/04/16 09:36:19 yada
fix temporary exception vector
0x27fffd9c->0x027ffd9c
Revision 1.21 2004/04/14 12:48:20 yada
IS-NITRO-DEBUGGERへの暫定対応
Revision 1.20 2004/03/30 06:09:29 yada
ldconst や lda を ldr = を使用する記述にした。
Revision 1.19 2004/03/18 12:56:43 yada
例外ベクタ設定のミス修正
Revision 1.18 2004/03/11 09:47:14 yada
例外時にFIQ,IRQ割り込み禁止していたのをIRQ割り込み禁止のみにした。
Revision 1.17 2004/03/09 02:37:59 yada
debuggerモニタハンドラ呼び出し判定部分修正
Revision 1.16 2004/03/08 02:54:13 yada
デバッガモニタの例外ハンドラを考慮
Revision 1.15 2004/03/01 11:54:24 yada
英語の関数comment作成
Revision 1.14 2004/02/19 08:43:05 yada
ユーザ例外ルーチンの型追加
Revision 1.13 2004/02/17 06:04:38 yada
ARM7への対応
Revision 1.12 2004/02/16 09:40:12 yada
ARM7側の割り込みもフックするようにした。
Revision 1.11 2004/02/16 00:49:30 yasu
Don't switch ISD/noISD by SDK_LINK_ISD.
Please use stubs library to resolve it at link time.
Revision 1.10 2004/02/13 04:05:28 yada
ARM9とAMR7 の場合わけ考慮
Revision 1.9 2004/02/12 11:08:30 yada
ARM9/ARM7 振り分け作業
Revision 1.8 2004/02/09 11:17:22 yasu
include code32.h
Revision 1.7 2004/02/05 10:50:59 yada
未定義命令で停止するようにした
Revision 1.6 2004/02/05 07:09:02 yasu
change SDK prefix iris -> nitro
Revision 1.5 2004/02/02 05:34:54 yada
OS_SetIrqMask()→OS_EnableIrqMask() へ
Revision 1.4 2004/01/30 08:05:36 yada
FINALROMでは例外表示をしないように修正
Revision 1.3 2004/01/30 04:31:47 yada
例外表示の組み込み
Revision 1.2 2004/01/16 01:18:05 yasu
Support SDK_BB
Revision 1.1 2004/01/14 12:03:05 yada
初版
$NoKeywords: $
*---------------------------------------------------------------------------*/
#include <nitro/hw/common/armArch.h>
#include <nitro/memorymap.h>
#include <nitro/os.h>
//---- displaying function OSi_ExPrintf
#ifdef SDK_ARM9
#define OSi_ExPrintf OS_Printf
//#define OSi_ExPrintf ISDPrintf
//void ISDPrintf( const char *pBuf, ... );
#else
#define OSi_ExPrintf OS_Printf
#endif
static asm void OSi_ExceptionHandler( void );
static asm void OSi_GetAndDisplayContext( void );
static asm void OSi_SetExContext( void );
static void OSi_DisplayExContext( void );
//---- context for exception display
typedef struct
{
OSContext context;
u32 cp15;
u32 spsr;
u32 exinfo;
u32 debug[4];
} OSiExContext;
static OSiExContext OSi_ExContext;
//---- user's exception handler
static OSExceptionHandler OSi_UserExceptionHandler;
static void *OSi_UserExceptionHandlerArg;
//---- debugger's exception handler
static void *OSi_DebuggerHandler = NULL;
//================================================================================
// exception vector
//================================================================================
/*---------------------------------------------------------------------------*
Name: OS_SetExceptionVectorUpper
Description: set exception vector to high address
Arguments: None
Returns: None
*---------------------------------------------------------------------------*/
#include <nitro/code32.h>
asm void OS_SetExceptionVectorUpper( void )
{
mrc p15, 0, r0, c1, c0, 0
orr r0, r0, #HW_C1_EXCEPT_VEC_UPPER
mcr p15, 0, r0, c1, c0, 0
bx lr
}
/*---------------------------------------------------------------------------*
Name: OS_SetExceptionVectorLower
Description: set exception vector to low address
Arguments: None
Returns: None
*---------------------------------------------------------------------------*/
asm void OS_SetExceptionVectorLower( void )
{
mrc p15, 0, r0, c1, c0, 0
bic r0, r0, #HW_C1_EXCEPT_VEC_UPPER
mcr p15, 0, r0, c1, c0, 0
bx lr
}
#include <nitro/codereset.h>
//================================================================================
// exception handling
//================================================================================
/*---------------------------------------------------------------------------*
Name: OS_InitException
Description: Initialize exception handling system
Arguments: None
Returns: None
*---------------------------------------------------------------------------*/
// 将来的には HW_EXCP_VECTOR_BUF をこの値に。
#define HW_EXCP_VECTOR_BUF_FOR_DEBUGGER HW_EXCP_VECTOR_MAIN
void OS_InitException(void)
{
//---- consider for debugger exception handler
if (0x2600000 <= *(u32 *)HW_EXCP_VECTOR_BUF_FOR_DEBUGGER
&& *(u32 *)HW_EXCP_VECTOR_BUF_FOR_DEBUGGER < HW_MAIN_MEM_EX_END)
{
OSi_DebuggerHandler = *(void **)HW_EXCP_VECTOR_BUF_FOR_DEBUGGER;
}
else
{
OSi_DebuggerHandler = NULL;
}
//---- exception hook
if (!OSi_DebuggerHandler)
{
*(u32 *)(HW_EXCP_VECTOR_BUF_FOR_DEBUGGER) = (u32)OSi_ExceptionHandler;
// for not-debugger, store handler address into original hook
*(u32 *)(HW_EXCP_VECTOR_BUF) = (u32)OSi_ExceptionHandler;
}
//---- user's handler
OSi_UserExceptionHandler = NULL;
}
/*---------------------------------------------------------------------------*
Name: OS_SetUserExceptionHandler
Description: set user exception handler and its argument
Arguments: handler exception hander
arg its argument
Returns: None
*---------------------------------------------------------------------------*/
void OS_SetUserExceptionHandler(OSExceptionHandler handler, void *arg)
{
OSi_UserExceptionHandler = handler;
OSi_UserExceptionHandlerArg = arg;
}
/*---------------------------------------------------------------------------*
Name: OSi_ExceptionHandler
Description: system exception handler
user handler is called from here
Arguments: None
Returns: None
*---------------------------------------------------------------------------*/
//
// status of stack is {cp15,spsr,r12,lr}
// LSB = 1 means coming by reset
//
#include <nitro/code32.h>
asm void OSi_ExceptionHandler( void )
{
//---- call debugger monitor handler (if exists)
ldr r12, =OSi_DebuggerHandler // r12のみ破壊可
ldr r12, [r12]
cmp r12, #0
movne lr, pc
bxne r12
//---- setting stack pointer <------------------------- consider later
#ifdef SDK_ARM9
//---- ARM9 stack
ldr r12, =HW_ITCM_END
#else
//---- ARM7 stack
ldr r12, =0x3806000
#endif
stmfd r12!, {r0-r3,sp,lr}
and r0, sp, #1
mov sp, r12
mrs r1, CPSR
and r1, r1, #0x1f
//---- if ABORT exception, stop
teq r1, #0x17
bne @10
bl OSi_GetAndDisplayContext
b usr_return
@10:
//---- if UNDEF exception, stop
teq r1, #0x1b
bne usr_return
bl OSi_GetAndDisplayContext
usr_return:
ldr r12, =OSi_DebuggerHandler
ldr r12, [r12]
cmp r12, #0
@1: beq @1
//( stop now even if debugger )
@2:
mov r0,r0 // nop
b @2
ldmfd sp!, {r0-r3, r12, lr}
mov sp, r12
bx lr
}
/*---------------------------------------------------------------------------*
Name: OSi_GetAndDisplayContext
Description: stop after displaying registers
Arguments: None
Returns: None
*---------------------------------------------------------------------------*/
static asm void OSi_GetAndDisplayContext( void )
{
stmfd sp!, {r0, lr} /* コールスタックを 8 バイト整合 */
//---- set exception context
bl OSi_SetExContext
//---- display exception context (and call user callback)
bl OSi_DisplayExContext
ldmfd sp!, {r0, lr} /* コールスタックを 8 バイト整合 */
bx lr
}
/*---------------------------------------------------------------------------*
Name: OSi_SetExContext
Description: set context when exception occurred
Arguments: None
Returns: None
*---------------------------------------------------------------------------*/
// explanation registers at the top of this function.
//
// in r12, {r0-r3,sp} (sp is exception sp) stored.
// in this sp, {cp15,spsr,r12,lr} (cp15,spsr,r12,lr is registers when exception occurred) stored.
// r4-r11 is registers then exception occurred.
// if you want to know spsr,sp,lr, please switch bank and read.
//
static asm void OSi_SetExContext( void )
{
//---- pointer ExContext structure
ldr r1, =OSi_ExContext;
mrs r2, CPSR
str r2, [r1, #OSiExContext.debug[1] ]
//---- store bit which means which is the reason, reset or exception
str r0, [r1, #OSiExContext.exinfo ]
//---- store r0 - r3
ldr r0, [r12,#0]
str r0, [r1, #OS_CONTEXT_R0]
ldr r0, [r12,#4]
str r0, [r1, #OS_CONTEXT_R1]
ldr r0, [r12,#8]
str r0, [r1, #OS_CONTEXT_R2]
ldr r0, [r12, #12]
str r0, [r1, #OS_CONTEXT_R3]
ldr r2, [r12, #16]
bic r2, r2, #1
//---- store r4 - r11
add r0, r1, #OS_CONTEXT_R4
stmia r0, {r4-r11}
//---- (for debug)
str r12, [r1, #OSiExContext.debug[0] ]
#ifdef SDK_ARM9
//---- get {cp15,cpsr,r12,pc} from stack
ldr r0, [r2, #0]
str r0, [r1, #OSiExContext.cp15 ]
ldr r3, [r2, #4]
str r3, [r1, #OS_CONTEXT_CPSR]
ldr r0, [r2, #8]
str r0, [r1, #OS_CONTEXT_R12]
ldr r0, [r2, #12]
str r0, [r1, #OS_CONTEXT_PC_PLUS4]
#else // ifdef SDK_ARM9
//---- get {cpsr,r12,pc} from stack
mov r0, #0
str r0, [r1, #OSiExContext.cp15]
ldr r3, [r2, #0]
str r3, [r1, #OS_CONTEXT_CPSR]
ldr r0, [r2, #4]
str r0, [r1, #OS_CONTEXT_R12]
ldr r0, [r2, #8]
str r0, [r1, #OS_CONTEXT_PC_PLUS4]
#endif // ifdef SDK_ARM9
//---- set mode to one which exception occurred
// but, disable IRQ
mrs r0, CPSR
orr r3, r3, #0x80
bic r3, r3, #0x20
msr CPSR_cxsf, r3
//---- get sp, lr, spsr
str sp, [r1, #OS_CONTEXT_R13]
str lr, [r1, #OS_CONTEXT_R14]
mrs r2, SPSR
//---- debugger
str r2, [r1, #OSiExContext.debug[3] ]
//---- restore mode
msr CPSR_cxsf, r0
bx lr
}
/*---------------------------------------------------------------------------*
Name: OSi_DisplayExContext
Description: stop after display exception context
Arguments: None
Returns: None
*---------------------------------------------------------------------------*/
static void OSi_DisplayExContext()
{
#ifndef SDK_FINALROM
int i;
OSi_ExPrintf("**** Exception Occurred ****\n");
//---------------- displaying registers
//---- for R0-15 Registers
for (i = 0; i < 13; i++)
{
OSi_ExPrintf("R%02d=%08X %c", i, OSi_ExContext.context.r[i], ((i & 3) == 3) ? '\n' : ' ');
}
OSi_ExPrintf("SP =%08X ", OSi_ExContext.context.sp);
OSi_ExPrintf("LR =%08X ", OSi_ExContext.context.lr);
OSi_ExPrintf("PC =%08X\n", OSi_ExContext.context.pc_plus4);
//---- for status Registers
#ifdef SDK_ARM9
OSi_ExPrintf(" CPSR=%08X SPSR=%08X CP15=%08X\n",
OSi_ExContext.context.cpsr, OSi_ExContext.spsr, OSi_ExContext.cp15);
#else
OSi_ExPrintf(" CPSR=%08X SPSR=%08X\n", OSi_ExContext.context.cpsr, OSi_ExContext.spsr);
#endif
//---- for Debug Values
#if 0
for (i = 0; i < 4; i++)
{
OSi_ExPrintf("DEBUG%02d=%08X ", i, OSi_ExContext.debug[i]);
}
#endif
OSi_ExPrintf("\n\n");
#endif
//---------------- user's callback
if (OSi_UserExceptionHandler)
{
//---- force to become SYS mode
// but, use current stack not SYS mode stack
asm
{
/* *INDENT-OFF* */
mov r0, sp
ldr r1, =0x9f
msr CPSR_cxsf, r1
mov sp, r0
/* *INDENT-ON* */
}
#ifdef SDK_ARM9
OS_EnableProtectionUnit();
#endif
//---- call user handler
((void (*)(u32, void *))OSi_UserExceptionHandler) ((u32)&OSi_ExContext,
OSi_UserExceptionHandlerArg);
#ifdef SDK_ARM9
OS_DisableProtectionUnit();
#endif
}
}
#include <nitro/codereset.h>