Hardware Timers: Difference between revisions
(Created page with "The PSVita system embeds 8 Word timers (<code>SceWT0</code> to <code>SceWT7</code>) and 6 Longrange timers (<code>SceLT0</code> to <code>SceLT5</code>). The timers are counter...") |
(Change description of some fields in timers structure, change wording of cfg register) |
||
Line 48: | Line 48: | ||
<source lang="C"> | <source lang="C"> | ||
typedef volatile _SceWordTimer { | typedef volatile _SceWordTimer { | ||
SceUInt32 unk0; // | SceUInt32 unk0; // Value at which an interrupt is triggered? | ||
SceUInt32 unk4; // | SceUInt32 unk4; // Current value of the timer counter? | ||
SceUInt32 unk8; // Configuration register? | SceUInt32 unk8; // Configuration register? | ||
SceUInt32 unkC; | SceUInt32 unkC; // Another counter? | ||
SceUInt32 unk10; | SceUInt32 unk10; // Unused? | ||
SceUInt32 unk14; // Write 0x3 to clear interrupt? | SceUInt32 unk14; // Write 0x3 to clear interrupt? | ||
// Unused? | |||
SceUInt32 unk18; | SceUInt32 unk18; | ||
SceUInt32 unk1C; | SceUInt32 unk1C; | ||
Line 65: | Line 67: | ||
<source lang="C"> | <source lang="C"> | ||
typedef volatile _SceLongTimer { | typedef volatile _SceLongTimer { | ||
SceKernelSysClock unk0; // Current value of the timer counter? | SceKernelSysClock unk0; // Current value of the timer counter? | ||
SceKernelSysClock | SceKernelSysClock unk8; // Value at which an interrupt is triggered? | ||
SceKernelSysClock unk10; | SceKernelSysClock unk10; // Another counter? | ||
SceUInt32 unk18; // Write 0x3 to clear interrupts? | SceUInt32 unk18; // Write 0x3 to clear interrupts? | ||
SceUInt32 unk1C; // Configuration register? | SceUInt32 unk1C; // Configuration register? | ||
SceUInt32 unk20; | SceUInt32 unk20; // Unused | ||
} SceLongTimer; | } SceLongTimer; | ||
</source> | </source> | ||
Line 96: | Line 98: | ||
TODO | TODO | ||
Bit 0x1 | Bit 0x1 seems to be the "enable" bit |
Revision as of 22:13, 11 July 2022
The PSVita system embeds 8 Word timers (SceWT0
to SceWT7
) and 6 Longrange timers (SceLT0
to SceLT5
). The timers are counters incremented every ?microsecond?, can generate an interrupt when a certain value is reached or simply increase forever.
Most timers are managed by SceSystimer.
Available timers
The Address
column indicates the physical address at which the interface for a timer is located.
Each timer interface takes 0x1000 bytes.
Name | Address | Interrupt ID | Usage |
---|---|---|---|
SceLT0 / SceSystimerLongrangeTimer0 | 0xE20B1000 | 0x88 | Available for SceSystimer |
SceLT1 / SceSystimerLongrangeTimer1 | 0xE20B2000 | 0x89 | Available for SceSystimer |
SceLT2 / SceSystimerLongrangeTimer2 | 0xE20B3000 | 0x8A | Available for SceSystimer |
SceLT3 / SceSystimerLongrangeTimer3 | 0xE20B4000 | 0x8B | Available for SceSystimer |
SceLT4 / SceSystimerLongrangeTimer4 | 0xE20B5000 | 0x8C | Available for SceSystimer |
SceLT5 | 0xE20B6000 | 0x8D | Used by SceKernelThreadMgr as CPU timer |
SceWT0 / SceSystimerWordTimer0 | 0xE20B7000 | 0x80 | Available for SceSystimer |
SceWT1 / SceSystimerWordTimer1 | 0xE20B8000 | 0x81 | Available for SceSystimer |
SceWT2 / SceSystimerWordTimer2 | 0xE20B9000 | 0x82 | Available for SceSystimer |
SceWT3 / SceSystimerWordTimer3 | 0xE20BA000 | 0x83 | Available for SceSystimer |
SceWT4 / SceSystimerWordTimer4 | 0xE20BB000 | 0x84 | Available for SceSystimer |
SceWT5 / SceSystimerWordTimer5 | 0xE20BC000 | 0x85 | Available for SceSystimer |
SceWT6 / SceSystimerWordTimer6 | 0xE20BD000 | 0x86 | Available for SceSystimer |
SceWT7 / SceTimerForUsleep | 0xE20BE000 | 0x87 | Used by Tzs SceKernelIntrMgr for usleep - ?may be accessible in Secure state only? |
Word Timers
Timers with 32-bit counters.
typedef volatile _SceWordTimer { SceUInt32 unk0; // Value at which an interrupt is triggered? SceUInt32 unk4; // Current value of the timer counter? SceUInt32 unk8; // Configuration register? SceUInt32 unkC; // Another counter? SceUInt32 unk10; // Unused? SceUInt32 unk14; // Write 0x3 to clear interrupt? // Unused? SceUInt32 unk18; SceUInt32 unk1C; SceUInt32 unk20; } SceWordTimer;
Long Timers
Timers with 64-bit counters.
typedef volatile _SceLongTimer { SceKernelSysClock unk0; // Current value of the timer counter? SceKernelSysClock unk8; // Value at which an interrupt is triggered? SceKernelSysClock unk10; // Another counter? SceUInt32 unk18; // Write 0x3 to clear interrupts? SceUInt32 unk1C; // Configuration register? SceUInt32 unk20; // Unused } SceLongTimer;
NOTE: on the PSVita CPU, 64-bit accesses are not guaranteed to be atomic. This can lead to issues when reading the timer if the low word of a counter is about to overflow. To ensure the readings from a timer are accurate, use code similar to the following code:
//Return value should hopefully be optimized into registers SceKernelSysClock readCounter(volatile SceKernelSysClock* pTimerCounter) { SceKernelSysClock ctr; SceUInt32 ctrHi; do { ctr.hi = pTimeCounter->hi; //Read high word first ctr.lo = pTimeCounter->lo; //Read low word next ctrHi = pTimeCounter->hi; //Read high word again to make sure no overflow happened } while (timerVal.hi != timerValHi); //Try again if high word changed while reading low word return ctr; }
Configuration register
TODO
Bit 0x1 seems to be the "enable" bit