Skip to content

Commit

Permalink
Rework EE timer to more closely match official behavior
Browse files Browse the repository at this point in the history
  • Loading branch information
uyjulian committed Dec 26, 2023
1 parent c28c917 commit dcbc279
Show file tree
Hide file tree
Showing 15 changed files with 1,261 additions and 455 deletions.
58 changes: 54 additions & 4 deletions ee/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,55 @@ EXIT_OBJS += _exit_internals.o SetArg.o Exit.o ExecPS2.o LoadExecPS2.o ExecOSD.o

### Timer objects

TIMER_OBJS = __time_internals.o StartTimerSystemTime.o StopTimerSystemTime.o iGetTimerSystemTime.o GetTimerSystemTime.o cpu_ticks.o
TIMER_ALARM_OBJS = TimerAlarmInternals.o __Timer2Resched.o InitTimerAlarm.o DeinitTimerAlarm.o InitializeTimerAlarm.o \
iStopTimerAlarm.o StopTimerAlarm.o iStartTimerAlarm.o StartTimerAlarm.o SetTimerAlarm.o ThreadWaitClock.o
TIMER_OBJS = \
timer_data.o \
SetT2.o \
SetT2_COUNT.o \
SetT2_MODE.o \
SetT2_COMP.o \
InitTimer.o \
EndTimer.o \
GetTimerPreScaleFactor.o \
StartTimerSystemTime.o \
StopTimerSystemTime.o \
SetNextComp.o \
InsertAlarm_ForTimer.o \
UnlinkAlarm_ForTimer.o \
TimerHandler_callback.o \
iGetTimerSystemTime.o \
GetTimerSystemTime.o \
iAllocTimerCounter.o \
AllocTimerCounter.o \
iFreeTimerCounter.o \
FreeTimerCounter.o \
iGetTimerUsedUnusedCounters.o \
GetTimerUsedUnusedCounters.o \
iStartTimerCounter.o \
StartTimerCounter.o \
iStopTimerCounter.o \
StopTimerCounter.o \
SetTimerCount.o \
iGetTimerBaseTime.o \
GetTimerBaseTime.o \
iGetTimerCount.o \
GetTimerCount.o \
iSetTimerHandler.o \
SetTimerHandler.o \
TimerBusClock2USec.o \
TimerUSec2BusClock.o \
TimerBusClock2Freq.o \
TimerFreq2BusClock.o \
cpu_ticks.o
TIMER_ALARM_OBJS = \
alarm_data.o \
ForTimer_InitAlarm.o \
AlarmHandler.o \
iSetTimerAlarm.o \
SetTimerAlarm.o \
iReleaseTimerAlarm.o \
ReleaseTimerAlarm.o
DELAYTHREAD_OBJS = \
DelayThread.o

### Getter objects

Expand Down Expand Up @@ -155,7 +201,7 @@ KERNEL_OBJS = ResetEE.o SetGsCrt.o $(EXEC_SYSCALLS) \

EE_OBJS = $(KERNEL_OBJS) $(SIFCMD_OBJS) $(SIFRPC_OBJS) $(FILEIO_OBJS) \
$(LOADFILE_OBJS) $(IOPHEAP_OBJS) $(IOPCONTROL_OBJS) $(ROM0_OBJS) $(CONFIG_OBJS) \
$(GLUE_OBJS) $(SIO_OBJS) $(TIMER_OBJS) $(TIMER_ALARM_OBJS) $(GETKERNEL_OBJS) \
$(GLUE_OBJS) $(SIO_OBJS) $(TIMER_OBJS) $(TIMER_ALARM_OBJS) $(DELAYTHREAD_OBJS) $(GETKERNEL_OBJS) \
$(INITSYS_OBJS) $(KERNEL_UTIL_OBJS) erl-support.o


Expand Down Expand Up @@ -202,6 +248,10 @@ $(TIMER_ALARM_OBJS:%=$(EE_OBJS_DIR)%): $(EE_SRC_DIR)timer_alarm.c
$(DIR_GUARD)
$(EE_C_COMPILE) -DF_$(*:$(EE_OBJS_DIR)%=%) $< -c -o $@

$(DELAYTHREAD_OBJS:%=$(EE_OBJS_DIR)%): $(EE_SRC_DIR)delaythread.c
$(DIR_GUARD)
$(EE_C_COMPILE) -DF_$(*:$(EE_OBJS_DIR)%=%) $< -c -o $@

$(GETKERNEL_OBJS:%=$(EE_OBJS_DIR)%): $(EE_SRC_DIR)getkernel.c
$(DIR_GUARD)
$(EE_C_COMPILE) -DF_$(*:$(EE_OBJS_DIR)%=%) $< -c -o $@
Expand Down
20 changes: 20 additions & 0 deletions ee/kernel/include/delaythread.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
# _____ ___ ____ ___ ____
# ____| | ____| | | |____|
# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
#-----------------------------------------------------------------------
# Copyright 2023, ps2dev - http://www.ps2dev.org
# Licenced under Academic Free License version 2.0
# Review ps2sdk README & LICENSE files for further details.
*/

#ifndef __DELAYTHREAD_H__
#define __DELAYTHREAD_H__

#include <tamtypes.h>
#include <timer.h>

extern s32 DelayThread(s32 microseconds);

#endif

9 changes: 5 additions & 4 deletions ee/kernel/include/kernel.h
Original file line number Diff line number Diff line change
Expand Up @@ -532,12 +532,13 @@ void *GetEntryAddress(int syscall);
void ExecOSD(int num_args, char *args[]) { _ExecOSD(num_args, args); }

#define DISABLE_TimerSystemTime() \
void StartTimerSystemTime(void) {} \
void StopTimerSystemTime(void) {}
s32 InitTimer(s32 in_mode) {(void)in_mode; return 0;} \
s32 EndTimer(void) {return 0;} \
s32 StartTimerSystemTime(void) {return 0;} \
s32 StopTimerSystemTime(void) {return 0;}

#define DISABLE_TimerAlarm() \
void InitTimerAlarm(void) {} \
void DeinitTimerAlarm(void) {}
void ForTimer_InitAlarm(void) {}

#define DISABLE_PATCHED_ALARMS() \
void InitAlarm(void) {}
Expand Down
56 changes: 51 additions & 5 deletions ee/kernel/include/timer.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,61 @@
#define kHBLNK_DTV480p (31469)
#define kHBLNK_DTV1080i (33750)

typedef u64 (*timer_alarm_handler_t)(s32 id, u64 scheduled_time, u64 actual_time, void *arg, void *pc_value);

#ifdef __cplusplus
extern "C" {
#endif

void StartTimerSystemTime(void);
void StopTimerSystemTime(void);
u64 GetTimerSystemTime(void);
u64 iGetTimerSystemTime(void);
u32 cpu_ticks(void);
extern s32 InitTimer(s32 in_mode);
extern s32 EndTimer(void);
extern s32 GetTimerPreScaleFactor(void);
extern s32 StartTimerSystemTime(void);
extern s32 StopTimerSystemTime(void);
extern void SetNextComp(u64 time);
extern u64 iGetTimerSystemTime(void);
extern u64 GetTimerSystemTime(void);
extern s32 iAllocTimerCounter(void);
extern s32 AllocTimerCounter(void);
extern s32 iFreeTimerCounter(s32 id);
extern s32 FreeTimerCounter(s32 id);
extern s32 iGetTimerUsedUnusedCounters(u32 *used_counters, u32 *unused_counters);
extern s32 GetTimerUsedUnusedCounters(u32 *used_counters, u32 *unused_counters);
extern s32 iStartTimerCounter(s32 id);
extern s32 StartTimerCounter(s32 id);
extern s32 iStopTimerCounter(s32 id);
extern s32 StopTimerCounter(s32 id);
extern u64 SetTimerCount(s32 id, u64 timer_count);
extern u64 iGetTimerBaseTime(s32 id);
extern u64 GetTimerBaseTime(s32 id);
extern u64 iGetTimerCount(s32 id);
extern u64 GetTimerCount(s32 id);
extern s32 iSetTimerHandler(s32 id, u64 scheduled_time, timer_alarm_handler_t callback_handler, void *arg);
extern s32 SetTimerHandler(s32 id, u64 scheduled_time, timer_alarm_handler_t callback_handler, void *arg);
extern void TimerBusClock2USec(u64 clocks, u32 *seconds_result, u32 *microseconds_result);
extern u64 TimerUSec2BusClock(u32 seconds, u32 microseconds);
extern float TimerBusClock2Freq(s64 clocks);
extern u64 TimerFreq2BusClock(float timer_frequency);
extern u32 cpu_ticks(void);

// Additional conversion functions, from time to bus cycles
static inline u64 NSec2TimerBusClock(u64 usec) {
// Approximate, avoid 64 bit division
return ((((kBUSCLK / 1000) * 65536ULL) / 1000000) * usec) >> 16;
}

static inline u64 USec2TimerBusClock(u64 usec) {
// Approximate, avoid 64 bit division
return ((((kBUSCLK / 1000) * 1024) / 1000) * usec) >> 10;
}

static inline u64 MSec2TimerBusClock(u64 msec) {
return (kBUSCLK / 1000) * msec;
}

static inline u64 Sec2TimerBusClock(u64 sec) {
return kBUSCLK * sec;
}

#ifdef __cplusplus
}
Expand Down
66 changes: 6 additions & 60 deletions ee/kernel/include/timer_alarm.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# ____| | ____| | | |____|
# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
#-----------------------------------------------------------------------
# Copyright 2022, ps2dev - http://www.ps2dev.org
# Copyright ps2dev - http://www.ps2dev.org
# Licenced under Academic Free License version 2.0
# Review ps2sdk README & LICENSE files for further details.
*/
Expand All @@ -14,65 +14,11 @@
#include <tamtypes.h>
#include <timer.h>

struct timer_alarm_t;
typedef void (*timer_alarm_callback_t)(struct timer_alarm_t *alarm, void *arg);

// Defines an alarm object
// Do not manipulate fields directly, but through functions.

struct timer_alarm_t {
u64 scheduled_time; // Clock tick when the alarm should be triggered
u64 timer_cycles; // Alarm period in clock ticks
struct timer_alarm_t *prev, *next; // Previous and next alarm in the sorted event list
timer_alarm_callback_t callback; // User callback to call during the IRQ
void *usr_arg;
};

// Init/Deinit functions
void InitTimerAlarm();
void DeinitTimerAlarm();

// Allocate a timer-based alarm
void InitializeTimerAlarm(struct timer_alarm_t *alarm);
// Sets up an alarm (with a user callback function and argument) that triggers some cycles in the future.
void SetTimerAlarm(struct timer_alarm_t *alarm, u64 clock_cycles, timer_alarm_callback_t user_callback, void *user_arg);
// Starts/Enables the alarm.
void iStartTimerAlarm(struct timer_alarm_t *alarm);
void StartTimerAlarm(struct timer_alarm_t *alarm);
// Stops/Disabled the alarm.
void iStopTimerAlarm(struct timer_alarm_t *alarm);
void StopTimerAlarm(struct timer_alarm_t *alarm);
// Sleeping function
void ThreadWaitClock(u64 clock_cycles);

// Conversion functions, from time to bus cycles
static inline u64 NSec2TimerBusClock(u64 usec) {
// Approximate, avoid 64 bit division
return ((((kBUSCLK / 1000) * 65536ULL) / 1000000) * usec) >> 16;
}

static inline u64 USec2TimerBusClock(u64 usec) {
// Approximate, avoid 64 bit division
return ((((kBUSCLK / 1000) * 1024) / 1000) * usec) >> 10;
}

static inline u64 MSec2TimerBusClock(u64 msec) {
return (kBUSCLK / 1000) * msec;
}

static inline u64 Sec2TimerBusClock(u64 sec) {
return kBUSCLK * sec;
}

static inline void TimerBusClock2USec (u64 ulClock, u32 *pSec, u32 *pUsec) {
u64 sec = ulClock/kBUSCLK;
*pSec = (u32)sec;
*pUsec = (1000000 * (ulClock - (sec * kBUSCLK))) / kBUSCLK;
}

static inline u64 TimerUSec2BusClock (u32 sec, u32 usec) {
return Sec2TimerBusClock(sec) + USec2TimerBusClock(usec);
}
extern u64 AlarmHandler(s32 alarm_id, u64 scheduled_time, u64 actual_time, void *arg, void *last_pc);
extern s32 iSetTimerAlarm(u64 clock_cycles, timer_alarm_handler_t callback_handler, void *arg);
extern s32 SetTimerAlarm(u64 clock_cycles, timer_alarm_handler_t callback_handler, void *arg);
extern s32 iReleaseTimerAlarm(s32 id);
extern s32 ReleaseTimerAlarm(s32 id);

#endif

28 changes: 14 additions & 14 deletions ee/kernel/samples/timer_alarm/test_alarm.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,32 +15,32 @@
#include <timer.h>
#include <timer_alarm.h>

int flag = 0, flag2 = 0;
int flag = 2, flag2 = 2;

void usercb(struct timer_alarm_t *alarm, void *arg) {
static u64 usercb(s32 id, u64 scheduled_time, u64 actual_time, void *arg, void *pc_value)
{
*(int*)arg = 1;
// The alarm does not trigger again unless we re-enable it manually
iStartTimerAlarm(alarm);
return 0;
}

int main(int argc, char *argv[])
{
struct timer_alarm_t alarm, alarm2;
InitializeTimerAlarm(&alarm);
InitializeTimerAlarm(&alarm2);
SetTimerAlarm(&alarm, Sec2TimerBusClock(2), &usercb, &flag);
SetTimerAlarm(&alarm2, MSec2TimerBusClock(1414), &usercb, &flag2);
StartTimerAlarm(&alarm);
StartTimerAlarm(&alarm2);

while (1) {
if (flag) {
printf("Hello there, 2 second tick!\n");
if (flag != 2)
{
printf("Hello there, 2 second tick!\n");
}
flag = 0;
SetTimerAlarm(Sec2TimerBusClock(2), &usercb, &flag);
}
if (flag2) {
printf("Hello there, sqrt(2) second tick!\n");
if (flag2 != 2)
{
printf("Hello there, sqrt(2) second tick!\n");
}
flag2 = 0;
SetTimerAlarm(MSec2TimerBusClock(1414), &usercb, &flag2);
}
}

Expand Down
5 changes: 2 additions & 3 deletions ee/kernel/samples/timer_alarm_sleep/test_alarm_sleep.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,14 @@
#include <kernel.h>
#include <stdlib.h>
#include <stdio.h>
#include <timer.h>
#include <timer_alarm.h>
#include <delaythread.h>

volatile int flag = 0;

int main(int argc, char *argv[])
{
while (1) {
ThreadWaitClock(MSec2TimerBusClock(350));
DelayThread(350 * 1000);
printf("Hello there, 350ms tick!\n");
}

Expand Down
38 changes: 19 additions & 19 deletions ee/kernel/samples/timer_alarm_stop/test_alarm_stop.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,38 +15,38 @@
#include <timer.h>
#include <timer_alarm.h>

struct timer_alarm_t alarm, alarm2;
int flag = 0, flag2 = 0;
volatile s32 alarm1 = -1, alarm2 = -1;
int flag = 2, flag2 = 2;

void usercb1(struct timer_alarm_t *trigalarm, void *arg) {
static u64 usercb(s32 id, u64 scheduled_time, u64 actual_time, void *arg, void *pc_value) {
*(int*)arg = 1;
iStartTimerAlarm(trigalarm);
}

void usercb2(struct timer_alarm_t *trigalarm, void *arg) {
*(int*)arg = 1;
iStartTimerAlarm(trigalarm);
// Disable the 2s alarm
iStopTimerAlarm(&alarm);
if (alarm2 == id)
{
iReleaseTimerAlarm(alarm1);
alarm1 = -1;
}
return 0;
}

int main(int argc, char *argv[])
{
InitializeTimerAlarm(&alarm);
InitializeTimerAlarm(&alarm2);
SetTimerAlarm(&alarm, Sec2TimerBusClock(2), &usercb1, &flag);
SetTimerAlarm(&alarm2, Sec2TimerBusClock(5), &usercb2, &flag2);
StartTimerAlarm(&alarm);
StartTimerAlarm(&alarm2);

while (1) {
if (flag) {
printf("2s alarm triggered!\n");
if (flag != 2)
{
printf("2s alarm triggered!\n");
}
flag = 0;
alarm1 = SetTimerAlarm(Sec2TimerBusClock(2), &usercb, &flag);
}
if (flag2) {
printf("5s alarm triggered!\n");
if (flag2 != 2)
{
printf("5s alarm triggered!\n");
}
flag2 = 0;
alarm2 = SetTimerAlarm(Sec2TimerBusClock(5), &usercb, &flag2);
}
}

Expand Down
Loading

0 comments on commit dcbc279

Please sign in to comment.