 |
forums.ps2dev.org Homebrew PS2, PSP & PS3 Development Discussions
|
| View previous topic :: View next topic |
| Author |
Message |
urchin
Joined: 02 Jun 2005 Posts: 121
|
Posted: Tue May 09, 2006 4:58 pm Post subject: Interrupts and Timers |
|
|
PSP_VBLANK_INT
The vblank interrupt triggers every 1/60 second. Using the following function:
| Code: | | int sceKernelRegisterSubIntrHandler(int intno, int no, void *handler, void *arg); |
up to 16 individual subinterrupt handlers may be installed for the vblank interrupt (intno = PSP_VBLANK_INT, no = 0 - 15). The prototype for vblank handler functions is:
| Code: | | void vblank_handler(int sub, void* arg); |
where "sub" is the subinterrupt number and "arg" is the arg parameter passed in during the register function. Registering more than one subinterrupt handler is probably not very useful for vblank, but may be useful for others. Before calling QueryIntrHandlerInfo, the PspIntrHandlerOptionParam "size" field must be initialised with sizeof(PspIntrHandlerOptionParam). Calling the function yields the following info:
| Code: | enabled = 0 / 1 -> disabled / enabled
calls = number of times handler has been called since registration
intr_code = interrupt number, e.g. 0x1e = PSP_VBLANK_INT
common = "common" parameter pass during handler registration
entry = handler function pointer
intr_level = 3 (?) |
Attempting to register PSP_VBLANK_INT with subinterrupt PSP_DISPLAY_SUBINT results in failure (as PSP_DISPLAY_SUBINT > 15), suggesting that the PspSubInterrupts enum or my use of it may be incorrect.
PSP_SYSTIMER(N)_INT
Calls to register or enable on these interrupts always yield 0x80020065 (illegal intr code), which seems plausible if they are system interrupts. QueryIntrHandlerInfo yields the following interesting information:
| Code: | min_clock_low = 0xFFFFFFFF
min_clock_hi = 0xFFFFFFFF
max_clock_low = 0x00000000
max_clock_hi = 0x00000000
enabled = always 0
gp = 0x88052FB0
entry = 0x8804A4E2
common = 0x8804AF30 for timer #0, (#1 -> AF50, #2 -> AF70, #3 -> AF90) |
The "entry" and "common" addresses appear to map into the "SysTimerForKernel" module, but not to any of the known functions.
VTimers
VTimers are configurable virtual timers that are called from system interrupts, possibly PSP_SYSTIMER(N)_INT. sceKernelCreateVTimer returns the UID of a new timer. I managed to create 1300 timers before my PSP asploded, but I didn't try to use them all. The upper limit may be imposed by the size of the UID table. Timer resolution is in microseconds and calling sceKernelGetVTimerTime before the timer has started returns 0. Each timer can be started using the sceKernelStartVTimer using the UID returned from sceKernelCreateVTimer.
The sceKernelSetVTimerHandler function is used to register a handler with the timer. In user mode, simply pass in the address of the function. When called from kernel mode, the handler seems to be required to reside in kernel space (> 0x80000000) otherwise registration fails with a return code of 0x800200D3 (illegal address). Adding 0x80000000 to the address of the handler seems to work well. Kernel mode can be detected by checking the "attr" field of the current thread's info struct.
When registering the timer, the "time" parameter indicates the period before the handler is triggered (assuming the timer is started from zero)
The handler prototype is:
| Code: | | SceUInt vtimer_handler(SceUID uid, SceKernelSysClock* requested, SceKernelSysClock* actual, void* common); |
where "uid" is UID of the timer, "requested" is the requested callback time, "actual" is the actual time it was called (e.g. requested may be 1000, but actual 1015) and "common" is the common parameter passed in during handler registration. Set the return code of the handler to the period desired before the handler is called again. If set to 0, the handler will not be called. Note that the handler is called from an interrupt, so thread related functions and others such as printf may not be used.
btw, this research was sponsored by psplink :) |
|
| Back to top |
|
 |
kasikeeper
Joined: 29 Nov 2007 Posts: 36
|
Posted: Wed Mar 05, 2008 7:33 am Post subject: |
|
|
Hi,
I tried out the code outline given above and the timer interrupts work just fine. However as you said already ...
| Quote: | | Note that the handler is called from an interrupt, so thread related functions and others such as printf may not be used. |
... some fancier stuff like putting up a psp message dialog box do not work inside my callback function. Do you know what is required to make that possible. I guess some kind of a thread maybe but I am unsure.
Kai |
|
| Back to top |
|
 |
hlide
Joined: 10 Sep 2006 Posts: 750
|
Posted: Wed Mar 05, 2008 9:20 am Post subject: |
|
|
| kasikeeper wrote: | Hi,
I tried out the code outline given above and the timer interrupts work just fine. However as you said already ...
| Quote: | | Note that the handler is called from an interrupt, so thread related functions and others such as printf may not be used. |
... some fancier stuff like putting up a psp message dialog box do not work inside my callback function. Do you know what is required to make that possible. I guess some kind of a thread maybe but I am unsure.
Kai |
you shouldn't use any blocking functions (functions that can switch thread) in a callback. If you need so, you must create a thread and an event (or a semaphore, a messagebox, etc.). Your thread just needs to wait for this event to run your blocking functions in a loop. Your callback just sets an event to wakeup this thread. |
|
| Back to top |
|
 |
J.F.
Joined: 22 Feb 2004 Posts: 2906
|
Posted: Wed Mar 05, 2008 9:46 am Post subject: |
|
|
| Can you set the semaphore inside the interrupt handler? That would be handy for things that want to delay on the vertical blank - just add the handler and at the proper place, just wait on the semaphore. |
|
| Back to top |
|
 |
kasikeeper
Joined: 29 Nov 2007 Posts: 36
|
Posted: Thu Mar 06, 2008 5:43 am Post subject: |
|
|
Thanks a lot four your help so far. I followed up on the thread approach and successfully created my thread which I call from the timer callback. Now the problem is the my thread is not started from my timer callback. The timer callback is triggered properly but
| Code: | | sceKernelStartThread(EventAlarmThreadID, 0, 0); |
does not start my thread. I did put the sceKernelStartThread(EventAlarmThreadID, 0, 0); statement in other places of my program just to make sure my thread works at all and it does indeed work alright. But for some reason it does not start my thread from within the timer callback. No error messages or something. sceKernelStartThread returns a number other than the thread id but not 0 or -1 so I guess it should be fine. Does anyone know??? |
|
| Back to top |
|
 |
hlide
Joined: 10 Sep 2006 Posts: 750
|
Posted: Thu Mar 06, 2008 7:45 am Post subject: |
|
|
huh i'm not sure about what you wanted to do...
say, you have a main thread.
Initially, your main thread is creating your Alarm thread and your Alarm event. Just let your main tread to start your Alarm thread once, before triggering any Alarm callbacks.
The code to run in your Alarm thread is quite simple : a loop which waits for the Alarm event. When an event wakes up the Alarm thread, and conditions are okay for a thread switch to occur and elect your Alarm thread, the Alarm thread exits from the event wait function : here you must put your code to run then loop again when finished so the Alarm thread waits for the next Alarm event.
Your Alarm callback, when running, just sets an Alarm event then exits the callback : you should not start a thread here.
The Alarm thread must have a higher priority than the main thread, so it can have more chance to be elected just after exiting interrupt. Don't expect a thread switch in a interrupt, this is a silly idea. Your callback is just a deferred call to wake up a higher prioritized but shorter thread which will be elected as soon as possible (i.e, when a thread switch can occur).
There is no way else. |
|
| Back to top |
|
 |
kasikeeper
Joined: 29 Nov 2007 Posts: 36
|
Posted: Tue Mar 11, 2008 12:02 am Post subject: |
|
|
Thanks a lot for all your help. I got it running and my timer works perfectly now. Now I want my timer to continue working also in sleep mode and - once the callback is triggered - I want the PSP to wake from sleep mode to do something.
From another thread I learned that the PSP's RTC functionality would allow to create timers that continue working in sleep mode. I checked the corresponding header file psprtc.h but could not find timer handle functionality. Where is the RTC / sleep&wake functionality hidden. Can you give me some clues? |
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|