mbed library sources. Supersedes mbed-src.

Dependents:   Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more

Committer:
AnnaBridge
Date:
Thu Nov 08 11:46:34 2018 +0000
Revision:
188:bcfe06ba3d64
Parent:
187:0387e8f68319
mbed-dev library. Release version 164

Who changed what in which revision?

UserRevisionLine numberNew contents of line
AnnaBridge 174:b96e65c34a4d 1 /* mbed Microcontroller Library
AnnaBridge 174:b96e65c34a4d 2 * Copyright (c) 2017 ARM Limited
AnnaBridge 174:b96e65c34a4d 3 *
AnnaBridge 174:b96e65c34a4d 4 * Licensed under the Apache License, Version 2.0 (the "License");
AnnaBridge 174:b96e65c34a4d 5 * you may not use this file except in compliance with the License.
AnnaBridge 174:b96e65c34a4d 6 * You may obtain a copy of the License at
AnnaBridge 174:b96e65c34a4d 7 *
AnnaBridge 174:b96e65c34a4d 8 * http://www.apache.org/licenses/LICENSE-2.0
AnnaBridge 174:b96e65c34a4d 9 *
AnnaBridge 174:b96e65c34a4d 10 * Unless required by applicable law or agreed to in writing, software
AnnaBridge 174:b96e65c34a4d 11 * distributed under the License is distributed on an "AS IS" BASIS,
AnnaBridge 174:b96e65c34a4d 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
AnnaBridge 174:b96e65c34a4d 13 * See the License for the specific language governing permissions and
AnnaBridge 174:b96e65c34a4d 14 * limitations under the License.
AnnaBridge 174:b96e65c34a4d 15 */
AnnaBridge 174:b96e65c34a4d 16
AnnaBridge 188:bcfe06ba3d64 17 #include "platform/mbed_assert.h"
AnnaBridge 188:bcfe06ba3d64 18 #include "platform/mbed_power_mgmt.h"
AnnaBridge 188:bcfe06ba3d64 19 #include "platform/mbed_critical.h"
AnnaBridge 174:b96e65c34a4d 20 #include "sleep_api.h"
AnnaBridge 188:bcfe06ba3d64 21 #include "platform/mbed_error.h"
AnnaBridge 188:bcfe06ba3d64 22 #include "platform/mbed_debug.h"
AnnaBridge 188:bcfe06ba3d64 23 #include "platform/mbed_stats.h"
AnnaBridge 188:bcfe06ba3d64 24 #include "us_ticker_api.h"
Anna Bridge 186:707f6e361f3e 25 #include "lp_ticker_api.h"
AnnaBridge 174:b96e65c34a4d 26 #include <limits.h>
AnnaBridge 184:08ed48f1de7f 27 #include <stdio.h>
AnnaBridge 188:bcfe06ba3d64 28 #include "platform/mbed_stats.h"
Anna Bridge 186:707f6e361f3e 29
AnnaBridge 174:b96e65c34a4d 30
AnnaBridge 174:b96e65c34a4d 31 #if DEVICE_SLEEP
AnnaBridge 174:b96e65c34a4d 32
AnnaBridge 174:b96e65c34a4d 33 // deep sleep locking counter. A target is allowed to deep sleep if counter == 0
AnnaBridge 174:b96e65c34a4d 34 static uint16_t deep_sleep_lock = 0U;
Anna Bridge 186:707f6e361f3e 35 static us_timestamp_t sleep_time = 0;
Anna Bridge 186:707f6e361f3e 36 static us_timestamp_t deep_sleep_time = 0;
Anna Bridge 186:707f6e361f3e 37
Anna Bridge 186:707f6e361f3e 38 #if defined(MBED_CPU_STATS_ENABLED) && defined(DEVICE_LPTICKER)
Anna Bridge 186:707f6e361f3e 39 static ticker_data_t *sleep_ticker = NULL;
Anna Bridge 186:707f6e361f3e 40 #endif
Anna Bridge 186:707f6e361f3e 41
Anna Bridge 186:707f6e361f3e 42 static inline us_timestamp_t read_us(void)
Anna Bridge 186:707f6e361f3e 43 {
Anna Bridge 186:707f6e361f3e 44 #if defined(MBED_CPU_STATS_ENABLED) && defined(DEVICE_LPTICKER)
Anna Bridge 186:707f6e361f3e 45 if (NULL == sleep_ticker) {
Anna Bridge 186:707f6e361f3e 46 sleep_ticker = (ticker_data_t *)get_lp_ticker_data();
Anna Bridge 186:707f6e361f3e 47 }
Anna Bridge 186:707f6e361f3e 48 return ticker_read_us(sleep_ticker);
Anna Bridge 186:707f6e361f3e 49 #else
Anna Bridge 186:707f6e361f3e 50 return 0;
Anna Bridge 186:707f6e361f3e 51 #endif
Anna Bridge 186:707f6e361f3e 52 }
Anna Bridge 186:707f6e361f3e 53
Anna Bridge 186:707f6e361f3e 54 us_timestamp_t mbed_time_idle(void)
Anna Bridge 186:707f6e361f3e 55 {
Anna Bridge 186:707f6e361f3e 56 return (sleep_time + deep_sleep_time);
Anna Bridge 186:707f6e361f3e 57 }
Anna Bridge 186:707f6e361f3e 58
Anna Bridge 186:707f6e361f3e 59 us_timestamp_t mbed_uptime(void)
Anna Bridge 186:707f6e361f3e 60 {
Anna Bridge 186:707f6e361f3e 61 return read_us();
Anna Bridge 186:707f6e361f3e 62 }
Anna Bridge 186:707f6e361f3e 63
Anna Bridge 186:707f6e361f3e 64 us_timestamp_t mbed_time_sleep(void)
Anna Bridge 186:707f6e361f3e 65 {
Anna Bridge 186:707f6e361f3e 66 return sleep_time;
Anna Bridge 186:707f6e361f3e 67 }
Anna Bridge 186:707f6e361f3e 68
Anna Bridge 186:707f6e361f3e 69 us_timestamp_t mbed_time_deepsleep(void)
Anna Bridge 186:707f6e361f3e 70 {
Anna Bridge 186:707f6e361f3e 71 return deep_sleep_time;
Anna Bridge 186:707f6e361f3e 72 }
AnnaBridge 174:b96e65c34a4d 73
AnnaBridge 184:08ed48f1de7f 74 #ifdef MBED_SLEEP_TRACING_ENABLED
AnnaBridge 184:08ed48f1de7f 75
AnnaBridge 184:08ed48f1de7f 76 // Number of drivers that can be stored in the structure
AnnaBridge 184:08ed48f1de7f 77 #define STATISTIC_COUNT 10
AnnaBridge 184:08ed48f1de7f 78
AnnaBridge 184:08ed48f1de7f 79 typedef struct sleep_statistic {
Anna Bridge 186:707f6e361f3e 80 const char *identifier;
AnnaBridge 184:08ed48f1de7f 81 uint8_t count;
AnnaBridge 184:08ed48f1de7f 82 } sleep_statistic_t;
AnnaBridge 184:08ed48f1de7f 83
AnnaBridge 184:08ed48f1de7f 84 static sleep_statistic_t sleep_stats[STATISTIC_COUNT];
AnnaBridge 184:08ed48f1de7f 85
AnnaBridge 187:0387e8f68319 86 static sleep_statistic_t *sleep_tracker_find(const char *const filename)
AnnaBridge 184:08ed48f1de7f 87 {
AnnaBridge 184:08ed48f1de7f 88 for (int i = 0; i < STATISTIC_COUNT; ++i) {
AnnaBridge 184:08ed48f1de7f 89 if (sleep_stats[i].identifier == filename) {
AnnaBridge 184:08ed48f1de7f 90 return &sleep_stats[i];
AnnaBridge 184:08ed48f1de7f 91 }
AnnaBridge 184:08ed48f1de7f 92 }
AnnaBridge 184:08ed48f1de7f 93
AnnaBridge 184:08ed48f1de7f 94 return NULL;
AnnaBridge 184:08ed48f1de7f 95 }
AnnaBridge 184:08ed48f1de7f 96
AnnaBridge 187:0387e8f68319 97 static sleep_statistic_t *sleep_tracker_add(const char *const filename)
AnnaBridge 184:08ed48f1de7f 98 {
AnnaBridge 184:08ed48f1de7f 99 for (int i = 0; i < STATISTIC_COUNT; ++i) {
AnnaBridge 184:08ed48f1de7f 100 if (sleep_stats[i].identifier == NULL) {
AnnaBridge 184:08ed48f1de7f 101 sleep_stats[i].identifier = filename;
AnnaBridge 184:08ed48f1de7f 102
AnnaBridge 184:08ed48f1de7f 103 return &sleep_stats[i];
AnnaBridge 184:08ed48f1de7f 104 }
AnnaBridge 184:08ed48f1de7f 105 }
AnnaBridge 184:08ed48f1de7f 106
AnnaBridge 184:08ed48f1de7f 107 debug("No free indexes left to use in mbed sleep tracker.\r\n");
AnnaBridge 184:08ed48f1de7f 108
AnnaBridge 184:08ed48f1de7f 109 return NULL;
AnnaBridge 184:08ed48f1de7f 110 }
AnnaBridge 184:08ed48f1de7f 111
AnnaBridge 184:08ed48f1de7f 112 static void sleep_tracker_print_stats(void)
AnnaBridge 184:08ed48f1de7f 113 {
AnnaBridge 184:08ed48f1de7f 114 debug("Sleep locks held:\r\n");
AnnaBridge 184:08ed48f1de7f 115 for (int i = 0; i < STATISTIC_COUNT; ++i) {
AnnaBridge 184:08ed48f1de7f 116 if (sleep_stats[i].count == 0) {
AnnaBridge 184:08ed48f1de7f 117 continue;
AnnaBridge 184:08ed48f1de7f 118 }
AnnaBridge 184:08ed48f1de7f 119
AnnaBridge 184:08ed48f1de7f 120 if (sleep_stats[i].identifier == NULL) {
AnnaBridge 184:08ed48f1de7f 121 return;
AnnaBridge 184:08ed48f1de7f 122 }
AnnaBridge 184:08ed48f1de7f 123
AnnaBridge 184:08ed48f1de7f 124 debug("[id: %s, count: %u]\r\n", sleep_stats[i].identifier,
AnnaBridge 187:0387e8f68319 125 sleep_stats[i].count);
AnnaBridge 184:08ed48f1de7f 126 }
AnnaBridge 184:08ed48f1de7f 127 }
AnnaBridge 184:08ed48f1de7f 128
Anna Bridge 186:707f6e361f3e 129 void sleep_tracker_lock(const char *const filename, int line)
AnnaBridge 184:08ed48f1de7f 130 {
AnnaBridge 184:08ed48f1de7f 131 sleep_statistic_t *stat = sleep_tracker_find(filename);
AnnaBridge 184:08ed48f1de7f 132
AnnaBridge 184:08ed48f1de7f 133 // Entry for this driver does not exist, create one.
AnnaBridge 184:08ed48f1de7f 134 if (stat == NULL) {
AnnaBridge 184:08ed48f1de7f 135 stat = sleep_tracker_add(filename);
AnnaBridge 184:08ed48f1de7f 136 }
AnnaBridge 184:08ed48f1de7f 137
AnnaBridge 184:08ed48f1de7f 138 core_util_atomic_incr_u8(&stat->count, 1);
AnnaBridge 184:08ed48f1de7f 139
AnnaBridge 184:08ed48f1de7f 140 debug("LOCK: %s, ln: %i, lock count: %u\r\n", filename, line, deep_sleep_lock);
AnnaBridge 184:08ed48f1de7f 141 }
AnnaBridge 184:08ed48f1de7f 142
AnnaBridge 187:0387e8f68319 143 void sleep_tracker_unlock(const char *const filename, int line)
AnnaBridge 184:08ed48f1de7f 144 {
AnnaBridge 184:08ed48f1de7f 145 sleep_statistic_t *stat = sleep_tracker_find(filename);
AnnaBridge 184:08ed48f1de7f 146
AnnaBridge 184:08ed48f1de7f 147 // Entry for this driver does not exist, something went wrong.
AnnaBridge 184:08ed48f1de7f 148 if (stat == NULL) {
AnnaBridge 184:08ed48f1de7f 149 debug("Unlocking sleep for driver that was not previously locked: %s, ln: %i\r\n", filename, line);
AnnaBridge 184:08ed48f1de7f 150 return;
AnnaBridge 184:08ed48f1de7f 151 }
AnnaBridge 184:08ed48f1de7f 152
AnnaBridge 184:08ed48f1de7f 153 core_util_atomic_decr_u8(&stat->count, 1);
AnnaBridge 184:08ed48f1de7f 154
AnnaBridge 184:08ed48f1de7f 155 debug("UNLOCK: %s, ln: %i, lock count: %u\r\n", filename, line, deep_sleep_lock);
AnnaBridge 184:08ed48f1de7f 156 }
AnnaBridge 184:08ed48f1de7f 157
AnnaBridge 184:08ed48f1de7f 158 #endif // MBED_SLEEP_TRACING_ENABLED
AnnaBridge 184:08ed48f1de7f 159
AnnaBridge 184:08ed48f1de7f 160 void sleep_manager_lock_deep_sleep_internal(void)
AnnaBridge 174:b96e65c34a4d 161 {
AnnaBridge 174:b96e65c34a4d 162 core_util_critical_section_enter();
AnnaBridge 174:b96e65c34a4d 163 if (deep_sleep_lock == USHRT_MAX) {
AnnaBridge 174:b96e65c34a4d 164 core_util_critical_section_exit();
Anna Bridge 186:707f6e361f3e 165 MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_HAL, MBED_ERROR_CODE_OVERFLOW), "DeepSleepLock overflow (> USHRT_MAX)", deep_sleep_lock);
AnnaBridge 188:bcfe06ba3d64 166 // When running sleep_manager tests, the mbed_error() is overridden
AnnaBridge 188:bcfe06ba3d64 167 // and no longer calls mbed_halt_system(). Return to prevent
AnnaBridge 188:bcfe06ba3d64 168 // execution of the following code.
AnnaBridge 188:bcfe06ba3d64 169 return;
AnnaBridge 174:b96e65c34a4d 170 }
AnnaBridge 174:b96e65c34a4d 171 core_util_atomic_incr_u16(&deep_sleep_lock, 1);
AnnaBridge 174:b96e65c34a4d 172 core_util_critical_section_exit();
AnnaBridge 174:b96e65c34a4d 173 }
AnnaBridge 174:b96e65c34a4d 174
AnnaBridge 184:08ed48f1de7f 175 void sleep_manager_unlock_deep_sleep_internal(void)
AnnaBridge 174:b96e65c34a4d 176 {
AnnaBridge 174:b96e65c34a4d 177 core_util_critical_section_enter();
AnnaBridge 174:b96e65c34a4d 178 if (deep_sleep_lock == 0) {
AnnaBridge 174:b96e65c34a4d 179 core_util_critical_section_exit();
Anna Bridge 186:707f6e361f3e 180 MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_HAL, MBED_ERROR_CODE_UNDERFLOW), "DeepSleepLock underflow (< 0)", deep_sleep_lock);
AnnaBridge 188:bcfe06ba3d64 181 // When running sleep_manager tests, the mbed_error() is overridden
AnnaBridge 188:bcfe06ba3d64 182 // and no longer calls mbed_halt_system(). Return to prevent
AnnaBridge 188:bcfe06ba3d64 183 // execution of the following code.
AnnaBridge 188:bcfe06ba3d64 184 return;
AnnaBridge 174:b96e65c34a4d 185 }
AnnaBridge 174:b96e65c34a4d 186 core_util_atomic_decr_u16(&deep_sleep_lock, 1);
AnnaBridge 174:b96e65c34a4d 187 core_util_critical_section_exit();
AnnaBridge 174:b96e65c34a4d 188 }
AnnaBridge 174:b96e65c34a4d 189
AnnaBridge 174:b96e65c34a4d 190 bool sleep_manager_can_deep_sleep(void)
AnnaBridge 174:b96e65c34a4d 191 {
AnnaBridge 174:b96e65c34a4d 192 return deep_sleep_lock == 0 ? true : false;
AnnaBridge 174:b96e65c34a4d 193 }
AnnaBridge 174:b96e65c34a4d 194
AnnaBridge 188:bcfe06ba3d64 195 bool sleep_manager_can_deep_sleep_test_check()
AnnaBridge 188:bcfe06ba3d64 196 {
AnnaBridge 188:bcfe06ba3d64 197 const uint32_t check_time_us = 2000;
AnnaBridge 188:bcfe06ba3d64 198 const ticker_data_t *const ticker = get_us_ticker_data();
AnnaBridge 188:bcfe06ba3d64 199 uint32_t start = ticker_read(ticker);
AnnaBridge 188:bcfe06ba3d64 200 while ((ticker_read(ticker) - start) < check_time_us) {
AnnaBridge 188:bcfe06ba3d64 201 if (sleep_manager_can_deep_sleep()) {
AnnaBridge 188:bcfe06ba3d64 202 return true;
AnnaBridge 188:bcfe06ba3d64 203 }
AnnaBridge 188:bcfe06ba3d64 204 }
AnnaBridge 188:bcfe06ba3d64 205 return false;
AnnaBridge 188:bcfe06ba3d64 206 }
AnnaBridge 188:bcfe06ba3d64 207
AnnaBridge 174:b96e65c34a4d 208 void sleep_manager_sleep_auto(void)
AnnaBridge 174:b96e65c34a4d 209 {
AnnaBridge 184:08ed48f1de7f 210 #ifdef MBED_SLEEP_TRACING_ENABLED
AnnaBridge 184:08ed48f1de7f 211 sleep_tracker_print_stats();
AnnaBridge 184:08ed48f1de7f 212 #endif
AnnaBridge 174:b96e65c34a4d 213 core_util_critical_section_enter();
Anna Bridge 186:707f6e361f3e 214 us_timestamp_t start = read_us();
Anna Bridge 186:707f6e361f3e 215 bool deep = false;
Anna Bridge 186:707f6e361f3e 216
AnnaBridge 174:b96e65c34a4d 217 // debug profile should keep debuggers attached, no deep sleep allowed
AnnaBridge 174:b96e65c34a4d 218 #ifdef MBED_DEBUG
AnnaBridge 174:b96e65c34a4d 219 hal_sleep();
AnnaBridge 174:b96e65c34a4d 220 #else
AnnaBridge 174:b96e65c34a4d 221 if (sleep_manager_can_deep_sleep()) {
Anna Bridge 186:707f6e361f3e 222 deep = true;
AnnaBridge 174:b96e65c34a4d 223 hal_deepsleep();
AnnaBridge 174:b96e65c34a4d 224 } else {
AnnaBridge 174:b96e65c34a4d 225 hal_sleep();
AnnaBridge 174:b96e65c34a4d 226 }
AnnaBridge 174:b96e65c34a4d 227 #endif
Anna Bridge 186:707f6e361f3e 228
Anna Bridge 186:707f6e361f3e 229 us_timestamp_t end = read_us();
Anna Bridge 186:707f6e361f3e 230 if (true == deep) {
Anna Bridge 186:707f6e361f3e 231 deep_sleep_time += end - start;
Anna Bridge 186:707f6e361f3e 232 } else {
Anna Bridge 186:707f6e361f3e 233 sleep_time += end - start;
Anna Bridge 186:707f6e361f3e 234 }
AnnaBridge 174:b96e65c34a4d 235 core_util_critical_section_exit();
AnnaBridge 174:b96e65c34a4d 236 }
AnnaBridge 174:b96e65c34a4d 237
AnnaBridge 174:b96e65c34a4d 238 #else
AnnaBridge 174:b96e65c34a4d 239
AnnaBridge 174:b96e65c34a4d 240 // locking is valid only if DEVICE_SLEEP is defined
AnnaBridge 174:b96e65c34a4d 241 // we provide empty implementation
AnnaBridge 174:b96e65c34a4d 242
AnnaBridge 184:08ed48f1de7f 243 void sleep_manager_lock_deep_sleep_internal(void)
AnnaBridge 174:b96e65c34a4d 244 {
AnnaBridge 174:b96e65c34a4d 245
AnnaBridge 174:b96e65c34a4d 246 }
AnnaBridge 174:b96e65c34a4d 247
AnnaBridge 184:08ed48f1de7f 248 void sleep_manager_unlock_deep_sleep_internal(void)
AnnaBridge 174:b96e65c34a4d 249 {
AnnaBridge 174:b96e65c34a4d 250
AnnaBridge 174:b96e65c34a4d 251 }
AnnaBridge 174:b96e65c34a4d 252
AnnaBridge 174:b96e65c34a4d 253 bool sleep_manager_can_deep_sleep(void)
AnnaBridge 174:b96e65c34a4d 254 {
AnnaBridge 174:b96e65c34a4d 255 // no sleep implemented
AnnaBridge 174:b96e65c34a4d 256 return false;
AnnaBridge 174:b96e65c34a4d 257 }
AnnaBridge 174:b96e65c34a4d 258
AnnaBridge 174:b96e65c34a4d 259 #endif