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 May 07 09:00:08 2015 +0100
Revision:
536:c48d7048ab6e
Parent:
515:7467ef1f4ad8
Synchronized with git revision a1e04f782bf013aeb4122c3ec408e3b011de60ed

Full URL: https://github.com/mbedmicro/mbed/commit/a1e04f782bf013aeb4122c3ec408e3b011de60ed/

MAX32600MBED,MAXWSNENV - Add low-power ticker.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mbed_official 507:d4fc7603a669 1 /*******************************************************************************
mbed_official 507:d4fc7603a669 2 * Copyright (C) 2015 Maxim Integrated Products, Inc., All Rights Reserved.
mbed_official 507:d4fc7603a669 3 *
mbed_official 507:d4fc7603a669 4 * Permission is hereby granted, free of charge, to any person obtaining a
mbed_official 507:d4fc7603a669 5 * copy of this software and associated documentation files (the "Software"),
mbed_official 507:d4fc7603a669 6 * to deal in the Software without restriction, including without limitation
mbed_official 507:d4fc7603a669 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
mbed_official 507:d4fc7603a669 8 * and/or sell copies of the Software, and to permit persons to whom the
mbed_official 507:d4fc7603a669 9 * Software is furnished to do so, subject to the following conditions:
mbed_official 507:d4fc7603a669 10 *
mbed_official 507:d4fc7603a669 11 * The above copyright notice and this permission notice shall be included
mbed_official 507:d4fc7603a669 12 * in all copies or substantial portions of the Software.
mbed_official 507:d4fc7603a669 13 *
mbed_official 507:d4fc7603a669 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
mbed_official 507:d4fc7603a669 15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
mbed_official 507:d4fc7603a669 16 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
mbed_official 507:d4fc7603a669 17 * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
mbed_official 507:d4fc7603a669 18 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
mbed_official 507:d4fc7603a669 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
mbed_official 507:d4fc7603a669 20 * OTHER DEALINGS IN THE SOFTWARE.
mbed_official 507:d4fc7603a669 21 *
mbed_official 507:d4fc7603a669 22 * Except as contained in this notice, the name of Maxim Integrated
mbed_official 507:d4fc7603a669 23 * Products, Inc. shall not be used except as stated in the Maxim Integrated
mbed_official 507:d4fc7603a669 24 * Products, Inc. Branding Policy.
mbed_official 507:d4fc7603a669 25 *
mbed_official 507:d4fc7603a669 26 * The mere transfer of this software does not imply any licenses
mbed_official 507:d4fc7603a669 27 * of trade secrets, proprietary technology, copyrights, patents,
mbed_official 507:d4fc7603a669 28 * trademarks, maskwork rights, or any other form of intellectual
mbed_official 507:d4fc7603a669 29 * property whatsoever. Maxim Integrated Products, Inc. retains all
mbed_official 507:d4fc7603a669 30 * ownership rights.
mbed_official 507:d4fc7603a669 31 *******************************************************************************
mbed_official 507:d4fc7603a669 32 */
mbed_official 536:c48d7048ab6e 33
mbed_official 507:d4fc7603a669 34 #include "mbed_error.h"
mbed_official 507:d4fc7603a669 35 #include "us_ticker_api.h"
mbed_official 507:d4fc7603a669 36 #include "PeripheralNames.h"
mbed_official 507:d4fc7603a669 37 #include "tmr_regs.h"
mbed_official 507:d4fc7603a669 38
mbed_official 507:d4fc7603a669 39 #define US_TIMER MXC_TMR0
mbed_official 507:d4fc7603a669 40 #define US_TIMER_IRQn TMR0_IRQn
mbed_official 507:d4fc7603a669 41
mbed_official 507:d4fc7603a669 42 static int us_ticker_inited = 0;
mbed_official 507:d4fc7603a669 43 static uint32_t ticks_per_us;
mbed_official 507:d4fc7603a669 44 static uint32_t tick_win;
mbed_official 507:d4fc7603a669 45 static volatile uint64_t current_cnt; // Hold the current ticks
mbed_official 507:d4fc7603a669 46 static volatile uint64_t event_cnt; // Holds the value of the next event
mbed_official 507:d4fc7603a669 47
mbed_official 507:d4fc7603a669 48 #define ticks_to_us(ticks) ((ticks) / ticks_per_us);
mbed_official 507:d4fc7603a669 49 #define MAX_TICK_VAL ((uint64_t)0xFFFFFFFF * ticks_per_us)
mbed_official 507:d4fc7603a669 50
mbed_official 507:d4fc7603a669 51 //******************************************************************************
mbed_official 507:d4fc7603a669 52 static inline void inc_current_cnt(uint32_t inc) {
mbed_official 507:d4fc7603a669 53
mbed_official 507:d4fc7603a669 54 // Overflow the ticker when the us ticker overflows
mbed_official 507:d4fc7603a669 55 current_cnt += inc;
mbed_official 536:c48d7048ab6e 56 if (current_cnt > MAX_TICK_VAL) {
mbed_official 507:d4fc7603a669 57 current_cnt -= (MAX_TICK_VAL + 1);
mbed_official 507:d4fc7603a669 58 }
mbed_official 507:d4fc7603a669 59 }
mbed_official 507:d4fc7603a669 60
mbed_official 507:d4fc7603a669 61 //******************************************************************************
mbed_official 507:d4fc7603a669 62 static inline int event_passed(uint64_t current, uint64_t event) {
mbed_official 507:d4fc7603a669 63
mbed_official 507:d4fc7603a669 64 // Determine if the event has already happened.
mbed_official 507:d4fc7603a669 65 // If the event is behind the current ticker, within a window,
mbed_official 507:d4fc7603a669 66 // then the event has already happened.
mbed_official 536:c48d7048ab6e 67 if (((current < tick_win) && ((event < current) ||
mbed_official 507:d4fc7603a669 68 (event > (MAX_TICK_VAL - (tick_win - current))))) ||
mbed_official 507:d4fc7603a669 69 ((event < current) && (event > (current - tick_win)))) {
mbed_official 507:d4fc7603a669 70 return 1;
mbed_official 507:d4fc7603a669 71 }
mbed_official 507:d4fc7603a669 72
mbed_official 507:d4fc7603a669 73 return 0;
mbed_official 507:d4fc7603a669 74 }
mbed_official 507:d4fc7603a669 75
mbed_official 507:d4fc7603a669 76 //******************************************************************************
mbed_official 507:d4fc7603a669 77 static inline uint64_t event_diff(uint64_t current, uint64_t event) {
mbed_official 507:d4fc7603a669 78
mbed_official 507:d4fc7603a669 79 // Check to see if the ticker will overflow before the event
mbed_official 507:d4fc7603a669 80 if(current <= event) {
mbed_official 507:d4fc7603a669 81 return (event - current);
mbed_official 507:d4fc7603a669 82 }
mbed_official 507:d4fc7603a669 83
mbed_official 507:d4fc7603a669 84 return ((MAX_TICK_VAL - current) + event);
mbed_official 507:d4fc7603a669 85 }
mbed_official 507:d4fc7603a669 86
mbed_official 507:d4fc7603a669 87 //******************************************************************************
mbed_official 507:d4fc7603a669 88 static void tmr_handler(void)
mbed_official 507:d4fc7603a669 89 {
mbed_official 507:d4fc7603a669 90 uint32_t term_cnt32 = US_TIMER->term_cnt32;
mbed_official 507:d4fc7603a669 91 US_TIMER->term_cnt32 = 0xFFFFFFFF; // reset to max value to prevent further interrupts
mbed_official 507:d4fc7603a669 92 US_TIMER->intfl = (MXC_F_TMR_INTFL_TIMER0 | MXC_F_TMR_INTFL_TIMER1); // clear interrupt
mbed_official 507:d4fc7603a669 93 NVIC_ClearPendingIRQ(US_TIMER_IRQn);
mbed_official 507:d4fc7603a669 94
mbed_official 507:d4fc7603a669 95 inc_current_cnt(term_cnt32);
mbed_official 507:d4fc7603a669 96
mbed_official 507:d4fc7603a669 97 if (event_passed(current_cnt + US_TIMER->count32, event_cnt )) {
mbed_official 507:d4fc7603a669 98 // the timestamp has expired
mbed_official 515:7467ef1f4ad8 99 event_cnt = 0xFFFFFFFFFFFFFFFFULL; // reset to max value
mbed_official 507:d4fc7603a669 100 us_ticker_irq_handler();
mbed_official 507:d4fc7603a669 101 } else {
mbed_official 507:d4fc7603a669 102
mbed_official 507:d4fc7603a669 103 uint64_t diff = event_diff(current_cnt, event_cnt);
mbed_official 507:d4fc7603a669 104 if (diff < (uint64_t)0xFFFFFFFF) {
mbed_official 507:d4fc7603a669 105 // the event occurs before the next overflow
mbed_official 507:d4fc7603a669 106 US_TIMER->term_cnt32 = diff;
mbed_official 507:d4fc7603a669 107
mbed_official 507:d4fc7603a669 108 // Since the timer keeps counting after the terminal value is reached, it is possible that the new
mbed_official 507:d4fc7603a669 109 // terminal value is in the past.
mbed_official 507:d4fc7603a669 110 if (US_TIMER->term_cnt32 < US_TIMER->count32) {
mbed_official 507:d4fc7603a669 111 // the timestamp has expired
mbed_official 507:d4fc7603a669 112 US_TIMER->term_cnt32 = 0xFFFFFFFF; // reset to max value to prevent further interrupts
mbed_official 507:d4fc7603a669 113 US_TIMER->intfl = (MXC_F_TMR_INTFL_TIMER0 | MXC_F_TMR_INTFL_TIMER1); // clear interrupt
mbed_official 507:d4fc7603a669 114 NVIC_ClearPendingIRQ(US_TIMER_IRQn);
mbed_official 515:7467ef1f4ad8 115 event_cnt = 0xFFFFFFFFFFFFFFFFULL; // reset to max value
mbed_official 507:d4fc7603a669 116 us_ticker_irq_handler();
mbed_official 507:d4fc7603a669 117 }
mbed_official 507:d4fc7603a669 118 }
mbed_official 507:d4fc7603a669 119 }
mbed_official 507:d4fc7603a669 120 }
mbed_official 507:d4fc7603a669 121
mbed_official 507:d4fc7603a669 122 //******************************************************************************
mbed_official 507:d4fc7603a669 123 void us_ticker_init(void)
mbed_official 507:d4fc7603a669 124 {
mbed_official 507:d4fc7603a669 125 if (us_ticker_inited)
mbed_official 507:d4fc7603a669 126 return;
mbed_official 507:d4fc7603a669 127 us_ticker_inited = 1;
mbed_official 507:d4fc7603a669 128
mbed_official 507:d4fc7603a669 129 current_cnt = 0;
mbed_official 515:7467ef1f4ad8 130 event_cnt = 0xFFFFFFFFFFFFFFFFULL; // reset to max value
mbed_official 507:d4fc7603a669 131
mbed_official 507:d4fc7603a669 132 if (SystemCoreClock <= 1000000) {
mbed_official 507:d4fc7603a669 133 error("us_ticker cannot operate at this SystemCoreClock");
mbed_official 507:d4fc7603a669 134 return;
mbed_official 507:d4fc7603a669 135 }
mbed_official 507:d4fc7603a669 136
mbed_official 507:d4fc7603a669 137 // Configure timer for 32-bit continuous mode with /1 prescaler
mbed_official 507:d4fc7603a669 138 US_TIMER->ctrl = MXC_E_TMR_MODE_CONTINUOUS << MXC_F_TMR_CTRL_MODE_POS | (0 << MXC_F_TMR_CTRL_PRESCALE_POS);
mbed_official 507:d4fc7603a669 139 ticks_per_us = SystemCoreClock / 1000000;
mbed_official 507:d4fc7603a669 140
mbed_official 507:d4fc7603a669 141 // Set the tick window to 10ms
mbed_official 507:d4fc7603a669 142 tick_win = SystemCoreClock/100;
mbed_official 507:d4fc7603a669 143
mbed_official 507:d4fc7603a669 144 // Set timer overflow to the max
mbed_official 507:d4fc7603a669 145 US_TIMER->term_cnt32 = 0xFFFFFFFF;
mbed_official 507:d4fc7603a669 146 US_TIMER->pwm_cap32 = 0xFFFFFFFF;
mbed_official 507:d4fc7603a669 147 US_TIMER->count32 = 0;
mbed_official 507:d4fc7603a669 148
mbed_official 507:d4fc7603a669 149 US_TIMER->intfl = (MXC_F_TMR_INTFL_TIMER0 | MXC_F_TMR_INTFL_TIMER1); // clear pending interrupts
mbed_official 507:d4fc7603a669 150
mbed_official 507:d4fc7603a669 151 NVIC_SetVector(US_TIMER_IRQn, (uint32_t)tmr_handler);
mbed_official 507:d4fc7603a669 152 NVIC_EnableIRQ(US_TIMER_IRQn);
mbed_official 507:d4fc7603a669 153
mbed_official 507:d4fc7603a669 154 US_TIMER->inten |= MXC_F_TMR_INTEN_TIMER0; // enable interrupts
mbed_official 507:d4fc7603a669 155 US_TIMER->ctrl |= MXC_F_TMR_CTRL_ENABLE0; // enable timer
mbed_official 507:d4fc7603a669 156 }
mbed_official 507:d4fc7603a669 157
mbed_official 507:d4fc7603a669 158 //******************************************************************************
mbed_official 507:d4fc7603a669 159 void us_ticker_deinit(void)
mbed_official 507:d4fc7603a669 160 {
mbed_official 507:d4fc7603a669 161 US_TIMER->ctrl = 0; // disable timer
mbed_official 507:d4fc7603a669 162 US_TIMER->inten = 0; // disable interrupts
mbed_official 507:d4fc7603a669 163 US_TIMER->intfl = (MXC_F_TMR_INTFL_TIMER0 | MXC_F_TMR_INTFL_TIMER1); // clear interrupts
mbed_official 507:d4fc7603a669 164 us_ticker_inited = 0;
mbed_official 507:d4fc7603a669 165 }
mbed_official 507:d4fc7603a669 166
mbed_official 507:d4fc7603a669 167 //******************************************************************************
mbed_official 507:d4fc7603a669 168 uint32_t us_ticker_read(void)
mbed_official 507:d4fc7603a669 169 {
mbed_official 507:d4fc7603a669 170 uint64_t current_cnt1, current_cnt2;
mbed_official 507:d4fc7603a669 171 uint32_t term_cnt, tmr_cnt;
mbed_official 536:c48d7048ab6e 172 uint32_t intfl1, intfl2;
mbed_official 507:d4fc7603a669 173
mbed_official 507:d4fc7603a669 174 if (!us_ticker_inited)
mbed_official 507:d4fc7603a669 175 us_ticker_init();
mbed_official 507:d4fc7603a669 176
mbed_official 507:d4fc7603a669 177 // Ensure coherency between current_cnt and US_TIMER->count32
mbed_official 507:d4fc7603a669 178 do {
mbed_official 507:d4fc7603a669 179 current_cnt1 = current_cnt;
mbed_official 507:d4fc7603a669 180 intfl1 = US_TIMER->intfl;
mbed_official 507:d4fc7603a669 181 term_cnt = US_TIMER->term_cnt32;
mbed_official 507:d4fc7603a669 182 tmr_cnt = US_TIMER->count32;
mbed_official 507:d4fc7603a669 183 intfl2 = US_TIMER->intfl;
mbed_official 507:d4fc7603a669 184 current_cnt2 = current_cnt;
mbed_official 507:d4fc7603a669 185 } while ((current_cnt1 != current_cnt2) || (intfl1 != intfl2));
mbed_official 507:d4fc7603a669 186
mbed_official 536:c48d7048ab6e 187 // Account for an unserviced interrupt
mbed_official 507:d4fc7603a669 188 if (intfl1) {
mbed_official 507:d4fc7603a669 189 current_cnt1 += term_cnt;
mbed_official 507:d4fc7603a669 190 }
mbed_official 507:d4fc7603a669 191
mbed_official 507:d4fc7603a669 192 current_cnt1 += tmr_cnt;
mbed_official 507:d4fc7603a669 193
mbed_official 507:d4fc7603a669 194 return (current_cnt1 / ticks_per_us);
mbed_official 507:d4fc7603a669 195 }
mbed_official 507:d4fc7603a669 196
mbed_official 507:d4fc7603a669 197 //******************************************************************************
mbed_official 507:d4fc7603a669 198 void us_ticker_set_interrupt(timestamp_t timestamp)
mbed_official 507:d4fc7603a669 199 {
mbed_official 507:d4fc7603a669 200 // Note: interrupts are disabled before this function is called.
mbed_official 536:c48d7048ab6e 201
mbed_official 507:d4fc7603a669 202 US_TIMER->ctrl &= ~MXC_F_TMR_CTRL_ENABLE0; // disable timer
mbed_official 507:d4fc7603a669 203
mbed_official 507:d4fc7603a669 204 if (US_TIMER->intfl) {
mbed_official 507:d4fc7603a669 205 US_TIMER->intfl = (MXC_F_TMR_INTFL_TIMER0 | MXC_F_TMR_INTFL_TIMER1); // clear interrupt
mbed_official 507:d4fc7603a669 206 NVIC_ClearPendingIRQ(US_TIMER_IRQn);
mbed_official 507:d4fc7603a669 207 inc_current_cnt(US_TIMER->term_cnt32);
mbed_official 507:d4fc7603a669 208 }
mbed_official 507:d4fc7603a669 209
mbed_official 507:d4fc7603a669 210 // add and reset the current count value
mbed_official 507:d4fc7603a669 211 inc_current_cnt(US_TIMER->count32);
mbed_official 507:d4fc7603a669 212 US_TIMER->count32 = 0;
mbed_official 507:d4fc7603a669 213
mbed_official 507:d4fc7603a669 214 // add the number of cycles that the timer is disabled here for
mbed_official 507:d4fc7603a669 215 inc_current_cnt(200);
mbed_official 507:d4fc7603a669 216
mbed_official 507:d4fc7603a669 217 event_cnt = (uint64_t)timestamp * ticks_per_us;
mbed_official 507:d4fc7603a669 218
mbed_official 507:d4fc7603a669 219 // Check to see if the event has already passed
mbed_official 507:d4fc7603a669 220 if (!event_passed(current_cnt, event_cnt)) {
mbed_official 507:d4fc7603a669 221 uint64_t diff = event_diff(current_cnt, event_cnt);
mbed_official 507:d4fc7603a669 222 if (diff < (uint64_t)0xFFFFFFFF) {
mbed_official 507:d4fc7603a669 223 // the event occurs before the next overflow
mbed_official 507:d4fc7603a669 224 US_TIMER->term_cnt32 = diff;
mbed_official 507:d4fc7603a669 225 } else {
mbed_official 507:d4fc7603a669 226 // the event occurs after the next overflow
mbed_official 507:d4fc7603a669 227 US_TIMER->term_cnt32 = 0xFFFFFFFF; // set to max
mbed_official 507:d4fc7603a669 228 }
mbed_official 507:d4fc7603a669 229 } else {
mbed_official 507:d4fc7603a669 230 // the requested timestamp occurs in the past
mbed_official 507:d4fc7603a669 231 // set the timer up to immediately expire
mbed_official 507:d4fc7603a669 232 US_TIMER->term_cnt32 = 1;
mbed_official 507:d4fc7603a669 233 }
mbed_official 507:d4fc7603a669 234 US_TIMER->ctrl |= MXC_F_TMR_CTRL_ENABLE0; // enable timer
mbed_official 507:d4fc7603a669 235 }
mbed_official 507:d4fc7603a669 236
mbed_official 507:d4fc7603a669 237 //******************************************************************************
mbed_official 507:d4fc7603a669 238 void us_ticker_disable_interrupt(void)
mbed_official 507:d4fc7603a669 239 {
mbed_official 507:d4fc7603a669 240 // There are no more events, set timer overflow to the max
mbed_official 507:d4fc7603a669 241 US_TIMER->term_cnt32 = 0xFFFFFFFF;
mbed_official 507:d4fc7603a669 242 }
mbed_official 507:d4fc7603a669 243
mbed_official 507:d4fc7603a669 244 //******************************************************************************
mbed_official 507:d4fc7603a669 245 void us_ticker_clear_interrupt(void)
mbed_official 507:d4fc7603a669 246 {
mbed_official 507:d4fc7603a669 247 // cleared in the local handler
mbed_official 507:d4fc7603a669 248 }
mbed_official 507:d4fc7603a669 249
mbed_official 507:d4fc7603a669 250 //******************************************************************************
mbed_official 507:d4fc7603a669 251 void us_ticker_set(timestamp_t timestamp)
mbed_official 507:d4fc7603a669 252 {
mbed_official 507:d4fc7603a669 253 US_TIMER->ctrl &= ~MXC_F_TMR_CTRL_ENABLE0; // disable timer
mbed_official 507:d4fc7603a669 254 current_cnt = (uint64_t)timestamp * ticks_per_us;
mbed_official 507:d4fc7603a669 255 US_TIMER->count32 = 0;
mbed_official 507:d4fc7603a669 256 US_TIMER->term_cnt32 = 0xFFFFFFFF;
mbed_official 507:d4fc7603a669 257 US_TIMER->ctrl |= MXC_F_TMR_CTRL_ENABLE0; // enable timer
mbed_official 507:d4fc7603a669 258
mbed_official 507:d4fc7603a669 259 if (((uint64_t)timestamp * ticks_per_us) >= event_cnt) {
mbed_official 507:d4fc7603a669 260 // The next timestamp has elapsed. Trigger the interrupt to handle it.
mbed_official 507:d4fc7603a669 261 NVIC_SetPendingIRQ(US_TIMER_IRQn);
mbed_official 507:d4fc7603a669 262 }
mbed_official 507:d4fc7603a669 263 }