ChibiOS/HAL  6.1.0
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  */
56 void pwmInit(void) {
57 
58  pwm_lld_init();
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  */
68 void pwmObjectInit(PWMDriver *pwmp) {
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  *
87  * @api
88  */
89 void pwmStart(PWMDriver *pwmp, const PWMConfig *config) {
90 
91  osalDbgCheck((pwmp != NULL) && (config != NULL));
92 
93  osalSysLock();
94  osalDbgAssert((pwmp->state == PWM_STOP) || (pwmp->state == PWM_READY),
95  "invalid state");
96  pwmp->config = config;
97  pwmp->period = config->period;
98  pwm_lld_start(pwmp);
99  pwmp->enabled = 0;
100  pwmp->state = PWM_READY;
101  osalSysUnlock();
102 }
103 
104 /**
105  * @brief Deactivates the PWM peripheral.
106  *
107  * @param[in] pwmp pointer to a @p PWMDriver object
108  *
109  * @api
110  */
111 void pwmStop(PWMDriver *pwmp) {
112 
113  osalDbgCheck(pwmp != NULL);
114 
115  osalSysLock();
116 
117  osalDbgAssert((pwmp->state == PWM_STOP) || (pwmp->state == PWM_READY),
118  "invalid state");
119 
120  pwm_lld_stop(pwmp);
121  pwmp->enabled = 0;
122  pwmp->config = NULL;
123  pwmp->state = PWM_STOP;
124 
125  osalSysUnlock();
126 }
127 
128 /**
129  * @brief Changes the period the PWM peripheral.
130  * @details This function changes the period of a PWM unit that has already
131  * been activated using @p pwmStart().
132  * @pre The PWM unit must have been activated using @p pwmStart().
133  * @post The PWM unit period is changed to the new value.
134  * @note If a period is specified that is shorter than the pulse width
135  * programmed in one of the channels then the behavior is not
136  * guaranteed.
137  *
138  * @param[in] pwmp pointer to a @p PWMDriver object
139  * @param[in] period new cycle time in ticks
140  *
141  * @api
142  */
143 void pwmChangePeriod(PWMDriver *pwmp, pwmcnt_t period) {
144 
145  osalDbgCheck(pwmp != NULL);
146 
147  osalSysLock();
148  osalDbgAssert(pwmp->state == PWM_READY, "invalid state");
149  pwmChangePeriodI(pwmp, period);
150  osalSysUnlock();
151 }
152 
153 /**
154  * @brief Enables a PWM channel.
155  * @pre The PWM unit must have been activated using @p pwmStart().
156  * @post The channel is active using the specified configuration.
157  * @note Depending on the hardware implementation this function has
158  * effect starting on the next cycle (recommended implementation)
159  * or immediately (fallback implementation).
160  *
161  * @param[in] pwmp pointer to a @p PWMDriver object
162  * @param[in] channel PWM channel identifier (0...channels-1)
163  * @param[in] width PWM pulse width as clock pulses number
164  *
165  * @api
166  */
168  pwmchannel_t channel,
169  pwmcnt_t width) {
170 
171  osalDbgCheck((pwmp != NULL) && (channel < pwmp->channels));
172 
173  osalSysLock();
174 
175  osalDbgAssert(pwmp->state == PWM_READY, "not ready");
176 
177  pwmEnableChannelI(pwmp, channel, width);
178 
179  osalSysUnlock();
180 }
181 
182 /**
183  * @brief Disables a PWM channel and its notification.
184  * @pre The PWM unit must have been activated using @p pwmStart().
185  * @post The channel is disabled and its output line returned to the
186  * idle state.
187  * @note Depending on the hardware implementation this function has
188  * effect starting on the next cycle (recommended implementation)
189  * or immediately (fallback implementation).
190  *
191  * @param[in] pwmp pointer to a @p PWMDriver object
192  * @param[in] channel PWM channel identifier (0...channels-1)
193  *
194  * @api
195  */
197 
198  osalDbgCheck((pwmp != NULL) && (channel < pwmp->channels));
199 
200  osalSysLock();
201 
202  osalDbgAssert(pwmp->state == PWM_READY, "not ready");
203 
204  pwmDisableChannelI(pwmp, channel);
205 
206  osalSysUnlock();
207 }
208 
209 /**
210  * @brief Enables the periodic activation edge notification.
211  * @pre The PWM unit must have been activated using @p pwmStart().
212  * @note If the notification is already enabled then the call has no effect.
213  *
214  * @param[in] pwmp pointer to a @p PWMDriver object
215  *
216  * @api
217  */
219 
220  osalDbgCheck(pwmp != NULL);
221 
222  osalSysLock();
223 
224  osalDbgAssert(pwmp->state == PWM_READY, "not ready");
225  osalDbgAssert(pwmp->config->callback != NULL, "undefined periodic callback");
226 
228 
229  osalSysUnlock();
230 }
231 
232 /**
233  * @brief Disables the periodic activation edge notification.
234  * @pre The PWM unit must have been activated using @p pwmStart().
235  * @note If the notification is already disabled then the call has no effect.
236  *
237  * @param[in] pwmp pointer to a @p PWMDriver object
238  *
239  * @api
240  */
242 
243  osalDbgCheck(pwmp != NULL);
244 
245  osalSysLock();
246 
247  osalDbgAssert(pwmp->state == PWM_READY, "not ready");
248  osalDbgAssert(pwmp->config->callback != NULL, "undefined periodic callback");
249 
251 
252  osalSysUnlock();
253 }
254 
255 /**
256  * @brief Enables a channel de-activation edge notification.
257  * @pre The PWM unit must have been activated using @p pwmStart().
258  * @pre The channel must have been activated using @p pwmEnableChannel().
259  * @note If the notification is already enabled then the call has no effect.
260  *
261  * @param[in] pwmp pointer to a @p PWMDriver object
262  * @param[in] channel PWM channel identifier (0...channels-1)
263  *
264  * @api
265  */
267 
268  osalDbgCheck((pwmp != NULL) && (channel < pwmp->channels));
269 
270  osalSysLock();
271 
272  osalDbgAssert(pwmp->state == PWM_READY, "not ready");
273  osalDbgAssert((pwmp->enabled & ((pwmchnmsk_t)1U << (pwmchnmsk_t)channel)) != 0U,
274  "channel not enabled");
275  osalDbgAssert(pwmp->config->channels[channel].callback != NULL,
276  "undefined channel callback");
277 
278  pwmEnableChannelNotificationI(pwmp, channel);
279 
280  osalSysUnlock();
281 }
282 
283 /**
284  * @brief Disables a channel de-activation edge notification.
285  * @pre The PWM unit must have been activated using @p pwmStart().
286  * @pre The channel must have been activated using @p pwmEnableChannel().
287  * @note If the notification is already disabled then the call has no effect.
288  *
289  * @param[in] pwmp pointer to a @p PWMDriver object
290  * @param[in] channel PWM channel identifier (0...channels-1)
291  *
292  * @api
293  */
295 
296  osalDbgCheck((pwmp != NULL) && (channel < pwmp->channels));
297 
298  osalSysLock();
299 
300  osalDbgAssert(pwmp->state == PWM_READY, "not ready");
301  osalDbgAssert((pwmp->enabled & ((pwmchnmsk_t)1U << (pwmchnmsk_t)channel)) != 0U,
302  "channel not enabled");
303  osalDbgAssert(pwmp->config->channels[channel].callback != NULL,
304  "undefined channel callback");
305 
306  pwmDisableChannelNotificationI(pwmp, channel);
307 
308  osalSysUnlock();
309 }
310 
311 #endif /* HAL_USE_PWM == TRUE */
312 
313 /** @} */
void pwmEnableChannel(PWMDriver *pwmp, pwmchannel_t channel, pwmcnt_t width)
Enables a PWM channel.
Definition: hal_pwm.c:167
const PWMConfig * config
Current driver configuration data.
Definition: hal_pwm_lld.h:142
pwmcnt_t period
PWM period in ticks.
Definition: hal_pwm_lld.h:117
#define pwmDisablePeriodicNotificationI(pwmp)
Disables the periodic activation edge notification.
Definition: hal_pwm.h:248
pwmstate_t state
Driver state.
Definition: hal_pwm_lld.h:138
void pwmChangePeriod(PWMDriver *pwmp, pwmcnt_t period)
Changes the period the PWM peripheral.
Definition: hal_pwm.c:143
pwmchnmsk_t enabled
Mask of the enabled channels.
Definition: hal_pwm_lld.h:150
Type of a PWM driver configuration structure.
Definition: hal_pwm_lld.h:105
HAL subsystem header.
uint32_t pwmcnt_t
Type of a PWM counter.
Definition: hal_pwm_lld.h:83
static void osalSysUnlock(void)
Leaves a critical zone from thread context.
Definition: osal.h:540
#define pwmEnableChannelNotificationI(pwmp, channel)
Enables a channel de-activation edge notification.
Definition: hal_pwm.h:262
pwmcallback_t callback
Channel callback pointer.
Definition: hal_pwm_lld.h:98
pwmchannel_t channels
Number of channels in this instance.
Definition: hal_pwm_lld.h:154
void pwmEnablePeriodicNotification(PWMDriver *pwmp)
Enables the periodic activation edge notification.
Definition: hal_pwm.c:218
void pwmStop(PWMDriver *pwmp)
Deactivates the PWM peripheral.
Definition: hal_pwm.c:111
void pwmStart(PWMDriver *pwmp, const PWMConfig *config)
Configures and activates the PWM peripheral.
Definition: hal_pwm.c:89
pwmcallback_t callback
Periodic callback pointer.
Definition: hal_pwm_lld.h:123
#define pwmEnablePeriodicNotificationI(pwmp)
Enables the periodic activation edge notification.
Definition: hal_pwm.h:236
Structure representing a PWM driver.
Definition: hal_pwm_lld.h:134
void pwmInit(void)
PWM Driver initialization.
Definition: hal_pwm.c:56
void pwmDisableChannel(PWMDriver *pwmp, pwmchannel_t channel)
Disables a PWM channel and its notification.
Definition: hal_pwm.c:196
uint32_t pwmchnmsk_t
Type of a channels mask.
Definition: hal_pwm_lld.h:78
#define osalDbgCheck(c)
Function parameters check.
Definition: osal.h:278
#define pwmEnableChannelI(pwmp, channel, width)
Enables a PWM channel.
Definition: hal_pwm.h:191
void pwmDisablePeriodicNotification(PWMDriver *pwmp)
Disables the periodic activation edge notification.
Definition: hal_pwm.c:241
static void osalSysLock(void)
Enters a critical zone from thread context.
Definition: osal.h:530
void pwm_lld_stop(PWMDriver *pwmp)
Deactivates the PWM peripheral.
Definition: hal_pwm_lld.c:102
void pwm_lld_start(PWMDriver *pwmp)
Configures and activates the PWM peripheral.
Definition: hal_pwm_lld.c:83
#define pwmChangePeriodI(pwmp, value)
Changes the period the PWM peripheral.
Definition: hal_pwm.h:172
uint8_t pwmchannel_t
Type of a PWM channel.
Definition: hal_pwm_lld.h:73
void pwmEnableChannelNotification(PWMDriver *pwmp, pwmchannel_t channel)
Enables a channel de-activation edge notification.
Definition: hal_pwm.c:266
void pwmObjectInit(PWMDriver *pwmp)
Initializes the standard part of a PWMDriver structure.
Definition: hal_pwm.c:68
void pwm_lld_init(void)
Low level PWM driver initialization.
Definition: hal_pwm_lld.c:66
#define osalDbgAssert(c, remark)
Condition assertion.
Definition: osal.h:258
void pwmDisableChannelNotification(PWMDriver *pwmp, pwmchannel_t channel)
Disables a channel de-activation edge notification.
Definition: hal_pwm.c:294
#define pwmDisableChannelNotificationI(pwmp, channel)
Disables a channel de-activation edge notification.
Definition: hal_pwm.h:276
PWMChannelConfig channels[PWM_CHANNELS]
Channels configurations.
Definition: hal_pwm_lld.h:127
pwmcnt_t period
Current PWM period in ticks.
Definition: hal_pwm_lld.h:146
#define pwmDisableChannelI(pwmp, channel)
Disables a PWM channel.
Definition: hal_pwm.h:210