Skip to content

Raspberry Pi Hardware

thanos edited this page Mar 23, 2021 · 6 revisions

Raspberry Pi Hardware

Pi Models

There are many versions of Raspberry Pi boards, each with each own characteristics, but many share a lot of similarities.

The main classification that can be done for the different models, is based on their Broadcom chip, their ARM Core, and their ARM Architecture.

  • The Broadcom chip mainly determines the Peripherals of the boards, their addresses and their function.
    • BCM2835, BCM2836, BCM2837 have pretty much the same architecture and they share the same datasheet with some differences in the ARM-local peripherals, because of the different ARM Cores used.
    • BCM2711 is a considerable on the previous ones and it has its own datasheet.
  • The ARM Core mainly determines the ARM-local peripherals of each board, its speed and multicore support.
  • The ARM Architecture determines the Instruction Set and as so the support for 32-bit or 64-bit architectures.
    • ARMv6 and ARMv7-A are 32-bit architectures with many similarities.
    • ARMv8-A is a newer architecture family that has support for both 32-bit or 64-bit instruction sets (AArch32 & AArch64).

Here is a table that compares all the different characteristics of each model:

Specs / Pi Vers. Pi Zero - Pi Zero W Pi 2 Pi 3 Pi 4
Broadcom Chip BCM2835 BCM2836 BCM2837 BCM2711
ARM Core ARM1176JZF-S Cortex-A7 Cortex A53 Cortex A72
ARM Core Family ARM11 Cortex-A Cortex-A Cortex-A
ARM Architecture ARMv6 ARMv7-A ARMv8-A ARMv8-A
Cores Single core Quad Core Quad Core Quad Core
ISA Support Arch - AArch32 AArch32 & AArch64 AArch32 & AArch64
Instruction Set 32 + 16 bit 32 + 16 bit 64 + 32 bit 64 + 32 bit
Thumb Support Thumb2 (T32) Thumb2 (T32) - -
FPU VFPv2 VFPv4 VFPv4 VFPv4
NEON (SIMD) - 64-bit wide 128-bit wide 128-bit wide

Pi Addresses

All peripherals communicate in memory with the CPU. Each has it's dedicated memory address starting from 0x7E000000, but it's not in real RAM, it is what is called Memory Mapped IO.

The starting peripheral address for each board maps to different physical addresses based on the chip. So any reference at the datasheets for peripheral addresses that are advertised as 0x7Ennnnnn bus addresses are:

  • For Pi Zero - Pi Zero W:
    • Mapped to 0x20nnnnnn physical addresses (With starting address: 0x20000000).
  • For Pi 2, Pi 3:
    • Mapped to 0x3Fnnnnnn physical addresses (With starting address: 0x3F000000).
  • For Pi 4:
    • Mapped to 0xFEnnnnnn physical addresses (With starting address: 0xFE000000).

Pi Uart

The UART is a hardware device for asynchronous serial communication in which the data format and transmission speeds are configurable. It is a very useful interface for bare-metal applications or kernel development as it is the main form of input and output with the device, through serial communication, so it is usually the first thing that gets implemented in the kernel in order to send and receive messages to/from the application.

In order to have a sucessful UART connection, usually there are two connections needed:

  • An Rx pin, that receives serial data.
  • An Tx pin, that transmits serial data.

The two devices that want to communicate, connect each of their Rx, Tx pin to the opposite pin of the other device.

There are two types of UART available on the Raspberry Pi - PL011 and mini UART. The PL011 is a capable, broadly 16550-compatible UART, while the mini UART has a reduced feature set.

Pi Zero, 1, 2 and 3 - two UARTs

The Raspberry Pi Zero, 1, 2, and 3 each contain two UARTs as follows:

Name Type
UART0 PL011
UART1 mini UART

Pi 4 - six UARTS

The Raspberry Pi 4 has four additional PL011s, which are disabled by default. The full list of UARTs on the Pi 4 is:

Name Type
UART0 PL011
UART1 mini UART
UART2 PL011
UART3 PL011
UART4 PL011
UART5 PL011

Primary UART

On the Raspberry Pi, one UART is selected to be present on GPIO 14 (transmit) and GPIO 15 (receive) - this is the primary UART. By default, this will also be the UART on which a Linux console may be present. Note that GPIO 14 is pin 8 on the GPIO header, while GPIO 15 is pin 10.

Secondary UART

The secondary UART is not normally present on the GPIO connector. By default, the secondary UART is connected to the Bluetooth side of the combined wireless LAN/Bluetooth controller, on models which contain this controller.

Configuration

By default, only UART0 is enabled. The following table summarises the assignment of the first two UARTs:

Model first PL011 (UART0) mini UART
Raspberry Pi Zero primary secondary
Raspberry Pi Zero W secondary (Bluetooth) primary
Raspberry Pi 1 primary secondary
Raspberry Pi 2 primary secondary
Raspberry Pi 3 secondary (Bluetooth) primary
Raspberry Pi 4 secondary (Bluetooth) primary

Note: the mini UART is disabled by default, whether it is designated primary or secondary UART.

Linux devices on Raspberry Pi OS

From the perspective of a Linux host, each UART device is shown differently in the /dev directory:

Linux device Description
/dev/ttyS0 mini UART
/dev/ttyAMA0 first PL011 (UART0)
/dev/serial0 primary UART
/dev/serial1 secondary UART

Differences between PL011 and mini UART

The mini UART has smaller FIFOs. Combined with the lack of flow control, this makes it more prone to losing characters at higher baudrates. It is also generally less capable than a PL011, mainly due to its baud rate link to the VPU clock speed.

The particular deficiencies of the mini UART compared to a PL011 are:

  • No break detection
  • No framing errors detection
  • No parity bit
  • No receive timeout interrupt
  • No DCD, DSR, DTR or RI signals

But the mini UART is more easy to setup and configure, so it is the prefered choice as a first form of UART communication.

Set Up mini UART

There are different configurations that need to be set up in order to use the mini UART for each Pi board. For the boards that have the mini UART as a secondary interface we need to set, we need to activate them and select the pin's alternative function 5 in order to make them work for UART 1 which is the mini UART, the primary UART for the Raspberry Pi Zero W, Raspberry Pi 3, Raspberry Pi 4.

Also for the Raspberry Pi 3 and Pi 4, in order to use the mini UART, we need to configure the Raspberry Pi to use a fixed VPU core clock frequency. This is because the mini UART clock is linked to the VPU core clock, so that when the core clock frequency changes, the UART baud rate will also change.

The core_freq=500 setting can be added to config.txt, in order to force the core clock to a fixed frequency of 500MHz, to change the behaviour of the mini UART.

UART Addresses

Specifically for the UART the physical addresses for each board are the following:

Specs / Pi Vers. Pi Zero - Pi Zero W Pi 2 - Pi 3 Pi 4
MMIO_BASE 0x20000000 0x3F000000 0xFE000000
GPIO_BASE 0x20200000 0x3F200000 0xFE200000
UART_BASE 0x20201000 0x3F201000 0xFE201000

Pi config.txt

We mentioned earlier a file called config.txt. This file we can set the system configuration parameters, which would traditionally be edited and stored using a BIOS.

This is read by the GPU before the ARM CPU and the kernel are initialised. It must therefore be located on the first (boot) partition of the SD card, alongside bootcode.bin and start.elf.

In the following sections, this file will be refernced in order to set some needed configurations.

Pi Interrupts

Devices usually don't interrupt processor directly: instead, they rely on interrupt controller to do the job. Interrupt controller can be used to enable/disable interrupts sent by the hardware. We can also use interrupt controller to figure out which device generates an interrupt.

Raspberry PI has its own interrupt controller that is described on page 109 of BCM2835 ARM Peripherals manual and page 83 of BCM2711 ARM Peripherals manual.

The interrupt controllers for each chip are somewhat different, so we are going to examine each controller differently.

BCM2835

The base address for the ARM interrupt register is 0x7E00B000.

Registers overview:

Address offset Name
0x200 IRQ basic pending
0x204 IRQ pending 1
0x208 IRQ pending 2
0x20C FIQ control
0x210 Enable IRQs 1
0x214 Enable IRQs 2
0x218 Enable Basic IRQs
0x21C Disable IRQs 1
0x220 Disable IRQs 2
0x224 Disable Basic IRQs

The table in page 113, lists all interrupts which can come from the peripherals which can be handled by the ARM.

ARM peripherals interrupts table is broken into to banks:

  • Bank 1: 0 - 31
  • Bank 2: 32 - 63

In page 113, IRQ 0-3 are system timer interrupts 0-3, and are missing from the table, source.

Raspberry Pi interrupt controller has 3 registers (1, 2, Basic) that hold enabled/disabled status for all types of interrupts.

The Basic IRQs are some common interrupts together with ARM local interrupts, and are defined from the ARM peripherals interrupts table:

# ARM peripherals interrupts
0 ARM Timer
1 ARM Mailbox
2 ARM Doorbell 0
3 ARM Doorbell 1
4 GPU0 halted (Or GPU1 halted if bit 10 of control register 1 is set)
5 GPU1 halted
6 Illegal access type 1
7 Illegal access type 0

Timer Interrupts

If we are interested in system timer interrupts, they are at lines 0 - 3 of the table in page 113, so they are in Bank 1.

We can enable system timer interrupts, by setting the bits 0-3 of IRQ enable 1 register at 0x210 according to the timer we want:

ENABLE_IRQS_1 = (1 << 0)    // System Timer Compare 0
ENABLE_IRQS_1 = (1 << 1)    // System Timer Compare 1
ENABLE_IRQS_1 = (1 << 2)    // System Timer Compare 2
ENABLE_IRQS_1 = (1 << 3)    // System Timer Compare 3

In the same maner we can disable the interrupts for system timers, by setting the bits 0-3 of IRQ disable 1 register at 0x21C according to the timer we want:

DISABLE_IRQS_1 = (1 << 0)    // System Timer Compare 0
DISABLE_IRQS_1 = (1 << 1)    // System Timer Compare 1
DISABLE_IRQS_1 = (1 << 2)    // System Timer Compare 2
DISABLE_IRQS_1 = (1 << 3)    // System Timer Compare 3

BCM2711

The BCM2711 has a large number of interrupts from various sources, and a choice of two interrupt controllers. The GIC-400 interrupt controller is selected by default, but the legacy interrupt controller can be selected with a setting in config.txt.

In the VideoCore interrupts table at page 85, we can see all the peripheral interrupts that we might be interested in:

# IRQ 0-15 # IRQ 16-31 # IRQ 32-47 # IRQ 48-63
0 Timer 0 16 DMA 0 32 HDMI CEC 48 SMI
1 Timer 1 17 DMA 1 33 HVS 49 GPIO 0
2 Timer 2 18 DMA 2 34 RPIVID 50 GPIO 1
3 Timer 3 19 DMA 3 35 SDC 51 GPIO 2
4 H264 0 20 DMA 4 36 DSI 0 52 GPIO 3
5 H264 1 21 DMA 5 37 Pixel Valve 2 53 OR of all I2C
6 H264 2 22 DMA 6 38 Camera 0 54 OR of all SPI
7 JPEG 23 DMA 7 & 8 39 Camera 1 55 PCM/I2S
8 ISP 24 DMA 9 & 10 40 HDMI 0 56 SDHOST
9 USB 25 DMA 11 41 HDMI 1 57 OR of all PL011 UART
10 V3D 26 DMA 12 42 Pixel Valve 3 58 OR of all ETH_PCIe L2
11 Transposer 27 DMA 13 43 SPI/BSC Slave 59 VEC
12 Multicore Sync 0 28 DMA 14 44 DSI 1 60 CPG
13 MultiCore Sync 1 29 AUX 45 Pixel Valve 0 61 RNG
14 MultiCore Sync 2 30 ARM 46 Pixel Valve 1 & 4 62 EMMC & EMMC2
15 MultiCore Sync 3 31 DMA 15 47 CPR 63 ETH_PCIe secure

The ARMC register base address is 0x7E00B000 (the same as the BCM2835).

There are 4 cores in the ARM processor (n = 0,1,2,3), and there are 4 diferrent exceptions to be handled:

  • IRQ
  • FIQ
  • SWIR

We have set and clear registers responsible for the masking and unmasking of the exceptions, for each core and interrupt:

  • IRQn_SET_EN_x
  • IRQn_CLR_EN_x
  • FIQn_SET_EN_x
  • FIQn_CLR_EN_x
  • SWIRQ_SET
  • SWIRQ_CLEAR

We are interested in the IRQ interrupts and only for one core (core 0) so here is the table (page 98) that describes the function of each register and its offset from the ARMC register base address:

Offset Name Description
0x200 IRQ0_PENDING0 ARM Core 0 IRQ Enabled Interrupt Pending bits [31:0]
0x204 IRQ0_PENDING1 ARM Core 0 IRQ Enabled Interrupt pending bits [63:32]
0x208 IRQ0_PENDING2 ARM Core 0 IRQ Enabled Interrupt pending bits [79:64]
0x210 IRQ0_SET_EN_0 Write to Set ARM Core 0 IRQ enable bits [31:0]
0x214 IRQ0_SET_EN_1 Write to Set ARM Core 0 IRQ enable bits [63:32]
0x218 IRQ0_SET_EN_2 Write to Set ARM Core 0 IRQ enable bits [79:64]
0x220 IRQ0_CLR_EN_0 Write to Clear ARM Core 0 IRQ enable bits [31:0]
0x224 IRQ0_CLR_EN_1 Write to Clear ARM Core 0 IRQ enable bits [63:32]
0x228 IRQ0_CLR_EN_2 Write to Clear ARM Core 0 IRQ enable bits [79:64]

Timer Interrupts

If we are interested in system timer interrupts, they are at lines 0 - 3 of the table, so they are in Bank 0.

We can enable system timer interrupts, by setting the bits 0-3 of IRQ0_SET_EN_0 register at 0x210 according to the timer we want:

IRQ0_SET_EN_0 = (1 << 0)    // System Timer Compare 0
IRQ0_SET_EN_0 = (1 << 1)    // System Timer Compare 1
IRQ0_SET_EN_0 = (1 << 2)    // System Timer Compare 2
IRQ0_SET_EN_0 = (1 << 3)    // System Timer Compare 3

In the same maner we can disable the interrupts for system timers, by setting the bits 0-3 of IRQ0_CLR_EN_0 register at 0x220 according to the timer we want:

IRQ0_CLR_EN_0 = (1 << 0)    // System Timer Compare 0
IRQ0_CLR_EN_0 = (1 << 1)    // System Timer Compare 1
IRQ0_CLR_EN_0 = (1 << 2)    // System Timer Compare 2
IRQ0_CLR_EN_0 = (1 << 3)    // System Timer Compare 3

Pi Timer

The System Timer on the Pi's uses a different clock frequence from the ARM cpu and it is 1MHz.

The System Timer peripheral provides four 32-bit timer channels (n = 0,1,2,3) and a single 64-bit free running counter. Each channel has an output compare register (Cn), which is compared against the 32 least significant bits of the free running counter values.

The 4 output compare register for each channel:

  • System Timer 0: C0
  • System Timer 1: C1
  • System Timer 2: C2
  • System Timer 3: C3

System Timer 0 and 2 are not usable for us, because they are being used internally for the GPU (VideoCore device).

The 2 32-bit registers for the single 64-bit free running counter:

  • CLO
  • CHI

When the two values match (Cn with CL0), the system timer peripheral generates a signal to indicate a match for the appropriate channel. The match signal is then fed into the interrupt controller. Totally 4 different interrupts can be generated from the 4 channels.

The interrupt service routine then reads the output compare register and adds the appropriate offset for the next timer tick.

The free running counter is driven by the timer clock and stopped whenever the processor is stopped in debug mode.

The System Timer Registers are defined in page 172 of BCM2835 ARM Peripherals manual and page 140 of BCM2711 ARM Peripherals manual:

Offset Name Description
0x00 CS System Timer Control/Status
0x04 CLO System Timer Counter Lower 32 bits
0x08 CHI System Timer Counter Higher 32 bits
0x0c C0 System Timer Compare 0
0x10 C1 System Timer Compare 1
0x14 C2 System Timer Compare 2
0x18 C3 System Timer Compare 3

The System Timer Control / Status CS register, is used to record and clear timer channel comparator matches. The system timer match bits are routed to the interrupt controller where they can generate an interrupt.

The M0-3 fields contain the free-running counter match status.

We write a one to the relevant bit to clear the match detect status bit and the corresponding interrupt request line.

If we are using System Timer 1, in the interrupt handler we set the bit M1 to 1:

TIMER_CS = (1 << 1)

Pi Gpio

There are 54 general-purpose I/O (GPIO) lines split into two banks for thre BCM2835 chip and 57 for the BCM2711. All GPIO pins have at least two alternative functions within BCM. The alternate functions are usually peripheral IO and a single peripheral may appear in each bank to allow flexibility on the choice of IO voltage.

The GPIO pins have some dedicated registers, the main ones are responsible for doing the following:

  • Setting pins High
  • Clearing pins Low
  • Defining the operation of the pin (Alternative Functions)
  • Control the actuation of internal pull-downs resistors.

Set - Clear Pins

The registers responible for setting and clearing the pins are the following:

Name Description
GPSET0 The GPSET0 register is used to set GPIO pins 0-31
GPSET1 The GPSET1 register is used to set GPIO pins 32-53
GPCLR0 The GPCLR0 register is used to clear GPIO pins 0-31
GPCLR1 The GPCLR1 register is used to clear GPIO pins 32-53

Alternative Functions

Most of the pins can be used with different devices, so before using a particular pin, we need to select the pin's alternative function. An alternative function is just a number from 0 to 5 that can be set for each pin and configures which device is connected to the pin.

All available GPIO alternative functions are the following:

  • 000 = GPIO Pin 9 is an input
  • 001 = GPIO Pin 9 is an output
  • 100 = GPIO Pin 9 takes alternate function 0
  • 101 = GPIO Pin 9 takes alternate function 1
  • 110 = GPIO Pin 9 takes alternate function 2
  • 111 = GPIO Pin 9 takes alternate function 3
  • 011 = GPIO Pin 9 takes alternate function 4
  • 010 = GPIO Pin 9 takes alternate function 5
Name Description
GPFSEL0 GPIO Function Select 0,1,2,3,4,5 for pins 0-9
GPFSEL1 GPIO Function Select 0,1,2,3,4,5 for pins 10-19
GPFSEL2 GPIO Function Select 0,1,2,3,4,5 for pins 20-29
GPFSEL3 GPIO Function Select 0,1,2,3,4,5 for pins 30-39
GPFSEL4 GPIO Function Select 0,1,2,3,4,5 for pins 40-49
GPFSEL5 GPIO Function Select 0,1,2,3,4,5 for pins 50-59

Gpio pull-up/down

These registers are used to control the pull-up/pull-down state of the pin. There are three available states: pull-up, pull-down, and neither (to remove the current pull-up or pull-down state).

The registers and their function have changed from the BCM2835 to the BCM2711 chip.

BCM2835

It has 3 registers:

Name Description
GPPUD Controls actuation of pull up/down to ALL GPIO pins
GPPUDCLK0 Controls actuation of pull up/down for GPIO pins 0-31
GPPUDCLK1 Controls actuation of pull up/down for GPIO pins 32-53

The GPPUD who is responsible for controlling the pull-up/pull-down state of all pins, can take the following values:

  • 00 = Off - disable pull-up/down
  • 01 = Enable Pull Down control
  • 10 = Enable Pull Up control
  • 11 = Reserved

The GPPUDCLK0-1 registers are used in conjunction with the GPPUD register to effect GPIO Pull-up/down changes for each pin, and they can take the following values:

  • 0 = No Effect
  • 1 = Assert Clock on line (n)

BCM2711

In this chip, we have the following 4 registers that control the actuation of the internal pull-up/down resistors for each pin:

Name Description
GPIO_PUP_PDN_CNTRL_REG0 Controls actuation of pull up/down for GPIO pins 0-15
GPIO_PUP_PDN_CNTRL_REG1 Controls actuation of pull up/down for GPIO pins 16-31
GPIO_PUP_PDN_CNTRL_REG2 Controls actuation of pull up/down for GPIO pins 32-47
GPIO_PUP_PDN_CNTRL_REG3 Controls actuation of pull up/down for GPIO pins 48-57

Each can take the following values:

  • 00 = No resistor is selected
  • 01 = Pull up resistor is selected
  • 10 = Pull down resistor is selected
  • 11 = Reserved

Pi Led

Blinking an LED for the Pi, is just a matter of manipulating the GPIO pins. In order to light an a LED we have to set a specific pin and in order to turn it off, we need to clear the pin. Also, we need to define that the pin is set as an output, by choosing the correct alternative function for the pin.

Onboard LEDs

We can blink the following onboard LEDs for each model, using a GPIO PIN:

  • Pi 1 Models A and B

    • The green activity LED (GPIO 16) may be written.
  • Pi 1 Models A+ and B+

    • The green activity LED (GPIO 47) may be written.
    • The red power LED (GPIO 35) may be written.
    • The high USB power mode (GPIO 38) may be written.
  • Pi Zero and Pi Zero W

    • The green activity LED (GPIO 47) may be written.
  • Pi 2

    • The green activity LED (GPIO 47) may be written.
    • The red power LED (GPIO 35) may be written.
    • The high USB power mode (GPIO 38) may be written.
  • Pi 3

    • The green activity LED writeable via mailbox .. as GPIO 130
  • Pi 3 B+

    • The green activity LED (GPIO 29) may be written

Source for this info

If we want ot move the function of ACT LED to other GPIO pin, we can set the following in config.txt:

dtoverlay=act-led,gpio=17

On Raspberry Pi Zero the LED has inverted logic:

  • We CLR its pin in order to turn it on.
  • We SET its pin in order to turn it off.

In order to invert that, we can set the following in config.txt:

dtparam=act_led_trigger=none
dtparam=act_led_activelow=on

External LEDs to GPIO

For Raspberry Pi 4 (and Pi 3), we can easily connect an external LED to a free GPIO PIN and control that. A full pinout for the Pi. From there select a GPIO PIN that preferably has not any other function. Such as GPIO PIN 17 (Physical PIN 11).

In order to connect it to the Pi, you need:

  • 2 jumber wires
  • An LED
  • An 330 Ω resistor

The shorter leg (known as the ‘cathode’) is connected to the negative side of the power supply, known as ‘ground.

We have the following connections:

  • Connect GPIO PIN 17 (physical pin 11), to the anode of the LED (positive side - the longer leg).
  • Connect GRND PIN (physical pin 9), to the resistor
  • Connect the other end of the resistor to the cathode of the LED(negative side - the shorter leg).

Resistor 330Ω color band:

  • If there are four colour bands, they will be:
    • Orange, Orange, Brown, and then Gold.
  • If there are five bands, then the colours will be:
    • Orange, Orange, Black, Black, Brown.

References

Previous Page

ARM Arch

Next Page

Implementation Docs

Clone this wiki locally