GP2X Ram-hack (tweak) Topic


Q

quasist

Guest
Since me is lacking the system programming skills I copy-paste some code from very popular tweaking untility.
Here is final version of code that is easy to add to program.
As far it works nicely.
But It will be good if some pro-gp2x-linux-coder would look through for some bug... and saving the innocent users

CODE

#ifdef GP2X
#include "sys/mman.h"
#include "fcntl.h"

volatile unsigned short *MEM_REG;
unsigned long gp2x_dev=0;

void RamHack(void)//I't me! RamHack!
{
gp2x_dev = open("/dev/mem", O_RDWR);

MEM_REG=(unsigned short *)mmap(0, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, gp2x_dev, 0xc0000000);
unsigned short v,timing;

//tRC
timing=5;
v = (unsigned short)(MEM_REG[0x3804>>1] & (~(0xF << 8)));
MEM_REG[0x3804>>1] = ((timing & 0xF) << 8) | v;

//tRAS
timing=3;
v = (unsigned short)(MEM_REG[0x3804>>1] & (~(0xF << 4)));
MEM_REG[0x3804>>1] = ((timing & 0xF) << 4) | v;

//tWR
timing=0;
v = (unsigned short)(MEM_REG[0x3804>>1] & (~(0xF)));
MEM_REG[0x3804>>1] = (timing & 0xF) | v;

//tMRD
timing=0;

v = (unsigned short)(MEM_REG[0x3802>>1] & (~(0xF << 12)));
MEM_REG[0x3802>>1] = ((timing & 0xF) << 12) | v;

//tRFC
timing=0;

v = (unsigned short)(MEM_REG[0x3802>>1] & (~(0xF << 8)));
MEM_REG[0x3802>>1] = ((timing & 0xF) << 8) | v;

//tRP
timing=1;

v = (unsigned short)(MEM_REG[0x3802>>1] & (~(0xF << 4)));
MEM_REG[0x3802>>1] = ((timing & 0xF) << 4) | v;
//tRCD
timing=1;

v = (unsigned short)(MEM_REG[0x3802>>1] & (~(0xF)));
MEM_REG[0x3802>>1] = (timing & 0xF) | v;

close(gp2x_dev);
}

#endif
 
This is for the RAM timings? Does not make me that happy then, as my GP2x unit can be overclocked stable up to 270Mhz, but crashes when I fiddle with the RAMtimings. Thus I always leave the RAM timings for what they are. If people start to include this as 'always on' in there programs, then some consoles will crash.
 
Daid said:
This is for the RAM timings? Does not make me that happy then, as my GP2x unit can be overclocked stable up to 270Mhz, but crashes when I fiddle with the RAMtimings. Thus I always leave the RAM timings for what they are. If people start to include this as 'always on' in there programs, then some consoles will crash.
for very low underclock, I've never seen (yet) a gp2x which crash with aggresive ram tweak
and you win a lot of fps :)
but i always add ram tweak like an option for if one day one unlucky gp2x exist :)
 
Last edited by a moderator:
Just tried it on my game and got a very noticeable increase in speed, at least 10 FPS which I quickly timed (certain point in the music). combined with the mmuhack there's loads of extra FPS out there now :)
 
I've don't really an idea what this is doing, but I have tried to simplify it :(
CODE

#ifdef GP2X
#include "sys/mman.h"
#include "fcntl.h"

volatile unsigned short *MEM_REG;
unsigned long gp2x_dev=0;

void RamHack(void)
{
gp2x_dev = open("/dev/mem", O_RDWR);

MEM_REG=(unsigned short *)mmap(0, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, gp2x_dev, 0xc0000000);
MEM_REG[0x3804>>1] = 0x0530 | (MEM_REG[0x3804>>1] & 0xF000);
MEM_REG[0x3802>>1] = 0x0011;

close(gp2x_dev);
}

#endif
 
i find that in a few cases if i use gmenu's ram tweak option, i get corrupt sound output. maybe this is because of something else though, i dunno. also, with gpsp it took me a while to find good ram timings that weren't actually causing a net speed loss, and that didn't cause a crash.

so my advice would be to always leave the option of turning it on or off. also if you don't change those registers at all then the user can still script the cpu/lcd/ram tweaker, or use the similar functionality that's built into gmenu2x.
 
Hi,

That RAM tweak increases a lot performance, but it doesn't dissapear when you exit that program...

Does anyone know what are the default values for that registers or how to revert to "normal" timmings?

Thanks :)

EDIT: I'm quite tired or stupid, forget what I've asked, it's too simple to ask that :D
 
Ok, I still have to test this code with my software renderer to see if it makes things noticeably faster. But for now I created a very cleaned up version of the code (warning: not tested yet).

CODE
#define MEMTIMEX0 0x3802
#define MEMTIMEX1 0x3804

union memtimex0_t {
struct {
unsigned int tRCD : 4; // default = 2
unsigned int tRP : 4; // default = 15
unsigned int tRFC : 4; // default = 4
unsigned int tMRD : 4; // default = 4
} s;
unsigned short i;
};

union memtimex1_t {
struct {
unsigned int tWR : 4; // default = 2
unsigned int tRAS : 4; // default = 7
unsigned int tRC : 4; // default = 10
unsigned int LAT : 1; // default = 1; apparently readonly
unsigned int reserved : 2; // readonly

// Write: Set 1 to set new SDRAM mode parameter;
// Read: 0 = complete, 1 = busy
unsigned int ModeStatusSet : 1;
} s;
unsigned short i;
};

void RamHack()
{
memtimex0_t t0;
t0.i = memreg16(MEMTIMEX0);
t0.s.tRCD = 1;
t0.s.tRP = 1;
t0.s.tRFC = 0;
t0.s.tMRD = 0;
memreg16(MEMTIMEX0) = t0.i;

memtimex1_t t1;
t1.i = memreg16(MEMTIMEX1);
t1.s.tWR = 0;
t1.s.tRAS = 3;
t1.s.tRC = 5;

// The docs say to write 1 to set new mode
// parameter but seems to work without?
t1.s.ModeStatusSet = 1;
memreg16(MEMTIMEX1) = t1.i;

// Wait until mode is set. May not be necessary?
do {
t1.i = memreg16(MEMTIMEX1);
} while (t1.s.ModeStatusSet);
}

The default values were taken from the MMSP2 Data Book. Some values seem to be read only. There is a ModeSet/ModeStatus bit in the MEMTIMEX1 register. The docs says to write 1 to set new SDRAM parameters, so I do this in the above code and also wait for this bit to be cleared as this should indicate completion. I don't realy know if this is actually necessary as it seems to work without it.

I don't really know what the individual values mean. I assume it is: cylcles = value + 1. If this is true we really lower the numer of cycles by a lot!

I think it would be quite useful to create a wiki page for this and put some explanations on it and post appropriate timing data which would make it as fast as possible while also keeping it stable even when the CPU is overclocked to say 266MHz.

EDIT: I tested it now. The first time it crashed my GP2X! But it worked on the second try. With this hack my demo runs ~11% faster on average. Actually the scene where I least expected it runs fastest.
 
I got nearly same speed increase (10-20%), when was added ramhack it to my FleshChasmer. I'm not sure, but h/w accelerated SDL blitting could be more benefit from ramhack than software 3d.

2Puck2099
Just launch the cpu&lcd tweak untility with no ramhack aplied. There should be displayed current ram-timings settings.
 
earx said:
is this the same thing as squidge's mmu hack? if not, i should really give it a try :)
no, not the same has Squidge mmu hack. Here we just change the ram timings of the gp2x to have faster acces to the ram
 
Last edited by a moderator:
these values have been discused a few times in this board afaik
if i'm right, emu&co discovered the magic values, then craigix modified them a little and posted them at boards

this is the implementation from minimal library which also sets the cpu clock:

CODE


/* Function: gp2x_dualcore_clock
This function sets the clock at ARM 920T coprocessor and RAM tweaks.

Note:
- Call this function only from your 920T program.

Parameters:
s (50,75,100,125,150,175,200,225,250) - Speed value in MHz. Default is 200.

Credits:
RobBrown, sasq and whizzbang (original clock setting code)

god_at_hell (original RAM tweaking code)

craigix, Emu&Co (tweaked RAM timing values) */

void gp2x_dualcore_clock(int s)
{
unsigned long interrupt_flags = gp2x_memregl[0x808>>2],
//tRC=7-1 if mhz > 266
//CAS=0,tRC=6-1,tRAS=3-1,tWR=1-1,tMRD=1-1,tRFC=1-1,tRP=1-1,tRCD=2-1; //emu&co's timings
CAS=0,tRC=6-1,tRAS=4-1,tWR=1-1,tMRD=1-1,tRFC=1-1,tRP=2-1,tRCD=2-1; //craigix's timings

//hardcoded values:
s=(s>=250?0x5D04:s>=225?0x5304:s>=200?0x4904:s>=175?0x3F04:s>=125?0x3c01:s>=100?0x6502:s>=75?0x4902:s>=50?0x6503:0);

if(s)
{
gp2x_memregl[0x0808>>2] = 0xFF8FFFE7; // Mask interrupts

gp2x_memregs[0x0910>>1] = s; // Set clock and wait

while(gp2x_memregs[0x0902>>1] & 1);

gp2x_memregs[0x3802>>1] = ((tMRD<<12)|(tRFC<<8)|(tRP<<4)|(tRCD)); //set RAM tweaks
gp2x_memregs[0x3804>>1] = ((CAS<<12)|(tRC<<8)|(tRAS<<4)|(tWR));

gp2x_memregs[0x0924>>1] = 0x8900 + ((1)<<8); // Set upll timing prescaler to 1 (0x5A00 for fw 1.0.x)

gp2x_memregl[0x0808>>2] = interrupt_flags; // Turn on interrupts
}
}




hope this helps someone
 
Back
Top