In some cases we may want information from the Raspberry without having to look at the UART output. In this case we can use either the green activitiy LED or an external LED connected via the pins.

After some research I could figure out that the ACT LED can be set via the GPIO29 on a Raspberry PI 3B+. When using an external LED, choose a GPIO pin that is not in use(ex. GPIO17).

Step 0: Setting up the GPIO Link to heading

Note: This is not needed for GPIO29

Here we just have to go the same route as mentioned in previos section by setting the GPIO function. Instead of ALT0 we will use output which is 001 in binary.

Step 1: Changing state Link to heading

To set the GPIO low and high, broadcom gives us 2 register types; GPCLRn to pull a pin to ground(0V); GPSETn to pull a pin high(3.3V).

Each register typ has 2 x 32bit registers with each bit representing a GPIO pin, except bit 22-31 in the second register. Setting a bit to 1 in GPCLRn will pull the pin down. Setting a bit to 1 in GPSETn will pull the pin up. Setting 0 has no effect.

Field Name Physical Address
GPSET0 0x3F20001C
GPSET1 0x3F200020
GPCLR0 0x3F200028
GPCLR1 0x3F20002C

GPCLR0 Link to heading

Bits Field Name Description
31-0 CLRn (n=0..31) 1 = Clear GPIO pin n; 0 = No effect

GPCLR1 Link to heading

Bits Field Name Description
31-22 - Reserved
21-0 CLRn (n=32..53) 1 = Clear GPIO pin n; 0 = No effect

GPSET0 Link to heading

Bits Field Name Description
31-0 SETn (n=0..31) 1 = Clear GPIO pin n; 0 = No effect

GPSET1 Link to heading

Bits Field Name Description
31-22 - Reserved
21-0 SETn (n=32..53) 1 = Set GPIO pin n.; 0 = No effect

Step 3: Clock Link to heading

To keep track of time the broadcom chip has a System Timer that allows us to keep track of time in micro seconds.

At 0x3F003000 we have multiple registers again that let us interact with the system timer. For now only CLO(Lower 32 bit clock) and CHI(Higher 32 bit clock) are important. Together it gives us 64 bits of accuarte time tracking. But CLO should already be enough because it allows us to track time of up to 2147483647μs equaling 2147 seconds.

For now we can call nops while waiting for our delay to run out:

pub fn sleep_us(us: u32) {
    let start = read_clo();
    while read_clo() - start < us {
        unsafe { core::arch::asm!("nop") }
    }
}

Git Repository Link to heading