Skip to content

Commit

Permalink
Finish changes to GPIO HIL
Browse files Browse the repository at this point in the history
Separate out Pin and PinCtl

Port boards, chips and capsules to new interface
  • Loading branch information
alevy committed Oct 6, 2016
1 parent f16beac commit 38d5fbb
Show file tree
Hide file tree
Showing 8 changed files with 86 additions and 76 deletions.
10 changes: 5 additions & 5 deletions boards/nrf51dk/src/main.rs
Expand Up @@ -46,7 +46,7 @@ extern crate nrf51;
use capsules::timer::TimerDriver;
use capsules::virtual_alarm::{MuxAlarm, VirtualMuxAlarm};
use kernel::{Chip, SysTick};
use kernel::hil::gpio::GPIOPin;
use kernel::hil::gpio::Pin;
use nrf51::timer::ALARM1;
use nrf51::timer::TimerAlarm;

Expand Down Expand Up @@ -140,7 +140,7 @@ pub unsafe fn reset_handler() {
],
4 * 22);

nrf51::gpio::PORT[LED1_PIN].enable_output();
nrf51::gpio::PORT[LED1_PIN].make_output();
nrf51::gpio::PORT[LED1_PIN].clear();

let gpio = static_init!(
Expand Down Expand Up @@ -218,13 +218,13 @@ pub unsafe extern "C" fn rust_begin_unwind(_args: &Arguments,
_file: &'static str,
_line: usize)
-> ! {
use kernel::hil::gpio::GPIOPin;
use kernel::hil::gpio::Pin;

let led0 = &nrf51::gpio::PORT[LED1_PIN];
let led1 = &nrf51::gpio::PORT[LED2_PIN];

led0.enable_output();
led1.enable_output();
led0.make_output();
led1.make_output();
loop {
for _ in 0..100000 {
led0.set();
Expand Down
23 changes: 12 additions & 11 deletions capsules/src/gpio.rs
@@ -1,13 +1,13 @@
use core::cell::Cell;
use kernel::{AppId, Callback, Driver};
use kernel::hil::gpio::{GPIOPin, InputMode, InterruptMode, Client};
use kernel::hil::gpio::{Pin, PinCtl, InputMode, InterruptMode, Client};

pub struct GPIO<'a, G: GPIOPin + 'a> {
pub struct GPIO<'a, G: Pin + 'a> {
pins: &'a [&'a G],
callback: Cell<Option<Callback>>,
}

impl<'a, G: GPIOPin> GPIO<'a, G> {
impl<'a, G: Pin + PinCtl> GPIO<'a, G> {
pub fn new(pins: &'a [&'a G]) -> GPIO<'a, G> {
GPIO {
pins: pins,
Expand All @@ -16,20 +16,21 @@ impl<'a, G: GPIOPin> GPIO<'a, G> {
}

fn configure_input_pin(&self, pin_num: usize, config: usize) -> isize {
let pins = self.pins.as_ref();
let pin = self.pins[pin_num];
pin.make_input();
match config {
0 => {
pins[pin_num].enable_input(InputMode::PullUp);
pin.set_input_mode(InputMode::PullUp);
0
}

1 => {
pins[pin_num].enable_input(InputMode::PullDown);
pin.set_input_mode(InputMode::PullDown);
0
}

2 => {
pins[pin_num].enable_input(InputMode::PullNone);
pin.set_input_mode(InputMode::PullNone);
0
}

Expand All @@ -41,7 +42,7 @@ impl<'a, G: GPIOPin> GPIO<'a, G> {
let pins = self.pins.as_ref();
match config {
0 => {
pins[pin_num].enable_interrupt(pin_num, InterruptMode::Change);
pins[pin_num].enable_interrupt(pin_num, InterruptMode::EitherEdge);
0
}

Expand All @@ -60,7 +61,7 @@ impl<'a, G: GPIOPin> GPIO<'a, G> {
}
}

impl<'a, G: GPIOPin> Client for GPIO<'a, G> {
impl<'a, G: Pin> Client for GPIO<'a, G> {
fn fired(&self, pin_num: usize) {
// read the value of the pin
let pins = self.pins.as_ref();
Expand All @@ -73,7 +74,7 @@ impl<'a, G: GPIOPin> Client for GPIO<'a, G> {
}
}

impl<'a, G: GPIOPin> Driver for GPIO<'a, G> {
impl<'a, G: Pin + PinCtl> Driver for GPIO<'a, G> {
fn subscribe(&self, subscribe_num: usize, callback: Callback) -> isize {
match subscribe_num {
// subscribe to all pin interrupts
Expand All @@ -96,7 +97,7 @@ impl<'a, G: GPIOPin> Driver for GPIO<'a, G> {
if data >= pins.len() {
-1
} else {
pins[data].enable_output();
pins[data].make_output();
0
}
}
Expand Down
9 changes: 5 additions & 4 deletions capsules/src/tmp006.rs
Expand Up @@ -2,7 +2,7 @@ use core::cell::Cell;
use kernel::{AppId, Callback, Driver};
use kernel::common::math::{sqrtf32, get_errno};
use kernel::common::take_cell::TakeCell;
use kernel::hil::gpio::{GPIOPin, InputMode, InterruptMode, Client};
use kernel::hil::gpio::{Pin, InterruptMode, Client};
use kernel::hil::i2c;

pub static mut BUFFER: [u8; 3] = [0; 3];
Expand Down Expand Up @@ -87,7 +87,7 @@ enum ProtocolState {

pub struct TMP006<'a> {
i2c: &'a i2c::I2CDevice,
interrupt_pin: &'a GPIOPin,
interrupt_pin: &'a Pin,
sampling_period: Cell<u8>,
repeated_mode: Cell<bool>,
callback: Cell<Option<Callback>>,
Expand All @@ -97,7 +97,7 @@ pub struct TMP006<'a> {

impl<'a> TMP006<'a> {
pub fn new(i2c: &'a i2c::I2CDevice,
interrupt_pin: &'a GPIOPin,
interrupt_pin: &'a Pin,
buffer: &'static mut [u8])
-> TMP006<'a> {
// setup and return struct
Expand Down Expand Up @@ -144,7 +144,8 @@ impl<'a> TMP006<'a> {

fn enable_interrupts(&self) {
// setup interrupts from the sensor
self.interrupt_pin.enable_input(InputMode::PullUp);
// TODO(alevy): do we need to make sure it's a pull up?
self.interrupt_pin.make_input();
self.interrupt_pin.enable_interrupt(0, InterruptMode::FallingEdge);
}

Expand Down
4 changes: 2 additions & 2 deletions capsules/src/virtual_spi.rs
Expand Up @@ -94,7 +94,7 @@ enum Op {
pub struct SPIMasterDevice<'a> {
mux: &'a MuxSPIMaster<'a>,
chip_select: Option<u8>,
chip_select_gpio: Option<&'static hil::gpio::GPIOPin>,
chip_select_gpio: Option<&'static hil::gpio::Pin>,
txbuffer: TakeCell<&'static mut [u8]>,
rxbuffer: TakeCell<Option<&'static mut [u8]>>,
operation: Cell<Op>,
Expand All @@ -105,7 +105,7 @@ pub struct SPIMasterDevice<'a> {
impl<'a> SPIMasterDevice<'a> {
pub const fn new(mux: &'a MuxSPIMaster<'a>,
chip_select: Option<u8>,
chip_select_gpio: Option<&'static hil::gpio::GPIOPin>)
chip_select_gpio: Option<&'static hil::gpio::Pin>)
-> SPIMasterDevice<'a> {
SPIMasterDevice {
mux: mux,
Expand Down
40 changes: 19 additions & 21 deletions chips/nrf51/src/gpio.rs
Expand Up @@ -108,34 +108,32 @@ impl GPIOPin {
}
}

impl hil::gpio::GPIOPin for GPIOPin {
fn enable_output(&self) {
// bit 0: set as output
// bit 1: disconnect input buffer (1 is disconnect)
// bit 2-3: no pullup/down
// bit 8-10: drive configruation
// bit 16-17: sensing
GPIO().pin_cnf[self.pin as usize].set((1 << 0) | // set as output
(1 << 1) | // no input buf
(0 << 2) | // no pull
(0 << 8) | // no drive
(0 << 16)); // no sensing
impl hil::gpio::PinCtl for GPIOPin {
fn set_input_mode(&self, mode: hil::gpio::InputMode) {
let conf = match mode {
hil::gpio::InputMode::PullUp => 0x3,
hil::gpio::InputMode::PullDown => 0x1,
hil::gpio::InputMode::PullNone => 0,
};
let pin_cnf = GPIO().pin_cnf[self.pin as usize];
pin_cnf.set((pin_cnf.get() & !(0b11 << 2)) | (conf << 2));
}
}

impl hil::gpio::Pin for GPIOPin {
fn make_output(&self) {
GPIO().dirset.set(1 << self.pin);
}

// Configuration constants stolen from
// mynewt/hw/mcu/nordic/nrf51xxx/include/mcu/nrf51_bitfields.h
fn enable_input(&self, mode: hil::gpio::InputMode) {
let conf = match mode {
hil::gpio::InputMode::PullUp => 0x3 << 2,
hil::gpio::InputMode::PullDown => 0x1 << 2,
hil::gpio::InputMode::PullNone => 0,
};
GPIO().pin_cnf[self.pin as usize].set(conf);
fn make_input(&self) {
GPIO().dirclr.set(1 << self.pin);
}

// Not clk
fn disable(&self) {
self.enable_input(hil::gpio::InputMode::PullNone);
hil::gpio::PinCtl::set_input_mode(self, hil::gpio::InputMode::PullNone);
}

fn set(&self) {
Expand All @@ -158,7 +156,7 @@ impl hil::gpio::GPIOPin for GPIOPin {
self.client_data.set(_client_data);
let mut mode_bits: u32 = 1; // Event
mode_bits |= match _mode {
hil::gpio::InterruptMode::Change => 3 << 16,
hil::gpio::InterruptMode::EitherEdge => 3 << 16,
hil::gpio::InterruptMode::RisingEdge => 1 << 16,
hil::gpio::InterruptMode::FallingEdge => 2 << 16,
};
Expand Down
37 changes: 21 additions & 16 deletions chips/sam4l/src/gpio.rs
Expand Up @@ -459,21 +459,8 @@ impl hil::Controller for GPIOPin {
}
}

impl hil::gpio::GPIOPin for GPIOPin {
fn disable(&self) {
GPIOPin::disable(self);
}

fn enable_output(&self) {
self.enable();
GPIOPin::enable_output(self);
self.disable_schmidtt_trigger();
}

fn enable_input(&self, mode: hil::gpio::InputMode) {
self.enable();
GPIOPin::disable_output(self);
self.enable_schmidtt_trigger();
impl hil::gpio::PinCtl for GPIOPin {
fn set_input_mode(&self, mode: hil::gpio::InputMode) {
match mode {
hil::gpio::InputMode::PullUp => {
self.disable_pull_down();
Expand All @@ -489,6 +476,24 @@ impl hil::gpio::GPIOPin for GPIOPin {
}
}
}
}

impl hil::gpio::Pin for GPIOPin {
fn disable(&self) {
GPIOPin::disable(self);
}

fn make_output(&self) {
self.enable();
GPIOPin::enable_output(self);
self.disable_schmidtt_trigger();
}

fn make_input(&self) {
self.enable();
GPIOPin::disable_output(self);
self.enable_schmidtt_trigger();
}

fn read(&self) -> bool {
GPIOPin::read(self)
Expand All @@ -508,7 +513,7 @@ impl hil::gpio::GPIOPin for GPIOPin {

fn enable_interrupt(&self, client_data: usize, mode: hil::gpio::InterruptMode) {
let mode_bits = match mode {
hil::gpio::InterruptMode::Change => 0b00,
hil::gpio::InterruptMode::EitherEdge => 0b00,
hil::gpio::InterruptMode::RisingEdge => 0b01,
hil::gpio::InterruptMode::FallingEdge => 0b10,
};
Expand Down
27 changes: 16 additions & 11 deletions kernel/src/hil/gpio.rs
Expand Up @@ -14,37 +14,42 @@ pub enum InterruptMode {
EitherEdge,
}

pub trait PinCtl {
/// Configure whether the pin should have a pull-up or pull-down resistor or
/// neither.
fn set_input_mode(&self, InputMode);
}

/// Interface for synchronous GPIO pins.
pub trait Pin {
/// Configure the GPIO pin as an output pin.
fn make_output(&self);

/// Configure the GPIO pin as an input pin. Also configure
/// if it should have a pull-up, pull-down, or neither.
fn make_input(&self, mode: InputMode);


/// Configure the GPIO pin as an input pin.
fn make_input(&self);

/// Disable the GPIO pin and put it into its lowest power
/// mode.
fn disable(&self);

/// Set the GPIO pin high. It must be an output.
fn set(&self);

/// Set the GPIO pin low. It must be an output.
fn clear(&self);

/// Toggle the GPIO pin. It must be an output.
fn toggle(&self);

/// Get the current state of an input GPIO pin.
fn read(&self) -> bool;

/// Enable an interrupt on the GPIO pin. It must
/// be configured as an interrupt. The `identifier`
/// can be any value and will be returned to you
/// when the interrupt on this pin fires.
fn enable_interrupt(&self, identifier: usize, mode: InterruptMode);

/// Disable the interrupt for the GPIO pin.
fn disable_interrupt(&self);
}
Expand Down
12 changes: 6 additions & 6 deletions kernel/src/hil/led.rs
Expand Up @@ -16,29 +16,29 @@ pub trait Led {

/// For LEDs in which on is when GPIO is high.
pub struct LedHigh {
pub pin: &'static mut gpio::GPIOPin,
pub pin: &'static mut gpio::Pin,
}

/// For LEDs in which on is when GPIO is low.
pub struct LedLow {
pub pin: &'static mut gpio::GPIOPin,
pub pin: &'static mut gpio::Pin,
}

impl LedHigh {
pub fn new(p: &'static mut gpio::GPIOPin) -> LedHigh {
pub fn new(p: &'static mut gpio::Pin) -> LedHigh {
LedHigh { pin: p }
}
}

impl LedLow {
pub fn new(p: &'static mut gpio::GPIOPin) -> LedLow {
pub fn new(p: &'static mut gpio::Pin) -> LedLow {
LedLow { pin: p }
}
}

impl Led for LedHigh {
fn init(&mut self) {
self.pin.enable_output();
self.pin.make_output();
}

fn on(&mut self) {
Expand All @@ -60,7 +60,7 @@ impl Led for LedHigh {

impl Led for LedLow {
fn init(&mut self) {
self.pin.enable_output();
self.pin.make_output();
}

fn on(&mut self) {
Expand Down

0 comments on commit 38d5fbb

Please sign in to comment.