mbed library sources. Supersedes mbed-src.
Dependents: Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more
mbed_sleep_manager.c
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2017 ARM Limited 00003 * SPDX-License-Identifier: Apache-2.0 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); 00006 * you may not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 00018 #include "mbed_power_mgmt.h" 00019 #include "mbed_interface.h" 00020 #include "mbed_critical.h" 00021 #include "mbed_assert.h" 00022 #include "mbed_error.h" 00023 #include "mbed_stats.h" 00024 00025 #include "hal/us_ticker_api.h" 00026 #include "hal/lp_ticker_api.h" 00027 00028 #include <limits.h> 00029 #include <stdio.h> 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) && 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) && 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 mbed_error_printf("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 mbed_error_printf("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 mbed_error_printf("[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 mbed_error_printf("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 mbed_error_printf("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 mbed_error_printf("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 } 00167 core_util_atomic_incr_u16(&deep_sleep_lock, 1); 00168 core_util_critical_section_exit(); 00169 } 00170 00171 void sleep_manager_unlock_deep_sleep_internal(void) 00172 { 00173 core_util_critical_section_enter(); 00174 if (deep_sleep_lock == 0) { 00175 core_util_critical_section_exit(); 00176 MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_HAL, MBED_ERROR_CODE_UNDERFLOW), "DeepSleepLock underflow (< 0)", deep_sleep_lock); 00177 } 00178 core_util_atomic_decr_u16(&deep_sleep_lock, 1); 00179 core_util_critical_section_exit(); 00180 } 00181 00182 bool sleep_manager_can_deep_sleep(void) 00183 { 00184 return deep_sleep_lock == 0 ? true : false; 00185 } 00186 00187 bool sleep_manager_can_deep_sleep_test_check() 00188 { 00189 const uint32_t check_time_us = 2000; 00190 const ticker_data_t *const ticker = get_us_ticker_data(); 00191 uint32_t start = ticker_read(ticker); 00192 while ((ticker_read(ticker) - start) < check_time_us) { 00193 if (sleep_manager_can_deep_sleep()) { 00194 return true; 00195 } 00196 } 00197 return false; 00198 } 00199 00200 void sleep_manager_sleep_auto(void) 00201 { 00202 #ifdef MBED_SLEEP_TRACING_ENABLED 00203 sleep_tracker_print_stats(); 00204 #endif 00205 core_util_critical_section_enter(); 00206 us_timestamp_t start = read_us(); 00207 bool deep = false; 00208 00209 // debug profile should keep debuggers attached, no deep sleep allowed 00210 #ifdef MBED_DEBUG 00211 hal_sleep(); 00212 #else 00213 if (sleep_manager_can_deep_sleep()) { 00214 deep = true; 00215 hal_deepsleep(); 00216 } else { 00217 hal_sleep(); 00218 } 00219 #endif 00220 00221 us_timestamp_t end = read_us(); 00222 if (true == deep) { 00223 deep_sleep_time += end - start; 00224 } else { 00225 sleep_time += end - start; 00226 } 00227 core_util_critical_section_exit(); 00228 } 00229 00230 #else 00231 00232 // locking is valid only if DEVICE_SLEEP is defined 00233 // we provide empty implementation 00234 00235 void sleep_manager_lock_deep_sleep_internal(void) 00236 { 00237 00238 } 00239 00240 void sleep_manager_unlock_deep_sleep_internal(void) 00241 { 00242 00243 } 00244 00245 bool sleep_manager_can_deep_sleep(void) 00246 { 00247 // no sleep implemented 00248 return false; 00249 } 00250 00251 #endif
Generated on Tue Jul 12 2022 20:41:15 by 1.7.2