From e228f637f9bbf78ea25ff21ce92b05c54e5802b2 Mon Sep 17 00:00:00 2001 From: Alex Martens Date: Sun, 14 Aug 2022 14:49:41 -0700 Subject: [PATCH] change internal structure from Mutex> to Arc> --- CHANGELOG.md | 3 + src/gpio.rs | 53 +++++------ src/i2c.rs | 260 ++++++++++++++++++++++++--------------------------- src/lib.rs | 6 +- src/spi.rs | 47 +++++----- 5 files changed, 172 insertions(+), 197 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b120bfd..c624b5a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Added re-exports for `libftd2xx` and `ftdi` when the respective feature is used. +### Changed +- Changed the internal shared FTDI type from `Mutex>>` to `Arc>>`. + ## [0.11.0] - 2022-01-18 ### Added - Added support for input pins. diff --git a/src/gpio.rs b/src/gpio.rs index c3142de..73d6fdd 100644 --- a/src/gpio.rs +++ b/src/gpio.rs @@ -1,8 +1,7 @@ use crate::error::Error; use crate::{FtInner, PinUse}; use ftdi_mpsse::{MpsseCmdBuilder, MpsseCmdExecutor}; -use std::result::Result; -use std::{cell::RefCell, sync::Mutex}; +use std::sync::{Arc, Mutex}; /// FTDI output pin. /// @@ -13,7 +12,7 @@ use std::{cell::RefCell, sync::Mutex}; #[derive(Debug)] pub struct OutputPin<'a, Device: MpsseCmdExecutor> { /// Parent FTDI device. - mtx: &'a Mutex>>, + mtx: &'a Arc>>, /// GPIO pin index. 0-7 for the FT232H. idx: u8, } @@ -25,34 +24,33 @@ where Error: From, { pub(crate) fn new( - mtx: &'a Mutex>>, + mtx: &'a Arc>>, idx: u8, ) -> Result, Error> { - let lock = mtx.lock().expect("Failed to aquire FTDI mutex"); - let mut inner = lock.borrow_mut(); - inner.direction |= 1 << idx; - inner.allocate_pin(idx, PinUse::Output); + let mut lock = mtx.lock().expect("Failed to aquire FTDI mutex"); + + lock.direction |= 1 << idx; + lock.allocate_pin(idx, PinUse::Output); let cmd: MpsseCmdBuilder = MpsseCmdBuilder::new() - .set_gpio_lower(inner.value, inner.direction) + .set_gpio_lower(lock.value, lock.direction) .send_immediate(); - inner.ft.send(cmd.as_slice())?; + lock.ft.send(cmd.as_slice())?; Ok(OutputPin { mtx, idx }) } pub(crate) fn set(&self, state: bool) -> Result<(), Error> { - let lock = self.mtx.lock().expect("Failed to aquire FTDI mutex"); - let mut inner = lock.borrow_mut(); + let mut lock = self.mtx.lock().expect("Failed to aquire FTDI mutex"); if state { - inner.value |= self.mask(); + lock.value |= self.mask(); } else { - inner.value &= !self.mask(); + lock.value &= !self.mask(); }; let cmd: MpsseCmdBuilder = MpsseCmdBuilder::new() - .set_gpio_lower(inner.value, inner.direction) + .set_gpio_lower(lock.value, lock.direction) .send_immediate(); - inner.ft.send(cmd.as_slice())?; + lock.ft.send(cmd.as_slice())?; Ok(()) } @@ -91,7 +89,7 @@ where #[derive(Debug)] pub struct InputPin<'a, Device: MpsseCmdExecutor> { /// Parent FTDI device. - mtx: &'a Mutex>>, + mtx: &'a Arc>>, /// GPIO pin index. 0-7 for the FT232H. idx: u8, } @@ -103,28 +101,27 @@ where Error: From, { pub(crate) fn new( - mtx: &'a Mutex>>, + mtx: &'a Arc>>, idx: u8, ) -> Result, Error> { - let lock = mtx.lock().expect("Failed to aquire FTDI mutex"); - let mut inner = lock.borrow_mut(); - inner.direction &= !(1 << idx); - inner.allocate_pin(idx, PinUse::Input); + let mut lock = mtx.lock().expect("Failed to aquire FTDI mutex"); + + lock.direction &= !(1 << idx); + lock.allocate_pin(idx, PinUse::Input); let cmd: MpsseCmdBuilder = MpsseCmdBuilder::new() - .set_gpio_lower(inner.value, inner.direction) + .set_gpio_lower(lock.value, lock.direction) .send_immediate(); - inner.ft.send(cmd.as_slice())?; + lock.ft.send(cmd.as_slice())?; Ok(InputPin { mtx, idx }) } pub(crate) fn get(&self) -> Result> { - let lock = self.mtx.lock().expect("Failed to aquire FTDI mutex"); - let mut inner = lock.borrow_mut(); + let mut lock = self.mtx.lock().expect("Failed to aquire FTDI mutex"); let mut buffer = [0u8; 1]; let cmd: MpsseCmdBuilder = MpsseCmdBuilder::new().gpio_lower().send_immediate(); - inner.ft.send(cmd.as_slice())?; - inner.ft.recv(&mut buffer)?; + lock.ft.send(cmd.as_slice())?; + lock.ft.recv(&mut buffer)?; Ok((buffer[0] & self.mask()) != 0) } diff --git a/src/i2c.rs b/src/i2c.rs index 9653c68..ea9d180 100644 --- a/src/i2c.rs +++ b/src/i2c.rs @@ -2,8 +2,7 @@ use crate::error::Error; use crate::error::ErrorKind::I2cNoAck; use crate::{FtInner, PinUse}; use ftdi_mpsse::{ClockBitsIn, ClockBitsOut, MpsseCmdBuilder, MpsseCmdExecutor}; -use std::result::Result; -use std::{cell::RefCell, sync::Mutex}; +use std::sync::{Arc, Mutex}; /// SCL bitmask const SCL: u8 = 1 << 0; @@ -21,7 +20,7 @@ const BITS_OUT: ClockBitsOut = ClockBitsOut::MsbNeg; #[derive(Debug)] pub struct I2c<'a, Device: MpsseCmdExecutor> { /// Parent FTDI device. - mtx: &'a Mutex>>, + mtx: &'a Arc>>, /// Length of the start, repeated start, and stop conditions. /// /// The units for these are dimensionless number of MPSSE commands. @@ -37,17 +36,16 @@ where E: std::error::Error, Error: From, { - pub(crate) fn new(mtx: &Mutex>>) -> Result, Error> { - let lock = mtx.lock().expect("Failed to aquire FTDI mutex"); - let mut inner = lock.borrow_mut(); - inner.allocate_pin(0, PinUse::I2c); - inner.allocate_pin(1, PinUse::I2c); - inner.allocate_pin(2, PinUse::I2c); + pub(crate) fn new(mtx: &Arc>>) -> Result, Error> { + let mut lock = mtx.lock().expect("Failed to aquire FTDI mutex"); - // clear direction and value of first 3 pins + lock.allocate_pin(0, PinUse::I2c); + lock.allocate_pin(1, PinUse::I2c); + lock.allocate_pin(2, PinUse::I2c); - inner.direction &= !0x07; - inner.value &= !0x07; + // clear direction and value of first 3 pins + lock.direction &= !0x07; + lock.value &= !0x07; // AD0: SCL // AD1: SDA (master out) // AD2: SDA (master in) @@ -55,10 +53,10 @@ where // set GPIO pins to new state let cmd: MpsseCmdBuilder = MpsseCmdBuilder::new() - .set_gpio_lower(inner.value, inner.direction) + .set_gpio_lower(lock.value, lock.direction) .enable_3phase_data_clocking() .send_immediate(); - inner.ft.send(cmd.as_slice())?; + lock.ft.send(cmd.as_slice())?; Ok(I2c { mtx, @@ -127,66 +125,63 @@ where fn read_fast(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> { assert!(!buffer.is_empty(), "buffer must be a non-empty slice"); - let lock = self.mtx.lock().expect("Failed to aquire FTDI mutex"); - let mut inner = lock.borrow_mut(); + let mut lock = self.mtx.lock().expect("Failed to aquire FTDI mutex"); // ST let mut mpsse_cmd: MpsseCmdBuilder = MpsseCmdBuilder::new(); for _ in 0..self.start_stop_cmds { - mpsse_cmd = - mpsse_cmd.set_gpio_lower(inner.value | SCL | SDA, SCL | SDA | inner.direction) + mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value | SCL | SDA, SCL | SDA | lock.direction) } for _ in 0..self.start_stop_cmds { - mpsse_cmd = mpsse_cmd.set_gpio_lower(inner.value | SCL, SCL | SDA | inner.direction) + mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value | SCL, SCL | SDA | lock.direction) } mpsse_cmd = mpsse_cmd // SAD+R - .set_gpio_lower(inner.value, SCL | SDA | inner.direction) + .set_gpio_lower(lock.value, SCL | SDA | lock.direction) .clock_bits_out(BITS_OUT, (address << 1) | 1, 8) // SAK - .set_gpio_lower(inner.value, SCL | inner.direction) + .set_gpio_lower(lock.value, SCL | lock.direction) .clock_bits_in(BITS_IN, 1); for idx in 0..buffer.len() { // Bn mpsse_cmd = mpsse_cmd - .set_gpio_lower(inner.value, SCL | inner.direction) + .set_gpio_lower(lock.value, SCL | lock.direction) .clock_bits_in(BITS_IN, 8); if idx == buffer.len() - 1 { // NMAK mpsse_cmd = mpsse_cmd - .set_gpio_lower(inner.value, SCL | SDA | inner.direction) + .set_gpio_lower(lock.value, SCL | SDA | lock.direction) .clock_bits_out(BITS_OUT, 0x80, 1) } else { // MAK mpsse_cmd = mpsse_cmd - .set_gpio_lower(inner.value, SCL | SDA | inner.direction) + .set_gpio_lower(lock.value, SCL | SDA | lock.direction) .clock_bits_out(BITS_OUT, 0x00, 1) } } // SP for _ in 0..self.start_stop_cmds { - mpsse_cmd = mpsse_cmd.set_gpio_lower(inner.value, SCL | SDA | inner.direction) + mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value, SCL | SDA | lock.direction) } for _ in 0..self.start_stop_cmds { - mpsse_cmd = mpsse_cmd.set_gpio_lower(inner.value | SCL, SCL | SDA | inner.direction) + mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value | SCL, SCL | SDA | lock.direction) } for _ in 0..self.start_stop_cmds { - mpsse_cmd = - mpsse_cmd.set_gpio_lower(inner.value | SCL | SDA, SCL | SDA | inner.direction) + mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value | SCL | SDA, SCL | SDA | lock.direction) } mpsse_cmd = mpsse_cmd // Idle - .set_gpio_lower(inner.value, inner.direction) + .set_gpio_lower(lock.value, lock.direction) .send_immediate(); - inner.ft.send(mpsse_cmd.as_slice())?; + lock.ft.send(mpsse_cmd.as_slice())?; let mut ack_buf: [u8; 1] = [0; 1]; - inner.ft.recv(&mut ack_buf)?; - inner.ft.recv(buffer)?; + lock.ft.recv(&mut ack_buf)?; + lock.ft.recv(buffer)?; if (ack_buf[0] & 0b1) != 0x00 { return Err(Error::Hal(I2cNoAck)); @@ -198,31 +193,29 @@ where fn read_slow(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> { assert!(!buffer.is_empty(), "buffer must be a non-empty slice"); - let lock = self.mtx.lock().expect("Failed to aquire FTDI mutex"); - let mut inner = lock.borrow_mut(); + let mut lock = self.mtx.lock().expect("Failed to aquire FTDI mutex"); // ST let mut mpsse_cmd: MpsseCmdBuilder = MpsseCmdBuilder::new(); for _ in 0..self.start_stop_cmds { - mpsse_cmd = - mpsse_cmd.set_gpio_lower(inner.value | SCL | SDA, SCL | SDA | inner.direction) + mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value | SCL | SDA, SCL | SDA | lock.direction) } for _ in 0..self.start_stop_cmds { - mpsse_cmd = mpsse_cmd.set_gpio_lower(inner.value | SCL, SCL | SDA | inner.direction) + mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value | SCL, SCL | SDA | lock.direction) } mpsse_cmd = mpsse_cmd // SAD+R - .set_gpio_lower(inner.value, SCL | SDA | inner.direction) + .set_gpio_lower(lock.value, SCL | SDA | lock.direction) .clock_bits_out(BITS_OUT, (address << 1) | 1, 8) // SAK - .set_gpio_lower(inner.value, SCL | inner.direction) + .set_gpio_lower(lock.value, SCL | lock.direction) .clock_bits_in(BITS_IN, 1) .send_immediate(); - inner.ft.send(mpsse_cmd.as_slice())?; + lock.ft.send(mpsse_cmd.as_slice())?; let mut ack_buf: [u8; 1] = [0; 1]; - inner.ft.recv(&mut ack_buf)?; + lock.ft.recv(&mut ack_buf)?; if (ack_buf[0] & 0b1) != 0x00 { return Err(Error::Hal(I2cNoAck)); } @@ -231,40 +224,39 @@ where for idx in 0..buffer.len() { // Bn mpsse_cmd = mpsse_cmd - .set_gpio_lower(inner.value, SCL | inner.direction) + .set_gpio_lower(lock.value, SCL | lock.direction) .clock_bits_in(BITS_IN, 8); if idx == buffer.len() - 1 { // NMAK mpsse_cmd = mpsse_cmd - .set_gpio_lower(inner.value, SCL | SDA | inner.direction) + .set_gpio_lower(lock.value, SCL | SDA | lock.direction) .clock_bits_out(BITS_OUT, 0x80, 1) } else { // MAK mpsse_cmd = mpsse_cmd - .set_gpio_lower(inner.value, SCL | SDA | inner.direction) + .set_gpio_lower(lock.value, SCL | SDA | lock.direction) .clock_bits_out(BITS_OUT, 0x00, 1) } } // SP for _ in 0..self.start_stop_cmds { - mpsse_cmd = mpsse_cmd.set_gpio_lower(inner.value, SCL | SDA | inner.direction) + mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value, SCL | SDA | lock.direction) } for _ in 0..self.start_stop_cmds { - mpsse_cmd = mpsse_cmd.set_gpio_lower(inner.value | SCL, SCL | SDA | inner.direction) + mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value | SCL, SCL | SDA | lock.direction) } for _ in 0..self.start_stop_cmds { - mpsse_cmd = - mpsse_cmd.set_gpio_lower(inner.value | SCL | SDA, SCL | SDA | inner.direction) + mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value | SCL | SDA, SCL | SDA | lock.direction) } mpsse_cmd = mpsse_cmd // Idle - .set_gpio_lower(inner.value, inner.direction) + .set_gpio_lower(lock.value, lock.direction) .send_immediate(); - inner.ft.send(mpsse_cmd.as_slice())?; - inner.ft.recv(buffer)?; + lock.ft.send(mpsse_cmd.as_slice())?; + lock.ft.recv(buffer)?; Ok(()) } @@ -272,57 +264,55 @@ where fn write_fast(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> { assert!(!bytes.is_empty(), "bytes must be a non-empty slice"); - let lock = self.mtx.lock().expect("Failed to aquire FTDI mutex"); - let mut inner = lock.borrow_mut(); + let mut lock = self.mtx.lock().expect("Failed to aquire FTDI mutex"); + let mut mpsse_cmd: MpsseCmdBuilder = MpsseCmdBuilder::new(); // ST for _ in 0..self.start_stop_cmds { - mpsse_cmd = - mpsse_cmd.set_gpio_lower(inner.value | SCL | SDA, SCL | SDA | inner.direction) + mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value | SCL | SDA, SCL | SDA | lock.direction) } for _ in 0..self.start_stop_cmds { - mpsse_cmd = mpsse_cmd.set_gpio_lower(inner.value | SCL, SCL | SDA | inner.direction) + mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value | SCL, SCL | SDA | lock.direction) } mpsse_cmd = mpsse_cmd // SAD+W - .set_gpio_lower(inner.value, SCL | SDA | inner.direction) + .set_gpio_lower(lock.value, SCL | SDA | lock.direction) .clock_bits_out(BITS_OUT, addr << 1, 8) // SAK - .set_gpio_lower(inner.value, SCL | inner.direction) + .set_gpio_lower(lock.value, SCL | lock.direction) .clock_bits_in(BITS_IN, 1); for byte in bytes.iter() { mpsse_cmd = mpsse_cmd // Bi - .set_gpio_lower(inner.value, SCL | SDA | inner.direction) + .set_gpio_lower(lock.value, SCL | SDA | lock.direction) .clock_bits_out(BITS_OUT, *byte, 8) // SAK - .set_gpio_lower(inner.value, SCL | inner.direction) + .set_gpio_lower(lock.value, SCL | lock.direction) .clock_bits_in(BITS_IN, 1); } // SP for _ in 0..self.start_stop_cmds { - mpsse_cmd = mpsse_cmd.set_gpio_lower(inner.value, SCL | SDA | inner.direction) + mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value, SCL | SDA | lock.direction) } for _ in 0..self.start_stop_cmds { - mpsse_cmd = mpsse_cmd.set_gpio_lower(inner.value | SCL, SCL | SDA | inner.direction) + mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value | SCL, SCL | SDA | lock.direction) } for _ in 0..self.start_stop_cmds { - mpsse_cmd = - mpsse_cmd.set_gpio_lower(inner.value | SCL | SDA, SCL | SDA | inner.direction) + mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value | SCL | SDA, SCL | SDA | lock.direction) } mpsse_cmd = mpsse_cmd // Idle - .set_gpio_lower(inner.value, inner.direction) + .set_gpio_lower(lock.value, lock.direction) .send_immediate(); - inner.ft.send(mpsse_cmd.as_slice())?; + lock.ft.send(mpsse_cmd.as_slice())?; let mut ack_buf: Vec = vec![0; 1 + bytes.len()]; - inner.ft.recv(ack_buf.as_mut_slice())?; + lock.ft.recv(ack_buf.as_mut_slice())?; if ack_buf.iter().any(|&ack| (ack & 0b1) != 0x00) { Err(Error::Hal(I2cNoAck)) } else { @@ -333,31 +323,29 @@ where fn write_slow(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> { assert!(!bytes.is_empty(), "bytes must be a non-empty slice"); - let lock = self.mtx.lock().expect("Failed to aquire FTDI mutex"); - let mut inner = lock.borrow_mut(); + let mut lock = self.mtx.lock().expect("Failed to aquire FTDI mutex"); // ST let mut mpsse_cmd: MpsseCmdBuilder = MpsseCmdBuilder::new(); for _ in 0..self.start_stop_cmds { - mpsse_cmd = - mpsse_cmd.set_gpio_lower(SCL | SDA | inner.value, SCL | SDA | inner.direction) + mpsse_cmd = mpsse_cmd.set_gpio_lower(SCL | SDA | lock.value, SCL | SDA | lock.direction) } for _ in 0..self.start_stop_cmds { - mpsse_cmd = mpsse_cmd.set_gpio_lower(SCL | inner.value, SCL | SDA | inner.direction) + mpsse_cmd = mpsse_cmd.set_gpio_lower(SCL | lock.value, SCL | SDA | lock.direction) } mpsse_cmd = mpsse_cmd // SAD+W - .set_gpio_lower(inner.value, SCL | SDA | inner.direction) + .set_gpio_lower(lock.value, SCL | SDA | lock.direction) .clock_bits_out(BITS_OUT, addr << 1, 8) // SAK - .set_gpio_lower(inner.value, SCL | inner.direction) + .set_gpio_lower(lock.value, SCL | lock.direction) .clock_bits_in(BITS_IN, 1) .send_immediate(); - inner.ft.send(mpsse_cmd.as_slice())?; + lock.ft.send(mpsse_cmd.as_slice())?; let mut ack_buf: [u8; 1] = [0; 1]; - inner.ft.recv(&mut ack_buf)?; + lock.ft.recv(&mut ack_buf)?; if (ack_buf[0] & 0b1) != 0x00 { return Err(Error::Hal(I2cNoAck)); } @@ -365,36 +353,36 @@ where for (idx, byte) in bytes.iter().enumerate() { let mut mpsse_cmd: MpsseCmdBuilder = MpsseCmdBuilder::new() // Bi - .set_gpio_lower(inner.value, SCL | SDA | inner.direction) + .set_gpio_lower(lock.value, SCL | SDA | lock.direction) .clock_bits_out(BITS_OUT, *byte, 8) // SAK - .set_gpio_lower(inner.value, SCL | inner.direction) + .set_gpio_lower(lock.value, SCL | lock.direction) .clock_bits_in(BITS_IN, 1); // last byte if idx == bytes.len() - 1 { // SP for _ in 0..self.start_stop_cmds { - mpsse_cmd = mpsse_cmd.set_gpio_lower(inner.value, SCL | SDA | inner.direction) + mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value, SCL | SDA | lock.direction) } for _ in 0..self.start_stop_cmds { mpsse_cmd = - mpsse_cmd.set_gpio_lower(inner.value | SCL, SCL | SDA | inner.direction) + mpsse_cmd.set_gpio_lower(lock.value | SCL, SCL | SDA | lock.direction) } for _ in 0..self.start_stop_cmds { - mpsse_cmd = mpsse_cmd - .set_gpio_lower(inner.value | SCL | SDA, SCL | SDA | inner.direction) + mpsse_cmd = + mpsse_cmd.set_gpio_lower(lock.value | SCL | SDA, SCL | SDA | lock.direction) } // Idle - mpsse_cmd = mpsse_cmd.set_gpio_lower(inner.value, inner.direction) + mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value, lock.direction) } mpsse_cmd = mpsse_cmd.send_immediate(); - inner.ft.send(mpsse_cmd.as_slice())?; + lock.ft.send(mpsse_cmd.as_slice())?; let mut ack_buf: [u8; 1] = [0; 1]; - inner.ft.recv(&mut ack_buf)?; + lock.ft.recv(&mut ack_buf)?; if (ack_buf[0] & 0b1) != 0x00 { return Err(Error::Hal(I2cNoAck)); } @@ -414,95 +402,91 @@ where // lock at the start to prevent GPIO from being modified while we build // the MPSSE command - let lock = self.mtx.lock().expect("Failed to aquire FTDI mutex"); - let mut inner = lock.borrow_mut(); + let mut lock = self.mtx.lock().expect("Failed to aquire FTDI mutex"); let mut mpsse_cmd: MpsseCmdBuilder = MpsseCmdBuilder::new(); // ST for _ in 0..self.start_stop_cmds { - mpsse_cmd = - mpsse_cmd.set_gpio_lower(inner.value | SCL | SDA, SCL | SDA | inner.direction) + mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value | SCL | SDA, SCL | SDA | lock.direction) } for _ in 0..self.start_stop_cmds { - mpsse_cmd = mpsse_cmd.set_gpio_lower(inner.value | SCL, SCL | SDA | inner.direction) + mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value | SCL, SCL | SDA | lock.direction) } mpsse_cmd = mpsse_cmd // SAD + W - .set_gpio_lower(inner.value, SCL | SDA | inner.direction) + .set_gpio_lower(lock.value, SCL | SDA | lock.direction) .clock_bits_out(BITS_OUT, address << 1, 8) // SAK - .set_gpio_lower(inner.value, SCL | inner.direction) + .set_gpio_lower(lock.value, SCL | lock.direction) .clock_bits_in(BITS_IN, 1); for byte in bytes { mpsse_cmd = mpsse_cmd // Oi - .set_gpio_lower(inner.value, SCL | SDA | inner.direction) + .set_gpio_lower(lock.value, SCL | SDA | lock.direction) .clock_bits_out(BITS_OUT, *byte, 8) // SAK - .set_gpio_lower(inner.value, SCL | inner.direction) + .set_gpio_lower(lock.value, SCL | lock.direction) .clock_bits_in(BITS_IN, 1); } // SR for _ in 0..self.start_stop_cmds { - mpsse_cmd = - mpsse_cmd.set_gpio_lower(inner.value | SCL | SDA, SCL | SDA | inner.direction) + mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value | SCL | SDA, SCL | SDA | lock.direction) } for _ in 0..self.start_stop_cmds { - mpsse_cmd = mpsse_cmd.set_gpio_lower(inner.value | SCL, SCL | SDA | inner.direction) + mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value | SCL, SCL | SDA | lock.direction) } for _ in 0..self.start_stop_cmds { - mpsse_cmd = mpsse_cmd.set_gpio_lower(inner.value, SCL | SDA | inner.direction) + mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value, SCL | SDA | lock.direction) } mpsse_cmd = mpsse_cmd // SAD + R .clock_bits_out(BITS_OUT, (address << 1) | 1, 8) // SAK - .set_gpio_lower(inner.value, SCL | inner.direction) + .set_gpio_lower(lock.value, SCL | lock.direction) .clock_bits_in(BITS_IN, 1); for idx in 0..buffer.len() { mpsse_cmd = mpsse_cmd - .set_gpio_lower(inner.value, SCL | inner.direction) + .set_gpio_lower(lock.value, SCL | lock.direction) .clock_bits_in(BITS_IN, 8); if idx == buffer.len() - 1 { // NMAK mpsse_cmd = mpsse_cmd - .set_gpio_lower(inner.value, SCL | SDA | inner.direction) + .set_gpio_lower(lock.value, SCL | SDA | lock.direction) .clock_bits_out(BITS_OUT, 0x80, 1) } else { // MAK mpsse_cmd = mpsse_cmd - .set_gpio_lower(inner.value, SCL | SDA | inner.direction) + .set_gpio_lower(lock.value, SCL | SDA | lock.direction) .clock_bits_out(BITS_OUT, 0x00, 1) } } // SP for _ in 0..self.start_stop_cmds { - mpsse_cmd = mpsse_cmd.set_gpio_lower(inner.value, SCL | SDA | inner.direction) + mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value, SCL | SDA | lock.direction) } for _ in 0..self.start_stop_cmds { - mpsse_cmd = mpsse_cmd.set_gpio_lower(inner.value | SCL, SCL | SDA | inner.direction) + mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value | SCL, SCL | SDA | lock.direction) } for _ in 0..self.start_stop_cmds { - mpsse_cmd = - mpsse_cmd.set_gpio_lower(inner.value | SCL | SDA, SCL | SDA | inner.direction) + mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value | SCL | SDA, SCL | SDA | lock.direction) } mpsse_cmd = mpsse_cmd // Idle - .set_gpio_lower(inner.value, inner.direction) + .set_gpio_lower(lock.value, lock.direction) .send_immediate(); - inner.ft.send(mpsse_cmd.as_slice())?; + lock.ft.send(mpsse_cmd.as_slice())?; let mut ack_buf: Vec = vec![0; 2 + bytes.len()]; - inner.ft.recv(&mut ack_buf)?; - inner.ft.recv(buffer)?; + lock.ft.recv(&mut ack_buf)?; + lock.ft.recv(buffer)?; if ack_buf.iter().any(|&ack| (ack & 0b1) != 0x00) { Err(Error::Hal(I2cNoAck)) @@ -522,31 +506,29 @@ where // lock at the start to prevent GPIO from being modified while we build // the MPSSE command - let lock = self.mtx.lock().expect("Failed to aquire FTDI mutex"); - let mut inner = lock.borrow_mut(); + let mut lock = self.mtx.lock().expect("Failed to aquire FTDI mutex"); // ST let mut mpsse_cmd: MpsseCmdBuilder = MpsseCmdBuilder::new(); for _ in 0..self.start_stop_cmds { - mpsse_cmd = - mpsse_cmd.set_gpio_lower(inner.value | SCL | SDA, SCL | SDA | inner.direction) + mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value | SCL | SDA, SCL | SDA | lock.direction) } for _ in 0..self.start_stop_cmds { - mpsse_cmd = mpsse_cmd.set_gpio_lower(inner.value | SCL, SCL | SDA | inner.direction) + mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value | SCL, SCL | SDA | lock.direction) } mpsse_cmd = mpsse_cmd // SAD + W - .set_gpio_lower(inner.value, SCL | SDA | inner.direction) + .set_gpio_lower(lock.value, SCL | SDA | lock.direction) .clock_bits_out(BITS_OUT, address << 1, 8) // SAK - .set_gpio_lower(inner.value, SCL | inner.direction) + .set_gpio_lower(lock.value, SCL | lock.direction) .clock_bits_in(BITS_IN, 1) .send_immediate(); - inner.ft.send(mpsse_cmd.as_slice())?; + lock.ft.send(mpsse_cmd.as_slice())?; let mut ack_buf: [u8; 1] = [0; 1]; - inner.ft.recv(&mut ack_buf)?; + lock.ft.recv(&mut ack_buf)?; if (ack_buf[0] & 0b1) != 0x00 { return Err(Error::Hal(I2cNoAck)); } @@ -554,16 +536,16 @@ where for byte in bytes { let mpsse_cmd: MpsseCmdBuilder = MpsseCmdBuilder::new() // Oi - .set_gpio_lower(inner.value, SCL | SDA | inner.direction) + .set_gpio_lower(lock.value, SCL | SDA | lock.direction) .clock_bits_out(BITS_OUT, *byte, 8) // SAK - .set_gpio_lower(inner.value, SCL | inner.direction) + .set_gpio_lower(lock.value, SCL | lock.direction) .clock_bits_in(BITS_IN, 1) .send_immediate(); - inner.ft.send(mpsse_cmd.as_slice())?; + lock.ft.send(mpsse_cmd.as_slice())?; let mut ack_buf: [u8; 1] = [0; 1]; - inner.ft.recv(&mut ack_buf)?; + lock.ft.recv(&mut ack_buf)?; if (ack_buf[0] & 0b1) != 0x00 { return Err(Error::Hal(I2cNoAck)); } @@ -572,27 +554,26 @@ where // SR let mut mpsse_cmd: MpsseCmdBuilder = MpsseCmdBuilder::new(); for _ in 0..self.start_stop_cmds { - mpsse_cmd = - mpsse_cmd.set_gpio_lower(inner.value | SCL | SDA, SCL | SDA | inner.direction) + mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value | SCL | SDA, SCL | SDA | lock.direction) } for _ in 0..self.start_stop_cmds { - mpsse_cmd = mpsse_cmd.set_gpio_lower(inner.value | SCL, SCL | SDA | inner.direction) + mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value | SCL, SCL | SDA | lock.direction) } for _ in 0..self.start_stop_cmds { - mpsse_cmd = mpsse_cmd.set_gpio_lower(inner.value, SCL | SDA | inner.direction) + mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value, SCL | SDA | lock.direction) } mpsse_cmd = mpsse_cmd // SAD + R .clock_bits_out(BITS_OUT, (address << 1) | 1, 8) // SAK - .set_gpio_lower(inner.value, SCL | inner.direction) + .set_gpio_lower(lock.value, SCL | lock.direction) .clock_bits_in(BITS_IN, 1) .send_immediate(); - inner.ft.send(mpsse_cmd.as_slice())?; + lock.ft.send(mpsse_cmd.as_slice())?; let mut ack_buf: [u8; 1] = [0; 1]; - inner.ft.recv(&mut ack_buf)?; + lock.ft.recv(&mut ack_buf)?; if (ack_buf[0] & 0b1) != 0x00 { return Err(Error::Hal(I2cNoAck)); } @@ -600,40 +581,39 @@ where let mut mpsse_cmd: MpsseCmdBuilder = MpsseCmdBuilder::new(); for idx in 0..buffer.len() { mpsse_cmd = mpsse_cmd - .set_gpio_lower(inner.value, SCL | inner.direction) + .set_gpio_lower(lock.value, SCL | lock.direction) .clock_bits_in(BITS_IN, 8); if idx == buffer.len() - 1 { // NMAK mpsse_cmd = mpsse_cmd - .set_gpio_lower(inner.value, SCL | SDA | inner.direction) + .set_gpio_lower(lock.value, SCL | SDA | lock.direction) .clock_bits_out(BITS_OUT, 0x80, 1) } else { // MAK mpsse_cmd = mpsse_cmd - .set_gpio_lower(inner.value, SCL | SDA | inner.direction) + .set_gpio_lower(lock.value, SCL | SDA | lock.direction) .clock_bits_out(BITS_OUT, 0x00, 1) } } // SP for _ in 0..self.start_stop_cmds { - mpsse_cmd = mpsse_cmd.set_gpio_lower(inner.value, SCL | SDA | inner.direction) + mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value, SCL | SDA | lock.direction) } for _ in 0..self.start_stop_cmds { - mpsse_cmd = mpsse_cmd.set_gpio_lower(inner.value | SCL, SCL | SDA | inner.direction) + mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value | SCL, SCL | SDA | lock.direction) } for _ in 0..self.start_stop_cmds { - mpsse_cmd = - mpsse_cmd.set_gpio_lower(inner.value | SCL | SDA, SCL | SDA | inner.direction) + mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value | SCL | SDA, SCL | SDA | lock.direction) } mpsse_cmd = mpsse_cmd // Idle - .set_gpio_lower(inner.value, inner.direction) + .set_gpio_lower(lock.value, lock.direction) .send_immediate(); - inner.ft.send(mpsse_cmd.as_slice())?; - inner.ft.recv(buffer)?; + lock.ft.send(mpsse_cmd.as_slice())?; + lock.ft.recv(buffer)?; Ok(()) } diff --git a/src/lib.rs b/src/lib.rs index d163beb..b34a4e4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -164,7 +164,7 @@ pub use i2c::I2c; pub use spi::Spi; use ftdi_mpsse::{MpsseCmdExecutor, MpsseSettings}; -use std::{cell::RefCell, sync::Mutex}; +use std::sync::{Arc, Mutex}; /// State tracker for each pin on the FTDI chip. #[derive(Debug, Clone, Copy)] @@ -228,7 +228,7 @@ impl From for FtInner { /// FTxxx device. #[derive(Debug)] pub struct FtHal { - mtx: Mutex>>, + mtx: Arc>>, } impl FtHal @@ -333,7 +333,7 @@ where device.init(mpsse_settings)?; Ok(FtHal { - mtx: Mutex::new(RefCell::new(device.into())), + mtx: Arc::new(Mutex::new(device.into())), }) } } diff --git a/src/spi.rs b/src/spi.rs index 022dd99..3e3a552 100644 --- a/src/spi.rs +++ b/src/spi.rs @@ -2,8 +2,7 @@ use crate::error::Error; use crate::{FtInner, PinUse}; use embedded_hal::spi::Polarity; use ftdi_mpsse::{ClockData, ClockDataOut, MpsseCmdBuilder, MpsseCmdExecutor}; -use std::result::Result; -use std::{cell::RefCell, sync::Mutex}; +use std::sync::{Arc, Mutex}; /// FTDI SPI interface. /// @@ -13,7 +12,7 @@ use std::{cell::RefCell, sync::Mutex}; #[derive(Debug)] pub struct Spi<'a, Device: MpsseCmdExecutor> { /// Parent FTDI device. - mtx: &'a Mutex>>, + mtx: &'a Arc>>, /// MPSSE command used to clock data in and out simultaneously. /// /// This is set by [`Spi::set_clock_polarity`]. @@ -30,23 +29,22 @@ where E: std::error::Error, Error: From, { - pub(crate) fn new(mtx: &Mutex>>) -> Result, Error> { - let lock = mtx.lock().expect("Failed to aquire FTDI mutex"); - let mut inner = lock.borrow_mut(); - inner.allocate_pin(0, PinUse::Spi); - inner.allocate_pin(1, PinUse::Spi); - inner.allocate_pin(2, PinUse::Spi); + pub(crate) fn new(mtx: &Arc>>) -> Result, Error> { + let mut lock = mtx.lock().expect("Failed to aquire FTDI mutex"); + lock.allocate_pin(0, PinUse::Spi); + lock.allocate_pin(1, PinUse::Spi); + lock.allocate_pin(2, PinUse::Spi); // clear direction of first 3 pins - inner.direction &= !0x07; + lock.direction &= !0x07; // set SCK (AD0) and MOSI (AD1) as output pins - inner.direction |= 0x03; + lock.direction |= 0x03; // set GPIO pins to new state let cmd: MpsseCmdBuilder = MpsseCmdBuilder::new() - .set_gpio_lower(inner.value, inner.direction) + .set_gpio_lower(lock.value, lock.direction) .send_immediate(); - inner.ft.send(cmd.as_slice())?; + lock.ft.send(cmd.as_slice())?; Ok(Spi { mtx, @@ -101,10 +99,9 @@ where .clock_data_out(self.clk_out, words) .send_immediate(); - let lock = self.mtx.lock().expect("Failed to aquire FTDI mutex"); - let mut inner = lock.borrow_mut(); + let mut lock = self.mtx.lock().expect("Failed to aquire FTDI mutex"); - inner.ft.send(cmd.as_slice())?; + lock.ft.send(cmd.as_slice())?; Ok(()) } @@ -123,10 +120,10 @@ where .clock_data(self.clk, words) .send_immediate(); - let lock = self.mtx.lock().expect("Failed to aquire FTDI mutex"); - let mut inner = lock.borrow_mut(); - inner.ft.send(cmd.as_slice())?; - inner.ft.recv(words)?; + let mut lock = self.mtx.lock().expect("Failed to aquire FTDI mutex"); + + lock.ft.send(cmd.as_slice())?; + lock.ft.recv(words)?; Ok(words) } @@ -146,10 +143,9 @@ where .clock_data(self.clk, &buf) .send_immediate(); - let lock = self.mtx.lock().expect("Failed to aquire FTDI mutex"); - let mut inner = lock.borrow_mut(); + let mut lock = self.mtx.lock().expect("Failed to aquire FTDI mutex"); - match inner.ft.xfer(cmd.as_slice(), &mut buf) { + match lock.ft.xfer(cmd.as_slice(), &mut buf) { Ok(()) => Ok(buf[0]), Err(e) => Err(nb::Error::Other(Error::from(e))), } @@ -160,10 +156,9 @@ where .clock_data_out(self.clk_out, &[byte]) .send_immediate(); - let lock = self.mtx.lock().expect("Failed to aquire FTDI mutex"); - let mut inner = lock.borrow_mut(); + let mut lock = self.mtx.lock().expect("Failed to aquire FTDI mutex"); - match inner.ft.send(cmd.as_slice()) { + match lock.ft.send(cmd.as_slice()) { Ok(()) => Ok(()), Err(e) => Err(nb::Error::Other(Error::from(e))), }