• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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