2023-02-01 00:48:33 +01:00
//! I2C-compatible Two Wire Interface in master mode (TWIM) driver.
2021-05-11 03:07:37 +02:00
#![ macro_use ]
2022-09-22 16:42:49 +02:00
use core ::future ::{ poll_fn , Future } ;
2023-03-05 22:12:34 +01:00
use core ::marker ::PhantomData ;
2022-06-12 22:15:44 +02:00
use core ::sync ::atomic ::compiler_fence ;
use core ::sync ::atomic ::Ordering ::SeqCst ;
2021-06-04 17:31:35 +02:00
use core ::task ::Poll ;
2022-06-12 22:15:44 +02:00
2022-07-08 15:47:47 +02:00
use embassy_embedded_hal ::SetConfig ;
2023-07-28 13:23:22 +02:00
use embassy_hal_internal ::{ into_ref , PeripheralRef } ;
2022-08-22 21:46:09 +02:00
use embassy_sync ::waitqueue ::AtomicWaker ;
2022-08-17 23:40:16 +02:00
#[ cfg(feature = " time " ) ]
use embassy_time ::{ Duration , Instant } ;
2021-05-11 03:07:37 +02:00
use crate ::chip ::{ EASY_DMA_SIZE , FORCE_COPY_BUFFER_SIZE } ;
use crate ::gpio ::Pin as GpioPin ;
2023-06-08 16:08:40 +02:00
use crate ::interrupt ::typelevel ::Interrupt ;
2021-05-11 03:07:37 +02:00
use crate ::util ::{ slice_in_ram , slice_in_ram_or } ;
2023-06-08 16:08:40 +02:00
use crate ::{ gpio , interrupt , pac , Peripheral } ;
2021-05-11 03:07:37 +02:00
2023-02-01 00:48:33 +01:00
/// TWI frequency
2022-07-08 15:47:47 +02:00
#[ derive(Clone, Copy) ]
2021-05-11 03:07:37 +02:00
pub enum Frequency {
2023-02-01 00:48:33 +01:00
/// 100 kbps
2021-05-11 03:07:37 +02:00
K100 = 26738688 ,
2023-02-01 00:48:33 +01:00
/// 250 kbps
2021-05-11 03:07:37 +02:00
K250 = 67108864 ,
2023-02-01 00:48:33 +01:00
/// 400 kbps
2021-05-11 03:07:37 +02:00
K400 = 104857600 ,
}
2023-02-01 00:48:33 +01:00
/// TWIM config.
2021-05-11 03:07:37 +02:00
#[ non_exhaustive ]
pub struct Config {
2023-02-01 00:48:33 +01:00
/// Frequency
2021-05-11 03:07:37 +02:00
pub frequency : Frequency ,
2023-02-01 00:48:33 +01:00
/// Enable high drive for the SDA line.
2022-05-03 00:43:46 +02:00
pub sda_high_drive : bool ,
2023-02-01 00:48:33 +01:00
/// Enable internal pullup for the SDA line.
///
/// Note that using external pullups is recommended for I2C, and
/// most boards already have them.
2021-05-26 18:15:05 +02:00
pub sda_pullup : bool ,
2023-02-01 00:48:33 +01:00
/// Enable high drive for the SCL line.
2022-05-03 00:43:46 +02:00
pub scl_high_drive : bool ,
2023-02-01 00:48:33 +01:00
/// Enable internal pullup for the SCL line.
///
/// Note that using external pullups is recommended for I2C, and
/// most boards already have them.
2021-05-26 18:15:05 +02:00
pub scl_pullup : bool ,
2021-05-11 03:07:37 +02:00
}
impl Default for Config {
fn default ( ) -> Self {
Self {
frequency : Frequency ::K100 ,
2022-05-03 00:43:46 +02:00
scl_high_drive : false ,
2021-05-26 18:15:05 +02:00
sda_pullup : false ,
2022-05-03 00:43:46 +02:00
sda_high_drive : false ,
2021-05-26 18:15:05 +02:00
scl_pullup : false ,
2021-05-11 03:07:37 +02:00
}
}
}
2023-02-01 00:48:33 +01:00
/// TWI error.
2022-01-13 23:56:25 +01:00
#[ derive(Debug, Copy, Clone, Eq, PartialEq) ]
#[ cfg_attr(feature = " defmt " , derive(defmt::Format)) ]
#[ non_exhaustive ]
pub enum Error {
2023-02-01 00:48:33 +01:00
/// TX buffer was too long.
2022-01-13 23:56:25 +01:00
TxBufferTooLong ,
2023-02-01 00:48:33 +01:00
/// RX buffer was too long.
2022-01-13 23:56:25 +01:00
RxBufferTooLong ,
2023-02-01 00:48:33 +01:00
/// Data transmit failed.
2022-01-13 23:56:25 +01:00
Transmit ,
2023-02-01 00:48:33 +01:00
/// Data reception failed.
2022-01-13 23:56:25 +01:00
Receive ,
2023-02-01 00:48:33 +01:00
/// The buffer is not in data RAM. It's most likely in flash, and nRF's DMA cannot access flash.
BufferNotInRAM ,
/// Didn't receive an ACK bit after the address byte. Address might be wrong, or the i2c device chip might not be connected properly.
2022-01-13 23:56:25 +01:00
AddressNack ,
2023-02-01 00:48:33 +01:00
/// Didn't receive an ACK bit after a data byte.
2022-01-13 23:56:25 +01:00
DataNack ,
2023-02-01 00:48:33 +01:00
/// Overrun error.
2022-01-13 23:56:25 +01:00
Overrun ,
2023-02-01 00:48:33 +01:00
/// Timeout error.
2022-05-03 00:43:59 +02:00
Timeout ,
2022-01-13 23:56:25 +01:00
}
2023-03-05 22:12:34 +01:00
/// Interrupt handler.
pub struct InterruptHandler < T : Instance > {
_phantom : PhantomData < T > ,
}
2023-06-08 16:08:40 +02:00
impl < T : Instance > interrupt ::typelevel ::Handler < T ::Interrupt > for InterruptHandler < T > {
2023-03-05 22:12:34 +01:00
unsafe fn on_interrupt ( ) {
let r = T ::regs ( ) ;
let s = T ::state ( ) ;
if r . events_stopped . read ( ) . bits ( ) ! = 0 {
s . end_waker . wake ( ) ;
r . intenclr . write ( | w | w . stopped ( ) . clear ( ) ) ;
}
if r . events_error . read ( ) . bits ( ) ! = 0 {
s . end_waker . wake ( ) ;
r . intenclr . write ( | w | w . error ( ) . clear ( ) ) ;
}
}
}
2023-02-01 00:48:33 +01:00
/// TWI driver.
2021-05-11 03:07:37 +02:00
pub struct Twim < ' d , T : Instance > {
2022-07-23 15:13:47 +02:00
_p : PeripheralRef < ' d , T > ,
2021-05-11 03:07:37 +02:00
}
impl < ' d , T : Instance > Twim < ' d , T > {
2023-02-01 00:48:33 +01:00
/// Create a new TWI driver.
2021-05-11 03:07:37 +02:00
pub fn new (
2022-07-23 15:13:47 +02:00
twim : impl Peripheral < P = T > + ' d ,
2023-06-08 16:08:40 +02:00
_irq : impl interrupt ::typelevel ::Binding < T ::Interrupt , InterruptHandler < T > > + ' d ,
2022-07-23 14:00:19 +02:00
sda : impl Peripheral < P = impl GpioPin > + ' d ,
scl : impl Peripheral < P = impl GpioPin > + ' d ,
2021-05-11 03:07:37 +02:00
config : Config ,
) -> Self {
2023-03-05 22:12:34 +01:00
into_ref! ( twim , sda , scl ) ;
2021-05-11 03:07:37 +02:00
let r = T ::regs ( ) ;
// Configure pins
sda . conf ( ) . write ( | w | {
w . dir ( ) . input ( ) ;
w . input ( ) . connect ( ) ;
2022-05-03 00:43:46 +02:00
if config . sda_high_drive {
w . drive ( ) . h0d1 ( ) ;
} else {
w . drive ( ) . s0d1 ( ) ;
}
2021-05-26 18:15:05 +02:00
if config . sda_pullup {
w . pull ( ) . pullup ( ) ;
}
2021-05-11 03:07:37 +02:00
w
} ) ;
scl . conf ( ) . write ( | w | {
w . dir ( ) . input ( ) ;
w . input ( ) . connect ( ) ;
2022-05-03 00:43:46 +02:00
if config . scl_high_drive {
w . drive ( ) . h0d1 ( ) ;
} else {
w . drive ( ) . s0d1 ( ) ;
}
2021-05-26 18:15:05 +02:00
if config . scl_pullup {
w . pull ( ) . pullup ( ) ;
}
2021-05-11 03:07:37 +02:00
w
} ) ;
// Select pins.
r . psel . sda . write ( | w | unsafe { w . bits ( sda . psel_bits ( ) ) } ) ;
r . psel . scl . write ( | w | unsafe { w . bits ( scl . psel_bits ( ) ) } ) ;
// Enable TWIM instance.
r . enable . write ( | w | w . enable ( ) . enabled ( ) ) ;
// Configure frequency.
r . frequency
. write ( | w | unsafe { w . frequency ( ) . bits ( config . frequency as u32 ) } ) ;
// Disable all events interrupts
r . intenclr . write ( | w | unsafe { w . bits ( 0xFFFF_FFFF ) } ) ;
2023-06-01 02:22:46 +02:00
T ::Interrupt ::unpend ( ) ;
unsafe { T ::Interrupt ::enable ( ) } ;
2021-05-11 03:07:37 +02:00
2022-07-23 15:13:47 +02:00
Self { _p : twim }
2021-05-11 03:07:37 +02:00
}
/// Set TX buffer, checking that it is in RAM and has suitable length.
unsafe fn set_tx_buffer ( & mut self , buffer : & [ u8 ] ) -> Result < ( ) , Error > {
2023-02-01 00:48:33 +01:00
slice_in_ram_or ( buffer , Error ::BufferNotInRAM ) ? ;
2021-05-11 03:07:37 +02:00
if buffer . len ( ) > EASY_DMA_SIZE {
return Err ( Error ::TxBufferTooLong ) ;
}
let r = T ::regs ( ) ;
r . txd . ptr . write ( | w |
// We're giving the register a pointer to the stack. Since we're
// waiting for the I2C transaction to end before this stack pointer
// becomes invalid, there's nothing wrong here.
//
// The PTR field is a full 32 bits wide and accepts the full range
// of values.
w . ptr ( ) . bits ( buffer . as_ptr ( ) as u32 ) ) ;
r . txd . maxcnt . write ( | w |
// We're giving it the length of the buffer, so no danger of
// accessing invalid memory. We have verified that the length of the
// buffer fits in an `u8`, so the cast to `u8` is also fine.
//
// The MAXCNT field is 8 bits wide and accepts the full range of
// values.
w . maxcnt ( ) . bits ( buffer . len ( ) as _ ) ) ;
Ok ( ( ) )
}
/// Set RX buffer, checking that it has suitable length.
unsafe fn set_rx_buffer ( & mut self , buffer : & mut [ u8 ] ) -> Result < ( ) , Error > {
// NOTE: RAM slice check is not necessary, as a mutable
// slice can only be built from data located in RAM.
if buffer . len ( ) > EASY_DMA_SIZE {
return Err ( Error ::RxBufferTooLong ) ;
}
let r = T ::regs ( ) ;
r . rxd . ptr . write ( | w |
// We're giving the register a pointer to the stack. Since we're
// waiting for the I2C transaction to end before this stack pointer
// becomes invalid, there's nothing wrong here.
//
// The PTR field is a full 32 bits wide and accepts the full range
// of values.
w . ptr ( ) . bits ( buffer . as_mut_ptr ( ) as u32 ) ) ;
r . rxd . maxcnt . write ( | w |
// We're giving it the length of the buffer, so no danger of
// accessing invalid memory. We have verified that the length of the
// buffer fits in an `u8`, so the cast to the type of maxcnt
// is also fine.
//
// Note that that nrf52840 maxcnt is a wider
// type than a u8, so we use a `_` cast rather than a `u8` cast.
// The MAXCNT field is thus at least 8 bits wide and accepts the
// full range of values that fit in a `u8`.
w . maxcnt ( ) . bits ( buffer . len ( ) as _ ) ) ;
Ok ( ( ) )
}
fn clear_errorsrc ( & mut self ) {
let r = T ::regs ( ) ;
r . errorsrc
. write ( | w | w . anack ( ) . bit ( true ) . dnack ( ) . bit ( true ) . overrun ( ) . bit ( true ) ) ;
}
/// Get Error instance, if any occurred.
2022-01-13 20:47:28 +01:00
fn check_errorsrc ( & self ) -> Result < ( ) , Error > {
2021-05-11 03:07:37 +02:00
let r = T ::regs ( ) ;
let err = r . errorsrc . read ( ) ;
if err . anack ( ) . is_received ( ) {
return Err ( Error ::AddressNack ) ;
}
if err . dnack ( ) . is_received ( ) {
return Err ( Error ::DataNack ) ;
}
if err . overrun ( ) . is_received ( ) {
2023-02-01 00:48:33 +01:00
return Err ( Error ::Overrun ) ;
2021-05-11 03:07:37 +02:00
}
Ok ( ( ) )
}
2022-01-13 20:47:28 +01:00
fn check_rx ( & self , len : usize ) -> Result < ( ) , Error > {
let r = T ::regs ( ) ;
if r . rxd . amount . read ( ) . bits ( ) ! = len as u32 {
Err ( Error ::Receive )
} else {
Ok ( ( ) )
}
}
fn check_tx ( & self , len : usize ) -> Result < ( ) , Error > {
let r = T ::regs ( ) ;
if r . txd . amount . read ( ) . bits ( ) ! = len as u32 {
Err ( Error ::Transmit )
} else {
Ok ( ( ) )
}
}
2021-05-11 03:07:37 +02:00
/// Wait for stop or error
2022-01-13 20:47:28 +01:00
fn blocking_wait ( & mut self ) {
2021-05-11 03:07:37 +02:00
let r = T ::regs ( ) ;
loop {
if r . events_stopped . read ( ) . bits ( ) ! = 0 {
r . events_stopped . reset ( ) ;
break ;
}
if r . events_error . read ( ) . bits ( ) ! = 0 {
r . events_error . reset ( ) ;
r . tasks_stop . write ( | w | unsafe { w . bits ( 1 ) } ) ;
}
}
}
2022-05-03 00:43:59 +02:00
/// Wait for stop or error
#[ cfg(feature = " time " ) ]
fn blocking_wait_timeout ( & mut self , timeout : Duration ) -> Result < ( ) , Error > {
let r = T ::regs ( ) ;
let deadline = Instant ::now ( ) + timeout ;
loop {
if r . events_stopped . read ( ) . bits ( ) ! = 0 {
r . events_stopped . reset ( ) ;
break ;
}
if r . events_error . read ( ) . bits ( ) ! = 0 {
r . events_error . reset ( ) ;
r . tasks_stop . write ( | w | unsafe { w . bits ( 1 ) } ) ;
}
if Instant ::now ( ) > deadline {
r . tasks_stop . write ( | w | unsafe { w . bits ( 1 ) } ) ;
return Err ( Error ::Timeout ) ;
}
}
Ok ( ( ) )
}
2022-01-13 20:47:28 +01:00
/// Wait for stop or error
fn async_wait ( & mut self ) -> impl Future < Output = ( ) > {
poll_fn ( move | cx | {
let r = T ::regs ( ) ;
let s = T ::state ( ) ;
s . end_waker . register ( cx . waker ( ) ) ;
if r . events_stopped . read ( ) . bits ( ) ! = 0 {
r . events_stopped . reset ( ) ;
return Poll ::Ready ( ( ) ) ;
}
2023-05-08 23:25:01 +02:00
// stop if an error occurred
2022-01-13 20:47:28 +01:00
if r . events_error . read ( ) . bits ( ) ! = 0 {
r . events_error . reset ( ) ;
r . tasks_stop . write ( | w | unsafe { w . bits ( 1 ) } ) ;
}
Poll ::Pending
} )
}
2022-06-12 22:15:44 +02:00
fn setup_write_from_ram ( & mut self , address : u8 , buffer : & [ u8 ] , inten : bool ) -> Result < ( ) , Error > {
2021-05-11 03:07:37 +02:00
let r = T ::regs ( ) ;
compiler_fence ( SeqCst ) ;
r . address . write ( | w | unsafe { w . address ( ) . bits ( address ) } ) ;
// Set up the DMA write.
unsafe { self . set_tx_buffer ( buffer ) ? } ;
// Clear events
r . events_stopped . reset ( ) ;
r . events_error . reset ( ) ;
r . events_lasttx . reset ( ) ;
self . clear_errorsrc ( ) ;
2022-01-13 20:47:28 +01:00
if inten {
r . intenset . write ( | w | w . stopped ( ) . set ( ) . error ( ) . set ( ) ) ;
} else {
r . intenclr . write ( | w | w . stopped ( ) . clear ( ) . error ( ) . clear ( ) ) ;
2021-05-11 03:07:37 +02:00
}
2022-01-13 20:47:28 +01:00
// Start write operation.
r . shorts . write ( | w | w . lasttx_stop ( ) . enabled ( ) ) ;
r . tasks_starttx . write ( | w | unsafe { w . bits ( 1 ) } ) ;
2022-06-07 14:52:45 +02:00
if buffer . len ( ) = = 0 {
// With a zero-length buffer, LASTTX doesn't fire (because there's no last byte!), so do the STOP ourselves.
r . tasks_stop . write ( | w | unsafe { w . bits ( 1 ) } ) ;
}
2021-05-11 03:07:37 +02:00
Ok ( ( ) )
}
2022-01-13 20:47:28 +01:00
fn setup_read ( & mut self , address : u8 , buffer : & mut [ u8 ] , inten : bool ) -> Result < ( ) , Error > {
2021-05-11 03:07:37 +02:00
let r = T ::regs ( ) ;
compiler_fence ( SeqCst ) ;
r . address . write ( | w | unsafe { w . address ( ) . bits ( address ) } ) ;
// Set up the DMA read.
unsafe { self . set_rx_buffer ( buffer ) ? } ;
// Clear events
r . events_stopped . reset ( ) ;
r . events_error . reset ( ) ;
self . clear_errorsrc ( ) ;
2022-01-13 20:47:28 +01:00
if inten {
r . intenset . write ( | w | w . stopped ( ) . set ( ) . error ( ) . set ( ) ) ;
} else {
r . intenclr . write ( | w | w . stopped ( ) . clear ( ) . error ( ) . clear ( ) ) ;
2021-05-11 03:07:37 +02:00
}
2022-01-13 20:47:28 +01:00
// Start read operation.
r . shorts . write ( | w | w . lastrx_stop ( ) . enabled ( ) ) ;
r . tasks_startrx . write ( | w | unsafe { w . bits ( 1 ) } ) ;
2022-06-07 14:52:45 +02:00
if buffer . len ( ) = = 0 {
// With a zero-length buffer, LASTRX doesn't fire (because there's no last byte!), so do the STOP ourselves.
r . tasks_stop . write ( | w | unsafe { w . bits ( 1 ) } ) ;
}
2021-05-11 03:07:37 +02:00
Ok ( ( ) )
}
2022-03-02 22:45:38 +01:00
fn setup_write_read_from_ram (
2021-05-11 03:07:37 +02:00
& mut self ,
address : u8 ,
wr_buffer : & [ u8 ] ,
rd_buffer : & mut [ u8 ] ,
2022-01-13 20:47:28 +01:00
inten : bool ,
2021-05-11 03:07:37 +02:00
) -> Result < ( ) , Error > {
let r = T ::regs ( ) ;
compiler_fence ( SeqCst ) ;
r . address . write ( | w | unsafe { w . address ( ) . bits ( address ) } ) ;
// Set up DMA buffers.
unsafe {
self . set_tx_buffer ( wr_buffer ) ? ;
self . set_rx_buffer ( rd_buffer ) ? ;
}
// Clear events
r . events_stopped . reset ( ) ;
r . events_error . reset ( ) ;
self . clear_errorsrc ( ) ;
2022-01-13 20:47:28 +01:00
if inten {
r . intenset . write ( | w | w . stopped ( ) . set ( ) . error ( ) . set ( ) ) ;
} else {
r . intenclr . write ( | w | w . stopped ( ) . clear ( ) . error ( ) . clear ( ) ) ;
}
2021-05-11 03:07:37 +02:00
// Start write+read operation.
r . shorts . write ( | w | {
w . lasttx_startrx ( ) . enabled ( ) ;
w . lastrx_stop ( ) . enabled ( ) ;
w
} ) ;
r . tasks_starttx . write ( | w | unsafe { w . bits ( 1 ) } ) ;
2022-06-07 14:52:45 +02:00
if wr_buffer . len ( ) = = 0 & & rd_buffer . len ( ) = = 0 {
// With a zero-length buffer, LASTRX/LASTTX doesn't fire (because there's no last byte!), so do the STOP ourselves.
// TODO handle when only one of the buffers is zero length
r . tasks_stop . write ( | w | unsafe { w . bits ( 1 ) } ) ;
}
2022-01-13 20:47:28 +01:00
Ok ( ( ) )
}
2021-05-11 03:07:37 +02:00
2022-03-02 22:45:38 +01:00
fn setup_write_read (
& mut self ,
address : u8 ,
wr_buffer : & [ u8 ] ,
rd_buffer : & mut [ u8 ] ,
inten : bool ,
) -> Result < ( ) , Error > {
match self . setup_write_read_from_ram ( address , wr_buffer , rd_buffer , inten ) {
Ok ( _ ) = > Ok ( ( ) ) ,
2023-02-01 00:48:33 +01:00
Err ( Error ::BufferNotInRAM ) = > {
2022-03-02 22:45:38 +01:00
trace! ( " Copying TWIM tx buffer into RAM for DMA " ) ;
2022-03-02 22:48:58 +01:00
let tx_ram_buf = & mut [ 0 ; FORCE_COPY_BUFFER_SIZE ] [ .. wr_buffer . len ( ) ] ;
tx_ram_buf . copy_from_slice ( wr_buffer ) ;
self . setup_write_read_from_ram ( address , & tx_ram_buf , rd_buffer , inten )
2022-03-02 22:45:38 +01:00
}
Err ( error ) = > Err ( error ) ,
}
}
fn setup_write ( & mut self , address : u8 , wr_buffer : & [ u8 ] , inten : bool ) -> Result < ( ) , Error > {
match self . setup_write_from_ram ( address , wr_buffer , inten ) {
Ok ( _ ) = > Ok ( ( ) ) ,
2023-02-01 00:48:33 +01:00
Err ( Error ::BufferNotInRAM ) = > {
2022-03-02 22:45:38 +01:00
trace! ( " Copying TWIM tx buffer into RAM for DMA " ) ;
2022-03-02 22:48:58 +01:00
let tx_ram_buf = & mut [ 0 ; FORCE_COPY_BUFFER_SIZE ] [ .. wr_buffer . len ( ) ] ;
tx_ram_buf . copy_from_slice ( wr_buffer ) ;
self . setup_write_from_ram ( address , & tx_ram_buf , inten )
2022-03-02 22:45:38 +01:00
}
Err ( error ) = > Err ( error ) ,
}
}
2022-01-13 20:47:28 +01:00
/// Write to an I2C slave.
///
/// The buffer must have a length of at most 255 bytes on the nRF52832
/// and at most 65535 bytes on the nRF52840.
pub fn blocking_write ( & mut self , address : u8 , buffer : & [ u8 ] ) -> Result < ( ) , Error > {
self . setup_write ( address , buffer , false ) ? ;
self . blocking_wait ( ) ;
2021-05-11 03:07:37 +02:00
compiler_fence ( SeqCst ) ;
2022-01-13 20:47:28 +01:00
self . check_errorsrc ( ) ? ;
self . check_tx ( buffer . len ( ) ) ? ;
Ok ( ( ) )
}
2021-05-11 03:07:37 +02:00
2022-03-08 16:42:46 +01:00
/// Same as [`blocking_write`](Twim::blocking_write) but will fail instead of copying data into RAM. Consult the module level documentation to learn more.
2022-03-02 22:45:38 +01:00
pub fn blocking_write_from_ram ( & mut self , address : u8 , buffer : & [ u8 ] ) -> Result < ( ) , Error > {
self . setup_write_from_ram ( address , buffer , false ) ? ;
self . blocking_wait ( ) ;
compiler_fence ( SeqCst ) ;
self . check_errorsrc ( ) ? ;
self . check_tx ( buffer . len ( ) ) ? ;
Ok ( ( ) )
}
2022-01-13 20:47:28 +01:00
/// Read from an I2C slave.
///
/// The buffer must have a length of at most 255 bytes on the nRF52832
/// and at most 65535 bytes on the nRF52840.
pub fn blocking_read ( & mut self , address : u8 , buffer : & mut [ u8 ] ) -> Result < ( ) , Error > {
self . setup_read ( address , buffer , false ) ? ;
self . blocking_wait ( ) ;
compiler_fence ( SeqCst ) ;
self . check_errorsrc ( ) ? ;
self . check_rx ( buffer . len ( ) ) ? ;
Ok ( ( ) )
}
2021-05-11 03:07:37 +02:00
2022-01-13 20:47:28 +01:00
/// Write data to an I2C slave, then read data from the slave without
/// triggering a stop condition between the two.
///
/// The buffers must have a length of at most 255 bytes on the nRF52832
/// and at most 65535 bytes on the nRF52840.
2022-06-12 22:15:44 +02:00
pub fn blocking_write_read ( & mut self , address : u8 , wr_buffer : & [ u8 ] , rd_buffer : & mut [ u8 ] ) -> Result < ( ) , Error > {
2022-01-13 20:47:28 +01:00
self . setup_write_read ( address , wr_buffer , rd_buffer , false ) ? ;
self . blocking_wait ( ) ;
compiler_fence ( SeqCst ) ;
self . check_errorsrc ( ) ? ;
self . check_tx ( wr_buffer . len ( ) ) ? ;
self . check_rx ( rd_buffer . len ( ) ) ? ;
2021-05-11 03:07:37 +02:00
Ok ( ( ) )
}
2022-03-08 16:42:46 +01:00
/// Same as [`blocking_write_read`](Twim::blocking_write_read) but will fail instead of copying data into RAM. Consult the module level documentation to learn more.
2022-03-02 22:45:38 +01:00
pub fn blocking_write_read_from_ram (
2021-05-11 03:07:37 +02:00
& mut self ,
address : u8 ,
wr_buffer : & [ u8 ] ,
rd_buffer : & mut [ u8 ] ,
) -> Result < ( ) , Error > {
2022-03-02 22:45:38 +01:00
self . setup_write_read_from_ram ( address , wr_buffer , rd_buffer , false ) ? ;
self . blocking_wait ( ) ;
compiler_fence ( SeqCst ) ;
self . check_errorsrc ( ) ? ;
self . check_tx ( wr_buffer . len ( ) ) ? ;
self . check_rx ( rd_buffer . len ( ) ) ? ;
Ok ( ( ) )
2021-05-11 03:07:37 +02:00
}
2021-06-05 11:58:50 +02:00
2022-05-03 00:43:59 +02:00
// ===========================================
/// Write to an I2C slave with timeout.
///
/// See [`blocking_write`].
#[ cfg(feature = " time " ) ]
2022-06-12 22:15:44 +02:00
pub fn blocking_write_timeout ( & mut self , address : u8 , buffer : & [ u8 ] , timeout : Duration ) -> Result < ( ) , Error > {
2022-05-03 00:43:59 +02:00
self . setup_write ( address , buffer , false ) ? ;
self . blocking_wait_timeout ( timeout ) ? ;
compiler_fence ( SeqCst ) ;
self . check_errorsrc ( ) ? ;
self . check_tx ( buffer . len ( ) ) ? ;
Ok ( ( ) )
}
/// Same as [`blocking_write`](Twim::blocking_write) but will fail instead of copying data into RAM. Consult the module level documentation to learn more.
#[ cfg(feature = " time " ) ]
pub fn blocking_write_from_ram_timeout (
& mut self ,
address : u8 ,
buffer : & [ u8 ] ,
timeout : Duration ,
) -> Result < ( ) , Error > {
self . setup_write_from_ram ( address , buffer , false ) ? ;
self . blocking_wait_timeout ( timeout ) ? ;
compiler_fence ( SeqCst ) ;
self . check_errorsrc ( ) ? ;
self . check_tx ( buffer . len ( ) ) ? ;
Ok ( ( ) )
}
/// Read from an I2C slave.
///
/// The buffer must have a length of at most 255 bytes on the nRF52832
/// and at most 65535 bytes on the nRF52840.
#[ cfg(feature = " time " ) ]
2022-06-12 22:15:44 +02:00
pub fn blocking_read_timeout ( & mut self , address : u8 , buffer : & mut [ u8 ] , timeout : Duration ) -> Result < ( ) , Error > {
2022-05-03 00:43:59 +02:00
self . setup_read ( address , buffer , false ) ? ;
self . blocking_wait_timeout ( timeout ) ? ;
compiler_fence ( SeqCst ) ;
self . check_errorsrc ( ) ? ;
self . check_rx ( buffer . len ( ) ) ? ;
Ok ( ( ) )
}
/// Write data to an I2C slave, then read data from the slave without
/// triggering a stop condition between the two.
///
/// The buffers must have a length of at most 255 bytes on the nRF52832
/// and at most 65535 bytes on the nRF52840.
#[ cfg(feature = " time " ) ]
pub fn blocking_write_read_timeout (
& mut self ,
address : u8 ,
wr_buffer : & [ u8 ] ,
rd_buffer : & mut [ u8 ] ,
timeout : Duration ,
) -> Result < ( ) , Error > {
self . setup_write_read ( address , wr_buffer , rd_buffer , false ) ? ;
self . blocking_wait_timeout ( timeout ) ? ;
compiler_fence ( SeqCst ) ;
self . check_errorsrc ( ) ? ;
self . check_tx ( wr_buffer . len ( ) ) ? ;
self . check_rx ( rd_buffer . len ( ) ) ? ;
Ok ( ( ) )
}
/// Same as [`blocking_write_read`](Twim::blocking_write_read) but will fail instead of copying data into RAM. Consult the module level documentation to learn more.
#[ cfg(feature = " time " ) ]
pub fn blocking_write_read_from_ram_timeout (
& mut self ,
address : u8 ,
wr_buffer : & [ u8 ] ,
rd_buffer : & mut [ u8 ] ,
timeout : Duration ,
) -> Result < ( ) , Error > {
self . setup_write_read_from_ram ( address , wr_buffer , rd_buffer , false ) ? ;
self . blocking_wait_timeout ( timeout ) ? ;
compiler_fence ( SeqCst ) ;
self . check_errorsrc ( ) ? ;
self . check_tx ( wr_buffer . len ( ) ) ? ;
self . check_rx ( rd_buffer . len ( ) ) ? ;
Ok ( ( ) )
}
// ===========================================
2023-02-01 00:48:33 +01:00
/// Read from an I2C slave.
///
/// The buffer must have a length of at most 255 bytes on the nRF52832
/// and at most 65535 bytes on the nRF52840.
2022-01-13 20:47:28 +01:00
pub async fn read ( & mut self , address : u8 , buffer : & mut [ u8 ] ) -> Result < ( ) , Error > {
self . setup_read ( address , buffer , true ) ? ;
self . async_wait ( ) . await ;
compiler_fence ( SeqCst ) ;
self . check_errorsrc ( ) ? ;
self . check_rx ( buffer . len ( ) ) ? ;
Ok ( ( ) )
}
2021-06-05 11:58:50 +02:00
2023-02-01 00:48:33 +01:00
/// Write to an I2C slave.
///
/// The buffer must have a length of at most 255 bytes on the nRF52832
/// and at most 65535 bytes on the nRF52840.
2022-01-13 20:47:28 +01:00
pub async fn write ( & mut self , address : u8 , buffer : & [ u8 ] ) -> Result < ( ) , Error > {
self . setup_write ( address , buffer , true ) ? ;
self . async_wait ( ) . await ;
compiler_fence ( SeqCst ) ;
self . check_errorsrc ( ) ? ;
self . check_tx ( buffer . len ( ) ) ? ;
Ok ( ( ) )
}
2021-06-05 11:58:50 +02:00
2022-03-08 16:42:46 +01:00
/// Same as [`write`](Twim::write) but will fail instead of copying data into RAM. Consult the module level documentation to learn more.
2022-03-02 22:45:38 +01:00
pub async fn write_from_ram ( & mut self , address : u8 , buffer : & [ u8 ] ) -> Result < ( ) , Error > {
self . setup_write_from_ram ( address , buffer , true ) ? ;
self . async_wait ( ) . await ;
compiler_fence ( SeqCst ) ;
self . check_errorsrc ( ) ? ;
self . check_tx ( buffer . len ( ) ) ? ;
Ok ( ( ) )
}
2023-02-01 00:48:33 +01:00
/// Write data to an I2C slave, then read data from the slave without
/// triggering a stop condition between the two.
///
/// The buffers must have a length of at most 255 bytes on the nRF52832
/// and at most 65535 bytes on the nRF52840.
2022-06-12 22:15:44 +02:00
pub async fn write_read ( & mut self , address : u8 , wr_buffer : & [ u8 ] , rd_buffer : & mut [ u8 ] ) -> Result < ( ) , Error > {
2022-01-13 20:47:28 +01:00
self . setup_write_read ( address , wr_buffer , rd_buffer , true ) ? ;
self . async_wait ( ) . await ;
compiler_fence ( SeqCst ) ;
self . check_errorsrc ( ) ? ;
self . check_tx ( wr_buffer . len ( ) ) ? ;
self . check_rx ( rd_buffer . len ( ) ) ? ;
Ok ( ( ) )
2021-06-05 11:58:50 +02:00
}
2022-03-02 22:45:38 +01:00
2022-03-08 16:42:46 +01:00
/// Same as [`write_read`](Twim::write_read) but will fail instead of copying data into RAM. Consult the module level documentation to learn more.
2022-03-02 22:45:38 +01:00
pub async fn write_read_from_ram (
& mut self ,
address : u8 ,
wr_buffer : & [ u8 ] ,
rd_buffer : & mut [ u8 ] ,
) -> Result < ( ) , Error > {
self . setup_write_read_from_ram ( address , wr_buffer , rd_buffer , true ) ? ;
self . async_wait ( ) . await ;
compiler_fence ( SeqCst ) ;
self . check_errorsrc ( ) ? ;
self . check_tx ( wr_buffer . len ( ) ) ? ;
self . check_rx ( rd_buffer . len ( ) ) ? ;
Ok ( ( ) )
}
2021-05-11 03:07:37 +02:00
}
impl < ' a , T : Instance > Drop for Twim < ' a , T > {
fn drop ( & mut self ) {
2021-12-23 13:43:14 +01:00
trace! ( " twim drop " ) ;
2021-05-11 03:07:37 +02:00
2022-01-13 20:47:28 +01:00
// TODO: check for abort
2021-05-11 03:07:37 +02:00
// disable!
let r = T ::regs ( ) ;
r . enable . write ( | w | w . enable ( ) . disabled ( ) ) ;
2021-05-26 18:09:18 +02:00
gpio ::deconfigure_pin ( r . psel . sda . read ( ) . bits ( ) ) ;
gpio ::deconfigure_pin ( r . psel . scl . read ( ) . bits ( ) ) ;
2021-05-11 03:07:37 +02:00
2021-12-23 13:43:14 +01:00
trace! ( " twim drop: done " ) ;
2021-05-11 03:07:37 +02:00
}
}
pub ( crate ) mod sealed {
use super ::* ;
pub struct State {
pub end_waker : AtomicWaker ,
}
impl State {
pub const fn new ( ) -> Self {
Self {
end_waker : AtomicWaker ::new ( ) ,
}
}
}
pub trait Instance {
fn regs ( ) -> & 'static pac ::twim0 ::RegisterBlock ;
fn state ( ) -> & 'static State ;
}
}
2023-02-01 00:48:33 +01:00
/// TWIM peripheral instance.
2022-07-23 14:00:19 +02:00
pub trait Instance : Peripheral < P = Self > + sealed ::Instance + 'static {
2023-02-01 00:48:33 +01:00
/// Interrupt for this peripheral.
2023-06-08 16:08:40 +02:00
type Interrupt : interrupt ::typelevel ::Interrupt ;
2021-05-11 03:07:37 +02:00
}
macro_rules ! impl_twim {
( $type :ident , $pac_type :ident , $irq :ident ) = > {
impl crate ::twim ::sealed ::Instance for peripherals ::$type {
fn regs ( ) -> & 'static pac ::twim0 ::RegisterBlock {
unsafe { & * pac ::$pac_type ::ptr ( ) }
}
fn state ( ) -> & 'static crate ::twim ::sealed ::State {
static STATE : crate ::twim ::sealed ::State = crate ::twim ::sealed ::State ::new ( ) ;
& STATE
}
}
impl crate ::twim ::Instance for peripherals ::$type {
2023-06-08 16:08:40 +02:00
type Interrupt = crate ::interrupt ::typelevel ::$irq ;
2021-05-11 03:07:37 +02:00
}
} ;
}
2022-01-13 23:56:25 +01:00
// ====================
mod eh02 {
use super ::* ;
impl < ' a , T : Instance > embedded_hal_02 ::blocking ::i2c ::Write for Twim < ' a , T > {
type Error = Error ;
fn write < ' w > ( & mut self , addr : u8 , bytes : & ' w [ u8 ] ) -> Result < ( ) , Error > {
if slice_in_ram ( bytes ) {
self . blocking_write ( addr , bytes )
} else {
let buf = & mut [ 0 ; FORCE_COPY_BUFFER_SIZE ] [ .. ] ;
for chunk in bytes . chunks ( FORCE_COPY_BUFFER_SIZE ) {
buf [ .. chunk . len ( ) ] . copy_from_slice ( chunk ) ;
self . blocking_write ( addr , & buf [ .. chunk . len ( ) ] ) ? ;
}
Ok ( ( ) )
}
}
}
impl < ' a , T : Instance > embedded_hal_02 ::blocking ::i2c ::Read for Twim < ' a , T > {
type Error = Error ;
fn read < ' w > ( & mut self , addr : u8 , bytes : & ' w mut [ u8 ] ) -> Result < ( ) , Error > {
self . blocking_read ( addr , bytes )
}
}
impl < ' a , T : Instance > embedded_hal_02 ::blocking ::i2c ::WriteRead for Twim < ' a , T > {
type Error = Error ;
2022-06-12 22:15:44 +02:00
fn write_read < ' w > ( & mut self , addr : u8 , bytes : & ' w [ u8 ] , buffer : & ' w mut [ u8 ] ) -> Result < ( ) , Error > {
2022-03-02 22:45:38 +01:00
self . blocking_write_read ( addr , bytes , buffer )
2022-01-13 23:56:25 +01:00
}
}
}
#[ cfg(feature = " unstable-traits " ) ]
mod eh1 {
use super ::* ;
impl embedded_hal_1 ::i2c ::Error for Error {
fn kind ( & self ) -> embedded_hal_1 ::i2c ::ErrorKind {
match * self {
Self ::TxBufferTooLong = > embedded_hal_1 ::i2c ::ErrorKind ::Other ,
Self ::RxBufferTooLong = > embedded_hal_1 ::i2c ::ErrorKind ::Other ,
Self ::Transmit = > embedded_hal_1 ::i2c ::ErrorKind ::Other ,
Self ::Receive = > embedded_hal_1 ::i2c ::ErrorKind ::Other ,
2023-02-01 00:48:33 +01:00
Self ::BufferNotInRAM = > embedded_hal_1 ::i2c ::ErrorKind ::Other ,
2022-06-12 22:15:44 +02:00
Self ::AddressNack = > {
embedded_hal_1 ::i2c ::ErrorKind ::NoAcknowledge ( embedded_hal_1 ::i2c ::NoAcknowledgeSource ::Address )
}
Self ::DataNack = > {
embedded_hal_1 ::i2c ::ErrorKind ::NoAcknowledge ( embedded_hal_1 ::i2c ::NoAcknowledgeSource ::Data )
}
2022-01-13 23:56:25 +01:00
Self ::Overrun = > embedded_hal_1 ::i2c ::ErrorKind ::Overrun ,
2022-05-03 00:43:59 +02:00
Self ::Timeout = > embedded_hal_1 ::i2c ::ErrorKind ::Other ,
2022-01-13 23:56:25 +01:00
}
}
}
impl < ' d , T : Instance > embedded_hal_1 ::i2c ::ErrorType for Twim < ' d , T > {
type Error = Error ;
}
2022-09-29 11:02:43 +02:00
impl < ' d , T : Instance > embedded_hal_1 ::i2c ::I2c for Twim < ' d , T > {
2022-01-13 23:56:25 +01:00
fn read ( & mut self , address : u8 , buffer : & mut [ u8 ] ) -> Result < ( ) , Self ::Error > {
self . blocking_read ( address , buffer )
}
fn write ( & mut self , address : u8 , buffer : & [ u8 ] ) -> Result < ( ) , Self ::Error > {
self . blocking_write ( address , buffer )
}
2022-06-12 22:15:44 +02:00
fn write_read ( & mut self , address : u8 , wr_buffer : & [ u8 ] , rd_buffer : & mut [ u8 ] ) -> Result < ( ) , Self ::Error > {
2022-01-13 23:56:25 +01:00
self . blocking_write_read ( address , wr_buffer , rd_buffer )
}
fn transaction < ' a > (
& mut self ,
_address : u8 ,
2022-09-29 11:02:43 +02:00
_operations : & mut [ embedded_hal_1 ::i2c ::Operation < ' a > ] ,
2022-01-13 23:56:25 +01:00
) -> Result < ( ) , Self ::Error > {
todo! ( ) ;
}
}
2022-02-12 00:24:04 +01:00
}
2022-01-13 23:56:25 +01:00
2022-08-31 02:46:52 +02:00
#[ cfg(all(feature = " unstable-traits " , feature = " nightly " )) ]
mod eha {
use super ::* ;
impl < ' d , T : Instance > embedded_hal_async ::i2c ::I2c for Twim < ' d , T > {
2023-04-06 22:25:24 +02:00
async fn read ( & mut self , address : u8 , read : & mut [ u8 ] ) -> Result < ( ) , Self ::Error > {
self . read ( address , read ) . await
2022-08-31 02:46:52 +02:00
}
2022-01-13 23:56:25 +01:00
2023-04-06 22:25:24 +02:00
async fn write ( & mut self , address : u8 , write : & [ u8 ] ) -> Result < ( ) , Self ::Error > {
self . write ( address , write ) . await
2022-08-31 02:46:52 +02:00
}
2023-04-06 22:25:24 +02:00
async fn write_read ( & mut self , address : u8 , write : & [ u8 ] , read : & mut [ u8 ] ) -> Result < ( ) , Self ::Error > {
self . write_read ( address , write , read ) . await
2022-08-31 02:46:52 +02:00
}
2022-01-13 23:56:25 +01:00
2023-04-06 22:25:24 +02:00
async fn transaction (
& mut self ,
2022-08-31 02:46:52 +02:00
address : u8 ,
2023-04-06 22:25:24 +02:00
operations : & mut [ embedded_hal_1 ::i2c ::Operation < '_ > ] ,
) -> Result < ( ) , Self ::Error > {
2022-08-31 02:46:52 +02:00
let _ = address ;
let _ = operations ;
2022-11-21 23:31:31 +01:00
todo! ( )
2022-02-16 03:54:39 +01:00
}
2022-01-13 23:56:25 +01:00
}
}
2022-07-08 15:47:47 +02:00
2022-07-09 00:00:55 +02:00
impl < ' d , T : Instance > SetConfig for Twim < ' d , T > {
type Config = Config ;
fn set_config ( & mut self , config : & Self ::Config ) {
2022-07-08 15:47:47 +02:00
let r = T ::regs ( ) ;
r . frequency
. write ( | w | unsafe { w . frequency ( ) . bits ( config . frequency as u32 ) } ) ;
}
}