Skip to content

Commit a137444

Browse files
authored
Merge pull request #6142 from scartmell-arm/feature-deep-sleep-tracing
Add optional tracing to sleep manager lock/unlock
2 parents 6e1cd9b + d6f57bc commit a137444

File tree

3 files changed

+161
-8
lines changed

3 files changed

+161
-8
lines changed

hal/mbed_sleep_manager.c

Lines changed: 129 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,140 @@
1414
* limitations under the License.
1515
*/
1616

17+
#include "mbed_assert.h"
1718
#include "mbed_power_mgmt.h"
1819
#include "mbed_critical.h"
1920
#include "sleep_api.h"
2021
#include "mbed_error.h"
22+
#include "mbed_debug.h"
2123
#include <limits.h>
24+
#include <stdio.h>
2225

2326
#if DEVICE_SLEEP
2427

2528
// deep sleep locking counter. A target is allowed to deep sleep if counter == 0
2629
static uint16_t deep_sleep_lock = 0U;
2730

28-
void sleep_manager_lock_deep_sleep(void)
31+
#ifdef MBED_SLEEP_TRACING_ENABLED
32+
33+
// Length of the identifier extracted from the driver name to store for logging.
34+
#define IDENTIFIER_WIDTH 15
35+
// Number of drivers that can be stored in the structure
36+
#define STATISTIC_COUNT 10
37+
38+
typedef struct sleep_statistic {
39+
char identifier[IDENTIFIER_WIDTH];
40+
uint8_t count;
41+
} sleep_statistic_t;
42+
43+
static sleep_statistic_t sleep_stats[STATISTIC_COUNT];
44+
45+
static const char* strip_path(const char* const filename)
46+
{
47+
char *output = strrchr(filename, '/');
48+
49+
if (output != NULL) {
50+
return output + 1;
51+
}
52+
53+
output = strrchr(filename, '\\');
54+
55+
if (output != NULL) {
56+
return output + 1;
57+
}
58+
59+
return filename;
60+
}
61+
62+
static sleep_statistic_t* sleep_tracker_find(const char *const filename)
63+
{
64+
char temp[IDENTIFIER_WIDTH];
65+
strncpy(temp, filename, IDENTIFIER_WIDTH);
66+
temp[IDENTIFIER_WIDTH - 1] = '\0';
67+
68+
// Search for the a driver matching the current name and return it's index
69+
for (int i = 0; i < STATISTIC_COUNT; ++i) {
70+
if (strcmp(sleep_stats[i].identifier, temp) == 0) {
71+
return &sleep_stats[i];
72+
}
73+
}
74+
75+
return NULL;
76+
}
77+
78+
static sleep_statistic_t* sleep_tracker_add(const char* const filename)
79+
{
80+
char temp[IDENTIFIER_WIDTH];
81+
strncpy(temp, filename, IDENTIFIER_WIDTH);
82+
temp[IDENTIFIER_WIDTH - 1] = '\0';
83+
84+
for (int i = 0; i < STATISTIC_COUNT; ++i) {
85+
if (sleep_stats[i].identifier[0] == '\0') {
86+
core_util_critical_section_enter();
87+
strncpy(sleep_stats[i].identifier, temp, sizeof(temp));
88+
core_util_critical_section_exit();
89+
90+
return &sleep_stats[i];
91+
}
92+
}
93+
94+
debug("No free indexes left to use in mbed sleep tracker.\r\n");
95+
96+
return NULL;
97+
}
98+
99+
static void sleep_tracker_print_stats(void)
100+
{
101+
debug("Sleep locks held:\r\n");
102+
for (int i = 0; i < STATISTIC_COUNT; ++i) {
103+
if (sleep_stats[i].count == 0) {
104+
continue;
105+
}
106+
107+
if (sleep_stats[i].identifier[0] == '\0') {
108+
return;
109+
}
110+
111+
debug("[id: %s, count: %u]\r\n", sleep_stats[i].identifier,
112+
sleep_stats[i].count);
113+
}
114+
}
115+
116+
void sleep_tracker_lock(const char* const filename, int line)
117+
{
118+
const char* const stripped_path = strip_path(filename);
119+
120+
sleep_statistic_t* stat = sleep_tracker_find(stripped_path);
121+
122+
// Entry for this driver does not exist, create one.
123+
if (stat == NULL) {
124+
stat = sleep_tracker_add(stripped_path);
125+
}
126+
127+
core_util_atomic_incr_u8(&stat->count, 1);
128+
129+
debug("LOCK: %s, ln: %i, lock count: %u\r\n", stripped_path, line, deep_sleep_lock);
130+
}
131+
132+
void sleep_tracker_unlock(const char* const filename, int line)
133+
{
134+
const char* const stripped_path = strip_path(filename);
135+
sleep_statistic_t* stat = sleep_tracker_find(stripped_path);
136+
137+
// Entry for this driver does not exist, something went wrong.
138+
if (stat == NULL) {
139+
debug("Unlocking sleep for driver that was not previously locked: %s, ln: %i\r\n", stripped_path, line);
140+
return;
141+
}
142+
143+
core_util_atomic_decr_u8(&stat->count, 1);
144+
145+
debug("UNLOCK: %s, ln: %i, lock count: %u\r\n", stripped_path, line, deep_sleep_lock);
146+
}
147+
148+
#endif // MBED_SLEEP_TRACING_ENABLED
149+
150+
void sleep_manager_lock_deep_sleep_internal(void)
29151
{
30152
core_util_critical_section_enter();
31153
if (deep_sleep_lock == USHRT_MAX) {
@@ -36,7 +158,7 @@ void sleep_manager_lock_deep_sleep(void)
36158
core_util_critical_section_exit();
37159
}
38160

39-
void sleep_manager_unlock_deep_sleep(void)
161+
void sleep_manager_unlock_deep_sleep_internal(void)
40162
{
41163
core_util_critical_section_enter();
42164
if (deep_sleep_lock == 0) {
@@ -54,6 +176,9 @@ bool sleep_manager_can_deep_sleep(void)
54176

55177
void sleep_manager_sleep_auto(void)
56178
{
179+
#ifdef MBED_SLEEP_TRACING_ENABLED
180+
sleep_tracker_print_stats();
181+
#endif
57182
core_util_critical_section_enter();
58183
// debug profile should keep debuggers attached, no deep sleep allowed
59184
#ifdef MBED_DEBUG
@@ -73,12 +198,12 @@ void sleep_manager_sleep_auto(void)
73198
// locking is valid only if DEVICE_SLEEP is defined
74199
// we provide empty implementation
75200

76-
void sleep_manager_lock_deep_sleep(void)
201+
void sleep_manager_lock_deep_sleep_internal(void)
77202
{
78203

79204
}
80205

81-
void sleep_manager_unlock_deep_sleep(void)
206+
void sleep_manager_unlock_deep_sleep_internal(void)
82207
{
83208

84209
}

platform/mbed_power_mgmt.h

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
#ifndef MBED_POWER_MGMT_H
2424
#define MBED_POWER_MGMT_H
2525

26-
#include "hal/sleep_api.h"
26+
#include "sleep_api.h"
2727
#include "mbed_toolchain.h"
2828
#include <stdbool.h>
2929

@@ -63,6 +63,34 @@ extern "C" {
6363
* }
6464
* @endcode
6565
*/
66+
#ifdef MBED_SLEEP_TRACING_ENABLED
67+
68+
void sleep_tracker_lock(const char *const filename, int line);
69+
void sleep_tracker_unlock(const char *const filename, int line);
70+
71+
#define sleep_manager_lock_deep_sleep() \
72+
do \
73+
{ \
74+
sleep_manager_lock_deep_sleep_internal(); \
75+
sleep_tracker_lock(__FILE__, __LINE__); \
76+
} while (0);
77+
78+
#define sleep_manager_unlock_deep_sleep() \
79+
do \
80+
{ \
81+
sleep_manager_unlock_deep_sleep_internal(); \
82+
sleep_tracker_unlock(__FILE__, __LINE__); \
83+
} while (0);
84+
85+
#else
86+
87+
#define sleep_manager_lock_deep_sleep() \
88+
sleep_manager_lock_deep_sleep_internal()
89+
90+
#define sleep_manager_unlock_deep_sleep() \
91+
sleep_manager_unlock_deep_sleep_internal()
92+
93+
#endif // MBED_SLEEP_TRACING_ENABLED
6694

6795
/** Lock the deep sleep mode
6896
*
@@ -76,7 +104,7 @@ extern "C" {
76104
* The lock is a counter, can be locked up to USHRT_MAX
77105
* This function is IRQ and thread safe
78106
*/
79-
void sleep_manager_lock_deep_sleep(void);
107+
void sleep_manager_lock_deep_sleep_internal(void);
80108

81109
/** Unlock the deep sleep mode
82110
*
@@ -85,14 +113,15 @@ void sleep_manager_lock_deep_sleep(void);
85113
* The lock is a counter, should be equally unlocked as locked
86114
* This function is IRQ and thread safe
87115
*/
88-
void sleep_manager_unlock_deep_sleep(void);
116+
void sleep_manager_unlock_deep_sleep_internal(void);
89117

90118
/** Get the status of deep sleep allowance for a target
91119
*
92120
* @return true if a target can go to deepsleep, false otherwise
93121
*/
94122
bool sleep_manager_can_deep_sleep(void);
95123

124+
96125
/** Enter auto selected sleep mode. It chooses the sleep or deeepsleep modes based
97126
* on the deepsleep locking counter
98127
*

platform/mbed_sleep.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
* See the License for the specific language governing permissions and
1515
* limitations under the License.
1616
*/
17-
1817
#ifndef MBED_MBED_SLEEP_H
1918
#define MBED_MBED_SLEEP_H
2019

0 commit comments

Comments
 (0)