]> granicus.if.org Git - esp-idf/commitdiff
Make it easier to look up error messages
authorRoland Dobai <dobai.roland@gmail.com>
Thu, 1 Feb 2018 12:14:47 +0000 (13:14 +0100)
committerRoland Dobai <dobai.roland@gmail.com>
Thu, 15 Feb 2018 13:19:03 +0000 (14:19 +0100)
tools/gen_esp_err_to_name.py generates
components/esp32/esp_err_to_name.c for lookup of the error codes from
all of the IDF project and easily identify all codes in one place

.gitlab-ci.yml
components/esp32/esp_err_to_name.c [new file with mode: 0644]
components/esp32/esp_err_to_name.c.in [new file with mode: 0644]
components/esp32/include/esp_err.h
tools/gen_esp_err_to_name.py [new file with mode: 0755]

index 2153a3d4ed1582ec497e64d295ada0c941a59c54..09711b6b75129c64903f3088eaef3246f2a5bf74 100644 (file)
@@ -319,6 +319,17 @@ test_report:
     - git push origin master
     - test "${TEST_RESULT}" = "Pass" || exit 1
 
+test_esp_err_to_name_on_host:
+  stage: test
+  image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG
+  tags:
+    - build
+  dependencies: []
+  script:
+    - cd tools/
+    - ./gen_esp_err_to_name.py
+    - git diff --exit-code -- ../components/esp32/esp_err_to_name.c || (echo 'Differences found. Please run gen_esp_err_to_name.py and commit the changes.'; exit 1)
+
 push_master_to_github:
   stage: deploy
   image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG
diff --git a/components/esp32/esp_err_to_name.c b/components/esp32/esp_err_to_name.c
new file mode 100644 (file)
index 0000000..a706a68
--- /dev/null
@@ -0,0 +1,396 @@
+//Do not edit this file because it is autogenerated by gen_esp_err_to_name.py
+
+#include <string.h>
+#if __has_include("soc/soc.h")
+#include "soc/soc.h"
+#endif
+#if __has_include("esp32/ulp.h")
+#include "esp32/ulp.h"
+#endif
+#if __has_include("esp_err.h")
+#include "esp_err.h"
+#endif
+#if __has_include("esp_image_format.h")
+#include "esp_image_format.h"
+#endif
+#if __has_include("esp_now.h")
+#include "esp_now.h"
+#endif
+#if __has_include("esp_ota_ops.h")
+#include "esp_ota_ops.h"
+#endif
+#if __has_include("esp_ping.h")
+#include "esp_ping.h"
+#endif
+#if __has_include("esp_spi_flash.h")
+#include "esp_spi_flash.h"
+#endif
+#if __has_include("esp_wifi.h")
+#include "esp_wifi.h"
+#endif
+#if __has_include("esp_wps.h")
+#include "esp_wps.h"
+#endif
+#if __has_include("nvs.h")
+#include "nvs.h"
+#endif
+#if __has_include("tcpip_adapter.h")
+#include "tcpip_adapter.h"
+#endif
+
+#define ERR_TBL_IT(err)    {err, #err}
+
+typedef struct {
+    esp_err_t code;
+    const char *msg;
+} esp_err_msg_t;
+
+static const esp_err_msg_t esp_err_msg_table[] = {
+    // components/esp32/include/esp_err.h
+#   ifdef      ESP_FAIL
+    ERR_TBL_IT(ESP_FAIL),                                   /*    -1 */
+#   endif
+    // components/esp32/include/esp_wifi.h
+#   ifdef      ESP_ERR_WIFI_FAIL
+    ERR_TBL_IT(ESP_ERR_WIFI_FAIL),                          /*    -1 General fail code */
+#   endif
+    // components/esp32/include/esp_err.h
+#   ifdef      ESP_OK
+    ERR_TBL_IT(ESP_OK),                                     /*     0 */
+#   endif
+    // components/esp32/include/esp_wifi.h
+#   ifdef      ESP_ERR_WIFI_OK
+    ERR_TBL_IT(ESP_ERR_WIFI_OK),                            /*     0 No error */
+#   endif
+    // components/esp32/include/esp_err.h
+#   ifdef      ESP_ERR_NO_MEM
+    ERR_TBL_IT(ESP_ERR_NO_MEM),                             /*   257 0x101 */
+#   endif
+    // components/esp32/include/esp_wifi.h
+#   ifdef      ESP_ERR_WIFI_NO_MEM
+    ERR_TBL_IT(ESP_ERR_WIFI_NO_MEM),                        /*   257 0x101 Out of memory */
+#   endif
+    // components/esp32/include/esp_err.h
+#   ifdef      ESP_ERR_INVALID_ARG
+    ERR_TBL_IT(ESP_ERR_INVALID_ARG),                        /*   258 0x102 */
+#   endif
+    // components/esp32/include/esp_wifi.h
+#   ifdef      ESP_ERR_WIFI_ARG
+    ERR_TBL_IT(ESP_ERR_WIFI_ARG),                           /*   258 0x102 Invalid argument */
+#   endif
+    // components/esp32/include/esp_err.h
+#   ifdef      ESP_ERR_INVALID_STATE
+    ERR_TBL_IT(ESP_ERR_INVALID_STATE),                      /*   259 0x103 */
+#   endif
+#   ifdef      ESP_ERR_INVALID_SIZE
+    ERR_TBL_IT(ESP_ERR_INVALID_SIZE),                       /*   260 0x104 */
+#   endif
+#   ifdef      ESP_ERR_NOT_FOUND
+    ERR_TBL_IT(ESP_ERR_NOT_FOUND),                          /*   261 0x105 */
+#   endif
+#   ifdef      ESP_ERR_NOT_SUPPORTED
+    ERR_TBL_IT(ESP_ERR_NOT_SUPPORTED),                      /*   262 0x106 */
+#   endif
+    // components/esp32/include/esp_wifi.h
+#   ifdef      ESP_ERR_WIFI_NOT_SUPPORT
+    ERR_TBL_IT(ESP_ERR_WIFI_NOT_SUPPORT),                   /*   262 0x106 Indicates that API is not supported yet */
+#   endif
+    // components/esp32/include/esp_err.h
+#   ifdef      ESP_ERR_TIMEOUT
+    ERR_TBL_IT(ESP_ERR_TIMEOUT),                            /*   263 0x107 */
+#   endif
+#   ifdef      ESP_ERR_INVALID_RESPONSE
+    ERR_TBL_IT(ESP_ERR_INVALID_RESPONSE),                   /*   264 0x108 */
+#   endif
+#   ifdef      ESP_ERR_INVALID_CRC
+    ERR_TBL_IT(ESP_ERR_INVALID_CRC),                        /*   265 0x109 */
+#   endif
+#   ifdef      ESP_ERR_INVALID_VERSION
+    ERR_TBL_IT(ESP_ERR_INVALID_VERSION),                    /*   266 0x10a */
+#   endif
+#   ifdef      ESP_ERR_INVALID_MAC
+    ERR_TBL_IT(ESP_ERR_INVALID_MAC),                        /*   267 0x10b */
+#   endif
+    // components/nvs_flash/include/nvs.h
+#   ifdef      ESP_ERR_NVS_BASE
+    ERR_TBL_IT(ESP_ERR_NVS_BASE),                           /*  4352 0x1100 Starting number of error codes */
+#   endif
+#   ifdef      ESP_ERR_NVS_NOT_INITIALIZED
+    ERR_TBL_IT(ESP_ERR_NVS_NOT_INITIALIZED),                /*  4353 0x1101 The storage driver is not initialized */
+#   endif
+#   ifdef      ESP_ERR_NVS_NOT_FOUND
+    ERR_TBL_IT(ESP_ERR_NVS_NOT_FOUND),                      /*  4354 0x1102 Id namespace doesn’t exist yet and mode is
+                                                                            NVS_READONLY */
+#   endif
+#   ifdef      ESP_ERR_NVS_TYPE_MISMATCH
+    ERR_TBL_IT(ESP_ERR_NVS_TYPE_MISMATCH),                  /*  4355 0x1103 The type of set or get operation doesn't
+                                                                            match the type of value stored in NVS */
+#   endif
+#   ifdef      ESP_ERR_NVS_READ_ONLY
+    ERR_TBL_IT(ESP_ERR_NVS_READ_ONLY),                      /*  4356 0x1104 Storage handle was opened as read only */
+#   endif
+#   ifdef      ESP_ERR_NVS_NOT_ENOUGH_SPACE
+    ERR_TBL_IT(ESP_ERR_NVS_NOT_ENOUGH_SPACE),               /*  4357 0x1105 There is not enough space in the underlying
+                                                                            storage to save the value */
+#   endif
+#   ifdef      ESP_ERR_NVS_INVALID_NAME
+    ERR_TBL_IT(ESP_ERR_NVS_INVALID_NAME),                   /*  4358 0x1106 Namespace name doesn’t satisfy constraints */
+#   endif
+#   ifdef      ESP_ERR_NVS_INVALID_HANDLE
+    ERR_TBL_IT(ESP_ERR_NVS_INVALID_HANDLE),                 /*  4359 0x1107 Handle has been closed or is NULL */
+#   endif
+#   ifdef      ESP_ERR_NVS_REMOVE_FAILED
+    ERR_TBL_IT(ESP_ERR_NVS_REMOVE_FAILED),                  /*  4360 0x1108 The value wasn’t updated because flash
+                                                                            write operation has failed. The value was
+                                                                            written however, and update will be finished
+                                                                            after re-initialization of nvs, provided
+                                                                            that flash operation doesn’t fail again. */
+#   endif
+#   ifdef      ESP_ERR_NVS_KEY_TOO_LONG
+    ERR_TBL_IT(ESP_ERR_NVS_KEY_TOO_LONG),                   /*  4361 0x1109 Key name is too long */
+#   endif
+#   ifdef      ESP_ERR_NVS_PAGE_FULL
+    ERR_TBL_IT(ESP_ERR_NVS_PAGE_FULL),                      /*  4362 0x110a Internal error; never returned by nvs_ API
+                                                                            functions */
+#   endif
+#   ifdef      ESP_ERR_NVS_INVALID_STATE
+    ERR_TBL_IT(ESP_ERR_NVS_INVALID_STATE),                  /*  4363 0x110b NVS is in an inconsistent state due to a
+                                                                            previous error. Call nvs_flash_init and
+                                                                            nvs_open again, then retry. */
+#   endif
+#   ifdef      ESP_ERR_NVS_INVALID_LENGTH
+    ERR_TBL_IT(ESP_ERR_NVS_INVALID_LENGTH),                 /*  4364 0x110c String or blob length is not sufficient to
+                                                                            store data */
+#   endif
+#   ifdef      ESP_ERR_NVS_NO_FREE_PAGES
+    ERR_TBL_IT(ESP_ERR_NVS_NO_FREE_PAGES),                  /*  4365 0x110d NVS partition doesn't contain any empty
+                                                                            pages. This may happen if NVS partition was
+                                                                            truncated. Erase the whole partition and
+                                                                            call nvs_flash_init again. */
+#   endif
+#   ifdef      ESP_ERR_NVS_VALUE_TOO_LONG
+    ERR_TBL_IT(ESP_ERR_NVS_VALUE_TOO_LONG),                 /*  4366 0x110e String or blob length is longer than
+                                                                            supported by the implementation */
+#   endif
+#   ifdef      ESP_ERR_NVS_PART_NOT_FOUND
+    ERR_TBL_IT(ESP_ERR_NVS_PART_NOT_FOUND),                 /*  4367 0x110f Partition with specified name is not found
+                                                                            in the partition table */
+#   endif
+    // components/ulp/include/esp32/ulp.h
+#   ifdef      ESP_ERR_ULP_BASE
+    ERR_TBL_IT(ESP_ERR_ULP_BASE),                           /*  4608 0x1200 Offset for ULP-related error codes */
+#   endif
+#   ifdef      ESP_ERR_ULP_SIZE_TOO_BIG
+    ERR_TBL_IT(ESP_ERR_ULP_SIZE_TOO_BIG),                   /*  4609 0x1201 Program doesn't fit into RTC memory reserved
+                                                                            for the ULP */
+#   endif
+#   ifdef      ESP_ERR_ULP_INVALID_LOAD_ADDR
+    ERR_TBL_IT(ESP_ERR_ULP_INVALID_LOAD_ADDR),              /*  4610 0x1202 Load address is outside of RTC memory
+                                                                            reserved for the ULP */
+#   endif
+#   ifdef      ESP_ERR_ULP_DUPLICATE_LABEL
+    ERR_TBL_IT(ESP_ERR_ULP_DUPLICATE_LABEL),                /*  4611 0x1203 More than one label with the same number was
+                                                                            defined */
+#   endif
+#   ifdef      ESP_ERR_ULP_UNDEFINED_LABEL
+    ERR_TBL_IT(ESP_ERR_ULP_UNDEFINED_LABEL),                /*  4612 0x1204 Branch instructions references an undefined label */
+#   endif
+#   ifdef      ESP_ERR_ULP_BRANCH_OUT_OF_RANGE
+    ERR_TBL_IT(ESP_ERR_ULP_BRANCH_OUT_OF_RANGE),            /*  4613 0x1205 Branch target is out of range of B
+                                                                            instruction (try replacing with BX) */
+#   endif
+    // components/app_update/include/esp_ota_ops.h
+#   ifdef      ESP_ERR_OTA_BASE
+    ERR_TBL_IT(ESP_ERR_OTA_BASE),                           /*  5376 0x1500 Base error code for ota_ops api */
+#   endif
+#   ifdef      ESP_ERR_OTA_PARTITION_CONFLICT
+    ERR_TBL_IT(ESP_ERR_OTA_PARTITION_CONFLICT),             /*  5377 0x1501 Error if request was to write or erase the
+                                                                            current running partition */
+#   endif
+#   ifdef      ESP_ERR_OTA_SELECT_INFO_INVALID
+    ERR_TBL_IT(ESP_ERR_OTA_SELECT_INFO_INVALID),            /*  5378 0x1502 Error if OTA data partition contains invalid
+                                                                            content */
+#   endif
+#   ifdef      ESP_ERR_OTA_VALIDATE_FAILED
+    ERR_TBL_IT(ESP_ERR_OTA_VALIDATE_FAILED),                /*  5379 0x1503 Error if OTA app image is invalid */
+#   endif
+    // components/bootloader_support/include/esp_image_format.h
+#   ifdef      ESP_ERR_IMAGE_BASE
+    ERR_TBL_IT(ESP_ERR_IMAGE_BASE),                         /*  8192 0x2000 */
+#   endif
+#   ifdef      ESP_ERR_IMAGE_FLASH_FAIL
+    ERR_TBL_IT(ESP_ERR_IMAGE_FLASH_FAIL),                   /*  8193 0x2001 */
+#   endif
+#   ifdef      ESP_ERR_IMAGE_INVALID
+    ERR_TBL_IT(ESP_ERR_IMAGE_INVALID),                      /*  8194 0x2002 */
+#   endif
+    // components/esp32/include/esp_err.h
+#   ifdef      ESP_ERR_WIFI_BASE
+    ERR_TBL_IT(ESP_ERR_WIFI_BASE),                          /* 12288 0x3000 Starting number of WiFi error codes */
+#   endif
+    // components/esp32/include/esp_wifi.h
+#   ifdef      ESP_ERR_WIFI_NOT_INIT
+    ERR_TBL_IT(ESP_ERR_WIFI_NOT_INIT),                      /* 12289 0x3001 WiFi driver was not installed by esp_wifi_init */
+#   endif
+#   ifdef      ESP_ERR_WIFI_NOT_STARTED
+    ERR_TBL_IT(ESP_ERR_WIFI_NOT_STARTED),                   /* 12290 0x3002 WiFi driver was not started by esp_wifi_start */
+#   endif
+#   ifdef      ESP_ERR_WIFI_NOT_STOPPED
+    ERR_TBL_IT(ESP_ERR_WIFI_NOT_STOPPED),                   /* 12291 0x3003 WiFi driver was not stopped by esp_wifi_stop */
+#   endif
+#   ifdef      ESP_ERR_WIFI_IF
+    ERR_TBL_IT(ESP_ERR_WIFI_IF),                            /* 12292 0x3004 WiFi interface error */
+#   endif
+#   ifdef      ESP_ERR_WIFI_MODE
+    ERR_TBL_IT(ESP_ERR_WIFI_MODE),                          /* 12293 0x3005 WiFi mode error */
+#   endif
+#   ifdef      ESP_ERR_WIFI_STATE
+    ERR_TBL_IT(ESP_ERR_WIFI_STATE),                         /* 12294 0x3006 WiFi internal state error */
+#   endif
+#   ifdef      ESP_ERR_WIFI_CONN
+    ERR_TBL_IT(ESP_ERR_WIFI_CONN),                          /* 12295 0x3007 WiFi internal control block of station or
+                                                                            soft-AP error */
+#   endif
+#   ifdef      ESP_ERR_WIFI_NVS
+    ERR_TBL_IT(ESP_ERR_WIFI_NVS),                           /* 12296 0x3008 WiFi internal NVS module error */
+#   endif
+#   ifdef      ESP_ERR_WIFI_MAC
+    ERR_TBL_IT(ESP_ERR_WIFI_MAC),                           /* 12297 0x3009 MAC address is invalid */
+#   endif
+#   ifdef      ESP_ERR_WIFI_SSID
+    ERR_TBL_IT(ESP_ERR_WIFI_SSID),                          /* 12298 0x300a SSID is invalid */
+#   endif
+#   ifdef      ESP_ERR_WIFI_PASSWORD
+    ERR_TBL_IT(ESP_ERR_WIFI_PASSWORD),                      /* 12299 0x300b Password is invalid */
+#   endif
+#   ifdef      ESP_ERR_WIFI_TIMEOUT
+    ERR_TBL_IT(ESP_ERR_WIFI_TIMEOUT),                       /* 12300 0x300c Timeout error */
+#   endif
+#   ifdef      ESP_ERR_WIFI_WAKE_FAIL
+    ERR_TBL_IT(ESP_ERR_WIFI_WAKE_FAIL),                     /* 12301 0x300d WiFi is in sleep state(RF closed) and wakeup fail */
+#   endif
+#   ifdef      ESP_ERR_WIFI_WOULD_BLOCK
+    ERR_TBL_IT(ESP_ERR_WIFI_WOULD_BLOCK),                   /* 12302 0x300e The caller would block */
+#   endif
+#   ifdef      ESP_ERR_WIFI_NOT_CONNECT
+    ERR_TBL_IT(ESP_ERR_WIFI_NOT_CONNECT),                   /* 12303 0x300f Station still in disconnect status */
+#   endif
+    // components/esp32/include/esp_wps.h
+#   ifdef      ESP_ERR_WIFI_REGISTRAR
+    ERR_TBL_IT(ESP_ERR_WIFI_REGISTRAR),                     /* 12339 0x3033 WPS registrar is not supported */
+#   endif
+#   ifdef      ESP_ERR_WIFI_WPS_TYPE
+    ERR_TBL_IT(ESP_ERR_WIFI_WPS_TYPE),                      /* 12340 0x3034 WPS type error */
+#   endif
+#   ifdef      ESP_ERR_WIFI_WPS_SM
+    ERR_TBL_IT(ESP_ERR_WIFI_WPS_SM),                        /* 12341 0x3035 WPS state machine is not initialized */
+#   endif
+    // components/esp32/include/esp_now.h
+#   ifdef      ESP_ERR_ESPNOW_NOT_INIT
+    ERR_TBL_IT(ESP_ERR_ESPNOW_NOT_INIT),                    /* 12389 0x3065 ESPNOW is not initialized. */
+#   endif
+#   ifdef      ESP_ERR_ESPNOW_BASE
+    ERR_TBL_IT(ESP_ERR_ESPNOW_BASE),                        /* 12389 0x3065 ESPNOW error number base. */
+#   endif
+#   ifdef      ESP_ERR_ESPNOW_ARG
+    ERR_TBL_IT(ESP_ERR_ESPNOW_ARG),                         /* 12390 0x3066 Invalid argument */
+#   endif
+#   ifdef      ESP_ERR_ESPNOW_NO_MEM
+    ERR_TBL_IT(ESP_ERR_ESPNOW_NO_MEM),                      /* 12391 0x3067 Out of memory */
+#   endif
+#   ifdef      ESP_ERR_ESPNOW_FULL
+    ERR_TBL_IT(ESP_ERR_ESPNOW_FULL),                        /* 12392 0x3068 ESPNOW peer list is full */
+#   endif
+#   ifdef      ESP_ERR_ESPNOW_NOT_FOUND
+    ERR_TBL_IT(ESP_ERR_ESPNOW_NOT_FOUND),                   /* 12393 0x3069 ESPNOW peer is not found */
+#   endif
+#   ifdef      ESP_ERR_ESPNOW_INTERNAL
+    ERR_TBL_IT(ESP_ERR_ESPNOW_INTERNAL),                    /* 12394 0x306a Internal error */
+#   endif
+#   ifdef      ESP_ERR_ESPNOW_EXIST
+    ERR_TBL_IT(ESP_ERR_ESPNOW_EXIST),                       /* 12395 0x306b ESPNOW peer has existed */
+#   endif
+#   ifdef      ESP_ERR_ESPNOW_IF
+    ERR_TBL_IT(ESP_ERR_ESPNOW_IF),                          /* 12396 0x306c Interface error */
+#   endif
+    // components/tcpip_adapter/include/tcpip_adapter.h
+#   ifdef      ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS
+    ERR_TBL_IT(ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS),       /* 20480 0x5000 */
+#   endif
+#   ifdef      ESP_ERR_TCPIP_ADAPTER_BASE
+    ERR_TBL_IT(ESP_ERR_TCPIP_ADAPTER_BASE),                 /* 20480 0x5000 */
+#   endif
+#   ifdef      ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY
+    ERR_TBL_IT(ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY),         /* 20481 0x5001 */
+#   endif
+#   ifdef      ESP_ERR_TCPIP_ADAPTER_DHCPC_START_FAILED
+    ERR_TBL_IT(ESP_ERR_TCPIP_ADAPTER_DHCPC_START_FAILED),   /* 20482 0x5002 */
+#   endif
+#   ifdef      ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STARTED
+    ERR_TBL_IT(ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STARTED), /* 20483 0x5003 */
+#   endif
+#   ifdef      ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STOPPED
+    ERR_TBL_IT(ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STOPPED), /* 20484 0x5004 */
+#   endif
+#   ifdef      ESP_ERR_TCPIP_ADAPTER_NO_MEM
+    ERR_TBL_IT(ESP_ERR_TCPIP_ADAPTER_NO_MEM),               /* 20485 0x5005 */
+#   endif
+#   ifdef      ESP_ERR_TCPIP_ADAPTER_DHCP_NOT_STOPPED
+    ERR_TBL_IT(ESP_ERR_TCPIP_ADAPTER_DHCP_NOT_STOPPED),     /* 20486 0x5006 */
+#   endif
+    // components/lwip/apps/ping/esp_ping.h
+#   ifdef      ESP_ERR_PING_INVALID_PARAMS
+    ERR_TBL_IT(ESP_ERR_PING_INVALID_PARAMS),                /* 24576 0x6000 */
+#   endif
+#   ifdef      ESP_ERR_PING_BASE
+    ERR_TBL_IT(ESP_ERR_PING_BASE),                          /* 24576 0x6000 */
+#   endif
+#   ifdef      ESP_ERR_PING_NO_MEM
+    ERR_TBL_IT(ESP_ERR_PING_NO_MEM),                        /* 24577 0x6001 */
+#   endif
+    // components/spi_flash/include/esp_spi_flash.h
+#   ifdef      ESP_ERR_FLASH_BASE
+    ERR_TBL_IT(ESP_ERR_FLASH_BASE),                         /* 65552 0x10010 */
+#   endif
+#   ifdef      ESP_ERR_FLASH_OP_FAIL
+    ERR_TBL_IT(ESP_ERR_FLASH_OP_FAIL),                      /* 65553 0x10011 */
+#   endif
+#   ifdef      ESP_ERR_FLASH_OP_TIMEOUT
+    ERR_TBL_IT(ESP_ERR_FLASH_OP_TIMEOUT),                   /* 65554 0x10012 */
+#   endif
+};
+
+static const char esp_unknown_msg[] = "UNKNOWN ERROR";
+
+const char *esp_err_to_name(esp_err_t code)
+{
+    int i;
+
+    for (i = 0; i < sizeof(esp_err_msg_table)/sizeof(esp_err_msg_table[0]); ++i) {
+        if (esp_err_msg_table[i].code == code) {
+            return esp_err_msg_table[i].msg;
+        }
+    }
+
+    return esp_unknown_msg;
+}
+
+const char *esp_err_to_name_r(esp_err_t code, char *buf, size_t buflen)
+{
+    int i;
+
+    for (i = 0; i < sizeof(esp_err_msg_table)/sizeof(esp_err_msg_table[0]); ++i) {
+        if (esp_err_msg_table[i].code == code) {
+            strlcpy(buf, esp_err_msg_table[i].msg, buflen);
+            return buf;
+        }
+    }
+
+    if (strerror_r(code, buf, buflen) == 0) {
+        return buf;
+    }
+
+    snprintf(buf, buflen, "Unknown error %d", code);
+
+    return buf;
+}
diff --git a/components/esp32/esp_err_to_name.c.in b/components/esp32/esp_err_to_name.c.in
new file mode 100644 (file)
index 0000000..86085bb
--- /dev/null
@@ -0,0 +1,53 @@
+@COMMENT@
+
+#include <string.h>
+#if __has_include("soc/soc.h")
+#include "soc/soc.h"
+#endif
+@HEADERS@
+
+#define ERR_TBL_IT(err)    {err, #err}
+
+typedef struct {
+    esp_err_t code;
+    const char *msg;
+} esp_err_msg_t;
+
+static const esp_err_msg_t esp_err_msg_table[] = {
+@ERROR_ITEMS@
+};
+
+static const char esp_unknown_msg[] = "UNKNOWN ERROR";
+
+const char *esp_err_to_name(esp_err_t code)
+{
+    int i;
+
+    for (i = 0; i < sizeof(esp_err_msg_table)/sizeof(esp_err_msg_table[0]); ++i) {
+        if (esp_err_msg_table[i].code == code) {
+            return esp_err_msg_table[i].msg;
+        }
+    }
+
+    return esp_unknown_msg;
+}
+
+const char *esp_err_to_name_r(esp_err_t code, char *buf, size_t buflen)
+{
+    int i;
+
+    for (i = 0; i < sizeof(esp_err_msg_table)/sizeof(esp_err_msg_table[0]); ++i) {
+        if (esp_err_msg_table[i].code == code) {
+            strlcpy(buf, esp_err_msg_table[i].msg, buflen);
+            return buf;
+        }
+    }
+
+    if (strerror_r(code, buf, buflen) == 0) {
+        return buf;
+    }
+
+    snprintf(buf, buflen, "Unknown error %d", code);
+
+    return buf;
+}
index 5486b1410528b56fa26a60b47d1762e84f10b7f9..8bed65cd3c74ca7b6a6c93195abd1b1a9a63edc7 100644 (file)
@@ -42,6 +42,39 @@ typedef int32_t esp_err_t;
 
 #define ESP_ERR_WIFI_BASE       0x3000 /*!< Starting number of WiFi error codes */
 
+/**
+  * @brief Returns string for esp_err_t error codes
+  *
+  * This function finds the error code in a pre-generated lookup-table and
+  * returns its string representation.
+  *
+  * The function is generated by the Python script
+  * tools/gen_esp_err_to_name.py which should be run each time an esp_err_t
+  * error is modified, created or removed from the IDF project.
+  *
+  * @param code esp_err_t error code
+  * @return string error message
+  */
+const char *esp_err_to_name(esp_err_t code);
+
+/**
+  * @brief Returns string for esp_err_t and system error codes
+  *
+  * This function finds the error code in a pre-generated lookup-table of
+  * esp_err_t errors and returns its string representation. If the error code
+  * is not found then it is attempted to be found among system errors.
+  *
+  * The function is generated by the Python script
+  * tools/gen_esp_err_to_name.py which should be run each time an esp_err_t
+  * error is modified, created or removed from the IDF project.
+  *
+  * @param code esp_err_t error code
+  * @param[out] buf buffer where the error message should be written
+  * @param buflen Size of buffer buf. At most buflen bytes are written into the buf buffer (including the terminating null byte).
+  * @return buf containing the string error message
+  */
+const char *esp_err_to_name_r(esp_err_t code, char *buf, size_t buflen);
+
 void _esp_error_check_failed(esp_err_t rc, const char *file, int line, const char *function, const char *expression) __attribute__((noreturn));
 
 #ifndef __ASSERT_FUNC
diff --git a/tools/gen_esp_err_to_name.py b/tools/gen_esp_err_to_name.py
new file mode 100755 (executable)
index 0000000..1dfe15b
--- /dev/null
@@ -0,0 +1,300 @@
+#!/usr/bin/env python
+#
+# Copyright 2018 Espressif Systems (Shanghai) PTE LTD
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import os
+import argparse
+import mmap
+import re
+import fnmatch
+import string
+import collections
+import textwrap
+
+# list files here which should not be parsed
+ignore_files = [ 'components/mdns/test_afl_fuzz_host/esp32_compat.h' ]
+
+# macros from here have higher priorities in case of collisions
+priority_headers = [ 'components/esp32/include/esp_err.h' ]
+
+err_dict = collections.defaultdict(list) #identified errors are stored here; mapped by the error code
+rev_err_dict = dict() #map of error string to error code
+unproc_list = list() #errors with unknown codes which depend on other errors
+
+class ErrItem:
+    """
+    Contains information about the error:
+    - name - error string
+    - file - relative path inside the IDF project to the file which defines this error
+    - comment - (optional) comment for the error
+    - rel_str - (optional) error string which is a base for the error
+    - rel_off - (optional) offset in relation to the base error
+    """
+    def __init__(self, name, file, comment, rel_str = "", rel_off = 0):
+        self.name = name
+        self.file = file
+        self.comment = comment
+        self.rel_str = rel_str
+        self.rel_off = rel_off
+    def __str__(self):
+        ret = self.name + " from " + self.file
+        if (self.rel_str != ""):
+            ret += " is (" + self.rel_str + " + " + str(self.rel_off) + ")"
+        if self.comment != "":
+            ret += " // " + self.comment
+        return ret
+    def __cmp__(self, other):
+        if self.file in priority_headers and other.file not in priority_headers:
+            return -1
+        elif self.file not in priority_headers and other.file in priority_headers:
+            return 1
+
+        base = "_BASE"
+
+        if self.file == other.file:
+            if self.name.endswith(base) and not(other.name.endswith(base)):
+                return 1
+            elif not(self.name.endswith(base)) and other.name.endswith(base):
+                return -1
+
+        self_key = self.file + self.name
+        other_key = other.file + other.name
+        if self_key < other_key:
+            return -1
+        elif self_key > other_key:
+            return 1
+        else:
+            return 0
+
+class InputError(RuntimeError):
+    """
+    Represents and error on the input
+    """
+    def __init__(self, p, e):
+        super(InputError, self).__init__(p + ": " + e)
+
+def process(line, idf_path):
+    """
+    Process a line of text from file idf_path (relative to IDF project).
+    Fills the global list unproc_list and dictionaries err_dict, rev_err_dict
+    """
+    if idf_path.endswith(".c"):
+        # We would not try to include a C file
+        raise InputError(idf_path, "This line should be in a header file: %s" % line)
+
+    words = re.split(r' +', line, 2)
+    # words[1] is the error name
+    # words[2] is the rest of the line (value, base + value, comment)
+    if len(words) < 2:
+        raise InputError(idf_path, "Error at line %s" % line)
+
+    line = ""
+    todo_str = words[2]
+
+    comment = ""
+    # identify possible comment
+    m = re.search(r'/\*!<(.+?(?=\*/))', todo_str)
+    if m:
+        comment = string.strip(m.group(1))
+        todo_str = string.strip(todo_str[:m.start()]) # keep just the part before the comment
+
+    # identify possible parentheses ()
+    m = re.search(r'\((.+)\)', todo_str)
+    if m:
+        todo_str = m.group(1) #keep what is inside the parentheses
+
+    # identify BASE error code, e.g. from the form BASE + 0x01
+    m = re.search(r'\s*(\w+)\s*\+(.+)', todo_str)
+    if m:
+        related = m.group(1) # BASE
+        todo_str = m.group(2) # keep and process only what is after "BASE +"
+
+    # try to match a hexadecimal number
+    m = re.search(r'0x([0-9A-Fa-f]+)', todo_str)
+    if m:
+        num = int(m.group(1), 16)
+    else:
+        # Try to match a decimal number. Negative value is possible for some numbers, e.g. ESP_FAIL
+        m = re.search(r'(-?[0-9]+)', todo_str)
+        if m:
+            num = int(m.group(1), 10)
+        elif re.match(r'\w+', todo_str):
+            # It is possible that there is no number, e.g. #define ERROR BASE
+            related = todo_str # BASE error
+            num = 0 # (BASE + 0)
+        else:
+            raise InputError(idf_path, "Cannot parse line %s" % line)
+
+    try:
+        related
+    except NameError:
+        # The value of the error is known at this moment because it do not depends on some other BASE error code
+        err_dict[num].append(ErrItem(words[1], idf_path, comment))
+        rev_err_dict[words[1]] = num
+    else:
+        # Store the information available now and compute the error code later
+        unproc_list.append(ErrItem(words[1], idf_path, comment, related, num))
+
+def process_remaining_errors():
+    """
+    Create errors which could not be processed before because the error code
+    for the BASE error code wasn't known.
+    This works for sure only if there is no multiple-time dependency, e.g.:
+        #define BASE1   0
+        #define BASE2   (BASE1 + 10)
+        #define ERROR   (BASE2 + 10) - ERROR will be processed successfully only if it processed later than BASE2
+    """
+    for item in unproc_list:
+        if item.rel_str in rev_err_dict:
+            base_num = rev_err_dict[item.rel_str]
+            base = err_dict[base_num][0]
+            num = base_num + item.rel_off
+            err_dict[num].append(ErrItem(item.name, item.file, item.comment))
+            rev_err_dict[item.name] = num
+        else:
+            print(item.rel_str + " referenced by " + item.name + " in " + item.file + " is unknown")
+
+    del unproc_list[:]
+
+def path_to_include(path):
+    """
+    Process the path (relative to the IDF project) in a form which can be used
+    to include in a C file. Using just the filename does not work all the
+    time because some files are deeper in the tree. This approach tries to
+    find an 'include' parent directory an include its subdirectories, e.g.
+    "components/XY/include/esp32/file.h" will be transported into "esp32/file.h"
+    So this solution works only works when the subdirectory or subdirectories
+    are inside the "include" directory. Other special cases need to be handled
+    here when the compiler gives an unknown header file error message.
+    """
+    spl_path = string.split(path, os.sep)
+    try:
+        i = spl_path.index('include')
+    except ValueError:
+        # no include in the path -> use just the filename
+        return os.path.basename(path)
+    else:
+        return str(os.sep).join(spl_path[i+1:]) # subdirectories and filename in "include"
+
+def print_warning(error_list, error_code):
+    """
+    Print warning about errors with the same error code
+    """
+    print("[WARNING] The following errors have the same code (%d):" % error_code)
+    for e in error_list:
+        print("    " + str(e))
+
+def max_string_width():
+    max = 0
+    for k in err_dict.keys():
+        for e in err_dict[k]:
+            x = len(e.name)
+            if x > max:
+                max = x
+    return max
+
+def generate_output(fin, fout):
+    """
+    Writes the output to fout based on th error dictionary err_dict and
+    template file fin.
+    """
+    # make includes unique by using a set
+    includes = set()
+    for k in err_dict.keys():
+        for e in err_dict[k]:
+            includes.add(path_to_include(e.file))
+
+    # The order in a set in non-deterministic therefore it could happen that the
+    # include order will be different in other machines and false difference
+    # in the output file could be reported. In order to avoid this, the items
+    # are sorted in a list.
+    include_list = list(includes)
+    include_list.sort()
+
+    max_width = max_string_width() + 17 + 1 # length of "    ERR_TBL_IT()," with spaces is 17
+    max_decdig = max(len(str(k)) for k in err_dict.keys())
+
+    for line in fin:
+        if re.match(r'@COMMENT@', line):
+            fout.write("//Do not edit this file because it is autogenerated by " + os.path.basename(__file__) + "\n")
+
+        elif re.match(r'@HEADERS@', line):
+            for i in include_list:
+                fout.write("#if __has_include(\"" + i + "\")\n#include \"" + i + "\"\n#endif\n")
+        elif re.match(r'@ERROR_ITEMS@', line):
+            last_file = ""
+            for k in sorted(err_dict.keys()):
+                if len(err_dict[k]) > 1:
+                    err_dict[k].sort()
+                    print_warning(err_dict[k], k)
+                for e in err_dict[k]:
+                    if e.file != last_file:
+                        last_file = e.file
+                        fout.write("    // %s\n" % last_file)
+                    table_line = ("    ERR_TBL_IT(" + e.name + "), ").ljust(max_width) + "/* " + str(k).rjust(max_decdig)
+                    fout.write("#   ifdef      %s\n" % e.name)
+                    fout.write(table_line)
+                    hexnum_length = 0
+                    if k > 0: # negative number and zero should be only ESP_FAIL and ESP_OK
+                        hexnum = " 0x%x" % k
+                        hexnum_length = len(hexnum)
+                        fout.write(hexnum)
+                    if e.comment != "":
+                        if len(e.comment) < 50:
+                            fout.write(" %s" % e.comment)
+                        else:
+                            indent = " " * (len(table_line) + hexnum_length + 1)
+                            w = textwrap.wrap(e.comment, width=120, initial_indent = indent, subsequent_indent = indent)
+                            # this couldn't be done with initial_indent because there is no initial_width option
+                            fout.write(" %s" % w[0].strip())
+                            for i in range(1, len(w)):
+                                fout.write("\n%s" % w[i])
+                    fout.write(" */\n#   endif\n")
+        else:
+            fout.write(line)
+
+def main():
+    parser = argparse.ArgumentParser(description='ESP32 esp_err_to_name lookup generator for esp_err_t')
+    parser.add_argument('input', help='Path to the esp_err_to_name.c.in template input.', default=os.environ['IDF_PATH'] + '/components/esp32/esp_err_to_name.c.in', nargs='?')
+    parser.add_argument('output', help='Path to the esp_err_to_name.c output.', default=os.environ['IDF_PATH'] + '/components/esp32/esp_err_to_name.c', nargs='?')
+    args = parser.parse_args()
+
+    for root, dirnames, filenames in os.walk(os.environ['IDF_PATH']):
+        for filename in fnmatch.filter(filenames, '*.[ch]'):
+            full_path = os.path.join(root, filename)
+            idf_path = os.path.relpath(full_path, os.environ['IDF_PATH'])
+            if idf_path in ignore_files:
+                continue
+            with open(full_path, "r+b") as f:
+                try:
+                    map = mmap.mmap(f.fileno(), 0, prot=mmap.ACCESS_READ)
+                except ValueError:
+                    pass # An empty file cannot be mmaped
+                else:
+                    for line in iter(map.readline, ""):
+                        # match also ESP_OK and ESP_FAIL because some of ESP_ERRs are referencing them
+                        if re.match(r"\s*#define\s+(ESP_ERR_|ESP_OK|ESP_FAIL)", line):
+                            try:
+                                process(str.strip(line), idf_path)
+                            except InputError as e:
+                                print (e)
+
+    process_remaining_errors()
+
+    with open(args.input, 'r') as fin, open(args.output, 'w') as fout:
+        generate_output(fin, fout)
+
+if __name__ == "__main__":
+    main()