Skip to content

Commit

Permalink
Merge pull request #1062 from tock/optional-cell-nrf52
Browse files Browse the repository at this point in the history
Optional cell nrf52
  • Loading branch information
ppannuto committed Jul 9, 2018
2 parents 6fdad03 + 18d9622 commit 9f76bf6
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 78 deletions.
8 changes: 4 additions & 4 deletions chips/nrf52/src/clock.rs
Expand Up @@ -16,7 +16,7 @@
//! * 32.768 kHz synthesized from HFCLK (LFSYNT)
//!

use core::cell::Cell;
use kernel::common::cells::OptionalCell;
use kernel::common::regs::{ReadOnly, ReadWrite, WriteOnly};
use kernel::common::StaticRef;

Expand Down Expand Up @@ -145,7 +145,7 @@ pub enum HighClockSource {
/// Clock struct
pub struct Clock {
registers: StaticRef<ClockRegisters>,
client: Cell<Option<&'static ClockClient>>,
client: OptionalCell<&'static ClockClient>,
}

pub trait ClockClient {
Expand All @@ -163,13 +163,13 @@ impl Clock {
pub const fn new() -> Clock {
Clock {
registers: CLOCK_BASE,
client: Cell::new(None),
client: OptionalCell::empty(),
}
}

/// Client for callbacks
pub fn set_client(&self, client: &'static ClockClient) {
self.client.set(Some(client));
self.client.set(client);
}

/// Enable interrupt
Expand Down
50 changes: 22 additions & 28 deletions chips/nrf52/src/i2c.rs
Expand Up @@ -7,7 +7,7 @@
//! - Author: Andrew Thompson
//! - Date: Nov 4, 2017

use core::cell::Cell;
use kernel::common::cells::OptionalCell;
use kernel::common::cells::TakeCell;
use kernel::common::cells::VolatileCell;
use kernel::common::regs::{ReadWrite, WriteOnly};
Expand All @@ -29,7 +29,7 @@ const INSTANCES: [StaticRef<TwimRegisters>; 2] = unsafe {
/// additional data necessary to implement an asynchronous interface.
pub struct TWIM {
registers: StaticRef<TwimRegisters>,
client: Cell<Option<&'static hil::i2c::I2CHwMasterClient>>,
client: OptionalCell<&'static hil::i2c::I2CHwMasterClient>,
buf: TakeCell<'static, [u8]>,
}

Expand All @@ -45,14 +45,14 @@ impl TWIM {
const fn new(registers: StaticRef<TwimRegisters>) -> TWIM {
TWIM {
registers: registers,
client: Cell::new(None),
client: OptionalCell::empty(),
buf: TakeCell::empty(),
}
}

pub fn set_client(&self, client: &'static hil::i2c::I2CHwMasterClient) {
debug_assert!(self.client.get().is_none());
self.client.set(Some(client));
debug_assert!(self.client.is_none());
self.client.set(client);
}

/// Configures an already constructed `TWIM`.
Expand Down Expand Up @@ -80,15 +80,12 @@ impl TWIM {
pub fn handle_interrupt(&self) {
if self.registers.events_stopped.is_set(EVENT::EVENT) {
self.registers.events_stopped.write(EVENT::EVENT::CLEAR);
match self.client.get() {
self.client.map(|client| match self.buf.take() {
None => (),
Some(client) => match self.buf.take() {
None => (),
Some(buf) => {
client.command_complete(buf, hil::i2c::Error::CommandComplete);
}
},
};
Some(buf) => {
client.command_complete(buf, hil::i2c::Error::CommandComplete);
}
});
}

if self.registers.events_error.is_set(EVENT::EVENT) {
Expand All @@ -97,22 +94,19 @@ impl TWIM {
self.registers
.errorsrc
.write(ERRORSRC::ANACK::ErrorDidNotOccur + ERRORSRC::DNACK::ErrorDidNotOccur);
match self.client.get() {
self.client.map(|client| match self.buf.take() {
None => (),
Some(client) => match self.buf.take() {
None => (),
Some(buf) => {
let i2c_error = if errorsrc.is_set(ERRORSRC::ANACK) {
hil::i2c::Error::AddressNak
} else if errorsrc.is_set(ERRORSRC::DNACK) {
hil::i2c::Error::DataNak
} else {
hil::i2c::Error::CommandComplete
};
client.command_complete(buf, i2c_error);
}
},
};
Some(buf) => {
let i2c_error = if errorsrc.is_set(ERRORSRC::ANACK) {
hil::i2c::Error::AddressNak
} else if errorsrc.is_set(ERRORSRC::DNACK) {
hil::i2c::Error::DataNak
} else {
hil::i2c::Error::CommandComplete
};
client.command_complete(buf, i2c_error);
}
});
}

// We can blindly clear the following events since we're not using them.
Expand Down
13 changes: 7 additions & 6 deletions chips/nrf52/src/nvmc.rs
Expand Up @@ -4,6 +4,7 @@

use core::cell::Cell;
use core::ops::{Index, IndexMut};
use kernel::common::cells::OptionalCell;
use kernel::common::cells::TakeCell;
use kernel::common::cells::VolatileCell;
use kernel::common::deferred_call::DeferredCall;
Expand Down Expand Up @@ -196,7 +197,7 @@ pub static mut NVMC: Nvmc = Nvmc::new();

pub struct Nvmc {
registers: StaticRef<NvmcRegisters>,
client: Cell<Option<&'static hil::flash::Client<Nvmc>>>,
client: OptionalCell<&'static hil::flash::Client<Nvmc>>,
buffer: TakeCell<'static, NrfPage>,
state: Cell<FlashState>,
}
Expand All @@ -205,7 +206,7 @@ impl Nvmc {
pub const fn new() -> Nvmc {
Nvmc {
registers: NVMC_BASE,
client: Cell::new(None),
client: OptionalCell::empty(),
buffer: TakeCell::empty(),
state: Cell::new(FlashState::Ready),
}
Expand Down Expand Up @@ -242,21 +243,21 @@ impl Nvmc {

match state {
FlashState::Read => {
self.client.get().map(|client| {
self.client.map(|client| {
self.buffer.take().map(|buffer| {
client.read_complete(buffer, hil::flash::Error::CommandComplete);
});
});
}
FlashState::Write => {
self.client.get().map(|client| {
self.client.map(|client| {
self.buffer.take().map(|buffer| {
client.write_complete(buffer, hil::flash::Error::CommandComplete);
});
});
}
FlashState::Erase => {
self.client.get().map(|client| {
self.client.map(|client| {
client.erase_complete(hil::flash::Error::CommandComplete);
});
}
Expand Down Expand Up @@ -351,7 +352,7 @@ impl Nvmc {

impl<C: hil::flash::Client<Self>> hil::flash::HasClient<'static, C> for Nvmc {
fn set_client(&self, client: &'static C) {
self.client.set(Some(client));
self.client.set(client);
}
}

Expand Down
19 changes: 9 additions & 10 deletions chips/nrf52/src/radio.rs
Expand Up @@ -36,6 +36,7 @@
use core::cell::Cell;
use core::convert::TryFrom;
use kernel;
use kernel::common::cells::OptionalCell;
use kernel::common::regs::{ReadOnly, ReadWrite, WriteOnly};
use kernel::common::StaticRef;
use kernel::hil::ble_advertising;
Expand Down Expand Up @@ -532,8 +533,8 @@ static mut PAYLOAD: [u8; nrf5x::constants::RADIO_PAYLOAD_LENGTH] =
pub struct Radio {
registers: StaticRef<RadioRegisters>,
tx_power: Cell<TxPower>,
rx_client: Cell<Option<&'static ble_advertising::RxClient>>,
tx_client: Cell<Option<&'static ble_advertising::TxClient>>,
rx_client: OptionalCell<&'static ble_advertising::RxClient>,
tx_client: OptionalCell<&'static ble_advertising::TxClient>,
}

pub static mut RADIO: Radio = Radio::new();
Expand All @@ -543,8 +544,8 @@ impl Radio {
Radio {
registers: RADIO_BASE,
tx_power: Cell::new(TxPower::ZerodBm),
rx_client: Cell::new(None),
tx_client: Cell::new(None),
rx_client: OptionalCell::empty(),
tx_client: OptionalCell::empty(),
}
}

Expand Down Expand Up @@ -628,17 +629,15 @@ impl Radio {
| nrf5x::constants::RADIO_STATE_TXDISABLE
| nrf5x::constants::RADIO_STATE_TX => {
self.radio_off();
self.tx_client
.get()
.map(|client| client.transmit_event(result));
self.tx_client.map(|client| client.transmit_event(result));
}
nrf5x::constants::RADIO_STATE_RXRU
| nrf5x::constants::RADIO_STATE_RXIDLE
| nrf5x::constants::RADIO_STATE_RXDISABLE
| nrf5x::constants::RADIO_STATE_RX => {
self.radio_off();
unsafe {
self.rx_client.get().map(|client| {
self.rx_client.map(|client| {
// Length is: S0 (1 Byte) + Length (1 Byte) + S1 (0 Bytes) + Payload
// And because the length field is directly read from the packet
// We need to add 2 to length to get the total length
Expand Down Expand Up @@ -814,11 +813,11 @@ impl ble_advertising::BleAdvertisementDriver for Radio {
}

fn set_receive_client(&self, client: &'static ble_advertising::RxClient) {
self.rx_client.set(Some(client));
self.rx_client.set(client);
}

fn set_transmit_client(&self, client: &'static ble_advertising::TxClient) {
self.tx_client.set(Some(client));
self.tx_client.set(client);
}
}

Expand Down
45 changes: 21 additions & 24 deletions chips/nrf52/src/spi.rs
Expand Up @@ -31,7 +31,7 @@

use core::cell::Cell;
use core::{cmp, ptr};
use kernel::common::cells::{TakeCell, VolatileCell};
use kernel::common::cells::{OptionalCell, TakeCell, VolatileCell};
use kernel::common::regs::{ReadWrite, WriteOnly};
use kernel::common::StaticRef;
use kernel::hil;
Expand Down Expand Up @@ -230,8 +230,8 @@ impl From<u32> for Frequency {
/// addition data necessary to implement an asynchronous interface.
pub struct SPIM {
registers: StaticRef<SpimRegisters>,
client: Cell<Option<&'static hil::spi::SpiMasterClient>>,
chip_select: Cell<Option<&'static hil::gpio::Pin>>,
client: OptionalCell<&'static hil::spi::SpiMasterClient>,
chip_select: OptionalCell<&'static hil::gpio::Pin>,
initialized: Cell<bool>,
busy: Cell<bool>,
tx_buf: TakeCell<'static, [u8]>,
Expand All @@ -243,8 +243,8 @@ impl SPIM {
const fn new(instance: usize) -> SPIM {
SPIM {
registers: INSTANCES[instance],
client: Cell::new(None),
chip_select: Cell::new(None),
client: OptionalCell::empty(),
chip_select: OptionalCell::empty(),
initialized: Cell::new(false),
busy: Cell::new(false),
tx_buf: TakeCell::empty(),
Expand All @@ -257,24 +257,21 @@ impl SPIM {
pub fn handle_interrupt(&self) {
if self.registers.events_end.is_set(EVENT::EVENT) {
// End of RXD buffer and TXD buffer reached
match self.chip_select.get() {
Some(cs) => cs.set(),
None => {
debug_assert!(false, "Invariant violated. Chip-select must be Some.");
return;
}

if self.chip_select.is_none() {
debug_assert!(false, "Invariant violated. Chip-select must be Some.");
return;
}

self.chip_select.map(|cs| cs.set());
self.registers.events_end.write(EVENT::EVENT::CLEAR);

match self.client.get() {
self.client.map(|client| match self.tx_buf.take() {
None => (),
Some(client) => match self.tx_buf.take() {
None => (),
Some(tx_buf) => {
client.read_write_done(tx_buf, self.rx_buf.take(), self.transfer_len.take())
}
},
};
Some(tx_buf) => {
client.read_write_done(tx_buf, self.rx_buf.take(), self.transfer_len.take())
}
});

self.busy.set(false);
}
Expand Down Expand Up @@ -331,7 +328,7 @@ impl hil::spi::SpiMaster for SPIM {
type ChipSelect = &'static hil::gpio::Pin;

fn set_client(&self, client: &'static hil::spi::SpiMasterClient) {
self.client.set(Some(client));
self.client.set(client);
}

fn init(&self) {
Expand All @@ -355,10 +352,10 @@ impl hil::spi::SpiMaster for SPIM {
debug_assert!(self.rx_buf.is_none());

// Clear (set to low) chip-select
match self.chip_select.get() {
Some(cs) => cs.clear(),
None => return ReturnCode::ENODEVICE,
if self.chip_select.is_none() {
return ReturnCode::ENODEVICE;
}
self.chip_select.map(|cs| cs.clear());

// Setup transmit data registers
let tx_len: u32 = cmp::min(len, tx_buf.len()) as u32;
Expand Down Expand Up @@ -410,7 +407,7 @@ impl hil::spi::SpiMaster for SPIM {
fn specify_chip_select(&self, cs: Self::ChipSelect) {
cs.make_output();
cs.set();
self.chip_select.set(Some(cs));
self.chip_select.set(cs);
}

// Returns the actual rate set
Expand Down

0 comments on commit 9f76bf6

Please sign in to comment.