Branch data Line data Source code
1 : : /* 2 : : * Copyright (c) 2018 - 2022, Nordic Semiconductor ASA 3 : : * All rights reserved. 4 : : * 5 : : * SPDX-License-Identifier: BSD-3-Clause 6 : : * 7 : : * Redistribution and use in source and binary forms, with or without 8 : : * modification, are permitted provided that the following conditions are met: 9 : : * 10 : : * 1. Redistributions of source code must retain the above copyright notice, this 11 : : * list of conditions and the following disclaimer. 12 : : * 13 : : * 2. Redistributions in binary form must reproduce the above copyright 14 : : * notice, this list of conditions and the following disclaimer in the 15 : : * documentation and/or other materials provided with the distribution. 16 : : * 17 : : * 3. Neither the name of the copyright holder nor the names of its 18 : : * contributors may be used to endorse or promote products derived from this 19 : : * software without specific prior written permission. 20 : : * 21 : : * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 : : * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 : : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 : : * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 25 : : * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 : : * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 : : * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 : : * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 : : * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 : : * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 : : * POSSIBILITY OF SUCH DAMAGE. 32 : : */ 33 : : 34 : : #ifndef NRFX_COREDEP_H__ 35 : : #define NRFX_COREDEP_H__ 36 : : 37 : : /** 38 : : * @defgroup nrfx_coredep Core-dependent functionality 39 : : * @{ 40 : : * @ingroup nrfx 41 : : * @brief Module containing functions with core-dependent implementation, like delay. 42 : : */ 43 : : 44 : : #if defined(__NRFX_DOXYGEN__) 45 : : 46 : : /** @brief Core frequency (in MHz). */ 47 : : #define NRFX_DELAY_CPU_FREQ_MHZ 48 : : /** @brief Availability of Data Watchpoint and Trace (DWT) unit in the given SoC. */ 49 : : #define NRFX_DELAY_DWT_PRESENT 50 : : /** 51 : : * @brief Number of cycles consumed by one iteration of the internal loop 52 : : * in the function @ref nrfx_coredep_delay_us. 53 : : * 54 : : * This value can be specified externally (for example, when the SoC is emulated). 55 : : */ 56 : : #define NRFX_COREDEP_DELAY_US_LOOP_CYCLES 57 : : 58 : : #elif defined(NRF51) 59 : : #define NRFX_DELAY_CPU_FREQ_MHZ 16 60 : : #define NRFX_DELAY_DWT_PRESENT 0 61 : : #elif defined(NRF52805_XXAA) || defined(NRF52810_XXAA) || \ 62 : : defined(NRF52811_XXAA) || defined(NRF52820_XXAA) 63 : : #define NRFX_DELAY_CPU_FREQ_MHZ 64 64 : : #define NRFX_DELAY_DWT_PRESENT 0 65 : : #elif defined(NRF52832_XXAA) || defined(NRF52832_XXAB) || \ 66 : : defined(NRF52833_XXAA) || defined(NRF52840_XXAA) || \ 67 : : defined(NRF9160_XXAA) 68 : : #define NRFX_DELAY_CPU_FREQ_MHZ 64 69 : : #define NRFX_DELAY_DWT_PRESENT 1 70 : : #elif defined(NRF5340_XXAA_APPLICATION) 71 : : #define NRFX_DELAY_CPU_FREQ_MHZ (SystemCoreClock / 1000000) 72 : : #define NRFX_DELAY_DWT_PRESENT 1 73 : : #elif defined(NRF5340_XXAA_NETWORK) 74 : : #define NRFX_DELAY_CPU_FREQ_MHZ 64 75 : : #define NRFX_DELAY_DWT_PRESENT 1 76 : : #else 77 : : #define NRFX_DELAY_CPU_FREQ_MHZ (SystemCoreClock / 1000000) 78 : : #define NRFX_DELAY_DWT_PRESENT 0 79 : : #endif 80 : : 81 : : /** 82 : : * @brief Function for delaying execution for a number of microseconds. 83 : : * 84 : : * The value of @p time_us is multiplied by the CPU frequency in MHz. Therefore, the delay 85 : : * is limited to the maximum value of the uint32_t type divided by the frequency. 86 : : * @sa NRFX_COREDEP_DELAY_US_LOOP_CYCLES 87 : : * 88 : : * @param time_us Number of microseconds to wait. 89 : : */ 90 : : NRF_STATIC_INLINE void nrfx_coredep_delay_us(uint32_t time_us); 91 : : 92 : : /** @} */ 93 : : 94 : : #ifndef NRF_DECLARE_ONLY 95 : : 96 : : #if NRFX_CHECK(NRFX_DELAY_DWT_BASED) 97 : : 98 : : #if !NRFX_DELAY_DWT_PRESENT 99 : : #error "DWT unit not present in the SoC that is used." 100 : : #endif 101 : : 102 : : NRF_STATIC_INLINE void nrfx_coredep_delay_us(uint32_t time_us) 103 : : { 104 : : if (time_us == 0) 105 : : { 106 : : return; 107 : : } 108 : : uint32_t time_cycles = time_us * NRFX_DELAY_CPU_FREQ_MHZ; 109 : : 110 : : // Save the current state of the DEMCR register to be able to restore it before exiting 111 : : // this function. Enable the trace and debug blocks (including DWT). 112 : : uint32_t core_debug = CoreDebug->DEMCR; 113 : : CoreDebug->DEMCR = core_debug | CoreDebug_DEMCR_TRCENA_Msk; 114 : : 115 : : // Save the current state of the CTRL register in the DWT block. Make sure 116 : : // that the cycle counter is enabled. 117 : : uint32_t dwt_ctrl = DWT->CTRL; 118 : : DWT->CTRL = dwt_ctrl | DWT_CTRL_CYCCNTENA_Msk; 119 : : 120 : : // Store start value of the cycle counter. 121 : : uint32_t cyccnt_initial = DWT->CYCCNT; 122 : : 123 : : // Delay required time. 124 : : while ((DWT->CYCCNT - cyccnt_initial) < time_cycles) 125 : : {} 126 : : 127 : : // Restore preserved registers. 128 : : DWT->CTRL = dwt_ctrl; 129 : : CoreDebug->DEMCR = core_debug; 130 : : } 131 : : 132 : : #else // NRFX_CHECK(NRFX_DELAY_DWT_BASED) 133 : : 134 : 1791410 : NRF_STATIC_INLINE void nrfx_coredep_delay_us(uint32_t time_us) 135 : : { 136 [ - + ]: 1791410 : if (time_us == 0) 137 : : { 138 : 0 : return; 139 : : } 140 : : 141 : : // Allow overriding the number of cycles per loop iteration, in case it is 142 : : // needed to adjust this number externally (for example, when the SoC is 143 : : // emulated). 144 : : #ifndef NRFX_COREDEP_DELAY_US_LOOP_CYCLES 145 : : #if defined(NRF51) 146 : : // The loop takes 4 cycles: 1 for SUBS, 3 for BHI. 147 : : #define NRFX_COREDEP_DELAY_US_LOOP_CYCLES 4 148 : : #elif defined(NRF52805_XXAA) || defined(NRF52810_XXAA) || \ 149 : : defined(NRF52811_XXAA) || defined(NRF52820_XXAA) 150 : : // The loop takes 7 cycles: 1 for SUBS, 2 for BHI, 2 wait states 151 : : // for each instruction. 152 : : #define NRFX_COREDEP_DELAY_US_LOOP_CYCLES 7 153 : : #else 154 : : // The loop takes 3 cycles: 1 for SUBS, 2 for BHI. 155 : : #define NRFX_COREDEP_DELAY_US_LOOP_CYCLES 3 156 : : #endif 157 : : #endif // NRFX_COREDEP_DELAY_US_LOOP_CYCLES 158 : : // Align the machine code, so that it can be cached properly and no extra 159 : : // wait states appear. 160 : : __ALIGN(16) 161 : : static const uint16_t delay_machine_code[] = { 162 : : 0x3800 + NRFX_COREDEP_DELAY_US_LOOP_CYCLES, // SUBS r0, #loop_cycles 163 : : 0xd8fd, // BHI .-2 164 : : 0x4770 // BX LR 165 : : }; 166 : : 167 : : typedef void (* delay_func_t)(uint32_t); 168 : 1791410 : const delay_func_t delay_cycles = 169 : : // Set LSB to 1 to execute the code in the Thumb mode. 170 : 1791410 : (delay_func_t)((((uint32_t)delay_machine_code) | 1)); 171 : 1791410 : uint32_t cycles = time_us * NRFX_DELAY_CPU_FREQ_MHZ; 172 : 1791410 : delay_cycles(cycles); 173 : : } 174 : : 175 : : #endif // !NRFX_CHECK(NRFX_DELAY_DWT_BASED_DELAY) 176 : : 177 : : #endif // NRF_DECLARE_ONLY 178 : : 179 : : #endif // NRFX_COREDEP_H__