Merge branch 'docs/translate_error_handling' into 'master'

docs: Update translation for error handling

Closes DOC-7836

See merge request espressif/esp-idf!30867
This commit is contained in:
Zhang Shu Xian
2024-06-19 09:13:13 +08:00

View File

@@ -23,7 +23,7 @@
本文将介绍 ESP-IDF 中针对可恢复错误的错误处理机制,并提供一些常见错误的处理模式。 本文将介绍 ESP-IDF 中针对可恢复错误的错误处理机制,并提供一些常见错误的处理模式。
关于如何处理不可恢复的错误,请:doc:`不可恢复错误 <fatal-errors>` 关于如何处理不可恢复的错误,请:doc:`/api-guides/fatal-errors`
错误码 错误码
@@ -33,13 +33,13 @@ ESP-IDF 中大多数函数会返回 :cpp:type:`esp_err_t` 类型的错误码,
在 ESP-IDF 中,许多头文件都会使用预处理器,定义可能出现的错误代码。这些错误代码通常均以 ``ESP_ERR_`` 前缀开头,一些常见错误(比如内存不足、超时、无效参数等)的错误代码则已经在 ``esp_err.h`` 文件中定义好了。此外ESP-IDF 中的各种组件 (component) 也都可以针对具体情况,自行定义更多错误代码。 在 ESP-IDF 中,许多头文件都会使用预处理器,定义可能出现的错误代码。这些错误代码通常均以 ``ESP_ERR_`` 前缀开头,一些常见错误(比如内存不足、超时、无效参数等)的错误代码则已经在 ``esp_err.h`` 文件中定义好了。此外ESP-IDF 中的各种组件 (component) 也都可以针对具体情况,自行定义更多错误代码。
完整错误代码列表,请见 :doc:`错误代码参考 <../api-reference/error-codes>` 查看完整的错误列表。 请参考 :doc:`错误代码参考 <../api-reference/error-codes>` 查看完整的错误列表。
错误码错误消息 错误码转换为错误消息
---------------- ------------------------------
错误代码并不直观,因此 ESP-IDF 还可以使用 :cpp:func:`esp_err_to_name` 或者 :cpp:func:`esp_err_to_name_r` 函数,将错误代码转换为具体的错误消息。例如,我们可以向 :cpp:func:`esp_err_to_name` 函数传递错误代码 ``0x101``,可以得到返回字符串 ESP_ERR_NO_MEM。这样一来,我们可以在日志中输出更加直观的错误消息,而不是简单的错误码,从而帮助研发人员更快理解发生了何种错误。 错误代码并不直观,因此 ESP-IDF 还可以使用 :cpp:func:`esp_err_to_name` 或者 :cpp:func:`esp_err_to_name_r` 函数,将错误代码转换为具体的错误消息。例如,我们可以向 :cpp:func:`esp_err_to_name` 函数传递错误代码 ``0x101``,可以得到返回字符串 ``ESP_ERR_NO_MEM``。这样一来,我们可以在日志中输出更加直观的错误消息,而不是简单的错误码,从而帮助研发人员更快理解发生了何种错误。
此外,如果出现找不到匹配的 ``ESP_ERR_`` 值的情况,函数 :cpp:func:`esp_err_to_name_r` 则会尝试将错误码作为一种 `标准 POSIX 错误代码 <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/errno.h.html>`_ 进行解释。具体过程为POSIX 错误代码(例如 ``ENOENT`` ``ENOMEM``)定义在 ``errno.h`` 文件中,可以通过 ``errno`` 变量获得,进而调用 ``strerror_r`` 函数实现。在 ESP-IDF 中,``errno`` 是一个基于线程的局部变量,即每个 FreeRTOS 任务都有自己的 ``errno`` 副本,通过函数修改 ``errno`` 也只会作用于当前任务中的 ``errno`` 变量值。 此外,如果出现找不到匹配的 ``ESP_ERR_`` 值的情况,函数 :cpp:func:`esp_err_to_name_r` 则会尝试将错误码作为一种 `标准 POSIX 错误代码 <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/errno.h.html>`_ 进行解释。具体过程为POSIX 错误代码(例如 ``ENOENT`` ``ENOMEM``)定义在 ``errno.h`` 文件中,可以通过 ``errno`` 变量获得,进而调用 ``strerror_r`` 函数实现。在 ESP-IDF 中,``errno`` 是一个基于线程的局部变量,即每个 FreeRTOS 任务都有自己的 ``errno`` 副本,通过函数修改 ``errno`` 也只会作用于当前任务中的 ``errno`` 变量值。
@@ -53,7 +53,9 @@ ESP-IDF 中大多数函数会返回 :cpp:type:`esp_err_t` 类型的错误码,
:c:macro:`ESP_ERROR_CHECK` 的功能和 ``assert`` 类似,不同之处在于:这个宏会检查 :cpp:type:`esp_err_t` 的值,而非判断 ``bool`` 条件。如果传给 :c:macro:`ESP_ERROR_CHECK` 的参数不等于 :c:macro:`ESP_OK` ,则会在控制台上打印错误消息,然后调用 ``abort()`` 函数。 :c:macro:`ESP_ERROR_CHECK` 的功能和 ``assert`` 类似,不同之处在于:这个宏会检查 :cpp:type:`esp_err_t` 的值,而非判断 ``bool`` 条件。如果传给 :c:macro:`ESP_ERROR_CHECK` 的参数不等于 :c:macro:`ESP_OK` ,则会在控制台上打印错误消息,然后调用 ``abort()`` 函数。
错误消息通常如下所示:: 错误消息通常如下所示
.. code-block:: none
ESP_ERROR_CHECK failed: esp_err_t 0x107 (ESP_ERR_TIMEOUT) at 0x400d1fdf ESP_ERROR_CHECK failed: esp_err_t 0x107 (ESP_ERR_TIMEOUT) at 0x400d1fdf
@@ -63,13 +65,15 @@ ESP-IDF 中大多数函数会返回 :cpp:type:`esp_err_t` 类型的错误码,
Backtrace: 0x40086e7c:0x3ffb4ff0 0x40087328:0x3ffb5010 0x400d1fdf:0x3ffb5030 0x400d0816:0x3ffb5050 Backtrace: 0x40086e7c:0x3ffb4ff0 0x40087328:0x3ffb5010 0x400d1fdf:0x3ffb5030 0x400d0816:0x3ffb5050
.. note:: 如果使用 :doc:`IDF 监视器 <tools/idf-monitor>`,则最后一行回溯结果中的地址将会被自动解析为相应的文件名和行号。 .. note::
如果使用 :doc:`tools/idf-monitor`,则最后一行回溯结果中的地址将会被自动解析为相应的文件名和行号。
- 第一行打印错误代码的十六进制表示,及该错误在源代码中的标识符。这个标识符取决于 :ref:`CONFIG_ESP_ERR_TO_NAME_LOOKUP` 选项的设定。最后,第一行还会打印程序中该错误发生的具体位置。 - 第一行打印错误代码的十六进制表示,及该错误在源代码中的标识符。这个标识符取决于 :ref:`CONFIG_ESP_ERR_TO_NAME_LOOKUP` 选项的设定。最后,第一行还会打印程序中该错误发生的具体位置。
- 下面几行显示了程序中调用 :c:macro:`ESP_ERROR_CHECK` 宏的具体位置,以及传递给该宏的参数。 - 下面几行显示了程序中调用 :c:macro:`ESP_ERROR_CHECK` 宏的具体位置,以及传递给该宏的参数。
- 最后一行打印回溯结果。对于所有不可恢复错误,这里在应急处理程序中打印的内容都是一样的。更多有关回溯结果的详细信息,请参阅 :doc:`不可恢复错误 <fatal-errors>` - 最后一行打印回溯结果。对于所有不可恢复错误,这里在应急处理程序中打印的内容都是一样的。更多有关回溯结果的详细信息,请参阅 :doc:`/api-guides/fatal-errors`
.. _esp-error-check-without-abort-macro: .. _esp-error-check-without-abort-macro:
@@ -77,7 +81,7 @@ ESP-IDF 中大多数函数会返回 :cpp:type:`esp_err_t` 类型的错误码,
``ESP_ERROR_CHECK_WITHOUT_ABORT`` 宏 ``ESP_ERROR_CHECK_WITHOUT_ABORT`` 宏
------------------------------------ ------------------------------------
:c:macro:`ESP_ERROR_CHECK_WITHOUT_ABORT` 的功能和 ``ESP_ERROR_CHECK`` 类似, 不同之处在于它不会调用 ``abort()``. :c:macro:`ESP_ERROR_CHECK_WITHOUT_ABORT` 的功能和 ``ESP_ERROR_CHECK`` 类似不同之处在于它不会调用 ``abort()``
.. _esp-return-on-error-macro: .. _esp-return-on-error-macro:
@@ -85,7 +89,7 @@ ESP-IDF 中大多数函数会返回 :cpp:type:`esp_err_t` 类型的错误码,
``ESP_RETURN_ON_ERROR`` ``ESP_RETURN_ON_ERROR``
-------------------------- --------------------------
:c:macro:`ESP_RETURN_ON_ERROR` 用于错误码检查, 如果错误码不等于 :c:macro:`ESP_OK`, 该宏会打印错误信息,并使原函数立刻返回。 :c:macro:`ESP_RETURN_ON_ERROR` 用于错误码检查如果错误码不等于 :c:macro:`ESP_OK` 该宏会打印错误信息,并使原函数立刻返回。
.. _esp-goto-on-error-macro: .. _esp-goto-on-error-macro:
@@ -93,7 +97,7 @@ ESP-IDF 中大多数函数会返回 :cpp:type:`esp_err_t` 类型的错误码,
``ESP_GOTO_ON_ERROR`` 宏 ``ESP_GOTO_ON_ERROR`` 宏
------------------------ ------------------------
:c:macro:`ESP_GOTO_ON_ERROR` 用于错误码检查, 如果错误码不等于 :c:macro:`ESP_OK`, 该宏会打印错误信息,将局部变量 `ret` 赋值为该错误码, 并使原函数跳转至给定的 `goto_tag`. :c:macro:`ESP_GOTO_ON_ERROR` 用于错误码检查如果错误码不等于 :c:macro:`ESP_OK`该宏会打印错误信息,将局部变量 ``ret`` 赋值为该错误码并使原函数跳转至给定的 ``goto_tag``
.. _esp-return-on-false-macro: .. _esp-return-on-false-macro:
@@ -101,7 +105,7 @@ ESP-IDF 中大多数函数会返回 :cpp:type:`esp_err_t` 类型的错误码,
``ESP_RETURN_ON_FALSE`` ``ESP_RETURN_ON_FALSE``
-------------------------- --------------------------
:c:macro:`ESP_RETURN_ON_FALSE` 用于条件检查, 如果给定条件不等于 `true`, 该宏会打印错误信息,并使原函数立刻返回,返回值为给定的 `err_code`. :c:macro:`ESP_RETURN_ON_FALSE` 用于条件检查如果给定条件不等于 ``true``该宏会打印错误信息,并使原函数立刻返回,返回值为给定的 ``err_code``
.. _esp-goto-on-false-macro: .. _esp-goto-on-false-macro:
@@ -109,7 +113,7 @@ ESP-IDF 中大多数函数会返回 :cpp:type:`esp_err_t` 类型的错误码,
``ESP_GOTO_ON_FALSE`` ``ESP_GOTO_ON_FALSE``
------------------------ ------------------------
:c:macro:`ESP_GOTO_ON_FALSE` 用于条件检查, 如果给定条件不等于 `true`, 该宏会打印错误信息,将局部变量 `ret` 赋值为给定的 `err_code`, 并使原函数跳转至给定的 `goto_tag`. :c:macro:`ESP_GOTO_ON_FALSE` 用于条件检查如果给定条件不等于 ``true``该宏会打印错误信息,将局部变量 ``ret`` 赋值为给定的 ``err_code``并使原函数跳转至给定的 ``goto_tag``
.. _check_macros_examples: .. _check_macros_examples:
@@ -117,7 +121,9 @@ ESP-IDF 中大多数函数会返回 :cpp:type:`esp_err_t` 类型的错误码,
``CHECK 宏使用示例`` ``CHECK 宏使用示例``
------------------------- -------------------------
示例:: 示例
.. code-block:: c
static const char* TAG = "Test"; static const char* TAG = "Test";
@@ -125,12 +131,12 @@ ESP-IDF 中大多数函数会返回 :cpp:type:`esp_err_t` 类型的错误码,
{ {
esp_err_t ret = ESP_OK; 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(x); // 如果错误码不等于 `ESP_OK`,则打印错误信息,然后调用 `abort()`
ESP_ERROR_CHECK_WITHOUT_ABORT(x); // err message printed if `x` is not `ESP_OK`, without `abort()`. ESP_ERROR_CHECK_WITHOUT_ABORT(x); // 如果错误码不等于 `ESP_OK`,则打印错误信息,不调用 `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_RETURN_ON_ERROR(x, TAG, "fail reason 1"); // 如果错误码不等于 `ESP_OK`,则打印错误信息,并使原函数立刻返回,返回值为给定的错误码.
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_GOTO_ON_ERROR(x, err, TAG, "fail reason 2"); // 如果错误码不等于 `ESP_OK`,则打印错误信息,将局部变量 `ret` 赋值为该错误码,并使原函数跳转至 `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_RETURN_ON_FALSE(a, err_code, TAG, "fail reason 3"); // 如果给定条件不等于 `true`,则打印错误信息,并使原函数立刻返回,返回值为给定的错误码。
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`. ESP_GOTO_ON_FALSE(a, err_code, err, TAG, "fail reason 4"); // 如果给定条件不等于 `true`,该宏会打印错误信息,将局部变量 `ret` 赋值为给定的 `err_code`,并使原函数跳转至 `err`
err: err:
// clean up // clean up
@@ -139,7 +145,7 @@ ESP-IDF 中大多数函数会返回 :cpp:type:`esp_err_t` 类型的错误码,
.. note:: .. note::
如果 Kconfig 中的 :ref:`CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT` 选项被打开, CHECK 宏将不会打印错误信息,其他功能不变。 如果 Kconfig 中的 :ref:`CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT` 选项被打开CHECK 宏将不会打印错误信息,其他功能不变。
``ESP_RETURN_xx````ESP_GOTO_xx`` 宏不可以在中断服务程序里被调用。如需要在中断中使用类似功能,请使用 ``xx_ISR`` 宏,如 ``ESP_RETURN_ON_ERROR_ISR`` 等。 ``ESP_RETURN_xx````ESP_GOTO_xx`` 宏不可以在中断服务程序里被调用。如需要在中断中使用类似功能,请使用 ``xx_ISR`` 宏,如 ``ESP_RETURN_ON_ERROR_ISR`` 等。
@@ -153,7 +159,9 @@ ESP-IDF 中大多数函数会返回 :cpp:type:`esp_err_t` 类型的错误码,
- 尝试删除该驱动,然后重新进行“初始化”; - 尝试删除该驱动,然后重新进行“初始化”;
- 采用其他带外机制,修改导致错误发生的条件(例如,对一直没有响应的外设进行复位等)。 - 采用其他带外机制,修改导致错误发生的条件(例如,对一直没有响应的外设进行复位等)。
示例:: 示例
.. code-block:: c
esp_err_t err; esp_err_t err;
do { do {
@@ -166,7 +174,9 @@ ESP-IDF 中大多数函数会返回 :cpp:type:`esp_err_t` 类型的错误码,
2. 将错误传递回调用程序。在某些中间件组件中,采用此类处理模式代表函数必须以相同的错误码退出,这样才能确保所有分配的资源都能得到释放。 2. 将错误传递回调用程序。在某些中间件组件中,采用此类处理模式代表函数必须以相同的错误码退出,这样才能确保所有分配的资源都能得到释放。
示例:: 示例
.. code-block:: c
sdmmc_card_t* card = calloc(1, sizeof(sdmmc_card_t)); sdmmc_card_t* card = calloc(1, sizeof(sdmmc_card_t));
if (card == NULL) { if (card == NULL) {
@@ -187,7 +197,9 @@ ESP-IDF 中大多数函数会返回 :cpp:type:`esp_err_t` 类型的错误码,
在 ESP-IDF 的示例代码中,很多都会使用 ``ESP_ERROR_CHECK`` 来处理各种 API 引发的错误,虽然这不是应用程序的最佳做法,但可以让示例代码看起来更加简洁。 在 ESP-IDF 的示例代码中,很多都会使用 ``ESP_ERROR_CHECK`` 来处理各种 API 引发的错误,虽然这不是应用程序的最佳做法,但可以让示例代码看起来更加简洁。
示例:: 示例
.. code-block:: c
ESP_ERROR_CHECK(spi_bus_initialize(host, bus_config, dma_chan)); ESP_ERROR_CHECK(spi_bus_initialize(host, bus_config, dma_chan));