Showing preview only (1,052K chars total). Download the full file or copy to clipboard to get everything.
Repository: tock/libtock-rs
Branch: master
Commit: 0766d8cf65b2
Files: 290
Total size: 973.9 KB
Directory structure:
gitextract_5tcgoj5o/
├── .cargo/
│ └── config.toml
├── .github/
│ └── workflows/
│ ├── artifacts.yml
│ ├── ci.yml
│ ├── mac-os.yml
│ └── size-diff.yml
├── .gitignore
├── .gitmodules
├── .ignore
├── .vscode/
│ └── settings.json
├── CHANGELOG.md
├── CONTRIBUTING.md
├── Cargo.toml
├── LICENSE-APACHE
├── LICENSE-MIT
├── Makefile
├── README.md
├── Targets.mk
├── apis/
│ ├── display/
│ │ └── screen/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ ├── lib.rs
│ │ └── tests.rs
│ ├── interface/
│ │ ├── buttons/
│ │ │ ├── Cargo.toml
│ │ │ └── src/
│ │ │ ├── lib.rs
│ │ │ └── tests.rs
│ │ ├── buzzer/
│ │ │ ├── Cargo.toml
│ │ │ └── src/
│ │ │ ├── lib.rs
│ │ │ └── tests.rs
│ │ ├── console/
│ │ │ ├── Cargo.toml
│ │ │ └── src/
│ │ │ ├── lib.rs
│ │ │ └── tests.rs
│ │ └── leds/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ ├── lib.rs
│ │ └── tests.rs
│ ├── kernel/
│ │ └── low_level_debug/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ ├── lib.rs
│ │ └── tests.rs
│ ├── net/
│ │ └── ieee802154/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ ├── lib.rs
│ │ ├── rx.rs
│ │ └── tests.rs
│ ├── peripherals/
│ │ ├── adc/
│ │ │ ├── Cargo.toml
│ │ │ └── src/
│ │ │ ├── lib.rs
│ │ │ └── tests.rs
│ │ ├── alarm/
│ │ │ ├── Cargo.toml
│ │ │ └── src/
│ │ │ ├── lib.rs
│ │ │ └── tests.rs
│ │ ├── gpio/
│ │ │ ├── Cargo.toml
│ │ │ └── src/
│ │ │ ├── lib.rs
│ │ │ └── tests.rs
│ │ ├── i2c_master/
│ │ │ ├── Cargo.toml
│ │ │ └── src/
│ │ │ └── lib.rs
│ │ ├── i2c_master_slave/
│ │ │ ├── Cargo.toml
│ │ │ └── src/
│ │ │ └── lib.rs
│ │ ├── rng/
│ │ │ ├── Cargo.toml
│ │ │ └── src/
│ │ │ └── lib.rs
│ │ └── spi_controller/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ └── lib.rs
│ ├── sensors/
│ │ ├── air_quality/
│ │ │ ├── Cargo.toml
│ │ │ └── src/
│ │ │ ├── lib.rs
│ │ │ └── tests.rs
│ │ ├── ambient_light/
│ │ │ ├── Cargo.toml
│ │ │ └── src/
│ │ │ ├── lib.rs
│ │ │ └── tests.rs
│ │ ├── ninedof/
│ │ │ ├── Cargo.toml
│ │ │ └── src/
│ │ │ ├── lib.rs
│ │ │ └── tests.rs
│ │ ├── proximity/
│ │ │ ├── Cargo.toml
│ │ │ └── src/
│ │ │ ├── lib.rs
│ │ │ └── tests.rs
│ │ ├── sound_pressure/
│ │ │ ├── Cargo.toml
│ │ │ └── src/
│ │ │ ├── lib.rs
│ │ │ └── tests.rs
│ │ └── temperature/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ ├── lib.rs
│ │ └── tests.rs
│ └── storage/
│ └── key_value/
│ ├── Cargo.toml
│ └── src/
│ ├── lib.rs
│ └── tests.rs
├── build.rs
├── build_scripts/
│ ├── Cargo.toml
│ ├── README.md
│ ├── libtock_layout.ld
│ └── src/
│ └── lib.rs
├── demos/
│ ├── embedded_graphics/
│ │ ├── buttons/
│ │ │ ├── Cargo.toml
│ │ │ ├── Makefile
│ │ │ ├── README.md
│ │ │ ├── build.rs
│ │ │ └── src/
│ │ │ └── main.rs
│ │ └── spin/
│ │ ├── Cargo.toml
│ │ ├── Makefile
│ │ ├── README.md
│ │ ├── build.rs
│ │ └── src/
│ │ └── main.rs
│ ├── st7789/
│ │ ├── Cargo.toml
│ │ ├── Makefile
│ │ ├── build.rs
│ │ └── src/
│ │ └── main.rs
│ └── st7789-slint/
│ ├── Cargo.toml
│ ├── Makefile
│ ├── build.rs
│ ├── src/
│ │ └── main.rs
│ └── ui/
│ └── appwindow.slint
├── doc/
│ ├── CargoFeatures.md
│ ├── CodeReview.md
│ ├── Dependencies.md
│ ├── DesignConsiderations.md
│ ├── FaultDebuggingExample.md
│ ├── MiriTips.md
│ ├── Overview.md
│ ├── PlatformDesignStory.md
│ ├── Startup.md
│ ├── Style.md
│ ├── Testing.md
│ └── UnitTestOwnership.md
├── examples/
│ ├── adc.rs
│ ├── ambient_light.rs
│ ├── blink.rs
│ ├── buttons.rs
│ ├── console.rs
│ ├── gpio.rs
│ ├── i2c_master_write_read.rs
│ ├── i2c_slave_send_recv.rs
│ ├── ieee802154_raw.rs
│ ├── ieee802154_rx_raw.rs
│ ├── ieee802154_rx_tx_raw.rs
│ ├── ieee802154_tx_raw.rs
│ ├── kv.rs
│ ├── leds.rs
│ ├── low_level_debug.rs
│ ├── music.rs
│ ├── ninedof.rs
│ ├── proximity.rs
│ ├── rng.rs
│ ├── rng_async.rs
│ ├── screen.rs
│ ├── sound_pressure.rs
│ ├── spi_controller_write_read.rs
│ ├── temperature.rs
│ └── usb_i2c_mctp.rs
├── libraries/
│ └── embedded_graphics_libtock/
│ ├── Cargo.toml
│ ├── README.md
│ └── src/
│ ├── lib.rs
│ └── tock_screen.rs
├── nightly/
│ └── rust-toolchain.toml
├── panic_handlers/
│ ├── debug_panic/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ └── lib.rs
│ └── small_panic/
│ ├── Cargo.toml
│ └── src/
│ └── lib.rs
├── platform/
│ ├── Cargo.toml
│ └── src/
│ ├── allow_ro.rs
│ ├── allow_rw.rs
│ ├── command_return.rs
│ ├── command_return_tests.rs
│ ├── constants.rs
│ ├── default_config.rs
│ ├── error_code.rs
│ ├── error_code_tests.rs
│ ├── exit_on_drop.rs
│ ├── lib.rs
│ ├── raw_syscalls.rs
│ ├── register.rs
│ ├── return_variant.rs
│ ├── share/
│ │ ├── handle.rs
│ │ ├── mod.rs
│ │ ├── tests.rs
│ │ └── tuple_impls.rs
│ ├── subscribe.rs
│ ├── syscalls.rs
│ ├── syscalls_impl.rs
│ ├── termination.rs
│ └── yield_types.rs
├── runner/
│ ├── Cargo.toml
│ └── src/
│ ├── elf2tab.rs
│ ├── main.rs
│ ├── output_processor.rs
│ ├── qemu.rs
│ └── tockloader.rs
├── runtime/
│ ├── Cargo.toml
│ └── src/
│ ├── lib.rs
│ ├── startup/
│ │ ├── asm_arm.s
│ │ ├── asm_riscv32.s
│ │ ├── asm_x86.s
│ │ ├── mod.rs
│ │ └── start_prototype.rs
│ ├── syscalls_impl_arm.rs
│ ├── syscalls_impl_riscv.rs
│ └── syscalls_impl_x86.rs
├── rust-toolchain.toml
├── rustfmt.toml
├── src/
│ ├── lib.rs
│ └── spi_controller.rs
├── syscalls_tests/
│ ├── Cargo.toml
│ └── src/
│ ├── allow_ro.rs
│ ├── allow_rw.rs
│ ├── command_tests.rs
│ ├── exit_on_drop.rs
│ ├── lib.rs
│ ├── memop_tests.rs
│ ├── subscribe_tests.rs
│ └── yield_tests.rs
├── tools/
│ └── print_sizes/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── ufmt/
│ ├── Cargo.toml
│ ├── LICENSE-APACHE
│ ├── LICENSE-MIT
│ ├── README.md
│ ├── macros/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ └── lib.rs
│ ├── src/
│ │ ├── helpers.rs
│ │ ├── impls/
│ │ │ ├── array.rs
│ │ │ ├── core.rs
│ │ │ ├── ixx.rs
│ │ │ ├── nz.rs
│ │ │ ├── ptr.rs
│ │ │ ├── std.rs
│ │ │ ├── tuple.rs
│ │ │ └── uxx.rs
│ │ ├── impls.rs
│ │ ├── lib.rs
│ │ └── macros.rs
│ ├── tests/
│ │ └── vs-std-write.rs
│ ├── utils/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ └── lib.rs
│ └── write/
│ ├── Cargo.toml
│ └── src/
│ └── lib.rs
└── unittest/
├── Cargo.toml
└── src/
├── allow_db.rs
├── allow_db_test.rs
├── command_return.rs
├── driver_info.rs
├── exit_test/
│ ├── mod.rs
│ └── tests.rs
├── expected_syscall.rs
├── fake/
│ ├── adc/
│ │ ├── mod.rs
│ │ └── tests.rs
│ ├── air_quality/
│ │ ├── mod.rs
│ │ └── tests.rs
│ ├── alarm/
│ │ ├── mod.rs
│ │ └── tests.rs
│ ├── ambient_light/
│ │ ├── mod.rs
│ │ └── tests.rs
│ ├── buttons/
│ │ ├── mod.rs
│ │ └── tests.rs
│ ├── buzzer/
│ │ ├── mod.rs
│ │ └── tests.rs
│ ├── console/
│ │ ├── mod.rs
│ │ └── tests.rs
│ ├── gpio/
│ │ ├── mod.rs
│ │ └── tests.rs
│ ├── ieee802154/
│ │ └── mod.rs
│ ├── kernel.rs
│ ├── kernel_tests.rs
│ ├── key_value/
│ │ └── mod.rs
│ ├── leds/
│ │ ├── mod.rs
│ │ └── tests.rs
│ ├── low_level_debug/
│ │ ├── mod.rs
│ │ └── tests.rs
│ ├── mod.rs
│ ├── ninedof/
│ │ ├── mod.rs
│ │ └── tests.rs
│ ├── proximity/
│ │ ├── mod.rs
│ │ └── tests.rs
│ ├── screen/
│ │ ├── mod.rs
│ │ └── tests.rs
│ ├── sound_pressure/
│ │ ├── mod.rs
│ │ └── tests.rs
│ ├── syscall_driver.rs
│ ├── syscalls/
│ │ ├── allow_ro_impl.rs
│ │ ├── allow_ro_impl_tests.rs
│ │ ├── allow_rw_impl.rs
│ │ ├── allow_rw_impl_tests.rs
│ │ ├── command_impl.rs
│ │ ├── command_impl_tests.rs
│ │ ├── exit_impl.rs
│ │ ├── exit_impl_tests.rs
│ │ ├── memop_impl.rs
│ │ ├── memop_impl_tests.rs
│ │ ├── mod.rs
│ │ ├── raw_syscalls_impl.rs
│ │ ├── raw_syscalls_impl_tests.rs
│ │ ├── subscribe_impl.rs
│ │ ├── subscribe_impl_tests.rs
│ │ ├── yield_impl.rs
│ │ └── yield_impl_tests.rs
│ └── temperature/
│ ├── mod.rs
│ └── tests.rs
├── kernel_data.rs
├── lib.rs
├── share_data.rs
├── syscall_log.rs
└── upcall.rs
================================================
FILE CONTENTS
================================================
================================================
FILE: .cargo/config.toml
================================================
[alias]
rriscv32imac = "run --release --target=riscv32imac-unknown-none-elf --example"
rrv32imac = "rriscv32imac"
rriscv32imc = "run --release --target=riscv32imc-unknown-none-elf --example"
rrv32imc = "rriscv32imc"
rthumbv7em = "run --release --target=thumbv7em-none-eabi --example"
rtv7em = "rthumbv7em"
# Common settings for all embedded targets
[target.'cfg(any(target_arch = "arm", target_arch = "riscv32", target_arch = "x86"))']
rustflags = [
"-C", "relocation-model=static",
"-C", "link-arg=-icf=all",
]
runner = ["cargo", "run", "-p", "runner", "--release"]
================================================
FILE: .github/workflows/artifacts.yml
================================================
name: Artifacts
on:
push:
branches: [master]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Install dependencies
run: |
cargo install elf2tab
- name: Build LEDs
run: |
make -j2 EXAMPLE=leds apollo3
make -j2 EXAMPLE=leds hail
make -j2 EXAMPLE=leds imix
make -j2 EXAMPLE=leds nucleo_f429zi
make -j2 EXAMPLE=leds nucleo_f446re
make -j2 EXAMPLE=leds nrf52840
make -j2 EXAMPLE=leds opentitan
make -j2 EXAMPLE=leds hifive1
make -j2 EXAMPLE=leds nrf52
- name: Build Low Level Debug
run: |
make -j2 EXAMPLE=low_level_debug apollo3
make -j2 EXAMPLE=low_level_debug hail
make -j2 EXAMPLE=low_level_debug imix
make -j2 EXAMPLE=low_level_debug nucleo_f429zi
make -j2 EXAMPLE=low_level_debug nucleo_f446re
make -j2 EXAMPLE=low_level_debug nrf52840
make -j2 EXAMPLE=low_level_debug opentitan
make -j2 EXAMPLE=low_level_debug hifive1
make -j2 EXAMPLE=low_level_debug nrf52
- name: Archive artifacts
uses: actions/upload-artifact@v4
with:
name: libtock-rs examples
path: target/tbf
================================================
FILE: .github/workflows/ci.yml
================================================
# This workflow provides automated testing. It builds and runs tests on each PR.
name: ci
# We want to run CI on all pull requests. Additionally, GitHub actions merge
# queue needs workflows to run on the `merge_queue` trigger to block merges on
# them.
on:
pull_request:
merge_group:
jobs:
ci:
# Using ubuntu-latest can cause breakage when ubuntu-latest is updated to
# point at a new Ubuntu version. Instead, explicitly specify the version, so
# we can update when we need to. This *could* break if we don't update it
# until support for this version is dropped, but it is likely we'll have a
# reason to update to a newer Ubuntu before then anyway.
runs-on: ubuntu-22.04
steps:
# Clones a single commit from the libtock-rs repository. The commit cloned
# is a merge commit between the PR's target branch and the PR's source.
# Note that we checkout submodules so that we can invoke Tock's CI setup
# scripts, but we do not recursively checkout submodules as we need Tock's
# makefile to set up the qemu submodule itself.
- name: Clone repository
uses: actions/checkout@v3
with:
submodules: true
# The main test step. We let the makefile do most of the work because the
# makefile can be tested locally. We experimentally determined that -j2 is
# optimal for the Azure Standard_DS2_v2 VM, which is the VM type used by
# GitHub Actions at the time of this writing.
#
# We have to append the "-D warnings" flag to .cargo/config.toml rather
# than using the RUSTFLAGS environment variable because if we set
# RUSTFLAGS cargo will ignore the rustflags config in .cargo/config,
# breaking relocation.
- name: Build and Test
run: |
sudo apt-get install ninja-build
cd "${GITHUB_WORKSPACE}"
echo "[target.'cfg(all())']" >> .cargo/config.toml
echo 'rustflags = ["-D", "warnings"]' >> .cargo/config.toml
make -j2 setup
make -j2 test
make demos
================================================
FILE: .github/workflows/mac-os.yml
================================================
# This workflow verifies libtock-rs is usable on Mac OS.
name: ci-mac-os
# We run this workflow during pull request review, but not as a required status
# for GitHub actions merge-queue merges. We can change this if the workflow is
# reasonably quick and reliable.
on: pull_request
jobs:
ci-mac-os:
runs-on: macos-latest
steps:
# Clones a single commit from the libtock-rs repository. The commit cloned
# is a merge commit between the PR's target branch and the PR's source.
- name: Clone repository
uses: actions/checkout@v3
- name: Build and Test
run: |
cd "${GITHUB_WORKSPACE}"
LIBTOCK_PLATFORM=nrf52 cargo build -p libtock \
--target=thumbv7em-none-eabi
LIBTOCK_PLATFORM=hifive1 cargo build -p libtock \
--target=riscv32imac-unknown-none-elf
================================================
FILE: .github/workflows/size-diff.yml
================================================
# Calculates the size diffs for the each example binary. Runs when a pull
# request is created or modified.
name: size-diff
# We want to run this on all pull requests. Additionally, GitHub actions merge
# queue needs workflows to run on the `merge_queue` trigger to block merges on
# them.
on:
pull_request:
merge_group:
jobs:
size-diff:
# Using ubuntu-latest can cause breakage when ubuntu-latest is updated to
# point at a new Ubuntu version. Instead, explicitly specify the version, so
# we can update when we need to. This *could* break if we don't update it
# until support for this version is dropped, but it is likely we'll have a
# reason to update to a newer Ubuntu before then anyway.
runs-on: ubuntu-22.04
steps:
# Clones a single commit from the libtock-rs repository. The commit cloned
# is a merge commit between the PR's target branch and the PR's source.
# We'll later add another commit (the pre-merge target branch) to the
# repository.
- name: Clone repository
uses: actions/checkout@v3
# The main diff script. Stores the sizes of the example binaries for both
# the merge commit and the target branch. We display the diff in a
# separate step to make it easy to navigate to in the GitHub Actions UI.
#
# If the build on master doesn't work (`make -j2 examples` fails), we
# output a warning message and ignore the error. Ignoring the error
# prevents this workflow from blocking PRs that fix a broken build in
# master.
- name: Compute sizes
run: |
UPSTREAM_REMOTE_NAME="${UPSTREAM_REMOTE_NAME:-origin}"
GITHUB_BASE_REF="${GITHUB_BASE_REF:-master}"
cd "${GITHUB_WORKSPACE}"
make -j2 examples # The VM this runs on has 2 logical cores.
cargo run --release -p print_sizes >'${{runner.temp}}/merge-sizes'
git remote set-branches "${UPSTREAM_REMOTE_NAME}" "${GITHUB_BASE_REF}"
git fetch --depth=1 "${UPSTREAM_REMOTE_NAME}" "${GITHUB_BASE_REF}"
git checkout "${UPSTREAM_REMOTE_NAME}/${GITHUB_BASE_REF}"
make -j2 examples && \
cargo run --release -p print_sizes >'${{runner.temp}}/base-sizes' || \
echo 'Broken build on the master branch.'
# Computes and displays the size diff. diff returns a nonzero status code
# if the files differ, and GitHub interprets a nonzero status code as an
# error. To avoid GitHub interpreting a difference as an error, we add
# || exit 0 to the command. This also prevents the workflow from failing
# if the master build is broken and we didn't generate base-sizes.
- name: Size diff
run: diff '${{runner.temp}}/base-sizes' '${{runner.temp}}/merge-sizes' || exit 0
================================================
FILE: .gitignore
================================================
/Cargo.lock
/nightly/target
/target
/demos/*/target
/demos/*/*/target
================================================
FILE: .gitmodules
================================================
[submodule "tock"]
path = tock
url = https://github.com/tock/tock.git
================================================
FILE: .ignore
================================================
# Cargo and GitHub Actions keep their configs in hidden directories. Some search
# tools skip hidden directories by default. This overrides that, and makes them
# search .cargo and .github.
!.cargo/
!.github/
# Tell search tools to ignore the Tock submodule. Usually when someone wants to
# search this repository they want to search libtock-rs' codebase, not the Tock
# kernel.
/tock/
================================================
FILE: .vscode/settings.json
================================================
{
"editor.formatOnSave": true,
"rust.all_targets": true,
"rust.clippy_preference": "on"
}
================================================
FILE: CHANGELOG.md
================================================
# Releases
## 0.2.0 (WIP)
### Comprehensive Changes
- Many functions are asynchronous
- To create an `async` main function you can use the attribute `#[libtock::main]`
- To retrieve the value of an asynchronous `value`, use `value.await`
- This is only possible within an `async fn`, so either
- Make the caller `fn` of `.await` an `async fn`
- Not recommended: Use `libtock::executor::block_on(value)` to retrieve the `value`
- Most API functions, including `main()`, return a `Result<T, TockError>`
- All drivers can exclusively be retrieved by `retrieve_drivers` which returns a `Drivers` singleton. Drivers can be shared between different tasks only if it is safe to do so.
- The low-level functions have been moved to a new crate called `libtock-core`. This crate is intended to be less experimental and more stable.
### Changed APIs
- The basic APIs have been made consistent. They are initialized via driver factories and no longer require a `WithCallback` object, s.t. the callback subscription is more intuitive. The affected APIs are:
- LEDs
- Buttons
- GPIO
- Temperature
- ADC (partially)
- The timer API now supports concurrent sleep operations
### Syscalls
- `syscalls::subscribe` is actually usable
- `syscalls::yieldk_for` is no longer available
- Yielding manually is discouraged as it conflicts with Rust's safety guarantees. If you need to wait for a condition, use `futures::wait_until` and `.await`.
- `syscalls::yieldk` has become `unsafe` for the same reason
- `syscalls::command` is no longer `unsafe`
- The low-level syscalls have been moved to `syscalls::raw`
- `syscalls::subscribe_ptr` becomes `syscalls::raw::subscribe`
- `syscalls::allow_ptr` becomes `syscalls::raw::allow`
### Miscellaneous
- Flashing examples is no longer restricted to the nRF52 DK board
- `./run_example.sh` has been deleted
- Instead, use `PLATFORM=<platform> cargo r<arch> <your_app>`. This will build the app for your CPU architecture and platform-specific memory layout and flash it via J-Link to your board
- Targets without support for atomics can be built
- The `TockAllocator` is no longer included by default and needs to to be opted-in via `--features=alloc`
- `hardware_test.rs` is now called `libtock_test.rs` to make clear that the intent is to test the correctness of `libtock-rs`, not the hardware or the kernel
- The panic handler can now be customized using the `custom_panic_handler` feature
- The error alloc handler can now be customized using the `custom_alloc_error_handler` feature
## a8bb4fa9be504517d5533511fd8e607ea61f1750 (0.1.0)
- First and highly experimental `libtock-rs` API
================================================
FILE: CONTRIBUTING.md
================================================
# Tests
Our aim is to provide a number of tests to be safe from regression.
## Compilation
`libtock-rs` currently has the following compilation targets
- `riscv32imac-unknown-none-elf`
- `riscv32imc-unknown-none-elf`
- `thumbv7em-none-eabi`
You can trigger a test build of the library and the examples using `make test`.
You can run the library's test suite using `make test`.
# PR Review Workflow
Our code review practices are documented in our [Code Review](doc/CodeReview.md)
document.
================================================
FILE: Cargo.toml
================================================
[package]
authors = ["Tock Project Developers <tock-dev@googlegroups.com>"]
categories = ["embedded", "no-std", "os"]
description = """Tock Rust userspace library collection. Provides all the \
tools needed to create a Tock Rust process binary."""
edition = "2021"
license = "Apache-2.0 OR MIT"
name = "libtock"
repository = "https://www.github.com/tock/libtock-rs"
rust-version.workspace = true
version = "0.1.0"
[workspace.package]
# This must be kept in sync with rust-toolchain.toml; please see that file for
# more information.
rust-version = "1.87"
[features]
rust_embedded = [
"embedded-hal",
"libtock_platform/rust_embedded",
"libtock_gpio/rust_embedded",
]
[dependencies]
libtock_adc = { path = "apis/peripherals/adc" }
libtock_air_quality = { path = "apis/sensors/air_quality" }
libtock_alarm = { path = "apis/peripherals/alarm" }
libtock_ambient_light = { path = "apis/sensors/ambient_light" }
libtock_buttons = { path = "apis/interface/buttons" }
libtock_buzzer = { path = "apis/interface/buzzer" }
libtock_console = { path = "apis/interface/console" }
libtock_debug_panic = { path = "panic_handlers/debug_panic" }
libtock_gpio = { path = "apis/peripherals/gpio" }
libtock_i2c_master = { path = "apis/peripherals/i2c_master" }
libtock_ieee802154 = { path = "apis/net/ieee802154" }
libtock_i2c_master_slave = { path = "apis/peripherals/i2c_master_slave" }
libtock_key_value = { path = "apis/storage/key_value" }
libtock_leds = { path = "apis/interface/leds" }
libtock_low_level_debug = { path = "apis/kernel/low_level_debug" }
libtock_ninedof = { path = "apis/sensors/ninedof" }
libtock_platform = { path = "platform" }
libtock_proximity = { path = "apis/sensors/proximity" }
libtock_screen = { path = "apis/display/screen" }
libtock_rng = { path = "apis/peripherals/rng" }
libtock_runtime = { path = "runtime" }
libtock_small_panic = { path = "panic_handlers/small_panic" }
libtock_sound_pressure = { path = "apis/sensors/sound_pressure" }
libtock_spi_controller = { path = "apis/peripherals/spi_controller" }
libtock_temperature = { path = "apis/sensors/temperature" }
embedded-hal = { version = "1.0", optional = true }
[build-dependencies]
libtock_build_scripts = { path = "build_scripts" }
[profile.dev]
debug = true
lto = true
panic = "abort"
[profile.release]
debug = true
lto = true
panic = "abort"
opt-level = "z"
codegen-units = 1
[workspace]
exclude = ["tock"]
members = [
"apis/interface/buttons",
"apis/interface/buzzer",
"apis/interface/console",
"apis/interface/leds",
"apis/kernel/low_level_debug",
"apis/peripherals/adc",
"apis/peripherals/alarm",
"apis/peripherals/gpio",
"apis/peripherals/i2c_master",
"apis/peripherals/i2c_master_slave",
"apis/peripherals/rng",
"apis/sensors/air_quality",
"apis/sensors/ambient_light",
"apis/sensors/ninedof",
"apis/display/screen",
"apis/sensors/proximity",
"apis/sensors/temperature",
"apis/storage/key_value",
"libraries/embedded_graphics_libtock",
"panic_handlers/debug_panic",
"panic_handlers/small_panic",
"platform",
"runner",
"runtime",
"syscalls_tests",
"tools/print_sizes",
"ufmt",
"unittest",
]
================================================
FILE: LICENSE-APACHE
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
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.
================================================
FILE: LICENSE-MIT
================================================
Copyright (c) 2016 The Tock Project Developers
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: Makefile
================================================
# Make uses /bin/sh by default, which is a different shell on different OSes.
# Specify Bash instead so we don't have to test against a variety of shells.
SHELL := /usr/bin/env bash
# By default, let's print out some help
.PHONY: usage
usage:
@echo "$$(tput bold)Welcome to libtock-rs!$$(tput sgr0)"
@echo
@echo "First things first, if you haven't yet, check out Tocks's doc/Getting_Started."
@echo "After that read the README from libtock-rs"
@echo "You'll need to install a few requirements before we get going."
@echo
@echo "The next step is to choose a board to build Tock for. Mainline"
@echo "libtock-rs currently includes support for the following platforms:"
@echo " - apollo3"
@echo " - clue_nrf52840"
@echo " - esp32_c3_devkitm_1"
@echo " - hail"
@echo " - hifive1"
@echo " - imxrt1050"
@echo " - microbit_v2"
@echo " - nrf52"
@echo " - nrf52840"
@echo " - nucleo_f429zi"
@echo " - nucleo_f446re"
@echo " - opentitan"
@echo " - qemu_rv32_virt"
@echo " - stm32f3discovery"
@echo " - stm32f412gdiscovery"
@echo " - esp32_c3_devkitm_1"
@echo " - clue_nrf52840"
@echo " - raspberry_pi_pico"
@echo " - pico_explorer_base"
@echo
@echo "Run 'make setup' to setup Rust to build libtock-rs."
@echo "Run 'make <board> EXAMPLE=<>' to build EXAMPLE for that board."
@echo "Run 'make flash-<board> EXAMPLE=<>' to flash EXAMPLE to a tockloader-supported board."
@echo "Run 'make qemu-example EXAMPLE=<>' to run EXAMPLE in QEMU"
@echo "Run 'make test' to test any local changes you have made"
@echo "Run 'make print-sizes' to print size data for the example binaries"
ifdef FEATURES
features=--features=$(FEATURES)
endif
ifndef DEBUG
release=--release
artifact_dir=release
else
artifact_dir=debug
endif
# Rustup currently lacks the locking needed for concurrent use:
# https://github.com/rust-lang/rustup/issues/988. In particular, running
# concurrent cargo commands with a missing toolchain results in parallel rustup
# instances installing the same toolchain, corrupting that toolchain. To
# mitigate that issue, every target that uses the main (MSRV) toolchain should
# depend transitively on the `toolchain` target, so that the toolchain is
# installed before it is invoked concurrently. Note that we don't need to do
# this for the nightly toolchain because the nightly toolchain is only used by
# the `test` target, so this Makefile won't invoke it concurrently.
.PHONY: toolchain
toolchain:
cargo -V
.PHONY: setup
setup: setup-qemu toolchain
cargo install elf2tab
# Sets up QEMU in the tock/ directory. We use Tock's QEMU which may contain
# patches to better support boards that Tock supports.
.PHONY: setup-qemu
setup-qemu:
CI=true $(MAKE) -C tock ci-setup-qemu
# Builds a Tock 2.0 kernel for the HiFive board for use by QEMU tests.
.PHONY: kernel-hifive
kernel-hifive:
$(MAKE) -C tock/boards/hifive1 \
$(CURDIR)/tock/target/riscv32imac-unknown-none-elf/release/hifive1.elf
# Builds a Tock kernel for the OpenTitan board on the cw310 FPGA for use by QEMU
# tests.
.PHONY: kernel-opentitan
kernel-opentitan:
CARGO_TARGET_RISCV32IMC_UNKNOWN_NONE_ELF_RUNNER="[]" \
$(MAKE) -C tock/boards/opentitan/earlgrey-cw310 \
$(CURDIR)/tock/target/riscv32imc-unknown-none-elf/release/earlgrey-cw310.elf
# Prints out the sizes of the example binaries.
.PHONY: print-sizes
print-sizes: examples toolchain
cargo run --release -p print_sizes
# Runs a libtock example in QEMU on a simulated HiFive board.
.PHONY: qemu-example
qemu-example: kernel-hifive toolchain
LIBTOCK_PLATFORM="hifive1" cargo run --example "$(EXAMPLE)" -p libtock \
--release --target=riscv32imac-unknown-none-elf -- --deploy qemu
# Build the examples on both a RISC-V target and an ARM target. We pick
# opentitan as the RISC-V target because it lacks atomics.
.PHONY: examples
examples: toolchain
LIBTOCK_PLATFORM=nrf52 cargo build --examples --release \
--target=thumbv7em-none-eabi
LIBTOCK_PLATFORM=opentitan cargo build --examples --release \
--target=riscv32imc-unknown-none-elf
# Arguments to pass to cargo to exclude crates that require a Tock runtime.
# This is largely libtock_runtime and crates that depend on libtock_runtime.
# Used when we need to build a crate for the host OS, as libtock_runtime only
# supports running on Tock.
EXCLUDE_RUNTIME := --exclude libtock --exclude libtock_runtime \
--exclude libtock_debug_panic --exclude libtock_small_panic --exclude embedded_graphics_libtock
# Arguments to pass to cargo to exclude crates that cannot be tested by Miri. In
# addition to excluding libtock_runtime, Miri also cannot test proc macro crates
# (and in fact will generate broken data that causes cargo test to fail).
EXCLUDE_MIRI := $(EXCLUDE_RUNTIME) --exclude ufmt-macros
# Arguments to pass to cargo to exclude `std` and crates that depend on it. Used
# when we build a crate for an embedded target, as those targets lack `std`.
EXCLUDE_STD := --exclude libtock_unittest --exclude print_sizes \
--exclude runner --exclude syscalls_tests \
--exclude libtock_build_scripts
.PHONY: test
test: examples
cargo test $(EXCLUDE_RUNTIME) --workspace
LIBTOCK_PLATFORM=nrf52 cargo fmt --all -- --check
cargo clippy --all-targets $(EXCLUDE_RUNTIME) --workspace
LIBTOCK_PLATFORM=nrf52 cargo clippy $(EXCLUDE_STD) \
--target=thumbv7em-none-eabi --workspace
LIBTOCK_PLATFORM=hifive1 cargo clippy $(EXCLUDE_STD) \
--target=riscv32imac-unknown-none-elf --workspace
cd nightly && \
MIRIFLAGS="-Zmiri-strict-provenance -Zmiri-symbolic-alignment-check" \
cargo miri test $(EXCLUDE_MIRI) --manifest-path=../Cargo.toml \
--target-dir=target --workspace
echo '[ SUCCESS ] libtock-rs tests pass'
include Targets.mk
$(ELF_TARGETS): toolchain
LIBTOCK_LINKER_FLASH=$(F) LIBTOCK_LINKER_RAM=$(R) cargo build --example $(EXAMPLE) $(features) --target=$(T) $(release)
@mkdir -p target/$(A).$(F).$(R)/
@cp target/$(T)/$(artifact_dir)/examples/$(EXAMPLE) target/$(A).$(F).$(R)/
$(eval ELF_LIST += target/$(A).$(F).$(R)/$(EXAMPLE),$(A).$(F).$(R))
# This target (`make tab`) is not parallel-safe
.PHONY: tab
tab: $(ELF_TARGETS)
mkdir -p target/tab
elf2tab --kernel-major 2 --kernel-minor 1 -n $(EXAMPLE) -o target/tab/$(EXAMPLE).tab --stack 1024 --minimum-footer-size 256 $(ELF_LIST)
# Creates the `make <BOARD> EXAMPLE=<EXAMPLE>` targets. Arguments:
# 1) The name of the platform to build for.
# 2) The target architecture the platform uses.
#
# A different --target-dir is passed for each platform to prevent race
# conditions between concurrent cargo run invocations. See
# https://github.com/tock/libtock-rs/issues/366 for more information.
define platform_build
.PHONY: $(1)
$(1): toolchain
LIBTOCK_PLATFORM=$(1) cargo run --example $(EXAMPLE) $(features) \
$(release) --target=$(2) --target-dir=target/$(1)
mkdir -p target/tbf/$(1)
cp target/$(1)/$(2)/release/examples/$(EXAMPLE).{tab,tbf} \
target/tbf/$(1)
endef
# Creates the `make flash-<BOARD> EXAMPLE=<EXAMPLE>` targets. Arguments:
# 1) The name of the platform to flash for.
define platform_flash
.PHONY: flash-$(1)
flash-$(1): toolchain
LIBTOCK_PLATFORM=$(1) cargo run --example $(EXAMPLE) $(features) \
$(release) --target=$(2) --target-dir=target/flash-$(1) -- \
--deploy=tockloader
endef
$(eval $(call platform_build,apollo3,thumbv7em-none-eabi))
$(eval $(call platform_build,esp32_c3_devkitm_1,riscv32imc-unknown-none-elf))
$(eval $(call platform_build,hail,thumbv7em-none-eabi))
$(eval $(call platform_flash,hail,thumbv7em-none-eabi))
$(eval $(call platform_build,imix,thumbv7em-none-eabi))
$(eval $(call platform_flash,imix,thumbv7em-none-eabi))
$(eval $(call platform_build,microbit_v2,thumbv7em-none-eabi))
$(eval $(call platform_flash,microbit_v2,thumbv7em-none-eabi))
$(eval $(call platform_build,nucleo_f429zi,thumbv7em-none-eabi))
$(eval $(call platform_build,nucleo_f446re,thumbv7em-none-eabi))
$(eval $(call platform_build,nrf52840,thumbv7em-none-eabi))
$(eval $(call platform_flash,nrf52840,thumbv7em-none-eabi))
$(eval $(call platform_build,raspberry_pi_pico,thumbv6m-none-eabi))
$(eval $(call platform_build,pico_explorer_base,thumbv6m-none-eabi))
$(eval $(call platform_build,nano33ble,thumbv6m-none-eabi))
$(eval $(call platform_build,nano_rp2040_connect,thumbv6m-none-eabi))
$(eval $(call platform_build,qemu_rv32_virt,riscv32imac-unknown-none-elf))
$(eval $(call platform_build,stm32f3discovery,thumbv7em-none-eabi))
$(eval $(call platform_build,stm32f412gdiscovery,thumbv7em-none-eabi))
$(eval $(call platform_build,opentitan,riscv32imc-unknown-none-elf))
$(eval $(call platform_build,hifive1,riscv32imac-unknown-none-elf))
$(eval $(call platform_build,nrf52,thumbv7em-none-eabi))
$(eval $(call platform_flash,nrf52,thumbv7em-none-eabi))
$(eval $(call platform_build,imxrt1050,thumbv7em-none-eabi))
$(eval $(call platform_build,msp432,thumbv7em-none-eabi))
$(eval $(call platform_build,clue_nrf52840,thumbv7em-none-eabi))
$(eval $(call platform_flash,clue_nrf52840,thumbv7em-none-eabi))
.PHONY: demos
demos:
$(MAKE) -C demos/embedded_graphics/spin
$(MAKE) -C demos/embedded_graphics/buttons
$(MAKE) -C demos/st7789
$(MAKE) -C demos/st7789-slint
# clean cannot safely be invoked concurrently with other actions, so we don't
# need to depend on toolchain. We also manually remove the nightly toolchain's
# target directory, in case the user doesn't want to install the nightly
# toolchain.
.PHONY: clean
clean:
cargo clean
rm -fr nightly/target/
cd demos/st7789 && cargo clean
$(MAKE) -C tock clean
================================================
FILE: README.md
================================================

# libtock-rs
Rust userland library for Tock
Generally this library was tested with Tock [Release
2.1.1](https://github.com/tock/tock/releases/tag/release-2.1.1).
The library should work on all Tock boards, but currently apps must be compiled
for the flash and RAM address they are executed at. See [Fix
relocation](https://github.com/tock/libtock-rs/issues/28) for more details. You
may either compile a process binary especially for your board and use only a
single application written in rust at a time, or use the `make tab` target that
builds examples for a series of likely useful flash and RAM addresses.
## Getting Started
1. Ensure you have [rustup](https://www.rustup.rs/) installed.
1. Clone the repository:
```shell
git clone --recursive https://github.com/tock/libtock-rs
cd libtock-rs
```
1. Install the dependencies:
```shell
make setup
```
1. Use `make` to build examples
```shell
make nrf52 EXAMPLE=console # Builds the console example for the nrf52
```
## Using libtock-rs
The easiest way to start using libtock-rs is adding an example to the
`examples/` folder. We recommend starting by copying the `console` example, as
it is a simple example that shows you how to perform normal debug prints.
### Building for a specific board
To build your example for your board you can use
```shell
make <platform> EXAMPLE=<example>
```
An example can be flashed to your board after the build process by running:
```shell
make flash-<platform> EXAMPLE=<example>
```
This script does the following steps for you:
- cross-compile your program
- create a TAB (tock application bundle)
- if you have a J-Link compatible board connected: flash this TAB to your board (using tockloader)
### Enabling rust-embedded support
libtock-rs can be built to be compatible with the rust-embedded
[embedded_hal](https://docs.rs/embedded-hal/1.0.0/embedded_hal/index.html) by
including the following when running `make`
```shell
FEATURES=rust_embedded
```
If using libtock-rs or a sub-crate as a cargo dependency the `rust_embedded`
can also be enabled via Cargo.
### Building a generic TAB (Tock Application Bundle) file
To build your example for a variety of boards you can use
```shell
make tab EXAMPLE=<example>
```
To install the tab use tockloader
```shell
tockloader install target/tab/<example.tab>
```
Tockloader will determine which compiled version with the correct flash and RAM
addresses to use.
## License
libtock-rs is licensed under either of
- Apache License, Version 2.0
([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license
([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
at your option.
Submodules, as well as the code in the `ufmt` directory, have their own licenses.
### Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
dual licensed as above, without any additional terms or conditions.
The contribution guidelines can be found here: [contribution guidelines](CONTRIBUTING.md)
================================================
FILE: Targets.mk
================================================
# Helper makefile to define build location targets for many common tock
# platforms.
#
# To use:
#
# include Targets.mk
# Helper functions to define make targets to build for specific (flash, ram,
# target) compilation tuples.
#
# Inspiration from these answers:
# - https://stackoverflow.com/a/50357925
# - https://stackoverflow.com/a/9458230
#
# To create a compilation target for a specific architecture with specific flash
# and RAM addresses, use `fixed-target`:
#
# ```
# $(call fixed-target, F=0x00030000 R=0x20008000 T=thumbv7em-none-eabi A=cortex-m4)
# ```
#
# The "arguments" if you will are:
# - F = Flash Address: The address in flash the app is compiled for.
# - R = RAM Address: The address in RAM the app is compiled for.
# - T = Target: The cargo target to compile for.
# - A = Architecture: The Tock architecture name the target corresponds to.
#
# This technique uses two make variables internally to keep track of state:
# - `ELF_TARGETS`: This is the list of unique targets for each compilation
# tuple. Each target invokes `cargo build` with the specified settings.
# - `ELF_LIST`: The is a list of .elf paths of the generated elfs (one per
# compilation tuple). This is passed to `elf2tab` to generate the output .tab
# file.
#
# Internally, what `fixed-target` does is define a new make target named the
# join of all of the F/R/T/A variables (with the `=` characters removed) and
# then assigns target variables to that new target to represent the compilation
# tuple values.
concat = $(subst =,,$(subst $(eval ) ,,$1))
fixed-target = $(foreach A,$1,$(eval $(call concat,$1): $A)) $(eval ELF_TARGETS += $(call concat,$1))
$(call fixed-target, F=0x00030000 R=0x20008000 T=thumbv7em-none-eabi A=cortex-m4)
$(call fixed-target, F=0x00038000 R=0x20010000 T=thumbv7em-none-eabi A=cortex-m4)
$(call fixed-target, F=0x00040000 R=0x10002000 T=thumbv7em-none-eabi A=cortex-m4)
$(call fixed-target, F=0x00048000 R=0x1000a000 T=thumbv7em-none-eabi A=cortex-m4)
$(call fixed-target, F=0x00040000 R=0x20008000 T=thumbv7em-none-eabi A=cortex-m4)
$(call fixed-target, F=0x00042000 R=0x2000a000 T=thumbv7em-none-eabi A=cortex-m4)
$(call fixed-target, F=0x00048000 R=0x20010000 T=thumbv7em-none-eabi A=cortex-m4)
$(call fixed-target, F=0x00080000 R=0x20006000 T=thumbv7em-none-eabi A=cortex-m4)
$(call fixed-target, F=0x00088000 R=0x2000e000 T=thumbv7em-none-eabi A=cortex-m4)
$(call fixed-target, F=0x403b0000 R=0x3fca2000 T=riscv32imc-unknown-none-elf A=rv32imc)
$(call fixed-target, F=0x40440000 R=0x3fcaa000 T=riscv32imc-unknown-none-elf A=rv32imc)
$(call fixed-target, F=0x80100000 R=0x80300000 T=riscv32imac-unknown-none-elf A=rv32imac)
$(call fixed-target, F=0x80110000 R=0x80310000 T=riscv32imac-unknown-none-elf A=rv32imac)
$(call fixed-target, F=0x80130000 R=0x80330000 T=riscv32imac-unknown-none-elf A=rv32imac)
$(call fixed-target, F=0x80180000 R=0x80380000 T=riscv32imac-unknown-none-elf A=rv32imac)
$(call fixed-target, F=0x10020000 R=0x20004000 T=thumbv6m-none-eabi A=cortex-m0)
$(call fixed-target, F=0x10028000 R=0x2000c000 T=thumbv6m-none-eabi A=cortex-m0)
$(call fixed-target, F=0x10040000 R=0x20020000 T=thumbv8m.main-none-eabi A=cortex-m33)
$(call fixed-target, F=0x10060000 R=0x20028000 T=thumbv8m.main-none-eabi A=cortex-m33)
================================================
FILE: apis/display/screen/Cargo.toml
================================================
[package]
name = "libtock_screen"
version = "0.1.0"
authors = ["Tock Project Developers <tock-dev@googlegroups.com>"]
license = "Apache-2.0 OR MIT"
edition = "2021"
repository = "https://www.github.com/tock/libtock-rs"
rust-version.workspace = true
description = "libtock display driver"
[dependencies]
libtock_platform = { path = "../../../platform" }
[dev-dependencies]
libtock_unittest = { path = "../../../unittest" }
================================================
FILE: apis/display/screen/src/lib.rs
================================================
#![no_std]
use core::cell::Cell;
use libtock_platform::allow_ro::AllowRo;
use libtock_platform::share;
use libtock_platform::subscribe::Subscribe;
use libtock_platform::{self as platform, DefaultConfig};
use libtock_platform::{ErrorCode, Syscalls};
pub struct Screen<S: Syscalls, C: Config = DefaultConfig>(S, C);
impl<S: Syscalls, C: Config> Screen<S, C> {
/// Check if the Screen driver exists
pub fn exists() -> Result<(), ErrorCode> {
let val = S::command(DRIVER_NUM, command::EXISTS, 0, 0).is_success();
if val {
Ok(())
} else {
Err(ErrorCode::Fail)
}
}
/// Perform initial screen setup
pub fn screen_setup() -> Result<u32, ErrorCode> {
S::command(DRIVER_NUM, command::SCREEN_SETUP, 0, 0).to_result()
}
/// Turn on Screen power
pub fn set_power(value: usize) -> Result<(), ErrorCode> {
if value != 0 {
S::command(DRIVER_NUM, command::SET_POWER, value as u32, 0).to_result()
} else {
Err(ErrorCode::Invalid)
}
}
/// Set screen brightness, wait for completion via subscribe
pub fn set_brightness(value: usize) -> Result<(), ErrorCode> {
let called: Cell<Option<(u32,)>> = Cell::new(None);
share::scope(|subscribe| {
S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::WRITE }>(subscribe, &called)?;
S::command(DRIVER_NUM, command::SET_BRIGHTNESS, value as u32, 0)
.to_result::<(), _>()?;
loop {
S::yield_wait();
if let Some((_,)) = called.get() {
return Ok(());
}
}
})
}
/// Turn on screen color inversion
pub fn set_invert_on() -> Result<(), ErrorCode> {
let called: Cell<Option<(u32,)>> = Cell::new(None);
share::scope(|subscribe| {
S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::WRITE }>(subscribe, &called)?;
S::command(DRIVER_NUM, command::SET_INVERT_ON, 0, 0).to_result::<(), _>()?;
loop {
S::yield_wait();
if let Some((_,)) = called.get() {
return Ok(());
}
}
})
}
/// Turn off screen color inversion
pub fn set_invert_off() -> Result<(), ErrorCode> {
let called: Cell<Option<(u32,)>> = Cell::new(None);
share::scope(|subscribe| {
S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::WRITE }>(subscribe, &called)?;
S::command(DRIVER_NUM, command::SET_INVERT_OFF, 0, 0).to_result::<(), _>()?;
loop {
S::yield_wait();
if let Some((_,)) = called.get() {
return Ok(());
}
}
})
}
/// Set inversion using a numeric value (non-zero = on)
pub fn set_invert(value: usize) -> Result<(), ErrorCode> {
if value != 0 {
S::command(DRIVER_NUM, command::SET_INVERT, value as u32, 0).to_result()
} else {
Err(ErrorCode::Invalid)
}
}
/// Get the number of supported resolution modes
pub fn get_resolution_modes_count() -> Result<u32, ErrorCode> {
S::command(DRIVER_NUM, command::GET_RESOLUTION_MODES_COUNT, 0, 0).to_result()
}
/// Get width and height for a given resolution index
pub fn get_resolution_width_height(index: usize) -> Result<(u32, u32), ErrorCode> {
S::command(
DRIVER_NUM,
command::GET_RESOLUTION_WIDTH_HEIGHT,
index as u32,
0,
)
.to_result()
}
/// Get the number of supported pixel modes
pub fn pixel_modes_count() -> Result<u32, ErrorCode> {
S::command(DRIVER_NUM, command::PIXEL_MODES_COUNT, 0, 0).to_result()
}
/// Get the pixel format at a specific index
pub fn pixel_format(index: usize) -> Result<u32, ErrorCode> {
S::command(DRIVER_NUM, command::PIXEL_FORMAT, index as u32, 0).to_result()
}
/// Get the current rotation of the screen
pub fn get_rotation() -> Result<u32, ErrorCode> {
let called: Cell<Option<(u32,)>> = Cell::new(None);
share::scope(|subscribe| {
S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::WRITE }>(subscribe, &called)?;
let val = S::command(DRIVER_NUM, command::GET_ROTATION, 0, 0).to_result();
val?;
loop {
S::yield_wait();
if let Some((_,)) = called.get() {
return val;
}
}
})
}
/// Set the screen rotation
pub fn set_rotation(rotation: usize) -> Result<(), ErrorCode> {
let called: Cell<Option<(u32,)>> = Cell::new(None);
share::scope(|subscribe| {
S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::WRITE }>(subscribe, &called)?;
S::command(DRIVER_NUM, command::SET_ROTATION, rotation as u32, 0)
.to_result::<(), _>()?;
loop {
S::yield_wait();
if let Some((_,)) = called.get() {
return Ok(());
}
}
})
}
/// Get the currently set screen resolution
pub fn get_resolution() -> Result<(u32, u32), ErrorCode> {
S::command(DRIVER_NUM, command::GET_RESOLUTION, 0, 0).to_result()
}
/// Set the screen resolution
pub fn set_resolution(width: usize, height: usize) -> Result<(), ErrorCode> {
let called: Cell<Option<(u32,)>> = Cell::new(None);
share::scope(|subscribe| {
S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::WRITE }>(subscribe, &called)?;
S::command(
DRIVER_NUM,
command::SET_RESOLUTION,
width as u32,
height as u32,
)
.to_result::<(), _>()?;
loop {
S::yield_wait();
if let Some((_,)) = called.get() {
return Ok(());
}
}
})
}
/// Get the currently set pixel format
pub fn get_pixel_format() -> Result<u32, ErrorCode> {
S::command(DRIVER_NUM, command::GET_PIXEL_FORMAT, 0, 0).to_result()
}
/// Set the pixel format
pub fn set_pixel_format(format: usize) -> Result<(), ErrorCode> {
let called: Cell<Option<(u32,)>> = Cell::new(None);
share::scope(|subscribe| {
S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::WRITE }>(subscribe, &called)?;
S::command(DRIVER_NUM, command::SET_PIXEL_FORMAT, format as u32, 0)
.to_result::<(), _>()?;
loop {
S::yield_wait();
if let Some((_,)) = called.get() {
return Ok(());
}
}
})
}
/// Define the region of the screen that will be written to
pub fn set_write_frame(x: u32, y: u32, width: u32, height: u32) -> Result<(), ErrorCode> {
let data1: u32 = ((x & 0xFFFF) << 16_u8) | (y & 0xFFFF);
let data2: u32 = ((width & 0xFFFF) << 16_u8) | (height & 0xFFFF);
let called: Cell<Option<(u32,)>> = Cell::new(None);
share::scope(|subscribe| {
S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::WRITE }>(subscribe, &called)?;
S::command(DRIVER_NUM, command::SET_WRITE_FRAME, data1, data2).to_result::<(), _>()?;
loop {
S::yield_wait();
if let Some((_,)) = called.get() {
return Ok(());
}
}
})
}
/// Write data to the screen using the given buffer
pub fn write(s: &[u8]) -> Result<(), ErrorCode> {
let called: Cell<Option<(u32,)>> = Cell::new(None);
share::scope::<
(
AllowRo<_, DRIVER_NUM, { allow_ro::WRITE_BUFFER_ID }>,
Subscribe<_, DRIVER_NUM, { subscribe::WRITE }>,
),
_,
_,
>(|handle| {
let (allow_ro, subscribe) = handle.split();
S::allow_ro::<C, DRIVER_NUM, { allow_ro::WRITE_BUFFER_ID }>(allow_ro, s)?;
S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::WRITE }>(subscribe, &called)?;
S::command(DRIVER_NUM, command::WRITE, s.len() as u32, 0).to_result::<(), _>()?;
loop {
S::yield_wait();
if let Some((_,)) = called.get() {
return Ok(());
}
}
})
}
/// Fill the screen
pub fn fill(s: &mut [u8], color: u16) -> Result<(), ErrorCode> {
if s.len() >= 2 {
s[0] = ((color >> 8) & 0xFF) as u8;
s[1] = (color & 0xFF) as u8;
let called: Cell<Option<(u32,)>> = Cell::new(None);
share::scope::<
(
AllowRo<_, DRIVER_NUM, { allow_ro::WRITE_BUFFER_ID }>,
Subscribe<_, DRIVER_NUM, { subscribe::WRITE }>,
),
_,
_,
>(|handle| {
let (allow_ro, subscribe) = handle.split();
S::allow_ro::<C, DRIVER_NUM, { allow_ro::WRITE_BUFFER_ID }>(allow_ro, s)?;
S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::WRITE }>(subscribe, &called)?;
S::command(DRIVER_NUM, command::FILL, 0, 0).to_result::<(), _>()?;
loop {
S::yield_wait();
if let Some((_,)) = called.get() {
return Ok(());
}
}
})
} else {
Err(ErrorCode::Fail)
}
}
}
pub trait Config:
platform::allow_ro::Config + platform::allow_rw::Config + platform::subscribe::Config
{
}
impl<T: platform::allow_ro::Config + platform::allow_rw::Config + platform::subscribe::Config>
Config for T
{
}
#[cfg(test)]
mod tests;
// -----------------------------------------------------------------------------
// Driver number and command IDs
// -----------------------------------------------------------------------------
const DRIVER_NUM: u32 = 0x90001;
// Command IDs
#[allow(unused)]
mod command {
pub const EXISTS: u32 = 0;
pub const SCREEN_SETUP: u32 = 1;
pub const SET_POWER: u32 = 2;
pub const SET_BRIGHTNESS: u32 = 3;
pub const SET_INVERT_ON: u32 = 4;
pub const SET_INVERT_OFF: u32 = 5;
pub const SET_INVERT: u32 = 6;
pub const GET_RESOLUTION_MODES_COUNT: u32 = 11;
pub const GET_RESOLUTION_WIDTH_HEIGHT: u32 = 12;
pub const PIXEL_MODES_COUNT: u32 = 13;
pub const PIXEL_FORMAT: u32 = 14;
pub const GET_ROTATION: u32 = 21;
pub const SET_ROTATION: u32 = 22;
pub const GET_RESOLUTION: u32 = 23;
pub const SET_RESOLUTION: u32 = 24;
pub const GET_PIXEL_FORMAT: u32 = 25;
pub const SET_PIXEL_FORMAT: u32 = 26;
pub const SET_WRITE_FRAME: u32 = 100;
pub const WRITE: u32 = 200;
pub const FILL: u32 = 300;
}
// Subscribe ID used for callbacks
mod subscribe {
pub const WRITE: u32 = 0;
}
// Allow-readonly buffer ID
mod allow_ro {
pub const WRITE_BUFFER_ID: u32 = 0;
}
================================================
FILE: apis/display/screen/src/tests.rs
================================================
use libtock_platform::ErrorCode;
use libtock_unittest::{fake, ExpectedSyscall};
type Screen = super::Screen<fake::Syscalls>;
#[test]
// Test fails when no screen driver is registered.
fn no_driver() {
let _kernel = fake::Kernel::new();
assert_eq!(Screen::exists(), Err(ErrorCode::Fail))
}
#[test]
// Test passes when screen driver is present.
fn exists() {
let kernel = fake::Kernel::new();
let driver = fake::Screen::new();
kernel.add_driver(&driver);
assert_eq!(Screen::exists(), Ok(()));
}
#[test]
// Tests basic screen setup returns expected value (3).
fn screen_setup() {
let kernel = fake::Kernel::new();
let driver = fake::Screen::new();
kernel.add_driver(&driver);
assert_eq!(Screen::screen_setup(), Ok(3));
}
#[test]
// Tests setting screen power to ON.
fn set_power() {
let kernel = fake::Kernel::new();
let driver = fake::Screen::new();
kernel.add_driver(&driver);
assert_eq!(Screen::set_power(1), Ok(()));
}
#[test]
// Tests setting brightness.
fn set_brightness() {
let kernel = fake::Kernel::new();
let driver = fake::Screen::new();
kernel.add_driver(&driver);
kernel.add_expected_syscall(ExpectedSyscall::Subscribe {
driver_num: 0x90001,
subscribe_num: 0,
skip_with_error: None,
});
assert_eq!(Screen::set_brightness(90), Ok(()));
}
#[test]
// Turns inversion ON.
fn set_invert_on() {
let kernel = fake::Kernel::new();
let driver = fake::Screen::new();
kernel.add_driver(&driver);
kernel.add_expected_syscall(ExpectedSyscall::Subscribe {
driver_num: 0x90001,
subscribe_num: 0,
skip_with_error: None,
});
assert_eq!(Screen::set_invert_on(), Ok(()));
}
#[test]
// Turns inversion OFF.
fn set_invert_off() {
let kernel = fake::Kernel::new();
let driver = fake::Screen::new();
kernel.add_driver(&driver);
kernel.add_expected_syscall(ExpectedSyscall::Subscribe {
driver_num: 0x90001,
subscribe_num: 0,
skip_with_error: None,
});
assert_eq!(Screen::set_invert_off(), Ok(()));
}
#[test]
// Tests invert value.
fn set_invert() {
let kernel = fake::Kernel::new();
let driver = fake::Screen::new();
kernel.add_driver(&driver);
assert_eq!(Screen::set_invert(2), Ok(()));
}
#[test]
// Checks number of supported resolution modes.
fn get_resolution_modes_count() {
let kernel = fake::Kernel::new();
let driver = fake::Screen::new();
kernel.add_driver(&driver);
assert_eq!(Screen::get_resolution_modes_count(), Ok(2));
}
#[test]
// Tests fetching resolutions for indices 0-2.
fn get_resolution_width_height() {
let kernel = fake::Kernel::new();
let driver = fake::Screen::new();
kernel.add_driver(&driver);
assert_eq!(Screen::get_resolution_width_height(0), Ok((1920, 1080)));
assert_eq!(Screen::get_resolution_width_height(1), Ok((2560, 1440)));
assert_eq!(Screen::get_resolution_width_height(2), Ok((1280, 720)));
}
#[test]
// Invalid resolution index returns error.
fn get_resolution_width_height_fail() {
let kernel = fake::Kernel::new();
let driver = fake::Screen::new();
kernel.add_driver(&driver);
assert_eq!(
Screen::get_resolution_width_height(3),
Err(ErrorCode::Invalid)
);
}
#[test]
// Checks total available pixel modes.
fn pixel_modes_count() {
let kernel = fake::Kernel::new();
let driver = fake::Screen::new();
kernel.add_driver(&driver);
assert_eq!(Screen::pixel_modes_count(), Ok(5));
}
#[test]
// Gets pixel format for valid indices.
fn get_screen_pixel_format_success() {
let kernel = fake::Kernel::new();
let driver = fake::Screen::new();
kernel.add_driver(&driver);
assert_eq!(Screen::pixel_format(0), Ok(332));
assert_eq!(Screen::pixel_format(1), Ok(565));
}
#[test]
// Invalid index returns error.
fn get_screen_pixel_format_fail() {
let kernel = fake::Kernel::new();
let driver = fake::Screen::new();
kernel.add_driver(&driver);
assert_eq!(Screen::pixel_format(8), Err(ErrorCode::Invalid));
}
#[test]
// Sets screen rotation.
fn set_rotation_success() {
let kernel = fake::Kernel::new();
let driver = fake::Screen::new();
kernel.add_driver(&driver);
kernel.add_expected_syscall(ExpectedSyscall::Subscribe {
driver_num: 0x90001,
subscribe_num: 0,
skip_with_error: None,
});
assert_eq!(Screen::set_rotation(30), Ok(()));
}
#[test]
// Invalid rotation (>=360 degrees) fails.
fn set_rotation_fail() {
let kernel = fake::Kernel::new();
let driver = fake::Screen::new();
kernel.add_driver(&driver);
assert_eq!(Screen::set_rotation(360), Err(ErrorCode::Invalid));
}
#[test]
// Sets and then reads rotation.
fn get_rotation_success() {
let kernel = fake::Kernel::new();
let driver = fake::Screen::new();
kernel.add_driver(&driver);
kernel.add_expected_syscall(ExpectedSyscall::Subscribe {
driver_num: 0x90001,
subscribe_num: 0,
skip_with_error: None,
});
assert_eq!(Screen::set_rotation(30), Ok(()));
kernel.add_expected_syscall(ExpectedSyscall::Subscribe {
driver_num: 0x90001,
subscribe_num: 0,
skip_with_error: None,
});
assert_eq!(Screen::get_rotation(), Ok(30));
}
#[test]
// Gets default rotation (0) without prior set.
fn get_rotation_fail() {
let kernel = fake::Kernel::new();
let driver = fake::Screen::new();
kernel.add_driver(&driver);
kernel.add_expected_syscall(ExpectedSyscall::Subscribe {
driver_num: 0x90001,
subscribe_num: 0,
skip_with_error: None,
});
assert_eq!(Screen::get_rotation(), Ok(0));
}
#[test]
// Sets resolution to custom dimensions.
fn set_resolution() {
let kernel = fake::Kernel::new();
let driver = fake::Screen::new();
kernel.add_driver(&driver);
kernel.add_expected_syscall(ExpectedSyscall::Subscribe {
driver_num: 0x90001,
subscribe_num: 0,
skip_with_error: None,
});
assert_eq!(Screen::set_resolution(360, 720), Ok(()));
}
#[test]
// Verifies resolution was correctly set and retrieved.
fn get_resolution_sucess() {
let kernel = fake::Kernel::new();
let driver = fake::Screen::new();
kernel.add_driver(&driver);
kernel.add_expected_syscall(ExpectedSyscall::Subscribe {
driver_num: 0x90001,
subscribe_num: 0,
skip_with_error: None,
});
assert_eq!(Screen::set_resolution(360, 720), Ok(()));
assert_eq!(Screen::get_resolution(), Ok((360, 720)));
}
#[test]
// Returns (0,0) when no resolution was set.
fn get_resolution_fail() {
let kernel = fake::Kernel::new();
let driver = fake::Screen::new();
kernel.add_driver(&driver);
assert_eq!(Screen::get_resolution(), Ok((0, 0)));
}
#[test]
// Sets pixel format.
fn set_pixel_format() {
let kernel = fake::Kernel::new();
let driver = fake::Screen::new();
kernel.add_driver(&driver);
kernel.add_expected_syscall(ExpectedSyscall::Subscribe {
driver_num: 0x90001,
subscribe_num: 0,
skip_with_error: None,
});
assert_eq!(Screen::set_pixel_format(2), Ok(()));
}
#[test]
// Retrieves the pixel format that was previously set.
fn get_pixel_format_success() {
let kernel = fake::Kernel::new();
let driver = fake::Screen::new();
kernel.add_driver(&driver);
kernel.add_expected_syscall(ExpectedSyscall::Subscribe {
driver_num: 0x90001,
subscribe_num: 0,
skip_with_error: None,
});
assert_eq!(Screen::set_pixel_format(2), Ok(()));
assert_eq!(Screen::get_pixel_format(), Ok(2));
}
#[test]
// Returns 0 if format was never set.
fn get_pixel_format_fail() {
let kernel = fake::Kernel::new();
let driver = fake::Screen::new();
kernel.add_driver(&driver);
assert_eq!(Screen::get_pixel_format(), Ok(0));
}
#[test]
// Sets the region of screen to write pixels to.
fn set_write_frame() {
let kernel = fake::Kernel::new();
let driver = fake::Screen::new();
kernel.add_driver(&driver);
assert_eq!(Screen::set_write_frame(10, 20, 30, 30), Ok(()));
}
#[test]
// Writes pixel data to screen using a buffer.
fn write_buffer() {
let kernel = fake::Kernel::new();
let driver = fake::Screen::new();
kernel.add_driver(&driver);
let _ = Screen::set_pixel_format(2);
let buffer = [0u8; 4];
kernel.add_expected_syscall(ExpectedSyscall::AllowRo {
driver_num: 0x90001,
buffer_num: 0,
return_error: None,
});
kernel.add_expected_syscall(ExpectedSyscall::Subscribe {
driver_num: 0x90001,
subscribe_num: 0,
skip_with_error: None,
});
assert_eq!(Screen::write(&buffer), Ok(()));
}
#[test]
fn fill_success() {
// Fills buffer with a color and writes to screen.
let kernel = fake::Kernel::new();
let driver = fake::Screen::new();
kernel.add_driver(&driver);
let _ = Screen::set_pixel_format(2);
let mut buffer = [0u8; 2];
let color = 0xF800;
kernel.add_expected_syscall(ExpectedSyscall::AllowRo {
driver_num: 0x90001,
buffer_num: 0,
return_error: None,
});
kernel.add_expected_syscall(ExpectedSyscall::Subscribe {
driver_num: 0x90001,
subscribe_num: 0,
skip_with_error: None,
});
assert_eq!(Screen::fill(&mut buffer, color), Ok(()));
}
#[test]
fn fill_fail() {
// Buffer too small causes fill failure.
let kernel = fake::Kernel::new();
let driver = fake::Screen::new();
kernel.add_driver(&driver);
let _ = Screen::set_pixel_format(2);
let mut buffer = [0u8; 1];
let color = 0xF800;
kernel.add_expected_syscall(ExpectedSyscall::AllowRo {
driver_num: 0x90001,
buffer_num: 0,
return_error: None,
});
kernel.add_expected_syscall(ExpectedSyscall::Subscribe {
driver_num: 0x90001,
subscribe_num: 0,
skip_with_error: None,
});
assert_eq!(Screen::fill(&mut buffer, color), Err(ErrorCode::Fail));
}
================================================
FILE: apis/interface/buttons/Cargo.toml
================================================
[package]
name = "libtock_buttons"
version = "0.1.0"
authors = ["Tock Project Developers <tock-dev@googlegroups.com>"]
license = "Apache-2.0 OR MIT"
edition = "2018"
repository = "https://www.github.com/tock/libtock-rs"
rust-version.workspace = true
description = "libtock buttons driver"
[dependencies]
libtock_platform = { path = "../../../platform" }
[dev-dependencies]
libtock_unittest = { path = "../../../unittest" }
================================================
FILE: apis/interface/buttons/src/lib.rs
================================================
#![no_std]
use libtock_platform::{
share::Handle, subscribe::OneId, DefaultConfig, ErrorCode, Subscribe, Syscalls, Upcall,
};
/// The Buttons driver
///
/// # Example
/// ```ignore
/// use libtock::Buttons;
///
/// // Read button state
/// Buttons::is_pressed(0);
///
/// // Register for events
///
/// let listener = ButtonListener(|button, state| {
/// // make use of the button's state
/// });
///
/// share::scope(|subscribe| {
/// if let Ok(()) = Buttons::register_listener(&listener, subscribe) {
/// // yield
/// }
/// });
/// ```
pub struct Buttons<S: Syscalls>(S);
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum ButtonState {
Pressed,
Released,
}
impl From<u32> for ButtonState {
fn from(value: u32) -> ButtonState {
match value {
0 => ButtonState::Released,
_ => ButtonState::Pressed,
}
}
}
impl<S: Syscalls> Buttons<S> {
/// Run a check against the buttons capsule to ensure it is present.
///
/// Returns `Ok(number_of_buttons)` if the driver was present. This does not necessarily mean
/// that the driver is working.
pub fn count() -> Result<u32, ErrorCode> {
S::command(DRIVER_NUM, BUTTONS_COUNT, 0, 0).to_result()
}
/// Read the state of a button
pub fn read(button: u32) -> Result<ButtonState, ErrorCode> {
let button_state: u32 = S::command(DRIVER_NUM, BUTTONS_READ, button, 0).to_result()?;
Ok(button_state.into())
}
/// Returns `true` if a button is pressed
///
/// This function returns `false` if:
/// - the button is released
/// - the button number is invalid
/// - there is an error
pub fn is_pressed(button: u32) -> bool {
Self::read(button)
.map(|state| state == ButtonState::Pressed)
.unwrap_or(false)
}
/// Returns `true` if a button is released
///
/// This function returns `false` if:
/// - the button is pressed
/// - the button number is invalid
/// - there is an error
pub fn is_released(button: u32) -> bool {
Self::read(button)
.map(|state| state == ButtonState::Released)
.unwrap_or(false)
}
/// Enable events (interrupts) for a button
pub fn enable_interrupts(button: u32) -> Result<(), ErrorCode> {
S::command(DRIVER_NUM, BUTTONS_ENABLE_INTERRUPTS, button, 0).to_result()
}
/// Disable events (interrupts) for a button
pub fn disable_interrupts(button: u32) -> Result<(), ErrorCode> {
S::command(DRIVER_NUM, BUTTONS_DISABLE_INTERRUPTS, button, 0).to_result()
}
/// Register an events listener
///
/// There can be only one single listener registered at a time.
/// Each time this function is used, it will replace the
/// previously registered listener.
pub fn register_listener<'share, F: Fn(u32, ButtonState)>(
listener: &'share ButtonListener<F>,
subscribe: Handle<Subscribe<'share, S, DRIVER_NUM, 0>>,
) -> Result<(), ErrorCode> {
S::subscribe::<_, _, DefaultConfig, DRIVER_NUM, 0>(subscribe, listener)
}
/// Unregister the events listener
///
/// This function may be used even if there was no
/// previously registered listener.
pub fn unregister_listener() {
S::unsubscribe(DRIVER_NUM, 0)
}
}
/// A wrapper around a closure to be registered and called when
/// a button event occurs.
///
/// ```ignore
/// let listener = ButtonListener(|button, state| {
/// // make use of the button's state
/// });
/// ```
pub struct ButtonListener<F: Fn(u32, ButtonState)>(pub F);
impl<F: Fn(u32, ButtonState)> Upcall<OneId<DRIVER_NUM, 0>> for ButtonListener<F> {
fn upcall(&self, button_index: u32, state: u32, _arg2: u32) {
self.0(button_index, state.into())
}
}
#[cfg(test)]
mod tests;
// -----------------------------------------------------------------------------
// Driver number and command IDs
// -----------------------------------------------------------------------------
const DRIVER_NUM: u32 = 0x3;
// Command IDs
const BUTTONS_COUNT: u32 = 0;
const BUTTONS_ENABLE_INTERRUPTS: u32 = 1;
const BUTTONS_DISABLE_INTERRUPTS: u32 = 2;
const BUTTONS_READ: u32 = 3;
================================================
FILE: apis/interface/buttons/src/tests.rs
================================================
use core::cell::Cell;
use libtock_platform::{share, ErrorCode, Syscalls, YieldNoWaitReturn};
use libtock_unittest::fake;
use crate::{ButtonListener, ButtonState};
type Buttons = super::Buttons<fake::Syscalls>;
#[test]
fn no_driver() {
let _kernel = fake::Kernel::new();
assert_eq!(Buttons::count(), Err(ErrorCode::NoDevice));
}
#[test]
fn num_buttons() {
let kernel = fake::Kernel::new();
let driver = fake::Buttons::<10>::new();
kernel.add_driver(&driver);
assert_eq!(Buttons::count(), Ok(10));
}
#[test]
fn read() {
let kernel = fake::Kernel::new();
let driver = fake::Buttons::<10>::new();
kernel.add_driver(&driver);
assert_eq!(driver.set_pressed(0, true), Ok(()));
assert_eq!(Buttons::read(0), Ok(ButtonState::Pressed));
assert_eq!(driver.set_pressed(0, false), Ok(()));
assert_eq!(Buttons::read(0), Ok(ButtonState::Released));
assert_eq!(Buttons::read(11), Err(ErrorCode::Invalid));
}
#[test]
fn interrupts() {
let kernel = fake::Kernel::new();
let driver = fake::Buttons::<10>::new();
kernel.add_driver(&driver);
assert_eq!(Buttons::enable_interrupts(0), Ok(()));
assert!(driver.get_button_state(0).unwrap().interrupt_enabled);
assert_eq!(Buttons::disable_interrupts(0), Ok(()));
assert!(!driver.get_button_state(0).unwrap().interrupt_enabled);
assert_eq!(Buttons::enable_interrupts(11), Err(ErrorCode::Invalid));
assert_eq!(Buttons::disable_interrupts(11), Err(ErrorCode::Invalid));
}
#[test]
fn subscribe() {
let kernel = fake::Kernel::new();
let driver = fake::Buttons::<10>::new();
kernel.add_driver(&driver);
let pressed_interrupt_count: Cell<bool> = Cell::new(false);
let listener = ButtonListener(|button, state| {
assert_eq!(button, 0);
assert_eq!(state, ButtonState::Pressed);
pressed_interrupt_count.set(true);
});
assert_eq!(Buttons::enable_interrupts(0), Ok(()));
share::scope(|subscribe| {
assert_eq!(Buttons::register_listener(&listener, subscribe), Ok(()));
assert_eq!(driver.set_pressed(0, true), Ok(()));
assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);
});
assert!(pressed_interrupt_count.get());
let pressed_interrupt_count: Cell<u32> = Cell::new(0);
let expected_button_state: Cell<ButtonState> = Cell::new(ButtonState::Released);
let listener = ButtonListener(|button, state| {
assert_eq!(button, 1);
assert_eq!(state, expected_button_state.get());
pressed_interrupt_count.set(pressed_interrupt_count.get() + 1);
});
share::scope(|subscribe| {
assert_eq!(Buttons::enable_interrupts(1), Ok(()));
assert_eq!(Buttons::register_listener(&listener, subscribe), Ok(()));
expected_button_state.set(ButtonState::Pressed);
assert_eq!(driver.set_pressed(1, true), Ok(()));
assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);
assert_eq!(driver.set_pressed(1, true), Ok(()));
assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);
expected_button_state.set(ButtonState::Released);
assert_eq!(driver.set_pressed(1, false), Ok(()));
assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);
assert_eq!(driver.set_pressed(1, false), Ok(()));
assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);
assert_eq!(Buttons::disable_interrupts(1), Ok(()));
assert_eq!(driver.set_pressed(1, true), Ok(()));
assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);
assert_eq!(driver.set_pressed(1, false), Ok(()));
assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);
});
assert_eq!(pressed_interrupt_count.get(), 2);
let pressed_interrupt_count: Cell<bool> = Cell::new(false);
let listener = ButtonListener(|_, _| {
pressed_interrupt_count.set(true);
});
share::scope(|subscribe| {
assert_eq!(Buttons::enable_interrupts(0), Ok(()));
assert_eq!(Buttons::register_listener(&listener, subscribe), Ok(()));
Buttons::unregister_listener();
assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);
});
assert!(!pressed_interrupt_count.get());
}
================================================
FILE: apis/interface/buzzer/Cargo.toml
================================================
[package]
name = "libtock_buzzer"
version = "0.1.0"
authors = ["Tock Project Developers <tock-dev@googlegroups.com>"]
license = "Apache-2.0 OR MIT"
edition = "2021"
repository = "https://www.github.com/tock/libtock-rs"
rust-version.workspace = true
description = "libtock buzzer driver"
[dependencies]
libtock_platform = { path = "../../../platform" }
[dev-dependencies]
libtock_unittest = { path = "../../../unittest" }
================================================
FILE: apis/interface/buzzer/src/lib.rs
================================================
//! Implementation started by : https://github.com/teodorobert
//! Continued and modified by : https://github.com/SheepSeb
#![no_std]
use core::cell::Cell;
use core::time::Duration;
use libtock_platform::{
share, subscribe::OneId, DefaultConfig, ErrorCode, Subscribe, Syscalls, Upcall,
};
pub struct Buzzer<S: Syscalls>(S);
impl<S: Syscalls> Buzzer<S> {
/// Returns Ok() if the driver was present.This does not necessarily mean
/// that the driver is working.
pub fn exists() -> Result<(), ErrorCode> {
S::command(DRIVER_NUM, EXISTS, 0, 0).to_result()
}
/// Initiate a tone
pub fn tone(freq: u32, duration: Duration) -> Result<(), ErrorCode> {
S::command(DRIVER_NUM, BUZZER_ON, freq, duration.as_millis() as u32).to_result()
}
/// Register an events listener
pub fn register_listener<'share, F: Fn(u32)>(
listener: &'share BuzzerListener<F>,
subscribe: share::Handle<Subscribe<'share, S, DRIVER_NUM, 0>>,
) -> Result<(), ErrorCode> {
S::subscribe::<_, _, DefaultConfig, DRIVER_NUM, 0>(subscribe, listener)
}
/// Unregister the events listener
pub fn unregister_listener() {
S::unsubscribe(DRIVER_NUM, 0)
}
/// Initiate a synchronous tone
/// Returns Ok() if the operation was successful
pub fn tone_sync(freq: u32, duration: Duration) -> Result<(), ErrorCode> {
let buzzer_cell: Cell<Option<u32>> = Cell::new(None);
let listener = BuzzerListener(|buzzer_val| {
buzzer_cell.set(Some(buzzer_val));
});
share::scope(|subscribe| {
Self::register_listener(&listener, subscribe)?;
Self::tone(freq, duration)?;
while buzzer_cell.get().is_none() {
S::yield_wait();
}
match buzzer_cell.get() {
None => Err(ErrorCode::Fail),
Some(_) => Ok(()),
}
})
}
}
pub struct BuzzerListener<F: Fn(u32)>(pub F);
impl<F: Fn(u32)> Upcall<OneId<DRIVER_NUM, 0>> for BuzzerListener<F> {
fn upcall(&self, _arg0: u32, _arg1: u32, _arg2: u32) {
(self.0)(_arg0);
}
}
#[cfg(test)]
mod tests;
// -----------------------------------------------------------------------------
// Driver number and command IDs
// -----------------------------------------------------------------------------
const DRIVER_NUM: u32 = 0x90000;
// Command IDs
const EXISTS: u32 = 0;
const BUZZER_ON: u32 = 1;
/// The notes that can be played by the buzzer
#[allow(unused)]
#[repr(u32)]
#[derive(Copy, Clone, Debug)]
pub enum Note {
B0 = 31,
C1 = 33,
CS1 = 35,
D1 = 37,
DS1 = 39,
E1 = 41,
F1 = 44,
FS1 = 46,
G1 = 49,
GS1 = 52,
A1 = 55,
AS1 = 58,
B1 = 62,
C2 = 65,
CS2 = 69,
D2 = 73,
DS2 = 78,
E2 = 82,
F2 = 87,
FS2 = 93,
G2 = 98,
GS2 = 104,
A2 = 110,
AS2 = 117,
B2 = 123,
C3 = 131,
CS3 = 139,
D3 = 147,
DS3 = 156,
E3 = 165,
F3 = 175,
FS3 = 185,
G3 = 196,
GS3 = 208,
A3 = 220,
AS3 = 233,
B3 = 247,
C4 = 262,
CS4 = 277,
D4 = 294,
DS4 = 311,
E4 = 330,
F4 = 349,
FS4 = 370,
G4 = 392,
GS4 = 415,
A4 = 440,
AS4 = 466,
B4 = 494,
C5 = 523,
CS5 = 554,
D5 = 587,
DS5 = 622,
E5 = 659,
F5 = 698,
FS5 = 740,
G5 = 784,
GS5 = 831,
A5 = 880,
AS5 = 932,
B5 = 988,
C6 = 1047,
CS6 = 1109,
D6 = 1175,
DS6 = 1245,
E6 = 1319,
F6 = 1397,
FS6 = 1480,
G6 = 1568,
GS6 = 1661,
A6 = 1760,
AS6 = 1865,
B6 = 1976,
C7 = 2093,
CS7 = 2217,
D7 = 2349,
DS7 = 2489,
E7 = 2637,
F7 = 2794,
FS7 = 2960,
G7 = 3136,
GS7 = 3322,
A7 = 3520,
AS7 = 3729,
B7 = 3951,
C8 = 4186,
CS8 = 4435,
D8 = 4699,
DS8 = 4978,
}
================================================
FILE: apis/interface/buzzer/src/tests.rs
================================================
use core::time::Duration;
use libtock_platform::ErrorCode;
use libtock_unittest::fake;
type Buzzer = super::Buzzer<fake::Syscalls>;
#[test]
fn no_driver() {
let _kernel = fake::Kernel::new();
assert_eq!(Buzzer::exists(), Err(ErrorCode::NoDevice));
}
#[test]
fn exists() {
let kernel = fake::Kernel::new();
let driver = fake::Buzzer::new();
kernel.add_driver(&driver);
assert_eq!(Buzzer::exists(), Ok(()));
}
#[test]
fn tone() {
let kernel = fake::Kernel::new();
let driver = fake::Buzzer::new();
kernel.add_driver(&driver);
let duration = Duration::from_millis(100);
assert_eq!(Buzzer::tone(1000, duration), Ok(()));
assert!(driver.is_busy());
assert_eq!(Buzzer::tone(1000, duration), Err(ErrorCode::Busy));
}
#[test]
fn tone_sync() {
let kernel = fake::Kernel::new();
let driver = fake::Buzzer::new();
kernel.add_driver(&driver);
let duration = Duration::from_millis(100);
driver.set_tone_sync(1000, 100);
assert_eq!(Buzzer::tone_sync(1000, duration), Ok(()));
}
================================================
FILE: apis/interface/console/Cargo.toml
================================================
[package]
name = "libtock_console"
version = "0.1.0"
authors = [
"Tock Project Developers <tock-dev@googlegroups.com>",
"dcz <gihuac.dcz@porcupinefactory.org>",
]
license = "Apache-2.0 OR MIT"
edition = "2021"
repository = "https://www.github.com/tock/libtock-rs"
rust-version.workspace = true
description = "libtock console driver"
[dependencies]
libtock_platform = { path = "../../../platform" }
[dev-dependencies]
libtock_unittest = { path = "../../../unittest" }
================================================
FILE: apis/interface/console/src/lib.rs
================================================
#![no_std]
use core::cell::Cell;
use core::fmt;
use core::marker::PhantomData;
use libtock_platform as platform;
use libtock_platform::allow_ro::AllowRo;
use libtock_platform::allow_rw::AllowRw;
use libtock_platform::share;
use libtock_platform::subscribe::Subscribe;
use libtock_platform::{DefaultConfig, ErrorCode, Syscalls};
/// The console driver.
///
/// It allows libraries to pass strings to the kernel's console driver.
///
/// # Example
/// ```ignore
/// use libtock::Console;
///
/// // Writes "foo", followed by a newline, to the console
/// let mut writer = Console::writer();
/// writeln!(writer, foo).unwrap();
/// ```
pub struct Console<S: Syscalls, C: Config = DefaultConfig>(S, C);
impl<S: Syscalls, C: Config> Console<S, C> {
/// Run a check against the console capsule to ensure it is present.
///
/// Returns `true` if the driver was present. This does not necessarily mean
/// that the driver is working, as it may still fail to allocate grant
/// memory.
#[inline(always)]
pub fn exists() -> bool {
S::command(DRIVER_NUM, command::EXISTS, 0, 0).is_success()
}
/// Writes bytes.
/// This is an alternative to `fmt::Write::write`
/// because this can actually return an error code.
pub fn write(s: &[u8]) -> Result<(), ErrorCode> {
let called: Cell<Option<(u32,)>> = Cell::new(None);
share::scope::<
(
AllowRo<_, DRIVER_NUM, { allow_ro::WRITE }>,
Subscribe<_, DRIVER_NUM, { subscribe::WRITE }>,
),
_,
_,
>(|handle| {
let (allow_ro, subscribe) = handle.split();
S::allow_ro::<C, DRIVER_NUM, { allow_ro::WRITE }>(allow_ro, s)?;
S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::WRITE }>(subscribe, &called)?;
S::command(DRIVER_NUM, command::WRITE, s.len() as u32, 0)
.to_result::<(), ErrorCode>()?;
loop {
S::yield_wait();
if let Some((_,)) = called.get() {
return Ok(());
}
}
})
}
/// Reads bytes
/// Reads from the device and writes to `buf`, starting from index 0.
/// No special guarantees about when the read stops.
/// Returns count of bytes written to `buf`.
pub fn read(buf: &mut [u8]) -> (usize, Result<(), ErrorCode>) {
let called: Cell<Option<(u32, u32)>> = Cell::new(None);
let mut bytes_received = 0;
let r = share::scope::<
(
AllowRw<_, DRIVER_NUM, { allow_rw::READ }>,
Subscribe<_, DRIVER_NUM, { subscribe::READ }>,
),
_,
_,
>(|handle| {
let (allow_rw, subscribe) = handle.split();
let len = buf.len();
S::allow_rw::<C, DRIVER_NUM, { allow_rw::READ }>(allow_rw, buf)?;
S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::READ }>(subscribe, &called)?;
// When this fails, `called` is guaranteed unmodified,
// because upcalls are never processed until we call `yield`.
S::command(DRIVER_NUM, command::READ, len as u32, 0).to_result::<(), ErrorCode>()?;
loop {
S::yield_wait();
if let Some((status, bytes_pushed_count)) = called.get() {
bytes_received = bytes_pushed_count as usize;
return match status {
0 => Ok(()),
e_status => Err(e_status.try_into().unwrap_or(ErrorCode::Fail)),
};
}
}
});
(bytes_received, r)
}
pub fn writer() -> ConsoleWriter<S> {
ConsoleWriter {
syscalls: Default::default(),
}
}
}
pub struct ConsoleWriter<S: Syscalls> {
syscalls: PhantomData<S>,
}
impl<S: Syscalls> fmt::Write for ConsoleWriter<S> {
fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> {
Console::<S>::write(s.as_bytes()).map_err(|_e| fmt::Error)
}
}
/// System call configuration trait for `Console`.
pub trait Config:
platform::allow_ro::Config + platform::allow_rw::Config + platform::subscribe::Config
{
}
impl<T: platform::allow_ro::Config + platform::allow_rw::Config + platform::subscribe::Config>
Config for T
{
}
#[cfg(test)]
mod tests;
// -----------------------------------------------------------------------------
// Driver number and command IDs
// -----------------------------------------------------------------------------
const DRIVER_NUM: u32 = 0x1;
// Command IDs
#[allow(unused)]
mod command {
pub const EXISTS: u32 = 0;
pub const WRITE: u32 = 1;
pub const READ: u32 = 2;
pub const ABORT: u32 = 3;
}
#[allow(unused)]
mod subscribe {
pub const WRITE: u32 = 1;
pub const READ: u32 = 2;
}
mod allow_ro {
pub const WRITE: u32 = 1;
}
mod allow_rw {
pub const READ: u32 = 1;
}
================================================
FILE: apis/interface/console/src/tests.rs
================================================
use super::*;
use core::fmt::Write;
use libtock_platform::ErrorCode;
use libtock_unittest::{command_return, fake, ExpectedSyscall};
type Console = super::Console<fake::Syscalls>;
#[test]
fn no_driver() {
let _kernel = fake::Kernel::new();
assert!(!Console::exists());
}
#[test]
fn exists() {
let kernel = fake::Kernel::new();
let driver = fake::Console::new();
kernel.add_driver(&driver);
assert!(Console::exists());
assert_eq!(driver.take_bytes(), &[]);
}
#[test]
fn write_bytes() {
let kernel = fake::Kernel::new();
let driver = fake::Console::new();
kernel.add_driver(&driver);
Console::write(b"foo").unwrap();
Console::write(b"bar").unwrap();
assert_eq!(driver.take_bytes(), b"foobar",);
}
#[test]
fn write_str() {
let kernel = fake::Kernel::new();
let driver = fake::Console::new();
kernel.add_driver(&driver);
write!(Console::writer(), "foo").unwrap();
assert_eq!(driver.take_bytes(), b"foo");
}
#[test]
fn read_bytes_short() {
let kernel = fake::Kernel::new();
let driver = fake::Console::new_with_input(b"Hello");
kernel.add_driver(&driver);
let mut buf = [0; 10];
let (count, res) = Console::read(&mut buf);
res.unwrap();
assert_eq!(&buf[..count], b"Hello");
}
#[test]
fn read_bytes_alot() {
let kernel = fake::Kernel::new();
let driver = fake::Console::new_with_input(b"Hello Alot!");
kernel.add_driver(&driver);
let mut buf = [0; 5];
let (count, res) = Console::read(&mut buf);
res.unwrap();
assert_eq!(&buf[..count], b"Hello");
let (count, res) = Console::read(&mut buf);
res.unwrap();
assert_eq!(&buf[..count], b" Alot");
}
#[test]
fn failed_print() {
let kernel = fake::Kernel::new();
let driver = fake::Console::new();
kernel.add_driver(&driver);
kernel.add_expected_syscall(ExpectedSyscall::AllowRo {
driver_num: DRIVER_NUM,
buffer_num: allow_ro::WRITE,
return_error: None,
});
kernel.add_expected_syscall(ExpectedSyscall::Subscribe {
driver_num: DRIVER_NUM,
subscribe_num: subscribe::WRITE,
skip_with_error: None,
});
kernel.add_expected_syscall(ExpectedSyscall::Command {
driver_id: DRIVER_NUM,
command_id: command::WRITE,
argument0: 5,
argument1: 0,
override_return: Some(command_return::failure(ErrorCode::Fail)),
});
assert_eq!(Console::write(b"abcde"), Err(ErrorCode::Fail));
// The fake driver still receives the command even if a fake error is injected.
assert_eq!(driver.take_bytes(), b"abcde");
}
#[test]
fn failed_read() {
let kernel = fake::Kernel::new();
let driver = fake::Console::new_with_input(b"bugxxxx");
kernel.add_driver(&driver);
kernel.add_expected_syscall(ExpectedSyscall::AllowRw {
driver_num: DRIVER_NUM,
buffer_num: allow_rw::READ,
return_error: None,
});
kernel.add_expected_syscall(ExpectedSyscall::Subscribe {
driver_num: DRIVER_NUM,
subscribe_num: subscribe::READ,
skip_with_error: None,
});
kernel.add_expected_syscall(ExpectedSyscall::Command {
driver_id: DRIVER_NUM,
command_id: command::READ,
argument0: 3,
argument1: 0,
override_return: Some(command_return::failure(ErrorCode::Fail)),
});
let mut buf = [0; 3];
let (count, res) = Console::read(&mut buf);
assert_eq!(res, Err(ErrorCode::Fail));
assert_eq!(count, 0);
}
================================================
FILE: apis/interface/leds/Cargo.toml
================================================
[package]
name = "libtock_leds"
version = "0.1.0"
authors = ["Tock Project Developers <tock-dev@googlegroups.com>"]
license = "Apache-2.0 OR MIT"
edition = "2021"
repository = "https://www.github.com/tock/libtock-rs"
rust-version.workspace = true
description = "libtock leds driver"
[dependencies]
libtock_platform = { path = "../../../platform" }
[dev-dependencies]
libtock_unittest = { path = "../../../unittest" }
================================================
FILE: apis/interface/leds/src/lib.rs
================================================
#![no_std]
use libtock_platform::{ErrorCode, Syscalls};
/// The LEDs driver
///
/// # Example
/// ```ignore
/// use libtock::Leds;
///
/// // Turn on led 0
/// let _ = Leds::on(0);
/// ```
pub struct Leds<S: Syscalls>(S);
impl<S: Syscalls> Leds<S> {
/// Run a check against the leds capsule to ensure it is present.
///
/// Returns `Ok(number_of_leds)` if the driver was present. This does not necessarily mean
/// that the driver is working, as it may still fail to allocate grant
/// memory.
pub fn count() -> Result<u32, ErrorCode> {
S::command(DRIVER_NUM, LEDS_COUNT, 0, 0).to_result()
}
pub fn on(led: u32) -> Result<(), ErrorCode> {
S::command(DRIVER_NUM, LED_ON, led, 0).to_result()
}
pub fn off(led: u32) -> Result<(), ErrorCode> {
S::command(DRIVER_NUM, LED_OFF, led, 0).to_result()
}
pub fn toggle(led: u32) -> Result<(), ErrorCode> {
S::command(DRIVER_NUM, LED_TOGGLE, led, 0).to_result()
}
}
#[cfg(test)]
mod tests;
// -----------------------------------------------------------------------------
// Driver number and command IDs
// -----------------------------------------------------------------------------
const DRIVER_NUM: u32 = 0x2;
// Command IDs
const LEDS_COUNT: u32 = 0;
const LED_ON: u32 = 1;
const LED_OFF: u32 = 2;
const LED_TOGGLE: u32 = 3;
================================================
FILE: apis/interface/leds/src/tests.rs
================================================
use libtock_platform::ErrorCode;
use libtock_unittest::fake;
type Leds = super::Leds<fake::Syscalls>;
#[test]
fn no_driver() {
let _kernel = fake::Kernel::new();
assert_eq!(Leds::count(), Err(ErrorCode::NoDevice));
}
#[test]
fn exists() {
let kernel = fake::Kernel::new();
let driver = fake::Leds::<10>::new();
kernel.add_driver(&driver);
assert_eq!(Leds::count(), Ok(10));
for led in 0..10 {
assert_eq!(driver.get_led(led), Some(false));
}
}
#[test]
fn num_leds() {
let kernel = fake::Kernel::new();
let driver = fake::Leds::<10>::new();
kernel.add_driver(&driver);
assert_eq!(Leds::count().unwrap_or_default(), 10);
}
#[test]
fn on() {
let kernel = fake::Kernel::new();
let driver = fake::Leds::<10>::new();
kernel.add_driver(&driver);
assert_eq!(Leds::on(0), Ok(()));
assert_eq!(driver.get_led(0), Some(true));
}
#[test]
fn off() {
let kernel = fake::Kernel::new();
let driver = fake::Leds::<10>::new();
kernel.add_driver(&driver);
assert_eq!(Leds::off(0), Ok(()));
assert_eq!(driver.get_led(0), Some(false));
}
#[test]
fn toggle() {
let kernel = fake::Kernel::new();
let driver = fake::Leds::<10>::new();
kernel.add_driver(&driver);
assert_eq!(Leds::toggle(0), Ok(()));
assert_eq!(driver.get_led(0), Some(true));
assert_eq!(Leds::toggle(0), Ok(()));
assert_eq!(driver.get_led(0), Some(false));
}
#[test]
fn on_off() {
let kernel = fake::Kernel::new();
let driver = fake::Leds::<10>::new();
kernel.add_driver(&driver);
assert_eq!(Leds::on(0), Ok(()));
assert_eq!(driver.get_led(0), Some(true));
assert_eq!(Leds::off(0), Ok(()));
assert_eq!(driver.get_led(0), Some(false));
}
#[test]
fn no_led() {
let kernel = fake::Kernel::new();
let driver = fake::Leds::<10>::new();
kernel.add_driver(&driver);
assert_eq!(Leds::on(11), Err(ErrorCode::Invalid));
for led in 0..Leds::count().unwrap_or_default() {
assert_eq!(driver.get_led(led), Some(false));
}
}
================================================
FILE: apis/kernel/low_level_debug/Cargo.toml
================================================
[package]
name = "libtock_low_level_debug"
version = "0.1.0"
authors = ["Tock Project Developers <tock-dev@googlegroups.com>"]
license = "Apache-2.0 OR MIT"
edition = "2021"
repository = "https://www.github.com/tock/libtock-rs"
rust-version.workspace = true
description = "libtock low-level debug drivers"
[dependencies]
libtock_platform = { path = "../../../platform" }
[dev-dependencies]
libtock_unittest = { path = "../../../unittest" }
================================================
FILE: apis/kernel/low_level_debug/src/lib.rs
================================================
#![no_std]
use libtock_platform::Syscalls;
/// The low-level debug API provides tools to diagnose userspace issues that
/// make normal debugging workflows (e.g. printing to the console) difficult.
///
/// It allows libraries to print alert codes and apps to print numeric
/// information using only the command system call.
///
/// # Example
/// ```ignore
/// use libtock::LowLevelDebug;
///
/// // Prints 0x45 and the app which called it.
/// LowLevelDebug::print_1(0x45);
/// ```
pub struct LowLevelDebug<S: Syscalls>(S);
impl<S: Syscalls> LowLevelDebug<S> {
/// Run a check against the low-level debug capsule to ensure it is present.
///
/// Returns `true` if the driver was present. This does not necessarily mean
/// that the driver is working, as it may still fail to allocate grant
/// memory.
#[inline(always)]
pub fn exists() -> bool {
S::command(DRIVER_NUM, EXISTS, 0, 0).is_success()
}
/// Print one of the predefined alerts in [`AlertCode`].
#[inline(always)]
pub fn print_alert_code(code: AlertCode) {
let _ = S::command(DRIVER_NUM, PRINT_ALERT_CODE, code as u32, 0);
}
/// Print a single number. The number will be printed in hexadecimal.
///
/// In general, this should only be added temporarily for debugging and
/// should not be called by released library code.
#[inline(always)]
pub fn print_1(x: u32) {
let _ = S::command(DRIVER_NUM, PRINT_1, x, 0);
}
/// Print two numbers. The numbers will be printed in hexadecimal.
///
/// Like `print_1`, this is intended for temporary debugging and should not
/// be called by released library code. If you want to print multiple
/// values, it is often useful to use the first argument to indicate what
/// value is being printed.
#[inline(always)]
pub fn print_2(x: u32, y: u32) {
let _ = S::command(DRIVER_NUM, PRINT_2, x, y);
}
}
/// A predefined alert code, for use with [`LowLevelDebug::print_alert_code`].
pub enum AlertCode {
/// Application panic (e.g. `panic!()` called in Rust code).
Panic = 0x01,
/// A statically-linked app was not installed in the correct location in
/// flash.
WrongLocation = 0x02,
}
#[cfg(test)]
mod tests;
// -----------------------------------------------------------------------------
// Driver number and command IDs
// -----------------------------------------------------------------------------
const DRIVER_NUM: u32 = 0x8;
// Command IDs
const EXISTS: u32 = 0;
const PRINT_ALERT_CODE: u32 = 1;
const PRINT_1: u32 = 2;
const PRINT_2: u32 = 3;
================================================
FILE: apis/kernel/low_level_debug/src/tests.rs
================================================
use super::*;
use libtock_platform::ErrorCode;
use libtock_unittest::{command_return, fake, ExpectedSyscall};
type LowLevelDebug = super::LowLevelDebug<fake::Syscalls>;
#[test]
fn no_driver() {
let _kernel = fake::Kernel::new();
assert!(!LowLevelDebug::exists());
}
#[test]
fn exists() {
let kernel = fake::Kernel::new();
let driver = fake::LowLevelDebug::new();
kernel.add_driver(&driver);
assert!(LowLevelDebug::exists());
assert_eq!(driver.take_messages(), []);
}
#[test]
fn print_alert_code() {
let kernel = fake::Kernel::new();
let driver = fake::LowLevelDebug::new();
kernel.add_driver(&driver);
LowLevelDebug::print_alert_code(AlertCode::Panic);
LowLevelDebug::print_alert_code(AlertCode::WrongLocation);
assert_eq!(
driver.take_messages(),
[
fake::Message::AlertCode(0x01),
fake::Message::AlertCode(0x02)
]
);
}
#[test]
fn print_1() {
let kernel = fake::Kernel::new();
let driver = fake::LowLevelDebug::new();
kernel.add_driver(&driver);
LowLevelDebug::print_1(42);
assert_eq!(driver.take_messages(), [fake::Message::Print1(42)]);
}
#[test]
fn print_2() {
let kernel = fake::Kernel::new();
let driver = fake::LowLevelDebug::new();
kernel.add_driver(&driver);
LowLevelDebug::print_2(42, 27);
LowLevelDebug::print_2(29, 43);
assert_eq!(
driver.take_messages(),
[fake::Message::Print2(42, 27), fake::Message::Print2(29, 43)]
);
}
#[test]
fn failed_print() {
let kernel = fake::Kernel::new();
let driver = fake::LowLevelDebug::new();
kernel.add_driver(&driver);
kernel.add_expected_syscall(ExpectedSyscall::Command {
driver_id: DRIVER_NUM,
command_id: PRINT_1,
argument0: 72,
argument1: 0,
override_return: Some(command_return::failure(ErrorCode::Fail)),
});
// The error is explicitly silenced, and cannot be detected.
LowLevelDebug::print_1(72);
// The fake driver still receives the command even if a fake error is injected.
assert_eq!(driver.take_messages(), [fake::Message::Print1(72)]);
}
================================================
FILE: apis/net/ieee802154/Cargo.toml
================================================
[package]
name = "libtock_ieee802154"
version = "0.1.0"
authors = [
"Tock Project Developers <tock-dev@googlegroups.com>",
]
license = "Apache-2.0 OR MIT"
edition = "2021"
repository = "https://www.github.com/tock/libtock-rs"
rust-version.workspace = true
description = "libtock raw IEEE 802.15.4 stack driver"
[dependencies]
libtock_platform = { path = "../../../platform" }
[dev-dependencies]
libtock_unittest = { path = "../../../unittest" }
================================================
FILE: apis/net/ieee802154/src/lib.rs
================================================
//! The raw IEEE 802.15.4 stack driver.
#![no_std]
use core::cell::Cell;
use libtock_platform as platform;
use libtock_platform::allow_ro::AllowRo;
use libtock_platform::allow_rw::AllowRw;
use libtock_platform::share;
use libtock_platform::subscribe::Subscribe;
use libtock_platform::{DefaultConfig, ErrorCode, Syscalls};
/// The raw IEEE 802.15.4 stack driver.
///
/// It allows libraries to pass frames to and from kernel's 802.15.4 driver.
///
/// # Example
/// ```ignore
/// use libtock::ieee802154::{Ieee802154, RxOperator, RxRingBuffer, RxSingleBufferOperator};
///
/// // Configure the radio
/// let pan: u16 = 0xcafe;
/// let addr_short: u16 = 0xdead;
/// let addr_long: u64 = 0xdead_dad;
/// let tx_power: i8 = -0x42;
/// let channel: u8 = 0xff;
///
/// Ieee802154::set_pan(pan);
/// Ieee802154::set_address_short(addr_short);
/// Ieee802154::set_address_long(addr_long);
/// Ieee802154::set_tx_power(tx_power).unwrap();
/// Ieee802154::set_channel(channel).unwrap();
///
/// // Don't forget to commit the config!
/// Ieee802154::commit_config();
///
/// Ieee802154::radio_on()?;
///
/// // Transmit a frame
/// Ieee802154::transmit_frame(b"foobar").unwrap();
///
/// // Receive frames
/// let mut buf = RxRingBuffer::<2>::new();
/// let mut operator = RxSingleBufferOperator::new(&mut buf);
///
/// let frame = operator.receive_frame()?;
/// // Access frame data here:
/// let _body_len = frame.payload_len;
/// let _first_body_byte = frame.body[0];
///
/// ```
pub struct Ieee802154<S: Syscalls, C: Config = DefaultConfig>(S, C);
// Existence check
impl<S: Syscalls, C: Config> Ieee802154<S, C> {
/// Run a check against the console capsule to ensure it is present.
///
/// Returns `true` if the driver was present. This does not necessarily mean
/// that the driver is working, as it may still fail to allocate grant
/// memory.
#[inline(always)]
pub fn exists() -> bool {
S::command(DRIVER_NUM, command::EXISTS, 0, 0).is_success()
}
}
// Power management
impl<S: Syscalls, C: Config> Ieee802154<S, C> {
#[inline(always)]
pub fn is_on() -> bool {
S::command(DRIVER_NUM, command::STATUS, 0, 0).is_success()
}
#[inline(always)]
pub fn radio_on() -> Result<(), ErrorCode> {
S::command(DRIVER_NUM, command::TURN_ON, 0, 0).to_result()
}
#[inline(always)]
pub fn radio_off() -> Result<(), ErrorCode> {
S::command(DRIVER_NUM, command::TURN_OFF, 0, 0).to_result()
}
}
// Configuration
impl<S: Syscalls, C: Config> Ieee802154<S, C> {
#[inline(always)]
pub fn set_address_short(short_addr: u16) {
// Setting short address can't fail, so no need to check the return value.
let _ = S::command(
DRIVER_NUM,
command::SET_SHORT_ADDR,
// Driver expects 1 added to make the value positive.
short_addr as u32 + 1,
0,
);
}
#[inline(always)]
pub fn set_address_long(long_addr: u64) {
// Setting long address can't fail, so no need to check the return value.
let addr_lower: u32 = long_addr as u32;
let addr_upper: u32 = (long_addr >> 32) as u32;
let _ = S::command(DRIVER_NUM, command::SET_LONG_ADDR, addr_lower, addr_upper);
}
#[inline(always)]
pub fn set_pan(pan: u16) {
// Setting PAN can't fail, so no need to check the return value.
let _ = S::command(
DRIVER_NUM,
command::SET_PAN,
pan as u32 + 1, // Driver expects 1 added to make the value positive.
0,
);
}
#[inline(always)]
pub fn set_channel(chan: u8) -> Result<(), ErrorCode> {
S::command(DRIVER_NUM, command::SET_CHAN, chan as u32, 0).to_result()
}
#[inline(always)]
pub fn set_tx_power(power: i8) -> Result<(), ErrorCode> {
S::command(DRIVER_NUM, command::SET_TX_PWR, power as i32 as u32, 0).to_result()
}
#[inline(always)]
pub fn commit_config() {
// Committing config can't fail, so no need to check the return value.
let _ = S::command(DRIVER_NUM, command::COMMIT_CFG, 0, 0);
}
#[inline(always)]
pub fn get_address_short() -> Result<u16, ErrorCode> {
S::command(DRIVER_NUM, command::GET_SHORT_ADDR, 0, 0)
.to_result::<u32, _>()
// Driver adds 1 to make the value positive.
.map(|addr| addr as u16 - 1)
}
#[inline(always)]
pub fn get_address_long() -> Result<u64, ErrorCode> {
S::command(DRIVER_NUM, command::GET_LONG_ADDR, 0, 0).to_result()
}
#[inline(always)]
pub fn get_pan() -> Result<u16, ErrorCode> {
S::command(DRIVER_NUM, command::GET_PAN, 0, 0)
.to_result::<u32, _>()
// Driver adds 1 to make the value positive.
.map(|pan| pan as u16 - 1)
}
#[inline(always)]
pub fn get_channel() -> Result<u8, ErrorCode> {
S::command(DRIVER_NUM, command::GET_CHAN, 0, 0)
.to_result::<u32, _>()
.map(|chan| chan as u8)
}
#[inline(always)]
pub fn get_tx_power() -> Result<i8, ErrorCode> {
S::command(DRIVER_NUM, command::GET_TX_PWR, 0, 0)
.to_result::<u32, _>()
.map(|power| power as i32 as i8)
}
}
// Transmission
impl<S: Syscalls, C: Config> Ieee802154<S, C> {
/// Transmit a frame using the IEEE 802.15.4 Phy Driver.
pub fn transmit_frame_raw(frame: &[u8]) -> Result<(), ErrorCode> {
let called: Cell<Option<(u32,)>> = Cell::new(None);
share::scope::<
(
AllowRo<_, DRIVER_NUM, { allow_ro::WRITE }>,
Subscribe<_, DRIVER_NUM, { subscribe::FRAME_TRANSMITTED }>,
),
_,
_,
>(|handle| {
let (allow_ro, subscribe) = handle.split();
S::allow_ro::<C, DRIVER_NUM, { allow_ro::WRITE }>(allow_ro, frame)?;
S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::FRAME_TRANSMITTED }>(
subscribe, &called,
)?;
S::command(DRIVER_NUM, command::TRANSMIT_RAW, 0, 0).to_result::<(), ErrorCode>()?;
loop {
S::yield_wait();
if called.get().is_some() {
return Ok(());
}
}
})
}
}
mod rx;
pub use rx::{Frame, RxOperator, RxRingBuffer, RxSingleBufferOperator};
/// System call configuration trait for `Ieee802154`.
pub trait Config:
platform::allow_ro::Config + platform::allow_rw::Config + platform::subscribe::Config
{
}
impl<T: platform::allow_ro::Config + platform::allow_rw::Config + platform::subscribe::Config>
Config for T
{
}
#[cfg(test)]
mod tests;
// -----------------------------------------------------------------------------
// Driver number and command IDs
// -----------------------------------------------------------------------------
const DRIVER_NUM: u32 = 0x30001;
// Command IDs
/// - `0`: Driver existence check.
/// - `1`: Return radio status. Ok(())/OFF = on/off.
/// - `2`: Set short address.
/// - `4`: Set PAN ID.
/// - `5`: Set channel.
/// - `6`: Set transmission power.
/// - `7`: Commit any configuration changes.
/// - `8`: Get the short MAC address.
/// - `10`: Get the PAN ID.
/// - `11`: Get the channel.
/// - `12`: Get the transmission power.
/// - `27`: Transmit a frame. The frame must be stored in the write RO allow
/// buffer 0. The allowed buffer must be the length of the frame. The
/// frame includes the PDSU (i.e., the MAC payload) _without_ the MFR
/// (i.e., CRC) bytes.
/// - `28`: Set long address.
/// - `29`: Get the long MAC address.
/// - `30`: Turn the radio on.
/// - `31`: Turn the radio off.
mod command {
pub const EXISTS: u32 = 0;
pub const STATUS: u32 = 1;
pub const SET_SHORT_ADDR: u32 = 2;
pub const SET_PAN: u32 = 4;
pub const SET_CHAN: u32 = 5;
pub const SET_TX_PWR: u32 = 6;
pub const COMMIT_CFG: u32 = 7;
pub const GET_SHORT_ADDR: u32 = 8;
pub const GET_PAN: u32 = 10;
pub const GET_CHAN: u32 = 11;
pub const GET_TX_PWR: u32 = 12;
pub const TRANSMIT_RAW: u32 = 27;
pub const SET_LONG_ADDR: u32 = 28;
pub const GET_LONG_ADDR: u32 = 29;
pub const TURN_ON: u32 = 30;
pub const TURN_OFF: u32 = 31;
}
mod subscribe {
/// Frame is received
pub const FRAME_RECEIVED: u32 = 0;
/// Frame is transmitted
pub const FRAME_TRANSMITTED: u32 = 1;
}
/// Ids for read-only allow buffers
mod allow_ro {
/// Write buffer. Contains the frame payload to be transmitted.
pub const WRITE: u32 = 0;
}
/// Ids for read-write allow buffers
mod allow_rw {
/// Read buffer. Will contain the received frame.
pub const READ: u32 = 0;
}
================================================
FILE: apis/net/ieee802154/src/rx.rs
================================================
use core::marker::PhantomData;
use super::*;
/// Maximum length of a MAC frame.
const MAX_MTU: usize = 127;
#[derive(Debug)]
#[repr(C)]
pub struct Frame {
pub header_len: u8,
pub payload_len: u8,
pub mic_len: u8,
pub body: [u8; MAX_MTU],
}
const EMPTY_FRAME: Frame = Frame {
header_len: 0,
payload_len: 0,
mic_len: 0,
body: [0; MAX_MTU],
};
/// The ring buffer that is shared with kernel using allow-rw syscall, with kernel acting
/// as a producer of frames and we acting a consumer.
///
/// The `N` parameter specifies the capacity of the buffer in number of frames.
/// Unfortunately, due to a design flaw of the ring buffer, it can never be fully utilised,
/// as it's impossible to distinguish an empty buffer from a full one. The kernel code
/// actually uses up to `N - 1` slots, and then starts overwriting old frames with
/// new ones. Remember to specify `N` as `F + 1`, where `F` is the maximum expected number
/// of frames received in short succession.
///
/// Given the non-deterministic nature of upcalls, the userprocess must carefully
/// handle receiving upcalls. There exists a risk of dropping 15.4 packets while
/// reading from the ring buffer (as the ring buffer is unallowed while reading).
/// This could be handled by utilizing two ring buffers and alternating which
/// belongs to the kernel and which is being read from. However, efforts to implement that
/// failed on Miri level - we couldn't find a sound way to achieve that.
/// Alternatively, the user can also utilize a single ring buffer if dropped frames may be permissible.
/// This is done by [RxSingleBufferOperator].
#[derive(Debug)]
#[repr(C)]
pub struct RxRingBuffer<const N: usize> {
/// From where the next frame will be read by process.
/// Updated by process only.
read_index: u8,
/// Where the next frame will be written by kernel.
/// Updated by kernel only.
write_index: u8,
/// Slots for received frames.
frames: [Frame; N],
}
impl<const N: usize> Default for RxRingBuffer<N> {
fn default() -> Self {
Self::new()
}
}
impl<const N: usize> RxRingBuffer<N> {
/// Creates a new [RxRingBuffer] that can be used to receive frames into.
pub const fn new() -> Self {
Self {
read_index: 0,
write_index: 0,
frames: [EMPTY_FRAME; N],
}
}
fn as_mut_byte_slice(&mut self) -> &mut [u8] {
// SAFETY: any byte value is valid for any byte of Self,
// as well as for any byte of [u8], so casts back and forth
// cannot break the type system.
unsafe {
core::slice::from_raw_parts_mut(
self as *mut Self as *mut u8,
core::mem::size_of::<Self>(),
)
}
}
fn has_frame(&self) -> bool {
self.read_index != self.write_index
}
fn next_frame(&mut self) -> &mut Frame {
let frame = self.frames.get_mut(self.read_index as usize).unwrap();
self.read_index = (self.read_index + 1) % N as u8;
frame
}
}
pub trait RxOperator {
/// Receive one new frame.
///
/// Logically pop one frame out of the ring buffer and provide mutable access to it.
/// If no frame is ready for reception, yield_wait to kernel until one is available.
fn receive_frame(&mut self) -> Result<&mut Frame, ErrorCode>;
}
/// Safe encapsulation that can receive frames from the kernel using a single ring buffer.
/// See [RxRingBuffer] for more information.
///
/// This operator can lose some frames: if a frame is received in the kernel when
/// the app is examining its received frames (and hence has its buffer unallowed),
/// then the frame can be lost. Unfortunately, no alternative at the moment due to
/// soundness issues in tried implementation.
pub struct RxSingleBufferOperator<'buf, const N: usize, S: Syscalls, C: Config = DefaultConfig> {
buf: &'buf mut RxRingBuffer<N>,
s: PhantomData<S>,
c: PhantomData<C>,
}
impl<'buf, const N: usize, S: Syscalls, C: Config> RxSingleBufferOperator<'buf, N, S, C> {
/// Creates a new [RxSingleBufferOperator] that can be used to receive frames.
pub fn new(buf: &'buf mut RxRingBuffer<N>) -> Self {
Self {
buf,
s: PhantomData,
c: PhantomData,
}
}
}
impl<const N: usize, S: Syscalls, C: Config> RxOperator for RxSingleBufferOperator<'_, N, S, C> {
fn receive_frame(&mut self) -> Result<&mut Frame, ErrorCode> {
if self.buf.has_frame() {
Ok(self.buf.next_frame())
} else {
// If no frame is there, wait until one comes, then return it.
Ieee802154::<S, C>::receive_frame_single_buf(self.buf)?;
// Safety: kernel schedules an upcall iff a new frame becomes available,
// i.e. when it increments `read_index`.
Ok(self.buf.next_frame())
}
}
}
// Reception
impl<S: Syscalls, C: Config> Ieee802154<S, C> {
fn receive_frame_single_buf<const N: usize>(
buf: &mut RxRingBuffer<N>,
) -> Result<(), ErrorCode> {
let called: Cell<Option<(u32,)>> = Cell::new(None);
share::scope::<
(
AllowRw<_, DRIVER_NUM, { allow_rw::READ }>,
Subscribe<_, DRIVER_NUM, { subscribe::FRAME_RECEIVED }>,
),
_,
_,
>(|handle| {
let (allow_rw, subscribe) = handle.split();
S::allow_rw::<C, DRIVER_NUM, { allow_rw::READ }>(allow_rw, buf.as_mut_byte_slice())?;
S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::FRAME_RECEIVED }>(subscribe, &called)?;
loop {
S::yield_wait();
if let Some((_lqi,)) = called.get() {
// At least one frame was received.
return Ok(());
}
}
})
}
}
================================================
FILE: apis/net/ieee802154/src/tests.rs
================================================
use libtock_platform::{RawSyscalls, Register};
use libtock_unittest::fake::{self, ieee802154::Frame as FakeFrame, Ieee802154Phy};
/// The Ieee8021514Phy userspace driver calls yield_wait() immediately after subscribe().
/// Normally, it would wait for the kernel to receive a frame and then asynchronously
/// schedule an upcall, but in this testing framework it is required to schedule
/// an upcall before yield_wait(), because otherwise a panic is raised.
///
/// HACK: This wraps around fake::Syscalls to hook subscribe::FRAME_RECEIVED
/// so that immediately after subscribing for the upcall, frames are received
/// by the kernel driver and the corresponding upcall is scheduled.
struct FakeSyscalls;
unsafe impl RawSyscalls for FakeSyscalls {
unsafe fn yield1([r0]: [Register; 1]) {
libtock_unittest::fake::Syscalls::yield1([r0])
}
unsafe fn yield2([r0, r1]: [Register; 2]) {
libtock_unittest::fake::Syscalls::yield2([r0, r1])
}
unsafe fn syscall1<const CLASS: usize>([r0]: [Register; 1]) -> [Register; 2] {
libtock_unittest::fake::Syscalls::syscall1::<CLASS>([r0])
}
unsafe fn syscall2<const CLASS: usize>([r0, r1]: [Register; 2]) -> [Register; 2] {
libtock_unittest::fake::Syscalls::syscall2::<CLASS>([r0, r1])
}
unsafe fn syscall4<const CLASS: usize>([r0, r1, r2, r3]: [Register; 4]) -> [Register; 4] {
let trigger_rx_upcall = match CLASS {
libtock_platform::syscall_class::SUBSCRIBE => {
let driver_num: u32 = r0.try_into().unwrap();
let subscribe_num: u32 = r1.try_into().unwrap();
let len: usize = r3.into();
assert_eq!(driver_num, DRIVER_NUM);
subscribe_num == subscribe::FRAME_RECEIVED && len > 0
}
_ => false,
};
let ret = libtock_unittest::fake::Syscalls::syscall4::<CLASS>([r0, r1, r2, r3]);
if trigger_rx_upcall {
if let Some(driver) = Ieee802154Phy::instance() {
driver.driver_receive_pending_frames();
if driver.has_pending_rx_frames() {
driver.trigger_rx_upcall();
}
}
}
ret
}
}
use crate::{subscribe, DRIVER_NUM};
use super::{RxOperator, RxRingBuffer};
type Ieee802154 = super::Ieee802154<FakeSyscalls>;
type RxSingleBufferOperator<'buf, const N: usize> =
super::RxSingleBufferOperator<'buf, N, FakeSyscalls>;
#[test]
fn no_driver() {
let _kernel = fake::Kernel::new();
assert!(!Ieee802154::exists());
}
#[test]
fn exists() {
let kernel = fake::Kernel::new();
let driver = fake::Ieee802154Phy::new();
kernel.add_driver(&driver);
assert!(Ieee802154::exists());
}
#[test]
fn configure() {
let kernel = fake::Kernel::new();
let driver = fake::Ieee802154Phy::new();
kernel.add_driver(&driver);
let pan: u16 = 0xcafe;
let addr_short: u16 = 0xdead;
let addr_long: u64 = 0xdeaddad;
let tx_power: i8 = -0x42;
let channel: u8 = 0xff;
Ieee802154::set_pan(pan);
Ieee802154::set_address_short(addr_short);
Ieee802154::set_address_long(addr_long);
Ieee802154::set_tx_power(tx_power).unwrap();
Ieee802154::set_channel(channel).unwrap();
Ieee802154::commit_config();
assert_eq!(Ieee802154::get_pan().unwrap(), pan);
assert_eq!(Ieee802154::get_address_short().unwrap(), addr_short);
assert_eq!(Ieee802154::get_address_long().unwrap(), addr_long);
assert_eq!(Ieee802154::get_channel().unwrap(), channel);
assert_eq!(Ieee802154::get_tx_power().unwrap(), tx_power);
}
#[test]
fn transmit_frame() {
let kernel = fake::Kernel::new();
let driver = fake::Ieee802154Phy::new();
kernel.add_driver(&driver);
Ieee802154::transmit_frame_raw(b"foo").unwrap();
Ieee802154::transmit_frame_raw(b"bar").unwrap();
assert_eq!(
driver.take_transmitted_frames(),
&[&b"foo"[..], &b"bar"[..]],
);
}
mod rx {
use super::*;
fn test_with_driver(test: impl FnOnce(&Ieee802154Phy)) {
let kernel = fake::Kernel::new();
let driver = fake::Ieee802154Phy::new();
kernel.add_driver(&driver);
test(&driver)
}
fn test_with_single_buf_operator<const SUPPORTED_FRAMES: usize>(
driver: &Ieee802154Phy,
test: impl Fn(&Ieee802154Phy, &mut dyn RxOperator),
) {
let mut buf = RxRingBuffer::<SUPPORTED_FRAMES>::new();
let mut operator = RxSingleBufferOperator::new(&mut buf);
test(driver, &mut operator)
}
fn no_frame_comes(_driver: &Ieee802154Phy, operator: &mut dyn RxOperator) {
// No frame is available, so we expect to panic in tests,
// because yield_wait is called without pending upcalls.
// THIS PANICS
let _ = operator.receive_frame();
}
#[test]
#[should_panic = "yield-wait called with no queued upcall"]
fn no_frame_comes_single_buf() {
test_with_driver(|driver| {
const SUPPORTED_FRAMES: usize = 2;
test_with_single_buf_operator::<SUPPORTED_FRAMES>(driver, no_frame_comes);
});
}
#[test]
fn receive_frame() {
test_with_driver(|driver| {
const SUPPORTED_FRAMES: usize = 2;
test_with_single_buf_operator::<SUPPORTED_FRAMES>(driver, |driver, operator| {
let frame1 = b"alamakota";
driver.radio_receive_frame(FakeFrame::with_body(frame1));
// Now one frame is available.
let got_frame1 = operator.receive_frame().unwrap();
assert_eq!(got_frame1.payload_len as usize, frame1.len());
assert_eq!(
&got_frame1.body[..got_frame1.payload_len as usize],
&frame1[..]
);
});
});
}
fn only_one_frame_comes(driver: &Ieee802154Phy, operator: &mut dyn RxOperator) {
let frame1 = b"alamakota";
// Now one frame is available.
driver.radio_receive_frame(FakeFrame::with_body(frame1));
let got_frame1 = operator.receive_frame().unwrap();
assert_eq!(got_frame1.payload_len as usize, frame1.len());
assert_eq!(&got_frame1.body[..frame1.len()], frame1);
// But only one!
// THIS PANICS
let _ = operator.receive_frame();
}
#[test]
#[should_panic = "yield-wait called with no queued upcall"]
fn receive_frame_only_one_single_buf() {
test_with_driver(|driver| {
const SUPPORTED_FRAMES: usize = 2;
test_with_single_buf_operator::<SUPPORTED_FRAMES>(driver, only_one_frame_comes);
});
}
#[test]
fn receive_many_frames() {
test_with_driver(|driver| {
const SUPPORTED_FRAMES: usize = 3;
test_with_single_buf_operator::<{ SUPPORTED_FRAMES + 1 }>(
driver,
|driver, operator| {
for (times, frame) in
[1, 2, 3, 10]
.iter()
.copied()
.zip([&b"one"[..], b"two", b"three", b"ten"])
{
for _ in 0..times {
driver.radio_receive_frame(FakeFrame::with_body(frame));
}
for _ in 0..core::cmp::min(times, SUPPORTED_FRAMES) {
let got_frame = operator.receive_frame().unwrap();
let expected_frame = frame;
assert_eq!(got_frame.payload_len as usize, expected_frame.len());
assert_eq!(
&got_frame.body[..got_frame.payload_len as usize],
expected_frame
);
}
}
},
);
});
}
#[test]
fn receive_various_frames() {
test_with_driver(|driver| {
const SUPPORTED_FRAMES: usize = 3;
test_with_single_buf_operator::<{ SUPPORTED_FRAMES + 1 }>(
driver,
|driver, operator| {
let frame1 = b"alamakota";
let frame2 = b"ewamamewe";
let frame3 = b"wojciechmalaptop";
let frames: [&[u8]; 3] = [frame1, frame2, frame3];
let order = [0, 1, 2, 2, 1, 0, 2, 2, 1, 0, 2];
for idx in order {
let times = idx + 1;
for _ in 0..times {
driver.radio_receive_frame(FakeFrame::with_body(frames[idx]));
}
for _ in 0..core::cmp::min(times, SUPPORTED_FRAMES) {
let got_frame = operator.receive_frame().unwrap();
let expected_frame = frames[idx];
assert_eq!(got_frame.payload_len as usize, expected_frame.len());
assert_eq!(
&got_frame.body[..got_frame.payload_len as usize],
expected_frame
);
}
}
},
);
});
}
}
================================================
FILE: apis/peripherals/adc/Cargo.toml
================================================
[package]
name = "libtock_adc"
version = "0.1.0"
authors = ["Tock Project Developers <tock-dev@googlegroups.com>"]
license = "Apache-2.0 OR MIT"
edition = "2021"
repository = "https://www.github.com/tock/libtock-rs"
rust-version.workspace = true
description = "libtock adc driver"
[dependencies]
libtock_platform = { path = "../../../platform" }
[dev-dependencies]
libtock_unittest = { path = "../../../unittest" }
================================================
FILE: apis/peripherals/adc/src/lib.rs
================================================
#![no_std]
use core::cell::Cell;
use libtock_platform::{
share, subscribe::OneId, DefaultConfig, ErrorCode, Subscribe, Syscalls, Upcall,
};
pub struct Adc<S: Syscalls>(S);
impl<S: Syscalls> Adc<S> {
/// Returns Ok() if the driver was present.This does not necessarily mean
/// that the driver is working.
pub fn exists() -> Result<(), ErrorCode> {
// TODO(Tock 3.0): The "exists" command should return directly return
// `Result<(), ErrorCode>` (i.e. with no `.and()` call), but the
// current ADC driver in the kernel returns the number of ADC channels
// instead of just success. This will be fixed in a future release of
// Tock, but for now we workaround this issue.
//
// https://github.com/tock/tock/issues/3375
S::command(DRIVER_NUM, EXISTS, 0, 0)
.to_result::<u32, ErrorCode>()
.and(Ok(()))
}
// Initiate a sample reading
pub fn read_single_sample() -> Result<(), ErrorCode> {
S::command(DRIVER_NUM, SINGLE_SAMPLE, 0, 0).to_result()
}
// Register a listener to be called when the ADC conversion is finished
pub fn register_listener<'share, F: Fn(u16)>(
listener: &'share ADCListener<F>,
subscribe: share::Handle<Subscribe<'share, S, DRIVER_NUM, 0>>,
) -> Result<(), ErrorCode> {
S::subscribe::<_, _, DefaultConfig, DRIVER_NUM, 0>(subscribe, listener)
}
/// Unregister the events listener
pub fn unregister_listener() {
S::unsubscribe(DRIVER_NUM, 0)
}
/// Initiates a synchronous ADC conversion
/// Returns the converted ADC value or an error
pub fn read_single_sample_sync() -> Result<u16, ErrorCode> {
let sample: Cell<Option<u16>> = Cell::new(None);
let listener = ADCListener(|adc_val| {
sample.set(Some(adc_val));
});
share::scope(|subscribe| {
Self::register_listener(&listener, subscribe)?;
Self::read_single_sample()?;
while sample.get().is_none() {
S::yield_wait();
}
match sample.get() {
None => Err(ErrorCode::Busy),
Some(adc_val) => Ok(adc_val),
}
})
}
/// Returns the number of ADC resolution bits
pub fn get_resolution_bits() -> Result<u32, ErrorCode> {
S::command(DRIVER_NUM, GET_RES_BITS, 0, 0).to_result()
}
/// Returns the reference voltage in millivolts (mV)
pub fn get_reference_voltage_mv() -> Result<u32, ErrorCode> {
S::command(DRIVER_NUM, GET_VOLTAGE_REF, 0, 0).to_result()
}
}
pub struct ADCListener<F: Fn(u16)>(pub F);
impl<F: Fn(u16)> Upcall<OneId<DRIVER_NUM, 0>> for ADCListener<F> {
fn upcall(&self, adc_val: u32, _arg1: u32, _arg2: u32) {
self.0(adc_val as u16)
}
}
#[cfg(test)]
mod tests;
// -----------------------------------------------------------------------------
// Driver number and command IDs
// -----------------------------------------------------------------------------
const DRIVER_NUM: u32 = 0x5;
// Command IDs
const EXISTS: u32 = 0;
const SINGLE_SAMPLE: u32 = 1;
// const REPEAT_SINGLE_SAMPLE: u32 = 2;
// const MULTIPLE_SAMPLE: u32 = 3;
// const CONTINUOUS_BUFF_SAMPLE: u32 = 4;
// const STOP_SAMPLE: u32 = 5;
const GET_RES_BITS: u32 = 101;
const GET_VOLTAGE_REF: u32 = 102;
================================================
FILE: apis/peripherals/adc/src/tests.rs
================================================
use core::cell::Cell;
use libtock_platform::{share, ErrorCode, Syscalls, YieldNoWaitReturn};
use libtock_unittest::fake;
type Adc = super::Adc<fake::Syscalls>;
#[test]
fn no_driver() {
let _kernel = fake::Kernel::new();
assert_eq!(Adc::exists(), Err(ErrorCode::NoDevice));
}
#[test]
fn exists() {
let kernel = fake::Kernel::new();
let driver = fake::Adc::new();
kernel.add_driver(&driver);
assert_eq!(Adc::exists(), Ok(()));
}
#[test]
fn read_single_sample() {
let kernel = fake::Kernel::new();
let driver = fake::Adc::new();
kernel.add_driver(&driver);
assert_eq!(Adc::read_single_sample(), Ok(()));
assert!(driver.is_busy());
assert_eq!(Adc::read_single_sample(), Err(ErrorCode::Busy));
assert_eq!(Adc::read_single_sample_sync(), Err(ErrorCode::Busy));
}
#[test]
fn register_unregister_listener() {
let kernel = fake::Kernel::new();
let driver = fake::Adc::new();
kernel.add_driver(&driver);
let sample: Cell<Option<u16>> = Cell::new(None);
let listener = crate::ADCListener(|adc_val| {
sample.set(Some(adc_val));
});
share::scope(|subscribe| {
assert_eq!(Adc::read_single_sample(), Ok(()));
driver.set_value(100);
assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);
assert_eq!(Adc::register_listener(&listener, subscribe), Ok(()));
assert_eq!(Adc::read_single_sample(), Ok(()));
driver.set_value(100);
assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);
assert_eq!(sample.get(), Some(100));
Adc::unregister_listener();
assert_eq!(Adc::read_single_sample(), Ok(()));
driver.set_value(100);
assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);
});
}
#[test]
fn read_single_sample_sync() {
let kernel = fake::Kernel::new();
let driver = fake::Adc::new();
kernel.add_driver(&driver);
driver.set_value_sync(1000);
assert_eq!(Adc::read_single_sample_sync(), Ok(1000));
}
================================================
FILE: apis/peripherals/alarm/Cargo.toml
================================================
[package]
name = "libtock_alarm"
version = "0.1.0"
authors = [
"Tock Project Developers <tock-dev@googlegroups.com>",
"dcz <gihuac.dcz@porcupinefactory.org>",
]
license = "Apache-2.0 OR MIT"
edition = "2018"
repository = "https://www.github.com/tock/libtock-rs"
rust-version.workspace = true
description = "libtock alarm driver"
[dependencies]
libtock_platform = { path = "../../../platform" }
[dev-dependencies]
libtock_unittest = { path = "../../../unittest" }
================================================
FILE: apis/peripherals/alarm/src/lib.rs
================================================
#![no_std]
use core::cell::Cell;
use libtock_platform as platform;
use libtock_platform::share;
use libtock_platform::{DefaultConfig, ErrorCode, Syscalls};
/// The alarm driver
///
/// # Example
/// ```ignore
/// use libtock2::Alarm;
///
/// // Wait for timeout
/// Alarm::sleep(Alarm::Milliseconds(2500));
/// ```
pub struct Alarm<S: Syscalls, C: platform::subscribe::Config = DefaultConfig>(S, C);
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct Hz(pub u32);
pub trait Convert {
/// Converts a time unit by rounding up.
fn to_ticks(self, freq: Hz) -> Ticks;
}
#[derive(Copy, Clone, Debug)]
pub struct Ticks(pub u32);
impl Convert for Ticks {
fn to_ticks(self, _freq: Hz) -> Ticks {
self
}
}
#[derive(Copy, Clone)]
pub struct Milliseconds(pub u32);
impl Convert for Milliseconds {
fn to_ticks(self, freq: Hz) -> Ticks {
// Saturating multiplication will top out at about 1 hour at 1MHz.
// It's large enough for an alarm, and much simpler than failing
// or losing precision for short sleeps.
/// u32::div_ceil is still unstable.
fn div_ceil(a: u32, other: u32) -> u32 {
let d = a / other;
let m = a % other;
if m == 0 {
d
} else {
d + 1
}
}
Ticks(div_ceil(self.0.saturating_mul(freq.0), 1000))
}
}
impl<S: Syscalls, C: platform::subscribe::Config> Alarm<S, C> {
/// Run a check against the console capsule to ensure it is present.
#[inline(always)]
pub fn exists() -> Result<(), ErrorCode> {
S::command(DRIVER_NUM, command::EXISTS, 0, 0).to_result()
}
pub fn get_frequency() -> Result<Hz, ErrorCode> {
S::command(DRIVER_NUM, command::FREQUENCY, 0, 0)
.to_result()
.map(Hz)
}
pub fn get_ticks() -> Result<u32, ErrorCode> {
S::command(DRIVER_NUM, command::TIME, 0, 0).to_result()
}
pub fn get_milliseconds() -> Result<u64, ErrorCode> {
let ticks = Self::get_ticks()? as u64;
let freq = (Self::get_frequency()?).0 as u64;
Ok(ticks.saturating_div(freq / 1000))
}
pub fn sleep_for<T: Convert>(time: T) -> Result<(), ErrorCode> {
let freq = Self::get_frequency()?;
let ticks = time.to_ticks(freq);
let called: Cell<Option<(u32, u32)>> = Cell::new(None);
share::scope(|subscribe| {
S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::CALLBACK }>(subscribe, &called)?;
S::command(DRIVER_NUM, command::SET_RELATIVE, ticks.0, 0)
.to_result()
.map(|_when: u32| ())?;
loop {
S::yield_wait();
if let Some((_when, _ref)) = called.get() {
return Ok(());
}
}
})
}
}
#[cfg(test)]
mod tests;
// -----------------------------------------------------------------------------
// Driver number and command IDs
// -----------------------------------------------------------------------------
const DRIVER_NUM: u32 = 0x0;
// Command IDs
#[allow(unused)]
mod command {
pub const EXISTS: u32 = 0;
pub const FREQUENCY: u32 = 1;
pub const TIME: u32 = 2;
pub const STOP: u32 = 3;
pub const SET_RELATIVE: u32 = 5;
pub const SET_ABSOLUTE: u32 = 6;
}
#[allow(unused)]
mod subscribe {
pub const CALLBACK: u32 = 0;
}
================================================
FILE: apis/peripherals/alarm/src/tests.rs
================================================
use libtock_unittest::fake;
use crate::{Hz, Milliseconds, Ticks};
type Alarm = crate::Alarm<fake::Syscalls>;
#[test]
fn get_freq() {
let kernel = fake::Kernel::new();
let driver = fake::Alarm::new(1000);
kernel.add_driver(&driver);
assert_eq!(Alarm::get_frequency(), Ok(Hz(1000)));
}
#[test]
fn sleep() {
let kernel = fake::Kernel::new();
let driver = fake::Alarm::new(1000);
kernel.add_driver(&driver);
assert_eq!(Alarm::sleep_for(Ticks(0)), Ok(()));
assert_eq!(Alarm::sleep_for(Ticks(1000)), Ok(()));
assert_eq!(Alarm::sleep_for(Milliseconds(1000)), Ok(()));
}
================================================
FILE: apis/peripherals/gpio/Cargo.toml
================================================
[package]
name = "libtock_gpio"
version = "0.1.0"
authors = ["Tock Project Developers <tock-dev@googlegroups.com>"]
license = "Apache-2.0 OR MIT"
edition = "2018"
repository = "https://www.github.com/tock/libtock-rs"
rust-version.workspace = true
description = "libtock gpio driver"
[features]
rust_embedded = ["embedded-hal"]
[dependencies]
libtock_platform = { path = "../../../platform" }
embedded-hal = { version = "1.0", optional = true }
[dev-dependencies]
libtock_unittest = { path = "../../../unittest" }
================================================
FILE: apis/peripherals/gpio/src/lib.rs
================================================
#![no_std]
use core::marker::PhantomData;
use libtock_platform::{
share::Handle, subscribe::OneId, DefaultConfig, ErrorCode, Subscribe, Syscalls, Upcall,
};
/// The GPIO driver.
///
/// # Example
/// ```ignore
/// use libtock::gpio;
///
/// // Set pin to high.
/// let pin = gpio::Gpio::get_pin(0).unwrap().make_output().unwrap();
/// let _ = pin.set();
/// ```
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum GpioState {
Low = 0,
High = 1,
}
pub enum PinInterruptEdge {
Either = 0,
Rising = 1,
Falling = 2,
}
pub enum Error {
Invalid,
Failed,
}
pub trait Pull {
const MODE: u32;
}
pub struct PullUp;
impl Pull for PullUp {
const MODE: u32 = 1;
}
pub struct PullDown;
impl Pull for PullDown {
const MODE: u32 = 2;
}
pub struct PullNone;
impl Pull for PullNone {
const MODE: u32 = 0;
}
pub struct Gpio<S: Syscalls>(S);
impl<S: Syscalls> Gpio<S> {
/// Returns Ok() if the driver was present.This does not necessarily mean
/// that the driver is working, as it may still fail to allocate grant
/// memory.
pub fn exists() -> Result<(), ErrorCode> {
S::command(DRIVER_NUM, EXISTS, 0, 0).to_result()
}
pub fn count() -> Result<u32, ErrorCode> {
S::command(DRIVER_NUM, GPIO_COUNT, 0, 0).to_result()
}
pub fn get_pin(pin: u32) -> Result<Pin<S>, ErrorCode> {
Self::disable(pin)?;
Ok(Pin {
pin_number: pin,
_syscalls: PhantomData,
})
}
/// Register an interrupt listener
///
/// There can be only one single listener registered at a time.
/// Each time this function is used, it will replace the
/// previously registered listener.
pub fn register_listener<'share, F: Fn(u32, GpioState)>(
listener: &'share GpioInterruptListener<F>,
subscribe: Handle<Subscribe<'share, S, DRIVER_NUM, 0>>,
) -> Result<(), ErrorCode> {
S::subscribe::<_, _, DefaultConfig, DRIVER_NUM, 0>(subscribe, listener)
}
/// Unregister the interrupt listener
///
/// This function may be used even if there was no
/// previously registered listener.
pub fn unregister_listener() {
S::unsubscribe(DRIVER_NUM, 0)
}
}
/// A wrapper around a closure to be registered and called when
/// a gpio interrupt occurs.
///
/// ```ignore
/// let listener = GpioInterruptListener(|gpio, interrupt_edge| {
/// // make use of the button's state
/// });
/// ```
pub struct GpioInterruptListener<F: Fn(u32, GpioState)>(pub F);
impl<F: Fn(u32, GpioState)> Upcall<OneId<DRIVER_NUM, 0>> for GpioInterruptListener<F> {
fn upcall(&self, gpio_index: u32, value: u32, _arg2: u32) {
self.0(gpio_index, value.into())
}
}
impl From<u32> for GpioState {
fn from(original: u32) -> GpioState {
match original {
0 => GpioState::Low,
_ => GpioState::High,
}
}
}
pub struct Pin<S: Syscalls> {
pin_number: u32,
_syscalls: PhantomData<S>,
}
impl<S: Syscalls> Pin<S> {
pub fn make_output(&mut self) -> Result<OutputPin<'_, S>, ErrorCode> {
Gpio::<S>::enable_gpio_output(self.pin_number)?;
Ok(OutputPin { pin: self })
}
pub fn make_input<P: Pull>(&self) -> Result<InputPin<'_, S, P>, ErrorCode> {
Gpio::<S>::enable_gpio_input(self.pin_number, P::MODE)?;
Ok(InputPin {
pin: self,
_pull: PhantomData,
})
}
}
pub struct OutputPin<'a, S: Syscalls> {
pin: &'a Pin<S>,
}
impl<S: Syscalls> OutputPin<'_, S> {
pub fn toggle(&mut self) -> Result<(), ErrorCode> {
Gpio::<S>::toggle(self.pin.pin_number)
}
pub fn set(&mut self) -> Result<(), ErrorCode> {
Gpio::<S>::write(self.pin.pin_number, GpioState::High)
}
pub fn clear(&mut self) -> Result<(), ErrorCode> {
Gpio::<S>::write(self.pin.pin_number, GpioState::Low)
}
}
pub struct InputPin<'a, S: Syscalls, P: Pull> {
pin: &'a Pin<S>,
_pull: PhantomData<P>,
}
impl<S: Syscalls, P: Pull> InputPin<'_, S, P> {
pub fn read(&self) -> Result<GpioState, ErrorCode> {
Gpio::<S>::read(self.pin.pin_number)
}
pub fn enable_interrupts(&self, edge: PinInterruptEdge) -> Result<(), ErrorCode> {
Gpio::<S>::enable_interrupts(self.pin.pin_number, edge)
}
pub fn disable_interrupts(&self) -> Result<(), ErrorCode> {
Gpio::<S>::disable_interrupts(self.pin.pin_number)
}
}
impl<S: Syscalls> Drop for OutputPin<'_, S> {
fn drop(&mut self) {
let _ = Gpio::<S>::disable(self.pin.pin_number);
}
}
impl<S: Syscalls, P: Pull> Drop for InputPin<'_, S, P> {
fn drop(&mut self) {
let _ = Gpio::<S>::disable(self.pin.pin_number);
}
}
// -----------------------------------------------------------------------------
// Implementation details below
// -----------------------------------------------------------------------------
impl<S: Syscalls> Gpio<S> {
fn enable_gpio_output(pin: u32) -> Result<(), ErrorCode> {
S::command(DRIVER_NUM, GPIO_ENABLE_OUTPUT, pin, 0).to_result()
}
fn enable_gpio_input(pin: u32, mode: u32) -> Result<(), ErrorCode> {
S::command(DRIVER_NUM, GPIO_ENABLE_INPUT, pin, mode).to_result()
}
fn write(pin: u32, state: GpioState) -> Result<(), ErrorCode> {
let action = match state {
GpioState::Low => GPIO_CLEAR,
_ => GPIO_SET,
};
S::command(DRIVER_NUM, action, pin, 0).to_result()
}
fn read(pin: u32) -> Result<GpioState, ErrorCode> {
let pin_state: u32 = S::command(DRIVER_NUM, GPIO_READ_INPUT, pin, 0).to_result()?;
Ok(pin_state.into())
}
fn toggle(pin: u32) -> Result<(), ErrorCode> {
S::command(DRIVER_NUM, GPIO_TOGGLE, pin, 0).to_result()
}
fn disable(pin: u32) -> Result<(), ErrorCode> {
S::command(DRIVER_NUM, GPIO_DISABLE, pin, 0).to_result()
}
fn enable_interrupts(pin: u32, edge: PinInterruptEdge) -> Result<(), ErrorCode> {
S::command(DRIVER_NUM, GPIO_ENABLE_INTERRUPTS, pin, edge as u32).to_result()
}
fn disable_interrupts(pin: u32) -> Result<(), ErrorCode> {
S::command(DRIVER_NUM, GPIO_DISABLE_INTERRUPTS, pin, 0).to_result()
}
}
#[cfg(feature = "rust_embedded")]
impl<S: Syscalls> embedded_hal::digital::ErrorType for OutputPin<'_, S> {
type Error = ErrorCode;
}
#[cfg(feature = "rust_embedded")]
impl<S: Syscalls> embedded_hal::digital::OutputPin for OutputPin<'_, S> {
fn set_low(&mut self) -> Result<(), Self::Error> {
self.clear()
}
fn set_high(&mut self) -> Result<(), Self::Error> {
self.set()
}
}
#[cfg(test)]
mod tests;
// -----------------------------------------------------------------------------
// Driver number and command IDs
// -----------------------------------------------------------------------------
const DRIVER_NUM: u32 = 0x4;
// Command IDs
const EXISTS: u32 = 0;
const GPIO_ENABLE_OUTPUT: u32 = 1;
const GPIO_SET: u32 = 2;
const GPIO_CLEAR: u32 = 3;
const GPIO_TOGGLE: u32 = 4;
const GPIO_ENABLE_INPUT: u32 = 5;
const GPIO_READ_INPUT: u32 = 6;
const GPIO_ENABLE_INTERRUPTS: u32 = 7;
const GPIO_DISABLE_INTERRUPTS: u32 = 8;
const GPIO_DISABLE: u32 = 9;
const GPIO_COUNT: u32 = 10;
================================================
FILE: apis/peripherals/gpio/src/tests.rs
================================================
use core::cell::Cell;
use libtock_platform::{share, ErrorCode, Syscalls, YieldNoWaitReturn};
use libtock_unittest::fake::{self, GpioMode, InterruptEdge, PullMode};
use crate::{GpioInterruptListener, GpioState, PinInterruptEdge, PullDown, PullNone, PullUp};
type Gpio = super::Gpio<fake::Syscalls>;
#[test]
fn no_driver() {
let _kernel = fake::Kernel::new();
assert_eq!(Gpio::count(), Err(ErrorCode::NoDevice));
}
#[test]
fn num_gpio() {
let kernel = fake::Kernel::new();
let driver = fake::Gpio::<10>::new();
kernel.add_driver(&driver);
assert_eq!(Gpio::count(), Ok(10));
}
// Tests the OutputPin implementation.
#[test]
fn output() {
let kernel = fake::Kernel::new();
let driver = fake::Gpio::<10>::new();
driver.set_missing_gpio(1);
kernel.add_driver(&driver);
assert_eq!(Gpio::count(), Ok(10));
assert!(core::matches!(Gpio::get_pin(11), Err(ErrorCode::Invalid)));
assert!(core::matches!(Gpio::get_pin(1), Err(ErrorCode::NoDevice)));
let pin_0 = Gpio::get_pin(0);
assert!(pin_0.is_ok());
let _ = pin_0.map(|mut pin| {
let output_pin = pin.make_output();
assert!(output_pin.is_ok());
assert_eq!(driver.get_gpio_state(0).unwrap().mode, GpioMode::Output);
let _ = output_pin.map(|mut pin| {
assert_eq!(pin.set(), Ok(()));
assert!(driver.get_gpio_state(0).unwrap().value);
assert_eq!(pin.clear(), Ok(()));
assert!(!driver.get_gpio_state(0).unwrap().value);
assert_eq!(pin.toggle(), Ok(()));
assert!(driver.get_gpio_state(0).unwrap().value);
assert_eq!(pin.toggle(), Ok(()));
assert!(!driver.get_gpio_state(0).unwrap().value);
});
assert_eq!(driver.get_gpio_state(0).unwrap().mode, GpioMode::Disable);
});
}
// Tests the InputPin implementation
#[test]
fn input() {
let kernel = fake::Kernel::new();
let driver = fake::Gpio::<10>::new();
driver.set_missing_gpio(1);
kernel.add_driver(&driver);
assert_eq!(Gpio::count(), Ok(10));
assert!(core::matches!(Gpio::get_pin(11), Err(ErrorCode::Invalid)));
assert!(core::matches!(Gpio::get_pin(1), Err(ErrorCode::NoDevice)));
let pin_0 = Gpio::get_pin(0);
assert!(pin_0.is_ok());
let _ = pin_0.map(|pin| {
let input_pin = pin.make_input::<PullNone>();
assert!(input_pin.is_ok());
assert_eq!(
driver.get_gpio_state(0).unwrap().mode,
GpioMode::Input(PullMode::PullNone)
);
let input_pin = pin.make_input::<PullUp>();
assert!(input_pin.is_ok());
assert_eq!(
driver.get_gpio_state(0).unwrap().mode,
GpioMode::Input(PullMode::PullUp)
);
let input_pin = pin.make_input::<PullDown>();
assert!(input_pin.is_ok());
assert_eq!(
driver.get_gpio_state(0).unwrap().mode,
GpioMode::Input(PullMode::PullDown)
);
let _ = input_pin.map(|pin| {
assert_eq!(driver.set_value(0, true), Ok(()));
assert_eq!(pin.read(), Ok(GpioState::High));
assert_eq!(driver.set_value(0, false), Ok(()));
assert_eq!(pin.read(), Ok(GpioState::Low));
});
assert_eq!(driver.get_gpio_state(0).unwrap().mode, GpioMode::Disable);
});
}
// Tests the pin interrupts implementation
#[test]
fn interrupts() {
let kernel = fake::Kernel::new();
let driver = fake::Gpio::<10>::new();
driver.set_missing_gpio(1);
kernel.add_driver(&driver);
assert_eq!(Gpio::count(), Ok(10));
let gpio_state = Cell::<Option<GpioState>>::new(None);
let listener = GpioInterruptListener(|gpio, state| {
assert_eq!(gpio, 0);
gpio_state.set(Some(state));
});
assert_eq!(Gpio::enable_interrupts(0, PinInterruptEdge::Either), Ok(()));
share::scope(|subscribe| {
assert_eq!(Gpio::register_listener(&listener, subscribe), Ok(()));
assert_eq!(driver.set_value(0, true), Ok(()));
assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);
assert_eq!(gpio_state.get(), Some(GpioState::High));
});
assert_eq!(driver.set_value(0, false), Ok(()));
assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);
assert!(core::matches!(Gpio::get_pin(11), Err(ErrorCode::Invalid)));
assert!(core::matches!(Gpio::get_pin(1), Err(ErrorCode::NoDevice)));
let pin_0 = Gpio::get_pin(0);
assert!(pin_0.is_ok());
let _ = pin_0.map(|pin| {
// Either
let input_pin = pin.make_input::<PullNone>();
assert!(input_pin.is_ok());
assert_eq!(
driver.get_gpio_state(0).unwrap().mode,
GpioMode::Input(PullMode::PullNone)
);
let _ = input_pin.map(|pin| {
assert_eq!(
pin.enable_interrupts(crate::PinInterruptEdge::Either),
Ok(())
);
assert_eq!(
driver.get_gpio_state(0).unwrap().interrupt_enabled,
Some(InterruptEdge::Either)
);
assert_eq!(driver.set_value(0, false), Ok(()));
let gpio_state = Cell::<Option<GpioState>>::new(None);
let listener = GpioInterruptListener(|gpio, state| {
assert_eq!(gpio, 0);
gpio_state.set(Some(state));
});
share::scope(|subscribe| {
assert_eq!(Gpio::register_listener(&listener, subscribe), Ok(()));
assert_eq!(driver.set_value(0, true), Ok(()));
assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);
assert_eq!(gpio_state.get(), Some(GpioState::High));
gpio_state.set(None);
assert_eq!(driver.set_value(0, false), Ok(()));
assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);
assert_eq!(gpio_state.get(), Some(GpioState::Low));
assert_eq!(pin.disable_interrupts(), Ok(()));
assert_eq!(driver.set_value(0, true), Ok(()));
assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);
assert_eq!(driver.set_value(0, false), Ok(()));
assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);
});
});
// Rising
let input_pin = pin.make_input::<PullNone>();
assert!(input_pin.is_ok());
assert_eq!(
driver.get_gpio_state(0).unwrap().mode,
GpioMode::Input(PullMode::PullNone)
);
let _ = input_pin.map(|pin| {
assert_eq!(
pin.enable_interrupts(crate::PinInterruptEdge::Rising),
Ok(())
);
assert_eq!(
driver.get_gpio_state(0).unwrap().interrupt_enabled,
Some(InterruptEdge::Rising)
);
assert_eq!(driver.set_value(0, false), Ok(()));
let gpio_state = Cell::<Option<GpioState>>::new(None);
let listener = GpioInterruptListener(|gpio, state| {
assert_eq!(gpio, 0);
gpio_state.set(Some(state));
});
share::scope(|subscribe| {
assert_eq!(Gpio::register_listener(&listener, subscribe), Ok(()));
assert_eq!(driver.set_value(0, true), Ok(()));
assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);
assert_eq!(gpio_state.get(), Some(GpioState::High));
assert_eq!(driver.set_value(0, false), Ok(()));
assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);
assert_eq!(pin.disable_interrupts(), Ok(()));
assert_eq!(driver.set_value(0, true), Ok(()));
assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);
assert_eq!(driver.set_value(0, false), Ok(()));
assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);
});
});
// Falling
let input_pin = pin.make_input::<PullNone>();
assert!(input_pin.is_ok());
assert_eq!(
driver.get_gpio_state(0).unwrap().mode,
GpioMode::Input(PullMode::PullNone)
);
let _ = input_pin.map(|pin| {
assert_eq!(
pin.enable_interrupts(crate::PinInterruptEdge::Falling),
Ok(())
);
assert_eq!(
driver.get_gpio_state(0).unwrap().interrupt_enabled,
Some(InterruptEdge::Falling)
);
assert_eq!(driver.set_value(0, false), Ok(()));
let gpio_state = Cell::<Option<GpioState>>::new(None);
let listener = GpioInterruptListener(|gpio, state| {
assert_eq!(gpio, 0);
gpio_state.set(Some(state));
});
share::scope(|subscribe| {
assert_eq!(Gpio::register_listener(&listener, subscribe), Ok(()));
assert_eq!(driver.set_value(0, true), Ok(()));
assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);
assert_eq!(driver.set_value(0, false), Ok(()));
assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);
assert_eq!(gpio_state.get(), Some(GpioState::Low));
assert_eq!(pin.disable_interrupts(), Ok(()));
assert_eq!(driver.set_value(0, true), Ok(()));
assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);
assert_eq!(driver.set_value(0, false), Ok(()));
assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);
});
});
});
}
// Tests the pin event subcribe implementation
#[test]
fn subscribe() {
let kernel = fake::Kernel::new();
let driver = fake::Gpio::<10>::new();
driver.set_missing_gpio(1);
kernel.add_driver(&driver);
assert_eq!(Gpio::count(), Ok(10));
let gpio_state = Cell::<Option<GpioState>>::new(None);
let listener = GpioInterruptListener(|gpio, state| {
assert_eq!(gpio, 0);
gpio_state.set(Some(state));
});
assert_eq!(Gpio::enable_interrupts(0, PinInterruptEdge::Either), Ok(()));
share::scope(|subscribe| {
assert_eq!(Gpio::register_listener(&listener, subscribe), Ok(()));
assert_eq!(driver.set_value(0, true), Ok(()));
assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);
assert_eq!(gpio_state.get(), Some(GpioState::High));
});
assert_eq!(driver.set_value(0, false), Ok(()));
assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);
}
================================================
FILE: apis/peripherals/i2c_master/Cargo.toml
================================================
[package]
name = "libtock_i2c_master"
version = "0.1.0"
authors = [
"Tock Project Developers <tock-dev@googlegroups.com>",
"Alistair Francis <alistair.francis@wdc.com>",
]
license = "Apache-2.0 OR MIT"
edition = "2021"
repository = "https://www.github.com/tock/libtock-rs"
rust-version.workspace = true
description = "libtock I2C master driver"
[dependencies]
libtock_platform = { path = "../../../platform" }
================================================
FILE: apis/peripherals/i2c_master/src/lib.rs
================================================
#![no_std]
use core::cell::Cell;
use libtock_platform as platform;
use libtock_platform::allow_rw::AllowRw;
use libtock_platform::share;
use libtock_platform::subscribe::Subscribe;
use libtock_platform::{DefaultConfig, ErrorCode, Syscalls};
pub struct I2CMaster<S: Syscalls, C: Config = DefaultConfig>(S, C);
impl<S: Syscalls, C: Config> I2CMaster<S, C> {
pub fn exists() -> Result<(), ErrorCode> {
S::command(DRIVER_NUM, i2c_master_cmd::EXISTS, 0, 0).to_result()
}
/// # Summary
///
/// Perform an I2C write followed by a read.
///
/// TODO: Add async support
///
/// # Parameter
///
/// * `addr`: Slave device address
/// * `buf`: Buffer
/// * `w_len`: Number of bytes to write from @w_buf
/// * `r_len`: Number of bytes to read into @r_buf
///
/// # Returns
/// On success: Returns Ok(())
/// On failure: Err(ErrorCode)
pub fn i2c_master_write_read_sync(
addr: u16,
buf: &mut [u8],
w_len: u16,
r_len: u16,
) -> Result<(), ErrorCode> {
if w_len as usize > buf.len() || r_len as usize > buf.len() {
return Err(ErrorCode::NoMem);
}
let called: Cell<Option<(u32, u32, u32)>> = Cell::new(None);
let cmd_arg0: u32 = (w_len as u32) << 8 | addr as u32;
share::scope::<
(
AllowRw<_, DRIVER_NUM, { rw_allow::MASTER }>,
Subscribe<_, DRIVER_NUM, { subscribe::MASTER_WRITE }>,
),
_,
_,
>(|handle| {
let (allow_rw, subscribe) = handle.split();
S::allow_rw::<C, DRIVER_NUM, { rw_allow::MASTER }>(allow_rw, buf)?;
S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::MASTER_READ_WRITE }>(
subscribe, &called,
)?;
S::command(
DRIVER_NUM,
i2c_master_cmd::MASTER_WRITE,
cmd_arg0,
r_len.into(),
)
.to_result::<(), ErrorCode>()?;
loop {
S::yield_wait();
if let Some((r0, status, _)) = called.get() {
assert_eq!(r0, 0);
return match status {
0 => Ok(()),
e_status => Err(e_status.try_into().unwrap_or(ErrorCode::Fail)),
};
}
}
})
}
/// # Summary
///
/// Write to an I2C device the data from the buffer pointed by @buf. This function is
/// synchronous and returns only when the operation has completed.
///
/// TODO: Add async support
///
/// # Parameter
///
/// * `addr`: Slave device address
/// * `buf`: Storage buffer, this should be bigger than @len
/// * `len`: Number of bytes to read into @buf
///
/// # Returns
/// On success: Returns Ok(())
/// On failure: Err(ErrorCode)
pub fn i2c_master_write_sync(addr: u16, buf: &mut [u8], len: u16) -> Result<(), ErrorCode> {
let called: Cell<Option<(u32, u32, u32)>> = Cell::new(None);
share::scope::<
(
AllowRw<_, DRIVER_NUM, { rw_allow::MASTER }>,
Subscribe<_, DRIVER_NUM, { subscribe::MASTER_WRITE }>,
),
_,
_,
>(|handle| {
let (allow_rw, subscribe) = handle.split();
S::allow_rw::<C, DRIVER_NUM, { rw_allow::MASTER }>(allow_rw, buf)?;
S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::MASTER_WRITE }>(subscribe, &called)?;
S::command(
DRIVER_NUM,
i2c_master_cmd::MASTER_WRITE,
addr.into(),
len.into(),
)
.to_result::<(), ErrorCode>()?;
loop {
S::yield_wait();
if let Some((r0, status, _)) = called.get() {
assert_eq!(r0, 0);
return match status {
0 => Ok(()),
e_status => Err(e_status.try_into().unwrap_or(ErrorCode::Fail)),
};
}
}
})
}
/// # Summary
///
/// Read from an I2C device the data to the buffer pointed by @buf. This function is
/// synchronous and returns only when the operation has completed.
///
/// TODO: Add async support
///
/// # Parameter
///
/// * `addr`: Slave device address
/// * `buf`: Storage buffer, this should be bigger than @len
/// * `len`: Number of bytes to read into @buf
///
/// # Returns
/// On success: Returns Ok(())
/// On failure: Err(ErrorCode)
pub fn i2c_master_read_sync(addr: u16, buf: &mut [u8], len: u16) -> Result<(), ErrorCode> {
let called: Cell<Option<(u32, u32, u32)>> = Cell::new(None);
share::scope::<
(
AllowRw<_, DRIVER_NUM, { rw_allow::MASTER }>,
Subscribe<_, DRIVER_NUM, { subscribe::MASTER_READ }>,
),
_,
_,
>(|handle| {
let (allow_rw, subscribe) = handle.split();
S::allow_rw::<C, DRIVER_NUM, { rw_allow::MASTER }>(allow_rw, buf)?;
S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::MASTER_READ }>(subscribe, &called)?;
S::command(
DRIVER_NUM,
i2c_master_cmd::MASTER_READ,
addr.into(),
len.into(),
)
.to_result::<(), ErrorCode>()?;
loop {
S::yield_wait();
if let Some((r0, status, _)) = called.get() {
assert_eq!(r0, 0);
return match status {
0 => Ok(()),
e_status => Err(e_status.try_into().unwrap_or(ErrorCode::Fail)),
};
}
}
})
}
}
/// System call configuration trait for `I2CMaster`.
pub trait Config:
platform::allow_ro::Config + platform::allow_rw::Config + platform::subscribe::Config
{
}
impl<T: platform::allow_ro::Config + platform::allow_rw::Config + platform::subscribe::Config>
Config for T
{
}
// -----------------------------------------------------------------------------
// Driver number and command IDs
// -----------------------------------------------------------------------------
const DRIVER_NUM: u32 = 0x20003;
#[allow(unused)]
mod subscribe {
pub const MASTER_READ: u32 = 0;
pub const MASTER_WRITE: u32 = 0;
pub const MASTER_READ_WRITE: u32 = 0;
}
/// Ids for read-write allow buffers
#[allow(unused)]
mod rw_allow {
pub const MASTER: u32 = 1;
}
#[allow(unused)]
mod i2c_master_cmd {
pub const EXISTS: u32 = 0;
pub const MASTER_WRITE: u32 = 1;
pub const MASTER_READ: u32 = 2;
pub const MASTER_WRITE_READ: u32 = 3;
}
================================================
FILE: apis/peripherals/i2c_master_slave/Cargo.toml
================================================
[package]
name = "libtock_i2c_master_slave"
version = "0.1.0"
authors = [
"Tock Project Developers <tock-dev@googlegroups.com>",
"Wilfred Mallawa <wilfred.mallawa@wdc.com>",
]
license = "Apache-2.0 OR MIT"
edition = "2021"
repository = "https://www.github.com/tock/libtock-rs"
rust-version.workspace = true
description = "libtock I2C master-slave driver"
[dependencies]
libtock_platform = { path = "../../../platform" }
================================================
FILE: apis/peripherals/i2c_master_slave/src/lib.rs
================================================
#![no_std]
use core::cell::Cell;
use libtock_platform as platform;
use libtock_platform::allow_ro::AllowRo;
use libtock_platform::allow_rw::AllowRw;
use libtock_platform::share;
use libtock_platform::subscribe::Subscribe;
use libtock_platform::{DefaultConfig, ErrorCode, Syscalls};
pub struct I2CMasterSlave<S: Syscalls, C: Config = DefaultConfig>(S, C);
impl<S: Syscalls, C: Config> I2CMasterSlave<S, C> {
pub fn exists() -> Result<(), ErrorCode> {
S::command(DRIVER_NUM, i2c_master_slave_cmd::EXISTS, 0, 0).to_result()
}
/// # Summary
///
/// Perform an I2C write to the slave device on @addr.
///
/// # Parameter
///
/// * `addr`: Slave device address
/// * `buf`: Storage buffer, this should be bigger than @len
/// * `len`: Number of bytes to write from @buf
///
/// # Returns
/// On success: Returns Ok(()), @len bytes were written from @buf.
/// On failure: Err(ErrorCode), with failure ErrorCode.
pub fn i2c_master_slave_write_sync(
addr: u16,
buffer: &[u8],
len: u16,
) -> Result<(), ErrorCode> {
// We could write just the buffer length, but this may lead to
// ambiguities for the caller. So Err out early.
if len as usize > buffer.len() {
return Err(ErrorCode::NoMem);
}
let called: Cell<Option<(u32, u32, u32)>> = Cell::new(None);
// The kernel will split this argument into upper length and lower address.
let cmd_arg0: u32 = (len as u32) << 16 | addr as u32;
share::scope::<
(
AllowRo<_, DRIVER_NUM, { ro_allow::MASTER_TX }>,
Subscribe<_, DRIVER_NUM, { subscribe::MASTER_WRITE }>,
),
_,
_,
>(|handle| {
let (allow_ro, subscribe) = handle.split();
S::allow_ro::<C, DRIVER_NUM, { i2c_buffers::MASTER_WRITE }>(allow_ro, buffer)?;
S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::MASTER_WRITE }>(subscribe, &called)?;
S::command(DRIVER_NUM, i2c_master_slave_cmd::MASTER_WRITE, cmd_arg0, 0)
.to_result::<(), ErrorCode>()?;
loop {
S::yield_wait();
if let Some((r0, status, _r1)) = called.get() {
// Kernel uses a different cmd number for this...
assert_eq!(r0, 0);
return match status {
0 => Ok(()),
e_status => Err(e_status.try_into().unwrap_or(ErrorCode::Fail)),
};
}
}
})
}
/// # Summary
///
/// Perform an I2C read from the the slave device with the slave address of @addr.
///
/// # Parameter
///
/// * `addr`: Slave device address
/// * `buf`: Storage buffer, this should be bigger than @len
/// * `len`: Number of bytes to read into @buf
///
/// # Returns
/// On success: Returns Ok(()) with @bytes_received valid.
/// On failure: Err(ErrorCode), Failure ErrorCode and @bytes_received is invalid.
///
/// Note: @bytes_received is the first return tuple index (valid only on success).
pub fn i2c_master_slave_read_sync(
addr: u16,
buf: &mut [u8],
len: u16,
) -> (usize, Result<(), ErrorCode>) {
if len as usize > buf.len() {
return (0, Err(ErrorCode::NoMem));
}
// This is the total amount of bytes read if the operation was a success.
// Otherwise, it is invalid.
let mut bytes_received: usize = core::cmp::min(buf.len(), len as usize);
let called: Cell<Option<(u32, u32, u32)>> = Cell::new(None);
// The kernel will split this argument into upper length and lower address.
let cmd_arg0: u32 = (len as u32) << 16 | addr as u32;
let r = share::scope::<
(
AllowRw<_, DRIVER_NUM, { rw_allow::MASTER_RX }>,
Subscribe<_, DRIVER_NUM, { subscribe::MASTER_READ }>,
),
_,
_,
>(|handle| {
let (allow_rw, subscribe) = handle.split();
S::allow_rw::<C, DRIVER_NUM, { i2c_buffers::MASTER_READ }>(allow_rw, buf)?;
S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::MASTER_READ }>(subscribe, &called)?;
// When this fails, `called` is guaranteed unmodified,
// because upcalls are never processed until we call `yield`.
S::command(DRIVER_NUM, i2c_master_slave_cmd::MASTER_READ, cmd_arg0, 0)
.to_result::<(), ErrorCode>()?;
loop {
S::yield_wait();
if let Some((r0, _read_len, status)) = called.get() {
// TODO: The kernel I2C api does not currently return the read_len, so this
// will be invalid. We should keep track, likely assume the transfer was
// done if no error. See: tock@capsules/core/src/i2c_master_slave_driver.rs:129
// see: https://github.com/tock/tock/issues/3735
// Kernel uses a different cmd number for this...
assert_eq!(r0, 1);
return match status {
0 => Ok(()),
e_status => Err(e_status.try_into().unwrap_or(ErrorCode::Fail)),
};
}
}
});
// If the operation failed, make bytes received zero so that the caller isn't confused in case
// the error is not handled properly. That is, in case of an error, we cannot guarantee the
// number of bytes received.
if r.is_err() {
bytes_received = 0;
}
(bytes_received, r)
}
/// # Summary
///
/// Perform an I2C write followed by a read.
///
/// Note: The kernel uses the TX buffer for both actions, such that if you request a
/// a read that exceeds the buffer length of @w_buf, the read will be
/// limited to the capacity of @w_buf. This API will detect such a case
/// and error to avoid ambiguities until we have a better solution in the kernel.
///
/// # Parameter
///
/// * `addr`: Slave device address
/// * `w_buf`: Write buffer
/// * `r_buf`: Read buffer
/// * `w_len`: Number of bytes to write from @w_buf
/// * `r_len`: Number of bytes to read into @r_buf
///
/// # Returns
/// On success: Returns Ok(()) with @bytes_received valid.
/// On failure: Err(ErrorCode), Failure ErrorCode and @bytes_received is invalid.
///
/// Note: @bytes_received is the first return tuple index (valid only on success).
pub fn i2c_master_slave_write_read_sync(
addr: u16,
w_buf: &mut [u8],
r_buf: &mut [u8],
w_len: u16,
r_len: u16,
) -> (usize, Result<(), ErrorCode>) {
if w_len as usize > w_buf.len() || r_len as usize > r_buf.len() {
return (0, Err(ErrorCode::NoMem));
}
// TODO: Kernel uses the TX Buffer to perform both RX/TX for a write_read, so if
// the @w_buff is smaller than @r_len. The subsequent read will stop prematurely.
// So let's error here until that is addressed.
if r_len as usize > w_buf.len() {
return (0, Err(ErrorCode::NoMem));
}
// This is the total amount of bytes read if the operation was a success.
// Otherwise, it is invalid.
let mut bytes_received: usize = core::cmp::min(r_buf.len(), r_len as usize);
let called: Cell<Option<(u32, u32, u32)>> = Cell::new(None);
let cmd_arg0: u32 = (w_len as u32) << 16 | (r_len as u32) << 8 | addr as u32;
let r = share::scope::<
(
AllowRw<_, DRIVER_NUM, { rw_allow::MASTER_RX }>,
AllowRo<_, DRIVER_NUM, { ro_allow::MASTER_TX }>,
Subscribe<_, DRIVER_NUM, { subscribe::MASTER_WRITE_READ }>,
),
_,
_,
>(|handle| {
let (allow_rw, allow_ro, subscribe) = handle.split();
S::allow_rw::<C, DRIVER_NUM, { i2c_buffers::MASTER_READ }>(allow_rw, r_buf)?;
S::allow_ro::<C, DRIVER_NUM, { i2c_buffers::MASTER_WRITE }>(allow_ro, w_buf)?;
S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::MASTER_WRITE_READ }>(
subscribe, &called,
)?;
// When this fails, `called` is guaranteed unmodified,
// because upcalls are never processed until we call `yield`.
S::command(
DRIVER_NUM,
i2c_master_slave_cmd::MASTER_WRITE_READ,
cmd_arg0,
0,
)
.to_result::<(), ErrorCode>()?;
loop {
S::yield_wait();
if let Some((r0, _read_len, status)) = called.get() {
// TODO: The kernel I2C api does not currently return the read_len, so this
// will be invalid. We should keep track, likely assume the transfer was
// done if no error. See: tock@capsules/core/src/i2c_master_slave_driver.rs:129
// see: https://github.com/tock/tock/issues/3735
assert_eq!(r0, i2c_master_slave_cmd::MASTER_WRITE_READ);
return match status {
0 => Ok(()),
e_status => Err(e_status.try_into().unwrap_or(ErrorCode::Fail)),
};
}
}
});
// If the operation failed, make bytes received zero so that the caller isn't confused in case
// the error is not handled properly. That is, in case of an error, we cannot guarantee the
// number of bytes received.
if r.is_err() {
bytes_received = 0;
}
(bytes_received, r)
}
/// # Summary
///
/// Set the slave address for this device for slave mode operation. The IP should respond
/// to @addr.
///
/// # Parameter
///
/// * `addr`: Slave device address to set
///
/// # Returns
/// On success: Returns Ok(())
/// On failure: Err(ErrorCode)
pub fn i2c_master_slave_set_slave_address(addr: u8) -> Result<(), ErrorCode> {
// We do not count the R/W bit as part of the address, so the
// valid range is 0x00-0x7f
if addr > 0x7f {
return Err(ErrorCode::Invalid);
}
S::command(
DRIVER_NUM,
i2c_master_slave_cmd::SLAVE_SET_ADDR,
addr as u32,
0,
)
.to_result()
}
/// # Summary
///
/// Expect a write from master into the buffer pointed by @buf. This function is
/// synchronous and returns only when the operation has completed.
///
/// TODO: Add async support
///
/// Note: As we do not know the size of data to be sent from a master device,
/// it is suggested to allocated a large buffer to accommodate bigger transfers.
///
/// # Parameter
///
/// * `buf`: Buffer into which to copy data from master
///
/// # Returns
/// On success: Returns (bytes_read, Ok(()))
/// On failure: (0, Err(ErrorCode))
pub fn i2c_master_slave_write_recv_sync(buf: &mut [u8]) -> (usize, Result<(), ErrorCode>) {
let called: Cell<Option<(u32, u32, u32)>> = Cell::new(None);
let mut bytes_recvd_ret: u32 = 0;
let r = share::scope::<
(
AllowRw<_, DRIVER_NUM, { rw_allow::SLAVE_RX }>,
Subscribe<_, DRIVER_NUM, { subscribe::SLAVE_WRITE_RECV }>,
),
_,
_,
>(|handle| {
let (allow_rw, subscribe) = handle.split();
S::allow_rw::<C, DRIVER_NUM, { rw_allow::SLAVE_RX }>(allow_rw, buf)?;
S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::SLAVE_READ }>(subscribe, &called)?;
S::command(DRIVER_NUM, i2c_master_slave_cmd::SLAVE_START_LISTEN, 0, 0)
.to_result::<(), ErrorCode>()?;
loop {
S::yield_wait();
if let Some((r0, bytes_recvd, status)) = called.get() {
// TODO: Ensure we are returning from the correct upcall and not from an unexpected `read_expect`
// Everything in this module subscribes to `0`. Which can be problematic from an async context.
assert_eq!(r0, i2c_master_slave_cmd::SLAVE_START_LISTEN);
return match status {
0 => {
bytes_recvd_ret = bytes_recvd;
Ok(())
}
e_status => Err(e_status.try_into().unwrap_or(ErrorCode::Fail)),
};
}
}
});
(bytes_recvd_ret as usize, r)
}
/// # Summary
///
/// Expect a write from master into the buffer pointed by @buf. This function is
/// synchronous and returns only when the operation has completed.
///
/// TODO: Add async support
///
/// # Parameter
///
/// * `buf`: Buffer from which to transfer data from
/// * `len`: max number of bytes from buffer to transfer
///
/// # Returns
/// On success: Returns (bytes_sent, Ok(()))
/// On failure: (0, Err(ErrorCode))
pub fn i2c_master_slave_read_send_sync(
buf: &[u8],
len: usize,
) -> (usize, Result<(), ErrorCode>) {
if len > buf.len() {
return (0, Err(ErrorCode::Invalid));
}
let called: Cell<Option<(u32, u32, u32)>> = Cell::new(None);
let mut bytes_sent_ret: u32 = 0;
let r = share::scope::<
(
AllowRo<_, DRIVER_NUM, { ro_allow::SLAVE_TX }>,
Subscribe<_, DRIVER_NUM, { subscribe::SLAVE_READ_SEND }>,
),
_,
_,
>(|handle| {
let (allow_ro, subscribe) = handle.split();
S::allow_ro::<C, DRIVER_NUM, { ro_allow::SLAVE_TX }>(allow_ro, buf)?;
S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::SLAVE_READ }>(subscribe, &called)?;
S::command(
DRIVER_NUM,
i2c_master_slave_cmd::SLAVE_READ_SEND,
len as u32,
0,
)
.to_result::<(), ErrorCode>()?;
loop {
S::yield_wait();
if let Some((r0, bytes_sent, status)) = called.get() {
// TODO: Ensure we are returning from the correct upcall and not from an unexpected `read_expect`
// Everything in this module subscribes to `0`. Which can be problematic from an async context.
assert_eq!(r0, i2c_master_slave_cmd::SLAVE_READ_SEND);
return match status {
0 => {
bytes_sent_ret = bytes_sent;
Ok(())
}
e_status => Err(e_status.try_into().unwrap_or(ErrorCode::Fail)),
};
}
}
});
(bytes_sent_ret as usize, r)
}
}
/// System call configuration trait for `I2CMaster`.
pub trait Config:
platform::allow_ro::Config + platform::allow_rw::Config + platform::subscribe::Config
{
}
impl<T: platform::allow_ro::Config + platform::allow_rw::Config + platform::subscribe::Config>
Config for T
{
}
// -----------------------------------------------------------------------------
// Driver number and command IDs
// -----------------------------------------------------------------------------
const DRIVER_NUM: u32 = 0x20006;
#[allow(unused)]
mod subscribe {
// TODO: It seems like only 0 is supported by the i2c_master_slave capsule currently
// would be nice to improve this.
pub const MASTER_WRITE: u32 = 0;
pub const MASTER_WRITE_READ: u32 = 0;
pub const MASTER_READ: u32 = 0;
pub const SLAVE_READ: u32 = 0;
pub const SLAVE_WRITE_RECV: u32 = 0;
pub const SLAVE_READ_SEND: u32 = 0;
}
/// Ids for read-only allow buffers
#[allow(unused)]
mod ro_allow {
pub const MASTER_TX: u32 = 0;
pub const SLAVE_TX: u32 = 2;
/// The number of allow buffers the kernel stores for this grant
pub const COUNT: u8 = 3;
}
/// Ids for read-write allow buffers
#[allow(unused)]
mod rw_allow {
pub const MASTER_RX: u32 = 1;
pub const SLAVE_RX: u32 = 3;
}
#[allow(unused)]
mod i2c_buffers {
pub const MASTER_WRITE: u32 = 0;
pub const MASTER_READ: u32 = 1;
pub const SLAVE_READ: u32 = 2;
pub const SLAVE_WRITE: u32 = 3;
}
#[allow(unused)]
mod i2c_master_slave_cmd {
pub const EXISTS: u32 = 0;
pub const MASTER_WRITE: u32 = 1;
pub const MASTER_READ: u32 = 2;
pub const SLAVE_START_LISTEN: u32 = 3;
pub const SLAVE_READ_SEND: u32 = 4;
pub const SLAVE_SET_ADDR: u32 = 6;
pub const MASTER_WRITE_READ: u32 = 7;
}
================================================
FILE: apis/peripherals/rng/Cargo.toml
================================================
[package]
name = "libtock_rng"
version = "0.1.0"
authors = [
"Tock Project Developers <tock-dev@googlegroups.com>",
"Cosmin Gabriel Georgescu <cosmingg2013@gmail.com>",
]
license = "Apache-2.0 OR MIT"
edition = "2021"
repository = "https://www.github.com/tock/libtock-rs"
rust-version.workspace = true
description = "libtock rng driver"
[dependencies]
libtock_platform = { path = "../../../platform" }
[dev-dependencies]
libtock_unittest = { path = "../../../unittest" }
================================================
FILE: apis/peripherals/rng/src/lib.rs
================================================
#![no_std]
use core::cell::Cell;
use libtock_platform::{
share, subscribe::OneId, AllowRw, DefaultConfig, ErrorCode, Subscribe, Syscalls, Upcall,
};
pub struct Rng<S: Syscalls>(S);
impl<S: Syscalls> Rng<S> {
/// Check if the RNG kernel driver exists
pub fn exists() -> Result<(), ErrorCode> {
S::command(DRIVER_NUM, EXISTS, 0, 0).to_result()
}
/// Request `n` bytes of randomness in an asynchronous way.
/// Users must first share a buffer slice with the kernel and register an Rng listener
pub fn get_bytes_async(n: u32) -> Result<(), ErrorCode> {
S::command(DRIVER_NUM, GET_BYTES, n, 0).to_result()
}
/// Share a buffer slice with the kernel.
/// Must be used in conjunction with the `share::scope` function
pub fn allow_buffer<'share>(
buf: &'share mut [u8],
allow_rw: share::Handle<AllowRw<'share, S, DRIVER_NUM, 0>>,
) -> Result<(), ErrorCode> {
S::allow_rw::<DefaultConfig, DRIVER_NUM, 0>(allow_rw, buf)
}
pub fn unallow_buffer() {
S::unallow_rw(DRIVER_NUM, 0)
}
/// Register an Rng listener to be called when an upcall is serviced
/// Must be used in conjunction with the `share::scope` function
pub fn register_listener<'share, F: Fn(u32)>(
listener: &'share RngListener<F>,
subscribe: share::Handle<Subscribe<'share, S, DRIVER_NUM, 0>>,
) -> Result<(), ErrorCode> {
S::subscribe::<_, _, DefaultConfig, DRIVER_NUM, 0>(subscribe, listener)
}
pub fn unregister_listener() {
S::unsubscribe(DRIVER_NUM, 0)
}
/// Ask to fill the provided `buf` with `n` random bytes.
/// If `n > buf.len()`, it will simply fill the whole buffer.
pub fn get_bytes_sync(buf: &mut [u8], n: u32) -> Result<(), ErrorCode> {
let called = Cell::new(false);
share::scope::<(AllowRw<S, DRIVER_NUM, 0>, Subscribe<S, DRIVER_NUM, 0>), _, _>(|handle| {
let (allow_rw, subscribe) = handle.split();
// Share the provided buffer with the kernel
S::allow_rw::<DefaultConfig, DRIVER_NUM, 0>(allow_rw, buf)?;
// Subscribe for an upcall with the kernel
S::subscribe::<_, _, DefaultConfig, DRIVER_NUM, 0>(subscribe, &called)?;
// Send the command to the kernel driver to fill the allowed_readwrite buffer
S::command(DRIVER_NUM, GET_BYTES, n, 0).to_result::<(), ErrorCode>()?;
// Wait for a callback to happen
while !called.get() {
S::yield_wait();
}
Ok(())
})
}
}
/// The provided listener to be called.
/// Interior function operates on the number of random bytes filled into the buffer
pub struct RngListener<F: Fn(u32)>(pub F);
impl<F: Fn(u32)> Upcall<OneId<DRIVER_NUM, 0>> for RngListener<F> {
fn upcall(&self, _: u32, arg1: u32, _: u32) {
(self.0)(arg1)
}
}
// -------------
// DRIVER NUMBER
// -------------
const DRIVER_NUM: u32 = 0x40001;
// ---------------
// COMMAND NUMBERS
// ---------------
const EXISTS: u32 = 0;
const GET_BYTES: u32 = 1;
================================================
FILE: apis/peripherals/spi_controller/Cargo.toml
================================================
[package]
name = "libtock_spi_controller"
version = "0.1.0"
authors = [
"Tock Project Developers <tock-dev@googlegroups.com>",
"Alistair Francis <alistair.francis@wdc.com>",
]
license = "Apache-2.0 OR MIT"
edition = "2021"
repository = "https://www.github.com/tock/libtock-rs"
rust-version.workspace = true
description = "libtock SPI controller driver"
[dependencies]
libtock_platform = { path = "../../../platform" }
================================================
FILE: apis/peripherals/spi_controller/src/lib.rs
================================================
#![no_std]
use core::cell::Cell;
use libtock_platform as platform;
use libtock_platform::allow_rw::AllowRw;
use libtock_platform::share;
use libtock_platform::subscribe::Subscribe;
use libtock_platform::AllowRo;
use libtock_platform::{DefaultConfig, ErrorCode, Syscalls};
pub struct SpiController<S: Syscalls, C: Config = DefaultConfig>(S, C);
impl<S: Syscalls, C: Config> SpiController<S, C> {
pub fn exists() -> Result<(), ErrorCode> {
S::command(DRIVER_NUM, spi_controller_cmd::EXISTS, 0, 0).to_result()
}
/// # Summary
///
/// Perform an I2C write followed by a read.
///
/// TODO: Add async support
///
/// # Parameter
///
/// * `addr`: Slave device address
/// * `buf`: Buffer
/// * `w_len`: Number of bytes to write from @w_buf
/// * `r_len`: Number of bytes to read into @r_buf
///
/// # Returns
/// On success: Returns Ok(())
/// On failure: Err(ErrorCode)
pub fn spi_controller_write_read_sync(
w_buf: &[u8],
r_buf: &mut [u8],
len: u32,
) -> Result<(), ErrorCode> {
if len as usize > w_buf.len() || len as usize > r_buf.len() {
return Err(ErrorCode::NoMem);
}
let called: Cell<Option<(u32, u32, u32)>> = Cell::new(None);
share::scope::<
(
AllowRw<_, DRIVER_NUM, { rw_allow::READ }>,
AllowRo<_, DRIVER_NUM, { ro_allow::WRITE }>,
Subscribe<_, DRIVER_NUM, { subscribe::COMPLETE }>,
),
_,
_,
>(|handle| {
let (allow_rw, allow_ro, subscribe) = handle.split();
S::allow_rw::<C, DRIVER_NUM, { rw_allow::READ }>(allow_rw, r_buf)?;
S::allow_ro::<C, DRIVER_NUM, { ro_allow::WRITE }>(allow_ro, w_buf)?;
S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::COMPLETE }>(subscribe, &called)?;
S::command(DRIVER_NUM, spi_controller_cmd::READ_WRITE_BYTES, len, 0)
.to_result::<(), ErrorCode>()?;
loop {
S::yield_wait();
if let Some((r0, status, _)) = called.get() {
assert_eq!(r0, len);
return match status {
0 => Ok(()),
e_status => Err(e_status.try_into().unwrap_or(ErrorCode::Fail)),
};
}
}
})
}
pub fn spi_controller_write_sync(w_buf: &[u8], len: u32) -> Result<(), ErrorCode> {
if len as usize > w_buf.len() {
return Err(ErrorCode::NoMem);
}
let called: Cell<Option<(u32, u32, u32)>> = Cell::new(None);
share::scope::<
(
AllowRo<_, DRIVER_NUM, { ro_allow::WRITE }>,
Subscribe<_, DRIVER_NUM, { subscribe::COMPLETE }>,
),
_,
_,
>(|handle| {
let (allow_ro, subscribe) = handle.split();
S::allow_ro::<C, DRIVER_NUM, { ro_allow::WRITE }>(allow_ro, w_buf)?;
S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::COMPLETE }>(subscribe, &called)?;
S::command(DRIVER_NUM, spi_controller_cmd::READ_WRITE_BYTES, len, 0)
.to_result::<(), ErrorCode>()?;
loop {
S::yield_wait();
if let Some((r0, status, _)) = called.get() {
assert_eq!(r0, len);
return match status {
0 => Ok(()),
e_status => Err(e_status.try_into().unwrap_or(ErrorCode::Fail)),
};
}
}
})
}
pub fn spi_controller_read_sync(r_buf: &mut [u8], len: u32) -> Result<(), ErrorCode> {
if len as usize > r_buf.len() {
return Err(ErrorCode::NoMem);
}
let called: Cell<Option<(u32, u32, u32)>> = Cell::new(None);
share::scope::<
(
AllowRw<_, DRIVER_NUM, { rw_allow::READ }>,
Subscribe<_, DRIVER_NUM, { subscribe::COMPLETE }>,
),
_,
_,
>(|handle| {
let (allow_rw, subscribe) = handle.split();
S::allow_rw::<C, DRIVER_NUM, { rw_allow::READ }>(allow_rw, r_buf)?;
S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::COMPLETE }>(subscribe, &called)?;
S::command(DRIVER_NUM, spi_controller_cmd::READ_BYTES, len, 0)
.to_result::<(), ErrorCode>()?;
loop {
S::yield_wait();
if let Some((r0, status, _)) = called.get() {
assert_eq!(r0, len);
return match status {
0 => Ok(()),
e_status => Err(e_status.try_into().unwrap_or(ErrorCode::Fail)),
};
}
}
})
}
pub fn spi_controller_inplace_write_read_sync(
r_buf: &mut [u8],
len: u32,
) -> Result<(), ErrorCode> {
if len as usize > r_buf.len() {
return Err(ErrorCode::NoMem);
}
let called: Cell<Option<(u32, u32, u32)>> = Cell::new(None);
share::scope::<
(
AllowRw<_, DRIVER_NUM, { rw_allow::READ }>,
Subscribe<_, DRIVER_NUM, { subscribe::COMPLETE }>,
),
_,
_,
>(|handle| {
let (allow_rw, subscribe) = handle.split();
S::allow_rw::<C, DRIVER_NUM, { rw_allow::READ }>(allow_rw, r_buf)?;
S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::COMPLETE }>(subscribe, &called)?;
S::command(
DRIVER_NUM,
spi_controller_cmd::INPLACE_READ_WRITE_BYTES,
len,
0,
)
.to_result::<(), ErrorCode>()?;
loop {
S::yield_wait();
if let Some((r0, status, _)) = called.get() {
assert_eq!(r0, len);
return match status {
0 => Ok(()),
e_status => Err(e_status.try_into().unwrap_or(ErrorCode::Fail)),
};
}
}
})
}
}
/// System call configuration trait for `SpiController`.
pub trait Config:
platform::allow_ro::Config + platform::allow_rw::Config + platform::subscribe::Config
{
}
impl<T: platform::allow_ro::Config + platform::allow_rw::Config + platform::subscribe::Config>
Config for T
{
}
// -----------------------------------------------------------------------------
// Driver number and command IDs
// -----------------------------------------------------------------------------
const DRIVER_NUM: u32 = 0x20001;
#[allow(unused)]
mod subscribe {
pub const COMPLETE: u32 = 0;
}
#[allow(unused)]
mod ro_allow {
pub const WRITE: u32 = 0;
}
#[allow(unused)]
mod rw_allow {
pub const READ: u32 = 0;
}
#[allow(unused)]
mod spi_controller_cmd {
pub const EXISTS: u32 = 0;
pub const READ_WRITE_BYTES: u32 = 2;
pub const SET_BAUD: u32 = 5;
pub const GET_BAUD: u32 = 6;
pub const SET_PHASE: u32 = 7;
pub const GET_PHASE: u32 = 8;
pub const SET_POLARITY: u32 = 9;
pub const GET_POLARITY: u32 = 10;
pub const READ_BYTES: u32 = 11;
pub const INPLACE_READ_WRITE_BYTES: u32 = 12;
}
================================================
FILE: apis/sensors/air_quality/Cargo.toml
================================================
[package]
name = "libtock_air_quality"
version = "0.1.0"
authors = ["Tock Project Developers <tock-dev@googlegroups.com>"]
license = "Apache-2.0 OR MIT"
edition = "2021"
repository = "https://www.github.com/tock/libtock-rs"
rust-version.workspace = true
description = "libtock air quality driver"
[dependencies]
libtock_platform = { path = "../../../platform" }
[dev-dependencies]
libtock_unittest = { path = "../../../unittest" }
================================================
FILE: apis/sensors/air_quality/src/lib.rs
================================================
#![no_std]
use core::cell::Cell;
use libtock_platform::subscribe::OneId;
use libtock_platform::{
share::scope, share::Handle, DefaultConfig, ErrorCode, Subscribe, Syscalls, Upcall,
};
use Value::{Tvoc, CO2};
enum Value {
CO2 = READ_CO2 as isize,
Tvoc = READ_TVOC as isize,
}
pub struct AirQuality<S: Syscalls>(S);
impl<S: Syscalls> AirQuality<S> {
/// Returns Ok() if the driver was present.This does not necessarily mean
/// that the driver is working.
pub fn exists() -> Result<(), ErrorCode> {
S::command(DRIVER_NUM, EXISTS, 0, 0).to_result()
}
/// Register an events listener
pub fn register_listener<'share, F: Fn(u32)>(
listener: &'share AirQualityListener<F>,
subscribe: Handle<Subscribe<'share, S, DRIVER_NUM, 0>>,
) -> Result<(), ErrorCode> {
S::subscribe::<_, _, DefaultConfig, DRIVER_NUM, 0>(subscribe, listener)
}
/// Unregister the events listener
pub fn unregister_listener() {
S::unsubscribe(DRIVER_NUM, 0)
}
/// Initiate a CO2 measurement.
///
/// This function is used both for synchronous and asynchronous readings
pub fn read_co2() -> Result<(), ErrorCode> {
S::command(DRIVER_NUM, READ_CO2, 0, 0).to_result()
}
/// Initiate a TVOC measurement.
///
/// This function is used both for synchronous and asynchronous readings
pub fn read_tvoc() -> Result<(), ErrorCode> {
S::command(DRIVER_NUM, READ_TVOC, 0, 0).to_result()
}
/// Public wrapper for `read_data_sync` for CO2 synchronous measurement
pub fn read_co2_sync() -> Result<u32, ErrorCode> {
Self::read_data_sync(CO2)
}
/// Public wrapper for `read_data_sync` for TVOC synchronous measurement
pub fn read_tvoc_sync() -> Result<u32, ErrorCode> {
Self::read_data_sync(Tvoc)
}
/// Read both CO2 and TVOC values synchronously
pub fn read_sync() -> Result<(u32, u32), ErrorCode> {
match (Self::read_data_sync(CO2), Self::read_data_sync(Tvoc)) {
(Ok(co2_value), Ok(tvoc_value)) => Ok((co2_value, tvoc_value)),
(Err(co2_error), _) => Err(co2_error),
(_, Err(tvoc_error)) => Err(tvoc_error),
}
}
/// Initiate a synchronous CO2 or TVOC measurement, based on the `read_type`.
/// Returns Ok(value) if the operation was successful
fn read_data_sync(read_type: Value) -> Result<u32, ErrorCode> {
let data_cell: Cell<Option<u32>> = Cell::new(None);
let listener = AirQualityListener(|data_val| {
data_cell.set(Some(data_val));
});
scope(|subscribe| {
Self::register_listener(&listener, subscribe)?;
match read_type {
CO2 => {
Self::read_co2()?;
while data_cell.get().is_none() {
S::yield_wait();
}
match data_cell.get() {
None => Err(ErrorCode::Fail),
Some(co2_value) => Ok(co2_value),
}
}
Tvoc => {
Self::read_tvoc()?;
while data_cell.get().is_none() {
S::yield_wait();
}
match data_cell.get() {
None => Err(ErrorCode::Fail),
Some(tvoc_value) => Ok(tvoc_value),
}
}
}
})
}
}
pub struct AirQualityListener<F: Fn(u32)>(pub F);
impl<F: Fn(u32)> Upcall<OneId<DRIVER_NUM, 0>> for AirQualityListener<F> {
fn upcall(&self, data_val: u32, _arg1: u32, _arg2: u32) {
self.0(data_val)
}
}
#[cfg(test)]
mod tests;
// -----------------------------------------------------------------------------
// Driver number and command IDs
// -----------------------------------------------------------------------------
const DRIVER_NUM: u32 = 0x60007;
// Command IDs
const EXISTS: u32 = 0;
const READ_CO2: u32 = 2;
const READ_TVOC: u32 = 3;
================================================
FILE: apis/sensors/air_quality/src/tests.rs
================================================
use crate::AirQualityListener;
use core::cell::Cell;
use libtock_platform::{share::scope, ErrorCode, Syscalls, YieldNoWaitReturn};
use libtock_unittest::fake;
type AirQuality = super::AirQuality<fake::Syscalls>;
#[test]
fn no_driver() {
let _kernel = fake::Kernel::new();
assert_eq!(AirQuality::exists(), Err(ErrorCode::NoDevice));
}
#[test]
fn exists() {
let kernel = fake::Kernel::new();
let driver = fake::AirQuality::new();
kernel.add_driver(&driver);
assert_eq!(AirQuality::exists(), Ok(()));
}
#
gitextract_5tcgoj5o/
├── .cargo/
│ └── config.toml
├── .github/
│ └── workflows/
│ ├── artifacts.yml
│ ├── ci.yml
│ ├── mac-os.yml
│ └── size-diff.yml
├── .gitignore
├── .gitmodules
├── .ignore
├── .vscode/
│ └── settings.json
├── CHANGELOG.md
├── CONTRIBUTING.md
├── Cargo.toml
├── LICENSE-APACHE
├── LICENSE-MIT
├── Makefile
├── README.md
├── Targets.mk
├── apis/
│ ├── display/
│ │ └── screen/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ ├── lib.rs
│ │ └── tests.rs
│ ├── interface/
│ │ ├── buttons/
│ │ │ ├── Cargo.toml
│ │ │ └── src/
│ │ │ ├── lib.rs
│ │ │ └── tests.rs
│ │ ├── buzzer/
│ │ │ ├── Cargo.toml
│ │ │ └── src/
│ │ │ ├── lib.rs
│ │ │ └── tests.rs
│ │ ├── console/
│ │ │ ├── Cargo.toml
│ │ │ └── src/
│ │ │ ├── lib.rs
│ │ │ └── tests.rs
│ │ └── leds/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ ├── lib.rs
│ │ └── tests.rs
│ ├── kernel/
│ │ └── low_level_debug/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ ├── lib.rs
│ │ └── tests.rs
│ ├── net/
│ │ └── ieee802154/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ ├── lib.rs
│ │ ├── rx.rs
│ │ └── tests.rs
│ ├── peripherals/
│ │ ├── adc/
│ │ │ ├── Cargo.toml
│ │ │ └── src/
│ │ │ ├── lib.rs
│ │ │ └── tests.rs
│ │ ├── alarm/
│ │ │ ├── Cargo.toml
│ │ │ └── src/
│ │ │ ├── lib.rs
│ │ │ └── tests.rs
│ │ ├── gpio/
│ │ │ ├── Cargo.toml
│ │ │ └── src/
│ │ │ ├── lib.rs
│ │ │ └── tests.rs
│ │ ├── i2c_master/
│ │ │ ├── Cargo.toml
│ │ │ └── src/
│ │ │ └── lib.rs
│ │ ├── i2c_master_slave/
│ │ │ ├── Cargo.toml
│ │ │ └── src/
│ │ │ └── lib.rs
│ │ ├── rng/
│ │ │ ├── Cargo.toml
│ │ │ └── src/
│ │ │ └── lib.rs
│ │ └── spi_controller/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ └── lib.rs
│ ├── sensors/
│ │ ├── air_quality/
│ │ │ ├── Cargo.toml
│ │ │ └── src/
│ │ │ ├── lib.rs
│ │ │ └── tests.rs
│ │ ├── ambient_light/
│ │ │ ├── Cargo.toml
│ │ │ └── src/
│ │ │ ├── lib.rs
│ │ │ └── tests.rs
│ │ ├── ninedof/
│ │ │ ├── Cargo.toml
│ │ │ └── src/
│ │ │ ├── lib.rs
│ │ │ └── tests.rs
│ │ ├── proximity/
│ │ │ ├── Cargo.toml
│ │ │ └── src/
│ │ │ ├── lib.rs
│ │ │ └── tests.rs
│ │ ├── sound_pressure/
│ │ │ ├── Cargo.toml
│ │ │ └── src/
│ │ │ ├── lib.rs
│ │ │ └── tests.rs
│ │ └── temperature/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ ├── lib.rs
│ │ └── tests.rs
│ └── storage/
│ └── key_value/
│ ├── Cargo.toml
│ └── src/
│ ├── lib.rs
│ └── tests.rs
├── build.rs
├── build_scripts/
│ ├── Cargo.toml
│ ├── README.md
│ ├── libtock_layout.ld
│ └── src/
│ └── lib.rs
├── demos/
│ ├── embedded_graphics/
│ │ ├── buttons/
│ │ │ ├── Cargo.toml
│ │ │ ├── Makefile
│ │ │ ├── README.md
│ │ │ ├── build.rs
│ │ │ └── src/
│ │ │ └── main.rs
│ │ └── spin/
│ │ ├── Cargo.toml
│ │ ├── Makefile
│ │ ├── README.md
│ │ ├── build.rs
│ │ └── src/
│ │ └── main.rs
│ ├── st7789/
│ │ ├── Cargo.toml
│ │ ├── Makefile
│ │ ├── build.rs
│ │ └── src/
│ │ └── main.rs
│ └── st7789-slint/
│ ├── Cargo.toml
│ ├── Makefile
│ ├── build.rs
│ ├── src/
│ │ └── main.rs
│ └── ui/
│ └── appwindow.slint
├── doc/
│ ├── CargoFeatures.md
│ ├── CodeReview.md
│ ├── Dependencies.md
│ ├── DesignConsiderations.md
│ ├── FaultDebuggingExample.md
│ ├── MiriTips.md
│ ├── Overview.md
│ ├── PlatformDesignStory.md
│ ├── Startup.md
│ ├── Style.md
│ ├── Testing.md
│ └── UnitTestOwnership.md
├── examples/
│ ├── adc.rs
│ ├── ambient_light.rs
│ ├── blink.rs
│ ├── buttons.rs
│ ├── console.rs
│ ├── gpio.rs
│ ├── i2c_master_write_read.rs
│ ├── i2c_slave_send_recv.rs
│ ├── ieee802154_raw.rs
│ ├── ieee802154_rx_raw.rs
│ ├── ieee802154_rx_tx_raw.rs
│ ├── ieee802154_tx_raw.rs
│ ├── kv.rs
│ ├── leds.rs
│ ├── low_level_debug.rs
│ ├── music.rs
│ ├── ninedof.rs
│ ├── proximity.rs
│ ├── rng.rs
│ ├── rng_async.rs
│ ├── screen.rs
│ ├── sound_pressure.rs
│ ├── spi_controller_write_read.rs
│ ├── temperature.rs
│ └── usb_i2c_mctp.rs
├── libraries/
│ └── embedded_graphics_libtock/
│ ├── Cargo.toml
│ ├── README.md
│ └── src/
│ ├── lib.rs
│ └── tock_screen.rs
├── nightly/
│ └── rust-toolchain.toml
├── panic_handlers/
│ ├── debug_panic/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ └── lib.rs
│ └── small_panic/
│ ├── Cargo.toml
│ └── src/
│ └── lib.rs
├── platform/
│ ├── Cargo.toml
│ └── src/
│ ├── allow_ro.rs
│ ├── allow_rw.rs
│ ├── command_return.rs
│ ├── command_return_tests.rs
│ ├── constants.rs
│ ├── default_config.rs
│ ├── error_code.rs
│ ├── error_code_tests.rs
│ ├── exit_on_drop.rs
│ ├── lib.rs
│ ├── raw_syscalls.rs
│ ├── register.rs
│ ├── return_variant.rs
│ ├── share/
│ │ ├── handle.rs
│ │ ├── mod.rs
│ │ ├── tests.rs
│ │ └── tuple_impls.rs
│ ├── subscribe.rs
│ ├── syscalls.rs
│ ├── syscalls_impl.rs
│ ├── termination.rs
│ └── yield_types.rs
├── runner/
│ ├── Cargo.toml
│ └── src/
│ ├── elf2tab.rs
│ ├── main.rs
│ ├── output_processor.rs
│ ├── qemu.rs
│ └── tockloader.rs
├── runtime/
│ ├── Cargo.toml
│ └── src/
│ ├── lib.rs
│ ├── startup/
│ │ ├── asm_arm.s
│ │ ├── asm_riscv32.s
│ │ ├── asm_x86.s
│ │ ├── mod.rs
│ │ └── start_prototype.rs
│ ├── syscalls_impl_arm.rs
│ ├── syscalls_impl_riscv.rs
│ └── syscalls_impl_x86.rs
├── rust-toolchain.toml
├── rustfmt.toml
├── src/
│ ├── lib.rs
│ └── spi_controller.rs
├── syscalls_tests/
│ ├── Cargo.toml
│ └── src/
│ ├── allow_ro.rs
│ ├── allow_rw.rs
│ ├── command_tests.rs
│ ├── exit_on_drop.rs
│ ├── lib.rs
│ ├── memop_tests.rs
│ ├── subscribe_tests.rs
│ └── yield_tests.rs
├── tools/
│ └── print_sizes/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── ufmt/
│ ├── Cargo.toml
│ ├── LICENSE-APACHE
│ ├── LICENSE-MIT
│ ├── README.md
│ ├── macros/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ └── lib.rs
│ ├── src/
│ │ ├── helpers.rs
│ │ ├── impls/
│ │ │ ├── array.rs
│ │ │ ├── core.rs
│ │ │ ├── ixx.rs
│ │ │ ├── nz.rs
│ │ │ ├── ptr.rs
│ │ │ ├── std.rs
│ │ │ ├── tuple.rs
│ │ │ └── uxx.rs
│ │ ├── impls.rs
│ │ ├── lib.rs
│ │ └── macros.rs
│ ├── tests/
│ │ └── vs-std-write.rs
│ ├── utils/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ └── lib.rs
│ └── write/
│ ├── Cargo.toml
│ └── src/
│ └── lib.rs
└── unittest/
├── Cargo.toml
└── src/
├── allow_db.rs
├── allow_db_test.rs
├── command_return.rs
├── driver_info.rs
├── exit_test/
│ ├── mod.rs
│ └── tests.rs
├── expected_syscall.rs
├── fake/
│ ├── adc/
│ │ ├── mod.rs
│ │ └── tests.rs
│ ├── air_quality/
│ │ ├── mod.rs
│ │ └── tests.rs
│ ├── alarm/
│ │ ├── mod.rs
│ │ └── tests.rs
│ ├── ambient_light/
│ │ ├── mod.rs
│ │ └── tests.rs
│ ├── buttons/
│ │ ├── mod.rs
│ │ └── tests.rs
│ ├── buzzer/
│ │ ├── mod.rs
│ │ └── tests.rs
│ ├── console/
│ │ ├── mod.rs
│ │ └── tests.rs
│ ├── gpio/
│ │ ├── mod.rs
│ │ └── tests.rs
│ ├── ieee802154/
│ │ └── mod.rs
│ ├── kernel.rs
│ ├── kernel_tests.rs
│ ├── key_value/
│ │ └── mod.rs
│ ├── leds/
│ │ ├── mod.rs
│ │ └── tests.rs
│ ├── low_level_debug/
│ │ ├── mod.rs
│ │ └── tests.rs
│ ├── mod.rs
│ ├── ninedof/
│ │ ├── mod.rs
│ │ └── tests.rs
│ ├── proximity/
│ │ ├── mod.rs
│ │ └── tests.rs
│ ├── screen/
│ │ ├── mod.rs
│ │ └── tests.rs
│ ├── sound_pressure/
│ │ ├── mod.rs
│ │ └── tests.rs
│ ├── syscall_driver.rs
│ ├── syscalls/
│ │ ├── allow_ro_impl.rs
│ │ ├── allow_ro_impl_tests.rs
│ │ ├── allow_rw_impl.rs
│ │ ├── allow_rw_impl_tests.rs
│ │ ├── command_impl.rs
│ │ ├── command_impl_tests.rs
│ │ ├── exit_impl.rs
│ │ ├── exit_impl_tests.rs
│ │ ├── memop_impl.rs
│ │ ├── memop_impl_tests.rs
│ │ ├── mod.rs
│ │ ├── raw_syscalls_impl.rs
│ │ ├── raw_syscalls_impl_tests.rs
│ │ ├── subscribe_impl.rs
│ │ ├── subscribe_impl_tests.rs
│ │ ├── yield_impl.rs
│ │ └── yield_impl_tests.rs
│ └── temperature/
│ ├── mod.rs
│ └── tests.rs
├── kernel_data.rs
├── lib.rs
├── share_data.rs
├── syscall_log.rs
└── upcall.rs
SYMBOL INDEX (1648 symbols across 194 files)
FILE: apis/display/screen/src/lib.rs
type Screen (line 9) | pub struct Screen<S: Syscalls, C: Config = DefaultConfig>(S, C);
function exists (line 13) | pub fn exists() -> Result<(), ErrorCode> {
function screen_setup (line 23) | pub fn screen_setup() -> Result<u32, ErrorCode> {
function set_power (line 28) | pub fn set_power(value: usize) -> Result<(), ErrorCode> {
function set_brightness (line 37) | pub fn set_brightness(value: usize) -> Result<(), ErrorCode> {
function set_invert_on (line 53) | pub fn set_invert_on() -> Result<(), ErrorCode> {
function set_invert_off (line 68) | pub fn set_invert_off() -> Result<(), ErrorCode> {
function set_invert (line 83) | pub fn set_invert(value: usize) -> Result<(), ErrorCode> {
function get_resolution_modes_count (line 92) | pub fn get_resolution_modes_count() -> Result<u32, ErrorCode> {
function get_resolution_width_height (line 97) | pub fn get_resolution_width_height(index: usize) -> Result<(u32, u32), E...
function pixel_modes_count (line 108) | pub fn pixel_modes_count() -> Result<u32, ErrorCode> {
function pixel_format (line 113) | pub fn pixel_format(index: usize) -> Result<u32, ErrorCode> {
function get_rotation (line 118) | pub fn get_rotation() -> Result<u32, ErrorCode> {
function set_rotation (line 134) | pub fn set_rotation(rotation: usize) -> Result<(), ErrorCode> {
function get_resolution (line 150) | pub fn get_resolution() -> Result<(u32, u32), ErrorCode> {
function set_resolution (line 155) | pub fn set_resolution(width: usize, height: usize) -> Result<(), ErrorCo...
function get_pixel_format (line 176) | pub fn get_pixel_format() -> Result<u32, ErrorCode> {
function set_pixel_format (line 181) | pub fn set_pixel_format(format: usize) -> Result<(), ErrorCode> {
function set_write_frame (line 197) | pub fn set_write_frame(x: u32, y: u32, width: u32, height: u32) -> Resul...
function write (line 214) | pub fn write(s: &[u8]) -> Result<(), ErrorCode> {
function fill (line 238) | pub fn fill(s: &mut [u8], color: u16) -> Result<(), ErrorCode> {
type Config (line 269) | pub trait Config:
constant DRIVER_NUM (line 286) | const DRIVER_NUM: u32 = 0x90001;
constant EXISTS (line 291) | pub const EXISTS: u32 = 0;
constant SCREEN_SETUP (line 292) | pub const SCREEN_SETUP: u32 = 1;
constant SET_POWER (line 293) | pub const SET_POWER: u32 = 2;
constant SET_BRIGHTNESS (line 294) | pub const SET_BRIGHTNESS: u32 = 3;
constant SET_INVERT_ON (line 295) | pub const SET_INVERT_ON: u32 = 4;
constant SET_INVERT_OFF (line 296) | pub const SET_INVERT_OFF: u32 = 5;
constant SET_INVERT (line 297) | pub const SET_INVERT: u32 = 6;
constant GET_RESOLUTION_MODES_COUNT (line 298) | pub const GET_RESOLUTION_MODES_COUNT: u32 = 11;
constant GET_RESOLUTION_WIDTH_HEIGHT (line 299) | pub const GET_RESOLUTION_WIDTH_HEIGHT: u32 = 12;
constant PIXEL_MODES_COUNT (line 300) | pub const PIXEL_MODES_COUNT: u32 = 13;
constant PIXEL_FORMAT (line 301) | pub const PIXEL_FORMAT: u32 = 14;
constant GET_ROTATION (line 302) | pub const GET_ROTATION: u32 = 21;
constant SET_ROTATION (line 303) | pub const SET_ROTATION: u32 = 22;
constant GET_RESOLUTION (line 304) | pub const GET_RESOLUTION: u32 = 23;
constant SET_RESOLUTION (line 305) | pub const SET_RESOLUTION: u32 = 24;
constant GET_PIXEL_FORMAT (line 306) | pub const GET_PIXEL_FORMAT: u32 = 25;
constant SET_PIXEL_FORMAT (line 307) | pub const SET_PIXEL_FORMAT: u32 = 26;
constant SET_WRITE_FRAME (line 308) | pub const SET_WRITE_FRAME: u32 = 100;
constant WRITE (line 309) | pub const WRITE: u32 = 200;
constant FILL (line 310) | pub const FILL: u32 = 300;
constant WRITE (line 315) | pub const WRITE: u32 = 0;
constant WRITE_BUFFER_ID (line 320) | pub const WRITE_BUFFER_ID: u32 = 0;
FILE: apis/display/screen/src/tests.rs
type Screen (line 4) | type Screen = super::Screen<fake::Syscalls>;
function no_driver (line 8) | fn no_driver() {
function exists (line 14) | fn exists() {
function screen_setup (line 23) | fn screen_setup() {
function set_power (line 32) | fn set_power() {
function set_brightness (line 41) | fn set_brightness() {
function set_invert_on (line 55) | fn set_invert_on() {
function set_invert_off (line 69) | fn set_invert_off() {
function set_invert (line 83) | fn set_invert() {
function get_resolution_modes_count (line 92) | fn get_resolution_modes_count() {
function get_resolution_width_height (line 101) | fn get_resolution_width_height() {
function get_resolution_width_height_fail (line 111) | fn get_resolution_width_height_fail() {
function pixel_modes_count (line 122) | fn pixel_modes_count() {
function get_screen_pixel_format_success (line 131) | fn get_screen_pixel_format_success() {
function get_screen_pixel_format_fail (line 141) | fn get_screen_pixel_format_fail() {
function set_rotation_success (line 150) | fn set_rotation_success() {
function set_rotation_fail (line 164) | fn set_rotation_fail() {
function get_rotation_success (line 173) | fn get_rotation_success() {
function get_rotation_fail (line 193) | fn get_rotation_fail() {
function set_resolution (line 207) | fn set_resolution() {
function get_resolution_sucess (line 221) | fn get_resolution_sucess() {
function get_resolution_fail (line 236) | fn get_resolution_fail() {
function set_pixel_format (line 245) | fn set_pixel_format() {
function get_pixel_format_success (line 259) | fn get_pixel_format_success() {
function get_pixel_format_fail (line 274) | fn get_pixel_format_fail() {
function set_write_frame (line 283) | fn set_write_frame() {
function write_buffer (line 292) | fn write_buffer() {
function fill_success (line 315) | fn fill_success() {
function fill_fail (line 339) | fn fill_fail() {
FILE: apis/interface/buttons/src/lib.rs
type Buttons (line 28) | pub struct Buttons<S: Syscalls>(S);
type ButtonState (line 31) | pub enum ButtonState {
method from (line 37) | fn from(value: u32) -> ButtonState {
function count (line 50) | pub fn count() -> Result<u32, ErrorCode> {
function read (line 55) | pub fn read(button: u32) -> Result<ButtonState, ErrorCode> {
function is_pressed (line 66) | pub fn is_pressed(button: u32) -> bool {
function is_released (line 78) | pub fn is_released(button: u32) -> bool {
function enable_interrupts (line 85) | pub fn enable_interrupts(button: u32) -> Result<(), ErrorCode> {
function disable_interrupts (line 90) | pub fn disable_interrupts(button: u32) -> Result<(), ErrorCode> {
function register_listener (line 99) | pub fn register_listener<'share, F: Fn(u32, ButtonState)>(
function unregister_listener (line 110) | pub fn unregister_listener() {
type ButtonListener (line 123) | pub struct ButtonListener<F: Fn(u32, ButtonState)>(pub F);
function upcall (line 126) | fn upcall(&self, button_index: u32, state: u32, _arg2: u32) {
constant DRIVER_NUM (line 137) | const DRIVER_NUM: u32 = 0x3;
constant BUTTONS_COUNT (line 140) | const BUTTONS_COUNT: u32 = 0;
constant BUTTONS_ENABLE_INTERRUPTS (line 142) | const BUTTONS_ENABLE_INTERRUPTS: u32 = 1;
constant BUTTONS_DISABLE_INTERRUPTS (line 143) | const BUTTONS_DISABLE_INTERRUPTS: u32 = 2;
constant BUTTONS_READ (line 145) | const BUTTONS_READ: u32 = 3;
FILE: apis/interface/buttons/src/tests.rs
type Buttons (line 8) | type Buttons = super::Buttons<fake::Syscalls>;
function no_driver (line 11) | fn no_driver() {
function num_buttons (line 17) | fn num_buttons() {
function read (line 25) | fn read() {
function interrupts (line 40) | fn interrupts() {
function subscribe (line 56) | fn subscribe() {
FILE: apis/interface/buzzer/src/lib.rs
type Buzzer (line 11) | pub struct Buzzer<S: Syscalls>(S);
function exists (line 16) | pub fn exists() -> Result<(), ErrorCode> {
function tone (line 21) | pub fn tone(freq: u32, duration: Duration) -> Result<(), ErrorCode> {
function register_listener (line 26) | pub fn register_listener<'share, F: Fn(u32)>(
function unregister_listener (line 34) | pub fn unregister_listener() {
function tone_sync (line 40) | pub fn tone_sync(freq: u32, duration: Duration) -> Result<(), ErrorCode> {
type BuzzerListener (line 59) | pub struct BuzzerListener<F: Fn(u32)>(pub F);
function upcall (line 61) | fn upcall(&self, _arg0: u32, _arg1: u32, _arg2: u32) {
constant DRIVER_NUM (line 73) | const DRIVER_NUM: u32 = 0x90000;
constant EXISTS (line 76) | const EXISTS: u32 = 0;
constant BUZZER_ON (line 77) | const BUZZER_ON: u32 = 1;
type Note (line 83) | pub enum Note {
FILE: apis/interface/buzzer/src/tests.rs
type Buzzer (line 5) | type Buzzer = super::Buzzer<fake::Syscalls>;
function no_driver (line 8) | fn no_driver() {
function exists (line 14) | fn exists() {
function tone (line 23) | fn tone() {
function tone_sync (line 35) | fn tone_sync() {
FILE: apis/interface/console/src/lib.rs
type Console (line 25) | pub struct Console<S: Syscalls, C: Config = DefaultConfig>(S, C);
function exists (line 34) | pub fn exists() -> bool {
function write (line 41) | pub fn write(s: &[u8]) -> Result<(), ErrorCode> {
function read (line 73) | pub fn read(buf: &mut [u8]) -> (usize, Result<(), ErrorCode>) {
function writer (line 107) | pub fn writer() -> ConsoleWriter<S> {
type ConsoleWriter (line 114) | pub struct ConsoleWriter<S: Syscalls> {
function write_str (line 119) | fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> {
type Config (line 125) | pub trait Config:
constant DRIVER_NUM (line 141) | const DRIVER_NUM: u32 = 0x1;
constant EXISTS (line 146) | pub const EXISTS: u32 = 0;
constant WRITE (line 147) | pub const WRITE: u32 = 1;
constant READ (line 148) | pub const READ: u32 = 2;
constant ABORT (line 149) | pub const ABORT: u32 = 3;
constant WRITE (line 154) | pub const WRITE: u32 = 1;
constant READ (line 155) | pub const READ: u32 = 2;
constant WRITE (line 159) | pub const WRITE: u32 = 1;
constant READ (line 163) | pub const READ: u32 = 1;
FILE: apis/interface/console/src/tests.rs
type Console (line 6) | type Console = super::Console<fake::Syscalls>;
function no_driver (line 9) | fn no_driver() {
function exists (line 15) | fn exists() {
function write_bytes (line 25) | fn write_bytes() {
function write_str (line 36) | fn write_str() {
function read_bytes_short (line 46) | fn read_bytes_short() {
function read_bytes_alot (line 59) | fn read_bytes_alot() {
function failed_print (line 76) | fn failed_print() {
function failed_read (line 104) | fn failed_read() {
FILE: apis/interface/leds/src/lib.rs
type Leds (line 14) | pub struct Leds<S: Syscalls>(S);
function count (line 22) | pub fn count() -> Result<u32, ErrorCode> {
function on (line 26) | pub fn on(led: u32) -> Result<(), ErrorCode> {
function off (line 30) | pub fn off(led: u32) -> Result<(), ErrorCode> {
function toggle (line 34) | pub fn toggle(led: u32) -> Result<(), ErrorCode> {
constant DRIVER_NUM (line 46) | const DRIVER_NUM: u32 = 0x2;
constant LEDS_COUNT (line 49) | const LEDS_COUNT: u32 = 0;
constant LED_ON (line 50) | const LED_ON: u32 = 1;
constant LED_OFF (line 51) | const LED_OFF: u32 = 2;
constant LED_TOGGLE (line 52) | const LED_TOGGLE: u32 = 3;
FILE: apis/interface/leds/src/tests.rs
type Leds (line 4) | type Leds = super::Leds<fake::Syscalls>;
function no_driver (line 7) | fn no_driver() {
function exists (line 13) | fn exists() {
function num_leds (line 25) | fn num_leds() {
function on (line 33) | fn on() {
function off (line 43) | fn off() {
function toggle (line 53) | fn toggle() {
function on_off (line 65) | fn on_off() {
function no_led (line 77) | fn no_led() {
FILE: apis/kernel/low_level_debug/src/lib.rs
type LowLevelDebug (line 18) | pub struct LowLevelDebug<S: Syscalls>(S);
function exists (line 27) | pub fn exists() -> bool {
function print_alert_code (line 33) | pub fn print_alert_code(code: AlertCode) {
function print_1 (line 42) | pub fn print_1(x: u32) {
function print_2 (line 53) | pub fn print_2(x: u32, y: u32) {
type AlertCode (line 59) | pub enum AlertCode {
constant DRIVER_NUM (line 75) | const DRIVER_NUM: u32 = 0x8;
constant EXISTS (line 78) | const EXISTS: u32 = 0;
constant PRINT_ALERT_CODE (line 79) | const PRINT_ALERT_CODE: u32 = 1;
constant PRINT_1 (line 80) | const PRINT_1: u32 = 2;
constant PRINT_2 (line 81) | const PRINT_2: u32 = 3;
FILE: apis/kernel/low_level_debug/src/tests.rs
type LowLevelDebug (line 5) | type LowLevelDebug = super::LowLevelDebug<fake::Syscalls>;
function no_driver (line 8) | fn no_driver() {
function exists (line 14) | fn exists() {
function print_alert_code (line 24) | fn print_alert_code() {
function print_1 (line 41) | fn print_1() {
function print_2 (line 51) | fn print_2() {
function failed_print (line 65) | fn failed_print() {
FILE: apis/net/ieee802154/src/lib.rs
type Ieee802154 (line 52) | pub struct Ieee802154<S: Syscalls, C: Config = DefaultConfig>(S, C);
function exists (line 62) | pub fn exists() -> bool {
function is_on (line 70) | pub fn is_on() -> bool {
function radio_on (line 75) | pub fn radio_on() -> Result<(), ErrorCode> {
function radio_off (line 80) | pub fn radio_off() -> Result<(), ErrorCode> {
function set_address_short (line 88) | pub fn set_address_short(short_addr: u16) {
function set_address_long (line 100) | pub fn set_address_long(long_addr: u64) {
function set_pan (line 108) | pub fn set_pan(pan: u16) {
function set_channel (line 119) | pub fn set_channel(chan: u8) -> Result<(), ErrorCode> {
function set_tx_power (line 124) | pub fn set_tx_power(power: i8) -> Result<(), ErrorCode> {
function commit_config (line 129) | pub fn commit_config() {
function get_address_short (line 135) | pub fn get_address_short() -> Result<u16, ErrorCode> {
function get_address_long (line 143) | pub fn get_address_long() -> Result<u64, ErrorCode> {
function get_pan (line 148) | pub fn get_pan() -> Result<u16, ErrorCode> {
function get_channel (line 156) | pub fn get_channel() -> Result<u8, ErrorCode> {
function get_tx_power (line 163) | pub fn get_tx_power() -> Result<i8, ErrorCode> {
function transmit_frame_raw (line 173) | pub fn transmit_frame_raw(frame: &[u8]) -> Result<(), ErrorCode> {
type Config (line 207) | pub trait Config:
constant DRIVER_NUM (line 223) | const DRIVER_NUM: u32 = 0x30001;
constant EXISTS (line 246) | pub const EXISTS: u32 = 0;
constant STATUS (line 247) | pub const STATUS: u32 = 1;
constant SET_SHORT_ADDR (line 248) | pub const SET_SHORT_ADDR: u32 = 2;
constant SET_PAN (line 249) | pub const SET_PAN: u32 = 4;
constant SET_CHAN (line 250) | pub const SET_CHAN: u32 = 5;
constant SET_TX_PWR (line 251) | pub const SET_TX_PWR: u32 = 6;
constant COMMIT_CFG (line 252) | pub const COMMIT_CFG: u32 = 7;
constant GET_SHORT_ADDR (line 253) | pub const GET_SHORT_ADDR: u32 = 8;
constant GET_PAN (line 254) | pub const GET_PAN: u32 = 10;
constant GET_CHAN (line 255) | pub const GET_CHAN: u32 = 11;
constant GET_TX_PWR (line 256) | pub const GET_TX_PWR: u32 = 12;
constant TRANSMIT_RAW (line 257) | pub const TRANSMIT_RAW: u32 = 27;
constant SET_LONG_ADDR (line 258) | pub const SET_LONG_ADDR: u32 = 28;
constant GET_LONG_ADDR (line 259) | pub const GET_LONG_ADDR: u32 = 29;
constant TURN_ON (line 260) | pub const TURN_ON: u32 = 30;
constant TURN_OFF (line 261) | pub const TURN_OFF: u32 = 31;
constant FRAME_RECEIVED (line 266) | pub const FRAME_RECEIVED: u32 = 0;
constant FRAME_TRANSMITTED (line 268) | pub const FRAME_TRANSMITTED: u32 = 1;
constant WRITE (line 274) | pub const WRITE: u32 = 0;
constant READ (line 280) | pub const READ: u32 = 0;
FILE: apis/net/ieee802154/src/rx.rs
constant MAX_MTU (line 6) | const MAX_MTU: usize = 127;
type Frame (line 10) | pub struct Frame {
constant EMPTY_FRAME (line 17) | const EMPTY_FRAME: Frame = Frame {
type RxRingBuffer (line 44) | pub struct RxRingBuffer<const N: usize> {
method default (line 56) | fn default() -> Self {
function new (line 63) | pub const fn new() -> Self {
function as_mut_byte_slice (line 71) | fn as_mut_byte_slice(&mut self) -> &mut [u8] {
function has_frame (line 83) | fn has_frame(&self) -> bool {
function next_frame (line 87) | fn next_frame(&mut self) -> &mut Frame {
type RxOperator (line 94) | pub trait RxOperator {
method receive_frame (line 99) | fn receive_frame(&mut self) -> Result<&mut Frame, ErrorCode>;
method receive_frame (line 126) | fn receive_frame(&mut self) -> Result<&mut Frame, ErrorCode> {
type RxSingleBufferOperator (line 109) | pub struct RxSingleBufferOperator<'buf, const N: usize, S: Syscalls, C: ...
function new (line 117) | pub fn new(buf: &'buf mut RxRingBuffer<N>) -> Self {
function receive_frame_single_buf (line 143) | fn receive_frame_single_buf<const N: usize>(
FILE: apis/net/ieee802154/src/tests.rs
type FakeSyscalls (line 12) | struct FakeSyscalls;
method yield1 (line 15) | unsafe fn yield1([r0]: [Register; 1]) {
method yield2 (line 19) | unsafe fn yield2([r0, r1]: [Register; 2]) {
method syscall1 (line 23) | unsafe fn syscall1<const CLASS: usize>([r0]: [Register; 1]) -> [Register...
method syscall2 (line 27) | unsafe fn syscall2<const CLASS: usize>([r0, r1]: [Register; 2]) -> [Regi...
method syscall4 (line 31) | unsafe fn syscall4<const CLASS: usize>([r0, r1, r2, r3]: [Register; 4]) ...
type Ieee802154 (line 62) | type Ieee802154 = super::Ieee802154<FakeSyscalls>;
type RxSingleBufferOperator (line 63) | type RxSingleBufferOperator<'buf, const N: usize> =
function no_driver (line 67) | fn no_driver() {
function exists (line 73) | fn exists() {
function configure (line 82) | fn configure() {
function transmit_frame (line 109) | fn transmit_frame() {
function test_with_driver (line 124) | fn test_with_driver(test: impl FnOnce(&Ieee802154Phy)) {
function test_with_single_buf_operator (line 132) | fn test_with_single_buf_operator<const SUPPORTED_FRAMES: usize>(
function no_frame_comes (line 142) | fn no_frame_comes(_driver: &Ieee802154Phy, operator: &mut dyn RxOperator) {
function no_frame_comes_single_buf (line 151) | fn no_frame_comes_single_buf() {
function receive_frame (line 160) | fn receive_frame() {
function only_one_frame_comes (line 180) | fn only_one_frame_comes(driver: &Ieee802154Phy, operator: &mut dyn RxOpe...
function receive_frame_only_one_single_buf (line 196) | fn receive_frame_only_one_single_buf() {
function receive_many_frames (line 205) | fn receive_many_frames() {
function receive_various_frames (line 238) | fn receive_various_frames() {
FILE: apis/peripherals/adc/src/lib.rs
type Adc (line 8) | pub struct Adc<S: Syscalls>(S);
function exists (line 13) | pub fn exists() -> Result<(), ErrorCode> {
function read_single_sample (line 27) | pub fn read_single_sample() -> Result<(), ErrorCode> {
function register_listener (line 32) | pub fn register_listener<'share, F: Fn(u16)>(
function unregister_listener (line 40) | pub fn unregister_listener() {
function read_single_sample_sync (line 46) | pub fn read_single_sample_sync() -> Result<u16, ErrorCode> {
function get_resolution_bits (line 66) | pub fn get_resolution_bits() -> Result<u32, ErrorCode> {
function get_reference_voltage_mv (line 71) | pub fn get_reference_voltage_mv() -> Result<u32, ErrorCode> {
type ADCListener (line 76) | pub struct ADCListener<F: Fn(u16)>(pub F);
function upcall (line 79) | fn upcall(&self, adc_val: u32, _arg1: u32, _arg2: u32) {
constant DRIVER_NUM (line 91) | const DRIVER_NUM: u32 = 0x5;
constant EXISTS (line 95) | const EXISTS: u32 = 0;
constant SINGLE_SAMPLE (line 96) | const SINGLE_SAMPLE: u32 = 1;
constant GET_RES_BITS (line 101) | const GET_RES_BITS: u32 = 101;
constant GET_VOLTAGE_REF (line 102) | const GET_VOLTAGE_REF: u32 = 102;
FILE: apis/peripherals/adc/src/tests.rs
type Adc (line 5) | type Adc = super::Adc<fake::Syscalls>;
function no_driver (line 8) | fn no_driver() {
function exists (line 14) | fn exists() {
function read_single_sample (line 23) | fn read_single_sample() {
function register_unregister_listener (line 36) | fn register_unregister_listener() {
function read_single_sample_sync (line 64) | fn read_single_sample_sync() {
FILE: apis/peripherals/alarm/src/lib.rs
type Alarm (line 17) | pub struct Alarm<S: Syscalls, C: platform::subscribe::Config = DefaultCo...
type Hz (line 20) | pub struct Hz(pub u32);
type Convert (line 22) | pub trait Convert {
method to_ticks (line 24) | fn to_ticks(self, freq: Hz) -> Ticks;
method to_ticks (line 31) | fn to_ticks(self, _freq: Hz) -> Ticks {
method to_ticks (line 40) | fn to_ticks(self, freq: Hz) -> Ticks {
type Ticks (line 28) | pub struct Ticks(pub u32);
type Milliseconds (line 37) | pub struct Milliseconds(pub u32);
function exists (line 62) | pub fn exists() -> Result<(), ErrorCode> {
function get_frequency (line 66) | pub fn get_frequency() -> Result<Hz, ErrorCode> {
function get_ticks (line 72) | pub fn get_ticks() -> Result<u32, ErrorCode> {
function get_milliseconds (line 76) | pub fn get_milliseconds() -> Result<u64, ErrorCode> {
function sleep_for (line 83) | pub fn sleep_for<T: Convert>(time: T) -> Result<(), ErrorCode> {
constant DRIVER_NUM (line 112) | const DRIVER_NUM: u32 = 0x0;
constant EXISTS (line 117) | pub const EXISTS: u32 = 0;
constant FREQUENCY (line 118) | pub const FREQUENCY: u32 = 1;
constant TIME (line 119) | pub const TIME: u32 = 2;
constant STOP (line 120) | pub const STOP: u32 = 3;
constant SET_RELATIVE (line 122) | pub const SET_RELATIVE: u32 = 5;
constant SET_ABSOLUTE (line 123) | pub const SET_ABSOLUTE: u32 = 6;
constant CALLBACK (line 128) | pub const CALLBACK: u32 = 0;
FILE: apis/peripherals/alarm/src/tests.rs
type Alarm (line 5) | type Alarm = crate::Alarm<fake::Syscalls>;
function get_freq (line 8) | fn get_freq() {
function sleep (line 16) | fn sleep() {
FILE: apis/peripherals/gpio/src/lib.rs
type GpioState (line 20) | pub enum GpioState {
method from (line 115) | fn from(original: u32) -> GpioState {
type PinInterruptEdge (line 25) | pub enum PinInterruptEdge {
type Error (line 31) | pub enum Error {
type Pull (line 36) | pub trait Pull {
constant MODE (line 37) | const MODE: u32;
constant MODE (line 42) | const MODE: u32 = 1;
constant MODE (line 47) | const MODE: u32 = 2;
constant MODE (line 52) | const MODE: u32 = 0;
type PullUp (line 40) | pub struct PullUp;
type PullDown (line 45) | pub struct PullDown;
type PullNone (line 50) | pub struct PullNone;
type Gpio (line 55) | pub struct Gpio<S: Syscalls>(S);
function exists (line 61) | pub fn exists() -> Result<(), ErrorCode> {
function count (line 65) | pub fn count() -> Result<u32, ErrorCode> {
function get_pin (line 69) | pub fn get_pin(pin: u32) -> Result<Pin<S>, ErrorCode> {
function register_listener (line 82) | pub fn register_listener<'share, F: Fn(u32, GpioState)>(
function unregister_listener (line 93) | pub fn unregister_listener() {
type GpioInterruptListener (line 106) | pub struct GpioInterruptListener<F: Fn(u32, GpioState)>(pub F);
function upcall (line 109) | fn upcall(&self, gpio_index: u32, value: u32, _arg2: u32) {
type Pin (line 123) | pub struct Pin<S: Syscalls> {
function make_output (line 129) | pub fn make_output(&mut self) -> Result<OutputPin<'_, S>, ErrorCode> {
function make_input (line 134) | pub fn make_input<P: Pull>(&self) -> Result<InputPin<'_, S, P>, ErrorCod...
type OutputPin (line 143) | pub struct OutputPin<'a, S: Syscalls> {
function toggle (line 148) | pub fn toggle(&mut self) -> Result<(), ErrorCode> {
function set (line 151) | pub fn set(&mut self) -> Result<(), ErrorCode> {
function clear (line 154) | pub fn clear(&mut self) -> Result<(), ErrorCode> {
type InputPin (line 159) | pub struct InputPin<'a, S: Syscalls, P: Pull> {
function read (line 165) | pub fn read(&self) -> Result<GpioState, ErrorCode> {
function enable_interrupts (line 169) | pub fn enable_interrupts(&self, edge: PinInterruptEdge) -> Result<(), Er...
function disable_interrupts (line 173) | pub fn disable_interrupts(&self) -> Result<(), ErrorCode> {
method drop (line 179) | fn drop(&mut self) {
method drop (line 185) | fn drop(&mut self) {
function enable_gpio_output (line 195) | fn enable_gpio_output(pin: u32) -> Result<(), ErrorCode> {
function enable_gpio_input (line 199) | fn enable_gpio_input(pin: u32, mode: u32) -> Result<(), ErrorCode> {
function write (line 203) | fn write(pin: u32, state: GpioState) -> Result<(), ErrorCode> {
function read (line 211) | fn read(pin: u32) -> Result<GpioState, ErrorCode> {
function toggle (line 216) | fn toggle(pin: u32) -> Result<(), ErrorCode> {
function disable (line 220) | fn disable(pin: u32) -> Result<(), ErrorCode> {
function enable_interrupts (line 224) | fn enable_interrupts(pin: u32, edge: PinInterruptEdge) -> Result<(), Err...
function disable_interrupts (line 228) | fn disable_interrupts(pin: u32) -> Result<(), ErrorCode> {
type Error (line 235) | type Error = ErrorCode;
function set_low (line 240) | fn set_low(&mut self) -> Result<(), Self::Error> {
function set_high (line 244) | fn set_high(&mut self) -> Result<(), Self::Error> {
constant DRIVER_NUM (line 256) | const DRIVER_NUM: u32 = 0x4;
constant EXISTS (line 259) | const EXISTS: u32 = 0;
constant GPIO_ENABLE_OUTPUT (line 261) | const GPIO_ENABLE_OUTPUT: u32 = 1;
constant GPIO_SET (line 262) | const GPIO_SET: u32 = 2;
constant GPIO_CLEAR (line 263) | const GPIO_CLEAR: u32 = 3;
constant GPIO_TOGGLE (line 264) | const GPIO_TOGGLE: u32 = 4;
constant GPIO_ENABLE_INPUT (line 266) | const GPIO_ENABLE_INPUT: u32 = 5;
constant GPIO_READ_INPUT (line 267) | const GPIO_READ_INPUT: u32 = 6;
constant GPIO_ENABLE_INTERRUPTS (line 269) | const GPIO_ENABLE_INTERRUPTS: u32 = 7;
constant GPIO_DISABLE_INTERRUPTS (line 270) | const GPIO_DISABLE_INTERRUPTS: u32 = 8;
constant GPIO_DISABLE (line 272) | const GPIO_DISABLE: u32 = 9;
constant GPIO_COUNT (line 274) | const GPIO_COUNT: u32 = 10;
FILE: apis/peripherals/gpio/src/tests.rs
type Gpio (line 8) | type Gpio = super::Gpio<fake::Syscalls>;
function no_driver (line 11) | fn no_driver() {
function num_gpio (line 17) | fn num_gpio() {
function output (line 26) | fn output() {
function input (line 60) | fn input() {
function interrupts (line 108) | fn interrupts() {
function subscribe (line 272) | fn subscribe() {
FILE: apis/peripherals/i2c_master/src/lib.rs
type I2CMaster (line 10) | pub struct I2CMaster<S: Syscalls, C: Config = DefaultConfig>(S, C);
function exists (line 13) | pub fn exists() -> Result<(), ErrorCode> {
function i2c_master_write_read_sync (line 33) | pub fn i2c_master_write_read_sync(
function i2c_master_write_sync (line 95) | pub fn i2c_master_write_sync(addr: u16, buf: &mut [u8], len: u16) -> Res...
function i2c_master_read_sync (line 146) | pub fn i2c_master_read_sync(addr: u16, buf: &mut [u8], len: u16) -> Resu...
type Config (line 183) | pub trait Config:
constant DRIVER_NUM (line 195) | const DRIVER_NUM: u32 = 0x20003;
constant MASTER_READ (line 199) | pub const MASTER_READ: u32 = 0;
constant MASTER_WRITE (line 200) | pub const MASTER_WRITE: u32 = 0;
constant MASTER_READ_WRITE (line 201) | pub const MASTER_READ_WRITE: u32 = 0;
constant MASTER (line 207) | pub const MASTER: u32 = 1;
constant EXISTS (line 212) | pub const EXISTS: u32 = 0;
constant MASTER_WRITE (line 213) | pub const MASTER_WRITE: u32 = 1;
constant MASTER_READ (line 214) | pub const MASTER_READ: u32 = 2;
constant MASTER_WRITE_READ (line 215) | pub const MASTER_WRITE_READ: u32 = 3;
FILE: apis/peripherals/i2c_master_slave/src/lib.rs
type I2CMasterSlave (line 11) | pub struct I2CMasterSlave<S: Syscalls, C: Config = DefaultConfig>(S, C);
function exists (line 14) | pub fn exists() -> Result<(), ErrorCode> {
function i2c_master_slave_write_sync (line 31) | pub fn i2c_master_slave_write_sync(
function i2c_master_slave_read_sync (line 90) | pub fn i2c_master_slave_read_sync(
function i2c_master_slave_write_read_sync (line 167) | pub fn i2c_master_slave_write_read_sync(
function i2c_master_slave_set_slave_address (line 251) | pub fn i2c_master_slave_set_slave_address(addr: u8) -> Result<(), ErrorC...
function i2c_master_slave_write_recv_sync (line 283) | pub fn i2c_master_slave_write_recv_sync(buf: &mut [u8]) -> (usize, Resul...
function i2c_master_slave_read_send_sync (line 335) | pub fn i2c_master_slave_read_send_sync(
type Config (line 385) | pub trait Config:
constant DRIVER_NUM (line 397) | const DRIVER_NUM: u32 = 0x20006;
constant MASTER_WRITE (line 403) | pub const MASTER_WRITE: u32 = 0;
constant MASTER_WRITE_READ (line 404) | pub const MASTER_WRITE_READ: u32 = 0;
constant MASTER_READ (line 405) | pub const MASTER_READ: u32 = 0;
constant SLAVE_READ (line 406) | pub const SLAVE_READ: u32 = 0;
constant SLAVE_WRITE_RECV (line 407) | pub const SLAVE_WRITE_RECV: u32 = 0;
constant SLAVE_READ_SEND (line 408) | pub const SLAVE_READ_SEND: u32 = 0;
constant MASTER_TX (line 414) | pub const MASTER_TX: u32 = 0;
constant SLAVE_TX (line 415) | pub const SLAVE_TX: u32 = 2;
constant COUNT (line 417) | pub const COUNT: u8 = 3;
constant MASTER_RX (line 423) | pub const MASTER_RX: u32 = 1;
constant SLAVE_RX (line 424) | pub const SLAVE_RX: u32 = 3;
constant MASTER_WRITE (line 429) | pub const MASTER_WRITE: u32 = 0;
constant MASTER_READ (line 430) | pub const MASTER_READ: u32 = 1;
constant SLAVE_READ (line 431) | pub const SLAVE_READ: u32 = 2;
constant SLAVE_WRITE (line 432) | pub const SLAVE_WRITE: u32 = 3;
constant EXISTS (line 437) | pub const EXISTS: u32 = 0;
constant MASTER_WRITE (line 438) | pub const MASTER_WRITE: u32 = 1;
constant MASTER_READ (line 439) | pub const MASTER_READ: u32 = 2;
constant SLAVE_START_LISTEN (line 440) | pub const SLAVE_START_LISTEN: u32 = 3;
constant SLAVE_READ_SEND (line 441) | pub const SLAVE_READ_SEND: u32 = 4;
constant SLAVE_SET_ADDR (line 442) | pub const SLAVE_SET_ADDR: u32 = 6;
constant MASTER_WRITE_READ (line 443) | pub const MASTER_WRITE_READ: u32 = 7;
FILE: apis/peripherals/rng/src/lib.rs
type Rng (line 8) | pub struct Rng<S: Syscalls>(S);
function exists (line 12) | pub fn exists() -> Result<(), ErrorCode> {
function get_bytes_async (line 18) | pub fn get_bytes_async(n: u32) -> Result<(), ErrorCode> {
function allow_buffer (line 24) | pub fn allow_buffer<'share>(
function unallow_buffer (line 31) | pub fn unallow_buffer() {
function register_listener (line 37) | pub fn register_listener<'share, F: Fn(u32)>(
function unregister_listener (line 44) | pub fn unregister_listener() {
function get_bytes_sync (line 50) | pub fn get_bytes_sync(buf: &mut [u8], n: u32) -> Result<(), ErrorCode> {
type RngListener (line 76) | pub struct RngListener<F: Fn(u32)>(pub F);
function upcall (line 79) | fn upcall(&self, _: u32, arg1: u32, _: u32) {
constant DRIVER_NUM (line 87) | const DRIVER_NUM: u32 = 0x40001;
constant EXISTS (line 92) | const EXISTS: u32 = 0;
constant GET_BYTES (line 93) | const GET_BYTES: u32 = 1;
FILE: apis/peripherals/spi_controller/src/lib.rs
type SpiController (line 11) | pub struct SpiController<S: Syscalls, C: Config = DefaultConfig>(S, C);
function exists (line 14) | pub fn exists() -> Result<(), ErrorCode> {
function spi_controller_write_read_sync (line 34) | pub fn spi_controller_write_read_sync(
function spi_controller_write_sync (line 74) | pub fn spi_controller_write_sync(w_buf: &[u8], len: u32) -> Result<(), E...
function spi_controller_read_sync (line 108) | pub fn spi_controller_read_sync(r_buf: &mut [u8], len: u32) -> Result<()...
function spi_controller_inplace_write_read_sync (line 142) | pub fn spi_controller_inplace_write_read_sync(
type Config (line 186) | pub trait Config:
constant DRIVER_NUM (line 198) | const DRIVER_NUM: u32 = 0x20001;
constant COMPLETE (line 202) | pub const COMPLETE: u32 = 0;
constant WRITE (line 207) | pub const WRITE: u32 = 0;
constant READ (line 212) | pub const READ: u32 = 0;
constant EXISTS (line 217) | pub const EXISTS: u32 = 0;
constant READ_WRITE_BYTES (line 218) | pub const READ_WRITE_BYTES: u32 = 2;
constant SET_BAUD (line 219) | pub const SET_BAUD: u32 = 5;
constant GET_BAUD (line 220) | pub const GET_BAUD: u32 = 6;
constant SET_PHASE (line 221) | pub const SET_PHASE: u32 = 7;
constant GET_PHASE (line 222) | pub const GET_PHASE: u32 = 8;
constant SET_POLARITY (line 223) | pub const SET_POLARITY: u32 = 9;
constant GET_POLARITY (line 224) | pub const GET_POLARITY: u32 = 10;
constant READ_BYTES (line 225) | pub const READ_BYTES: u32 = 11;
constant INPLACE_READ_WRITE_BYTES (line 226) | pub const INPLACE_READ_WRITE_BYTES: u32 = 12;
FILE: apis/sensors/air_quality/src/lib.rs
type Value (line 10) | enum Value {
type AirQuality (line 15) | pub struct AirQuality<S: Syscalls>(S);
function exists (line 20) | pub fn exists() -> Result<(), ErrorCode> {
function register_listener (line 25) | pub fn register_listener<'share, F: Fn(u32)>(
function unregister_listener (line 33) | pub fn unregister_listener() {
function read_co2 (line 40) | pub fn read_co2() -> Result<(), ErrorCode> {
function read_tvoc (line 47) | pub fn read_tvoc() -> Result<(), ErrorCode> {
function read_co2_sync (line 52) | pub fn read_co2_sync() -> Result<u32, ErrorCode> {
function read_tvoc_sync (line 57) | pub fn read_tvoc_sync() -> Result<u32, ErrorCode> {
function read_sync (line 62) | pub fn read_sync() -> Result<(u32, u32), ErrorCode> {
function read_data_sync (line 72) | fn read_data_sync(read_type: Value) -> Result<u32, ErrorCode> {
type AirQualityListener (line 108) | pub struct AirQualityListener<F: Fn(u32)>(pub F);
function upcall (line 110) | fn upcall(&self, data_val: u32, _arg1: u32, _arg2: u32) {
constant DRIVER_NUM (line 122) | const DRIVER_NUM: u32 = 0x60007;
constant EXISTS (line 126) | const EXISTS: u32 = 0;
constant READ_CO2 (line 127) | const READ_CO2: u32 = 2;
constant READ_TVOC (line 128) | const READ_TVOC: u32 = 3;
FILE: apis/sensors/air_quality/src/tests.rs
type AirQuality (line 6) | type AirQuality = super::AirQuality<fake::Syscalls>;
function no_driver (line 9) | fn no_driver() {
function exists (line 15) | fn exists() {
function read_co2 (line 24) | fn read_co2() {
function read_tvoc (line 37) | fn read_tvoc() {
function register_unregister_listener (line 50) | fn register_unregister_listener() {
function read_co2_sync (line 93) | fn read_co2_sync() {
function read_tvoc_sync (line 103) | fn read_tvoc_sync() {
function read_sync (line 113) | fn read_sync() {
FILE: apis/sensors/ambient_light/src/lib.rs
type AmbientLight (line 8) | pub struct AmbientLight<S: Syscalls>(S);
function exists (line 13) | pub fn exists() -> Result<(), ErrorCode> {
function read_intensity (line 18) | pub fn read_intensity() -> Result<(), ErrorCode> {
function register_listener (line 23) | pub fn register_listener<'share, F: Fn(u32)>(
function unregister_listener (line 31) | pub fn unregister_listener() {
function read_intensity_sync (line 38) | pub fn read_intensity_sync() -> Result<u32, ErrorCode> {
type IntensityListener (line 67) | pub struct IntensityListener<F: Fn(u32)>(pub F);
function upcall (line 70) | fn upcall(&self, intensity: u32, _arg1: u32, _arg2: u32) {
constant DRIVER_NUM (line 82) | const DRIVER_NUM: u32 = 0x60002;
constant EXISTS (line 86) | const EXISTS: u32 = 0;
constant READ_INTENSITY (line 87) | const READ_INTENSITY: u32 = 1;
FILE: apis/sensors/ambient_light/src/tests.rs
type AmbientLight (line 7) | type AmbientLight = super::AmbientLight<fake::Syscalls>;
function no_driver (line 10) | fn no_driver() {
function exists (line 16) | fn exists() {
function read_temperature (line 25) | fn read_temperature() {
function register_unregister_listener (line 38) | fn register_unregister_listener() {
function read_temperature_sync (line 69) | fn read_temperature_sync() {
FILE: apis/sensors/ninedof/src/lib.rs
type NineDof (line 8) | pub struct NineDof<S: Syscalls>(S);
type NineDofData (line 11) | pub struct NineDofData {
function exists (line 20) | pub fn exists() -> Result<(), ErrorCode> {
function read_accelerometer (line 26) | pub fn read_accelerometer() -> Result<(), ErrorCode> {
function read_magnetometer (line 32) | pub fn read_magnetometer() -> Result<(), ErrorCode> {
function read_gyro (line 38) | pub fn read_gyro() -> Result<(), ErrorCode> {
function unregister_listener (line 43) | pub fn unregister_listener() {
function register_listener (line 48) | pub fn register_listener<'share, F: Fn(NineDofData)>(
function read_accelerometer_sync (line 58) | pub fn read_accelerometer_sync() -> Result<NineDofData, ErrorCode> {
function read_magnetometer_sync (line 79) | pub fn read_magnetometer_sync() -> Result<NineDofData, ErrorCode> {
function read_gyroscope_sync (line 100) | pub fn read_gyroscope_sync() -> Result<NineDofData, ErrorCode> {
function read_accelerometer_mag (line 121) | pub fn read_accelerometer_mag() -> f64 {
type NineDofListener (line 136) | pub struct NineDofListener<F: Fn(NineDofData)>(pub F);
function upcall (line 139) | fn upcall(&self, arg0: u32, arg1: u32, arg2: u32) {
constant DRIVER_NUM (line 155) | const DRIVER_NUM: u32 = 0x60004;
constant EXISTS (line 158) | const EXISTS: u32 = 0;
constant READ_ACCELEROMETER (line 159) | const READ_ACCELEROMETER: u32 = 1;
constant READ_MAGNETOMETER (line 160) | const READ_MAGNETOMETER: u32 = 100;
constant READ_GYRO (line 161) | const READ_GYRO: u32 = 200;
FILE: apis/sensors/ninedof/src/tests.rs
type NineDof (line 7) | type NineDof = super::NineDof<fake::Syscalls>;
function no_driver (line 10) | fn no_driver() {
function exists (line 16) | fn exists() {
function driver_busy (line 25) | fn driver_busy() {
function read_accelerometer (line 38) | fn read_accelerometer() {
function read_magnetometer (line 61) | fn read_magnetometer() {
function read_gyro (line 84) | fn read_gyro() {
function register_unregister_listener (line 107) | fn register_unregister_listener() {
function read_accelerometer_sync (line 159) | fn read_accelerometer_sync() {
function read_magnetometer_sync (line 170) | fn read_magnetometer_sync() {
function read_gyro_sync (line 183) | fn read_gyro_sync() {
FILE: apis/sensors/proximity/src/lib.rs
type Proximity (line 7) | pub struct Proximity<S: Syscalls>(S);
function exists (line 12) | pub fn exists() -> Result<(), ErrorCode> {
function register_listener (line 17) | pub fn register_listener<'share>(
function unregister_listener (line 25) | pub fn unregister_listener() {
function read (line 30) | pub fn read() -> Result<(), ErrorCode> {
function read_sync (line 38) | pub fn read_sync() -> Result<u8, ErrorCode> {
function read_on_interrupt (line 60) | pub fn read_on_interrupt(lower: u8, upper: u8) -> Result<(), ErrorCode> {
function wait_for_value_between (line 72) | pub fn wait_for_value_between(lower: u8, upper: u8) -> Result<u8, ErrorC...
constant DRIVER_NUM (line 101) | const DRIVER_NUM: u32 = 0x60005;
constant EXISTS (line 105) | const EXISTS: u32 = 0;
constant READ (line 106) | const READ: u32 = 1;
constant READ_ON_INT (line 107) | const READ_ON_INT: u32 = 2;
FILE: apis/sensors/proximity/src/tests.rs
type Proximity (line 5) | type Proximity = super::Proximity<fake::Syscalls>;
function no_driver (line 8) | fn no_driver() {
function exists (line 14) | fn exists() {
function busy_driver (line 23) | fn busy_driver() {
function async_readings (line 39) | fn async_readings() {
function sync_readings (line 68) | fn sync_readings() {
function bad_arguments (line 81) | fn bad_arguments() {
FILE: apis/sensors/sound_pressure/src/lib.rs
type SoundPressure (line 8) | pub struct SoundPressure<S: Syscalls>(S);
function exists (line 13) | pub fn exists() -> Result<(), ErrorCode> {
function read (line 19) | pub fn read() -> Result<(), ErrorCode> {
function register_listener (line 24) | pub fn register_listener<'share, F: Fn(u32)>(
function unregister_listener (line 32) | pub fn unregister_listener() {
function enable (line 37) | pub fn enable() -> Result<(), ErrorCode> {
function disable (line 42) | pub fn disable() -> Result<(), ErrorCode> {
function read_sync (line 49) | pub fn read_sync() -> Result<u8, ErrorCode> {
type SoundPressureListener (line 74) | pub struct SoundPressureListener<F: Fn(u32)>(pub F);
function upcall (line 76) | fn upcall(&self, pressure_val: u32, _arg1: u32, _arg2: u32) {
constant DRIVER_NUM (line 88) | const DRIVER_NUM: u32 = 0x60006;
constant EXISTS (line 92) | const EXISTS: u32 = 0;
constant READ_PRESSURE (line 93) | const READ_PRESSURE: u32 = 1;
FILE: apis/sensors/sound_pressure/src/tests.rs
type SoundPressure (line 5) | type SoundPressure = super::SoundPressure<fake::Syscalls>;
function no_driver (line 8) | fn no_driver() {
function exists (line 14) | fn exists() {
function driver_busy (line 23) | fn driver_busy() {
function read_pressure (line 36) | fn read_pressure() {
function read_pressure_sync (line 68) | fn read_pressure_sync() {
FILE: apis/sensors/temperature/src/lib.rs
type Temperature (line 8) | pub struct Temperature<S: Syscalls>(S);
function exists (line 13) | pub fn exists() -> Result<(), ErrorCode> {
function read_temperature (line 20) | pub fn read_temperature() -> Result<(), ErrorCode> {
function register_listener (line 25) | pub fn register_listener<'share, F: Fn(i32)>(
function unregister_listener (line 33) | pub fn unregister_listener() {
function read_temperature_sync (line 40) | pub fn read_temperature_sync() -> Result<i32, ErrorCode> {
type TemperatureListener (line 62) | pub struct TemperatureListener<F: Fn(i32)>(pub F);
function upcall (line 64) | fn upcall(&self, temp_val: u32, _arg1: u32, _arg2: u32) {
constant DRIVER_NUM (line 76) | const DRIVER_NUM: u32 = 0x60000;
constant EXISTS (line 80) | const EXISTS: u32 = 0;
constant READ_TEMP (line 81) | const READ_TEMP: u32 = 1;
FILE: apis/sensors/temperature/src/tests.rs
type Temperature (line 5) | type Temperature = super::Temperature<fake::Syscalls>;
function no_driver (line 8) | fn no_driver() {
function exists (line 14) | fn exists() {
function read_temperature (line 23) | fn read_temperature() {
function register_unregister_listener (line 36) | fn register_unregister_listener() {
function read_temperature_sync (line 64) | fn read_temperature_sync() {
function negative_value (line 74) | fn negative_value() {
FILE: apis/storage/key_value/src/lib.rs
type KeyValue (line 14) | pub struct KeyValue<S: Syscalls, C: Config = DefaultConfig>(S, C);
function exists (line 19) | pub fn exists() -> bool {
function get (line 24) | pub fn get(key: &[u8], value: &mut [u8]) -> Result<u32, ErrorCode> {
function insert (line 54) | fn insert(command_num: u32, key: &[u8], value: &[u8]) -> Result<(), Erro...
function set (line 84) | pub fn set(key: &[u8], value: &[u8]) -> Result<(), ErrorCode> {
function add (line 89) | pub fn add(key: &[u8], value: &[u8]) -> Result<(), ErrorCode> {
function update (line 94) | pub fn update(key: &[u8], value: &[u8]) -> Result<(), ErrorCode> {
function delete (line 99) | pub fn delete(key: &[u8]) -> Result<(), ErrorCode> {
type Config (line 128) | pub trait Config:
constant DRIVER_NUM (line 144) | const DRIVER_NUM: u32 = 0x50003;
constant DRIVER_CHECK (line 149) | pub const DRIVER_CHECK: u32 = 0;
constant GET (line 150) | pub const GET: u32 = 1;
constant SET (line 151) | pub const SET: u32 = 2;
constant DELETE (line 152) | pub const DELETE: u32 = 3;
constant ADD (line 153) | pub const ADD: u32 = 4;
constant UPDATE (line 154) | pub const UPDATE: u32 = 5;
constant CALLBACK (line 159) | pub const CALLBACK: u32 = 0;
constant KEY (line 163) | pub const KEY: u32 = 0;
constant VALUE_WRITE (line 164) | pub const VALUE_WRITE: u32 = 1;
constant VALUE_READ (line 168) | pub const VALUE_READ: u32 = 0;
FILE: apis/storage/key_value/src/tests.rs
type Kv (line 5) | type Kv = super::KeyValue<fake::Syscalls>;
function _get (line 7) | fn _get(kernel: &fake::Kernel) -> Result<u32, ErrorCode> {
function _set (line 35) | fn _set(kernel: &fake::Kernel) -> Result<(), ErrorCode> {
function _add (line 62) | fn _add(kernel: &fake::Kernel) -> Result<(), ErrorCode> {
function _update (line 89) | fn _update(kernel: &fake::Kernel) -> Result<(), ErrorCode> {
function _delete (line 116) | fn _delete(kernel: &fake::Kernel) -> Result<(), ErrorCode> {
function no_driver (line 139) | fn no_driver() {
function driver_check (line 145) | fn driver_check() {
function get_fail (line 154) | fn get_fail() {
function set_get (line 163) | fn set_get() {
function add (line 173) | fn add() {
function add_fail (line 182) | fn add_fail() {
function update (line 192) | fn update() {
function update_fail (line 202) | fn update_fail() {
function delete (line 211) | fn delete() {
function delete_fail (line 221) | fn delete_fail() {
FILE: build.rs
function main (line 1) | fn main() {
FILE: build_scripts/src/lib.rs
constant PLATFORMS (line 5) | const PLATFORMS: &[(&str, &str, &str, &str, &str)] = &[
function auto_layout (line 56) | pub fn auto_layout() {
function get_env_var (line 188) | fn get_env_var(name: &str) -> Option<String> {
FILE: demos/embedded_graphics/buttons/build.rs
function main (line 1) | fn main() {
FILE: demos/embedded_graphics/buttons/src/main.rs
function run (line 23) | fn run() -> Result<(), ErrorCode> {
function main (line 113) | fn main() {
FILE: demos/embedded_graphics/spin/build.rs
function main (line 1) | fn main() {
FILE: demos/embedded_graphics/spin/src/main.rs
function main (line 19) | fn main() {
FILE: demos/st7789-slint/build.rs
function main (line 1) | fn main() {
FILE: demos/st7789-slint/src/main.rs
type MyCriticalSection (line 32) | struct MyCriticalSection;
method acquire (line 36) | unsafe fn acquire() -> RawRestoreState {
method release (line 45) | unsafe fn release(_token: RawRestoreState) {}
function setup_heap (line 49) | unsafe fn setup_heap() {
constant W (line 58) | const W: i32 = 240;
constant H (line 59) | const H: i32 = 240;
type Delay (line 61) | struct Delay;
method delay_ns (line 64) | fn delay_ns(&mut self, ns: u32) {
function main (line 70) | fn main() {
type SlintPlatform (line 92) | struct SlintPlatform {
method create_window_adapter (line 97) | fn create_window_adapter(
method duration_since_start (line 103) | fn duration_since_start(&self) -> core::time::Duration {
method debug_log (line 107) | fn debug_log(&self, arguments: core::fmt::Arguments) {
method run_event_loop (line 111) | fn run_event_loop(&self) -> Result<(), slint::PlatformError> {
type DrawBuffer (line 153) | struct DrawBuffer<'a, Display> {
type TargetPixel (line 162) | type TargetPixel = slint::platform::software_renderer::Rgb565Pixel;
function process_line (line 164) | fn process_line(
FILE: demos/st7789/build.rs
function main (line 1) | fn main() {
FILE: demos/st7789/src/main.rs
constant W (line 27) | const W: i32 = 240;
constant H (line 28) | const H: i32 = 240;
type Delay (line 30) | struct Delay;
method delay_ns (line 33) | fn delay_ns(&mut self, ns: u32) {
function main (line 38) | fn main() {
FILE: examples/adc.rs
function main (line 17) | fn main() {
FILE: examples/ambient_light.rs
function main (line 17) | fn main() {
FILE: examples/blink.rs
function main (line 13) | fn main() {
FILE: examples/buttons.rs
function main (line 17) | fn main() {
FILE: examples/console.rs
function main (line 13) | fn main() {
FILE: examples/gpio.rs
function main (line 20) | fn main() {
FILE: examples/i2c_master_write_read.rs
constant SLAVE_DEVICE_ADDR (line 21) | pub const SLAVE_DEVICE_ADDR: u16 = 0x69;
function main (line 23) | fn main() {
FILE: examples/i2c_slave_send_recv.rs
constant SLAVE_DEVICE_ADDR (line 20) | pub const SLAVE_DEVICE_ADDR: u8 = 0x69;
function main (line 21) | fn main() {
FILE: examples/ieee802154_raw.rs
function main (line 22) | fn main() {
function rx_single_buffer (line 75) | fn rx_single_buffer() {
FILE: examples/ieee802154_rx_raw.rs
function main (line 23) | fn main() {
FILE: examples/ieee802154_rx_tx_raw.rs
function main (line 25) | fn main() {
FILE: examples/ieee802154_tx_raw.rs
function main (line 25) | fn main() {
FILE: examples/kv.rs
function get_and_print (line 18) | fn get_and_print(key: &[u8], value: &mut [u8]) {
function main (line 39) | fn main() {
FILE: examples/leds.rs
function main (line 13) | fn main() {
FILE: examples/low_level_debug.rs
function main (line 13) | fn main() {
FILE: examples/music.rs
constant MELODY (line 18) | const MELODY: [(Note, i32); 62] = [
constant TEMPO (line 83) | const TEMPO: u32 = 114;
constant WHOLE_NOTE (line 84) | const WHOLE_NOTE: u32 = (60000 * 4) / TEMPO;
function main (line 86) | fn main() {
FILE: examples/ninedof.rs
function main (line 16) | fn main() {
FILE: examples/proximity.rs
function main (line 17) | fn main() {
FILE: examples/rng.rs
type Randomness (line 13) | struct Randomness<'a, const N: usize>(&'a [u8; N]);
function fmt (line 16) | fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
function main (line 25) | fn main() {
FILE: examples/rng_async.rs
function main (line 14) | fn main() {
FILE: examples/screen.rs
function main (line 13) | fn main() {
FILE: examples/sound_pressure.rs
function main (line 17) | fn main() {
FILE: examples/spi_controller_write_read.rs
constant OPERATION_LEN (line 13) | const OPERATION_LEN: usize = 0x08;
function main (line 15) | fn main() {
FILE: examples/temperature.rs
function main (line 17) | fn main() {
FILE: examples/usb_i2c_mctp.rs
constant MY_ID (line 89) | pub const MY_ID: u8 = 0x34;
constant HEADER_LEN (line 91) | pub const HEADER_LEN: usize = 4;
constant MAX_DLEN (line 93) | pub const MAX_DLEN: usize = 128;
constant RX_BUF_LEN (line 95) | pub const RX_BUF_LEN: usize = HEADER_LEN + MAX_DLEN;
constant PANIC_LED (line 97) | pub const PANIC_LED: u32 = 0;
constant RX_LED (line 99) | pub const RX_LED: u32 = 1;
constant TX_LED (line 101) | pub const TX_LED: u32 = 2;
function prepare_tx_header (line 123) | fn prepare_tx_header(buf: &mut [u8], n_bytes: usize) -> Result<usize, ()> {
function main (line 137) | fn main() {
FILE: libraries/embedded_graphics_libtock/src/tock_screen.rs
type TockMonochrome8BitPage128x64Screen (line 11) | pub struct TockMonochrome8BitPage128x64Screen {
method new (line 26) | pub fn new() -> Self {
method get_width (line 41) | pub fn get_width(&self) -> u32 {
method get_height (line 45) | pub fn get_height(&self) -> u32 {
method flush (line 50) | pub fn flush(&self) -> Result<(), ErrorCode> {
type Color (line 58) | type Color = embedded_graphics::pixelcolor::BinaryColor;
type Error (line 59) | type Error = core::convert::Infallible;
method draw_iter (line 61) | fn draw_iter<I>(&mut self, pixels: I) -> Result<(), Self::Error>
method size (line 94) | fn size(&self) -> embedded_graphics::geometry::Size {
method default (line 20) | fn default() -> Self {
FILE: panic_handlers/debug_panic/src/lib.rs
function panic_handler (line 10) | fn panic_handler(info: &core::panic::PanicInfo) -> ! {
FILE: panic_handlers/small_panic/src/lib.rs
function panic_handler (line 8) | fn panic_handler(_info: &core::panic::PanicInfo) -> ! {
FILE: platform/src/allow_ro.rs
type AllowRo (line 14) | pub struct AllowRo<'share, S: Syscalls, const DRIVER_NUM: u32, const BUF...
method default (line 40) | fn default() -> Self {
method drop (line 51) | fn drop(&mut self) {
type Config (line 68) | pub trait Config {
method returned_nonzero_buffer (line 72) | fn returned_nonzero_buffer(_driver_num: u32, _buffer_num: u32) {}
FILE: platform/src/allow_rw.rs
type AllowRw (line 14) | pub struct AllowRw<'share, S: Syscalls, const DRIVER_NUM: u32, const BUF...
method default (line 40) | fn default() -> Self {
method drop (line 51) | fn drop(&mut self) {
type Config (line 68) | pub trait Config {
method returned_nonzero_buffer (line 72) | fn returned_nonzero_buffer(_driver_num: u32, _buffer_num: u32) {}
FILE: platform/src/command_return.rs
type CommandReturn (line 63) | pub struct CommandReturn {
method new (line 76) | pub unsafe fn new(return_variant: ReturnVariant, r1: u32, r2: u32, r3:...
method is_failure (line 87) | pub fn is_failure(&self) -> bool {
method is_failure_u32 (line 92) | pub fn is_failure_u32(&self) -> bool {
method is_failure_2_u32 (line 97) | pub fn is_failure_2_u32(&self) -> bool {
method is_failure_u64 (line 102) | pub fn is_failure_u64(&self) -> bool {
method is_success (line 108) | pub fn is_success(&self) -> bool {
method is_success_u32 (line 113) | pub fn is_success_u32(&self) -> bool {
method is_success_2_u32 (line 118) | pub fn is_success_2_u32(&self) -> bool {
method is_success_u64 (line 123) | pub fn is_success_u64(&self) -> bool {
method is_success_3_u32 (line 128) | pub fn is_success_3_u32(&self) -> bool {
method is_success_u32_u64 (line 133) | pub fn is_success_u32_u64(&self) -> bool {
method get_failure (line 138) | pub fn get_failure(&self) -> Option<ErrorCode> {
method get_failure_u32 (line 147) | pub fn get_failure_u32(&self) -> Option<(ErrorCode, u32)> {
method get_failure_2_u32 (line 156) | pub fn get_failure_2_u32(&self) -> Option<(ErrorCode, u32, u32)> {
method get_failure_u64 (line 169) | pub fn get_failure_u64(&self) -> Option<(ErrorCode, u64)> {
method get_success_u32 (line 180) | pub fn get_success_u32(&self) -> Option<u32> {
method get_success_2_u32 (line 188) | pub fn get_success_2_u32(&self) -> Option<(u32, u32)> {
method get_success_u64 (line 196) | pub fn get_success_u64(&self) -> Option<u64> {
method get_success_3_u32 (line 204) | pub fn get_success_3_u32(&self) -> Option<(u32, u32, u32)> {
method get_success_u32_u64 (line 213) | pub fn get_success_u32_u64(&self) -> Option<(u32, u64)> {
method raw_values (line 221) | pub fn raw_values(&self) -> (ReturnVariant, u32, u32, u32) {
method return_variant (line 226) | pub fn return_variant(&self) -> ReturnVariant {
method to_result (line 239) | pub fn to_result<T, E>(self) -> Result<T, E>
type Sealed (line 262) | pub trait Sealed {}
type SuccessData (line 271) | pub trait SuccessData: sealed::Sealed {
constant RETURN_VARIANT (line 274) | const RETURN_VARIANT: ReturnVariant;
method from_raw_values (line 277) | fn from_raw_values(r1: u32, r2: u32, r3: u32) -> Self;
constant RETURN_VARIANT (line 282) | const RETURN_VARIANT: ReturnVariant = return_variant::SUCCESS;
method from_raw_values (line 284) | fn from_raw_values(_r1: u32, _r2: u32, _r3: u32) -> Self {}
constant RETURN_VARIANT (line 288) | const RETURN_VARIANT: ReturnVariant = return_variant::SUCCESS_U32;
method from_raw_values (line 290) | fn from_raw_values(r1: u32, _r2: u32, _r3: u32) -> Self {
constant RETURN_VARIANT (line 296) | const RETURN_VARIANT: ReturnVariant = return_variant::SUCCESS_U64;
method from_raw_values (line 298) | fn from_raw_values(r1: u32, r2: u32, _r3: u32) -> Self {
constant RETURN_VARIANT (line 304) | const RETURN_VARIANT: ReturnVariant = return_variant::SUCCESS_2_U32;
method from_raw_values (line 306) | fn from_raw_values(r1: u32, r2: u32, _r3: u32) -> Self {
constant RETURN_VARIANT (line 312) | const RETURN_VARIANT: ReturnVariant = return_variant::SUCCESS_U32_U64;
method from_raw_values (line 314) | fn from_raw_values(r1: u32, r2: u32, r3: u32) -> Self {
constant RETURN_VARIANT (line 320) | const RETURN_VARIANT: ReturnVariant = return_variant::SUCCESS_3_U32;
method from_raw_values (line 322) | fn from_raw_values(r1: u32, r2: u32, r3: u32) -> Self {
type FailureData (line 337) | pub unsafe trait FailureData: sealed::Sealed {
constant RETURN_VARIANT (line 340) | const RETURN_VARIANT: ReturnVariant;
method from_raw_values (line 343) | fn from_raw_values(r1: ErrorCode, r2: u32, r3: u32) -> Self;
constant RETURN_VARIANT (line 348) | const RETURN_VARIANT: ReturnVariant = return_variant::FAILURE;
method from_raw_values (line 350) | fn from_raw_values(r1: ErrorCode, _r2: u32, _r3: u32) -> Self {
constant RETURN_VARIANT (line 356) | const RETURN_VARIANT: ReturnVariant = return_variant::FAILURE_U32;
method from_raw_values (line 358) | fn from_raw_values(r1: ErrorCode, r2: u32, _r3: u32) -> Self {
constant RETURN_VARIANT (line 364) | const RETURN_VARIANT: ReturnVariant = return_variant::FAILURE_2_U32;
method from_raw_values (line 366) | fn from_raw_values(r1: ErrorCode, r2: u32, r3: u32) -> Self {
constant RETURN_VARIANT (line 372) | const RETURN_VARIANT: ReturnVariant = return_variant::FAILURE_U64;
method from_raw_values (line 374) | fn from_raw_values(r1: ErrorCode, r2: u32, r3: u32) -> Self {
FILE: platform/src/command_return_tests.rs
function failure (line 4) | fn failure() {
function failure_u32 (line 56) | fn failure_u32() {
function failure_2_u32 (line 111) | fn failure_2_u32() {
function failure_u64 (line 169) | fn failure_u64() {
function success (line 224) | fn success() {
function success_u32 (line 274) | fn success_u32() {
function success_2_u32 (line 325) | fn success_2_u32() {
function success_u64 (line 382) | fn success_u64() {
function success_3_u32 (line 439) | fn success_3_u32() {
function success_u32_u64 (line 496) | fn success_u32_u64() {
FILE: platform/src/constants.rs
constant TERMINATE (line 4) | pub const TERMINATE: u32 = 0;
constant RESTART (line 5) | pub const RESTART: u32 = 1;
constant SUBSCRIBE (line 9) | pub const SUBSCRIBE: usize = 1;
constant COMMAND (line 10) | pub const COMMAND: usize = 2;
constant ALLOW_RW (line 11) | pub const ALLOW_RW: usize = 3;
constant ALLOW_RO (line 12) | pub const ALLOW_RO: usize = 4;
constant MEMOP (line 13) | pub const MEMOP: usize = 5;
constant EXIT (line 14) | pub const EXIT: usize = 6;
constant NO_WAIT (line 18) | pub const NO_WAIT: u32 = 0;
constant WAIT (line 19) | pub const WAIT: u32 = 1;
FILE: platform/src/default_config.rs
type DefaultConfig (line 3) | pub struct DefaultConfig;
FILE: platform/src/error_code.rs
type ErrorCode (line 14) | pub enum ErrorCode {
method as_str (line 245) | fn as_str(self) -> Option<&'static str> {
method fmt (line 267) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
type Error (line 276) | type Error = NotAnErrorCode;
method try_from (line 278) | fn try_from(value: u32) -> Result<Self, Self::Error> {
method kind (line 289) | fn kind(&self) -> embedded_hal::digital::ErrorKind {
method kind (line 297) | fn kind(&self) -> embedded_hal::spi::ErrorKind {
type NotAnErrorCode (line 241) | pub struct NotAnErrorCode;
FILE: platform/src/error_code_tests.rs
function error_code_range (line 9) | fn error_code_range() {
function error_code_try_into (line 16) | fn error_code_try_into() {
FILE: platform/src/exit_on_drop.rs
type ExitOnDrop (line 15) | pub struct ExitOnDrop<S: crate::Syscalls>(core::marker::PhantomData<S>);
method default (line 18) | fn default() -> ExitOnDrop<S> {
method drop (line 24) | fn drop(&mut self) {
FILE: platform/src/raw_syscalls.rs
type RawSyscalls (line 65) | pub unsafe trait RawSyscalls: Sized {
method yield1 (line 85) | unsafe fn yield1(_: [Register; 1]);
method yield2 (line 105) | unsafe fn yield2(_: [Register; 2]);
method syscall1 (line 134) | unsafe fn syscall1<const CLASS: usize>(_: [Register; 1]) -> [Register;...
method syscall2 (line 159) | unsafe fn syscall2<const CLASS: usize>(_: [Register; 2]) -> [Register;...
method syscall4 (line 197) | unsafe fn syscall4<const CLASS: usize>(_: [Register; 4]) -> [Register;...
FILE: platform/src/register.rs
type Register (line 18) | pub struct Register(pub *mut ());
method from (line 25) | fn from(value: crate::ErrorCode) -> Register {
method from (line 31) | fn from(value: u32) -> Register {
method from (line 37) | fn from(value: i32) -> Register {
method from (line 43) | fn from(value: usize) -> Register {
method from (line 64) | fn from(value: *mut T) -> Register {
method from (line 70) | fn from(value: *const T) -> Register {
method as_u32 (line 89) | pub fn as_u32(self) -> u32 {
method as_i32 (line 96) | pub fn as_i32(self) -> i32 {
function from (line 102) | fn from(register: Register) -> usize {
function from (line 112) | fn from(register: Register) -> *mut T {
function from (line 118) | fn from(register: Register) -> *const T {
type Error (line 131) | type Error = core::num::TryFromIntError;
function try_from (line 133) | fn try_from(register: Register) -> Result<u32, core::num::TryFromIntErro...
FILE: platform/src/return_variant.rs
type ReturnVariant (line 9) | pub struct ReturnVariant(u32);
method from (line 12) | fn from(value: u32) -> ReturnVariant {
function from (line 18) | fn from(return_variant: ReturnVariant) -> crate::Register {
function from (line 24) | fn from(return_variant: ReturnVariant) -> u32 {
constant FAILURE (line 29) | pub const FAILURE: ReturnVariant = ReturnVariant(0);
constant FAILURE_U32 (line 30) | pub const FAILURE_U32: ReturnVariant = ReturnVariant(1);
constant FAILURE_2_U32 (line 31) | pub const FAILURE_2_U32: ReturnVariant = ReturnVariant(2);
constant FAILURE_U64 (line 32) | pub const FAILURE_U64: ReturnVariant = ReturnVariant(3);
constant SUCCESS (line 33) | pub const SUCCESS: ReturnVariant = ReturnVariant(128);
constant SUCCESS_U32 (line 34) | pub const SUCCESS_U32: ReturnVariant = ReturnVariant(129);
constant SUCCESS_2_U32 (line 35) | pub const SUCCESS_2_U32: ReturnVariant = ReturnVariant(130);
constant SUCCESS_U64 (line 36) | pub const SUCCESS_U64: ReturnVariant = ReturnVariant(131);
constant SUCCESS_3_U32 (line 37) | pub const SUCCESS_3_U32: ReturnVariant = ReturnVariant(132);
constant SUCCESS_U32_U64 (line 38) | pub const SUCCESS_U32_U64: ReturnVariant = ReturnVariant(133);
FILE: platform/src/share/handle.rs
type Handle (line 12) | pub struct Handle<'handle, L: List> {
method clone (line 26) | fn clone(&self) -> Self {
function new (line 40) | pub unsafe fn new(_list: &'handle L) -> Self {
function change_type (line 52) | pub unsafe fn change_type<Other: List>(self) -> Handle<'handle, Other> {
function split (line 59) | pub fn split(self) -> L::SplitHandles
type SplittableHandle (line 70) | pub trait SplittableHandle<'handle>: List {
method split (line 77) | fn split(handle: Handle<'handle, Self>) -> Self::SplitHandles;
FILE: platform/src/share/mod.rs
function scope (line 10) | pub fn scope<L: List, Output, F: FnOnce(Handle<L>) -> Output>(fcn: F) ->...
type List (line 21) | pub trait List: Default {}
FILE: platform/src/share/tests.rs
type InstanceCounter (line 7) | struct InstanceCounter {
method default (line 12) | fn default() -> Self {
method drop (line 19) | fn drop(&mut self) {
function list_lifetime (line 27) | fn list_lifetime() {
function tuple_impls (line 41) | fn tuple_impls() {
FILE: platform/src/share/tuple_impls.rs
type SplitHandles (line 11) | type SplitHandles = ();
function split (line 13) | fn split(_handle: Handle<'handle, ()>) {}
FILE: platform/src/subscribe.rs
type Subscribe (line 13) | pub struct Subscribe<'share, S: Syscalls, const DRIVER_NUM: u32, const S...
method default (line 35) | fn default() -> Self {
method drop (line 46) | fn drop(&mut self) {
type Upcall (line 67) | pub trait Upcall<SupportedIds> {
method upcall (line 68) | fn upcall(&self, arg0: u32, arg1: u32, arg2: u32);
type SupportsId (line 71) | pub trait SupportsId<const DRIVER_NUM: u32, const SUBSCRIBE_NUM: u32> {}
type AnyId (line 73) | pub struct AnyId;
type OneId (line 79) | pub struct OneId<const DRIVER_NUM: u32, const SUBSCRIBE_NUM: u32>;
function upcall (line 92) | fn upcall(&self, _: u32, _: u32, _: u32) {
function upcall (line 101) | fn upcall(&self, _: u32, _: u32, _: u32) {
function upcall (line 108) | fn upcall(&self, arg0: u32, _: u32, _: u32) {
function upcall (line 115) | fn upcall(&self, arg0: u32, arg1: u32, _: u32) {
function upcall (line 122) | fn upcall(&self, arg0: u32, arg1: u32, arg2: u32) {
function upcall (line 130) | fn upcall(&self, arg0: u32, _: u32, _: u32) {
function upcall (line 141) | fn upcall(&self, arg0: u32, arg1: u32, _: u32) {
function upcall (line 152) | fn upcall(&self, arg0: u32, arg1: u32, arg2: u32) {
function upcall_impls (line 162) | fn upcall_impls() {
type Config (line 218) | pub trait Config {
method returned_nonnull_upcall (line 222) | fn returned_nonnull_upcall(_driver_num: u32, _subscribe_num: u32) {}
FILE: platform/src/syscalls.rs
type Syscalls (line 9) | pub trait Syscalls: RawSyscalls + Sized {
method yield_no_wait (line 17) | fn yield_no_wait() -> YieldNoWaitReturn;
method yield_wait (line 21) | fn yield_wait();
method subscribe (line 28) | fn subscribe<
method unsubscribe (line 42) | fn unsubscribe(driver_num: u32, subscribe_num: u32);
method command (line 48) | fn command(driver_id: u32, command_id: u32, argument0: u32, argument1:...
method allow_rw (line 55) | fn allow_rw<'share, CONFIG: allow_rw::Config, const DRIVER_NUM: u32, c...
method unallow_rw (line 63) | fn unallow_rw(driver_num: u32, buffer_num: u32);
method allow_ro (line 70) | fn allow_ro<'share, CONFIG: allow_ro::Config, const DRIVER_NUM: u32, c...
method unallow_ro (line 78) | fn unallow_ro(driver_num: u32, buffer_num: u32);
method memop_brk (line 90) | unsafe fn memop_brk(addr: *const u8) -> Result<(), ErrorCode>;
method memop_sbrk (line 99) | unsafe fn memop_sbrk(incr: i32) -> Result<*const u8, ErrorCode>;
method memop_increment_brk (line 103) | fn memop_increment_brk(incr: u32) -> Result<*const u8, ErrorCode>;
method memop_app_ram_start (line 106) | fn memop_app_ram_start() -> Result<*const u8, ErrorCode>;
method memop_debug_stack_start (line 110) | fn memop_debug_stack_start(stack_top: *const u8) -> Result<(), ErrorCo...
method memop_debug_heap_start (line 113) | fn memop_debug_heap_start(initial_break: *const u8) -> Result<(), Erro...
method exit_terminate (line 121) | fn exit_terminate(exit_code: u32) -> !;
method exit_restart (line 123) | fn exit_restart(exit_code: u32) -> !;
FILE: platform/src/syscalls_impl.rs
method yield_no_wait (line 14) | fn yield_no_wait() -> YieldNoWaitReturn {
method yield_wait (line 29) | fn yield_wait() {
method subscribe (line 42) | fn subscribe<
method unsubscribe (line 147) | fn unsubscribe(driver_num: u32, subscribe_num: u32) {
method command (line 165) | fn command(driver_id: u32, command_id: u32, argument0: u32, argument1: u...
method allow_rw (line 188) | fn allow_rw<'share, CONFIG: allow_rw::Config, const DRIVER_NUM: u32, con...
method unallow_rw (line 254) | fn unallow_rw(driver_num: u32, buffer_num: u32) {
method allow_ro (line 272) | fn allow_ro<'share, CONFIG: allow_ro::Config, const DRIVER_NUM: u32, con...
method unallow_ro (line 341) | fn unallow_ro(driver_num: u32, buffer_num: u32) {
method memop_brk (line 361) | unsafe fn memop_brk(addr: *const u8) -> Result<(), ErrorCode> {
method memop_sbrk (line 392) | unsafe fn memop_sbrk(incr: i32) -> Result<*const u8, ErrorCode> {
method memop_increment_brk (line 416) | fn memop_increment_brk(incr: u32) -> Result<*const u8, ErrorCode> {
method memop_app_ram_start (line 421) | fn memop_app_ram_start() -> Result<*const u8, ErrorCode> {
method memop_debug_stack_start (line 445) | fn memop_debug_stack_start(stack_top: *const u8) -> Result<(), ErrorCode> {
method memop_debug_heap_start (line 473) | fn memop_debug_heap_start(initial_break: *const u8) -> Result<(), ErrorC...
method exit_terminate (line 506) | fn exit_terminate(exit_code: u32) -> ! {
method exit_restart (line 521) | fn exit_restart(exit_code: u32) -> ! {
FILE: platform/src/termination.rs
type Termination (line 6) | pub trait Termination {
method complete (line 7) | fn complete<S: Syscalls>(self) -> !;
method complete (line 11) | fn complete<S: Syscalls>(self) -> ! {
method complete (line 17) | fn complete<S: Syscalls>(self) -> ! {
FILE: platform/src/yield_types.rs
type YieldNoWaitReturn (line 12) | pub enum YieldNoWaitReturn {
FILE: runner/src/elf2tab.rs
function get_platform_architecture (line 7) | fn get_platform_architecture(platform: &str) -> Option<&'static str> {
function convert_elf (line 32) | pub fn convert_elf(cli: &Cli, platform: &str) -> OutFiles {
type OutFiles (line 108) | pub struct OutFiles {
function read_stack_size (line 115) | fn read_stack_size(cli: &Cli) -> String {
FILE: runner/src/main.rs
type Cli (line 13) | pub struct Cli {
type Deploy (line 29) | pub enum Deploy {
function main (line 34) | fn main() {
FILE: runner/src/output_processor.rs
function process (line 10) | pub fn process(cli: &Cli, mut child: Child) {
function forward_stdin_if_piped (line 57) | fn forward_stdin_if_piped(child: &mut Child) -> Option<RawTerminal<Stdou...
function forward_stderr_if_piped (line 104) | fn forward_stderr_if_piped(child: &mut Child, raw_mode: bool) {
FILE: runner/src/qemu.rs
function deploy (line 7) | pub fn deploy(cli: &Cli, platform: String, tbf_path: PathBuf) -> Child {
function get_platform_args (line 40) | fn get_platform_args(platform: String) -> PlatformConfig {
type PlatformConfig (line 64) | struct PlatformConfig {
FILE: runner/src/tockloader.rs
function deploy (line 10) | pub fn deploy(cli: &Cli, platform: String, tab_path: PathBuf) -> Child {
FILE: runtime/src/lib.rs
type TockSyscalls (line 27) | pub struct TockSyscalls;
FILE: runtime/src/startup/mod.rs
function handle_main_return (line 63) | pub fn handle_main_return<T: Termination>(result: T) -> ! {
type RtHeader (line 70) | struct RtHeader {
function rust_start (line 84) | extern "C" fn rust_start() -> ! {
function get_heap_start (line 107) | pub fn get_heap_start() -> *mut () {
FILE: runtime/src/startup/start_prototype.rs
function start_prototype (line 17) | extern "C" fn start_prototype(
FILE: runtime/src/syscalls_impl_arm.rs
method yield1 (line 5) | unsafe fn yield1([Register(r0)]: [Register; 1]) {
method yield2 (line 25) | unsafe fn yield2([Register(r0), Register(r1)]: [Register; 2]) {
method syscall1 (line 46) | unsafe fn syscall1<const SYSCALL_CLASS_NUMBER: usize>(
method syscall2 (line 65) | unsafe fn syscall2<const SYSCALL_CLASS_NUMBER: usize>(
method syscall4 (line 83) | unsafe fn syscall4<const SYSCALL_CLASS_NUMBER: usize>(
FILE: runtime/src/syscalls_impl_riscv.rs
method yield1 (line 8) | unsafe fn yield1([Register(r0)]: [Register; 1]) {
method yield2 (line 41) | unsafe fn yield2([Register(r0), Register(r1)]: [Register; 2]) {
method syscall1 (line 71) | unsafe fn syscall1<const CLASS: usize>([Register(mut r0)]: [Register; 1]...
method syscall2 (line 87) | unsafe fn syscall2<const CLASS: usize>(
method syscall4 (line 104) | unsafe fn syscall4<const CLASS: usize>(
FILE: runtime/src/syscalls_impl_x86.rs
method yield1 (line 6) | unsafe fn yield1([Register(r0)]: [Register; 1]) {
method yield2 (line 29) | unsafe fn yield2([Register(r0), Register(r1)]: [Register; 2]) {
method syscall1 (line 52) | unsafe fn syscall1<const CLASS: usize>([Register(mut r0)]: [Register; 1]...
method syscall2 (line 78) | unsafe fn syscall2<const CLASS: usize>(
method syscall4 (line 112) | unsafe fn syscall4<const CLASS: usize>(
FILE: src/lib.rs
type Adc (line 14) | pub type Adc = adc::Adc<super::runtime::TockSyscalls>;
type Screen (line 19) | pub type Screen = screen::Screen<super::runtime::TockSyscalls>;
type AirQuality (line 23) | pub type AirQuality = air_quality::AirQuality<super::runtime::TockSyscal...
type Alarm (line 29) | pub type Alarm = alarm::Alarm<super::runtime::TockSyscalls>;
type AmbientLight (line 34) | pub type AmbientLight = ambient_light::AmbientLight<super::runtime::Tock...
type Buttons (line 39) | pub type Buttons = buttons::Buttons<super::runtime::TockSyscalls>;
type Buzzer (line 44) | pub type Buzzer = buzzer::Buzzer<super::runtime::TockSyscalls>;
type Console (line 49) | pub type Console = console::Console<super::runtime::TockSyscalls>;
type Gpio (line 54) | pub type Gpio = gpio::Gpio<super::runtime::TockSyscalls>;
type I2CMaster (line 62) | pub type I2CMaster = i2c_master::I2CMaster<super::runtime::TockSyscalls>;
type I2CMasterSlave (line 66) | pub type I2CMasterSlave = i2c_master_slave::I2CMasterSlave<super::runtim...
type Ieee802154 (line 70) | pub type Ieee802154 = ieee802154::Ieee802154<super::runtime::TockSyscalls>;
type RxSingleBufferOperator (line 72) | pub type RxSingleBufferOperator<'buf, const N: usize> =
type Leds (line 77) | pub type Leds = leds::Leds<super::runtime::TockSyscalls>;
type LowLevelDebug (line 81) | pub type LowLevelDebug = lldb::LowLevelDebug<super::runtime::TockSyscalls>;
type NineDof (line 86) | pub type NineDof = ninedof::NineDof<super::runtime::TockSyscalls>;
type Proximity (line 91) | pub type Proximity = proximity::Proximity<super::runtime::TockSyscalls>;
type Rng (line 95) | pub type Rng = rng::Rng<super::runtime::TockSyscalls>;
type SoundPressure (line 100) | pub type SoundPressure = sound_pressure::SoundPressure<super::runtime::T...
type SpiController (line 107) | pub type SpiController = spi_controller::SpiController<super::runtime::T...
type Temperature (line 111) | pub type Temperature = temperature::Temperature<super::runtime::TockSysc...
type KeyValue (line 116) | pub type KeyValue = key_value::KeyValue<super::runtime::TockSyscalls>;
FILE: src/spi_controller.rs
type SpiController (line 5) | pub type SpiController = spi_controller::SpiController<super::runtime::T...
type EmbeddedHalSpi (line 7) | pub struct EmbeddedHalSpi;
type Error (line 10) | type Error = ErrorCode;
method transaction (line 14) | fn transaction(
FILE: syscalls_tests/src/allow_ro.rs
type TestDriver (line 8) | struct TestDriver {
method info (line 13) | fn info(&self) -> DriverInfo {
method command (line 17) | fn command(&self, _command_num: u32, _argument0: u32, _argument1: u32)...
method allow_readonly (line 21) | fn allow_readonly(
type TestConfig (line 33) | struct TestConfig;
method returned_nonzero_buffer (line 39) | fn returned_nonzero_buffer(driver_num: u32, buffer_num: u32) {
function allow_ro (line 47) | fn allow_ro() {
FILE: syscalls_tests/src/allow_rw.rs
type TestDriver (line 8) | struct TestDriver {
method info (line 13) | fn info(&self) -> DriverInfo {
method command (line 17) | fn command(&self, _command_num: u32, _argument0: u32, _argument1: u32)...
method allow_readwrite (line 21) | fn allow_readwrite(
type TestConfig (line 33) | struct TestConfig;
method returned_nonzero_buffer (line 39) | fn returned_nonzero_buffer(driver_num: u32, buffer_num: u32) {
function allow_rw (line 47) | fn allow_rw() {
FILE: syscalls_tests/src/command_tests.rs
function command (line 8) | fn command() {
FILE: syscalls_tests/src/exit_on_drop.rs
function maybe_unwind (line 5) | fn maybe_unwind(unwind: bool) {
function exit (line 13) | fn exit() {
function no_exit (line 23) | fn no_exit() {
FILE: syscalls_tests/src/memop_tests.rs
function memop (line 8) | fn memop() {
function brk_test (line 29) | fn brk_test() {
function sbrk_test (line 51) | fn sbrk_test() {
function increment_brk_test (line 75) | fn increment_brk_test() {
function app_ram_start_test (line 99) | fn app_ram_start_test() {
function debug_stack_start_test (line 117) | fn debug_stack_start_test() {
function debug_heap_start_test (line 136) | fn debug_heap_start_test() {
FILE: syscalls_tests/src/subscribe_tests.rs
type MockDriver (line 9) | struct MockDriver {
method info (line 14) | fn info(&self) -> DriverInfo {
method register (line 18) | fn register(&self, share_ref: DriverShareRef) {
method command (line 22) | fn command(&self, _: u32, _: u32, _: u32) -> CommandReturn {
function config (line 28) | fn config() {
function failed (line 60) | fn failed() {
function success (line 72) | fn success() {
function unwinding_upcall (line 109) | fn unwinding_upcall() {
FILE: syscalls_tests/src/yield_tests.rs
function no_wait_upcall (line 9) | fn no_wait_upcall() {
function no_wait_no_upcall (line 21) | fn no_wait_no_upcall() {
function wait (line 33) | fn wait() {
FILE: tools/print_sizes/src/main.rs
constant ARCHITECTURES (line 2) | const ARCHITECTURES: [&str; 2] = ["riscv32imc-unknown-none-elf", "thumbv...
type Example (line 9) | struct Example {
function find_examples (line 16) | fn find_examples() -> Vec<Example> {
type ElfSizes (line 67) | struct ElfSizes {
function get_sizes (line 74) | fn get_sizes(path: &std::path::Path) -> ElfSizes {
type ExampleData (line 94) | struct ExampleData {
function main (line 100) | fn main() {
FILE: ufmt/macros/src/lib.rs
function debug (line 35) | pub fn debug(input: TokenStream) -> TokenStream {
function uwrite (line 170) | pub fn uwrite(input: TokenStream) -> TokenStream {
function uwriteln (line 175) | pub fn uwriteln(input: TokenStream) -> TokenStream {
function write (line 179) | fn write(input: TokenStream, newline: bool) -> TokenStream {
type Input (line 290) | struct Input {
method parse (line 299) | fn parse(input: ParseStream) -> parse::Result<Self> {
type Hex (line 325) | pub(crate) enum Hex {
type Piece (line 331) | enum Piece<'a> {
function is_str (line 345) | fn is_str(&self) -> bool {
function mk_ident (line 353) | fn mk_ident(i: usize) -> Ident {
function unescape (line 358) | fn unescape<'l>(mut literal: &'l str, span: Span) -> parse::Result<Cow<'...
function parse (line 392) | fn parse<'l>(mut literal: &'l str, span: Span) -> parse::Result<Vec<Piec...
function pieces (line 534) | fn pieces() {
function unescape (line 625) | fn unescape() {
FILE: ufmt/src/helpers.rs
function debug_list (line 9) | pub fn debug_list(&mut self) -> Result<DebugList<'_, 'w, W>, W::Error> {
function debug_map (line 24) | pub fn debug_map(&mut self) -> Result<DebugMap<'_, 'w, W>, W::Error> {
function debug_set (line 39) | pub fn debug_set(&mut self) -> Result<DebugSet<'_, 'w, W>, W::Error> {
function debug_struct (line 54) | pub fn debug_struct(&mut self, name: &str) -> Result<DebugStruct<'_, 'w,...
function debug_tuple (line 69) | pub fn debug_tuple(&mut self, name: &str) -> Result<DebugTuple<'_, 'w, W...
type DebugList (line 91) | pub struct DebugList<'f, 'w, W>
function entry (line 104) | pub fn entry(&mut self, entry: &impl uDebug) -> Result<&mut Self, W::Err...
function entries (line 129) | pub fn entries(
function finish (line 141) | pub fn finish(&mut self) -> Result<(), W::Error> {
type DebugMap (line 157) | pub struct DebugMap<'f, 'w, W>
function entry (line 170) | pub fn entry(&mut self, key: &impl uDebug, value: &impl uDebug) -> Resul...
function entries (line 197) | pub fn entries(
function finish (line 209) | pub fn finish(&mut self) -> Result<(), W::Error> {
type DebugSet (line 220) | pub struct DebugSet<'f, 'w, W>
function entry (line 233) | pub fn entry(&mut self, entry: &impl uDebug) -> Result<&mut Self, W::Err...
function entries (line 258) | pub fn entries(
function finish (line 270) | pub fn finish(&mut self) -> Result<(), W::Error> {
type DebugStruct (line 281) | pub struct DebugStruct<'f, 'w, W>
function field (line 294) | pub fn field(&mut self, name: &str, value: &impl uDebug) -> Result<&mut ...
function finish (line 325) | pub fn finish(&mut self) -> Result<(), W::Error> {
type DebugTuple (line 350) | pub struct DebugTuple<'f, 'w, W>
function field (line 365) | pub fn field(&mut self, value: &impl uDebug) -> Result<&mut Self, W::Err...
function finish (line 394) | pub fn finish(&mut self) -> Result<(), W::Error> {
FILE: ufmt/src/impls/core.rs
method fmt (line 4) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
method fmt (line 18) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
method fmt (line 42) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
method fmt (line 54) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
method fmt (line 64) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
method fmt (line 97) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
method fmt (line 110) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
method fmt (line 123) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
method fmt (line 136) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
method fmt (line 149) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
method fmt (line 161) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
method fmt (line 177) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
FILE: ufmt/src/impls/ixx.rs
function isize_pad (line 76) | fn isize_pad(n: isize, width: Option<u8>, pad: char, buf: &mut [u8]) -> ...
method fmt (line 81) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
method fmt (line 97) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
method fmt (line 106) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
method fmt (line 122) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
method fmt (line 131) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
method fmt (line 147) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
method fmt (line 157) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
method fmt (line 172) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
method fmt (line 188) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
method fmt (line 197) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
method fmt (line 214) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
method fmt (line 225) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
method fmt (line 234) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
method fmt (line 243) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
method fmt (line 254) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
method fmt (line 263) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
method fmt (line 272) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
FILE: ufmt/src/impls/ptr.rs
function hex (line 19) | fn hex(mut n: usize, buf: &mut [u8]) -> usize {
method fmt (line 47) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
method fmt (line 55) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
method fmt (line 63) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
method fmt (line 73) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
FILE: ufmt/src/impls/std.rs
method fmt (line 9) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
method fmt (line 21) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
method fmt (line 34) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
method fmt (line 46) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
method fmt (line 59) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
method fmt (line 71) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
method fmt (line 80) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
method fmt (line 89) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
method fmt (line 101) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
FILE: ufmt/src/impls/tuple.rs
method fmt (line 21) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
FILE: ufmt/src/impls/uxx.rs
function usize_pad (line 127) | fn usize_pad(n: usize, width: Option<u8>, pad: char, buf: &mut [u8]) -> ...
function usize_hex_pad (line 131) | fn usize_hex_pad(
method fmt (line 143) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
method fmt (line 165) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
method fmt (line 174) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
method fmt (line 196) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
method fmt (line 205) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
method fmt (line 227) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
method fmt (line 237) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
method fmt (line 251) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
method fmt (line 273) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
method fmt (line 282) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
method fmt (line 298) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
method fmt (line 309) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
method fmt (line 318) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
method fmt (line 327) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
method fmt (line 338) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
method fmt (line 347) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
method fmt (line 356) | fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
FILE: ufmt/src/lib.rs
type uDebug (line 262) | pub trait uDebug {
method fmt (line 264) | fn fmt<W>(&self, _: &mut Formatter<'_, W>) -> Result<(), W::Error>
type uDisplay (line 271) | pub trait uDisplay {
method fmt (line 273) | fn fmt<W>(&self, _: &mut Formatter<'_, W>) -> Result<(), W::Error>
type Formatter (line 280) | pub struct Formatter<'w, W>
function new (line 298) | pub fn new(writer: &'w mut W) -> Self {
function pretty (line 311) | pub fn pretty(
function hex (line 323) | pub fn hex(
function fixed_width (line 340) | pub fn fixed_width(
function write_char (line 381) | pub fn write_char(&mut self, c: char) -> Result<(), W::Error> {
function write_str (line 390) | pub fn write_str(&mut self, s: &str) -> Result<(), W::Error> {
function indent (line 399) | fn indent(&mut self) -> Result<(), W::Error> {
type UnstableDoAsFormatter (line 410) | pub trait UnstableDoAsFormatter {
method do_as_formatter (line 413) | fn do_as_formatter(
type Writer (line 423) | type Writer = W;
method do_as_formatter (line 425) | fn do_as_formatter(
type Writer (line 437) | type Writer = W;
method do_as_formatter (line 439) | fn do_as_formatter(
FILE: ufmt/tests/vs-std-write.rs
function core (line 27) | fn core() {
function recursion (line 42) | fn recursion() {
function uxx (line 65) | fn uxx() {
function ixx (line 80) | fn ixx() {
function hex (line 102) | fn hex() {
function special_hex (line 130) | fn special_hex() {
function width_format_numbers (line 190) | fn width_format_numbers() {
function width_non_numbers (line 243) | fn width_non_numbers() {
function fmt (line 250) | fn fmt() {
function map (line 256) | fn map() {
function set (line 272) | fn set() {
function struct_ (line 288) | fn struct_() {
function enum_ (line 329) | fn enum_() {
function ptr (line 347) | fn ptr() {
function tuples (line 363) | fn tuples() {
function slice (line 384) | fn slice() {
function uwriteln (line 395) | fn uwriteln() {
function formatter_uwrite (line 403) | fn formatter_uwrite() {
function generic (line 422) | fn generic() {
function static_lifetime (line 438) | fn static_lifetime(x: &'static mut u32) {
function dst (line 448) | fn dst() {
FILE: ufmt/utils/src/lib.rs
type Ignore (line 32) | pub struct Ignore<W>
function new (line 44) | pub fn new(writer: W) -> Self {
function free (line 49) | pub fn free(self) -> W {
type Error (line 58) | type Error = Infallible;
method write_str (line 60) | fn write_str(&mut self, s: &str) -> Result<(), Infallible> {
type LineBuffered (line 67) | pub struct LineBuffered<W, N>
function new (line 82) | pub fn new(writer: W) -> Self {
function flush (line 90) | pub fn flush(&mut self) -> Result<(), W::Error> {
function free (line 97) | pub fn free(self) -> W {
function push_str (line 101) | fn push_str(&mut self, s: &str) -> Result<(), W::Error> {
type Error (line 124) | type Error = W::Error;
method write_str (line 126) | fn write_str(&mut self, mut s: &str) -> Result<(), W::Error> {
type WriteAdapter (line 159) | pub struct WriteAdapter<W>(pub W) where W: fmt::Write;
type Error (line 162) | type Error = fmt::Error;
method write_char (line 164) | fn write_char(&mut self, c: char) -> Result<(), Self::Error> {
method write_str (line 168) | fn write_str(&mut self, s: &str) -> Result<(), Self::Error> {
FILE: ufmt/write/src/lib.rs
type uWrite (line 14) | pub trait uWrite {
method write_str (line 22) | fn write_str(&mut self, s: &str) -> Result<(), Self::Error>;
method write_char (line 29) | fn write_char(&mut self, c: char) -> Result<(), Self::Error> {
type Error (line 37) | type Error = Infallible;
method write_str (line 39) | fn write_str(&mut self, s: &str) -> Result<(), Infallible> {
FILE: unittest/src/allow_db.rs
type AllowDb (line 24) | pub struct AllowDb {
method insert_raw (line 38) | unsafe fn insert_raw(
method insert_ro_buffer (line 85) | pub unsafe fn insert_ro_buffer(
method insert_rw_buffer (line 110) | pub unsafe fn insert_rw_buffer(
method remove_ro_buffer (line 132) | pub fn remove_ro_buffer(&mut self, buffer: RoAllowBuffer) -> (Register...
method remove_rw_buffer (line 142) | pub fn remove_rw_buffer(&mut self, buffer: RwAllowBuffer) -> (Register...
type OverlapError (line 150) | pub struct OverlapError;
type RoAllowBuffer (line 156) | pub struct RoAllowBuffer {
type Target (line 177) | type Target = [u8];
method deref (line 178) | fn deref(&self) -> &[u8] {
method default (line 165) | fn default() -> RoAllowBuffer {
type RwAllowBuffer (line 192) | pub struct RwAllowBuffer {
type Target (line 213) | type Target = [u8];
method deref (line 214) | fn deref(&self) -> &[u8] {
method deref_mut (line 226) | fn deref_mut(&mut self) -> &mut [u8] {
method default (line 201) | fn default() -> RwAllowBuffer {
FILE: unittest/src/allow_db_test.rs
function insert_ro_slice (line 10) | unsafe fn insert_ro_slice(
function insert_rw_slice (line 23) | unsafe fn insert_rw_slice(
function remove_ro_check (line 34) | fn remove_ro_check(db: &mut AllowDb, buffer: RoAllowBuffer, slice: &[Cel...
function remove_rw_check (line 44) | fn remove_rw_check(db: &mut AllowDb, buffer: RwAllowBuffer, slice: &[Cel...
function allow_db (line 53) | fn allow_db() {
FILE: unittest/src/command_return.rs
function failure (line 5) | pub fn failure(error_code: ErrorCode) -> CommandReturn {
function failure_u32 (line 11) | pub fn failure_u32(error_code: ErrorCode, value: u32) -> CommandReturn {
function failure_2_u32 (line 17) | pub fn failure_2_u32(error_code: ErrorCode, value0: u32, value1: u32) ->...
function failure_u64 (line 30) | pub fn failure_u64(error_code: ErrorCode, value: u64) -> CommandReturn {
function success (line 43) | pub fn success() -> CommandReturn {
function success_u32 (line 49) | pub fn success_u32(value: u32) -> CommandReturn {
function success_2_u32 (line 55) | pub fn success_2_u32(value0: u32, value1: u32) -> CommandReturn {
function success_u64 (line 61) | pub fn success_u64(value: u64) -> CommandReturn {
function success_3_u32 (line 74) | pub fn success_3_u32(value0: u32, value1: u32, value2: u32) -> CommandRe...
function success_u32_u64 (line 80) | pub fn success_u32_u64(value0: u32, value1: u64) -> CommandReturn {
function failure_test (line 98) | fn failure_test() {
function failure_u32_test (line 106) | fn failure_u32_test() {
function failure_2_u32_test (line 114) | fn failure_2_u32_test() {
function failure_u64_test (line 122) | fn failure_u64_test() {
function success_test (line 130) | fn success_test() {
function success_u32_test (line 135) | fn success_u32_test() {
function success_2_u32_test (line 140) | fn success_2_u32_test() {
function success_u64_test (line 145) | fn success_u64_test() {
function success_3_u32_test (line 153) | fn success_3_u32_test() {
function success_u32_u64_test (line 158) | fn success_u32_u64_test() {
FILE: unittest/src/driver_info.rs
type DriverInfo (line 5) | pub struct DriverInfo {
method new (line 18) | pub fn new(driver_num: u32) -> Self {
method upcall_count (line 41) | pub fn upcall_count(mut self, upcall_count: u32) -> Self {
FILE: unittest/src/exit_test/mod.rs
function exit_test (line 60) | pub fn exit_test<F: FnOnce() + UnwindSafe>(test_name: &str, fcn: F) -> E...
type ExitCall (line 73) | pub enum ExitCall {
method fmt (line 89) | fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Err...
type Err (line 99) | type Err = ParseExitError;
method from_str (line 101) | fn from_str(s: &str) -> Result<ExitCall, ParseExitError> {
function signal_exit (line 83) | pub(crate) fn signal_exit(exit_call: ExitCall) {
type ParseExitError (line 117) | pub struct ParseExitError;
constant SIGNAL_VAR (line 123) | const SIGNAL_VAR: &str = "LIBTOCK_UNITTEST_EXIT_TEST";
constant EXIT_STRING (line 127) | const EXIT_STRING: &str = "LIBTOCK_UNITTEST_EXIT_TEST_RESULT: ";
type ExitMessage (line 130) | enum ExitMessage {
method fmt (line 137) | fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Err...
type Err (line 147) | type Err = ParseExitError;
method from_str (line 149) | fn from_str(s: &str) -> Result<ExitMessage, ParseExitError> {
function spawn_test (line 166) | fn spawn_test(test_name: &str) -> ExitCall {
function signal_message (line 201) | fn signal_message(message: ExitMessage) {
function run_test (line 209) | fn run_test<F: FnOnce() + UnwindSafe>(signal_var: std::ffi::OsString, fc...
FILE: unittest/src/exit_test/tests.rs
function exitcall_display (line 4) | fn exitcall_display() {
function exitcall_parse (line 10) | fn exitcall_parse() {
function exitmessage_display (line 23) | fn exitmessage_display() {
function exitmessage_parse (line 33) | fn exitmessage_parse() {
function exit_test_did_not_exit (line 56) | fn exit_test_did_not_exit() {
function exit_test_did_not_signal (line 62) | fn exit_test_did_not_signal() {
function exit_test_signal_terminate (line 69) | fn exit_test_signal_terminate() {
function exit_test_signal_restart (line 78) | fn exit_test_signal_restart() {
function exit_test_wrong_case (line 88) | fn exit_test_wrong_case() {
FILE: unittest/src/expected_syscall.rs
type ExpectedSyscall (line 8) | pub enum ExpectedSyscall {
method panic_wrong_call (line 94) | pub(crate) fn panic_wrong_call(&self, called: &str) -> ! {
FILE: unittest/src/fake/adc/mod.rs
type Adc (line 14) | pub struct Adc {
method new (line 21) | pub fn new() -> std::rc::Rc<Adc> {
method is_busy (line 29) | pub fn is_busy(&self) -> bool {
method set_value (line 32) | pub fn set_value(&self, value: i32) {
method set_value_sync (line 40) | pub fn set_value_sync(&self, value: i32) {
method info (line 46) | fn info(&self) -> DriverInfo {
method register (line 50) | fn register(&self, share_ref: DriverShareRef) {
method command (line 54) | fn command(&self, command_id: u32, _argument0: u32, _argument1: u32) -...
constant DRIVER_NUM (line 79) | const DRIVER_NUM: u32 = 0x5;
constant EXISTS (line 83) | const EXISTS: u32 = 0;
constant SINGLE_SAMPLE (line 84) | const SINGLE_SAMPLE: u32 = 1;
FILE: unittest/src/fake/adc/tests.rs
function command (line 7) | fn command() {
function kernel_integration (line 31) | fn kernel_integration() {
FILE: unittest/src/fake/air_quality/mod.rs
type AirQuality (line 5) | pub struct AirQuality {
method new (line 15) | pub fn new() -> std::rc::Rc<AirQuality> {
method set_co2_available (line 26) | pub fn set_co2_available(&self, co2_available: bool) {
method set_tvoc_available (line 30) | pub fn set_tvoc_available(&self, tvoc_available: bool) {
method is_busy (line 34) | pub fn is_busy(&self) -> bool {
method set_value (line 38) | pub fn set_value(&self, value: u32) {
method set_value_sync (line 46) | pub fn set_value_sync(&self, value: u32) {
method set_values_sync (line 49) | pub fn set_values_sync(&self, co2_value: u32, tvoc_value: u32) {
method info (line 55) | fn info(&self) -> DriverInfo {
method register (line 59) | fn register(&self, share_ref: DriverShareRef) {
method command (line 63) | fn command(&self, command_id: u32, _argument0: u32, _argument1: u32) -...
constant DRIVER_NUM (line 113) | const DRIVER_NUM: u32 = 0x60007;
constant EXISTS (line 117) | const EXISTS: u32 = 0;
constant READ_CO2 (line 118) | const READ_CO2: u32 = 2;
constant READ_TVOC (line 119) | const READ_TVOC: u32 = 3;
FILE: unittest/src/fake/air_quality/tests.rs
function command (line 7) | fn command() {
function kernel_integration (line 52) | fn kernel_integration() {
FILE: unittest/src/fake/alarm/mod.rs
type Alarm (line 12) | pub struct Alarm {
method new (line 19) | pub fn new(frequency_hz: u32) -> std::rc::Rc<Alarm> {
method info (line 29) | fn info(&self) -> DriverInfo {
method register (line 33) | fn register(&self, share_ref: DriverShareRef) {
method command (line 37) | fn command(&self, command_number: u32, argument0: u32, _argument1: u32...
constant DRIVER_NUM (line 65) | const DRIVER_NUM: u32 = 0x0;
constant EXISTS (line 70) | pub const EXISTS: u32 = 0;
constant FREQUENCY (line 71) | pub const FREQUENCY: u32 = 1;
constant TIME (line 72) | pub const TIME: u32 = 2;
constant STOP (line 73) | pub const STOP: u32 = 3;
constant SET_RELATIVE (line 75) | pub const SET_RELATIVE: u32 = 5;
constant SET_ABSOLUTE (line 76) | pub const SET_ABSOLUTE: u32 = 6;
constant CALLBACK (line 81) | pub const CALLBACK: u32 = 0;
FILE: unittest/src/fake/alarm/tests.rs
function command (line 6) | fn command() {
FILE: unittest/src/fake/ambient_light/mod.rs
type AmbientLight (line 15) | pub struct AmbientLight {
method new (line 22) | pub fn new() -> std::rc::Rc<AmbientLight> {
method is_busy (line 30) | pub fn is_busy(&self) -> bool {
method set_value (line 33) | pub fn set_value(&self, value: u32) {
method set_value_sync (line 41) | pub fn set_value_sync(&self, value: u32) {
method info (line 47) | fn info(&self) -> DriverInfo {
method register (line 51) | fn register(&self, share_ref: DriverShareRef) {
method command (line 55) | fn command(&self, command_id: u32, _argument0: u32, _argument1: u32) -...
constant DRIVER_NUM (line 80) | const DRIVER_NUM: u32 = 0x60002;
constant EXISTS (line 84) | const EXISTS: u32 = 0;
constant READ_INTENSITY (line 85) | const READ_INTENSITY: u32 = 1;
FILE: unittest/src/fake/ambient_light/tests.rs
function command (line 7) | fn command() {
function kernel_integration (line 31) | fn kernel_integration() {
FILE: unittest/src/fake/buttons/mod.rs
type ButtonState (line 16) | pub struct ButtonState {
type Buttons (line 21) | pub struct Buttons<const NUM_BUTTONS: usize> {
function new (line 27) | pub fn new() -> std::rc::Rc<Buttons<NUM_BUTTONS>> {
function set_pressed (line 39) | pub fn set_pressed(&self, button: u32, pressed: bool) -> Result<(), Erro...
function get_button_state (line 59) | pub fn get_button_state(&self, button: u32) -> Option<ButtonState> {
function info (line 65) | fn info(&self) -> DriverInfo {
function register (line 69) | fn register(&self, share_ref: DriverShareRef) {
function command (line 73) | fn command(&self, command_number: u32, argument0: u32, _argument1: u32) ...
constant DRIVER_NUM (line 121) | const DRIVER_NUM: u32 = 0x3;
constant BUTTONS_COUNT (line 124) | const BUTTONS_COUNT: u32 = 0;
constant BUTTONS_ENABLE_INTERRUPTS (line 126) | const BUTTONS_ENABLE_INTERRUPTS: u32 = 1;
constant BUTTONS_DISABLE_INTERRUPTS (line 127) | const BUTTONS_DISABLE_INTERRUPTS: u32 = 2;
constant BUTTONS_READ (line 129) | const BUTTONS_READ: u32 = 3;
FILE: unittest/src/fake/buttons/tests.rs
function command (line 7) | fn command() {
function kernel_integration (line 87) | fn kernel_integration() {
FILE: unittest/src/fake/buzzer/mod.rs
type Buzzer (line 15) | pub struct Buzzer {
method new (line 22) | pub fn new() -> std::rc::Rc<Buzzer> {
method is_busy (line 30) | pub fn is_busy(&self) -> bool {
method set_tone (line 34) | pub fn set_tone(&self, freq: i32, duration: Duration) {
method set_tone_sync (line 43) | pub fn set_tone_sync(&self, freq: i32, duration: i32) {
method info (line 50) | fn info(&self) -> DriverInfo {
method register (line 54) | fn register(&self, share_ref: DriverShareRef) {
method command (line 58) | fn command(&self, command_num: u32, _argument0: u32, _argument1: u32) ...
constant DRIVER_NUM (line 85) | const DRIVER_NUM: u32 = 0x90000;
constant EXISTS (line 88) | const EXISTS: u32 = 0;
constant TONE (line 89) | const TONE: u32 = 1;
FILE: unittest/src/fake/buzzer/tests.rs
function command (line 6) | fn command() {
function kernel_integration (line 26) | fn kernel_integration() {
FILE: unittest/src/fake/console/mod.rs
type Console (line 14) | pub struct Console {
method new (line 26) | pub fn new() -> std::rc::Rc<Console> {
method new_with_input (line 30) | pub fn new_with_input(inputs: &[u8]) -> std::rc::Rc<Console> {
method take_bytes (line 42) | pub fn take_bytes(&self) -> Vec<u8> {
method info (line 48) | fn info(&self) -> DriverInfo {
method register (line 52) | fn register(&self, share_ref: DriverShareRef) {
method allow_readonly (line 56) | fn allow_readonly(
method allow_readwrite (line 68) | fn allow_readwrite(
method command (line 80) | fn command(&self, command_num: u32, argument0: u32, _argument1: u32) -...
constant DRIVER_NUM (line 121) | const DRIVER_NUM: u32 = 0x1;
constant EXISTS (line 124) | const EXISTS: u32 = 0;
constant WRITE (line 125) | const WRITE: u32 = 1;
constant READ (line 126) | const READ: u32 = 2;
constant SUBSCRIBE_WRITE (line 128) | const SUBSCRIBE_WRITE: u32 = 1;
constant SUBSCRIBE_READ (line 129) | const SUBSCRIBE_READ: u32 = 2;
constant ALLOW_WRITE (line 130) | const ALLOW_WRITE: u32 = 1;
constant ALLOW_READ (line 131) | const ALLOW_READ: u32 = 1;
FILE: unittest/src/fake/console/tests.rs
function command (line 8) | fn command() {
function kernel_integration (line 24) | fn kernel_integration() {
FILE: unittest/src/fake/gpio/mod.rs
type GpioMode (line 17) | pub enum GpioMode {
type PullMode (line 24) | pub enum PullMode {
type Error (line 31) | type Error = ErrorCode;
method try_from (line 33) | fn try_from(value: u32) -> Result<Self, Self::Error> {
type InterruptEdge (line 44) | pub enum InterruptEdge {
type Error (line 51) | type Error = ErrorCode;
method try_from (line 53) | fn try_from(value: u32) -> Result<Self, Self::Error> {
type GpioState (line 64) | pub struct GpioState {
type Gpio (line 70) | pub struct Gpio<const NUM_GPIOS: usize> {
function new (line 76) | pub fn new() -> std::rc::Rc<Gpio<NUM_GPIOS>> {
function set_missing_gpio (line 89) | pub fn set_missing_gpio(&self, gpio: usize) {
function set_value (line 95) | pub fn set_value(&self, pin: u32, value: bool) -> Result<(), ErrorCode> {
function get_gpio_state (line 131) | pub fn get_gpio_state(&self, button: u32) -> Option<GpioState> {
function info (line 140) | fn info(&self) -> DriverInfo {
function register (line 144) | fn register(&self, share_ref: DriverShareRef) {
function command (line 148) | fn command(&self, command_number: u32, argument0: u32, argument1: u32) -...
constant DRIVER_NUM (line 256) | const DRIVER_NUM: u32 = 0x4;
constant EXISTS (line 259) | const EXISTS: u32 = 0;
constant GPIO_ENABLE_OUTPUT (line 261) | const GPIO_ENABLE_OUTPUT: u32 = 1;
constant GPIO_SET (line 262) | const GPIO_SET: u32 = 2;
constant GPIO_CLEAR (line 263) | const GPIO_CLEAR: u32 = 3;
constant GPIO_TOGGLE (line 264) | const GPIO_TOGGLE: u32 = 4;
constant GPIO_ENABLE_INPUT (line 266) | const GPIO_ENABLE_INPUT: u32 = 5;
constant GPIO_READ_INPUT (line 267) | const GPIO_READ_INPUT: u32 = 6;
constant GPIO_ENABLE_INTERRUPTS (line 269) | const GPIO_ENABLE_INTERRUPTS: u32 = 7;
constant GPIO_DISABLE_INTERRUPTS (line 270) | const GPIO_DISABLE_INTERRUPTS: u32 = 8;
constant GPIO_DISABLE (line 272) | const GPIO_DISABLE: u32 = 9;
constant GPIO_COUNT (line 274) | const GPIO_COUNT: u32 = 10;
FILE: unittest/src/fake/gpio/tests.rs
function command (line 7) | fn command() {
function kernel_integration (line 180) | fn kernel_integration() {
FILE: unittest/src/fake/ieee802154/mod.rs
constant MAX_MTU (line 15) | const MAX_MTU: usize = 127;
constant PSDU_OFFSET (line 17) | const PSDU_OFFSET: usize = 2;
type Frame (line 21) | pub struct Frame {
method with_body (line 29) | pub fn with_body(body: &[u8]) -> Self {
type Ieee802154Phy (line 44) | pub struct Ieee802154Phy {
method instance (line 68) | pub fn instance() -> Option<Rc<Self>> {
method new (line 72) | pub fn new() -> Rc<Self> {
method new_with_frames_to_be_received (line 78) | pub fn new_with_frames_to_be_received(
method take_transmitted_frames (line 96) | pub fn take_transmitted_frames(&self) -> Vec<Vec<u8>> {
method has_pending_rx_frames (line 100) | pub fn has_pending_rx_frames(&self) -> bool {
method radio_receive_frame (line 110) | pub fn radio_receive_frame(&self, frame: Frame) {
method driver_receive_pending_frames (line 114) | pub fn driver_receive_pending_frames(&self) {
method driver_receive_frame (line 120) | fn driver_receive_frame(&self, frame: &[u8]) {
method phy_driver_receive_frame (line 126) | fn phy_driver_receive_frame(rbuf: &mut [u8], frame: &[u8]) {
method trigger_rx_upcall (line 221) | pub fn trigger_rx_upcall(&self) {
method info (line 229) | fn info(&self) -> DriverInfo {
method register (line 233) | fn register(&self, share_ref: DriverShareRef) {
method command (line 237) | fn command(&self, command_number: u32, argument0: u32, argument1: u32)...
method allow_readonly (line 299) | fn allow_readonly(
method allow_readwrite (line 311) | fn allow_readwrite(
constant DRIVER_NUM (line 332) | const DRIVER_NUM: u32 = 0x30001;
constant EXISTS (line 355) | pub const EXISTS: u32 = 0;
constant STATUS (line 356) | pub const STATUS: u32 = 1;
constant SET_SHORT_ADDR (line 357) | pub const SET_SHORT_ADDR: u32 = 2;
constant SET_PAN (line 358) | pub const SET_PAN: u32 = 4;
constant SET_CHAN (line 359) | pub const SET_CHAN: u32 = 5;
constant SET_TX_PWR (line 360) | pub const SET_TX_PWR: u32 = 6;
constant COMMIT_CFG (line 361) | pub const COMMIT_CFG: u32 = 7;
constant GET_SHORT_ADDR (line 362) | pub const GET_SHORT_ADDR: u32 = 8;
constant GET_PAN (line 363) | pub const GET_PAN: u32 = 10;
constant GET_CHAN (line 364) | pub const GET_CHAN: u32 = 11;
constant GET_TX_PWR (line 365) | pub const GET_TX_PWR: u32 = 12;
constant TRANSMIT (line 366) | pub const TRANSMIT: u32 = 27;
constant SET_LONG_ADDR (line 367) | pub const SET_LONG_ADDR: u32 = 28;
constant GET_LONG_ADDR (line 368) | pub const GET_LONG_ADDR: u32 = 29;
constant TURN_ON (line 369) | pub const TURN_ON: u32 = 30;
constant TURN_OFF (line 370) | pub const TURN_OFF: u32 = 31;
constant FRAME_RECEIVED (line 375) | pub const FRAME_RECEIVED: u32 = 0;
constant FRAME_TRANSMITTED (line 377) | pub const FRAME_TRANSMITTED: u32 = 1;
constant WRITE (line 383) | pub const WRITE: u32 = 0;
constant READ (line 389) | pub const READ: u32 = 0;
FILE: unittest/src/fake/kernel.rs
type Kernel (line 15) | pub struct Kernel {
method new (line 31) | pub fn new() -> Kernel {
method add_driver (line 60) | pub fn add_driver<D: crate::fake::SyscallDriver>(&self, driver: &std::...
method add_expected_syscall (line 99) | pub fn add_expected_syscall(&self, expected_syscall: ExpectedSyscall) {
method take_syscall_log (line 109) | pub fn take_syscall_log(&self) -> Vec<SyscallLogEntry> {
method is_driver_present (line 114) | pub fn is_driver_present(driver_num: u32) -> bool {
method is_upcall_pending (line 121) | pub fn is_upcall_pending() -> bool {
method drop (line 129) | fn drop(&mut self) {
FILE: unittest/src/fake/kernel_tests.rs
function expected_syscall_queue (line 5) | fn expected_syscall_queue() {
function syscall_log (line 36) | fn syscall_log() {
FILE: unittest/src/fake/key_value/mod.rs
type KeyValue (line 9) | pub struct KeyValue {
method new (line 21) | pub fn new() -> std::rc::Rc<KeyValue> {
method info (line 35) | fn info(&self) -> DriverInfo {
method register (line 39) | fn register(&self, share_ref: DriverShareRef) {
method allow_readonly (line 43) | fn allow_readonly(
method allow_readwrite (line 55) | fn allow_readwrite(
method command (line 66) | fn command(&self, command_id: u32, _argument0: u32, _argument1: u32) -...
constant DRIVER_NUM (line 211) | const DRIVER_NUM: u32 = 0x50003;
constant CMD_DRIVER_CHECK (line 215) | const CMD_DRIVER_CHECK: u32 = 0;
constant CMD_GET (line 216) | const CMD_GET: u32 = 1;
constant CMD_SET (line 217) | const CMD_SET: u32 = 2;
constant CMD_DELETE (line 218) | const CMD_DELETE: u32 = 3;
constant CMD_ADD (line 219) | const CMD_ADD: u32 = 4;
constant CMD_UPDATE (line 220) | const CMD_UPDATE: u32 = 5;
constant RO_ALLOW_KEY (line 222) | const RO_ALLOW_KEY: u32 = 0;
constant RO_ALLOW_VAL (line 223) | const RO_ALLOW_VAL: u32 = 1;
constant RW_ALLOW_VAL (line 224) | const RW_ALLOW_VAL: u32 = 0;
constant SUB_CALLBACK (line 226) | const SUB_CALLBACK: u32 = 0;
FILE: unittest/src/fake/leds/mod.rs
type Leds (line 11) | pub struct Leds<const LEDS_COUNT: usize> {
function new (line 16) | pub fn new() -> std::rc::Rc<Leds<LEDS_COUNT>> {
function get_led (line 24) | pub fn get_led(&self, led: u32) -> Option<bool> {
function info (line 30) | fn info(&self) -> DriverInfo {
function command (line 34) | fn command(&self, command_num: u32, argument0: u32, _argument1: u32) -> ...
constant DRIVER_NUM (line 73) | const DRIVER_NUM: u32 = 0x2;
constant EXISTS (line 76) | const EXISTS: u32 = 0;
constant LED_ON (line 77) | const LED_ON: u32 = 1;
constant LED_OFF (line 78) | const LED_OFF: u32 = 2;
constant LED_TOGGLE (line 79) | const LED_TOGGLE: u32 = 3;
FILE: unittest/src/fake/leds/tests.rs
function command (line 7) | fn command() {
function kernel_integration (line 30) | fn kernel_integration() {
FILE: unittest/src/fake/low_level_debug/mod.rs
type LowLevelDebug (line 11) | pub struct LowLevelDebug {
method new (line 16) | pub fn new() -> std::rc::Rc<LowLevelDebug> {
method take_messages (line 24) | pub fn take_messages(&self) -> Vec<Message> {
method info (line 30) | fn info(&self) -> DriverInfo {
method command (line 34) | fn command(&self, command_num: u32, argument0: u32, argument1: u32) ->...
method handle_message (line 85) | fn handle_message(&self, message: Message) {
type Message (line 47) | pub enum Message {
method fmt (line 54) | fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
constant DRIVER_NUM (line 72) | const DRIVER_NUM: u32 = 0x8;
constant EXISTS (line 75) | const EXISTS: u32 = 0;
constant PRINT_ALERT_CODE (line 76) | const PRINT_ALERT_CODE: u32 = 1;
constant PRINT_1 (line 77) | const PRINT_1: u32 = 2;
constant PRINT_2 (line 78) | const PRINT_2: u32 = 3;
constant PANIC (line 81) | const PANIC: u32 = 0x01;
constant WRONG_LOCATION (line 82) | const WRONG_LOCATION: u32 = 0x02;
function alert_description (line 97) | fn alert_description(code: u32) -> &'static str {
FILE: unittest/src/fake/low_level_debug/tests.rs
function command (line 6) | fn command() {
function kernel_integration (line 23) | fn kernel_integration() {
function message_display (line 41) | fn message_display() {
FILE: unittest/src/fake/ninedof/mod.rs
type NineDof (line 11) | pub struct NineDof {
method new (line 24) | pub fn new() -> std::rc::Rc<NineDof> {
method is_busy (line 32) | pub fn is_busy(&self) -> bool {
method set_value (line 35) | pub fn set_value(&self, value: NineDofData) {
method set_value_sync (line 43) | pub fn set_value_sync(&self, value: NineDofData) {
method info (line 49) | fn info(&self) -> DriverInfo {
method register (line 53) | fn register(&self, share_ref: DriverShareRef) {
method command (line 57) | fn command(&self, command_id: u32, _argument0: u32, _argument1: u32) -...
type NineDofData (line 17) | pub struct NineDofData {
constant DRIVER_NUM (line 103) | const DRIVER_NUM: u32 = 0x60004;
constant EXISTS (line 106) | const EXISTS: u32 = 0;
constant READ_ACCELEROMETER (line 107) | const READ_ACCELEROMETER: u32 = 1;
constant READ_MAGNETOMETER (line 108) | const READ_MAGNETOMETER: u32 = 100;
constant READ_GYRO (line 109) | const READ_GYRO: u32 = 200;
FILE: unittest/src/fake/ninedof/tests.rs
function command (line 7) | fn command() {
function kernel_integration (line 33) | fn kernel_integration() {
FILE: unittest/src/fake/proximity/mod.rs
type ProximityCommand (line 14) | pub enum ProximityCommand {
type Thresholds (line 20) | pub struct Thresholds {
type Proximity (line 28) | pub struct Proximity {
method new (line 36) | pub fn new() -> std::rc::Rc<Proximity> {
method set_value (line 45) | pub fn set_value(&self, value: u8) {
method set_value_sync (line 64) | pub fn set_value_sync(&self, value: u8) {
method info (line 70) | fn info(&self) -> DriverInfo {
method register (line 74) | fn register(&self, share_ref: DriverShareRef) {
method command (line 78) | fn command(&self, command_id: u32, argument0: u32, argument1: u32) -> ...
constant DRIVER_NUM (line 118) | const DRIVER_NUM: u32 = 0x60005;
constant EXISTS (line 122) | const EXISTS: u32 = 0;
constant READ (line 123) | const READ: u32 = 1;
constant READ_ON_INT (line 124) | const READ_ON_INT: u32 = 2;
FILE: unittest/src/fake/proximity/tests.rs
function command (line 7) | fn command() {
function kernel_integration (line 45) | fn kernel_integration() {
FILE: unittest/src/fake/screen/mod.rs
type Screen (line 5) | pub struct Screen {
method new (line 24) | pub fn new() -> std::rc::Rc<Screen> {
method take_bytes (line 52) | pub fn take_bytes(&self) -> Vec<u8> {
method is_buffer_length_valid (line 57) | fn is_buffer_length_valid(&self, buffer_len: usize) -> bool {
method write (line 70) | fn write(&self, buffer: &[u8]) -> Result<(), ErrorCode> {
method fill (line 82) | fn fill(&self, _color: u16) -> Result<(), ErrorCode> {
method info (line 91) | fn info(&self) -> DriverInfo {
method register (line 95) | fn register(&self, share_ref: DriverShareRef) {
method allow_readonly (line 99) | fn allow_readonly(
method command (line 112) | fn command(&self, command_num: u32, argument0: u32, argument1: u32) ->...
constant DRIVER_NUM (line 310) | const DRIVER_NUM: u32 = 0x90001;
constant WRITE_BUFFER_ID (line 311) | const WRITE_BUFFER_ID: u32 = 0;
constant EXISTS (line 315) | pub const EXISTS: u32 = 0;
constant SCREEN_SETUP (line 316) | pub const SCREEN_SETUP: u32 = 1;
constant SET_POWER (line 317) | pub const SET_POWER: u32 = 2;
constant SET_BRIGHTNESS (line 318) | pub const SET_BRIGHTNESS: u32 = 3;
constant SET_INVERT_ON (line 319) | pub const SET_INVERT_ON: u32 = 4;
constant SET_INVERT_OFF (line 320) | pub const SET_INVERT_OFF: u32 = 5;
constant SET_INVERT (line 321) | pub const SET_INVERT: u32 = 6;
constant GET_RESOLUTION_MODES_COUNT (line 322) | pub const GET_RESOLUTION_MODES_COUNT: u32 = 11;
constant GET_RESOLUTION_WIDTH_HEIGHT (line 323) | pub const GET_RESOLUTION_WIDTH_HEIGHT: u32 = 12;
constant PIXEL_MODES_COUNT (line 324) | pub const PIXEL_MODES_COUNT: u32 = 13;
constant PIXEL_FORMAT (line 325) | pub const PIXEL_FORMAT: u32 = 14;
constant GET_ROTATION (line 326) | pub const GET_ROTATION: u32 = 21;
constant SET_ROTATION (line 327) | pub const SET_ROTATION: u32 = 22;
constant GET_RESOLUTION (line 328) | pub const GET_RESOLUTION: u32 = 23;
constant SET_RESOLUTION (line 329) | pub const SET_RESOLUTION: u32 = 24;
constant GET_PIXEL_FORMAT (line 330) | pub const GET_PIXEL_FORMAT: u32 = 25;
constant SET_PIXEL_FORMAT (line 331) | pub const SET_PIXEL_FORMAT: u32 = 26;
constant SET_WRITE_FRAME (line 332) | pub const SET_WRITE_FRAME: u32 = 100;
constant WRITE (line 333) | pub const WRITE: u32 = 200;
constant FILL (line 334) | pub const FILL: u32 = 300;
constant GET_POWER (line 335) | pub const GET_POWER: u32 = 400;
constant GET_BRIGHTNESS (line 336) | pub const GET_BRIGHTNESS: u32 = 401;
constant GET_INVERT (line 337) | pub const GET_INVERT: u32 = 402;
constant GET_WRITE_FRAME (line 338) | pub const GET_WRITE_FRAME: u32 = 403;
FILE: unittest/src/fake/screen/tests.rs
function command (line 10) | fn command() {
function kernel_integration (line 98) | fn kernel_integration() {
FILE: unittest/src/fake/sound_pressure/mod.rs
type SoundPressure (line 13) | pub struct SoundPressure {
method new (line 20) | pub fn new() -> std::rc::Rc<SoundPressure> {
method is_busy (line 28) | pub fn is_busy(&self) -> bool {
method set_value (line 32) | pub fn set_value(&self, value: u8) {
method set_value_sync (line 41) | pub fn set_value_sync(&self, value: u8) {
method info (line 47) | fn info(&self) -> DriverInfo {
method register (line 51) | fn register(&self, share_ref: DriverShareRef) {
method command (line 55) | fn command(&self, command_id: u32, _argument0: u32, _argument1: u32) -...
constant DRIVER_NUM (line 80) | const DRIVER_NUM: u32 = 0x60006;
constant EXISTS (line 83) | const EXISTS: u32 = 0;
constant READ_PRESSURE (line 84) | const READ_PRESSURE: u32 = 1;
FILE: unittest/src/fake/sound_pressure/tests.rs
function command (line 7) | fn command() {
function kernel_integration (line 31) | fn kernel_integration() {
FILE: unittest/src/fake/syscall_driver.rs
type SyscallDriver (line 7) | pub trait SyscallDriver: 'static {
method info (line 13) | fn info(&self) -> DriverInfo;
method register (line 18) | fn register(&self, share_ref: DriverShareRef) {
method command (line 28) | fn command(&self, command_id: u32, argument0: u32, argument1: u32) -> ...
method allow_readonly (line 37) | fn allow_readonly(
method allow_readwrite (line 49) | fn allow_readwrite(
FILE: unittest/src/fake/syscalls/allow_ro_impl.rs
function allow_ro (line 6) | pub(super) unsafe fn allow_ro(
FILE: unittest/src/fake/syscalls/allow_ro_impl_tests.rs
function expected_wrong (line 16) | fn expected_wrong() {
function no_driver (line 62) | fn no_driver() {
function no_kernel (line 75) | fn no_kernel() {
function syscall_log (line 86) | fn syscall_log() {
function too_large_buffer_number (line 111) | fn too_large_buffer_number() {
function too_large_driver_number (line 130) | fn too_large_driver_number() {
FILE: unittest/src/fake/syscalls/allow_rw_impl.rs
function allow_rw (line 6) | pub(super) unsafe fn allow_rw(
FILE: unittest/src/fake/syscalls/allow_rw_impl_tests.rs
function expected_wrong (line 16) | fn expected_wrong() {
function no_driver (line 62) | fn no_driver() {
function no_kernel (line 75) | fn no_kernel() {
function syscall_log (line 86) | fn syscall_log() {
function too_large_buffer_number (line 111) | fn too_large_buffer_number() {
function too_large_driver_number (line 130) | fn too_large_driver_number() {
FILE: unittest/src/fake/syscalls/command_impl.rs
function command (line 8) | pub(super) fn command(
FILE: unittest/src/fake/syscalls/command_impl_tests.rs
function driver_support (line 13) | fn driver_support() {
function expected_wrong_command (line 54) | fn expected_wrong_command() {
function no_kernel (line 102) | fn no_kernel() {
function override_return (line 112) | fn override_return() {
function syscall4 (line 138) | fn syscall4() {
function too_large_argument0 (line 161) | fn too_large_argument0() {
function too_large_argument1 (line 180) | fn too_large_argument1() {
function too_large_command_id (line 199) | fn too_large_command_id() {
function too_large_driver_id (line 218) | fn too_large_driver_id() {
FILE: unittest/src/fake/syscalls/exit_impl.rs
function exit (line 3) | pub(super) fn exit(r0: libtock_platform::Register, r1: libtock_platform:...
FILE: unittest/src/fake/syscalls/exit_impl_tests.rs
function exit_restart (line 5) | fn exit_restart() {
function exit_terminate (line 13) | fn exit_terminate() {
FILE: unittest/src/fake/syscalls/memop_impl.rs
function memop (line 8) | pub(super) fn memop(memop_num: Register, argument0: Register) -> [Regist...
FILE: unittest/src/fake/syscalls/memop_impl_tests.rs
function expected_wrong_memop (line 9) | fn expected_wrong_memop() {
function no_kernel (line 33) | fn no_kernel() {
function return_error (line 43) | fn return_error() {
function too_large_memop_num (line 60) | fn too_large_memop_num() {
function memop_using_syscall1 (line 71) | fn memop_using_syscall1() {
FILE: unittest/src/fake/syscalls/mod.rs
type Syscalls (line 13) | pub struct Syscalls;
function assert_valid (line 36) | fn assert_valid<T: core::fmt::Debug>(_value: T) {
FILE: unittest/src/fake/syscalls/raw_syscalls_impl.rs
method yield1 (line 5) | unsafe fn yield1([r0]: [Register; 1]) {
method yield2 (line 14) | unsafe fn yield2([r0, r1]: [Register; 2]) {
method syscall1 (line 28) | unsafe fn syscall1<const CLASS: usize>([r0]: [Register; 1]) -> [Register...
method syscall2 (line 35) | unsafe fn syscall2<const CLASS: usize>([r0, r1]: [Register; 2]) -> [Regi...
method syscall4 (line 44) | unsafe fn syscall4<const CLASS: usize>([r0, r1, r2, r3]: [Register; 4]) ...
FILE: unittest/src/fake/syscalls/raw_syscalls_impl_tests.rs
function allow_ro (line 10) | fn allow_ro() {
function allow_rw (line 31) | fn allow_rw() {
function memop (line 56) | fn memop() {
FILE: unittest/src/fake/syscalls/subscribe_impl.rs
function subscribe (line 8) | pub(super) unsafe fn subscribe(
FILE: unittest/src/fake/syscalls/subscribe_impl_tests.rs
function expected_wrong (line 16) | fn expected_wrong() {
function missing_driver (line 61) | fn missing_driver() {
function no_kernel (line 78) | fn no_kernel() {
function skip_with_error (line 90) | fn skip_with_error() {
function syscall4_subscribe (line 124) | fn syscall4_subscribe() {
function too_large_inputs (line 146) | fn too_large_inputs() {
FILE: unittest/src/fake/syscalls/yield_impl.rs
function yield_no_wait (line 10) | pub(super) unsafe fn yield_no_wait(return_ptr: *mut libtock_platform::Yi...
function yield_wait (line 36) | pub(super) fn yield_wait() {
function invoke_next_upcall (line 70) | fn invoke_next_upcall() -> bool {
FILE: unittest/src/fake/syscalls/yield_impl_tests.rs
function copy_args (line 11) | unsafe extern "C" fn copy_args(
function yield_no_wait_test (line 24) | fn yield_no_wait_test() {
function yield_wait_test (line 138) | fn yield_wait_test() {
function yield1 (line 197) | fn yield1() {
function yield2 (line 237) | fn yield2() {
FILE: unittest/src/fake/temperature/mod.rs
type Temperature (line 15) | pub struct Temperature {
method new (line 22) | pub fn new() -> std::rc::Rc<Temperature> {
method is_busy (line 30) | pub fn is_busy(&self) -> bool {
method set_value (line 33) | pub fn set_value(&self, value: i32) {
method set_value_sync (line 41) | pub fn set_value_sync(&self, value: i32) {
method info (line 47) | fn info(&self) -> DriverInfo {
method register (line 51) | fn register(&self, share_ref: DriverShareRef) {
method command (line 55) | fn command(&self, command_id: u32, _argument0: u32, _argument1: u32) -...
constant DRIVER_NUM (line 80) | const DRIVER_NUM: u32 = 0x60000;
constant EXISTS (line 84) | const EXISTS: u32 = 0;
constant READ_TEMP (line 85) | const READ_TEMP: u32 = 1;
FILE: unittest/src/fake/temperature/tests.rs
function command (line 7) | fn command() {
function kernel_integration (line 31) | fn kernel_integration() {
FILE: unittest/src/kernel_data.rs
type KernelData (line 14) | pub(crate) struct KernelData {
function with_kernel_data (line 34) | pub(crate) fn with_kernel_data<F: FnOnce(Option<&mut KernelData>) -> R, ...
type DriverData (line 39) | pub struct DriverData {
FILE: unittest/src/share_data.rs
type DriverShareRef (line 13) | pub struct DriverShareRef {
method replace (line 21) | pub fn replace(&self, new: Self) {
method schedule_upcall (line 28) | pub fn schedule_upcall(
type InvalidSubscribeNum (line 73) | pub struct InvalidSubscribeNum {
type MockDriver (line 88) | struct MockDriver {
method info (line 92) | fn info(&self) -> DriverInfo {
method register (line 95) | fn register(&self, share_ref: DriverShareRef) {
method command (line 98) | fn command(&self, _: u32, _: u32, _: u32) -> libtock_platform::Command...
function schedule_errors (line 104) | fn schedule_errors() {
function schedule_success (line 118) | fn schedule_success() {
FILE: unittest/src/syscall_log.rs
type SyscallLogEntry (line 5) | pub enum SyscallLogEntry {
FILE: unittest/src/upcall.rs
type Upcall (line 4) | pub struct Upcall {
method is_null (line 11) | pub fn is_null(&self) -> bool {
method invoke (line 20) | pub unsafe fn invoke(&self, args: (u32, u32, u32)) {
type UpcallQueue (line 44) | pub(crate) type UpcallQueue = std::collections::VecDeque<UpcallQueueEntry>;
type UpcallQueueEntry (line 47) | pub(crate) struct UpcallQueueEntry {
type UpcallId (line 54) | pub(crate) struct UpcallId {
Condensed preview — 290 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,049K chars).
[
{
"path": ".cargo/config.toml",
"chars": 576,
"preview": "[alias]\nrriscv32imac = \"run --release --target=riscv32imac-unknown-none-elf --example\"\nrrv32imac = \"rriscv32imac\"\nrriscv"
},
{
"path": ".github/workflows/artifacts.yml",
"chars": 1333,
"preview": "name: Artifacts\non:\n push:\n branches: [master]\n\njobs:\n build:\n runs-on: ubuntu-latest\n steps:\n - name: C"
},
{
"path": ".github/workflows/ci.yml",
"chars": 2076,
"preview": "# This workflow provides automated testing. It builds and runs tests on each PR.\n\nname: ci\n\n# We want to run CI on all p"
},
{
"path": ".github/workflows/mac-os.yml",
"chars": 855,
"preview": "# This workflow verifies libtock-rs is usable on Mac OS.\n\nname: ci-mac-os\n\n# We run this workflow during pull request re"
},
{
"path": ".github/workflows/size-diff.yml",
"chars": 2810,
"preview": "# Calculates the size diffs for the each example binary. Runs when a pull\n# request is created or modified.\n\nname: size-"
},
{
"path": ".gitignore",
"chars": 70,
"preview": "/Cargo.lock\n/nightly/target\n/target\n/demos/*/target\n/demos/*/*/target\n"
},
{
"path": ".gitmodules",
"chars": 72,
"preview": "[submodule \"tock\"]\n\tpath = tock\n\turl = https://github.com/tock/tock.git\n"
},
{
"path": ".ignore",
"chars": 387,
"preview": "# Cargo and GitHub Actions keep their configs in hidden directories. Some search\n# tools skip hidden directories by defa"
},
{
"path": ".vscode/settings.json",
"chars": 96,
"preview": "{\n \"editor.formatOnSave\": true,\n \"rust.all_targets\": true,\n \"rust.clippy_preference\": \"on\"\n}\n"
},
{
"path": "CHANGELOG.md",
"chars": 2652,
"preview": "# Releases\n\n## 0.2.0 (WIP)\n\n### Comprehensive Changes\n\n- Many functions are asynchronous\n - To create an `async` main f"
},
{
"path": "CONTRIBUTING.md",
"chars": 496,
"preview": "# Tests\n\nOur aim is to provide a number of tests to be safe from regression.\n\n## Compilation\n\n`libtock-rs` currently has"
},
{
"path": "Cargo.toml",
"chars": 3220,
"preview": "[package]\nauthors = [\"Tock Project Developers <tock-dev@googlegroups.com>\"]\ncategories = [\"embedded\", \"no-std\", \"os\"]\nde"
},
{
"path": "LICENSE-APACHE",
"chars": 11358,
"preview": "\n Apache License\n Version 2.0, January 2004\n "
},
{
"path": "LICENSE-MIT",
"chars": 1071,
"preview": "Copyright (c) 2016 The Tock Project Developers\n\nPermission is hereby granted, free of charge, to any\nperson obtaining a "
},
{
"path": "Makefile",
"chars": 9485,
"preview": "# Make uses /bin/sh by default, which is a different shell on different OSes.\n# Specify Bash instead so we don't have to"
},
{
"path": "README.md",
"chars": 3236,
"preview": "\n\n# libtock-rs\n\nRust userland library for Tock"
},
{
"path": "Targets.mk",
"chars": 3274,
"preview": "# Helper makefile to define build location targets for many common tock\n# platforms.\n#\n# To use:\n#\n# include Targets"
},
{
"path": "apis/display/screen/Cargo.toml",
"chars": 423,
"preview": "[package]\nname = \"libtock_screen\"\nversion = \"0.1.0\"\nauthors = [\"Tock Project Developers <tock-dev@googlegroups.com>\"]\nli"
},
{
"path": "apis/display/screen/src/lib.rs",
"chars": 11210,
"preview": "#![no_std]\nuse core::cell::Cell;\nuse libtock_platform::allow_ro::AllowRo;\nuse libtock_platform::share;\nuse libtock_platf"
},
{
"path": "apis/display/screen/src/tests.rs",
"chars": 10046,
"preview": "use libtock_platform::ErrorCode;\nuse libtock_unittest::{fake, ExpectedSyscall};\n\ntype Screen = super::Screen<fake::Sysca"
},
{
"path": "apis/interface/buttons/Cargo.toml",
"chars": 425,
"preview": "[package]\nname = \"libtock_buttons\"\nversion = \"0.1.0\"\nauthors = [\"Tock Project Developers <tock-dev@googlegroups.com>\"]\nl"
},
{
"path": "apis/interface/buttons/src/lib.rs",
"chars": 4247,
"preview": "#![no_std]\n\nuse libtock_platform::{\n share::Handle, subscribe::OneId, DefaultConfig, ErrorCode, Subscribe, Syscalls, "
},
{
"path": "apis/interface/buttons/src/tests.rs",
"chars": 4343,
"preview": "use core::cell::Cell;\n\nuse libtock_platform::{share, ErrorCode, Syscalls, YieldNoWaitReturn};\nuse libtock_unittest::fake"
},
{
"path": "apis/interface/buzzer/Cargo.toml",
"chars": 423,
"preview": "[package]\nname = \"libtock_buzzer\"\nversion = \"0.1.0\"\nauthors = [\"Tock Project Developers <tock-dev@googlegroups.com>\"]\nli"
},
{
"path": "apis/interface/buzzer/src/lib.rs",
"chars": 3891,
"preview": "//! Implementation started by : https://github.com/teodorobert\n//! Continued and modified by : https://github.com/SheepS"
},
{
"path": "apis/interface/buzzer/src/tests.rs",
"chars": 1049,
"preview": "use core::time::Duration;\nuse libtock_platform::ErrorCode;\nuse libtock_unittest::fake;\n\ntype Buzzer = super::Buzzer<fake"
},
{
"path": "apis/interface/console/Cargo.toml",
"chars": 477,
"preview": "[package]\nname = \"libtock_console\"\nversion = \"0.1.0\"\nauthors = [\n \"Tock Project Developers <tock-dev@googlegroups.com"
},
{
"path": "apis/interface/console/src/lib.rs",
"chars": 4981,
"preview": "#![no_std]\n\nuse core::cell::Cell;\nuse core::fmt;\nuse core::marker::PhantomData;\nuse libtock_platform as platform;\nuse li"
},
{
"path": "apis/interface/console/src/tests.rs",
"chars": 3506,
"preview": "use super::*;\nuse core::fmt::Write;\nuse libtock_platform::ErrorCode;\nuse libtock_unittest::{command_return, fake, Expect"
},
{
"path": "apis/interface/leds/Cargo.toml",
"chars": 419,
"preview": "[package]\nname = \"libtock_leds\"\nversion = \"0.1.0\"\nauthors = [\"Tock Project Developers <tock-dev@googlegroups.com>\"]\nlice"
},
{
"path": "apis/interface/leds/src/lib.rs",
"chars": 1362,
"preview": "#![no_std]\n\nuse libtock_platform::{ErrorCode, Syscalls};\n\n/// The LEDs driver\n///\n/// # Example\n/// ```ignore\n/// use li"
},
{
"path": "apis/interface/leds/src/tests.rs",
"chars": 2050,
"preview": "use libtock_platform::ErrorCode;\nuse libtock_unittest::fake;\n\ntype Leds = super::Leds<fake::Syscalls>;\n\n#[test]\nfn no_dr"
},
{
"path": "apis/kernel/low_level_debug/Cargo.toml",
"chars": 442,
"preview": "[package]\nname = \"libtock_low_level_debug\"\nversion = \"0.1.0\"\nauthors = [\"Tock Project Developers <tock-dev@googlegroups."
},
{
"path": "apis/kernel/low_level_debug/src/lib.rs",
"chars": 2621,
"preview": "#![no_std]\n\nuse libtock_platform::Syscalls;\n\n/// The low-level debug API provides tools to diagnose userspace issues tha"
},
{
"path": "apis/kernel/low_level_debug/src/tests.rs",
"chars": 2156,
"preview": "use super::*;\nuse libtock_platform::ErrorCode;\nuse libtock_unittest::{command_return, fake, ExpectedSyscall};\n\ntype LowL"
},
{
"path": "apis/net/ieee802154/Cargo.toml",
"chars": 451,
"preview": "[package]\nname = \"libtock_ieee802154\"\nversion = \"0.1.0\"\nauthors = [\n \"Tock Project Developers <tock-dev@googlegroups."
},
{
"path": "apis/net/ieee802154/src/lib.rs",
"chars": 8743,
"preview": "//! The raw IEEE 802.15.4 stack driver.\n\n#![no_std]\n\nuse core::cell::Cell;\nuse libtock_platform as platform;\nuse libtock"
},
{
"path": "apis/net/ieee802154/src/rx.rs",
"chars": 5914,
"preview": "use core::marker::PhantomData;\n\nuse super::*;\n\n/// Maximum length of a MAC frame.\nconst MAX_MTU: usize = 127;\n\n#[derive("
},
{
"path": "apis/net/ieee802154/src/tests.rs",
"chars": 9379,
"preview": "use libtock_platform::{RawSyscalls, Register};\nuse libtock_unittest::fake::{self, ieee802154::Frame as FakeFrame, Ieee80"
},
{
"path": "apis/peripherals/adc/Cargo.toml",
"chars": 417,
"preview": "[package]\nname = \"libtock_adc\"\nversion = \"0.1.0\"\nauthors = [\"Tock Project Developers <tock-dev@googlegroups.com>\"]\nlicen"
},
{
"path": "apis/peripherals/adc/src/lib.rs",
"chars": 3381,
"preview": "#![no_std]\n\nuse core::cell::Cell;\nuse libtock_platform::{\n share, subscribe::OneId, DefaultConfig, ErrorCode, Subscri"
},
{
"path": "apis/peripherals/adc/src/tests.rs",
"chars": 2052,
"preview": "use core::cell::Cell;\nuse libtock_platform::{share, ErrorCode, Syscalls, YieldNoWaitReturn};\nuse libtock_unittest::fake;"
},
{
"path": "apis/peripherals/alarm/Cargo.toml",
"chars": 473,
"preview": "[package]\nname = \"libtock_alarm\"\nversion = \"0.1.0\"\nauthors = [\n \"Tock Project Developers <tock-dev@googlegroups.com>\""
},
{
"path": "apis/peripherals/alarm/src/lib.rs",
"chars": 3430,
"preview": "#![no_std]\n\nuse core::cell::Cell;\nuse libtock_platform as platform;\nuse libtock_platform::share;\nuse libtock_platform::{"
},
{
"path": "apis/peripherals/alarm/src/tests.rs",
"chars": 608,
"preview": "use libtock_unittest::fake;\n\nuse crate::{Hz, Milliseconds, Ticks};\n\ntype Alarm = crate::Alarm<fake::Syscalls>;\n\n#[test]\n"
},
{
"path": "apis/peripherals/gpio/Cargo.toml",
"chars": 516,
"preview": "[package]\nname = \"libtock_gpio\"\nversion = \"0.1.0\"\nauthors = [\"Tock Project Developers <tock-dev@googlegroups.com>\"]\nlice"
},
{
"path": "apis/peripherals/gpio/src/lib.rs",
"chars": 7286,
"preview": "#![no_std]\n\nuse core::marker::PhantomData;\n\nuse libtock_platform::{\n share::Handle, subscribe::OneId, DefaultConfig, "
},
{
"path": "apis/peripherals/gpio/src/tests.rs",
"chars": 10891,
"preview": "use core::cell::Cell;\n\nuse libtock_platform::{share, ErrorCode, Syscalls, YieldNoWaitReturn};\nuse libtock_unittest::fake"
},
{
"path": "apis/peripherals/i2c_master/Cargo.toml",
"chars": 420,
"preview": "[package]\nname = \"libtock_i2c_master\"\nversion = \"0.1.0\"\nauthors = [\n \"Tock Project Developers <tock-dev@googlegroups."
},
{
"path": "apis/peripherals/i2c_master/src/lib.rs",
"chars": 6902,
"preview": "#![no_std]\n\nuse core::cell::Cell;\nuse libtock_platform as platform;\nuse libtock_platform::allow_rw::AllowRw;\nuse libtock"
},
{
"path": "apis/peripherals/i2c_master_slave/Cargo.toml",
"chars": 430,
"preview": "[package]\nname = \"libtock_i2c_master_slave\"\nversion = \"0.1.0\"\nauthors = [\n \"Tock Project Developers <tock-dev@googleg"
},
{
"path": "apis/peripherals/i2c_master_slave/src/lib.rs",
"chars": 17103,
"preview": "#![no_std]\n\nuse core::cell::Cell;\nuse libtock_platform as platform;\nuse libtock_platform::allow_ro::AllowRo;\nuse libtock"
},
{
"path": "apis/peripherals/rng/Cargo.toml",
"chars": 481,
"preview": "[package]\nname = \"libtock_rng\"\nversion = \"0.1.0\"\nauthors = [\n \"Tock Project Developers <tock-dev@googlegroups.com>\",\n"
},
{
"path": "apis/peripherals/rng/src/lib.rs",
"chars": 3108,
"preview": "#![no_std]\n\nuse core::cell::Cell;\nuse libtock_platform::{\n share, subscribe::OneId, AllowRw, DefaultConfig, ErrorCode"
},
{
"path": "apis/peripherals/spi_controller/Cargo.toml",
"chars": 427,
"preview": "[package]\nname = \"libtock_spi_controller\"\nversion = \"0.1.0\"\nauthors = [\n \"Tock Project Developers <tock-dev@googlegro"
},
{
"path": "apis/peripherals/spi_controller/src/lib.rs",
"chars": 7390,
"preview": "#![no_std]\n\nuse core::cell::Cell;\nuse libtock_platform as platform;\nuse libtock_platform::allow_rw::AllowRw;\nuse libtock"
},
{
"path": "apis/sensors/air_quality/Cargo.toml",
"chars": 433,
"preview": "[package]\nname = \"libtock_air_quality\"\nversion = \"0.1.0\"\nauthors = [\"Tock Project Developers <tock-dev@googlegroups.com>"
},
{
"path": "apis/sensors/air_quality/src/lib.rs",
"chars": 4084,
"preview": "#![no_std]\n\nuse core::cell::Cell;\nuse libtock_platform::subscribe::OneId;\nuse libtock_platform::{\n share::scope, shar"
},
{
"path": "apis/sensors/air_quality/src/tests.rs",
"chars": 3491,
"preview": "use crate::AirQualityListener;\nuse core::cell::Cell;\nuse libtock_platform::{share::scope, ErrorCode, Syscalls, YieldNoWa"
},
{
"path": "apis/sensors/ambient_light/Cargo.toml",
"chars": 437,
"preview": "[package]\nname = \"libtock_ambient_light\"\nversion = \"0.1.0\"\nauthors = [\"Tock Project Developers <tock-dev@googlegroups.co"
},
{
"path": "apis/sensors/ambient_light/src/lib.rs",
"chars": 2671,
"preview": "#![no_std]\n\nuse core::cell::Cell;\nuse libtock_platform::{\n share, subscribe::OneId, DefaultConfig, ErrorCode, Subscri"
},
{
"path": "apis/sensors/ambient_light/src/tests.rs",
"chars": 2253,
"preview": "use core::cell::Cell;\nuse libtock_platform::{share, ErrorCode, Syscalls, YieldNoWaitReturn};\nuse libtock_unittest::fake;"
},
{
"path": "apis/sensors/ninedof/Cargo.toml",
"chars": 458,
"preview": "[package]\nname = \"libtock_ninedof\"\nversion = \"0.1.0\"\nauthors = [ \"Tock Project Developers <tock-dev@googlegroups.com>\" ]"
},
{
"path": "apis/sensors/ninedof/src/lib.rs",
"chars": 5457,
"preview": "#![no_std]\n\nuse core::cell::Cell;\nuse libtock_platform::{\n share, share::Handle, subscribe::OneId, DefaultConfig, Err"
},
{
"path": "apis/sensors/ninedof/src/tests.rs",
"chars": 6171,
"preview": "use core::cell::Cell;\nuse libtock_platform::{share, ErrorCode, Syscalls, YieldNoWaitReturn};\nuse libtock_unittest::fake;"
},
{
"path": "apis/sensors/proximity/Cargo.toml",
"chars": 430,
"preview": "[package]\nname = \"libtock_proximity\"\nversion = \"0.1.0\"\nauthors = [\"Tock Project Developers <tock-dev@googlegroups.com>\"]"
},
{
"path": "apis/sensors/proximity/src/lib.rs",
"chars": 3870,
"preview": "#![no_std]\n\nuse core::cell::Cell;\n\nuse libtock_platform::{share, DefaultConfig, ErrorCode, Subscribe, Syscalls};\n\npub st"
},
{
"path": "apis/sensors/proximity/src/tests.rs",
"chars": 2444,
"preview": "use core::cell::Cell;\nuse libtock_platform::{share, ErrorCode, Syscalls, YieldNoWaitReturn};\nuse libtock_unittest::fake;"
},
{
"path": "apis/sensors/sound_pressure/Cargo.toml",
"chars": 439,
"preview": "[package]\nname = \"libtock_sound_pressure\"\nversion = \"0.1.0\"\nauthors = [\"Tock Project Developers <tock-dev@googlegroups.c"
},
{
"path": "apis/sensors/sound_pressure/src/lib.rs",
"chars": 2998,
"preview": "#![no_std]\n\nuse core::cell::Cell;\nuse libtock_platform::{\n share, subscribe::OneId, DefaultConfig, ErrorCode, Subscri"
},
{
"path": "apis/sensors/sound_pressure/src/tests.rs",
"chars": 2171,
"preview": "use core::cell::Cell;\nuse libtock_platform::{share, ErrorCode, Syscalls, YieldNoWaitReturn};\nuse libtock_unittest::fake;"
},
{
"path": "apis/sensors/temperature/Cargo.toml",
"chars": 433,
"preview": "[package]\nname = \"libtock_temperature\"\nversion = \"0.1.0\"\nauthors = [\"Tock Project Developers <tock-dev@googlegroups.com>"
},
{
"path": "apis/sensors/temperature/src/lib.rs",
"chars": 2617,
"preview": "#![no_std]\n\nuse core::cell::Cell;\nuse libtock_platform::{\n share, subscribe::OneId, DefaultConfig, ErrorCode, Subscri"
},
{
"path": "apis/sensors/temperature/src/tests.rs",
"chars": 2456,
"preview": "use core::cell::Cell;\nuse libtock_platform::{share, ErrorCode, Syscalls, YieldNoWaitReturn};\nuse libtock_unittest::fake;"
},
{
"path": "apis/storage/key_value/Cargo.toml",
"chars": 403,
"preview": "[package]\nname = \"libtock_key_value\"\nversion = \"0.1.0\"\nauthors = [\n \"Tock Project Developers <tock-dev@googlegroups.c"
},
{
"path": "apis/storage/key_value/src/lib.rs",
"chars": 5306,
"preview": "#![no_std]\n\nuse core::cell::Cell;\nuse libtock_platform as platform;\nuse libtock_platform::allow_ro::AllowRo;\nuse libtock"
},
{
"path": "apis/storage/key_value/src/tests.rs",
"chars": 6172,
"preview": "use super::*;\nuse libtock_platform::ErrorCode;\nuse libtock_unittest::{command_return, fake, ExpectedSyscall};\n\ntype Kv ="
},
{
"path": "build.rs",
"chars": 56,
"preview": "fn main() {\n libtock_build_scripts::auto_layout();\n}\n"
},
{
"path": "build_scripts/Cargo.toml",
"chars": 366,
"preview": "[package]\nauthors = [\"Tock Project Developers <tock-dev@googlegroups.com>\"]\ncategories = [\"embedded\", \"no-std\", \"os\"]\nde"
},
{
"path": "build_scripts/README.md",
"chars": 1920,
"preview": "Libtock Build Scripts Support Crate\n===================================\n\nThis crate provides helpers for building libtoc"
},
{
"path": "build_scripts/libtock_layout.ld",
"chars": 7824,
"preview": "/* Layout file for Tock process binaries that use libtock-rs. This currently\n * implements static linking, because we do"
},
{
"path": "build_scripts/src/lib.rs",
"chars": 9072,
"preview": "//! Utility functions for implementing build.rs files for libtock-rs apps.\n\n/// List of known `LIBTOCK_PLATFORM` values."
},
{
"path": "demos/embedded_graphics/buttons/Cargo.toml",
"chars": 658,
"preview": "[package]\nname = \"buttons\"\nversion = \"0.1.0\"\nauthors = [\"Tock Project Developers <tock-dev@googlegroups.com>\"]\nlicense ="
},
{
"path": "demos/embedded_graphics/buttons/Makefile",
"chars": 608,
"preview": "# Makefile for the demo app.\n\n# Crate name of the demo app\nDEMO := buttons\n\nall: tab\n\ninclude ../../../Targets.mk\n\n$(ELF"
},
{
"path": "demos/embedded_graphics/buttons/README.md",
"chars": 179,
"preview": "Buttons Demo Using Embedded Graphics\n====================================\n\nDraws buttons as circles on the screen. When "
},
{
"path": "demos/embedded_graphics/buttons/build.rs",
"chars": 56,
"preview": "fn main() {\n libtock_build_scripts::auto_layout();\n}\n"
},
{
"path": "demos/embedded_graphics/buttons/src/main.rs",
"chars": 4250,
"preview": "#![no_main]\n#![no_std]\nuse core::cell::Cell;\nuse core::fmt::Write;\nuse libtock::buttons::{ButtonListener, ButtonState, B"
},
{
"path": "demos/embedded_graphics/spin/Cargo.toml",
"chars": 603,
"preview": "[package]\nname = \"spin\"\nversion = \"0.1.0\"\nauthors = [\"Tock Project Developers <tock-dev@googlegroups.com>\"]\nlicense = \"A"
},
{
"path": "demos/embedded_graphics/spin/Makefile",
"chars": 605,
"preview": "# Makefile for the demo app.\n\n# Crate name of the demo app\nDEMO := spin\n\nall: tab\n\ninclude ../../../Targets.mk\n\n$(ELF_TA"
},
{
"path": "demos/embedded_graphics/spin/README.md",
"chars": 162,
"preview": "Spin Demo Using Embedded Graphics\n=================================\n\nThis demo spins a line on a screen. It was tested u"
},
{
"path": "demos/embedded_graphics/spin/build.rs",
"chars": 56,
"preview": "fn main() {\n libtock_build_scripts::auto_layout();\n}\n"
},
{
"path": "demos/embedded_graphics/spin/src/main.rs",
"chars": 1482,
"preview": "#![no_main]\n#![no_std]\nuse libtock::alarm::Alarm;\nuse libtock::alarm::Milliseconds;\nuse libtock::runtime::{set_main, sta"
},
{
"path": "demos/st7789/Cargo.toml",
"chars": 515,
"preview": "[package]\nname = \"st7789\"\nversion = \"0.1.0\"\nedition = \"2021\"\nrust-version = \"1.87\"\nauthors = [\"Alistair Francis <alistai"
},
{
"path": "demos/st7789/Makefile",
"chars": 604,
"preview": "# Makefile for the demo app.\n\n# Crate name of the demo app\nDEMO := st7789\n\nall: tab\n\ninclude ../../Targets.mk\n\n$(ELF_TAR"
},
{
"path": "demos/st7789/build.rs",
"chars": 56,
"preview": "fn main() {\n libtock_build_scripts::auto_layout();\n}\n"
},
{
"path": "demos/st7789/src/main.rs",
"chars": 1944,
"preview": "//! This sample demonstrates displaying text on a ST7789 display\n//! using a rust-embedded based crate\n\n#![no_main]\n#![n"
},
{
"path": "demos/st7789-slint/Cargo.toml",
"chars": 936,
"preview": "[package]\nname = \"st7789-slint\"\nversion = \"0.1.0\"\nedition = \"2021\"\nrust-version = \"1.87\"\nauthors = [\"Alistair Francis <a"
},
{
"path": "demos/st7789-slint/Makefile",
"chars": 610,
"preview": "# Makefile for the demo app.\n\n# Crate name of the demo app\nDEMO := st7789-slint\n\nall: tab\n\ninclude ../../Targets.mk\n\n$(E"
},
{
"path": "demos/st7789-slint/build.rs",
"chars": 325,
"preview": "fn main() {\n libtock_build_scripts::auto_layout();\n\n let config = slint_build::CompilerConfiguration::new()\n "
},
{
"path": "demos/st7789-slint/src/main.rs",
"chars": 5604,
"preview": "//! This sample demonstrates displaying a slint GUI on a ST7789 display\n//! using a rust-embedded based crate\n\n# used to find th"
},
{
"path": "doc/MiriTips.md",
"chars": 1675,
"preview": "Miri Tips\n=========\n\n`libtock-rs` runs most of its unit tests under\n[Miri](https://github.com/rust-lang/miri) to detect "
},
{
"path": "doc/Overview.md",
"chars": 2694,
"preview": "Overview\n======\n\nThis document gives an overview of the crates in this repository, and is\nintended to be useful to `libt"
},
{
"path": "doc/PlatformDesignStory.md",
"chars": 19954,
"preview": "`libtock_platform` Design Story\n===============================\n\n`libtock_platform` is a crate that will contain core ab"
},
{
"path": "doc/Startup.md",
"chars": 3112,
"preview": "Startup\n=======\n\nThis document describes the `libtock_runtime` startup process, up until the\nprocess binary's `main` sta"
},
{
"path": "doc/Style.md",
"chars": 1786,
"preview": "Coding Style\n============\n\n## List Ordering\n\nSource code tends to contain many lists whose order is unimportant, such as"
},
{
"path": "doc/Testing.md",
"chars": 1683,
"preview": "Testing\n=======\n\nThis document gives an introduction to the tests in this repository, and is\nintended to be useful to `l"
},
{
"path": "doc/UnitTestOwnership.md",
"chars": 6835,
"preview": "Unit Test Ownership Design\n==========================\n\n**TODO: This document describes a not-yet-implemented design for\n"
},
{
"path": "examples/adc.rs",
"chars": 779,
"preview": "//! A simple libtock-rs example. Checks for adc driver\n//! and samples the sensor every 2 seconds.\n\n#![no_main]\n#![no_st"
},
{
"path": "examples/ambient_light.rs",
"chars": 897,
"preview": "//! A simple libtock-rs example. Checks for ambient light driver\n//! and samples the sensor every 2 seconds.\n\n#![no_main"
},
{
"path": "examples/blink.rs",
"chars": 644,
"preview": "//! The blink app.\n\n#![no_main]\n#![no_std]\n\nuse libtock::alarm::{Alarm, Milliseconds};\nuse libtock::leds::Leds;\nuse libt"
},
{
"path": "examples/buttons.rs",
"chars": 1167,
"preview": "//! An extremely simple libtock-rs example. Register button events.\n\n#![no_main]\n#![no_std]\n\nuse core::fmt::Write;\nuse l"
},
{
"path": "examples/console.rs",
"chars": 352,
"preview": "//! An extremely simple libtock-rs example. Just prints out a message\n//! using the Console capsule, then terminates.\n\n#"
},
{
"path": "examples/gpio.rs",
"chars": 1227,
"preview": "//! A simple GPIO example for getting GPIO interrupts.\n//!\n//! This will configure GPIO 0 to be a rising-edge triggered "
},
{
"path": "examples/i2c_master_write_read.rs",
"chars": 2914,
"preview": "//! This sample demonstrates setting up the i2c ip (assuming board has support)\n//! for master mode. In the event loop, "
},
{
"path": "examples/i2c_slave_send_recv.rs",
"chars": 2908,
"preview": "//! This sample demonstrates setting up the i2c ip (assuming board has support)\n//! for target mode. In the event loop, "
},
{
"path": "examples/ieee802154_raw.rs",
"chars": 2690,
"preview": "//! An example showing use of IEEE 802.15.4 networking.\n//!\n//! The kernel contains a standard and phy 15.4 driver. This"
},
{
"path": "examples/ieee802154_rx_raw.rs",
"chars": 2938,
"preview": "//! An example showing use of IEEE 802.15.4 networking.\n//! It infinitely received a frame and prints its content to Con"
},
{
"path": "examples/ieee802154_rx_tx_raw.rs",
"chars": 3759,
"preview": "//! An example showing use of IEEE 802.15.4 networking.\n//! It infinitely sends a frame with a constantly incremented co"
},
{
"path": "examples/ieee802154_tx_raw.rs",
"chars": 2822,
"preview": "//! An example showing use of IEEE 802.15.4 networking.\n//! It infinitely sends a frame with a constantly incremented co"
},
{
"path": "examples/kv.rs",
"chars": 2368,
"preview": "//! A key-value store example. Gets and sets key-value objects.\n\n#![no_main]\n#![no_std]\n\nuse core::fmt::Write;\nuse core:"
},
{
"path": "examples/leds.rs",
"chars": 492,
"preview": "//! A simple libtock-rs example. Just blinks all the LEDs.\n\n#![no_main]\n#![no_std]\n\nuse libtock::alarm::{Alarm, Millisec"
},
{
"path": "examples/low_level_debug.rs",
"chars": 361,
"preview": "//! An extremely simple libtock-rs example. Just prints out a few numbers using\n//! the LowLevelDebug capsule then termi"
},
{
"path": "examples/music.rs",
"chars": 2452,
"preview": "//! Implementation done by : https://github.com/teodorobert\n//! A simple libtock-rs example. Plays Ode of Joy using the "
},
{
"path": "examples/ninedof.rs",
"chars": 2056,
"preview": "//! Libtock-rs example for the ninedof sensor.\n\n#![no_main]\n#![no_std]\n\nuse core::fmt::Write;\nuse libtock::console::Cons"
},
{
"path": "examples/proximity.rs",
"chars": 880,
"preview": "//! A simple libtock-rs example. Checks for proximity driver\n//! and samples the sensor every 2 seconds.\n\n#![no_main]\n#!"
},
{
"path": "examples/rng.rs",
"chars": 1210,
"preview": "#![no_std]\n#![no_main]\n\nuse core::fmt::Write;\nuse libtock::alarm::{Alarm, Milliseconds};\nuse libtock::console::Console;\n"
},
{
"path": "examples/rng_async.rs",
"chars": 1222,
"preview": "#![no_std]\n#![no_main]\n\nuse core::fmt::Write;\nuse libtock::alarm::{Alarm, Milliseconds};\nuse libtock::rng::RngListener;\n"
},
{
"path": "examples/screen.rs",
"chars": 6231,
"preview": "#![no_main]\n#![no_std]\nuse core::fmt::Write;\nuse libtock::alarm::Alarm;\nuse libtock::alarm::Milliseconds;\nuse libtock::c"
},
{
"path": "examples/sound_pressure.rs",
"chars": 1424,
"preview": "//! This example shows how to use the sound pressure driver.\n//! It checks for the sound pressure driver and samples the"
},
{
"path": "examples/spi_controller_write_read.rs",
"chars": 2360,
"preview": "//! This sample demonstrates setting up the SPI controller (assuming board has support)\n\n#![no_main]\n#![no_std]\nuse core"
},
{
"path": "examples/temperature.rs",
"chars": 1152,
"preview": "//! A simple libtock-rs example. Checks for temperature driver\n//! and samples the sensor every 2 seconds.\n\n#![no_main]\n"
},
{
"path": "examples/usb_i2c_mctp.rs",
"chars": 7626,
"preview": "//! A sample app that implements MCTP messages to be transceived from a host\n//! machine without exposed SMBus/I2C capab"
},
{
"path": "libraries/embedded_graphics_libtock/Cargo.toml",
"chars": 434,
"preview": "[package]\nname = \"embedded_graphics_libtock\"\nversion = \"0.1.0\"\nauthors = [\"Tock Project Developers <tock-dev@googlegroup"
},
{
"path": "libraries/embedded_graphics_libtock/README.md",
"chars": 351,
"preview": "Embedded Graphics - Libtock\n===========================\n\nThis crate connects the\n[Embedded Graphics library](https://cra"
},
{
"path": "libraries/embedded_graphics_libtock/src/lib.rs",
"chars": 1032,
"preview": "//! Interface library for using Embedded Graphics with libtock-rs\n//!\n//! This library implements `embedded_graphics::dr"
},
{
"path": "libraries/embedded_graphics_libtock/src/tock_screen.rs",
"chars": 3043,
"preview": "//! Implementations of `DrawTarget` using the screen system call.\n\nuse libtock::display::Screen;\nuse libtock_platform::E"
},
{
"path": "nightly/rust-toolchain.toml",
"chars": 135,
"preview": "# This is the nightly Rust toolchain used by `make test`.\n[toolchain]\nchannel = \"nightly-2025-09-11\"\ncomponents = [\"miri"
},
{
"path": "panic_handlers/debug_panic/Cargo.toml",
"chars": 593,
"preview": "[package]\nname = \"libtock_debug_panic\"\nauthors = [\"Tock Project Developers <tock-dev@googlegroups.com>\"]\nversion = \"0.1."
},
{
"path": "panic_handlers/debug_panic/src/lib.rs",
"chars": 766,
"preview": "#![no_std]\nuse core::fmt::Write;\nuse libtock_console::Console;\nuse libtock_low_level_debug::{AlertCode, LowLevelDebug};\n"
},
{
"path": "panic_handlers/small_panic/Cargo.toml",
"chars": 545,
"preview": "[package]\nname = \"libtock_small_panic\"\nauthors = [\"Tock Project Developers <tock-dev@googlegroups.com>\"]\nversion = \"0.1."
},
{
"path": "panic_handlers/small_panic/src/lib.rs",
"chars": 591,
"preview": "#![no_std]\n\nuse libtock_low_level_debug::{AlertCode, LowLevelDebug};\nuse libtock_platform::{ErrorCode, Syscalls};\nuse li"
},
{
"path": "platform/Cargo.toml",
"chars": 749,
"preview": "[package]\nauthors = [\"Tock Project Developers <tock-dev@googlegroups.com>\"]\ncategories = [\"embedded\", \"no-std\", \"os\"]\nde"
},
{
"path": "platform/src/allow_ro.rs",
"chars": 3033,
"preview": "use crate::share::List;\nuse crate::Syscalls;\nuse core::marker::PhantomData;\n\n// ----------------------------------------"
},
{
"path": "platform/src/allow_rw.rs",
"chars": 3033,
"preview": "use crate::share::List;\nuse crate::Syscalls;\nuse core::marker::PhantomData;\n\n// ----------------------------------------"
},
{
"path": "platform/src/command_return.rs",
"chars": 13345,
"preview": "use crate::{return_variant, ErrorCode, ReturnVariant};\n\nuse core::mem::transmute;\n\n/// The response type from the [`comm"
},
{
"path": "platform/src/command_return_tests.rs",
"chars": 19896,
"preview": "use crate::{return_variant, CommandReturn, ErrorCode};\n\n#[test]\nfn failure() {\n let command_return = unsafe {\n "
},
{
"path": "platform/src/constants.rs",
"chars": 467,
"preview": "//! Defines constants shared between multiple `libtock-rs` crates.\n\npub mod exit_id {\n pub const TERMINATE: u32 = 0;\n"
},
{
"path": "platform/src/default_config.rs",
"chars": 285,
"preview": "/// A general purpose syscall configuration, which drivers should use as their\n/// default syscall config.\npub struct De"
},
{
"path": "platform/src/error_code.rs",
"chars": 20103,
"preview": "use core::{convert::TryFrom, fmt, mem::transmute};\n\n// TODO: Add a ufmt debug implementation for process binaries to use"
},
{
"path": "platform/src/error_code_tests.rs",
"chars": 629,
"preview": "use core::convert::TryInto;\n\nuse crate::{error_code::NotAnErrorCode, ErrorCode};\n\n// Verifies that `ErrorCode` represent"
},
{
"path": "platform/src/exit_on_drop.rs",
"chars": 866,
"preview": "/// Calls the Exit system call when dropped. Used to catch panic unwinding from\n/// a `#![no_std]` context. The caller s"
},
{
"path": "platform/src/lib.rs",
"chars": 895,
"preview": "#![cfg_attr(not(test), no_std)]\n#![warn(unsafe_op_in_unsafe_fn)]\n\npub mod allow_ro;\npub mod allow_rw;\npub mod command_re"
},
{
"path": "platform/src/raw_syscalls.rs",
"chars": 10168,
"preview": "use crate::Register;\n\n/// `RawSyscalls` allows a fake Tock kernel to be injected into components for\n/// unit testing. I"
},
{
"path": "platform/src/register.rs",
"chars": 5087,
"preview": "/// `Register` represents the value of a register used in Tock's syscall ABI. It\n/// can contain integer values as well "
},
{
"path": "platform/src/return_variant.rs",
"chars": 1453,
"preview": "// TODO: Re-evaluate whether u32 is the correct type to wrap. Maybe it should\n// wrap a Register instead? Also, double-c"
},
{
"path": "platform/src/share/handle.rs",
"chars": 3084,
"preview": "use crate::share::List;\nuse core::marker::PhantomData;\n\n/// A `Handle`'s existence indicates two things:\n///\n/// 1. The "
},
{
"path": "platform/src/share/mod.rs",
"chars": 838,
"preview": "//! `share` contains tools for safely sharing objects (such as buffers and\n//! upcalls) with the Tock kernel.\n\nmod handl"
},
{
"path": "platform/src/share/tests.rs",
"chars": 2659,
"preview": "use crate::share::{scope, Handle, List};\n\nstd::thread_local! {static INSTANCE_COUNT: core::cell::Cell<u64> = const {core"
},
{
"path": "platform/src/share/tuple_impls.rs",
"chars": 2189,
"preview": "/// Implements `share::List` and `share::SplittableHandle` on tuples of various\n/// sizes.\nuse crate::share::{Handle, Li"
},
{
"path": "platform/src/subscribe.rs",
"chars": 8749,
"preview": "use crate::share::List;\nuse crate::ErrorCode;\nuse crate::Syscalls;\n\n// -------------------------------------------------"
},
{
"path": "platform/src/syscalls.rs",
"chars": 5322,
"preview": "use crate::{\n allow_ro, allow_rw, share, subscribe, AllowRo, AllowRw, CommandReturn, ErrorCode, RawSyscalls,\n Subs"
},
{
"path": "platform/src/syscalls_impl.rs",
"chars": 26307,
"preview": "//! Implements `Syscalls` for all types that implement `RawSyscalls`.\n\nuse crate::{\n allow_ro, allow_rw, exit_id, exi"
},
{
"path": "platform/src/termination.rs",
"chars": 587,
"preview": "//! Definition of the Termination trait. The main() function (set using set_main!())\n//! must return a type that impleme"
},
{
"path": "platform/src/yield_types.rs",
"chars": 721,
"preview": "/// The return value from a yield_no_wait call.\n// Calling yield-no-wait passes a *mut YieldNoWaitReturn to the kernel, "
},
{
"path": "runner/Cargo.toml",
"chars": 441,
"preview": "[package]\nauthors = [\"Tock Project Developers <tock-dev@googlegroups.com>\"]\ndescription = \"\"\"Tool used to run libtock-rs"
},
{
"path": "runner/src/elf2tab.rs",
"chars": 4699,
"preview": "use super::Cli;\nuse std::fs::{metadata, remove_file};\nuse std::io::ErrorKind;\nuse std::path::PathBuf;\nuse std::process::"
},
{
"path": "runner/src/main.rs",
"chars": 1654,
"preview": "mod elf2tab;\nmod output_processor;\nmod qemu;\nmod tockloader;\n\nuse clap::{Parser, ValueEnum};\nuse std::env::{var, VarErro"
},
{
"path": "runner/src/output_processor.rs",
"chars": 4919,
"preview": "use super::Cli;\nuse libc::{kill, pid_t, SIGINT};\nuse std::io::{stderr, stdin, stdout, BufRead, BufReader, ErrorKind, Std"
},
{
"path": "runner/src/qemu.rs",
"chars": 2787,
"preview": "use super::Cli;\nuse std::path::PathBuf;\nuse std::process::{Child, Command, Stdio};\n\n// Spawns a QEMU VM with a simulated"
},
{
"path": "runner/src/tockloader.rs",
"chars": 3949,
"preview": "use super::Cli;\nuse std::path::PathBuf;\nuse std::process::{Child, Command, Stdio};\n\n// Uses tockloader to deploy the pro"
},
{
"path": "runtime/Cargo.toml",
"chars": 885,
"preview": "[package]\nauthors = [\"Tock Project Developers <tock-dev@googlegroups.com>\"]\ncategories = [\"embedded\", \"no-std\", \"os\"]\nde"
},
{
"path": "runtime/src/lib.rs",
"chars": 1192,
"preview": "//! `libtock_runtime` provides the runtime for Tock process binaries written in\n//! Rust as well as interfaces to Tock's"
},
{
"path": "runtime/src/startup/asm_arm.s",
"chars": 3885,
"preview": "/* rt_header is defined by the general linker script (libtock_layout.ld). It has\n * the following layout:\n *\n * Fiel"
},
{
"path": "runtime/src/startup/asm_riscv32.s",
"chars": 3517,
"preview": "/* rt_header is defined by the general linker script (libtock_layout.ld). It has\n * the following layout:\n *\n * Fiel"
},
{
"path": "runtime/src/startup/asm_x86.s",
"chars": 4718,
"preview": "/* rt_header is defined by the general linker script (libtock_layout.ld). It has\n * the following layout:\n *\n * Fiel"
},
{
"path": "runtime/src/startup/mod.rs",
"chars": 4010,
"preview": "//! Runtime components related to process startup.\n\nuse crate::TockSyscalls;\nuse libtock_platform::{Syscalls, Terminatio"
},
{
"path": "runtime/src/startup/start_prototype.rs",
"chars": 3147,
"preview": "// This file is not compiled or tested! It is kept in this repository in case\n// future libtock_runtime developers want "
},
{
"path": "runtime/src/syscalls_impl_arm.rs",
"chars": 3886,
"preview": "use core::arch::asm;\nuse libtock_platform::{RawSyscalls, Register};\n\nunsafe impl RawSyscalls for crate::TockSyscalls {\n "
},
{
"path": "runtime/src/syscalls_impl_riscv.rs",
"chars": 4834,
"preview": "use core::arch::asm;\nuse libtock_platform::{RawSyscalls, Register};\n\nunsafe impl RawSyscalls for crate::TockSyscalls {\n "
},
{
"path": "runtime/src/syscalls_impl_x86.rs",
"chars": 4319,
"preview": "use core::arch::asm;\nuse libtock_platform::{syscall_class, RawSyscalls, Register};\n\nunsafe impl RawSyscalls for crate::T"
},
{
"path": "rust-toolchain.toml",
"chars": 593,
"preview": "[toolchain]\n# This is libtock-rs' Minimum Supported Rust Version (MSRV).\n#\n# Update policy: Update this if doing so allo"
},
{
"path": "rustfmt.toml",
"chars": 32,
"preview": "use_field_init_shorthand = true\n"
},
{
"path": "src/lib.rs",
"chars": 3973,
"preview": "#![forbid(unsafe_code)]\n#![no_std]\n\n#[cfg(debug_assertions)]\nextern crate libtock_debug_panic;\n#[cfg(not(debug_assertion"
},
{
"path": "src/spi_controller.rs",
"chars": 2108,
"preview": "use crate::alarm::{Alarm, Milliseconds};\nuse crate::platform::ErrorCode;\nuse libtock_spi_controller as spi_controller;\n\n"
},
{
"path": "syscalls_tests/Cargo.toml",
"chars": 203,
"preview": "[package]\nedition = \"2021\"\nname = \"syscalls_tests\"\nrust-version.workspace = true\nversion = \"0.1.0\"\n\n[dependencies]\nlibto"
},
{
"path": "syscalls_tests/src/allow_ro.rs",
"chars": 3422,
"preview": "use libtock_platform::{allow_ro, share, CommandReturn, ErrorCode, Syscalls};\nuse libtock_unittest::{command_return, fake"
},
{
"path": "syscalls_tests/src/allow_rw.rs",
"chars": 3753,
"preview": "use libtock_platform::{allow_rw, share, CommandReturn, ErrorCode, Syscalls};\nuse libtock_unittest::{command_return, fake"
},
{
"path": "syscalls_tests/src/command_tests.rs",
"chars": 816,
"preview": "//! Tests for the Command system call implementation in\n//! `libtock_platform::Syscalls`.\n\nuse libtock_platform::Syscall"
},
{
"path": "syscalls_tests/src/exit_on_drop.rs",
"chars": 722,
"preview": "use libtock_platform::exit_on_drop::ExitOnDrop;\nuse libtock_unittest::fake;\n\n// Unwinds if `unwind` is true, otherwise j"
},
{
"path": "syscalls_tests/src/lib.rs",
"chars": 844,
"preview": "//! This crate contains tests for `libtock_platform` functionality that use the\n//! `Syscalls` implementation.\n//!\n//! T"
},
{
"path": "syscalls_tests/src/memop_tests.rs",
"chars": 4006,
"preview": "//! Tests for the Memop system call implementation in\n//! `libtock_platform::Syscalls`.\n\nuse libtock_platform::{ErrorCod"
},
{
"path": "syscalls_tests/src/subscribe_tests.rs",
"chars": 4336,
"preview": "use libtock_platform::{\n share, subscribe, CommandReturn, DefaultConfig, ErrorCode, Syscalls, YieldNoWaitReturn,\n};\nu"
},
{
"path": "syscalls_tests/src/yield_tests.rs",
"chars": 1280,
"preview": "//! Tests for implementations of Yield system calls in\n//! `libtock_platform::Syscalls`.\n\nuse libtock_platform::{Syscall"
},
{
"path": "tools/print_sizes/Cargo.toml",
"chars": 448,
"preview": "# Finds all the libtock_core and libtock examples and prints the sizes of\n# several of their sections. Searches the targ"
}
]
// ... and 90 more files (download for full content)
About this extraction
This page contains the full source code of the tock/libtock-rs GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 290 files (973.9 KB), approximately 266.1k tokens, and a symbol index with 1648 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.