rust-raspberrypi-OS-tutorials/06_drivers_gpio_uart
2020-03-28 13:26:38 +01:00
..
.vscode Switch to rust-analyzer 2020-03-10 23:40:04 +01:00
src Refactor tutorial 06 2020-03-28 13:26:38 +01:00
Cargo.lock Bump to register 0.5.x 2020-01-16 22:06:43 +01:00
Cargo.toml Bump to register 0.5.x 2020-01-16 22:06:43 +01:00
kernel Refactor tutorial 06 2020-03-28 13:26:38 +01:00
kernel8.img Refactor tutorial 06 2020-03-28 13:26:38 +01:00
Makefile Refactor tutorial 06 2020-03-28 13:26:38 +01:00
README.md Refactor tutorial 06 2020-03-28 13:26:38 +01:00

Tutorial 06 - Drivers: GPIO and UART

tl;dr

Now that we enabled safe globals in the previous tutorial, the infrastructure is laid for adding the first real device drivers. We throw out the magic QEMU console and use a real UART now. Like serious embedded hackers do!

Notable additions

  • For the first time, we will be able to run the code on the real hardware.
    • Therefore, building is now differentiated between the RPi 3 and the RPi4.
    • By default, all Makefile targets will build for the RPi 3.
    • In order to build for the the RPi4, prepend BSP=rpi4 to each target. For example:
      • BSP=rpi4 make
      • BSP=rpi4 make doc
    • Unfortunately, QEMU does not yet support the RPi4, so BSP=rpi4 make qemu won't work.
  • A driver::interface::DeviceDriver trait is added for abstracting BSP driver implementations from kernel code.
  • Drivers are stored in src/bsp/device_driver, and can be reused between BSPs.
    • We introduce the GPIO driver, which pinmuxes the RPi's PL011 UART.
    • Most importantly, the PL011Uart driver: It implements the console::interface::* traits and is from now on used as the main system console output.
  • BSPs now contain a memory map in src/bsp/memory.rs. In the specific case, they contain the Raspberry's MMIO addresses which are used to instantiate the respectivedevice drivers.
  • We also modify the panic! handler, so that it does not anymore rely on println!, which uses the globally-shared instance of the UART that might be locked when an error is encountered (for now this can't happen due to the NullLock, but with a real lock it becomes an issue).
    • Instead, it creates a new UART driver instance, re-initializes the device and uses that one to print. This increases the chances that the system is able to print a final important message before it suspends itself.

Boot it from SD card

Some steps for preparing the SD card differ between RPi3 and RPi4, so be careful.

Common for both

  1. Make a single FAT32 partition named boot.
  2. On the card, generate a file named config.txt with the following contents:
init_uart_clock=48000000

Pi 3

  1. Copy the following files from the Raspberry Pi firmware repo onto the SD card:
  2. Run make and copy the kernel8.img onto the SD card.

Pi 4

  1. Copy the following files from the Raspberry Pi firmware repo onto the SD card:
  2. Run BSP=rpi4 make and copy the kernel8.img onto the SD card.

Note: Should it not work on your RPi4, try renaming start4.elf to start.elf (without the 4) on the SD card.

Common again

  1. Insert the SD card into the RPi and connect the USB serial to your host PC.
  2. Run screen (you might need to install it first):
sudo screen /dev/ttyUSB0 230400
  1. Hit Enter to kick off the kernel boot process. Observe the output:
[0] Booting on: Raspberry Pi 3
[1] Drivers loaded:
      1. BCM GPIO
      2. BCM PL011 UART
[2] Chars written: 93
[3] Echoing input now
  1. Exit screen by pressing ctrl-a ctrl-d or disconnecting the USB serial.

Diff to previous