WIP for i2c

This commit is contained in:
Marc Poulhiès 2020-07-08 21:13:26 +02:00
parent 44dfef354d
commit e0f51c6cb8
5 changed files with 401 additions and 51 deletions

View File

@ -14,6 +14,7 @@ targets = ["riscv64gc-unknown-none-elf"]
[dependencies]
embedded-hal = "1.0.0-alpha.1"
## embedded-hal = { version = "0.2.4", features = ["unproven"] }
nb = "0.1.1"
k210-pac = "0.2.0"
k210-pac = { pat="../k210-pac"}
bitflags = "1.2.1"

View File

@ -87,7 +87,7 @@ pub mod io_pins {
use core::marker::PhantomData;
use super::{Function, IoPin, Mode, FUNCTION_DEFAULTS};
use crate::pac::FPIOA;
$(
/// Programmable I/O pin
pub struct $IoX<FUNC> {
@ -148,8 +148,8 @@ def_io_pin! {
Io27: (27, io27, GPIOHS11);
Io28: (28, io28, GPIOHS12);
Io29: (29, io29, GPIOHS13);
Io30: (30, io30, GPIOHS14);
Io31: (31, io31, GPIOHS15);
Io30: (30, io30, I2C1_SCLK);
Io31: (31, io31, I2C1_SDA);
Io32: (32, io32, GPIOHS16);
Io33: (33, io33, GPIOHS17);
Io34: (34, io34, GPIOHS18);

View File

@ -117,15 +117,15 @@ impl<MODE> Gpiohs0<MODE> {
impl<MODE> InputPin for Gpiohs0<Input<MODE>> {
type Error = core::convert::Infallible;
fn try_is_high(&self) -> Result<bool, Self::Error> {
Ok(unsafe {
fn try_is_high(&self) -> Result<bool, Self::Error> {
Ok(unsafe {
let p = &(*GPIOHS::ptr()).input_val as *const _ as *const _;
u32_bit_is_set(p, 0)
})
}
fn try_is_low(&self) -> Result<bool, Self::Error> {
Ok(unsafe {
fn try_is_low(&self) -> Result<bool, Self::Error> {
Ok(unsafe {
let p = &(*GPIOHS::ptr()).input_val as *const _ as *const _;
u32_bit_is_clear(p, 0)
})
@ -136,7 +136,7 @@ impl<MODE> OutputPin for Gpiohs0<Output<MODE>> {
type Error = core::convert::Infallible;
fn try_set_high(&mut self) -> Result<(), Self::Error> {
unsafe {
unsafe {
let p = &(*GPIOHS::ptr()).output_val as *const _ as *mut _;
u32_set_bit(p, true, 0);
}
@ -144,7 +144,7 @@ impl<MODE> OutputPin for Gpiohs0<Output<MODE>> {
}
fn try_set_low(&mut self) -> Result<(), Self::Error> {
unsafe {
unsafe {
let p = &(*GPIOHS::ptr()).output_val as *const _ as *mut _;
u32_set_bit(p, false, 0);
}
@ -156,187 +156,186 @@ trait GpiohsAccess {
fn peripheral() -> &'static mut crate::pac::gpiohs::RegisterBlock;
fn set_drive(index: usize, bit: bool) {
unsafe {
let p = &mut Self::peripheral().drive as *mut _ as *mut _;
unsafe {
let p = &mut Self::peripheral().drive as *mut _ as *mut _;
u32_set_bit(p, bit, index);
}
}
fn input_value(index: usize) -> bool {
unsafe {
let p = &mut Self::peripheral().input_val as *mut _ as *mut _;
let p = &mut Self::peripheral().input_val as *mut _ as *mut _;
u32_bit_is_set(p, index)
}
}
fn set_input_en(index: usize, bit: bool) {
unsafe {
let p = &mut Self::peripheral().input_en as *mut _ as *mut _;
unsafe {
let p = &mut Self::peripheral().input_en as *mut _ as *mut _;
u32_set_bit(p, bit, index);
}
}
fn set_iof_en(index: usize, bit: bool) {
unsafe {
let p = &mut Self::peripheral().iof_en as *mut _ as *mut _;
unsafe {
let p = &mut Self::peripheral().iof_en as *mut _ as *mut _;
u32_set_bit(p, bit, index);
}
}
fn set_iof_sel(index: usize, bit: bool) {
unsafe {
let p = &mut Self::peripheral().iof_sel as *mut _ as *mut _;
unsafe {
let p = &mut Self::peripheral().iof_sel as *mut _ as *mut _;
u32_set_bit(p, bit, index);
}
}
fn set_output_en(index: usize, bit: bool) {
unsafe {
let p = &mut Self::peripheral().output_en as *mut _ as *mut _;
unsafe {
let p = &mut Self::peripheral().output_en as *mut _ as *mut _;
u32_set_bit(p, bit, index);
}
}
fn set_output_value(index: usize, bit: bool) {
unsafe {
let p = &mut Self::peripheral().output_val as *mut _ as *mut _;
unsafe {
let p = &mut Self::peripheral().output_val as *mut _ as *mut _;
u32_set_bit(p, bit, index);
}
}
fn set_output_xor(index: usize, bit: bool) {
unsafe {
let p = &mut Self::peripheral().output_xor as *mut _ as *mut _;
let p = &mut Self::peripheral().output_xor as *mut _ as *mut _;
u32_set_bit(p, bit, index);
}
}
fn toggle_pin(index: usize) {
unsafe {
let p = &mut Self::peripheral().output_val as *mut _ as *mut _;
let p = &mut Self::peripheral().output_val as *mut _ as *mut _;
u32_toggle_bit(p, index);
}
}
fn set_pullup_en(index: usize, bit: bool) {
unsafe {
let p = &mut Self::peripheral().pullup_en as *mut _ as *mut _;
unsafe {
let p = &mut Self::peripheral().pullup_en as *mut _ as *mut _;
u32_set_bit(p, bit, index);
}
}
fn set_rise_ie(index: usize, bit: bool) {
unsafe {
let p = &mut Self::peripheral().rise_ie as *mut _ as *mut _;
let p = &mut Self::peripheral().rise_ie as *mut _ as *mut _;
u32_set_bit(p, bit, index);
}
}
fn clear_rise_ip(index: usize) {
unsafe {
let p = &mut Self::peripheral().rise_ip as *mut _ as *mut _;
let p = &mut Self::peripheral().rise_ip as *mut _ as *mut _;
u32_set_bit(p, true, index);
}
}
fn set_fall_ie(index: usize, bit: bool) {
unsafe {
let p = &mut Self::peripheral().fall_ie as *mut _ as *mut _;
let p = &mut Self::peripheral().fall_ie as *mut _ as *mut _;
u32_set_bit(p, bit, index);
}
}
fn clear_fall_ip(index: usize) {
unsafe {
let p = &mut Self::peripheral().fall_ip as *mut _ as *mut _;
let p = &mut Self::peripheral().fall_ip as *mut _ as *mut _;
u32_set_bit(p, true, index);
}
}
fn set_high_ie(index: usize, bit: bool) {
unsafe {
let p = &mut Self::peripheral().high_ie as *mut _ as *mut _;
let p = &mut Self::peripheral().high_ie as *mut _ as *mut _;
u32_set_bit(p, bit, index);
}
}
fn clear_high_ip(index: usize,) {
unsafe {
let p = &mut Self::peripheral().high_ip as *mut _ as *mut _;
let p = &mut Self::peripheral().high_ip as *mut _ as *mut _;
u32_set_bit(p, true, index);
}
}
fn set_low_ie(index: usize, bit: bool) {
unsafe {
let p = &mut Self::peripheral().low_ie as *mut _ as *mut _;
let p = &mut Self::peripheral().low_ie as *mut _ as *mut _;
u32_set_bit(p, bit, index);
}
}
fn clear_low_ip(index: usize) {
unsafe {
let p = &mut Self::peripheral().low_ip as *mut _ as *mut _;
let p = &mut Self::peripheral().low_ip as *mut _ as *mut _;
u32_set_bit(p, true, index);
}
}
fn has_rise_ie(index: usize) -> bool {
unsafe {
let p = &mut Self::peripheral().rise_ie as *mut _ as *mut _;
let p = &mut Self::peripheral().rise_ie as *mut _ as *mut _;
u32_bit_is_set(p, index)
}
}
fn has_fall_ie(index: usize) -> bool {
unsafe {
let p = &mut Self::peripheral().fall_ie as *mut _ as *mut _;
let p = &mut Self::peripheral().fall_ie as *mut _ as *mut _;
u32_bit_is_set(p, index)
}
}
fn has_high_ie(index: usize) -> bool {
unsafe {
let p = &mut Self::peripheral().high_ie as *mut _ as *mut _;
let p = &mut Self::peripheral().high_ie as *mut _ as *mut _;
u32_bit_is_set(p, index)
}
}
fn has_low_ie(index: usize) -> bool {
unsafe {
let p = &mut Self::peripheral().low_ie as *mut _ as *mut _;
let p = &mut Self::peripheral().low_ie as *mut _ as *mut _;
u32_bit_is_set(p, index)
}
}
fn has_rise_ip(index: usize) -> bool {
unsafe {
let p = &mut Self::peripheral().rise_ip as *mut _ as *mut _;
let p = &mut Self::peripheral().rise_ip as *mut _ as *mut _;
u32_bit_is_set(p, index)
}
}
fn has_fall_ip(index: usize) -> bool {
unsafe {
let p = &mut Self::peripheral().fall_ip as *mut _ as *mut _;
let p = &mut Self::peripheral().fall_ip as *mut _ as *mut _;
u32_bit_is_set(p, index)
}
}
fn has_high_ip(index: usize) -> bool {
unsafe {
let p = &mut Self::peripheral().high_ip as *mut _ as *mut _;
let p = &mut Self::peripheral().high_ip as *mut _ as *mut _;
u32_bit_is_set(p, index)
}
}
fn has_low_ip(index: usize) -> bool {
unsafe {
let p = &mut Self::peripheral().low_ip as *mut _ as *mut _;
let p = &mut Self::peripheral().low_ip as *mut _ as *mut _;
u32_bit_is_set(p, index)
}
}
}
impl GpiohsAccess for GPIOHS {

349
src/i2c.rs Normal file
View File

@ -0,0 +1,349 @@
//! Inter-Integrated Circuit (I2C) bus
use crate::pac::I2C1;
use core::marker::PhantomData;
use crate::bit_utils::{u32_set_bit, u32_toggle_bit, u32_bit_is_set, u32_bit_is_clear};
use embedded_hal::digital::v2::{InputPin, OutputPin};
use embedded_hal::blocking::i2c::{Read, Write, WriteRead};
use crate::{
fpioa::{
io_pins::{Io30, Io31},
functions::{I2C1_SCLK, I2C1_SDA},
},
time::Hertz,
};
// use crate::{
// gpio::{
// gpioa::{PA6, PA7},
// gpiob::{PB2, PB3},
// gpiod::{PD0, PD1},
// gpioe::{PE4, PE5},
// AlternateFunction, Floating, OpenDrain, OutputMode, AF3,
// },
// hal::blocking::i2c::{Read, Write, WriteRead},
// sysctl::{self, Clocks},
// };
/// I2C error
#[derive(Debug)]
pub enum Error {
/// Bus error
Bus,
/// Arbitration loss
Arbitration,
/// Missing Data ACK
DataAck,
/// Missing Addrees ACK
AdrAck,
#[doc(hidden)]
_Extensible,
}
// FIXME these should be "closed" traits
/// SCL pin -- DO NOT IMPLEMENT THIS TRAIT
pub unsafe trait SclPin<I2C> {}
/// SDA pin -- DO NOT IMPLEMENT THIS TRAIT
pub unsafe trait SdaPin<I2C> {}
unsafe impl SclPin<I2C1> for Io30<I2C1_SCLK> {}
unsafe impl SdaPin<I2C1> for Io31<I2C1_SDA> {}
/// I2C peripheral operating in master mode
pub struct I2c<I2C, PINS> {
i2c: I2C,
pins: PINS,
}
// macro_rules! busy_wait {
// ($i2c:expr, $flag:ident, $op:ident) => {
// // in 'release' builds, the time between setting the `run` bit and checking the `busy`
// // bit is too short and the `busy` bit is not reliably set by the time you get there,
// // it can take up to 8 clock cycles for the `run` to begin so this delay allows time
// // for that hardware synchronization
// delay(2);
// loop {
// let mcs = $i2c.mcs.read();
// if mcs.error().bit_is_set() {
// if mcs.adrack().bit_is_set() {
// return Err(Error::AdrAck);
// } else if mcs.datack().bit_is_set() {
// return Err(Error::DataAck);
// }
// return Err(Error::Bus);
// } else if mcs.arblst().bit_is_set() {
// return Err(Error::Arbitration);
// } else if mcs.$flag().$op() {
// break;
// } else {
// // try again
// }
// }
// };
// }
macro_rules! hal {
($($I2CX:ident: ($powerDomain:ident, $i2cX:ident),)+) => {
$(
impl<SCL, SDA> I2c<$I2CX, (SCL, SDA)> {
/// Configures the I2C peripheral to work in master mode
pub fn $i2cX<F>(
i2c: $I2CX,
pins: (SCL, SDA),
freq: F,
// clocks: &Clocks,
// pc: &sysctl::PowerControl,
) -> Self where
F: Into<Hertz>,
SCL: SclPin<$I2CX>,
SDA: SdaPin<$I2CX>,
{
// sysctl::control_power(
// pc, sysctl::Domain::$powerDomain,
// sysctl::RunMode::Run, sysctl::PowerState::On);
// sysctl::reset(pc, sysctl::Domain::$powerDomain);
// // set Master Function Enable, and clear other bits.
// i2c.mcr.write(|w| w.mfe().set_bit());
// // Write TimerPeriod configuration and clear other bits.
// let freq = freq.into().0;
// let tpr = ((clocks.sysclk.0/(2*10*freq))-1) as u8;
// i2c.mtpr.write(|w| unsafe {w.tpr().bits(tpr)});
I2c { i2c, pins }
}
/// Releases the I2C peripheral and associated pins
pub fn free(self) -> ($I2CX, (SCL, SDA)) {
(self.i2c, self.pins)
}
}
impl<PINS> Write for I2c<$I2CX, PINS> {
type Error = Error;
fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> {
// Write Slave address and clear Receive bit
// self.i2c.msa.write(|w| unsafe {
// w.sa().bits(addr)
// });
// // Put first byte in data register
// self.i2c.mdr.write(|w| unsafe {
// w.data().bits(bytes[0])
// });
// let sz = bytes.len();
// busy_wait!(self.i2c, busbsy, bit_is_clear);
// // Send START + RUN
// // If single byte transfer, set STOP
// self.i2c.mcs.write(|w| {
// if sz == 1 {
// w.stop().set_bit();
// }
// w.start().set_bit()
// .run().set_bit()
// });
// for (i,byte) in (&bytes[1..]).iter().enumerate() {
// busy_wait!(self.i2c, busy, bit_is_clear);
// // Put next byte in data register
// self.i2c.mdr.write(|w| unsafe {
// w.data().bits(*byte)
// });
// // Send RUN command (Burst continue)
// // Set STOP on last byte
// self.i2c.mcs.write(|w| {
// if (i+1) == (sz-1) {
// w.stop().set_bit();
// }
// w.run().set_bit()
// });
// }
// busy_wait!(self.i2c, busy, bit_is_clear);
Ok(())
}
}
impl<PINS> Read for I2c<$I2CX, PINS> {
type Error = Error;
fn read(
&mut self,
addr: u8,
buffer: &mut [u8],
) -> Result<(), Error> {
// // Write Slave address and set Receive bit
// self.i2c.msa.write(|w| unsafe {
// w.sa().bits(addr)
// .rs().set_bit()
// });
// busy_wait!(self.i2c, busbsy, bit_is_clear);
// let recv_sz = buffer.len();
// if recv_sz == 1 {
// // Single receive
// self.i2c.mcs.write(|w| {
// w.run().set_bit()
// .start().set_bit()
// .stop().set_bit()
// });
// busy_wait!(self.i2c, busy, bit_is_clear);
// buffer[0] = self.i2c.mdr.read().data().bits();
// } else {
// self.i2c.mcs.write(|w| {
// w.start().set_bit()
// .run().set_bit()
// .ack().set_bit()
// });
// busy_wait!(self.i2c, busy, bit_is_clear);
// buffer[0] = self.i2c.mdr.read().data().bits();
// for byte in &mut buffer[1..recv_sz-1] {
// self.i2c.mcs.write(|w| {
// w.run().set_bit()
// .ack().set_bit()
// });
// busy_wait!(self.i2c, busy, bit_is_clear);
// *byte = self.i2c.mdr.read().data().bits();
// }
// self.i2c.mcs.write(|w| {
// w.run().set_bit()
// .stop().set_bit()
// });
// busy_wait!(self.i2c, busy, bit_is_clear);
// buffer[recv_sz-1] = self.i2c.mdr.read().data().bits();
// }
Ok(())
}
}
impl<PINS> WriteRead for I2c<$I2CX, PINS> {
type Error = Error;
fn write_read(
&mut self,
addr: u8,
bytes: &[u8],
buffer: &mut [u8],
) -> Result<(), Error> {
// let write_len = bytes.len();
// if buffer.len() == 0 {
// return self.write(addr, bytes);
// }
// if bytes.len() == 0 {
// return self.read(addr, buffer);
// }
// // Write Slave address and clear Receive bit
// self.i2c.msa.write(|w| unsafe {
// w.sa().bits(addr)
// });
// // send first byte
// self.i2c.mdr.write(|w| unsafe {
// w.data().bits(bytes[0])
// });
// busy_wait!(self.i2c, busbsy, bit_is_clear);
// self.i2c.mcs.write(|w| {
// w.start().set_bit()
// .run().set_bit()
// });
// busy_wait!(self.i2c, busy, bit_is_clear);
// for byte in (&bytes[1..write_len]).iter() {
// self.i2c.mdr.write(|w| unsafe {
// w.data().bits(*byte)
// });
// self.i2c.mcs.write(|w| {
// w.run().set_bit()
// });
// busy_wait!(self.i2c, busy, bit_is_clear);
// }
// // Write Slave address and set Receive bit
// self.i2c.msa.write(|w| unsafe {
// w.sa().bits(addr)
// .rs().set_bit()
// });
// let recv_sz = buffer.len();
// if recv_sz == 1 {
// // emit Repeated START and STOP for single receive
// self.i2c.mcs.write(|w| {
// w.run().set_bit()
// .start().set_bit()
// .stop().set_bit()
// });
// busy_wait!(self.i2c, busy, bit_is_clear);
// buffer[0] = self.i2c.mdr.read().data().bits();
// } else {
// // emit Repeated START
// self.i2c.mcs.write(|w| {
// w.run().set_bit()
// .start().set_bit()
// .ack().set_bit()
// });
// busy_wait!(self.i2c, busy, bit_is_clear);
// buffer[0] = self.i2c.mdr.read().data().bits();
// for byte in &mut buffer[1..recv_sz-1] {
// self.i2c.mcs.write(|w| {
// w.run().set_bit()
// .ack().set_bit()
// });
// busy_wait!(self.i2c, busy, bit_is_clear);
// *byte = self.i2c.mdr.read().data().bits();
// }
// self.i2c.mcs.write(|w| {
// w.run().set_bit()
// .stop().set_bit()
// });
// busy_wait!(self.i2c, busy, bit_is_clear);
// buffer[recv_sz-1] = self.i2c.mdr.read().data().bits();
// }
Ok(())
}
}
)+
}
}
hal! {
I2C1: (I2c1, i2c1),
}

View File

@ -15,6 +15,7 @@ pub mod clock;
pub mod dmac;
pub mod fft;
pub mod fpioa;
pub mod i2c;
pub mod gpio;
pub mod gpiohs;
pub mod plic;