PWM Controller Register Guide

From linux-sunxi.org
Jump to navigation Jump to search

PWM

There are two 16-bit up counters in the A10 SoC. Counters will reset when PWM_CH0_PERIOD/PWM_CH1_PERIOD has been reached. On initialization PWM_OUT is active high and starts counting from 0x0000.

The PWM divisor devides the 24MHz clock by 1-4096 depending on the PWM_CTRL register.

There are two output modes, cycle mode and pulse mode which are either, a square waveform or a postive/negative pulse, based on the frequency in the PWM_CH0_PERIOD/PWM_CH1_PERIOD register.

Observed behaviour on GR8 from NextThing

In this section, clock cycles refers to the 24 MHz divided by the current prescaler. With the default prescaler of 120, a clock cycle is 5 microseconds.

GR8 has two PWM channels.

In pulse mode, sending a pulse (time between starting and when the bit has been cleared) takes the time it should take + 1-2 clock cycles.

Writing the period register (between starting and the ready bit has been cleared) takes 3-4 clock cycles. If the register is written while the clock gating is off, the ready bit will stay busy until the clock gating is turned on (and 3-4 clock cycles have passed).

Time needed between disabling PWM and disabling the clock gate to make sure the PWM is actually turned off: 1-2 clock cycles. Otherwise the output signal may be stuck in the active state if it was turned off when the signal was active.

A pulse (regardless of single pulse or cycle mode) always starts with the inactive part, followed by the active part, contrary to what the user manual says.

The polarity register can always be written to, even when the clock gate is off, and will be applied immediately.

In cycle mode, writing 0 to EN and then 1 to EN resets the pulse, i.e. it will immediately perform the inactive part and then the active part and repeat. Same applies if 1 is written to MODE followed by 0. Note that at least 1 clock cycle should be slept between the two writes. By only temporarily disabling the clock gating, that rather just pauses the PWM.

In cycle mode, after a new value has been written to the period register, a pulse with the old parameters must first complete, regardless if the PWM is disabled and then enabled, prescaler is changed, or clock gate is toggled. The new values are applied as soon as the active part of a complete pulse ends. If the PWM is enabled when the period register is written, it may take up to one full pulse length before the new settings are applied. If the PWM was disabled when the period register got a new value, a full pulse with the old parameters will first take place after enabling, before the new parameters are applied. If the PWM is disabled while the pulse with the old parameters is in progress, then after enabling the PWM again a full pulse with the old parameters will still need to take place. Also note that if the prescaler is also changed in conjunction with the new period/duty values, for this complete pulse the old period/duty will be used with the new prescaler, which might lead to a very long period. The only way to clear the previous internal values without the need to wait one pulse with the previous settings seems to temporarily switch to pulse mode. After the period register has been written, sending a single pulse will use the new values immediately. After the single pulse has been sent and switching back to cycle mode, the new values are used (and not the old ones). So a simple workaround when changing the period register is to first write 0x00000000 to the period register (entire period is then one 1 clock cycle and active part is 0 clock cycles), switch to pulse mode and send a single pulse, write the desired value to the period register and then switch to cycle mode.

Note that with the prescaler of 72k, one clock cycle is 3 ms, which depending on use case, might be a long time. If one wants to perform an operation quicker than the timings according to the clock cycle timings mentioned above, one could temporarily change the prescaler to the smallest available. If the prescaler of 1 is available (like it is on GR8), one clock cycle is around 42 nanoseconds.

Info

PWM Base address: 0x01c20e00

PWM Registers

Register Name Offset Size Description Note
PWM_CTRL 0x0000 4B PWM Control register
PWM_CH0_PERIOD 0x0004 4B PWM Channel 0 period register
PWM_CH1_PERIOD 0x0008 4B PWM Channel 1 period register Not available on sun5i
PWM_CTRL

Default value: 0x00000000
Offset: 0x00

Name Bit Read/Write Default Values Description
PWM_CH0_PRESCALAR 0:3 Read/Write 0x00
    0x00 = div(120)
    0x01 = div(180)
    0x02 = div(240)
    0x03 = div(360)
    0x04 = div(480)
    0x05 = no operation
    ...
    0x08 = div(12000)
    0x09 = div(24000)
    0x0a = div(36000)
    0x0b = div(48000)
    0x0c = div(72000)
    0x0d = no operation
    ...
  
Setup the Channel 0 PWM prescalar

Set these bits before enabling the clock-gate to this channel!

PWM_CH0_EN 4 Read/Write 0b0
    0 = disable
    1 = enable
  
Enable or disable the Channel 0 PWM
PWM_CH0_ACT_STA 5 Read/Write 0b0
    0 = low level
    1 = high level
  
Setup Channel 0 PWM Active State
PWM_CH0_CLK_GATING 6 Read/Write 0b0
    0 = mask
    1 = pass
  
Special clock gating for Channel 0 PWM
PWM_CH0_MODE 7 Read/Write 0b0
    0 = cycle mode
    1 = pulse mode
  
Setup Channel 0 PWM Mode
PWM_CH0_PUL_START 8 Read/Write 0b0
    0 = no operation
    1 = output 1 pulse
  
Output one pulse according to PWM_CH0_PERIOD and PWM_CH0_ACT_STATE.

The bit is cleared after the pulse.

no operation 9:14
PWM_CH1_PRESCALAR 15:18 Read/Write 0x00
    0x00 = div(120)
    0x01 = div(180)
    0x02 = div(240)
    0x03 = div(360)
    0x04 = div(480)
    0x05 = no operation
    ...
    0x08 = div(12000)
    0x09 = div(24000)
    0x0a = div(36000)
    0x0b = div(48000)
    0x0c = div(72000)
    0x0d = no operation
    ...
  
Setup the PWM Channel 1 prescalar

Set these bits before enabling the clock-gate to this channel!

PWM_CH1_EN 19 Read/Write 0b0
    0 = disable
    1 = enable
  
Enable or disable the Channel 1 PWM
PWM_CH1_ACT_STATE 20 Read/Write 0b0
    0 = low level
    1 = high level
  
Setup Channel 1 PWM Active State
PWM_CH1_CLK_GATING 21 Read/Write 0b0
    0 = mask
    1 = pass
  
Special clock gating for Channel 1 PWM
PWM_CH1_MODE 22 Read/Write 0b0
    0 = cycle mode
    1 = pulse mode
  
Setup Channel 1 PWM Mode
PWM_CH1_PUL_START 23 Read/Write 0b0
    0 = no operation
    1 = output 1 pulse
  
Output one pulse according to PWM_CH1_PERIOD and PWM_CH1_ACT_STATE.

The bit is cleared after the pulse.

no operation 24:31
PWM_CH0_PERIOD

Default value: 0x00000000
Offset: 0x04

Name Bit Read/Write Default Values Description
PWM_CH0_ACT_CYC 0:15 Read/Write 0x00
    0 = 0 cycles
    1 = 1 cycle
    ...
    n = n cycles
  
Number of active cycles in the channel 0 PWM clock
PWM_CH0_ENTIRE_CYC 16:31 Read/Write 0x00
    0 = 1 cycle
    1 = 2 cycles
    ...
    n = n + 1 cycles
  
Numer of entire cycles in the channel 0 PWM clock

If dynamic updates are required, the PCLK needs to be faster then the PWM_CLK (PWM_CLK = 24MHz/PWM_CH0_PRESCALAR)

PWM_CH1_PERIOD

Default value: 0x00000000
Offset: 0x08

Name Bit Read/Write Default Values Description
PWM_CH1_ACT_CYC 0:15 Read/Write 0x00
    0 = 0 cycles
    1 = 1 cycle
    ...
    n = n cycles
  
Number of active cycles in the channel 1 PWM clock
PWM_CH1_ENTIRE_CYC 16:31 Read/Write 0x00
    0 = 1 cycle
    1 = 2 cycles
    ...
    n = n + 1 cycles
  
Numer of entire cycles in the channel 1 PWM clock

If dynamic updates are required, the PCLK needs to be faster then the PWM_CLK (PWM_CLK = 24MHz/PWM_CH1_PRESCALAR)

Initial values

default map

md 0x01c20e00 3

01c20e00: 00000000 00000000 00000000    ...........

all to 1

mw 0x01c20e00 0xffffffff 3
md 0x01c20e00 3

01c20e00: 007f80ff 00ff00ff 00ff00ff    ............

all to 0

mw 0x01c20e00 0x00 3
md 0x01c20c00 3

01c20c00: 00000000 00000000 00000000    ............