GP2X 940 Unstable


DrStrider

Still Fresh
Joined
Sep 11, 2006
Messages
13
Hello everyone,

Was wondering if anyone might be able to help me - I'm trying to run some code on the 940, specifically a sound mixer, and I'm running into trouble. I can run code on the 940, which I can see by setting the video registers to the program location, but occasionally, especially after restarting the program Linux becomes unstable and my PuTTY connection either drops or gets garbage thrown to it

Has anyone ever seem anything like this before?

Here is my code for loading a 940 program:
Code:
static void Init940()
{
	FILE *f=NULL;
	int len=0,ret=0,pos=0;
	unsigned char temp[0x400];

	memset(temp,0,sizeof(temp));

	MainRegs[0x0904>>1]=0xaffe; // Stop 940
	MainRegs[0x3b48>>1]=0x0083; // Reset

	// Disable interrupts:
	MainRegs[0x3b40>>1]=0;
	MainRegs[0x3b42>>1]=0;
	MainRegs[0x3b44>>1]=0xffff;
	MainRegs[0x3b46>>1]=0xffff;

	asm volatile("":::"memory");

	// Clear part of 940's memory
 	memset(Memory+0x01000000,0,0x80000);

	// Read the 940 code into the upper 32Meg:
	f=fopen("Code940.bin","rb");
	if (f==NULL) return;

	for (;;)
	{
		ret=fread(temp,1,sizeof(temp),f);

		if (ret>0)
		{
			memcpy(Memory+0x01000000+pos,temp,ret);
			pos+=ret;
 		}
		
		if (ret!=sizeof(temp)) break; // Finished reading
	}

	MainRegs[0x3b48>>1]=0x0003; // Reset to 0x03000000
	MainRegs[0x0904>>1]=0xafff; // Run 940

	// Look at the 940 program:
	unsigned int phys=0x03000000;
	MainRegs[0x290e>>1]=(unsigned short) phys;
	MainRegs[0x2910>>1]=(unsigned short)(phys>>16);
	MainRegs[0x2912>>1]=(unsigned short) phys;
	MainRegs[0x2914>>1]=(unsigned short)(phys>>16);
	for(;;) { } // Loop forever
}

My 940 initialisation is currently from Dzz's OGG decoding sample! Here it is (Main940.c):
Code:
void DoStuff();

void Main940() __attribute__((naked));

void Main940()
{
	// Interrupt and reset opcodes
	asm("b .StartPoint");
	asm("b .StartPoint");
	asm("b .StartPoint");
	asm("b .StartPoint");
	asm("b .StartPoint");
	asm("b .StartPoint");
	asm("b .StartPoint");
	asm("b .StartPoint");
	asm(".StartPoint:");

	asm ("mov sp, #0x80000");	// set the stack top
	asm ("sub sp, sp, #4");	   // minus 4

	// set up memory region 0 -- the whole 4GB address space
	asm ("mov r0, #63");  // region data
	asm ("mcr p15, 0, r0, c6, c0, 0");
	asm ("mcr p15, 0, r0, c6, c0, 1");
	// set up region 1 which is the first 2 megabytes.
	asm ("mov r0, #0x00000029");  // region data
	asm ("mcr p15, 0, r0, c6, c1, 0");
	asm ("mcr p15, 0, r0, c6, c1, 1");
	// set region 1 to be cacheable (so the first 2M will be cacheable)
	asm ("mov r0, #2");
	asm ("mcr p15, 0, r0, c2, c0, 0");
	asm ("mcr p15, 0, r0, c2, c0, 1");
	// set region 1 to be bufferable too (only data)
	asm ("mcr p15, 0, r0, c3, c0, 0");
	// set protection on for all regions
	asm ("mov r0, #15");
	asm ("mcr p15, 0, r0, c5, c0, 0");
	asm ("mcr p15, 0, r0, c5, c0, 1");

	asm ("mrc p15, 0, r0, c1, c0, 0"); // fetch current control reg
	asm ("orr r0, r0, #1"); // 0x00000001: enable protection unit
	asm ("orr r0, r0, #4"); // 0x00000004: enable D cache
	asm ("orr r0, r0, #0x1000"); // 0x00001000: enable I cache
	asm ("orr r0, r0, #0xC0000000"); //  0xC0000000: async+fastbus
	asm ("mcr p15, 0, r0, c1, c0, 0"); // set control reg

	DoStuff();
}

And finally the simple routine which just draws some data into memory (Stuff940.c):

Code:
void DoStuff()
{
	// Loop forever:
	int i=0,col=0xfe00;

	for (;;)
	{
		for (i=2*320*10; i<2*320*20; i+=2)
		{
			*(unsigned short *)(0xe00000+i)=col;

		}

		col^=0x00ff;
	}
}

Finally the 940 part of the makefile, in case there are errors:
Code:
# ---------------------------------------------------------------------

OBJS_940 = Main940.o Stuff940.o

Code940.bin : $(OBJS_940)
	$(LD) -e Main940 -Ttext 0 $(OBJS_940) -o Code940.elf
	$(OBJCOPY) -O binary Code940.elf Code940.bin

Main940.o : Main940.c
	$(CC) -O0 -W -Wall -c $<

# ---------------------------------------------------------------------


I would think there is very little which could go wrong, but well every now and again Linux just dies on me, which it never does without the 940 running, which makes me think I am doing something very unstable indeed.

Here is my 'upload a new version' batch file. TypeInWindow is a little program I wrote to automatically type characters into my PuTTY window:
Code:
TypeInWindow.exe "10.1.0.2 - PuTTY" "killall test.gpe"

make all
@if errorlevel 1 pause&exit

mkdir \\10.1.0.2\gp2x\mnt\sd\test
xcopy /d /y *.gpe	   \\10.1.0.2\gp2x\mnt\sd\test\
@if errorlevel 1 pause&exit

cl /W4 TypeInWindow.cpp user32.lib
del TypeInWindow.obj

TypeInWindow.exe "10.1.0.2 - PuTTY" "cd /mnt/sd/test/;./test.gpe &"



Does anyone have any ideas at all? My current best theory is that by running killall test.gpe I am shutting down the program without shutting down the 940, and if Linux was to then replace 0x3000000 with a piece of random data, the 940 would crash and possible wreck memory within Linux. But what is the recommended way of shutting down a 920/940 program? Would Ctrl-C do anything different??

Any help gladly appreciated :)
 
You could setup a signal handler to exit the program nicely (stop the 940 etc).

http://www.die.net/doc/linux/man/man2/signal.2.html - signal man page
http://www.die.net/doc/linux/man/man7/signal.7.html - description of the signals man page

It's been a while since I did any C programming in Linux but an example to trap when the user presses CTRL-C would be something like:

Code:
int quit = 0;

void sigint() {
	signal(SIGINT, sigint); // setup the signal handler again in case there are multiple signals
	quit = 1;
}

int main() {
	signal(SIGINT, sigint); // setup the signal handler

	printf("Press CTRL-C to exit.\n");

	for(;;) {
		if(quit) {
			// perform shutdown
			break;
		}
	}
}
 
Found another url with info:

http://www.gnu.org/software/libc/manual/ht...l-Handling.html

The killall likely sends a SIGTERM so you could try trapping that too.


Thanks for the stuff!

It's so weird, I tried all that but the 940 is behaving even weirder now... remember that loop which counts up and fills up a few lines of the screen?
Code:
void DoStuff()
{
	// Loop forever:
	int i=0,col=0xfe00;

	for (;;)
	{
		for (i=2*320*10; i<2*320*20; i+=2)
		{
			*(unsigned short *)(0x000000+i)=col;
		}

		col^=0x00ff;
	}
}


When I change that, recompile and upload, and restart the program, sometimes it works, but sometimes it starts to fill the whole screen, presumably filling the whole of the memory... I see it go off the bottom then about 2 minutes later the colour fills the top of the screen where the program is running and of course that's where it stops (because it just overwrote the program)

it's almost as if the loop read:
for (i=2*320*10; ; i+=2)
or something!! Like a compare opcode is missing! I just don't get it!

Typically if I restart with the same program, it's fine!

I just don't get it?? Some werid caching thing?!
 
Last edited by a moderator:
Are you disabling 920 interrupts after starting up/switching over to the 940?
 
Hi !

Not a long answer because I *hate* web forums.

Yes, I experienced such hangs when I code for the 940.

The main source of problems I encountered were due to 'I/O starvation'
when the 940 do a lot of reads/writes to the MMSP registers.

This should not be your case.

I also had these hangs when benchmarking mem writes.
I never understood those. Probably a misconfiguration in the
940 memory access controler.

Anyway, Im now used to 940 coding, because I do a lot of
3d rendering with the 940, and now it really works like a charm (better
than the PC version, actually).

Did you check that your stack size was enought ?
Also, please post a link to you Code940.bin so that we
can have a look. I'd also like to test it with my own loader.
 
Are you disabling 920 interrupts after starting up/switching over to the 940?

What for ??

Sorry was picking up bits and pieces and not the whole picture. Saw the infinite loop on the 920 assumed you were done using it...

I have not had any problems running the 940. But I intentionally hose linux and the 920. Before I started doing that I was still not having problems, the 920 would wait for a button to be pressed and take over again. Only the movie playing was hosed, the rest worked.
 
Last edited by a moderator:
Okay I think I've sorted it!

If it helps anyone else here's what seemed to fix it, not sure which change it was or if it was all of them put together which made it stable....

Code:
static void Init940()
{
	FILE *f=NULL;
	int ret=0,pos=0;
	unsigned char temp[0x400];

	memset(temp,0,sizeof(temp));

	MainRegs[0x0904>>1]=0xaffe; // Stop 940
	asm volatile("":::"memory");
	// Disable interrupts:
	MainRegs[0x3b40>>1]=0;
	MainRegs[0x3b42>>1]=0;
	MainRegs[0x3b44>>1]=0xffff;
	MainRegs[0x3b46>>1]=0xffff;
 	MainRegs[0x3b48>>1]=0x0082; // Reset 940
	asm volatile("":::"memory");

	// Clear part of 940's memory
 	memset(Memory,0,0x80000);

	// Read the 940 code into the upper 32Meg:
	f=fopen("Code940.bin","rb");
	if (f==NULL) return;

	for (;;)
	{
		ret=fread(temp,1,sizeof(temp),f);

		if (ret>0)
		{
			memcpy(Memory+pos,temp,ret);
			pos+=ret;
 		}
		
		if (ret!=sizeof(temp)) break; // Finished reading
	}


	MainRegs[0x0904>>1]=0xafff; // Start 940	  **** NOTE <----- reversing of the Start and Reset, I think this is what helped stablise it most....****
	asm volatile("":::"memory");
 	MainRegs[0x3b48>>1]=0x0002; // Reset 940
}

Code:
	// set region 1 to be cacheable (so the first 2M will be cacheable)
	asm ("mov r0, #0"); // #2");  <---------------------------CHANGE
	asm ("mcr p15, 0, r0, c2, c0, 0");
	asm ("mcr p15, 0, r0, c2, c0, 1");
	// set region 1 to be bufferable too (only data)
	asm ("mcr p15, 0, r0, c3, c0, 0");

	// set protection on for all regions
	asm ("mov r0, #15");
	asm ("mcr p15, 0, r0, c5, c0, 0");
	asm ("mcr p15, 0, r0, c5, c0, 1");

	asm ("mrc p15, 0, r0, c1, c0, 0"); // fetch current control reg
	asm ("orr r0, r0, #1"); // 0x00000001: enable protection unit
	asm ("orr r0, r0, #4"); // 0x00000004: enable D cache
	asm ("orr r0, r0, #0x1000"); // 0x00001000: enable I cache
	asm ("orr r0, r0, #0"); // <----------------CHANGE #0xC0000000"); //  0xC0000000: async+fastbus
	asm ("mcr p15, 0, r0, c1, c0, 0"); // set control reg

	DoStuff();
}
 
Back
Top