mirror of
https://github.com/google/comprehensive-rust.git
synced 2025-03-19 22:19:29 +02:00
APS updates (#2528)
These are some minor updates from walking through the session myself. * Add some context to the `entry.S` slide, which is otherwise a bit terrifying for someone who does not speak ARM assembly. * Include a simple, fake example of MMIO. * Add a "Using It" section to the minimal UART segment, parallel to the better UART * Better explanation of the `unwrap` calls in the logging example. Unwrap is never "unsafe", so remove that word. * Allow dead code in some `.rs` files. * Remove redundant warning about use of memory before MMU setup. * Rephase text about buddy-system * Fix lint warning in spin slide.
This commit is contained in:
parent
3764569198
commit
c04d2860e8
@ -336,6 +336,7 @@
|
||||
- [MMIO](bare-metal/aps/mmio.md)
|
||||
- [Let's Write a UART Driver](bare-metal/aps/uart.md)
|
||||
- [More Traits](bare-metal/aps/uart/traits.md)
|
||||
- [Using It](bare-metal/aps/uart/using.md)
|
||||
- [A Better UART Driver](bare-metal/aps/better-uart.md)
|
||||
- [Bitflags](bare-metal/aps/better-uart/bitflags.md)
|
||||
- [Multiple Registers](bare-metal/aps/better-uart/registers.md)
|
||||
|
@ -9,9 +9,6 @@ echo incoming bytes.
|
||||
|
||||
<details>
|
||||
|
||||
- As in the [inline assembly](../inline-assembly.md) example, this `main`
|
||||
function is called from our entry point code in `entry.S`. See the speaker
|
||||
notes there for details.
|
||||
- Run the example in QEMU with `make qemu` under `src/bare-metal/aps/examples`.
|
||||
|
||||
</details>
|
||||
|
@ -8,6 +8,10 @@ Before we can start running Rust code, we need to do some initialisation.
|
||||
|
||||
<details>
|
||||
|
||||
This code is in `src/bare-metal/aps/examples/entry.S`. It's not necessary to
|
||||
understand this in detail -- the takeaway is that typically some low-level setup
|
||||
is needed to meet Rust's expectations of the system.
|
||||
|
||||
- This is the same as it would be for C: initialising the processor state,
|
||||
zeroing the BSS, and setting up the stack pointer.
|
||||
- The BSS (block starting symbol, for historical reasons) is the part of the
|
||||
|
@ -11,6 +11,7 @@
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#![allow(dead_code)]
|
||||
|
||||
use core::fmt::{self, Write};
|
||||
|
||||
|
@ -9,8 +9,9 @@ We can do this by implementing the `Log` trait.
|
||||
|
||||
<details>
|
||||
|
||||
- The unwrap in `log` is safe because we initialise `LOGGER` before calling
|
||||
`set_logger`.
|
||||
- The first unwrap in `log` will succeed because we initialise `LOGGER` before
|
||||
calling `set_logger`. The second will succeed because `Uart::write_str` always
|
||||
returns `Ok`.
|
||||
|
||||
</details>
|
||||
|
||||
|
@ -5,6 +5,16 @@
|
||||
- Use `&raw` to get fields of structs without creating an intermediate
|
||||
reference.
|
||||
|
||||
```rust,editable,ignore
|
||||
const SOME_DEVICE_REGISTER: *mut u64 = 0x800_0000 as _;
|
||||
// SAFETY: Some device is mapped at this address.
|
||||
unsafe {
|
||||
SOME_DEVICE_REGISTER.write_volatile(0xff);
|
||||
SOME_DEVICE_REGISTER.write_volatile(0x80);
|
||||
assert_eq!(SOME_DEVICE_REGISTER.read_volatile(), 0xaa);
|
||||
}
|
||||
```
|
||||
|
||||
[`pointer::read_volatile`]: https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.read_volatile
|
||||
[`pointer::write_volatile`]: https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.write_volatile
|
||||
[`addr_of!`]: https://doc.rust-lang.org/stable/core/ptr/macro.addr_of.html
|
||||
|
@ -15,17 +15,8 @@
|
||||
<details>
|
||||
|
||||
- The RaspberryPi OS tutorial runs Rust code before the MMU and caches are
|
||||
enabled. This will read and write memory (e.g. the stack). However:
|
||||
- Without the MMU and cache, unaligned accesses will fault. It builds with
|
||||
`aarch64-unknown-none` which sets `+strict-align` to prevent the compiler
|
||||
generating unaligned accesses so it should be alright, but this is not
|
||||
necessarily the case in general.
|
||||
- If it were running in a VM, this can lead to cache coherency issues. The
|
||||
problem is that the VM is accessing memory directly with the cache disabled,
|
||||
while the host has cacheable aliases to the same memory. Even if the host
|
||||
doesn't explicitly access the memory, speculative accesses can lead to cache
|
||||
fills, and then changes from one or the other will get lost. Again this is
|
||||
alright in this particular case (running directly on the hardware with no
|
||||
hypervisor), but isn't a good pattern in general.
|
||||
enabled. This will read and write memory (e.g. the stack). However, this has
|
||||
the problems mentioned at the beginning of this session regarding unaligned
|
||||
access and cache coherency.
|
||||
|
||||
</details>
|
||||
|
@ -11,7 +11,8 @@ too.
|
||||
|
||||
- Implementing `Write` lets us use the `write!` and `writeln!` macros with our
|
||||
`Uart` type.
|
||||
- Run the example in QEMU with `make qemu_minimal` under
|
||||
`src/bare-metal/aps/examples`.
|
||||
|
||||
- `Send` is an auto-trait, but not implemented automatically because it is not
|
||||
implemented for pointers.
|
||||
|
||||
</details>
|
||||
|
17
src/bare-metal/aps/uart/using.md
Normal file
17
src/bare-metal/aps/uart/using.md
Normal file
@ -0,0 +1,17 @@
|
||||
# Using it
|
||||
|
||||
Let's write a small program using our driver to write to the serial console.
|
||||
|
||||
```rust,editable,compile_fail
|
||||
{{#include ../examples/src/main_minimal.rs:main}}
|
||||
```
|
||||
|
||||
<details>
|
||||
|
||||
- As in the [inline assembly](../inline-assembly.md) example, this `main`
|
||||
function is called from our entry point code in `entry.S`. See the speaker
|
||||
notes there for details.
|
||||
- Run the example in QEMU with `make qemu_minimal` under
|
||||
`src/bare-metal/aps/examples`.
|
||||
|
||||
</details>
|
@ -1,4 +1,4 @@
|
||||
# Useful crates
|
||||
|
||||
We'll go over a few crates which solve some common problems in bare-metal
|
||||
We'll look at a few crates which solve some common problems in bare-metal
|
||||
programming.
|
||||
|
@ -1,10 +1,11 @@
|
||||
# `buddy_system_allocator`
|
||||
|
||||
[`buddy_system_allocator`][1] is a crate implementing a basic buddy system
|
||||
allocator. It can be used both for [`LockedHeap`][2] implementing
|
||||
[`GlobalAlloc`][3] so you can use the standard `alloc` crate (as we saw
|
||||
[before][4]), or for allocating other address space. For example, we might want
|
||||
to allocate MMIO space for PCI BARs:
|
||||
allocator. It can be used both to implement [`GlobalAlloc`][3] (using
|
||||
[`LockedHeap`][2]) so you can use the standard `alloc` crate (as we saw
|
||||
[before][4]), or for allocating other address space (using
|
||||
[`FrameAllocator`][5]) . For example, we might want to allocate MMIO space for
|
||||
PCI BARs:
|
||||
|
||||
<!-- mdbook-xgettext: skip -->
|
||||
|
||||
@ -25,3 +26,4 @@ to allocate MMIO space for PCI BARs:
|
||||
[2]: https://docs.rs/buddy_system_allocator/0.9.0/buddy_system_allocator/struct.LockedHeap.html
|
||||
[3]: https://doc.rust-lang.org/core/alloc/trait.GlobalAlloc.html
|
||||
[4]: ../alloc.md
|
||||
[5]: https://docs.rs/buddy_system_allocator/0.9.0/buddy_system_allocator/struct.FrameAllocator.html
|
||||
|
@ -12,12 +12,12 @@ primitives.
|
||||
```rust,editable,compile_fail
|
||||
use spin::mutex::SpinMutex;
|
||||
|
||||
static counter: SpinMutex<u32> = SpinMutex::new(0);
|
||||
static COUNTER: SpinMutex<u32> = SpinMutex::new(0);
|
||||
|
||||
fn main() {
|
||||
println!("count: {}", counter.lock());
|
||||
*counter.lock() += 2;
|
||||
println!("count: {}", counter.lock());
|
||||
println!("count: {}", COUNTER.lock());
|
||||
*COUNTER.lock() += 2;
|
||||
println!("count: {}", COUNTER.lock());
|
||||
}
|
||||
```
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user