diff options
| author | Caleb Jamison <[email protected]> | 2023-08-14 16:50:57 -0400 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2023-09-10 23:01:15 +0200 |
| commit | 26e0823c3507a537d72fa5d6d7e97126314c0f0c (patch) | |
| tree | 12336d61c85117019e4012531c89ffb64a12c5cc /tests | |
| parent | ceca8b4336d8706a9e767c0d397182d02527d8cc (diff) | |
rp2040 I2cDevice
Move i2c to mod, split device and controller
Remove mode generic:
I don't think it's reasonable to use the i2c in device mode while
blocking, so I'm cutting the generic.
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/rp/src/bin/i2c.rs | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/tests/rp/src/bin/i2c.rs b/tests/rp/src/bin/i2c.rs new file mode 100644 index 000000000..63dd00233 --- /dev/null +++ b/tests/rp/src/bin/i2c.rs | |||
| @@ -0,0 +1,215 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | |||
| 5 | use defmt::{assert_eq, info, panic, unwrap}; | ||
| 6 | use embassy_executor::Executor; | ||
| 7 | use embassy_executor::_export::StaticCell; | ||
| 8 | use embassy_rp::bind_interrupts; | ||
| 9 | use embassy_rp::i2c::{self, Async, InterruptHandler}; | ||
| 10 | use embassy_rp::multicore::{spawn_core1, Stack}; | ||
| 11 | use embassy_rp::peripherals::{I2C0, I2C1}; | ||
| 12 | use embedded_hal_1::i2c::Operation; | ||
| 13 | use embedded_hal_async::i2c::I2c; | ||
| 14 | use {defmt_rtt as _, panic_probe as _, panic_probe as _, panic_probe as _}; | ||
| 15 | |||
| 16 | static mut CORE1_STACK: Stack<1024> = Stack::new(); | ||
| 17 | static EXECUTOR0: StaticCell<Executor> = StaticCell::new(); | ||
| 18 | static EXECUTOR1: StaticCell<Executor> = StaticCell::new(); | ||
| 19 | |||
| 20 | use crate::i2c::AbortReason; | ||
| 21 | |||
| 22 | bind_interrupts!(struct Irqs { | ||
| 23 | I2C0_IRQ => InterruptHandler<I2C0>; | ||
| 24 | I2C1_IRQ => InterruptHandler<I2C1>; | ||
| 25 | }); | ||
| 26 | |||
| 27 | const DEV_ADDR: u8 = 0x42; | ||
| 28 | |||
| 29 | #[embassy_executor::task] | ||
| 30 | async fn device_task(mut dev: i2c::I2cDevice<'static, I2C1>) -> ! { | ||
| 31 | info!("Device start"); | ||
| 32 | |||
| 33 | let mut count = 0xD0; | ||
| 34 | |||
| 35 | loop { | ||
| 36 | let mut buf = [0u8; 128]; | ||
| 37 | match dev.listen(&mut buf).await { | ||
| 38 | Ok(i2c::Command::GeneralCall(len)) => { | ||
| 39 | assert_eq!(buf[..len], [0xCA, 0x11], "recieving the general call failed"); | ||
| 40 | info!("General Call - OK"); | ||
| 41 | } | ||
| 42 | Ok(i2c::Command::Read) => { | ||
| 43 | loop { | ||
| 44 | //info!("Responding to read, count {}", count); | ||
| 45 | let a = dev.respond_to_read(&[count]).await; | ||
| 46 | //info!("x {}", a); | ||
| 47 | match a { | ||
| 48 | Ok(x) => match x { | ||
| 49 | i2c::ReadStatus::Done => break, | ||
| 50 | i2c::ReadStatus::NeedMoreBytes => count += 1, | ||
| 51 | i2c::ReadStatus::LeftoverBytes(x) => { | ||
| 52 | info!("tried to write {} extra bytes", x); | ||
| 53 | break; | ||
| 54 | } | ||
| 55 | }, | ||
| 56 | Err(e) => match e { | ||
| 57 | embassy_rp::i2c::Error::Abort(AbortReason::Other(n)) => panic!("Other {:b}", n), | ||
| 58 | _ => panic!("{}", e), | ||
| 59 | }, | ||
| 60 | } | ||
| 61 | } | ||
| 62 | count += 1; | ||
| 63 | } | ||
| 64 | Ok(i2c::Command::Write(len)) => match len { | ||
| 65 | 1 => { | ||
| 66 | assert_eq!(buf[..len], [0xAA], "recieving a single byte failed"); | ||
| 67 | info!("Single Byte Write - OK") | ||
| 68 | } | ||
| 69 | 4 => { | ||
| 70 | assert_eq!(buf[..len], [0xAA, 0xBB, 0xCC, 0xDD], "recieving 4 bytes failed"); | ||
| 71 | info!("4 Byte Write - OK") | ||
| 72 | } | ||
| 73 | 32 => { | ||
| 74 | assert_eq!( | ||
| 75 | buf[..len], | ||
| 76 | [ | ||
| 77 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, | ||
| 78 | 25, 26, 27, 28, 29, 30, 31 | ||
| 79 | ], | ||
| 80 | "recieving 32 bytes failed" | ||
| 81 | ); | ||
| 82 | info!("32 Byte Write - OK") | ||
| 83 | } | ||
| 84 | _ => panic!("Invalid write length {}", len), | ||
| 85 | }, | ||
| 86 | Ok(i2c::Command::WriteRead(len)) => { | ||
| 87 | info!("device recieved write read: {:x}", buf[..len]); | ||
| 88 | match buf[0] { | ||
| 89 | 0xC2 => { | ||
| 90 | let resp_buff = [0xD1, 0xD2, 0xD3, 0xD4]; | ||
| 91 | dev.respond_to_read(&resp_buff).await.unwrap(); | ||
| 92 | } | ||
| 93 | 0xC8 => { | ||
| 94 | let mut resp_buff = [0u8; 32]; | ||
| 95 | for i in 0..32 { | ||
| 96 | resp_buff[i] = i as u8; | ||
| 97 | } | ||
| 98 | dev.respond_to_read(&resp_buff).await.unwrap(); | ||
| 99 | } | ||
| 100 | x => panic!("Invalid Write Read {:x}", x), | ||
| 101 | } | ||
| 102 | } | ||
| 103 | Err(e) => match e { | ||
| 104 | embassy_rp::i2c::Error::Abort(AbortReason::Other(n)) => panic!("Other {:b}", n), | ||
| 105 | _ => panic!("{}", e), | ||
| 106 | }, | ||
| 107 | } | ||
| 108 | } | ||
| 109 | } | ||
| 110 | |||
| 111 | #[embassy_executor::task] | ||
| 112 | async fn controller_task(mut con: i2c::I2c<'static, I2C0, Async>) { | ||
| 113 | info!("Device start"); | ||
| 114 | |||
| 115 | { | ||
| 116 | let buf = [0xCA, 0x11]; | ||
| 117 | con.write(0u16, &buf).await.unwrap(); | ||
| 118 | info!("Controler general call write"); | ||
| 119 | embassy_futures::yield_now().await; | ||
| 120 | } | ||
| 121 | |||
| 122 | { | ||
| 123 | let mut buf = [0u8]; | ||
| 124 | con.read(DEV_ADDR, &mut buf).await.unwrap(); | ||
| 125 | assert_eq!(buf, [0xD0], "single byte read failed"); | ||
| 126 | info!("single byte read - OK"); | ||
| 127 | embassy_futures::yield_now().await; | ||
| 128 | } | ||
| 129 | |||
| 130 | { | ||
| 131 | let mut buf = [0u8; 4]; | ||
| 132 | con.read(DEV_ADDR, &mut buf).await.unwrap(); | ||
| 133 | assert_eq!(buf, [0xD1, 0xD2, 0xD3, 0xD4], "single byte read failed"); | ||
| 134 | info!("4 byte read - OK"); | ||
| 135 | embassy_futures::yield_now().await; | ||
| 136 | } | ||
| 137 | |||
| 138 | { | ||
| 139 | let buf = [0xAA]; | ||
| 140 | con.write(DEV_ADDR, &buf).await.unwrap(); | ||
| 141 | info!("Controler single byte write"); | ||
| 142 | embassy_futures::yield_now().await; | ||
| 143 | } | ||
| 144 | |||
| 145 | { | ||
| 146 | let buf = [0xAA, 0xBB, 0xCC, 0xDD]; | ||
| 147 | con.write(DEV_ADDR, &buf).await.unwrap(); | ||
| 148 | info!("Controler 4 byte write"); | ||
| 149 | embassy_futures::yield_now().await; | ||
| 150 | } | ||
| 151 | |||
| 152 | { | ||
| 153 | let mut buf = [0u8; 32]; | ||
| 154 | for i in 0..32 { | ||
| 155 | buf[i] = i as u8; | ||
| 156 | } | ||
| 157 | con.write(DEV_ADDR, &buf).await.unwrap(); | ||
| 158 | info!("Controler 32 byte write"); | ||
| 159 | embassy_futures::yield_now().await; | ||
| 160 | } | ||
| 161 | |||
| 162 | { | ||
| 163 | let mut buf = [0u8; 4]; | ||
| 164 | let mut ops = [Operation::Write(&[0xC2]), Operation::Read(&mut buf)]; | ||
| 165 | con.transaction(DEV_ADDR, &mut ops).await.unwrap(); | ||
| 166 | assert_eq!(buf, [0xD1, 0xD2, 0xD3, 0xD4], "write_read failed"); | ||
| 167 | info!("write_read - OK"); | ||
| 168 | embassy_futures::yield_now().await; | ||
| 169 | } | ||
| 170 | |||
| 171 | { | ||
| 172 | let mut buf = [0u8; 32]; | ||
| 173 | let mut ops = [Operation::Write(&[0xC8]), Operation::Read(&mut buf)]; | ||
| 174 | con.transaction(DEV_ADDR, &mut ops).await.unwrap(); | ||
| 175 | assert_eq!( | ||
| 176 | buf, | ||
| 177 | [ | ||
| 178 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, | ||
| 179 | 28, 29, 30, 31 | ||
| 180 | ], | ||
| 181 | "write_read of 32 bytes failed" | ||
| 182 | ); | ||
| 183 | info!("large write_read - OK") | ||
| 184 | } | ||
| 185 | |||
| 186 | info!("Test OK"); | ||
| 187 | cortex_m::asm::bkpt(); | ||
| 188 | } | ||
| 189 | |||
| 190 | #[cortex_m_rt::entry] | ||
| 191 | fn main() -> ! { | ||
| 192 | let p = embassy_rp::init(Default::default()); | ||
| 193 | info!("Hello World!"); | ||
| 194 | |||
| 195 | let d_sda = p.PIN_19; | ||
| 196 | let d_scl = p.PIN_18; | ||
| 197 | let mut config = i2c::DeviceConfig::default(); | ||
| 198 | config.addr = DEV_ADDR as u16; | ||
| 199 | let device = i2c::I2cDevice::new(p.I2C1, d_sda, d_scl, Irqs, config); | ||
| 200 | |||
| 201 | spawn_core1(p.CORE1, unsafe { &mut CORE1_STACK }, move || { | ||
| 202 | let executor1 = EXECUTOR1.init(Executor::new()); | ||
| 203 | executor1.run(|spawner| unwrap!(spawner.spawn(device_task(device)))); | ||
| 204 | }); | ||
| 205 | |||
| 206 | let executor0 = EXECUTOR0.init(Executor::new()); | ||
| 207 | |||
| 208 | let c_sda = p.PIN_21; | ||
| 209 | let c_scl = p.PIN_20; | ||
| 210 | let mut config = i2c::Config::default(); | ||
| 211 | config.frequency = 5_000; | ||
| 212 | let controller = i2c::I2c::new_async(p.I2C0, c_sda, c_scl, Irqs, config); | ||
| 213 | |||
| 214 | executor0.run(|spawner| unwrap!(spawner.spawn(controller_task(controller)))); | ||
| 215 | } | ||
