Skip to content

Commit

Permalink
welllll, it works...
Browse files Browse the repository at this point in the history
  • Loading branch information
hawkw committed Jul 21, 2023
1 parent 813b565 commit 1004efc
Show file tree
Hide file tree
Showing 9 changed files with 354 additions and 167 deletions.
44 changes: 22 additions & 22 deletions platforms/allwinner-d1/boards/src/bin/lichee-rv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,13 @@ fn main() -> ! {
}

let mut p = unsafe { d1_pac::Peripherals::steal() };
let uart = unsafe { kernel_uart(&mut p.CCU, &mut p.GPIO, p.UART0) };
let spim = unsafe { kernel_spim1(p.SPI_DBI, &mut p.CCU, &mut p.GPIO) };
let i2c0 = unsafe { twi::I2c0::lichee_rv_dock(p.TWI2, &mut p.CCU, &mut p.GPIO) };
let uart = unsafe { kernel_uart(&mut p.CCU, p.UART0) };
let spim = unsafe { kernel_spim1(p.SPI_DBI, &mut p.CCU) };
let i2c0 = unsafe { twi::I2c0::lichee_rv_dock(p.TWI2, &mut p.CCU) };
let timers = Timers::new(p.TIMER);
let dmac = Dmac::new(p.DMAC, &mut p.CCU);
let plic = Plic::new(p.PLIC);

let d1 = D1::initialize(timers, uart, spim, dmac, plic, i2c0).unwrap();

p.GPIO.pc_cfg0.modify(|_r, w| {
w.pc1_select().output();
w
Expand All @@ -44,25 +42,27 @@ fn main() -> ! {
w
});

let d1 = D1::initialize(timers, uart, spim, dmac, plic, i2c0, p.GPIO).unwrap();

d1.initialize_sharp_display();

// Initialize LED loop
d1.kernel
.initialize(async move {
loop {
p.GPIO.pc_dat.modify(|_r, w| {
w.pc_dat().variant(0b0000_0010);
w
});
d1.kernel.sleep(Duration::from_millis(250)).await;
p.GPIO.pc_dat.modify(|_r, w| {
w.pc_dat().variant(0b0000_0000);
w
});
d1.kernel.sleep(Duration::from_millis(250)).await;
}
})
.unwrap();
// // Initialize LED loop
// d1.kernel
// .initialize(async move {
// loop {
// p.GPIO.pc_dat.modify(|_r, w| {
// w.pc_dat().variant(0b0000_0010);
// w
// });
// d1.kernel.sleep(Duration::from_millis(250)).await;
// p.GPIO.pc_dat.modify(|_r, w| {
// w.pc_dat().variant(0b0000_0000);
// w
// });
// d1.kernel.sleep(Duration::from_millis(250)).await;
// }
// })
// .unwrap();

d1.run()
}
44 changes: 22 additions & 22 deletions platforms/allwinner-d1/boards/src/bin/mq-pro.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,13 @@ fn main() -> ! {
}

let mut p = unsafe { d1_pac::Peripherals::steal() };
let uart = unsafe { kernel_uart(&mut p.CCU, &mut p.GPIO, p.UART0) };
let spim = unsafe { kernel_spim1(p.SPI_DBI, &mut p.CCU, &mut p.GPIO) };
let i2c0 = unsafe { twi::I2c0::mq_pro(p.TWI0, &mut p.CCU, &mut p.GPIO) };
let uart = unsafe { kernel_uart(&mut p.CCU, p.UART0) };
let spim = unsafe { kernel_spim1(p.SPI_DBI, &mut p.CCU) };
let i2c0 = unsafe { twi::I2c0::mq_pro(p.TWI0, &mut p.CCU) };
let timers = Timers::new(p.TIMER);
let dmac = Dmac::new(p.DMAC, &mut p.CCU);
let plic = Plic::new(p.PLIC);

let d1 = D1::initialize(timers, uart, spim, dmac, plic, i2c0).unwrap();

p.GPIO.pd_cfg2.modify(|_r, w| {
w.pd18_select().output();
w
Expand All @@ -45,23 +43,25 @@ fn main() -> ! {
w
});

// Initialize LED loop
d1.kernel
.initialize(async move {
loop {
p.GPIO.pd_dat.modify(|_r, w| {
w.pd_dat().variant(1 << 18);
w
});
d1.kernel.sleep(Duration::from_millis(250)).await;
p.GPIO.pd_dat.modify(|_r, w| {
w.pd_dat().variant(0);
w
});
d1.kernel.sleep(Duration::from_millis(250)).await;
}
})
.unwrap();
let d1 = D1::initialize(timers, uart, spim, dmac, plic, i2c0, p.GPIO).unwrap();

// // Initialize LED loop
// d1.kernel
// .initialize(async move {
// loop {
// p.GPIO.pd_dat.modify(|_r, w| {
// w.pd_dat().variant(1 << 18);
// w
// });
// d1.kernel.sleep(Duration::from_millis(250)).await;
// p.GPIO.pd_dat.modify(|_r, w| {
// w.pd_dat().variant(0);
// w
// });
// d1.kernel.sleep(Duration::from_millis(250)).await;
// }
// })
// .unwrap();

d1.initialize_sharp_display();

Expand Down
149 changes: 111 additions & 38 deletions platforms/allwinner-d1/core/src/drivers/gpio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use kernel::{
},
isr::Isr,
maitake::sync::WaitQueue,
mnemos_alloc::containers::FixedVec,
registry::{self, uuid, Envelope, KernelHandle, RegisteredDriver, Uuid},
trace, Kernel,
};
Expand All @@ -33,19 +34,21 @@ pub enum Request {
mode: InterruptMode,
},
RegisterCustom {
pin: Pin,
name: &'static str,
pins: FixedVec<(Pin, &'static str)>,
register: fn(&gpio::RegisterBlock),
},
PinState(Pin),
}

#[derive(Debug)]
pub enum Response {
RegisterIrq(&'static WaitQueue),
RegisterCustom,
PinState(Pin, PinState),
// actually do IO...
}

#[derive(Debug)]
pub enum Error {
PinInUse(Pin, PinState),
}
Expand Down Expand Up @@ -206,6 +209,27 @@ pub enum PinState {
Other(&'static str),
}

macro_rules! impl_from_pins {
($($P:ty => $pin:ident),+ $(,)?) => {
$(
impl From<$P> for Pin {
fn from(p: $P) -> Self {
Self::$pin(p)
}
}
)+
}
}

impl_from_pins! {
PinB => B,
PinC => C,
PinD => D,
PinE => E,
PinF => F,
PinG => G,
}

////////////////////////////////////////////////////////////////////////////////
// Client Definition
////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -246,6 +270,32 @@ impl GpioClient {
reply: Reusable::new_async().await,
})
}

/// Configure a pin with a custom configuration.
///
/// # Warnings
///
/// The provided function must only modify the pin configuration for `pin`.
/// There is currently no way to enforce this.
pub async fn register_custom(
&mut self,
pins: impl Into<FixedVec<(Pin, &'static str)>>,
register: fn(&gpio::RegisterBlock),
) -> Result<(), Error> {
let pins = pins.into();
let resp = self
.handle
.request_oneshot(Request::RegisterCustom { pins, register }, &self.reply)
.await
.unwrap();
match resp.body {
Ok(Response::RegisterCustom) => Ok(()),
Ok(resp) => unreachable!(
"expected the GpioService to respond with RegisterCustom, got {resp:?}"
),
Err(e) => Err(e),
}
}
}

////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -287,59 +337,82 @@ impl GpioServer {
#[trace::instrument(level = trace::Level::INFO, name = "GpioServer", skip(self, gpio))]
async fn run(mut self, gpio: GPIO) {
while let Ok(registry::Message { msg, reply }) = self.rx.dequeue_async().await {
let rsp = match msg.body {
Request::RegisterIrq { pin, mode } => {
tracing::debug!(?pin, ?mode, "registering GPIO interrupt...");
let (state, irq) = self.pin(pin);
match *state {
PinState::Unregistered => {
*state = PinState::Interrupt(mode);
// TODO(eliza): configure the interrupt mode!
let rsp = msg.reply_with_body(|body| self.handle_msg(&gpio, body));
if let Err(error) = reply.reply_konly(rsp).await {
tracing::warn!(?error, "requester cancelled request!")
// TODO(eliza): we should probably undo any pin state changes here...
}
}
}

tracing::info!(?pin, ?mode, "GPIO interrupt registered!");
Ok(Response::RegisterIrq(irq))
}
PinState::Interrupt(cur_mode) if cur_mode == mode => {
tracing::info!(?pin, ?mode, "GPIO interrupt subscribed.");
Ok(Response::RegisterIrq(irq))
}
state => {
fn handle_msg(&mut self, gpio: &GPIO, msg: Request) -> Result<Response, Error> {
match msg {
Request::RegisterIrq { pin, mode } => {
tracing::debug!(?pin, ?mode, "registering GPIO interrupt...");
let (state, irq) = self.pin(pin);
match *state {
PinState::Unregistered => {
*state = PinState::Interrupt(mode);
// TODO(eliza): configure the interrupt mode!

tracing::info!(?pin, ?mode, "GPIO interrupt registered!");
Ok(Response::RegisterIrq(irq))
}
PinState::Interrupt(cur_mode) if cur_mode == mode => {
tracing::info!(?pin, ?mode, "GPIO interrupt subscribed.");
Ok(Response::RegisterIrq(irq))
}
state => {
tracing::warn!(
?pin,
?state,
?mode,
"can't register GPIO interrupt, pin already in use!"
);
// TODO(eliza): add a way for a requester to wait
// for a pin to become available?
Err(Error::PinInUse(pin, state))
}
}
}
Request::RegisterCustom { pins, register } => {
// first, try to claim all the requested pins --- don't do
// the register block manipulation if we can't claim any of
// the requested pins.
for &(pin, name) in pins.as_slice() {
match self.pin(pin) {
(PinState::Unregistered, _) => {}
(&mut PinState::Other(other_name), _) if other_name == name => {}
(&mut state, _) => {
tracing::warn!(
?pin,
?state,
?mode,
"can't register GPIO interrupt, pin already in use!"
"can't claim pin for {name}, already in use!"
);
// TODO(eliza): add a way for a requester to wait
// for a pin to become available?
Err(Error::PinInUse(pin, state))
return Err(Error::PinInUse(pin, state));
}
}
}
Request::RegisterCustom {
pin,
name,
register,
} => {
// now that we've confirmed that all pins are claimable,
// actually perform the registration and set the pin states.
register(gpio);
for &(pin, name) in pins.as_slice() {
let (state, _) = self.pin(pin);
match *state {
PinState::Unregistered => {
register(&gpio);
tracing::info!(?pin, state = %name, "claimed pin");
*state = PinState::Other(name);
Ok(Response::RegisterCustom)
}
PinState::Other(cur_mode) if cur_mode == name => {
Ok(Response::RegisterCustom)
PinState::Other(_) => {}
state => {
unreachable!("we just checked the pin's state, and it was claimable!")
}
state => Err(Error::PinInUse(pin, state)),
}
}
Request::PinState(pin) => Ok(Response::PinState(pin, *self.pin(pin).0)),
};
if let Err(error) = reply.reply_konly(msg.reply_with(rsp)).await {
tracing::warn!(?error, "requester cancelled request!")
// TODO(eliza): we should probably undo any pin state changes here...

Ok(Response::RegisterCustom)
}
Request::PinState(pin) => Ok(Response::PinState(pin, *self.pin(pin).0)),
}
}

Expand Down
2 changes: 1 addition & 1 deletion platforms/allwinner-d1/core/src/drivers/sharp_display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ impl SharpDisplay {
let draw = Draw {
kernel,
buf: linebuf,
spim: SpiSenderClient::from_registry(kernel).await.unwrap(),
spim: SpiSenderClient::from_registry(kernel).await,
ctxt,
};

Expand Down
Loading

0 comments on commit 1004efc

Please sign in to comment.