rp2040/
pwm.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! Pulse wave modulation (PWM) driver for RP2040.
6//!
7//! # Hardware Interface Layer (HIL)
8//!
9//! The driver implements both Pwm and PwmPin HILs. The following features are available when using
10//! the driver through HIL:
11//!
12//! + Configurable top and compare values
13//! + Independent configuration for each channel and for each output/input pin
14//! + Duty cycle from 0% to 100% **inclusive**
15//!
16//! # Examples
17//!
18//! The integration tests for Raspberry Pi Pico provide some examples using the driver.
19//! See boards/raspberry_pi_pico/src/test/pwm.rs
20
21use kernel::debug;
22use kernel::hil;
23use kernel::utilities::cells::OptionalCell;
24use kernel::utilities::registers::interfaces::{ReadWriteable, Readable, Writeable};
25use kernel::utilities::registers::{
26    register_bitfields, register_structs, ReadOnly, ReadWrite, WriteOnly,
27};
28use kernel::utilities::StaticRef;
29use kernel::ErrorCode;
30
31use crate::clocks;
32use crate::gpio::RPGpio;
33
34register_bitfields![u32,
35    CSR [
36        // Enable PWM channel
37        EN OFFSET(0) NUMBITS(1) [],
38        // Enable phase-correct modulation
39        PH_CORRECT OFFSET(1) NUMBITS(1) [],
40        // Invert output A
41        A_INV OFFSET(2) NUMBITS(1) [],
42        // Invert output B
43        B_INV OFFSET(3) NUMBITS(1) [],
44        // PWM slice event selection for fractional clock divider
45        // Default value = FREE_RUNNING (always on)
46        // If the event is different from FREE_RUNNING, then pin B becomes
47        // an input pin
48        DIVMOD OFFSET(4) NUMBITS(2) [
49            // Free-running counting at rate dictated by fractional divider
50            FREE_RUNNING = 0,
51            // Fractional divider operation is gated by the PWM B pin
52            B_HIGH = 1,
53            // Counter advances with each rising edge of the PWM B pin
54            B_RISING = 2,
55            // Counter advances with each falling edge of the PWM B pin
56            B_FALLING = 3
57        ],
58        // Retard the phase of the counter by 1 count, while it is running
59        // Self-clearing. Write a 1, and poll until low. Counter must be running.
60        PH_RET OFFSET(6) NUMBITS(1) [],
61        // Advance the phase of the counter by 1 count, while it is running
62        // Self clearing. Write a 1, and poll until low. Counter must be running.
63        PH_ADV OFFSET(7) NUMBITS(1) []
64    ],
65
66    // DIV register
67    // INT and FRAC form a fixed-point fractional number.
68    // Counting rate is system clock frequency divided by this number.
69    // Fractional division uses simple 1st-order sigma-delta.
70    DIV [
71        FRAC OFFSET(0) NUMBITS(4) [],
72        INT OFFSET(4) NUMBITS(8) []
73    ],
74
75    // Direct access to the PWM counter
76    CTR [
77        CTR OFFSET(0) NUMBITS(16) []
78    ],
79
80    // Counter compare values
81    CC [
82        A OFFSET(0) NUMBITS(16) [],
83        B OFFSET(16) NUMBITS(16) []
84    ],
85
86    // Counter top value
87    // When the value of the counter reaches the top value, depending on the
88    // ph_correct value, the counter will either:
89    // + wrap to 0 if ph_correct == 0
90    // + it starts counting downward until it reaches 0 again if ph_correct == 0
91    TOP [
92        TOP OFFSET(0) NUMBITS(16) []
93    ],
94
95    // Control multiple channels at once.
96    // Each bit controls one channel.
97    CH [
98        CH OFFSET(0) NUMBITS(8) [
99            CH0 = 1,
100            CH1 = 2,
101            CH2 = 4,
102            CH3 = 8,
103            CH4 = 16,
104            CH5 = 32,
105            CH6 = 64,
106            CH7 = 128
107        ]
108    ]
109];
110
111const NUMBER_CHANNELS: usize = 8;
112
113#[repr(C)]
114struct Channel {
115    // Control and status register
116    csr: ReadWrite<u32, CSR::Register>,
117    // Division register
118    div: ReadWrite<u32, DIV::Register>,
119    // Direct access to the PWM counter register
120    ctr: ReadWrite<u32, CTR::Register>,
121    // Counter compare values register
122    cc: ReadWrite<u32, CC::Register>,
123    // Counter wrap value register
124    top: ReadWrite<u32, TOP::Register>,
125}
126
127register_structs! {
128    PwmRegisters {
129        // Channel registers
130        (0x0000 => ch: [Channel; NUMBER_CHANNELS]),
131        // Enable register
132        // This register aliases the CSR_EN bits for all channels.
133        // Writing to this register allows multiple channels to be enabled or disabled
134        // or disables simultaneously, so they can run in perfect sync.
135        (0x00A0 => en: ReadWrite<u32, CH::Register>),
136        // Raw interrupts register
137        (0x00A4 => intr: WriteOnly<u32, CH::Register>),
138        // Interrupt enable register
139        (0x00A8 => inte: ReadWrite<u32, CH::Register>),
140        // Interrupt force register
141        (0x00AC => intf: ReadWrite<u32, CH::Register>),
142        // Interrupt status after masking & forcing
143        (0x00B0 => ints: ReadOnly<u32, CH::Register>),
144        (0x00B4 => @END),
145    }
146}
147
148#[derive(Clone, Copy)]
149/// Fractional clock divider running mode
150///
151/// Each channel can be configured to run in four different ways:
152///
153/// + Free running: The fractional clock divider is always enabled. In this mode,
154/// pins A and B are configured as output pins. In other modes, pin B becomes
155/// an input pin.
156/// + High: The fractional clock divider is enabled when pin B is high.
157/// + Rising: The fractional clock divider is enabled when a rising-edge is
158/// detected on pin B.
159/// + Falling: The fractional clock divider is enabled when a falling-edge
160/// is detected on pin B.
161pub enum DivMode {
162    FreeRunning,
163    High,
164    Rising,
165    Falling,
166}
167
168/// Channel identifier
169///
170/// There are a total of 8 eight PWM channels.
171#[derive(Clone, Copy, PartialEq, Debug)]
172pub enum ChannelNumber {
173    Ch0,
174    Ch1,
175    Ch2,
176    Ch3,
177    Ch4,
178    Ch5,
179    Ch6,
180    Ch7,
181}
182
183const CHANNEL_NUMBERS: [ChannelNumber; NUMBER_CHANNELS] = [
184    ChannelNumber::Ch0,
185    ChannelNumber::Ch1,
186    ChannelNumber::Ch2,
187    ChannelNumber::Ch3,
188    ChannelNumber::Ch4,
189    ChannelNumber::Ch5,
190    ChannelNumber::Ch6,
191    ChannelNumber::Ch7,
192];
193
194/// Each GPIO pin can be configured as a PWM pin.
195/// The following table shows the mapping between GPIO pins and PWM pins:
196///
197/// | GPIO  | PWM |
198/// | ----- | --- |
199/// | 0     | 0A  |
200/// | 1     | 0B  |
201/// | 2     | 1A  |
202/// | 3     | 1B  |
203/// | 4     | 2A  |
204/// | 5     | 2B  |
205/// | 6     | 3A  |
206/// | 7     | 3B  |
207/// | 8     | 4A  |
208/// | 9     | 4B  |
209/// | 10    | 5A  |
210/// | 11    | 5B  |
211/// | 12    | 6A  |
212/// | 13    | 6B  |
213/// | 14    | 7A  |
214/// | 15    | 7B  |
215/// | 16    | 0A  |
216/// | 17    | 0B  |
217/// | 18    | 1A  |
218/// | 19    | 1B  |
219/// | 20    | 2A  |
220/// | 21    | 2B  |
221/// | 22    | 3A  |
222/// | 23    | 3B  |
223/// | 24    | 4A  |
224/// | 25    | 4B  |
225/// | 26    | 5A  |
226/// | 27    | 5B  |
227/// | 28    | 6A  |
228/// | 29    | 6B  |
229///
230/// **Note**:
231///
232/// + The same PWM output can be selected on two GPIO pins. The same signal will appear on each
233/// GPIO.
234/// + If a PWM B pin is used as an input, and is selected on multiple GPIO pins, then the PWM
235/// channel will see the logical OR of those two GPIO inputs
236impl From<RPGpio> for ChannelNumber {
237    fn from(gpio: RPGpio) -> Self {
238        match gpio as u8 >> 1 & 0b111 {
239            // Because of the bitwise AND, there are only eight possible values
240            0 => ChannelNumber::Ch0,
241            1 => ChannelNumber::Ch1,
242            2 => ChannelNumber::Ch2,
243            3 => ChannelNumber::Ch3,
244            4 => ChannelNumber::Ch4,
245            5 => ChannelNumber::Ch5,
246            6 => ChannelNumber::Ch6,
247            _ => ChannelNumber::Ch7,
248        }
249    }
250}
251
252/// Identifier for a channel pin
253///
254/// Each PWM channel has two pins: A and B.
255/// Pin A is always configured as an output pin.
256/// Pin B is configured as an output pin when running in free running mode. Otherwise, it is
257/// configured as an input pin.
258#[derive(Clone, Copy, PartialEq, Debug)]
259pub enum ChannelPin {
260    A,
261    B,
262}
263
264/// Check ChannelNumber implementation for more details
265impl From<RPGpio> for ChannelPin {
266    fn from(gpio: RPGpio) -> Self {
267        match gpio as u8 & 0b0000_0001 {
268            // Because of the bitwise AND, there are only two possible values
269            0 => ChannelPin::A,
270            _ => ChannelPin::B,
271        }
272    }
273}
274
275// PWM channel configuration structure
276//
277// This helper struct allows multiple channels to share the same configuration.
278struct PwmChannelConfiguration {
279    en: bool,
280    ph_correct: bool,
281    a_inv: bool,
282    b_inv: bool,
283    divmode: DivMode,
284    int: u8,
285    frac: u8,
286    cc_a: u16,
287    cc_b: u16,
288    top: u16,
289}
290
291impl Default for PwmChannelConfiguration {
292    // Create a set of default values to use for configuring a PWM channel:
293    // + the channel is disabled
294    // + trailing-edge modulation configured
295    // + no pin A and B polarity inversion
296    // + free running mode for the fractional clock divider
297    // + integral part of the divider is 1 and the fractional part is 0
298    // + compare values for both pins are set 0 (0% duty cycle)
299    // + top value is set to its maximum value
300    fn default() -> Self {
301        PwmChannelConfiguration {
302            en: false,
303            ph_correct: false,
304            a_inv: false,
305            b_inv: false,
306            divmode: DivMode::FreeRunning,
307            int: 1,
308            frac: 0,
309            cc_a: 0,
310            cc_b: 0,
311            top: u16::MAX,
312        }
313    }
314}
315
316const PWM_BASE: StaticRef<PwmRegisters> =
317    unsafe { StaticRef::new(0x40050000 as *const PwmRegisters) };
318
319/// Main struct for controlling PWM peripheral
320pub struct Pwm<'a> {
321    registers: StaticRef<PwmRegisters>,
322    clocks: OptionalCell<&'a clocks::Clocks>,
323}
324
325impl<'a> Pwm<'a> {
326    /// Create a new Pwm struct
327    ///
328    /// **Note**:
329    /// + This method must be called only once when setting up the kernel peripherals.
330    /// + This peripheral depends on the chip's clocks.
331    /// + Also, if interrupts are required, then an interrupt handler must be set. Otherwise, all
332    /// the interrupts will be ignored.
333    pub fn new() -> Self {
334        let pwm = Self {
335            registers: PWM_BASE,
336            clocks: OptionalCell::empty(),
337        };
338        pwm.init();
339        pwm
340    }
341
342    // Enable or disable the given PWM channel
343    //
344    // enable == false ==> disable channel
345    // enable == true ==> enable channel
346    fn set_enabled(&self, channel_number: ChannelNumber, enable: bool) {
347        self.registers.ch[channel_number as usize]
348            .csr
349            .modify(match enable {
350                true => CSR::EN::SET,
351                false => CSR::EN::CLEAR,
352            });
353    }
354
355    // Set phase correct (dual slope) modulation for the givem PWM channel
356    //
357    // ph_correct == false ==> trailing-edge modulation
358    // ph_correct == true ==> phase-correct modulation
359    fn set_ph_correct(&self, channel_number: ChannelNumber, ph_correct: bool) {
360        self.registers.ch[channel_number as usize]
361            .csr
362            .modify(match ph_correct {
363                true => CSR::PH_CORRECT::SET,
364                false => CSR::PH_CORRECT::CLEAR,
365            });
366    }
367
368    // Invert polarity for pin A
369    // a_inv == true ==> invert polarity for pin A
370    fn set_invert_polarity_a(&self, channel_number: ChannelNumber, inv: bool) {
371        self.registers.ch[channel_number as usize]
372            .csr
373            .modify(match inv {
374                true => CSR::A_INV::SET,
375                false => CSR::A_INV::CLEAR,
376            });
377    }
378
379    // Invert polarity for pin B
380    // b_inv == true ==> invert polarity for pin B
381    fn set_invert_polarity_b(&self, channel_number: ChannelNumber, inv: bool) {
382        self.registers.ch[channel_number as usize]
383            .csr
384            .modify(match inv {
385                true => CSR::B_INV::SET,
386                false => CSR::B_INV::CLEAR,
387            });
388    }
389
390    // Invert polarity for both pins
391    fn set_invert_polarity(&self, channel_number: ChannelNumber, a_inv: bool, b_inv: bool) {
392        self.set_invert_polarity_a(channel_number, a_inv);
393        self.set_invert_polarity_b(channel_number, b_inv);
394    }
395
396    // Set running mode for the givel channel
397    //
398    // divmode == FreeRunning ==> always enable clock divider
399    // divmode == High ==> enable clock divider when pin B is high
400    // divmode == Rising ==> enable clock divider when pin B is rising
401    // divmode == Falling ==> enable clock divider when pin B is falling
402    fn set_div_mode(&self, channel_number: ChannelNumber, div_mode: DivMode) {
403        self.registers.ch[channel_number as usize]
404            .csr
405            .modify(match div_mode {
406                DivMode::FreeRunning => CSR::DIVMOD::FREE_RUNNING,
407                DivMode::High => CSR::DIVMOD::B_HIGH,
408                DivMode::Rising => CSR::DIVMOD::B_RISING,
409                DivMode::Falling => CSR::DIVMOD::B_FALLING,
410            });
411    }
412
413    // Set integral and fractional part of the clock divider
414    // RP 2040 uses a 8.4 fractional clock divider.
415    // The minimum value of the divider is   1 (int) +  0 / 16 (frac).
416    // The maximum value of the divider is 255 (int) + 15 / 16 (frac).
417    //
418    // **Note**: this method will do nothing if int == 0 || frac > 15.
419    fn set_divider_int_frac(&self, channel_number: ChannelNumber, int: u8, frac: u8) {
420        if int == 0 || frac > 15 {
421            return;
422        }
423        self.registers.ch[channel_number as usize]
424            .div
425            .modify(DIV::INT.val(int as u32));
426        self.registers.ch[channel_number as usize]
427            .div
428            .modify(DIV::FRAC.val(frac as u32));
429    }
430
431    // Set output pin A compare value
432    // If counter value < compare value A ==> pin A high
433    fn set_compare_value_a(&self, channel_number: ChannelNumber, cc_a: u16) {
434        self.registers.ch[channel_number as usize]
435            .cc
436            .modify(CC::A.val(cc_a as u32));
437    }
438
439    // Set output pin B compare value
440    // If counter value < compare value B ==> pin B high (if divmode == FreeRunning)
441    fn set_compare_value_b(&self, channel_number: ChannelNumber, cc_b: u16) {
442        self.registers.ch[channel_number as usize]
443            .cc
444            .modify(CC::B.val(cc_b as u32));
445    }
446
447    // Set compare values for both pins
448    fn set_compare_values_a_and_b(&self, channel_number: ChannelNumber, cc_a: u16, cc_b: u16) {
449        self.set_compare_value_a(channel_number, cc_a);
450        self.set_compare_value_b(channel_number, cc_b);
451    }
452
453    // Set counter top value
454    fn set_top(&self, channel_number: ChannelNumber, top: u16) {
455        self.registers.ch[channel_number as usize]
456            .top
457            .modify(TOP::TOP.val(top as u32));
458    }
459
460    // Get the current value of the counter
461    fn get_counter(&self, channel_number: ChannelNumber) -> u16 {
462        self.registers.ch[channel_number as usize]
463            .ctr
464            .read(CTR::CTR) as u16
465    }
466
467    // Set the value of the counter
468    fn set_counter(&self, channel_number: ChannelNumber, value: u16) {
469        self.registers.ch[channel_number as usize]
470            .ctr
471            .modify(CTR::CTR.val(value as u32));
472    }
473
474    fn wait_for(count: usize, f: impl Fn() -> bool) -> bool {
475        for _ in 0..count {
476            if f() {
477                return true;
478            }
479        }
480
481        false
482    }
483
484    // Increments the value of the counter
485    //
486    // The counter must be running at less than full speed. The method will return
487    // once the increment is complete.
488    fn advance_count(&self, channel_number: ChannelNumber) -> bool {
489        self.registers.ch[channel_number as usize]
490            .csr
491            .modify(CSR::PH_ADV::SET);
492        Self::wait_for(100, || {
493            self.registers.ch[channel_number as usize]
494                .csr
495                .read(CSR::PH_ADV)
496                == 0
497        })
498    }
499
500    // Retards the phase of the counter by 1 count
501    //
502    // The counter must be running. The method will return once the retardation
503    // is complete.
504    fn retard_count(&self, channel_number: ChannelNumber) -> bool {
505        self.registers.ch[channel_number as usize]
506            .csr
507            .modify(CSR::PH_RET::SET);
508        Self::wait_for(100, || {
509            self.registers.ch[channel_number as usize]
510                .csr
511                .read(CSR::PH_RET)
512                == 0
513        })
514    }
515
516    // Enable interrupt on the given PWM channel
517    fn enable_interrupt(&self, channel_number: ChannelNumber) {
518        // What about adding a new method to the register interface which performs
519        // a bitwise OR and another one for AND?
520        let mask = self.registers.inte.read(CH::CH);
521        self.registers
522            .inte
523            .modify(CH::CH.val(mask | 1 << channel_number as u32));
524    }
525
526    // Disable interrupt on the given PWM channel
527    fn disable_interrupt(&self, channel_number: ChannelNumber) {
528        let mask = self.registers.inte.read(CH::CH);
529        self.registers
530            .inte
531            .modify(CH::CH.val(mask & !(1 << channel_number as u32)));
532    }
533
534    // Enable multiple channel interrupts at once.
535    //
536    // Bits 0 to 7 ==> enable channel 0-7 interrupts.
537    fn enable_mask_interrupt(&self, mask: u8) {
538        let old_mask = self.registers.inte.read(CH::CH);
539        self.registers
540            .inte
541            .modify(CH::CH.val(old_mask | mask as u32));
542    }
543
544    // Disable multiple channel interrupts at once.
545    //
546    // Bits 0 to 7 ==> disable channel 0-7 interrupts.
547    fn disable_mask_interrupt(&self, mask: u8) {
548        let old_mask = self.registers.inte.read(CH::CH);
549        self.registers
550            .inte
551            .modify(CH::CH.val(old_mask & !mask as u32));
552    }
553
554    // Clear interrupt flag
555    fn clear_interrupt(&self, channel_number: ChannelNumber) {
556        self.registers
557            .intr
558            .write(CH::CH.val(1 << channel_number as u32));
559    }
560
561    // Force interrupt on the given channel
562    fn force_interrupt(&self, channel_number: ChannelNumber) {
563        let mask = self.registers.intf.read(CH::CH);
564        self.registers
565            .intf
566            .modify(CH::CH.val(mask | 1 << channel_number as u32));
567    }
568
569    // Unforce interrupt
570    fn unforce_interrupt(&self, channel_number: ChannelNumber) {
571        let mask = self.registers.intf.read(CH::CH);
572        self.registers
573            .intf
574            .modify(CH::CH.val(mask & !(1 << channel_number as u32)));
575    }
576
577    // Get interrupt status
578    fn get_interrupt_status(&self, channel_number: ChannelNumber) -> bool {
579        (self.registers.ints.read(CH::CH) & 1 << channel_number as u32) != 0
580    }
581
582    // Configure the given channel using the given configuration
583    fn configure_channel(&self, channel_number: ChannelNumber, config: &PwmChannelConfiguration) {
584        self.set_ph_correct(channel_number, config.ph_correct);
585        self.set_invert_polarity(channel_number, config.a_inv, config.b_inv);
586        self.set_div_mode(channel_number, config.divmode);
587        self.set_divider_int_frac(channel_number, config.int, config.frac);
588        self.set_compare_value_a(channel_number, config.cc_a);
589        self.set_compare_value_b(channel_number, config.cc_b);
590        self.set_top(channel_number, config.top);
591        self.set_enabled(channel_number, config.en);
592    }
593
594    // Initialize the struct
595    fn init(&self) {
596        let default_config: PwmChannelConfiguration = PwmChannelConfiguration::default();
597        for channel_number in CHANNEL_NUMBERS {
598            self.configure_channel(channel_number, &default_config);
599            self.set_counter(channel_number, 0);
600            self.disable_interrupt(channel_number);
601        }
602        self.registers.intr.write(CH::CH.val(0));
603    }
604
605    // This method should be called when resolving dependencies for the
606    // default peripherals. See [crate::chip::Rp2040DefaultPeripherals::resolve_dependencies]
607    pub(crate) fn set_clocks(&self, clocks: &'a clocks::Clocks) {
608        self.clocks.set(clocks);
609    }
610
611    // Given a channel number and a channel pin, return a struct that allows controlling it
612    fn new_pwm_pin(&'a self, channel_number: ChannelNumber, channel_pin: ChannelPin) -> PwmPin<'a> {
613        PwmPin {
614            pwm_struct: self,
615            channel_number,
616            channel_pin,
617        }
618    }
619
620    // Map the given GPIO to a PWM channel and a PWM pin
621    fn gpio_to_pwm(&self, gpio: RPGpio) -> (ChannelNumber, ChannelPin) {
622        (ChannelNumber::from(gpio), ChannelPin::from(gpio))
623    }
624
625    /// Map the GPIO to a PwmPin struct
626    ///
627    /// The returned structure can be used to control the PWM pin.
628    ///
629    /// See [PwmPin]
630    pub fn gpio_to_pwm_pin(&'a self, gpio: RPGpio) -> PwmPin<'a> {
631        let (channel_number, channel_pin) = self.gpio_to_pwm(gpio);
632        self.new_pwm_pin(channel_number, channel_pin)
633    }
634
635    // Helper function to compute top, int and frac values
636    // selected_freq_hz ==> user's desired frequency
637    //
638    // Return value: Ok(top, int, frac) in case of no error, otherwise Err(())
639    fn compute_top_int_frac(&self, selected_freq_hz: usize) -> Result<(u16, u8, u8), ()> {
640        let max_freq_hz = hil::pwm::Pwm::get_maximum_frequency_hz(self);
641        let threshold_freq_hz = max_freq_hz / hil::pwm::Pwm::get_maximum_duty_cycle(self);
642        // If the desired frequency doesn't make sense, return directly an error
643        if selected_freq_hz > max_freq_hz || selected_freq_hz == 0 {
644            return Err(());
645        }
646
647        // If the selected frequency is high enough, then there is no need for a divider
648        if selected_freq_hz > threshold_freq_hz {
649            return Ok(((max_freq_hz / selected_freq_hz - 1) as u16, 1, 0));
650        }
651        // If the selected frequency is below the threshold frequency, then a divider is necessary
652
653        // Set top to max
654        let top = u16::MAX;
655        // Get the corresponding integral part of the divider
656        let int = threshold_freq_hz / selected_freq_hz;
657        // If the desired frequency is too low, then it can't be achieved using the divider.
658        // In this case, notify the caller with an error.
659        if int >= 256 {
660            return Err(());
661        }
662        // Now that the integral part is valid, the fractional part can be computed as well.
663        // The fractional part is on 4 bits.
664        let frac = ((threshold_freq_hz << 4) / selected_freq_hz - (int << 4)) as u8;
665
666        // Return the final result
667        // Since int < 256, the cast will not truncate the value.
668        Ok((top, int as u8, frac))
669    }
670
671    // Starts a PWM pin with the given frequency and duty cycle.
672    //
673    // Note: the actual values may vary due to rounding errors.
674    fn start_pwm_pin(
675        &self,
676        channel_number: ChannelNumber,
677        channel_pin: ChannelPin,
678        frequency_hz: usize,
679        duty_cycle: usize,
680    ) -> Result<(), ErrorCode> {
681        let (top, int, frac) = match self.compute_top_int_frac(frequency_hz) {
682            Ok(result) => result,
683            Err(()) => return Result::from(ErrorCode::INVAL),
684        };
685
686        let max_duty_cycle = hil::pwm::Pwm::get_maximum_duty_cycle(self);
687        // Return an error if the selected duty cycle is higher than the maximum value
688        if duty_cycle > max_duty_cycle {
689            return Err(ErrorCode::INVAL);
690        }
691        // If top value is equal to u16::MAX, then it is impossible to
692        // have a 100% duty cycle, so an error will be returned.
693        let compare_value = if duty_cycle == max_duty_cycle {
694            if top == u16::MAX {
695                return Result::from(ErrorCode::INVAL);
696            } else {
697                // counter compare value for 100% glitch-free duty cycle
698                top + 1
699            }
700        } else {
701            // Normally, no overflow should occur if duty_cycle is less than or
702            // equal to get_maximum_duty_cycle(). It is in user's responsability to
703            // ensure the value is valid.
704            ((top as usize + 1) * duty_cycle / max_duty_cycle) as u16
705        };
706
707        // Configure the channel accordingly
708        self.set_top(channel_number, top);
709        self.set_divider_int_frac(channel_number, int, frac);
710        // Configure the pin accordingly
711        if channel_pin == ChannelPin::A {
712            self.set_compare_value_a(channel_number, compare_value);
713        } else {
714            self.set_compare_value_b(channel_number, compare_value);
715        }
716        // Finally, enable the channel
717        self.set_enabled(channel_number, true);
718        Ok(())
719    }
720
721    // Stop a PWM channel.
722    //
723    // This method does nothing if the PWM channel was already disabled.
724    //
725    // Note that disabling a PWM channel may result in disabling multiple PWM pins.
726    fn stop_pwm_channel(&self, channel_number: ChannelNumber) -> Result<(), ErrorCode> {
727        self.set_enabled(channel_number, false);
728        Ok(())
729    }
730}
731
732/// Implementation of the Hardware Interface Layer (HIL)
733impl hil::pwm::Pwm for Pwm<'_> {
734    type Pin = RPGpio;
735
736    /// Start a PWM pin
737    ///
738    /// Start the given PWM pin with the given frequency and the given duty cycle.
739    /// The actual values may vary due to rounding errors. For high precision duty cycles,
740    /// the frequency should be set less than:
741    ///
742    /// ```rust,ignore
743    /// let threshold_freq = pwm_struct.get_maximum_frequency_hz() / pwm_struct.get_maximum_duty_cycle()
744    /// ```
745    ///
746    /// ## Errors
747    ///
748    /// This method may fail in one of the following situations:
749    ///
750    /// + selected frequency and duty cycle higher than the maximum possible values
751    /// + 100% duty cycle demand for low frequencies (close to or below threshold_freq)
752    /// + very low frequencies
753    ///
754    /// ## Safety
755    ///
756    /// It is safe to call multiples times this method with different values while the pin is
757    /// running.
758    ///
759    /// **Note**: the pin must be set as a PWM pin prior to calling this method.
760    fn start(
761        &self,
762        pin: &Self::Pin,
763        frequency_hz: usize,
764        duty_cycle: usize,
765    ) -> Result<(), ErrorCode> {
766        let (channel_number, channel_pin) = self.gpio_to_pwm(*pin);
767        self.start_pwm_pin(channel_number, channel_pin, frequency_hz, duty_cycle)
768    }
769
770    /// Stop the given pin
771    ///
772    /// ## Errors
773    ///
774    /// This method may never fail.
775    ///
776    /// ## Safety
777    ///
778    /// It is safe to call this method multiple times on the same pin. If the pin is already
779    /// stopped, then it does nothing.
780    fn stop(&self, pin: &Self::Pin) -> Result<(), ErrorCode> {
781        let (channel_number, _) = self.gpio_to_pwm(*pin);
782        self.stop_pwm_channel(channel_number)
783    }
784
785    /// Return the maximum value of the frequency in Hz
786    ///
787    /// ## Panics
788    ///
789    /// This method will panic if the dependencies are not resolved.
790    fn get_maximum_frequency_hz(&self) -> usize {
791        self.clocks
792            .unwrap_or_panic()
793            .get_frequency(clocks::Clock::System) as usize
794    }
795
796    /// Return an opaque value representing 100% duty cycle
797    fn get_maximum_duty_cycle(&self) -> usize {
798        u16::MAX as usize + 1
799    }
800}
801
802/// Helper structure to control a PWM pin
803pub struct PwmPin<'a> {
804    pwm_struct: &'a Pwm<'a>,
805    channel_number: ChannelNumber,
806    channel_pin: ChannelPin,
807}
808
809impl PwmPin<'_> {
810    /// Returns the PWM channel the pin belongs to
811    pub fn get_channel_number(&self) -> ChannelNumber {
812        self.channel_number
813    }
814
815    /// Returns the PWM pin the pin belongs to
816    pub fn get_channel_pin(&self) -> ChannelPin {
817        self.channel_pin
818    }
819
820    // See [Pwm::set_invert_polarity_a] and [Pwm::set_invert_polarity_b]
821    fn set_invert_polarity(&self, inv: bool) {
822        if self.channel_pin == ChannelPin::A {
823            self.pwm_struct
824                .set_invert_polarity_a(self.channel_number, inv);
825        } else {
826            self.pwm_struct
827                .set_invert_polarity_b(self.channel_number, inv);
828        }
829    }
830
831    // See [Pwm::set_compare_value_a] and [Pwm::set_compare_value_b]
832    fn set_compare_value(&self, compare_value: u16) {
833        if self.channel_pin == ChannelPin::A {
834            self.pwm_struct
835                .set_compare_value_a(self.channel_number, compare_value);
836        } else {
837            self.pwm_struct
838                .set_compare_value_b(self.channel_number, compare_value);
839        }
840    }
841}
842
843impl hil::pwm::PwmPin for PwmPin<'_> {
844    /// Same as Pwm::start
845    fn start(&self, frequency_hz: usize, duty_cycle: usize) -> Result<(), ErrorCode> {
846        self.pwm_struct.start_pwm_pin(
847            self.channel_number,
848            self.channel_pin,
849            frequency_hz,
850            duty_cycle,
851        )
852    }
853
854    /// Same as Pwm::stop
855    fn stop(&self) -> Result<(), ErrorCode> {
856        self.pwm_struct.stop_pwm_channel(self.channel_number)
857    }
858
859    /// Same as Pwm::get_maximum_frequency_hz
860    fn get_maximum_frequency_hz(&self) -> usize {
861        hil::pwm::Pwm::get_maximum_frequency_hz(self.pwm_struct)
862    }
863
864    /// Same as Pwm::get_maximum_duty_cycle
865    fn get_maximum_duty_cycle(&self) -> usize {
866        hil::pwm::Pwm::get_maximum_duty_cycle(self.pwm_struct)
867    }
868}
869
870/// Unit tests
871///
872/// This module provides unit tests for the PWM driver.
873///
874/// To run the tests, add the following line before loading processes:
875///
876/// ```rust,ignore
877/// rp2040::pwm::unit_tests::run::(&peripherals.pwm);
878/// ```
879///
880/// Compile and flash the kernel on the board. Then, connect to UART on GPIOs 1 and 2.
881/// If everything goes right, the following output should be displayed:
882///
883/// ```txt
884/// Testing ChannelNumber enum...
885/// ChannelNumber enum OK
886/// Testing ChannelPin enum...
887/// ChannelPin enum OK
888/// Testing PWM struct...
889/// Starting testing channel 1...
890/// Channel 1 works!
891/// Starting testing channel 2...
892/// Channel 2 works!
893/// Starting testing channel 3...
894/// Channel 3 works!
895/// Starting testing channel 4...
896/// Channel 4 works!
897/// Starting testing channel 5...
898/// Channel 5 works!
899/// Starting testing channel 6...
900/// Channel 6 works!
901/// Starting testing channel 7...
902/// Channel 7 works!
903/// PWM struct OK
904/// Testing PwmPinStruct...
905/// PwmPin struct OK
906/// Testing PWM HIL trait...
907/// PWM HIL trait OK
908/// ```
909
910pub mod unit_tests {
911    use super::{
912        debug, hil, ChannelNumber, ChannelPin, DivMode, Pwm, RPGpio, Readable, CC, CH, CSR, CTR,
913        DIV, TOP,
914    };
915
916    fn test_channel_number() {
917        debug!("Testing ChannelNumber enum...");
918        assert_eq!(ChannelNumber::from(RPGpio::GPIO0), ChannelNumber::Ch0);
919        assert_eq!(ChannelNumber::from(RPGpio::GPIO3), ChannelNumber::Ch1);
920        assert_eq!(ChannelNumber::from(RPGpio::GPIO14), ChannelNumber::Ch7);
921        assert_eq!(ChannelNumber::from(RPGpio::GPIO28), ChannelNumber::Ch6);
922        debug!("ChannelNumber enum OK");
923    }
924
925    fn test_channel_pin() {
926        debug!("Testing ChannelPin enum...");
927        assert_eq!(ChannelPin::from(RPGpio::GPIO4), ChannelPin::A);
928        assert_eq!(ChannelPin::from(RPGpio::GPIO5), ChannelPin::B);
929        debug!("ChannelPin enum OK");
930    }
931
932    fn test_channel(pwm: &Pwm, channel_number: ChannelNumber) {
933        debug!("Starting testing channel {}...", channel_number as usize);
934
935        // Testing set_enabled()
936        pwm.set_enabled(channel_number, true);
937        assert_eq!(
938            pwm.registers.ch[channel_number as usize].csr.read(CSR::EN),
939            1
940        );
941        pwm.set_enabled(channel_number, false);
942        assert_eq!(
943            pwm.registers.ch[channel_number as usize].csr.read(CSR::EN),
944            0
945        );
946
947        // Testing set_ph_correct()
948        pwm.set_ph_correct(channel_number, true);
949        assert_eq!(
950            pwm.registers.ch[channel_number as usize]
951                .csr
952                .read(CSR::PH_CORRECT),
953            1
954        );
955        pwm.set_ph_correct(channel_number, false);
956        assert_eq!(
957            pwm.registers.ch[channel_number as usize]
958                .csr
959                .read(CSR::PH_CORRECT),
960            0
961        );
962
963        // Testing set_invert_polarity()
964        pwm.set_invert_polarity(channel_number, true, true);
965        assert_eq!(
966            pwm.registers.ch[channel_number as usize]
967                .csr
968                .read(CSR::A_INV),
969            1
970        );
971        assert_eq!(
972            pwm.registers.ch[channel_number as usize]
973                .csr
974                .read(CSR::B_INV),
975            1
976        );
977        pwm.set_invert_polarity(channel_number, true, false);
978        assert_eq!(
979            pwm.registers.ch[channel_number as usize]
980                .csr
981                .read(CSR::A_INV),
982            1
983        );
984        assert_eq!(
985            pwm.registers.ch[channel_number as usize]
986                .csr
987                .read(CSR::B_INV),
988            0
989        );
990        pwm.set_invert_polarity(channel_number, false, true);
991        assert_eq!(
992            pwm.registers.ch[channel_number as usize]
993                .csr
994                .read(CSR::A_INV),
995            0
996        );
997        assert_eq!(
998            pwm.registers.ch[channel_number as usize]
999                .csr
1000                .read(CSR::B_INV),
1001            1
1002        );
1003        pwm.set_invert_polarity(channel_number, false, false);
1004        assert_eq!(
1005            pwm.registers.ch[channel_number as usize]
1006                .csr
1007                .read(CSR::A_INV),
1008            0
1009        );
1010        assert_eq!(
1011            pwm.registers.ch[channel_number as usize]
1012                .csr
1013                .read(CSR::B_INV),
1014            0
1015        );
1016
1017        // Testing set_div_mode()
1018        pwm.set_div_mode(channel_number, DivMode::FreeRunning);
1019        assert_eq!(
1020            pwm.registers.ch[channel_number as usize]
1021                .csr
1022                .read(CSR::DIVMOD),
1023            DivMode::FreeRunning as u32
1024        );
1025        pwm.set_div_mode(channel_number, DivMode::High);
1026        assert_eq!(
1027            pwm.registers.ch[channel_number as usize]
1028                .csr
1029                .read(CSR::DIVMOD),
1030            DivMode::High as u32
1031        );
1032        pwm.set_div_mode(channel_number, DivMode::Rising);
1033        assert_eq!(
1034            pwm.registers.ch[channel_number as usize]
1035                .csr
1036                .read(CSR::DIVMOD),
1037            DivMode::Rising as u32
1038        );
1039        pwm.set_div_mode(channel_number, DivMode::Falling);
1040        assert_eq!(
1041            pwm.registers.ch[channel_number as usize]
1042                .csr
1043                .read(CSR::DIVMOD),
1044            DivMode::Falling as u32
1045        );
1046
1047        // Testing set_divider_int_frac()
1048        pwm.set_divider_int_frac(channel_number, 123, 4);
1049        assert_eq!(
1050            pwm.registers.ch[channel_number as usize].div.read(DIV::INT),
1051            123
1052        );
1053        assert_eq!(
1054            pwm.registers.ch[channel_number as usize]
1055                .div
1056                .read(DIV::FRAC),
1057            4
1058        );
1059
1060        // Testing set_compare_value() methods
1061        pwm.set_compare_value_a(channel_number, 2022);
1062        assert_eq!(
1063            pwm.registers.ch[channel_number as usize].cc.read(CC::A),
1064            2022
1065        );
1066        pwm.set_compare_value_b(channel_number, 12);
1067        assert_eq!(pwm.registers.ch[channel_number as usize].cc.read(CC::B), 12);
1068        pwm.set_compare_values_a_and_b(channel_number, 2023, 1);
1069        assert_eq!(
1070            pwm.registers.ch[channel_number as usize].cc.read(CC::A),
1071            2023
1072        );
1073        assert_eq!(pwm.registers.ch[channel_number as usize].cc.read(CC::B), 1);
1074
1075        // Testing set_top()
1076        pwm.set_top(channel_number, 12345);
1077        assert_eq!(
1078            pwm.registers.ch[channel_number as usize].top.read(TOP::TOP),
1079            12345
1080        );
1081
1082        // Testing get_counter() and set_counter()
1083        pwm.set_counter(channel_number, 1);
1084        assert_eq!(
1085            pwm.registers.ch[channel_number as usize].ctr.read(CTR::CTR),
1086            1
1087        );
1088        assert_eq!(pwm.get_counter(channel_number), 1);
1089
1090        // Testing advance_count and retard_count()
1091        // The counter must be running to pass retard_count()
1092        // The counter must run at less than full speed (div_int + div_frac / 16 > 1) to pass
1093        // advance_count()
1094        pwm.set_div_mode(channel_number, DivMode::FreeRunning);
1095        assert!(pwm.advance_count(channel_number));
1096        assert_eq!(pwm.get_counter(channel_number), 2);
1097        pwm.set_enabled(channel_number, true);
1098        // No assert for retard count since it is impossible to predict how much the counter
1099        // will advance while running. However, the fact that the function returns true is a
1100        // good indicator that it does its job.
1101        assert!(pwm.retard_count(channel_number));
1102        // Disabling PWM to prevent it from generating interrupts signals for next tests
1103        pwm.set_enabled(channel_number, false);
1104
1105        // Testing enable_interrupt() and disable_interrupt()
1106        pwm.enable_interrupt(channel_number);
1107        assert_eq!(
1108            pwm.registers.inte.read(CH::CH),
1109            1 << (channel_number as u32)
1110        );
1111        pwm.disable_interrupt(channel_number);
1112        assert_eq!(pwm.registers.inte.read(CH::CH), 0);
1113
1114        // Testing get_interrupt_status()
1115        pwm.enable_interrupt(channel_number);
1116        pwm.set_counter(channel_number, 12345);
1117        pwm.advance_count(channel_number);
1118        assert!(pwm.get_interrupt_status(channel_number));
1119        pwm.disable_interrupt(channel_number);
1120
1121        // Testing clear_interrupt()
1122        pwm.clear_interrupt(channel_number);
1123        assert!(!pwm.get_interrupt_status(channel_number));
1124
1125        // Testing force_interrupt(), unforce_interrupt()
1126        pwm.force_interrupt(channel_number);
1127        assert_eq!(
1128            pwm.registers.intf.read(CH::CH),
1129            1 << (channel_number as u32)
1130        );
1131        assert!(pwm.get_interrupt_status(channel_number));
1132        pwm.unforce_interrupt(channel_number);
1133        assert_eq!(pwm.registers.intf.read(CH::CH), 0);
1134        assert!(!pwm.get_interrupt_status(channel_number));
1135
1136        debug!("Channel {} works!", channel_number as usize);
1137    }
1138
1139    fn test_pwm_struct(pwm: &Pwm) {
1140        debug!("Testing PWM struct...");
1141        let channel_number_list = [
1142            // Pins 0 and 1 are kept available for UART
1143            ChannelNumber::Ch1,
1144            ChannelNumber::Ch2,
1145            ChannelNumber::Ch3,
1146            ChannelNumber::Ch4,
1147            ChannelNumber::Ch5,
1148            ChannelNumber::Ch6,
1149            ChannelNumber::Ch7,
1150        ];
1151
1152        // Testing enable_mask_interrupt() and disable_mask_interrupt()
1153        pwm.enable_mask_interrupt(u8::MAX);
1154        assert_eq!(pwm.registers.inte.read(CH::CH), u8::MAX as u32);
1155        pwm.disable_mask_interrupt(u8::MAX);
1156        assert_eq!(pwm.registers.inte.read(CH::CH), 0);
1157
1158        for channel_number in channel_number_list {
1159            test_channel(pwm, channel_number);
1160        }
1161        debug!("PWM struct OK");
1162    }
1163
1164    fn test_pwm_pin_struct<'a>(pwm: &'a Pwm<'a>) {
1165        debug!("Testing PwmPin struct...");
1166        let pwm_pin = pwm.gpio_to_pwm_pin(RPGpio::GPIO13);
1167        assert_eq!(pwm_pin.get_channel_number(), ChannelNumber::Ch6);
1168        assert_eq!(pwm_pin.get_channel_pin(), ChannelPin::B);
1169
1170        pwm_pin.set_invert_polarity(true);
1171        assert_eq!(
1172            pwm.registers.ch[pwm_pin.get_channel_number() as usize]
1173                .csr
1174                .read(CSR::B_INV),
1175            1
1176        );
1177        pwm_pin.set_invert_polarity(false);
1178        assert_eq!(
1179            pwm.registers.ch[pwm_pin.get_channel_number() as usize]
1180                .csr
1181                .read(CSR::B_INV),
1182            0
1183        );
1184
1185        pwm_pin.set_compare_value(987);
1186        assert_eq!(
1187            pwm.registers.ch[pwm_pin.get_channel_number() as usize]
1188                .cc
1189                .read(CC::B),
1190            987
1191        );
1192        debug!("PwmPin struct OK");
1193    }
1194
1195    fn test_pwm_trait(pwm: &Pwm) {
1196        debug!("Testing PWM HIL trait...");
1197        let max_freq_hz = hil::pwm::Pwm::get_maximum_frequency_hz(pwm);
1198        let max_duty_cycle = hil::pwm::Pwm::get_maximum_duty_cycle(pwm);
1199
1200        let (top, int, frac) = pwm.compute_top_int_frac(max_freq_hz).unwrap();
1201        assert_eq!(top, 0);
1202        assert_eq!(int, 1);
1203        assert_eq!(frac, 0);
1204
1205        let (top, int, frac) = pwm.compute_top_int_frac(max_freq_hz / 4).unwrap();
1206        assert_eq!(top, 3);
1207        assert_eq!(int, 1);
1208        assert_eq!(frac, 0);
1209
1210        let (top, int, frac) = pwm
1211            .compute_top_int_frac(max_freq_hz / max_duty_cycle)
1212            .unwrap();
1213        assert_eq!(top, u16::MAX);
1214        assert_eq!(int, 1);
1215        assert_eq!(frac, 0);
1216
1217        let (top, int, frac) = pwm
1218            .compute_top_int_frac(max_freq_hz / max_duty_cycle / 2)
1219            .unwrap();
1220        assert_eq!(top, u16::MAX);
1221        assert_eq!(int, 2);
1222        assert_eq!(frac, 0);
1223
1224        let freq = ((max_freq_hz / max_duty_cycle) as f32 / 2.5) as usize;
1225        let (top, int, frac) = pwm.compute_top_int_frac(freq).unwrap();
1226        assert_eq!(top, u16::MAX);
1227        assert_eq!(int, 2);
1228        assert_eq!(frac, 8);
1229
1230        let freq = ((max_freq_hz / max_duty_cycle) as f32 / 3.15) as usize;
1231        let (top, int, frac) = pwm.compute_top_int_frac(freq).unwrap();
1232        assert_eq!(top, u16::MAX);
1233        assert_eq!(int, 3);
1234        assert_eq!(frac, 2);
1235
1236        assert!(pwm
1237            .compute_top_int_frac(max_freq_hz / max_duty_cycle / 256)
1238            .is_err());
1239        assert!(pwm.compute_top_int_frac(max_freq_hz + 1).is_err());
1240
1241        let (channel_number, channel_pin) = pwm.gpio_to_pwm(RPGpio::GPIO24);
1242        assert!(pwm
1243            .start_pwm_pin(channel_number, channel_pin, max_freq_hz / 4, 0)
1244            .is_ok());
1245        assert_eq!(pwm.registers.ch[channel_number as usize].cc.read(CC::A), 0);
1246
1247        assert!(pwm
1248            .start_pwm_pin(
1249                channel_number,
1250                channel_pin,
1251                max_freq_hz / 4,
1252                max_duty_cycle / 4 * 3
1253            )
1254            .is_ok());
1255        assert_eq!(pwm.registers.ch[channel_number as usize].cc.read(CC::A), 3);
1256
1257        assert!(pwm
1258            .start_pwm_pin(channel_number, channel_pin, max_freq_hz / 4, max_duty_cycle)
1259            .is_ok());
1260        assert_eq!(pwm.registers.ch[channel_number as usize].cc.read(CC::A), 4);
1261
1262        assert!(pwm
1263            .start_pwm_pin(
1264                channel_number,
1265                channel_pin,
1266                max_freq_hz / max_duty_cycle,
1267                max_duty_cycle
1268            )
1269            .is_err());
1270        assert!(pwm
1271            .start_pwm_pin(channel_number, channel_pin, max_freq_hz + 1, max_duty_cycle)
1272            .is_err());
1273        assert!(pwm
1274            .start_pwm_pin(channel_number, channel_pin, max_freq_hz, max_duty_cycle + 1)
1275            .is_err());
1276        debug!("PWM HIL trait OK")
1277    }
1278
1279    /// Run all unit tests
1280    ///
1281    /// pwm must be initialized and its dependencies resolved.
1282    pub fn run<'a>(pwm: &'a Pwm<'a>) {
1283        test_channel_number();
1284        test_channel_pin();
1285        test_pwm_struct(pwm);
1286        test_pwm_pin_struct(pwm);
1287        test_pwm_trait(pwm);
1288    }
1289}