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 <limits.h> 00024 #include <stdio.h> 00025 00026 #if DEVICE_SLEEP 00027 00028 // deep sleep locking counter. A target is allowed to deep sleep if counter == 0 00029 static uint16_t deep_sleep_lock = 0U; 00030 00031 #ifdef MBED_SLEEP_TRACING_ENABLED 00032 00033 // Number of drivers that can be stored in the structure 00034 #define STATISTIC_COUNT 10 00035 00036 typedef struct sleep_statistic { 00037 const char* identifier; 00038 uint8_t count; 00039 } sleep_statistic_t; 00040 00041 static sleep_statistic_t sleep_stats[STATISTIC_COUNT]; 00042 00043 static sleep_statistic_t* sleep_tracker_find(const char *const filename) 00044 { 00045 for (int i = 0; i < STATISTIC_COUNT; ++i) { 00046 if (sleep_stats[i].identifier == filename) { 00047 return &sleep_stats[i]; 00048 } 00049 } 00050 00051 return NULL; 00052 } 00053 00054 static sleep_statistic_t* sleep_tracker_add(const char* const filename) 00055 { 00056 for (int i = 0; i < STATISTIC_COUNT; ++i) { 00057 if (sleep_stats[i].identifier == NULL) { 00058 sleep_stats[i].identifier = filename; 00059 00060 return &sleep_stats[i]; 00061 } 00062 } 00063 00064 debug("No free indexes left to use in mbed sleep tracker.\r\n"); 00065 00066 return NULL; 00067 } 00068 00069 static void sleep_tracker_print_stats(void) 00070 { 00071 debug("Sleep locks held:\r\n"); 00072 for (int i = 0; i < STATISTIC_COUNT; ++i) { 00073 if (sleep_stats[i].count == 0) { 00074 continue; 00075 } 00076 00077 if (sleep_stats[i].identifier == NULL) { 00078 return; 00079 } 00080 00081 debug("[id: %s, count: %u]\r\n", sleep_stats[i].identifier, 00082 sleep_stats[i].count); 00083 } 00084 } 00085 00086 void sleep_tracker_lock(const char* const filename, int line) 00087 { 00088 sleep_statistic_t *stat = sleep_tracker_find(filename); 00089 00090 // Entry for this driver does not exist, create one. 00091 if (stat == NULL) { 00092 stat = sleep_tracker_add(filename); 00093 } 00094 00095 core_util_atomic_incr_u8(&stat->count, 1); 00096 00097 debug("LOCK: %s, ln: %i, lock count: %u\r\n", filename, line, deep_sleep_lock); 00098 } 00099 00100 void sleep_tracker_unlock(const char* const filename, int line) 00101 { 00102 sleep_statistic_t *stat = sleep_tracker_find(filename); 00103 00104 // Entry for this driver does not exist, something went wrong. 00105 if (stat == NULL) { 00106 debug("Unlocking sleep for driver that was not previously locked: %s, ln: %i\r\n", filename, line); 00107 return; 00108 } 00109 00110 core_util_atomic_decr_u8(&stat->count, 1); 00111 00112 debug("UNLOCK: %s, ln: %i, lock count: %u\r\n", filename, line, deep_sleep_lock); 00113 } 00114 00115 #endif // MBED_SLEEP_TRACING_ENABLED 00116 00117 void sleep_manager_lock_deep_sleep_internal(void) 00118 { 00119 core_util_critical_section_enter(); 00120 if (deep_sleep_lock == USHRT_MAX) { 00121 core_util_critical_section_exit(); 00122 error("Deep sleep lock would overflow (> USHRT_MAX)"); 00123 } 00124 core_util_atomic_incr_u16(&deep_sleep_lock, 1); 00125 core_util_critical_section_exit(); 00126 } 00127 00128 void sleep_manager_unlock_deep_sleep_internal(void) 00129 { 00130 core_util_critical_section_enter(); 00131 if (deep_sleep_lock == 0) { 00132 core_util_critical_section_exit(); 00133 error("Deep sleep lock would underflow (< 0)"); 00134 } 00135 core_util_atomic_decr_u16(&deep_sleep_lock, 1); 00136 core_util_critical_section_exit(); 00137 } 00138 00139 bool sleep_manager_can_deep_sleep(void) 00140 { 00141 return deep_sleep_lock == 0 ? true : false; 00142 } 00143 00144 void sleep_manager_sleep_auto(void) 00145 { 00146 #ifdef MBED_SLEEP_TRACING_ENABLED 00147 sleep_tracker_print_stats(); 00148 #endif 00149 core_util_critical_section_enter(); 00150 // debug profile should keep debuggers attached, no deep sleep allowed 00151 #ifdef MBED_DEBUG 00152 hal_sleep(); 00153 #else 00154 if (sleep_manager_can_deep_sleep()) { 00155 hal_deepsleep(); 00156 } else { 00157 hal_sleep(); 00158 } 00159 #endif 00160 core_util_critical_section_exit(); 00161 } 00162 00163 #else 00164 00165 // locking is valid only if DEVICE_SLEEP is defined 00166 // we provide empty implementation 00167 00168 void sleep_manager_lock_deep_sleep_internal(void) 00169 { 00170 00171 } 00172 00173 void sleep_manager_unlock_deep_sleep_internal(void) 00174 { 00175 00176 } 00177 00178 bool sleep_manager_can_deep_sleep(void) 00179 { 00180 // no sleep implemented 00181 return false; 00182 } 00183 00184 #endif
Generated on Tue Jul 12 2022 12:22:11 by
