The GBA Architecture

The GBA features a 32-bit RISC processor as its primary MCU. It uses the ARM7TDMI core, designed by ARM™ Inc.. Additionally the Z80/8080-style 8-bit CPU of the previous Game Boys is provided for compatibility. Our Linux kernel will only use the ARM processor in ARM mode (as opposed to Thumb mode; this is an alternative instruction set).

The GBA provides for 288 kBytes (32kB in-chip and 256kB on-board) of Work RAM (WRAM). The in-chip WRAM is currently not used by Linux (except for the interrupt vector). The kernel uses the same RAM as the applications for all its operations. This means that all the data currently resides in the on-board WRAM. Normally the in-chip WRAM is used for the usermode stack. As Linux is a multitasking operating system this cannot be done that way anyhow. The system is MMU-less, that is it doesn't support Virtual Memory for lack of a Memory Management Unit (MMU). This restriction has a severe impact on the Linux kernel, which relies completely on the existence of a MMU. For this reason, we are using the Linux derivative Microcontroller Linux or simply uClinux, which completely reimplements memory management for this purpose. For further information on uClinux please consult their webpage.

Additionally, the GBA contains a DMA-capable sound chip and a Gamepad consisting of 4 direction keys and 6 buttons (A, B, L, R, start and select). I will consequently refer to this Gamepad simply as the keypad.

An internal UART is also available. It is currently not used because it is connected to the GBA link cable, which would have to be manipulated in order to connect it to a standard RS232 interface. (The voltage levels are unknown to me as well.)

Memory Map, I/O Map, ROM Data

GBA Memory can be divided into the following regions:

  • BIOS - System ROM (16 kB)

  • In-chip Work RAM (32 kB)

  • On-chip Work RAM (256 kB)

  • I/O Registers

  • Display Memory

  • Game Pak ROM (up to 32 MB)

The Linux kernel is executed directly from the Game Pak (AKA cartridge) ROM using the eXecute In Place (XIP) method. On the other hand, user applications are loaded into the on-chip work RAM on execution. The user mode stack as allocated per-process in the on-chip Work RAM. The interrupt stack resides within the in-chip work RAM. The kernel data segment also resides within on-chip work RAM.

Additionally, the ROM filesystem is appended to the Linux kernel and mounted as root filesystem during start-up.

Kernel Initialization

After reset, the GBA BIOS displays the Nintendo logo and branches to the beginning of the cartridge ROM. The flow of execution in the Linux kernel starts at the start label in arch/armnommu/kernel/head-arm-gba.S. After set-up for execution of the kernel this code branches to start_kernel() in init/main.c.

Interrupt Handling

The GBA features an interrupt controller, which can be accessed through the I/O registers. It has a global Interrupt Mask Enable flag (IME) as well as an Interrupt Enable (IE) and an Interrupt pending Flag (IF) for each interrupt.

As the ARM processor has only one interrupt request line, the interrupt dispatch code first has to determine which interrupt actually triggered the execption. This is done by the get_irqnr_and_base macro in arch/armnommu/kernel/entry-armv.S.

Normally the IME flag would not used, as the ARM processor provides an interrupt disable flag in its internal status register. Still, for the Game Boy Advance we need this flag in one special case. This is explained in detail in the ``Interrupted System Calls'' section.

Configuration

Select the following options:

  • Vendor/Product: Nintendo/GBA

  • Kernel Version: linux-2.0.x

  • Libc Version: uC-libc

  • Default all settings (lose changes)