1 /*
2  * Copyright (c) 2017 - 2023, 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 <assert.h>
39 #include <stdint.h>
40 #include <string.h>
41 #include "nrfx.h"
42 #include <soc/nrfx_coredep.h>
43 
44 /**
45  * @defgroup nrf_802154_utils Utils definitions used in the 802.15.4 driver
46  * @{
47  * @ingroup nrf_802154
48  * @brief Definitions of utils used in the 802.15.4 driver.
49  */
50 
51 /**@brief RTC clock frequency. */
52 #define NRF_802154_RTC_FREQUENCY               32768UL
53 
54 /**@brief Defines the number of microseconds in one second. */
55 #define NRF_802154_US_PER_S                    1000000ULL
56 
57 /**@brief Number of microseconds in one RTC tick (rounded up). */
58 #define NRF_802154_US_PER_TICK                 NRF_802154_RTC_TICKS_TO_US(1)
59 
60 /**@brief Number of bits to shift RTC_FREQUENCY and US_PER_S to achieve the division by greatest common divisor. */
61 #define NRF_802154_FREQUENCY_US_PER_S_GCD_BITS 6
62 
63 /**@brief Ceil division helper. */
64 #define NRF_802154_DIVIDE_AND_CEIL(A, B)       (((A) + (B)-1) / (B))
65 
66 /**@brief Defines the conversion of RTC ticks to microseconds (us). */
67 #define NRF_802154_RTC_TICKS_TO_US(ticks)                                          \
68     NRF_802154_DIVIDE_AND_CEIL(                                                    \
69         (ticks) * (NRF_802154_US_PER_S >> NRF_802154_FREQUENCY_US_PER_S_GCD_BITS), \
70         (NRF_802154_RTC_FREQUENCY >> NRF_802154_FREQUENCY_US_PER_S_GCD_BITS))
71 
72 /**@brief Macro to get the number of elements in an array.
73  *
74  * @param[in] X   Array.
75  */
76 #define NUMELTS(X)                      (sizeof((X)) / sizeof(X[0]))
77 
78 /**@brief Wait procedure used in a busy loop. */
79 #define nrf_802154_busy_wait()          __WFE()
80 
81 /**@brief Active waiting for given number of microseconds.
82  *
83  * It is guaranteed that execution of this macro will take at least @c time_in_us
84  * number of microseconds.
85  */
86 #define nrf_802154_delay_us(time_in_us) nrfx_coredep_delay_us(time_in_us)
87 
88 /**@brief Type holding MCU critical section state.
89  *
90  * Variable of this type is required to hold state saved by @ref nrf_802154_mcu_critical_enter
91  * and restored by @ref nrf_802154_mcu_critical_exit.
92  */
93 typedef uint32_t nrf_802154_mcu_critical_state_t;
94 
95 /**@brief Enters critical section on MCU level.
96  *
97  * Use @ref nrf_802154_mcu_critical_exit complementary. Consider following code:
98  * @code
99  * nrf_802154_mcu_critical_state_t mcu_cs;
100  * nrf_802154_mcu_critical_enter(mcu_cs);
101  * // do your critical stuff as fast as possible
102  * nrf_802154_mcu_critical_exit(mcu_cs);
103  * @endcode
104  *
105  * @param mcu_critical_state    Variable of @ref nrf_802154_mcu_critical_state_t where current
106  *                              state of MCU level critical section will be stored.
107  */
108 #define nrf_802154_mcu_critical_enter(mcu_critical_state) \
109     do                                                    \
110     {                                                     \
111         (mcu_critical_state) = __get_PRIMASK();           \
112         __disable_irq();                                  \
113     }                                                     \
114     while (0)
115 
116 /**@brief Exits critical section on MCU level.
117  *
118  * This shall be used complementary to @ref nrf_802154_mcu_critical_enter.
119  *
120  * @param mcu_critical_state    Variable of @ref nrf_802154_mcu_critical_state_t where
121  *                              state of MCU level critical section is stored by
122  *                              former call to @ref nrf_802154_mcu_critical_enter
123  */
124 #define nrf_802154_mcu_critical_exit(mcu_critical_state) \
125     do                                                   \
126     {                                                    \
127         __set_PRIMASK(mcu_critical_state);               \
128     }                                                    \
129     while (0)
130 
NRF_802154_US_TO_RTC_TICKS(uint64_t time)131 static inline uint64_t NRF_802154_US_TO_RTC_TICKS(uint64_t time)
132 {
133     uint64_t t1, u1;
134     uint64_t result;
135 
136     /* The required range for time is [0..315360000000000], and the calculation below is
137        verified to work within a broader range [0...2^49 ~ 17 years].
138 
139        This first step in the calculation is to find out how many units
140        of 15625 us there are in the input_us, because 512 RTC units
141        correspond _exactly_ to 15625 us. The desired calculation is therefore
142        t1 = time / 15625, but the division is slow and therefore let's calculate
143        t1 = time * k instead. The constant k is 1/15625, shifted up by as many bits
144        as possible without causing overflow during the calculation.
145 
146        49 bits are needed to store the maximum value that time can have, and the
147        lowest 13 bits in that value can be shifted away because a minimum of 14 bits
148        are needed to store the divisor.
149 
150        This means that the time can be reduced to 49 - 13 = 36 bits to make space
151        for k.
152 
153        The most suitable number of shift for the value 1/15625 = 0.000064
154        (binary 0.00000000000001000011000110111101111...) is 41, because that results
155        in a 28-bit number that does not cause overflow in the multiplication.
156 
157        ((2^41)/15625) is equal to 0x8637bd0, and is written in a hexadecimal representation
158        to show the bit width of the number. Shifting is limited to 41 bits because:
159          1  The time uses up to 49 bits;
160          2) The time can only be shifted down 13 bits to avoid shifting away
161             a full unit of 15625 microseconds;
162          3) The maximum value of the calculation would otherwise overflow (that is,
163             (315360000000000 >> 13) * 0x8637bd0 = 0x4b300bfcd0aefde0 would no longer be less than
164             0Xffffffffffffffff).
165 
166        There is a possible loss of precision, so that t1 will be up to 93*15625 _smaller_
167        than the accurate number. This is taken into account in the next step.
168      */
169 
170     t1     = ((time >> 13) * 0x8637bd0) >> 28; // ((time >> 13) * (2^41 / 15625)) >> (41 - 13)
171     result = t1 * 512;
172     t1     = time - t1 * 15625;
173 
174     /* This second step of the calculation is to find out how many RTC units there are
175        still left in the remaining microseconds.
176 
177        ((2^56)/15625) is equal to 0x431bde82d7b, and is written in a hexadecimal representation
178        to show the bit width of the number. Shifting 56 bits is determined by the worst
179        case value of t1. The constant is selected by using the same methodology as in the
180        first step of the calculation above.
181 
182        The possible loss of precision in the calculation above can make t1 93*15625 lower
183        than it should have been here. The worst case found is that t1 can be 1453125, and
184        therefore there is no overflow in the calculation
185        1453125 * 0x431bde82d7b = 0x5cfffffffff76627 (that is, it is less than 0xffffffffffffffff).
186 
187        15625 below is the binary representation of 30.51757813 (11110.100001001)
188        scaled up by 2^9, and the calculation below are therefore using that scale.
189 
190        Rounding up to the nearest RTC tick is done by adding the value of the least
191        significant bits of the fraction (that is, adding the value of bits 1..47 of the scaled
192        up timer unit size (2^47)) to the calculated value before scaling the final
193        value down to RTC ticks.*/
194 
195     // ceil((time * (2^56 / 15625)) >> (56 - 9))
196     assert(t1 <= 1453125);
197     u1   = (t1 * 0x431bde82d7b); // (time * (2^56 / 15625))
198     u1  += 0x7fffffffffff;       // round up
199     u1 >>= 47;                   // ceil(u1 >> (56 - 9))
200 
201     result += u1;
202 
203     return result;
204 }
205 
206 /**
207  *@}
208  **/
209 
210 #endif // NRF_802154_UTILS_H__
211