Skip to content

Internals

Andrea Barisani edited this page Jun 26, 2025 · 145 revisions

Key concepts

  • Go applications built with TamaGo run on bare metal, without any underlying OS. All required support is provided by the Go runtime and driver packages, also written in Go.

  • When hardware initialization is provided (like in the imx6ul package), the compiled binaries can be directly executed by the processor, without any need for a 3rd party bootloader. This completely eliminates any non-Go dependency.

  • Due to its design TamaGo also allows user space execution.

Go language and library support

The GOOS=tamago target maintains full language and standard library support, see Compatibility.

Go runtime API for GOOS=tamago

Go Reference

Board support packages or applications are required to define specific functions to support the runtime, additional functions/variables can be optionally set for more fine grained control over the runtime context.

The API is described in package tamago/doc.

Go distribution changes

  • TamaGo modifications to the original Go distribution are minimal to ease maintainability and potential upstream acceptance.

TamaGo support is implemented with a clean separation from other OSes, all modifications are conditional to compilation option GOOS=tamago and do not affect other architectures.

Go runtime changes

In addition to the runtime API, the following changes are highlighted:

Default memory layout (AMD64)

  +----------------------------------+ 0x00000000 (zero page start)
  |                                  |
  |           INACCESSIBLE           |
  |                                  |
  +----------------------------------+ 0x00009000
  |                                  |
  |        PAGE TABLES (16 kB)       |
  |                                  |
  +----------------------------------+ 0x0000d000
  |                                  |
  |           INACCESSIBLE           |
  |                                  |
  +----------------------------------+ 0x00200000 (zero page end)
  |                                  |
  |             UNUSED               |
  |                                  |
  +----------------------------------+ runtime.ramStart + 0x10000 (64 kB)
  |                                  |
  | .text                            |
  |                                  |
  | .noptrdata                       |
  |                Go application    |
  | .data                            |
  |                                  |
  | .bss                             |
  |                                  |
  | .noptrbss                        |
  |                                  |
  +----------------------------------+
  |                                  |
  |              HEAP                |
  |                                  |
  +----------------------------------+ runtime.g0.stack.lo (runtime.go.stack.hi - 0x10000)
  |                                  |
  |             STACK                |
  |                                  |
  +----------------------------------+ runtime.go.stack.hi (runtime.ramStart + runtime.ramSize - runtime.ramStackOffset)
  |                                  |
  |             UNUSED               |
  |                                  |
  +----------------------------------+ runtime.ramStart + runtime.ramSize
  |                                  |
  |             UNUSED               |
  |                                  |
  +----------------------------------+ 0xc0000000
  |                                  |
  |           UNCACHEABLE            |
  |                                  |
  +----------------------------------+ 0x100000000

Default memory layout (ARM)

  +----------------------------------+ 0x00000000 (zero page start)
  |                                  |
  |           INACCESSIBLE           |
  |                                  |
  +----------------------------------+ 0x00001000 (zero page end)
  |                                  |
  |             UNUSED               |
  |                                  |
  +----------------------------------+ runtime.ramStart (default for runtime.vecTableStart)
  |                                  |
  |  EXCEPTION VECTOR TABLE (16 kB)  |
  |                                  |
  +----------------------------------+ runtime.ramStart + 0x4000 (16 kB)
  |                                  |
  |        L1 PAGE TABLE (16 kB)     |
  |                                  |
  +----------------------------------+ runtime.ramStart + 0x8000 (32 kB)
  |                                  |
  |       EXCEPTION STACK (16 kB)    |
  |                                  |
  +----------------------------------+ runtime.ramStart + 0xC000 (48 kB)
  |                                  |
  |       L2 PAGE TABLE (16 kB)      |
  |                                  |
  +----------------------------------+ runtime.ramStart + 0x10000 (64 kB)
  |                                  |
  | .text                            |
  |                                  |
  | .noptrdata                       |
  |                Go application    |
  | .data                            |
  |                                  |
  | .bss                             |
  |                                  |
  | .noptrbss                        |
  |                                  |
  +----------------------------------+
  |                                  |
  |              HEAP                |
  |                                  |
  +----------------------------------+ runtime.g0.stack.lo (runtime.go.stack.hi - 0x10000)
  |                                  |
  |             STACK                |
  |                                  |
  +----------------------------------+ runtime.go.stack.hi (runtime.ramStart + runtime.ramSize - runtime.ramStackOffset)
  |                                  |
  |             UNUSED               |
  |                                  |
  +----------------------------------+ runtime.ramStart + runtime.ramSize
  |                                  |
  |                                  |
  +----------------------------------+ 0x100000000

Direct memory access (DMA)

The dma provides primitives for direct memory allocation.

Such DMA areas can be defined outside Go runtime, to prevent any GC operation on it and allow its use for transfers with hardware peripherals.

  +----------------------------------+ mem.dmaStart
  |                                  |
  |           DMA BUFFERS            |
  |                                  |
  +----------------------------------+ mem.dmaStart + mem.dmaSize

As an example the imx6ul package uses the 128KB On-Chip RAM (also known as iRAM) for DMA transfers.

Board packages and applications are free re-initialize DMA buffers if more, or alternate, space is required.

Interrupts

The handling of interrupts is achieved by GOOS=tamago specific runtime.WakeG which implements a pure Go assembly procedure to wake a sleeping goroutine.

In combination with runtime.GetG, which obtains the current goroutine pointer, this allows to park an arbitrary goroutine and asynchronously wake it from an execution context outside the Go runtime, such as an interrupt service routine (ISR) vector.

This enables the following pattern to implement ISRs:

func ServiceInterrupts(isr func(id int)) {
	irqHandlerG, _ = runtime.GetG()

	// irqHandlerG gets registered to be woken up by runtime.WakeG with
	// architecture specific code, see tamago/{amd64|arm}/irq.{go|s}

	for {
		// re-enable interrupts after we get parked
		go irq_enable()

		// sleep indefinitely until woken up by runtime.WakeG
		time.Sleep(math.MaxInt64)

		// handle interrupts
		isr(id)
	}
}

To reduce power consumption when the CPU is idle, tamago amd64 and arm packages use the optional runtime.Idle function to halt the processor until an interrupt is received when no runtime activity is scheduled in the future.

Interrupts (AMD64)

On AMD/Intel 64-bit architecture interrupts are supported with the following helpers:

  • Packages lapic and ioapic provides a driver for Intel Local (LAPIC) and I/O (IOAPIC) Advanced Programmable Interrupt Controllers.

  • Package pci provides support for MSI-X.

  • Function ServiceInterrupts allows registration of a goroutine as IRQ handler.

The following projects provide an example use of such helpers:

Interrupts (ARM)

On the ARM architecture interrupts are supported with the following helpers:

  • Package gic, provides a driver for the ARM Generic Interrupt Controller.

  • Function ServiceInterrupts, allows registration of a goroutine as IRQ handler.

  • Function SetAlarm, allows registration of a physical countdown timer to raise an interrupt at a specific time.

  • Peripheral drivers functions to enable specific controller IRQs as needed, such as NXP ENET Ethernet driver.

The following projects provide an example use of such helpers:

Platform support packages

Processor support packages

Applications

External drivers

Clone this wiki locally