mbed library sources

Dependents:   Encrypted my_mbed lklk CyaSSL_DTLS_Cellular ... more

Superseded

This library was superseded by mbed-dev - https://os.mbed.com/users/mbed_official/code/mbed-dev/.

Development branch of the mbed library sources. This library is kept in synch with the latest changes from the mbed SDK and it is not guaranteed to work.

If you are looking for a stable and tested release, please import one of the official mbed library releases:

Import librarymbed

The official Mbed 2 C/C++ SDK provides the software platform and libraries to build your applications.

Committer:
mbed_official
Date:
Thu Aug 13 10:30:09 2015 +0100
Revision:
603:3c75ef011213
Parent:
495:01cb89f68337
Synchronized with git revision 7cbf9896cc73d825b242028a5f95030a9e1016a4

Full URL: https://github.com/mbedmicro/mbed/commit/7cbf9896cc73d825b242028a5f95030a9e1016a4/

Added requirements.txt file

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mbed_official 85:e1a8e879a6a9 1 /* mbed Microcontroller Library
mbed_official 104:a6a92e2e5a92 2 * Copyright (c) 2013 Nordic Semiconductor
mbed_official 85:e1a8e879a6a9 3 *
mbed_official 85:e1a8e879a6a9 4 * Licensed under the Apache License, Version 2.0 (the "License");
mbed_official 85:e1a8e879a6a9 5 * you may not use this file except in compliance with the License.
mbed_official 85:e1a8e879a6a9 6 * You may obtain a copy of the License at
mbed_official 85:e1a8e879a6a9 7 *
mbed_official 85:e1a8e879a6a9 8 * http://www.apache.org/licenses/LICENSE-2.0
mbed_official 85:e1a8e879a6a9 9 *
mbed_official 85:e1a8e879a6a9 10 * Unless required by applicable law or agreed to in writing, software
mbed_official 85:e1a8e879a6a9 11 * distributed under the License is distributed on an "AS IS" BASIS,
mbed_official 85:e1a8e879a6a9 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
mbed_official 85:e1a8e879a6a9 13 * See the License for the specific language governing permissions and
mbed_official 85:e1a8e879a6a9 14 * limitations under the License.
mbed_official 85:e1a8e879a6a9 15 */
mbed_official 85:e1a8e879a6a9 16 #include <stddef.h>
mbed_official 495:01cb89f68337 17 #include <stdbool.h>
mbed_official 85:e1a8e879a6a9 18 #include "us_ticker_api.h"
mbed_official 85:e1a8e879a6a9 19 #include "cmsis.h"
mbed_official 85:e1a8e879a6a9 20 #include "PeripheralNames.h"
mbed_official 495:01cb89f68337 21 #include "nrf_delay.h"
mbed_official 495:01cb89f68337 22
mbed_official 495:01cb89f68337 23 /*
mbed_official 495:01cb89f68337 24 * Note: The micro-second timer API on the nRF51 platform is implemented using
mbed_official 495:01cb89f68337 25 * the RTC counter run at 32kHz (sourced from an external oscillator). This is
mbed_official 495:01cb89f68337 26 * a trade-off between precision and power. Running a normal 32-bit MCU counter
mbed_official 495:01cb89f68337 27 * at high frequency causes the average power consumption to rise to a few
mbed_official 495:01cb89f68337 28 * hundred micro-amps, which is prohibitive for typical low-power BLE
mbed_official 495:01cb89f68337 29 * applications.
mbed_official 495:01cb89f68337 30 * A 32kHz clock doesn't offer the precision needed for keeping u-second time,
mbed_official 495:01cb89f68337 31 * but we're assuming that this will not be a problem for the average user.
mbed_official 495:01cb89f68337 32 */
mbed_official 495:01cb89f68337 33
mbed_official 495:01cb89f68337 34 #define MAX_RTC_COUNTER_VAL 0x00FFFFFF /**< Maximum value of the RTC counter. */
mbed_official 495:01cb89f68337 35 #define RTC_CLOCK_FREQ (uint32_t)(32768)
mbed_official 495:01cb89f68337 36 #define RTC1_IRQ_PRI 3 /**< Priority of the RTC1 interrupt (used
mbed_official 495:01cb89f68337 37 * for checking for timeouts and executing
mbed_official 495:01cb89f68337 38 * timeout handlers). This must be the same
mbed_official 495:01cb89f68337 39 * as APP_IRQ_PRIORITY_LOW; taken from the
mbed_official 495:01cb89f68337 40 * Nordic SDK. */
mbed_official 495:01cb89f68337 41 #define MAX_RTC_TASKS_DELAY 47 /**< Maximum delay until an RTC task is executed. */
mbed_official 495:01cb89f68337 42
mbed_official 495:01cb89f68337 43 #define FUZZY_RTC_TICKS 2 /* RTC COMPARE occurs when a CC register is N and the RTC
mbed_official 495:01cb89f68337 44 * COUNTER value transitions from N-1 to N. If we're trying to
mbed_official 495:01cb89f68337 45 * setup a callback for a time which will arrive very shortly,
mbed_official 495:01cb89f68337 46 * there are limits to how short the callback interval may be for us
mbed_official 495:01cb89f68337 47 * to rely upon the RTC Compare trigger. If the COUNTER is N,
mbed_official 495:01cb89f68337 48 * writing N+2 to a CC register is guaranteed to trigger a COMPARE
mbed_official 495:01cb89f68337 49 * event at N+2. */
mbed_official 495:01cb89f68337 50
mbed_official 495:01cb89f68337 51 #define RTC_UNITS_TO_MICROSECONDS(RTC_UNITS) (((RTC_UNITS) * (uint64_t)1000000) / RTC_CLOCK_FREQ)
mbed_official 495:01cb89f68337 52 #define MICROSECONDS_TO_RTC_UNITS(MICROS) ((((uint64_t)(MICROS) * RTC_CLOCK_FREQ) + 999999) / 1000000)
mbed_official 495:01cb89f68337 53
mbed_official 495:01cb89f68337 54 static bool us_ticker_inited = false;
mbed_official 495:01cb89f68337 55 static volatile uint32_t overflowCount; /**< The number of times the 24-bit RTC counter has overflowed. */
mbed_official 495:01cb89f68337 56 static volatile bool us_ticker_callbackPending = false;
mbed_official 495:01cb89f68337 57 static uint32_t us_ticker_callbackTimestamp;
mbed_official 495:01cb89f68337 58
mbed_official 495:01cb89f68337 59 static inline void rtc1_enableCompareInterrupt(void)
mbed_official 495:01cb89f68337 60 {
mbed_official 495:01cb89f68337 61 NRF_RTC1->EVTENCLR = RTC_EVTEN_COMPARE0_Msk;
mbed_official 495:01cb89f68337 62 NRF_RTC1->INTENSET = RTC_INTENSET_COMPARE0_Msk;
mbed_official 495:01cb89f68337 63 }
mbed_official 495:01cb89f68337 64
mbed_official 495:01cb89f68337 65 static inline void rtc1_disableCompareInterrupt(void)
mbed_official 495:01cb89f68337 66 {
mbed_official 495:01cb89f68337 67 NRF_RTC1->INTENCLR = RTC_INTENSET_COMPARE0_Msk;
mbed_official 495:01cb89f68337 68 NRF_RTC1->EVTENCLR = RTC_EVTEN_COMPARE0_Msk;
mbed_official 495:01cb89f68337 69 }
mbed_official 495:01cb89f68337 70
mbed_official 495:01cb89f68337 71 static inline void rtc1_enableOverflowInterrupt(void)
mbed_official 495:01cb89f68337 72 {
mbed_official 495:01cb89f68337 73 NRF_RTC1->EVTENCLR = RTC_EVTEN_OVRFLW_Msk;
mbed_official 495:01cb89f68337 74 NRF_RTC1->INTENSET = RTC_INTENSET_OVRFLW_Msk;
mbed_official 495:01cb89f68337 75 }
mbed_official 495:01cb89f68337 76
mbed_official 495:01cb89f68337 77 static inline void rtc1_disableOverflowInterrupt(void)
mbed_official 495:01cb89f68337 78 {
mbed_official 495:01cb89f68337 79 NRF_RTC1->INTENCLR = RTC_INTENSET_OVRFLW_Msk;
mbed_official 495:01cb89f68337 80 NRF_RTC1->EVTENCLR = RTC_EVTEN_OVRFLW_Msk;
mbed_official 495:01cb89f68337 81 }
mbed_official 495:01cb89f68337 82
mbed_official 495:01cb89f68337 83 static inline void invokeCallback(void)
mbed_official 495:01cb89f68337 84 {
mbed_official 495:01cb89f68337 85 us_ticker_callbackPending = false;
mbed_official 495:01cb89f68337 86 rtc1_disableCompareInterrupt();
mbed_official 495:01cb89f68337 87 us_ticker_irq_handler();
mbed_official 495:01cb89f68337 88 }
mbed_official 127:ce7cebc0511f 89
mbed_official 495:01cb89f68337 90 /**
mbed_official 495:01cb89f68337 91 * @brief Function for starting the RTC1 timer. The RTC timer is expected to
mbed_official 495:01cb89f68337 92 * keep running--some interrupts may be disabled temporarily.
mbed_official 495:01cb89f68337 93 */
mbed_official 495:01cb89f68337 94 static void rtc1_start()
mbed_official 495:01cb89f68337 95 {
mbed_official 495:01cb89f68337 96 NRF_RTC1->PRESCALER = 0; /* for no pre-scaling. */
mbed_official 495:01cb89f68337 97
mbed_official 495:01cb89f68337 98 rtc1_enableOverflowInterrupt();
mbed_official 495:01cb89f68337 99
mbed_official 495:01cb89f68337 100 NVIC_SetPriority(RTC1_IRQn, RTC1_IRQ_PRI);
mbed_official 495:01cb89f68337 101 NVIC_ClearPendingIRQ(RTC1_IRQn);
mbed_official 495:01cb89f68337 102 NVIC_EnableIRQ(RTC1_IRQn);
mbed_official 495:01cb89f68337 103
mbed_official 495:01cb89f68337 104 NRF_RTC1->TASKS_START = 1;
mbed_official 495:01cb89f68337 105 nrf_delay_us(MAX_RTC_TASKS_DELAY);
mbed_official 495:01cb89f68337 106 }
mbed_official 495:01cb89f68337 107
mbed_official 495:01cb89f68337 108 /**
mbed_official 495:01cb89f68337 109 * @brief Function for stopping the RTC1 timer. We don't expect to call this.
mbed_official 495:01cb89f68337 110 */
mbed_official 495:01cb89f68337 111 void rtc1_stop(void)
mbed_official 495:01cb89f68337 112 {
mbed_official 495:01cb89f68337 113 NVIC_DisableIRQ(RTC1_IRQn);
mbed_official 495:01cb89f68337 114 rtc1_disableCompareInterrupt();
mbed_official 495:01cb89f68337 115 rtc1_disableOverflowInterrupt();
mbed_official 495:01cb89f68337 116
mbed_official 495:01cb89f68337 117 NRF_RTC1->TASKS_STOP = 1;
mbed_official 495:01cb89f68337 118 nrf_delay_us(MAX_RTC_TASKS_DELAY);
mbed_official 495:01cb89f68337 119
mbed_official 495:01cb89f68337 120 NRF_RTC1->TASKS_CLEAR = 1;
mbed_official 495:01cb89f68337 121 nrf_delay_us(MAX_RTC_TASKS_DELAY);
mbed_official 495:01cb89f68337 122 }
mbed_official 495:01cb89f68337 123
mbed_official 495:01cb89f68337 124 /**
mbed_official 495:01cb89f68337 125 * @brief Function for returning the current value of the RTC1 counter.
mbed_official 495:01cb89f68337 126 *
mbed_official 495:01cb89f68337 127 * @return Current RTC1 counter as a 64-bit value with 56-bit precision (even
mbed_official 495:01cb89f68337 128 * though the underlying counter is 24-bit)
mbed_official 495:01cb89f68337 129 */
mbed_official 495:01cb89f68337 130 static inline uint64_t rtc1_getCounter64(void)
mbed_official 495:01cb89f68337 131 {
mbed_official 495:01cb89f68337 132 if (NRF_RTC1->EVENTS_OVRFLW) {
mbed_official 495:01cb89f68337 133 overflowCount++;
mbed_official 495:01cb89f68337 134 NRF_RTC1->EVENTS_OVRFLW = 0;
mbed_official 495:01cb89f68337 135 NRF_RTC1->EVTENCLR = RTC_EVTEN_OVRFLW_Msk;
mbed_official 495:01cb89f68337 136 }
mbed_official 495:01cb89f68337 137 return ((uint64_t)overflowCount << 24) | NRF_RTC1->COUNTER;
mbed_official 495:01cb89f68337 138 }
mbed_official 495:01cb89f68337 139
mbed_official 495:01cb89f68337 140 /**
mbed_official 495:01cb89f68337 141 * @brief Function for returning the current value of the RTC1 counter.
mbed_official 495:01cb89f68337 142 *
mbed_official 495:01cb89f68337 143 * @return Current RTC1 counter as a 32-bit value (even though the underlying counter is 24-bit)
mbed_official 495:01cb89f68337 144 */
mbed_official 495:01cb89f68337 145 static inline uint32_t rtc1_getCounter(void)
mbed_official 495:01cb89f68337 146 {
mbed_official 495:01cb89f68337 147 return rtc1_getCounter64();
mbed_official 495:01cb89f68337 148 }
mbed_official 495:01cb89f68337 149
mbed_official 495:01cb89f68337 150 /**
mbed_official 495:01cb89f68337 151 * @brief Function for handling the RTC1 interrupt.
mbed_official 495:01cb89f68337 152 *
mbed_official 495:01cb89f68337 153 * @details Checks for timeouts, and executes timeout handlers for expired timers.
mbed_official 495:01cb89f68337 154 */
mbed_official 495:01cb89f68337 155 void RTC1_IRQHandler(void)
mbed_official 495:01cb89f68337 156 {
mbed_official 495:01cb89f68337 157 if (NRF_RTC1->EVENTS_OVRFLW) {
mbed_official 495:01cb89f68337 158 overflowCount++;
mbed_official 495:01cb89f68337 159 NRF_RTC1->EVENTS_OVRFLW = 0;
mbed_official 495:01cb89f68337 160 NRF_RTC1->EVTENCLR = RTC_EVTEN_OVRFLW_Msk;
mbed_official 495:01cb89f68337 161 }
mbed_official 603:3c75ef011213 162 if (NRF_RTC1->EVENTS_COMPARE[0]) {
mbed_official 495:01cb89f68337 163 NRF_RTC1->EVENTS_COMPARE[0] = 0;
mbed_official 495:01cb89f68337 164 NRF_RTC1->EVTENCLR = RTC_EVTEN_COMPARE0_Msk;
mbed_official 603:3c75ef011213 165 if (us_ticker_callbackPending && ((int)(us_ticker_callbackTimestamp - rtc1_getCounter()) <= 0))
mbed_official 603:3c75ef011213 166 invokeCallback();
mbed_official 495:01cb89f68337 167 }
mbed_official 495:01cb89f68337 168 }
mbed_official 300:55638feb26a4 169
mbed_official 300:55638feb26a4 170 void us_ticker_init(void)
mbed_official 300:55638feb26a4 171 {
mbed_official 304:89b9c3a9a045 172 if (us_ticker_inited) {
mbed_official 85:e1a8e879a6a9 173 return;
mbed_official 85:e1a8e879a6a9 174 }
mbed_official 300:55638feb26a4 175
mbed_official 495:01cb89f68337 176 rtc1_start();
mbed_official 304:89b9c3a9a045 177 us_ticker_inited = true;
mbed_official 85:e1a8e879a6a9 178 }
mbed_official 85:e1a8e879a6a9 179
mbed_official 300:55638feb26a4 180 uint32_t us_ticker_read()
mbed_official 300:55638feb26a4 181 {
mbed_official 304:89b9c3a9a045 182 if (!us_ticker_inited) {
mbed_official 304:89b9c3a9a045 183 us_ticker_init();
mbed_official 304:89b9c3a9a045 184 }
mbed_official 304:89b9c3a9a045 185
mbed_official 495:01cb89f68337 186 /* Return a pseudo microsecond counter value. This is only as precise as the
mbed_official 495:01cb89f68337 187 * 32khz low-freq clock source, but could be adequate.*/
mbed_official 495:01cb89f68337 188 return RTC_UNITS_TO_MICROSECONDS(rtc1_getCounter64());
mbed_official 304:89b9c3a9a045 189 }
mbed_official 304:89b9c3a9a045 190
mbed_official 495:01cb89f68337 191 /**
mbed_official 495:01cb89f68337 192 * Setup the us_ticker callback interrupt to go at the given timestamp.
mbed_official 495:01cb89f68337 193 *
mbed_official 495:01cb89f68337 194 * @Note: Only one callback is pending at any time.
mbed_official 495:01cb89f68337 195 *
mbed_official 495:01cb89f68337 196 * @Note: If a callback is pending, and this function is called again, the new
mbed_official 495:01cb89f68337 197 * callback-time overrides the existing callback setting. It is the caller's
mbed_official 495:01cb89f68337 198 * responsibility to ensure that this function is called to setup a callback for
mbed_official 495:01cb89f68337 199 * the earliest timeout.
mbed_official 495:01cb89f68337 200 *
mbed_official 495:01cb89f68337 201 * @Note: If this function is used to setup an interrupt which is immediately
mbed_official 495:01cb89f68337 202 * pending--such as for 'now' or a time in the past,--then the callback is
mbed_official 495:01cb89f68337 203 * invoked a few ticks later.
mbed_official 495:01cb89f68337 204 */
mbed_official 304:89b9c3a9a045 205 void us_ticker_set_interrupt(timestamp_t timestamp)
mbed_official 304:89b9c3a9a045 206 {
mbed_official 304:89b9c3a9a045 207 if (!us_ticker_inited) {
mbed_official 85:e1a8e879a6a9 208 us_ticker_init();
mbed_official 85:e1a8e879a6a9 209 }
mbed_official 300:55638feb26a4 210
mbed_official 495:01cb89f68337 211 /*
mbed_official 495:01cb89f68337 212 * The argument to this function is a 32-bit microsecond timestamp for when
mbed_official 495:01cb89f68337 213 * a callback should be invoked. On the nRF51, we use an RTC timer running
mbed_official 495:01cb89f68337 214 * at 32kHz to implement a low-power us-ticker. This results in a problem
mbed_official 495:01cb89f68337 215 * based on the fact that 1000000 is not a multiple of 32768.
mbed_official 495:01cb89f68337 216 *
mbed_official 495:01cb89f68337 217 * Going from a micro-second based timestamp to a 32kHz based RTC-time is a
mbed_official 495:01cb89f68337 218 * linear mapping; but this mapping doesn't preserve wraparounds--i.e. when
mbed_official 495:01cb89f68337 219 * the 32-bit micro-second timestamp wraps around unfortunately the
mbed_official 495:01cb89f68337 220 * underlying RTC counter doesn't. The result is that timestamp expiry
mbed_official 495:01cb89f68337 221 * checks on micro-second timestamps don't yield the same result when
mbed_official 495:01cb89f68337 222 * applied on the corresponding RTC timestamp values.
mbed_official 495:01cb89f68337 223 *
mbed_official 495:01cb89f68337 224 * One solution is to translate the incoming 32-bit timestamp into a virtual
mbed_official 495:01cb89f68337 225 * 64-bit timestamp based on the knowledge of system-uptime, and then use
mbed_official 495:01cb89f68337 226 * this wraparound-free 64-bit value to do a linear mapping to RTC time.
mbed_official 495:01cb89f68337 227 * System uptime on an nRF is maintained using the 24-bit RTC counter. We
mbed_official 495:01cb89f68337 228 * track the overflow count to extend the 24-bit hardware counter by an
mbed_official 495:01cb89f68337 229 * additional 32 bits. RTC_UNITS_TO_MICROSECONDS() converts this into
mbed_official 495:01cb89f68337 230 * microsecond units (in 64-bits).
mbed_official 495:01cb89f68337 231 */
mbed_official 495:01cb89f68337 232 const uint64_t currentTime64 = RTC_UNITS_TO_MICROSECONDS(rtc1_getCounter64());
mbed_official 495:01cb89f68337 233 uint64_t timestamp64 = (currentTime64 & ~(uint64_t)0xFFFFFFFFULL) + timestamp;
mbed_official 495:01cb89f68337 234 if (((uint32_t)currentTime64 > 0x80000000) && (timestamp < 0x80000000)) {
mbed_official 495:01cb89f68337 235 timestamp64 += (uint64_t)0x100000000ULL;
mbed_official 300:55638feb26a4 236 }
mbed_official 495:01cb89f68337 237 uint32_t newCallbackTime = MICROSECONDS_TO_RTC_UNITS(timestamp64);
mbed_official 85:e1a8e879a6a9 238
mbed_official 495:01cb89f68337 239 /* Check for repeat setup of an existing callback. This is actually not
mbed_official 495:01cb89f68337 240 * important; the following code should work even without this check. */
mbed_official 495:01cb89f68337 241 if (us_ticker_callbackPending && (newCallbackTime == us_ticker_callbackTimestamp)) {
mbed_official 304:89b9c3a9a045 242 return;
mbed_official 300:55638feb26a4 243 }
mbed_official 300:55638feb26a4 244
mbed_official 495:01cb89f68337 245 /* Check for callbacks which are immediately (or will *very* shortly become) pending.
mbed_official 495:01cb89f68337 246 * Even if they are immediately pending, they are scheduled to trigger a few
mbed_official 495:01cb89f68337 247 * ticks later. This keeps things simple by invoking the callback from an
mbed_official 495:01cb89f68337 248 * independent interrupt context. */
mbed_official 495:01cb89f68337 249 if ((int)(newCallbackTime - rtc1_getCounter()) <= (int)FUZZY_RTC_TICKS) {
mbed_official 495:01cb89f68337 250 newCallbackTime = rtc1_getCounter() + FUZZY_RTC_TICKS;
mbed_official 300:55638feb26a4 251 }
mbed_official 361:56c2a6244bba 252
mbed_official 495:01cb89f68337 253 NRF_RTC1->CC[0] = newCallbackTime & MAX_RTC_COUNTER_VAL;
mbed_official 495:01cb89f68337 254 us_ticker_callbackTimestamp = newCallbackTime;
mbed_official 495:01cb89f68337 255 if (!us_ticker_callbackPending) {
mbed_official 495:01cb89f68337 256 us_ticker_callbackPending = true;
mbed_official 495:01cb89f68337 257 rtc1_enableCompareInterrupt();
mbed_official 361:56c2a6244bba 258 }
mbed_official 85:e1a8e879a6a9 259 }
mbed_official 85:e1a8e879a6a9 260
mbed_official 300:55638feb26a4 261 void us_ticker_disable_interrupt(void)
mbed_official 300:55638feb26a4 262 {
mbed_official 495:01cb89f68337 263 if (us_ticker_callbackPending) {
mbed_official 495:01cb89f68337 264 rtc1_disableCompareInterrupt();
mbed_official 495:01cb89f68337 265 us_ticker_callbackPending = false;
mbed_official 304:89b9c3a9a045 266 }
mbed_official 85:e1a8e879a6a9 267 }
mbed_official 300:55638feb26a4 268
mbed_official 300:55638feb26a4 269 void us_ticker_clear_interrupt(void)
mbed_official 300:55638feb26a4 270 {
mbed_official 495:01cb89f68337 271 NRF_RTC1->EVENTS_OVRFLW = 0;
mbed_official 495:01cb89f68337 272 NRF_RTC1->EVENTS_COMPARE[0] = 0;
mbed_official 85:e1a8e879a6a9 273 }