Skip to content

Commit acb2eaf

Browse files
committed
wip: rtio/i2c
1 parent fdb98a9 commit acb2eaf

File tree

8 files changed

+349
-1
lines changed

8 files changed

+349
-1
lines changed

dt-rust.yaml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,22 @@
3535
value: gpios
3636
device: crate::device::gpio::GpioPin
3737

38+
# Hook up the gpio-keys as gpio pins as well
39+
- name: gpio-keys
40+
rules:
41+
- type: compatible
42+
value:
43+
names:
44+
- gpio-keys
45+
level: 1
46+
actions:
47+
- type: instance
48+
value:
49+
raw:
50+
type: phandle
51+
value: gpios
52+
device: crate::device::gpio::GpioPin
53+
3854
# Flash controllers don't have any particular property to identify them, so we need a list of
3955
# compatible values that should match.
4056
- name: flash-controller
@@ -45,6 +61,8 @@
4561
- "nordic,nrf52-flash-controller"
4662
- "nordic,nrf51-flash-controller"
4763
- "raspberrypi,pico-flash-controller"
64+
- "st,stm32g4-flash-controller"
65+
- "st,stm32l5-flash-controller"
4866
- "zephyr,sim-flash"
4967
level: 0
5068
actions:
@@ -80,6 +98,21 @@
8098
- type: reg
8199
device: "crate::device::flash::FlashPartition"
82100

101+
# I2C.
102+
- name: i2c
103+
rules:
104+
- type: compatible
105+
value:
106+
names:
107+
- "snps,designware-i2c"
108+
level: 0
109+
actions:
110+
- type: instance
111+
value:
112+
raw:
113+
type: myself
114+
device: crate::device::i2c::I2C
115+
83116
# Generate a pseudo node that matches all of the labels across the tree with their nodes.
84117
- name: labels
85118
rules:

zephyr-sys/build.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,13 @@ fn main() -> Result<()> {
7676
.derive_copy(false)
7777
.allowlist_function("k_.*")
7878
.allowlist_function("gpio_.*")
79+
.allowlist_function("i2c_.*")
7980
.allowlist_function("flash_.*")
8081
.allowlist_function("zr_.*")
82+
.allowlist_function("mpsc_.*")
83+
.allowlist_function("rtio.*")
8184
.allowlist_item("GPIO_.*")
85+
.allowlist_item("I2C_.*")
8286
.allowlist_item("FLASH_.*")
8387
.allowlist_item("Z_.*")
8488
.allowlist_item("ZR_.*")

zephyr-sys/wrapper.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ extern int errno;
4343
#include <zephyr/bluetooth/bluetooth.h>
4444
#include <zephyr/drivers/flash.h>
4545
#include <zephyr/irq.h>
46+
#include <zephyr/drivers/i2c.h>
47+
#include <zephyr/rtio/rtio.h>
48+
#include <zephyr/sys/mpsc_lockfree.h>
4649

4750
/*
4851
* bindgen will only output #defined constants that resolve to simple numbers. These are some
@@ -63,6 +66,12 @@ const uint32_t ZR_GPIO_INT_MODE_DISABLE_ONLY = GPIO_INT_MODE_DISABLE_ONLY;
6366
const uint32_t ZR_GPIO_INT_MODE_ENABLE_ONLY = GPIO_INT_MODE_ENABLE_ONLY;
6467
#endif
6568

69+
const uint8_t ZR_I2C_MSG_WRITE = I2C_MSG_WRITE;
70+
const uint8_t ZR_I2C_MSG_READ = I2C_MSG_READ;
71+
const uint8_t ZR_I2C_MSG_STOP = I2C_MSG_STOP;
72+
73+
const uint16_t ZR_RTIO_SQE_NO_RESPONSE = RTIO_SQE_NO_RESPONSE;
74+
6675
/*
6776
* Zephyr's irq_lock() and irq_unlock() are macros not inline functions, so we need some inlines to
6877
* access them.

zephyr/src/device.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use crate::sync::atomic::{AtomicBool, Ordering};
1212

1313
pub mod flash;
1414
pub mod gpio;
15+
pub mod i2c;
1516

1617
// Allow dead code, because it isn't required for a given build to have any devices.
1718
/// Device uniqueness.

zephyr/src/device/gpio.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,10 @@ mod async_io {
3535
ZR_GPIO_INT_MODE_DISABLE_ONLY,
3636
};
3737

38-
use crate::sync::atomic::{AtomicBool, AtomicU32};
38+
use crate::{
39+
printkln,
40+
sync::atomic::{AtomicBool, AtomicU32},
41+
};
3942

4043
use super::{GpioPin, GpioToken};
4144

@@ -112,6 +115,7 @@ mod async_io {
112115
cb: *mut gpio_callback,
113116
mut pins: gpio_port_pins_t,
114117
) {
118+
printkln!("GPIO callback: {}", pins);
115119
let data = unsafe {
116120
cb.cast::<u8>()
117121
.sub(mem::offset_of!(Self, callback))

zephyr/src/device/i2c.rs

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
//! Zpehyr I2C interface
2+
3+
use core::{ffi::c_int, marker::PhantomData};
4+
5+
use crate::{error::to_result, printkln, raw};
6+
7+
use super::{NoStatic, Unique};
8+
9+
/// A single I2C controller.
10+
pub struct I2C {
11+
/// The underlying device itself.
12+
#[allow(dead_code)]
13+
pub(crate) device: *const raw::device,
14+
}
15+
16+
unsafe impl Send for I2C {}
17+
18+
impl I2C {
19+
/// Constructor, used by the devicetree generated code.
20+
#[allow(dead_code)]
21+
pub(crate) unsafe fn new(
22+
unique: &Unique,
23+
_data: &'static NoStatic,
24+
device: *const raw::device,
25+
) -> Option<Self> {
26+
if !unique.once() {
27+
return None;
28+
}
29+
Some(I2C { device })
30+
}
31+
32+
/// Do a write/read.
33+
pub fn write_read(&mut self, write: &[u8], read: &mut [u8]) -> crate::Result<c_int> {
34+
let mut msg = [
35+
raw::i2c_msg {
36+
buf: write.as_ptr() as *mut _,
37+
len: write.len() as u32,
38+
flags: raw::ZR_I2C_MSG_WRITE,
39+
},
40+
raw::i2c_msg {
41+
buf: read.as_mut_ptr(),
42+
len: read.len() as u32,
43+
flags: raw::ZR_I2C_MSG_READ | raw::ZR_I2C_MSG_STOP,
44+
},
45+
];
46+
let res = unsafe { to_result(raw::i2c_transfer(self.device, msg.as_mut_ptr(), 2, 0x42)) };
47+
48+
printkln!("res: {} {}", msg[1].len, msg[1].flags);
49+
50+
res
51+
}
52+
53+
/// Add an i2c operation to the RTIO.
54+
///
55+
/// TODO: Unclear how to indicate that the buffers must live long enough for the submittion.
56+
/// As it is, this is actually completely unsound.
57+
pub fn rtio_write_read(&mut self, write: &[u8], read: &mut [u8]) -> crate::Result<()> {
58+
let _msg = [
59+
raw::i2c_msg {
60+
buf: write.as_ptr() as *mut _,
61+
len: write.len() as u32,
62+
flags: raw::ZR_I2C_MSG_WRITE,
63+
},
64+
raw::i2c_msg {
65+
buf: read.as_mut_ptr(),
66+
len: read.len() as u32,
67+
flags: raw::ZR_I2C_MSG_READ | raw::ZR_I2C_MSG_STOP,
68+
},
69+
];
70+
71+
todo!()
72+
}
73+
}
74+
75+
/// An i2c transaction.
76+
pub struct ReadWrite<'a> {
77+
_phantom: PhantomData<&'a ()>,
78+
msgs: [raw::i2c_msg; 2],
79+
}
80+
81+
impl<'a> ReadWrite<'a> {
82+
/// Construct a new read/write transaction.
83+
pub fn new(write: &'a [u8], read: &'a mut [u8]) -> Self {
84+
Self {
85+
_phantom: PhantomData,
86+
msgs: [
87+
raw::i2c_msg {
88+
buf: write.as_ptr() as *mut _,
89+
len: write.len() as u32,
90+
flags: raw::ZR_I2C_MSG_WRITE,
91+
},
92+
raw::i2c_msg {
93+
buf: read.as_mut_ptr(),
94+
len: read.len() as u32,
95+
flags: raw::ZR_I2C_MSG_READ | raw::ZR_I2C_MSG_STOP,
96+
},
97+
],
98+
}
99+
}
100+
}

zephyr/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ pub mod embassy;
7474
pub mod error;
7575
pub mod logging;
7676
pub mod object;
77+
#[cfg(CONFIG_RTIO)]
78+
pub mod rtio;
7779
#[cfg(CONFIG_RUST_ALLOC)]
7880
pub mod simpletls;
7981
pub mod sync;

0 commit comments

Comments
 (0)