Software APIs
dif_pwm.h
Go to the documentation of this file.
1
// Copyright lowRISC contributors (OpenTitan project).
2
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3
// SPDX-License-Identifier: Apache-2.0
4
5
#ifndef OPENTITAN_SW_DEVICE_LIB_DIF_DIF_PWM_H_
6
#define OPENTITAN_SW_DEVICE_LIB_DIF_DIF_PWM_H_
7
8
/**
9
* @file
10
* @brief <a href="/book/hw/ip/pwm/">PWM</a> Device Interface Functions
11
*
12
* The PWM block contains a 16-bit "phase counter" that controls each channel's
13
* output signal. The "phase counter" acts as a point of reference for a single
14
* PWM "pulse cycle", that is further broken into "beats", depending on the
15
* `beats_per_cycle` parameter. Specifically, a "pulse cycle" may contain [2,
16
* 2^16] "beats". Within a "pulse cycle", users can configure the duty cycle in
17
* number of "beats". Additionally, the duration of a single "beat", is computed
18
* by dividing the core clock frequency by `clock_divisor + 1`.
19
*
20
* PWM "pulse cycle" defined by 16-bit phase counter
21
* ___________________________________________________________
22
* | |
23
* v v
24
* |-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-| ... |-|-|-|-|
25
*
26
* |-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-| ... |-|-|-|-|
27
* min beat size = 1 phase counter tick --> 2^16 "beats" / "pulse cycle"
28
*
29
* |---------------------------------------------- ... | ... --|
30
* max beat size = 2^15 phase counter ticks --> 2 "beats" / "pulse cycle"
31
*/
32
33
#include <stdint.h>
34
35
#include "
sw/device/lib/dif/autogen/dif_pwm_autogen.h
"
36
37
#ifdef __cplusplus
38
extern
"C"
{
39
#endif
// __cplusplus
40
41
/**
42
* A PWM channel.
43
*
44
* Channels are numbered 0 to N-1, where N is the number of channels.
45
*/
46
typedef
size_t
dif_pwm_channel_t
;
47
48
/**
49
* Runtime configuration for PWM.
50
*
51
* This struct describes runtime configuration for one-time configuration of the
52
* PWM "pulse cycle" and "beat" durations that impact all PWM channels.
53
*/
54
typedef
struct
dif_pwm_config
{
55
/**
56
* The core clock frequency divisor that determines the period of a single
57
* "beat" within a PWM "pulse cycle".
58
*
59
* Valid range: [0, 2^26)
60
*
61
* A value of zero, configures the "beat" period to the core clock period.
62
*/
63
uint32_t
clock_divisor
;
64
/**
65
* The total number of "beats" in a "pulse cycle", including both "on" and
66
* "off" beats in a "pulse cycle".
67
*
68
* Valid range: [2, 2^16]
69
*
70
* Note: while any value in the range is acceptable, values will be rounded
71
* down to closest power-of-two.
72
*
73
* A "beat" represents a unit of time of the PWM output signal. Higher values
74
* provide higher duty cycle resolutions, at the expense of longer "pulse
75
* cycles", while lower values provide shorter "pulse cycles", at the expense
76
* of lower duty cycle resolutions (since duty cycles are configured in
77
* "beats" / "pulse cycle").
78
*/
79
uint32_t
beats_per_pulse_cycle
;
80
}
dif_pwm_config_t
;
81
82
/**
83
* A PWM channel mode.
84
*/
85
typedef
enum
dif_pwm_mode
{
86
/**
87
* The PWM duty cycle is set by the firmware and remains constant.
88
*/
89
kDifPwmModeFirmware
= 0,
90
/**
91
* The PWM duty cycle linearly sweeps between both primary and secondary
92
* firmware-configured values, based on a firmware-configured step size.
93
*/
94
kDifPwmModeHeartbeat
= 1,
95
/**
96
* The PWM duty cycle alternates between both primary and secondary
97
* firmware-configured values, based on two firmware-configured durations.
98
*/
99
kDifPwmModeBlink
= 2,
100
}
dif_pwm_mode_t
;
101
102
/**
103
* A PWM channel polarity.
104
*/
105
typedef
enum
dif_pwm_polarity
{
106
/**
107
* A PWM signal is active-high.
108
*/
109
kDifPwmPolarityActiveHigh
= 0,
110
/**
111
* A PWM signal is active-low.
112
*/
113
kDifPwmPolarityActiveLow
= 1,
114
}
dif_pwm_polarity_t
;
115
116
/**
117
* Runtime configuration for a specific PWM channel.
118
*
119
* This struct describes runtime configuration for one-time configuration of a
120
* specific PWM channel.
121
*/
122
typedef
struct
dif_pwm_channel_config
{
123
/**
124
* Primary duty cycle, in number of "beats" / "pulse cycle".
125
*
126
* Valid range: [0, beats_per_pulse_cycle)
127
*
128
* Note: the raw value written to the `A_*` bitfield in each PWM channel's
129
* `DUTY_CYCLE_*` CSR is in units of "phase counter ticks", not "beats".
130
* However, the hardware only takes into account the first `DC_RESN` + 1
131
* MSBs of the raw duty cycle value to determine the number of "beats"
132
* for a given duty cycle. To make this configuration easier, the
133
* software manages the conversion from "beats_per_cycle" to
134
* "phase_counter_ticks" under the hood.
135
*/
136
uint16_t
duty_cycle_a
;
137
/**
138
* Secondary duty cycle, in number of "beats" / "pulse cycle", that is only
139
* relevant in heartbeat and blink modes.
140
*
141
* Valid range: [0, beats_per_pulse_cycle)
142
*
143
* Note: above notes for `duty_cycle_a` apply here too.
144
*/
145
uint16_t
duty_cycle_b
;
146
/**
147
* Phase delay at the beginning of a "pulse cycle" to delay the active
148
* duty cycle "beats" for, in number of "beats".
149
*
150
* Valid range: [0, beats_per_pulse_cycle)
151
*/
152
uint16_t
phase_delay
;
153
/**
154
* The operation mode to configure the channel in, see `dif_pwm_mode_t`.
155
*/
156
dif_pwm_mode_t
mode
;
157
/**
158
* The polarity to configure the channel in, see `dif_pwm_polarity_t`.
159
*/
160
dif_pwm_polarity_t
polarity
;
161
/**
162
* One of two blink parameters that only impact the "Heartbeat" and "Blink"
163
* operation modes.
164
*
165
* The meaning of this parameter is different based on the operation mode:
166
* - Heartbeat mode: determines the number of "pulse cycles" between
167
* increments/decrements to the duty cycle.
168
*
169
* - Blink mode: determines the number of "pulse cycles" to pulse at duty
170
* cycle A, before switching to duty cycle B.
171
*/
172
uint16_t
blink_parameter_x
;
173
/**
174
* One of two blink parameters that only impact the "Heartbeat" and "Blink"
175
* operation modes.
176
*
177
* The meaning of this parameter is different based on the operation mode:
178
* - Heartbeat mode: determines the increment/decrement amount in number
179
* of duty cycle "beats".
180
*
181
* - Blink mode: determines the number of "pulse cycles" to pulse at duty
182
* cycle B, before switching to duty cycle A.
183
*
184
* Note: the raw value written to the `blink_parameter_x` bitfield in each PWM
185
* channel's `BLINK_PARAM_*` CSR is in units of "phase counter ticks", not
186
* "beats". However, for ease of configuration, the software manages this
187
* conversion under the hood.
188
*/
189
uint16_t
blink_parameter_y
;
190
}
dif_pwm_channel_config_t
;
191
192
/**
193
* Configures "phase cycle" and "beat" durations of all PWM channels.
194
*
195
* Since changes to `CLK_DIV` and `DC_RESN` are only allowed when the PWM is
196
* disabled, this function has the side effect of temporarily disabling all PWM
197
* channels while configurations are updated, before restoring the original
198
* enablement state.
199
*
200
* This function should only need to be called once for the lifetime of
201
* `handle`.
202
*
203
* @param pwm A PWM handle.
204
* @param config Runtime configuration parameters.
205
* @return The result of the operation.
206
*/
207
OT_WARN_UNUSED_RESULT
208
dif_result_t
dif_pwm_configure
(
const
dif_pwm_t
*pwm,
dif_pwm_config_t
config);
209
210
/**
211
* Configures a single PWM channel.
212
*
213
* This function should only need to be called once for each PWM channel that
214
* will be used.
215
*
216
* @param pwm A PWM handle.
217
* @param channel A PWM channel to configure.
218
* @param config Runtime configuration parameters for the channel.
219
* @return The result of the operation.
220
*/
221
OT_WARN_UNUSED_RESULT
222
dif_result_t
dif_pwm_configure_channel
(
const
dif_pwm_t
*pwm,
223
dif_pwm_channel_t
channel,
224
dif_pwm_channel_config_t
config);
225
226
/**
227
* Sets the enablement state of the PWM phase counter, which controls the
228
* enablement of all PWM channels.
229
*
230
* @param pwm A PWM handle.
231
* @param enabled The enablement state to configure the PWM phase counter in.
232
* @return The result of the operation.
233
*/
234
OT_WARN_UNUSED_RESULT
235
dif_result_t
dif_pwm_phase_cntr_set_enabled
(
const
dif_pwm_t
*pwm,
236
dif_toggle_t
enabled);
237
238
/**
239
* Gets the enablement state of the PWM phase counter, which controls the
240
* enablement of all PWM channels.
241
*
242
* @param pwm A PWM handle.
243
* @param[out] is_enabled The enablement state of the PWM phase counter.
244
* @return The result of the operation.
245
*/
246
OT_WARN_UNUSED_RESULT
247
dif_result_t
dif_pwm_phase_cntr_get_enabled
(
const
dif_pwm_t
*pwm,
248
dif_toggle_t
*is_enabled);
249
250
/**
251
* Sets the enablement states of one or more PWM channels.
252
*
253
* @param pwm A PWM handle.
254
* @param channels The channels to enable (bitmask, the i-th bit corresponds to
255
* the i-th channel).
256
* @param enabled The enablement state to set.
257
* @return The result of the operation.
258
*/
259
OT_WARN_UNUSED_RESULT
260
dif_result_t
dif_pwm_channels_set_enabled
(
const
dif_pwm_t
*pwm,
261
uint32_t channels,
262
dif_toggle_t
enabled);
263
264
/**
265
* Gets the enablement state of one PWM channel.
266
*
267
* @param pwm A PWM handle.
268
* @param channel The PWM channel to get the enablement state of.
269
* @param[out] is_enabled The enablement state of the PWM channel.
270
* @return The result of the operation.
271
*/
272
OT_WARN_UNUSED_RESULT
273
dif_result_t
dif_pwm_channel_get_enabled
(
const
dif_pwm_t
*pwm,
274
dif_pwm_channel_t
channel,
275
dif_toggle_t
*is_enabled);
276
277
/**
278
* Locks PWM configurations.
279
*
280
* This function is reentrant: calling it while locked will have no effect and
281
* return `kDifOk`.
282
*
283
* @param pwm A PWM handle.
284
* @return The result of the operation.
285
*/
286
OT_WARN_UNUSED_RESULT
287
dif_result_t
dif_pwm_lock
(
const
dif_pwm_t
*pwm);
288
289
/**
290
* Checks whether PWM configurations are locked.
291
*
292
* @param pwm A PWM handle.
293
* @param[out] is_locked Out-param for the locked state.
294
* @return The result of the operation.
295
*/
296
OT_WARN_UNUSED_RESULT
297
dif_result_t
dif_pwm_is_locked
(
const
dif_pwm_t
*pwm,
bool
*is_locked);
298
299
#ifdef __cplusplus
300
}
// extern "C"
301
#endif
// __cplusplus
302
303
#endif
// OPENTITAN_SW_DEVICE_LIB_DIF_DIF_PWM_H_
sw
device
lib
dif
dif_pwm.h
Return to
OpenTitan Documentation