1 /*
2  * Copyright (c) 2019 Alexander Wachter
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/sys/printk.h>
8 #include <zephyr/shell/shell.h>
9 #include <zephyr/drivers/hwinfo.h>
10 #include <zephyr/types.h>
11 #include <zephyr/logging/log.h>
12 
cmd_get_device_id(const struct shell * sh,size_t argc,char ** argv)13 static int cmd_get_device_id(const struct shell *sh, size_t argc, char **argv)
14 {
15 	uint8_t dev_id[16];
16 	ssize_t length;
17 	int i;
18 
19 	length = hwinfo_get_device_id(dev_id, sizeof(dev_id));
20 
21 	if (length == -ENOSYS) {
22 		shell_error(sh, "Not supported by hardware");
23 		return -ENOSYS;
24 	} else if (length < 0) {
25 		shell_error(sh, "Error: %zd", length);
26 		return length;
27 	}
28 
29 	shell_fprintf(sh, SHELL_NORMAL, "Length: %zd\n", length);
30 	shell_fprintf(sh, SHELL_NORMAL, "ID: 0x");
31 
32 	for (i = 0 ; i < length ; i++) {
33 		shell_fprintf(sh, SHELL_NORMAL, "%02x", dev_id[i]);
34 	}
35 
36 	shell_fprintf(sh, SHELL_NORMAL, "\n");
37 
38 	return 0;
39 }
40 
cmd_get_device_eui64(const struct shell * sh,size_t argc,char ** argv)41 static int cmd_get_device_eui64(const struct shell *sh, size_t argc, char **argv)
42 {
43 	uint8_t dev_eui64[8];
44 	int ret;
45 	int i;
46 
47 	ret = hwinfo_get_device_eui64(dev_eui64);
48 
49 	if (ret == -ENOSYS) {
50 		shell_error(sh, "Not supported by hardware");
51 		return -ENOSYS;
52 	} else if (ret < 0) {
53 		shell_error(sh, "Error: %d", ret);
54 		return ret;
55 	}
56 
57 	shell_fprintf(sh, SHELL_NORMAL, "EUI64: 0x");
58 
59 	for (i = 0 ; i < 8 ; i++) {
60 		shell_fprintf(sh, SHELL_NORMAL, "%02x", dev_eui64[i]);
61 	}
62 
63 	shell_fprintf(sh, SHELL_NORMAL, "\n");
64 
65 	return 0;
66 }
67 
cause_to_string(uint32_t cause)68 static inline const char *cause_to_string(uint32_t cause)
69 {
70 	switch (cause) {
71 	case RESET_PIN:
72 		return "pin";
73 
74 	case RESET_SOFTWARE:
75 		return "software";
76 
77 	case RESET_BROWNOUT:
78 		return "brownout";
79 
80 	case RESET_POR:
81 		return "power-on reset";
82 
83 	case RESET_WATCHDOG:
84 		return "watchdog";
85 
86 	case RESET_DEBUG:
87 		return "debug";
88 
89 	case RESET_SECURITY:
90 		return "security";
91 
92 	case RESET_LOW_POWER_WAKE:
93 		return "low power wake-up";
94 
95 	case RESET_CPU_LOCKUP:
96 		return "CPU lockup";
97 
98 	case RESET_PARITY:
99 		return "parity error";
100 
101 	case RESET_PLL:
102 		return "PLL error";
103 
104 	case RESET_CLOCK:
105 		return "clock";
106 
107 	case RESET_HARDWARE:
108 		return "hardware";
109 
110 	case RESET_USER:
111 		return "user";
112 
113 	case RESET_TEMPERATURE:
114 		return "temperature";
115 
116 	default:
117 		return "unknown";
118 	}
119 }
120 
print_all_reset_causes(const struct shell * sh,uint32_t cause)121 static void print_all_reset_causes(const struct shell *sh, uint32_t cause)
122 {
123 	for (uint32_t cause_mask = 1; cause_mask; cause_mask <<= 1) {
124 		if (cause & cause_mask) {
125 			shell_print(sh, "- %s",
126 				    cause_to_string(cause & cause_mask));
127 		}
128 	}
129 }
130 
cmd_show_reset_cause(const struct shell * sh,size_t argc,char ** argv)131 static int cmd_show_reset_cause(const struct shell *sh, size_t argc,
132 				char **argv)
133 {
134 	int res;
135 	uint32_t cause;
136 
137 	ARG_UNUSED(argc);
138 	ARG_UNUSED(argv);
139 
140 	res = hwinfo_get_reset_cause(&cause);
141 	if (res == -ENOSYS) {
142 		shell_error(sh, "Not supported by hardware");
143 		return res;
144 	} else if (res != 0) {
145 		shell_error(sh, "Error reading the cause [%d]", res);
146 		return res;
147 	}
148 
149 	if (cause != 0) {
150 		shell_print(sh, "reset caused by:");
151 		print_all_reset_causes(sh, cause);
152 	} else {
153 		shell_print(sh, "No reset cause set");
154 	}
155 
156 	return 0;
157 }
158 
cmd_clear_reset_cause(const struct shell * sh,size_t argc,char ** argv)159 static int cmd_clear_reset_cause(const struct shell *sh, size_t argc,
160 				 char **argv)
161 {
162 	int res;
163 
164 	ARG_UNUSED(argc);
165 	ARG_UNUSED(argv);
166 
167 	res = hwinfo_clear_reset_cause();
168 	if (res == -ENOSYS) {
169 		shell_error(sh, "Not supported by hardware");
170 	} else if (res != 0) {
171 		shell_error(sh, "Error clearing the reset causes [%d]", res);
172 		return res;
173 	}
174 
175 	return 0;
176 }
177 
cmd_supported_reset_cause(const struct shell * sh,size_t argc,char ** argv)178 static int cmd_supported_reset_cause(const struct shell *sh, size_t argc,
179 				     char **argv)
180 {
181 	uint32_t cause;
182 	int res;
183 
184 	ARG_UNUSED(argc);
185 	ARG_UNUSED(argv);
186 
187 	res = hwinfo_get_supported_reset_cause(&cause);
188 	if (res == -ENOSYS) {
189 		shell_error(sh, "Not supported by hardware");
190 	} else if (res != 0) {
191 		shell_error(sh, "Could not get the supported reset causes [%d]", res);
192 		return res;
193 	}
194 
195 	if (cause != 0) {
196 		shell_print(sh, "supported reset causes:");
197 		print_all_reset_causes(sh, cause);
198 	} else {
199 		shell_print(sh, "No causes supported");
200 	}
201 
202 	return 0;
203 }
204 
205 SHELL_STATIC_SUBCMD_SET_CREATE(sub_reset_cause,
206 	SHELL_CMD_ARG(show, NULL, "Show persistent reset causes",
207 		      cmd_show_reset_cause, 1, 0),
208 	SHELL_CMD_ARG(clear, NULL, "Clear all persistent reset causes",
209 		      cmd_clear_reset_cause, 1, 0),
210 	SHELL_CMD_ARG(supported, NULL,
211 		      "Get a list of all supported reset causes",
212 		      cmd_supported_reset_cause, 1, 0),
213 	SHELL_SUBCMD_SET_END /* Array terminated. */
214 );
215 
216 SHELL_STATIC_SUBCMD_SET_CREATE(sub_hwinfo,
217 	SHELL_CMD_ARG(devid, NULL, "Show device id", cmd_get_device_id, 1, 0),
218 	SHELL_CMD_ARG(deveui64, NULL, "Show device eui64", cmd_get_device_eui64, 1, 0),
219 	SHELL_CMD_ARG(reset_cause, &sub_reset_cause, "Reset cause commands",
220 		      cmd_show_reset_cause, 1, 0),
221 	SHELL_SUBCMD_SET_END /* Array terminated. */
222 );
223 
224 SHELL_CMD_ARG_REGISTER(hwinfo, &sub_hwinfo, "HWINFO commands", NULL, 2, 0);
225