mbed library sources

Dependents:   Encrypted my_mbed lklk CyaSSL_DTLS_Cellular ... more

Superseded

This library was superseded by mbed-dev - https://os.mbed.com/users/mbed_official/code/mbed-dev/.

Development branch of the mbed library sources. This library is kept in synch with the latest changes from the mbed SDK and it is not guaranteed to work.

If you are looking for a stable and tested release, please import one of the official mbed library releases:

Import librarymbed

The official Mbed 2 C/C++ SDK provides the software platform and libraries to build your applications.

Committer:
mbed_official
Date:
Thu Oct 23 09:45:08 2014 +0100
Revision:
363:12a245e5c745
Parent:
304:89b9c3a9a045
Synchronized with git revision 6ff7dfe464a15417f666938479c7860707707331

Full URL: https://github.com/mbedmicro/mbed/commit/6ff7dfe464a15417f666938479c7860707707331/

Target: Freescale FRDM-KL43Z addition

Who changed what in which revision?

UserRevisionLine numberNew contents of line
emilmont 10:3bc89ef62ce7 1 /* mbed Microcontroller Library
emilmont 10:3bc89ef62ce7 2 * Copyright (c) 2006-2013 ARM Limited
emilmont 10:3bc89ef62ce7 3 *
emilmont 10:3bc89ef62ce7 4 * Licensed under the Apache License, Version 2.0 (the "License");
emilmont 10:3bc89ef62ce7 5 * you may not use this file except in compliance with the License.
emilmont 10:3bc89ef62ce7 6 * You may obtain a copy of the License at
emilmont 10:3bc89ef62ce7 7 *
emilmont 10:3bc89ef62ce7 8 * http://www.apache.org/licenses/LICENSE-2.0
emilmont 10:3bc89ef62ce7 9 *
emilmont 10:3bc89ef62ce7 10 * Unless required by applicable law or agreed to in writing, software
emilmont 10:3bc89ef62ce7 11 * distributed under the License is distributed on an "AS IS" BASIS,
emilmont 10:3bc89ef62ce7 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
emilmont 10:3bc89ef62ce7 13 * See the License for the specific language governing permissions and
emilmont 10:3bc89ef62ce7 14 * limitations under the License.
emilmont 10:3bc89ef62ce7 15 */
emilmont 10:3bc89ef62ce7 16 #include <stddef.h>
emilmont 10:3bc89ef62ce7 17 #include "us_ticker_api.h"
emilmont 10:3bc89ef62ce7 18 #include "PeripheralNames.h"
mbed_official 72:248c61396e08 19 #include "clk_freqs.h"
emilmont 10:3bc89ef62ce7 20
emilmont 10:3bc89ef62ce7 21 static void pit_init(void);
emilmont 10:3bc89ef62ce7 22 static void lptmr_init(void);
emilmont 10:3bc89ef62ce7 23
emilmont 10:3bc89ef62ce7 24 static int us_ticker_inited = 0;
emilmont 10:3bc89ef62ce7 25
emilmont 10:3bc89ef62ce7 26 void us_ticker_init(void) {
emilmont 10:3bc89ef62ce7 27 if (us_ticker_inited) return;
emilmont 10:3bc89ef62ce7 28 us_ticker_inited = 1;
emilmont 10:3bc89ef62ce7 29
emilmont 10:3bc89ef62ce7 30 pit_init();
emilmont 10:3bc89ef62ce7 31 lptmr_init();
emilmont 10:3bc89ef62ce7 32 }
emilmont 10:3bc89ef62ce7 33
emilmont 10:3bc89ef62ce7 34 /******************************************************************************
emilmont 10:3bc89ef62ce7 35 * Timer for us timing.
emilmont 10:3bc89ef62ce7 36 ******************************************************************************/
emilmont 10:3bc89ef62ce7 37 static void pit_init(void) {
emilmont 10:3bc89ef62ce7 38 SIM->SCGC6 |= SIM_SCGC6_PIT_MASK; // Clock PIT
emilmont 10:3bc89ef62ce7 39 PIT->MCR = 0; // Enable PIT
emilmont 10:3bc89ef62ce7 40
emilmont 10:3bc89ef62ce7 41 // Channel 1
emilmont 10:3bc89ef62ce7 42 PIT->CHANNEL[1].LDVAL = 0xFFFFFFFF;
emilmont 10:3bc89ef62ce7 43 PIT->CHANNEL[1].TCTRL = PIT_TCTRL_CHN_MASK; // Chain to timer 0, disable Interrupts
emilmont 10:3bc89ef62ce7 44 PIT->CHANNEL[1].TCTRL |= PIT_TCTRL_TEN_MASK; // Start timer 1
emilmont 10:3bc89ef62ce7 45
emilmont 10:3bc89ef62ce7 46 // Use channel 0 as a prescaler for channel 1
mbed_official 97:a69e21de83fb 47 PIT->CHANNEL[0].LDVAL = (bus_frequency() + 500000) / 1000000 - 1;
emilmont 10:3bc89ef62ce7 48 PIT->CHANNEL[0].TCTRL = PIT_TCTRL_TEN_MASK; // Start timer 0, disable interrupts
emilmont 10:3bc89ef62ce7 49 }
emilmont 10:3bc89ef62ce7 50
emilmont 10:3bc89ef62ce7 51 uint32_t us_ticker_read() {
emilmont 10:3bc89ef62ce7 52 if (!us_ticker_inited)
emilmont 10:3bc89ef62ce7 53 us_ticker_init();
emilmont 10:3bc89ef62ce7 54
emilmont 10:3bc89ef62ce7 55 // The PIT is a countdown timer
emilmont 10:3bc89ef62ce7 56 return ~(PIT->CHANNEL[1].CVAL);
emilmont 10:3bc89ef62ce7 57 }
emilmont 10:3bc89ef62ce7 58
emilmont 10:3bc89ef62ce7 59 /******************************************************************************
emilmont 10:3bc89ef62ce7 60 * Timer Event
emilmont 10:3bc89ef62ce7 61 *
emilmont 10:3bc89ef62ce7 62 * It schedules interrupts at given (32bit)us interval of time.
emilmont 10:3bc89ef62ce7 63 * It is implemented used the 16bit Low Power Timer that remains powered in all
emilmont 10:3bc89ef62ce7 64 * power modes.
emilmont 10:3bc89ef62ce7 65 ******************************************************************************/
emilmont 10:3bc89ef62ce7 66 static void lptmr_isr(void);
emilmont 10:3bc89ef62ce7 67
emilmont 10:3bc89ef62ce7 68 static void lptmr_init(void) {
mbed_official 363:12a245e5c745 69 uint32_t extosc;
mbed_official 363:12a245e5c745 70
emilmont 10:3bc89ef62ce7 71 /* Clock the timer */
emilmont 10:3bc89ef62ce7 72 SIM->SCGC5 |= SIM_SCGC5_LPTMR_MASK;
emilmont 10:3bc89ef62ce7 73
emilmont 10:3bc89ef62ce7 74 /* Reset */
emilmont 10:3bc89ef62ce7 75 LPTMR0->CSR = 0;
mbed_official 363:12a245e5c745 76
mbed_official 363:12a245e5c745 77 #if defined(TARGET_KL43Z)
mbed_official 363:12a245e5c745 78 /* Set interrupt handler */
mbed_official 363:12a245e5c745 79 NVIC_SetVector(LPTMR0_IRQn, (uint32_t)lptmr_isr);
mbed_official 363:12a245e5c745 80 NVIC_EnableIRQ(LPTMR0_IRQn);
mbed_official 363:12a245e5c745 81
mbed_official 363:12a245e5c745 82
mbed_official 363:12a245e5c745 83 MCG->C1 |= MCG_C1_IRCLKEN_MASK;
mbed_official 363:12a245e5c745 84 extosc = mcgirc_frequency();
mbed_official 363:12a245e5c745 85 #else
emilmont 10:3bc89ef62ce7 86 /* Set interrupt handler */
emilmont 10:3bc89ef62ce7 87 NVIC_SetVector(LPTimer_IRQn, (uint32_t)lptmr_isr);
emilmont 10:3bc89ef62ce7 88 NVIC_EnableIRQ(LPTimer_IRQn);
mbed_official 363:12a245e5c745 89
emilmont 10:3bc89ef62ce7 90 /* Clock at (1)MHz -> (1)tick/us */
mbed_official 72:248c61396e08 91 /* Check if the external oscillator can be divided to 1MHz */
mbed_official 363:12a245e5c745 92 extosc = extosc_frequency();
mbed_official 363:12a245e5c745 93 #endif
mbed_official 72:248c61396e08 94 if (extosc != 0) { //If external oscillator found
mbed_official 72:248c61396e08 95 if (extosc % 1000000u == 0) { //If it is a multiple if 1MHz
mbed_official 72:248c61396e08 96 extosc /= 1000000;
mbed_official 72:248c61396e08 97 if (extosc == 1) { //1MHz, set timerprescaler in bypass mode
mbed_official 72:248c61396e08 98 LPTMR0->PSR = LPTMR_PSR_PCS(3) | LPTMR_PSR_PBYP_MASK;
mbed_official 72:248c61396e08 99 return;
mbed_official 72:248c61396e08 100 } else { //See if we can divide it to 1MHz
mbed_official 72:248c61396e08 101 uint32_t divider = 0;
mbed_official 72:248c61396e08 102 extosc >>= 1;
mbed_official 72:248c61396e08 103 while (1) {
mbed_official 72:248c61396e08 104 if (extosc == 1) {
mbed_official 72:248c61396e08 105 LPTMR0->PSR = LPTMR_PSR_PCS(3) | LPTMR_PSR_PRESCALE(divider);
mbed_official 72:248c61396e08 106 return;
mbed_official 72:248c61396e08 107 }
mbed_official 72:248c61396e08 108 if (extosc % 2 != 0) //If we can't divide by two anymore
mbed_official 72:248c61396e08 109 break;
mbed_official 72:248c61396e08 110 divider++;
mbed_official 72:248c61396e08 111 extosc >>= 1;
mbed_official 72:248c61396e08 112 }
mbed_official 72:248c61396e08 113 }
mbed_official 72:248c61396e08 114 }
mbed_official 72:248c61396e08 115 }
mbed_official 363:12a245e5c745 116 #if defined(TARGET_KL43Z)
mbed_official 363:12a245e5c745 117 //No suitable actual IRC oscillator clock -> Set it to (8MHz / divider)
mbed_official 363:12a245e5c745 118 MCG->SC &= ~MCG_SC_FCRDIV_MASK;
mbed_official 363:12a245e5c745 119 MCG->MC &= ~MCG->MC & MCG_MC_LIRC_DIV2_MASK;
mbed_official 363:12a245e5c745 120 LPTMR0->PSR = LPTMR_PSR_PCS(0) | LPTMR_PSR_PRESCALE(2);
mbed_official 363:12a245e5c745 121 #else
mbed_official 74:847f030b50ee 122 //No suitable external oscillator clock -> Use fast internal oscillator (4MHz / divider)
mbed_official 72:248c61396e08 123 MCG->C1 |= MCG_C1_IRCLKEN_MASK;
mbed_official 72:248c61396e08 124 MCG->C2 |= MCG_C2_IRCS_MASK;
mbed_official 74:847f030b50ee 125 LPTMR0->PSR = LPTMR_PSR_PCS(0);
mbed_official 74:847f030b50ee 126 switch (MCG->SC & MCG_SC_FCRDIV_MASK) {
mbed_official 74:847f030b50ee 127 case MCG_SC_FCRDIV(0): //4MHz
mbed_official 74:847f030b50ee 128 LPTMR0->PSR |= LPTMR_PSR_PRESCALE(1);
mbed_official 74:847f030b50ee 129 break;
mbed_official 74:847f030b50ee 130 case MCG_SC_FCRDIV(1): //2MHz
mbed_official 74:847f030b50ee 131 LPTMR0->PSR |= LPTMR_PSR_PRESCALE(0);
mbed_official 74:847f030b50ee 132 break;
mbed_official 74:847f030b50ee 133 default: //1MHz or anything else, in which case we put it on 1MHz
mbed_official 74:847f030b50ee 134 MCG->SC &= ~MCG_SC_FCRDIV_MASK;
mbed_official 74:847f030b50ee 135 MCG->SC |= MCG_SC_FCRDIV(2);
mbed_official 74:847f030b50ee 136 LPTMR0->PSR |= LPTMR_PSR_PBYP_MASK;
mbed_official 74:847f030b50ee 137 }
mbed_official 363:12a245e5c745 138 #endif
emilmont 10:3bc89ef62ce7 139 }
emilmont 10:3bc89ef62ce7 140
emilmont 10:3bc89ef62ce7 141 void us_ticker_disable_interrupt(void) {
emilmont 10:3bc89ef62ce7 142 LPTMR0->CSR &= ~LPTMR_CSR_TIE_MASK;
emilmont 10:3bc89ef62ce7 143 }
emilmont 10:3bc89ef62ce7 144
emilmont 10:3bc89ef62ce7 145 void us_ticker_clear_interrupt(void) {
emilmont 10:3bc89ef62ce7 146 // we already clear interrupt in lptmr_isr
emilmont 10:3bc89ef62ce7 147 }
emilmont 10:3bc89ef62ce7 148
emilmont 10:3bc89ef62ce7 149 static uint32_t us_ticker_int_counter = 0;
emilmont 10:3bc89ef62ce7 150 static uint16_t us_ticker_int_remainder = 0;
emilmont 10:3bc89ef62ce7 151
emilmont 10:3bc89ef62ce7 152 static void lptmr_set(unsigned short count) {
emilmont 10:3bc89ef62ce7 153 /* Reset */
emilmont 10:3bc89ef62ce7 154 LPTMR0->CSR = 0;
emilmont 10:3bc89ef62ce7 155
emilmont 10:3bc89ef62ce7 156 /* Set the compare register */
emilmont 10:3bc89ef62ce7 157 LPTMR0->CMR = count;
emilmont 10:3bc89ef62ce7 158
emilmont 10:3bc89ef62ce7 159 /* Enable interrupt */
emilmont 10:3bc89ef62ce7 160 LPTMR0->CSR |= LPTMR_CSR_TIE_MASK;
emilmont 10:3bc89ef62ce7 161
emilmont 10:3bc89ef62ce7 162 /* Start the timer */
emilmont 10:3bc89ef62ce7 163 LPTMR0->CSR |= LPTMR_CSR_TEN_MASK;
emilmont 10:3bc89ef62ce7 164 }
emilmont 10:3bc89ef62ce7 165
emilmont 10:3bc89ef62ce7 166 static void lptmr_isr(void) {
emilmont 10:3bc89ef62ce7 167 // write 1 to TCF to clear the LPT timer compare flag
emilmont 10:3bc89ef62ce7 168 LPTMR0->CSR |= LPTMR_CSR_TCF_MASK;
emilmont 10:3bc89ef62ce7 169
emilmont 10:3bc89ef62ce7 170 if (us_ticker_int_counter > 0) {
emilmont 10:3bc89ef62ce7 171 lptmr_set(0xFFFF);
emilmont 10:3bc89ef62ce7 172 us_ticker_int_counter--;
emilmont 10:3bc89ef62ce7 173
emilmont 10:3bc89ef62ce7 174 } else {
emilmont 10:3bc89ef62ce7 175 if (us_ticker_int_remainder > 0) {
emilmont 10:3bc89ef62ce7 176 lptmr_set(us_ticker_int_remainder);
emilmont 10:3bc89ef62ce7 177 us_ticker_int_remainder = 0;
emilmont 10:3bc89ef62ce7 178
emilmont 10:3bc89ef62ce7 179 } else {
emilmont 10:3bc89ef62ce7 180 // This function is going to disable the interrupts if there are
emilmont 10:3bc89ef62ce7 181 // no other events in the queue
emilmont 10:3bc89ef62ce7 182 us_ticker_irq_handler();
emilmont 10:3bc89ef62ce7 183 }
emilmont 10:3bc89ef62ce7 184 }
emilmont 10:3bc89ef62ce7 185 }
emilmont 10:3bc89ef62ce7 186
mbed_official 304:89b9c3a9a045 187 void us_ticker_set_interrupt(timestamp_t timestamp) {
mbed_official 304:89b9c3a9a045 188 int delta = (int)((uint32_t)timestamp - us_ticker_read());
emilmont 10:3bc89ef62ce7 189 if (delta <= 0) {
emilmont 10:3bc89ef62ce7 190 // This event was in the past:
emilmont 10:3bc89ef62ce7 191 us_ticker_irq_handler();
emilmont 10:3bc89ef62ce7 192 return;
emilmont 10:3bc89ef62ce7 193 }
emilmont 10:3bc89ef62ce7 194
emilmont 10:3bc89ef62ce7 195 us_ticker_int_counter = (uint32_t)(delta >> 16);
emilmont 10:3bc89ef62ce7 196 us_ticker_int_remainder = (uint16_t)(0xFFFF & delta);
emilmont 10:3bc89ef62ce7 197 if (us_ticker_int_counter > 0) {
emilmont 10:3bc89ef62ce7 198 lptmr_set(0xFFFF);
emilmont 10:3bc89ef62ce7 199 us_ticker_int_counter--;
emilmont 10:3bc89ef62ce7 200 } else {
emilmont 10:3bc89ef62ce7 201 lptmr_set(us_ticker_int_remainder);
emilmont 10:3bc89ef62ce7 202 us_ticker_int_remainder = 0;
emilmont 10:3bc89ef62ce7 203 }
emilmont 10:3bc89ef62ce7 204 }