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
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 nop
s 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") }
}
}