Difference between revisions of "Hardware Timers"

From Vita Development Wiki
Jump to navigation Jump to search
(Add timer frequency estimates based on testing, change timers description, change some names in the timer's struct)
(Change "fixed" to "configurable" for time interval, add frequency estimates, add WT5 config)
Line 1: Line 1:
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 consist of a counter that gets incremented at a fixed time interval, and can generate an interrupt when a certain value is reached.
+
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 consist of a counter that gets incremented at a configurable time interval (multiple of a base frequency?), and can generate an interrupt when a certain value is reached.
  
 
Most timers are managed by [[SceSystimer]].
 
Most timers are managed by [[SceSystimer]].
Line 45: Line 45:
 
== Word Timers ==
 
== Word Timers ==
  
Timers with 32-bit counters, incremented at an unknown frequency (seems to be in the order of ns).
+
Timers with 32-bit counters, unknown base frequency (seems to be in the order of ns).
 
<source lang="C">
 
<source lang="C">
 
typedef volatile _SceWordTimer {
 
typedef volatile _SceWordTimer {
Line 59: Line 59:
 
== Long Timers ==
 
== Long Timers ==
  
Timers with 64-bit counters. SceLT5 timer is incremented every microsecond (1MHz frequency).
+
Timers with 64-bit counters, unknown base frequency (seems to be in the order of ns). SceLT5 timer is incremented every microsecond (1MHz frequency).
 
<source lang="C">
 
<source lang="C">
 
typedef volatile _SceLongTimer {
 
typedef volatile _SceLongTimer {
Line 97: Line 97:
 
! Timer !! Value !! Behaviour/notes
 
! Timer !! Value !! Behaviour/notes
 
|-
 
|-
| SceLT5 || 0x2F34500D || Interrupt fired when counter reaches threshold
+
| SceWT7 || 0xDD00000D || ~1MHz frequency, interrupt fired when counter reached threshold
 +
|-
 +
| SceLT5 || 0x2F34500D || 1MHz frequency, interrupt fired when counter reaches threshold
 
|-
 
|-
 
|}
 
|}
Line 122: Line 124:
 
| 0x000F0000 || ? ||
 
| 0x000F0000 || ? ||
 
|-
 
|-
| 0x00F00000 || ? ||
+
| 0x00F00000 || ? || Related to frequency scaling
 
|-
 
|-
| 0xFF000000 || ? ||
+
| 0xFF000000 || ? || Related to frequency scaling
 
|}
 
|}

Revision as of 11:24, 15 July 2022

The PSVita system embeds 8 Word timers (SceWT0 to SceWT7) and 6 Longrange timers (SceLT0 to SceLT5). The timers consist of a counter that gets incremented at a configurable time interval (multiple of a base frequency?), and can generate an interrupt when a certain value is reached.

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.

List of timers
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, unknown base frequency (seems to be in the order of ns).

typedef volatile _SceWordTimer {
    SceUInt32 unk0; // Value at which an interrupt is triggered?
    SceUInt32 current; // Current value of the timer's counter
    SceUInt32 cfg; // Configuration register
    SceUInt32 unkC; // Another counter?
    SceUInt32 unk10; // Unused?
    SceUInt32 unk14; // Interrupt status? Write 0x3 to clear pending IRQ?
} SceWordTimer;

Long Timers

Timers with 64-bit counters, unknown base frequency (seems to be in the order of ns). SceLT5 timer is incremented every microsecond (1MHz frequency).

typedef volatile _SceLongTimer {
    SceKernelSysClock current;  // Current value of the timer counter
    SceKernelSysClock unk8;  // Value at which an interrupt is triggered?
    SceKernelSysClock unk10; // Another counter?
    SceUInt32 unk18; // Interrupt status? Write 0x3 to clear pending IRQ?
    SceUInt32 cfg; // Configuration register
} 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

The configuration register bit mappings seems to be identical for Word and Long timers.

Known values
Timer Value Behaviour/notes
SceWT7 0xDD00000D ~1MHz frequency, interrupt fired when counter reached threshold
SceLT5 0x2F34500D 1MHz frequency, interrupt fired when counter reaches threshold
Configuration register bit mappings
Mask Effect Notes
0x00000001 Counting enable 0x0 = timer stopped, 0x1 = timer counting
0x0000000E ?
0x00000070 ? ?Mode select?
0x00000080 ?
0x00000700 ?
0x00000800 ? Unused?
0x0000F000 ?
0x000F0000 ?
0x00F00000 ? Related to frequency scaling
0xFF000000 ? Related to frequency scaling