Skip to content

Commit

Permalink
Boot keyboard example for RP235x
Browse files Browse the repository at this point in the history
  • Loading branch information
dlkj committed Oct 18, 2024
1 parent 67da705 commit e2ae064
Show file tree
Hide file tree
Showing 10 changed files with 759 additions and 3 deletions.
4 changes: 4 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,7 @@ updates:
directory: "/examples/rp2040/"
schedule:
interval: "daily"
- package-ecosystem: "cargo"
directory: "/examples/rp235x/"
schedule:
interval: "daily"
34 changes: 34 additions & 0 deletions .github/workflows/examples_rp235x_build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
on: [push, pull_request]

name: Examples RP235x build

jobs:
check_format_build:
name: Examples - Check, Format, Build
runs-on: ubuntu-latest
steps:
#Checkout source
- name: Checkout sources
uses: actions/checkout@v3
#toolchain and tools
- name: Install stable toolchain
uses: dtolnay/rust-toolchain@master
with:
toolchain: stable
target: thumbv6m-none-eabi
components: rustfmt, clippy
- name: Install flip-link linker
run: cargo install flip-link
#build and lint
- name: Run cargo check - examples rp235x
working-directory: ./examples/rp235x/
run: cargo check
- name: Run cargo fmt - examples rp235x
working-directory: ./examples/rp235x/
run: cargo fmt --all -- --check
- name: Run cargo clippy - examples rp235x
working-directory: ./examples/rp235x/
run: cargo clippy -- -D warnings
- name: Run cargo build - examples rp235x
working-directory: ./examples/rp235x/
run: cargo build
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
[![Library build](https://github.com/dlkj/usbd-human-interface-device/actions/workflows/lib_build.yml/badge.svg)](https://github.com/dlkj/usbd-human-interface-device/actions/workflows/lib_build.yml)
[![Example build](https://github.com/dlkj/usbd-human-interface-device/actions/workflows/example_build.yml/badge.svg)](https://github.com/dlkj/usbd-human-interface-device/actions/workflows/example_build.yml)
[![RP2040 examples build](https://github.com/dlkj/usbd-human-interface-device/actions/workflows/example_build.yml/badge.svg)](https://github.com/dlkj/usbd-human-interface-device/actions/workflows/examples_rp2040_build.yml)
[![RP235x examples build](https://github.com/dlkj/usbd-human-interface-device/actions/workflows/example_build.yml/badge.svg)](https://github.com/dlkj/usbd-human-interface-device/actions/workflows/examples_rp235x_build.yml)
[![Security audit](https://github.com/dlkj/usbd-human-interface-device/actions/workflows/audit.yml/badge.svg)](https://github.com/dlkj/usbd-human-interface-device/actions/workflows/audit.yml)

[![crates.io](https://img.shields.io/crates/v/usbd-human-interface-device.svg)](https://crates.io/crates/usbd-human-interface-device)
Expand All @@ -9,7 +10,7 @@ Batteries included embedded USB HID library for [`usb-device`](https://crates.io
Includes Keyboard (boot and NKRO), Mouse, Joystick and Consumer Control implementations as well as
support for building your own HID classes.

Tested on the RP2040, but should work on any platform supported by
Tested on the RP2040 and RP235x, but should work on any platform supported by
[`usb-device`](https://crates.io/crates/usb-device).

Devices created with this library should work with any USB host. Tested on Windows,
Expand All @@ -35,7 +36,7 @@ require the `UsbHidClass::tick()` method calling every 1ms.
## Examples

See [examples](https://github.com/dlkj/usbd-human-interface-device/tree/main/examples) for
demonstrations of how to use this library on the RP2040 (Raspberry Pi Pico)
demonstrations of how to use this library on the RP2040 (Raspberry Pi Pico) and RP235x (Raspberry Pi Pico 2).

## Road map

Expand Down
91 changes: 91 additions & 0 deletions examples/rp235x/.cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
#
# Cargo Configuration for the https://github.com/rp-rs/rp-hal.git repository.
#
# You might want to make a similar file in your own repository if you are
# writing programs for Raspberry Silicon microcontrollers.
#

[build]
# Set the default target to match the Cortex-M33 in the RP2350
target = "thumbv8m.main-none-eabihf"

# This is the hard-float ABI for Arm mode.
#
# The FPU is enabled by default, and float function arguments use FPU
# registers.
[target.thumbv8m.main-none-eabihf]
# Pass some extra options to rustc, some of which get passed on to the linker.
#
# * linker argument --nmagic turns off page alignment of sections (which saves
# flash space)
# * linker argument -Tlink.x tells the linker to use link.x as a linker script.
# This is usually provided by the cortex-m-rt crate, and by default the
# version in that crate will include a file called `memory.x` which describes
# the particular memory layout for your specific chip.
# * linker argument -Tdefmt.x also tells the linker to use `defmt.x` as a
# secondary linker script. This is required to make defmt_rtt work.
rustflags = [
"-C",
"link-arg=--nmagic",
"-C",
"link-arg=-Tlink.x",
"-C",
"link-arg=-Tdefmt.x",
"-C",
"target-cpu=cortex-m33",
]

# Use picotool for loading.
#
# Load an elf, skipping unchanged flash sectors, verify it, and execute it
runner = "picotool load -u -v -x -t elf"

# This is the soft-float ABI for Arm mode.
#
# The FPU is disabled by default, and float function arguments use integer
# registers. Only useful for making the `float_test` example give really bad
# results on the `f32` benchmark.
[target.thumbv8m.main-none-eabi]
# Pass some extra options to rustc. See above for descriptions.
rustflags = [
"-C",
"link-arg=--nmagic",
"-C",
"link-arg=-Tlink.x",
"-C",
"link-arg=-Tdefmt.x",
]

# Use picotool for loading.
#
# Load an elf, skipping unchanged flash sectors, verify it, and execute it
runner = "picotool load -u -v -x -t elf"

# This is the soft-float ABI for RISC-V mode.
#
# Hazard 3 does not have an FPU and so float function arguments use integer
# registers.
[target.riscv32imac-unknown-none-elf]
# Pass some extra options to rustc, some of which get passed on to the linker.
#
# * linker argument --nmagic turns off page alignment of sections (which saves
# flash space)
# * linker argument -Trp235x_riscv.x also tells the linker to use
# `rp235x_riscv.x` as a linker script. This adds in RP2350 RISC-V specific
# things that the riscv-rt crate's `link.x` requires and then includes
# `link.x` automatically. This is the reverse of how we do it on Cortex-M.
# * linker argument -Tdefmt.x also tells the linker to use `defmt.x` as a
# secondary linker script. This is required to make defmt_rtt work.
rustflags = [
"-C",
"link-arg=--nmagic",
"-C",
"link-arg=-Trp235x_riscv.x",
"-C",
"link-arg=-Tdefmt.x",
]

# Use picotool for loading.
#
# Load an elf, skipping unchanged flash sectors, verify it, and execute it
runner = "picotool load -u -v -x -t elf"
34 changes: 34 additions & 0 deletions examples/rp235x/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
[package]
name = "usbd-human-interface-device-example-rp235x"
version = "0.1.0"
edition = "2021"
authors = ["DLKJ"]
description = "Example using the rust usbd-human-interface-device library on the Raspberry Pi RP235x/Pico2"
license = "MIT"

[workspace]

[dependencies]
usbd-human-interface-device = { path = "../.." }
usb-device = "0.3"

cortex-m = "0.7.2"
cortex-m-rt = "0.7"
cortex-m-rtic = "1.1"
critical-section = { version = "1.2" }
defmt = "0.3"
defmt-rtt = "0.4"
dht-sensor = "0.2.1"
embedded-hal = "1.0.0"
embedded-io = "0.6.1"
embedded_hal_0_2 = { package = "embedded-hal", version = "0.2.5", features = [
"unproven",
] }
fugit = "0.3.6"
panic-halt = "0.2.0"
rp235x-hal = { version = "0.2.0", features = [
"binary-info",
"critical-section-impl",
"rt",
"defmt",
] }
24 changes: 24 additions & 0 deletions examples/rp235x/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Examples

- keyboard_boot - keyboard implementing the HID boot specification

The examples target the Raspberry Pi Pico2/RP235x but can be ported to other boards.

## Installation of development dependencies

```shell
$ rustup target add thumbv8m.main-none-eabihf
$ rustup target add riscv32imac-unknown-none-elf
```

You can also 'run' an example, which invoke Raspberry Pi's picotool to copy it to an RP235x in USB Bootloader mode.
You should install that if you don't have it already, from https://github.com/raspberrypi/pico-sdk-tools/releases.

These examples are based off the [rp235x-hal-examples](https://github.com/rp-rs/rp-hal/tree/main/rp235x-hal-examples).
See the project README for more detailed instructions.

## Running

```shell
cargo run --release --bin {example name}
```
27 changes: 27 additions & 0 deletions examples/rp235x/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//! Set up linker scripts for the rp235x-hal examples
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;

fn main() {
// Put the linker script somewhere the linker can find it
let out = PathBuf::from(std::env::var_os("OUT_DIR").unwrap());
println!("cargo:rustc-link-search={}", out.display());

// The file `memory.x` is loaded by cortex-m-rt's `link.x` script, which
// is what we specify in `.cargo/config.toml` for Arm builds
let memory_x = include_bytes!("memory.x");
let mut f = File::create(out.join("memory.x")).unwrap();
f.write_all(memory_x).unwrap();
println!("cargo:rerun-if-changed=memory.x");

// The file `rp235x_riscv.x` is what we specify in `.cargo/config.toml` for
// RISC-V builds
let rp235x_riscv_x = include_bytes!("rp235x_riscv.x");
let mut f = File::create(out.join("rp235x_riscv.x")).unwrap();
f.write_all(rp235x_riscv_x).unwrap();
println!("cargo:rerun-if-changed=rp235x_riscv.x");

println!("cargo:rerun-if-changed=build.rs");
}
77 changes: 77 additions & 0 deletions examples/rp235x/memory.x
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
MEMORY {
/*
* The RP2350 has either external or internal flash.
*
* 2 MiB is a safe default here, although a Pico 2 has 4 MiB.
*/
FLASH : ORIGIN = 0x10000000, LENGTH = 2048K
/*
* RAM consists of 8 banks, SRAM0-SRAM7, with a striped mapping.
* This is usually good for performance, as it distributes load on
* those banks evenly.
*/
RAM : ORIGIN = 0x20000000, LENGTH = 512K
/*
* RAM banks 8 and 9 use a direct mapping. They can be used to have
* memory areas dedicated for some specific job, improving predictability
* of access times.
* Example: Separate stacks for core0 and core1.
*/
SRAM4 : ORIGIN = 0x20080000, LENGTH = 4K
SRAM5 : ORIGIN = 0x20081000, LENGTH = 4K
}

SECTIONS {
/* ### Boot ROM info
*
* Goes after .vector_table, to keep it in the first 4K of flash
* where the Boot ROM (and picotool) can find it
*/
.start_block : ALIGN(4)
{
__start_block_addr = .;
KEEP(*(.start_block));
KEEP(*(.boot_info));
} > FLASH

} INSERT AFTER .vector_table;

/* move .text to start /after/ the boot info */
_stext = ADDR(.start_block) + SIZEOF(.start_block);

SECTIONS {
/* ### Picotool 'Binary Info' Entries
*
* Picotool looks through this block (as we have pointers to it in our
* header) to find interesting information.
*/
.bi_entries : ALIGN(4)
{
/* We put this in the header */
__bi_entries_start = .;
/* Here are the entries */
KEEP(*(.bi_entries));
/* Keep this block a nice round size */
. = ALIGN(4);
/* We put this in the header */
__bi_entries_end = .;
} > FLASH
} INSERT AFTER .text;

SECTIONS {
/* ### Boot ROM extra info
*
* Goes after everything in our program, so it can contain a signature.
*/
.end_block : ALIGN(4)
{
__end_block_addr = .;
KEEP(*(.end_block));
} > FLASH

} INSERT AFTER .uninit;

PROVIDE(start_to_end = __end_block_addr - __start_block_addr);
PROVIDE(end_to_start = __start_block_addr - __end_block_addr);


Loading

0 comments on commit e2ae064

Please sign in to comment.