From cc0e98edeab295d94429ecb381ce91d9e65faf60 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Sun, 9 Oct 2022 22:55:20 +0200 Subject: [PATCH] Almost compiling --- Cargo.toml | 2 + src/mcpwm/mod.rs | 93 +++++++++++++++++++++------------- src/mcpwm/operator.rs | 94 ++++++++++++++--------------------- src/mcpwm/timer.rs | 66 +++++++++++++++--------- src/mcpwm/timer_connection.rs | 68 ++++++++++++++++++------- src/peripherals.rs | 16 ++---- 6 files changed, 191 insertions(+), 148 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 90a31c99fe1..2bdde4c247d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,6 +33,8 @@ heapless = "0.7" embassy-sync = { version = "0.1", optional = true, git = "https://github.com/ivmarkov/embassy" } embassy-time = { version = "0.1", optional = true, features = ["tick-hz-1_000_000"], git = "https://github.com/ivmarkov/embassy" } edge-executor = { version = "0.2", optional = true, default-features = false } +libc = "0.2.134" + [build-dependencies] embuild = "0.30.3" diff --git a/src/mcpwm/mod.rs b/src/mcpwm/mod.rs index 949445866ce..a3cd07e397a 100644 --- a/src/mcpwm/mod.rs +++ b/src/mcpwm/mod.rs @@ -55,12 +55,18 @@ mod timer; mod operator; mod timer_connection; -use core::borrow::Borrow; +use core::ffi; -use crate::gpio::OutputPin; -use crate::units::{FromValueType, Hertz}; -use crate::mcpwm::operator::{HwOperator, OPERATOR0, OPERATOR1, OPERATOR2}; -use esp_idf_sys::*; +use crate::mcpwm::operator::{ + HwOperator0, HwOperator1, HwOperator2, + OPERATOR00, OPERATOR01, OPERATOR02, + OPERATOR10, OPERATOR11, OPERATOR12 +}; + +use crate::mcpwm::timer::{ + TIMER00, TIMER01, TIMER02, + TIMER10, TIMER11, TIMER12 +}; // MCPWM clock source frequency for ESP32 and ESP32-s3 const MCPWM_CLOCK_SOURCE_FREQUENCY: u32 = 160_000_000; @@ -72,58 +78,75 @@ const MAX_PWM_TIMER_PRESCALE: u32 = 0x1_00; const MAX_PWM_TIMER_PERIOD: u32 = 0x1_00_00; /// The Motor Control Pulse Width Modulator peripheral -pub struct Peripheral { - pub mcpwm: MCPWM, - pub operator0: OPERATOR0, - pub operator1: OPERATOR1, - pub operator2: OPERATOR2, +pub struct MCPWM0 { + timer0: TIMER00, + timer1: TIMER01, + timer2: TIMER02, + + pub operator0: OPERATOR00, + pub operator1: OPERATOR01, + pub operator2: OPERATOR02, } -impl Peripheral { +impl MCPWM0 { /// # Safety /// - /// It is safe to instantiate this exactly one time per `Unit`. + /// It is safe to instantiate this exactly one time per `Group`. pub unsafe fn new() -> Self { Self { - mcpwm: MCPWM::new(), - operator0: OPERATOR0::new(), - operator1: OPERATOR1::new(), - operator2: OPERATOR2::new(), + timer0: TIMER00::new(), + timer1: TIMER01::new(), + timer2: TIMER02::new(), + operator0: OPERATOR00::new(), + operator1: OPERATOR01::new(), + operator2: OPERATOR02::new(), } } } -#[derive(Default)] -pub struct UnitZero; - -#[derive(Default)] -pub struct UnitOne; +pub struct MCPWM1 { + timer0: TIMER10, + timer1: TIMER11, + timer2: TIMER12, -pub type Duty = u16; - -pub struct MCPWM { - _unit: U, + pub operator0: OPERATOR10, + pub operator1: OPERATOR11, + pub operator2: OPERATOR12, } -impl MCPWM { +impl MCPWM1 { /// # Safety /// - /// It is safe to instantiate this exactly one time per `Unit`. - unsafe fn new() -> Self { + /// It is safe to instantiate this exactly one time per `Group`. + pub unsafe fn new() -> Self { Self { - _unit: U::default(), + timer0: TIMER10::new(), + timer1: TIMER11::new(), + timer2: TIMER12::new(), + operator0: OPERATOR10::new(), + operator1: OPERATOR11::new(), + operator2: OPERATOR12::new(), } } } -pub trait Unit: Default { - const ID: mcpwm_unit_t; +#[derive(Default)] +pub struct Group0; + +#[derive(Default)] +pub struct Group1; + +pub type Duty = u16; + +// Note this was called `Unit` in IDF < 5.0 +pub trait Group: Default { + const ID: ffi::c_int; } -impl Unit for UnitZero { - const ID: mcpwm_unit_t = mcpwm_unit_t_MCPWM_UNIT_0; +impl Group for Group0 { + const ID: ffi::c_int = 0; } -impl Unit for UnitOne { - const ID: mcpwm_unit_t = mcpwm_unit_t_MCPWM_UNIT_1; +impl Group for Group1 { + const ID: ffi::c_int = 1; } \ No newline at end of file diff --git a/src/mcpwm/operator.rs b/src/mcpwm/operator.rs index dfaab85935b..95dfd97431d 100644 --- a/src/mcpwm/operator.rs +++ b/src/mcpwm/operator.rs @@ -1,69 +1,47 @@ -use std::borrow::Borrow; +use esp_idf_sys::{EspError, mcpwm_oper_handle_t}; -use esp_idf_sys::{mcpwm_io_signals_t, mcpwm_unit_t, mcpwm_operator_t, - mcpwm_io_signals_t_MCPWM0A, mcpwm_io_signals_t_MCPWM0B, - mcpwm_io_signals_t_MCPWM1A, mcpwm_io_signals_t_MCPWM1B, - mcpwm_io_signals_t_MCPWM2A, mcpwm_io_signals_t_MCPWM2B, EspError -}; - -use crate::{mcpwm::{Unit, UnitZero, UnitOne}, gpio::OutputPin}; +use crate::{mcpwm::{Group, Group0, Group1}, gpio::OutputPin}; use super::{Duty, timer_connection::OptionalOutputPin}; +use core::ffi; + // The hardware for ESP32 and ESP32-S3 can associate any operator(within the mcpwm module) with any // timer(within the mcpwm module) for example allowing using the same timer for all three operators. -pub trait HwOperator { - const SIGNAL_A: mcpwm_io_signals_t; - const SIGNAL_B: mcpwm_io_signals_t; - const UNIT_ID: mcpwm_unit_t = U::ID; +pub trait HwOperator { + const GROUP_ID: ffi::c_int = U::ID; } -macro_rules! impl_operator_helper { - ($instance:ident: $timer:expr, $signal_a:expr, $signal_b:expr, $unit:ty) => { - impl HwOperator<$unit> for $instance<$unit> { - const SIGNAL_A: mcpwm_io_signals_t = $signal_a; - const SIGNAL_B: mcpwm_io_signals_t = $signal_b; - } +macro_rules! impl_operator { + ($t:ident, $g:ty) => { + crate::impl_peripheral!($t); + + impl HwOperator<$g> for $t {} }; } -macro_rules! impl_operator { - ($instance:ident: $timer:expr, $signal_a:expr, $signal_b:expr) => { - pub struct $instance { - _unit: U, - } +pub trait HwOperator0: HwOperator {} +pub trait HwOperator1: HwOperator {} +pub trait HwOperator2: HwOperator {} - impl $instance { - /// # Safety - /// - /// It is safe to instantiate this operator exactly one time per Unit. - pub unsafe fn new() -> Self { - $instance { - _unit: U::default(), - } - } - } +// Group 0 +impl_operator!(OPERATOR00, Group0); +impl_operator!(OPERATOR01, Group0); +impl_operator!(OPERATOR02, Group0); - impl_operator_helper!($instance: $timer, $signal_a, $signal_b, UnitZero); - impl_operator_helper!($instance: $timer, $signal_a, $signal_b, UnitOne); - }; -} +// Group 1 +impl_operator!(OPERATOR10, Group1); +impl_operator!(OPERATOR11, Group1); +impl_operator!(OPERATOR12, Group1); + +impl HwOperator0 for OPERATOR00 {} +impl HwOperator0 for OPERATOR10 {} + +impl HwOperator1 for OPERATOR01 {} +impl HwOperator1 for OPERATOR11 {} -impl_operator!( - OPERATOR0: mcpwm_timer_t_MCPWM_TIMER_0, - mcpwm_io_signals_t_MCPWM0A, - mcpwm_io_signals_t_MCPWM0B -); -impl_operator!( - OPERATOR1: mcpwm_timer_t_MCPWM_TIMER_1, - mcpwm_io_signals_t_MCPWM1A, - mcpwm_io_signals_t_MCPWM1B -); -impl_operator!( - OPERATOR2: mcpwm_timer_t_MCPWM_TIMER_2, - mcpwm_io_signals_t_MCPWM2A, - mcpwm_io_signals_t_MCPWM2B -); +impl HwOperator2 for OPERATOR02 {} +impl HwOperator2 for OPERATOR12 {} // TODO: How do we want syncing to fit in to this? // TODO: How do we want carrier to fit into this? @@ -73,8 +51,8 @@ impl_operator!( /// /// Every Motor Control module has three operators. Every operator can generate two output signals called A and B. /// A and B share the same timer and thus frequency and phase but can have induvidual duty set. -pub struct Operator, PA: OptionalOutputPin, PB: OptionalOutputPin> { - handle: mcpwm_operator_t, +pub struct Operator, PA: OptionalOutputPin, PB: OptionalOutputPin> { + handle: mcpwm_oper_handle_t, _instance: O, _pin_a: PA, @@ -85,7 +63,7 @@ pub struct Operator, PA: OptionalOutputPin, PB: Option impl Operator where - U: Unit, + U: Group, O: HwOperator, PA: OutputPin, PB: OptionalOutputPin, @@ -103,7 +81,7 @@ where impl Operator where - U: Unit, + U: Group, O: HwOperator, PA: OptionalOutputPin, PB: OutputPin, @@ -187,10 +165,10 @@ pub enum DutyMode { ActiveLow, } -pub trait OptionalOperator> {} +pub trait OptionalOperator> {} pub struct NoOperator; -impl> OptionalOperator for NoOperator {} +impl> OptionalOperator for NoOperator {} /* diff --git a/src/mcpwm/timer.rs b/src/mcpwm/timer.rs index abed247e175..e116a5ff87f 100644 --- a/src/mcpwm/timer.rs +++ b/src/mcpwm/timer.rs @@ -1,9 +1,9 @@ use std::ptr; -use esp_idf_sys::{mcpwm_counter_type_t_MCPWM_UP_DOWN_COUNTER, mcpwm_counter_type_t_MCPWM_DOWN_COUNTER, mcpwm_counter_type_t_MCPWM_UP_COUNTER, mcpwm_timer_t, mcpwm_timer_handle_t, mcpwm_timer_enable, mcpwm_timer_t_MCPWM_TIMER_0, mcpwm_timer_t_MCPWM_TIMER_1, mcpwm_timer_t_MCPWM_TIMER_2, mcpwm_counter_type_t}; +use esp_idf_sys::{mcpwm_timer_t, mcpwm_timer_handle_t, mcpwm_timer_enable, mcpwm_timer_config_t, mcpwm_new_timer, mcpwm_del_timer, esp, EspError}; use crate::units::Hertz; -use crate::mcpwm::Unit; +use crate::mcpwm::{Group, Group0, Group1}; use super::operator::NoOperator; use super::timer_connection::TimerConnection; @@ -51,23 +51,30 @@ impl TimerConfig { //} //} -pub struct Timer> { +pub struct Timer> { handle: mcpwm_timer_handle_t, _timer: T, } -impl> Timer { +impl> Timer { pub fn new(timer: T, config: TimerConfig) -> Self { let config = mcpwm_timer_config_t { - resolution + group_id: todo!(), + clk_src: todo!(), + resolution_hz: todo!(), + count_mode: todo!(), + period_ticks: todo!(), + flags: todo!(), }; let mut handle = ptr::null(); - mcpwm_new_timer(config, &mut handle); - + unsafe { + esp!(mcpwm_new_timer(config, &mut handle)); + } // TODO: note that this has to be called before mcpwm_timer_enable // mcpwm_timer_register_event_callbacks() - - mcpwm_timer_enable(); + unsafe { + esp!(mcpwm_timer_enable(*handle)).unwrap(); + } Self { handle, _timer: timer } } @@ -81,8 +88,8 @@ impl> Timer { todo!() } - pub fn timer(&self) -> mcpwm_timer_t { - T::ID + pub fn timer(&self) -> mcpwm_timer_handle_t { + self.handle } pub fn release(self) -> T { @@ -90,7 +97,9 @@ impl> Timer { _timer, handle } = self; - mcpwm_del_timer(handle); + unsafe { + esp!(mcpwm_del_timer(handle)).unwrap(); + } _timer } @@ -99,9 +108,13 @@ impl> Timer { } } -impl> Drop for Timer { +impl> Drop for Timer { fn drop(self) { - mcpwm_del_timer(self.handle) + unsafe { + unsafe { + esp!(mcpwm_del_timer(self.handle)).unwrap(); + } + } } } @@ -166,6 +179,7 @@ pub enum CounterMode { UpDown, } +/* impl From for mcpwm_counter_type_t { fn from(val: CounterMode) -> Self { match val { @@ -175,21 +189,25 @@ impl From for mcpwm_counter_type_t { CounterMode::UpDown => mcpwm_counter_type_t_MCPWM_UP_DOWN_COUNTER, } } -} +}*/ -unsafe trait HwTimer { +pub unsafe trait HwTimer { const ID: mcpwm_timer_t; } macro_rules! impl_timer { - ($t:ident, $id:expr) => { - struct $t; - impl HwTimer for $t { - const ID: mcpwm_timer_t = $id; - } + ($t:ident, $g:ty) => { + crate::impl_peripheral!($t); + impl HwTimer<$g> for $t {} }; } -impl_timer!(TIMER0, mcpwm_timer_t_MCPWM_TIMER_0); -impl_timer!(TIMER1, mcpwm_timer_t_MCPWM_TIMER_1); -impl_timer!(TIMER2, mcpwm_timer_t_MCPWM_TIMER_2); \ No newline at end of file +// Group 0 +impl_timer!(TIMER00, Group0); +impl_timer!(TIMER01, Group0); +impl_timer!(TIMER02, Group0); + +// Group 1 +impl_timer!(TIMER10, Group1); +impl_timer!(TIMER11, Group1); +impl_timer!(TIMER12, Group1); \ No newline at end of file diff --git a/src/mcpwm/timer_connection.rs b/src/mcpwm/timer_connection.rs index 02ee3d8daa6..fc891c65e2d 100644 --- a/src/mcpwm/timer_connection.rs +++ b/src/mcpwm/timer_connection.rs @@ -1,19 +1,24 @@ -use crate::{mcpwm::Unit, gpio::OutputPin}; +use crate::mcpwm::Group; -use super::operator::{OptionalOperator, OPERATOR0, OperatorConfig, NoOperator, OPERATOR2, OPERATOR1}; +use super::{ + operator::{ + HwOperator0, HwOperator1, HwOperator2, NoOperator, OperatorConfig, OptionalOperator, + }, + timer::{HwTimer, Timer}, +}; // TODO: How do we want fault module to fit into this? /// Created by `Timer::into_connection()` -pub struct TimerConnection, O0, O1, O2> - where - O0: OptionalOperator>, - O1: OptionalOperator>, - O2: OptionalOperator>, +pub struct TimerConnection, O0, O1, O2> +where + O0: OptionalOperator>, + O1: OptionalOperator>, + O2: OptionalOperator>, { - timer: Timer, + timer: Timer, operator0: O0, operator1: O1, - operator2: O2 + operator2: O2, } impl TimerConnection { @@ -22,7 +27,7 @@ impl TimerConnection { timer, operator0: NoOperator, operator1: NoOperator, - operator2: NoOperator + operator2: NoOperator, } } } @@ -32,8 +37,15 @@ impl TimerConnection { // // Thus we know that after split is called nothing can be added/removed while still having access to // the individual objects. We also garantuee that the operators wont live longer than the timer -impl, O1: OptionalOperator, O2: OptionalOperator> TimerConnection { - fn split(&mut self) -> (&mut timer, &mut O0, &mut O1, &mut O2) { +impl< + U, + T, + O0: OptionalOperator, + O1: OptionalOperator, + O2: OptionalOperator, + > TimerConnection +{ + fn split(&mut self) -> (&mut Timer, &mut O0, &mut O1, &mut O2) { ( &mut self.timer, &mut self.operator0, @@ -44,41 +56,59 @@ impl, O1: OptionalOperator TimerConnection { - fn attatch_operator0(mut self, operator_handle: OPERATOR0, operator_cfg: OperatorConfig, pin_a: PA, pin_b: PB) -> TimerConnection { + fn attatch_operator0( + mut self, + operator_handle: HwOperator0, + operator_cfg: OperatorConfig, + pin_a: PA, + pin_b: PB, + ) -> TimerConnection, O1, O2> { let operator = self.init_and_attach_operator(operator_cfg, pin_a, pin_b); TimerConnection { timer: self.timer, operator0: operator, operator1: self.operator1, - operator2: self.operator2 + operator2: self.operator2, } } } impl TimerConnection { - fn attatch_operator1(mut self, operator_handle: OPERATOR1, operator_cfg: OperatorConfig, pin_a: PA, pin_b: PB) -> TimerConnection { + fn attatch_operator1( + mut self, + operator_handle: HwOperator1, + operator_cfg: OperatorConfig, + pin_a: PA, + pin_b: PB, + ) -> TimerConnection, O2> { let operator = self.init_and_attach_operator(operator_cfg, pin_a, pin_b); TimerConnection { timer: self.timer, operator0: self.operator0, operator1: operator, - operator2: self.operator2 + operator2: self.operator2, } } } impl TimerConnection { - fn attatch_operator2(mut self, operator_handle: OPERATOR2, operator_cfg: OperatorConfig, pin_a: PA, pin_b: PB) -> TimerConnection { + fn attatch_operator2( + mut self, + operator_handle: HwOperator2, + operator_cfg: OperatorConfig, + pin_a: PA, + pin_b: PB, + ) -> TimerConnection> { let operator = self.init_and_attach_operator(operator_cfg, pin_a, pin_b); TimerConnection { timer: self.timer, operator0: self.operator0, operator1: self.operator1, - operator2: operator + operator2: operator, } } } pub struct NoPin; -pub trait OptionalOutputPin {} \ No newline at end of file +pub trait OptionalOutputPin {} diff --git a/src/peripherals.rs b/src/peripherals.rs index acc2a2031b6..128a9982bde 100644 --- a/src/peripherals.rs +++ b/src/peripherals.rs @@ -55,15 +55,11 @@ pub struct Peripherals { #[cfg(not(feature = "riscv-ulp-hal"))] pub can: can::CAN, #[cfg(not(feature = "riscv-ulp-hal"))] -<<<<<<< HEAD pub ledc: ledc::LEDC, -======= - pub ledc: ledc::Peripheral, #[cfg(all(any(esp32, esp32s3), not(feature = "riscv-ulp-hal")))] - pub mcpwm0: mcpwm::Peripheral, + pub mcpwm0: mcpwm::MCPWM0, #[cfg(all(any(esp32, esp32s3), not(feature = "riscv-ulp-hal")))] - pub mcpwm1: mcpwm::Peripheral, ->>>>>>> The beginning of a first rough draft... + pub mcpwm1: mcpwm::MCPWM1, #[cfg(not(feature = "riscv-ulp-hal"))] pub rmt: rmt::RMT, #[cfg(all( @@ -171,15 +167,11 @@ impl Peripherals { #[cfg(not(feature = "riscv-ulp-hal"))] can: can::CAN::new(), #[cfg(not(feature = "riscv-ulp-hal"))] -<<<<<<< HEAD ledc: ledc::LEDC::new(), -======= - ledc: ledc::Peripheral::new(), #[cfg(any(esp32, esp32s3))] - mcpwm0: mcpwm::Peripheral::new(), + mcpwm0: mcpwm::MCPWM0::new(), #[cfg(any(esp32, esp32s3))] - mcpwm1: mcpwm::Peripheral::new(), ->>>>>>> The beginning of a first rough draft... + mcpwm1: mcpwm::MCPWM1::new(), #[cfg(not(feature = "riscv-ulp-hal"))] rmt: rmt::RMT::new(), #[cfg(all(