Skip to content

Commit

Permalink
pic32-hal v0.12.0 - add support for embedded-hal-1.0 (#18)
Browse files Browse the repository at this point in the history
  • Loading branch information
kiffie authored Oct 19, 2024
1 parent f31d712 commit 9b17484
Show file tree
Hide file tree
Showing 8 changed files with 446 additions and 119 deletions.
5 changes: 3 additions & 2 deletions pic32-hal/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "pic32-hal"
version = "0.11.0"
version = "0.12.0"
authors = ["Stephan <kiffie@mailbox.org>"]
edition = "2021"
description = "Hardware Abstraction Layer (HAL) for PIC32 microcontrollers"
Expand All @@ -20,7 +20,8 @@ device-selected = []

[dependencies]
nb = "1.0.0"
embedded-hal = { version = "0.2.7", features = ["unproven"] }
embedded-hal = "1.0.0"
embedded_hal_0_2 = { package = "embedded-hal", version = "0.2.7", features = ["unproven"] }
mips-mcu = "0.3.0"
mips-rt = "0.3.0"
critical-section = "1.0.0"
Expand Down
33 changes: 26 additions & 7 deletions pic32-hal/src/coretimer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,52 +3,62 @@
//!
//! Uses the MIPS CP0 registers "count" and "compare".
use crate::hal::blocking::delay::{DelayMs, DelayUs};
use crate::pac::INT; // interrupt controller
use crate::time::Hertz;
use embedded_hal::delay::DelayNs;
use embedded_hal_0_2::blocking::delay::{DelayMs, DelayUs};

use critical_section::Mutex;
pub use mips_mcu::core_timer::read_count;
use mips_mcu::core_timer::{read_compare, write_compare};

use core::cell::Cell;

const fn rounded_div_u32(a: u32, b: u32) -> u32 {
(a + b / 2) / b
}

/// Delay implementation based on read-only access to the core timer "count"
/// register
pub struct Delay {
ticks_per_us: u32,
nanos_per_tick: u32,
}

impl Delay {
pub const fn new(sysclock: Hertz) -> Self {
let ticks_per_us = sysclock.0 / 1_000_000 / 2;
Delay { ticks_per_us }
let nanos_per_tick = rounded_div_u32(2 * 1_000_000_000, sysclock.0);
Delay {
ticks_per_us,
nanos_per_tick,
}
}
}

impl DelayMs<u32> for Delay {
fn delay_ms(&mut self, ms: u32) {
self.delay_us(ms * 1_000);
DelayUs::delay_us(self, ms * 1_000);
}
}

impl DelayMs<i32> for Delay {
fn delay_ms(&mut self, ms: i32) {
if ms >= 0 {
self.delay_us((ms as u32) * 1000);
DelayUs::delay_us(self, (ms as u32) * 1000);
}
}
}

impl DelayMs<u16> for Delay {
fn delay_ms(&mut self, ms: u16) {
self.delay_ms(ms as u32);
DelayMs::delay_ms(self, ms as u32);
}
}

impl DelayMs<u8> for Delay {
fn delay_ms(&mut self, ms: u8) {
self.delay_ms(ms as u32);
DelayMs::delay_ms(self, ms as u32);
}
}

Expand Down Expand Up @@ -84,7 +94,16 @@ impl DelayUs<u16> for Delay {

impl DelayUs<u8> for Delay {
fn delay_us(&mut self, us: u8) {
self.delay_us(us as u16)
DelayUs::delay_us(self, us as u16)
}
}

impl DelayNs for Delay {
fn delay_ns(&mut self, ns: u32) {
// read the count first for most accurate timing
let start = read_count();
let ticks = ns / self.nanos_per_tick;
while read_count().wrapping_sub(start) < ticks {}
}
}

Expand Down
75 changes: 66 additions & 9 deletions pic32-hal/src/gpio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,10 @@ macro_rules! port {
/// GPIO
pub mod $portx {
use core::marker::PhantomData;
use core::convert::Infallible;

use crate::hal::digital::v2::*;
use embedded_hal_0_2::digital::v2 as eh02;
use embedded_hal::digital as eh;
use crate::pac::$PORTX;

#[allow(unused_imports)]
Expand Down Expand Up @@ -192,7 +194,7 @@ macro_rules! port {
}
}

impl<MODE> OutputPin for $PXi<Output<MODE>> {
impl<MODE> eh02::OutputPin for $PXi<Output<MODE>> {

type Error = ();

Expand All @@ -209,18 +211,18 @@ macro_rules! port {
}
}

impl<MODE> StatefulOutputPin for $PXi<Output<MODE>> {
impl<MODE> eh02::StatefulOutputPin for $PXi<Output<MODE>> {

fn is_set_high(&self) -> Result<bool, Self::Error> {
Ok(unsafe { (*$PORTX::ptr()).lat.read().bits() & (1 << $i) != 0 })
}

fn is_set_low(&self) -> Result<bool, Self::Error> {
self.is_set_high().map(|b| !b)
Ok(unsafe { (*$PORTX::ptr()).lat.read().bits() & (1 << $i) == 0 })
}
}

impl<MODE> ToggleableOutputPin for $PXi<Output<MODE>> {
impl<MODE> eh02::ToggleableOutputPin for $PXi<Output<MODE>> {

type Error = ();

Expand All @@ -230,7 +232,7 @@ macro_rules! port {
}
}

impl<MODE> InputPin for $PXi<Input<MODE>> {
impl<MODE> eh02::InputPin for $PXi<Input<MODE>> {

type Error = ();

Expand All @@ -239,11 +241,11 @@ macro_rules! port {
}

fn is_low(&self) -> Result<bool, Self::Error> {
self.is_high().map(|b| !b)
Ok(unsafe { (*$PORTX::ptr()).port.read().bits() & (1 << $i) == 0 })
}
}

impl InputPin for $PXi<Output<OpenDrain>> {
impl eh02::InputPin for $PXi<Output<OpenDrain>> {

type Error = ();

Expand All @@ -252,7 +254,62 @@ macro_rules! port {
}

fn is_low(&self) -> Result<bool, Self::Error> {
self.is_high().map(|b| !b)
Ok(unsafe { (*$PORTX::ptr()).port.read().bits() & (1 << $i) == 0 })
}
}

impl<MODE> eh::ErrorType for $PXi<MODE> {
type Error = Infallible;
}

impl<MODE> eh::InputPin for $PXi<Input<MODE>> {

fn is_high(&mut self) -> Result<bool, Self::Error> {
Ok(unsafe { (*$PORTX::ptr()).lat.read().bits() & (1 << $i) != 0 })
}

fn is_low(&mut self) -> Result<bool, Self::Error> {
Ok(unsafe { (*$PORTX::ptr()).lat.read().bits() & (1 << $i) == 0 })
}
}

impl eh::InputPin for $PXi<Output<OpenDrain>> {

fn is_high(&mut self) -> Result<bool, Self::Error> {
Ok(unsafe { (*$PORTX::ptr()).lat.read().bits() & (1 << $i) != 0 })
}

fn is_low(&mut self) -> Result<bool, Self::Error> {
Ok(unsafe { (*$PORTX::ptr()).lat.read().bits() & (1 << $i) == 0 })
}
}

impl<MODE> eh::OutputPin for $PXi<Output<MODE>> {

fn set_low(&mut self) -> Result<(), Self::Error> {
unsafe { (*$PORTX::ptr()).latclr.write(|w| w.bits(1 << $i)) }
Ok(())
}

fn set_high(&mut self) -> Result<(), Self::Error> {
unsafe { (*$PORTX::ptr()).latset.write(|w| w.bits(1 << $i)) }
Ok(())
}
}

impl<MODE> eh::StatefulOutputPin for $PXi<Output<MODE>> {

fn is_set_high(&mut self) -> Result<bool, Self::Error> {
Ok(unsafe { (*$PORTX::ptr()).lat.read().bits() & (1 << $i) != 0 })
}

fn is_set_low(&mut self) -> Result<bool, Self::Error> {
Ok(unsafe { (*$PORTX::ptr()).lat.read().bits() & (1 << $i) == 0 })
}

fn toggle(&mut self) -> Result<(), Self::Error> {
unsafe { (*$PORTX::ptr()).latinv.write(|w| w.bits(1 << $i)) };
Ok(())
}
}
)+
Expand Down
Loading

0 comments on commit 9b17484

Please sign in to comment.