RTC auf true

Committer:
kevman
Date:
Wed Mar 13 11:03:24 2019 +0000
Revision:
2:7aab896b1a3b
Parent:
0:38ceb79fef03
2019-03-13

Who changed what in which revision?

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