diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 14c870267..720c06728 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -65,7 +65,7 @@ build_template_app: IDF_PATH: "$CI_PROJECT_DIR" GIT_STRATEGY: clone BATCH_BUILD: "1" - + V: "0" build_ssc: <<: *build_template @@ -79,7 +79,6 @@ build_ssc: - cd SSC - git checkout ${CI_BUILD_REF_NAME} || echo "Using SSC default branch..." - make defconfig - - chmod +x gen_misc_ng.sh - ./gen_misc_ng.sh build_at: @@ -151,6 +150,18 @@ test_nvs_on_host: - cd components/nvs_flash/test_nvs_host - make test +test_wl_on_host: + stage: test + image: $CI_DOCKER_REGISTRY/esp32-ci-env + tags: + - wl_host_test + artifacts: + paths: + - components/wear_levelling/test_wl_host/coverage_report.zip + script: + - cd components/wear_levelling/test_wl_host + - make test + test_build_system: stage: test image: $CI_DOCKER_REGISTRY/esp32-ci-env diff --git a/components/bootloader/src/main/bootloader_start.c b/components/bootloader/src/main/bootloader_start.c index af729c705..aa30ad4c7 100644 --- a/components/bootloader/src/main/bootloader_start.c +++ b/components/bootloader/src/main/bootloader_start.c @@ -19,6 +19,7 @@ #include "esp_log.h" #include "rom/cache.h" +#include "rom/efuse.h" #include "rom/ets_sys.h" #include "rom/spi_flash.h" #include "rom/crc.h" @@ -73,6 +74,7 @@ static void set_cache_and_start_app(uint32_t drom_addr, uint32_t entry_addr); static void update_flash_config(const esp_image_header_t* pfhdr); static void uart_console_configure(void); +static void wdt_reset_check(void); void IRAM_ATTR call_start_cpu0() { @@ -238,12 +240,14 @@ void bootloader_main() /* Set CPU to 80MHz. Keep other clocks unmodified. */ uart_tx_wait_idle(0); rtc_clk_config_t clk_cfg = RTC_CLK_CONFIG_DEFAULT(); + clk_cfg.xtal_freq = CONFIG_ESP32_XTAL_FREQ; clk_cfg.cpu_freq = RTC_CPU_FREQ_80M; clk_cfg.slow_freq = rtc_clk_slow_freq_get(); clk_cfg.fast_freq = rtc_clk_fast_freq_get(); rtc_clk_init(clk_cfg); uart_console_configure(); + wdt_reset_check(); ESP_LOGI(TAG, "ESP-IDF %s 2nd stage bootloader", IDF_VER); #if defined(CONFIG_SECURE_BOOT_ENABLED) || defined(CONFIG_FLASH_ENCRYPTION_ENABLED) esp_err_t err; @@ -260,6 +264,15 @@ void bootloader_main() /* disable watch dog here */ REG_CLR_BIT( RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_FLASHBOOT_MOD_EN ); REG_CLR_BIT( TIMG_WDTCONFIG0_REG(0), TIMG_WDT_FLASHBOOT_MOD_EN ); + +#ifndef CONFIG_SPI_FLASH_ROM_DRIVER_PATCH + const uint32_t spiconfig = ets_efuse_get_spiconfig(); + if(spiconfig != EFUSE_SPICONFIG_SPI_DEFAULTS && spiconfig != EFUSE_SPICONFIG_HSPI_DEFAULTS) { + ESP_LOGE(TAG, "SPI flash pins are overridden. \"Enable SPI flash ROM driver patched functions\" must be enabled in menuconfig"); + return; + } +#endif + esp_rom_spiflash_unlock(); ESP_LOGI(TAG, "Enabling RNG early entropy source..."); @@ -728,3 +741,81 @@ static void uart_console_configure(void) #endif // CONFIG_CONSOLE_UART_NONE } + +static void wdt_reset_info_enable(void) +{ + REG_SET_BIT(DPORT_PRO_CPU_RECORD_CTRL_REG, DPORT_PRO_CPU_PDEBUG_ENABLE | DPORT_PRO_CPU_RECORD_ENABLE); + REG_CLR_BIT(DPORT_PRO_CPU_RECORD_CTRL_REG, DPORT_PRO_CPU_RECORD_ENABLE); + REG_SET_BIT(DPORT_APP_CPU_RECORD_CTRL_REG, DPORT_APP_CPU_PDEBUG_ENABLE | DPORT_APP_CPU_RECORD_ENABLE); + REG_CLR_BIT(DPORT_APP_CPU_RECORD_CTRL_REG, DPORT_APP_CPU_RECORD_ENABLE); +} + +static void wdt_reset_info_dump(int cpu) +{ + uint32_t inst = 0, pid = 0, stat = 0, data = 0, pc = 0, + lsstat = 0, lsaddr = 0, lsdata = 0, dstat = 0; + char *cpu_name = cpu ? "APP" : "PRO"; + + if (cpu == 0) { + stat = REG_READ(DPORT_PRO_CPU_RECORD_STATUS_REG); + pid = REG_READ(DPORT_PRO_CPU_RECORD_PID_REG); + inst = REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGINST_REG); + dstat = REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGSTATUS_REG); + data = REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGDATA_REG); + pc = REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGPC_REG); + lsstat = REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGLS0STAT_REG); + lsaddr = REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGLS0ADDR_REG); + lsdata = REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGLS0DATA_REG); + + } else { + stat = REG_READ(DPORT_APP_CPU_RECORD_STATUS_REG); + pid = REG_READ(DPORT_APP_CPU_RECORD_PID_REG); + inst = REG_READ(DPORT_APP_CPU_RECORD_PDEBUGINST_REG); + dstat = REG_READ(DPORT_APP_CPU_RECORD_PDEBUGSTATUS_REG); + data = REG_READ(DPORT_APP_CPU_RECORD_PDEBUGDATA_REG); + pc = REG_READ(DPORT_APP_CPU_RECORD_PDEBUGPC_REG); + lsstat = REG_READ(DPORT_APP_CPU_RECORD_PDEBUGLS0STAT_REG); + lsaddr = REG_READ(DPORT_APP_CPU_RECORD_PDEBUGLS0ADDR_REG); + lsdata = REG_READ(DPORT_APP_CPU_RECORD_PDEBUGLS0DATA_REG); + } + if (DPORT_RECORD_PDEBUGINST_SZ(inst) == 0 && + DPORT_RECORD_PDEBUGSTATUS_BBCAUSE(dstat) == DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_WAITI) { + ESP_LOGW(TAG, "WDT reset info: %s CPU PC=0x%x (waiti mode)", cpu_name, pc); + } else { + ESP_LOGW(TAG, "WDT reset info: %s CPU PC=0x%x", cpu_name, pc); + } + ESP_LOGD(TAG, "WDT reset info: %s CPU STATUS 0x%08x", cpu_name, stat); + ESP_LOGD(TAG, "WDT reset info: %s CPU PID 0x%08x", cpu_name, pid); + ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGINST 0x%08x", cpu_name, inst); + ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGSTATUS 0x%08x", cpu_name, dstat); + ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGDATA 0x%08x", cpu_name, data); + ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGPC 0x%08x", cpu_name, pc); + ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGLS0STAT 0x%08x", cpu_name, lsstat); + ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGLS0ADDR 0x%08x", cpu_name, lsaddr); + ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGLS0DATA 0x%08x", cpu_name, lsdata); +} + +static void wdt_reset_check(void) +{ + int wdt_rst = 0; + RESET_REASON rst_reas[2]; + + rst_reas[0] = rtc_get_reset_reason(0); + rst_reas[1] = rtc_get_reset_reason(1); + if (rst_reas[0] == RTCWDT_SYS_RESET || rst_reas[0] == TG0WDT_SYS_RESET || rst_reas[0] == TG1WDT_SYS_RESET || + rst_reas[0] == TGWDT_CPU_RESET || rst_reas[0] == RTCWDT_CPU_RESET) { + ESP_LOGW(TAG, "PRO CPU has been reset by WDT."); + wdt_rst = 1; + } + if (rst_reas[1] == RTCWDT_SYS_RESET || rst_reas[1] == TG0WDT_SYS_RESET || rst_reas[1] == TG1WDT_SYS_RESET || + rst_reas[1] == TGWDT_CPU_RESET || rst_reas[1] == RTCWDT_CPU_RESET) { + ESP_LOGW(TAG, "APP CPU has been reset by WDT."); + wdt_rst = 1; + } + if (wdt_rst) { + // if reset by WDT dump info from trace port + wdt_reset_info_dump(0); + wdt_reset_info_dump(1); + } + wdt_reset_info_enable(); +} diff --git a/components/bootloader/src/main/flash_qio_mode.c b/components/bootloader/src/main/flash_qio_mode.c index 4b2ec3088..cd288290c 100644 --- a/components/bootloader/src/main/flash_qio_mode.c +++ b/components/bootloader/src/main/flash_qio_mode.c @@ -16,7 +16,9 @@ #include "flash_qio_mode.h" #include "esp_log.h" #include "rom/spi_flash.h" +#include "rom/efuse.h" #include "soc/spi_struct.h" +#include "soc/efuse_reg.h" #include "sdkconfig.h" /* SPI flash controller */ @@ -33,6 +35,9 @@ #define CMD_RDSR 0x05 #define CMD_RDSR2 0x35 /* Not all SPI flash uses this command */ + +#define ESP32_D2WD_WP_GPIO 7 /* ESP32-D2WD has this GPIO wired to WP pin of flash */ + static const char *TAG = "qio_mode"; typedef unsigned (*read_status_fn_t)(); @@ -77,7 +82,7 @@ static void write_status_16b_wrsr(unsigned new_status); const static qio_info_t chip_data[] = { /* Manufacturer, mfg_id, flash_id, id mask, Read Status, Write Status, QIE Bit */ { "MXIC", 0xC2, 0x2000, 0xFF00, read_status_8b_rdsr, write_status_8b_wrsr, 6 }, - { "ISSI", 0x9D, 0x4000, 0xFF00, read_status_8b_rdsr, write_status_8b_wrsr, 6 }, + { "ISSI", 0x9D, 0x4000, 0xCF00, read_status_8b_rdsr, write_status_8b_wrsr, 6 }, /* IDs 0x40xx, 0x70xx */ { "WinBond", 0xEF, 0x4000, 0xFF00, read_status_16b_rdsr_rdsr2, write_status_16b_wrsr, 9 }, /* Final entry is default entry, if no other IDs have matched. @@ -102,6 +107,9 @@ static void enable_qio_mode(read_status_fn_t read_status_fn, */ static uint32_t execute_flash_command(uint8_t command, uint32_t mosi_data, uint8_t mosi_len, uint8_t miso_len); +/* dummy_len_plus values defined in ROM for SPI flash configuration */ +extern uint8_t g_rom_spiflash_dummy_len_plus[]; + void bootloader_enable_qio_mode(void) { uint32_t raw_flash_id; @@ -149,6 +157,20 @@ static void enable_qio_mode(read_status_fn_t read_status_fn, uint8_t status_qio_bit) { uint32_t status; + const uint32_t spiconfig = ets_efuse_get_spiconfig(); + + if (spiconfig != EFUSE_SPICONFIG_SPI_DEFAULTS && spiconfig != EFUSE_SPICONFIG_HSPI_DEFAULTS) { + // spiconfig specifies a custom efuse pin configuration. This config defines all pins -except- WP. + // + // For now, in this situation we only support Quad I/O mode for ESP32-D2WD where WP pin is known. + uint32_t chip_ver = REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_RESERVE); + uint32_t pkg_ver = chip_ver & 0x7; + const uint32_t PKG_VER_ESP32_D2WD = 2; // TODO: use chip detection API once available + if (pkg_ver != PKG_VER_ESP32_D2WD) { + ESP_LOGE(TAG, "Quad I/O is only supported for standard pin numbers or ESP32-D2WD. Falling back to Dual I/O."); + return; + } + } esp_rom_spiflash_wait_idle(&g_rom_flashchip); @@ -180,7 +202,10 @@ static void enable_qio_mode(read_status_fn_t read_status_fn, #else mode = ESP_ROM_SPIFLASH_QIO_MODE; #endif - esp_rom_spiflash_master_config_readmode(mode); + + esp_rom_spiflash_config_readmode(mode); + + esp_rom_spiflash_select_qio_pins(ESP32_D2WD_WP_GPIO, spiconfig); } static unsigned read_status_8b_rdsr() @@ -222,6 +247,17 @@ static uint32_t execute_flash_command(uint8_t command, uint32_t mosi_data, uint8 SPIFLASH.mosi_dlen.usr_mosi_dbitlen = mosi_len ? (mosi_len - 1) : 0; SPIFLASH.data_buf[0] = mosi_data; + if (g_rom_spiflash_dummy_len_plus[1]) { + /* When flash pins are mapped via GPIO matrix, need a dummy cycle before reading via MISO */ + if (miso_len > 0) { + SPIFLASH.user.usr_dummy = 1; + SPIFLASH.user1.usr_dummy_cyclelen = g_rom_spiflash_dummy_len_plus[1] - 1; + } else { + SPIFLASH.user.usr_dummy = 0; + SPIFLASH.user1.usr_dummy_cyclelen = 0; + } + } + SPIFLASH.cmd.usr = 1; while(SPIFLASH.cmd.usr != 0) { } diff --git a/components/bt/bluedroid/btc/core/btc_alarm.c b/components/bt/bluedroid/btc/core/btc_alarm.c new file mode 100644 index 000000000..15587d674 --- /dev/null +++ b/components/bt/bluedroid/btc/core/btc_alarm.c @@ -0,0 +1,27 @@ +// Copyright 2015-2016 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. + +#include "btc_task.h" +#include "btc_alarm.h" + +void btc_alarm_handler(btc_msg_t *msg) +{ + btc_alarm_args_t *arg = (btc_alarm_args_t *)msg->arg; + + LOG_DEBUG("%s act %d\n", __FUNCTION__, msg->act); + + if (arg->cb) { + arg->cb(arg->cb_data); + } +} diff --git a/components/bt/bluedroid/btc/core/btc_task.c b/components/bt/bluedroid/btc/core/btc_task.c index d576fdd76..e267f0936 100644 --- a/components/bt/bluedroid/btc/core/btc_task.c +++ b/components/bt/bluedroid/btc/core/btc_task.c @@ -26,6 +26,7 @@ #include "btc_gap_ble.h" #include "btc_blufi_prf.h" #include "btc_dm.h" +#include "btc_alarm.h" #include "bta_gatt_api.h" #if CONFIG_CLASSIC_BT_ENABLED #include "btc_gap_bt.h" @@ -48,6 +49,7 @@ static btc_func_t profile_tab[BTC_PID_NUM] = { [BTC_PID_SPPLIKE] = {NULL, NULL}, [BTC_PID_BLUFI] = {btc_blufi_call_handler, btc_blufi_cb_handler }, [BTC_PID_DM_SEC] = {NULL, btc_dm_sec_cb_handler }, + [BTC_PID_ALARM] = {btc_alarm_handler, NULL }, #if CONFIG_CLASSIC_BT_ENABLED [BTC_PID_GAP_BT] = {btc_gap_bt_call_handler, NULL }, [BTC_PID_PRF_QUE] = {btc_profile_queue_handler, NULL }, diff --git a/components/bt/bluedroid/btc/include/btc_alarm.h b/components/bt/bluedroid/btc/include/btc_alarm.h new file mode 100644 index 000000000..ca9640a3f --- /dev/null +++ b/components/bt/bluedroid/btc/include/btc_alarm.h @@ -0,0 +1,30 @@ +// Copyright 2015-2016 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. + + +#ifndef __BTC_ALARM_H__ +#define __BTC_ALARM_H__ + +#include +#include "alarm.h" + +/* btc_alarm_args_t */ +typedef struct { + osi_alarm_callback_t cb; + void *cb_data; +} btc_alarm_args_t; + +void btc_alarm_handler(btc_msg_t *msg); + +#endif /* __BTC_ALARM_H__ */ diff --git a/components/bt/bluedroid/btc/include/btc_task.h b/components/bt/bluedroid/btc/include/btc_task.h index bb8996974..9cb1fa610 100644 --- a/components/bt/bluedroid/btc/include/btc_task.h +++ b/components/bt/bluedroid/btc/include/btc_task.h @@ -44,6 +44,7 @@ typedef enum { BTC_PID_SPPLIKE, BTC_PID_BLUFI, BTC_PID_DM_SEC, + BTC_PID_ALARM, #if CONFIG_CLASSIC_BT_ENABLED BTC_PID_GAP_BT, BTC_PID_PRF_QUE, diff --git a/components/bt/bluedroid/btc/profile/esp/blufi/blufi_prf.c b/components/bt/bluedroid/btc/profile/esp/blufi/blufi_prf.c index 737919257..800f8d8d7 100644 --- a/components/bt/bluedroid/btc/profile/esp/blufi/blufi_prf.c +++ b/components/bt/bluedroid/btc/profile/esp/blufi/blufi_prf.c @@ -345,7 +345,7 @@ static void btc_blufi_send_notify(uint8_t *pkt, int pkt_len) static void btc_blufi_recv_handler(uint8_t *data, int len) { struct blufi_hdr *hdr = (struct blufi_hdr *)data; - uint16_t checksum; + uint16_t checksum, checksum_pkt; int ret; if (hdr->seq != blufi_env.recv_seq) { @@ -369,8 +369,9 @@ static void btc_blufi_recv_handler(uint8_t *data, int len) if (BLUFI_FC_IS_CHECK(hdr->fc) && (blufi_env.cbs && blufi_env.cbs->checksum_func)) { checksum = blufi_env.cbs->checksum_func(hdr->seq, &hdr->seq, hdr->data_len + 2); - if (memcmp(&checksum, &hdr->data[hdr->data_len], 2) != 0) { - LOG_ERROR("%s checksum error %04x, pkt %04x\n", __func__, checksum, *(uint16_t *)&hdr->data[hdr->data_len]); + checksum_pkt = hdr->data[hdr->data_len] | (((uint16_t) hdr->data[hdr->data_len + 1]) << 8); + if (checksum != checksum_pkt) { + LOG_ERROR("%s checksum error %04x, pkt %04x\n", __func__, checksum, checksum_pkt); return; } } @@ -381,7 +382,7 @@ static void btc_blufi_recv_handler(uint8_t *data, int len) if (BLUFI_FC_IS_FRAG(hdr->fc)) { if (blufi_env.offset == 0) { - blufi_env.total_len = *(uint16_t *)(hdr->data); + blufi_env.total_len = hdr->data[0] | (((uint16_t) hdr->data[1]) << 8); blufi_env.aggr_buf = GKI_getbuf(blufi_env.total_len); if (blufi_env.aggr_buf == NULL) { LOG_ERROR("%s no mem, len %d\n", __func__, blufi_env.total_len); @@ -420,7 +421,8 @@ void btc_blufi_send_encap(uint8_t type, uint8_t *data, int total_data_len) } hdr->fc = 0x0; hdr->data_len = blufi_env.frag_size + 2; - *(uint16_t *)hdr->data = remain_len; + hdr->data[0] = remain_len & 0xff; + hdr->data[1] = (remain_len >> 8) & 0xff; memcpy(hdr->data + 2, &data[total_data_len - remain_len], blufi_env.frag_size); //copy first, easy for check sum hdr->fc |= BLUFI_FC_FRAG; } else { diff --git a/components/bt/bluedroid/osi/alarm.c b/components/bt/bluedroid/osi/alarm.c index 3d36be727..4ac903cc4 100644 --- a/components/bt/bluedroid/osi/alarm.c +++ b/components/bt/bluedroid/osi/alarm.c @@ -27,6 +27,8 @@ #include "freertos/FreeRTOSConfig.h" #include "freertos/xtensa_api.h" #include "rom/ets_sys.h" +#include "btc_task.h" +#include "btc_alarm.h" #define RTC_TIMER_TICKS_TO_MS(ticks) (((ticks/625)<<1) + (ticks-(ticks/625)*625)/312) @@ -122,17 +124,21 @@ static struct alarm_t *alarm_cbs_lookfor_available(void) static void alarm_cb_handler(TimerHandle_t xTimer) { struct alarm_t *alarm; - if (!xTimer) { LOG_ERROR("TimerName: NULL\n"); return; } - + alarm = pvTimerGetTimerID(xTimer); LOG_DEBUG("TimerID %p, Name %s\n", alarm, pcTimerGetTimerName(xTimer)); - if (alarm->cb) { - alarm->cb(alarm->cb_data); - } + + btc_msg_t msg; + btc_alarm_args_t arg; + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_ALARM; + arg.cb = alarm->cb; + arg.cb_data = alarm->cb_data; + btc_transfer_context(&msg, &arg, sizeof(btc_alarm_args_t), NULL); } osi_alarm_t *osi_alarm_new(char *alarm_name, osi_alarm_callback_t callback, void *data, period_ms_t timer_expire) diff --git a/components/bt/bluedroid/stack/btu/btu_task.c b/components/bt/bluedroid/stack/btu/btu_task.c index 4c640fad7..feaa50faf 100644 --- a/components/bt/bluedroid/stack/btu/btu_task.c +++ b/components/bt/bluedroid/stack/btu/btu_task.c @@ -223,8 +223,11 @@ static void btu_hci_msg_process(BT_HDR *p_msg) /* Determine the input message type. */ switch (p_msg->event & BT_EVT_MASK) { case BTU_POST_TO_TASK_NO_GOOD_HORRIBLE_HACK: // TODO(zachoverflow): remove this - ((post_to_task_hack_t *)(&p_msg->data[0]))->callback(p_msg); + { + post_to_task_hack_t *ph = (post_to_task_hack_t *) &p_msg->data[0]; + ph->callback(p_msg); break; + } case BT_EVT_TO_BTU_HCI_ACL: /* All Acl Data goes to L2CAP */ l2c_rcv_acl_data (p_msg); diff --git a/components/driver/gpio.c b/components/driver/gpio.c index f1e724dd5..0fc9adec3 100644 --- a/components/driver/gpio.c +++ b/components/driver/gpio.c @@ -270,7 +270,7 @@ esp_err_t gpio_set_direction(gpio_num_t gpio_num, gpio_mode_t mode) return ret; } -esp_err_t gpio_config(gpio_config_t *pGPIOConfig) +esp_err_t gpio_config(const gpio_config_t *pGPIOConfig) { uint64_t gpio_pin_mask = (pGPIOConfig->pin_bit_mask); uint32_t io_reg = 0; diff --git a/components/driver/i2c.c b/components/driver/i2c.c index f286c657a..ec80d75c2 100644 --- a/components/driver/i2c.c +++ b/components/driver/i2c.c @@ -429,7 +429,7 @@ esp_err_t i2c_get_data_mode(i2c_port_t i2c_num, i2c_trans_mode_t *tx_trans_mode, return ESP_OK; } -esp_err_t i2c_param_config(i2c_port_t i2c_num, i2c_config_t* i2c_conf) +esp_err_t i2c_param_config(i2c_port_t i2c_num, const i2c_config_t* i2c_conf) { I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG); I2C_CHECK(i2c_conf != NULL, I2C_ADDR_ERROR_STR, ESP_ERR_INVALID_ARG); diff --git a/components/driver/include/driver/gpio.h b/components/driver/include/driver/gpio.h index 485afb696..f044964da 100644 --- a/components/driver/include/driver/gpio.h +++ b/components/driver/include/driver/gpio.h @@ -221,7 +221,7 @@ typedef intr_handle_t gpio_isr_handle_t; * - ESP_ERR_INVALID_ARG Parameter error * */ -esp_err_t gpio_config(gpio_config_t *pGPIOConfig); +esp_err_t gpio_config(const gpio_config_t *pGPIOConfig); /** diff --git a/components/driver/include/driver/i2c.h b/components/driver/include/driver/i2c.h index 960ec61d2..323a91a3c 100644 --- a/components/driver/include/driver/i2c.h +++ b/components/driver/include/driver/i2c.h @@ -135,7 +135,7 @@ esp_err_t i2c_driver_delete(i2c_port_t i2c_num); * - ESP_OK Success * - ESP_ERR_INVALID_ARG Parameter error */ -esp_err_t i2c_param_config(i2c_port_t i2c_num, i2c_config_t* i2c_conf); +esp_err_t i2c_param_config(i2c_port_t i2c_num, const i2c_config_t* i2c_conf); /** * @brief reset I2C tx hardware fifo diff --git a/components/driver/include/driver/ledc.h b/components/driver/include/driver/ledc.h index 70e21d9e4..841b1c8d7 100644 --- a/components/driver/include/driver/ledc.h +++ b/components/driver/include/driver/ledc.h @@ -115,7 +115,7 @@ typedef intr_handle_t ledc_isr_handle_t; * - ESP_OK Success * - ESP_ERR_INVALID_ARG Parameter error */ -esp_err_t ledc_channel_config(ledc_channel_config_t* ledc_conf); +esp_err_t ledc_channel_config(const ledc_channel_config_t* ledc_conf); /** * @brief LEDC timer configuration @@ -128,7 +128,7 @@ esp_err_t ledc_channel_config(ledc_channel_config_t* ledc_conf); * - ESP_ERR_INVALID_ARG Parameter error * - ESP_FAIL Can not find a proper pre-divider number base on the given frequency and the current bit_num. */ -esp_err_t ledc_timer_config(ledc_timer_config_t* timer_conf); +esp_err_t ledc_timer_config(const ledc_timer_config_t* timer_conf); /** * @brief LEDC update channel parameters diff --git a/components/driver/include/driver/pcnt.h b/components/driver/include/driver/pcnt.h index f5a10581c..38a7e41d7 100644 --- a/components/driver/include/driver/pcnt.h +++ b/components/driver/include/driver/pcnt.h @@ -88,7 +88,7 @@ typedef intr_handle_t pcnt_isr_handle_t; * - ESP_OK Success * - ESP_ERR_INVALID_ARG Parameter error */ -esp_err_t pcnt_unit_config(pcnt_config_t *pcnt_config); +esp_err_t pcnt_unit_config(const pcnt_config_t *pcnt_config); /** * @brief Get pulse counter value diff --git a/components/driver/include/driver/sigmadelta.h b/components/driver/include/driver/sigmadelta.h index db167837b..61a35c21f 100644 --- a/components/driver/include/driver/sigmadelta.h +++ b/components/driver/include/driver/sigmadelta.h @@ -57,7 +57,7 @@ typedef struct { * - ESP_OK Success * - ESP_ERR_INVALID_ARG Parameter error */ -esp_err_t sigmadelta_config(sigmadelta_config_t *config); +esp_err_t sigmadelta_config(const sigmadelta_config_t *config); /** * @brief Set Sigma-delta channel duty. diff --git a/components/driver/include/driver/spi_master.h b/components/driver/include/driver/spi_master.h index d78f5ea0b..063984df7 100644 --- a/components/driver/include/driver/spi_master.h +++ b/components/driver/include/driver/spi_master.h @@ -131,7 +131,7 @@ typedef struct spi_device_t* spi_device_handle_t; ///< Handle for a device on a * - ESP_ERR_NO_MEM if out of memory * - ESP_OK on success */ -esp_err_t spi_bus_initialize(spi_host_device_t host, spi_bus_config_t *bus_config, int dma_chan); +esp_err_t spi_bus_initialize(spi_host_device_t host, const spi_bus_config_t *bus_config, int dma_chan); /** * @brief Free a SPI bus @@ -235,4 +235,4 @@ esp_err_t spi_device_transmit(spi_device_handle_t handle, spi_transaction_t *tra } #endif -#endif \ No newline at end of file +#endif diff --git a/components/driver/include/driver/timer.h b/components/driver/include/driver/timer.h index 134fd504f..2914a90a3 100644 --- a/components/driver/include/driver/timer.h +++ b/components/driver/include/driver/timer.h @@ -287,7 +287,7 @@ esp_err_t timer_isr_register(timer_group_t group_num, timer_idx_t timer_num, voi * - ESP_OK Success * - ESP_ERR_INVALID_ARG Parameter error */ -esp_err_t timer_init(timer_group_t group_num, timer_idx_t timer_num, timer_config_t* config); +esp_err_t timer_init(timer_group_t group_num, timer_idx_t timer_num, const timer_config_t* config); /** @brief Get timer configure value. * diff --git a/components/driver/ledc.c b/components/driver/ledc.c index 7da353869..9cea7b5ec 100644 --- a/components/driver/ledc.c +++ b/components/driver/ledc.c @@ -180,7 +180,7 @@ esp_err_t ledc_isr_register(void (*fn)(void*), void * arg, int intr_alloc_flags, return ret; } -esp_err_t ledc_timer_config(ledc_timer_config_t* timer_conf) +esp_err_t ledc_timer_config(const ledc_timer_config_t* timer_conf) { int freq_hz = timer_conf->freq_hz; int bit_num = timer_conf->bit_num; @@ -245,7 +245,7 @@ esp_err_t ledc_set_pin(int gpio_num, ledc_mode_t speed_mode, ledc_channel_t ledc return ESP_OK; } -esp_err_t ledc_channel_config(ledc_channel_config_t* ledc_conf) +esp_err_t ledc_channel_config(const ledc_channel_config_t* ledc_conf) { uint32_t speed_mode = ledc_conf->speed_mode; uint32_t gpio_num = ledc_conf->gpio_num; @@ -541,6 +541,7 @@ esp_err_t ledc_set_fade_with_step(ledc_mode_t speed_mode, ledc_channel_t channel int duty_cur = LEDC.channel_group[speed_mode].channel[channel].duty_rd.duty_read >> LEDC_DUTY_DECIMAL_BIT_NUM; int duty_delta = target_duty > duty_cur ? target_duty - duty_cur : duty_cur - target_duty; if (duty_delta == 0) { + portEXIT_CRITICAL(&ledc_spinlock); return ESP_OK; } s_ledc_fade_rec[speed_mode][channel]->speed_mode = speed_mode; diff --git a/components/driver/pcnt.c b/components/driver/pcnt.c index ac4089889..9c16e92eb 100644 --- a/components/driver/pcnt.c +++ b/components/driver/pcnt.c @@ -39,7 +39,7 @@ static portMUX_TYPE pcnt_spinlock = portMUX_INITIALIZER_UNLOCKED; #define PCNT_ENTER_CRITICAL_ISR(mux) portENTER_CRITICAL_ISR(mux) #define PCNT_EXIT_CRITICAL_ISR(mux) portEXIT_CRITICAL_ISR(mux) -esp_err_t pcnt_unit_config(pcnt_config_t *pcnt_config) +esp_err_t pcnt_unit_config(const pcnt_config_t *pcnt_config) { uint8_t unit = pcnt_config->unit; uint8_t channel = pcnt_config->channel; diff --git a/components/driver/sdmmc_host.c b/components/driver/sdmmc_host.c index 706a1e3fe..2ef7b2e0c 100644 --- a/components/driver/sdmmc_host.c +++ b/components/driver/sdmmc_host.c @@ -202,6 +202,17 @@ esp_err_t sdmmc_host_set_card_clk(int slot, uint32_t freq_khz) SDMMC.clkena.cclk_enable |= BIT(slot); SDMMC.clkena.cclk_low_power |= BIT(slot); sdmmc_host_clock_update_command(slot); + + // set data timeout + const uint32_t data_timeout_ms = 100; + uint32_t data_timeout_cycles = data_timeout_ms * freq_khz; + const uint32_t data_timeout_cycles_max = 0xffffff; + if (data_timeout_cycles > data_timeout_cycles_max) { + data_timeout_cycles = data_timeout_cycles_max; + } + SDMMC.tmout.data = data_timeout_cycles; + // always set response timeout to highest value, it's small enough anyway + SDMMC.tmout.response = 255; return ESP_OK; } @@ -419,9 +430,6 @@ void sdmmc_host_dma_stop() void sdmmc_host_dma_prepare(sdmmc_desc_t* desc, size_t block_size, size_t data_size) { - // TODO: set timeout depending on data size - SDMMC.tmout.val = 0xffffffff; - // Set size of data and DMA descriptor pointer SDMMC.bytcnt = data_size; SDMMC.blksiz = block_size; diff --git a/components/driver/sdmmc_transaction.c b/components/driver/sdmmc_transaction.c index 59b439eec..92876f75a 100644 --- a/components/driver/sdmmc_transaction.c +++ b/components/driver/sdmmc_transaction.c @@ -32,6 +32,13 @@ */ #define SDMMC_DMA_DESC_CNT 4 +/* Max delay value is mostly useful for cases when CD pin is not used, and + * the card is removed. In this case, SDMMC peripheral may not always return + * CMD_DONE / DATA_DONE interrupts after signaling the error. This delay works + * as a safety net in such cases. + */ +#define SDMMC_MAX_EVT_WAIT_DELAY_MS 1000 + static const char* TAG = "sdmmc_req"; typedef enum { @@ -188,9 +195,12 @@ static esp_err_t handle_idle_state_events() static esp_err_t handle_event(sdmmc_command_t* cmd, sdmmc_req_state_t* state) { sdmmc_event_t evt; - esp_err_t err = sdmmc_host_wait_for_event(portMAX_DELAY, &evt); + esp_err_t err = sdmmc_host_wait_for_event(SDMMC_MAX_EVT_WAIT_DELAY_MS / portTICK_PERIOD_MS, &evt); if (err != ESP_OK) { - ESP_LOGE(TAG, "sdmmc_host_wait_for_event returned %d", err); + ESP_LOGE(TAG, "sdmmc_host_wait_for_event returned 0x%x", err); + if (err == ESP_ERR_TIMEOUT) { + sdmmc_host_dma_stop(); + } return err; } ESP_LOGV(TAG, "sdmmc_handle_event: evt %08x %08x", evt.sdmmc_status, evt.dma_status); @@ -268,7 +278,7 @@ static void process_command_response(uint32_t status, sdmmc_command_t* cmd) if (cmd->data) { sdmmc_host_dma_stop(); } - ESP_LOGD(TAG, "%s: error %d", __func__, cmd->error); + ESP_LOGD(TAG, "%s: error 0x%x (status=%08x)", __func__, cmd->error, status); } } @@ -291,7 +301,7 @@ static void process_data_status(uint32_t status, sdmmc_command_t* cmd) if (cmd->data) { sdmmc_host_dma_stop(); } - ESP_LOGD(TAG, "%s: error %d", __func__, cmd->error); + ESP_LOGD(TAG, "%s: error 0x%x (status=%08x)", __func__, cmd->error, status); } } @@ -323,9 +333,14 @@ static esp_err_t process_events(sdmmc_event_t evt, sdmmc_command_t* cmd, sdmmc_r case SDMMC_SENDING_CMD: if (mask_check_and_clear(&evt.sdmmc_status, SDMMC_CMD_ERR_MASK)) { process_command_response(orig_evt.sdmmc_status, cmd); - break; + if (cmd->error != ESP_ERR_TIMEOUT) { + // Unless this is a timeout error, we need to wait for the + // CMD_DONE interrupt + break; + } } - if (!mask_check_and_clear(&evt.sdmmc_status, SDMMC_INTMASK_CMD_DONE)) { + if (!mask_check_and_clear(&evt.sdmmc_status, SDMMC_INTMASK_CMD_DONE) && + cmd->error != ESP_ERR_TIMEOUT) { break; } process_command_response(orig_evt.sdmmc_status, cmd); @@ -352,6 +367,11 @@ static esp_err_t process_events(sdmmc_event_t evt, sdmmc_command_t* cmd, sdmmc_r next_state = SDMMC_BUSY; } } + if (orig_evt.sdmmc_status & (SDMMC_INTMASK_SBE | SDMMC_INTMASK_DATA_OVER)) { + // On start bit error, DATA_DONE interrupt will not be generated + next_state = SDMMC_IDLE; + break; + } break; case SDMMC_BUSY: diff --git a/components/driver/sigmadelta.c b/components/driver/sigmadelta.c index 09969e663..d68071bf7 100644 --- a/components/driver/sigmadelta.c +++ b/components/driver/sigmadelta.c @@ -25,7 +25,7 @@ static const char* SIGMADELTA_TAG = "SIGMADELTA"; return (ret_val); \ } -esp_err_t sigmadelta_config(sigmadelta_config_t *config) +esp_err_t sigmadelta_config(const sigmadelta_config_t *config) { SIGMADELTA_CHECK(config->channel < SIGMADELTA_CHANNEL_MAX, SIGMADELTA_CHANNEL_ERR_STR, ESP_ERR_INVALID_ARG); SIGMADELTA_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(config->sigmadelta_gpio), SIGMADELTA_IO_ERR_STR, ESP_ERR_INVALID_ARG); diff --git a/components/driver/spi_master.c b/components/driver/spi_master.c index 723fbdb03..8951371fd 100644 --- a/components/driver/spi_master.c +++ b/components/driver/spi_master.c @@ -191,7 +191,7 @@ static const spi_signal_conn_t io_signal[3]={ static void spi_intr(void *arg); -esp_err_t spi_bus_initialize(spi_host_device_t host, spi_bus_config_t *bus_config, int dma_chan) +esp_err_t spi_bus_initialize(spi_host_device_t host, const spi_bus_config_t *bus_config, int dma_chan) { bool native=true; /* ToDo: remove this when we have flash operations cooperating with this */ @@ -698,8 +698,8 @@ esp_err_t spi_device_queue_trans(spi_device_handle_t handle, spi_transaction_t * { BaseType_t r; SPI_CHECK(handle!=NULL, "invalid dev handle", ESP_ERR_INVALID_ARG); - SPI_CHECK((trans_desc->flags & SPI_TRANS_USE_RXDATA)==0 ||trans_desc->length <= 32, "rxdata transfer > 32bytes", ESP_ERR_INVALID_ARG); - SPI_CHECK((trans_desc->flags & SPI_TRANS_USE_TXDATA)==0 ||trans_desc->length <= 32, "txdata transfer > 32bytes", ESP_ERR_INVALID_ARG); + SPI_CHECK((trans_desc->flags & SPI_TRANS_USE_RXDATA)==0 ||trans_desc->rxlength <= 32, "rxdata transfer > 32 bits", ESP_ERR_INVALID_ARG); + SPI_CHECK((trans_desc->flags & SPI_TRANS_USE_TXDATA)==0 ||trans_desc->length <= 32, "txdata transfer > 32 bits", ESP_ERR_INVALID_ARG); SPI_CHECK(!((trans_desc->flags & (SPI_TRANS_MODE_DIO|SPI_TRANS_MODE_QIO)) && (handle->cfg.flags & SPI_DEVICE_3WIRE)), "incompatible iface params", ESP_ERR_INVALID_ARG); SPI_CHECK(!((trans_desc->flags & (SPI_TRANS_MODE_DIO|SPI_TRANS_MODE_QIO)) && (!(handle->cfg.flags & SPI_DEVICE_HALFDUPLEX))), "incompatible iface params", ESP_ERR_INVALID_ARG); r=xQueueSend(handle->trans_queue, (void*)&trans_desc, ticks_to_wait); diff --git a/components/driver/timer.c b/components/driver/timer.c index de968c5e2..b80ed643e 100644 --- a/components/driver/timer.c +++ b/components/driver/timer.c @@ -204,7 +204,7 @@ esp_err_t timer_isr_register(timer_group_t group_num, timer_idx_t timer_num, return esp_intr_alloc_intrstatus(intr_source, intr_alloc_flags, status_reg, mask, fn, arg, handle); } -esp_err_t timer_init(timer_group_t group_num, timer_idx_t timer_num, timer_config_t *config) +esp_err_t timer_init(timer_group_t group_num, timer_idx_t timer_num, const timer_config_t *config) { TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG); TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG); diff --git a/components/esp32/Kconfig b/components/esp32/Kconfig index 0db76f3d5..6a73463c5 100644 --- a/components/esp32/Kconfig +++ b/components/esp32/Kconfig @@ -28,24 +28,33 @@ config MEMMAP_SMP to save some memory. (ToDo: Make this automatically depend on unicore support) config MEMMAP_TRACEMEM - bool "Use TRAX tracing feature" - default "n" - help - The ESP32 contains a feature which allows you to trace the execution path the processor - has taken through the program. This is stored in a chunk of 32K (16K for single-processor) - of memory that can't be used for general purposes anymore. Disable this if you do not know - what this is. + bool + default "n" config MEMMAP_TRACEMEM_TWOBANKS - bool "Reserve memory for tracing both pro as well as app cpu execution" + bool default "n" - depends on MEMMAP_TRACEMEM && MEMMAP_SMP + +config ESP32_TRAX + bool "Use TRAX tracing feature" + default "n" + select MEMMAP_TRACEMEM help The ESP32 contains a feature which allows you to trace the execution path the processor has taken through the program. This is stored in a chunk of 32K (16K for single-processor) of memory that can't be used for general purposes anymore. Disable this if you do not know what this is. +config ESP32_TRAX_TWOBANKS + bool "Reserve memory for tracing both pro as well as app cpu execution" + default "n" + depends on ESP32_TRAX && MEMMAP_SMP + select MEMMAP_TRACEMEM_TWOBANKS + help + The ESP32 contains a feature which allows you to trace the execution path the processor + has taken through the program. This is stored in a chunk of 32K (16K for single-processor) + of memory that can't be used for general purposes anymore. Disable this if you do not know + what this is. # Memory to reverse for trace, used in linker script config TRACEMEM_RESERVE_DRAM @@ -95,6 +104,45 @@ config ESP32_CORE_DUMP_LOG_LEVEL help Config core dump module logging level (0-5). +choice ESP32_APPTRACE_DESTINATION + prompt "AppTrace: destination" + default ESP32_APPTRACE_DEST_NONE + help + Select destination for application trace: trace memory, uart or none (to disable). + +config ESP32_APPTRACE_DEST_TRAX + bool "Trace memory" + select ESP32_APPTRACE_ENABLE +config ESP32_APPTRACE_DEST_UART + bool "UART" + select ESP32_APPTRACE_ENABLE +config ESP32_APPTRACE_DEST_NONE + bool "None" +endchoice + +config ESP32_APPTRACE_ENABLE + bool + depends on !ESP32_TRAX + select MEMMAP_TRACEMEM + select MEMMAP_TRACEMEM_TWOBANKS + default F + help + Enables/disable application tracing module. + +config ESP32_APPTRACE_ONPANIC_HOST_FLUSH_TMO + int "AppTrace: Timeout for flushing last trace data to host on panic" + depends on ESP32_APPTRACE_ENABLE + default 4294967295 + help + Timeout for flushing last trace data to host in case of panic. In us. + +config ESP32_APPTRACE_ONPANIC_HOST_FLUSH_TRAX_THRESH + int "AppTrace: Threshold for flushing last trace data to host on panic" + depends on ESP32_APPTRACE_DEST_TRAX + default 50 + help + Threshold for flushing last trace data to host on panic. In percents of TRAX memory block length. + # Not implemented and/or needs new silicon rev to work config MEMMAP_SPISRAM bool "Use external SPI SRAM chip as main memory" @@ -105,16 +153,37 @@ config MEMMAP_SPISRAM main memory map. Enable this if you have this hardware and want to use it in the same way as on-chip RAM. +choice BASE_MAC_ADDRESS_STORAGE + prompt "Storage of the base MAC address" + default BASE_MAC_STORED_DEFAULT_EFUSE + help + Select storage of the base MAC address which is used for all network interfaces when networking is initialized. + If "Default place in EFUSE" is selected, esp32 will use the base MAC address which is written into default + place in EFUSE when the chip is manufactured. + If "Customer-defined place in EFUSE" is selected, ESP32 will use customer-defined base MAC address which + is written into EFUSE Block 3 words 0, 1. + If "Other customer-defined place" is selected, esp32 will use customer-defined base MAC address from other + place(flash, EEPROM, etc). User code must call esp_base_mac_addr_set_external to set the base MAC address + before network features are initialised. + +config BASE_MAC_STORED_DEFAULT_EFUSE + bool "Default place in EFUSE" +config BASE_MAC_STORED_CUSTOMER_DEFINED_EFUSE + bool "Customer-defined place in EFUSE" +config BASE_MAC_STORED_OTHER_CUSTOMER_DEFINED_PLACE + bool "Other customer-defined place" +endchoice + choice NUMBER_OF_MAC_ADDRESS_GENERATED_FROM_EFUSE bool "Number of MAC address generated from the hardware MAC address in efuse" default FOUR_MAC_ADDRESS_FROM_EFUSE help - Config the number of MAC address which is generated from the hardware MAC address in efuse. + Config the number of MAC address which is generated from the base MAC address in efuse. If the number is two, the MAC addresses of WiFi station and bluetooth are generated from - the hardware MAC address in efuse. The MAC addresses of WiFi softap and ethernet are derived + the base MAC address in efuse. The MAC addresses of WiFi softap and ethernet are derived from that of WiFi station and bluetooth respectively. If the number is four, the MAC addresses of WiFi station, WiFi softap, bluetooth and ethernet - are all generated from the hardware MAC address in efuse. + are all generated from the base MAC address in efuse. config TWO_MAC_ADDRESS_FROM_EFUSE bool "Two" @@ -139,7 +208,6 @@ config SYSTEM_EVENT_TASK_STACK_SIZE help Config system event task stack size in different application. - config MAIN_TASK_STACK_SIZE int "Main task stack size" default 4096 @@ -492,6 +560,34 @@ config ESP32_DEEP_SLEEP_WAKEUP_DELAY If you are seeing "flash read err, 1000" message printed to the console after deep sleep reset, try increasing this value. +choice ESP32_XTAL_FREQ_SEL + prompt "Main XTAL frequency" + default ESP32_XTAL_FREQ_AUTO + help + ESP32 currently supports the following XTAL frequencies: + - 26 MHz + - 40 MHz + Startup code can automatically estimate XTAL frequency. This feature + uses the internal 8MHz oscillator as a reference. Because the internal + oscillator frequency is temperature dependent, it is not recommended + to use automatic XTAL frequency detection in applications which need + to work at high ambient temperatures and use high-temperature + qualified chips and modules. +config ESP32_XTAL_FREQ_40 + bool "40 MHz" +config ESP32_XTAL_FREQ_26 + bool "26 MHz" +config ESP32_XTAL_FREQ_AUTO + bool "Autodetect" +endchoice + +# Keep these values in sync with rtc_xtal_freq_t enum in soc/rtc.h +config ESP32_XTAL_FREQ + int + default 0 if ESP32_XTAL_FREQ_AUTO + default 40 if ESP32_XTAL_FREQ_40 + default 26 if ESP32_XTAL_FREQ_26 + endmenu menuconfig WIFI_ENABLED @@ -525,8 +621,8 @@ config ESP32_WIFI_STATIC_RX_BUFFER_NUM config ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM int "Max number of WiFi dynamic RX buffers" depends on WIFI_ENABLED - range 0 64 - default 0 + range 0 128 + default 64 help Set the number of WiFi dynamic rx buffers, 0 means no limitation for dynamic rx buffer allocation. The size of dynamic rx buffers is not fixed. diff --git a/components/esp32/app_trace.c b/components/esp32/app_trace.c new file mode 100644 index 000000000..47b7a021e --- /dev/null +++ b/components/esp32/app_trace.c @@ -0,0 +1,994 @@ +// Copyright 2017 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. +// +// Hot It Works +// ************ + +// 1. Components Overview +// ====================== + +// Xtensa has useful feature: TRAX debug module. It allows recording program execution flow during run-time without disturbing CPU commands flow. +// Exectution flow data are written to configurable Trace RAM block. Besides accessing Trace RAM itself TRAX module also allows to read/write +// trace memory via its registers by means of JTAG, APB or ERI transactions. +// ESP32 has two Xtensa cores with separate TRAX modules on them and provides two special memory regions to be used as trace memory. +// ESP32 allows muxing access to trace memory blocks in such a way that while one block is accessed by CPUs another can be accessed via JTAG by host +// via reading/writing TRAX registers. Block muxing is configurable at run-time and allows switching trace memory blocks between +// accessors in round-robin fashion so they can read/write separate memory blocks without disturbing each other. +// This moduile implements application tracing feature based on above mechanisms. This feature allows to transfer arbitrary user data to +// host via JTAG with minimal impact on system performance. This module is implied to be used in the following tracing scheme. + +// ------>------ ----- (host components) ----- +// | | | | +// --------------- ----------------------- ----------------------- ---------------- ------ --------- ----------------- +// |apptrace user|-->|target tracing module|<--->|TRAX_MEM0 | TRAX_MEM1|---->|TRAX_DATA_REGS|<-->|JTAG|<--->|OpenOCD|-->|trace data file| +// --------------- ----------------------- ----------------------- ---------------- ------ --------- ----------------- +// | | | | +// | ------<------ ---------------- | +// |<------------------------------------------->|TRAX_CTRL_REGS|<---->| +// ---------------- + +// In general tracing happens in the following way. User aplication requests tracing module to send some data by calling esp_apptrace_buffer_get(), +// moduile allocates necessary buffer in current input trace block. Then user fills received buffer with data and calls esp_apptrace_buffer_put(). +// When current input trace block is filled with app data it is exposed to host and the second block becomes input one and buffer filling restarts. +// While target application fills one memory block host reads another block via JTAG. +// To control buffer switching and for other communication purposes this implementation uses some TRAX registers. It is safe since HW TRAX tracing +// can not be used along with application tracing feature so these registers are freely readable/writeable via JTAG from host and via ERI from ESP32 cores. +// So this implementation's target CPU overhead is produced only by calls to allocate/manage buffers and data copying. +// On host special OpenOCD command must be used to read trace data. + +// 2.1.1.1 TRAX Registers layout +// ============================= + +// This module uses two TRAX HW registers to communicate with host SW (OpenOCD). +// - Control register uses TRAX_DELAYCNT as storage. Only lower 24 bits of TRAX_DELAYCNT are writable. Control register has the following bitfields: +// | 31..XXXXXX..24 | 23 .(host_connect). 23| 22..(block_id)..15 | 14..(block_len)..0 | +// 14..0 bits - actual length of user data in trace memory block. Target updates it every time it fills memory block and exposes it to host. +// Host writes zero to this field when it finishes reading exposed block; +// 22..15 bits - trace memory block transfer ID. Block counter. It can overflow. Updated by target, host should not modify it. Actually can be 1-2 bits; +// 23 bit - 'host connected' flag. If zero then host is not connected and tracing module works in post-mortem mode, otherwise in streaming mode; +// - Status register uses TRAX_TRIGGERPC as storage. If this register is not zero then currentlly CPU is changing TRAX registers and +// this register holds address of the instruction which application will execute when it finishes with those registers modifications. +// See 'Targets Connection' setion for details. + +// 3. Modes of operation +// ===================== + +// This module supports two modes of operation: +// - Post-mortem mode. This is the default mode. In this mode application tracing module does not check whether host has read all the data from block +// exposed to it and switches block in any case. The mode does not need host interaction for operation and so can be useful when only the latest +// trace data are necessary, e.g. for analyzing crashes. On panic the latest data from current input block are exposed to host and host can read them. +// There is menuconfig option CONFIG_ESP32_APPTRACE_ONPANIC_HOST_FLUSH_TRAX_THRESH which control the threshold for flushing data on panic. +// - Streaming mode. Tracing module enters this mode when host connects to targets and sets respective bit in control register. In this mode tracing +// module waits for specified time until host read all the data from exposed block. +// On panic tracing module waits (timeout is configured via menuconfig via ESP32_APPTRACE_ONPANIC_HOST_FLUSH_TMO) for the host to read all data +// from the previously exposed block. + +// 4. Communication Protocol +// ========================= + +// 4.1 Trace Memory Blocks +// ^^^^^^^^^^^^^^^^^^^^^^^^^ + +// Communication is controlled via special register. Host periodically polls control register on each core to find out if there are any data avalable. +// When current input trace memory block is filled tracing module exposes block to host and updates block_len and block_id fields in control register. +// Host reads new register value and according to it starts reading data from exposed block. Meanwhile target starts filling another trace block. +// When host finishes reading the block it clears block_len field in control register indicating to target that it is ready to accept the next block. + +// 4.2 User Data Chunks Level +// -------------------------- + +// Since trace memory block is shared between user data chunks and data copying is performed on behalf of the API user (in its normal context) in +// multithreading environment it can happen that task/ISR which copies data is preempted by another high prio task/ISR. So it is possible situation +// that task/ISR will fail to complete filling its data chunk before the whole trace block is exposed to the host. To handle such conditions tracing +// module prepends all user data chunks with 4 bytes header which contains allocated buffer size and actual data length within it. OpenOCD command +// which reads application traces will report error when it will read incompleted user data block. + +// 4.3 Targets Connection/Disconnection +// ------------------------------------ + +// When host is going to start tracing in streaming mode it needs to put both ESP32 cores into initial state when 'host connected' bit is set +// on both cores. To accomplish this host halts both cores and sets this bit in TRAX registers. But target code can be halted in state when it has read control +// register but has not updated its value. To handle such situations target code indicates to the host that it is updating control register by writing +// non-zero value to status register. Actually it writes address of the instruction which it will execute when it finishes with +// the registers update. When target is halted during control register update host sets breakpoint at the address from status register and resumes CPU. +// After target code finishes with register update it is halted on breakpoint, host detects it and safely sets 'host connected' bit. When both cores +// are set up they are resumed. Tracing starts without further intrusion into CPUs work. +// When host is going to stop tracing in streaming mode it needs to disconnect targets. Disconnection process is done using the same algorithm +// as for connecting, but 'host connected' bits are cleared on ESP32 cores. + +// 5. Module Access Synchronization +// ================================ + +// Access to internal module's data is synchronized with custom mutex. Mutex is a wrapper for portMUX_TYPE and uses almost the same sync mechanism as in +// vPortCPUAcquireMutex/vPortCPUReleaseMutex. The mechanism uses S32C1I Xtensa instruction to implement exclusive access to module's data from tasks and +// ISRs running on both cores. Also custom mutex allows specifying timeout for locking operation. Locking routine checks underlaying mutex in cycle until +// it gets its ownership or timeout expires. The differences of application tracing module's mutex implementation from vPortCPUAcquireMutex/vPortCPUReleaseMutex are: +// - Support for timeouts. +// - Local IRQs for CPU which owns the mutex are disabled till the call to unlocking routine. This is made to avoid possible task's prio inversion. +// When low prio task takes mutex and enables local IRQs gets preempted by high prio task which in its turn can try to acquire mutex using infinite timeout. +// So no local task switch occurs when mutex is locked. But this does not apply to tasks on another CPU. +// WARNING: Priority inversion can happen when low prio task works on one CPU and medium and high prio tasks work on another. +// There are some differences how mutex behaves when it is used from task and ISR context when timeout is non-zero: +// - In task context when mutex can not be locked portYIELD() is called before check for timeout condition to alow othet tasks work on the same CPU. +// - In ISR context when mutex can not be locked nothing is done before expired time check. +// WARNING: Care must be taken when selecting timeout values for trace calls from ISRs. Tracing module does not care about watchdogs when waiting on internal locks +// and when waiting for host to complete previous block reading, so if wating timeout value exceedes watchdog's one it can lead to system reboot. + +// 6. Timeouts +// ------------ + +// Timeout mechanism is based on xthal_get_ccount() routine and supports timeout values in micorseconds. +// There are two situations when task/ISR can be delayed by tracing API call. Timeout mechanism takes into account both conditions: +// - Trace data are locked by another task/ISR. When wating on trace data lock. +// - Current TRAX memory input block is full when working in streaming mode (host is connected). When waiting for host to complete previous block reading. +// When wating for any of above conditions xthal_get_ccount() is called periodically to calculate time elapsed from trace API routine entry. When elapsed +// time exceeds specified timeout value operation is canceled and ESP_ERR_TIMEOUT code is returned. + +// ALSO SEE example usage of application tracing module in 'components/log/README.rst' + +#include +#include "soc/soc.h" +#include "soc/dport_reg.h" +#include "eri.h" +#include "trax.h" +#include "freertos/FreeRTOS.h" +#include "freertos/portmacro.h" +#include "freertos/semphr.h" +#include "freertos/task.h" +#include "soc/timer_group_struct.h" +#include "soc/timer_group_reg.h" +#include "esp_app_trace.h" + +#if CONFIG_ESP32_APPTRACE_ENABLE +#define ESP_APPTRACE_DEBUG_STATS_ENABLE 0 +#define ESP_APPTRACE_BUF_HISTORY_DEPTH (16*100) + +#define ESP_APPTRACE_MAX_VPRINTF_ARGS 256 + +#define ESP_APPTRACE_PRINT_LOCK_NONE 0 +#define ESP_APPTRACE_PRINT_LOCK_SEM 1 +#define ESP_APPTRACE_PRINT_LOCK_MUX 2 +#define ESP_APPTRACE_PRINT_LOCK ESP_APPTRACE_PRINT_LOCK_NONE//ESP_APPTRACE_PRINT_LOCK_SEM + +#define ESP_APPTRACE_USE_LOCK_SEM 0 // 1 - semaphore (now may be broken), 0 - portMUX_TYPE + +#define LOG_LOCAL_LEVEL ESP_LOG_VERBOSE +#include "esp_log.h" +const static char *TAG = "esp_apptrace"; + +#if ESP_APPTRACE_PRINT_LOCK != ESP_APPTRACE_PRINT_LOCK_NONE +#define ESP_APPTRACE_LOG( format, ... ) \ + do { \ + esp_apptrace_log_lock(); \ + ets_printf(format, ##__VA_ARGS__); \ + esp_apptrace_log_unlock(); \ + } while(0) +#else +#define ESP_APPTRACE_LOG( format, ... ) \ + do { \ + ets_printf(format, ##__VA_ARGS__); \ + } while(0) +#endif + +#define ESP_APPTRACE_LOG_LEV( _L_, level, format, ... ) \ + do { \ + if (LOG_LOCAL_LEVEL >= level) { \ + ESP_APPTRACE_LOG(LOG_FORMAT(_L_, format), esp_log_early_timestamp(), TAG, ##__VA_ARGS__); \ + } \ + } while(0) + +#define ESP_APPTRACE_LOGE( format, ... ) ESP_APPTRACE_LOG_LEV(E, ESP_LOG_ERROR, format, ##__VA_ARGS__) +#define ESP_APPTRACE_LOGW( format, ... ) ESP_APPTRACE_LOG_LEV(W, ESP_LOG_WARN, format, ##__VA_ARGS__) +#define ESP_APPTRACE_LOGI( format, ... ) ESP_APPTRACE_LOG_LEV(I, ESP_LOG_INFO, format, ##__VA_ARGS__) +#define ESP_APPTRACE_LOGD( format, ... ) ESP_APPTRACE_LOG_LEV(D, ESP_LOG_DEBUG, format, ##__VA_ARGS__) +#define ESP_APPTRACE_LOGV( format, ... ) ESP_APPTRACE_LOG_LEV(V, ESP_LOG_VERBOSE, format, ##__VA_ARGS__) +#define ESP_APPTRACE_LOGO( format, ... ) ESP_APPTRACE_LOG_LEV(E, ESP_LOG_NONE, format, ##__VA_ARGS__) + +#define ESP_APPTRACE_CPUTICKS2US(_t_) ((_t_)/(XT_CLOCK_FREQ/1000000)) + +// TODO: move these (and same definitions in trax.c to dport_reg.h) +#define TRACEMEM_MUX_PROBLK0_APPBLK1 0 +#define TRACEMEM_MUX_BLK0_ONLY 1 +#define TRACEMEM_MUX_BLK1_ONLY 2 +#define TRACEMEM_MUX_PROBLK1_APPBLK0 3 + +// TRAX is disabled, so we use its registers for our own purposes +// | 31..XXXXXX..24 | 23 .(host_connect). 23| 22..(block_id)..15 | 14..(block_len)..0 | +#define ESP_APPTRACE_TRAX_CTRL_REG ERI_TRAX_DELAYCNT +#define ESP_APPTRACE_TRAX_STAT_REG ERI_TRAX_TRIGGERPC + +#define ESP_APPTRACE_TRAX_BLOCK_LEN_MSK 0x7FFFUL +#define ESP_APPTRACE_TRAX_BLOCK_LEN(_l_) ((_l_) & ESP_APPTRACE_TRAX_BLOCK_LEN_MSK) +#define ESP_APPTRACE_TRAX_BLOCK_LEN_GET(_v_) ((_v_) & ESP_APPTRACE_TRAX_BLOCK_LEN_MSK) +#define ESP_APPTRACE_TRAX_BLOCK_ID_MSK 0xFFUL +#define ESP_APPTRACE_TRAX_BLOCK_ID(_id_) (((_id_) & ESP_APPTRACE_TRAX_BLOCK_ID_MSK) << 15) +#define ESP_APPTRACE_TRAX_BLOCK_ID_GET(_v_) (((_v_) >> 15) & ESP_APPTRACE_TRAX_BLOCK_ID_MSK) +#define ESP_APPTRACE_TRAX_HOST_CONNECT (1 << 23) + +static volatile uint8_t *s_trax_blocks[] = { + (volatile uint8_t *) 0x3FFFC000, + (volatile uint8_t *) 0x3FFF8000 +}; + +#define ESP_APPTRACE_TRAX_BLOCKS_NUM (sizeof(s_trax_blocks)/sizeof(s_trax_blocks[0])) + +//#define ESP_APPTRACE_TRAX_BUFFER_SIZE (ESP_APPTRACE_TRAX_BLOCK_SIZE/4) + +#define ESP_APPTRACE_TRAX_INBLOCK_START 0//(ESP_APPTRACE_TRAX_BLOCK_ID_MSK - 4) + + +#define ESP_APPTRACE_TRAX_INBLOCK_MARKER_PTR_GET() (&s_trace_buf.trax.state.markers[s_trace_buf.trax.state.in_block % 2]) +#define ESP_APPTRACE_TRAX_INBLOCK_GET() (&s_trace_buf.trax.blocks[s_trace_buf.trax.state.in_block % 2]) + +#if ESP_APPTRACE_DEBUG_STATS_ENABLE == 1 +/** keeps info about apptrace API (write/get buffer) caller and internal module's data related to that call + * NOTE: used for module debug purposes, currently this functionality is partially broken, + * but can be useful in future + */ +typedef struct { + uint32_t hnd; // task/ISR handle + uint32_t ts; // timestamp + uint32_t stamp; // test (user) trace buffer stamp + uint32_t in_block; // TRAX input block ID + uint32_t eri_len[2]; // contents of ERI control register upon entry to / exit from API routine + uint32_t wr_err; // number of trace write errors +} esp_trace_buffer_wr_hitem_t; + +/** apptrace API calls history. History is organized as ring buffer*/ +typedef struct { + uint32_t hist_rd; // the first history entry index + uint32_t hist_wr; // the last history entry index + esp_trace_buffer_wr_hitem_t hist[ESP_APPTRACE_BUF_HISTORY_DEPTH]; // history data +} esp_trace_buffer_wr_stats_t; + +/** trace module stats */ +typedef struct { + esp_trace_buffer_wr_stats_t wr; +} esp_trace_buffer_stats_t; +#endif + +/** Trace data header. Every user data chunk is prepended with this header. + * User allocates block with esp_apptrace_buffer_get and then fills it with data, + * in multithreading environment it can happen that tasks gets buffer and then gets interrupted, + * so it is possible that user data are incomplete when TRAX memory block is exposed to the host. + * In this case host SW will see that wr_sz < block_sz and will report error. + */ +typedef struct { + uint16_t block_sz; // size of allocated block for user data + uint16_t wr_sz; // size of actually written data +} esp_tracedata_hdr_t; + +/** TRAX HW transport state */ +typedef struct { + uint32_t in_block; // input block ID + uint32_t markers[ESP_APPTRACE_TRAX_BLOCKS_NUM]; // block filling level markers +#if ESP_APPTRACE_DEBUG_STATS_ENABLE == 1 + esp_trace_buffer_stats_t stats; // stats +#endif +} esp_apptrace_trax_state_t; + +/** memory block parameters */ +typedef struct { + uint8_t *start; // start address + uint32_t sz; // size +} esp_apptrace_mem_block_t; + +/** TRAX HW transport data */ +typedef struct { + volatile esp_apptrace_trax_state_t state; // state + esp_apptrace_mem_block_t blocks[ESP_APPTRACE_TRAX_BLOCKS_NUM]; // memory blocks +} esp_apptrace_trax_data_t; + +/** tracing module synchronization lock */ +typedef struct { + volatile unsigned int irq_stat; // local (on 1 CPU) IRQ state + portMUX_TYPE portmux; // mux for synchronization +} esp_apptrace_lock_t; + +#define ESP_APPTRACE_MUX_GET(_m_) (&(_m_)->portmux) + +/** tracing module internal data */ +typedef struct { +#if ESP_APPTRACE_USE_LOCK_SEM == 1 + SemaphoreHandle_t lock; +#else + esp_apptrace_lock_t lock; // sync lock +#endif + uint8_t inited; // module initialization state flag + esp_apptrace_trax_data_t trax; // TRAX HW transport data +} esp_apptrace_buffer_t; + +/** waiting timeout data */ +typedef struct { + uint32_t start; // waiting start (in ticks) + uint32_t tmo; // timeout (in us) +} esp_apptrace_tmo_t; + +static esp_apptrace_buffer_t s_trace_buf; + +#if ESP_APPTRACE_PRINT_LOCK == ESP_APPTRACE_PRINT_LOCK_SEM +static SemaphoreHandle_t s_log_lock; +#elif ESP_APPTRACE_PRINT_LOCK == ESP_APPTRACE_PRINT_LOCK_MUX +static esp_apptrace_lock_t s_log_lock; +#endif + +static inline void esp_apptrace_tmo_init(esp_apptrace_tmo_t *tmo, uint32_t user_tmo) +{ + tmo->start = xthal_get_ccount(); + tmo->tmo = user_tmo; +} + +static esp_err_t esp_apptrace_tmo_check(esp_apptrace_tmo_t *tmo) +{ + unsigned cur, elapsed; + + if (tmo->tmo != ESP_APPTRACE_TMO_INFINITE) { + cur = xthal_get_ccount(); + if (tmo->start <= cur) { + elapsed = cur - tmo->start; + } else { + elapsed = 0xFFFFFFFF - tmo->start + cur; + } + if (ESP_APPTRACE_CPUTICKS2US(elapsed) >= tmo->tmo) { + return ESP_ERR_TIMEOUT; + } + } + return ESP_OK; +} + +#if ESP_APPTRACE_PRINT_LOCK == ESP_APPTRACE_PRINT_LOCK_MUX || ESP_APPTRACE_USE_LOCK_SEM == 0 +static inline void esp_apptrace_mux_init(esp_apptrace_lock_t *mux) +{ + ESP_APPTRACE_MUX_GET(mux)->mux = portMUX_FREE_VAL; + mux->irq_stat = 0; +} + +static esp_err_t esp_apptrace_lock_take(esp_apptrace_lock_t *mux, uint32_t tmo) +{ + uint32_t res = ~portMUX_FREE_VAL; + esp_apptrace_tmo_t sleeping_tmo; + + esp_apptrace_tmo_init(&sleeping_tmo, tmo); + while (1) { + res = (xPortGetCoreID() << portMUX_VAL_SHIFT) | portMUX_MAGIC_VAL; + // first disable IRQs on this CPU, this will prevent current task from been + // preempted by higher prio tasks, otherwise deadlock can happen: + // when lower prio task took mux and then preempted by higher prio one which also tries to + // get mux with INFINITE timeout + unsigned int irq_stat = portENTER_CRITICAL_NESTED(); + // Now try to lock mux + uxPortCompareSet(&ESP_APPTRACE_MUX_GET(mux)->mux, portMUX_FREE_VAL, &res); + if (res == portMUX_FREE_VAL) { + // do not enable IRQs, we will held them disabled until mux is unlocked + // we do not need to flush cache region for mux->irq_stat because it is used + // to hold and restore IRQ state only for CPU which took mux, other CPUs will not use this value + mux->irq_stat = irq_stat; + break; + } + // if mux is locked by other task/ISR enable IRQs and let other guys work + portEXIT_CRITICAL_NESTED(irq_stat); + + if (!xPortInIsrContext()) { + portYIELD(); + } + + int err = esp_apptrace_tmo_check(&sleeping_tmo); + if (err != ESP_OK) { + return err; + } + } + + return ESP_OK; +} + +esp_err_t esp_apptrace_mux_give(esp_apptrace_lock_t *mux) +{ + esp_err_t ret = ESP_OK; + uint32_t res = 0; + unsigned int irq_stat; + + res = portMUX_FREE_VAL; + + // first of all save a copy of IRQ status for this locker because uxPortCompareSet will unlock mux and tasks/ISRs + // from other core can overwrite mux->irq_stat + irq_stat = mux->irq_stat; + uxPortCompareSet(&ESP_APPTRACE_MUX_GET(mux)->mux, (xPortGetCoreID() << portMUX_VAL_SHIFT) | portMUX_MAGIC_VAL, &res); + // enable local interrupts + portEXIT_CRITICAL_NESTED(irq_stat); + + if ( ((res & portMUX_VAL_MASK) >> portMUX_VAL_SHIFT) == xPortGetCoreID() ) { + // nothing to do + } else if ( res == portMUX_FREE_VAL ) { + ret = ESP_FAIL; // should never get here + } else { + ret = ESP_FAIL; // should never get here + } + return ret; +} +#endif + +static inline esp_err_t esp_apptrace_log_init() +{ +#if ESP_APPTRACE_PRINT_LOCK == ESP_APPTRACE_PRINT_LOCK_SEM + s_log_lock = xSemaphoreCreateBinary(); + if (!s_log_lock) { + ets_printf("%s: Failed to create print lock sem!", TAG); + return ESP_FAIL; + } + xSemaphoreGive(s_log_lock); +#elif ESP_APPTRACE_PRINT_LOCK == ESP_APPTRACE_PRINT_LOCK_MUX + esp_apptrace_mux_init(&s_log_lock); +#endif + return ESP_OK; +} + +static inline void esp_apptrace_log_cleanup() +{ +#if ESP_APPTRACE_PRINT_LOCK == ESP_APPTRACE_PRINT_LOCK_SEM + vSemaphoreDelete(s_log_lock); +#endif +} + +static inline int esp_apptrace_log_lock() +{ +#if ESP_APPTRACE_PRINT_LOCK == ESP_APPTRACE_PRINT_LOCK_SEM + BaseType_t ret; + if (xPortInIsrContext()) { + ret = xSemaphoreTakeFromISR(s_print_lock, NULL); + } else { + ret = xSemaphoreTake(s_print_lock, portMAX_DELAY); + } + return ret; +#elif ESP_APPTRACE_PRINT_LOCK == ESP_APPTRACE_PRINT_LOCK_MUX + int ret = esp_apptrace_lock_take(&s_log_lock, ESP_APPTRACE_TMO_INFINITE); + return ret; +#endif + return 0; +} + +static inline void esp_apptrace_log_unlock() +{ +#if ESP_APPTRACE_PRINT_LOCK == ESP_APPTRACE_PRINT_LOCK_SEM + if (xPortInIsrContext()) { + xSemaphoreGiveFromISR(s_log_lock, NULL); + } else { + xSemaphoreGive(s_log_lock); + } +#elif ESP_APPTRACE_PRINT_LOCK == ESP_APPTRACE_PRINT_LOCK_MUX + esp_apptrace_mux_give(&s_log_lock); +#endif +} + +esp_err_t esp_apptrace_lock_init() +{ +#if ESP_APPTRACE_USE_LOCK_SEM == 1 + s_trace_buf.lock = xSemaphoreCreateBinary(); + if (!s_trace_buf.lock) { + ESP_APPTRACE_LOGE("Failed to create lock!"); + return ESP_FAIL; + } + xSemaphoreGive(s_trace_buf.lock); +#else + esp_apptrace_mux_init(&s_trace_buf.lock); +#endif + return ESP_OK; +} + +esp_err_t esp_apptrace_lock_cleanup() +{ +#if ESP_APPTRACE_USE_LOCK_SEM == 1 + vSemaphoreDelete(s_trace_buf.lock); +#endif + return ESP_OK; +} + +esp_err_t esp_apptrace_lock(uint32_t *tmo) +{ + unsigned cur, elapsed, start = xthal_get_ccount(); + +#if ESP_APPTRACE_USE_LOCK_SEM == 1 + BaseType_t ret; + if (xPortInIsrContext()) { + ret = xSemaphoreTakeFromISR(s_trace_buf.lock, NULL); + } else { + ret = xSemaphoreTake(s_trace_buf.lock, portTICK_PERIOD_MS * (*tmo) / 1000); + } + if (ret != pdTRUE) { + return ESP_FAIL; + } +#else + esp_err_t ret = esp_apptrace_lock_take(&s_trace_buf.lock, *tmo); + if (ret != ESP_OK) { + return ESP_FAIL; + } +#endif + // decrease tmo by actual waiting time + cur = xthal_get_ccount(); + if (start <= cur) { + elapsed = cur - start; + } else { + elapsed = ULONG_MAX - start + cur; + } + if (ESP_APPTRACE_CPUTICKS2US(elapsed) > *tmo) { + *tmo = 0; + } else { + *tmo -= ESP_APPTRACE_CPUTICKS2US(elapsed); + } + + return ESP_OK; +} + +esp_err_t esp_apptrace_unlock() +{ + esp_err_t ret = ESP_OK; +#if ESP_APPTRACE_USE_LOCK_SEM == 1 + if (xPortInIsrContext()) { + xSemaphoreGiveFromISR(s_trace_buf.lock, NULL); + } else { + xSemaphoreGive(s_trace_buf.lock); + } +#else + ret = esp_apptrace_mux_give(&s_trace_buf.lock); +#endif + return ret; +} + +#if CONFIG_ESP32_APPTRACE_DEST_TRAX +static void esp_apptrace_trax_init() +{ + // Stop trace, if any (on the current CPU) + eri_write(ERI_TRAX_TRAXCTRL, TRAXCTRL_TRSTP); + eri_write(ERI_TRAX_TRAXCTRL, TRAXCTRL_TMEN); + eri_write(ESP_APPTRACE_TRAX_CTRL_REG, ESP_APPTRACE_TRAX_BLOCK_ID(ESP_APPTRACE_TRAX_INBLOCK_START)); + eri_write(ESP_APPTRACE_TRAX_STAT_REG, 0); + + ESP_APPTRACE_LOGI("Initialized TRAX on CPU%d", xPortGetCoreID()); +} + +// assumed to be protected by caller from multi-core/thread access +static esp_err_t esp_apptrace_trax_block_switch() +{ + int prev_block_num = s_trace_buf.trax.state.in_block % 2; + int new_block_num = prev_block_num ? (0) : (1); + int res = ESP_OK; + extern uint32_t __esp_apptrace_trax_eri_updated; + + // indicate to host that we are about to update. + // this is used only to place CPU into streaming mode at tracing startup + // before starting streaming host can halt us after we read ESP_APPTRACE_TRAX_CTRL_REG and before we updated it + // HACK: in this case host will set breakpoint just after ESP_APPTRACE_TRAX_CTRL_REG update, + // here we set address to set bp at + // enter ERI update critical section + eri_write(ESP_APPTRACE_TRAX_STAT_REG, (uint32_t)&__esp_apptrace_trax_eri_updated); + + uint32_t ctrl_reg = eri_read(ESP_APPTRACE_TRAX_CTRL_REG); +#if ESP_APPTRACE_DEBUG_STATS_ENABLE == 1 + if (s_trace_buf.state.stats.wr.hist_wr < ESP_APPTRACE_BUF_HISTORY_DEPTH) { + esp_trace_buffer_wr_hitem_t *hi = (esp_trace_buffer_wr_hitem_t *)&s_trace_buf.state.stats.wr.hist[s_trace_buf.state.stats.wr.hist_wr - 1]; + hi->eri_len[1] = ctrl_reg; + } +#endif + uint32_t host_connected = ESP_APPTRACE_TRAX_HOST_CONNECT & ctrl_reg; + if (host_connected) { + uint32_t acked_block = ESP_APPTRACE_TRAX_BLOCK_ID_GET(ctrl_reg); + uint32_t host_to_read = ESP_APPTRACE_TRAX_BLOCK_LEN_GET(ctrl_reg); + if (host_to_read != 0 || acked_block != (s_trace_buf.trax.state.in_block & ESP_APPTRACE_TRAX_BLOCK_ID_MSK)) { + // ESP_APPTRACE_LOGE("HC[%d]: Can not switch %x %d %x %x/%lx", xPortGetCoreID(), ctrl_reg, host_to_read, acked_block, + // s_trace_buf.trax.state.in_block & ESP_APPTRACE_TRAX_BLOCK_ID_MSK, s_trace_buf.trax.state.in_block); + res = ESP_ERR_NO_MEM; + goto _on_func_exit; + } + } + s_trace_buf.trax.state.markers[new_block_num] = 0; + // switch to new block + s_trace_buf.trax.state.in_block++; + + WRITE_PERI_REG(DPORT_TRACEMEM_MUX_MODE_REG, new_block_num ? TRACEMEM_MUX_BLK0_ONLY : TRACEMEM_MUX_BLK1_ONLY); + eri_write(ESP_APPTRACE_TRAX_CTRL_REG, ESP_APPTRACE_TRAX_BLOCK_ID(s_trace_buf.trax.state.in_block) | + host_connected | ESP_APPTRACE_TRAX_BLOCK_LEN(s_trace_buf.trax.state.markers[prev_block_num])); + +_on_func_exit: + // exit ERI update critical section + eri_write(ESP_APPTRACE_TRAX_STAT_REG, 0x0); + asm volatile ( + " .global __esp_apptrace_trax_eri_updated\n" + "__esp_apptrace_trax_eri_updated:\n"); // host will set bp here to resolve collision at streaming start + return res; +} + +static esp_err_t esp_apptrace_trax_block_switch_waitus(uint32_t tmo) +{ + int res; + esp_apptrace_tmo_t sleeping_tmo; + + esp_apptrace_tmo_init(&sleeping_tmo, tmo); + + while ((res = esp_apptrace_trax_block_switch()) != ESP_OK) { + res = esp_apptrace_tmo_check(&sleeping_tmo); + if (res != ESP_OK) { + break; + } + } + return res; +} + +static uint8_t *esp_apptrace_trax_get_buffer(size_t size, uint32_t *tmo) +{ + uint8_t *buf_ptr = NULL; + volatile uint32_t *cur_block_marker; + esp_apptrace_mem_block_t *cur_block; + + int res = esp_apptrace_lock(tmo); + if (res != ESP_OK) { + return NULL; + } + +#if ESP_APPTRACE_DEBUG_STATS_ENABLE == 1 + esp_trace_buffer_wr_hitem_t *hi = NULL; + if (s_trace_buf.state.stats.wr.hist_wr < ESP_APPTRACE_BUF_HISTORY_DEPTH) { + hi = (esp_trace_buffer_wr_hitem_t *)&s_trace_buf.state.stats.wr.hist[s_trace_buf.state.stats.wr.hist_wr++]; + hi->hnd = *(uint32_t *)(buf + 0); + hi->ts = *(uint32_t *)(buf + sizeof(uint32_t)); + hi->stamp = *(buf + 2 * sizeof(uint32_t)); + hi->in_block = s_trace_buf.state.in_block; + hi->wr_err = 0; + hi->eri_len[0] = eri_read(ESP_APPTRACE_TRAX_CTRL_REG); + if (s_trace_buf.state.stats.wr.hist_wr == ESP_APPTRACE_BUF_HISTORY_DEPTH) { + s_trace_buf.state.stats.wr.hist_wr = 0; + } + if (s_trace_buf.state.stats.wr.hist_wr == s_trace_buf.state.stats.wr.hist_rd) { + s_trace_buf.state.stats.wr.hist_rd++; + if (s_trace_buf.state.stats.wr.hist_rd == ESP_APPTRACE_BUF_HISTORY_DEPTH) { + s_trace_buf.state.stats.wr.hist_rd = 0; + } + } + } +#endif + + cur_block_marker = ESP_APPTRACE_TRAX_INBLOCK_MARKER_PTR_GET(); + cur_block = ESP_APPTRACE_TRAX_INBLOCK_GET(); + + if (*cur_block_marker + size + sizeof(esp_tracedata_hdr_t) >= cur_block->sz) { + // flush data, we can not unlock apptrace until we have buffer for all user data + // otherwise other tasks/ISRs can get control and write their data between chunks of this data + res = esp_apptrace_trax_block_switch_waitus(/*size + sizeof(esp_tracedata_hdr_t),*/*tmo); + if (res != ESP_OK) { + if (esp_apptrace_unlock() != ESP_OK) { + ESP_APPTRACE_LOGE("Failed to unlock apptrace data!"); + // there is a bug, should never get here + } + return NULL; + } + // we switched to new block, update TRAX block pointers + cur_block_marker = ESP_APPTRACE_TRAX_INBLOCK_MARKER_PTR_GET(); + cur_block = ESP_APPTRACE_TRAX_INBLOCK_GET(); + } + + buf_ptr = cur_block->start + *cur_block_marker; + ((esp_tracedata_hdr_t *)buf_ptr)->block_sz = size; + ((esp_tracedata_hdr_t *)buf_ptr)->wr_sz = 0; + + *cur_block_marker += size + sizeof(esp_tracedata_hdr_t); + + // now we can safely unlock apptrace to allow other tasks/ISRs to get other buffers and write their data + if (esp_apptrace_unlock() != ESP_OK) { + ESP_APPTRACE_LOGE("Failed to unlock apptrace data!"); + // there is a bug, should never get here + } + + return buf_ptr + sizeof(esp_tracedata_hdr_t); +} + +static esp_err_t esp_apptrace_trax_put_buffer(uint8_t *ptr, uint32_t *tmo) +{ + int res = ESP_OK; + esp_tracedata_hdr_t *hdr = (esp_tracedata_hdr_t *)(ptr - sizeof(esp_tracedata_hdr_t)); + + // update written size + hdr->wr_sz = hdr->block_sz; + + // TODO: mark block as busy in order not to re-use it for other tracing calls until it is completely written + // TODO: avoid potential situation when all memory is consumed by low prio tasks which can not complete writing due to + // higher prio tasks and the latter can not allocate buffers at all + // this is abnormal situation can be detected on host which will receive only uncompleted buffers + // workaround: use own memcpy which will kick-off dead tracing calls + + return res; +} + +static esp_err_t esp_apptrace_trax_flush(uint32_t min_sz, uint32_t tmo) +{ + volatile uint32_t *in_block_marker; + int res = ESP_OK; + + in_block_marker = ESP_APPTRACE_TRAX_INBLOCK_MARKER_PTR_GET(); + if (*in_block_marker > min_sz) { + ESP_APPTRACE_LOGD("Wait until block switch for %u us", tmo); + res = esp_apptrace_trax_block_switch_waitus(/*0 query any size,*/tmo); + if (res != ESP_OK) { + ESP_APPTRACE_LOGE("Failed to switch to another block"); + return res; + } + ESP_APPTRACE_LOGD("Flushed last block %u bytes", *in_block_marker); + *in_block_marker = 0; + } + + return res; +} + +static esp_err_t esp_apptrace_trax_dest_init() +{ + for (int i = 0; i < ESP_APPTRACE_TRAX_BLOCKS_NUM; i++) { + s_trace_buf.trax.blocks[i].start = (uint8_t *)s_trax_blocks[i]; + s_trace_buf.trax.blocks[i].sz = ESP_APPTRACE_TRAX_BLOCK_SIZE; + s_trace_buf.trax.state.markers[i] = 0; + } + s_trace_buf.trax.state.in_block = ESP_APPTRACE_TRAX_INBLOCK_START; + + WRITE_PERI_REG(DPORT_PRO_TRACEMEM_ENA_REG, DPORT_PRO_TRACEMEM_ENA_M); +#if CONFIG_FREERTOS_UNICORE == 0 + WRITE_PERI_REG(DPORT_APP_TRACEMEM_ENA_REG, DPORT_APP_TRACEMEM_ENA_M); +#endif + // Expose block 1 to host, block 0 is current trace input buffer + WRITE_PERI_REG(DPORT_TRACEMEM_MUX_MODE_REG, TRACEMEM_MUX_BLK1_ONLY); + + return ESP_OK; +} +#endif + +esp_err_t esp_apptrace_init() +{ + int res; + + if (!s_trace_buf.inited) { + res = esp_apptrace_log_init(); + if (res != ESP_OK) { + ets_printf("%s: Failed to init log lock (%d)!", TAG, res); + return res; + } + //memset(&s_trace_buf, 0, sizeof(s_trace_buf)); + res = esp_apptrace_lock_init(&s_trace_buf.lock); + if (res != ESP_OK) { + ESP_APPTRACE_LOGE("Failed to init log lock (%d)!", res); + esp_apptrace_log_cleanup(); + return res; + } +#if CONFIG_ESP32_APPTRACE_DEST_TRAX + res = esp_apptrace_trax_dest_init(); + if (res != ESP_OK) { + ESP_APPTRACE_LOGE("Failed to init TRAX dest data (%d)!", res); + esp_apptrace_lock_cleanup(); + esp_apptrace_log_cleanup(); + return res; + } +#endif + } + +#if CONFIG_ESP32_APPTRACE_DEST_TRAX + // init TRAX on this CPU + esp_apptrace_trax_init(); +#endif + + s_trace_buf.inited |= 1 << xPortGetCoreID(); // global and this CPU-specific data are inited + + return ESP_OK; +} + +esp_err_t esp_apptrace_write(esp_apptrace_dest_t dest, void *data, size_t size, uint32_t user_tmo) +{ + uint8_t *ptr = NULL; + uint32_t tmo = user_tmo; + //TODO: use ptr to HW transport iface struct + uint8_t *(*apptrace_get_buffer)(size_t, uint32_t *); + esp_err_t (*apptrace_put_buffer)(uint8_t *, uint32_t *); + + if (dest == ESP_APPTRACE_DEST_TRAX) { +#if CONFIG_ESP32_APPTRACE_DEST_TRAX + apptrace_get_buffer = esp_apptrace_trax_get_buffer; + apptrace_put_buffer = esp_apptrace_trax_put_buffer; +#else + ESP_APPTRACE_LOGE("Application tracing via TRAX is disabled in menuconfig!"); + return ESP_ERR_NOT_SUPPORTED; +#endif + } else { + ESP_APPTRACE_LOGE("Trace destinations other then TRAX are not supported yet!"); + return ESP_ERR_NOT_SUPPORTED; + } + + ptr = apptrace_get_buffer(size, &tmo); + if (ptr == NULL) { + //ESP_APPTRACE_LOGE("Failed to get buffer!"); + return ESP_ERR_NO_MEM; + } + + // actually can be suspended here by higher prio tasks/ISRs + //TODO: use own memcpy with dead trace calls kick-off algo, and tmo expiration check + memcpy(ptr, data, size); + + // now indicate that this buffer is ready to be sent off to host + return apptrace_put_buffer(ptr, &tmo); +} + +int esp_apptrace_vprintf_to(esp_apptrace_dest_t dest, uint32_t user_tmo, const char *fmt, va_list ap) +{ + uint16_t nargs = 0; + uint8_t *pout, *p = (uint8_t *)fmt; + uint32_t tmo = user_tmo; + //TODO: use ptr to HW transport iface struct + uint8_t *(*apptrace_get_buffer)(size_t, uint32_t *); + esp_err_t (*apptrace_put_buffer)(uint8_t *, uint32_t *); + + if (dest == ESP_APPTRACE_DEST_TRAX) { +#if CONFIG_ESP32_APPTRACE_DEST_TRAX + apptrace_get_buffer = esp_apptrace_trax_get_buffer; + apptrace_put_buffer = esp_apptrace_trax_put_buffer; +#else + ESP_APPTRACE_LOGE("Application tracing via TRAX is disabled in menuconfig!"); + return ESP_ERR_NOT_SUPPORTED; +#endif + } else { + ESP_APPTRACE_LOGE("Trace destinations other then TRAX are not supported yet!"); + return ESP_ERR_NOT_SUPPORTED; + } + + // ESP_APPTRACE_LOGI("fmt %x", fmt); + while ((p = (uint8_t *)strchr((char *)p, '%')) && nargs < ESP_APPTRACE_MAX_VPRINTF_ARGS) { + p++; + if (*p != '%' && *p != 0) { + nargs++; + } + } + // ESP_APPTRACE_LOGI("nargs = %d", nargs); + if (p) { + ESP_APPTRACE_LOGE("Failed to store all printf args!"); + } + + pout = apptrace_get_buffer(1 + sizeof(char *) + nargs * sizeof(uint32_t), &tmo); + if (pout == NULL) { + ESP_APPTRACE_LOGE("Failed to get buffer!"); + return -1; + } + p = pout; + *pout = nargs; + pout++; + *(const char **)pout = fmt; + pout += sizeof(char *); + while (nargs-- > 0) { + uint32_t arg = va_arg(ap, uint32_t); + *(uint32_t *)pout = arg; + pout += sizeof(uint32_t); + // ESP_APPTRACE_LOGI("arg %x", arg); + } + + int ret = apptrace_put_buffer(p, &tmo); + if (ret != ESP_OK) { + ESP_APPTRACE_LOGE("Failed to put printf buf (%d)!", ret); + return -1; + } + + return (pout - p); +} + +int esp_apptrace_vprintf(const char *fmt, va_list ap) +{ + return esp_apptrace_vprintf_to(ESP_APPTRACE_DEST_TRAX, /*ESP_APPTRACE_TMO_INFINITE*/0, fmt, ap); +} + +uint8_t *esp_apptrace_buffer_get(esp_apptrace_dest_t dest, size_t size, uint32_t user_tmo) +{ + uint32_t tmo = user_tmo; + //TODO: use ptr to HW transport iface struct + uint8_t *(*apptrace_get_buffer)(size_t, uint32_t *); + + if (dest == ESP_APPTRACE_DEST_TRAX) { +#if CONFIG_ESP32_APPTRACE_DEST_TRAX + apptrace_get_buffer = esp_apptrace_trax_get_buffer; +#else + ESP_APPTRACE_LOGE("Application tracing via TRAX is disabled in menuconfig!"); + return NULL; +#endif + } else { + ESP_APPTRACE_LOGE("Trace destinations other then TRAX are not supported yet!"); + return NULL; + } + + return apptrace_get_buffer(size, &tmo); +} + +esp_err_t esp_apptrace_buffer_put(esp_apptrace_dest_t dest, uint8_t *ptr, uint32_t user_tmo) +{ + uint32_t tmo = user_tmo; + //TODO: use ptr to HW transport iface struct + esp_err_t (*apptrace_put_buffer)(uint8_t *, uint32_t *); + + if (dest == ESP_APPTRACE_DEST_TRAX) { +#if CONFIG_ESP32_APPTRACE_DEST_TRAX + apptrace_put_buffer = esp_apptrace_trax_put_buffer; +#else + ESP_APPTRACE_LOGE("Application tracing via TRAX is disabled in menuconfig!"); + return ESP_ERR_NOT_SUPPORTED; +#endif + } else { + ESP_APPTRACE_LOGE("Trace destinations other then TRAX are not supported yet!"); + return ESP_ERR_NOT_SUPPORTED; + } + + return apptrace_put_buffer(ptr, &tmo); +} + +esp_err_t esp_apptrace_flush_nolock(esp_apptrace_dest_t dest, uint32_t min_sz, uint32_t tmo) +{ + //TODO: use ptr to HW transport iface struct + esp_err_t (*apptrace_flush)(uint32_t, uint32_t); + + if (dest == ESP_APPTRACE_DEST_TRAX) { +#if CONFIG_ESP32_APPTRACE_DEST_TRAX + apptrace_flush = esp_apptrace_trax_flush; +#else + ESP_APPTRACE_LOGE("Application tracing via TRAX is disabled in menuconfig!"); + return ESP_ERR_NOT_SUPPORTED; +#endif + } else { + ESP_APPTRACE_LOGE("Trace destinations other then TRAX are not supported yet!"); + return ESP_ERR_NOT_SUPPORTED; + } + + return apptrace_flush(min_sz, tmo); +} + +esp_err_t esp_apptrace_flush(esp_apptrace_dest_t dest, uint32_t tmo) +{ + int res; + + res = esp_apptrace_lock(&tmo); + if (res != ESP_OK) { + ESP_APPTRACE_LOGE("Failed to lock apptrace data (%d)!", res); + return res; + } + + res = esp_apptrace_flush_nolock(dest, 0, tmo); + if (res != ESP_OK) { + ESP_APPTRACE_LOGE("Failed to fluch apptrace data (%d)!", res); + } + + if (esp_apptrace_unlock() != ESP_OK) { + ESP_APPTRACE_LOGE("Failed to unlock apptrace data (%d)!", res); + } + + return res; +} + +#if ESP_APPTRACE_DEBUG_STATS_ENABLE == 1 +void esp_apptrace_print_stats() +{ + uint32_t i; + uint32_t tmo = ESP_APPTRACE_TMO_INFINITE; + + esp_apptrace_lock(&tmo); + + for (i = s_trace_buf.state.stats.wr.hist_rd; (i < s_trace_buf.state.stats.wr.hist_wr) && (i < ESP_APPTRACE_BUF_HISTORY_DEPTH); i++) { + esp_trace_buffer_wr_hitem_t *hi = (esp_trace_buffer_wr_hitem_t *)&s_trace_buf.state.stats.wr.hist[i]; + ESP_APPTRACE_LOGO("hist[%u] = {%x, %x}", i, hi->hnd, hi->ts); + } + if (i == ESP_APPTRACE_BUF_HISTORY_DEPTH) { + for (i = 0; i < s_trace_buf.state.stats.wr.hist_wr; i++) { + esp_trace_buffer_wr_hitem_t *hi = (esp_trace_buffer_wr_hitem_t *)&s_trace_buf.state.stats.wr.hist[i]; + ESP_APPTRACE_LOGO("hist[%u] = {%x, %x}", i, hi->hnd, hi->ts); + } + } + + esp_apptrace_unlock(); +} +#endif +#endif diff --git a/components/esp32/cpu_start.c b/components/esp32/cpu_start.c index c3ef142c6..7211b8b47 100644 --- a/components/esp32/cpu_start.c +++ b/components/esp32/cpu_start.c @@ -59,6 +59,7 @@ #include "esp_coexist.h" #include "esp_panic.h" #include "esp_core_dump.h" +#include "esp_app_trace.h" #include "trax.h" #define STRINGIFY(s) STRINGIFY2(s) @@ -108,20 +109,21 @@ void IRAM_ATTR call_start_cpu0() ::"r"(&_init_start)); rst_reas[0] = rtc_get_reset_reason(0); + #if !CONFIG_FREERTOS_UNICORE rst_reas[1] = rtc_get_reset_reason(1); #endif + // from panic handler we can be reset by RWDT or TG0WDT if (rst_reas[0] == RTCWDT_SYS_RESET || rst_reas[0] == TG0WDT_SYS_RESET #if !CONFIG_FREERTOS_UNICORE || rst_reas[1] == RTCWDT_SYS_RESET || rst_reas[1] == TG0WDT_SYS_RESET #endif - ) { - // stop wdt in case of any - ESP_EARLY_LOGI(TAG, "Stop panic WDT"); + ) { esp_panic_wdt_stop(); } + //Clear BSS. Please do not attempt to do any complex stuff (like early logging) before this. memset(&_bss_start, 0, (&_bss_end - &_bss_start) * sizeof(_bss_start)); /* Unless waking from deep sleep (implying RTC memory is intact), clear RTC bss */ @@ -129,7 +131,6 @@ void IRAM_ATTR call_start_cpu0() memset(&_rtc_bss_start, 0, (&_rtc_bss_end - &_rtc_bss_start) * sizeof(_rtc_bss_start)); } - ESP_EARLY_LOGI(TAG, "Pro cpu up."); #if !CONFIG_FREERTOS_UNICORE @@ -193,8 +194,8 @@ void start_cpu0_default(void) { esp_setup_syscall_table(); //Enable trace memory and immediately start trace. -#if CONFIG_MEMMAP_TRACEMEM -#if CONFIG_MEMMAP_TRACEMEM_TWOBANKS +#if CONFIG_ESP32_TRAX +#if CONFIG_ESP32_TRAX_TWOBANKS trax_enable(TRAX_ENA_PRO_APP); #else trax_enable(TRAX_ENA_PRO); @@ -221,6 +222,12 @@ void start_cpu0_default(void) _GLOBAL_REENT->_stdin = (FILE*) &__sf_fake_stdin; _GLOBAL_REENT->_stdout = (FILE*) &__sf_fake_stdout; _GLOBAL_REENT->_stderr = (FILE*) &__sf_fake_stderr; +#endif +#if CONFIG_ESP32_APPTRACE_ENABLE + esp_err_t err = esp_apptrace_init(); + if (err != ESP_OK) { + ESP_EARLY_LOGE(TAG, "Failed to init apptrace module on CPU0 (%d)!", err); + } #endif do_global_ctors(); #if CONFIG_INT_WDT @@ -250,8 +257,14 @@ void start_cpu0_default(void) #if !CONFIG_FREERTOS_UNICORE void start_cpu1_default(void) { -#if CONFIG_MEMMAP_TRACEMEM_TWOBANKS +#if CONFIG_ESP32_TRAX_TWOBANKS trax_start_trace(TRAX_DOWNCOUNT_WORDS); +#endif +#if CONFIG_ESP32_APPTRACE_ENABLE + esp_err_t err = esp_apptrace_init(); + if (err != ESP_OK) { + ESP_EARLY_LOGE(TAG, "Failed to init apptrace module on CPU1 (%d)!", err); + } #endif // Wait for FreeRTOS initialization to finish on PRO CPU while (port_xSchedulerRunning[0] == 0) { diff --git a/components/esp32/include/esp_app_trace.h b/components/esp32/include/esp_app_trace.h new file mode 100644 index 000000000..bd33e589d --- /dev/null +++ b/components/esp32/include/esp_app_trace.h @@ -0,0 +1,123 @@ +// Copyright 2017 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. +#ifndef ESP_APP_TRACE_H_ +#define ESP_APP_TRACE_H_ + +#include +#include "esp_err.h" + +// infinite waiting timeout +#define ESP_APPTRACE_TMO_INFINITE ((uint32_t)-1) + +// Trace memory block size +#define ESP_APPTRACE_TRAX_BLOCK_SIZE 0x4000UL + +/** + * Application trace data destinations bits. + */ +typedef enum { + ESP_APPTRACE_DEST_TRAX = 0x1, + ESP_APPTRACE_DEST_UART0 = 0x2, + //ESP_APPTRACE_DEST_UART1 = 0x4, +} esp_apptrace_dest_t; + +/** + * @brief Initializes application tracing module. + * + * @note Should be called before any esp_apptrace_xxx call. + * + * @return ESP_OK on success, otherwise \see esp_err_t + */ +esp_err_t esp_apptrace_init(); + +/** + * @brief Allocates buffer for trace data. + * After data in buffer are ready to be sent off esp_apptrace_buffer_put must be called to indicate it. + * + * @param dest Indicates HW interface to send data. + * @param size Size of data to write to trace buffer. + * @param tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinetly. + * + * @return non-NULL on success, otherwise NULL. + */ +uint8_t *esp_apptrace_buffer_get(esp_apptrace_dest_t dest, size_t size, uint32_t tmo); + +/** + * @brief Indicates that the data in buffer are ready to be sent off. + * This function is a counterpart of must be preceeded by esp_apptrace_buffer_get. + * + * @param dest Indicates HW interface to send data. Should be identical to the same parameter in call to esp_apptrace_buffer_get. + * @param ptr Address of trace buffer to release. Should be the value returned by call to esp_apptrace_buffer_get. + * @param tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinetly. + * + * @return ESP_OK on success, otherwise \see esp_err_t + */ +esp_err_t esp_apptrace_buffer_put(esp_apptrace_dest_t dest, uint8_t *ptr, uint32_t tmo); + +/** + * @brief Writes data to trace buffer. + * + * @param dest Indicates HW interface to send data. + * @param data Address of data to write to trace buffer. + * @param size Size of data to write to trace buffer. + * @param tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinetly. + * + * @return ESP_OK on success, otherwise \see esp_err_t + */ +esp_err_t esp_apptrace_write(esp_apptrace_dest_t dest, void *data, size_t size, uint32_t tmo); + +/** + * @brief vprintf-like function to sent log messages to host via specified HW interface. + * + * @param dest Indicates HW interface to send data. + * @param fmt Address of format string. + * @param ap List of arguments. + * + * @return Number of bytes written. + */ +int esp_apptrace_vprintf_to(esp_apptrace_dest_t dest, uint32_t user_tmo, const char *fmt, va_list ap); + +/** + * @brief vprintf-like function to sent log messages to host. + * + * @param fmt Address of format string. + * @param ap List of arguments. + * + * @return Number of bytes written. + */ +int esp_apptrace_vprintf(const char *fmt, va_list ap); + +/** + * @brief Flushes remaining data in trace buffer to host. + * + * @param dest Indicates HW interface to flush data on. + * @param tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinetly. + * + * @return ESP_OK on success, otherwise \see esp_err_t + */ +esp_err_t esp_apptrace_flush(esp_apptrace_dest_t dest, uint32_t tmo); + +/** + * @brief Flushes remaining data in trace buffer to host without locking internal data. + This is special version of esp_apptrace_flush which should be called from panic handler. + * + * @param dest Indicates HW interface to flush data on. + * @param min_sz Threshold for flushing data. If current filling level is above this value, data will be flushed. TRAX destinations only. + * @param tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinetly. + * + * @return ESP_OK on success, otherwise \see esp_err_t + */ +esp_err_t esp_apptrace_flush_nolock(esp_apptrace_dest_t dest, uint32_t min_sz, uint32_t tmo); + +#endif diff --git a/components/esp32/include/esp_system.h b/components/esp32/include/esp_system.h index 9a88743b8..24eebb8b0 100644 --- a/components/esp32/include/esp_system.h +++ b/components/esp32/include/esp_system.h @@ -103,7 +103,33 @@ uint32_t system_get_free_heap_size(void) __attribute__ ((deprecated)); uint32_t esp_random(void); /** - * @brief Read hardware MAC address. + * @brief Set base MAC address from external storage e.g. flash and EEPROM. + * + * Base MAC address is used to generate the MAC addresses used by the networking interfaces. + * If using base MAC address stored in external storage, call this API to set base MAC + * address from external storage before initializing WiFi/BT/Ethernet. + * + * @param mac base MAC address, length: 6 bytes. + * + * @return ESP_OK on success + */ +esp_err_t esp_base_mac_addr_set_external(uint8_t *mac); + +/** + * @brief Return base MAC address set using esp_mac_addr_set_external. + * + * @param mac base MAC address, length: 6 bytes. + * + * Base MAC address is used to generate the MAC addresses used by the networking interfaces. + * If using base MAC address stored in external storage, call this API to set base MAC + * address from external storage before initializing WiFi/BT/Ethernet. + * + * @return ESP_OK on success + */ +esp_err_t esp_base_mac_addr_get_external(uint8_t *mac); + +/** + * @brief Read hardware MAC address from efuse. * * In WiFi MAC, only ESP32 station MAC is the hardware MAC, ESP32 softAP MAC is a software MAC * calculated from ESP32 station MAC. diff --git a/components/esp32/include/esp_task.h b/components/esp32/include/esp_task.h index 522067ca7..aa694d3aa 100644 --- a/components/esp32/include/esp_task.h +++ b/components/esp32/include/esp_task.h @@ -46,7 +46,7 @@ #define ESP_TASKD_EVENT_PRIO (ESP_TASK_PRIO_MAX - 5) #define ESP_TASKD_EVENT_STACK CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE #define ESP_TASK_TCPIP_PRIO (ESP_TASK_PRIO_MAX - 7) -#define ESP_TASK_TCPIP_STACK 2048 +#define ESP_TASK_TCPIP_STACK CONFIG_TCPIP_TASK_STACK_SIZE #define ESP_TASK_MAIN_PRIO (ESP_TASK_PRIO_MIN + 1) #define ESP_TASK_MAIN_STACK CONFIG_MAIN_TASK_STACK_SIZE diff --git a/components/esp32/include/esp_wifi_types.h b/components/esp32/include/esp_wifi_types.h index a473d3b04..b47aa351f 100755 --- a/components/esp32/include/esp_wifi_types.h +++ b/components/esp32/include/esp_wifi_types.h @@ -20,7 +20,6 @@ #include #include "rom/queue.h" #include "esp_err.h" -#include "esp_wifi_types.h" #include "esp_interface.h" #ifdef __cplusplus diff --git a/components/esp32/include/rom/efuse.h b/components/esp32/include/rom/efuse.h index 58cfdb20b..337227ab0 100644 --- a/components/esp32/include/rom/efuse.h +++ b/components/esp32/include/rom/efuse.h @@ -60,15 +60,20 @@ void ets_efuse_program_op(void); uint32_t ets_efuse_get_8M_clock(void); /** - * @brief Read spi pad configuration, show gpio number of flash pad, includes 5 pads. + * @brief Read spi flash pin configuration from Efuse * - * @param null - * - * @return uint32_t: 0, invalid, flash pad decided by strapping - * else, bit[5:0] spiclk, bit[11:6] spiq, bit[17:12] spid, bit[23:18] spics0, bit[29:24] spihd + * @return + * - 0 for default SPI pins. + * - 1 for default HSPI pins. + * - Other values define a custom pin configuration mask. Pins are encoded as per the EFUSE_SPICONFIG_RET_SPICLK, + * EFUSE_SPICONFIG_RET_SPIQ, EFUSE_SPICONFIG_RET_SPID, EFUSE_SPICONFIG_RET_SPICS0, EFUSE_SPICONFIG_RET_SPIHD macros. + * WP pin (for quad I/O modes) is not saved in efuse and not returned by this function. */ uint32_t ets_efuse_get_spiconfig(void); +#define EFUSE_SPICONFIG_SPI_DEFAULTS 0 +#define EFUSE_SPICONFIG_HSPI_DEFAULTS 1 + #define EFUSE_SPICONFIG_RET_SPICLK_MASK 0x3f #define EFUSE_SPICONFIG_RET_SPICLK_SHIFT 0 #define EFUSE_SPICONFIG_RET_SPICLK(ret) (((ret) >> EFUSE_SPICONFIG_RET_SPICLK_SHIFT) & EFUSE_SPICONFIG_RET_SPICLK_MASK) diff --git a/components/esp32/include/rom/spi_flash.h b/components/esp32/include/rom/spi_flash.h index bb2da748b..35d010d79 100644 --- a/components/esp32/include/rom/spi_flash.h +++ b/components/esp32/include/rom/spi_flash.h @@ -279,25 +279,13 @@ esp_rom_spiflash_result_t esp_rom_spiflash_read_user_cmd(uint32_t *status, uint8 * * @param esp_rom_spiflash_read_mode_t mode : QIO/QOUT/DIO/DOUT/FastRD/SlowRD. * - * @param uint8_t legacy: In legacy mode, more SPI command is used in line. + * This function does not try to set the QIO Enable bit in the status register, caller is responsible for this. * * @return ESP_ROM_SPIFLASH_RESULT_OK : config OK. * ESP_ROM_SPIFLASH_RESULT_ERR : config error. * ESP_ROM_SPIFLASH_RESULT_TIMEOUT : config timeout. */ -esp_rom_spiflash_result_t esp_rom_spiflash_config_readmode(esp_rom_spiflash_read_mode_t mode, bool legacy); - -/** - * @brief Config SPI Flash read mode when Flash is running in some mode. - * Please do not call this function in SDK. - * - * @param esp_rom_spiflash_read_mode_t mode : QIO/QOUT/DIO/DOUT/FastRD/SlowRD. - * - * @return ESP_ROM_SPIFLASH_RESULT_OK : config OK. - * ESP_ROM_SPIFLASH_RESULT_ERR : config error. - * ESP_ROM_SPIFLASH_RESULT_TIMEOUT : config timeout. - */ -esp_rom_spiflash_result_t esp_rom_spiflash_master_config_readmode(esp_rom_spiflash_read_mode_t mode); +esp_rom_spiflash_result_t esp_rom_spiflash_config_readmode(esp_rom_spiflash_read_mode_t mode); /** * @brief Config SPI Flash clock divisor. @@ -524,6 +512,24 @@ esp_rom_spiflash_result_t esp_rom_spiflash_write_encrypted(uint32_t flash_addr, esp_rom_spiflash_result_t esp_rom_spiflash_wait_idle(esp_rom_spiflash_chip_t *spi); +/** @brief Enable Quad I/O pin functions + * + * @note Please do not call this function in SDK. + * + * Sets the HD & WP pin functions for Quad I/O modes, based on the + * efuse SPI pin configuration. + * + * @param wp_gpio_num - Number of the WP pin to reconfigure for quad I/O. + * + * @param spiconfig - Pin configuration, as returned from ets_efuse_get_spiconfig(). + * - If this parameter is 0, default SPI pins are used and wp_gpio_num parameter is ignored. + * - If this parameter is 1, default HSPI pins are used and wp_gpio_num parameter is ignored. + * - For other values, this parameter encodes the HD pin number and also the CLK pin number. CLK pin selection is used + * to determine if HSPI or SPI peripheral will be used (use HSPI if CLK pin is the HSPI clock pin, otherwise use SPI). + * Both HD & WP pins are configured via GPIO matrix to map to the selected peripheral. + */ +void esp_rom_spiflash_select_qio_pins(uint8_t wp_gpio_num, uint32_t spiconfig); + /** @brief Global esp_rom_spiflash_chip_t structure used by ROM functions * */ diff --git a/components/esp32/ld/esp32.common.ld b/components/esp32/ld/esp32.common.ld index 5c1dba68c..48e31d1ea 100644 --- a/components/esp32/ld/esp32.common.ld +++ b/components/esp32/ld/esp32.common.ld @@ -86,16 +86,11 @@ SECTIONS *libesp32.a:panic.o(.literal .text .literal.* .text.*) *libesp32.a:core_dump.o(.literal .text .literal.* .text.*) *libesp32.a:heap_alloc_caps.o(.literal .text .literal.* .text.*) + *libesp32.a:app_trace.o(.literal .text .literal.* .text.*) *libphy.a:(.literal .text .literal.* .text.*) *librtc.a:(.literal .text .literal.* .text.*) *libsoc.a:(.literal .text .literal.* .text.*) - *libpp.a:pp.o(.literal .text .literal.* .text.*) - *libpp.a:lmac.o(.literal .text .literal.* .text.*) - *libpp.a:wdev.o(.literal .text .literal.* .text.*) - *libcore.a:ets_timer.o(.literal .text .literal.* .text.*) - *libnet80211.a:ieee80211_misc.o(.literal .text .literal.* .text.*) *libhal.a:(.literal .text .literal.* .text.*) - *libcoexist.a:(.literal .text .literal.* .text.*) *libspi_flash.a:spi_flash_rom_patch.o(.literal .text .literal.* .text.*) _iram_text_end = ABSOLUTE(.); } > iram0_0_seg @@ -116,6 +111,8 @@ SECTIONS KEEP(*(.jcr)) *(.dram1 .dram1.*) *libesp32.a:panic.o(.rodata .rodata.*) + *libesp32.a:app_trace.o(.rodata .rodata.*) + *libphy.a:(.rodata .rodata.*) _data_end = ABSOLUTE(.); . = ALIGN(4); } >dram0_0_seg diff --git a/components/esp32/ld/esp32.rom.ld b/components/esp32/ld/esp32.rom.ld index 6529e31df..3b81f2cec 100644 --- a/components/esp32/ld/esp32.rom.ld +++ b/components/esp32/ld/esp32.rom.ld @@ -1537,6 +1537,7 @@ PROVIDE ( esp_rom_spiflash_read_user_cmd = 0x400621b0 ); PROVIDE ( esp_rom_spiflash_write_encrypted_disable = 0x40062e60 ); PROVIDE ( esp_rom_spiflash_write_encrypted_enable = 0x40062df4 ); PROVIDE ( esp_rom_spiflash_prepare_encrypted_data = 0x40062e1c ); +PROVIDE ( esp_rom_spiflash_select_qio_pins = 0x40061ddc ); PROVIDE ( g_rom_spiflash_chip = 0x3ffae270 ); /* diff --git a/components/esp32/ld/esp32.rom.spiflash.ld b/components/esp32/ld/esp32.rom.spiflash.ld index 64af6a4b9..709b35811 100644 --- a/components/esp32/ld/esp32.rom.spiflash.ld +++ b/components/esp32/ld/esp32.rom.spiflash.ld @@ -10,7 +10,7 @@ PROVIDE ( esp_rom_spiflash_erase_chip = 0x40062c14 ); PROVIDE ( esp_rom_spiflash_erase_sector = 0x40062ccc ); PROVIDE ( esp_rom_spiflash_lock = 0x400628f0 ); PROVIDE ( esp_rom_spiflash_read = 0x40062ed8 ); -PROVIDE ( esp_rom_spiflash_config_readmode = 0x40062944 ); +PROVIDE ( esp_rom_spiflash_config_readmode = 0x40062b64 ); /* SPIMasterReadModeCnfig */ PROVIDE ( esp_rom_spiflash_read_status = 0x4006226c ); PROVIDE ( esp_rom_spiflash_read_statushigh = 0x40062448 ); PROVIDE ( esp_rom_spiflash_write = 0x40062d50 ); diff --git a/components/esp32/lib b/components/esp32/lib index 7910a6872..53aac75af 160000 --- a/components/esp32/lib +++ b/components/esp32/lib @@ -1 +1 @@ -Subproject commit 7910a6872bbdd50e0184cfc5bd2a9a2040231a1b +Subproject commit 53aac75afe219af9feca42aca7f1126d394844c9 diff --git a/components/esp32/panic.c b/components/esp32/panic.c index 08c13f765..8ec362f9c 100644 --- a/components/esp32/panic.c +++ b/components/esp32/panic.c @@ -38,6 +38,7 @@ #include "esp_core_dump.h" #include "esp_spi_flash.h" #include "esp_cache_err_int.h" +#include "esp_app_trace.h" /* Panic handlers; these get called when an unhandled exception occurs or the assembly-level @@ -114,6 +115,9 @@ static bool abort_called; static __attribute__((noreturn)) inline void invoke_abort() { abort_called = true; +#if CONFIG_ESP32_APPTRACE_ENABLE + esp_apptrace_flush_nolock(ESP_APPTRACE_DEST_TRAX, ESP_APPTRACE_TRAX_BLOCK_SIZE*CONFIG_ESP32_APPTRACE_ONPANIC_HOST_FLUSH_TRAX_THRESH/100, CONFIG_ESP32_APPTRACE_ONPANIC_HOST_FLUSH_TMO); +#endif while(1) { __asm__ ("break 0,0"); *((int*) 0) = 0; @@ -226,6 +230,9 @@ void panicHandler(XtExcFrame *frame) } if (esp_cpu_in_ocd_debug_mode()) { +#if CONFIG_ESP32_APPTRACE_ENABLE + esp_apptrace_flush_nolock(ESP_APPTRACE_DEST_TRAX, ESP_APPTRACE_TRAX_BLOCK_SIZE*CONFIG_ESP32_APPTRACE_ONPANIC_HOST_FLUSH_TRAX_THRESH/100, CONFIG_ESP32_APPTRACE_ONPANIC_HOST_FLUSH_TMO); +#endif setFirstBreakpoint(frame->pc); return; } @@ -248,6 +255,9 @@ void xt_unhandled_exception(XtExcFrame *frame) panicPutStr(" at pc="); panicPutHex(frame->pc); panicPutStr(". Setting bp and returning..\r\n"); +#if CONFIG_ESP32_APPTRACE_ENABLE + esp_apptrace_flush_nolock(ESP_APPTRACE_DEST_TRAX, ESP_APPTRACE_TRAX_BLOCK_SIZE*CONFIG_ESP32_APPTRACE_ONPANIC_HOST_FLUSH_TRAX_THRESH/100, CONFIG_ESP32_APPTRACE_ONPANIC_HOST_FLUSH_TMO); +#endif //Stick a hardware breakpoint on the address the handler returns to. This way, the OCD debugger //will kick in exactly at the context the error happened. setFirstBreakpoint(frame->pc); @@ -282,11 +292,10 @@ static void reconfigureAllWdts() TIMERG1.wdt_wprotect = 0; } -#if CONFIG_ESP32_PANIC_GDBSTUB || CONFIG_ESP32_PANIC_PRINT_HALT || CONFIG_ESP32_ENABLE_COREDUMP /* This disables all the watchdogs for when we call the gdbstub. */ -static void disableAllWdts() +static inline void disableAllWdts() { TIMERG0.wdt_wprotect = TIMG_WDT_WKEY_VALUE; TIMERG0.wdt_config0.en = 0; @@ -296,8 +305,6 @@ static void disableAllWdts() TIMERG1.wdt_wprotect = 0; } -#endif - static void esp_panic_wdt_start() { if (REG_GET_BIT(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_EN)) { @@ -422,6 +429,12 @@ static void commonErrorHandler(XtExcFrame *frame) /* With windowed ABI backtracing is easy, let's do it. */ doBacktrace(frame); +#if CONFIG_ESP32_APPTRACE_ENABLE + disableAllWdts(); + esp_apptrace_flush_nolock(ESP_APPTRACE_DEST_TRAX, ESP_APPTRACE_TRAX_BLOCK_SIZE*CONFIG_ESP32_APPTRACE_ONPANIC_HOST_FLUSH_TRAX_THRESH/100, CONFIG_ESP32_APPTRACE_ONPANIC_HOST_FLUSH_TMO); + reconfigureAllWdts(); +#endif + #if CONFIG_ESP32_PANIC_GDBSTUB disableAllWdts(); esp_panic_wdt_stop(); diff --git a/components/esp32/system_api.c b/components/esp32/system_api.c index 028513718..ab271063e 100644 --- a/components/esp32/system_api.c +++ b/components/esp32/system_api.c @@ -36,16 +36,48 @@ static const char* TAG = "system_api"; +static uint8_t ext_base_mac_addr[6] = {0}; + void system_init() { } +esp_err_t esp_base_mac_addr_set_external(uint8_t *mac) +{ + if (mac == NULL) { + ESP_LOGE(TAG, "External base MAC address is NULL"); + abort(); + } + + memcpy(ext_base_mac_addr, mac, 6); + + return ESP_OK; +} + +esp_err_t esp_base_mac_addr_get_external(uint8_t *mac) +{ + uint8_t null_mac[6] = {0}; + + if (memcmp(ext_base_mac_addr, null_mac, 6) == 0) { + ESP_LOGE(TAG, "External MAC address is not set"); + abort(); + } + + memcpy(mac, ext_base_mac_addr, 6); + + return ESP_OK; +} + esp_err_t esp_efuse_read_mac(uint8_t* mac) { + uint32_t mac_low; + uint32_t mac_high; uint8_t efuse_crc; uint8_t calc_crc; - uint32_t mac_low = REG_READ(EFUSE_BLK0_RDATA1_REG); - uint32_t mac_high = REG_READ(EFUSE_BLK0_RDATA2_REG); + +#ifdef CONFIG_BASE_MAC_STORED_DEFAULT_EFUSE + mac_low = REG_READ(EFUSE_BLK0_RDATA1_REG); + mac_high = REG_READ(EFUSE_BLK0_RDATA2_REG); mac[0] = mac_high >> 8; mac[1] = mac_high; @@ -55,6 +87,27 @@ esp_err_t esp_efuse_read_mac(uint8_t* mac) mac[5] = mac_low; efuse_crc = mac_high >> 16; +#else + uint8_t version = REG_READ(EFUSE_BLK3_RDATA5_REG) >> 24; + + if (version != 1) { + ESP_LOGE(TAG, "Customer efuse MAC address version error, version = %d", version); + abort(); + } + + mac_low = REG_READ(EFUSE_BLK3_RDATA1_REG); + mac_high = REG_READ(EFUSE_BLK3_RDATA0_REG); + + mac[0] = mac_high >> 8; + mac[1] = mac_high >> 16; + mac[2] = mac_high >> 24; + mac[3] = mac_low; + mac[4] = mac_low >> 8; + mac[5] = mac_low >> 16; + + efuse_crc = mac_high; +#endif //CONFIG_BASE_MAC_STORED_DEFAULT_EFUSE + calc_crc = esp_crc8(mac, 6); if (efuse_crc != calc_crc) { @@ -114,7 +167,13 @@ esp_err_t esp_read_mac(uint8_t* mac, esp_mac_type_t type) || NUM_MAC_ADDRESS_FROM_EFUSE == TWO_MAC_ADDRESS_FROM_EFUSE, \ "incorrect NUM_MAC_ADDRESS_FROM_EFUSE value"); +#if defined(CONFIG_BASE_MAC_STORED_DEFAULT_EFUSE) || defined(CONFIG_BASE_MAC_STORED_CUSTOMER_DEFINED_EFUSE) esp_efuse_read_mac(efuse_mac); +#endif + +#if defined(CONFIG_BASE_MAC_STORED_OTHER_CUSTOMER_DEFINED_PLACE) + esp_base_mac_addr_get_external(efuse_mac); +#endif switch (type) { case ESP_MAC_WIFI_STA: diff --git a/components/esp32/test/test_trace.c b/components/esp32/test/test_trace.c new file mode 100644 index 000000000..48e53adba --- /dev/null +++ b/components/esp32/test/test_trace.c @@ -0,0 +1,817 @@ +#include +#include +#include +#include +#include +#include "unity.h" +#include "driver/timer.h" +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" +#include "freertos/task.h" +#if CONFIG_ESP32_APPTRACE_ENABLE == 1 +#include "esp_app_trace.h" + +#define ESP_APPTRACE_TEST_USE_PRINT_LOCK 0 +#define ESP_APPTRACE_TEST_PRN_WRERR_MAX 5 +#define ESP_APPTRACE_TEST_BLOCKS_BEFORE_CRASH 100 +#define ESP_APPTRACE_TEST_BLOCK_SIZE 1024 + +#define LOG_LOCAL_LEVEL ESP_LOG_VERBOSE +#include "esp_log.h" +const static char *TAG = "esp_apptrace_test"; + +#if ESP_APPTRACE_TEST_USE_PRINT_LOCK == 1 +#define ESP_APPTRACE_TEST_LOG( format, ... ) \ + do { \ + BaseType_t ret; \ + if (xPortInIsrContext()) \ + ret = xSemaphoreTakeFromISR(s_print_lock, NULL); \ + else \ + ret = xSemaphoreTake(s_print_lock, portMAX_DELAY); \ + if (ret == pdTRUE) { \ + ets_printf(format, ##__VA_ARGS__); \ + if (xPortInIsrContext()) \ + xSemaphoreGiveFromISR(s_print_lock, NULL); \ + else \ + xSemaphoreGive(s_print_lock); \ + } \ + } while(0) +#else +#define ESP_APPTRACE_TEST_LOG( format, ... ) \ + do { \ + ets_printf(format, ##__VA_ARGS__); \ + } while(0) +#endif + +#define ESP_APPTRACE_TEST_LOG_LEVEL( _L_, level, format, ... ) \ + do { \ + if (LOG_LOCAL_LEVEL >= level) { \ + ESP_APPTRACE_TEST_LOG(LOG_FORMAT(_L_, format), esp_log_early_timestamp(), TAG, ##__VA_ARGS__); \ + } \ + } while(0) + +#define ESP_APPTRACE_TEST_LOGE( format, ... ) ESP_APPTRACE_TEST_LOG_LEVEL(E, ESP_LOG_ERROR, format, ##__VA_ARGS__) +#define ESP_APPTRACE_TEST_LOGW( format, ... ) ESP_APPTRACE_TEST_LOG_LEVEL(W, ESP_LOG_WARN, format, ##__VA_ARGS__) +#define ESP_APPTRACE_TEST_LOGI( format, ... ) ESP_APPTRACE_TEST_LOG_LEVEL(I, ESP_LOG_INFO, format, ##__VA_ARGS__) +#define ESP_APPTRACE_TEST_LOGD( format, ... ) ESP_APPTRACE_TEST_LOG_LEVEL(D, ESP_LOG_DEBUG, format, ##__VA_ARGS__) +#define ESP_APPTRACE_TEST_LOGV( format, ... ) ESP_APPTRACE_TEST_LOG_LEVEL(V, ESP_LOG_VERBOSE, format, ##__VA_ARGS__) +#define ESP_APPTRACE_TEST_LOGO( format, ... ) ESP_APPTRACE_TEST_LOG_LEVEL(E, ESP_LOG_NONE, format, ##__VA_ARGS__) + +#define ESP_APPTRACE_TEST_WRITE(_b_, _s_) esp_apptrace_write(ESP_APPTRACE_DEST_TRAX, _b_, _s_, ESP_APPTRACE_TMO_INFINITE) +#define ESP_APPTRACE_TEST_WRITE_FROM_ISR(_b_, _s_) esp_apptrace_write(ESP_APPTRACE_DEST_TRAX, _b_, _s_, 100UL) +#define ESP_APPTRACE_TEST_WRITE_NOWAIT(_b_, _s_) esp_apptrace_write(ESP_APPTRACE_DEST_TRAX, _b_, _s_, 0) + +#define ESP_APPTRACE_TEST_CPUTICKS2US(_t_) ((_t_)/(XT_CLOCK_FREQ/1000000)) + +typedef struct { + uint8_t *buf; + uint32_t buf_sz; + uint8_t mask; + uint32_t period; // trace write period in us + uint32_t wr_err; + uint32_t wr_cnt; +} esp_apptrace_test_gen_data_t; + +typedef struct { + int group; + int id; + void (*isr_func)(void *); + esp_apptrace_test_gen_data_t data; +} esp_apptrace_test_timer_arg_t; + +typedef struct { + int nowait; + int core; + int prio; + void (*task_func)(void *); + esp_apptrace_test_gen_data_t data; + volatile int stop; + SemaphoreHandle_t done; + + uint32_t timers_num; + esp_apptrace_test_timer_arg_t *timers; +} esp_apptrace_test_task_arg_t; + +typedef struct { + uint32_t tasks_num; + esp_apptrace_test_task_arg_t *tasks; +} esp_apptrace_test_cfg_t; + +#if ESP_APPTRACE_TEST_USE_PRINT_LOCK == 1 +static SemaphoreHandle_t s_print_lock; +#endif + +static uint64_t esp_apptrace_test_ts_get(); + +static void esp_apptrace_test_timer_init(int timer_group, int timer_idx, uint32_t period) +{ + timer_config_t config; + uint64_t alarm_val = (period * (TIMER_BASE_CLK / 1000000UL)) / 2; + + config.alarm_en = 1; + config.auto_reload = 1; + config.counter_dir = TIMER_COUNT_UP; + config.divider = 1; + config.intr_type = TIMER_INTR_LEVEL; + config.counter_en = TIMER_PAUSE; + /*Configure timer*/ + timer_init(timer_group, timer_idx, &config); + /*Stop timer counter*/ + timer_pause(timer_group, timer_idx); + /*Load counter value */ + timer_set_counter_value(timer_group, timer_idx, 0x00000000ULL); + /*Set alarm value*/ + timer_set_alarm_value(timer_group, timer_idx, alarm_val); + /*Enable timer interrupt*/ + timer_enable_intr(timer_group, timer_idx); +} + +static void esp_apptrace_test_timer_isr(void *arg) +{ + esp_apptrace_test_timer_arg_t *tim_arg = (esp_apptrace_test_timer_arg_t *)arg; + + uint32_t *ts = (uint32_t *)(tim_arg->data.buf + sizeof(uint32_t)); + *ts = (uint32_t)esp_apptrace_test_ts_get(); + memset(tim_arg->data.buf + 2 * sizeof(uint32_t), tim_arg->data.wr_cnt & tim_arg->data.mask, tim_arg->data.buf_sz - 2 * sizeof(uint32_t)); + int res = ESP_APPTRACE_TEST_WRITE_FROM_ISR(tim_arg->data.buf, tim_arg->data.buf_sz); + if (res != ESP_OK) { + } else { + if (0) { + ets_printf("tim-%d-%d: Written chunk%d %d bytes, %x\n", + tim_arg->group, tim_arg->id, tim_arg->data.wr_cnt, tim_arg->data.buf_sz, tim_arg->data.wr_cnt & tim_arg->data.mask); + } + tim_arg->data.wr_err = 0; + } + + tim_arg->data.wr_cnt++; + if (tim_arg->group == 0) { + if (tim_arg->id == 0) { + TIMERG0.int_clr_timers.t0 = 1; + TIMERG0.hw_timer[0].update = 1; + TIMERG0.hw_timer[0].config.alarm_en = 1; + } else { + TIMERG0.int_clr_timers.t1 = 1; + TIMERG0.hw_timer[1].update = 1; + TIMERG0.hw_timer[1].config.alarm_en = 1; + } + } + if (tim_arg->group == 1) { + if (tim_arg->id == 0) { + TIMERG1.int_clr_timers.t0 = 1; + TIMERG1.hw_timer[0].update = 1; + TIMERG1.hw_timer[0].config.alarm_en = 1; + } else { + TIMERG1.int_clr_timers.t1 = 1; + TIMERG1.hw_timer[1].update = 1; + TIMERG1.hw_timer[1].config.alarm_en = 1; + } + } +} + +static void esp_apptrace_test_timer_isr_crash(void *arg) +{ + esp_apptrace_test_timer_arg_t *tim_arg = (esp_apptrace_test_timer_arg_t *)arg; + + if (tim_arg->group == 0) { + if (tim_arg->id == 0) { + TIMERG0.int_clr_timers.t0 = 1; + TIMERG0.hw_timer[0].update = 1; + TIMERG0.hw_timer[0].config.alarm_en = 1; + } else { + TIMERG0.int_clr_timers.t1 = 1; + TIMERG0.hw_timer[1].update = 1; + TIMERG0.hw_timer[1].config.alarm_en = 1; + } + } + if (tim_arg->group == 1) { + if (tim_arg->id == 0) { + TIMERG1.int_clr_timers.t0 = 1; + TIMERG1.hw_timer[0].update = 1; + TIMERG1.hw_timer[0].config.alarm_en = 1; + } else { + TIMERG1.int_clr_timers.t1 = 1; + TIMERG1.hw_timer[1].update = 1; + TIMERG1.hw_timer[1].config.alarm_en = 1; + } + } + if (tim_arg->data.wr_cnt < ESP_APPTRACE_TEST_BLOCKS_BEFORE_CRASH) { + uint32_t *ts = (uint32_t *)(tim_arg->data.buf + sizeof(uint32_t)); + *ts = (uint32_t)esp_apptrace_test_ts_get();//xthal_get_ccount();//xTaskGetTickCount(); + memset(tim_arg->data.buf + 2 * sizeof(uint32_t), tim_arg->data.wr_cnt & tim_arg->data.mask, tim_arg->data.buf_sz - 2 * sizeof(uint32_t)); + int res = ESP_APPTRACE_TEST_WRITE_FROM_ISR(tim_arg->data.buf, tim_arg->data.buf_sz); + if (res != ESP_OK) { + ets_printf("tim-%d-%d: Failed to write trace %d %x!\n", tim_arg->group, tim_arg->id, res, tim_arg->data.wr_cnt & tim_arg->data.mask); + } else { + ets_printf("tim-%d-%d: Written chunk%d %d bytes, %x\n", + tim_arg->group, tim_arg->id, tim_arg->data.wr_cnt, tim_arg->data.buf_sz, tim_arg->data.wr_cnt & tim_arg->data.mask); + tim_arg->data.wr_cnt++; + } + } else { + uint32_t *ptr = 0; + *ptr = 1000; + } +} + +static void esp_apptrace_dummy_task(void *p) +{ + esp_apptrace_test_task_arg_t *arg = (esp_apptrace_test_task_arg_t *) p; + int res, flags = 0, i; + timer_isr_handle_t *inth = NULL; + TickType_t tmo_ticks = arg->data.period / (1000 * portTICK_PERIOD_MS); + + ESP_APPTRACE_TEST_LOGI("%x: run dummy task (period %u us, %u timers)", xTaskGetCurrentTaskHandle(), arg->data.period, arg->timers_num); + + if (arg->timers_num > 0) { + inth = pvPortMalloc(arg->timers_num * sizeof(timer_isr_handle_t)); + if (!inth) { + ESP_APPTRACE_TEST_LOGE("Failed to alloc timer ISR handles!"); + goto on_fail; + } + memset(inth, 0, arg->timers_num * sizeof(timer_isr_handle_t)); + for (int i = 0; i < arg->timers_num; i++) { + esp_apptrace_test_timer_init(arg->timers[i].group, arg->timers[i].id, arg->timers[i].data.period); + res = timer_isr_register(arg->timers[i].group, arg->timers[i].id, arg->timers[i].isr_func, &arg->timers[i], flags, &inth[i]); + if (res != ESP_OK) { + ESP_APPTRACE_TEST_LOGE("Failed to timer_isr_register (%d)!", res); + goto on_fail; + } + *(uint32_t *)arg->timers[i].data.buf = (uint32_t)inth[i] | (1 << 31); + ESP_APPTRACE_TEST_LOGI("%x: start timer %x period %u us", xTaskGetCurrentTaskHandle(), inth[i], arg->timers[i].data.period); + res = timer_start(arg->timers[i].group, arg->timers[i].id); + if (res != ESP_OK) { + ESP_APPTRACE_TEST_LOGE("Failed to timer_start (%d)!", res); + goto on_fail; + } + } + } + + i = 0; + while (!arg->stop) { + ESP_APPTRACE_TEST_LOGD("%x: dummy task work %d.%d", xTaskGetCurrentTaskHandle(), xPortGetCoreID(), i++); + if (tmo_ticks) { + vTaskDelay(tmo_ticks); + } + } + +on_fail: + if (inth) { + for (int i = 0; i < arg->timers_num; i++) { + timer_pause(arg->timers[i].group, arg->timers[i].id); + timer_disable_intr(arg->timers[i].group, arg->timers[i].id); + if (inth[i]) { + esp_intr_free(inth[i]); + } + } + vPortFree(inth); + } + xSemaphoreGive(arg->done); + vTaskDelay(1); + vTaskDelete(NULL); +} + +static void esp_apptrace_test_task(void *p) +{ + esp_apptrace_test_task_arg_t *arg = (esp_apptrace_test_task_arg_t *) p; + int res, flags = 0; + timer_isr_handle_t *inth = NULL; + TickType_t tmo_ticks = arg->data.period / (1000 * portTICK_PERIOD_MS); + + ESP_APPTRACE_TEST_LOGI("%x: run (period %u us, stamp mask %x, %u timers)", xTaskGetCurrentTaskHandle(), arg->data.period, arg->data.mask, arg->timers_num); + + if (arg->timers_num > 0) { + inth = pvPortMalloc(arg->timers_num * sizeof(timer_isr_handle_t)); + if (!inth) { + ESP_APPTRACE_TEST_LOGE("Failed to alloc timer ISR handles!"); + goto on_fail; + } + memset(inth, 0, arg->timers_num * sizeof(timer_isr_handle_t)); + for (int i = 0; i < arg->timers_num; i++) { + esp_apptrace_test_timer_init(arg->timers[i].group, arg->timers[i].id, arg->timers[i].data.period); + res = timer_isr_register(arg->timers[i].group, arg->timers[i].id, arg->timers[i].isr_func, &arg->timers[i], flags, &inth[i]); + if (res != ESP_OK) { + ESP_APPTRACE_TEST_LOGE("Failed to timer_isr_register (%d)!", res); + goto on_fail; + } + *(uint32_t *)arg->timers[i].data.buf = ((uint32_t)inth[i]) | (1 << 31) | (xPortGetCoreID() ? 0x1 : 0); + ESP_APPTRACE_TEST_LOGI("%x: start timer %x period %u us", xTaskGetCurrentTaskHandle(), inth[i], arg->timers[i].data.period); + res = timer_start(arg->timers[i].group, arg->timers[i].id); + if (res != ESP_OK) { + ESP_APPTRACE_TEST_LOGE("Failed to timer_start (%d)!", res); + goto on_fail; + } + } + } + + *(uint32_t *)arg->data.buf = (uint32_t)xTaskGetCurrentTaskHandle() | (xPortGetCoreID() ? 0x1 : 0); + arg->data.wr_cnt = 0; + arg->data.wr_err = 0; + while (!arg->stop) { + uint32_t *ts = (uint32_t *)(arg->data.buf + sizeof(uint32_t)); + *ts = (uint32_t)esp_apptrace_test_ts_get(); + memset(arg->data.buf + 2 * sizeof(uint32_t), arg->data.wr_cnt & arg->data.mask, arg->data.buf_sz - 2 * sizeof(uint32_t)); + if (arg->nowait) { + res = ESP_APPTRACE_TEST_WRITE_NOWAIT(arg->data.buf, arg->data.buf_sz); + } else { + res = ESP_APPTRACE_TEST_WRITE(arg->data.buf, arg->data.buf_sz); + } + if (res) { + if (arg->data.wr_err++ < ESP_APPTRACE_TEST_PRN_WRERR_MAX) { + ESP_APPTRACE_TEST_LOGE("%x: Failed to write trace %d %x!", xTaskGetCurrentTaskHandle(), res, arg->data.wr_cnt & arg->data.mask); + if (arg->data.wr_err == ESP_APPTRACE_TEST_PRN_WRERR_MAX) { + ESP_APPTRACE_TEST_LOGE("\n"); + } + } + } else { + if (0) { + ESP_APPTRACE_TEST_LOGD("%x:%x: Written chunk%d %d bytes, %x", xTaskGetCurrentTaskHandle(), *ts, arg->data.wr_cnt, arg->data.buf_sz, arg->data.wr_cnt & arg->data.mask); + } + arg->data.wr_err = 0; + } + arg->data.wr_cnt++; + if (tmo_ticks) { + vTaskDelay(tmo_ticks); + } + } + +on_fail: + if (inth) { + for (int i = 0; i < arg->timers_num; i++) { + timer_pause(arg->timers[i].group, arg->timers[i].id); + timer_disable_intr(arg->timers[i].group, arg->timers[i].id); + if (inth[i]) { + esp_intr_free(inth[i]); + } + } + vPortFree(inth); + } + xSemaphoreGive(arg->done); + vTaskDelay(1); + vTaskDelete(NULL); +} + +static void esp_apptrace_test_task_crash(void *p) +{ + esp_apptrace_test_task_arg_t *arg = (esp_apptrace_test_task_arg_t *) p; + int res, i; + + ESP_APPTRACE_TEST_LOGE("%x: run (period %u us, stamp mask %x, %u timers)", xTaskGetCurrentTaskHandle(), arg->data.period, arg->data.mask, arg->timers_num); + + arg->data.wr_cnt = 0; + *(uint32_t *)arg->data.buf = (uint32_t)xTaskGetCurrentTaskHandle(); + for (i = 0; i < ESP_APPTRACE_TEST_BLOCKS_BEFORE_CRASH; i++) { + uint32_t *ts = (uint32_t *)(arg->data.buf + sizeof(uint32_t)); + *ts = (uint32_t)esp_apptrace_test_ts_get(); + memset(arg->data.buf + sizeof(uint32_t), arg->data.wr_cnt & arg->data.mask, arg->data.buf_sz - sizeof(uint32_t)); + res = ESP_APPTRACE_TEST_WRITE(arg->data.buf, arg->data.buf_sz); + if (res) { + ESP_APPTRACE_TEST_LOGE("%x: Failed to write trace %d %x!", xTaskGetCurrentTaskHandle(), res, arg->data.wr_cnt & arg->data.mask); + } else { + ESP_APPTRACE_TEST_LOGD("%x: Written chunk%d %d bytes, %x", xTaskGetCurrentTaskHandle(), arg->data.wr_cnt, arg->data.buf_sz, arg->data.wr_cnt & arg->data.mask); + } + arg->data.wr_cnt++; + } + vTaskDelay(500); + uint32_t *ptr = 0; + *ptr = 1000; + + xSemaphoreGive(arg->done); + vTaskDelay(1); + vTaskDelete(NULL); +} + +static int s_ts_timer_group, s_ts_timer_idx; + +static uint64_t esp_apptrace_test_ts_get() +{ + uint64_t ts = 0; + timer_get_counter_value(s_ts_timer_group, s_ts_timer_idx, &ts); + return ts; +} + +static void esp_apptrace_test_ts_init(int timer_group, int timer_idx) +{ + timer_config_t config; + //uint64_t alarm_val = period * (TIMER_BASE_CLK / 1000000UL); + + ESP_APPTRACE_TEST_LOGI("Use timer%d.%d for TS", timer_group, timer_idx); + + s_ts_timer_group = timer_group; + s_ts_timer_idx = timer_idx; + + config.alarm_en = 0; + config.auto_reload = 0; + config.counter_dir = TIMER_COUNT_UP; + config.divider = 1; + config.counter_en = 0; + /*Configure timer*/ + timer_init(timer_group, timer_idx, &config); + /*Load counter value */ + timer_set_counter_value(timer_group, timer_idx, 0x00000000ULL); + /*Enable timer interrupt*/ + timer_start(timer_group, timer_idx); +} + +static void esp_apptrace_test_ts_cleanup() +{ + timer_config_t config; + + config.alarm_en = 0; + config.auto_reload = 0; + config.counter_dir = TIMER_COUNT_UP; + config.divider = 1; + config.counter_en = 0; + /*Configure timer*/ + timer_init(s_ts_timer_group, s_ts_timer_idx, &config); +} + +static void esp_apptrace_test(esp_apptrace_test_cfg_t *test_cfg) +{ + int i, k; + int tims_in_use[TIMER_GROUP_MAX][TIMER_MAX] = {{0, 0}, {0, 0}}; + esp_apptrace_test_task_arg_t dummy_task_arg[1]; + + memset(dummy_task_arg, 0, sizeof(dummy_task_arg)); + dummy_task_arg[0].core = 0; + dummy_task_arg[0].prio = 3; + dummy_task_arg[0].task_func = esp_apptrace_test_task_crash; + dummy_task_arg[0].data.buf = NULL; + dummy_task_arg[0].data.buf_sz = 0; + dummy_task_arg[0].data.period = 500000; + dummy_task_arg[0].timers_num = 0; + dummy_task_arg[0].timers = NULL; +#if ESP_APPTRACE_TEST_USE_PRINT_LOCK == 1 + s_print_lock = xSemaphoreCreateBinary(); + if (!s_print_lock) { + ets_printf("%s: Failed to create print lock!", TAG); + return; + } + xSemaphoreGive(s_print_lock); +#else +#endif + + for (i = 0; i < test_cfg->tasks_num; i++) { + test_cfg->tasks[i].data.mask = 0xFF; + test_cfg->tasks[i].stop = 0; + test_cfg->tasks[i].done = xSemaphoreCreateBinary(); + if (!test_cfg->tasks[i].done) { + ESP_APPTRACE_TEST_LOGE("Failed to create task completion semaphore!"); + goto on_fail; + } + for (k = 0; k < test_cfg->tasks[i].timers_num; k++) { + test_cfg->tasks[i].timers[k].data.mask = 0xFF; + tims_in_use[test_cfg->tasks[i].timers[k].group][test_cfg->tasks[i].timers[k].id] = 1; + } + } + + int found = 0; + for (i = 0; i < TIMER_GROUP_MAX; i++) { + for (k = 0; k < TIMER_MAX; k++) { + if (!tims_in_use[i][k]) { + ESP_APPTRACE_TEST_LOGD("Found timer%d.%d", i, k); + found = 1; + break; + } + } + if (found) { + break; + } + } + if (!found) { + ESP_APPTRACE_TEST_LOGE("No free timer for TS!"); + goto on_fail; + } + esp_apptrace_test_ts_init(i, k); + + for (int i = 0; i < test_cfg->tasks_num; i++) { + char name[30]; + TaskHandle_t thnd; + sprintf(name, "apptrace_test%d", i); + xTaskCreatePinnedToCore(test_cfg->tasks[i].task_func, name, 2048, &test_cfg->tasks[i], test_cfg->tasks[i].prio, &thnd, test_cfg->tasks[i].core); + ESP_APPTRACE_TEST_LOGI("Created task %x", thnd); + } + xTaskCreatePinnedToCore(esp_apptrace_dummy_task, "dummy0", 2048, &dummy_task_arg[0], dummy_task_arg[0].prio, NULL, 0); + xTaskCreatePinnedToCore(esp_apptrace_dummy_task, "dummy1", 2048, &dummy_task_arg[0], dummy_task_arg[0].prio, NULL, 1); + + for (int i = 0; i < test_cfg->tasks_num; i++) { + //arg1.stop = 1; + xSemaphoreTake(test_cfg->tasks[i].done, portMAX_DELAY); + } + +on_fail: + for (int i = 0; i < test_cfg->tasks_num; i++) { + if (test_cfg->tasks[i].done) { + vSemaphoreDelete(test_cfg->tasks[i].done); + } + } + esp_apptrace_test_ts_cleanup(); + +#if ESP_APPTRACE_TEST_USE_PRINT_LOCK == 1 + vSemaphoreDelete(s_print_lock); +#else +#endif +} + +static esp_apptrace_test_task_arg_t s_test_tasks[4]; +static esp_apptrace_test_timer_arg_t s_test_timers[2]; +static uint8_t s_bufs[6][ESP_APPTRACE_TEST_BLOCK_SIZE]; + +TEST_CASE("App trace test (1 task + 1 crashed timer ISR @ 1 core)", "[trace][ignore]") +{ + esp_apptrace_test_cfg_t test_cfg = { + .tasks_num = 1, + .tasks = s_test_tasks, + }; + + memset(s_test_timers, 0, sizeof(s_test_timers)); + memset(s_test_tasks, 0, sizeof(s_test_tasks)); + + s_test_timers[0].group = TIMER_GROUP_0; + s_test_timers[0].id = TIMER_0; + s_test_timers[0].isr_func = esp_apptrace_test_timer_isr_crash; + s_test_timers[0].data.buf = s_bufs[0]; + s_test_timers[0].data.buf_sz = sizeof(s_bufs[0]); + s_test_timers[0].data.period = 1000; + + s_test_tasks[0].core = 0; + s_test_tasks[0].prio = 3; + s_test_tasks[0].task_func = esp_apptrace_dummy_task; + s_test_tasks[0].data.buf = NULL; + s_test_tasks[0].data.buf_sz = 0; + s_test_tasks[0].data.period = 1000000; + s_test_tasks[0].timers_num = 1; + s_test_tasks[0].timers = s_test_timers; + + esp_apptrace_test(&test_cfg); +} + + +TEST_CASE("App trace test (1 crashed task)", "[trace][ignore]") +{ + esp_apptrace_test_task_arg_t s_test_tasks[1]; + esp_apptrace_test_cfg_t test_cfg = { + .tasks_num = 1, + .tasks = s_test_tasks, + }; + + memset(s_test_tasks, 0, sizeof(s_test_tasks)); + + s_test_tasks[0].core = 0; + s_test_tasks[0].prio = 3; + s_test_tasks[0].task_func = esp_apptrace_test_task_crash; + s_test_tasks[0].data.buf = s_bufs[0]; + s_test_tasks[0].data.buf_sz = sizeof(s_bufs[0]); + s_test_tasks[0].data.period = 6000; + s_test_tasks[0].timers_num = 0; + s_test_tasks[0].timers = NULL; + + esp_apptrace_test(&test_cfg); +} + +TEST_CASE("App trace test (2 tasks + 1 timer @ each core", "[trace][ignore]") +{ + int ntask = 0; + esp_apptrace_test_cfg_t test_cfg = { + .tasks_num = 4, + .tasks = s_test_tasks, + }; + + memset(s_test_tasks, 0, sizeof(s_test_tasks)); + memset(s_test_timers, 0, sizeof(s_test_timers)); + + s_test_timers[0].group = TIMER_GROUP_0; + s_test_timers[0].id = TIMER_0; + s_test_timers[0].isr_func = esp_apptrace_test_timer_isr; + s_test_timers[0].data.buf = s_bufs[0]; + s_test_timers[0].data.buf_sz = sizeof(s_bufs[0]); + s_test_timers[0].data.period = 150; + + s_test_timers[1].group = TIMER_GROUP_1; + s_test_timers[1].id = TIMER_0; + s_test_timers[1].isr_func = esp_apptrace_test_timer_isr; + s_test_timers[1].data.buf = s_bufs[1]; + s_test_timers[1].data.buf_sz = sizeof(s_bufs[1]); + s_test_timers[1].data.period = 150; + + s_test_tasks[ntask].core = 0; + s_test_tasks[ntask].prio = 4; + s_test_tasks[ntask].task_func = esp_apptrace_test_task; + s_test_tasks[ntask].data.buf = s_bufs[2]; + s_test_tasks[ntask].data.buf_sz = sizeof(s_bufs[2]); + s_test_tasks[ntask].data.period = 1000; + s_test_tasks[ntask].timers_num = 1; + s_test_tasks[ntask].timers = &s_test_timers[0]; + ntask++; + s_test_tasks[ntask].core = 0; + s_test_tasks[ntask].prio = 3; + s_test_tasks[ntask].task_func = esp_apptrace_test_task; + s_test_tasks[ntask].data.buf = s_bufs[3]; + s_test_tasks[ntask].data.buf_sz = sizeof(s_bufs[3]); + s_test_tasks[ntask].data.period = 0; + s_test_tasks[ntask].timers_num = 0; + s_test_tasks[ntask].timers = NULL; + ntask++; + s_test_tasks[ntask].core = 1; + s_test_tasks[ntask].prio = 4; + s_test_tasks[ntask].task_func = esp_apptrace_test_task; + s_test_tasks[ntask].data.buf = s_bufs[4]; + s_test_tasks[ntask].data.buf_sz = sizeof(s_bufs[4]); + s_test_tasks[ntask].data.period = 1000; + s_test_tasks[ntask].timers_num = 1; + s_test_tasks[ntask].timers = &s_test_timers[1]; + ntask++; + s_test_tasks[ntask].core = 1; + s_test_tasks[ntask].prio = 3; + s_test_tasks[ntask].task_func = esp_apptrace_test_task; + s_test_tasks[ntask].data.buf = s_bufs[5]; + s_test_tasks[ntask].data.buf_sz = sizeof(s_bufs[5]); + s_test_tasks[ntask].data.period = 0; + s_test_tasks[ntask].timers_num = 0; + s_test_tasks[ntask].timers = NULL; + ntask++; + + esp_apptrace_test(&test_cfg); +} + +TEST_CASE("App trace test (1 task + 1 timer @ 1 core)", "[trace][ignore]") +{ + esp_apptrace_test_cfg_t test_cfg = { + .tasks_num = 1, + .tasks = s_test_tasks, + }; + + memset(s_test_timers, 0, sizeof(s_test_timers)); + memset(s_test_tasks, 0, sizeof(s_test_tasks)); + + s_test_timers[0].group = TIMER_GROUP_0; + s_test_timers[0].id = TIMER_0; + s_test_timers[0].isr_func = esp_apptrace_test_timer_isr; + s_test_timers[0].data.buf = s_bufs[0]; + s_test_timers[0].data.buf_sz = sizeof(s_bufs[0]); + s_test_timers[0].data.period = 150; + + s_test_tasks[0].core = 0; + s_test_tasks[0].prio = 3; + s_test_tasks[0].task_func = esp_apptrace_test_task; + s_test_tasks[0].data.buf = s_bufs[1]; + s_test_tasks[0].data.buf_sz = sizeof(s_bufs[1]); + s_test_tasks[0].data.period = 0; + s_test_tasks[0].timers_num = 1; + s_test_tasks[0].timers = s_test_timers; + + esp_apptrace_test(&test_cfg); +} + +TEST_CASE("App trace test (2 tasks (nowait): 1 @ each core)", "[trace][ignore]") +{ + esp_apptrace_test_cfg_t test_cfg = { + .tasks_num = 2, + .tasks = s_test_tasks, + }; + + memset(s_test_tasks, 0, sizeof(s_test_tasks)); + + s_test_tasks[0].nowait = 1; + s_test_tasks[0].core = 0; + s_test_tasks[0].prio = 3; + s_test_tasks[0].task_func = esp_apptrace_test_task; + s_test_tasks[0].data.buf = s_bufs[0]; + s_test_tasks[0].data.buf_sz = sizeof(s_bufs[0]); + s_test_tasks[0].data.period = 6700; + s_test_tasks[0].timers_num = 0; + s_test_tasks[0].timers = NULL; + + s_test_tasks[1].nowait = 1; + s_test_tasks[1].core = 1; + s_test_tasks[1].prio = 3; + s_test_tasks[1].task_func = esp_apptrace_test_task; + s_test_tasks[1].data.buf = s_bufs[1]; + s_test_tasks[1].data.buf_sz = sizeof(s_bufs[1]); + s_test_tasks[1].data.period = 6700; + s_test_tasks[1].timers_num = 0; + s_test_tasks[1].timers = NULL; + + esp_apptrace_test(&test_cfg); +} + +TEST_CASE("App trace test (2 tasks: 1 @ each core)", "[trace][ignore]") +{ + esp_apptrace_test_cfg_t test_cfg = { + .tasks_num = 2, + .tasks = s_test_tasks, + }; + + memset(s_test_tasks, 0, sizeof(s_test_tasks)); + + s_test_tasks[0].core = 0; + s_test_tasks[0].prio = 3; + s_test_tasks[0].task_func = esp_apptrace_test_task; + s_test_tasks[0].data.buf = s_bufs[0]; + s_test_tasks[0].data.buf_sz = sizeof(s_bufs[0]); + s_test_tasks[0].data.period = 0; + s_test_tasks[0].timers_num = 0; + s_test_tasks[0].timers = NULL; + + s_test_tasks[1].core = 1; + s_test_tasks[1].prio = 3; + s_test_tasks[1].task_func = esp_apptrace_test_task; + s_test_tasks[1].data.buf = s_bufs[1]; + s_test_tasks[1].data.buf_sz = sizeof(s_bufs[1]); + s_test_tasks[1].data.period = 0; + s_test_tasks[1].timers_num = 0; + s_test_tasks[1].timers = NULL; + + esp_apptrace_test(&test_cfg); +} + +TEST_CASE("App trace test (1 task)", "[trace][ignore]") +{ + esp_apptrace_test_cfg_t test_cfg = { + .tasks_num = 1, + .tasks = s_test_tasks, + }; + + memset(s_test_tasks, 0, sizeof(s_test_tasks)); + + s_test_tasks[0].core = 1; + s_test_tasks[0].prio = 3; + s_test_tasks[0].task_func = esp_apptrace_test_task; + s_test_tasks[0].data.buf = s_bufs[0]; + s_test_tasks[0].data.buf_sz = sizeof(s_bufs[0]); + s_test_tasks[0].data.period = 0; + s_test_tasks[0].timers_num = 0; + s_test_tasks[0].timers = NULL; + + esp_apptrace_test(&test_cfg); +} + +static int esp_logtrace_printf(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + + int ret = esp_apptrace_vprintf_to(ESP_APPTRACE_DEST_TRAX, ESP_APPTRACE_TMO_INFINITE, fmt, ap); + + va_end(ap); + + return ret; +} + +typedef struct { + SemaphoreHandle_t done; +} esp_logtrace_task_t; + +static void esp_logtrace_task(void *p) +{ + esp_logtrace_task_t *arg = (esp_logtrace_task_t *) p; + + ESP_APPTRACE_TEST_LOGI("%x: run log test task", xTaskGetCurrentTaskHandle()); + + int i = 0; + while (1) { + esp_logtrace_printf("sample print %lx %hx %c\n", 2 * i + 0x10, 2 * i + 0x20, (2 * i + 0x30) & 0xFF); + esp_logtrace_printf("sample print %lx %hx %c %lu %hu %d %d %d %d\n", i, i + 0x10, (i + 0x20) & 0xFF, i + 0x30, i + 0x40, i + 0x50, i + 0x60, i + 0x70, i + 0x80); + ESP_LOGI(TAG, "%p: sample print 1", xTaskGetCurrentTaskHandle()); + ESP_LOGI(TAG, "%p: sample print 2 %u", xTaskGetCurrentTaskHandle(), (unsigned)i); + ESP_LOGI(TAG, "%p: sample print 4 %c", xTaskGetCurrentTaskHandle(), ((i & 0xFF) % 95) + 32); + ESP_LOGI(TAG, "%p: sample print 5 %f", xTaskGetCurrentTaskHandle(), 1.0); + ESP_LOGI(TAG, "%p: sample print 6 %f", xTaskGetCurrentTaskHandle(), 3.45); + ESP_LOGI(TAG, "%p: logtrace task work %d.%d", xTaskGetCurrentTaskHandle(), xPortGetCoreID(), i); + if (++i == 10000) { + break; + } + } + esp_err_t ret = esp_apptrace_flush(ESP_APPTRACE_DEST_TRAX, ESP_APPTRACE_TMO_INFINITE); + if (ret != ESP_OK) { + ESP_APPTRACE_TEST_LOGE("Failed to flush printf buf (%d)!", ret); + } + + ESP_APPTRACE_TEST_LOGI("%x: finished", xTaskGetCurrentTaskHandle()); + + xSemaphoreGive(arg->done); + vTaskDelay(1); + vTaskDelete(NULL); +} + +TEST_CASE("Log trace test (1 task)", "[trace][ignore]") +{ + TaskHandle_t thnd; + + esp_logtrace_task_t arg1 = { + .done = xSemaphoreCreateBinary(), + }; + esp_logtrace_task_t arg2 = { + .done = xSemaphoreCreateBinary(), + }; + + xTaskCreatePinnedToCore(esp_logtrace_task, "logtrace0", 2048, &arg1, 3, &thnd, 0); + ESP_APPTRACE_TEST_LOGI("Created task %x", thnd); + xTaskCreatePinnedToCore(esp_logtrace_task, "logtrace1", 2048, &arg2, 3, &thnd, 1); + ESP_APPTRACE_TEST_LOGI("Created task %x", thnd); + + xSemaphoreTake(arg1.done, portMAX_DELAY); + vSemaphoreDelete(arg1.done); + xSemaphoreTake(arg2.done, portMAX_DELAY); + vSemaphoreDelete(arg2.done); +} +#endif diff --git a/components/esptool_py/esptool b/components/esptool_py/esptool index 907273664..96698a3da 160000 --- a/components/esptool_py/esptool +++ b/components/esptool_py/esptool @@ -1 +1 @@ -Subproject commit 907273664ada32fc33f3fbfeba99550512c67e4d +Subproject commit 96698a3da9acc6e357741663830f97524b688ade diff --git a/components/ethernet/component.mk b/components/ethernet/component.mk index c2c4c03a1..0856e27d6 100755 --- a/components/ethernet/component.mk +++ b/components/ethernet/component.mk @@ -1,5 +1,5 @@ # # Component Makefile # -# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) +COMPONENT_SRCDIRS := . eth_phy diff --git a/components/ethernet/emac_main.c b/components/ethernet/emac_main.c index 672ab75df..7e299be94 100644 --- a/components/ethernet/emac_main.c +++ b/components/ethernet/emac_main.c @@ -204,6 +204,25 @@ uint16_t esp_eth_smi_read(uint32_t reg_num) return value; } +esp_err_t esp_eth_smi_wait_value(uint32_t reg_num, uint16_t value, uint16_t value_mask, int timeout_ms) +{ + unsigned start = xTaskGetTickCount(); + unsigned timeout_ticks = (timeout_ms + portTICK_PERIOD_MS - 1) / portTICK_PERIOD_MS; + uint16_t current_value = 0; + + while (timeout_ticks == 0 || (xTaskGetTickCount() - start < timeout_ticks)) { + current_value = esp_eth_smi_read(reg_num); + if ((current_value & value_mask) == (value & value_mask)) { + return ESP_OK; + } + vTaskDelay(1); + } + ESP_LOGE(TAG, "Timed out waiting for PHY register 0x%x to have value 0x%04x (mask 0x%04x). Current value 0x%04x", + reg_num, value, value_mask, current_value); + return ESP_ERR_TIMEOUT; +} + + static void emac_set_user_config_data(eth_config_t *config ) { emac_config.phy_addr = config->phy_addr; @@ -532,7 +551,7 @@ static void emac_set_macaddr_reg(void) static void emac_check_phy_init(void) { emac_config.emac_phy_check_init(); - if (emac_config.emac_phy_get_duplex_mode() == ETH_MDOE_FULLDUPLEX) { + if (emac_config.emac_phy_get_duplex_mode() == ETH_MODE_FULLDUPLEX) { REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_GMACDUPLEX); } else { REG_CLR_BIT(EMAC_GMACCONFIG_REG, EMAC_GMACDUPLEX); @@ -547,7 +566,7 @@ static void emac_check_phy_init(void) emac_config.emac_flow_ctrl_partner_support = false; #else if (emac_config.emac_flow_ctrl_enable == true) { - if (emac_config.emac_phy_get_partner_pause_enable() == true && emac_config.emac_phy_get_duplex_mode() == ETH_MDOE_FULLDUPLEX) { + if (emac_config.emac_phy_get_partner_pause_enable() == true && emac_config.emac_phy_get_duplex_mode() == ETH_MODE_FULLDUPLEX) { emac_enable_flowctrl(); emac_config.emac_flow_ctrl_partner_support = true; } else { @@ -954,7 +973,7 @@ esp_err_t esp_eth_init(eth_config_t *config) goto _exit; } - emac_config.emac_phy_power_enable(true); + emac_config.emac_phy_power_enable(true); //before set emac reg must enable clk emac_enable_clk(true); diff --git a/components/ethernet/eth_phy/phy_common.c b/components/ethernet/eth_phy/phy_common.c new file mode 100644 index 000000000..a72a6daf8 --- /dev/null +++ b/components/ethernet/eth_phy/phy_common.c @@ -0,0 +1,75 @@ +// Copyright 2015-2016 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. + +#include "eth_phy/phy.h" +#include "eth_phy/phy_reg.h" +#include "driver/gpio.h" +#include "esp_log.h" + +static const char *TAG = "phy_common"; + +void phy_rmii_configure_data_interface_pins(void) +{ + // CRS_DRV to GPIO27 + PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO27_U, FUNC_GPIO27_EMAC_RX_DV); + + // TXD0 to GPIO19 + PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO19_U, FUNC_GPIO19_EMAC_TXD0); + // TX_EN to GPIO21 + PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO21_U, FUNC_GPIO21_EMAC_TX_EN); + // TXD1 to GPIO22 + PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO22_U, FUNC_GPIO22_EMAC_TXD1); + // RXD0 to GPIO25 + gpio_set_direction(25, GPIO_MODE_INPUT); + // RXD1 to GPIO26 + gpio_set_direction(26, GPIO_MODE_INPUT); + // RMII CLK to GPIO0 + gpio_set_direction(0, GPIO_MODE_INPUT); +} + +void phy_rmii_smi_configure_pins(uint8_t mdc_gpio, uint8_t mdio_gpio) +{ + gpio_matrix_out(mdc_gpio, EMAC_MDC_O_IDX, 0, 0); + gpio_matrix_out(mdio_gpio, EMAC_MDO_O_IDX, 0, 0); + gpio_matrix_in(mdio_gpio, EMAC_MDI_I_IDX, 0); +} + +void phy_mii_enable_flow_ctrl(void) +{ + uint32_t data = esp_eth_smi_read(MII_AUTO_NEG_ADVERTISEMENT_REG); + data |= MII_ASM_DIR | MII_PAUSE; + esp_eth_smi_write(MII_AUTO_NEG_ADVERTISEMENT_REG, data); +} + +bool phy_mii_check_link_status(void) +{ + if ((esp_eth_smi_read(MII_BASIC_MODE_STATUS_REG) & MII_LINK_STATUS)) { + ESP_LOGD(TAG, "phy_mii_check_link_status(UP)"); + return true; + } else { + ESP_LOGD(TAG, "phy_mii_check_link_status(DOWN)"); + return false; + } +} + +bool phy_mii_get_partner_pause_enable(void) +{ + if((esp_eth_smi_read(MII_PHY_LINK_PARTNER_ABILITY_REG) & MII_PARTNER_PAUSE)) { + ESP_LOGD(TAG, "phy_mii_get_partner_pause_enable(TRUE)"); + return true; + } else { + ESP_LOGD(TAG, "phy_mii_get_partner_pause_enable(FALSE)"); + return false; + } +} diff --git a/components/ethernet/eth_phy/phy_lan8720.c b/components/ethernet/eth_phy/phy_lan8720.c new file mode 100644 index 000000000..b0f793b33 --- /dev/null +++ b/components/ethernet/eth_phy/phy_lan8720.c @@ -0,0 +1,149 @@ +// Copyright 2015-2017 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. +#include "esp_attr.h" +#include "esp_log.h" +#include "esp_eth.h" + +#include "eth_phy/phy_lan8720.h" +#include "eth_phy/phy_reg.h" + +/* Value of MII_PHY_IDENTIFIER_REGs for Microchip LAN8720 + * (Except for bottom 4 bits of ID2, used for model revision) + */ +#define LAN8720_PHY_ID1 0x0007 +#define LAN8720_PHY_ID2 0xc0f0 +#define LAN8720_PHY_ID2_MASK 0xFFF0 + +/* LAN8720-specific registers */ +#define SW_STRAP_CONTROL_REG (0x9) +#define SW_STRAP_CONFIG_DONE BIT(15) +#define AUTO_MDIX_ENABLE BIT(14) +#define AUTO_NEGOTIATION_ENABLE BIT(13) +#define AN_1 BIT(12) +#define AN_0 BIT(11) +#define LED_CFG BIT(10) +#define RMII_ENHANCED_MODE BIT(9) + +#define DEFAULT_STRAP_CONFIG (AUTO_MDIX_ENABLE|AUTO_NEGOTIATION_ENABLE|AN_1|AN_0|LED_CFG) + +#define PHY_SPECIAL_CONTROL_STATUS_REG (0x1f) +#define AUTO_NEGOTIATION_DONE BIT(12) +#define SPEED_DUPLEX_INDICATION_10T_HALF 0x04 +#define SPEED_DUPLEX_INDICATION_10T_FULL 0x14 +#define SPEED_DUPLEX_INDICATION_100T_HALF 0x08 +#define SPEED_DUPLEX_INDICATION_100T_FULL 0x18 +#define SPEED_INDICATION_100T BIT(3) +#define SPEED_INDICATION_10T BIT(2) +#define DUPLEX_INDICATION_FULL BIT(4) + +static const char *TAG = "lan8720"; + +void phy_lan8720_check_phy_init(void) +{ + phy_lan8720_dump_registers(); + + esp_eth_smi_wait_set(MII_BASIC_MODE_STATUS_REG, MII_AUTO_NEGOTIATION_COMPLETE, 0); + esp_eth_smi_wait_set(PHY_SPECIAL_CONTROL_STATUS_REG, AUTO_NEGOTIATION_DONE, 0); +} + +eth_speed_mode_t phy_lan8720_get_speed_mode(void) +{ + if(esp_eth_smi_read(PHY_SPECIAL_CONTROL_STATUS_REG) & SPEED_INDICATION_100T) { + ESP_LOGD(TAG, "phy_lan8720_get_speed_mode(100)"); + return ETH_SPEED_MODE_100M; + } else { + ESP_LOGD(TAG, "phy_lan8720_get_speed_mode(10)"); + return ETH_SPEED_MODE_10M; + } +} + +eth_duplex_mode_t phy_lan8720_get_duplex_mode(void) +{ + if(esp_eth_smi_read(PHY_SPECIAL_CONTROL_STATUS_REG) & DUPLEX_INDICATION_FULL) { + ESP_LOGD(TAG, "phy_lan8720_get_duplex_mode(FULL)"); + return ETH_MODE_FULLDUPLEX; + } else { + ESP_LOGD(TAG, "phy_lan8720_get_duplex_mode(HALF)"); + return ETH_MODE_HALFDUPLEX; + } +} + +void phy_lan8720_power_enable(bool enable) +{ + if (enable) { + esp_eth_smi_write(SW_STRAP_CONTROL_REG, DEFAULT_STRAP_CONFIG | SW_STRAP_CONFIG_DONE); + // TODO: only enable if config.flow_ctrl_enable == true + phy_mii_enable_flow_ctrl(); + } +} + +void phy_lan8720_init(void) +{ + ESP_LOGD(TAG, "phy_lan8720_init()"); + phy_lan8720_dump_registers(); + + esp_eth_smi_write(MII_BASIC_MODE_CONTROL_REG, MII_SOFTWARE_RESET); + + esp_err_t res1, res2; + do { + // Call esp_eth_smi_wait_value() with a timeout so it prints an error periodically + res1 = esp_eth_smi_wait_value(MII_PHY_IDENTIFIER_1_REG, LAN8720_PHY_ID1, UINT16_MAX, 1000); + res2 = esp_eth_smi_wait_value(MII_PHY_IDENTIFIER_2_REG, LAN8720_PHY_ID2, LAN8720_PHY_ID2_MASK, 1000); + } while(res1 != ESP_OK || res2 != ESP_OK); + + esp_eth_smi_write(SW_STRAP_CONTROL_REG, + DEFAULT_STRAP_CONFIG | SW_STRAP_CONFIG_DONE); + + + ets_delay_us(300); + + // TODO: only enable if config.flow_ctrl_enable == true + phy_mii_enable_flow_ctrl(); +} + +const eth_config_t phy_lan8720_default_ethernet_config = { + // By default, the PHY address is 0 or 1 based on PHYAD0 + // pin. Can also be overriden in software. See datasheet + // for defaults. + .phy_addr = 0, + .mac_mode = ETH_MODE_RMII, + //Only FULLDUPLEX mode support flow ctrl now! + .flow_ctrl_enable = true, + .phy_init = phy_lan8720_init, + .phy_check_init = phy_lan8720_check_phy_init, + .phy_power_enable = phy_lan8720_power_enable, + .phy_check_link = phy_mii_check_link_status, + .phy_get_speed_mode = phy_lan8720_get_speed_mode, + .phy_get_duplex_mode = phy_lan8720_get_duplex_mode, + .phy_get_partner_pause_enable = phy_mii_get_partner_pause_enable, +}; + +void phy_lan8720_dump_registers() +{ + ESP_LOGD(TAG, "LAN8720 Registers:"); + ESP_LOGD(TAG, "BCR 0x%04x", esp_eth_smi_read(0x0)); + ESP_LOGD(TAG, "BSR 0x%04x", esp_eth_smi_read(0x1)); + ESP_LOGD(TAG, "PHY1 0x%04x", esp_eth_smi_read(0x2)); + ESP_LOGD(TAG, "PHY2 0x%04x", esp_eth_smi_read(0x3)); + ESP_LOGD(TAG, "ANAR 0x%04x", esp_eth_smi_read(0x4)); + ESP_LOGD(TAG, "ANLPAR 0x%04x", esp_eth_smi_read(0x5)); + ESP_LOGD(TAG, "ANER 0x%04x", esp_eth_smi_read(0x6)); + ESP_LOGD(TAG, "MCSR 0x%04x", esp_eth_smi_read(0x17)); + ESP_LOGD(TAG, "SM 0x%04x", esp_eth_smi_read(0x18)); + ESP_LOGD(TAG, "SECR 0x%04x", esp_eth_smi_read(0x26)); + ESP_LOGD(TAG, "CSIR 0x%04x", esp_eth_smi_read(0x27)); + ESP_LOGD(TAG, "ISR 0x%04x", esp_eth_smi_read(0x29)); + ESP_LOGD(TAG, "IMR 0x%04x", esp_eth_smi_read(0x30)); + ESP_LOGD(TAG, "PSCSR 0x%04x", esp_eth_smi_read(0x31)); +} diff --git a/components/ethernet/eth_phy/phy_tlk110.c b/components/ethernet/eth_phy/phy_tlk110.c new file mode 100644 index 000000000..020329a26 --- /dev/null +++ b/components/ethernet/eth_phy/phy_tlk110.c @@ -0,0 +1,173 @@ +// Copyright 2015-2017 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. +#include "esp_attr.h" +#include "esp_log.h" +#include "esp_eth.h" + +#include "eth_phy/phy_tlk110.h" +#include "eth_phy/phy_reg.h" + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +/* Value of MII_PHY_IDENTIFIER_REG for TI TLK110, + Excluding bottom 4 bytes of ID2, used for model revision + */ +#define TLK110_PHY_ID1 0x2000 +#define TLK110_PHY_ID2 0xa210 +#define TLK110_PHY_ID2_MASK 0xFFF0 + +/* TLK110-specific registers */ +#define SW_STRAP_CONTROL_REG (0x9) +#define SW_STRAP_CONFIG_DONE BIT(15) +#define AUTO_MDIX_ENABLE BIT(14) +#define AUTO_NEGOTIATION_ENABLE BIT(13) +#define AN_1 BIT(12) +#define AN_0 BIT(11) +#define LED_CFG BIT(10) +#define RMII_ENHANCED_MODE BIT(9) + +#define DEFAULT_STRAP_CONFIG (AUTO_MDIX_ENABLE|AUTO_NEGOTIATION_ENABLE|AN_1|AN_0|LED_CFG) + +#define PHY_STATUS_REG (0x10) +#define AUTO_NEGOTIATION_STATUS BIT(4) +#define DUPLEX_STATUS BIT(2) +#define SPEED_STATUS BIT(1) + +#define CABLE_DIAGNOSTIC_CONTROL_REG (0x1e) +#define DIAGNOSTIC_DONE BIT(1) + +#define PHY_RESET_CONTROL_REG (0x1f) +#define SOFTWARE_RESET BIT(15) + +static const char *TAG = "tlk110"; + +void phy_tlk110_check_phy_init(void) +{ + phy_tlk110_dump_registers(); + + esp_eth_smi_wait_set(MII_BASIC_MODE_STATUS_REG, MII_AUTO_NEGOTIATION_COMPLETE, 0); + esp_eth_smi_wait_set(PHY_STATUS_REG, AUTO_NEGOTIATION_STATUS, 0); + esp_eth_smi_wait_set(CABLE_DIAGNOSTIC_CONTROL_REG, DIAGNOSTIC_DONE, 0); +} + +eth_speed_mode_t phy_tlk110_get_speed_mode(void) +{ + if((esp_eth_smi_read(PHY_STATUS_REG) & SPEED_STATUS ) != SPEED_STATUS) { + ESP_LOGD(TAG, "phy_tlk110_get_speed_mode(100)"); + return ETH_SPEED_MODE_100M; + } else { + ESP_LOGD(TAG, "phy_tlk110_get_speed_mode(10)"); + return ETH_SPEED_MODE_10M; + } +} + +eth_duplex_mode_t phy_tlk110_get_duplex_mode(void) +{ + if((esp_eth_smi_read(PHY_STATUS_REG) & DUPLEX_STATUS ) == DUPLEX_STATUS) { + ESP_LOGD(TAG, "phy_tlk110_get_duplex_mode(FULL)"); + return ETH_MODE_FULLDUPLEX; + } else { + ESP_LOGD(TAG, "phy_tlk110_get_duplex_mode(HALF)"); + return ETH_MODE_HALFDUPLEX; + } +} + +void phy_tlk110_power_enable(bool enable) +{ + if (enable) { + esp_eth_smi_write(SW_STRAP_CONTROL_REG, DEFAULT_STRAP_CONFIG | SW_STRAP_CONFIG_DONE); + + // TODO: only do this if config.flow_ctrl_enable == true + phy_mii_enable_flow_ctrl(); + } +} + +void phy_tlk110_init(void) +{ + ESP_LOGD(TAG, "phy_tlk110_init()"); + phy_tlk110_dump_registers(); + + esp_eth_smi_write(PHY_RESET_CONTROL_REG, SOFTWARE_RESET); + + esp_err_t res1, res2; + do { + // Call esp_eth_smi_wait_value() with a timeout so it prints an error periodically + res1 = esp_eth_smi_wait_value(MII_PHY_IDENTIFIER_1_REG, TLK110_PHY_ID1, UINT16_MAX, 1000); + res2 = esp_eth_smi_wait_value(MII_PHY_IDENTIFIER_2_REG, TLK110_PHY_ID2, TLK110_PHY_ID2_MASK, 1000); + } while(res1 != ESP_OK || res2 != ESP_OK); + + esp_eth_smi_write(SW_STRAP_CONTROL_REG, + DEFAULT_STRAP_CONFIG | SW_STRAP_CONFIG_DONE); + + ets_delay_us(300); + + // TODO: only do this if config.flow_ctrl_enable == true + phy_mii_enable_flow_ctrl(); +} + +const eth_config_t phy_tlk110_default_ethernet_config = { + // PHY address configured by PHYADx pins. Default value of 0x1 + // is used if all pins are unconnected. + .phy_addr = 0x1, + .mac_mode = ETH_MODE_RMII, + //Only FULLDUPLEX mode support flow ctrl now! + .flow_ctrl_enable = true, + .phy_init = phy_tlk110_init, + .phy_check_init = phy_tlk110_check_phy_init, + .phy_check_link = phy_mii_check_link_status, + .phy_get_speed_mode = phy_tlk110_get_speed_mode, + .phy_get_duplex_mode = phy_tlk110_get_duplex_mode, + .phy_get_partner_pause_enable = phy_mii_get_partner_pause_enable, + .phy_power_enable = phy_tlk110_power_enable, +}; + +void phy_tlk110_dump_registers() +{ + ESP_LOGD(TAG, "TLK110 Registers:"); + ESP_LOGD(TAG, "BMCR 0x%04x", esp_eth_smi_read(0x0)); + ESP_LOGD(TAG, "BMSR 0x%04x", esp_eth_smi_read(0x1)); + ESP_LOGD(TAG, "PHYIDR1 0x%04x", esp_eth_smi_read(0x2)); + ESP_LOGD(TAG, "PHYIDR2 0x%04x", esp_eth_smi_read(0x3)); + ESP_LOGD(TAG, "ANAR 0x%04x", esp_eth_smi_read(0x4)); + ESP_LOGD(TAG, "ANLPAR 0x%04x", esp_eth_smi_read(0x5)); + ESP_LOGD(TAG, "ANER 0x%04x", esp_eth_smi_read(0x6)); + ESP_LOGD(TAG, "ANNPTR 0x%04x", esp_eth_smi_read(0x7)); + ESP_LOGD(TAG, "ANLNPTR 0x%04x", esp_eth_smi_read(0x8)); + ESP_LOGD(TAG, "SWSCR1 0x%04x", esp_eth_smi_read(0x9)); + ESP_LOGD(TAG, "SWSCR2 0x%04x", esp_eth_smi_read(0xa)); + ESP_LOGD(TAG, "SWSCR3 0x%04x", esp_eth_smi_read(0xb)); + ESP_LOGD(TAG, "REGCR 0x%04x", esp_eth_smi_read(0xd)); + ESP_LOGD(TAG, "ADDAR 0x%04x", esp_eth_smi_read(0xe)); + ESP_LOGD(TAG, "PHYSTS 0x%04x", esp_eth_smi_read(0x10)); + ESP_LOGD(TAG, "PHYSCR 0x%04x", esp_eth_smi_read(0x11)); + ESP_LOGD(TAG, "MISR1 0x%04x", esp_eth_smi_read(0x12)); + ESP_LOGD(TAG, "MISR2 0x%04x", esp_eth_smi_read(0x13)); + ESP_LOGD(TAG, "FCSCR 0x%04x", esp_eth_smi_read(0x14)); + ESP_LOGD(TAG, "RECR 0x%04x", esp_eth_smi_read(0x15)); + ESP_LOGD(TAG, "BISCR 0x%04x", esp_eth_smi_read(0x16)); + ESP_LOGD(TAG, "RBR 0x%04x", esp_eth_smi_read(0x17)); + ESP_LOGD(TAG, "LEDCR 0x%04x", esp_eth_smi_read(0x18)); + ESP_LOGD(TAG, "PHYCR 0x%04x", esp_eth_smi_read(0x19)); + ESP_LOGD(TAG, "10BTSCR 0x%04x", esp_eth_smi_read(0x1a)); + ESP_LOGD(TAG, "BICSR1 0x%04x", esp_eth_smi_read(0x1b)); + ESP_LOGD(TAG, "BICSR2 0x%04x", esp_eth_smi_read(0x1c)); + ESP_LOGD(TAG, "CDCR 0x%04x", esp_eth_smi_read(0x1e)); + ESP_LOGD(TAG, "TRXCPSR 0x%04x", esp_eth_smi_read(0x42)); + ESP_LOGD(TAG, "PWRBOCR 0x%04x", esp_eth_smi_read(0xae)); + ESP_LOGD(TAG, "VRCR 0x%04x", esp_eth_smi_read(0xD0)); + ESP_LOGD(TAG, "ALCDRR1 0x%04x", esp_eth_smi_read(0x155)); + ESP_LOGD(TAG, "CDSCR1 0x%04x", esp_eth_smi_read(0x170)); + ESP_LOGD(TAG, "CDSCR2 0x%04x", esp_eth_smi_read(0x171)); +} diff --git a/components/ethernet/include/esp_eth.h b/components/ethernet/include/esp_eth.h index c2a3554b1..a7f92ad4b 100644 --- a/components/ethernet/include/esp_eth.h +++ b/components/ethernet/include/esp_eth.h @@ -15,6 +15,7 @@ #ifndef __ESP_ETH_H__ #define __ESP_ETH_H__ +#include #include #include "esp_err.h" @@ -24,7 +25,7 @@ extern "C" { typedef enum { ETH_MODE_RMII = 0, - ETH_MDOE_MII, + ETH_MODE_MII, } eth_mode_t; typedef enum { @@ -34,7 +35,7 @@ typedef enum { typedef enum { ETH_MODE_HALFDUPLEX = 0, - ETH_MDOE_FULLDUPLEX, + ETH_MODE_FULLDUPLEX, } eth_duplex_mode_t; typedef enum { @@ -99,9 +100,10 @@ typedef struct { bool flow_ctrl_enable; /*!< flag of flow ctrl enable */ eth_phy_get_partner_pause_enable_func phy_get_partner_pause_enable; /*!< get partner pause enable */ eth_phy_power_enable_func phy_power_enable; /*!< enable or disable phy power */ - + } eth_config_t; + /** * @brief Init ethernet mac * @@ -173,7 +175,7 @@ void esp_eth_get_mac(uint8_t mac[6]); void esp_eth_smi_write(uint32_t reg_num, uint16_t value); /** - * @brief Write phy reg with smi interface. + * @brief Read phy reg with smi interface. * * @note phy base addr must be right. * @@ -183,6 +185,35 @@ void esp_eth_smi_write(uint32_t reg_num, uint16_t value); */ uint16_t esp_eth_smi_read(uint32_t reg_num); +/** + * @brief Continuously read a PHY register over SMI interface, wait until the register has the desired value. + * + * @note PHY base address must be right. + * + * @param reg_num: PHY register number + * @param value: Value to wait for (masked with value_mask) + * @param value_mask: Mask of bits to match in the register. + * @param timeout_ms: Timeout to wait for this value (milliseconds). 0 means never timeout. + * + * @return ESP_OK if desired value matches, ESP_ERR_TIMEOUT if timed out. + */ +esp_err_t esp_eth_smi_wait_value(uint32_t reg_num, uint16_t value, uint16_t value_mask, int timeout_ms); + +/** + * @brief Continuously read a PHY register over SMI interface, wait until the register has all bits in a mask set. + * + * @note PHY base address must be right. + * + * @param reg_num: PHY register number + * @param value_mask: Value mask to wait for (all bits in this mask must be set) + * @param timeout_ms: Timeout to wait for this value (milliseconds). 0 means never timeout. + * + * @return ESP_OK if desired value matches, ESP_ERR_TIMEOUT if timed out. + */ +static inline esp_err_t esp_eth_smi_wait_set(uint32_t reg_num, uint16_t value_mask, int timeout_ms) { + return esp_eth_smi_wait_value(reg_num, value_mask, value_mask, timeout_ms); +} + /** * @brief Free emac rx buf. * diff --git a/components/ethernet/include/eth_phy/phy.h b/components/ethernet/include/eth_phy/phy.h new file mode 100644 index 000000000..44edd7491 --- /dev/null +++ b/components/ethernet/include/eth_phy/phy.h @@ -0,0 +1,59 @@ +// Copyright 2015-2016 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. + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "esp_eth.h" + +/* Common PHY-management functions. + + These are not enough to drive any particular Ethernet PHY, but they provide a common configuration structure and + management functions. +*/ + +/* Configure fixed pins for RMII data interface. + + This configures GPIOs 0, 19, 22, 25, 26, 27 for use with RMII + data interface. These pins cannot be changed, and must be wired to + ethernet functions. + + This is not sufficient to fully configure the Ethernet PHY, + MDIO configuration interface pins (such as SMI MDC, MDO, MDI) + must also be configured correctly in the GPIO matrix. +*/ +void phy_rmii_configure_data_interface_pins(void); + +/* Configure variable pins for SMI (MDIO) ethernet functions. + + Calling this function along with mii_configure_default_pins() will + fully configure the GPIOs for the ethernet PHY. + */ +void phy_rmii_smi_configure_pins(uint8_t mdc_gpio, uint8_t mdio_gpio); + + +/* Enable flow control in standard PHY MII register. + */ +void phy_mii_enable_flow_ctrl(void); + +bool phy_mii_check_link_status(void); + +bool phy_mii_get_partner_pause_enable(void); + +#ifdef __cplusplus +} +#endif diff --git a/components/ethernet/include/eth_phy/phy_lan8720.h b/components/ethernet/include/eth_phy/phy_lan8720.h new file mode 100644 index 000000000..7bde42eca --- /dev/null +++ b/components/ethernet/include/eth_phy/phy_lan8720.h @@ -0,0 +1,67 @@ +// Copyright 2015-2017 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. + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "phy.h" + + +/* @brief Dump all LAN8720 PHY SMI configuration registers + * + * @note These registers are dumped at 'debug' level, so output + * may not be visible depending on default log levels. + */ +void phy_lan8720_dump_registers(); + +/* @brief Default LAN8720 phy_check_init function. + */ +void phy_lan8720_check_phy_init(void); + +/* @brief Default LAN8720 phy_get_speed_mode function. + */ +eth_speed_mode_t phy_lan8720_get_speed_mode(void); + +/* @brief Default LAN8720 phy_get_duplex_mode function. + */ +eth_duplex_mode_t phy_lan8720_get_duplex_mode(void); + +/* @brief Default LAN8720 phy_power_enable function. + * + * @note This function may need to be replaced with a custom function + * if the PHY has a GPIO to enable power or start a clock. + * + * Consult the ethernet example to see how this is done. + */ +void phy_lan8720_power_enable(bool); + +/* @brief Default LAN8720 phy_init function. + */ +void phy_lan8720_init(void); + +/* @brief Default LAN8720 PHY configuration + * + * This configuration is not suitable for use as-is, it will need + * to be modified for your particular PHY hardware setup. + * + * Consult the Ethernet example to see how this is done. + */ +extern const eth_config_t phy_lan8720_default_ethernet_config; + +#ifdef __cplusplus +} +#endif diff --git a/components/ethernet/include/eth_phy/phy_reg.h b/components/ethernet/include/eth_phy/phy_reg.h new file mode 100644 index 000000000..33c9a064a --- /dev/null +++ b/components/ethernet/include/eth_phy/phy_reg.h @@ -0,0 +1,37 @@ +// Copyright 2015-2016 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. + +#pragma once + +/* This header contains register/bit masks for the standard + PHY MII registers that should be supported by all PHY models. +*/ + +#define MII_BASIC_MODE_CONTROL_REG (0x0) +#define MII_SOFTWARE_RESET BIT(15) + +#define MII_BASIC_MODE_STATUS_REG (0x1) +#define MII_AUTO_NEGOTIATION_COMPLETE BIT(5) +#define MII_LINK_STATUS BIT(2) + +#define MII_PHY_IDENTIFIER_1_REG (0x2) +#define MII_PHY_IDENTIFIER_2_REG (0x3) + +#define MII_AUTO_NEG_ADVERTISEMENT_REG (0x4) +#define MII_ASM_DIR BIT(11) +#define MII_PAUSE BIT(10) + +#define MII_PHY_LINK_PARTNER_ABILITY_REG (0x5) +#define MII_PARTNER_ASM_DIR BIT(11) +#define MII_PARTNER_PAUSE BIT(10) diff --git a/components/ethernet/include/eth_phy/phy_tlk110.h b/components/ethernet/include/eth_phy/phy_tlk110.h new file mode 100644 index 000000000..1019044e9 --- /dev/null +++ b/components/ethernet/include/eth_phy/phy_tlk110.h @@ -0,0 +1,66 @@ +// Copyright 2015-2017 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. + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "phy.h" + +/* @brief Dump all TLK110 PHY SMI configuration registers + * + * @note These registers are dumped at 'debug' level, so output + * may not be visible depending on default log levels. + */ +void phy_tlk110_dump_registers(); + +/* @brief Default TLK110 phy_check_init function. + */ +void phy_tlk110_check_phy_init(void); + +/* @brief Default TLK110 phy_get_speed_mode function. + */ +eth_speed_mode_t phy_tlk110_get_speed_mode(void); + +/* @brief Default TLK110 phy_get_duplex_mode function. + */ +eth_duplex_mode_t phy_tlk110_get_duplex_mode(void); + +/* @brief Default TLK110 phy_power_enable function. + * + * @note This function may need to be replaced with a custom function + * if the PHY has a GPIO to enable power or start a clock. + * + * Consult the ethernet example to see how this is done. + */ +void phy_tlk110_power_enable(bool); + +/* @brief Default TLK110 phy_init function. + */ +void phy_tlk110_init(void); + +/* @brief Default TLK110 PHY configuration + * + * This configuration is not suitable for use as-is, it will need + * to be modified for your particular PHY hardware setup. + * + * Consult the Ethernet example to see how this is done. + */ +extern const eth_config_t phy_tlk110_default_ethernet_config; + +#ifdef __cplusplus +} +#endif diff --git a/components/fatfs/src/diskio_spiflash.c b/components/fatfs/src/diskio_spiflash.c new file mode 100644 index 000000000..eb518e0e8 --- /dev/null +++ b/components/fatfs/src/diskio_spiflash.c @@ -0,0 +1,130 @@ +// Copyright 2015-2017 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. + +#include +#include "diskio.h" /* FatFs lower layer API */ +#include "ffconf.h" +#include "ff.h" +#include "sdmmc_cmd.h" +#include "esp_log.h" +#include +#include + +#include "diskio_spiflash.h" +#include "wear_levelling.h" + +static const char* TAG = "ff_diskio_spiflash"; +#ifndef MAX_FF_WL_DRIVES +#define MAX_FF_WL_DRIVES 8 +#endif // MAX_FF_WL_DRIVES + +wl_handle_t ff_wl_handles[MAX_FF_WL_DRIVES] = { + WL_INVALID_HANDLE, + WL_INVALID_HANDLE, + WL_INVALID_HANDLE, + WL_INVALID_HANDLE, + WL_INVALID_HANDLE, + WL_INVALID_HANDLE, + WL_INVALID_HANDLE, + WL_INVALID_HANDLE +}; + +DSTATUS ff_wl_initialize (BYTE pdrv) +{ + return 0; +} + +DSTATUS ff_wl_status (BYTE pdrv) +{ + return 0; +} + +DRESULT ff_wl_read (BYTE pdrv, BYTE *buff, DWORD sector, UINT count) +{ + ESP_LOGV(TAG, "ff_wl_read - pdrv=%i, sector=%i, count=%i\n", (unsigned int)pdrv, (unsigned int)sector, (unsigned int)count); + wl_handle_t wl_handle = ff_wl_handles[pdrv]; + assert(wl_handle + 1); + esp_err_t err = wl_read(wl_handle, sector * wl_sector_size(wl_handle), buff, count * wl_sector_size(wl_handle)); + if (err != ESP_OK) { + ESP_LOGE(TAG, "wl_read failed (%d)", err); + return RES_ERROR; + } + return RES_OK; +} + +DRESULT ff_wl_write (BYTE pdrv, const BYTE *buff, DWORD sector, UINT count) +{ + ESP_LOGV(TAG, "ff_wl_write - pdrv=%i, sector=%i, count=%i\n", (unsigned int)pdrv, (unsigned int)sector, (unsigned int)count); + wl_handle_t wl_handle = ff_wl_handles[pdrv]; + assert(wl_handle + 1); + esp_err_t err = wl_erase_range(wl_handle, sector * wl_sector_size(wl_handle), count * wl_sector_size(wl_handle)); + if (err != ESP_OK) { + ESP_LOGE(TAG, "wl_erase_range failed (%d)", err); + return RES_ERROR; + } + err = wl_write(wl_handle, sector * wl_sector_size(wl_handle), buff, count * wl_sector_size(wl_handle)); + if (err != ESP_OK) { + ESP_LOGE(TAG, "wl_write failed (%d)", err); + return RES_ERROR; + } + return RES_OK; +} + +DRESULT ff_wl_ioctl (BYTE pdrv, BYTE cmd, void *buff) +{ + wl_handle_t wl_handle = ff_wl_handles[pdrv]; + ESP_LOGV(TAG, "ff_wl_ioctl: cmd=%i\n", cmd); + assert(wl_handle + 1); + switch (cmd) { + case CTRL_SYNC: + return RES_OK; + case GET_SECTOR_COUNT: + *((uint32_t *) buff) = wl_size(wl_handle) / wl_sector_size(wl_handle); + return RES_OK; + case GET_SECTOR_SIZE: + *((uint32_t *) buff) = wl_sector_size(wl_handle); + return RES_OK; + case GET_BLOCK_SIZE: + return RES_ERROR; + } + return RES_ERROR; +} + + +esp_err_t ff_diskio_register_wl_partition(BYTE pdrv, wl_handle_t flash_handle) +{ + if (pdrv >= MAX_FF_WL_DRIVES) return ESP_FAIL; + static const ff_diskio_impl_t wl_impl = { + .init = &ff_wl_initialize, + .status = &ff_wl_status, + .read = &ff_wl_read, + .write = &ff_wl_write, + .ioctl = &ff_wl_ioctl + }; + ff_wl_handles[pdrv] = flash_handle; + ff_diskio_register(pdrv, &wl_impl); + return ESP_OK; +} + +BYTE ff_diskio_get_pdrv_wl(wl_handle_t flash_handle) +{ + for (int i=0 ; i< MAX_FF_WL_DRIVES ; i++) + { + if (flash_handle == ff_wl_handles[i]) + { + return i; + } + } + return -1; +} diff --git a/components/fatfs/src/diskio_spiflash.h b/components/fatfs/src/diskio_spiflash.h new file mode 100644 index 000000000..d1de1d3da --- /dev/null +++ b/components/fatfs/src/diskio_spiflash.h @@ -0,0 +1,39 @@ +// Copyright 2015-2017 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. + +#ifndef _DISKIO_SPIFLASH_DEFINED +#define _DISKIO_SPIFLASH_DEFINED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "integer.h" +#include "wear_levelling.h" + + +/** + * Register spi flash partition + * + * @param pdrv drive number + * @param flash_handle handle of the wear levelling partition. + */ +esp_err_t ff_diskio_register_wl_partition(BYTE pdrv, wl_handle_t flash_handle); +BYTE ff_diskio_get_pdrv_wl(wl_handle_t flash_handle); + +#ifdef __cplusplus +} +#endif + +#endif // _DISKIO_SPIFLASH_DEFINED diff --git a/components/fatfs/src/esp_vfs_fat.h b/components/fatfs/src/esp_vfs_fat.h index 4e27dce69..140f8bdc3 100644 --- a/components/fatfs/src/esp_vfs_fat.h +++ b/components/fatfs/src/esp_vfs_fat.h @@ -19,6 +19,7 @@ #include "driver/sdmmc_types.h" #include "driver/sdmmc_host.h" #include "ff.h" +#include "wear_levelling.h" /** * @brief Register FATFS with VFS component @@ -77,13 +78,17 @@ esp_err_t esp_vfs_fat_unregister() __attribute__((deprecated)); */ esp_err_t esp_vfs_fat_unregister_path(const char* base_path); + /** - * @brief Configuration arguments for esp_vfs_fat_sdmmc_mount function + * @brief Configuration arguments for esp_vfs_fat_sdmmc_mount and esp_vfs_fat_spiflash_mount functions */ typedef struct { - bool format_if_mount_failed; ///< If FAT partition can not be mounted, and this parameter is true, create partition table and format the filesystem - int max_files; ///< Max number of open files -} esp_vfs_fat_sdmmc_mount_config_t; + bool format_if_mount_failed; ///< If FAT partition can not be mounted, and this parameter is true, create partition table and format the filesystem + int max_files; ///< Max number of open files +} esp_vfs_fat_mount_config_t; + +// Compatibility definition +typedef esp_vfs_fat_mount_config_t esp_vfs_fat_sdmmc_mount_config_t; /** * @brief Convenience function to get FAT filesystem on SD card registered in VFS @@ -114,7 +119,7 @@ typedef struct { esp_err_t esp_vfs_fat_sdmmc_mount(const char* base_path, const sdmmc_host_t* host_config, const sdmmc_slot_config_t* slot_config, - const esp_vfs_fat_sdmmc_mount_config_t* mount_config, + const esp_vfs_fat_mount_config_t* mount_config, sdmmc_card_t** out_card); /** @@ -125,3 +130,46 @@ esp_err_t esp_vfs_fat_sdmmc_mount(const char* base_path, * - ESP_ERR_INVALID_STATE if esp_vfs_fat_sdmmc_mount hasn't been called */ esp_err_t esp_vfs_fat_sdmmc_unmount(); + +/** + * @brief Convenience function to initialize FAT filesystem in SPI flash and register it in VFS + * + * This is an all-in-one function which does the following: + * + * - finds the partition with defined partition_label. Partition label should be + * configured in the partition table. + * - initializes flash wear levelling library on top of the given partition + * - mounts FAT partition using FATFS library on top of flash wear levelling + * library + * - registers FATFS library with VFS, with prefix given by base_prefix variable + * + * This function is intended to make example code more compact. + * + * @param base_path path where FATFS partition should be mounted (e.g. "/spiflash") + * @param partition_label label of the partition which should be used + * @param mount_config pointer to structure with extra parameters for mounting FATFS + * @param[out] wl_handle wear levelling driver handle + * @return + * - ESP_OK on success + * - ESP_ERR_NOT_FOUND if the partition table does not contain FATFS partition with given label + * - ESP_ERR_INVALID_STATE if esp_vfs_fat_spiflash_mount was already called + * - ESP_ERR_NO_MEM if memory can not be allocated + * - ESP_FAIL if partition can not be mounted + * - other error codes from wear levelling library, SPI flash driver, or FATFS drivers + */ +esp_err_t esp_vfs_fat_spiflash_mount(const char* base_path, + const char* partition_label, + const esp_vfs_fat_mount_config_t* mount_config, + wl_handle_t* wl_handle); + +/** + * @brief Unmount FAT filesystem and release resources acquired using esp_vfs_fat_spiflash_mount + * + * @param base_path path where partition should be registered (e.g. "/spiflash") + * @param wl_handle wear levelling driver handle returned by esp_vfs_fat_spiflash_mount + * + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_STATE if esp_vfs_fat_spiflash_mount hasn't been called + */ + esp_err_t esp_vfs_fat_spiflash_unmount(const char* base_path, wl_handle_t wl_handle); diff --git a/components/fatfs/src/ff.c b/components/fatfs/src/ff.c index 0d7d7366b..53361e50f 100644 --- a/components/fatfs/src/ff.c +++ b/components/fatfs/src/ff.c @@ -5665,6 +5665,9 @@ FRESULT f_mkfs ( /* Create partition table on the physical drive */ /*-----------------------------------------------------------------------*/ +#define CLUSTER_SIZE 63 +#define SUPPORTED_FLASH_SIZE 0x1000 + FRESULT f_fdisk ( BYTE pdrv, /* Physical drive number */ const DWORD* szt, /* Pointer to the size table for each partitions */ @@ -5675,18 +5678,21 @@ FRESULT f_fdisk ( BYTE s_hd, e_hd, *p, *buf = (BYTE*)work; DSTATUS stat; DWORD sz_disk, sz_part, s_part; - + DWORD cluster_size = CLUSTER_SIZE; stat = disk_initialize(pdrv); if (stat & STA_NOINIT) return FR_NOT_READY; if (stat & STA_PROTECT) return FR_WRITE_PROTECTED; if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_disk)) return FR_DISK_ERR; - /* Determine the CHS without any care of the drive geometry */ - for (n = 16; n < 256 && sz_disk / n / 63 > 1024; n *= 2) ; + for (n = 16; n < 256 && sz_disk / n / cluster_size > 1024; n *= 2) ; if (n == 256) n--; + if (sz_disk < SUPPORTED_FLASH_SIZE) { + cluster_size = 1; + n = sz_disk; + } e_hd = n - 1; - sz_cyl = 63 * n; + sz_cyl = cluster_size * n; tot_cyl = sz_disk / sz_cyl; /* Create partition table */ @@ -5699,7 +5705,7 @@ FRESULT f_fdisk ( sz_part = (DWORD)sz_cyl * p_cyl; if (i == 0) { /* Exclude first track of cylinder 0 */ s_hd = 1; - s_part += 63; sz_part -= 63; + s_part += cluster_size; sz_part -= cluster_size; } else { s_hd = 0; } @@ -5712,7 +5718,7 @@ FRESULT f_fdisk ( p[3] = (BYTE)b_cyl; /* Start cylinder */ p[4] = 0x06; /* System type (temporary setting) */ p[5] = e_hd; /* End head */ - p[6] = (BYTE)((e_cyl >> 2) + 63); /* End sector */ + p[6] = (BYTE)((e_cyl >> 2) + cluster_size); /* End sector */ p[7] = (BYTE)e_cyl; /* End cylinder */ st_dword(p + 8, s_part); /* Start sector in LBA */ st_dword(p + 12, sz_part); /* Partition size */ diff --git a/components/fatfs/src/ffconf.h b/components/fatfs/src/ffconf.h index 3556b31b2..ab17e6922 100644 --- a/components/fatfs/src/ffconf.h +++ b/components/fatfs/src/ffconf.h @@ -179,7 +179,7 @@ #define _MIN_SS 512 -#define _MAX_SS 512 +#define _MAX_SS 4096 /* These options configure the range of sector size to be supported. (512, 1024, / 2048 or 4096) Always set both 512 for most systems, all type of memory cards and / harddisk. But a larger value may be required for on-board flash memory and some diff --git a/components/fatfs/src/vfs_fat_sdmmc.c b/components/fatfs/src/vfs_fat_sdmmc.c index a9e5362dc..edbc2c12e 100644 --- a/components/fatfs/src/vfs_fat_sdmmc.c +++ b/components/fatfs/src/vfs_fat_sdmmc.c @@ -34,6 +34,7 @@ esp_err_t esp_vfs_fat_sdmmc_mount(const char* base_path, { const size_t workbuf_size = 4096; void* workbuf = NULL; + FATFS* fs = NULL; if (s_card != NULL) { return ESP_ERR_INVALID_STATE; @@ -82,7 +83,6 @@ esp_err_t esp_vfs_fat_sdmmc_mount(const char* base_path, char drv[3] = {(char)('0' + pdrv), ':', 0}; // connect FATFS to VFS - FATFS* fs; err = esp_vfs_fat_register(base_path, drv, mount_config->max_files, &fs); if (err == ESP_ERR_INVALID_STATE) { // it's okay, already registered with VFS @@ -129,6 +129,9 @@ esp_err_t esp_vfs_fat_sdmmc_mount(const char* base_path, fail: sdmmc_host_deinit(); free(workbuf); + if (fs) { + f_mount(NULL, drv, 0); + } esp_vfs_fat_unregister_path(base_path); ff_diskio_unregister(pdrv); free(s_card); diff --git a/components/fatfs/src/vfs_fat_spiflash.c b/components/fatfs/src/vfs_fat_spiflash.c new file mode 100644 index 000000000..10c4781f2 --- /dev/null +++ b/components/fatfs/src/vfs_fat_spiflash.c @@ -0,0 +1,116 @@ +// Copyright 2015-2017 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. + +#include +#include +#include "esp_log.h" +#include "esp_vfs.h" +#include "esp_vfs_fat.h" +#include "diskio.h" + +#include "wear_levelling.h" +#include "diskio_spiflash.h" + +static const char *TAG = "vfs_fat_spiflash"; +esp_err_t esp_vfs_fat_spiflash_mount(const char* base_path, + const char* partition_label, + const esp_vfs_fat_mount_config_t* mount_config, + wl_handle_t* wl_handle) +{ + esp_err_t result = ESP_OK; + const size_t workbuf_size = 4096; + void *workbuf = NULL; + + esp_partition_t *data_partition = (esp_partition_t *)esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_FAT, partition_label); + if (data_partition == NULL) { + ESP_LOGE(TAG, "Failed to find FATFS partition (type='data', subtype='fat', partition_label='%s'). Check the partition table.", partition_label); + return ESP_ERR_NOT_FOUND; + } + + result = wl_mount(data_partition, wl_handle); + if (result != ESP_OK) { + ESP_LOGE(TAG, "failed to mount wear levelling layer. result = %i", result); + return result; + } + // connect driver to FATFS + BYTE pdrv = 0xFF; + if (ff_diskio_get_drive(&pdrv) != ESP_OK || pdrv == 0xFF) { + ESP_LOGD(TAG, "the maximum count of volumes is already mounted"); + return ESP_ERR_NO_MEM; + } + ESP_LOGD(TAG, "pdrv=%i\n", pdrv); + + char drv[3] = {(char)('0' + pdrv), ':', 0}; + + result = ff_diskio_register_wl_partition(pdrv, *wl_handle); + if (result != ESP_OK) { + ESP_LOGE(TAG, "ff_diskio_register_wl_partition failed pdrv=%i, error - 0x(%x)", pdrv, result); + goto fail; + } + FATFS *fs; + result = esp_vfs_fat_register(base_path, drv, mount_config->max_files, &fs); + if (result == ESP_ERR_INVALID_STATE) { + // it's okay, already registered with VFS + } else if (result != ESP_OK) { + ESP_LOGD(TAG, "esp_vfs_fat_register failed 0x(%x)", result); + goto fail; + } + + // Try to mount partition + FRESULT fresult = f_mount(fs, drv, 1); + if (fresult != FR_OK) { + ESP_LOGW(TAG, "f_mount failed (%d)", fresult); + if (!(fresult == FR_NO_FILESYSTEM && mount_config->format_if_mount_failed)) { + result = ESP_FAIL; + goto fail; + } + workbuf = malloc(workbuf_size); + ESP_LOGI(TAG, "Formatting FATFS partition"); + fresult = f_mkfs("", FM_ANY | FM_SFD, workbuf_size, workbuf, workbuf_size); + if (fresult != FR_OK) { + result = ESP_FAIL; + ESP_LOGE(TAG, "f_mkfs failed (%d)", fresult); + goto fail; + } + free(workbuf); + ESP_LOGI(TAG, "Mounting again"); + fresult = f_mount(fs, drv, 0); + if (fresult != FR_OK) { + result = ESP_FAIL; + ESP_LOGE(TAG, "f_mount failed after formatting (%d)", fresult); + goto fail; + } + } + return ESP_OK; + +fail: + free(workbuf); + esp_vfs_fat_unregister_path(base_path); + ff_diskio_unregister(pdrv); + return result; +} + +esp_err_t esp_vfs_fat_spiflash_unmount(const char *base_path, wl_handle_t wl_handle) +{ + BYTE s_pdrv = ff_diskio_get_pdrv_wl(wl_handle); + char drv[3] = {(char)('0' + s_pdrv), ':', 0}; + + f_mount(0, drv, 0); + ff_diskio_unregister(s_pdrv); + // release partition driver + esp_err_t err_drv = wl_unmount(wl_handle); + esp_err_t err = esp_vfs_fat_unregister_path(base_path); + if (err == ESP_OK) err = err_drv; + return err; +} diff --git a/components/freertos/port.c b/components/freertos/port.c index 756e14295..83b793c9d 100644 --- a/components/freertos/port.c +++ b/components/freertos/port.c @@ -255,7 +255,6 @@ void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMOR } #endif - /* * Returns true if the current core is in ISR context; low prio ISR, med prio ISR or timer tick ISR. High prio ISRs * aren't detected here, but they normally cannot call C code, so that should not be an issue anyway. diff --git a/components/log/README.rst b/components/log/README.rst index 002dadf81..f732a9e90 100644 --- a/components/log/README.rst +++ b/components/log/README.rst @@ -59,3 +59,136 @@ To configure logging output per module at runtime, add calls to ``esp_log_level_ esp_log_level_set("wifi", ESP_LOG_WARN); // enable WARN logs from WiFi stack esp_log_level_set("dhcpc", ESP_LOG_INFO); // enable INFO logs from DHCP client +Logging to Host via JTAG +^^^^^^^^^^^^^^^^^^^^^^^^ + +By default logging library uses vprintf-like function to write formatted output to dedicated UART. In general it invloves the following steps: + +1. Format string is parsed to obtain type of each argument. +2. According to its type every argument is converted to string representation. +3. Format string combined with converted arguments is sent to UART. + +Though implementation of vprintf-like function can be optimised to a certain level, all steps above have to be peformed in any case and every step takes some time (especially item 3). So it is frequent situation when addition of extra logging to the program to diagnose some problem changes its behaviour and problem dissapears or in the worst cases program can not work normally at all and ends up with an error or even hangs. +Possible ways to overcome this problem are to use faster UART bitrates (or another faster interface) and/or move string formatting procedure to the host. +ESP IDF has `Application Tracing` feature which allows to sent arbitrary application data to host via JTAG. This feature can also be used to transfer log information to host using ``esp_apptrace_vprintf`` function. This function does not perform full parsing of the format string and arguments, instead it just calculates number of arguments passed and sends them along with the format string address to the host. On the host log data are processed and printed out by a special Python script. + +Config Options and Dependencies +""""""""""""""""""""""""""""""" + +Using of the feature depends on two components: + +1. Host side: Application tracing is done over JTAG, so it needs OpenOCD to be set up and running on host machine. For instructions how to set it up, please, see :idf:`OpenOCD setup for ESP32` section for details. **NOTE:** `in order to achieve higher data rates you may need to modify JTAG adapter working frequency in OpenOCD config file. Maximum tested stable speed is 26MHz, so you need to have the following statement in your configuration file` ``adapter_khz 26000`` `instead of default` ``adapter_khz 200``. `Actually maximum stable JTAG frequency can depend on host system configuration.` +2. Target side: Application tracing functionality can be enabled by ``CONFIG_ESP32_APPTRACE_ENABLE`` macro via menuconfig. This option enables the module and makes ``esp_apptrace_vprintf`` available for users. + +Limitations +""""""""""" + +Curent implmentation of logging over JTAG has several limitations: + +1. Tracing from ``ESP_EARLY_LOGx`` macros is not supported. +2. No support for printf arguments which size exceeds 4 bytes (e.g. ``double`` and ``uint64_t``). +3. Only strings from .rodata section are supported as format strings and arguments. +4. Maximum number of printf arguments is 256. + +How To Use It +""""""""""""" + +To use logging via JTAG user needs to perform the following steps: + +1. On target side special vprintf-like function needs to be installed. As it was mentioned earlier this function is ``esp_apptrace_vprintf``. It sends log data to the host via JTAG. Example code is shown below. + +.. code-block:: c + + #include "esp_app_trace.h" + ... + void app_main() + { + // set log vprintf handler + esp_log_set_vprintf(esp_apptrace_vprintf); + ... + // user code using ESP_LOGx starts here + // all data passed to ESP_LOGx are sent to host + ... + // restore log vprintf handler + esp_log_set_vprintf(vprintf); + // flush last data to host + esp_apptrace_flush(ESP_APPTRACE_DEST_TRAX, 100000 /*tmo in us*/); + ESP_LOGI(TAG, "Tracing is finished."); // this will be printed out to UART + while (1); + } + +2. Build the program image and download it to target as described in :idf:`Developing With the ESP-IDF` section. +3. Run OpenOCD (see :idf:`OpenOCD setup for ESP32` section). +4. Connect to OpenOCD telnet server. On Linux it can be done using the following command in terminal ``telnet 4444``. If telnet session is opened on the same machine which runs OpenOCD you can use `localhost` as `` in the command. +5. Run the following command in OpenOCD telnet session: ``esp108 apptrace start /path/to/trace/file -1 -1 0 0 1``. This command will wait for board reset and transfer tracing data at the highest possible rate. +6. Reset the board. Logging to host will start automatically. +7. ``esp108 apptrace`` command with given arguments will never return (see other command options below), so you must stop it manually by resetting the board or pressing CTRL+C in OpenOCD window (not one with the telnet session). +8. Reset board or press CTRL+C in OpenOCD window (not one with the telnet session) when tracing is completed (for the example code above after the message `"Tracing is finished."` appears on UART). +9. To print out collected log records run the following command in terminal: ``$IDF_PATH/tools/esp_app_trace/logtrace_proc.py /path/to/trace/file /path/to/program/elf/file``. + +OpenOCD Application Tracing Command Options +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Command usage: +``esp108 apptrace [start [options] | [stop] | [status] | [dump ]`` + +Sub-commands: + * ``start``. Start tracing (continuous streaming). + * ``stop``. Stop tracing. + * ``status``. Get tracing status. + * ``dump``. Dump as much data as possible without waiting for trace memory block switch (post-mortem dump). + +Start command syntax: + ``start [trace_size [stop_tmo [skip_size [poll_period [wait4halt]]]]]`` + + .. list-table:: + :widths: 20 80 + :header-rows: 1 + + * - Argument + - Description + * - outfile + - Path to log trace file to save data + * - trace_size + - Maximum size of data to collect (in bytes). Tracing is stopped after specified amount of data is received. By default -1 (trace size stop trigger is disabled). + * - stop_tmo + - Idle timeout (in ms). Tracing is stopped if there is no data for specified period of time. By default 10 s (-1 to disable this stop trigger). + * - skip_size + - Number of bytes to skip at the start. By default 0. + * - poll_period + - Data polling period (in ms). If greater then 0 then command runs in non-blocking mode, otherwise command line will not be avalable until tracing is stopped. By default 1 ms. + * - wait4halt + - If 0 start tracing immediately, otherwise command waits for the target to be halted (after reset, by breakpoint etc) and then automatically resumes it and starts tracing. By default 0. + +Log Trace Processor Command Options +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Command usage: +``logtrace_proc.py [-h] [--no-errors] `` + +Positional arguments: + + .. list-table:: + :widths: 20 80 + :header-rows: 1 + + * - Argument + - Description + * - trace_file + - Path to log trace file + * - elf_file + - Path to program ELF file + +Optional arguments: + + .. list-table:: + :widths: 20 80 + :header-rows: 1 + + * - Argument + - Description + * - -h, --help + - show this help message and exit + * - --no-errors, -n + - Do not print errors + diff --git a/components/lwip/Kconfig b/components/lwip/Kconfig index be97573a1..1e37056fb 100644 --- a/components/lwip/Kconfig +++ b/components/lwip/Kconfig @@ -89,6 +89,54 @@ config LWIP_DHCP_DOES_ARP_CHECK Enabling this option allows check if the offered IP address is not already in use by another host on the network. +config TCPIP_TASK_STACK_SIZE + int "TCP/IP Task Stack Size" + default 2048 + help + Configure TCP/IP task stack size, used by LWIP to process multi-threaded TCP/IP operations. + The default is 2048 bytes, setting this stack too small will result in stack overflow crashes. + +menuconfig PPP_SUPPORT + bool "Enable PPP support (new/experimental)" + default n + help + Enable PPP stack. Now only PPP over serial is possible. + + PPP over serial support is experimental and unsupported. + +config PPP_PAP_SUPPORT + bool "Enable PAP support" + depends on PPP_SUPPORT + default n + help + Enable Password Authentication Protocol (PAP) support + +config PPP_CHAP_SUPPORT + bool "Enable CHAP support" + depends on PPP_SUPPORT + default n + help + Enable Challenge Handshake Authentication Protocol (CHAP) support + +config PPP_MSCHAP_SUPPORT + bool "Enable MSCHAP support" + depends on PPP_SUPPORT + default n + help + Enable Microsoft version of the Challenge-Handshake Authentication Protocol (MSCHAP) support + +config PPP_MPPE_SUPPORT + bool "Enable MPPE support" + depends on PPP_SUPPORT + default n + help + Enable Microsoft Point-to-Point Encryption (MPPE) support + +config PPP_DEBUG_ON + bool "Enable PPP debug log output" + depends on PPP_SUPPORT + default n + help + Enable PPP debug log output + endmenu - - diff --git a/components/lwip/api/pppapi.c b/components/lwip/api/pppapi.c index b5dcd144b..2212233ce 100755 --- a/components/lwip/api/pppapi.c +++ b/components/lwip/api/pppapi.c @@ -73,10 +73,10 @@ pppapi_set_default(ppp_pcb *pcb) static err_t pppapi_do_ppp_set_auth(struct tcpip_api_call *m) { - struct pppapi_msg_msg *msg = (struct pppapi_msg_msg *)m; + struct pppapi_msg *msg = (struct pppapi_msg *)m; - ppp_set_auth(msg->ppp, msg->msg.setauth.authtype, - msg->msg.setauth.user, msg->msg.setauth.passwd); + ppp_set_auth(msg->msg.ppp, msg->msg.msg.setauth.authtype, + msg->msg.msg.setauth.user, msg->msg.msg.setauth.passwd); return ERR_OK; } @@ -131,10 +131,10 @@ pppapi_set_notify_phase_callback(ppp_pcb *pcb, ppp_notify_phase_cb_fn notify_pha static err_t pppapi_do_pppos_create(struct tcpip_api_call *m) { - struct pppapi_msg_msg *msg = (struct pppapi_msg_msg *)m; + struct pppapi_msg *msg = (struct pppapi_msg *)(m); - msg->ppp = pppos_create(msg->msg.serialcreate.pppif, msg->msg.serialcreate.output_cb, - msg->msg.serialcreate.link_status_cb, msg->msg.serialcreate.ctx_cb); + msg->msg.ppp = pppos_create(msg->msg.msg.serialcreate.pppif, msg->msg.msg.serialcreate.output_cb, + msg->msg.msg.serialcreate.link_status_cb, msg->msg.msg.serialcreate.ctx_cb); return ERR_OK; } @@ -247,9 +247,9 @@ pppapi_pppol2tp_create(struct netif *pppif, struct netif *netif, ip_addr_t *ipad static err_t pppapi_do_ppp_connect(struct tcpip_api_call *m) { - struct pppapi_msg_msg *msg = (struct pppapi_msg_msg *)m; + struct pppapi_msg *msg = (struct pppapi_msg *)m; - return ppp_connect(msg->ppp, msg->msg.connect.holdoff); + return ppp_connect(msg->msg.ppp, msg->msg.msg.connect.holdoff); } /** @@ -300,9 +300,9 @@ pppapi_listen(ppp_pcb *pcb, struct ppp_addrs *addrs) static err_t pppapi_do_ppp_close(struct tcpip_api_call *m) { - struct pppapi_msg_msg *msg = (struct pppapi_msg_msg *)m; + struct pppapi_msg *msg = (struct pppapi_msg *)m; - return ppp_close(msg->ppp, msg->msg.close.nocarrier); + return ppp_close(msg->msg.ppp, msg->msg.msg.close.nocarrier); } /** @@ -349,9 +349,9 @@ pppapi_free(ppp_pcb *pcb) static err_t pppapi_do_ppp_ioctl(struct tcpip_api_call *m) { - struct pppapi_msg_msg *msg = (struct pppapi_msg_msg *)m; + struct pppapi_msg *msg = (struct pppapi_msg *)m; - return ppp_ioctl(msg->ppp, msg->msg.ioctl.cmd, msg->msg.ioctl.arg); + return ppp_ioctl(msg->msg.ppp, msg->msg.msg.ioctl.cmd, msg->msg.msg.ioctl.arg); } /** diff --git a/components/lwip/apps/dhcpserver.c b/components/lwip/apps/dhcpserver.c index 94acc881e..d3cf99370 100644 --- a/components/lwip/apps/dhcpserver.c +++ b/components/lwip/apps/dhcpserver.c @@ -719,6 +719,8 @@ static u8_t parse_options(u8_t *optptr, s16_t len) *******************************************************************************/ static s16_t parse_msg(struct dhcps_msg *m, u16_t len) { + u32_t lease_timer = (dhcps_lease_time * 60)/DHCPS_COARSE_TIMER_SECS; + if (memcmp((char *)m->options, &magic_cookie, sizeof(magic_cookie)) == 0) { #if DHCPS_DEBUG DHCPS_LOG("dhcps: len = %d\n", len); @@ -745,7 +747,7 @@ static s16_t parse_msg(struct dhcps_msg *m, u16_t len) } client_address.addr = pdhcps_pool->ip.addr; - pdhcps_pool->lease_timer = dhcps_lease_time; + pdhcps_pool->lease_timer = lease_timer; pnode = pback_node; goto POOL_CHECK; } else if (pdhcps_pool->ip.addr == client_address_plus.addr) { @@ -783,7 +785,7 @@ static s16_t parse_msg(struct dhcps_msg *m, u16_t len) pdhcps_pool->ip.addr = client_address.addr; memcpy(pdhcps_pool->mac, m->chaddr, sizeof(pdhcps_pool->mac)); - pdhcps_pool->lease_timer = dhcps_lease_time; + pdhcps_pool->lease_timer = lease_timer; pnode = (list_node *)malloc(sizeof(list_node)); memset(pnode , 0x00 , sizeof(list_node)); diff --git a/components/lwip/component.mk b/components/lwip/component.mk index 0f47dc3e9..6473b021a 100644 --- a/components/lwip/component.mk +++ b/components/lwip/component.mk @@ -2,11 +2,26 @@ # Component Makefile # -COMPONENT_ADD_INCLUDEDIRS := include/lwip include/lwip/port include/lwip/posix apps/ping +COMPONENT_ADD_INCLUDEDIRS := \ + include/lwip \ + include/lwip/port \ + include/lwip/posix \ + apps/ping -COMPONENT_SRCDIRS := api apps/sntp apps/ping apps core/ipv4 core/ipv6 core netif port/freertos port/netif port/debug port +ifdef CONFIG_PPP_SUPPORT +LWIP_PPP_DIRS := netif/ppp/polarssl netif/ppp +endif + +COMPONENT_SRCDIRS := \ + api \ + apps/sntp apps/ping apps \ + core/ipv4 core/ipv6 core \ + $(LWIP_PPP_DIRS) netif \ + port/freertos port/netif port/debug port CFLAGS += -Wno-address # lots of LWIP source files evaluate macros that check address of stack variables api/tcpip.o apps/dhcpserver.o: CFLAGS += -Wno-unused-variable apps/dhcpserver.o core/pbuf.o core/tcp_in.o: CFLAGS += -Wno-unused-but-set-variable +netif/ppp/pppos.o: CFLAGS += -Wno-type-limits + diff --git a/components/lwip/include/lwip/apps/dhcpserver.h b/components/lwip/include/lwip/apps/dhcpserver.h index 39781d966..9e361833d 100644 --- a/components/lwip/include/lwip/apps/dhcpserver.h +++ b/components/lwip/include/lwip/apps/dhcpserver.h @@ -166,6 +166,7 @@ enum dhcps_offer_option{ OFFER_END }; +#define DHCPS_COARSE_TIMER_SECS 1 #define DHCPS_MAX_LEASE 0x64 #define DHCPS_LEASE_TIME_DEF (120) diff --git a/components/lwip/include/lwip/netif/etharp.h b/components/lwip/include/lwip/netif/etharp.h index e745dcc3e..3e25c389d 100755 --- a/components/lwip/include/lwip/netif/etharp.h +++ b/components/lwip/include/lwip/netif/etharp.h @@ -134,6 +134,10 @@ err_t etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr, void etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p); +#if ETHARP_TRUST_IP_MAC +void etharp_ip_input(struct netif *netif, struct pbuf *p); +#endif + #ifdef __cplusplus } #endif diff --git a/components/lwip/include/lwip/port/lwipopts.h b/components/lwip/include/lwip/port/lwipopts.h index 21a5ac417..1fba71042 100644 --- a/components/lwip/include/lwip/port/lwipopts.h +++ b/components/lwip/include/lwip/port/lwipopts.h @@ -503,6 +503,56 @@ --------------------------------- */ +/** + * PPP_SUPPORT==1: Enable PPP. + */ +#define PPP_SUPPORT CONFIG_PPP_SUPPORT + +#if PPP_SUPPORT + +/** + * PAP_SUPPORT==1: Support PAP. + */ +#define PAP_SUPPORT CONFIG_PPP_PAP_SUPPORT + +/** + * CHAP_SUPPORT==1: Support CHAP. + */ +#define CHAP_SUPPORT CONFIG_PPP_CHAP_SUPPORT + +/** + * MSCHAP_SUPPORT==1: Support MSCHAP. + */ +#define MSCHAP_SUPPORT CONFIG_PPP_MSCHAP_SUPPORT + +/** + * CCP_SUPPORT==1: Support CCP. + */ +#define MPPE_SUPPORT CONFIG_PPP_MPPE_SUPPORT + +/** + * PPP_MAXIDLEFLAG: Max Xmit idle time (in ms) before resend flag char. + * TODO: If PPP_MAXIDLEFLAG > 0 and next package is send during PPP_MAXIDLEFLAG time, + * then 0x7E is not added at the begining of PPP package but 0x7E termination + * is always at the end. This behaviour brokes PPP dial with GSM (PPPoS). + * The PPP package should always start and end with 0x7E. + */ + +#define PPP_MAXIDLEFLAG 0 + +/** + * PPP_DEBUG: Enable debugging for PPP. + */ +#define PPP_DEBUG_ON CONFIG_PPP_DEBUG_ON + +#if PPP_DEBUG_ON +#define PPP_DEBUG LWIP_DBG_ON +#else +#define PPP_DEBUG LWIP_DBG_OFF +#endif + +#endif + /* -------------------------------------- ---------- Checksum options ---------- @@ -585,6 +635,18 @@ */ #define TCPIP_DEBUG LWIP_DBG_OFF +/** + * ETHARP_TRUST_IP_MAC==1: Incoming IP packets cause the ARP table to be + * updated with the source MAC and IP addresses supplied in the packet. + * You may want to disable this if you do not trust LAN peers to have the + * correct addresses, or as a limited approach to attempt to handle + * spoofing. If disabled, lwIP will need to make a new ARP request if + * the peer is not already in the ARP table, adding a little latency. + * The peer *is* in the ARP table if it requested our address before. + * Also notice that this slows down input processing of every IP packet! + */ +#define ETHARP_TRUST_IP_MAC 1 + /* Enable all Espressif-only options */ diff --git a/components/lwip/netif/etharp.c b/components/lwip/netif/etharp.c index b51a20222..d9854dbb0 100755 --- a/components/lwip/netif/etharp.c +++ b/components/lwip/netif/etharp.c @@ -670,8 +670,7 @@ etharp_get_entry(u8_t i, ip4_addr_t **ipaddr, struct netif **netif, struct eth_a * * @see pbuf_free() */ -static void -etharp_ip_input(struct netif *netif, struct pbuf *p) +void etharp_ip_input(struct netif *netif, struct pbuf *p) { struct eth_hdr *ethhdr; struct ip_hdr *iphdr; diff --git a/components/lwip/port/freertos/sys_arch.c b/components/lwip/port/freertos/sys_arch.c index 8d7b86501..b03fd6df5 100755 --- a/components/lwip/port/freertos/sys_arch.c +++ b/components/lwip/port/freertos/sys_arch.c @@ -435,6 +435,13 @@ sys_init(void) } } +/*-----------------------------------------------------------------------------------*/ +u32_t +sys_jiffies(void) +{ + return xTaskGetTickCount(); +} + /*-----------------------------------------------------------------------------------*/ u32_t sys_now(void) diff --git a/components/mbedtls/port/net.c b/components/mbedtls/port/net.c index 459106b40..f12b57e73 100644 --- a/components/mbedtls/port/net.c +++ b/components/mbedtls/port/net.c @@ -201,10 +201,14 @@ int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char * * Note: on a blocking socket this function always returns 0! */ -static int net_would_block( const mbedtls_net_context *ctx ) +static int net_would_block( const mbedtls_net_context *ctx, int *errout ) { int error = mbedtls_net_errno(ctx->fd); + if ( errout ) { + *errout = error; + } + /* * Never return 'WOULD BLOCK' on a non-blocking socket */ @@ -260,7 +264,7 @@ int mbedtls_net_accept( mbedtls_net_context *bind_ctx, } if ( ret < 0 ) { - if ( net_would_block( bind_ctx ) != 0 ) { + if ( net_would_block( bind_ctx, NULL ) != 0 ) { return ( MBEDTLS_ERR_SSL_WANT_READ ); } @@ -349,11 +353,10 @@ int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len ) ret = (int) read( fd, buf, len ); if ( ret < 0 ) { - if ( net_would_block( ctx ) != 0 ) { + if ( net_would_block( ctx, &error ) != 0 ) { return ( MBEDTLS_ERR_SSL_WANT_READ ); } - error = mbedtls_net_errno(fd); if ( error == EPIPE || error == ECONNRESET ) { return ( MBEDTLS_ERR_NET_CONN_RESET ); } @@ -425,11 +428,10 @@ int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len ) ret = (int) write( fd, buf, len ); if ( ret < 0 ) { - if ( net_would_block( ctx ) != 0 ) { + if ( net_would_block( ctx, &error ) != 0 ) { return ( MBEDTLS_ERR_SSL_WANT_WRITE ); } - error = mbedtls_net_errno(fd); if ( error == EPIPE || error == ECONNRESET ) { return ( MBEDTLS_ERR_NET_CONN_RESET ); } diff --git a/components/nvs_flash/.gitignore b/components/nvs_flash/.gitignore index f07085166..3318e4068 100644 --- a/components/nvs_flash/.gitignore +++ b/components/nvs_flash/.gitignore @@ -1,7 +1,7 @@ -test/test_nvs -test/coverage -test/coverage.info -*.gcno -*.gcda -*.gcov -*.o +test_nvs_host/test_nvs +test_nvs_host/coverage_report +test_nvs_host/coverage.info +**/*.gcno +**/*.gcda +**/*.gcov +**/*.o diff --git a/components/nvs_flash/test_nvs_host/Makefile b/components/nvs_flash/test_nvs_host/Makefile index 133762992..f1f5b52f2 100644 --- a/components/nvs_flash/test_nvs_host/Makefile +++ b/components/nvs_flash/test_nvs_host/Makefile @@ -19,7 +19,7 @@ SOURCE_FILES = \ crc.cpp \ main.cpp -CPPFLAGS += -I../include -I../src -I./ -I../../esp32/include -I ../../spi_flash/include -fprofile-arcs -ftest-coverage +CPPFLAGS += -I../include -I../src -I./ -I../../esp32/include -I ../../spi_flash/include -I ../../../tools/catch -fprofile-arcs -ftest-coverage CFLAGS += -fprofile-arcs -ftest-coverage CXXFLAGS += -std=c++11 -Wall -Werror LDFLAGS += -lstdc++ -Wall -fprofile-arcs -ftest-coverage diff --git a/components/partition_table/Kconfig.projbuild b/components/partition_table/Kconfig.projbuild index 36e435ba2..5a12512d5 100644 --- a/components/partition_table/Kconfig.projbuild +++ b/components/partition_table/Kconfig.projbuild @@ -57,6 +57,7 @@ config APP_OFFSET default 0x10000 # this is the factory app offset used by the default tables config PHY_DATA_OFFSET + depends on ESP32_PHY_INIT_DATA_IN_PARTITION hex default PARTITION_TABLE_CUSTOM_PHY_DATA_OFFSET if PARTITION_TABLE_CUSTOM default 0xf000 # this is the factory app offset used by the default tables diff --git a/components/soc/esp32/include/soc/bb_reg.h b/components/soc/esp32/include/soc/bb_reg.h index fca84deb1..69d2f43d2 100644 --- a/components/soc/esp32/include/soc/bb_reg.h +++ b/components/soc/esp32/include/soc/bb_reg.h @@ -21,12 +21,20 @@ #define BBPD_CTRL (DR_REG_BB_BASE + 0x0054) #define BB_FFT_FORCE_PU (BIT(3)) +#define BB_FFT_FORCE_PU_M (BIT(3)) +#define BB_FFT_FORCE_PU_V 1 #define BB_FFT_FORCE_PU_S 3 #define BB_FFT_FORCE_PD (BIT(2)) +#define BB_FFT_FORCE_PD_M (BIT(2)) +#define BB_FFT_FORCE_PD_V 1 #define BB_FFT_FORCE_PD_S 2 #define BB_DC_EST_FORCE_PU (BIT(1)) +#define BB_DC_EST_FORCE_PU_M (BIT(1)) +#define BB_DC_EST_FORCE_PU_V 1 #define BB_DC_EST_FORCE_PU_S 1 #define BB_DC_EST_FORCE_PD (BIT(0)) +#define BB_DC_EST_FORCE_PD_M (BIT(0)) +#define BB_DC_EST_FORCE_PD_V 1 #define BB_DC_EST_FORCE_PD_S 0 diff --git a/components/soc/esp32/include/soc/dport_reg.h b/components/soc/esp32/include/soc/dport_reg.h index 3677216bb..b2e14376e 100644 --- a/components/soc/esp32/include/soc/dport_reg.h +++ b/components/soc/esp32/include/soc/dport_reg.h @@ -3151,6 +3151,32 @@ #define DPORT_RECORD_PRO_PDEBUGINST_M ((DPORT_RECORD_PRO_PDEBUGINST_V)<<(DPORT_RECORD_PRO_PDEBUGINST_S)) #define DPORT_RECORD_PRO_PDEBUGINST_V 0xFFFFFFFF #define DPORT_RECORD_PRO_PDEBUGINST_S 0 +/* register layout: + * SIZE [7..0] : Instructions normally complete in the W stage. The size of the instruction in the W is given + * by this field in number of bytes. If it is 8’b0 in a given cycle the W stage has no completing + * instruction. This is also known as a bubble cycle. Also see DPORT_PRO_CPU_RECORD_PDEBUGSTATUS_REG. + * ISRC [14..12] : Instruction source. +** LOOP [23..20] : Loopback status. +** CINTLEVEL [27..24]: CINTLEVEL. +*/ +#define DPORT_RECORD_PDEBUGINST_SZ_M ((DPORT_RECORD_PDEBUGINST_SZ_V)<<(DPORT_RECORD_PDEBUGINST_SZ_S)) +#define DPORT_RECORD_PDEBUGINST_SZ_V 0xFF +#define DPORT_RECORD_PDEBUGINST_SZ_S 0 +#define DPORT_RECORD_PDEBUGINST_SZ(_r_) (((_r_)>>DPORT_RECORD_PDEBUGINST_SZ_S) & DPORT_RECORD_PDEBUGINST_SZ_V) +#define DPORT_RECORD_PDEBUGINST_ISRC_M ((DPORT_RECORD_PDEBUGINST_ISRC_V)<<(DPORT_RECORD_PDEBUGINST_ISRC_S)) +#define DPORT_RECORD_PDEBUGINST_ISRC_V 0x07 +#define DPORT_RECORD_PDEBUGINST_ISRC_S 12 +#define DPORT_RECORD_PDEBUGINST_ISRC(_r_) (((_r_)>>DPORT_RECORD_PDEBUGINST_ISRC_S) & DPORT_RECORD_PDEBUGINST_ISRC_V) +// #define DPORT_RECORD_PDEBUGINST_LOOP_M ((DPORT_RECORD_PDEBUGINST_LOOP_V)<<(DPORT_RECORD_PDEBUGINST_LOOP_S)) +// #define DPORT_RECORD_PDEBUGINST_LOOP_V 0x0F +// #define DPORT_RECORD_PDEBUGINST_LOOP_S 20 +// #define DPORT_RECORD_PDEBUGINST_LOOP(_r_) (((_r_)>>DPORT_RECORD_PDEBUGINST_LOOP_S) & DPORT_RECORD_PDEBUGINST_LOOP_V) +#define DPORT_RECORD_PDEBUGINST_LOOP_REP (BIT(20)) /* loopback will occur */ +#define DPORT_RECORD_PDEBUGINST_LOOP (BIT(21)) /* last inst of loop */ +#define DPORT_RECORD_PDEBUGINST_CINTL_M ((DPORT_RECORD_PDEBUGINST_CINTL_V)<<(DPORT_RECORD_PDEBUGINST_CINTL_S)) +#define DPORT_RECORD_PDEBUGINST_CINTL_V 0x0F +#define DPORT_RECORD_PDEBUGINST_CINTL_S 24 +#define DPORT_RECORD_PDEBUGINST_CINTL(_r_) (((_r_)>>DPORT_RECORD_PDEBUGINST_CINTL_S) & DPORT_RECORD_PDEBUGINST_CINTL_V) #define DPORT_PRO_CPU_RECORD_PDEBUGSTATUS_REG (DR_REG_DPORT_BASE + 0x450) /* DPORT_RECORD_PRO_PDEBUGSTATUS : RO ;bitpos:[7:0] ;default: 8'b0 ; */ @@ -3159,6 +3185,52 @@ #define DPORT_RECORD_PRO_PDEBUGSTATUS_M ((DPORT_RECORD_PRO_PDEBUGSTATUS_V)<<(DPORT_RECORD_PRO_PDEBUGSTATUS_S)) #define DPORT_RECORD_PRO_PDEBUGSTATUS_V 0xFF #define DPORT_RECORD_PRO_PDEBUGSTATUS_S 0 +/* register layout: + * BBCAUSE [5..0]: Indicates cause for bubble cycle. See below for posible values. When DPORT_RECORD_PDEBUGINST_SZ == 0 + * INSNTYPE[5..0]: Indicates type of instruction retiring in the W stage. See below for posible values. When DPORT_RECORD_PDEBUGINST_SZ > 0 +*/ +#define DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_M ((DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_V)<<(DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_S)) +#define DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_V 0x3F +#define DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_S 0 +#define DPORT_RECORD_PDEBUGSTATUS_BBCAUSE(_r_) (((_r_)>>DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_S) & DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_V) +#define DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_PSO 0x00 /* Power shut off */ +#define DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_DEP 0x02 /* Register dependency or resource conflict. See DPORT_XXX_CPU_RECORD_PDEBUGDATA_REG for extra info. */ +#define DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_CTL 0x04 /* Control transfer bubble */ +#define DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_ICM 0x08 /* I-cache miss (incl uncached miss) */ +#define DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_DCM 0x0C /* D-cache miss (excl uncached miss) */ +#define DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_EXC0 0x10 /* Exception or interrupt (W stage). See DPORT_XXX_CPU_RECORD_PDEBUGDATA_REG for extra info. + The virtual address of the instruction that was killed appears on DPORT_PRO_CPU_RECORD_PDEBUGPC_REG[31:0] */ +#define DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_EXC1 0x11 /* Exception or interrupt (W+1 stage). See DPORT_XXX_CPU_RECORD_PDEBUGDATA_REG for extra info. */ +#define DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_RPL 0x14 /* Instruction replay (other). DPORT_XXX_CPU_RECORD_PDEBUGDATA_REG has the PC of the replaying instruction. */ +#define DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_ITLB 0x18 /* HW ITLB refill. The refill address and data are available on + DPORT_PRO_CPU_RECORD_PDEBUGLS0ADDR_REG and DPORT_PRO_CPU_RECORD_PDEBUGLS0DATA_REG. */ +#define DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_ITLBM 0x1A /* ITLB miss */ +#define DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_DTLB 0x1C /* HW DTLB refill. The refill address and data are available on + DPORT_PRO_CPU_RECORD_PDEBUGLS0ADDR_REG and DPORT_PRO_CPU_RECORD_PDEBUGLS0DATA_REG. */ +#define DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_DTLBM 0x1E /* DTLB miss */ +#define DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_STALL 0x20 /* Stall . The cause of the global stall is further classified in the DPORT_XXX_CPU_RECORD_PDEBUGDATA_REG. */ +#define DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_HWMEC 0x24 /* HW-corrected memory error */ +#define DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_WAITI 0x28 /* WAITI mode */ +#define DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_OTHER 0x3C /* all other bubbles */ +#define DPORT_RECORD_PDEBUGSTATUS_INSNTYPE_M ((DPORT_RECORD_PDEBUGSTATUS_INSNTYPE_V)<<(DPORT_RECORD_PDEBUGSTATUS_INSNTYPE_S)) +#define DPORT_RECORD_PDEBUGSTATUS_INSNTYPE_V 0x3F +#define DPORT_RECORD_PDEBUGSTATUS_INSNTYPE_S 0 +#define DPORT_RECORD_PDEBUGSTATUS_INSNTYPE(_r_) (((_r_)>>DPORT_RECORD_PDEBUGSTATUS_INSNTYPE_S) & DPORT_RECORD_PDEBUGSTATUS_INSNTYPE_V) +#define DPORT_RECORD_PDEBUGSTATUS_INSNTYPE_JX 0x00 /* JX */ +#define DPORT_RECORD_PDEBUGSTATUS_INSNTYPE_CALLX 0x04 /* CALLX */ +#define DPORT_RECORD_PDEBUGSTATUS_INSNTYPE_CRET 0x08 /* All call returns */ +#define DPORT_RECORD_PDEBUGSTATUS_INSNTYPE_ERET 0x0C /* All exception returns */ +#define DPORT_RECORD_PDEBUGSTATUS_INSNTYPE_B 0x10 /* Branch taken or loop not taken */ +#define DPORT_RECORD_PDEBUGSTATUS_INSNTYPE_J 0x14 /* J */ +#define DPORT_RECORD_PDEBUGSTATUS_INSNTYPE_CALL 0x18 /* CALL */ +#define DPORT_RECORD_PDEBUGSTATUS_INSNTYPE_BN 0x1C /* Branch not taken */ +#define DPORT_RECORD_PDEBUGSTATUS_INSNTYPE_LOOP 0x20 /* Loop instruction (taken) */ +#define DPORT_RECORD_PDEBUGSTATUS_INSNTYPE_S32C1I 0x24 /* S32C1I. The address and load data (before the conditional store) are available on the LS signals*/ +#define DPORT_RECORD_PDEBUGSTATUS_INSNTYPE_WXSR2LB 0x28 /* WSR/XSR to LBEGIN */ +#define DPORT_RECORD_PDEBUGSTATUS_INSNTYPE_WSR2MMID 0x2C /* WSR to MMID */ +#define DPORT_RECORD_PDEBUGSTATUS_INSNTYPE_RWXSR 0x30 /* RSR or WSR (except MMID and LBEGIN) or XSR (except LBEGIN) */ +#define DPORT_RECORD_PDEBUGSTATUS_INSNTYPE_RWER 0x34 /* RER or WER */ +#define DPORT_RECORD_PDEBUGSTATUS_INSNTYPE_DEF 0x3C /* Default */ #define DPORT_PRO_CPU_RECORD_PDEBUGDATA_REG (DR_REG_DPORT_BASE + 0x454) /* DPORT_RECORD_PRO_PDEBUGDATA : RO ;bitpos:[31:0] ;default: 32'b0 ; */ @@ -3167,6 +3239,115 @@ #define DPORT_RECORD_PRO_PDEBUGDATA_M ((DPORT_RECORD_PRO_PDEBUGDATA_V)<<(DPORT_RECORD_PRO_PDEBUGDATA_S)) #define DPORT_RECORD_PRO_PDEBUGDATA_V 0xFFFFFFFF #define DPORT_RECORD_PRO_PDEBUGDATA_S 0 +/* register layout when bubble cycke cause is DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_DEP: + * + * HALT [17]: HALT instruction (TX only) + * MEMW [16]: MEMW, EXTW or EXCW instruction dependency + * REG [12]: register dependencies or resource (e.g.TIE ports) conflicts + * STR [11]: store release (instruction) dependency + * LSU [8] : various LSU dependencies (MHT access, prefetch, cache access insts, s32c1i, etc) + * OTHER[0] : all other hold dependencies resulting from data or resource dependencies +*/ +#define DPORT_RECORD_PDEBUGDATA_DEP_HALT (BIT(17)) +#define DPORT_RECORD_PDEBUGDATA_DEP_MEMW (BIT(16)) +#define DPORT_RECORD_PDEBUGDATA_DEP_REG (BIT(12)) +#define DPORT_RECORD_PDEBUGDATA_DEP_STR (BIT(11)) +#define DPORT_RECORD_PDEBUGDATA_DEP_LSU (BIT(8)) +#define DPORT_RECORD_PDEBUGDATA_DEP_OTHER (BIT(0)) +/* register layout when bubble cycke cause is DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_EXCn: + * + * EXCCAUSE[21..16]: Processor exception cause + * EXCVEC [4..0] : Encoded Exception Vector +*/ +#define DPORT_RECORD_PDEBUGDATA_EXCCAUSE_M ((DPORT_RECORD_PDEBUGDATA_EXCCAUSE_V)<<(DPORT_RECORD_PDEBUGDATA_EXCCAUSE_S)) +#define DPORT_RECORD_PDEBUGDATA_EXCCAUSE_V 0x3F +#define DPORT_RECORD_PDEBUGDATA_EXCCAUSE_S 16 +#define DPORT_RECORD_PDEBUGDATA_EXCCAUSE(_r_) (((_r_)>>DPORT_RECORD_PDEBUGDATA_EXCCAUSE_S) & DPORT_RECORD_PDEBUGDATA_EXCCAUSE_V) +#define DPORT_RECORD_PDEBUGDATA_EXCVEC_M ((DPORT_RECORD_PDEBUGDATA_EXCCAUSE_V)<<(DPORT_RECORD_PDEBUGDATA_EXCCAUSE_S)) +#define DPORT_RECORD_PDEBUGDATA_EXCVEC_V 0x1F +#define DPORT_RECORD_PDEBUGDATA_EXCVEC_S 0 +#define DPORT_RECORD_PDEBUGDATA_EXCVEC(_r_) (((_r_)>>DPORT_RECORD_PDEBUGDATA_EXCCAUSE_S) & DPORT_RECORD_PDEBUGDATA_EXCCAUSE_V) +#define DPORT_RECORD_PDEBUGDATA_EXCVEC_NONE 0x00 /* no vector */ +#define DPORT_RECORD_PDEBUGDATA_EXCVEC_RST 0x01 /* Reset */ +#define DPORT_RECORD_PDEBUGDATA_EXCVEC_DBG 0x02 /* Debug (repl corresp level “n”) */ +#define DPORT_RECORD_PDEBUGDATA_EXCVEC_NMI 0x03 /* NMI (repl corresp level “n”) */ +#define DPORT_RECORD_PDEBUGDATA_EXCVEC_USR 0x04 /* User */ +#define DPORT_RECORD_PDEBUGDATA_EXCVEC_KRNL 0x05 /* Kernel */ +#define DPORT_RECORD_PDEBUGDATA_EXCVEC_DBL 0x06 /* Double */ +#define DPORT_RECORD_PDEBUGDATA_EXCVEC_EMEM 0x07 /* Memory Error */ +#define DPORT_RECORD_PDEBUGDATA_EXCVEC_OVF4 0x0A /* Window Overflow 4 */ +#define DPORT_RECORD_PDEBUGDATA_EXCVEC_UNF4 0x0B /* Window Underflow 4 */ +#define DPORT_RECORD_PDEBUGDATA_EXCVEC_OVF8 0x0C /* Window Overflow 8 */ +#define DPORT_RECORD_PDEBUGDATA_EXCVEC_UNF8 0x0D /* Window Underflow 8 */ +#define DPORT_RECORD_PDEBUGDATA_EXCVEC_OVF12 0x0E /* Window Overflow 12 */ +#define DPORT_RECORD_PDEBUGDATA_EXCVEC_UNF12 0x0F /* Window Underflow 12 */ +#define DPORT_RECORD_PDEBUGDATA_EXCVEC_INT2 0x10 /* Int Level 2 (n/a if debug/NMI) */ +#define DPORT_RECORD_PDEBUGDATA_EXCVEC_INT3 0x11 /* Int Level 3 (n/a if debug/NMI) */ +#define DPORT_RECORD_PDEBUGDATA_EXCVEC_INT4 0x12 /* Int Level 4 (n/a if debug/NMI) */ +#define DPORT_RECORD_PDEBUGDATA_EXCVEC_INT5 0x13 /* Int Level 5 (n/a if debug/NMI) */ +#define DPORT_RECORD_PDEBUGDATA_EXCVEC_INT6 0x14 /* Int Level 6 (n/a if debug/NMI) */ +/* register layout when bubble cycke cause is DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_STALL: + * + * ITERDIV[19] : Iterative divide stall. + * ITERMUL[18] : Iterative multiply stall. + * BANKCONFL[16]: Bank-conflict stall. + * BPLOAD[15] : Bypass load stall. + * LSPROC[14] : Load/store miss-processing stall. + * L32R[13] : FastL32R stall. + * BPIFETCH[12] : Bypass I fetch stall. + * RUNSTALL[10] : RunStall. + * TIE[9] : TIE port stall. + * IPIF[8] : Instruction RAM inbound-PIF stall. + * IRAMBUSY[7] : Instruction RAM/ROM busy stall. + * ICM[6] : I-cache-miss stall. + * LSU[4] : The LSU will stall the pipeline under various local memory access conflict situations. + * DCM[3] : D-cache-miss stall. + * BUFFCONFL[2] : Store buffer conflict stall. + * BUFF[1] : Store buffer full stall. +*/ +#define DPORT_RECORD_PDEBUGDATA_STALL_ITERDIV (BIT(19)) +#define DPORT_RECORD_PDEBUGDATA_STALL_ITERMUL (BIT(18)) +#define DPORT_RECORD_PDEBUGDATA_STALL_BANKCONFL (BIT(16)) +#define DPORT_RECORD_PDEBUGDATA_STALL_BPLOAD (BIT(15)) +#define DPORT_RECORD_PDEBUGDATA_STALL_LSPROC (BIT(14)) +#define DPORT_RECORD_PDEBUGDATA_STALL_L32R (BIT(13)) +#define DPORT_RECORD_PDEBUGDATA_STALL_BPIFETCH (BIT(12)) +#define DPORT_RECORD_PDEBUGDATA_STALL_RUN (BIT(10)) +#define DPORT_RECORD_PDEBUGDATA_STALL_TIE (BIT(9)) +#define DPORT_RECORD_PDEBUGDATA_STALL_IPIF (BIT(8)) +#define DPORT_RECORD_PDEBUGDATA_STALL_IRAMBUSY (BIT(7)) +#define DPORT_RECORD_PDEBUGDATA_STALL_ICM (BIT(6)) +#define DPORT_RECORD_PDEBUGDATA_STALL_LSU (BIT(4)) +#define DPORT_RECORD_PDEBUGDATA_STALL_DCM (BIT(3)) +#define DPORT_RECORD_PDEBUGDATA_STALL_BUFFCONFL (BIT(2)) +#define DPORT_RECORD_PDEBUGDATA_STALL_BUFF (BIT(1)) +/* register layout for DPORT_RECORD_PDEBUGSTATUS_INSNTYPE_RWXSR: + * + * XSR[10] : XSR Instruction + * WSR[9] : WSR Instruction + * RSR[8] : RSR Instruction + * SR[7..0] : Special Register Number +*/ +#define DPORT_RECORD_PDEBUGDATA_INSNTYPE_XSR (BIT(10)) +#define DPORT_RECORD_PDEBUGDATA_INSNTYPE_WSR (BIT(9)) +#define DPORT_RECORD_PDEBUGDATA_INSNTYPE_RSR (BIT(8)) +#define DPORT_RECORD_PDEBUGDATA_INSNTYPE_SR_M ((DPORT_RECORD_PDEBUGDATA_INSNTYPE_SR_V)<<(DPORT_RECORD_PDEBUGDATA_INSNTYPE_SR_S)) +#define DPORT_RECORD_PDEBUGDATA_INSNTYPE_SR_V 0xFF +#define DPORT_RECORD_PDEBUGDATA_INSNTYPE_SR_S 0 +#define DPORT_RECORD_PDEBUGDATA_INSNTYPE_SR(_r_) (((_r_)>>DPORT_RECORD_PDEBUGDATA_INSNTYPE_SR_S) & DPORT_RECORD_PDEBUGDATA_INSNTYPE_SR_V) +/* register layout for DPORT_RECORD_PDEBUGSTATUS_INSNTYPE_RWER: + * + * ER[13..2]: ER Address + * WER[1] : WER Instruction + * RER[0] : RER Instruction +*/ +#define DPORT_RECORD_PDEBUGDATA_INSNTYPE_ER_M ((DPORT_RECORD_PDEBUGDATA_INSNTYPE_ER_V)<<(DPORT_RECORD_PDEBUGDATA_INSNTYPE_ER_S)) +#define DPORT_RECORD_PDEBUGDATA_INSNTYPE_ER_V 0xFFF +#define DPORT_RECORD_PDEBUGDATA_INSNTYPE_ER_S 2 +#define DPORT_RECORD_PDEBUGDATA_INSNTYPE_ER(_r_) (((_r_)>>DPORT_RECORD_PDEBUGDATA_INSNTYPE_ER_S) & DPORT_RECORD_PDEBUGDATA_INSNTYPE_ER_V) +#define DPORT_RECORD_PDEBUGDATA_INSNTYPE_WER (BIT(1)) +#define DPORT_RECORD_PDEBUGDATA_INSNTYPE_RER (BIT(0)) + #define DPORT_PRO_CPU_RECORD_PDEBUGPC_REG (DR_REG_DPORT_BASE + 0x458) /* DPORT_RECORD_PRO_PDEBUGPC : RO ;bitpos:[31:0] ;default: 32'b0 ; */ @@ -3183,6 +3364,68 @@ #define DPORT_RECORD_PRO_PDEBUGLS0STAT_M ((DPORT_RECORD_PRO_PDEBUGLS0STAT_V)<<(DPORT_RECORD_PRO_PDEBUGLS0STAT_S)) #define DPORT_RECORD_PRO_PDEBUGLS0STAT_V 0xFFFFFFFF #define DPORT_RECORD_PRO_PDEBUGLS0STAT_S 0 +/* register layout: + * TYPE [3..0] : Type of instruction in LS. + * SZ [7..4] : Operand size. + * DTLBM [8] : Data TLB miss. + * DCM [9] : D-cache miss. + * DCH [10] : D-cache hit. + * UC [12] : Uncached. + * WB [13] : Writeback. + * COH [16] : Coherency. + * STCOH [18..17]: Coherent state. + * TGT [23..20] : Local target. +*/ +#define DPORT_RECORD_PDEBUGLS0STAT_TYPE_M ((DPORT_RECORD_PDEBUGLS0STAT_TYPE_V)<<(DPORT_RECORD_PDEBUGLS0STAT_TYPE_S)) +#define DPORT_RECORD_PDEBUGLS0STAT_TYPE_V 0x0F +#define DPORT_RECORD_PDEBUGLS0STAT_TYPE_S 0 +#define DPORT_RECORD_PDEBUGLS0STAT_TYPE(_r_) (((_r_)>>DPORT_RECORD_PDEBUGLS0STAT_TYPE_S) & DPORT_RECORD_PDEBUGLS0STAT_TYPE_V) +#define DPORT_RECORD_PDEBUGLS0STAT_TYPE_NONE 0x00 /* neither */ +#define DPORT_RECORD_PDEBUGLS0STAT_TYPE_ITLBR 0x01 /* hw itlb refill */ +#define DPORT_RECORD_PDEBUGLS0STAT_TYPE_DTLBR 0x02 /* hw dtlb refill */ +#define DPORT_RECORD_PDEBUGLS0STAT_TYPE_LD 0x05 /* load */ +#define DPORT_RECORD_PDEBUGLS0STAT_TYPE_STR 0x06 /* store */ +#define DPORT_RECORD_PDEBUGLS0STAT_TYPE_L32R 0x08 /* l32r */ +#define DPORT_RECORD_PDEBUGLS0STAT_TYPE_S32CLI1 0x0A /* s32ci1 */ +#define DPORT_RECORD_PDEBUGLS0STAT_TYPE_CTI 0x0C /* cache test inst */ +#define DPORT_RECORD_PDEBUGLS0STAT_TYPE_RWXSR 0x0E /* rsr/wsr/xsr */ +#define DPORT_RECORD_PDEBUGLS0STAT_TYPE_RWER 0x0F /* rer/wer */ +#define DPORT_RECORD_PDEBUGLS0STAT_SZ_M ((DPORT_RECORD_PDEBUGLS0STAT_SZ_V)<<(DPORT_RECORD_PDEBUGLS0STAT_SZ_S)) +#define DPORT_RECORD_PDEBUGLS0STAT_SZ_V 0x0F +#define DPORT_RECORD_PDEBUGLS0STAT_SZ_S 4 +#define DPORT_RECORD_PDEBUGLS0STAT_SZ(_r_) (((_r_)>>DPORT_RECORD_PDEBUGLS0STAT_SZ_S) & DPORT_RECORD_PDEBUGLS0STAT_SZ_V) +#define DPORT_RECORD_PDEBUGLS0STAT_SZB(_r_) ((8<>DPORT_RECORD_PDEBUGLS0STAT_STCOH_S) & DPORT_RECORD_PDEBUGLS0STAT_STCOH_V) +#define DPORT_RECORD_PDEBUGLS0STAT_STCOH_NONE 0x0 /* neither shared nor exclusive nor modified */ +#define DPORT_RECORD_PDEBUGLS0STAT_STCOH_SHARED 0x1 /* shared */ +#define DPORT_RECORD_PDEBUGLS0STAT_STCOH_EXCL 0x2 /* exclusive */ +#define DPORT_RECORD_PDEBUGLS0STAT_STCOH_MOD 0x3 /* modified */ +#define DPORT_RECORD_PDEBUGLS0STAT_TGT_M ((DPORT_RECORD_PDEBUGLS0STAT_TGT_V)<<(DPORT_RECORD_PDEBUGLS0STAT_TGT_S)) +#define DPORT_RECORD_PDEBUGLS0STAT_TGT_V 0x0F +#define DPORT_RECORD_PDEBUGLS0STAT_TGT_S 20 +#define DPORT_RECORD_PDEBUGLS0STAT_TGT(_r_) (((_r_)>>DPORT_RECORD_PDEBUGLS0STAT_TGT_S) & DPORT_RECORD_PDEBUGLS0STAT_TGT_V) +#define DPORT_RECORD_PDEBUGLS0STAT_TGT_EXT 0x0 /* not to local memory */ +#define DPORT_RECORD_PDEBUGLS0STAT_TGT_IRAM0 0x2 /* 001x: InstRAM (0/1) */ +#define DPORT_RECORD_PDEBUGLS0STAT_TGT_IRAM1 0x3 /* 001x: InstRAM (0/1) */ +#define DPORT_RECORD_PDEBUGLS0STAT_TGT_IROM0 0x4 /* 010x: InstROM (0/1) */ +#define DPORT_RECORD_PDEBUGLS0STAT_TGT_IROM1 0x5 /* 010x: InstROM (0/1) */ +#define DPORT_RECORD_PDEBUGLS0STAT_TGT_DRAM0 0x0A /* 101x: DataRAM (0/1) */ +#define DPORT_RECORD_PDEBUGLS0STAT_TGT_DRAM1 0x0B /* 101x: DataRAM (0/1) */ +#define DPORT_RECORD_PDEBUGLS0STAT_TGT_DROM0 0xE /* 111x: DataROM (0/1) */ +#define DPORT_RECORD_PDEBUGLS0STAT_TGT_DROM1 0xF /* 111x: DataROM (0/1) */ +// #define DPORT_RECORD_PDEBUGLS0STAT_TGT_IRAM(_t_) (((_t_)&0xE)=0x2) /* 001x: InstRAM (0/1) */ +// #define DPORT_RECORD_PDEBUGLS0STAT_TGT_IROM(_t_) (((_t_)&0xE)=0x4) /* 010x: InstROM (0/1) */ +// #define DPORT_RECORD_PDEBUGLS0STAT_TGT_DRAM(_t_) (((_t_)&0xE)=0x2) /* 101x: DataRAM (0/1) */ +// #define DPORT_RECORD_PDEBUGLS0STAT_TGT_DROM(_t_) (((_t_)&0xE)=0x2) /* 111x: DataROM (0/1) */ #define DPORT_PRO_CPU_RECORD_PDEBUGLS0ADDR_REG (DR_REG_DPORT_BASE + 0x460) /* DPORT_RECORD_PRO_PDEBUGLS0ADDR : RO ;bitpos:[31:0] ;default: 32'b0 ; */ diff --git a/components/soc/esp32/include/soc/emac_ex_reg.h b/components/soc/esp32/include/soc/emac_ex_reg.h index 9b7c59096..e43217e08 100644 --- a/components/soc/esp32/include/soc/emac_ex_reg.h +++ b/components/soc/esp32/include/soc/emac_ex_reg.h @@ -23,75 +23,135 @@ extern "C" { #define EMAC_EX_CLKOUT_CONF_REG (REG_EMAC_EX_BASE + 0x0000) #define EMAC_EX_CLK_OUT_DLY_NUM 0x00000003 +#define EMAC_EX_CLK_OUT_DLY_NUM_M (EMAC_EX_CLK_OUT_DLY_NUM_V << EMAC_EX_CLK_OUT_DLY_NUM_S) +#define EMAC_EX_CLK_OUT_DLY_NUM_V 0x00000003 #define EMAC_EX_CLK_OUT_DLY_NUM_S 8 #define EMAC_EX_CLK_OUT_H_DIV_NUM 0x0000000F +#define EMAC_EX_CLK_OUT_H_DIV_NUM_M (EMAC_EX_CLK_OUT_H_DIV_NUM_V << EMAC_EX_CLK_OUT_H_DIV_NUM_S) +#define EMAC_EX_CLK_OUT_H_DIV_NUM_V 0x0000000F #define EMAC_EX_CLK_OUT_H_DIV_NUM_S 4 #define EMAC_EX_CLK_OUT_DIV_NUM 0x0000000F +#define EMAC_EX_CLK_OUT_DIV_NUM_M (EMAC_EX_CLK_OUT_DIV_NUM_V << EMAC_EX_CLK_OUT_DIV_NUM_S) +#define EMAC_EX_CLK_OUT_DIV_NUM_V 0x0000000F #define EMAC_EX_CLK_OUT_DIV_NUM_S 0 #define EMAC_EX_OSCCLK_CONF_REG (REG_EMAC_EX_BASE + 0x0004) #define EMAC_EX_OSC_CLK_SEL (BIT(24)) +#define EMAC_EX_OSC_CLK_SEL_M (BIT(24)) +#define EMAC_EX_OSC_CLK_SEL_V 1 #define EMAC_EX_OSC_CLK_SEL_S 24 #define EMAC_EX_OSC_H_DIV_NUM_100M 0x0000003F +#define EMAC_EX_OSC_H_DIV_NUM_100M_M (EMAC_EX_OSC_H_DIV_NUM_100M_V << EMAC_EX_OSC_H_DIV_NUM_100M_S) +#define EMAC_EX_OSC_H_DIV_NUM_100M_V 0x0000003F #define EMAC_EX_OSC_H_DIV_NUM_100M_S 18 #define EMAC_EX_OSC_DIV_NUM_100M 0x0000003F +#define EMAC_EX_OSC_DIV_NUM_100M_M (EMAC_EX_OSC_DIV_NUM_100M_V << EMAC_EX_OSC_DIV_NUM_100M_S) +#define EMAC_EX_OSC_DIV_NUM_100M_V 0x0000003F #define EMAC_EX_OSC_DIV_NUM_100M_S 12 #define EMAC_EX_OSC_H_DIV_NUM_10M 0x0000003F +#define EMAC_EX_OSC_H_DIV_NUM_10M_M (EMAC_EX_OSC_H_DIV_NUM_10M_V << EMAC_EX_OSC_H_DIV_NUM_10M_S) +#define EMAC_EX_OSC_H_DIV_NUM_10M_V 0x0000003F #define EMAC_EX_OSC_H_DIV_NUM_10M_S 6 #define EMAC_EX_OSC_DIV_NUM_10M 0x0000003F +#define EMAC_EX_OSC_DIV_NUM_10M_M (EMAC_EX_OSC_DIV_NUM_10M_V << EMAC_EX_OSC_DIV_NUM_10M_S) +#define EMAC_EX_OSC_DIV_NUM_10M_V 0x0000003F #define EMAC_EX_OSC_DIV_NUM_10M_S 0 #define EMAC_EX_CLK_CTRL_REG (REG_EMAC_EX_BASE + 0x0008) #define EMAC_EX_CLK_EN (BIT(5)) +#define EMAC_EX_CLK_EN_M (BIT(5)) +#define EMAC_EX_CLK_EN_V 1 #define EMAC_EX_CLK_EN_S 5 #define EMAC_EX_MII_CLK_RX_EN (BIT(4)) +#define EMAC_EX_MII_CLK_RX_EN_M (BIT(4)) +#define EMAC_EX_MII_CLK_RX_EN_V 1 #define EMAC_EX_MII_CLK_RX_EN_S 4 #define EMAC_EX_MII_CLK_TX_EN (BIT(3)) +#define EMAC_EX_MII_CLK_TX_EN_M (BIT(3)) +#define EMAC_EX_MII_CLK_TX_EN_V 1 #define EMAC_EX_MII_CLK_TX_EN_S 3 #define EMAC_EX_RX_125_CLK_EN (BIT(2)) +#define EMAC_EX_RX_125_CLK_EN_M (BIT(2)) +#define EMAC_EX_RX_125_CLK_EN_V 1 #define EMAC_EX_RX_125_CLK_EN_S 2 #define EMAC_EX_INT_OSC_EN (BIT(1)) +#define EMAC_EX_INT_OSC_EN_M (BIT(1)) +#define EMAC_EX_INT_OSC_EN_V 1 #define EMAC_EX_INT_OSC_EN_S 1 #define EMAC_EX_EXT_OSC_EN (BIT(0)) +#define EMAC_EX_EXT_OSC_EN_M (BIT(0)) +#define EMAC_EX_EXT_OSC_EN_V 1 #define EMAC_EX_EXT_OSC_EN_S 0 #define EMAC_EX_PHYINF_CONF_REG (REG_EMAC_EX_BASE + 0x000c) #define EMAC_EX_TX_ERR_OUT_EN (BIT(20)) +#define EMAC_EX_TX_ERR_OUT_EN_M (BIT(20)) +#define EMAC_EX_TX_ERR_OUT_EN_V 1 #define EMAC_EX_TX_ERR_OUT_EN_S 20 #define EMAC_EX_SCR_SMI_DLY_RX_SYNC (BIT(19)) +#define EMAC_EX_SCR_SMI_DLY_RX_SYNC_M (BIT(19)) +#define EMAC_EX_SCR_SMI_DLY_RX_SYNC_V 1 #define EMAC_EX_SCR_SMI_DLY_RX_SYNC_S 19 #define EMAC_EX_PMT_CTRL_EN (BIT(18)) +#define EMAC_EX_PMT_CTRL_EN_M (BIT(18)) +#define EMAC_EX_PMT_CTRL_EN_V 1 #define EMAC_EX_PMT_CTRL_EN_S 18 #define EMAC_EX_SBD_CLK_GATING_EN (BIT(17)) +#define EMAC_EX_SBD_CLK_GATING_EN_M (BIT(17)) +#define EMAC_EX_SBD_CLK_GATING_EN_V 1 #define EMAC_EX_SBD_CLK_GATING_EN_S 17 #define EMAC_EX_SS_MODE (BIT(16)) +#define EMAC_EX_SS_MODE_M (BIT(16)) +#define EMAC_EX_SS_MODE_V 1 #define EMAC_EX_SS_MODE_S 16 #define EMAC_EX_PHY_INTF_SEL 0x00000007 +#define EMAC_EX_PHY_INTF_SEL_M (EMAC_EX_PHY_INTF_SEL_V << EMAC_EX_PHY_INTF_SEL_S) +#define EMAC_EX_PHY_INTF_SEL_V 0x00000007 #define EMAC_EX_PHY_INTF_SEL_S 13 #define EMAC_EX_REVMII_PHY_ADDR 0x0000001F +#define EMAC_EX_REVMII_PHY_ADDR_M (EMAC_EX_REVMII_PHY_ADDR_V << EMAC_EX_REVMII_PHY_ADDR_S) +#define EMAC_EX_REVMII_PHY_ADDR_V 0x0000001F #define EMAC_EX_REVMII_PHY_ADDR_S 8 #define EMAC_EX_CORE_PHY_ADDR 0x0000001F +#define EMAC_EX_CORE_PHY_ADDR_M (EMAC_EX_CORE_PHY_ADDR_V << EMAC_EX_CORE_PHY_ADDR_S) +#define EMAC_EX_CORE_PHY_ADDR_V 0x0000001F #define EMAC_EX_CORE_PHY_ADDR_S 3 #define EMAC_EX_SBD_FLOWCTRL (BIT(2)) +#define EMAC_EX_SBD_FLOWCTRL_M (BIT(2)) +#define EMAC_EX_SBD_FLOWCTRL_V 1 #define EMAC_EX_SBD_FLOWCTRL_S 2 #define EMAC_EX_EXT_REVMII_RX_CLK_SEL (BIT(1)) +#define EMAC_EX_EXT_REVMII_RX_CLK_SEL_M (BIT(1)) +#define EMAC_EX_EXT_REVMII_RX_CLK_SEL_V 1 #define EMAC_EX_EXT_REVMII_RX_CLK_SEL_S 1 #define EMAC_EX_INT_REVMII_RX_CLK_SEL (BIT(0)) +#define EMAC_EX_INT_REVMII_RX_CLK_SEL_M (BIT(0)) +#define EMAC_EX_INT_REVMII_RX_CLK_SEL_V 1 #define EMAC_EX_INT_REVMII_RX_CLK_SEL_S 0 #define EMAC_EX_PHY_INTF_RMII 4 #define EMAC_EX_EMAC_PD_SEL_REG (REG_EMAC_EX_BASE + 0x0010) #define EMAC_EX_RAM_PD_EN 0x00000003 +#define EMAC_EX_RAM_PD_EN_M (EMAC_EX_RAM_PD_EN_V << EMAC_EX_RAM_PD_EN_S) +#define EMAC_EX_RAM_PD_EN_V 0x00000003 #define EMAC_EX_RAM_PD_EN_S 0 #define EMAC_EX_DATE_REG (REG_EMAC_EX_BASE + 0x00fc) #define EMAC_EX_DATE 0xFFFFFFFF +#define EMAC_EX_DATE_M (EMAC_EX_DATE_V << EMAC_EX_DATE_S) +#define EMAC_EX_DATE_V 0xFFFFFFFF #define EMAC_EX_DATE_S 0 #define EMAC_EX_DATE_VERSION 0x16042200 +#define EMAC_EX_DATE_VERSION_M (EMAC_EX_DATE_VERSION_V << EMAC_EX_DATE_VERSION_S) +#define EMAC_EX_DATE_VERSION_V 0x16042200 #define EMAC_CLK_EN_REG 0x3ff000cc +#define EMAC_CLK_EN_REG_M (EMAC_CLK_EN_REG_V << EMAC_CLK_EN_REG_S) +#define EMAC_CLK_EN_REG_V 0x3ff000cc #define EMAC_CLK_EN (BIT(14)) +#define EMAC_CLK_EN_M (BIT(14)) +#define EMAC_CLK_EN_V 1 #ifdef __cplusplus } diff --git a/components/soc/esp32/include/soc/emac_reg_v2.h b/components/soc/esp32/include/soc/emac_reg_v2.h index 6ab1afe03..a33ce44ad 100644 --- a/components/soc/esp32/include/soc/emac_reg_v2.h +++ b/components/soc/esp32/include/soc/emac_reg_v2.h @@ -24,686 +24,1256 @@ extern "C" { #define EMAC_DMABUSMODE_REG (REG_EMAC_BASE + 0x0000) #define EMAC_DMAREBINCRBURST (BIT(31)) +#define EMAC_DMAREBINCRBURST_M (BIT(31)) +#define EMAC_DMAREBINCRBURST_V 1 #define EMAC_DMAREBINCRBURST_S 31 #define EMAC_DMACHANNELPRIOWT 0x00000003 +#define EMAC_DMACHANNELPRIOWT_M (EMAC_DMACHANNELPRIOWT_V << EMAC_DMACHANNELPRIOWT_S) +#define EMAC_DMACHANNELPRIOWT_V 0x00000003 #define EMAC_DMACHANNELPRIOWT_S 28 #define EMAC_DMATXRXPRIO (BIT(27)) +#define EMAC_DMATXRXPRIO_M (BIT(27)) +#define EMAC_DMATXRXPRIO_V 1 #define EMAC_DMATXRXPRIO_S 27 #define EMAC_DMAMIXEDBURST (BIT(26)) +#define EMAC_DMAMIXEDBURST_M (BIT(26)) +#define EMAC_DMAMIXEDBURST_V 1 #define EMAC_DMAMIXEDBURST_S 26 #define EMAC_DMAADDRALIBEA (BIT(25)) +#define EMAC_DMAADDRALIBEA_M (BIT(25)) +#define EMAC_DMAADDRALIBEA_V 1 #define EMAC_DMAADDRALIBEA_S 25 #define EMAC_PBLX8_MODE (BIT(24)) +#define EMAC_PBLX8_MODE_M (BIT(24)) +#define EMAC_PBLX8_MODE_V 1 #define EMAC_PBLX8_MODE_S 24 #define EMAC_USE_SEP_PBL (BIT(23)) +#define EMAC_USE_SEP_PBL_M (BIT(23)) +#define EMAC_USE_SEP_PBL_V 1 #define EMAC_USE_SEP_PBL_S 23 #define EMAC_RX_DMA_PBL 0x0000003F +#define EMAC_RX_DMA_PBL_M (EMAC_RX_DMA_PBL_V << EMAC_RX_DMA_PBL_S) +#define EMAC_RX_DMA_PBL_V 0x0000003F #define EMAC_RX_DMA_PBL_S 17 #define EMAC_FIXED_BURST (BIT(16)) +#define EMAC_FIXED_BURST_M (BIT(16)) +#define EMAC_FIXED_BURST_V 1 #define EMAC_FIXED_BURST_S 16 #define EMAC_PRI_RATIO 0x00000003 +#define EMAC_PRI_RATIO_M (EMAC_PRI_RATIO_V << EMAC_PRI_RATIO_S) +#define EMAC_PRI_RATIO_V 0x00000003 #define EMAC_PRI_RATIO_S 14 #define EMAC_PROG_BURST_LEN 0x0000003F +#define EMAC_PROG_BURST_LEN_M (EMAC_PROG_BURST_LEN_V << EMAC_PROG_BURST_LEN_S) +#define EMAC_PROG_BURST_LEN_V 0x0000003F #define EMAC_PROG_BURST_LEN_S 8 #define EMAC_ALT_DESC_SIZE (BIT(7)) +#define EMAC_ALT_DESC_SIZE_M (BIT(7)) +#define EMAC_ALT_DESC_SIZE_V 1 #define EMAC_ALT_DESC_SIZE_S 7 #define EMAC_DESC_SKIP_LEN 0x0000001F +#define EMAC_DESC_SKIP_LEN_M (EMAC_DESC_SKIP_LEN_V << EMAC_DESC_SKIP_LEN_S) +#define EMAC_DESC_SKIP_LEN_V 0x0000001F #define EMAC_DESC_SKIP_LEN_S 2 #define EMAC_DMA_ARB_SCH (BIT(1)) +#define EMAC_DMA_ARB_SCH_M (BIT(1)) +#define EMAC_DMA_ARB_SCH_V 1 #define EMAC_DMA_ARB_SCH_S 1 #define EMAC_SW_RST (BIT(0)) +#define EMAC_SW_RST_M (BIT(0)) +#define EMAC_SW_RST_V 1 #define EMAC_SW_RST_S 0 #define EMAC_DMATXPOLLDEMAND_REG (REG_EMAC_BASE + 0x0004) #define EMAC_TRANS_POLL_DEMAND 0xFFFFFFFF +#define EMAC_TRANS_POLL_DEMAND_M (EMAC_TRANS_POLL_DEMAND_V << EMAC_TRANS_POLL_DEMAND_S) +#define EMAC_TRANS_POLL_DEMAND_V 0xFFFFFFFF #define EMAC_TRANS_POLL_DEMAND_S 0 #define EMAC_DMARXPOLLDEMAND_REG (REG_EMAC_BASE + 0x0008) #define EMAC_RECV_POLL_DEMAND 0xFFFFFFFF +#define EMAC_RECV_POLL_DEMAND_M (EMAC_RECV_POLL_DEMAND_V << EMAC_RECV_POLL_DEMAND_S) +#define EMAC_RECV_POLL_DEMAND_V 0xFFFFFFFF #define EMAC_RECV_POLL_DEMAND_S 0 #define EMAC_DMARXBASEADDR_REG (REG_EMAC_BASE + 0x000C) #define EMAC_START_RECV_LIST 0xFFFFFFFF +#define EMAC_START_RECV_LIST_M (EMAC_START_RECV_LIST_V << EMAC_START_RECV_LIST_S) +#define EMAC_START_RECV_LIST_V 0xFFFFFFFF #define EMAC_START_RECV_LIST_S 0 #define EMAC_DMATXBASEADDR_REG (REG_EMAC_BASE + 0x0010) #define EMAC_START_TRANS_LIST 0xFFFFFFFF +#define EMAC_START_TRANS_LIST_M (EMAC_START_TRANS_LIST_V << EMAC_START_TRANS_LIST_S) +#define EMAC_START_TRANS_LIST_V 0xFFFFFFFF #define EMAC_START_TRANS_LIST_S 0 #define EMAC_DMASTATUS_REG (REG_EMAC_BASE + 0x0014) #define EMAC_GMAC_LPI_INT (BIT(30)) +#define EMAC_GMAC_LPI_INT_M (BIT(30)) +#define EMAC_GMAC_LPI_INT_V 1 #define EMAC_GMAC_LPI_INT_S 30 #define EMAC_TS_TRI_INT (BIT(29)) +#define EMAC_TS_TRI_INT_M (BIT(29)) +#define EMAC_TS_TRI_INT_V 1 #define EMAC_TS_TRI_INT_S 29 #define EMAC_GMAC_PMT_INT (BIT(28)) +#define EMAC_GMAC_PMT_INT_M (BIT(28)) +#define EMAC_GMAC_PMT_INT_V 1 #define EMAC_GMAC_PMT_INT_S 28 #define EMAC_GMAC_MMC_INT (BIT(27)) +#define EMAC_GMAC_MMC_INT_M (BIT(27)) +#define EMAC_GMAC_MMC_INT_V 1 #define EMAC_GMAC_MMC_INT_S 27 #define EMAC_GMAC_LINE_INF_INT (BIT(26)) +#define EMAC_GMAC_LINE_INF_INT_M (BIT(26)) +#define EMAC_GMAC_LINE_INF_INT_V 1 #define EMAC_GMAC_LINE_INF_INT_S 26 #define EMAC_ERROR_BITS 0x00000007 +#define EMAC_ERROR_BITS_M (EMAC_ERROR_BITS_V << EMAC_ERROR_BITS_S) +#define EMAC_ERROR_BITS_V 0x00000007 #define EMAC_ERROR_BITS_S 23 #define EMAC_TRANS_PROC_STATE 0x00000007 +#define EMAC_TRANS_PROC_STATE_M (EMAC_TRANS_PROC_STATE_V << EMAC_TRANS_PROC_STATE_S) +#define EMAC_TRANS_PROC_STATE_V 0x00000007 #define EMAC_TRANS_PROC_STATE_S 20 #define EMAC_RECV_PROC_STATE 0x00000007 +#define EMAC_RECV_PROC_STATE_M (EMAC_RECV_PROC_STATE_V << EMAC_RECV_PROC_STATE_S) +#define EMAC_RECV_PROC_STATE_V 0x00000007 #define EMAC_RECV_PROC_STATE_S 17 #define EMAC_NORM_INT_SUMM (BIT(16)) +#define EMAC_NORM_INT_SUMM_M (BIT(16)) +#define EMAC_NORM_INT_SUMM_V 1 #define EMAC_NORM_INT_SUMM_S 16 #define EMAC_ABN_INT_SUMM (BIT(15)) +#define EMAC_ABN_INT_SUMM_M (BIT(15)) +#define EMAC_ABN_INT_SUMM_V 1 #define EMAC_ABN_INT_SUMM_S 15 #define EMAC_EARLY_RECV_INT (BIT(14)) +#define EMAC_EARLY_RECV_INT_M (BIT(14)) +#define EMAC_EARLY_RECV_INT_V 1 #define EMAC_EARLY_RECV_INT_S 14 #define EMAC_FATAL_BUS_ERR_INT (BIT(13)) +#define EMAC_FATAL_BUS_ERR_INT_M (BIT(13)) +#define EMAC_FATAL_BUS_ERR_INT_V 1 #define EMAC_FATAL_BUS_ERR_INT_S 13 #define EMAC_EARLY_TRANS_INT (BIT(10)) +#define EMAC_EARLY_TRANS_INT_M (BIT(10)) +#define EMAC_EARLY_TRANS_INT_V 1 #define EMAC_EARLY_TRANS_INT_S 10 #define EMAC_RECV_WDT_TO (BIT(9)) +#define EMAC_RECV_WDT_TO_M (BIT(9)) +#define EMAC_RECV_WDT_TO_V 1 #define EMAC_RECV_WDT_TO_S 9 #define EMAC_RECV_PROC_STOP (BIT(8)) +#define EMAC_RECV_PROC_STOP_M (BIT(8)) +#define EMAC_RECV_PROC_STOP_V 1 #define EMAC_RECV_PROC_STOP_S 8 #define EMAC_RECV_BUF_UNAVAIL (BIT(7)) +#define EMAC_RECV_BUF_UNAVAIL_M (BIT(7)) +#define EMAC_RECV_BUF_UNAVAIL_V 1 #define EMAC_RECV_BUF_UNAVAIL_S 7 #define EMAC_RECV_INT (BIT(6)) +#define EMAC_RECV_INT_M (BIT(6)) +#define EMAC_RECV_INT_V 1 #define EMAC_RECV_INT_S 6 #define EMAC_TRANS_UNDFLOW (BIT(5)) +#define EMAC_TRANS_UNDFLOW_M (BIT(5)) +#define EMAC_TRANS_UNDFLOW_V 1 #define EMAC_TRANS_UNDFLOW_S 5 #define EMAC_RECV_OVFLOW (BIT(4)) +#define EMAC_RECV_OVFLOW_M (BIT(4)) +#define EMAC_RECV_OVFLOW_V 1 #define EMAC_RECV_OVFLOW_S 4 #define EMAC_TRANS_JABBER_TO (BIT(3)) +#define EMAC_TRANS_JABBER_TO_M (BIT(3)) +#define EMAC_TRANS_JABBER_TO_V 1 #define EMAC_TRANS_JABBER_TO_S 3 #define EMAC_TRANS_BUF_UNAVAIL (BIT(2)) +#define EMAC_TRANS_BUF_UNAVAIL_M (BIT(2)) +#define EMAC_TRANS_BUF_UNAVAIL_V 1 #define EMAC_TRANS_BUF_UNAVAIL_S 2 #define EMAC_TRANS_PROC_STOP (BIT(1)) +#define EMAC_TRANS_PROC_STOP_M (BIT(1)) +#define EMAC_TRANS_PROC_STOP_V 1 #define EMAC_TRANS_PROC_STOP_S 1 #define EMAC_TRANS_INT (BIT(0)) +#define EMAC_TRANS_INT_M (BIT(0)) +#define EMAC_TRANS_INT_V 1 #define EMAC_TRANS_INT_S 0 #define EMAC_DMAOPERATION_MODE_REG (REG_EMAC_BASE + 0x0018) #define EMAC_DIS_DROP_TCPIP_CHKSUM_ERR_FRAM (BIT(26)) +#define EMAC_DIS_DROP_TCPIP_CHKSUM_ERR_FRAM_M (BIT(26)) +#define EMAC_DIS_DROP_TCPIP_CHKSUM_ERR_FRAM_V 1 #define EMAC_DIS_DROP_TCPIP_CHKSUM_ERR_FRAM_S 26 #define EMAC_RECV_STORE_FORWARD (BIT(25)) +#define EMAC_RECV_STORE_FORWARD_M (BIT(25)) +#define EMAC_RECV_STORE_FORWARD_V 1 #define EMAC_RECV_STORE_FORWARD_S 25 #define EMAC_DIS_FLUSH_RECV_FRAMES (BIT(24)) +#define EMAC_DIS_FLUSH_RECV_FRAMES_M (BIT(24)) +#define EMAC_DIS_FLUSH_RECV_FRAMES_V 1 #define EMAC_DIS_FLUSH_RECV_FRAMES_S 24 #define EMAC_MSB_THRESHOLD_ACTIVATING_FLOW_CONTROL (BIT(23)) +#define EMAC_MSB_THRESHOLD_ACTIVATING_FLOW_CONTROL_M (BIT(23)) +#define EMAC_MSB_THRESHOLD_ACTIVATING_FLOW_CONTROL_V 1 #define EMAC_MSB_THRESHOLD_ACTIVATING_FLOW_CONTROL_S 23 #define EMAC_MSB_THRESHOLD_DEACTIVATING_FLOW_CONTROL (BIT(22)) +#define EMAC_MSB_THRESHOLD_DEACTIVATING_FLOW_CONTROL_M (BIT(22)) +#define EMAC_MSB_THRESHOLD_DEACTIVATING_FLOW_CONTROL_V 1 #define EMAC_MSB_THRESHOLD_DEACTIVATING_FLOW_CONTROL_S 22 #define EMAC_TRANSMIT_STORE_FORWARD (BIT(21)) +#define EMAC_TRANSMIT_STORE_FORWARD_M (BIT(21)) +#define EMAC_TRANSMIT_STORE_FORWARD_V 1 #define EMAC_TRANSMIT_STORE_FORWARD_S 21 #define EMAC_FLUSH_TRANSMIT_FIFO (BIT(20)) +#define EMAC_FLUSH_TRANSMIT_FIFO_M (BIT(20)) +#define EMAC_FLUSH_TRANSMIT_FIFO_V 1 #define EMAC_FLUSH_TRANSMIT_FIFO_S 20 #define EMAC_TRANSMIT_THRESHOLD_CONTROL 0x00000007 +#define EMAC_TRANSMIT_THRESHOLD_CONTROL_M (EMAC_TRANSMIT_THRESHOLD_CONTROL_V << EMAC_TRANSMIT_THRESHOLD_CONTROL_S) +#define EMAC_TRANSMIT_THRESHOLD_CONTROL_V 0x00000007 #define EMAC_TRANSMIT_THRESHOLD_CONTROL_S 14 #define EMAC_START_STOP_TRANSMISSION_COMMAND (BIT(13)) +#define EMAC_START_STOP_TRANSMISSION_COMMAND_M (BIT(13)) +#define EMAC_START_STOP_TRANSMISSION_COMMAND_V 1 #define EMAC_START_STOP_TRANSMISSION_COMMAND_S 13 #define EMAC_THRESHOLD_DEACTIVATING_FLOW_CONTROL 0x00000003 +#define EMAC_THRESHOLD_DEACTIVATING_FLOW_CONTROL_M (EMAC_THRESHOLD_DEACTIVATING_FLOW_CONTROL_V << EMAC_THRESHOLD_DEACTIVATING_FLOW_CONTROL_S) +#define EMAC_THRESHOLD_DEACTIVATING_FLOW_CONTROL_V 0x00000003 #define EMAC_THRESHOLD_DEACTIVATING_FLOW_CONTROL_S 11 #define EMAC_THRESHOLD_ACTIVATING_FLOW_CONTROL 0x00000003 +#define EMAC_THRESHOLD_ACTIVATING_FLOW_CONTROL_M (EMAC_THRESHOLD_ACTIVATING_FLOW_CONTROL_V << EMAC_THRESHOLD_ACTIVATING_FLOW_CONTROL_S) +#define EMAC_THRESHOLD_ACTIVATING_FLOW_CONTROL_V 0x00000003 #define EMAC_THRESHOLD_ACTIVATING_FLOW_CONTROL_S 9 #define EMAC_ENABLE_HW_FLOW_CONTROL (BIT(8)) +#define EMAC_ENABLE_HW_FLOW_CONTROL_M (BIT(8)) +#define EMAC_ENABLE_HW_FLOW_CONTROL_V 1 #define EMAC_ENABLE_HW_FLOW_CONTROL_S 8 #define EMAC_FORWARD_ERROR_FRAMES (BIT(7)) +#define EMAC_FORWARD_ERROR_FRAMES_M (BIT(7)) +#define EMAC_FORWARD_ERROR_FRAMES_V 1 #define EMAC_FORWARD_ERROR_FRAMES_S 7 #define EMAC_FORWARD_UNDERSIZED_GOOD_FRAMES (BIT(6)) +#define EMAC_FORWARD_UNDERSIZED_GOOD_FRAMES_M (BIT(6)) +#define EMAC_FORWARD_UNDERSIZED_GOOD_FRAMES_V 1 #define EMAC_FORWARD_UNDERSIZED_GOOD_FRAMES_S 6 #define EMAC_DROP_GIANT_FRAMES (BIT(5)) +#define EMAC_DROP_GIANT_FRAMES_M (BIT(5)) +#define EMAC_DROP_GIANT_FRAMES_V 1 #define EMAC_DROP_GIANT_FRAMES_S 5 #define EMAC_RECEIVE_THRESHOLD_CONTROL 0x00000003 +#define EMAC_RECEIVE_THRESHOLD_CONTROL_M (EMAC_RECEIVE_THRESHOLD_CONTROL_V << EMAC_RECEIVE_THRESHOLD_CONTROL_S) +#define EMAC_RECEIVE_THRESHOLD_CONTROL_V 0x00000003 #define EMAC_RECEIVE_THRESHOLD_CONTROL_S 3 #define EMAC_OPERATE_SECOND_FRAME (BIT(2)) +#define EMAC_OPERATE_SECOND_FRAME_M (BIT(2)) +#define EMAC_OPERATE_SECOND_FRAME_V 1 #define EMAC_OPERATE_SECOND_FRAME_S 2 #define EMAC_START_STOP_RECEIVE (BIT(1)) +#define EMAC_START_STOP_RECEIVE_M (BIT(1)) +#define EMAC_START_STOP_RECEIVE_V 1 #define EMAC_START_STOP_RECEIVE_S 1 #define EMAC_DMAINTERRUPT_EN_REG (REG_EMAC_BASE + 0x001C) #define EMAC_NORMAL_INTERRUPT_SUMMARY_ENABLE (BIT(16)) +#define EMAC_NORMAL_INTERRUPT_SUMMARY_ENABLE_M (BIT(16)) +#define EMAC_NORMAL_INTERRUPT_SUMMARY_ENABLE_V 1 #define EMAC_NORMAL_INTERRUPT_SUMMARY_ENABLE_S 16 #define EMAC_ABNORMAL_INTERRUPT_SUMMARY_ENABLE (BIT(15)) +#define EMAC_ABNORMAL_INTERRUPT_SUMMARY_ENABLE_M (BIT(15)) +#define EMAC_ABNORMAL_INTERRUPT_SUMMARY_ENABLE_V 1 #define EMAC_ABNORMAL_INTERRUPT_SUMMARY_ENABLE_S 15 #define EMAC_EARLY_RECEIVE_INTERRUPT_ENABLE (BIT(14)) +#define EMAC_EARLY_RECEIVE_INTERRUPT_ENABLE_M (BIT(14)) +#define EMAC_EARLY_RECEIVE_INTERRUPT_ENABLE_V 1 #define EMAC_EARLY_RECEIVE_INTERRUPT_ENABLE_S 14 #define EMAC_FATAL_BUS_ERROR_ENABLE (BIT(13)) +#define EMAC_FATAL_BUS_ERROR_ENABLE_M (BIT(13)) +#define EMAC_FATAL_BUS_ERROR_ENABLE_V 1 #define EMAC_FATAL_BUS_ERROR_ENABLE_S 13 #define EMAC_EARLY_TRANSMIT_INTERRUPT_ENABLE (BIT(10)) +#define EMAC_EARLY_TRANSMIT_INTERRUPT_ENABLE_M (BIT(10)) +#define EMAC_EARLY_TRANSMIT_INTERRUPT_ENABLE_V 1 #define EMAC_EARLY_TRANSMIT_INTERRUPT_ENABLE_S 10 #define EMAC_RECEIVE_WATCHDOG_TIMEOUT_ENABLE (BIT(9)) +#define EMAC_RECEIVE_WATCHDOG_TIMEOUT_ENABLE_M (BIT(9)) +#define EMAC_RECEIVE_WATCHDOG_TIMEOUT_ENABLE_V 1 #define EMAC_RECEIVE_WATCHDOG_TIMEOUT_ENABLE_S 9 #define EMAC_RECEIVE_STOPPED_ENABLE (BIT(8)) +#define EMAC_RECEIVE_STOPPED_ENABLE_M (BIT(8)) +#define EMAC_RECEIVE_STOPPED_ENABLE_V 1 #define EMAC_RECEIVE_STOPPED_ENABLE_S 8 #define EMAC_RECEIVE_BUFFER_UNAVAILABLE_ENABLE (BIT(7)) +#define EMAC_RECEIVE_BUFFER_UNAVAILABLE_ENABLE_M (BIT(7)) +#define EMAC_RECEIVE_BUFFER_UNAVAILABLE_ENABLE_V 1 #define EMAC_RECEIVE_BUFFER_UNAVAILABLE_ENABLE_S 7 #define EMAC_RECEIVE_INTERRUPT_ENABLE (BIT(6)) +#define EMAC_RECEIVE_INTERRUPT_ENABLE_M (BIT(6)) +#define EMAC_RECEIVE_INTERRUPT_ENABLE_V 1 #define EMAC_RECEIVE_INTERRUPT_ENABLE_S 6 #define EMAC_UNDERFLOW_INTERRUPT_ENABLE (BIT(5)) +#define EMAC_UNDERFLOW_INTERRUPT_ENABLE_M (BIT(5)) +#define EMAC_UNDERFLOW_INTERRUPT_ENABLE_V 1 #define EMAC_UNDERFLOW_INTERRUPT_ENABLE_S 5 #define EMAC_OVERFLOW_INTERRUPT_ENABLE (BIT(4)) +#define EMAC_OVERFLOW_INTERRUPT_ENABLE_M (BIT(4)) +#define EMAC_OVERFLOW_INTERRUPT_ENABLE_V 1 #define EMAC_OVERFLOW_INTERRUPT_ENABLE_S 4 #define EMAC_TRANSMIT_JABBER_TIMEOUT_ENABLE (BIT(3)) +#define EMAC_TRANSMIT_JABBER_TIMEOUT_ENABLE_M (BIT(3)) +#define EMAC_TRANSMIT_JABBER_TIMEOUT_ENABLE_V 1 #define EMAC_TRANSMIT_JABBER_TIMEOUT_ENABLE_S 3 #define EMAC_TRANSMIT_BUFFER_UNAVAILABLE_ENABLE (BIT(2)) +#define EMAC_TRANSMIT_BUFFER_UNAVAILABLE_ENABLE_M (BIT(2)) +#define EMAC_TRANSMIT_BUFFER_UNAVAILABLE_ENABLE_V 1 #define EMAC_TRANSMIT_BUFFER_UNAVAILABLE_ENABLE_S 2 #define EMAC_TRANSMIT_STOPPED_ENABLE (BIT(1)) +#define EMAC_TRANSMIT_STOPPED_ENABLE_M (BIT(1)) +#define EMAC_TRANSMIT_STOPPED_ENABLE_V 1 #define EMAC_TRANSMIT_STOPPED_ENABLE_S 1 #define EMAC_TRANSMIT_INTERRUPT_ENABLE (BIT(0)) +#define EMAC_TRANSMIT_INTERRUPT_ENABLE_M (BIT(0)) +#define EMAC_TRANSMIT_INTERRUPT_ENABLE_V 1 #define EMAC_TRANSMIT_INTERRUPT_ENABLE_S 0 #define EMAC_DMAMISSEDFR_REG (REG_EMAC_BASE + 0x0020) #define EMAC_OVERFLOW_BIT_FIFO_OVERFLOW_COUNTER (BIT(28)) +#define EMAC_OVERFLOW_BIT_FIFO_OVERFLOW_COUNTER_M (BIT(28)) +#define EMAC_OVERFLOW_BIT_FIFO_OVERFLOW_COUNTER_V 1 #define EMAC_OVERFLOW_BIT_FIFO_OVERFLOW_COUNTER_S 28 #define EMAC_OVERFLOW_FRAME_COUNTER 0x000007FF +#define EMAC_OVERFLOW_FRAME_COUNTER_M (EMAC_OVERFLOW_FRAME_COUNTER_V << EMAC_OVERFLOW_FRAME_COUNTER_S) +#define EMAC_OVERFLOW_FRAME_COUNTER_V 0x000007FF #define EMAC_OVERFLOW_FRAME_COUNTER_S 17 #define EMAC_OVERFLOW_BIT_MISSED_FRAME_COUNTER (BIT(16)) +#define EMAC_OVERFLOW_BIT_MISSED_FRAME_COUNTER_M (BIT(16)) +#define EMAC_OVERFLOW_BIT_MISSED_FRAME_COUNTER_V 1 #define EMAC_OVERFLOW_BIT_MISSED_FRAME_COUNTER_S 16 #define EMAC_MISSED_FRAME_COUNTER 0x0000FFFF +#define EMAC_MISSED_FRAME_COUNTER_M (EMAC_MISSED_FRAME_COUNTER_V << EMAC_MISSED_FRAME_COUNTER_S) +#define EMAC_MISSED_FRAME_COUNTER_V 0x0000FFFF #define EMAC_MISSED_FRAME_COUNTER_S 0 #define EMAC_DMARECEIVE_INTERRUPT_WATCHDOG_TIMER_REG (REG_EMAC_BASE + 0x0024) #define EMAC_RI_WATCHDOG_TIMER_COUNT 0x000000FF +#define EMAC_RI_WATCHDOG_TIMER_COUNT_M (EMAC_RI_WATCHDOG_TIMER_COUNT_V << EMAC_RI_WATCHDOG_TIMER_COUNT_S) +#define EMAC_RI_WATCHDOG_TIMER_COUNT_V 0x000000FF #define EMAC_RI_WATCHDOG_TIMER_COUNT_S 0 #define EMAC_DMATXCURRDESC_REG (REG_EMAC_BASE + 0x0048) #define EMAC_HOST_TRANSMIT_DESCRIPTOR_ADDRESS_POINTER 0xFFFFFFFF +#define EMAC_HOST_TRANSMIT_DESCRIPTOR_ADDRESS_POINTER_M (EMAC_HOST_TRANSMIT_DESCRIPTOR_ADDRESS_POINTER_V << EMAC_HOST_TRANSMIT_DESCRIPTOR_ADDRESS_POINTER_S) +#define EMAC_HOST_TRANSMIT_DESCRIPTOR_ADDRESS_POINTER_V 0xFFFFFFFF #define EMAC_HOST_TRANSMIT_DESCRIPTOR_ADDRESS_POINTER_S 0 #define EMAC_DMARXCURRDESC_REG (REG_EMAC_BASE + 0x004C) #define EMAC_HOST_RECEIVE_DESCRIPTOR_ADDRESS_POINTER 0xFFFFFFFF +#define EMAC_HOST_RECEIVE_DESCRIPTOR_ADDRESS_POINTER_M (EMAC_HOST_RECEIVE_DESCRIPTOR_ADDRESS_POINTER_V << EMAC_HOST_RECEIVE_DESCRIPTOR_ADDRESS_POINTER_S) +#define EMAC_HOST_RECEIVE_DESCRIPTOR_ADDRESS_POINTER_V 0xFFFFFFFF #define EMAC_HOST_RECEIVE_DESCRIPTOR_ADDRESS_POINTER_S 0 #define EMAC_DMATXCURRADDR_BUF_REG (REG_EMAC_BASE + 0x0050) #define EMAC_HOST_TRANSMIT_BUFFER_ADDRESS_POINTER 0xFFFFFFFF +#define EMAC_HOST_TRANSMIT_BUFFER_ADDRESS_POINTER_M (EMAC_HOST_TRANSMIT_BUFFER_ADDRESS_POINTER_V << EMAC_HOST_TRANSMIT_BUFFER_ADDRESS_POINTER_S) +#define EMAC_HOST_TRANSMIT_BUFFER_ADDRESS_POINTER_V 0xFFFFFFFF #define EMAC_HOST_TRANSMIT_BUFFER_ADDRESS_POINTER_S 0 #define EMAC_DMARXCURRADDR_BUF_REG (REG_EMAC_BASE + 0x0054) #define EMAC_HOST_RECEIVE_BUFFER_ADDRESS_POINTER 0xFFFFFFFF +#define EMAC_HOST_RECEIVE_BUFFER_ADDRESS_POINTER_M (EMAC_HOST_RECEIVE_BUFFER_ADDRESS_POINTER_V << EMAC_HOST_RECEIVE_BUFFER_ADDRESS_POINTER_S) +#define EMAC_HOST_RECEIVE_BUFFER_ADDRESS_POINTER_V 0xFFFFFFFF #define EMAC_HOST_RECEIVE_BUFFER_ADDRESS_POINTER_S 0 #define EMAC_DMAHWFEATURE_REG (REG_EMAC_BASE + 0x0058) #define EMAC_SELECTED_PHY_INTERFACE 0x00000007 +#define EMAC_SELECTED_PHY_INTERFACE_M (EMAC_SELECTED_PHY_INTERFACE_V << EMAC_SELECTED_PHY_INTERFACE_S) +#define EMAC_SELECTED_PHY_INTERFACE_V 0x00000007 #define EMAC_SELECTED_PHY_INTERFACE_S 28 #define EMAC_SOURCE_ADDRESS_VLAN_INSERTION (BIT(27)) +#define EMAC_SOURCE_ADDRESS_VLAN_INSERTION_M (BIT(27)) +#define EMAC_SOURCE_ADDRESS_VLAN_INSERTION_V 1 #define EMAC_SOURCE_ADDRESS_VLAN_INSERTION_S 27 #define EMAC_FLEXIBLE_PULSE_PER_SECOND_OUTPUT (BIT(26)) +#define EMAC_FLEXIBLE_PULSE_PER_SECOND_OUTPUT_M (BIT(26)) +#define EMAC_FLEXIBLE_PULSE_PER_SECOND_OUTPUT_V 1 #define EMAC_FLEXIBLE_PULSE_PER_SECOND_OUTPUT_S 26 #define EMAC_TIMESTAMPING_INTERNAL_SYSTEM_TIME (BIT(25)) +#define EMAC_TIMESTAMPING_INTERNAL_SYSTEM_TIME_M (BIT(25)) +#define EMAC_TIMESTAMPING_INTERNAL_SYSTEM_TIME_V 1 #define EMAC_TIMESTAMPING_INTERNAL_SYSTEM_TIME_S 25 #define EMAC_ENHANCED_DESCRIPTOR (BIT(24)) +#define EMAC_ENHANCED_DESCRIPTOR_M (BIT(24)) +#define EMAC_ENHANCED_DESCRIPTOR_V 1 #define EMAC_ENHANCED_DESCRIPTOR_S 24 #define EMAC_NUMBER_ADDITIONAL_TX_CHANNELS 0x00000003 +#define EMAC_NUMBER_ADDITIONAL_TX_CHANNELS_M (EMAC_NUMBER_ADDITIONAL_TX_CHANNELS_V << EMAC_NUMBER_ADDITIONAL_TX_CHANNELS_S) +#define EMAC_NUMBER_ADDITIONAL_TX_CHANNELS_V 0x00000003 #define EMAC_NUMBER_ADDITIONAL_TX_CHANNELS_S 22 #define EMAC_NUMBER_ADDITIONAL_RX_CHANNELS 0x00000003 +#define EMAC_NUMBER_ADDITIONAL_RX_CHANNELS_M (EMAC_NUMBER_ADDITIONAL_RX_CHANNELS_V << EMAC_NUMBER_ADDITIONAL_RX_CHANNELS_S) +#define EMAC_NUMBER_ADDITIONAL_RX_CHANNELS_V 0x00000003 #define EMAC_NUMBER_ADDITIONAL_RX_CHANNELS_S 20 #define EMAC_RXFIFOSIZE (BIT(19)) +#define EMAC_RXFIFOSIZE_M (BIT(19)) +#define EMAC_RXFIFOSIZE_V 1 #define EMAC_RXFIFOSIZE_S 19 #define EMAC_IP_CHECKSUM_OFFLOAD_TYPE2 (BIT(18)) +#define EMAC_IP_CHECKSUM_OFFLOAD_TYPE2_M (BIT(18)) +#define EMAC_IP_CHECKSUM_OFFLOAD_TYPE2_V 1 #define EMAC_IP_CHECKSUM_OFFLOAD_TYPE2_S 18 #define EMAC_IP_CHECKSUM_OFFLOAD_TYPE1 (BIT(17)) +#define EMAC_IP_CHECKSUM_OFFLOAD_TYPE1_M (BIT(17)) +#define EMAC_IP_CHECKSUM_OFFLOAD_TYPE1_V 1 #define EMAC_IP_CHECKSUM_OFFLOAD_TYPE1_S 17 #define EMAC_CHECKSUM_OFFLOAD_TX (BIT(16)) +#define EMAC_CHECKSUM_OFFLOAD_TX_M (BIT(16)) +#define EMAC_CHECKSUM_OFFLOAD_TX_V 1 #define EMAC_CHECKSUM_OFFLOAD_TX_S 16 #define EMAC_AV_FEATURE_SEL (BIT(15)) +#define EMAC_AV_FEATURE_SEL_M (BIT(15)) +#define EMAC_AV_FEATURE_SEL_V 1 #define EMAC_AV_FEATURE_SEL_S 15 #define EMAC_EEE_SEL (BIT(14)) +#define EMAC_EEE_SEL_M (BIT(14)) +#define EMAC_EEE_SEL_V 1 #define EMAC_EEE_SEL_S 14 #define EMAC_TSVER2_SEL (BIT(13)) +#define EMAC_TSVER2_SEL_M (BIT(13)) +#define EMAC_TSVER2_SEL_V 1 #define EMAC_TSVER2_SEL_S 13 #define EMAC_TSVER1_SEL (BIT(12)) +#define EMAC_TSVER1_SEL_M (BIT(12)) +#define EMAC_TSVER1_SEL_V 1 #define EMAC_TSVER1_SEL_S 12 #define EMAC_MMC_SEL (BIT(11)) +#define EMAC_MMC_SEL_M (BIT(11)) +#define EMAC_MMC_SEL_V 1 #define EMAC_MMC_SEL_S 11 #define EMAC_MGK_SEL (BIT(10)) +#define EMAC_MGK_SEL_M (BIT(10)) +#define EMAC_MGK_SEL_V 1 #define EMAC_MGK_SEL_S 10 #define EMAC_RWK_SEL (BIT(9)) +#define EMAC_RWK_SEL_M (BIT(9)) +#define EMAC_RWK_SEL_V 1 #define EMAC_RWK_SEL_S 9 #define EMAC_SMA_SEL (BIT(8)) +#define EMAC_SMA_SEL_M (BIT(8)) +#define EMAC_SMA_SEL_V 1 #define EMAC_SMA_SEL_S 8 #define EMAC_L3L4FLTR_EN (BIT(7)) +#define EMAC_L3L4FLTR_EN_M (BIT(7)) +#define EMAC_L3L4FLTR_EN_V 1 #define EMAC_L3L4FLTR_EN_S 7 #define EMAC_PCS_SEL (BIT(6)) +#define EMAC_PCS_SEL_M (BIT(6)) +#define EMAC_PCS_SEL_V 1 #define EMAC_PCS_SEL_S 6 #define EMAC_ADDMACADR_SEL (BIT(5)) +#define EMAC_ADDMACADR_SEL_M (BIT(5)) +#define EMAC_ADDMACADR_SEL_V 1 #define EMAC_ADDMACADR_SEL_S 5 #define EMAC_HASH_SEL (BIT(4)) +#define EMAC_HASH_SEL_M (BIT(4)) +#define EMAC_HASH_SEL_V 1 #define EMAC_HASH_SEL_S 4 #define EMAC_EXTHASH_EN (BIT(3)) +#define EMAC_EXTHASH_EN_M (BIT(3)) +#define EMAC_EXTHASH_EN_V 1 #define EMAC_EXTHASH_EN_S 3 #define EMAC_HD_SEL (BIT(2)) +#define EMAC_HD_SEL_M (BIT(2)) +#define EMAC_HD_SEL_V 1 #define EMAC_HD_SEL_S 2 #define EMAC_GMII_SEL (BIT(1)) +#define EMAC_GMII_SEL_M (BIT(1)) +#define EMAC_GMII_SEL_V 1 #define EMAC_GMII_SEL_S 1 #define EMAC_MII_SEL (BIT(0)) +#define EMAC_MII_SEL_M (BIT(0)) +#define EMAC_MII_SEL_V 1 #define EMAC_MII_SEL_S 0 #define EMAC_DMASLOTFNCTRLSTS_REG (REG_EMAC_BASE + 0x0130) #define EMAC_REFERENCE_SLOT_NUMBER 0x0000000F +#define EMAC_REFERENCE_SLOT_NUMBER_M (EMAC_REFERENCE_SLOT_NUMBER_V << EMAC_REFERENCE_SLOT_NUMBER_S) +#define EMAC_REFERENCE_SLOT_NUMBER_V 0x0000000F #define EMAC_REFERENCE_SLOT_NUMBER_S 16 #define EMAC_ADVANCE_SLOT_CHECK (BIT(1)) +#define EMAC_ADVANCE_SLOT_CHECK_M (BIT(1)) +#define EMAC_ADVANCE_SLOT_CHECK_V 1 #define EMAC_ADVANCE_SLOT_CHECK_S 1 #define EMAC_ENABLE_SLOT_COMPARISON (BIT(0)) +#define EMAC_ENABLE_SLOT_COMPARISON_M (BIT(0)) +#define EMAC_ENABLE_SLOT_COMPARISON_V 1 #define EMAC_ENABLE_SLOT_COMPARISON_S 0 #define EMAC_DMACHANNELCTRL_REG (REG_EMAC_BASE + 0x0160) #define EMAC_AVERAGE_BITS_PER_SLOT_INTERRUPT_ENABLE (BIT(17)) +#define EMAC_AVERAGE_BITS_PER_SLOT_INTERRUPT_ENABLE_M (BIT(17)) +#define EMAC_AVERAGE_BITS_PER_SLOT_INTERRUPT_ENABLE_V 1 #define EMAC_AVERAGE_BITS_PER_SLOT_INTERRUPT_ENABLE_S 17 #define EMAC_SLOT_COUNT 0x00000007 +#define EMAC_SLOT_COUNT_M (EMAC_SLOT_COUNT_V << EMAC_SLOT_COUNT_S) +#define EMAC_SLOT_COUNT_V 0x00000007 #define EMAC_SLOT_COUNT_S 4 #define EMAC_CREDIT_CONTROL (BIT(1)) +#define EMAC_CREDIT_CONTROL_M (BIT(1)) +#define EMAC_CREDIT_CONTROL_V 1 #define EMAC_CREDIT_CONTROL_S 1 #define EMAC_CREDIT_BASED_SHAPER_DISABLE (BIT(0)) +#define EMAC_CREDIT_BASED_SHAPER_DISABLE_M (BIT(0)) +#define EMAC_CREDIT_BASED_SHAPER_DISABLE_V 1 #define EMAC_CREDIT_BASED_SHAPER_DISABLE_S 0 #define EMAC_DMACHANNELAVSTS_REG (REG_EMAC_BASE + 0x0064) #define EMAC_ABS_UPDATED (BIT(17)) +#define EMAC_ABS_UPDATED_M (BIT(17)) +#define EMAC_ABS_UPDATED_V 1 #define EMAC_ABS_UPDATED_S 17 #define EMAC_AVERAGE_BITS_PER_SLOT 0x0001FFFF +#define EMAC_AVERAGE_BITS_PER_SLOT_M (EMAC_AVERAGE_BITS_PER_SLOT_V << EMAC_AVERAGE_BITS_PER_SLOT_S) +#define EMAC_AVERAGE_BITS_PER_SLOT_V 0x0001FFFF #define EMAC_AVERAGE_BITS_PER_SLOT_S 0 #define EMAC_DMAIDLESLOPECREDIT_REG (REG_EMAC_BASE + 0x0068) #define EMAC_IDLESLOPECREDIT 0x00003FFF +#define EMAC_IDLESLOPECREDIT_M (EMAC_IDLESLOPECREDIT_V << EMAC_IDLESLOPECREDIT_S) +#define EMAC_IDLESLOPECREDIT_V 0x00003FFF #define EMAC_IDLESLOPECREDIT_S 0 #define EMAC_DMASENDSLOPECREDIT_REG (REG_EMAC_BASE + 0x006C) #define EMAC_SENDSLOPECREDIT 0x00003FFF +#define EMAC_SENDSLOPECREDIT_M (EMAC_SENDSLOPECREDIT_V << EMAC_SENDSLOPECREDIT_S) +#define EMAC_SENDSLOPECREDIT_V 0x00003FFF #define EMAC_SENDSLOPECREDIT_S 0 #define EMAC_DMAHIGHCREDIT_REG (REG_EMAC_BASE + 0x0070) #define EMAC_HICREDIT 0x1FFFFFFF +#define EMAC_HICREDIT_M (EMAC_HICREDIT_V << EMAC_HICREDIT_S) +#define EMAC_HICREDIT_V 0x1FFFFFFF #define EMAC_HICREDIT_S 0 #define EMAC_DMALOCREDIT_REG (REG_EMAC_BASE + 0x0074) #define EMAC_LOCREDIT 0x1FFFFFFF +#define EMAC_LOCREDIT_M (EMAC_LOCREDIT_V << EMAC_LOCREDIT_S) +#define EMAC_LOCREDIT_V 0x1FFFFFFF #define EMAC_LOCREDIT_S 0 #define EMAC_GMACCONFIG_REG (REG_EMAC_BASE + 0x1000) #define EMAC_SOURCE_ADDRESS_INSERTION_REPLACEMENT_CONTROL 0x00000007 +#define EMAC_SOURCE_ADDRESS_INSERTION_REPLACEMENT_CONTROL_M (EMAC_SOURCE_ADDRESS_INSERTION_REPLACEMENT_CONTROL_V << EMAC_SOURCE_ADDRESS_INSERTION_REPLACEMENT_CONTROL_S) +#define EMAC_SOURCE_ADDRESS_INSERTION_REPLACEMENT_CONTROL_V 0x00000007 #define EMAC_SOURCE_ADDRESS_INSERTION_REPLACEMENT_CONTROL_S 28 #define EMAC_AS_SUPPORT_2K_PACKETS (BIT(27)) +#define EMAC_AS_SUPPORT_2K_PACKETS_M (BIT(27)) +#define EMAC_AS_SUPPORT_2K_PACKETS_V 1 #define EMAC_AS_SUPPORT_2K_PACKETS_S 27 #define EMAC_SMII_FORCE_TRANSMIT_ERROR (BIT(26)) +#define EMAC_SMII_FORCE_TRANSMIT_ERROR_M (BIT(26)) +#define EMAC_SMII_FORCE_TRANSMIT_ERROR_V 1 #define EMAC_SMII_FORCE_TRANSMIT_ERROR_S 26 #define EMAC_CRC_STRIPPING_TYPE_FRAMES (BIT(25)) +#define EMAC_CRC_STRIPPING_TYPE_FRAMES_M (BIT(25)) +#define EMAC_CRC_STRIPPING_TYPE_FRAMES_V 1 #define EMAC_CRC_STRIPPING_TYPE_FRAMES_S 25 #define EMAC_TRANSMIT_CONFIGURATION (BIT(24)) +#define EMAC_TRANSMIT_CONFIGURATION_M (BIT(24)) +#define EMAC_TRANSMIT_CONFIGURATION_V 1 #define EMAC_TRANSMIT_CONFIGURATION_S 24 #define EMAC_GMACWATCHDOG (BIT(23)) +#define EMAC_GMACWATCHDOG_M (BIT(23)) +#define EMAC_GMACWATCHDOG_V 1 #define EMAC_GMACWATCHDOG_S 23 #define EMAC_GMACJABBER (BIT(22)) +#define EMAC_GMACJABBER_M (BIT(22)) +#define EMAC_GMACJABBER_V 1 #define EMAC_GMACJABBER_S 22 #define EMAC_GMACFRAMEBURST (BIT(21)) +#define EMAC_GMACFRAMEBURST_M (BIT(21)) +#define EMAC_GMACFRAMEBURST_V 1 #define EMAC_GMACFRAMEBURST_S 21 #define EMAC_GMACJUMBOFRAME (BIT(20)) +#define EMAC_GMACJUMBOFRAME_M (BIT(20)) +#define EMAC_GMACJUMBOFRAME_V 1 #define EMAC_GMACJUMBOFRAME_S 20 #define EMAC_GMACINTERFRAMEGAP 0x00000007 +#define EMAC_GMACINTERFRAMEGAP_M (EMAC_GMACINTERFRAMEGAP_V << EMAC_GMACINTERFRAMEGAP_S) +#define EMAC_GMACINTERFRAMEGAP_V 0x00000007 #define EMAC_GMACINTERFRAMEGAP_S 17 #define EMAC_GMACDISABLECRS (BIT(16)) +#define EMAC_GMACDISABLECRS_M (BIT(16)) +#define EMAC_GMACDISABLECRS_V 1 #define EMAC_GMACDISABLECRS_S 16 #define EMAC_GMACMIIGMII (BIT(15)) +#define EMAC_GMACMIIGMII_M (BIT(15)) +#define EMAC_GMACMIIGMII_V 1 #define EMAC_GMACMIIGMII_S 15 #define EMAC_GMACFESPEED (BIT(14)) +#define EMAC_GMACFESPEED_M (BIT(14)) +#define EMAC_GMACFESPEED_V 1 #define EMAC_GMACFESPEED_S 14 #define EMAC_GMACRXOWN (BIT(13)) +#define EMAC_GMACRXOWN_M (BIT(13)) +#define EMAC_GMACRXOWN_V 1 #define EMAC_GMACRXOWN_S 13 #define EMAC_GMACLOOPBACK (BIT(12)) +#define EMAC_GMACLOOPBACK_M (BIT(12)) +#define EMAC_GMACLOOPBACK_V 1 #define EMAC_GMACLOOPBACK_S 12 #define EMAC_GMACDUPLEX (BIT(11)) +#define EMAC_GMACDUPLEX_M (BIT(11)) +#define EMAC_GMACDUPLEX_V 1 #define EMAC_GMACDUPLEX_S 11 #define EMAC_GMACRXIPCOFFLOAD (BIT(10)) +#define EMAC_GMACRXIPCOFFLOAD_M (BIT(10)) +#define EMAC_GMACRXIPCOFFLOAD_V 1 #define EMAC_GMACRXIPCOFFLOAD_S 10 #define EMAC_GMACRETRY (BIT(9)) +#define EMAC_GMACRETRY_M (BIT(9)) +#define EMAC_GMACRETRY_V 1 #define EMAC_GMACRETRY_S 9 #define EMAC_GMACLINK (BIT(8)) +#define EMAC_GMACLINK_M (BIT(8)) +#define EMAC_GMACLINK_V 1 #define EMAC_GMACLINK_S 8 #define EMAC_GMACPADCRCSTRIP (BIT(7)) +#define EMAC_GMACPADCRCSTRIP_M (BIT(7)) +#define EMAC_GMACPADCRCSTRIP_V 1 #define EMAC_GMACPADCRCSTRIP_S 7 #define EMAC_GMACBACKOFFLIMIT 0x00000003 +#define EMAC_GMACBACKOFFLIMIT_M (EMAC_GMACBACKOFFLIMIT_V << EMAC_GMACBACKOFFLIMIT_S) +#define EMAC_GMACBACKOFFLIMIT_V 0x00000003 #define EMAC_GMACBACKOFFLIMIT_S 5 #define EMAC_GMACDEFERRALCHECK (BIT(4)) +#define EMAC_GMACDEFERRALCHECK_M (BIT(4)) +#define EMAC_GMACDEFERRALCHECK_V 1 #define EMAC_GMACDEFERRALCHECK_S 4 #define EMAC_GMACTX (BIT(3)) +#define EMAC_GMACTX_M (BIT(3)) +#define EMAC_GMACTX_V 1 #define EMAC_GMACTX_S 3 #define EMAC_GMACRX (BIT(2)) +#define EMAC_GMACRX_M (BIT(2)) +#define EMAC_GMACRX_V 1 #define EMAC_GMACRX_S 2 #define EMAC_PREAMBLE_LENGTH_TRANSMIT_FRAMES 0x00000003 +#define EMAC_PREAMBLE_LENGTH_TRANSMIT_FRAMES_M (EMAC_PREAMBLE_LENGTH_TRANSMIT_FRAMES_V << EMAC_PREAMBLE_LENGTH_TRANSMIT_FRAMES_S) +#define EMAC_PREAMBLE_LENGTH_TRANSMIT_FRAMES_V 0x00000003 #define EMAC_PREAMBLE_LENGTH_TRANSMIT_FRAMES_S 0 #define EMAC_GMACFRAMEFILTER_REG (REG_EMAC_BASE + 0x1004) #define EMAC_RECEIVEALL (BIT(31)) +#define EMAC_RECEIVEALL_M (BIT(31)) +#define EMAC_RECEIVEALL_V 1 #define EMAC_RECEIVEALL_S 31 #define EMAC_DROP_NON_TCP_UDP_IP_FRAMES (BIT(21)) +#define EMAC_DROP_NON_TCP_UDP_IP_FRAMES_M (BIT(21)) +#define EMAC_DROP_NON_TCP_UDP_IP_FRAMES_V 1 #define EMAC_DROP_NON_TCP_UDP_IP_FRAMES_S 21 #define EMAC_LAYER_3_AND_LAYER_4_FILTER_ENABLE (BIT(20)) +#define EMAC_LAYER_3_AND_LAYER_4_FILTER_ENABLE_M (BIT(20)) +#define EMAC_LAYER_3_AND_LAYER_4_FILTER_ENABLE_V 1 #define EMAC_LAYER_3_AND_LAYER_4_FILTER_ENABLE_S 20 #define EMAC_VLAN_TAG_FILTER_ENABLE (BIT(16)) +#define EMAC_VLAN_TAG_FILTER_ENABLE_M (BIT(16)) +#define EMAC_VLAN_TAG_FILTER_ENABLE_V 1 #define EMAC_VLAN_TAG_FILTER_ENABLE_S 16 #define EMAC_HASH_OR_PERFECT_FILTE (BIT(10)) +#define EMAC_HASH_OR_PERFECT_FILTE_M (BIT(10)) +#define EMAC_HASH_OR_PERFECT_FILTE_V 1 #define EMAC_HASH_OR_PERFECT_FILTE_S 10 #define EMAC_SOURCE_ADDRESS_FILTER_ENABLE (BIT(9)) +#define EMAC_SOURCE_ADDRESS_FILTER_ENABLE_M (BIT(9)) +#define EMAC_SOURCE_ADDRESS_FILTER_ENABLE_V 1 #define EMAC_SOURCE_ADDRESS_FILTER_ENABLE_S 9 #define EMAC_SA_INVERSE_FILTERING (BIT(8)) +#define EMAC_SA_INVERSE_FILTERING_M (BIT(8)) +#define EMAC_SA_INVERSE_FILTERING_V 1 #define EMAC_SA_INVERSE_FILTERING_S 8 #define EMAC_PASS_CONTROL_FRAMES 0x00000003 +#define EMAC_PASS_CONTROL_FRAMES_M (EMAC_PASS_CONTROL_FRAMES_V << EMAC_PASS_CONTROL_FRAMES_S) +#define EMAC_PASS_CONTROL_FRAMES_V 0x00000003 #define EMAC_PASS_CONTROL_FRAMES_S 6 #define EMAC_DISABLE_BROADCAST_FRAMES (BIT(5)) +#define EMAC_DISABLE_BROADCAST_FRAMES_M (BIT(5)) +#define EMAC_DISABLE_BROADCAST_FRAMES_V 1 #define EMAC_DISABLE_BROADCAST_FRAMES_S 5 #define EMAC_PASS_ALL_MULTICAST (BIT(4)) +#define EMAC_PASS_ALL_MULTICAST_M (BIT(4)) +#define EMAC_PASS_ALL_MULTICAST_V 1 #define EMAC_PASS_ALL_MULTICAST_S 4 #define EMAC_DA_INVERSE_FILTERING (BIT(3)) +#define EMAC_DA_INVERSE_FILTERING_M (BIT(3)) +#define EMAC_DA_INVERSE_FILTERING_V 1 #define EMAC_DA_INVERSE_FILTERING_S 3 #define EMAC_HASH_MULTICAST (BIT(2)) +#define EMAC_HASH_MULTICAST_M (BIT(2)) +#define EMAC_HASH_MULTICAST_V 1 #define EMAC_HASH_MULTICAST_S 2 #define EMAC_HASH_UNICAST (BIT(1)) +#define EMAC_HASH_UNICAST_M (BIT(1)) +#define EMAC_HASH_UNICAST_V 1 #define EMAC_HASH_UNICAST_S 1 #define EMAC_PROMISCUOUS_MODE (BIT(0)) +#define EMAC_PROMISCUOUS_MODE_M (BIT(0)) +#define EMAC_PROMISCUOUS_MODE_V 1 #define EMAC_PROMISCUOUS_MODE_S 0 #define EMAC_GMACHASHHIGH_REG (REG_EMAC_BASE + 0x1008) #define EMAC_HASH_TABLE_HIGH 0xFFFFFFFF +#define EMAC_HASH_TABLE_HIGH_M (EMAC_HASH_TABLE_HIGH_V << EMAC_HASH_TABLE_HIGH_S) +#define EMAC_HASH_TABLE_HIGH_V 0xFFFFFFFF #define EMAC_HASH_TABLE_HIGH_S 0 #define EMAC_GMACHASHLOW_REG (REG_EMAC_BASE + 0x100C) #define EMAC_HASH_TABLE_LOW 0xFFFFFFFF +#define EMAC_HASH_TABLE_LOW_M (EMAC_HASH_TABLE_LOW_V << EMAC_HASH_TABLE_LOW_S) +#define EMAC_HASH_TABLE_LOW_V 0xFFFFFFFF #define EMAC_HASH_TABLE_LOW_S 0 #define EMAC_GMACGMIIADDR_REG (REG_EMAC_BASE + 0x1010) #define EMAC_GMIIDEV 0x0000001F +#define EMAC_GMIIDEV_M (EMAC_GMIIDEV_V << EMAC_GMIIDEV_S) +#define EMAC_GMIIDEV_V 0x0000001F #define EMAC_GMIIDEV_S 11 #define EMAC_GMIIREG 0x0000001F +#define EMAC_GMIIREG_M (EMAC_GMIIREG_V << EMAC_GMIIREG_S) +#define EMAC_GMIIREG_V 0x0000001F #define EMAC_GMIIREG_S 6 #define EMAC_GMIICSRCLK 0x0000000F +#define EMAC_GMIICSRCLK_M (EMAC_GMIICSRCLK_V << EMAC_GMIICSRCLK_S) +#define EMAC_GMIICSRCLK_V 0x0000000F #define EMAC_GMIICSRCLK_S 2 #define EMAC_GMIIWRITE (BIT(1)) +#define EMAC_GMIIWRITE_M (BIT(1)) +#define EMAC_GMIIWRITE_V 1 #define EMAC_GMIIWRITE_S 1 #define EMAC_GMIIBUSY (BIT(0)) +#define EMAC_GMIIBUSY_M (BIT(0)) +#define EMAC_GMIIBUSY_V 1 #define EMAC_GMIIBUSY_S 0 #define EMAC_GMACGMIIDATA_REG (REG_EMAC_BASE + 0x1014) #define EMAC_GMII_DATA 0x0000FFFF +#define EMAC_GMII_DATA_M (EMAC_GMII_DATA_V << EMAC_GMII_DATA_S) +#define EMAC_GMII_DATA_V 0x0000FFFF #define EMAC_GMII_DATA_S 0 #define EMAC_GMACFLOWCONTROL_REG (REG_EMAC_BASE + 0x1018) #define EMAC_PAUSE_TIME 0x0000FFFF +#define EMAC_PAUSE_TIME_M (EMAC_PAUSE_TIME_V << EMAC_PAUSE_TIME_S) +#define EMAC_PAUSE_TIME_V 0x0000FFFF #define EMAC_PAUSE_TIME_S 16 #define EMAC_DISABLE_ZERO_QUANTA_PAUSE (BIT(7)) +#define EMAC_DISABLE_ZERO_QUANTA_PAUSE_M (BIT(7)) +#define EMAC_DISABLE_ZERO_QUANTA_PAUSE_V 1 #define EMAC_DISABLE_ZERO_QUANTA_PAUSE_S 7 #define EMAC_PAUSE_LOW_THRESHOLD 0x00000003 +#define EMAC_PAUSE_LOW_THRESHOLD_M (EMAC_PAUSE_LOW_THRESHOLD_V << EMAC_PAUSE_LOW_THRESHOLD_S) +#define EMAC_PAUSE_LOW_THRESHOLD_V 0x00000003 #define EMAC_PAUSE_LOW_THRESHOLD_S 4 #define EMAC_UNICAST_PAUSE_FRAME_DETECT (BIT(3)) +#define EMAC_UNICAST_PAUSE_FRAME_DETECT_M (BIT(3)) +#define EMAC_UNICAST_PAUSE_FRAME_DETECT_V 1 #define EMAC_UNICAST_PAUSE_FRAME_DETECT_S 3 #define EMAC_RECEIVE_FLOW_CONTROL_ENABLE (BIT(2)) +#define EMAC_RECEIVE_FLOW_CONTROL_ENABLE_M (BIT(2)) +#define EMAC_RECEIVE_FLOW_CONTROL_ENABLE_V 1 #define EMAC_RECEIVE_FLOW_CONTROL_ENABLE_S 2 #define EMAC_TRANSMIT_FLOW_CONTROL_ENABLE (BIT(1)) +#define EMAC_TRANSMIT_FLOW_CONTROL_ENABLE_M (BIT(1)) +#define EMAC_TRANSMIT_FLOW_CONTROL_ENABLE_V 1 #define EMAC_TRANSMIT_FLOW_CONTROL_ENABLE_S 1 #define EMAC_FLOW_CONTROL_BUSY_BACKPRESSURE_ACTIVATE (BIT(0)) +#define EMAC_FLOW_CONTROL_BUSY_BACKPRESSURE_ACTIVATE_M (BIT(0)) +#define EMAC_FLOW_CONTROL_BUSY_BACKPRESSURE_ACTIVATE_V 1 #define EMAC_FLOW_CONTROL_BUSY_BACKPRESSURE_ACTIVATE_S 0 #define EMAC_GMACVLAN_REG (REG_EMAC_BASE + 0x101C) #define EMAC_VLAN_TAG_HASH_TABLE_MATCH_ENABLE (BIT(19)) +#define EMAC_VLAN_TAG_HASH_TABLE_MATCH_ENABLE_M (BIT(19)) +#define EMAC_VLAN_TAG_HASH_TABLE_MATCH_ENABLE_V 1 #define EMAC_VLAN_TAG_HASH_TABLE_MATCH_ENABLE_S 19 #define EMAC_ENABLE_S_VLAN (BIT(18)) +#define EMAC_ENABLE_S_VLAN_M (BIT(18)) +#define EMAC_ENABLE_S_VLAN_V 1 #define EMAC_ENABLE_S_VLAN_S 18 #define EMAC_VLAN_TAG_INVERSE_MATCH_ENABLE (BIT(17)) +#define EMAC_VLAN_TAG_INVERSE_MATCH_ENABLE_M (BIT(17)) +#define EMAC_VLAN_TAG_INVERSE_MATCH_ENABLE_V 1 #define EMAC_VLAN_TAG_INVERSE_MATCH_ENABLE_S 17 #define EMAC_ENABLE_VLAN_TAG_COMPARISON (BIT(16)) +#define EMAC_ENABLE_VLAN_TAG_COMPARISON_M (BIT(16)) +#define EMAC_ENABLE_VLAN_TAG_COMPARISON_V 1 #define EMAC_ENABLE_VLAN_TAG_COMPARISON_S 16 #define EMAC_VLAN_TAG_IDENTIFIER_RECEIVE_FRAMES 0x0000FFFF +#define EMAC_VLAN_TAG_IDENTIFIER_RECEIVE_FRAMES_M (EMAC_VLAN_TAG_IDENTIFIER_RECEIVE_FRAMES_V << EMAC_VLAN_TAG_IDENTIFIER_RECEIVE_FRAMES_S) +#define EMAC_VLAN_TAG_IDENTIFIER_RECEIVE_FRAMES_V 0x0000FFFF #define EMAC_VLAN_TAG_IDENTIFIER_RECEIVE_FRAMES_S 0 #define EMAC_GMACVERSION_REG (REG_EMAC_BASE + 0x1020) #define EMAC_USERVER 0x000000FF +#define EMAC_USERVER_M (EMAC_USERVER_V << EMAC_USERVER_S) +#define EMAC_USERVER_V 0x000000FF #define EMAC_USERVER_S 8 #define EMAC_SNPSVER 0x000000FF +#define EMAC_SNPSVER_M (EMAC_SNPSVER_V << EMAC_SNPSVER_S) +#define EMAC_SNPSVER_V 0x000000FF #define EMAC_SNPSVER_S 0 #define EMAC_GMACDEBUG_REG (REG_EMAC_BASE + 0x1024) #define EMAC_MTL_TXSTATUS_FIFO_FULL_STATUS (BIT(25)) +#define EMAC_MTL_TXSTATUS_FIFO_FULL_STATUS_M (BIT(25)) +#define EMAC_MTL_TXSTATUS_FIFO_FULL_STATUS_V 1 #define EMAC_MTL_TXSTATUS_FIFO_FULL_STATUS_S 25 #define EMAC_MTL_TX_FIFO_NOT_EMPTY_STATUS (BIT(24)) +#define EMAC_MTL_TX_FIFO_NOT_EMPTY_STATUS_M (BIT(24)) +#define EMAC_MTL_TX_FIFO_NOT_EMPTY_STATUS_V 1 #define EMAC_MTL_TX_FIFO_NOT_EMPTY_STATUS_S 24 #define EMAC_MTL_TX_FIFO_WRITE_CONTROLLER_STATUS (BIT(22)) +#define EMAC_MTL_TX_FIFO_WRITE_CONTROLLER_STATUS_M (BIT(22)) +#define EMAC_MTL_TX_FIFO_WRITE_CONTROLLER_STATUS_V 1 #define EMAC_MTL_TX_FIFO_WRITE_CONTROLLER_STATUS_S 22 #define EMAC_MTL_TX_FIFO_READ_CONTROLLER_STATUS 0x00000003 +#define EMAC_MTL_TX_FIFO_READ_CONTROLLER_STATUS_M (EMAC_MTL_TX_FIFO_READ_CONTROLLER_STATUS_V << EMAC_MTL_TX_FIFO_READ_CONTROLLER_STATUS_S) +#define EMAC_MTL_TX_FIFO_READ_CONTROLLER_STATUS_V 0x00000003 #define EMAC_MTL_TX_FIFO_READ_CONTROLLER_STATUS_S 20 #define EMAC_MAC_TRANSMITTER_PAUSE (BIT(19)) +#define EMAC_MAC_TRANSMITTER_PAUSE_M (BIT(19)) +#define EMAC_MAC_TRANSMITTER_PAUSE_V 1 #define EMAC_MAC_TRANSMITTER_PAUSE_S 19 #define EMAC_MAC_TRANSMIT_FRAME_CONTROLLER_STATUS 0x00000003 +#define EMAC_MAC_TRANSMIT_FRAME_CONTROLLER_STATUS_M (EMAC_MAC_TRANSMIT_FRAME_CONTROLLER_STATUS_V << EMAC_MAC_TRANSMIT_FRAME_CONTROLLER_STATUS_S) +#define EMAC_MAC_TRANSMIT_FRAME_CONTROLLER_STATUS_V 0x00000003 #define EMAC_MAC_TRANSMIT_FRAME_CONTROLLER_STATUS_S 17 #define EMAC_MAC_TRANSMIT_PROTOCOL_ENGINE_STATUS (BIT(16)) +#define EMAC_MAC_TRANSMIT_PROTOCOL_ENGINE_STATUS_M (BIT(16)) +#define EMAC_MAC_TRANSMIT_PROTOCOL_ENGINE_STATUS_V 1 #define EMAC_MAC_TRANSMIT_PROTOCOL_ENGINE_STATUS_S 16 #define EMAC_MTL_RXFIFO_FILL_LEVEL_STATUS 0x00000003 +#define EMAC_MTL_RXFIFO_FILL_LEVEL_STATUS_M (EMAC_MTL_RXFIFO_FILL_LEVEL_STATUS_V << EMAC_MTL_RXFIFO_FILL_LEVEL_STATUS_S) +#define EMAC_MTL_RXFIFO_FILL_LEVEL_STATUS_V 0x00000003 #define EMAC_MTL_RXFIFO_FILL_LEVEL_STATUS_S 8 #define EMAC_MTL_RXFIFO_READ_CONTROLLER_STATE 0x00000003 +#define EMAC_MTL_RXFIFO_READ_CONTROLLER_STATE_M (EMAC_MTL_RXFIFO_READ_CONTROLLER_STATE_V << EMAC_MTL_RXFIFO_READ_CONTROLLER_STATE_S) +#define EMAC_MTL_RXFIFO_READ_CONTROLLER_STATE_V 0x00000003 #define EMAC_MTL_RXFIFO_READ_CONTROLLER_STATE_S 5 #define EMAC_MTL_RX_FIFO_WRITE_CONTROLLER_ACTIVE_STATUS (BIT(4)) +#define EMAC_MTL_RX_FIFO_WRITE_CONTROLLER_ACTIVE_STATUS_M (BIT(4)) +#define EMAC_MTL_RX_FIFO_WRITE_CONTROLLER_ACTIVE_STATUS_V 1 #define EMAC_MTL_RX_FIFO_WRITE_CONTROLLER_ACTIVE_STATUS_S 4 #define EMAC_MAC_RECEIVE_FRAME_FIFO_CONTROLLER_STATUS 0x00000003 +#define EMAC_MAC_RECEIVE_FRAME_FIFO_CONTROLLER_STATUS_M (EMAC_MAC_RECEIVE_FRAME_FIFO_CONTROLLER_STATUS_V << EMAC_MAC_RECEIVE_FRAME_FIFO_CONTROLLER_STATUS_S) +#define EMAC_MAC_RECEIVE_FRAME_FIFO_CONTROLLER_STATUS_V 0x00000003 #define EMAC_MAC_RECEIVE_FRAME_FIFO_CONTROLLER_STATUS_S 1 #define EMAC_MAC_RECEIVE_PROTOCOL_ENGINE_STATUS (BIT(0)) +#define EMAC_MAC_RECEIVE_PROTOCOL_ENGINE_STATUS_M (BIT(0)) +#define EMAC_MAC_RECEIVE_PROTOCOL_ENGINE_STATUS_V 1 #define EMAC_MAC_RECEIVE_PROTOCOL_ENGINE_STATUS_S 0 #define EMAC_GMACLPITIMERSCONTROL_REG (REG_EMAC_BASE + 0x1034) #define EMAC_LPI_LS_TIMER 0x000003FF +#define EMAC_LPI_LS_TIMER_M (EMAC_LPI_LS_TIMER_V << EMAC_LPI_LS_TIMER_S) +#define EMAC_LPI_LS_TIMER_V 0x000003FF #define EMAC_LPI_LS_TIMER_S 16 #define EMAC_LPI_TW_TIMER 0x0000FFFF +#define EMAC_LPI_TW_TIMER_M (EMAC_LPI_TW_TIMER_V << EMAC_LPI_TW_TIMER_S) +#define EMAC_LPI_TW_TIMER_V 0x0000FFFF #define EMAC_LPI_TW_TIMER_S 0 #define EMAC_GMACINTERRUPTSTATUS_REG (REG_EMAC_BASE + 0x1038) #define EMAC_GPI_INTERRUPT_STATUS (BIT(11)) +#define EMAC_GPI_INTERRUPT_STATUS_M (BIT(11)) +#define EMAC_GPI_INTERRUPT_STATUS_V 1 #define EMAC_GPI_INTERRUPT_STATUS_S 11 #define EMAC_LPI_INTERRUPT_STATUS (BIT(10)) +#define EMAC_LPI_INTERRUPT_STATUS_M (BIT(10)) +#define EMAC_LPI_INTERRUPT_STATUS_V 1 #define EMAC_LPI_INTERRUPT_STATUS_S 10 #define EMAC_TIMESTAMP_INTERRUP_STATUS (BIT(9)) +#define EMAC_TIMESTAMP_INTERRUP_STATUS_M (BIT(9)) +#define EMAC_TIMESTAMP_INTERRUP_STATUS_V 1 #define EMAC_TIMESTAMP_INTERRUP_STATUS_S 9 #define EMAC_MMC_RECEIVE_CHECKSUM_OFFLOAD_INTERRUPT_STATUS (BIT(7)) +#define EMAC_MMC_RECEIVE_CHECKSUM_OFFLOAD_INTERRUPT_STATUS_M (BIT(7)) +#define EMAC_MMC_RECEIVE_CHECKSUM_OFFLOAD_INTERRUPT_STATUS_V 1 #define EMAC_MMC_RECEIVE_CHECKSUM_OFFLOAD_INTERRUPT_STATUS_S 7 #define EMAC_MMC_TRANSMIT_INTERRUPT_STATUS (BIT(6)) +#define EMAC_MMC_TRANSMIT_INTERRUPT_STATUS_M (BIT(6)) +#define EMAC_MMC_TRANSMIT_INTERRUPT_STATUS_V 1 #define EMAC_MMC_TRANSMIT_INTERRUPT_STATUS_S 6 #define EMAC_MMC_RECEIVE_INTERRUPT_STATUS (BIT(5)) +#define EMAC_MMC_RECEIVE_INTERRUPT_STATUS_M (BIT(5)) +#define EMAC_MMC_RECEIVE_INTERRUPT_STATUS_V 1 #define EMAC_MMC_RECEIVE_INTERRUPT_STATUS_S 5 #define EMAC_MMC_INTERRUPT_STATUS (BIT(4)) +#define EMAC_MMC_INTERRUPT_STATUS_M (BIT(4)) +#define EMAC_MMC_INTERRUPT_STATUS_V 1 #define EMAC_MMC_INTERRUPT_STATUS_S 4 #define EMAC_PMT_INTERRUPT_STATUS (BIT(3)) +#define EMAC_PMT_INTERRUPT_STATUS_M (BIT(3)) +#define EMAC_PMT_INTERRUPT_STATUS_V 1 #define EMAC_PMT_INTERRUPT_STATUS_S 3 #define EMAC_PCS_AUTO_NEGOTIATION_COMPLETE (BIT(2)) +#define EMAC_PCS_AUTO_NEGOTIATION_COMPLETE_M (BIT(2)) +#define EMAC_PCS_AUTO_NEGOTIATION_COMPLETE_V 1 #define EMAC_PCS_AUTO_NEGOTIATION_COMPLETE_S 2 #define EMAC_PCS_LINK_STATUS_CHANGED (BIT(1)) +#define EMAC_PCS_LINK_STATUS_CHANGED_M (BIT(1)) +#define EMAC_PCS_LINK_STATUS_CHANGED_V 1 #define EMAC_PCS_LINK_STATUS_CHANGED_S 1 #define EMAC_INTERRUPT_STATUS (BIT(0)) +#define EMAC_INTERRUPT_STATUS_M (BIT(0)) +#define EMAC_INTERRUPT_STATUS_V 1 #define EMAC_INTERRUPT_STATUS_S 0 #define EMAC_GMACINTERRUPTMASK_REG (REG_EMAC_BASE + 0x103C) #define EMAC_LPI_INTERRUPT_MASK (BIT(10)) +#define EMAC_LPI_INTERRUPT_MASK_M (BIT(10)) +#define EMAC_LPI_INTERRUPT_MASK_V 1 #define EMAC_LPI_INTERRUPT_MASK_S 10 #define EMAC_TIMESTAMP_INTERRUPT_MASK (BIT(9)) +#define EMAC_TIMESTAMP_INTERRUPT_MASK_M (BIT(9)) +#define EMAC_TIMESTAMP_INTERRUPT_MASK_V 1 #define EMAC_TIMESTAMP_INTERRUPT_MASK_S 9 #define EMAC_PMT_INTERRUPT_MASK (BIT(3)) +#define EMAC_PMT_INTERRUPT_MASK_M (BIT(3)) +#define EMAC_PMT_INTERRUPT_MASK_V 1 #define EMAC_PMT_INTERRUPT_MASK_S 3 #define EMAC_PCS_AN_COMPLETION_INTERRUPT_MASK (BIT(2)) +#define EMAC_PCS_AN_COMPLETION_INTERRUPT_MASK_M (BIT(2)) +#define EMAC_PCS_AN_COMPLETION_INTERRUPT_MASK_V 1 #define EMAC_PCS_AN_COMPLETION_INTERRUPT_MASK_S 2 #define EMAC_PCS_LINK_STATUS_INTERRUPT_MASK (BIT(1)) +#define EMAC_PCS_LINK_STATUS_INTERRUPT_MASK_M (BIT(1)) +#define EMAC_PCS_LINK_STATUS_INTERRUPT_MASK_V 1 #define EMAC_PCS_LINK_STATUS_INTERRUPT_MASK_S 1 #define EMAC_INTERRUPT_MASK (BIT(0)) +#define EMAC_INTERRUPT_MASK_M (BIT(0)) +#define EMAC_INTERRUPT_MASK_V 1 #define EMAC_INTERRUPT_MASK_S 0 #define EMAC_GMACADDR0HIGH_REG (REG_EMAC_BASE + 0x1040) #define EMAC_ADDRESS_ENABLE0 (BIT(31)) +#define EMAC_ADDRESS_ENABLE0_M (BIT(31)) +#define EMAC_ADDRESS_ENABLE0_V 1 #define EMAC_ADDRESS_ENABLE0_S 31 #define EMAC_MAC_ADDRESS0_HI 0x0000FFFF +#define EMAC_MAC_ADDRESS0_HI_M (EMAC_MAC_ADDRESS0_HI_V << EMAC_MAC_ADDRESS0_HI_S) +#define EMAC_MAC_ADDRESS0_HI_V 0x0000FFFF #define EMAC_MAC_ADDRESS0_HI_S 0 #define EMAC_GMACADDR0LOW_REG (REG_EMAC_BASE + 0x1044) #define EMAC_MAC_ADDRESS0_LOW 0xFFFFFFFF +#define EMAC_MAC_ADDRESS0_LOW_M (EMAC_MAC_ADDRESS0_LOW_V << EMAC_MAC_ADDRESS0_LOW_S) +#define EMAC_MAC_ADDRESS0_LOW_V 0xFFFFFFFF #define EMAC_MAC_ADDRESS0_LOW_S 0 #define EMAC_GMACADDR1HIGH_REG (REG_EMAC_BASE + 0x1048) #define EMAC_ADDRESS_ENABLE1 (BIT(31)) +#define EMAC_ADDRESS_ENABLE1_M (BIT(31)) +#define EMAC_ADDRESS_ENABLE1_V 1 #define EMAC_ADDRESS_ENABLE1_S 31 #define EMAC_SOURCE_ADDRESS (BIT(30)) +#define EMAC_SOURCE_ADDRESS_M (BIT(30)) +#define EMAC_SOURCE_ADDRESS_V 1 #define EMAC_SOURCE_ADDRESS_S 30 #define EMAC_MASK_BYTE_CONTROL 0x0000003F +#define EMAC_MASK_BYTE_CONTROL_M (EMAC_MASK_BYTE_CONTROL_V << EMAC_MASK_BYTE_CONTROL_S) +#define EMAC_MASK_BYTE_CONTROL_V 0x0000003F #define EMAC_MASK_BYTE_CONTROL_S 24 #define EMAC_MAC_ADDRESS1_HI 0x0000FFFF +#define EMAC_MAC_ADDRESS1_HI_M (EMAC_MAC_ADDRESS1_HI_V << EMAC_MAC_ADDRESS1_HI_S) +#define EMAC_MAC_ADDRESS1_HI_V 0x0000FFFF #define EMAC_MAC_ADDRESS1_HI_S 0 #define EMAC_GMACADDR1LOW_REG (REG_EMAC_BASE + 0x104C) #define EMAC_MAC_ADDRESS1_LOW 0xFFFFFFFF +#define EMAC_MAC_ADDRESS1_LOW_M (EMAC_MAC_ADDRESS1_LOW_V << EMAC_MAC_ADDRESS1_LOW_S) +#define EMAC_MAC_ADDRESS1_LOW_V 0xFFFFFFFF #define EMAC_MAC_ADDRESS1_LOW_S 0 #define EMAC_GMAC_AN_CONTROL_REG (REG_EMAC_BASE + 0x10C0) #define EMAC_SGMII_RAL_CONTROL (BIT(18)) +#define EMAC_SGMII_RAL_CONTROL_M (BIT(18)) +#define EMAC_SGMII_RAL_CONTROL_V 1 #define EMAC_SGMII_RAL_CONTROL_S 18 #define EMAC_LOCK_REFERENCE (BIT(17)) +#define EMAC_LOCK_REFERENCE_M (BIT(17)) +#define EMAC_LOCK_REFERENCE_V 1 #define EMAC_LOCK_REFERENCE_S 17 #define EMAC_ENABLE_COMMA_DETECT (BIT(16)) +#define EMAC_ENABLE_COMMA_DETECT_M (BIT(16)) +#define EMAC_ENABLE_COMMA_DETECT_V 1 #define EMAC_ENABLE_COMMA_DETECT_S 16 #define EMAC_EXTERNAL_LOOPBACK_ENABLE (BIT(14)) +#define EMAC_EXTERNAL_LOOPBACK_ENABLE_M (BIT(14)) +#define EMAC_EXTERNAL_LOOPBACK_ENABLE_V 1 #define EMAC_EXTERNAL_LOOPBACK_ENABLE_S 14 #define EMAC_AUTO_NEGOTIATION_ENABLE (BIT(12)) +#define EMAC_AUTO_NEGOTIATION_ENABLE_M (BIT(12)) +#define EMAC_AUTO_NEGOTIATION_ENABLE_V 1 #define EMAC_AUTO_NEGOTIATION_ENABLE_S 12 #define EMAC_RESTART_AUTO_NEGOTIATION (BIT(9)) +#define EMAC_RESTART_AUTO_NEGOTIATION_M (BIT(9)) +#define EMAC_RESTART_AUTO_NEGOTIATION_V 1 #define EMAC_RESTART_AUTO_NEGOTIATION_S 9 #define EMAC_GMAC_AN_STATUS_REG (REG_EMAC_BASE + 0x10C4) #define EMAC_EXTENDED_STATUS (BIT(8)) +#define EMAC_EXTENDED_STATUS_M (BIT(8)) +#define EMAC_EXTENDED_STATUS_V 1 #define EMAC_EXTENDED_STATUS_S 8 #define EMAC_AUTO_NEGOTIATION_COMPLETE (BIT(5)) +#define EMAC_AUTO_NEGOTIATION_COMPLETE_M (BIT(5)) +#define EMAC_AUTO_NEGOTIATION_COMPLETE_V 1 #define EMAC_AUTO_NEGOTIATION_COMPLETE_S 5 #define EMAC_AUTO_NEGOTIATION_ABILITY (BIT(3)) +#define EMAC_AUTO_NEGOTIATION_ABILITY_M (BIT(3)) +#define EMAC_AUTO_NEGOTIATION_ABILITY_V 1 #define EMAC_AUTO_NEGOTIATION_ABILITY_S 3 #define EMAC_LINK_AN_STATUS (BIT(2)) +#define EMAC_LINK_AN_STATUS_M (BIT(2)) +#define EMAC_LINK_AN_STATUS_V 1 #define EMAC_LINK_AN_STATUS_S 2 #define EMAC_GMAC_AUTO_NEGOTIATION_ADVERTISEMENT_REG (REG_EMAC_BASE + 0x10C8) #define EMAC_ADV_NEXT_PAGE_SUPPORT (BIT(15)) +#define EMAC_ADV_NEXT_PAGE_SUPPORT_M (BIT(15)) +#define EMAC_ADV_NEXT_PAGE_SUPPORT_V 1 #define EMAC_ADV_NEXT_PAGE_SUPPORT_S 15 #define EMAC_ADV_REMOTE_FAULT_ENCODING 0x00000003 +#define EMAC_ADV_REMOTE_FAULT_ENCODING_M (EMAC_ADV_REMOTE_FAULT_ENCODING_V << EMAC_ADV_REMOTE_FAULT_ENCODING_S) +#define EMAC_ADV_REMOTE_FAULT_ENCODING_V 0x00000003 #define EMAC_ADV_REMOTE_FAULT_ENCODING_S 12 #define EMAC_ADV_PAUSE_ENCODING 0x00000003 +#define EMAC_ADV_PAUSE_ENCODING_M (EMAC_ADV_PAUSE_ENCODING_V << EMAC_ADV_PAUSE_ENCODING_S) +#define EMAC_ADV_PAUSE_ENCODING_V 0x00000003 #define EMAC_ADV_PAUSE_ENCODING_S 7 #define EMAC_ADV_HALF_DUPLEX (BIT(6)) +#define EMAC_ADV_HALF_DUPLEX_M (BIT(6)) +#define EMAC_ADV_HALF_DUPLEX_V 1 #define EMAC_ADV_HALF_DUPLEX_S 6 #define EMAC_ADV_FULL_DUPLEX (BIT(5)) +#define EMAC_ADV_FULL_DUPLEX_M (BIT(5)) +#define EMAC_ADV_FULL_DUPLEX_V 1 #define EMAC_ADV_FULL_DUPLEX_S 5 #define EMAC_GMAC_AUTO_NEGOTIATION_LINK_PARTNER_ABILITY_REG (REG_EMAC_BASE + 0x10CC) #define EMAC_LINK_NEXT_PAGE_SUPPORT (BIT(15)) +#define EMAC_LINK_NEXT_PAGE_SUPPORT_M (BIT(15)) +#define EMAC_LINK_NEXT_PAGE_SUPPORT_V 1 #define EMAC_LINK_NEXT_PAGE_SUPPORT_S 15 #define EMAC_LINK_ACKNOWLEDGE (BIT(14)) +#define EMAC_LINK_ACKNOWLEDGE_M (BIT(14)) +#define EMAC_LINK_ACKNOWLEDGE_V 1 #define EMAC_LINK_ACKNOWLEDGE_S 14 #define EMAC_LINK_REMOTE_FAULT_ENCODING 0x00000003 +#define EMAC_LINK_REMOTE_FAULT_ENCODING_M (EMAC_LINK_REMOTE_FAULT_ENCODING_V << EMAC_LINK_REMOTE_FAULT_ENCODING_S) +#define EMAC_LINK_REMOTE_FAULT_ENCODING_V 0x00000003 #define EMAC_LINK_REMOTE_FAULT_ENCODING_S 12 #define EMAC_LINK_PAUSE_ENCODING 0x00000003 +#define EMAC_LINK_PAUSE_ENCODING_M (EMAC_LINK_PAUSE_ENCODING_V << EMAC_LINK_PAUSE_ENCODING_S) +#define EMAC_LINK_PAUSE_ENCODING_V 0x00000003 #define EMAC_LINK_PAUSE_ENCODING_S 7 #define EMAC_LINK_HALF_DUPLEX (BIT(6)) +#define EMAC_LINK_HALF_DUPLEX_M (BIT(6)) +#define EMAC_LINK_HALF_DUPLEX_V 1 #define EMAC_LINK_HALF_DUPLEX_S 6 #define EMAC_LINK_FULL_DUPLEX (BIT(5)) +#define EMAC_LINK_FULL_DUPLEX_M (BIT(5)) +#define EMAC_LINK_FULL_DUPLEX_V 1 #define EMAC_LINK_FULL_DUPLEX_S 5 #define EMAC_GMAC_AUTO_NEGOTIATION_EXPANSION_REG (REG_EMAC_BASE + 0x10D0) #define EMAC_NEXT_PAGE_ABILITY (BIT(2)) +#define EMAC_NEXT_PAGE_ABILITY_M (BIT(2)) +#define EMAC_NEXT_PAGE_ABILITY_V 1 #define EMAC_NEXT_PAGE_ABILITY_S 2 #define EMAC_NEW_PAGE_RECEIVED (BIT(1)) +#define EMAC_NEW_PAGE_RECEIVED_M (BIT(1)) +#define EMAC_NEW_PAGE_RECEIVED_V 1 #define EMAC_NEW_PAGE_RECEIVED_S 1 #define EMAC_GMAC_TBI_EXTENDED_STATUS_REG (REG_EMAC_BASE + 0x10D4) #define EMAC_1000BASE_X_FULL_DUPLEX_CAPABLE (BIT(15)) +#define EMAC_1000BASE_X_FULL_DUPLEX_CAPABLE_M (BIT(15)) +#define EMAC_1000BASE_X_FULL_DUPLEX_CAPABLE_V 1 #define EMAC_1000BASE_X_FULL_DUPLEX_CAPABLE_S 15 #define EMAC_1000BASE_X_HALF_DUPLEX_CAPABLE (BIT(14)) +#define EMAC_1000BASE_X_HALF_DUPLEX_CAPABLE_M (BIT(14)) +#define EMAC_1000BASE_X_HALF_DUPLEX_CAPABLE_V 1 #define EMAC_1000BASE_X_HALF_DUPLEX_CAPABLE_S 14 #define EMAC_GMAC_CONTROL_STATUS_REG (REG_EMAC_BASE + 0x10D8) #define EMAC_SMIDRXS (BIT(16)) +#define EMAC_SMIDRXS_M (BIT(16)) +#define EMAC_SMIDRXS_V 1 #define EMAC_SMIDRXS_S 16 #define EMAC_FALSE_CARRIER_DETECTED (BIT(5)) +#define EMAC_FALSE_CARRIER_DETECTED_M (BIT(5)) +#define EMAC_FALSE_CARRIER_DETECTED_V 1 #define EMAC_FALSE_CARRIER_DETECTED_S 5 #define EMAC_JABBER_TIMEOUT (BIT(4)) +#define EMAC_JABBER_TIMEOUT_M (BIT(4)) +#define EMAC_JABBER_TIMEOUT_V 1 #define EMAC_JABBER_TIMEOUT_S 4 #define EMAC_LINK_STATUS (BIT(3)) +#define EMAC_LINK_STATUS_M (BIT(3)) +#define EMAC_LINK_STATUS_V 1 #define EMAC_LINK_STATUS_S 3 #define EMAC_LINK_SPEED 0x00000003 +#define EMAC_LINK_SPEED_M (EMAC_LINK_SPEED_V << EMAC_LINK_SPEED_S) +#define EMAC_LINK_SPEED_V 0x00000003 #define EMAC_LINK_SPEED_S 1 #define EMAC_LINK_MODE (BIT(0)) +#define EMAC_LINK_MODE_M (BIT(0)) +#define EMAC_LINK_MODE_V 1 #define EMAC_LINK_MODE_S 0 #define EMAC_GMAC_WATCHDOG_TIMEOUT_REG (REG_EMAC_BASE + 0x10DC) #define EMAC_PROGRAMMABLE_WATCHDOG_ENABLE (BIT(16)) +#define EMAC_PROGRAMMABLE_WATCHDOG_ENABLE_M (BIT(16)) +#define EMAC_PROGRAMMABLE_WATCHDOG_ENABLE_V 1 #define EMAC_PROGRAMMABLE_WATCHDOG_ENABLE_S 16 #define EMAC_WATCHDOG_TIMEOUT 0x00003FFF +#define EMAC_WATCHDOG_TIMEOUT_M (EMAC_WATCHDOG_TIMEOUT_V << EMAC_WATCHDOG_TIMEOUT_S) +#define EMAC_WATCHDOG_TIMEOUT_V 0x00003FFF #define EMAC_WATCHDOG_TIMEOUT_S 0 #define EMAC_GMAC_GENERAL_PURPOSE_IO_REG (REG_EMAC_BASE + 0x10E0) #define EMAC_GPI_TYPE 0x0000000F +#define EMAC_GPI_TYPE_M (EMAC_GPI_TYPE_V << EMAC_GPI_TYPE_S) +#define EMAC_GPI_TYPE_V 0x0000000F #define EMAC_GPI_TYPE_S 24 #define EMAC_GPI_INTERRUPT_ENABLE 0x0000000F +#define EMAC_GPI_INTERRUPT_ENABLE_M (EMAC_GPI_INTERRUPT_ENABLE_V << EMAC_GPI_INTERRUPT_ENABLE_S) +#define EMAC_GPI_INTERRUPT_ENABLE_V 0x0000000F #define EMAC_GPI_INTERRUPT_ENABLE_S 16 #define EMAC_GENERAL_PURPOSE_OUTPUT 0x0000000F +#define EMAC_GENERAL_PURPOSE_OUTPUT_M (EMAC_GENERAL_PURPOSE_OUTPUT_V << EMAC_GENERAL_PURPOSE_OUTPUT_S) +#define EMAC_GENERAL_PURPOSE_OUTPUT_V 0x0000000F #define EMAC_GENERAL_PURPOSE_OUTPUT_S 8 #define EMAC_GENERAL_PURPOSE_INPUT_STATUS 0x0000000F +#define EMAC_GENERAL_PURPOSE_INPUT_STATUS_M (EMAC_GENERAL_PURPOSE_INPUT_STATUS_V << EMAC_GENERAL_PURPOSE_INPUT_STATUS_S) +#define EMAC_GENERAL_PURPOSE_INPUT_STATUS_V 0x0000000F #define EMAC_GENERAL_PURPOSE_INPUT_STATUS_S 0 #define EMAC_GMAC_LAYER3_LAYER4_CONTROL0_REG (REG_EMAC_BASE + 0x1400) #define EMAC_LAYER4_DESTINATION_PORT_INVERSE_MATCH_ENABLE (BIT(21)) +#define EMAC_LAYER4_DESTINATION_PORT_INVERSE_MATCH_ENABLE_M (BIT(21)) +#define EMAC_LAYER4_DESTINATION_PORT_INVERSE_MATCH_ENABLE_V 1 #define EMAC_LAYER4_DESTINATION_PORT_INVERSE_MATCH_ENABLE_S 21 #define EMAC_LAYER4_DESTINATION_PORT_MATCH_ENABLE (BIT(20)) +#define EMAC_LAYER4_DESTINATION_PORT_MATCH_ENABLE_M (BIT(20)) +#define EMAC_LAYER4_DESTINATION_PORT_MATCH_ENABLE_V 1 #define EMAC_LAYER4_DESTINATION_PORT_MATCH_ENABLE_S 20 #define EMAC_LAYER4_SOURCE_PORT_INVERSE_MATCH_ENABLE (BIT(19)) +#define EMAC_LAYER4_SOURCE_PORT_INVERSE_MATCH_ENABLE_M (BIT(19)) +#define EMAC_LAYER4_SOURCE_PORT_INVERSE_MATCH_ENABLE_V 1 #define EMAC_LAYER4_SOURCE_PORT_INVERSE_MATCH_ENABLE_S 19 #define EMAC_LAYER4_SOURCE_PORT_MATCH_ENABLE (BIT(18)) +#define EMAC_LAYER4_SOURCE_PORT_MATCH_ENABLE_M (BIT(18)) +#define EMAC_LAYER4_SOURCE_PORT_MATCH_ENABLE_V 1 #define EMAC_LAYER4_SOURCE_PORT_MATCH_ENABLE_S 18 #define EMAC_LAYER4_PROTOCOL_ENABLE (BIT(16)) +#define EMAC_LAYER4_PROTOCOL_ENABLE_M (BIT(16)) +#define EMAC_LAYER4_PROTOCOL_ENABLE_V 1 #define EMAC_LAYER4_PROTOCOL_ENABLE_S 16 #define EMAC_LAYER3_IP_DA_HIGHER_BITS_MATCH 0x0000001F +#define EMAC_LAYER3_IP_DA_HIGHER_BITS_MATCH_M (EMAC_LAYER3_IP_DA_HIGHER_BITS_MATCH_V << EMAC_LAYER3_IP_DA_HIGHER_BITS_MATCH_S) +#define EMAC_LAYER3_IP_DA_HIGHER_BITS_MATCH_V 0x0000001F #define EMAC_LAYER3_IP_DA_HIGHER_BITS_MATCH_S 11 #define EMAC_LAYER3_IP_SA_HIGHER_BITS_MATCH 0x0000001F +#define EMAC_LAYER3_IP_SA_HIGHER_BITS_MATCH_M (EMAC_LAYER3_IP_SA_HIGHER_BITS_MATCH_V << EMAC_LAYER3_IP_SA_HIGHER_BITS_MATCH_S) +#define EMAC_LAYER3_IP_SA_HIGHER_BITS_MATCH_V 0x0000001F #define EMAC_LAYER3_IP_SA_HIGHER_BITS_MATCH_S 6 #define EMAC_LAYER3_IP_DA_INVERSE_MATCH_ENABLE (BIT(5)) +#define EMAC_LAYER3_IP_DA_INVERSE_MATCH_ENABLE_M (BIT(5)) +#define EMAC_LAYER3_IP_DA_INVERSE_MATCH_ENABLE_V 1 #define EMAC_LAYER3_IP_DA_INVERSE_MATCH_ENABLE_S 5 #define EMAC_LAYER3_IP_DA_MATCH_ENABLE (BIT(4)) +#define EMAC_LAYER3_IP_DA_MATCH_ENABLE_M (BIT(4)) +#define EMAC_LAYER3_IP_DA_MATCH_ENABLE_V 1 #define EMAC_LAYER3_IP_DA_MATCH_ENABLE_S 4 #define EMAC_LAYER3_IP_SA_INVERSE_MATCH_ENABLE (BIT(3)) +#define EMAC_LAYER3_IP_SA_INVERSE_MATCH_ENABLE_M (BIT(3)) +#define EMAC_LAYER3_IP_SA_INVERSE_MATCH_ENABLE_V 1 #define EMAC_LAYER3_IP_SA_INVERSE_MATCH_ENABLE_S 3 #define EMAC_LAYER3_IP_SA_MATCH_ENABLE (BIT(2)) +#define EMAC_LAYER3_IP_SA_MATCH_ENABLE_M (BIT(2)) +#define EMAC_LAYER3_IP_SA_MATCH_ENABLE_V 1 #define EMAC_LAYER3_IP_SA_MATCH_ENABLE_S 2 #define EMAC_LAYER3_PROTOCOL_ENABLE (BIT(0)) +#define EMAC_LAYER3_PROTOCOL_ENABLE_M (BIT(0)) +#define EMAC_LAYER3_PROTOCOL_ENABLE_V 1 #define EMAC_LAYER3_PROTOCOL_ENABLE_S 0 #define EMAC_GMAC_LAYER4_ADDRESS0_REG (REG_EMAC_BASE + 0x1404) #define EMAC_LAYER4_DESTINATION_PORT_NUMBER_FIELD 0x0000FFFF +#define EMAC_LAYER4_DESTINATION_PORT_NUMBER_FIELD_M (EMAC_LAYER4_DESTINATION_PORT_NUMBER_FIELD_V << EMAC_LAYER4_DESTINATION_PORT_NUMBER_FIELD_S) +#define EMAC_LAYER4_DESTINATION_PORT_NUMBER_FIELD_V 0x0000FFFF #define EMAC_LAYER4_DESTINATION_PORT_NUMBER_FIELD_S 16 #define EMAC_LAYER4_SOURCE_PORT_NUMBER_FIELD 0x0000FFFF +#define EMAC_LAYER4_SOURCE_PORT_NUMBER_FIELD_M (EMAC_LAYER4_SOURCE_PORT_NUMBER_FIELD_V << EMAC_LAYER4_SOURCE_PORT_NUMBER_FIELD_S) +#define EMAC_LAYER4_SOURCE_PORT_NUMBER_FIELD_V 0x0000FFFF #define EMAC_LAYER4_SOURCE_PORT_NUMBER_FIELD_S 0 #define EMAC_GMAC_LAYER3_ADDRESS0_REG (REG_EMAC_BASE + 0x1410) #define EMAC_LAYER3_ADDRESS0_FIELD 0xFFFFFFFF +#define EMAC_LAYER3_ADDRESS0_FIELD_M (EMAC_LAYER3_ADDRESS0_FIELD_V << EMAC_LAYER3_ADDRESS0_FIELD_S) +#define EMAC_LAYER3_ADDRESS0_FIELD_V 0xFFFFFFFF #define EMAC_LAYER3_ADDRESS0_FIELD_S 0 #define EMAC_GMAC_LAYER3_ADDRESS1_REG (REG_EMAC_BASE + 0x1414) #define EMAC_LAYER3_ADDRESS1_FIELD 0xFFFFFFFF +#define EMAC_LAYER3_ADDRESS1_FIELD_M (EMAC_LAYER3_ADDRESS1_FIELD_V << EMAC_LAYER3_ADDRESS1_FIELD_S) +#define EMAC_LAYER3_ADDRESS1_FIELD_V 0xFFFFFFFF #define EMAC_LAYER3_ADDRESS1_FIELD_S 0 #define EMAC_GMAC_LAYER3_ADDRESS2_REG (REG_EMAC_BASE + 0x1418) #define EMAC_LAYER3_ADDRESS2_FIELD 0xFFFFFFFF +#define EMAC_LAYER3_ADDRESS2_FIELD_M (EMAC_LAYER3_ADDRESS2_FIELD_V << EMAC_LAYER3_ADDRESS2_FIELD_S) +#define EMAC_LAYER3_ADDRESS2_FIELD_V 0xFFFFFFFF #define EMAC_LAYER3_ADDRESS2_FIELD_S 0 #define EMAC_GMAC_LAYER3_ADDRESS3_REG (REG_EMAC_BASE + 0x141C) #define EMAC_LAYER3_ADDRESS3_FIELD 0xFFFFFFFF +#define EMAC_LAYER3_ADDRESS3_FIELD_M (EMAC_LAYER3_ADDRESS3_FIELD_V << EMAC_LAYER3_ADDRESS3_FIELD_S) +#define EMAC_LAYER3_ADDRESS3_FIELD_V 0xFFFFFFFF #define EMAC_LAYER3_ADDRESS3_FIELD_S 0 #define EMAC_GMAC_HASH_TABLE0_REG (REG_EMAC_BASE + 0x1500) #define EMAC_FIRST32_BITS_HASH_TABLE 0xFFFFFFFF +#define EMAC_FIRST32_BITS_HASH_TABLE_M (EMAC_FIRST32_BITS_HASH_TABLE_V << EMAC_FIRST32_BITS_HASH_TABLE_S) +#define EMAC_FIRST32_BITS_HASH_TABLE_V 0xFFFFFFFF #define EMAC_FIRST32_BITS_HASH_TABLE_S 0 #define EMAC_GMAC_VLAN_TAG_INCLUSION_REPLACEMENT_REG (REG_EMAC_BASE + 0x1584) #define EMAC_VLAN_C_VLAN_S_VLAN (BIT(19)) +#define EMAC_VLAN_C_VLAN_S_VLAN_M (BIT(19)) +#define EMAC_VLAN_C_VLAN_S_VLAN_V 1 #define EMAC_VLAN_C_VLAN_S_VLAN_S 19 #define EMAC_VLAN_PRIORITY_CONTROL (BIT(18)) +#define EMAC_VLAN_PRIORITY_CONTROL_M (BIT(18)) +#define EMAC_VLAN_PRIORITY_CONTROL_V 1 #define EMAC_VLAN_PRIORITY_CONTROL_S 18 #define EMAC_VLAN_TAG_CONTROL_TRANSMIT_FRAMES 0x00000003 +#define EMAC_VLAN_TAG_CONTROL_TRANSMIT_FRAMES_M (EMAC_VLAN_TAG_CONTROL_TRANSMIT_FRAMES_V << EMAC_VLAN_TAG_CONTROL_TRANSMIT_FRAMES_S) +#define EMAC_VLAN_TAG_CONTROL_TRANSMIT_FRAMES_V 0x00000003 #define EMAC_VLAN_TAG_CONTROL_TRANSMIT_FRAMES_S 16 #define EMAC_VLAN_TAG_TRANSMIT_FRAMES 0x0000FFFF +#define EMAC_VLAN_TAG_TRANSMIT_FRAMES_M (EMAC_VLAN_TAG_TRANSMIT_FRAMES_V << EMAC_VLAN_TAG_TRANSMIT_FRAMES_S) +#define EMAC_VLAN_TAG_TRANSMIT_FRAMES_V 0x0000FFFF #define EMAC_VLAN_TAG_TRANSMIT_FRAMES_S 0 #define EMAC_GMAC_VLAN_HASH_TABLE_REG (REG_EMAC_BASE + 0x1588) #define EMAC_VLAN_HASH_TABLE 0x0000FFFF +#define EMAC_VLAN_HASH_TABLE_M (EMAC_VLAN_HASH_TABLE_V << EMAC_VLAN_HASH_TABLE_S) +#define EMAC_VLAN_HASH_TABLE_V 0x0000FFFF #define EMAC_VLAN_HASH_TABLE_S 0 #ifdef __cplusplus diff --git a/components/soc/esp32/include/soc/fe_reg.h b/components/soc/esp32/include/soc/fe_reg.h index f8c2ce58f..7705586d7 100644 --- a/components/soc/esp32/include/soc/fe_reg.h +++ b/components/soc/esp32/include/soc/fe_reg.h @@ -22,12 +22,20 @@ #define FE_GEN_CTRL (DR_REG_FE_BASE + 0x0090) #define FE_IQ_EST_FORCE_PU (BIT(5)) +#define FE_IQ_EST_FORCE_PU_M (BIT(5)) +#define FE_IQ_EST_FORCE_PU_V 1 #define FE_IQ_EST_FORCE_PU_S 5 #define FE_IQ_EST_FORCE_PD (BIT(4)) +#define FE_IQ_EST_FORCE_PD_M (BIT(4)) +#define FE_IQ_EST_FORCE_PD_V 1 #define FE_IQ_EST_FORCE_PD_S 4 #define FE2_TX_INTERP_CTRL (DR_REG_FE2_BASE + 0x00f0) #define FE2_TX_INF_FORCE_PU (BIT(10)) +#define FE2_TX_INF_FORCE_PU_M (BIT(10)) +#define FE2_TX_INF_FORCE_PU_V 1 #define FE2_TX_INF_FORCE_PU_S 10 #define FE2_TX_INF_FORCE_PD (BIT(9)) +#define FE2_TX_INF_FORCE_PD_M (BIT(9)) +#define FE2_TX_INF_FORCE_PD_V 1 #define FE2_TX_INF_FORCE_PD_S 9 diff --git a/components/soc/esp32/include/soc/io_mux_reg.h b/components/soc/esp32/include/soc/io_mux_reg.h index 459a97009..2598989d0 100644 --- a/components/soc/esp32/include/soc/io_mux_reg.h +++ b/components/soc/esp32/include/soc/io_mux_reg.h @@ -1,9 +1,9 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// Copyright 2015-2017 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 @@ -16,19 +16,61 @@ #include "soc.h" +/* The following are the bit fields for PERIPHS_IO_MUX_x_U registers */ +/* Output enable in sleep mode */ #define SLP_OE (BIT(0)) +#define SLP_OE_M (BIT(0)) +#define SLP_OE_V 1 +#define SLP_OE_S 0 +/* Pin used for wakeup from sleep */ #define SLP_SEL (BIT(1)) +#define SLP_SEL_M (BIT(1)) +#define SLP_SEL_V 1 +#define SLP_SEL_S 1 +/* Pulldown enable in sleep mode */ #define SLP_PD (BIT(2)) +#define SLP_PD_M (BIT(2)) +#define SLP_PD_V 1 +#define SLP_PD_S 2 +/* Pullup enable in sleep mode */ #define SLP_PU (BIT(3)) +#define SLP_PU_M (BIT(3)) +#define SLP_PU_V 1 +#define SLP_PU_S 3 +/* Input enable in sleep mode */ #define SLP_IE (BIT(4)) +#define SLP_IE_M (BIT(4)) +#define SLP_IE_V 1 +#define SLP_IE_S 4 +/* Drive strength in sleep mode */ #define SLP_DRV 0x3 +#define SLP_DRV_M (SLP_DRV_V << SLP_DRV_S) +#define SLP_DRV_V 0x3 #define SLP_DRV_S 5 +/* Pulldown enable */ #define FUN_PD (BIT(7)) +#define FUN_PD_M (BIT(7)) +#define FUN_PD_V 1 +#define FUN_PD_S 7 +/* Pullup enable */ #define FUN_PU (BIT(8)) +#define FUN_PU_M (BIT(8)) +#define FUN_PU_V 1 +#define FUN_PU_S 8 +/* Input enable */ #define FUN_IE (BIT(9)) +#define FUN_IE_M (FUN_IE_V << FUN_IE_S) +#define FUN_IE_V 1 +#define FUN_IE_S 9 +/* Drive strength */ #define FUN_DRV 0x3 +#define FUN_DRV_M (FUN_DRV_V << FUN_DRV_S) +#define FUN_DRV_V 0x3 #define FUN_DRV_S 10 +/* Function select (possible values are defined for each pin as FUNC_pinname_function below) */ #define MCU_SEL 0x7 +#define MCU_SEL_M (MCU_SEL_V << MCU_SEL_S) +#define MCU_SEL_V 0x7 #define MCU_SEL_S 12 #define PIN_INPUT_ENABLE(PIN_NAME) SET_PERI_REG_MASK(PIN_NAME,FUN_IE) diff --git a/components/soc/esp32/include/soc/nrx_reg.h b/components/soc/esp32/include/soc/nrx_reg.h index cd13319c9..ca338b89a 100644 --- a/components/soc/esp32/include/soc/nrx_reg.h +++ b/components/soc/esp32/include/soc/nrx_reg.h @@ -22,18 +22,34 @@ #define NRXPD_CTRL (DR_REG_NRX_BASE + 0x00d4) #define NRX_CHAN_EST_FORCE_PU (BIT(7)) +#define NRX_CHAN_EST_FORCE_PU_M (BIT(7)) +#define NRX_CHAN_EST_FORCE_PU_V 1 #define NRX_CHAN_EST_FORCE_PU_S 7 #define NRX_CHAN_EST_FORCE_PD (BIT(6)) +#define NRX_CHAN_EST_FORCE_PD_M (BIT(6)) +#define NRX_CHAN_EST_FORCE_PD_V 1 #define NRX_CHAN_EST_FORCE_PD_S 6 #define NRX_RX_ROT_FORCE_PU (BIT(5)) +#define NRX_RX_ROT_FORCE_PU_M (BIT(5)) +#define NRX_RX_ROT_FORCE_PU_V 1 #define NRX_RX_ROT_FORCE_PU_S 5 #define NRX_RX_ROT_FORCE_PD (BIT(4)) +#define NRX_RX_ROT_FORCE_PD_M (BIT(4)) +#define NRX_RX_ROT_FORCE_PD_V 1 #define NRX_RX_ROT_FORCE_PD_S 4 #define NRX_VIT_FORCE_PU (BIT(3)) +#define NRX_VIT_FORCE_PU_M (BIT(3)) +#define NRX_VIT_FORCE_PU_V 1 #define NRX_VIT_FORCE_PU_S 3 #define NRX_VIT_FORCE_PD (BIT(2)) +#define NRX_VIT_FORCE_PD_M (BIT(2)) +#define NRX_VIT_FORCE_PD_V 1 #define NRX_VIT_FORCE_PD_S 2 #define NRX_DEMAP_FORCE_PU (BIT(1)) +#define NRX_DEMAP_FORCE_PU_M (BIT(1)) +#define NRX_DEMAP_FORCE_PU_V 1 #define NRX_DEMAP_FORCE_PU_S 1 #define NRX_DEMAP_FORCE_PD (BIT(0)) +#define NRX_DEMAP_FORCE_PD_M (BIT(0)) +#define NRX_DEMAP_FORCE_PD_V 1 #define NRX_DEMAP_FORCE_PD_S 0 diff --git a/components/soc/esp32/include/soc/rtc.h b/components/soc/esp32/include/soc/rtc.h index aecf76bec..a0813294a 100644 --- a/components/soc/esp32/include/soc/rtc.h +++ b/components/soc/esp32/include/soc/rtc.h @@ -92,6 +92,9 @@ typedef enum { RTC_FAST_FREQ_8M = 1, //!< Internal 8 MHz RC oscillator } rtc_fast_freq_t; +/* With the default value of CK8M_DFREQ, 8M clock frequency is 8.5 MHz +/- 7% */ +#define RTC_FAST_CLK_FREQ_APPROX 8500000 + /** * @brief Clock source to be calibrated using rtc_clk_cal function */ @@ -307,6 +310,15 @@ uint32_t rtc_clk_apb_freq_get(); */ uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slow_clk_cycles); +/** + * @brief Measure ratio between XTAL frequency and RTC slow clock frequency + * @param cal_clk slow clock to be measured + * @param slow_clk_cycles number of slow clock cycles to average + * @return average ratio between XTAL frequency and slow clock frequency, + * Q13.19 fixed point format, or 0 if calibration has timed out. + */ +uint32_t rtc_clk_cal_ratio(rtc_cal_sel_t cal_clk, uint32_t slow_clk_cycles); + /** * @brief Convert time interval from microseconds to RTC_SLOW_CLK cycles * @param time_in_us Time interval in microseconds diff --git a/components/soc/esp32/include/soc/rtc_io_reg.h b/components/soc/esp32/include/soc/rtc_io_reg.h index f6d0dac76..5a3ce10d4 100644 --- a/components/soc/esp32/include/soc/rtc_io_reg.h +++ b/components/soc/esp32/include/soc/rtc_io_reg.h @@ -511,6 +511,7 @@ #define RTC_IO_DEBUG_SEL0_M ((RTC_IO_DEBUG_SEL0_V)<<(RTC_IO_DEBUG_SEL0_S)) #define RTC_IO_DEBUG_SEL0_V 0x1F #define RTC_IO_DEBUG_SEL0_S 0 +#define RTC_IO_DEBUG_SEL0_8M 1 #define RTC_IO_DEBUG_SEL0_32K_XTAL 4 #define RTC_IO_DEBUG_SEL0_150K_OSC 5 diff --git a/components/soc/esp32/include/soc/soc.h b/components/soc/esp32/include/soc/soc.h index 18dd093ff..fe6acee2a 100644 --- a/components/soc/esp32/include/soc/soc.h +++ b/components/soc/esp32/include/soc/soc.h @@ -1,9 +1,9 @@ -// Copyright 2010-2016 Espressif Systems (Shanghai) PTE LTD +// Copyright 2010-2017 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 @@ -89,8 +89,8 @@ //get field from register, uses field _S & _V to determine mask #define REG_GET_FIELD(_r, _f) ((REG_READ(_r) >> (_f##_S)) & (_f##_V)) -//set field to register, used when _f is not left shifted by _f##_S -#define REG_SET_FIELD(_r, _f, _v) (REG_WRITE((_r),((REG_READ(_r) & ~((_f) << (_f##_S)))|(((_v) & (_f))<<(_f##_S))))) +//set field of a register from variable, uses field _S & _V to determine mask +#define REG_SET_FIELD(_r, _f, _v) (REG_WRITE((_r),((REG_READ(_r) & ~((_f##_V) << (_f##_S)))|(((_v) & (_f##_V))<<(_f##_S))))) //get field value from a variable, used when _f is not left shifted by _f##_S #define VALUE_GET_FIELD(_r, _f) (((_r) >> (_f##_S)) & (_f)) diff --git a/components/soc/esp32/rtc_clk.c b/components/soc/esp32/rtc_clk.c index 79b56f993..1397705c2 100644 --- a/components/soc/esp32/rtc_clk.c +++ b/components/soc/esp32/rtc_clk.c @@ -67,6 +67,11 @@ static const char* TAG = "rtc_clk"; #define DELAY_SLOW_CLK_SWITCH 300 #define DELAY_8M_ENABLE 50 +/* Number of 8M/256 clock cycles to use for XTAL frequency estimation. + * 10 cycles will take approximately 300 microseconds. + */ +#define XTAL_FREQ_EST_CYCLES 10 + void rtc_clk_32k_enable(bool enable) { @@ -422,19 +427,12 @@ void rtc_clk_xtal_freq_update(rtc_xtal_freq_t xtal_freq) static rtc_xtal_freq_t rtc_clk_xtal_freq_estimate() { - /* ROM startup code estimates XTAL frequency using an 8MD256 clock and stores - * the value into RTC_APB_FREQ_REG. The value is in Hz, right shifted by 12. - * Use this value to guess the real XTAL frequency. - * - * TODO: make this more robust by calibrating again after setting - * RTC_CNTL_CK8M_DFREQ. + uint64_t cal_val = rtc_clk_cal_ratio(RTC_CAL_8MD256, XTAL_FREQ_EST_CYCLES); + /* cal_val contains period of 8M/256 clock in XTAL clock cycles + * (shifted by RTC_CLK_CAL_FRACT bits). + * Xtal frequency will be (cal_val * 8M / 256) / 2^19 */ - uint32_t apb_freq_reg = READ_PERI_REG(RTC_APB_FREQ_REG); - if (!clk_val_is_valid(apb_freq_reg)) { - SOC_LOGW(TAG, "invalid RTC_APB_FREQ_REG value: 0x%08x", apb_freq_reg); - return RTC_XTAL_FREQ_AUTO; - } - uint32_t freq_mhz = (reg_val_to_clk_val(apb_freq_reg) << 12) / MHZ; + uint32_t freq_mhz = (cal_val * (RTC_FAST_CLK_FREQ_APPROX / MHZ) / 256 ) >> RTC_CLK_CAL_FRACT; /* Guess the XTAL type. For now, only 40 and 26MHz are supported. */ switch (freq_mhz) { @@ -467,6 +465,19 @@ uint32_t rtc_clk_apb_freq_get() void rtc_clk_init(rtc_clk_config_t cfg) { + /* If we get a TG WDT system reset while running at 240MHz, + * DPORT_CPUPERIOD_SEL register will be reset to 0 resulting in 120MHz + * APB and CPU frequencies after reset. This will cause issues with XTAL + * frequency estimation, so we switch to XTAL frequency first. + * + * Ideally we would only do this if RTC_CNTL_SOC_CLK_SEL == PLL and + * PLL is configured for 480M, but it takes less time to switch to 40M and + * run the following code than querying the PLL does. + */ + if (REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_SOC_CLK_SEL) == RTC_CNTL_SOC_CLK_SEL_PLL) { + rtc_clk_cpu_freq_set(RTC_CPU_FREQ_XTAL); + } + /* Set tuning parameters for 8M and 150k clocks. * Note: this doesn't attempt to set the clocks to precise frequencies. * Instead, we calibrate these clocks against XTAL frequency later, when necessary. @@ -488,10 +499,16 @@ void rtc_clk_init(rtc_clk_config_t cfg) /* Estimate XTAL frequency if requested */ rtc_xtal_freq_t xtal_freq = cfg.xtal_freq; if (xtal_freq == RTC_XTAL_FREQ_AUTO) { - xtal_freq = rtc_clk_xtal_freq_estimate(); - if (xtal_freq == RTC_XTAL_FREQ_AUTO) { - SOC_LOGW(TAG, "Can't estimate XTAL frequency, assuming 26MHz"); - xtal_freq = RTC_XTAL_FREQ_26M; + if (clk_val_is_valid(READ_PERI_REG(RTC_XTAL_FREQ_REG))) { + /* XTAL frequency has already been set, use existing value */ + xtal_freq = rtc_clk_xtal_freq_get(); + } else { + /* Not set yet, estimate XTAL frequency based on RTC_FAST_CLK */ + xtal_freq = rtc_clk_xtal_freq_estimate(); + if (xtal_freq == RTC_XTAL_FREQ_AUTO) { + SOC_LOGW(TAG, "Can't estimate XTAL frequency, assuming 26MHz"); + xtal_freq = RTC_XTAL_FREQ_26M; + } } } rtc_clk_xtal_freq_update(xtal_freq); @@ -515,20 +532,3 @@ void rtc_clk_init(rtc_clk_config_t cfg) * TODO: update the library to use rtc_clk_xtal_freq_get */ rtc_xtal_freq_t rtc_get_xtal() __attribute__((alias("rtc_clk_xtal_freq_get"))); - - -/* Referenced in librtc.a:rtc.o. - * TODO: remove - */ -void rtc_uart_div_modify(int latch) -{ - -} - -/* Referenced in librtc.a:rtc.o. - * TODO: remove - */ -void rtc_uart_tx_wait_idle(int uart) -{ - -} diff --git a/components/soc/esp32/rtc_time.c b/components/soc/esp32/rtc_time.c index 7b1fb45f3..9e974cc94 100644 --- a/components/soc/esp32/rtc_time.c +++ b/components/soc/esp32/rtc_time.c @@ -31,9 +31,8 @@ * once, and TIMG_RTC_CALI_RDY bit is set when counting is done. One-off mode is * enabled using TIMG_RTC_CALI_START bit. */ -uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles) +uint32_t rtc_clk_cal_ratio(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles) { - rtc_xtal_freq_t xtal_freq = rtc_clk_xtal_freq_get(); /* Enable requested clock (150k clock is always on) */ if (cal_clk == RTC_CAL_32K_XTAL) { SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN); @@ -53,7 +52,7 @@ uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles) expected_freq = 32768; /* standard 32k XTAL */ } else if (cal_clk == RTC_CAL_8MD256 || (cal_clk == RTC_CAL_RTC_MUX && slow_freq == RTC_SLOW_FREQ_8MD256)) { - expected_freq = 8 * MHZ / 256; + expected_freq = RTC_FAST_CLK_FREQ_APPROX / 256; } else { expected_freq = 150000; /* 150k internal oscillator */ } @@ -69,7 +68,8 @@ uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles) /* Wait for calibration to finish up to another us_time_estimate */ int timeout_us = us_time_estimate; while (!GET_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_RDY) && - timeout_us-- > 0) { + timeout_us > 0) { + timeout_us--; ets_delay_us(1); } if (cal_clk == RTC_CAL_32K_XTAL) { @@ -84,9 +84,16 @@ uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles) } uint64_t xtal_cycles = REG_GET_FIELD(TIMG_RTCCALICFG1_REG(0), TIMG_RTC_CALI_VALUE); - uint64_t divider = ((uint64_t)xtal_freq) * slowclk_cycles; - uint64_t period_64 = (xtal_cycles << RTC_CLK_CAL_FRACT) / divider; - uint32_t period = (uint32_t)(period_64 & UINT32_MAX); + uint64_t ratio_64 = (xtal_cycles << RTC_CLK_CAL_FRACT) / slowclk_cycles; + uint32_t ratio = (uint32_t)(ratio_64 & UINT32_MAX); + return ratio; +} + +uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles) +{ + rtc_xtal_freq_t xtal_freq = rtc_clk_xtal_freq_get(); + uint32_t ratio = rtc_clk_cal_ratio(cal_clk, slowclk_cycles); + uint32_t period = ratio / xtal_freq; return period; } diff --git a/components/soc/esp32/test/test_rtc_clk.c b/components/soc/esp32/test/test_rtc_clk.c index cad78297b..48905acd0 100644 --- a/components/soc/esp32/test/test_rtc_clk.c +++ b/components/soc/esp32/test/test_rtc_clk.c @@ -82,3 +82,10 @@ TEST_CASE("Output 32k XTAL clock to GPIO25", "[rtc_clk][ignore]") rtc_clk_32k_enable(true); pull_out_clk(RTC_IO_DEBUG_SEL0_32K_XTAL); } + +TEST_CASE("Output 8M XTAL clock to GPIO25", "[rtc_clk][ignore]") +{ + rtc_clk_8m_enable(true, true); + SET_PERI_REG_MASK(RTC_IO_RTC_DEBUG_SEL_REG, RTC_IO_DEBUG_12M_NO_GATING); + pull_out_clk(RTC_IO_DEBUG_SEL0_8M); +} diff --git a/components/spi_flash/spi_flash_rom_patch.c b/components/spi_flash/spi_flash_rom_patch.c index 0664c7482..ec59a1ff1 100644 --- a/components/spi_flash/spi_flash_rom_patch.c +++ b/components/spi_flash/spi_flash_rom_patch.c @@ -87,9 +87,6 @@ extern uint8_t g_rom_spiflash_dummy_len_plus[]; static esp_rom_spiflash_result_t esp_rom_spiflash_enable_write(esp_rom_spiflash_chip_t *spi); -static esp_rom_spiflash_result_t esp_rom_spiflash_enable_qmode(esp_rom_spiflash_chip_t *spi); -static esp_rom_spiflash_result_t esp_rom_spiflash_disable_qmode(esp_rom_spiflash_chip_t *spi); - //only support spi1 static esp_rom_spiflash_result_t esp_rom_spiflash_erase_chip_internal(esp_rom_spiflash_chip_t *spi) @@ -309,65 +306,6 @@ static esp_rom_spiflash_result_t esp_rom_spiflash_enable_write(esp_rom_spiflash_ return ESP_ROM_SPIFLASH_RESULT_OK; } -static esp_rom_spiflash_result_t esp_rom_spiflash_enable_qmode(esp_rom_spiflash_chip_t *spi) -{ - uint32_t flash_status; - uint32_t status; - //read QE bit, not write if QE - if (ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_read_statushigh(spi, &status)) { - return ESP_ROM_SPIFLASH_RESULT_ERR; - } - if (status & ESP_ROM_SPIFLASH_QE) { - return ESP_ROM_SPIFLASH_RESULT_OK; - } - - //enable 2 byte status writing - SET_PERI_REG_MASK(PERIPHS_SPI_FLASH_CTRL, ESP_ROM_SPIFLASH_TWO_BYTE_STATUS_EN); - - if ( ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_enable_write(spi)) { - return ESP_ROM_SPIFLASH_RESULT_ERR; - } - - esp_rom_spiflash_read_status(spi, &flash_status); - - if ( ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_write_status(spi, flash_status | ESP_ROM_SPIFLASH_QE)) { - return ESP_ROM_SPIFLASH_RESULT_ERR; - } - - return ESP_ROM_SPIFLASH_RESULT_OK; -} - -static esp_rom_spiflash_result_t esp_rom_spiflash_disable_qmode(esp_rom_spiflash_chip_t *spi) -{ - uint32_t flash_status; - uint32_t status; - - //read QE bit, not write if not QE - if (ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_read_statushigh(spi, &status)) { - return ESP_ROM_SPIFLASH_RESULT_ERR; - } - //ets_printf("status %08x, line:%u\n", status, __LINE__); - - if (!(status & ESP_ROM_SPIFLASH_QE)) { - return ESP_ROM_SPIFLASH_RESULT_OK; - } - - //enable 2 byte status writing - SET_PERI_REG_MASK(PERIPHS_SPI_FLASH_CTRL, ESP_ROM_SPIFLASH_TWO_BYTE_STATUS_EN); - - if ( ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_enable_write(spi)) { - return ESP_ROM_SPIFLASH_RESULT_ERR; - } - - esp_rom_spiflash_read_status(spi, &flash_status); - //keep low 8 bit - if ( ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_write_status(spi, flash_status & 0xff)) { - return ESP_ROM_SPIFLASH_RESULT_ERR; - } - - return ESP_ROM_SPIFLASH_RESULT_OK; -} - static void spi_cache_mode_switch(uint32_t modebit) { if ((modebit & SPI_FREAD_QIO) && (modebit & SPI_FASTRD_MODE)) { @@ -431,7 +369,7 @@ esp_rom_spiflash_result_t esp_rom_spiflash_lock() } -esp_rom_spiflash_result_t esp_rom_spiflash_config_readmode(esp_rom_spiflash_read_mode_t mode, bool legacy) +esp_rom_spiflash_result_t esp_rom_spiflash_config_readmode(esp_rom_spiflash_read_mode_t mode) { uint32_t modebit; @@ -453,15 +391,6 @@ esp_rom_spiflash_result_t esp_rom_spiflash_config_readmode(esp_rom_spiflash_read default : modebit = 0; } - if ((ESP_ROM_SPIFLASH_QIO_MODE == mode) || (ESP_ROM_SPIFLASH_QOUT_MODE == mode)) { - esp_rom_spiflash_enable_qmode(&g_rom_spiflash_chip); - } else { - //do not need disable QMode in faster boot - if (legacy) { - esp_rom_spiflash_disable_qmode(&g_rom_spiflash_chip); - } - } - SET_PERI_REG_MASK(PERIPHS_SPI_FLASH_CTRL, modebit); SET_PERI_REG_MASK(SPI_CTRL_REG(0), modebit); spi_cache_mode_switch(modebit); @@ -668,7 +597,10 @@ esp_rom_spiflash_result_t esp_rom_spiflash_erase_area(uint32_t start_addr, uint3 uint32_t sector_num_per_block; //set read mode to Fastmode ,not QDIO mode for erase - esp_rom_spiflash_config_readmode(ESP_ROM_SPIFLASH_SLOWRD_MODE, true); + // + // TODO: this is probably a bug as it doesn't re-enable QIO mode, not serious as this + // function is not used in IDF. + esp_rom_spiflash_config_readmode(ESP_ROM_SPIFLASH_SLOWRD_MODE); //check if area is oversize of flash if ((start_addr + area_len) > g_rom_spiflash_chip.chip_size) { diff --git a/components/wear_levelling/.gitignore b/components/wear_levelling/.gitignore new file mode 100644 index 000000000..6bef194b9 --- /dev/null +++ b/components/wear_levelling/.gitignore @@ -0,0 +1,6 @@ +**/*.gcno +**/*.gcda +test_wl_host/coverage_report +test_wl_host/coverage.info +**/*.o +test_wl_host/test_wl diff --git a/components/wear_levelling/Partition.cpp b/components/wear_levelling/Partition.cpp new file mode 100644 index 000000000..63fef6ed6 --- /dev/null +++ b/components/wear_levelling/Partition.cpp @@ -0,0 +1,66 @@ +// Copyright 2015-2017 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. + +#include "esp_log.h" +#include "Partition.h" +static const char *TAG = "wl_partition"; + +Partition::Partition(const esp_partition_t *partition) +{ + this->partition = partition; +} + +size_t Partition::chip_size() +{ + return this->partition->size; +} + +esp_err_t Partition::erase_sector(size_t sector) +{ + esp_err_t result = ESP_OK; + result = erase_range(sector * SPI_FLASH_SEC_SIZE, SPI_FLASH_SEC_SIZE); + return result; +} +esp_err_t Partition::erase_range(size_t start_address, size_t size) +{ + esp_err_t result = esp_partition_erase_range(this->partition, start_address, size); + if (result == ESP_OK) { + ESP_LOGV(TAG, "erase_range - start_address=0x%08x, size=0x%08x, result=0x%08x", start_address, size, result); + } else { + ESP_LOGE(TAG, "erase_range - start_address=0x%08x, size=0x%08x, result=0x%08x", start_address, size, result); + } + return result; +} + +esp_err_t Partition::write(size_t dest_addr, const void *src, size_t size) +{ + esp_err_t result = ESP_OK; + result = esp_partition_write(this->partition, dest_addr, src, size); + return result; +} +esp_err_t Partition::read(size_t src_addr, void *dest, size_t size) +{ + esp_err_t result = ESP_OK; + result = esp_partition_read(this->partition, src_addr, dest, size); + return result; +} + +size_t Partition::sector_size() +{ + return SPI_FLASH_SEC_SIZE; +} + +Partition::~Partition() +{ + +} diff --git a/components/wear_levelling/README.rst b/components/wear_levelling/README.rst new file mode 100644 index 000000000..a51185ea3 --- /dev/null +++ b/components/wear_levelling/README.rst @@ -0,0 +1,42 @@ +Wear Levelling APIs +=================== + +Overview +-------- +Most of the flash devices and specially SPI flash devices that are used in ESP32 +have sector based organization and have limited amount of erase/modification cycles +per memory sector. To avoid situation when one sector reach the limit of erases when +other sectors was used not often, we have made a component that avoid this situation. +The wear levelling component share the amount of erases between all sectors in the +memory without user interaction. +The wear_levelling component contains APIs related to reading, writing, erasing, +memory mapping data in the external SPI flash through the partition component. It +also has higher-level APIs which work with FAT filesystem defined in +the :doc:`FAT filesystem `. + +The wear levelling component does not cache data in RAM. Write and erase functions +modify flash directly, and flash contents is consistent when the function returns. + + +Wear Levelling access APIs +-------------------------- + +This is the set of APIs for working with data in flash: + +- ``wl_mount`` mount wear levelling module for defined partition +- ``wl_unmount`` used to unmount levelling module +- ``wl_erase_range`` used to erase range of addresses in flash +- ``wl_write`` used to write data to the partition +- ``wl_read`` used to read data from the partition +- ``wl_size`` return size of avalible memory in bytes +- ``wl_sector_size`` returns size of one sector + +Generally, try to avoid using the raw wear levelling functions in favor of +filesystem-specific functions. + +Memory Size +----------- + +The memory size calculated in the wear Levelling module based on parameters of +partition. The module use few sectors of flash for internal data. + diff --git a/components/wear_levelling/SPI_Flash.cpp b/components/wear_levelling/SPI_Flash.cpp new file mode 100644 index 000000000..def91a2aa --- /dev/null +++ b/components/wear_levelling/SPI_Flash.cpp @@ -0,0 +1,81 @@ +// Copyright 2015-2017 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. + +#include "esp_log.h" +#include "SPI_Flash.h" +#include "esp_spi_flash.h" +static const char *TAG = "spi_flash"; + +SPI_Flash::SPI_Flash() +{ +} + +size_t SPI_Flash::chip_size() +{ + return spi_flash_get_chip_size(); +} + +esp_err_t SPI_Flash::erase_sector(size_t sector) +{ + esp_err_t result = spi_flash_erase_sector(sector); + if (result == ESP_OK) { + ESP_LOGV(TAG, "erase_sector - sector=0x%08x, result=0x%08x", sector, result); + } else { + ESP_LOGE(TAG, "erase_sector - sector=0x%08x, result=0x%08x", sector, result); + } + return result; +} +esp_err_t SPI_Flash::erase_range(size_t start_address, size_t size) +{ + size = (size + SPI_FLASH_SEC_SIZE - 1) / SPI_FLASH_SEC_SIZE; + size = size * SPI_FLASH_SEC_SIZE; + esp_err_t result = spi_flash_erase_range(start_address, size); + if (result == ESP_OK) { + ESP_LOGV(TAG, "erase_range - start_address=0x%08x, size=0x%08x, result=0x%08x", start_address, size, result); + } else { + ESP_LOGE(TAG, "erase_range - start_address=0x%08x, size=0x%08x, result=0x%08x", start_address, size, result); + } + return result; +} + +esp_err_t SPI_Flash::write(size_t dest_addr, const void *src, size_t size) +{ + esp_err_t result = spi_flash_write(dest_addr, src, size); + if (result == ESP_OK) { + ESP_LOGV(TAG, "write - dest_addr=0x%08x, size=0x%08x, result=0x%08x", dest_addr, size, result); + } else { + ESP_LOGE(TAG, "write - dest_addr=0x%08x, size=0x%08x, result=0x%08x", dest_addr, size, result); + } + return result; +} + +esp_err_t SPI_Flash::read(size_t src_addr, void *dest, size_t size) +{ + esp_err_t result = spi_flash_read(src_addr, dest, size); + if (result == ESP_OK) { + ESP_LOGV(TAG, "read - src_addr=0x%08x, size=0x%08x, result=0x%08x", src_addr, size, result); + } else { + ESP_LOGE(TAG, "read - src_addr=0x%08x, size=0x%08x, result=0x%08x", src_addr, size, result); + } + return result; +} + +size_t SPI_Flash::sector_size() +{ + return SPI_FLASH_SEC_SIZE; +} + +SPI_Flash::~SPI_Flash() +{ +} diff --git a/components/wear_levelling/WL_Flash.cpp b/components/wear_levelling/WL_Flash.cpp new file mode 100644 index 000000000..03db08302 --- /dev/null +++ b/components/wear_levelling/WL_Flash.cpp @@ -0,0 +1,478 @@ +// Copyright 2015-2017 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. + +#include +#include "esp_log.h" +#include "WL_Flash.h" +#include +#include "crc32.h" +#include + +static const char *TAG = "wl_flash"; +#ifndef WL_CFG_CRC_CONST +#define WL_CFG_CRC_CONST UINT32_MAX +#endif // WL_CFG_CRC_CONST + +#define WL_RESULT_CHECK(result) \ + if (result != ESP_OK) { \ + ESP_LOGE(TAG,"%s(%d): result = 0x%08x", __FUNCTION__, __LINE__, result); \ + return (result); \ + } + +#ifndef _MSC_VER // MSVS has different format for this define +static_assert(sizeof(wl_state_t) % 32 == 0, "wl_state_t structure size must be multiple of flash encryption unit size"); +#endif // _MSC_VER + + +WL_Flash::WL_Flash() +{ +} + +WL_Flash::~WL_Flash() +{ + free(this->temp_buff); +} + +esp_err_t WL_Flash::config(wl_config_t *cfg, Flash_Access *flash_drv) +{ + ESP_LOGV(TAG, "%s start_addr=0x%08x, full_mem_size=0x%08x, page_size=0x%08x, sector_size=0x%08x, updaterate=0x%08x, wr_size=0x%08x, version=0x%08x, temp_buff_size=0x%08x", __func__, + (uint32_t) cfg->start_addr, + cfg->full_mem_size, + cfg->page_size, + cfg->sector_size, + cfg->updaterate, + cfg->wr_size, + cfg->version, + (uint32_t) cfg->temp_buff_size); + + cfg->crc = crc32::crc32_le(WL_CFG_CRC_CONST, (const unsigned char *)cfg, sizeof(wl_config_t) - sizeof(cfg->crc)); + esp_err_t result = ESP_OK; + memcpy(&this->cfg, cfg, sizeof(wl_config_t)); + this->configured = false; + if (cfg == NULL) { + result = ESP_ERR_INVALID_ARG; + } + this->flash_drv = flash_drv; + if (flash_drv == NULL) { + result = ESP_ERR_INVALID_ARG; + } + if ((this->cfg.sector_size % this->cfg.temp_buff_size) != 0) { + result = ESP_ERR_INVALID_ARG; + } + if (this->cfg.page_size < this->cfg.sector_size) { + result = ESP_ERR_INVALID_ARG; + } + WL_RESULT_CHECK(result); + + this->temp_buff = (uint8_t *)malloc(this->cfg.temp_buff_size); + this->state_size = this->cfg.sector_size; + if (this->state_size < (sizeof(wl_state_t) + (this->cfg.full_mem_size / this->cfg.sector_size)*this->cfg.wr_size)) { + this->state_size = ((sizeof(wl_state_t) + (this->cfg.full_mem_size / this->cfg.sector_size) * this->cfg.wr_size) + this->cfg.sector_size - 1) / this->cfg.sector_size; + this->state_size = this->state_size * this->cfg.sector_size; + } + this->cfg_size = (sizeof(wl_config_t) + this->cfg.sector_size - 1) / this->cfg.sector_size; + this->cfg_size = cfg_size * this->cfg.sector_size; + + this->addr_cfg = this->cfg.start_addr + this->cfg.full_mem_size - this->cfg_size; + this->addr_state1 = this->cfg.start_addr + this->cfg.full_mem_size - this->state_size * 2 - this->cfg_size; // allocate data at the end of memory + this->addr_state2 = this->cfg.start_addr + this->cfg.full_mem_size - this->state_size * 1 - this->cfg_size; // allocate data at the end of memory + + this->flash_size = ((this->cfg.full_mem_size - this->state_size * 2 - this->cfg_size) / this->cfg.page_size - 1) * this->cfg.page_size; // -1 remove dummy block + + ESP_LOGV(TAG, "%s - this->addr_state1=0x%08x", __func__, (uint32_t) this->addr_state1); + ESP_LOGV(TAG, "%s - this->addr_state2=0x%08x", __func__, (uint32_t) this->addr_state2); + + this->configured = true; + return ESP_OK; +} + +esp_err_t WL_Flash::init() +{ + esp_err_t result = ESP_OK; + if (this->configured == false) { + ESP_LOGW(TAG, "WL_Flash: not configured, call config() first"); + return ESP_ERR_INVALID_STATE; + } + // If flow will be interrupted by error, then this flag will be false + this->initialized = false; + // Init states if it is first time... + this->flash_drv->read(this->addr_state1, &this->state, sizeof(wl_state_t)); + wl_state_t sa_copy; + wl_state_t *state_copy = &sa_copy; + result = this->flash_drv->read(this->addr_state2, state_copy, sizeof(wl_state_t)); + WL_RESULT_CHECK(result); + + int check_size = sizeof(wl_state_t) - sizeof(uint32_t); + // Chech CRC and recover state + uint32_t crc1 = crc32::crc32_le(WL_CFG_CRC_CONST, (uint8_t *)&this->state, check_size); + uint32_t crc2 = crc32::crc32_le(WL_CFG_CRC_CONST, (uint8_t *)state_copy, check_size); + + ESP_LOGD(TAG, "%s - config ID=%i, stored ID=%i, access_count=%i, block_size=%i, max_count=%i, pos=%i, move_count=%i", + __func__, + this->cfg.version, + this->state.version, + this->state.access_count, + this->state.block_size, + this->state.max_count, + this->state.pos, + this->state.move_count); + + + ESP_LOGD(TAG, "%s starts: crc1=%i, crc2 = %i, this->state.crc=%i, state_copy->crc=%i", __func__, crc1, crc2, this->state.crc, state_copy->crc); + if ((crc1 == this->state.crc) && (crc2 == state_copy->crc)) { + // The state is OK. Check the ID + if (this->state.version != this->cfg.version) { + result = this->initSections(); + WL_RESULT_CHECK(result); + result = this->recoverPos(); + WL_RESULT_CHECK(result); + } else { + if (crc1 != crc2) {// we did not update second structure. + result = this->flash_drv->erase_range(this->addr_state2, this->state_size); + WL_RESULT_CHECK(result); + result = this->flash_drv->write(this->addr_state2, &this->state, sizeof(wl_state_t)); + WL_RESULT_CHECK(result); + for (size_t i = 0; i < ((this->cfg.full_mem_size / this->cfg.sector_size)*this->cfg.wr_size); i++) { + uint8_t pos_bits = 0; + result = this->flash_drv->read(this->addr_state1 + sizeof(wl_state_t) + i, &pos_bits, 1); + WL_RESULT_CHECK(result); + if (pos_bits != 0xff) { + result = this->flash_drv->write(this->addr_state2 + sizeof(wl_state_t) + i, &pos_bits, 1); + WL_RESULT_CHECK(result); + } + } + } + ESP_LOGD(TAG, "%s: crc1=%i, crc2 = %i, result=%i", __func__, crc1, crc2, result); + result = this->recoverPos(); + WL_RESULT_CHECK(result); + } + } else if ((crc1 != this->state.crc) && (crc2 != state_copy->crc)) { // This is just new flash + result = this->initSections(); + WL_RESULT_CHECK(result); + result = this->recoverPos(); + WL_RESULT_CHECK(result); + } else { + // recover broken state + if (crc1 == this->state.crc) {// we have to recover state 2 + result = this->flash_drv->erase_range(this->addr_state2, this->state_size); + WL_RESULT_CHECK(result); + result = this->flash_drv->write(this->addr_state2, &this->state, sizeof(wl_state_t)); + WL_RESULT_CHECK(result); + for (size_t i = 0; i < ((this->cfg.full_mem_size / this->cfg.sector_size) * this->cfg.wr_size); i++) { + uint8_t pos_bits = 0; + result = this->flash_drv->read(this->addr_state1 + sizeof(wl_state_t) + i, &pos_bits, 1); + WL_RESULT_CHECK(result); + if (pos_bits != 0xff) { + result = this->flash_drv->write(this->addr_state2 + sizeof(wl_state_t) + i, &pos_bits, 1); + WL_RESULT_CHECK(result); + } + } + result = this->flash_drv->read(this->addr_state2, &this->state, sizeof(wl_state_t)); + WL_RESULT_CHECK(result); + } else { // we have to recover state 1 + result = this->flash_drv->erase_range(this->addr_state1, this->state_size); + WL_RESULT_CHECK(result); + result = this->flash_drv->write(this->addr_state1, state_copy, sizeof(wl_state_t)); + WL_RESULT_CHECK(result); + for (size_t i = 0; i < ((this->cfg.full_mem_size / this->cfg.sector_size) * this->cfg.wr_size); i++) { + uint8_t pos_bits = 0; + result = this->flash_drv->read(this->addr_state2 + sizeof(wl_state_t) + i, &pos_bits, 1); + WL_RESULT_CHECK(result); + if (pos_bits != 0xff) { + result = this->flash_drv->write(this->addr_state1 + sizeof(wl_state_t) + i, &pos_bits, 1); + WL_RESULT_CHECK(result); + } + } + result = this->flash_drv->read(this->addr_state1, &this->state, sizeof(wl_state_t)); + WL_RESULT_CHECK(result); + this->state.pos = this->state.max_pos - 1; + } + // done. We have recovered the state + // If we have a new configuration, we will overwrite it + if (this->state.version != this->cfg.version) { + result = this->initSections(); + WL_RESULT_CHECK(result); + } + } + if (result != ESP_OK) { + this->initialized = false; + ESP_LOGE(TAG, "%s: returned 0x%x", __func__, result); + return result; + } + this->initialized = true; + return ESP_OK; +} + +esp_err_t WL_Flash::recoverPos() +{ + esp_err_t result = ESP_OK; + size_t position = 0; + for (size_t i = 0; i < this->state.max_pos; i++) { + uint8_t pos_bits = 0; + result = this->flash_drv->read(this->addr_state1 + sizeof(wl_state_t) + i * this->cfg.wr_size, &pos_bits, 1); + WL_RESULT_CHECK(result); + position = i; + if (pos_bits == 0xff) { + break; // we have found position + } + } + this->state.pos = position; + if (this->state.pos == this->state.max_pos) { + this->state.pos--; + } + ESP_LOGD(TAG, "%s - this->state.pos=0x%08x, result=%08x", __func__, this->state.pos, result); + return result; +} + +esp_err_t WL_Flash::initSections() +{ + esp_err_t result = ESP_OK; + this->state.pos = 0; + this->state.access_count = 0; + this->state.move_count = 0; + // max count + this->state.max_count = this->flash_size / this->state_size * this->cfg.updaterate; + if (this->cfg.updaterate != 0) { + this->state.max_count = this->cfg.updaterate; + } + this->state.version = this->cfg.version; + this->state.block_size = this->cfg.page_size; + this->used_bits = 0; + + this->state.max_pos = 1 + this->flash_size / this->cfg.page_size; + + this->state.crc = crc32::crc32_le(WL_CFG_CRC_CONST, (uint8_t *)&this->state, sizeof(wl_state_t) - sizeof(uint32_t)); + + result = this->flash_drv->erase_range(this->addr_state1, this->state_size); + WL_RESULT_CHECK(result); + result = this->flash_drv->write(this->addr_state1, &this->state, sizeof(wl_state_t)); + WL_RESULT_CHECK(result); + // write state copy + result = this->flash_drv->erase_range(this->addr_state2, this->state_size); + WL_RESULT_CHECK(result); + result = this->flash_drv->write(this->addr_state2, &this->state, sizeof(wl_state_t)); + WL_RESULT_CHECK(result); + + result = this->flash_drv->erase_range(this->addr_cfg, this->cfg_size); + WL_RESULT_CHECK(result); + result = this->flash_drv->write(this->addr_cfg, &this->cfg, sizeof(wl_config_t)); + WL_RESULT_CHECK(result); + + ESP_LOGD(TAG, "%s - this->state->max_count=%08x, this->state->max_pos=%08x", __func__, this->state.max_count, this->state.max_pos); + ESP_LOGD(TAG, "%s - result=%08x", __func__, result); + return result; +} + +esp_err_t WL_Flash::updateWL() +{ + esp_err_t result = ESP_OK; + this->state.access_count++; + if (this->state.access_count < this->state.max_count) { + return result; + } + // Here we have to move the block and increase the state + this->state.access_count = 0; + ESP_LOGV(TAG, "%s - access_count=0x%08x, pos=0x%08x", __func__, this->state.access_count, this->state.pos); + // copy data to dummy block + size_t data_addr = this->state.pos + 1; // next block, [pos+1] copy to [pos] + if (data_addr >= this->state.max_pos) { + data_addr = 0; + } + data_addr = this->cfg.start_addr + data_addr * this->cfg.page_size; + this->dummy_addr = this->cfg.start_addr + this->state.pos * this->cfg.page_size; + result = this->flash_drv->erase_range(this->dummy_addr, this->cfg.page_size); + if (result != ESP_OK) { + ESP_LOGE(TAG, "%s - erase wl dummy sector result=%08x", __func__, result); + this->state.access_count = this->state.max_count - 1; // we will update next time + return result; + } + + size_t copy_count = this->cfg.page_size / this->cfg.temp_buff_size; + for (size_t i = 0; i < copy_count; i++) { + result = this->flash_drv->read(data_addr + i * this->cfg.temp_buff_size, this->temp_buff, this->cfg.temp_buff_size); + if (result != ESP_OK) { + ESP_LOGE(TAG, "%s - not possible to read buffer, will try next time, result=%08x", __func__, result); + this->state.access_count = this->state.max_count - 1; // we will update next time + return result; + } + result = this->flash_drv->write(this->dummy_addr + i * this->cfg.temp_buff_size, this->temp_buff, this->cfg.temp_buff_size); + if (result != ESP_OK) { + ESP_LOGE(TAG, "%s - not possible to write buffer, will try next time, result=%08x", __func__, result); + this->state.access_count = this->state.max_count - 1; // we will update next time + return result; + } + } + // done... block moved. + // Here we will update structures... + // Update bits and save to flash: + uint32_t byte_pos = this->state.pos * this->cfg.wr_size; + this->used_bits = 0; + // write state to mem. We updating only affected bits + result |= this->flash_drv->write(this->addr_state1 + sizeof(wl_state_t) + byte_pos, &this->used_bits, 1); + if (result != ESP_OK) { + ESP_LOGE(TAG, "%s - update position 1 result=%08x", __func__, result); + this->state.access_count = this->state.max_count - 1; // we will update next time + return result; + } + result |= this->flash_drv->write(this->addr_state2 + sizeof(wl_state_t) + byte_pos, &this->used_bits, 1); + if (result != ESP_OK) { + ESP_LOGE(TAG, "%s - update position 2 result=%08x", __func__, result); + this->state.access_count = this->state.max_count - 1; // we will update next time + return result; + } + + this->state.pos++; + if (this->state.pos >= this->state.max_pos) { + this->state.pos = 0; + // one loop more + this->state.move_count++; + if (this->state.move_count >= (this->state.max_pos - 1)) { + this->state.move_count = 0; + } + // write main state + this->state.crc = crc32::crc32_le(WL_CFG_CRC_CONST, (uint8_t *)&this->state, sizeof(wl_state_t) - sizeof(uint32_t)); + + result = this->flash_drv->erase_range(this->addr_state1, this->state_size); + WL_RESULT_CHECK(result); + result = this->flash_drv->write(this->addr_state1, &this->state, sizeof(wl_state_t)); + WL_RESULT_CHECK(result); + result = this->flash_drv->erase_range(this->addr_state2, this->state_size); + WL_RESULT_CHECK(result); + result = this->flash_drv->write(this->addr_state2, &this->state, sizeof(wl_state_t)); + WL_RESULT_CHECK(result); + ESP_LOGD(TAG, "%s - move_count=%08x", __func__, this->state.move_count); + } + // Save structures to the flash... and check result + if (result == ESP_OK) { + ESP_LOGV(TAG, "%s - result=%08x", __func__, result); + } else { + ESP_LOGE(TAG, "%s - result=%08x", __func__, result); + } + return result; +} + +size_t WL_Flash::calcAddr(size_t addr) +{ + size_t result = (this->flash_size - this->state.move_count * this->cfg.page_size + addr) % this->flash_size; + size_t dummy_addr = this->state.pos * this->cfg.page_size; + if (result < dummy_addr) { + } else { + result += this->cfg.page_size; + } + ESP_LOGV(TAG, "%s - addr=0x%08x -> result=0x%08x", __func__, (uint32_t) addr, (uint32_t) result); + return result; +} + + +size_t WL_Flash::chip_size() +{ + if (!this->configured) { + return 0; + } + return this->flash_size; +} +size_t WL_Flash::sector_size() +{ + if (!this->configured) { + return 0; + } + return this->cfg.sector_size; +} + + +esp_err_t WL_Flash::erase_sector(size_t sector) +{ + esp_err_t result = ESP_OK; + if (!this->initialized) { + return ESP_ERR_INVALID_STATE; + } + ESP_LOGV(TAG, "%s - sector=0x%08x", __func__, (uint32_t) sector); + result = this->updateWL(); + WL_RESULT_CHECK(result); + size_t virt_addr = this->calcAddr(sector * this->cfg.sector_size); + result = this->flash_drv->erase_sector((this->cfg.start_addr + virt_addr) / this->cfg.sector_size); + WL_RESULT_CHECK(result); + return result; +} +esp_err_t WL_Flash::erase_range(size_t start_address, size_t size) +{ + esp_err_t result = ESP_OK; + if (!this->initialized) { + return ESP_ERR_INVALID_STATE; + } + ESP_LOGV(TAG, "%s - start_address=0x%08x, size=0x%08x", __func__, (uint32_t) start_address, (uint32_t) size); + size_t erase_count = (size + this->cfg.sector_size - 1) / this->cfg.sector_size; + size_t start_sector = start_address / this->cfg.sector_size; + for (size_t i = 0; i < erase_count; i++) { + result = this->erase_sector(start_sector + i); + WL_RESULT_CHECK(result); + } + ESP_LOGV(TAG, "%s - result=%08x", __func__, result); + return result; +} + +esp_err_t WL_Flash::write(size_t dest_addr, const void *src, size_t size) +{ + esp_err_t result = ESP_OK; + if (!this->initialized) { + return ESP_ERR_INVALID_STATE; + } + ESP_LOGV(TAG, "%s - dest_addr=0x%08x, size=0x%08x", __func__, (uint32_t) dest_addr, (uint32_t) size); + uint32_t count = (size - 1) / this->cfg.page_size; + for (size_t i = 0; i < count; i++) { + size_t virt_addr = this->calcAddr(dest_addr + i * this->cfg.page_size); + result = this->flash_drv->write(this->cfg.start_addr + virt_addr, &((uint8_t *)src)[i * this->cfg.page_size], size); + WL_RESULT_CHECK(result); + } + size_t virt_addr_last = this->calcAddr(dest_addr + count * this->cfg.page_size); + result = this->flash_drv->write(this->cfg.start_addr + virt_addr_last, &((uint8_t *)src)[count * this->cfg.page_size], size - count * this->cfg.page_size); + WL_RESULT_CHECK(result); + return result; +} + +esp_err_t WL_Flash::read(size_t src_addr, void *dest, size_t size) +{ + esp_err_t result = ESP_OK; + if (!this->initialized) { + return ESP_ERR_INVALID_STATE; + } + ESP_LOGV(TAG, "%s - src_addr=0x%08x, size=0x%08x", __func__, (uint32_t) src_addr, (uint32_t) size); + uint32_t count = (size - 1) / this->cfg.page_size; + for (size_t i = 0; i < count; i++) { + size_t virt_addr = this->calcAddr(src_addr + i * this->cfg.page_size); + result = this->flash_drv->read(this->cfg.start_addr + virt_addr, &((uint8_t *)dest)[i * this->cfg.page_size], size); + WL_RESULT_CHECK(result); + } + size_t virt_addr_last = this->calcAddr(src_addr + count * this->cfg.page_size); + result = this->flash_drv->read(this->cfg.start_addr + virt_addr_last, &((uint8_t *)dest)[count * this->cfg.page_size], size - count * this->cfg.page_size); + WL_RESULT_CHECK(result); + return result; +} + +Flash_Access *WL_Flash::get_drv() +{ + return this->flash_drv; +} +wl_config_t *WL_Flash::get_cfg() +{ + return &this->cfg; +} + +esp_err_t WL_Flash::flush() +{ + esp_err_t result = ESP_OK; + this->state.access_count = this->state.max_count - 1; + result = this->updateWL(); + ESP_LOGV(TAG, "%s - result=%08x", __func__, result); + return result; +} diff --git a/components/wear_levelling/component.mk b/components/wear_levelling/component.mk new file mode 100644 index 000000000..191e63814 --- /dev/null +++ b/components/wear_levelling/component.mk @@ -0,0 +1 @@ +COMPONENT_PRIV_INCLUDEDIRS := private_include diff --git a/components/wear_levelling/crc32.cpp b/components/wear_levelling/crc32.cpp new file mode 100644 index 000000000..1a857db55 --- /dev/null +++ b/components/wear_levelling/crc32.cpp @@ -0,0 +1,20 @@ +// Copyright 2015-2016 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. + +#include "crc32.h" +#include "rom/crc.h" + +unsigned int crc32::crc32_le(unsigned int crc, unsigned char const *buf, unsigned int len) +{ + return ::crc32_le(crc, buf, len); +} diff --git a/components/wear_levelling/crc32.h b/components/wear_levelling/crc32.h new file mode 100644 index 000000000..bac6a808e --- /dev/null +++ b/components/wear_levelling/crc32.h @@ -0,0 +1,26 @@ +// Copyright 2015-2016 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. + +#ifndef _crc32_H_ +#define _crc32_H_ + +/** +* @brief This class is used to access crc32 module +* +*/ +class crc32 +{ +public: + static unsigned int crc32_le(unsigned int crc, unsigned char const *buf, unsigned int len); +}; +#endif // _crc32_H_ \ No newline at end of file diff --git a/components/wear_levelling/doc/wl_sw_structure.rst b/components/wear_levelling/doc/wl_sw_structure.rst new file mode 100644 index 000000000..ee897489b --- /dev/null +++ b/components/wear_levelling/doc/wl_sw_structure.rst @@ -0,0 +1,89 @@ +Wear Levelling Component +======================== + +Wear Levelling Component (WLC) it is a software component that is implemented to prevent situation when some sectors in flash memory used by erase operations more then others. The component shares access attempts between all avalible sectors. +The WLC do not have internal cache. When write operation is finished, that means that data was really stored to the flash. +As a parameter the WLC requires the driver to access the flash device. The driver has to implement Flash_Access interface. + + +The WLC Files +^^^^^^^^^^^^^^^ +The WLC consist of few components that are implemented in different files. The list and brief description of these components written below. + + - Flash_Access - memory access interface. Used to access the memory. A classes WL_Flash, Partition, SPI_Flash, Flash_Emulator are implements this interface. + - SPI_Flash - class implements the Flash_Access interface to provide access to the flash memory. + - Partition - class implements the Flash_Access interface to provide access to the partition. + - Flash_Emulator - class implements the Flash_Access interface to provide test functionality for WLC testing. + - WL_Flash - the main class that implements wear levelling functionality. + - WL_State - contains state structure of the WLC. + - WL_Config - contains structure to configure the WLC component at startup. + - wear_levelling - wrapper API class that provides "C" interface to access the memory through the WLC + + +Flash_Access Interface +^^^^^^^^^^^^^^^^^^^^^^ + +In the component exist virtual interface Flash_Access. This interface implement main basic functions: + - read - read memory to the buffer. + - write - writes buffer to the memory. + - erase - erase one sector. + - erase_range - erase range of memory. The address of rage must be rounded to the sector size. + - chip_size - returns the equivalent amount of memory. + - sector_size - returns the sector size. + - flush - stores current state to the flash, if needed. + +The WLC implements this interface for the user, and requires this interface to access the memory. + +Structure wl_config_t to Configure the WLC at startup +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The wl_config_t contains configuration parameters for the WLC component. + - start_addr - offset in the flash memory. The WLC will place all data after this address. + - full_mem_size - amount of memory that was allocated and can be used by WLC + - sector_size - flash memory sector size + - page_size - size of memory for relocation at once. Must be N*sector_size, where N > 0. + - updaterate - amount of erase cycles to execute the relocation procedure. + - wr_size - smalest possible write access size without erasing of sector. + - version - version of the WLC component. + - temp_buff_size - amount of memory that the WLC will allocate internally. Must be > 0. + +Internal Memory Organization +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The WLC divide the memory that are define by start_addr and full_mem_size to three regions: + - Configuration + - Data + - States + +The Configuration region used to store configuration information. The user can use it to recover the WLC from memory dump. +The Data - is a region where user data stored. +The States - is a region where the WLC stores internal information about the WLC state. The States region contains two copies of the WLC states. It is implemented to prevent situation when the device is shut down +during operation when the device stores the states. If one of copies is wrong, the WLC can recover the state from another. The broken copy will be overwritten by another. + +Main Idea +^^^^^^^^^ +The WLC has two access addresses: virtual address and real address. The virtual address used by user to access the WLC, the real address used by the WLC to access the real memory. +The WLC makes the conversion between virtual and real addresses. +The Data region divided to N pages (page could be equal to the sector size). One page defined as dummy page. For user will be available only N-1 pages. +The WLC has two internal counters to calculate virtual and real addresses: erase counter and move counter. +Every erase operation will be counted by erase counter. When this counter reached the *updaterate* number the page after Dummy page will be moved to the Dummy page, and Dummy page will be changed to this one. The erase counter will +be cleared and move counter will be incremented. This procedure will be repeated again and again. +When the Dummy page will be at last page in the memory and erase counter will reach the updaterate, the move counter will be cleared and the state will be stored to the State memory. +Bellow shown the example with 4 available memory pages. Every state after updaterate erases. The X is a Dummy page. + +- X 0 1 2 - start position +- 0 X 1 2 - first move, the page 0 and Dummy page change the places +- 0 1 X 2 - second move, the page 1 and Dummy page change the places +- 0 1 2 X - +- X 1 2 0 - state stored to the memory +- 1 X 2 0 - +- 1 2 X 0 - +- 1 2 0 X - +- X 2 0 1 - state stored to the memory +- 2 X 0 1 - +- 2 0 X 1 - +- 2 0 1 X - +- X 0 1 2 - state stored to the memory, the memory made full cycle. + +As we see, if user will write data only to one address, amount of erase cycles will be shared between the full memory. The price for that is a one memory page that will not be used by user. + + diff --git a/components/wear_levelling/include/wear_levelling.h b/components/wear_levelling/include/wear_levelling.h new file mode 100644 index 000000000..60f252e9c --- /dev/null +++ b/components/wear_levelling/include/wear_levelling.h @@ -0,0 +1,136 @@ +// Copyright 2015-2017 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. + +#ifndef _wear_levelling_H_ +#define _wear_levelling_H_ + +#include "esp_log.h" +#include "esp_partition.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** +* @brief wear levelling handle +*/ +typedef int32_t wl_handle_t; + +#define WL_INVALID_HANDLE -1 + +/** +* @brief Mount WL for defined partition +* +* @param partition that will be used for access +* @param out_handle handle of the WL instance +* +* @return +* - ESP_OK, if the allocation was successfully; +* - ESP_ERR_INVALID_ARG, if WL allocation was unsuccessful; +* - ESP_ERR_NO_MEM, if there was no memory to allocate WL components; +*/ +esp_err_t wl_mount(const esp_partition_t *partition, wl_handle_t *out_handle); + +/** +* @brief Unmount WL for defined partition +* +* @param handle WL partition handle +* +* @return +* - ESP_OK, if the operation completed successfully; +* - or one of error codes from lower-level flash driver. +*/ +esp_err_t wl_unmount(wl_handle_t handle); + +/** +* @brief Erase part of the WL storage +* +* @param handle WL handle that are related to the partition +* @param start_addr Address where erase operation should start. Must be aligned +* to the result of function wl_sector_size(...). +* @param size Size of the range which should be erased, in bytes. +* Must be divisible by result of function wl_sector_size(...).. +* +* @return +* - ESP_OK, if the range was erased successfully; +* - ESP_ERR_INVALID_ARG, if iterator or dst are NULL; +* - ESP_ERR_INVALID_SIZE, if erase would go out of bounds of the partition; +* - or one of error codes from lower-level flash driver. +*/ +esp_err_t wl_erase_range(wl_handle_t handle, size_t start_addr, size_t size); + +/** +* @brief Write data to the WL storage +* +* Before writing data to flash, corresponding region of flash needs to be erased. +* This can be done using wl_erase_range function. +* +* @param handle WL handle that are related to the partition +* @param dest_addr Address where the data should be written, relative to the +* beginning of the partition. +* @param src Pointer to the source buffer. Pointer must be non-NULL and +* buffer must be at least 'size' bytes long. +* @param size Size of data to be written, in bytes. +* +* @note Prior to writing to WL storage, make sure it has been erased with +* wl_erase_range call. +* +* @return +* - ESP_OK, if data was written successfully; +* - ESP_ERR_INVALID_ARG, if dst_offset exceeds partition size; +* - ESP_ERR_INVALID_SIZE, if write would go out of bounds of the partition; +* - or one of error codes from lower-level flash driver. +*/ +esp_err_t wl_write(wl_handle_t handle, size_t dest_addr, const void *src, size_t size); + +/** +* @brief Read data from the WL storage +* +* @param handle WL module instance that was initialized before +* @param dest Pointer to the buffer where data should be stored. +* Pointer must be non-NULL and buffer must be at least 'size' bytes long. +* @param src_addr Address of the data to be read, relative to the +* beginning of the partition. +* @param size Size of data to be read, in bytes. +* +* @return +* - ESP_OK, if data was read successfully; +* - ESP_ERR_INVALID_ARG, if src_offset exceeds partition size; +* - ESP_ERR_INVALID_SIZE, if read would go out of bounds of the partition; +* - or one of error codes from lower-level flash driver. +*/ +esp_err_t wl_read(wl_handle_t handle, size_t src_addr, void *dest, size_t size); + +/** +* @brief Get size of the WL storage +* +* @param handle WL module handle that was initialized before +* @return usable size, in bytes +*/ +size_t wl_size(wl_handle_t handle); + +/** +* @brief Get sector size of the WL instance +* +* @param handle WL module handle that was initialized before +* @return sector size, in bytes +*/ +size_t wl_sector_size(wl_handle_t handle); + + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _wear_levelling_H_ diff --git a/components/wear_levelling/private_include/Flash_Access.h b/components/wear_levelling/private_include/Flash_Access.h new file mode 100644 index 000000000..e5bd8f276 --- /dev/null +++ b/components/wear_levelling/private_include/Flash_Access.h @@ -0,0 +1,44 @@ +// Copyright 2015-2017 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. + + +#ifndef _Flash_Access_H_ +#define _Flash_Access_H_ +#include "esp_err.h" + +/** +* @brief Universal flash access interface class +* +*/ +class Flash_Access +{ +public: + virtual size_t chip_size() = 0; + + virtual esp_err_t erase_sector(size_t sector) = 0; + virtual esp_err_t erase_range(size_t start_address, size_t size) = 0; + + virtual esp_err_t write(size_t dest_addr, const void *src, size_t size) = 0; + virtual esp_err_t read(size_t src_addr, void *dest, size_t size) = 0; + + virtual size_t sector_size() = 0; + + virtual esp_err_t flush() + { + return ESP_OK; + }; + + virtual ~Flash_Access() {}; +}; + +#endif // _Flash_Access_H_ \ No newline at end of file diff --git a/components/wear_levelling/private_include/Partition.h b/components/wear_levelling/private_include/Partition.h new file mode 100644 index 000000000..6d07964d6 --- /dev/null +++ b/components/wear_levelling/private_include/Partition.h @@ -0,0 +1,36 @@ +#ifndef _Partition_H_ +#define _Partition_H_ + +#include "esp_err.h" + +#include "Flash_Access.h" +#include "esp_partition.h" + +/** +* @brief This class is used to access partition. Class implements Flash_Access interface +* +*/ +class Partition : public Flash_Access +{ + +public: + Partition(const esp_partition_t *partition); + + virtual size_t chip_size(); + + virtual esp_err_t erase_sector(size_t sector); + virtual esp_err_t erase_range(size_t start_address, size_t size); + + virtual esp_err_t write(size_t dest_addr, const void *src, size_t size); + virtual esp_err_t read(size_t src_addr, void *dest, size_t size); + + virtual size_t sector_size(); + + virtual ~Partition(); +protected: + const esp_partition_t *partition; + +}; + +#endif // _Partition_H_ + diff --git a/components/wear_levelling/private_include/SPI_Flash.h b/components/wear_levelling/private_include/SPI_Flash.h new file mode 100644 index 000000000..aadd42b7e --- /dev/null +++ b/components/wear_levelling/private_include/SPI_Flash.h @@ -0,0 +1,26 @@ +#ifndef _SPI_Flash_H_ +#define _SPI_Flash_H_ + +#include "esp_err.h" +#include "Flash_Access.h" + +/** +* @brief This class is used to access SPI flash devices. Class implements Flash_Access interface +* +*/ +class SPI_Flash : public Flash_Access +{ + +public: + SPI_Flash(); + + size_t chip_size() override; + esp_err_t erase_sector(size_t sector) override; + esp_err_t erase_range(size_t start_address, size_t size) override; + esp_err_t write(size_t dest_addr, const void *src, size_t size) override; + esp_err_t read(size_t src_addr, void *dest, size_t size) override; + size_t sector_size() override; + ~SPI_Flash() override; +}; + +#endif // _SPI_Flash_H_ \ No newline at end of file diff --git a/components/wear_levelling/private_include/WL_Config.h b/components/wear_levelling/private_include/WL_Config.h new file mode 100644 index 000000000..66beb851d --- /dev/null +++ b/components/wear_levelling/private_include/WL_Config.h @@ -0,0 +1,36 @@ +// Copyright 2015-2017 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. + +#ifndef _WL_Config_H_ +#define _WL_Config_H_ + +#include "Flash_Access.h" + +/** +* @brief This class is used as a structure to configure wear levelling module +* +*/ +typedef struct WL_Config_s { + size_t start_addr; /*!< start address in the flash*/ + uint32_t full_mem_size; /*!< Amount of memory used to store data in bytes*/ + uint32_t page_size; /*!< One page size in bytes. Page could be more then memory block. This parameter must be page_size >= N*block_size.*/ + uint32_t sector_size; /*!< size of flash memory sector that will be erased and stored at once (erase)*/ + uint32_t updaterate; /*!< Amount of accesses before block will be moved*/ + uint32_t wr_size; /*!< Minimum amount of bytes per one block at write operation: 1...*/ + uint32_t version; /*!< A version of current implementatioon. To erase and reallocate complete memory this ID must be different from id before.*/ + size_t temp_buff_size; /*!< Size of temporary allocated buffer to copy from one flash area to another. The best way, if this value will be equal to sector size.*/ + uint32_t crc; /*!< CRC for this config*/ + +} wl_config_t; + +#endif // _WL_Config_H_ \ No newline at end of file diff --git a/components/wear_levelling/private_include/WL_Flash.h b/components/wear_levelling/private_include/WL_Flash.h new file mode 100644 index 000000000..504a18522 --- /dev/null +++ b/components/wear_levelling/private_include/WL_Flash.h @@ -0,0 +1,76 @@ +// Copyright 2015-2017 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. + +#ifndef _WL_Flash_H_ +#define _WL_Flash_H_ + +#include "esp_err.h" +#include "Flash_Access.h" +#include "WL_Config.h" +#include "WL_State.h" + +/** +* @brief This class is used to make wear levelling for flash devices. Class implements Flash_Access interface +* +*/ +class WL_Flash : public Flash_Access +{ +public : + WL_Flash(); + ~WL_Flash() override; + + virtual esp_err_t config(wl_config_t *cfg, Flash_Access *flash_drv); + virtual esp_err_t init(); + + size_t chip_size() override; + size_t sector_size() override; + + + esp_err_t erase_sector(size_t sector) override; + esp_err_t erase_range(size_t start_address, size_t size) override; + + esp_err_t write(size_t dest_addr, const void *src, size_t size) override; + esp_err_t read(size_t src_addr, void *dest, size_t size) override; + + esp_err_t flush() override; + + Flash_Access *get_drv(); + wl_config_t *get_cfg(); + +protected: + bool configured = false; + bool initialized = false; + wl_state_t state; + wl_config_t cfg; + Flash_Access *flash_drv = NULL; + + size_t addr_cfg; + size_t addr_state1; + size_t addr_state2; + size_t index_state1; + size_t index_state2; + + size_t flash_size; + uint32_t state_size; + uint32_t cfg_size; + uint8_t *temp_buff = NULL; + size_t dummy_addr; + uint8_t used_bits; + + esp_err_t initSections(); + esp_err_t updateWL(); + esp_err_t recoverPos(); + size_t calcAddr(size_t addr); +}; + +#endif // _WL_Flash_H_ diff --git a/components/wear_levelling/private_include/WL_State.h b/components/wear_levelling/private_include/WL_State.h new file mode 100644 index 000000000..2654d7011 --- /dev/null +++ b/components/wear_levelling/private_include/WL_State.h @@ -0,0 +1,34 @@ +// Copyright 2015-2017 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. + +#ifndef _WL_State_H_ +#define _WL_State_H_ +#include "esp_err.h" + +/** +* @brief This structure is used to store current state of flash access +* +*/ +typedef struct WL_State_s { +public: + uint32_t pos; /*!< current dummy block position*/ + uint32_t max_pos; /*!< maximum amount of positions*/ + uint32_t move_count; /*!< total amount of move counts. Used to calculate the address*/ + uint32_t access_count; /*!< current access count*/ + uint32_t max_count; /*!< max access count when block will be moved*/ + uint32_t block_size; /*!< size of move block*/ + uint32_t version; /*!< state id used to identify the version of current libary implementaion*/ + uint32_t crc; /*!< CRC of structure*/ +} wl_state_t; + +#endif // _WL_State_H_ diff --git a/components/wear_levelling/test/component.mk b/components/wear_levelling/test/component.mk new file mode 100644 index 000000000..ce464a212 --- /dev/null +++ b/components/wear_levelling/test/component.mk @@ -0,0 +1 @@ +COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive diff --git a/components/wear_levelling/test/test_wl.c b/components/wear_levelling/test/test_wl.c new file mode 100644 index 000000000..b34d8a86e --- /dev/null +++ b/components/wear_levelling/test/test_wl.c @@ -0,0 +1,151 @@ +#include +#include "unity.h" +#include "wear_levelling.h" +#include "test_utils.h" +#include "freertos/FreeRTOS.h" +#include "freertos/portable.h" +#include "freertos/task.h" +#include "freertos/semphr.h" + +TEST_CASE("wl_unmount doesn't leak memory", "[wear_levelling]") +{ + const esp_partition_t *partition = get_test_data_partition(); + wl_handle_t handle; + // dummy unmount is needed to initialize static lock in WL + wl_unmount(WL_INVALID_HANDLE); + size_t size_before = xPortGetFreeHeapSize(); + TEST_ESP_OK(wl_mount(partition, &handle)); + wl_unmount(handle); + size_t size_after = xPortGetFreeHeapSize(); + TEST_ASSERT_EQUAL_UINT32(size_before, size_after); +} + +TEST_CASE("wl_mount check partition parameters", "[wear_levelling][ignore]") +{ + const esp_partition_t *test_partition = get_test_data_partition(); + esp_partition_t fake_partition; + memcpy(&fake_partition, test_partition, sizeof(fake_partition)); + wl_handle_t handle; + size_t size_before, size_after; + + // test small partition + fake_partition.size = SPI_FLASH_SEC_SIZE; + size_before = xPortGetFreeHeapSize(); + TEST_ESP_ERR(ESP_ERR_INVALID_ARG, wl_mount(&fake_partition, &handle)); + size_after = xPortGetFreeHeapSize(); + TEST_ASSERT_EQUAL_HEX32(size_before, size_after); + // currently this test leaks memory + + // test slightly bigger partition + fake_partition.size = SPI_FLASH_SEC_SIZE * 3; + size_before = xPortGetFreeHeapSize(); + TEST_ESP_ERR(ESP_ERR_INVALID_ARG, wl_mount(&fake_partition, &handle)); + size_after = xPortGetFreeHeapSize(); + TEST_ASSERT_EQUAL_HEX32(size_before, size_after); + // currently this test hangs +} + +typedef struct { + size_t offset; + bool write; + size_t word_count; + int seed; + SemaphoreHandle_t done; + int result; + wl_handle_t handle; +} read_write_test_arg_t; + +#define READ_WRITE_TEST_ARG_INIT(offset_, seed_, handle_) \ + { \ + .offset = offset_, \ + .seed = seed_, \ + .word_count = 1024, \ + .write = true, \ + .done = xSemaphoreCreateBinary(), \ + .handle = handle_ \ + } + +static void read_write_task(void* param) +{ + read_write_test_arg_t* args = (read_write_test_arg_t*) param; + esp_err_t err; + srand(args->seed); + for (size_t i = 0; i < args->word_count; ++i) { + uint32_t val = rand(); + if (args->write) { + err = wl_write(args->handle, args->offset + i * sizeof(val), &val, sizeof(val)); + if (err != ESP_OK) { + args->result = err; + goto done; + } + } else { + uint32_t rval; + err = wl_read(args->handle, args->offset + i * sizeof(rval), &rval, sizeof(rval)); + if (err != ESP_OK || rval != val) { + ets_printf("E: i=%d, cnt=%d rval=%d val=%d\n\n", i, args->word_count, rval, val); + args->result = ESP_FAIL; + goto done; + } + } + } + args->result = ESP_OK; + +done: + xSemaphoreGive(args->done); + vTaskDelay(1); + vTaskDelete(NULL); +} + +TEST_CASE("multiple tasks can access wl handle simultaneously", "[wear_levelling]") +{ + const esp_partition_t *partition = get_test_data_partition(); + wl_handle_t handle; + TEST_ESP_OK(wl_mount(partition, &handle)); + + size_t sector_size = wl_sector_size(handle); + TEST_ESP_OK(wl_erase_range(handle, 0, sector_size * 4)); + read_write_test_arg_t args1 = READ_WRITE_TEST_ARG_INIT(0, 1, handle); + read_write_test_arg_t args2 = READ_WRITE_TEST_ARG_INIT(sector_size, 2, handle); + const size_t stack_size = 4096; + + printf("writing 1 and 2\n"); + xTaskCreatePinnedToCore(&read_write_task, "rw1", stack_size, &args1, 3, NULL, 0); + xTaskCreatePinnedToCore(&read_write_task, "rw2", stack_size, &args2, 3, NULL, 1); + + xSemaphoreTake(args1.done, portMAX_DELAY); + printf("f1 done\n"); + TEST_ASSERT_EQUAL(ESP_OK, args1.result); + xSemaphoreTake(args2.done, portMAX_DELAY); + printf("f2 done\n"); + TEST_ASSERT_EQUAL(ESP_OK, args2.result); + + args1.write = false; + args2.write = false; + read_write_test_arg_t args3 = READ_WRITE_TEST_ARG_INIT(2 * sector_size, 3, handle); + read_write_test_arg_t args4 = READ_WRITE_TEST_ARG_INIT(3 * sector_size, 4, handle); + + printf("reading 1 and 2, writing 3 and 4\n"); + xTaskCreatePinnedToCore(&read_write_task, "rw3", stack_size, &args3, 3, NULL, 1); + xTaskCreatePinnedToCore(&read_write_task, "rw4", stack_size, &args4, 3, NULL, 0); + xTaskCreatePinnedToCore(&read_write_task, "rw1", stack_size, &args1, 3, NULL, 0); + xTaskCreatePinnedToCore(&read_write_task, "rw2", stack_size, &args2, 3, NULL, 1); + + xSemaphoreTake(args1.done, portMAX_DELAY); + printf("f1 done\n"); + TEST_ASSERT_EQUAL(ESP_OK, args1.result); + xSemaphoreTake(args2.done, portMAX_DELAY); + printf("f2 done\n"); + TEST_ASSERT_EQUAL(ESP_OK, args2.result); + xSemaphoreTake(args3.done, portMAX_DELAY); + printf("f3 done\n"); + TEST_ASSERT_EQUAL(ESP_OK, args3.result); + xSemaphoreTake(args4.done, portMAX_DELAY); + printf("f4 done\n"); + TEST_ASSERT_EQUAL(ESP_OK, args4.result); + + vSemaphoreDelete(args1.done); + vSemaphoreDelete(args2.done); + vSemaphoreDelete(args3.done); + vSemaphoreDelete(args4.done); + wl_unmount(handle); +} diff --git a/components/wear_levelling/test_wl_host/Flash_Emulator.cpp b/components/wear_levelling/test_wl_host/Flash_Emulator.cpp new file mode 100644 index 000000000..71f1bb1b1 --- /dev/null +++ b/components/wear_levelling/test_wl_host/Flash_Emulator.cpp @@ -0,0 +1,120 @@ +// Copyright 2015-2017 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. + +#include "Flash_Emulator.h" + +#include +#include +#include + +Flash_Emulator::Flash_Emulator(size_t size, size_t sector_sise) +{ + this->reset_count = 0x7fffffff; + this->size = size; + this->sector_sise = sector_sise; + this->buff = (uint8_t *)malloc(this->size); + this->access_count = new uint32_t[this->size / this->sector_sise]; + memset(this->access_count, 0, this->size / this->sector_sise * sizeof(uint32_t)); +} + +size_t Flash_Emulator::chip_size() +{ + return this->size; +} +size_t Flash_Emulator::sector_size() +{ + return this->sector_sise; +} + +esp_err_t Flash_Emulator::erase_sector(size_t sector) +{ + esp_err_t result = ESP_OK; + if ((this->reset_count != 0x7fffffff) && (this->reset_count != 0)) { + this->reset_count--; + } + if (this->reset_count <= 0) { + result = ESP_FAIL; + return result; + } + memset(&this->buff[sector * this->sector_sise], -1, this->sector_sise); + this->access_count[sector]++; + return result; +} + +uint32_t Flash_Emulator::get_access_minmax() +{ + uint32_t min = INT32_MAX; + uint32_t max = 0; + for (size_t i = 0; i < (this->size / this->sector_sise) - 2; i++) { + if (this->access_count[i] < min) { + min = this->access_count[i]; + } + if (this->access_count[i] > max) { + max = this->access_count[i]; + } + } + return max - min; +} + +esp_err_t Flash_Emulator::erase_range(size_t start_address, size_t size) +{ + esp_err_t result = ESP_OK; + uint32_t start_sector = start_address / this->sector_sise; + uint32_t count = (size + this->sector_sise - 1) / this->sector_sise; + for (size_t i = 0; i < count; i++) { + result |= this->erase_sector(start_sector + i); + } + return result; +} + +esp_err_t Flash_Emulator::write(size_t dest_addr, const void *src, size_t size) +{ + esp_err_t result = ESP_OK; + if ((this->reset_count != 0x7fffffff) && (this->reset_count != 0)) { + this->reset_count--; + } + if (this->reset_count <= 0) { + result = ESP_FAIL; + return result; + } + memcpy(&this->buff[dest_addr], src, size); + return result; +} + +esp_err_t Flash_Emulator::read(size_t src_addr, void *dest, size_t size) +{ + esp_err_t result = ESP_OK; + if (this->reset_count <= 0) { + result = ESP_FAIL; + return result; + } + memcpy(dest, &this->buff[src_addr], size); + return result; +} + +Flash_Emulator::~Flash_Emulator() +{ + free(this->buff); + delete this->access_count; +} + +void Flash_Emulator::SetResetCount(uint32_t count) +{ + this->reset_count = count; +} + +void Flash_Emulator::SetResetSector(size_t sector) +{ + this->reset_sector = sector; +} diff --git a/components/wear_levelling/test_wl_host/Flash_Emulator.h b/components/wear_levelling/test_wl_host/Flash_Emulator.h new file mode 100644 index 000000000..c9ec3c0ad --- /dev/null +++ b/components/wear_levelling/test_wl_host/Flash_Emulator.h @@ -0,0 +1,58 @@ +// Copyright 2015-2017 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. + +#ifndef _Flash_Emulator_H_ +#define _Flash_Emulator_H_ + +#include "esp_err.h" +#include "Flash_Access.h" +/** +* @brief This class is used to emulate flash devices. Class implements Flash_Access interface +* +*/ +class Flash_Emulator : public Flash_Access +{ + +public: + Flash_Emulator(size_t size, size_t sector_sise); + + virtual size_t chip_size(); + + virtual esp_err_t erase_sector(size_t sector); + virtual esp_err_t erase_range(size_t start_address, size_t size); + + virtual esp_err_t write(size_t dest_addr, const void *src, size_t size); + virtual esp_err_t read(size_t src_addr, void *dest, size_t size); + + virtual size_t sector_size(); + + virtual ~Flash_Emulator(); + + uint32_t get_access_minmax(); +public: + size_t size; + size_t sector_sise; + uint8_t *buff; + + uint32_t *access_count; + +public: + uint32_t reset_count; + size_t reset_sector; + void SetResetCount(uint32_t count); + void SetResetSector(size_t sector); + +}; + +#endif // _Flash_Emulator_H_ diff --git a/components/wear_levelling/test_wl_host/Makefile b/components/wear_levelling/test_wl_host/Makefile new file mode 100644 index 000000000..e71187180 --- /dev/null +++ b/components/wear_levelling/test_wl_host/Makefile @@ -0,0 +1,68 @@ +TEST_PROGRAM=test_wl +all: $(TEST_PROGRAM) + +SOURCE_FILES = \ + esp_error_check_stub.cpp \ + $(addprefix ../, \ + crc32.cpp \ + WL_Flash.cpp \ + ../nvs_flash/test_nvs_host/crc.cpp\ + ) \ + Flash_Emulator.cpp \ + wl_tests_host.cpp \ + TestPowerDown.cpp \ + esp_log_stub.cpp \ + main.cpp + + +INCLUDE_FLAGS = $(addprefix -I,\ + ../ \ + ../include \ + ../private_include \ + ../../esp32/include \ + ../../soc/esp32/include \ + ../../log/include \ + ../../spi_flash/include \ + ../../nvs_flash/test_nvs_host \ + ../../../tools/catch \ +) + +GCOV ?= gcov + +CPPFLAGS += $(INCLUDE_FLAGS) -D CONFIG_LOG_DEFAULT_LEVEL +CFLAGS += -fprofile-arcs -ftest-coverage +CXXFLAGS += -std=c++11 -Wall -Werror -fprofile-arcs -ftest-coverage +LDFLAGS += -lstdc++ -fprofile-arcs -ftest-coverage + +OBJ_FILES = $(SOURCE_FILES:.cpp=.o) + +COVERAGE_FILES = $(OBJ_FILES:.o=.gc*) + +$(OBJ_FILES): %.o: %.cpp + +$(TEST_PROGRAM): $(OBJ_FILES) + g++ $(LDFLAGS) -o $(TEST_PROGRAM) $(OBJ_FILES) + +$(OUTPUT_DIR): + mkdir -p $(OUTPUT_DIR) + +test: $(TEST_PROGRAM) + ./$(TEST_PROGRAM) + +$(COVERAGE_FILES): $(TEST_PROGRAM) test + +coverage.info: $(COVERAGE_FILES) + find ../ -name "*.gcno" -exec $(GCOV) -r -pb {} + + lcov --capture --directory ../ --no-external --output-file coverage.info --gcov-tool $(GCOV) + +coverage_report: coverage.info + genhtml coverage.info --output-directory coverage_report + @echo "Coverage report is in coverage_report/index.html" + +clean: + rm -f $(OBJ_FILES) $(TEST_PROGRAM) + rm -f $(COVERAGE_FILES) *.gcov + rm -rf coverage_report/ + rm -f coverage.info + +.PHONY: clean all test diff --git a/components/wear_levelling/test_wl_host/TestPowerDown.cpp b/components/wear_levelling/test_wl_host/TestPowerDown.cpp new file mode 100644 index 000000000..056d815a1 --- /dev/null +++ b/components/wear_levelling/test_wl_host/TestPowerDown.cpp @@ -0,0 +1,110 @@ +// Copyright 2015-2017 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. + + +#include "WL_Config.h" +#include "WL_Flash.h" +#include "Flash_Emulator.h" +#ifdef _MSC_VER +#define CHECK(m) +#else +#include "catch.hpp" +#endif + +extern Flash_Access *s_flash; + +bool test_power_down(WL_Flash *wl_flash, Flash_Emulator *emul, uint32_t used_sectors_count) +{ + REQUIRE(wl_flash->init() == ESP_OK); + s_flash = wl_flash; + + uint32_t add_const = 0; + int32_t sectors_count = s_flash->chip_size() / s_flash->sector_size(); + esp_err_t err = ESP_OK; + uint32_t *sector_data = new uint32_t[s_flash->sector_size() / sizeof(uint32_t)]; + + for (int32_t i = 0; i < sectors_count; i++) { + REQUIRE(s_flash->erase_sector(i) == ESP_OK); + for (uint32_t m = 0; m < s_flash->sector_size() / sizeof(uint32_t); m++) { + uint32_t temp_data = i * s_flash->sector_size() + add_const + m; + sector_data[m] = temp_data; + } + REQUIRE(s_flash->write(i * s_flash->sector_size(), sector_data, s_flash->sector_size()) == ESP_OK); + } + for (int32_t i = 0; i < sectors_count; i++) { + err |= s_flash->read(i * s_flash->sector_size(), sector_data, s_flash->sector_size()); + for (uint32_t m = 0; m < s_flash->sector_size() / sizeof(uint32_t); m++) { + uint32_t temp_data = i * s_flash->sector_size() + add_const + m; + REQUIRE(temp_data == sector_data[m]); + if (temp_data != sector_data[m]) { + printf("Error - read: %08x, expected %08x\n", sector_data[m], temp_data); + } + } + } + + int32_t max_count = 100; + int32_t max_check_count = used_sectors_count; + printf("used_sectors_count=%d\n", used_sectors_count); + for (int32_t k = 0; k < max_check_count; k++) { + + emul->SetResetCount(max_count); + int32_t err_sector = -1; + for (int32_t i = 0; i < sectors_count; i++) { + err = ESP_OK; + err = s_flash->erase_sector(i); + if (err != ESP_OK) { + err_sector = i; + break; + } + for (uint32_t m = 0; m < s_flash->sector_size() / sizeof(uint32_t); m++) { + uint32_t temp_data = i * s_flash->sector_size() + add_const + m; + sector_data[m] = temp_data; + } + err = s_flash->write(i * s_flash->sector_size(), sector_data, s_flash->sector_size()); + if (err != ESP_OK) { + err_sector = i; + break; + } + } + if (err_sector >= 0) { + max_count++; + } else { + max_count = 0; + } + emul->SetResetCount(INT32_MAX); + REQUIRE(wl_flash->init() == ESP_OK); + for (int32_t i = 0; i < sectors_count; i++) { + if (i != err_sector) { + err |= s_flash->read(i * s_flash->sector_size(), sector_data, s_flash->sector_size()); + for (uint32_t m = 0; m < s_flash->sector_size() / sizeof(uint32_t); m++) { + uint32_t temp_data = i * s_flash->sector_size() + add_const + m; + REQUIRE(temp_data == sector_data[m]); + if (temp_data != sector_data[m]) { + printf("Error - read: %08x, expected %08x, m=%i, sector=%i\n", sector_data[m], temp_data, m, i); + } + } + } + } + if (err_sector != -1) { + err |= s_flash->erase_sector(err_sector); + for (uint32_t m = 0; m < s_flash->sector_size() / sizeof(uint32_t); m++) { + uint32_t temp_data = err_sector * s_flash->sector_size() + add_const + m; + sector_data[m] = temp_data; + } + err |= s_flash->write(err_sector * s_flash->sector_size(), sector_data, s_flash->sector_size()); + } + printf("[%3.f%%] err_sector=%i\n", (float)k / ((float)max_check_count) * 100.0f, err_sector); + } + delete[] sector_data; + return true; +} diff --git a/components/wear_levelling/test_wl_host/esp_error_check_stub.cpp b/components/wear_levelling/test_wl_host/esp_error_check_stub.cpp new file mode 100644 index 000000000..9cff4af31 --- /dev/null +++ b/components/wear_levelling/test_wl_host/esp_error_check_stub.cpp @@ -0,0 +1,9 @@ +#include "catch.hpp" +#include "esp_err.h" + +void _esp_error_check_failed(esp_err_t rc, const char *file, int line, const char *function, const char *expression) +{ + printf("ESP_ERROR_CHECK failed: esp_err_t 0x%x at %p\n", rc, __builtin_return_address(0)); + printf("file: \"%s\" line %d\nfunc: %s\nexpression: %s\n", file, line, function, expression); + abort(); +} diff --git a/components/wear_levelling/test_wl_host/esp_log_stub.cpp b/components/wear_levelling/test_wl_host/esp_log_stub.cpp new file mode 100644 index 000000000..87dd12a90 --- /dev/null +++ b/components/wear_levelling/test_wl_host/esp_log_stub.cpp @@ -0,0 +1,17 @@ +#include +#include "esp_log.h" + +void esp_log_write(esp_log_level_t level, + const char *tag, + const char *format, ...) +{ + va_list arg; + va_start(arg, format); + vprintf(format, arg); + va_end(arg); +} + +uint32_t esp_log_timestamp() +{ + return 0; +} diff --git a/components/wear_levelling/test_wl_host/main.cpp b/components/wear_levelling/test_wl_host/main.cpp new file mode 100644 index 000000000..0c7c351f4 --- /dev/null +++ b/components/wear_levelling/test_wl_host/main.cpp @@ -0,0 +1,2 @@ +#define CATCH_CONFIG_MAIN +#include "catch.hpp" diff --git a/components/wear_levelling/test_wl_host/sdkconfig.h b/components/wear_levelling/test_wl_host/sdkconfig.h new file mode 100644 index 000000000..e69de29bb diff --git a/components/wear_levelling/test_wl_host/wl_tests_host.cpp b/components/wear_levelling/test_wl_host/wl_tests_host.cpp new file mode 100644 index 000000000..05068ac75 --- /dev/null +++ b/components/wear_levelling/test_wl_host/wl_tests_host.cpp @@ -0,0 +1,56 @@ +// Copyright 2015-2017 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. + +#include +#include "WL_Config.h" +#include "WL_Flash.h" +#include "Flash_Emulator.h" +#include "catch.hpp" + +#define FLASH_SECTOR_SIZE 512 +#define FLASH_USED_SECTOR (1024 - 3) +#define FLASH_ACCESS_SIZE (FLASH_SECTOR_SIZE*(FLASH_USED_SECTOR + 1 + 2)) +#define FLASH_START_ADDR 0x1000 +#define FLASH_PAGE_SIZE FLASH_SECTOR_SIZE*1 +#define FLASH_UPDATERATE 3 +#define FLASH_TEMP_SIZE FLASH_SECTOR_SIZE +#define FLASH_WR_BLOCK_SIZE 2 + +static const char *TAG = "wl_test_host"; +Flash_Access *s_flash; + +extern bool test_power_down(WL_Flash *wl_flash, Flash_Emulator *emul, uint32_t used_sectors_count); + +#define TEST_COUNT_MAX 100 + +TEST_CASE("flash starts with all bytes == 0xff", "[spi_flash_emu]") +{ + wl_config_t *wl = new wl_config_t(); + + wl->full_mem_size = FLASH_ACCESS_SIZE; + wl->start_addr = FLASH_START_ADDR; + wl->sector_size = FLASH_SECTOR_SIZE; + wl->page_size = FLASH_PAGE_SIZE; + wl->updaterate = FLASH_UPDATERATE; + wl->temp_buff_size = FLASH_TEMP_SIZE; + wl->wr_size = FLASH_WR_BLOCK_SIZE; + + WL_Flash *wl_flash = new WL_Flash(); + Flash_Emulator *emul = new Flash_Emulator(FLASH_ACCESS_SIZE + FLASH_START_ADDR, FLASH_SECTOR_SIZE); + CHECK(wl_flash->config(wl, emul) == ESP_OK); + + test_power_down(wl_flash, emul, TEST_COUNT_MAX); +} + + diff --git a/components/wear_levelling/wear_levelling.cpp b/components/wear_levelling/wear_levelling.cpp new file mode 100644 index 000000000..4e581196b --- /dev/null +++ b/components/wear_levelling/wear_levelling.cpp @@ -0,0 +1,238 @@ +// Copyright 2015-2017 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. + +#include +#include +#include +#include "wear_levelling.h" +#include "WL_Config.h" +#include "WL_Flash.h" +#include "SPI_Flash.h" +#include "Partition.h" + +#ifndef MAX_WL_HANDLES +#define MAX_WL_HANDLES 8 +#endif // MAX_WL_HANDLES + +#ifndef WL_DEFAULT_UPDATERATE +#define WL_DEFAULT_UPDATERATE 16 +#endif //WL_DEFAULT_UPDATERATE + +#ifndef WL_DEFAULT_TEMP_BUFF_SIZE +#define WL_DEFAULT_TEMP_BUFF_SIZE 32 +#endif //WL_DEFAULT_TEMP_BUFF_SIZE + +#ifndef WL_DEFAULT_WRITE_SIZE +#define WL_DEFAULT_WRITE_SIZE 16 +#endif //WL_DEFAULT_WRITE_SIZE + +#ifndef WL_DEFAULT_START_ADDR +#define WL_DEFAULT_START_ADDR 0 +#endif //WL_DEFAULT_START_ADDR + +#ifndef WL_CURRENT_VERSION +#define WL_CURRENT_VERSION 1 +#endif //WL_CURRENT_VERSION + +typedef struct { + WL_Flash *instance; + _lock_t lock; +} wl_instance_t; + +static wl_instance_t s_instances[MAX_WL_HANDLES]; +static _lock_t s_instances_lock; +static const char *TAG = "wear_levelling"; + +static esp_err_t check_handle(wl_handle_t handle, const char *func); + +esp_err_t wl_mount(const esp_partition_t *partition, wl_handle_t *out_handle) +{ + // Initialize variables before the first jump to cleanup label + void *wl_flash_ptr = NULL; + WL_Flash *wl_flash = NULL; + void *part_ptr = NULL; + Partition *part = NULL; + + _lock_acquire(&s_instances_lock); + esp_err_t result = ESP_OK; + *out_handle = WL_INVALID_HANDLE; + for (size_t i = 0; i < MAX_WL_HANDLES; i++) { + if (s_instances[i].instance == NULL) { + *out_handle = i; + break; + } + } + if (*out_handle == WL_INVALID_HANDLE) { + ESP_LOGE(TAG, "MAX_WL_HANDLES=%d instances already allocated", MAX_WL_HANDLES); + result = ESP_ERR_NO_MEM; + goto out; + } + + wl_config_t cfg; + cfg.full_mem_size = partition->size; + cfg.start_addr = WL_DEFAULT_START_ADDR; + cfg.version = WL_CURRENT_VERSION; + cfg.sector_size = SPI_FLASH_SEC_SIZE; + cfg.page_size = SPI_FLASH_SEC_SIZE; + cfg.updaterate = WL_DEFAULT_UPDATERATE; + cfg.temp_buff_size = WL_DEFAULT_TEMP_BUFF_SIZE; + cfg.wr_size = WL_DEFAULT_WRITE_SIZE; + + // Allocate memory for a Partition object, and then initialize the object + // using placement new operator. This way we can recover from out of + // memory condition. + part_ptr = malloc(sizeof(Partition)); + if (part_ptr == NULL) { + result = ESP_ERR_NO_MEM; + ESP_LOGE(TAG, "%s: can't allocate Partition", __func__); + goto out; + } + part = new (part_ptr) Partition(partition); + + // Same for WL_Flash: allocate memory, use placement new + wl_flash_ptr = malloc(sizeof(WL_Flash)); + if (wl_flash_ptr == NULL) { + result = ESP_ERR_NO_MEM; + ESP_LOGE(TAG, "%s: can't allocate WL_Flash", __func__); + goto out; + } + wl_flash = new (wl_flash_ptr) WL_Flash(); + + result = wl_flash->config(&cfg, part); + if (ESP_OK != result) { + ESP_LOGE(TAG, "%s: config instance=0x%08x, result=0x%x", __func__, *out_handle, result); + goto out; + } + result = wl_flash->init(); + if (ESP_OK != result) { + ESP_LOGE(TAG, "%s: init instance=0x%08x, result=0x%x", __func__, *out_handle, result); + goto out; + } + s_instances[*out_handle].instance = wl_flash; + _lock_init(&s_instances[*out_handle].lock); + _lock_release(&s_instances_lock); + return ESP_OK; + +out: + _lock_release(&s_instances_lock); + *out_handle = WL_INVALID_HANDLE; + if (wl_flash) { + wl_flash->~WL_Flash(); + free(wl_flash); + } + if (part) { + part->~Partition(); + free(part); + } + return result; +} + +esp_err_t wl_unmount(wl_handle_t handle) +{ + esp_err_t result = ESP_OK; + _lock_acquire(&s_instances_lock); + result = check_handle(handle, __func__); + if (result == ESP_OK) { + ESP_LOGV(TAG, "deleting handle 0x%08x", handle); + // We have to flush state of the component + result = s_instances[handle].instance->flush(); + // We use placement new in wl_mount, so call destructor directly + Flash_Access *drv = s_instances[handle].instance->get_drv(); + drv->~Flash_Access(); + free(drv); + s_instances[handle].instance->~WL_Flash(); + free(s_instances[handle].instance); + s_instances[handle].instance = NULL; + _lock_close(&s_instances[handle].lock); // also zeroes the lock variable + } + _lock_release(&s_instances_lock); + return result; +} + +esp_err_t wl_erase_range(wl_handle_t handle, size_t start_addr, size_t size) +{ + esp_err_t result = check_handle(handle, __func__); + if (result != ESP_OK) { + return result; + } + _lock_acquire(&s_instances[handle].lock); + result = s_instances[handle].instance->erase_range(start_addr, size); + _lock_release(&s_instances[handle].lock); + return result; +} + +esp_err_t wl_write(wl_handle_t handle, size_t dest_addr, const void *src, size_t size) +{ + esp_err_t result = check_handle(handle, __func__); + if (result != ESP_OK) { + return result; + } + _lock_acquire(&s_instances[handle].lock); + result = s_instances[handle].instance->write(dest_addr, src, size); + _lock_release(&s_instances[handle].lock); + return result; +} + +esp_err_t wl_read(wl_handle_t handle, size_t src_addr, void *dest, size_t size) +{ + esp_err_t result = check_handle(handle, __func__); + if (result != ESP_OK) { + return result; + } + _lock_acquire(&s_instances[handle].lock); + result = s_instances[handle].instance->read(src_addr, dest, size); + _lock_release(&s_instances[handle].lock); + return result; +} + +size_t wl_size(wl_handle_t handle) +{ + esp_err_t err = check_handle(handle, __func__); + if (err != ESP_OK) { + return 0; + } + _lock_acquire(&s_instances[handle].lock); + size_t result = s_instances[handle].instance->chip_size(); + _lock_release(&s_instances[handle].lock); + return result; +} + +size_t wl_sector_size(wl_handle_t handle) +{ + esp_err_t err = check_handle(handle, __func__); + if (err != ESP_OK) { + return 0; + } + _lock_acquire(&s_instances[handle].lock); + size_t result = s_instances[handle].instance->sector_size(); + _lock_release(&s_instances[handle].lock); + return result; +} + +static esp_err_t check_handle(wl_handle_t handle, const char *func) +{ + if (handle == WL_INVALID_HANDLE) { + ESP_LOGE(TAG, "%s: invalid handle", func); + return ESP_ERR_NOT_FOUND; + } + if (handle >= MAX_WL_HANDLES) { + ESP_LOGE(TAG, "%s: instance[0x%08x] out of range", func, handle); + return ESP_ERR_INVALID_ARG; + } + if (s_instances[handle].instance == NULL) { + ESP_LOGE(TAG, "%s: instance[0x%08x] not initialized", func, handle); + return ESP_ERR_NOT_FOUND; + } + return ESP_OK; +} diff --git a/components/xtensa-debug-module/trax.c b/components/xtensa-debug-module/trax.c index 5174e4477..15a125584 100644 --- a/components/xtensa-debug-module/trax.c +++ b/components/xtensa-debug-module/trax.c @@ -30,11 +30,11 @@ static const char* TAG = "trax"; int trax_enable(trax_ena_select_t which) { -#if !CONFIG_MEMMAP_TRACEMEM +#if !CONFIG_ESP32_TRAX ESP_LOGE(TAG, "Trax_enable called, but trax is disabled in menuconfig!"); return ESP_ERR_NO_MEM; #endif -#if !CONFIG_MEMMAP_TRACEMEM_TWOBANKS +#if !CONFIG_ESP32_TRAX_TWOBANKS if (which == TRAX_ENA_PRO_APP || which == TRAX_ENA_PRO_APP_SWAP) return ESP_ERR_NO_MEM; #endif if (which == TRAX_ENA_PRO_APP || which == TRAX_ENA_PRO_APP_SWAP) { @@ -50,7 +50,7 @@ int trax_enable(trax_ena_select_t which) int trax_start_trace(trax_downcount_unit_t units_until_stop) { -#if !CONFIG_MEMMAP_TRACEMEM +#if !CONFIG_ESP32_TRAX ESP_LOGE(TAG, "Trax_start_trace called, but trax is disabled in menuconfig!"); return ESP_ERR_NO_MEM; #endif @@ -74,7 +74,7 @@ int trax_start_trace(trax_downcount_unit_t units_until_stop) int trax_trigger_traceend_after_delay(int delay) { -#if !CONFIG_MEMMAP_TRACEMEM +#if !CONFIG_ESP32_TRAX ESP_LOGE(TAG, "Trax_trigger_traceend_after_delay called, but trax is disabled in menuconfig!"); return ESP_ERR_NO_MEM; #endif diff --git a/docs/Doxyfile b/docs/Doxyfile index 43d227381..9b7d602b9 100755 --- a/docs/Doxyfile +++ b/docs/Doxyfile @@ -38,7 +38,9 @@ INPUT = ../components/esp32/include/esp_wifi.h \ ../components/fatfs/src/diskio.h \ ../components/esp32/include/esp_core_dump.h \ ../components/mdns/include/mdns.h \ - ../components/bootloader_support/include/esp_flash_encrypt.h + ../components/bootloader_support/include/esp_flash_encrypt.h \ + ../components/wear_levelling/include/wear_levelling.h + ## Get warnings for functions that have no documentation for their parameters or return value ## diff --git a/docs/api/ethernet/esp_eth.rst b/docs/api/ethernet/esp_eth.rst index fbecdca33..223c7b226 100644 --- a/docs/api/ethernet/esp_eth.rst +++ b/docs/api/ethernet/esp_eth.rst @@ -13,10 +13,17 @@ Header Files ^^^^^^^^^^^^ * :component_file:`ethernet/include/esp_eth.h` + * :component_file:`ethernet/include/phy/phy.h` -Macros -^^^^^^ +PHY Interfaces +^^^^^^^^^^^^^^ +The configured PHY model(s) are set in software by configuring the eth_config_t structure for the given PHY. + +Headers include a default configuration structure. These default configurations will need some members overriden or re-set before they can be used for a particular PHY hardware configuration. Consult the Ethernet example to see how this is done. + + * :component_file:`ethernet/include/phy/phy_tlk110.h` + * :component_file:`ethernet/include/phy/phy_lan8720.h` Type Definitions ^^^^^^^^^^^^^^^^ @@ -55,4 +62,13 @@ Functions .. doxygenfunction:: esp_eth_get_mac .. doxygenfunction:: esp_eth_smi_write .. doxygenfunction:: esp_eth_smi_read +.. doxygenfunction:: esp_eth_smi_wait_value +.. doxygenfunction:: esp_eth_smi_wait_set .. doxygenfunction:: esp_eth_free_rx_buf + + +PHY Configuration Constants +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. doxygenvariable:: phy_tlk110_default_ethernet_config +.. doxygenvariable:: phy_lan8720_default_ethernet_config diff --git a/docs/api/storage/fatfs.rst b/docs/api/storage/fatfs.rst index 6dd04ae3e..b6735b7c0 100644 --- a/docs/api/storage/fatfs.rst +++ b/docs/api/storage/fatfs.rst @@ -12,7 +12,7 @@ Using FatFs with VFS Most applications will use the following flow when working with ``esp_vfs_fat_`` functions: -1. Call ``esp_vfs_fat_register``, specifying path prefix where the filesystem has to be mounted (e.g. ``"/sdcard"``), FatFs drive number, and a variable which will receive a pointer to ``FATFS`` structure. +1. Call ``esp_vfs_fat_register``, specifying path prefix where the filesystem has to be mounted (e.g. ``"/sdcard"``, ``"/spiflash"``), FatFs drive number, and a variable which will receive a pointer to ``FATFS`` structure. 2. Call ``ff_diskio_register`` function to register disk IO driver for the drive number used in step 1. @@ -43,7 +43,7 @@ Using FatFs with VFS and SD cards .. doxygenfunction:: esp_vfs_fat_sdmmc_mount -.. doxygenstruct:: esp_vfs_fat_sdmmc_mount_config_t +.. doxygenstruct:: esp_vfs_fat_mount_config_t :members: .. doxygenfunction:: esp_vfs_fat_sdmmc_unmount diff --git a/docs/api/storage/index.rst b/docs/api/storage/index.rst index 207ad01cc..a1d3f553d 100644 --- a/docs/api/storage/index.rst +++ b/docs/api/storage/index.rst @@ -9,6 +9,7 @@ Storage API Non-Volatile Storage Virtual Filesystem FAT Filesystem + Wear Levelling Example code for this API section is provided in :example:`storage` directory of ESP-IDF examples. diff --git a/docs/api/storage/wear-levelling.rst b/docs/api/storage/wear-levelling.rst new file mode 100644 index 000000000..71bb3d4b6 --- /dev/null +++ b/docs/api/storage/wear-levelling.rst @@ -0,0 +1,50 @@ +.. include:: ../../../components/wear_levelling/README.rst + +See also +-------- + +- :doc:`FAT Filesystem ` +- :doc:`Partition Table documentation ` + + +Application Example +------------------- + +An example which combines wear levelling driver with FATFS library is provided in ``examples/storage/wear_levelling`` directory. This example initializes the +wear levelling driver, mounts FATFS partition, and writes and reads data from it using POSIX and C library APIs. See README.md file in the example directory for more information. + +High level API Reference +------------- + +Header Files +^^^^^^^^^^^^ + + * :component_file:`fatfs/src/esp_vfs_fat.h` + +Functions +^^^^^^^^^ + +.. doxygenfunction:: esp_vfs_fat_spiflash_mount +.. doxygenstruct:: esp_vfs_fat_mount_config_t + :members: +.. doxygenfunction:: esp_vfs_fat_spiflash_unmount + +Mid level API Reference +------------- + +Header Files +^^^^^^^^^^^^ + + * :component_file:`wear_levelling/include/wear_levelling.h` + +Functions +^^^^^^^^^ + +.. doxygenfunction:: wl_mount +.. doxygenfunction:: wl_unmount +.. doxygenfunction:: wl_erase_range +.. doxygenfunction:: wl_write +.. doxygenfunction:: wl_read +.. doxygenfunction:: wl_size +.. doxygenfunction:: wl_sector_size + diff --git a/examples/bluetooth/gatt_client/main/gattc_demo.c b/examples/bluetooth/gatt_client/main/gattc_demo.c index 2d852c831..089289d00 100644 --- a/examples/bluetooth/gatt_client/main/gattc_demo.c +++ b/examples/bluetooth/gatt_client/main/gattc_demo.c @@ -318,8 +318,8 @@ static void esp_gap_cb(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *par } if (adv_name != NULL) { - if (strcmp((char *)adv_name, device_name) == 0) { - ESP_LOGI(GATTC_TAG, "Searched device %s", device_name); + if (strlen(device_name) == adv_name_len && strncmp((char *)adv_name, device_name, adv_name_len) == 0) { + ESP_LOGI(GATTC_TAG, "Searched device %s\n", device_name); if (connect == false) { connect = true; ESP_LOGI(GATTC_TAG, "Connect to the remote device."); diff --git a/examples/ethernet/ethernet/README.md b/examples/ethernet/ethernet/README.md index 71c259045..e4a6e5cc7 100644 --- a/examples/ethernet/ethernet/README.md +++ b/examples/ethernet/ethernet/README.md @@ -1,6 +1,56 @@ -# ethernet Example +# Ethernet Example -Init ethernet interface and enable it ,then you can ping it if it got ip address. +Initialises the ethernet interface and enables it, then sends DHCP requests and tries to obtain a DHCP lease. If successful then you will be able to ping the device. +# PHY Configuration -See the README.md file in the upper level 'examples' directory for more information about examples. +Use "make menuconfig" to set the PHY model and the PHY address, and configure the SMI I/O pins (see below). These configuration items will vary depending on the hardware configuration you are using. + +The default example configuration is correct for Espressif's Ethernet board with TLK110 PHY. Other hardware will require different configuration and/or changes to the example. + +## PHY Address + +The PHY address depends on the hardware and the PHY configuration. Consult the documentation/datasheet for the PHY hardware you have. + +* Default address 31 is correct for Espressif's Ethernet board with TLK110 PHY. +* Address 1 is correct for the common Waveshare LAN8720 PHY breakout. +* Other LAN8720 breakouts may take address 0. + +If the PHY address is incorrect then the EMAC will initialise but all attempts to read/write configuration registers on the PHY will fail. + +## RMII PHY Wiring + +The following PHY connections are required for RMII PHY data connections. These GPIO pin assignments cannot be changed. + +| GPIO | RMII Signal | ESP32 EMAC Function | Notes | +| ------- | ----------- | ------------------- | ----- | +| 0 | REF_CLK | EMAC_TX_CLK | Currently this must be a 50MHz reference clock input from the PHY (ext_osc configuration). | +| 21 | TX_EN | EMAC_TX_EN | | +| 19 | TX0 | EMAC_TXD0 | | +| 22 | TX1 | EMAC_TXD1 | | +| 25 | RX0 | EMAC_RXD0 | | +| 26 | RX1 | EMAC_RXD1 | | +| 27 | CRS_DV | EMAC_RX_DRV | | + +## RMII PHY SMI Wiring + +The following PHY connections are required for RMII PHY SMI (aka MDIO) management interface. These GPIO pin assignments can be changed to any unused GPIO pin. + +For the example, these pins are configured via `make menuconfig` under the Example configuration. + +| Default Example GPIO | RMII Signal | Notes | +| -------------------- | ----------- | ------------- | +| 23 | MDC | Output to PHY | +| 18 | MDIO | Bidirectional | + +The defaults in the example are correct for Espressif's Ethernet development board. + +## Note about GPIO0 + +Because GPIO0 is a strapping pin for entering UART flashing mode on reset, care must be taken when also using this pin as EMAC_TX_CLK. If the clock output from the PHY is oscillating during reset, the ESP32 may randomly enter UART flashing mode. + +One solution is to use an additional GPIO as a "power pin", which either powers the PHY on/off or enables/disables the PHY's own oscillator. This prevents the clock signal from being active during a system reset. For this configuration to work, GPIO0 also needs a pullup resistor and the "power pin" GPIO will need a pullup/pulldown resistor - as appropriate in order to keep the PHY clock disabled when the ESP32 is in reset. + +See the example source code to see how the "power pin" GPIO can be managed in software. + +The example defaults to using GPIO 17 for this function, but it can be overriden. On Espressif's Ethernet development board, GPIO 17 is the power pin used to enable/disable the PHY oscillator. diff --git a/examples/ethernet/ethernet/main/Kconfig.projbuild b/examples/ethernet/ethernet/main/Kconfig.projbuild new file mode 100644 index 000000000..f6c46b54d --- /dev/null +++ b/examples/ethernet/ethernet/main/Kconfig.projbuild @@ -0,0 +1,54 @@ +menu "Example Configuration" + +choice PHY_MODEL + prompt "Ethernet PHY" + default CONFIG_PHY_TLK110 + help + Select the PHY driver to use for the example. + +config PHY_TLK110 + bool "TI TLK110 PHY" + help + Select this to use the TI TLK110 PHY + +config PHY_LAN8720 + bool "Microchip LAN8720 PHY" + help + Select this to use the Microchip LAN8720 PHY + +endchoice + +config PHY_ADDRESS + int "PHY Address (0-31)" + default 31 + range 0 31 + help + Select the PHY Address (0-31) for the hardware configuration and PHY model. + +config PHY_USE_POWER_PIN + bool "Use PHY Power (enable/disable) pin" + default y + help + Use a GPIO "power pin" to power the PHY on/off during operation. + Consult the example README for more details + +config PHY_POWER_PIN + int "PHY Power GPIO" + default 17 + depends on PHY_USE_POWER_PIN + help + GPIO number to use for powering on/off the PHY. + +config PHY_SMI_MDC_PIN + int "SMI MDC Pin" + default 23 + help + GPIO number to use for SMI clock output MDC to PHY. + +config PHY_SMI_MDIO_PIN + int "SMI MDIO Pin" + default 18 + help + GPIO number to use for SMI data pin MDIO to/from PHY. + +endmenu diff --git a/examples/ethernet/ethernet/main/ethernet_example_main.c b/examples/ethernet/ethernet/main/ethernet_example_main.c index d46e2e6d9..8345ab6da 100644 --- a/examples/ethernet/ethernet/main/ethernet_example_main.c +++ b/examples/ethernet/ethernet/main/ethernet_example_main.c @@ -32,110 +32,70 @@ #include "tcpip_adapter.h" #include "nvs_flash.h" #include "driver/gpio.h" -#include "tlk110_phy.h" + +#ifdef CONFIG_PHY_LAN8720 +#include "eth_phy/phy_lan8720.h" +#define DEFAULT_ETHERNET_PHY_CONFIG phy_lan8720_default_ethernet_config +#endif +#ifdef CONFIG_PHY_TLK110 +#include "eth_phy/phy_tlk110.h" +#define DEFAULT_ETHERNET_PHY_CONFIG phy_tlk110_default_ethernet_config +#endif static const char *TAG = "eth_example"; -#define DEFAULT_PHY_CONFIG (AUTO_MDIX_ENABLE|AUTO_NEGOTIATION_ENABLE|AN_1|AN_0|LED_CFG) -#define PIN_PHY_POWER 17 -#define PIN_SMI_MDC 23 -#define PIN_SMI_MDIO 18 +#define PIN_PHY_POWER CONFIG_PHY_POWER_PIN +#define PIN_SMI_MDC CONFIG_PHY_SMI_MDC_PIN +#define PIN_SMI_MDIO CONFIG_PHY_SMI_MDIO_PIN -void phy_tlk110_check_phy_init(void) -{ - while((esp_eth_smi_read(BASIC_MODE_STATUS_REG) & AUTO_NEGOTIATION_COMPLETE ) != AUTO_NEGOTIATION_COMPLETE) - {}; - while((esp_eth_smi_read(PHY_STATUS_REG) & AUTO_NEGOTIATION_STATUS ) != AUTO_NEGOTIATION_STATUS) - {}; - while((esp_eth_smi_read(CABLE_DIAGNOSTIC_CONTROL_REG) & DIAGNOSTIC_DONE ) != DIAGNOSTIC_DONE) - {}; -} +#ifdef CONFIG_PHY_USE_POWER_PIN +/* This replaces the default PHY power on/off function with one that + also uses a GPIO for power on/off. -eth_speed_mode_t phy_tlk110_get_speed_mode(void) + If this GPIO is not connected on your device (and PHY is always powered), you can use the default PHY-specific power + on/off function rather than overriding with this one. +*/ +static void phy_device_power_enable_via_gpio(bool enable) { - if((esp_eth_smi_read(PHY_STATUS_REG) & SPEED_STATUS ) != SPEED_STATUS) { - return ETH_SPEED_MODE_100M; - } else { - return ETH_SPEED_MODE_10M; - } -} + assert(DEFAULT_ETHERNET_PHY_CONFIG.phy_power_enable); -eth_duplex_mode_t phy_tlk110_get_duplex_mode(void) -{ - if((esp_eth_smi_read(PHY_STATUS_REG) & DUPLEX_STATUS ) == DUPLEX_STATUS) { - return ETH_MDOE_FULLDUPLEX; - } else { - return ETH_MODE_HALFDUPLEX; - } -} + if (!enable) { + /* Do the PHY-specific power_enable(false) function before powering down */ + DEFAULT_ETHERNET_PHY_CONFIG.phy_power_enable(false); + } -bool phy_tlk110_check_phy_link_status(void) -{ - return ((esp_eth_smi_read(BASIC_MODE_STATUS_REG) & LINK_STATUS) == LINK_STATUS ); -} - -bool phy_tlk110_get_partner_pause_enable(void) -{ - if((esp_eth_smi_read(PHY_LINK_PARTNER_ABILITY_REG) & PARTNER_PAUSE) == PARTNER_PAUSE) { - return true; - } else { - return false; - } -} - -void phy_enable_flow_ctrl(void) -{ - uint32_t data = 0; - data = esp_eth_smi_read(AUTO_NEG_ADVERTISEMENT_REG); - esp_eth_smi_write(AUTO_NEG_ADVERTISEMENT_REG,data|ASM_DIR|PAUSE); -} - -void phy_tlk110_power_enable(bool enable) -{ gpio_pad_select_gpio(PIN_PHY_POWER); gpio_set_direction(PIN_PHY_POWER,GPIO_MODE_OUTPUT); if(enable == true) { gpio_set_level(PIN_PHY_POWER, 1); + ESP_LOGD(TAG, "phy_device_power_enable(TRUE)"); } else { gpio_set_level(PIN_PHY_POWER, 0); - } -} - -void phy_tlk110_init(void) -{ - esp_eth_smi_write(PHY_RESET_CONTROL_REG, SOFTWARE_RESET); - - while (esp_eth_smi_read(PHY_IDENTIFIER_REG) != OUI_MSB_21TO6_DEF) { + ESP_LOGD(TAG, "power_enable(FALSE)"); } - esp_eth_smi_write(SW_STRAP_CONTROL_REG, DEFAULT_PHY_CONFIG | SW_STRAP_CONFIG_DONE); - - ets_delay_us(300); + // Allow the power up/down to take effect, min 300us + vTaskDelay(1); - //if config.flow_ctrl_enable == true ,enable this - phy_enable_flow_ctrl(); + if (enable) { + /* Run the PHY-specific power on operations now the PHY has power */ + DEFAULT_ETHERNET_PHY_CONFIG.phy_power_enable(true); + } } +#endif -void eth_gpio_config_rmii(void) +static void eth_gpio_config_rmii(void) { - //txd0 to gpio19 ,can not change - PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO19_U, FUNC_GPIO19_EMAC_TXD0); - //tx_en to gpio21 ,can not change - PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO21_U, FUNC_GPIO21_EMAC_TX_EN); - //txd1 to gpio22 , can not change - PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO22_U, FUNC_GPIO22_EMAC_TXD1); - //rxd0 to gpio25 , can not change - gpio_set_direction(25, GPIO_MODE_INPUT); - //rxd1 to gpio26 ,can not change - gpio_set_direction(26, GPIO_MODE_INPUT); - //rmii clk ,can not change - gpio_set_direction(0, GPIO_MODE_INPUT); - - //mdc to gpio23 - gpio_matrix_out(PIN_SMI_MDC, EMAC_MDC_O_IDX, 0, 0); - //mdio to gpio18 - gpio_matrix_out(PIN_SMI_MDIO, EMAC_MDO_O_IDX, 0, 0); - gpio_matrix_in(PIN_SMI_MDIO, EMAC_MDI_I_IDX, 0); + // RMII data pins are fixed: + // TXD0 = GPIO19 + // TXD1 = GPIO22 + // TX_EN = GPIO21 + // RXD0 = GPIO25 + // RXD1 = GPIO26 + // CLK == GPIO0 + phy_rmii_configure_data_interface_pins(); + // MDC is GPIO 23, MDIO is GPIO 18 + phy_rmii_smi_configure_pins(PIN_SMI_MDC, PIN_SMI_MDIO); } void eth_task(void *pvParameter) @@ -149,11 +109,11 @@ void eth_task(void *pvParameter) vTaskDelay(2000 / portTICK_PERIOD_MS); if (tcpip_adapter_get_ip_info(ESP_IF_ETH, &ip) == 0) { - ESP_LOGI(TAG, "\n~~~~~~~~~~~\n"); + ESP_LOGI(TAG, "~~~~~~~~~~~"); ESP_LOGI(TAG, "ETHIP:"IPSTR, IP2STR(&ip.ip)); ESP_LOGI(TAG, "ETHPMASK:"IPSTR, IP2STR(&ip.netmask)); ESP_LOGI(TAG, "ETHPGW:"IPSTR, IP2STR(&ip.gw)); - ESP_LOGI(TAG, "\n~~~~~~~~~~~\n"); + ESP_LOGI(TAG, "~~~~~~~~~~~"); } } } @@ -164,20 +124,17 @@ void app_main() tcpip_adapter_init(); esp_event_loop_init(NULL, NULL); - eth_config_t config; - config.phy_addr = PHY31; - config.mac_mode = ETH_MODE_RMII; - config.phy_init = phy_tlk110_init; + eth_config_t config = DEFAULT_ETHERNET_PHY_CONFIG; + /* Set the PHY address in the example configuration */ + config.phy_addr = CONFIG_PHY_ADDRESS; config.gpio_config = eth_gpio_config_rmii; config.tcpip_input = tcpip_adapter_eth_input; - config.phy_check_init = phy_tlk110_check_phy_init; - config.phy_check_link = phy_tlk110_check_phy_link_status; - config.phy_get_speed_mode = phy_tlk110_get_speed_mode; - config.phy_get_duplex_mode = phy_tlk110_get_duplex_mode; - //Only FULLDUPLEX mode support flow ctrl now! - config.flow_ctrl_enable = true; - config.phy_get_partner_pause_enable = phy_tlk110_get_partner_pause_enable; - config.phy_power_enable = phy_tlk110_power_enable; + +#ifdef CONFIG_PHY_USE_POWER_PIN + /* Replace the default 'power enable' function with an example-specific + one that toggles a power GPIO. */ + config.phy_power_enable = phy_device_power_enable_via_gpio; +#endif ret = esp_eth_init(&config); diff --git a/examples/ethernet/ethernet/main/tlk110_phy.h b/examples/ethernet/ethernet/main/tlk110_phy.h deleted file mode 100644 index 63236edeb..000000000 --- a/examples/ethernet/ethernet/main/tlk110_phy.h +++ /dev/null @@ -1,36 +0,0 @@ -#define BASIC_MODE_STATUS_REG (0x1) -#define AUTO_NEGOTIATION_COMPLETE BIT(5) -#define LINK_STATUS BIT(2) - -#define PHY_IDENTIFIER_REG (0x2) -#define OUI_MSB_21TO6_DEF 0x2000 - -#define AUTO_NEG_ADVERTISEMENT_REG (0x4) -#define ASM_DIR BIT(11) -#define PAUSE BIT(10) - -#define PHY_LINK_PARTNER_ABILITY_REG (0x5) -#define PARTNER_ASM_DIR BIT(11) -#define PARTNER_PAUSE BIT(10) - -#define SW_STRAP_CONTROL_REG (0x9) -#define SW_STRAP_CONFIG_DONE BIT(15) -#define AUTO_MDIX_ENABLE BIT(14) -#define AUTO_NEGOTIATION_ENABLE BIT(13) -#define AN_1 BIT(12) -#define AN_0 BIT(11) -#define LED_CFG BIT(10) -#define RMII_ENHANCED_MODE BIT(9) - -#define PHY_STATUS_REG (0x10) -#define AUTO_NEGOTIATION_STATUS BIT(4) -#define DUPLEX_STATUS BIT(2) -#define SPEED_STATUS BIT(1) - -#define CABLE_DIAGNOSTIC_CONTROL_REG (0x1e) -#define DIAGNOSTIC_DONE BIT(1) - -#define PHY_RESET_CONTROL_REG (0x1f) -#define SOFTWARE_RESET BIT(15) - - diff --git a/examples/performance/tcp_perf/main/Kconfig.projbuild b/examples/performance/tcp_perf/main/Kconfig.projbuild index 92bf8387f..7c95b49bc 100644 --- a/examples/performance/tcp_perf/main/Kconfig.projbuild +++ b/examples/performance/tcp_perf/main/Kconfig.projbuild @@ -103,6 +103,7 @@ config TCP_PERF_SERVER_PORT config TCP_PERF_SERVER_IP string "TCP server ip" + depends on TCP_PERF_ESP_IS_CLIENT default "192.168.4.1" help IP of TCP server. diff --git a/examples/performance/tcp_perf/main/tcp_main.c b/examples/performance/tcp_perf/main/tcp_main.c index fbb65c0f0..bb86700a7 100644 --- a/examples/performance/tcp_perf/main/tcp_main.c +++ b/examples/performance/tcp_perf/main/tcp_main.c @@ -1,3 +1,11 @@ +/* tcp_perf Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ /* @@ -22,6 +30,7 @@ step3: #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" +#include "freertos/event_groups.h" #include "esp_log.h" #include "esp_err.h" @@ -32,63 +41,62 @@ step3: //this task establish a TCP connection and receive data from TCP static void tcp_conn(void *pvParameters) { - ESP_LOGI(TAG, "task tcp_conn start."); + ESP_LOGI(TAG, "task tcp_conn."); /*wating for connecting to AP*/ - do - { - vTaskDelay(100); - } - while (!connectedflag); + xEventGroupWaitBits(tcp_event_group, WIFI_CONNECTED_BIT,false, true, portMAX_DELAY); + ESP_LOGI(TAG, "sta has connected to ap."); /*create tcp socket*/ int socket_ret; -#if ESP_TCP_MODE_SERVER +#if EXAMPLE_ESP_TCP_MODE_SERVER + ESP_LOGI(TAG, "tcp_server will start after 3s..."); vTaskDelay(3000 / portTICK_RATE_MS); ESP_LOGI(TAG, "create_tcp_server."); socket_ret=create_tcp_server(); -#else /*ESP_TCP_MODE_SERVER*/ +#else /*EXAMPLE_ESP_TCP_MODE_SERVER*/ + ESP_LOGI(TAG, "tcp_client will start after 20s..."); vTaskDelay(20000 / portTICK_RATE_MS); ESP_LOGI(TAG, "create_tcp_client."); socket_ret = create_tcp_client(); #endif - if(ESP_FAIL == socket_ret) { + if(socket_ret == ESP_FAIL) { ESP_LOGI(TAG, "create tcp socket error,stop."); vTaskDelete(NULL); } /*create a task to tx/rx data*/ TaskHandle_t tx_rx_task; -#if ESP_TCP_PERF_TX +#if EXAMPLE_ESP_TCP_PERF_TX xTaskCreate(&send_data, "send_data", 4096, NULL, 4, &tx_rx_task); -#else /*ESP_TCP_PERF_TX*/ +#else /*EXAMPLE_ESP_TCP_PERF_TX*/ xTaskCreate(&recv_data, "recv_data", 4096, NULL, 4, &tx_rx_task); #endif - int pps; + int bps; while (1) { total_data = 0; vTaskDelay(3000 / portTICK_RATE_MS);//every 3s - pps = total_data / 3; + bps = total_data / 3; if (total_data <= 0) { - int err_ret = check_socket_error_code(); - if (err_ret == ECONNRESET) { - ESP_LOGI(TAG, "disconnected... stop."); + int err_ret = check_working_socket(); + if (err_ret == ECONNRESET || ECONNABORTED) { + ESP_LOGW(TAG, "tcp disconnected... stop.\n"); break; } } -#if ESP_TCP_PERF_TX - ESP_LOGI(TAG, "tcp send %d byte per sec!", pps); -#if ESP_TCP_DELAY_INFO +#if EXAMPLE_ESP_TCP_PERF_TX + ESP_LOGI(TAG, "tcp send %d byte per sec!", bps); +#if EXAMPLE_ESP_TCP_DELAY_INFO ESP_LOGI(TAG, "tcp send packet total:%d succeed:%d failed:%d\n" "time(ms):0-30:%d 30-100:%d 100-300:%d 300-1000:%d 1000+:%d\n", total_pack, send_success, send_fail, delay_classify[0], delay_classify[1], delay_classify[2], delay_classify[3], delay_classify[4]); -#endif /*ESP_TCP_DELAY_INFO*/ +#endif /*EXAMPLE_ESP_TCP_DELAY_INFO*/ #else - ESP_LOGI(TAG, "tcp recv %d byte per sec!\n", pps); -#endif /*ESP_TCP_PERF_TX*/ + ESP_LOGI(TAG, "tcp recv %d byte per sec!\n", bps); +#endif /*EXAMPLE_ESP_TCP_PERF_TX*/ } close_socket(); vTaskDelete(tx_rx_task); @@ -99,12 +107,12 @@ static void tcp_conn(void *pvParameters) void app_main(void) { -#if ESP_WIFI_MODE_AP - ESP_LOGI(TAG, "ESP_WIFI_MODE_AP\n"); +#if EXAMPLE_ESP_WIFI_MODE_AP + ESP_LOGI(TAG, "EXAMPLE_ESP_WIFI_MODE_AP"); wifi_init_softap(); -#else /*ESP_WIFI_MODE_AP*/ - ESP_LOGI(TAG, "ESP_WIFI_MODE_STA\n"); +#else + ESP_LOGI(TAG, "ESP_WIFI_MODE_STA"); wifi_init_sta(); -#endif +#endif /*EXAMPLE_ESP_WIFI_MODE_AP*/ xTaskCreate(&tcp_conn, "tcp_conn", 4096, NULL, 5, NULL); } diff --git a/examples/performance/tcp_perf/main/tcp_perf.c b/examples/performance/tcp_perf/main/tcp_perf.c index 0b8447ee9..d0c817147 100644 --- a/examples/performance/tcp_perf/main/tcp_perf.c +++ b/examples/performance/tcp_perf/main/tcp_perf.c @@ -1,21 +1,17 @@ -// Copyright 2013-2016 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. +/* tcp_perf Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ #include #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" +#include "freertos/event_groups.h" #include "esp_wifi.h" #include "esp_event_loop.h" #include "esp_log.h" @@ -23,6 +19,10 @@ #include "tcp_perf.h" + +/* FreeRTOS event group to signal when we are connected to wifi */ +EventGroupHandle_t tcp_event_group; + /*socket*/ static int server_socket = 0; static struct sockaddr_in server_addr; @@ -30,17 +30,18 @@ static struct sockaddr_in client_addr; static unsigned int socklen = sizeof(client_addr); static int connect_socket = 0; -int connectedflag = 0; int total_data = 0; -#if ESP_TCP_PERF_TX && ESP_TCP_DELAY_INFO +#if EXAMPLE_ESP_TCP_PERF_TX && EXAMPLE_ESP_TCP_DELAY_INFO int total_pack = 0; int send_success = 0; int send_fail = 0; int delay_classify[5] = { 0 }; -#endif /*ESP_TCP_PERF_TX && ESP_TCP_DELAY_INFO*/ +#endif /*EXAMPLE_ESP_TCP_PERF_TX && EXAMPLE_ESP_TCP_DELAY_INFO*/ + + static esp_err_t event_handler(void *ctx, system_event_t *event) @@ -51,26 +52,26 @@ static esp_err_t event_handler(void *ctx, system_event_t *event) break; case SYSTEM_EVENT_STA_DISCONNECTED: esp_wifi_connect(); + xEventGroupClearBits(tcp_event_group, WIFI_CONNECTED_BIT); break; case SYSTEM_EVENT_STA_CONNECTED: break; case SYSTEM_EVENT_STA_GOT_IP: - ESP_LOGI(TAG, "event_handler:SYSTEM_EVENT_STA_GOT_IP!"); ESP_LOGI(TAG, "got ip:%s\n", ip4addr_ntoa(&event->event_info.got_ip.ip_info.ip)); - connectedflag = 1; + xEventGroupSetBits(tcp_event_group, WIFI_CONNECTED_BIT); break; case SYSTEM_EVENT_AP_STACONNECTED: ESP_LOGI(TAG, "station:"MACSTR" join,AID=%d\n", MAC2STR(event->event_info.sta_connected.mac), event->event_info.sta_connected.aid); - connectedflag = 1; + xEventGroupSetBits(tcp_event_group, WIFI_CONNECTED_BIT); break; case SYSTEM_EVENT_AP_STADISCONNECTED: ESP_LOGI(TAG, "station:"MACSTR"leave,AID=%d\n", MAC2STR(event->event_info.sta_disconnected.mac), event->event_info.sta_disconnected.aid); - connectedflag = 0; + xEventGroupClearBits(tcp_event_group, WIFI_CONNECTED_BIT); break; default: break; @@ -82,33 +83,33 @@ static esp_err_t event_handler(void *ctx, system_event_t *event) void send_data(void *pvParameters) { int len = 0; - char databuff[DEFAULT_PKTSIZE]; - memset(databuff, PACK_BYTE_IS, DEFAULT_PKTSIZE); + char databuff[EXAMPLE_DEFAULT_PKTSIZE]; + memset(databuff, EXAMPLE_PACK_BYTE_IS, EXAMPLE_DEFAULT_PKTSIZE); vTaskDelay(100/portTICK_RATE_MS); ESP_LOGI(TAG, "start sending..."); -#if ESP_TCP_PERF_TX && ESP_TCP_DELAY_INFO +#if EXAMPLE_ESP_TCP_PERF_TX && EXAMPLE_ESP_TCP_DELAY_INFO //delaytime struct timeval tv_start; struct timeval tv_finish; unsigned long send_delay_ms; -#endif /*ESP_TCP_PERF_TX && ESP_TCP_DELAY_INFO*/ +#endif /*EXAMPLE_ESP_TCP_PERF_TX && EXAMPLE_ESP_TCP_DELAY_INFO*/ while(1) { -#if ESP_TCP_PERF_TX && ESP_TCP_DELAY_INFO +#if EXAMPLE_ESP_TCP_PERF_TX && EXAMPLE_ESP_TCP_DELAY_INFO total_pack++; gettimeofday(&tv_start, NULL); -#endif /*ESP_TCP_PERF_TX && ESP_TCP_DELAY_INFO*/ +#endif /*EXAMPLE_ESP_TCP_PERF_TX && EXAMPLE_ESP_TCP_DELAY_INFO*/ //send function - len = send(connect_socket, databuff, DEFAULT_PKTSIZE, 0); + len = send(connect_socket, databuff, EXAMPLE_DEFAULT_PKTSIZE, 0); -#if ESP_TCP_PERF_TX && ESP_TCP_DELAY_INFO +#if EXAMPLE_ESP_TCP_PERF_TX && EXAMPLE_ESP_TCP_DELAY_INFO gettimeofday(&tv_finish, NULL); -#endif /*ESP_TCP_PERF_TX && ESP_TCP_DELAY_INFO*/ +#endif /*EXAMPLE_ESP_TCP_PERF_TX && EXAMPLE_ESP_TCP_DELAY_INFO*/ if(len > 0) { total_data += len; -#if ESP_TCP_PERF_TX && ESP_TCP_DELAY_INFO +#if EXAMPLE_ESP_TCP_PERF_TX && EXAMPLE_ESP_TCP_DELAY_INFO send_success++; send_delay_ms = (tv_finish.tv_sec - tv_start.tv_sec) * 1000 + (tv_finish.tv_usec - tv_start.tv_usec) / 1000; @@ -122,37 +123,34 @@ void send_data(void *pvParameters) delay_classify[3]++; else delay_classify[4]++; -#endif /*ESP_TCP_PERF_TX && ESP_TCP_DELAY_INFO*/ +#endif /*EXAMPLE_ESP_TCP_PERF_TX && EXAMPLE_ESP_TCP_DELAY_INFO*/ - }/*if(len > 0)*/ - else { + } else { -#if ESP_TCP_PERF_TX && ESP_TCP_DELAY_INFO +#if EXAMPLE_ESP_TCP_PERF_TX && EXAMPLE_ESP_TCP_DELAY_INFO send_fail++; -#endif /*ESP_TCP_PERF_TX && ESP_TCP_DELAY_INFO*/ - - /*Most of the error code will be send window full. - *So, for faster sending,don't show error code. - *if it can't work as expectations,unnote the two lines here. - **/ - //show_socket_error_code(connect_socket); - //vTaskDelay(500/portTICK_RATE_MS); - } +#endif /*EXAMPLE_ESP_TCP_PERF_TX && EXAMPLE_ESP_TCP_DELAY_INFO*/ + + if (LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG) { + show_socket_error_reason(connect_socket); + } + } /*if(len > 0)*/ } } //receive data void recv_data(void *pvParameters) { int len = 0; - char databuff[DEFAULT_PKTSIZE]; + char databuff[EXAMPLE_DEFAULT_PKTSIZE]; while (1) { - len = recv(connect_socket, databuff, DEFAULT_PKTSIZE, 0); + len = recv(connect_socket, databuff, EXAMPLE_DEFAULT_PKTSIZE, 0); if (len > 0) { total_data += len; - } - else { - show_socket_error_code(connect_socket); - vTaskDelay(500 / portTICK_RATE_MS); + } else { + if (LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG) { + show_socket_error_reason(connect_socket); + } + vTaskDelay(100 / portTICK_RATE_MS); } } } @@ -161,28 +159,28 @@ void recv_data(void *pvParameters) //use this esp32 as a tcp server. return ESP_OK:success ESP_FAIL:error esp_err_t create_tcp_server() { - ESP_LOGI(TAG, "server socket....port=%d\n", DEFAULT_PORT); + ESP_LOGI(TAG, "server socket....port=%d\n", EXAMPLE_DEFAULT_PORT); server_socket = socket(AF_INET, SOCK_STREAM, 0); if (server_socket < 0) { - show_socket_error_code(server_socket); + show_socket_error_reason(server_socket); return ESP_FAIL; } server_addr.sin_family = AF_INET; - server_addr.sin_port = htons(DEFAULT_PORT); + server_addr.sin_port = htons(EXAMPLE_DEFAULT_PORT); server_addr.sin_addr.s_addr = htonl(INADDR_ANY); if (bind(server_socket, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) { - show_socket_error_code(server_socket); + show_socket_error_reason(server_socket); close(server_socket); return ESP_FAIL; } if (listen(server_socket, 5) < 0) { - show_socket_error_code(server_socket); + show_socket_error_reason(server_socket); close(server_socket); return ESP_FAIL; } connect_socket = accept(server_socket, (struct sockaddr*)&client_addr, &socklen); if (connect_socket<0) { - show_socket_error_code(connect_socket); + show_socket_error_reason(connect_socket); close(server_socket); return ESP_FAIL; } @@ -194,18 +192,18 @@ esp_err_t create_tcp_server() esp_err_t create_tcp_client() { ESP_LOGI(TAG, "client socket....serverip:port=%s:%d\n", - DEFAULT_SERVER_IP, DEFAULT_PORT); + EXAMPLE_DEFAULT_SERVER_IP, EXAMPLE_DEFAULT_PORT); connect_socket = socket(AF_INET, SOCK_STREAM, 0); if (connect_socket < 0) { - show_socket_error_code(connect_socket); + show_socket_error_reason(connect_socket); return ESP_FAIL; } server_addr.sin_family = AF_INET; - server_addr.sin_port = htons(DEFAULT_PORT); - server_addr.sin_addr.s_addr = inet_addr(DEFAULT_SERVER_IP); + server_addr.sin_port = htons(EXAMPLE_DEFAULT_PORT); + server_addr.sin_addr.s_addr = inet_addr(EXAMPLE_DEFAULT_SERVER_IP); ESP_LOGI(TAG, "connecting to server..."); if (connect(connect_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { - show_socket_error_code(connect_socket); + show_socket_error_reason(connect_socket); return ESP_FAIL; } ESP_LOGI(TAG, "connect to server success!"); @@ -215,6 +213,8 @@ esp_err_t create_tcp_client() //wifi_init_sta void wifi_init_sta() { + tcp_event_group = xEventGroupCreate(); + tcpip_adapter_init(); ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL) ); @@ -222,8 +222,8 @@ void wifi_init_sta() ESP_ERROR_CHECK(esp_wifi_init(&cfg)); wifi_config_t wifi_config = { .sta = { - .ssid = DEFAULT_SSID, - .password = DEFAULT_PWD + .ssid = EXAMPLE_DEFAULT_SSID, + .password = EXAMPLE_DEFAULT_PWD }, }; @@ -233,11 +233,13 @@ void wifi_init_sta() ESP_LOGI(TAG, "wifi_init_sta finished."); ESP_LOGI(TAG, "connect to ap SSID:%s password:%s \n", - DEFAULT_SSID,DEFAULT_PWD); + EXAMPLE_DEFAULT_SSID,EXAMPLE_DEFAULT_PWD); } //wifi_init_softap void wifi_init_softap() { + tcp_event_group = xEventGroupCreate(); + tcpip_adapter_init(); ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL)); @@ -245,14 +247,14 @@ void wifi_init_softap() ESP_ERROR_CHECK(esp_wifi_init(&cfg)); wifi_config_t wifi_config = { .ap = { - .ssid = DEFAULT_SSID, + .ssid = EXAMPLE_DEFAULT_SSID, .ssid_len = 0, - .max_connection=MAX_STA_CONN, - .password = DEFAULT_PWD, + .max_connection=EXAMPLE_MAX_STA_CONN, + .password = EXAMPLE_DEFAULT_PWD, .authmode = WIFI_AUTH_WPA_WPA2_PSK }, }; - if (strlen(DEFAULT_PWD) ==0) { + if (strlen(EXAMPLE_DEFAULT_PWD) ==0) { wifi_config.ap.authmode = WIFI_AUTH_OPEN; } @@ -261,71 +263,48 @@ void wifi_init_softap() ESP_ERROR_CHECK(esp_wifi_start()); ESP_LOGI(TAG, "wifi_init_softap finished.SSID:%s password:%s \n", - DEFAULT_SSID, DEFAULT_PWD); + EXAMPLE_DEFAULT_SSID, EXAMPLE_DEFAULT_PWD); } -char* tcpip_get_reason(int err) -{ - switch (err) { - case 0: - return "reason: other reason"; - case ENOMEM: - return "reason: out of memory"; - case ENOBUFS: - return "reason: buffer error"; - case EWOULDBLOCK: - return "reason: timeout, try again"; - case EHOSTUNREACH: - return "reason: routing problem"; - case EINPROGRESS: - return "reason: operation in progress"; - case EINVAL: - return "reason: invalid value"; - case EADDRINUSE: - return "reason: address in use"; - case EALREADY: - return "reason: conn already connected"; - case EISCONN: - return "reason: conn already established"; - case ECONNABORTED: - return "reason: connection aborted"; - case ECONNRESET: - return "reason: connection is reset"; - case ENOTCONN: - return "reason: connection closed"; - case EIO: - return "reason: invalid argument"; - case -1: - return "reason: low level netif error"; - default: - return "reason not found"; - } -} - -int show_socket_error_code(int socket) +int get_socket_error_code(int socket) { int result; u32_t optlen = sizeof(int); - getsockopt(socket, SOL_SOCKET, SO_ERROR, &result, &optlen); - ESP_LOGI(TAG, "socket error %d reason: %s", result, tcpip_get_reason(result)); + if(getsockopt(socket, SOL_SOCKET, SO_ERROR, &result, &optlen) == -1) { + ESP_LOGE(TAG, "getsockopt failed"); + return -1; + } return result; } -int check_socket_error_code() +int show_socket_error_reason(int socket) +{ + int err = get_socket_error_code(socket); + ESP_LOGW(TAG, "socket error %d %s", err, strerror(err)); + return err; +} + +int check_working_socket() { int ret; -#if ESP_TCP_MODE_SERVER - ESP_LOGI(TAG, "check server_socket"); - ret = show_socket_error_code(server_socket); +#if EXAMPLE_ESP_TCP_MODE_SERVER + ESP_LOGD(TAG, "check server_socket"); + ret = get_socket_error_code(server_socket); + if(ret != 0) { + ESP_LOGW(TAG, "server socket error %d %s", ret, strerror(ret)); + } if(ret == ECONNRESET) return ret; #endif - ESP_LOGI(TAG, "check connect_socket"); - ret = show_socket_error_code(connect_socket); - if(ret == ECONNRESET) + ESP_LOGD(TAG, "check connect_socket"); + ret = get_socket_error_code(connect_socket); + if(ret != 0) { + ESP_LOGW(TAG, "connect socket error %d %s", ret, strerror(ret)); + } + if(ret != 0) return ret; return 0; } diff --git a/examples/performance/tcp_perf/main/tcp_perf.h b/examples/performance/tcp_perf/main/tcp_perf.h index e29215b5b..2280dc8f4 100644 --- a/examples/performance/tcp_perf/main/tcp_perf.h +++ b/examples/performance/tcp_perf/main/tcp_perf.h @@ -1,3 +1,13 @@ +/* tcp_perf Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + + #ifndef __TCP_PERF_H__ #define __TCP_PERF_H__ @@ -7,33 +17,43 @@ extern "C" { #endif -/*AP info and tcp_server info*/ -#define DEFAULT_SSID CONFIG_TCP_PERF_WIFI_SSID -#define DEFAULT_PWD CONFIG_TCP_PERF_WIFI_PASSWORD -#define DEFAULT_PORT CONFIG_TCP_PERF_SERVER_PORT -#define DEFAULT_SERVER_IP CONFIG_TCP_PERF_SERVER_IP -#define DEFAULT_PKTSIZE CONFIG_TCP_PERF_PKT_SIZE -#define MAX_STA_CONN 1 //how many sta can be connected(AP mode) + /*test options*/ -#define ESP_WIFI_MODE_AP CONFIG_TCP_PERF_WIFI_MODE_AP //TRUE:AP FALSE:STA -#define ESP_TCP_MODE_SERVER CONFIG_TCP_PERF_SERVER //TRUE:server FALSE:client -#define ESP_TCP_PERF_TX CONFIG_TCP_PERF_TX //TRUE:send FALSE:receive -#define ESP_TCP_DELAY_INFO CONFIG_TCP_PERF_DELAY_DEBUG //TRUE:show delay time info +#define EXAMPLE_ESP_WIFI_MODE_AP CONFIG_TCP_PERF_WIFI_MODE_AP //TRUE:AP FALSE:STA +#define EXAMPLE_ESP_TCP_MODE_SERVER CONFIG_TCP_PERF_SERVER //TRUE:server FALSE:client +#define EXAMPLE_ESP_TCP_PERF_TX CONFIG_TCP_PERF_TX //TRUE:send FALSE:receive +#define EXAMPLE_ESP_TCP_DELAY_INFO CONFIG_TCP_PERF_DELAY_DEBUG //TRUE:show delay time info + +/*AP info and tcp_server info*/ +#define EXAMPLE_DEFAULT_SSID CONFIG_TCP_PERF_WIFI_SSID +#define EXAMPLE_DEFAULT_PWD CONFIG_TCP_PERF_WIFI_PASSWORD +#define EXAMPLE_DEFAULT_PORT CONFIG_TCP_PERF_SERVER_PORT +#define EXAMPLE_DEFAULT_PKTSIZE CONFIG_TCP_PERF_PKT_SIZE +#define EXAMPLE_MAX_STA_CONN 1 //how many sta can be connected(AP mode) + +#ifdef CONFIG_TCP_PERF_SERVER_IP +#define EXAMPLE_DEFAULT_SERVER_IP CONFIG_TCP_PERF_SERVER_IP +#else +#define EXAMPLE_DEFAULT_SERVER_IP "192.168.4.1" +#endif /*CONFIG_TCP_PERF_SERVER_IP*/ -#define PACK_BYTE_IS 97 //'a' + +#define EXAMPLE_PACK_BYTE_IS 97 //'a' #define TAG "tcp_perf:" +/* FreeRTOS event group to signal when we are connected to wifi*/ +extern EventGroupHandle_t tcp_event_group; +#define WIFI_CONNECTED_BIT BIT0 -extern int connectedflag; extern int total_data; -#if ESP_TCP_PERF_TX && ESP_TCP_DELAY_INFO +#if EXAMPLE_ESP_TCP_PERF_TX && EXAMPLE_ESP_TCP_DELAY_INFO extern int total_pack; extern int send_success; extern int send_fail; extern int delay_classify[5]; -#endif/*ESP_TCP_PERF_TX && ESP_TCP_DELAY_INFO*/ +#endif/*EXAMPLE_ESP_TCP_PERF_TX && EXAMPLE_ESP_TCP_DELAY_INFO*/ //using esp as station @@ -54,11 +74,14 @@ void recv_data(void *pvParameters); //close all socket void close_socket(); +//get socket error code. return: error code +int get_socket_error_code(int socket); + //show socket error code. return: error code -int show_socket_error_code(int socket); +int show_socket_error_reason(int socket); //check working socket -int check_socket_error_code(); +int check_working_socket(); #ifdef __cplusplus diff --git a/examples/performance/udp_perf/main/Kconfig.projbuild b/examples/performance/udp_perf/main/Kconfig.projbuild index 72d40cb98..81ab39589 100644 --- a/examples/performance/udp_perf/main/Kconfig.projbuild +++ b/examples/performance/udp_perf/main/Kconfig.projbuild @@ -78,34 +78,35 @@ config UDP_PERF_TX config UDP_PERF_WIFI_SSID string "WiFi SSID" - default "esp_wifi_test1" - help - SSID (network name) for the example to connect to. + default "esp_wifi_test1" + help + SSID (network name) for the example to connect to. config UDP_PERF_WIFI_PASSWORD string "WiFi Password" - default "1234567890" - help - WiFi password (WPA or WPA2) for the example to use. + default "1234567890" + help + WiFi password (WPA or WPA2) for the example to use. config UDP_PERF_SERVER_PORT int "UDP server port" - default 4567 - help - Which will the udp server use. + default 4567 + help + Which will the udp server use. config UDP_PERF_SERVER_IP string "UDP server ip" - default "192.168.4.1" - help - IP of UDP server. + depends on UDP_PERF_ESP_IS_CLIENT + default "192.168.4.1" + help + IP of UDP server. - Ignore in UDP server. + Ignore in UDP server. config UDP_PERF_PKT_SIZE int "Size of UDP packet" - default 1460 - help - the data send&recv packet size. + default 1460 + help + the data send&recv packet size. endmenu diff --git a/examples/performance/udp_perf/main/udp_main.c b/examples/performance/udp_perf/main/udp_main.c index 60f59e9b3..d4d8b1fa9 100644 --- a/examples/performance/udp_perf/main/udp_main.c +++ b/examples/performance/udp_perf/main/udp_main.c @@ -1,3 +1,13 @@ +/* udp_perf Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + + /* @@ -20,8 +30,10 @@ step3: */ +#include #include "freertos/FreeRTOS.h" #include "freertos/task.h" +#include "freertos/event_groups.h" #include "esp_log.h" #include "esp_err.h" @@ -33,26 +45,24 @@ static void udp_conn(void *pvParameters) { ESP_LOGI(TAG, "task udp_conn start."); /*wating for connecting to AP*/ - do - { - vTaskDelay(100); - } - while (!connectedflag); + xEventGroupWaitBits(udp_event_group, WIFI_CONNECTED_BIT,false, true, portMAX_DELAY); ESP_LOGI(TAG, "sta has connected to ap."); /*create udp socket*/ int socket_ret; -#if ESP_UDP_MODE_SERVER +#if EXAMPLE_ESP_UDP_MODE_SERVER + ESP_LOGI(TAG, "create udp server after 3s..."); vTaskDelay(3000 / portTICK_RATE_MS); ESP_LOGI(TAG, "create_udp_server."); socket_ret=create_udp_server(); -#else /*ESP_UDP_MODE_SERVER*/ +#else /*EXAMPLE_ESP_UDP_MODE_SERVER*/ + ESP_LOGI(TAG, "create udp client after 20s..."); vTaskDelay(20000 / portTICK_RATE_MS); ESP_LOGI(TAG, "create_udp_client."); socket_ret = create_udp_client(); #endif - if(ESP_FAIL == socket_ret) { + if(socket_ret == ESP_FAIL) { ESP_LOGI(TAG, "create udp socket error,stop."); vTaskDelete(NULL); } @@ -61,17 +71,27 @@ static void udp_conn(void *pvParameters) TaskHandle_t tx_rx_task; xTaskCreate(&send_recv_data, "send_recv_data", 4096, NULL, 4, &tx_rx_task); - int pps; + /*waiting udp connected success*/ + xEventGroupWaitBits(udp_event_group, UDP_CONNCETED_SUCCESS,false, true, portMAX_DELAY); + int bps; while (1) { total_data = 0; vTaskDelay(3000 / portTICK_RATE_MS);//every 3s - pps = total_data / 3; + bps = total_data / 3; -#if ESP_UDP_PERF_TX - ESP_LOGI(TAG, "udp send %d byte per sec! total pack: %d \n", pps, success_pack); + if (total_data <= 0) { + int err_ret = check_connected_socket(); + if (err_ret == -1) { //-1 reason: low level netif error + ESP_LOGW(TAG, "udp send & recv stop.\n"); + break; + } + } + +#if EXAMPLE_ESP_UDP_PERF_TX + ESP_LOGI(TAG, "udp send %d byte per sec! total pack: %d \n", bps, success_pack); #else - ESP_LOGI(TAG, "udp recv %d byte per sec! total pack: %d \n", pps, success_pack); -#endif /*ESP_UDP_PERF_TX*/ + ESP_LOGI(TAG, "udp recv %d byte per sec! total pack: %d \n", bps, success_pack); +#endif /*EXAMPLE_ESP_UDP_PERF_TX*/ } close_socket(); vTaskDelete(tx_rx_task); @@ -82,11 +102,11 @@ static void udp_conn(void *pvParameters) void app_main(void) { -#if ESP_WIFI_MODE_AP - ESP_LOGI(TAG, "ESP_WIFI_MODE_AP\n"); +#if EXAMPLE_ESP_WIFI_MODE_AP + ESP_LOGI(TAG, "EXAMPLE_ESP_WIFI_MODE_AP"); wifi_init_softap(); -#else /*ESP_WIFI_MODE_AP*/ - ESP_LOGI(TAG, "ESP_WIFI_MODE_STA\n"); +#else /*EXAMPLE_ESP_WIFI_MODE_AP*/ + ESP_LOGI(TAG, "ESP_WIFI_MODE_STA"); wifi_init_sta(); #endif xTaskCreate(&udp_conn, "udp_conn", 4096, NULL, 5, NULL); diff --git a/examples/performance/udp_perf/main/udp_perf.c b/examples/performance/udp_perf/main/udp_perf.c index 22a55ad90..694494624 100644 --- a/examples/performance/udp_perf/main/udp_perf.c +++ b/examples/performance/udp_perf/main/udp_perf.c @@ -1,21 +1,17 @@ -// Copyright 2013-2016 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. +/* udp_perf Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ #include #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" +#include "freertos/event_groups.h" #include "esp_wifi.h" #include "esp_event_loop.h" #include "esp_log.h" @@ -24,13 +20,15 @@ #include "udp_perf.h" +/* FreeRTOS event group to signal when we are connected to WiFi and ready to start UDP test*/ +EventGroupHandle_t udp_event_group; + static int mysocket; static struct sockaddr_in remote_addr; static unsigned int socklen; -int connectedflag = 0; int total_data = 0; int success_pack = 0; @@ -43,6 +41,7 @@ static esp_err_t event_handler(void *ctx, system_event_t *event) break; case SYSTEM_EVENT_STA_DISCONNECTED: esp_wifi_connect(); + xEventGroupClearBits(udp_event_group, WIFI_CONNECTED_BIT); break; case SYSTEM_EVENT_STA_CONNECTED: break; @@ -50,18 +49,19 @@ static esp_err_t event_handler(void *ctx, system_event_t *event) ESP_LOGI(TAG, "event_handler:SYSTEM_EVENT_STA_GOT_IP!"); ESP_LOGI(TAG, "got ip:%s\n", ip4addr_ntoa(&event->event_info.got_ip.ip_info.ip)); - connectedflag=1; + xEventGroupSetBits(udp_event_group, WIFI_CONNECTED_BIT); break; case SYSTEM_EVENT_AP_STACONNECTED: ESP_LOGI(TAG, "station:"MACSTR" join,AID=%d\n", MAC2STR(event->event_info.sta_connected.mac), event->event_info.sta_connected.aid); - connectedflag=1; + xEventGroupSetBits(udp_event_group, WIFI_CONNECTED_BIT); break; case SYSTEM_EVENT_AP_STADISCONNECTED: ESP_LOGI(TAG, "station:"MACSTR"leave,AID=%d\n", MAC2STR(event->event_info.sta_disconnected.mac), event->event_info.sta_disconnected.aid); + xEventGroupClearBits(udp_event_group, WIFI_CONNECTED_BIT); break; default: break; @@ -73,6 +73,8 @@ static esp_err_t event_handler(void *ctx, system_event_t *event) //wifi_init_sta void wifi_init_sta() { + udp_event_group = xEventGroupCreate(); + tcpip_adapter_init(); ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL) ); @@ -80,8 +82,8 @@ void wifi_init_sta() ESP_ERROR_CHECK(esp_wifi_init(&cfg)); wifi_config_t wifi_config = { .sta = { - .ssid = DEFAULT_SSID, - .password = DEFAULT_PWD + .ssid = EXAMPLE_DEFAULT_SSID, + .password = EXAMPLE_DEFAULT_PWD }, }; @@ -91,11 +93,13 @@ void wifi_init_sta() ESP_LOGI(TAG, "wifi_init_sta finished."); ESP_LOGI(TAG, "connect to ap SSID:%s password:%s \n", - DEFAULT_SSID,DEFAULT_PWD); + EXAMPLE_DEFAULT_SSID,EXAMPLE_DEFAULT_PWD); } //wifi_init_softap void wifi_init_softap() { + udp_event_group = xEventGroupCreate(); + tcpip_adapter_init(); ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL)); @@ -103,14 +107,14 @@ void wifi_init_softap() ESP_ERROR_CHECK(esp_wifi_init(&cfg)); wifi_config_t wifi_config = { .ap = { - .ssid = DEFAULT_SSID, + .ssid = EXAMPLE_DEFAULT_SSID, .ssid_len=0, - .max_connection=MAX_STA_CONN, - .password = DEFAULT_PWD, + .max_connection=EXAMPLE_MAX_STA_CONN, + .password = EXAMPLE_DEFAULT_PWD, .authmode=WIFI_AUTH_WPA_WPA2_PSK }, }; - if (strlen(DEFAULT_PWD) ==0) { + if (strlen(EXAMPLE_DEFAULT_PWD) ==0) { wifi_config.ap.authmode = WIFI_AUTH_OPEN; } @@ -119,24 +123,24 @@ void wifi_init_softap() ESP_ERROR_CHECK(esp_wifi_start()); ESP_LOGI(TAG, "wifi_init_softap finished.SSID:%s password:%s \n", - DEFAULT_SSID, DEFAULT_PWD); + EXAMPLE_DEFAULT_SSID, EXAMPLE_DEFAULT_PWD); } //create a udp server socket. return ESP_OK:success ESP_FAIL:error esp_err_t create_udp_server() { - ESP_LOGI(TAG, "create_udp_server()"); + ESP_LOGI(TAG, "create_udp_server() port:%d", EXAMPLE_DEFAULT_PORT); mysocket = socket(AF_INET, SOCK_DGRAM, 0); if (mysocket < 0) { - show_socket_error_code(mysocket); + show_socket_error_reason(mysocket); return ESP_FAIL; } struct sockaddr_in server_addr; server_addr.sin_family = AF_INET; - server_addr.sin_port = htons(DEFAULT_PORT); + server_addr.sin_port = htons(EXAMPLE_DEFAULT_PORT); server_addr.sin_addr.s_addr = htonl(INADDR_ANY); if (bind(mysocket, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { - show_socket_error_code(mysocket); + show_socket_error_reason(mysocket); close(mysocket); return ESP_FAIL; } @@ -147,15 +151,17 @@ esp_err_t create_udp_server() esp_err_t create_udp_client() { ESP_LOGI(TAG, "create_udp_client()"); + ESP_LOGI(TAG, "connecting to %s:%d", + EXAMPLE_DEFAULT_SERVER_IP, EXAMPLE_DEFAULT_PORT); mysocket = socket(AF_INET, SOCK_DGRAM, 0); if (mysocket < 0) { - show_socket_error_code(mysocket); + show_socket_error_reason(mysocket); return ESP_FAIL; } /*for client remote_addr is also server_addr*/ remote_addr.sin_family = AF_INET; - remote_addr.sin_port = htons(DEFAULT_PORT); - remote_addr.sin_addr.s_addr = inet_addr(DEFAULT_SERVER_IP); + remote_addr.sin_port = htons(EXAMPLE_DEFAULT_PORT); + remote_addr.sin_addr.s_addr = inet_addr(EXAMPLE_DEFAULT_SERVER_IP); return ESP_OK; } @@ -167,102 +173,79 @@ void send_recv_data(void *pvParameters) ESP_LOGI(TAG, "task send_recv_data start!\n"); int len; - char databuff[DEFAULT_PKTSIZE]; + char databuff[EXAMPLE_DEFAULT_PKTSIZE]; /*send&receive first packet*/ socklen = sizeof(remote_addr); - memset(databuff, PACK_BYTE_IS, DEFAULT_PKTSIZE); -#if ESP_UDP_MODE_SERVER + memset(databuff, EXAMPLE_PACK_BYTE_IS, EXAMPLE_DEFAULT_PKTSIZE); +#if EXAMPLE_ESP_UDP_MODE_SERVER ESP_LOGI(TAG, "first recvfrom:"); - len = recvfrom(mysocket, databuff, DEFAULT_PKTSIZE, 0, (struct sockaddr *)&remote_addr, &socklen); + len = recvfrom(mysocket, databuff, EXAMPLE_DEFAULT_PKTSIZE, 0, (struct sockaddr *)&remote_addr, &socklen); #else ESP_LOGI(TAG, "first sendto:"); - len = sendto(mysocket, databuff, DEFAULT_PKTSIZE, 0, (struct sockaddr *)&remote_addr, sizeof(remote_addr)); + len = sendto(mysocket, databuff, EXAMPLE_DEFAULT_PKTSIZE, 0, (struct sockaddr *)&remote_addr, sizeof(remote_addr)); #endif if (len > 0) { ESP_LOGI(TAG, "transfer data with %s:%u\n", inet_ntoa(remote_addr.sin_addr), ntohs(remote_addr.sin_port)); + xEventGroupSetBits(udp_event_group, UDP_CONNCETED_SUCCESS); } else { - show_socket_error_code(mysocket); + show_socket_error_reason(mysocket); close(mysocket); vTaskDelete(NULL); - } + } /*if (len > 0)*/ -#if ESP_UDP_PERF_TX +#if EXAMPLE_ESP_UDP_PERF_TX vTaskDelay(500 / portTICK_RATE_MS); #endif ESP_LOGI(TAG, "start count!\n"); - while(1) - { - /*you can add delay time for fixed-frequency*/ - //vTaskDelay(5 / portTICK_RATE_MS); -#if ESP_UDP_PERF_TX - len = sendto(mysocket, databuff, DEFAULT_PKTSIZE, 0, (struct sockaddr *)&remote_addr, sizeof(remote_addr)); + while(1) { +#if EXAMPLE_ESP_UDP_PERF_TX + len = sendto(mysocket, databuff, EXAMPLE_DEFAULT_PKTSIZE, 0, (struct sockaddr *)&remote_addr, sizeof(remote_addr)); #else - len = recvfrom(mysocket, databuff, DEFAULT_PKTSIZE, 0, (struct sockaddr *)&remote_addr, &socklen); + len = recvfrom(mysocket, databuff, EXAMPLE_DEFAULT_PKTSIZE, 0, (struct sockaddr *)&remote_addr, &socklen); #endif if (len > 0) { total_data += len; success_pack++; } else { - //show_socket_error_code(mysocket); - /*you'd better turn off watch dog in menuconfig - *Component config->ESP32-specific->Task watchdog. - **/ - //vTaskDelay(1/portTICK_RATE_MS); - } - } + if (LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG) { + show_socket_error_reason(mysocket); + } + } /*if (len > 0)*/ + } /*while(1)*/ } -char* tcpip_get_reason(int err) -{ - switch (err) { - case 0: - return "reason: other reason"; - case ENOMEM: - return "reason: out of memory"; - case ENOBUFS: - return "reason: buffer error"; - case EWOULDBLOCK: - return "reason: timeout, try again"; - case EHOSTUNREACH: - return "reason: routing problem"; - case EINPROGRESS: - return "reason: operation in progress"; - case EINVAL: - return "reason: invalid value"; - case EADDRINUSE: - return "reason: address in use"; - case EALREADY: - return "reason: conn already connected"; - case EISCONN: - return "reason: conn already established"; - case ECONNABORTED: - return "reason: connection aborted"; - case ECONNRESET: - return "reason: connection is reset"; - case ENOTCONN: - return "reason: connection closed"; - case EIO: - return "reason: invalid argument"; - case -1: - return "reason: low level netif error"; - default: - return "reason not found"; - } -} - -int show_socket_error_code(int socket) +int get_socket_error_code(int socket) { int result; u32_t optlen = sizeof(int); - getsockopt(socket, SOL_SOCKET, SO_ERROR, &result, &optlen); - ESP_LOGI(TAG, "socket error %d reason: %s", result, tcpip_get_reason(result)); + if(getsockopt(socket, SOL_SOCKET, SO_ERROR, &result, &optlen) == -1) { + ESP_LOGE(TAG, "getsockopt failed"); + return -1; + } return result; } +int show_socket_error_reason(int socket) +{ + int err = get_socket_error_code(socket); + ESP_LOGW(TAG, "socket error %d %s", err, strerror(err)); + return err; +} + +int check_connected_socket() +{ + int ret; + ESP_LOGD(TAG, "check connect_socket"); + ret = get_socket_error_code(mysocket); + if(ret != 0) { + ESP_LOGW(TAG, "socket error %d %s", ret, strerror(ret)); + } + return ret; +} void close_socket() { diff --git a/examples/performance/udp_perf/main/udp_perf.h b/examples/performance/udp_perf/main/udp_perf.h index 0f8221559..11c1c512d 100644 --- a/examples/performance/udp_perf/main/udp_perf.h +++ b/examples/performance/udp_perf/main/udp_perf.h @@ -1,3 +1,13 @@ +/* udp_perf Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + + #ifndef __UDP_PERF_H__ #define __UDP_PERF_H__ @@ -7,23 +17,33 @@ extern "C" { #endif -/*AP info and tcp_server info*/ -#define DEFAULT_SSID CONFIG_UDP_PERF_WIFI_SSID -#define DEFAULT_PWD CONFIG_UDP_PERF_WIFI_PASSWORD -#define DEFAULT_PORT CONFIG_UDP_PERF_SERVER_PORT -#define DEFAULT_SERVER_IP CONFIG_UDP_PERF_SERVER_IP -#define DEFAULT_PKTSIZE CONFIG_UDP_PERF_PKT_SIZE -#define MAX_STA_CONN 1 //how many sta can be connected(AP mode) + /*test options*/ -#define ESP_WIFI_MODE_AP CONFIG_UDP_PERF_WIFI_MODE_AP //TRUE:AP FALSE:STA -#define ESP_UDP_MODE_SERVER CONFIG_UDP_PERF_SERVER //TRUE:server FALSE:client -#define ESP_UDP_PERF_TX CONFIG_UDP_PERF_TX //TRUE:send FALSE:receive -#define PACK_BYTE_IS 97 //'a' +#define EXAMPLE_ESP_WIFI_MODE_AP CONFIG_UDP_PERF_WIFI_MODE_AP //TRUE:AP FALSE:STA +#define EXAMPLE_ESP_UDP_MODE_SERVER CONFIG_UDP_PERF_SERVER //TRUE:server FALSE:client +#define EXAMPLE_ESP_UDP_PERF_TX CONFIG_UDP_PERF_TX //TRUE:send FALSE:receive +#define EXAMPLE_PACK_BYTE_IS 97 //'a' +/*AP info and tcp_server info*/ +#define EXAMPLE_DEFAULT_SSID CONFIG_UDP_PERF_WIFI_SSID +#define EXAMPLE_DEFAULT_PWD CONFIG_UDP_PERF_WIFI_PASSWORD +#define EXAMPLE_DEFAULT_PORT CONFIG_UDP_PERF_SERVER_PORT +#define EXAMPLE_DEFAULT_PKTSIZE CONFIG_UDP_PERF_PKT_SIZE +#define EXAMPLE_MAX_STA_CONN 1 //how many sta can be connected(AP mode) + +#ifdef CONFIG_UDP_PERF_SERVER_IP +#define EXAMPLE_DEFAULT_SERVER_IP CONFIG_UDP_PERF_SERVER_IP +#else +#define EXAMPLE_DEFAULT_SERVER_IP "192.168.4.1" +#endif /*CONFIG_UDP_PERF_SERVER_IP*/ + #define TAG "udp_perf:" +/* FreeRTOS event group to signal when we are connected to WiFi and ready to start UDP test*/ +extern EventGroupHandle_t udp_event_group; +#define WIFI_CONNECTED_BIT BIT0 +#define UDP_CONNCETED_SUCCESS BIT1 -extern int connectedflag; extern int total_data; extern int success_pack; @@ -41,8 +61,14 @@ esp_err_t create_udp_client(); //send or recv data task void send_recv_data(void *pvParameters); +//get socket error code. return: error code +int get_socket_error_code(int socket); + //show socket error code. return: error code -int show_socket_error_code(int socket); +int show_socket_error_reason(int socket); + +//check connected socket. return: error code +int check_connected_socket(); //close all socket void close_socket(); diff --git a/examples/protocols/pppos_client/Makefile b/examples/protocols/pppos_client/Makefile new file mode 100644 index 000000000..25571d087 --- /dev/null +++ b/examples/protocols/pppos_client/Makefile @@ -0,0 +1,9 @@ +# +# This is a project Makefile. It is assumed the directory this Makefile resides in is a +# project subdirectory. +# + +PROJECT_NAME := pppos_client + +include $(IDF_PATH)/make/project.mk + diff --git a/examples/protocols/pppos_client/README.md b/examples/protocols/pppos_client/README.md new file mode 100644 index 000000000..f9e0ce690 --- /dev/null +++ b/examples/protocols/pppos_client/README.md @@ -0,0 +1,9 @@ +#PPP over Serial (PPPoS) client example + +It shows example of ppp client using lwip PPPoS api and GSM. +Before you run this example, make sure your GSM is in command mode +and is registered to network. + +PPP over serial support is experimental and unsupported. This example was tested with GSM Telit GL865-DUAL V3. + +See the README.md file in the upper level 'examples' directory for more information about examples. diff --git a/examples/protocols/pppos_client/main/Kconfig.projbuild b/examples/protocols/pppos_client/main/Kconfig.projbuild new file mode 100644 index 000000000..af3153fa0 --- /dev/null +++ b/examples/protocols/pppos_client/main/Kconfig.projbuild @@ -0,0 +1,49 @@ +menu "Example Configuration" + +config GSM_INTERNET_USER + string "GSM Internet User" + default "" + help + Network provider internet user. + +config GSM_INTERNET_PASSWORD + string "GSM Internet password" + default "" + help + Network provider internet password + +config GSM_APN + string "GSM Internet APN" + default "playmetric" + help + APN from network provider for internet access + +config UART1_TX_PIN + int "PPP serial TX GPIO" + default 17 + range 0 31 + help + Pin to configure for UART1 TX + +config UART1_RX_PIN + int "PPP serial RX GPIO" + default 16 + range 0 31 + help + Pin to configure for UART1 RX + +config UART1_RTS_PIN + int "PPP serial RTS GPIO" + default 18 + range 0 31 + help + Pin to configure for UART1 RTS + +config UART1_CTS_PIN + int "PPP serial CTS GPIO" + default 23 + range 0 31 + help + Pin to configure for UART1 CTS + +endmenu diff --git a/examples/protocols/pppos_client/main/component.mk b/examples/protocols/pppos_client/main/component.mk new file mode 100644 index 000000000..a98f634ea --- /dev/null +++ b/examples/protocols/pppos_client/main/component.mk @@ -0,0 +1,4 @@ +# +# "main" pseudo-component makefile. +# +# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) diff --git a/examples/protocols/pppos_client/main/pppos_client_main.c b/examples/protocols/pppos_client/main/pppos_client_main.c new file mode 100644 index 000000000..432bd6bc0 --- /dev/null +++ b/examples/protocols/pppos_client/main/pppos_client_main.c @@ -0,0 +1,296 @@ +/* PPPoS Client Example with GSM (tested with Telit GL865-DUAL-V3) + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. + */ +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/event_groups.h" +#include "esp_system.h" +#include "esp_wifi.h" +#include "esp_event_loop.h" +#include "esp_log.h" +#include "nvs_flash.h" + +#include "driver/uart.h" + +#include "netif/ppp/pppos.h" +#include "lwip/err.h" +#include "lwip/sockets.h" +#include "lwip/sys.h" +#include "lwip/netdb.h" +#include "lwip/dns.h" +#include "lwip/pppapi.h" + +/* The examples use simple GSM configuration that you can set via + 'make menuconfig'. + */ +#define BUF_SIZE (1024) +const char *PPP_User = CONFIG_GSM_INTERNET_USER; +const char *PPP_Pass = CONFIG_GSM_INTERNET_PASSWORD; +const char *PPP_ApnATReq = "AT+CGDCONT=1,\"IP\",\"" \ + CONFIG_GSM_APN \ + "\""; + +/* Pins used for serial communication with GSM module */ +#define UART1_TX_PIN CONFIG_UART1_TX_PIN +#define UART1_RX_PIN CONFIG_UART1_RX_PIN +#define UART1_RTS_PIN CONFIG_UART1_RTS_PIN +#define UART1_CTS_PIN CONFIG_UART1_CTS_PIN + +/* UART */ +int uart_num = UART_NUM_1; + +/* The PPP control block */ +ppp_pcb *ppp; + +/* The PPP IP interface */ +struct netif ppp_netif; + +static const char *TAG = "example"; + +typedef struct { + char *cmd; + uint16_t cmdSize; + char *cmdResponseOnOk; + uint32_t timeoutMs; +} GSM_Cmd; + +#define GSM_OK_Str "OK" + +GSM_Cmd GSM_MGR_InitCmds[] = { + { + .cmd = "AT\r", + .cmdSize = sizeof("AT\r") - 1, + .cmdResponseOnOk = GSM_OK_Str, + .timeoutMs = 3000, + }, + { + .cmd = "ATE0\r", + .cmdSize = sizeof("ATE0\r") - 1, + .cmdResponseOnOk = GSM_OK_Str, + .timeoutMs = 3000, + }, + { + .cmd = "AT+CPIN?\r", + .cmdSize = sizeof("AT+CPIN?\r") - 1, + .cmdResponseOnOk = "CPIN: READY", + .timeoutMs = 3000, + }, + { + //AT+CGDCONT=1,"IP","apn" + .cmd = "AT+CGDCONT=1,\"IP\",\"playmetric\"\r", + .cmdSize = sizeof("AT+CGDCONT=1,\"IP\",\"playmetric\"\r") - 1, + .cmdResponseOnOk = GSM_OK_Str, + .timeoutMs = 3000, + }, + { + .cmd = "ATDT*99***1#\r", + .cmdSize = sizeof("ATDT*99***1#\r") - 1, + .cmdResponseOnOk = "CONNECT", + .timeoutMs = 30000, + } +}; + +#define GSM_MGR_InitCmdsSize (sizeof(GSM_MGR_InitCmds)/sizeof(GSM_Cmd)) + +/* PPP status callback example */ +static void ppp_status_cb(ppp_pcb *pcb, int err_code, void *ctx) +{ + struct netif *pppif = ppp_netif(pcb); + LWIP_UNUSED_ARG(ctx); + + switch (err_code) { + case PPPERR_NONE: { + ESP_LOGI(TAG, "status_cb: Connected\n"); +#if PPP_IPV4_SUPPORT + ESP_LOGI(TAG, " our_ipaddr = %s\n", ipaddr_ntoa(&pppif->ip_addr)); + ESP_LOGI(TAG, " his_ipaddr = %s\n", ipaddr_ntoa(&pppif->gw)); + ESP_LOGI(TAG, " netmask = %s\n", ipaddr_ntoa(&pppif->netmask)); +#endif /* PPP_IPV4_SUPPORT */ +#if PPP_IPV6_SUPPORT + ESP_LOGI(TAG, " our6_ipaddr = %s\n", ip6addr_ntoa(netif_ip6_addr(pppif, 0))); +#endif /* PPP_IPV6_SUPPORT */ + break; + } + case PPPERR_PARAM: { + ESP_LOGE(TAG, "status_cb: Invalid parameter\n"); + break; + } + case PPPERR_OPEN: { + ESP_LOGE(TAG, "status_cb: Unable to open PPP session\n"); + break; + } + case PPPERR_DEVICE: { + ESP_LOGE(TAG, "status_cb: Invalid I/O device for PPP\n"); + break; + } + case PPPERR_ALLOC: { + ESP_LOGE(TAG, "status_cb: Unable to allocate resources\n"); + break; + } + case PPPERR_USER: { + ESP_LOGE(TAG, "status_cb: User interrupt\n"); + break; + } + case PPPERR_CONNECT: { + ESP_LOGE(TAG, "status_cb: Connection lost\n"); + break; + } + case PPPERR_AUTHFAIL: { + ESP_LOGE(TAG, "status_cb: Failed authentication challenge\n"); + break; + } + case PPPERR_PROTOCOL: { + ESP_LOGE(TAG, "status_cb: Failed to meet protocol\n"); + break; + } + case PPPERR_PEERDEAD: { + ESP_LOGE(TAG, "status_cb: Connection timeout\n"); + break; + } + case PPPERR_IDLETIMEOUT: { + ESP_LOGE(TAG, "status_cb: Idle Timeout\n"); + break; + } + case PPPERR_CONNECTTIME: { + ESP_LOGE(TAG, "status_cb: Max connect time reached\n"); + break; + } + case PPPERR_LOOPBACK: { + ESP_LOGE(TAG, "status_cb: Loopback detected\n"); + break; + } + default: { + ESP_LOGE(TAG, "status_cb: Unknown error code %d\n", err_code); + break; + } + } + + /* + * This should be in the switch case, this is put outside of the switch + * case for example readability. + */ + + if (err_code == PPPERR_NONE) { + return; + } + + /* ppp_close() was previously called, don't reconnect */ + if (err_code == PPPERR_USER) { + /* ppp_free(); -- can be called here */ + return; + } + + + /* + * Try to reconnect in 30 seconds, if you need a modem chatscript you have + * to do a much better signaling here ;-) + */ + //ppp_connect(pcb, 30); + /* OR ppp_listen(pcb); */ +} + +static u32_t ppp_output_callback(ppp_pcb *pcb, u8_t *data, u32_t len, void *ctx) +{ + ESP_LOGI(TAG, "PPP tx len %d", len); + return uart_write_bytes(uart_num, (const char *)data, len); +} + +static void pppos_client_task() +{ + char *data = (char *) malloc(BUF_SIZE); + uart_config_t uart_config = { + .baud_rate = 115200, + .data_bits = UART_DATA_8_BITS, + .parity = UART_PARITY_DISABLE, + .stop_bits = UART_STOP_BITS_1, + .flow_ctrl = UART_HW_FLOWCTRL_CTS_RTS + }; + //Configure UART1 parameters + uart_param_config(uart_num, &uart_config); + + // Configure UART1 pins (as set in example's menuconfig) + ESP_LOGI(TAG, "Configuring UART1 GPIOs: TX:%d RX:%d RTS:%d CTS: %d", + UART1_TX_PIN, UART1_RX_PIN, UART1_RTS_PIN, UART1_CTS_PIN); + uart_set_pin(uart_num, UART1_TX_PIN, UART1_RX_PIN, UART1_RTS_PIN, UART1_CTS_PIN); + uart_driver_install(uart_num, BUF_SIZE * 2, BUF_SIZE * 2, 0, NULL, 0); + + while (1) { + //init gsm + int gsmCmdIter = 0; + while (1) { + ESP_LOGI(TAG, "%s", GSM_MGR_InitCmds[gsmCmdIter].cmd); + uart_write_bytes(uart_num, (const char *)GSM_MGR_InitCmds[gsmCmdIter].cmd, + GSM_MGR_InitCmds[gsmCmdIter].cmdSize); + + int timeoutCnt = 0; + while (1) { + memset(data, 0, BUF_SIZE); + int len = uart_read_bytes(uart_num, (uint8_t *)data, BUF_SIZE, 500 / portTICK_RATE_MS); + if (len > 0) { + ESP_LOGI(TAG, "%s", data); + } + + timeoutCnt += 500; + if (strstr(data, GSM_MGR_InitCmds[gsmCmdIter].cmdResponseOnOk) != NULL) { + break; + } + + if (timeoutCnt > GSM_MGR_InitCmds[gsmCmdIter].timeoutMs) { + ESP_LOGE(TAG, "Gsm Init Error"); + return; + } + } + gsmCmdIter++; + + if (gsmCmdIter >= GSM_MGR_InitCmdsSize) { + break; + } + } + + ESP_LOGI(TAG, "Gsm init end"); + + ppp = pppapi_pppos_create(&ppp_netif, + ppp_output_callback, ppp_status_cb, NULL); + + ESP_LOGI(TAG, "After pppapi_pppos_create"); + + if (ppp == NULL) { + ESP_LOGE(TAG, "Error init pppos"); + return; + } + + pppapi_set_default(ppp); + + ESP_LOGI(TAG, "After pppapi_set_default"); + + pppapi_set_auth(ppp, PPPAUTHTYPE_PAP, PPP_User, PPP_Pass); + + ESP_LOGI(TAG, "After pppapi_set_auth"); + + pppapi_connect(ppp, 0); + + ESP_LOGI(TAG, "After pppapi_connect"); + + while (1) { + memset(data, 0, BUF_SIZE); + int len = uart_read_bytes(uart_num, (uint8_t *)data, BUF_SIZE, 10 / portTICK_RATE_MS); + if (len > 0) { + ESP_LOGI(TAG, "PPP rx len %d", len); + pppos_input_tcpip(ppp, (u8_t *)data, len); + } + } + + } +} + +void app_main() +{ + tcpip_adapter_init(); + xTaskCreate(&pppos_client_task, "pppos_client_task", 2048, NULL, 5, NULL); +} diff --git a/examples/protocols/pppos_client/sdkconfig.defaults b/examples/protocols/pppos_client/sdkconfig.defaults new file mode 100644 index 000000000..ad5b9364f --- /dev/null +++ b/examples/protocols/pppos_client/sdkconfig.defaults @@ -0,0 +1,5 @@ +# Override some defaults to enable PPP +CONFIG_PPP_SUPPORT=y +CONFIG_PPP_PAP_SUPPORT=y +CONFIG_PPP_DEBUG_ON=y +CONFIG_TCPIP_TASK_STACK_SIZE=4096 \ No newline at end of file diff --git a/examples/storage/wear_levelling/Makefile b/examples/storage/wear_levelling/Makefile new file mode 100644 index 000000000..cb63d4b56 --- /dev/null +++ b/examples/storage/wear_levelling/Makefile @@ -0,0 +1,9 @@ +# +# This is a project Makefile. It is assumed the directory this Makefile resides in is a +# project subdirectory. +# + +PROJECT_NAME := wear_levelling_example + +include $(IDF_PATH)/make/project.mk + diff --git a/examples/storage/wear_levelling/README.md b/examples/storage/wear_levelling/README.md new file mode 100644 index 000000000..40e492498 --- /dev/null +++ b/examples/storage/wear_levelling/README.md @@ -0,0 +1,23 @@ +# SD Card example + +This example demonstrates how to use wear levelling library and FATFS library to store files in a partition inside SPI flash. Example does the following steps: + +1. Use an "all-in-one" `esp_vfs_fat_spiflash_mount` function to: + - find a partition in SPI flash, + - initialize wear levelling library using this partition + - mount FAT filesystem using FATFS library (and format the filesystem, if the filesystem can not be mounted), + - register FAT filesystem in VFS, enabling C standard library and POSIX functions to be used. +2. Create a file using `fopen` and write to it using `fprintf`. +3. Open file for reading, read back the line, and print it to the terminal. + +## Example output + +Here is an typical example console output. + +``` +Try to open file ... +I (239) wear_level: Reading file +Read from file: 'Hello User! I'm happy to see you!1' +W (239) wear_levelling: wl_unmount Delete driver +``` + diff --git a/examples/storage/wear_levelling/main/component.mk b/examples/storage/wear_levelling/main/component.mk new file mode 100644 index 000000000..a98f634ea --- /dev/null +++ b/examples/storage/wear_levelling/main/component.mk @@ -0,0 +1,4 @@ +# +# "main" pseudo-component makefile. +# +# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) diff --git a/examples/storage/wear_levelling/main/wear_levelling_example_main.c b/examples/storage/wear_levelling/main/wear_levelling_example_main.c new file mode 100644 index 000000000..dd02542fc --- /dev/null +++ b/examples/storage/wear_levelling/main/wear_levelling_example_main.c @@ -0,0 +1,74 @@ +/* Wear levelling and FAT filesystem example. + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. + + This sample shows how to store files inside a FAT filesystem. + FAT filesystem is stored in a partition inside SPI flash, using the + flash wear levelling library. +*/ + +#include +#include +#include +#include "esp_vfs.h" +#include "esp_vfs_fat.h" +#include "esp_system.h" + +static const char *TAG = "example"; + +// Handle of the wear levelling library instance +static wl_handle_t s_wl_handle = WL_INVALID_HANDLE; + +// Mount path for the partition +const char *base_path = "/spiflash"; + +void app_main(void) +{ + ESP_LOGI(TAG, "Mounting FAT filesystem"); + // To mount device we need name of device partition, define base_path + // and allow format partition in case if it is new one and was not formated before + const esp_vfs_fat_mount_config_t mount_config = { + .max_files = 4, + .format_if_mount_failed = true + }; + esp_err_t err = esp_vfs_fat_spiflash_mount(base_path, "storage", &mount_config, &s_wl_handle); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to mount FATFS (0x%x)", err); + return; + } + ESP_LOGI(TAG, "Opening file"); + FILE *f = fopen("/spiflash/hello.txt", "wb"); + if (f == NULL) { + ESP_LOGE(TAG, "Failed to open file for writing"); + return; + } + fprintf(f, "written using ESP-IDF %s\n", esp_get_idf_version()); + fclose(f); + ESP_LOGI(TAG, "File written"); + + // Open file for reading + ESP_LOGI(TAG, "Reading file"); + f = fopen("/spiflash/hello.txt", "rb"); + if (f == NULL) { + ESP_LOGE(TAG, "Failed to open file for reading"); + return; + } + char line[128]; + fgets(line, sizeof(line), f); + fclose(f); + // strip newline + char *pos = strchr(line, '\n'); + if (pos) { + *pos = '\0'; + } + ESP_LOGI(TAG, "Read from file: '%s'", line); + + // Unmount FATFS + ESP_LOGI(TAG, "Unmounting FAT filesystem"); + ESP_ERROR_CHECK( esp_vfs_fat_spiflash_unmount(base_path, s_wl_handle)); + + ESP_LOGI(TAG, "Done"); +} diff --git a/examples/storage/wear_levelling/partitions_example.csv b/examples/storage/wear_levelling/partitions_example.csv new file mode 100644 index 000000000..7e28b5668 --- /dev/null +++ b/examples/storage/wear_levelling/partitions_example.csv @@ -0,0 +1,6 @@ +# Name, Type, SubType, Offset, Size, Flags +# Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild +nvs, data, nvs, 0x9000, 0x6000, +phy_init, data, phy, 0xf000, 0x1000, +factory, app, factory, 0x10000, 1M, +storage, data, fat, , 1M, diff --git a/examples/storage/wear_levelling/sdkconfig.defaults b/examples/storage/wear_levelling/sdkconfig.defaults new file mode 100644 index 000000000..f30f322c6 --- /dev/null +++ b/examples/storage/wear_levelling/sdkconfig.defaults @@ -0,0 +1,5 @@ +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_example.csv" +CONFIG_PARTITION_TABLE_CUSTOM_APP_BIN_OFFSET=0x10000 +CONFIG_PARTITION_TABLE_FILENAME="partitions_example.csv" +CONFIG_APP_OFFSET=0x10000 diff --git a/examples/system/ota/README.md b/examples/system/ota/README.md index 886dbf5fb..2b0e0202b 100644 --- a/examples/system/ota/README.md +++ b/examples/system/ota/README.md @@ -16,7 +16,7 @@ In this example, the ESP32 has 3 images in flash: factory, OTA_0, OTA_1. Each of Flashing the example over serial with "make flash" updates the factory app image. On first boot, the bootloader loads this factory app image which then performs an OTA update (triggered in the example code). The update downloads a new image from an http server and saves it into the OTA_0 partition. At this point the example code updates the ota_data partition to indicate the new app partition, and resets. The bootloader reads ota_data, determines the new OTA image has been selected, and runs it. -# Worflow +# Workflow The OTA_workflow.png diagram demonstrates the overall workflow: diff --git a/make/project.mk b/make/project.mk index fd85ef4e5..1c868ad30 100644 --- a/make/project.mk +++ b/make/project.mk @@ -189,9 +189,9 @@ endif IDF_VER := $(shell cd ${IDF_PATH} && git describe --always --tags --dirty) # Set default LDFLAGS - +SRCDIRS_COMPONENT_NAMES := $(sort $(foreach comp,$(SRCDIRS),$(lastword $(subst /, ,$(comp))))) LDFLAGS ?= -nostdlib \ - $(addprefix -L$(BUILD_DIR_BASE)/,$(COMPONENTS) $(TEST_COMPONENT_NAMES) $(SRCDIRS) ) \ + $(addprefix -L$(BUILD_DIR_BASE)/,$(COMPONENTS) $(TEST_COMPONENT_NAMES) $(SRCDIRS_COMPONENT_NAMES) ) \ -u call_user_start_cpu0 \ $(EXTRA_LDFLAGS) \ -Wl,--gc-sections \ diff --git a/tools/catch/LICENSE.txt b/tools/catch/LICENSE.txt new file mode 100644 index 000000000..36b7cd93c --- /dev/null +++ b/tools/catch/LICENSE.txt @@ -0,0 +1,23 @@ +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/tools/catch/README.md b/tools/catch/README.md new file mode 100644 index 000000000..9937d965e --- /dev/null +++ b/tools/catch/README.md @@ -0,0 +1,4 @@ +This directory contains header-only version of Catch C++ unit test library, +mostly used in host-side tests. + +See https://github.com/philsquared/catch for more info. diff --git a/components/nvs_flash/test_nvs_host/catch.hpp b/tools/catch/catch.hpp similarity index 100% rename from components/nvs_flash/test_nvs_host/catch.hpp rename to tools/catch/catch.hpp diff --git a/tools/esp_app_trace/apptrace_proc.py b/tools/esp_app_trace/apptrace_proc.py new file mode 100755 index 000000000..d676b0c06 --- /dev/null +++ b/tools/esp_app_trace/apptrace_proc.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python +# + +import argparse +import struct +import sys + +class bcolors: + HEADER = '\033[95m' + OKBLUE = '\033[94m' + OKGREEN = '\033[92m' + WARNING = '\033[93m' + FAIL = '\033[91m' + ENDC = '\033[0m' + BOLD = '\033[1m' + UNDERLINE = '\033[4m' + +def main(): + ESP32_TRACE_BLOCK_HDR_SZ = 8 + ESP32_TRACE_BLOCK_TASK_IDX = 0 + ESP32_TRACE_BLOCK_TS_IDX = 1 + ESP32_TRACE_BLOCK_DATA_IDX = 2 + + parser = argparse.ArgumentParser(description='ESP32 App Trace Parse Tool') + + parser.add_argument('file', help='Path to app trace file', type=str) + parser.add_argument('--print-tasks', '-p', help='Print tasks', action='store_true') + parser.add_argument('--print-details', '-d', help='Print detailed stats', action='store_true') + parser.add_argument('--no-errors', '-n', help='Do not print errors', action='store_true') + parser.add_argument('--block-len', '-b', help='Block length', type=int, default=1024) + + args = parser.parse_args() + + print "====================================================================" + try: + ftrc = open(args.file, 'rb') + except IOError as e: + print "Failed to open trace file (%s)!" % e + sys.exit(2) + + passed = True + off = 0 + data_stats = {} + last_ts = None + tot_discont = 0 + while True: + #ftrc.seek(off) + task = None + ts = 0 + trc_buf = ftrc.read(args.block_len) + if len(trc_buf) == 0: +# print 'EOF' + break + trc_data = struct.unpack('= ts: +# print "Global TS discontinuity %x -> %x, task %x, stamp %x at %x" % (last_ts, ts, task, data_stats[task]['stamp'], off) + if args.print_details: + print "Global TS discontinuity %x -> %x, task %x at %x" % (last_ts, ts, task, off) +# tot_discont += 1 +# passed = False + last_ts = ts + if not task in data_stats: + print "%x: NEW TASK" % task + data_stats[task] = {'stamp' : trc_data[ESP32_TRACE_BLOCK_DATA_IDX], 'last_ts' : ts, 'count' : 1, 'discont_offs' : [], 'inv_stamps_offs' : []} + else: + if data_stats[task]['last_ts'] == ts: + print "Task TS discontinuity %x -> %x, task %x, stamp %x at %x" % (last_ts, ts, task, data_stats[task]['stamp'], off) + data_stats[task]['discont_offs'].append(off) + tot_discont += 1 + passed = False + data_stats[task]['last_ts'] = ts + data_stats[task]['count'] += 1 + if len(trc_data) > ESP32_TRACE_BLOCK_DATA_IDX: +# print "DATA = %x %x %x %x" % (trc_data[-4], trc_data[-3], trc_data[-2], trc_data[-1]) + if args.print_tasks: + print "Task[%d] %x, ts %08x, stamp %x" % (off/args.block_len, task, ts, trc_data[ESP32_TRACE_BLOCK_DATA_IDX]) + else: + print "%x: NO DATA" % task + else: + print "Failed to unpack data!" + sys.exit(2) + + # check data + for i in range(ESP32_TRACE_BLOCK_DATA_IDX, len(trc_data)): + if trc_data[i] != data_stats[task]['stamp']: + if not args.no_errors: + print "Invalid stamp %x->%x at %x, task %x" % (data_stats[task]['stamp'], trc_data[i], off + ESP32_TRACE_BLOCK_HDR_SZ + i, task) + passed = False + data_stats[task]['stamp'] = trc_data[i] + data_stats[task]['inv_stamps_offs'].append(off) +# break + if len(trc_buf) < args.block_len: + print 'Last block (not full)' + break + + if data_stats[task]['stamp'] != None: + data_stats[task]['stamp'] = (data_stats[task]['stamp'] + 1) & 0xFF +# print "stamp=%x" % data_stats[task][ESP32_TRACE_STAMP_IDX] + off += args.block_len + + ftrc.close() + print "====================================================================" + print "Trace size %d bytes, discont %d\n" % (off, tot_discont) + for t in data_stats: + print "Task %x. Total count %d. Inv stamps %d. TS Discontinuities %d." % (t, data_stats[t]['count'], len(data_stats[t]['inv_stamps_offs']), len(data_stats[t]['discont_offs'])) + if args.print_details: + print 'Invalid stamps offs: [{}]'.format(', '.join(hex(x) for x in data_stats[t]['inv_stamps_offs'])) + print 'TS Discontinuities offs: [{}]'.format(', '.join(hex(x) for x in data_stats[t]['discont_offs'])) + print "\n" + + if passed: + print "Data - OK" + else: + print "Data - FAILED!" + +if __name__ == '__main__': + main() diff --git a/tools/esp_app_trace/logtrace_proc.py b/tools/esp_app_trace/logtrace_proc.py new file mode 100755 index 000000000..74860252a --- /dev/null +++ b/tools/esp_app_trace/logtrace_proc.py @@ -0,0 +1,163 @@ +#!/usr/bin/env python +# + +import argparse +import struct +import sys +import pylibelf as elf +import pylibelf.util as elfutil +import pylibelf.iterators as elfiter +import pylibelf.constants as elfconst +from ctypes import * + +class ESPLogTraceParserError(RuntimeError): + def __init__(self, message): + RuntimeError.__init__(self, message) + + +class ESPLogTraceRecord(object): + def __init__(self, fmt_addr, log_args): + super(ESPLogTraceRecord, self).__init__() + self.fmt_addr = fmt_addr + self.args = log_args + + def __repr__(self): + return "fmt_addr = 0x%x, args = %d/%s" % (self.fmt_addr, len(self.args), self.args) + + +def logtrace_parse(fname): + ESP32_LOGTRACE_HDR_FMT = ' 0: + print "Unprocessed %d bytes of log record header!" % len(trc_buf) + # data_ok = False + break + try: + nargs,fmt_addr = struct.unpack(ESP32_LOGTRACE_HDR_FMT, trc_buf) + except struct.error as e: + raise ESPLogTraceParserError("Failed to unpack log record header (%s)!" % e) + # read args + args_sz = struct.calcsize('<%sL' % nargs) + try: + trc_buf = ftrc.read(args_sz) + except IOError as e: + raise ESPLogTraceParserError("Failed to read log record args (%s)!" % e) + if len(trc_buf) < args_sz: + # print "EOF" + if len(trc_buf) > 0: + print "Unprocessed %d bytes of log record args!" % len(trc_buf) + # data_ok = False + break + try: + log_args = struct.unpack('<%sL' % nargs, trc_buf) + except struct.error as e: + raise ESPLogTraceParserError("Failed to unpack log record args (%s)!" % e) + # print log_args + recs.append(ESPLogTraceRecord(fmt_addr, list(log_args))) + + ftrc.close() + # sorted(recs, key=lambda rec: rec.fmt_addr) + return recs + + +def logtrace_get_str_from_elf(felf, str_addr): + tgt_str = "" + for sect in elfiter.sections(felf): + hdr = elfutil.section_hdr(felf, sect) + if hdr.sh_addr == 0 or hdr.sh_type != elfconst.SHT_PROGBITS: + continue + if str_addr < hdr.sh_addr or str_addr >= hdr.sh_addr + hdr.sh_size: + continue + # print "Found SECT: %x..%x @ %x" % (hdr.sh_addr, hdr.sh_addr + hdr.sh_size, str_addr - hdr.sh_addr) + sec_data = elfiter.getOnlyData(sect).contents + buf = cast(sec_data.d_buf, POINTER(c_char)) + for i in range(str_addr - hdr.sh_addr, hdr.sh_size): + if buf[i] == "\0": + break + tgt_str += buf[i] + if len(tgt_str) > 0: + return tgt_str + return None + +def logtrace_formated_print(recs, elfname, no_err): + try: + felf = elfutil.open_elf(elfname) + except OSError as e: + raise ESPLogTraceParserError("Failed to open ELF file (%s)!" % e) + + for lrec in recs: + fmt_str = logtrace_get_str_from_elf(felf, lrec.fmt_addr) + i = 0 + prcnt_idx = 0 + while i < len(lrec.args): + prcnt_idx = fmt_str.find('%', prcnt_idx, -2) # TODO: check str ending with % + if prcnt_idx == -1: + break + prcnt_idx += 1 # goto next char + if fmt_str[prcnt_idx] == 's': + # find string + arg_str = logtrace_get_str_from_elf(felf, lrec.args[i]) + if arg_str: + lrec.args[i] = arg_str + i += 1 + # print "\nFmt = {%s}, args = %d/%s" % lrec + fmt_str = fmt_str.replace('%p', '%x') + # print "=====> " + fmt_str % lrec.args + try: + print fmt_str % tuple(lrec.args), + # print ".", + pass + except Exception as e: + if not no_err: + print "Print error (%s)" % e + print "\nFmt = {%s}, args = %d/%s" % (fmt_str, len(lrec.args), lrec.args) + + elf.elf_end(felf) + +def main(): + + parser = argparse.ArgumentParser(description='ESP32 Log Trace Parsing Tool') + + parser.add_argument('trace_file', help='Path to log trace file', type=str) + parser.add_argument('elf_file', help='Path to program ELF file', type=str) + # parser.add_argument('--print-details', '-d', help='Print detailed stats', action='store_true') + parser.add_argument('--no-errors', '-n', help='Do not print errors', action='store_true') + args = parser.parse_args() + + # parse trace file + try: + print "Parse trace file '%s'..." % args.trace_file + lrecs = logtrace_parse(args.trace_file); + print "Parsing completed." + except ESPLogTraceParserError as e: + print "Failed to parse log trace (%s)!" % e + sys.exit(2) + # print recs + # get format strings and print info + print "====================================================================" + try: + logtrace_formated_print(lrecs, args.elf_file, args.no_errors); + except ESPLogTraceParserError as e: + print "Failed to print log trace (%s)!" % e + sys.exit(2) + print "\n====================================================================\n" + + print "Log records count: %d" % len(lrecs) + +if __name__ == '__main__': + main() diff --git a/tools/esp_app_trace/pylibelf/.gitignore b/tools/esp_app_trace/pylibelf/.gitignore new file mode 100644 index 000000000..42ac64781 --- /dev/null +++ b/tools/esp_app_trace/pylibelf/.gitignore @@ -0,0 +1,59 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] + +# C extensions +*.so + +# Distribution / packaging +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +*.egg-info/ +.installed.cfg +*.egg + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.cache +nosetests.xml +coverage.xml + +# Translations +*.mo +*.pot + +# Django stuff: +*.log + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +*.swp +*.swo +*.swn + diff --git a/tools/esp_app_trace/pylibelf/LICENSE b/tools/esp_app_trace/pylibelf/LICENSE new file mode 100644 index 000000000..2e216332f --- /dev/null +++ b/tools/esp_app_trace/pylibelf/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2014 d1m0 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/tools/esp_app_trace/pylibelf/README.md b/tools/esp_app_trace/pylibelf/README.md new file mode 100644 index 000000000..1019a8f32 --- /dev/null +++ b/tools/esp_app_trace/pylibelf/README.md @@ -0,0 +1,5 @@ +pylibelf +======== + +Python binding for libelf. + diff --git a/tools/esp_app_trace/pylibelf/__init__.py b/tools/esp_app_trace/pylibelf/__init__.py new file mode 100644 index 000000000..d00da18ab --- /dev/null +++ b/tools/esp_app_trace/pylibelf/__init__.py @@ -0,0 +1,155 @@ +from types import * +from constants import * +from ctypes import * + +lelf=CDLL("libelf.so.1") + +__all__ = [] + +all_objs = [] + +class ElfError(Exception): + def __init__(self, msg): + self.msg = msg + self.errno = elf_errno() + self.elfmsg = elf_errmsg(self.errno) + + def __str__(self): + return "ElfError(%d, %s): %s" % (self.errno, self.elfmsg, self.msg) + +__all__.append("ElfError") + +def nonNullDec(f): + def decorated(*args): + res = f(*args) + try: + a = res.contents + all_objs.append(res) + except ValueError: # NULL + raise ElfError(f.__name__ + " returned NULL") + return res + return decorated + +def nonNegDec(f): + def decorated(*args): + res = f(*args) + if 0 > res: + raise ElfError(f.__name__ + " returned %d" % (res,)) + return res + return decorated + +def badValDec(badVal): + def decorator(f): + def decorated(*args): + res = f(*args) + if res == badVal: + raise ElfError(f.__name__ + " returned %s" % (str(res),)) + return res + return decorated + return decorator + +def define(f, argtypes, restype, err_decorator = None): + f.argtypes = argtypes + f.restype = restype + name = f.__name__ + __all__.append(name) + + if (err_decorator != None): + f = err_decorator(f) + + globals()[name] = f + +define(lelf.elf_version, [ c_int ], c_int ) + +if (elf_version(EV_CURRENT) == EV_NONE): + raise Exception("Version mismatch") + +off_t = c_size_t # TODO(dbounov): Figure out actual off_t type + +define(lelf.elf_begin, [ c_int, Elf_Cmd, ElfP ], ElfP) +define(lelf.elf_getident, [ ElfP, POINTER(c_int) ], POINTER(Elf_IdentT), nonNullDec) +define(lelf.elf_end, [ ElfP ], c_int, nonNegDec ) +define(lelf.elf_cntl, [ ElfP, c_int ], c_int, nonNegDec) +define(lelf.elf_errmsg, [ c_int ], c_char_p) +define(lelf.elf_errno, [ ], c_int) +define(lelf.elf_fill, [ c_int ], None) +define(lelf.elf_flagdata, [ Elf_DataP, c_int, c_uint ], c_uint) +define(lelf.elf_flagehdr, [ ElfP, c_int, c_uint ], c_uint) +define(lelf.elf_flagelf, [ ElfP, c_int, c_uint ], c_uint) +define(lelf.elf_flagphdr, [ ElfP, c_int, c_uint ], c_uint) +define(lelf.elf_flagscn, [ Elf_ScnP, c_int, c_uint ], c_uint) +define(lelf.elf_flagshdr, [ Elf_ScnP, c_int, c_uint ], c_uint) +define(lelf.elf_getarhdr, [ ElfP ], POINTER(Elf_Arhdr)) +#define(lelf.elf_getarsym, [ ], ) +define(lelf.elf_getbase, [ ElfP ], off_t, nonNegDec) +define(lelf.elf_getdata, [ Elf_ScnP, Elf_DataP ], Elf_DataP) +define(lelf.elf_getscn, [ ElfP, c_size_t ], Elf_ScnP, nonNullDec ) +define(lelf.elf_getshnum, [ ElfP, POINTER(c_size_t) ], c_int, nonNegDec ) +define(lelf.elf_getshstrndx, [ ElfP, POINTER(c_size_t) ], c_int, nonNegDec ) +define(lelf.elf_hash, [ c_char_p ], c_ulong) +define(lelf.elf_kind, [ ElfP ], c_int ) +define(lelf.elf_memory, [ POINTER(c_char), c_size_t ], ElfP, nonNullDec) +define(lelf.elf_ndxscn, [ Elf_ScnP ], c_size_t, badValDec(SHN_UNDEF)) +define(lelf.elf_newdata, [ Elf_ScnP ], Elf_DataP, nonNullDec) +define(lelf.elf_newscn, [ ElfP ], Elf_ScnP, nonNullDec) +#define(lelf.elf_next, [ ], ) +define(lelf.elf_nextscn, [ ElfP, Elf_ScnP ], Elf_ScnP) +#define(lelf.elf_rand, [ ], ) +define(lelf.elf_rawdata, [ Elf_ScnP, Elf_DataP ], Elf_DataP) +#define(lelf.elf_rawfile, [ ], ) +define(lelf.elf_strptr, [ ElfP, c_size_t, c_size_t ], c_char_p) +define(lelf.elf_update, [ ElfP, c_int], off_t, nonNegDec) + +define(lelf.elf32_checksum, [ ElfP ], c_long) +define(lelf.elf32_fsize, [ c_int, c_size_t, c_uint ], c_size_t, nonNegDec) +define(lelf.elf32_getehdr, [ ElfP ], POINTER(Elf32_Ehdr), nonNullDec) +define(lelf.elf32_getphdr, [ ElfP ], POINTER(Elf32_Phdr), nonNullDec) +define(lelf.elf32_getshdr, [ Elf_ScnP ], POINTER(Elf32_Shdr), nonNullDec) +define(lelf.elf32_newehdr, [ ElfP ], POINTER(Elf32_Ehdr), nonNullDec) +define(lelf.elf32_newphdr, [ ElfP, c_size_t ], POINTER(Elf32_Phdr), nonNullDec) +define(lelf.elf32_xlatetof, [ Elf_DataP, Elf_DataP, c_uint ], Elf_DataP, nonNullDec) +define(lelf.elf32_xlatetom, [ Elf_DataP, Elf_DataP, c_uint ], Elf_DataP, nonNullDec) + + +define(lelf.elf64_checksum, [ ElfP ], c_long ) +define(lelf.elf64_fsize, [ c_int, c_size_t, c_uint ], c_size_t, nonNegDec) +define(lelf.elf64_getehdr,[ ElfP ], POINTER(Elf64_Ehdr), nonNullDec) +define(lelf.elf64_getphdr, [ ElfP ], POINTER(Elf64_Phdr), nonNullDec) +define(lelf.elf64_getshdr, [ Elf_ScnP ], POINTER(Elf64_Shdr), nonNullDec) +define(lelf.elf64_newehdr, [ ElfP ], POINTER(Elf64_Ehdr), nonNullDec) +define(lelf.elf64_newphdr, [ ElfP, c_size_t ], POINTER(Elf64_Phdr), nonNullDec) +define(lelf.elf64_xlatetof, [ Elf_DataP, Elf_DataP, c_uint ], Elf_DataP, nonNullDec) +define(lelf.elf64_xlatetom, [ Elf_DataP, Elf_DataP, c_uint ], Elf_DataP, nonNullDec) + +# NOTE(dbounov): Ignoring gelf functions for now + +#define(lelf.gelf_checksum, [ ], ) +#define(lelf.gelf_fsize, [ ], ) +#define(lelf.gelf_getcap, [ ], ) +#define(lelf.gelf_getclass, [ ], ) +#define(lelf.gelf_getdyn, [ ], ) +#define(lelf.gelf_getehdr, [ ], ) +#define(lelf.gelf_getmove, [ ], ) +#define(lelf.gelf_getphdr, [ ], ) +#define(lelf.gelf_getrel, [ ], ) +#define(lelf.gelf_getrela, [ ], ) +#define(lelf.gelf_getshdr, [ ], ) +#define(lelf.gelf_getsym, [ ], ) +#define(lelf.gelf_getsyminfo, [ ], ) +#define(lelf.gelf_getsymshndx, [ ], ) +#define(lelf.gelf_newehdr, [ ], ) +#define(lelf.gelf_newphdr, [ ], ) +#define(lelf.gelf_update_cap, [ ], ) +#define(lelf.gelf_update_dyn, [ ], ) +#define(lelf.gelf_update_ehdr, [ ], ) +#define(lelf.gelf_update_move, [ ], ) +#define(lelf.gelf_update_phdr, [ ], ) +#define(lelf.gelf_update_rel, [ ], ) +#define(lelf.gelf_update_rela, [ ], ) +#define(lelf.gelf_update_shdr, [ ], ) +#define(lelf.gelf_update_sym, [ ], ) +#define(lelf.gelf_update_symshndx, [ ], ) +#define(lelf.gelf_update_syminfo, [ ], ) +#define(lelf.gelf_xlatetof, [ ], ) +#define(lelf.gelf_xlatetom, [ ], ) +#define(lelf.nlist, [ ], ) diff --git a/tools/esp_app_trace/pylibelf/constants/__init__.py b/tools/esp_app_trace/pylibelf/constants/__init__.py new file mode 100644 index 000000000..890f97abb --- /dev/null +++ b/tools/esp_app_trace/pylibelf/constants/__init__.py @@ -0,0 +1,1850 @@ + +# Really simple expression types to handle arithmetic expressions referring +# to other # defines +class MacroExp: pass +class MacroRef(MacroExp): + def __init__(s, name): + s._name = name; + + def eval(s): + return lookup(s._name) + + def __add__(s, o): + return MacroAdd(s, o) + + def __radd__(s, o): + return MacroAdd(o, s) + +class MacroAdd(MacroExp): + def __init__(s, l, r): + s.l = l; + s.r = r; + + def eval(s): + l = s.l.eval() if (isinstance(s.l, MacroExp)) else s.l + r = s.r.eval() if (isinstance(s.r, MacroExp)) else s.r + + return l + r + + def __add__(s, o): + return MacroAdd(s, o) + + def __radd__(s, o): + return MacroAdd(o, s) + + +def lookup(n): + v = _consts[n] + if isinstance(v, MacroExp): + return v.eval() + else: + return v + +# Macro constants +_consts = { + "EI_NIDENT": 16 , # + "EI_MAG0": 0 , # File identification byte 0 index + "ELFMAG0": 0x7f , # Magic number byte 0 + "EI_MAG1": 1 , # File identification byte 1 index + "ELFMAG1": 'E' , # Magic number byte 1 + "EI_MAG2": 2 , # File identification byte 2 index + "ELFMAG2": 'L' , # Magic number byte 2 + "EI_MAG3": 3 , # File identification byte 3 index + "ELFMAG3": 'F' , # Magic number byte 3 + "ELFMAG": "\177ELF" , # + "SELFMAG": 4 , # + "EI_CLASS": 4 , # File class byte index + "ELFCLASSNONE": 0 , # Invalid class + "ELFCLASS32": 1 , # 32-bit objects + "ELFCLASS64": 2 , # 64-bit objects + "ELFCLASSNUM": 3 , # + "EI_DATA": 5 , # Data encoding byte index + "ELFDATANONE": 0 , # Invalid data encoding + "ELFDATA2LSB": 1 , # 2's complement, little endian + "ELFDATA2MSB": 2 , # 2's complement, big endian + "ELFDATANUM": 3 , # + "EI_VERSION": 6 , # File version byte index + "EI_OSABI": 7 , # OS ABI identification + "ELFOSABI_NONE": 0 , # UNIX System V ABI + "ELFOSABI_SYSV": 0 , # Alias. + "ELFOSABI_HPUX": 1 , # HP-UX + "ELFOSABI_NETBSD": 2 , # NetBSD. + "ELFOSABI_GNU": 3 , # Object uses GNU ELF extensions. + "ELFOSABI_LINUX": MacroRef("ELFOSABI_GNU") , # Compatibility alias. + "ELFOSABI_SOLARIS": 6 , # Sun Solaris. + "ELFOSABI_AIX": 7 , # IBM AIX. + "ELFOSABI_IRIX": 8 , # SGI Irix. + "ELFOSABI_FREEBSD": 9 , # FreeBSD. + "ELFOSABI_TRU64": 10 , # Compaq TRU64 UNIX. + "ELFOSABI_MODESTO": 11 , # Novell Modesto. + "ELFOSABI_OPENBSD": 12 , # OpenBSD. + "ELFOSABI_ARM_AEABI": 64 , # ARM EABI + "ELFOSABI_ARM": 97 , # ARM + "ELFOSABI_STANDALONE": 255 , # Standalone (embedded) application + "EI_ABIVERSION": 8 , # ABI version + "EI_PAD": 9 , # Byte index of padding bytes + "ET_NONE": 0 , # No file type + "ET_REL": 1 , # Relocatable file + "ET_EXEC": 2 , # Executable file + "ET_DYN": 3 , # Shared object file + "ET_CORE": 4 , # Core file + "ET_NUM": 5 , # Number of defined types + "ET_LOOS": 0xfe00 , # OS-specific range start + "ET_HIOS": 0xfeff , # OS-specific range end + "ET_LOPROC": 0xff00 , # Processor-specific range start + "ET_HIPROC": 0xffff , # Processor-specific range end + "EM_NONE": 0 , # No machine + "EM_M32": 1 , # AT&T WE 32100 + "EM_SPARC": 2 , # SUN SPARC + "EM_386": 3 , # Intel 80386 + "EM_68K": 4 , # Motorola m68k family + "EM_88K": 5 , # Motorola m88k family + "EM_860": 7 , # Intel 80860 + "EM_MIPS": 8 , # MIPS R3000 big-endian + "EM_S370": 9 , # IBM System/370 + "EM_MIPS_RS3_LE": 10 , # MIPS R3000 little-endian + "EM_PARISC": 15 , # HPPA + "EM_VPP500": 17 , # Fujitsu VPP500 + "EM_SPARC32PLUS": 18 , # Sun's "v8plus" + "EM_960": 19 , # Intel 80960 + "EM_PPC": 20 , # PowerPC + "EM_PPC64": 21 , # PowerPC 64-bit + "EM_S390": 22 , # IBM S390 + "EM_V800": 36 , # NEC V800 series + "EM_FR20": 37 , # Fujitsu FR20 + "EM_RH32": 38 , # TRW RH-32 + "EM_RCE": 39 , # Motorola RCE + "EM_ARM": 40 , # ARM + "EM_FAKE_ALPHA": 41 , # Digital Alpha + "EM_SH": 42 , # Hitachi SH + "EM_SPARCV9": 43 , # SPARC v9 64-bit + "EM_TRICORE": 44 , # Siemens Tricore + "EM_ARC": 45 , # Argonaut RISC Core + "EM_H8_300": 46 , # Hitachi H8/300 + "EM_H8_300H": 47 , # Hitachi H8/300H + "EM_H8S": 48 , # Hitachi H8S + "EM_H8_500": 49 , # Hitachi H8/500 + "EM_IA_64": 50 , # Intel Merced + "EM_MIPS_X": 51 , # Stanford MIPS-X + "EM_COLDFIRE": 52 , # Motorola Coldfire + "EM_68HC12": 53 , # Motorola M68HC12 + "EM_MMA": 54 , # Fujitsu MMA Multimedia Accelerator + "EM_PCP": 55 , # Siemens PCP + "EM_NCPU": 56 , # Sony nCPU embeeded RISC + "EM_NDR1": 57 , # Denso NDR1 microprocessor + "EM_STARCORE": 58 , # Motorola Start*Core processor + "EM_ME16": 59 , # Toyota ME16 processor + "EM_ST100": 60 , # STMicroelectronic ST100 processor + "EM_TINYJ": 61 , # Advanced Logic Corp. Tinyj emb.fam + "EM_X86_64": 62 , # AMD x86-64 architecture + "EM_PDSP": 63 , # Sony DSP Processor + "EM_FX66": 66 , # Siemens FX66 microcontroller + "EM_ST9PLUS": 67 , # STMicroelectronics ST9+ 8/16 mc + "EM_ST7": 68 , # STmicroelectronics ST7 8 bit mc + "EM_68HC16": 69 , # Motorola MC68HC16 microcontroller + "EM_68HC11": 70 , # Motorola MC68HC11 microcontroller + "EM_68HC08": 71 , # Motorola MC68HC08 microcontroller + "EM_68HC05": 72 , # Motorola MC68HC05 microcontroller + "EM_SVX": 73 , # Silicon Graphics SVx + "EM_ST19": 74 , # STMicroelectronics ST19 8 bit mc + "EM_VAX": 75 , # Digital VAX + "EM_CRIS": 76 , # Axis Communications 32-bit embedded processor + "EM_JAVELIN": 77 , # Infineon Technologies 32-bit embedded processor + "EM_FIREPATH": 78 , # Element 14 64-bit DSP Processor + "EM_ZSP": 79 , # LSI Logic 16-bit DSP Processor + "EM_MMIX": 80 , # Donald Knuth's educational 64-bit processor + "EM_HUANY": 81 , # Harvard University machine-independent object files + "EM_PRISM": 82 , # SiTera Prism + "EM_AVR": 83 , # Atmel AVR 8-bit microcontroller + "EM_FR30": 84 , # Fujitsu FR30 + "EM_D10V": 85 , # Mitsubishi D10V + "EM_D30V": 86 , # Mitsubishi D30V + "EM_V850": 87 , # NEC v850 + "EM_M32R": 88 , # Mitsubishi M32R + "EM_MN10300": 89 , # Matsushita MN10300 + "EM_MN10200": 90 , # Matsushita MN10200 + "EM_PJ": 91 , # picoJava + "EM_OPENRISC": 92 , # OpenRISC 32-bit embedded processor + "EM_ARC_A5": 93 , # ARC Cores Tangent-A5 + "EM_XTENSA": 94 , # Tensilica Xtensa Architecture + "EM_NUM": 95 , # + "EM_ALPHA": 0x9026 , # + "EV_NONE": 0 , # Invalid ELF version + "EV_CURRENT": 1 , # Current version + "EV_NUM": 2 , # + "SHN_UNDEF": 0 , # Undefined section + "SHN_LORESERVE": 0xff00 , # Start of reserved indices + "SHN_LOPROC": 0xff00 , # Start of processor-specific + "SHN_BEFORE": 0xff00 , # Order section before all others + "SHN_AFTER": 0xff01 , # Order section after all others + "SHN_HIPROC": 0xff1f , # End of processor-specific + "SHN_LOOS": 0xff20 , # Start of OS-specific + "SHN_HIOS": 0xff3f , # End of OS-specific + "SHN_ABS": 0xfff1 , # Associated symbol is absolute + "SHN_COMMON": 0xfff2 , # Associated symbol is common + "SHN_XINDEX": 0xffff , # Index is in extra table. + "SHN_HIRESERVE": 0xffff , # End of reserved indices + "SHT_NULL": 0 , # Section header table entry unused + "SHT_PROGBITS": 1 , # Program data + "SHT_SYMTAB": 2 , # Symbol table + "SHT_STRTAB": 3 , # String table + "SHT_RELA": 4 , # Relocation entries with addends + "SHT_HASH": 5 , # Symbol hash table + "SHT_DYNAMIC": 6 , # Dynamic linking information + "SHT_NOTE": 7 , # Notes + "SHT_NOBITS": 8 , # Program space with no data (bss) + "SHT_REL": 9 , # Relocation entries, no addends + "SHT_SHLIB": 10 , # Reserved + "SHT_DYNSYM": 11 , # Dynamic linker symbol table + "SHT_INIT_ARRAY": 14 , # Array of constructors + "SHT_FINI_ARRAY": 15 , # Array of destructors + "SHT_PREINIT_ARRAY": 16 , # Array of pre-constructors + "SHT_GROUP": 17 , # Section group + "SHT_SYMTAB_SHNDX": 18 , # Extended section indeces + "SHT_NUM": 19 , # Number of defined types. + "SHT_LOOS": 0x60000000 , # Start OS-specific. + "SHT_GNU_ATTRIBUTES": 0x6ffffff5 , # Object attributes. + "SHT_GNU_HASH": 0x6ffffff6 , # GNU-style hash table. + "SHT_GNU_LIBLIST": 0x6ffffff7 , # Prelink library list + "SHT_CHECKSUM": 0x6ffffff8 , # Checksum for DSO content. + "SHT_LOSUNW": 0x6ffffffa , # Sun-specific low bound. + "SHT_SUNW_move": 0x6ffffffa , # + "SHT_SUNW_COMDAT": 0x6ffffffb , # + "SHT_SUNW_syminfo": 0x6ffffffc , # + "SHT_GNU_verdef": 0x6ffffffd , # Version definition section. + "SHT_GNU_verneed": 0x6ffffffe , # Version needs section. + "SHT_GNU_versym": 0x6fffffff , # Version symbol table. + "SHT_HISUNW": 0x6fffffff , # Sun-specific high bound. + "SHT_HIOS": 0x6fffffff , # End OS-specific type + "SHT_LOPROC": 0x70000000 , # Start of processor-specific + "SHT_HIPROC": 0x7fffffff , # End of processor-specific + "SHT_LOUSER": 0x80000000 , # Start of application-specific + "SHT_HIUSER": 0x8fffffff , # End of application-specific + "SHF_MASKOS": 0x0ff00000 , # OS-specific. + "SHF_MASKPROC": 0xf0000000 , # Processor-specific + "SHF_ORDERED": (1 << 30) , # Special ordering requirement + "SHF_EXCLUDE": (1 << 31) , # Section is excluded unless + "GRP_COMDAT": 0x1 , # Mark group as COMDAT. + "SYMINFO_BT_SELF": 0xffff , # Symbol bound to self + "SYMINFO_BT_PARENT": 0xfffe , # Symbol bound to parent + "SYMINFO_BT_LOWRESERVE": 0xff00 , # Beginning of reserved entries + "SYMINFO_FLG_DIRECT": 0x0001 , # Direct bound symbol + "SYMINFO_FLG_PASSTHRU": 0x0002 , # Pass-thru symbol for translator + "SYMINFO_FLG_COPY": 0x0004 , # Symbol is a copy-reloc + "SYMINFO_FLG_LAZYLOAD": 0x0008 , # Symbol bound to object to be lazy + "SYMINFO_NONE": 0 , # + "SYMINFO_CURRENT": 1 , # + "SYMINFO_NUM": 2 , # + "STB_LOCAL": 0 , # Local symbol + "STB_GLOBAL": 1 , # Global symbol + "STB_WEAK": 2 , # Weak symbol + "STB_NUM": 3 , # Number of defined types. + "STB_LOOS": 10 , # Start of OS-specific + "STB_GNU_UNIQUE": 10 , # Unique symbol. + "STB_HIOS": 12 , # End of OS-specific + "STB_LOPROC": 13 , # Start of processor-specific + "STB_HIPROC": 15 , # End of processor-specific + "STT_NOTYPE": 0 , # Symbol type is unspecified + "STT_OBJECT": 1 , # Symbol is a data object + "STT_FUNC": 2 , # Symbol is a code object + "STT_SECTION": 3 , # Symbol associated with a section + "STT_FILE": 4 , # Symbol's name is file name + "STT_COMMON": 5 , # Symbol is a common data object + "STT_TLS": 6 , # Symbol is thread-local data object + "STT_NUM": 7 , # Number of defined types. + "STT_LOOS": 10 , # Start of OS-specific + "STT_GNU_IFUNC": 10 , # Symbol is indirect code object + "STT_HIOS": 12 , # End of OS-specific + "STT_LOPROC": 13 , # Start of processor-specific + "STT_HIPROC": 15 , # End of processor-specific + "STN_UNDEF": 0 , # End of a chain. + "STV_DEFAULT": 0 , # Default symbol visibility rules + "STV_INTERNAL": 1 , # Processor specific hidden class + "STV_HIDDEN": 2 , # Sym unavailable in other modules + "STV_PROTECTED": 3 , # Not preemptible, not exported + "PN_XNUM": 0xffff , # + "PT_NULL": 0 , # Program header table entry unused + "PT_LOAD": 1 , # Loadable program segment + "PT_DYNAMIC": 2 , # Dynamic linking information + "PT_INTERP": 3 , # Program interpreter + "PT_NOTE": 4 , # Auxiliary information + "PT_SHLIB": 5 , # Reserved + "PT_PHDR": 6 , # Entry for header table itself + "PT_TLS": 7 , # Thread-local storage segment + "PT_NUM": 8 , # Number of defined types + "PT_LOOS": 0x60000000 , # Start of OS-specific + "PT_GNU_EH_FRAME": 0x6474e550 , # GCC .eh_frame_hdr segment + "PT_GNU_STACK": 0x6474e551 , # Indicates stack executability + "PT_GNU_RELRO": 0x6474e552 , # Read-only after relocation + "PT_LOSUNW": 0x6ffffffa , # + "PT_SUNWBSS": 0x6ffffffa , # Sun Specific segment + "PT_SUNWSTACK": 0x6ffffffb , # Stack segment + "PT_HISUNW": 0x6fffffff , # + "PT_HIOS": 0x6fffffff , # End of OS-specific + "PT_LOPROC": 0x70000000 , # Start of processor-specific + "PT_HIPROC": 0x7fffffff , # End of processor-specific + "PF_X": (1 << 0) , # Segment is executable + "PF_W": (1 << 1) , # Segment is writable + "PF_R": (1 << 2) , # Segment is readable + "PF_MASKOS": 0x0ff00000 , # OS-specific + "PF_MASKPROC": 0xf0000000 , # Processor-specific + "NT_PRSTATUS": 1 , # Contains copy of prstatus struct + "NT_FPREGSET": 2 , # Contains copy of fpregset struct + "NT_PRPSINFO": 3 , # Contains copy of prpsinfo struct + "NT_PRXREG": 4 , # Contains copy of prxregset struct + "NT_TASKSTRUCT": 4 , # Contains copy of task structure + "NT_PLATFORM": 5 , # String from sysinfo(SI_PLATFORM) + "NT_AUXV": 6 , # Contains copy of auxv array + "NT_GWINDOWS": 7 , # Contains copy of gwindows struct + "NT_ASRS": 8 , # Contains copy of asrset struct + "NT_PSTATUS": 10 , # Contains copy of pstatus struct + "NT_PSINFO": 13 , # Contains copy of psinfo struct + "NT_PRCRED": 14 , # Contains copy of prcred struct + "NT_UTSNAME": 15 , # Contains copy of utsname struct + "NT_LWPSTATUS": 16 , # Contains copy of lwpstatus struct + "NT_LWPSINFO": 17 , # Contains copy of lwpinfo struct + "NT_PRFPXREG": 20 , # Contains copy of fprxregset struct + "NT_PRXFPREG": 0x46e62b7f , # Contains copy of user_fxsr_struct + "NT_PPC_VMX": 0x100 , # PowerPC Altivec/VMX registers + "NT_PPC_SPE": 0x101 , # PowerPC SPE/EVR registers + "NT_PPC_VSX": 0x102 , # PowerPC VSX registers + "NT_386_TLS": 0x200 , # i386 TLS slots (struct user_desc) + "NT_386_IOPERM": 0x201 , # x86 io permission bitmap (1=deny) + "NT_X86_XSTATE": 0x202 , # x86 extended state using xsave + "NT_VERSION": 1 , # Contains a version string. + "DT_NULL": 0 , # Marks end of dynamic section + "DT_NEEDED": 1 , # Name of needed library + "DT_PLTRELSZ": 2 , # Size in bytes of PLT relocs + "DT_PLTGOT": 3 , # Processor defined value + "DT_HASH": 4 , # Address of symbol hash table + "DT_STRTAB": 5 , # Address of string table + "DT_SYMTAB": 6 , # Address of symbol table + "DT_RELA": 7 , # Address of Rela relocs + "DT_RELASZ": 8 , # Total size of Rela relocs + "DT_RELAENT": 9 , # Size of one Rela reloc + "DT_STRSZ": 10 , # Size of string table + "DT_SYMENT": 11 , # Size of one symbol table entry + "DT_INIT": 12 , # Address of init function + "DT_FINI": 13 , # Address of termination function + "DT_SONAME": 14 , # Name of shared object + "DT_RPATH": 15 , # Library search path (deprecated) + "DT_SYMBOLIC": 16 , # Start symbol search here + "DT_REL": 17 , # Address of Rel relocs + "DT_RELSZ": 18 , # Total size of Rel relocs + "DT_RELENT": 19 , # Size of one Rel reloc + "DT_PLTREL": 20 , # Type of reloc in PLT + "DT_DEBUG": 21 , # For debugging; unspecified + "DT_TEXTREL": 22 , # Reloc might modify .text + "DT_JMPREL": 23 , # Address of PLT relocs + "DT_BIND_NOW": 24 , # Process relocations of object + "DT_INIT_ARRAY": 25 , # Array with addresses of init fct + "DT_FINI_ARRAY": 26 , # Array with addresses of fini fct + "DT_INIT_ARRAYSZ": 27 , # Size in bytes of DT_INIT_ARRAY + "DT_FINI_ARRAYSZ": 28 , # Size in bytes of DT_FINI_ARRAY + "DT_RUNPATH": 29 , # Library search path + "DT_FLAGS": 30 , # Flags for the object being loaded + "DT_ENCODING": 32 , # Start of encoded range + "DT_PREINIT_ARRAY": 32 , # Array with addresses of preinit fct + "DT_PREINIT_ARRAYSZ": 33 , # size in bytes of DT_PREINIT_ARRAY + "DT_NUM": 34 , # Number used + "DT_LOOS": 0x6000000d , # Start of OS-specific + "DT_HIOS": 0x6ffff000 , # End of OS-specific + "DT_LOPROC": 0x70000000 , # Start of processor-specific + "DT_HIPROC": 0x7fffffff , # End of processor-specific + "DT_PROCNUM": MacroRef("DT_MIPS_NUM") , # Most used by any processor + "DT_VALRNGLO": 0x6ffffd00 , # + "DT_GNU_PRELINKED": 0x6ffffdf5 , # Prelinking timestamp + "DT_GNU_CONFLICTSZ": 0x6ffffdf6 , # Size of conflict section + "DT_GNU_LIBLISTSZ": 0x6ffffdf7 , # Size of library list + "DT_CHECKSUM": 0x6ffffdf8 , # + "DT_PLTPADSZ": 0x6ffffdf9 , # + "DT_MOVEENT": 0x6ffffdfa , # + "DT_MOVESZ": 0x6ffffdfb , # + "DT_FEATURE_1": 0x6ffffdfc , # Feature selection (DTF_*). + "DT_POSFLAG_1": 0x6ffffdfd , # Flags for DT_* entries, effecting + "DT_SYMINSZ": 0x6ffffdfe , # Size of syminfo table (in bytes) + "DT_SYMINENT": 0x6ffffdff , # Entry size of syminfo + "DT_VALRNGHI": 0x6ffffdff , # + "DT_VALNUM": 12 , # + "DT_ADDRRNGLO": 0x6ffffe00 , # + "DT_GNU_HASH": 0x6ffffef5 , # GNU-style hash table. + "DT_TLSDESC_PLT": 0x6ffffef6 , # + "DT_TLSDESC_GOT": 0x6ffffef7 , # + "DT_GNU_CONFLICT": 0x6ffffef8 , # Start of conflict section + "DT_GNU_LIBLIST": 0x6ffffef9 , # Library list + "DT_CONFIG": 0x6ffffefa , # Configuration information. + "DT_DEPAUDIT": 0x6ffffefb , # Dependency auditing. + "DT_AUDIT": 0x6ffffefc , # Object auditing. + "DT_PLTPAD": 0x6ffffefd , # PLT padding. + "DT_MOVETAB": 0x6ffffefe , # Move table. + "DT_SYMINFO": 0x6ffffeff , # Syminfo table. + "DT_ADDRRNGHI": 0x6ffffeff , # + "DT_ADDRNUM": 11 , # + "DT_VERSYM": 0x6ffffff0 , # + "DT_RELACOUNT": 0x6ffffff9 , # + "DT_RELCOUNT": 0x6ffffffa , # + "DT_FLAGS_1": 0x6ffffffb , # State flags, see DF_1_* below. + "DT_VERDEF": 0x6ffffffc , # Address of version definition + "DT_VERDEFNUM": 0x6ffffffd , # Number of version definitions + "DT_VERNEED": 0x6ffffffe , # Address of table with needed + "DT_VERNEEDNUM": 0x6fffffff , # Number of needed versions + "DT_VERSIONTAGNUM": 16 , # + "DT_AUXILIARY": 0x7ffffffd , # Shared object to load before self + "DT_FILTER": 0x7fffffff , # Shared object to get values from + "DT_EXTRANUM": 3 , # + "DF_ORIGIN": 0x00000001 , # Object may use DF_ORIGIN + "DF_SYMBOLIC": 0x00000002 , # Symbol resolutions starts here + "DF_TEXTREL": 0x00000004 , # Object contains text relocations + "DF_BIND_NOW": 0x00000008 , # No lazy binding for this object + "DF_STATIC_TLS": 0x00000010 , # Module uses the static TLS model + "DF_1_NOW": 0x00000001 , # Set RTLD_NOW for this object. + "DF_1_GLOBAL": 0x00000002 , # Set RTLD_GLOBAL for this object. + "DF_1_GROUP": 0x00000004 , # Set RTLD_GROUP for this object. + "DF_1_NODELETE": 0x00000008 , # Set RTLD_NODELETE for this object. + "DF_1_LOADFLTR": 0x00000010 , # Trigger filtee loading at runtime. + "DF_1_INITFIRST": 0x00000020 , # Set RTLD_INITFIRST for this object + "DF_1_NOOPEN": 0x00000040 , # Set RTLD_NOOPEN for this object. + "DF_1_ORIGIN": 0x00000080 , # $ORIGIN must be handled. + "DF_1_DIRECT": 0x00000100 , # Direct binding enabled. + "DF_1_TRANS": 0x00000200 , # + "DF_1_INTERPOSE": 0x00000400 , # Object is used to interpose. + "DF_1_NODEFLIB": 0x00000800 , # Ignore default lib search path. + "DF_1_NODUMP": 0x00001000 , # Object can't be dldump'ed. + "DF_1_CONFALT": 0x00002000 , # Configuration alternative created. + "DF_1_ENDFILTEE": 0x00004000 , # Filtee terminates filters search. + "DF_1_DISPRELDNE": 0x00008000 , # Disp reloc applied at build time. + "DF_1_DISPRELPND": 0x00010000 , # Disp reloc applied at run-time. + "DTF_1_PARINIT": 0x00000001 , # + "DTF_1_CONFEXP": 0x00000002 , # + "DF_P1_LAZYLOAD": 0x00000001 , # Lazyload following object. + "DF_P1_GROUPPERM": 0x00000002 , # Symbols from next object are not + "VER_DEF_NONE": 0 , # No version + "VER_DEF_CURRENT": 1 , # Current version + "VER_DEF_NUM": 2 , # Given version number + "VER_FLG_BASE": 0x1 , # Version definition of file itself + "VER_FLG_WEAK": 0x2 , # Weak version identifier + "VER_NDX_LOCAL": 0 , # Symbol is local. + "VER_NDX_GLOBAL": 1 , # Symbol is global. + "VER_NDX_LORESERVE": 0xff00 , # Beginning of reserved entries. + "VER_NDX_ELIMINATE": 0xff01 , # Symbol is to be eliminated. + "VER_NEED_NONE": 0 , # No version + "VER_NEED_CURRENT": 1 , # Current version + "VER_NEED_NUM": 2 , # Given version number + "VER_FLG_WEAK": 0x2 , # Weak version identifier + "AT_NULL": 0 , # End of vector + "AT_IGNORE": 1 , # Entry should be ignored + "AT_EXECFD": 2 , # File descriptor of program + "AT_PHDR": 3 , # Program headers for program + "AT_PHENT": 4 , # Size of program header entry + "AT_PHNUM": 5 , # Number of program headers + "AT_PAGESZ": 6 , # System page size + "AT_BASE": 7 , # Base address of interpreter + "AT_FLAGS": 8 , # Flags + "AT_ENTRY": 9 , # Entry point of program + "AT_NOTELF": 10 , # Program is not ELF + "AT_UID": 11 , # Real uid + "AT_EUID": 12 , # Effective uid + "AT_GID": 13 , # Real gid + "AT_EGID": 14 , # Effective gid + "AT_CLKTCK": 17 , # Frequency of times() + "AT_PLATFORM": 15 , # String identifying platform. + "AT_HWCAP": 16 , # Machine dependent hints about + "AT_FPUCW": 18 , # Used FPU control word. + "AT_DCACHEBSIZE": 19 , # Data cache block size. + "AT_ICACHEBSIZE": 20 , # Instruction cache block size. + "AT_UCACHEBSIZE": 21 , # Unified cache block size. + "AT_IGNOREPPC": 22 , # Entry should be ignored. + "AT_SECURE": 23 , # Boolean, was exec setuid-like? + "AT_BASE_PLATFORM": 24 , # String identifying real platforms. + "AT_RANDOM": 25 , # Address of 16 random bytes. + "AT_EXECFN": 31 , # Filename of executable. + "AT_SYSINFO": 32 , # + "AT_SYSINFO_EHDR": 33 , # + "AT_L1I_CACHESHAPE": 34 , # + "AT_L1D_CACHESHAPE": 35 , # + "AT_L2_CACHESHAPE": 36 , # + "AT_L3_CACHESHAPE": 37 , # + "ELF_NOTE_SOLARIS": "SUNW Solaris" , # + "ELF_NOTE_GNU": "GNU" , # + "ELF_NOTE_PAGESIZE_HINT": 1 , # + "NT_GNU_ABI_TAG": 1 , # + "ELF_NOTE_ABI": MacroRef("NT_GNU_ABI_TAG") , # Old name. + "ELF_NOTE_OS_LINUX": 0 , # + "ELF_NOTE_OS_GNU": 1 , # + "ELF_NOTE_OS_SOLARIS2": 2 , # + "ELF_NOTE_OS_FREEBSD": 3 , # + "NT_GNU_HWCAP": 2 , # + "NT_GNU_BUILD_ID": 3 , # + "NT_GNU_GOLD_VERSION": 4 , # + "EF_CPU32": 0x00810000 , # + "R_68K_NONE": 0 , # No reloc + "R_68K_32": 1 , # Direct 32 bit + "R_68K_16": 2 , # Direct 16 bit + "R_68K_8": 3 , # Direct 8 bit + "R_68K_PC32": 4 , # PC relative 32 bit + "R_68K_PC16": 5 , # PC relative 16 bit + "R_68K_PC8": 6 , # PC relative 8 bit + "R_68K_GOT32": 7 , # 32 bit PC relative GOT entry + "R_68K_GOT16": 8 , # 16 bit PC relative GOT entry + "R_68K_GOT8": 9 , # 8 bit PC relative GOT entry + "R_68K_GOT32O": 10 , # 32 bit GOT offset + "R_68K_GOT16O": 11 , # 16 bit GOT offset + "R_68K_GOT8O": 12 , # 8 bit GOT offset + "R_68K_PLT32": 13 , # 32 bit PC relative PLT address + "R_68K_PLT16": 14 , # 16 bit PC relative PLT address + "R_68K_PLT8": 15 , # 8 bit PC relative PLT address + "R_68K_PLT32O": 16 , # 32 bit PLT offset + "R_68K_PLT16O": 17 , # 16 bit PLT offset + "R_68K_PLT8O": 18 , # 8 bit PLT offset + "R_68K_COPY": 19 , # Copy symbol at runtime + "R_68K_GLOB_DAT": 20 , # Create GOT entry + "R_68K_JMP_SLOT": 21 , # Create PLT entry + "R_68K_RELATIVE": 22 , # Adjust by program base + "R_68K_TLS_GD32": 25 , # 32 bit GOT offset for GD + "R_68K_TLS_GD16": 26 , # 16 bit GOT offset for GD + "R_68K_TLS_GD8": 27 , # 8 bit GOT offset for GD + "R_68K_TLS_LDM32": 28 , # 32 bit GOT offset for LDM + "R_68K_TLS_LDM16": 29 , # 16 bit GOT offset for LDM + "R_68K_TLS_LDM8": 30 , # 8 bit GOT offset for LDM + "R_68K_TLS_LDO32": 31 , # 32 bit module-relative offset + "R_68K_TLS_LDO16": 32 , # 16 bit module-relative offset + "R_68K_TLS_LDO8": 33 , # 8 bit module-relative offset + "R_68K_TLS_IE32": 34 , # 32 bit GOT offset for IE + "R_68K_TLS_IE16": 35 , # 16 bit GOT offset for IE + "R_68K_TLS_IE8": 36 , # 8 bit GOT offset for IE + "R_68K_TLS_LE32": 37 , # 32 bit offset relative to + "R_68K_TLS_LE16": 38 , # 16 bit offset relative to + "R_68K_TLS_LE8": 39 , # 8 bit offset relative to + "R_68K_TLS_DTPMOD32": 40 , # 32 bit module number + "R_68K_TLS_DTPREL32": 41 , # 32 bit module-relative offset + "R_68K_TLS_TPREL32": 42 , # 32 bit TP-relative offset + "R_68K_NUM": 43 , # + "R_386_NONE": 0 , # No reloc + "R_386_32": 1 , # Direct 32 bit + "R_386_PC32": 2 , # PC relative 32 bit + "R_386_GOT32": 3 , # 32 bit GOT entry + "R_386_PLT32": 4 , # 32 bit PLT address + "R_386_COPY": 5 , # Copy symbol at runtime + "R_386_GLOB_DAT": 6 , # Create GOT entry + "R_386_JMP_SLOT": 7 , # Create PLT entry + "R_386_RELATIVE": 8 , # Adjust by program base + "R_386_GOTOFF": 9 , # 32 bit offset to GOT + "R_386_GOTPC": 10 , # 32 bit PC relative offset to GOT + "R_386_32PLT": 11 , # + "R_386_TLS_TPOFF": 14 , # Offset in static TLS block + "R_386_TLS_IE": 15 , # Address of GOT entry for static TLS + "R_386_TLS_GOTIE": 16 , # GOT entry for static TLS block + "R_386_TLS_LE": 17 , # Offset relative to static TLS + "R_386_TLS_GD": 18 , # Direct 32 bit for GNU version of + "R_386_TLS_LDM": 19 , # Direct 32 bit for GNU version of + "R_386_16": 20 , # + "R_386_PC16": 21 , # + "R_386_8": 22 , # + "R_386_PC8": 23 , # + "R_386_TLS_GD_32": 24 , # Direct 32 bit for general dynamic + "R_386_TLS_GD_PUSH": 25 , # Tag for pushl in GD TLS code + "R_386_TLS_GD_CALL": 26 , # Relocation for call to + "R_386_TLS_GD_POP": 27 , # Tag for popl in GD TLS code + "R_386_TLS_LDM_32": 28 , # Direct 32 bit for local dynamic + "R_386_TLS_LDM_PUSH": 29 , # Tag for pushl in LDM TLS code + "R_386_TLS_LDM_CALL": 30 , # Relocation for call to + "R_386_TLS_LDM_POP": 31 , # Tag for popl in LDM TLS code + "R_386_TLS_LDO_32": 32 , # Offset relative to TLS block + "R_386_TLS_IE_32": 33 , # GOT entry for negated static TLS + "R_386_TLS_LE_32": 34 , # Negated offset relative to static + "R_386_TLS_DTPMOD32": 35 , # ID of module containing symbol + "R_386_TLS_DTPOFF32": 36 , # Offset in TLS block + "R_386_TLS_TPOFF32": 37 , # Negated offset in static TLS block + "R_386_TLS_GOTDESC": 39 , # GOT offset for TLS descriptor. + "R_386_TLS_DESC_CALL": 40 , # Marker of call through TLS + "R_386_TLS_DESC": 41 , # TLS descriptor containing + "R_386_IRELATIVE": 42 , # Adjust indirectly by program base + "R_386_NUM": 43 , # + "STT_SPARC_REGISTER": 13 , # Global register reserved to app. + "EF_SPARCV9_MM": 3 , # + "EF_SPARCV9_TSO": 0 , # + "EF_SPARCV9_PSO": 1 , # + "EF_SPARCV9_RMO": 2 , # + "EF_SPARC_LEDATA": 0x800000 , # little endian data + "EF_SPARC_EXT_MASK": 0xFFFF00 , # + "EF_SPARC_32PLUS": 0x000100 , # generic V8+ features + "EF_SPARC_SUN_US1": 0x000200 , # Sun UltraSPARC1 extensions + "EF_SPARC_HAL_R1": 0x000400 , # HAL R1 extensions + "EF_SPARC_SUN_US3": 0x000800 , # Sun UltraSPARCIII extensions + "R_SPARC_NONE": 0 , # No reloc + "R_SPARC_8": 1 , # Direct 8 bit + "R_SPARC_16": 2 , # Direct 16 bit + "R_SPARC_32": 3 , # Direct 32 bit + "R_SPARC_DISP8": 4 , # PC relative 8 bit + "R_SPARC_DISP16": 5 , # PC relative 16 bit + "R_SPARC_DISP32": 6 , # PC relative 32 bit + "R_SPARC_WDISP30": 7 , # PC relative 30 bit shifted + "R_SPARC_WDISP22": 8 , # PC relative 22 bit shifted + "R_SPARC_HI22": 9 , # High 22 bit + "R_SPARC_22": 10 , # Direct 22 bit + "R_SPARC_13": 11 , # Direct 13 bit + "R_SPARC_LO10": 12 , # Truncated 10 bit + "R_SPARC_GOT10": 13 , # Truncated 10 bit GOT entry + "R_SPARC_GOT13": 14 , # 13 bit GOT entry + "R_SPARC_GOT22": 15 , # 22 bit GOT entry shifted + "R_SPARC_PC10": 16 , # PC relative 10 bit truncated + "R_SPARC_PC22": 17 , # PC relative 22 bit shifted + "R_SPARC_WPLT30": 18 , # 30 bit PC relative PLT address + "R_SPARC_COPY": 19 , # Copy symbol at runtime + "R_SPARC_GLOB_DAT": 20 , # Create GOT entry + "R_SPARC_JMP_SLOT": 21 , # Create PLT entry + "R_SPARC_RELATIVE": 22 , # Adjust by program base + "R_SPARC_UA32": 23 , # Direct 32 bit unaligned + "R_SPARC_PLT32": 24 , # Direct 32 bit ref to PLT entry + "R_SPARC_HIPLT22": 25 , # High 22 bit PLT entry + "R_SPARC_LOPLT10": 26 , # Truncated 10 bit PLT entry + "R_SPARC_PCPLT32": 27 , # PC rel 32 bit ref to PLT entry + "R_SPARC_PCPLT22": 28 , # PC rel high 22 bit PLT entry + "R_SPARC_PCPLT10": 29 , # PC rel trunc 10 bit PLT entry + "R_SPARC_10": 30 , # Direct 10 bit + "R_SPARC_11": 31 , # Direct 11 bit + "R_SPARC_64": 32 , # Direct 64 bit + "R_SPARC_OLO10": 33 , # 10bit with secondary 13bit addend + "R_SPARC_HH22": 34 , # Top 22 bits of direct 64 bit + "R_SPARC_HM10": 35 , # High middle 10 bits of ... + "R_SPARC_LM22": 36 , # Low middle 22 bits of ... + "R_SPARC_PC_HH22": 37 , # Top 22 bits of pc rel 64 bit + "R_SPARC_PC_HM10": 38 , # High middle 10 bit of ... + "R_SPARC_PC_LM22": 39 , # Low miggle 22 bits of ... + "R_SPARC_WDISP16": 40 , # PC relative 16 bit shifted + "R_SPARC_WDISP19": 41 , # PC relative 19 bit shifted + "R_SPARC_GLOB_JMP": 42 , # was part of v9 ABI but was removed + "R_SPARC_7": 43 , # Direct 7 bit + "R_SPARC_5": 44 , # Direct 5 bit + "R_SPARC_6": 45 , # Direct 6 bit + "R_SPARC_DISP64": 46 , # PC relative 64 bit + "R_SPARC_PLT64": 47 , # Direct 64 bit ref to PLT entry + "R_SPARC_HIX22": 48 , # High 22 bit complemented + "R_SPARC_LOX10": 49 , # Truncated 11 bit complemented + "R_SPARC_H44": 50 , # Direct high 12 of 44 bit + "R_SPARC_M44": 51 , # Direct mid 22 of 44 bit + "R_SPARC_L44": 52 , # Direct low 10 of 44 bit + "R_SPARC_REGISTER": 53 , # Global register usage + "R_SPARC_UA64": 54 , # Direct 64 bit unaligned + "R_SPARC_UA16": 55 , # Direct 16 bit unaligned + "R_SPARC_TLS_GD_HI22": 56 , # + "R_SPARC_TLS_GD_LO10": 57 , # + "R_SPARC_TLS_GD_ADD": 58 , # + "R_SPARC_TLS_GD_CALL": 59 , # + "R_SPARC_TLS_LDM_HI22": 60 , # + "R_SPARC_TLS_LDM_LO10": 61 , # + "R_SPARC_TLS_LDM_ADD": 62 , # + "R_SPARC_TLS_LDM_CALL": 63 , # + "R_SPARC_TLS_LDO_HIX22": 64 , # + "R_SPARC_TLS_LDO_LOX10": 65 , # + "R_SPARC_TLS_LDO_ADD": 66 , # + "R_SPARC_TLS_IE_HI22": 67 , # + "R_SPARC_TLS_IE_LO10": 68 , # + "R_SPARC_TLS_IE_LD": 69 , # + "R_SPARC_TLS_IE_LDX": 70 , # + "R_SPARC_TLS_IE_ADD": 71 , # + "R_SPARC_TLS_LE_HIX22": 72 , # + "R_SPARC_TLS_LE_LOX10": 73 , # + "R_SPARC_TLS_DTPMOD32": 74 , # + "R_SPARC_TLS_DTPMOD64": 75 , # + "R_SPARC_TLS_DTPOFF32": 76 , # + "R_SPARC_TLS_DTPOFF64": 77 , # + "R_SPARC_TLS_TPOFF32": 78 , # + "R_SPARC_TLS_TPOFF64": 79 , # + "R_SPARC_GOTDATA_HIX22": 80 , # + "R_SPARC_GOTDATA_LOX10": 81 , # + "R_SPARC_GOTDATA_OP_HIX22": 82 , # + "R_SPARC_GOTDATA_OP_LOX10": 83 , # + "R_SPARC_GOTDATA_OP": 84 , # + "R_SPARC_H34": 85 , # + "R_SPARC_SIZE32": 86 , # + "R_SPARC_SIZE64": 87 , # + "R_SPARC_JMP_IREL": 248 , # + "R_SPARC_IRELATIVE": 249 , # + "R_SPARC_GNU_VTINHERIT": 250 , # + "R_SPARC_GNU_VTENTRY": 251 , # + "R_SPARC_REV32": 252 , # + "R_SPARC_NUM": 253 , # + "DT_SPARC_REGISTER": 0x70000001 , # + "DT_SPARC_NUM": 2 , # + "EF_MIPS_NOREORDER": 1 , # A .noreorder directive was used + "EF_MIPS_PIC": 2 , # Contains PIC code + "EF_MIPS_CPIC": 4 , # Uses PIC calling sequence + "EF_MIPS_XGOT": 8 , # + "EF_MIPS_64BIT_WHIRL": 16 , # + "EF_MIPS_ABI2": 32 , # + "EF_MIPS_ABI_ON32": 64 , # + "EF_MIPS_ARCH": 0xf0000000 , # MIPS architecture level + "EF_MIPS_ARCH_1": 0x00000000 , # -mips1 code. + "EF_MIPS_ARCH_2": 0x10000000 , # -mips2 code. + "EF_MIPS_ARCH_3": 0x20000000 , # -mips3 code. + "EF_MIPS_ARCH_4": 0x30000000 , # -mips4 code. + "EF_MIPS_ARCH_5": 0x40000000 , # -mips5 code. + "EF_MIPS_ARCH_32": 0x60000000 , # MIPS32 code. + "EF_MIPS_ARCH_64": 0x70000000 , # MIPS64 code. + "E_MIPS_ARCH_1": 0x00000000 , # -mips1 code. + "E_MIPS_ARCH_2": 0x10000000 , # -mips2 code. + "E_MIPS_ARCH_3": 0x20000000 , # -mips3 code. + "E_MIPS_ARCH_4": 0x30000000 , # -mips4 code. + "E_MIPS_ARCH_5": 0x40000000 , # -mips5 code. + "E_MIPS_ARCH_32": 0x60000000 , # MIPS32 code. + "E_MIPS_ARCH_64": 0x70000000 , # MIPS64 code. + "SHN_MIPS_ACOMMON": 0xff00 , # Allocated common symbols + "SHN_MIPS_TEXT": 0xff01 , # Allocated test symbols. + "SHN_MIPS_DATA": 0xff02 , # Allocated data symbols. + "SHN_MIPS_SCOMMON": 0xff03 , # Small common symbols + "SHN_MIPS_SUNDEFINED": 0xff04 , # Small undefined symbols + "SHT_MIPS_LIBLIST": 0x70000000 , # Shared objects used in link + "SHT_MIPS_MSYM": 0x70000001 , # + "SHT_MIPS_CONFLICT": 0x70000002 , # Conflicting symbols + "SHT_MIPS_GPTAB": 0x70000003 , # Global data area sizes + "SHT_MIPS_UCODE": 0x70000004 , # Reserved for SGI/MIPS compilers + "SHT_MIPS_DEBUG": 0x70000005 , # MIPS ECOFF debugging information + "SHT_MIPS_REGINFO": 0x70000006 , # Register usage information + "SHT_MIPS_PACKAGE": 0x70000007 , # + "SHT_MIPS_PACKSYM": 0x70000008 , # + "SHT_MIPS_RELD": 0x70000009 , # + "SHT_MIPS_IFACE": 0x7000000b , # + "SHT_MIPS_CONTENT": 0x7000000c , # + "SHT_MIPS_OPTIONS": 0x7000000d , # Miscellaneous options. + "SHT_MIPS_SHDR": 0x70000010 , # + "SHT_MIPS_FDESC": 0x70000011 , # + "SHT_MIPS_EXTSYM": 0x70000012 , # + "SHT_MIPS_DENSE": 0x70000013 , # + "SHT_MIPS_PDESC": 0x70000014 , # + "SHT_MIPS_LOCSYM": 0x70000015 , # + "SHT_MIPS_AUXSYM": 0x70000016 , # + "SHT_MIPS_OPTSYM": 0x70000017 , # + "SHT_MIPS_LOCSTR": 0x70000018 , # + "SHT_MIPS_LINE": 0x70000019 , # + "SHT_MIPS_RFDESC": 0x7000001a , # + "SHT_MIPS_DELTASYM": 0x7000001b , # + "SHT_MIPS_DELTAINST": 0x7000001c , # + "SHT_MIPS_DELTACLASS": 0x7000001d , # + "SHT_MIPS_DWARF": 0x7000001e , # DWARF debugging information. + "SHT_MIPS_DELTADECL": 0x7000001f , # + "SHT_MIPS_SYMBOL_LIB": 0x70000020 , # + "SHT_MIPS_EVENTS": 0x70000021 , # Event section. + "SHT_MIPS_TRANSLATE": 0x70000022 , # + "SHT_MIPS_PIXIE": 0x70000023 , # + "SHT_MIPS_XLATE": 0x70000024 , # + "SHT_MIPS_XLATE_DEBUG": 0x70000025 , # + "SHT_MIPS_WHIRL": 0x70000026 , # + "SHT_MIPS_EH_REGION": 0x70000027 , # + "SHT_MIPS_XLATE_OLD": 0x70000028 , # + "SHT_MIPS_PDR_EXCEPTION": 0x70000029 , # + "SHF_MIPS_GPREL": 0x10000000 , # Must be part of global data area + "SHF_MIPS_MERGE": 0x20000000 , # + "SHF_MIPS_ADDR": 0x40000000 , # + "SHF_MIPS_STRINGS": 0x80000000 , # + "SHF_MIPS_NOSTRIP": 0x08000000 , # + "SHF_MIPS_LOCAL": 0x04000000 , # + "SHF_MIPS_NAMES": 0x02000000 , # + "SHF_MIPS_NODUPE": 0x01000000 , # + "STO_MIPS_DEFAULT": 0x0 , # + "STO_MIPS_INTERNAL": 0x1 , # + "STO_MIPS_HIDDEN": 0x2 , # + "STO_MIPS_PROTECTED": 0x3 , # + "STO_MIPS_PLT": 0x8 , # + "STO_MIPS_SC_ALIGN_UNUSED": 0xff , # + "STB_MIPS_SPLIT_COMMON": 13 , # + "ODK_NULL": 0 , # Undefined. + "ODK_REGINFO": 1 , # Register usage information. + "ODK_EXCEPTIONS": 2 , # Exception processing options. + "ODK_PAD": 3 , # Section padding options. + "ODK_HWPATCH": 4 , # Hardware workarounds performed + "ODK_FILL": 5 , # record the fill value used by the linker. + "ODK_TAGS": 6 , # reserve space for desktop tools to write. + "ODK_HWAND": 7 , # HW workarounds. 'AND' bits when merging. + "ODK_HWOR": 8 , # HW workarounds. 'OR' bits when merging. + "OEX_FPU_MIN": 0x1f , # FPE's which MUST be enabled. + "OEX_FPU_MAX": 0x1f00 , # FPE's which MAY be enabled. + "OEX_PAGE0": 0x10000 , # page zero must be mapped. + "OEX_SMM": 0x20000 , # Force sequential memory mode? + "OEX_FPDBUG": 0x40000 , # Force floating point debug mode? + "OEX_PRECISEFP": MacroRef("OEX_FPDBUG") , # + "OEX_DISMISS": 0x80000 , # Dismiss invalid address faults? + "OEX_FPU_INVAL": 0x10 , # + "OEX_FPU_DIV0": 0x08 , # + "OEX_FPU_OFLO": 0x04 , # + "OEX_FPU_UFLO": 0x02 , # + "OEX_FPU_INEX": 0x01 , # + "OHW_R4KEOP": 0x1 , # R4000 end-of-page patch. + "OHW_R8KPFETCH": 0x2 , # may need R8000 prefetch patch. + "OHW_R5KEOP": 0x4 , # R5000 end-of-page patch. + "OHW_R5KCVTL": 0x8 , # R5000 cvt.[ds].l bug. clean=1. + "OPAD_PREFIX": 0x1 , # + "OPAD_POSTFIX": 0x2 , # + "OPAD_SYMBOL": 0x4 , # + "OHWA0_R4KEOP_CHECKED": 0x00000001 , # + "OHWA1_R4KEOP_CLEAN": 0x00000002 , # + "R_MIPS_NONE": 0 , # No reloc + "R_MIPS_16": 1 , # Direct 16 bit + "R_MIPS_32": 2 , # Direct 32 bit + "R_MIPS_REL32": 3 , # PC relative 32 bit + "R_MIPS_26": 4 , # Direct 26 bit shifted + "R_MIPS_HI16": 5 , # High 16 bit + "R_MIPS_LO16": 6 , # Low 16 bit + "R_MIPS_GPREL16": 7 , # GP relative 16 bit + "R_MIPS_LITERAL": 8 , # 16 bit literal entry + "R_MIPS_GOT16": 9 , # 16 bit GOT entry + "R_MIPS_PC16": 10 , # PC relative 16 bit + "R_MIPS_CALL16": 11 , # 16 bit GOT entry for function + "R_MIPS_GPREL32": 12 , # GP relative 32 bit + "R_MIPS_SHIFT5": 16 , # + "R_MIPS_SHIFT6": 17 , # + "R_MIPS_64": 18 , # + "R_MIPS_GOT_DISP": 19 , # + "R_MIPS_GOT_PAGE": 20 , # + "R_MIPS_GOT_OFST": 21 , # + "R_MIPS_GOT_HI16": 22 , # + "R_MIPS_GOT_LO16": 23 , # + "R_MIPS_SUB": 24 , # + "R_MIPS_INSERT_A": 25 , # + "R_MIPS_INSERT_B": 26 , # + "R_MIPS_DELETE": 27 , # + "R_MIPS_HIGHER": 28 , # + "R_MIPS_HIGHEST": 29 , # + "R_MIPS_CALL_HI16": 30 , # + "R_MIPS_CALL_LO16": 31 , # + "R_MIPS_SCN_DISP": 32 , # + "R_MIPS_REL16": 33 , # + "R_MIPS_ADD_IMMEDIATE": 34 , # + "R_MIPS_PJUMP": 35 , # + "R_MIPS_RELGOT": 36 , # + "R_MIPS_JALR": 37 , # + "R_MIPS_TLS_DTPMOD32": 38 , # Module number 32 bit + "R_MIPS_TLS_DTPREL32": 39 , # Module-relative offset 32 bit + "R_MIPS_TLS_DTPMOD64": 40 , # Module number 64 bit + "R_MIPS_TLS_DTPREL64": 41 , # Module-relative offset 64 bit + "R_MIPS_TLS_GD": 42 , # 16 bit GOT offset for GD + "R_MIPS_TLS_LDM": 43 , # 16 bit GOT offset for LDM + "R_MIPS_TLS_DTPREL_HI16": 44 , # Module-relative offset, high 16 bits + "R_MIPS_TLS_DTPREL_LO16": 45 , # Module-relative offset, low 16 bits + "R_MIPS_TLS_GOTTPREL": 46 , # 16 bit GOT offset for IE + "R_MIPS_TLS_TPREL32": 47 , # TP-relative offset, 32 bit + "R_MIPS_TLS_TPREL64": 48 , # TP-relative offset, 64 bit + "R_MIPS_TLS_TPREL_HI16": 49 , # TP-relative offset, high 16 bits + "R_MIPS_TLS_TPREL_LO16": 50 , # TP-relative offset, low 16 bits + "R_MIPS_GLOB_DAT": 51 , # + "R_MIPS_COPY": 126 , # + "R_MIPS_JUMP_SLOT": 127 , # + "R_MIPS_NUM": 128 , # + "PT_MIPS_REGINFO": 0x70000000 , # Register usage information + "PT_MIPS_RTPROC": 0x70000001 , # Runtime procedure table. + "PT_MIPS_OPTIONS": 0x70000002 , # + "PF_MIPS_LOCAL": 0x10000000 , # + "DT_MIPS_RLD_VERSION": 0x70000001 , # Runtime linker interface version + "DT_MIPS_TIME_STAMP": 0x70000002 , # Timestamp + "DT_MIPS_ICHECKSUM": 0x70000003 , # Checksum + "DT_MIPS_IVERSION": 0x70000004 , # Version string (string tbl index) + "DT_MIPS_FLAGS": 0x70000005 , # Flags + "DT_MIPS_BASE_ADDRESS": 0x70000006 , # Base address + "DT_MIPS_MSYM": 0x70000007 , # + "DT_MIPS_CONFLICT": 0x70000008 , # Address of CONFLICT section + "DT_MIPS_LIBLIST": 0x70000009 , # Address of LIBLIST section + "DT_MIPS_LOCAL_GOTNO": 0x7000000a , # Number of local GOT entries + "DT_MIPS_CONFLICTNO": 0x7000000b , # Number of CONFLICT entries + "DT_MIPS_LIBLISTNO": 0x70000010 , # Number of LIBLIST entries + "DT_MIPS_SYMTABNO": 0x70000011 , # Number of DYNSYM entries + "DT_MIPS_UNREFEXTNO": 0x70000012 , # First external DYNSYM + "DT_MIPS_GOTSYM": 0x70000013 , # First GOT entry in DYNSYM + "DT_MIPS_HIPAGENO": 0x70000014 , # Number of GOT page table entries + "DT_MIPS_RLD_MAP": 0x70000016 , # Address of run time loader map. + "DT_MIPS_DELTA_CLASS": 0x70000017 , # Delta C++ class definition. + "DT_MIPS_DELTA_CLASS_NO": 0x70000018 , # Number of entries in + "DT_MIPS_DELTA_INSTANCE": 0x70000019 , # Delta C++ class instances. + "DT_MIPS_DELTA_INSTANCE_NO": 0x7000001a , # Number of entries in + "DT_MIPS_DELTA_RELOC": 0x7000001b , # Delta relocations. + "DT_MIPS_DELTA_RELOC_NO": 0x7000001c , # Number of entries in + "DT_MIPS_DELTA_SYM": 0x7000001d , # Delta symbols that Delta + "DT_MIPS_DELTA_SYM_NO": 0x7000001e , # Number of entries in + "DT_MIPS_DELTA_CLASSSYM": 0x70000020 , # Delta symbols that hold the + "DT_MIPS_DELTA_CLASSSYM_NO": 0x70000021 , # Number of entries in + "DT_MIPS_CXX_FLAGS": 0x70000022 , # Flags indicating for C++ flavor. + "DT_MIPS_PIXIE_INIT": 0x70000023 , # + "DT_MIPS_SYMBOL_LIB": 0x70000024 , # + "DT_MIPS_LOCALPAGE_GOTIDX": 0x70000025 , # + "DT_MIPS_LOCAL_GOTIDX": 0x70000026 , # + "DT_MIPS_HIDDEN_GOTIDX": 0x70000027 , # + "DT_MIPS_PROTECTED_GOTIDX": 0x70000028 , # + "DT_MIPS_OPTIONS": 0x70000029 , # Address of .options. + "DT_MIPS_INTERFACE": 0x7000002a , # Address of .interface. + "DT_MIPS_DYNSTR_ALIGN": 0x7000002b , # + "DT_MIPS_INTERFACE_SIZE": 0x7000002c , # Size of the .interface section. + "DT_MIPS_RLD_TEXT_RESOLVE_ADDR": 0x7000002d , # Address of rld_text_rsolve + "DT_MIPS_PERF_SUFFIX": 0x7000002e , # Default suffix of dso to be added + "DT_MIPS_COMPACT_SIZE": 0x7000002f , # (O32)Size of compact rel section. + "DT_MIPS_GP_VALUE": 0x70000030 , # GP value for aux GOTs. + "DT_MIPS_AUX_DYNAMIC": 0x70000031 , # Address of aux .dynamic. + "DT_MIPS_PLTGOT": 0x70000032 , # + "DT_MIPS_RWPLT": 0x70000034 , # + "DT_MIPS_NUM": 0x35 , # + "RHF_NONE": 0 , # No flags + "RHF_QUICKSTART": (1 << 0) , # Use quickstart + "RHF_NOTPOT": (1 << 1) , # Hash size not power of 2 + "RHF_NO_LIBRARY_REPLACEMENT": (1 << 2) , # Ignore LD_LIBRARY_PATH + "RHF_NO_MOVE": (1 << 3) , # + "RHF_SGI_ONLY": (1 << 4) , # + "RHF_GUARANTEE_INIT": (1 << 5) , # + "RHF_DELTA_C_PLUS_PLUS": (1 << 6) , # + "RHF_GUARANTEE_START_INIT": (1 << 7) , # + "RHF_PIXIE": (1 << 8) , # + "RHF_DEFAULT_DELAY_LOAD": (1 << 9) , # + "RHF_REQUICKSTART": (1 << 10) , # + "RHF_REQUICKSTARTED": (1 << 11) , # + "RHF_CORD": (1 << 12) , # + "RHF_NO_UNRES_UNDEF": (1 << 13) , # + "RHF_RLD_ORDER_SAFE": (1 << 14) , # + "LL_NONE": 0 , # + "LL_EXACT_MATCH": (1 << 0) , # Require exact match + "LL_IGNORE_INT_VER": (1 << 1) , # Ignore interface version + "LL_REQUIRE_MINOR": (1 << 2) , # + "LL_EXPORTS": (1 << 3) , # + "LL_DELAY_LOAD": (1 << 4) , # + "LL_DELTA": (1 << 5) , # + "EF_PARISC_TRAPNIL": 0x00010000 , # Trap nil pointer dereference. + "EF_PARISC_EXT": 0x00020000 , # Program uses arch. extensions. + "EF_PARISC_LSB": 0x00040000 , # Program expects little endian. + "EF_PARISC_WIDE": 0x00080000 , # Program expects wide mode. + "EF_PARISC_NO_KABP": 0x00100000 , # No kernel assisted branch + "EF_PARISC_LAZYSWAP": 0x00400000 , # Allow lazy swapping. + "EF_PARISC_ARCH": 0x0000ffff , # Architecture version. + "EFA_PARISC_1_0": 0x020b , # PA-RISC 1.0 big-endian. + "EFA_PARISC_1_1": 0x0210 , # PA-RISC 1.1 big-endian. + "EFA_PARISC_2_0": 0x0214 , # PA-RISC 2.0 big-endian. + "SHN_PARISC_ANSI_COMMON": 0xff00 , # Section for tenatively declared + "SHN_PARISC_HUGE_COMMON": 0xff01 , # Common blocks in huge model. + "SHT_PARISC_EXT": 0x70000000 , # Contains product specific ext. + "SHT_PARISC_UNWIND": 0x70000001 , # Unwind information. + "SHT_PARISC_DOC": 0x70000002 , # Debug info for optimized code. + "SHF_PARISC_SHORT": 0x20000000 , # Section with short addressing. + "SHF_PARISC_HUGE": 0x40000000 , # Section far from gp. + "SHF_PARISC_SBP": 0x80000000 , # Static branch prediction code. + "STT_PARISC_MILLICODE": 13 , # Millicode function entry point. + "STT_HP_OPAQUE": (MacroRef("STT_LOOS") + 0x1) , # + "STT_HP_STUB": (MacroRef("STT_LOOS") + 0x2) , # + "R_PARISC_NONE": 0 , # No reloc. + "R_PARISC_DIR32": 1 , # Direct 32-bit reference. + "R_PARISC_DIR21L": 2 , # Left 21 bits of eff. address. + "R_PARISC_DIR17R": 3 , # Right 17 bits of eff. address. + "R_PARISC_DIR17F": 4 , # 17 bits of eff. address. + "R_PARISC_DIR14R": 6 , # Right 14 bits of eff. address. + "R_PARISC_PCREL32": 9 , # 32-bit rel. address. + "R_PARISC_PCREL21L": 10 , # Left 21 bits of rel. address. + "R_PARISC_PCREL17R": 11 , # Right 17 bits of rel. address. + "R_PARISC_PCREL17F": 12 , # 17 bits of rel. address. + "R_PARISC_PCREL14R": 14 , # Right 14 bits of rel. address. + "R_PARISC_DPREL21L": 18 , # Left 21 bits of rel. address. + "R_PARISC_DPREL14R": 22 , # Right 14 bits of rel. address. + "R_PARISC_GPREL21L": 26 , # GP-relative, left 21 bits. + "R_PARISC_GPREL14R": 30 , # GP-relative, right 14 bits. + "R_PARISC_LTOFF21L": 34 , # LT-relative, left 21 bits. + "R_PARISC_LTOFF14R": 38 , # LT-relative, right 14 bits. + "R_PARISC_SECREL32": 41 , # 32 bits section rel. address. + "R_PARISC_SEGBASE": 48 , # No relocation, set segment base. + "R_PARISC_SEGREL32": 49 , # 32 bits segment rel. address. + "R_PARISC_PLTOFF21L": 50 , # PLT rel. address, left 21 bits. + "R_PARISC_PLTOFF14R": 54 , # PLT rel. address, right 14 bits. + "R_PARISC_LTOFF_FPTR32": 57 , # 32 bits LT-rel. function pointer. + "R_PARISC_LTOFF_FPTR21L": 58 , # LT-rel. fct ptr, left 21 bits. + "R_PARISC_LTOFF_FPTR14R": 62 , # LT-rel. fct ptr, right 14 bits. + "R_PARISC_FPTR64": 64 , # 64 bits function address. + "R_PARISC_PLABEL32": 65 , # 32 bits function address. + "R_PARISC_PLABEL21L": 66 , # Left 21 bits of fdesc address. + "R_PARISC_PLABEL14R": 70 , # Right 14 bits of fdesc address. + "R_PARISC_PCREL64": 72 , # 64 bits PC-rel. address. + "R_PARISC_PCREL22F": 74 , # 22 bits PC-rel. address. + "R_PARISC_PCREL14WR": 75 , # PC-rel. address, right 14 bits. + "R_PARISC_PCREL14DR": 76 , # PC rel. address, right 14 bits. + "R_PARISC_PCREL16F": 77 , # 16 bits PC-rel. address. + "R_PARISC_PCREL16WF": 78 , # 16 bits PC-rel. address. + "R_PARISC_PCREL16DF": 79 , # 16 bits PC-rel. address. + "R_PARISC_DIR64": 80 , # 64 bits of eff. address. + "R_PARISC_DIR14WR": 83 , # 14 bits of eff. address. + "R_PARISC_DIR14DR": 84 , # 14 bits of eff. address. + "R_PARISC_DIR16F": 85 , # 16 bits of eff. address. + "R_PARISC_DIR16WF": 86 , # 16 bits of eff. address. + "R_PARISC_DIR16DF": 87 , # 16 bits of eff. address. + "R_PARISC_GPREL64": 88 , # 64 bits of GP-rel. address. + "R_PARISC_GPREL14WR": 91 , # GP-rel. address, right 14 bits. + "R_PARISC_GPREL14DR": 92 , # GP-rel. address, right 14 bits. + "R_PARISC_GPREL16F": 93 , # 16 bits GP-rel. address. + "R_PARISC_GPREL16WF": 94 , # 16 bits GP-rel. address. + "R_PARISC_GPREL16DF": 95 , # 16 bits GP-rel. address. + "R_PARISC_LTOFF64": 96 , # 64 bits LT-rel. address. + "R_PARISC_LTOFF14WR": 99 , # LT-rel. address, right 14 bits. + "R_PARISC_LTOFF14DR": 100 , # LT-rel. address, right 14 bits. + "R_PARISC_LTOFF16F": 101 , # 16 bits LT-rel. address. + "R_PARISC_LTOFF16WF": 102 , # 16 bits LT-rel. address. + "R_PARISC_LTOFF16DF": 103 , # 16 bits LT-rel. address. + "R_PARISC_SECREL64": 104 , # 64 bits section rel. address. + "R_PARISC_SEGREL64": 112 , # 64 bits segment rel. address. + "R_PARISC_PLTOFF14WR": 115 , # PLT-rel. address, right 14 bits. + "R_PARISC_PLTOFF14DR": 116 , # PLT-rel. address, right 14 bits. + "R_PARISC_PLTOFF16F": 117 , # 16 bits LT-rel. address. + "R_PARISC_PLTOFF16WF": 118 , # 16 bits PLT-rel. address. + "R_PARISC_PLTOFF16DF": 119 , # 16 bits PLT-rel. address. + "R_PARISC_LTOFF_FPTR64": 120 , # 64 bits LT-rel. function ptr. + "R_PARISC_LTOFF_FPTR14WR": 123 , # LT-rel. fct. ptr., right 14 bits. + "R_PARISC_LTOFF_FPTR14DR": 124 , # LT-rel. fct. ptr., right 14 bits. + "R_PARISC_LTOFF_FPTR16F": 125 , # 16 bits LT-rel. function ptr. + "R_PARISC_LTOFF_FPTR16WF": 126 , # 16 bits LT-rel. function ptr. + "R_PARISC_LTOFF_FPTR16DF": 127 , # 16 bits LT-rel. function ptr. + "R_PARISC_LORESERVE": 128 , # + "R_PARISC_COPY": 128 , # Copy relocation. + "R_PARISC_IPLT": 129 , # Dynamic reloc, imported PLT + "R_PARISC_EPLT": 130 , # Dynamic reloc, exported PLT + "R_PARISC_TPREL32": 153 , # 32 bits TP-rel. address. + "R_PARISC_TPREL21L": 154 , # TP-rel. address, left 21 bits. + "R_PARISC_TPREL14R": 158 , # TP-rel. address, right 14 bits. + "R_PARISC_LTOFF_TP21L": 162 , # LT-TP-rel. address, left 21 bits. + "R_PARISC_LTOFF_TP14R": 166 , # LT-TP-rel. address, right 14 bits. + "R_PARISC_LTOFF_TP14F": 167 , # 14 bits LT-TP-rel. address. + "R_PARISC_TPREL64": 216 , # 64 bits TP-rel. address. + "R_PARISC_TPREL14WR": 219 , # TP-rel. address, right 14 bits. + "R_PARISC_TPREL14DR": 220 , # TP-rel. address, right 14 bits. + "R_PARISC_TPREL16F": 221 , # 16 bits TP-rel. address. + "R_PARISC_TPREL16WF": 222 , # 16 bits TP-rel. address. + "R_PARISC_TPREL16DF": 223 , # 16 bits TP-rel. address. + "R_PARISC_LTOFF_TP64": 224 , # 64 bits LT-TP-rel. address. + "R_PARISC_LTOFF_TP14WR": 227 , # LT-TP-rel. address, right 14 bits. + "R_PARISC_LTOFF_TP14DR": 228 , # LT-TP-rel. address, right 14 bits. + "R_PARISC_LTOFF_TP16F": 229 , # 16 bits LT-TP-rel. address. + "R_PARISC_LTOFF_TP16WF": 230 , # 16 bits LT-TP-rel. address. + "R_PARISC_LTOFF_TP16DF": 231 , # 16 bits LT-TP-rel. address. + "R_PARISC_GNU_VTENTRY": 232 , # + "R_PARISC_GNU_VTINHERIT": 233 , # + "R_PARISC_TLS_GD21L": 234 , # GD 21-bit left. + "R_PARISC_TLS_GD14R": 235 , # GD 14-bit right. + "R_PARISC_TLS_GDCALL": 236 , # GD call to __t_g_a. + "R_PARISC_TLS_LDM21L": 237 , # LD module 21-bit left. + "R_PARISC_TLS_LDM14R": 238 , # LD module 14-bit right. + "R_PARISC_TLS_LDMCALL": 239 , # LD module call to __t_g_a. + "R_PARISC_TLS_LDO21L": 240 , # LD offset 21-bit left. + "R_PARISC_TLS_LDO14R": 241 , # LD offset 14-bit right. + "R_PARISC_TLS_DTPMOD32": 242 , # DTP module 32-bit. + "R_PARISC_TLS_DTPMOD64": 243 , # DTP module 64-bit. + "R_PARISC_TLS_DTPOFF32": 244 , # DTP offset 32-bit. + "R_PARISC_TLS_DTPOFF64": 245 , # DTP offset 32-bit. + "R_PARISC_TLS_LE21L": MacroRef("R_PARISC_TPREL21L"), # + "R_PARISC_TLS_LE14R": MacroRef("R_PARISC_TPREL14R"), # + "R_PARISC_TLS_IE21L": MacroRef("R_PARISC_LTOFF_TP21L") , # + "R_PARISC_TLS_IE14R": MacroRef("R_PARISC_LTOFF_TP14R") , # + "R_PARISC_TLS_TPREL32": MacroRef("R_PARISC_TPREL32") , # + "R_PARISC_TLS_TPREL64": MacroRef("R_PARISC_TPREL64") , # + "R_PARISC_HIRESERVE": 255 , # + "PT_HP_TLS": (MacroRef("PT_LOOS") + 0x0) , # + "PT_HP_CORE_NONE": (MacroRef("PT_LOOS") + 0x1) , # + "PT_HP_CORE_VERSION": (MacroRef("PT_LOOS") + 0x2) , # + "PT_HP_CORE_KERNEL": (MacroRef("PT_LOOS") + 0x3) , # + "PT_HP_CORE_COMM": (MacroRef("PT_LOOS") + 0x4) , # + "PT_HP_CORE_PROC": (MacroRef("PT_LOOS") + 0x5) , # + "PT_HP_CORE_LOADABLE": (MacroRef("PT_LOOS") + 0x6) , # + "PT_HP_CORE_STACK": (MacroRef("PT_LOOS") + 0x7) , # + "PT_HP_CORE_SHM": (MacroRef("PT_LOOS") + 0x8) , # + "PT_HP_CORE_MMF": (MacroRef("PT_LOOS") + 0x9) , # + "PT_HP_PARALLEL": (MacroRef("PT_LOOS") + 0x10) , # + "PT_HP_FASTBIND": (MacroRef("PT_LOOS") + 0x11) , # + "PT_HP_OPT_ANNOT": (MacroRef("PT_LOOS") + 0x12) , # + "PT_HP_HSL_ANNOT": (MacroRef("PT_LOOS") + 0x13) , # + "PT_HP_STACK": (MacroRef("PT_LOOS") + 0x14) , # + "PT_PARISC_ARCHEXT": 0x70000000 , # + "PT_PARISC_UNWIND": 0x70000001 , # + "PF_PARISC_SBP": 0x08000000 , # + "PF_HP_PAGE_SIZE": 0x00100000 , # + "PF_HP_FAR_SHARED": 0x00200000 , # + "PF_HP_NEAR_SHARED": 0x00400000 , # + "PF_HP_CODE": 0x01000000 , # + "PF_HP_MODIFY": 0x02000000 , # + "PF_HP_LAZYSWAP": 0x04000000 , # + "PF_HP_SBP": 0x08000000 , # + "EF_ALPHA_32BIT": 1 , # All addresses must be < 2GB. + "EF_ALPHA_CANRELAX": 2 , # Relocations for relaxing exist. + "SHT_ALPHA_DEBUG": 0x70000001 , # + "SHT_ALPHA_REGINFO": 0x70000002 , # + "SHF_ALPHA_GPREL": 0x10000000 , # + "STO_ALPHA_NOPV": 0x80 , # No PV required. + "STO_ALPHA_STD_GPLOAD": 0x88 , # PV only used for initial ldgp. + "R_ALPHA_NONE": 0 , # No reloc + "R_ALPHA_REFLONG": 1 , # Direct 32 bit + "R_ALPHA_REFQUAD": 2 , # Direct 64 bit + "R_ALPHA_GPREL32": 3 , # GP relative 32 bit + "R_ALPHA_LITERAL": 4 , # GP relative 16 bit w/optimization + "R_ALPHA_LITUSE": 5 , # Optimization hint for LITERAL + "R_ALPHA_GPDISP": 6 , # Add displacement to GP + "R_ALPHA_BRADDR": 7 , # PC+4 relative 23 bit shifted + "R_ALPHA_HINT": 8 , # PC+4 relative 16 bit shifted + "R_ALPHA_SREL16": 9 , # PC relative 16 bit + "R_ALPHA_SREL32": 10 , # PC relative 32 bit + "R_ALPHA_SREL64": 11 , # PC relative 64 bit + "R_ALPHA_GPRELHIGH": 17 , # GP relative 32 bit, high 16 bits + "R_ALPHA_GPRELLOW": 18 , # GP relative 32 bit, low 16 bits + "R_ALPHA_GPREL16": 19 , # GP relative 16 bit + "R_ALPHA_COPY": 24 , # Copy symbol at runtime + "R_ALPHA_GLOB_DAT": 25 , # Create GOT entry + "R_ALPHA_JMP_SLOT": 26 , # Create PLT entry + "R_ALPHA_RELATIVE": 27 , # Adjust by program base + "R_ALPHA_TLS_GD_HI": 28 , # + "R_ALPHA_TLSGD": 29 , # + "R_ALPHA_TLS_LDM": 30 , # + "R_ALPHA_DTPMOD64": 31 , # + "R_ALPHA_GOTDTPREL": 32 , # + "R_ALPHA_DTPREL64": 33 , # + "R_ALPHA_DTPRELHI": 34 , # + "R_ALPHA_DTPRELLO": 35 , # + "R_ALPHA_DTPREL16": 36 , # + "R_ALPHA_GOTTPREL": 37 , # + "R_ALPHA_TPREL64": 38 , # + "R_ALPHA_TPRELHI": 39 , # + "R_ALPHA_TPRELLO": 40 , # + "R_ALPHA_TPREL16": 41 , # + "R_ALPHA_NUM": 46 , # + "LITUSE_ALPHA_ADDR": 0 , # + "LITUSE_ALPHA_BASE": 1 , # + "LITUSE_ALPHA_BYTOFF": 2 , # + "LITUSE_ALPHA_JSR": 3 , # + "LITUSE_ALPHA_TLS_GD": 4 , # + "LITUSE_ALPHA_TLS_LDM": 5 , # + "DT_ALPHA_PLTRO": (MacroRef("DT_LOPROC") + 0) , # + "DT_ALPHA_NUM": 1 , # + "EF_PPC_EMB": 0x80000000 , # PowerPC embedded flag + "EF_PPC_RELOCATABLE": 0x00010000 , # PowerPC -mrelocatable flag + "EF_PPC_RELOCATABLE_LIB": 0x00008000 , # PowerPC -mrelocatable-lib + "R_PPC_NONE": 0 , # + "R_PPC_ADDR32": 1 , # 32bit absolute address + "R_PPC_ADDR24": 2 , # 26bit address, 2 bits ignored. + "R_PPC_ADDR16": 3 , # 16bit absolute address + "R_PPC_ADDR16_LO": 4 , # lower 16bit of absolute address + "R_PPC_ADDR16_HI": 5 , # high 16bit of absolute address + "R_PPC_ADDR16_HA": 6 , # adjusted high 16bit + "R_PPC_ADDR14": 7 , # 16bit address, 2 bits ignored + "R_PPC_ADDR14_BRTAKEN": 8 , # + "R_PPC_ADDR14_BRNTAKEN": 9 , # + "R_PPC_REL24": 10 , # PC relative 26 bit + "R_PPC_REL14": 11 , # PC relative 16 bit + "R_PPC_REL14_BRTAKEN": 12 , # + "R_PPC_REL14_BRNTAKEN": 13 , # + "R_PPC_GOT16": 14 , # + "R_PPC_GOT16_LO": 15 , # + "R_PPC_GOT16_HI": 16 , # + "R_PPC_GOT16_HA": 17 , # + "R_PPC_PLTREL24": 18 , # + "R_PPC_COPY": 19 , # + "R_PPC_GLOB_DAT": 20 , # + "R_PPC_JMP_SLOT": 21 , # + "R_PPC_RELATIVE": 22 , # + "R_PPC_LOCAL24PC": 23 , # + "R_PPC_UADDR32": 24 , # + "R_PPC_UADDR16": 25 , # + "R_PPC_REL32": 26 , # + "R_PPC_PLT32": 27 , # + "R_PPC_PLTREL32": 28 , # + "R_PPC_PLT16_LO": 29 , # + "R_PPC_PLT16_HI": 30 , # + "R_PPC_PLT16_HA": 31 , # + "R_PPC_SDAREL16": 32 , # + "R_PPC_SECTOFF": 33 , # + "R_PPC_SECTOFF_LO": 34 , # + "R_PPC_SECTOFF_HI": 35 , # + "R_PPC_SECTOFF_HA": 36 , # + "R_PPC_TLS": 67 , # none (sym+add)@tls + "R_PPC_DTPMOD32": 68 , # word32 (sym+add)@dtpmod + "R_PPC_TPREL16": 69 , # half16* (sym+add)@tprel + "R_PPC_TPREL16_LO": 70 , # half16 (sym+add)@tprel@l + "R_PPC_TPREL16_HI": 71 , # half16 (sym+add)@tprel@h + "R_PPC_TPREL16_HA": 72 , # half16 (sym+add)@tprel@ha + "R_PPC_TPREL32": 73 , # word32 (sym+add)@tprel + "R_PPC_DTPREL16": 74 , # half16* (sym+add)@dtprel + "R_PPC_DTPREL16_LO": 75 , # half16 (sym+add)@dtprel@l + "R_PPC_DTPREL16_HI": 76 , # half16 (sym+add)@dtprel@h + "R_PPC_DTPREL16_HA": 77 , # half16 (sym+add)@dtprel@ha + "R_PPC_DTPREL32": 78 , # word32 (sym+add)@dtprel + "R_PPC_GOT_TLSGD16": 79 , # half16* (sym+add)@got@tlsgd + "R_PPC_GOT_TLSGD16_LO": 80 , # half16 (sym+add)@got@tlsgd@l + "R_PPC_GOT_TLSGD16_HI": 81 , # half16 (sym+add)@got@tlsgd@h + "R_PPC_GOT_TLSGD16_HA": 82 , # half16 (sym+add)@got@tlsgd@ha + "R_PPC_GOT_TLSLD16": 83 , # half16* (sym+add)@got@tlsld + "R_PPC_GOT_TLSLD16_LO": 84 , # half16 (sym+add)@got@tlsld@l + "R_PPC_GOT_TLSLD16_HI": 85 , # half16 (sym+add)@got@tlsld@h + "R_PPC_GOT_TLSLD16_HA": 86 , # half16 (sym+add)@got@tlsld@ha + "R_PPC_GOT_TPREL16": 87 , # half16* (sym+add)@got@tprel + "R_PPC_GOT_TPREL16_LO": 88 , # half16 (sym+add)@got@tprel@l + "R_PPC_GOT_TPREL16_HI": 89 , # half16 (sym+add)@got@tprel@h + "R_PPC_GOT_TPREL16_HA": 90 , # half16 (sym+add)@got@tprel@ha + "R_PPC_GOT_DTPREL16": 91 , # half16* (sym+add)@got@dtprel + "R_PPC_GOT_DTPREL16_LO": 92 , # half16* (sym+add)@got@dtprel@l + "R_PPC_GOT_DTPREL16_HI": 93 , # half16* (sym+add)@got@dtprel@h + "R_PPC_GOT_DTPREL16_HA": 94 , # half16* (sym+add)@got@dtprel@ha + "R_PPC_EMB_NADDR32": 101 , # + "R_PPC_EMB_NADDR16": 102 , # + "R_PPC_EMB_NADDR16_LO": 103 , # + "R_PPC_EMB_NADDR16_HI": 104 , # + "R_PPC_EMB_NADDR16_HA": 105 , # + "R_PPC_EMB_SDAI16": 106 , # + "R_PPC_EMB_SDA2I16": 107 , # + "R_PPC_EMB_SDA2REL": 108 , # + "R_PPC_EMB_SDA21": 109 , # 16 bit offset in SDA + "R_PPC_EMB_MRKREF": 110 , # + "R_PPC_EMB_RELSEC16": 111 , # + "R_PPC_EMB_RELST_LO": 112 , # + "R_PPC_EMB_RELST_HI": 113 , # + "R_PPC_EMB_RELST_HA": 114 , # + "R_PPC_EMB_BIT_FLD": 115 , # + "R_PPC_EMB_RELSDA": 116 , # 16 bit relative offset in SDA + "R_PPC_DIAB_SDA21_LO": 180 , # like EMB_SDA21, but lower 16 bit + "R_PPC_DIAB_SDA21_HI": 181 , # like EMB_SDA21, but high 16 bit + "R_PPC_DIAB_SDA21_HA": 182 , # like EMB_SDA21, adjusted high 16 + "R_PPC_DIAB_RELSDA_LO": 183 , # like EMB_RELSDA, but lower 16 bit + "R_PPC_DIAB_RELSDA_HI": 184 , # like EMB_RELSDA, but high 16 bit + "R_PPC_DIAB_RELSDA_HA": 185 , # like EMB_RELSDA, adjusted high 16 + "R_PPC_IRELATIVE": 248 , # + "R_PPC_REL16": 249 , # half16 (sym+add-.) + "R_PPC_REL16_LO": 250 , # half16 (sym+add-.)@l + "R_PPC_REL16_HI": 251 , # half16 (sym+add-.)@h + "R_PPC_REL16_HA": 252 , # half16 (sym+add-.)@ha + "R_PPC_TOC16": 255 , # + "DT_PPC_GOT": (MacroRef("DT_LOPROC") + 0) , # + "DT_PPC_NUM": 1 , # + "R_PPC64_NONE": MacroRef("R_PPC_NONE") , # + "R_PPC64_ADDR32": MacroRef("R_PPC_ADDR32") , # 32bit absolute address + "R_PPC64_ADDR24": MacroRef("R_PPC_ADDR24") , # 26bit address, word aligned + "R_PPC64_ADDR16": MacroRef("R_PPC_ADDR16") , # 16bit absolute address + "R_PPC64_ADDR16_LO": MacroRef("R_PPC_ADDR16_LO") , # lower 16bits of address + "R_PPC64_ADDR16_HI": MacroRef("R_PPC_ADDR16_HI") , # high 16bits of address. + "R_PPC64_ADDR16_HA": MacroRef("R_PPC_ADDR16_HA") , # adjusted high 16bits. + "R_PPC64_ADDR14": MacroRef("R_PPC_ADDR14") , # 16bit address, word aligned + "R_PPC64_ADDR14_BRTAKEN": MacroRef("R_PPC_ADDR14_BRTAKEN") , # + "R_PPC64_ADDR14_BRNTAKEN": MacroRef("R_PPC_ADDR14_BRNTAKEN") , # + "R_PPC64_REL24": MacroRef("R_PPC_REL24") , # PC-rel. 26 bit, word aligned + "R_PPC64_REL14": MacroRef("R_PPC_REL14") , # PC relative 16 bit + "R_PPC64_REL14_BRTAKEN": MacroRef("R_PPC_REL14_BRTAKEN") , # + "R_PPC64_REL14_BRNTAKEN": MacroRef("R_PPC_REL14_BRNTAKEN") , # + "R_PPC64_GOT16": MacroRef("R_PPC_GOT16") , # + "R_PPC64_GOT16_LO": MacroRef("R_PPC_GOT16_LO") , # + "R_PPC64_GOT16_HI": MacroRef("R_PPC_GOT16_HI") , # + "R_PPC64_GOT16_HA": MacroRef("R_PPC_GOT16_HA") , # + "R_PPC64_COPY": MacroRef("R_PPC_COPY") , # + "R_PPC64_GLOB_DAT": MacroRef("R_PPC_GLOB_DAT") , # + "R_PPC64_JMP_SLOT": MacroRef("R_PPC_JMP_SLOT") , # + "R_PPC64_RELATIVE": MacroRef("R_PPC_RELATIVE") , # + "R_PPC64_UADDR32": MacroRef("R_PPC_UADDR32") , # + "R_PPC64_UADDR16": MacroRef("R_PPC_UADDR16") , # + "R_PPC64_REL32": MacroRef("R_PPC_REL32") , # + "R_PPC64_PLT32": MacroRef("R_PPC_PLT32") , # + "R_PPC64_PLTREL32": MacroRef("R_PPC_PLTREL32") , # + "R_PPC64_PLT16_LO": MacroRef("R_PPC_PLT16_LO") , # + "R_PPC64_PLT16_HI": MacroRef("R_PPC_PLT16_HI") , # + "R_PPC64_PLT16_HA": MacroRef("R_PPC_PLT16_HA") , # + "R_PPC64_SECTOFF": MacroRef("R_PPC_SECTOFF") , # + "R_PPC64_SECTOFF_LO": MacroRef("R_PPC_SECTOFF_LO") , # + "R_PPC64_SECTOFF_HI": MacroRef("R_PPC_SECTOFF_HI") , # + "R_PPC64_SECTOFF_HA": MacroRef("R_PPC_SECTOFF_HA") , # + "R_PPC64_ADDR30": 37 , # word30 (S + A - P) >> 2 + "R_PPC64_ADDR64": 38 , # doubleword64 S + A + "R_PPC64_ADDR16_HIGHER": 39 , # half16 #higher(S + A) + "R_PPC64_ADDR16_HIGHERA": 40 , # half16 #highera(S + A) + "R_PPC64_ADDR16_HIGHEST": 41 , # half16 #highest(S + A) + "R_PPC64_ADDR16_HIGHESTA": 42 , # half16 #highesta(S + A) + "R_PPC64_UADDR64": 43 , # doubleword64 S + A + "R_PPC64_REL64": 44 , # doubleword64 S + A - P + "R_PPC64_PLT64": 45 , # doubleword64 L + A + "R_PPC64_PLTREL64": 46 , # doubleword64 L + A - P + "R_PPC64_TOC16": 47 , # half16* S + A - .TOC + "R_PPC64_TOC16_LO": 48 , # half16 #lo(S + A - .TOC.) + "R_PPC64_TOC16_HI": 49 , # half16 #hi(S + A - .TOC.) + "R_PPC64_TOC16_HA": 50 , # half16 #ha(S + A - .TOC.) + "R_PPC64_TOC": 51 , # doubleword64 .TOC + "R_PPC64_PLTGOT16": 52 , # half16* M + A + "R_PPC64_PLTGOT16_LO": 53 , # half16 #lo(M + A) + "R_PPC64_PLTGOT16_HI": 54 , # half16 #hi(M + A) + "R_PPC64_PLTGOT16_HA": 55 , # half16 #ha(M + A) + "R_PPC64_ADDR16_DS": 56 , # half16ds* (S + A) >> 2 + "R_PPC64_ADDR16_LO_DS": 57 , # half16ds #lo(S + A) >> 2 + "R_PPC64_GOT16_DS": 58 , # half16ds* (G + A) >> 2 + "R_PPC64_GOT16_LO_DS": 59 , # half16ds #lo(G + A) >> 2 + "R_PPC64_PLT16_LO_DS": 60 , # half16ds #lo(L + A) >> 2 + "R_PPC64_SECTOFF_DS": 61 , # half16ds* (R + A) >> 2 + "R_PPC64_SECTOFF_LO_DS": 62 , # half16ds #lo(R + A) >> 2 + "R_PPC64_TOC16_DS": 63 , # half16ds* (S + A - .TOC.) >> 2 + "R_PPC64_TOC16_LO_DS": 64 , # half16ds #lo(S + A - .TOC.) >> 2 + "R_PPC64_PLTGOT16_DS": 65 , # half16ds* (M + A) >> 2 + "R_PPC64_PLTGOT16_LO_DS": 66 , # half16ds #lo(M + A) >> 2 + "R_PPC64_TLS": 67 , # none (sym+add)@tls + "R_PPC64_DTPMOD64": 68 , # doubleword64 (sym+add)@dtpmod + "R_PPC64_TPREL16": 69 , # half16* (sym+add)@tprel + "R_PPC64_TPREL16_LO": 70 , # half16 (sym+add)@tprel@l + "R_PPC64_TPREL16_HI": 71 , # half16 (sym+add)@tprel@h + "R_PPC64_TPREL16_HA": 72 , # half16 (sym+add)@tprel@ha + "R_PPC64_TPREL64": 73 , # doubleword64 (sym+add)@tprel + "R_PPC64_DTPREL16": 74 , # half16* (sym+add)@dtprel + "R_PPC64_DTPREL16_LO": 75 , # half16 (sym+add)@dtprel@l + "R_PPC64_DTPREL16_HI": 76 , # half16 (sym+add)@dtprel@h + "R_PPC64_DTPREL16_HA": 77 , # half16 (sym+add)@dtprel@ha + "R_PPC64_DTPREL64": 78 , # doubleword64 (sym+add)@dtprel + "R_PPC64_GOT_TLSGD16": 79 , # half16* (sym+add)@got@tlsgd + "R_PPC64_GOT_TLSGD16_LO": 80 , # half16 (sym+add)@got@tlsgd@l + "R_PPC64_GOT_TLSGD16_HI": 81 , # half16 (sym+add)@got@tlsgd@h + "R_PPC64_GOT_TLSGD16_HA": 82 , # half16 (sym+add)@got@tlsgd@ha + "R_PPC64_GOT_TLSLD16": 83 , # half16* (sym+add)@got@tlsld + "R_PPC64_GOT_TLSLD16_LO": 84 , # half16 (sym+add)@got@tlsld@l + "R_PPC64_GOT_TLSLD16_HI": 85 , # half16 (sym+add)@got@tlsld@h + "R_PPC64_GOT_TLSLD16_HA": 86 , # half16 (sym+add)@got@tlsld@ha + "R_PPC64_GOT_TPREL16_DS": 87 , # half16ds* (sym+add)@got@tprel + "R_PPC64_GOT_TPREL16_LO_DS": 88 , # half16ds (sym+add)@got@tprel@l + "R_PPC64_GOT_TPREL16_HI": 89 , # half16 (sym+add)@got@tprel@h + "R_PPC64_GOT_TPREL16_HA": 90 , # half16 (sym+add)@got@tprel@ha + "R_PPC64_GOT_DTPREL16_DS": 91 , # half16ds* (sym+add)@got@dtprel + "R_PPC64_GOT_DTPREL16_LO_DS": 92 , # half16ds (sym+add)@got@dtprel@l + "R_PPC64_GOT_DTPREL16_HI": 93 , # half16 (sym+add)@got@dtprel@h + "R_PPC64_GOT_DTPREL16_HA": 94 , # half16 (sym+add)@got@dtprel@ha + "R_PPC64_TPREL16_DS": 95 , # half16ds* (sym+add)@tprel + "R_PPC64_TPREL16_LO_DS": 96 , # half16ds (sym+add)@tprel@l + "R_PPC64_TPREL16_HIGHER": 97 , # half16 (sym+add)@tprel@higher + "R_PPC64_TPREL16_HIGHERA": 98 , # half16 (sym+add)@tprel@highera + "R_PPC64_TPREL16_HIGHEST": 99 , # half16 (sym+add)@tprel@highest + "R_PPC64_TPREL16_HIGHESTA": 100 , # half16 (sym+add)@tprel@highesta + "R_PPC64_DTPREL16_DS": 101 , # half16ds* (sym+add)@dtprel + "R_PPC64_DTPREL16_LO_DS": 102 , # half16ds (sym+add)@dtprel@l + "R_PPC64_DTPREL16_HIGHER": 103 , # half16 (sym+add)@dtprel@higher + "R_PPC64_DTPREL16_HIGHERA": 104 , # half16 (sym+add)@dtprel@highera + "R_PPC64_DTPREL16_HIGHEST": 105 , # half16 (sym+add)@dtprel@highest + "R_PPC64_DTPREL16_HIGHESTA": 106 , # half16 (sym+add)@dtprel@highesta + "R_PPC64_JMP_IREL": 247 , # + "R_PPC64_IRELATIVE": 248 , # + "R_PPC64_REL16": 249 , # half16 (sym+add-.) + "R_PPC64_REL16_LO": 250 , # half16 (sym+add-.)@l + "R_PPC64_REL16_HI": 251 , # half16 (sym+add-.)@h + "R_PPC64_REL16_HA": 252 , # half16 (sym+add-.)@ha + "DT_PPC64_GLINK": (MacroRef("DT_LOPROC") + 0) , # + "DT_PPC64_OPD": (MacroRef("DT_LOPROC") + 1) , # + "DT_PPC64_OPDSZ": (MacroRef("DT_LOPROC") + 2) , # + "DT_PPC64_NUM": 3 , # + "EF_ARM_RELEXEC": 0x01 , # + "EF_ARM_HASENTRY": 0x02 , # + "EF_ARM_INTERWORK": 0x04 , # + "EF_ARM_APCS_26": 0x08 , # + "EF_ARM_APCS_FLOAT": 0x10 , # + "EF_ARM_PIC": 0x20 , # + "EF_ARM_ALIGN8": 0x40 , # 8-bit structure alignment is in use + "EF_ARM_NEW_ABI": 0x80 , # + "EF_ARM_OLD_ABI": 0x100 , # + "EF_ARM_SOFT_FLOAT": 0x200 , # + "EF_ARM_VFP_FLOAT": 0x400 , # + "EF_ARM_MAVERICK_FLOAT": 0x800 , # + "EF_ARM_SYMSARESORTED": 0x04 , # + "EF_ARM_DYNSYMSUSESEGIDX": 0x08 , # + "EF_ARM_MAPSYMSFIRST": 0x10 , # + "EF_ARM_EABIMASK": 0XFF000000 , # + "EF_ARM_BE8": 0x00800000 , # + "EF_ARM_LE8": 0x00400000 , # + "EF_ARM_EABI_UNKNOWN": 0x00000000 , # + "EF_ARM_EABI_VER1": 0x01000000 , # + "EF_ARM_EABI_VER2": 0x02000000 , # + "EF_ARM_EABI_VER3": 0x03000000 , # + "EF_ARM_EABI_VER4": 0x04000000 , # + "EF_ARM_EABI_VER5": 0x05000000 , # + "STT_ARM_TFUNC": MacroRef("STT_LOPROC") , # A Thumb function. + "STT_ARM_16BIT": MacroRef("STT_HIPROC") , # A Thumb label. + "SHF_ARM_ENTRYSECT": 0x10000000 , # Section contains an entry point + "SHF_ARM_COMDEF": 0x80000000 , # Section may be multiply defined + "PF_ARM_SB": 0x10000000 , # Segment contains the location + "PF_ARM_PI": 0x20000000 , # Position-independent segment. + "PF_ARM_ABS": 0x40000000 , # Absolute segment. + "PT_ARM_EXIDX": (MacroRef("PT_LOPROC") + 1) , # ARM unwind segment. + "SHT_ARM_EXIDX": (MacroRef("SHT_LOPROC") + 1) , # ARM unwind section. + "SHT_ARM_PREEMPTMAP": (MacroRef("SHT_LOPROC") + 2) , # Preemption details. + "SHT_ARM_ATTRIBUTES": (MacroRef("SHT_LOPROC") + 3) , # ARM attributes section. + "R_ARM_NONE": 0 , # No reloc + "R_ARM_PC24": 1 , # PC relative 26 bit branch + "R_ARM_ABS32": 2 , # Direct 32 bit + "R_ARM_REL32": 3 , # PC relative 32 bit + "R_ARM_PC13": 4 , # + "R_ARM_ABS16": 5 , # Direct 16 bit + "R_ARM_ABS12": 6 , # Direct 12 bit + "R_ARM_THM_ABS5": 7 , # + "R_ARM_ABS8": 8 , # Direct 8 bit + "R_ARM_SBREL32": 9 , # + "R_ARM_THM_PC22": 10 , # + "R_ARM_THM_PC8": 11 , # + "R_ARM_AMP_VCALL9": 12 , # + "R_ARM_SWI24": 13 , # Obsolete static relocation. + "R_ARM_TLS_DESC": 13 , # Dynamic relocation. + "R_ARM_THM_SWI8": 14 , # + "R_ARM_XPC25": 15 , # + "R_ARM_THM_XPC22": 16 , # + "R_ARM_TLS_DTPMOD32": 17 , # ID of module containing symbol + "R_ARM_TLS_DTPOFF32": 18 , # Offset in TLS block + "R_ARM_TLS_TPOFF32": 19 , # Offset in static TLS block + "R_ARM_COPY": 20 , # Copy symbol at runtime + "R_ARM_GLOB_DAT": 21 , # Create GOT entry + "R_ARM_JUMP_SLOT": 22 , # Create PLT entry + "R_ARM_RELATIVE": 23 , # Adjust by program base + "R_ARM_GOTOFF": 24 , # 32 bit offset to GOT + "R_ARM_GOTPC": 25 , # 32 bit PC relative offset to GOT + "R_ARM_GOT32": 26 , # 32 bit GOT entry + "R_ARM_PLT32": 27 , # 32 bit PLT address + "R_ARM_ALU_PCREL_7_0": 32 , # + "R_ARM_ALU_PCREL_15_8": 33 , # + "R_ARM_ALU_PCREL_23_15": 34 , # + "R_ARM_LDR_SBREL_11_0": 35 , # + "R_ARM_ALU_SBREL_19_12": 36 , # + "R_ARM_ALU_SBREL_27_20": 37 , # + "R_ARM_TLS_GOTDESC": 90 , # + "R_ARM_TLS_CALL": 91 , # + "R_ARM_TLS_DESCSEQ": 92 , # + "R_ARM_THM_TLS_CALL": 93 , # + "R_ARM_GNU_VTENTRY": 100 , # + "R_ARM_GNU_VTINHERIT": 101 , # + "R_ARM_THM_PC11": 102 , # thumb unconditional branch + "R_ARM_THM_PC9": 103 , # thumb conditional branch + "R_ARM_TLS_GD32": 104 , # PC-rel 32 bit for global dynamic + "R_ARM_TLS_LDM32": 105 , # PC-rel 32 bit for local dynamic + "R_ARM_TLS_LDO32": 106 , # 32 bit offset relative to TLS + "R_ARM_TLS_IE32": 107 , # PC-rel 32 bit for GOT entry of + "R_ARM_TLS_LE32": 108 , # 32 bit offset relative to static + "R_ARM_THM_TLS_DESCSEQ": 129 , # + "R_ARM_IRELATIVE": 160 , # + "R_ARM_RXPC25": 249 , # + "R_ARM_RSBREL32": 250 , # + "R_ARM_THM_RPC22": 251 , # + "R_ARM_RREL32": 252 , # + "R_ARM_RABS22": 253 , # + "R_ARM_RPC24": 254 , # + "R_ARM_RBASE": 255 , # + "R_ARM_NUM": 256 , # + "EF_IA_64_MASKOS": 0x0000000f , # os-specific flags + "EF_IA_64_ABI64": 0x00000010 , # 64-bit ABI + "EF_IA_64_ARCH": 0xff000000 , # arch. version mask + "PT_IA_64_ARCHEXT": (MacroRef("PT_LOPROC") + 0) , # arch extension bits + "PT_IA_64_UNWIND": (MacroRef("PT_LOPROC") + 1) , # ia64 unwind bits + "PT_IA_64_HP_OPT_ANOT": (MacroRef("PT_LOOS") + 0x12) , # + "PT_IA_64_HP_HSL_ANOT": (MacroRef("PT_LOOS") + 0x13) , # + "PT_IA_64_HP_STACK": (MacroRef("PT_LOOS") + 0x14) , # + "PF_IA_64_NORECOV": 0x80000000 , # spec insns w/o recovery + "SHT_IA_64_EXT": (MacroRef("SHT_LOPROC") + 0) , # extension bits + "SHT_IA_64_UNWIND": (MacroRef("SHT_LOPROC") + 1) , # unwind bits + "SHF_IA_64_SHORT": 0x10000000 , # section near gp + "SHF_IA_64_NORECOV": 0x20000000 , # spec insns w/o recovery + "DT_IA_64_PLT_RESERVE": (MacroRef("DT_LOPROC") + 0) , # + "DT_IA_64_NUM": 1 , # + "R_IA64_NONE": 0x00 , # none + "R_IA64_IMM14": 0x21 , # symbol + addend, add imm14 + "R_IA64_IMM22": 0x22 , # symbol + addend, add imm22 + "R_IA64_IMM64": 0x23 , # symbol + addend, mov imm64 + "R_IA64_DIR32MSB": 0x24 , # symbol + addend, data4 MSB + "R_IA64_DIR32LSB": 0x25 , # symbol + addend, data4 LSB + "R_IA64_DIR64MSB": 0x26 , # symbol + addend, data8 MSB + "R_IA64_DIR64LSB": 0x27 , # symbol + addend, data8 LSB + "R_IA64_GPREL22": 0x2a , # @gprel(sym + add), add imm22 + "R_IA64_GPREL64I": 0x2b , # @gprel(sym + add), mov imm64 + "R_IA64_GPREL32MSB": 0x2c , # @gprel(sym + add), data4 MSB + "R_IA64_GPREL32LSB": 0x2d , # @gprel(sym + add), data4 LSB + "R_IA64_GPREL64MSB": 0x2e , # @gprel(sym + add), data8 MSB + "R_IA64_GPREL64LSB": 0x2f , # @gprel(sym + add), data8 LSB + "R_IA64_LTOFF22": 0x32 , # @ltoff(sym + add), add imm22 + "R_IA64_LTOFF64I": 0x33 , # @ltoff(sym + add), mov imm64 + "R_IA64_PLTOFF22": 0x3a , # @pltoff(sym + add), add imm22 + "R_IA64_PLTOFF64I": 0x3b , # @pltoff(sym + add), mov imm64 + "R_IA64_PLTOFF64MSB": 0x3e , # @pltoff(sym + add), data8 MSB + "R_IA64_PLTOFF64LSB": 0x3f , # @pltoff(sym + add), data8 LSB + "R_IA64_FPTR64I": 0x43 , # @fptr(sym + add), mov imm64 + "R_IA64_FPTR32MSB": 0x44 , # @fptr(sym + add), data4 MSB + "R_IA64_FPTR32LSB": 0x45 , # @fptr(sym + add), data4 LSB + "R_IA64_FPTR64MSB": 0x46 , # @fptr(sym + add), data8 MSB + "R_IA64_FPTR64LSB": 0x47 , # @fptr(sym + add), data8 LSB + "R_IA64_PCREL60B": 0x48 , # @pcrel(sym + add), brl + "R_IA64_PCREL21B": 0x49 , # @pcrel(sym + add), ptb, call + "R_IA64_PCREL21M": 0x4a , # @pcrel(sym + add), chk.s + "R_IA64_PCREL21F": 0x4b , # @pcrel(sym + add), fchkf + "R_IA64_PCREL32MSB": 0x4c , # @pcrel(sym + add), data4 MSB + "R_IA64_PCREL32LSB": 0x4d , # @pcrel(sym + add), data4 LSB + "R_IA64_PCREL64MSB": 0x4e , # @pcrel(sym + add), data8 MSB + "R_IA64_PCREL64LSB": 0x4f , # @pcrel(sym + add), data8 LSB + "R_IA64_LTOFF_FPTR22": 0x52 , # @ltoff(@fptr(s+a)), imm22 + "R_IA64_LTOFF_FPTR64I": 0x53 , # @ltoff(@fptr(s+a)), imm64 + "R_IA64_LTOFF_FPTR32MSB": 0x54 , # @ltoff(@fptr(s+a)), data4 MSB + "R_IA64_LTOFF_FPTR32LSB": 0x55 , # @ltoff(@fptr(s+a)), data4 LSB + "R_IA64_LTOFF_FPTR64MSB": 0x56 , # @ltoff(@fptr(s+a)), data8 MSB + "R_IA64_LTOFF_FPTR64LSB": 0x57 , # @ltoff(@fptr(s+a)), data8 LSB + "R_IA64_SEGREL32MSB": 0x5c , # @segrel(sym + add), data4 MSB + "R_IA64_SEGREL32LSB": 0x5d , # @segrel(sym + add), data4 LSB + "R_IA64_SEGREL64MSB": 0x5e , # @segrel(sym + add), data8 MSB + "R_IA64_SEGREL64LSB": 0x5f , # @segrel(sym + add), data8 LSB + "R_IA64_SECREL32MSB": 0x64 , # @secrel(sym + add), data4 MSB + "R_IA64_SECREL32LSB": 0x65 , # @secrel(sym + add), data4 LSB + "R_IA64_SECREL64MSB": 0x66 , # @secrel(sym + add), data8 MSB + "R_IA64_SECREL64LSB": 0x67 , # @secrel(sym + add), data8 LSB + "R_IA64_REL32MSB": 0x6c , # data 4 + REL + "R_IA64_REL32LSB": 0x6d , # data 4 + REL + "R_IA64_REL64MSB": 0x6e , # data 8 + REL + "R_IA64_REL64LSB": 0x6f , # data 8 + REL + "R_IA64_LTV32MSB": 0x74 , # symbol + addend, data4 MSB + "R_IA64_LTV32LSB": 0x75 , # symbol + addend, data4 LSB + "R_IA64_LTV64MSB": 0x76 , # symbol + addend, data8 MSB + "R_IA64_LTV64LSB": 0x77 , # symbol + addend, data8 LSB + "R_IA64_PCREL21BI": 0x79 , # @pcrel(sym + add), 21bit inst + "R_IA64_PCREL22": 0x7a , # @pcrel(sym + add), 22bit inst + "R_IA64_PCREL64I": 0x7b , # @pcrel(sym + add), 64bit inst + "R_IA64_IPLTMSB": 0x80 , # dynamic reloc, imported PLT, MSB + "R_IA64_IPLTLSB": 0x81 , # dynamic reloc, imported PLT, LSB + "R_IA64_COPY": 0x84 , # copy relocation + "R_IA64_SUB": 0x85 , # Addend and symbol difference + "R_IA64_LTOFF22X": 0x86 , # LTOFF22, relaxable. + "R_IA64_LDXMOV": 0x87 , # Use of LTOFF22X. + "R_IA64_TPREL14": 0x91 , # @tprel(sym + add), imm14 + "R_IA64_TPREL22": 0x92 , # @tprel(sym + add), imm22 + "R_IA64_TPREL64I": 0x93 , # @tprel(sym + add), imm64 + "R_IA64_TPREL64MSB": 0x96 , # @tprel(sym + add), data8 MSB + "R_IA64_TPREL64LSB": 0x97 , # @tprel(sym + add), data8 LSB + "R_IA64_LTOFF_TPREL22": 0x9a , # @ltoff(@tprel(s+a)), imm2 + "R_IA64_DTPMOD64MSB": 0xa6 , # @dtpmod(sym + add), data8 MSB + "R_IA64_DTPMOD64LSB": 0xa7 , # @dtpmod(sym + add), data8 LSB + "R_IA64_LTOFF_DTPMOD22": 0xaa , # @ltoff(@dtpmod(sym + add)), imm22 + "R_IA64_DTPREL14": 0xb1 , # @dtprel(sym + add), imm14 + "R_IA64_DTPREL22": 0xb2 , # @dtprel(sym + add), imm22 + "R_IA64_DTPREL64I": 0xb3 , # @dtprel(sym + add), imm64 + "R_IA64_DTPREL32MSB": 0xb4 , # @dtprel(sym + add), data4 MSB + "R_IA64_DTPREL32LSB": 0xb5 , # @dtprel(sym + add), data4 LSB + "R_IA64_DTPREL64MSB": 0xb6 , # @dtprel(sym + add), data8 MSB + "R_IA64_DTPREL64LSB": 0xb7 , # @dtprel(sym + add), data8 LSB + "R_IA64_LTOFF_DTPREL22": 0xba , # @ltoff(@dtprel(s+a)), imm22 + "EF_SH_MACH_MASK": 0x1f , # + "EF_SH_UNKNOWN": 0x0 , # + "EF_SH1": 0x1 , # + "EF_SH2": 0x2 , # + "EF_SH3": 0x3 , # + "EF_SH_DSP": 0x4 , # + "EF_SH3_DSP": 0x5 , # + "EF_SH4AL_DSP": 0x6 , # + "EF_SH3E": 0x8 , # + "EF_SH4": 0x9 , # + "EF_SH2E": 0xb , # + "EF_SH4A": 0xc , # + "EF_SH2A": 0xd , # + "EF_SH4_NOFPU": 0x10 , # + "EF_SH4A_NOFPU": 0x11 , # + "EF_SH4_NOMMU_NOFPU": 0x12 , # + "EF_SH2A_NOFPU": 0x13 , # + "EF_SH3_NOMMU": 0x14 , # + "EF_SH2A_SH4_NOFPU": 0x15 , # + "EF_SH2A_SH3_NOFPU": 0x16 , # + "EF_SH2A_SH4": 0x17 , # + "EF_SH2A_SH3E": 0x18 , # + "R_SH_NONE": 0 , # + "R_SH_DIR32": 1 , # + "R_SH_REL32": 2 , # + "R_SH_DIR8WPN": 3 , # + "R_SH_IND12W": 4 , # + "R_SH_DIR8WPL": 5 , # + "R_SH_DIR8WPZ": 6 , # + "R_SH_DIR8BP": 7 , # + "R_SH_DIR8W": 8 , # + "R_SH_DIR8L": 9 , # + "R_SH_SWITCH16": 25 , # + "R_SH_SWITCH32": 26 , # + "R_SH_USES": 27 , # + "R_SH_COUNT": 28 , # + "R_SH_ALIGN": 29 , # + "R_SH_CODE": 30 , # + "R_SH_DATA": 31 , # + "R_SH_LABEL": 32 , # + "R_SH_SWITCH8": 33 , # + "R_SH_GNU_VTINHERIT": 34 , # + "R_SH_GNU_VTENTRY": 35 , # + "R_SH_TLS_GD_32": 144 , # + "R_SH_TLS_LD_32": 145 , # + "R_SH_TLS_LDO_32": 146 , # + "R_SH_TLS_IE_32": 147 , # + "R_SH_TLS_LE_32": 148 , # + "R_SH_TLS_DTPMOD32": 149 , # + "R_SH_TLS_DTPOFF32": 150 , # + "R_SH_TLS_TPOFF32": 151 , # + "R_SH_GOT32": 160 , # + "R_SH_PLT32": 161 , # + "R_SH_COPY": 162 , # + "R_SH_GLOB_DAT": 163 , # + "R_SH_JMP_SLOT": 164 , # + "R_SH_RELATIVE": 165 , # + "R_SH_GOTOFF": 166 , # + "R_SH_GOTPC": 167 , # + "R_SH_NUM": 256 , # + "EF_S390_HIGH_GPRS": 0x00000001 , # High GPRs kernel facility needed. + "R_390_NONE": 0 , # No reloc. + "R_390_8": 1 , # Direct 8 bit. + "R_390_12": 2 , # Direct 12 bit. + "R_390_16": 3 , # Direct 16 bit. + "R_390_32": 4 , # Direct 32 bit. + "R_390_PC32": 5 , # PC relative 32 bit. + "R_390_GOT12": 6 , # 12 bit GOT offset. + "R_390_GOT32": 7 , # 32 bit GOT offset. + "R_390_PLT32": 8 , # 32 bit PC relative PLT address. + "R_390_COPY": 9 , # Copy symbol at runtime. + "R_390_GLOB_DAT": 10 , # Create GOT entry. + "R_390_JMP_SLOT": 11 , # Create PLT entry. + "R_390_RELATIVE": 12 , # Adjust by program base. + "R_390_GOTOFF32": 13 , # 32 bit offset to GOT. + "R_390_GOTPC": 14 , # 32 bit PC relative offset to GOT. + "R_390_GOT16": 15 , # 16 bit GOT offset. + "R_390_PC16": 16 , # PC relative 16 bit. + "R_390_PC16DBL": 17 , # PC relative 16 bit shifted by 1. + "R_390_PLT16DBL": 18 , # 16 bit PC rel. PLT shifted by 1. + "R_390_PC32DBL": 19 , # PC relative 32 bit shifted by 1. + "R_390_PLT32DBL": 20 , # 32 bit PC rel. PLT shifted by 1. + "R_390_GOTPCDBL": 21 , # 32 bit PC rel. GOT shifted by 1. + "R_390_64": 22 , # Direct 64 bit. + "R_390_PC64": 23 , # PC relative 64 bit. + "R_390_GOT64": 24 , # 64 bit GOT offset. + "R_390_PLT64": 25 , # 64 bit PC relative PLT address. + "R_390_GOTENT": 26 , # 32 bit PC rel. to GOT entry >> 1. + "R_390_GOTOFF16": 27 , # 16 bit offset to GOT. + "R_390_GOTOFF64": 28 , # 64 bit offset to GOT. + "R_390_GOTPLT12": 29 , # 12 bit offset to jump slot. + "R_390_GOTPLT16": 30 , # 16 bit offset to jump slot. + "R_390_GOTPLT32": 31 , # 32 bit offset to jump slot. + "R_390_GOTPLT64": 32 , # 64 bit offset to jump slot. + "R_390_GOTPLTENT": 33 , # 32 bit rel. offset to jump slot. + "R_390_PLTOFF16": 34 , # 16 bit offset from GOT to PLT. + "R_390_PLTOFF32": 35 , # 32 bit offset from GOT to PLT. + "R_390_PLTOFF64": 36 , # 16 bit offset from GOT to PLT. + "R_390_TLS_LOAD": 37 , # Tag for load insn in TLS code. + "R_390_TLS_GDCALL": 38 , # Tag for function call in general + "R_390_TLS_LDCALL": 39 , # Tag for function call in local + "R_390_TLS_GD32": 40 , # Direct 32 bit for general dynamic + "R_390_TLS_GD64": 41 , # Direct 64 bit for general dynamic + "R_390_TLS_GOTIE12": 42 , # 12 bit GOT offset for static TLS + "R_390_TLS_GOTIE32": 43 , # 32 bit GOT offset for static TLS + "R_390_TLS_GOTIE64": 44 , # 64 bit GOT offset for static TLS + "R_390_TLS_LDM32": 45 , # Direct 32 bit for local dynamic + "R_390_TLS_LDM64": 46 , # Direct 64 bit for local dynamic + "R_390_TLS_IE32": 47 , # 32 bit address of GOT entry for + "R_390_TLS_IE64": 48 , # 64 bit address of GOT entry for + "R_390_TLS_IEENT": 49 , # 32 bit rel. offset to GOT entry for + "R_390_TLS_LE32": 50 , # 32 bit negated offset relative to + "R_390_TLS_LE64": 51 , # 64 bit negated offset relative to + "R_390_TLS_LDO32": 52 , # 32 bit offset relative to TLS + "R_390_TLS_LDO64": 53 , # 64 bit offset relative to TLS + "R_390_TLS_DTPMOD": 54 , # ID of module containing symbol. + "R_390_TLS_DTPOFF": 55 , # Offset in TLS block. + "R_390_TLS_TPOFF": 56 , # Negated offset in static TLS + "R_390_20": 57 , # Direct 20 bit. + "R_390_GOT20": 58 , # 20 bit GOT offset. + "R_390_GOTPLT20": 59 , # 20 bit offset to jump slot. + "R_390_TLS_GOTIE20": 60 , # 20 bit GOT offset for static TLS + "R_390_NUM": 61 , # + "R_CRIS_NONE": 0 , # + "R_CRIS_8": 1 , # + "R_CRIS_16": 2 , # + "R_CRIS_32": 3 , # + "R_CRIS_8_PCREL": 4 , # + "R_CRIS_16_PCREL": 5 , # + "R_CRIS_32_PCREL": 6 , # + "R_CRIS_GNU_VTINHERIT": 7 , # + "R_CRIS_GNU_VTENTRY": 8 , # + "R_CRIS_COPY": 9 , # + "R_CRIS_GLOB_DAT": 10 , # + "R_CRIS_JUMP_SLOT": 11 , # + "R_CRIS_RELATIVE": 12 , # + "R_CRIS_16_GOT": 13 , # + "R_CRIS_32_GOT": 14 , # + "R_CRIS_16_GOTPLT": 15 , # + "R_CRIS_32_GOTPLT": 16 , # + "R_CRIS_32_GOTREL": 17 , # + "R_CRIS_32_PLT_GOTREL": 18 , # + "R_CRIS_32_PLT_PCREL": 19 , # + "R_CRIS_NUM": 20 , # + "R_X86_64_NONE": 0 , # No reloc + "R_X86_64_64": 1 , # Direct 64 bit + "R_X86_64_PC32": 2 , # PC relative 32 bit signed + "R_X86_64_GOT32": 3 , # 32 bit GOT entry + "R_X86_64_PLT32": 4 , # 32 bit PLT address + "R_X86_64_COPY": 5 , # Copy symbol at runtime + "R_X86_64_GLOB_DAT": 6 , # Create GOT entry + "R_X86_64_JUMP_SLOT": 7 , # Create PLT entry + "R_X86_64_RELATIVE": 8 , # Adjust by program base + "R_X86_64_GOTPCREL": 9 , # 32 bit signed PC relative + "R_X86_64_32": 10 , # Direct 32 bit zero extended + "R_X86_64_32S": 11 , # Direct 32 bit sign extended + "R_X86_64_16": 12 , # Direct 16 bit zero extended + "R_X86_64_PC16": 13 , # 16 bit sign extended pc relative + "R_X86_64_8": 14 , # Direct 8 bit sign extended + "R_X86_64_PC8": 15 , # 8 bit sign extended pc relative + "R_X86_64_DTPMOD64": 16 , # ID of module containing symbol + "R_X86_64_DTPOFF64": 17 , # Offset in module's TLS block + "R_X86_64_TPOFF64": 18 , # Offset in initial TLS block + "R_X86_64_TLSGD": 19 , # 32 bit signed PC relative offset + "R_X86_64_TLSLD": 20 , # 32 bit signed PC relative offset + "R_X86_64_DTPOFF32": 21 , # Offset in TLS block + "R_X86_64_GOTTPOFF": 22 , # 32 bit signed PC relative offset + "R_X86_64_TPOFF32": 23 , # Offset in initial TLS block + "R_X86_64_PC64": 24 , # PC relative 64 bit + "R_X86_64_GOTOFF64": 25 , # 64 bit offset to GOT + "R_X86_64_GOTPC32": 26 , # 32 bit signed pc relative + "R_X86_64_GOT64": 27 , # 64-bit GOT entry offset + "R_X86_64_GOTPCREL64": 28 , # 64-bit PC relative offset + "R_X86_64_GOTPC64": 29 , # 64-bit PC relative offset to GOT + "R_X86_64_GOTPLT64": 30 , # like GOT64, says PLT entry needed + "R_X86_64_PLTOFF64": 31 , # 64-bit GOT relative offset + "R_X86_64_SIZE32": 32 , # Size of symbol plus 32-bit addend + "R_X86_64_SIZE64": 33 , # Size of symbol plus 64-bit addend + "R_X86_64_GOTPC32_TLSDESC": 34 , # GOT offset for TLS descriptor. + "R_X86_64_TLSDESC_CALL": 35 , # Marker for call through TLS + "R_X86_64_TLSDESC": 36 , # TLS descriptor. + "R_X86_64_IRELATIVE": 37 , # Adjust indirectly by program base + "R_X86_64_NUM": 38 , # + "R_MN10300_NONE": 0 , # No reloc. + "R_MN10300_32": 1 , # Direct 32 bit. + "R_MN10300_16": 2 , # Direct 16 bit. + "R_MN10300_8": 3 , # Direct 8 bit. + "R_MN10300_PCREL32": 4 , # PC-relative 32-bit. + "R_MN10300_PCREL16": 5 , # PC-relative 16-bit signed. + "R_MN10300_PCREL8": 6 , # PC-relative 8-bit signed. + "R_MN10300_GNU_VTINHERIT": 7 , # Ancient C++ vtable garbage... + "R_MN10300_GNU_VTENTRY": 8 , # ... collection annotation. + "R_MN10300_24": 9 , # Direct 24 bit. + "R_MN10300_GOTPC32": 10 , # 32-bit PCrel offset to GOT. + "R_MN10300_GOTPC16": 11 , # 16-bit PCrel offset to GOT. + "R_MN10300_GOTOFF32": 12 , # 32-bit offset from GOT. + "R_MN10300_GOTOFF24": 13 , # 24-bit offset from GOT. + "R_MN10300_GOTOFF16": 14 , # 16-bit offset from GOT. + "R_MN10300_PLT32": 15 , # 32-bit PCrel to PLT entry. + "R_MN10300_PLT16": 16 , # 16-bit PCrel to PLT entry. + "R_MN10300_GOT32": 17 , # 32-bit offset to GOT entry. + "R_MN10300_GOT24": 18 , # 24-bit offset to GOT entry. + "R_MN10300_GOT16": 19 , # 16-bit offset to GOT entry. + "R_MN10300_COPY": 20 , # Copy symbol at runtime. + "R_MN10300_GLOB_DAT": 21 , # Create GOT entry. + "R_MN10300_JMP_SLOT": 22 , # Create PLT entry. + "R_MN10300_RELATIVE": 23 , # Adjust by program base. + "R_MN10300_NUM": 24 , # + "R_M32R_NONE": 0 , # No reloc. + "R_M32R_16": 1 , # Direct 16 bit. + "R_M32R_32": 2 , # Direct 32 bit. + "R_M32R_24": 3 , # Direct 24 bit. + "R_M32R_10_PCREL": 4 , # PC relative 10 bit shifted. + "R_M32R_18_PCREL": 5 , # PC relative 18 bit shifted. + "R_M32R_26_PCREL": 6 , # PC relative 26 bit shifted. + "R_M32R_HI16_ULO": 7 , # High 16 bit with unsigned low. + "R_M32R_HI16_SLO": 8 , # High 16 bit with signed low. + "R_M32R_LO16": 9 , # Low 16 bit. + "R_M32R_SDA16": 10 , # 16 bit offset in SDA. + "R_M32R_GNU_VTINHERIT": 11 , # + "R_M32R_GNU_VTENTRY": 12 , # + "R_M32R_16_RELA": 33 , # Direct 16 bit. + "R_M32R_32_RELA": 34 , # Direct 32 bit. + "R_M32R_24_RELA": 35 , # Direct 24 bit. + "R_M32R_10_PCREL_RELA": 36 , # PC relative 10 bit shifted. + "R_M32R_18_PCREL_RELA": 37 , # PC relative 18 bit shifted. + "R_M32R_26_PCREL_RELA": 38 , # PC relative 26 bit shifted. + "R_M32R_HI16_ULO_RELA": 39 , # High 16 bit with unsigned low + "R_M32R_HI16_SLO_RELA": 40 , # High 16 bit with signed low + "R_M32R_LO16_RELA": 41 , # Low 16 bit + "R_M32R_SDA16_RELA": 42 , # 16 bit offset in SDA + "R_M32R_RELA_GNU_VTINHERIT": 43 , # + "R_M32R_RELA_GNU_VTENTRY": 44 , # + "R_M32R_REL32": 45 , # PC relative 32 bit. + "R_M32R_GOT24": 48 , # 24 bit GOT entry + "R_M32R_26_PLTREL": 49 , # 26 bit PC relative to PLT shifted + "R_M32R_COPY": 50 , # Copy symbol at runtime + "R_M32R_GLOB_DAT": 51 , # Create GOT entry + "R_M32R_JMP_SLOT": 52 , # Create PLT entry + "R_M32R_RELATIVE": 53 , # Adjust by program base + "R_M32R_GOTOFF": 54 , # 24 bit offset to GOT + "R_M32R_GOTPC24": 55 , # 24 bit PC relative offset to GOT + "R_M32R_GOT16_HI_ULO": 56 , # High 16 bit GOT entry with unsigned + "R_M32R_GOT16_HI_SLO": 57 , # High 16 bit GOT entry with signed + "R_M32R_GOT16_LO": 58 , # Low 16 bit GOT entry + "R_M32R_GOTPC_HI_ULO": 59 , # High 16 bit PC relative offset to + "R_M32R_GOTPC_HI_SLO": 60 , # High 16 bit PC relative offset to + "R_M32R_GOTPC_LO": 61 , # Low 16 bit PC relative offset to + "R_M32R_GOTOFF_HI_ULO": 62 , # High 16 bit offset to GOT + "R_M32R_GOTOFF_HI_SLO": 63 , # High 16 bit offset to GOT + "R_M32R_GOTOFF_LO": 64 , # Low 16 bit offset to GOT + "R_M32R_NUM": 256 , # Keep this the last entry. + "SHF_WRITE": (1 << 0) , # Writable + "SHF_ALLOC": (1 << 1) , # Occupies memory during execution + "SHF_EXECINSTR": (1 << 2) , # Executable + "SHF_MERGE": (1 << 4) , # Might be merged + "SHF_STRINGS": (1 << 5) , # Contains nul-terminated strings + "SHF_INFO_LINK": (1 << 6) , # `sh_info' contains SHT index + "SHF_LINK_ORDER": (1 << 7) , # Preserve order after combining + "SHF_OS_NONCONFORMING": (1 << 8) , # Non-standard OS specific handling + "SHF_GROUP": (1 << 9) , # Section is member of a group. + "SHF_TLS": (1 << 10) , # Section hold thread-local data. +# libelf.h constants +# ELF_C + "ELF_C_NULL": 0, + "ELF_C_READ": 1, + "ELF_C_WRITE": 2, + "ELF_C_CLR": 3, + "ELF_C_SET": 4, + "ELF_C_FDDONE": 5, + "ELF_C_FDREAD": 6, + "ELF_C_RDWR": 7, + "ELF_C_NUM": 8, +# ELF_K + "ELF_K_NONE": 0, + "ELF_K_AR": 1, + "ELF_K_COFF": 2, + "ELF_K_ELF": 3, + "ELF_K_NUM": 4, +# ELF_T + "ELF_T_BYTE": 00, + "ELF_T_ADDR": 01, + "ELF_T_DYN": 02, + "ELF_T_EHDR": 03, + "ELF_T_HALF": 04, + "ELF_T_OFF": 05, + "ELF_T_PHDR": 06, + "ELF_T_RELA": 07, + "ELF_T_REL": 8, + "ELF_T_SHDR": 9, + "ELF_T_SWORD": 10, + "ELF_T_SYM": 11, + "ELF_T_WORD": 12, + "ELF_T_SXWORD": 13, + "ELF_T_XWORD": 14, + "ELF_T_VDEF": 15, + "ELF_T_VNEED": 16, + "ELF_T_NUM": 17, +# ELF_F (ELF flags) + "ELF_F_DIRTY": 0x1 , # + "ELF_F_LAYOUT": 0x4 , # + "ELF_F_LAYOUT_OVERLAP": 0x10000000 , # +} + +# Now lets generate constants for all + +g = globals() + +for c in _consts: + g[c] = _consts[c] + +__all__ = _consts.keys() + +# TODO: Move these to the macros module + +#elf.h + +# Macro functions + +#define ELF32_ST_VISIBILITY(o) ((o) & 0x03) +#define ELF64_ST_VISIBILITY(o) ELF32_ST_VISIBILITY (o) + +#define DT_VALTAGIDX(tag) (DT_VALRNGHI - (tag)) # Reverse order! + +#define DT_ADDRTAGIDX(tag) (DT_ADDRRNGHI - (tag)) # Reverse order! + +#define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) # Reverse order! +#define DT_EXTRATAGIDX(tag) ((Elf32_Word)-((Elf32_Sword) (tag) <<1>>1)-1) + +#define ELF32_M_SYM(info) ((info) >> 8) +#define ELF32_M_SIZE(info) ((unsigned char) (info)) +#define ELF32_M_INFO(sym, size) (((sym) << 8) + (unsigned char) (size)) +#define ELF64_M_SYM(info) ELF32_M_SYM (info) +#define ELF64_M_SIZE(info) ELF32_M_SIZE (info) +#define ELF64_M_INFO(sym, size) ELF32_M_INFO (sym, size) + +#define EF_ARM_EABI_VERSION(flags) ((flags) & EF_ARM_EABIMASK) + +#libelf.h diff --git a/tools/esp_app_trace/pylibelf/iterators/__init__.py b/tools/esp_app_trace/pylibelf/iterators/__init__.py new file mode 100644 index 000000000..437a7118c --- /dev/null +++ b/tools/esp_app_trace/pylibelf/iterators/__init__.py @@ -0,0 +1,216 @@ +import sys +import os +from .. import * +from ..constants import * +from ..types import * +from ..util import * +from ctypes import * + +def sections(elf, **kwargs): + i = None + ndx = 0 # we skip the first null section + if 'info' in kwargs: + if (isinstance(kwargs['info'], Elf_Scn)): + info = elf_ndxscn(kwargs['info']) + else: + info = kwargs['info'] + else: + info = None + while 1: + i = elf_nextscn(elf, i) + ndx += 1 + + if (not bool(i)): + break + + try: + if ('name' in kwargs and section_name(elf, i) != kwargs['name']): + continue + + if ('type' in kwargs and section_type(elf, i) != kwargs['type']): + continue + + if ('link' in kwargs and section_link(elf, i) != kwargs['link']): + continue + + if (info != None and section_hdr(elf, i).sh_info != info): + continue + except ValueError: + print "Error iterating over section ", i + continue + + if ('ndx' in kwargs and kwargs['ndx']): + yield (ndx, i.contents) + else: + yield i.contents + + +def shdrs(elf): + i = None + while 1: + i = elf_nextscn(elf, i) + if (not bool(i)): + break + + yield select(elf, 'getshdr')(i.contents).contents + +def phdrs(elf): + phdrTbl = select(elf, "getphdr")(elf) + ehdr = select(elf, "getehdr")(elf).contents + phdrCnt = ehdr.e_phnum + + for i in xrange(0, phdrCnt): + yield phdrTbl[i] + +def data(elf_scn): + i = None + while 1: + i = elf_getdata(elf_scn, i) + + if (not bool(i)): + break + + yield i.contents + +def strings(v): + if (isinstance(v, Elf_Data)): + strtab_data = v + size = strtab_data.d_size + buf = cast(strtab_data.d_buf, POINTER(c_char)) + start = 0; + while start < size: + end = start; + while buf[end] != '\x00': end += 1 + yield (strtab_data.d_off + start, buf[start:end]) + + start = end+1 + elif (isinstance(v, Elf_Scn)): + for d in data(v): + strtab_data = d + size = strtab_data.d_size + buf = cast(strtab_data.d_buf, POINTER(c_char)) + start = 0; + while start < size: + end = start; + while buf[end] != '\x00': end += 1 + yield (strtab_data.d_off + start, buf[start:end]) + + start = end+1 + + +def arr_iter(data, itemT, ind = False): + size = data.d_size + + if size % sizeof(itemT) != 0: + raise Exception("Data size not a multiple of symbol size!") + + buf = cast(data.d_buf, POINTER(itemT)) + nelems = size / sizeof(itemT) + + for i in xrange(0, nelems): + if ind: + yield (i, buf[i]) + else: + yield buf[i] + +def syms(elf, v = None): + symT = Elf32_Sym if (is32(elf)) else Elf64_Sym + if v == None: + for s in sections(elf): + hdr = section_hdr(elf, s) + + if (hdr.sh_type != SHT_SYMTAB and hdr.sh_type != SHT_DYNSYM): + continue + + for d in data(s): + for (ind, sym) in arr_iter(d, symT, True): + yield (ind, sym) + elif isinstance(v, Elf_Scn): + for d in data(v): + for (ind, sym) in arr_iter(d, symT, True): + yield (ind, sym) + else: + assert isinstance(v, Elf_Data) + for (ind, sym) in arr_iter(v, symT, True): + yield (ind, sym) + +def rels(elf, **kwargs): + relT = Elf32_Rel if (is32(elf)) else Elf64_Rel + if 'section' in kwargs: + secl = sections(elf, type = SHT_REL, info = kwargs['section']) + else: + secl = sections(elf, type = SHT_REL) + + + if 'range' in kwargs: + for scn in secl: + for d in data(scn): + for rel in arr_iter(d, relT): + if (rel.r_offset >= kwargs['range'][0] and + rel.r_offset < kwargs['range'][1]): + yield (rel, section_hdr(elf, scn).sh_link) + else: + for scn in secl: + for d in data(scn): + for rel in arr_iter(d, relT): + yield (rel, section_hdr(elf, scn).sh_link) + +def relas(elf, **kwargs): + relT = Elf32_Rela if (is32(elf)) else Elf64_Rela + if 'section' in kwargs: + scn = kwargs['section'] + if (type(scn) == str): scn = list(sections(elf, name=scn))[0] + if (isinstance(scn, Elf_Scn)): scn = elf_ndxscn(byref(scn)) + secl = list(sections(elf, type = SHT_RELA, info = scn)) + else: + secl = list(sections(elf, type = SHT_RELA)) + + if 'range' in kwargs: + for scn in secl: + for d in data(scn): + for rel in arr_iter(d, relT): + if (rel.r_offset + rel.r_addend >= kwargs['range'][0] and + rel.r_offset + rel.r_addend < kwargs['range'][1]): + yield (rel, section_hdr(elf, scn).sh_link) + else: + addSecId = kwargs['withSectionId']==True \ + if 'withSectionId' in kwargs \ + else False + if not addSecId: + for scn in secl: + for d in data(scn): + for rel in arr_iter(d, relT): + yield (rel, section_hdr(elf, scn).sh_link) + else: + for scn in secl: + for d in data(scn): + for rel in arr_iter(d, relT): + yield (rel, section_hdr(elf, scn).sh_info) + +def getOnlyData(scn): + d = elf_getdata(scn, None); + assert bool(elf_getdata(scn, d)) == False + return d + +def dyns(elf): + relT = Elf64_Dyn + for scn in sections(elf, name=".dynamic"): + for d in data(scn): + for dyn in arr_iter(d, relT): + yield dyn + +def elfs(fname): + fd = os.open(fname, os.O_RDONLY) + ar = elf_begin(fd, ELF_C_READ, None) + + i = None + while 1: + i = elf_begin(fd, ELF_C_READ, ar) + if (not bool(i)): + break + + yield i + + elf_end(ar) + os.close(fd) + diff --git a/tools/esp_app_trace/pylibelf/macros/__init__.py b/tools/esp_app_trace/pylibelf/macros/__init__.py new file mode 100644 index 000000000..d51a8d93f --- /dev/null +++ b/tools/esp_app_trace/pylibelf/macros/__init__.py @@ -0,0 +1,55 @@ +def ELF32_R_SYM(i): + if type(i) == str: + assert(len(i) == 1) # Single char + i = ord(i) + return i >> 8 + +def ELF32_R_TYPE(i): + if type(i) == str: + assert(len(i) == 1) # Single char + i = ord(i) + return i % 256 # Lowest 8 bits + +def ELF32_R_INFO(sym, typ): + return (((sym) << 8) + typ % 256) + +def ELF64_R_SYM(i): + if type(i) == str: + assert(len(i) == 1) # Single char + i = ord(i) + return i >> 32 + +def ELF64_R_TYPE(i): + if type(i) == str: + assert(len(i) == 1) # Single char + i = ord(i) + return i & 0xffffffffL + +def ELF64_R_INFO(sym, typ): + return ((sym << 32) + (typ & 0xffffffffL)) + +# symbol st_info + +def ELF32_ST_BIND(val): + if type(val) == str: + assert(len(val) == 1) # Single char + val = ord(val) + return val >> 4 + +def ELF32_ST_TYPE(val): + if type(val) == str: + assert(len(val) == 1) # Single char + val = ord(val) + return val & 0xf + +def ELF32_ST_INFO(bind, type): + return (((bind) << 4) + ((type) & 0xf)) + +def ELF64_ST_BIND(val): + return ELF32_ST_BIND(val) + +def ELF64_ST_TYPE(val): + return ELF32_ST_TYPE(val) + +def ELF64_ST_INFO(bind, type): + return ELF32_ST_INFO(bind, type) diff --git a/tools/esp_app_trace/pylibelf/types/__init__.py b/tools/esp_app_trace/pylibelf/types/__init__.py new file mode 100644 index 000000000..cc838d2f0 --- /dev/null +++ b/tools/esp_app_trace/pylibelf/types/__init__.py @@ -0,0 +1,274 @@ +from ctypes import * +from ..constants import EI_NIDENT + +# Obtained from /usr/lib/elf.h + +# Type for a 16-bit quantity. +Elf32_Half = c_uint16 +Elf64_Half = c_uint16 + +# Types for signed and unsigned 32-bit quantities. +Elf32_Word = c_uint32 +Elf32_Sword = c_int32 +Elf64_Word = c_uint32 +Elf64_Sword = c_int32 + +# Types for signed and unsigned 64-bit quantities. +Elf32_Xword = c_uint64 +Elf32_Sxword = c_int64 +Elf64_Xword = c_uint64 +Elf64_Sxword = c_int64 + +# Type of addresses. +Elf32_Addr = c_uint32 +Elf64_Addr = c_uint64 + +# Type of file offsets. +Elf32_Off = c_uint32 +Elf64_Off = c_uint64 + +# Type for section indices, which are 16-bit quantities. +Elf32_Section = c_uint16 +Elf64_Section = c_uint16 + +# Type for version symbol information. +Elf32_Versym = Elf32_Half +Elf64_Versym = Elf64_Half + +# The ELF file header. This appears at the start of every ELF file. + +Elf_IdentT = c_char * EI_NIDENT + +Elf_Cmd = c_int + +class _ElfStructure(Structure): + def __str__(self): + return self.__class__.__name__ + '(' + \ + ','.join([field[0] + '=' + str(getattr(self, field[0])) for field in self._fields_]) + ')' + +class _ElfUnion(Union): + def __str__(self): + return self.__class__.__name__ + '(' + \ + ','.join([field[0] + '=' + str(getattr(self, field[0])) for field in self._fields_]) + ')' + +# Libelf opaque handles +class Elf(_ElfStructure): + _fields_ = [] +class Elf_Scn(_ElfStructure): + _fields_ = [] + +class Elf_Data(_ElfStructure): + _fields_ = [ + ('d_buf', c_void_p), + ('d_type', c_int), + ('d_size', c_size_t), + ('d_off', c_size_t), + ('d_align', c_size_t), + ('d_version', c_uint) + ] + +ElfP = POINTER(Elf) +Elf_ScnP = POINTER(Elf_Scn) +Elf_DataP = POINTER(Elf_Data) + +class Elf32_Ehdr(_ElfStructure): + _fields_ = [ + ('e_ident', Elf_IdentT ), # Magic number and other info + ('e_type', Elf32_Half ), # Object file type + ('e_machine', Elf32_Half ), # Architecture + ('e_version', Elf32_Word ), # Object file version + ('e_entry', Elf32_Addr ), # Entry point virtual address + ('e_phoff', Elf32_Off), # Program header table file offset + ('e_shoff', Elf32_Off), # Section header table file offset + ('e_flags', Elf32_Word ), # Processor-specific flags + ('e_ehsize', Elf32_Half ), # ELF header size in bytes + ('e_phentsize', Elf32_Half ), # Program header table entry size + ('e_phnum', Elf32_Half ), # Program header table entry count + ('e_shentsize', Elf32_Half ), # Section header table entry size + ('e_shnum', Elf32_Half ), # Section header table entry count + ('e_shstrndx', Elf32_Half ), # Section header string table index + ] + +class Elf64_Ehdr(_ElfStructure): + _fields_ = [ + ('e_ident', Elf_IdentT ), # Magic number and other info + ('e_type', Elf64_Half ), # Object file type + ('e_machine', Elf64_Half ), # Architecture + ('e_version', Elf64_Word ), # Object file version + ('e_entry', Elf64_Addr ), # Entry point virtual address + ('e_phoff', Elf64_Off), # Program header table file offset + ('e_shoff', Elf64_Off), # Section header table file offset + ('e_flags', Elf64_Word ), # Processor-specific flags + ('e_ehsize', Elf64_Half ), # ELF header size in bytes + ('e_phentsize', Elf64_Half ), # Program header table entry size + ('e_phnum', Elf64_Half ), # Program header table entry count + ('e_shentsize', Elf64_Half ), # Section header table entry size + ('e_shnum', Elf64_Half ), # Section header table entry count + ('e_shstrndx', Elf64_Half ), # Section header string table index + ] + +class Elf32_Shdr(_ElfStructure): + _fields_ = [ + ('sh_name', Elf32_Word), # Section name (string tbl index) + ('sh_type', Elf32_Word), # Section type + ('sh_flags', Elf32_Word), # Section flags + ('sh_addr', Elf32_Addr), # Section virtual addr at execution + ('sh_offset', Elf32_Off), # Section file offset + ('sh_size', Elf32_Word), # Section size in bytes + ('sh_link', Elf32_Word), # Link to another section + ('sh_info', Elf32_Word), # Additional section information + ('sh_addralign', Elf32_Word), # Section alignment + ('sh_entsize', Elf32_Word), # Entry size if section holds table + ] + +class Elf64_Shdr(_ElfStructure): + _fields_ = [ + ('sh_name', Elf64_Word), # Section name (string tbl index) + ('sh_type', Elf64_Word), # Section type + ('sh_flags', Elf64_Xword), # Section flags + ('sh_addr', Elf64_Addr), # Section virtual addr at execution + ('sh_offset', Elf64_Off), # Section file offset + ('sh_size', Elf64_Xword), # Section size in bytes + ('sh_link', Elf64_Word), # Link to another section + ('sh_info', Elf64_Word), # Additional section information + ('sh_addralign', Elf64_Xword), # Section alignment + ('sh_entsize', Elf64_Xword), # Entry size if section holds table + ] + +class Elf32_Phdr(_ElfStructure): + _fields_ = [ + ('p_type', Elf32_Word), # Segment type + ('p_offset', Elf32_Off), # Segment file offset + ('p_vaddr', Elf32_Addr), # Segment virtual address + ('p_paddr', Elf32_Addr), # Segment physical address + ('p_filesz', Elf32_Word), # Segment size in file + ('p_memsz', Elf32_Word), # Segment size in memory + ('p_flags', Elf32_Word), # Segment flags + ('p_align', Elf32_Word), # Segment alignment + ] + +class Elf64_Phdr(_ElfStructure): + _fields_ = [ + ('p_type', Elf64_Word), # Segment type + ('p_flags', Elf64_Word), # Segment flags + ('p_offset', Elf64_Off), # Segment file offset + ('p_vaddr', Elf64_Addr), # Segment virtual address + ('p_paddr', Elf64_Addr), # Segment physical address + ('p_filesz', Elf64_Xword), # Segment size in file + ('p_memsz', Elf64_Xword), # Segment size in memory + ('p_align', Elf64_Xword), # Segment alignment + ] + +# /* Symbol table entry. */ +class Elf32_Sym(_ElfStructure): + _fields_ = [ + ('st_name', Elf32_Word), # Symbol name (string tbl index) + ('st_value', Elf32_Addr), # Symbol value + ('st_size', Elf32_Word), # Symbol size + ('st_info', c_char), # Symbol type and binding + ('st_other', c_char), # Symbol visibility + ('st_shndx', Elf32_Section), # Section index + ] + +class Elf64_Sym(_ElfStructure): + _fields_ = [ + ('st_name', Elf64_Word), # Symbol name (string tbl index) + ('st_info', c_char), # Symbol type and binding + ('st_other', c_char), # Symbol visibility + ('st_shndx', Elf64_Section), # Section index + ('st_value', Elf64_Addr), # Symbol value + ('st_size', Elf64_Xword), # Symbol size + ] + +#/* The syminfo section if available contains additional information about +# every dynamic symbol. */ + +class Elf32_Syminfo(_ElfStructure): + _fields_ = [ + ('si_boundto', Elf32_Half), # Direct bindings, symbol bound to + ('si_flags', Elf32_Half), # Per symbol flags + ] + +class Elf64_Syminfo(_ElfStructure): + _fields_ = [ + ('si_boundto', Elf64_Half), # Direct bindings, symbol bound to + ('si_flags', Elf64_Half), # Per symbol flags + ] + +# /* Relocation table entry without addend (in section of type SHT_REL). */ + +class Elf32_Rel(_ElfStructure): + _fields_ = [ + ('r_offset', Elf32_Addr), # Address + ('r_info', Elf32_Word), # Relocation type and symbol index + ] + +class Elf64_Rel(_ElfStructure): + _fields_ = [ + ('r_offset', Elf64_Addr), # Address + ('r_info', Elf64_Xword), # Relocation type and symbol index + ] + +# # Relocation table entry with addend (in section of type SHT_RELA). + +class Elf32_Rela(_ElfStructure): + _fields_ = [ + ('r_offset', Elf32_Addr), # Address + ('r_info', Elf32_Word), # Relocation type and symbol index + ('r_addend', Elf32_Sword), # Addend + ] + +class Elf64_Rela(_ElfStructure): + _fields_ = [ + ('r_offset', Elf64_Addr), # Address + ('r_info', Elf64_Xword), # Relocation type and symbol index + ('r_addend', Elf64_Sxword), # Addend + ] + +time_t = c_int64 +uid_t = c_int32 +gid_t = c_int32 +mode_t = c_int32 +off_t = c_int64 + +class Elf_Arhdr(_ElfStructure): + _fields_ = [ + ('ar_name', c_char_p), + ('ar_date', time_t), + ('ar_uid', uid_t), + ('ar_gid', gid_t), + ('ar_mode', mode_t), + ('ar_size', off_t), + ('ar_fmag', POINTER(c_char)), + ] + +class _Elf64_DynUnion(_ElfUnion): + _fields_ = [ + ('d_val', Elf64_Xword), + ('d_ptr', Elf64_Addr), + ] + +class Elf64_Dyn(_ElfStructure): + _fields_ = [ + ('d_tag', Elf64_Xword), + ('d_un', _Elf64_DynUnion), + ] + +# GNU Extensions +class Elf64_Verneed(_ElfStructure): + _fields_ = [ + ('vn_version', Elf64_Half), + ('vn_cnt', Elf64_Half), + ('vn_file', Elf64_Word), + ('vn_aux', Elf64_Word), + ('vn_next', Elf64_Word), + ] + +class Elf64_Vernaux(_ElfStructure): + _fields_ = [ + ('vna_hash', Elf64_Word), + ('vna_flags', Elf64_Half), + ('vna_other', Elf64_Half), + ('vna_name', Elf64_Word), + ('vna_next', Elf64_Word), + ] diff --git a/tools/esp_app_trace/pylibelf/util/__init__.py b/tools/esp_app_trace/pylibelf/util/__init__.py new file mode 100644 index 000000000..5eb472a4f --- /dev/null +++ b/tools/esp_app_trace/pylibelf/util/__init__.py @@ -0,0 +1,38 @@ +from .. import * +from ..types import * +from ..constants import * +from ctypes import * +import os + +def _class(elf): return ord(elf_getident(elf, None).contents[EI_CLASS]) + +def is32(elf): return _class(elf) == ELFCLASS32 +def is64(elf): return _class(elf) == ELFCLASS64 + +def select(elf, fname): + if is32(elf): + return globals()['elf32_' + fname] + else: + return globals()['elf64_' + fname] + +def section_name(elfP, secP): + shstrndx = c_size_t() + r = elf_getshstrndx(elfP, byref(shstrndx)) + shdr = select(elfP, 'getshdr')(secP) + return elf_strptr(elfP, shstrndx, shdr.contents.sh_name) + +def section_type(elfP, secP): + return select(elfP, 'getshdr')(secP).contents.sh_type + +def section_link(elfP, secP): + return select(elfP, 'getshdr')(secP).contents.sh_link + +def section_hdr(elfP, secP): + return select(elfP, 'getshdr')(secP).contents + +def open_elf(fname): + fd = os.open(fname, os.O_RDONLY) + return elf_begin(fd, ELF_C_READ, None) + +def sym_name(elf, scn, sym): + return elf_strptr(elf, section_link(elf, scn), sym.st_name) diff --git a/tools/esp_app_trace/pylibelf/util/syms/__init__.py b/tools/esp_app_trace/pylibelf/util/syms/__init__.py new file mode 100644 index 000000000..ac7267e18 --- /dev/null +++ b/tools/esp_app_trace/pylibelf/util/syms/__init__.py @@ -0,0 +1,58 @@ +from .. import * +from ...types import * +from ...iterators import * + +def defined(s): return s.st_shndx != SHN_UNDEF + +def defines(elf, symN): + s = findSymbol(elf, symN) + print elf, symN, s + if s != None: + print s.st_shndx, s.st_name + return s != None and defined(s[1]) + +def derefSymbol(elf, s): + assert defined(s) + if s.st_shndx == SHN_ABS: + raise Exception("NYI") + else: + scn = elf_getscn(elf, s.st_shndx) + shdr = section_hdr(elf, scn); + off = 0 + base = shdr.sh_addr if shdr.sh_addr != 0 else 0 + start = s.st_value + end = s.st_value + s.st_size + r = '' + for d in data(scn): + if start >= end: break; + off = base + d.d_off + if start >= off and start < off + d.d_size: + c = cast(d.d_buf, POINTER(c_char)) + l = min(off + d.d_size, end) - start + r += c[start- off : start - off + l] + start += l + + return r + +def derefSymbolFull(elf, s): + """ Given an elf file and a Elf{32/64}_Sym defined in the elf file, + return a tuple with the contents of memory refered to by the symbol, + and any Rel's and Rela's inside that memory. + """ + assert (defined(s)) + contents = derefSymbol(elf, s) + relL = list(rels(elf, section=s.st_shndx, \ + range=(s.st_value, s.st_size + s.st_value))) + relaL = list(relas(elf, section=s.st_shndx, \ + range=(s.st_value, s.st_size + s.st_value))) + return (contents, relL, relaL) + +# Given a symbol name return the symbol and section in which it occurs +def findSymbol(elf, s): + for scn in sections(elf, type=SHT_SYMTAB): + strndx = section_link(elf, scn) + for d in data(scn): + for (ind, sym) in syms(elf, d): + if s == elf_strptr(elf, strndx, sym.st_name): + return (scn, sym) + return None diff --git a/tools/unit-test-app/partition_table_unit_test_app.csv b/tools/unit-test-app/partition_table_unit_test_app.csv index b6e57b4ed..129d0d3f6 100644 --- a/tools/unit-test-app/partition_table_unit_test_app.csv +++ b/tools/unit-test-app/partition_table_unit_test_app.csv @@ -6,7 +6,9 @@ nvs, data, nvs, 0x9000, 0x4000 otadata, data, ota, 0xd000, 0x2000 phy_init, data, phy, 0xf000, 0x1000 factory, 0, 0, 0x10000, 1M -ota_0, 0, ota_0, , 1M -ota_1, 0, ota_1, , 1M +# these OTA partitions are used for tests, but can't fit real OTA apps in them +# (done this way so tests can run in 2MB of flash.) +ota_0, 0, ota_0, , 128K +ota_1, 0, ota_1, , 128K # flash_test partition used for SPI flash tests flash_test, 0x55, 0x55, , 512K diff --git a/tools/unit-test-app/sdkconfig b/tools/unit-test-app/sdkconfig index 2c73a45ca..44b599b4a 100644 --- a/tools/unit-test-app/sdkconfig +++ b/tools/unit-test-app/sdkconfig @@ -106,11 +106,17 @@ CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=240 CONFIG_MEMMAP_SMP=y # CONFIG_MEMMAP_TRACEMEM is not set +# CONFIG_MEMMAP_TRACEMEM_TWOBANKS is not set +# CONFIG_ESP32_TRAX is not set CONFIG_TRACEMEM_RESERVE_DRAM=0x0 # CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH is not set # CONFIG_ESP32_ENABLE_COREDUMP_TO_UART is not set CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE=y # CONFIG_ESP32_ENABLE_COREDUMP is not set +# CONFIG_ESP32_APPTRACE_DEST_TRAX is not set +# CONFIG_ESP32_APPTRACE_DEST_UART is not set +CONFIG_ESP32_APPTRACE_DEST_NONE=y +# CONFIG_ESP32_APPTRACE_ENABLE is not set # CONFIG_TWO_MAC_ADDRESS_FROM_EFUSE is not set CONFIG_FOUR_MAC_ADDRESS_FROM_EFUSE=y CONFIG_NUMBER_OF_MAC_ADDRESS_GENERATED_FROM_EFUSE=4