mbed library sources. Supersedes mbed-src.

Fork of mbed-dev by mbed official

Committer:
pmcorreia
Date:
Tue Oct 09 14:42:37 2018 +0000
Revision:
187:fa51feb62426
Parent:
186:707f6e361f3e
Updated version to work with F446RE

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 184:08ed48f1de7f 17 #include "mbed_assert.h"
AnnaBridge 184:08ed48f1de7f 18 #include "mbed_power_mgmt.h"
AnnaBridge 174:b96e65c34a4d 19 #include "mbed_critical.h"
AnnaBridge 174:b96e65c34a4d 20 #include "sleep_api.h"
AnnaBridge 174:b96e65c34a4d 21 #include "mbed_error.h"
AnnaBridge 184:08ed48f1de7f 22 #include "mbed_debug.h"
Anna Bridge 186:707f6e361f3e 23 #include "mbed_stats.h"
Anna Bridge 186:707f6e361f3e 24 #include "lp_ticker_api.h"
AnnaBridge 174:b96e65c34a4d 25 #include <limits.h>
AnnaBridge 184:08ed48f1de7f 26 #include <stdio.h>
Anna Bridge 186:707f6e361f3e 27 #include "mbed_stats.h"
Anna Bridge 186:707f6e361f3e 28
AnnaBridge 174:b96e65c34a4d 29
AnnaBridge 174:b96e65c34a4d 30 #if DEVICE_SLEEP
AnnaBridge 174:b96e65c34a4d 31
AnnaBridge 174:b96e65c34a4d 32 // deep sleep locking counter. A target is allowed to deep sleep if counter == 0
AnnaBridge 174:b96e65c34a4d 33 static uint16_t deep_sleep_lock = 0U;
Anna Bridge 186:707f6e361f3e 34 static us_timestamp_t sleep_time = 0;
Anna Bridge 186:707f6e361f3e 35 static us_timestamp_t deep_sleep_time = 0;
Anna Bridge 186:707f6e361f3e 36
Anna Bridge 186:707f6e361f3e 37 #if defined(MBED_CPU_STATS_ENABLED) && defined(DEVICE_LPTICKER)
Anna Bridge 186:707f6e361f3e 38 static ticker_data_t *sleep_ticker = NULL;
Anna Bridge 186:707f6e361f3e 39 #endif
Anna Bridge 186:707f6e361f3e 40
Anna Bridge 186:707f6e361f3e 41 static inline us_timestamp_t read_us(void)
Anna Bridge 186:707f6e361f3e 42 {
Anna Bridge 186:707f6e361f3e 43 #if defined(MBED_CPU_STATS_ENABLED) && defined(DEVICE_LPTICKER)
Anna Bridge 186:707f6e361f3e 44 if (NULL == sleep_ticker) {
Anna Bridge 186:707f6e361f3e 45 sleep_ticker = (ticker_data_t *)get_lp_ticker_data();
Anna Bridge 186:707f6e361f3e 46 }
Anna Bridge 186:707f6e361f3e 47 return ticker_read_us(sleep_ticker);
Anna Bridge 186:707f6e361f3e 48 #else
Anna Bridge 186:707f6e361f3e 49 return 0;
Anna Bridge 186:707f6e361f3e 50 #endif
Anna Bridge 186:707f6e361f3e 51 }
Anna Bridge 186:707f6e361f3e 52
Anna Bridge 186:707f6e361f3e 53 us_timestamp_t mbed_time_idle(void)
Anna Bridge 186:707f6e361f3e 54 {
Anna Bridge 186:707f6e361f3e 55 return (sleep_time + deep_sleep_time);
Anna Bridge 186:707f6e361f3e 56 }
Anna Bridge 186:707f6e361f3e 57
Anna Bridge 186:707f6e361f3e 58 us_timestamp_t mbed_uptime(void)
Anna Bridge 186:707f6e361f3e 59 {
Anna Bridge 186:707f6e361f3e 60 return read_us();
Anna Bridge 186:707f6e361f3e 61 }
Anna Bridge 186:707f6e361f3e 62
Anna Bridge 186:707f6e361f3e 63 us_timestamp_t mbed_time_sleep(void)
Anna Bridge 186:707f6e361f3e 64 {
Anna Bridge 186:707f6e361f3e 65 return sleep_time;
Anna Bridge 186:707f6e361f3e 66 }
Anna Bridge 186:707f6e361f3e 67
Anna Bridge 186:707f6e361f3e 68 us_timestamp_t mbed_time_deepsleep(void)
Anna Bridge 186:707f6e361f3e 69 {
Anna Bridge 186:707f6e361f3e 70 return deep_sleep_time;
Anna Bridge 186:707f6e361f3e 71 }
AnnaBridge 174:b96e65c34a4d 72
AnnaBridge 184:08ed48f1de7f 73 #ifdef MBED_SLEEP_TRACING_ENABLED
AnnaBridge 184:08ed48f1de7f 74
AnnaBridge 184:08ed48f1de7f 75 // Number of drivers that can be stored in the structure
AnnaBridge 184:08ed48f1de7f 76 #define STATISTIC_COUNT 10
AnnaBridge 184:08ed48f1de7f 77
AnnaBridge 184:08ed48f1de7f 78 typedef struct sleep_statistic {
Anna Bridge 186:707f6e361f3e 79 const char *identifier;
AnnaBridge 184:08ed48f1de7f 80 uint8_t count;
AnnaBridge 184:08ed48f1de7f 81 } sleep_statistic_t;
AnnaBridge 184:08ed48f1de7f 82
AnnaBridge 184:08ed48f1de7f 83 static sleep_statistic_t sleep_stats[STATISTIC_COUNT];
AnnaBridge 184:08ed48f1de7f 84
AnnaBridge 184:08ed48f1de7f 85 static sleep_statistic_t* sleep_tracker_find(const char *const filename)
AnnaBridge 184:08ed48f1de7f 86 {
AnnaBridge 184:08ed48f1de7f 87 for (int i = 0; i < STATISTIC_COUNT; ++i) {
AnnaBridge 184:08ed48f1de7f 88 if (sleep_stats[i].identifier == filename) {
AnnaBridge 184:08ed48f1de7f 89 return &sleep_stats[i];
AnnaBridge 184:08ed48f1de7f 90 }
AnnaBridge 184:08ed48f1de7f 91 }
AnnaBridge 184:08ed48f1de7f 92
AnnaBridge 184:08ed48f1de7f 93 return NULL;
AnnaBridge 184:08ed48f1de7f 94 }
AnnaBridge 184:08ed48f1de7f 95
AnnaBridge 184:08ed48f1de7f 96 static sleep_statistic_t* sleep_tracker_add(const char* const filename)
AnnaBridge 184:08ed48f1de7f 97 {
AnnaBridge 184:08ed48f1de7f 98 for (int i = 0; i < STATISTIC_COUNT; ++i) {
AnnaBridge 184:08ed48f1de7f 99 if (sleep_stats[i].identifier == NULL) {
AnnaBridge 184:08ed48f1de7f 100 sleep_stats[i].identifier = filename;
AnnaBridge 184:08ed48f1de7f 101
AnnaBridge 184:08ed48f1de7f 102 return &sleep_stats[i];
AnnaBridge 184:08ed48f1de7f 103 }
AnnaBridge 184:08ed48f1de7f 104 }
AnnaBridge 184:08ed48f1de7f 105
AnnaBridge 184:08ed48f1de7f 106 debug("No free indexes left to use in mbed sleep tracker.\r\n");
AnnaBridge 184:08ed48f1de7f 107
AnnaBridge 184:08ed48f1de7f 108 return NULL;
AnnaBridge 184:08ed48f1de7f 109 }
AnnaBridge 184:08ed48f1de7f 110
AnnaBridge 184:08ed48f1de7f 111 static void sleep_tracker_print_stats(void)
AnnaBridge 184:08ed48f1de7f 112 {
AnnaBridge 184:08ed48f1de7f 113 debug("Sleep locks held:\r\n");
AnnaBridge 184:08ed48f1de7f 114 for (int i = 0; i < STATISTIC_COUNT; ++i) {
AnnaBridge 184:08ed48f1de7f 115 if (sleep_stats[i].count == 0) {
AnnaBridge 184:08ed48f1de7f 116 continue;
AnnaBridge 184:08ed48f1de7f 117 }
AnnaBridge 184:08ed48f1de7f 118
AnnaBridge 184:08ed48f1de7f 119 if (sleep_stats[i].identifier == NULL) {
AnnaBridge 184:08ed48f1de7f 120 return;
AnnaBridge 184:08ed48f1de7f 121 }
AnnaBridge 184:08ed48f1de7f 122
AnnaBridge 184:08ed48f1de7f 123 debug("[id: %s, count: %u]\r\n", sleep_stats[i].identifier,
AnnaBridge 184:08ed48f1de7f 124 sleep_stats[i].count);
AnnaBridge 184:08ed48f1de7f 125 }
AnnaBridge 184:08ed48f1de7f 126 }
AnnaBridge 184:08ed48f1de7f 127
Anna Bridge 186:707f6e361f3e 128 void sleep_tracker_lock(const char *const filename, int line)
AnnaBridge 184:08ed48f1de7f 129 {
AnnaBridge 184:08ed48f1de7f 130 sleep_statistic_t *stat = sleep_tracker_find(filename);
AnnaBridge 184:08ed48f1de7f 131
AnnaBridge 184:08ed48f1de7f 132 // Entry for this driver does not exist, create one.
AnnaBridge 184:08ed48f1de7f 133 if (stat == NULL) {
AnnaBridge 184:08ed48f1de7f 134 stat = sleep_tracker_add(filename);
AnnaBridge 184:08ed48f1de7f 135 }
AnnaBridge 184:08ed48f1de7f 136
AnnaBridge 184:08ed48f1de7f 137 core_util_atomic_incr_u8(&stat->count, 1);
AnnaBridge 184:08ed48f1de7f 138
AnnaBridge 184:08ed48f1de7f 139 debug("LOCK: %s, ln: %i, lock count: %u\r\n", filename, line, deep_sleep_lock);
AnnaBridge 184:08ed48f1de7f 140 }
AnnaBridge 184:08ed48f1de7f 141
AnnaBridge 184:08ed48f1de7f 142 void sleep_tracker_unlock(const char* const filename, int line)
AnnaBridge 184:08ed48f1de7f 143 {
AnnaBridge 184:08ed48f1de7f 144 sleep_statistic_t *stat = sleep_tracker_find(filename);
AnnaBridge 184:08ed48f1de7f 145
AnnaBridge 184:08ed48f1de7f 146 // Entry for this driver does not exist, something went wrong.
AnnaBridge 184:08ed48f1de7f 147 if (stat == NULL) {
AnnaBridge 184:08ed48f1de7f 148 debug("Unlocking sleep for driver that was not previously locked: %s, ln: %i\r\n", filename, line);
AnnaBridge 184:08ed48f1de7f 149 return;
AnnaBridge 184:08ed48f1de7f 150 }
AnnaBridge 184:08ed48f1de7f 151
AnnaBridge 184:08ed48f1de7f 152 core_util_atomic_decr_u8(&stat->count, 1);
AnnaBridge 184:08ed48f1de7f 153
AnnaBridge 184:08ed48f1de7f 154 debug("UNLOCK: %s, ln: %i, lock count: %u\r\n", filename, line, deep_sleep_lock);
AnnaBridge 184:08ed48f1de7f 155 }
AnnaBridge 184:08ed48f1de7f 156
AnnaBridge 184:08ed48f1de7f 157 #endif // MBED_SLEEP_TRACING_ENABLED
AnnaBridge 184:08ed48f1de7f 158
AnnaBridge 184:08ed48f1de7f 159 void sleep_manager_lock_deep_sleep_internal(void)
AnnaBridge 174:b96e65c34a4d 160 {
AnnaBridge 174:b96e65c34a4d 161 core_util_critical_section_enter();
AnnaBridge 174:b96e65c34a4d 162 if (deep_sleep_lock == USHRT_MAX) {
AnnaBridge 174:b96e65c34a4d 163 core_util_critical_section_exit();
Anna Bridge 186:707f6e361f3e 164 MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_HAL, MBED_ERROR_CODE_OVERFLOW), "DeepSleepLock overflow (> USHRT_MAX)", deep_sleep_lock);
AnnaBridge 174:b96e65c34a4d 165 }
AnnaBridge 174:b96e65c34a4d 166 core_util_atomic_incr_u16(&deep_sleep_lock, 1);
AnnaBridge 174:b96e65c34a4d 167 core_util_critical_section_exit();
AnnaBridge 174:b96e65c34a4d 168 }
AnnaBridge 174:b96e65c34a4d 169
AnnaBridge 184:08ed48f1de7f 170 void sleep_manager_unlock_deep_sleep_internal(void)
AnnaBridge 174:b96e65c34a4d 171 {
AnnaBridge 174:b96e65c34a4d 172 core_util_critical_section_enter();
AnnaBridge 174:b96e65c34a4d 173 if (deep_sleep_lock == 0) {
AnnaBridge 174:b96e65c34a4d 174 core_util_critical_section_exit();
Anna Bridge 186:707f6e361f3e 175 MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_HAL, MBED_ERROR_CODE_UNDERFLOW), "DeepSleepLock underflow (< 0)", deep_sleep_lock);
AnnaBridge 174:b96e65c34a4d 176 }
AnnaBridge 174:b96e65c34a4d 177 core_util_atomic_decr_u16(&deep_sleep_lock, 1);
AnnaBridge 174:b96e65c34a4d 178 core_util_critical_section_exit();
AnnaBridge 174:b96e65c34a4d 179 }
AnnaBridge 174:b96e65c34a4d 180
AnnaBridge 174:b96e65c34a4d 181 bool sleep_manager_can_deep_sleep(void)
AnnaBridge 174:b96e65c34a4d 182 {
AnnaBridge 174:b96e65c34a4d 183 return deep_sleep_lock == 0 ? true : false;
AnnaBridge 174:b96e65c34a4d 184 }
AnnaBridge 174:b96e65c34a4d 185
AnnaBridge 174:b96e65c34a4d 186 void sleep_manager_sleep_auto(void)
AnnaBridge 174:b96e65c34a4d 187 {
AnnaBridge 184:08ed48f1de7f 188 #ifdef MBED_SLEEP_TRACING_ENABLED
AnnaBridge 184:08ed48f1de7f 189 sleep_tracker_print_stats();
AnnaBridge 184:08ed48f1de7f 190 #endif
AnnaBridge 174:b96e65c34a4d 191 core_util_critical_section_enter();
Anna Bridge 186:707f6e361f3e 192 us_timestamp_t start = read_us();
Anna Bridge 186:707f6e361f3e 193 bool deep = false;
Anna Bridge 186:707f6e361f3e 194
AnnaBridge 174:b96e65c34a4d 195 // debug profile should keep debuggers attached, no deep sleep allowed
AnnaBridge 174:b96e65c34a4d 196 #ifdef MBED_DEBUG
AnnaBridge 174:b96e65c34a4d 197 hal_sleep();
AnnaBridge 174:b96e65c34a4d 198 #else
AnnaBridge 174:b96e65c34a4d 199 if (sleep_manager_can_deep_sleep()) {
Anna Bridge 186:707f6e361f3e 200 deep = true;
AnnaBridge 174:b96e65c34a4d 201 hal_deepsleep();
AnnaBridge 174:b96e65c34a4d 202 } else {
AnnaBridge 174:b96e65c34a4d 203 hal_sleep();
AnnaBridge 174:b96e65c34a4d 204 }
AnnaBridge 174:b96e65c34a4d 205 #endif
Anna Bridge 186:707f6e361f3e 206
Anna Bridge 186:707f6e361f3e 207 us_timestamp_t end = read_us();
Anna Bridge 186:707f6e361f3e 208 if (true == deep) {
Anna Bridge 186:707f6e361f3e 209 deep_sleep_time += end - start;
Anna Bridge 186:707f6e361f3e 210 } else {
Anna Bridge 186:707f6e361f3e 211 sleep_time += end - start;
Anna Bridge 186:707f6e361f3e 212 }
AnnaBridge 174:b96e65c34a4d 213 core_util_critical_section_exit();
AnnaBridge 174:b96e65c34a4d 214 }
AnnaBridge 174:b96e65c34a4d 215
AnnaBridge 174:b96e65c34a4d 216 #else
AnnaBridge 174:b96e65c34a4d 217
AnnaBridge 174:b96e65c34a4d 218 // locking is valid only if DEVICE_SLEEP is defined
AnnaBridge 174:b96e65c34a4d 219 // we provide empty implementation
AnnaBridge 174:b96e65c34a4d 220
AnnaBridge 184:08ed48f1de7f 221 void sleep_manager_lock_deep_sleep_internal(void)
AnnaBridge 174:b96e65c34a4d 222 {
AnnaBridge 174:b96e65c34a4d 223
AnnaBridge 174:b96e65c34a4d 224 }
AnnaBridge 174:b96e65c34a4d 225
AnnaBridge 184:08ed48f1de7f 226 void sleep_manager_unlock_deep_sleep_internal(void)
AnnaBridge 174:b96e65c34a4d 227 {
AnnaBridge 174:b96e65c34a4d 228
AnnaBridge 174:b96e65c34a4d 229 }
AnnaBridge 174:b96e65c34a4d 230
AnnaBridge 174:b96e65c34a4d 231 bool sleep_manager_can_deep_sleep(void)
AnnaBridge 174:b96e65c34a4d 232 {
AnnaBridge 174:b96e65c34a4d 233 // no sleep implemented
AnnaBridge 174:b96e65c34a4d 234 return false;
AnnaBridge 174:b96e65c34a4d 235 }
AnnaBridge 174:b96e65c34a4d 236
AnnaBridge 174:b96e65c34a4d 237 #endif