lol
Fork of Application by
mbed-dev/targets/TARGET_ONSEMI/TARGET_NCS36510/rtc.c@10:41552d038a69, 2017-01-10 (annotated)
- Committer:
- Zaitsev
- Date:
- Tue Jan 10 20:42:26 2017 +0000
- Revision:
- 10:41552d038a69
USB Serial bi-directional bridge
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Zaitsev | 10:41552d038a69 | 1 | /** |
Zaitsev | 10:41552d038a69 | 2 | ******************************************************************************* |
Zaitsev | 10:41552d038a69 | 3 | * @file rtc.c |
Zaitsev | 10:41552d038a69 | 4 | * @brief Implementation of a Rtc driver |
Zaitsev | 10:41552d038a69 | 5 | * @internal |
Zaitsev | 10:41552d038a69 | 6 | * @author ON Semiconductor |
Zaitsev | 10:41552d038a69 | 7 | * $Rev: 3525 $ |
Zaitsev | 10:41552d038a69 | 8 | * $Date: 2015-07-20 15:24:25 +0530 (Mon, 20 Jul 2015) $ |
Zaitsev | 10:41552d038a69 | 9 | ****************************************************************************** |
Zaitsev | 10:41552d038a69 | 10 | * Copyright 2016 Semiconductor Components Industries LLC (d/b/a ON Semiconductor). |
Zaitsev | 10:41552d038a69 | 11 | * All rights reserved. This software and/or documentation is licensed by ON Semiconductor |
Zaitsev | 10:41552d038a69 | 12 | * under limited terms and conditions. The terms and conditions pertaining to the software |
Zaitsev | 10:41552d038a69 | 13 | * and/or documentation are available at http://www.onsemi.com/site/pdf/ONSEMI_T&C.pdf |
Zaitsev | 10:41552d038a69 | 14 | * (ON Semiconductor Standard Terms and Conditions of Sale, Section 8 Software) and |
Zaitsev | 10:41552d038a69 | 15 | * if applicable the software license agreement. Do not use this software and/or |
Zaitsev | 10:41552d038a69 | 16 | * documentation unless you have carefully read and you agree to the limited terms and |
Zaitsev | 10:41552d038a69 | 17 | * conditions. By using this software and/or documentation, you agree to the limited |
Zaitsev | 10:41552d038a69 | 18 | * terms and conditions. |
Zaitsev | 10:41552d038a69 | 19 | * |
Zaitsev | 10:41552d038a69 | 20 | * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED |
Zaitsev | 10:41552d038a69 | 21 | * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF |
Zaitsev | 10:41552d038a69 | 22 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. |
Zaitsev | 10:41552d038a69 | 23 | * ON SEMICONDUCTOR SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, |
Zaitsev | 10:41552d038a69 | 24 | * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. |
Zaitsev | 10:41552d038a69 | 25 | * @endinternal |
Zaitsev | 10:41552d038a69 | 26 | * |
Zaitsev | 10:41552d038a69 | 27 | * @ingroup rtc |
Zaitsev | 10:41552d038a69 | 28 | * |
Zaitsev | 10:41552d038a69 | 29 | * @details |
Zaitsev | 10:41552d038a69 | 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 |
Zaitsev | 10:41552d038a69 | 31 | * freely running counters one for each time unit, The series of counters is linked as follows: a roll over event of |
Zaitsev | 10:41552d038a69 | 32 | * the seconds counter produces a minutes enable pulse; a roll over event of the minutes counter produces an hours |
Zaitsev | 10:41552d038a69 | 33 | * enable pulse, etc.Note that all Counter registers are in an undefined state on power-up. |
Zaitsev | 10:41552d038a69 | 34 | * Use the Reset bit in the Control Register to reset the counters to their default values. |
Zaitsev | 10:41552d038a69 | 35 | * DIVISOR is the register containing the value to divide the clock frequency to produce 1Hz strobe ; 1Hz strobe is used |
Zaitsev | 10:41552d038a69 | 36 | * internally to time the incrementing of the Seconds Counter. |
Zaitsev | 10:41552d038a69 | 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. |
Zaitsev | 10:41552d038a69 | 38 | * There is another set of register to set the ALARM ...Each of the Alarm Registers can be programmed with a value that |
Zaitsev | 10:41552d038a69 | 39 | * is used to compare to a Counter Register in order to produce an alarm (an interrupt) when the values match. |
Zaitsev | 10:41552d038a69 | 40 | * There is a programmable bit in each Alarm Register that determines if the alarm occurs upon a value match, or |
Zaitsev | 10:41552d038a69 | 41 | * if the alarm occurs upon a Counter increment condition. |
Zaitsev | 10:41552d038a69 | 42 | * |
Zaitsev | 10:41552d038a69 | 43 | */ |
Zaitsev | 10:41552d038a69 | 44 | #include "rtc.h" |
Zaitsev | 10:41552d038a69 | 45 | #include "mbed_assert.h" |
Zaitsev | 10:41552d038a69 | 46 | #include "lp_ticker_api.h" |
Zaitsev | 10:41552d038a69 | 47 | |
Zaitsev | 10:41552d038a69 | 48 | static uint16_t SubSecond; |
Zaitsev | 10:41552d038a69 | 49 | static uint64_t LastRtcTimeus; |
Zaitsev | 10:41552d038a69 | 50 | |
Zaitsev | 10:41552d038a69 | 51 | /* See rtc.h for details */ |
Zaitsev | 10:41552d038a69 | 52 | void fRtcInit(void) |
Zaitsev | 10:41552d038a69 | 53 | { |
Zaitsev | 10:41552d038a69 | 54 | CLOCK_ENABLE(CLOCK_RTC); /* enable rtc peripheral */ |
Zaitsev | 10:41552d038a69 | 55 | CLOCKREG->CCR.BITS.RTCEN = True; /* Enable RTC clock 32K */ |
Zaitsev | 10:41552d038a69 | 56 | |
Zaitsev | 10:41552d038a69 | 57 | /* Reset RTC control register */ |
Zaitsev | 10:41552d038a69 | 58 | RTCREG->CONTROL.WORD = False; |
Zaitsev | 10:41552d038a69 | 59 | |
Zaitsev | 10:41552d038a69 | 60 | /* Initialize all counters */ |
Zaitsev | 10:41552d038a69 | 61 | RTCREG->SECOND_COUNTER = False; |
Zaitsev | 10:41552d038a69 | 62 | RTCREG->SUB_SECOND_COUNTER = False; |
Zaitsev | 10:41552d038a69 | 63 | RTCREG->SECOND_ALARM = False; |
Zaitsev | 10:41552d038a69 | 64 | RTCREG->SUB_SECOND_ALARM = False; |
Zaitsev | 10:41552d038a69 | 65 | LastRtcTimeus = 0; |
Zaitsev | 10:41552d038a69 | 66 | |
Zaitsev | 10:41552d038a69 | 67 | /* Reset RTC Status register */ |
Zaitsev | 10:41552d038a69 | 68 | RTCREG->STATUS.WORD = False; |
Zaitsev | 10:41552d038a69 | 69 | |
Zaitsev | 10:41552d038a69 | 70 | /* Clear interrupt status */ |
Zaitsev | 10:41552d038a69 | 71 | RTCREG->INT_CLEAR.WORD = False; |
Zaitsev | 10:41552d038a69 | 72 | |
Zaitsev | 10:41552d038a69 | 73 | /* Start sec & sub_sec counter */ |
Zaitsev | 10:41552d038a69 | 74 | while(RTCREG->STATUS.BITS.BSY_CTRL_REG_WRT == True);/* Wait previous write to complete */ |
Zaitsev | 10:41552d038a69 | 75 | RTCREG->CONTROL.WORD |= ((True << RTC_CONTROL_SUBSEC_CNT_START_BIT_POS) | |
Zaitsev | 10:41552d038a69 | 76 | (True << RTC_CONTROL_SEC_CNT_START_BIT_POS)); |
Zaitsev | 10:41552d038a69 | 77 | |
Zaitsev | 10:41552d038a69 | 78 | /* enable interruption associated with the rtc at NVIC level */ |
Zaitsev | 10:41552d038a69 | 79 | NVIC_SetVector(Rtc_IRQn,(uint32_t)fRtcHandler); /* TODO define lp_ticker_isr */ |
Zaitsev | 10:41552d038a69 | 80 | NVIC_ClearPendingIRQ(Rtc_IRQn); |
Zaitsev | 10:41552d038a69 | 81 | NVIC_EnableIRQ(Rtc_IRQn); |
Zaitsev | 10:41552d038a69 | 82 | |
Zaitsev | 10:41552d038a69 | 83 | 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*/ |
Zaitsev | 10:41552d038a69 | 84 | |
Zaitsev | 10:41552d038a69 | 85 | return; |
Zaitsev | 10:41552d038a69 | 86 | } |
Zaitsev | 10:41552d038a69 | 87 | |
Zaitsev | 10:41552d038a69 | 88 | /* See rtc.h for details */ |
Zaitsev | 10:41552d038a69 | 89 | void fRtcFree(void) |
Zaitsev | 10:41552d038a69 | 90 | { |
Zaitsev | 10:41552d038a69 | 91 | /* Reset RTC control register */ |
Zaitsev | 10:41552d038a69 | 92 | RTCREG->CONTROL.WORD = False; |
Zaitsev | 10:41552d038a69 | 93 | |
Zaitsev | 10:41552d038a69 | 94 | /* disable interruption associated with the rtc */ |
Zaitsev | 10:41552d038a69 | 95 | NVIC_DisableIRQ(Rtc_IRQn); |
Zaitsev | 10:41552d038a69 | 96 | |
Zaitsev | 10:41552d038a69 | 97 | 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*/ |
Zaitsev | 10:41552d038a69 | 98 | } |
Zaitsev | 10:41552d038a69 | 99 | |
Zaitsev | 10:41552d038a69 | 100 | /* See rtc.h for details */ |
Zaitsev | 10:41552d038a69 | 101 | void fRtcSetInterrupt(uint32_t timestamp) |
Zaitsev | 10:41552d038a69 | 102 | { |
Zaitsev | 10:41552d038a69 | 103 | SubSecond = False; |
Zaitsev | 10:41552d038a69 | 104 | uint32_t Second = False, EnableInterrupt = False; |
Zaitsev | 10:41552d038a69 | 105 | uint8_t DividerAdjust = 1; |
Zaitsev | 10:41552d038a69 | 106 | |
Zaitsev | 10:41552d038a69 | 107 | if(timestamp) { |
Zaitsev | 10:41552d038a69 | 108 | if(timestamp >= RTC_SEC_TO_US) { |
Zaitsev | 10:41552d038a69 | 109 | /* TimeStamp is big enough to set second alarm */ |
Zaitsev | 10:41552d038a69 | 110 | Second = ((timestamp / RTC_SEC_TO_US) & RTC_SEC_MASK); /* Convert micro second to second */ |
Zaitsev | 10:41552d038a69 | 111 | RTCREG->SECOND_ALARM = Second; /* Write to alarm register */ |
Zaitsev | 10:41552d038a69 | 112 | |
Zaitsev | 10:41552d038a69 | 113 | /* Enable second interrupt */ |
Zaitsev | 10:41552d038a69 | 114 | EnableInterrupt = True << RTC_CONTROL_SEC_CNT_INT_BIT_POS; |
Zaitsev | 10:41552d038a69 | 115 | } |
Zaitsev | 10:41552d038a69 | 116 | timestamp = timestamp - Second * RTC_SEC_TO_US; /* Take out micro second for sub second alarm */ |
Zaitsev | 10:41552d038a69 | 117 | if(timestamp > False) { |
Zaitsev | 10:41552d038a69 | 118 | /* We have some thing for sub second */ |
Zaitsev | 10:41552d038a69 | 119 | |
Zaitsev | 10:41552d038a69 | 120 | /* Convert micro second to sub_seconds(each count = 30.5 us) */ |
Zaitsev | 10:41552d038a69 | 121 | if(timestamp > 131000) { |
Zaitsev | 10:41552d038a69 | 122 | DividerAdjust = 100; |
Zaitsev | 10:41552d038a69 | 123 | } |
Zaitsev | 10:41552d038a69 | 124 | |
Zaitsev | 10:41552d038a69 | 125 | volatile uint64_t Temp = (timestamp / DividerAdjust * RTC_CLOCK_HZ); |
Zaitsev | 10:41552d038a69 | 126 | Temp = (uint64_t)(Temp / RTC_SEC_TO_US * DividerAdjust); |
Zaitsev | 10:41552d038a69 | 127 | SubSecond = Temp & RTC_SUB_SEC_MASK; |
Zaitsev | 10:41552d038a69 | 128 | |
Zaitsev | 10:41552d038a69 | 129 | if(SubSecond <= 5) { |
Zaitsev | 10:41552d038a69 | 130 | SubSecond = 0; |
Zaitsev | 10:41552d038a69 | 131 | } |
Zaitsev | 10:41552d038a69 | 132 | |
Zaitsev | 10:41552d038a69 | 133 | if(SubSecond > False) { |
Zaitsev | 10:41552d038a69 | 134 | /* Second interrupt not enabled */ |
Zaitsev | 10:41552d038a69 | 135 | |
Zaitsev | 10:41552d038a69 | 136 | /* Set SUB SEC_ALARM */ |
Zaitsev | 10:41552d038a69 | 137 | RTCREG->SUB_SECOND_ALARM = SubSecond; /* Write to sub second alarm */ |
Zaitsev | 10:41552d038a69 | 138 | |
Zaitsev | 10:41552d038a69 | 139 | /* Enable sub second interrupt */ |
Zaitsev | 10:41552d038a69 | 140 | EnableInterrupt |= (True << RTC_CONTROL_SUBSEC_CNT_INT_BIT_POS); |
Zaitsev | 10:41552d038a69 | 141 | } |
Zaitsev | 10:41552d038a69 | 142 | } |
Zaitsev | 10:41552d038a69 | 143 | |
Zaitsev | 10:41552d038a69 | 144 | RTCREG->CONTROL.WORD |= EnableInterrupt; |
Zaitsev | 10:41552d038a69 | 145 | /* Enable RTC interrupt */ |
Zaitsev | 10:41552d038a69 | 146 | NVIC_EnableIRQ(Rtc_IRQn); |
Zaitsev | 10:41552d038a69 | 147 | |
Zaitsev | 10:41552d038a69 | 148 | /* Wait for RTC to finish writing register - RTC operates on 32K clock as compared to 32M core*/ |
Zaitsev | 10:41552d038a69 | 149 | while((RTCREG->STATUS.WORD & ((True << RTC_STATUS_SUB_SEC_ALARM_WRT_BIT_POS) | |
Zaitsev | 10:41552d038a69 | 150 | (True << RTC_STATUS_SEC_ALARM_WRT_BIT_POS) | |
Zaitsev | 10:41552d038a69 | 151 | (True << RTC_STATUS_CONTROL_WRT_BIT_POS))) == True); |
Zaitsev | 10:41552d038a69 | 152 | } |
Zaitsev | 10:41552d038a69 | 153 | return; |
Zaitsev | 10:41552d038a69 | 154 | } |
Zaitsev | 10:41552d038a69 | 155 | |
Zaitsev | 10:41552d038a69 | 156 | /* See rtc.h for details */ |
Zaitsev | 10:41552d038a69 | 157 | void fRtcDisableInterrupt(void) |
Zaitsev | 10:41552d038a69 | 158 | { |
Zaitsev | 10:41552d038a69 | 159 | /* Disable RTC interrupt */ |
Zaitsev | 10:41552d038a69 | 160 | NVIC_DisableIRQ(Rtc_IRQn); |
Zaitsev | 10:41552d038a69 | 161 | } |
Zaitsev | 10:41552d038a69 | 162 | |
Zaitsev | 10:41552d038a69 | 163 | /* See rtc.h for details */ |
Zaitsev | 10:41552d038a69 | 164 | void fRtcEnableInterrupt(void) |
Zaitsev | 10:41552d038a69 | 165 | { |
Zaitsev | 10:41552d038a69 | 166 | /* Enable RTC interrupt */ |
Zaitsev | 10:41552d038a69 | 167 | NVIC_EnableIRQ(Rtc_IRQn); |
Zaitsev | 10:41552d038a69 | 168 | } |
Zaitsev | 10:41552d038a69 | 169 | |
Zaitsev | 10:41552d038a69 | 170 | /* See rtc.h for details */ |
Zaitsev | 10:41552d038a69 | 171 | void fRtcClearInterrupt(void) |
Zaitsev | 10:41552d038a69 | 172 | { |
Zaitsev | 10:41552d038a69 | 173 | /* Disable subsec/sec interrupt */ |
Zaitsev | 10:41552d038a69 | 174 | /* Clear sec & sub_sec interrupts */ |
Zaitsev | 10:41552d038a69 | 175 | RTCREG->INT_CLEAR.WORD = ((True << RTC_INT_CLR_SUB_SEC_BIT_POS) | |
Zaitsev | 10:41552d038a69 | 176 | (True << RTC_INT_CLR_SEC_BIT_POS)); |
Zaitsev | 10:41552d038a69 | 177 | |
Zaitsev | 10:41552d038a69 | 178 | while((RTCREG->STATUS.WORD & ((True << RTC_STATUS_SUB_SEC_INT_CLR_WRT_BIT_POS) | |
Zaitsev | 10:41552d038a69 | 179 | (True << RTC_STATUS_SEC_INT_CLR_WRT_BIT_POS))) == True); /* Wait for RTC to finish writing register - RTC operates on 32K clock as compared to 32M core*/ |
Zaitsev | 10:41552d038a69 | 180 | } |
Zaitsev | 10:41552d038a69 | 181 | |
Zaitsev | 10:41552d038a69 | 182 | /* See rtc.h for details */ |
Zaitsev | 10:41552d038a69 | 183 | uint64_t fRtcRead(void) |
Zaitsev | 10:41552d038a69 | 184 | { |
Zaitsev | 10:41552d038a69 | 185 | uint32_t Second; |
Zaitsev | 10:41552d038a69 | 186 | uint16_t SubSecond; |
Zaitsev | 10:41552d038a69 | 187 | |
Zaitsev | 10:41552d038a69 | 188 | /* Hardware Bug fix: The rollover of the sub-second counter initiates the increment of the second counter. |
Zaitsev | 10:41552d038a69 | 189 | * That means there is one cycle where the sub-second has rolled back to zero and the second counter has not incremented |
Zaitsev | 10:41552d038a69 | 190 | * and a read during that cycle will be incorrect. That will occur for one RTC cycle and that is about 31us of exposure. |
Zaitsev | 10:41552d038a69 | 191 | * If you read a zero in the sub-second counter then increment the second counter by 1. |
Zaitsev | 10:41552d038a69 | 192 | * Alternatively, subtract 1 from the Sub-seconds counter to align the Second and Sub-Second rollover. |
Zaitsev | 10:41552d038a69 | 193 | */ |
Zaitsev | 10:41552d038a69 | 194 | |
Zaitsev | 10:41552d038a69 | 195 | /* Read the Second and Sub-second counters, then read the Second counter again. |
Zaitsev | 10:41552d038a69 | 196 | * If it changed, then the Second rolled over while reading Sub-seconds, so go back and read them both again. |
Zaitsev | 10:41552d038a69 | 197 | */ |
Zaitsev | 10:41552d038a69 | 198 | |
Zaitsev | 10:41552d038a69 | 199 | do { |
Zaitsev | 10:41552d038a69 | 200 | Second = RTCREG->SECOND_COUNTER; /* Get SEC_COUNTER reg value */ |
Zaitsev | 10:41552d038a69 | 201 | SubSecond = (RTCREG->SUB_SECOND_COUNTER - 1) & SUB_SEC_MASK; /* Get SUB_SEC_COUNTER reg value */ |
Zaitsev | 10:41552d038a69 | 202 | } while (Second != RTCREG->SECOND_COUNTER); /* Repeat if the second has changed */ |
Zaitsev | 10:41552d038a69 | 203 | |
Zaitsev | 10:41552d038a69 | 204 | //note: casting to float removed to avoid reduction in resolution |
Zaitsev | 10:41552d038a69 | 205 | uint64_t RtcTimeus = ((uint64_t)SubSecond * RTC_SEC_TO_US / RTC_CLOCK_HZ) + ((uint64_t)Second * RTC_SEC_TO_US); |
Zaitsev | 10:41552d038a69 | 206 | |
Zaitsev | 10:41552d038a69 | 207 | /*check that the time did not go backwards */ |
Zaitsev | 10:41552d038a69 | 208 | MBED_ASSERT(RtcTimeus >= LastRtcTimeus); |
Zaitsev | 10:41552d038a69 | 209 | LastRtcTimeus = RtcTimeus; |
Zaitsev | 10:41552d038a69 | 210 | |
Zaitsev | 10:41552d038a69 | 211 | return RtcTimeus; |
Zaitsev | 10:41552d038a69 | 212 | } |
Zaitsev | 10:41552d038a69 | 213 | |
Zaitsev | 10:41552d038a69 | 214 | /* See rtc.h for details */ |
Zaitsev | 10:41552d038a69 | 215 | void fRtcWrite(uint64_t RtcTimeus) |
Zaitsev | 10:41552d038a69 | 216 | { |
Zaitsev | 10:41552d038a69 | 217 | uint32_t Second = False; |
Zaitsev | 10:41552d038a69 | 218 | uint16_t SubSecond = False; |
Zaitsev | 10:41552d038a69 | 219 | /* Stop RTC */ |
Zaitsev | 10:41552d038a69 | 220 | RTCREG->CONTROL.WORD &= ~((True << RTC_CONTROL_SUBSEC_CNT_START_BIT_POS) | |
Zaitsev | 10:41552d038a69 | 221 | (True << RTC_CONTROL_SEC_CNT_START_BIT_POS)); |
Zaitsev | 10:41552d038a69 | 222 | |
Zaitsev | 10:41552d038a69 | 223 | if(RtcTimeus > RTC_SEC_TO_US) { |
Zaitsev | 10:41552d038a69 | 224 | /* TimeStamp is big enough to set second counter */ |
Zaitsev | 10:41552d038a69 | 225 | Second = ((RtcTimeus / RTC_SEC_TO_US) & RTC_SEC_MASK); |
Zaitsev | 10:41552d038a69 | 226 | } |
Zaitsev | 10:41552d038a69 | 227 | RTCREG->SECOND_COUNTER = Second; |
Zaitsev | 10:41552d038a69 | 228 | RtcTimeus = RtcTimeus - (Second * RTC_SEC_TO_US); |
Zaitsev | 10:41552d038a69 | 229 | if(RtcTimeus > False) { |
Zaitsev | 10:41552d038a69 | 230 | /* Convert TimeStamp to sub_seconds */ |
Zaitsev | 10:41552d038a69 | 231 | SubSecond = (uint16_t)((float)(RtcTimeus * RTC_CLOCK_HZ / RTC_SEC_TO_US)) & RTC_SUB_SEC_MASK; |
Zaitsev | 10:41552d038a69 | 232 | } |
Zaitsev | 10:41552d038a69 | 233 | /* Set SUB_SEC_ALARM */ |
Zaitsev | 10:41552d038a69 | 234 | RTCREG->SUB_SECOND_COUNTER = SubSecond; |
Zaitsev | 10:41552d038a69 | 235 | |
Zaitsev | 10:41552d038a69 | 236 | 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*/ |
Zaitsev | 10:41552d038a69 | 237 | /* Start RTC */ |
Zaitsev | 10:41552d038a69 | 238 | RTCREG->CONTROL.WORD |= ((True << RTC_CONTROL_SUBSEC_CNT_START_BIT_POS) | |
Zaitsev | 10:41552d038a69 | 239 | (True << RTC_CONTROL_SEC_CNT_START_BIT_POS)); |
Zaitsev | 10:41552d038a69 | 240 | |
Zaitsev | 10:41552d038a69 | 241 | 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*/ |
Zaitsev | 10:41552d038a69 | 242 | } |
Zaitsev | 10:41552d038a69 | 243 | |
Zaitsev | 10:41552d038a69 | 244 | /* See rtc.h for details */ |
Zaitsev | 10:41552d038a69 | 245 | void fRtcHandler(void) |
Zaitsev | 10:41552d038a69 | 246 | { |
Zaitsev | 10:41552d038a69 | 247 | /* SUB_SECOND/SECOND interrupt occured */ |
Zaitsev | 10:41552d038a69 | 248 | volatile uint32_t TempStatus = RTCREG->STATUS.WORD; |
Zaitsev | 10:41552d038a69 | 249 | |
Zaitsev | 10:41552d038a69 | 250 | /* Disable RTC interrupt */ |
Zaitsev | 10:41552d038a69 | 251 | NVIC_DisableIRQ(Rtc_IRQn); |
Zaitsev | 10:41552d038a69 | 252 | |
Zaitsev | 10:41552d038a69 | 253 | /* Clear sec & sub_sec interrupts */ |
Zaitsev | 10:41552d038a69 | 254 | RTCREG->INT_CLEAR.WORD = ((True << RTC_INT_CLR_SUB_SEC_BIT_POS) | |
Zaitsev | 10:41552d038a69 | 255 | (True << RTC_INT_CLR_SEC_BIT_POS)); |
Zaitsev | 10:41552d038a69 | 256 | |
Zaitsev | 10:41552d038a69 | 257 | /* TODO ANDing SUB_SEC & SEC interrupt - work around for RTC issue - will be resolved in REV G */ |
Zaitsev | 10:41552d038a69 | 258 | if(TempStatus & RTC_SEC_INT_STATUS_MASK) { |
Zaitsev | 10:41552d038a69 | 259 | /* Second interrupt occured */ |
Zaitsev | 10:41552d038a69 | 260 | if(SubSecond > False) { |
Zaitsev | 10:41552d038a69 | 261 | /* Set SUB SEC_ALARM */ |
Zaitsev | 10:41552d038a69 | 262 | RTCREG->SUB_SECOND_ALARM = SubSecond + RTCREG->SUB_SECOND_COUNTER; |
Zaitsev | 10:41552d038a69 | 263 | /* Enable sub second interrupt */ |
Zaitsev | 10:41552d038a69 | 264 | RTCREG->CONTROL.WORD |= (True << RTC_CONTROL_SUBSEC_CNT_INT_BIT_POS); |
Zaitsev | 10:41552d038a69 | 265 | } else { |
Zaitsev | 10:41552d038a69 | 266 | /* We reach here after second interrupt is occured */ |
Zaitsev | 10:41552d038a69 | 267 | RTCREG->CONTROL.WORD &= ~(True << RTC_CONTROL_SUBSEC_CNT_INT_BIT_POS) | |
Zaitsev | 10:41552d038a69 | 268 | (True << RTC_CONTROL_SEC_CNT_INT_BIT_POS); |
Zaitsev | 10:41552d038a69 | 269 | } |
Zaitsev | 10:41552d038a69 | 270 | } else { |
Zaitsev | 10:41552d038a69 | 271 | /* We reach here after sub_second or (Sub second + second) interrupt occured */ |
Zaitsev | 10:41552d038a69 | 272 | /* Disable Second and sub_second interrupt */ |
Zaitsev | 10:41552d038a69 | 273 | RTCREG->CONTROL.WORD &= ~(True << RTC_CONTROL_SUBSEC_CNT_INT_BIT_POS) | |
Zaitsev | 10:41552d038a69 | 274 | (True << RTC_CONTROL_SEC_CNT_INT_BIT_POS); |
Zaitsev | 10:41552d038a69 | 275 | } |
Zaitsev | 10:41552d038a69 | 276 | |
Zaitsev | 10:41552d038a69 | 277 | NVIC_EnableIRQ(Rtc_IRQn); |
Zaitsev | 10:41552d038a69 | 278 | |
Zaitsev | 10:41552d038a69 | 279 | /* Wait for RTC to finish writing register - RTC operates on 32K clock as compared to 32M core*/ |
Zaitsev | 10:41552d038a69 | 280 | while((RTCREG->STATUS.WORD & ((True << RTC_STATUS_SUB_SEC_ALARM_WRT_BIT_POS) | |
Zaitsev | 10:41552d038a69 | 281 | (True << RTC_STATUS_CONTROL_WRT_BIT_POS) | |
Zaitsev | 10:41552d038a69 | 282 | (True << RTC_STATUS_SUB_SEC_INT_CLR_WRT_BIT_POS) | |
Zaitsev | 10:41552d038a69 | 283 | (True << RTC_STATUS_SEC_INT_CLR_WRT_BIT_POS))) == True); |
Zaitsev | 10:41552d038a69 | 284 | |
Zaitsev | 10:41552d038a69 | 285 | lp_ticker_irq_handler(); |
Zaitsev | 10:41552d038a69 | 286 | } |
Zaitsev | 10:41552d038a69 | 287 | |
Zaitsev | 10:41552d038a69 | 288 | boolean fIsRtcEnabled(void) |
Zaitsev | 10:41552d038a69 | 289 | { |
Zaitsev | 10:41552d038a69 | 290 | if(RTCREG->CONTROL.BITS.SUB_SEC_COUNTER_EN | RTCREG->CONTROL.BITS.SEC_COUNTER_EN) { |
Zaitsev | 10:41552d038a69 | 291 | return True; |
Zaitsev | 10:41552d038a69 | 292 | } else { |
Zaitsev | 10:41552d038a69 | 293 | return False; |
Zaitsev | 10:41552d038a69 | 294 | } |
Zaitsev | 10:41552d038a69 | 295 | } |