割り込みハンドラ追加。

git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-09-30%20-%20paladin.7z/paladin/ctr_firmware@89 b871894f-2f95-9b40-918c-086798483c85
This commit is contained in:
nakasima 2008-12-09 08:11:33 +00:00
parent 450a4db341
commit 6c21e49937
14 changed files with 1607 additions and 18 deletions

View File

@ -28,6 +28,7 @@ BROM_CODEGEN_ALL ?= TRUE
SRCDIR = . ../common
SRCS = \
os_irqHandler.c \
os_timer.c \
os_interrupt.c \
os_interrupt_common.c \

View File

@ -0,0 +1,226 @@
/*---------------------------------------------------------------------------*
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>
extern OSIntrFunction osIntrTable[OS_INTR_ID_NUM];
//---- thread queue for interrupt
OSThreadQueue OSi_IrqThreadQueue;
/*---------------------------------------------------------------------------*
Name: osIrqHandler
Description: IRQ handler. call handler according to OS_InterruptTable
Arguments: None
Returns: None
*---------------------------------------------------------------------------*/
asm void osIrqHandler( void )
{
PRESERVE8
INASM_EXTERN( osIntrTable )
stmfd sp!, { r0-r3,r12,lr }
stmfd sp!, { lr } // save 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, r0, LSL #2 ]
adr lr, irq_return
bx r0 // set return address for thread rescheduling
irq_return
// End of Interrupt Register
ldr lr, =REG_CPUI_EOI_ADDR
str r4, [lr]
bl osIrqHandler_ThreadSwitch
my_undefined_interrupt_1
ldmfd sp!, { lr }
ldmfd sp!, { r0-r3,r12,pc } // return to interrupted address
}
/*---------------------------------------------------------------------------*
Name: OS_IRQHandler_ThreadSwitch
Description: OS_InterruptTable
Arguments:
Returns:
*---------------------------------------------------------------------------*/
asm void osIrqHandler_ThreadSwitch(void)
{
INASM_EXTERN( OSi_IrqThreadQueue )
INASM_EXTERN( OSi_ThreadInfo )
//--------------------------------------------------
// wakeup threads in OSi_IrqThreadQueue
//--------------------------------------------------
ldr r12, =OSi_IrqThreadQueue
mov r3, #0 // avoid stall
ldr r12, [r12, #__cpp(offsetof(OSThreadQueue,head))] // r12 = OSi_IrqThreadQueue.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, =OSi_IrqThreadQueue
str r3, [r12, #__cpp(offsetof(OSThreadQueue,head))] // clear OSi_IrqThreadQueue.head
str r3, [r12, #__cpp(offsetof(OSThreadQueue,tail))] // clear OSi_IrqThreadQueue.tail
ldr r12, =OSi_ThreadInfo // 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 = OSi_ThreadInfo.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, =OSi_ThreadInfo
ldrh r1, [ r12, #OS_THREADINFO_OFFSET_ISNEEDRESCHEDULING ]
cmp r1, #0
beq _dont_switched_ // return if OSi_IsNeedResceduling == 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 = &OSi_ThreadInfo.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
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
}

View File

@ -31,9 +31,10 @@ BROM_PROC = ARM9
SRCDIR = . ../common
SRCS = \
os_interrupt.c \
os_irqHandler.c \
os_timer.c \
os_tick.c \
os_interrupt.c \
os_interrupt_common.c \
TARGET_LIB = libos_sp$(BROM_LIBSUFFIX).a

View File

@ -0,0 +1,248 @@
/*---------------------------------------------------------------------------*
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>
#ifdef SDK_ARM9
#include <brom/dtcm_begin.h>
#endif
//---- thread queue for interrupt
OSThreadQueue OSi_IrqThreadQueue; // = { NULL, NULL };
#ifdef SDK_ARM9
#include <brom/dtcm_end.h>
#include <brom/itcm_begin.h>
#endif
extern OSIntrFunction osIntrTable[OS_INTR_ID_NUM];
/*---------------------------------------------------------------------------*
Name: osIrqHandler
Description: IRQ handler. call handler according to OS_InterruptTable
Arguments: None
Returns: None
*---------------------------------------------------------------------------*/
asm void osIrqHandler( void )
{
PRESERVE8
INASM_EXTERN( osIntrTable )
stmfd sp!, { r0-r3,r12,lr }
stmfd sp!, { lr } // save LR
// get IE address
mov r12, #HW_REG_BASE
add r12, r12, #REG_IE_OFFSET // r12: REG_IE address
// get IE&IF
ldmia r12, { r1-r2 } // r1: IE, r2: 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
//--------------------------------------------------
// get lowest 1 bit
mov r3, #1<<31
LSYM(1) clz r0, r1 // count zero of high bit
bics r1, r1, r3, LSR r0
bne BSYM(1)
// clear IF
mov r1, r3, LSR r0
str r1, [ r12, #REG_IF_ADDR - REG_IE_ADDR ]
rsbs r0, r0, #31
// get jump vector
ldr r1, =osIntrTable
ldr r0, [ r1, r0, LSL #2 ]
ldr lr, =osIrqHandler_ThreadSwitch
bx r0 // set return address for thread rescheduling
}
/*---------------------------------------------------------------------------*
Name: OS_IRQHandler_ThreadSwitch
Description: OS_InterruptTable
Arguments:
Returns:
*---------------------------------------------------------------------------*/
asm void osIrqHandler_ThreadSwitch(void)
{
INASM_EXTERN( OSi_IrqThreadQueue )
INASM_EXTERN( OSi_ThreadInfo )
//--------------------------------------------------
// wakeup threads in OSi_IrqThreadQueue
//--------------------------------------------------
ldr r12, =OSi_IrqThreadQueue
mov r3, #0 // avoid stall
ldr r12, [r12, #__cpp(offsetof(OSThreadQueue,head))] // r12 = OSi_IrqThreadQueue.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, =OSi_IrqThreadQueue
str r3, [r12, #__cpp(offsetof(OSThreadQueue,head))] // clear OSi_IrqThreadQueue.head
str r3, [r12, #__cpp(offsetof(OSThreadQueue,tail))] // clear OSi_IrqThreadQueue.tail
ldr r12, =OSi_ThreadInfo // 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 = OSi_ThreadInfo.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, =OSi_ThreadInfo
ldrh r1, [ r12, #OS_THREADINFO_OFFSET_ISNEEDRESCHEDULING ]
cmp r1, #0
beq _dont_switched_ // return if OSi_IsNeedResceduling == 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 = &OSi_ThreadInfo.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
ldmfd sp!, { lr }
ldmfd sp!, { r0-r3,r12,lr } // return to interrupted address
bx lr
// 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
}
#ifdef SDK_ARM9
#include <brom/itcm_end.h>
#endif

View File

@ -0,0 +1,29 @@
/*---------------------------------------------------------------------------*
Project: CtrBrom - include -
File: dtcm_begin.h
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 this instead of using C99 pragma extensions for compatibility
//
#if defined(__CC_ARM)
#pragma arm section rodata=".dtcm", rwdata=".dtcm", zidata=".dtcm.bss"
#elif defined(__MWERKS__)
#include <brom/section.h>
#pragma section DTCM begin
#elif defined(__GNUC__)
TO BE DEFINED
#endif

View File

@ -0,0 +1,28 @@
/*---------------------------------------------------------------------------*
Project: CtrBrom - include -
File: dtcm_end.h
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 this instead of using C99 pragma extensions for compatibility
//
#if defined(__CC_ARM)
#pragma arm section code, rwdata, rodata, zidata
#elif defined(__MWERKS__)
#pragma section DTCM end
#elif defined(__GNUC__)
TO BE DEFINED
#endif

View File

@ -0,0 +1,29 @@
/*---------------------------------------------------------------------------*
Project: CtrBrom - include -
File: itcm_begin.h
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 this instead of using C99 pragma extensions for compatibility
//
#if defined(__CC_ARM)
#pragma arm section code=".itcm", rodata=".itcm", rwdata=".itcm", zidata=".itcm.bss"
#elif defined(__MWERKS__)
#include <brom/section.h>
#pragma section ITCM begin
#elif defined(__GNUC__)
TO BE DEFINED
#endif

View File

@ -0,0 +1,28 @@
/*---------------------------------------------------------------------------*
Project: CtrBrom - include -
File: itcm_begin.h
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 this instead of using C99 pragma extensions for compatibility
//
#if defined(__CC_ARM)
#pragma arm section code, rwdata, rodata, zidata
#elif defined(__MWERKS__)
#pragma section ITCM end
#elif defined(__GNUC__)
TO BE DEFINED
#endif

View File

@ -23,7 +23,7 @@
extern "C" {
#endif
#define offsetof(t, memb) ((size_t)(&(((t *)0)->memb)))
#define offsetof(t, memb) ((u32)(&(((t *)0)->memb)))
#ifdef __cplusplus
} /* extern "C" */

View File

@ -31,6 +31,7 @@ extern "C" {
#include <brom/math.h>
#include <brom/os/common/system.h>
#include <brom/os/common/init.h>
#include <brom/os/common/thread.h>
#ifdef SDK_ARM11
#include <brom/os/ARM11/interrupt.h>
#include <brom/os/ARM11/timer.h>

View File

@ -27,9 +27,6 @@ extern "C" {
#define OS_IDR_INTR_PRIO_DEFAULT 8 // Interrupt priority default (0-15)
extern OSIntrFunction osIntrTable[OS_INTR_ID_NUM];
OSIntrID i_osReadHighestPendingInterruptRegister( void );
OSIntrID i_osReadInterruptAcknowledgeRegister( void );

View File

@ -0,0 +1,95 @@
/*---------------------------------------------------------------------------*
Project: CtrBrom - OS - include
File: context.h
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$
*---------------------------------------------------------------------------*/
#ifndef BROM_OS_CONTEXT_H_
#define BROM_OS_CONTEXT_H_
#include <brom/os/common/system.h>
#ifdef SDK_ARM11
//#include <brom/cp/context.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
//----------------------------------------------------------------------------
#define SDK_CONTEXT_HAS_SP_SVC
//----------------------------------------------------------------------------
#define OS_CONTEXT_CPSR 0
#define OS_CONTEXT_R0 4
#define OS_CONTEXT_R1 8
#define OS_CONTEXT_R2 12
#define OS_CONTEXT_R3 16
#define OS_CONTEXT_R4 20
#define OS_CONTEXT_R5 24
#define OS_CONTEXT_R6 28
#define OS_CONTEXT_R7 32
#define OS_CONTEXT_R8 36
#define OS_CONTEXT_R9 40
#define OS_CONTEXT_R10 44
#define OS_CONTEXT_R11 48
#define OS_CONTEXT_R12 52
#define OS_CONTEXT_R13 56
#define OS_CONTEXT_R14 60
#define OS_CONTEXT_PC_PLUS4 64 // Should be set to PC+4 for interrupt handling
#define OS_CONTEXT_SP OS_CONTEXT_R13
#define OS_CONTEXT_LR OS_CONTEXT_R14
#ifdef SDK_CONTEXT_HAS_SP_SVC
#define OS_CONTEXT_R13_SVC 68
#define OS_CONTEXT_SP_SVC OS_CONTEXT_R13_SVC
#endif
#ifdef SDK_ARM9
#ifdef SDK_CONTEXT_HAS_SP_SVC
#define OS_CONTEXT_CP_CONTEXT 72
#else
#define OS_CONTEXT_CP_CONTEXT 68
#endif
#endif
typedef struct OSContext
{
u32 cpsr;
u32 r[13];
u32 sp;
u32 lr;
u32 pc_plus4;
#ifdef SDK_CONTEXT_HAS_SP_SVC
u32 sp_svc;
#endif
}
OSContext;
//----------------------------------------------------------------------------
void OS_InitContext(OSContext *context, u32 newpc, u32 newsp);
BOOL OS_SaveContext(OSContext *context);
void OS_LoadContext(OSContext *context);
void OS_DumpContext(OSContext *context);
#ifdef __cplusplus
} /* extern "C" */
#endif
/* BROM_OS_CONTEXT_H_ */
#endif

View File

@ -96,19 +96,6 @@ void osInitInterrupt( void );
void osSetInterruptHandler( OSIntrID id, OSIntrFunction handler );
/*---------------------------------------------------------------------------*
Name: osSetInterruptMaskForMultiInterrupt
Description: Set interrupt mask for multi interrupt
Arguments: interrupt ID
interrupt mask
Returns: None
*---------------------------------------------------------------------------*/
void osSetInterruptMaskForMultiInterrupt( OSIntrID id, OSIntrMask *mask );
/*---------------------------------------------------------------------------*
Name: osHalt

View File

@ -0,0 +1,919 @@
/*---------------------------------------------------------------------------*
Project: CtrBrom - OS - include
File: thread.h
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$
*---------------------------------------------------------------------------*/
#ifndef BROM_OS_THREAD_H_
#define BROM_OS_THREAD_H_
#include <brom/misc.h>
#include <brom/os/common/context.h>
//#include <brom/os/common/callTrace.h>
//#include <ctr/version.h>
#ifdef __cplusplus
extern "C" {
#endif
//---- build switch to let number of thread infinity, for version 3.0 or later
//#if SDK_VERSION_MAJOR >= 3
#define SDK_THREAD_INFINITY 1
//#endif
#ifdef SDK_FINALROM
// define if callTrace system not used
#define OS_NO_CALLTRACE
#endif
#ifndef SDK_THREAD_INFINITY
//---- maximum number of thread
#define OS_THREAD_MAX_NUM 16 // changed 8 to 16 (2004/5/26)
#endif
//---- priority of thread that calls OS_InitThread()
#define OS_THREAD_LAUNCHER_PRIORITY 16
//---- range of thread priority
#define OS_THREAD_PRIORITY_MIN 0
#define OS_THREAD_PRIORITY_MAX 31
//----------------------------------------------------------------------------
typedef struct _OSThread OSThread;
#ifdef SDK_THREAD_INFINITY
typedef struct _OSThreadQueue OSThreadQueue;
typedef struct _OSThreadLink OSThreadLink;
typedef struct _OSMutexQueue OSMutexQueue;
typedef struct _OSMutexLink OSMutexLink;
typedef struct OSMutex OSMutex;
#endif
typedef struct OSiAlarm OSAlarm;
#ifdef SDK_THREAD_INFINITY
struct _OSThreadQueue
{
OSThread *head;
OSThread *tail;
};
struct _OSThreadLink
{
OSThread *prev;
OSThread *next;
};
struct _OSMutexQueue
{
OSMutex *head;
OSMutex *tail;
};
struct _OSMutexLink
{
OSMutex *next;
OSMutex *prev;
};
#endif
//---------------- Thread status
typedef enum
{
OS_THREAD_STATE_WAITING = 0,
OS_THREAD_STATE_READY = 1,
OS_THREAD_STATE_TERMINATED = 2
}
OSThreadState;
#ifndef SDK_THREAD_INFINITY
//---------------- thread queue
#if ( OS_THREAD_MAX_NUM <= 16 )
typedef u16 OSThreadQueue;
#define OS_SIZEOF_OSTHREADQUEUE 16
#elif ( OS_THREAD_MAX_NUM <= 32 )
typedef u32 OSThreadQueue;
#define OS_SIZEOF_OSTHREADQUEUE 32
#else
Error:no bit field any more
#endif
#endif
#define OS_THREAD_SPECIFIC_MAX 3
typedef void (*OSThreadDestructor) (void *);
//---------------- Thread structure
struct _OSThread
{
OSContext context;
OSThreadState state;
OSThread *next;
u32 id;
u32 priority;
void *profiler;
#ifdef SDK_THREAD_INFINITY
OSThreadQueue *queue;
OSThreadLink link;
#endif
#ifndef SDK_THREAD_INFINITY
void *mutex;
void *mutexQueueHead;
void *mutexQueueTail;
#else
OSMutex *mutex; // OSMutex
OSMutexQueue mutexQueue; // OSMutexQueue
#endif
u32 stackTop; // for stack overflow
u32 stackBottom; // for stack underflow
u32 stackWarningOffset;
#ifndef SDK_THREAD_INFINITY
OSThreadQueue joinQueue; // for wakeup threads in thread termination
#if OS_SIZEOF_OSTHREADQUEUE == 16
u16 padding;
#endif
#else
OSThreadQueue joinQueue;
void *specific[OS_THREAD_SPECIFIC_MAX]; // for internal use
OSAlarm *alarmForSleep; // OSAlarm for sleeping
OSThreadDestructor destructor; // thread destructor
void *userParameter; // for user
int systemErrno;
#endif
};
//---------------- Thread & context packed structure
typedef struct OSThreadInfo
{
u16 isNeedRescheduling;
#ifndef SDK_THREAD_INFINITY
u16 max_entry;
u16 irqDepth;
u16 padding;
#else
u16 irqDepth;
#endif
OSThread *current;
OSThread *list;
void *switchCallback; // type: OSSwitchThreadCallback
#ifndef SDK_THREAD_INFINITY
OSThread *entry[OS_THREAD_MAX_NUM];
#endif
}
OSThreadInfo;
// offset
#ifndef SDK_THREAD_INFINITY
#define OS_THREADINFO_OFFSET_ISNEEDRESCHEDULING 0
#define OS_THREADINFO_OFFSET_MAX_ENTRY 2
#define OS_THREADINFO_OFFSET_IRQDEPTH 4
#define OS_THREADINFO_OFFSET_PADDING 6
#define OS_THREADINFO_OFFSET_CURRENT 8
#define OS_THREADINFO_OFFSET_LIST 12
#define OS_THREADINFO_OFFSET_SWITCHCALLBACK 16
#define OS_THREADINFO_OFFSET_ENTRY 20
#else // ifndef SDK_THREAD_INFINITY
#define OS_THREADINFO_OFFSET_ISNEEDRESCHEDULING 0
#define OS_THREADINFO_OFFSET_IRQDEPTH 2
#define OS_THREADINFO_OFFSET_CURRENT 4
#define OS_THREADINFO_OFFSET_LIST 8
#define OS_THREADINFO_OFFSET_SWITCHCALLBACK 12
#define OS_THREADINFO_OFFSET_ENTRY 16
#endif
//---------------- CONTEXT OFFSET
#define OS_THREAD_OFFSET_CONTEXT 0
#define OS_THREAD_OFFSET_STATE (sizeof(OSContext))
#define OS_THREAD_OFFSET_NEXT (sizeof(OSContext)+sizeof(OSThreadState))
#define OS_THREAD_OFFSET_ID (OS_THREAD_OFFSET_NEXT+sizeof(OSThread*))
//---------------- thread stack overflow status
typedef enum
{
OS_STACK_NO_ERROR = 0,
OS_STACK_OVERFLOW = 1,
OS_STACK_ABOUT_TO_OVERFLOW = 2,
OS_STACK_UNDERFLOW = 3
}
OSStackStatus;
//---------------- thread switch callback
typedef void (*OSSwitchThreadCallback) (OSThread *from, OSThread *to);
//----------------------------------------------------------------------------
//---- private function ( don't use these OSi_* function )
void OSi_CheckStack(const char *file, int line, const OSThread *thread);
u32 OSi_GetSystemStackPointer(void);
u32 OSi_GetCurrentStackPointer(void);
OSThread *OSi_GetIdleThread(void);
/*---------------------------------------------------------------------------*
Name: OS_InitThread
Description: Initialize Thread System
Arguments: None
Returns: None
*---------------------------------------------------------------------------*/
void OS_InitThread(void);
/*---------------------------------------------------------------------------*
Name: OS_IsThreadAvailable
Description: check if thread system is available
Arguments: None
Returns: TRUE if available, FALSE if not
*---------------------------------------------------------------------------*/
BOOL OS_IsThreadAvailable(void);
/*---------------------------------------------------------------------------*
Name: OS_CreateThread
Description: Create a new Thread
Arguments: thread pointer of thread structure
func function to start thread
arg argument for func
stack stack bottom address
stackSize stack size (byte. must be aligned by 4)
prio thread priority
Returns: None
*---------------------------------------------------------------------------*/
void OS_CreateThread(OSThread *thread,
void (*func) (void *), void *arg, void *stack, u32 stackSize, u32 prio);
/*---------------------------------------------------------------------------*
Name: OS_ExitThread
Description: Exit thread
Arguments: None
Returns: None
*---------------------------------------------------------------------------*/
void OS_ExitThread(void);
/*---------------------------------------------------------------------------*
Name: OS_DestroyThread
Description: destroy specified thread.
Arguments: thread: thread to be destroyed
Returns: None
*---------------------------------------------------------------------------*/
void OS_DestroyThread(OSThread *thread);
/*---------------------------------------------------------------------------*
Name: OS_KillThread
Description: switch PC to thread destructor to finalize thread
Arguments: thread : thread to wait to finish
flag : argument for destructor
Returns: None
*---------------------------------------------------------------------------*/
#ifdef SDK_THREAD_INFINITY
void OS_KillThread(OSThread *thread, void *arg);
void OS_KillThreadWithPriority(OSThread *thread, void *arg, u32 prio);
#endif
/*---------------------------------------------------------------------------*
Name: OS_JoinThread
Description: wait for specified thread to terminated
Arguments: thread : thraead to wait to finish
Returns: None
*---------------------------------------------------------------------------*/
void OS_JoinThread(OSThread *thread);
/*---------------------------------------------------------------------------*
Name: OS_IsThreadTeminated
Description: check thread status whether it's terminated
Arguments: thread : pointer to thread to be examined
Returns: TRUE if the thread is terminated. FALSE if not
*---------------------------------------------------------------------------*/
BOOL OS_IsThreadTerminated(const OSThread *thread);
/*---------------------------------------------------------------------------*
Name: OS_SelectThread
Description: Select thread to execute
Arguments: None
Returns: thread to execute
*---------------------------------------------------------------------------*/
OSThread *OS_SelectThread(void);
/*---------------------------------------------------------------------------*
Name: OS_RescheduleThread
Description: do rescheduling threads
Arguments: None
Returns: None
*---------------------------------------------------------------------------*/
void OS_RescheduleThread(void);
/*---------------------------------------------------------------------------*
Name: OS_YieldThread
Description: do thread rescheduling. current thread relinquish CPU
to give chance of running to other threads which has same
priority.
Arguments: None
Returns: None
*---------------------------------------------------------------------------*/
extern void OS_YieldThread(void);
/*---------------------------------------------------------------------------*
Name: OS_SleepThread
Description: sleep current thread
Arguments: thread Thread queue
Returns: None
*---------------------------------------------------------------------------*/
void OS_SleepThread(OSThreadQueue *queue);
/*---------------------------------------------------------------------------*
Name: OS_WakeupThread
Description: wake up threads by queue
Arguments: queue Thread queue
Returns: None
*---------------------------------------------------------------------------*/
void OS_WakeupThread(OSThreadQueue *queue);
/*---------------------------------------------------------------------------*
Name: OS_WakeupThreadDirect
Description: wake up thread by specifying thread directly
Arguments: thread Thread to wake up
Returns: None
*---------------------------------------------------------------------------*/
void OS_WakeupThreadDirect(OSThread *thread);
/*---------------------------------------------------------------------------*
Name: OS_DumpThreadList
Description: Dump All Thread Infomation (for DEBUG)
Arguments: None
Returns: None
*---------------------------------------------------------------------------*/
void OS_DumpThreadList(void);
/*---------------------------------------------------------------------------*
Name: OS_GetNumberOfThread
Description: Get number of thread which exists in system
Arguments: None
Returns: number of thread which exists in system
*---------------------------------------------------------------------------*/
int OS_GetNumberOfThread(void);
/*==== static inlie functions ====*/
/*---------------------------------------------------------------------------*
Name: OS_GetThreadInfo
Description: Get pointer of system thread info structure.
Arguments: None
Returns: pointer of thread info structure
*---------------------------------------------------------------------------*/
extern OSThreadInfo OSi_ThreadInfo;
static inline OSThreadInfo *OS_GetThreadInfo(void)
{
return &OSi_ThreadInfo;
}
/*---------------------------------------------------------------------------*
Name: OS_GetMaxThreadId
Description: Gets Max id number of available thread number
Arguments: None
Returns: Max id of available thread number
*---------------------------------------------------------------------------*/
static inline u32 OS_GetMaxThreadId(void)
{
#ifndef SDK_THREAD_INFINITY
return OS_GetThreadInfo()->max_entry;
#else
return 0x7fffffff; // (=maximin number of int)
#endif
}
/*---------------------------------------------------------------------------*
Name: OS_GetThread
Description: Gets pointer to thread which id is specified
Arguments: id : thread id to get thread
Returns: pointer to thread which id is specified
*---------------------------------------------------------------------------*/
#ifndef SDK_THREAD_INFINITY
static inline OSThread *OS_GetThread(u32 id)
{
SDK_ASSERTMSG(id < OS_THREAD_MAX_NUM, "Thread id illegal\n");
return OS_GetThreadInfo()->entry[id];
}
#else
extern OSThread *OS_GetThread(u32 id);
#endif
/*---------------------------------------------------------------------------*
Name: OS_GetThreadId
Description: Gets id of specified thread
Arguments: thread pointer to thread
Returns: id of specified thread
*---------------------------------------------------------------------------*/
static inline u32 OS_GetThreadId(const OSThread *thread)
{
SDK_ASSERTMSG(thread, "null thread pointer.");
return thread->id;
}
/*---------------------------------------------------------------------------*
Name: OS_GetThreadState
Description: Gets state of specified thread
Arguments: thread pointer to thread
Returns: state of specified thead
*---------------------------------------------------------------------------*/
static inline OSThreadState OS_GetThreadState(const OSThread *thread)
{
SDK_ASSERTMSG(thread, "null thread pointer.");
return thread->state;
}
/*---------------------------------------------------------------------------*
Name: OS_GetThreadContext
Description: Gets pointer to context of specified thread
Arguments: thread pointer to thread
Returns: pointer to context of specified thread
*---------------------------------------------------------------------------*/
static inline OSContext *OS_GetThreadContext(const OSThread *thread)
{
SDK_ASSERTMSG(thread, "null thread pointer.");
return (OSContext *)&thread->context;
}
/*---------------------------------------------------------------------------*
Name: OS_IsThreadRunnable
Description: Check if thread is runnable
Arguments: thread pointer to thread
Returns: non zero if thread is runnable
*---------------------------------------------------------------------------*/
static inline BOOL OS_IsThreadRunnable(const OSThread *thread)
{
return thread->state == OS_THREAD_STATE_READY;
}
/*---------------------------------------------------------------------------*
Name: OS_InitThreadQueue
Description: Initialize thread queue
Arguments: queue pointer to thread queue
Returns: None
*---------------------------------------------------------------------------*/
static inline void OS_InitThreadQueue(OSThreadQueue *queue)
{
#ifndef SDK_THREAD_INFINITY
*queue = 0;
#else
queue->head = queue->tail = NULL;
#endif
}
/*---------------------------------------------------------------------------*
Name: OS_GetCurrentThread
Description: Gets pointer to the current thread
Arguments: None
Returns: Pointer to the current thread
*---------------------------------------------------------------------------*/
static inline OSThread *OS_GetCurrentThread(void)
{
return OS_GetThreadInfo()->current;
}
/*---------------------------------------------------------------------------*
Name: OS_SetCurrentThread
Description: Saves pointer to the current thread
Arguments: thread : thread to be current thread
Returns: Pointer to the current thread
*---------------------------------------------------------------------------*/
static inline void OS_SetCurrentThread(OSThread *thread)
{
OS_GetThreadInfo()->current = thread;
}
/*==== stack check ====*/
/*---------------------------------------------------------------------------*
Name: OS_SetThreadStackWarningOffset
Description: Set warning level for stack checker
Arguments: thread thread to set
offset offset from stack top. must be multiple of 4
Returns: None
*---------------------------------------------------------------------------*/
void OS_SetThreadStackWarningOffset(OSThread *thread, u32 offset);
/*---------------------------------------------------------------------------*
Name: OS_GetStackStatus
Description: check thread stack. check each CheckNUM.
return result.
Arguments: thread thread checked
Returns: 0 no error
OS_STACK_OVERFLOW overflow
OS_STACK_ABOUT_TO_OVERFLOW about to overflow
OS_STACK_UNDERFLOW underflow
*---------------------------------------------------------------------------*/
OSStackStatus OS_GetStackStatus(const OSThread *thread);
/*---------------------------------------------------------------------------*
Name: OS_CheckStack
Description: check thread stack. check each CheckNum.
if changed, display warning and halt.
Arguments: thread thread to check stack
Returns: None.
( if error occurred, never return )
*---------------------------------------------------------------------------*/
#if !defined(SDK_FINALROM) && !defined(SDK_NO_MESSAGE)
#define OS_CheckStack( thread ) OSi_CheckStack( __FILE__, __LINE__, (const OSThread*)thread );
#else
#define OS_CheckStack( thread ) ((void)0)
#endif
/*---------------------------------------------------------------------------*
Name: OS_SetThreadPriority
Description: change priority of thread
Arguments: thread thread to set priority
prio new priority to be set
Returns: TRUE if success
*---------------------------------------------------------------------------*/
BOOL OS_SetThreadPriority(OSThread *thread, u32 prio);
/*---------------------------------------------------------------------------*
Name: OS_GetThreadPriority
Description: get priority of thread
Arguments: thread thread to get priority
Returns: priority
*---------------------------------------------------------------------------*/
u32 OS_GetThreadPriority(const OSThread *thread);
/*---------------------------------------------------------------------------*
Name: OS_Sleep
Description: sleep specified period
Arguments: msec sleeping period. ( milliseconds )
Returns: None.
*---------------------------------------------------------------------------*/
void OS_Sleep(u32 msec);
/*---------------------------------------------------------------------------*
Name: OS_SetSwitchThreadCallback
Description: set callback called at switching thread
Arguments: callback callback function
Returns: previous callback function before set callback now
*---------------------------------------------------------------------------*/
OSSwitchThreadCallback OS_SetSwitchThreadCallback(OSSwitchThreadCallback callback);
// notice: substans is in os_callTrace.c.
// define here because of OSThread declaration.
/*---------------------------------------------------------------------------*
Name: OS_DumpThreadCallTrace
Description: dump callStack of thread
Arguments: thread : thread
Returns: None
*---------------------------------------------------------------------------*/
void OS_DumpThreadCallTrace(const OSThread *thread);
/*---------------------------------------------------------------------------*
Name: OS_DisableScheduler
Description: disable scheduler
Arguments: None
Returns: Previous scheduler suspend count.
Suspended if value >= 0.
*---------------------------------------------------------------------------*/
u32 OS_DisableScheduler(void);
/*---------------------------------------------------------------------------*
Name: OS_EnableScheduler
Description: enable scheduler
Arguments: None
Returns: Previous scheduler suspend count.
Suspended if value >= 0.
*---------------------------------------------------------------------------*/
u32 OS_EnableScheduler(void);
#ifdef SDK_THREAD_INFINITY
/*---------------------------------------------------------------------------*
Name: OS_SetThreadDestructor
Description: set thread destructor, which is called when that thread exits.
Arguments: thread : thread pointer
dtor : destructor function
Returns: None
*---------------------------------------------------------------------------*/
void OS_SetThreadDestructor(OSThread *thread, OSThreadDestructor dtor);
/*---------------------------------------------------------------------------*
Name: OS_GetThreadDestructor
Description: get thread destructor which is set
Arguments: thread : thread pointer
Returns: destructor function
*---------------------------------------------------------------------------*/
OSThreadDestructor OS_GetThreadDestructor(const OSThread *thread);
/*---------------------------------------------------------------------------*
Name: OS_SetThreadParameter
Description: set user parameter which is allowed to use freely.
Arguments: thread : thread pointer
parameter : user parameter
Returns: None
*---------------------------------------------------------------------------*/
void OS_SetThreadParameter(OSThread *thread, void *parameter);
/*---------------------------------------------------------------------------*
Name: OS_GetThreadParameter
Description: get user parameter which is set
Arguments: thread : thread pointer
Returns: user parameter which is set
*---------------------------------------------------------------------------*/
void *OS_GetThreadParameter(const OSThread *thread);
/*---------------------------------------------------------------------------*
Name: OS_GetErrno
Description: get system error number.
Arguments: None.
Returns: error number
*---------------------------------------------------------------------------*/
int OS_GetErrno(void);
#endif
/*---------------------------------------------------------------------------*
Name: OS_IsThreadInList
Description: check if the specified thread is in the thread list
Arguments: thread : thread
Returns: TRUE if thread is in the thread list
*---------------------------------------------------------------------------*/
BOOL OS_IsThreadInList(const OSThread *thread);
/*---------------------------------------------------------------------------*
Name: OS_SetThreadDestructorStack
Description: specify stack area to call thread destructor
Arguments: stack stack bottom address
Returns: None
*---------------------------------------------------------------------------*/
void OS_SetThreadDestructorStack(void *stack);
#ifdef SDK_THREAD_INFINITY
//================================================================================
// The following functions are for internal use. Not for user.
//================================================================================
/*---------------------------------------------------------------------------*
Name: OSi_RemoveMutexLinkFromQueue
Description: remove mutex from mutex queue
Arguments: queue : mutex queue
Returns: mutex pointer which is removed
*---------------------------------------------------------------------------*/
extern OSMutex *OSi_RemoveMutexLinkFromQueue(OSMutexQueue * queue);
/*---------------------------------------------------------------------------*
Name: OSi_SetSystemErrno
Description: set system error number.
Arguments: thread : thread to set error number
errno : error number to set
Returns: None
*---------------------------------------------------------------------------*/
void OSi_SetSystemErrno(OSThread *thread, int errno);
/*---------------------------------------------------------------------------*
Name: OSi_GetSystemErrno
Description: get system error number.
Arguments: thread : thread to set error number
Returns: error number
*---------------------------------------------------------------------------*/
int OSi_GetSystemErrno(const OSThread *thread);
#define OSi_SPECIFIC_CPS 0
/*---------------------------------------------------------------------------*
Name: OSi_SetSpecificData
Description: set system specific data
Arguments: thread : thread to set data
index : index of specific array
data : data to set
Returns: None
*---------------------------------------------------------------------------*/
static inline void OSi_SetSpecificData(OSThread *thread, int index, void *data)
{
SDK_ASSERT(thread && 0 <= index && index < OS_THREAD_SPECIFIC_MAX);
thread->specific[index] = data;
}
/*---------------------------------------------------------------------------*
Name: OSi_GetSpecificData
Description: get system specific data
Arguments: thread : thread to get data
index : index of specific array
Returns: error number
*---------------------------------------------------------------------------*/
static inline void *OSi_GetSpecificData(const OSThread *thread, int index)
{
SDK_ASSERT(thread && 0 <= index && index < OS_THREAD_SPECIFIC_MAX);
return thread->specific[index];
}
#endif
//================================================================================
// The following functions are for operations of thread struct.
// use carefully.
//================================================================================
/*---------------------------------------------------------------------------*
Name: OS_GetThreadList
Description: get first thread of thread list.
Arguments: None
Returns: first thread of thread list
*---------------------------------------------------------------------------*/
static inline OSThread *OS_GetThreadList(void)
{
return OS_GetThreadInfo()->list;
}
/*---------------------------------------------------------------------------*
Name: OS_GetNextThread
Description: get thread which is linked next in thread list
Arguments: thread : thread to get next thread
Returns: next thread. NULL means no next thread ( specified thread may be last )
*---------------------------------------------------------------------------*/
static inline OSThread *OS_GetNextThread(const OSThread *thread)
{
SDK_ASSERT(thread);
return thread->next;
}
#ifdef __cplusplus
} /* extern "C" */
#endif
/* BROM_OS_THREAD_H_ */
#endif