I am having problems with interrupt handling for serial IO port.
Basically, the code (below) works fine in kernel mode on the phat. The sio reads work on the slim too, but they don't seem to wait for the interrupt/timeout and return right away, thus making a very tight loop.
I don't see any errors during the registering and enabling the handler.. so the whole thing is a bit puzzling..
Any suggestions are greatly appreciated!
Here is the main.c
Code: Select all
#include <pspkernel.h>
#include <pspdebug.h>
#include <pspdisplay.h>
#include <pspsdk.h>
#include <pspctrl.h>
#include <stdio.h>
#include <string.h>
PSP_MODULE_INFO("SIO_TESTER", 0, 1, 1);
PSP_MAIN_THREAD_ATTR(PSP_THREAD_ATTR_USER);
//PSP_MODULE_INFO("SIO_TESTER", 0x1000, 1, 1);
//PSP_MAIN_THREAD_ATTR(0);
int sioReadChar();
void sioInit(int,int);
int main(void)
{
int baud=38400;
pspDebugScreenInit();
pspDebugScreenPrintf("PSP GPSlim 236 test - Press X to exit\n");
pspDebugScreenPrintf("Press UP/DOWN to change baud\n");
sceDisplayWaitVblankStart();
sceCtrlSetSamplingCycle(0);
sceCtrlSetSamplingMode(PSP_CTRL_MODE_ANALOG);
SceUID mod = pspSdkLoadStartModule("sioprx.prx", PSP_MEMORY_PARTITION_KERNEL);
if (mod < 0)
{
pspDebugScreenPrintf(" Error 0x%08X loading/starting pspremoteprx.prx.\n", mod);
sceKernelDelayThread(3*1000*1000);
sceKernelExitGame();
}
sceKernelDelayThread(1000000);
pspDebugScreenPrintf("module loaded !!!\n");
sioInit(baud,0);
sceKernelDelayThread(1000000);
pspDebugScreenPrintf("INIT DONE!!!\n");
int thid = sceKernelGetThreadId();
sceKernelChangeThreadPriority(thid, 31);
SceCtrlData pad;
int ch=-1;
while(1)
{
sceCtrlPeekBufferPositive(&pad, 1);
if(pad.Buttons & PSP_CTRL_SQUARE) {
sioInit(baud,0);
}
if(pad.Buttons & PSP_CTRL_UP) {
baud*=2;
pspDebugScreenPrintf("setting baud to: %d\n", baud);
sioInit(baud,0);
sceKernelDelayThread(500000);
} else
if(pad.Buttons & PSP_CTRL_DOWN) {
baud/=2;
pspDebugScreenPrintf("setting baud to: %d\n", baud);
sioInit(baud,0);
sceKernelDelayThread(500000);
} else
if(pad.Buttons & PSP_CTRL_CROSS)
{
break;
}
ch = sioReadChar();
if((ch >= 0) && (ch != '\r'))
pspDebugScreenPrintf("%c", ch);
else
pspDebugScreenPrintf(".");
}
sceKernelExitGame();
return 0;
}
Code: Select all
TARGET = pspgpslim236
OBJS = main.o sioprx.o
BUILD_PRX=1
PSP_FW_VERSION=371
INCDIR =
CFLAGS = -O2 -G0 -Wall
CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti
ASFLAGS = $(CFLAGS)
LIBDIR =
LDFLAGS =
EXTRA_TARGETS = EBOOT.PBP
PSP_EBOOT_TITLE = GPSlim236
PSPSDK=$(shell psp-config --pspsdk-path)
include $(PSPSDK)/lib/build.mak
Code: Select all
#include <pspsdk.h>
#include <pspintrman_kernel.h>
#include <pspintrman.h>
#include <pspsyscon.h>
PSP_MODULE_INFO("sioprx", 0x1006, 1, 1);
PSP_MAIN_THREAD_ATTR(0);
#define PSP_UART4_DIV1 0xBE500024
#define PSP_UART4_DIV2 0xBE500028
#define PSP_UART4_CTRL 0xBE50002C
#define PSP_UART_CLK 96000000
#define EVENT_SIO 0x01
int sceHprmEnd(void);
int sceSysregUartIoEnable(int uart);
int sceSyscon_driver_44439604(int power);
static SceUID g_eventflag = -1;
void sioSetBaud(int baud)
{
int div1, div2;
div1 = PSP_UART_CLK / baud;
div2 = div1 & 0x3F;
div1 >>= 6;
_sw(div1, PSP_UART4_DIV1);
_sw(div2, PSP_UART4_DIV2);
_sw(0x60, PSP_UART4_CTRL);
}
void _sioInit(void)
{
sceHprmEnd();
sceSysregUartIoEnable(4);
sceSysconCtrlHRPower(1);
}
int intr_handler(void *arg)
{
u32 stat;
/* Read out the interrupt state and clear it */
stat = _lw(0xBE500040);
_sw(stat, 0xBE500044);
sceKernelDisableIntr(PSP_HPREMOTE_INT);
sceKernelSetEventFlag(g_eventflag, EVENT_SIO);
return -1;
}
void sioInit(int baud, int kponly)
{
_sioInit();
if(!kponly)
{
g_eventflag = sceKernelCreateEventFlag("SioShellEvent", 0, 0, 0);
//void *func = (void *) ((unsigned int) intr_handler | 0x80000000);
void *func = (void *) ((unsigned int) intr_handler);
int st=sceKernelRegisterIntrHandler(PSP_HPREMOTE_INT, 1, func, NULL, NULL);
st=sceKernelEnableIntr(PSP_HPREMOTE_INT);
sceKernelDelayThread(2000000);
}
sioSetBaud(baud);
}
int sioReadChar(void)
{
int ch;
u32 result;
SceUInt timeout;
timeout = 1000000;
ch = pspDebugSioGetchar();
if(ch == -1)
{
sceKernelEnableIntr(PSP_HPREMOTE_INT);
sceKernelWaitEventFlag(g_eventflag, EVENT_SIO, 0x21, &result, &timeout);
ch = pspDebugSioGetchar();
}
return ch;
}
int module_start(SceSize args, void *argp)
{
return 0;
}
int module_stop()
{
return 0;
}
Code: Select all
PSP_BEGIN_EXPORTS
PSP_EXPORT_START(syslib, 0, 0x8000)
PSP_EXPORT_FUNC_HASH(module_start)
PSP_EXPORT_VAR_HASH(module_info)
PSP_EXPORT_END
PSP_EXPORT_START(sioprx, 0, 0x4001)
PSP_EXPORT_FUNC(sioInit)
PSP_EXPORT_FUNC(sioReadChar)
PSP_EXPORT_END
PSP_END_EXPORTS
Code: Select all
TARGET = sioprx
OBJS = main.o
INCDIR =
CFLAGS = -O2 -G0 -Wall -g
CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti
ASFLAGS = $(CFLAGS)
BUILD_PRX = 1
PRX_EXPORTS = sioprx.exp
USE_KERNEL_LIBC=1
USE_KERNEL_LIBS=1
LIBDIR =
LDFLAGS = -mno-crt0 -nostartfiles
LIBS = -lpspdebug -lpspsdk -lpsphprm_driver
PSPSDK=$(shell psp-config --pspsdk-path)
include $(PSPSDK)/lib/build.mak
all:
echo "$PSPSDK"
psp-build-exports -s sioprx.exp
cp *.S ../
cp *.prx ../
clean:
rm -f $(FINAL_TARGET) $(EXTRA_CLEAN) $(OBJS) $(PSP_EBOOT_SFO) $(PSP_EBOOT) $(EXTRA_TARGETS)
rm -f *.S