1 /***************************************************************************//**
2  * @file
3  * @brief Power Manager Debug API implementation.
4  *******************************************************************************
5  * # License
6  * <b>Copyright 2019 Silicon Laboratories Inc. www.silabs.com</b>
7  *******************************************************************************
8  *
9  * SPDX-License-Identifier: Zlib
10  *
11  * The licensor of this software is Silicon Laboratories Inc.
12  *
13  * This software is provided 'as-is', without any express or implied
14  * warranty. In no event will the authors be held liable for any damages
15  * arising from the use of this software.
16  *
17  * Permission is granted to anyone to use this software for any purpose,
18  * including commercial applications, and to alter it and redistribute it
19  * freely, subject to the following restrictions:
20  *
21  * 1. The origin of this software must not be misrepresented; you must not
22  *    claim that you wrote the original software. If you use this software
23  *    in a product, an acknowledgment in the product documentation would be
24  *    appreciated but is not required.
25  * 2. Altered source versions must be plainly marked as such, and must not be
26  *    misrepresented as being the original software.
27  * 3. This notice may not be removed or altered from any source distribution.
28  *
29  ******************************************************************************/
30 
31 #include "sl_power_manager.h"
32 #include "sl_power_manager_config.h"
33 #include "sl_power_manager_debug.h"
34 #include "sli_power_manager_private.h"
35 
36 #if (SL_POWER_MANAGER_DEBUG == 1)
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <stdint.h>
40 #include <string.h>
41 
42 static sl_slist_node_t *power_manager_debug_requirement_em_table[SLI_POWER_MANAGER_EM_TABLE_SIZE];
43 static sli_power_debug_requirement_entry_t  power_debug_entry_table[SL_POWER_MANAGER_DEBUG_POOL_SIZE];
44 static sl_slist_node_t *power_debug_free_entry_list = NULL;
45 static bool power_debug_ran_out_of_entry = false;
46 
47 static void power_manager_log_add_requirement(sl_slist_node_t **p_list,
48                                               bool            add,
49                                               const char      *name);
50 
51 /***************************************************************************//**
52  * Print a fancy table that describes the current requirements on each energy
53  * mode and their owner.
54  ******************************************************************************/
sl_power_manager_debug_print_em_requirements(void)55 void sl_power_manager_debug_print_em_requirements(void)
56 {
57   uint8_t i;
58   sli_power_debug_requirement_entry_t *entry;
59 
60   if (power_debug_ran_out_of_entry) {
61     printf("WARNING: The system ran out of Debug Entry; This report is likely to be incomplete. Increase SL_POWER_MANAGER_DEBUG_POOL_SIZE\n\n");
62   }
63   printf("------------------------------------------\n");
64   printf("| EM requirements\n");
65   printf("------------------------------------------\n");
66   for (i = 0; i < SLI_POWER_MANAGER_EM_TABLE_SIZE; i++) {
67     if (power_manager_debug_requirement_em_table[i] != NULL) {
68       printf("| EM%d requirement module owners:\n", i + 1);
69     }
70     SL_SLIST_FOR_EACH_ENTRY(power_manager_debug_requirement_em_table[i], entry, sli_power_debug_requirement_entry_t, node) {
71       printf("|     %s\n", entry->module_name);
72     }
73     if (power_manager_debug_requirement_em_table[i] != NULL) {
74       printf("------------------------------------------\n");
75     }
76   }
77 }
78 
79 /***************************************************************************//**
80  * Initialize debugging feature.
81  ******************************************************************************/
sli_power_manager_debug_init(void)82 void sli_power_manager_debug_init(void)
83 {
84   uint32_t i;
85 
86   for (i = 0; i < SL_POWER_MANAGER_DEBUG_POOL_SIZE; i++) {
87     sli_power_debug_requirement_entry_t  *entry = &power_debug_entry_table[i];
88     sl_slist_push(&power_debug_free_entry_list, &entry->node);
89   }
90 }
91 
92 /***************************************************************************//**
93  * Log requirement to a list
94  *
95  * @param p_list  List where to push or remove the requirement.
96  *
97  * @param add     Add (true) or remove (false) the requirement.
98  *
99  * @param name    Module name that acquired or remove the requirement.
100  ******************************************************************************/
power_manager_log_add_requirement(sl_slist_node_t ** p_list,bool add,const char * name)101 static void power_manager_log_add_requirement(sl_slist_node_t **p_list,
102                                               bool            add,
103                                               const char      *name)
104 {
105   sl_slist_node_t *node;
106   sli_power_debug_requirement_entry_t  *entry;
107 
108   if (add == true) {
109     // Get entry from free list
110     node = sl_slist_pop(&power_debug_free_entry_list);
111     if (node == NULL) {
112       power_debug_ran_out_of_entry = true;
113       return;
114     }
115 
116     // Push entry to the EMx requirement debug list
117     entry = SL_SLIST_ENTRY(node, sli_power_debug_requirement_entry_t, node);
118     entry->module_name = name;
119     sl_slist_push(p_list, &entry->node);
120   } else {
121     sli_power_debug_requirement_entry_t  *entry_remove = NULL;
122 
123     // Search in the EMx requirement debug list
124     SL_SLIST_FOR_EACH_ENTRY(*p_list, entry, sli_power_debug_requirement_entry_t, node) {
125       // Current module name and entry module name
126       if (strcmp(entry->module_name, name) == 0) {
127         entry_remove = entry;
128         break;
129       }
130     }
131 
132     if (entry_remove == NULL) {
133       return;
134     }
135 
136     sl_slist_remove(p_list, &entry_remove->node);
137     sl_slist_push(&power_debug_free_entry_list, &entry_remove->node);
138   }
139 }
140 #endif // SL_POWER_MANAGER_DEBUG
141 
142 #undef sli_power_manager_debug_log_em_requirement
143 /***************************************************************************//**
144  * Log energy mode (EM) requirement
145  *
146  * @param em    Energy mode added or removed.
147  *
148  * @param add   Add (true) or remove (false) the requirement.
149  *
150  * @param name  Module name that adds or removes the requirement.
151  ******************************************************************************/
sli_power_manager_debug_log_em_requirement(sl_power_manager_em_t em,bool add,const char * name)152 void sli_power_manager_debug_log_em_requirement(sl_power_manager_em_t em,
153                                                 bool                  add,
154                                                 const char            *name)
155 {
156 #if (SL_POWER_MANAGER_DEBUG == 1)
157   if (em != SL_POWER_MANAGER_EM0) {
158     power_manager_log_add_requirement(&power_manager_debug_requirement_em_table[em - 1], add, name);
159   }
160 #else
161   (void)em;
162   (void)add;
163   (void)name;
164 #endif
165 }
166