gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

DS development > Can ARM7 code/data be linked into EWRAM?

#152749 - Maximus32 - Thu Mar 20, 2008 11:26 am

Currently the ARM7 code can only be linked in IWRAM by the linker scripts. Since I need more than 64KiB for ARM7 I would like to use the shared EWRAM. I was thinking to split this up:

ARM9: 3.0MiB or 3.5MiB
ARM7: 1.0MiB or 0.5MiB

- Is this possible?
- How can this be done in the linker scripts?
- Do the crt0 files need to be changed for this?

#152753 - eKid - Thu Mar 20, 2008 12:32 pm

I don't know if it's possible with devkitARM (two binaries sharing memory space). Also, sharing main ram for code can yield some side effects. Mainly, the memory can only be accessed by one CPU at a time. So, while one CPU is running code, the other will be completely frozen until the active one goes to sleep. I think there's a bit somewhere that controls which CPU has priority for the memory.

#152755 - Dwedit - Thu Mar 20, 2008 12:42 pm

If you're using C++, there are tricks you can use to make your binary a lot smaller.
_________________
"We are merely sprites that dance at the beck and call of our button pressing overlord."

#152756 - Maximus32 - Thu Mar 20, 2008 1:08 pm

I am using C++ so making that smaller would be very welcome! I am using -fno-rtti and -fno-exceptions, any other tips to making it smaller?

Still I would like to use EWRAM, since it's a big project, I will eventually need more than 64KiB anyway.

The performance penalty for sharing EWRAM is acceptable to me.

#152757 - simonjhall - Thu Mar 20, 2008 1:10 pm

You can keep all your code in the ARM9 binary and then pass across a function pointer (via shared memory, the fifo, whatever) and then call it from the ARM7.
Just make sure that you've compiled that bit of code (the one that lives in the ARM9 binary) with options that are compatible with the ARM7 instruction set.

Easy money...
_________________
Big thanks to everyone who donated for Quake2

#152764 - wintermute - Thu Mar 20, 2008 4:09 pm

Maximus32 wrote:

Still I would like to use EWRAM, since it's a big project, I will eventually need more than 64KiB anyway.


I'd think seriously about redesign. To me this would suggest you want to use the ARM7 for something that it's not really suited

Quote:

The performance penalty for sharing EWRAM is acceptable to me.


That performance penalty is rather larger than you might expect.

To others answering questons like these :- have you considered that perhaps the posters interests might be better served by asking what the final objective is rather than telling him how to achieve something that may lead to major refactoring later?
_________________
devkitPro - professional toolchains at amateur prices
devkitPro IRC support
Personal Blog

#152765 - Maximus32 - Thu Mar 20, 2008 4:30 pm

You are absolutely right. I am trying to use it for something it's not really suited for...

I'm trying to build an operating system for game consoles (currently runs on gba, nds, ps2, psp, ngc, i386). My goals are to make everyting communicate through message passing (send/receive/reply), this already works.

The thing is... I'm treating the NDS as TWO systems, with TWO operating systems, communicating through IPC, this way I have multithreading, sleep, etc, etc in ARM7 also.

I know it would probably be better to keep the ARM7 simple (no OS, just simple execution of commands from ARM9), but it's really cool to see two osses in one DS communicating to eachother, and it's my perfect testing system for message passing between two systems.

Why should the ARM9 have all 4MiB (and only use ~150KiB now), and the ARM7 have nothing? As I said before performance is not an isue for now, and I intend to put all processing intesive tasks and ISR's into IWRAM, and use the EWRAM for everyting else.

#152769 - wintermute - Thu Mar 20, 2008 5:19 pm

Sounds quite entertaining :)

Personally I'd tend more towards treating the ARM7 as a peripheral controller than using separate OS components in both. One of the difficulties you end up running into is how to manage main memory if both processors can allocate and free blocks, then there's the bus priority which ends up crippling at least one of the processors.

The way the default linkscripts & crt0s are set up, the arm7 has 96k of internal RAM and the arm9 controls main memory. This works rather well for our purposes and is much the same route that Nintendo went in the end. Depending on your needs, it's also possible to allocate 256K of VRAM to the arm7 and use that in conjunction with or instead of the 96K the arm7 normally has access to.

devkitARM is not built for multithreading so you need to be careful with malloc and stdio if you're using things from the standard libraries.

If you really want to attempt the everything in ewram thing.

Check the linker script documentation @ http://sourceware.org/binutils/docs-2.18/ld/Scripts.html#Scripts and familiarise yourself with the current scripts, found in devkitARM/arm-eabi/lib ( ds_arm9.ld, ds_arm7.ld ) and the specs fragments.

You'll need to adjust the crt0 files too, the source for those is in the same place, they should be fairly self explanatory.

The parameters for ndstool will need to be adjusted for custom start & memory addresses.

Simon's suggestion is likely to lead to trouble, I made a few attempts to build a single binary way back in the early days but I had a lot of serious head bending problems with it. It's *very* difficult to make sure that code running on the arm9 doesn't call code intended for the arm7 and vice versa. Having said that, the main thing that made me give up on it was how much it crippled performance.

Apart from that, have fun - sounds like a very interesting little project.
_________________
devkitPro - professional toolchains at amateur prices
devkitPro IRC support
Personal Blog

#152774 - simonjhall - Thu Mar 20, 2008 6:36 pm

Well I always figure people don't want to know my opinion when they ask stuff like this, they just want to know the answer!
Plus I'm normally at work when I write messages like this so I ain't got a lot of time to write a long rambling message about how dey is WRONG!

Pub time ;-)
_________________
Big thanks to everyone who donated for Quake2

#152778 - Maximus32 - Thu Mar 20, 2008 7:41 pm

Managing main memory can be simple. Just divide it statically in the linker script (3MiB for ARM9, 1MiB for ARM7).

Adding extra video memory is a good idea! That way the performance penalty won't be so big. I'll have to look into the linker scrips though (not my favorite)

As for memory allocation, I have my own routines for malloc, free, new and delete. Currently ARM9 uses what's left of the 4MiB and ARM7 uses what's left of IWRAM (not much).

If you're interested you can have a look at the "interesting little project" ;-)

svn co https://bricks-os.svn.sourceforge.net/svnroot/bricks-os/trunk bricks-os

#152780 - Dwedit - Thu Mar 20, 2008 7:51 pm

Smaller C++ binary: (the short post)
#1) Link with -lsupc++ as the first library instead of -lstdc++. Doing this alone makes a huge difference. Among other things, you will no longer find lots of C++ error messages dealing with rtti in your binaries.

#2) Include this C++ code somewhere in your program:
Code:

extern "C" {
   void __gxx_personality_v0()
   {
      
   }
   void __aeabi_atexit()
   {
      
   }
}


The longer version of this post:
To find out what functions you can make blank, look through the .map file your compiler generates. Whenever a function is linked in from the standard C++ library, it loves it invite a bunch of friends to come along with it. Here's a line from a .map file:
Code:

c:/devkitpro/devkitarm/bin/../lib/gcc/arm-eabi/4.1.2/../../../../arm-eabi/lib/thumb\libstdc++.a(eh_personality.o)
                              main.o (__gxx_personality_v0)

This shows that main.o is asking for __gxx_personality_v0. Linking to that function adds a bunch of its friends:
Code:

(std::terminate())
(__cxxabiv1::__terminate_handler)
(__cxxabiv1::__unexpected_handler)
(__gnu_cxx::__verbose_terminate_handler())
(__cxa_demangle)
(__cxa_end_cleanup)
(__cxa_bad_typeid)
(__cxa_call_terminate)
(__cxa_end_catch)
(vtable for std::bad_exception)
(__cxa_get_globals_fast)
(__cxa_rethrow)
(__cxa_current_exception_type)
(vtable for __cxxabiv1::__class_type_info)
(typeinfo for void)
(operator delete(void*))
(__cxa_free_exception)

The clincher: In the test program that included this, __gxx_personality_v0 is never called or referred to!
If you create your own blank version, the compiler will not try to link it in.

Another library that shows up commonly is __aebai_atexit().
It shows up any time you have global instances of classes, so that your program can destruct them when your program finishes.
Only problem is that there's no notion of exit() for NDS programs. Why bother with the big bunch of code for handling and registering "atexit" events?
That's a good one to make blank.
_________________
"We are merely sprites that dance at the beck and call of our button pressing overlord."


Last edited by Dwedit on Thu Mar 20, 2008 8:14 pm; edited 1 time in total

#152781 - Maximus32 - Thu Mar 20, 2008 8:08 pm

Thanks, I'll try those as well.

I already have those for the i386 version, becouse there are no c++ libraries for i386 when building an os. Guess it makes sense using them for the other platforms as well.

#152783 - tepples - Thu Mar 20, 2008 8:24 pm

wintermute wrote:
Personally I'd tend more towards treating the ARM7 as a peripheral controller than using separate OS components in both.

Like the IOP of the PlayStation 2 and the MC68000 of the Jaguar, right?

Dwedit wrote:
Smaller C++ binary: (the short post)

Has anybody looked into how one might port uClibc++ to the GBA or DS, so that cout << "hello world\n"; doesn't take the majority of the GBA's EWRAM like it does with GNU libstdc++?

Dwedit wrote:
Only problem is that there's no notion of exit() for NDS programs.

Would rebootlib count?
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#152786 - wintermute - Thu Mar 20, 2008 8:44 pm

simonjhall wrote:
Well I always figure people don't want to know my opinion when they ask stuff like this, they just want to know the answer!
Plus I'm normally at work when I write messages like this so I ain't got a lot of time to write a long rambling message about how dey is WRONG!


It's not really about wrong, more about how sometimes it's more helpful to suggest a less awkward path to a solution. Many programmers ( including me ) sometimes get stuck on using a particular algorithm when something else might be better suited.

Quote:

Pub time ;-)


mmm, beer

Maximus32 wrote:
Managing main memory can be simple. Just divide it statically in the linker script (3MiB for ARM9, 1MiB for ARM7).


What if you delegated the ARM9 to memory management and had the ARM7 request blocks? That way you don't really need to make static divisions, especially if the core ARM7 code can fit in the usual 96K.

Quote:

If you're interested you can have a look at the "interesting little project" ;-)

svn co https://bricks-os.svn.sourceforge.net/svnroot/bricks-os/trunk bricks-os


Quick note - avoid using the -o option to ndstool, that way your .nds file will still run on slot2 cards & no$gba.

Also, doesn't google forbid putting adsense stuff in a sponsors/ads box like that? Hate to see you get your account pulled for something so simple.
_________________
devkitPro - professional toolchains at amateur prices
devkitPro IRC support
Personal Blog

#152796 - Maximus32 - Thu Mar 20, 2008 10:57 pm

Quote:
What if you delegated the ARM9 to memory management and had the ARM7 request blocks? That way you don't really need to make static divisions, especially if the core ARM7 code can fit in the usual 96K.

Before IPC is set up I need memory management, plus, what is an OS without memory management.... a library?

Quote:
Quick note - avoid using the -o option to ndstool, that way your .nds file will still run on slot2 cards & no$gba.

Wow, you've looked at my code, thanks for the tip!

Quote:
Also, doesn't google forbid putting adsense stuff in a sponsors/ads box like that? Hate to see you get your account pulled for something so simple.

Damn, you also looked at my site... needs some serious updating. I wasn't aware of that, I'll look into it when I update my site.

#152842 - Maximus32 - Fri Mar 21, 2008 3:42 pm

Talk about waisting memory!

Adding __gxx_personality_v0 and __aeabi_atexit saved me 4KB.

Adding __cxa_pure_virtual saved me 39KB!!!!! Thats more than half the entire IWRAM, waisted.

I now have more than enough memory for now!

Thanks Dwedit!