1 /**
2 ****************************************************************************************
3 * @file app_pwm.c
4 * @author BLE Driver Team
5 * @brief HAL APP module driver.
6 ****************************************************************************************
7 * @attention
8 #####Copyright (c) 2019 GOODIX
9 All rights reserved.
10
11 Redistribution and use in source and binary forms, with or without
12 modification, are permitted provided that the following conditions are met:
13 * Redistributions of source code must retain the above copyright
14 notice, this list of conditions and the following disclaimer.
15 * Redistributions in binary form must reproduce the above copyright
16 notice, this list of conditions and the following disclaimer in the
17 documentation and/or other materials provided with the distribution.
18 * Neither the name of GOODIX nor the names of its contributors may be used
19 to endorse or promote products derived from this software without
20 specific prior written permission.
21
22 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
26 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 POSSIBILITY OF SUCH DAMAGE.
33 ****************************************************************************************
34 */
35
36 /*
37 * INCLUDE FILES
38 *****************************************************************************************
39 */
40 #include <string.h>
41 #include "app_io.h"
42 #include "app_systick.h"
43 #include "app_pwr_mgmt.h"
44 #include "app_pwm.h"
45
46 #ifdef HAL_CALENDAR_MODULE_ENABLED
47
48 /*
49 * STRUCT DEFINE
50 *****************************************************************************************
51 */
52
53 /**@brief App pwm state types. */
54 typedef enum {
55 APP_PWM_INVALID = 0,
56 APP_PWM_ACTIVITY,
57 #ifdef APP_DRIVER_WAKEUP_CALL_FUN
58 APP_PWM_SLEEP,
59 #endif
60 } app_pwm_state_t;
61
62 /**@brief App pwm module state types. */
63 typedef enum {
64 APP_PWM_STOP = 0,
65 APP_PWM_START,
66 } app_pwm_module_state_t;
67
68 struct pwm_env_t {
69 app_pwm_pin_cfg_t pin_cfg;
70 app_pwm_state_t pwm_state;
71 app_pwm_module_state_t pwm_module_state;
72 pwm_handle_t handle;
73 };
74
75
76 /*
77 * LOCAL FUNCTION DEFINITIONS
78 *****************************************************************************************
79 */
80 static bool pwm_prepare_for_sleep(void);
81 static void pwm_sleep_canceled(void);
82 static void pwm_wake_up_ind(void);
83 static uint16_t pwm_gpio_config(app_pwm_pin_cfg_t pin_cfg);
84
85 /*
86 * LOCAL VARIABLE DEFINITIONS
87 *****************************************************************************************
88 */
89 struct pwm_env_t s_pwm_env[APP_PWM_ID_MAX];
90 static const uint32_t s_pwm_instance[APP_PWM_ID_MAX] = {PWM0_BASE, PWM1_BASE};
91 static bool s_sleep_cb_registered_flag = false;
92 static uint16_t s_pwm_pwr_id;
93
94 static const app_sleep_callbacks_t pwm_sleep_cb = {
95 .app_prepare_for_sleep = pwm_prepare_for_sleep,
96 .app_sleep_canceled = pwm_sleep_canceled,
97 .app_wake_up_ind = pwm_wake_up_ind
98 };
99
100 /*
101 * LOCAL FUNCTION DEFINITIONS
102 *****************************************************************************************
103 */
pwm_prepare_for_sleep(void)104 static bool pwm_prepare_for_sleep(void)
105 {
106 hal_pwm_state_t state;
107 uint8_t i;
108
109 for (i = 0; i < APP_PWM_ID_MAX; i++) {
110 if (s_pwm_env[i].pwm_state == APP_PWM_ACTIVITY) {
111 state = hal_pwm_get_state(&s_pwm_env[i].handle);
112 if ((state != HAL_PWM_STATE_RESET) && (state != HAL_PWM_STATE_READY)) {
113 return false;
114 }
115
116 GLOBAL_EXCEPTION_DISABLE();
117 hal_pwm_suspend_reg(&s_pwm_env[i].handle);
118 GLOBAL_EXCEPTION_ENABLE();
119 #ifdef APP_DRIVER_WAKEUP_CALL_FUN
120 s_pwm_env[i].pwm_state = APP_PWM_SLEEP;
121 #endif
122 }
123 }
124 return true;
125 }
126
pwm_sleep_canceled(void)127 static void pwm_sleep_canceled(void)
128 {
129 }
130
pwm_wake_up_ind(void)131 SECTION_RAM_CODE static void pwm_wake_up_ind(void)
132 {
133 #ifndef APP_DRIVER_WAKEUP_CALL_FUN
134 uint8_t i;
135
136 for (i = 0; i < APP_PWM_ID_MAX; i++) {
137 if (s_pwm_env[i].pwm_state == APP_PWM_ACTIVITY) {
138 GLOBAL_EXCEPTION_DISABLE();
139 hal_pwm_resume_reg(&s_pwm_env[i].handle);
140 GLOBAL_EXCEPTION_ENABLE();
141
142 if (s_pwm_env[i].pwm_module_state == APP_PWM_START) {
143 hal_pwm_start(&s_pwm_env[i].handle);
144 }
145 }
146 }
147 #endif
148 }
149
150
151 #ifdef APP_DRIVER_WAKEUP_CALL_FUN
pwm_wake_up(app_pwm_id_t id)152 static void pwm_wake_up(app_pwm_id_t id)
153 {
154 if (s_pwm_env[id].pwm_state == APP_PWM_SLEEP) {
155 GLOBAL_EXCEPTION_DISABLE();
156 hal_pwm_resume_reg(&s_pwm_env[id].handle);
157 GLOBAL_EXCEPTION_ENABLE();
158
159 if (s_pwm_env[id].pwm_module_state == APP_PWM_START) {
160 hal_pwm_start(&s_pwm_env[id].handle);
161 }
162 }
163 }
164 #endif
165
166
pwm_gpio_config(app_pwm_pin_cfg_t pin_cfg)167 static uint16_t pwm_gpio_config(app_pwm_pin_cfg_t pin_cfg)
168 {
169 app_io_init_t io_init = APP_IO_DEFAULT_CONFIG;
170 app_drv_err_t err_code = APP_DRV_SUCCESS;
171
172 io_init.pull = APP_IO_PULLUP;
173 io_init.mode = APP_IO_MODE_MUX;
174
175 if (pin_cfg.channel_a.enable == APP_PWM_PIN_ENABLE) {
176 io_init.pin = pin_cfg.channel_a.pin;
177 io_init.mux = pin_cfg.channel_a.mux;
178 err_code = app_io_init(pin_cfg.channel_a.type, &io_init);
179 APP_DRV_ERR_CODE_CHECK(err_code);
180 }
181
182 if (pin_cfg.channel_b.enable == APP_PWM_PIN_ENABLE) {
183 io_init.pin = pin_cfg.channel_b.pin;
184 io_init.mux = pin_cfg.channel_b.mux;
185 err_code = app_io_init(pin_cfg.channel_b.type, &io_init);
186 APP_DRV_ERR_CODE_CHECK(err_code);
187 }
188
189 if (pin_cfg.channel_c.enable == APP_PWM_PIN_ENABLE) {
190 io_init.pin = pin_cfg.channel_c.pin;
191 io_init.mux = pin_cfg.channel_c.mux;
192 err_code = app_io_init(pin_cfg.channel_c.type, &io_init);
193 APP_DRV_ERR_CODE_CHECK(err_code);
194 }
195 return err_code;
196 }
197
198 /*
199 * GLOBAL FUNCTION DEFINITIONS
200 ****************************************************************************************
201 */
202
app_pwm_init(app_pwm_params_t * p_params)203 uint16_t app_pwm_init(app_pwm_params_t *p_params)
204 {
205 uint8_t id = p_params->id;
206 app_drv_err_t app_err_code;
207 hal_status_t hal_err_code;
208
209 if (p_params == NULL) {
210 return APP_DRV_ERR_POINTER_NULL;
211 }
212
213 if (id >= APP_PWM_ID_MAX) {
214 return APP_DRV_ERR_INVALID_ID;
215 }
216
217 app_systick_init();
218
219 app_err_code = pwm_gpio_config(p_params->pin_cfg);
220 APP_DRV_ERR_CODE_CHECK(app_err_code);
221
222 s_pwm_env[id].handle.active_channel = (hal_pwm_active_channel_t)p_params->active_channel;
223
224 memcpy_s(&s_pwm_env[id].pin_cfg, sizeof (s_pwm_env[id].pin_cfg), &p_params->pin_cfg, sizeof(app_pwm_pin_cfg_t));
225 memcpy_s(&s_pwm_env[id].handle.init, sizeof (s_pwm_env[id].handle.init), &p_params->init, sizeof(pwm_init_t));
226
227 pwm_gpio_config(s_pwm_env[id].pin_cfg);
228
229 s_pwm_env[id].handle.p_instance = (pwm_regs_t *)s_pwm_instance[id];
230
231 hal_err_code = hal_pwm_deinit(&s_pwm_env[id].handle);
232 HAL_ERR_CODE_CHECK(hal_err_code);
233
234 hal_err_code = hal_pwm_init(&s_pwm_env[id].handle);
235 HAL_ERR_CODE_CHECK(hal_err_code);
236
237 if (!s_sleep_cb_registered_flag) {
238 s_sleep_cb_registered_flag = true;
239
240 s_pwm_pwr_id = pwr_register_sleep_cb(&pwm_sleep_cb, APP_DRIVER_PWM_WAPEUP_PRIORITY);
241 if (s_pwm_pwr_id < 0) {
242 return APP_DRV_ERR_INVALID_PARAM;
243 }
244 }
245
246 s_pwm_env[id].pwm_state = APP_PWM_ACTIVITY;
247 s_pwm_env[id].pwm_module_state = APP_PWM_STOP;
248
249 return APP_DRV_SUCCESS;
250 }
251
252
app_pwm_deinit(app_pwm_id_t id)253 uint16_t app_pwm_deinit(app_pwm_id_t id)
254 {
255 hal_status_t err_code = HAL_ERROR;
256
257 if (id >= APP_PWM_ID_MAX) {
258 return APP_DRV_ERR_INVALID_ID;
259 }
260
261 if (s_pwm_env[id].pwm_state == APP_PWM_INVALID) {
262 return APP_DRV_ERR_INVALID_ID;
263 }
264
265 GLOBAL_EXCEPTION_DISABLE();
266 if (s_pwm_env[APP_PWM_ID_0].pwm_state == APP_PWM_INVALID &&
267 s_pwm_env[APP_PWM_ID_1].pwm_state == APP_PWM_INVALID) {
268 pwr_unregister_sleep_cb(s_pwm_pwr_id);
269 s_sleep_cb_registered_flag = false;
270 }
271 GLOBAL_EXCEPTION_ENABLE();
272
273 if (s_pwm_env[id].pin_cfg.channel_a.enable == APP_PWM_PIN_ENABLE) {
274 app_io_deinit(s_pwm_env[id].pin_cfg.channel_a.type, s_pwm_env[id].pin_cfg.channel_a.pin);
275 }
276 if (s_pwm_env[id].pin_cfg.channel_b.enable == APP_PWM_PIN_ENABLE) {
277 app_io_deinit(s_pwm_env[id].pin_cfg.channel_b.type, s_pwm_env[id].pin_cfg.channel_b.pin);
278 }
279 if (s_pwm_env[id].pin_cfg.channel_c.enable == APP_PWM_PIN_ENABLE) {
280 app_io_deinit(s_pwm_env[id].pin_cfg.channel_c.type, s_pwm_env[id].pin_cfg.channel_c.pin);
281 }
282
283 err_code = hal_pwm_deinit(&s_pwm_env[id].handle);
284 HAL_ERR_CODE_CHECK(err_code);
285
286 s_pwm_env[id].pwm_state = APP_PWM_INVALID;
287 s_pwm_env[id].pwm_module_state = APP_PWM_STOP;
288
289 return APP_DRV_SUCCESS;
290 }
291
292
app_pwm_start(app_pwm_id_t id)293 uint16_t app_pwm_start(app_pwm_id_t id)
294 {
295 hal_status_t err_code;
296
297 if (id >= APP_PWM_ID_MAX) {
298 return APP_DRV_ERR_INVALID_ID;
299 }
300
301 #ifdef APP_DRIVER_WAKEUP_CALL_FUN
302 pwm_wake_up(id);
303 #endif
304 err_code = hal_pwm_start(&s_pwm_env[id].handle);
305 HAL_ERR_CODE_CHECK(err_code);
306
307 s_pwm_env[id].pwm_module_state = APP_PWM_START;
308
309 return APP_DRV_SUCCESS;
310 }
311
312
app_pwm_stop(app_pwm_id_t id)313 uint16_t app_pwm_stop(app_pwm_id_t id)
314 {
315 hal_status_t err_code;
316
317 if (id >= APP_PWM_ID_MAX) {
318 return APP_DRV_ERR_INVALID_ID;
319 }
320
321 #ifdef APP_DRIVER_WAKEUP_CALL_FUN
322 pwm_wake_up(id);
323 #endif
324
325 err_code = hal_pwm_stop(&s_pwm_env[id].handle);
326 HAL_ERR_CODE_CHECK(err_code);
327
328 s_pwm_env[id].pwm_module_state = APP_PWM_STOP;
329
330 return APP_DRV_SUCCESS;
331 }
332
333
app_pwm_update_freq(app_pwm_id_t id,uint32_t freq)334 uint16_t app_pwm_update_freq(app_pwm_id_t id, uint32_t freq)
335 {
336 hal_status_t err_code;
337
338 if (id >= APP_PWM_ID_MAX) {
339 return APP_DRV_ERR_INVALID_ID;
340 }
341
342 #ifdef APP_DRIVER_WAKEUP_CALL_FUN
343 pwm_wake_up(id);
344 #endif
345
346 err_code = hal_pwm_update_freq(&s_pwm_env[id].handle, freq);
347 HAL_ERR_CODE_CHECK(err_code);
348
349 return APP_DRV_SUCCESS;
350 }
351
352
app_pwm_config_channel(app_pwm_id_t id,app_pwm_active_channel_t channel,app_pwm_channel_init_t * p_config)353 uint16_t app_pwm_config_channel(app_pwm_id_t id, app_pwm_active_channel_t channel, app_pwm_channel_init_t *p_config)
354 {
355 hal_status_t err_code;
356
357 hal_pwm_active_channel_t active_channel;
358 pwm_channel_init_t channel_cfg;
359
360 if (id >= APP_PWM_ID_MAX) {
361 return APP_DRV_ERR_INVALID_ID;
362 }
363
364 #ifdef APP_DRIVER_WAKEUP_CALL_FUN
365 pwm_wake_up(id);
366 #endif
367
368 active_channel = (hal_pwm_active_channel_t)channel;
369 channel_cfg.duty = p_config->duty;
370 channel_cfg.drive_polarity = p_config->drive_polarity;
371
372 err_code = hal_pwm_config_channel(&s_pwm_env[id].handle, &channel_cfg, active_channel);
373 HAL_ERR_CODE_CHECK(err_code);
374
375 return APP_DRV_SUCCESS;
376 }
377 #endif
378