1 /*
2 * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <stdbool.h>
10 #include <stdarg.h>
11 #include <assert.h>
12 #include <unistd.h>
13 #include "esp_rom_sys.h"
14
15 static void call_linux_putc(char c);
16
17 static void (*s_esp_rom_putc)(char c) = call_linux_putc;
18
call_linux_putc(char c)19 static void call_linux_putc(char c) {
20 putc(c, stdout);
21 }
22
23 #define is_digit(c) ((c >= '0') && (c <= '9'))
24
_cvt(unsigned long long val,char * buf,long radix,const char * digits)25 static int _cvt(unsigned long long val, char *buf, long radix, const char *digits)
26 {
27 #ifdef SUPPORT_LITTLE_RADIX
28 char temp[64];
29 #else
30 char temp[32];
31 #endif
32 char *cp = temp;
33 int length = 0;
34
35 if (val == 0) {
36 /* Special case */
37 *cp++ = '0';
38 } else {
39 while (val) {
40 *cp++ = digits[val % radix];
41 val /= radix;
42 }
43 }
44 while (cp != temp) {
45 *buf++ = *--cp;
46 length++;
47 }
48 *buf = '\0';
49 return (length);
50 }
51
esp_rom_vprintf(void (* putc)(char c),const char * fmt,va_list ap)52 static int esp_rom_vprintf(void (*putc)(char c), const char *fmt, va_list ap)
53 {
54 #ifdef BINARY_SUPPORT
55 char buf[sizeof(long long)*8];
56 int i;
57 #else
58 char buf[32];
59 #endif
60 char c, sign;
61 const char *cp = buf;
62 int left_prec, right_prec, zero_fill, pad, pad_on_right,
63 islong, islonglong;
64 long long val = 0;
65 int res = 0, length = 0;
66
67 while ((c = *fmt++) != '\0') {
68 if (c == '%') {
69 c = *fmt++;
70 left_prec = right_prec = pad_on_right = islong = islonglong = 0;
71 if (c == '-') {
72 c = *fmt++;
73 pad_on_right++;
74 }
75 if (c == '0') {
76 zero_fill = true;
77 c = *fmt++;
78 } else {
79 zero_fill = false;
80 }
81 while (is_digit(c)) {
82 left_prec = (left_prec * 10) + (c - '0');
83 c = *fmt++;
84 }
85 if (c == '.') {
86 c = *fmt++;
87 zero_fill++;
88 while (is_digit(c)) {
89 right_prec = (right_prec * 10) + (c - '0');
90 c = *fmt++;
91 }
92 } else {
93 right_prec = left_prec;
94 }
95 sign = '\0';
96 if (c == 'l') {
97 c = *fmt++;
98 islong = 1;
99 if (c == 'l') {
100 c = *fmt++;
101 islonglong = 1;
102 }
103 }
104 switch (c) {
105 case 'p':
106 islong = 1;
107 case 'd':
108 case 'D':
109 case 'x':
110 case 'X':
111 case 'u':
112 case 'U':
113 #ifdef BINARY_SUPPORT
114 case 'b':
115 case 'B':
116 #endif
117 if (islonglong) {
118 val = va_arg(ap, long long);
119 } else if (islong) {
120 val = (long long)va_arg(ap, long);
121 } else{
122 val = (long long)va_arg(ap, int);
123 }
124 if ((c == 'd') || (c == 'D')) {
125 if (val < 0) {
126 sign = '-';
127 val = -val;
128 }
129 } else {
130 if (islong) {
131 val &= (((long long)1) << (sizeof(long) * 8)) - 1;
132 } else{
133 val &= (((long long)1) << (sizeof(int) * 8)) - 1;
134 }
135 }
136 break;
137 default:
138 break;
139 }
140
141 switch (c) {
142 case 'p':
143 (*putc)('0');
144 (*putc)('x');
145 zero_fill = true;
146 left_prec = sizeof(unsigned long)*2;
147 case 'd':
148 case 'D':
149 case 'u':
150 case 'U':
151 case 'x':
152 case 'X':
153 switch (c) {
154 case 'd':
155 case 'D':
156 case 'u':
157 case 'U':
158 length = _cvt(val, buf, 10, "0123456789");
159 break;
160 case 'p':
161 case 'x':
162 length = _cvt(val, buf, 16, "0123456789abcdef");
163 break;
164 case 'X':
165 length = _cvt(val, buf, 16, "0123456789ABCDEF");
166 break;
167 }
168 cp = buf;
169 break;
170 case 's':
171 case 'S':
172 cp = va_arg(ap, char *);
173 if (cp == NULL) {
174 cp = "<null>";
175 }
176 length = 0;
177 while (cp[length] != '\0') length++;
178 break;
179 case 'c':
180 case 'C':
181 c = va_arg(ap, int /*char*/);
182 (*putc)(c);
183 res++;
184 continue;
185 #ifdef BINARY_SUPPORT
186 case 'b':
187 case 'B':
188 length = left_prec;
189 if (left_prec == 0) {
190 if (islonglong)
191 length = sizeof(long long)*8;
192 else if (islong)
193 length = sizeof(long)*8;
194 else
195 length = sizeof(int)*8;
196 }
197 for (i = 0; i < length-1; i++) {
198 buf[i] = ((val & ((long long)1<<i)) ? '1' : '.');
199 }
200 cp = buf;
201 break;
202 #endif
203 case '%':
204 (*putc)('%');
205 break;
206 default:
207 (*putc)('%');
208 (*putc)(c);
209 res += 2;
210 }
211 pad = left_prec - length;
212 if (sign != '\0') {
213 pad--;
214 }
215 if (zero_fill) {
216 c = '0';
217 if (sign != '\0') {
218 (*putc)(sign);
219 res++;
220 sign = '\0';
221 }
222 } else {
223 c = ' ';
224 }
225 if (!pad_on_right) {
226 while (pad-- > 0) {
227 (*putc)(c);
228 res++;
229 }
230 }
231 if (sign != '\0') {
232 (*putc)(sign);
233 res++;
234 }
235 while (length-- > 0) {
236 c = *cp++;
237 (*putc)(c);
238 res++;
239 }
240 if (pad_on_right) {
241 while (pad-- > 0) {
242 (*putc)(' ');
243 res++;
244 }
245 }
246 } else {
247 (*putc)(c);
248 res++;
249 }
250 }
251 return (res);
252 }
253
esp_rom_printf(const char * fmt,...)254 int esp_rom_printf(const char *fmt, ...)
255 {
256
257 va_list list;
258 va_start(list, fmt);
259 int result = esp_rom_vprintf(s_esp_rom_putc, fmt, list);
260 va_end(list);
261 return result;
262 }
263
esp_rom_delay_us(uint32_t us)264 void esp_rom_delay_us(uint32_t us)
265 {
266 int sleep_result = usleep(us);
267 assert(sleep_result == 0);
268 (void)sleep_result; // Prevents compiler from optimizing out usleep() due to unused result. Also prevents warning.
269 }
270
esp_rom_install_channel_putc(int channel,void (* putc)(char c))271 void esp_rom_install_channel_putc(int channel, void (*putc)(char c))
272 {
273 if (putc != NULL) {
274 s_esp_rom_putc = putc;
275 }
276 }
277
esp_rom_install_uart_printf(void)278 void esp_rom_install_uart_printf(void)
279 {
280 // Since this is the linux implementation, we don't set any "UART" putc function, but the one which delegates to
281 // the Linux libc version of putc.
282 s_esp_rom_putc = call_linux_putc;
283 }
284
esp_rom_get_reset_reason(int cpu_no)285 soc_reset_reason_t esp_rom_get_reset_reason(int cpu_no)
286 {
287 return RESET_REASON_CHIP_POWER_ON;
288 }
289