1 /*
2 * Copyright (c) 2017, STMicroelectronics - All Rights Reserved
3 *
4 * This file is part of VL53L1 Core and is dual licensed,
5 * either 'STMicroelectronics
6 * Proprietary license'
7 * or 'BSD 3-clause "New" or "Revised" License' , at your option.
8 *
9 ********************************************************************************
10 *
11 * 'STMicroelectronics Proprietary license'
12 *
13 ********************************************************************************
14 *
15 * License terms: STMicroelectronics Proprietary in accordance with licensing
16 * terms at www.st.com/sla0081
17 *
18 * STMicroelectronics confidential
19 * Reproduction and Communication of this document is strictly prohibited unless
20 * specifically authorized in writing by STMicroelectronics.
21 *
22 *
23 ********************************************************************************
24 *
25 * Alternatively, VL53L1 Core may be distributed under the terms of
26 * 'BSD 3-clause "New" or "Revised" License', in which case the following
27 * provisions apply instead of the ones mentioned above :
28 *
29 ********************************************************************************
30 *
31 * License terms: BSD 3-clause "New" or "Revised" License.
32 *
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions are met:
35 *
36 * 1. Redistributions of source code must retain the above copyright notice, this
37 * list of conditions and the following disclaimer.
38 *
39 * 2. Redistributions in binary form must reproduce the above copyright notice,
40 * this list of conditions and the following disclaimer in the documentation
41 * and/or other materials provided with the distribution.
42 *
43 * 3. Neither the name of the copyright holder nor the names of its contributors
44 * may be used to endorse or promote products derived from this software
45 * without specific prior written permission.
46 *
47 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
48 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
50 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
51 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
52 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
53 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
54 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
55 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
56 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
57 *
58 *
59 ********************************************************************************
60 *
61 */
62
63 /**
64 * @file vl53l1_wait.c
65 *
66 * @brief EwokPlus25 low level Driver wait function definition
67 */
68
69
70 #include "vl53l1_ll_def.h"
71 #include "vl53l1_ll_device.h"
72 #include "vl53l1_platform.h"
73 #include "vl53l1_core.h"
74 #include "vl53l1_silicon_core.h"
75 #include "vl53l1_wait.h"
76 #include "vl53l1_register_settings.h"
77
78
79 #define LOG_FUNCTION_START(fmt, ...) \
80 _LOG_FUNCTION_START(VL53L1_TRACE_MODULE_CORE, fmt, ##__VA_ARGS__)
81 #define LOG_FUNCTION_END(status, ...) \
82 _LOG_FUNCTION_END(VL53L1_TRACE_MODULE_CORE, status, ##__VA_ARGS__)
83 #define LOG_FUNCTION_END_FMT(status, fmt, ...) \
84 _LOG_FUNCTION_END_FMT(VL53L1_TRACE_MODULE_CORE, status, \
85 fmt, ##__VA_ARGS__)
86
87
VL53L1_wait_for_boot_completion(VL53L1_DEV Dev)88 VL53L1_Error VL53L1_wait_for_boot_completion(
89 VL53L1_DEV Dev)
90 {
91
92 /* Waits for firmware boot to finish
93 */
94
95 VL53L1_Error status = VL53L1_ERROR_NONE;
96 VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev);
97
98 uint8_t fw_ready = 0;
99
100 LOG_FUNCTION_START("");
101
102 if (pdev->wait_method == VL53L1_WAIT_METHOD_BLOCKING) {
103
104 /* blocking version */
105
106 status =
107 VL53L1_poll_for_boot_completion(
108 Dev,
109 VL53L1_BOOT_COMPLETION_POLLING_TIMEOUT_MS);
110
111 } else {
112
113 /* implement non blocking version below */
114
115 fw_ready = 0;
116 while (fw_ready == 0x00 && status == VL53L1_ERROR_NONE) {
117 status = VL53L1_is_boot_complete(
118 Dev,
119 &fw_ready);
120
121 if (status == VL53L1_ERROR_NONE) {
122 status = VL53L1_WaitMs(
123 Dev,
124 VL53L1_POLLING_DELAY_MS);
125 }
126 }
127 }
128
129 LOG_FUNCTION_END(status);
130
131 return status;
132
133 }
134
135
VL53L1_wait_for_firmware_ready(VL53L1_DEV Dev)136 VL53L1_Error VL53L1_wait_for_firmware_ready(
137 VL53L1_DEV Dev)
138 {
139
140 /* If in timed mode or single shot then check firmware is ready
141 * before sending handshake
142 */
143
144 VL53L1_Error status = VL53L1_ERROR_NONE;
145 VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev);
146
147 uint8_t fw_ready = 0;
148 uint8_t mode_start = 0;
149
150 LOG_FUNCTION_START("");
151
152 /* Filter out tje measure mode part of the mode
153 * start register
154 */
155 mode_start =
156 pdev->sys_ctrl.system__mode_start &
157 VL53L1_DEVICEMEASUREMENTMODE_MODE_MASK;
158
159 /*
160 * conditional wait for firmware ready
161 * only waits for timed and single shot modes
162 */
163
164 if ((mode_start == VL53L1_DEVICEMEASUREMENTMODE_TIMED) ||
165 (mode_start == VL53L1_DEVICEMEASUREMENTMODE_SINGLESHOT)) {
166
167 if (pdev->wait_method == VL53L1_WAIT_METHOD_BLOCKING) {
168
169 /* blocking version */
170
171 status =
172 VL53L1_poll_for_firmware_ready(
173 Dev,
174 VL53L1_RANGE_COMPLETION_POLLING_TIMEOUT_MS);
175
176 } else {
177
178 /* implement non blocking version below */
179
180 fw_ready = 0;
181 while (fw_ready == 0x00 && status == VL53L1_ERROR_NONE) {
182 status = VL53L1_is_firmware_ready(
183 Dev,
184 &fw_ready);
185
186 if (status == VL53L1_ERROR_NONE) {
187 status = VL53L1_WaitMs(
188 Dev,
189 VL53L1_POLLING_DELAY_MS);
190 }
191 }
192 }
193 }
194
195 LOG_FUNCTION_END(status);
196
197 return status;
198 }
199
200
VL53L1_wait_for_range_completion(VL53L1_DEV Dev)201 VL53L1_Error VL53L1_wait_for_range_completion(
202 VL53L1_DEV Dev)
203 {
204
205 /* Wrapper function for waiting for range completion
206 */
207
208 VL53L1_Error status = VL53L1_ERROR_NONE;
209 VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev);
210
211 uint8_t data_ready = 0;
212
213 LOG_FUNCTION_START("");
214
215 if (pdev->wait_method == VL53L1_WAIT_METHOD_BLOCKING) {
216
217 /* blocking version */
218
219 status =
220 VL53L1_poll_for_range_completion(
221 Dev,
222 VL53L1_RANGE_COMPLETION_POLLING_TIMEOUT_MS);
223
224 } else {
225
226 /* implement non blocking version below */
227
228 data_ready = 0;
229 while (data_ready == 0x00 && status == VL53L1_ERROR_NONE) {
230 status = VL53L1_is_new_data_ready(
231 Dev,
232 &data_ready);
233
234 if (status == VL53L1_ERROR_NONE) {
235 status = VL53L1_WaitMs(
236 Dev,
237 VL53L1_POLLING_DELAY_MS);
238 }
239 }
240 }
241
242 LOG_FUNCTION_END(status);
243
244 return status;
245 }
246
247
VL53L1_wait_for_test_completion(VL53L1_DEV Dev)248 VL53L1_Error VL53L1_wait_for_test_completion(
249 VL53L1_DEV Dev)
250 {
251
252 /* Wrapper function for waiting for test mode completion
253 */
254
255 VL53L1_Error status = VL53L1_ERROR_NONE;
256 VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev);
257
258 uint8_t data_ready = 0;
259
260 LOG_FUNCTION_START("");
261
262 if (pdev->wait_method == VL53L1_WAIT_METHOD_BLOCKING) {
263
264 /* blocking version */
265
266 status =
267 VL53L1_poll_for_range_completion(
268 Dev,
269 VL53L1_TEST_COMPLETION_POLLING_TIMEOUT_MS);
270
271 } else {
272
273 /* implement non blocking version below */
274
275 data_ready = 0;
276 while (data_ready == 0x00 && status == VL53L1_ERROR_NONE) {
277 status = VL53L1_is_new_data_ready(
278 Dev,
279 &data_ready);
280
281 if (status == VL53L1_ERROR_NONE) {
282 status = VL53L1_WaitMs(
283 Dev,
284 VL53L1_POLLING_DELAY_MS);
285 }
286 }
287 }
288
289 LOG_FUNCTION_END(status);
290
291 return status;
292 }
293
294
295
296
VL53L1_is_boot_complete(VL53L1_DEV Dev,uint8_t * pready)297 VL53L1_Error VL53L1_is_boot_complete(
298 VL53L1_DEV Dev,
299 uint8_t *pready)
300 {
301 /**
302 * Determines if the firmware finished booting by reading
303 * bit 0 of firmware__system_status register
304 */
305
306 VL53L1_Error status = VL53L1_ERROR_NONE;
307 uint8_t firmware__system_status = 0;
308
309 LOG_FUNCTION_START("");
310
311 /* read current range interrupt state */
312
313 status =
314 VL53L1_RdByte(
315 Dev,
316 VL53L1_FIRMWARE__SYSTEM_STATUS,
317 &firmware__system_status);
318
319 /* set *pready = 1 if new range data ready complete
320 * zero otherwise
321 */
322
323 if ((firmware__system_status & 0x01) == 0x01) {
324 *pready = 0x01;
325 VL53L1_init_ll_driver_state(
326 Dev,
327 VL53L1_DEVICESTATE_SW_STANDBY);
328 } else {
329 *pready = 0x00;
330 VL53L1_init_ll_driver_state(
331 Dev,
332 VL53L1_DEVICESTATE_FW_COLDBOOT);
333 }
334
335 LOG_FUNCTION_END(status);
336
337 return status;
338 }
339
340
VL53L1_is_firmware_ready(VL53L1_DEV Dev,uint8_t * pready)341 VL53L1_Error VL53L1_is_firmware_ready(
342 VL53L1_DEV Dev,
343 uint8_t *pready)
344 {
345 /**
346 * Determines if the firmware is ready to range
347 */
348
349 VL53L1_Error status = VL53L1_ERROR_NONE;
350 VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev);
351
352 LOG_FUNCTION_START("");
353
354 status = VL53L1_is_firmware_ready_silicon(
355 Dev,
356 pready);
357
358 pdev->fw_ready = *pready;
359
360 LOG_FUNCTION_END(status);
361
362 return status;
363 }
364
365
VL53L1_is_new_data_ready(VL53L1_DEV Dev,uint8_t * pready)366 VL53L1_Error VL53L1_is_new_data_ready(
367 VL53L1_DEV Dev,
368 uint8_t *pready)
369 {
370 /**
371 * Determines if new range data is ready by reading bit 0 of
372 * VL53L1_GPIO__TIO_HV_STATUS to determine the current state
373 * of output interrupt pin
374 */
375
376 VL53L1_Error status = VL53L1_ERROR_NONE;
377 VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev);
378
379 uint8_t gpio__mux_active_high_hv = 0;
380 uint8_t gpio__tio_hv_status = 0;
381 uint8_t interrupt_ready = 0;
382
383 LOG_FUNCTION_START("");
384
385 gpio__mux_active_high_hv =
386 pdev->stat_cfg.gpio_hv_mux__ctrl &
387 VL53L1_DEVICEINTERRUPTLEVEL_ACTIVE_MASK;
388
389 if (gpio__mux_active_high_hv == VL53L1_DEVICEINTERRUPTLEVEL_ACTIVE_HIGH)
390 interrupt_ready = 0x01;
391 else
392 interrupt_ready = 0x00;
393
394 /* read current range interrupt state */
395
396 status = VL53L1_RdByte(
397 Dev,
398 VL53L1_GPIO__TIO_HV_STATUS,
399 &gpio__tio_hv_status);
400
401 /* set *pready = 1 if new range data ready complete zero otherwise */
402
403 if ((gpio__tio_hv_status & 0x01) == interrupt_ready)
404 *pready = 0x01;
405 else
406 *pready = 0x00;
407
408 LOG_FUNCTION_END(status);
409
410 return status;
411 }
412
413
414
415
VL53L1_poll_for_boot_completion(VL53L1_DEV Dev,uint32_t timeout_ms)416 VL53L1_Error VL53L1_poll_for_boot_completion(
417 VL53L1_DEV Dev,
418 uint32_t timeout_ms)
419 {
420 /**
421 * Polls the bit 0 of the FIRMWARE__SYSTEM_STATUS register to see if
422 * the firmware is ready.
423 */
424
425 VL53L1_Error status = VL53L1_ERROR_NONE;
426
427 LOG_FUNCTION_START("");
428
429 /* after reset for the firmware blocks I2C access while
430 * it copies the NVM data into the G02 host register banks
431 * The host must wait the required time to allow the copy
432 * to complete before attempting to read the firmware status
433 */
434
435 status = VL53L1_WaitUs(
436 Dev,
437 VL53L1_FIRMWARE_BOOT_TIME_US);
438
439 if (status == VL53L1_ERROR_NONE)
440 status =
441 VL53L1_WaitValueMaskEx(
442 Dev,
443 timeout_ms,
444 VL53L1_FIRMWARE__SYSTEM_STATUS,
445 0x01,
446 0x01,
447 VL53L1_POLLING_DELAY_MS);
448
449 if (status == VL53L1_ERROR_NONE)
450 VL53L1_init_ll_driver_state(Dev, VL53L1_DEVICESTATE_SW_STANDBY);
451
452 LOG_FUNCTION_END(status);
453
454 return status;
455 }
456
457
VL53L1_poll_for_firmware_ready(VL53L1_DEV Dev,uint32_t timeout_ms)458 VL53L1_Error VL53L1_poll_for_firmware_ready(
459 VL53L1_DEV Dev,
460 uint32_t timeout_ms)
461 {
462 /**
463 * Polls the bit 0 of the FIRMWARE__SYSTEM_STATUS register to see if
464 * the firmware is ready.
465 */
466
467 VL53L1_Error status = VL53L1_ERROR_NONE;
468 VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev);
469
470 uint32_t start_time_ms = 0;
471 uint32_t current_time_ms = 0;
472 int32_t poll_delay_ms = VL53L1_POLLING_DELAY_MS;
473 uint8_t fw_ready = 0;
474
475 /* calculate time limit in absolute time */
476
477 VL53L1_GetTickCount(&start_time_ms); /*lint !e534 ignoring return*/
478 pdev->fw_ready_poll_duration_ms = 0;
479
480 /* wait until firmware is ready, timeout reached on error occurred */
481
482 while ((status == VL53L1_ERROR_NONE) &&
483 (pdev->fw_ready_poll_duration_ms < timeout_ms) &&
484 (fw_ready == 0)) {
485
486 status = VL53L1_is_firmware_ready(
487 Dev,
488 &fw_ready);
489
490 if (status == VL53L1_ERROR_NONE &&
491 fw_ready == 0 &&
492 poll_delay_ms > 0) {
493 status = VL53L1_WaitMs(
494 Dev,
495 poll_delay_ms);
496 }
497
498 /*
499 * Update polling time (Compare difference rather than
500 * absolute to negate 32bit wrap around issue)
501 */
502 VL53L1_GetTickCount(¤t_time_ms); /*lint !e534 ignoring return*/
503 pdev->fw_ready_poll_duration_ms =
504 current_time_ms - start_time_ms;
505 }
506
507 if (fw_ready == 0 && status == VL53L1_ERROR_NONE)
508 status = VL53L1_ERROR_TIME_OUT;
509
510 LOG_FUNCTION_END(status);
511
512 return status;
513 }
514
515
VL53L1_poll_for_range_completion(VL53L1_DEV Dev,uint32_t timeout_ms)516 VL53L1_Error VL53L1_poll_for_range_completion(
517 VL53L1_DEV Dev,
518 uint32_t timeout_ms)
519 {
520 /**
521 * Polls bit 0 of VL53L1_GPIO__TIO_HV_STATUS to determine
522 * the state of output interrupt pin
523 *
524 * Interrupt may be either active high or active low. Use active_high to
525 * select the required level check
526 */
527
528 VL53L1_Error status = VL53L1_ERROR_NONE;
529 VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev);
530
531 uint8_t gpio__mux_active_high_hv = 0;
532 uint8_t interrupt_ready = 0;
533
534 LOG_FUNCTION_START("");
535
536 gpio__mux_active_high_hv =
537 pdev->stat_cfg.gpio_hv_mux__ctrl &
538 VL53L1_DEVICEINTERRUPTLEVEL_ACTIVE_MASK;
539
540 if (gpio__mux_active_high_hv == VL53L1_DEVICEINTERRUPTLEVEL_ACTIVE_HIGH)
541 interrupt_ready = 0x01;
542 else
543 interrupt_ready = 0x00;
544
545 status =
546 VL53L1_WaitValueMaskEx(
547 Dev,
548 timeout_ms,
549 VL53L1_GPIO__TIO_HV_STATUS,
550 interrupt_ready,
551 0x01,
552 VL53L1_POLLING_DELAY_MS);
553
554 LOG_FUNCTION_END(status);
555
556 return status;
557 }
558
559