Timers

The Game Boy Advance has four 16-bit hardware timers (TM0 - TM3 or generally TM[x]).

Each timer is made up of a 16-bit counter, a 16-bit reload value and a control register.

IO registers

Overview

AddressNameDescription
0x04000100TM0DTimer #0 counter (on read) and reload (on write) value
0x04000102TM0CNTTimer #0 control register
0x04000104TM1DTimer #1 counter (on read) and reload (on write) value
0x04000106TM1CNTTimer #1 control register
0x04000108TM2DTimer #2 counter (on read) and reload (on write) value
0x0400010ATM2CNTTimer #2 control register
0x0400010CTM3DTimer #3 counter (on read) and reload (on write) value
0x0400010ETM3CNTTimer #3 control register

TM[x]D

Reads return the current 16-bit counter value. Writes set the 16-bit reload value.

TM[x]CNT

Bit(s)R/WNameDescription
0 - 1RWClock DividerSelect a clock divider frequency (see Clock Divider)
2RWClock Select 10 = clock divider output, 1 = on TM[x-1] overflow
3 - 50Unused
6RWIRQ enable0 = IRQ disabled, 1 = IRQ enabled
7RWEnable0 = disable, 1 = enabled
8 - 150Unused

Clock Divider

The 16 MiHz (16.777.216 Hz) system clock is divided into four frequencies using a single clock divider.

When a timer uses the system clock (meaning Clock Select is zero), it runs at one of those frequencies:

ValueFrequencyDivisor
016 MiHz1
1256 KiHz64
264 KiHz256
316 KiHz1024

The relation between frequency and divisor is: Frequency = 16 MiHz / Divisor

Functionality

When the enable bit (TM[x]CNT.bit7) changes from 0 to 1 the reload value is loaded into the counter.

While the enable bit is set, the counter is incremented every time its input clock pulses:

  • when Clock Select = 0: at the frequency selected via Clock Divider.
  • when Clock Select = 1: when TM[x-1] ticks and overflows (the overflow flag of TM[x-1] is connected as input clock).

When the 16-bit counter overflows:

  1. the reload value is loaded into the counter
  2. if IRQ enable (TM[x]CNT.bit6) is set: an IRQ is requested in IE bit 3 + x

Timing notes

  1. Changes to TM[x]D and TM[x]CNT take one cycle to apply2.
  2. The clock divider appears to generate pulses every n cycles (where n is the divisor) relative to system startup (meaning a timer can tick in less than n cycles after it was enabled). This however hasn't been thoroughly researched yet.
1

for TM0 this bit always reads zero (the clock divider output is forcibly used)