BA / SerialCom

Fork of OmniWheels by Gustav Atmel

Committer:
gustavatmel
Date:
Tue May 01 15:47:08 2018 +0000
Revision:
1:9c5af431a1f1
sdf

Who changed what in which revision?

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