diff options
-rw-r--r-- | arm9/asm/OS_alarm.s | 350 | ||||
-rw-r--r-- | arm9/lib/include/OS_alarm.h | 14 | ||||
-rw-r--r-- | arm9/lib/include/OS_interrupt.h | 1 | ||||
-rw-r--r-- | arm9/lib/include/registers.h | 1 | ||||
-rw-r--r-- | arm9/lib/src/OS_alarm.c | 250 |
5 files changed, 265 insertions, 351 deletions
diff --git a/arm9/asm/OS_alarm.s b/arm9/asm/OS_alarm.s deleted file mode 100644 index 9978bfbe..00000000 --- a/arm9/asm/OS_alarm.s +++ /dev/null @@ -1,350 +0,0 @@ - .include "asm/macros.inc" - .include "global.inc" - - .section .bss - - .global OSi_UseAlarm -OSi_UseAlarm: ; 0x021D37BC - .space 0x4 - - .global OSi_AlarmQueue -OSi_AlarmQueue: ; 0x021D37C0 - .space 0x8 - - .text - - arm_func_start OSi_AlarmHandler -OSi_AlarmHandler: ; 0x020CCE00 - stmdb sp!, {r0,lr} - bl OSi_ArrangeTimer - ldmia sp!, {r0,lr} - bx lr - - arm_func_start OSi_ArrangeTimer -OSi_ArrangeTimer: ; 0x020CCE10 - stmdb sp!, {r4-r5,lr} - sub sp, sp, #0x4 - ldr r1, _020CCF1C ; =0x04000106 - mov r2, #0x0 - mov r0, #0x10 - strh r2, [r1, #0x0] - bl OS_DisableIrqMask - ldr r0, _020CCF20 ; =0x027E0000 - add r0, r0, #0x3000 - ldr r1, [r0, #0xff8] - orr r1, r1, #0x10 - str r1, [r0, #0xff8] - bl OS_GetTick - ldr r2, _020CCF24 ; =OSi_AlarmQueue - ldr r4, [r2, #0x0] - cmp r4, #0x0 - addeq sp, sp, #0x4 - ldmeqia sp!, {r4-r5,lr} - bxeq lr - ldr r3, [r4, #0x10] - ldr r12, [r4, #0xc] - cmp r1, r3 - cmpeq r0, r12 - bhs _020CCE84 - mov r0, r4 - bl OSi_SetTimer - add sp, sp, #0x4 - ldmia sp!, {r4-r5,lr} - bx lr -_020CCE84: - ldr r1, [r4, #0x18] - cmp r1, #0x0 - moveq r0, #0x0 - streq r0, [r2, #0x4] - str r1, [r2, #0x0] - movne r0, #0x0 - strne r0, [r1, #0x14] - ldr r2, [r4, #0x1c] - ldr r1, [r4, #0x20] - mov r0, #0x0 - cmp r1, r0 - ldr r5, [r4, #0x0] - cmpeq r2, r0 - streq r0, [r4, #0x0] - cmp r5, #0x0 - beq _020CCECC - ldr r0, [r4, #0x4] - blx r5 -_020CCECC: - ldr r2, [r4, #0x1c] - ldr r0, [r4, #0x20] - mov r1, #0x0 - cmp r0, r1 - cmpeq r2, r1 - beq _020CCEF4 - mov r0, r4 - mov r2, r1 - str r5, [r4, #0x0] - bl OSi_InsertAlarm -_020CCEF4: - ldr r0, _020CCF24 ; =OSi_AlarmQueue - ldr r0, [r0, #0x0] - cmp r0, #0x0 - addeq sp, sp, #0x4 - ldmeqia sp!, {r4-r5,lr} - bxeq lr - bl OSi_SetTimer - add sp, sp, #0x4 - ldmia sp!, {r4-r5,lr} - bx lr - .balign 4 -_020CCF1C: .word 0x04000106 -_020CCF20: .word 0x027E0000 -_020CCF24: .word OSi_AlarmQueue - - arm_func_start OS_CancelAlarm -OS_CancelAlarm: ; 0x020CCF28 - stmdb sp!, {r4-r5,lr} - sub sp, sp, #0x4 - mov r5, r0 - bl OS_DisableInterrupts - ldr r1, [r5, #0x0] - mov r4, r0 - cmp r1, #0x0 - bne _020CCF58 - bl OS_RestoreInterrupts - add sp, sp, #0x4 - ldmia sp!, {r4-r5,lr} - bx lr -_020CCF58: - ldr r0, [r5, #0x18] - cmp r0, #0x0 - ldreq r2, [r5, #0x14] - ldreq r1, _020CCFBC ; =OSi_AlarmQueue - streq r2, [r1, #0x4] - ldrne r1, [r5, #0x14] - strne r1, [r0, #0x14] - ldr r1, [r5, #0x14] - cmp r1, #0x0 - strne r0, [r1, #0x18] - bne _020CCF98 - ldr r1, _020CCFBC ; =OSi_AlarmQueue - cmp r0, #0x0 - str r0, [r1, #0x0] - beq _020CCF98 - bl OSi_SetTimer -_020CCF98: - mov r1, #0x0 - str r1, [r5, #0x0] - str r1, [r5, #0x1c] - mov r0, r4 - str r1, [r5, #0x20] - bl OS_RestoreInterrupts - add sp, sp, #0x4 - ldmia sp!, {r4-r5,lr} - bx lr - .balign 4 -_020CCFBC: .word OSi_AlarmQueue - - arm_func_start OS_SetAlarm -OS_SetAlarm: ; 0x020CCFC0 - stmdb sp!, {r4-r7,lr} - sub sp, sp, #0x4 - movs r6, r0 - mov r5, r1 - mov r4, r2 - mov r7, r3 - beq _020CCFE8 - ldr r0, [r6, #0x0] - cmp r0, #0x0 - beq _020CCFEC -_020CCFE8: - bl OS_Terminate -_020CCFEC: - bl OS_DisableInterrupts - mov r1, #0x0 - str r1, [r6, #0x1c] - str r1, [r6, #0x20] - str r7, [r6, #0x0] - ldr r1, [sp, #0x18] - mov r7, r0 - str r1, [r6, #0x4] - bl OS_GetTick - adds r3, r5, r0 - adc r2, r4, r1 - mov r0, r6 - mov r1, r3 - bl OSi_InsertAlarm - mov r0, r7 - bl OS_RestoreInterrupts - add sp, sp, #0x4 - ldmia sp!, {r4-r7,lr} - bx lr - - arm_func_start OSi_InsertAlarm -OSi_InsertAlarm: ; 0x020CD038 - stmdb sp!, {r4-r8,lr} - mov r8, r0 - ldr r4, [r8, #0x1c] - ldr r3, [r8, #0x20] - mov r0, #0x0 - cmp r3, r0 - mov r7, r1 - mov r6, r2 - cmpeq r4, r0 - beq _020CD0B4 - bl OS_GetTick - ldr r6, [r8, #0x28] - ldr r7, [r8, #0x24] - cmp r6, r1 - cmpeq r7, r0 - bhs _020CD0B4 - ldr r5, [r8, #0x1c] - ldr r4, [r8, #0x20] - subs r0, r0, r7 - mov r2, r5 - mov r3, r4 - sbc r1, r1, r6 - bl _ll_udiv - mov r2, #0x1 - adds r2, r0, r2 - adc r0, r1, #0x0 - umull r3, r1, r5, r2 - mla r1, r5, r0, r1 - mla r1, r4, r2, r1 - adds r7, r7, r3 - adc r6, r6, r1 -_020CD0B4: - str r7, [r8, #0xc] - ldr r0, _020CD174 ; =OSi_AlarmQueue - str r6, [r8, #0x10] - ldr r4, [r0, #0x0] - cmp r4, #0x0 - beq _020CD134 - mov r1, #0x0 -_020CD0D0: - ldr r2, [r4, #0xc] - ldr r0, [r4, #0x10] - subs r3, r7, r2 - sbc r2, r6, r0 - subs r0, r3, r1 - sbcs r0, r2, r1 - bge _020CD128 - ldr r0, [r4, #0x14] - str r0, [r8, #0x14] - str r8, [r4, #0x14] - str r4, [r8, #0x18] - ldr r0, [r8, #0x14] - cmp r0, #0x0 - strne r8, [r0, #0x18] - ldmneia sp!, {r4-r8,lr} - bxne lr - ldr r1, _020CD174 ; =OSi_AlarmQueue - mov r0, r8 - str r8, [r1, #0x0] - bl OSi_SetTimer - ldmia sp!, {r4-r8,lr} - bx lr -_020CD128: - ldr r4, [r4, #0x18] - cmp r4, #0x0 - bne _020CD0D0 -_020CD134: - ldr r1, _020CD174 ; =OSi_AlarmQueue - mov r0, #0x0 - str r0, [r8, #0x18] - ldr r0, [r1, #0x4] - str r8, [r1, #0x4] - str r0, [r8, #0x14] - cmp r0, #0x0 - strne r8, [r0, #0x18] - ldmneia sp!, {r4-r8,lr} - bxne lr - mov r0, r8 - str r8, [r1, #0x4] - str r8, [r1, #0x0] - bl OSi_SetTimer - ldmia sp!, {r4-r8,lr} - bx lr - .balign 4 -_020CD174: .word OSi_AlarmQueue - - arm_func_start OS_CreateAlarm -OS_CreateAlarm: ; 0x020CD178 - mov r1, #0x0 - str r1, [r0, #0x0] - str r1, [r0, #0x8] - bx lr - - arm_func_start OS_IsAlarmAvailable -OS_IsAlarmAvailable: ; 0x020CD188 - ldr r0, _020CD194 ; =OSi_UseAlarm - ldrh r0, [r0, #0x0] - bx lr - .balign 4 -_020CD194: .word OSi_UseAlarm - - arm_func_start OS_InitAlarm -OS_InitAlarm: ; 0x020CD198 - stmdb sp!, {lr} - sub sp, sp, #0x4 - ldr r1, _020CD1E8 ; =OSi_UseAlarm - ldrh r0, [r1, #0x0] - cmp r0, #0x0 - addne sp, sp, #0x4 - ldmneia sp!, {lr} - bxne lr - mov r0, #0x1 - strh r0, [r1, #0x0] - bl OSi_SetTimerReserved - ldr r1, _020CD1EC ; =OSi_AlarmQueue - mov r2, #0x0 - mov r0, #0x10 - str r2, [r1, #0x0] - str r2, [r1, #0x4] - bl OS_DisableIrqMask - add sp, sp, #0x4 - ldmia sp!, {lr} - bx lr - .balign 4 -_020CD1E8: .word OSi_UseAlarm -_020CD1EC: .word OSi_AlarmQueue - - arm_func_start OSi_SetTimer -OSi_SetTimer: ; 0x020CD1F0 - stmdb sp!, {r4-r5,lr} - sub sp, sp, #0x4 - mov r4, r0 - bl OS_GetTick - ldr r3, _020CD27C ; =0x04000106 - mov r2, #0x0 - strh r2, [r3, #0x0] - ldr r12, [r4, #0xc] - ldr r3, [r4, #0x10] - subs r5, r12, r0 - sbc r4, r3, r1 - ldr r1, _020CD280 ; =OSi_AlarmHandler - mov r0, #0x1 - bl OSi_EnterTimerCallback - mov r2, #0x0 - subs r0, r5, r2 - sbcs r0, r4, r2 - ldrlt r2, _020CD284 ; =0x0000FFFE - blt _020CD254 - mov r0, #0x10000 - subs r0, r5, r0 - sbcs r0, r4, r2 - mvnlt r0, r5 - movlt r0, r0, lsl #0x10 - movlt r2, r0, lsr #0x10 -_020CD254: - ldr r0, _020CD288 ; =0x04000104 - ldr r1, _020CD27C ; =0x04000106 - strh r2, [r0, #0x0] - mov r2, #0xc1 - mov r0, #0x10 - strh r2, [r1, #0x0] - bl OS_EnableIrqMask - add sp, sp, #0x4 - ldmia sp!, {r4-r5,lr} - bx lr - .balign 4 -_020CD27C: .word 0x04000106 -_020CD280: .word OSi_AlarmHandler -_020CD284: .word 0x0000FFFE -_020CD288: .word 0x04000104 diff --git a/arm9/lib/include/OS_alarm.h b/arm9/lib/include/OS_alarm.h index ebdf01ba..c8d0682d 100644 --- a/arm9/lib/include/OS_alarm.h +++ b/arm9/lib/include/OS_alarm.h @@ -6,8 +6,20 @@ #include "OS_tick.h" #include "nitro/OS_alarm_shared.h" -void OS_CancelAlarm(OSAlarm *alarm); +struct OSiAlarmQueue +{ + OSAlarm *head; + OSAlarm *tail; +}; + +static void OSi_SetTimer(OSAlarm *alarm); +void OS_InitAlarm(void); +BOOL OS_IsAlarmAvailable(void); void OS_CreateAlarm(OSAlarm *alarm); +static void OSi_InsertAlarm(OSAlarm *alarm, OSTick fire); void OS_SetAlarm(OSAlarm *alarm, OSTick tick, OSAlarmHandler handler, void *arg); +void OS_CancelAlarm(OSAlarm *alarm); +void OSi_AlarmHandler(void *arg); +static void OSi_ArrangeTimer(void); #endif //POKEDIAMOND_ARM9_OS_ALARM_H diff --git a/arm9/lib/include/OS_interrupt.h b/arm9/lib/include/OS_interrupt.h index a828c62e..d84cae00 100644 --- a/arm9/lib/include/OS_interrupt.h +++ b/arm9/lib/include/OS_interrupt.h @@ -5,6 +5,7 @@ #include "nitro/OS_interrupt_shared.h" #define OS_IE_TIMER0 (1UL << REG_OS_IE_T0_SHIFT) +#define OS_IE_TIMER1 (1UL << REG_OS_IE_T1_SHIFT) extern OSIrqFunction OS_IRQTable[]; extern OSIrqCallbackInfo OSi_IrqCallbackInfo[8]; diff --git a/arm9/lib/include/registers.h b/arm9/lib/include/registers.h index 75046308..37ca97e6 100644 --- a/arm9/lib/include/registers.h +++ b/arm9/lib/include/registers.h @@ -346,6 +346,7 @@ #define reg_CARD_DATA (*(REGType32v *)0x4100010) //? #define REG_OS_IE_T0_SHIFT 3 +#define REG_OS_IE_T1_SHIFT 4 #define REG_OS_TM0CNT_H_I_MASK 0x0040 #define REG_OS_TM0CNT_H_E_MASK 0x0080 diff --git a/arm9/lib/src/OS_alarm.c b/arm9/lib/src/OS_alarm.c new file mode 100644 index 00000000..1bd3ff2f --- /dev/null +++ b/arm9/lib/src/OS_alarm.c @@ -0,0 +1,250 @@ +#include "function_target.h" +#include "consts.h" +#include "OS_alarm.h" +#include "OS_interrupt.h" +#include "OS_irqTable.h" +#include "OS_terminate_proc.h" +#include "OS_system.h" + +static struct OSiAlarmQueue OSi_AlarmQueue; + +static u16 OSi_UseAlarm = FALSE; + +ARM_FUNC static void OSi_SetTimer(OSAlarm *alarm) +{ + OSTick tick = OS_GetTick(); + + OS_SetTimerControl(OS_TIMER_1, 0); + + s64 delta = (s64)(alarm->fire - tick); + + OSi_EnterTimerCallback(OS_TIMER_1, OSi_AlarmHandler, NULL); + + u16 timerCount; + if (delta < 0) + { + timerCount = (u16)~1; + } + else if (delta < 0x10000) + { + timerCount = (u16)(~delta); + } + else + { + timerCount = 0; + } + + OS_SetTimerCount((OSTimer)OS_TIMER_1, timerCount); + OS_SetTimerControl(OS_TIMER_1, (u16)OSi_TICK_TIMERCONTROL); + + (void)OS_EnableIrqMask(OS_IE_TIMER1); +} + +ARM_FUNC void OS_InitAlarm(void) +{ + if (!OSi_UseAlarm) + { + OSi_UseAlarm = TRUE; + + OSi_SetTimerReserved(OS_TIMER_1); + + OSi_AlarmQueue.head = NULL; + OSi_AlarmQueue.tail = NULL; + + (void)OS_DisableIrqMask(OS_IE_TIMER1); + } +} + +ARM_FUNC BOOL OS_IsAlarmAvailable(void) +{ + return OSi_UseAlarm; +} + +ARM_FUNC void OS_CreateAlarm(OSAlarm *alarm) +{ + alarm->handler = 0; + alarm->tag = 0; +} + +ARM_FUNC static void OSi_InsertAlarm(OSAlarm *alarm, OSTick fire) +{ + if (alarm->period > 0) + { + OSTick tick = OS_GetTick(); + + fire = alarm->start; + if (alarm->start < tick) + { + fire += alarm->period * ((tick - alarm->start) / alarm->period + 1); + } + } + + alarm->fire = fire; + + OSAlarm *prev; + OSAlarm *next; + + for (next = OSi_AlarmQueue.head; next; next = next->next) + { + if ((s64)(fire - next->fire) >= 0) + { + continue; + } + + alarm->prev = next->prev; + next->prev = alarm; + alarm->next = next; + prev = alarm->prev; + if (prev) + { + prev->next = alarm; + } + else + { + OSi_AlarmQueue.head = alarm; + OSi_SetTimer(alarm); + } + + return; + } + + alarm->next = 0; + prev = OSi_AlarmQueue.tail; + OSi_AlarmQueue.tail = alarm; + alarm->prev = prev; + if (prev) + { + prev->next = alarm; + } + else + { + OSi_AlarmQueue.head = OSi_AlarmQueue.tail = alarm; + OSi_SetTimer(alarm); + } +} + +ARM_FUNC void OS_SetAlarm(OSAlarm * alarm, OSTick tick, OSAlarmHandler handler, void *arg) +{ + if (!alarm || alarm->handler) + { + OS_Terminate(); + } + + OSIntrMode enabled = OS_DisableInterrupts(); + + alarm->period = 0; + + alarm->handler = handler; + alarm->arg = arg; + + OSi_InsertAlarm(alarm, OS_GetTick() + tick); + + (void)OS_RestoreInterrupts(enabled); +} + +ARM_FUNC void OS_CancelAlarm(OSAlarm *alarm) +{ + OSIntrMode enabled = OS_DisableInterrupts(); + + if (!alarm->handler) + { + (void)OS_RestoreInterrupts(enabled); + return; + } + + OSAlarm *next = alarm->next; + + if (!next) + { + OSi_AlarmQueue.tail = alarm->prev; + } + else + { + next->prev = alarm->prev; + } + + if (alarm->prev) + { + alarm->prev->next = next; + } + else + { + OSi_AlarmQueue.head = next; + if (next) + { + OSi_SetTimer(next); + } + } + + alarm->handler = NULL; + alarm->period = 0; + + (void)OS_RestoreInterrupts(enabled); +} + +ARM_FUNC asm void OSi_AlarmHandler(void *arg) +{ + stmfd sp!, {r0, lr} + bl OSi_ArrangeTimer + ldmfd sp!, {r0, lr} + bx lr +} + +ARM_FUNC static void OSi_ArrangeTimer(void) +{ + OS_SetTimerControl(OS_TIMER_1, 0); + + (void)OS_DisableIrqMask(OS_IE_TIMER1); + + OS_SetIrqCheckFlag(OS_IE_TIMER1); + + OSTick tick = OS_GetTick(); + + OSAlarm *alarm = OSi_AlarmQueue.head; + + if (!alarm) + { + return; + } + + if (tick < alarm->fire) + { + OSi_SetTimer(alarm); + return; + } + + OSAlarm *next = alarm->next; + OSi_AlarmQueue.head = next; + + if (!next) + { + OSi_AlarmQueue.tail = NULL; + } + else + { + next->prev = NULL; + } + + OSAlarmHandler handler = alarm->handler; + + if (!alarm->period) + { + alarm->handler = NULL; + } + + if (handler) + { + (handler)(alarm->arg); + } + + if (alarm->period > 0) + { + alarm->handler = handler; + OSi_InsertAlarm(alarm, 0); + } + + if (OSi_AlarmQueue.head) + { + OSi_SetTimer(OSi_AlarmQueue.head); + } +} |