Skip to content

Commit 5e98514

Browse files
Merge pull request #196 from kalkyl/twis
Add TWIS module
2 parents bb94d90 + 66d209b commit 5e98514

File tree

9 files changed

+693
-0
lines changed

9 files changed

+693
-0
lines changed

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ members = [
1616
"examples/lpcomp-demo",
1717
"examples/qdec-demo",
1818
"examples/comp-demo",
19+
"examples/twim-demo",
20+
"examples/twis-demo",
1921
]
2022

2123
[profile.dev]

examples/twim-demo/Cargo.toml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
[package]
2+
name = "twim-demo"
3+
version = "0.1.0"
4+
authors = ["Henrik Alsér"]
5+
edition = "2018"
6+
7+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
8+
9+
[dependencies]
10+
cortex-m = "0.6.2"
11+
cortex-m-rtic = "0.5.3"
12+
rtt-target = {version = "0.2.0", features = ["cortex-m"] }
13+
nrf52840-hal = { features = ["rt"], path = "../../nrf52840-hal" }
14+
15+
[dependencies.embedded-hal]
16+
version = "0.2.3"
17+
features = ["unproven"]

examples/twim-demo/Embed.toml

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
[default.probe]
2+
# The index of the probe in the connected probe list.
3+
# probe_index = 0
4+
# The protocol to be used for communicating with the target.
5+
protocol = "Swd"
6+
# The speed in kHz of the data link to the target.
7+
# speed = 1337
8+
9+
[default.flashing]
10+
# Whether or not the target should be flashed.
11+
enabled = true
12+
# Whether or not the target should be halted after flashing.
13+
halt_afterwards = false
14+
# Whether or not bytes erased but not rewritten with data from the ELF
15+
# should be restored with their contents before erasing.
16+
restore_unwritten_bytes = false
17+
# The path where an SVG of the assembled flash layout should be written to.
18+
# flash_layout_output_path = "out.svg"
19+
20+
[default.general]
21+
# The chip name of the chip to be debugged.
22+
chip = "nRF52840"
23+
# A list of chip descriptions to be loaded during runtime.
24+
chip_descriptions = []
25+
# The default log level to be used.
26+
log_level = "Warn"
27+
28+
[default.rtt]
29+
# Whether or not an RTTUI should be opened after flashing.
30+
# This is exclusive and cannot be used with GDB at the moment.
31+
enabled = true
32+
# A list of channel associations to be displayed. If left empty, all channels are displayed.
33+
channels = [
34+
# { up = 0, down = 0, name = "name" }
35+
]
36+
# The duration in ms for which the logger should retry to attach to RTT.
37+
timeout = 3000
38+
# Whether timestamps in the RTTUI are enabled
39+
show_timestamps = true
40+
41+
[default.gdb]
42+
# Whether or not a GDB server should be opened after flashing.
43+
# This is exclusive and cannot be used with RTT at the moment.
44+
enabled = false
45+
# The connection string in host:port format wher the GDB server will open a socket.
46+
# gdb_connection_string

examples/twim-demo/src/main.rs

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
#![no_std]
2+
#![no_main]
3+
4+
#[allow(unused_imports)]
5+
use embedded_hal::blocking::i2c::{Read, Write};
6+
use embedded_hal::digital::v2::InputPin;
7+
use {
8+
core::{
9+
panic::PanicInfo,
10+
sync::atomic::{compiler_fence, Ordering},
11+
},
12+
hal::{
13+
gpio::{p0::Parts, Input, Pin, PullUp},
14+
gpiote::Gpiote,
15+
pac::TWIM0,
16+
twim::*,
17+
},
18+
nrf52840_hal as hal,
19+
rtic::cyccnt::U32Ext,
20+
rtt_target::{rprintln, rtt_init_print},
21+
};
22+
23+
#[rtic::app(device = crate::hal::pac, peripherals = true, monotonic = rtic::cyccnt::CYCCNT)]
24+
const APP: () = {
25+
struct Resources {
26+
twim: Twim<TWIM0>,
27+
gpiote: Gpiote,
28+
btn1: Pin<Input<PullUp>>,
29+
btn2: Pin<Input<PullUp>>,
30+
btn3: Pin<Input<PullUp>>,
31+
btn4: Pin<Input<PullUp>>,
32+
}
33+
34+
#[init]
35+
fn init(mut ctx: init::Context) -> init::LateResources {
36+
let _clocks = hal::clocks::Clocks::new(ctx.device.CLOCK).enable_ext_hfosc();
37+
ctx.core.DCB.enable_trace();
38+
ctx.core.DWT.enable_cycle_counter();
39+
rtt_init_print!();
40+
41+
let p0 = Parts::new(ctx.device.P0);
42+
let scl = p0.p0_30.into_floating_input().degrade();
43+
let sda = p0.p0_31.into_floating_input().degrade();
44+
let btn1 = p0.p0_11.into_pullup_input().degrade();
45+
let btn2 = p0.p0_12.into_pullup_input().degrade();
46+
let btn3 = p0.p0_24.into_pullup_input().degrade();
47+
let btn4 = p0.p0_25.into_pullup_input().degrade();
48+
49+
let gpiote = Gpiote::new(ctx.device.GPIOTE);
50+
gpiote.port().input_pin(&btn1).low();
51+
gpiote.port().input_pin(&btn2).low();
52+
gpiote.port().input_pin(&btn3).low();
53+
gpiote.port().input_pin(&btn4).low();
54+
gpiote.port().enable_interrupt();
55+
56+
let twim = Twim::new(ctx.device.TWIM0, Pins { scl, sda }, Frequency::K100);
57+
58+
init::LateResources {
59+
twim,
60+
gpiote,
61+
btn1,
62+
btn2,
63+
btn3,
64+
btn4,
65+
}
66+
}
67+
68+
#[idle]
69+
fn idle(_: idle::Context) -> ! {
70+
rprintln!("Press button 1 to READ from addr 0x1A");
71+
rprintln!("Press button 2 to WRITE to addr 0x1A");
72+
rprintln!("Press button 3 to READ from addr 0x1B");
73+
rprintln!("Press button 4 to WRITE from addr 0x1B");
74+
loop {
75+
cortex_m::asm::wfi();
76+
}
77+
}
78+
79+
#[task(binds = GPIOTE, resources = [gpiote], schedule = [debounce])]
80+
fn on_gpiote(ctx: on_gpiote::Context) {
81+
ctx.resources.gpiote.reset_events();
82+
ctx.schedule.debounce(ctx.start + 3_000_000.cycles()).ok();
83+
}
84+
85+
#[task(resources = [twim, gpiote, btn1, btn2, btn3, btn4])]
86+
fn debounce(ctx: debounce::Context) {
87+
let twim = ctx.resources.twim;
88+
if ctx.resources.btn1.is_low().unwrap() {
89+
rprintln!("\nREAD from address 0x1A");
90+
let rx_buf = &mut [0; 8][..];
91+
let res = twim.read(0x1A, rx_buf);
92+
rprintln!("Result: {:?}\n{:?}", res, rx_buf);
93+
}
94+
if ctx.resources.btn2.is_low().unwrap() {
95+
rprintln!("\nWRITE to address 0x1A");
96+
let tx_buf = [1, 2, 3, 4, 5, 6, 7, 8];
97+
let res = twim.write(0x1A, &tx_buf[..]);
98+
rprintln!("Result: {:?}\n{:?}", res, tx_buf);
99+
}
100+
if ctx.resources.btn3.is_low().unwrap() {
101+
rprintln!("\nREAD from address 0x1B");
102+
let rx_buf = &mut [0; 4][..];
103+
let res = twim.read(0x1B, rx_buf);
104+
rprintln!("Result: {:?}\n{:?}", res, rx_buf);
105+
}
106+
if ctx.resources.btn4.is_low().unwrap() {
107+
rprintln!("\nWRITE to address 0x1B");
108+
let tx_buf = [9, 10, 11, 12];
109+
let res = twim.write(0x1B, &tx_buf[..]);
110+
rprintln!("Result: {:?}\n{:?}", res, tx_buf);
111+
}
112+
}
113+
114+
extern "C" {
115+
fn SWI0_EGU0();
116+
}
117+
};
118+
119+
#[inline(never)]
120+
#[panic_handler]
121+
fn panic(info: &PanicInfo) -> ! {
122+
cortex_m::interrupt::disable();
123+
rprintln!("{}", info);
124+
loop {
125+
compiler_fence(Ordering::SeqCst);
126+
}
127+
}

examples/twis-demo/Cargo.toml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
[package]
2+
name = "twis-demo"
3+
version = "0.1.0"
4+
authors = ["Henrik Alsér"]
5+
edition = "2018"
6+
7+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
8+
9+
[dependencies]
10+
cortex-m = "0.6.2"
11+
cortex-m-rtic = "0.5.3"
12+
rtt-target = {version = "0.2.0", features = ["cortex-m"] }
13+
nrf52840-hal = { features = ["rt"], path = "../../nrf52840-hal" }
14+
15+
[dependencies.embedded-hal]
16+
version = "0.2.3"
17+
features = ["unproven"]

examples/twis-demo/Embed.toml

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
[default.probe]
2+
# The index of the probe in the connected probe list.
3+
# probe_index = 0
4+
# The protocol to be used for communicating with the target.
5+
protocol = "Swd"
6+
# The speed in kHz of the data link to the target.
7+
# speed = 1337
8+
9+
[default.flashing]
10+
# Whether or not the target should be flashed.
11+
enabled = true
12+
# Whether or not the target should be halted after flashing.
13+
halt_afterwards = false
14+
# Whether or not bytes erased but not rewritten with data from the ELF
15+
# should be restored with their contents before erasing.
16+
restore_unwritten_bytes = false
17+
# The path where an SVG of the assembled flash layout should be written to.
18+
# flash_layout_output_path = "out.svg"
19+
20+
[default.general]
21+
# The chip name of the chip to be debugged.
22+
chip = "nRF52840"
23+
# A list of chip descriptions to be loaded during runtime.
24+
chip_descriptions = []
25+
# The default log level to be used.
26+
log_level = "Warn"
27+
28+
[default.rtt]
29+
# Whether or not an RTTUI should be opened after flashing.
30+
# This is exclusive and cannot be used with GDB at the moment.
31+
enabled = true
32+
# A list of channel associations to be displayed. If left empty, all channels are displayed.
33+
channels = [
34+
# { up = 0, down = 0, name = "name" }
35+
]
36+
# The duration in ms for which the logger should retry to attach to RTT.
37+
timeout = 3000
38+
# Whether timestamps in the RTTUI are enabled
39+
show_timestamps = true
40+
41+
[default.gdb]
42+
# Whether or not a GDB server should be opened after flashing.
43+
# This is exclusive and cannot be used with RTT at the moment.
44+
enabled = false
45+
# The connection string in host:port format wher the GDB server will open a socket.
46+
# gdb_connection_string

examples/twis-demo/src/main.rs

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
#![no_std]
2+
#![no_main]
3+
4+
use embedded_hal::digital::v2::OutputPin;
5+
use {
6+
core::{
7+
panic::PanicInfo,
8+
sync::atomic::{compiler_fence, Ordering},
9+
},
10+
hal::{
11+
gpio::{p0::Parts, Level, Output, Pin, PushPull},
12+
pac::TWIS0,
13+
twis::*,
14+
},
15+
nrf52840_hal as hal,
16+
rtt_target::{rprintln, rtt_init_print},
17+
};
18+
19+
const ADDR0: u8 = 0x1A;
20+
const ADDR1: u8 = 0x1B;
21+
const BUF0_SZ: usize = 8;
22+
const BUF1_SZ: usize = 4;
23+
24+
#[rtic::app(device = crate::hal::pac, peripherals = true)]
25+
const APP: () = {
26+
struct Resources {
27+
twis: Twis<TWIS0>,
28+
#[init([0; BUF0_SZ])]
29+
buffer0: [u8; BUF0_SZ],
30+
#[init([0; BUF1_SZ])]
31+
buffer1: [u8; BUF1_SZ],
32+
led: Pin<Output<PushPull>>,
33+
}
34+
35+
#[init]
36+
fn init(ctx: init::Context) -> init::LateResources {
37+
let _clocks = hal::clocks::Clocks::new(ctx.device.CLOCK).enable_ext_hfosc();
38+
rtt_init_print!();
39+
40+
let p0 = Parts::new(ctx.device.P0);
41+
let led = p0.p0_06.into_push_pull_output(Level::High).degrade();
42+
let scl = p0.p0_14.into_floating_input().degrade();
43+
let sda = p0.p0_16.into_floating_input().degrade();
44+
45+
let twis = Twis::new(ctx.device.TWIS0, Pins { scl, sda }, ADDR0);
46+
twis.address1(ADDR1) // Add a secondary i2c address
47+
.enable_interrupt(TwiEvent::Write) // Trigger interrupt on WRITE command
48+
.enable_interrupt(TwiEvent::Read) // Trigger interrupt on READ command
49+
.enable();
50+
51+
init::LateResources { twis, led }
52+
}
53+
54+
#[idle]
55+
fn idle(_: idle::Context) -> ! {
56+
rprintln!("Waiting for commands from controller...");
57+
loop {
58+
cortex_m::asm::wfi();
59+
}
60+
}
61+
62+
#[task(binds = SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0, resources = [twis, buffer0, buffer1, led])]
63+
fn on_twis(ctx: on_twis::Context) {
64+
let twis = ctx.resources.twis;
65+
let buffer0 = ctx.resources.buffer0;
66+
let buffer1 = ctx.resources.buffer1;
67+
let led = ctx.resources.led;
68+
69+
if twis.is_event_triggered(TwiEvent::Read) {
70+
twis.reset_event(TwiEvent::Read);
71+
led.set_low().ok();
72+
rprintln!("\nREAD cmd received on addr 0x{:x}", twis.address_match());
73+
rprintln!("Writing data to controller...");
74+
match twis.address_match() {
75+
ADDR0 => {
76+
let res = twis.tx(&buffer0[..]);
77+
rprintln!("Result: {:?}\n{:?}", res, buffer0);
78+
}
79+
ADDR1 => {
80+
let res = twis.tx(&buffer1[..]);
81+
rprintln!("Result: {:?}\n{:?}", res, buffer1);
82+
}
83+
_ => unreachable!(),
84+
}
85+
}
86+
if twis.is_event_triggered(TwiEvent::Write) {
87+
twis.reset_event(TwiEvent::Write);
88+
led.set_high().ok();
89+
rprintln!("\nWRITE cmd received on addr 0x{:x}", twis.address_match());
90+
rprintln!("Reading data from controller...");
91+
match twis.address_match() {
92+
ADDR0 => {
93+
let res = twis.rx(&mut buffer0[..]);
94+
rprintln!("Result: {:?}\n{:?}", res, buffer0);
95+
}
96+
ADDR1 => {
97+
let res = twis.rx(&mut buffer1[..]);
98+
rprintln!("Result: {:?}\n{:?}", res, buffer1);
99+
}
100+
_ => unreachable!(),
101+
}
102+
}
103+
}
104+
};
105+
106+
#[inline(never)]
107+
#[panic_handler]
108+
fn panic(info: &PanicInfo) -> ! {
109+
cortex_m::interrupt::disable();
110+
rprintln!("{}", info);
111+
loop {
112+
compiler_fence(Ordering::SeqCst);
113+
}
114+
}

nrf-hal-common/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ pub mod timer;
6060
pub mod twi;
6161
#[cfg(not(feature = "51"))]
6262
pub mod twim;
63+
#[cfg(not(any(feature = "51", feature = "9160")))]
64+
pub mod twis;
6365
#[cfg(feature = "51")]
6466
pub mod uart;
6567
#[cfg(not(feature = "51"))]

0 commit comments

Comments
 (0)