nrfxlib API 3.3.99
Loading...
Searching...
No Matches
nrf_802154_utils.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2017, 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 Nordic Semiconductor ASA 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
35#ifndef NRF_802154_UTILS_H__
36#define NRF_802154_UTILS_H__
37
38#include "nrf_802154_assert.h"
39#include <stdint.h>
40#include "nrfx.h"
41#include <lib/nrfx_coredep.h>
42
43#ifdef __STATIC_INLINE__
44#undef __STATIC_INLINE__
45#endif
46
47#ifdef NRF_802154_UTILS_DECLARE_ONLY
48#define __STATIC_INLINE__
49#else
50#define __STATIC_INLINE__ __STATIC_INLINE
51#endif
52
61#define NRF_802154_RTC_FREQUENCY 32768UL
62
64#define NRF_802154_US_PER_S 1000000ULL
65
67#define NRF_802154_US_PER_TICK NRF_802154_RTC_TICKS_TO_US(1)
68
70#define NRF_802154_FREQUENCY_US_PER_S_GCD_BITS 6
71
73#define NRF_802154_DIVIDE_AND_CEIL(A, B) (((A) + (B)-1) / (B))
74
76#define NRF_802154_RTC_TICKS_TO_US(ticks) \
77 NRF_802154_DIVIDE_AND_CEIL( \
78 (ticks) * (NRF_802154_US_PER_S >> NRF_802154_FREQUENCY_US_PER_S_GCD_BITS), \
79 (NRF_802154_RTC_FREQUENCY >> NRF_802154_FREQUENCY_US_PER_S_GCD_BITS))
80
87
93__STATIC_INLINE__ void nrf_802154_delay_us(uint32_t time_in_us);
94
108
116
123__STATIC_INLINE__ uint64_t NRF_802154_US_TO_RTC_TICKS(uint64_t time);
124
125#ifndef NRF_802154_UTILS_DECLARE_ONLY
126
127__STATIC_INLINE__ void nrf_802154_delay_us(uint32_t time_in_us)
128{
129 nrfx_coredep_delay_us(time_in_us);
130}
131
133{
135
136 mcu_cs = __get_PRIMASK();
137 __disable_irq();
138
139 return mcu_cs;
140}
141
143{
144 __set_PRIMASK(mcu_cs);
145}
146
147__STATIC_INLINE__ uint64_t NRF_802154_US_TO_RTC_TICKS(uint64_t time)
148{
149 uint64_t t1, u1;
150 uint64_t result;
151
152 /* The required range for time is [0..315360000000000], and the calculation below is
153 verified to work within a broader range [0...2^49 ~ 17 years].
154
155 This first step in the calculation is to find out how many units
156 of 15625 us there are in the input_us, because 512 RTC units
157 correspond _exactly_ to 15625 us. The desired calculation is therefore
158 t1 = time / 15625, but the division is slow and therefore let's calculate
159 t1 = time * k instead. The constant k is 1/15625, shifted up by as many bits
160 as possible without causing overflow during the calculation.
161
162 49 bits are needed to store the maximum value that time can have, and the
163 lowest 13 bits in that value can be shifted away because a minimum of 14 bits
164 are needed to store the divisor.
165
166 This means that the time can be reduced to 49 - 13 = 36 bits to make space
167 for k.
168
169 The most suitable number of shift for the value 1/15625 = 0.000064
170 (binary 0.00000000000001000011000110111101111...) is 41, because that results
171 in a 28-bit number that does not cause overflow in the multiplication.
172
173 ((2^41)/15625) is equal to 0x8637bd0, and is written in a hexadecimal representation
174 to show the bit width of the number. Shifting is limited to 41 bits because:
175 1 The time uses up to 49 bits;
176 2) The time can only be shifted down 13 bits to avoid shifting away
177 a full unit of 15625 microseconds;
178 3) The maximum value of the calculation would otherwise overflow (that is,
179 (315360000000000 >> 13) * 0x8637bd0 = 0x4b300bfcd0aefde0 would no longer be less than
180 0Xffffffffffffffff).
181
182 There is a possible loss of precision, so that t1 will be up to 93*15625 _smaller_
183 than the accurate number. This is taken into account in the next step.
184 */
185
186 t1 = ((time >> 13) * 0x8637bd0) >> 28; // ((time >> 13) * (2^41 / 15625)) >> (41 - 13)
187 result = t1 * 512;
188 t1 = time - t1 * 15625;
189
190 /* This second step of the calculation is to find out how many RTC units there are
191 still left in the remaining microseconds.
192
193 ((2^56)/15625) is equal to 0x431bde82d7b, and is written in a hexadecimal representation
194 to show the bit width of the number. Shifting 56 bits is determined by the worst
195 case value of t1. The constant is selected by using the same methodology as in the
196 first step of the calculation above.
197
198 The possible loss of precision in the calculation above can make t1 93*15625 lower
199 than it should have been here. The worst case found is that t1 can be 1453125, and
200 therefore there is no overflow in the calculation
201 1453125 * 0x431bde82d7b = 0x5cfffffffff76627 (that is, it is less than 0xffffffffffffffff).
202
203 15625 below is the binary representation of 30.51757813 (11110.100001001)
204 scaled up by 2^9, and the calculation below are therefore using that scale.
205
206 Rounding up to the nearest RTC tick is done by adding the value of the least
207 significant bits of the fraction (that is, adding the value of bits 1..47 of the scaled
208 up timer unit size (2^47)) to the calculated value before scaling the final
209 value down to RTC ticks.*/
210
211 // ceil((time * (2^56 / 15625)) >> (56 - 9))
212 NRF_802154_ASSERT(t1 <= 1453125);
213 u1 = (t1 * 0x431bde82d7b); // (time * (2^56 / 15625))
214 u1 += 0x7fffffffffff; // round up
215 u1 >>= 47; // ceil(u1 >> (56 - 9))
216
217 result += u1;
218
219 return result;
220}
221
222#endif /* NRF_802154_UTILS_DECLARE_ONLY */
223
228#endif // NRF_802154_UTILS_H__
__STATIC_INLINE nrf_802154_mcu_critical_state_t nrf_802154_mcu_critical_enter(void)
Enters critical section on MCU level.
Definition nrf_802154_utils.h:132
__STATIC_INLINE void nrf_802154_mcu_critical_exit(nrf_802154_mcu_critical_state_t mcu_cs)
Exits critical section on MCU level.
Definition nrf_802154_utils.h:142
__STATIC_INLINE uint64_t NRF_802154_US_TO_RTC_TICKS(uint64_t time)
Convert microseconds to RTC ticks.
Definition nrf_802154_utils.h:147
__STATIC_INLINE void nrf_802154_delay_us(uint32_t time_in_us)
Active waiting for given number of microseconds.
Definition nrf_802154_utils.h:127
uint32_t nrf_802154_mcu_critical_state_t
Type holding MCU critical section state.
Definition nrf_802154_utils.h:86
#define NRF_802154_ASSERT(condition)
Definition nrf_802154_assert.h:45