984: rp pico async i2c implementation r=Dirbaio a=jsgf This implements an interrupt-driven async i2c master. It is based on https://github.com/embassy-rs/embassy/pull/914, a bit of https://github.com/embassy-rs/embassy/pull/978 and `@ithinuel's` https://github.com/ithinuel/rp2040-async-i2c.git This is still work-in-progress, and is currently untested. 1006: Removes some of the code duplication for UarteWithIdle r=Dirbaio a=huntc This PR removes some of the code duplications for `UarteWithIdle` at the slight expense of requiring a split when using idle processing. As the nRF example illustrates though given the LoC removed, this expense seems worth the benefit in terms of maintenance, and the avoidance of copying over methods. My main motivation for this PR was actually due to the `event_endtx` method not having been copied across to the idle-related code. Tested the uart_idle example on my nRF52840-dk, and from within my app. Both appear to work fine. Co-authored-by: Jeremy Fitzhardinge <jeremy@goop.org> Co-authored-by: huntc <huntchr@gmail.com>
This commit is contained in:
@ -31,3 +31,6 @@ embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.9" }
|
||||
embedded-hal-async = { version = "0.1.0-alpha.1" }
|
||||
embedded-io = { version = "0.3.0", features = ["async", "defmt"] }
|
||||
static_cell = "1.0.0"
|
||||
|
||||
[profile.release]
|
||||
debug = true
|
||||
|
102
examples/rp/src/bin/i2c_async.rs
Normal file
102
examples/rp/src/bin/i2c_async.rs
Normal file
@ -0,0 +1,102 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
use defmt::*;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_rp::i2c::{self, Config};
|
||||
use embassy_rp::interrupt;
|
||||
use embassy_time::{Duration, Timer};
|
||||
use embedded_hal_async::i2c::I2c;
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
#[allow(dead_code)]
|
||||
mod mcp23017 {
|
||||
pub const ADDR: u8 = 0x20; // default addr
|
||||
|
||||
macro_rules! mcpregs {
|
||||
($($name:ident : $val:expr),* $(,)?) => {
|
||||
$(
|
||||
pub const $name: u8 = $val;
|
||||
)*
|
||||
|
||||
pub fn regname(reg: u8) -> &'static str {
|
||||
match reg {
|
||||
$(
|
||||
$val => stringify!($name),
|
||||
)*
|
||||
_ => panic!("bad reg"),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// These are correct for IOCON.BANK=0
|
||||
mcpregs! {
|
||||
IODIRA: 0x00,
|
||||
IPOLA: 0x02,
|
||||
GPINTENA: 0x04,
|
||||
DEFVALA: 0x06,
|
||||
INTCONA: 0x08,
|
||||
IOCONA: 0x0A,
|
||||
GPPUA: 0x0C,
|
||||
INTFA: 0x0E,
|
||||
INTCAPA: 0x10,
|
||||
GPIOA: 0x12,
|
||||
OLATA: 0x14,
|
||||
IODIRB: 0x01,
|
||||
IPOLB: 0x03,
|
||||
GPINTENB: 0x05,
|
||||
DEFVALB: 0x07,
|
||||
INTCONB: 0x09,
|
||||
IOCONB: 0x0B,
|
||||
GPPUB: 0x0D,
|
||||
INTFB: 0x0F,
|
||||
INTCAPB: 0x11,
|
||||
GPIOB: 0x13,
|
||||
OLATB: 0x15,
|
||||
}
|
||||
}
|
||||
|
||||
#[embassy_executor::main]
|
||||
async fn main(_spawner: Spawner) {
|
||||
let p = embassy_rp::init(Default::default());
|
||||
|
||||
let sda = p.PIN_14;
|
||||
let scl = p.PIN_15;
|
||||
let irq = interrupt::take!(I2C1_IRQ);
|
||||
|
||||
info!("set up i2c ");
|
||||
let mut i2c = i2c::I2c::new_async(p.I2C1, scl, sda, irq, Config::default());
|
||||
|
||||
use mcp23017::*;
|
||||
|
||||
info!("init mcp23017 config for IxpandO");
|
||||
// init - a outputs, b inputs
|
||||
i2c.write(ADDR, &[IODIRA, 0x00]).await.unwrap();
|
||||
i2c.write(ADDR, &[IODIRB, 0xff]).await.unwrap();
|
||||
i2c.write(ADDR, &[GPPUB, 0xff]).await.unwrap(); // pullups
|
||||
|
||||
let mut val = 1;
|
||||
loop {
|
||||
let mut portb = [0];
|
||||
|
||||
i2c.write_read(mcp23017::ADDR, &[GPIOB], &mut portb).await.unwrap();
|
||||
info!("portb = {:02x}", portb[0]);
|
||||
i2c.write(mcp23017::ADDR, &[GPIOA, val | portb[0]]).await.unwrap();
|
||||
val = val.rotate_left(1);
|
||||
|
||||
// get a register dump
|
||||
info!("getting register dump");
|
||||
let mut regs = [0; 22];
|
||||
i2c.write_read(ADDR, &[0], &mut regs).await.unwrap();
|
||||
// always get the regdump but only display it if portb'0 is set
|
||||
if portb[0] & 1 != 0 {
|
||||
for (idx, reg) in regs.into_iter().enumerate() {
|
||||
info!("{} => {:02x}", regname(idx as u8), reg);
|
||||
}
|
||||
}
|
||||
|
||||
Timer::after(Duration::from_millis(100)).await;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user