1 /* 2 * Copyright (c) 2014 - 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 32 #include <nrfx.h> 33 34 #if NRFX_CHECK(NRFX_RTC_ENABLED) 35 36 #if !(NRFX_CHECK(NRFX_RTC0_ENABLED) || NRFX_CHECK(NRFX_RTC1_ENABLED) || \ 37 NRFX_CHECK(NRFX_RTC2_ENABLED)) 38 #error "No enabled RTC instances. Check <nrfx_config.h>." 39 #endif 40 41 #include <nrfx_rtc.h> 42 43 #define NRFX_LOG_MODULE RTC 44 #include <nrfx_log.h> 45 46 #define EVT_TO_STR(event) \ 47 (event == NRF_RTC_EVENT_TICK ? "NRF_RTC_EVENT_TICK" : \ 48 (event == NRF_RTC_EVENT_OVERFLOW ? "NRF_RTC_EVENT_OVERFLOW" : \ 49 (event == NRF_RTC_EVENT_COMPARE_0 ? "NRF_RTC_EVENT_COMPARE_0" : \ 50 (event == NRF_RTC_EVENT_COMPARE_1 ? "NRF_RTC_EVENT_COMPARE_1" : \ 51 (event == NRF_RTC_EVENT_COMPARE_2 ? "NRF_RTC_EVENT_COMPARE_2" : \ 52 (event == NRF_RTC_EVENT_COMPARE_3 ? "NRF_RTC_EVENT_COMPARE_3" : \ 53 "UNKNOWN EVENT")))))) 54 55 56 /**@brief RTC driver instance control block structure. */ 57 typedef struct 58 { 59 nrfx_drv_state_t state; /**< Instance state. */ 60 bool reliable; /**< Reliable mode flag. */ 61 uint8_t tick_latency; /**< Maximum length of interrupt handler in ticks (max 7.7 ms). */ 62 } nrfx_rtc_cb_t; 63 64 // User callbacks local storage. 65 static nrfx_rtc_handler_t m_handlers[NRFX_RTC_ENABLED_COUNT]; 66 static nrfx_rtc_cb_t m_cb[NRFX_RTC_ENABLED_COUNT]; 67 68 nrfx_err_t nrfx_rtc_init(nrfx_rtc_t const * const p_instance, 69 nrfx_rtc_config_t const * p_config, 70 nrfx_rtc_handler_t handler) 71 { 72 NRFX_ASSERT(p_config); 73 NRFX_ASSERT(handler); 74 nrfx_err_t err_code; 75 76 m_handlers[p_instance->instance_id] = handler; 77 78 if (m_cb[p_instance->instance_id].state != NRFX_DRV_STATE_UNINITIALIZED) 79 { 80 err_code = NRFX_ERROR_INVALID_STATE; 81 NRFX_LOG_WARNING("Function: %s, error code: %s.", 82 __func__, 83 NRFX_LOG_ERROR_STRING_GET(err_code)); 84 return err_code; 85 } 86 87 NRFX_IRQ_PRIORITY_SET(p_instance->irq, p_config->interrupt_priority); 88 NRFX_IRQ_ENABLE(p_instance->irq); 89 nrf_rtc_prescaler_set(p_instance->p_reg, p_config->prescaler); 90 m_cb[p_instance->instance_id].reliable = p_config->reliable; 91 m_cb[p_instance->instance_id].tick_latency = p_config->tick_latency; 92 m_cb[p_instance->instance_id].state = NRFX_DRV_STATE_INITIALIZED; 93 94 err_code = NRFX_SUCCESS; 95 NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code)); 96 return err_code; 97 } 98 99 void nrfx_rtc_uninit(nrfx_rtc_t const * const p_instance) 100 { 101 uint32_t mask = NRF_RTC_INT_TICK_MASK | 102 NRF_RTC_INT_OVERFLOW_MASK | 103 NRF_RTC_INT_COMPARE0_MASK | 104 NRF_RTC_INT_COMPARE1_MASK | 105 NRF_RTC_INT_COMPARE2_MASK | 106 NRF_RTC_INT_COMPARE3_MASK; 107 NRFX_ASSERT(m_cb[p_instance->instance_id].state != NRFX_DRV_STATE_UNINITIALIZED); 108 109 NRFX_IRQ_DISABLE(p_instance->irq); 110 111 nrf_rtc_task_trigger(p_instance->p_reg, NRF_RTC_TASK_STOP); 112 nrf_rtc_event_disable(p_instance->p_reg, mask); 113 nrf_rtc_int_disable(p_instance->p_reg, mask); 114 115 m_cb[p_instance->instance_id].state = NRFX_DRV_STATE_UNINITIALIZED; 116 NRFX_LOG_INFO("Uninitialized."); 117 } 118 119 void nrfx_rtc_enable(nrfx_rtc_t const * const p_instance) 120 { 121 NRFX_ASSERT(m_cb[p_instance->instance_id].state == NRFX_DRV_STATE_INITIALIZED); 122 123 nrf_rtc_task_trigger(p_instance->p_reg, NRF_RTC_TASK_START); 124 m_cb[p_instance->instance_id].state = NRFX_DRV_STATE_POWERED_ON; 125 NRFX_LOG_INFO("Enabled."); 126 } 127 128 void nrfx_rtc_disable(nrfx_rtc_t const * const p_instance) 129 { 130 NRFX_ASSERT(m_cb[p_instance->instance_id].state != NRFX_DRV_STATE_UNINITIALIZED); 131 132 nrf_rtc_task_trigger(p_instance->p_reg, NRF_RTC_TASK_STOP); 133 m_cb[p_instance->instance_id].state = NRFX_DRV_STATE_INITIALIZED; 134 NRFX_LOG_INFO("Disabled."); 135 } 136 137 nrfx_err_t nrfx_rtc_cc_disable(nrfx_rtc_t const * const p_instance, uint32_t channel) 138 { 139 NRFX_ASSERT(m_cb[p_instance->instance_id].state != NRFX_DRV_STATE_UNINITIALIZED); 140 NRFX_ASSERT(channel<p_instance->cc_channel_count); 141 142 nrfx_err_t err_code; 143 uint32_t int_mask = RTC_CHANNEL_INT_MASK(channel); 144 nrf_rtc_event_t event = RTC_CHANNEL_EVENT_ADDR(channel); 145 146 nrf_rtc_event_disable(p_instance->p_reg,int_mask); 147 if (nrf_rtc_int_is_enabled(p_instance->p_reg,int_mask)) 148 { 149 nrf_rtc_int_disable(p_instance->p_reg,int_mask); 150 if (nrf_rtc_event_pending(p_instance->p_reg,event)) 151 { 152 nrf_rtc_event_clear(p_instance->p_reg,event); 153 err_code = NRFX_ERROR_TIMEOUT; 154 NRFX_LOG_WARNING("Function: %s, error code: %s.", 155 __func__, 156 NRFX_LOG_ERROR_STRING_GET(err_code)); 157 return err_code; 158 } 159 } 160 NRFX_LOG_INFO("RTC id: %d, channel disabled: %lu.", p_instance->instance_id, channel); 161 err_code = NRFX_SUCCESS; 162 NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code)); 163 return err_code; 164 } 165 166 nrfx_err_t nrfx_rtc_cc_set(nrfx_rtc_t const * const p_instance, 167 uint32_t channel, 168 uint32_t val, 169 bool enable_irq) 170 { 171 NRFX_ASSERT(m_cb[p_instance->instance_id].state != NRFX_DRV_STATE_UNINITIALIZED); 172 NRFX_ASSERT(channel<p_instance->cc_channel_count); 173 174 nrfx_err_t err_code; 175 uint32_t int_mask = RTC_CHANNEL_INT_MASK(channel); 176 nrf_rtc_event_t event = RTC_CHANNEL_EVENT_ADDR(channel); 177 178 nrf_rtc_event_disable(p_instance->p_reg, int_mask); 179 nrf_rtc_int_disable(p_instance->p_reg, int_mask); 180 181 val = RTC_WRAP(val); 182 if (m_cb[p_instance->instance_id].reliable) 183 { 184 nrf_rtc_cc_set(p_instance->p_reg,channel,val); 185 uint32_t cnt = nrf_rtc_counter_get(p_instance->p_reg); 186 int32_t diff = cnt - val; 187 if (cnt < val) 188 { 189 diff += RTC_COUNTER_COUNTER_Msk; 190 } 191 if (diff < m_cb[p_instance->instance_id].tick_latency) 192 { 193 err_code = NRFX_ERROR_TIMEOUT; 194 NRFX_LOG_WARNING("Function: %s, error code: %s.", 195 __func__, 196 NRFX_LOG_ERROR_STRING_GET(err_code)); 197 return err_code; 198 } 199 } 200 else 201 { 202 nrf_rtc_cc_set(p_instance->p_reg,channel,val); 203 } 204 205 if (enable_irq) 206 { 207 nrf_rtc_event_clear(p_instance->p_reg,event); 208 nrf_rtc_int_enable(p_instance->p_reg, int_mask); 209 } 210 nrf_rtc_event_enable(p_instance->p_reg,int_mask); 211 212 NRFX_LOG_INFO("RTC id: %d, channel enabled: %lu, compare value: %lu.", 213 p_instance->instance_id, 214 channel, 215 val); 216 err_code = NRFX_SUCCESS; 217 NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code)); 218 return err_code; 219 } 220 221 void nrfx_rtc_tick_enable(nrfx_rtc_t const * const p_instance, bool enable_irq) 222 { 223 nrf_rtc_event_t event = NRF_RTC_EVENT_TICK; 224 uint32_t mask = NRF_RTC_INT_TICK_MASK; 225 226 nrf_rtc_event_clear(p_instance->p_reg, event); 227 nrf_rtc_event_enable(p_instance->p_reg, mask); 228 if (enable_irq) 229 { 230 nrf_rtc_int_enable(p_instance->p_reg, mask); 231 } 232 NRFX_LOG_INFO("Tick events enabled."); 233 } 234 235 void nrfx_rtc_tick_disable(nrfx_rtc_t const * const p_instance) 236 { 237 uint32_t mask = NRF_RTC_INT_TICK_MASK; 238 239 nrf_rtc_event_disable(p_instance->p_reg, mask); 240 nrf_rtc_int_disable(p_instance->p_reg, mask); 241 NRFX_LOG_INFO("Tick events disabled."); 242 } 243 244 void nrfx_rtc_overflow_enable(nrfx_rtc_t const * const p_instance, bool enable_irq) 245 { 246 nrf_rtc_event_t event = NRF_RTC_EVENT_OVERFLOW; 247 uint32_t mask = NRF_RTC_INT_OVERFLOW_MASK; 248 249 nrf_rtc_event_clear(p_instance->p_reg, event); 250 nrf_rtc_event_enable(p_instance->p_reg, mask); 251 if (enable_irq) 252 { 253 nrf_rtc_int_enable(p_instance->p_reg, mask); 254 } 255 } 256 257 void nrfx_rtc_overflow_disable(nrfx_rtc_t const * const p_instance) 258 { 259 uint32_t mask = NRF_RTC_INT_OVERFLOW_MASK; 260 nrf_rtc_event_disable(p_instance->p_reg, mask); 261 nrf_rtc_int_disable(p_instance->p_reg, mask); 262 } 263 264 uint32_t nrfx_rtc_max_ticks_get(nrfx_rtc_t const * const p_instance) 265 { 266 uint32_t ticks; 267 if (m_cb[p_instance->instance_id].reliable) 268 { 269 ticks = RTC_COUNTER_COUNTER_Msk - m_cb[p_instance->instance_id].tick_latency; 270 } 271 else 272 { 273 ticks = RTC_COUNTER_COUNTER_Msk; 274 } 275 return ticks; 276 } 277 278 static void irq_handler(NRF_RTC_Type * p_reg, 279 uint32_t instance_id, 280 uint32_t channel_count) 281 { 282 uint32_t i; 283 uint32_t int_mask = (uint32_t)NRF_RTC_INT_COMPARE0_MASK; 284 nrf_rtc_event_t event = NRF_RTC_EVENT_COMPARE_0; 285 286 for (i = 0; i < channel_count; i++) 287 { 288 if (nrf_rtc_int_is_enabled(p_reg,int_mask) && nrf_rtc_event_pending(p_reg,event)) 289 { 290 nrf_rtc_event_disable(p_reg,int_mask); 291 nrf_rtc_int_disable(p_reg,int_mask); 292 nrf_rtc_event_clear(p_reg,event); 293 NRFX_LOG_DEBUG("Event: %s, instance id: %lu.", EVT_TO_STR(event), instance_id); 294 m_handlers[instance_id]((nrfx_rtc_int_type_t)i); 295 } 296 int_mask <<= 1; 297 event = (nrf_rtc_event_t)((uint32_t)event + sizeof(uint32_t)); 298 } 299 event = NRF_RTC_EVENT_TICK; 300 if (nrf_rtc_int_is_enabled(p_reg,NRF_RTC_INT_TICK_MASK) && 301 nrf_rtc_event_pending(p_reg, event)) 302 { 303 nrf_rtc_event_clear(p_reg, event); 304 NRFX_LOG_DEBUG("Event: %s, instance id: %lu.", EVT_TO_STR(event), instance_id); 305 m_handlers[instance_id](NRFX_RTC_INT_TICK); 306 } 307 308 event = NRF_RTC_EVENT_OVERFLOW; 309 if (nrf_rtc_int_is_enabled(p_reg,NRF_RTC_INT_OVERFLOW_MASK) && 310 nrf_rtc_event_pending(p_reg, event)) 311 { 312 nrf_rtc_event_clear(p_reg,event); 313 NRFX_LOG_DEBUG("Event: %s, instance id: %lu.", EVT_TO_STR(event), instance_id); 314 m_handlers[instance_id](NRFX_RTC_INT_OVERFLOW); 315 } 316 } 317 318 #if NRFX_CHECK(NRFX_RTC0_ENABLED) 319 void nrfx_rtc_0_irq_handler(void) 320 { 321 irq_handler(NRF_RTC0, NRFX_RTC0_INST_IDX, NRF_RTC_CC_CHANNEL_COUNT(0)); 322 } 323 #endif 324 325 #if NRFX_CHECK(NRFX_RTC1_ENABLED) 326 void nrfx_rtc_1_irq_handler(void) 327 { 328 irq_handler(NRF_RTC1, NRFX_RTC1_INST_IDX, NRF_RTC_CC_CHANNEL_COUNT(1)); 329 } 330 #endif 331 332 #if NRFX_CHECK(NRFX_RTC2_ENABLED) 333 void nrfx_rtc_2_irq_handler(void) 334 { 335 irq_handler(NRF_RTC2, NRFX_RTC2_INST_IDX, NRF_RTC_CC_CHANNEL_COUNT(2)); 336 } 337 #endif 338 339 #endif // NRFX_CHECK(NRFX_RTC_ENABLED) 340