esp_rom_sys.c 7.7 KB

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