GP2X Gp2x Sdk?


Squidge posted on Oct 19 2005 at 09:17 AM said:
Yes, you can access second arm core. It's an Arm940 if you want to look it up. Basically, just a scaled down 920, bit less cache, no mmu/etc.

Am I the only one that confused by this? Why is the 940 weaker then a 920? :huh:
Of course I am just working with the name of the proccessor, but it seems weird.
 
Last edited by a moderator:
Squidge posted on Oct 19 2005 at 03:38 PM said:
Just give it the physical start address (upper 8-bits) and tell it to go.

The docs say that the 940 powers up in the reset state. So let me get this straight. Let's say I've got a function called 940main that is located at 0x0200000, halfway up the SDRAM, that I want the 940 start at. I would just set the bottom 8 bits of the DUALCTRL940 register (at 0xC0003B48) to be 0x02 and then clear the RST940 bit to let it go? According to the docs, 940 should start at address 0x02000000.

I wonder how the memory arbitration is handled? It might be better to code up micro tasks that can fit in the 4KB I cache of the 940 and let it crank on data. I wonder if there are cache prefetch intrinsics that would allow me to pull 4KB blocks into the D cache. That would keep the 940 off the bus as much as possible while maximizing it's usefulness.

Using the DUAL920 and DUAL940 registers to do interrupt driven synchronization looks easy enough. Offloading sound, and graphics routines should be easy enough. Squidge, are there any atomic instructions for direct memory synchronization (e.g. CAS, DCAS, atomic increment and test)? (I've only skimmed the docs at this point and I'm kinda new to ARM).

I wonder how the embedded Linux is going to handle this? I wonder if the Linux kernel will report two processors and let you set affinity or if you will have to hand code your apps to use the 940.
 
Last edited by a moderator:
theoddbot posted on Oct 20 2005 at 07:50 PM said:
You have to hand-code it. The kernel just sees the 940T as a couple of registers.

Hrm, I wonder how the virtual memory plays into this. The 920 has an MMU but the 940 doesn't.
 
Last edited by a moderator:
reallynotnick posted on Oct 19 2005 at 06:01 PM said:
Am I the only one that confused by this? Why is the 940 weaker then a 920? :huh:
Of course I am just working with the name of the proccessor, but it seems weird.
The 940 isn't weaker than the 920 per se. It is actually the same exact chip running at the same frequency. What's different is that the 940 lacks MMU hardware and has smaller instruction (I) and data (D) caches. To understand how CPU caches effect performance read the wikipedia article on CPU caches.

It looks like the 940 is meant for pure helper processing (i.e. handling sound system, I/O, maybe graphics, probably AI, etc.) Think of it as the Igor to the 920 Dr. Frankenstein.

I'm not sure how I would partition game subsystems but it is likely that I would use it for handling async I/O, sound, input handling, and possibly AI. I'd leave the 920, with it's larger caches to handle the graphics nearly exclusively.
 
Last edited by a moderator:
MiniMoose: Linux only see's one processor, if you want to use the second processor, you have to copy your code (which should be compiled to run at address 0) into a physical page in memory that linux does not have access to, setup the control register and then just let it run. You can't use malloc()'d memory, as user apps will not know the physical address for this memory, and the memory may be split up and not actually allocated due to Linux's copy-on-write technique. However, upon bootup, 17MB of physical RAM is dedicated to the second processor at a fixed address (0x02000000 onwards), which should be enough for most purposes.
 
Squidge posted on Oct 21 2005 at 09:24 AM said:
MiniMoose: Linux only see's one processor, if you want to use the second processor, you have to copy your code (which should be compiled to run at address 0) into a physical page in memory that linux does not have access to, setup the control register and then just let it run. You can't use malloc()'d memory, as user apps will not know the physical address for this memory, and the memory may be split up and not actually allocated due to Linux's copy-on-write technique. However, upon bootup, 17MB of physical RAM is dedicated to the second processor at a fixed address (0x02000000 onwards), which should be enough for most purposes.

Does this mean you have to write that code in ASM? I don't know about any facility in starndard C to specify the physical address of a function, or even of any way to know exactly where a function ends (you can know where it starts, though...)
 
Last edited by a moderator:
Just keep the 940 functions in a completely self-contained file and modify the linker script to set the start address. Eg:

MEMORY
{
ram (rw) : ORIGIN = 0x0, LENGTH = 0x100000
}

SECTIONS
{
. = 0x0;

// etc...
 
Squidge posted on Oct 21 2005 at 11:48 AM said:
Just keep the 940 functions in a completely self-contained file and modify the linker script to set the start address. Eg:

MEMORY
{
ram (rw) : ORIGIN = 0x0, LENGTH = 0x100000
}

SECTIONS
{
. = 0x0;

// etc...

Ooooh :eek:

This opens a whole new world of opportunities... I guess I've always been a little too "high level" (never even heard about a linker script...)

Thanks.
 
Last edited by a moderator:
Squidge posted on Oct 21 2005 at 11:48 AM said:
Just keep the 940 functions in a completely self-contained file and modify the linker script to set the start address. Eg:

MEMORY
{
ram (rw) : ORIGIN = 0x0, LENGTH = 0x100000
}

SECTIONS
{
. = 0x0;

// etc...

Does this mean all that functions on that file will run on the 940 while the others will run on the 920? Or is more complicated than that? :eek:
 
Last edited by a moderator:
That is correct, but don't forget they are completely seperate - functions running on the 920 can not call functions on the 940 and functions on the 940 can not call functions on the 920. The same goes for variables. Treat them as two completely seperate processors.

What you can do however, is put something into memory out of reach of linux (eg. any memory address higher than 32MB). That way, either processor can access it. See the datasheet for info on how to tell each processor there is something waiting for it to process.
 
I'm sure Squidge and I can put together a nice tutorial on using the 940 and post it on the wiki page. I'd include things such as writing your own linker script for your app to locate 940 functions in it's memory space, setting up the 940 manually (i.e. cache behavior and start address), using the DUAL* registers for interrupt driven communication between the 920 and 940, and possibly, implement large-block data exchange via physical memory pages.

That last item depends on being able to tell the Linux kernel to lock down a virtual memory page into a physical address and not touch it until I release it back to the VMS. That way you could get the physical address, pass it to the 940, and let the 940 crank on the data for a bit and then tell the 920 it is done via the DUAL* registers and interrupt.

Squidge, how do the DUAL* registers and their associated interrupts work in the embedded Linux kernel? Is there a kernel driver that handles the interrupts and translates them into signals?

If the Linux kernel and its virtual memory crap get in the way, I think I may just not use it at all and write my own kernel. Virtual memory is nice on systems with HDD's, but on embedded systems, I never could figure out why it is useful, there's no place to swap pages out to. Memory protection is valuable for general OS's, but for video games, you don't have to, and most likely don't want to, worry about it.
 
just out of curiousity: how feasible would it be to let the second core do 3d graphics?

something like: a gp2x opengl "driver" that runs on the second core.
 
Orion_ posted on Oct 21 2005 at 08:49 AM said:
interesting :)
one question, can you fill the processor cache with data yourself ? how work the cache exactly ?

Usually the instruction and data caches get filled with instructions and data automatically by the memory controller. To figure out why, try reading the wikipedia post on CPU caches.

Squidge, do you know if there are instructions for prefetching data into the cache ahead of time? We use those a lot on regular game consoles (e.g. PS2, XBox, etc).
 
Last edited by a moderator:
no_skill posted on Oct 21 2005 at 12:24 PM said:
just out of curiousity: how feasible would it be to let the second core do 3d graphics?

something like: a gp2x opengl "driver" that runs on the second core.

You'd probably want to offload everything else to the second core and use the first core for 3D because it has larger caches. The cores themselves are more than powerful enough to do good 3D. Quake 1 is already running with a software renderer. Don't expect PS2/XBox/PS3/XBox360 3D graphics, but I think it is reasonable to be able to do near-dreamcast quality 3D.

The real hurdle is lighting and character skinning. I'm pretty sure that character skinning is doable in software, but dynamic lights are most certainly not possible without hardware help. Baking per-pixel lighting into the textures could make a game look great, even without dynamic lights.

I think I would aim for skeleton-based animation and character skinning, baked in per-pixel lighting (since SD cards have lots of storage capacity), and pray that dynamic vertex lighting from one or two lights is possible.

Remember that the GP2X has twice the RAM of a PS2. That means that we can preprocess and bake-in tons of data to reduce or elliminate run-time costs.
 
Last edited by a moderator:
Oh yeah, and did I mention that I think the GP2X could do 3D probably as well as the PSP? A friend of mine is writing PSP games ATM and it has pretty limited 3D capabilities even though it has a 3D chip. The extra RAM and dual processors on the GP2X make it mighty powerful. The PSP's paltry amount of RAM means that you can't bake in lots of data ahead of time.
 
Squidge posted on Oct 21 2005 at 12:24 AM said:
However, upon bootup, 17MB of physical RAM is dedicated to the second processor at a fixed address (0x02000000 onwards), which should be enough for most purposes.
So the memory map has a 17MB hole in it starting at 0x02000000 that the second core uses. The Linux kernel manages the two blocks of RAM on either side of it (the low 32MB and the remaining 15MB above it)?

Is there any way to reconfigure the 940's memory map? You say that the 940's 0x00000000 maps to 0x02000000 in the 920's memory map. Can you change that or is the address decoding logic static?
 
Last edited by a moderator:
MiniMoose posted on Oct 21 2005 at 07:55 PM said:
That last item depends on being able to tell the Linux kernel to lock down a virtual memory page into a physical address and not touch it until I release it back to the VMS. That way you could get the physical address, pass it to the 940, and let the 940 crank on the data for a bit and then tell the 920 it is done via the DUAL* registers and interrupt.

Not possible without using a driver, and since we don't have the kernel source, the likelihood of a driver is remote. Also, even if you could translate a virtual address into a physical one, there is no guarantee that the data is contiguous in memory when allocated by a user application, so the actual allocation would need to be done by a driver too, but then, user apps can't write to kernel mode allocated memory.

Squidge, how do the DUAL* registers and their associated interrupts work in the embedded Linux kernel? Is there a kernel driver that handles the interrupts and translates them into signals?

No, you need to write a driver to that yourself. See above.

Squidge, do you know if there are instructions for prefetching data into the cache ahead of time? We use those a lot on regular game consoles (e.g. PS2, XBox, etc).

There will be ways of flushing the cache, but no ways of prefetching - I think that's all automatic.

MiniMoose posted on Oct 21 2005 at 09:49 PM said:
So the memory map has a 17MB hole in it starting at 0x02000000 that the second core uses. The Linux kernel manages the two blocks of RAM on either side of it (the low 32MB and the remaining 15MB above it)?

The current kernel only manages one block of RAM - the low 32MB. The upper is 32MB is either reserved for the second core or unused.

Is there any way to reconfigure the 940's memory map?

Yes, rebuild the kernel, but then mpeg hardware acceleration will not work, as the mpeg decoding requires to be at a certain address.

You say that the 940's 0x00000000 maps to 0x02000000 in the 920's memory map. Can you change that or is the address decoding logic static?

You control the upper 8-bits of the address, So if you put 0x03 there, 0x0 will map to 0x03000000 (0x02000000 is normally mpeg buffers).
 
Last edited by a moderator:
Thanks Squidge.

So basically, to use the 2D accelerator and MPEG decoder and such we have to use the Linux kernel that GPH has put into the flash rom. I've never been much of a fan of the embedded Linux kernel since it still treats the hardware like a PC...which of course it is not.

To get the most out of the device we're going to have to code on the bare metal. Is there a way to take over the whole device and not use the Linux kernel?
 
Back
Top