Merge #272

272: Add the RISC-V entry point assembly to libtock_runtime r=hudson-ayers a=jrvanwhy

To support the entry point assembly, I rewrote the linker script ([link to the new version]( in case you don't want to see the diff).

The rust toolchain is unable to compile raw assembly files on its own. I don't want a separate toolchain to be a build requirement of `libtock-rs`, so instead I committed the compiled library into the repository. To keep the compiled library and source code in sync, I added an actions workflow that verifies the compiled library matches the provided sources.

There is one part of this PR I am unhappy with. I have to manually `strip` local symbols from the compiled library -- i.e., removing the `riscv64-linux-gnu-strip` invocation from `` gives the following:

Disassembly of section .start:

00000000 <start>:
   0:   00000417                auipc   s0,0x0
   4:   87aa                    mv      a5,a0
   6:   4384                    lw      s1,0(a5)
   8:   00940c63                beq     s0,s1,20 <.Lset_brk>
   c:   4521                    li      a0,8
   e:   4585                    li      a1,1
  10:   4609                    li      a2,2
  12:   4709                    li      a4,2
  14:   00000073                ecall
  18:   4501                    li      a0,0
  1a:   4719                    li      a4,6
  1c:   00000073                ecall

00000020 <.Lset_brk>:
  20:   4501                    li      a0,0
  22:   43cc                    lw      a1,4(a5)
  24:   4715                    li      a4,5
  26:   00000073                ecall
  2a:   0087a103                lw      sp,8(a5)
  2e:   47c8                    lw      a0,12(a5)
  30:   c909                    beqz    a0,42 <.Lzero_bss>
  32:   4b8c                    lw      a1,16(a5)
  34:   4bd0                    lw      a2,20(a5)

00000036 <.Ldata_loop_body>:
  36:   4194                    lw      a3,0(a1)
  38:   c214                    sw      a3,0(a2)
  3a:   1571                    addi    a0,a0,-4
  3c:   0591                    addi    a1,a1,4
  3e:   0611                    addi    a2,a2,4
  40:   f97d                    bnez    a0,36 <.Ldata_loop_body>

00000042 <.Lzero_bss>:
  42:   4f88                    lw      a0,24(a5)
  44:   c519                    beqz    a0,52 <.Lcall_rust_start>
  46:   4fcc                    lw      a1,28(a5)

00000048 <.Lbss_loop_body>:
  48:   00058023                sb      zero,0(a1)
  4c:   157d                    addi    a0,a0,-1
  4e:   0585                    addi    a1,a1,1
  50:   fd65                    bnez    a0,48 <.Lbss_loop_body>

00000052 <.Lcall_rust_start>:
  52:   fafff0ef                jal     ra,0 <start>

I'd appreciate advice on how to prevent `riscv64-linux-gnu-as` from including the local symbols in its output.

Co-authored-by: Johnathan Van Why <>
tree: 9dedcbf92098e6f251fd8c52955cbb466b0fb240
  1. .cargo/
  2. .github/
  3. .vscode/
  4. boards/
  5. codegen/
  6. core/
  7. doc/
  8. examples/
  9. examples-features/
  10. src/
  11. test_runner/
  12. tools/
  13. .gitignore
  14. .gitmodules
  15. bors.toml
  17. Cargo.toml
  20. layout_generic.ld
  23. Makefile
  25. rust-toolchain
  26. rustfmt.toml

Build Status


Rust userland library for Tock (WIP)

Generally this library was tested with tock Release 1.5. Since then changes have been made that might not work with the Tock release 1.5, but instead target Tock master. For example this library might support newer boards (Apollo3), changed boards (HiFive1 revB) or new drivers (HMAC).

The library works in principle on most boards, but there is currently the showstopper bug #28 that prevents the generation of relocatable code. This means that all applications must be installed at the flash address they are compiled with, which usually means that they must be compiled especially for your board and that there can only be one application written in rust at a time and it must be installed as the first application on the board, unless you want to play games with linker scripts. There are some boards/layout_*.ld files provided that allow to run the examples on common boards. Due to MPU region alignment issues they may not work for applications that use a lot of RAM, in that case you may have to change the SRAM start address to fit your application.

Getting Started

This project is nascent and still under heavy development, but first steps:

  1. Ensure you have rustup installed.

  2. Clone the repository:

    git clone --recursive
    cd libtock-rs
  3. Install the dependencies:

    make setup
  4. Use make to build examples

    make nrf52 # Builds all examples for the nrf52 platform
    make opentitan # Builds all examples for the OpenTitan platform
    make opentitan FEATURES=alloc # Builds all examples for the OpenTitan platform, with alloc feature enabled
    make flash-hail EXAMPLE=blink # Flash the example 'blink' program to the hail platform

    For an unknown platform, you may have to create your own memory layout definition. Place the layout definition file at boards/layout_<platform>.ld and do not forget to enhance the tockloader_flags dispatching section in tools/ You are welcome to create a PR, s.t. the number of supported platforms grows.

Using libtock-rs

The easiest way to start using libtock-rs is adding an example to the examples folder. The boiler plate code you would write is


use libtock::result::TockResult;

async fn main() -> TockResult<()> {
  // Your code

If you want to use heap based allocation you will have to add

extern crate alloc;

to the preamble and store your example in the examples-alloc folder.

To build the examples for your board you can use

make <platform> [FEATURES=alloc]

An example can be flashed to your board after the build process by running:

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)


libtock-rs is licensed under either of

at your option.

Submodules have their own licenses.


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