Skip to content

Commit c24a3d3

Browse files
authored
Merge pull request #25 from ithinuel/prepare-for-async
Add on-target-tests and prepare for async implementation
2 parents a4523d6 + dcf69d3 commit c24a3d3

15 files changed

+1651
-557
lines changed

.cargo/config.toml

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#
2+
# Cargo Configuration for the https://github.com/rp-rs/rp-hal.git repository.
3+
#
4+
# Copyright (c) The RP-RS Developers, 2021
5+
#
6+
# You might want to make a similar file in your own repository if you are
7+
# writing programs for Raspberry Silicon microcontrollers.
8+
#
9+
# This file is MIT or Apache-2.0 as per the repository README.md file
10+
#
11+
12+
[build]
13+
# Set the default target to match the Cortex-M0+ in the RP2040
14+
target = "thumbv6m-none-eabi"
15+
16+
# Target specific options
17+
[target.thumbv6m-none-eabi]
18+
# Pass some extra options to rustc, some of which get passed on to the linker.
19+
#
20+
# * linker argument --nmagic turns off page alignment of sections (which saves
21+
# flash space)
22+
# * linker argument -Tlink.x tells the linker to use link.x as the linker
23+
# script. This is usually provided by the cortex-m-rt crate, and by default
24+
# the version in that crate will include a file called `memory.x` which
25+
# describes the particular memory layout for your specific chip.
26+
# * inline-threshold=5 makes the compiler more aggressive and inlining functions
27+
# * no-vectorize-loops turns off the loop vectorizer (seeing as the M0+ doesn't
28+
# have SIMD)
29+
rustflags = [
30+
"-C", "link-arg=--nmagic",
31+
"-C", "link-arg=-Tlink.x",
32+
"-C", "link-arg=-Tdefmt.x",
33+
"-C", "inline-threshold=5",
34+
"-C", "no-vectorize-loops",
35+
]
36+
37+
# This runner will find a supported SWD debug probe and flash your RP2040 over
38+
# SWD:
39+
runner = "probe-rs run --chip RP2040"

Cargo.toml

+7-4
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,18 @@ description = "I2C driver implementation using the RP2040's PIO peripheral."
77
documentation = "https://docs.rs/i2c-pio"
88
repository = "https://github.com/rp-rs/i2c-pio-rs"
99

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

1213
[dependencies]
1314
cortex-m = "0.7.3"
14-
eh1_0_alpha = { version = "=1.0.0-alpha.11", package = "embedded-hal", optional = true }
15-
embedded-hal = "0.2.6"
15+
embedded-hal = { version = "1.0.0" }
16+
embedded_hal_0_2 = { version = "0.2.6", package = "embedded-hal" }
1617
nb = "1.0.0"
1718
pio = "0.2.0"
1819
pio-proc = "0.2.0"
19-
rp2040-hal = "0.9.0"
20+
rp2040-hal = "0.10.0"
2021
fugit = "0.3.5"
2122
defmt = { version = "0.3.0", optional = true }
23+
either = { version = "1.10.0", default-features = false }
24+
heapless = { version = "0.8.0", default-features = false }

memory.x

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
MEMORY {
2+
BOOT2 : ORIGIN = 0x10000000, LENGTH = 0x100
3+
FLASH : ORIGIN = 0x10000100, LENGTH = 2048K - 0x100
4+
/*
5+
* RAM consists of 4 banks, SRAM0-SRAM3, with a striped mapping.
6+
* This is usually good for performance, as it distributes load on
7+
* those banks evenly.
8+
*/
9+
RAM : ORIGIN = 0x20000000, LENGTH = 256K
10+
/*
11+
* RAM banks 4 and 5 use a direct mapping. They can be used to have
12+
* memory areas dedicated for some specific job, improving predictability
13+
* of access times.
14+
* Example: Separate stacks for core0 and core1.
15+
*/
16+
SRAM4 : ORIGIN = 0x20040000, LENGTH = 4k
17+
SRAM5 : ORIGIN = 0x20041000, LENGTH = 4k
18+
19+
/* SRAM banks 0-3 can also be accessed directly. However, those ranges
20+
alias with the RAM mapping, above. So don't use them at the same time!
21+
SRAM0 : ORIGIN = 0x21000000, LENGTH = 64k
22+
SRAM1 : ORIGIN = 0x21010000, LENGTH = 64k
23+
SRAM2 : ORIGIN = 0x21020000, LENGTH = 64k
24+
SRAM3 : ORIGIN = 0x21030000, LENGTH = 64k
25+
*/
26+
}
27+
28+
EXTERN(BOOT2_FIRMWARE)
29+
30+
SECTIONS {
31+
/* ### Boot loader */
32+
.boot2 ORIGIN(BOOT2) :
33+
{
34+
KEEP(*(.boot2));
35+
} > BOOT2
36+
} INSERT BEFORE .text;

on-target-tests/.gitignore

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
**/*.rs.bk
2+
.#*
3+
.gdb_history
4+
Cargo.lock
5+
target/
6+
7+
# editor files
8+
.vscode/*
9+
!.vscode/*.md
10+
!.vscode/*.svd
11+
!.vscode/launch.json
12+
!.vscode/tasks.json
13+
!.vscode/extensions.json
14+
!.vscode/settings.json

on-target-tests/Cargo.toml

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
[package]
2+
edition = "2021"
3+
name = "on-target-tests"
4+
version = "0.1.0"
5+
publish = false
6+
7+
[[test]]
8+
name = "i2c_loopback"
9+
harness = false
10+
11+
[dependencies]
12+
i2c-pio = { path = "../", features = ["defmt"] }
13+
14+
cortex-m = "0.7"
15+
cortex-m-rt = "0.7"
16+
embedded_hal_0_2 = { package = "embedded-hal", version = "0.2.5", features = [
17+
"unproven",
18+
] }
19+
embedded-hal = "1.0.0"
20+
embedded-hal-async = "1.0.0"
21+
fugit = "0.3.5"
22+
23+
defmt = "0.3"
24+
defmt-rtt = "0.4"
25+
defmt-test = "0.3.1"
26+
panic-probe = { version = "0.3", features = ["print-defmt"] }
27+
28+
rp2040-hal = { version = "0.10.0", features = [
29+
"critical-section-impl",
30+
"defmt",
31+
"rt",
32+
] }
33+
34+
rp2040-boot2 = "0.3.0"
35+
critical-section = "1.0.0"
36+
heapless = { version = "0.8.0", features = [
37+
"portable-atomic-critical-section",
38+
"defmt-03",
39+
] }
40+
itertools = { version = "0.12.0", default-features = false }

on-target-tests/README.md

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Target tests for i2c-pio
2+
3+
This project is for running tests of i2c-pio against real hardware via knurling-rs tools.
4+
It is based or rp2040-hal own on-target-tests.
5+
6+
Adding a test:
7+
- Add a new Rust program to tests (eg tests/my_new_test.rs)
8+
- Add a new [[test]] to the Cargo.toml
9+
10+
Running all tests:
11+
Linux (and any other Unix-likes where probe-rs are supported):
12+
```system
13+
./run_tests.sh
14+
```
15+
Windows
16+
```system
17+
run_tests.bat
18+
```
19+
20+
To run a specific test (to make developing tests faster)
21+
22+
```system
23+
cargo test -p on-target-tests --test my_new_test
24+
```
25+
26+
## Prerequisites
27+
28+
Some of the tests need connections between specific pins.
29+
30+
Currently, the following connections are required:
31+
32+
- Connect GPIO 0 to GPIO 2 (pins 1 and 4 on a Pico) and
33+
connect GPIO 1 to GPIO 3 (pins 2 and 5 on a Pico) for the I2C loopback tests
34+
35+
If you add tests that need some hardware setup, make sure that they are
36+
compatible to the existing on-target tests, so all tests can be run with
37+
a single configuration.

on-target-tests/tests/i2c_loopback.rs

+130
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
//! This test needs a connection between:
2+
//!
3+
//! | from GPIO (pico Pin) | to GPIO (pico Pin) |
4+
//! | -------------------- | ------------------ |
5+
//! | 0 (1) | 2 (4) |
6+
//! | 1 (2) | 3 (5) |
7+
8+
#![no_std]
9+
#![no_main]
10+
#![cfg(test)]
11+
12+
use defmt_rtt as _; // defmt transport
13+
use defmt_test as _;
14+
use panic_probe as _;
15+
use rp2040_hal as hal; // memory layout // panic handler
16+
17+
use hal::pac::interrupt;
18+
19+
/// The linker will place this boot block at the start of our program image. We
20+
/// need this to help the ROM bootloader get our code up and running.
21+
/// Note: This boot block is not necessary when using a rp-hal based BSP
22+
/// as the BSPs already perform this step.
23+
#[link_section = ".boot2"]
24+
#[used]
25+
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER_GENERIC_03H;
26+
27+
/// External high-speed crystal on the Raspberry Pi Pico board is 12 MHz. Adjust
28+
/// if your board has a different frequency
29+
const XTAL_FREQ_HZ: u32 = 12_000_000u32;
30+
31+
pub mod i2c_tests;
32+
33+
#[interrupt]
34+
unsafe fn I2C1_IRQ() {
35+
i2c_tests::blocking::peripheral_handler();
36+
}
37+
38+
#[defmt_test::tests]
39+
mod tests {
40+
use crate::i2c_tests::{self, blocking::State, ADDR_10BIT, ADDR_7BIT};
41+
42+
#[init]
43+
fn setup() -> State {
44+
i2c_tests::blocking::system_setup(super::XTAL_FREQ_HZ, ADDR_7BIT)
45+
}
46+
47+
#[test]
48+
fn write(state: &mut State) {
49+
i2c_tests::blocking::write(state, ADDR_7BIT);
50+
i2c_tests::blocking::write(state, ADDR_10BIT);
51+
}
52+
53+
#[test]
54+
fn write_iter(state: &mut State) {
55+
i2c_tests::blocking::write_iter(state, ADDR_7BIT);
56+
i2c_tests::blocking::write_iter(state, ADDR_10BIT);
57+
}
58+
59+
#[test]
60+
fn write_iter_read(state: &mut State) {
61+
i2c_tests::blocking::write_iter_read(state, ADDR_7BIT, 1..=1);
62+
i2c_tests::blocking::write_iter_read(state, ADDR_10BIT, 2..=2);
63+
}
64+
65+
#[test]
66+
fn write_read(state: &mut State) {
67+
i2c_tests::blocking::write_read(state, ADDR_7BIT, 1..=1);
68+
i2c_tests::blocking::write_read(state, ADDR_10BIT, 2..=2);
69+
}
70+
71+
#[test]
72+
fn read(state: &mut State) {
73+
i2c_tests::blocking::read(state, ADDR_7BIT, 0..=0);
74+
i2c_tests::blocking::read(state, ADDR_10BIT, 1..=1);
75+
}
76+
77+
#[test]
78+
fn transactions_read(state: &mut State) {
79+
i2c_tests::blocking::transactions_read(state, ADDR_7BIT, 0..=0);
80+
i2c_tests::blocking::transactions_read(state, ADDR_10BIT, 1..=1);
81+
}
82+
83+
#[test]
84+
fn transactions_write(state: &mut State) {
85+
i2c_tests::blocking::transactions_write(state, ADDR_7BIT);
86+
i2c_tests::blocking::transactions_write(state, ADDR_10BIT);
87+
}
88+
89+
#[test]
90+
fn transactions_read_write(state: &mut State) {
91+
i2c_tests::blocking::transactions_read_write(state, ADDR_7BIT, 1..=1);
92+
i2c_tests::blocking::transactions_read_write(state, ADDR_10BIT, 2..=2);
93+
}
94+
95+
#[test]
96+
fn transactions_write_read(state: &mut State) {
97+
i2c_tests::blocking::transactions_write_read(state, ADDR_7BIT, 1..=1);
98+
i2c_tests::blocking::transactions_write_read(state, ADDR_10BIT, 2..=2);
99+
}
100+
101+
#[test]
102+
fn transaction(state: &mut State) {
103+
i2c_tests::blocking::transaction(state, ADDR_7BIT, 7..=9);
104+
i2c_tests::blocking::transaction(state, ADDR_10BIT, 7..=14);
105+
}
106+
107+
#[test]
108+
fn transactions_iter(state: &mut State) {
109+
i2c_tests::blocking::transactions_iter(state, ADDR_7BIT, 1..=1);
110+
i2c_tests::blocking::transactions_iter(state, ADDR_10BIT, 2..=2);
111+
}
112+
113+
#[test]
114+
fn embedded_hal(state: &mut State) {
115+
i2c_tests::blocking::embedded_hal(state, ADDR_7BIT, 2..=2);
116+
i2c_tests::blocking::embedded_hal(state, ADDR_10BIT, 2..=7);
117+
}
118+
119+
// Sad paths:
120+
// Peripheral Nack on Addr
121+
#[test]
122+
fn nak_on_addr(state: &mut State) {
123+
i2c_tests::blocking::nak_on_addr(state, ADDR_7BIT, ADDR_7BIT + 1);
124+
i2c_tests::blocking::nak_on_addr(state, ADDR_10BIT, ADDR_10BIT + 1);
125+
i2c_tests::blocking::nak_on_addr(state, ADDR_10BIT, ADDR_10BIT + 0x100);
126+
}
127+
// Peripheral Nack on Data
128+
//
129+
// Arbritration conflict
130+
}

0 commit comments

Comments
 (0)