forked from tock/libtock-rs
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
examples: i2c: add master/slave examples
Adds a master/slave sample that can be used to communicate with eachother. These two samples were verified using 2x Particle Borons (nrf52840 based). With one sample running on one board, the other on the 2nd board. Signed-off-by: Wilfred Mallawa <wilfred.mallawa@wdc.com>
- Loading branch information
Showing
2 changed files
with
177 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
//! This sample demonstrates setting up the i2c ip (assuming board has support) | ||
//! for master mode. In the event loop, we write some bytes to the target, then | ||
//! attempt to read some bytes from the target. | ||
//! | ||
//! This sample is tested with `i2c_slave_send_recv.rs` sample running on the | ||
//! slave device. That sample uses the synchronous slave api, so the order of operations | ||
//! is important to ensure we don't cause the slave to stretch clocks if it hasn't setup | ||
//! send buffers in time. | ||
#![no_main] | ||
#![no_std] | ||
use core::fmt::Write; | ||
use libtock::alarm::{Alarm, Milliseconds}; | ||
use libtock::console::Console; | ||
use libtock::i2c_master_slave::I2CMasterSlave; | ||
use libtock::runtime::{set_main, stack_size}; | ||
|
||
set_main! {main} | ||
stack_size! {0x400} | ||
|
||
pub const SLAVE_DEVICE_ADDR: u16 = 0x69; | ||
|
||
fn main() { | ||
let addr = SLAVE_DEVICE_ADDR; | ||
// 7-bit addressing | ||
assert!(addr <= 0x7f); | ||
let mut tx_buf: [u8; 4] = [0; 4]; | ||
// Write 4 bytes to the slave | ||
let tx_len = 4; | ||
let mut rx_buf: [u8; 2] = [0; 2]; | ||
// Attempt to read 2 bytes from the slave | ||
let rx_len = 2; | ||
|
||
writeln!(Console::writer(), "i2c-master: write-read sample\r").unwrap(); | ||
writeln!( | ||
Console::writer(), | ||
"i2c-master: slave address 0x{:x}!\r", | ||
addr | ||
) | ||
.unwrap(); | ||
|
||
let mut i: u32 = 0; | ||
loop { | ||
writeln!( | ||
Console::writer(), | ||
"i2c-master: write-read operation {:?}\r", | ||
i | ||
) | ||
.unwrap(); | ||
|
||
// Change up the data in tx-buffer | ||
tx_buf[0] = tx_buf[0].wrapping_add(2); | ||
tx_buf[1] = tx_buf[1].wrapping_add(4); | ||
tx_buf[2] = tx_buf[2].wrapping_add(6); | ||
tx_buf[3] = tx_buf[3].wrapping_add(8); | ||
|
||
if let Err(why) = I2CMasterSlave::i2c_master_slave_write_sync(addr, &tx_buf, tx_len) { | ||
writeln!( | ||
Console::writer(), | ||
"i2c-master: write operation failed {:?}", | ||
why | ||
) | ||
.unwrap(); | ||
} else { | ||
// This sample target the i2c_slave_send_recv.rs sample, which is synchronous. | ||
// so allow some time for it to setup 'send' buffer. | ||
Alarm::sleep_for(Milliseconds(200)).unwrap(); | ||
|
||
let r = I2CMasterSlave::i2c_master_slave_read_sync(addr, &mut rx_buf, rx_len); | ||
match r.1 { | ||
Ok(()) => { | ||
writeln!( | ||
Console::writer(), | ||
"{:} bytes read from slave | data received (0h): {:x?}\r\n", | ||
r.0, | ||
rx_buf | ||
) | ||
.unwrap(); | ||
} | ||
Err(why) => { | ||
writeln!( | ||
Console::writer(), | ||
"i2c-master: read operation failed {:?}", | ||
why | ||
) | ||
.unwrap(); | ||
} | ||
} | ||
i += 1; | ||
} | ||
Alarm::sleep_for(Milliseconds(1000)).unwrap(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
//! This sample demonstrates setting up the i2c ip (assuming board has support) | ||
//! for target mode. In the event loop, we first expect the master to write some data | ||
//! then we setup a response packet. | ||
//! | ||
//! NOTE: The device (based on hwip) may stretch clocks by holding the SCL line low if the master attempts to | ||
//! read data before we have setup the read data buffers. | ||
//! | ||
//! This sample is tested with `i2c_master_write_read.rs` sample running on the | ||
//! master device. | ||
#![no_main] | ||
#![no_std] | ||
use core::fmt::Write; | ||
use libtock::console::Console; | ||
use libtock::i2c_master_slave::I2CMasterSlave; | ||
use libtock::runtime::{set_main, stack_size}; | ||
|
||
set_main! {main} | ||
stack_size! {0x400} | ||
pub const SLAVE_DEVICE_ADDR: u8 = 0x69; | ||
fn main() { | ||
let mut rx_buf: [u8; 8] = [0; 8]; | ||
let mut tx_buf: [u8; 8] = [0; 8]; | ||
let addr: u8 = SLAVE_DEVICE_ADDR; | ||
// 7-bit addressing | ||
assert!(addr <= 0x7f); | ||
|
||
writeln!(Console::writer(), "i2c-slave: setting up\r").unwrap(); | ||
writeln!(Console::writer(), "i2c-slave: address 0x{:x}!\r", addr).unwrap(); | ||
|
||
I2CMasterSlave::i2c_master_slave_set_slave_address(addr).expect("i2c-target: Failed to listen"); | ||
let mut i: u32 = 0; | ||
loop { | ||
writeln!(Console::writer(), "i2c-slave: operation {:?}\r", i).unwrap(); | ||
|
||
// Expect a write, if the master reads here, the IP may stretch clocks! | ||
let r = I2CMasterSlave::i2c_master_slave_write_recv_sync(&mut rx_buf); | ||
|
||
if let Err(why) = r.1 { | ||
writeln!( | ||
Console::writer(), | ||
"i2c-slave: error to receiving data {:?}\r", | ||
why | ||
) | ||
.unwrap(); | ||
} else { | ||
writeln!( | ||
Console::writer(), | ||
"{:} bytes received from master | buf: {:x?}\r", | ||
r.0, | ||
rx_buf | ||
) | ||
.unwrap(); | ||
|
||
// Note: The master should allow a little delay when communicating with this slave | ||
// as we are doing everything synchronously. | ||
// Expect a 2 byte read by master and let's keep changing the values | ||
tx_buf[0] = tx_buf[0].wrapping_add(1); | ||
tx_buf[1] = tx_buf[1].wrapping_add(5); | ||
let r = I2CMasterSlave::i2c_master_slave_read_send_sync(&tx_buf, tx_buf.len()); | ||
|
||
match r.1 { | ||
Ok(()) => { | ||
writeln!( | ||
Console::writer(), | ||
"{:} bytes read by master | data sent: {:x?}\r", | ||
r.0, | ||
tx_buf | ||
) | ||
.unwrap(); | ||
i += 1; | ||
} | ||
Err(why) => { | ||
writeln!( | ||
Console::writer(), | ||
"i2c-slave: error setting up read_send {:?}\r", | ||
why | ||
) | ||
.unwrap(); | ||
} | ||
} | ||
} | ||
} | ||
} |