Skip to content

Commit 5a107e1

Browse files
bors[bot]burrbull
andauthored
Merge #578
578: read/write dead_time r=therealprof a=burrbull Co-authored-by: Andrey Zgarbul <[email protected]>
2 parents e4ff964 + 8edbbd8 commit 5a107e1

File tree

3 files changed

+161
-5
lines changed

3 files changed

+161
-5
lines changed

CHANGELOG.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1111

1212
- Bump `synopsys-usb-otg` to 0.3.2 (bug fix)
1313
- Update readme, clippy fixes
14-
- Added possibility to pass complementary pins to `Pwm` and change pwm channel polarity [#571]
14+
- Added possibility to pass complementary pins to `Pwm` and change pwm channel polarity [#571],
15+
set dead time and idle state for advanced timers [#578]
1516

1617
### Added
1718

@@ -27,6 +28,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
2728
[#571]: https://github.com/stm32-rs/stm32f4xx-hal/pull/571
2829
[#572]: https://github.com/stm32-rs/stm32f4xx-hal/pull/572
2930
[#577]: https://github.com/stm32-rs/stm32f4xx-hal/pull/577
31+
[#578]: https://github.com/stm32-rs/stm32f4xx-hal/pull/578
32+
3033

3134
## [v0.14.0] - 2022-12-12
3235

src/timer.rs

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,13 @@ pub enum Polarity {
6464
ActiveLow,
6565
}
6666

67+
/// Output Idle state
68+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
69+
pub enum IdleState {
70+
Reset,
71+
Set,
72+
}
73+
6774
/// Interrupt events
6875
#[derive(Clone, Copy, PartialEq, Eq)]
6976
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
@@ -239,7 +246,7 @@ pub type CCR4<T> = CCR<T, 3>;
239246
pub struct DMAR<T>(T);
240247

241248
mod sealed {
242-
use super::{Channel, Event, Ocm, Polarity};
249+
use super::{Channel, Event, IdleState, Ocm, Polarity};
243250
pub trait General {
244251
type Width: Into<u32> + From<u16>;
245252
fn max_auto_reload() -> u32;
@@ -266,6 +273,7 @@ mod sealed {
266273

267274
pub trait WithPwmCommon: General {
268275
const CH_NUMBER: u8;
276+
const COMP_CH_NUMBER: u8;
269277
fn read_cc_value(channel: u8) -> u32;
270278
fn set_cc_value(channel: u8, value: u32);
271279
fn enable_channel(channel: u8, b: bool);
@@ -275,6 +283,9 @@ mod sealed {
275283

276284
pub trait Advanced: WithPwmCommon {
277285
fn enable_nchannel(channel: u8, b: bool);
286+
fn set_dtg_value(value: u8);
287+
fn read_dtg_value() -> u8;
288+
fn idle_state(channel: u8, comp: bool, s: IdleState);
278289
}
279290

280291
pub trait WithPwm: WithPwmCommon {
@@ -409,6 +420,7 @@ macro_rules! hal {
409420
$(
410421
impl WithPwmCommon for $TIM {
411422
const CH_NUMBER: u8 = $cnum;
423+
const COMP_CH_NUMBER: u8 = $cnum;
412424

413425
#[inline(always)]
414426
fn read_cc_value(c: u8) -> u32 {
@@ -448,7 +460,7 @@ macro_rules! hal {
448460
#[inline(always)]
449461
fn set_nchannel_polarity(c: u8, p: Polarity) {
450462
let tim = unsafe { &*<$TIM>::ptr() };
451-
if c < Self::CH_NUMBER {
463+
if c < Self::COMP_CH_NUMBER {
452464
unsafe { bb::write(&tim.ccer, c*4 + 3, p == Polarity::ActiveLow); }
453465
}
454466
}
@@ -459,10 +471,30 @@ macro_rules! hal {
459471
fn enable_nchannel(c: u8, b: bool) {
460472
let $aoe = ();
461473
let tim = unsafe { &*<$TIM>::ptr() };
462-
if c < Self::CH_NUMBER {
474+
if c < Self::COMP_CH_NUMBER {
463475
unsafe { bb::write(&tim.ccer, c*4 + 2, b); }
464476
}
465477
}
478+
fn set_dtg_value(value: u8) {
479+
let tim = unsafe { &*<$TIM>::ptr() };
480+
tim.bdtr.modify(|_,w| unsafe { w.dtg().bits(value) });
481+
}
482+
fn read_dtg_value() -> u8 {
483+
let tim = unsafe { &*<$TIM>::ptr() };
484+
tim.bdtr.read().dtg().bits()
485+
}
486+
fn idle_state(c: u8, comp: bool, s: IdleState) {
487+
let tim = unsafe { &*<$TIM>::ptr() };
488+
if !comp {
489+
if c < Self::CH_NUMBER {
490+
unsafe { bb::write(&tim.cr2, c*2 + 8, s == IdleState::Set); }
491+
}
492+
} else {
493+
if c < Self::COMP_CH_NUMBER {
494+
unsafe { bb::write(&tim.cr2, c*2 + 9, s == IdleState::Set); }
495+
}
496+
}
497+
}
466498
}
467499
)?
468500

src/timer/pwm.rs

Lines changed: 122 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@
3434
//! and change their polarity with `set_polarity` and `set_complementary_polarity`.
3535
3636
use super::{
37-
compute_arr_presc, Advanced, Channel, FTimer, Instance, Ocm, Polarity, Timer, WithPwm,
37+
compute_arr_presc, Advanced, Channel, FTimer, IdleState, Instance, Ocm, Polarity, Timer,
38+
WithPwm,
3839
};
3940
use crate::rcc::Clocks;
4041
use core::marker::PhantomData;
@@ -263,6 +264,16 @@ impl<TIM: Instance + WithPwm + Advanced, const C: u8> PwmChannel<TIM, C, true> {
263264
pub fn enable_complementary(&mut self) {
264265
TIM::enable_nchannel(C, true);
265266
}
267+
268+
#[inline]
269+
pub fn set_idle_state(&mut self, s: IdleState) {
270+
TIM::idle_state(C, false, s);
271+
}
272+
273+
#[inline]
274+
pub fn set_complementary_idle_state(&mut self, s: IdleState) {
275+
TIM::idle_state(C, true, s);
276+
}
266277
}
267278

268279
pub struct PwmHz<TIM, P, PINS>
@@ -359,22 +370,27 @@ where
359370
TIM: Instance + WithPwm,
360371
PINS: Pins<TIM, P>,
361372
{
373+
#[inline]
362374
pub fn enable(&mut self, channel: Channel) {
363375
TIM::enable_channel(PINS::check_used(channel) as u8, true)
364376
}
365377

378+
#[inline]
366379
pub fn disable(&mut self, channel: Channel) {
367380
TIM::enable_channel(PINS::check_used(channel) as u8, false)
368381
}
369382

383+
#[inline]
370384
pub fn set_polarity(&mut self, channel: Channel, p: Polarity) {
371385
TIM::set_channel_polarity(PINS::check_used(channel) as u8, p);
372386
}
373387

388+
#[inline]
374389
pub fn get_duty(&self, channel: Channel) -> u16 {
375390
TIM::read_cc_value(PINS::check_used(channel) as u8) as u16
376391
}
377392

393+
#[inline]
378394
pub fn set_duty(&mut self, channel: Channel, duty: u16) {
379395
TIM::set_cc_value(PINS::check_used(channel) as u8, duty as u32)
380396
}
@@ -402,6 +418,7 @@ where
402418
self.tim.cnt_reset();
403419
}
404420

421+
#[inline]
405422
pub fn set_complementary_polarity(&mut self, channel: Channel, p: Polarity) {
406423
TIM::set_channel_polarity(PINS::check_complementary_used(channel) as u8, p);
407424
}
@@ -412,13 +429,50 @@ where
412429
TIM: Instance + WithPwm + Advanced,
413430
PINS: Pins<TIM, P>,
414431
{
432+
#[inline]
415433
pub fn enable_complementary(&mut self, channel: Channel) {
416434
TIM::enable_nchannel(PINS::check_complementary_used(channel) as u8, true)
417435
}
418436

437+
#[inline]
419438
pub fn disable_complementary(&mut self, channel: Channel) {
420439
TIM::enable_nchannel(PINS::check_complementary_used(channel) as u8, false)
421440
}
441+
442+
/// Set number DTS ticks during that complementary pin is `dead`
443+
#[inline]
444+
pub fn set_dead_time(&mut self, dts_ticks: u16) {
445+
let bits = pack_ceil_dead_time(dts_ticks);
446+
TIM::set_dtg_value(bits);
447+
}
448+
449+
/// Set raw dead time (DTG) bits
450+
#[inline]
451+
pub fn set_dead_time_bits(&mut self, bits: u8) {
452+
TIM::set_dtg_value(bits);
453+
}
454+
455+
/// Return dead time for complementary pins in DTS ticks
456+
#[inline]
457+
pub fn get_dead_time(&self) -> u16 {
458+
unpack_dead_time(TIM::read_dtg_value())
459+
}
460+
461+
/// Get raw dead time (DTG) bits
462+
#[inline]
463+
pub fn get_dead_time_bits(&self) -> u8 {
464+
TIM::read_dtg_value()
465+
}
466+
467+
#[inline]
468+
pub fn set_idle_state(&mut self, channel: Channel, s: IdleState) {
469+
TIM::idle_state(PINS::check_used(channel) as u8, false, s);
470+
}
471+
472+
#[inline]
473+
pub fn set_complementary_idle_state(&mut self, channel: Channel, s: IdleState) {
474+
TIM::idle_state(PINS::check_complementary_used(channel) as u8, true, s);
475+
}
422476
}
423477

424478
pub struct Pwm<TIM, P, PINS, const FREQ: u32>
@@ -517,30 +571,37 @@ where
517571
TIM: Instance + WithPwm,
518572
PINS: Pins<TIM, P>,
519573
{
574+
#[inline]
520575
pub fn enable(&mut self, channel: Channel) {
521576
TIM::enable_channel(PINS::check_used(channel) as u8, true)
522577
}
523578

579+
#[inline]
524580
pub fn disable(&mut self, channel: Channel) {
525581
TIM::enable_channel(PINS::check_used(channel) as u8, false)
526582
}
527583

584+
#[inline]
528585
pub fn set_polarity(&mut self, channel: Channel, p: Polarity) {
529586
TIM::set_channel_polarity(PINS::check_used(channel) as u8, p);
530587
}
531588

589+
#[inline]
532590
pub fn get_duty(&self, channel: Channel) -> u16 {
533591
TIM::read_cc_value(PINS::check_used(channel) as u8) as u16
534592
}
535593

594+
#[inline]
536595
pub fn get_duty_time(&self, channel: Channel) -> TimerDurationU32<FREQ> {
537596
TimerDurationU32::from_ticks(TIM::read_cc_value(PINS::check_used(channel) as u8))
538597
}
539598

599+
#[inline]
540600
pub fn set_duty(&mut self, channel: Channel, duty: u16) {
541601
TIM::set_cc_value(PINS::check_used(channel) as u8, duty.into())
542602
}
543603

604+
#[inline]
544605
pub fn set_duty_time(&mut self, channel: Channel, duty: TimerDurationU32<FREQ>) {
545606
TIM::set_cc_value(PINS::check_used(channel) as u8, duty.ticks())
546607
}
@@ -559,6 +620,7 @@ where
559620
self.tim.cnt_reset();
560621
}
561622

623+
#[inline]
562624
pub fn set_complementary_polarity(&mut self, channel: Channel, p: Polarity) {
563625
TIM::set_channel_polarity(PINS::check_complementary_used(channel) as u8, p);
564626
}
@@ -569,11 +631,70 @@ where
569631
TIM: Instance + WithPwm + Advanced,
570632
PINS: Pins<TIM, P>,
571633
{
634+
#[inline]
572635
pub fn enable_complementary(&mut self, channel: Channel) {
573636
TIM::enable_nchannel(PINS::check_complementary_used(channel) as u8, true)
574637
}
575638

639+
#[inline]
576640
pub fn disable_complementary(&mut self, channel: Channel) {
577641
TIM::enable_nchannel(PINS::check_complementary_used(channel) as u8, false)
578642
}
643+
644+
/// Set number DTS ticks during that complementary pin is `dead`
645+
#[inline]
646+
pub fn set_dead_time(&mut self, dts_ticks: u16) {
647+
let bits = pack_ceil_dead_time(dts_ticks);
648+
TIM::set_dtg_value(bits);
649+
}
650+
651+
/// Set raw dead time (DTG) bits
652+
#[inline]
653+
pub fn set_dead_time_bits(&mut self, bits: u8) {
654+
TIM::set_dtg_value(bits);
655+
}
656+
657+
/// Return dead time for complementary pins in DTS ticks
658+
#[inline]
659+
pub fn get_dead_time(&self) -> u16 {
660+
unpack_dead_time(TIM::read_dtg_value())
661+
}
662+
663+
/// Get raw dead time (DTG) bits
664+
#[inline]
665+
pub fn get_dead_time_bits(&self) -> u8 {
666+
TIM::read_dtg_value()
667+
}
668+
669+
#[inline]
670+
pub fn set_idle_state(&mut self, channel: Channel, s: IdleState) {
671+
TIM::idle_state(PINS::check_used(channel) as u8, false, s);
672+
}
673+
674+
#[inline]
675+
pub fn set_complementary_idle_state(&mut self, channel: Channel, s: IdleState) {
676+
TIM::idle_state(PINS::check_complementary_used(channel) as u8, true, s);
677+
}
678+
}
679+
680+
const fn pack_ceil_dead_time(dts_ticks: u16) -> u8 {
681+
match dts_ticks {
682+
0..=127 => dts_ticks as u8,
683+
128..=254 => ((((dts_ticks + 1) >> 1) - 64) as u8) | 0b_1000_0000,
684+
255..=504 => ((((dts_ticks + 7) >> 3) - 32) as u8) | 0b_1100_0000,
685+
505..=1008 => ((((dts_ticks + 15) >> 4) - 32) as u8) | 0b_1110_0000,
686+
1009.. => 0xff,
687+
}
688+
}
689+
690+
const fn unpack_dead_time(bits: u8) -> u16 {
691+
if bits & 0b_1000_0000 == 0 {
692+
bits as u16
693+
} else if bits & 0b_0100_0000 == 0 {
694+
(((bits & !0b_1000_0000) as u16) + 64) * 2
695+
} else if bits & 0b_0010_0000 == 0 {
696+
(((bits & !0b_1100_0000) as u16) + 32) * 8
697+
} else {
698+
(((bits & !0b_1110_0000) as u16) + 32) * 16
699+
}
579700
}

0 commit comments

Comments
 (0)