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
2629static 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
55177void 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}
0 commit comments