2022-11-03 05:12:14 -04:00
|
|
|
/*
|
2024-04-12 05:52:38 -04:00
|
|
|
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
|
2022-11-03 05:12:14 -04:00
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
*/
|
2021-06-02 23:59:00 -04:00
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <assert.h>
|
|
|
|
#include <unistd.h>
|
2024-04-12 05:52:38 -04:00
|
|
|
#include <errno.h>
|
|
|
|
#include <time.h>
|
2021-06-02 23:59:00 -04:00
|
|
|
#include "esp_rom_sys.h"
|
|
|
|
|
|
|
|
static void call_linux_putc(char c);
|
|
|
|
|
|
|
|
static void (*s_esp_rom_putc)(char c) = call_linux_putc;
|
|
|
|
|
2023-10-09 10:47:25 -04:00
|
|
|
static void call_linux_putc(char c)
|
|
|
|
{
|
2021-06-02 23:59:00 -04:00
|
|
|
putc(c, stdout);
|
|
|
|
}
|
|
|
|
|
|
|
|
#define is_digit(c) ((c >= '0') && (c <= '9'))
|
|
|
|
|
2022-11-03 05:12:14 -04:00
|
|
|
static int _cvt(unsigned long long val, char *buf, long radix, const char *digits)
|
2021-06-02 23:59:00 -04:00
|
|
|
{
|
|
|
|
#ifdef SUPPORT_LITTLE_RADIX
|
|
|
|
char temp[64];
|
|
|
|
#else
|
|
|
|
char temp[32];
|
|
|
|
#endif
|
|
|
|
char *cp = temp;
|
|
|
|
int length = 0;
|
|
|
|
|
|
|
|
if (val == 0) {
|
|
|
|
/* Special case */
|
|
|
|
*cp++ = '0';
|
|
|
|
} else {
|
|
|
|
while (val) {
|
|
|
|
*cp++ = digits[val % radix];
|
|
|
|
val /= radix;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while (cp != temp) {
|
|
|
|
*buf++ = *--cp;
|
|
|
|
length++;
|
|
|
|
}
|
|
|
|
*buf = '\0';
|
|
|
|
return (length);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int esp_rom_vprintf(void (*putc)(char c), const char *fmt, va_list ap)
|
|
|
|
{
|
|
|
|
#ifdef BINARY_SUPPORT
|
2023-10-09 10:47:25 -04:00
|
|
|
char buf[sizeof(long long) * 8];
|
2021-06-02 23:59:00 -04:00
|
|
|
int i;
|
|
|
|
#else
|
|
|
|
char buf[32];
|
|
|
|
#endif
|
2022-11-03 05:12:14 -04:00
|
|
|
char c, sign;
|
|
|
|
const char *cp = buf;
|
2021-06-02 23:59:00 -04:00
|
|
|
int left_prec, right_prec, zero_fill, pad, pad_on_right,
|
|
|
|
islong, islonglong;
|
|
|
|
long long val = 0;
|
|
|
|
int res = 0, length = 0;
|
|
|
|
|
|
|
|
while ((c = *fmt++) != '\0') {
|
|
|
|
if (c == '%') {
|
|
|
|
c = *fmt++;
|
|
|
|
left_prec = right_prec = pad_on_right = islong = islonglong = 0;
|
|
|
|
if (c == '-') {
|
|
|
|
c = *fmt++;
|
|
|
|
pad_on_right++;
|
|
|
|
}
|
|
|
|
if (c == '0') {
|
|
|
|
zero_fill = true;
|
|
|
|
c = *fmt++;
|
|
|
|
} else {
|
|
|
|
zero_fill = false;
|
|
|
|
}
|
|
|
|
while (is_digit(c)) {
|
|
|
|
left_prec = (left_prec * 10) + (c - '0');
|
|
|
|
c = *fmt++;
|
|
|
|
}
|
|
|
|
if (c == '.') {
|
|
|
|
c = *fmt++;
|
|
|
|
zero_fill++;
|
|
|
|
while (is_digit(c)) {
|
|
|
|
right_prec = (right_prec * 10) + (c - '0');
|
|
|
|
c = *fmt++;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
right_prec = left_prec;
|
|
|
|
}
|
|
|
|
sign = '\0';
|
|
|
|
if (c == 'l') {
|
|
|
|
c = *fmt++;
|
|
|
|
islong = 1;
|
|
|
|
if (c == 'l') {
|
|
|
|
c = *fmt++;
|
|
|
|
islonglong = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
switch (c) {
|
|
|
|
case 'p':
|
|
|
|
islong = 1;
|
|
|
|
case 'd':
|
|
|
|
case 'D':
|
|
|
|
case 'x':
|
|
|
|
case 'X':
|
|
|
|
case 'u':
|
|
|
|
case 'U':
|
|
|
|
#ifdef BINARY_SUPPORT
|
|
|
|
case 'b':
|
|
|
|
case 'B':
|
|
|
|
#endif
|
|
|
|
if (islonglong) {
|
|
|
|
val = va_arg(ap, long long);
|
|
|
|
} else if (islong) {
|
|
|
|
val = (long long)va_arg(ap, long);
|
2023-10-09 10:47:25 -04:00
|
|
|
} else {
|
2021-06-02 23:59:00 -04:00
|
|
|
val = (long long)va_arg(ap, int);
|
|
|
|
}
|
|
|
|
if ((c == 'd') || (c == 'D')) {
|
|
|
|
if (val < 0) {
|
|
|
|
sign = '-';
|
|
|
|
val = -val;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (islong) {
|
|
|
|
val &= (((long long)1) << (sizeof(long) * 8)) - 1;
|
2023-10-09 10:47:25 -04:00
|
|
|
} else {
|
2021-06-02 23:59:00 -04:00
|
|
|
val &= (((long long)1) << (sizeof(int) * 8)) - 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (c) {
|
|
|
|
case 'p':
|
|
|
|
(*putc)('0');
|
|
|
|
(*putc)('x');
|
|
|
|
zero_fill = true;
|
2023-10-09 10:47:25 -04:00
|
|
|
left_prec = sizeof(unsigned long) * 2;
|
2021-06-02 23:59:00 -04:00
|
|
|
case 'd':
|
|
|
|
case 'D':
|
|
|
|
case 'u':
|
|
|
|
case 'U':
|
|
|
|
case 'x':
|
|
|
|
case 'X':
|
|
|
|
switch (c) {
|
|
|
|
case 'd':
|
|
|
|
case 'D':
|
|
|
|
case 'u':
|
|
|
|
case 'U':
|
|
|
|
length = _cvt(val, buf, 10, "0123456789");
|
|
|
|
break;
|
|
|
|
case 'p':
|
|
|
|
case 'x':
|
|
|
|
length = _cvt(val, buf, 16, "0123456789abcdef");
|
|
|
|
break;
|
|
|
|
case 'X':
|
|
|
|
length = _cvt(val, buf, 16, "0123456789ABCDEF");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
cp = buf;
|
|
|
|
break;
|
|
|
|
case 's':
|
|
|
|
case 'S':
|
|
|
|
cp = va_arg(ap, char *);
|
|
|
|
if (cp == NULL) {
|
|
|
|
cp = "<null>";
|
|
|
|
}
|
|
|
|
length = 0;
|
|
|
|
while (cp[length] != '\0') length++;
|
|
|
|
break;
|
|
|
|
case 'c':
|
|
|
|
case 'C':
|
|
|
|
c = va_arg(ap, int /*char*/);
|
|
|
|
(*putc)(c);
|
|
|
|
res++;
|
|
|
|
continue;
|
|
|
|
#ifdef BINARY_SUPPORT
|
|
|
|
case 'b':
|
|
|
|
case 'B':
|
|
|
|
length = left_prec;
|
|
|
|
if (left_prec == 0) {
|
|
|
|
if (islonglong)
|
|
|
|
length = sizeof(long long)*8;
|
|
|
|
else if (islong)
|
|
|
|
length = sizeof(long)*8;
|
|
|
|
else
|
|
|
|
length = sizeof(int)*8;
|
|
|
|
}
|
|
|
|
for (i = 0; i < length-1; i++) {
|
|
|
|
buf[i] = ((val & ((long long)1<<i)) ? '1' : '.');
|
|
|
|
}
|
|
|
|
cp = buf;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
case '%':
|
|
|
|
(*putc)('%');
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
(*putc)('%');
|
|
|
|
(*putc)(c);
|
|
|
|
res += 2;
|
|
|
|
}
|
|
|
|
pad = left_prec - length;
|
|
|
|
if (sign != '\0') {
|
|
|
|
pad--;
|
|
|
|
}
|
|
|
|
if (zero_fill) {
|
|
|
|
c = '0';
|
|
|
|
if (sign != '\0') {
|
|
|
|
(*putc)(sign);
|
|
|
|
res++;
|
|
|
|
sign = '\0';
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
c = ' ';
|
|
|
|
}
|
|
|
|
if (!pad_on_right) {
|
|
|
|
while (pad-- > 0) {
|
|
|
|
(*putc)(c);
|
|
|
|
res++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (sign != '\0') {
|
|
|
|
(*putc)(sign);
|
|
|
|
res++;
|
|
|
|
}
|
|
|
|
while (length-- > 0) {
|
|
|
|
c = *cp++;
|
|
|
|
(*putc)(c);
|
|
|
|
res++;
|
|
|
|
}
|
|
|
|
if (pad_on_right) {
|
|
|
|
while (pad-- > 0) {
|
|
|
|
(*putc)(' ');
|
|
|
|
res++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
(*putc)(c);
|
|
|
|
res++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return (res);
|
|
|
|
}
|
|
|
|
|
|
|
|
int esp_rom_printf(const char *fmt, ...)
|
|
|
|
{
|
|
|
|
|
|
|
|
va_list list;
|
|
|
|
va_start(list, fmt);
|
|
|
|
int result = esp_rom_vprintf(s_esp_rom_putc, fmt, list);
|
|
|
|
va_end(list);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
void esp_rom_delay_us(uint32_t us)
|
|
|
|
{
|
2024-04-12 05:52:38 -04:00
|
|
|
struct timespec wait_time = {
|
|
|
|
.tv_sec = us / 1000000,
|
|
|
|
.tv_nsec = us % 1000000 * 1000,
|
|
|
|
};
|
|
|
|
/*
|
|
|
|
If nanosleep() is interrupted by a signal handler, nanosleep()
|
|
|
|
returns -1, sets errno to EINTR, and writes the remaining time.
|
|
|
|
The remaining time is used to call nanosleep() again and complete the specified pause.
|
|
|
|
*/
|
|
|
|
while (nanosleep(&wait_time, &wait_time) == -1 && errno == EINTR) { };
|
2021-06-02 23:59:00 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void esp_rom_install_channel_putc(int channel, void (*putc)(char c))
|
|
|
|
{
|
|
|
|
if (putc != NULL) {
|
|
|
|
s_esp_rom_putc = putc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void esp_rom_install_uart_printf(void)
|
|
|
|
{
|
|
|
|
// Since this is the linux implementation, we don't set any "UART" putc function, but the one which delegates to
|
|
|
|
// the Linux libc version of putc.
|
|
|
|
s_esp_rom_putc = call_linux_putc;
|
|
|
|
}
|
|
|
|
|
|
|
|
soc_reset_reason_t esp_rom_get_reset_reason(int cpu_no)
|
|
|
|
{
|
|
|
|
return RESET_REASON_CHIP_POWER_ON;
|
|
|
|
}
|
2023-10-09 10:47:25 -04:00
|
|
|
|
|
|
|
void __assert_func(const char *file, int line, const char *func, const char *failedexpr)
|
|
|
|
{
|
|
|
|
esp_rom_printf("assertion \"%s\" failed: file \"%s\", line %d%s%s\n",
|
|
|
|
failedexpr, file, line,
|
|
|
|
func ? ", function: " : "", func ? func : "");
|
|
|
|
while (1) {}
|
|
|
|
}
|