Skip to content

Commit

Permalink
added std chapter
Browse files Browse the repository at this point in the history
  • Loading branch information
kiarie404 committed Mar 25, 2024
1 parent 3b07623 commit 231558f
Show file tree
Hide file tree
Showing 51 changed files with 1,482 additions and 55 deletions.
9 changes: 4 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,23 @@

# Intro

This book is on driver development using Rust. You get to procedurally write a UART driver for a RISCV chip called ESP32C3.
This book is on driver development using Rust. You get to procedurally write a UART driver for two chips:
- a RISCV chip called ESP32C3.
- a riscv virtual qemu board.

The chip costs less than 8 dollars, kindly... politely...with utmost humility... burn that cash. BURN THAT CAAAASHHH!!! Money machine go BRRRR!!!


## If You are coming from the freestyle classes...

If you are currently taking the [gdsc course](https://gdsc.community.dev/events/details/developer-student-clubs-university-of-nairobi-presents-introduction-to-rust-on-embedded/), then take a look at this paper
If you are currently taking the [gdsc course](https://gdsc.community.dev/events/details/developer-student-clubs-university-of-nairobi-presents-introduction-to-rust-on-embedded/), then take a look at [this paper](./driver_book/src/direction/course_outline.md)

This book is currently in active development, chapters will be updated as we go through the [gdsc course](https://gdsc.community.dev/events/details/developer-student-clubs-university-of-nairobi-presents-introduction-to-rust-on-embedded/).
Here is the :
- [Course outline](./driver_book/src/direction/course_outline.md).
- The class recordings can be found in [this youtube playlist][driver-development-playlist].


**If you are looking for the updated chapter that was referenced in the LAST LESSON : read chapter 18 of the book**




### Why the UART?
Expand Down
2 changes: 1 addition & 1 deletion driver_book/book/404.html

Large diffs are not rendered by default.

Large diffs are not rendered by default.

260 changes: 260 additions & 0 deletions driver_book/book/bare_metal/definition.html

Large diffs are not rendered by default.

272 changes: 272 additions & 0 deletions driver_book/book/bare_metal/dependencies.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion driver_book/book/bare_metal/linking/linking.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion driver_book/book/bare_metal/linking/rusty_linkers.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion driver_book/book/bare_metal/no_std/pracs_1.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion driver_book/book/bare_metal/no_std/pracs_2.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion driver_book/book/bare_metal/no_std/removing_std_lib.html

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions driver_book/book/bare_metal/no_std/the_no_std_intro.html

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions driver_book/book/bare_metal/the_no_std_preface.html

Large diffs are not rendered by default.

322 changes: 322 additions & 0 deletions driver_book/book/bare_metal/the_std_library.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion driver_book/book/index.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion driver_book/book/intro/intro.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion driver_book/book/intro/prerequisites.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion driver_book/book/misc/API.html

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions driver_book/book/misc/abi.html

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions driver_book/book/misc/building_runtime_crates.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion driver_book/book/misc/different_std_libs.html

Large diffs are not rendered by default.

284 changes: 284 additions & 0 deletions driver_book/book/misc/isa.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion driver_book/book/misc/notable_core_crates.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion driver_book/book/misc/panicking.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion driver_book/book/misc/the_C_runtime.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion driver_book/book/notable_crates.html

Large diffs are not rendered by default.

126 changes: 124 additions & 2 deletions driver_book/book/print.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion driver_book/book/searchindex.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion driver_book/book/searchindex.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion driver_book/book/todo.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion driver_book/book/uart_implementations/on_qemu/intro.html

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion driver_book/book/uart_theory/draft_1.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion driver_book/book/uart_theory/draft_2.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion driver_book/book/uart_theory/intro.html

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion driver_book/book/why_embedded_rust.html

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions driver_book/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@

# BARE METAL PROGRAMMING
- [No std preface](./bare_metal/the_no_std_preface.md)
- [Machine Code](./bare_metal/definition.md)
- [Dependencies](./bare_metal/dependencies.md)
- [The Standard Library](./bare_metal/the_std_library.md)
- [No std](./bare_metal/no_std/the_no_std_intro.md)
- [Disabling the Standard Library](./bare_metal/no_std/removing_std_lib.md)
- [Pracs 1](./bare_metal/no_std/pracs_1.md)
Expand Down Expand Up @@ -95,6 +98,7 @@
- [the-C-runtime](./misc/the_C_runtime.md)
- [api-definition](./misc/API.md)
- [abi-definition](./misc/abi.md)
- [isa-definition](./misc/isa.md)
- [Building runtimes](./misc/building_runtime_crates.md)
- [Panicking](./misc/panicking.md)
- [To-do](todo.md)
13 changes: 13 additions & 0 deletions driver_book/src/bare_metal/definition.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Machine code


From your Computer architecture class, you learnt that the processor is a bunch of gates cramped up together in a meaningful way. A circuit of some sort.

You also learnt that each processor implements an [ISA (Instruction Set Architecture)](../misc/isa.md).
As long as you can compile high level code into machine code that is within the bounds of the ISA, that CPU will gladly execute your code. You don't even have to follow a certain [ABI](../misc/abi.md) in order for that code to run.

The main point here is that : "Machine code that follows a certain ISA can run on any processor that implements that ISA." This is because the processor is a DIRECT implementation of the ISA specifications.

So the processor that you built in your room can run Rust code. As long as that rust code gets compiled into machine code that follows the ISA specifications of your custom processor.


31 changes: 31 additions & 0 deletions driver_book/src/bare_metal/dependencies.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Dependencies

A library refers to a collection of precompiled routines, functions, classes, or modules that can be reused by various programs or applications to perform specific tasks or operations. Libraries are essentially packages of code that provide commonly used functionality, such as mathematical operations, file handling, networking, user interface components, and more.

A dependency, on the other hand, refers to a specific software component or library that a project relies on to function properly.


For example, the hello-world program below uses the `time` library as a dependency:
```rust
use time;

fn main(){
println!("Hello world!!!");
}
```


## Default dependencies
By default, all rust programs use the [`std` library](https://doc.rust-lang.org/std/index.html) as a dependency. Even if you write a simple hello-world or an add-library, the contents of the [`std::prelude`](https://doc.rust-lang.org/std/prelude/index.html) library get included as part of your code as if you had written it as follows...

```rust
use std::prelude::*; // this line is usually not there... but theoretically,
// your compiler treats your code as if this line was explicitly declared here

fn main(){
println!("Hello world!!!");
}
```


So ... what is the standard library? What is a prelude?
98 changes: 98 additions & 0 deletions driver_book/src/bare_metal/the_std_library.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# The Standard Library

The standard library is a library like any other... it is just that it contains definitions of things that help in very essential tasks. Tasks that are expected to be found in almost every OS.

For example, it may contain declarations & definitions of `file-handling functions`, `thread-handling functions`, `String struct definition`, ... etc

You can find the documentation of the rust standard library [here](https://doc.rust-lang.org/std/index.html).

Below is a story that explains more about standard libraries (the story does not explain the actual modules of the standard library).


# Story time
You can skip this page if you already understand ...
- What the standard library is
- Why it exists
- The different standards that may be followed


## Posix

Long ago ... once upon a time (in the 70s-80s), there were a lot of upcoming operating systems. Each operating system had its's own features. For example, some had graphical interfaces, some didn't. Some could run apps using multi-threading capabilities, others didn't. Some had file systems that contained like 100 functions... others had like 10 file-handling functions.

It was chaos everywhere. For example : the `open_file()` function might have had different names across many operting systems. So if you wrote an app for 3 OSes, you would have re-written your code 3 times just because the `open_file` function was not universal.
It was a bad time to be an app developer. You either had to specialize in writing apps for one operating system OR sacrifice your sanity and learn the commands of multiple Operating systems.

To make matters worse... the individual operting systems were improving FAST... so function names were changing, file_handling routines were changing, graphical output commands were changing. CHAOS! EVERYWHERE.


So developers decided that they needed some form of decorum for the sake of their sanity.
They decided to create common rules and definitions on the three topics below :
1. Basic definitions
2. System interface
3. Shell and utilities.

So what the hell are these three things?

### 1. Basic definitions
Just as the title says, before the devs made rules, they had to first know that they were speaking the same language. I mean... how can you make rules about something that you don't even have a description for?

They had to define the meaning of words. Eg "What is a `process`? What is an `integer`? What is a `file`? What is a `kernel` even?
Defining things explicitly reduced confusion.

They had to
1. Agree on the definition of things ie terminology.
2. Agree on the exact representation of data-types and their behavior. This representation does not have to be the same as the ABI that you are using, you just have to make sure that your kernel interface *treats* data-types as defined here.
3. Agree on the common constants : For example error_codes, port numbers of interes ...

### 2. System Interface
As earlier mentioned, each kernel had different features and capabilities... some had dozens of advanced and uniquely named file-handling functions while others had like 2 poorly named and unique file-handling functions.

This was a problem. It forced devs to have to re-write apps for each OS.
So the devs sat down and created a list of well-named function signatures... and declared that kernel developers should implement kernels that us those exact signatures. They also explicitly defined the purpose of each of those functions. eg
```bash
void _exit(int status); # A function that terminates a process

```
You can find the full description of the `_exit` function [here](https://pubs.opengroup.org/onlinepubs/9699919799/functions/_exit.html) and see how explicit the definitions were.


This ensured that all kernels, no matter how different, had a similar interface. Now devs did not need to re-write apps for each OS. They no longer had to learn the interfaces of each OS. They just had to learn ONE interface only.

These set of functions became known as the System interface.
You can view the POSIX system interface [here](https://pubs.opengroup.org/onlinepubs/9699919799/functions/contents.html)


### 3. Shell and its utilities
The Operating system is more than just a kernel. You need the command line. You may even need a Graphic User Interface like a Desktop.
In the 1980's, shells were the hit. So there were dozens of unique shells, each with their own commands and syntax.

The devs sat down and declared the common commands that had to be implemented by all shells eg `ls`, `mv`, `grep`, `cd`...


As for the shell syntax... well... I don't know... the devs tried to write a formal syntax. It somehow worked, but people still introduced
their own variations. (which is good, bash syntax is horrifying... I took years to get good at Rust/JS/C/C++, but I'm sure I'll take my whole life to get comfortable with bash)


This specifications came to be known as the [POSIX standard](https://en.wikipedia.org/wiki/POSIX).


## Entry of the standard library
Why is this POSIX story relevant?
Well... because the standard libraries implement parts of the POSIX standard.

For example...
1. The standard library defines the definitions of the functions defined in the POSIX system interface.
2. The data-types used in the above function definitions follow the data-type representation specified by the POSIX's basic deinitions chapter.

Examples of standard libraries that adhere to the POSIX standard include : The C standard library(glibc) and The Rust standard library. They may not strictly adhere to the POSIX specifications but they come close to it.


## POSIX compliance
If you look at the [list of system functions specified by posix](https://pubs.opengroup.org/onlinepubs/9699919799/idx/functions.html), you might get a heart-attack. That list is LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOONG.

What if I just wanted to create a small-specialized kernel that does not have a file-system or thread-management? Do I still have to define file-handling functions? Do I still have to define thread-management functions? - NO!, that would be a waste of everyone's time and RAM.

That is why there are many versions of the C standard library. For example, we have `glibc` and `new-libc`.
`glibc` is more POSIX-compliant because it defines more system functions than `new-libc`.
`newlib-c` is a C standard library specifically made for **minimalist** kernels. `newlib-c` defines essential system functions only.
22 changes: 22 additions & 0 deletions driver_book/src/misc/isa.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
An ISA specification is a piece of document that elaborates on how a certain processor functions. It does so by explaining the things listed below :

- Supported Instructions:
This refers to the set of operations or commands that a processor can understand and execute. Instructions could include arithmetic operations (addition, subtraction, multiplication, division), logical operations (AND, OR, NOT), control flow operations (branches, jumps, calls), and others specific to the architecture.

- Data Types:
ISA specifies the types of data that can be manipulated by the processor. This might include integer types (such as 8-bit, 16-bit, 32-bit, or 64-bit integers), floating-point types (single precision, double precision), and sometimes vector or SIMD (Single Instruction, Multiple Data) types for parallel processing.

- Registers:
Registers are small, fast storage locations within the processor that hold data temporarily during processing. ISA defines the number of registers, their sizes, and their intended purposes (e.g., general-purpose registers, special-purpose registers for specific tasks like storing the program counter or stack pointer).

- Hardware Support for Managing Main Memory:
ISA specifies how the processor interacts with main memory (RAM). This includes mechanisms for loading and storing data from/to memory, handling memory access permissions, cache management, and mechanisms for memory protection to prevent unauthorized access.

- Fundamental Features:
These are core aspects of the ISA that define its behavior and capabilities.
Memory Consistency: Specifies how memory accesses by different parts of a program are ordered and synchronized.
Addressing Modes: Defines the various ways in which memory addresses can be specified in instructions (e.g., direct addressing, indirect addressing, indexed addressing).
Virtual Memory: Defines how the processor interacts with virtual memory systems, including mechanisms for address translation between virtual and physical memory, page tables, and memory protection.

- Input/Output Model:
This refers to how the processor communicates with peripheral devices such as keyboards, displays, storage devices, and network interfaces. ISA specifies the instructions and mechanisms for transferring data between the processor and these devices, often through dedicated I/O instructions or memory-mapped I/O.

0 comments on commit 231558f

Please sign in to comment.