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