mbed library sources. Supersedes mbed-src.

Dependents:   Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more

Committer:
AnnaBridge
Date:
Wed Feb 20 22:31:08 2019 +0000
Revision:
189:f392fc9709a3
Parent:
188:bcfe06ba3d64
mbed library release version 165

Who changed what in which revision?

UserRevisionLine numberNew contents of line
<> 144:ef7eb2e8f9f7 1 /* mbed Microcontroller Library
Anna Bridge 186:707f6e361f3e 2 * Copyright (c) 2006-2018 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 #include <stddef.h>
<> 144:ef7eb2e8f9f7 17 #include "us_ticker_api.h"
<> 144:ef7eb2e8f9f7 18 #include "PeripheralNames.h"
<> 144:ef7eb2e8f9f7 19 #include "clk_freqs.h"
<> 144:ef7eb2e8f9f7 20
Anna Bridge 186:707f6e361f3e 21 const ticker_info_t* us_ticker_get_info()
Anna Bridge 186:707f6e361f3e 22 {
Anna Bridge 186:707f6e361f3e 23 static const ticker_info_t info = {
Anna Bridge 186:707f6e361f3e 24 1000000, // 1 MHz
Anna Bridge 186:707f6e361f3e 25 32 // 32 bit counter
Anna Bridge 186:707f6e361f3e 26 };
Anna Bridge 186:707f6e361f3e 27 return &info;
Anna Bridge 186:707f6e361f3e 28 }
Anna Bridge 186:707f6e361f3e 29
Anna Bridge 186:707f6e361f3e 30 static bool us_ticker_inited = false;
Anna Bridge 186:707f6e361f3e 31
<> 144:ef7eb2e8f9f7 32 static void pit_init(void);
<> 144:ef7eb2e8f9f7 33 static void lptmr_init(void);
<> 144:ef7eb2e8f9f7 34
<> 144:ef7eb2e8f9f7 35
<> 144:ef7eb2e8f9f7 36 void us_ticker_init(void) {
Anna Bridge 186:707f6e361f3e 37 if (us_ticker_inited) {
Anna Bridge 186:707f6e361f3e 38 /* calling init again should cancel current interrupt */
Anna Bridge 186:707f6e361f3e 39 us_ticker_disable_interrupt();
Anna Bridge 186:707f6e361f3e 40 return;
Anna Bridge 186:707f6e361f3e 41 }
Anna Bridge 186:707f6e361f3e 42 us_ticker_inited = true;
Anna Bridge 186:707f6e361f3e 43
<> 144:ef7eb2e8f9f7 44 pit_init();
<> 144:ef7eb2e8f9f7 45 lptmr_init();
<> 144:ef7eb2e8f9f7 46 }
<> 144:ef7eb2e8f9f7 47
<> 144:ef7eb2e8f9f7 48 /******************************************************************************
<> 144:ef7eb2e8f9f7 49 * Timer for us timing.
<> 144:ef7eb2e8f9f7 50 ******************************************************************************/
<> 144:ef7eb2e8f9f7 51 static void pit_init(void) {
<> 144:ef7eb2e8f9f7 52 SIM->SCGC6 |= SIM_SCGC6_PIT_MASK; // Clock PIT
<> 144:ef7eb2e8f9f7 53 PIT->MCR = 0; // Enable PIT
Anna Bridge 186:707f6e361f3e 54
<> 144:ef7eb2e8f9f7 55 // Channel 1
<> 144:ef7eb2e8f9f7 56 PIT->CHANNEL[1].LDVAL = 0xFFFFFFFF;
<> 144:ef7eb2e8f9f7 57 PIT->CHANNEL[1].TCTRL = PIT_TCTRL_CHN_MASK; // Chain to timer 0, disable Interrupts
<> 144:ef7eb2e8f9f7 58 PIT->CHANNEL[1].TCTRL |= PIT_TCTRL_TEN_MASK; // Start timer 1
Anna Bridge 186:707f6e361f3e 59
<> 144:ef7eb2e8f9f7 60 // Use channel 0 as a prescaler for channel 1
<> 144:ef7eb2e8f9f7 61 PIT->CHANNEL[0].LDVAL = (bus_frequency() + 500000) / 1000000 - 1;
<> 144:ef7eb2e8f9f7 62 PIT->CHANNEL[0].TCTRL = PIT_TCTRL_TEN_MASK; // Start timer 0, disable interrupts
<> 144:ef7eb2e8f9f7 63 }
<> 144:ef7eb2e8f9f7 64
<> 144:ef7eb2e8f9f7 65 uint32_t us_ticker_read() {
<> 144:ef7eb2e8f9f7 66 // The PIT is a countdown timer
<> 144:ef7eb2e8f9f7 67 return ~(PIT->CHANNEL[1].CVAL);
<> 144:ef7eb2e8f9f7 68 }
<> 144:ef7eb2e8f9f7 69
<> 144:ef7eb2e8f9f7 70 /******************************************************************************
<> 144:ef7eb2e8f9f7 71 * Timer Event
Anna Bridge 186:707f6e361f3e 72 *
<> 144:ef7eb2e8f9f7 73 * It schedules interrupts at given (32bit)us interval of time.
<> 144:ef7eb2e8f9f7 74 * It is implemented used the 16bit Low Power Timer that remains powered in all
<> 144:ef7eb2e8f9f7 75 * power modes.
<> 144:ef7eb2e8f9f7 76 ******************************************************************************/
<> 144:ef7eb2e8f9f7 77 static void lptmr_isr(void);
<> 144:ef7eb2e8f9f7 78
<> 144:ef7eb2e8f9f7 79 static void lptmr_init(void) {
Anna Bridge 186:707f6e361f3e 80 uint32_t extosc;
<> 144:ef7eb2e8f9f7 81
<> 144:ef7eb2e8f9f7 82 /* Clock the timer */
<> 144:ef7eb2e8f9f7 83 SIM->SCGC5 |= SIM_SCGC5_LPTMR_MASK;
Anna Bridge 186:707f6e361f3e 84
<> 144:ef7eb2e8f9f7 85 /* Reset */
<> 144:ef7eb2e8f9f7 86 LPTMR0->CSR = 0;
<> 144:ef7eb2e8f9f7 87
<> 144:ef7eb2e8f9f7 88 #if defined(TARGET_KL43Z)
<> 144:ef7eb2e8f9f7 89 /* Set interrupt handler */
<> 144:ef7eb2e8f9f7 90 NVIC_SetVector(LPTMR0_IRQn, (uint32_t)lptmr_isr);
<> 144:ef7eb2e8f9f7 91 NVIC_EnableIRQ(LPTMR0_IRQn);
<> 144:ef7eb2e8f9f7 92
<> 144:ef7eb2e8f9f7 93
<> 144:ef7eb2e8f9f7 94 MCG->C1 |= MCG_C1_IRCLKEN_MASK;
<> 144:ef7eb2e8f9f7 95 extosc = mcgirc_frequency();
<> 144:ef7eb2e8f9f7 96 #else
<> 144:ef7eb2e8f9f7 97 /* Set interrupt handler */
<> 144:ef7eb2e8f9f7 98 NVIC_SetVector(LPTimer_IRQn, (uint32_t)lptmr_isr);
<> 144:ef7eb2e8f9f7 99 NVIC_EnableIRQ(LPTimer_IRQn);
<> 144:ef7eb2e8f9f7 100
<> 144:ef7eb2e8f9f7 101 /* Clock at (1)MHz -> (1)tick/us */
<> 144:ef7eb2e8f9f7 102 /* Check if the external oscillator can be divided to 1MHz */
<> 144:ef7eb2e8f9f7 103 extosc = extosc_frequency();
<> 144:ef7eb2e8f9f7 104 #endif
<> 144:ef7eb2e8f9f7 105 if (extosc != 0) { //If external oscillator found
<> 144:ef7eb2e8f9f7 106 if (extosc % 1000000u == 0) { //If it is a multiple if 1MHz
<> 144:ef7eb2e8f9f7 107 extosc /= 1000000;
<> 144:ef7eb2e8f9f7 108 if (extosc == 1) { //1MHz, set timerprescaler in bypass mode
<> 144:ef7eb2e8f9f7 109 LPTMR0->PSR = LPTMR_PSR_PCS(3) | LPTMR_PSR_PBYP_MASK;
<> 144:ef7eb2e8f9f7 110 return;
<> 144:ef7eb2e8f9f7 111 } else { //See if we can divide it to 1MHz
<> 144:ef7eb2e8f9f7 112 uint32_t divider = 0;
<> 144:ef7eb2e8f9f7 113 extosc >>= 1;
<> 144:ef7eb2e8f9f7 114 while (1) {
<> 144:ef7eb2e8f9f7 115 if (extosc == 1) {
<> 144:ef7eb2e8f9f7 116 LPTMR0->PSR = LPTMR_PSR_PCS(3) | LPTMR_PSR_PRESCALE(divider);
<> 144:ef7eb2e8f9f7 117 return;
<> 144:ef7eb2e8f9f7 118 }
<> 144:ef7eb2e8f9f7 119 if (extosc % 2 != 0) //If we can't divide by two anymore
<> 144:ef7eb2e8f9f7 120 break;
<> 144:ef7eb2e8f9f7 121 divider++;
<> 144:ef7eb2e8f9f7 122 extosc >>= 1;
<> 144:ef7eb2e8f9f7 123 }
<> 144:ef7eb2e8f9f7 124 }
<> 144:ef7eb2e8f9f7 125 }
<> 144:ef7eb2e8f9f7 126 }
<> 144:ef7eb2e8f9f7 127 #if defined(TARGET_KL43Z)
Anna Bridge 186:707f6e361f3e 128 //No suitable actual IRC oscillator clock -> Set it to (8MHz / divider)
<> 144:ef7eb2e8f9f7 129 MCG->SC &= ~MCG_SC_FCRDIV_MASK;
<> 144:ef7eb2e8f9f7 130 MCG->MC &= ~MCG->MC & MCG_MC_LIRC_DIV2_MASK;
<> 144:ef7eb2e8f9f7 131 LPTMR0->PSR = LPTMR_PSR_PCS(0) | LPTMR_PSR_PRESCALE(2);
<> 144:ef7eb2e8f9f7 132 #else
<> 144:ef7eb2e8f9f7 133 //No suitable external oscillator clock -> Use fast internal oscillator (4MHz / divider)
<> 144:ef7eb2e8f9f7 134 MCG->C1 |= MCG_C1_IRCLKEN_MASK;
<> 144:ef7eb2e8f9f7 135 MCG->C2 |= MCG_C2_IRCS_MASK;
<> 144:ef7eb2e8f9f7 136 LPTMR0->PSR = LPTMR_PSR_PCS(0);
<> 144:ef7eb2e8f9f7 137 switch (MCG->SC & MCG_SC_FCRDIV_MASK) {
<> 144:ef7eb2e8f9f7 138 case MCG_SC_FCRDIV(0): //4MHz
<> 144:ef7eb2e8f9f7 139 LPTMR0->PSR |= LPTMR_PSR_PRESCALE(1);
<> 144:ef7eb2e8f9f7 140 break;
<> 144:ef7eb2e8f9f7 141 case MCG_SC_FCRDIV(1): //2MHz
<> 144:ef7eb2e8f9f7 142 LPTMR0->PSR |= LPTMR_PSR_PRESCALE(0);
<> 144:ef7eb2e8f9f7 143 break;
<> 144:ef7eb2e8f9f7 144 default: //1MHz or anything else, in which case we put it on 1MHz
<> 144:ef7eb2e8f9f7 145 MCG->SC &= ~MCG_SC_FCRDIV_MASK;
<> 144:ef7eb2e8f9f7 146 MCG->SC |= MCG_SC_FCRDIV(2);
<> 144:ef7eb2e8f9f7 147 LPTMR0->PSR |= LPTMR_PSR_PBYP_MASK;
<> 144:ef7eb2e8f9f7 148 }
Anna Bridge 186:707f6e361f3e 149 #endif
<> 144:ef7eb2e8f9f7 150 }
<> 144:ef7eb2e8f9f7 151
<> 144:ef7eb2e8f9f7 152 void us_ticker_disable_interrupt(void) {
<> 144:ef7eb2e8f9f7 153 LPTMR0->CSR &= ~LPTMR_CSR_TIE_MASK;
<> 144:ef7eb2e8f9f7 154 }
<> 144:ef7eb2e8f9f7 155
<> 144:ef7eb2e8f9f7 156 void us_ticker_clear_interrupt(void) {
<> 144:ef7eb2e8f9f7 157 // we already clear interrupt in lptmr_isr
<> 144:ef7eb2e8f9f7 158 }
<> 144:ef7eb2e8f9f7 159
<> 144:ef7eb2e8f9f7 160 static uint32_t us_ticker_int_counter = 0;
<> 144:ef7eb2e8f9f7 161 static uint16_t us_ticker_int_remainder = 0;
<> 144:ef7eb2e8f9f7 162
<> 144:ef7eb2e8f9f7 163 static void lptmr_set(unsigned short count) {
<> 144:ef7eb2e8f9f7 164 /* Reset */
<> 144:ef7eb2e8f9f7 165 LPTMR0->CSR = 0;
Anna Bridge 186:707f6e361f3e 166
<> 144:ef7eb2e8f9f7 167 /* Set the compare register */
<> 144:ef7eb2e8f9f7 168 LPTMR0->CMR = count;
Anna Bridge 186:707f6e361f3e 169
<> 144:ef7eb2e8f9f7 170 /* Enable interrupt */
<> 144:ef7eb2e8f9f7 171 LPTMR0->CSR |= LPTMR_CSR_TIE_MASK;
Anna Bridge 186:707f6e361f3e 172
<> 144:ef7eb2e8f9f7 173 /* Start the timer */
<> 144:ef7eb2e8f9f7 174 LPTMR0->CSR |= LPTMR_CSR_TEN_MASK;
<> 144:ef7eb2e8f9f7 175 }
<> 144:ef7eb2e8f9f7 176
<> 144:ef7eb2e8f9f7 177 static void lptmr_isr(void) {
<> 144:ef7eb2e8f9f7 178 // write 1 to TCF to clear the LPT timer compare flag
<> 144:ef7eb2e8f9f7 179 LPTMR0->CSR |= LPTMR_CSR_TCF_MASK;
Anna Bridge 186:707f6e361f3e 180
<> 144:ef7eb2e8f9f7 181 if (us_ticker_int_counter > 0) {
<> 144:ef7eb2e8f9f7 182 lptmr_set(0xFFFF);
<> 144:ef7eb2e8f9f7 183 us_ticker_int_counter--;
Anna Bridge 186:707f6e361f3e 184
<> 144:ef7eb2e8f9f7 185 } else {
<> 144:ef7eb2e8f9f7 186 if (us_ticker_int_remainder > 0) {
<> 144:ef7eb2e8f9f7 187 lptmr_set(us_ticker_int_remainder);
<> 144:ef7eb2e8f9f7 188 us_ticker_int_remainder = 0;
Anna Bridge 186:707f6e361f3e 189
<> 144:ef7eb2e8f9f7 190 } else {
Anna Bridge 186:707f6e361f3e 191 /* Stop the timer */
Anna Bridge 186:707f6e361f3e 192 LPTMR0->CSR &= ~LPTMR_CSR_TEN_MASK;
Anna Bridge 186:707f6e361f3e 193
<> 144:ef7eb2e8f9f7 194 // This function is going to disable the interrupts if there are
<> 144:ef7eb2e8f9f7 195 // no other events in the queue
<> 144:ef7eb2e8f9f7 196 us_ticker_irq_handler();
<> 144:ef7eb2e8f9f7 197 }
<> 144:ef7eb2e8f9f7 198 }
<> 144:ef7eb2e8f9f7 199 }
<> 144:ef7eb2e8f9f7 200
<> 144:ef7eb2e8f9f7 201 void us_ticker_set_interrupt(timestamp_t timestamp) {
AnnaBridge 174:b96e65c34a4d 202 uint32_t delta = timestamp - us_ticker_read();
<> 144:ef7eb2e8f9f7 203 us_ticker_int_counter = (uint32_t)(delta >> 16);
<> 144:ef7eb2e8f9f7 204 us_ticker_int_remainder = (uint16_t)(0xFFFF & delta);
<> 144:ef7eb2e8f9f7 205 if (us_ticker_int_counter > 0) {
<> 144:ef7eb2e8f9f7 206 lptmr_set(0xFFFF);
<> 144:ef7eb2e8f9f7 207 us_ticker_int_counter--;
<> 144:ef7eb2e8f9f7 208 } else {
<> 144:ef7eb2e8f9f7 209 lptmr_set(us_ticker_int_remainder);
<> 144:ef7eb2e8f9f7 210 us_ticker_int_remainder = 0;
<> 144:ef7eb2e8f9f7 211 }
<> 144:ef7eb2e8f9f7 212 }
AnnaBridge 174:b96e65c34a4d 213
AnnaBridge 174:b96e65c34a4d 214 void us_ticker_fire_interrupt(void)
AnnaBridge 174:b96e65c34a4d 215 {
AnnaBridge 182:a56a73fd2a6f 216 us_ticker_int_counter = 0;
AnnaBridge 182:a56a73fd2a6f 217 us_ticker_int_remainder = 0;
AnnaBridge 182:a56a73fd2a6f 218
AnnaBridge 174:b96e65c34a4d 219 #if defined(TARGET_KL43Z)
AnnaBridge 174:b96e65c34a4d 220 NVIC_SetPendingIRQ(LPTMR0_IRQn);
AnnaBridge 174:b96e65c34a4d 221 #else
AnnaBridge 174:b96e65c34a4d 222 NVIC_SetPendingIRQ(LPTimer_IRQn);
AnnaBridge 174:b96e65c34a4d 223
AnnaBridge 174:b96e65c34a4d 224 #endif
AnnaBridge 174:b96e65c34a4d 225 }
AnnaBridge 188:bcfe06ba3d64 226
AnnaBridge 188:bcfe06ba3d64 227 void us_ticker_free(void)
AnnaBridge 188:bcfe06ba3d64 228 {
AnnaBridge 188:bcfe06ba3d64 229
AnnaBridge 188:bcfe06ba3d64 230 }