ChibiOS 21.11.4
hal_pwm.c
Go to the documentation of this file.
1/*
2 ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15*/
16
17/**
18 * @file hal_pwm.c
19 * @brief PWM Driver code.
20 *
21 * @addtogroup PWM
22 * @{
23 */
24
25#include "hal.h"
26
27#if (HAL_USE_PWM == TRUE) || defined(__DOXYGEN__)
28
29/*===========================================================================*/
30/* Driver local definitions. */
31/*===========================================================================*/
32
33/*===========================================================================*/
34/* Driver exported variables. */
35/*===========================================================================*/
36
37/*===========================================================================*/
38/* Driver local variables and types. */
39/*===========================================================================*/
40
41/*===========================================================================*/
42/* Driver local functions. */
43/*===========================================================================*/
44
45/*===========================================================================*/
46/* Driver exported functions. */
47/*===========================================================================*/
48
49/**
50 * @brief PWM Driver initialization.
51 * @note This function is implicitly invoked by @p halInit(), there is
52 * no need to explicitly initialize the driver.
53 *
54 * @init
55 */
56void pwmInit(void) {
57
59}
60
61/**
62 * @brief Initializes the standard part of a @p PWMDriver structure.
63 *
64 * @param[out] pwmp pointer to a @p PWMDriver object
65 *
66 * @init
67 */
69
70 pwmp->state = PWM_STOP;
71 pwmp->config = NULL;
72 pwmp->enabled = 0;
73 pwmp->channels = 0;
74#if defined(PWM_DRIVER_EXT_INIT_HOOK)
75 PWM_DRIVER_EXT_INIT_HOOK(pwmp);
76#endif
77}
78
79/**
80 * @brief Configures and activates the PWM peripheral.
81 * @note Starting a driver that is already in the @p PWM_READY state
82 * disables all the active channels.
83 *
84 * @param[in] pwmp pointer to a @p PWMDriver object
85 * @param[in] config pointer to a @p PWMConfig object
86 * @return The operation status.
87 *
88 * @api
89 */
90msg_t pwmStart(PWMDriver *pwmp, const PWMConfig *config) {
91 msg_t msg;
92
93 osalDbgCheck((pwmp != NULL) && (config != NULL));
94
96 osalDbgAssert((pwmp->state == PWM_STOP) || (pwmp->state == PWM_READY),
97 "invalid state");
98
99 pwmp->config = config;
100 pwmp->period = config->period;
101 pwmp->enabled = 0U;
102
103#if defined(PWM_LLD_ENHANCED_API)
104 msg = pwm_lld_start(pwmp);
105 if (msg == HAL_RET_SUCCESS) {
106 pwmp->state = PWM_READY;
107 }
108 else {
109 pwmp->state = PWM_STOP;
110 }
111#else
112 pwm_lld_start(pwmp);
113 pwmp->state = PWM_READY;
114 msg = HAL_RET_SUCCESS;
115#endif
116
118
119 return msg;
120}
121
122/**
123 * @brief Deactivates the PWM peripheral.
124 *
125 * @param[in] pwmp pointer to a @p PWMDriver object
126 *
127 * @api
128 */
129void pwmStop(PWMDriver *pwmp) {
130
131 osalDbgCheck(pwmp != NULL);
132
133 osalSysLock();
134
135 osalDbgAssert((pwmp->state == PWM_STOP) || (pwmp->state == PWM_READY),
136 "invalid state");
137
138 pwm_lld_stop(pwmp);
139 pwmp->enabled = 0;
140 pwmp->config = NULL;
141 pwmp->state = PWM_STOP;
142
144}
145
146/**
147 * @brief Changes the period the PWM peripheral.
148 * @details This function changes the period of a PWM unit that has already
149 * been activated using @p pwmStart().
150 * @pre The PWM unit must have been activated using @p pwmStart().
151 * @post The PWM unit period is changed to the new value.
152 * @note If a period is specified that is shorter than the pulse width
153 * programmed in one of the channels then the behavior is not
154 * guaranteed.
155 *
156 * @param[in] pwmp pointer to a @p PWMDriver object
157 * @param[in] period new cycle time in ticks
158 *
159 * @api
160 */
161void pwmChangePeriod(PWMDriver *pwmp, pwmcnt_t period) {
162
163 osalDbgCheck(pwmp != NULL);
164
165 osalSysLock();
166 osalDbgAssert(pwmp->state == PWM_READY, "invalid state");
167 pwmChangePeriodI(pwmp, period);
169}
170
171/**
172 * @brief Enables a PWM channel.
173 * @pre The PWM unit must have been activated using @p pwmStart().
174 * @post The channel is active using the specified configuration.
175 * @note Depending on the hardware implementation this function has
176 * effect starting on the next cycle (recommended implementation)
177 * or immediately (fallback implementation).
178 *
179 * @param[in] pwmp pointer to a @p PWMDriver object
180 * @param[in] channel PWM channel identifier (0...channels-1)
181 * @param[in] width PWM pulse width as clock pulses number
182 *
183 * @api
184 */
186 pwmchannel_t channel,
187 pwmcnt_t width) {
188
189 osalDbgCheck((pwmp != NULL) && (channel < pwmp->channels));
190
191 osalSysLock();
192
193 osalDbgAssert(pwmp->state == PWM_READY, "not ready");
194
195 pwmEnableChannelI(pwmp, channel, width);
196
198}
199
200/**
201 * @brief Disables a PWM channel and its notification.
202 * @pre The PWM unit must have been activated using @p pwmStart().
203 * @post The channel is disabled and its output line returned to the
204 * idle state.
205 * @note Depending on the hardware implementation this function has
206 * effect starting on the next cycle (recommended implementation)
207 * or immediately (fallback implementation).
208 *
209 * @param[in] pwmp pointer to a @p PWMDriver object
210 * @param[in] channel PWM channel identifier (0...channels-1)
211 *
212 * @api
213 */
215
216 osalDbgCheck((pwmp != NULL) && (channel < pwmp->channels));
217
218 osalSysLock();
219
220 osalDbgAssert(pwmp->state == PWM_READY, "not ready");
221
222 pwmDisableChannelI(pwmp, channel);
223
225}
226
227/**
228 * @brief Enables the periodic activation edge notification.
229 * @pre The PWM unit must have been activated using @p pwmStart().
230 * @note If the notification is already enabled then the call has no effect.
231 *
232 * @param[in] pwmp pointer to a @p PWMDriver object
233 *
234 * @api
235 */
237
238 osalDbgCheck(pwmp != NULL);
239
240 osalSysLock();
241
242 osalDbgAssert(pwmp->state == PWM_READY, "not ready");
243 osalDbgAssert(pwmp->config->callback != NULL, "undefined periodic callback");
244
246
248}
249
250/**
251 * @brief Disables the periodic activation edge notification.
252 * @pre The PWM unit must have been activated using @p pwmStart().
253 * @note If the notification is already disabled then the call has no effect.
254 *
255 * @param[in] pwmp pointer to a @p PWMDriver object
256 *
257 * @api
258 */
260
261 osalDbgCheck(pwmp != NULL);
262
263 osalSysLock();
264
265 osalDbgAssert(pwmp->state == PWM_READY, "not ready");
266 osalDbgAssert(pwmp->config->callback != NULL, "undefined periodic callback");
267
269
271}
272
273/**
274 * @brief Enables a channel de-activation edge notification.
275 * @pre The PWM unit must have been activated using @p pwmStart().
276 * @pre The channel must have been activated using @p pwmEnableChannel().
277 * @note If the notification is already enabled then the call has no effect.
278 *
279 * @param[in] pwmp pointer to a @p PWMDriver object
280 * @param[in] channel PWM channel identifier (0...channels-1)
281 *
282 * @api
283 */
285
286 osalDbgCheck((pwmp != NULL) && (channel < pwmp->channels));
287
288 osalSysLock();
289
290 osalDbgAssert(pwmp->state == PWM_READY, "not ready");
291 osalDbgAssert((pwmp->enabled & ((pwmchnmsk_t)1U << (pwmchnmsk_t)channel)) != 0U,
292 "channel not enabled");
293 osalDbgAssert(pwmp->config->channels[channel].callback != NULL,
294 "undefined channel callback");
295
296 pwmEnableChannelNotificationI(pwmp, channel);
297
299}
300
301/**
302 * @brief Disables a channel de-activation edge notification.
303 * @pre The PWM unit must have been activated using @p pwmStart().
304 * @pre The channel must have been activated using @p pwmEnableChannel().
305 * @note If the notification is already disabled then the call has no effect.
306 *
307 * @param[in] pwmp pointer to a @p PWMDriver object
308 * @param[in] channel PWM channel identifier (0...channels-1)
309 *
310 * @api
311 */
313
314 osalDbgCheck((pwmp != NULL) && (channel < pwmp->channels));
315
316 osalSysLock();
317
318 osalDbgAssert(pwmp->state == PWM_READY, "not ready");
319 osalDbgAssert((pwmp->enabled & ((pwmchnmsk_t)1U << (pwmchnmsk_t)channel)) != 0U,
320 "channel not enabled");
321 osalDbgAssert(pwmp->config->channels[channel].callback != NULL,
322 "undefined channel callback");
323
324 pwmDisableChannelNotificationI(pwmp, channel);
325
327}
328
329#endif /* HAL_USE_PWM == TRUE */
330
331/** @} */
#define HAL_RET_SUCCESS
Definition hal.h:93
static void osalSysLock(void)
Enters a critical zone from thread context.
Definition osal.h:601
static void osalSysUnlock(void)
Leaves a critical zone from thread context.
Definition osal.h:611
#define osalDbgAssert(c, remark)
Condition assertion.
Definition osal.h:264
#define osalDbgCheck(c)
Function parameters check.
Definition osal.h:284
void pwmDisablePeriodicNotification(PWMDriver *pwmp)
Disables the periodic activation edge notification.
Definition hal_pwm.c:259
void pwmInit(void)
PWM Driver initialization.
Definition hal_pwm.c:56
#define pwmEnablePeriodicNotificationI(pwmp)
Enables the periodic activation edge notification.
Definition hal_pwm.h:236
void pwmEnablePeriodicNotification(PWMDriver *pwmp)
Enables the periodic activation edge notification.
Definition hal_pwm.c:236
void pwm_lld_stop(PWMDriver *pwmp)
Deactivates the PWM peripheral.
uint32_t pwmcnt_t
Type of a PWM counter.
Definition hal_pwm_lld.h:83
void pwmObjectInit(PWMDriver *pwmp)
Initializes the standard part of a PWMDriver structure.
Definition hal_pwm.c:68
#define pwmEnableChannelNotificationI(pwmp, channel)
Enables a channel de-activation edge notification.
Definition hal_pwm.h:262
uint8_t pwmchannel_t
Type of a PWM channel.
Definition hal_pwm_lld.h:73
#define pwmDisablePeriodicNotificationI(pwmp)
Disables the periodic activation edge notification.
Definition hal_pwm.h:248
void pwm_lld_init(void)
Low level PWM driver initialization.
Definition hal_pwm_lld.c:66
void pwmStop(PWMDriver *pwmp)
Deactivates the PWM peripheral.
Definition hal_pwm.c:129
void pwm_lld_start(PWMDriver *pwmp)
Configures and activates the PWM peripheral.
Definition hal_pwm_lld.c:83
uint32_t pwmchnmsk_t
Type of a channels mask.
Definition hal_pwm_lld.h:78
msg_t pwmStart(PWMDriver *pwmp, const PWMConfig *config)
Configures and activates the PWM peripheral.
Definition hal_pwm.c:90
#define pwmDisableChannelNotificationI(pwmp, channel)
Disables a channel de-activation edge notification.
Definition hal_pwm.h:276
#define pwmDisableChannelI(pwmp, channel)
Disables a PWM channel.
Definition hal_pwm.h:210
void pwmEnableChannelNotification(PWMDriver *pwmp, pwmchannel_t channel)
Enables a channel de-activation edge notification.
Definition hal_pwm.c:284
#define pwmEnableChannelI(pwmp, channel, width)
Enables a PWM channel.
Definition hal_pwm.h:191
void pwmDisableChannel(PWMDriver *pwmp, pwmchannel_t channel)
Disables a PWM channel and its notification.
Definition hal_pwm.c:214
void pwmDisableChannelNotification(PWMDriver *pwmp, pwmchannel_t channel)
Disables a channel de-activation edge notification.
Definition hal_pwm.c:312
void pwmChangePeriod(PWMDriver *pwmp, pwmcnt_t period)
Changes the period the PWM peripheral.
Definition hal_pwm.c:161
#define pwmChangePeriodI(pwmp, value)
Changes the period the PWM peripheral.
Definition hal_pwm.h:172
void pwmEnableChannel(PWMDriver *pwmp, pwmchannel_t channel, pwmcnt_t width)
Enables a PWM channel.
Definition hal_pwm.c:185
@ PWM_READY
Definition hal_pwm.h:77
@ PWM_STOP
Definition hal_pwm.h:76
int32_t msg_t
Definition chearly.h:88
HAL subsystem header.
pwmcallback_t callback
Channel callback pointer.
Definition hal_pwm_lld.h:98
Type of a PWM driver configuration structure.
pwmcallback_t callback
Periodic callback pointer.
PWMChannelConfig channels[PWM_CHANNELS]
Channels configurations.
pwmcnt_t period
PWM period in ticks.
Structure representing a PWM driver.
pwmcnt_t period
Current PWM period in ticks.
pwmchannel_t channels
Number of channels in this instance.
pwmchnmsk_t enabled
Mask of the enabled channels.
const PWMConfig * config
Current driver configuration data.
pwmstate_t state
Driver state.