Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
mbed_sleep_manager.c
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2017 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 #include "platform/mbed_assert.h" 00018 #include "platform/mbed_power_mgmt.h" 00019 #include "platform/mbed_critical.h" 00020 #include "sleep_api.h" 00021 #include "platform/mbed_error.h" 00022 #include "platform/mbed_debug.h" 00023 #include "platform/mbed_stats.h" 00024 #include "us_ticker_api.h" 00025 #include "lp_ticker_api.h" 00026 #include <limits.h> 00027 #include <stdio.h> 00028 #include "platform/mbed_stats.h" 00029 00030 00031 #if DEVICE_SLEEP 00032 00033 // deep sleep locking counter. A target is allowed to deep sleep if counter == 0 00034 static uint16_t deep_sleep_lock = 0U; 00035 static us_timestamp_t sleep_time = 0; 00036 static us_timestamp_t deep_sleep_time = 0; 00037 00038 #if defined(MBED_CPU_STATS_ENABLED) && defined(DEVICE_LPTICKER) 00039 static ticker_data_t *sleep_ticker = NULL; 00040 #endif 00041 00042 static inline us_timestamp_t read_us(void) 00043 { 00044 #if defined(MBED_CPU_STATS_ENABLED) && defined(DEVICE_LPTICKER) 00045 if (NULL == sleep_ticker) { 00046 sleep_ticker = (ticker_data_t *)get_lp_ticker_data(); 00047 } 00048 return ticker_read_us(sleep_ticker); 00049 #else 00050 return 0; 00051 #endif 00052 } 00053 00054 us_timestamp_t mbed_time_idle(void) 00055 { 00056 return (sleep_time + deep_sleep_time); 00057 } 00058 00059 us_timestamp_t mbed_uptime(void) 00060 { 00061 return read_us(); 00062 } 00063 00064 us_timestamp_t mbed_time_sleep(void) 00065 { 00066 return sleep_time; 00067 } 00068 00069 us_timestamp_t mbed_time_deepsleep(void) 00070 { 00071 return deep_sleep_time; 00072 } 00073 00074 #ifdef MBED_SLEEP_TRACING_ENABLED 00075 00076 // Number of drivers that can be stored in the structure 00077 #define STATISTIC_COUNT 10 00078 00079 typedef struct sleep_statistic { 00080 const char *identifier; 00081 uint8_t count; 00082 } sleep_statistic_t; 00083 00084 static sleep_statistic_t sleep_stats[STATISTIC_COUNT]; 00085 00086 static sleep_statistic_t *sleep_tracker_find(const char *const filename) 00087 { 00088 for (int i = 0; i < STATISTIC_COUNT; ++i) { 00089 if (sleep_stats[i].identifier == filename) { 00090 return &sleep_stats[i]; 00091 } 00092 } 00093 00094 return NULL; 00095 } 00096 00097 static sleep_statistic_t *sleep_tracker_add(const char *const filename) 00098 { 00099 for (int i = 0; i < STATISTIC_COUNT; ++i) { 00100 if (sleep_stats[i].identifier == NULL) { 00101 sleep_stats[i].identifier = filename; 00102 00103 return &sleep_stats[i]; 00104 } 00105 } 00106 00107 debug("No free indexes left to use in mbed sleep tracker.\r\n"); 00108 00109 return NULL; 00110 } 00111 00112 static void sleep_tracker_print_stats(void) 00113 { 00114 debug("Sleep locks held:\r\n"); 00115 for (int i = 0; i < STATISTIC_COUNT; ++i) { 00116 if (sleep_stats[i].count == 0) { 00117 continue; 00118 } 00119 00120 if (sleep_stats[i].identifier == NULL) { 00121 return; 00122 } 00123 00124 debug("[id: %s, count: %u]\r\n", sleep_stats[i].identifier, 00125 sleep_stats[i].count); 00126 } 00127 } 00128 00129 void sleep_tracker_lock(const char *const filename, int line) 00130 { 00131 sleep_statistic_t *stat = sleep_tracker_find(filename); 00132 00133 // Entry for this driver does not exist, create one. 00134 if (stat == NULL) { 00135 stat = sleep_tracker_add(filename); 00136 } 00137 00138 core_util_atomic_incr_u8(&stat->count, 1); 00139 00140 debug("LOCK: %s, ln: %i, lock count: %u\r\n", filename, line, deep_sleep_lock); 00141 } 00142 00143 void sleep_tracker_unlock(const char *const filename, int line) 00144 { 00145 sleep_statistic_t *stat = sleep_tracker_find(filename); 00146 00147 // Entry for this driver does not exist, something went wrong. 00148 if (stat == NULL) { 00149 debug("Unlocking sleep for driver that was not previously locked: %s, ln: %i\r\n", filename, line); 00150 return; 00151 } 00152 00153 core_util_atomic_decr_u8(&stat->count, 1); 00154 00155 debug("UNLOCK: %s, ln: %i, lock count: %u\r\n", filename, line, deep_sleep_lock); 00156 } 00157 00158 #endif // MBED_SLEEP_TRACING_ENABLED 00159 00160 void sleep_manager_lock_deep_sleep_internal(void) 00161 { 00162 core_util_critical_section_enter(); 00163 if (deep_sleep_lock == USHRT_MAX) { 00164 core_util_critical_section_exit(); 00165 MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_HAL, MBED_ERROR_CODE_OVERFLOW), "DeepSleepLock overflow (> USHRT_MAX)", deep_sleep_lock); 00166 // When running sleep_manager tests, the mbed_error() is overridden 00167 // and no longer calls mbed_halt_system(). Return to prevent 00168 // execution of the following code. 00169 return; 00170 } 00171 core_util_atomic_incr_u16(&deep_sleep_lock, 1); 00172 core_util_critical_section_exit(); 00173 } 00174 00175 void sleep_manager_unlock_deep_sleep_internal(void) 00176 { 00177 core_util_critical_section_enter(); 00178 if (deep_sleep_lock == 0) { 00179 core_util_critical_section_exit(); 00180 MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_HAL, MBED_ERROR_CODE_UNDERFLOW), "DeepSleepLock underflow (< 0)", deep_sleep_lock); 00181 // When running sleep_manager tests, the mbed_error() is overridden 00182 // and no longer calls mbed_halt_system(). Return to prevent 00183 // execution of the following code. 00184 return; 00185 } 00186 core_util_atomic_decr_u16(&deep_sleep_lock, 1); 00187 core_util_critical_section_exit(); 00188 } 00189 00190 bool sleep_manager_can_deep_sleep(void) 00191 { 00192 return deep_sleep_lock == 0 ? true : false; 00193 } 00194 00195 bool sleep_manager_can_deep_sleep_test_check() 00196 { 00197 const uint32_t check_time_us = 2000; 00198 const ticker_data_t *const ticker = get_us_ticker_data(); 00199 uint32_t start = ticker_read(ticker); 00200 while ((ticker_read(ticker) - start) < check_time_us) { 00201 if (sleep_manager_can_deep_sleep()) { 00202 return true; 00203 } 00204 } 00205 return false; 00206 } 00207 00208 void sleep_manager_sleep_auto(void) 00209 { 00210 #ifdef MBED_SLEEP_TRACING_ENABLED 00211 sleep_tracker_print_stats(); 00212 #endif 00213 core_util_critical_section_enter(); 00214 us_timestamp_t start = read_us(); 00215 bool deep = false; 00216 00217 // debug profile should keep debuggers attached, no deep sleep allowed 00218 #ifdef MBED_DEBUG 00219 hal_sleep(); 00220 #else 00221 if (sleep_manager_can_deep_sleep()) { 00222 deep = true; 00223 hal_deepsleep(); 00224 } else { 00225 hal_sleep(); 00226 } 00227 #endif 00228 00229 us_timestamp_t end = read_us(); 00230 if (true == deep) { 00231 deep_sleep_time += end - start; 00232 } else { 00233 sleep_time += end - start; 00234 } 00235 core_util_critical_section_exit(); 00236 } 00237 00238 #else 00239 00240 // locking is valid only if DEVICE_SLEEP is defined 00241 // we provide empty implementation 00242 00243 void sleep_manager_lock_deep_sleep_internal(void) 00244 { 00245 00246 } 00247 00248 void sleep_manager_unlock_deep_sleep_internal(void) 00249 { 00250 00251 } 00252 00253 bool sleep_manager_can_deep_sleep(void) 00254 { 00255 // no sleep implemented 00256 return false; 00257 } 00258 00259 #endif
Generated on Tue Jul 12 2022 20:52:50 by
