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 "mbed_assert.h" 00018 #include "mbed_power_mgmt.h" 00019 #include "mbed_critical.h" 00020 #include "sleep_api.h" 00021 #include "mbed_error.h" 00022 #include "mbed_debug.h" 00023 #include "mbed_stats.h" 00024 #include "lp_ticker_api.h" 00025 #include <limits.h> 00026 #include <stdio.h> 00027 #include "mbed_stats.h" 00028 00029 00030 #if DEVICE_SLEEP 00031 00032 // deep sleep locking counter. A target is allowed to deep sleep if counter == 0 00033 static uint16_t deep_sleep_lock = 0U; 00034 static us_timestamp_t sleep_time = 0; 00035 static us_timestamp_t deep_sleep_time = 0; 00036 00037 #if defined(MBED_CPU_STATS_ENABLED) && defined(DEVICE_LPTICKER) 00038 static ticker_data_t *sleep_ticker = NULL; 00039 #endif 00040 00041 static inline us_timestamp_t read_us(void) 00042 { 00043 #if defined(MBED_CPU_STATS_ENABLED) && defined(DEVICE_LPTICKER) 00044 if (NULL == sleep_ticker) { 00045 sleep_ticker = (ticker_data_t *)get_lp_ticker_data(); 00046 } 00047 return ticker_read_us(sleep_ticker); 00048 #else 00049 return 0; 00050 #endif 00051 } 00052 00053 us_timestamp_t mbed_time_idle(void) 00054 { 00055 return (sleep_time + deep_sleep_time); 00056 } 00057 00058 us_timestamp_t mbed_uptime(void) 00059 { 00060 return read_us(); 00061 } 00062 00063 us_timestamp_t mbed_time_sleep(void) 00064 { 00065 return sleep_time; 00066 } 00067 00068 us_timestamp_t mbed_time_deepsleep(void) 00069 { 00070 return deep_sleep_time; 00071 } 00072 00073 #ifdef MBED_SLEEP_TRACING_ENABLED 00074 00075 // Number of drivers that can be stored in the structure 00076 #define STATISTIC_COUNT 10 00077 00078 typedef struct sleep_statistic { 00079 const char *identifier; 00080 uint8_t count; 00081 } sleep_statistic_t; 00082 00083 static sleep_statistic_t sleep_stats[STATISTIC_COUNT]; 00084 00085 static sleep_statistic_t* sleep_tracker_find(const char *const filename) 00086 { 00087 for (int i = 0; i < STATISTIC_COUNT; ++i) { 00088 if (sleep_stats[i].identifier == filename) { 00089 return &sleep_stats[i]; 00090 } 00091 } 00092 00093 return NULL; 00094 } 00095 00096 static sleep_statistic_t* sleep_tracker_add(const char* const filename) 00097 { 00098 for (int i = 0; i < STATISTIC_COUNT; ++i) { 00099 if (sleep_stats[i].identifier == NULL) { 00100 sleep_stats[i].identifier = filename; 00101 00102 return &sleep_stats[i]; 00103 } 00104 } 00105 00106 debug("No free indexes left to use in mbed sleep tracker.\r\n"); 00107 00108 return NULL; 00109 } 00110 00111 static void sleep_tracker_print_stats(void) 00112 { 00113 debug("Sleep locks held:\r\n"); 00114 for (int i = 0; i < STATISTIC_COUNT; ++i) { 00115 if (sleep_stats[i].count == 0) { 00116 continue; 00117 } 00118 00119 if (sleep_stats[i].identifier == NULL) { 00120 return; 00121 } 00122 00123 debug("[id: %s, count: %u]\r\n", sleep_stats[i].identifier, 00124 sleep_stats[i].count); 00125 } 00126 } 00127 00128 void sleep_tracker_lock(const char *const filename, int line) 00129 { 00130 sleep_statistic_t *stat = sleep_tracker_find(filename); 00131 00132 // Entry for this driver does not exist, create one. 00133 if (stat == NULL) { 00134 stat = sleep_tracker_add(filename); 00135 } 00136 00137 core_util_atomic_incr_u8(&stat->count, 1); 00138 00139 debug("LOCK: %s, ln: %i, lock count: %u\r\n", filename, line, deep_sleep_lock); 00140 } 00141 00142 void sleep_tracker_unlock(const char* const filename, int line) 00143 { 00144 sleep_statistic_t *stat = sleep_tracker_find(filename); 00145 00146 // Entry for this driver does not exist, something went wrong. 00147 if (stat == NULL) { 00148 debug("Unlocking sleep for driver that was not previously locked: %s, ln: %i\r\n", filename, line); 00149 return; 00150 } 00151 00152 core_util_atomic_decr_u8(&stat->count, 1); 00153 00154 debug("UNLOCK: %s, ln: %i, lock count: %u\r\n", filename, line, deep_sleep_lock); 00155 } 00156 00157 #endif // MBED_SLEEP_TRACING_ENABLED 00158 00159 void sleep_manager_lock_deep_sleep_internal(void) 00160 { 00161 core_util_critical_section_enter(); 00162 if (deep_sleep_lock == USHRT_MAX) { 00163 core_util_critical_section_exit(); 00164 MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_HAL, MBED_ERROR_CODE_OVERFLOW), "DeepSleepLock overflow (> USHRT_MAX)", deep_sleep_lock); 00165 } 00166 core_util_atomic_incr_u16(&deep_sleep_lock, 1); 00167 core_util_critical_section_exit(); 00168 } 00169 00170 void sleep_manager_unlock_deep_sleep_internal(void) 00171 { 00172 core_util_critical_section_enter(); 00173 if (deep_sleep_lock == 0) { 00174 core_util_critical_section_exit(); 00175 MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_HAL, MBED_ERROR_CODE_UNDERFLOW), "DeepSleepLock underflow (< 0)", deep_sleep_lock); 00176 } 00177 core_util_atomic_decr_u16(&deep_sleep_lock, 1); 00178 core_util_critical_section_exit(); 00179 } 00180 00181 bool sleep_manager_can_deep_sleep(void) 00182 { 00183 return deep_sleep_lock == 0 ? true : false; 00184 } 00185 00186 void sleep_manager_sleep_auto(void) 00187 { 00188 #ifdef MBED_SLEEP_TRACING_ENABLED 00189 sleep_tracker_print_stats(); 00190 #endif 00191 core_util_critical_section_enter(); 00192 us_timestamp_t start = read_us(); 00193 bool deep = false; 00194 00195 // debug profile should keep debuggers attached, no deep sleep allowed 00196 #ifdef MBED_DEBUG 00197 hal_sleep(); 00198 #else 00199 if (sleep_manager_can_deep_sleep()) { 00200 deep = true; 00201 hal_deepsleep(); 00202 } else { 00203 hal_sleep(); 00204 } 00205 #endif 00206 00207 us_timestamp_t end = read_us(); 00208 if (true == deep) { 00209 deep_sleep_time += end - start; 00210 } else { 00211 sleep_time += end - start; 00212 } 00213 core_util_critical_section_exit(); 00214 } 00215 00216 #else 00217 00218 // locking is valid only if DEVICE_SLEEP is defined 00219 // we provide empty implementation 00220 00221 void sleep_manager_lock_deep_sleep_internal(void) 00222 { 00223 00224 } 00225 00226 void sleep_manager_unlock_deep_sleep_internal(void) 00227 { 00228 00229 } 00230 00231 bool sleep_manager_can_deep_sleep(void) 00232 { 00233 // no sleep implemented 00234 return false; 00235 } 00236 00237 #endif
Generated on Tue Jul 12 2022 12:45:30 by
