mbed library sources. Supersedes mbed-src.
Dependents: Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more
targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/api/lp_ticker.c@177:d650f5d4c87a, 2017-11-08 (annotated)
- Committer:
- AnnaBridge
- Date:
- Wed Nov 08 13:50:44 2017 +0000
- Revision:
- 177:d650f5d4c87a
- Parent:
- 174:b96e65c34a4d
- Child:
- 182:a56a73fd2a6f
This updates the lib to the mbed lib v 155
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
<> | 154:37f96f9d4de2 | 1 | /* mbed Microcontroller Library |
<> | 154:37f96f9d4de2 | 2 | * Copyright (c) 2016 ARM Limited |
<> | 154:37f96f9d4de2 | 3 | * |
<> | 154:37f96f9d4de2 | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
<> | 154:37f96f9d4de2 | 5 | * you may not use this file except in compliance with the License. |
<> | 154:37f96f9d4de2 | 6 | * You may obtain a copy of the License at |
<> | 154:37f96f9d4de2 | 7 | * |
<> | 154:37f96f9d4de2 | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
<> | 154:37f96f9d4de2 | 9 | * |
<> | 154:37f96f9d4de2 | 10 | * Unless required by applicable law or agreed to in writing, software |
<> | 154:37f96f9d4de2 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
<> | 154:37f96f9d4de2 | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
<> | 154:37f96f9d4de2 | 13 | * See the License for the specific language governing permissions and |
<> | 154:37f96f9d4de2 | 14 | * limitations under the License. |
<> | 154:37f96f9d4de2 | 15 | */ |
<> | 154:37f96f9d4de2 | 16 | |
<> | 154:37f96f9d4de2 | 17 | #if DEVICE_LOWPOWERTIMER |
<> | 154:37f96f9d4de2 | 18 | |
<> | 154:37f96f9d4de2 | 19 | #include "lp_ticker_api.h" |
<> | 154:37f96f9d4de2 | 20 | #include "fsl_rtc.h" |
<> | 154:37f96f9d4de2 | 21 | #include "fsl_lptmr.h" |
<> | 154:37f96f9d4de2 | 22 | #include "cmsis.h" |
<> | 154:37f96f9d4de2 | 23 | #include "rtc_api.h" |
<> | 154:37f96f9d4de2 | 24 | |
<> | 154:37f96f9d4de2 | 25 | #define MAX_SEC_BITS (12) |
<> | 154:37f96f9d4de2 | 26 | #define MAX_SEC_MASK ((1 << MAX_SEC_BITS) - 1) |
<> | 154:37f96f9d4de2 | 27 | #define SEC_IN_USEC (1000000) |
<> | 154:37f96f9d4de2 | 28 | #define OSC32K_CLK_HZ (32768) |
<> | 154:37f96f9d4de2 | 29 | #define MAX_LPTMR_SLEEP ((1 << 16) - 1) |
<> | 154:37f96f9d4de2 | 30 | |
<> | 154:37f96f9d4de2 | 31 | static bool lp_ticker_inited = false; |
<> | 154:37f96f9d4de2 | 32 | static int lptmr_schedule = 0; |
<> | 154:37f96f9d4de2 | 33 | |
<> | 154:37f96f9d4de2 | 34 | static void rtc_isr(void) |
<> | 154:37f96f9d4de2 | 35 | { |
AnnaBridge | 167:e84263d55307 | 36 | uint32_t sr = RTC->SR; |
AnnaBridge | 167:e84263d55307 | 37 | if (sr & RTC_SR_TOF_MASK) { |
AnnaBridge | 167:e84263d55307 | 38 | // Reset RTC to 0 so it keeps counting |
AnnaBridge | 167:e84263d55307 | 39 | RTC_StopTimer(RTC); |
AnnaBridge | 167:e84263d55307 | 40 | RTC->TSR = 0; |
AnnaBridge | 167:e84263d55307 | 41 | RTC_StartTimer(RTC); |
AnnaBridge | 167:e84263d55307 | 42 | } else if (sr & RTC_SR_TAF_MASK) { |
AnnaBridge | 167:e84263d55307 | 43 | RTC_DisableInterrupts(RTC, kRTC_AlarmInterruptEnable); |
AnnaBridge | 167:e84263d55307 | 44 | RTC->TAR = 0; /* Write clears the IRQ flag */ |
<> | 154:37f96f9d4de2 | 45 | |
AnnaBridge | 167:e84263d55307 | 46 | /* Wait subsecond remainder if any */ |
AnnaBridge | 167:e84263d55307 | 47 | if (lptmr_schedule) { |
AnnaBridge | 167:e84263d55307 | 48 | LPTMR_SetTimerPeriod(LPTMR0, lptmr_schedule); |
AnnaBridge | 167:e84263d55307 | 49 | LPTMR_EnableInterrupts(LPTMR0, kLPTMR_TimerInterruptEnable); |
AnnaBridge | 167:e84263d55307 | 50 | LPTMR_StartTimer(LPTMR0); |
AnnaBridge | 167:e84263d55307 | 51 | } else { |
AnnaBridge | 167:e84263d55307 | 52 | lp_ticker_irq_handler(); |
AnnaBridge | 167:e84263d55307 | 53 | } |
AnnaBridge | 167:e84263d55307 | 54 | } else if (sr & RTC_SR_TIF_MASK) { |
AnnaBridge | 167:e84263d55307 | 55 | RTC_DisableInterrupts(RTC, kRTC_TimeOverflowInterruptEnable); |
<> | 154:37f96f9d4de2 | 56 | } |
<> | 154:37f96f9d4de2 | 57 | } |
<> | 154:37f96f9d4de2 | 58 | |
<> | 154:37f96f9d4de2 | 59 | static void lptmr_isr(void) |
<> | 154:37f96f9d4de2 | 60 | { |
<> | 154:37f96f9d4de2 | 61 | LPTMR_ClearStatusFlags(LPTMR0, kLPTMR_TimerCompareFlag); |
<> | 154:37f96f9d4de2 | 62 | LPTMR_StopTimer(LPTMR0); |
<> | 154:37f96f9d4de2 | 63 | |
<> | 154:37f96f9d4de2 | 64 | lp_ticker_irq_handler(); |
<> | 154:37f96f9d4de2 | 65 | } |
<> | 154:37f96f9d4de2 | 66 | |
<> | 154:37f96f9d4de2 | 67 | /** Initialize the low power ticker |
<> | 154:37f96f9d4de2 | 68 | * |
<> | 154:37f96f9d4de2 | 69 | */ |
<> | 154:37f96f9d4de2 | 70 | void lp_ticker_init(void) |
<> | 154:37f96f9d4de2 | 71 | { |
<> | 154:37f96f9d4de2 | 72 | lptmr_config_t lptmrConfig; |
<> | 154:37f96f9d4de2 | 73 | |
<> | 154:37f96f9d4de2 | 74 | if (lp_ticker_inited) { |
<> | 154:37f96f9d4de2 | 75 | return; |
<> | 154:37f96f9d4de2 | 76 | } |
<> | 154:37f96f9d4de2 | 77 | lp_ticker_inited = true; |
<> | 154:37f96f9d4de2 | 78 | |
<> | 154:37f96f9d4de2 | 79 | /* Setup low resolution clock - RTC */ |
<> | 154:37f96f9d4de2 | 80 | if (!rtc_isenabled()) { |
<> | 154:37f96f9d4de2 | 81 | rtc_init(); |
<> | 154:37f96f9d4de2 | 82 | RTC_DisableInterrupts(RTC, kRTC_AlarmInterruptEnable | kRTC_SecondsInterruptEnable); |
<> | 154:37f96f9d4de2 | 83 | RTC_StartTimer(RTC); |
<> | 154:37f96f9d4de2 | 84 | } |
<> | 154:37f96f9d4de2 | 85 | |
AnnaBridge | 167:e84263d55307 | 86 | RTC->TAR = 0; /* Write clears the IRQ flag */ |
<> | 154:37f96f9d4de2 | 87 | NVIC_ClearPendingIRQ(RTC_IRQn); |
<> | 154:37f96f9d4de2 | 88 | NVIC_SetVector(RTC_IRQn, (uint32_t)rtc_isr); |
<> | 154:37f96f9d4de2 | 89 | NVIC_EnableIRQ(RTC_IRQn); |
<> | 154:37f96f9d4de2 | 90 | |
<> | 154:37f96f9d4de2 | 91 | /* Setup high resolution clock - LPTMR */ |
<> | 154:37f96f9d4de2 | 92 | LPTMR_GetDefaultConfig(&lptmrConfig); |
<> | 154:37f96f9d4de2 | 93 | /* Use 32kHz drive */ |
<> | 154:37f96f9d4de2 | 94 | CLOCK_SetXtal32Freq(OSC32K_CLK_HZ); |
<> | 154:37f96f9d4de2 | 95 | lptmrConfig.prescalerClockSource = kLPTMR_PrescalerClock_2; |
<> | 154:37f96f9d4de2 | 96 | LPTMR_Init(LPTMR0, &lptmrConfig); |
<> | 154:37f96f9d4de2 | 97 | LPTMR_EnableInterrupts(LPTMR0, kLPTMR_TimerInterruptEnable); |
<> | 154:37f96f9d4de2 | 98 | NVIC_ClearPendingIRQ(LPTMR0_IRQn); |
<> | 154:37f96f9d4de2 | 99 | NVIC_SetVector(LPTMR0_IRQn, (uint32_t)lptmr_isr); |
<> | 154:37f96f9d4de2 | 100 | EnableIRQ(LPTMR0_IRQn); |
<> | 154:37f96f9d4de2 | 101 | } |
<> | 154:37f96f9d4de2 | 102 | |
<> | 154:37f96f9d4de2 | 103 | /** Read the current counter |
<> | 154:37f96f9d4de2 | 104 | * |
<> | 154:37f96f9d4de2 | 105 | * @return The current timer's counter value in microseconds |
<> | 154:37f96f9d4de2 | 106 | */ |
<> | 154:37f96f9d4de2 | 107 | uint32_t lp_ticker_read(void) |
<> | 154:37f96f9d4de2 | 108 | { |
<> | 154:37f96f9d4de2 | 109 | uint32_t sec, pre; |
<> | 154:37f96f9d4de2 | 110 | |
<> | 154:37f96f9d4de2 | 111 | if (!lp_ticker_inited) { |
<> | 154:37f96f9d4de2 | 112 | lp_ticker_init(); |
<> | 154:37f96f9d4de2 | 113 | } |
<> | 154:37f96f9d4de2 | 114 | |
<> | 154:37f96f9d4de2 | 115 | sec = RTC->TSR; /* 32b: Seconds */ |
<> | 154:37f96f9d4de2 | 116 | pre = RTC->TPR; /* 16b: Increments every 32.768kHz clock cycle (30us) */ |
<> | 154:37f96f9d4de2 | 117 | |
<> | 154:37f96f9d4de2 | 118 | /* Final value: 11b (4095) for sec and 21b for usec (pre can reach 1,000,000us which is close to 1<<20) */ |
<> | 154:37f96f9d4de2 | 119 | uint32_t ret = (((sec & MAX_SEC_MASK) * SEC_IN_USEC) + (((uint64_t)pre * SEC_IN_USEC) / OSC32K_CLK_HZ)); |
<> | 154:37f96f9d4de2 | 120 | |
<> | 154:37f96f9d4de2 | 121 | return ret; |
<> | 154:37f96f9d4de2 | 122 | } |
<> | 154:37f96f9d4de2 | 123 | |
<> | 154:37f96f9d4de2 | 124 | /** Set interrupt for specified timestamp |
<> | 154:37f96f9d4de2 | 125 | * |
<> | 154:37f96f9d4de2 | 126 | * @param timestamp The time in microseconds to be set |
<> | 154:37f96f9d4de2 | 127 | */ |
<> | 154:37f96f9d4de2 | 128 | void lp_ticker_set_interrupt(timestamp_t timestamp) |
<> | 154:37f96f9d4de2 | 129 | { |
<> | 154:37f96f9d4de2 | 130 | uint32_t now_us, delta_us, delta_ticks; |
<> | 154:37f96f9d4de2 | 131 | |
<> | 154:37f96f9d4de2 | 132 | if (!lp_ticker_inited) { |
<> | 154:37f96f9d4de2 | 133 | lp_ticker_init(); |
<> | 154:37f96f9d4de2 | 134 | } |
<> | 154:37f96f9d4de2 | 135 | |
<> | 154:37f96f9d4de2 | 136 | lptmr_schedule = 0; |
<> | 154:37f96f9d4de2 | 137 | now_us = lp_ticker_read(); |
<> | 154:37f96f9d4de2 | 138 | delta_us = timestamp > now_us ? timestamp - now_us : (uint32_t)((uint64_t)timestamp + 0xFFFFFFFF - now_us); |
<> | 154:37f96f9d4de2 | 139 | |
<> | 154:37f96f9d4de2 | 140 | /* Checking if LPTRM can handle this sleep */ |
<> | 154:37f96f9d4de2 | 141 | delta_ticks = USEC_TO_COUNT(delta_us, CLOCK_GetFreq(kCLOCK_Er32kClk)); |
AnnaBridge | 177:d650f5d4c87a | 142 | if (delta_ticks == 0) { |
AnnaBridge | 177:d650f5d4c87a | 143 | /* The requested delay is less than the minimum resolution of this counter */ |
AnnaBridge | 177:d650f5d4c87a | 144 | delta_ticks = 1; |
AnnaBridge | 177:d650f5d4c87a | 145 | } |
AnnaBridge | 177:d650f5d4c87a | 146 | |
<> | 154:37f96f9d4de2 | 147 | if (delta_ticks > MAX_LPTMR_SLEEP) { |
<> | 154:37f96f9d4de2 | 148 | /* Using RTC if wait time is over 16b (2s @32kHz) */ |
<> | 154:37f96f9d4de2 | 149 | uint32_t delta_sec; |
<> | 154:37f96f9d4de2 | 150 | |
<> | 154:37f96f9d4de2 | 151 | delta_us += COUNT_TO_USEC(RTC->TPR, CLOCK_GetFreq(kCLOCK_Er32kClk)); /* Accounting for started second */ |
<> | 154:37f96f9d4de2 | 152 | delta_sec = delta_us / SEC_IN_USEC; |
<> | 154:37f96f9d4de2 | 153 | delta_us -= delta_sec * SEC_IN_USEC; |
<> | 154:37f96f9d4de2 | 154 | |
<> | 154:37f96f9d4de2 | 155 | RTC->TAR = RTC->TSR + delta_sec - 1; |
<> | 154:37f96f9d4de2 | 156 | |
<> | 154:37f96f9d4de2 | 157 | RTC_EnableInterrupts(RTC, kRTC_AlarmInterruptEnable); |
<> | 154:37f96f9d4de2 | 158 | |
<> | 154:37f96f9d4de2 | 159 | /* Set aditional, subsecond, sleep time */ |
<> | 154:37f96f9d4de2 | 160 | if (delta_us) { |
<> | 154:37f96f9d4de2 | 161 | lptmr_schedule = USEC_TO_COUNT(delta_us, CLOCK_GetFreq(kCLOCK_Er32kClk)); |
AnnaBridge | 177:d650f5d4c87a | 162 | if (lptmr_schedule == 0) { |
AnnaBridge | 177:d650f5d4c87a | 163 | /* The requested delay is less than the minimum resolution of this counter */ |
AnnaBridge | 177:d650f5d4c87a | 164 | lptmr_schedule = 1; |
AnnaBridge | 177:d650f5d4c87a | 165 | } |
AnnaBridge | 177:d650f5d4c87a | 166 | |
<> | 154:37f96f9d4de2 | 167 | } |
<> | 154:37f96f9d4de2 | 168 | } else { |
<> | 154:37f96f9d4de2 | 169 | /* Below RTC resolution using LPTMR */ |
<> | 154:37f96f9d4de2 | 170 | LPTMR_SetTimerPeriod(LPTMR0, delta_ticks); |
<> | 154:37f96f9d4de2 | 171 | LPTMR_EnableInterrupts(LPTMR0, kLPTMR_TimerInterruptEnable); |
<> | 154:37f96f9d4de2 | 172 | LPTMR_StartTimer(LPTMR0); |
<> | 154:37f96f9d4de2 | 173 | } |
<> | 154:37f96f9d4de2 | 174 | } |
<> | 154:37f96f9d4de2 | 175 | |
AnnaBridge | 174:b96e65c34a4d | 176 | void lp_ticker_fire_interrupt(void) |
AnnaBridge | 174:b96e65c34a4d | 177 | { |
AnnaBridge | 174:b96e65c34a4d | 178 | NVIC_SetPendingIRQ(LPTMR0_IRQn); |
AnnaBridge | 174:b96e65c34a4d | 179 | } |
AnnaBridge | 174:b96e65c34a4d | 180 | |
<> | 154:37f96f9d4de2 | 181 | /** Disable low power ticker interrupt |
<> | 154:37f96f9d4de2 | 182 | * |
<> | 154:37f96f9d4de2 | 183 | */ |
<> | 154:37f96f9d4de2 | 184 | void lp_ticker_disable_interrupt(void) |
<> | 154:37f96f9d4de2 | 185 | { |
<> | 154:37f96f9d4de2 | 186 | LPTMR_DisableInterrupts(LPTMR0, kLPTMR_TimerInterruptEnable); |
<> | 154:37f96f9d4de2 | 187 | RTC_DisableInterrupts(RTC, kRTC_AlarmInterruptEnable); |
<> | 154:37f96f9d4de2 | 188 | } |
<> | 154:37f96f9d4de2 | 189 | |
<> | 154:37f96f9d4de2 | 190 | /** Clear the low power ticker interrupt |
<> | 154:37f96f9d4de2 | 191 | * |
<> | 154:37f96f9d4de2 | 192 | */ |
<> | 154:37f96f9d4de2 | 193 | void lp_ticker_clear_interrupt(void) |
<> | 154:37f96f9d4de2 | 194 | { |
<> | 154:37f96f9d4de2 | 195 | RTC->TAR = 0; /* Write clears the IRQ flag */ |
<> | 154:37f96f9d4de2 | 196 | LPTMR_ClearStatusFlags(LPTMR0, kLPTMR_TimerCompareFlag); |
<> | 154:37f96f9d4de2 | 197 | } |
AnnaBridge | 174:b96e65c34a4d | 198 | |
<> | 154:37f96f9d4de2 | 199 | #endif /* DEVICE_LOWPOWERTIMER */ |