Solution for Bluetooth SIG hands-on training course
Dependencies: BLE_API mbed-dev-bin nRF51822-bluetooth-mdw
Fork of microbit-dal-bluetooth-mdw_starter by
MicroBitSystemTimer.cpp
00001 /* 00002 The MIT License (MIT) 00003 00004 Copyright (c) 2016 British Broadcasting Corporation. 00005 This software is provided by Lancaster University by arrangement with the BBC. 00006 00007 Permission is hereby granted, free of charge, to any person obtaining a 00008 copy of this software and associated documentation files (the "Software"), 00009 to deal in the Software without restriction, including without limitation 00010 the rights to use, copy, modify, merge, publish, distribute, sublicense, 00011 and/or sell copies of the Software, and to permit persons to whom the 00012 Software is furnished to do so, subject to the following conditions: 00013 00014 The above copyright notice and this permission notice shall be included in 00015 all copies or substantial portions of the Software. 00016 00017 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00018 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00019 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 00020 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00021 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 00022 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 00023 DEALINGS IN THE SOFTWARE. 00024 */ 00025 00026 /** 00027 * Definitions for the MicroBit system timer. 00028 * 00029 * This module provides: 00030 * 00031 * 1) a concept of global system time since power up 00032 * 2) a simple periodic multiplexing API for the underlying mbed implementation. 00033 * 00034 * The latter is useful to avoid costs associated with multiple mbed Ticker instances 00035 * in microbit-dal components, as each incurs a significant additional RAM overhead (circa 80 bytes). 00036 */ 00037 #include "MicroBitConfig.h" 00038 #include "MicroBitSystemTimer.h" 00039 #include "ErrorNo.h" 00040 00041 /* 00042 * Time since power on. Measured in milliseconds. 00043 * When stored as an unsigned long, this gives us approx 50 days between rollover, which is ample. :-) 00044 */ 00045 static uint64_t time_us = 0; 00046 static unsigned int tick_period = 0; 00047 00048 // Array of components which are iterated during a system tick 00049 static MicroBitComponent* systemTickComponents[MICROBIT_SYSTEM_COMPONENTS]; 00050 00051 // Periodic callback interrupt 00052 static Ticker *ticker = NULL; 00053 00054 // System timer. 00055 static Timer *timer = NULL; 00056 00057 00058 /** 00059 * Initialises a system wide timer, used to drive the various components used in the runtime. 00060 * 00061 * This must be called before any components register to receive periodic periodic callbacks. 00062 * 00063 * @param timer_period The initial period between interrupts, in millseconds. 00064 * 00065 * @return MICROBIT_OK on success. 00066 */ 00067 int system_timer_init(int period) 00068 { 00069 if (ticker == NULL) 00070 ticker = new Ticker(); 00071 00072 if (timer == NULL) 00073 { 00074 timer = new Timer(); 00075 timer->start(); 00076 } 00077 00078 return system_timer_set_period(period); 00079 } 00080 00081 /** 00082 * Reconfigures the system wide timer to the given period in milliseconds. 00083 * 00084 * @param period the new period of the timer in milliseconds 00085 * 00086 * @return MICROBIT_OK on success. MICROBIT_INVALID_PARAMETER is returned if period < 1 00087 */ 00088 int system_timer_set_period(int period) 00089 { 00090 if (period < 1) 00091 return MICROBIT_INVALID_PARAMETER; 00092 00093 // If a timer is already running, ensure it is disabled before reconfiguring. 00094 if (tick_period) 00095 ticker->detach(); 00096 00097 // register a period callback to drive the scheduler and any other registered components. 00098 tick_period = period; 00099 ticker->attach_us(system_timer_tick, period * 1000); 00100 00101 return MICROBIT_OK; 00102 } 00103 00104 /** 00105 * Accessor to obtain the current tick period in milliseconds 00106 * 00107 * @return the current tick period in milliseconds 00108 */ 00109 int system_timer_get_period() 00110 { 00111 return tick_period; 00112 } 00113 00114 /** 00115 * Updates the current time in microseconds, since power on. 00116 * 00117 * If the mbed Timer hasn't been initialised, it will be initialised 00118 * on the first call to this function. 00119 */ 00120 void update_time() 00121 { 00122 // If we haven't been initialized, bring up the timer with the default period. 00123 if (timer == NULL || ticker == NULL) 00124 system_timer_init(SYSTEM_TICK_PERIOD_MS); 00125 00126 time_us += timer->read_us(); 00127 timer->reset(); 00128 } 00129 00130 /** 00131 * Determines the time since the device was powered on. 00132 * 00133 * @return the current time since power on in milliseconds 00134 */ 00135 uint64_t system_timer_current_time() 00136 { 00137 return system_timer_current_time_us() / 1000; 00138 } 00139 00140 /** 00141 * Determines the time since the device was powered on. 00142 * 00143 * @return the current time since power on in microseconds 00144 */ 00145 uint64_t system_timer_current_time_us() 00146 { 00147 update_time(); 00148 return time_us; 00149 } 00150 00151 /** 00152 * Timer callback. Called from interrupt context, once per period. 00153 * 00154 * Simply checks to determine if any fibers blocked on the sleep queue need to be woken up 00155 * and made runnable. 00156 */ 00157 void system_timer_tick() 00158 { 00159 update_time(); 00160 00161 // Update any components registered for a callback 00162 for(int i = 0; i < MICROBIT_SYSTEM_COMPONENTS; i++) 00163 if(systemTickComponents[i] != NULL) 00164 systemTickComponents[i]->systemTick(); 00165 } 00166 00167 /** 00168 * Add a component to the array of system components. This component will then receive 00169 * periodic callbacks, once every tick period. 00170 * 00171 * @param component The component to add. 00172 * 00173 * @return MICROBIT_OK on success. MICROBIT_NO_RESOURCES is returned if the component array is full. 00174 * 00175 * @note The callback will be in interrupt context. 00176 */ 00177 int system_timer_add_component(MicroBitComponent *component) 00178 { 00179 int i = 0; 00180 00181 // If we haven't been initialized, bring up the timer with the default period. 00182 if (timer == NULL || ticker == NULL) 00183 system_timer_init(SYSTEM_TICK_PERIOD_MS); 00184 00185 while(systemTickComponents[i] != NULL && i < MICROBIT_SYSTEM_COMPONENTS) 00186 i++; 00187 00188 if(i == MICROBIT_SYSTEM_COMPONENTS) 00189 return MICROBIT_NO_RESOURCES; 00190 00191 systemTickComponents[i] = component; 00192 return MICROBIT_OK; 00193 } 00194 00195 /** 00196 * Remove a component from the array of system components. This component will no longer receive 00197 * periodic callbacks. 00198 * 00199 * @param component The component to remove. 00200 * 00201 * @return MICROBIT_OK on success. MICROBIT_INVALID_PARAMETER is returned if the given component has not been previously added. 00202 */ 00203 int system_timer_remove_component(MicroBitComponent *component) 00204 { 00205 int i = 0; 00206 00207 while(systemTickComponents[i] != component && i < MICROBIT_SYSTEM_COMPONENTS) 00208 i++; 00209 00210 if(i == MICROBIT_SYSTEM_COMPONENTS) 00211 return MICROBIT_INVALID_PARAMETER; 00212 00213 systemTickComponents[i] = NULL; 00214 00215 return MICROBIT_OK; 00216 }
Generated on Tue Jul 12 2022 20:39:13 by 1.7.2