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