From 0f6b73ae0f30d4aab8617fe62a6cc469bc5a352b Mon Sep 17 00:00:00 2001 From: Steven Cartmell Date: Mon, 5 Feb 2018 15:14:42 +0000 Subject: [PATCH 1/9] Add optional tracing to sleep manager lock/unlock Add tracing output to console to track when drivers lock and unlock deep sleep. Tracing output is enabled by configuring the 'SLEEP_PROFILING_ENABLED' at compile time. - Wrapped sleep_manager_lock/sleep_manager_unlock in a macro to conditionally call tracing functions when 'SLEEP_PROFILING_ENABLED' is set. - Define a global structure to track driver names and how many locks they hold in the sleep manager. --- hal/mbed_sleep_manager.c | 113 +++++++++++++++++++++++++++++++++-- platform/mbed_power_mgmt.h | 117 ++++++++++--------------------------- 2 files changed, 140 insertions(+), 90 deletions(-) diff --git a/hal/mbed_sleep_manager.c b/hal/mbed_sleep_manager.c index 8efd7bcc8e..58e1c13c3d 100644 --- a/hal/mbed_sleep_manager.c +++ b/hal/mbed_sleep_manager.c @@ -14,18 +14,123 @@ * limitations under the License. */ +#include "mbed_assert.h" #include "mbed_power_mgmt.h" #include "mbed_critical.h" #include "sleep_api.h" #include "mbed_error.h" #include +#include #if DEVICE_SLEEP // deep sleep locking counter. A target is allowed to deep sleep if counter == 0 static uint16_t deep_sleep_lock = 0U; -void sleep_manager_lock_deep_sleep(void) +#ifdef SLEEP_PROFILING_ENABLED + +// Length of the identifier extracted from the driver name to store for logging. +#define IDENTIFIER_WIDTH 7 +// Number of drivers that can be stored in the structure +#define STATISTIC_COUNT 10 + +typedef struct __PACKED sleep_statistic { + char identifier[IDENTIFIER_WIDTH]; + uint8_t count; +} sleep_statistic_t; + +static sleep_statistic_t sleep_stats[STATISTIC_COUNT]; + +static const char* strip_path(const char* const filename) +{ + char *output = strrchr(filename, '/'); + + if (output != NULL) { + return output + 1; + } + + output = strrchr(filename, '\\'); + + if (output != NULL) { + return output + 1; + } + + return filename; +} + +static size_t sleep_tracker_find_index(const char *const filename) +{ + char temp[IDENTIFIER_WIDTH]; + strncpy(temp, filename, IDENTIFIER_WIDTH); + temp[IDENTIFIER_WIDTH - 1] = '\0'; + + // Search for the a driver matching the current name and return it's index + for (int i = 0; i < STATISTIC_COUNT; ++i) { + if (strcmp(sleep_stats[i].identifier, temp) == 0) { + return i; + } + } + + // If no driver was found currently in the structure, find the first array + // index that hasn't been used by a driver and fill it, then return the + // index. + for (int i = 0; i < STATISTIC_COUNT; ++i) { + if (sleep_stats[i].identifier[0] == '\0') { + core_util_critical_section_enter(); + strncpy(sleep_stats[i].identifier, temp, sizeof(temp)); + core_util_critical_section_exit(); + + return i; + } + } + + // Panic if there are no free indexes left to track with + MBED_ASSERT(true); + + return -1; +} + +static void sleep_tracker_print_stats(void) +{ + for (int i = 0; i < STATISTIC_COUNT; ++i) { + if (sleep_stats[i].count == 0) { + continue; + } + + if (sleep_stats[i].identifier[0] == '\0') { + return; + } + + printf("[id: %s, count: %u]\r\n", sleep_stats[i].identifier, + sleep_stats[i].count); + } +} + +void sleep_tracker_lock(const char* const filename, int line) +{ + const char* const stripped_path = strip_path(filename); + size_t index = sleep_tracker_find_index(stripped_path); + + core_util_atomic_incr_u8(&sleep_stats[index].count, 1); + + printf("LOCK: %s, ln: %i, lock count: %u\r\n", stripped_path, line, deep_sleep_lock); +} + +void sleep_tracker_unlock(const char* const filename, int line) +{ + const char* const stripped_path = strip_path(filename); + size_t index = sleep_tracker_find_index(stripped_path); + + core_util_atomic_decr_u8(&sleep_stats[index].count, 1); + + printf("UNLOCK: %s, ln: %i, lock count: %u\r\n", stripped_path, line, deep_sleep_lock); + sleep_tracker_print_stats(); + printf("\r\n"); +} + +#endif // SLEEP_PROFILING_ENABLED + +void sleep_manager_lock_deep_sleep_internal(void) { core_util_critical_section_enter(); if (deep_sleep_lock == USHRT_MAX) { @@ -36,7 +141,7 @@ void sleep_manager_lock_deep_sleep(void) core_util_critical_section_exit(); } -void sleep_manager_unlock_deep_sleep(void) +void sleep_manager_unlock_deep_sleep_internal(void) { core_util_critical_section_enter(); if (deep_sleep_lock == 0) { @@ -73,12 +178,12 @@ void sleep_manager_sleep_auto(void) // locking is valid only if DEVICE_SLEEP is defined // we provide empty implementation -void sleep_manager_lock_deep_sleep(void) +void sleep_manager_lock_deep_sleep_internal(void) { } -void sleep_manager_unlock_deep_sleep(void) +void sleep_manager_unlock_deep_sleep_internal(void) { } diff --git a/platform/mbed_power_mgmt.h b/platform/mbed_power_mgmt.h index 9efbaca411..92f916f6e2 100644 --- a/platform/mbed_power_mgmt.h +++ b/platform/mbed_power_mgmt.h @@ -23,7 +23,7 @@ #ifndef MBED_POWER_MGMT_H #define MBED_POWER_MGMT_H -#include "hal/sleep_api.h" +#include "sleep_api.h" #include "mbed_toolchain.h" #include @@ -63,6 +63,34 @@ extern "C" { * } * @endcode */ +#ifdef SLEEP_PROFILING_ENABLED + +#define sleep_manager_lock_deep_sleep() \ + do \ + { \ + sleep_manager_lock_deep_sleep_internal(); \ + sleep_tracker_lock(__FILE__, __LINE__); \ + } while (0); + +#define sleep_manager_unlock_deep_sleep() \ + do \ + { \ + sleep_manager_unlock_deep_sleep_internal(); \ + sleep_tracker_unlock(__FILE__, __LINE__); \ + } while (0); + +void sleep_tracker_lock(const char *const filename, int line); +void sleep_tracker_unlock(const char *const filename, int line); + +#else + +#define sleep_manager_lock_deep_sleep() \ + sleep_manager_lock_deep_sleep_internal() + +#define sleep_manager_unlock_deep_sleep() \ + sleep_manager_lock_deep_sleep_internal() + +#endif // SLEEP_PROFILING_ENABLED /** Lock the deep sleep mode * @@ -76,7 +104,7 @@ extern "C" { * The lock is a counter, can be locked up to USHRT_MAX * This function is IRQ and thread safe */ -void sleep_manager_lock_deep_sleep(void); +void sleep_manager_lock_deep_sleep_internal(void); /** Unlock the deep sleep mode * @@ -85,96 +113,13 @@ void sleep_manager_lock_deep_sleep(void); * The lock is a counter, should be equally unlocked as locked * This function is IRQ and thread safe */ -void sleep_manager_unlock_deep_sleep(void); +void sleep_manager_unlock_deep_sleep_internal(void); /** Get the status of deep sleep allowance for a target * * @return true if a target can go to deepsleep, false otherwise */ bool sleep_manager_can_deep_sleep(void); - -/** Enter auto selected sleep mode. It chooses the sleep or deeepsleep modes based - * on the deepsleep locking counter - * - * This function is IRQ and thread safe - * - * @note - * If MBED_DEBUG is defined, only hal_sleep is allowed. This ensures the debugger - * to be active for debug modes. - * - */ -void sleep_manager_sleep_auto(void); - -/** Send the microcontroller to sleep - * - * @note This function can be a noop if not implemented by the platform. - * @note This function will be a noop in debug mode (debug build profile when MBED_DEBUG is defined). - * @note This function will be a noop while uVisor is in use. - * @note This function will be a noop if the following conditions are met: - * - The RTOS is present - * - The processor turn off the Systick clock during sleep - * - The target does not implement tickless mode - * - * The processor is setup ready for sleep, and sent to sleep using __WFI(). In this mode, the - * system clock to the core is stopped until a reset or an interrupt occurs. This eliminates - * dynamic power used by the processor, memory systems and buses. The processor, peripheral and - * memory state are maintained, and the peripherals continue to work and can generate interrupts. - * - * The processor can be woken up by any internal peripheral interrupt or external pin interrupt. - * - * @note - * The mbed interface semihosting is disconnected as part of going to sleep, and can not be restored. - * Flash re-programming and the USB serial port will remain active, but the mbed program will no longer be - * able to access the LocalFileSystem - */ -static inline void sleep(void) -{ -#if !(defined(FEATURE_UVISOR) && defined(TARGET_UVISOR_SUPPORTED)) -#if DEVICE_SLEEP -#if (MBED_CONF_RTOS_PRESENT == 0) || (DEVICE_STCLK_OFF_DURING_SLEEP == 0) || defined(MBED_TICKLESS) - sleep_manager_sleep_auto(); -#endif /* (MBED_CONF_RTOS_PRESENT == 0) || (DEVICE_STCLK_OFF_DURING_SLEEP == 0) || defined(MBED_TICKLESS) */ -#endif /* DEVICE_SLEEP */ -#endif /* !(defined(FEATURE_UVISOR) && defined(TARGET_UVISOR_SUPPORTED)) */ -} - -/** Send the microcontroller to deep sleep - * - * @note This function can be a noop if not implemented by the platform. - * @note This function will be a noop in debug mode (debug build profile when MBED_DEBUG is defined) - * @note This function will be a noop while uVisor is in use. - * - * This processor is setup ready for deep sleep, and sent to sleep. This mode - * has the same sleep features as sleep plus it powers down peripherals and clocks. All state - * is still maintained. - * - * The processor can only be woken up by an external interrupt on a pin or a watchdog timer. - * - * @note - * The mbed interface semihosting is disconnected as part of going to sleep, and can not be restored. - * Flash re-programming and the USB serial port will remain active, but the mbed program will no longer be - * able to access the LocalFileSystem - */ - -MBED_DEPRECATED_SINCE("mbed-os-5.6", "One entry point for an application, use sleep()") -static inline void deepsleep(void) -{ -#if !(defined(FEATURE_UVISOR) && defined(TARGET_UVISOR_SUPPORTED)) -#if DEVICE_SLEEP - sleep_manager_sleep_auto(); -#endif /* DEVICE_SLEEP */ -#endif /* !(defined(FEATURE_UVISOR) && defined(TARGET_UVISOR_SUPPORTED)) */ -} - -/** Resets the processor and most of the sub-system - * - * @note Does not affect the debug sub-system - */ -static inline void system_reset(void) -{ - NVIC_SystemReset(); -} - #ifdef __cplusplus } #endif From 74bdf1c3a32d1c08e45d730391f01075f8574eaf Mon Sep 17 00:00:00 2001 From: Steven Cartmell Date: Fri, 23 Feb 2018 10:03:35 +0000 Subject: [PATCH 2/9] Rename SLEEP_PROFILING_ENABLED to MBED_SLEEP_STATS_ENABLED --- hal/mbed_sleep_manager.c | 4 +- platform/mbed_sleep.h | 97 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+), 2 deletions(-) diff --git a/hal/mbed_sleep_manager.c b/hal/mbed_sleep_manager.c index 58e1c13c3d..95dc9dc6fd 100644 --- a/hal/mbed_sleep_manager.c +++ b/hal/mbed_sleep_manager.c @@ -27,7 +27,7 @@ // deep sleep locking counter. A target is allowed to deep sleep if counter == 0 static uint16_t deep_sleep_lock = 0U; -#ifdef SLEEP_PROFILING_ENABLED +#ifdef MBED_SLEEP_STATS_ENABLED // Length of the identifier extracted from the driver name to store for logging. #define IDENTIFIER_WIDTH 7 @@ -128,7 +128,7 @@ void sleep_tracker_unlock(const char* const filename, int line) printf("\r\n"); } -#endif // SLEEP_PROFILING_ENABLED +#endif // MBED_SLEEP_STATS_ENABLED void sleep_manager_lock_deep_sleep_internal(void) { diff --git a/platform/mbed_sleep.h b/platform/mbed_sleep.h index c29549f331..b3388855a5 100644 --- a/platform/mbed_sleep.h +++ b/platform/mbed_sleep.h @@ -14,6 +14,103 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +<<<<<<< HEAD +======= +#ifndef MBED_SLEEP_H +#define MBED_SLEEP_H + +#include "sleep_api.h" +#include "mbed_toolchain.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** Sleep manager API + * The sleep manager provides API to automatically select sleep mode. + * + * There are two sleep modes: + * - sleep + * - deepsleep + * + * Use locking/unlocking deepsleep for drivers that depend on features that + * are not allowed (=disabled) during the deepsleep. For instance, high frequency + * clocks. + * + * Example: + * @code + * + * void driver::handler() + * { + * if (_sensor.get_event()) { + * // any event - we are finished, unlock the deepsleep + * sleep_manager_unlock_deep_sleep(); + * _callback(); + * } + * } + * + * int driver::measure(event_t event, callback_t& callback) + * { + * _callback = callback; + * sleep_manager_lock_deep_sleep(); + * // start async transaction, we are waiting for an event + * return _sensor.start(event, callback); + * } + * @endcode + */ +#ifdef MBED_SLEEP_STATS_ENABLED + +#define sleep_manager_lock_deep_sleep() \ + do \ + { \ + sleep_manager_lock_deep_sleep_internal(); \ + sleep_tracker_lock(__FILE__, __LINE__); \ + } while (0); + +#define sleep_manager_unlock_deep_sleep() \ + do \ + { \ + sleep_manager_unlock_deep_sleep_internal(); \ + sleep_tracker_unlock(__FILE__, __LINE__); \ + } while (0); + +void sleep_tracker_lock(const char *const filename, int line); +void sleep_tracker_unlock(const char *const filename, int line); + +#else + +#define sleep_manager_lock_deep_sleep() \ + sleep_manager_lock_deep_sleep_internal() + +#define sleep_manager_unlock_deep_sleep() \ + sleep_manager_lock_deep_sleep_internal() + +#endif // MBED_SLEEP_STATS_ENABLED + +/** Lock the deep sleep mode + * + * This locks the automatic deep mode selection. + * sleep_manager_sleep_auto() will ignore deepsleep mode if + * this function is invoked at least once (the internal counter is non-zero) + * + * Use this locking mechanism for interrupt driven API that are + * running in the background and deepsleep could affect their functionality + * + * The lock is a counter, can be locked up to USHRT_MAX + * This function is IRQ and thread safe + */ +void sleep_manager_lock_deep_sleep_internal(void); + +/** Unlock the deep sleep mode + * + * Use unlocking in pair with sleep_manager_lock_deep_sleep(). + * + * The lock is a counter, should be equally unlocked as locked + * This function is IRQ and thread safe + */ +void sleep_manager_unlock_deep_sleep_internal(void); +>>>>>>> Rename SLEEP_PROFILING_ENABLED to MBED_SLEEP_STATS_ENABLED #ifndef MBED_MBED_SLEEP_H #define MBED_MBED_SLEEP_H From 21e5f1134de1e1dfd17526abbaf08ebc789df046 Mon Sep 17 00:00:00 2001 From: Steven Cartmell Date: Mon, 26 Feb 2018 13:14:08 +0000 Subject: [PATCH 3/9] Remove '_PACKED' keyword from sleep statistic structure --- hal/mbed_sleep_manager.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hal/mbed_sleep_manager.c b/hal/mbed_sleep_manager.c index 95dc9dc6fd..14acde48b1 100644 --- a/hal/mbed_sleep_manager.c +++ b/hal/mbed_sleep_manager.c @@ -34,7 +34,7 @@ static uint16_t deep_sleep_lock = 0U; // Number of drivers that can be stored in the structure #define STATISTIC_COUNT 10 -typedef struct __PACKED sleep_statistic { +typedef struct sleep_statistic { char identifier[IDENTIFIER_WIDTH]; uint8_t count; } sleep_statistic_t; From 5a4027b71d60e8905d6fc44900b887be9c01833f Mon Sep 17 00:00:00 2001 From: Steven Cartmell Date: Tue, 27 Feb 2018 10:48:34 +0000 Subject: [PATCH 4/9] Remove newline printf from sleep manager --- hal/mbed_sleep_manager.c | 1 - 1 file changed, 1 deletion(-) diff --git a/hal/mbed_sleep_manager.c b/hal/mbed_sleep_manager.c index 14acde48b1..bc710e497d 100644 --- a/hal/mbed_sleep_manager.c +++ b/hal/mbed_sleep_manager.c @@ -125,7 +125,6 @@ void sleep_tracker_unlock(const char* const filename, int line) printf("UNLOCK: %s, ln: %i, lock count: %u\r\n", stripped_path, line, deep_sleep_lock); sleep_tracker_print_stats(); - printf("\r\n"); } #endif // MBED_SLEEP_STATS_ENABLED From bd23625d23f918e065231bf0a2069c5e6d611243 Mon Sep 17 00:00:00 2001 From: Steven Cartmell Date: Tue, 27 Feb 2018 11:35:24 +0000 Subject: [PATCH 5/9] Rename SLEEP_STATS_ENABLED to SLEEP_TRACING_ENABLED --- hal/mbed_sleep_manager.c | 10 +++++++--- platform/mbed_sleep.h | 10 +++++----- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/hal/mbed_sleep_manager.c b/hal/mbed_sleep_manager.c index bc710e497d..30f472d925 100644 --- a/hal/mbed_sleep_manager.c +++ b/hal/mbed_sleep_manager.c @@ -14,8 +14,12 @@ * limitations under the License. */ +<<<<<<< HEAD #include "mbed_assert.h" #include "mbed_power_mgmt.h" +======= +#include "mbed_sleep.h" +>>>>>>> Rename SLEEP_STATS_ENABLED to SLEEP_TRACING_ENABLED #include "mbed_critical.h" #include "sleep_api.h" #include "mbed_error.h" @@ -27,7 +31,7 @@ // deep sleep locking counter. A target is allowed to deep sleep if counter == 0 static uint16_t deep_sleep_lock = 0U; -#ifdef MBED_SLEEP_STATS_ENABLED +#ifdef MBED_SLEEP_TRACING_ENABLED // Length of the identifier extracted from the driver name to store for logging. #define IDENTIFIER_WIDTH 7 @@ -85,7 +89,7 @@ static size_t sleep_tracker_find_index(const char *const filename) } // Panic if there are no free indexes left to track with - MBED_ASSERT(true); + error("No free indexes left to use in mbed stats tracker"); return -1; } @@ -127,7 +131,7 @@ void sleep_tracker_unlock(const char* const filename, int line) sleep_tracker_print_stats(); } -#endif // MBED_SLEEP_STATS_ENABLED +#endif // MBED_SLEEP_TRACING_ENABLED void sleep_manager_lock_deep_sleep_internal(void) { diff --git a/platform/mbed_sleep.h b/platform/mbed_sleep.h index b3388855a5..1086324e94 100644 --- a/platform/mbed_sleep.h +++ b/platform/mbed_sleep.h @@ -59,7 +59,10 @@ extern "C" { * } * @endcode */ -#ifdef MBED_SLEEP_STATS_ENABLED +#ifdef MBED_SLEEP_TRACING_ENABLED + +void sleep_tracker_lock(const char *const filename, int line); +void sleep_tracker_unlock(const char *const filename, int line); #define sleep_manager_lock_deep_sleep() \ do \ @@ -75,9 +78,6 @@ extern "C" { sleep_tracker_unlock(__FILE__, __LINE__); \ } while (0); -void sleep_tracker_lock(const char *const filename, int line); -void sleep_tracker_unlock(const char *const filename, int line); - #else #define sleep_manager_lock_deep_sleep() \ @@ -86,7 +86,7 @@ void sleep_tracker_unlock(const char *const filename, int line); #define sleep_manager_unlock_deep_sleep() \ sleep_manager_lock_deep_sleep_internal() -#endif // MBED_SLEEP_STATS_ENABLED +#endif // MBED_SLEEP_TRACING_ENABLED /** Lock the deep sleep mode * From 076548aa6b2db44025efcd40e0f9843e85e87dfe Mon Sep 17 00:00:00 2001 From: Steven Cartmell Date: Thu, 1 Mar 2018 17:03:28 +0000 Subject: [PATCH 6/9] Split find/insert sleep tracker function into two seperate functions. Throw an error when trying to unlock driver that was not previously locked. --- hal/mbed_sleep_manager.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/hal/mbed_sleep_manager.c b/hal/mbed_sleep_manager.c index 30f472d925..cd3cd83eb8 100644 --- a/hal/mbed_sleep_manager.c +++ b/hal/mbed_sleep_manager.c @@ -75,9 +75,15 @@ static size_t sleep_tracker_find_index(const char *const filename) } } - // If no driver was found currently in the structure, find the first array - // index that hasn't been used by a driver and fill it, then return the - // index. + return -1; +} + +static size_t sleep_tracker_add(const char* const filename) +{ + char temp[IDENTIFIER_WIDTH]; + strncpy(temp, filename, IDENTIFIER_WIDTH); + temp[IDENTIFIER_WIDTH - 1] = '\0'; + for (int i = 0; i < STATISTIC_COUNT; ++i) { if (sleep_stats[i].identifier[0] == '\0') { core_util_critical_section_enter(); @@ -113,8 +119,14 @@ static void sleep_tracker_print_stats(void) void sleep_tracker_lock(const char* const filename, int line) { const char* const stripped_path = strip_path(filename); + size_t index = sleep_tracker_find_index(stripped_path); + // Entry for this driver does not exist, create one. + if (index == -1) { + index = sleep_tracker_add(filename); + } + core_util_atomic_incr_u8(&sleep_stats[index].count, 1); printf("LOCK: %s, ln: %i, lock count: %u\r\n", stripped_path, line, deep_sleep_lock); @@ -125,6 +137,11 @@ void sleep_tracker_unlock(const char* const filename, int line) const char* const stripped_path = strip_path(filename); size_t index = sleep_tracker_find_index(stripped_path); + // Entry for this driver does not exist, something went wrong. + if (index == -1) { + error("Unlocking sleep for driver that was not previously locked."); + } + core_util_atomic_decr_u8(&sleep_stats[index].count, 1); printf("UNLOCK: %s, ln: %i, lock count: %u\r\n", stripped_path, line, deep_sleep_lock); From fed511562411218dac9b59a0c5479d9200e4bc00 Mon Sep 17 00:00:00 2001 From: Steven Cartmell Date: Thu, 1 Mar 2018 17:14:41 +0000 Subject: [PATCH 7/9] Return pointer to sleep tracker array element instead of an index --- hal/mbed_sleep_manager.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/hal/mbed_sleep_manager.c b/hal/mbed_sleep_manager.c index cd3cd83eb8..62e234604d 100644 --- a/hal/mbed_sleep_manager.c +++ b/hal/mbed_sleep_manager.c @@ -62,7 +62,7 @@ static const char* strip_path(const char* const filename) return filename; } -static size_t sleep_tracker_find_index(const char *const filename) +static sleep_statistic_t* sleep_tracker_find(const char *const filename) { char temp[IDENTIFIER_WIDTH]; strncpy(temp, filename, IDENTIFIER_WIDTH); @@ -71,14 +71,14 @@ static size_t sleep_tracker_find_index(const char *const filename) // Search for the a driver matching the current name and return it's index for (int i = 0; i < STATISTIC_COUNT; ++i) { if (strcmp(sleep_stats[i].identifier, temp) == 0) { - return i; + return &sleep_stats[i]; } } - return -1; + return NULL; } -static size_t sleep_tracker_add(const char* const filename) +static sleep_statistic_t* sleep_tracker_add(const char* const filename) { char temp[IDENTIFIER_WIDTH]; strncpy(temp, filename, IDENTIFIER_WIDTH); @@ -90,14 +90,14 @@ static size_t sleep_tracker_add(const char* const filename) strncpy(sleep_stats[i].identifier, temp, sizeof(temp)); core_util_critical_section_exit(); - return i; + return &sleep_stats[i]; } } // Panic if there are no free indexes left to track with error("No free indexes left to use in mbed stats tracker"); - return -1; + return NULL; } static void sleep_tracker_print_stats(void) @@ -120,14 +120,14 @@ void sleep_tracker_lock(const char* const filename, int line) { const char* const stripped_path = strip_path(filename); - size_t index = sleep_tracker_find_index(stripped_path); + sleep_statistic_t* stat = sleep_tracker_find(stripped_path); // Entry for this driver does not exist, create one. - if (index == -1) { - index = sleep_tracker_add(filename); + if (stat == NULL) { + stat = sleep_tracker_add(filename); } - core_util_atomic_incr_u8(&sleep_stats[index].count, 1); + core_util_atomic_incr_u8(&stat->count, 1); printf("LOCK: %s, ln: %i, lock count: %u\r\n", stripped_path, line, deep_sleep_lock); } @@ -135,14 +135,14 @@ void sleep_tracker_lock(const char* const filename, int line) void sleep_tracker_unlock(const char* const filename, int line) { const char* const stripped_path = strip_path(filename); - size_t index = sleep_tracker_find_index(stripped_path); + sleep_statistic_t* stat = sleep_tracker_find(stripped_path); // Entry for this driver does not exist, something went wrong. - if (index == -1) { + if (stat == NULL) { error("Unlocking sleep for driver that was not previously locked."); } - core_util_atomic_decr_u8(&sleep_stats[index].count, 1); + core_util_atomic_decr_u8(&stat->count, 1); printf("UNLOCK: %s, ln: %i, lock count: %u\r\n", stripped_path, line, deep_sleep_lock); sleep_tracker_print_stats(); From 206cc299e01e1181842676fd45164953e0dfec67 Mon Sep 17 00:00:00 2001 From: Steven Cartmell Date: Thu, 1 Mar 2018 17:28:18 +0000 Subject: [PATCH 8/9] Fix merge conflict mishap --- hal/mbed_sleep_manager.c | 4 -- platform/mbed_power_mgmt.h | 84 ++++++++++++++++++++++++++++++++ platform/mbed_sleep.h | 98 -------------------------------------- 3 files changed, 84 insertions(+), 102 deletions(-) diff --git a/hal/mbed_sleep_manager.c b/hal/mbed_sleep_manager.c index 62e234604d..4a521f348b 100644 --- a/hal/mbed_sleep_manager.c +++ b/hal/mbed_sleep_manager.c @@ -14,12 +14,8 @@ * limitations under the License. */ -<<<<<<< HEAD #include "mbed_assert.h" #include "mbed_power_mgmt.h" -======= -#include "mbed_sleep.h" ->>>>>>> Rename SLEEP_STATS_ENABLED to SLEEP_TRACING_ENABLED #include "mbed_critical.h" #include "sleep_api.h" #include "mbed_error.h" diff --git a/platform/mbed_power_mgmt.h b/platform/mbed_power_mgmt.h index 92f916f6e2..292ba3eab7 100644 --- a/platform/mbed_power_mgmt.h +++ b/platform/mbed_power_mgmt.h @@ -120,6 +120,90 @@ void sleep_manager_unlock_deep_sleep_internal(void); * @return true if a target can go to deepsleep, false otherwise */ bool sleep_manager_can_deep_sleep(void); + + +/** Enter auto selected sleep mode. It chooses the sleep or deeepsleep modes based + * on the deepsleep locking counter + * + * This function is IRQ and thread safe + * + * @note + * If MBED_DEBUG is defined, only hal_sleep is allowed. This ensures the debugger + * to be active for debug modes. + * + */ +void sleep_manager_sleep_auto(void); + +/** Send the microcontroller to sleep + * + * @note This function can be a noop if not implemented by the platform. + * @note This function will be a noop in debug mode (debug build profile when MBED_DEBUG is defined). + * @note This function will be a noop while uVisor is in use. + * @note This function will be a noop if the following conditions are met: + * - The RTOS is present + * - The processor turn off the Systick clock during sleep + * - The target does not implement tickless mode + * + * The processor is setup ready for sleep, and sent to sleep using __WFI(). In this mode, the + * system clock to the core is stopped until a reset or an interrupt occurs. This eliminates + * dynamic power used by the processor, memory systems and buses. The processor, peripheral and + * memory state are maintained, and the peripherals continue to work and can generate interrupts. + * + * The processor can be woken up by any internal peripheral interrupt or external pin interrupt. + * + * @note + * The mbed interface semihosting is disconnected as part of going to sleep, and can not be restored. + * Flash re-programming and the USB serial port will remain active, but the mbed program will no longer be + * able to access the LocalFileSystem + */ +static inline void sleep(void) +{ +#if !(defined(FEATURE_UVISOR) && defined(TARGET_UVISOR_SUPPORTED)) +#if DEVICE_SLEEP +#if (MBED_CONF_RTOS_PRESENT == 0) || (DEVICE_STCLK_OFF_DURING_SLEEP == 0) || defined(MBED_TICKLESS) + sleep_manager_sleep_auto(); +#endif /* (MBED_CONF_RTOS_PRESENT == 0) || (DEVICE_STCLK_OFF_DURING_SLEEP == 0) || defined(MBED_TICKLESS) */ +#endif /* DEVICE_SLEEP */ +#endif /* !(defined(FEATURE_UVISOR) && defined(TARGET_UVISOR_SUPPORTED)) */ +} + +/** Send the microcontroller to deep sleep + * + * @note This function can be a noop if not implemented by the platform. + * @note This function will be a noop in debug mode (debug build profile when MBED_DEBUG is defined) + * @note This function will be a noop while uVisor is in use. + * + * This processor is setup ready for deep sleep, and sent to sleep. This mode + * has the same sleep features as sleep plus it powers down peripherals and clocks. All state + * is still maintained. + * + * The processor can only be woken up by an external interrupt on a pin or a watchdog timer. + * + * @note + * The mbed interface semihosting is disconnected as part of going to sleep, and can not be restored. + * Flash re-programming and the USB serial port will remain active, but the mbed program will no longer be + * able to access the LocalFileSystem + */ + +MBED_DEPRECATED_SINCE("mbed-os-5.6", "One entry point for an application, use sleep()") +static inline void deepsleep(void) +{ +#if !(defined(FEATURE_UVISOR) && defined(TARGET_UVISOR_SUPPORTED)) +#if DEVICE_SLEEP + sleep_manager_sleep_auto(); +#endif /* DEVICE_SLEEP */ +#endif /* !(defined(FEATURE_UVISOR) && defined(TARGET_UVISOR_SUPPORTED)) */ +} + +/** Resets the processor and most of the sub-system + * + * @note Does not affect the debug sub-system + */ +static inline void system_reset(void) +{ + NVIC_SystemReset(); +} + #ifdef __cplusplus } #endif diff --git a/platform/mbed_sleep.h b/platform/mbed_sleep.h index 1086324e94..89b8b4ec3f 100644 --- a/platform/mbed_sleep.h +++ b/platform/mbed_sleep.h @@ -14,104 +14,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -<<<<<<< HEAD -======= -#ifndef MBED_SLEEP_H -#define MBED_SLEEP_H - -#include "sleep_api.h" -#include "mbed_toolchain.h" -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** Sleep manager API - * The sleep manager provides API to automatically select sleep mode. - * - * There are two sleep modes: - * - sleep - * - deepsleep - * - * Use locking/unlocking deepsleep for drivers that depend on features that - * are not allowed (=disabled) during the deepsleep. For instance, high frequency - * clocks. - * - * Example: - * @code - * - * void driver::handler() - * { - * if (_sensor.get_event()) { - * // any event - we are finished, unlock the deepsleep - * sleep_manager_unlock_deep_sleep(); - * _callback(); - * } - * } - * - * int driver::measure(event_t event, callback_t& callback) - * { - * _callback = callback; - * sleep_manager_lock_deep_sleep(); - * // start async transaction, we are waiting for an event - * return _sensor.start(event, callback); - * } - * @endcode - */ -#ifdef MBED_SLEEP_TRACING_ENABLED - -void sleep_tracker_lock(const char *const filename, int line); -void sleep_tracker_unlock(const char *const filename, int line); - -#define sleep_manager_lock_deep_sleep() \ - do \ - { \ - sleep_manager_lock_deep_sleep_internal(); \ - sleep_tracker_lock(__FILE__, __LINE__); \ - } while (0); - -#define sleep_manager_unlock_deep_sleep() \ - do \ - { \ - sleep_manager_unlock_deep_sleep_internal(); \ - sleep_tracker_unlock(__FILE__, __LINE__); \ - } while (0); - -#else - -#define sleep_manager_lock_deep_sleep() \ - sleep_manager_lock_deep_sleep_internal() - -#define sleep_manager_unlock_deep_sleep() \ - sleep_manager_lock_deep_sleep_internal() - -#endif // MBED_SLEEP_TRACING_ENABLED - -/** Lock the deep sleep mode - * - * This locks the automatic deep mode selection. - * sleep_manager_sleep_auto() will ignore deepsleep mode if - * this function is invoked at least once (the internal counter is non-zero) - * - * Use this locking mechanism for interrupt driven API that are - * running in the background and deepsleep could affect their functionality - * - * The lock is a counter, can be locked up to USHRT_MAX - * This function is IRQ and thread safe - */ -void sleep_manager_lock_deep_sleep_internal(void); - -/** Unlock the deep sleep mode - * - * Use unlocking in pair with sleep_manager_lock_deep_sleep(). - * - * The lock is a counter, should be equally unlocked as locked - * This function is IRQ and thread safe - */ -void sleep_manager_unlock_deep_sleep_internal(void); ->>>>>>> Rename SLEEP_PROFILING_ENABLED to MBED_SLEEP_STATS_ENABLED - #ifndef MBED_MBED_SLEEP_H #define MBED_MBED_SLEEP_H From d6f57bc3e80ca8a8c6be624b6c8e1fc3f7a61645 Mon Sep 17 00:00:00 2001 From: Bartek Szatkowski Date: Thu, 1 Mar 2018 23:39:24 +0000 Subject: [PATCH 9/9] Fix review comments and merge issues --- hal/mbed_sleep_manager.c | 22 +++++++++++++--------- platform/mbed_power_mgmt.h | 12 ++++++------ 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/hal/mbed_sleep_manager.c b/hal/mbed_sleep_manager.c index 4a521f348b..79fbc58d52 100644 --- a/hal/mbed_sleep_manager.c +++ b/hal/mbed_sleep_manager.c @@ -19,6 +19,7 @@ #include "mbed_critical.h" #include "sleep_api.h" #include "mbed_error.h" +#include "mbed_debug.h" #include #include @@ -30,7 +31,7 @@ static uint16_t deep_sleep_lock = 0U; #ifdef MBED_SLEEP_TRACING_ENABLED // Length of the identifier extracted from the driver name to store for logging. -#define IDENTIFIER_WIDTH 7 +#define IDENTIFIER_WIDTH 15 // Number of drivers that can be stored in the structure #define STATISTIC_COUNT 10 @@ -90,14 +91,14 @@ static sleep_statistic_t* sleep_tracker_add(const char* const filename) } } - // Panic if there are no free indexes left to track with - error("No free indexes left to use in mbed stats tracker"); + debug("No free indexes left to use in mbed sleep tracker.\r\n"); return NULL; } static void sleep_tracker_print_stats(void) { + debug("Sleep locks held:\r\n"); for (int i = 0; i < STATISTIC_COUNT; ++i) { if (sleep_stats[i].count == 0) { continue; @@ -107,7 +108,7 @@ static void sleep_tracker_print_stats(void) return; } - printf("[id: %s, count: %u]\r\n", sleep_stats[i].identifier, + debug("[id: %s, count: %u]\r\n", sleep_stats[i].identifier, sleep_stats[i].count); } } @@ -120,12 +121,12 @@ void sleep_tracker_lock(const char* const filename, int line) // Entry for this driver does not exist, create one. if (stat == NULL) { - stat = sleep_tracker_add(filename); + stat = sleep_tracker_add(stripped_path); } core_util_atomic_incr_u8(&stat->count, 1); - printf("LOCK: %s, ln: %i, lock count: %u\r\n", stripped_path, line, deep_sleep_lock); + debug("LOCK: %s, ln: %i, lock count: %u\r\n", stripped_path, line, deep_sleep_lock); } void sleep_tracker_unlock(const char* const filename, int line) @@ -135,13 +136,13 @@ void sleep_tracker_unlock(const char* const filename, int line) // Entry for this driver does not exist, something went wrong. if (stat == NULL) { - error("Unlocking sleep for driver that was not previously locked."); + debug("Unlocking sleep for driver that was not previously locked: %s, ln: %i\r\n", stripped_path, line); + return; } core_util_atomic_decr_u8(&stat->count, 1); - printf("UNLOCK: %s, ln: %i, lock count: %u\r\n", stripped_path, line, deep_sleep_lock); - sleep_tracker_print_stats(); + debug("UNLOCK: %s, ln: %i, lock count: %u\r\n", stripped_path, line, deep_sleep_lock); } #endif // MBED_SLEEP_TRACING_ENABLED @@ -175,6 +176,9 @@ bool sleep_manager_can_deep_sleep(void) void sleep_manager_sleep_auto(void) { +#ifdef MBED_SLEEP_TRACING_ENABLED + sleep_tracker_print_stats(); +#endif core_util_critical_section_enter(); // debug profile should keep debuggers attached, no deep sleep allowed #ifdef MBED_DEBUG diff --git a/platform/mbed_power_mgmt.h b/platform/mbed_power_mgmt.h index 292ba3eab7..c70fb515f9 100644 --- a/platform/mbed_power_mgmt.h +++ b/platform/mbed_power_mgmt.h @@ -63,7 +63,10 @@ extern "C" { * } * @endcode */ -#ifdef SLEEP_PROFILING_ENABLED +#ifdef MBED_SLEEP_TRACING_ENABLED + +void sleep_tracker_lock(const char *const filename, int line); +void sleep_tracker_unlock(const char *const filename, int line); #define sleep_manager_lock_deep_sleep() \ do \ @@ -79,18 +82,15 @@ extern "C" { sleep_tracker_unlock(__FILE__, __LINE__); \ } while (0); -void sleep_tracker_lock(const char *const filename, int line); -void sleep_tracker_unlock(const char *const filename, int line); - #else #define sleep_manager_lock_deep_sleep() \ sleep_manager_lock_deep_sleep_internal() #define sleep_manager_unlock_deep_sleep() \ - sleep_manager_lock_deep_sleep_internal() + sleep_manager_unlock_deep_sleep_internal() -#endif // SLEEP_PROFILING_ENABLED +#endif // MBED_SLEEP_TRACING_ENABLED /** Lock the deep sleep mode *