14
14
* limitations under the License.
15
15
*/
16
16
17
+ #include "mbed_assert.h"
17
18
#include "mbed_power_mgmt.h"
18
19
#include "mbed_critical.h"
19
20
#include "sleep_api.h"
20
21
#include "mbed_error.h"
22
+ #include "mbed_debug.h"
21
23
#include <limits.h>
24
+ #include <stdio.h>
22
25
23
26
#if DEVICE_SLEEP
24
27
25
28
// deep sleep locking counter. A target is allowed to deep sleep if counter == 0
26
29
static uint16_t deep_sleep_lock = 0U ;
27
30
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 )
29
151
{
30
152
core_util_critical_section_enter ();
31
153
if (deep_sleep_lock == USHRT_MAX ) {
@@ -36,7 +158,7 @@ void sleep_manager_lock_deep_sleep(void)
36
158
core_util_critical_section_exit ();
37
159
}
38
160
39
- void sleep_manager_unlock_deep_sleep (void )
161
+ void sleep_manager_unlock_deep_sleep_internal (void )
40
162
{
41
163
core_util_critical_section_enter ();
42
164
if (deep_sleep_lock == 0 ) {
@@ -54,6 +176,9 @@ bool sleep_manager_can_deep_sleep(void)
54
176
55
177
void sleep_manager_sleep_auto (void )
56
178
{
179
+ #ifdef MBED_SLEEP_TRACING_ENABLED
180
+ sleep_tracker_print_stats ();
181
+ #endif
57
182
core_util_critical_section_enter ();
58
183
// debug profile should keep debuggers attached, no deep sleep allowed
59
184
#ifdef MBED_DEBUG
@@ -73,12 +198,12 @@ void sleep_manager_sleep_auto(void)
73
198
// locking is valid only if DEVICE_SLEEP is defined
74
199
// we provide empty implementation
75
200
76
- void sleep_manager_lock_deep_sleep (void )
201
+ void sleep_manager_lock_deep_sleep_internal (void )
77
202
{
78
203
79
204
}
80
205
81
- void sleep_manager_unlock_deep_sleep (void )
206
+ void sleep_manager_unlock_deep_sleep_internal (void )
82
207
{
83
208
84
209
}
0 commit comments