A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/error-handling.html below:

Website Navigation


Error Handling - ESP32 - — ESP-IDF Programming Guide latest documentation

Error Handling

[中文]

Overview

Identifying and handling run-time errors is important for developing robust applications. There can be multiple kinds of run-time errors:

This guide primarily introduces the error handling mechanisms in ESP-IDF for recoverable errors and provides common error handling patterns. Some sections also mention macros used for unrecoverable errors, with the aim of illustrating their use in scenarios with different levels of error severity.

For instructions on diagnosing unrecoverable errors, see Fatal Errors.

Error Codes

The majority of ESP-IDF-specific functions use esp_err_t type to return error codes. esp_err_t is a signed integer type. Success (no error) is indicated with ESP_OK code, which is defined as zero.

Various ESP-IDF header files define possible error codes using preprocessor defines. Usually these defines start with ESP_ERR_ prefix. Common error codes for generic failures (out of memory, timeout, invalid argument, etc.) are defined in esp_err.h file. Various components in ESP-IDF may define additional error codes for specific situations.

For the complete list of error codes, see Error Code Reference.

Converting Error Codes to Error Messages

For each error code defined in ESP-IDF components, esp_err_t value can be converted to an error code name using esp_err_to_name() or esp_err_to_name_r() functions. For example, passing 0x101 to esp_err_to_name() will return a ESP_ERR_NO_MEM string. Such strings can be used in log output to make it easier to understand which error has happened.

Additionally, esp_err_to_name_r() function will attempt to interpret the error code as a standard POSIX error code, if no matching ESP_ERR_ value is found. This is done using strerror_r function. POSIX error codes (such as ENOENT, ENOMEM) are defined in errno.h and are typically obtained from errno variable. In ESP-IDF this variable is thread-local: multiple FreeRTOS tasks have their own copies of errno. Functions which set errno only modify its value for the task they run in.

This feature is enabled by default, but can be disabled to reduce application binary size. See CONFIG_ESP_ERR_TO_NAME_LOOKUP. When this feature is disabled, esp_err_to_name() and esp_err_to_name_r() are still defined and can be called. In this case, esp_err_to_name() will return UNKNOWN ERROR, and esp_err_to_name_r() will return Unknown error 0xXXXX(YYYYY), where 0xXXXX and YYYYY are the hexadecimal and decimal representations of the error code, respectively.

Macro For Unrecoverable Errors

The ESP_ERROR_CHECK macro, defined in esp_err.h, is used to handle unrecoverable errors in ESP-IDF applications. It functions similarly to the standard assert macro, but specifically checks whether an esp_err_t value is equal to ESP_OK. If the value is not ESP_OK, ESP_ERROR_CHECK prints a detailed error message and calls abort(), terminating the application.

The behavior of ESP_ERROR_CHECK can be controlled using assertion-related configuration options:

Use ESP_ERROR_CHECK in situations where an error is considered fatal and the application cannot continue safely. For situations where the application can recover from an error, use the macros described in the next section.

ESP_ERROR_CHECK_WITHOUT_ABORT

The ESP_ERROR_CHECK_WITHOUT_ABORT macro, defined in esp_err.h, is closely related to the Macros For Recoverable Errors. The macro behaves similarly to ESP_ERROR_CHECK, but instead of terminating the program with abort(), it prints an error message in the same format and returns the error code if the value is not ESP_OK. This allows the application to continue running, making it suitable for cases where errors should be reported but are not considered fatal.

The behavior of ESP_ERROR_CHECK_WITHOUT_ABORT is controlled by the same assertion-related configuration options as ESP_ERROR_CHECK. If either CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE or CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT is enabled, the macro does not print any error message, otherwise, the macro prints an error message.

Use ESP_ERROR_CHECK_WITHOUT_ABORT when you want to print errors for diagnostic purposes without stopping the application.

Error message will typically look like this:

ESP_ERROR_CHECK failed: esp_err_t 0x107 (ESP_ERR_TIMEOUT) at 0x400d1fdf

file: "/Users/user/esp/example/main/main.c" line 20
func: app_main
expression: sdmmc_card_init(host, &card)

Backtrace: 0x40086e7c:0x3ffb4ff0 0x40087328:0x3ffb5010 0x400d1fdf:0x3ffb5030 0x400d0816:0x3ffb5050

Note

If ESP-IDF monitor is used, addresses in the backtrace will be converted to file names and line numbers.

Macros For Recoverable Errors

For recoverable errors, ESP-IDF provides a set of macros defined in esp_check.h. The ESP_RETURN_ON_..., ESP_GOTO_ON_..., and ESP_RETURN_VOID_ON_... macros enable concise and consistent error handling, improving code readability and maintainability. Unlike ESP_ERROR_CHECK, these macros do not terminate the program; instead, they print an error message and return or jump as appropriate. For use in interrupt service routines (ISRs), corresponding _ISR versions (such as ESP_RETURN_ON_ERROR_ISR) are available, ensuring safe operation in interrupt contexts.

The macros are defined as follows:

The default behavior of these macros can be adjusted: if the CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT option is enabled in Kconfig, error messages will not be included in the application binary and will not be printed.

Error Handling Examples

Some examples

static const char* TAG = "Test";

esp_err_t test_func(void)
{
    esp_err_t ret = ESP_OK;

    ESP_ERROR_CHECK(x);                                         // err message printed if `x` is not `ESP_OK`, and then `abort()`.
    ESP_ERROR_CHECK_WITHOUT_ABORT(x);                           // err message printed if `x` is not `ESP_OK`, without `abort()`.
    ESP_RETURN_ON_ERROR(x, TAG, "fail reason 1");               // err message printed if `x` is not `ESP_OK`, and then function returns with code `x`.
    ESP_GOTO_ON_ERROR(x, err, TAG, "fail reason 2");            // err message printed if `x` is not `ESP_OK`, `ret` is set to `x`, and then jumps to `err`.
    ESP_RETURN_ON_FALSE(a, err_code, TAG, "fail reason 3");     // err message printed if `a` is not `true`, and then function returns with code `err_code`.
    ESP_GOTO_ON_FALSE(a, err_code, err, TAG, "fail reason 4");  // err message printed if `a` is not `true`, `ret` is set to `err_code`, and then jumps to `err`.

err:
    // clean up
    return ret;
}
Error Handling Patterns
  1. Attempt to recover. Depending on the situation, we may try the following methods:

    • retry the call after some time;

    • attempt to de-initialize the driver and re-initialize it again;

    • fix the error condition using an out-of-band mechanism (e.g reset an external peripheral which is not responding).

    Example:

    esp_err_t err;
    do {
        err = sdio_slave_send_queue(addr, len, arg, timeout);
        // keep retrying while the sending queue is full
    } while (err == ESP_ERR_TIMEOUT);
    if (err != ESP_OK) {
        // handle other errors
    }
    
  2. Propagate the error to the caller. In some middleware components this means that a function must exit with the same error code, making sure any resource allocations are rolled back.

    Example:

    sdmmc_card_t* card = calloc(1, sizeof(sdmmc_card_t));
    if (card == NULL) {
        return ESP_ERR_NO_MEM;
    }
    esp_err_t err = sdmmc_card_init(host, &card);
    if (err != ESP_OK) {
        // Clean up
        free(card);
        // Propagate the error to the upper layer (e.g., to notify the user).
        // Alternatively, application can define and return custom error code.
        return err;
    }
    
  3. Convert into unrecoverable error, for example using ESP_ERROR_CHECK. See Macro For Unrecoverable Errors section for details.

    Terminating the application in case of an error is usually undesirable behavior for middleware components, but is sometimes acceptable at application level.

    Many ESP-IDF examples use ESP_ERROR_CHECK to handle errors from various APIs. This is not the best practice for applications, and is done to make example code more concise.

    Example:

    ESP_ERROR_CHECK(spi_bus_initialize(host, bus_config, dma_chan));
    
C++ Exceptions

See Exception Handling.

API Reference

See API Reference.


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4