1 /* 2 * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, this 9 * list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * 3. Neither the name of the copyright holder nor the names of its 16 * contributors may be used to endorse or promote products derived from this 17 * software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 #include <nrfx.h> 32 33 #if NRFX_CHECK(NRFX_SYSTICK_ENABLED) 34 #include <nrfx_systick.h> 35 36 /** 37 * @brief Maximum number of ticks to delay 38 * 39 * The maximum number of ticks should be much lower than 40 * Physical maximum count of the SysTick timer. 41 * It is dictated by the fact that it would be impossible to detect delay 42 * properly when the timer value warps around the starting point. 43 */ 44 #define NRFX_SYSTICK_TICKS_MAX (NRF_SYSTICK_VAL_MASK / 2UL) 45 46 /** 47 * @brief Number of milliseconds in a second 48 */ 49 #define NRFX_SYSTICK_MS (1000UL) 50 51 /** 52 * @brief Number of microseconds in a second 53 */ 54 #define NRFX_SYSTICK_US (1000UL * NRFX_SYSTICK_MS) 55 56 /** 57 * @brief Number of milliseconds to wait in single loop 58 * 59 * Constant used by @ref nrd_drv_systick_delay_ms function 60 * to split waiting into loops and rest. 61 * 62 * It describes the number of milliseconds to wait in single loop. 63 * 64 * See @ref nrfx_systick_delay_ms source code for details. 65 */ 66 #define NRFX_SYSTICK_MS_STEP (64U) 67 68 /** 69 * @brief Checks if the given time is in correct range 70 * 71 * Function tests given time is not to big for this library. 72 * Assertion is used for testing. 73 * 74 * @param us Time in microseconds to check 75 */ 76 #define NRFX_SYSTICK_ASSERT_TIMEOUT(us) \ 77 NRFX_ASSERT(us <= (NRFX_SYSTICK_TICKS_MAX / ((SystemCoreClock) / NRFX_SYSTICK_US))); 78 79 /** 80 * @brief Function that converts microseconds to ticks 81 * 82 * Function converts from microseconds to CPU ticks. 83 * 84 * @param us Number of microseconds 85 * 86 * @return Number of ticks 87 * 88 * @sa nrfx_systick_ms_tick 89 */ 90 static inline uint32_t nrfx_systick_us_tick(uint32_t us) 91 { 92 return us * ((SystemCoreClock) / NRFX_SYSTICK_US); 93 } 94 95 /** 96 * @brief Function that converts milliseconds to ticks 97 * 98 * Function converts from milliseconds to CPU ticks. 99 * 100 * @param us Number of milliseconds 101 * 102 * @return Number of ticks 103 * 104 * @sa nrfx_systick_us_tick 105 */ 106 static inline uint32_t nrfx_systick_ms_tick(uint32_t ms) 107 { 108 return ms * ((SystemCoreClock) / NRFX_SYSTICK_MS); 109 } 110 111 void nrfx_systick_init(void) 112 { 113 nrf_systick_load_set(NRF_SYSTICK_VAL_MASK); 114 nrf_systick_csr_set( 115 NRF_SYSTICK_CSR_CLKSOURCE_CPU | 116 NRF_SYSTICK_CSR_TICKINT_DISABLE | 117 NRF_SYSTICK_CSR_ENABLE); 118 } 119 120 void nrfx_systick_get(nrfx_systick_state_t * p_state) 121 { 122 p_state->time = nrf_systick_val_get(); 123 } 124 125 bool nrfx_systick_test(nrfx_systick_state_t const * p_state, uint32_t us) 126 { 127 NRFX_SYSTICK_ASSERT_TIMEOUT(us); 128 129 const uint32_t diff = NRF_SYSTICK_VAL_MASK & ((p_state->time) - nrf_systick_val_get()); 130 return (diff >= nrfx_systick_us_tick(us)); 131 } 132 133 void nrfx_systick_delay_ticks(uint32_t ticks) 134 { 135 NRFX_ASSERT(ticks <= NRFX_SYSTICK_TICKS_MAX); 136 137 const uint32_t start = nrf_systick_val_get(); 138 while ((NRF_SYSTICK_VAL_MASK & (start - nrf_systick_val_get())) < ticks) 139 { 140 /* Nothing to do */ 141 } 142 } 143 144 void nrfx_systick_delay_us(uint32_t us) 145 { 146 NRFX_SYSTICK_ASSERT_TIMEOUT(us); 147 nrfx_systick_delay_ticks(nrfx_systick_us_tick(us)); 148 } 149 150 void nrfx_systick_delay_ms(uint32_t ms) 151 { 152 uint32_t n = ms / NRFX_SYSTICK_MS_STEP; 153 uint32_t r = ms % NRFX_SYSTICK_MS_STEP; 154 while (0 != (n--)) 155 { 156 nrfx_systick_delay_ticks(nrfx_systick_ms_tick(NRFX_SYSTICK_MS_STEP)); 157 } 158 nrfx_systick_delay_ticks(nrfx_systick_ms_tick(r)); 159 } 160 161 #endif // NRFX_CHECK(NRFX_SYSTICK_ENABLED) 162