1 /**
2 ****************************************************************************************
3 * @file app_rng.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 "platform_sdk.h"
42 #include "app_pwr_mgmt.h"
43 #include "app_systick.h"
44 #include "app_rng.h"
45
46 #ifdef HAL_RNG_MODULE_ENABLED
47
48 /*
49 * DEFINES
50 *****************************************************************************************
51 */
52
53 #ifdef ENV_RTOS_USE_MUTEX
54
55 #define APP_RNG_DRV_SYNC_MUTEX_LOCK app_driver_mutex_pend(s_rng_env.mutex_sync, MUTEX_WAIT_FOREVER)
56 #define APP_RNG_DRV_SYNC_MUTEX_UNLOCK app_driver_mutex_post(s_rng_env.mutex_sync)
57
58 #define APP_RNG_DRV_ASYNC_MUTEX_LOCK app_driver_mutex_pend(s_rng_env.mutex_async, MUTEX_WAIT_FOREVER)
59 #define APP_RNG_DRV_ASYNC_MUTEX_UNLOCK app_driver_mutex_post(s_rng_env.mutex_async)
60
61 #endif
62
63 /*
64 * STRUCT DEFINE
65 *****************************************************************************************
66 */
67
68 /**@brief App rng state types. */
69 typedef enum {
70 APP_RNG_INVALID = 0,
71 APP_RNG_ACTIVITY,
72 #ifdef APP_DRIVER_WAKEUP_CALL_FUN
73 APP_RNG_SLEEP,
74 #endif
75 } app_rng_state_t;
76
77 struct rng_env_t {
78 app_rng_evt_handler_t evt_handler;
79 rng_handle_t handle;
80 app_rng_type_t ues_type;
81 app_rng_state_t rng_state;
82 #ifdef ENV_RTOS_USE_SEMP
83 APP_DRV_SEM_DECL(sem_rx);
84 #endif
85
86 #ifdef ENV_RTOS_USE_MUTEX
87 APP_DRV_MUTEX_DECL(mutex_sync);
88 APP_DRV_MUTEX_DECL(mutex_async);
89 #endif
90 };
91
92 /*
93 * LOCAL FUNCTION DECLARATION
94 *****************************************************************************************
95 */
96 static bool rng_prepare_for_sleep(void);
97 static void rng_sleep_canceled(void);
98 static void rng_wake_up_ind(void);
99
100 /*
101 * LOCAL VARIABLE DEFINITIONS
102 *****************************************************************************************
103 */
104 struct rng_env_t s_rng_env = {
105 .evt_handler = NULL,
106 #ifdef ENV_RTOS_USE_SEMP
107 .sem_rx = NULL,
108 #endif
109 #ifdef ENV_RTOS_USE_MUTEX
110 .mutex_sync = NULL,
111 .mutex_async = NULL,
112 #endif
113 };
114 static bool s_sleep_cb_registered_flag = false;
115 static int16_t s_rng_pwr_id;
116
117 const static app_sleep_callbacks_t rng_sleep_cb = {
118 .app_prepare_for_sleep = rng_prepare_for_sleep,
119 .app_sleep_canceled = rng_sleep_canceled,
120 .app_wake_up_ind = rng_wake_up_ind
121 };
122
123 /*
124 * LOCAL FUNCTION DEFINITIONS
125 *****************************************************************************************
126 */
rng_prepare_for_sleep(void)127 static bool rng_prepare_for_sleep(void)
128 {
129 hal_rng_state_t state;
130
131 if (s_rng_env.rng_state == APP_RNG_ACTIVITY) {
132 state = hal_rng_get_state(&s_rng_env.handle);
133 if ((state != HAL_RNG_STATE_READY) && (state != HAL_RNG_STATE_RESET)) {
134 return false;
135 }
136
137 GLOBAL_EXCEPTION_DISABLE();
138 hal_rng_suspend_reg(&s_rng_env.handle);
139 GLOBAL_EXCEPTION_ENABLE();
140 #ifdef APP_DRIVER_WAKEUP_CALL_FUN
141 s_rng_env.rng_state = APP_RNG_SLEEP;
142 #endif
143 }
144
145 return true;
146 }
147
rng_sleep_canceled(void)148 static void rng_sleep_canceled(void)
149 {
150 }
151
rng_wake_up_ind(void)152 SECTION_RAM_CODE static void rng_wake_up_ind(void)
153 {
154 #ifndef APP_DRIVER_WAKEUP_CALL_FUN
155 if (s_rng_env.rng_state == APP_RNG_ACTIVITY) {
156 GLOBAL_EXCEPTION_DISABLE();
157 hal_rng_resume_reg(&s_rng_env.handle);
158 GLOBAL_EXCEPTION_ENABLE();
159 if (s_rng_env.ues_type == APP_RNG_TYPE_INTERRUPT) {
160 hal_nvic_clear_pending_irq(RNG_IRQn);
161 hal_nvic_enable_irq(RNG_IRQn);
162 }
163 }
164 #endif
165 }
166
167 #ifdef APP_DRIVER_WAKEUP_CALL_FUN
rng_wake_up(void)168 static void rng_wake_up(void)
169 {
170 if (s_rng_env.rng_state == APP_RNG_SLEEP) {
171 GLOBAL_EXCEPTION_DISABLE();
172 hal_rng_resume_reg(&s_rng_env.handle);
173 GLOBAL_EXCEPTION_ENABLE();
174 if (s_rng_env.ues_type == APP_RNG_TYPE_INTERRUPT) {
175 hal_nvic_clear_pending_irq(RNG_IRQn);
176 hal_nvic_enable_irq(RNG_IRQn);
177 }
178 s_rng_env.rng_state = APP_RNG_ACTIVITY;
179 }
180 }
181 #endif
182
app_rng_event_call(rng_handle_t * p_rng,app_rng_evt_type_t evt_type,uint32_t random32bit)183 static void app_rng_event_call(rng_handle_t *p_rng, app_rng_evt_type_t evt_type, uint32_t random32bit)
184 {
185 app_rng_evt_t rng_evt = {APP_RNG_EVT_ERROR, 0x0};
186
187 if (p_rng->p_instance == RNG) {
188 rng_evt.type = evt_type;
189 rng_evt.random_data = random32bit;
190 }
191
192 #ifdef ENV_RTOS_USE_SEMP
193 app_driver_sem_post_from_isr(s_rng_env.sem_rx);
194 #endif
195
196 if (s_rng_env.evt_handler != NULL) {
197 s_rng_env.evt_handler(&rng_evt);
198 }
199 }
200
201 /*
202 * GLOBAL FUNCTION DEFINITIONS
203 ****************************************************************************************
204 */
app_rng_init(app_rng_params_t * p_params,app_rng_evt_handler_t evt_handler)205 uint16_t app_rng_init(app_rng_params_t *p_params, app_rng_evt_handler_t evt_handler)
206 {
207 hal_status_t hal_err_code = HAL_OK;
208 app_drv_err_t app_err_code = APP_DRV_SUCCESS;
209
210 if (p_params == NULL) {
211 return APP_DRV_ERR_POINTER_NULL;
212 }
213
214 #ifdef ENV_RTOS_USE_SEMP
215 if (s_rng_env.sem_rx == NULL) {
216 app_err_code = app_driver_sem_init(&s_rng_env.sem_rx);
217 APP_DRV_ERR_CODE_CHECK(app_err_code);
218 }
219 #endif
220
221 #ifdef ENV_RTOS_USE_MUTEX
222 if (s_rng_env.mutex_async == NULL) {
223 app_err_code = app_driver_mutex_init(&s_rng_env.mutex_async);
224 APP_DRV_ERR_CODE_CHECK(app_err_code);
225 }
226 if (s_rng_env.mutex_sync == NULL) {
227 app_err_code = app_driver_mutex_init(&s_rng_env.mutex_sync);
228 APP_DRV_ERR_CODE_CHECK(app_err_code);
229 }
230 #endif
231
232 app_systick_init();
233
234 if (p_params->use_type == APP_RNG_TYPE_INTERRUPT) {
235 hal_nvic_clear_pending_irq(RNG_IRQn);
236 hal_nvic_enable_irq(RNG_IRQn);
237 }
238
239 s_rng_env.ues_type = p_params->use_type;
240 s_rng_env.evt_handler = evt_handler;
241
242 memcpy_s(&s_rng_env.handle.init, sizeof (s_rng_env.handle.init), &p_params->init, sizeof(rng_init_t));
243 s_rng_env.handle.p_instance = RNG;
244 hal_err_code = hal_rng_deinit(&s_rng_env.handle);
245 APP_DRV_ERR_CODE_CHECK(hal_err_code);
246
247 hal_err_code = hal_rng_init(&s_rng_env.handle);
248 APP_DRV_ERR_CODE_CHECK(hal_err_code);
249
250 if (s_sleep_cb_registered_flag == false) { // register sleep callback
251 s_sleep_cb_registered_flag = true;
252 s_rng_pwr_id = pwr_register_sleep_cb(&rng_sleep_cb, APP_DRIVER_RNG_WAPEUP_PRIORITY);
253 if (s_rng_pwr_id < 0) {
254 return APP_DRV_ERR_INVALID_PARAM;
255 }
256 }
257
258 s_rng_env.rng_state = APP_RNG_ACTIVITY;
259
260 return app_err_code;
261 }
262
app_rng_deinit(void)263 uint16_t app_rng_deinit(void)
264 {
265 hal_status_t hal_err_code;
266
267 if (s_rng_env.rng_state == APP_RNG_INVALID) {
268 return APP_DRV_ERR_INVALID_ID;
269 }
270
271 #ifdef ENV_RTOS_USE_SEMP
272 if (s_rng_env.sem_rx != NULL) {
273 app_driver_sem_deinit(s_rng_env.sem_rx);
274 s_rng_env.sem_rx = NULL;
275 }
276 #endif
277
278 #ifdef ENV_RTOS_USE_MUTEX
279 if (s_rng_env.mutex_sync != NULL) {
280 app_driver_mutex_deinit(s_rng_env.mutex_sync);
281 s_rng_env.mutex_sync = NULL;
282 }
283 if (s_rng_env.mutex_async != NULL) {
284 app_driver_mutex_deinit(s_rng_env.mutex_async);
285 s_rng_env.mutex_async = NULL;
286 }
287 #endif
288
289 hal_nvic_disable_irq(RNG_IRQn);
290 s_rng_env.rng_state = APP_RNG_INVALID;
291
292 GLOBAL_EXCEPTION_DISABLE();
293 pwr_unregister_sleep_cb(s_rng_pwr_id);
294 s_sleep_cb_registered_flag = false;
295 GLOBAL_EXCEPTION_ENABLE();
296
297 app_systick_deinit();
298
299 hal_err_code = hal_rng_deinit(&s_rng_env.handle);
300 HAL_ERR_CODE_CHECK(hal_err_code);
301
302 return APP_DRV_SUCCESS;
303 }
304
app_rng_gen_sync(uint16_t * p_seed,uint32_t * p_random32bit)305 uint16_t app_rng_gen_sync(uint16_t *p_seed, uint32_t *p_random32bit)
306 {
307 hal_status_t err_code;
308
309 if (s_rng_env.rng_state == APP_RNG_INVALID ||
310 p_seed == NULL ||
311 p_random32bit == NULL) {
312 return APP_DRV_ERR_INVALID_PARAM;
313 }
314
315 #ifdef APP_DRIVER_WAKEUP_CALL_FUN
316 rng_wake_up();
317 #endif
318
319 err_code = hal_rng_generate_random_number(&s_rng_env.handle, p_seed, p_random32bit);
320 if (err_code != HAL_OK) {
321 return (uint16_t)err_code;
322 }
323
324 return APP_DRV_SUCCESS;
325 }
326
327 #ifdef ENV_RTOS_USE_SEMP
app_rng_gen_sem_sync(uint16_t * p_seed)328 uint16_t app_rng_gen_sem_sync(uint16_t *p_seed)
329 {
330 hal_status_t err_code;
331
332 #ifdef ENV_RTOS_USE_MUTEX
333 APP_RNG_DRV_ASYNC_MUTEX_LOCK;
334 #endif
335
336 if (s_rng_env.rng_state == APP_RNG_INVALID ||
337 s_rng_env.ues_type == APP_RNG_TYPE_POLLING ||
338 p_seed == NULL) {
339 #ifdef ENV_RTOS_USE_MUTEX
340 APP_RNG_DRV_ASYNC_MUTEX_UNLOCK;
341 #endif
342 return APP_DRV_ERR_INVALID_PARAM;
343 }
344
345 #ifdef APP_DRIVER_WAKEUP_CALL_FUN
346 rng_wake_up();
347 #endif
348
349 err_code = hal_rng_generate_random_number_it(&s_rng_env.handle, p_seed);
350 if (err_code != HAL_OK) {
351 #ifdef ENV_RTOS_USE_MUTEX
352 APP_RNG_DRV_ASYNC_MUTEX_UNLOCK;
353 #endif
354 return (uint16_t)err_code;
355 }
356
357 app_driver_sem_pend(s_rng_env.sem_rx, OS_WAIT_FOREVER);
358
359 #ifdef ENV_RTOS_USE_MUTEX
360 APP_RNG_DRV_ASYNC_MUTEX_UNLOCK;
361 #endif
362
363 return APP_DRV_SUCCESS;
364 }
365 #endif
366
app_rng_gen_async(uint16_t * p_seed)367 uint16_t app_rng_gen_async(uint16_t *p_seed)
368 {
369 hal_status_t err_code;
370
371 if (s_rng_env.rng_state == APP_RNG_INVALID ||
372 s_rng_env.ues_type == APP_RNG_TYPE_POLLING ||
373 p_seed == NULL) {
374 return APP_DRV_ERR_INVALID_PARAM;
375 }
376
377 #ifdef APP_DRIVER_WAKEUP_CALL_FUN
378 rng_wake_up();
379 #endif
380
381 err_code = hal_rng_generate_random_number_it(&s_rng_env.handle, p_seed);
382 if (err_code != HAL_OK) {
383 return (uint16_t)err_code;
384 }
385
386 return APP_DRV_SUCCESS;
387 }
388
app_rng_get_handle(void)389 rng_handle_t *app_rng_get_handle(void)
390 {
391 if (s_rng_env.rng_state == APP_RNG_INVALID) {
392 return NULL;
393 }
394
395 #ifdef APP_DRIVER_WAKEUP_CALL_FUN
396 rng_wake_up();
397 #endif
398
399 return &s_rng_env.handle;
400 }
401
hal_rng_ready_data_callback(rng_handle_t * p_rng,uint32_t random32bit)402 void hal_rng_ready_data_callback(rng_handle_t *p_rng, uint32_t random32bit)
403 {
404 app_rng_event_call(p_rng, APP_RNG_EVT_DONE, random32bit);
405 }
406
RNG_IRQHandler(void)407 SECTION_RAM_CODE void RNG_IRQHandler(void)
408 {
409 #if FLASH_PROTECT_PRIORITY
410 platform_interrupt_protection_push();
411 #endif
412 hal_rng_irq_handler(&s_rng_env.handle);
413 #if FLASH_PROTECT_PRIORITY
414 platform_interrupt_protection_pop();
415 #endif
416 }
417
418 #endif
419