Initial commit

Dependencies:   FastPWM

Committer:
lypinator
Date:
Wed Sep 16 01:11:49 2020 +0000
Revision:
0:bb348c97df44
Added PWM

Who changed what in which revision?

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