feat(esp_rom): Adds esp_rom_vprintf with the same capabilities as esp_rom_print

This commit is contained in:
Konstantin Kondrashov 2024-05-22 17:42:03 +03:00
parent 60532e7a80
commit a3be04a087
36 changed files with 516 additions and 289 deletions

View File

@ -9,11 +9,14 @@ else()
set(target_folder "${target}")
endif()
set(include_dirs "include" "include/${target_folder}")
set(include_dirs "include"
"include/${target_folder}"
"${target_folder}")
set(private_required_comp "")
set(sources "")
set(sources "patches/esp_rom_sys.c"
"patches/esp_rom_print.c")
if(target STREQUAL "linux")
list(APPEND sources "${target}/esp_rom_sys.c"
@ -21,12 +24,10 @@ if(target STREQUAL "linux")
"${target}/esp_rom_md5.c"
"${target}/esp_rom_efuse.c")
else()
list(APPEND include_dirs "${target_folder}")
if(CONFIG_IDF_TARGET_ESP32C5)
list(APPEND include_dirs "include/${target_folder}/..")
endif()
list(APPEND sources "patches/esp_rom_crc.c"
"patches/esp_rom_sys.c"
"patches/esp_rom_uart.c"
"patches/esp_rom_spiflash.c"
"patches/esp_rom_efuse.c")

View File

@ -54,3 +54,7 @@ config ESP_ROM_USB_SERIAL_DEVICE_NUM
config ESP_ROM_SUPPORT_DEEP_SLEEP_WAKEUP_STUB
bool
default y
config ESP_ROM_HAS_OUTPUT_PUTC_FUNC
bool
default y

View File

@ -19,3 +19,4 @@
#define ESP_ROM_USB_OTG_NUM (-1) // No USB_OTG CDC in the ROM, set -1 for Kconfig usage.
#define ESP_ROM_USB_SERIAL_DEVICE_NUM (-1) // No USB_SERIAL_JTAG in the ROM, set -1 for Kconfig usage.
#define ESP_ROM_SUPPORT_DEEP_SLEEP_WAKEUP_STUB (1) // ROM supports the HP core to jump to the RTC memory to execute stub code after waking up from deepsleep.
#define ESP_ROM_HAS_OUTPUT_PUTC_FUNC (1) // ROM has esp_rom_output_putc (or ets_write_char_uart)

View File

@ -90,3 +90,11 @@ config ESP_ROM_USB_SERIAL_DEVICE_NUM
config ESP_ROM_HAS_VERSION
bool
default y
config ESP_ROM_HAS_VPRINTF_FUNC
bool
default y
config ESP_ROM_HAS_OUTPUT_PUTC_FUNC
bool
default y

View File

@ -28,3 +28,5 @@
#define ESP_ROM_USB_OTG_NUM (-1) // No USB_OTG CDC in the ROM, set -1 for Kconfig usage.
#define ESP_ROM_USB_SERIAL_DEVICE_NUM (-1) // No USB_SERIAL_JTAG in the ROM, set -1 for Kconfig usage.
#define ESP_ROM_HAS_VERSION (1) // ROM has version/eco information
#define ESP_ROM_HAS_VPRINTF_FUNC (1) // ROM has ets_vprintf
#define ESP_ROM_HAS_OUTPUT_PUTC_FUNC (1) // ROM has esp_rom_output_putc (or ets_write_char_uart)

View File

@ -94,3 +94,7 @@ config ESP_ROM_HAS_VERSION
config ESP_ROM_SUPPORT_DEEP_SLEEP_WAKEUP_STUB
bool
default y
config ESP_ROM_HAS_OUTPUT_PUTC_FUNC
bool
default y

View File

@ -29,3 +29,4 @@
#define ESP_ROM_USB_OTG_NUM (-1) // No USB_OTG CDC in the ROM, set -1 for Kconfig usage.
#define ESP_ROM_HAS_VERSION (1) // ROM has version/eco information
#define ESP_ROM_SUPPORT_DEEP_SLEEP_WAKEUP_STUB (1) // ROM supports the HP core to jump to the RTC memory to execute stub code after waking up from deepsleep.
#define ESP_ROM_HAS_OUTPUT_PUTC_FUNC (1) // ROM has esp_rom_output_putc (or ets_write_char_uart)

View File

@ -82,3 +82,7 @@ config ESP_ROM_HAS_VERSION
config ESP_ROM_SUPPORT_DEEP_SLEEP_WAKEUP_STUB
bool
default y
config ESP_ROM_HAS_OUTPUT_PUTC_FUNC
bool
default y

View File

@ -28,3 +28,4 @@
#define ESP_ROM_RAM_APP_NEEDS_MMU_INIT (1) // ROM doesn't init cache MMU when it's a RAM APP, needs MMU hal to init
#define ESP_ROM_HAS_VERSION (1) // ROM has version/eco information
#define ESP_ROM_SUPPORT_DEEP_SLEEP_WAKEUP_STUB (1) // ROM supports the HP core to jump to the RTC memory to execute stub code after waking up from deepsleep.
#define ESP_ROM_HAS_OUTPUT_PUTC_FUNC (1) // ROM has esp_rom_output_putc (or ets_write_char_uart)

View File

@ -106,3 +106,7 @@ config ESP_ROM_HAS_VERSION
config ESP_ROM_SUPPORT_DEEP_SLEEP_WAKEUP_STUB
bool
default y
config ESP_ROM_HAS_OUTPUT_PUTC_FUNC
bool
default y

View File

@ -32,3 +32,4 @@
#define ESP_ROM_USB_OTG_NUM (-1) // No USB_OTG CDC in the ROM, set -1 for Kconfig usage.
#define ESP_ROM_HAS_VERSION (1) // ROM has version/eco information
#define ESP_ROM_SUPPORT_DEEP_SLEEP_WAKEUP_STUB (1) // ROM supports the HP core to jump to the RTC memory to execute stub code after waking up from deepsleep.
#define ESP_ROM_HAS_OUTPUT_PUTC_FUNC (1) // ROM has esp_rom_output_putc (or ets_write_char_uart)

View File

@ -86,3 +86,7 @@ config ESP_ROM_HAS_SW_FLOAT
config ESP_ROM_USB_OTG_NUM
int
default -1
config ESP_ROM_HAS_OUTPUT_PUTC_FUNC
bool
default y

View File

@ -29,3 +29,4 @@
#define ESP_ROM_RAM_APP_NEEDS_MMU_INIT (1) // ROM doesn't init cache MMU when it's a RAM APP, needs MMU hal to init
#define ESP_ROM_HAS_SW_FLOAT (1) // ROM has libgcc software floating point emulation functions
#define ESP_ROM_USB_OTG_NUM (-1) // No USB_OTG CDC in the ROM, set -1 for Kconfig usage.
#define ESP_ROM_HAS_OUTPUT_PUTC_FUNC (1) // ROM has esp_rom_output_putc (or ets_write_char_uart)

View File

@ -94,3 +94,7 @@ config ESP_ROM_HAS_VERSION
config ESP_ROM_SUPPORT_DEEP_SLEEP_WAKEUP_STUB
bool
default y
config ESP_ROM_HAS_OUTPUT_PUTC_FUNC
bool
default y

View File

@ -29,3 +29,4 @@
#define ESP_ROM_USB_OTG_NUM (-1) // No USB_OTG CDC in the ROM, set -1 for Kconfig usage.
#define ESP_ROM_HAS_VERSION (1) // ROM has version/eco information
#define ESP_ROM_SUPPORT_DEEP_SLEEP_WAKEUP_STUB (1) // ROM supports the HP core to jump to the RTC memory to execute stub code after waking up from deepsleep.
#define ESP_ROM_HAS_OUTPUT_PUTC_FUNC (1) // ROM has esp_rom_output_putc (or ets_write_char_uart)

View File

@ -74,3 +74,7 @@ config ESP_ROM_HAS_VERSION
config ESP_ROM_CLIC_INT_TYPE_PATCH
bool
default y
config ESP_ROM_HAS_OUTPUT_PUTC_FUNC
bool
default y

View File

@ -24,3 +24,4 @@
#define ESP_ROM_HAS_NEWLIB_NANO_FORMAT (1) // ROM has the newlib nano version of formatting functions
#define ESP_ROM_HAS_VERSION (1) // ROM has version/eco information
#define ESP_ROM_CLIC_INT_TYPE_PATCH (1) // ROM api esprv_intc_int_set_type configuring edge type interrupt is invalid
#define ESP_ROM_HAS_OUTPUT_PUTC_FUNC (1) // ROM has esp_rom_output_putc (or ets_write_char_uart)

View File

@ -54,3 +54,15 @@ config ESP_ROM_USB_SERIAL_DEVICE_NUM
config ESP_ROM_SUPPORT_DEEP_SLEEP_WAKEUP_STUB
bool
default y
config ESP_ROM_HAS_VPRINTF_FUNC
bool
default y
config ESP_ROM_HAS_OUTPUT_TO_CHANNELS_FUNC
bool
default y
config ESP_ROM_HAS_OUTPUT_PUTC_FUNC
bool
default y

View File

@ -19,3 +19,6 @@
#define ESP_ROM_HAS_SW_FLOAT (1) // ROM has libgcc software floating point emulation functions
#define ESP_ROM_USB_SERIAL_DEVICE_NUM (-1) // No USB_SERIAL_JTAG in the ROM, set -1 for Kconfig usage.
#define ESP_ROM_SUPPORT_DEEP_SLEEP_WAKEUP_STUB (1) // ROM supports the HP core to jump to the RTC memory to execute stub code after waking up from deepsleep.
#define ESP_ROM_HAS_VPRINTF_FUNC (1) // ROM has ets_vprintf
#define ESP_ROM_HAS_OUTPUT_TO_CHANNELS_FUNC (1) // ROM has ets_write_char, alias is esp_rom_output_to_channels
#define ESP_ROM_HAS_OUTPUT_PUTC_FUNC (1) // ROM has esp_rom_output_putc (or ets_write_char_uart)

View File

@ -49,6 +49,7 @@ PROVIDE ( esp_rom_software_reset_system = software_reset );
PROVIDE ( esp_rom_software_reset_cpu = software_reset_cpu );
PROVIDE ( esp_rom_printf = ets_printf );
PROVIDE ( esp_rom_output_to_channels = ets_write_char );
PROVIDE ( esp_rom_delay_us = ets_delay_us );
PROVIDE ( esp_rom_install_uart_printf = ets_install_uart_printf );
PROVIDE ( esp_rom_get_reset_reason = rtc_get_reset_reason );

View File

@ -110,3 +110,7 @@ config ESP_ROM_HAS_VERSION
config ESP_ROM_SUPPORT_DEEP_SLEEP_WAKEUP_STUB
bool
default y
config ESP_ROM_HAS_OUTPUT_PUTC_FUNC
bool
default y

View File

@ -33,3 +33,4 @@
#define ESP_ROM_HAS_SW_FLOAT (1) // ROM has libgcc software floating point emulation functions
#define ESP_ROM_HAS_VERSION (1) // ROM has version/eco information
#define ESP_ROM_SUPPORT_DEEP_SLEEP_WAKEUP_STUB (1) // ROM supports the HP core to jump to the RTC memory to execute stub code after waking up from deepsleep.
#define ESP_ROM_HAS_OUTPUT_PUTC_FUNC (1) // ROM has esp_rom_output_putc (or ets_write_char_uart)

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -9,6 +9,7 @@
#include <stdint.h>
#include <stdbool.h>
#include <stdarg.h>
#ifdef __cplusplus
extern "C" {
@ -61,7 +62,7 @@ struct ETSEventTag {
ETSParam par; /**< Event parameter, sometimes without usage, then will be set as 0*/
};
typedef void (*ETSTask)(ETSEvent *e); /**< Type of the Task processer*/
typedef void (*ETSTask)(ETSEvent *e); /**< Type of the Task processor*/
typedef void (* ets_idle_cb_t)(void *arg); /**< Type of the system idle callback*/
@ -80,7 +81,7 @@ typedef void (* ets_idle_cb_t)(void *arg); /**< Type of the system idle callbac
* @{
*/
extern const char *const exc_cause_table[40]; ///**< excption cause that defined by the core.*/
extern const char *const exc_cause_table[40]; ///**< exception cause that defined by the core.*/
/**
* @brief Set Pro cpu Entry code, code can be called in PRO CPU when booting is not completed.
@ -117,6 +118,20 @@ void ets_set_user_start(uint32_t start);
*/
int ets_printf(const char *fmt, ...);
/**
* @brief A ROM implementation of the `vprintf` function.
*
* This function formats and prints data to a specified output function based on the provided format string and arguments.
*
* @param putc A pointer to a function that outputs a single character.
* This function will be called for each character in the formatted output.
* @param fmt A format string that specifies how to format the arguments.
* @param ap A variable argument list containing the values to be formatted.
*
* @return The number of characters printed.
*/
int ets_vprintf(void (*putc)(char c), const char *fmt, va_list ap);
/**
* @brief Get the uart channel of ets_printf(uart_tx_one_char).
*
@ -135,7 +150,7 @@ uint8_t ets_get_printf_channel(void);
void ets_write_char_uart(char c);
/**
* @brief Ets_printf have two output functions putc1 and putc2, both of which will be called if need ouput.
* @brief Ets_printf has two output functions putc1 and putc2, both of which will be called if needed.
* To install putc1, which is defaulted installed as ets_write_char_uart in none silent boot mode, as NULL in silent mode.
*
* @param void (*)(char) p: Output function to install.
@ -145,7 +160,7 @@ void ets_write_char_uart(char c);
void ets_install_putc1(void (*p)(char c));
/**
* @brief Ets_printf have two output functions putc1 and putc2, both of which will be called if need ouput.
* @brief Ets_printf has two output functions putc1 and putc2, both of which will be called if needed.
* To install putc2, which is defaulted installed as NULL.
*
* @param void (*)(char) p: Output function to install.
@ -188,7 +203,7 @@ typedef void ETSTimerFunc(void *timer_arg);/**< timer handler*/
typedef struct _ETSTIMER_ {
struct _ETSTIMER_ *timer_next; /**< timer linker*/
uint32_t timer_expire; /**< abstruct time when timer expire*/
uint32_t timer_expire; /**< abstract time when timer expire*/
uint32_t timer_period; /**< timer period, 0 means timer is not periodic repeated*/
ETSTimerFunc *timer_func; /**< timer handler*/
void *timer_arg; /**< timer handler argument*/

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2010-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2010-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -9,6 +9,7 @@
#include <stdint.h>
#include <stdbool.h>
#include <stdarg.h>
#include "soc/soc.h"
@ -63,7 +64,7 @@ struct ETSEventTag {
ETSParam par; /**< Event parameter, sometimes without usage, then will be set as 0*/
};
typedef void (*ETSTask)(ETSEvent *e); /**< Type of the Task processer*/
typedef void (*ETSTask)(ETSEvent *e); /**< Type of the Task processor*/
typedef void (* ets_idle_cb_t)(void *arg); /**< Type of the system idle callback*/
@ -82,7 +83,7 @@ typedef void (* ets_idle_cb_t)(void *arg); /**< Type of the system idle callbac
* @{
*/
extern const char *const exc_cause_table[40]; ///**< excption cause that defined by the core.*/
extern const char *const exc_cause_table[40]; ///**< exception cause that defined by the core.*/
/**
* @brief Set Pro cpu Entry code, code can be called in PRO CPU when booting is not completed.
@ -119,6 +120,20 @@ void ets_set_user_start(uint32_t start);
*/
int ets_printf(const char *fmt, ...);
/**
* @brief A ROM implementation of the `vprintf` function.
*
* This function formats and prints data to a specified output function based on the provided format string and arguments.
*
* @param putc A pointer to a function that outputs a single character.
* This function will be called for each character in the formatted output.
* @param fmt A format string that specifies how to format the arguments.
* @param ap A variable argument list containing the values to be formatted.
*
* @return The number of characters printed.
*/
int ets_vprintf(void (*putc)(char c), const char *fmt, va_list ap);
/**
* @brief Set the uart channel of ets_printf(uart_tx_one_char).
* ROM will set it base on the efuse and gpio setting, however, this can be changed after booting.
@ -147,7 +162,7 @@ uint8_t ets_get_printf_channel(void);
void ets_write_char_uart(char c);
/**
* @brief Ets_printf have two output functions putc1 and putc2, both of which will be called if need ouput.
* @brief Ets_printf has two output functions putc1 and putc2, both of which will be called if needed.
* To install putc1, which is defaulted installed as ets_write_char_uart in none silent boot mode, as NULL in silent mode.
*
* @param void (*)(char) p: Output function to install.
@ -157,7 +172,7 @@ void ets_write_char_uart(char c);
void ets_install_putc1(void (*p)(char c));
/**
* @brief Ets_printf have two output functions putc1 and putc2, both of which will be called if need ouput.
* @brief Ets_printf has two output functions putc1 and putc2, both of which will be called if needed.
* To install putc2, which is defaulted installed as NULL.
*
* @param void (*)(char) p: Output function to install.
@ -200,7 +215,7 @@ typedef void ETSTimerFunc(void *timer_arg);/**< timer handler*/
typedef struct _ETSTIMER_ {
struct _ETSTIMER_ *timer_next; /**< timer linker*/
uint32_t timer_expire; /**< abstruct time when timer expire*/
uint32_t timer_expire; /**< abstract time when timer expire*/
uint32_t timer_period; /**< timer period, 0 means timer is not periodic repeated*/
ETSTimerFunc *timer_func; /**< timer handler*/
void *timer_arg; /**< timer handler argument*/

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2010-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2010-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -8,6 +8,7 @@
#include "sdkconfig.h"
#include <stdint.h>
#include <inttypes.h>
#include <stdarg.h>
#include "soc/reset_reasons.h"
#ifdef __cplusplus
@ -33,7 +34,7 @@ void esp_rom_software_reset_system(void);
void esp_rom_software_reset_cpu(int cpu_no);
/**
* @brief Print formated string to console device
* @brief Print formatted string to console device
* @note float and long long data are not supported!
*
* @param fmt Format string
@ -42,6 +43,16 @@ void esp_rom_software_reset_cpu(int cpu_no);
*/
int esp_rom_printf(const char *fmt, ...);
/**
* @brief Print formatted string to console device
* @note float and long long data are not supported!
*
* @param fmt Format string
* @param ap List of arguments.
* @return int: Total number of characters written on success; A negative number on failure.
*/
int esp_rom_vprintf(const char *fmt, va_list ap);
/**
* @brief Pauses execution for us microseconds
*
@ -53,11 +64,19 @@ void esp_rom_delay_us(uint32_t us);
* @brief esp_rom_printf can print message to different channels simultaneously.
* This function can help install the low level putc function for esp_rom_printf.
*
* @param channel Channel number (startting from 1)
* @param channel Channel number (starting from 1)
* @param putc Function pointer to the putc implementation. Set NULL can disconnect esp_rom_printf with putc.
*/
void esp_rom_install_channel_putc(int channel, void (*putc)(char c));
/**
* @brief It outputs a character to different channels simultaneously.
* This function is used by esp_rom_printf/esp_rom_vprintf.
*
* @param c Char to output.
*/
void esp_rom_output_to_channels(char c);
/**
* @brief Install UART1 as the default console channel, equivalent to `esp_rom_install_channel_putc(1, esp_rom_output_putc)`
*/

View File

@ -0,0 +1,7 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once

View File

@ -1,6 +1,8 @@
[mapping:esp_rom]
archive: libesp_rom.a
entries:
esp_rom_sys (noflash)
esp_rom_print (noflash)
esp_rom_spiflash (noflash)
if ESP_ROM_HAS_FLASH_COUNT_PAGES_BUG = y:
esp_rom_cache_esp32s2_esp32s3 (noflash)

View File

@ -10,3 +10,11 @@ config ESP_ROM_USB_OTG_NUM
config ESP_ROM_USB_SERIAL_DEVICE_NUM
int
default -1
config ESP_ROM_HAS_ETS_PRINTF_BUG
bool
default y
config ESP_ROM_HAS_OUTPUT_PUTC_FUNC
bool
default y

View File

@ -6,3 +6,5 @@
#define ESP_ROM_USB_OTG_NUM (-1) // No USB_OTG CDC in the ROM, set -1 for Kconfig usage.
#define ESP_ROM_USB_SERIAL_DEVICE_NUM (-1) // No USB_SERIAL_JTAG in the ROM, set -1 for Kconfig usage.
#define ESP_ROM_HAS_ETS_PRINTF_BUG (1) // The build will include esp_rom_install_uart_printf, which is used for host tests.
#define ESP_ROM_HAS_OUTPUT_PUTC_FUNC (1) // The Linux target has an implementation of esp_rom_output_putc.

View File

@ -4,6 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
@ -14,256 +15,11 @@
#include <time.h>
#include "esp_rom_sys.h"
static void call_linux_putc(char c);
static void (*s_esp_rom_putc)(char c) = call_linux_putc;
static void call_linux_putc(char c)
void esp_rom_output_putc(char c)
{
putc(c, stdout);
}
#define is_digit(c) ((c >= '0') && (c <= '9'))
static int _cvt(unsigned long long val, char *buf, long radix, const char *digits)
{
#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
char buf[sizeof(long long) * 8];
int i;
#else
char buf[32];
#endif
char c, sign;
const char *cp = buf;
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);
} else {
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;
} else {
val &= (((long long)1) << (sizeof(int) * 8)) - 1;
}
}
break;
default:
break;
}
switch (c) {
case 'p':
(*putc)('0');
(*putc)('x');
zero_fill = true;
left_prec = sizeof(unsigned long) * 2;
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)
{
struct timespec wait_time = {
@ -278,20 +34,6 @@ void esp_rom_delay_us(uint32_t us)
while (nanosleep(&wait_time, &wait_time) == -1 && errno == EINTR) { };
}
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;

View File

@ -0,0 +1,267 @@
/*
* SPDX-FileCopyrightText: 2010-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include <stdbool.h>
#include <stdarg.h>
#include <stddef.h>
#include "esp_rom_caps.h"
#include "esp_rom_sys.h"
#include "rom/ets_sys.h"
#include "sdkconfig.h"
#if !ESP_ROM_HAS_VPRINTF_FUNC
static int _cvt(unsigned long long val, char *buf, long radix, const char *digits)
{
#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);
}
#define is_digit(c) ((c >= '0') && (c <= '9'))
static int ets_vprintf(void (*putc)(char c), const char *fmt, va_list ap)
{
#ifdef BINARY_SUPPORT
char buf[sizeof(long long)*8];
#else
char buf[32];
#endif
char c, sign, *cp=buf;
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;
islong = 0;
}
}
switch (c) {
case 'p':
islong = 1;
/* fall through */
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);
} else {
val = (long long)va_arg(ap, int);
}
if ((c == 'd') || (c == 'D')) {
if (val < 0) {
sign = '-';
val = -val;
}
} else {
if (islonglong) {
;
} else if (islong) {
val &= ((long long)1 << (sizeof(long) * 8)) - 1;
} else {
val &= ((long long)1 << (sizeof(int) * 8)) - 1;
}
}
break;
default:
break;
}
switch (c) {
case 'p':
(*putc)('0');
(*putc)('x');
zero_fill = true;
left_prec = sizeof(unsigned long)*2;
/* fall through */
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 = (char *)"<null000>";
}
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);
}
#endif // !ESP_ROM_HAS_VPRINTF_FUNC
#if CONFIG_IDF_TARGET_LINUX
// esp_rom_printf is already available from ROM. At the moment we only need this for LINUX.
int esp_rom_printf(const char *fmt, ...)
{
va_list list;
va_start(list, fmt);
int result = ets_vprintf(esp_rom_output_to_channels, fmt, list);
va_end(list);
return result;
}
#endif // CONFIG_IDF_TARGET_LINUX
int esp_rom_vprintf(const char *fmt, va_list ap)
{
return ets_vprintf(esp_rom_output_to_channels, fmt, ap);
}

View File

@ -1,26 +1,65 @@
/*
* SPDX-FileCopyrightText: 2010-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2010-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include <stdbool.h>
#include "sdkconfig.h"
#include "esp_attr.h"
#include <stddef.h>
#include "soc/soc_caps.h"
#include "esp_rom_caps.h"
#include "esp_rom_uart.h"
#include "rom/ets_sys.h"
#include "sdkconfig.h"
IRAM_ATTR void esp_rom_install_channel_putc(int channel, void (*putc)(char c))
#if !ESP_ROM_HAS_OUTPUT_PUTC_FUNC
void esp_rom_output_putc(char c)
{
if (c == '\n') {
esp_rom_output_tx_one_char('\r');
esp_rom_output_tx_one_char('\n');
} else if (c == '\r') {
} else {
esp_rom_output_tx_one_char(c);
}
}
#endif // !ESP_ROM_HAS_OUTPUT_PUTC_FUNC
#if !ESP_ROM_HAS_OUTPUT_TO_CHANNELS_FUNC
void (* _putc1)(char c) = esp_rom_output_putc;
void (* _putc2)(char c) = NULL;
void esp_rom_output_to_channels(char c)
{
if (_putc1) {
_putc1(c);
}
if (_putc2) {
_putc2(c);
}
}
#endif // !ESP_ROM_HAS_OUTPUT_TO_CHANNELS_FUNC
void esp_rom_install_channel_putc(int channel, void (*putc)(char c))
{
extern void ets_install_putc1(void (*p)(char c));
extern void ets_install_putc2(void (*p)(char c));
switch (channel) {
case 1:
#if !ESP_ROM_HAS_OUTPUT_TO_CHANNELS_FUNC
_putc1 = putc;
#endif
#if !CONFIG_IDF_TARGET_LINUX
ets_install_putc1(putc);
#endif
break;
case 2:
#if !ESP_ROM_HAS_OUTPUT_TO_CHANNELS_FUNC
_putc2 = putc;
#endif
#if !CONFIG_IDF_TARGET_LINUX
ets_install_putc2(putc);
#endif
break;
default:
break;
@ -28,8 +67,12 @@ IRAM_ATTR void esp_rom_install_channel_putc(int channel, void (*putc)(char c))
}
#if ESP_ROM_HAS_ETS_PRINTF_BUG
IRAM_ATTR void esp_rom_install_uart_printf(void)
void esp_rom_install_uart_printf(void)
{
#if !ESP_ROM_HAS_OUTPUT_TO_CHANNELS_FUNC
_putc1 = esp_rom_output_putc;
#endif
#if !CONFIG_IDF_TARGET_LINUX
extern void ets_install_uart_printf(void);
extern bool g_uart_print;
extern bool g_usb_print;
@ -38,6 +81,7 @@ IRAM_ATTR void esp_rom_install_uart_printf(void)
g_uart_print = true;
g_usb_print = true;
ets_install_uart_printf();
#endif // !CONFIG_IDF_TARGET_LINUX
}
#endif
@ -48,7 +92,7 @@ extern uint32_t g_ticks_per_us_pro;
extern uint32_t g_ticks_per_us_app;
#endif
#endif
IRAM_ATTR void esp_rom_set_cpu_ticks_per_us(uint32_t ticks_per_us)
void esp_rom_set_cpu_ticks_per_us(uint32_t ticks_per_us)
{
/* Update scale factors used by esp_rom_delay_us */
g_ticks_per_us_pro = ticks_per_us;

View File

@ -1,5 +1,6 @@
set(srcs "test_app_main.c"
"test_libgcc.c")
"test_libgcc.c"
"test_printf.c")
if(CONFIG_IDF_ENV_FPGA)
list(APPEND srcs "test_miniz.c")

View File

@ -0,0 +1,30 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdarg.h>
#include "sdkconfig.h"
#include "esp_rom_sys.h"
#include "unity.h"
static int my_printf(const char *fmt, ...)
{
va_list list;
va_start(list, fmt);
int len = esp_rom_vprintf(fmt, list);
va_end(list);
return len;
}
TEST_CASE("Test esp_rom_vprintf", "[rom][vprintf]")
{
int len = esp_rom_printf("esp_rom_printf function works %d %d %d\n", 1, 2, 3);
TEST_ASSERT_EQUAL_INT(36, len);
len = my_printf("esp_rom_vprintf function works %d %d %d\n", 1, 2, 3);
TEST_ASSERT_EQUAL_INT(37, len);
}

View File

@ -0,0 +1,7 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once

View File

@ -9,6 +9,7 @@
#include <cstdio>
#include <regex>
#include <iostream>
#include "esp_rom_sys.h"
#include "esp_log.h"
#include "esp_private/log_util.h"
#include "esp_private/log_timestamp.h"
@ -111,7 +112,7 @@ struct PutcFixture : BasicLogFixture {
throw exception();
}
esp_rom_install_channel_putc(0, putc_callback);
esp_rom_install_channel_putc(1, putc_callback);
instance = this;
}