mbed library sources. Supersedes mbed-src.
Dependents: Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more
targets/TARGET_ONSEMI/TARGET_NCS36510/rtc.c@167:e84263d55307, 2017-06-21 (annotated)
- Committer:
- AnnaBridge
- Date:
- Wed Jun 21 17:46:44 2017 +0100
- Revision:
- 167:e84263d55307
- Parent:
- 150:02e0a0aed4ec
- Child:
- 174:b96e65c34a4d
This updates the lib to the mbed lib v 145
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
<> | 149:156823d33999 | 1 | /** |
<> | 149:156823d33999 | 2 | ******************************************************************************* |
<> | 149:156823d33999 | 3 | * @file rtc.c |
<> | 149:156823d33999 | 4 | * @brief Implementation of a Rtc driver |
<> | 149:156823d33999 | 5 | * @internal |
<> | 149:156823d33999 | 6 | * @author ON Semiconductor |
<> | 149:156823d33999 | 7 | * $Rev: 3525 $ |
<> | 149:156823d33999 | 8 | * $Date: 2015-07-20 15:24:25 +0530 (Mon, 20 Jul 2015) $ |
<> | 149:156823d33999 | 9 | ****************************************************************************** |
AnnaBridge | 167:e84263d55307 | 10 | * Copyright 2016 Semiconductor Components Industries LLC (d/b/a �ON Semiconductor�). |
<> | 149:156823d33999 | 11 | * All rights reserved. This software and/or documentation is licensed by ON Semiconductor |
<> | 149:156823d33999 | 12 | * under limited terms and conditions. The terms and conditions pertaining to the software |
<> | 149:156823d33999 | 13 | * and/or documentation are available at http://www.onsemi.com/site/pdf/ONSEMI_T&C.pdf |
AnnaBridge | 167:e84263d55307 | 14 | * (�ON Semiconductor Standard Terms and Conditions of Sale, Section 8 Software�) and |
<> | 149:156823d33999 | 15 | * if applicable the software license agreement. Do not use this software and/or |
<> | 149:156823d33999 | 16 | * documentation unless you have carefully read and you agree to the limited terms and |
<> | 149:156823d33999 | 17 | * conditions. By using this software and/or documentation, you agree to the limited |
<> | 149:156823d33999 | 18 | * terms and conditions. |
<> | 149:156823d33999 | 19 | * |
<> | 149:156823d33999 | 20 | * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED |
<> | 149:156823d33999 | 21 | * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF |
<> | 149:156823d33999 | 22 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. |
<> | 149:156823d33999 | 23 | * ON SEMICONDUCTOR SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, |
<> | 149:156823d33999 | 24 | * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. |
<> | 149:156823d33999 | 25 | * @endinternal |
<> | 149:156823d33999 | 26 | * |
<> | 149:156823d33999 | 27 | * @ingroup rtc |
<> | 149:156823d33999 | 28 | * |
<> | 149:156823d33999 | 29 | * @details |
<> | 149:156823d33999 | 30 | * A real-time clock (RTC) is a computer clock ,that keeps track of the current time. The heart of the RTC is a series of |
<> | 149:156823d33999 | 31 | * freely running counters one for each time unit, The series of counters is linked as follows: a roll over event of |
<> | 149:156823d33999 | 32 | * the seconds counter produces a minutes enable pulse; a roll over event of the minutes counter produces an hours |
<> | 149:156823d33999 | 33 | * enable pulse, etc.Note that all Counter registers are in an undefined state on power-up. |
<> | 149:156823d33999 | 34 | * Use the Reset bit in the Control Register to reset the counters to their default values. |
<> | 149:156823d33999 | 35 | * DIVISOR is the register containing the value to divide the clock frequency to produce 1Hz strobe ; 1Hz strobe is used |
<> | 149:156823d33999 | 36 | * internally to time the incrementing of the Seconds Counter. |
<> | 149:156823d33999 | 37 | * There is a set of register to set the values in the counter for each time unit.from where time is start to increment. |
<> | 149:156823d33999 | 38 | * There is another set of register to set the ALARM ...Each of the Alarm Registers can be programmed with a value that |
<> | 149:156823d33999 | 39 | * is used to compare to a Counter Register in order to produce an alarm (an interrupt) when the values match. |
<> | 149:156823d33999 | 40 | * There is a programmable bit in each Alarm Register that determines if the alarm occurs upon a value match, or |
<> | 149:156823d33999 | 41 | * if the alarm occurs upon a Counter increment condition. |
<> | 149:156823d33999 | 42 | * |
<> | 149:156823d33999 | 43 | */ |
<> | 149:156823d33999 | 44 | #include "rtc.h" |
<> | 149:156823d33999 | 45 | #include "mbed_assert.h" |
<> | 150:02e0a0aed4ec | 46 | #include "lp_ticker_api.h" |
<> | 149:156823d33999 | 47 | |
AnnaBridge | 167:e84263d55307 | 48 | static volatile uint64_t last_time_read; |
AnnaBridge | 167:e84263d55307 | 49 | |
AnnaBridge | 167:e84263d55307 | 50 | /** |
AnnaBridge | 167:e84263d55307 | 51 | * Convert sub seconds ticks to micro seconds. |
AnnaBridge | 167:e84263d55307 | 52 | * The clock running at 32kHz, a tick is 1/32768 of a second. |
AnnaBridge | 167:e84263d55307 | 53 | */ |
AnnaBridge | 167:e84263d55307 | 54 | static inline uint32_t ticks_to_us(uint16_t ticks) { |
AnnaBridge | 167:e84263d55307 | 55 | return (((uint64_t)ticks * RTC_SEC_TO_US) / RTC_CLOCK_HZ); |
AnnaBridge | 167:e84263d55307 | 56 | } |
AnnaBridge | 167:e84263d55307 | 57 | |
AnnaBridge | 167:e84263d55307 | 58 | /** |
AnnaBridge | 167:e84263d55307 | 59 | * Convert us into sub seconds ticks. |
AnnaBridge | 167:e84263d55307 | 60 | * @note result might be troncated to be in the range [0 - RTC_SUB_SEC_MASK]. |
AnnaBridge | 167:e84263d55307 | 61 | */ |
AnnaBridge | 167:e84263d55307 | 62 | static inline uint16_t us_to_ticks(uint32_t us) { |
AnnaBridge | 167:e84263d55307 | 63 | return (((uint64_t) us * RTC_CLOCK_HZ) / RTC_SEC_TO_US) & RTC_SUB_SEC_MASK; |
AnnaBridge | 167:e84263d55307 | 64 | } |
AnnaBridge | 167:e84263d55307 | 65 | |
AnnaBridge | 167:e84263d55307 | 66 | #define RTC_TICK_THRESHOLD 5 |
<> | 149:156823d33999 | 67 | |
<> | 149:156823d33999 | 68 | /* See rtc.h for details */ |
<> | 149:156823d33999 | 69 | void fRtcInit(void) |
<> | 149:156823d33999 | 70 | { |
<> | 149:156823d33999 | 71 | CLOCK_ENABLE(CLOCK_RTC); /* enable rtc peripheral */ |
<> | 149:156823d33999 | 72 | CLOCKREG->CCR.BITS.RTCEN = True; /* Enable RTC clock 32K */ |
<> | 149:156823d33999 | 73 | |
<> | 149:156823d33999 | 74 | /* Reset RTC control register */ |
AnnaBridge | 167:e84263d55307 | 75 | RTCREG->CONTROL.WORD = 0; |
<> | 149:156823d33999 | 76 | |
<> | 149:156823d33999 | 77 | /* Initialize all counters */ |
AnnaBridge | 167:e84263d55307 | 78 | RTCREG->SECOND_COUNTER = 0; |
AnnaBridge | 167:e84263d55307 | 79 | RTCREG->SUB_SECOND_COUNTER = 0; |
AnnaBridge | 167:e84263d55307 | 80 | RTCREG->SECOND_ALARM = 0; |
AnnaBridge | 167:e84263d55307 | 81 | RTCREG->SUB_SECOND_ALARM = 0; |
AnnaBridge | 167:e84263d55307 | 82 | last_time_read = 0; |
<> | 149:156823d33999 | 83 | |
<> | 149:156823d33999 | 84 | /* Reset RTC Status register */ |
AnnaBridge | 167:e84263d55307 | 85 | RTCREG->STATUS.WORD = 0; |
<> | 149:156823d33999 | 86 | |
<> | 149:156823d33999 | 87 | /* Clear interrupt status */ |
AnnaBridge | 167:e84263d55307 | 88 | RTCREG->INT_CLEAR.WORD = ( |
AnnaBridge | 167:e84263d55307 | 89 | (1 << RTC_INT_CLR_SUB_SEC_BIT_POS) | |
AnnaBridge | 167:e84263d55307 | 90 | (1 << RTC_INT_CLR_SEC_BIT_POS) |
AnnaBridge | 167:e84263d55307 | 91 | ); |
<> | 149:156823d33999 | 92 | |
AnnaBridge | 167:e84263d55307 | 93 | /* Wait previous write to complete */ |
AnnaBridge | 167:e84263d55307 | 94 | while(RTCREG->STATUS.BITS.BSY_CTRL_REG_WRT == True); |
<> | 149:156823d33999 | 95 | /* Start sec & sub_sec counter */ |
AnnaBridge | 167:e84263d55307 | 96 | RTCREG->CONTROL.WORD |= ( |
AnnaBridge | 167:e84263d55307 | 97 | (True << RTC_CONTROL_SUBSEC_CNT_START_BIT_POS) | |
AnnaBridge | 167:e84263d55307 | 98 | (True << RTC_CONTROL_SEC_CNT_START_BIT_POS) |
AnnaBridge | 167:e84263d55307 | 99 | ); |
<> | 149:156823d33999 | 100 | |
<> | 149:156823d33999 | 101 | /* enable interruption associated with the rtc at NVIC level */ |
AnnaBridge | 167:e84263d55307 | 102 | NVIC_SetVector(Rtc_IRQn,(uint32_t) fRtcHandler); /* TODO define lp_ticker_isr */ |
<> | 149:156823d33999 | 103 | NVIC_ClearPendingIRQ(Rtc_IRQn); |
<> | 149:156823d33999 | 104 | NVIC_EnableIRQ(Rtc_IRQn); |
<> | 149:156823d33999 | 105 | |
AnnaBridge | 167:e84263d55307 | 106 | /* Wait for RTC to finish writing register */ |
AnnaBridge | 167:e84263d55307 | 107 | while(RTCREG->STATUS.BITS.BSY_CTRL_REG_WRT == True); |
<> | 149:156823d33999 | 108 | } |
<> | 149:156823d33999 | 109 | |
<> | 149:156823d33999 | 110 | /* See rtc.h for details */ |
<> | 149:156823d33999 | 111 | void fRtcFree(void) |
<> | 149:156823d33999 | 112 | { |
AnnaBridge | 167:e84263d55307 | 113 | /* Disable interrupts and counter */ |
AnnaBridge | 167:e84263d55307 | 114 | RTCREG->CONTROL.WORD = 0; |
<> | 149:156823d33999 | 115 | |
<> | 149:156823d33999 | 116 | /* disable interruption associated with the rtc */ |
<> | 149:156823d33999 | 117 | NVIC_DisableIRQ(Rtc_IRQn); |
<> | 149:156823d33999 | 118 | |
AnnaBridge | 167:e84263d55307 | 119 | /* Wait for RTC to finish writing register */ |
AnnaBridge | 167:e84263d55307 | 120 | while(RTCREG->STATUS.BITS.BSY_CTRL_REG_WRT == True); |
<> | 149:156823d33999 | 121 | } |
<> | 149:156823d33999 | 122 | |
<> | 149:156823d33999 | 123 | /* See rtc.h for details */ |
<> | 149:156823d33999 | 124 | void fRtcSetInterrupt(uint32_t timestamp) |
<> | 149:156823d33999 | 125 | { |
AnnaBridge | 167:e84263d55307 | 126 | uint64_t current_time = fRtcRead(); |
<> | 149:156823d33999 | 127 | |
AnnaBridge | 167:e84263d55307 | 128 | /* compute delta between current time and timestamp. |
AnnaBridge | 167:e84263d55307 | 129 | * Note: the current time used to compute the delta is relative (truncated |
AnnaBridge | 167:e84263d55307 | 130 | * to 32 bits). |
AnnaBridge | 167:e84263d55307 | 131 | */ |
AnnaBridge | 167:e84263d55307 | 132 | int32_t delta = timestamp - (uint32_t) current_time; |
AnnaBridge | 167:e84263d55307 | 133 | if (delta <= 0) { |
AnnaBridge | 167:e84263d55307 | 134 | // event considered in the past, set the interrupt as pending. |
AnnaBridge | 167:e84263d55307 | 135 | NVIC_SetPendingIRQ(Rtc_IRQn); |
AnnaBridge | 167:e84263d55307 | 136 | return; |
AnnaBridge | 167:e84263d55307 | 137 | } |
<> | 149:156823d33999 | 138 | |
AnnaBridge | 167:e84263d55307 | 139 | uint64_t full_timestamp = (current_time & ~UINT32_MAX) | timestamp; |
AnnaBridge | 167:e84263d55307 | 140 | if ( (uint32_t)current_time > timestamp) { |
AnnaBridge | 167:e84263d55307 | 141 | full_timestamp += ((uint64_t) UINT32_MAX) + 1; |
AnnaBridge | 167:e84263d55307 | 142 | } |
<> | 149:156823d33999 | 143 | |
AnnaBridge | 167:e84263d55307 | 144 | uint32_t target_seconds = full_timestamp / RTC_SEC_TO_US; |
AnnaBridge | 167:e84263d55307 | 145 | uint16_t target_ticks = us_to_ticks(full_timestamp); |
<> | 149:156823d33999 | 146 | |
AnnaBridge | 167:e84263d55307 | 147 | /* |
AnnaBridge | 167:e84263d55307 | 148 | * If the interrupt is in more than one second from now then use the |
AnnaBridge | 167:e84263d55307 | 149 | * second alarm, otherwise use the subsecond alarm. |
AnnaBridge | 167:e84263d55307 | 150 | * In case of the second alarm is used, there is no need to preserve the |
AnnaBridge | 167:e84263d55307 | 151 | * remaining subsecond because the irq handler should manage spurious |
AnnaBridge | 167:e84263d55307 | 152 | * interrupts (like when the timestamp is in the past). In such case, irq |
AnnaBridge | 167:e84263d55307 | 153 | * handler will schedule a new interrupt with the remaining us. |
AnnaBridge | 167:e84263d55307 | 154 | */ |
AnnaBridge | 167:e84263d55307 | 155 | NVIC_DisableIRQ(Rtc_IRQn); |
AnnaBridge | 167:e84263d55307 | 156 | if (target_seconds != RTCREG->SECOND_COUNTER) { |
AnnaBridge | 167:e84263d55307 | 157 | RTCREG->SECOND_ALARM = target_seconds; |
<> | 149:156823d33999 | 158 | |
AnnaBridge | 167:e84263d55307 | 159 | uint32_t rtc_control = RTCREG->CONTROL.WORD; |
AnnaBridge | 167:e84263d55307 | 160 | rtc_control |= (1 << RTC_CONTROL_SEC_CNT_INT_BIT_POS); // enable seconds interrupt |
AnnaBridge | 167:e84263d55307 | 161 | rtc_control &= ~(1 << RTC_CONTROL_SUBSEC_CNT_INT_BIT_POS); // disable sub sec interrupt |
AnnaBridge | 167:e84263d55307 | 162 | RTCREG->CONTROL.WORD = rtc_control; |
AnnaBridge | 167:e84263d55307 | 163 | } else { |
AnnaBridge | 167:e84263d55307 | 164 | uint16_t current_ticks = RTCREG->SUB_SECOND_COUNTER; |
AnnaBridge | 167:e84263d55307 | 165 | if (current_ticks == target_ticks || |
AnnaBridge | 167:e84263d55307 | 166 | ((target_ticks > current_ticks) && ((target_ticks - current_ticks) < RTC_TICK_THRESHOLD)) || |
AnnaBridge | 167:e84263d55307 | 167 | ((target_ticks < current_ticks) && ((RTC_SUB_SEC_MASK - (current_ticks - target_ticks)) < RTC_TICK_THRESHOLD))) { |
AnnaBridge | 167:e84263d55307 | 168 | // target ticks too close; schedule the interrupt immediately |
AnnaBridge | 167:e84263d55307 | 169 | NVIC_SetPendingIRQ(Rtc_IRQn); |
AnnaBridge | 167:e84263d55307 | 170 | } else { |
AnnaBridge | 167:e84263d55307 | 171 | RTCREG->SUB_SECOND_ALARM = target_ticks; |
AnnaBridge | 167:e84263d55307 | 172 | |
AnnaBridge | 167:e84263d55307 | 173 | uint32_t rtc_control = RTCREG->CONTROL.WORD; |
AnnaBridge | 167:e84263d55307 | 174 | rtc_control &= ~(1 << RTC_CONTROL_SEC_CNT_INT_BIT_POS); // disable seconds interrupt |
AnnaBridge | 167:e84263d55307 | 175 | rtc_control |= (1 << RTC_CONTROL_SUBSEC_CNT_INT_BIT_POS); // enable sub sec interrupt |
AnnaBridge | 167:e84263d55307 | 176 | RTCREG->CONTROL.WORD = rtc_control; |
AnnaBridge | 167:e84263d55307 | 177 | } |
AnnaBridge | 167:e84263d55307 | 178 | } |
AnnaBridge | 167:e84263d55307 | 179 | NVIC_EnableIRQ(Rtc_IRQn); |
AnnaBridge | 167:e84263d55307 | 180 | |
AnnaBridge | 167:e84263d55307 | 181 | /* Wait for RTC to finish writing register - RTC operates on 32K clock as compared to 32M core*/ |
AnnaBridge | 167:e84263d55307 | 182 | while(RTCREG->STATUS.WORD & |
AnnaBridge | 167:e84263d55307 | 183 | ( |
AnnaBridge | 167:e84263d55307 | 184 | (True << RTC_STATUS_SUB_SEC_ALARM_WRT_BIT_POS) | |
AnnaBridge | 167:e84263d55307 | 185 | (True << RTC_STATUS_SEC_ALARM_WRT_BIT_POS) | |
AnnaBridge | 167:e84263d55307 | 186 | (True << RTC_STATUS_CONTROL_WRT_BIT_POS) |
AnnaBridge | 167:e84263d55307 | 187 | ) |
AnnaBridge | 167:e84263d55307 | 188 | ); |
<> | 149:156823d33999 | 189 | } |
<> | 149:156823d33999 | 190 | |
<> | 149:156823d33999 | 191 | /* See rtc.h for details */ |
<> | 149:156823d33999 | 192 | void fRtcDisableInterrupt(void) |
<> | 149:156823d33999 | 193 | { |
<> | 150:02e0a0aed4ec | 194 | NVIC_DisableIRQ(Rtc_IRQn); |
<> | 149:156823d33999 | 195 | } |
<> | 149:156823d33999 | 196 | |
<> | 149:156823d33999 | 197 | /* See rtc.h for details */ |
<> | 149:156823d33999 | 198 | void fRtcEnableInterrupt(void) |
<> | 149:156823d33999 | 199 | { |
<> | 150:02e0a0aed4ec | 200 | NVIC_EnableIRQ(Rtc_IRQn); |
<> | 149:156823d33999 | 201 | } |
<> | 149:156823d33999 | 202 | |
<> | 149:156823d33999 | 203 | /* See rtc.h for details */ |
<> | 149:156823d33999 | 204 | void fRtcClearInterrupt(void) |
<> | 149:156823d33999 | 205 | { |
<> | 149:156823d33999 | 206 | /* Disable subsec/sec interrupt */ |
<> | 149:156823d33999 | 207 | /* Clear sec & sub_sec interrupts */ |
<> | 149:156823d33999 | 208 | RTCREG->INT_CLEAR.WORD = ((True << RTC_INT_CLR_SUB_SEC_BIT_POS) | |
<> | 149:156823d33999 | 209 | (True << RTC_INT_CLR_SEC_BIT_POS)); |
<> | 150:02e0a0aed4ec | 210 | |
<> | 150:02e0a0aed4ec | 211 | while((RTCREG->STATUS.WORD & ((True << RTC_STATUS_SUB_SEC_INT_CLR_WRT_BIT_POS) | |
AnnaBridge | 167:e84263d55307 | 212 | (True << RTC_STATUS_SEC_INT_CLR_WRT_BIT_POS)))); /* Wait for RTC to finish writing register - RTC operates on 32K clock as compared to 32M core*/ |
<> | 149:156823d33999 | 213 | } |
<> | 149:156823d33999 | 214 | |
<> | 149:156823d33999 | 215 | /* See rtc.h for details */ |
<> | 149:156823d33999 | 216 | uint64_t fRtcRead(void) |
<> | 149:156823d33999 | 217 | { |
<> | 149:156823d33999 | 218 | /* Hardware Bug fix: The rollover of the sub-second counter initiates the increment of the second counter. |
<> | 149:156823d33999 | 219 | * That means there is one cycle where the sub-second has rolled back to zero and the second counter has not incremented |
<> | 149:156823d33999 | 220 | * and a read during that cycle will be incorrect. That will occur for one RTC cycle and that is about 31us of exposure. |
<> | 149:156823d33999 | 221 | * If you read a zero in the sub-second counter then increment the second counter by 1. |
<> | 149:156823d33999 | 222 | * Alternatively, subtract 1 from the Sub-seconds counter to align the Second and Sub-Second rollover. |
<> | 149:156823d33999 | 223 | */ |
AnnaBridge | 167:e84263d55307 | 224 | uint32_t seconds = RTCREG->SECOND_COUNTER; |
AnnaBridge | 167:e84263d55307 | 225 | uint16_t ticks = (RTCREG->SUB_SECOND_COUNTER - 1) & SUB_SEC_MASK; |
<> | 149:156823d33999 | 226 | |
AnnaBridge | 167:e84263d55307 | 227 | /* |
AnnaBridge | 167:e84263d55307 | 228 | * If seconds has changed while reading ticks, read them both again. |
AnnaBridge | 167:e84263d55307 | 229 | */ |
AnnaBridge | 167:e84263d55307 | 230 | while (seconds != RTCREG->SECOND_COUNTER) { |
AnnaBridge | 167:e84263d55307 | 231 | seconds = RTCREG->SECOND_COUNTER; |
AnnaBridge | 167:e84263d55307 | 232 | ticks = (RTCREG->SUB_SECOND_COUNTER - 1) & SUB_SEC_MASK; |
AnnaBridge | 167:e84263d55307 | 233 | } |
<> | 149:156823d33999 | 234 | |
AnnaBridge | 167:e84263d55307 | 235 | uint64_t current_time = ((uint64_t) seconds * RTC_SEC_TO_US) + ticks_to_us(ticks); |
<> | 149:156823d33999 | 236 | |
<> | 149:156823d33999 | 237 | /*check that the time did not go backwards */ |
AnnaBridge | 167:e84263d55307 | 238 | MBED_ASSERT(current_time >= last_time_read); |
AnnaBridge | 167:e84263d55307 | 239 | last_time_read = current_time; |
<> | 149:156823d33999 | 240 | |
AnnaBridge | 167:e84263d55307 | 241 | return current_time; |
<> | 149:156823d33999 | 242 | } |
<> | 149:156823d33999 | 243 | |
<> | 149:156823d33999 | 244 | /* See rtc.h for details */ |
<> | 149:156823d33999 | 245 | void fRtcWrite(uint64_t RtcTimeus) |
<> | 149:156823d33999 | 246 | { |
<> | 150:02e0a0aed4ec | 247 | uint32_t Second = False; |
<> | 150:02e0a0aed4ec | 248 | uint16_t SubSecond = False; |
<> | 149:156823d33999 | 249 | /* Stop RTC */ |
<> | 149:156823d33999 | 250 | RTCREG->CONTROL.WORD &= ~((True << RTC_CONTROL_SUBSEC_CNT_START_BIT_POS) | |
<> | 149:156823d33999 | 251 | (True << RTC_CONTROL_SEC_CNT_START_BIT_POS)); |
<> | 149:156823d33999 | 252 | |
<> | 149:156823d33999 | 253 | if(RtcTimeus > RTC_SEC_TO_US) { |
<> | 149:156823d33999 | 254 | /* TimeStamp is big enough to set second counter */ |
<> | 149:156823d33999 | 255 | Second = ((RtcTimeus / RTC_SEC_TO_US) & RTC_SEC_MASK); |
<> | 149:156823d33999 | 256 | } |
<> | 149:156823d33999 | 257 | RTCREG->SECOND_COUNTER = Second; |
<> | 149:156823d33999 | 258 | RtcTimeus = RtcTimeus - (Second * RTC_SEC_TO_US); |
<> | 149:156823d33999 | 259 | if(RtcTimeus > False) { |
<> | 149:156823d33999 | 260 | /* Convert TimeStamp to sub_seconds */ |
<> | 149:156823d33999 | 261 | SubSecond = (uint16_t)((float)(RtcTimeus * RTC_CLOCK_HZ / RTC_SEC_TO_US)) & RTC_SUB_SEC_MASK; |
<> | 149:156823d33999 | 262 | } |
<> | 149:156823d33999 | 263 | /* Set SUB_SEC_ALARM */ |
<> | 149:156823d33999 | 264 | RTCREG->SUB_SECOND_COUNTER = SubSecond; |
<> | 149:156823d33999 | 265 | |
<> | 149:156823d33999 | 266 | while(RTCREG->STATUS.BITS.BSY_CTRL_REG_WRT == True); /* Wait for RTC to finish writing register - RTC operates on 32K clock as compared to 32M core*/ |
<> | 149:156823d33999 | 267 | /* Start RTC */ |
<> | 149:156823d33999 | 268 | RTCREG->CONTROL.WORD |= ((True << RTC_CONTROL_SUBSEC_CNT_START_BIT_POS) | |
<> | 149:156823d33999 | 269 | (True << RTC_CONTROL_SEC_CNT_START_BIT_POS)); |
<> | 149:156823d33999 | 270 | |
<> | 149:156823d33999 | 271 | while(RTCREG->STATUS.BITS.BSY_ANY_WRT == True); /* Wait for RTC to finish writing register - RTC operates on 32K clock as compared to 32M core*/ |
<> | 149:156823d33999 | 272 | } |
<> | 149:156823d33999 | 273 | |
<> | 149:156823d33999 | 274 | /* See rtc.h for details */ |
<> | 149:156823d33999 | 275 | void fRtcHandler(void) |
<> | 149:156823d33999 | 276 | { |
<> | 149:156823d33999 | 277 | /* Disable RTC interrupt */ |
<> | 149:156823d33999 | 278 | NVIC_DisableIRQ(Rtc_IRQn); |
<> | 149:156823d33999 | 279 | |
<> | 149:156823d33999 | 280 | /* Clear sec & sub_sec interrupts */ |
AnnaBridge | 167:e84263d55307 | 281 | RTCREG->INT_CLEAR.WORD = ( |
AnnaBridge | 167:e84263d55307 | 282 | (True << RTC_INT_CLR_SUB_SEC_BIT_POS) | |
AnnaBridge | 167:e84263d55307 | 283 | (True << RTC_INT_CLR_SEC_BIT_POS) |
AnnaBridge | 167:e84263d55307 | 284 | ); |
<> | 149:156823d33999 | 285 | |
AnnaBridge | 167:e84263d55307 | 286 | /* Disable sub seconds and seconds interrupts */ |
AnnaBridge | 167:e84263d55307 | 287 | RTCREG->CONTROL.WORD &= ~( |
AnnaBridge | 167:e84263d55307 | 288 | (True << RTC_CONTROL_SUBSEC_CNT_INT_BIT_POS) | |
AnnaBridge | 167:e84263d55307 | 289 | (True << RTC_CONTROL_SEC_CNT_INT_BIT_POS) |
AnnaBridge | 167:e84263d55307 | 290 | ); |
<> | 149:156823d33999 | 291 | |
<> | 149:156823d33999 | 292 | NVIC_EnableIRQ(Rtc_IRQn); |
<> | 149:156823d33999 | 293 | |
AnnaBridge | 167:e84263d55307 | 294 | /* Wait for RTC to finish writing registers */ |
AnnaBridge | 167:e84263d55307 | 295 | while(RTCREG->STATUS.WORD & |
AnnaBridge | 167:e84263d55307 | 296 | ( |
AnnaBridge | 167:e84263d55307 | 297 | (True << RTC_STATUS_CONTROL_WRT_BIT_POS) | |
AnnaBridge | 167:e84263d55307 | 298 | (True << RTC_STATUS_SUB_SEC_INT_CLR_WRT_BIT_POS) | |
AnnaBridge | 167:e84263d55307 | 299 | (True << RTC_STATUS_SEC_INT_CLR_WRT_BIT_POS) |
AnnaBridge | 167:e84263d55307 | 300 | ) |
AnnaBridge | 167:e84263d55307 | 301 | ); |
<> | 149:156823d33999 | 302 | |
<> | 149:156823d33999 | 303 | lp_ticker_irq_handler(); |
<> | 149:156823d33999 | 304 | } |
<> | 149:156823d33999 | 305 | |
<> | 149:156823d33999 | 306 | boolean fIsRtcEnabled(void) |
<> | 149:156823d33999 | 307 | { |
<> | 149:156823d33999 | 308 | if(RTCREG->CONTROL.BITS.SUB_SEC_COUNTER_EN | RTCREG->CONTROL.BITS.SEC_COUNTER_EN) { |
<> | 149:156823d33999 | 309 | return True; |
<> | 149:156823d33999 | 310 | } else { |
<> | 149:156823d33999 | 311 | return False; |
<> | 149:156823d33999 | 312 | } |
<> | 149:156823d33999 | 313 | } |