Getting Code On The Arm940


DieMumiee

Still Fresh
Joined
Jan 13, 2007
Messages
8
I want to use the 2nd core of the gp2x. But up to now nothing happens.

Here is the code that is supposed to load the binary that resides in "940bin.hpp"

Code:
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <iostream>
#include "940bin.hpp"
enum Registers 
{
  SystemClocks		= 0x0904
	, VSync		   = 0x1182
	, ScreenBitDepth  = 0x28DA
	, ScreenLineWidth = 0x290C
	, RGBLayerOddL	= 0x290E
	, RGBLayerOddH	= 0x2910
	, RGBLayerEvenL   = 0x2912
	, RGBLayerEvenH   = 0x2914
	, Interrupt940_1  = 0x3B40
	, Interrupt940_2  = 0x3B42
	, MemoryBase940   = 0x3B48 
	, VideoSync	   = 0x1182
};
int main()
{
  int memory = open("/dev/mem", O_RDWR);
  if( memory == -1 )
  {
	std::cerr << "FOO" << std::endl;
  }
  unsigned char* upper_memory = reinterpret_cast<unsigned char*>(
	  mmap(0,  sizeof(compiled_940bin_binary), PROT_READ | PROT_WRITE, MAP_SHARED, memory, 0x2000000)
	  );
  volatile unsigned short* registers = reinterpret_cast<unsigned short*>(
	  mmap(0, 0x10000, PROT_READ | PROT_WRITE, MAP_SHARED, memory, 0xc0000000)
	  );

  registers[SystemClocks>>1] &= ~(1<<0);
  registers[MemoryBase940>>1] = (1<<7) | 2; 

  memcpy( upper_memory , static_cast<void const*>(compiled_940bin_binary), sizeof(compiled_940bin_binary));

  registers[Interrupt940_1>>1] = 0;
  registers[Interrupt940_2>>1] = 0;

  registers[SystemClocks>>1] |= (1<<0);
  registers[MemoryBase940>>1] = 2; 

  munmap( const_cast<unsigned short*>(registers), 0x10000);
  munmap( upper_memory, sizeof(compiled_940bin_binary));
  close( memory );

}

940bin is created from the following source code, by linking a binary with the current crt0.s of squidge and relocating it with objdump. The tool hexdump creates a char array called compiled_940bin_binary containing the application.
Code:
gcc src/940/main940.cpp -c -I . -I gp2xfw940/
gcc crt0.s -c 
ld crt0.o main940.o  -o 940bin.elf
arm-gp2x-linux-objcopy -O binary  940bin.elf  940bin
./hexdump 940bin > src/940bin.hpp

Here is the main940.cpp
Code:
enum Registers 
{
  SystemClocks		= 0x0904
	, VSync		   = 0x1182
	, ScreenBitDepth  = 0x28DA
	, ScreenLineWidth = 0x290C
	, RGBLayerOddL	= 0x290E
	, RGBLayerOddH	= 0x2910
	, RGBLayerEvenL   = 0x2912
	, RGBLayerEvenH   = 0x2914
	, Interrupt940_1  = 0x3B40
	, Interrupt940_2  = 0x3B42
	, MemoryBase940   = 0x3B48 
	, VideoSync	   = 0x1182
};


const long GP940_OFFSET = 0x2000000;

// void flip_unsync();

int main()
{
  unsigned short* screen;
  unsigned short* screens[2];
  volatile unsigned short* registers = (volatile unsigned short*)(0xc0000000 - GP940_OFFSET);
  unsigned int screen_addr[2];

  registers[ScreenBitDepth>>1] =  0x04ab;  /* hex(1|1<<1|1<<3|1<<5|1<<7|2<<9) */
  registers[ScreenLineWidth>>1] = 0x0280; /* Line width in bytes*/

  screen_addr[0]  = 0x03101000;
  screen_addr[1]  = 0x03381000;
  screens[0]	  = (unsigned short*)(screen_addr[0] - GP940_OFFSET);
  screens[1]	  = (unsigned short*)(screen_addr[1] - GP940_OFFSET);

  screen = screens[1];
  registers[RGBLayerOddL>>1] = registers[RGBLayerEvenL>>1] = screen_addr[0] & 0xFFFF;
  registers[RGBLayerOddH>>1] = registers[RGBLayerEvenH>>1] = screen_addr[0] >> 16;

  while(true)
  {
	for( unsigned short color = 0; color < 32000; ++color )
	{
	  for( int j = 0; j < 320*240; ++j )
	  {
		screen[j] = color;
	  }

	  if(screen == screens[0]) 
	  {
		screen = screens[1];
		registers[RGBLayerOddL>>1] = registers[RGBLayerEvenL>>1] = screen_addr[0] & 0xFFFF;
		registers[RGBLayerOddH>>1] = registers[RGBLayerEvenH>>1] = screen_addr[0] >> 16;
	  } 
	  else 
	  {
		screen = screens[0];
		registers[RGBLayerOddL>>1] = registers[RGBLayerEvenL>>1] = screen_addr[1] & 0xFFFF;
		registers[RGBLayerOddH>>1] = registers[RGBLayerEvenH>>1] = screen_addr[1] >> 16;
	  }

	  while(~registers[VideoSync>>1] & (1 << 4));
	}
  }

}

When executing the application nothing happens. The application just terminates without error.
 
I compiled it and had a look to the generated code. It looked all right as far as I can tell.
I did not test your loader, though, because I have to gp2x here.

There is a general purpose loader in gpu940 (load940) that could load and run your 940bin file. You could try that to find out if the problem lies in your main940 or in your loader (load940 is in the egoboo2x archive file if you don't want to compile it).
 
Are you sure your 940 binary is linked and compiled to start from address zero ?

Also, you may need to specify an appropriate linker script (I don't know if this is necessary, but it's the way I did it).

For the compiling, I used a version of GCC made for general ARM usage (ie. one compatible with the GP32).
 
Squidge posted on Feb 8 2007 at 05:07 PM said:
Are you sure your 940 binary is linked and compiled to start from address zero ?

Also, you may need to specify an appropriate linker script (I don't know if this is necessary, but it's the way I did it).

I just looked at gpu940 and found a linker script, adapted to my modules it looks like:
Code:
SECTIONS {
  upper32 0x0000 : {
	crt0.o(.text)
	main940.o(.text)
	. = ALIGN(16);
	*(.data)
	. = ALIGN(4);
	*(.rodata*)
	. = ALIGN(4);
	*(COMMON)
	. = ALIGN(4);
	*(.bss)
  }
  /DISCARD/ : {
	*(*)
  }
}

There is a change in produced code. objdump without linker script:
Code:
 objdump -S 940bin.elf 

940bin.elf:	 file format elf32-littlearm

Disassembly of section .init:

00008074 <_start>:
	8074:	e59ff0c4 	ldr	pc, [pc, #196]; 8140 <.init+0xcc>
	8078:	e59ff0c4 	ldr	pc, [pc, #196]; 8144 <.init+0xd0>
	807c:	e59ff0c0 	ldr	pc, [pc, #192]; 8144 <.init+0xd0>
	8080:	e59ff0bc 	ldr	pc, [pc, #188]; 8144 <.init+0xd0>
	8084:	e59ff0b8 	ldr	pc, [pc, #184]; 8144 <.init+0xd0>
	8088:	e59ff0b4 	ldr	pc, [pc, #180]; 8144 <.init+0xd0>
	808c:	e59ff0b0 	ldr	pc, [pc, #176]; 8144 <.init+0xd0>
	8090:	e59ff0ac 	ldr	pc, [pc, #172]; 8144 <.init+0xd0>

00008094 <_xxinit>:
	8094:	e3a0003f 	mov	r0, #63; 0x3f
	8098:	ee060f10 	mcr	15, 0, r0, cr6, cr0, {0}
	809c:	ee060f30 	mcr	15, 0, r0, cr6, cr0, {1}
	80a0:	e3a00001 	mov	r0, #1; 0x1
	80a4:	ee020f10 	mcr	15, 0, r0, cr2, cr0, {0}
	80a8:	ee030f10 	mcr	15, 0, r0, cr3, cr0, {0}
....

With the linker script:
Code:
940bin_script.elf:	 file format elf32-littlearm

Disassembly of section upper32:

00000000 <upper32>:
   0:	e1a0c00d 	mov	ip, sp
   4:	e92dd800 	stmdb	sp!, {fp, ip, lr, pc}
   8:	e24cb004 	sub	fp, ip, #4; 0x4
   c:	e24dd020 	sub	sp, sp, #32; 0x20
  10:	e3a034bf 	mov	r3, #-1090519040; 0xbf000000
  14:	e24b001c 	sub	r0, fp, #28; 0x1c
  18:	e5803000 	str	r3, [r0]
  1c:	e59f2344 	ldr	r2, [pc, #836]; 0x368
  20:	e24b101c 	sub	r1, fp, #28; 0x1c
  24:	e5913000 	ldr	r3, [r1]
  28:	e0822003 	add	r2, r2, r3
  2c:	e59f3338 	ldr	r3, [pc, #824]; 0x36c
  30:	e1c230b0 	strh	r3, [r2]
  34:	e59f2334 	ldr	r2, [pc, #820]; 0x370
  38:	e24b001c 	sub	r0, fp, #28; 0x1c
  3c:	e5903000 	ldr	r3, [r0]
...
Is that what you mean by "compiled to start from address zero"?
But still nothing happens when loaded with load940.
 
Last edited by a moderator:
Yup, looks good to me. Don't forget however that your second code will not work without a valid crt0.s, so you'll need to link with that.

If it's my crt0.s unmodified, then the binary you upload to the 940 will usually start with two 0xe59ff0c4 words (which is bascially the start of the LDR instructions for the vector table)
 
Thank you, to both of you.

I just noticed that the second output did not include the code from crt0.o.

When running:
Code:
ld -T script.ld -N -s -o 940bin.elf
ld skiped the contents of crt0.s because the code there was marked to go into
the .init section.

So with
Code:
crt0.o(.text) => crt0.o(.init)
[c/code]
the initcode went into the hexdump with and without --only-section upper32.

But, still nothing happens when loaded on the gp2x.
 
Back
Top