master 31fc1481f529 cached
2526 files
2.7 MB
845.2k tokens
2309 symbols
1 requests
Download .txt
Showing preview only (3,305K chars total). Download the full file or copy to clipboard to get everything.
Repository: s-matyukevich/raspberry-pi-os
Branch: master
Commit: 31fc1481f529
Files: 2526
Total size: 2.7 MB

Directory structure:
gitextract_cgeajq_d/

├── .gitignore
├── Dockerfile
├── LICENSE
├── README.md
├── _config.yml
├── _layouts/
│   └── default.html
├── assets/
│   └── css/
│       └── style.scss
├── docs/
│   ├── Contributions.md
│   ├── Introduction.md
│   ├── Prerequisites.md
│   ├── lesson01/
│   │   ├── exercises.md
│   │   ├── linux/
│   │   │   ├── build-system.md
│   │   │   ├── kernel-startup.md
│   │   │   └── project-structure.md
│   │   └── rpi-os.md
│   ├── lesson02/
│   │   ├── exercises.md
│   │   ├── linux.md
│   │   └── rpi-os.md
│   ├── lesson03/
│   │   ├── exercises.md
│   │   ├── linux/
│   │   │   ├── interrupt_controllers.md
│   │   │   ├── low_level-exception_handling.md
│   │   │   └── timer.md
│   │   └── rpi-os.md
│   ├── lesson04/
│   │   ├── exercises.md
│   │   ├── linux/
│   │   │   ├── basic_structures.md
│   │   │   ├── fork.md
│   │   │   └── scheduler.md
│   │   └── rpi-os.md
│   ├── lesson05/
│   │   ├── exercises.md
│   │   ├── linux.md
│   │   └── rpi-os.md
│   └── lesson06/
│       ├── exercises.md
│       └── rpi-os.md
├── exercises/
│   ├── lesson01/
│   │   ├── 1/
│   │   │   ├── H-4ND-H/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       └── utils.S
│   │   │   ├── a-v-v/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       └── utils.S
│   │   │   ├── adkaster/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       └── utils.S
│   │   │   ├── avenito/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       └── utils.S
│   │   │   ├── bl4ckout31/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       └── utils.S
│   │   │   ├── evopen/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.sh
│   │   │   │   ├── config.txt
│   │   │   │   ├── include/
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── kernel_main.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       └── utils.S
│   │   │   ├── gcrisis/
│   │   │   │   ├── Makefile
│   │   │   │   ├── include/
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       └── utils.S
│   │   │   ├── rs/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       └── utils.S
│   │   │   ├── stefanji/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       └── utils.S
│   │   │   ├── xdfm1/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       └── utils.S
│   │   │   └── zjd0112/
│   │   │       ├── Makefile
│   │   │       ├── build.bat
│   │   │       ├── build.sh
│   │   │       ├── include/
│   │   │       │   ├── mini_uart.h
│   │   │       │   ├── mm.h
│   │   │       │   ├── peripherals/
│   │   │       │   │   ├── base.h
│   │   │       │   │   ├── gpio.h
│   │   │       │   │   └── mini_uart.h
│   │   │       │   └── utils.h
│   │   │       └── src/
│   │   │           ├── boot.S
│   │   │           ├── config.txt
│   │   │           ├── kernel.c
│   │   │           ├── linker.ld
│   │   │           ├── mini_uart.c
│   │   │           ├── mm.S
│   │   │           └── utils.S
│   │   ├── 2/
│   │   │   ├── H-4ND-H/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── uart_pl011.h
│   │   │   │   │   ├── uart_pl011.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mm.S
│   │   │   │       ├── uart_pl011.c
│   │   │   │       └── utils.S
│   │   │   ├── a-v-v/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── uart.h
│   │   │   │   │   ├── uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mm.S
│   │   │   │       ├── uart.c
│   │   │   │       └── utils.S
│   │   │   ├── adkaster/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   │   └── uart.h
│   │   │   │   │   ├── uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       ├── uart.c
│   │   │   │       └── utils.S
│   │   │   ├── avenito/
│   │   │   │   ├── Makefile
│   │   │   │   ├── README.md
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── uart.h
│   │   │   │   │   ├── uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mm.S
│   │   │   │       ├── uart.c
│   │   │   │       └── utils.S
│   │   │   ├── bl4ckout31/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── uart.h
│   │   │   │   │   ├── uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mm.S
│   │   │   │       ├── uart.c
│   │   │   │       └── utils.S
│   │   │   ├── evopen/
│   │   │   │   ├── .gitignore
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.sh
│   │   │   │   ├── config.txt
│   │   │   │   ├── include/
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   │   └── uart.h
│   │   │   │   │   ├── uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   ├── src/
│   │   │   │   │   ├── boot.S
│   │   │   │   │   ├── kernel.c
│   │   │   │   │   ├── linker-qemu.ld
│   │   │   │   │   ├── linker.ld
│   │   │   │   │   ├── mm.S
│   │   │   │   │   ├── uart.c
│   │   │   │   │   └── utils.S
│   │   │   │   └── start.sh
│   │   │   ├── gcrisis/
│   │   │   │   ├── Makefile
│   │   │   │   ├── include/
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── uart.h
│   │   │   │   │   ├── uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   ├── src/
│   │   │   │   │   ├── boot.S
│   │   │   │   │   ├── config.txt
│   │   │   │   │   ├── kernel.c
│   │   │   │   │   ├── linker.ld
│   │   │   │   │   ├── mm.S
│   │   │   │   │   ├── uart.c
│   │   │   │   │   └── utils.S
│   │   │   │   └── uart-boot/
│   │   │   │       ├── Makefile
│   │   │   │       ├── downloader/
│   │   │   │       │   └── raspiloader.c
│   │   │   │       ├── include/
│   │   │   │       │   ├── mm.h
│   │   │   │       │   ├── peripherals/
│   │   │   │       │   │   ├── base.h
│   │   │   │       │   │   ├── gpio.h
│   │   │   │       │   │   └── uart.h
│   │   │   │       │   ├── uart.h
│   │   │   │       │   └── utils.h
│   │   │   │       ├── readme
│   │   │   │       └── src/
│   │   │   │           ├── boot.S
│   │   │   │           ├── config.txt
│   │   │   │           ├── linker.ld
│   │   │   │           ├── main.c
│   │   │   │           ├── mm.S
│   │   │   │           ├── uart.c
│   │   │   │           └── utils.S
│   │   │   ├── rs/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── uart.h
│   │   │   │   │   ├── uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mm.S
│   │   │   │       ├── uart.c
│   │   │   │       └── utils.S
│   │   │   ├── stefanji/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── uart_pl011.h
│   │   │   │   │   ├── pl011_uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mm.S
│   │   │   │       ├── pl011_uart.c
│   │   │   │       └── utils.S
│   │   │   ├── xdfm1/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── uart.h
│   │   │   │   │   ├── uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mm.S
│   │   │   │       ├── uart.c
│   │   │   │       └── utils.S
│   │   │   └── zjd0112/
│   │   │       ├── Makefile
│   │   │       ├── build.bat
│   │   │       ├── build.sh
│   │   │       ├── include/
│   │   │       │   ├── mini_uart.h
│   │   │       │   ├── mm.h
│   │   │       │   ├── peripherals/
│   │   │       │   │   ├── base.h
│   │   │       │   │   ├── gpio.h
│   │   │       │   │   ├── mini_uart.h
│   │   │       │   │   └── pl011_uart.h
│   │   │       │   ├── pl011_uart.h
│   │   │       │   └── utils.h
│   │   │       └── src/
│   │   │           ├── boot.S
│   │   │           ├── config.txt
│   │   │           ├── kernel.c
│   │   │           ├── linker.ld
│   │   │           ├── mini_uart.c
│   │   │           ├── mm.S
│   │   │           ├── pl011_uart.c
│   │   │           └── utils.S
│   │   ├── 3/
│   │   │   ├── a-v-v/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       └── utils.S
│   │   │   ├── adkaster/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       └── utils.S
│   │   │   ├── avenito/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       └── utils.S
│   │   │   ├── bl4ckout31/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       └── utils.S
│   │   │   ├── evopen/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.sh
│   │   │   │   ├── config.txt
│   │   │   │   ├── include/
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       └── utils.S
│   │   │   ├── gcrisis/
│   │   │   │   ├── Makefile
│   │   │   │   ├── include/
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       └── utils.S
│   │   │   ├── rs/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       └── utils.S
│   │   │   ├── stefanji/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       └── utils.S
│   │   │   ├── szediwy/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       └── utils.S
│   │   │   └── zjd0112/
│   │   │       ├── Makefile
│   │   │       ├── build.bat
│   │   │       ├── build.sh
│   │   │       ├── include/
│   │   │       │   ├── mini_uart.h
│   │   │       │   ├── mm.h
│   │   │       │   ├── peripherals/
│   │   │       │   │   ├── base.h
│   │   │       │   │   ├── gpio.h
│   │   │       │   │   ├── mini_uart.h
│   │   │       │   │   └── pl011_uart.h
│   │   │       │   ├── pl011_uart.h
│   │   │       │   └── utils.h
│   │   │       └── src/
│   │   │           ├── boot.S
│   │   │           ├── config.txt
│   │   │           ├── kernel.c
│   │   │           ├── linker.ld
│   │   │           ├── mini_uart.c
│   │   │           ├── mm.S
│   │   │           ├── pl011_uart.c
│   │   │           └── utils.S
│   │   └── 4/
│   │       ├── H-4ND-H/
│   │       │   ├── Makefile
│   │       │   ├── build.bat
│   │       │   ├── build.sh
│   │       │   ├── include/
│   │       │   │   ├── mini_uart.h
│   │       │   │   ├── mm.h
│   │       │   │   ├── peripherals/
│   │       │   │   │   ├── base.h
│   │       │   │   │   ├── gpio.h
│   │       │   │   │   └── mini_uart.h
│   │       │   │   └── utils.h
│   │       │   └── src/
│   │       │       ├── boot.S
│   │       │       ├── config.txt
│   │       │       ├── kernel.c
│   │       │       ├── linker.ld
│   │       │       ├── mini_uart.c
│   │       │       ├── mm.S
│   │       │       └── utils.S
│   │       ├── a-v-v/
│   │       │   ├── Makefile
│   │       │   ├── build.bat
│   │       │   ├── build.sh
│   │       │   ├── include/
│   │       │   │   ├── mini_uart.h
│   │       │   │   ├── mm.h
│   │       │   │   ├── peripherals/
│   │       │   │   │   ├── base.h
│   │       │   │   │   ├── gpio.h
│   │       │   │   │   └── mini_uart.h
│   │       │   │   └── utils.h
│   │       │   ├── src/
│   │       │   │   ├── boot.S
│   │       │   │   ├── config.txt
│   │       │   │   ├── kernel.c
│   │       │   │   ├── linker.ld
│   │       │   │   ├── mini_uart.c
│   │       │   │   ├── mm.S
│   │       │   │   └── utils.S
│   │       │   └── start_qemu.sh
│   │       ├── avenito/
│   │       │   ├── Makefile
│   │       │   ├── build.bat
│   │       │   ├── build.sh
│   │       │   ├── include/
│   │       │   │   ├── mm.h
│   │       │   │   ├── peripherals/
│   │       │   │   │   ├── base.h
│   │       │   │   │   ├── gpio.h
│   │       │   │   │   └── uart.h
│   │       │   │   ├── uart.h
│   │       │   │   └── utils.h
│   │       │   └── src/
│   │       │       ├── boot.S
│   │       │       ├── config.txt
│   │       │       ├── kernel.c
│   │       │       ├── linker.ld
│   │       │       ├── mm.S
│   │       │       ├── uart.c
│   │       │       └── utils.S
│   │       ├── bl4ckout31/
│   │       │   ├── Makefile
│   │       │   ├── build.bat
│   │       │   ├── build.sh
│   │       │   ├── include/
│   │       │   │   ├── mm.h
│   │       │   │   ├── peripherals/
│   │       │   │   │   ├── base.h
│   │       │   │   │   ├── gpio.h
│   │       │   │   │   └── uart.h
│   │       │   │   ├── uart.h
│   │       │   │   └── utils.h
│   │       │   ├── src/
│   │       │   │   ├── boot.S
│   │       │   │   ├── config.txt
│   │       │   │   ├── kernel.c
│   │       │   │   ├── linker.ld
│   │       │   │   ├── mm.S
│   │       │   │   ├── uart.c
│   │       │   │   └── utils.S
│   │       │   └── start.sh
│   │       ├── evopen/
│   │       │   ├── .gitignore
│   │       │   ├── Makefile
│   │       │   ├── build.sh
│   │       │   ├── config.txt
│   │       │   ├── include/
│   │       │   │   ├── mm.h
│   │       │   │   ├── peripherals/
│   │       │   │   │   ├── base.h
│   │       │   │   │   ├── gpio.h
│   │       │   │   │   ├── mini_uart.h
│   │       │   │   │   └── uart.h
│   │       │   │   ├── uart.h
│   │       │   │   └── utils.h
│   │       │   ├── src/
│   │       │   │   ├── boot.S
│   │       │   │   ├── kernel.c
│   │       │   │   ├── linker-qemu.ld
│   │       │   │   ├── linker.ld
│   │       │   │   ├── mm.S
│   │       │   │   ├── uart.c
│   │       │   │   └── utils.S
│   │       │   └── start.sh
│   │       ├── rs/
│   │       │   ├── Makefile
│   │       │   ├── build.bat
│   │       │   ├── build.sh
│   │       │   ├── include/
│   │       │   │   ├── mini_uart.h
│   │       │   │   ├── mm.h
│   │       │   │   ├── peripherals/
│   │       │   │   │   ├── base.h
│   │       │   │   │   ├── gpio.h
│   │       │   │   │   └── mini_uart.h
│   │       │   │   └── utils.h
│   │       │   ├── src/
│   │       │   │   ├── boot.S
│   │       │   │   ├── config.txt
│   │       │   │   ├── kernel.c
│   │       │   │   ├── linker.ld
│   │       │   │   ├── mini_uart.c
│   │       │   │   ├── mm.S
│   │       │   │   └── utils.S
│   │       │   └── start.sh
│   │       └── stefanji/
│   │           └── run_on_qemu.sh
│   ├── lesson02/
│   │   ├── 1/
│   │   │   ├── H-4ND-H/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       ├── printf.c
│   │   │   │       └── utils.S
│   │   │   ├── avenito/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       ├── printf.c
│   │   │   │       └── utils.S
│   │   │   ├── bl4ckout31/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   └── utils.h
│   │   │   │   ├── src/
│   │   │   │   │   ├── boot.S
│   │   │   │   │   ├── config.txt
│   │   │   │   │   ├── kernel.c
│   │   │   │   │   ├── linker.ld
│   │   │   │   │   ├── mini_uart.c
│   │   │   │   │   ├── mm.S
│   │   │   │   │   ├── printf.c
│   │   │   │   │   └── utils.S
│   │   │   │   └── start.sh
│   │   │   ├── evopen/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── config.txt
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   └── utils.h
│   │   │   │   ├── src/
│   │   │   │   │   ├── boot.S
│   │   │   │   │   ├── config.txt
│   │   │   │   │   ├── kernel.c
│   │   │   │   │   ├── linker.ld
│   │   │   │   │   ├── mini_uart.c
│   │   │   │   │   ├── mm.S
│   │   │   │   │   ├── printf.c
│   │   │   │   │   └── utils.S
│   │   │   │   └── start.sh
│   │   │   ├── gcrisis/
│   │   │   │   ├── Makefile
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       ├── printf.c
│   │   │   │       └── utils.S
│   │   │   ├── rs/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       ├── printf.c
│   │   │   │       └── utils.S
│   │   │   └── zjd0112/
│   │   │       ├── Makefile
│   │   │       ├── build.bat
│   │   │       ├── build.sh
│   │   │       ├── include/
│   │   │       │   ├── arm/
│   │   │       │   │   └── sysregs.h
│   │   │       │   ├── mini_uart.h
│   │   │       │   ├── mm.h
│   │   │       │   ├── peripherals/
│   │   │       │   │   ├── base.h
│   │   │       │   │   ├── gpio.h
│   │   │       │   │   └── mini_uart.h
│   │   │       │   ├── printf.h
│   │   │       │   └── utils.h
│   │   │       └── src/
│   │   │           ├── boot.S
│   │   │           ├── config.txt
│   │   │           ├── kernel.c
│   │   │           ├── linker.ld
│   │   │           ├── mini_uart.c
│   │   │           ├── mm.S
│   │   │           ├── printf.c
│   │   │           └── utils.S
│   │   ├── 2/
│   │   │   ├── H-4ND-H/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       ├── printf.c
│   │   │   │       └── utils.S
│   │   │   ├── avenito/
│   │   │   │   ├── Makefile
│   │   │   │   ├── README.md
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── dis_with.txt
│   │   │   │   ├── dis_without.txt
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       ├── printf.c
│   │   │   │       └── utils.S
│   │   │   ├── bl4ckout31/
│   │   │   │   ├── Makefile
│   │   │   │   ├── avec
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   └── utils.h
│   │   │   │   ├── sans
│   │   │   │   ├── src/
│   │   │   │   │   ├── boot.S
│   │   │   │   │   ├── config.txt
│   │   │   │   │   ├── kernel.c
│   │   │   │   │   ├── linker.ld
│   │   │   │   │   ├── mini_uart.c
│   │   │   │   │   ├── mm.S
│   │   │   │   │   ├── printf.c
│   │   │   │   │   └── utils.S
│   │   │   │   └── start.sh
│   │   │   ├── evopen/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── config.txt
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   └── utils.h
│   │   │   │   ├── src/
│   │   │   │   │   ├── boot.S
│   │   │   │   │   ├── config.txt
│   │   │   │   │   ├── kernel.c
│   │   │   │   │   ├── linker.ld
│   │   │   │   │   ├── mini_uart.c
│   │   │   │   │   ├── mm.S
│   │   │   │   │   ├── printf.c
│   │   │   │   │   └── utils.S
│   │   │   │   └── start.sh
│   │   │   ├── gcrisis/
│   │   │   │   ├── Makefile
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       ├── printf.c
│   │   │   │       └── utils.S
│   │   │   ├── rs/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       ├── printf.c
│   │   │   │       └── utils.S
│   │   │   ├── szediwy/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── custom_printf.h
│   │   │   │   │   ├── entry.h
│   │   │   │   │   ├── irq.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   ├── irq.h
│   │   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   │   └── timer.h
│   │   │   │   │   ├── sysregs.h
│   │   │   │   │   ├── timer.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── custom_printf.c
│   │   │   │       ├── entry.S
│   │   │   │       ├── irq.S
│   │   │   │       ├── irq.c
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       ├── timer.c
│   │   │   │       └── utils.S
│   │   │   └── zjd0112/
│   │   │       ├── Makefile
│   │   │       ├── build.bat
│   │   │       ├── build.sh
│   │   │       ├── include/
│   │   │       │   ├── arm/
│   │   │       │   │   └── sysregs.h
│   │   │       │   ├── mini_uart.h
│   │   │       │   ├── mm.h
│   │   │       │   ├── peripherals/
│   │   │       │   │   ├── base.h
│   │   │       │   │   ├── gpio.h
│   │   │       │   │   └── mini_uart.h
│   │   │       │   ├── printf.h
│   │   │       │   └── utils.h
│   │   │       ├── src/
│   │   │       │   ├── boot.S
│   │   │       │   ├── config.txt
│   │   │       │   ├── kernel.c
│   │   │       │   ├── linker.ld
│   │   │       │   ├── mini_uart.c
│   │   │       │   ├── mm.S
│   │   │       │   ├── printf.c
│   │   │       │   └── utils.S
│   │   │       ├── test1.txt
│   │   │       └── test2.txt
│   │   └── 3/
│   │       ├── H-4ND-H/
│   │       │   ├── Makefile
│   │       │   ├── build.bat
│   │       │   ├── build.sh
│   │       │   ├── include/
│   │       │   │   ├── arm/
│   │       │   │   │   └── sysregs.h
│   │       │   │   ├── mini_uart.h
│   │       │   │   ├── mm.h
│   │       │   │   ├── peripherals/
│   │       │   │   │   ├── base.h
│   │       │   │   │   ├── gpio.h
│   │       │   │   │   └── mini_uart.h
│   │       │   │   ├── printf.h
│   │       │   │   └── utils.h
│   │       │   └── src/
│   │       │       ├── boot.S
│   │       │       ├── config.txt
│   │       │       ├── kernel.c
│   │       │       ├── linker.ld
│   │       │       ├── mini_uart.c
│   │       │       ├── mm.S
│   │       │       ├── printf.c
│   │       │       └── utils.S
│   │       ├── avenito/
│   │       │   ├── Makefile
│   │       │   ├── README.md
│   │       │   ├── build.bat
│   │       │   ├── build.sh
│   │       │   ├── include/
│   │       │   │   ├── arm/
│   │       │   │   │   └── sysregs.h
│   │       │   │   ├── mm.h
│   │       │   │   ├── peripherals/
│   │       │   │   │   ├── base.h
│   │       │   │   │   ├── gpio.h
│   │       │   │   │   └── uart.h
│   │       │   │   ├── printf.h
│   │       │   │   ├── uart.h
│   │       │   │   └── utils.h
│   │       │   └── src/
│   │       │       ├── boot.S
│   │       │       ├── config.txt
│   │       │       ├── kernel.c
│   │       │       ├── linker.ld
│   │       │       ├── mm.S
│   │       │       ├── printf.c
│   │       │       ├── uart.c
│   │       │       └── utils.S
│   │       ├── bl4ckout31/
│   │       │   ├── Makefile
│   │       │   ├── build.bat
│   │       │   ├── build.sh
│   │       │   ├── include/
│   │       │   │   ├── arm/
│   │       │   │   │   └── sysregs.h
│   │       │   │   ├── mini_uart.h
│   │       │   │   ├── mm.h
│   │       │   │   ├── peripherals/
│   │       │   │   │   ├── base.h
│   │       │   │   │   ├── gpio.h
│   │       │   │   │   └── mini_uart.h
│   │       │   │   ├── printf.h
│   │       │   │   └── utils.h
│   │       │   ├── src/
│   │       │   │   ├── boot.S
│   │       │   │   ├── config.txt
│   │       │   │   ├── kernel.c
│   │       │   │   ├── linker.ld
│   │       │   │   ├── mini_uart.c
│   │       │   │   ├── mm.S
│   │       │   │   ├── printf.c
│   │       │   │   └── utils.S
│   │       │   └── start.sh
│   │       ├── evopen/
│   │       │   ├── Makefile
│   │       │   ├── build.sh
│   │       │   ├── config.txt
│   │       │   ├── include/
│   │       │   │   ├── arm/
│   │       │   │   │   └── sysregs.h
│   │       │   │   ├── mm.h
│   │       │   │   ├── peripherals/
│   │       │   │   │   ├── base.h
│   │       │   │   │   ├── gpio.h
│   │       │   │   │   ├── mini_uart.h
│   │       │   │   │   └── uart.h
│   │       │   │   ├── printf.h
│   │       │   │   ├── uart.h
│   │       │   │   └── utils.h
│   │       │   ├── src/
│   │       │   │   ├── boot.S
│   │       │   │   ├── kernel.c
│   │       │   │   ├── linker-qemu.ld
│   │       │   │   ├── linker.ld
│   │       │   │   ├── mm.S
│   │       │   │   ├── printf.c
│   │       │   │   ├── uart.c
│   │       │   │   └── utils.S
│   │       │   └── start.sh
│   │       └── rs/
│   │           ├── Makefile
│   │           ├── build.bat
│   │           ├── build.sh
│   │           ├── include/
│   │           │   ├── arm/
│   │           │   │   └── sysregs.h
│   │           │   ├── mini_uart.h
│   │           │   ├── mm.h
│   │           │   ├── peripherals/
│   │           │   │   ├── base.h
│   │           │   │   ├── gpio.h
│   │           │   │   └── mini_uart.h
│   │           │   ├── printf.h
│   │           │   └── utils.h
│   │           ├── src/
│   │           │   ├── boot.S
│   │           │   ├── config.txt
│   │           │   ├── kernel.c
│   │           │   ├── linker.ld
│   │           │   ├── mini_uart.c
│   │           │   ├── mm.S
│   │           │   ├── printf.c
│   │           │   └── utils.S
│   │           └── start.sh
│   ├── lesson03/
│   │   ├── 1/
│   │   │   ├── H-4ND-H/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── entry.h
│   │   │   │   │   ├── irq.h
│   │   │   │   │   ├── local_timer.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   ├── irq.h
│   │   │   │   │   │   ├── local_timer.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── entry.S
│   │   │   │       ├── irq.S
│   │   │   │       ├── irq.c
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── local_timer.c
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       ├── printf.c
│   │   │   │       └── utils.S
│   │   │   ├── avenito/
│   │   │   │   ├── Makefile
│   │   │   │   ├── README.md
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── entry.h
│   │   │   │   │   ├── irq.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   ├── irq.h
│   │   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   │   └── timer.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   ├── timer.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── entry.S
│   │   │   │       ├── irq.S
│   │   │   │       ├── irq.c
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       ├── printf.c
│   │   │   │       ├── timer.c
│   │   │   │       └── utils.S
│   │   │   ├── bl4ckout31/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── entry.h
│   │   │   │   │   ├── irq.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   ├── irq.h
│   │   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   │   └── timer.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   ├── timer.h
│   │   │   │   │   └── utils.h
│   │   │   │   ├── src/
│   │   │   │   │   ├── boot.S
│   │   │   │   │   ├── config.txt
│   │   │   │   │   ├── entry.S
│   │   │   │   │   ├── irq.S
│   │   │   │   │   ├── irq.c
│   │   │   │   │   ├── kernel.c
│   │   │   │   │   ├── linker.ld
│   │   │   │   │   ├── mini_uart.c
│   │   │   │   │   ├── mm.S
│   │   │   │   │   ├── printf.c
│   │   │   │   │   ├── timer.c
│   │   │   │   │   └── utils.S
│   │   │   │   └── start.sh
│   │   │   ├── rs/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── entry.h
│   │   │   │   │   ├── irq.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   ├── irq.h
│   │   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   │   └── timer.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   ├── timer.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── entry.S
│   │   │   │       ├── irq.S
│   │   │   │       ├── irq.c
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       ├── printf.c
│   │   │   │       ├── timer.c
│   │   │   │       └── utils.S
│   │   │   ├── szediwy/
│   │   │   │   ├── Makefile
│   │   │   │   ├── README.md
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── custom_printf.h
│   │   │   │   │   ├── entry.h
│   │   │   │   │   ├── irq.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   ├── irq.h
│   │   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   │   └── timer.h
│   │   │   │   │   ├── sysregs.h
│   │   │   │   │   ├── timer.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── custom_printf.c
│   │   │   │       ├── debug.c
│   │   │   │       ├── entry.S
│   │   │   │       ├── irq.S
│   │   │   │       ├── irq.c
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       ├── timer.c
│   │   │   │       └── utils.S
│   │   │   └── xdfm1/
│   │   │       ├── Makefile
│   │   │       ├── build.bat
│   │   │       ├── build.sh
│   │   │       ├── include/
│   │   │       │   ├── arm/
│   │   │       │   │   └── sysregs.h
│   │   │       │   ├── arm_timer.h
│   │   │       │   ├── entry.h
│   │   │       │   ├── irq.h
│   │   │       │   ├── mini_uart.h
│   │   │       │   ├── mm.h
│   │   │       │   ├── peripherals/
│   │   │       │   │   ├── arm_timer.h
│   │   │       │   │   ├── base.h
│   │   │       │   │   ├── gpio.h
│   │   │       │   │   ├── irq.h
│   │   │       │   │   ├── mini_uart.h
│   │   │       │   │   └── timer.h
│   │   │       │   ├── printf.h
│   │   │       │   └── utils.h
│   │   │       └── src/
│   │   │           ├── arm_timer.c
│   │   │           ├── boot.S
│   │   │           ├── config.txt
│   │   │           ├── entry.S
│   │   │           ├── irq.S
│   │   │           ├── irq.c
│   │   │           ├── kernel.c
│   │   │           ├── linker.ld
│   │   │           ├── mini_uart.c
│   │   │           ├── mm.S
│   │   │           ├── printf.c
│   │   │           └── utils.S
│   │   ├── 2/
│   │   │   ├── H-4ND-H/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── entry.h
│   │   │   │   │   ├── irq.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   ├── irq.h
│   │   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   │   └── timer.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   ├── timer.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── entry.S
│   │   │   │       ├── irq.S
│   │   │   │       ├── irq.c
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       ├── printf.c
│   │   │   │       ├── timer.c
│   │   │   │       └── utils.S
│   │   │   ├── avenito/
│   │   │   │   ├── Makefile
│   │   │   │   ├── README.md
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── entry.h
│   │   │   │   │   ├── irq.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   ├── irq.h
│   │   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   │   └── timer.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   ├── timer.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── entry.S
│   │   │   │       ├── irq.S
│   │   │   │       ├── irq.c
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       ├── printf.c
│   │   │   │       ├── timer.c
│   │   │   │       └── utils.S
│   │   │   ├── bl4ckout31/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── entry.h
│   │   │   │   │   ├── irq.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   ├── irq.h
│   │   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   │   └── timer.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   ├── timer.h
│   │   │   │   │   └── utils.h
│   │   │   │   ├── src/
│   │   │   │   │   ├── boot.S
│   │   │   │   │   ├── config.txt
│   │   │   │   │   ├── entry.S
│   │   │   │   │   ├── irq.S
│   │   │   │   │   ├── irq.c
│   │   │   │   │   ├── kernel.c
│   │   │   │   │   ├── linker.ld
│   │   │   │   │   ├── mini_uart.c
│   │   │   │   │   ├── mm.S
│   │   │   │   │   ├── printf.c
│   │   │   │   │   ├── timer.c
│   │   │   │   │   └── utils.S
│   │   │   │   └── start.sh
│   │   │   ├── rs/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── entry.h
│   │   │   │   │   ├── irq.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   ├── irq.h
│   │   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   │   └── timer.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   ├── timer.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── entry.S
│   │   │   │       ├── irq.S
│   │   │   │       ├── irq.c
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       ├── printf.c
│   │   │   │       ├── timer.c
│   │   │   │       └── utils.S
│   │   │   └── szediwy/
│   │   │       ├── Makefile
│   │   │       ├── README.md
│   │   │       ├── build.bat
│   │   │       ├── build.sh
│   │   │       ├── include/
│   │   │       │   ├── custom_printf.h
│   │   │       │   ├── entry.h
│   │   │       │   ├── irq.h
│   │   │       │   ├── mini_uart.h
│   │   │       │   ├── mm.h
│   │   │       │   ├── peripherals/
│   │   │       │   │   ├── base.h
│   │   │       │   │   ├── gpio.h
│   │   │       │   │   ├── irq.h
│   │   │       │   │   ├── mini_uart.h
│   │   │       │   │   └── timer.h
│   │   │       │   ├── sysregs.h
│   │   │       │   ├── timer.h
│   │   │       │   └── utils.h
│   │   │       └── src/
│   │   │           ├── boot.S
│   │   │           ├── config.txt
│   │   │           ├── custom_printf.c
│   │   │           ├── debug.c
│   │   │           ├── entry.S
│   │   │           ├── irq.S
│   │   │           ├── irq.c
│   │   │           ├── kernel.c
│   │   │           ├── linker.ld
│   │   │           ├── mini_uart.c
│   │   │           ├── mm.S
│   │   │           ├── timer.c
│   │   │           └── utils.S
│   │   └── 3/
│   │       ├── H-4ND-H/
│   │       │   ├── Makefile
│   │       │   ├── build.bat
│   │       │   ├── build.sh
│   │       │   ├── include/
│   │       │   │   ├── arm/
│   │       │   │   │   └── sysregs.h
│   │       │   │   ├── entry.h
│   │       │   │   ├── irq.h
│   │       │   │   ├── mini_uart.h
│   │       │   │   ├── mm.h
│   │       │   │   ├── peripherals/
│   │       │   │   │   ├── base.h
│   │       │   │   │   ├── gpio.h
│   │       │   │   │   ├── irq.h
│   │       │   │   │   ├── mini_uart.h
│   │       │   │   │   └── timer.h
│   │       │   │   ├── printf.h
│   │       │   │   ├── timer.h
│   │       │   │   └── utils.h
│   │       │   └── src/
│   │       │       ├── boot.S
│   │       │       ├── config.txt
│   │       │       ├── entry.S
│   │       │       ├── irq.S
│   │       │       ├── irq.c
│   │       │       ├── kernel.c
│   │       │       ├── linker.ld
│   │       │       ├── mini_uart.c
│   │       │       ├── mm.S
│   │       │       ├── printf.c
│   │       │       ├── timer.c
│   │       │       └── utils.S
│   │       ├── avenito/
│   │       │   ├── Makefile
│   │       │   ├── build.bat
│   │       │   ├── build.sh
│   │       │   ├── include/
│   │       │   │   ├── arm/
│   │       │   │   │   └── sysregs.h
│   │       │   │   ├── entry.h
│   │       │   │   ├── irq.h
│   │       │   │   ├── mm.h
│   │       │   │   ├── peripherals/
│   │       │   │   │   ├── base.h
│   │       │   │   │   ├── gpio.h
│   │       │   │   │   ├── irq.h
│   │       │   │   │   ├── timer.h
│   │       │   │   │   └── uart.h
│   │       │   │   ├── printf.h
│   │       │   │   ├── timer.h
│   │       │   │   ├── uart.h
│   │       │   │   └── utils.h
│   │       │   └── src/
│   │       │       ├── boot.S
│   │       │       ├── config.txt
│   │       │       ├── entry.S
│   │       │       ├── irq.S
│   │       │       ├── irq.c
│   │       │       ├── kernel.c
│   │       │       ├── linker.ld
│   │       │       ├── mm.S
│   │       │       ├── printf.c
│   │       │       ├── timer.c
│   │       │       ├── uart.c
│   │       │       └── utils.S
│   │       ├── bl4ckout31/
│   │       │   ├── Makefile
│   │       │   ├── build.bat
│   │       │   ├── build.sh
│   │       │   ├── include/
│   │       │   │   ├── arm/
│   │       │   │   │   └── sysregs.h
│   │       │   │   ├── entry.h
│   │       │   │   ├── irq.h
│   │       │   │   ├── mini_uart.h
│   │       │   │   ├── mm.h
│   │       │   │   ├── peripherals/
│   │       │   │   │   ├── base.h
│   │       │   │   │   ├── gpio.h
│   │       │   │   │   ├── irq.h
│   │       │   │   │   ├── mini_uart.h
│   │       │   │   │   └── timer.h
│   │       │   │   ├── printf.h
│   │       │   │   ├── timer.h
│   │       │   │   └── utils.h
│   │       │   ├── src/
│   │       │   │   ├── boot.S
│   │       │   │   ├── config.txt
│   │       │   │   ├── entry.S
│   │       │   │   ├── irq.S
│   │       │   │   ├── irq.c
│   │       │   │   ├── kernel.c
│   │       │   │   ├── linker.ld
│   │       │   │   ├── mini_uart.c
│   │       │   │   ├── mm.S
│   │       │   │   ├── printf.c
│   │       │   │   ├── timer.S
│   │       │   │   ├── timer.c
│   │       │   │   └── utils.S
│   │       │   └── start.sh
│   │       └── rs/
│   │           ├── Makefile
│   │           ├── build.bat
│   │           ├── build.sh
│   │           ├── include/
│   │           │   ├── arm/
│   │           │   │   └── sysregs.h
│   │           │   ├── entry.h
│   │           │   ├── irq.h
│   │           │   ├── mini_uart.h
│   │           │   ├── mm.h
│   │           │   ├── peripherals/
│   │           │   │   ├── base.h
│   │           │   │   ├── gpio.h
│   │           │   │   ├── irq.h
│   │           │   │   ├── mini_uart.h
│   │           │   │   └── timer.h
│   │           │   ├── printf.h
│   │           │   ├── timer.h
│   │           │   └── utils.h
│   │           ├── src/
│   │           │   ├── boot.S
│   │           │   ├── config.txt
│   │           │   ├── entry.S
│   │           │   ├── irq.S
│   │           │   ├── irq.c
│   │           │   ├── kernel.c
│   │           │   ├── linker.ld
│   │           │   ├── mini_uart.c
│   │           │   ├── mm.S
│   │           │   ├── printf.c
│   │           │   ├── timer.c
│   │           │   └── utils.S
│   │           └── start.sh
│   ├── lesson04/
│   │   ├── 1/
│   │   │   ├── avenito/
│   │   │   │   ├── Makefile
│   │   │   │   ├── README.md
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── entry.h
│   │   │   │   │   ├── fork.h
│   │   │   │   │   ├── irq.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   ├── irq.h
│   │   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   │   ├── timer.h
│   │   │   │   │   │   └── uart.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   ├── sched.h
│   │   │   │   │   ├── timer.h
│   │   │   │   │   └── utils.h
│   │   │   │   ├── saida.txt
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── entry.S
│   │   │   │       ├── fork.c
│   │   │   │       ├── irq.S
│   │   │   │       ├── irq.c
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       ├── mm.c
│   │   │   │       ├── printf.c
│   │   │   │       ├── sched.S
│   │   │   │       ├── sched.c
│   │   │   │       ├── timer.c
│   │   │   │       └── utils.S
│   │   │   ├── bl4ckout31/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── entry.h
│   │   │   │   │   ├── fork.h
│   │   │   │   │   ├── irq.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   ├── irq.h
│   │   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   │   └── timer.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   ├── sched.h
│   │   │   │   │   ├── timer.h
│   │   │   │   │   └── utils.h
│   │   │   │   ├── src/
│   │   │   │   │   ├── boot.S
│   │   │   │   │   ├── config.txt
│   │   │   │   │   ├── entry.S
│   │   │   │   │   ├── fork.c
│   │   │   │   │   ├── irq.S
│   │   │   │   │   ├── irq.c
│   │   │   │   │   ├── kernel.c
│   │   │   │   │   ├── linker.ld
│   │   │   │   │   ├── mini_uart.c
│   │   │   │   │   ├── mm.S
│   │   │   │   │   ├── mm.c
│   │   │   │   │   ├── printf.c
│   │   │   │   │   ├── sched.S
│   │   │   │   │   ├── sched.c
│   │   │   │   │   ├── timer.c
│   │   │   │   │   └── utils.S
│   │   │   │   └── start.sh
│   │   │   └── rs/
│   │   │       ├── Makefile
│   │   │       ├── build.bat
│   │   │       ├── build.sh
│   │   │       ├── include/
│   │   │       │   ├── arm/
│   │   │       │   │   └── sysregs.h
│   │   │       │   ├── entry.h
│   │   │       │   ├── fork.h
│   │   │       │   ├── irq.h
│   │   │       │   ├── mini_uart.h
│   │   │       │   ├── mm.h
│   │   │       │   ├── peripherals/
│   │   │       │   │   ├── base.h
│   │   │       │   │   ├── gpio.h
│   │   │       │   │   ├── irq.h
│   │   │       │   │   ├── mini_uart.h
│   │   │       │   │   └── timer.h
│   │   │       │   ├── printf.h
│   │   │       │   ├── sched.h
│   │   │       │   ├── timer.h
│   │   │       │   └── utils.h
│   │   │       ├── output.txt
│   │   │       └── src/
│   │   │           ├── boot.S
│   │   │           ├── config.txt
│   │   │           ├── entry.S
│   │   │           ├── fork.c
│   │   │           ├── irq.S
│   │   │           ├── irq.c
│   │   │           ├── kernel.c
│   │   │           ├── linker.ld
│   │   │           ├── mini_uart.c
│   │   │           ├── mm.S
│   │   │           ├── mm.c
│   │   │           ├── printf.c
│   │   │           ├── sched.S
│   │   │           ├── sched.c
│   │   │           ├── timer.c
│   │   │           └── utils.S
│   │   ├── 2/
│   │   │   ├── avenito/
│   │   │   │   ├── Makefile
│   │   │   │   ├── README.md
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── entry.h
│   │   │   │   │   ├── fork.h
│   │   │   │   │   ├── irq.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   ├── irq.h
│   │   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   │   └── timer.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   ├── sched.h
│   │   │   │   │   ├── timer.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── entry.S
│   │   │   │       ├── fork.c
│   │   │   │       ├── irq.S
│   │   │   │       ├── irq.c
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       ├── mm.c
│   │   │   │       ├── printf.c
│   │   │   │       ├── sched.S
│   │   │   │       ├── sched.c
│   │   │   │       ├── timer.c
│   │   │   │       └── utils.S
│   │   │   ├── bl4ckout31/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── entry.h
│   │   │   │   │   ├── fork.h
│   │   │   │   │   ├── irq.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   ├── irq.h
│   │   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   │   └── timer.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   ├── sched.h
│   │   │   │   │   ├── timer.h
│   │   │   │   │   └── utils.h
│   │   │   │   ├── src/
│   │   │   │   │   ├── boot.S
│   │   │   │   │   ├── config.txt
│   │   │   │   │   ├── entry.S
│   │   │   │   │   ├── fork.c
│   │   │   │   │   ├── irq.S
│   │   │   │   │   ├── irq.c
│   │   │   │   │   ├── kernel.c
│   │   │   │   │   ├── linker.ld
│   │   │   │   │   ├── mini_uart.c
│   │   │   │   │   ├── mm.S
│   │   │   │   │   ├── mm.c
│   │   │   │   │   ├── printf.c
│   │   │   │   │   ├── sched.S
│   │   │   │   │   ├── sched.c
│   │   │   │   │   ├── timer.c
│   │   │   │   │   └── utils.S
│   │   │   │   └── start.sh
│   │   │   └── rs/
│   │   │       ├── Makefile
│   │   │       ├── build.bat
│   │   │       ├── build.sh
│   │   │       ├── include/
│   │   │       │   ├── arm/
│   │   │       │   │   └── sysregs.h
│   │   │       │   ├── entry.h
│   │   │       │   ├── fork.h
│   │   │       │   ├── irq.h
│   │   │       │   ├── mini_uart.h
│   │   │       │   ├── mm.h
│   │   │       │   ├── peripherals/
│   │   │       │   │   ├── base.h
│   │   │       │   │   ├── gpio.h
│   │   │       │   │   ├── irq.h
│   │   │       │   │   ├── mini_uart.h
│   │   │       │   │   └── timer.h
│   │   │       │   ├── printf.h
│   │   │       │   ├── sched.h
│   │   │       │   ├── timer.h
│   │   │       │   └── utils.h
│   │   │       ├── output.txt
│   │   │       └── src/
│   │   │           ├── boot.S
│   │   │           ├── config.txt
│   │   │           ├── entry.S
│   │   │           ├── fork.c
│   │   │           ├── irq.S
│   │   │           ├── irq.c
│   │   │           ├── kernel.c
│   │   │           ├── linker.ld
│   │   │           ├── mini_uart.c
│   │   │           ├── mm.S
│   │   │           ├── mm.c
│   │   │           ├── printf.c
│   │   │           ├── sched.S
│   │   │           ├── sched.c
│   │   │           ├── timer.c
│   │   │           └── utils.S
│   │   ├── 3/
│   │   │   ├── avenito/
│   │   │   │   ├── Makefile
│   │   │   │   ├── README.md
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── file.txt
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── entry.h
│   │   │   │   │   ├── fork.h
│   │   │   │   │   ├── irq.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   ├── irq.h
│   │   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   │   └── timer.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   ├── sched.h
│   │   │   │   │   ├── timer.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── entry.S
│   │   │   │       ├── fork.c
│   │   │   │       ├── irq.S
│   │   │   │       ├── irq.c
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       ├── mm.c
│   │   │   │       ├── printf.c
│   │   │   │       ├── sched.S
│   │   │   │       ├── sched.c
│   │   │   │       ├── timer.c
│   │   │   │       └── utils.S
│   │   │   └── bl4ckout31/
│   │   │       ├── Makefile
│   │   │       ├── build.bat
│   │   │       ├── build.sh
│   │   │       ├── include/
│   │   │       │   ├── arm/
│   │   │       │   │   └── sysregs.h
│   │   │       │   ├── entry.h
│   │   │       │   ├── fork.h
│   │   │       │   ├── irq.h
│   │   │       │   ├── mini_uart.h
│   │   │       │   ├── mm.h
│   │   │       │   ├── peripherals/
│   │   │       │   │   ├── base.h
│   │   │       │   │   ├── gpio.h
│   │   │       │   │   ├── irq.h
│   │   │       │   │   ├── mini_uart.h
│   │   │       │   │   └── timer.h
│   │   │       │   ├── printf.h
│   │   │       │   ├── sched.h
│   │   │       │   ├── timer.h
│   │   │       │   └── utils.h
│   │   │       ├── src/
│   │   │       │   ├── boot.S
│   │   │       │   ├── config.txt
│   │   │       │   ├── entry.S
│   │   │       │   ├── fork.c
│   │   │       │   ├── irq.S
│   │   │       │   ├── irq.c
│   │   │       │   ├── kernel.c
│   │   │       │   ├── linker.ld
│   │   │       │   ├── mini_uart.c
│   │   │       │   ├── mm.S
│   │   │       │   ├── mm.c
│   │   │       │   ├── printf.c
│   │   │       │   ├── sched.S
│   │   │       │   ├── sched.c
│   │   │       │   ├── timer.c
│   │   │       │   └── utils.S
│   │   │       └── start.sh
│   │   ├── 4/
│   │   │   ├── avenito/
│   │   │   │   ├── Makefile
│   │   │   │   ├── README.md
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── entry.h
│   │   │   │   │   ├── fork.h
│   │   │   │   │   ├── irq.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   ├── irq.h
│   │   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   │   └── timer.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   ├── sched.h
│   │   │   │   │   ├── timer.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── entry.S
│   │   │   │       ├── fork.c
│   │   │   │       ├── irq.S
│   │   │   │       ├── irq.c
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       ├── mm.c
│   │   │   │       ├── printf.c
│   │   │   │       ├── sched.S
│   │   │   │       ├── sched.c
│   │   │   │       ├── timer.c
│   │   │   │       └── utils.S
│   │   │   ├── bl4ckout31/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── entry.h
│   │   │   │   │   ├── fork.h
│   │   │   │   │   ├── irq.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   ├── irq.h
│   │   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   │   └── timer.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   ├── sched.h
│   │   │   │   │   ├── timer.h
│   │   │   │   │   └── utils.h
│   │   │   │   ├── src/
│   │   │   │   │   ├── boot.S
│   │   │   │   │   ├── config.txt
│   │   │   │   │   ├── entry.S
│   │   │   │   │   ├── fork.c
│   │   │   │   │   ├── irq.S
│   │   │   │   │   ├── irq.c
│   │   │   │   │   ├── kernel.c
│   │   │   │   │   ├── linker.ld
│   │   │   │   │   ├── mini_uart.c
│   │   │   │   │   ├── mm.S
│   │   │   │   │   ├── mm.c
│   │   │   │   │   ├── printf.c
│   │   │   │   │   ├── sched.S
│   │   │   │   │   ├── sched.c
│   │   │   │   │   ├── timer.c
│   │   │   │   │   └── utils.S
│   │   │   │   └── start.sh
│   │   │   └── rs/
│   │   │       ├── Makefile
│   │   │       ├── build.bat
│   │   │       ├── build.sh
│   │   │       ├── include/
│   │   │       │   ├── arm/
│   │   │       │   │   └── sysregs.h
│   │   │       │   ├── entry.h
│   │   │       │   ├── fork.h
│   │   │       │   ├── irq.h
│   │   │       │   ├── mini_uart.h
│   │   │       │   ├── mm.h
│   │   │       │   ├── peripherals/
│   │   │       │   │   ├── base.h
│   │   │       │   │   ├── gpio.h
│   │   │       │   │   ├── irq.h
│   │   │       │   │   ├── mini_uart.h
│   │   │       │   │   └── timer.h
│   │   │       │   ├── printf.h
│   │   │       │   ├── sched.h
│   │   │       │   ├── timer.h
│   │   │       │   └── utils.h
│   │   │       ├── output.txt
│   │   │       └── src/
│   │   │           ├── boot.S
│   │   │           ├── config.txt
│   │   │           ├── entry.S
│   │   │           ├── fork.c
│   │   │           ├── irq.S
│   │   │           ├── irq.c
│   │   │           ├── kernel.c
│   │   │           ├── linker.ld
│   │   │           ├── mini_uart.c
│   │   │           ├── mm.S
│   │   │           ├── mm.c
│   │   │           ├── printf.c
│   │   │           ├── sched.S
│   │   │           ├── sched.c
│   │   │           ├── timer.c
│   │   │           └── utils.S
│   │   └── 5/
│   │       ├── avenito/
│   │       │   ├── Makefile
│   │       │   ├── README.md
│   │       │   ├── build.bat
│   │       │   ├── build.sh
│   │       │   ├── include/
│   │       │   │   ├── arm/
│   │       │   │   │   └── sysregs.h
│   │       │   │   ├── entry.h
│   │       │   │   ├── fork.h
│   │       │   │   ├── irq.h
│   │       │   │   ├── mm.h
│   │       │   │   ├── peripherals/
│   │       │   │   │   ├── base.h
│   │       │   │   │   ├── gpio.h
│   │       │   │   │   ├── irq.h
│   │       │   │   │   ├── timer.h
│   │       │   │   │   └── uart.h
│   │       │   │   ├── printf.h
│   │       │   │   ├── sched.h
│   │       │   │   ├── timer.h
│   │       │   │   ├── uart.h
│   │       │   │   └── utils.h
│   │       │   ├── saida.txt
│   │       │   └── src/
│   │       │       ├── boot.S
│   │       │       ├── config.txt
│   │       │       ├── entry.S
│   │       │       ├── fork.c
│   │       │       ├── irq.S
│   │       │       ├── irq.c
│   │       │       ├── kernel.c
│   │       │       ├── linker.ld
│   │       │       ├── mm.S
│   │       │       ├── mm.c
│   │       │       ├── printf.c
│   │       │       ├── sched.S
│   │       │       ├── sched.c
│   │       │       ├── timer.c
│   │       │       ├── uart.c
│   │       │       └── utils.S
│   │       └── bl4ckout31/
│   │           ├── Makefile
│   │           ├── build.bat
│   │           ├── build.sh
│   │           ├── include/
│   │           │   ├── arm/
│   │           │   │   └── sysregs.h
│   │           │   ├── entry.h
│   │           │   ├── fork.h
│   │           │   ├── irq.h
│   │           │   ├── mini_uart.h
│   │           │   ├── mm.h
│   │           │   ├── peripherals/
│   │           │   │   ├── base.h
│   │           │   │   ├── gpio.h
│   │           │   │   ├── irq.h
│   │           │   │   ├── mini_uart.h
│   │           │   │   └── timer.h
│   │           │   ├── printf.h
│   │           │   ├── sched.h
│   │           │   ├── timer.h
│   │           │   └── utils.h
│   │           ├── src/
│   │           │   ├── boot.S
│   │           │   ├── config.txt
│   │           │   ├── entry.S
│   │           │   ├── fork.c
│   │           │   ├── irq.S
│   │           │   ├── irq.c
│   │           │   ├── kernel.c
│   │           │   ├── linker.ld
│   │           │   ├── mini_uart.c
│   │           │   ├── mm.S
│   │           │   ├── mm.c
│   │           │   ├── printf.c
│   │           │   ├── sched.S
│   │           │   ├── sched.c
│   │           │   ├── timer.S
│   │           │   ├── timer.c
│   │           │   └── utils.S
│   │           └── start.sh
│   ├── lesson05/
│   │   ├── 1/
│   │   │   ├── avenito/
│   │   │   │   ├── Makefile
│   │   │   │   ├── README.md
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── entry.h
│   │   │   │   │   ├── fork.h
│   │   │   │   │   ├── irq.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   ├── irq.h
│   │   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   │   └── timer.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   ├── sched.h
│   │   │   │   │   ├── sys.h
│   │   │   │   │   ├── timer.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── entry.S
│   │   │   │       ├── fork.c
│   │   │   │       ├── irq.S
│   │   │   │       ├── irq.c
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       ├── mm.c
│   │   │   │       ├── printf.c
│   │   │   │       ├── sched.S
│   │   │   │       ├── sched.c
│   │   │   │       ├── sys.S
│   │   │   │       ├── sys.c
│   │   │   │       ├── timer.c
│   │   │   │       └── utils.S
│   │   │   ├── bl4ckout31/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── entry.h
│   │   │   │   │   ├── fork.h
│   │   │   │   │   ├── irq.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   ├── irq.h
│   │   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   │   └── timer.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   ├── sched.h
│   │   │   │   │   ├── sys.h
│   │   │   │   │   ├── timer.h
│   │   │   │   │   └── utils.h
│   │   │   │   ├── src/
│   │   │   │   │   ├── boot.S
│   │   │   │   │   ├── config.txt
│   │   │   │   │   ├── entry.S
│   │   │   │   │   ├── fork.c
│   │   │   │   │   ├── irq.S
│   │   │   │   │   ├── irq.c
│   │   │   │   │   ├── kernel.c
│   │   │   │   │   ├── linker.ld
│   │   │   │   │   ├── mini_uart.c
│   │   │   │   │   ├── mm.S
│   │   │   │   │   ├── mm.c
│   │   │   │   │   ├── printf.c
│   │   │   │   │   ├── sched.S
│   │   │   │   │   ├── sched.c
│   │   │   │   │   ├── sys.S
│   │   │   │   │   ├── sys.c
│   │   │   │   │   ├── timer.c
│   │   │   │   │   └── utils.S
│   │   │   │   └── start.sh
│   │   │   └── xdfm1/
│   │   │       ├── Makefile
│   │   │       ├── build.bat
│   │   │       ├── build.sh
│   │   │       ├── include/
│   │   │       │   ├── arm/
│   │   │       │   │   └── sysregs.h
│   │   │       │   ├── entry.h
│   │   │       │   ├── fork.h
│   │   │       │   ├── irq.h
│   │   │       │   ├── mini_uart.h
│   │   │       │   ├── mm.h
│   │   │       │   ├── peripherals/
│   │   │       │   │   ├── base.h
│   │   │       │   │   ├── gpio.h
│   │   │       │   │   ├── irq.h
│   │   │       │   │   ├── mini_uart.h
│   │   │       │   │   └── timer.h
│   │   │       │   ├── printf.h
│   │   │       │   ├── sched.h
│   │   │       │   ├── sys.h
│   │   │       │   ├── timer.h
│   │   │       │   └── utils.h
│   │   │       └── src/
│   │   │           ├── boot.S
│   │   │           ├── config.txt
│   │   │           ├── entry.S
│   │   │           ├── fork.c
│   │   │           ├── irq.S
│   │   │           ├── irq.c
│   │   │           ├── kernel.c
│   │   │           ├── linker.ld
│   │   │           ├── mini_uart.c
│   │   │           ├── mm.S
│   │   │           ├── mm.c
│   │   │           ├── printf.c
│   │   │           ├── sched.S
│   │   │           ├── sched.c
│   │   │           ├── sys.S
│   │   │           ├── sys.c
│   │   │           ├── timer.c
│   │   │           └── utils.S
│   │   ├── 2/
│   │   │   ├── avenito/
│   │   │   │   ├── Makefile
│   │   │   │   ├── README.md
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── entry.h
│   │   │   │   │   ├── fork.h
│   │   │   │   │   ├── irq.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   ├── irq.h
│   │   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   │   └── timer.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   ├── sched.h
│   │   │   │   │   ├── sys.h
│   │   │   │   │   ├── timer.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── entry.S
│   │   │   │       ├── fork.c
│   │   │   │       ├── irq.S
│   │   │   │       ├── irq.c
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       ├── mm.c
│   │   │   │       ├── printf.c
│   │   │   │       ├── sched.S
│   │   │   │       ├── sched.c
│   │   │   │       ├── sys.S
│   │   │   │       ├── sys.c
│   │   │   │       ├── timer.c
│   │   │   │       └── utils.S
│   │   │   ├── bl4ckout31/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── entry.h
│   │   │   │   │   ├── fork.h
│   │   │   │   │   ├── irq.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   ├── irq.h
│   │   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   │   └── timer.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   ├── sched.h
│   │   │   │   │   ├── sys.h
│   │   │   │   │   ├── timer.h
│   │   │   │   │   └── utils.h
│   │   │   │   ├── src/
│   │   │   │   │   ├── boot.S
│   │   │   │   │   ├── config.txt
│   │   │   │   │   ├── entry.S
│   │   │   │   │   ├── fork.c
│   │   │   │   │   ├── irq.S
│   │   │   │   │   ├── irq.c
│   │   │   │   │   ├── kernel.c
│   │   │   │   │   ├── linker.ld
│   │   │   │   │   ├── mini_uart.c
│   │   │   │   │   ├── mm.S
│   │   │   │   │   ├── mm.c
│   │   │   │   │   ├── printf.c
│   │   │   │   │   ├── sched.S
│   │   │   │   │   ├── sched.c
│   │   │   │   │   ├── sys.S
│   │   │   │   │   ├── sys.c
│   │   │   │   │   ├── timer.c
│   │   │   │   │   └── utils.S
│   │   │   │   └── start.sh
│   │   │   └── xdfm1/
│   │   │       ├── Makefile
│   │   │       ├── build.bat
│   │   │       ├── build.sh
│   │   │       ├── include/
│   │   │       │   ├── arm/
│   │   │       │   │   └── sysregs.h
│   │   │       │   ├── entry.h
│   │   │       │   ├── fork.h
│   │   │       │   ├── irq.h
│   │   │       │   ├── mini_uart.h
│   │   │       │   ├── mm.h
│   │   │       │   ├── peripherals/
│   │   │       │   │   ├── base.h
│   │   │       │   │   ├── gpio.h
│   │   │       │   │   ├── irq.h
│   │   │       │   │   ├── mini_uart.h
│   │   │       │   │   └── timer.h
│   │   │       │   ├── printf.h
│   │   │       │   ├── sched.h
│   │   │       │   ├── sys.h
│   │   │       │   ├── timer.h
│   │   │       │   └── utils.h
│   │   │       └── src/
│   │   │           ├── boot.S
│   │   │           ├── config.txt
│   │   │           ├── entry.S
│   │   │           ├── fork.c
│   │   │           ├── irq.S
│   │   │           ├── irq.c
│   │   │           ├── kernel.c
│   │   │           ├── linker.ld
│   │   │           ├── mini_uart.c
│   │   │           ├── mm.S
│   │   │           ├── mm.c
│   │   │           ├── printf.c
│   │   │           ├── sched.S
│   │   │           ├── sched.c
│   │   │           ├── sys.S
│   │   │           ├── sys.c
│   │   │           ├── timer.c
│   │   │           └── utils.S
│   │   └── 3/
│   │       ├── avenito/
│   │       │   ├── Makefile
│   │       │   ├── README.md
│   │       │   ├── build.bat
│   │       │   ├── build.sh
│   │       │   ├── include/
│   │       │   │   ├── arm/
│   │       │   │   │   └── sysregs.h
│   │       │   │   ├── entry.h
│   │       │   │   ├── fork.h
│   │       │   │   ├── irq.h
│   │       │   │   ├── mini_uart.h
│   │       │   │   ├── mm.h
│   │       │   │   ├── peripherals/
│   │       │   │   │   ├── base.h
│   │       │   │   │   ├── gpio.h
│   │       │   │   │   ├── irq.h
│   │       │   │   │   ├── mini_uart.h
│   │       │   │   │   └── timer.h
│   │       │   │   ├── printf.h
│   │       │   │   ├── sched.h
│   │       │   │   ├── sys.h
│   │       │   │   ├── timer.h
│   │       │   │   └── utils.h
│   │       │   └── src/
│   │       │       ├── boot.S
│   │       │       ├── config.txt
│   │       │       ├── entry.S
│   │       │       ├── fork.c
│   │       │       ├── irq.S
│   │       │       ├── irq.c
│   │       │       ├── kernel.c
│   │       │       ├── linker.ld
│   │       │       ├── mini_uart.c
│   │       │       ├── mm.S
│   │       │       ├── mm.c
│   │       │       ├── printf.c
│   │       │       ├── sched.S
│   │       │       ├── sched.c
│   │       │       ├── sys.S
│   │       │       ├── sys.c
│   │       │       ├── timer.c
│   │       │       └── utils.S
│   │       └── bl4ckout31/
│   │           ├── Makefile
│   │           ├── build.bat
│   │           ├── build.sh
│   │           ├── include/
│   │           │   ├── arm/
│   │           │   │   └── sysregs.h
│   │           │   ├── entry.h
│   │           │   ├── fork.h
│   │           │   ├── irq.h
│   │           │   ├── mini_uart.h
│   │           │   ├── mm.h
│   │           │   ├── peripherals/
│   │           │   │   ├── base.h
│   │           │   │   ├── gpio.h
│   │           │   │   ├── irq.h
│   │           │   │   ├── mini_uart.h
│   │           │   │   └── timer.h
│   │           │   ├── printf.h
│   │           │   ├── sched.h
│   │           │   ├── sys.h
│   │           │   ├── timer.h
│   │           │   └── utils.h
│   │           ├── src/
│   │           │   ├── boot.S
│   │           │   ├── config.txt
│   │           │   ├── entry.S
│   │           │   ├── fork.c
│   │           │   ├── irq.S
│   │           │   ├── irq.c
│   │           │   ├── kernel.c
│   │           │   ├── linker.ld
│   │           │   ├── mini_uart.c
│   │           │   ├── mm.S
│   │           │   ├── mm.c
│   │           │   ├── printf.c
│   │           │   ├── sched.S
│   │           │   ├── sched.c
│   │           │   ├── sys.S
│   │           │   ├── sys.c
│   │           │   ├── timer.S
│   │           │   ├── timer.c
│   │           │   └── utils.S
│   │           └── start.sh
│   └── lesson06/
│       └── 1/
│           └── xdfm1/
│               ├── Makefile
│               ├── build.bat
│               ├── build.sh
│               ├── gdb.cmd
│               ├── include/
│               │   ├── arm/
│               │   │   ├── mmu.h
│               │   │   └── sysregs.h
│               │   ├── entry.h
│               │   ├── fork.h
│               │   ├── irq.h
│               │   ├── mini_uart.h
│               │   ├── mm.h
│               │   ├── peripherals/
│               │   │   ├── base.h
│               │   │   ├── gpio.h
│               │   │   ├── irq.h
│               │   │   ├── mini_uart.h
│               │   │   └── timer.h
│               │   ├── printf.h
│               │   ├── sched.h
│               │   ├── sys.h
│               │   ├── timer.h
│               │   ├── user.h
│               │   ├── user_sys.h
│               │   └── utils.h
│               ├── src/
│               │   ├── boot.S
│               │   ├── config.txt
│               │   ├── entry.S
│               │   ├── fork.c
│               │   ├── irq.S
│               │   ├── irq.c
│               │   ├── kernel.c
│               │   ├── linker.ld
│               │   ├── mini_uart.c
│               │   ├── mm.S
│               │   ├── mm.c
│               │   ├── printf.c
│               │   ├── sched.S
│               │   ├── sched.c
│               │   ├── sys.c
│               │   ├── timer.c
│               │   ├── user.c
│               │   ├── user_sys.S
│               │   └── utils.S
│               └── start.sh
├── src/
│   ├── lesson01/
│   │   ├── Makefile
│   │   ├── build.bat
│   │   ├── build.sh
│   │   ├── include/
│   │   │   ├── mini_uart.h
│   │   │   ├── mm.h
│   │   │   ├── peripherals/
│   │   │   │   ├── base.h
│   │   │   │   ├── gpio.h
│   │   │   │   └── mini_uart.h
│   │   │   └── utils.h
│   │   └── src/
│   │       ├── boot.S
│   │       ├── config.txt
│   │       ├── kernel.c
│   │       ├── linker.ld
│   │       ├── mini_uart.c
│   │       ├── mm.S
│   │       └── utils.S
│   ├── lesson02/
│   │   ├── Makefile
│   │   ├── build.bat
│   │   ├── build.sh
│   │   ├── include/
│   │   │   ├── arm/
│   │   │   │   └── sysregs.h
│   │   │   ├── mini_uart.h
│   │   │   ├── mm.h
│   │   │   ├── peripherals/
│   │   │   │   ├── base.h
│   │   │   │   ├── gpio.h
│   │   │   │   └── mini_uart.h
│   │   │   ├── printf.h
│   │   │   └── utils.h
│   │   └── src/
│   │       ├── boot.S
│   │       ├── config.txt
│   │       ├── kernel.c
│   │       ├── linker.ld
│   │       ├── mini_uart.c
│   │       ├── mm.S
│   │       ├── printf.c
│   │       └── utils.S
│   ├── lesson03/
│   │   ├── Makefile
│   │   ├── build.bat
│   │   ├── build.sh
│   │   ├── include/
│   │   │   ├── arm/
│   │   │   │   └── sysregs.h
│   │   │   ├── entry.h
│   │   │   ├── irq.h
│   │   │   ├── mini_uart.h
│   │   │   ├── mm.h
│   │   │   ├── peripherals/
│   │   │   │   ├── base.h
│   │   │   │   ├── gpio.h
│   │   │   │   ├── irq.h
│   │   │   │   ├── mini_uart.h
│   │   │   │   └── timer.h
│   │   │   ├── printf.h
│   │   │   ├── timer.h
│   │   │   └── utils.h
│   │   └── src/
│   │       ├── boot.S
│   │       ├── config.txt
│   │       ├── entry.S
│   │       ├── irq.S
│   │       ├── irq.c
│   │       ├── kernel.c
│   │       ├── linker.ld
│   │       ├── mini_uart.c
│   │       ├── mm.S
│   │       ├── printf.c
│   │       ├── timer.c
│   │       └── utils.S
│   ├── lesson04/
│   │   ├── Makefile
│   │   ├── build.bat
│   │   ├── build.sh
│   │   ├── include/
│   │   │   ├── arm/
│   │   │   │   └── sysregs.h
│   │   │   ├── entry.h
│   │   │   ├── fork.h
│   │   │   ├── irq.h
│   │   │   ├── mini_uart.h
│   │   │   ├── mm.h
│   │   │   ├── peripherals/
│   │   │   │   ├── base.h
│   │   │   │   ├── gpio.h
│   │   │   │   ├── irq.h
│   │   │   │   ├── mini_uart.h
│   │   │   │   └── timer.h
│   │   │   ├── printf.h
│   │   │   ├── sched.h
│   │   │   ├── timer.h
│   │   │   └── utils.h
│   │   └── src/
│   │       ├── boot.S
│   │       ├── config.txt
│   │       ├── entry.S
│   │       ├── fork.c
│   │       ├── irq.S
│   │       ├── irq.c
│   │       ├── kernel.c
│   │       ├── linker.ld
│   │       ├── mini_uart.c
│   │       ├── mm.S
│   │       ├── mm.c
│   │       ├── printf.c
│   │       ├── sched.S
│   │       ├── sched.c
│   │       ├── timer.c
│   │       └── utils.S
│   ├── lesson05/
│   │   ├── Makefile
│   │   ├── build.bat
│   │   ├── build.sh
│   │   ├── include/
│   │   │   ├── arm/
│   │   │   │   └── sysregs.h
│   │   │   ├── entry.h
│   │   │   ├── fork.h
│   │   │   ├── irq.h
│   │   │   ├── mini_uart.h
│   │   │   ├── mm.h
│   │   │   ├── peripherals/
│   │   │   │   ├── base.h
│   │   │   │   ├── gpio.h
│   │   │   │   ├── irq.h
│   │   │   │   ├── mini_uart.h
│   │   │   │   └── timer.h
│   │   │   ├── printf.h
│   │   │   ├── sched.h
│   │   │   ├── sys.h
│   │   │   ├── timer.h
│   │   │   └── utils.h
│   │   └── src/
│   │       ├── boot.S
│   │       ├── config.txt
│   │       ├── entry.S
│   │       ├── fork.c
│   │       ├── irq.S
│   │       ├── irq.c
│   │       ├── kernel.c
│   │       ├── linker.ld
│   │       ├── mini_uart.c
│   │       ├── mm.S
│   │       ├── mm.c
│   │       ├── printf.c
│   │       ├── sched.S
│   │       ├── sched.c
│   │       ├── sys.S
│   │       ├── sys.c
│   │       ├── timer.c
│   │       └── utils.S
│   └── lesson06/
│       ├── Makefile
│       ├── build.bat
│       ├── build.sh
│       ├── include/
│       │   ├── arm/
│       │   │   ├── mmu.h
│       │   │   └── sysregs.h
│       │   ├── entry.h
│       │   ├── fork.h
│       │   ├── irq.h
│       │   ├── mini_uart.h
│       │   ├── mm.h
│       │   ├── peripherals/
│       │   │   ├── base.h
│       │   │   ├── gpio.h
│       │   │   ├── irq.h
│       │   │   ├── mini_uart.h
│       │   │   └── timer.h
│       │   ├── printf.h
│       │   ├── sched.h
│       │   ├── sys.h
│       │   ├── timer.h
│       │   ├── user.h
│       │   ├── user_sys.h
│       │   └── utils.h
│       └── src/
│           ├── boot.S
│           ├── config.txt
│           ├── entry.S
│           ├── fork.c
│           ├── irq.S
│           ├── irq.c
│           ├── kernel.c
│           ├── linker.ld
│           ├── mini_uart.c
│           ├── mm.S
│           ├── mm.c
│           ├── printf.c
│           ├── sched.S
│           ├── sched.c
│           ├── sys.c
│           ├── timer.c
│           ├── user.c
│           ├── user_sys.S
│           └── utils.S
└── translations/
    ├── ko/
    │   ├── Introduction.md
    │   ├── Prerequisites.md
    │   ├── lesson01/
    │   │   ├── exercises.md
    │   │   ├── linux/
    │   │   │   ├── build-system.md
    │   │   │   ├── kernel-startup.md
    │   │   │   └── project-structure.md
    │   │   └── rpi-os.md
    │   ├── lesson02/
    │   │   ├── exercises.md
    │   │   ├── linux.md
    │   │   └── rpi-os.md
    │   ├── lesson03/
    │   │   ├── exercises.md
    │   │   ├── linux/
    │   │   │   ├── interrupt_controllers.md
    │   │   │   ├── low_level-exception_handling.md
    │   │   │   └── timer.md
    │   │   └── rpi-os.md
    │   └── lesson05/
    │       ├── exercises.md
    │       ├── linux.md
    │       └── rpi-os.md
    └── zh-cn/
        ├── Prerequisites.md
        ├── lesson01/
        │   ├── exercises.md
        │   ├── linux/
        │   │   ├── build-system.md
        │   │   ├── kernel-startup.md
        │   │   └── project-structure.md
        │   └── rpi-os.md
        ├── lesson02/
        │   ├── exercises.md
        │   ├── linux.md
        │   └── rpi-os.md
        ├── lesson03/
        │   ├── exercises.md
        │   ├── linux/
        │   │   ├── interrupt_controllers.md
        │   │   ├── low_level-exception_handling.md
        │   │   └── timer.md
        │   └── rpi-os.md
        ├── lesson04/
        │   ├── exercises.md
        │   ├── linux/
        │   │   ├── basic_structures.md
        │   │   ├── fork.md
        │   │   └── scheduler.md
        │   └── rpi-os.md
        ├── lesson05/
        │   ├── exercises.md
        │   ├── linux.md
        │   └── rpi-os.md
        └── lesson06/
            ├── exercises.md
            └── rpi-os.md

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
backup/*
src/*/build
**/*.o
**/*.d
**/*.swp
**/*.img
**/*.elf

# gnu global files
GPATH
GRTAGS
GSYMS
GTAGS


================================================
FILE: Dockerfile
================================================
FROM ubuntu:16.04
MAINTAINER Sergey Matyukevich <s-matyukevich@gmail.com>
RUN apt-get update && apt-get install -y gcc-aarch64-linux-gnu build-essential


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2018 Sergey Matyukevich

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
# Learning operating system development using Linux kernel and Raspberry Pi

This repository contains a step-by-step guide that teaches how to create a simple operating system (OS) kernel from scratch. I call this OS Raspberry Pi OS or just RPi OS. The RPi OS source code is largely based on [Linux kernel](https://github.com/torvalds/linux), but the OS has very limited functionality and supports only [Raspberry PI 3](https://www.raspberrypi.org/products/raspberry-pi-3-model-b/). 

Each lesson is designed in such a way that it first explains how some kernel feature is implemented in the RPi OS, and then it tries to demonstrate how the same functionality works in the Linux kernel. Each lesson has a corresponding folder in the [src](https://github.com/s-matyukevich/raspberry-pi-os/tree/master/src) directory, which contains a snapshot of the OS source code at the time when the lesson had just been completed. This allows the introduction of new concepts gracefully and helps readers to follow the evolution of the RPi OS. Understanding this guide doesn't require any specific OS development skills.

For more information about project goals and history, please read the [Introduction](docs/Introduction.md). The project is still under active development, if you are willing to participate - please read the [Contribution guide](docs/Contributions.md).

<p>
  <a href="https://twitter.com/RPi_OS" target="_blank">
    <img src="https://raw.githubusercontent.com/s-matyukevich/raspberry-pi-os/master/images/twitter.png" alt="Follow @RPi_OS on twitter" height="34" >
  </a>

  <a href="https://www.facebook.com/groups/251043708976964/" target="_blank">
    <img src="https://raw.githubusercontent.com/s-matyukevich/raspberry-pi-os/master/images/facebook.png" alt="Follow Raspberry Pi OS on facebook" height="34" >
  </a>

  <a href="https://join.slack.com/t/rpi-os/shared_invite/enQtNDQ1NTg2ODc1MDEwLWVjMTZlZmMyZDE4OGEyYmMzNTY1YjljZjU5YWI1NDllOWEwMjI5YzVkM2RiMzliYjEzN2RlYmUzNzBiYmQyMjY" target="_blank">
    <img src="https://raw.githubusercontent.com/s-matyukevich/raspberry-pi-os/master/images/slack.png" alt="Join Raspberry Pi OS in slack" height="34" >
  </a>

  <a href="https://www.producthunt.com/upcoming/raspberry-pi-os" target="_blank">
    <img src="https://raw.githubusercontent.com/s-matyukevich/raspberry-pi-os/master/images/subscribe.png" alt="Subscribe for updates" height="34" >
  </a>
</p>

## Table of Contents

* **[Introduction](docs/Introduction.md)**
* **[Contribution guide](docs/Contributions.md)**
* **[Prerequisites](docs/Prerequisites.md)**
* **Lesson 1: Kernel Initialization** 
  * 1.1 [Introducing RPi OS, or bare metal "Hello, world!"](docs/lesson01/rpi-os.md)
  * Linux
    * 1.2 [Project structure](docs/lesson01/linux/project-structure.md)
    * 1.3 [Kernel build system](docs/lesson01/linux/build-system.md) 
    * 1.4 [Startup sequence](docs/lesson01/linux/kernel-startup.md)
  * 1.5 [Exercises](docs/lesson01/exercises.md)
* **Lesson 2: Processor initialization**
  * 2.1 [RPi OS](docs/lesson02/rpi-os.md)
  * 2.2 [Linux](docs/lesson02/linux.md)
  * 2.3 [Exercises](docs/lesson02/exercises.md)
* **Lesson 3: Interrupt handling**
  * 3.1 [RPi OS](docs/lesson03/rpi-os.md)
  * Linux
    * 3.2 [Low level exception handling](docs/lesson03/linux/low_level-exception_handling.md) 
    * 3.3 [Interrupt controllers](docs/lesson03/linux/interrupt_controllers.md)
    * 3.4 [Timers](docs/lesson03/linux/timer.md)
  * 3.5 [Exercises](docs/lesson03/exercises.md)
* **Lesson 4: Process scheduler**
  * 4.1 [RPi OS](docs/lesson04/rpi-os.md) 
  * Linux
    * 4.2 [Scheduler basic structures](docs/lesson04/linux/basic_structures.md)
    * 4.3 [Forking a task](docs/lesson04/linux/fork.md)
    * 4.4 [Scheduler](docs/lesson04/linux/scheduler.md)
  * 4.5 [Exercises](docs/lesson04/exercises.md)
* **Lesson 5: User processes and system calls** 
  * 5.1 [RPi OS](docs/lesson05/rpi-os.md) 
  * 5.2 [Linux](docs/lesson05/linux.md)
  * 5.3 [Exercises](docs/lesson05/exercises.md)
* **Lesson 6: Virtual memory management**
  * 6.1 [RPi OS](docs/lesson06/rpi-os.md) 
  * 6.2 Linux (In progress)
  * 6.3 [Exercises](docs/lesson06/exercises.md)
* **Lesson 7: Signals and interrupt waiting** (To be done)
* **Lesson 8: File systems** (To be done)
* **Lesson 9: Executable files (ELF)** (To be done)
* **Lesson 10: Drivers** (To be done)
* **Lesson 11: Networking** (To be done)



================================================
FILE: _config.yml
================================================
theme: jekyll-theme-hacker

================================================
FILE: _layouts/default.html
================================================
<!DOCTYPE html>
<html lang="{{ site.lang | default: "en-US" }}">
  <head>
    <meta charset='utf-8'>
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="{{ '/assets/css/style.css?v=' | append: site.github.build_revision | relative_url }}">

{% seo %}
  </head>

  <body>

    <header>
      <div class="container">
        <a href="https://s-matyukevich.github.io/raspberry-pi-os/" class="logo">
          <h1>{{ site.title | default: site.github.repository_name }}</h1>
        </a>
        <h2>{{ site.description | default: site.github.project_tagline }}</h2>

        <section id="downloads">
          {% if site.show_downloads %}
            <a href="{{ site.github.zip_url }}" class="btn">Download as .zip</a>
            <a href="{{ site.github.tar_url }}" class="btn">Download as .tar.gz</a>
          {% endif %}
          <a href="{{ site.github.repository_url }}" class="btn btn-github"><span class="icon"></span>View on GitHub</a>
        </section>
      </div>
    </header>

    <div class="container">
      <section id="main_content">
        {{ content }}
      </section>
    </div>

    {% if site.google_analytics %}
      <script>
        (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
        (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
        m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
        })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
        ga('create', '{{ site.google_analytics }}', 'auto');
        ga('send', 'pageview');
      </script>
    {% endif %}
  </body>
</html>


================================================
FILE: assets/css/style.scss
================================================
---
---

@import "{{ site.theme }}";

#main_content a[target] {
  text-decoration: none;
}

header a.logo {
  text-decoration: none;
}


================================================
FILE: docs/Contributions.md
================================================
## Contributing to the Raspberry PI OS

The general workflow is the following:

1. Find an [issue](https://github.com/s-matyukevich/raspberry-pi-os/issues) you want to start working on or create a new one.
1. In comments claim that you want to take over the issue. The first person who does this will be assigned to the issue.
1. [Fork the repository](https://help.github.com/articles/fork-a-repo/).
1. Make all necessary changes.
1. [Send a pull request](https://help.github.com/articles/about-pull-requests/). 
1. After a review, your changes will be merged.

The following types of contributions are particularly useful for the project.

1. Validating the source code and text of the lessons, fixing bugs and errors.
1. Help in making lessons content more accurate and easier to understand.
1. Working on the source code and content for new lessons.
1. Sharing source code of completed exercises.
1. Suggesting new exercises.
1. Providing feedback, requesting new features and content.
1. Anything else that can help the project.

### Contributing completed exercises

If you successfully completed any of the exercises you can share your source code. The code should be placed in the following folder `/exercises/lessonXX/<exercise number>/<your github username>/` Such folder structure allows to accept pull requests for the same exercise from different people.

##### Previous Page

[Introduction](../docs/Introduction.md)

##### Next Page

[Prerequisites](../docs/Prerequisites.md)

================================================
FILE: docs/Introduction.md
================================================
## Raspberry Pi OS project introduction or how to efficiently learn operating system development?

A few years ago, I opened the source code of the Linux kernel for the first time. At that time, I considered myself more or less a skillful software developer: I knew a little bit of assembler and C programming, and had a high-level understanding of major operating system concepts, such as process scheduling and virtual memory management. However, my first attempt was a complete failure - I understood almost nothing.

For other software projects that I have to deal with, I have a simple approach that usually works very well: I find the entry point of the program and then start reading the source code, going as deep as necessary to understand all the details that I am interested in. This approach works well, but not for something as sophisticated as an operating system. It was not just that it took me more than a week just to find an entry point - the main problem was that I quickly found myself in a situation where I was looking at a few lines of code,  and I had no idea how to find any clues about what those lines were doing. This was especially true for the low-level assembler source code, but it worked no better for any other part of the system that I tried to investigate. 

I don't like the idea of dismissing a problem just because it looks complex from the beginning. Furthermore, I believe that there are no complex problems. Instead, there are a lot of problems we simply don't know how to address efficiently, so I started to look for an effective way to learn OS development in general and Linux in particular.

### Challenges in learning OS development

I know that there are tons of books and documentation written about Linux kernel development, but neither of them provides me with the learning experience that I want. Half of the material are so superficial that I already know it. With the other half I have a very similar problem that I have with exploring the kernel source code: as soon as a book goes deep enough, 90% of the details appear to be irrelevant to the core concepts, but related to some security, performance or legacy considerations as well as to millions of features that the Linux kernel supports. As a result, instead of learning core operating system concepts, you always end up digging into the implementation details of those features.

You may be wondering why I need to learn operating system development in the first place. For me, the main reason is that I was always interested in how things work under the hood. It is not just curiosity: the more difficult the task you are working on, frequently things begin to trace down to the operating system level. You just can't make fully informed technical decisions if you don't understand how everything works at a lower level. Another thing is that if you really like a technical challenge, working with OS development can be an exciting task for you.

The next question you may ask is, why Linux? Other operating systems would probably be easier to approach. The answer is that I want my knowledge to be, at least in some way, relevant to what I am currently doing and to something I expect to be doing in the future. Linux is perfect in this regard because nowadays everything from small IoT devices to large servers tend to run Linux.

When I said that most of the books about Linux kernel development didn't work well for me - I wasn't being quite honest. There was one book that explained some essential concepts using the actual source code that I was capable of fully understanding even though I am a novice in OS development. This book is "Linux Device Drivers", and it's no wonder that it is one of the most famous technical books about the Linux kernel. It starts by introducing source code of a simple driver that you can compile and play around with. Then it begins to introduce new driver related concepts one by one and explains how to modify the source code of the driver to use these new concepts. That is exactly what I refer to as a "good learning experience". The only problem with this book is that it focuses explicitly on driver development and says very little about core kernel implementation details.

But why has nobody created a similar book for kernel developers? I think this is because if you use the current Linux kernel source code as a base for your book, then it's just not possible. There is no function, structure, or module that can be used as a simple starting point because there is nothing simple about the Linux source. You also can't introduce new concepts one at a time because in the source code, everything is very closely related to one another. After I realized this, an idea came to me: if the Linux kernel is too vast and too complicated to be used as a starting point for learning OS development, why don't I implement my own OS that will be explicitly designed for learning purposes? In this way, I can make the OS simple enough to provide a good learning experience. Also, if this OS will be implemented mostly by copying and simplifying different parts of the Linux kernel source, it would be straightforward to use it as a starting point to learn the Linux kernel as well. In addition to the OS, I decided to write a series of lectures that teaches major OS development concepts and fully explains the OS source code.

### OS requirements

I started working on the project, which later became the [RPi OS](https://github.com/s-matyukevich/raspberry-pi-os). The first thing I had to do was to determine what parts of kernel development I considered to be "basic", and what components I considered to be not so essential and can be skipped (at least in the beginning). In my understanding, each operating system has 2 fundamental goals:

1. Run user processes in isolation.
1. Provide each user process with a unified view of the machine hardware.

To satisfy the first requirement, the RPi OS needs to have its own scheduler. If I want to implement a scheduler, I also have to handle timer interrupts. The second requirement implies that the OS should support some drivers and provide system calls to expose them to user applications. Since this is for beginners, I don't want to work with complicated hardware, so the only drivers I care about are drivers that can write something to screen and read user input from a keyboard. Also, the OS needs to be able to load and execute user programs, so naturally it needs to support some sort of file system and be capable of understanding some sort of executable file format. It would be nice if the OS can support basic networking, but I don't want to focus on that in a text for beginners. So those are basically the things that I can identify as "core concepts of any operating system".

Now let's take a look at the things that I want to ignore:
1. **Performance** I don't want to use any sophisticated algorithms in the OS. I am also going to disable all caches and other performance optimization techniques for simplicity.
1. **Security** It is true that the RPi OS has at least one security feature: virtual memory. Everything else can be safely ignored.
1. **Multiprocessing and synchronization** I am quite happy with my OS being executed on a single processor core. In particular, this allows me to get rid of a vast source of complexity - synchronization. 
1. **Support for multiple architectures and different types of devices** More on this in the next section.
1. **Millions of other features that any production-ready operating system supports**

### How Raspberry Pi comes into play

I already mentioned that I don't want the RPi OS to support multiple computer architectures or a lot of different devices. I felt even stronger about this after I dug into the Linux kernel driver model. It appears that even devices with similar purposes can largely vary in implementation details. This makes it very difficult to come up with simple abstractions around different driver types, and to reuse driver source code. To me, this seems like one of the primary sources of complexity in the Linux kernel, and I definitely want to avoid it in the RPi OS. Ok, but what kind of computer should I use then? I clearly don't want to test my bare metal programs using my working laptop, because I'm honestly not sure that it is going to survive. More importantly, I don't want people to buy an expensive laptop just to follow my OS development exercises (I don't think anybody would do this anyway). Emulators look like more or less a good choice, but I want to work with a real device because it gives me the feeling that I am doing something real rather than playing with bare metal programming.

I ended up using the Raspberry Pi, in particular, the [Raspberry Pi 3 Model B](https://www.raspberrypi.org/products/raspberry-pi-3-model-b/). Using this device looks like the ideal choice for a number of reasons:

1. It costs something around $35. I think that should be an affordable price.
1. This device is specially designed for learning. Its inner architecture is as simple as possible, and that perfectly suits my needs.
1. This device uses ARM v8 architecture. This is a simple RISC architecture, is very well adapted to OS authors' needs, and doesn't have so many legacy requirements as, for example, the popular x86 architecture. If you don't believe me, you can compare the amount of source code in the `/arch/arm64` and `/arch/x86` folders in the Linux kernel.

The OS is not compatible with the older versions of the Raspberry Pi, because neither of them support 64 bit ARM v8 architecture, though I think that support for all future devices should be trivial.

### Working with community

One major drawback of any technical book is that very soon after release each book becomes obsolete. Technology nowadays is evolving so fast that it is almost impossible for book writers to keep up with it. That's why I like the idea of an "open source book" - a book that is freely available on the internet and encourages its readers to participate in content creation and validation. If the book content is available on Github, it is very easy for any reader to fix and develop new code samples, update the book content, and participate in writing new chapters. I understand that right now the project is not perfect, and at the time of writing it is even not finished. But I still want to publish it now, because I hope that with the help of the community I will be able to not only complete the project faster but also to make it much better and much more useful than it was in the beginning. 

##### Previous Page

[Main Page](https://github.com/s-matyukevich/raspberry-pi-os#learning-operating-system-development-using-linux-kernel-and-raspberry-pi)

##### Next Page

[Contributing to the Raspberry PI OS](../docs/Contributions.md)


================================================
FILE: docs/Prerequisites.md
================================================
## Prerequisites

### 1. [Raspberry Pi 3 Model B](https://www.raspberrypi.org/products/raspberry-pi-3-model-b/)

Older versions of Raspberry Pi are not going to work with this tutorial because all lessons are designed to use a 64-bit processor that supports ARMv8 architecture, and such processor is only available in the Raspberry Pi 3. Newer versions, including [Raspberry Pi 3 Model B+](https://www.raspberrypi.org/products/raspberry-pi-3-model-b-plus/) should work fine, though I haven't tested it yet.

### 2. [USB to TTL serial cable](https://www.amazon.com/s/ref=nb_sb_noss_2?url=search-alias%3Daps&field-keywords=usb+to+ttl+serial+cable&rh=i%3Aaps%2Ck%3Ausb+to+ttl+serial+cable) 

After you get a serial cable, you need to test your connection. If you never did this before I recommend you to follow [this guide](https://cdn-learn.adafruit.com/downloads/pdf/adafruits-raspberry-pi-lesson-5-using-a-console-cable.pdf) It describes the process of connecting your Raspberry PI via a serial cable in great details. 

The guide also describes how to power your Raspberry Pi using a serial cable. RPi OS works fine with such kind of setup, however, in this case you need to run your terminal emulator right after you plug in the cable. Check [this](https://github.com/s-matyukevich/raspberry-pi-os/issues/2)
 issue for details..
 
### 3. [SD card](https://www.raspberrypi.org/documentation/installation/sd-cards.md) with installed [Raspbian OS](https://www.raspberrypi.org/downloads/raspbian/)

We need Raspbian to test USB to TTL cable connectivity initially. Another reason is that after installation it leaves the SD card formatted in the right way.

### 4. Docker

Strictly speaking, Docker is not a required dependency. It is just convenient to use Docker to build source code of the lessons, especially for Mac and Windows users. Each lesson has `build.sh` script (or `build.bat` for windows users) This script uses Docker to build source code of the lesson. Instructions how to install docker for your platform can be found on the [official docker website](https://docs.docker.com/engine/installation/)  

If for some reasons you want to avoid using Docker, you can install the [make utility](http://www.math.tau.ac.il/~danha/courses/software1/make-intro.html) as well as  `aarch64-linux-gnu` toolchain. If you are using Ubuntu you just need to install `gcc-aarch64-linux-gnu` and `build-essential` packages.

##### Previous Page

[Contribution guide](../docs/Contributions.md)

##### Next Page

1.1 [Kernel Initialization: Introducing RPi OS, or bare metal "Hello, world!"](../docs/lesson01/rpi-os.md)


================================================
FILE: docs/lesson01/exercises.md
================================================
## 1.5: Exercises.

Exercises are optional, though I strongly recommend you to experiment with the source code a little bit. If you were able to complete any of the exercises - please share your source code with others. For details see the [contribution guide](../Contributions.md).

1. Introduce a constant `baud_rate`, calculate necessary Mini UART register values using this constant. Make sure that the program can work using baud rates other than 115200.
1. Change the OS code to use UART device instead of Mini UART. Use `BCM2837 ARM Peripherals` and [ARM PrimeCell UART (PL011)](http://infocenter.arm.com/help/topic/com.arm.doc.ddi0183g/DDI0183G_uart_pl011_r1p5_trm.pdf) manuals to figure out how to access UART registers and how to configure GPIO pins. The UART device uses the 48MHz clock as a base.
1. Try to use all 4 processor cores. The OS should print `Hello, from processor <processor index>` for all of the cores. Don't forget to set up a separate stack for each core and make sure that Mini UART is initialized only once. You can use a combination of global variables and `delay` function for synchronization.
1. Adapt lesson 01 to run on qemu. Check [this](https://github.com/s-matyukevich/raspberry-pi-os/issues/8) issue for reference.

##### Previous Page

1.4 [Kernel Initialization: Linux startup sequence](../../docs/lesson01/linux/kernel-startup.md)

##### Next Page

2.1 [Processor initialization: RPi OS](../../docs/lesson02/rpi-os.md)


================================================
FILE: docs/lesson01/linux/build-system.md
================================================
## 1.3: Kernel build system

After we examined Linux kernel structure, it worth spending some time investigating how we can build and run it. Linux also uses `make` utility to build the kernel, though Linux makefile is much more complicated. Before we will take a look at the makefile, let's learn some important concepts about Linux build system, which is called "kbuild".

### A few essential kbuild concepts

* Build process can be customized by using kbuild variables. Those variables are defined in `Kconfig` files. Here you can define the variables themselves and their default values. Variables can have different types, including string, boolean and integer. In a Kconfig file you can also define dependencies between variables (for example, you can say that if variable X is selected then variable Y will be selected implicitly). As an example, you can take a look at [arm64 Kconfig file](https://github.com/torvalds/linux/tree/v4.14/arch/arm64/Kconfig). This file defines all variables, specific for `arm64` architecture. `Kconfig` functionality is not part of the standard `make` and is implemented in the Linux makefile. Variables, defined in `Kconfig` are exposed to the kernel source code as well as to the nested makefiles. Variable values can be set during kernel configuration step (for example, if you type `make menuconfig` a console GUI will be shown. It allows you to customize values for all kernel variables and stores the values in `.config`. Use `make help` command to view all possible options to configure the kernel)

* Linux uses recursive build. This means that each subfolder of the Linux kernel can define it's own `Makefile` and `Kconfig`. Most of the nested Makefiles are very simple and just define what object files need to be compiled. Usually, such definitions have the following format.

  ```
  obj-$(SOME_CONFIG_VARIABLE) += some_file.o
  ```

  This definition means that `some_file.c` will be compiled and linked to the kernel only if `SOME_CONFIG_VARIABLE` is set. If you want to compile and link a file unconditionally, you need to change the previous definition to look like this.

  ```
  obj-y += some_file.o
  ```

  An example of the nested Makefile can be found [here](https://github.com/torvalds/linux/tree/v4.14/kernel/Makefile).

* Before we move forward, you need to understand the structure of a basic make rule and be comfortable with make terminology. Common rule structure is illustrated in the following diagram. 

  ```
  targets : prerequisites
          recipe
          …
  ```
    * `targets` are file names, separated by spaces. Targets are generated after the rule is executed. Usually, there is only one target per rule.
    * `prerequisites` are files that `make` trackes to see whether it needs to update the targets.
    * `recipe` is a bash script. Make calls it when some of the prerequisites have been updated. The recipe is responsible for generating the targets.
    * Both targets and prerequisites can include wildcards (`%`). When wildcards are used the recipe is executed for each of the matched prerequisites separately. In this case, you can use `$<` and `$@` variables to refer to the prerequisite and the target inside the recipe. We already did it in the [RPi OS makefile](https://github.com/s-matyukevich/raspberry-pi-os/blob/master/src/lesson01/Makefile#L14).
  For additional information about make rules, please refer to the [official documentation](https://www.gnu.org/software/make/manual/html_node/Rule-Syntax.html#Rule-Syntax).

* `make` is very good in detecting whether any of the prerequisites have been changed and updating only targets that need to be rebuilt. However, if a recipe is dynamically updated, `make` is unable to detect this change. How can this happen? Very easily. One good example is when you change some configuration variable, which results in appending an additional option to the recipe. By default, in this case, `make` will not recompile previously generated object files, because their prerequisites haven't been changed, only the recipe have been updated. To overcome this behavior Linux introduces [if_changed](https://github.com/torvalds/linux/blob/v4.14/scripts/Kbuild.include#L264) function. To see how it works let's consider the following example.

  ```
  cmd_compile = gcc $(flags) -o $@ $<

  %.o: %.c FORCE
      $(call if_changed,compile)
  ```

  Here for each `.c` file we build corresponding `.o` file by calling `if_changed` function with the argument `compile`. `if_changed` then looks for `cmd_compile` variable (it adds `cmd_` prefix to the first argument) and checks whether this variable has been updated since the last execution, or any of the prerequisites has been changed. If yes - `cmd_compile` command is executed and object file is regenerated. Our sample rule has 2 prerequisites: source `.c` file and `FORCE`. `FORCE` is a special prerequisite that forces the recipe to be called each time when `make` command is called. Without it, the recipe would be called only if `.c` file was changed. You can read more about `FORCE` target [here](https://www.gnu.org/software/make/manual/html_node/Force-Targets.html).

### Building the kernel

Now, that we learned some important concepts about the Linux build system, let's try to figure out what exactly is going on after you type `make` command. This process is very complicated and includes a lot of details, most of which we will skip. Our goal will be to answer 2 questions.

1. How exactly are source files compiled into object files?
1. How are object files linked into the OS image?

We are going to tackle the second question first.

#### Link stage 

* As you might see from the output of `make help` command, the default target, which is responsible for building the kernel, is called `vmlinux`.

* `vmlinux` target definition can be found [here](https://github.com/torvalds/linux/blob/v4.14/Makefile#L1004) and it looks like this.

  ```
  cmd_link-vmlinux =                                                 \
      $(CONFIG_SHELL) $< $(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) ;    \
      $(if $(ARCH_POSTLINK), $(MAKE) -f $(ARCH_POSTLINK) $@, true)

  vmlinux: scripts/link-vmlinux.sh vmlinux_prereq $(vmlinux-deps) FORCE
      +$(call if_changed,link-vmlinux)
  ```

  This target uses already familiar to us `if_changed` function. Whenever some of the prerequsities are updated `cmd_link-vmlinux` command is executed. This command executes [scripts/link-vmlinux.sh](https://github.com/torvalds/linux/blob/v4.14/scripts/link-vmlinux.sh) script (Note usage of [$<](https://www.gnu.org/software/make/manual/html_node/Automatic-Variables.html) automatic variable in the `cmd_link-vmlinux` command). It also executes architecture specific [postlink script](https://github.com/torvalds/linux/blob/v4.14/Documentation/kbuild/makefiles.txt#L1229), but we are not very interested in it.

* When [scripts/link-vmlinux.sh](https://github.com/torvalds/linux/blob/v4.14/scripts/link-vmlinux.sh) is executed it assumes that all required object files are already built and their locations are stored in 3 variables: `KBUILD_VMLINUX_INIT`, `KBUILD_VMLINUX_MAIN`, `KBUILD_VMLINUX_LIBS`.  

* `link-vmlinux.sh` script first creates `thin archive` from all available object files. `thin archive` is a special object that contains references to a set of object files as well as their combined symbol table. This is done inside [archive_builtin](https://github.com/torvalds/linux/blob/v4.14/scripts/link-vmlinux.sh#L56) function. In order to create `thin archive` this function uses [ar](https://sourceware.org/binutils/docs/binutils/ar.html) utility. Generated `thin archive` is stored as `built-in.o` file and has the format that is understandable by the linker, so it can be used as any other normal object file.

* Next [modpost_link](https://github.com/torvalds/linux/blob/v4.14/scripts/link-vmlinux.sh#L69) is called. This function calls linker and generates `vmlinux.o` object file. We need this object file to perform [Section mismatch analysis](https://github.com/torvalds/linux/blob/v4.14/lib/Kconfig.debug#L308). This analysis is performed by the [modpost](https://github.com/torvalds/linux/tree/v4.14/scripts/mod) program and is triggered at [this](https://github.com/torvalds/linux/blob/v4.14/scripts/link-vmlinux.sh#L260) line.

* Next kernel symbol table is generated. It contains information about all functions and global variables as well as their location in the `vmlinux` binary. The main work is done inside [kallsyms](https://github.com/torvalds/linux/blob/v4.14/scripts/link-vmlinux.sh#L146) function. This function first uses [nm](https://sourceware.org/binutils/docs/binutils/nm.html) to extract all symbols from `vmlinux` binary. Then it uses [scripts/kallsyms](https://github.com/torvalds/linux/blob/v4.14/scripts/kallsyms.c)  utility to generate a special assembler file containing all symbols in a special format, understandable by the Linux kernel. Next, this assembler file is compiled and linked together with the original binary.  This process is repeated several times because after the final link addresses of some symbols can be changed.  Information from the kernel symbol table is used to generate '/proc/kallsyms' file at runtime.

* Finally `vmlinux` binary is ready and `System.map`  is build. `System.map` contains the same information as `/proc/kallsyms` but this is static file and unlike `/proc/kallsyms` it is not generated at runtime. `System.map` is mostly used to resolve addresses to symbol names during [kernel oops](https://en.wikipedia.org/wiki/Linux_kernel_oops). The same `nm` utility is used to build `System.map`. This is done [here](https://github.com/torvalds/linux/blob/v4.14/scripts/mksysmap#L44).

#### Build stage 

* Now let's take one step backward and examine how source code files are compiled into object files. As you might remember one of the prerequisites of the `vmlinux` target is `$(vmlinux-deps)` variable. Let me now copy a few relevant lines from the main Linux makefile to demonstrate how this variable is built. 

  ```
  init-y        := init/
  drivers-y    := drivers/ sound/ firmware/
  net-y        := net/
  libs-y        := lib/
  core-y        := usr/

  core-y        += kernel/ certs/ mm/ fs/ ipc/ security/ crypto/ block/

  init-y        := $(patsubst %/, %/built-in.o, $(init-y))
  core-y        := $(patsubst %/, %/built-in.o, $(core-y))
  drivers-y    := $(patsubst %/, %/built-in.o, $(drivers-y))
  net-y        := $(patsubst %/, %/built-in.o, $(net-y))

  export KBUILD_VMLINUX_INIT := $(head-y) $(init-y)
  export KBUILD_VMLINUX_MAIN := $(core-y) $(libs-y2) $(drivers-y) $(net-y) $(virt-y)
  export KBUILD_VMLINUX_LIBS := $(libs-y1)
  export KBUILD_LDS          := arch/$(SRCARCH)/kernel/vmlinux.lds

  vmlinux-deps := $(KBUILD_LDS) $(KBUILD_VMLINUX_INIT) $(KBUILD_VMLINUX_MAIN) $(KBUILD_VMLINUX_LIBS)
  ```

  It all starts with variables like `init-y`, `core-y`, etc., which combined contains all subfolders of the Linux kernel that contains buildable source code. Then `built-in.o` is appended to all the subfolder names, so, for example, `drivers/` becomes `drivers/built-in.o`. `vmlinux-deps` then just aggregates all resulting values. This explains how `vmlinux` eventually becomes dependent on all `built-in.o` files.

* Next question is how all `built-in.o` objects are created? Once again, let me copy all relevant lines and explain how it all works.

  ```
  $(sort $(vmlinux-deps)): $(vmlinux-dirs) ;

  vmlinux-dirs    := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \
               $(core-y) $(core-m) $(drivers-y) $(drivers-m) \
               $(net-y) $(net-m) $(libs-y) $(libs-m) $(virt-y)))

  build := -f $(srctree)/scripts/Makefile.build obj               #Copied from `scripts/Kbuild.include`

  $(vmlinux-dirs): prepare scripts
      $(Q)$(MAKE) $(build)=$@

  ```

  The first line tells us that `vmlinux-deps` depends on `vmlinux-dirs`. Next, we can see that `vmlinux-dirs` is a variable that contains all direct root subfolders without `/` character at the end. And the most important line here is the recipe to build `$(vmlinux-dirs)` target. After substitution of all variables, this recipe will look like the following (we use `drivers` folder as an example, but this rule will be executed for all root subfolders)

  ```
  make -f scripts/Makefile.build obj=drivers
  ```

  This line just calls another makefile  ([scripts/Makefile.build](https://github.com/torvalds/linux/blob/v4.14/scripts/Makefile.build)) and passes `obj` variable, which contains a folder to be compiled. 

* Next logical step is to take a look at [scripts/Makefile.build](https://github.com/torvalds/linux/blob/v4.14/scripts/Makefile.build). The first important thing that happens after it is executed is that all variables from `Makefile` or `Kbuild` files, defined in the current directory, are included. By current directory I mean the directory referenced by the `obj` variable. The inclusion is done in the [following 3 lines](https://github.com/torvalds/linux/blob/v4.14/scripts/Makefile.build#L43-L45).

  ```
  kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
  kbuild-file := $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile)
  include $(kbuild-file)
  ```
  Nested makefiles are mostly responsible for initializing variables like `obj-y`. As a quick reminder: `obj-y` variable should contain list of all source code files, located in the current directory. Another important variable that is initialized by the nested makefiles is `subdir-y`. This variable contains a list of all subfolders that need to be visited before the source code in the curent directory can be built. `subdir-y` is used to implement recursive descending into subfolders.

* When `make` is called without specifying the target (as it is in the case when `scripts/Makefile.build` is executed) it uses the first target. The first target for `scripts/Makefile.build` is called `__build` and it can be found [here](https://github.com/torvalds/linux/blob/v4.14/scripts/Makefile.build#L96) Let's take a look at it.

  ```
  __build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
       $(if $(KBUILD_MODULES),$(obj-m) $(modorder-target)) \
       $(subdir-ym) $(always)
      @:
  ```

  As you can see `__build` target doesn't have a receipt, but it depends on a bunch of other targets. We are only interested in `$(builtin-target)` - it is responsible for creating `built-in.o` file, and `$(subdir-ym)` - it is responsible for descending into nested directories.

* Let's take a look at `subdir-ym`. This variable is initialized [here](https://github.com/torvalds/linux/blob/v4.14/scripts/Makefile.lib#L48) and it is just a concatenation of `subdir-y` and `subdir-m` variables.  (`subdir-m` variable is similar to `subdir-y`, but it defines subfolders need to be included in a separate [kernel module](https://en.wikipedia.org/wiki/Loadable_kernel_module). We skip the discussion of modules, for now, to keep focused.) 

*  `subdir-ym` target is defined [here](https://github.com/torvalds/linux/blob/v4.14/scripts/Makefile.build#L572) and should look familiar to you.

  ```
  $(subdir-ym):
      $(Q)$(MAKE) $(build)=$@
  ```

  This target just triggers execution of the `scripts/Makefile.build` in one of the nested subfolders.

* Now it is time to examine the [builtin-target](https://github.com/torvalds/linux/blob/v4.14/scripts/Makefile.build#L467) target. Once again I am copying only relevant lines here.

  ```
  cmd_make_builtin = rm -f $@; $(AR) rcSTP$(KBUILD_ARFLAGS)
  cmd_make_empty_builtin = rm -f $@; $(AR) rcSTP$(KBUILD_ARFLAGS)

  cmd_link_o_target = $(if $(strip $(obj-y)),\
                $(cmd_make_builtin) $@ $(filter $(obj-y), $^) \
                $(cmd_secanalysis),\
                $(cmd_make_empty_builtin) $@)

  $(builtin-target): $(obj-y) FORCE
      $(call if_changed,link_o_target)
  ```

  This target depends on `$(obj-y)` target and `obj-y` is a list of all object files that need to be built in the current folder. After those files become ready `cmd_link_o_target` command is executed. In case if `obj-y` variable is empty `cmd_make_empty_builtin` is called, which just creates an empty `built-in.o`. Otherwise, `cmd_make_builtin` command is executed; it uses familiar to us `ar` tool to create `built-in.o` thin archive.

* Finally we got to the point where we need to compile something. You remember that our last unexplored dependency is `$(obj-y)` and `obj-y` is just a list of object files. The target that compiles all object files from corresponding `.c` files is defined [here](https://github.com/torvalds/linux/blob/v4.14/scripts/Makefile.build#L313). Let's examine all lines, needed to understand this target.

  ```
  cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $<

  define rule_cc_o_c
      $(call echo-cmd,checksrc) $(cmd_checksrc)              \
      $(call cmd_and_fixdep,cc_o_c)                      \
      $(cmd_modversions_c)                          \
      $(call echo-cmd,objtool) $(cmd_objtool)                  \
      $(call echo-cmd,record_mcount) $(cmd_record_mcount)
  endef

  $(obj)/%.o: $(src)/%.c $(recordmcount_source) $(objtool_dep) FORCE
      $(call cmd,force_checksrc)
      $(call if_changed_rule,cc_o_c)
  ```

  Inside it's recipe this target calls `rule_cc_o_c`. This rule is responsible for a lot of things, like checking the source code for some common errors (`cmd_checksrc`), enabling versioning for exported module symbols (`cmd_modversions_c`), using [objtool](https://github.com/torvalds/linux/tree/v4.14/tools/objtool) to validate some aspects of generated object files and constructing a list of calls to `mcount` function so that [ftrace](https://github.com/torvalds/linux/blob/v4.14/Documentation/trace/ftrace.txt) can find them quickly. But most importantly it calls `cmd_cc_o_c` command that actually compiles all `.c` files to object files. 

### Conclusion

Wow, it was a long journey inside kernel build system internals! Still, we skipped a lot of details and, for those who want to learn more about the subject, I can recommend to read the following [document](https://github.com/torvalds/linux/blob/v4.14/Documentation/kbuild/makefiles.txt) and continue reading Makefiles source code. Let me now emphasize the important points, that you should take as a take-home message from this chapter.

1. How `.c` files are compiled into object files.
1. How object files are combined into `built-in.o` files.
1. How  recursive build pick up all child `built-in.o` files and combines them into a single one.
1. How `vmlinux` is linked from all top-level `built-in.o` files.

My main goal was that after reading this chapter you will gain a general understanding of all above points.

##### Previous Page

1.2 [Kernel Initialization: Linux project structure](../../../docs/lesson01/linux/project-structure.md)

##### Next Page

1.4 [Kernel Initialization: Linux startup sequence](../../../docs/lesson01/linux/kernel-startup.md)


================================================
FILE: docs/lesson01/linux/kernel-startup.md
================================================
## 1.4: Linux startup sequence

### Searching for the entry point

After taking a look at the Linux project structure and examining how it can be built, next logical step is to find the program entry point. This step might be trivial for a lot of programs, but not for the Linux kernel. 

The first thing we are going to do is to take a look at [arm64 linker script](https://github.com/torvalds/linux/blob/v4.14/arch/arm64/kernel/vmlinux.lds.S). We have already seen how the linker script [is used in the main makefile](https://github.com/torvalds/linux/blob/v4.14/Makefile#L970). From this line, we can easily infer, where the linker script for a particular architecture can be found.

It should be mentioned that the file we are going to examine is not an actual linker script - it is a template, from which the actual linker script is built by substituting some macros with their actual values. But precisely because this file consists mostly of macros it becomes much easier to read and to port between different architectures.

The first section that we can find in the linker script is called [.head.text](https://github.com/torvalds/linux/blob/v4.14/arch/arm64/kernel/vmlinux.lds.S#L96). This is very important for us because the entry point should be defined in this section. If you think a little about it, it makes a perfect sense: after the kernel is loaded, the content of the binary image is copied into some memory area and execution is started from the beginning of that area. This means that just by searching who is using `.head.text` section we should be able to find the entry point. And indeed, `arm64` architecture has a single file that uses [__HEAD](https://github.com/torvalds/linux/blob/v4.14/include/linux/init.h#L90) macro, which is expanded to `.section    ".head.text","ax"` - this file is [head.S](https://github.com/torvalds/linux/blob/v4.14/arch/arm64/kernel/head.S).

The first executable line, that we can find in `head.S` file is [this one](https://github.com/torvalds/linux/blob/v4.14/arch/arm64/kernel/head.S#L85). Here we use arm assembler `b` of `branch` instruction to jump to the [stext](https://github.com/torvalds/linux/blob/v4.14/arch/arm64/kernel/head.S#L116) function. And this is the first function that is executed after you boot the kernel.

Next logical step is to explore what is going on inside the `stext` function - but we are not ready yet. First, we have to implement similar functionality in the RPi OS, and that is something we will cover in the next few lessons. What we are going to do right now is to examine a few critical concepts, related to kernel boot.

### Linux bootloader and boot protocol

When linux kernel boots it assumes that the machine hardware is prepared in some "known state". The set of rules that defines this state is called "boot protocol", and for `arm64` architecture it is documented [here](https://github.com/torvalds/linux/blob/v4.14/Documentation/arm64/booting.txt). Among other things, it defines, for example, that the execution must start only on primary CPU, Memory Mapping Unit must be turned off and all interrupts must be disabled. 

Ok, but who is responsible for bringing a machine into that known state? Usually, there is a special program that runs before the kernel and performs all initializations. This program is called `bootloader`. Bootloader code may be very machine specific, and this is the case, with Raspberry PI. Raspberry PI has a bootloader that is is built into the board. We can only use [config.txt](https://www.raspberrypi.org/documentation/configuration/config-txt/) file to customize its behavior. 

### UEFI boot

However, there is one boot loader that can be built into the kernel image itself. This bootloader can be used only on the platforms that support [Unified Extensible Firmware Interface (UEFI)](https://en.wikipedia.org/wiki/Unified_Extensible_Firmware_Interface). Devices that support UEFI provide a set of standardized services to the running software and those services can be used to figure out all necessary information about the machine itself and its capabilities. UEFI also requires that computer firmware should be capable of running executable files in [Portable Executable (PE)](https://en.wikipedia.org/wiki/Portable_Executable) format. Linux kernel UEFI bootloader makes use of this feature: it injects `PE` header at the beginning of the Linux kernel image so that computer firmware think that the image is a normal `PE` file. This is done in [efi-header.S](https://github.com/torvalds/linux/blob/v4.14/arch/arm64/kernel/efi-header.S) file. This file defines [__EFI_PE_HEADER](https://github.com/torvalds/linux/blob/v4.14/arch/arm64/kernel/efi-header.S#L13) macro, which is used inside [head.S](https://github.com/torvalds/linux/blob/v4.14/arch/arm64/kernel/head.S#L98).

One important property that is defined inside `__EFI_PE_HEADER` is the one that tells about the [location of the UEFI entry point](https://github.com/torvalds/linux/blob/v4.14/arch/arm64/kernel/efi-header.S#L33) and the entry point itself can be found in [efi-entry.S](https://github.com/torvalds/linux/blob/v4.14/arch/arm64/kernel/efi-entry.S#L32). Starting from this location, you can follow the source code and examine what exactly UEFI bootloader is doing (the source code itself is more or less straightforward). But we are going to stop here because the purpose of this section is not to examine UEFI bootloader in details, but instead, give you a general idea what UEFI is and how Linux kernel uses it.

### Device Tree

When I started to examine the startup code of the Linux kernel, I found a lot of mentions of `Device Trees`. It appears to be an essential concept, and I consider it necessary to discuss it.

When we were working on `Raspberry PI OS` kernel, we used [BCM2837 ARM Peripherals manual](https://github.com/raspberrypi/documentation/files/1888662/BCM2837-ARM-Peripherals.-.Revised.-.V2-1.pdf) to figure out what is the exact offset at which a particular memory mapped register is located. This information obviously is different for each board, and we are lucky that we have to support only one of them. But what if we need to support hundreds of different boards? It would be a total mess if we try to hardcode information about each board in the kernel code. And even if we manage to do so, how would we figure out what board we are using right now? `BCM2837`, for example, doesn't provide any means of communicating such information to the running kernel.

Device tree provides us with the solution to the problem, mentioned above. It is a special format that can be used to describe computer hardware. Device tree specification can be found [here](https://www.devicetree.org/). Before the kernel is executed, bootloader selects proper device tree file and passes it as an argument to the kernel. If you take a look at the files in the boot partition on a Raspberry PI SD card, you can find a lot of `.dtb` files here. `.dtb` are compiled device tree files. You can select some of them in the `config.txt` to enable or disable some Raspberry PI  hardware. This process is described in more details in the [Raspberry PI official documentation](https://www.raspberrypi.org/documentation/configuration/device-tree.md).

Ok, now it is time to take a look at how an actual device tree looks like. As a quick exercise, let's try to find a device tree for [Raspberry PI 3 Model B](https://www.raspberrypi.org/products/raspberry-pi-3-model-b/). From the [documentation](https://www.raspberrypi.org/documentation/hardware/raspberrypi/bcm2837/README.md) we can figure out that `Raspberry PI 3 Model B` uses a chip that is called `BCM2837`. If you search for this name you can find [/arch/arm64/boot/dts/broadcom/bcm2837-rpi-3-b.dts](https://github.com/torvalds/linux/blob/v4.14/arch/arm64/boot/dts/broadcom/bcm2837-rpi-3-b.dts)  file. As you might see it just includes the same file from `arm` architecture. This makes a perfect sense because `ARM.v8` processor supports 32-bit mode as well.

Next, we can find [bcm2837-rpi-3-b.dts](https://github.com/torvalds/linux/blob/v4.14/arch/arm/boot/dts/bcm2837-rpi-3-b.dts) belonging to the [arm](https://github.com/torvalds/linux/tree/v4.14/arch/arm) architecture. We already saw that device tree files could include on another. This is the case with the  `bcm2837-rpi-3-b.dts` - it only contains those definitions, that are specific for `BCM2837` and reuses everything else. For example,  `bcm2837-rpi-3-b.dts` specifies that [the device now have 1GB of memory](https://github.com/torvalds/linux/blob/v4.14/arch/arm/boot/dts/bcm2837-rpi-3-b.dts#L18). 

As I mentioned previously, `BCM2837` and `BCM2835` have an identical peripheral hardware, and, if you follow the chain of includes, you can find [bcm283x.dtsi](https://github.com/torvalds/linux/blob/v4.14/arch/arm/boot/dts/bcm283x.dtsi) that actually defines most of this hardware. 

A device tree definition consists of the blocks nested one in another. At the top level we usually can find such blocks as [cpus](https://github.com/torvalds/linux/blob/v4.14/arch/arm/boot/dts/bcm2837.dtsi#L30) or [memory](https://github.com/torvalds/linux/blob/v4.14/arch/arm/boot/dts/bcm2837-rpi-3-b.dts#L17) The meaning of those blocks should be quite self-explanatory. Another interesting top-level element that we can find in the `bcm283x.dtsi` is [SoC](https://github.com/torvalds/linux/blob/v4.14/arch/arm/boot/dts/bcm283x.dtsi#L52) that means [System on a chip](https://en.wikipedia.org/wiki/System_on_a_chip) It tells us that all peripheral devices are directly mapped to some memory area via memory mapped registers. `soc` element serves as a parent element for all peripheral devices. One of its children is [gpio](https://github.com/torvalds/linux/blob/v4.14/arch/arm/boot/dts/bcm283x.dtsi#L147) element. This element defines [reg = <0x7e200000 0xb4>](https://github.com/torvalds/linux/blob/v4.14/arch/arm/boot/dts/bcm283x.dtsi#L149) property that tells us that GPIO memory mapped registers are located in the  `[0x7e200000 : 0x7e2000b4]` region. One of the childern of `gpio` element has the [following definition](https://github.com/torvalds/linux/blob/v4.14/arch/arm/boot/dts/bcm283x.dtsi#L474)

```
uart1_gpio14: uart1_gpio14 {
        brcm,pins = <14 15>;
        brcm,function = <BCM2835_FSEL_ALT5>;
};
``` 
This definition tells us that if alternative function 5 is selected for pins 14 and 15 those pins will be connection to `uart1` device. You can easily gues that `uart1` device is the Mini UART that we have used already.

One important thing that you need to know about device trees is that the format is extendable. Each device can define its own properties and nested blocks. Those properties are transparently passed to the device driver, and it is driver responsibility to interpret them. But how can the kernel figure out the correspondence between a block in a device tree and the right driver? It uses `compatible` property to do this. For example, for `uart1` device `compatible` property is specified like this

```
compatible = "brcm,bcm2835-aux-uart";
```

And indeed, if you search for `bcm2835-aux-uart` in the Linux source code, you can find a matching driver, it is defined in [8250_bcm2835aux.c](https://github.com/torvalds/linux/blob/v4.14/drivers/tty/serial/8250/8250_bcm2835aux.c)

### Conclusion

You can think about this chapter as a preparation for reading `arm64` boot code - without understanding the concepts that we've just explored you would have a hard time learning it. In the next lesson, we will go back to the `stext` function and examine in details how it works.

##### Previous Page

1.3 [Kernel Initialization: Kernel build system](../../../docs/lesson01/linux/build-system.md)

##### Next Page

1.5 [Kernel Initialization: Exercises](../../../docs/lesson01/exercises.md)


================================================
FILE: docs/lesson01/linux/project-structure.md
================================================
## 1.2: Linux project structure

This is the first time we are going to talk about Linux. The idea is first to complete some small step in writing our own kernel, and then take a look at how the same things work in Linux. So far we have done very little: we just implemented our first bare metal hello world program, Still, we will be able to find some similarities between the RPi OS and Linux. And now we are going to explore some of them.

### Project structure

Whenever you start investigating any large software project, it worth taking a quick look at the project structure. This is very important because it allows you to understand what modules compose the project and what is the high-level architecture. Let's try to explore project structure of the Linux kernel.

First of all, you need to clone the Linux repository.

```
git clone -b v4.14 --depth 1 https://github.com/torvalds/linux.git
```

We are using `v4.14` version because this was the latest version at the time of writing. All references to the Linux source code will be made using this specific version.

Next, let's take a look at the folders that we can find inside the Linux repository. We are not going to look at all of them, but only at those that I consider the most important to start with.

* [arch](https://github.com/torvalds/linux/tree/v4.14/arch) This folder contains subfolders, each for a specific processor architecture. Mostly we are going to work with [arm64](https://github.com/torvalds/linux/tree/v4.14/arch/arm64) - this is the one that is compatible with ARM.v8 processors.
* [init](https://github.com/torvalds/linux/tree/v4.14/init) Kernel is always booted by architecture specific code. But then execution is passed to the [start_kernel](https://github.com/torvalds/linux/blob/v4.14/init/main.c#L509) function that is responsible for common kernel initialization and is an architecture independent kernel starting point. `start_kernel` function, together with some other initialization functions, is defined in the `init` folder.
* [kernel](https://github.com/torvalds/linux/tree/v4.14/kernel) This is the core of the Linux kernel. Almost all major kernel subsystems are implemented there.
* [mm](https://github.com/torvalds/linux/tree/v4.14/mm) All data structures and methods related to memory management are defined there.
* [drivers](https://github.com/torvalds/linux/tree/v4.14/drivers) This is the largest folder in the Linux kernel. It contains implementations of all device drivers.
* [fs](https://github.com/torvalds/linux/tree/v4.14/fs) You can look here to find different filesystem implementations.

This explanation is very high-level, but this is enough for now. In the next chapter, we will try to examine Linux build system in some details.

##### Previous Page

1.1 [Kernel Initialization: Introducing RPi OS, or bare metal "Hello, world!"](../../../docs/lesson01/rpi-os.md)

##### Next Page

1.3 [Kernel Initialization: Kernel build system](../../../docs/lesson01/linux/build-system.md)


================================================
FILE: docs/lesson01/rpi-os.md
================================================
## 1.1: Introducing RPi OS, or bare-metal "Hello, World!"

We are going to start our journey in OS development by writing a small, bare-metal "Hello, World" application. I assume that  you have gone through the [Prerequisites](../Prerequisites.md) and have everything ready. If not, now is the time to do this.

Before we move forward, I want to establish a simple naming convention. From the README file you can see that the whole tutorial is divided into lessons. Each lesson consists of individual files that I call "chapters" (right now, you are reading lesson 1, chapter 1.1). A chapter is further divided into "sections" with headings. This naming convention allows me to make references to different parts of the material.

Another thing I want you to pay attention to is that the tutorial contains a lot of source code samples. I'll usually start the explanation by providing the complete code block, and then describe it line by line. 

### Project structure

The source code of each lesson has the same structure. You can find this lesson's source code [here](https://github.com/s-matyukevich/raspberry-pi-os/tree/master/src/lesson01). Let's briefly describe the main components of this folder:
1. **Makefile** We will use the [make](http://www.math.tau.ac.il/~danha/courses/software1/make-intro.html) utility to build the kernel. `make`'s behavior is configured by a Makefile, which contains instructions on how to compile and link the source code. 
1. **build.sh or build.bat** You'll need these files if you want to build the kernel using Docker. You won't need to have the make utility or the compiler toolchain installed on your laptop.
1. **src** This folder contains all of the source code.
1. **include** All of the header files are placed here. 

### Makefile

Now let's take a closer look at the project Makefile. The primary purpose of the make utility is to automatically determine what pieces of a program need to be recompiled, and to issue commands to recompile them. If you are not familiar with make and Makefiles, I recommend that you read [this](http://opensourceforu.com/2012/06/gnu-make-in-detail-for-beginners/) article. 
The Makefile used in the first lesson can be found [here](https://github.com/s-matyukevich/raspberry-pi-os/blob/master/src/lesson01/Makefile). The whole Makefile is listed below:
```
ARMGNU ?= aarch64-linux-gnu

COPS = -Wall -nostdlib -nostartfiles -ffreestanding -Iinclude -mgeneral-regs-only
ASMOPS = -Iinclude 

BUILD_DIR = build
SRC_DIR = src

all : kernel8.img

clean :
    rm -rf $(BUILD_DIR) *.img 

$(BUILD_DIR)/%_c.o: $(SRC_DIR)/%.c
    mkdir -p $(@D)
    $(ARMGNU)-gcc $(COPS) -MMD -c $< -o $@

$(BUILD_DIR)/%_s.o: $(SRC_DIR)/%.S
    $(ARMGNU)-gcc $(ASMOPS) -MMD -c $< -o $@

C_FILES = $(wildcard $(SRC_DIR)/*.c)
ASM_FILES = $(wildcard $(SRC_DIR)/*.S)
OBJ_FILES = $(C_FILES:$(SRC_DIR)/%.c=$(BUILD_DIR)/%_c.o)
OBJ_FILES += $(ASM_FILES:$(SRC_DIR)/%.S=$(BUILD_DIR)/%_s.o)

DEP_FILES = $(OBJ_FILES:%.o=%.d)
-include $(DEP_FILES)

kernel8.img: $(SRC_DIR)/linker.ld $(OBJ_FILES)
    $(ARMGNU)-ld -T $(SRC_DIR)/linker.ld -o $(BUILD_DIR)/kernel8.elf  $(OBJ_FILES)
    $(ARMGNU)-objcopy $(BUILD_DIR)/kernel8.elf -O binary kernel8.img
``` 
Now, let's inspect this file in detail:
```
ARMGNU ?= aarch64-linux-gnu
```
The Makefile starts with a variable definition. `ARMGNU` is a cross-compiler prefix. We need to use a [cross-compiler](https://en.wikipedia.org/wiki/Cross_compiler) because we are compiling the source code for the `arm64` architecture on an `x86` machine. So instead of `gcc`, we will use `aarch64-linux-gnu-gcc`. 

```
COPS = -Wall -nostdlib -nostartfiles -ffreestanding -Iinclude -mgeneral-regs-only
ASMOPS = -Iinclude 
```

`COPS` and `ASMOPS` are options that we pass to the compiler when compiling C and assembler code, respectively. These options require a short explanation:

* **-Wall** Show all warnings.
* **-nostdlib** Don't use the C standard library. Most of the calls in the C standard library eventually interact with the operating system. We are writing a bare-metal program, and we don't have any underlying operating system, so the C standard library is not going to work for us anyway.
* **-nostartfiles** Don't use standard startup files. Startup files are responsible for setting an initial stack pointer, initializing static data, and jumping to the main entry point. We are going to do all of this by ourselves.
* **-ffreestanding** A freestanding environment is an environment in which the standard library may not exist, and program startup may not necessarily be at main. The option `-ffreestanding` directs the compiler to not assume that standard functions have their usual definition.
* **-Iinclude** Search for header files in the `include` folder.
* **-mgeneral-regs-only**. Use only general-purpose registers. ARM processors also have [NEON](https://developer.arm.com/technologies/neon) registers. We don't want the compiler to use them because they add additional complexity (since, for example, we will need to store the registers during a context switch).

```
BUILD_DIR = build
SRC_DIR = src
```

`SRC_DIR` and `BUILD_DIR` are directories that contain source code and compiled object files, respectively.

```
all : kernel8.img

clean :
    rm -rf $(BUILD_DIR) *.img 
```

Next, we define make targets. The first two targets are pretty simple: the `all` target is the default one, and it is executed whenever you type `make` without any arguments (`make` always uses the first target as the default). This target just redirects all work to a different target, `kernel8.img`. 
The `clean` target is responsible for deleting all compilation artifacts and the compiled kernel image.

```
$(BUILD_DIR)/%_c.o: $(SRC_DIR)/%.c
    mkdir -p $(@D)
    $(ARMGNU)-gcc $(COPS) -MMD -c $< -o $@

$(BUILD_DIR)/%_s.o: $(SRC_DIR)/%.S
    $(ARMGNU)-gcc $(ASMOPS) -MMD -c $< -o $@
```

The next two targets are responsible for compiling C and assembler files. If, for example, in the `src` directory we have `foo.c` and `foo.S` files, they will be compiled into `build/foo_c.o` and `build/foo_s.o`, respectively. `$<` and `$@` are substituted at runtime with the input and output filenames (`foo.c` and `foo_c.o`). Before compiling C files, we also create a `build` directory in case it doesn't exist yet.

```
C_FILES = $(wildcard $(SRC_DIR)/*.c)
ASM_FILES = $(wildcard $(SRC_DIR)/*.S)
OBJ_FILES = $(C_FILES:$(SRC_DIR)/%.c=$(BUILD_DIR)/%_c.o)
OBJ_FILES += $(ASM_FILES:$(SRC_DIR)/%.S=$(BUILD_DIR)/%_s.o)
```

Here we are building an array of all object files (`OBJ_FILES`) created from the concatenation of both C and assembler source files (see [Substitution References](https://www.gnu.org/software/make/manual/html_node/Substitution-Refs.html)).

```
DEP_FILES = $(OBJ_FILES:%.o=%.d)
-include $(DEP_FILES)
```

The next two lines are a little bit tricky. If you take a look at how we defined our compilation targets for both C and assembler source files, you will notice that we used the `-MMD` parameter. This parameter instructs the `gcc` compiler to create a dependency file for each generated object file. A dependency file defines all of the dependencies for a particular source file. These dependencies usually contain a list of all included headers. We need to include all of the generated dependency files so that make knows what exactly to recompile in case a header changes. 

```
$(ARMGNU)-ld -T $(SRC_DIR)/linker.ld -o kernel8.elf  $(OBJ_FILES)
``` 

We use the `OBJ_FILES` array to build the `kernel8.elf` file. We use the linker script `src/linker.ld` to define the basic layout of the resulting executable image (we will discuss the linker script in the next section).

```
$(ARMGNU)-objcopy kernel8.elf -O binary kernel8.img
```

`kernel8.elf` is in the [ELF](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format) format. The problem is that ELF files are designed to be executed by an operating system. To write a bare-metal program, we need to extract all executable and data sections from the ELF file and put them into the `kernel8.img` image. The trailing `8` denotes ARMv8 which is a 64-bit architecture. This filename tells the firmware to boot the processor into 64-bit mode.
You can also boot the CPU in the 64-bit mode by using `arm_control=0x200` flag in the `config.txt` file. The RPi OS previously used this method, and you can still find it in some of the exercise answers. However, `arm_control` flag is undocumented and it is preferable to use `kernel8.img` naming convention instead.

### The linker script

The primary purpose of the linker script is to describe how the sections in the input object files (`_c.o` and `_s.o`) should be mapped into the output file (`.elf`). More information about linker scripts can be found [here](https://sourceware.org/binutils/docs/ld/Scripts.html#Scripts). Now let's take a look at the RPi OS linker script:

```
SECTIONS
{
    .text.boot : { *(.text.boot) }
    .text :  { *(.text) }
    .rodata : { *(.rodata) }
    .data : { *(.data) }
    . = ALIGN(0x8);
    bss_begin = .;
    .bss : { *(.bss*) } 
    bss_end = .;
}
``` 

After startup, the Raspberry Pi loads `kernel8.img` into memory and starts execution from the beginning of the file. That's why the `.text.boot` section must be first; we are going to put the OS startup code inside this section. 
The `.text`, `.rodata`, and `.data` sections contain kernel-compiled instructions, read-only data, and normal data––there is nothing special to add about them.
The `.bss` section contains data that should be initialized to 0. By putting such data in a separate section, the compiler can save some space in the ELF binary––only the section size is stored in the ELF header, but the section itself is omitted. After loading the image into memory, we must initialize the `.bss` section to 0; that's why we need to record the start and end of the section (hence the `bss_begin` and `bss_end` symbols) and align the section so that it starts at an address that is a multiple of 8. If the section is not aligned, it would be more difficult to use the `str` instruction to store 0 at the beginning of the `bss` section because the `str` instruction can be used only with 8-byte-aligned addresses.

### Booting the kernel

Now it is time to take a look at the [boot.S](https://github.com/s-matyukevich/raspberry-pi-os/blob/master/src/lesson01/src/boot.S) file. This file contains the kernel startup code:

```
#include "mm.h"

.section ".text.boot"

.globl _start
_start:
    mrs    x0, mpidr_el1        
    and    x0, x0,#0xFF        // Check processor id
    cbz    x0, master        // Hang for all non-primary CPU
    b    proc_hang

proc_hang: 
    b proc_hang

master:
    adr    x0, bss_begin
    adr    x1, bss_end
    sub    x1, x1, x0
    bl     memzero

    mov    sp, #LOW_MEMORY
    bl    kernel_main
```
Let's review this file in detail:
```
.section ".text.boot"
```
First, we specify that everything defined in `boot.S` should go in the `.text.boot` section. Previously, we saw that this section is placed at the beginning of the kernel image by the linker script. So when the kernel is started, execution begins at the `start` function:
```
.globl _start
_start:
    mrs    x0, mpidr_el1        
    and    x0, x0,#0xFF        // Check processor id
    cbz    x0, master        // Hang for all non-primary CPU
    b    proc_hang
```

The first thing this function does is check the processor ID. The Raspberry Pi 3 has four core processors, and after the device is powered on, each core begins to execute the same code. However, we don't want to work with four cores; we want to work only with the first one and put all of the other cores in an endless loop. This is exactly what the `_start` function is responsible for. It gets the processor ID from the [mpidr_el1](http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0500g/BABHBJCI.html) system register. 
If the current process ID is 0, then execution is transferred to the `master` function:

```
master:
    adr    x0, bss_begin
    adr    x1, bss_end
    sub    x1, x1, x0
    bl     memzero
```

Here, we clean the `.bss` section by calling `memzero`. We will define this function later. In ARMv8 architecture, by convention, the first seven arguments are passed to the called function via registers x0–x6. The `memzero` function accepts only two arguments: the start address (`bss_begin`) and the size of the section needed to be cleaned (`bss_end - bss_begin`).

```
    mov    sp, #LOW_MEMORY
    bl    kernel_main
```

After cleaning the `.bss` section, we initialize the stack pointer and pass execution to the `kernel_main` function. The Raspberry Pi loads the kernel at address 0; that's why the initial stack pointer can be set to any location high enough so that stack will not override the kernel image when it grows sufficiently large. `LOW_MEMORY` is defined in [mm.h](https://github.com/s-matyukevich/raspberry-pi-os/blob/master/src/lesson01/include/mm.h) and is equal to 4MB. Our kernel's stack won't grow very large and the image itself is tiny, so `4MB` is more than enough for us. 

For those of you who are not familiar with ARM assembler syntax, let me quickly summarize the instructions that we have used:

* [**mrs**](http://www.keil.com/support/man/docs/armasm/armasm_dom1361289881374.htm) Load value from a system register to one of the general purpose registers (x0–x30)
* [**and**](http://www.keil.com/support/man/docs/armasm/armasm_dom1361289863017.htm) Perform the logical AND operation. We use this command to strip the last byte from the value we obtain from the `mpidr_el1` register.
* [**cbz**](http://www.keil.com/support/man/docs/armasm/armasm_dom1361289867296.htm) Compare the result of the previously executed operation to 0 and jump (or `branch` in ARM terminology) to the provided label if the comparison yields true.
* [**b**](http://www.keil.com/support/man/docs/armasm/armasm_dom1361289863797.htm) Perform an unconditional branch to some label.
* [**adr**](http://www.keil.com/support/man/docs/armasm/armasm_dom1361289862147.htm) Load a label's relative address into the target register. In this case, we want pointers to the start and end of the `.bss` region.
* [**sub**](http://www.keil.com/support/man/docs/armasm/armasm_dom1361289908389.htm) Subtract values from two registers.
* [**bl**](http://www.keil.com/support/man/docs/armasm/armasm_dom1361289865686.htm) "Branch with a link": perform an unconditional branch and store the return address in x30 (the link register). When the subroutine is finished, use the `ret` instruction to jump back to the return address.
* [**mov**](http://www.keil.com/support/man/docs/armasm/armasm_dom1361289878994.htm) Move a value between registers or from a constant to a register.

[Here](http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.den0024a/index.html) is the ARMv8-A developer's guide. It's a good resource if the ARM ISA is unfamiliar to you. [This page](http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.den0024a/ch09s01s01.html) specifically outlines the register usage convention in the ABI.

### The `kernel_main` function

We have seen that the boot code eventually passes control to the `kernel_main` function. Let's take a look at it:

```
#include "mini_uart.h"

void kernel_main(void)
{
    uart_init();
    uart_send_string("Hello, world!\r\n");

    while (1) {
        uart_send(uart_recv());
    }
}

```

This function is one of the simplest in the kernel. It works with the `Mini UART` device to print to screen and read user input. The kernel just prints `Hello, world!` and then enters an infinite loop that reads characters from the user and sends them back to the screen.

### Raspberry Pi devices 

Now we are going to dig into something specific to the Raspberry Pi. Before we begin, I recommend that you download the [BCM2837 ARM Peripherals manual](https://github.com/raspberrypi/documentation/files/1888662/BCM2837-ARM-Peripherals.-.Revised.-.V2-1.pdf). BCM2837 is a board that is used by the Raspberry Pi 3 Models B, and B+. Sometime in our discussion, I will also mention BCM2835 and BCM2836 - those are names of the board used in older versions of the Raspberry Pi.  

Before we proceed to the implementation details, I want to share some basic concepts on how to work with memory-mapped devices. BCM2837 is a simple [SOC (System on a chip)](https://en.wikipedia.org/wiki/System_on_a_chip) board. In such a board, access to all devices is performed via memory-mapped registers. The Raspberry Pi 3 reserves the memory above address `0x3F000000` for devices. To activate or configure a particular device, you need to write some data in one of the device's registers. A device register is just a 32-bit region of memory. The meaning of each bit in each device register is described in the `BCM2837 ARM Peripherals` manual. Take a look at section 1.2.3 ARM physical addresses in the manual and the surrounding documentation for more context on why we use `0x3F000000` as a base address (even though `0x7E000000` is used throughout the manual).

From the `kernel_main` function, you can guess that we are going to work with a Mini UART device. UART stands for [Universal asynchronous receiver-transmitter](https://en.wikipedia.org/wiki/Universal_asynchronous_receiver-transmitter). This device is capable of converting values stored in one of its memory mapped registers to a sequence of high and low voltages. This sequence is passed to your computer via the `TTL-to-serial cable` and is interpreted by your terminal emulator. We are going to use the Mini UART to facilitate communication with our Raspberry Pi. If you want to see the specification of the Mini UART registers, please go to page 8 of the `BCM2837 ARM Peripherals` manual. 

A Raspberry Pi has two UARTs: Mini UART and PL011 UART. In this tutorial, we are going to work only with the first one, because it is simpler. There is, however, an optional [exercise](https://github.com/s-matyukevich/raspberry-pi-os/blob/master/docs/lesson01/exercises.md) that shows how to work with PL011 UART. You can refer to the [official documentation](https://www.raspberrypi.org/documentation/configuration/uart.md) if you want to find out more about Raspberry Pi UARTs and learn the difference between them.

Another device that you need to familiarize yourself with is the GPIO [General-purpose input/output](https://en.wikipedia.org/wiki/General-purpose_input/output). GPIOs are responsible for controlling `GPIO pins`. You should be able to easily recognize them in the image below:

![Raspberry Pi GPIO pins](../../images/gpio-pins.jpg)

The GPIO can be used to configure the behavior of different GPIO pins. For example, to be able to use the Mini UART, we need to activate pins 14 and 15 and set them up to use this device. The image below illustrates how numbers are assigned to the GPIO pins:

![Raspberry Pi GPIO pin numbers](../../images/gpio-numbers.png)

### Mini UART initialization

Now let's take a look at how mini UART is initialized. This code is defined in [mini_uart.c](https://github.com/s-matyukevich/raspberry-pi-os/blob/master/src/lesson01/src/mini_uart.c):

```
void uart_init ( void )
{
    unsigned int selector;

    selector = get32(GPFSEL1);
    selector &= ~(7<<12);                   // clean gpio14
    selector |= 2<<12;                      // set alt5 for gpio14
    selector &= ~(7<<15);                   // clean gpio15
    selector |= 2<<15;                      // set alt5 for gpio 15
    put32(GPFSEL1,selector);

    put32(GPPUD,0);
    delay(150);
    put32(GPPUDCLK0,(1<<14)|(1<<15));
    delay(150);
    put32(GPPUDCLK0,0);

    put32(AUX_ENABLES,1);                   //Enable mini uart (this also enables access to its registers)
    put32(AUX_MU_CNTL_REG,0);               //Disable auto flow control and disable receiver and transmitter (for now)
    put32(AUX_MU_IER_REG,0);                //Disable receive and transmit interrupts
    put32(AUX_MU_LCR_REG,3);                //Enable 8 bit mode
    put32(AUX_MU_MCR_REG,0);                //Set RTS line to be always high
    put32(AUX_MU_BAUD_REG,270);             //Set baud rate to 115200

    put32(AUX_MU_CNTL_REG,3);               //Finally, enable transmitter and receiver
}
``` 

Here, we use the two functions `put32` and `get32`. Those functions are very simple; they allow us to read and write some data to and from a 32-bit register. You can take a look at how they are implemented in [utils.S](https://github.com/s-matyukevich/raspberry-pi-os/blob/master/src/lesson01/src/utils.S). `uart_init` is one of the most complex and important functions in this lesson, and we will continue to examine it in the next three sections.

#### GPIO alternative function selection 

First, we need to activate the GPIO pins. 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. You can see the list of all available GPIO alternative functions in the image below (the image is taken from page 102 of `BCM2837 ARM Peripherals` manual):

![Raspberry Pi GPIO alternative functions](../../images/alt.png?raw=true)

Here you can see that pins 14 and 15 have the TXD1 and RXD1 alternative functions available. This means that if we select alternative function number 5 for pins 14 and 15, they will be used as a Mini UART Transmit Data pin and Mini UART Receive Data pin, respectively. The `GPFSEL1` register is used to control alternative functions for pins 10-19. The meaning of all the bits in those registers is shown in the following table (page 92 of `BCM2837 ARM Peripherals` manual):

![Raspberry Pi GPIO function selector](../../images/gpfsel1.png?raw=true)

So now you know everything you need to understand the following lines of code that are used to configure GPIO pins 14 and 15 to work with the Mini UART device:

```
    unsigned int selector;

    selector = get32(GPFSEL1);
    selector &= ~(7<<12);                   // clean gpio14
    selector |= 2<<12;                      // set alt5 for gpio14
    selector &= ~(7<<15);                   // clean gpio15
    selector |= 2<<15;                      // set alt5 for gpio 15
    put32(GPFSEL1,selector);
```

#### GPIO pull-up/down 

When you work with Raspberry Pi GPIO pins, you will often encounter terms such as pull-up/pull-down. These concepts are explained in great detail in [this](https://grantwinney.com/using-pullup-and-pulldown-resistors-on-the-raspberry-pi/) article. For those who are too lazy to read the whole article, I will briefly explain the pull-up/pull-down concept.

If you use a particular pin as input and don't connect anything to this pin, you will not be able to identify whether the value of the pin is 1 or 0. In fact, the device will report random values. The pull-up/pull-down mechanism allows you to overcome this issue. If you set the pin to the pull-up state and nothing is connected to it, it will report `1` all the time (for the pull-down state, the value will always be 0). In our case, we need neither the pull-up nor the pull-down state, because both the 14 and 15 pins are going to be connected all the time. The pin state is preserved even after a reboot, so before using any pin, we always have to initialize its state. There are three available states: pull-up, pull-down, and neither (to remove the current pull-up or pull-down state), and we need the third one.

Switching between pin states is not a very simple procedure because it requires physically toggling a switch on the electric circuit. This process involves the `GPPUD` and `GPPUDCLK` registers and is described on page 101 of the `BCM2837 ARM Peripherals` manual. I copied the description here:

```
The GPIO Pull-up/down Clock Registers control the actuation of internal pull-downs on
the respective GPIO pins. These registers must be used in conjunction with the GPPUD
register to effect GPIO Pull-up/down changes. The following sequence of events is
required:
1. Write to GPPUD to set the required control signal (i.e. Pull-up or Pull-Down or neither
to remove the current Pull-up/down)
2. Wait 150 cycles – this provides the required set-up time for the control signal
3. Write to GPPUDCLK0/1 to clock the control signal into the GPIO pads you wish to
modify – NOTE only the pads which receive a clock will be modified, all others will
retain their previous state.
4. Wait 150 cycles – this provides the required hold time for the control signal
5. Write to GPPUD to remove the control signal
6. Write to GPPUDCLK0/1 to remove the clock
``` 

This procedure describes how we can remove both the pull-up and pull-down states from a pin, which is what we are doing for pins 14 and 15 in the following code:

```
    put32(GPPUD,0);
    delay(150);
    put32(GPPUDCLK0,(1<<14)|(1<<15));
    delay(150);
    put32(GPPUDCLK0,0);
```

#### Initializing the Mini UART

Now our Mini UART is connected to the GPIO pins, and the pins are configured. The rest of the `uart_init` function is dedicated to Mini UART initialization. 

```
    put32(AUX_ENABLES,1);                   //Enable mini uart (this also enables access to its registers)
    put32(AUX_MU_CNTL_REG,0);               //Disable auto flow control and disable receiver and transmitter (for now)
    put32(AUX_MU_IER_REG,0);                //Disable receive and transmit interrupts
    put32(AUX_MU_LCR_REG,3);                //Enable 8 bit mode
    put32(AUX_MU_MCR_REG,0);                //Set RTS line to be always high
    put32(AUX_MU_BAUD_REG,270);             //Set baud rate to 115200

    put32(AUX_MU_CNTL_REG,3);               //Finally, enable transmitter and receiver
```
Let's examine this code snippet line by line. 

```
    put32(AUX_ENABLES,1);                   //Enable mini uart (this also enables access to its registers)
```
This line enables the Mini UART. We must do this in the beginning, because this also enables access to all the other Mini UART registers.

```
    put32(AUX_MU_CNTL_REG,0);               //Disable auto flow control and disable receiver and transmitter (for now)
```
Here we disable the receiver and transmitter before the configuration is finished. We also permanently disable auto-flow control because it requires us to use additional GPIO pins, and the TTL-to-serial cable doesn't support it. For more information about auto-flow control, you can refer to [this](http://www.deater.net/weave/vmwprod/hardware/pi-rts/) article.

```
    put32(AUX_MU_IER_REG,0);                //Disable receive and transmit interrupts
```
It is possible to configure the Mini UART to generate a processor interrupt each time new data is available. We are going to start working with interrupts in lesson 3, so for now, we will just disable this feature.

```
    put32(AUX_MU_LCR_REG,3);                //Enable 8 bit mode
```
Mini UART can support either 7- or 8-bit operations. This is because an ASCII character is 7 bits for the standard set and 8 bits for the extended. We are going to use 8-bit mode. 

```
    put32(AUX_MU_MCR_REG,0);                //Set RTS line to be always high
```
The RTS line is used in the flow control and we don't need it. Set it to be high all the time.
```
    put32(AUX_MU_BAUD_REG,270);             //Set baud rate to 115200
```
The baud rate is the rate at which information is transferred in a communication channel. “115200 baud” means that the serial port is capable of transferring a maximum of 115200 bits per second. The baud rate of your Raspberry Pi mini UART device should be the same as the baud rate in your terminal emulator. 
The Mini UART calculates baud rate according to the following equation:
```
baudrate = system_clock_freq / (8 * ( baudrate_reg + 1 )) 
```
The `system_clock_freq` is 250 MHz, so we can easily calculate the value of `baudrate_reg` as 270.

``` 
    put32(AUX_MU_CNTL_REG,3);               //Finally, enable transmitter and receiver
```
After this line is executed, the Mini UART is ready for work!

### Sending data using the Mini UART

After the Mini UART is ready, we can try to use it to send and receive some data. To do this, we can use the following two functions:

```
void uart_send ( char c )
{
    while(1) {
        if(get32(AUX_MU_LSR_REG)&0x20) 
            break;
    }
    put32(AUX_MU_IO_REG,c);
}

char uart_recv ( void )
{
    while(1) {
        if(get32(AUX_MU_LSR_REG)&0x01) 
            break;
    }
    return(get32(AUX_MU_IO_REG)&0xFF);
}
```

Both of the functions start with an infinite loop, the purpose of which is to verify whether the device is ready to transmit or receive data. We are using  the `AUX_MU_LSR_REG` register to do this. Bit zero, if set to 1, indicates that the data is ready; this means that we can read from the UART. Bit five, if set to 1, tells us that the transmitter is empty, meaning that we can write to the UART.
Next, we use `AUX_MU_IO_REG` to either store the value of the transmitted character or read the value of the received character.

We also have a very simple function that is capable of sending strings instead of characters:

```
void uart_send_string(char* str)
{
    for (int i = 0; str[i] != '\0'; i ++) {
        uart_send((char)str[i]);
    }
}
```
This function just iterates over all characters in a string and sends them one by one. 

### Raspberry Pi config

The Raspberry Pi startup sequence is the following (simplified):

1. The device is powered on.
1. The GPU starts up and reads the `config.txt` file from the boot partition. This file contains some configuration parameters that the GPU uses to further adjust the startup sequence.
1. `kernel8.img` is loaded into memory and executed.

To be able to run our simple OS, the `config.txt` file should be the following:

```
kernel_old=1
disable_commandline_tags=1
```
* `kernel_old=1` specifies that the kernel image should be loaded at address 0.
* `disable_commandline_tags` instructs the GPU to not pass any command line arguments to the booted image.


### Testing the kernel

Now that we have gone through all of the source code, it is time to see it work. To build and test the kernel you need to  do the following:

1. Execute `./build.sh` or `./build.bat` from [src/lesson01](https://github.com/s-matyukevich/raspberry-pi-os/tree/master/src/lesson01) in order to build the kernel. 
1. Copy the generated `kernel8.img` file to the `boot` partition of your Raspberry Pi flash card and delete `kernel7.img` as well as any other `kernel*.img` files that may be present on your SD card. Make sure you left all other files in the boot partition untouched (see [43](https://github.com/s-matyukevich/raspberry-pi-os/issues/43) and [158](https://github.com/s-matyukevich/raspberry-pi-os/issues/158) issues for details)
1. Modify the `config.txt` file as described in the previous section.
1. Connect the USB-to-TTL serial cable as described in the [Prerequisites](../Prerequisites.md).
1. Power on your Raspberry Pi.
1. Open your terminal emulator. You should be able to see the `Hello, world!` message there.

Note that the sequence of steps described above asumes that you have Raspbian installed on your SD card. It is also posible to run the RPi OS using an empty SD card.

1. Prepare your SD card:
    * Use an MBR partition table
    * Format the boot partition as FAT32
    > The card should be formatted exactly in the same way as it is required to install Raspbian. Check `HOW TO FORMAT AN SD CARD AS FAT` section in the [official documentation](https://www.raspberrypi.org/documentation/installation/noobs.md) for more information.
1. Copy the following files to the card:
    * [bootcode.bin](https://github.com/raspberrypi/firmware/blob/master/boot/bootcode.bin) This is the GPU bootloader, it contains the GPU code to start the GPU and load the GPU firmware. 
    * [start.elf](https://github.com/raspberrypi/firmware/blob/master/boot/start.elf) This is the GPU firmware. It reads `config.txt` and enables the GPU to load and run ARM specific user code from `kernel8.img`
1. Copy `kernel8.img` and `config.txt` files. 
1. Connect the USB-to-TTL serial cable.
1. Power on your Raspberry Pi.
1. Use your terminal emulator to connect to the RPi OS. 

Unfortunately, all Raspberry Pi firmware files are closed-sourced and undocumented. For more information about the Raspberry Pi startup sequence, you can refer to some unofficial sources, like [this](https://raspberrypi.stackexchange.com/questions/10442/what-is-the-boot-sequence) StackExchange question or [this](https://github.com/DieterReuter/workshop-raspberrypi-64bit-os/blob/master/part1-bootloader.md) Github repository.

##### Previous Page

[Prerequisites](../../docs/Prerequisites.md)

##### Next Page

1.2 [Kernel Initialization: Linux project structure](../../docs/lesson01/linux/project-structure.md)


================================================
FILE: docs/lesson02/exercises.md
================================================
## 2.3: Exercises

1. Instead of jumping directly from EL3 to EL1, try to get to EL2 first and only then switch to EL1. 
1. One issue that I ran into when working on this lesson was that if FP/SIMD registers are used then everything works well at EL3, but as soon as you get to EL1 print function stops working. This was the reason why I've added [-mgeneral-regs-only](https://github.com/s-matyukevich/raspberry-pi-os/blob/master/src/lesson02/Makefile#L3) parameter to the compiler options. Now I want you to remove this parameter and reproduce this behavior. Next, you can use `objdump` tool to see how exactly gcc make use of FP/SIMD registers in the absence of `-mgeneral-regs-only` flag. Finally, I want you to use 'cpacr_el1' to allow using FP/SIMD registers.
1. Adapt lesson 02 to run on qemu. Check [this](https://github.com/s-matyukevich/raspberry-pi-os/issues/8) issue for reference.

##### Previous Page

2.2 [Processor initialization: Linux](../../docs/lesson02/linux.md)

##### Next Page

3.1 [Interrupt handling: RPi OS](../../docs/lesson03/rpi-os.md)


================================================
FILE: docs/lesson02/linux.md
================================================
## 2.2: Processor initialization (Linux)

We stopped our exploration of the Linux kernel at [stext](https://github.com/torvalds/linux/blob/v4.14/arch/arm64/kernel/head.S#L116) function, which is the entry point of `arm64` architecture. This time we are going to go a little bit deeper and find some similarities with the code that we have already implemented in this and previous lessons. 

You may find this chapter a little bit boring because it mostly discusses different ARM system registers and how they are used in the Linux kernel. But I still consider it very important for the following reasons:

1. It is necessary to understand the interface that the hardware provides to the software. Just by knowing this interface you will be able, in many cases, to deconstruct how a particular kernel feature is implemented and how software and hardware collaborate to implement this feature.
1. Different options in the system register are usually related to enabling/disabling various hardware features. If you learn what different system registers an ARM processor have you will already have an idea what kind of functionality it supports.

Ok, now let's resume our investigation of the `stext` function.

```
ENTRY(stext)
    bl    preserve_boot_args
    bl    el2_setup            // Drop to EL1, w0=cpu_boot_mode
    adrp    x23, __PHYS_OFFSET
    and    x23, x23, MIN_KIMG_ALIGN - 1    // KASLR offset, defaults to 0
    bl    set_cpu_boot_mode_flag
    bl    __create_page_tables
    /*
     * The following calls CPU setup code, see arch/arm64/mm/proc.S for
     * details.
     * On return, the CPU will be ready for the MMU to be turned on and
     * the TCR will have been set.
     */
    bl    __cpu_setup            // initialise processor
    b    __primary_switch
ENDPROC(stext)
``` 

### preserve_boot_args

[preserve_boot_args](https://github.com/torvalds/linux/blob/v4.14/arch/arm64/kernel/head.S#L136) function is responsible for saving parameters, passed to the kernel by the bootloader. 

```
preserve_boot_args:
    mov    x21, x0                // x21=FDT

    adr_l    x0, boot_args            // record the contents of
    stp    x21, x1, [x0]            // x0 .. x3 at kernel entry
    stp    x2, x3, [x0, #16]

    dmb    sy                // needed before dc ivac with
                        // MMU off

    mov    x1, #0x20            // 4 x 8 bytes
    b    __inval_dcache_area        // tail call
ENDPROC(preserve_boot_args)
```

Accordingly to the [kernel boot protocol](https://github.com/torvalds/linux/blob/v4.14/Documentation/arm64/booting.txt#L150), parameters are passed to the kernel in registers `x0 - x3`. `x0` contains the physical address of device tree blob (`.dtb`) in system RAM. `x1 - x3` are reserved for future usage. What this function is doing is copying the content of `x0 - x3` registers to the [boot_args](https://github.com/torvalds/linux/blob/v4.14/arch/arm64/kernel/setup.c#L93) array and then [invalidate](https://developer.arm.com/docs/den0024/latest/caches/cache-maintenance) the corresponding cache line from the data cache. Cache maintenance in a multiprocessor system is a large topic on its own, and we are going to skip it for now. For those who are interested in this subject, I can recommend reading [Caches](https://developer.arm.com/docs/den0024/latest/caches) and [Multi-core processors](https://developer.arm.com/docs/den0024/latest/multi-core-processors) chapters of the `ARM Programmer’s Guide`.

### el2_setup

Accordingly to the [arm64boot protocol](https://github.com/torvalds/linux/blob/v4.14/Documentation/arm64/booting.txt#L159), the kernel can be booted in either EL1 or EL2. In the second case, the kernel has access to the virtualization extensions and is able to act as a host operating system. If we are lucky enough to be booted in EL2, [el2_setup](https://github.com/torvalds/linux/blob/v4.14/arch/arm64/kernel/head.S#L386) function is called. It is responsible for configuring different parameters, accessible only at EL2, and dropping to EL1. Now I am going to split this function into small parts and explain each piece one by one.

```
    msr    SPsel, #1            // We want to use SP_EL{1,2}
``` 

Dedicated stack pointer will be used for both EL1 and EL2. Another option is to reuse stack pointer from EL0.

```
    mrs    x0, CurrentEL
    cmp    x0, #CurrentEL_EL2
    b.eq    1f
```

Only if current EL is EL2 branch to label `1`, otherwise we can't do EL2 setup and not much is left to be done in this function.

```
    mrs    x0, sctlr_el1
CPU_BE(    orr    x0, x0, #(3 << 24)    )    // Set the EE and E0E bits for EL1
CPU_LE(    bic    x0, x0, #(3 << 24)    )    // Clear the EE and E0E bits for EL1
    msr    sctlr_el1, x0
    mov    w0, #BOOT_CPU_MODE_EL1        // This cpu booted in EL1
    isb
    ret
```

If it happens that we execute at EL1, `sctlr_el1` register is updated so that CPU works in either `big-endian` of `little-endian` mode depending on the value of [CPU_BIG_ENDIAN](https://github.com/torvalds/linux/blob/v4.14/arch/arm64/Kconfig#L612) config setting. Then we just exit from the `el2_setup` function and return [BOOT_CPU_MODE_EL1](https://github.com/torvalds/linux/blob/v4.14/arch/arm64/include/asm/virt.h#L55) constant. Accordingly to [ARM64 Function Calling Conventions](http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf) return value should be placed in `x0` register (or `w0` in our case. You can think about `w0` register as the first 32 bit of `x0`.).

```
1:    mrs    x0, sctlr_el2
CPU_BE(    orr    x0, x0, #(1 << 25)    )    // Set the EE bit for EL2
CPU_LE(    bic    x0, x0, #(1 << 25)    )    // Clear the EE bit for EL2
    msr    sctlr_el2, x0
```

If it appears that we are booted in EL2 we are doing the same kind of setup for EL2 (note that this time `sctlr_el2` register is used instead of `sctlr_el1`.).

```
#ifdef CONFIG_ARM64_VHE
    /*
     * Check for VHE being present. For the rest of the EL2 setup,
     * x2 being non-zero indicates that we do have VHE, and that the
     * kernel is intended to run at EL2.
     */
    mrs    x2, id_aa64mmfr1_el1
    ubfx    x2, x2, #8, #4
#else
    mov    x2, xzr
#endif
```

If [Virtualization Host Extensions (VHE)](https://developer.arm.com/products/architecture/a-profile/docs/100942/latest/aarch64-virtualization) is enabled via [ARM64_VHE](https://github.com/torvalds/linux/blob/v4.14/arch/arm64/Kconfig#L926) config variable and the host machine supports them, `x2` then is updated with non zero value. `x2` will be used to check whether `VHE` is enabled later in the same function.

```
    mov    x0, #HCR_RW            // 64-bit EL1
    cbz    x2, set_hcr
    orr    x0, x0, #HCR_TGE        // Enable Host Extensions
    orr    x0, x0, #HCR_E2H
set_hcr:
    msr    hcr_el2, x0
    isb
```

Here we set `hcr_el2` register. We used the same register to set 64-bit execution mode for EL1 in the RPi OS. This is exactly what is done in the first line of the provided code sample. Also if `x2 != 0`, which means that VHE is available and the kernel is configured to use it, `hcr_el2` is also used to enable VHE.

```
    /*
     * Allow Non-secure EL1 and EL0 to access physical timer and counter.
     * This is not necessary for VHE, since the host kernel runs in EL2,
     * and EL0 accesses are configured in the later stage of boot process.
     * Note that when HCR_EL2.E2H == 1, CNTHCTL_EL2 has the same bit layout
     * as CNTKCTL_EL1, and CNTKCTL_EL1 accessing instructions are redefined
     * to access CNTHCTL_EL2. This allows the kernel designed to run at EL1
     * to transparently mess with the EL0 bits via CNTKCTL_EL1 access in
     * EL2.
     */
    cbnz    x2, 1f
    mrs    x0, cnthctl_el2
    orr    x0, x0, #3            // Enable EL1 physical timers
    msr    cnthctl_el2, x0
1:
    msr    cntvoff_el2, xzr        // Clear virtual offset

```

Next piece of code is well explained in the comment above it. I have nothing to add.

```
#ifdef CONFIG_ARM_GIC_V3
    /* GICv3 system register access */
    mrs    x0, id_aa64pfr0_el1
    ubfx    x0, x0, #24, #4
    cmp    x0, #1
    b.ne    3f

    mrs_s    x0, SYS_ICC_SRE_EL2
    orr    x0, x0, #ICC_SRE_EL2_SRE    // Set ICC_SRE_EL2.SRE==1
    orr    x0, x0, #ICC_SRE_EL2_ENABLE    // Set ICC_SRE_EL2.Enable==1
    msr_s    SYS_ICC_SRE_EL2, x0
    isb                    // Make sure SRE is now set
    mrs_s    x0, SYS_ICC_SRE_EL2        // Read SRE back,
    tbz    x0, #0, 3f            // and check that it sticks
    msr_s    SYS_ICH_HCR_EL2, xzr        // Reset ICC_HCR_EL2 to defaults

3:
#endif
```

Next code snippet is executed only if GICv3 is available and enabled. GIC stands for Generic Interrupt Controller. v3 version of the GIC specification adds a few features, that are particularly useful in virtualization context. For example, with GICv3 it becomes possible to have LPIs (Locality-specific Peripheral Interrupt). Such interrupts are routed via message bus and their configuration is held in special tables in memory.  

The provided code is responsible for enabling SRE (System Register Interface) This step must be done before we will be able to use `ICC_*_ELn` registers and take advantages of GICv3 features. 

```
    /* Populate ID registers. */
    mrs    x0, midr_el1
    mrs    x1, mpidr_el1
    msr    vpidr_el2, x0
    msr    vmpidr_el2, x1
```

`midr_el1` and `mpidr_el1` are read-only registers from the Identification registers group. They provide various information about processor manufacturer, processor architecture name, number of cores and some other info. It is possible to change this information for all readers that try to access it from EL1. Here we populate `vpidr_el2` and ` vmpidr_el2` with the values taken from `midr_el1` and `mpidr_el1`, so this information is the same whether you try to access it from EL1 or  higer exception levels.

```
#ifdef CONFIG_COMPAT
    msr    hstr_el2, xzr            // Disable CP15 traps to EL2
#endif
```

When the processor is executing in 32-bit execution mode, there is a concept of "coprocessor". The coprocessor can be used to access information, that in 64-bit execution mode is typically accessed via system registers. You can read about what exactly is accessible via coprocessor [in the official documentation](http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0311d/I1014521.html). `msr    hstr_el2, xzr` instruction allows using coprocessor from lower exception levels. This makes sense to do only when compatibility mode is enabled (in this mode kernel can run 32-bit user applications on top of 64-bit kernel.).

```
    /* EL2 debug */
    mrs    x1, id_aa64dfr0_el1        // Check ID_AA64DFR0_EL1 PMUVer
    sbfx    x0, x1, #8, #4
    cmp    x0, #1
    b.lt    4f                // Skip if no PMU present
    mrs    x0, pmcr_el0            // Disable debug access traps
    ubfx    x0, x0, #11, #5            // to EL2 and allow access to
4:
    csel    x3, xzr, x0, lt            // all PMU counters from EL1

    /* Statistical profiling */
    ubfx    x0, x1, #32, #4            // Check ID_AA64DFR0_EL1 PMSVer
    cbz    x0, 6f                // Skip if SPE not present
    cbnz    x2, 5f                // VHE?
    mov    x1, #(MDCR_EL2_E2PB_MASK << MDCR_EL2_E2PB_SHIFT)
    orr    x3, x3, x1            // If we don't have VHE, then
    b    6f                // use EL1&0 translation.
5:                        // For VHE, use EL2 translation
    orr    x3, x3, #MDCR_EL2_TPMS        // and disable access from EL1
6:
    msr    mdcr_el2, x3            // Configure debug traps
```

This piece of code is responsible for configuring `mdcr_el2` (Monitor Debug Configuration Register (EL2)). This register is responsible for setting different debug traps, related to the virtualization extension.  I am going to leave the details of this code block unexplained because debug and tracing are a little bit out of scope for our discussion. If you are interested in details, I can recommend you to read the description of `mdcr_el2` register on page `2810` of the [AArch64-Reference-Manual](https://developer.arm.com/docs/ddi0487/ca/arm-architecture-reference-manual-armv8-for-armv8-a-architecture-profile).

```
    /* Stage-2 translation */
    msr    vttbr_el2, xzr
```

When your OS is used as a hypervisor it should provide complete memory isolation for its guest OSes. Stage 2 virtual memory translation is used precisely for this purpose: each guest OS thinks that it owns all system memory, though in reality each memory access is mapped to the physical memory by stage 2 translation. `vttbr_el2`  holds the base address of the translation table for the stage 2 translation.  At this point, stage 2 translation is disabled, and `vttbr_el2` should be set to 0.

```
    cbz    x2, install_el2_stub

    mov    w0, #BOOT_CPU_MODE_EL2        // This CPU booted in EL2
    isb
    ret
```

First `x2` is compared to `0` to check whether VHE is enabled. If yes - jump to `install_el2_stub` label, otherwise record that CPU is booted in EL2 mode and exit from `el2_setup` function.  In the latter case, the processor continues to operate in EL2 mode and EL1 will not be used at all.

```
install_el2_stub:
    /* sctlr_el1 */
    mov    x0, #0x0800            // Set/clear RES{1,0} bits
CPU_BE(    movk    x0, #0x33d0, lsl #16    )    // Set EE and E0E on BE systems
CPU_LE(    movk    x0, #0x30d0, lsl #16    )    // Clear EE and E0E on LE systems
    msr    sctlr_el1, x0

```

If we reach this point it means that we don't need VHE and are going to switch to EL1 soon, so early EL1 initialization needs to be done here.  The copied code snippet is responsible for `sctlr_el1` (System Control Register) initialization. We already did the same job [here](https://github.com/s-matyukevich/raspberry-pi-os/blob/master/src/lesson02/src/boot.S#L18) for the RPi OS.

```
    /* Coprocessor traps. */
    mov    x0, #0x33ff
    msr    cptr_el2, x0            // Disable copro. traps to EL2
```

This code allows EL1 to access `cpacr_el1` register and, as a result, to control access to Trace, Floating-point, and Advanced SIMD functionality.

```
    /* Hypervisor stub */
    adr_l    x0, __hyp_stub_vectors
    msr    vbar_el2, x0
```

We don't plan to use EL2 now, though some functionality requires it. We need it, for example, to implement [kexec](https://linux.die.net/man/8/kexec) system call that enables you to load and boot into another kernel from the currently running kernel. 

[_hyp_stub_vectors](https://github.com/torvalds/linux/blob/v4.14/arch/arm64/kernel/hyp-stub.S#L33)  holds the addresses of all exception handlers for EL2. We are going to implement exception handling functionality for EL1 in the next lesson, after we talk about interrupts and exception handling in details.

```
    /* spsr */
    mov    x0, #(PSR_F_BIT | PSR_I_BIT | PSR_A_BIT | PSR_D_BIT |\
              PSR_MODE_EL1h)
    msr    spsr_el2, x0
    msr    elr_el2, lr
    mov    w0, #BOOT_CPU_MODE_EL2        // This CPU booted in EL2
    eret
```

Finally, we need to initialize processor state at EL1 and switch exception levels. We already did it for the [RPi OS](https://github.com/s-matyukevich/raspberry-pi-os/blob/master/src/lesson02/src/boot.S#L27-L33) so I am not going to explain the details of this code. 

The only new thing here is the way how `elr_el2` is initialized. `lr` or Link Register is an alias for `x30`. Whenever you execute `bl` (Branch Link) instruction `x30` is automatically populated with the address of the current instruction. This fact is usually used by `ret` instruction, so it knows where exactly to return. In our case, `lr` points [here](https://github.com/torvalds/linux/blob/v4.14/arch/arm64/kernel/head.S#L119) and, because of the way how we initialized  `elr_el2`, this is also the place from which the execution is going to be resumed after switching to EL1.

### Processor initialization at EL1

Now we are back to the `stext` function. Next few lines are not very important for us, but I want to explain them for the sake of completeness.

```
    adrp    x23, __PHYS_OFFSET
    and    x23, x23, MIN_KIMG_ALIGN - 1    // KASLR offset, defaults to 0
```
[KASLR](https://lwn.net/Articles/569635/), or Kernel address space layout randomization, is a technique that allows to place the kernel at a random address in the memory. This is required only for security reasons. For more information, you can read the link above.

```
    bl    set_cpu_boot_mode_flag
```

Here CPU boot mode is saved into [__boot_cpu_mode](https://github.com/torvalds/linux/blob/v4.14/arch/arm64/include/asm/virt.h#L74) variable. The code that does this is very similar to `preserve_boot_args` function that we explored previously.  

```
    bl    __create_page_tables
    bl    __cpu_setup            // initialise processor
    b    __primary_switch
```

The last 3 functions are very important, but they all are related to virtual memory management, so we are going to postpone their detailed exploration until the lesson 6. For now, I just want to brefely describe there meanings.
* `__create_page_tables` As its name stands this one is responsible for creating Page Tables.
* `__cpu_setup` Initialize various processor settings, mostly specific for virtual memory management.
* `__primary_switch` Enable MMU and jump to [start_kernel](https://github.com/torvalds/linux/blob/v4.14/init/main.c#L509) function, which is architecture independent starting point.

### Conclusion

In this chapter, we briefly discussed how a processor is initialized when the Linux kernel is booted. In the next lesson, we will continue to closely work with the ARM processor and investigate a vital topic for any OS: interrupt handling.
 
##### Previous Page

2.1 [Processor initialization: RPi OS](../../docs/lesson02/rpi-os.md)

##### Next Page

2.3 [Processor initialization: Exercises](../../docs/lesson02/exercises.md)


================================================
FILE: docs/lesson02/rpi-os.md
================================================
## 2.1: Processor initialization 

In this lesson, we are going to work more closely with the ARM processor. It has some essential features that can be utilized by the OS. The first such feature is called "Exception levels".

### Exception levels

Each ARM processor that supports ARM.v8 architecture has 4 exception levels. You can think about an exception level (or `EL` for short) as a processor execution mode in which only a subset of all operations and registers is available. The least privileged exception level is level 0. When processor operates at this level, it mostly uses only general purpose registers (X0 - X30) and stack pointer register (SP). EL0 also allows using `STR` and `LDR` commands to load and store data to and from memory and a few other instructions commonly used by a user program.

An operating system should deal with exception levels because it needs to implement process isolation. A user process should not be able to access other process's data. To achieve such behavior, an operating system always runs each user process at EL0. Operating at this exception level a process can only use it's own virtual memory and can't access any instructions that change virtual memory settings. So, to ensure process isolation, an OS need to prepare separate virtual memory mapping for each process and put the processor into EL0 before transferring execution to a user process.

An operating system itself usually works at EL1. While running at this exception level processor gets access to the registers that allows configuring virtual memory settings as well as to some system registers. Raspberry Pi OS also will be using EL1.

We are not going to use exceptions levels 2 and 3 a lot, but I just want to briefly describe them so you can get an idea why they are needed. 

EL2 is used in a scenario when we are using a hypervisor. In this case host operating system runs at EL2 and guest operating systems can only use EL 1. This allows host OS to isolate guest OSes in a similar way how OS isolates user processes.

EL3 is used for transitions from ARM "Secure World" to "Insecure world". This abstraction exist to provide full hardware isolation between the software running in two different "worlds". Application from an "Insecure world" can in no way access or modify information (both instruction and data) that belongs to "Secure world", and this restriction is enforced at the hardware level. 

### Debugging the kernel

Next thing that I want to do is to figure out which Exception level we are currently using. But when I tried to do this, I realized that the kernel could only print some constant string on a screen, but what I need is some analog of [printf](https://en.wikipedia.org/wiki/Printf_format_string) function. With `printf` I can easily display values of different registers and variables. Such functionality is essential for the kernel development because you don't have any other debugger support and `printf` becomes the only mean by which you can figure out what is going on inside your program.

For the RPi OS I decided not to reinvent the wheel and use one of  [existing printf implementations](http://www.sparetimelabs.com/tinyprintf/tinyprintf.php) This function consists mostly from string manipulations and is not very interesting from a kernel developer point of view. The implementation that I used is very small and don't have external dependencies, that allows it to be easily integrated into the kernel. The only thing that I have to do is to define `putc`  function that can send a single character to the screen. This function is defined [here](https://github.com/s-matyukevich/raspberry-pi-os/blob/master/src/lesson02/src/mini_uart.c#L59) and it just uses already existing `uart_send` function. Also, we need to initialize the `printf` library and specify the location of the `putc` function. This is done in a single [line of code](https://github.com/s-matyukevich/raspberry-pi-os/blob/master/src/lesson02/src/kernel.c#L8).

### Finding current Exception level

Now, when we are equipped with the `printf` function, we can complete our original task: figure out at which exception level the OS is booted. A small function that can answer this question is defined [here](https://github.com/s-matyukevich/raspberry-pi-os/blob/master/src/lesson02/src/utils.S#L1) and looks like this.

```
.globl get_el
get_el:
    mrs x0, CurrentEL
    lsr x0, x0, #2
    ret
```

Here we use `mrs` instruction to read the value from `CurrentEL` system register into `x0` register. Then we shift this value 2 bits to the right (we need to do this because first 2 bits in the `CurrentEL` register are reserved and always have value 0) And finally in the register `x0` we have an integer number indicating current exception level. Now the only thing that is left is to display this value, like [this](https://github.com/s-matyukevich/raspberry-pi-os/blob/master/src/lesson02/src/kernel.c#L10).

```
    int el = get_el();
    printf("Exception level: %d \r\n", el);
```

If you reproduce this experiment, you should see `Exception level: 3` on the screen.

### Changing current exception level

In ARM architecture there is no way how a program can increase its own exception level without the participation of the software that already runs on a higher level. This makes a perfect sense: otherwise, any program would be able to escape its assigned EL and access other programs data. Current EL can be changed only if an exception is generated. This can happen if a program executes some illegal instruction (for example, tries to access memory location at a nonexisting address, or tries to divide by 0) Also an application can run `svc` instruction to generate an exception on purpose. Hardware generated interrupts are also handled as a special type of exceptions. Whenever an exception is generated the following sequence of steps takes place (In the description I am assuming that the exception is handled at EL `n`, were `n` could be 1, 2 or 3).

1. Address of the current instruction is saved in the `ELR_ELn`  register. (It is called `Exception link register`)
1. Current processor state is stored in `SPSR_ELn` register (`Saved Program Status Register`)
1. An exception handler is executed and does whatever job it needs to do.
1. Exception handler calls `eret` instruction. This instruction restores processor state from `SPSR_ELn` and resumes execution starting from the address, stored in the `ELR_ELn`  register.

In practice the process is a little more complicated because exception handler also needs to store the state of all general purpose registers and restore it back afterwards, but we will discuss this process in details in the next lesson. For now, we need just to understand the process in general and remember the meaning of the `ELR_ELn` and `SPSR_ELn` registers.

An important thing to know is that exception handler is not obliged to return to the same location from which the exception originates. Both `ELR_ELn` and `SPSR_ELn` are writable and exception handler can modify them if it wants to. We are going to use this technique to our advantage when we try to switch from EL3 to EL1 in our code.

### Switching to EL1

Strictly speaking, our operating system is not obliged to switch to EL1, but EL1 is a natural choice for us because this level has just the right set of privileges to implement all common OS tasks. It also will be an interesting exercise to see how switching exceptions levels works in action. Let's take a look at the [source code that does this](https://github.com/s-matyukevich/raspberry-pi-os/blob/master/src/lesson02/src/boot.S#L17).

```
master:
    ldr    x0, =SCTLR_VALUE_MMU_DISABLED
    msr    sctlr_el1, x0        

    ldr    x0, =HCR_VALUE
    msr    hcr_el2, x0

    ldr    x0, =SCR_VALUE
    msr    scr_el3, x0

    ldr    x0, =SPSR_VALUE
    msr    spsr_el3, x0

    adr    x0, el1_entry        
    msr    elr_el3, x0

    eret                
```

As you can see the code consists mostly of configuring a few system registers. Now we are going to examine those registers one by one. In order to do this we first need to download [AArch64-Reference-Manual](https://developer.arm.com/docs/ddi0487/ca/arm-architecture-reference-manual-armv8-for-armv8-a-architecture-profile). This document contains the detailed specification of the `ARM.v8` architecture. 

#### SCTLR_EL1, System Control Register (EL1), Page 2654 of AArch64-Reference-Manual.

```
    ldr    x0, =SCTLR_VALUE_MMU_DISABLED
    msr    sctlr_el1, x0        
```

Here we set the value of the `sctlr_el1` system register. `sctlr_el1` is responsible for configuring different parameters of the processor, when it operates at EL1. For example, it controls whether the cache is enabled and, what is most important for us, whether the MMU (Memory Management Unit) is turned on. `sctlr_el1` is accessible from all exception levels higher or equal than EL1 (you can infer this from `_el1` postfix) 

`SCTLR_VALUE_MMU_DISABLED` constant is defined [here](https://github.com/s-matyukevich/raspberry-pi-os/blob/master/src/lesson02/include/arm/sysregs.h#L16) Individual bits of this value are defined like this:

* `#define SCTLR_RESERVED                  (3 << 28) | (3 << 22) | (1 << 20) | (1 << 11)` Some bits in the description of `sctlr_el1` register are marked as `RES1`. Those bits are reserved for future usage and should be initialized with `1`.
* `#define SCTLR_EE_LITTLE_ENDIAN          (0 << 25)` Exception [Endianness](https://en.wikipedia.org/wiki/Endianness). This field controls endianess of explicit data access at EL1. We are going to configure the processor to work only with `little-endian` format.
* `#define SCTLR_EOE_LITTLE_ENDIAN         (0 << 24)` Similar to previous field but this one controls endianess of explicit data access at EL0, instead of EL1. 
* `#define SCTLR_I_CACHE_DISABLED          (0 << 12)` Disable instruction cache. We are going to disable all caches for simplicity. You can find more information about data and instruction caches [here](https://stackoverflow.com/questions/22394750/what-is-meant-by-data-cache-and-instruction-cache).
* `#define SCTLR_D_CACHE_DISABLED          (0 << 2)` Disable data cache.
* `#define SCTLR_MMU_DISABLED              (0 << 0)` Disable MMU. MMU must be disabled until the lesson 6, where we are going to prepare page tables and start working with virtual memory.

#### HCR_EL2, Hypervisor Configuration Register (EL2), Page 2487 of AArch64-Reference-Manual. 

```
    ldr    x0, =HCR_VALUE
    msr    hcr_el2, x0
```

We are not going to implement our own [hypervisor](https://en.wikipedia.org/wiki/Hypervisor). Stil we need to use this register because, among other settings, it controls the execution state at EL1. Execution state must be `AArch64` and not `AArch32`. This is configured [here](https://github.com/s-matyukevich/raspberry-pi-os/blob/master/src/lesson02/include/arm/sysregs.h#L22).

#### SCR_EL3, Secure Configuration Register (EL3), Page 2648 of AArch64-Reference-Manual.

```
    ldr    x0, =SCR_VALUE
    msr    scr_el3, x0
```

This register is responsible for configuring security settings. For example, it controls whether all lower levels are executed in "secure" or "nonsecure" state. It also controls execution state at EL2. [here](https://github.com/s-matyukevich/raspberry-pi-os/blob/master/src/lesson02/include/arm/sysregs.h#L26) we set that EL2  will execute at `AArch64` state, and all lower exception levels will be "non secure". 

#### SPSR_EL3, Saved Program Status Register (EL3), Page 389 of AArch64-Reference-Manual.

```
    ldr    x0, =SPSR_VALUE
    msr    spsr_el3, x0
```

This register should be already familiar to you - we mentioned it when discussed the process of changing exception levels. `spsr_el3` contains processor state, that will be restored after we execute `eret` instruction.
It is worth saying a few words explaining what processor state is. Processor state includes the following information:

* **Condition Flags** Those flags contains information about previously executed operation: whether the result was negative (N flag), zero (A flag), has unsigned overflow (C flag) or has signed overflow (V flag). Values of those flags can be used in conditional branch instructions. For example, `b.eq` instruction will jump to the provided label only if the result of the last comparison operation is equal to 0. The processor checks this by testing whether Z flag is set to 1.

* **Interrupt disable bits** Those bits allows to enable/disable different types of interrupts.

* Some other information, required to fully restore the processor execution state after an exception is handled.

Usually `spsr_el3` is saved automatically when an exception is taken to EL3. However this register is writable, so we take advantage of this fact and manually prepare processor state. `SPSR_VALUE` is prepared [here](https://github.com/s-matyukevich/raspberry-pi-os/blob/master/src/lesson02/include/arm/sysregs.h#L35) and we initialize the following fields:

* `#define SPSR_MASK_ALL        (7 << 6)` After we change EL to EL1 all types of interrupts will be masked (or disabled, which is the same).
* `#define SPSR_EL1h        (5 << 0)` At EL1 we can either use our own dedicated stack pointer or use EL0 stack pointer. `EL1h` mode means that we are using EL1 dedicated stack pointer. 

#### ELR_EL3, Exception Link Register (EL3), Page 351 of AArch64-Reference-Manual.

```
    adr    x0, el1_entry        
    msr    elr_el3, x0

    eret                
```

`elr_el3` holds the address, to which we are going to return after `eret` instruction will be executed. Here we set this address to the location of `el1_entry` label.

### Conclusion

That is pretty much it: when we enter `el1_entry` function the execution should be already at EL1 mode. Go ahead and try it out! 

##### Previous Page

1.5 [Kernel Initialization: Exercises](../../docs/lesson01/exercises.md)

##### Next Page

2.2 [Processor initialization: Linux](../../docs/lesson02/linux.md)


================================================
FILE: docs/lesson03/exercises.md
================================================
## 3.5: Exercises

1. Use local timer instead of the system timer to generate processor interrupts. See [this](https://github.com/s-matyukevich/raspberry-pi-os/issues/70) issue for details.
1. Handle MiniUART interrupts. Replace the final loop in the `kernel_main` function with a loop that does nothing. Setup MiniUART device to generate an interrupt as soon as the user types a new character. Implement an interrupt handler that will be responsible for printing each newly arrived character on the screen.
1. Adapt lesson 03 to run on qemu. Check [this](https://github.com/s-matyukevich/raspberry-pi-os/issues/8) issue for reference.

##### Previous Page

3.4 [Interrupt handling: Timers](../../docs/lesson03/linux/timer.md)

##### Next Page

4.1 [Process scheduler: RPi OS Scheduler](../../docs/lesson04/rpi-os.md)


================================================
FILE: docs/lesson03/linux/interrupt_controllers.md
================================================
## 3.3: Interrupt controllers

In this chapter, we are going to talk a lot about Linux drivers and how they handle interrupts. We will start with driver initialization code and then take a look at how interrupts are processed after [handle_arch_irq](https://github.com/torvalds/linux/blob/v4.14/arch/arm64/kernel/irq.c#L44) function.

### Using device tree to find out needed devices and drivers

When implementing interrupts in the RPi OS we have been working with 2 devices: system timer and interrupt controller. Now our goal will be to understand how the same devices work in Linux. The first thing we need to do is to find drivers that are responsible for working with mentioned devices. And in order to find needed drivers we can use [bcm2837-rpi-3-b.dts](https://github.com/torvalds/linux/blob/v4.14/arch/arm/boot/dts/bcm2837-rpi-3-b.dts) device tree file. This is the top level device tree file that is specific for Raspberry Pi 3 Model B, it includes other more common device tree files, that are shared between different versions of Raspberry Pi. If you follow the chain of includes and search for `timer` and `interrupt-controller` you can find 4 devices.

1. [Local interrupt controller](https://github.com/torvalds/linux/blob/v4.14/arch/arm/boot/dts/bcm2837.dtsi#L11)
1. [Local timer](https://github.com/torvalds/linux/blob/v4.14/arch/arm/boot/dts/bcm2837.dtsi#L20)
1. Global interrupt controller. It is defined [here](https://github.com/torvalds/linux/blob/v4.14/arch/arm/boot/dts/bcm283x.dtsi#L109) and modified [here](https://github.com/torvalds/linux/blob/v4.14/arch/arm/boot/dts/bcm2837.dtsi#L72).
1. [System timer](https://github.com/torvalds/linux/blob/v4.14/arch/arm/boot/dts/bcm283x.dtsi#L57)

Stop, but why do we have 4 devices instead of 2? This requires some explanation, and we will tackle this question in the next section.

### Local vs global interrupt controllers

When you think about interrupt handling in multiprocessor systems, one question you should ask yourself is which core should be responsible for processing a particular interrupt? When an interrupt occurs, are all 4 cores interrupted, or only a single one? Is it possible to route a particular interrupt to a specific core? Another question you may wonder is how one processor can notify another processor if he needs to pass some information to it?

The local interrupt controller is a device that can help you in answering all those questions. It is responsible for the following tasks.

* Configuring which core should receive a specific interrupt.
* Sending interrupts between cores. Such interrupts are called "mailboxes" and allow cores to communicate one with each other.
* Handling interrupts from local timer and performance monitors interrupts (PMU).

The behavior of a local interrupt controller as well as a local timer is documented in [BCM2836 ARM-local peripherals](https://www.raspberrypi.org/documentation/hardware/raspberrypi/bcm2836/QA7_rev3.4.pdf) manual.

I already mentioned local timer several times. Now you probably wonder why do we need two independent timers in the system? I guess that the primary use-case for using the local timer is when you want to configure all 4 cores to receive timer interrupts simultaneously. If you use system timer you can only route interrupts to a single core.

When working with the RPi OS we didn't work with either local interrupt controller or local timer. That is because by default local interrupt controller is configured in such a way that all external interrupts are sent to the first core, which is exactly what we need. We haven't used local timer because we use system timer instead.

### Local interrupt controller

Accordingly to the [bcm2837.dtsi](https://github.com/torvalds/linux/blob/v4.14/arch/arm/boot/dts/bcm2837.dtsi#L75) the global interrupt controller is a child of the local one. Thus it makes sense to start our exploration with the local controller.

If we need to find a driver that works with a particular device, we should use [compatible](https://github.com/torvalds/linux/blob/v4.14/arch/arm/boot/dts/bcm2837.dtsi#L12) property. Searching for the value of this property you can easily find that there is a single driver that is compatible with RPi local interrupt controller - here is the corresponding [definition](https://github.com/torvalds/linux/blob/v4.14/drivers/irqchip/irq-bcm2836.c#L315).

```
IRQCHIP_DECLARE(bcm2836_arm_irqchip_l1_intc, "brcm,bcm2836-l1-intc",
        bcm2836_arm_irqchip_l1_intc_of_init);
```

Now you can probably guess what is the procedure of a driver initialization: the kernel walks through all device definitions in the device tree and for each definition it looks for a matching driver using "compatible" property. If the driver is found, then its initialization function is called. Initialization function is provided during device registration, and in our case this function is [bcm2836_arm_irqchip_l1_intc_of_init](https://github.com/torvalds/linux/blob/v4.14/drivers/irqchip/irq-bcm2836.c#L280).

```
static int __init bcm2836_arm_irqchip_l1_intc_of_init(struct device_node *node,
                              struct device_node *parent)
{
    intc.base = of_iomap(node, 0);
    if (!intc.base) {
        panic("%pOF: unable to map local interrupt registers\n", node);
    }

    bcm2835_init_local_timer_frequency();

    intc.domain = irq_domain_add_linear(node, LAST_IRQ + 1,
                        &bcm2836_arm_irqchip_intc_ops,
                        NULL);
    if (!intc.domain)
        panic("%pOF: unable to create IRQ domain\n", node);

    bcm2836_arm_irqchip_register_irq(LOCAL_IRQ_CNTPSIRQ,
                     &bcm2836_arm_irqchip_timer);
    bcm2836_arm_irqchip_register_irq(LOCAL_IRQ_CNTPNSIRQ,
                     &bcm2836_arm_irqchip_timer);
    bcm2836_arm_irqchip_register_irq(LOCAL_IRQ_CNTHPIRQ,
                     &bcm2836_arm_irqchip_timer);
    bcm2836_arm_irqchip_register_irq(LOCAL_IRQ_CNTVIRQ,
                     &bcm2836_arm_irqchip_timer);
    bcm2836_arm_irqchip_register_irq(LOCAL_IRQ_GPU_FAST,
                     &bcm2836_arm_irqchip_gpu);
    bcm2836_arm_irqchip_register_irq(LOCAL_IRQ_PMU_FAST,
                     &bcm2836_arm_irqchip_pmu);

    bcm2836_arm_irqchip_smp_init();

    set_handle_irq(bcm2836_arm_irqchip_handle_irq);
    return 0;
}
```

The initialization function takes 2 parameters: 'node' and 'parent', both of them are of the type [struct device_node](https://github.com/torvalds/linux/blob/v4.14/include/linux/of.h#L49). `node` represents the current node in the device tree, and in our case it points [here](https://github.com/torvalds/linux/blob/v4.14/arch/arm/boot/dts/bcm2837.dtsi#L11)  `parent` is a parent node in the device tree hierarchy, and for the local interrupt controller it points to `soc` element (`soc` stands for "system on chip" and it is the simplest possible bus which maps all device registers directly to main memory.).

`node` can be used to read various properties from the current device tree node. For example, the first line of the `bcm2836_arm_irqchip_l1_intc_of_init` function reads the device base address from [reg](https://github.com/torvalds/linux/blob/v4.14/arch/arm/boot/dts/bcm2837.dtsi#L13) property. However, the process is more complicated than that, because when this function is executed MMU is already enabled, and before we will be able to access some region of physical memory we must map this region to some virtual address. This is exactly what [of_iomap](https://github.com/torvalds/linux/blob/v4.14/drivers/of/address.c#L759) function is doing: it reads `reg` property of the provided node and maps the whole memory region, described by `reg` property, to some virtual memory region.

Next local timer frequency is initialized in [bcm2835_init_local_timer_frequency](https://github.com/torvalds/linux/blob/v4.14/drivers/irqchip/irq-bcm2836.c#L264) function. There is nothing specific about this function: it just uses some of the registers, described in [BCM2836 ARM-local peripherals](https://www.raspberrypi.org/documentation/hardware/raspberrypi/bcm2836/QA7_rev3.4.pdf) manual, to initialize local timer.

Next line requires some explanations.

```
    intc.domain = irq_domain_add_linear(node, LAST_IRQ + 1,
                        &bcm2836_arm_irqchip_intc_ops,
                        NULL);
```

Linux assigns a unique integer number to each interrupt, you can think about this number as a unique interrupt ID. This ID is used each time you want to do something with an interrupt (for example, assign a handler, or assign which CPU should handle it). Each interrupt also has a hardware interrupt number. This is usually a number that tells which interrupt line was triggered. `BCM2837 ARM Peripherals manual` has the peripheral interrupt table at page 113 - you can think about an index in this table as a hardware interrupt number. So obviously we need some mechanism to map Linux irq numbers to hardware irq number and vice versa. If there is only one interrupt controller it would be possible to use one to one mapping but in general case a more sophisticated mechanism need to be used. In Linux [struct irq_domain](https://github.com/torvalds/linux/blob/v4.14/include/linux/irqdomain.h#L152) implements such mapping. Each interrupt controller driver should create its own irq domain and register all interrupts that it can handle with this domain. Registration function returns Linux irq number that later is used to work with the interrupt.

Next 6 lines are responsible for registering each supported interrupt with the irq domain.

```
    bcm2836_arm_irqchip_register_irq(LOCAL_IRQ_CNTPSIRQ,
                     &bcm2836_arm_irqchip_timer);
    bcm2836_arm_irqchip_register_irq(LOCAL_IRQ_CNTPNSIRQ,
                     &bcm2836_arm_irqchip_timer);
    bcm2836_arm_irqchip_register_irq(LOCAL_IRQ_CNTHPIRQ,
                     &bcm2836_arm_irqchip_timer);
    bcm2836_arm_irqchip_register_irq(LOCAL_IRQ_CNTVIRQ,
                     &bcm2836_arm_irqchip_timer);
    bcm2836_arm_irqchip_register_irq(LOCAL_IRQ_GPU_FAST,
                     &bcm2836_arm_irqchip_gpu);
    bcm2836_arm_irqchip_register_irq(LOCAL_IRQ_PMU_FAST,
                     &bcm2836_arm_irqchip_pmu);
```

Accordingly to [BCM2836 ARM-local peripherals](https://www.raspberrypi.org/documentation/hardware/raspberrypi/bcm2836/QA7_rev3.4.pdf) manual local interrupt controller handles 10 different interrupts: 0 - 3 are interrupts from local timer, 4 - 7 are mailbox interrupts, which are used in interprocess communication, 8 corresponds to all interrupts generated by the global interrupt controller and interrupt 9 is a performance monitor interrupt. [Here](https://github.com/torvalds/linux/blob/v4.14/drivers/irqchip/irq-bcm2836.c#L67) you can see that the driver defines a set of constants that holds hardware irq number per each interrupt. The registration code above registers all interrupts, except mailbox interrupts, which are registered separately. In order to understand the registration code better lets examine [bcm2836_arm_irqchip_register_irq](https://github.com/torvalds/linux/blob/v4.14/drivers/irqchip/irq-bcm2836.c#L154) function.

```
static void bcm2836_arm_irqchip_register_irq(int hwirq, struct irq_chip *chip)
{
    int irq = irq_create_mapping(intc.domain, hwirq);

    irq_set_percpu_devid(irq);
    irq_set_chip_and_handler(irq, chip, handle_percpu_devid_irq);
    irq_set_status_flags(irq, IRQ_NOAUTOEN);
}
```

The first line here performs actual interrupt registration. [irq_create_mapping](https://github.com/torvalds/linux/blob/v4.14/kernel/irq/irqdomain.c#L632) takes hardware interrupt number as an input and returns Linux irq number.

[irq_set_percpu_devid](https://github.com/torvalds/linux/blob/v4.14/kernel/irq/irqdesc.c#L849) configures interrupt as "per CPU", so that it will be handled only on the current CPU. This makes perfect sense because all interrupts that we are discussing now are local and they all can be handled only on the current CPU.

[irq_set_chip_and_handler](https://github.com/torvalds/linux/blob/v4.14/include/linux/irq.h#L608), as its name suggest, sets irq chip and irq handler. Irq chip is a special struct, which needs to be created by the driver, that has methods for masking and unmasking a particular interrupt. The driver that we are examining right now defines 3 different irq chips: [timer](https://github.com/torvalds/linux/blob/v4.14/drivers/irqchip/irq-bcm2836.c#L118) chip, [PMU](https://github.com/torvalds/linux/blob/v4.14/drivers/irqchip/irq-bcm2836.c#L134) chip and [GPU](https://github.com/torvalds/linux/blob/v4.14/drivers/irqchip/irq-bcm2836.c#L148) chip, which controls all interrupts generated by the external peripheral devices. Handler is a function that is responsible for processing an interrupt. In this case, the handler is set to generic [handle_percpu_devid_irq](https://github.com/torvalds/linux/blob/v4.14/kernel/irq/chip.c#L859) function. This handler later will be rewritten by the global interrupt controller driver.

[irq_set_status_flags](https://github.com/torvalds/linux/blob/v4.14/include/linux/irq.h#L652) in this particular case sets a flag, indicating that the current interrupt should be enabled manually and should not be enabled by default.

Going back to the `bcm2836_arm_irqchip_l1_intc_of_init` function, there are only 2 calls left. The first one is [bcm2836_arm_irqchip_smp_init](https://github.com/torvalds/linux/blob/v4.14/drivers/irqchip/irq-bcm2836.c#L243). Here mailbox interrupts are enabled, allowing processors cores to communicate with each other.

The last function call is extremely important - this is the place where low-level exception handling code is connected to the driver.

```
    set_handle_irq(bcm2836_arm_irqchip_handle_irq);
```

[set_handle_irq](https://github.com/torvalds/linux/blob/v4.14/arch/arm64/kernel/irq.c#L46) is defined in architecture specific code and we already encountered this function. From the line above we can understand that [bcm2836_arm_irqchip_handle_irq](https://github.com/torvalds/linux/blob/v4.14/drivers/irqchip/irq-bcm2836.c#L164) will be called by the low-level exception code. The function itself is listed below.

```
static void
__exception_irq_entry bcm2836_arm_irqchip_handle_irq(struct pt_regs *regs)
{
    int cpu = smp_processor_id();
    u32 stat;

    stat = readl_relaxed(intc.base + LOCAL_IRQ_PENDING0 + 4 * cpu);
    if (stat & BIT(LOCAL_IRQ_MAILBOX0)) {
#ifdef CONFIG_SMP
        void __iomem *mailbox0 = (intc.base +
                      LOCAL_MAILBOX0_CLR0 + 16 * cpu);
        u32 mbox_val = readl(mailbox0);
        u32 ipi = ffs(mbox_val) - 1;

        writel(1 << ipi, mailbox0);
        handle_IPI(ipi, regs);
#endif
    } else if (stat) {
        u32 hwirq = ffs(stat) - 1;

        handle_domain_irq(intc.domain, hwirq, regs);
    }
}
```

This function reads `LOCAL_IRQ_PENDING` register to figure out what interrupts are currently pending. There are 4 `LOCAL_IRQ_PENDING` registers, each corresponding to its own processor core, that's why current processor index is used to select the right one. Mailbox interrupts and all other interrupts are processed in 2 different clauses of an if statement. The interaction between different cores of a multiprocessor system is out of scope for our current discussion, so we are going to skip mailbox interrupt handling part. Now we have only the following 2 lines left unexplained.

```
        u32 hwirq = ffs(stat) - 1;

        handle_domain_irq(intc.domain, hwirq, regs);
```

This is were interrupt is passed to the next handler. First of all hardware irq number is calculated. [ffs](https://github.com/torvalds/linux/blob/v4.14/include/asm-generic/bitops/ffs.h#L13) (Find first bit) function is used to do this. After hardware irq number is calculated [handle_domain_irq](https://github.com/torvalds/linux/blob/v4.14/kernel/irq/irqdesc.c#L622) function is called. This function uses irq domain to translate hardware irq number to Linux irq number, then checks irq configuration (it is stored in [irq_desc](https://github.com/torvalds/linux/blob/v4.14/include/linux/irqdesc.h#L55) struct) and calls an interrupt handler. We've seen that the handler was set to [handle_percpu_devid_irq](https://github.com/torvalds/linux/blob/v4.14/kernel/irq/chip.c#L859). However, this handler will be overwritten by the child interrupt controller later. Now, let's examine how this happens.

### Generic interrupt controller 

We have already seen how to use device tree and `compatible` property to find the driver corresponding to some device, so I am going to skip this part and jump straight to the generic interrupt controller driver source code. You can find it in [irq-bcm2835.c](https://github.com/torvalds/linux/blob/v4.14/drivers/irqchip/irq-bcm2835.c) file. As usual, we are going to start our exploration with the initialization function. It is called [armctrl_of_init](https://github.com/torvalds/linux/blob/v4.14/drivers/irqchip/irq-bcm2835.c#L141).

```
static int __init armctrl_of_init(struct device_node *node,
				  struct device_node *parent,
				  bool is_2836)
{
	void __iomem *base;
	int irq, b, i;

	base = of_iomap(node, 0);
	if (!base)
		panic("%pOF: unable to map IC registers\n", node);

	intc.domain = irq_domain_add_linear(node, MAKE_HWIRQ(NR_BANKS, 0),
			&armctrl_ops, NULL);
	if (!intc.domain)
		panic("%pOF: unable to create IRQ domain\n", node);

	for (b = 0; b < NR_BANKS; b++) {
		intc.pending[b] = base + reg_pending[b];
		intc.enable[b] = base + reg_enable[b];
		intc.disable[b] = base + reg_disable[b];

		for (i = 0; i < bank_irqs[b]; i++) {
			irq = irq_create_mapping(intc.domain, MAKE_HWIRQ(b, i));
			BUG_ON(irq <= 0);
			irq_set_chip_and_handler(irq, &armctrl_chip,
				handle_level_irq);
			irq_set_probe(irq);
		}
	}

	if (is_2836) {
		int parent_irq = irq_of_parse_and_map(node, 0);

		if (!parent_irq) {
			panic("%pOF: unable to get parent interrupt.\n",
			      node);
		}
		irq_set_chained_handler(parent_irq, bcm2836_chained_handle_irq);
	} else {
		set_handle_irq(bcm2835_handle_irq);
	}

	return 0;
}
```

Now, let's investigate this function in more details.

```
    void __iomem *base;
    int irq, b, i;

    base = of_iomap(node, 0);
    if (!base)
        panic("%pOF: unable to map IC registers\n", node);

    intc.domain = irq_domain_add_linear(node, MAKE_HWIRQ(NR_BANKS, 0),
            &armctrl_ops, NULL);
    if (!intc.domain)
        panic("%pOF: unable to create IRQ domain\n", node);

```

The function starts with the code that reads device base address from the device tree and initializes the irq domain. This part should be already familiar to you because we have seen similar code in the local irq controller driver.

```
    for (b = 0; b < NR_BANKS; b++) {
        intc.pending[b] = base + reg_pending[b];
        intc.enable[b] = base + reg_enable[b];
        intc.disable[b] = base + reg_disable[b];
```

Next, there is a loop that iterates over all irq banks. We already briefly touched irq banks in the first chapter of this lesson. The interrupt controller has 3 irq banks, which are controlled by `ENABLE_IRQS_1`, `ENABLE_IRQS_2` and `ENABLE_BASIC_IRQS` registers.  Each of the banks has its own enable, disable and pending registers. Enable and disable registers can be used to either enable or disable individual interrupts that belong to a particular bank. Pending register is used to determine what interrupts are waiting to be processed.

```
        for (i = 0; i < bank_irqs[b]; i++) {
            irq = irq_create_mapping(intc.domain, MAKE_HWIRQ(b, i));
            BUG_ON(irq <= 0);
            irq_set_chip_and_handler(irq, &armctrl_chip,
                handle_level_irq);
            irq_set_probe(irq);
        }
```

Next, there is a nested loop that is responsible for registering each supported interrupt and setting irq chip and handler.

We already saw how the same functions are used in the local interrupt controller driver. However, I would like to highlight a few important things.

* [MAKE_HWIRQ](https://github.com/torvalds/linux/blob/v4.14/drivers/irqchip/irq-bcm2835.c#L57) macro is used to calculate hardware irq number. It is calculated based on bank index and irq index inside the bank.
* [handle_level_irq](https://github.com/torvalds/linux/blob/v4.14/kernel/irq/chip.c#L603) is a common handler that is used for interrupts of the level type. Interrupts of such type keep interrupt line set to "high" until the interrupt is acknowledged. There are also edge type interrupts that works in a different way.
* [irq_set_probe](https://github.com/torvalds/linux/blob/v4.14/include/linux/irq.h#L667) function just unsets [IRQ_NOPROBE](https://github.com/torvalds/linux/blob/v4.14/include/linux/irq.h#L64) interrupt flag, effectively disabling interrupt auto-probing. Interrupt auto-probing is a process that allows different drivers to discover which interrupt line their devices are connected to. This is not needed for Raspberry Pi, because this information is encoded in the device tree, however, for some devices, this might be useful. Please, refer to [this](https://github.com/torvalds/linux/blob/v4.14/include/linux/interrupt.h#L662) comment to understand how auto-probing works in the Linux kernel.

Next piece of code is different for BCM2836 and BCM2835 interrupt controllers (the first one corresponds to the RPi models 2 and 3, and the second one to RPi Model 1).  If we are dealing with BCM2836 the following code is executed.

```
        int parent_irq = irq_of_parse_and_map(node, 0);

        if (!parent_irq) {
            panic("%pOF: unable to get parent interrupt.\n",
                  node);
        }
        irq_set_chained_handler(parent_irq, bcm2836_chained_handle_irq);
```

Device tree [indicates](https://github.com/torvalds/linux/blob/v4.14/arch/arm/boot/dts/bcm2837.dtsi#L75) that local interrupt controller is a parent of the global interrupt controller. Another device tree [property](https://github.com/torvalds/linux/blob/v4.14/arch/arm/boot/dts/bcm2837.dtsi#L76) tells us that global interrupt controller is connected to the interupt line number 8 of the local controller, this means that our parent irq is the one with hardware irq number 8. Those 2 properties allow Linux kernel to find out parent interrupt number (this is Linux interrupt number, not hardware number). Finally [irq_set_chained_handler](https://github.com/torvalds/linux/blob/v4.14/include/linux/irq.h#L636) function replaces the handler of the parent irq with [bcm2836_chained_handle_irq](https://github.com/torvalds/linux/blob/v4.14/drivers/irqchip/irq-bcm2835.c#L246) function.

[bcm2836_chained_handle_irq](https://github.com/torvalds/linux/blob/v4.14/drivers/irqchip/irq-bcm2835.c#L246) is very simple. Its code is listed below.

```
static void bcm2836_chained_handle_irq(struct irq_desc *desc)
{
    u32 hwirq;

    while ((hwirq = get_next_armctrl_hwirq()) != ~0)
        generic_handle_irq(irq_linear_revmap(intc.domain, hwirq));
}
```

You can think about this code as an advanced version of what we did [here](https://github.com/s-matyukevich/raspberry-pi-os/blob/master/src/lesson03/src/irq.c#L39) for the RPi OS. [get_next_armctrl_hwirq](https://github.com/torvalds/linux/blob/v4.14/drivers/irqchip/irq-bcm2835.c#L217) uses all 3 pending registers to figure out which interrupt was fired. [irq_linear_revmap](https://github.com/torvalds/linux/blob/v4.14/include/linux/irqdomain.h#L377) uses irq domain to translate hardware irq number into Linux irq number and [generic_handle_irq](https://github.com/torvalds/linux/blob/v4.14/include/linux/irqdesc.h#L156) just executes irq handler. Irq handler was set in the initialization function and it points to [handle_level_irq](https://github.com/torvalds/linux/blob/v4.14/kernel/irq/chip.c#L603) that eventually executes all irq actions associated with the interrupt (this is actually done [here](https://github.com/torvalds/linux/blob/v4.14/kernel/irq/handle.c#L135).). For now, the list of irq actions is empty for all supported interrupts - a driver that is interested in handling some interrupt should add an action to the appropriate list. In the next chapter, we are going to see how this is done using system timer as an example.

##### Previous Page

3.2 [Interrupt handling: Low-level exception handling in Linux](../../../docs/lesson03/linux/low_level-exception_handling.md)

##### Next Page

3.4 [Interrupt handling: Timers](../../../docs/lesson03/linux/timer.md)


================================================
FILE: docs/lesson03/linux/low_level-exception_handling.md
================================================
## 3.2: Low-level exception handling in Linux

Given huge Linux kernel source code, what is a good way to find the code that is responsible for interrupt handling? I can suggest one idea. Vector table base address should be stored in the 'vbar_el1' register, so, if you search for `vbar_el1`, you should be able to figure out where exactly the vector table is initialized. Indeed, the search gives us just a few usages, one of which belongs to already familiar to us [head.S](https://github.com/torvalds/linux/blob/v4.14/arch/arm64/kernel/head.S). This code is inside [__primary_switched](https://github.com/torvalds/linux/blob/v4.14/arch/arm64/kernel/head.S#L323) function. This function is executed after the MMU is switched on. The code looks like the following.

```
    adr_l    x8, vectors            // load VBAR_EL1 with virtual
    msr    vbar_el1, x8            // vector table address
```

From this code, we can infer that the vector table is called `vectors` and you should be able to easily find [its definition](https://github.com/torvalds/linux/blob/v4.14/arch/arm64/kernel/entry.S#L367).

```
/*
 * Exception vectors.
 */
    .pushsection ".entry.text", "ax"

    .align    11
ENTRY(vectors)
    kernel_ventry    el1_sync_invalid        // Synchronous EL1t
    kernel_ventry    el1_irq_invalid            // IRQ EL1t
    kernel_ventry    el1_fiq_invalid            // FIQ EL1t
    kernel_ventry    el1_error_invalid        // Error EL1t

    kernel_ventry    el1_sync            // Synchronous EL1h
    kernel_ventry    el1_irq                // IRQ EL1h
    kernel_ventry    el1_fiq_invalid            // FIQ EL1h
    kernel_ventry    el1_error_invalid        // Error EL1h

    kernel_ventry    el0_sync            // Synchronous 64-bit EL0
    kernel_ventry    el0_irq                // IRQ 64-bit EL0
    kernel_ventry    el0_fiq_invalid            // FIQ 64-bit EL0
    kernel_ventry    el0_error_invalid        // Error 64-bit EL0

#ifdef CONFIG_COMPAT
    kernel_ventry    el0_sync_compat            // Synchronous 32-bit EL0
    kernel_ventry    el0_irq_compat            // IRQ 32-bit EL0
    kernel_ventry    el0_fiq_invalid_compat        // FIQ 32-bit EL0
    kernel_ventry    el0_error_invalid_compat    // Error 32-bit EL0
#else
    kernel_ventry    el0_sync_invalid        // Synchronous 32-bit EL0
    kernel_ventry    el0_irq_invalid            // IRQ 32-bit EL0
    kernel_ventry    el0_fiq_invalid            // FIQ 32-bit EL0
    kernel_ventry    el0_error_invalid        // Error 32-bit EL0
#endif
END(vectors)
```

Looks familiar, isn't it? And indeed, I've copied most of this code and just simplified it a little bit. [kernel_ventry](https://github.com/torvalds/linux/blob/v4.14/arch/arm64/kernel/entry.S#L72) macro is almost the same as [ventry](https://github.com/s-matyukevich/raspberry-pi-os/blob/master/src/lesson03/src/entry.S#L12), defined in the RPi OS. One difference, though, is that `kernel_ventry`  also is responsible for checking whether a kernel stack overflow has occurred. This functionality is enabled if `CONFIG_VMAP_STACK` is set and it is a part of the kernel feature that is called `Virtually mapped kernel stacks`. I'm not going to explain it in details here, however, if you are interested, I can recommend you to read [this](https://lwn.net/Articles/692208/) article.

### kernel_entry

[kernel_entry](https://github.com/torvalds/linux/blob/v4.14/arch/arm64/kernel/entry.S#L120) macro should also be familiar to you. It is used exactly in the same way as the [corresonding macro](https://github.com/s-matyukevich/raspberry-pi-os/blob/master/src/lesson03/src/entry.S#L17) in the RPI OS. Original (Linux) version, however, is a lot more complicated. The code is listed below.

```
	.macro	kernel_entry, el, regsize = 64
	.if	\regsize == 32
	mov	w0, w0				// zero upper 32 bits of x0
	.endif
	stp	x0, x1, [sp, #16 * 0]
	stp	x2, x3, [sp, #16 * 1]
	stp	x4, x5, [sp, #16 * 2]
	stp	x6, x7, [sp, #16 * 3]
	stp	x8, x9, [sp, #16 * 4]
	stp	x10, x11, [sp, #16 * 5]
	stp	x12, x13, [sp, #16 * 6]
	stp	x14, x15, [sp, #16 * 7]
	stp	x16, x17, [sp, #16 * 8]
	stp	x18, x19, [sp, #16 * 9]
	stp	x20, x21, [sp, #16 * 10]
	stp	x22, x23, [sp, #16 * 11]
	stp	x24, x25, [sp, #16 * 12]
	stp	x26, x27, [sp, #16 * 13]
	stp	x28, x29, [sp, #16 * 14]

	.if	\el == 0
	mrs	x21, sp_el0
	ldr_this_cpu	tsk, __entry_task, x20	// Ensure MDSCR_EL1.SS is clear,
	ldr	x19, [tsk, #TSK_TI_FLAGS]	// since we can unmask debug
	disable_step_tsk x19, x20		// exceptions when scheduling.

	mov	x29, xzr			// fp pointed to user-space
	.else
	add	x21, sp, #S_FRAME_SIZE
	get_thread_info tsk
	/* Save the task's original addr_limit and set USER_DS (TASK_SIZE_64) */
	ldr	x20, [tsk, #TSK_TI_ADDR_LIMIT]
	str	x20, [sp, #S_ORIG_ADDR_LIMIT]
	mov	x20, #TASK_SIZE_64
	str	x20, [tsk, #TSK_TI_ADDR_LIMIT]
	/* No need to reset PSTATE.UAO, hardware's already set it to 0 for us */
	.endif /* \el == 0 */
	mrs	x22, elr_el1
	mrs	x23, spsr_el1
	stp	lr, x21, [sp, #S_LR]

	/*
	 * In order to be able to dump the contents of struct pt_regs at the
	 * time the exception was taken (in case we attempt to walk the call
	 * stack later), chain it together with the stack frames.
	 */
	.if \el == 0
	stp	xzr, xzr, [sp, #S_STACKFRAME]
	.else
	stp	x29, x22, [sp, #S_STACKFRAME]
	.endif
	add	x29, sp, #S_STACKFRAME

#ifdef CONFIG_ARM64_SW_TTBR0_PAN
	/*
	 * Set the TTBR0 PAN bit in SPSR. When the exception is taken from
	 * EL0, there is no need to check the state of TTBR0_EL1 since
	 * accesses are always enabled.
	 * Note that the meaning of this bit differs from the ARMv8.1 PAN
	 * feature as all TTBR0_EL1 accesses are disabled, not just those to
	 * user mappings.
	 */
alternative_if ARM64_HAS_PAN
	b	1f				// skip TTBR0 PAN
alternative_else_nop_endif

	.if	\el != 0
	mrs	x21, ttbr0_el1
	tst	x21, #0xffff << 48		// Check for the reserved ASID
	orr	x23, x23, #PSR_PAN_BIT		// Set the emulated PAN in the saved SPSR
	b.eq	1f				// TTBR0 access already disabled
	and	x23, x23, #~PSR_PAN_BIT		// Clear the emulated PAN in the saved SPSR
	.endif

	__uaccess_ttbr0_disable x21
1:
#endif

	stp	x22, x23, [sp, #S_PC]

	/* Not in a syscall by default (el0_svc overwrites for real syscall) */
	.if	\el == 0
	mov	w21, #NO_SYSCALL
	str	w21, [sp, #S_SYSCALLNO]
	.endif

	/*
	 * Set sp_el0 to current thread_info.
	 */
	.if	\el == 0
	msr	sp_el0, tsk
	.endif

	/*
	 * Registers that may be useful after this macro is invoked:
	 *
	 * x21 - aborted SP
	 * x22 - aborted PC
	 * x23 - aborted PSTATE
	*/
	.endm
```

Now we are going to explore the `kernel_entry` macro in details.

```
    .macro    kernel_entry, el, regsize = 64
```

The macro accepts 2 parameters: `el` and `regsize`. `el` can be either `0` or `1` depending on whether an exception was generated at EL0 or EL1. `regsize` is 32 if we came from 32-bit EL0 or 64 otherwise.

```
    .if    \regsize == 32
    mov    w0, w0                // zero upper 32 bits of x0
    .endif
```

In 32-bit mode, we use 32-bit general purpose registers (`w0` instead of `x0`).  `w0` is architecturally mapped to the lower part of `x0`. The provided code snippet zeroes upper 32 bits of the `x0` register by writing `w0` to itself.

```
    stp    x0, x1, [sp, #16 * 0]
    stp    x2, x3, [sp, #16 * 1]
    stp    x4, x5, [sp, #16 * 2]
    stp    x6, x7, [sp, #16 * 3]
    stp    x8, x9, [sp, #16 * 4]
    stp    x10, x11, [sp, #16 * 5]
    stp    x12, x13, [sp, #16 * 6]
    stp    x14, x15, [sp, #16 * 7]
    stp    x16, x17, [sp, #16 * 8]
    stp    x18, x19, [sp, #16 * 9]
    stp    x20, x21, [sp, #16 * 10]
    stp    x22, x23, [sp, #16 * 11]
    stp    x24, x25, [sp, #16 * 12]
    stp    x26, x27, [sp, #16 * 13]
    stp    x28, x29, [sp, #16 * 14]
```

This part saves all general purpose registers on the stack. Note, that stack pointer was already adjusted in the [kernel_ventry](https://github.com/torvalds/linux/blob/v4.14/arch/arm64/kernel/entry.S#L74) to fit everything that needs to be stored. The order in which we save registers matters because in Linux there is a special structure [pt_regs](https://github.com/torvalds/linux/blob/v4.14/arch/arm64/include/asm/ptrace.h#L119) that is used to access saved registers later inside an exception handler. As you might see this structure contains not only general purpose registers but also some other information, which is mostly populated later in the `kernel_entry` macro. I recommend you to remember `pt_regs` struct because we are going to implement and use a similar one in the next few lessons.

```
    .if    \el == 0
    mrs    x21, sp_el0
```

`x21` now contains aborted stack pointer. Note, that a task in Linux uses 2 different stacks for user and kernel mode. In case of user mode, we can use `sp_el0` register to figure out the stack pointer value at the moment when the exception was generated. This line is very important because we need to swap stack pointers during the context switch. We will talk about it in details in the next lesson.

```
    ldr_this_cpu    tsk, __entry_task, x20    // Ensure MDSCR_EL1.SS is clear,
    ldr    x19, [tsk, #TSK_TI_FLAGS]    // since we can unmask debug
    disable_step_tsk x19, x20        // exceptions when scheduling.
```

`MDSCR_EL1.SS` bit is responsible for enabling "Software Step exceptions". If this bit is set and debug exceptions are unmasked, an exception is generated after any instruction has been executed. This is commonly used by debuggers. When taking exception from user mode, we need to check first whether [TIF_SINGLESTEP](https://github.com/torvalds/linux/blob/v4.14/arch/arm64/include/asm/thread_info.h#L93) flag is set for the current task. If yes, this indicates that the task is executing under a debugger and we must unset `MDSCR_EL1.SS` bit.
The important thing to understand in this code is how information about the current task is obtained. In Linux, each process or thread (later I will reference any of them as just "task") has a [task_struct](https://github.com/torvalds/linux/blob/v4.14/include/linux/sched.h#L519) associated with it. This struct contains all metadata information about a task. On `arm64` architecture `task_struct` embeds another structure that is called [thread_info](https://github.com/torvalds/linux/blob/v4.14/arch/arm64/include/asm/thread_info.h#L39) so that a pointer to `task_struct` can always be used as a pointer to `thread_info`. `thread_info` is the place were flags are stored along with some other low-level values that `entry.S` need direct access to.

```
    mov    x29, xzr            // fp pointed to user-space
```

Though `x29` is a general purpose register it usually has a special meaning. It is used as a "Frame pointer". Now I want to spend some time to explain its purpose.

When a function is compiled, the first couple of instructions are usually responsible for storing old frame pointer and link register values on the stack. (Just a quick reminder: `x30` is called link register and it holds a "return address" that is used by the `ret` instruction) Then a new stack frame is allocated, so that it can contain all local variables of the function, and frame pointer register is set to point to the bottom of the frame. Whenever the function needs to access some local variable it simply adds hardcoded offset to the frame pointer. Imagine now that an error has occurred and we need to generate a stack trace. We can use current frame pointer to find all local variables in the stack, and the link register can be used used to figure out the precise location of the caller. Next, we take advantage of the fact that old frame pointer and link register values are always saved at the beginning of the stack frame, and we just read them from there. After we get caller's frame pointer we can now access all its local variables as well. This process is repeated recursively until we reach the top of the stack and is called "stack unwinding". A similar algorithm is used by [ptrace](http://man7.org/linux/man-pages/man2/ptrace.2.html) system call.

Now, going back to the `kernel_entry` macro, it should be clear why do we need to clear `x29` register after taking an exception from EL0. That is because in Linux each task uses a different stack for user and kernel mode, and therefore it doesn't make sense to have common stack traces.

```
    .else
    add    x21, sp, #S_FRAME_SIZE
```

Now we are inside else clause, which mean that this code is relevant only if we are handling an exception taken from EL1. In this case, we are reusing old stack and the provided code snippet just saves original `sp` value in the `x21` register for later usage.

```
    /* Save the task's original addr_limit and set USER_DS (TASK_SIZE_64) */
    ldr    x20, [tsk, #TSK_TI_ADDR_LIMIT]
    str    x20, [sp, #S_ORIG_ADDR_LIMIT]
    mov    x20, #TASK_SIZE_64
    str    x20, [tsk, #TSK_TI_ADDR_LIMIT]
```

Task address limit specifies the largest virtual address that can be used. When user process operates in 32-bit mode this limit is `2^32`. For 64 bit kernel it can be larger and usually is `2^48`. If it happens that an exception is taken from 32-bit EL1, task address limit need to be changed to [TASK_SIZE_64](https://github.com/torvalds/linux/blob/v4.14/arch/arm64/include/asm/memory.h#L80). Also, it is required to save the original address limit because it needs to be restored before the execution will be returned to user mode.

```
    mrs    x22, elr_el1
    mrs    x23, spsr_el1
```

`elr_el1` and `spsr_el1` must be saved on the stack before we start handling an exception. We haven't done it yet in the RPI OS, because for now we always return to the same location from which an exception was taken. But what if we need to do a context switch while handling an exception? We will discuss this scenario in details in the next lesson.

```
    stp    lr, x21, [sp, #S_LR]
```

Link register and frame pointer registers are saved on the stack. We already saw that frame pointer is calculated differently depending on whether an exception was taken from EL0 or EL1 and the result of this calculation was already stored in `x21` register.

```
    /*
     * In order to be able to dump the contents of struct pt_regs at the
     * time the exception was taken (in case we attempt to walk the call
     * stack later), chain it together with the stack frames.
     */
    .if \el == 0
    stp    xzr, xzr, [sp, #S_STACKFRAME]
    .else
    stp    x29, x22, [sp, #S_STACKFRAME]
    .endif
    add    x29, sp, #S_STACKFRAME
```

Here [stackframe](https://github.com/torvalds/linux/blob/v4.14/arch/arm64/include/asm/ptrace.h#L140) property of the `pt_regs` struct is filled. This property also contains link register and frame pointer, though this time the value of `elr_el1` (which is now in `x22`) is used instead of `lr`. `stackframe` is used solely for stack unwinding.

```
#ifdef CONFIG_ARM64_SW_TTBR0_PAN
alternative_if ARM64_HAS_PAN
    b    1f                // skip TTBR0 PAN
alternative_else_nop_endif

    .if    \el != 0
    mrs    x21, ttbr0_el1
    tst    x21, #0xffff << 48        // Check for the reserved ASID
    orr    x23, x23, #PSR_PAN_BIT        // Set the emulated PAN in the saved SPSR
    b.eq    1f                // TTBR0 access already disabled
    and    x23, x23, #~PSR_PAN_BIT        // Clear the emulated PAN in the saved SPSR
    .endif

    __uaccess_ttbr0_disable x21
1:
#endif
```

`CONFIG_ARM64_SW_TTBR0_PAN` parameter prevents the kernel from accessing user-space memory directly.  If you are wondering when this might be useful you can read [this](https://kernsec.org/wiki/index.php/Exploit_Methods/Userspace_data_usage) article. For now, I will also skip the detailed explanation of how this works, because such security features are too out of scope for our discussion.

```
    stp    x22, x23, [sp, #S_PC]
```

Here `elr_el1` and `spsr_el1` are saved on the stack.

```
    /* Not in a syscall by default (el0_svc overwrites for real syscall) */
    .if    \el == 0
    mov    w21, #NO_SYSCALL
    str    w21, [sp, #S_SYSCALLNO]
    .endif
```

`pt_regs` struct has a [field](https://github.com/torvalds/linux/blob/v4.14/arch/arm64/include/asm/ptrace.h#L132) indicating whether the current exception is a system call or not. By default, we assume that it isn't. Wait till lecture 5 for the detailed explanation how syscalls work.

```
    /*
     * Set sp_el0 to current thread_info.
     */
    .if    \el == 0
    msr    sp_el0, tsk
    .endif
```

When a task is executed in kernel mode, `sp_el0` is not needed. Its value was previously saved on the stack so it can be easily restored in `kernel_exit` macro. Starting from this point `sp_el0` will be used to hold a pointer to current [task_struct](https://github.com/torvalds/linux/blob/v4.14/include/linux/sched.h#L519) for quick access.

### el1_irq

Next thing we are going to explore is the handler that is responsible for processing IRQs taken from EL1. From the [vector table](https://github.com/torvalds/linux/blob/v4.14/arch/arm64/kernel/entry.S#L374) we can easily find out that the handler is called `el1_irq` and is defined [here](https://github.com/torvalds/linux/blob/v4.14/arch/arm64/kernel/entry.S#L562). Let's take a look on the code now and examine it line by line.

```
el1_irq:
    kernel_entry 1
    enable_dbg
#ifdef CONFIG_TRACE_IRQFLAGS
    bl    trace_hardirqs_off
#endif

    irq_handler

#ifdef CONFIG_PREEMPT
    ldr    w24, [tsk, #TSK_TI_PREEMPT]    // get preempt count
    cbnz    w24, 1f                // preempt count != 0
    ldr    x0, [tsk, #TSK_TI_FLAGS]    // get flags
    tbz    x0, #TIF_NEED_RESCHED, 1f    // needs rescheduling?
    bl    el1_preempt
1:
#endif
#ifdef CONFIG_TRACE_IRQFLAGS
    bl    trace_hardirqs_on
#endif
    kernel_exit 1
ENDPROC(el1_irq)
```

The following is done inside this function.

* `kernel_entry` and `kernel_exit` macros are called to save and restore processor state. The first parameter indicates that the exception is taken from EL1.
* Debug interrupts are unmasked by calling `enable_dbg` macro. At this point, it is safe to do so, because the processor state is already saved and, even if debug exception occurred in the middle of the interrupt handler, it will be processed correctly. If you wonder why is it necessary to unmask debug exceptions during an interrupt processing in the first place - read [this](https://github.com/torvalds/linux/commit/2a2830703a2371b47f7b50b1d35cb15dc0e2b717) commit message.
* Code inside `#ifdef CONFIG_TRACE_IRQFLAGS` block is responsible for tracing interrupts. It records 2 events: interrupt start and end. 
* Code inside `#ifdef CONFIG_PREEMPT` block access current task flags to check whether we need to call the scheduler. This code will be examined details in the next lesson.
* `irq_handler` - this is the place were actual interrupt handling is performed.

[irq_handler](https://github.com/torvalds/linux/blob/v4.14/arch/arm64/kernel/entry.S#L351) is a macro and it is defined as the follows.

```
    .macro    irq_handler
    ldr_l    x1, handle_arch_irq
    mov    x0, sp
    irq_stack_entry
    blr    x1
    irq_stack_exit
    .endm
```

As you might see from the code, `irq_handler` executes [handle_arch_irq](https://github.com/torvalds/linux/blob/v4.14/arch/arm64/kernel/irq.c#L44)  function. This function is executed with special stack, that is called "irq stack".  Why is it necessary to switch to a different stack? In RPI OS, for example, we didn't do this.  Well, I guess it is not necessary, but without it, an interrupt will be handled using task stack, and we can never be sure how much of it is still left for the interrupt handler.

Next, we need to look at [handle_arch_irq](https://github.com/torvalds/linux/blob/v4.14/arch/arm64/kernel/irq.c#L44). It appears that it is not a function, but a variable. It is set inside [set_handle_irq](https://github.com/torvalds/linux/blob/v4.14/arch/arm64/kernel/irq.c#L46) function. But who sets it, and what is the fade of an interrupt after it reaches this point? We will figure out the answer in the next chapter of this lesson.

### Conclusion

As a conclusion, I can say that we've already explored the low-level interrupt handling code and trace the path of an interrupt from the vector table all the way to the `handle_arch_irq`. This is the point were an interrupt leaves architecture specific code and started to be handled by a driver code. Our goal in the next chapter will be to trace the path of a timer interrupt through the driver source code.

##### Previous Page

3.1 [Interrupt handling: RPi OS](../../../docs/lesson03/rpi-os.md)

##### Next Page

3.3 [Interrupt handling: Interrupt controllers](../../../docs/lesson03/linux/interrupt_controllers.md)


================================================
FILE: docs/lesson03/linux/timer.md
================================================
## 3.4: Timers

We finished the last chapter by examining global interrupt controller. We were able to trace the path of a timer interrupt all the way up to the [bcm2836_chained_handle_irq](https://github.com/torvalds/linux/blob/v4.14/drivers/irqchip/irq-bcm2835.c#L246) function. Next logical step is to see how the timer driver handles this interrupt. However, before we can do this, you need to familiarize yourself with a few important concepts related to timer functionality. All of them are explained in the [official kernel documentation](https://github.com/torvalds/linux/blob/v4.14/Documentation/timers/timekeeping.txt), and I strongly advise you to read this document. But for those who are too busy to read it, I can provide my own brief explanation of the mentioned concepts.

1. **Clock sources** Each time you need to find out exactly what time it is now you are using clock source framework. Typically the clock source is implemented as a monotonic, atomic n-bit counter, which counts from 0 to 2^(n-1) and then wraps around to 0 and starts over. The clock source also provides means to translate the counter into a nanosecond value.
1. **Clock events** This abstraction is introduced to allow anybody to subscribe on timer interrupts. Clock events framework takes designed time of the next event as an input and, based on it, calculates appropriate values of the timer hardware registers.
1. **sched_clock()** This function returns the number of nanoseconds since the system was started. It usually does so by directly reading timer registers. This function is called very frequently and should be optimized for performance.

In the next section, we are going to see how system timer is used to implement clock sources, clock events and sched_clock functionality.

### BCM2835 System Timer.

As usual, we start the exploration of a particular device with finding its location in the device tree. System timer node is defined [here](https://github.com/torvalds/linux/blob/v4.14/arch/arm/boot/dts/bcm283x.dtsi#L57). You can keep this definition open for a while because we are going to reference it several times.

Next, we need to use `compatible` property to figure out the location of the corresponding driver. The driver can be found [here](https://github.com/torvalds/linux/blob/v4.14/drivers/clocksource/bcm2835_timer.c). The first thing we are going to look at is [bcm2835_timer](https://github.com/torvalds/linux/blob/v4.14/drivers/clocksource/bcm2835_timer.c#L42) structure.

```
struct bcm2835_timer {
    void __iomem *control;
    void __iomem *compare;
    int match_mask;
    struct clock_event_device evt;
    struct irqaction act;
};
```

This structure contains all state needed for the driver to function. `control` and `compare` fields holds the addresses of the corresponding memory mapped registers, `match_mask` is used to determine which of the 4 available timer interrupts we are going to use, `evt` field contains a structure that is passed to clock events framework and `act` is an irq action that is used to connect the current driver with the interrupt controller. 

Next we are going to look at [bcm2835_timer_init](https://github.com/torvalds/linux/blob/v4.14/drivers/clocksource/bcm2835_timer.c#L83) which is the driver initialization function. It is large, but not as difficult as you might think from the beginning.

```
static int __init bcm2835_timer_init(struct device_node *node)
{
    void __iomem *base;
    u32 freq;
    int irq, ret;
    struct bcm2835_timer *timer;

    base = of_iomap(node, 0);
    if (!base) {
        pr_err("Can't remap registers\n");
        return -ENXIO;
    }

    ret = of_property_read_u32(node, "clock-frequency", &freq);
    if (ret) {
        pr_err("Can't read clock-frequency\n");
        goto err_iounmap;
    }

    system_clock = base + REG_COUNTER_LO;
    sched_clock_register(bcm2835_sched_read, 32, freq);

    clocksource_mmio_init(base + REG_COUNTER_LO, node->name,
        freq, 300, 32, clocksource_mmio_readl_up);

    irq = irq_of_parse_and_map(node, DEFAULT_TIMER);
    if (irq <= 0) {
        pr_err("Can't parse IRQ\n");
        ret = -EINVAL;
        goto err_iounmap;
    }

    timer = kzalloc(sizeof(*timer), GFP_KERNEL);
    if (!timer) {
        ret = -ENOMEM;
        goto err_iounmap;
    }

    timer->control = base + REG_CONTROL;
    timer->compare = base + REG_COMPARE(DEFAULT_TIMER);
    timer->match_mask = BIT(DEFAULT_TIMER);
    timer->evt.name = node->name;
    timer->evt.rating = 300;
    timer->evt.features = CLOCK_EVT_FEAT_ONESHOT;
    timer->evt.set_next_event = bcm2835_time_set_next_event;
    timer->evt.cpumask = cpumask_of(0);
    timer->act.name = node->name;
    timer->act.flags = IRQF_TIMER | IRQF_SHARED;
    timer->act.dev_id = timer;
    timer->act.handler = bcm2835_time_interrupt;

    ret = setup_irq(irq, &timer->act);
    if (ret) {
        pr_err("Can't set up timer IRQ\n");
        goto err_iounmap;
    }

    clockevents_config_and_register(&timer->evt, freq, 0xf, 0xffffffff);

    pr_info("bcm2835: system timer (irq = %d)\n", irq);

    return 0;

err_iounmap:
    iounmap(base);
    return ret;
}
```
Now let's take a closer look at this function.

```
    base = of_iomap(node, 0);
    if (!base) {
        pr_err("Can't remap registers\n");
        return -ENXIO;
    }
```

It starts with mapping memory registers and obtaining register base address. You should be already familiar with this part.

```
    ret = of_property_read_u32(node, "clock-frequency", &freq);
    if (ret) {
        pr_err("Can't read clock-frequency\n");
        goto err_iounmap;
    }

    system_clock = base + REG_COUNTER_LO;
    sched_clock_register(bcm2835_sched_read, 32, freq);
```

Next, `sched_clock` subsystem is initialized. `sched_clock` need to access timer counter registers each time it is executed and [bcm2835_sched_read](https://github.com/torvalds/linux/blob/v4.14/drivers/clocksource/bcm2835_timer.c#L52) is passed as the first argument to assist with this task. The second argument corresponds to the number of bits that the timer counter has (in our case it is 32). the number of bits is used to calculate how soon the counter is going to wrap to 0. The last argument specifies timer frequency - it is used to convert values of the timer counter to nanoseconds. Timer frequency is defined in the device tree at [this](https://github.com/torvalds/linux/blob/v4.14/arch/arm/boot/dts/bcm283x.dtsi#L65) line.

```
    clocksource_mmio_init(base + REG_COUNTER_LO, node->name,
        freq, 300, 32, clocksource_mmio_readl_up);
```

Next line initializes clock source framework. [clocksource_mmio_init](https://github.com/torvalds/linux/blob/v4.14/drivers/clocksource/mmio.c#L52) initializes a simple clock source based on memory mapped registers. The clock source framework, in some aspects, duplicates the functionality of `sched_clock` and it needs access to the same 3 basic parameters.

* The location of the timer counter register.
* The number of valid bits in the counter.
* Timer frequency.

Another 3 parameters include the name of the clock source, its rating, which is used to rate clock source devices, and a function that can read timer counter register.

```
    irq = irq_of_parse_and_map(node, DEFAULT_TIMER);
    if (irq <= 0) {
        pr_err("Can't parse IRQ\n");
        ret = -EINVAL;
        goto err_iounmap;
    }
```

This code snippet is used to find Linux irq number, corresponding to the third timer interrupt (Number 3 is hardcoded as [DEFAULT_TIMER](https://github.com/torvalds/linux/blob/v4.14/drivers/clocksource/bcm2835_timer.c#L108) constant). Just a quick reminder: Raspberry Pi system timer has 4 independent set of timer registers, and here the third one is used.  If you go back to the device tree, you can find [interrupts](https://github.com/torvalds/linux/blob/v4.14/arch/arm/boot/dts/bcm283x.dtsi#L60) property. This property describes all interrupts, supported by a device, and how those interrupts are mapped to interrupt controller lines. It is an array, where each item represents one interrupt. The format of the items is specific to the interrupt controller. In our case, each item consists of 2 numbers: the first one specifies an interrupt bank and the second - interrupt number inside the bank. [irq_of_parse_and_map](https://github.com/torvalds/linux/blob/v4.14/drivers/of/irq.c#L41) reads the value of `interrupts` property, then it uses the second argument to find which of the supported interrupts we are interested in and returns Linux irq number for the requested interrupt.

```
    timer = kzalloc(sizeof(*timer), GFP_KERNEL);
    if (!timer) {
        ret = -ENOMEM;
        goto err_iounmap;
    }
```

Here memory for `bcm2835_timer` structure is allocated.

```
    timer->control = base + REG_CONTROL;
    timer->compare = base + REG_COMPARE(DEFAULT_TIMER);
    timer->match_mask = BIT(DEFAULT_TIMER);
```

Next, the addresses of the control and compare registers are calculated and `match_mask` is set to the `DEFAULT_TIMER` constant.

```
    timer->evt.name = node->name;
    timer->evt.rating = 300;
    timer->evt.features = CLOCK_EVT_FEAT_ONESHOT;
    timer->evt.set_next_event = bcm2835_time_set_next_event;
    timer->evt.cpumask = cpumask_of(0);
```

In this code snippet [clock_event_device](https://github.com/torvalds/linux/blob/v4.14/include/linux/clockchips.h#L100) struct is initialized. The most important property here is `set_next_event` which points to [bcm2835_time_set_next_event](https://github.com/torvalds/linux/blob/v4.14/drivers/clocksource/bcm2835_timer.c#L57)  function. This function is called by the clock events framework to schedule next interrupt. `bcm2835_time_set_next_event` is very simple - it updates compare register so that interrupt will be scheduled after a desied interval. This is analogaus to what we did [here](https://github.com/s-matyukevich/raspberry-pi-os/blob/master/src/lesson03/src/timer.c#L17) for the RPi OS.

```
    timer->act.flags = IRQF_TIMER | IRQF_SHARED;
    timer->act.dev_id = timer;
    timer->act.handler = bcm2835_time_interrupt;
```

Next, irq action is initialized. The most important property here is `handler`, which points to [bcm2835_time_interrupt](https://github.com/torvalds/linux/blob/v4.14/drivers/clocksource/bcm2835_timer.c#L67) -  this is the function that is called after an interrupt is fired. If you take a look at it, you will see that it redirects all work to the event handler, registered by the clock events framework. We will examine this event handler in a while.

```
    ret = setup_irq(irq, &timer->act);
    if (ret) {
        pr_err("Can't set up timer IRQ\n");
        goto err_iounmap;
    }
```

After the irq action is configured, it is added to the list of irq actions of the timer interrupt.

```
    clockevents_config_and_register(&timer->evt, freq, 0xf, 0xffffffff);
```

And finally clock events framework is initialized by calling [clockevents_config_and_register](https://github.com/torvalds/linux/blob/v4.14/kernel/time/clockevents.c#L504). `evt` structure and timer frequency are passed as first 2 arguments. Last 2 arguments are used only in "one-shot" timer mode and are not relevant to our current discussion.

Now, we have traced the path of a timer interrupt all the way up to the `bcm2835_time_interrupt` function, but we still didn't find the place were the actual work is done. In the next section, we are going to dig even deeper and find out how an interrupt is processed when it enters the clock events framework.

### How an interrupt is processed in the clock events framework

In the previous section, we have seen that the real work of handling a timer interrupt is outsourced to the clock events framework. This is done in the [following](https://github.com/torvalds/linux/blob/v4.14/drivers/clocksource/bcm2835_timer.c#L74) few lines.

```
        event_handler = ACCESS_ONCE(timer->evt.event_handler);
        if (event_handler)
            event_handler(&timer->evt);
```

Now our goal will be to figure out were exactly `event_handler`  is set and what happens after it is called.

[clockevents_config_and_register](https://github.com/torvalds/linux/blob/v4.14/kernel/time/clockevents.c#L504) function is a good place to start the exploration because this is the place where clock events framework is configured and, if we follow the logic of this function, eventually we should find how `event_handler` is set.

Now let me show you the chain of function calls that leads us to the place we need.

1. [clockevents_config_and_register](https://github.com/torvalds/linux/blob/v4.14/kernel/time/clockevents.c#L504) This is the top level initialization function.
1. [clockevents_register_device](https://github.com/torvalds/linux/blob/v4.14/kernel/time/clockevents.c#L449) In this function the timer is added to the global list of clock event devices.
1. [tick_check_new_device](https://github.com/torvalds/linux/blob/v4.14/kernel/time/tick-common.c#L300)  This function checks whether the current device is a good candidate to be used as a "tick device". If yes, such device will be used to generate periodic ticks that the rest of the kernel will use to do all work that needs to be done on a regular basis. 
1. [tick_setup_device](https://github.com/torvalds/linux/blob/v4.14/kernel/time/tick-common.c#L177) This function starts device configuration.
1. [tick_setup_periodic](https://github.com/torvalds/linux/blob/v4.14/kernel/time/tick-common.c#L144) This is the place were device is configured for periodic tics.
1. [tick_set_periodic_handler](https://github.com/torvalds/linux/blob/v4.14/kernel/time/tick-broadcast.c#L432)  Finally we reached the place where the handler is assigned!

If you take a look at the last function in the call chain, you will see that Linux uses different handlers depending on whether broadcast is enabled or not. Tick broadcast is used to awake idle CPUs, you can read more about it [here](https://lwn.net/Articles/574962/). But we are going to ignore it and concentrate on a more general tick handler instead.

In general case [tick_handle_periodic](https://github.com/torvalds/linux/blob/v4.14/kernel/time/tick-common.c#L99) and then [tick_periodic](https://github.com/torvalds/linux/blob/v4.14/kernel/time/tick-common.c#L79) functions are called. The later one is exactly the function that we are interested in. Let me copy its content here.

```
/*
 * Periodic tick
 */
static void tick_periodic(int cpu)
{
    if (tick_do_timer_cpu == cpu) {
        write_seqlock(&jiffies_lock);

        /* Keep track of the next tick event */
        tick_next_period = ktime_add(tick_next_period, tick_period);

        do_timer(1);
        write_sequnlock(&jiffies_lock);
        update_wall_time();
    }

    update_process_times(user_mode(get_irq_regs()));
    profile_tick(CPU_PROFILING);
}
```

A few important things are done in this function:

1. `tick_next_period` is calculated so that next tick event can be scheduled.
1.  [do_timer](https://github.com/torvalds/linux/blob/v4.14/kernel/time/timekeeping.c#L2200) is called, which is responsible for setting 'jiffies'. `jiffies` is a number of ticks since the last system reboot. `jiffies` can be used in the same way as `sched_clock` function, in cases when you don't need nanosecond precision.
1. [update_process_times](https://github.com/torvalds/linux/blob/v4.14/kernel/time/timer.c#L1583) is called. This is the place where currently executing process is given a chance to do all work that needed to be done periodically. This work includes, for example, running local process timers, or, most importantly, notifying the scheduler about the tick event.

### Conclusion

Now you see how long is the way of an ordinary timer interrupt, but we followed it from the beginning to the very end. One of the things that are the most important, is that we finally reached the place where the scheduler is called. The scheduler is one of the most critical parts of any operating system and it relies heavily on timer interrupts. So now, when we've seen where the scheduler functionality is triggered, its time to discuss its implementation - that is something we are going to do in the next lesson.

##### Previous Page

3.3 [Interrupt handling: Interrupt controllers](../../../docs/lesson03/linux/interrupt_controllers.md)

##### Next Page

3.5 [Interrupt handling: Exercises](../../../docs/lesson03/exercises.md)


================================================
FILE: docs/lesson03/rpi-os.md
================================================
## 3.1: Interrupts

From the lesson 1, we already know how to communicate with hardware. However, most of the time the pattern of communication is not that simple. Usually, this pattern is asynchronous: we send some command to a device, but it doesn't respond immediately. Instead, it notifies us when the work is completed. Such asynchronous notifications are called "interrupts" because they interrupt normal execution flow and force the processor to execute an "interrupt handler".

There is one device that is particularly useful in operating system development: system timer. It is a device that can be configured to periodically interrupt a processor with some predefined frequency. One particular application of the timer that it is used in the process scheduling. A scheduler needs to measure for how long each process has been executed and use this information to select the next process to run. This measurement is based on timer interrupts.

We are going to talk about process scheduling in details in the next lesson, but for now, our task will be to initialize system timer and implement a timer interrupt handler.

### Interrupts vs exceptions

In ARM.v8 architecture, interrupts are part of a more general term: exceptions. There are 4 types of exceptions

* **Synchronous exception** Exceptions of this type are always caused by the currently executed instruction. For example, you can use `str` instruction to store some data at an unexistent memory location. In this case, a synchronous exception is generated. Synchronous exceptions also can be used to generate a "software interrupt". Software interrupt is a synchronous exception that is generated on purpose by `svc` instruction. We will use this technique in lesson 5 to implement system calls.
* **IRQ (Interrupt Request)** Those are normal interrupts. They are always asynchronous, which means that they have nothing to do with the currently executed instruction.  In contrast to synchronous exceptions, they are always not generated by the processor itself, but by external hardware.
* **FIQ (Fast Interrupt Request)** This type of exception is called "fast interrupts" and exist solely for the purpose of prioritizing exceptions. It is possible to configure some interrupts as "normal" and other as "fast". Fast interrupts will be signaled first and will be handled by a separate exception handler. Linux doesn't use fast interrupts and we also are not going to do so.
* **SError (System Error)** Like `IRQ` and `FIQ`, `SError` exceptions are asynchronous and are generated by external hardware. Unlike `IRQ` and `FIQ`, `SError` always indicates some error condition. [Here](https://community.arm.com/processors/f/discussions/3205/re-what-is-serror-detailed-explanation-is-required) you can find an example explaining when `SError` can be generated.

### Exception vectors

Each exception type needs its own handler. Also, separate handlers should be defined for each different execution state, in which exception is generated. There are 4 execution states that are interesting from the exception handling standpoint. If we are working at EL1 those states can be defined as follows:

1. **EL1t** Exception is taken from EL1 while stack pointer was shared with EL0. This happens when `SPSel` register holds the value `0`.
1. **EL1h** Exception is taken from EL1 at the time when dedicated stack pointer was allocated for EL1. This means that `SPSel` holds the value `1` and this is the mode that we are currently using.
1. **EL0_64** Exception is taken from EL0 executing in 64-bit mode.
1. **EL0_32** Exception is taken from EL0 executing in 32-bit mode.

In total, we need to define 16 exception handlers (4 exception levels multiplied by 4 execution states) A special structure that holds addresses of all exception handlers is called *exception vector table* or just *vector table*. The structure of a vector table is defined in `Table D1-7 Vector offsets from vector table base address` at page 1876 of the [AArch64-Reference-Manual](https://developer.arm.com/docs/ddi0487/ca/arm-architecture-reference-manual-armv8-for-armv8-a-architecture-profile). You can think of a vector table as an array of exception vectors, where each exception vector (or handler) is a continuous sequence of instructions responsible for handling a particular exception. Accordingly, to `Table D1-7` from `AArch64-Reference-Manual`, each exception vector can ocupy `0x80` bytes maximum. This is not much, but nobody prevents us from jumping to some other memory location from an exception vector. 

I think all of this will be much clearer with an example, so now it is time to see how exception vectors are implemented in the RPI-OS. Everything related to exception handling is defined in [entry.S](https://github.com/s-matyukevich/raspberry-pi-os/blob/master/src/lesson03/src/entry.S) and we are going to start examining it right now.

The first useful macro is called [ventry](https://github.com/s-matyukevich/raspberry-pi-os/blob/master/src/lesson03/src/entry.S#L12) and it is used to create entries in the vector table.

```
    .macro    ventry    label
    .align    7
    b    \label
    .endm
```

As you might infer from this definition, we are not going to handle exceptions right inside the exception vector, but instead, we jump to a label that is provided for the macro as `label` argument. We need `.align 7` instruction because all exception vectors should be located at offset `0x80` bytes one from another. 

Vector table is defined [here](https://github.com/s-matyukevich/raspberry-pi-os/blob/master/src/lesson03/src/entry.S#L64) and it consists of 16 `ventry` definitions. For now we are only interested in handling `IRQ` from `EL1h` but we still need to define all 16 handlers. This is not because of some hardware requirement, but rather because we want to see a meaningful error message in case something goes wrong. All handlers that should never be executed in normal flow have `invalid` postfix and uses [handle_invalid_entry](https://github.com/s-matyukevich/raspberry-pi-os/blob/master/src/lesson03/src/entry.S#L3) macro. Let's take a look at how this macro is defined.

```
    .macro handle_invalid_entry type
    kernel_entry
    mov    x0, #\type
    mrs    x1, esr_el1
    mrs    x2, elr_el1
    bl    show_invalid_entry_message
    b    err_hang
    .endm
```

In the first line, you can see that another macro is used: `kernel_entry`. We will discuss it shortly.
Then we call [show_invalid_entry_message](https://github.com/s-matyukevich/raspberry-pi-os/blob/master/src/lesson03/src/irq.c#L34) and prepare 3 arguments for it. The first argument is exception type that can take one of [these](https://github.com/s-matyukevich/raspberry-pi-os/blob/master/src/lesson03/include/entry.h#L6) values. It tells us exactly which exception handler has been executed.
The second parameter is the most important one, it is called `ESR` which stands for Exception Syndrome Register. This argument is taken from `esr_el1` register, which is described on page 2431 of `AArch64-Reference-Manual`. This register contains detailed information about what causes an exception. 
The third argument is important mostly in case of synchronous exceptions. Its value is taken from already familiar to us `elr_el1` register, which contains the address of the instruction that had been executed when the exception was generated. For synchronous exceptions, this is also the instruction that causes the exception.
After `show_invalid_entry_message`  function prints all this information to the screen we put the processor in an infinite loop because there is not much else we can do.

### Saving register state

After an exception handler finishes execution, we want all general purpose registers to have the same values they had before the exception was generated. If we don't implement such functionality, an interrupt that has nothing to do with currently executing code, can influence the behavior of this code unpredictably. That's why the first thing we must do after an exception is generated is to save the processor state. This is done in the [kernel_entry](https://github.com/s-matyukevich/raspberry-pi-os/blob/master/src/lesson03/src/entry.S) macro. This macro is very simple: it just stores registers `x0 - x30` to the stack. There is also a corresponding macro [kernel_exit](https://github.com/s-matyukevich/raspberry-pi-os/blob/master/src/lesson03/src/entry.S#L37), which is called after an exception handler finishes execution. `kernel_exit` restores processor state by copying back the values of `x0 - x30` registers. It also executes `eret` instruction, which returns us back to normal execution flow. By the way, general purpose registers are not the only thing that needs to be saved before executing an exception handler, but it is enough for our simple kernel for now. In later lessons, we will add more functionality to the `kernel_entry` and `kernel_exit` macros.

### Setting the vector table

Ok, now we have prepared the vector table, but the processor doesn't know where it is located and therefore can't use it. In order for the exception handling to work, we must set `vbar_el1` (Vector Base Address Register) to the vector table address. This is done [here](https://github.com/s-matyukevich/raspberry-pi-os/blob/master/src/lesson03/src/irq.S#L2).

```
.globl irq_vector_init
irq_vector_init:
    adr    x0, vectors        // load VBAR_EL1 with virtual
    msr    vbar_el1, x0        // vector table address
    ret
```

### Masking/unmasking interrupts

Another thing that we need to do is to unmask all types of interrupts. Let me explain what I mean by "unmasking" an interrupt. Sometimes there is a need to tell that a particular piece of code must never be intercepted by an asynchronous interrupt. Imagine, for example, what happens if an interrupt occurs right in the middle of `kernel_entry` macro? In this case, processor state would be overwritten and lost. That's why whenever an exception handler is executed, the processor automatically disables all types of interrupts. This is called "masking", and this also can be done manually if we need to do so.

Many people mistakenly think that interrupts must be masked for the whole duration of the exception handler. This isn't true - it is perfectly legal to unmask interrupts after you saved processor state and therefore it is also legal to have nested interrupts. We are not going to do this right now, but this is important information to keep in mind.

The [following two functions](https://github.com/s-matyukevich/raspberry-pi-
Download .txt
gitextract_cgeajq_d/

├── .gitignore
├── Dockerfile
├── LICENSE
├── README.md
├── _config.yml
├── _layouts/
│   └── default.html
├── assets/
│   └── css/
│       └── style.scss
├── docs/
│   ├── Contributions.md
│   ├── Introduction.md
│   ├── Prerequisites.md
│   ├── lesson01/
│   │   ├── exercises.md
│   │   ├── linux/
│   │   │   ├── build-system.md
│   │   │   ├── kernel-startup.md
│   │   │   └── project-structure.md
│   │   └── rpi-os.md
│   ├── lesson02/
│   │   ├── exercises.md
│   │   ├── linux.md
│   │   └── rpi-os.md
│   ├── lesson03/
│   │   ├── exercises.md
│   │   ├── linux/
│   │   │   ├── interrupt_controllers.md
│   │   │   ├── low_level-exception_handling.md
│   │   │   └── timer.md
│   │   └── rpi-os.md
│   ├── lesson04/
│   │   ├── exercises.md
│   │   ├── linux/
│   │   │   ├── basic_structures.md
│   │   │   ├── fork.md
│   │   │   └── scheduler.md
│   │   └── rpi-os.md
│   ├── lesson05/
│   │   ├── exercises.md
│   │   ├── linux.md
│   │   └── rpi-os.md
│   └── lesson06/
│       ├── exercises.md
│       └── rpi-os.md
├── exercises/
│   ├── lesson01/
│   │   ├── 1/
│   │   │   ├── H-4ND-H/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       └── utils.S
│   │   │   ├── a-v-v/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       └── utils.S
│   │   │   ├── adkaster/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       └── utils.S
│   │   │   ├── avenito/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       └── utils.S
│   │   │   ├── bl4ckout31/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       └── utils.S
│   │   │   ├── evopen/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.sh
│   │   │   │   ├── config.txt
│   │   │   │   ├── include/
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── kernel_main.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       └── utils.S
│   │   │   ├── gcrisis/
│   │   │   │   ├── Makefile
│   │   │   │   ├── include/
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       └── utils.S
│   │   │   ├── rs/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       └── utils.S
│   │   │   ├── stefanji/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       └── utils.S
│   │   │   ├── xdfm1/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       └── utils.S
│   │   │   └── zjd0112/
│   │   │       ├── Makefile
│   │   │       ├── build.bat
│   │   │       ├── build.sh
│   │   │       ├── include/
│   │   │       │   ├── mini_uart.h
│   │   │       │   ├── mm.h
│   │   │       │   ├── peripherals/
│   │   │       │   │   ├── base.h
│   │   │       │   │   ├── gpio.h
│   │   │       │   │   └── mini_uart.h
│   │   │       │   └── utils.h
│   │   │       └── src/
│   │   │           ├── boot.S
│   │   │           ├── config.txt
│   │   │           ├── kernel.c
│   │   │           ├── linker.ld
│   │   │           ├── mini_uart.c
│   │   │           ├── mm.S
│   │   │           └── utils.S
│   │   ├── 2/
│   │   │   ├── H-4ND-H/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── uart_pl011.h
│   │   │   │   │   ├── uart_pl011.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mm.S
│   │   │   │       ├── uart_pl011.c
│   │   │   │       └── utils.S
│   │   │   ├── a-v-v/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── uart.h
│   │   │   │   │   ├── uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mm.S
│   │   │   │       ├── uart.c
│   │   │   │       └── utils.S
│   │   │   ├── adkaster/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   │   └── uart.h
│   │   │   │   │   ├── uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       ├── uart.c
│   │   │   │       └── utils.S
│   │   │   ├── avenito/
│   │   │   │   ├── Makefile
│   │   │   │   ├── README.md
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── uart.h
│   │   │   │   │   ├── uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mm.S
│   │   │   │       ├── uart.c
│   │   │   │       └── utils.S
│   │   │   ├── bl4ckout31/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── uart.h
│   │   │   │   │   ├── uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mm.S
│   │   │   │       ├── uart.c
│   │   │   │       └── utils.S
│   │   │   ├── evopen/
│   │   │   │   ├── .gitignore
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.sh
│   │   │   │   ├── config.txt
│   │   │   │   ├── include/
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   │   └── uart.h
│   │   │   │   │   ├── uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   ├── src/
│   │   │   │   │   ├── boot.S
│   │   │   │   │   ├── kernel.c
│   │   │   │   │   ├── linker-qemu.ld
│   │   │   │   │   ├── linker.ld
│   │   │   │   │   ├── mm.S
│   │   │   │   │   ├── uart.c
│   │   │   │   │   └── utils.S
│   │   │   │   └── start.sh
│   │   │   ├── gcrisis/
│   │   │   │   ├── Makefile
│   │   │   │   ├── include/
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── uart.h
│   │   │   │   │   ├── uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   ├── src/
│   │   │   │   │   ├── boot.S
│   │   │   │   │   ├── config.txt
│   │   │   │   │   ├── kernel.c
│   │   │   │   │   ├── linker.ld
│   │   │   │   │   ├── mm.S
│   │   │   │   │   ├── uart.c
│   │   │   │   │   └── utils.S
│   │   │   │   └── uart-boot/
│   │   │   │       ├── Makefile
│   │   │   │       ├── downloader/
│   │   │   │       │   └── raspiloader.c
│   │   │   │       ├── include/
│   │   │   │       │   ├── mm.h
│   │   │   │       │   ├── peripherals/
│   │   │   │       │   │   ├── base.h
│   │   │   │       │   │   ├── gpio.h
│   │   │   │       │   │   └── uart.h
│   │   │   │       │   ├── uart.h
│   │   │   │       │   └── utils.h
│   │   │   │       ├── readme
│   │   │   │       └── src/
│   │   │   │           ├── boot.S
│   │   │   │           ├── config.txt
│   │   │   │           ├── linker.ld
│   │   │   │           ├── main.c
│   │   │   │           ├── mm.S
│   │   │   │           ├── uart.c
│   │   │   │           └── utils.S
│   │   │   ├── rs/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── uart.h
│   │   │   │   │   ├── uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mm.S
│   │   │   │       ├── uart.c
│   │   │   │       └── utils.S
│   │   │   ├── stefanji/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── uart_pl011.h
│   │   │   │   │   ├── pl011_uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mm.S
│   │   │   │       ├── pl011_uart.c
│   │   │   │       └── utils.S
│   │   │   ├── xdfm1/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── uart.h
│   │   │   │   │   ├── uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mm.S
│   │   │   │       ├── uart.c
│   │   │   │       └── utils.S
│   │   │   └── zjd0112/
│   │   │       ├── Makefile
│   │   │       ├── build.bat
│   │   │       ├── build.sh
│   │   │       ├── include/
│   │   │       │   ├── mini_uart.h
│   │   │       │   ├── mm.h
│   │   │       │   ├── peripherals/
│   │   │       │   │   ├── base.h
│   │   │       │   │   ├── gpio.h
│   │   │       │   │   ├── mini_uart.h
│   │   │       │   │   └── pl011_uart.h
│   │   │       │   ├── pl011_uart.h
│   │   │       │   └── utils.h
│   │   │       └── src/
│   │   │           ├── boot.S
│   │   │           ├── config.txt
│   │   │           ├── kernel.c
│   │   │           ├── linker.ld
│   │   │           ├── mini_uart.c
│   │   │           ├── mm.S
│   │   │           ├── pl011_uart.c
│   │   │           └── utils.S
│   │   ├── 3/
│   │   │   ├── a-v-v/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       └── utils.S
│   │   │   ├── adkaster/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       └── utils.S
│   │   │   ├── avenito/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       └── utils.S
│   │   │   ├── bl4ckout31/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       └── utils.S
│   │   │   ├── evopen/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.sh
│   │   │   │   ├── config.txt
│   │   │   │   ├── include/
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       └── utils.S
│   │   │   ├── gcrisis/
│   │   │   │   ├── Makefile
│   │   │   │   ├── include/
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       └── utils.S
│   │   │   ├── rs/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       └── utils.S
│   │   │   ├── stefanji/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       └── utils.S
│   │   │   ├── szediwy/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       └── utils.S
│   │   │   └── zjd0112/
│   │   │       ├── Makefile
│   │   │       ├── build.bat
│   │   │       ├── build.sh
│   │   │       ├── include/
│   │   │       │   ├── mini_uart.h
│   │   │       │   ├── mm.h
│   │   │       │   ├── peripherals/
│   │   │       │   │   ├── base.h
│   │   │       │   │   ├── gpio.h
│   │   │       │   │   ├── mini_uart.h
│   │   │       │   │   └── pl011_uart.h
│   │   │       │   ├── pl011_uart.h
│   │   │       │   └── utils.h
│   │   │       └── src/
│   │   │           ├── boot.S
│   │   │           ├── config.txt
│   │   │           ├── kernel.c
│   │   │           ├── linker.ld
│   │   │           ├── mini_uart.c
│   │   │           ├── mm.S
│   │   │           ├── pl011_uart.c
│   │   │           └── utils.S
│   │   └── 4/
│   │       ├── H-4ND-H/
│   │       │   ├── Makefile
│   │       │   ├── build.bat
│   │       │   ├── build.sh
│   │       │   ├── include/
│   │       │   │   ├── mini_uart.h
│   │       │   │   ├── mm.h
│   │       │   │   ├── peripherals/
│   │       │   │   │   ├── base.h
│   │       │   │   │   ├── gpio.h
│   │       │   │   │   └── mini_uart.h
│   │       │   │   └── utils.h
│   │       │   └── src/
│   │       │       ├── boot.S
│   │       │       ├── config.txt
│   │       │       ├── kernel.c
│   │       │       ├── linker.ld
│   │       │       ├── mini_uart.c
│   │       │       ├── mm.S
│   │       │       └── utils.S
│   │       ├── a-v-v/
│   │       │   ├── Makefile
│   │       │   ├── build.bat
│   │       │   ├── build.sh
│   │       │   ├── include/
│   │       │   │   ├── mini_uart.h
│   │       │   │   ├── mm.h
│   │       │   │   ├── peripherals/
│   │       │   │   │   ├── base.h
│   │       │   │   │   ├── gpio.h
│   │       │   │   │   └── mini_uart.h
│   │       │   │   └── utils.h
│   │       │   ├── src/
│   │       │   │   ├── boot.S
│   │       │   │   ├── config.txt
│   │       │   │   ├── kernel.c
│   │       │   │   ├── linker.ld
│   │       │   │   ├── mini_uart.c
│   │       │   │   ├── mm.S
│   │       │   │   └── utils.S
│   │       │   └── start_qemu.sh
│   │       ├── avenito/
│   │       │   ├── Makefile
│   │       │   ├── build.bat
│   │       │   ├── build.sh
│   │       │   ├── include/
│   │       │   │   ├── mm.h
│   │       │   │   ├── peripherals/
│   │       │   │   │   ├── base.h
│   │       │   │   │   ├── gpio.h
│   │       │   │   │   └── uart.h
│   │       │   │   ├── uart.h
│   │       │   │   └── utils.h
│   │       │   └── src/
│   │       │       ├── boot.S
│   │       │       ├── config.txt
│   │       │       ├── kernel.c
│   │       │       ├── linker.ld
│   │       │       ├── mm.S
│   │       │       ├── uart.c
│   │       │       └── utils.S
│   │       ├── bl4ckout31/
│   │       │   ├── Makefile
│   │       │   ├── build.bat
│   │       │   ├── build.sh
│   │       │   ├── include/
│   │       │   │   ├── mm.h
│   │       │   │   ├── peripherals/
│   │       │   │   │   ├── base.h
│   │       │   │   │   ├── gpio.h
│   │       │   │   │   └── uart.h
│   │       │   │   ├── uart.h
│   │       │   │   └── utils.h
│   │       │   ├── src/
│   │       │   │   ├── boot.S
│   │       │   │   ├── config.txt
│   │       │   │   ├── kernel.c
│   │       │   │   ├── linker.ld
│   │       │   │   ├── mm.S
│   │       │   │   ├── uart.c
│   │       │   │   └── utils.S
│   │       │   └── start.sh
│   │       ├── evopen/
│   │       │   ├── .gitignore
│   │       │   ├── Makefile
│   │       │   ├── build.sh
│   │       │   ├── config.txt
│   │       │   ├── include/
│   │       │   │   ├── mm.h
│   │       │   │   ├── peripherals/
│   │       │   │   │   ├── base.h
│   │       │   │   │   ├── gpio.h
│   │       │   │   │   ├── mini_uart.h
│   │       │   │   │   └── uart.h
│   │       │   │   ├── uart.h
│   │       │   │   └── utils.h
│   │       │   ├── src/
│   │       │   │   ├── boot.S
│   │       │   │   ├── kernel.c
│   │       │   │   ├── linker-qemu.ld
│   │       │   │   ├── linker.ld
│   │       │   │   ├── mm.S
│   │       │   │   ├── uart.c
│   │       │   │   └── utils.S
│   │       │   └── start.sh
│   │       ├── rs/
│   │       │   ├── Makefile
│   │       │   ├── build.bat
│   │       │   ├── build.sh
│   │       │   ├── include/
│   │       │   │   ├── mini_uart.h
│   │       │   │   ├── mm.h
│   │       │   │   ├── peripherals/
│   │       │   │   │   ├── base.h
│   │       │   │   │   ├── gpio.h
│   │       │   │   │   └── mini_uart.h
│   │       │   │   └── utils.h
│   │       │   ├── src/
│   │       │   │   ├── boot.S
│   │       │   │   ├── config.txt
│   │       │   │   ├── kernel.c
│   │       │   │   ├── linker.ld
│   │       │   │   ├── mini_uart.c
│   │       │   │   ├── mm.S
│   │       │   │   └── utils.S
│   │       │   └── start.sh
│   │       └── stefanji/
│   │           └── run_on_qemu.sh
│   ├── lesson02/
│   │   ├── 1/
│   │   │   ├── H-4ND-H/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       ├── printf.c
│   │   │   │       └── utils.S
│   │   │   ├── avenito/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       ├── printf.c
│   │   │   │       └── utils.S
│   │   │   ├── bl4ckout31/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   └── utils.h
│   │   │   │   ├── src/
│   │   │   │   │   ├── boot.S
│   │   │   │   │   ├── config.txt
│   │   │   │   │   ├── kernel.c
│   │   │   │   │   ├── linker.ld
│   │   │   │   │   ├── mini_uart.c
│   │   │   │   │   ├── mm.S
│   │   │   │   │   ├── printf.c
│   │   │   │   │   └── utils.S
│   │   │   │   └── start.sh
│   │   │   ├── evopen/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── config.txt
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   └── utils.h
│   │   │   │   ├── src/
│   │   │   │   │   ├── boot.S
│   │   │   │   │   ├── config.txt
│   │   │   │   │   ├── kernel.c
│   │   │   │   │   ├── linker.ld
│   │   │   │   │   ├── mini_uart.c
│   │   │   │   │   ├── mm.S
│   │   │   │   │   ├── printf.c
│   │   │   │   │   └── utils.S
│   │   │   │   └── start.sh
│   │   │   ├── gcrisis/
│   │   │   │   ├── Makefile
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       ├── printf.c
│   │   │   │       └── utils.S
│   │   │   ├── rs/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       ├── printf.c
│   │   │   │       └── utils.S
│   │   │   └── zjd0112/
│   │   │       ├── Makefile
│   │   │       ├── build.bat
│   │   │       ├── build.sh
│   │   │       ├── include/
│   │   │       │   ├── arm/
│   │   │       │   │   └── sysregs.h
│   │   │       │   ├── mini_uart.h
│   │   │       │   ├── mm.h
│   │   │       │   ├── peripherals/
│   │   │       │   │   ├── base.h
│   │   │       │   │   ├── gpio.h
│   │   │       │   │   └── mini_uart.h
│   │   │       │   ├── printf.h
│   │   │       │   └── utils.h
│   │   │       └── src/
│   │   │           ├── boot.S
│   │   │           ├── config.txt
│   │   │           ├── kernel.c
│   │   │           ├── linker.ld
│   │   │           ├── mini_uart.c
│   │   │           ├── mm.S
│   │   │           ├── printf.c
│   │   │           └── utils.S
│   │   ├── 2/
│   │   │   ├── H-4ND-H/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       ├── printf.c
│   │   │   │       └── utils.S
│   │   │   ├── avenito/
│   │   │   │   ├── Makefile
│   │   │   │   ├── README.md
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── dis_with.txt
│   │   │   │   ├── dis_without.txt
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       ├── printf.c
│   │   │   │       └── utils.S
│   │   │   ├── bl4ckout31/
│   │   │   │   ├── Makefile
│   │   │   │   ├── avec
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   └── utils.h
│   │   │   │   ├── sans
│   │   │   │   ├── src/
│   │   │   │   │   ├── boot.S
│   │   │   │   │   ├── config.txt
│   │   │   │   │   ├── kernel.c
│   │   │   │   │   ├── linker.ld
│   │   │   │   │   ├── mini_uart.c
│   │   │   │   │   ├── mm.S
│   │   │   │   │   ├── printf.c
│   │   │   │   │   └── utils.S
│   │   │   │   └── start.sh
│   │   │   ├── evopen/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── config.txt
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   └── utils.h
│   │   │   │   ├── src/
│   │   │   │   │   ├── boot.S
│   │   │   │   │   ├── config.txt
│   │   │   │   │   ├── kernel.c
│   │   │   │   │   ├── linker.ld
│   │   │   │   │   ├── mini_uart.c
│   │   │   │   │   ├── mm.S
│   │   │   │   │   ├── printf.c
│   │   │   │   │   └── utils.S
│   │   │   │   └── start.sh
│   │   │   ├── gcrisis/
│   │   │   │   ├── Makefile
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       ├── printf.c
│   │   │   │       └── utils.S
│   │   │   ├── rs/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       ├── printf.c
│   │   │   │       └── utils.S
│   │   │   ├── szediwy/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── custom_printf.h
│   │   │   │   │   ├── entry.h
│   │   │   │   │   ├── irq.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   ├── irq.h
│   │   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   │   └── timer.h
│   │   │   │   │   ├── sysregs.h
│   │   │   │   │   ├── timer.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── custom_printf.c
│   │   │   │       ├── entry.S
│   │   │   │       ├── irq.S
│   │   │   │       ├── irq.c
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       ├── timer.c
│   │   │   │       └── utils.S
│   │   │   └── zjd0112/
│   │   │       ├── Makefile
│   │   │       ├── build.bat
│   │   │       ├── build.sh
│   │   │       ├── include/
│   │   │       │   ├── arm/
│   │   │       │   │   └── sysregs.h
│   │   │       │   ├── mini_uart.h
│   │   │       │   ├── mm.h
│   │   │       │   ├── peripherals/
│   │   │       │   │   ├── base.h
│   │   │       │   │   ├── gpio.h
│   │   │       │   │   └── mini_uart.h
│   │   │       │   ├── printf.h
│   │   │       │   └── utils.h
│   │   │       ├── src/
│   │   │       │   ├── boot.S
│   │   │       │   ├── config.txt
│   │   │       │   ├── kernel.c
│   │   │       │   ├── linker.ld
│   │   │       │   ├── mini_uart.c
│   │   │       │   ├── mm.S
│   │   │       │   ├── printf.c
│   │   │       │   └── utils.S
│   │   │       ├── test1.txt
│   │   │       └── test2.txt
│   │   └── 3/
│   │       ├── H-4ND-H/
│   │       │   ├── Makefile
│   │       │   ├── build.bat
│   │       │   ├── build.sh
│   │       │   ├── include/
│   │       │   │   ├── arm/
│   │       │   │   │   └── sysregs.h
│   │       │   │   ├── mini_uart.h
│   │       │   │   ├── mm.h
│   │       │   │   ├── peripherals/
│   │       │   │   │   ├── base.h
│   │       │   │   │   ├── gpio.h
│   │       │   │   │   └── mini_uart.h
│   │       │   │   ├── printf.h
│   │       │   │   └── utils.h
│   │       │   └── src/
│   │       │       ├── boot.S
│   │       │       ├── config.txt
│   │       │       ├── kernel.c
│   │       │       ├── linker.ld
│   │       │       ├── mini_uart.c
│   │       │       ├── mm.S
│   │       │       ├── printf.c
│   │       │       └── utils.S
│   │       ├── avenito/
│   │       │   ├── Makefile
│   │       │   ├── README.md
│   │       │   ├── build.bat
│   │       │   ├── build.sh
│   │       │   ├── include/
│   │       │   │   ├── arm/
│   │       │   │   │   └── sysregs.h
│   │       │   │   ├── mm.h
│   │       │   │   ├── peripherals/
│   │       │   │   │   ├── base.h
│   │       │   │   │   ├── gpio.h
│   │       │   │   │   └── uart.h
│   │       │   │   ├── printf.h
│   │       │   │   ├── uart.h
│   │       │   │   └── utils.h
│   │       │   └── src/
│   │       │       ├── boot.S
│   │       │       ├── config.txt
│   │       │       ├── kernel.c
│   │       │       ├── linker.ld
│   │       │       ├── mm.S
│   │       │       ├── printf.c
│   │       │       ├── uart.c
│   │       │       └── utils.S
│   │       ├── bl4ckout31/
│   │       │   ├── Makefile
│   │       │   ├── build.bat
│   │       │   ├── build.sh
│   │       │   ├── include/
│   │       │   │   ├── arm/
│   │       │   │   │   └── sysregs.h
│   │       │   │   ├── mini_uart.h
│   │       │   │   ├── mm.h
│   │       │   │   ├── peripherals/
│   │       │   │   │   ├── base.h
│   │       │   │   │   ├── gpio.h
│   │       │   │   │   └── mini_uart.h
│   │       │   │   ├── printf.h
│   │       │   │   └── utils.h
│   │       │   ├── src/
│   │       │   │   ├── boot.S
│   │       │   │   ├── config.txt
│   │       │   │   ├── kernel.c
│   │       │   │   ├── linker.ld
│   │       │   │   ├── mini_uart.c
│   │       │   │   ├── mm.S
│   │       │   │   ├── printf.c
│   │       │   │   └── utils.S
│   │       │   └── start.sh
│   │       ├── evopen/
│   │       │   ├── Makefile
│   │       │   ├── build.sh
│   │       │   ├── config.txt
│   │       │   ├── include/
│   │       │   │   ├── arm/
│   │       │   │   │   └── sysregs.h
│   │       │   │   ├── mm.h
│   │       │   │   ├── peripherals/
│   │       │   │   │   ├── base.h
│   │       │   │   │   ├── gpio.h
│   │       │   │   │   ├── mini_uart.h
│   │       │   │   │   └── uart.h
│   │       │   │   ├── printf.h
│   │       │   │   ├── uart.h
│   │       │   │   └── utils.h
│   │       │   ├── src/
│   │       │   │   ├── boot.S
│   │       │   │   ├── kernel.c
│   │       │   │   ├── linker-qemu.ld
│   │       │   │   ├── linker.ld
│   │       │   │   ├── mm.S
│   │       │   │   ├── printf.c
│   │       │   │   ├── uart.c
│   │       │   │   └── utils.S
│   │       │   └── start.sh
│   │       └── rs/
│   │           ├── Makefile
│   │           ├── build.bat
│   │           ├── build.sh
│   │           ├── include/
│   │           │   ├── arm/
│   │           │   │   └── sysregs.h
│   │           │   ├── mini_uart.h
│   │           │   ├── mm.h
│   │           │   ├── peripherals/
│   │           │   │   ├── base.h
│   │           │   │   ├── gpio.h
│   │           │   │   └── mini_uart.h
│   │           │   ├── printf.h
│   │           │   └── utils.h
│   │           ├── src/
│   │           │   ├── boot.S
│   │           │   ├── config.txt
│   │           │   ├── kernel.c
│   │           │   ├── linker.ld
│   │           │   ├── mini_uart.c
│   │           │   ├── mm.S
│   │           │   ├── printf.c
│   │           │   └── utils.S
│   │           └── start.sh
│   ├── lesson03/
│   │   ├── 1/
│   │   │   ├── H-4ND-H/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── entry.h
│   │   │   │   │   ├── irq.h
│   │   │   │   │   ├── local_timer.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   ├── irq.h
│   │   │   │   │   │   ├── local_timer.h
│   │   │   │   │   │   └── mini_uart.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── entry.S
│   │   │   │       ├── irq.S
│   │   │   │       ├── irq.c
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── local_timer.c
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       ├── printf.c
│   │   │   │       └── utils.S
│   │   │   ├── avenito/
│   │   │   │   ├── Makefile
│   │   │   │   ├── README.md
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── entry.h
│   │   │   │   │   ├── irq.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   ├── irq.h
│   │   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   │   └── timer.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   ├── timer.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── entry.S
│   │   │   │       ├── irq.S
│   │   │   │       ├── irq.c
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       ├── printf.c
│   │   │   │       ├── timer.c
│   │   │   │       └── utils.S
│   │   │   ├── bl4ckout31/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── entry.h
│   │   │   │   │   ├── irq.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   ├── irq.h
│   │   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   │   └── timer.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   ├── timer.h
│   │   │   │   │   └── utils.h
│   │   │   │   ├── src/
│   │   │   │   │   ├── boot.S
│   │   │   │   │   ├── config.txt
│   │   │   │   │   ├── entry.S
│   │   │   │   │   ├── irq.S
│   │   │   │   │   ├── irq.c
│   │   │   │   │   ├── kernel.c
│   │   │   │   │   ├── linker.ld
│   │   │   │   │   ├── mini_uart.c
│   │   │   │   │   ├── mm.S
│   │   │   │   │   ├── printf.c
│   │   │   │   │   ├── timer.c
│   │   │   │   │   └── utils.S
│   │   │   │   └── start.sh
│   │   │   ├── rs/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── entry.h
│   │   │   │   │   ├── irq.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   ├── irq.h
│   │   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   │   └── timer.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   ├── timer.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── entry.S
│   │   │   │       ├── irq.S
│   │   │   │       ├── irq.c
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       ├── printf.c
│   │   │   │       ├── timer.c
│   │   │   │       └── utils.S
│   │   │   ├── szediwy/
│   │   │   │   ├── Makefile
│   │   │   │   ├── README.md
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── custom_printf.h
│   │   │   │   │   ├── entry.h
│   │   │   │   │   ├── irq.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   ├── irq.h
│   │   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   │   └── timer.h
│   │   │   │   │   ├── sysregs.h
│   │   │   │   │   ├── timer.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── custom_printf.c
│   │   │   │       ├── debug.c
│   │   │   │       ├── entry.S
│   │   │   │       ├── irq.S
│   │   │   │       ├── irq.c
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       ├── timer.c
│   │   │   │       └── utils.S
│   │   │   └── xdfm1/
│   │   │       ├── Makefile
│   │   │       ├── build.bat
│   │   │       ├── build.sh
│   │   │       ├── include/
│   │   │       │   ├── arm/
│   │   │       │   │   └── sysregs.h
│   │   │       │   ├── arm_timer.h
│   │   │       │   ├── entry.h
│   │   │       │   ├── irq.h
│   │   │       │   ├── mini_uart.h
│   │   │       │   ├── mm.h
│   │   │       │   ├── peripherals/
│   │   │       │   │   ├── arm_timer.h
│   │   │       │   │   ├── base.h
│   │   │       │   │   ├── gpio.h
│   │   │       │   │   ├── irq.h
│   │   │       │   │   ├── mini_uart.h
│   │   │       │   │   └── timer.h
│   │   │       │   ├── printf.h
│   │   │       │   └── utils.h
│   │   │       └── src/
│   │   │           ├── arm_timer.c
│   │   │           ├── boot.S
│   │   │           ├── config.txt
│   │   │           ├── entry.S
│   │   │           ├── irq.S
│   │   │           ├── irq.c
│   │   │           ├── kernel.c
│   │   │           ├── linker.ld
│   │   │           ├── mini_uart.c
│   │   │           ├── mm.S
│   │   │           ├── printf.c
│   │   │           └── utils.S
│   │   ├── 2/
│   │   │   ├── H-4ND-H/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── entry.h
│   │   │   │   │   ├── irq.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   ├── irq.h
│   │   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   │   └── timer.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   ├── timer.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── entry.S
│   │   │   │       ├── irq.S
│   │   │   │       ├── irq.c
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       ├── printf.c
│   │   │   │       ├── timer.c
│   │   │   │       └── utils.S
│   │   │   ├── avenito/
│   │   │   │   ├── Makefile
│   │   │   │   ├── README.md
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── entry.h
│   │   │   │   │   ├── irq.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   ├── irq.h
│   │   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   │   └── timer.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   ├── timer.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── entry.S
│   │   │   │       ├── irq.S
│   │   │   │       ├── irq.c
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       ├── printf.c
│   │   │   │       ├── timer.c
│   │   │   │       └── utils.S
│   │   │   ├── bl4ckout31/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── entry.h
│   │   │   │   │   ├── irq.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   ├── irq.h
│   │   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   │   └── timer.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   ├── timer.h
│   │   │   │   │   └── utils.h
│   │   │   │   ├── src/
│   │   │   │   │   ├── boot.S
│   │   │   │   │   ├── config.txt
│   │   │   │   │   ├── entry.S
│   │   │   │   │   ├── irq.S
│   │   │   │   │   ├── irq.c
│   │   │   │   │   ├── kernel.c
│   │   │   │   │   ├── linker.ld
│   │   │   │   │   ├── mini_uart.c
│   │   │   │   │   ├── mm.S
│   │   │   │   │   ├── printf.c
│   │   │   │   │   ├── timer.c
│   │   │   │   │   └── utils.S
│   │   │   │   └── start.sh
│   │   │   ├── rs/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── entry.h
│   │   │   │   │   ├── irq.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   ├── irq.h
│   │   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   │   └── timer.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   ├── timer.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── entry.S
│   │   │   │       ├── irq.S
│   │   │   │       ├── irq.c
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       ├── printf.c
│   │   │   │       ├── timer.c
│   │   │   │       └── utils.S
│   │   │   └── szediwy/
│   │   │       ├── Makefile
│   │   │       ├── README.md
│   │   │       ├── build.bat
│   │   │       ├── build.sh
│   │   │       ├── include/
│   │   │       │   ├── custom_printf.h
│   │   │       │   ├── entry.h
│   │   │       │   ├── irq.h
│   │   │       │   ├── mini_uart.h
│   │   │       │   ├── mm.h
│   │   │       │   ├── peripherals/
│   │   │       │   │   ├── base.h
│   │   │       │   │   ├── gpio.h
│   │   │       │   │   ├── irq.h
│   │   │       │   │   ├── mini_uart.h
│   │   │       │   │   └── timer.h
│   │   │       │   ├── sysregs.h
│   │   │       │   ├── timer.h
│   │   │       │   └── utils.h
│   │   │       └── src/
│   │   │           ├── boot.S
│   │   │           ├── config.txt
│   │   │           ├── custom_printf.c
│   │   │           ├── debug.c
│   │   │           ├── entry.S
│   │   │           ├── irq.S
│   │   │           ├── irq.c
│   │   │           ├── kernel.c
│   │   │           ├── linker.ld
│   │   │           ├── mini_uart.c
│   │   │           ├── mm.S
│   │   │           ├── timer.c
│   │   │           └── utils.S
│   │   └── 3/
│   │       ├── H-4ND-H/
│   │       │   ├── Makefile
│   │       │   ├── build.bat
│   │       │   ├── build.sh
│   │       │   ├── include/
│   │       │   │   ├── arm/
│   │       │   │   │   └── sysregs.h
│   │       │   │   ├── entry.h
│   │       │   │   ├── irq.h
│   │       │   │   ├── mini_uart.h
│   │       │   │   ├── mm.h
│   │       │   │   ├── peripherals/
│   │       │   │   │   ├── base.h
│   │       │   │   │   ├── gpio.h
│   │       │   │   │   ├── irq.h
│   │       │   │   │   ├── mini_uart.h
│   │       │   │   │   └── timer.h
│   │       │   │   ├── printf.h
│   │       │   │   ├── timer.h
│   │       │   │   └── utils.h
│   │       │   └── src/
│   │       │       ├── boot.S
│   │       │       ├── config.txt
│   │       │       ├── entry.S
│   │       │       ├── irq.S
│   │       │       ├── irq.c
│   │       │       ├── kernel.c
│   │       │       ├── linker.ld
│   │       │       ├── mini_uart.c
│   │       │       ├── mm.S
│   │       │       ├── printf.c
│   │       │       ├── timer.c
│   │       │       └── utils.S
│   │       ├── avenito/
│   │       │   ├── Makefile
│   │       │   ├── build.bat
│   │       │   ├── build.sh
│   │       │   ├── include/
│   │       │   │   ├── arm/
│   │       │   │   │   └── sysregs.h
│   │       │   │   ├── entry.h
│   │       │   │   ├── irq.h
│   │       │   │   ├── mm.h
│   │       │   │   ├── peripherals/
│   │       │   │   │   ├── base.h
│   │       │   │   │   ├── gpio.h
│   │       │   │   │   ├── irq.h
│   │       │   │   │   ├── timer.h
│   │       │   │   │   └── uart.h
│   │       │   │   ├── printf.h
│   │       │   │   ├── timer.h
│   │       │   │   ├── uart.h
│   │       │   │   └── utils.h
│   │       │   └── src/
│   │       │       ├── boot.S
│   │       │       ├── config.txt
│   │       │       ├── entry.S
│   │       │       ├── irq.S
│   │       │       ├── irq.c
│   │       │       ├── kernel.c
│   │       │       ├── linker.ld
│   │       │       ├── mm.S
│   │       │       ├── printf.c
│   │       │       ├── timer.c
│   │       │       ├── uart.c
│   │       │       └── utils.S
│   │       ├── bl4ckout31/
│   │       │   ├── Makefile
│   │       │   ├── build.bat
│   │       │   ├── build.sh
│   │       │   ├── include/
│   │       │   │   ├── arm/
│   │       │   │   │   └── sysregs.h
│   │       │   │   ├── entry.h
│   │       │   │   ├── irq.h
│   │       │   │   ├── mini_uart.h
│   │       │   │   ├── mm.h
│   │       │   │   ├── peripherals/
│   │       │   │   │   ├── base.h
│   │       │   │   │   ├── gpio.h
│   │       │   │   │   ├── irq.h
│   │       │   │   │   ├── mini_uart.h
│   │       │   │   │   └── timer.h
│   │       │   │   ├── printf.h
│   │       │   │   ├── timer.h
│   │       │   │   └── utils.h
│   │       │   ├── src/
│   │       │   │   ├── boot.S
│   │       │   │   ├── config.txt
│   │       │   │   ├── entry.S
│   │       │   │   ├── irq.S
│   │       │   │   ├── irq.c
│   │       │   │   ├── kernel.c
│   │       │   │   ├── linker.ld
│   │       │   │   ├── mini_uart.c
│   │       │   │   ├── mm.S
│   │       │   │   ├── printf.c
│   │       │   │   ├── timer.S
│   │       │   │   ├── timer.c
│   │       │   │   └── utils.S
│   │       │   └── start.sh
│   │       └── rs/
│   │           ├── Makefile
│   │           ├── build.bat
│   │           ├── build.sh
│   │           ├── include/
│   │           │   ├── arm/
│   │           │   │   └── sysregs.h
│   │           │   ├── entry.h
│   │           │   ├── irq.h
│   │           │   ├── mini_uart.h
│   │           │   ├── mm.h
│   │           │   ├── peripherals/
│   │           │   │   ├── base.h
│   │           │   │   ├── gpio.h
│   │           │   │   ├── irq.h
│   │           │   │   ├── mini_uart.h
│   │           │   │   └── timer.h
│   │           │   ├── printf.h
│   │           │   ├── timer.h
│   │           │   └── utils.h
│   │           ├── src/
│   │           │   ├── boot.S
│   │           │   ├── config.txt
│   │           │   ├── entry.S
│   │           │   ├── irq.S
│   │           │   ├── irq.c
│   │           │   ├── kernel.c
│   │           │   ├── linker.ld
│   │           │   ├── mini_uart.c
│   │           │   ├── mm.S
│   │           │   ├── printf.c
│   │           │   ├── timer.c
│   │           │   └── utils.S
│   │           └── start.sh
│   ├── lesson04/
│   │   ├── 1/
│   │   │   ├── avenito/
│   │   │   │   ├── Makefile
│   │   │   │   ├── README.md
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── entry.h
│   │   │   │   │   ├── fork.h
│   │   │   │   │   ├── irq.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   ├── irq.h
│   │   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   │   ├── timer.h
│   │   │   │   │   │   └── uart.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   ├── sched.h
│   │   │   │   │   ├── timer.h
│   │   │   │   │   └── utils.h
│   │   │   │   ├── saida.txt
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── entry.S
│   │   │   │       ├── fork.c
│   │   │   │       ├── irq.S
│   │   │   │       ├── irq.c
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       ├── mm.c
│   │   │   │       ├── printf.c
│   │   │   │       ├── sched.S
│   │   │   │       ├── sched.c
│   │   │   │       ├── timer.c
│   │   │   │       └── utils.S
│   │   │   ├── bl4ckout31/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── entry.h
│   │   │   │   │   ├── fork.h
│   │   │   │   │   ├── irq.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   ├── irq.h
│   │   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   │   └── timer.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   ├── sched.h
│   │   │   │   │   ├── timer.h
│   │   │   │   │   └── utils.h
│   │   │   │   ├── src/
│   │   │   │   │   ├── boot.S
│   │   │   │   │   ├── config.txt
│   │   │   │   │   ├── entry.S
│   │   │   │   │   ├── fork.c
│   │   │   │   │   ├── irq.S
│   │   │   │   │   ├── irq.c
│   │   │   │   │   ├── kernel.c
│   │   │   │   │   ├── linker.ld
│   │   │   │   │   ├── mini_uart.c
│   │   │   │   │   ├── mm.S
│   │   │   │   │   ├── mm.c
│   │   │   │   │   ├── printf.c
│   │   │   │   │   ├── sched.S
│   │   │   │   │   ├── sched.c
│   │   │   │   │   ├── timer.c
│   │   │   │   │   └── utils.S
│   │   │   │   └── start.sh
│   │   │   └── rs/
│   │   │       ├── Makefile
│   │   │       ├── build.bat
│   │   │       ├── build.sh
│   │   │       ├── include/
│   │   │       │   ├── arm/
│   │   │       │   │   └── sysregs.h
│   │   │       │   ├── entry.h
│   │   │       │   ├── fork.h
│   │   │       │   ├── irq.h
│   │   │       │   ├── mini_uart.h
│   │   │       │   ├── mm.h
│   │   │       │   ├── peripherals/
│   │   │       │   │   ├── base.h
│   │   │       │   │   ├── gpio.h
│   │   │       │   │   ├── irq.h
│   │   │       │   │   ├── mini_uart.h
│   │   │       │   │   └── timer.h
│   │   │       │   ├── printf.h
│   │   │       │   ├── sched.h
│   │   │       │   ├── timer.h
│   │   │       │   └── utils.h
│   │   │       ├── output.txt
│   │   │       └── src/
│   │   │           ├── boot.S
│   │   │           ├── config.txt
│   │   │           ├── entry.S
│   │   │           ├── fork.c
│   │   │           ├── irq.S
│   │   │           ├── irq.c
│   │   │           ├── kernel.c
│   │   │           ├── linker.ld
│   │   │           ├── mini_uart.c
│   │   │           ├── mm.S
│   │   │           ├── mm.c
│   │   │           ├── printf.c
│   │   │           ├── sched.S
│   │   │           ├── sched.c
│   │   │           ├── timer.c
│   │   │           └── utils.S
│   │   ├── 2/
│   │   │   ├── avenito/
│   │   │   │   ├── Makefile
│   │   │   │   ├── README.md
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── entry.h
│   │   │   │   │   ├── fork.h
│   │   │   │   │   ├── irq.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   ├── irq.h
│   │   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   │   └── timer.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   ├── sched.h
│   │   │   │   │   ├── timer.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── entry.S
│   │   │   │       ├── fork.c
│   │   │   │       ├── irq.S
│   │   │   │       ├── irq.c
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       ├── mm.c
│   │   │   │       ├── printf.c
│   │   │   │       ├── sched.S
│   │   │   │       ├── sched.c
│   │   │   │       ├── timer.c
│   │   │   │       └── utils.S
│   │   │   ├── bl4ckout31/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── entry.h
│   │   │   │   │   ├── fork.h
│   │   │   │   │   ├── irq.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   ├── irq.h
│   │   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   │   └── timer.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   ├── sched.h
│   │   │   │   │   ├── timer.h
│   │   │   │   │   └── utils.h
│   │   │   │   ├── src/
│   │   │   │   │   ├── boot.S
│   │   │   │   │   ├── config.txt
│   │   │   │   │   ├── entry.S
│   │   │   │   │   ├── fork.c
│   │   │   │   │   ├── irq.S
│   │   │   │   │   ├── irq.c
│   │   │   │   │   ├── kernel.c
│   │   │   │   │   ├── linker.ld
│   │   │   │   │   ├── mini_uart.c
│   │   │   │   │   ├── mm.S
│   │   │   │   │   ├── mm.c
│   │   │   │   │   ├── printf.c
│   │   │   │   │   ├── sched.S
│   │   │   │   │   ├── sched.c
│   │   │   │   │   ├── timer.c
│   │   │   │   │   └── utils.S
│   │   │   │   └── start.sh
│   │   │   └── rs/
│   │   │       ├── Makefile
│   │   │       ├── build.bat
│   │   │       ├── build.sh
│   │   │       ├── include/
│   │   │       │   ├── arm/
│   │   │       │   │   └── sysregs.h
│   │   │       │   ├── entry.h
│   │   │       │   ├── fork.h
│   │   │       │   ├── irq.h
│   │   │       │   ├── mini_uart.h
│   │   │       │   ├── mm.h
│   │   │       │   ├── peripherals/
│   │   │       │   │   ├── base.h
│   │   │       │   │   ├── gpio.h
│   │   │       │   │   ├── irq.h
│   │   │       │   │   ├── mini_uart.h
│   │   │       │   │   └── timer.h
│   │   │       │   ├── printf.h
│   │   │       │   ├── sched.h
│   │   │       │   ├── timer.h
│   │   │       │   └── utils.h
│   │   │       ├── output.txt
│   │   │       └── src/
│   │   │           ├── boot.S
│   │   │           ├── config.txt
│   │   │           ├── entry.S
│   │   │           ├── fork.c
│   │   │           ├── irq.S
│   │   │           ├── irq.c
│   │   │           ├── kernel.c
│   │   │           ├── linker.ld
│   │   │           ├── mini_uart.c
│   │   │           ├── mm.S
│   │   │           ├── mm.c
│   │   │           ├── printf.c
│   │   │           ├── sched.S
│   │   │           ├── sched.c
│   │   │           ├── timer.c
│   │   │           └── utils.S
│   │   ├── 3/
│   │   │   ├── avenito/
│   │   │   │   ├── Makefile
│   │   │   │   ├── README.md
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── file.txt
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── entry.h
│   │   │   │   │   ├── fork.h
│   │   │   │   │   ├── irq.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   ├── irq.h
│   │   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   │   └── timer.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   ├── sched.h
│   │   │   │   │   ├── timer.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── entry.S
│   │   │   │       ├── fork.c
│   │   │   │       ├── irq.S
│   │   │   │       ├── irq.c
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       ├── mm.c
│   │   │   │       ├── printf.c
│   │   │   │       ├── sched.S
│   │   │   │       ├── sched.c
│   │   │   │       ├── timer.c
│   │   │   │       └── utils.S
│   │   │   └── bl4ckout31/
│   │   │       ├── Makefile
│   │   │       ├── build.bat
│   │   │       ├── build.sh
│   │   │       ├── include/
│   │   │       │   ├── arm/
│   │   │       │   │   └── sysregs.h
│   │   │       │   ├── entry.h
│   │   │       │   ├── fork.h
│   │   │       │   ├── irq.h
│   │   │       │   ├── mini_uart.h
│   │   │       │   ├── mm.h
│   │   │       │   ├── peripherals/
│   │   │       │   │   ├── base.h
│   │   │       │   │   ├── gpio.h
│   │   │       │   │   ├── irq.h
│   │   │       │   │   ├── mini_uart.h
│   │   │       │   │   └── timer.h
│   │   │       │   ├── printf.h
│   │   │       │   ├── sched.h
│   │   │       │   ├── timer.h
│   │   │       │   └── utils.h
│   │   │       ├── src/
│   │   │       │   ├── boot.S
│   │   │       │   ├── config.txt
│   │   │       │   ├── entry.S
│   │   │       │   ├── fork.c
│   │   │       │   ├── irq.S
│   │   │       │   ├── irq.c
│   │   │       │   ├── kernel.c
│   │   │       │   ├── linker.ld
│   │   │       │   ├── mini_uart.c
│   │   │       │   ├── mm.S
│   │   │       │   ├── mm.c
│   │   │       │   ├── printf.c
│   │   │       │   ├── sched.S
│   │   │       │   ├── sched.c
│   │   │       │   ├── timer.c
│   │   │       │   └── utils.S
│   │   │       └── start.sh
│   │   ├── 4/
│   │   │   ├── avenito/
│   │   │   │   ├── Makefile
│   │   │   │   ├── README.md
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── entry.h
│   │   │   │   │   ├── fork.h
│   │   │   │   │   ├── irq.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   ├── irq.h
│   │   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   │   └── timer.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   ├── sched.h
│   │   │   │   │   ├── timer.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── entry.S
│   │   │   │       ├── fork.c
│   │   │   │       ├── irq.S
│   │   │   │       ├── irq.c
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       ├── mm.c
│   │   │   │       ├── printf.c
│   │   │   │       ├── sched.S
│   │   │   │       ├── sched.c
│   │   │   │       ├── timer.c
│   │   │   │       └── utils.S
│   │   │   ├── bl4ckout31/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── entry.h
│   │   │   │   │   ├── fork.h
│   │   │   │   │   ├── irq.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   ├── irq.h
│   │   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   │   └── timer.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   ├── sched.h
│   │   │   │   │   ├── timer.h
│   │   │   │   │   └── utils.h
│   │   │   │   ├── src/
│   │   │   │   │   ├── boot.S
│   │   │   │   │   ├── config.txt
│   │   │   │   │   ├── entry.S
│   │   │   │   │   ├── fork.c
│   │   │   │   │   ├── irq.S
│   │   │   │   │   ├── irq.c
│   │   │   │   │   ├── kernel.c
│   │   │   │   │   ├── linker.ld
│   │   │   │   │   ├── mini_uart.c
│   │   │   │   │   ├── mm.S
│   │   │   │   │   ├── mm.c
│   │   │   │   │   ├── printf.c
│   │   │   │   │   ├── sched.S
│   │   │   │   │   ├── sched.c
│   │   │   │   │   ├── timer.c
│   │   │   │   │   └── utils.S
│   │   │   │   └── start.sh
│   │   │   └── rs/
│   │   │       ├── Makefile
│   │   │       ├── build.bat
│   │   │       ├── build.sh
│   │   │       ├── include/
│   │   │       │   ├── arm/
│   │   │       │   │   └── sysregs.h
│   │   │       │   ├── entry.h
│   │   │       │   ├── fork.h
│   │   │       │   ├── irq.h
│   │   │       │   ├── mini_uart.h
│   │   │       │   ├── mm.h
│   │   │       │   ├── peripherals/
│   │   │       │   │   ├── base.h
│   │   │       │   │   ├── gpio.h
│   │   │       │   │   ├── irq.h
│   │   │       │   │   ├── mini_uart.h
│   │   │       │   │   └── timer.h
│   │   │       │   ├── printf.h
│   │   │       │   ├── sched.h
│   │   │       │   ├── timer.h
│   │   │       │   └── utils.h
│   │   │       ├── output.txt
│   │   │       └── src/
│   │   │           ├── boot.S
│   │   │           ├── config.txt
│   │   │           ├── entry.S
│   │   │           ├── fork.c
│   │   │           ├── irq.S
│   │   │           ├── irq.c
│   │   │           ├── kernel.c
│   │   │           ├── linker.ld
│   │   │           ├── mini_uart.c
│   │   │           ├── mm.S
│   │   │           ├── mm.c
│   │   │           ├── printf.c
│   │   │           ├── sched.S
│   │   │           ├── sched.c
│   │   │           ├── timer.c
│   │   │           └── utils.S
│   │   └── 5/
│   │       ├── avenito/
│   │       │   ├── Makefile
│   │       │   ├── README.md
│   │       │   ├── build.bat
│   │       │   ├── build.sh
│   │       │   ├── include/
│   │       │   │   ├── arm/
│   │       │   │   │   └── sysregs.h
│   │       │   │   ├── entry.h
│   │       │   │   ├── fork.h
│   │       │   │   ├── irq.h
│   │       │   │   ├── mm.h
│   │       │   │   ├── peripherals/
│   │       │   │   │   ├── base.h
│   │       │   │   │   ├── gpio.h
│   │       │   │   │   ├── irq.h
│   │       │   │   │   ├── timer.h
│   │       │   │   │   └── uart.h
│   │       │   │   ├── printf.h
│   │       │   │   ├── sched.h
│   │       │   │   ├── timer.h
│   │       │   │   ├── uart.h
│   │       │   │   └── utils.h
│   │       │   ├── saida.txt
│   │       │   └── src/
│   │       │       ├── boot.S
│   │       │       ├── config.txt
│   │       │       ├── entry.S
│   │       │       ├── fork.c
│   │       │       ├── irq.S
│   │       │       ├── irq.c
│   │       │       ├── kernel.c
│   │       │       ├── linker.ld
│   │       │       ├── mm.S
│   │       │       ├── mm.c
│   │       │       ├── printf.c
│   │       │       ├── sched.S
│   │       │       ├── sched.c
│   │       │       ├── timer.c
│   │       │       ├── uart.c
│   │       │       └── utils.S
│   │       └── bl4ckout31/
│   │           ├── Makefile
│   │           ├── build.bat
│   │           ├── build.sh
│   │           ├── include/
│   │           │   ├── arm/
│   │           │   │   └── sysregs.h
│   │           │   ├── entry.h
│   │           │   ├── fork.h
│   │           │   ├── irq.h
│   │           │   ├── mini_uart.h
│   │           │   ├── mm.h
│   │           │   ├── peripherals/
│   │           │   │   ├── base.h
│   │           │   │   ├── gpio.h
│   │           │   │   ├── irq.h
│   │           │   │   ├── mini_uart.h
│   │           │   │   └── timer.h
│   │           │   ├── printf.h
│   │           │   ├── sched.h
│   │           │   ├── timer.h
│   │           │   └── utils.h
│   │           ├── src/
│   │           │   ├── boot.S
│   │           │   ├── config.txt
│   │           │   ├── entry.S
│   │           │   ├── fork.c
│   │           │   ├── irq.S
│   │           │   ├── irq.c
│   │           │   ├── kernel.c
│   │           │   ├── linker.ld
│   │           │   ├── mini_uart.c
│   │           │   ├── mm.S
│   │           │   ├── mm.c
│   │           │   ├── printf.c
│   │           │   ├── sched.S
│   │           │   ├── sched.c
│   │           │   ├── timer.S
│   │           │   ├── timer.c
│   │           │   └── utils.S
│   │           └── start.sh
│   ├── lesson05/
│   │   ├── 1/
│   │   │   ├── avenito/
│   │   │   │   ├── Makefile
│   │   │   │   ├── README.md
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── entry.h
│   │   │   │   │   ├── fork.h
│   │   │   │   │   ├── irq.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   ├── irq.h
│   │   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   │   └── timer.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   ├── sched.h
│   │   │   │   │   ├── sys.h
│   │   │   │   │   ├── timer.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── entry.S
│   │   │   │       ├── fork.c
│   │   │   │       ├── irq.S
│   │   │   │       ├── irq.c
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       ├── mm.c
│   │   │   │       ├── printf.c
│   │   │   │       ├── sched.S
│   │   │   │       ├── sched.c
│   │   │   │       ├── sys.S
│   │   │   │       ├── sys.c
│   │   │   │       ├── timer.c
│   │   │   │       └── utils.S
│   │   │   ├── bl4ckout31/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── entry.h
│   │   │   │   │   ├── fork.h
│   │   │   │   │   ├── irq.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   ├── irq.h
│   │   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   │   └── timer.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   ├── sched.h
│   │   │   │   │   ├── sys.h
│   │   │   │   │   ├── timer.h
│   │   │   │   │   └── utils.h
│   │   │   │   ├── src/
│   │   │   │   │   ├── boot.S
│   │   │   │   │   ├── config.txt
│   │   │   │   │   ├── entry.S
│   │   │   │   │   ├── fork.c
│   │   │   │   │   ├── irq.S
│   │   │   │   │   ├── irq.c
│   │   │   │   │   ├── kernel.c
│   │   │   │   │   ├── linker.ld
│   │   │   │   │   ├── mini_uart.c
│   │   │   │   │   ├── mm.S
│   │   │   │   │   ├── mm.c
│   │   │   │   │   ├── printf.c
│   │   │   │   │   ├── sched.S
│   │   │   │   │   ├── sched.c
│   │   │   │   │   ├── sys.S
│   │   │   │   │   ├── sys.c
│   │   │   │   │   ├── timer.c
│   │   │   │   │   └── utils.S
│   │   │   │   └── start.sh
│   │   │   └── xdfm1/
│   │   │       ├── Makefile
│   │   │       ├── build.bat
│   │   │       ├── build.sh
│   │   │       ├── include/
│   │   │       │   ├── arm/
│   │   │       │   │   └── sysregs.h
│   │   │       │   ├── entry.h
│   │   │       │   ├── fork.h
│   │   │       │   ├── irq.h
│   │   │       │   ├── mini_uart.h
│   │   │       │   ├── mm.h
│   │   │       │   ├── peripherals/
│   │   │       │   │   ├── base.h
│   │   │       │   │   ├── gpio.h
│   │   │       │   │   ├── irq.h
│   │   │       │   │   ├── mini_uart.h
│   │   │       │   │   └── timer.h
│   │   │       │   ├── printf.h
│   │   │       │   ├── sched.h
│   │   │       │   ├── sys.h
│   │   │       │   ├── timer.h
│   │   │       │   └── utils.h
│   │   │       └── src/
│   │   │           ├── boot.S
│   │   │           ├── config.txt
│   │   │           ├── entry.S
│   │   │           ├── fork.c
│   │   │           ├── irq.S
│   │   │           ├── irq.c
│   │   │           ├── kernel.c
│   │   │           ├── linker.ld
│   │   │           ├── mini_uart.c
│   │   │           ├── mm.S
│   │   │           ├── mm.c
│   │   │           ├── printf.c
│   │   │           ├── sched.S
│   │   │           ├── sched.c
│   │   │           ├── sys.S
│   │   │           ├── sys.c
│   │   │           ├── timer.c
│   │   │           └── utils.S
│   │   ├── 2/
│   │   │   ├── avenito/
│   │   │   │   ├── Makefile
│   │   │   │   ├── README.md
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── entry.h
│   │   │   │   │   ├── fork.h
│   │   │   │   │   ├── irq.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   ├── irq.h
│   │   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   │   └── timer.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   ├── sched.h
│   │   │   │   │   ├── sys.h
│   │   │   │   │   ├── timer.h
│   │   │   │   │   └── utils.h
│   │   │   │   └── src/
│   │   │   │       ├── boot.S
│   │   │   │       ├── config.txt
│   │   │   │       ├── entry.S
│   │   │   │       ├── fork.c
│   │   │   │       ├── irq.S
│   │   │   │       ├── irq.c
│   │   │   │       ├── kernel.c
│   │   │   │       ├── linker.ld
│   │   │   │       ├── mini_uart.c
│   │   │   │       ├── mm.S
│   │   │   │       ├── mm.c
│   │   │   │       ├── printf.c
│   │   │   │       ├── sched.S
│   │   │   │       ├── sched.c
│   │   │   │       ├── sys.S
│   │   │   │       ├── sys.c
│   │   │   │       ├── timer.c
│   │   │   │       └── utils.S
│   │   │   ├── bl4ckout31/
│   │   │   │   ├── Makefile
│   │   │   │   ├── build.bat
│   │   │   │   ├── build.sh
│   │   │   │   ├── include/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   └── sysregs.h
│   │   │   │   │   ├── entry.h
│   │   │   │   │   ├── fork.h
│   │   │   │   │   ├── irq.h
│   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   ├── mm.h
│   │   │   │   │   ├── peripherals/
│   │   │   │   │   │   ├── base.h
│   │   │   │   │   │   ├── gpio.h
│   │   │   │   │   │   ├── irq.h
│   │   │   │   │   │   ├── mini_uart.h
│   │   │   │   │   │   └── timer.h
│   │   │   │   │   ├── printf.h
│   │   │   │   │   ├── sched.h
│   │   │   │   │   ├── sys.h
│   │   │   │   │   ├── timer.h
│   │   │   │   │   └── utils.h
│   │   │   │   ├── src/
│   │   │   │   │   ├── boot.S
│   │   │   │   │   ├── config.txt
│   │   │   │   │   ├── entry.S
│   │   │   │   │   ├── fork.c
│   │   │   │   │   ├── irq.S
│   │   │   │   │   ├── irq.c
│   │   │   │   │   ├── kernel.c
│   │   │   │   │   ├── linker.ld
│   │   │   │   │   ├── mini_uart.c
│   │   │   │   │   ├── mm.S
│   │   │   │   │   ├── mm.c
│   │   │   │   │   ├── printf.c
│   │   │   │   │   ├── sched.S
│   │   │   │   │   ├── sched.c
│   │   │   │   │   ├── sys.S
│   │   │   │   │   ├── sys.c
│   │   │   │   │   ├── timer.c
│   │   │   │   │   └── utils.S
│   │   │   │   └── start.sh
│   │   │   └── xdfm1/
│   │   │       ├── Makefile
│   │   │       ├── build.bat
│   │   │       ├── build.sh
│   │   │       ├── include/
│   │   │       │   ├── arm/
│   │   │       │   │   └── sysregs.h
│   │   │       │   ├── entry.h
│   │   │       │   ├── fork.h
│   │   │       │   ├── irq.h
│   │   │       │   ├── mini_uart.h
│   │   │       │   ├── mm.h
│   │   │       │   ├── peripherals/
│   │   │       │   │   ├── base.h
│   │   │       │   │   ├── gpio.h
│   │   │       │   │   ├── irq.h
│   │   │       │   │   ├── mini_uart.h
│   │   │       │   │   └── timer.h
│   │   │       │   ├── printf.h
│   │   │       │   ├── sched.h
│   │   │       │   ├── sys.h
│   │   │       │   ├── timer.h
│   │   │       │   └── utils.h
│   │   │       └── src/
│   │   │           ├── boot.S
│   │   │           ├── config.txt
│   │   │           ├── entry.S
│   │   │           ├── fork.c
│   │   │           ├── irq.S
│   │   │           ├── irq.c
│   │   │           ├── kernel.c
│   │   │           ├── linker.ld
│   │   │           ├── mini_uart.c
│   │   │           ├── mm.S
│   │   │           ├── mm.c
│   │   │           ├── printf.c
│   │   │           ├── sched.S
│   │   │           ├── sched.c
│   │   │           ├── sys.S
│   │   │           ├── sys.c
│   │   │           ├── timer.c
│   │   │           └── utils.S
│   │   └── 3/
│   │       ├── avenito/
│   │       │   ├── Makefile
│   │       │   ├── README.md
│   │       │   ├── build.bat
│   │       │   ├── build.sh
│   │       │   ├── include/
│   │       │   │   ├── arm/
│   │       │   │   │   └── sysregs.h
│   │       │   │   ├── entry.h
│   │       │   │   ├── fork.h
│   │       │   │   ├── irq.h
│   │       │   │   ├── mini_uart.h
│   │       │   │   ├── mm.h
│   │       │   │   ├── peripherals/
│   │       │   │   │   ├── base.h
│   │       │   │   │   ├── gpio.h
│   │       │   │   │   ├── irq.h
│   │       │   │   │   ├── mini_uart.h
│   │       │   │   │   └── timer.h
│   │       │   │   ├── printf.h
│   │       │   │   ├── sched.h
│   │       │   │   ├── sys.h
│   │       │   │   ├── timer.h
│   │       │   │   └── utils.h
│   │       │   └── src/
│   │       │       ├── boot.S
│   │       │       ├── config.txt
│   │       │       ├── entry.S
│   │       │       ├── fork.c
│   │       │       ├── irq.S
│   │       │       ├── irq.c
│   │       │       ├── kernel.c
│   │       │       ├── linker.ld
│   │       │       ├── mini_uart.c
│   │       │       ├── mm.S
│   │       │       ├── mm.c
│   │       │       ├── printf.c
│   │       │       ├── sched.S
│   │       │       ├── sched.c
│   │       │       ├── sys.S
│   │       │       ├── sys.c
│   │       │       ├── timer.c
│   │       │       └── utils.S
│   │       └── bl4ckout31/
│   │           ├── Makefile
│   │           ├── build.bat
│   │           ├── build.sh
│   │           ├── include/
│   │           │   ├── arm/
│   │           │   │   └── sysregs.h
│   │           │   ├── entry.h
│   │           │   ├── fork.h
│   │           │   ├── irq.h
│   │           │   ├── mini_uart.h
│   │           │   ├── mm.h
│   │           │   ├── peripherals/
│   │           │   │   ├── base.h
│   │           │   │   ├── gpio.h
│   │           │   │   ├── irq.h
│   │           │   │   ├── mini_uart.h
│   │           │   │   └── timer.h
│   │           │   ├── printf.h
│   │           │   ├── sched.h
│   │           │   ├── sys.h
│   │           │   ├── timer.h
│   │           │   └── utils.h
│   │           ├── src/
│   │           │   ├── boot.S
│   │           │   ├── config.txt
│   │           │   ├── entry.S
│   │           │   ├── fork.c
│   │           │   ├── irq.S
│   │           │   ├── irq.c
│   │           │   ├── kernel.c
│   │           │   ├── linker.ld
│   │           │   ├── mini_uart.c
│   │           │   ├── mm.S
│   │           │   ├── mm.c
│   │           │   ├── printf.c
│   │           │   ├── sched.S
│   │           │   ├── sched.c
│   │           │   ├── sys.S
│   │           │   ├── sys.c
│   │           │   ├── timer.S
│   │           │   ├── timer.c
│   │           │   └── utils.S
│   │           └── start.sh
│   └── lesson06/
│       └── 1/
│           └── xdfm1/
│               ├── Makefile
│               ├── build.bat
│               ├── build.sh
│               ├── gdb.cmd
│               ├── include/
│               │   ├── arm/
│               │   │   ├── mmu.h
│               │   │   └── sysregs.h
│               │   ├── entry.h
│               │   ├── fork.h
│               │   ├── irq.h
│               │   ├── mini_uart.h
│               │   ├── mm.h
│               │   ├── peripherals/
│               │   │   ├── base.h
│               │   │   ├── gpio.h
│               │   │   ├── irq.h
│               │   │   ├── mini_uart.h
│               │   │   └── timer.h
│               │   ├── printf.h
│               │   ├── sched.h
│               │   ├── sys.h
│               │   ├── timer.h
│               │   ├── user.h
│               │   ├── user_sys.h
│               │   └── utils.h
│               ├── src/
│               │   ├── boot.S
│               │   ├── config.txt
│               │   ├── entry.S
│               │   ├── fork.c
│               │   ├── irq.S
│               │   ├── irq.c
│               │   ├── kernel.c
│               │   ├── linker.ld
│               │   ├── mini_uart.c
│               │   ├── mm.S
│               │   ├── mm.c
│               │   ├── printf.c
│               │   ├── sched.S
│               │   ├── sched.c
│               │   ├── sys.c
│               │   ├── timer.c
│               │   ├── user.c
│               │   ├── user_sys.S
│               │   └── utils.S
│               └── start.sh
├── src/
│   ├── lesson01/
│   │   ├── Makefile
│   │   ├── build.bat
│   │   ├── build.sh
│   │   ├── include/
│   │   │   ├── mini_uart.h
│   │   │   ├── mm.h
│   │   │   ├── peripherals/
│   │   │   │   ├── base.h
│   │   │   │   ├── gpio.h
│   │   │   │   └── mini_uart.h
│   │   │   └── utils.h
│   │   └── src/
│   │       ├── boot.S
│   │       ├── config.txt
│   │       ├── kernel.c
│   │       ├── linker.ld
│   │       ├── mini_uart.c
│   │       ├── mm.S
│   │       └── utils.S
│   ├── lesson02/
│   │   ├── Makefile
│   │   ├── build.bat
│   │   ├── build.sh
│   │   ├── include/
│   │   │   ├── arm/
│   │   │   │   └── sysregs.h
│   │   │   ├── mini_uart.h
│   │   │   ├── mm.h
│   │   │   ├── peripherals/
│   │   │   │   ├── base.h
│   │   │   │   ├── gpio.h
│   │   │   │   └── mini_uart.h
│   │   │   ├── printf.h
│   │   │   └── utils.h
│   │   └── src/
│   │       ├── boot.S
│   │       ├── config.txt
│   │       ├── kernel.c
│   │       ├── linker.ld
│   │       ├── mini_uart.c
│   │       ├── mm.S
│   │       ├── printf.c
│   │       └── utils.S
│   ├── lesson03/
│   │   ├── Makefile
│   │   ├── build.bat
│   │   ├── build.sh
│   │   ├── include/
│   │   │   ├── arm/
│   │   │   │   └── sysregs.h
│   │   │   ├── entry.h
│   │   │   ├── irq.h
│   │   │   ├── mini_uart.h
│   │   │   ├── mm.h
│   │   │   ├── peripherals/
│   │   │   │   ├── base.h
│   │   │   │   ├── gpio.h
│   │   │   │   ├── irq.h
│   │   │   │   ├── mini_uart.h
│   │   │   │   └── timer.h
│   │   │   ├── printf.h
│   │   │   ├── timer.h
│   │   │   └── utils.h
│   │   └── src/
│   │       ├── boot.S
│   │       ├── config.txt
│   │       ├── entry.S
│   │       ├── irq.S
│   │       ├── irq.c
│   │       ├── kernel.c
│   │       ├── linker.ld
│   │       ├── mini_uart.c
│   │       ├── mm.S
│   │       ├── printf.c
│   │       ├── timer.c
│   │       └── utils.S
│   ├── lesson04/
│   │   ├── Makefile
│   │   ├── build.bat
│   │   ├── build.sh
│   │   ├── include/
│   │   │   ├── arm/
│   │   │   │   └── sysregs.h
│   │   │   ├── entry.h
│   │   │   ├── fork.h
│   │   │   ├── irq.h
│   │   │   ├── mini_uart.h
│   │   │   ├── mm.h
│   │   │   ├── peripherals/
│   │   │   │   ├── base.h
│   │   │   │   ├── gpio.h
│   │   │   │   ├── irq.h
│   │   │   │   ├── mini_uart.h
│   │   │   │   └── timer.h
│   │   │   ├── printf.h
│   │   │   ├── sched.h
│   │   │   ├── timer.h
│   │   │   └── utils.h
│   │   └── src/
│   │       ├── boot.S
│   │       ├── config.txt
│   │       ├── entry.S
│   │       ├── fork.c
│   │       ├── irq.S
│   │       ├── irq.c
│   │       ├── kernel.c
│   │       ├── linker.ld
│   │       ├── mini_uart.c
│   │       ├── mm.S
│   │       ├── mm.c
│   │       ├── printf.c
│   │       ├── sched.S
│   │       ├── sched.c
│   │       ├── timer.c
│   │       └── utils.S
│   ├── lesson05/
│   │   ├── Makefile
│   │   ├── build.bat
│   │   ├── build.sh
│   │   ├── include/
│   │   │   ├── arm/
│   │   │   │   └── sysregs.h
│   │   │   ├── entry.h
│   │   │   ├── fork.h
│   │   │   ├── irq.h
│   │   │   ├── mini_uart.h
│   │   │   ├── mm.h
│   │   │   ├── peripherals/
│   │   │   │   ├── base.h
│   │   │   │   ├── gpio.h
│   │   │   │   ├── irq.h
│   │   │   │   ├── mini_uart.h
│   │   │   │   └── timer.h
│   │   │   ├── printf.h
│   │   │   ├── sched.h
│   │   │   ├── sys.h
│   │   │   ├── timer.h
│   │   │   └── utils.h
│   │   └── src/
│   │       ├── boot.S
│   │       ├── config.txt
│   │       ├── entry.S
│   │       ├── fork.c
│   │       ├── irq.S
│   │       ├── irq.c
│   │       ├── kernel.c
│   │       ├── linker.ld
│   │       ├── mini_uart.c
│   │       ├── mm.S
│   │       ├── mm.c
│   │       ├── printf.c
│   │       ├── sched.S
│   │       ├── sched.c
│   │       ├── sys.S
│   │       ├── sys.c
│   │       ├── timer.c
│   │       └── utils.S
│   └── lesson06/
│       ├── Makefile
│       ├── build.bat
│       ├── build.sh
│       ├── include/
│       │   ├── arm/
│       │   │   ├── mmu.h
│       │   │   └── sysregs.h
│       │   ├── entry.h
│       │   ├── fork.h
│       │   ├── irq.h
│       │   ├── mini_uart.h
│       │   ├── mm.h
│       │   ├── peripherals/
│       │   │   ├── base.h
│       │   │   ├── gpio.h
│       │   │   ├── irq.h
│       │   │   ├── mini_uart.h
│       │   │   └── timer.h
│       │   ├── printf.h
│       │   ├── sched.h
│       │   ├── sys.h
│       │   ├── timer.h
│       │   ├── user.h
│       │   ├── user_sys.h
│       │   └── utils.h
│       └── src/
│           ├── boot.S
│           ├── config.txt
│           ├── entry.S
│           ├── fork.c
│           ├── irq.S
│           ├── irq.c
│           ├── kernel.c
│           ├── linker.ld
│           ├── mini_uart.c
│           ├── mm.S
│           ├── mm.c
│           ├── printf.c
│           ├── sched.S
│           ├── sched.c
│           ├── sys.c
│           ├── timer.c
│           ├── user.c
│           ├── user_sys.S
│           └── utils.S
└── translations/
    ├── ko/
    │   ├── Introduction.md
    │   ├── Prerequisites.md
    │   ├── lesson01/
    │   │   ├── exercises.md
    │   │   ├── linux/
    │   │   │   ├── build-system.md
    │   │   │   ├── kernel-startup.md
    │   │   │   └── project-structure.md
    │   │   └── rpi-os.md
    │   ├── lesson02/
    │   │   ├── exercises.md
    │   │   ├── linux.md
    │   │   └── rpi-os.md
    │   ├── lesson03/
    │   │   ├── exercises.md
    │   │   ├── linux/
    │   │   │   ├── interrupt_controllers.md
    │   │   │   ├── low_level-exception_handling.md
    │   │   │   └── timer.md
    │   │   └── rpi-os.md
    │   └── lesson05/
    │       ├── exercises.md
    │       ├── linux.md
    │       └── rpi-os.md
    └── zh-cn/
        ├── Prerequisites.md
        ├── lesson01/
        │   ├── exercises.md
        │   ├── linux/
        │   │   ├── build-system.md
        │   │   ├── kernel-startup.md
        │   │   └── project-structure.md
        │   └── rpi-os.md
        ├── lesson02/
        │   ├── exercises.md
        │   ├── linux.md
        │   └── rpi-os.md
        ├── lesson03/
        │   ├── exercises.md
        │   ├── linux/
        │   │   ├── interrupt_controllers.md
        │   │   ├── low_level-exception_handling.md
        │   │   └── timer.md
        │   └── rpi-os.md
        ├── lesson04/
        │   ├── exercises.md
        │   ├── linux/
        │   │   ├── basic_structures.md
        │   │   ├── fork.md
        │   │   └── scheduler.md
        │   └── rpi-os.md
        ├── lesson05/
        │   ├── exercises.md
        │   ├── linux.md
        │   └── rpi-os.md
        └── lesson06/
            ├── exercises.md
            └── rpi-os.md
Download .txt
SYMBOL INDEX (2309 symbols across 483 files)

FILE: exercises/lesson01/1/H-4ND-H/src/kernel.c
  function kernel_main (line 3) | void kernel_main(void)

FILE: exercises/lesson01/1/H-4ND-H/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )

FILE: exercises/lesson01/1/a-v-v/src/kernel.c
  function kernel_main (line 3) | void kernel_main(void)

FILE: exercises/lesson01/1/a-v-v/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( unsigned int baudrate )

FILE: exercises/lesson01/1/adkaster/include/mini_uart.h
  type miniuart_baud_t (line 9) | typedef enum {

FILE: exercises/lesson01/1/adkaster/src/kernel.c
  function kernel_main (line 3) | void kernel_main(void)

FILE: exercises/lesson01/1/adkaster/src/mini_uart.c
  function uart_send (line 7) | void uart_send ( char c )
  function uart_recv (line 16) | char uart_recv ( void )
  function uart_send_string (line 25) | void uart_send_string(char* str)
  function uart_init (line 32) | void uart_init ( miniuart_baud_t baud_rate )

FILE: exercises/lesson01/1/avenito/src/kernel.c
  function kernel_main (line 3) | void kernel_main(void)

FILE: exercises/lesson01/1/avenito/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( int baudrate )

FILE: exercises/lesson01/1/bl4ckout31/src/kernel.c
  function kernel_main (line 3) | void kernel_main(void)

FILE: exercises/lesson01/1/bl4ckout31/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )

FILE: exercises/lesson01/1/evopen/src/kernel_main.c
  function kernel_main (line 4) | void kernel_main(void) {

FILE: exercises/lesson01/1/evopen/src/mini_uart.c
  function get_reg_baud (line 5) | unsigned int get_reg_baud(unsigned int core_freq, unsigned int baud) {
  function uart_init (line 9) | void uart_init(void) {
  function uart_send (line 38) | void uart_send(char c) {
  function uart_recv (line 45) | char uart_recv(void) {
  function uart_send_string (line 52) | void uart_send_string(char* str) {

FILE: exercises/lesson01/1/gcrisis/src/kernel.c
  function kernel_main (line 3) | void kernel_main(void)

FILE: exercises/lesson01/1/gcrisis/src/mini_uart.c
  function uart_send (line 7) | void uart_send ( char c )
  function uart_recv (line 16) | char uart_recv ( void )
  function uart_send_string (line 25) | void uart_send_string(char* str)
  function uart_init (line 32) | void uart_init (int baudrate )

FILE: exercises/lesson01/1/rs/src/kernel.c
  function kernel_main (line 3) | void kernel_main(void) {

FILE: exercises/lesson01/1/rs/src/mini_uart.c
  function uart_send (line 5) | void uart_send(char c) {
  function uart_recv (line 13) | char uart_recv(void) {
  function uart_send_string (line 21) | void uart_send_string(char *str) {
  function uart_init (line 27) | void uart_init(void) {

FILE: exercises/lesson01/1/stefanji/src/kernel.c
  function kernel_main (line 3) | void kernel_main(void)

FILE: exercises/lesson01/1/stefanji/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init (unsigned int rate)

FILE: exercises/lesson01/1/xdfm1/src/kernel.c
  function kernel_main (line 3) | void kernel_main(void)

FILE: exercises/lesson01/1/xdfm1/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_get_baudrate (line 30) | unsigned int uart_get_baudrate( void )
  function uart_init (line 35) | void uart_init ( void )

FILE: exercises/lesson01/1/zjd0112/src/kernel.c
  function kernel_main (line 3) | void kernel_main(void)

FILE: exercises/lesson01/1/zjd0112/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( unsigned int baud_rate )

FILE: exercises/lesson01/2/H-4ND-H/src/kernel.c
  function kernel_main (line 4) | void kernel_main(void)

FILE: exercises/lesson01/2/H-4ND-H/src/uart_pl011.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )

FILE: exercises/lesson01/2/a-v-v/src/kernel.c
  function kernel_main (line 3) | void kernel_main(void)

FILE: exercises/lesson01/2/a-v-v/src/uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 12) | char uart_recv ( void )
  function uart_send_string (line 19) | void uart_send_string(char* str)
  function uart_init (line 26) | void uart_init ( void )

FILE: exercises/lesson01/2/adkaster/src/kernel.c
  function kernel_main (line 3) | void kernel_main(void)

FILE: exercises/lesson01/2/adkaster/src/mini_uart.c
  function mini_uart_send (line 5) | void mini_uart_send ( char c )
  function mini_uart_recv (line 14) | char mini_uart_recv ( void )
  function mini_uart_send_string (line 23) | void mini_uart_send_string(char* str)
  function mini_uart_init (line 30) | void mini_uart_init ( void )

FILE: exercises/lesson01/2/adkaster/src/uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 15) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )

FILE: exercises/lesson01/2/avenito/src/kernel.c
  function kernel_main (line 3) | void kernel_main(void)

FILE: exercises/lesson01/2/avenito/src/uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 11) | char uart_recv ( void )
  function uart_send_string (line 17) | void uart_send_string(char* str)
  function uart_init (line 24) | void uart_init ( void )

FILE: exercises/lesson01/2/bl4ckout31/src/kernel.c
  function kernel_main (line 3) | void kernel_main(void)

FILE: exercises/lesson01/2/bl4ckout31/src/uart.c
  function uart_send (line 5) | void uart_send (char c)
  function uart_recv (line 13) | char uart_recv ()
  function uart_send_string (line 21) | void uart_send_string(char* str)
  function uart_init (line 28) | void uart_init (void)

FILE: exercises/lesson01/2/evopen/src/kernel.c
  function kernel_main (line 3) | void kernel_main(unsigned long id) {

FILE: exercises/lesson01/2/evopen/src/uart.c
  function uart_init (line 5) | void uart_init(void) {
  function uart_send (line 29) | void uart_send(char c) {
  function uart_recv (line 36) | char uart_recv(void) {
  function uart_send_string (line 43) | void uart_send_string(char* str) {

FILE: exercises/lesson01/2/gcrisis/src/kernel.c
  function kernel_main (line 3) | void kernel_main(void)

FILE: exercises/lesson01/2/gcrisis/src/uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 18) | char uart_recv ( void )
  function uart_send_string (line 31) | void uart_send_string(char* str)
  function uart_init (line 38) | void uart_init (int baudrate)

FILE: exercises/lesson01/2/gcrisis/uart-boot/downloader/raspiloader.c
  function do_exit (line 25) | void do_exit(int fd, int res) {
  function open_serial (line 32) | int open_serial(const char *dev) {
  function send_kernel (line 82) | void send_kernel(int fd, const char *file) {
  function main (line 165) | int main(int argc, char *argv[]) {

FILE: exercises/lesson01/2/gcrisis/uart-boot/src/main.c
  function check_head (line 5) | void check_head(char *h,int hlen)
  function kernel_main (line 27) | void kernel_main(void)

FILE: exercises/lesson01/2/gcrisis/uart-boot/src/uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 18) | char uart_recv ( void )
  function uart_send_string (line 31) | void uart_send_string(char* str)
  function uart_init (line 38) | void uart_init (int baudrate)

FILE: exercises/lesson01/2/rs/src/kernel.c
  function kernel_main (line 3) | void kernel_main(void) {

FILE: exercises/lesson01/2/rs/src/uart.c
  function uart_send (line 5) | void uart_send(char c) {
  function uart_recv (line 12) | char uart_recv(void) {
  function uart_send_string (line 19) | void uart_send_string(char *str) {
  function uart_init (line 25) | void uart_init(void) {

FILE: exercises/lesson01/2/stefanji/src/kernel.c
  function kernel_main (line 3) | void kernel_main(void)

FILE: exercises/lesson01/2/stefanji/src/pl011_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 11) | char uart_recv ( void )
  function uart_send_string (line 17) | void uart_send_string(char* str)
  function uart_init (line 24) | void uart_init ( void )

FILE: exercises/lesson01/2/xdfm1/src/kernel.c
  function kernel_main (line 3) | void kernel_main(void)

FILE: exercises/lesson01/2/xdfm1/src/uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 13) | char uart_recv ( void )
  function uart_send_string (line 21) | void uart_send_string(char* str )
  function uart_init (line 28) | void uart_init ( void )

FILE: exercises/lesson01/2/zjd0112/src/kernel.c
  function kernel_main (line 3) | void kernel_main(void)

FILE: exercises/lesson01/2/zjd0112/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )

FILE: exercises/lesson01/2/zjd0112/src/pl011_uart.c
  function pl011_uart_send (line 5) | void pl011_uart_send(char ch)
  function pl011_uart_recv (line 15) | char pl011_uart_recv(void)
  function pl011_uart_send_string (line 25) | void pl011_uart_send_string(char* str)
  function pl011_uart_init (line 33) | void pl011_uart_init(void)

FILE: exercises/lesson01/3/a-v-v/src/kernel.c
  function kernel_main (line 3) | void kernel_main(unsigned long processor_index)

FILE: exercises/lesson01/3/a-v-v/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )

FILE: exercises/lesson01/3/adkaster/src/kernel.c
  function kernel_main (line 4) | void kernel_main(int procid)

FILE: exercises/lesson01/3/adkaster/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )

FILE: exercises/lesson01/3/avenito/src/kernel.c
  function kernel_main (line 7) | void kernel_main(char proc_id)		// get processor id as 'char' from 'x0'

FILE: exercises/lesson01/3/avenito/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )

FILE: exercises/lesson01/3/bl4ckout31/src/kernel.c
  function kernel_main (line 6) | void kernel_main(void)

FILE: exercises/lesson01/3/bl4ckout31/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )

FILE: exercises/lesson01/3/evopen/src/kernel.c
  function kernel_main (line 4) | void kernel_main(unsigned long id) {

FILE: exercises/lesson01/3/evopen/src/mini_uart.c
  function get_reg_baud (line 5) | unsigned int get_reg_baud(unsigned int core_freq, unsigned int baud) {
  function uart_init (line 9) | void uart_init(void) {
  function uart_send (line 38) | void uart_send(char c) {
  function uart_recv (line 45) | char uart_recv(void) {
  function uart_send_string (line 52) | void uart_send_string(char* str) {

FILE: exercises/lesson01/3/gcrisis/src/kernel.c
  function kernel_main (line 7) | void kernel_main(int corenum)

FILE: exercises/lesson01/3/gcrisis/src/mini_uart.c
  function uart_send (line 7) | void uart_send ( char c )
  function uart_recv (line 16) | char uart_recv ( void )
  function uart_send_string (line 25) | void uart_send_string(char* str)
  function uart_init (line 32) | void uart_init (int baudrate )

FILE: exercises/lesson01/3/rs/src/kernel.c
  function kernel_main (line 6) | void kernel_main(void) {

FILE: exercises/lesson01/3/rs/src/mini_uart.c
  function uart_send (line 5) | void uart_send(char c) {
  function uart_recv (line 13) | char uart_recv(void) {
  function uart_send_string (line 21) | void uart_send_string(char *str) {
  function uart_init (line 27) | void uart_init(void) {

FILE: exercises/lesson01/3/stefanji/src/kernel.c
  function kernel_main (line 4) | void kernel_main(unsigned int core_id)

FILE: exercises/lesson01/3/stefanji/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )

FILE: exercises/lesson01/3/szediwy/src/kernel.c
  function kernel_main (line 3) | void kernel_main(unsigned long processor_index)

FILE: exercises/lesson01/3/szediwy/src/mini_uart.c
  function uart_send (line 5) | void uart_send(char c)
  function uart_recv (line 13) | char uart_recv(void)
  function uart_send_string (line 21) | void uart_send_string(char *str)
  function uart_init (line 29) | void uart_init(void)

FILE: exercises/lesson01/3/zjd0112/src/kernel.c
  function kernel_main (line 5) | void kernel_main(unsigned int proc_id)

FILE: exercises/lesson01/3/zjd0112/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )

FILE: exercises/lesson01/3/zjd0112/src/pl011_uart.c
  function pl011_uart_send (line 5) | void pl011_uart_send(char ch)
  function pl011_uart_recv (line 15) | char pl011_uart_recv(void)
  function pl011_uart_send_string (line 25) | void pl011_uart_send_string(char* str)
  function pl011_uart_init (line 33) | void pl011_uart_init(void)

FILE: exercises/lesson01/4/H-4ND-H/src/kernel.c
  function kernel_main (line 5) | void kernel_main(void)

FILE: exercises/lesson01/4/H-4ND-H/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )

FILE: exercises/lesson01/4/a-v-v/src/kernel.c
  function kernel_main (line 3) | void kernel_main(void)

FILE: exercises/lesson01/4/a-v-v/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( unsigned int baudrate )

FILE: exercises/lesson01/4/avenito/src/kernel.c
  function kernel_main (line 3) | void kernel_main(void)

FILE: exercises/lesson01/4/avenito/src/uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 11) | char uart_recv ( void )
  function uart_send_string (line 17) | void uart_send_string(char* str)
  function uart_init (line 24) | void uart_init ( void )

FILE: exercises/lesson01/4/bl4ckout31/src/kernel.c
  function kernel_main (line 3) | void kernel_main(void)

FILE: exercises/lesson01/4/bl4ckout31/src/uart.c
  function uart_send (line 5) | void uart_send (char c)
  function uart_recv (line 13) | char uart_recv ()
  function uart_send_string (line 21) | void uart_send_string(char* str)
  function uart_init (line 28) | void uart_init (void)

FILE: exercises/lesson01/4/evopen/src/kernel.c
  function kernel_main (line 3) | void kernel_main(unsigned long id) {

FILE: exercises/lesson01/4/evopen/src/uart.c
  function uart_init (line 5) | void uart_init(void) {
  function uart_send (line 29) | void uart_send(char c) {
  function uart_recv (line 36) | char uart_recv(void) {
  function uart_send_string (line 43) | void uart_send_string(char* str) {

FILE: exercises/lesson01/4/rs/src/kernel.c
  function kernel_main (line 3) | void kernel_main(void) {

FILE: exercises/lesson01/4/rs/src/mini_uart.c
  function uart_send (line 5) | void uart_send(char c) {
  function uart_recv (line 13) | char uart_recv(void) {
  function uart_send_string (line 21) | void uart_send_string(char *str) {
  function uart_init (line 27) | void uart_init(void) {

FILE: exercises/lesson02/1/H-4ND-H/src/kernel.c
  function print_el (line 6) | void print_el()
  function kernel_init (line 12) | void kernel_init()
  function kernel_main (line 19) | void kernel_main(void)

FILE: exercises/lesson02/1/H-4ND-H/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )
  function putc (line 59) | void putc ( void* p, char c)

FILE: exercises/lesson02/1/H-4ND-H/src/printf.c
  function uli2a (line 31) | static void uli2a(unsigned long int num, unsigned int base, int uc,char ...
  function li2a (line 49) | static void li2a (long num, char * bf)
  function ui2a (line 60) | static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
  function i2a (line 78) | static void i2a (int num, char * bf)
  function a2d (line 87) | static int a2d(char ch)
  function a2i (line 98) | static char a2i(char ch, char** src,int base,int* nump)
  function putchw (line 113) | static void putchw(void* putp,putcf putf,int n, char z, char* bf)
  function tfp_format (line 126) | void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
  function init_printf (line 205) | void init_printf(void* putp,void (*putf) (void*,char))
  function tfp_printf (line 211) | void tfp_printf(char *fmt, ...)
  function putcp (line 219) | static void putcp(void* p,char c)
  function tfp_sprintf (line 226) | void tfp_sprintf(char* s,char *fmt, ...)

FILE: exercises/lesson02/1/avenito/src/kernel.c
  function kernel_main_first (line 5) | void kernel_main_first(void)
  function kernel_main_second (line 14) | void kernel_main_second(void)

FILE: exercises/lesson02/1/avenito/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )
  function putc (line 59) | void putc ( void* p, char c)

FILE: exercises/lesson02/1/avenito/src/printf.c
  function uli2a (line 31) | static void uli2a(unsigned long int num, unsigned int base, int uc,char ...
  function li2a (line 49) | static void li2a (long num, char * bf)
  function ui2a (line 60) | static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
  function i2a (line 78) | static void i2a (int num, char * bf)
  function a2d (line 87) | static int a2d(char ch)
  function a2i (line 98) | static char a2i(char ch, char** src,int base,int* nump)
  function putchw (line 113) | static void putchw(void* putp,putcf putf,int n, char z, char* bf)
  function tfp_format (line 126) | void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
  function init_printf (line 205) | void init_printf(void* putp,void (*putf) (void*,char))
  function tfp_printf (line 211) | void tfp_printf(char *fmt, ...)
  function putcp (line 219) | static void putcp(void* p,char c)
  function tfp_sprintf (line 226) | void tfp_sprintf(char* s,char *fmt, ...)

FILE: exercises/lesson02/1/bl4ckout31/src/kernel.c
  function kernel_main (line 5) | void kernel_main(void)

FILE: exercises/lesson02/1/bl4ckout31/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )
  function putc (line 59) | void putc ( void* p, char c)

FILE: exercises/lesson02/1/bl4ckout31/src/printf.c
  function uli2a (line 31) | static void uli2a(unsigned long int num, unsigned int base, int uc,char ...
  function li2a (line 49) | static void li2a (long num, char * bf)
  function ui2a (line 60) | static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
  function i2a (line 78) | static void i2a (int num, char * bf)
  function a2d (line 87) | static int a2d(char ch)
  function a2i (line 98) | static char a2i(char ch, char** src,int base,int* nump)
  function putchw (line 113) | static void putchw(void* putp,putcf putf,int n, char z, char* bf)
  function tfp_format (line 126) | void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
  function init_printf (line 205) | void init_printf(void* putp,void (*putf) (void*,char))
  function tfp_printf (line 211) | void tfp_printf(char *fmt, ...)
  function putcp (line 219) | static void putcp(void* p,char c)
  function tfp_sprintf (line 226) | void tfp_sprintf(char* s,char *fmt, ...)

FILE: exercises/lesson02/1/evopen/src/kernel.c
  function kernel_main (line 5) | void kernel_main(void) {

FILE: exercises/lesson02/1/evopen/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )
  function putc (line 59) | void putc ( void* p, char c)

FILE: exercises/lesson02/1/evopen/src/printf.c
  function uli2a (line 31) | static void uli2a(unsigned long int num, unsigned int base, int uc,char ...
  function li2a (line 49) | static void li2a (long num, char * bf)
  function ui2a (line 60) | static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
  function i2a (line 78) | static void i2a (int num, char * bf)
  function a2d (line 87) | static int a2d(char ch)
  function a2i (line 98) | static char a2i(char ch, char** src,int base,int* nump)
  function putchw (line 113) | static void putchw(void* putp,putcf putf,int n, char z, char* bf)
  function tfp_format (line 126) | void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
  function init_printf (line 205) | void init_printf(void* putp,void (*putf) (void*,char))
  function tfp_printf (line 211) | void tfp_printf(char *fmt, ...)
  function putcp (line 219) | static void putcp(void* p,char c)
  function tfp_sprintf (line 226) | void tfp_sprintf(char* s,char *fmt, ...)

FILE: exercises/lesson02/1/gcrisis/src/kernel.c
  function kernel1_main (line 5) | void kernel1_main(void)
  function kernel2_main (line 17) | void kernel2_main(void)

FILE: exercises/lesson02/1/gcrisis/src/mini_uart.c
  function uart_send (line 7) | void uart_send ( char c )
  function uart_recv (line 16) | char uart_recv ( void )
  function uart_send_string (line 25) | void uart_send_string(char* str)
  function uart_init (line 32) | void uart_init (int baudrate )
  function putc (line 59) | void putc ( void* p, char c)

FILE: exercises/lesson02/1/gcrisis/src/printf.c
  function uli2a (line 41) | static void uli2a(unsigned long int num, unsigned int base, int uc,char ...
  function li2a (line 59) | static void li2a (long num, char * bf)
  function ui2a (line 70) | static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
  function i2a (line 88) | static void i2a (int num, char * bf)
  function a2d (line 97) | static int a2d(char ch)
  function a2i (line 108) | static char a2i(char ch, char** src,int base,int* nump)
  function putchw (line 123) | static void putchw(void* putp,putcf putf,int n, char z, char* bf)
  function tfp_format (line 136) | void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
  function init_printf (line 215) | void init_printf(void* putp,void (*putf) (void*,char))
  function tfp_printf (line 221) | void tfp_printf(char *fmt, ...)
  function putcp (line 229) | static void putcp(void* p,char c)
  function tfp_sprintf (line 236) | void tfp_sprintf(char* s,char *fmt, ...)

FILE: exercises/lesson02/1/rs/src/kernel.c
  function kernel_main (line 5) | void kernel_main(void) {

FILE: exercises/lesson02/1/rs/src/mini_uart.c
  function uart_send (line 5) | void uart_send(char c) {
  function uart_recv (line 13) | char uart_recv(void) {
  function uart_send_string (line 21) | void uart_send_string(char *str) {
  function uart_init (line 27) | void uart_init(void) {
  function putc (line 56) | void putc(void *p, char c) { uart_send(c); }

FILE: exercises/lesson02/1/rs/src/printf.c
  function uli2a (line 30) | static void uli2a(unsigned long int num, unsigned int base, int uc, char...
  function li2a (line 47) | static void li2a(long num, char *bf) {
  function ui2a (line 57) | static void ui2a(unsigned int num, unsigned int base, int uc, char *bf) {
  function i2a (line 74) | static void i2a(int num, char *bf) {
  function a2d (line 82) | static int a2d(char ch) {
  function a2i (line 93) | static char a2i(char ch, char **src, int base, int *nump) {
  function putchw (line 108) | static void putchw(void *putp, putcf putf, int n, char z, char *bf) {
  function tfp_format (line 120) | void tfp_format(void *putp, putcf putf, char *fmt, va_list va) {
  function init_printf (line 197) | void init_printf(void *putp, void (*putf)(void *, char)) {
  function tfp_printf (line 202) | void tfp_printf(char *fmt, ...) {
  function putcp (line 209) | static void putcp(void *p, char c) { *(*((char **)p))++ = c; }
  function tfp_sprintf (line 211) | void tfp_sprintf(char *s, char *fmt, ...) {

FILE: exercises/lesson02/1/zjd0112/src/kernel.c
  function kernel_el2 (line 5) | void kernel_el2(void)
  function kernel_el1 (line 13) | void kernel_el1(void)

FILE: exercises/lesson02/1/zjd0112/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )
  function putc (line 59) | void putc ( void* p, char c)

FILE: exercises/lesson02/1/zjd0112/src/printf.c
  function uli2a (line 31) | static void uli2a(unsigned long int num, unsigned int base, int uc,char ...
  function li2a (line 49) | static void li2a (long num, char * bf)
  function ui2a (line 60) | static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
  function i2a (line 78) | static void i2a (int num, char * bf)
  function a2d (line 87) | static int a2d(char ch)
  function a2i (line 98) | static char a2i(char ch, char** src,int base,int* nump)
  function putchw (line 113) | static void putchw(void* putp,putcf putf,int n, char z, char* bf)
  function tfp_format (line 126) | void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
  function init_printf (line 205) | void init_printf(void* putp,void (*putf) (void*,char))
  function tfp_printf (line 211) | void tfp_printf(char *fmt, ...)
  function putcp (line 219) | static void putcp(void* p,char c)
  function tfp_sprintf (line 226) | void tfp_sprintf(char* s,char *fmt, ...)

FILE: exercises/lesson02/2/H-4ND-H/src/kernel.c
  function kernel_main (line 5) | void kernel_main(void)

FILE: exercises/lesson02/2/H-4ND-H/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )
  function putc (line 59) | void putc ( void* p, char c)

FILE: exercises/lesson02/2/H-4ND-H/src/printf.c
  function uli2a (line 31) | static void uli2a(unsigned long int num, unsigned int base, int uc,char ...
  function li2a (line 49) | static void li2a (long num, char * bf)
  function ui2a (line 60) | static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
  function i2a (line 78) | static void i2a (int num, char * bf)
  function a2d (line 87) | static int a2d(char ch)
  function a2i (line 98) | static char a2i(char ch, char** src,int base,int* nump)
  function putchw (line 113) | static void putchw(void* putp,putcf putf,int n, char z, char* bf)
  function tfp_format (line 126) | void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
  function init_printf (line 205) | void init_printf(void* putp,void (*putf) (void*,char))
  function tfp_printf (line 211) | void tfp_printf(char *fmt, ...)
  function putcp (line 219) | static void putcp(void* p,char c)
  function tfp_sprintf (line 226) | void tfp_sprintf(char* s,char *fmt, ...)

FILE: exercises/lesson02/2/avenito/src/kernel.c
  function kernel_main (line 5) | void kernel_main(void)

FILE: exercises/lesson02/2/avenito/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )
  function putc (line 59) | void putc ( void* p, char c)

FILE: exercises/lesson02/2/avenito/src/printf.c
  function uli2a (line 31) | static void uli2a(unsigned long int num, unsigned int base, int uc,char ...
  function li2a (line 49) | static void li2a (long num, char * bf)
  function ui2a (line 60) | static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
  function i2a (line 78) | static void i2a (int num, char * bf)
  function a2d (line 87) | static int a2d(char ch)
  function a2i (line 98) | static char a2i(char ch, char** src,int base,int* nump)
  function putchw (line 113) | static void putchw(void* putp,putcf putf,int n, char z, char* bf)
  function tfp_format (line 126) | void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
  function init_printf (line 205) | void init_printf(void* putp,void (*putf) (void*,char))
  function tfp_printf (line 211) | void tfp_printf(char *fmt, ...)
  function putcp (line 219) | static void putcp(void* p,char c)
  function tfp_sprintf (line 226) | void tfp_sprintf(char* s,char *fmt, ...)

FILE: exercises/lesson02/2/bl4ckout31/src/kernel.c
  function kernel_main (line 5) | void kernel_main(void)

FILE: exercises/lesson02/2/bl4ckout31/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )
  function putc (line 59) | void putc ( void* p, char c)

FILE: exercises/lesson02/2/bl4ckout31/src/printf.c
  function uli2a (line 31) | static void uli2a(unsigned long int num, unsigned int base, int uc,char ...
  function li2a (line 49) | static void li2a (long num, char * bf)
  function ui2a (line 60) | static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
  function i2a (line 78) | static void i2a (int num, char * bf)
  function a2d (line 87) | static int a2d(char ch)
  function a2i (line 98) | static char a2i(char ch, char** src,int base,int* nump)
  function putchw (line 113) | static void putchw(void* putp,putcf putf,int n, char z, char* bf)
  function tfp_format (line 126) | void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
  function init_printf (line 205) | void init_printf(void* putp,void (*putf) (void*,char))
  function tfp_printf (line 211) | void tfp_printf(char *fmt, ...)
  function putcp (line 219) | static void putcp(void* p,char c)
  function tfp_sprintf (line 226) | void tfp_sprintf(char* s,char *fmt, ...)

FILE: exercises/lesson02/2/evopen/src/kernel.c
  function kernel_main (line 5) | void kernel_main(void)

FILE: exercises/lesson02/2/evopen/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )
  function putc (line 59) | void putc ( void* p, char c)

FILE: exercises/lesson02/2/evopen/src/printf.c
  function uli2a (line 31) | static void uli2a(unsigned long int num, unsigned int base, int uc,char ...
  function li2a (line 49) | static void li2a (long num, char * bf)
  function ui2a (line 60) | static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
  function i2a (line 78) | static void i2a (int num, char * bf)
  function a2d (line 87) | static int a2d(char ch)
  function a2i (line 98) | static char a2i(char ch, char** src,int base,int* nump)
  function putchw (line 113) | static void putchw(void* putp,putcf putf,int n, char z, char* bf)
  function tfp_format (line 126) | void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
  function init_printf (line 205) | void init_printf(void* putp,void (*putf) (void*,char))
  function tfp_printf (line 211) | void tfp_printf(char *fmt, ...)
  function putcp (line 219) | static void putcp(void* p,char c)
  function tfp_sprintf (line 226) | void tfp_sprintf(char* s,char *fmt, ...)

FILE: exercises/lesson02/2/gcrisis/src/kernel.c
  function kernel1_main (line 5) | void kernel1_main(void)
  function kernel2_main (line 17) | void kernel2_main(void)

FILE: exercises/lesson02/2/gcrisis/src/mini_uart.c
  function uart_send (line 7) | void uart_send ( char c )
  function uart_recv (line 16) | char uart_recv ( void )
  function uart_send_string (line 25) | void uart_send_string(char* str)
  function uart_init (line 32) | void uart_init (int baudrate )
  function putc (line 59) | void putc ( void* p, char c)

FILE: exercises/lesson02/2/gcrisis/src/printf.c
  function uli2a (line 41) | static void uli2a(unsigned long int num, unsigned int base, int uc,char ...
  function li2a (line 59) | static void li2a (long num, char * bf)
  function ui2a (line 70) | static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
  function i2a (line 88) | static void i2a (int num, char * bf)
  function a2d (line 97) | static int a2d(char ch)
  function a2i (line 108) | static char a2i(char ch, char** src,int base,int* nump)
  function putchw (line 123) | static void putchw(void* putp,putcf putf,int n, char z, char* bf)
  function tfp_format (line 136) | void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
  function init_printf (line 215) | void init_printf(void* putp,void (*putf) (void*,char))
  function tfp_printf (line 221) | void tfp_printf(char *fmt, ...)
  function putcp (line 229) | static void putcp(void* p,char c)
  function tfp_sprintf (line 236) | void tfp_sprintf(char* s,char *fmt, ...)

FILE: exercises/lesson02/2/rs/src/kernel.c
  function kernel_main (line 5) | void kernel_main(void) {

FILE: exercises/lesson02/2/rs/src/mini_uart.c
  function uart_send (line 5) | void uart_send(char c) {
  function uart_recv (line 13) | char uart_recv(void) {
  function uart_send_string (line 21) | void uart_send_string(char *str) {
  function uart_init (line 27) | void uart_init(void) {
  function putc (line 56) | void putc(void *p, char c) { uart_send(c); }

FILE: exercises/lesson02/2/rs/src/printf.c
  function uli2a (line 30) | static void uli2a(unsigned long int num, unsigned int base, int uc, char...
  function li2a (line 47) | static void li2a(long num, char *bf) {
  function ui2a (line 57) | static void ui2a(unsigned int num, unsigned int base, int uc, char *bf) {
  function i2a (line 74) | static void i2a(int num, char *bf) {
  function a2d (line 82) | static int a2d(char ch) {
  function a2i (line 93) | static char a2i(char ch, char **src, int base, int *nump) {
  function putchw (line 108) | static void putchw(void *putp, putcf putf, int n, char z, char *bf) {
  function tfp_format (line 120) | void tfp_format(void *putp, putcf putf, char *fmt, va_list va) {
  function init_printf (line 197) | void init_printf(void *putp, void (*putf)(void *, char)) {
  function tfp_printf (line 202) | void tfp_printf(char *fmt, ...) {
  function putcp (line 209) | static void putcp(void *p, char c) { *(*((char **)p))++ = c; }
  function tfp_sprintf (line 211) | void tfp_sprintf(char *s, char *fmt, ...) {

FILE: exercises/lesson02/2/szediwy/src/custom_printf.c
  function uli2a (line 30) | static void uli2a(unsigned long int num, unsigned int base, int uc, char...
  function li2a (line 50) | static void li2a(long num, char *bf)
  function ui2a (line 62) | static void ui2a(unsigned int num, unsigned int base, int uc, char *bf)
  function i2a (line 82) | static void i2a(int num, char *bf)
  function a2d (line 92) | static int a2d(char ch)
  function a2i (line 104) | static char a2i(char ch, char **src, int base, int *nump)
  function putchw (line 121) | static void putchw(void *putp, putcf putf, int n, char z, char *bf)
  function tfp_format (line 134) | void tfp_format(void *putp, putcf putf, char *fmt, va_list va)
  function init_printf (line 223) | void init_printf(void *putp, void (*putf)(void *, char))
  function tfp_printf (line 229) | void tfp_printf(char *fmt, ...)
  function putcp (line 237) | static void putcp(void *p, char c)
  function tfp_sprintf (line 242) | void tfp_sprintf(char *s, char *fmt, ...)

FILE: exercises/lesson02/2/szediwy/src/irq.c
  function enable_interrupt_controller (line 29) | void enable_interrupt_controller()
  function show_invalid_entry_message (line 34) | void show_invalid_entry_message(int type, unsigned long esr, unsigned lo...
  function handle_irq (line 39) | void handle_irq(void)

FILE: exercises/lesson02/2/szediwy/src/kernel.c
  function kernel_main (line 7) | void kernel_main(unsigned long processor_index)

FILE: exercises/lesson02/2/szediwy/src/mini_uart.c
  function uart_send (line 5) | void uart_send(char c)
  function uart_recv (line 13) | char uart_recv(void)
  function uart_send_string (line 21) | void uart_send_string(char *str)
  function uart_init (line 29) | void uart_init(void)
  function putc (line 70) | void putc(void* p, char c)

FILE: exercises/lesson02/2/szediwy/src/timer.c
  function timer_init (line 8) | void timer_init ( void )
  function handle_timer_irq (line 15) | void handle_timer_irq( void )

FILE: exercises/lesson02/2/zjd0112/src/kernel.c
  function kernel_el2 (line 5) | void kernel_el2(void)
  function kernel_el1 (line 13) | void kernel_el1(void)

FILE: exercises/lesson02/2/zjd0112/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )
  function putc (line 59) | void putc ( void* p, char c)

FILE: exercises/lesson02/2/zjd0112/src/printf.c
  function uli2a (line 31) | static void uli2a(unsigned long int num, unsigned int base, int uc,char ...
  function li2a (line 49) | static void li2a (long num, char * bf)
  function ui2a (line 60) | static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
  function i2a (line 78) | static void i2a (int num, char * bf)
  function a2d (line 87) | static int a2d(char ch)
  function a2i (line 98) | static char a2i(char ch, char** src,int base,int* nump)
  function putchw (line 113) | static void putchw(void* putp,putcf putf,int n, char z, char* bf)
  function tfp_format (line 126) | void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
  function init_printf (line 205) | void init_printf(void* putp,void (*putf) (void*,char))
  function tfp_printf (line 211) | void tfp_printf(char *fmt, ...)
  function putcp (line 219) | static void putcp(void* p,char c)
  function tfp_sprintf (line 226) | void tfp_sprintf(char* s,char *fmt, ...)

FILE: exercises/lesson02/3/H-4ND-H/src/kernel.c
  function kernel_main (line 6) | void kernel_main(void)

FILE: exercises/lesson02/3/H-4ND-H/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )
  function putc (line 59) | void putc ( void* p, char c)

FILE: exercises/lesson02/3/H-4ND-H/src/printf.c
  function uli2a (line 31) | static void uli2a(unsigned long int num, unsigned int base, int uc,char ...
  function li2a (line 49) | static void li2a (long num, char * bf)
  function ui2a (line 60) | static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
  function i2a (line 78) | static void i2a (int num, char * bf)
  function a2d (line 87) | static int a2d(char ch)
  function a2i (line 98) | static char a2i(char ch, char** src,int base,int* nump)
  function putchw (line 113) | static void putchw(void* putp,putcf putf,int n, char z, char* bf)
  function tfp_format (line 126) | void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
  function init_printf (line 205) | void init_printf(void* putp,void (*putf) (void*,char))
  function tfp_printf (line 211) | void tfp_printf(char *fmt, ...)
  function putcp (line 219) | static void putcp(void* p,char c)
  function tfp_sprintf (line 226) | void tfp_sprintf(char* s,char *fmt, ...)

FILE: exercises/lesson02/3/avenito/src/kernel.c
  function kernel_main (line 5) | void kernel_main(void)

FILE: exercises/lesson02/3/avenito/src/printf.c
  function uli2a (line 31) | static void uli2a(unsigned long int num, unsigned int base, int uc,char ...
  function li2a (line 49) | static void li2a (long num, char * bf)
  function ui2a (line 60) | static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
  function i2a (line 78) | static void i2a (int num, char * bf)
  function a2d (line 87) | static int a2d(char ch)
  function a2i (line 98) | static char a2i(char ch, char** src,int base,int* nump)
  function putchw (line 113) | static void putchw(void* putp,putcf putf,int n, char z, char* bf)
  function tfp_format (line 126) | void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
  function init_printf (line 205) | void init_printf(void* putp,void (*putf) (void*,char))
  function tfp_printf (line 211) | void tfp_printf(char *fmt, ...)
  function putcp (line 219) | static void putcp(void* p,char c)
  function tfp_sprintf (line 226) | void tfp_sprintf(char* s,char *fmt, ...)

FILE: exercises/lesson02/3/avenito/src/uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 11) | char uart_recv ( void )
  function uart_send_string (line 17) | void uart_send_string(char* str)
  function uart_init (line 24) | void uart_init ( void )
  function putc (line 52) | void putc ( void* p, char c)

FILE: exercises/lesson02/3/bl4ckout31/src/kernel.c
  function kernel_main (line 5) | void kernel_main(void)

FILE: exercises/lesson02/3/bl4ckout31/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )
  function putc (line 59) | void putc ( void* p, char c)

FILE: exercises/lesson02/3/bl4ckout31/src/printf.c
  function uli2a (line 31) | static void uli2a(unsigned long int num, unsigned int base, int uc,char ...
  function li2a (line 49) | static void li2a (long num, char * bf)
  function ui2a (line 60) | static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
  function i2a (line 78) | static void i2a (int num, char * bf)
  function a2d (line 87) | static int a2d(char ch)
  function a2i (line 98) | static char a2i(char ch, char** src,int base,int* nump)
  function putchw (line 113) | static void putchw(void* putp,putcf putf,int n, char z, char* bf)
  function tfp_format (line 126) | void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
  function init_printf (line 205) | void init_printf(void* putp,void (*putf) (void*,char))
  function tfp_printf (line 211) | void tfp_printf(char *fmt, ...)
  function putcp (line 219) | static void putcp(void* p,char c)
  function tfp_sprintf (line 226) | void tfp_sprintf(char* s,char *fmt, ...)

FILE: exercises/lesson02/3/evopen/src/kernel.c
  function kernel_main (line 5) | void kernel_main(void)

FILE: exercises/lesson02/3/evopen/src/printf.c
  function uli2a (line 30) | static void uli2a(unsigned long int num, unsigned int base, int uc, char...
  function li2a (line 46) | static void li2a(long num, char* bf) {
  function ui2a (line 56) | static void ui2a(unsigned int num, unsigned int base, int uc, char* bf) {
  function i2a (line 72) | static void i2a(int num, char* bf) {
  function a2d (line 80) | static int a2d(char ch) {
  function a2i (line 91) | static char a2i(char ch, char** src, int base, int* nump) {
  function putchw (line 105) | static void putchw(void* putp, putcf putf, int n, char z, char* bf) {
  function tfp_format (line 114) | void tfp_format(void* putp, putcf putf, char* fmt, va_list va) {
  function init_printf (line 192) | void init_printf(void* putp, void (*putf)(void*, char)) {
  function tfp_printf (line 197) | void tfp_printf(char* fmt, ...) {
  function putcp (line 204) | static void putcp(void* p, char c) { *(*((char**)p))++ = c; }
  function tfp_sprintf (line 206) | void tfp_sprintf(char* s, char* fmt, ...) {

FILE: exercises/lesson02/3/evopen/src/uart.c
  function uart_init (line 5) | void uart_init(void) {
  function uart_send (line 29) | void uart_send(char c) {
  function uart_recv (line 36) | char uart_recv(void) {
  function uart_send_string (line 43) | void uart_send_string(char* str) {
  function putc (line 49) | void putc(void* p, char c) { uart_send(c); }

FILE: exercises/lesson02/3/rs/src/kernel.c
  function kernel_main (line 5) | void kernel_main(void) {

FILE: exercises/lesson02/3/rs/src/mini_uart.c
  function uart_send (line 5) | void uart_send(char c) {
  function uart_recv (line 13) | char uart_recv(void) {
  function uart_send_string (line 21) | void uart_send_string(char *str) {
  function uart_init (line 27) | void uart_init(void) {
  function putc (line 56) | void putc(void *p, char c) { uart_send(c); }

FILE: exercises/lesson02/3/rs/src/printf.c
  function uli2a (line 30) | static void uli2a(unsigned long int num, unsigned int base, int uc, char...
  function li2a (line 47) | static void li2a(long num, char *bf) {
  function ui2a (line 57) | static void ui2a(unsigned int num, unsigned int base, int uc, char *bf) {
  function i2a (line 74) | static void i2a(int num, char *bf) {
  function a2d (line 82) | static int a2d(char ch) {
  function a2i (line 93) | static char a2i(char ch, char **src, int base, int *nump) {
  function putchw (line 108) | static void putchw(void *putp, putcf putf, int n, char z, char *bf) {
  function tfp_format (line 120) | void tfp_format(void *putp, putcf putf, char *fmt, va_list va) {
  function init_printf (line 197) | void init_printf(void *putp, void (*putf)(void *, char)) {
  function tfp_printf (line 202) | void tfp_printf(char *fmt, ...) {
  function putcp (line 209) | static void putcp(void *p, char c) { *(*((char **)p))++ = c; }
  function tfp_sprintf (line 211) | void tfp_sprintf(char *s, char *fmt, ...) {

FILE: exercises/lesson03/1/H-4ND-H/src/irq.c
  function enable_interrupt_controller (line 29) | void enable_interrupt_controller()
  function show_invalid_entry_message (line 34) | void show_invalid_entry_message(int type, unsigned long esr, unsigned lo...
  function handle_irq (line 39) | void handle_irq(void)

FILE: exercises/lesson03/1/H-4ND-H/src/kernel.c
  function kernel_main (line 7) | void kernel_main(void)

FILE: exercises/lesson03/1/H-4ND-H/src/local_timer.c
  function timer_init (line 7) | void timer_init ( void )
  function handle_timer_irq (line 13) | void handle_timer_irq( void )

FILE: exercises/lesson03/1/H-4ND-H/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )
  function putc (line 59) | void putc ( void* p, char c)

FILE: exercises/lesson03/1/H-4ND-H/src/printf.c
  function uli2a (line 31) | static void uli2a(unsigned long int num, unsigned int base, int uc,char ...
  function li2a (line 49) | static void li2a (long num, char * bf)
  function ui2a (line 60) | static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
  function i2a (line 78) | static void i2a (int num, char * bf)
  function a2d (line 87) | static int a2d(char ch)
  function a2i (line 98) | static char a2i(char ch, char** src,int base,int* nump)
  function putchw (line 113) | static void putchw(void* putp,putcf putf,int n, char z, char* bf)
  function tfp_format (line 126) | void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
  function init_printf (line 205) | void init_printf(void* putp,void (*putf) (void*,char))
  function tfp_printf (line 211) | void tfp_printf(char *fmt, ...)
  function putcp (line 219) | static void putcp(void* p,char c)
  function tfp_sprintf (line 226) | void tfp_sprintf(char* s,char *fmt, ...)

FILE: exercises/lesson03/1/avenito/src/irq.c
  function enable_interrupt_controller (line 30) | void enable_interrupt_controller()
  function show_invalid_entry_message (line 37) | void show_invalid_entry_message(int type, unsigned long esr, unsigned lo...
  function handle_irq (line 42) | void handle_irq(void)

FILE: exercises/lesson03/1/avenito/src/kernel.c
  function kernel_main (line 7) | void kernel_main(void)

FILE: exercises/lesson03/1/avenito/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )
  function putc (line 59) | void putc ( void* p, char c)

FILE: exercises/lesson03/1/avenito/src/printf.c
  function uli2a (line 31) | static void uli2a(unsigned long int num, unsigned int base, int uc,char ...
  function li2a (line 49) | static void li2a (long num, char * bf)
  function ui2a (line 60) | static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
  function i2a (line 78) | static void i2a (int num, char * bf)
  function a2d (line 87) | static int a2d(char ch)
  function a2i (line 98) | static char a2i(char ch, char** src,int base,int* nump)
  function putchw (line 113) | static void putchw(void* putp,putcf putf,int n, char z, char* bf)
  function tfp_format (line 126) | void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
  function init_printf (line 205) | void init_printf(void* putp,void (*putf) (void*,char))
  function tfp_printf (line 211) | void tfp_printf(char *fmt, ...)
  function putcp (line 219) | static void putcp(void* p,char c)
  function tfp_sprintf (line 226) | void tfp_sprintf(char* s,char *fmt, ...)

FILE: exercises/lesson03/1/avenito/src/timer.c
  function timer_init (line 8) | void timer_init ( void )
  function handle_timer_irq (line 14) | void handle_timer_irq( void )

FILE: exercises/lesson03/1/bl4ckout31/src/irq.c
  function enable_interrupt_controller (line 29) | void enable_interrupt_controller()
  function show_invalid_entry_message (line 41) | void show_invalid_entry_message(int type, unsigned long esr, unsigned lo...
  function handle_irq (line 46) | void handle_irq(void)

FILE: exercises/lesson03/1/bl4ckout31/src/kernel.c
  function kernel_main (line 7) | void kernel_main(void)

FILE: exercises/lesson03/1/bl4ckout31/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )
  function putc (line 59) | void putc ( void* p, char c)

FILE: exercises/lesson03/1/bl4ckout31/src/printf.c
  function uli2a (line 31) | static void uli2a(unsigned long int num, unsigned int base, int uc,char ...
  function li2a (line 49) | static void li2a (long num, char * bf)
  function ui2a (line 60) | static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
  function i2a (line 78) | static void i2a (int num, char * bf)
  function a2d (line 87) | static int a2d(char ch)
  function a2i (line 98) | static char a2i(char ch, char** src,int base,int* nump)
  function putchw (line 113) | static void putchw(void* putp,putcf putf,int n, char z, char* bf)
  function tfp_format (line 126) | void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
  function init_printf (line 205) | void init_printf(void* putp,void (*putf) (void*,char))
  function tfp_printf (line 211) | void tfp_printf(char *fmt, ...)
  function putcp (line 219) | static void putcp(void* p,char c)
  function tfp_sprintf (line 226) | void tfp_sprintf(char* s,char *fmt, ...)

FILE: exercises/lesson03/1/bl4ckout31/src/timer.c
  function timer_init (line 8) | void timer_init ( void )
  function handle_timer_irq (line 15) | void handle_timer_irq( void )
  function local_timer_init (line 23) | void local_timer_init ( void )
  function handle_local_timer_irq (line 28) | void handle_local_timer_irq( void )

FILE: exercises/lesson03/1/rs/src/irq.c
  function enable_interrupt_controller (line 20) | void enable_interrupt_controller() {
  function show_invalid_entry_message (line 25) | void show_invalid_entry_message(int type, unsigned long esr,
  function handle_irq (line 31) | void handle_irq(void) {

FILE: exercises/lesson03/1/rs/src/kernel.c
  function kernel_main (line 6) | void kernel_main(void) {

FILE: exercises/lesson03/1/rs/src/mini_uart.c
  function uart_send (line 5) | void uart_send(char c) {
  function uart_recv (line 13) | char uart_recv(void) {
  function uart_send_string (line 21) | void uart_send_string(char *str) {
  function uart_init (line 27) | void uart_init(void) {
  function putc (line 56) | void putc(void *p, char c) { uart_send(c); }

FILE: exercises/lesson03/1/rs/src/printf.c
  function uli2a (line 30) | static void uli2a(unsigned long int num, unsigned int base, int uc, char...
  function li2a (line 47) | static void li2a(long num, char *bf) {
  function ui2a (line 57) | static void ui2a(unsigned int num, unsigned int base, int uc, char *bf) {
  function i2a (line 74) | static void i2a(int num, char *bf) {
  function a2d (line 82) | static int a2d(char ch) {
  function a2i (line 93) | static char a2i(char ch, char **src, int base, int *nump) {
  function putchw (line 108) | static void putchw(void *putp, putcf putf, int n, char z, char *bf) {
  function tfp_format (line 120) | void tfp_format(void *putp, putcf putf, char *fmt, va_list va) {
  function init_printf (line 197) | void init_printf(void *putp, void (*putf)(void *, char)) {
  function tfp_printf (line 202) | void tfp_printf(char *fmt, ...) {
  function putcp (line 209) | static void putcp(void *p, char c) { *(*((char **)p))++ = c; }
  function tfp_sprintf (line 211) | void tfp_sprintf(char *s, char *fmt, ...) {

FILE: exercises/lesson03/1/rs/src/timer.c
  function timer_init (line 8) | void timer_init(void) {
  function handle_timer_irq (line 14) | void handle_timer_irq(void) {
  function arm_timer_init (line 21) | void arm_timer_init(void) {
  function handle_arm_timer_irq (line 29) | void handle_arm_timer_irq(void) {

FILE: exercises/lesson03/1/szediwy/src/custom_printf.c
  function uli2a (line 30) | static void uli2a(unsigned long int num, unsigned int base, int uc, char...
  function li2a (line 50) | static void li2a(long num, char *bf)
  function ui2a (line 62) | static void ui2a(unsigned int num, unsigned int base, int uc, char *bf)
  function i2a (line 82) | static void i2a(int num, char *bf)
  function a2d (line 92) | static int a2d(char ch)
  function a2i (line 104) | static char a2i(char ch, char **src, int base, int *nump)
  function putchw (line 121) | static void putchw(void *putp, putcf putf, int n, char z, char *bf)
  function tfp_format (line 134) | void tfp_format(void *putp, putcf putf, char *fmt, va_list va)
  function init_printf (line 223) | void init_printf(void *putp, void (*putf)(void *, char))
  function tfp_printf (line 229) | void tfp_printf(char *fmt, ...)
  function putcp (line 237) | static void putcp(void *p, char c)
  function tfp_sprintf (line 242) | void tfp_sprintf(char *s, char *fmt, ...)

FILE: exercises/lesson03/1/szediwy/src/debug.c
  function d0 (line 3) | void d0(void) {
  function d1 (line 7) | void d1(void) {
  function d2 (line 11) | void d2(void) {
  function d3 (line 15) | void d3(void) {
  function d4 (line 19) | void d4(void) {

FILE: exercises/lesson03/1/szediwy/src/irq.c
  function enable_interrupt (line 30) | void enable_interrupt(unsigned int irq) {
  function assign_target (line 44) | void assign_target(unsigned int irq, unsigned int cpu) {
  function enable_interrupt_controller (line 63) | void enable_interrupt_controller() {
  function show_invalid_entry_message (line 71) | void show_invalid_entry_message(int type, unsigned long esr, unsigned lo...
  function handle_irq (line 76) | void handle_irq(void)

FILE: exercises/lesson03/1/szediwy/src/kernel.c
  function kernel_main (line 7) | void kernel_main(unsigned long processor_index)

FILE: exercises/lesson03/1/szediwy/src/mini_uart.c
  function uart_send (line 5) | void uart_send(char c)
  function uart_recv (line 13) | char uart_recv(void)
  function uart_send_string (line 21) | void uart_send_string(char *str)
  function uart_init (line 29) | void uart_init(void)
  function putc (line 70) | void putc(void* p, char c)

FILE: exercises/lesson03/1/szediwy/src/timer.c
  function timer_init (line 8) | void timer_init ( void )
  function handle_timer_irq (line 15) | void handle_timer_irq( void )
  function handle_local_timer_irq (line 23) | void handle_local_timer_irq( void )
  function local_timer_init (line 29) | void local_timer_init (void) {

FILE: exercises/lesson03/1/xdfm1/src/arm_timer.c
  function armtimer_init (line 8) | void armtimer_init ( void )
  function handle_armtimer_irq (line 17) | void handle_armtimer_irq( void )

FILE: exercises/lesson03/1/xdfm1/src/irq.c
  function enable_interrupt_controller (line 29) | void enable_interrupt_controller()
  function show_invalid_entry_message (line 35) | void show_invalid_entry_message(int type, unsigned long esr, unsigned lo...
  function handle_irq (line 40) | void handle_irq(void)

FILE: exercises/lesson03/1/xdfm1/src/kernel.c
  function kernel_main (line 7) | void kernel_main(void)

FILE: exercises/lesson03/1/xdfm1/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )
  function putc (line 59) | void putc ( void* p, char c)

FILE: exercises/lesson03/1/xdfm1/src/printf.c
  function uli2a (line 31) | static void uli2a(unsigned long int num, unsigned int base, int uc,char ...
  function li2a (line 49) | static void li2a (long num, char * bf)
  function ui2a (line 60) | static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
  function i2a (line 78) | static void i2a (int num, char * bf)
  function a2d (line 87) | static int a2d(char ch)
  function a2i (line 98) | static char a2i(char ch, char** src,int base,int* nump)
  function putchw (line 113) | static void putchw(void* putp,putcf putf,int n, char z, char* bf)
  function tfp_format (line 126) | void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
  function init_printf (line 205) | void init_printf(void* putp,void (*putf) (void*,char))
  function tfp_printf (line 211) | void tfp_printf(char *fmt, ...)
  function putcp (line 219) | static void putcp(void* p,char c)
  function tfp_sprintf (line 226) | void tfp_sprintf(char* s,char *fmt, ...)

FILE: exercises/lesson03/2/H-4ND-H/src/irq.c
  function enable_interrupt_controller (line 30) | void enable_interrupt_controller()
  function show_invalid_entry_message (line 35) | void show_invalid_entry_message(int type, unsigned long esr, unsigned lo...
  function handle_irq (line 40) | void handle_irq(void)

FILE: exercises/lesson03/2/H-4ND-H/src/kernel.c
  function kernel_main (line 7) | void kernel_main(void)

FILE: exercises/lesson03/2/H-4ND-H/src/mini_uart.c
  function uart_send (line 11) | void uart_send ( char c )
  function uart_recv (line 20) | char uart_recv ( void )
  function uart_send_string (line 29) | void uart_send_string(char* str)
  function uart_init (line 36) | void uart_init ( void )
  function handle_uart_irq (line 63) | void handle_uart_irq()
  function putc (line 90) | void putc ( void* p, char c)

FILE: exercises/lesson03/2/H-4ND-H/src/printf.c
  function uli2a (line 31) | static void uli2a(unsigned long int num, unsigned int base, int uc,char ...
  function li2a (line 49) | static void li2a (long num, char * bf)
  function ui2a (line 60) | static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
  function i2a (line 78) | static void i2a (int num, char * bf)
  function a2d (line 87) | static int a2d(char ch)
  function a2i (line 98) | static char a2i(char ch, char** src,int base,int* nump)
  function putchw (line 113) | static void putchw(void* putp,putcf putf,int n, char z, char* bf)
  function tfp_format (line 126) | void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
  function init_printf (line 205) | void init_printf(void* putp,void (*putf) (void*,char))
  function tfp_printf (line 211) | void tfp_printf(char *fmt, ...)
  function putcp (line 219) | static void putcp(void* p,char c)
  function tfp_sprintf (line 226) | void tfp_sprintf(char* s,char *fmt, ...)

FILE: exercises/lesson03/2/H-4ND-H/src/timer.c
  function timer_init (line 8) | void timer_init ( void )
  function handle_timer_irq (line 15) | void handle_timer_irq( void )

FILE: exercises/lesson03/2/avenito/src/irq.c
  function enable_interrupt_controller (line 31) | void enable_interrupt_controller()
  function show_invalid_entry_message (line 36) | void show_invalid_entry_message(int type, unsigned long esr, unsigned lo...
  function handle_irq (line 41) | void handle_irq(void)

FILE: exercises/lesson03/2/avenito/src/kernel.c
  function kernel_main (line 7) | void kernel_main(void)

FILE: exercises/lesson03/2/avenito/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )
  function handle_uart_irq (line 57) | void handle_uart_irq( void )
  function putc (line 66) | void putc ( void* p, char c)

FILE: exercises/lesson03/2/avenito/src/printf.c
  function uli2a (line 31) | static void uli2a(unsigned long int num, unsigned int base, int uc,char ...
  function li2a (line 49) | static void li2a (long num, char * bf)
  function ui2a (line 60) | static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
  function i2a (line 78) | static void i2a (int num, char * bf)
  function a2d (line 87) | static int a2d(char ch)
  function a2i (line 98) | static char a2i(char ch, char** src,int base,int* nump)
  function putchw (line 113) | static void putchw(void* putp,putcf putf,int n, char z, char* bf)
  function tfp_format (line 126) | void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
  function init_printf (line 205) | void init_printf(void* putp,void (*putf) (void*,char))
  function tfp_printf (line 211) | void tfp_printf(char *fmt, ...)
  function putcp (line 219) | static void putcp(void* p,char c)
  function tfp_sprintf (line 226) | void tfp_sprintf(char* s,char *fmt, ...)

FILE: exercises/lesson03/2/avenito/src/timer.c
  function timer_init (line 8) | void timer_init ( void )
  function handle_timer_irq (line 15) | void handle_timer_irq( void )

FILE: exercises/lesson03/2/bl4ckout31/src/irq.c
  function enable_interrupt_controller (line 30) | void enable_interrupt_controller()
  function show_invalid_entry_message (line 35) | void show_invalid_entry_message(int type, unsigned long esr, unsigned lo...
  function handle_irq (line 40) | void handle_irq(void)

FILE: exercises/lesson03/2/bl4ckout31/src/kernel.c
  function kernel_main (line 7) | void kernel_main(void)

FILE: exercises/lesson03/2/bl4ckout31/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )
  function putc (line 59) | void putc ( void* p, char c)
  function handle_uart_irq (line 64) | void handle_uart_irq( void )

FILE: exercises/lesson03/2/bl4ckout31/src/printf.c
  function uli2a (line 31) | static void uli2a(unsigned long int num, unsigned int base, int uc,char ...
  function li2a (line 49) | static void li2a (long num, char * bf)
  function ui2a (line 60) | static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
  function i2a (line 78) | static void i2a (int num, char * bf)
  function a2d (line 87) | static int a2d(char ch)
  function a2i (line 98) | static char a2i(char ch, char** src,int base,int* nump)
  function putchw (line 113) | static void putchw(void* putp,putcf putf,int n, char z, char* bf)
  function tfp_format (line 126) | void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
  function init_printf (line 205) | void init_printf(void* putp,void (*putf) (void*,char))
  function tfp_printf (line 211) | void tfp_printf(char *fmt, ...)
  function putcp (line 219) | static void putcp(void* p,char c)
  function tfp_sprintf (line 226) | void tfp_sprintf(char* s,char *fmt, ...)

FILE: exercises/lesson03/2/bl4ckout31/src/timer.c
  function timer_init (line 8) | void timer_init ( void )
  function handle_timer_irq (line 15) | void handle_timer_irq( void )

FILE: exercises/lesson03/2/rs/src/irq.c
  function enable_interrupt_controller (line 20) | void enable_interrupt_controller() {
  function show_invalid_entry_message (line 25) | void show_invalid_entry_message(int type, unsigned long esr,
  function handle_irq (line 31) | void handle_irq(void) {

FILE: exercises/lesson03/2/rs/src/kernel.c
  function kernel_main (line 6) | void kernel_main(void) {

FILE: exercises/lesson03/2/rs/src/mini_uart.c
  function uart_send (line 6) | void uart_send(char c) {
  function uart_recv (line 14) | char uart_recv(void) {
  function uart_send_string (line 22) | void uart_send_string(char *str) {
  function handle_uart_irq (line 28) | void handle_uart_irq(void) {
  function uart_init (line 37) | void uart_init(void) {
  function putc (line 66) | void putc(void *p, char c) { uart_send(c); }

FILE: exercises/lesson03/2/rs/src/printf.c
  function uli2a (line 30) | static void uli2a(unsigned long int num, unsigned int base, int uc, char...
  function li2a (line 47) | static void li2a(long num, char *bf) {
  function ui2a (line 57) | static void ui2a(unsigned int num, unsigned int base, int uc, char *bf) {
  function i2a (line 74) | static void i2a(int num, char *bf) {
  function a2d (line 82) | static int a2d(char ch) {
  function a2i (line 93) | static char a2i(char ch, char **src, int base, int *nump) {
  function putchw (line 108) | static void putchw(void *putp, putcf putf, int n, char z, char *bf) {
  function tfp_format (line 120) | void tfp_format(void *putp, putcf putf, char *fmt, va_list va) {
  function init_printf (line 197) | void init_printf(void *putp, void (*putf)(void *, char)) {
  function tfp_printf (line 202) | void tfp_printf(char *fmt, ...) {
  function putcp (line 209) | static void putcp(void *p, char c) { *(*((char **)p))++ = c; }
  function tfp_sprintf (line 211) | void tfp_sprintf(char *s, char *fmt, ...) {

FILE: exercises/lesson03/2/rs/src/timer.c
  function timer_init (line 8) | void timer_init(void) {
  function handle_timer_irq (line 14) | void handle_timer_irq(void) {

FILE: exercises/lesson03/2/szediwy/src/custom_printf.c
  function uli2a (line 30) | static void uli2a(unsigned long int num, unsigned int base, int uc, char...
  function li2a (line 50) | static void li2a(long num, char *bf)
  function ui2a (line 62) | static void ui2a(unsigned int num, unsigned int base, int uc, char *bf)
  function i2a (line 82) | static void i2a(int num, char *bf)
  function a2d (line 92) | static int a2d(char ch)
  function a2i (line 104) | static char a2i(char ch, char **src, int base, int *nump)
  function putchw (line 121) | static void putchw(void *putp, putcf putf, int n, char z, char *bf)
  function tfp_format (line 134) | void tfp_format(void *putp, putcf putf, char *fmt, va_list va)
  function init_printf (line 223) | void init_printf(void *putp, void (*putf)(void *, char))
  function tfp_printf (line 229) | void tfp_printf(char *fmt, ...)
  function putcp (line 237) | static void putcp(void *p, char c)
  function tfp_sprintf (line 242) | void tfp_sprintf(char *s, char *fmt, ...)

FILE: exercises/lesson03/2/szediwy/src/debug.c
  function d0 (line 3) | void d0(void) {
  function d1 (line 7) | void d1(void) {
  function d2 (line 11) | void d2(void) {
  function d3 (line 15) | void d3(void) {
  function d4 (line 19) | void d4(void) {

FILE: exercises/lesson03/2/szediwy/src/irq.c
  function enable_interrupt (line 31) | void enable_interrupt(unsigned int irq) {
  function assign_target (line 45) | void assign_target(unsigned int irq, unsigned int cpu) {
  function enable_interrupt_controller (line 64) | void enable_interrupt_controller() {
  function show_invalid_entry_message (line 75) | void show_invalid_entry_message(int type, unsigned long esr, unsigned lo...
  function handle_irq (line 80) | void handle_irq(void)

FILE: exercises/lesson03/2/szediwy/src/kernel.c
  function kernel_main (line 7) | void kernel_main(unsigned long processor_index)

FILE: exercises/lesson03/2/szediwy/src/mini_uart.c
  function uart_send (line 6) | void uart_send(char c)
  function uart_recv (line 14) | char uart_recv(void)
  function uart_send_string (line 22) | void uart_send_string(char *str)
  function uart_init (line 30) | void uart_init(void)
  function putc (line 80) | void putc(void *p, char c)
  function handle_uart_interrupt (line 85) | void handle_uart_interrupt(void)

FILE: exercises/lesson03/2/szediwy/src/timer.c
  function timer_init (line 8) | void timer_init ( void )
  function handle_timer_irq (line 15) | void handle_timer_irq( void )
  function handle_local_timer_irq (line 23) | void handle_local_timer_irq( void )
  function local_timer_init (line 29) | void local_timer_init (void) {

FILE: exercises/lesson03/3/H-4ND-H/src/irq.c
  function enable_interrupt_controller (line 29) | void enable_interrupt_controller()
  function show_invalid_entry_message (line 34) | void show_invalid_entry_message(int type, unsigned long esr, unsigned lo...
  function handle_irq (line 39) | void handle_irq(void)

FILE: exercises/lesson03/3/H-4ND-H/src/kernel.c
  function kernel_main (line 7) | void kernel_main(void)

FILE: exercises/lesson03/3/H-4ND-H/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )
  function putc (line 59) | void putc ( void* p, char c)

FILE: exercises/lesson03/3/H-4ND-H/src/printf.c
  function uli2a (line 31) | static void uli2a(unsigned long int num, unsigned int base, int uc,char ...
  function li2a (line 49) | static void li2a (long num, char * bf)
  function ui2a (line 60) | static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
  function i2a (line 78) | static void i2a (int num, char * bf)
  function a2d (line 87) | static int a2d(char ch)
  function a2i (line 98) | static char a2i(char ch, char** src,int base,int* nump)
  function putchw (line 113) | static void putchw(void* putp,putcf putf,int n, char z, char* bf)
  function tfp_format (line 126) | void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
  function init_printf (line 205) | void init_printf(void* putp,void (*putf) (void*,char))
  function tfp_printf (line 211) | void tfp_printf(char *fmt, ...)
  function putcp (line 219) | static void putcp(void* p,char c)
  function tfp_sprintf (line 226) | void tfp_sprintf(char* s,char *fmt, ...)

FILE: exercises/lesson03/3/H-4ND-H/src/timer.c
  function timer_init (line 7) | void timer_init ( void )
  function handle_timer_irq (line 14) | void handle_timer_irq( void )

FILE: exercises/lesson03/3/avenito/src/irq.c
  function enable_interrupt_controller (line 30) | void enable_interrupt_controller()
  function show_invalid_entry_message (line 36) | void show_invalid_entry_message(int type, unsigned long esr, unsigned lo...
  function handle_irq (line 41) | void handle_irq(void)

FILE: exercises/lesson03/3/avenito/src/kernel.c
  function kernel_main (line 10) | void kernel_main(void)

FILE: exercises/lesson03/3/avenito/src/printf.c
  function uli2a (line 31) | static void uli2a(unsigned long int num, unsigned int base, int uc,char ...
  function li2a (line 49) | static void li2a (long num, char * bf)
  function ui2a (line 60) | static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
  function i2a (line 78) | static void i2a (int num, char * bf)
  function a2d (line 87) | static int a2d(char ch)
  function a2i (line 98) | static char a2i(char ch, char** src,int base,int* nump)
  function putchw (line 113) | static void putchw(void* putp,putcf putf,int n, char z, char* bf)
  function tfp_format (line 126) | void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
  function init_printf (line 205) | void init_printf(void* putp,void (*putf) (void*,char))
  function tfp_printf (line 211) | void tfp_printf(char *fmt, ...)
  function putcp (line 219) | static void putcp(void* p,char c)
  function tfp_sprintf (line 226) | void tfp_sprintf(char* s,char *fmt, ...)

FILE: exercises/lesson03/3/avenito/src/timer.c
  function timer_init (line 8) | void timer_init ( void )
  function handle_timer_irq (line 14) | void handle_timer_irq( void )

FILE: exercises/lesson03/3/avenito/src/uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 11) | char uart_recv ( void )
  function uart_send_string (line 17) | void uart_send_string(char* str)
  function uart_init (line 24) | void uart_init ( void )
  function putc (line 52) | void putc ( void* p, char c)

FILE: exercises/lesson03/3/bl4ckout31/src/irq.c
  function enable_interrupt_controller (line 29) | void enable_interrupt_controller()
  function show_invalid_entry_message (line 35) | void show_invalid_entry_message(int type, unsigned long esr, unsigned lo...
  function handle_irq (line 40) | void handle_irq(void)

FILE: exercises/lesson03/3/bl4ckout31/src/kernel.c
  function kernel_main (line 8) | void kernel_main(void)

FILE: exercises/lesson03/3/bl4ckout31/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )
  function putc (line 59) | void putc ( void* p, char c)

FILE: exercises/lesson03/3/bl4ckout31/src/printf.c
  function uli2a (line 31) | static void uli2a(unsigned long int num, unsigned int base, int uc,char ...
  function li2a (line 49) | static void li2a (long num, char * bf)
  function ui2a (line 60) | static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
  function i2a (line 78) | static void i2a (int num, char * bf)
  function a2d (line 87) | static int a2d(char ch)
  function a2i (line 98) | static char a2i(char ch, char** src,int base,int* nump)
  function putchw (line 113) | static void putchw(void* putp,putcf putf,int n, char z, char* bf)
  function tfp_format (line 126) | void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
  function init_printf (line 205) | void init_printf(void* putp,void (*putf) (void*,char))
  function tfp_printf (line 211) | void tfp_printf(char *fmt, ...)
  function putcp (line 219) | static void putcp(void* p,char c)
  function tfp_sprintf (line 226) | void tfp_sprintf(char* s,char *fmt, ...)

FILE: exercises/lesson03/3/bl4ckout31/src/timer.c
  function timer_init (line 9) | void timer_init ( void )
  function handle_timer_irq (line 16) | void handle_timer_irq( void )
  function generic_timer_init (line 24) | void generic_timer_init ( void )
  function handle_generic_timer_irq (line 30) | void handle_generic_timer_irq( void )

FILE: exercises/lesson03/3/rs/src/irq.c
  function enable_interrupt_controller (line 20) | void enable_interrupt_controller() {
  function show_invalid_entry_message (line 25) | void show_invalid_entry_message(int type, unsigned long esr,
  function handle_irq (line 31) | void handle_irq(void) {

FILE: exercises/lesson03/3/rs/src/kernel.c
  function kernel_main (line 6) | void kernel_main(void) {

FILE: exercises/lesson03/3/rs/src/mini_uart.c
  function uart_send (line 5) | void uart_send(char c) {
  function uart_recv (line 13) | char uart_recv(void) {
  function uart_send_string (line 21) | void uart_send_string(char *str) {
  function uart_init (line 27) | void uart_init(void) {
  function putc (line 56) | void putc(void *p, char c) { uart_send(c); }

FILE: exercises/lesson03/3/rs/src/printf.c
  function uli2a (line 30) | static void uli2a(unsigned long int num, unsigned int base, int uc, char...
  function li2a (line 47) | static void li2a(long num, char *bf) {
  function ui2a (line 57) | static void ui2a(unsigned int num, unsigned int base, int uc, char *bf) {
  function i2a (line 74) | static void i2a(int num, char *bf) {
  function a2d (line 82) | static int a2d(char ch) {
  function a2i (line 93) | static char a2i(char ch, char **src, int base, int *nump) {
  function putchw (line 108) | static void putchw(void *putp, putcf putf, int n, char z, char *bf) {
  function tfp_format (line 120) | void tfp_format(void *putp, putcf putf, char *fmt, va_list va) {
  function init_printf (line 197) | void init_printf(void *putp, void (*putf)(void *, char)) {
  function tfp_printf (line 202) | void tfp_printf(char *fmt, ...) {
  function putcp (line 209) | static void putcp(void *p, char c) { *(*((char **)p))++ = c; }
  function tfp_sprintf (line 211) | void tfp_sprintf(char *s, char *fmt, ...) {

FILE: exercises/lesson03/3/rs/src/timer.c
  function timer_init (line 8) | void timer_init(void) {
  function handle_timer_irq (line 14) | void handle_timer_irq(void) {
  function arm_timer_init (line 21) | void arm_timer_init(void) {
  function handle_arm_timer_irq (line 29) | void handle_arm_timer_irq(void) {

FILE: exercises/lesson04/1/avenito/include/sched.h
  type task_struct (line 17) | struct task_struct
  type task_struct (line 18) | struct task_struct
  type cpu_context (line 21) | struct cpu_context {
  type task_struct (line 37) | struct task_struct {
  type task_struct (line 50) | struct task_struct
  type task_struct (line 51) | struct task_struct
  type task_struct (line 51) | struct task_struct

FILE: exercises/lesson04/1/avenito/src/fork.c
  function copy_process (line 6) | int copy_process(unsigned long fn, unsigned long arg)

FILE: exercises/lesson04/1/avenito/src/irq.c
  function enable_interrupt_controller (line 29) | void enable_interrupt_controller()
  function show_invalid_entry_message (line 34) | void show_invalid_entry_message(int type, unsigned long esr, unsigned lo...
  function handle_irq (line 39) | void handle_irq(void)

FILE: exercises/lesson04/1/avenito/src/kernel.c
  function process (line 9) | void process(char *array)
  function kernel_main (line 19) | void kernel_main(void)

FILE: exercises/lesson04/1/avenito/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )
  function putc (line 59) | void putc ( void* p, char c)

FILE: exercises/lesson04/1/avenito/src/mm.c
  function get_free_page (line 5) | unsigned long get_free_page()
  function free_page (line 16) | void free_page(unsigned long p){

FILE: exercises/lesson04/1/avenito/src/printf.c
  function uli2a (line 31) | static void uli2a(unsigned long int num, unsigned int base, int uc,char ...
  function li2a (line 49) | static void li2a (long num, char * bf)
  function ui2a (line 60) | static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
  function i2a (line 78) | static void i2a (int num, char * bf)
  function a2d (line 87) | static int a2d(char ch)
  function a2i (line 98) | static char a2i(char ch, char** src,int base,int* nump)
  function putchw (line 113) | static void putchw(void* putp,putcf putf,int n, char z, char* bf)
  function tfp_format (line 126) | void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
  function init_printf (line 205) | void init_printf(void* putp,void (*putf) (void*,char))
  function tfp_printf (line 211) | void tfp_printf(char *fmt, ...)
  function putcp (line 219) | static void putcp(void* p,char c)
  function tfp_sprintf (line 226) | void tfp_sprintf(char* s,char *fmt, ...)

FILE: exercises/lesson04/1/avenito/src/sched.c
  type task_struct (line 5) | struct task_struct
  type task_struct (line 6) | struct task_struct
  type task_struct (line 7) | struct task_struct
  function preempt_disable (line 10) | void preempt_disable(void)
  function preempt_enable (line 15) | void preempt_enable(void)
  function _schedule (line 21) | void _schedule(void)
  function schedule (line 50) | void schedule(void)
  function switch_to (line 56) | void switch_to(struct task_struct * next)
  function schedule_tail (line 77) | void schedule_tail(void) {
  function timer_tick (line 82) | void timer_tick()

FILE: exercises/lesson04/1/avenito/src/timer.c
  function timer_init (line 9) | void timer_init ( void )
  function handle_timer_irq (line 16) | void handle_timer_irq( void )

FILE: exercises/lesson04/1/bl4ckout31/include/sched.h
  type task_struct (line 17) | struct task_struct
  type task_struct (line 18) | struct task_struct
  type cpu_context (line 21) | struct cpu_context {
  type task_struct (line 37) | struct task_struct {
  type task_struct (line 50) | struct task_struct
  type task_struct (line 51) | struct task_struct
  type task_struct (line 51) | struct task_struct

FILE: exercises/lesson04/1/bl4ckout31/src/fork.c
  function copy_process (line 6) | int copy_process(unsigned long fn, unsigned long arg)

FILE: exercises/lesson04/1/bl4ckout31/src/irq.c
  function enable_interrupt_controller (line 29) | void enable_interrupt_controller()
  function show_invalid_entry_message (line 34) | void show_invalid_entry_message(int type, unsigned long esr, unsigned lo...
  function handle_irq (line 39) | void handle_irq(void)

FILE: exercises/lesson04/1/bl4ckout31/src/kernel.c
  function process (line 9) | void process(char *array)
  function kernel_main (line 19) | void kernel_main(void)

FILE: exercises/lesson04/1/bl4ckout31/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )
  function putc (line 59) | void putc ( void* p, char c)

FILE: exercises/lesson04/1/bl4ckout31/src/mm.c
  function get_free_page (line 5) | unsigned long get_free_page()
  function free_page (line 16) | void free_page(unsigned long p){

FILE: exercises/lesson04/1/bl4ckout31/src/printf.c
  function uli2a (line 31) | static void uli2a(unsigned long int num, unsigned int base, int uc,char ...
  function li2a (line 49) | static void li2a (long num, char * bf)
  function ui2a (line 60) | static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
  function i2a (line 78) | static void i2a (int num, char * bf)
  function a2d (line 87) | static int a2d(char ch)
  function a2i (line 98) | static char a2i(char ch, char** src,int base,int* nump)
  function putchw (line 113) | static void putchw(void* putp,putcf putf,int n, char z, char* bf)
  function tfp_format (line 126) | void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
  function init_printf (line 205) | void init_printf(void* putp,void (*putf) (void*,char))
  function tfp_printf (line 211) | void tfp_printf(char *fmt, ...)
  function putcp (line 219) | static void putcp(void* p,char c)
  function tfp_sprintf (line 226) | void tfp_sprintf(char* s,char *fmt, ...)

FILE: exercises/lesson04/1/bl4ckout31/src/sched.c
  type task_struct (line 6) | struct task_struct
  type task_struct (line 7) | struct task_struct
  type task_struct (line 8) | struct task_struct
  function preempt_disable (line 11) | void preempt_disable(void)
  function preempt_enable (line 16) | void preempt_enable(void)
  function _schedule (line 22) | void _schedule(void)
  function schedule (line 54) | void schedule(void)
  function switch_to (line 60) | void switch_to(struct task_struct * next)
  function schedule_tail (line 69) | void schedule_tail(void) {
  function timer_tick (line 74) | void timer_tick()
  function print_tasks (line 86) | void print_tasks()

FILE: exercises/lesson04/1/bl4ckout31/src/timer.c
  function timer_init (line 9) | void timer_init ( void )
  function handle_timer_irq (line 16) | void handle_timer_irq( void )

FILE: exercises/lesson04/1/rs/include/sched.h
  type task_struct (line 17) | struct task_struct
  type task_struct (line 18) | struct task_struct
  type cpu_context (line 21) | struct cpu_context {
  type task_struct (line 37) | struct task_struct {
  type task_struct (line 50) | struct task_struct
  type task_struct (line 51) | struct task_struct
  type task_struct (line 51) | struct task_struct

FILE: exercises/lesson04/1/rs/src/fork.c
  function copy_process (line 6) | int copy_process(unsigned long fn, unsigned long arg) {

FILE: exercises/lesson04/1/rs/src/irq.c
  function enable_interrupt_controller (line 20) | void enable_interrupt_controller() { put32(ENABLE_IRQS_1, SYSTEM_TIMER_I...
  function show_invalid_entry_message (line 22) | void show_invalid_entry_message(int type, unsigned long esr,
  function handle_irq (line 28) | void handle_irq(void) {

FILE: exercises/lesson04/1/rs/src/kernel.c
  function process (line 9) | void process(char *array) {
  function kernel_main (line 18) | void kernel_main(void) {

FILE: exercises/lesson04/1/rs/src/mini_uart.c
  function uart_send (line 5) | void uart_send(char c) {
  function uart_recv (line 13) | char uart_recv(void) {
  function uart_send_string (line 21) | void uart_send_string(char *str) {
  function uart_init (line 27) | void uart_init(void) {
  function putc (line 56) | void putc(void *p, char c) { uart_send(c); }

FILE: exercises/lesson04/1/rs/src/mm.c
  function get_free_page (line 7) | unsigned long get_free_page() {
  function free_page (line 17) | void free_page(unsigned long p) { mem_map[(p - LOW_MEMORY) / PAGE_SIZE] ...

FILE: exercises/lesson04/1/rs/src/printf.c
  function uli2a (line 30) | static void uli2a(unsigned long int num, unsigned int base, int uc, char...
  function li2a (line 47) | static void li2a(long num, char *bf) {
  function ui2a (line 57) | static void ui2a(unsigned int num, unsigned int base, int uc, char *bf) {
  function i2a (line 74) | static void i2a(int num, char *bf) {
  function a2d (line 82) | static int a2d(char ch) {
  function a2i (line 93) | static char a2i(char ch, char **src, int base, int *nump) {
  function putchw (line 108) | static void putchw(void *putp, putcf putf, int n, char z, char *bf) {
  function tfp_format (line 120) | void tfp_format(void *putp, putcf putf, char *fmt, va_list va) {
  function init_printf (line 197) | void init_printf(void *putp, void (*putf)(void *, char)) {
  function tfp_printf (line 202) | void tfp_printf(char *fmt, ...) {
  function putcp (line 209) | static void putcp(void *p, char c) { *(*((char **)p))++ = c; }
  function tfp_sprintf (line 211) | void tfp_sprintf(char *s, char *fmt, ...) {

FILE: exercises/lesson04/1/rs/src/sched.c
  type task_struct (line 5) | struct task_struct
  type task_struct (line 6) | struct task_struct
  type task_struct (line 7) | struct task_struct
  function preempt_disable (line 12) | void preempt_disable(void) { current->preempt_count++; }
  function preempt_enable (line 14) | void preempt_enable(void) { current->preempt_count--; }
  function print_debug_tasks (line 16) | void print_debug_tasks(void) {
  function _schedule (line 27) | void _schedule(void) {
  function schedule (line 59) | void schedule(void) {
  function switch_to (line 64) | void switch_to(struct task_struct *next) {
  function schedule_tail (line 72) | void schedule_tail(void) { preempt_enable(); }
  function timer_tick (line 74) | void timer_tick() {

FILE: exercises/lesson04/1/rs/src/timer.c
  function timer_init (line 9) | void timer_init(void) {
  function handle_timer_irq (line 15) | void handle_timer_irq(void) {

FILE: exercises/lesson04/2/avenito/include/sched.h
  type task_struct (line 17) | struct task_struct
  type task_struct (line 18) | struct task_struct
  type cpu_context (line 21) | struct cpu_context {
  type task_struct (line 37) | struct task_struct {
  type task_struct (line 50) | struct task_struct
  type task_struct (line 51) | struct task_struct
  type task_struct (line 51) | struct task_struct

FILE: exercises/lesson04/2/avenito/src/fork.c
  function copy_process (line 8) | int copy_process(unsigned long fn, unsigned long arg, unsigned int pri)

FILE: exercises/lesson04/2/avenito/src/irq.c
  function enable_interrupt_controller (line 29) | void enable_interrupt_controller()
  function show_invalid_entry_message (line 34) | void show_invalid_entry_message(int type, unsigned long esr, unsigned lo...
  function handle_irq (line 39) | void handle_irq(void)

FILE: exercises/lesson04/2/avenito/src/kernel.c
  function process (line 9) | void process(char *array)
  function kernel_main (line 19) | void kernel_main(void)

FILE: exercises/lesson04/2/avenito/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )
  function putc (line 59) | void putc ( void* p, char c)

FILE: exercises/lesson04/2/avenito/src/mm.c
  function get_free_page (line 5) | unsigned long get_free_page()
  function free_page (line 16) | void free_page(unsigned long p){

FILE: exercises/lesson04/2/avenito/src/printf.c
  function uli2a (line 31) | static void uli2a(unsigned long int num, unsigned int base, int uc,char ...
  function li2a (line 49) | static void li2a (long num, char * bf)
  function ui2a (line 60) | static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
  function i2a (line 78) | static void i2a (int num, char * bf)
  function a2d (line 87) | static int a2d(char ch)
  function a2i (line 98) | static char a2i(char ch, char** src,int base,int* nump)
  function putchw (line 113) | static void putchw(void* putp,putcf putf,int n, char z, char* bf)
  function tfp_format (line 126) | void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
  function init_printf (line 205) | void init_printf(void* putp,void (*putf) (void*,char))
  function tfp_printf (line 211) | void tfp_printf(char *fmt, ...)
  function putcp (line 219) | static void putcp(void* p,char c)
  function tfp_sprintf (line 226) | void tfp_sprintf(char* s,char *fmt, ...)

FILE: exercises/lesson04/2/avenito/src/sched.c
  type task_struct (line 5) | struct task_struct
  type task_struct (line 6) | struct task_struct
  type task_struct (line 7) | struct task_struct
  function preempt_disable (line 10) | void preempt_disable(void)
  function preempt_enable (line 15) | void preempt_enable(void)
  function _schedule (line 21) | void _schedule(void)
  function schedule (line 50) | void schedule(void)
  function switch_to (line 56) | void switch_to(struct task_struct * next)
  function schedule_tail (line 77) | void schedule_tail(void) {
  function timer_tick (line 82) | void timer_tick()

FILE: exercises/lesson04/2/avenito/src/timer.c
  function timer_init (line 9) | void timer_init ( void )
  function handle_timer_irq (line 16) | void handle_timer_irq( void )

FILE: exercises/lesson04/2/bl4ckout31/include/sched.h
  type task_struct (line 17) | struct task_struct
  type task_struct (line 18) | struct task_struct
  type cpu_context (line 21) | struct cpu_context {
  type task_struct (line 37) | struct task_struct {
  type task_struct (line 50) | struct task_struct
  type task_struct (line 51) | struct task_struct
  type task_struct (line 51) | struct task_struct

FILE: exercises/lesson04/2/bl4ckout31/src/fork.c
  function copy_process (line 5) | int copy_process(unsigned long fn, unsigned int priority, unsigned long ...

FILE: exercises/lesson04/2/bl4ckout31/src/irq.c
  function enable_interrupt_controller (line 29) | void enable_interrupt_controller()
  function show_invalid_entry_message (line 34) | void show_invalid_entry_message(int type, unsigned long esr, unsigned lo...
  function handle_irq (line 39) | void handle_irq(void)

FILE: exercises/lesson04/2/bl4ckout31/src/kernel.c
  function process (line 9) | void process(char *array)
  function kernel_main (line 19) | void kernel_main(void)

FILE: exercises/lesson04/2/bl4ckout31/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )
  function putc (line 59) | void putc ( void* p, char c)

FILE: exercises/lesson04/2/bl4ckout31/src/mm.c
  function get_free_page (line 5) | unsigned long get_free_page()
  function free_page (line 16) | void free_page(unsigned long p){

FILE: exercises/lesson04/2/bl4ckout31/src/printf.c
  function uli2a (line 31) | static void uli2a(unsigned long int num, unsigned int base, int uc,char ...
  function li2a (line 49) | static void li2a (long num, char * bf)
  function ui2a (line 60) | static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
  function i2a (line 78) | static void i2a (int num, char * bf)
  function a2d (line 87) | static int a2d(char ch)
  function a2i (line 98) | static char a2i(char ch, char** src,int base,int* nump)
  function putchw (line 113) | static void putchw(void* putp,putcf putf,int n, char z, char* bf)
  function tfp_format (line 126) | void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
  function init_printf (line 205) | void init_printf(void* putp,void (*putf) (void*,char))
  function tfp_printf (line 211) | void tfp_printf(char *fmt, ...)
  function putcp (line 219) | static void putcp(void* p,char c)
  function tfp_sprintf (line 226) | void tfp_sprintf(char* s,char *fmt, ...)

FILE: exercises/lesson04/2/bl4ckout31/src/sched.c
  type task_struct (line 5) | struct task_struct
  type task_struct (line 6) | struct task_struct
  type task_struct (line 7) | struct task_struct
  function preempt_disable (line 10) | void preempt_disable(void)
  function preempt_enable (line 15) | void preempt_enable(void)
  function _schedule (line 21) | void _schedule(void)
  function schedule (line 50) | void schedule(void)
  function switch_to (line 56) | void switch_to(struct task_struct * next)
  function schedule_tail (line 65) | void schedule_tail(void) {
  function timer_tick (line 70) | void timer_tick()

FILE: exercises/lesson04/2/bl4ckout31/src/timer.c
  function timer_init (line 9) | void timer_init ( void )
  function handle_timer_irq (line 16) | void handle_timer_irq( void )

FILE: exercises/lesson04/2/rs/include/sched.h
  type task_struct (line 17) | struct task_struct
  type task_struct (line 18) | struct task_struct
  type cpu_context (line 21) | struct cpu_context {
  type task_struct (line 37) | struct task_struct {
  type task_struct (line 50) | struct task_struct
  type task_struct (line 51) | struct task_struct
  type task_struct (line 51) | struct task_struct

FILE: exercises/lesson04/2/rs/src/fork.c
  function copy_process (line 5) | int copy_process(unsigned long fn, unsigned long arg, long pri) {

FILE: exercises/lesson04/2/rs/src/irq.c
  function enable_interrupt_controller (line 20) | void enable_interrupt_controller() { put32(ENABLE_IRQS_1, SYSTEM_TIMER_I...
  function show_invalid_entry_message (line 22) | void show_invalid_entry_message(int type, unsigned long esr,
  function handle_irq (line 28) | void handle_irq(void) {

FILE: exercises/lesson04/2/rs/src/kernel.c
  function process (line 9) | void process(char *array) {
  function kernel_main (line 18) | void kernel_main(void) {

FILE: exercises/lesson04/2/rs/src/mini_uart.c
  function uart_send (line 5) | void uart_send(char c) {
  function uart_recv (line 13) | char uart_recv(void) {
  function uart_send_string (line 21) | void uart_send_string(char *str) {
  function uart_init (line 27) | void uart_init(void) {
  function putc (line 56) | void putc(void *p, char c) { uart_send(c); }

FILE: exercises/lesson04/2/rs/src/mm.c
  function get_free_page (line 7) | unsigned long get_free_page() {
  function free_page (line 17) | void free_page(unsigned long p) { mem_map[(p - LOW_MEMORY) / PAGE_SIZE] ...

FILE: exercises/lesson04/2/rs/src/printf.c
  function uli2a (line 30) | static void uli2a(unsigned long int num, unsigned int base, int uc, char...
  function li2a (line 47) | static void li2a(long num, char *bf) {
  function ui2a (line 57) | static void ui2a(unsigned int num, unsigned int base, int uc, char *bf) {
  function i2a (line 74) | static void i2a(int num, char *bf) {
  function a2d (line 82) | static int a2d(char ch) {
  function a2i (line 93) | static char a2i(char ch, char **src, int base, int *nump) {
  function putchw (line 108) | static void putchw(void *putp, putcf putf, int n, char z, char *bf) {
  function tfp_format (line 120) | void tfp_format(void *putp, putcf putf, char *fmt, va_list va) {
  function init_printf (line 197) | void init_printf(void *putp, void (*putf)(void *, char)) {
  function tfp_printf (line 202) | void tfp_printf(char *fmt, ...) {
  function putcp (line 209) | static void putcp(void *p, char c) { *(*((char **)p))++ = c; }
  function tfp_sprintf (line 211) | void tfp_sprintf(char *s, char *fmt, ...) {

FILE: exercises/lesson04/2/rs/src/sched.c
  type task_struct (line 5) | struct task_struct
  type task_struct (line 6) | struct task_struct
  type task_struct (line 7) | struct task_struct
  function preempt_disable (line 12) | void preempt_disable(void) { current->preempt_count++; }
  function preempt_enable (line 14) | void preempt_enable(void) { current->preempt_count--; }
  function _schedule (line 16) | void _schedule(void) {
  function schedule (line 44) | void schedule(void) {
  function switch_to (line 49) | void switch_to(struct task_struct *next) {
  function schedule_tail (line 57) | void schedule_tail(void) { preempt_enable(); }
  function timer_tick (line 59) | void timer_tick() {

FILE: exercises/lesson04/2/rs/src/timer.c
  function timer_init (line 9) | void timer_init(void) {
  function handle_timer_irq (line 15) | void handle_timer_irq(void) {

FILE: exercises/lesson04/3/avenito/include/sched.h
  type task_struct (line 19) | struct task_struct
  type task_struct (line 20) | struct task_struct
  type fpsimd_context (line 24) | struct fpsimd_context {
  type cpu_context (line 30) | struct cpu_context {
  type task_struct (line 46) | struct task_struct {
  type task_struct (line 60) | struct task_struct
  type task_struct (line 61) | struct task_struct
  type task_struct (line 61) | struct task_struct

FILE: exercises/lesson04/3/avenito/src/fork.c
  function copy_process (line 6) | int copy_process(unsigned long fn, unsigned long arg)

FILE: exercises/lesson04/3/avenito/src/irq.c
  function enable_interrupt_controller (line 29) | void enable_interrupt_controller()
  function show_invalid_entry_message (line 34) | void show_invalid_entry_message(int type, unsigned long esr, unsigned lo...
  function handle_irq (line 39) | void handle_irq(void)

FILE: exercises/lesson04/3/avenito/src/kernel.c
  function process (line 9) | void process(char *array)
  function kernel_main (line 19) | void kernel_main(void)

FILE: exercises/lesson04/3/avenito/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )
  function putc (line 59) | void putc ( void* p, char c)

FILE: exercises/lesson04/3/avenito/src/mm.c
  function get_free_page (line 5) | unsigned long get_free_page()
  function free_page (line 16) | void free_page(unsigned long p){

FILE: exercises/lesson04/3/avenito/src/printf.c
  function uli2a (line 31) | static void uli2a(unsigned long int num, unsigned int base, int uc,char ...
  function li2a (line 49) | static void li2a (long num, char * bf)
  function ui2a (line 60) | static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
  function i2a (line 78) | static void i2a (int num, char * bf)
  function a2d (line 87) | static int a2d(char ch)
  function a2i (line 98) | static char a2i(char ch, char** src,int base,int* nump)
  function putchw (line 113) | static void putchw(void* putp,putcf putf,int n, char z, char* bf)
  function tfp_format (line 126) | void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
  function init_printf (line 205) | void init_printf(void* putp,void (*putf) (void*,char))
  function tfp_printf (line 211) | void tfp_printf(char *fmt, ...)
  function putcp (line 219) | static void putcp(void* p,char c)
  function tfp_sprintf (line 226) | void tfp_sprintf(char* s,char *fmt, ...)

FILE: exercises/lesson04/3/avenito/src/sched.c
  type task_struct (line 5) | struct task_struct
  type task_struct (line 6) | struct task_struct
  type task_struct (line 7) | struct task_struct
  function preempt_disable (line 10) | void preempt_disable(void)
  function preempt_enable (line 15) | void preempt_enable(void)
  function _schedule (line 21) | void _schedule(void)
  function schedule (line 50) | void schedule(void)
  function switch_to (line 56) | void switch_to(struct task_struct * next)
  function schedule_tail (line 77) | void schedule_tail(void) {
  function timer_tick (line 82) | void timer_tick()

FILE: exercises/lesson04/3/avenito/src/timer.c
  function timer_init (line 9) | void timer_init ( void )
  function handle_timer_irq (line 16) | void handle_timer_irq( void )

FILE: exercises/lesson04/3/bl4ckout31/include/sched.h
  type task_struct (line 18) | struct task_struct
  type task_struct (line 19) | struct task_struct
  type cpu_context (line 22) | struct cpu_context {
  type fpsimd_context (line 38) | struct fpsimd_context {
  type task_struct (line 44) | struct task_struct {
  type task_struct (line 58) | struct task_struct
  type task_struct (line 59) | struct task_struct
  type task_struct (line 59) | struct task_struct

FILE: exercises/lesson04/3/bl4ckout31/src/fork.c
  function copy_process (line 5) | int copy_process(unsigned long fn, unsigned long arg)

FILE: exercises/lesson04/3/bl4ckout31/src/irq.c
  function enable_interrupt_controller (line 29) | void enable_interrupt_controller()
  function show_invalid_entry_message (line 34) | void show_invalid_entry_message(int type, unsigned long esr, unsigned lo...
  function handle_irq (line 39) | void handle_irq(void)

FILE: exercises/lesson04/3/bl4ckout31/src/kernel.c
  function process (line 10) | void process(char *array)
  function kernel_main (line 37) | void kernel_main(void)

FILE: exercises/lesson04/3/bl4ckout31/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )
  function putc (line 59) | void putc ( void* p, char c)

FILE: exercises/lesson04/3/bl4ckout31/src/mm.c
  function get_free_page (line 5) | unsigned long get_free_page()
  function free_page (line 16) | void free_page(unsigned long p){

FILE: exercises/lesson04/3/bl4ckout31/src/printf.c
  function uli2a (line 31) | static void uli2a(unsigned long int num, unsigned int base, int uc,char ...
  function li2a (line 49) | static void li2a (long num, char * bf)
  function ui2a (line 60) | static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
  function i2a (line 78) | static void i2a (int num, char * bf)
  function a2d (line 87) | static int a2d(char ch)
  function a2i (line 98) | static char a2i(char ch, char** src,int base,int* nump)
  function putchw (line 113) | static void putchw(void* putp,putcf putf,int n, char z, char* bf)
  function tfp_format (line 126) | void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
  function init_printf (line 205) | void init_printf(void* putp,void (*putf) (void*,char))
  function tfp_printf (line 211) | void tfp_printf(char *fmt, ...)
  function putcp (line 219) | static void putcp(void* p,char c)
  function tfp_sprintf (line 226) | void tfp_sprintf(char* s,char *fmt, ...)

FILE: exercises/lesson04/3/bl4ckout31/src/sched.c
  type task_struct (line 5) | struct task_struct
  type task_struct (line 6) | struct task_struct
  type task_struct (line 7) | struct task_struct
  function preempt_disable (line 10) | void preempt_disable(void)
  function preempt_enable (line 15) | void preempt_enable(void)
  function _schedule (line 21) | void _schedule(void)
  function schedule (line 50) | void schedule(void)
  function switch_to (line 56) | void switch_to(struct task_struct * next)
  function schedule_tail (line 65) | void schedule_tail(void) {
  function timer_tick (line 70) | void timer_tick()

FILE: exercises/lesson04/3/bl4ckout31/src/timer.c
  function timer_init (line 9) | void timer_init ( void )
  function handle_timer_irq (line 16) | void handle_timer_irq( void )

FILE: exercises/lesson04/4/avenito/include/sched.h
  type task_struct (line 17) | struct task_struct
  type task_struct (line 18) | struct task_struct
  type cpu_context (line 22) | struct cpu_context {
  type task_struct (line 39) | struct task_struct {
  type task_struct (line 53) | struct task_struct
  type task_struct (line 54) | struct task_struct
  type task_struct (line 54) | struct task_struct

FILE: exercises/lesson04/4/avenito/src/fork.c
  function copy_process (line 6) | int copy_process(unsigned long fn, unsigned long arg)

FILE: exercises/lesson04/4/avenito/src/irq.c
  function enable_interrupt_controller (line 29) | void enable_interrupt_controller()
  function show_invalid_entry_message (line 34) | void show_invalid_entry_message(int type, unsigned long esr, unsigned lo...
  function handle_irq (line 39) | void handle_irq(void)

FILE: exercises/lesson04/4/avenito/src/kernel.c
  function process (line 9) | void process(char *array)
  function kernel_main (line 19) | void kernel_main(void)

FILE: exercises/lesson04/4/avenito/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )
  function putc (line 59) | void putc ( void* p, char c)

FILE: exercises/lesson04/4/avenito/src/mm.c
  function get_free_page (line 5) | unsigned long get_free_page()
  function free_page (line 16) | void free_page(unsigned long p){

FILE: exercises/lesson04/4/avenito/src/printf.c
  function uli2a (line 31) | static void uli2a(unsigned long int num, unsigned int base, int uc,char ...
  function li2a (line 49) | static void li2a (long num, char * bf)
  function ui2a (line 60) | static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
  function i2a (line 78) | static void i2a (int num, char * bf)
  function a2d (line 87) | static int a2d(char ch)
  function a2i (line 98) | static char a2i(char ch, char** src,int base,int* nump)
  function putchw (line 113) | static void putchw(void* putp,putcf putf,int n, char z, char* bf)
  function tfp_format (line 126) | void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
  function init_printf (line 205) | void init_printf(void* putp,void (*putf) (void*,char))
  function tfp_printf (line 211) | void tfp_printf(char *fmt, ...)
  function putcp (line 219) | static void putcp(void* p,char c)
  function tfp_sprintf (line 226) | void tfp_sprintf(char* s,char *fmt, ...)

FILE: exercises/lesson04/4/avenito/src/sched.c
  type task_struct (line 5) | struct task_struct
  type task_struct (line 6) | struct task_struct
  type task_struct (line 8) | struct task_struct
  function preempt_disable (line 11) | void preempt_disable(void)
  function preempt_enable (line 16) | void preempt_enable(void)
  function _schedule (line 22) | void _schedule(void)
  function schedule (line 53) | void schedule(void)
  function switch_to (line 59) | void switch_to(struct task_struct * next)
  function schedule_tail (line 68) | void schedule_tail(void) {
  function timer_tick (line 73) | void timer_tick()

FILE: exercises/lesson04/4/avenito/src/timer.c
  function timer_init (line 9) | void timer_init ( void )
  function handle_timer_irq (line 16) | void handle_timer_irq( void )

FILE: exercises/lesson04/4/bl4ckout31/include/sched.h
  type task_struct (line 17) | struct task_struct
  type task_struct (line 18) | struct task_struct
  type cpu_context (line 21) | struct cpu_context {
  type task_struct (line 37) | struct task_struct {
  type task_struct (line 51) | struct task_struct
  type task_struct (line 52) | struct task_struct
  type task_struct (line 52) | struct task_struct

FILE: exercises/lesson04/4/bl4ckout31/src/fork.c
  function copy_process (line 5) | int copy_process(unsigned long fn, unsigned long arg)

FILE: exercises/lesson04/4/bl4ckout31/src/irq.c
  function enable_interrupt_controller (line 29) | void enable_interrupt_controller()
  function show_invalid_entry_message (line 34) | void show_invalid_entry_message(int type, unsigned long esr, unsigned lo...
  function handle_irq (line 39) | void handle_irq(void)

FILE: exercises/lesson04/4/bl4ckout31/src/kernel.c
  function process (line 9) | void process(char *array)
  function kernel_main (line 19) | void kernel_main(void)

FILE: exercises/lesson04/4/bl4ckout31/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )
  function putc (line 59) | void putc ( void* p, char c)

FILE: exercises/lesson04/4/bl4ckout31/src/mm.c
  function get_free_page (line 5) | unsigned long get_free_page()
  function free_page (line 16) | void free_page(unsigned long p){

FILE: exercises/lesson04/4/bl4ckout31/src/printf.c
  function uli2a (line 31) | static void uli2a(unsigned long int num, unsigned int base, int uc,char ...
  function li2a (line 49) | static void li2a (long num, char * bf)
  function ui2a (line 60) | static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
  function i2a (line 78) | static void i2a (int num, char * bf)
  function a2d (line 87) | static int a2d(char ch)
  function a2i (line 98) | static char a2i(char ch, char** src,int base,int* nump)
  function putchw (line 113) | static void putchw(void* putp,putcf putf,int n, char z, char* bf)
  function tfp_format (line 126) | void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
  function init_printf (line 205) | void init_printf(void* putp,void (*putf) (void*,char))
  function tfp_printf (line 211) | void tfp_printf(char *fmt, ...)
  function putcp (line 219) | static void putcp(void* p,char c)
  function tfp_sprintf (line 226) | void tfp_sprintf(char* s,char *fmt, ...)

FILE: exercises/lesson04/4/bl4ckout31/src/sched.c
  type task_struct (line 5) | struct task_struct
  type task_struct (line 6) | struct task_struct
  type task_struct (line 7) | struct task_struct
  function preempt_disable (line 10) | void preempt_disable(void)
  function preempt_enable (line 15) | void preempt_enable(void)
  function _schedule (line 21) | void _schedule(void)
  function schedule (line 45) | void schedule(void)
  function switch_to (line 51) | void switch_to(struct task_struct * next)
  function schedule_tail (line 60) | void schedule_tail(void) {
  function timer_tick (line 65) | void timer_tick()

FILE: exercises/lesson04/4/bl4ckout31/src/timer.c
  function timer_init (line 9) | void timer_init ( void )
  function handle_timer_irq (line 16) | void handle_timer_irq( void )

FILE: exercises/lesson04/4/rs/include/sched.h
  type task_struct (line 12) | struct task_struct
  type task_struct (line 13) | struct task_struct
  type cpu_context (line 15) | struct cpu_context {
  type task_struct (line 31) | struct task_struct {
  type task_struct (line 45) | struct task_struct
  type task_struct (line 46) | struct task_struct
  type task_struct (line 46) | struct task_struct

FILE: exercises/lesson04/4/rs/src/fork.c
  function copy_process (line 5) | int copy_process(unsigned long fn, unsigned long arg, long pri) {

FILE: exercises/lesson04/4/rs/src/irq.c
  function enable_interrupt_controller (line 20) | void enable_interrupt_controller() { put32(ENABLE_IRQS_1, SYSTEM_TIMER_I...
  function show_invalid_entry_message (line 22) | void show_invalid_entry_message(int type, unsigned long esr,
  function handle_irq (line 28) | void handle_irq(void) {

FILE: exercises/lesson04/4/rs/src/kernel.c
  function process (line 9) | void process(char *array) {
  function kernel_main (line 18) | void kernel_main(void) {

FILE: exercises/lesson04/4/rs/src/mini_uart.c
  function uart_send (line 5) | void uart_send(char c) {
  function uart_recv (line 13) | char uart_recv(void) {
  function uart_send_string (line 21) | void uart_send_string(char *str) {
  function uart_init (line 27) | void uart_init(void) {
  function putc (line 56) | void putc(void *p, char c) { uart_send(c); }

FILE: exercises/lesson04/4/rs/src/mm.c
  function get_free_page (line 7) | unsigned long get_free_page() {
  function free_page (line 17) | void free_page(unsigned long p) { mem_map[(p - LOW_MEMORY) / PAGE_SIZE] ...

FILE: exercises/lesson04/4/rs/src/printf.c
  function uli2a (line 30) | static void uli2a(unsigned long int num, unsigned int base, int uc, char...
  function li2a (line 47) | static void li2a(long num, char *bf) {
  function ui2a (line 57) | static void ui2a(unsigned int num, unsigned int base, int uc, char *bf) {
  function i2a (line 74) | static void i2a(int num, char *bf) {
  function a2d (line 82) | static int a2d(char ch) {
  function a2i (line 93) | static char a2i(char ch, char **src, int base, int *nump) {
  function putchw (line 108) | static void putchw(void *putp, putcf putf, int n, char z, char *bf) {
  function tfp_format (line 120) | void tfp_format(void *putp, putcf putf, char *fmt, va_list va) {
  function init_printf (line 197) | void init_printf(void *putp, void (*putf)(void *, char)) {
  function tfp_printf (line 202) | void tfp_printf(char *fmt, ...) {
  function putcp (line 209) | static void putcp(void *p, char c) { *(*((char **)p))++ = c; }
  function tfp_sprintf (line 211) | void tfp_sprintf(char *s, char *fmt, ...) {

FILE: exercises/lesson04/4/rs/src/sched.c
  type task_struct (line 4) | struct task_struct
  type task_struct (line 5) | struct task_struct
  type task_struct (line 6) | struct task_struct
  function preempt_disable (line 8) | void preempt_disable(void) { current->preempt_count++; }
  function preempt_enable (line 10) | void preempt_enable(void) { current->preempt_count--; }
  function _schedule (line 12) | void _schedule(void) {
  function schedule (line 37) | void schedule(void) {
  function switch_to (line 42) | void switch_to(struct task_struct *next) {
  function schedule_tail (line 50) | void schedule_tail(void) { preempt_enable(); }
  function timer_tick (line 52) | void timer_tick() {

FILE: exercises/lesson04/4/rs/src/timer.c
  function timer_init (line 9) | void timer_init(void) {
  function handle_timer_irq (line 15) | void handle_timer_irq(void) {

FILE: exercises/lesson04/5/avenito/include/sched.h
  type task_struct (line 17) | struct task_struct
  type task_struct (line 18) | struct task_struct
  type cpu_context (line 21) | struct cpu_context {
  type task_struct (line 37) | struct task_struct {
  type task_struct (line 50) | struct task_struct
  type task_struct (line 51) | struct task_struct
  type task_struct (line 51) | struct task_struct

FILE: exercises/lesson04/5/avenito/src/fork.c
  function copy_process (line 6) | int copy_process(unsigned long fn, unsigned long arg)

FILE: exercises/lesson04/5/avenito/src/irq.c
  function enable_interrupt_controller (line 30) | void enable_interrupt_controller()
  function show_invalid_entry_message (line 36) | void show_invalid_entry_message(int type, unsigned long esr, unsigned lo...
  function handle_irq (line 41) | void handle_irq(void)

FILE: exercises/lesson04/5/avenito/src/kernel.c
  function process (line 9) | void process(char *array)
  function kernel_main (line 19) | void kernel_main(void)

FILE: exercises/lesson04/5/avenito/src/mm.c
  function get_free_page (line 5) | unsigned long get_free_page()
  function free_page (line 16) | void free_page(unsigned long p){

FILE: exercises/lesson04/5/avenito/src/printf.c
  function uli2a (line 31) | static void uli2a(unsigned long int num, unsigned int base, int uc,char ...
  function li2a (line 49) | static void li2a (long num, char * bf)
  function ui2a (line 60) | static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
  function i2a (line 78) | static void i2a (int num, char * bf)
  function a2d (line 87) | static int a2d(char ch)
  function a2i (line 98) | static char a2i(char ch, char** src,int base,int* nump)
  function putchw (line 113) | static void putchw(void* putp,putcf putf,int n, char z, char* bf)
  function tfp_format (line 126) | void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
  function init_printf (line 205) | void init_printf(void* putp,void (*putf) (void*,char))
  function tfp_printf (line 211) | void tfp_printf(char *fmt, ...)
  function putcp (line 219) | static void putcp(void* p,char c)
  function tfp_sprintf (line 226) | void tfp_sprintf(char* s,char *fmt, ...)

FILE: exercises/lesson04/5/avenito/src/sched.c
  type task_struct (line 5) | struct task_struct
  type task_struct (line 6) | struct task_struct
  type task_struct (line 7) | struct task_struct
  function preempt_disable (line 10) | void preempt_disable(void)
  function preempt_enable (line 15) | void preempt_enable(void)
  function _schedule (line 21) | void _schedule(void)
  function schedule (line 50) | void schedule(void)
  function switch_to (line 56) | void switch_to(struct task_struct * next)
  function schedule_tail (line 77) | void schedule_tail(void) {
  function timer_tick (line 82) | void timer_tick()

FILE: exercises/lesson04/5/avenito/src/timer.c
  function timer_init (line 9) | void timer_init ( void )
  function handle_timer_irq (line 15) | void handle_timer_irq( void )

FILE: exercises/lesson04/5/avenito/src/uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 11) | char uart_recv ( void )
  function uart_send_string (line 17) | void uart_send_string(char* str)
  function uart_init (line 24) | void uart_init ( void )
  function putc (line 52) | void putc ( void* p, char c)

FILE: exercises/lesson04/5/bl4ckout31/include/sched.h
  type task_struct (line 17) | struct task_struct
  type task_struct (line 18) | struct task_struct
  type cpu_context (line 21) | struct cpu_context {
  type task_struct (line 37) | struct task_struct {
  type task_struct (line 50) | struct task_struct
  type task_struct (line 51) | struct task_struct
  type task_struct (line 51) | struct task_struct

FILE: exercises/lesson04/5/bl4ckout31/src/fork.c
  function copy_process (line 5) | int copy_process(unsigned long fn, unsigned long arg)

FILE: exercises/lesson04/5/bl4ckout31/src/irq.c
  function enable_interrupt_controller (line 29) | void enable_interrupt_controller()
  function show_invalid_entry_message (line 35) | void show_invalid_entry_message(int type, unsigned long esr, unsigned lo...
  function handle_irq (line 40) | void handle_irq(void)

FILE: exercises/lesson04/5/bl4ckout31/src/kernel.c
  function process (line 9) | void process(char *array)
  function kernel_main (line 19) | void kernel_main(void)

FILE: exercises/lesson04/5/bl4ckout31/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )
  function putc (line 59) | void putc ( void* p, char c)

FILE: exercises/lesson04/5/bl4ckout31/src/mm.c
  function get_free_page (line 5) | unsigned long get_free_page()
  function free_page (line 16) | void free_page(unsigned long p){

FILE: exercises/lesson04/5/bl4ckout31/src/printf.c
  function uli2a (line 31) | static void uli2a(unsigned long int num, unsigned int base, int uc,char ...
  function li2a (line 49) | static void li2a (long num, char * bf)
  function ui2a (line 60) | static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
  function i2a (line 78) | static void i2a (int num, char * bf)
  function a2d (line 87) | static int a2d(char ch)
  function a2i (line 98) | static char a2i(char ch, char** src,int base,int* nump)
  function putchw (line 113) | static void putchw(void* putp,putcf putf,int n, char z, char* bf)
  function tfp_format (line 126) | void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
  function init_printf (line 205) | void init_printf(void* putp,void (*putf) (void*,char))
  function tfp_printf (line 211) | void tfp_printf(char *fmt, ...)
  function putcp (line 219) | static void putcp(void* p,char c)
  function tfp_sprintf (line 226) | void tfp_sprintf(char* s,char *fmt, ...)

FILE: exercises/lesson04/5/bl4ckout31/src/sched.c
  type task_struct (line 5) | struct task_struct
  type task_struct (line 6) | struct task_struct
  type task_struct (line 7) | struct task_struct
  function preempt_disable (line 10) | void preempt_disable(void)
  function preempt_enable (line 15) | void preempt_enable(void)
  function _schedule (line 21) | void _schedule(void)
  function schedule (line 50) | void schedule(void)
  function switch_to (line 56) | void switch_to(struct task_struct * next)
  function schedule_tail (line 65) | void schedule_tail(void) {
  function timer_tick (line 70) | void timer_tick()

FILE: exercises/lesson04/5/bl4ckout31/src/timer.c
  function timer_init (line 10) | void timer_init ( void )
  function handle_timer_irq (line 17) | void handle_timer_irq( void )
  function generic_timer_init (line 25) | void generic_timer_init ( void )
  function handle_generic_timer_irq (line 31) | void handle_generic_timer_irq( void )

FILE: exercises/lesson05/1/avenito/include/fork.h
  type pt_regs (line 19) | struct pt_regs
  type task_struct (line 19) | struct task_struct
  type pt_regs (line 21) | struct pt_regs {

FILE: exercises/lesson05/1/avenito/include/sched.h
  type task_struct (line 20) | struct task_struct
  type task_struct (line 21) | struct task_struct
  type cpu_context (line 24) | struct cpu_context {
  type task_struct (line 40) | struct task_struct {
  type task_struct (line 55) | struct task_struct
  type task_struct (line 56) | struct task_struct
  type task_struct (line 56) | struct task_struct

FILE: exercises/lesson05/1/avenito/src/fork.c
  function copy_process (line 8) | int copy_process(unsigned long clone_flags, unsigned long fn, unsigned l...
  function move_to_user_mode (line 47) | int move_to_user_mode(unsigned long pc)
  type pt_regs (line 62) | struct pt_regs
  type task_struct (line 62) | struct task_struct
  type pt_regs (line 63) | struct pt_regs
  type pt_regs (line 64) | struct pt_regs

FILE: exercises/lesson05/1/avenito/src/irq.c
  function enable_interrupt_controller (line 32) | void enable_interrupt_controller()
  function show_invalid_entry_message (line 37) | void show_invalid_entry_message(int type, unsigned long esr, unsigned lo...
  function handle_irq (line 42) | void handle_irq(void)

FILE: exercises/lesson05/1/avenito/src/kernel.c
  function user_process1 (line 10) | void user_process1(char *array)
  function user_process (line 22) | void user_process(){
  function kernel_process (line 49) | void kernel_process(){
  function kernel_main (line 58) | void kernel_main(void)

FILE: exercises/lesson05/1/avenito/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )
  function putc (line 59) | void putc ( void* p, char c)

FILE: exercises/lesson05/1/avenito/src/mm.c
  function get_free_page (line 5) | unsigned long get_free_page()
  function free_page (line 16) | void free_page(unsigned long p){

FILE: exercises/lesson05/1/avenito/src/printf.c
  function uli2a (line 31) | static void uli2a(unsigned long int num, unsigned int base, int uc,char ...
  function li2a (line 49) | static void li2a (long num, char * bf)
  function ui2a (line 60) | static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
  function i2a (line 78) | static void i2a (int num, char * bf)
  function a2d (line 87) | static int a2d(char ch)
  function a2i (line 98) | static char a2i(char ch, char** src,int base,int* nump)
  function putchw (line 113) | static void putchw(void* putp,putcf putf,int n, char z, char* bf)
  function tfp_format (line 126) | void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
  function init_printf (line 205) | void init_printf(void* putp,void (*putf) (void*,char))
  function tfp_printf (line 211) | void tfp_printf(char *fmt, ...)
  function putcp (line 219) | static void putcp(void* p,char c)
  function tfp_sprintf (line 226) | void tfp_sprintf(char* s,char *fmt, ...)

FILE: exercises/lesson05/1/avenito/src/sched.c
  type task_struct (line 8) | struct task_struct
  type task_struct (line 9) | struct task_struct
  type task_struct (line 10) | struct task_struct
  function preempt_disable (line 13) | void preempt_disable(void)
  function preempt_enable (line 18) | void preempt_enable(void)
  function _schedule (line 24) | void _schedule(void)
  function schedule (line 53) | void schedule(void)
  function switch_to (line 60) | void switch_to(struct task_struct * next, int index)
  function schedule_tail (line 69) | void schedule_tail(void) {
  function timer_tick (line 73) | void timer_tick()
  function exit_process (line 85) | void exit_process(){

FILE: exercises/lesson05/1/avenito/src/sys.c
  function sys_write (line 7) | void sys_write(char * buf){
  function sys_clone (line 11) | int sys_clone(unsigned long stack){
  function sys_malloc (line 15) | unsigned long sys_malloc(){
  function sys_exit (line 23) | void sys_exit(){

FILE: exercises/lesson05/1/avenito/src/timer.c
  function timer_init (line 9) | void timer_init ( void )
  function handle_timer_irq (line 16) | void handle_timer_irq( void )

FILE: exercises/lesson05/1/bl4ckout31/include/fork.h
  type pt_regs (line 19) | struct pt_regs
  type task_struct (line 19) | struct task_struct
  type pt_regs (line 21) | struct pt_regs {

FILE: exercises/lesson05/1/bl4ckout31/include/sched.h
  type task_struct (line 20) | struct task_struct
  type task_struct (line 21) | struct task_struct
  type cpu_context (line 24) | struct cpu_context {
  type task_struct (line 40) | struct task_struct {
  type task_struct (line 55) | struct task_struct
  type task_struct (line 56) | struct task_struct
  type task_struct (line 56) | struct task_struct

FILE: exercises/lesson05/1/bl4ckout31/src/fork.c
  function copy_process (line 8) | int copy_process(unsigned long clone_flags, unsigned long fn, unsigned l...
  function move_to_user_mode (line 47) | int move_to_user_mode(unsigned long pc)
  type pt_regs (line 62) | struct pt_regs
  type task_struct (line 62) | struct task_struct
  type pt_regs (line 63) | struct pt_regs
  type pt_regs (line 64) | struct pt_regs

FILE: exercises/lesson05/1/bl4ckout31/src/irq.c
  function enable_interrupt_controller (line 31) | void enable_interrupt_controller()
  function show_invalid_entry_message (line 36) | void show_invalid_entry_message(int type, unsigned long esr, unsigned lo...
  function show_trapped_sys_instr (line 41) | void show_trapped_sys_instr() {
  function handle_irq (line 45) | void handle_irq(void)

FILE: exercises/lesson05/1/bl4ckout31/src/kernel.c
  function user_process1 (line 10) | void user_process1(char *array)
  function user_process (line 26) | void user_process(){
  function kernel_process (line 53) | void kernel_process(){
  function kernel_main (line 62) | void kernel_main(void)

FILE: exercises/lesson05/1/bl4ckout31/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )
  function putc (line 59) | void putc ( void* p, char c)

FILE: exercises/lesson05/1/bl4ckout31/src/mm.c
  function get_free_page (line 5) | unsigned long get_free_page()
  function free_page (line 16) | void free_page(unsigned long p){

FILE: exercises/lesson05/1/bl4ckout31/src/printf.c
  function uli2a (line 31) | static void uli2a(unsigned long int num, unsigned int base, int uc,char ...
  function li2a (line 49) | static void li2a (long num, char * bf)
  function ui2a (line 60) | static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
  function i2a (line 78) | static void i2a (int num, char * bf)
  function a2d (line 87) | static int a2d(char ch)
  function a2i (line 98) | static char a2i(char ch, char** src,int base,int* nump)
  function putchw (line 113) | static void putchw(void* putp,putcf putf,int n, char z, char* bf)
  function tfp_format (line 126) | void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
  function init_printf (line 205) | void init_printf(void* putp,void (*putf) (void*,char))
  function tfp_printf (line 211) | void tfp_printf(char *fmt, ...)
  function putcp (line 219) | static void putcp(void* p,char c)
  function tfp_sprintf (line 226) | void tfp_sprintf(char* s,char *fmt, ...)

FILE: exercises/lesson05/1/bl4ckout31/src/sched.c
  type task_struct (line 8) | struct task_struct
  type task_struct (line 9) | struct task_struct
  type task_struct (line 10) | struct task_struct
  function preempt_disable (line 13) | void preempt_disable(void)
  function preempt_enable (line 18) | void preempt_enable(void)
  function _schedule (line 24) | void _schedule(void)
  function schedule (line 53) | void schedule(void)
  function switch_to (line 60) | void switch_to(struct task_struct * next, int index)
  function schedule_tail (line 69) | void schedule_tail(void) {
  function timer_tick (line 73) | void timer_tick()
  function exit_process (line 85) | void exit_process(){

FILE: exercises/lesson05/1/bl4ckout31/src/sys.c
  function sys_write (line 7) | void sys_write(char * buf){
  function sys_clone (line 11) | int sys_clone(unsigned long stack){
  function sys_malloc (line 15) | unsigned long sys_malloc(){
  function sys_exit (line 23) | void sys_exit(){

FILE: exercises/lesson05/1/bl4ckout31/src/timer.c
  function timer_init (line 9) | void timer_init ( void )
  function handle_timer_irq (line 16) | void handle_timer_irq( void )

FILE: exercises/lesson05/1/xdfm1/include/fork.h
  type pt_regs (line 19) | struct pt_regs
  type task_struct (line 19) | struct task_struct
  type pt_regs (line 21) | struct pt_regs {

FILE: exercises/lesson05/1/xdfm1/include/sched.h
  type task_struct (line 20) | struct task_struct
  type task_struct (line 21) | struct task_struct
  type cpu_context (line 24) | struct cpu_context {
  type task_struct (line 40) | struct task_struct {
  type task_struct (line 55) | struct task_struct
  type task_struct (line 56) | struct task_struct
  type task_struct (line 56) | struct task_struct

FILE: exercises/lesson05/1/xdfm1/src/fork.c
  function copy_process (line 8) | int copy_process(unsigned long clone_flags, unsigned long fn, unsigned l...
  function move_to_user_mode (line 47) | int move_to_user_mode(unsigned long pc)
  type pt_regs (line 62) | struct pt_regs
  type task_struct (line 62) | struct task_struct
  type pt_regs (line 63) | struct pt_regs
  type pt_regs (line 64) | struct pt_regs

FILE: exercises/lesson05/1/xdfm1/src/irq.c
  function enable_interrupt_controller (line 30) | void enable_interrupt_controller()
  function show_invalid_entry_message (line 35) | void show_invalid_entry_message(int type, unsigned long esr, unsigned lo...
  function show_data_abort_message (line 40) | void show_data_abort_message(unsigned long esr, unsigned long address)
  function handle_irq (line 47) | void handle_irq(void)

FILE: exercises/lesson05/1/xdfm1/src/kernel.c
  function user_process1 (line 10) | void user_process1(char *array)
  function user_process (line 26) | void user_process(){
  function kernel_process (line 55) | void kernel_process(){
  function kernel_main (line 64) | void kernel_main(void)

FILE: exercises/lesson05/1/xdfm1/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )
  function putc (line 59) | void putc ( void* p, char c)

FILE: exercises/lesson05/1/xdfm1/src/mm.c
  function get_free_page (line 5) | unsigned long get_free_page()
  function free_page (line 16) | void free_page(unsigned long p){

FILE: exercises/lesson05/1/xdfm1/src/printf.c
  function uli2a (line 31) | static void uli2a(unsigned long int num, unsigned int base, int uc,char ...
  function li2a (line 49) | static void li2a (long num, char * bf)
  function ui2a (line 60) | static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
  function i2a (line 78) | static void i2a (int num, char * bf)
  function a2d (line 87) | static int a2d(char ch)
  function a2i (line 98) | static char a2i(char ch, char** src,int base,int* nump)
  function putchw (line 113) | static void putchw(void* putp,putcf putf,int n, char z, char* bf)
  function tfp_format (line 126) | void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
  function init_printf (line 205) | void init_printf(void* putp,void (*putf) (void*,char))
  function tfp_printf (line 211) | void tfp_printf(char *fmt, ...)
  function putcp (line 219) | static void putcp(void* p,char c)
  function tfp_sprintf (line 226) | void tfp_sprintf(char* s,char *fmt, ...)

FILE: exercises/lesson05/1/xdfm1/src/sched.c
  type task_struct (line 8) | struct task_struct
  type task_struct (line 9) | struct task_struct
  type task_struct (line 10) | struct task_struct
  function preempt_disable (line 13) | void preempt_disable(void)
  function preempt_enable (line 18) | void preempt_enable(void)
  function _schedule (line 24) | void _schedule(void)
  function schedule (line 53) | void schedule(void)
  function switch_to (line 60) | void switch_to(struct task_struct * next, int index)
  function schedule_tail (line 69) | void schedule_tail(void) {
  function timer_tick (line 73) | void timer_tick()
  function exit_process (line 85) | void exit_process(){

FILE: exercises/lesson05/1/xdfm1/src/sys.c
  function sys_write (line 7) | void sys_write(char * buf){
  function sys_clone (line 11) | int sys_clone(unsigned long stack){
  function sys_malloc (line 15) | unsigned long sys_malloc(){
  function sys_exit (line 23) | void sys_exit(){

FILE: exercises/lesson05/1/xdfm1/src/timer.c
  function timer_init (line 9) | void timer_init ( void )
  function handle_timer_irq (line 16) | void handle_timer_irq( void )

FILE: exercises/lesson05/2/avenito/include/fork.h
  type pt_regs (line 19) | struct pt_regs
  type task_struct (line 19) | struct task_struct
  type pt_regs (line 21) | struct pt_regs {

FILE: exercises/lesson05/2/avenito/include/sched.h
  type task_struct (line 20) | struct task_struct
  type task_struct (line 21) | struct task_struct
  type cpu_context (line 24) | struct cpu_context {
  type task_struct (line 40) | struct task_struct {
  type task_struct (line 55) | struct task_struct
  type task_struct (line 56) | struct task_struct
  type task_struct (line 56) | struct task_struct

FILE: exercises/lesson05/2/avenito/src/fork.c
  function copy_process (line 8) | int copy_process(unsigned long clone_flags, unsigned long fn, unsigned l...
  function move_to_user_mode (line 47) | int move_to_user_mode(unsigned long pc)
  type pt_regs (line 62) | struct pt_regs
  type task_struct (line 62) | struct task_struct
  type pt_regs (line 63) | struct pt_regs
  type pt_regs (line 64) | struct pt_regs

FILE: exercises/lesson05/2/avenito/src/irq.c
  function enable_interrupt_controller (line 32) | void enable_interrupt_controller()
  function show_invalid_entry_message (line 37) | void show_invalid_entry_message(int type, unsigned long esr, unsigned lo...
  function handle_irq (line 42) | void handle_irq(void)

FILE: exercises/lesson05/2/avenito/src/kernel.c
  function user_process1 (line 10) | void user_process1(char *array)
  function user_process (line 22) | void user_process(){
  function kernel_process (line 49) | void kernel_process(){
  function kernel_main (line 58) | void kernel_main(void)

FILE: exercises/lesson05/2/avenito/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )
  function putc (line 59) | void putc ( void* p, char c)

FILE: exercises/lesson05/2/avenito/src/mm.c
  function get_free_page (line 5) | unsigned long get_free_page()
  function free_page (line 16) | void free_page(unsigned long p){

FILE: exercises/lesson05/2/avenito/src/printf.c
  function uli2a (line 31) | static void uli2a(unsigned long int num, unsigned int base, int uc,char ...
  function li2a (line 49) | static void li2a (long num, char * bf)
  function ui2a (line 60) | static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
  function i2a (line 78) | static void i2a (int num, char * bf)
  function a2d (line 87) | static int a2d(char ch)
  function a2i (line 98) | static char a2i(char ch, char** src,int base,int* nump)
  function putchw (line 113) | static void putchw(void* putp,putcf putf,int n, char z, char* bf)
  function tfp_format (line 126) | void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
  function init_printf (line 205) | void init_printf(void* putp,void (*putf) (void*,char))
  function tfp_printf (line 211) | void tfp_printf(char *fmt, ...)
  function putcp (line 219) | static void putcp(void* p,char c)
  function tfp_sprintf (line 226) | void tfp_sprintf(char* s,char *fmt, ...)

FILE: exercises/lesson05/2/avenito/src/sched.c
  type task_struct (line 8) | struct task_struct
  type task_struct (line 9) | struct task_struct
  type task_struct (line 10) | struct task_struct
  function preempt_disable (line 13) | void preempt_disable(void)
  function preempt_enable (line 18) | void preempt_enable(void)
  function _schedule (line 24) | void _schedule(void)
  function schedule (line 53) | void schedule(void)
  function switch_to (line 60) | void switch_to(struct task_struct * next, int index)
  function schedule_tail (line 69) | void schedule_tail(void) {
  function timer_tick (line 73) | void timer_tick()
  function exit_process (line 85) | void exit_process(){

FILE: exercises/lesson05/2/avenito/src/sys.c
  function sys_write (line 7) | void sys_write(char * buf){
  function sys_clone (line 11) | int sys_clone(unsigned long stack){
  function sys_malloc (line 15) | unsigned long sys_malloc(){
  function sys_exit (line 23) | void sys_exit(){

FILE: exercises/lesson05/2/avenito/src/timer.c
  function timer_init (line 9) | void timer_init ( void )
  function handle_timer_irq (line 16) | void handle_timer_irq( void )

FILE: exercises/lesson05/2/bl4ckout31/include/fork.h
  type pt_regs (line 19) | struct pt_regs
  type task_struct (line 19) | struct task_struct
  type pt_regs (line 21) | struct pt_regs {

FILE: exercises/lesson05/2/bl4ckout31/include/sched.h
  type task_struct (line 20) | struct task_struct
  type task_struct (line 21) | struct task_struct
  type cpu_context (line 24) | struct cpu_context {
  type task_struct (line 40) | struct task_struct {
  type task_struct (line 55) | struct task_struct
  type task_struct (line 56) | struct task_struct
  type task_struct (line 56) | struct task_struct

FILE: exercises/lesson05/2/bl4ckout31/src/fork.c
  function copy_process (line 8) | int copy_process(unsigned long clone_flags, unsigned long fn, unsigned l...
  function move_to_user_mode (line 47) | int move_to_user_mode(unsigned long pc)
  type pt_regs (line 62) | struct pt_regs
  type task_struct (line 62) | struct task_struct
  type pt_regs (line 63) | struct pt_regs
  type pt_regs (line 64) | struct pt_regs

FILE: exercises/lesson05/2/bl4ckout31/src/irq.c
  function enable_interrupt_controller (line 29) | void enable_interrupt_controller()
  function show_invalid_entry_message (line 34) | void show_invalid_entry_message(int type, unsigned long esr, unsigned lo...
  function handle_irq (line 39) | void handle_irq(void)

FILE: exercises/lesson05/2/bl4ckout31/src/kernel.c
  function user_process1 (line 10) | void user_process1(char *array)
  function user_process (line 29) | void user_process(){
  function kernel_process (line 56) | void kernel_process(){
  function kernel_main (line 65) | void kernel_main(void)

FILE: exercises/lesson05/2/bl4ckout31/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )
  function putc (line 59) | void putc ( void* p, char c)

FILE: exercises/lesson05/2/bl4ckout31/src/mm.c
  function get_free_page (line 5) | unsigned long get_free_page()
  function free_page (line 16) | void free_page(unsigned long p){

FILE: exercises/lesson05/2/bl4ckout31/src/printf.c
  function uli2a (line 31) | static void uli2a(unsigned long int num, unsigned int base, int uc,char ...
  function li2a (line 49) | static void li2a (long num, char * bf)
  function ui2a (line 60) | static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
  function i2a (line 78) | static void i2a (int num, char * bf)
  function a2d (line 87) | static int a2d(char ch)
  function a2i (line 98) | static char a2i(char ch, char** src,int base,int* nump)
  function putchw (line 113) | static void putchw(void* putp,putcf putf,int n, char z, char* bf)
  function tfp_format (line 126) | void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
  function init_printf (line 205) | void init_printf(void* putp,void (*putf) (void*,char))
  function tfp_printf (line 211) | void tfp_printf(char *fmt, ...)
  function putcp (line 219) | static void putcp(void* p,char c)
  function tfp_sprintf (line 226) | void tfp_sprintf(char* s,char *fmt, ...)

FILE: exercises/lesson05/2/bl4ckout31/src/sched.c
  type task_struct (line 8) | struct task_struct
  type task_struct (line 9) | struct task_struct
  type task_struct (line 10) | struct task_struct
  function preempt_disable (line 13) | void preempt_disable(void)
  function preempt_enable (line 18) | void preempt_enable(void)
  function _schedule (line 24) | void _schedule(void)
  function schedule (line 53) | void schedule(void)
  function switch_to (line 60) | void switch_to(struct task_struct * next, int index)
  function schedule_tail (line 69) | void schedule_tail(void) {
  function timer_tick (line 73) | void timer_tick()
  function exit_process (line 85) | void exit_process(){

FILE: exercises/lesson05/2/bl4ckout31/src/sys.c
  function sys_write (line 7) | void sys_write(char * buf){
  function sys_clone (line 11) | int sys_clone(unsigned long stack){
  function sys_malloc (line 15) | unsigned long sys_malloc(){
  function sys_exit (line 23) | void sys_exit(){
  function sys_priority (line 27) | void sys_priority(long priority) {

FILE: exercises/lesson05/2/bl4ckout31/src/timer.c
  function timer_init (line 9) | void timer_init ( void )
  function handle_timer_irq (line 16) | void handle_timer_irq( void )

FILE: exercises/lesson05/2/xdfm1/include/fork.h
  type pt_regs (line 19) | struct pt_regs
  type task_struct (line 19) | struct task_struct
  type pt_regs (line 21) | struct pt_regs {

FILE: exercises/lesson05/2/xdfm1/include/sched.h
  type task_struct (line 20) | struct task_struct
  type task_struct (line 21) | struct task_struct
  type cpu_context (line 24) | struct cpu_context {
  type task_struct (line 40) | struct task_struct {
  type task_struct (line 55) | struct task_struct
  type task_struct (line 56) | struct task_struct
  type task_struct (line 56) | struct task_struct

FILE: exercises/lesson05/2/xdfm1/src/fork.c
  function copy_process (line 8) | int copy_process(unsigned long clone_flags, unsigned long fn, unsigned l...
  function move_to_user_mode (line 47) | int move_to_user_mode(unsigned long pc)
  type pt_regs (line 62) | struct pt_regs
  type task_struct (line 62) | struct task_struct
  type pt_regs (line 63) | struct pt_regs
  type pt_regs (line 64) | struct pt_regs

FILE: exercises/lesson05/2/xdfm1/src/irq.c
  function enable_interrupt_controller (line 29) | void enable_interrupt_controller()
  function show_invalid_entry_message (line 34) | void show_invalid_entry_message(int type, unsigned long esr, unsigned lo...
  function handle_irq (line 39) | void handle_irq(void)

FILE: exercises/lesson05/2/xdfm1/src/kernel.c
  function user_process1 (line 10) | void user_process1(char *array)
  function user_process (line 23) | void user_process(){
  function kernel_process (line 52) | void kernel_process(){
  function kernel_main (line 61) | void kernel_main(void)

FILE: exercises/lesson05/2/xdfm1/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )
  function putc (line 59) | void putc ( void* p, char c)

FILE: exercises/lesson05/2/xdfm1/src/mm.c
  function get_free_page (line 5) | unsigned long get_free_page()
  function free_page (line 16) | void free_page(unsigned long p){

FILE: exercises/lesson05/2/xdfm1/src/printf.c
  function uli2a (line 31) | static void uli2a(unsigned long int num, unsigned int base, int uc,char ...
  function li2a (line 49) | static void li2a (long num, char * bf)
  function ui2a (line 60) | static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
  function i2a (line 78) | static void i2a (int num, char * bf)
  function a2d (line 87) | static int a2d(char ch)
  function a2i (line 98) | static char a2i(char ch, char** src,int base,int* nump)
  function putchw (line 113) | static void putchw(void* putp,putcf putf,int n, char z, char* bf)
  function tfp_format (line 126) | void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
  function init_printf (line 205) | void init_printf(void* putp,void (*putf) (void*,char))
  function tfp_printf (line 211) | void tfp_printf(char *fmt, ...)
  function putcp (line 219) | static void putcp(void* p,char c)
  function tfp_sprintf (line 226) | void tfp_sprintf(char* s,char *fmt, ...)

FILE: exercises/lesson05/2/xdfm1/src/sched.c
  type task_struct (line 8) | struct task_struct
  type task_struct (line 9) | struct task_struct
  type task_struct (line 10) | struct task_struct
  function preempt_disable (line 13) | void preempt_disable(void)
  function preempt_enable (line 18) | void preempt_enable(void)
  function _schedule (line 24) | void _schedule(void)
  function schedule (line 53) | void schedule(void)
  function switch_to (line 60) | void switch_to(struct task_struct * next, int index)
  function schedule_tail (line 69) | void schedule_tail(void) {
  function timer_tick (line 73) | void timer_tick()
  function exit_process (line 85) | void exit_process(){

FILE: exercises/lesson05/2/xdfm1/src/sys.c
  function sys_write (line 7) | void sys_write(char * buf){
  function sys_clone (line 11) | int sys_clone(unsigned long stack){
  function sys_malloc (line 15) | unsigned long sys_malloc(){
  function sys_exit (line 23) | void sys_exit(){
  function sys_priority (line 27) | void sys_priority(int pid, unsigned long priority)

FILE: exercises/lesson05/2/xdfm1/src/timer.c
  function timer_init (line 9) | void timer_init ( void )
  function handle_timer_irq (line 16) | void handle_timer_irq( void )

FILE: exercises/lesson05/3/avenito/include/fork.h
  type pt_regs (line 19) | struct pt_regs
  type task_struct (line 19) | struct task_struct
  type pt_regs (line 21) | struct pt_regs {

FILE: exercises/lesson05/3/avenito/include/sched.h
  type task_struct (line 20) | struct task_struct
  type task_struct (line 21) | struct task_struct
  type cpu_context (line 24) | struct cpu_context {
  type task_struct (line 40) | struct task_struct {
  type task_struct (line 55) | struct task_struct
  type task_struct (line 56) | struct task_struct
  type task_struct (line 56) | struct task_struct

FILE: exercises/lesson05/3/avenito/src/fork.c
  function copy_process (line 8) | int copy_process(unsigned long clone_flags, unsigned long fn, unsigned l...
  function move_to_user_mode (line 47) | int move_to_user_mode(unsigned long pc)
  type pt_regs (line 62) | struct pt_regs
  type task_struct (line 62) | struct task_struct
  type pt_regs (line 63) | struct pt_regs
  type pt_regs (line 64) | struct pt_regs

FILE: exercises/lesson05/3/avenito/src/irq.c
  function enable_interrupt_controller (line 32) | void enable_interrupt_controller()
  function show_invalid_entry_message (line 37) | void show_invalid_entry_message(int type, unsigned long esr, unsigned lo...
  function handle_irq (line 42) | void handle_irq(void)

FILE: exercises/lesson05/3/avenito/src/kernel.c
  function user_process1 (line 10) | void user_process1(char *array)
  function user_process (line 22) | void user_process(){
  function kernel_process (line 49) | void kernel_process(){
  function kernel_main (line 58) | void kernel_main(void)

FILE: exercises/lesson05/3/avenito/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )
  function putc (line 59) | void putc ( void* p, char c)

FILE: exercises/lesson05/3/avenito/src/mm.c
  function get_free_page (line 5) | unsigned long get_free_page()
  function free_page (line 16) | void free_page(unsigned long p){

FILE: exercises/lesson05/3/avenito/src/printf.c
  function uli2a (line 31) | static void uli2a(unsigned long int num, unsigned int base, int uc,char ...
  function li2a (line 49) | static void li2a (long num, char * bf)
  function ui2a (line 60) | static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
  function i2a (line 78) | static void i2a (int num, char * bf)
  function a2d (line 87) | static int a2d(char ch)
  function a2i (line 98) | static char a2i(char ch, char** src,int base,int* nump)
  function putchw (line 113) | static void putchw(void* putp,putcf putf,int n, char z, char* bf)
  function tfp_format (line 126) | void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
  function init_printf (line 205) | void init_printf(void* putp,void (*putf) (void*,char))
  function tfp_printf (line 211) | void tfp_printf(char *fmt, ...)
  function putcp (line 219) | static void putcp(void* p,char c)
  function tfp_sprintf (line 226) | void tfp_sprintf(char* s,char *fmt, ...)

FILE: exercises/lesson05/3/avenito/src/sched.c
  type task_struct (line 8) | struct task_struct
  type task_struct (line 9) | struct task_struct
  type task_struct (line 10) | struct task_struct
  function preempt_disable (line 13) | void preempt_disable(void)
  function preempt_enable (line 18) | void preempt_enable(void)
  function _schedule (line 24) | void _schedule(void)
  function schedule (line 53) | void schedule(void)
  function switch_to (line 60) | void switch_to(struct task_struct * next, int index)
  function schedule_tail (line 69) | void schedule_tail(void) {
  function timer_tick (line 73) | void timer_tick()
  function exit_process (line 85) | void exit_process(){

FILE: exercises/lesson05/3/avenito/src/sys.c
  function sys_write (line 7) | void sys_write(char * buf){
  function sys_clone (line 11) | int sys_clone(unsigned long stack){
  function sys_malloc (line 15) | unsigned long sys_malloc(){
  function sys_exit (line 23) | void sys_exit(){

FILE: exercises/lesson05/3/avenito/src/timer.c
  function timer_init (line 9) | void timer_init ( void )
  function handle_timer_irq (line 16) | void handle_timer_irq( void )

FILE: exercises/lesson05/3/bl4ckout31/include/fork.h
  type pt_regs (line 19) | struct pt_regs
  type task_struct (line 19) | struct task_struct
  type pt_regs (line 21) | struct pt_regs {

FILE: exercises/lesson05/3/bl4ckout31/include/sched.h
  type task_struct (line 20) | struct task_struct
  type task_struct (line 21) | struct task_struct
  type cpu_context (line 24) | struct cpu_context {
  type task_struct (line 40) | struct task_struct {
  type task_struct (line 55) | struct task_struct
  type task_struct (line 56) | struct task_struct
  type task_struct (line 56) | struct task_struct

FILE: exercises/lesson05/3/bl4ckout31/src/fork.c
  function copy_process (line 8) | int copy_process(unsigned long clone_flags, unsigned long fn, unsigned l...
  function move_to_user_mode (line 47) | int move_to_user_mode(unsigned long pc)
  type pt_regs (line 62) | struct pt_regs
  type task_struct (line 62) | struct task_struct
  type pt_regs (line 63) | struct pt_regs
  type pt_regs (line 64) | struct pt_regs

FILE: exercises/lesson05/3/bl4ckout31/src/irq.c
  function enable_interrupt_controller (line 29) | void enable_interrupt_controller()
  function show_invalid_entry_message (line 35) | void show_invalid_entry_message(int type, unsigned long esr, unsigned lo...
  function handle_irq (line 40) | void handle_irq(void)

FILE: exercises/lesson05/3/bl4ckout31/src/kernel.c
  function user_process1 (line 10) | void user_process1(char *array)
  function user_process (line 22) | void user_process(){
  function kernel_process (line 49) | void kernel_process(){
  function kernel_main (line 58) | void kernel_main(void)

FILE: exercises/lesson05/3/bl4ckout31/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )
  function putc (line 59) | void putc ( void* p, char c)

FILE: exercises/lesson05/3/bl4ckout31/src/mm.c
  function get_free_page (line 5) | unsigned long get_free_page()
  function free_page (line 16) | void free_page(unsigned long p){

FILE: exercises/lesson05/3/bl4ckout31/src/printf.c
  function uli2a (line 31) | static void uli2a(unsigned long int num, unsigned int base, int uc,char ...
  function li2a (line 49) | static void li2a (long num, char * bf)
  function ui2a (line 60) | static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
  function i2a (line 78) | static void i2a (int num, char * bf)
  function a2d (line 87) | static int a2d(char ch)
  function a2i (line 98) | static char a2i(char ch, char** src,int base,int* nump)
  function putchw (line 113) | static void putchw(void* putp,putcf putf,int n, char z, char* bf)
  function tfp_format (line 126) | void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
  function init_printf (line 205) | void init_printf(void* putp,void (*putf) (void*,char))
  function tfp_printf (line 211) | void tfp_printf(char *fmt, ...)
  function putcp (line 219) | static void putcp(void* p,char c)
  function tfp_sprintf (line 226) | void tfp_sprintf(char* s,char *fmt, ...)

FILE: exercises/lesson05/3/bl4ckout31/src/sched.c
  type task_struct (line 8) | struct task_struct
  type task_struct (line 9) | struct task_struct
  type task_struct (line 10) | struct task_struct
  function preempt_disable (line 13) | void preempt_disable(void)
  function preempt_enable (line 18) | void preempt_enable(void)
  function _schedule (line 24) | void _schedule(void)
  function schedule (line 53) | void schedule(void)
  function switch_to (line 60) | void switch_to(struct task_struct * next, int index)
  function schedule_tail (line 69) | void schedule_tail(void) {
  function timer_tick (line 73) | void timer_tick()
  function exit_process (line 85) | void exit_process(){

FILE: exercises/lesson05/3/bl4ckout31/src/sys.c
  function sys_write (line 7) | void sys_write(char * buf){
  function sys_clone (line 11) | int sys_clone(unsigned long stack){
  function sys_malloc (line 15) | unsigned long sys_malloc(){
  function sys_exit (line 23) | void sys_exit(){

FILE: exercises/lesson05/3/bl4ckout31/src/timer.c
  function timer_init (line 10) | void timer_init ( void )
  function handle_timer_irq (line 17) | void handle_timer_irq( void )
  function generic_timer_init (line 25) | void generic_timer_init ( void )
  function handle_generic_timer_irq (line 31) | void handle_generic_timer_irq( void )

FILE: exercises/lesson06/1/xdfm1/include/fork.h
  type pt_regs (line 19) | struct pt_regs
  type task_struct (line 19) | struct task_struct
  type pt_regs (line 21) | struct pt_regs {

FILE: exercises/lesson06/1/xdfm1/include/mm.h
  type task_struct (line 38) | struct task_struct
  type task_struct (line 42) | struct task_struct
  type task_struct (line 44) | struct task_struct

FILE: exercises/lesson06/1/xdfm1/include/sched.h
  type task_struct (line 21) | struct task_struct
  type task_struct (line 22) | struct task_struct
  type cpu_context (line 25) | struct cpu_context {
  type user_page (line 43) | struct user_page {
  type mm_struct (line 48) | struct mm_struct {
  type task_struct (line 56) | struct task_struct {
  type task_struct (line 71) | struct task_struct
  type task_struct (line 72) | struct task_struct
  type task_struct (line 72) | struct task_struct

FILE: exercises/lesson06/1/xdfm1/src/fork.c
  function copy_process (line 7) | int copy_process(unsigned long clone_flags, unsigned long fn, unsigned l...
  function move_to_user_mode (line 44) | int move_to_user_mode(unsigned long start, unsigned long size, unsigned ...
  type pt_regs (line 59) | struct pt_regs
  type task_struct (line 59) | struct task_struct
  type pt_regs (line 61) | struct pt_regs
  type pt_regs (line 62) | struct pt_regs

FILE: exercises/lesson06/1/xdfm1/src/irq.c
  function enable_interrupt_controller (line 29) | void enable_interrupt_controller()
  function show_invalid_entry_message (line 34) | void show_invalid_entry_message(int type, unsigned long esr, unsigned lo...
  function handle_irq (line 39) | void handle_irq(void)

FILE: exercises/lesson06/1/xdfm1/src/kernel.c
  function kernel_process (line 15) | void kernel_process(){
  function kernel_main (line 27) | void kernel_main()

FILE: exercises/lesson06/1/xdfm1/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )
  function putc (line 59) | void putc ( void* p, char c)

FILE: exercises/lesson06/1/xdfm1/src/mm.c
  function allocate_kernel_page (line 6) | unsigned long allocate_kernel_page() {
  function allocate_user_page (line 14) | unsigned long allocate_user_page(struct task_struct *task, unsigned long...
  function get_free_page (line 23) | unsigned long get_free_page()
  function free_page (line 36) | void free_page(unsigned long p){
  function map_table_entry (line 40) | void map_table_entry(unsigned long *pte, unsigned long va, unsigned long...
  function map_table (line 47) | unsigned long map_table(unsigned long *table, unsigned long shift, unsig...
  function map_page (line 62) | void map_page(struct task_struct *task, unsigned long va, unsigned long ...
  function copy_virt_memory (line 87) | int copy_virt_memory(struct task_struct *dst) {
  function do_mem_abort (line 101) | int do_mem_abort(unsigned long addr, unsigned long esr) {

FILE: exercises/lesson06/1/xdfm1/src/printf.c
  function uli2a (line 31) | static void uli2a(unsigned long int num, unsigned int base, int uc,char ...
  function li2a (line 49) | static void li2a (long num, char * bf)
  function ui2a (line 60) | static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
  function i2a (line 78) | static void i2a (int num, char * bf)
  function a2d (line 87) | static int a2d(char ch)
  function a2i (line 98) | static char a2i(char ch, char** src,int base,int* nump)
  function putchw (line 113) | static void putchw(void* putp,putcf putf,int n, char z, char* bf)
  function tfp_format (line 126) | void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
  function init_printf (line 205) | void init_printf(void* putp,void (*putf) (void*,char))
  function tfp_printf (line 211) | void tfp_printf(char *fmt, ...)
  function putcp (line 219) | static void putcp(void* p,char c)
  function tfp_sprintf (line 226) | void tfp_sprintf(char* s,char *fmt, ...)

FILE: exercises/lesson06/1/xdfm1/src/sched.c
  type task_struct (line 7) | struct task_struct
  type task_struct (line 8) | struct task_struct
  type task_struct (line 9) | struct task_struct
  function preempt_disable (line 12) | void preempt_disable(void)
  function preempt_enable (line 17) | void preempt_enable(void)
  function _schedule (line 23) | void _schedule(void)
  function schedule (line 52) | void schedule(void)
  function switch_to (line 59) | void switch_to(struct task_struct * next)
  function schedule_tail (line 69) | void schedule_tail(void) {
  function timer_tick (line 74) | void timer_tick()
  function exit_process (line 86) | void exit_process(){

FILE: exercises/lesson06/1/xdfm1/src/sys.c
  function sys_write (line 8) | void sys_write(char * buf){
  function sys_fork (line 12) | int sys_fork(){
  function sys_exit (line 16) | void sys_exit(){

FILE: exercises/lesson06/1/xdfm1/src/timer.c
  function timer_init (line 9) | void timer_init ( void )
  function handle_timer_irq (line 16) | void handle_timer_irq( void )

FILE: exercises/lesson06/1/xdfm1/src/user.c
  function loop (line 5) | void loop(char* str)
  function user_process (line 17) | void user_process()

FILE: src/lesson01/src/kernel.c
  function kernel_main (line 3) | void kernel_main(void)

FILE: src/lesson01/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )

FILE: src/lesson02/src/kernel.c
  function kernel_main (line 5) | void kernel_main(void)

FILE: src/lesson02/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )
  function putc (line 59) | void putc ( void* p, char c)

FILE: src/lesson02/src/printf.c
  function uli2a (line 31) | static void uli2a(unsigned long int num, unsigned int base, int uc,char ...
  function li2a (line 49) | static void li2a (long num, char * bf)
  function ui2a (line 60) | static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
  function i2a (line 78) | static void i2a (int num, char * bf)
  function a2d (line 87) | static int a2d(char ch)
  function a2i (line 98) | static char a2i(char ch, char** src,int base,int* nump)
  function putchw (line 113) | static void putchw(void* putp,putcf putf,int n, char z, char* bf)
  function tfp_format (line 126) | void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
  function init_printf (line 205) | void init_printf(void* putp,void (*putf) (void*,char))
  function tfp_printf (line 211) | void tfp_printf(char *fmt, ...)
  function putcp (line 219) | static void putcp(void* p,char c)
  function tfp_sprintf (line 226) | void tfp_sprintf(char* s,char *fmt, ...)

FILE: src/lesson03/src/irq.c
  function enable_interrupt_controller (line 29) | void enable_interrupt_controller()
  function show_invalid_entry_message (line 34) | void show_invalid_entry_message(int type, unsigned long esr, unsigned lo...
  function handle_irq (line 39) | void handle_irq(void)

FILE: src/lesson03/src/kernel.c
  function kernel_main (line 7) | void kernel_main(void)

FILE: src/lesson03/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )
  function putc (line 59) | void putc ( void* p, char c)

FILE: src/lesson03/src/printf.c
  function uli2a (line 31) | static void uli2a(unsigned long int num, unsigned int base, int uc,char ...
  function li2a (line 49) | static void li2a (long num, char * bf)
  function ui2a (line 60) | static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
  function i2a (line 78) | static void i2a (int num, char * bf)
  function a2d (line 87) | static int a2d(char ch)
  function a2i (line 98) | static char a2i(char ch, char** src,int base,int* nump)
  function putchw (line 113) | static void putchw(void* putp,putcf putf,int n, char z, char* bf)
  function tfp_format (line 126) | void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
  function init_printf (line 205) | void init_printf(void* putp,void (*putf) (void*,char))
  function tfp_printf (line 211) | void tfp_printf(char *fmt, ...)
  function putcp (line 219) | static void putcp(void* p,char c)
  function tfp_sprintf (line 226) | void tfp_sprintf(char* s,char *fmt, ...)

FILE: src/lesson03/src/timer.c
  function timer_init (line 8) | void timer_init ( void )
  function handle_timer_irq (line 15) | void handle_timer_irq( void )

FILE: src/lesson04/include/sched.h
  type task_struct (line 17) | struct task_struct
  type task_struct (line 18) | struct task_struct
  type cpu_context (line 21) | struct cpu_context {
  type task_struct (line 37) | struct task_struct {
  type task_struct (line 50) | struct task_struct
  type task_struct (line 51) | struct task_struct
  type task_struct (line 51) | struct task_struct

FILE: src/lesson04/src/fork.c
  function copy_process (line 5) | int copy_process(unsigned long fn, unsigned long arg)

FILE: src/lesson04/src/irq.c
  function enable_interrupt_controller (line 29) | void enable_interrupt_controller()
  function show_invalid_entry_message (line 34) | void show_invalid_entry_message(int type, unsigned long esr, unsigned lo...
  function handle_irq (line 39) | void handle_irq(void)

FILE: src/lesson04/src/kernel.c
  function process (line 9) | void process(char *array)
  function kernel_main (line 19) | void kernel_main(void)

FILE: src/lesson04/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )
  function putc (line 59) | void putc ( void* p, char c)

FILE: src/lesson04/src/mm.c
  function get_free_page (line 5) | unsigned long get_free_page()
  function free_page (line 16) | void free_page(unsigned long p){

FILE: src/lesson04/src/printf.c
  function uli2a (line 31) | static void uli2a(unsigned long int num, unsigned int base, int uc,char ...
  function li2a (line 49) | static void li2a (long num, char * bf)
  function ui2a (line 60) | static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
  function i2a (line 78) | static void i2a (int num, char * bf)
  function a2d (line 87) | static int a2d(char ch)
  function a2i (line 98) | static char a2i(char ch, char** src,int base,int* nump)
  function putchw (line 113) | static void putchw(void* putp,putcf putf,int n, char z, char* bf)
  function tfp_format (line 126) | void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
  function init_printf (line 205) | void init_printf(void* putp,void (*putf) (void*,char))
  function tfp_printf (line 211) | void tfp_printf(char *fmt, ...)
  function putcp (line 219) | static void putcp(void* p,char c)
  function tfp_sprintf (line 226) | void tfp_sprintf(char* s,char *fmt, ...)

FILE: src/lesson04/src/sched.c
  type task_struct (line 5) | struct task_struct
  type task_struct (line 6) | struct task_struct
  type task_struct (line 7) | struct task_struct
  function preempt_disable (line 10) | void preempt_disable(void)
  function preempt_enable (line 15) | void preempt_enable(void)
  function _schedule (line 21) | void _schedule(void)
  function schedule (line 50) | void schedule(void)
  function switch_to (line 56) | void switch_to(struct task_struct * next)
  function schedule_tail (line 65) | void schedule_tail(void) {
  function timer_tick (line 70) | void timer_tick()

FILE: src/lesson04/src/timer.c
  function timer_init (line 9) | void timer_init ( void )
  function handle_timer_irq (line 16) | void handle_timer_irq( void )

FILE: src/lesson05/include/fork.h
  type pt_regs (line 19) | struct pt_regs
  type task_struct (line 19) | struct task_struct
  type pt_regs (line 21) | struct pt_regs {

FILE: src/lesson05/include/sched.h
  type task_struct (line 20) | struct task_struct
  type task_struct (line 21) | struct task_struct
  type cpu_context (line 24) | struct cpu_context {
  type task_struct (line 40) | struct task_struct {
  type task_struct (line 55) | struct task_struct
  type task_struct (line 56) | struct task_struct
  type task_struct (line 56) | struct task_struct

FILE: src/lesson05/src/fork.c
  function copy_process (line 8) | int copy_process(unsigned long clone_flags, unsigned long fn, unsigned l...
  function move_to_user_mode (line 47) | int move_to_user_mode(unsigned long pc)
  type pt_regs (line 62) | struct pt_regs
  type task_struct (line 62) | struct task_struct
  type pt_regs (line 63) | struct pt_regs
  type pt_regs (line 64) | struct pt_regs

FILE: src/lesson05/src/irq.c
  function enable_interrupt_controller (line 32) | void enable_interrupt_controller()
  function show_invalid_entry_message (line 37) | void show_invalid_entry_message(int type, unsigned long esr, unsigned lo...
  function handle_irq (line 42) | void handle_irq(void)

FILE: src/lesson05/src/kernel.c
  function user_process1 (line 10) | void user_process1(char *array)
  function user_process (line 22) | void user_process(){
  function kernel_process (line 49) | void kernel_process(){
  function kernel_main (line 58) | void kernel_main(void)

FILE: src/lesson05/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )
  function putc (line 59) | void putc ( void* p, char c)

FILE: src/lesson05/src/mm.c
  function get_free_page (line 5) | unsigned long get_free_page()
  function free_page (line 16) | void free_page(unsigned long p){

FILE: src/lesson05/src/printf.c
  function uli2a (line 31) | static void uli2a(unsigned long int num, unsigned int base, int uc,char ...
  function li2a (line 49) | static void li2a (long num, char * bf)
  function ui2a (line 60) | static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
  function i2a (line 78) | static void i2a (int num, char * bf)
  function a2d (line 87) | static int a2d(char ch)
  function a2i (line 98) | static char a2i(char ch, char** src,int base,int* nump)
  function putchw (line 113) | static void putchw(void* putp,putcf putf,int n, char z, char* bf)
  function tfp_format (line 126) | void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
  function init_printf (line 205) | void init_printf(void* putp,void (*putf) (void*,char))
  function tfp_printf (line 211) | void tfp_printf(char *fmt, ...)
  function putcp (line 219) | static void putcp(void* p,char c)
  function tfp_sprintf (line 226) | void tfp_sprintf(char* s,char *fmt, ...)

FILE: src/lesson05/src/sched.c
  type task_struct (line 8) | struct task_struct
  type task_struct (line 9) | struct task_struct
  type task_struct (line 10) | struct task_struct
  function preempt_disable (line 13) | void preempt_disable(void)
  function preempt_enable (line 18) | void preempt_enable(void)
  function _schedule (line 24) | void _schedule(void)
  function schedule (line 53) | void schedule(void)
  function switch_to (line 60) | void switch_to(struct task_struct * next, int index)
  function schedule_tail (line 69) | void schedule_tail(void) {
  function timer_tick (line 73) | void timer_tick()
  function exit_process (line 85) | void exit_process(){

FILE: src/lesson05/src/sys.c
  function sys_write (line 7) | void sys_write(char * buf){
  function sys_clone (line 11) | int sys_clone(unsigned long stack){
  function sys_malloc (line 15) | unsigned long sys_malloc(){
  function sys_exit (line 23) | void sys_exit(){

FILE: src/lesson05/src/timer.c
  function timer_init (line 9) | void timer_init ( void )
  function handle_timer_irq (line 16) | void handle_timer_irq( void )

FILE: src/lesson06/include/fork.h
  type pt_regs (line 19) | struct pt_regs
  type task_struct (line 19) | struct task_struct
  type pt_regs (line 21) | struct pt_regs {

FILE: src/lesson06/include/mm.h
  type task_struct (line 38) | struct task_struct
  type task_struct (line 42) | struct task_struct
  type task_struct (line 44) | struct task_struct

FILE: src/lesson06/include/sched.h
  type task_struct (line 21) | struct task_struct
  type task_struct (line 22) | struct task_struct
  type cpu_context (line 25) | struct cpu_context {
  type user_page (line 43) | struct user_page {
  type mm_struct (line 48) | struct mm_struct {
  type task_struct (line 56) | struct task_struct {
  type task_struct (line 71) | struct task_struct
  type task_struct (line 72) | struct task_struct
  type task_struct (line 72) | struct task_struct

FILE: src/lesson06/src/fork.c
  function copy_process (line 7) | int copy_process(unsigned long clone_flags, unsigned long fn, unsigned l...
  function move_to_user_mode (line 44) | int move_to_user_mode(unsigned long start, unsigned long size, unsigned ...
  type pt_regs (line 59) | struct pt_regs
  type task_struct (line 59) | struct task_struct
  type pt_regs (line 61) | struct pt_regs
  type pt_regs (line 62) | struct pt_regs

FILE: src/lesson06/src/irq.c
  function enable_interrupt_controller (line 32) | void enable_interrupt_controller()
  function show_invalid_entry_message (line 37) | void show_invalid_entry_message(int type, unsigned long esr, unsigned lo...
  function handle_irq (line 42) | void handle_irq(void)

FILE: src/lesson06/src/kernel.c
  function kernel_process (line 15) | void kernel_process(){
  function kernel_main (line 27) | void kernel_main()

FILE: src/lesson06/src/mini_uart.c
  function uart_send (line 5) | void uart_send ( char c )
  function uart_recv (line 14) | char uart_recv ( void )
  function uart_send_string (line 23) | void uart_send_string(char* str)
  function uart_init (line 30) | void uart_init ( void )
  function putc (line 59) | void putc ( void* p, char c)

FILE: src/lesson06/src/mm.c
  function allocate_kernel_page (line 6) | unsigned long allocate_kernel_page() {
  function allocate_user_page (line 14) | unsigned long allocate_user_page(struct task_struct *task, unsigned long...
  function get_free_page (line 23) | unsigned long get_free_page()
  function free_page (line 36) | void free_page(unsigned long p){
  function map_table_entry (line 40) | void map_table_entry(unsigned long *pte, unsigned long va, unsigned long...
  function map_table (line 47) | unsigned long map_table(unsigned long *table, unsigned long shift, unsig...
  function map_page (line 62) | void map_page(struct task_struct *task, unsigned long va, unsigned long ...
  function copy_virt_memory (line 87) | int copy_virt_memory(struct task_struct *dst) {
  function do_mem_abort (line 101) | int do_mem_abort(unsigned long addr, unsigned long esr) {

FILE: src/lesson06/src/printf.c
  function uli2a (line 31) | static void uli2a(unsigned long int num, unsigned int base, int uc,char ...
  function li2a (line 49) | static void li2a (long num, char * bf)
  function ui2a (line 60) | static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
  function i2a (line 78) | static void i2a (int num, char * bf)
  function a2d (line 87) | static int a2d(char ch)
  function a2i (line 98) | static char a2i(char ch, char** src,int base,int* nump)
  function putchw (line 113) | static void putchw(void* putp,putcf putf,int n, char z, char* bf)
  function tfp_format (line 126) | void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
  function init_printf (line 205) | void init_printf(void* putp,void (*putf) (void*,char))
  function tfp_printf (line 211) | void tfp_printf(char *fmt, ...)
  function putcp (line 219) | static void putcp(void* p,char c)
  function tfp_sprintf (line 226) | void tfp_sprintf(char* s,char *fmt, ...)

FILE: src/lesson06/src/sched.c
  type task_struct (line 7) | struct task_struct
  type task_struct (line 8) | struct task_struct
  type task_struct (line 9) | struct task_struct
  function preempt_disable (line 12) | void preempt_disable(void)
  function preempt_enable (line 17) | void preempt_enable(void)
  function _schedule (line 23) | void _schedule(void)
  function schedule (line 52) | void schedule(void)
  function switch_to (line 59) | void switch_to(struct task_struct * next)
  function schedule_tail (line 69) | void schedule_tail(void) {
  function timer_tick (line 74) | void timer_tick()
  function exit_process (line 86) | void exit_process(){

FILE: src/lesson06/src/sys.c
  function sys_write (line 8) | void sys_write(char * buf){
  function sys_fork (line 12) | int sys_fork(){
  function sys_exit (line 16) | void sys_exit(){

FILE: src/lesson06/src/timer.c
  function timer_init (line 9) | void timer_init ( void )
  function handle_timer_irq (line 16) | void handle_timer_irq( void )

FILE: src/lesson06/src/user.c
  function loop (line 5) | void loop(char* str)
  function user_process (line 17) | void user_process()
Condensed preview — 2526 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (3,186K chars).
[
  {
    "path": ".gitignore",
    "chars": 107,
    "preview": "backup/*\nsrc/*/build\n**/*.o\n**/*.d\n**/*.swp\n**/*.img\n**/*.elf\n\n# gnu global files\nGPATH\nGRTAGS\nGSYMS\nGTAGS\n"
  },
  {
    "path": "Dockerfile",
    "chars": 153,
    "preview": "FROM ubuntu:16.04\nMAINTAINER Sergey Matyukevich <s-matyukevich@gmail.com>\nRUN apt-get update && apt-get install -y gcc-a"
  },
  {
    "path": "LICENSE",
    "chars": 1075,
    "preview": "MIT License\n\nCopyright (c) 2018 Sergey Matyukevich\n\nPermission is hereby granted, free of charge, to any person obtainin"
  },
  {
    "path": "README.md",
    "chars": 4398,
    "preview": "# Learning operating system development using Linux kernel and Raspberry Pi\n\nThis repository contains a step-by-step gui"
  },
  {
    "path": "_config.yml",
    "chars": 26,
    "preview": "theme: jekyll-theme-hacker"
  },
  {
    "path": "_layouts/default.html",
    "chars": 1754,
    "preview": "<!DOCTYPE html>\n<html lang=\"{{ site.lang | default: \"en-US\" }}\">\n  <head>\n    <meta charset='utf-8'>\n    <meta http-equi"
  },
  {
    "path": "assets/css/style.scss",
    "chars": 135,
    "preview": "---\n---\n\n@import \"{{ site.theme }}\";\n\n#main_content a[target] {\n  text-decoration: none;\n}\n\nheader a.logo {\n  text-decor"
  },
  {
    "path": "docs/Contributions.md",
    "chars": 1488,
    "preview": "## Contributing to the Raspberry PI OS\n\nThe general workflow is the following:\n\n1. Find an [issue](https://github.com/s-"
  },
  {
    "path": "docs/Introduction.md",
    "chars": 10847,
    "preview": "## Raspberry Pi OS project introduction or how to efficiently learn operating system development?\n\nA few years ago, I op"
  },
  {
    "path": "docs/Prerequisites.md",
    "chars": 2612,
    "preview": "## Prerequisites\n\n### 1. [Raspberry Pi 3 Model B](https://www.raspberrypi.org/products/raspberry-pi-3-model-b/)\n\nOlder v"
  },
  {
    "path": "docs/lesson01/exercises.md",
    "chars": 1462,
    "preview": "## 1.5: Exercises.\n\nExercises are optional, though I strongly recommend you to experiment with the source code a little "
  },
  {
    "path": "docs/lesson01/linux/build-system.md",
    "chars": 19050,
    "preview": "## 1.3: Kernel build system\n\nAfter we examined Linux kernel structure, it worth spending some time investigating how we "
  },
  {
    "path": "docs/lesson01/linux/kernel-startup.md",
    "chars": 11848,
    "preview": "## 1.4: Linux startup sequence\n\n### Searching for the entry point\n\nAfter taking a look at the Linux project structure an"
  },
  {
    "path": "docs/lesson01/linux/project-structure.md",
    "chars": 3003,
    "preview": "## 1.2: Linux project structure\n\nThis is the first time we are going to talk about Linux. The idea is first to complete "
  },
  {
    "path": "docs/lesson01/rpi-os.md",
    "chars": 32961,
    "preview": "## 1.1: Introducing RPi OS, or bare-metal \"Hello, World!\"\n\nWe are going to start our journey in OS development by writin"
  },
  {
    "path": "docs/lesson02/exercises.md",
    "chars": 1065,
    "preview": "## 2.3: Exercises\n\n1. Instead of jumping directly from EL3 to EL1, try to get to EL2 first and only then switch to EL1. "
  },
  {
    "path": "docs/lesson02/linux.md",
    "chars": 17937,
    "preview": "## 2.2: Processor initialization (Linux)\n\nWe stopped our exploration of the Linux kernel at [stext](https://github.com/t"
  },
  {
    "path": "docs/lesson02/rpi-os.md",
    "chars": 14047,
    "preview": "## 2.1: Processor initialization \n\nIn this lesson, we are going to work more closely with the ARM processor. It has some"
  },
  {
    "path": "docs/lesson03/exercises.md",
    "chars": 818,
    "preview": "## 3.5: Exercises\n\n1. Use local timer instead of the system timer to generate processor interrupts. See [this](https://g"
  },
  {
    "path": "docs/lesson03/linux/interrupt_controllers.md",
    "chars": 24498,
    "preview": "## 3.3: Interrupt controllers\n\nIn this chapter, we are going to talk a lot about Linux drivers and how they handle inter"
  },
  {
    "path": "docs/lesson03/linux/low_level-exception_handling.md",
    "chars": 20678,
    "preview": "## 3.2: Low-level exception handling in Linux\n\nGiven huge Linux kernel source code, what is a good way to find the code "
  },
  {
    "path": "docs/lesson03/linux/timer.md",
    "chars": 16436,
    "preview": "## 3.4: Timers\n\nWe finished the last chapter by examining global interrupt controller. We were able to trace the path of"
  },
  {
    "path": "docs/lesson03/rpi-os.md",
    "chars": 18001,
    "preview": "## 3.1: Interrupts\n\nFrom the lesson 1, we already know how to communicate with hardware. However, most of the time the p"
  },
  {
    "path": "docs/lesson04/exercises.md",
    "chars": 1234,
    "preview": "## 4.5: Exercises\n\n1. Add `printf` to all main kernel functions to output information about the curent memory and proces"
  },
  {
    "path": "docs/lesson04/linux/basic_structures.md",
    "chars": 9315,
    "preview": "## 4.2: Scheduler basic structures\n\nIn all previous lessons we have been working mostly with either architecture specifi"
  },
  {
    "path": "docs/lesson04/linux/fork.md",
    "chars": 13821,
    "preview": "## 4.3: Forking a task\n\nScheduling is all about selecting a proper task to run from the list of available tasks. But bef"
  },
  {
    "path": "docs/lesson04/linux/scheduler.md",
    "chars": 6139,
    "preview": "## 4.4: Scheduler\n\nWe have already learned a lot of details about the Linux scheduler inner workings, so there is not so"
  },
  {
    "path": "docs/lesson04/rpi-os.md",
    "chars": 38010,
    "preview": "## 4.1: Scheduler\n\nBy now, the PRi OS is already a fairly complicated bare metal program, but to be honest, we still can"
  },
  {
    "path": "docs/lesson05/exercises.md",
    "chars": 731,
    "preview": "## 5.3: Exercises\n\n1. When a task is executed in user mode, try to access some of the system registers. Make sure that a"
  },
  {
    "path": "docs/lesson05/linux.md",
    "chars": 12952,
    "preview": "## 5.2: User processes and system calls \n\nThis chapter is going to be a short one. The reason is that I copied syscall i"
  },
  {
    "path": "docs/lesson05/rpi-os.md",
    "chars": 21565,
    "preview": "## 5.1: User processes and system calls\n\nWe have already added a lot of features to the RPi OS that makes it looks like "
  },
  {
    "path": "docs/lesson06/exercises.md",
    "chars": 486,
    "preview": "## 6.3 Exercises\n\n1. Adapt lesson 06 to run on qemu. You have to implement [identity mapping](https://wiki.osdev.org/Ide"
  },
  {
    "path": "docs/lesson06/rpi-os.md",
    "chars": 51395,
    "preview": "## 6.1: Virtual memory management\n\nThe RPi OS now can run and schedule user processes, but the isolation between them is"
  },
  {
    "path": "exercises/lesson01/1/H-4ND-H/Makefile",
    "chars": 834,
    "preview": "ARMGNU ?= aarch64-linux-gnu\n\nCOPS = -Wall -nostdlib -nostartfiles -ffreestanding -Iinclude -mgeneral-regs-only\nASMOPS = "
  },
  {
    "path": "exercises/lesson01/1/H-4ND-H/build.bat",
    "chars": 82,
    "preview": "docker run --rm -v %cd%:/app -w /app smatyukevich/raspberry-pi-os-builder make %1\n"
  },
  {
    "path": "exercises/lesson01/1/H-4ND-H/build.sh",
    "chars": 97,
    "preview": "#!/bin/bash\n\ndocker run --rm -v $(pwd):/app -w /app smatyukevich/raspberry-pi-os-builder make $1\n"
  },
  {
    "path": "exercises/lesson01/1/H-4ND-H/include/mini_uart.h",
    "chars": 181,
    "preview": "#ifndef\t_MINI_UART_H\n#define\t_MINI_UART_H\n\nvoid uart_init ( void );\nchar uart_recv ( void );\nvoid uart_send ( char c );\n"
  },
  {
    "path": "exercises/lesson01/1/H-4ND-H/include/mm.h",
    "chars": 373,
    "preview": "#ifndef\t_MM_H\n#define\t_MM_H\n\n#define PAGE_SHIFT\t \t\t12\n#define TABLE_SHIFT \t\t\t9\n#define SECTION_SHIFT\t\t\t(PAGE_SHIFT + TAB"
  },
  {
    "path": "exercises/lesson01/1/H-4ND-H/include/peripherals/base.h",
    "chars": 86,
    "preview": "#ifndef\t_P_BASE_H\n#define\t_P_BASE_H\n\n#define PBASE 0x3F000000\n\n#endif  /*_P_BASE_H */\n"
  },
  {
    "path": "exercises/lesson01/1/H-4ND-H/include/peripherals/gpio.h",
    "chars": 307,
    "preview": "#ifndef\t_P_GPIO_H\n#define\t_P_GPIO_H\n\n#include \"peripherals/base.h\"\n\n#define GPFSEL1         (PBASE+0x00200004)\n#define G"
  },
  {
    "path": "exercises/lesson01/1/H-4ND-H/include/peripherals/mini_uart.h",
    "chars": 765,
    "preview": "#ifndef\t_P_MINI_UART_H\n#define\t_P_MINI_UART_H\n\n#include \"peripherals/base.h\"\n\n#define AUX_ENABLES     (PBASE+0x00215004)"
  },
  {
    "path": "exercises/lesson01/1/H-4ND-H/include/utils.h",
    "chars": 187,
    "preview": "#ifndef\t_BOOT_H\n#define\t_BOOT_H\n\nextern void delay ( unsigned long);\nextern void put32 ( unsigned long, unsigned int );\n"
  },
  {
    "path": "exercises/lesson01/1/H-4ND-H/src/boot.S",
    "chars": 367,
    "preview": "#include \"mm.h\"\n\n.section \".text.boot\"\n\n.globl _start\n_start:\n\tmrs\tx0, mpidr_el1\t\t\n\tand\tx0, x0,#0xFF\t\t// Check processor"
  },
  {
    "path": "exercises/lesson01/1/H-4ND-H/src/config.txt",
    "chars": 40,
    "preview": "kernel_old=1\ndisable_commandline_tags=1\n"
  },
  {
    "path": "exercises/lesson01/1/H-4ND-H/src/kernel.c",
    "chars": 148,
    "preview": "#include \"mini_uart.h\"\n\nvoid kernel_main(void)\n{\n\tuart_init();\n\tuart_send_string(\"Hello, world!\\r\\n\");\n\n\twhile (1) {\n\t\tu"
  },
  {
    "path": "exercises/lesson01/1/H-4ND-H/src/linker.ld",
    "chars": 184,
    "preview": "SECTIONS\n{\n\t.text.boot : { *(.text.boot) }\n\t.text : { *(.text) }\n\t.rodata : { *(.rodata) }\n\t.data : { *(.data) }\n\t. = AL"
  },
  {
    "path": "exercises/lesson01/1/H-4ND-H/src/mini_uart.c",
    "chars": 1505,
    "preview": "#include \"utils.h\"\n#include \"peripherals/mini_uart.h\"\n#include \"peripherals/gpio.h\"\n\nvoid uart_send ( char c )\n{\n\twhile("
  },
  {
    "path": "exercises/lesson01/1/H-4ND-H/src/mm.S",
    "chars": 79,
    "preview": ".globl memzero\nmemzero:\n\tstr xzr, [x0], #8\n\tsubs x1, x1, #8\n\tb.gt memzero\n\tret\n"
  },
  {
    "path": "exercises/lesson01/1/H-4ND-H/src/utils.S",
    "chars": 131,
    "preview": ".globl put32\nput32:\n\tstr w1,[x0]\n\tret\n\n.globl get32\nget32:\n\tldr w0,[x0]\n\tret\n\n.globl delay\ndelay:\n\tsubs x0, x0, #1\n\tbne "
  },
  {
    "path": "exercises/lesson01/1/a-v-v/Makefile",
    "chars": 834,
    "preview": "ARMGNU ?= aarch64-linux-gnu\n\nCOPS = -Wall -nostdlib -nostartfiles -ffreestanding -Iinclude -mgeneral-regs-only\nASMOPS = "
  },
  {
    "path": "exercises/lesson01/1/a-v-v/build.bat",
    "chars": 82,
    "preview": "docker run --rm -v %cd%:/app -w /app smatyukevich/raspberry-pi-os-builder make %1\n"
  },
  {
    "path": "exercises/lesson01/1/a-v-v/build.sh",
    "chars": 97,
    "preview": "#!/bin/bash\n\ndocker run --rm -v $(pwd):/app -w /app smatyukevich/raspberry-pi-os-builder make $1\n"
  },
  {
    "path": "exercises/lesson01/1/a-v-v/include/mini_uart.h",
    "chars": 198,
    "preview": "#ifndef\t_MINI_UART_H\n#define\t_MINI_UART_H\n\nvoid uart_init ( unsigned int baudrate );\nchar uart_recv ( void );\nvoid uart_"
  },
  {
    "path": "exercises/lesson01/1/a-v-v/include/mm.h",
    "chars": 373,
    "preview": "#ifndef\t_MM_H\n#define\t_MM_H\n\n#define PAGE_SHIFT\t \t\t12\n#define TABLE_SHIFT \t\t\t9\n#define SECTION_SHIFT\t\t\t(PAGE_SHIFT + TAB"
  },
  {
    "path": "exercises/lesson01/1/a-v-v/include/peripherals/base.h",
    "chars": 86,
    "preview": "#ifndef\t_P_BASE_H\n#define\t_P_BASE_H\n\n#define PBASE 0x3F000000\n\n#endif  /*_P_BASE_H */\n"
  },
  {
    "path": "exercises/lesson01/1/a-v-v/include/peripherals/gpio.h",
    "chars": 307,
    "preview": "#ifndef\t_P_GPIO_H\n#define\t_P_GPIO_H\n\n#include \"peripherals/base.h\"\n\n#define GPFSEL1         (PBASE+0x00200004)\n#define G"
  },
  {
    "path": "exercises/lesson01/1/a-v-v/include/peripherals/mini_uart.h",
    "chars": 623,
    "preview": "#ifndef\t_P_MINI_UART_H\n#define\t_P_MINI_UART_H\n\n#include \"peripherals/base.h\"\n\n#define AUX_ENABLES     (PBASE+0x00215004)"
  },
  {
    "path": "exercises/lesson01/1/a-v-v/include/utils.h",
    "chars": 187,
    "preview": "#ifndef\t_BOOT_H\n#define\t_BOOT_H\n\nextern void delay ( unsigned long);\nextern void put32 ( unsigned long, unsigned int );\n"
  },
  {
    "path": "exercises/lesson01/1/a-v-v/src/boot.S",
    "chars": 367,
    "preview": "#include \"mm.h\"\n\n.section \".text.boot\"\n\n.globl _start\n_start:\n\tmrs\tx0, mpidr_el1\t\t\n\tand\tx0, x0,#0xFF\t\t// Check processor"
  },
  {
    "path": "exercises/lesson01/1/a-v-v/src/config.txt",
    "chars": 40,
    "preview": "kernel_old=1\ndisable_commandline_tags=1\n"
  },
  {
    "path": "exercises/lesson01/1/a-v-v/src/kernel.c",
    "chars": 197,
    "preview": "#include \"mini_uart.h\"\n\nvoid kernel_main(void)\n{\n\tconst unsigned int baud_rate = 460800;\n\tuart_init(baud_rate);\n\tuart_se"
  },
  {
    "path": "exercises/lesson01/1/a-v-v/src/linker.ld",
    "chars": 184,
    "preview": "SECTIONS\n{\n\t.text.boot : { *(.text.boot) }\n\t.text : { *(.text) }\n\t.rodata : { *(.rodata) }\n\t.data : { *(.data) }\n\t. = AL"
  },
  {
    "path": "exercises/lesson01/1/a-v-v/src/mini_uart.c",
    "chars": 1538,
    "preview": "#include \"utils.h\"\n#include \"peripherals/mini_uart.h\"\n#include \"peripherals/gpio.h\"\n\nvoid uart_send ( char c )\n{\n\twhile("
  },
  {
    "path": "exercises/lesson01/1/a-v-v/src/mm.S",
    "chars": 79,
    "preview": ".globl memzero\nmemzero:\n\tstr xzr, [x0], #8\n\tsubs x1, x1, #8\n\tb.gt memzero\n\tret\n"
  },
  {
    "path": "exercises/lesson01/1/a-v-v/src/utils.S",
    "chars": 131,
    "preview": ".globl put32\nput32:\n\tstr w1,[x0]\n\tret\n\n.globl get32\nget32:\n\tldr w0,[x0]\n\tret\n\n.globl delay\ndelay:\n\tsubs x0, x0, #1\n\tbne "
  },
  {
    "path": "exercises/lesson01/1/adkaster/Makefile",
    "chars": 834,
    "preview": "ARMGNU ?= aarch64-linux-gnu\n\nCOPS = -Wall -nostdlib -nostartfiles -ffreestanding -Iinclude -mgeneral-regs-only\nASMOPS = "
  },
  {
    "path": "exercises/lesson01/1/adkaster/build.bat",
    "chars": 82,
    "preview": "docker run --rm -v %cd%:/app -w /app smatyukevich/raspberry-pi-os-builder make %1\n"
  },
  {
    "path": "exercises/lesson01/1/adkaster/build.sh",
    "chars": 97,
    "preview": "#!/bin/bash\n\ndocker run --rm -v $(pwd):/app -w /app smatyukevich/raspberry-pi-os-builder make $1\n"
  },
  {
    "path": "exercises/lesson01/1/adkaster/include/mini_uart.h",
    "chars": 497,
    "preview": "#ifndef\t_MINI_UART_H\n#define\t_MINI_UART_H\n\nchar uart_recv ( void );\nvoid uart_send ( char c );\nvoid uart_send_string(cha"
  },
  {
    "path": "exercises/lesson01/1/adkaster/include/mm.h",
    "chars": 373,
    "preview": "#ifndef\t_MM_H\n#define\t_MM_H\n\n#define PAGE_SHIFT\t \t\t12\n#define TABLE_SHIFT \t\t\t9\n#define SECTION_SHIFT\t\t\t(PAGE_SHIFT + TAB"
  },
  {
    "path": "exercises/lesson01/1/adkaster/include/peripherals/base.h",
    "chars": 86,
    "preview": "#ifndef\t_P_BASE_H\n#define\t_P_BASE_H\n\n#define PBASE 0x3F000000\n\n#endif  /*_P_BASE_H */\n"
  },
  {
    "path": "exercises/lesson01/1/adkaster/include/peripherals/gpio.h",
    "chars": 307,
    "preview": "#ifndef\t_P_GPIO_H\n#define\t_P_GPIO_H\n\n#include \"peripherals/base.h\"\n\n#define GPFSEL1         (PBASE+0x00200004)\n#define G"
  },
  {
    "path": "exercises/lesson01/1/adkaster/include/peripherals/mini_uart.h",
    "chars": 623,
    "preview": "#ifndef\t_P_MINI_UART_H\n#define\t_P_MINI_UART_H\n\n#include \"peripherals/base.h\"\n\n#define AUX_ENABLES     (PBASE+0x00215004)"
  },
  {
    "path": "exercises/lesson01/1/adkaster/include/utils.h",
    "chars": 187,
    "preview": "#ifndef\t_BOOT_H\n#define\t_BOOT_H\n\nextern void delay ( unsigned long);\nextern void put32 ( unsigned long, unsigned int );\n"
  },
  {
    "path": "exercises/lesson01/1/adkaster/src/boot.S",
    "chars": 367,
    "preview": "#include \"mm.h\"\n\n.section \".text.boot\"\n\n.globl _start\n_start:\n\tmrs\tx0, mpidr_el1\t\t\n\tand\tx0, x0,#0xFF\t\t// Check processor"
  },
  {
    "path": "exercises/lesson01/1/adkaster/src/config.txt",
    "chars": 40,
    "preview": "kernel_old=1\ndisable_commandline_tags=1\n"
  },
  {
    "path": "exercises/lesson01/1/adkaster/src/kernel.c",
    "chars": 157,
    "preview": "#include \"mini_uart.h\"\n\nvoid kernel_main(void)\n{\n\tuart_init(BAUD_9600);\n\tuart_send_string(\"Hello, world!\\r\\n\");\n\n\twhile "
  },
  {
    "path": "exercises/lesson01/1/adkaster/src/linker.ld",
    "chars": 184,
    "preview": "SECTIONS\n{\n\t.text.boot : { *(.text.boot) }\n\t.text : { *(.text) }\n\t.rodata : { *(.rodata) }\n\t.data : { *(.data) }\n\t. = AL"
  },
  {
    "path": "exercises/lesson01/1/adkaster/src/mini_uart.c",
    "chars": 2021,
    "preview": "#include \"utils.h\"\n#include \"mini_uart.h\"\n#include \"peripherals/mini_uart.h\"\n#include \"peripherals/gpio.h\"\n#include <std"
  },
  {
    "path": "exercises/lesson01/1/adkaster/src/mm.S",
    "chars": 79,
    "preview": ".globl memzero\nmemzero:\n\tstr xzr, [x0], #8\n\tsubs x1, x1, #8\n\tb.gt memzero\n\tret\n"
  },
  {
    "path": "exercises/lesson01/1/adkaster/src/utils.S",
    "chars": 131,
    "preview": ".globl put32\nput32:\n\tstr w1,[x0]\n\tret\n\n.globl get32\nget32:\n\tldr w0,[x0]\n\tret\n\n.globl delay\ndelay:\n\tsubs x0, x0, #1\n\tbne "
  },
  {
    "path": "exercises/lesson01/1/avenito/Makefile",
    "chars": 834,
    "preview": "ARMGNU ?= aarch64-linux-gnu\n\nCOPS = -Wall -nostdlib -nostartfiles -ffreestanding -Iinclude -mgeneral-regs-only\nASMOPS = "
  },
  {
    "path": "exercises/lesson01/1/avenito/build.bat",
    "chars": 82,
    "preview": "docker run --rm -v %cd%:/app -w /app smatyukevich/raspberry-pi-os-builder make %1\n"
  },
  {
    "path": "exercises/lesson01/1/avenito/build.sh",
    "chars": 97,
    "preview": "#!/bin/bash\n\ndocker run --rm -v $(pwd):/app -w /app smatyukevich/raspberry-pi-os-builder make $1\n"
  },
  {
    "path": "exercises/lesson01/1/avenito/include/mini_uart.h",
    "chars": 385,
    "preview": "#ifndef\t_MINI_UART_H\n#define\t_MINI_UART_H\n\n// values according to N = (ClockFreq./(8*BAUD RATE))-1\n\n#define BAUDRATE_960"
  },
  {
    "path": "exercises/lesson01/1/avenito/include/mm.h",
    "chars": 373,
    "preview": "#ifndef\t_MM_H\n#define\t_MM_H\n\n#define PAGE_SHIFT\t \t\t12\n#define TABLE_SHIFT \t\t\t9\n#define SECTION_SHIFT\t\t\t(PAGE_SHIFT + TAB"
  },
  {
    "path": "exercises/lesson01/1/avenito/include/peripherals/base.h",
    "chars": 86,
    "preview": "#ifndef\t_P_BASE_H\n#define\t_P_BASE_H\n\n#define PBASE 0x3F000000\n\n#endif  /*_P_BASE_H */\n"
  },
  {
    "path": "exercises/lesson01/1/avenito/include/peripherals/gpio.h",
    "chars": 307,
    "preview": "#ifndef\t_P_GPIO_H\n#define\t_P_GPIO_H\n\n#include \"peripherals/base.h\"\n\n#define GPFSEL1         (PBASE+0x00200004)\n#define G"
  },
  {
    "path": "exercises/lesson01/1/avenito/include/peripherals/mini_uart.h",
    "chars": 623,
    "preview": "#ifndef\t_P_MINI_UART_H\n#define\t_P_MINI_UART_H\n\n#include \"peripherals/base.h\"\n\n#define AUX_ENABLES     (PBASE+0x00215004)"
  },
  {
    "path": "exercises/lesson01/1/avenito/include/utils.h",
    "chars": 187,
    "preview": "#ifndef\t_BOOT_H\n#define\t_BOOT_H\n\nextern void delay ( unsigned long);\nextern void put32 ( unsigned long, unsigned int );\n"
  },
  {
    "path": "exercises/lesson01/1/avenito/src/boot.S",
    "chars": 367,
    "preview": "#include \"mm.h\"\n\n.section \".text.boot\"\n\n.globl _start\n_start:\n\tmrs\tx0, mpidr_el1\t\t\n\tand\tx0, x0,#0xFF\t\t// Check processor"
  },
  {
    "path": "exercises/lesson01/1/avenito/src/config.txt",
    "chars": 40,
    "preview": "kernel_old=1\ndisable_commandline_tags=1\n"
  },
  {
    "path": "exercises/lesson01/1/avenito/src/kernel.c",
    "chars": 220,
    "preview": "#include \"mini_uart.h\"\n\nvoid kernel_main(void)\n{\n\tuart_init(BAUDRATE_19200);\t\t// the baud rate constants are definide in"
  },
  {
    "path": "exercises/lesson01/1/avenito/src/linker.ld",
    "chars": 184,
    "preview": "SECTIONS\n{\n\t.text.boot : { *(.text.boot) }\n\t.text : { *(.text) }\n\t.rodata : { *(.rodata) }\n\t.data : { *(.data) }\n\t. = AL"
  },
  {
    "path": "exercises/lesson01/1/avenito/src/mini_uart.c",
    "chars": 1520,
    "preview": "#include \"utils.h\"\n#include \"peripherals/mini_uart.h\"\n#include \"peripherals/gpio.h\"\n\nvoid uart_send ( char c )\n{\n\twhile("
  },
  {
    "path": "exercises/lesson01/1/avenito/src/mm.S",
    "chars": 79,
    "preview": ".globl memzero\nmemzero:\n\tstr xzr, [x0], #8\n\tsubs x1, x1, #8\n\tb.gt memzero\n\tret\n"
  },
  {
    "path": "exercises/lesson01/1/avenito/src/utils.S",
    "chars": 131,
    "preview": ".globl put32\nput32:\n\tstr w1,[x0]\n\tret\n\n.globl get32\nget32:\n\tldr w0,[x0]\n\tret\n\n.globl delay\ndelay:\n\tsubs x0, x0, #1\n\tbne "
  },
  {
    "path": "exercises/lesson01/1/bl4ckout31/Makefile",
    "chars": 813,
    "preview": "ARMGNU ?= aarch64-linux-gnu\n\nCOPS = -Wall -nostdlib -nostartfiles -ffreestanding -Iinclude -mgeneral-regs-only\nASMOPS = "
  },
  {
    "path": "exercises/lesson01/1/bl4ckout31/build.bat",
    "chars": 77,
    "preview": "docker run -v %cd%:/app -w /app smatyukevich/raspberry-pi-os-builder make %1\n"
  },
  {
    "path": "exercises/lesson01/1/bl4ckout31/build.sh",
    "chars": 92,
    "preview": "#!/bin/bash\n\ndocker run -v $(pwd):/app -w /app smatyukevich/raspberry-pi-os-builder make $1\n"
  },
  {
    "path": "exercises/lesson01/1/bl4ckout31/include/mini_uart.h",
    "chars": 181,
    "preview": "#ifndef\t_MINI_UART_H\n#define\t_MINI_UART_H\n\nvoid uart_init ( void );\nchar uart_recv ( void );\nvoid uart_send ( char c );\n"
  },
  {
    "path": "exercises/lesson01/1/bl4ckout31/include/mm.h",
    "chars": 373,
    "preview": "#ifndef\t_MM_H\n#define\t_MM_H\n\n#define PAGE_SHIFT\t \t\t12\n#define TABLE_SHIFT \t\t\t9\n#define SECTION_SHIFT\t\t\t(PAGE_SHIFT + TAB"
  },
  {
    "path": "exercises/lesson01/1/bl4ckout31/include/peripherals/base.h",
    "chars": 86,
    "preview": "#ifndef\t_P_BASE_H\n#define\t_P_BASE_H\n\n#define PBASE 0x3F000000\n\n#endif  /*_P_BASE_H */\n"
  },
  {
    "path": "exercises/lesson01/1/bl4ckout31/include/peripherals/gpio.h",
    "chars": 369,
    "preview": "#ifndef\t_P_GPIO_H\n#define\t_P_GPIO_H\n\n#include \"peripherals/base.h\"\n\n#define GPFSEL1         (PBASE+0x00200004)\n#define G"
  },
  {
    "path": "exercises/lesson01/1/bl4ckout31/include/peripherals/mini_uart.h",
    "chars": 623,
    "preview": "#ifndef\t_P_MINI_UART_H\n#define\t_P_MINI_UART_H\n\n#include \"peripherals/base.h\"\n\n#define AUX_ENABLES     (PBASE+0x00215004)"
  },
  {
    "path": "exercises/lesson01/1/bl4ckout31/include/utils.h",
    "chars": 187,
    "preview": "#ifndef\t_BOOT_H\n#define\t_BOOT_H\n\nextern void delay ( unsigned long);\nextern void put32 ( unsigned long, unsigned int );\n"
  },
  {
    "path": "exercises/lesson01/1/bl4ckout31/src/boot.S",
    "chars": 367,
    "preview": "#include \"mm.h\"\n\n.section \".text.boot\"\n\n.globl _start\n_start:\n\tmrs\tx0, mpidr_el1\t\t\n\tand\tx0, x0,#0xFF\t\t// Check processor"
  },
  {
    "path": "exercises/lesson01/1/bl4ckout31/src/config.txt",
    "chars": 58,
    "preview": "arm_control=0x200\nkernel_old=1\ndisable_commandline_tags=1\n"
  },
  {
    "path": "exercises/lesson01/1/bl4ckout31/src/kernel.c",
    "chars": 148,
    "preview": "#include \"mini_uart.h\"\n\nvoid kernel_main(void)\n{\n\tuart_init();\n\tuart_send_string(\"Hello, world!\\r\\n\");\n\n\twhile (1) {\n\t\tu"
  },
  {
    "path": "exercises/lesson01/1/bl4ckout31/src/linker.ld",
    "chars": 184,
    "preview": "SECTIONS\n{\n\t.text.boot : { *(.text.boot) }\n\t.text : { *(.text) }\n\t.rodata : { *(.rodata) }\n\t.data : { *(.data) }\n\t. = AL"
  },
  {
    "path": "exercises/lesson01/1/bl4ckout31/src/mini_uart.c",
    "chars": 1548,
    "preview": "#include \"utils.h\"\n#include \"peripherals/mini_uart.h\"\n#include \"peripherals/gpio.h\"\n\nvoid uart_send ( char c )\n{\n\twhile("
  },
  {
    "path": "exercises/lesson01/1/bl4ckout31/src/mm.S",
    "chars": 79,
    "preview": ".globl memzero\nmemzero:\n\tstr xzr, [x0], #8\n\tsubs x1, x1, #8\n\tb.gt memzero\n\tret\n"
  },
  {
    "path": "exercises/lesson01/1/bl4ckout31/src/utils.S",
    "chars": 131,
    "preview": ".globl put32\nput32:\n\tstr w1,[x0]\n\tret\n\n.globl get32\nget32:\n\tldr w0,[x0]\n\tret\n\n.globl delay\ndelay:\n\tsubs x0, x0, #1\n\tbne "
  },
  {
    "path": "exercises/lesson01/1/evopen/Makefile",
    "chars": 837,
    "preview": "ARMGNU ?= aarch64-linux-gnu\n\nC_FLAGS = -Wall -nostdlib -nostartfiles -ffreestanding -Iinclude -mgeneral-regs-only\nASM_FL"
  },
  {
    "path": "exercises/lesson01/1/evopen/build.sh",
    "chars": 97,
    "preview": "#!/bin/bash\n\ndocker run --rm -v $(pwd):/app -w /app smatyukevich/raspberry-pi-os-builder make $1\n"
  },
  {
    "path": "exercises/lesson01/1/evopen/config.txt",
    "chars": 40,
    "preview": "kernel_old=1\ndisable_commandline_tags=1\n"
  },
  {
    "path": "exercises/lesson01/1/evopen/include/mini_uart.h",
    "chars": 223,
    "preview": "#ifndef _MINI_UART_H\n#define _MINI_UART_H\n\nvoid uart_init(void);\nchar uart_recv(void);\nvoid uart_send(char c);\nvoid uart"
  },
  {
    "path": "exercises/lesson01/1/evopen/include/mm.h",
    "chars": 341,
    "preview": "#ifndef _MM_H\n#define _MM_H\n\n#define PAGE_SHIFT 12\n#define TABLE_SHIFT 9\n#define SECTION_SHIFT (PAGE_SHIFT + TABLE_SHIFT"
  },
  {
    "path": "exercises/lesson01/1/evopen/include/peripherals/base.h",
    "chars": 86,
    "preview": "#ifndef\t_P_BASE_H\n#define\t_P_BASE_H\n\n#define PBASE 0x3F000000\n\n#endif  /*_P_BASE_H */\n"
  },
  {
    "path": "exercises/lesson01/1/evopen/include/peripherals/gpio.h",
    "chars": 275,
    "preview": "\n#ifndef _P_GPIO_H\n#define _P_GPIO_H\n\n#include \"peripherals/base.h\"\n\n#define GPFSEL1 (PBASE + 0x00200004)\n#define GPSET0"
  },
  {
    "path": "exercises/lesson01/1/evopen/include/peripherals/mini_uart.h",
    "chars": 679,
    "preview": "#ifndef _P_MINI_UART_H\n#define _P_MINI_UART_H\n\n#include \"peripherals/base.h\"\n\n#define AUX_ENABLES (PBASE + 0x00215004)\n#"
  },
  {
    "path": "exercises/lesson01/1/evopen/include/utils.h",
    "chars": 178,
    "preview": "#ifndef _BOOT_H\n#define _BOOT_H\n\nextern void delay(unsigned long);\nextern void put32(unsigned long, unsigned int);\nexter"
  },
  {
    "path": "exercises/lesson01/1/evopen/src/boot.S",
    "chars": 354,
    "preview": "    #include \"mm.h\"\n\n    .section \".text.boot\"\n\n    .globl _start\n_start:\n    mrs     x0, mpidr_el1\n    and     x0, x0,#"
  },
  {
    "path": "exercises/lesson01/1/evopen/src/kernel_main.c",
    "chars": 172,
    "preview": "#include \"mini_uart.h\"\n\nint a;\nvoid kernel_main(void) {\n    uart_init();\n    uart_send_string(\"Hello, world!\\r\\n\");\n\n   "
  },
  {
    "path": "exercises/lesson01/1/evopen/src/linker.ld",
    "chars": 207,
    "preview": "SECTIONS\n{\n    .text.boot : { *(.text.boot) }\n    .text : { *(.text) }\n    .rodata : { *(.rodata) }\n    .data : { *(.dat"
  },
  {
    "path": "exercises/lesson01/1/evopen/src/mini_uart.c",
    "chars": 1545,
    "preview": "#include \"peripherals/mini_uart.h\"\n#include \"peripherals/gpio.h\"\n#include \"utils.h\"\n\nunsigned int get_reg_baud(unsigned "
  },
  {
    "path": "exercises/lesson01/1/evopen/src/mm.S",
    "chars": 80,
    "preview": "\t.globl memzero\nmemzero:\n\tstr xzr, [x0], #8\n\tsubs x1, x1, #8\n\tb.gt memzero\n\tret\n"
  },
  {
    "path": "exercises/lesson01/1/evopen/src/utils.S",
    "chars": 166,
    "preview": "    .globl put32\nput32:\n    str w1, [x0]\n    ret\n\n    .globl get32\nget32:\n    ldr w0, [x0]\n    ret\n\n    .globl delay\ndel"
  },
  {
    "path": "exercises/lesson01/1/gcrisis/Makefile",
    "chars": 836,
    "preview": "ARMGNU ?= aarch64-linux-gnu\n\nCOPS = -Wall -nostdlib -nostartfiles -ffreestanding -Iinclude -mgeneral-regs-only\nASMOPS = "
  },
  {
    "path": "exercises/lesson01/1/gcrisis/include/mini_uart.h",
    "chars": 188,
    "preview": "#ifndef\t_MINI_UART_H\n#define\t_MINI_UART_H\n\nvoid uart_init (int baudrate );\nchar uart_recv ( void );\nvoid uart_send ( cha"
  },
  {
    "path": "exercises/lesson01/1/gcrisis/include/mm.h",
    "chars": 373,
    "preview": "#ifndef\t_MM_H\n#define\t_MM_H\n\n#define PAGE_SHIFT\t \t\t12\n#define TABLE_SHIFT \t\t\t9\n#define SECTION_SHIFT\t\t\t(PAGE_SHIFT + TAB"
  },
  {
    "path": "exercises/lesson01/1/gcrisis/include/peripherals/base.h",
    "chars": 86,
    "preview": "#ifndef\t_P_BASE_H\n#define\t_P_BASE_H\n\n#define PBASE 0x3F000000\n\n#endif  /*_P_BASE_H */\n"
  },
  {
    "path": "exercises/lesson01/1/gcrisis/include/peripherals/gpio.h",
    "chars": 307,
    "preview": "#ifndef\t_P_GPIO_H\n#define\t_P_GPIO_H\n\n#include \"peripherals/base.h\"\n\n#define GPFSEL1         (PBASE+0x00200004)\n#define G"
  },
  {
    "path": "exercises/lesson01/1/gcrisis/include/peripherals/mini_uart.h",
    "chars": 623,
    "preview": "#ifndef\t_P_MINI_UART_H\n#define\t_P_MINI_UART_H\n\n#include \"peripherals/base.h\"\n\n#define AUX_ENABLES     (PBASE+0x00215004)"
  },
  {
    "path": "exercises/lesson01/1/gcrisis/include/utils.h",
    "chars": 187,
    "preview": "#ifndef\t_BOOT_H\n#define\t_BOOT_H\n\nextern void delay ( unsigned long);\nextern void put32 ( unsigned long, unsigned int );\n"
  },
  {
    "path": "exercises/lesson01/1/gcrisis/src/boot.S",
    "chars": 367,
    "preview": "#include \"mm.h\"\n\n.section \".text.boot\"\n\n.globl _start\n_start:\n\tmrs\tx0, mpidr_el1\t\t\n\tand\tx0, x0,#0xFF\t\t// Check processor"
  },
  {
    "path": "exercises/lesson01/1/gcrisis/src/config.txt",
    "chars": 40,
    "preview": "kernel_old=1\ndisable_commandline_tags=1\n"
  },
  {
    "path": "exercises/lesson01/1/gcrisis/src/kernel.c",
    "chars": 152,
    "preview": "#include \"mini_uart.h\"\n\nvoid kernel_main(void)\n{\n\tuart_init(9600);\n\tuart_send_string(\"Hello, world!\\r\\n\");\n\n\twhile (1) {"
  },
  {
    "path": "exercises/lesson01/1/gcrisis/src/linker.ld",
    "chars": 199,
    "preview": "SECTIONS\n{\n    .text.boot : { *(.text.boot)}\n    .text :{ *(.text)}\n    .rodata : {*(.rodata) }\n    .data : {*(.data) }\n"
  },
  {
    "path": "exercises/lesson01/1/gcrisis/src/mini_uart.c",
    "chars": 1579,
    "preview": "#include \"utils.h\"\n#include \"peripherals/mini_uart.h\"\n#include \"peripherals/gpio.h\"\n\n#define BAUD_REG_VAL(baud_rate)  (("
  },
  {
    "path": "exercises/lesson01/1/gcrisis/src/mm.S",
    "chars": 79,
    "preview": ".globl memzero\nmemzero:\n\tstr xzr, [x0], #8\n\tsubs x1, x1, #8\n\tb.gt memzero\n\tret\n"
  },
  {
    "path": "exercises/lesson01/1/gcrisis/src/utils.S",
    "chars": 131,
    "preview": ".globl put32\nput32:\n\tstr w1,[x0]\n\tret\n\n.globl get32\nget32:\n\tldr w0,[x0]\n\tret\n\n.globl delay\ndelay:\n\tsubs x0, x0, #1\n\tbne "
  },
  {
    "path": "exercises/lesson01/1/rs/Makefile",
    "chars": 834,
    "preview": "ARMGNU ?= aarch64-linux-gnu\n\nCOPS = -Wall -nostdlib -nostartfiles -ffreestanding -Iinclude -mgeneral-regs-only\nASMOPS = "
  },
  {
    "path": "exercises/lesson01/1/rs/build.bat",
    "chars": 82,
    "preview": "docker run --rm -v %cd%:/app -w /app smatyukevich/raspberry-pi-os-builder make %1\n"
  },
  {
    "path": "exercises/lesson01/1/rs/build.sh",
    "chars": 97,
    "preview": "#!/bin/bash\n\ndocker run --rm -v $(pwd):/app -w /app smatyukevich/raspberry-pi-os-builder make $1\n"
  },
  {
    "path": "exercises/lesson01/1/rs/include/mini_uart.h",
    "chars": 171,
    "preview": "#ifndef _MINI_UART_H\n#define _MINI_UART_H\n\nvoid uart_init(void);\nchar uart_recv(void);\nvoid uart_send(char c);\nvoid uart"
  },
  {
    "path": "exercises/lesson01/1/rs/include/mm.h",
    "chars": 341,
    "preview": "#ifndef _MM_H\n#define _MM_H\n\n#define PAGE_SHIFT 12\n#define TABLE_SHIFT 9\n#define SECTION_SHIFT (PAGE_SHIFT + TABLE_SHIFT"
  },
  {
    "path": "exercises/lesson01/1/rs/include/peripherals/base.h",
    "chars": 85,
    "preview": "#ifndef _P_BASE_H\n#define _P_BASE_H\n\n#define PBASE 0x3F000000\n\n#endif /*_P_BASE_H */\n"
  },
  {
    "path": "exercises/lesson01/1/rs/include/peripherals/gpio.h",
    "chars": 274,
    "preview": "#ifndef _P_GPIO_H\n#define _P_GPIO_H\n\n#include \"peripherals/base.h\"\n\n#define GPFSEL1 (PBASE + 0x00200004)\n#define GPSET0 "
  },
  {
    "path": "exercises/lesson01/1/rs/include/peripherals/mini_uart.h",
    "chars": 695,
    "preview": "#ifndef _P_MINI_UART_H\n#define _P_MINI_UART_H\n\n#include \"peripherals/base.h\"\n\n#define AUX_ENABLES (PBASE + 0x00215004)\n#"
  },
  {
    "path": "exercises/lesson01/1/rs/include/utils.h",
    "chars": 178,
    "preview": "#ifndef _BOOT_H\n#define _BOOT_H\n\nextern void delay(unsigned long);\nextern void put32(unsigned long, unsigned int);\nexter"
  },
  {
    "path": "exercises/lesson01/1/rs/src/boot.S",
    "chars": 363,
    "preview": "#include \"mm.h\"\n\n.section \".text.boot\"\n\n.globl _start\n_start:\n\tmrs x0, mpidr_el1\n\tand x0, x0, #0xFF // Check processor i"
  },
  {
    "path": "exercises/lesson01/1/rs/src/config.txt",
    "chars": 58,
    "preview": "arm_control=0x200\nkernel_old=1\ndisable_commandline_tags=1\n"
  },
  {
    "path": "exercises/lesson01/1/rs/src/kernel.c",
    "chars": 154,
    "preview": "#include \"mini_uart.h\"\n\nvoid kernel_main(void) {\n  uart_init();\n  uart_send_string(\"Hello, world!\\r\\n\");\n\n  while (1) {\n"
  },
  {
    "path": "exercises/lesson01/1/rs/src/linker.ld",
    "chars": 184,
    "preview": "SECTIONS\n{\n\t.text.boot : { *(.text.boot) }\n\t.text : { *(.text) }\n\t.rodata : { *(.rodata) }\n\t.data : { *(.data) }\n\t. = AL"
  },
  {
    "path": "exercises/lesson01/1/rs/src/mini_uart.c",
    "chars": 1474,
    "preview": "#include \"peripherals/mini_uart.h\"\n#include \"peripherals/gpio.h\"\n#include \"utils.h\"\n\nvoid uart_send(char c) {\n  while (1"
  },
  {
    "path": "exercises/lesson01/1/rs/src/mm.S",
    "chars": 79,
    "preview": ".globl memzero\nmemzero:\n\tstr xzr, [x0], #8\n\tsubs x1, x1, #8\n\tb.gt memzero\n\tret\n"
  },
  {
    "path": "exercises/lesson01/1/rs/src/utils.S",
    "chars": 133,
    "preview": ".globl put32\nput32:\n\tstr w1, [x0]\n\tret\n\n.globl get32\nget32:\n\tldr w0, [x0]\n\tret\n\n.globl delay\ndelay:\n\tsubs x0, x0, #1\n\tbn"
  },
  {
    "path": "exercises/lesson01/1/stefanji/Makefile",
    "chars": 834,
    "preview": "ARMGNU ?= aarch64-linux-gnu\n\nCOPS = -Wall -nostdlib -nostartfiles -ffreestanding -Iinclude -mgeneral-regs-only\nASMOPS = "
  },
  {
    "path": "exercises/lesson01/1/stefanji/build.bat",
    "chars": 82,
    "preview": "docker run --rm -v %cd%:/app -w /app smatyukevich/raspberry-pi-os-builder make %1\n"
  },
  {
    "path": "exercises/lesson01/1/stefanji/build.sh",
    "chars": 97,
    "preview": "#!/bin/bash\n\ndocker run --rm -v $(pwd):/app -w /app smatyukevich/raspberry-pi-os-builder make $1\n"
  },
  {
    "path": "exercises/lesson01/1/stefanji/include/mini_uart.h",
    "chars": 187,
    "preview": "#ifndef\t_MINI_UART_H\n#define\t_MINI_UART_H\n\nvoid uart_init (unsigned int);\nchar uart_recv ( void );\nvoid uart_send ( char"
  },
  {
    "path": "exercises/lesson01/1/stefanji/include/mm.h",
    "chars": 373,
    "preview": "#ifndef\t_MM_H\n#define\t_MM_H\n\n#define PAGE_SHIFT\t \t\t12\n#define TABLE_SHIFT \t\t\t9\n#define SECTION_SHIFT\t\t\t(PAGE_SHIFT + TAB"
  },
  {
    "path": "exercises/lesson01/1/stefanji/include/peripherals/base.h",
    "chars": 86,
    "preview": "#ifndef\t_P_BASE_H\n#define\t_P_BASE_H\n\n#define PBASE 0x3F000000\n\n#endif  /*_P_BASE_H */\n"
  },
  {
    "path": "exercises/lesson01/1/stefanji/include/peripherals/gpio.h",
    "chars": 307,
    "preview": "#ifndef\t_P_GPIO_H\n#define\t_P_GPIO_H\n\n#include \"peripherals/base.h\"\n\n#define GPFSEL1         (PBASE+0x00200004)\n#define G"
  },
  {
    "path": "exercises/lesson01/1/stefanji/include/peripherals/mini_uart.h",
    "chars": 741,
    "preview": "#ifndef\t_P_MINI_UART_H\n#define\t_P_MINI_UART_H\n\n#include \"peripherals/base.h\"\n\n#define AUX_ENABLES     (PBASE+0x00215004)"
  },
  {
    "path": "exercises/lesson01/1/stefanji/include/utils.h",
    "chars": 187,
    "preview": "#ifndef\t_BOOT_H\n#define\t_BOOT_H\n\nextern void delay ( unsigned long);\nextern void put32 ( unsigned long, unsigned int );\n"
  },
  {
    "path": "exercises/lesson01/1/stefanji/src/boot.S",
    "chars": 367,
    "preview": "#include \"mm.h\"\n\n.section \".text.boot\"\n\n.globl _start\n_start:\n\tmrs\tx0, mpidr_el1\t\t\n\tand\tx0, x0,#0xFF\t\t// Check processor"
  },
  {
    "path": "exercises/lesson01/1/stefanji/src/config.txt",
    "chars": 40,
    "preview": "kernel_old=1\ndisable_commandline_tags=1\n"
  },
  {
    "path": "exercises/lesson01/1/stefanji/src/kernel.c",
    "chars": 152,
    "preview": "#include \"mini_uart.h\"\n\nvoid kernel_main(void)\n{\n\tuart_init(9600);\n\tuart_send_string(\"Hello, world!\\r\\n\");\n\n\twhile (1) {"
  },
  {
    "path": "exercises/lesson01/1/stefanji/src/linker.ld",
    "chars": 184,
    "preview": "SECTIONS\n{\n\t.text.boot : { *(.text.boot) }\n\t.text : { *(.text) }\n\t.rodata : { *(.rodata) }\n\t.data : { *(.data) }\n\t. = AL"
  },
  {
    "path": "exercises/lesson01/1/stefanji/src/mini_uart.c",
    "chars": 1524,
    "preview": "#include \"utils.h\"\n#include \"peripherals/mini_uart.h\"\n#include \"peripherals/gpio.h\"\n\nvoid uart_send ( char c )\n{\n\twhile("
  },
  {
    "path": "exercises/lesson01/1/stefanji/src/mm.S",
    "chars": 79,
    "preview": ".globl memzero\nmemzero:\n\tstr xzr, [x0], #8\n\tsubs x1, x1, #8\n\tb.gt memzero\n\tret\n"
  },
  {
    "path": "exercises/lesson01/1/stefanji/src/utils.S",
    "chars": 131,
    "preview": ".globl put32\nput32:\n\tstr w1,[x0]\n\tret\n\n.globl get32\nget32:\n\tldr w0,[x0]\n\tret\n\n.globl delay\ndelay:\n\tsubs x0, x0, #1\n\tbne "
  },
  {
    "path": "exercises/lesson01/1/xdfm1/Makefile",
    "chars": 824,
    "preview": "ARMGNU ?= aarch64-linux-gnu\n\nCOPS = -Wall -nostdlib -nostartfiles -ffreestanding -Iinclude -mgeneral-regs-only -std=gnu9"
  },
  {
    "path": "exercises/lesson01/1/xdfm1/build.bat",
    "chars": 77,
    "preview": "docker run -v %cd%:/app -w /app smatyukevich/raspberry-pi-os-builder make %1\n"
  },
  {
    "path": "exercises/lesson01/1/xdfm1/build.sh",
    "chars": 92,
    "preview": "#!/bin/bash\n\ndocker run -v $(pwd):/app -w /app smatyukevich/raspberry-pi-os-builder make $1\n"
  },
  {
    "path": "exercises/lesson01/1/xdfm1/include/mini_uart.h",
    "chars": 221,
    "preview": "#ifndef\t_MINI_UART_H\n#define\t_MINI_UART_H\n\nvoid uart_init ( void );\nchar uart_recv ( void );\nvoid uart_send ( char c );\n"
  },
  {
    "path": "exercises/lesson01/1/xdfm1/include/mm.h",
    "chars": 373,
    "preview": "#ifndef\t_MM_H\n#define\t_MM_H\n\n#define PAGE_SHIFT\t \t\t12\n#define TABLE_SHIFT \t\t\t9\n#define SECTION_SHIFT\t\t\t(PAGE_SHIFT + TAB"
  },
  {
    "path": "exercises/lesson01/1/xdfm1/include/peripherals/base.h",
    "chars": 86,
    "preview": "#ifndef\t_P_BASE_H\n#define\t_P_BASE_H\n\n#define PBASE 0x3F000000\n\n#endif  /*_P_BASE_H */\n"
  },
  {
    "path": "exercises/lesson01/1/xdfm1/include/peripherals/gpio.h",
    "chars": 307,
    "preview": "#ifndef\t_P_GPIO_H\n#define\t_P_GPIO_H\n\n#include \"peripherals/base.h\"\n\n#define GPFSEL1         (PBASE+0x00200004)\n#define G"
  },
  {
    "path": "exercises/lesson01/1/xdfm1/include/peripherals/mini_uart.h",
    "chars": 671,
    "preview": "#ifndef\t_P_MINI_UART_H\n#define\t_P_MINI_UART_H\n\n#include \"peripherals/base.h\"\n\n#define AUX_ENABLES     (PBASE+0x00215004)"
  },
  {
    "path": "exercises/lesson01/1/xdfm1/include/utils.h",
    "chars": 187,
    "preview": "#ifndef\t_BOOT_H\n#define\t_BOOT_H\n\nextern void delay ( unsigned long);\nextern void put32 ( unsigned long, unsigned int );\n"
  },
  {
    "path": "exercises/lesson01/1/xdfm1/src/boot.S",
    "chars": 367,
    "preview": "#include \"mm.h\"\n\n.section \".text.boot\"\n\n.globl _start\n_start:\n\tmrs\tx0, mpidr_el1\t\t\n\tand\tx0, x0,#0xFF\t\t// Check processor"
  },
  {
    "path": "exercises/lesson01/1/xdfm1/src/config.txt",
    "chars": 58,
    "preview": "arm_control=0x200\nkernel_old=1\ndisable_commandline_tags=1\n"
  },
  {
    "path": "exercises/lesson01/1/xdfm1/src/kernel.c",
    "chars": 148,
    "preview": "#include \"mini_uart.h\"\n\nvoid kernel_main(void)\n{\n\tuart_init();\n\tuart_send_string(\"Hello, world!\\r\\n\");\n\n\twhile (1) {\n\t\tu"
  },
  {
    "path": "exercises/lesson01/1/xdfm1/src/linker.ld",
    "chars": 184,
    "preview": "SECTIONS\n{\n\t.text.boot : { *(.text.boot) }\n\t.text : { *(.text) }\n\t.rodata : { *(.rodata) }\n\t.data : { *(.data) }\n\t. = AL"
  },
  {
    "path": "exercises/lesson01/1/xdfm1/src/mini_uart.c",
    "chars": 1630,
    "preview": "#include \"utils.h\"\n#include \"peripherals/mini_uart.h\"\n#include \"peripherals/gpio.h\"\n\nvoid uart_send ( char c )\n{\n\twhile("
  },
  {
    "path": "exercises/lesson01/1/xdfm1/src/mm.S",
    "chars": 79,
    "preview": ".globl memzero\nmemzero:\n\tstr xzr, [x0], #8\n\tsubs x1, x1, #8\n\tb.gt memzero\n\tret\n"
  },
  {
    "path": "exercises/lesson01/1/xdfm1/src/utils.S",
    "chars": 131,
    "preview": ".globl put32\nput32:\n\tstr w1,[x0]\n\tret\n\n.globl get32\nget32:\n\tldr w0,[x0]\n\tret\n\n.globl delay\ndelay:\n\tsubs x0, x0, #1\n\tbne "
  },
  {
    "path": "exercises/lesson01/1/zjd0112/Makefile",
    "chars": 834,
    "preview": "ARMGNU ?= aarch64-linux-gnu\n\nCOPS = -Wall -nostdlib -nostartfiles -ffreestanding -Iinclude -mgeneral-regs-only\nASMOPS = "
  },
  {
    "path": "exercises/lesson01/1/zjd0112/build.bat",
    "chars": 82,
    "preview": "docker run --rm -v %cd%:/app -w /app smatyukevich/raspberry-pi-os-builder make %1\n"
  },
  {
    "path": "exercises/lesson01/1/zjd0112/build.sh",
    "chars": 97,
    "preview": "#!/bin/bash\n\ndocker run --rm -v $(pwd):/app -w /app smatyukevich/raspberry-pi-os-builder make $1\n"
  },
  {
    "path": "exercises/lesson01/1/zjd0112/include/mini_uart.h",
    "chars": 199,
    "preview": "#ifndef\t_MINI_UART_H\n#define\t_MINI_UART_H\n\nvoid uart_init ( unsigned int baud_rate );\nchar uart_recv ( void );\nvoid uart"
  },
  {
    "path": "exercises/lesson01/1/zjd0112/include/mm.h",
    "chars": 373,
    "preview": "#ifndef\t_MM_H\n#define\t_MM_H\n\n#define PAGE_SHIFT\t \t\t12\n#define TABLE_SHIFT \t\t\t9\n#define SECTION_SHIFT\t\t\t(PAGE_SHIFT + TAB"
  },
  {
    "path": "exercises/lesson01/1/zjd0112/include/peripherals/base.h",
    "chars": 86,
    "preview": "#ifndef\t_P_BASE_H\n#define\t_P_BASE_H\n\n#define PBASE 0x3F000000\n\n#endif  /*_P_BASE_H */\n"
  },
  {
    "path": "exercises/lesson01/1/zjd0112/include/peripherals/gpio.h",
    "chars": 307,
    "preview": "#ifndef\t_P_GPIO_H\n#define\t_P_GPIO_H\n\n#include \"peripherals/base.h\"\n\n#define GPFSEL1         (PBASE+0x00200004)\n#define G"
  },
  {
    "path": "exercises/lesson01/1/zjd0112/include/peripherals/mini_uart.h",
    "chars": 662,
    "preview": "#ifndef\t_P_MINI_UART_H\n#define\t_P_MINI_UART_H\n\n#include \"peripherals/base.h\"\n\n#define AUX_ENABLES     (PBASE+0x00215004)"
  },
  {
    "path": "exercises/lesson01/1/zjd0112/include/utils.h",
    "chars": 187,
    "preview": "#ifndef\t_BOOT_H\n#define\t_BOOT_H\n\nextern void delay ( unsigned long);\nextern void put32 ( unsigned long, unsigned int );\n"
  },
  {
    "path": "exercises/lesson01/1/zjd0112/src/boot.S",
    "chars": 367,
    "preview": "#include \"mm.h\"\n\n.section \".text.boot\"\n\n.globl _start\n_start:\n\tmrs\tx0, mpidr_el1\t\t\n\tand\tx0, x0,#0xFF\t\t// Check processor"
  }
]

// ... and 2326 more files (download for full content)

About this extraction

This page contains the full source code of the s-matyukevich/raspberry-pi-os GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 2526 files (2.7 MB), approximately 845.2k tokens, and a symbol index with 2309 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!