Skip to content

PWM

4.5. PWM

4.5.1. Overview

Pulse width modulation (PWM) is a scheme where a digital signal provides a smoothly varying average voltage. This is achieved with positive pulses of some controlled width, at regular intervals. The fraction of time spent high is known as the duty cycle. This may be used to approximate an analog output, or control switchmode power electronics.

The RP2040 PWM block has 8 identical slices. Each slice can drive two PWM output signals, or measure the frequency or duty cycle of an input signal. This gives a total of up to 16 controllable PWM outputs. All 30 GPIO pins can be driven by the PWM block.

521

4.5. PWM

RP2040 Datasheet

Figure 103. A single PWM slice. A 16-bit counter counts from 0 up to some programmed value, and then wraps to zero, or counts back down again, depending on PWM mode. The A and B outputs transition high and low based on the current count value and the preprogrammed A and B thresholds. The counter advances based on a number of events: it may be freerunning, or gated by level or edge of an input signal on the B pin. A fractional divider slows the overall count rate for finer control of output frequency.

==> picture [382 x 134] intentionally omitted <==

Each PWM slice is equipped with the following:

  • [16-bit counter]

  • [8.4 fractional clock divider]

  • [Two independent output channels, duty cycle from 0% to 100% ] [inclusive]

  • [Dual slope and trailing edge modulation]

  • [Edge-sensitive input mode for frequency measurement]

  • [Level-sensitive input mode for duty cycle measurement]

  • [Configurable counter wrap value]

  • [Wrap and level registers are double buffered and can be changed race-free while PWM is running]

  • [Interrupt request and DMA request on counter wrap]

  • [Phase can be precisely advanced or retarded while running (increments of one count)]

Slices can be enabled or disabled simultaneously via a single, global control register. The slices then run in perfect lockstep, so that more complex power circuitry can be switched by the outputs of multiple slices.

4.5.2. Programmer’s Model

All 30 GPIO pins on RP2040 can be used for PWM:

Table 515. Mapping of PWM channels to GPIO pins on RP2040. This is also shown in the main GPIO function table, Table 279

GPIO 0 1 2
3
4 5 6 7 8 9
1
0 11 12
13 14 15
PWM Channel 0A 0B 1A
1
B
2A
2B 3A 3B 4A 4B
5
A 5B 6A
6B 7A 7B
GPIO 16 17 18
1
9
20
21 22 23 24 25
2
6 27 28
29
PWM Channel 0A 0B 1A
1
B
2A
2B 3A 3B 4A 4B
5
A 5B 6A
6B
  • [The 16 PWM channels (8 2-channel slices) appear on GPIO0 to GPIO15, in the order PWM0 A, PWM0 B, PWM1 A…]

  • [This repeats for GPIO16 to GPIO29. GPIO16 is PWM0 A, GPIO17 is PWM0 B, so on up to PWM6 B on GPIO29]

  • [The same PWM output can be selected on two GPIO pins; the same signal will appear on each GPIO.]

  • [If a PWM B pin is used as an input, and is selected on multiple GPIO pins, then the PWM slice will see the logical] OR of those two GPIO inputs

4.5.2.1. Pulse Width Modulation

The PWM hardware functions by continuously comparing the input value to a free-running counter. This produces a toggling output where the amount of time spent at the high output level is proportional to the input value. The fraction of time spent at the high signal level is known as the duty cycle of the signal.

522

4.5. PWM

RP2040 Datasheet

The counting period is controlled by the TOP register, with a maximum possible period of 65536 cycles, as the counter and TOP are 16 bits in size. The input values are configured via the CC register.

==> picture [484 x 232] intentionally omitted <==

----- Start of picture text -----
Figure 104. The
counter repeatedly Input (Count)
Count
counts from 0 to TOP,
TOP
forming a sawtooth Counter compare level
shape. The counter is Counter
continuously
compared with some
TOP/3
input value. When the
input value is higherthan the counter, the 0 T 2T 3T t
output is driven high.
Otherwise, the output Output (Pulse)
is low. The output V
IOVDD
period T is defined by GPIO pulse output
the TOP value of the
counter, and how fast
the counter is
configured to count.
The voltage, as a fraction average output 0 T 2T 3T t
of the IO power
supply, is the input
value divided by the This example shows the counting period and the A and B counter compare levels being configured on one of RP2040’s
counter period (TOP + PWM slices.
1)
----- End of picture text -----

Pico Examples: https://github.com/raspberrypi/pico-examples/blob/master/pwm/hello_pwm/hello_pwm.c Lines 14 - 29

14 // Tell GPIO 0 and 1 they are allocated to the PWM 15 gpio_set_function(0, GPIO_FUNC_PWM); 16 gpio_set_function(1, GPIO_FUNC_PWM); 17 18 // Find out which PWM slice is connected to GPIO 0 (it's slice 0) 19 uint slice_num = pwm_gpio_to_slice_num(0); 20 21 // Set period of 4 cycles (0 to 3 inclusive) 22 pwm_set_wrap(slice_num, 3); 23 // Set channel A output high for one cycle before dropping 24 pwm_set_chan_level(slice_num, PWM_CHAN_A, 1); 25 // Set initial B output high for three cycles before dropping 26 pwm_set_chan_level(slice_num, PWM_CHAN_B, 3); 27 // Set the PWM running 28 pwm_set_enabled(slice_num, true);

Figure 105 shows how the PWM hardware operates once it has been configured in this way.

523

4.5. PWM

RP2040 Datasheet

Figure 105. The slice counts repeatedly from 0 to 3, which is configured as the TOP value. The output waves therefore have a period of 4. Output A is high for 1 cycle in 4, so the average output voltage is 1/4 of the IO supply voltage. Output B is high for 3 cycles in every 4. Note the rising edges of A and B are always aligned.

Figure 106. In phasecorrect mode, the counter counts back down from TOP to 0 once it reaches TOP.

==> picture [297 x 48] intentionally omitted <==

----- Start of picture text -----
Count 0 1 2 3 0 1 2 3 0 1 2 3
A
B
----- End of picture text -----

The default behaviour of a PWM slice is to count upward until the value of the TOP register is reached, and then immediately wrap to 0. PWM slices also offer a phase-correct mode, enabled by setting CSR_PH_CORRECT to 1, where the counter starts to count downward after reaching TOP, until it reaches 0 again.

It is called phase-correct mode because the pulse is always centred on the same point, no matter the duty cycle. In other words, its phase is not a function of duty cycle. The output frequency is halved when phase-correct mode is enabled.

==> picture [297 x 192] intentionally omitted <==

----- Start of picture text -----
Input (Count)
Count
TOP
Counter compare level
Counter
TOP/3
0 T 2T 3T t
Output (Pulse)
V
IOVDD
GPIO pulse output
0 T 2T 3T t
----- End of picture text -----

4.5.2.2. 0% and 100% Duty Cycle

The RP2040 PWM can produce toggle-free 0% and 100% duty cycle output.

==> picture [356 x 192] intentionally omitted <==

----- Start of picture text -----
Figure 107. Glitch-free
0% duty cycle output Input (Count)
Count
for CC = 0, and glitch-
TOP
free 100% duty cycle Counter compare level
output for CC = TOP + Counter
1
0 T 2T 3T t
Output (Pulse)
V
IOVDD
GPIO pulse output
0 T 2T 3T t
----- End of picture text -----

A CC value of 0 will produce a 0% output, i.e. the output signal is always low. A CC value of TOP + 1 (i.e. equal to the period, in non-phase-correct mode) will produce a 100% output. For example, if TOP is programmed to 254, the counter will have a period of 255 cycles, and CC values in the range of 0 to 255 inclusive will produce duty cycles in the range 0% to 100% inclusive.

Glitch-free output at 0% and 100% is important e.g. to avoid switching losses when a MOSFET is controlled at its minimum and maximum current levels.

524

4.5. PWM

RP2040 Datasheet

4.5.2.3. Double Buffering

Figure 108 shows how a change in input value will produce a change in output duty cycle. This can be used to approximate some analog waveform such as a sine wave.

==> picture [356 x 192] intentionally omitted <==

----- Start of picture text -----
Figure 108. The input
value varies with each Input (Count)
Count
counter period: first
TOP
TOP / 3, then 2 × TOP Counter compare level
/ 3, and finally TOP + 1 Counter
2×TOP/3
for 100% duty cycle.
Each increase in the
TOP/3
input value causes a
correspondingincrease in the output 0 T 2T 3T t
duty cycle.
Output (Pulse)
V
IOVDD
GPIO pulse output
0 T/3 T 5T/3 2T 3T t
----- End of picture text -----

In Figure 108, the input value only changes at the instant where the counter wraps through 0. Figure 109 shows what happens if the input value is allowed to change at any other time: an unwanted glitch is produced at the output.

Figure 109. The input value changes whilst the counter is midramp. This produces additional toggling at the output.

==> picture [297 x 192] intentionally omitted <==

----- Start of picture text -----
Input (Count)
Count
TOP
Counter compare level
2×TOP/3 Counter
TOP/3
0 T 2T 3T t
Output (Pulse)
V
IOVDD
GPIO pulse output
0 T/3 T 5T/3 2T 3T t
----- End of picture text -----

The behaviour becomes even more perplexing if the TOP register is also modified. It would be difficult for software to write to CC or TOP with the correct timing. To solve this, each slice has two copies of the CC and TOP registers: one copy which software can modify, and another, internal copy which is updated from the first register at the instant the counter wraps. Software can modify its copy of the register at will, but the changes are not captured by the PWM output until the next wrap.

Figure 110 shows the sequence of events where a software interrupt handler changes the value of CC_A each time the counter wraps.

525

4.5. PWM

RP2040 Datasheet

Figure 110. Each counter wrap causes the interrupt request signal to assert. The processor enters its interrupt handler, writes to its copy of the CC register, and clears the interrupt. When the counter wraps again, the latched version of the CC register is instantaneously updated with the most recent value written by software, and this value controls the duty cycle for the next period. The IRQ is reasserted so that software can write another fresh value to its copy of the CC register.

==> picture [297 x 64] intentionally omitted <==

----- Start of picture text -----
Counter at top
IRQ
CC_A 0 1 2 3
CC_A latched 0 1 2
----- End of picture text -----

There is no limitation on what values can be written to CC or TOP, or when they are written. In normal PWM mode (CSR_PH_CORRECT is 0) the latched copies are updated when the counter wraps to 0, which occurs once every TOP + 1 cycles. In phase-correct mode (CSR_PH_CORRECT is 1), the latched copies are updated on the 0 to 0 count transition, i.e. the point where the counter stops counting downward and begins to count upward again.

4.5.2.4. Clock Divider

Each slice has a fractional clock divider, configured by the DIV register. This is an 8 integer bit, 4 fractional bit clock divider, which allows the count rate to be slowed by up to a factor of 256. The clock divider allows much lower output frequencies to be achieved — approximately 7.5Hz from a 125MHz system clock. Lower frequencies than this will require a system timer interrupt (Section 4.6)

It does this by generating an enable signal which gates the operation of the counter.

Figure 111. The clock divider generates an enable signal. The counter only counts on cycles where this signal is high. A clock divisor of 1 causes the enable to be asserted on every cycle, so the counter counts by one on every system clock cycle. Higher divisors cause the count enable to be asserted less frequently. Fractional division achieves an average fractional counting rate by spacing some enable pulses further apart than others.

==> picture [297 x 161] intentionally omitted <==

----- Start of picture text -----
DIV_INT 1
DIV_FRAC .0
Counter enable
DIV_INT 3
DIV_FRAC .0
Counter enable
DIV_INT 2
DIV_FRAC .5
Counter enable
----- End of picture text -----

The fractional divider is a first-order delta-sigma type.

The clock divider also allows the effective count range to be extended, when using level-sensitive or edge-sensitive modes to take duty cycle or frequency measurements.

4.5.2.5. Level-sensitive and Edge-sensitive Triggering

526

4.5. PWM

RP2040 Datasheet

==> picture [484 x 174] intentionally omitted <==

----- Start of picture text -----
Figure 112. PWM slice
Event select Phase Phase
event selection. The Advance Retard
counter advances
when its enable input 1
is high, and this
enable is generated in Input
two sequential stages. (pin B) Fractional Clock Count
EN
First, any one of four Divider (8.4) enable
event types (always Rising edge
on, pin B high, pin B
rise, pin B fall) can Falling edge
generate enable
pulses for the
fractional clock
divider. The divider
can reduce the rate of By default, each slice’s counter is free-running, and will count continuously whenever the slice is enabled. There are
the enable pulses, three other options available:
before passing them
on to the counter. • [[Count continuously when a high level is detected on the B pin]]
----- End of picture text -----

  • [[Count continuously when a high level is detected on the B pin]]

  • [Count once with each rising edge detected on the B pin]

  • [Count once with each falling edge detected on the B pin]

These modes are selected by the DIVMODE field in each slice’s CSR. In free-running mode, the A and B pins are both outputs. In any other mode, the B pin becomes an input, and controls the operation of the counter. CC_B is ignored when not in free-running mode.

By allowing the slice to run for a fixed amount of time in level-sensitive or edge-sensitive mode, it’s possible to measure the duty cycle or frequency of an input signal. Due to the type of edge-detect circuit used, the low period and high period of the measured signal must both be strictly greater than the system clock period when taking frequency measurements.

The clock divider is still operational in level-sensitive and edge-sensitive mode. At maximum division (writing 0 to DIV_INT), the counter will only advance once per 256 high input cycles in level-sensitive modes, or once per 256 edges in edge-sensitive mode. This allows longer-running measurements to be taken, although the resolution is still just 16 bits.

Pico Examples: https://github.com/raspberrypi/pico-examples/blob/master/pwm/measure_duty_cycle/measure_duty_cycle.c Lines 19 - 37

19 float measure_duty_cycle(uint gpio) { 20 // Only the PWM B pins can be used as inputs. 21 assert(pwm_gpio_to_channel(gpio) == PWM_CHAN_B); 22 uint slice_num = pwm_gpio_to_slice_num(gpio); 23 24 // Count once for every 100 cycles the PWM B input is high 25 pwm_config cfg = pwm_get_default_config(); 26 pwm_config_set_clkdiv_mode(&cfg, PWM_DIV_B_HIGH); 27 pwm_config_set_clkdiv(&cfg, 100); 28 pwm_init(slice_num, &cfg, false); 29 gpio_set_function(gpio, GPIO_FUNC_PWM); 30 31 pwm_set_enabled(slice_num, true); 32 sleep_ms(10); 33 pwm_set_enabled(slice_num, false); 34 float counting_rate = clock_get_hz(clk_sys) / 100; 35 float max_possible_count = counting_rate * 0.01; 36 return pwm_get_counter(slice_num) / max_possible_count; 37 }

4.5.2.6. Configuring PWM Period

When free-running, the period of a PWM slice’s output (measured in system clock cycles) is controlled by three parameters:

527

4.5. PWM

RP2040 Datasheet

  • [The ][TOP][ register]

  • [Whether phase-correct mode is enabled (][CSR_PH_CORRECT][)]

  • [The ][DIV][ register]

The slice counts from 0 to TOP, and then either wraps, or begins counting backward, depending on the setting of CSR_PH_CORRECT. The rate of counting is slowed by the clock divider, with a maximum speed of one count per cycle, and a

minimum speed of one count per cycles. The period in clock cycles can be calculated as:

==> picture [296 x 22] intentionally omitted <==

The output frequency can then be determined based on the system clock frequency:

==> picture [318 x 28] intentionally omitted <==

4.5.2.7. Interrupt Request (IRQ) and DMA Data Request (DREQ)

The PWM block has a single IRQ output. The interrupt status registers INTR, INTS and INTE allow software to control which slices will assert this IRQ output, to check which slices are the cause of the IRQ’s assertion, and to clear and acknowledge the interrupt.

A slice generates an interrupt request each time its counter wraps (or, if CSR_PH_CORRECT is enabled, each time the counter returns to 0). This sets the flag corresponding to this slice in the raw interrupt status register, INTR. If this slice’s interrupt is enabled in INTE, then this flag will cause the PWM block’s IRQ to be asserted, and the flag will also appear in the masked interrupt status register INTS.

Flags are cleared by writing a mask back to INTR. This is demonstrated in the "LED fade" SDK example.

This scheme allows multiple slices to generate interrupts concurrently, and a system interrupt handler to determine which slices caused the most recent interruption, and handle appropriately. Normally this would mean reloading those slices' TOP or CC registers, but the PWM block can also be used as a source of regular interrupt requests for non-PWMrelated purposes.

The same pulse which sets the interrupt flag in INTR is also available as a one-cycle data request to the RP2040 system DMA. For each cycle the DMA sees a DREQ asserted, it will make one data transfer to its programmed location, in as timely a manner as possible. In combination with the double-buffered behaviour of CC and TOP, this allows the DMA to efficiently stream data to a PWM slice at a rate of one transfer per counter period. Alternatively, a PWM slice could serve as a pacing timer for DMA transfers to some other memory-mapped hardware.

4.5.2.8. On-the-fly Phase Adjustment

For some applications it is necessary to control the phase relationship between two PWM outputs on different slices.

The global enable register EN contains an alias of the CSR_EN flag for each slice, and allows multiple slices to be started and stopped simultaneously. If two slices with the same output frequency are started at the same time, they will run in perfect lockstep, and have a fixed phase relationship, determined by the initial counter values.

The CSR_PH_ADV and CSR_PH_RET fields will advance or retard a slice’s output phase by one count, whilst it is running. They do so by inserting or deleting pulses from the clock enable (the output of the clock divider), as shown in Figure 113.

528

4.5. PWM

RP2040 Datasheet

==> picture [356 x 214] intentionally omitted <==

----- Start of picture text -----
Figure 113. The clock
enable signal, output Clock
by the clock divider,
controls the rate of
counting. Phase DIV_INT 2
advance forces the
Clock enable
clock enable high on
cycles where it is low, Count 0 1 2 3 4 5
causing the counter to
jump forward by one
count. Phase retard DIV_INT 2
forces the clock CSR_PH_ADV
enable low when it
Clock enable
would be high, holding
the counter back by Count 0 1 2 3 4 5 6
one count.
DIV_INT 2
CSR_PH_RET
Clock enable
Count 0 1 2 3 4
----- End of picture text -----

The counter can not count faster than once per cycle, so PH_ADV requires DIV_INT > 1 or DIV_FRAC > 0. Likewise, the counter will not start to count backward if PH_RET is asserted when the clock enable is permanently low.

To advance or retard the phase by one count, software writes 1 to PH_ADV or PH_RET. Once an enable pulse has been inserted or deleted, the PH_ADV or PH_RET register bit will return to 0, and software can poll the CSR until this happens. PH_ADV will always insert a pulse into the next available gap, and PH_RET will always delete the next available pulse.

4.5.3. List of Registers

The PWM registers start at a base address of 0x40050000 (defined as PWM_BASE in SDK).

Table 516. List of PWM registers

Offset Name Info
0x00 CH0_CSR Control and status register
0x04 CH0_DIV INT and FRAC form a fixed-point fractional number.
Counting rate is system clock frequency divided by this number.
Fractional division uses simple 1st-order sigma-delta.
0x08 CH0_CTR Direct access to the PWM counter
0x0c CH0_CC Counter compare values
0x10 CH0_TOP Counter wrap value
0x14 CH1_CSR Control and status register
0x18 CH1_DIV INT and FRAC form a fixed-point fractional number.
Counting rate is system clock frequency divided by this number.
Fractional division uses simple 1st-order sigma-delta.
0x1c CH1_CTR Direct access to the PWM counter
0x20 CH1_CC Counter compare values
0x24 CH1_TOP Counter wrap value
0x28 CH2_CSR Control and status register
0x2c CH2_DIV INT and FRAC form a fixed-point fractional number.
Counting rate is system clock frequency divided by this number.
Fractional division uses simple 1st-order sigma-delta.

529

4.5. PWM

RP2040 Datasheet

Offset Name Info
0x30 CH2_CTR Direct access to the PWM counter
0x34 CH2_CC Counter compare values
0x38 CH2_TOP Counter wrap value
0x3c CH3_CSR Control and status register
0x40 CH3_DIV INT and FRAC form a fixed-point fractional number.
Counting rate is system clock frequency divided by this number.
Fractional division uses simple 1st-order sigma-delta.
0x44 CH3_CTR Direct access to the PWM counter
0x48 CH3_CC Counter compare values
0x4c CH3_TOP Counter wrap value
0x50 CH4_CSR Control and status register
0x54 CH4_DIV INT and FRAC form a fixed-point fractional number.
Counting rate is system clock frequency divided by this number.
Fractional division uses simple 1st-order sigma-delta.
0x58 CH4_CTR Direct access to the PWM counter
0x5c CH4_CC Counter compare values
0x60 CH4_TOP Counter wrap value
0x64 CH5_CSR Control and status register
0x68 CH5_DIV INT and FRAC form a fixed-point fractional number.
Counting rate is system clock frequency divided by this number.
Fractional division uses simple 1st-order sigma-delta.
0x6c CH5_CTR Direct access to the PWM counter
0x70 CH5_CC Counter compare values
0x74 CH5_TOP Counter wrap value
0x78 CH6_CSR Control and status register
0x7c CH6_DIV INT and FRAC form a fixed-point fractional number.
Counting rate is system clock frequency divided by this number.
Fractional division uses simple 1st-order sigma-delta.
0x80 CH6_CTR Direct access to the PWM counter
0x84 CH6_CC Counter compare values
0x88 CH6_TOP Counter wrap value
0x8c CH7_CSR Control and status register
0x90 CH7_DIV INT and FRAC form a fixed-point fractional number.
Counting rate is system clock frequency divided by this number.
Fractional division uses simple 1st-order sigma-delta.
0x94 CH7_CTR Direct access to the PWM counter
0x98 CH7_CC Counter compare values
0x9c CH7_TOP Counter wrap value

530

4.5. PWM

RP2040 Datasheet

Offset Name Info
0xa0 EN This register aliases the CSR_EN bits for all channels.
Writing to this register allows multiple channels to be enabled
or disabled simultaneously, so they can run in perfect sync.
For each channel, there is only one physical EN register bit,
which can be accessed through here or CHx_CSR.
0xa4 INTR Raw Interrupts
0xa8 INTE Interrupt Enable
0xac INTF Interrupt Force
0xb0 INTS Interrupt status after masking & forcing

PWM: CH0_CSR, CH1_CSR, …, CH6_CSR, CH7_CSR Registers

Offsets : 0x00, 0x14, …, 0x78, 0x8c

Description

Control and status register

Table 517. CH0_CSR,
CH1_CSR, …,
CH6_CSR, CH7_CSR
Registers
Bits Description Type Reset
31:8 Reserved. - -
7 PH_ADV: Advance the phase of the counter by 1 count, while it is running.
Self-clearing. Write a 1, and poll until low. Counter must be running
at less than full speed (div_int + div_frac / 16 > 1)
SC 0x0
6 PH_RET: Retard the phase of the counter by 1 count, while it is running.
Self-clearing. Write a 1, and poll until low. Counter must be running.
SC 0x0
5:4 DIVMODE RW 0x0
Enumerated values:
0x0→DIV: Free-running counting at rate dictated by fractional divider
0x1→LEVEL: Fractional divider operation is gated by the PWM B pin.
0x2→RISE: Counter advances with each rising edge of the PWM B pin.
0x3→FALL: Counter advances with each falling edge of the PWM B pin.
3 B_INV: Invert output B RW 0x0
2 A_INV: Invert output A RW 0x0
1 PH_CORRECT: 1: Enable phase-correct modulation. 0: Trailing-edge RW 0x0
0 EN: Enable the PWM channel. RW 0x0

PWM: CH0_DIV, CH1_DIV, …, CH6_DIV, CH7_DIV Registers

Offsets : 0x04, 0x18, …, 0x7c, 0x90

Description

INT and FRAC form a fixed-point fractional number. Counting rate is system clock frequency divided by this number. Fractional division uses simple 1st-order sigma-delta.

531

4.5. PWM

RP2040 Datasheet

Table 518. CH0_DIV,
CH1_DIV, …, CH6_DIV,
CH7_DIV Registers
Bits Description Type Reset
31:12 Reserved. - -
11:4 INT RW 0x01
3:0 FRAC RW 0x0

PWM: CH0_CTR, CH1_CTR, …, CH6_CTR, CH7_CTR Registers

Offsets : 0x08, 0x1c, …, 0x80, 0x94

Table 519. CH0_CTR,
CH1_CTR, …,
CH6_CTR, CH7_CTR
Registers
Bits Description Type Reset
31:16 Reserved. - -
15:0 Direct access to the PWM counter RW 0x0000

PWM: CH0_CC, CH1_CC, …, CH6_CC, CH7_CC Registers

Offsets : 0x0c, 0x20, …, 0x84, 0x98

Description

Counter compare values

Table 520. CH0_CC,
CH1_CC, …, CH6_CC,
CH7_CC Registers
Bits Description Type Reset
31:16 B RW 0x0000
15:0 A RW 0x0000

PWM: CH0_TOP, CH1_TOP, …, CH6_TOP, CH7_TOP Registers

Offsets : 0x10, 0x24, …, 0x88, 0x9c

Table 521. CH0_TOP,
CH1_TOP, …,
CH6_TOP, CH7_TOP
Registers
Bits Description Type Reset
31:16 Reserved. - -
15:0 Counter wrap value RW 0xffff

PWM: EN Register

Offset : 0xa0

Description

This register aliases the CSR_EN bits for all channels. Writing to this register allows multiple channels to be enabled or disabled simultaneously, so they can run in perfect sync. For each channel, there is only one physical EN register bit, which can be accessed through here or CHx_CSR.

Table 522. EN Register Bits Description Type Reset
31:8 Reserved. - -
7 CH7 RW 0x0
6 CH6 RW 0x0
5 CH5 RW 0x0
4 CH4 RW 0x0
3 CH3 RW 0x0

532

4.5. PWM

RP2040 Datasheet

Bits Description Type Reset
2 CH2 RW 0x0
1 CH1 RW 0x0
0 CH0 RW 0x0

PWM: INTR Register

Offset : 0xa4

Description

Raw Interrupts

Table 523. INTR Register

Bits Description Type Reset
31:8 Reserved. - -
7 CH7 WC 0x0
6 CH6 WC 0x0
5 CH5 WC 0x0
4 CH4 WC 0x0
3 CH3 WC 0x0
2 CH2 WC 0x0
1 CH1 WC 0x0
0 CH0 WC 0x0

PWM: INTE Register

Offset : 0xa8

Description

Interrupt Enable

Table 524. INTE Register

Bits Description Type Reset
31:8 Reserved. - -
7 CH7 RW 0x0
6 CH6 RW 0x0
5 CH5 RW 0x0
4 CH4 RW 0x0
3 CH3 RW 0x0
2 CH2 RW 0x0
1 CH1 RW 0x0
0 CH0 RW 0x0

PWM: INTF Register

Offset : 0xac

533

4.5. PWM

RP2040 Datasheet

Description

Interrupt Force

Table 525. INTF Register

Bits Description Type Reset
31:8 Reserved. - -
7 CH7 RW 0x0
6 CH6 RW 0x0
5 CH5 RW 0x0
4 CH4 RW 0x0
3 CH3 RW 0x0
2 CH2 RW 0x0
1 CH1 RW 0x0
0 CH0 RW 0x0

PWM: INTS Register

Offset : 0xb0

Description

Interrupt status after masking & forcing

Table 526. INTS Register

Bits Description Type Reset
31:8 Reserved. - -
7 CH7 RO 0x0
6 CH6 RO 0x0
5 CH5 RO 0x0
4 CH4 RO 0x0
3 CH3 RO 0x0
2 CH2 RO 0x0
1 CH1 RO 0x0
0 CH0 RO 0x0