Skip to content

Commit

Permalink
Add on-target-tests and prepare for async implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
ithinuel committed Feb 18, 2024
1 parent a4523d6 commit fcd05de
Show file tree
Hide file tree
Showing 16 changed files with 1,643 additions and 550 deletions.
39 changes: 39 additions & 0 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#
# Cargo Configuration for the https://github.com/rp-rs/rp-hal.git repository.
#
# Copyright (c) The RP-RS Developers, 2021
#
# You might want to make a similar file in your own repository if you are
# writing programs for Raspberry Silicon microcontrollers.
#
# This file is MIT or Apache-2.0 as per the repository README.md file
#

[build]
# Set the default target to match the Cortex-M0+ in the RP2040
target = "thumbv6m-none-eabi"

# Target specific options
[target.thumbv6m-none-eabi]
# 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 the 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.
# * inline-threshold=5 makes the compiler more aggressive and inlining functions
# * no-vectorize-loops turns off the loop vectorizer (seeing as the M0+ doesn't
# have SIMD)
rustflags = [
"-C", "link-arg=--nmagic",
"-C", "link-arg=-Tlink.x",
"-C", "link-arg=-Tdefmt.x",
"-C", "inline-threshold=5",
"-C", "no-vectorize-loops",
]

# This runner will find a supported SWD debug probe and flash your RP2040 over
# SWD:
runner = "probe-rs run --chip RP2040"
14 changes: 10 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,21 @@ description = "I2C driver implementation using the RP2040's PIO peripheral."
documentation = "https://docs.rs/i2c-pio"
repository = "https://github.com/rp-rs/i2c-pio-rs"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[workspace]
members = ["on-target-tests"]

[dependencies]
cortex-m = "0.7.3"
eh1_0_alpha = { version = "=1.0.0-alpha.11", package = "embedded-hal", optional = true }
embedded-hal = "0.2.6"
embedded-hal = { version = "1.0.0" }
embedded_hal_0_2 = { version = "0.2.6", package = "embedded-hal" }
nb = "1.0.0"
pio = "0.2.0"
pio-proc = "0.2.0"
rp2040-hal = "0.9.0"
rp2040-hal = "0.9.1"
fugit = "0.3.5"
defmt = { version = "0.3.0", optional = true }
either = { version = "1.10.0", default-features = false }
heapless = { version = "0.8.0", default-features = false }

[patch.crates-io]
rp2040-hal = { git = "https://github.com/rp-rs/rp-hal" }
36 changes: 36 additions & 0 deletions memory.x
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
MEMORY {
BOOT2 : ORIGIN = 0x10000000, LENGTH = 0x100
FLASH : ORIGIN = 0x10000100, LENGTH = 2048K - 0x100
/*
* RAM consists of 4 banks, SRAM0-SRAM3, with a striped mapping.
* This is usually good for performance, as it distributes load on
* those banks evenly.
*/
RAM : ORIGIN = 0x20000000, LENGTH = 256K
/*
* RAM banks 4 and 5 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 = 0x20040000, LENGTH = 4k
SRAM5 : ORIGIN = 0x20041000, LENGTH = 4k

/* SRAM banks 0-3 can also be accessed directly. However, those ranges
alias with the RAM mapping, above. So don't use them at the same time!
SRAM0 : ORIGIN = 0x21000000, LENGTH = 64k
SRAM1 : ORIGIN = 0x21010000, LENGTH = 64k
SRAM2 : ORIGIN = 0x21020000, LENGTH = 64k
SRAM3 : ORIGIN = 0x21030000, LENGTH = 64k
*/
}

EXTERN(BOOT2_FIRMWARE)

SECTIONS {
/* ### Boot loader */
.boot2 ORIGIN(BOOT2) :
{
KEEP(*(.boot2));
} > BOOT2
} INSERT BEFORE .text;
14 changes: 14 additions & 0 deletions on-target-tests/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
**/*.rs.bk
.#*
.gdb_history
Cargo.lock
target/

# editor files
.vscode/*
!.vscode/*.md
!.vscode/*.svd
!.vscode/launch.json
!.vscode/tasks.json
!.vscode/extensions.json
!.vscode/settings.json
40 changes: 40 additions & 0 deletions on-target-tests/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
[package]
edition = "2021"
name = "on-target-tests"
version = "0.1.0"
publish = false

[[test]]
name = "i2c_loopback"
harness = false

[dependencies]
i2c-pio = { path = "../", features = ["defmt"] }

cortex-m = "0.7"
cortex-m-rt = "0.7"
embedded_hal_0_2 = { package = "embedded-hal", version = "0.2.5", features = [
"unproven",
] }
embedded-hal = "1.0.0"
embedded-hal-async = "1.0.0"
fugit = "0.3.5"

defmt = "0.3"
defmt-rtt = "0.4"
defmt-test = "0.3.1"
panic-probe = { version = "0.3", features = ["print-defmt"] }

rp2040-hal = { version = "0.9.1", features = [
"critical-section-impl",
"defmt",
"rt",
] }

rp2040-boot2 = "0.3.0"
critical-section = "1.0.0"
heapless = { version = "0.8.0", features = [
"portable-atomic-critical-section",
"defmt-03",
] }
itertools = { version = "0.12.0", default-features = false }
37 changes: 37 additions & 0 deletions on-target-tests/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Target tests for i2c-pio

This project is for running tests of i2c-pio against real hardware via knurling-rs tools.
It is based or rp2040-hal own on-target-tests.

Adding a test:
- Add a new Rust program to tests (eg tests/my_new_test.rs)
- Add a new [[test]] to the Cargo.toml

Running all tests:
Linux (and any other Unix-likes where probe-rs are supported):
```system
./run_tests.sh
```
Windows
```system
run_tests.bat
```

To run a specific test (to make developing tests faster)

```system
cargo test -p on-target-tests --test my_new_test
```

## Prerequisites

Some of the tests need connections between specific pins.

Currently, the following connections are required:

- Connect GPIO 0 to GPIO 2 (pins 1 and 4 on a Pico) and
connect GPIO 1 to GPIO 3 (pins 2 and 5 on a Pico) for the I2C loopback tests

If you add tests that need some hardware setup, make sure that they are
compatible to the existing on-target tests, so all tests can be run with
a single configuration.
15 changes: 15 additions & 0 deletions on-target-tests/memory.x
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
MEMORY {
BOOT2 : ORIGIN = 0x10000000, LENGTH = 0x100
FLASH : ORIGIN = 0x10000100, LENGTH = 2048K - 0x100
RAM : ORIGIN = 0x20000000, LENGTH = 256K
}

EXTERN(BOOT2_FIRMWARE)

SECTIONS {
/* ### Boot loader */
.boot2 ORIGIN(BOOT2) :
{
KEEP(*(.boot2));
} > BOOT2
} INSERT BEFORE .text;
123 changes: 123 additions & 0 deletions on-target-tests/tests/i2c_loopback.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
//! This test needs a connection between:
//!
//! | from GPIO (pico Pin) | to GPIO (pico Pin) |
//! | -------------------- | ------------------ |
//! | 0 (1) | 2 (4) |
//! | 1 (2) | 3 (5) |

#![no_std]
#![no_main]
#![cfg(test)]

use defmt_rtt as _; // defmt transport
use defmt_test as _;
use panic_probe as _;
use rp2040_hal as hal; // memory layout // panic handler

use hal::pac::interrupt;

/// The linker will place this boot block at the start of our program image. We
/// need this to help the ROM bootloader get our code up and running.
/// Note: This boot block is not necessary when using a rp-hal based BSP
/// as the BSPs already perform this step.
#[link_section = ".boot2"]
#[used]
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER_GENERIC_03H;

/// External high-speed crystal on the Raspberry Pi Pico board is 12 MHz. Adjust
/// if your board has a different frequency
const XTAL_FREQ_HZ: u32 = 12_000_000u32;

pub mod i2c_tests;

#[interrupt]
unsafe fn I2C1_IRQ() {
i2c_tests::blocking::peripheral_handler();
}

#[defmt_test::tests]
mod tests {
use crate::i2c_tests::{self, blocking::State, ADDR_10BIT, ADDR_7BIT};

#[init]
fn setup() -> State {
i2c_tests::blocking::system_setup(super::XTAL_FREQ_HZ, ADDR_7BIT)
}

#[test]
fn write(state: &mut State) {
i2c_tests::blocking::write(state, ADDR_7BIT);
i2c_tests::blocking::write(state, ADDR_10BIT);
}

#[test]
fn write_iter(state: &mut State) {
i2c_tests::blocking::write_iter(state, ADDR_7BIT);
i2c_tests::blocking::write_iter(state, ADDR_10BIT);
}

#[test]
fn write_iter_read(state: &mut State) {
i2c_tests::blocking::write_iter_read(state, ADDR_7BIT, 1..=1);
i2c_tests::blocking::write_iter_read(state, ADDR_10BIT, 2..=2);
}

#[test]
fn write_read(state: &mut State) {
i2c_tests::blocking::write_read(state, ADDR_7BIT, 1..=1);
i2c_tests::blocking::write_read(state, ADDR_10BIT, 2..=2);
}

#[test]
fn read(state: &mut State) {
i2c_tests::blocking::read(state, ADDR_7BIT, 0..=0);
i2c_tests::blocking::read(state, ADDR_10BIT, 1..=1);
}

#[test]
fn transactions_read(state: &mut State) {
i2c_tests::blocking::transactions_read(state, ADDR_7BIT, 0..=0);
i2c_tests::blocking::transactions_read(state, ADDR_10BIT, 1..=1);
}

#[test]
fn transactions_write(state: &mut State) {
i2c_tests::blocking::transactions_write(state, ADDR_7BIT);
i2c_tests::blocking::transactions_write(state, ADDR_10BIT);
}

#[test]
fn transactions_read_write(state: &mut State) {
i2c_tests::blocking::transactions_read_write(state, ADDR_7BIT, 1..=1);
i2c_tests::blocking::transactions_read_write(state, ADDR_10BIT, 2..=2);
}

#[test]
fn transactions_write_read(state: &mut State) {
i2c_tests::blocking::transactions_write_read(state, ADDR_7BIT, 1..=1);
i2c_tests::blocking::transactions_write_read(state, ADDR_10BIT, 2..=2);
}

#[test]
fn transaction(state: &mut State) {
i2c_tests::blocking::transaction(state, ADDR_7BIT, 7..=9);
i2c_tests::blocking::transaction(state, ADDR_10BIT, 7..=14);
}

#[test]
fn transactions_iter(state: &mut State) {
i2c_tests::blocking::transactions_iter(state, ADDR_7BIT, 1..=1);
i2c_tests::blocking::transactions_iter(state, ADDR_10BIT, 2..=2);
}

#[test]
fn embedded_hal(state: &mut State) {
i2c_tests::blocking::embedded_hal(state, ADDR_7BIT, 2..=2);
i2c_tests::blocking::embedded_hal(state, ADDR_10BIT, 2..=7);
}

// Sad paths:
// Peripheral Nack
//
// Arbritration conflict
}
Loading

0 comments on commit fcd05de

Please sign in to comment.