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 // Length of the identifier extracted from the driver name to store for logging. 00034 #define IDENTIFIER_WIDTH 15 00035 // Number of drivers that can be stored in the structure 00036 #define STATISTIC_COUNT 10 00037 00038 typedef struct sleep_statistic { 00039 char identifier[IDENTIFIER_WIDTH]; 00040 uint8_t count; 00041 } sleep_statistic_t; 00042 00043 static sleep_statistic_t sleep_stats[STATISTIC_COUNT]; 00044 00045 static const char* strip_path(const char* const filename) 00046 { 00047 char *output = strrchr(filename, '/'); 00048 00049 if (output != NULL) { 00050 return output + 1; 00051 } 00052 00053 output = strrchr(filename, '\\'); 00054 00055 if (output != NULL) { 00056 return output + 1; 00057 } 00058 00059 return filename; 00060 } 00061 00062 static sleep_statistic_t* sleep_tracker_find(const char *const filename) 00063 { 00064 char temp[IDENTIFIER_WIDTH]; 00065 strncpy(temp, filename, IDENTIFIER_WIDTH); 00066 temp[IDENTIFIER_WIDTH - 1] = '\0'; 00067 00068 // Search for the a driver matching the current name and return it's index 00069 for (int i = 0; i < STATISTIC_COUNT; ++i) { 00070 if (strcmp(sleep_stats[i].identifier, temp) == 0) { 00071 return &sleep_stats[i]; 00072 } 00073 } 00074 00075 return NULL; 00076 } 00077 00078 static sleep_statistic_t* sleep_tracker_add(const char* const filename) 00079 { 00080 char temp[IDENTIFIER_WIDTH]; 00081 strncpy(temp, filename, IDENTIFIER_WIDTH); 00082 temp[IDENTIFIER_WIDTH - 1] = '\0'; 00083 00084 for (int i = 0; i < STATISTIC_COUNT; ++i) { 00085 if (sleep_stats[i].identifier[0] == '\0') { 00086 core_util_critical_section_enter(); 00087 strncpy(sleep_stats[i].identifier, temp, sizeof(temp)); 00088 core_util_critical_section_exit(); 00089 00090 return &sleep_stats[i]; 00091 } 00092 } 00093 00094 debug("No free indexes left to use in mbed sleep tracker.\r\n"); 00095 00096 return NULL; 00097 } 00098 00099 static void sleep_tracker_print_stats(void) 00100 { 00101 debug("Sleep locks held:\r\n"); 00102 for (int i = 0; i < STATISTIC_COUNT; ++i) { 00103 if (sleep_stats[i].count == 0) { 00104 continue; 00105 } 00106 00107 if (sleep_stats[i].identifier[0] == '\0') { 00108 return; 00109 } 00110 00111 debug("[id: %s, count: %u]\r\n", sleep_stats[i].identifier, 00112 sleep_stats[i].count); 00113 } 00114 } 00115 00116 void sleep_tracker_lock(const char* const filename, int line) 00117 { 00118 const char* const stripped_path = strip_path(filename); 00119 00120 sleep_statistic_t* stat = sleep_tracker_find(stripped_path); 00121 00122 // Entry for this driver does not exist, create one. 00123 if (stat == NULL) { 00124 stat = sleep_tracker_add(stripped_path); 00125 } 00126 00127 core_util_atomic_incr_u8(&stat->count, 1); 00128 00129 debug("LOCK: %s, ln: %i, lock count: %u\r\n", stripped_path, line, deep_sleep_lock); 00130 } 00131 00132 void sleep_tracker_unlock(const char* const filename, int line) 00133 { 00134 const char* const stripped_path = strip_path(filename); 00135 sleep_statistic_t* stat = sleep_tracker_find(stripped_path); 00136 00137 // Entry for this driver does not exist, something went wrong. 00138 if (stat == NULL) { 00139 debug("Unlocking sleep for driver that was not previously locked: %s, ln: %i\r\n", stripped_path, line); 00140 return; 00141 } 00142 00143 core_util_atomic_decr_u8(&stat->count, 1); 00144 00145 debug("UNLOCK: %s, ln: %i, lock count: %u\r\n", stripped_path, line, deep_sleep_lock); 00146 } 00147 00148 #endif // MBED_SLEEP_TRACING_ENABLED 00149 00150 void sleep_manager_lock_deep_sleep_internal(void) 00151 { 00152 core_util_critical_section_enter(); 00153 if (deep_sleep_lock == USHRT_MAX) { 00154 core_util_critical_section_exit(); 00155 error("Deep sleep lock would overflow (> USHRT_MAX)"); 00156 } 00157 core_util_atomic_incr_u16(&deep_sleep_lock, 1); 00158 core_util_critical_section_exit(); 00159 } 00160 00161 void sleep_manager_unlock_deep_sleep_internal(void) 00162 { 00163 core_util_critical_section_enter(); 00164 if (deep_sleep_lock == 0) { 00165 core_util_critical_section_exit(); 00166 error("Deep sleep lock would underflow (< 0)"); 00167 } 00168 core_util_atomic_decr_u16(&deep_sleep_lock, 1); 00169 core_util_critical_section_exit(); 00170 } 00171 00172 bool sleep_manager_can_deep_sleep(void) 00173 { 00174 return deep_sleep_lock == 0 ? true : false; 00175 } 00176 00177 void sleep_manager_sleep_auto(void) 00178 { 00179 #ifdef MBED_SLEEP_TRACING_ENABLED 00180 sleep_tracker_print_stats(); 00181 #endif 00182 core_util_critical_section_enter(); 00183 // debug profile should keep debuggers attached, no deep sleep allowed 00184 #ifdef MBED_DEBUG 00185 hal_sleep(); 00186 #else 00187 if (sleep_manager_can_deep_sleep()) { 00188 hal_deepsleep(); 00189 } else { 00190 hal_sleep(); 00191 } 00192 #endif 00193 core_util_critical_section_exit(); 00194 } 00195 00196 #else 00197 00198 // locking is valid only if DEVICE_SLEEP is defined 00199 // we provide empty implementation 00200 00201 void sleep_manager_lock_deep_sleep_internal(void) 00202 { 00203 00204 } 00205 00206 void sleep_manager_unlock_deep_sleep_internal(void) 00207 { 00208 00209 } 00210 00211 bool sleep_manager_can_deep_sleep(void) 00212 { 00213 // no sleep implemented 00214 return false; 00215 } 00216 00217 #endif
Generated on Tue Jul 12 2022 13:30:53 by
