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 Mar 06 10:00:06 2014 +0000
Revision:
111:ae4891ca7084
Parent:
97:a69e21de83fb
Child:
304:89b9c3a9a045
Synchronized with git revision 955bd9a5c9e042f1cf30bbae2a99afaab8eb4cbf

Full URL: https://github.com/mbedmicro/mbed/commit/955bd9a5c9e042f1cf30bbae2a99afaab8eb4cbf/

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) {
emilmont 10:3bc89ef62ce7 69 /* Clock the timer */
emilmont 10:3bc89ef62ce7 70 SIM->SCGC5 |= SIM_SCGC5_LPTMR_MASK;
emilmont 10:3bc89ef62ce7 71
emilmont 10:3bc89ef62ce7 72 /* Reset */
emilmont 10:3bc89ef62ce7 73 LPTMR0->CSR = 0;
emilmont 10:3bc89ef62ce7 74
emilmont 10:3bc89ef62ce7 75 /* Set interrupt handler */
emilmont 10:3bc89ef62ce7 76 NVIC_SetVector(LPTimer_IRQn, (uint32_t)lptmr_isr);
emilmont 10:3bc89ef62ce7 77 NVIC_EnableIRQ(LPTimer_IRQn);
emilmont 10:3bc89ef62ce7 78
emilmont 10:3bc89ef62ce7 79 /* Clock at (1)MHz -> (1)tick/us */
mbed_official 72:248c61396e08 80 /* Check if the external oscillator can be divided to 1MHz */
mbed_official 72:248c61396e08 81 uint32_t extosc = extosc_frequency();
mbed_official 72:248c61396e08 82
mbed_official 72:248c61396e08 83 if (extosc != 0) { //If external oscillator found
mbed_official 72:248c61396e08 84 if (extosc % 1000000u == 0) { //If it is a multiple if 1MHz
mbed_official 72:248c61396e08 85 extosc /= 1000000;
mbed_official 72:248c61396e08 86 if (extosc == 1) { //1MHz, set timerprescaler in bypass mode
mbed_official 72:248c61396e08 87 LPTMR0->PSR = LPTMR_PSR_PCS(3) | LPTMR_PSR_PBYP_MASK;
mbed_official 72:248c61396e08 88 return;
mbed_official 72:248c61396e08 89 } else { //See if we can divide it to 1MHz
mbed_official 72:248c61396e08 90 uint32_t divider = 0;
mbed_official 72:248c61396e08 91 extosc >>= 1;
mbed_official 72:248c61396e08 92 while (1) {
mbed_official 72:248c61396e08 93 if (extosc == 1) {
mbed_official 72:248c61396e08 94 LPTMR0->PSR = LPTMR_PSR_PCS(3) | LPTMR_PSR_PRESCALE(divider);
mbed_official 72:248c61396e08 95 return;
mbed_official 72:248c61396e08 96 }
mbed_official 72:248c61396e08 97 if (extosc % 2 != 0) //If we can't divide by two anymore
mbed_official 72:248c61396e08 98 break;
mbed_official 72:248c61396e08 99 divider++;
mbed_official 72:248c61396e08 100 extosc >>= 1;
mbed_official 72:248c61396e08 101 }
mbed_official 72:248c61396e08 102 }
mbed_official 72:248c61396e08 103 }
mbed_official 72:248c61396e08 104 }
mbed_official 74:847f030b50ee 105 //No suitable external oscillator clock -> Use fast internal oscillator (4MHz / divider)
mbed_official 72:248c61396e08 106 MCG->C1 |= MCG_C1_IRCLKEN_MASK;
mbed_official 72:248c61396e08 107 MCG->C2 |= MCG_C2_IRCS_MASK;
mbed_official 74:847f030b50ee 108 LPTMR0->PSR = LPTMR_PSR_PCS(0);
mbed_official 74:847f030b50ee 109 switch (MCG->SC & MCG_SC_FCRDIV_MASK) {
mbed_official 74:847f030b50ee 110 case MCG_SC_FCRDIV(0): //4MHz
mbed_official 74:847f030b50ee 111 LPTMR0->PSR |= LPTMR_PSR_PRESCALE(1);
mbed_official 74:847f030b50ee 112 break;
mbed_official 74:847f030b50ee 113 case MCG_SC_FCRDIV(1): //2MHz
mbed_official 74:847f030b50ee 114 LPTMR0->PSR |= LPTMR_PSR_PRESCALE(0);
mbed_official 74:847f030b50ee 115 break;
mbed_official 74:847f030b50ee 116 default: //1MHz or anything else, in which case we put it on 1MHz
mbed_official 74:847f030b50ee 117 MCG->SC &= ~MCG_SC_FCRDIV_MASK;
mbed_official 74:847f030b50ee 118 MCG->SC |= MCG_SC_FCRDIV(2);
mbed_official 74:847f030b50ee 119 LPTMR0->PSR |= LPTMR_PSR_PBYP_MASK;
mbed_official 74:847f030b50ee 120 }
mbed_official 72:248c61396e08 121
emilmont 10:3bc89ef62ce7 122 }
emilmont 10:3bc89ef62ce7 123
emilmont 10:3bc89ef62ce7 124 void us_ticker_disable_interrupt(void) {
emilmont 10:3bc89ef62ce7 125 LPTMR0->CSR &= ~LPTMR_CSR_TIE_MASK;
emilmont 10:3bc89ef62ce7 126 }
emilmont 10:3bc89ef62ce7 127
emilmont 10:3bc89ef62ce7 128 void us_ticker_clear_interrupt(void) {
emilmont 10:3bc89ef62ce7 129 // we already clear interrupt in lptmr_isr
emilmont 10:3bc89ef62ce7 130 }
emilmont 10:3bc89ef62ce7 131
emilmont 10:3bc89ef62ce7 132 static uint32_t us_ticker_int_counter = 0;
emilmont 10:3bc89ef62ce7 133 static uint16_t us_ticker_int_remainder = 0;
emilmont 10:3bc89ef62ce7 134
emilmont 10:3bc89ef62ce7 135 static void lptmr_set(unsigned short count) {
emilmont 10:3bc89ef62ce7 136 /* Reset */
emilmont 10:3bc89ef62ce7 137 LPTMR0->CSR = 0;
emilmont 10:3bc89ef62ce7 138
emilmont 10:3bc89ef62ce7 139 /* Set the compare register */
emilmont 10:3bc89ef62ce7 140 LPTMR0->CMR = count;
emilmont 10:3bc89ef62ce7 141
emilmont 10:3bc89ef62ce7 142 /* Enable interrupt */
emilmont 10:3bc89ef62ce7 143 LPTMR0->CSR |= LPTMR_CSR_TIE_MASK;
emilmont 10:3bc89ef62ce7 144
emilmont 10:3bc89ef62ce7 145 /* Start the timer */
emilmont 10:3bc89ef62ce7 146 LPTMR0->CSR |= LPTMR_CSR_TEN_MASK;
emilmont 10:3bc89ef62ce7 147 }
emilmont 10:3bc89ef62ce7 148
emilmont 10:3bc89ef62ce7 149 static void lptmr_isr(void) {
emilmont 10:3bc89ef62ce7 150 // write 1 to TCF to clear the LPT timer compare flag
emilmont 10:3bc89ef62ce7 151 LPTMR0->CSR |= LPTMR_CSR_TCF_MASK;
emilmont 10:3bc89ef62ce7 152
emilmont 10:3bc89ef62ce7 153 if (us_ticker_int_counter > 0) {
emilmont 10:3bc89ef62ce7 154 lptmr_set(0xFFFF);
emilmont 10:3bc89ef62ce7 155 us_ticker_int_counter--;
emilmont 10:3bc89ef62ce7 156
emilmont 10:3bc89ef62ce7 157 } else {
emilmont 10:3bc89ef62ce7 158 if (us_ticker_int_remainder > 0) {
emilmont 10:3bc89ef62ce7 159 lptmr_set(us_ticker_int_remainder);
emilmont 10:3bc89ef62ce7 160 us_ticker_int_remainder = 0;
emilmont 10:3bc89ef62ce7 161
emilmont 10:3bc89ef62ce7 162 } else {
emilmont 10:3bc89ef62ce7 163 // This function is going to disable the interrupts if there are
emilmont 10:3bc89ef62ce7 164 // no other events in the queue
emilmont 10:3bc89ef62ce7 165 us_ticker_irq_handler();
emilmont 10:3bc89ef62ce7 166 }
emilmont 10:3bc89ef62ce7 167 }
emilmont 10:3bc89ef62ce7 168 }
emilmont 10:3bc89ef62ce7 169
emilmont 10:3bc89ef62ce7 170 void us_ticker_set_interrupt(unsigned int timestamp) {
emilmont 10:3bc89ef62ce7 171 int delta = (int)(timestamp - us_ticker_read());
emilmont 10:3bc89ef62ce7 172 if (delta <= 0) {
emilmont 10:3bc89ef62ce7 173 // This event was in the past:
emilmont 10:3bc89ef62ce7 174 us_ticker_irq_handler();
emilmont 10:3bc89ef62ce7 175 return;
emilmont 10:3bc89ef62ce7 176 }
emilmont 10:3bc89ef62ce7 177
emilmont 10:3bc89ef62ce7 178 us_ticker_int_counter = (uint32_t)(delta >> 16);
emilmont 10:3bc89ef62ce7 179 us_ticker_int_remainder = (uint16_t)(0xFFFF & delta);
emilmont 10:3bc89ef62ce7 180 if (us_ticker_int_counter > 0) {
emilmont 10:3bc89ef62ce7 181 lptmr_set(0xFFFF);
emilmont 10:3bc89ef62ce7 182 us_ticker_int_counter--;
emilmont 10:3bc89ef62ce7 183 } else {
emilmont 10:3bc89ef62ce7 184 lptmr_set(us_ticker_int_remainder);
emilmont 10:3bc89ef62ce7 185 us_ticker_int_remainder = 0;
emilmont 10:3bc89ef62ce7 186 }
emilmont 10:3bc89ef62ce7 187 }