Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add on-target-tests and prepare for async implementation #25

Merged
merged 5 commits into from
Mar 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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"
11 changes: 7 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,18 @@ 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.10.0"
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 }
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.10.0", 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.
130 changes: 130 additions & 0 deletions on-target-tests/tests/i2c_loopback.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
//! 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 on Addr
#[test]
fn nak_on_addr(state: &mut State) {
i2c_tests::blocking::nak_on_addr(state, ADDR_7BIT, ADDR_7BIT + 1);
i2c_tests::blocking::nak_on_addr(state, ADDR_10BIT, ADDR_10BIT + 1);
i2c_tests::blocking::nak_on_addr(state, ADDR_10BIT, ADDR_10BIT + 0x100);
}
// Peripheral Nack on Data
//
// Arbritration conflict
}
Loading
Loading