Explorar o código

Merge branch 'master' into feature/btdm_bluedroid
1.update esptool submodule
2.new esp32 lib and new phy lib
3.new bt lib
4.soc.h add comment

Tian Hao %!s(int64=9) %!d(string=hai) anos
pai
achega
d472ff5856
Modificáronse 100 ficheiros con 3470 adicións e 5198 borrados
  1. 0 3
      .gitignore
  2. 6 0
      .gitlab-ci.yml
  3. 20 0
      Kconfig
  4. 20 14
      components/bootloader/Makefile.projbuild
  5. 2 1
      components/bootloader/src/Makefile
  6. 7 73
      components/bootloader/src/main/bootloader_config.h
  7. 80 67
      components/bootloader/src/main/bootloader_start.c
  8. 1 1
      components/bootloader/src/main/flash_encrypt.c
  9. 1 1
      components/bt/lib
  10. 182 1
      components/esp32/Kconfig
  11. 39 0
      components/esp32/brownout.c
  12. 3 1
      components/esp32/component.mk
  13. 44 2
      components/esp32/cpu_start.c
  14. 103 0
      components/esp32/crosscore_int.c
  15. 1 1
      components/esp32/gdbstub.c
  16. 4 0
      components/esp32/heap_alloc_caps.c
  17. 21 0
      components/esp32/include/esp_brownout.h
  18. 42 0
      components/esp32/include/esp_crosscore_int.h
  19. 2 0
      components/esp32/include/esp_err.h
  20. 106 0
      components/esp32/include/esp_flash_data_types.h
  21. 1 1
      components/esp32/include/esp_gdbstub.h
  22. 60 0
      components/esp32/include/esp_int_wdt.h
  23. 21 0
      components/esp32/include/esp_panic.h
  24. 83 0
      components/esp32/include/esp_task_wdt.h
  25. 20 10
      components/esp32/include/esp_wifi.h
  26. 80 0
      components/esp32/include/esp_wifi_internal.h
  27. 10 5
      components/esp32/include/esp_wifi_types.h
  28. 9 3
      components/esp32/include/rom/spi_flash.h
  29. 3 0
      components/esp32/include/soc/cpu.h
  30. 5 0
      components/esp32/include/soc/dport_reg.h
  31. 3 0
      components/esp32/include/soc/rtc_cntl_reg.h
  32. 4 4
      components/esp32/include/soc/soc.h
  33. 10 0
      components/esp32/include/soc/timer_group_reg.h
  34. 96 0
      components/esp32/int_wdt.c
  35. 2 0
      components/esp32/ld/esp32.common.ld
  36. 4 2
      components/esp32/ld/esp32.rom.ld
  37. 1 1
      components/esp32/lib
  38. 83 17
      components/esp32/panic.c
  39. 173 0
      components/esp32/task_wdt.c
  40. 27 0
      components/esptool_py/Kconfig.projbuild
  41. 5 2
      components/esptool_py/Makefile.projbuild
  42. 1 1
      components/esptool_py/esptool
  43. 1 1
      components/freertos/FreeRTOS-openocd.c
  44. 11 40
      components/freertos/Kconfig
  45. 162 0
      components/freertos/include/freertos/FreeRTOS.h
  46. 6 3
      components/freertos/include/freertos/FreeRTOSConfig.h
  47. 0 7
      components/freertos/include/freertos/panic.h
  48. 16 2
      components/freertos/include/freertos/portable.h
  49. 20 0
      components/freertos/include/freertos/portmacro.h
  50. 106 4
      components/freertos/include/freertos/queue.h
  51. 361 21
      components/freertos/include/freertos/semphr.h
  52. 161 11
      components/freertos/include/freertos/task.h
  53. 1 6
      components/freertos/include/freertos/xtensa_context.h
  54. 27 36
      components/freertos/port.c
  55. 19 41
      components/freertos/portasm.S
  56. 236 97
      components/freertos/queue.c
  57. 555 143
      components/freertos/tasks.c
  58. 66 38
      components/freertos/xtensa_vectors.S
  59. 0 1915
      components/freertos/xtensa_vectors.S-new
  60. 0 2064
      components/freertos/xtensa_vectors.S-old
  61. 4 4
      components/idf_test/integration_test/CIConfigs/IT_Function_TCPIP_02.yml
  62. 1 1
      components/idf_test/integration_test/CIConfigs/IT_Function_TCPIP_03.yml
  63. 1 1
      components/idf_test/integration_test/CIConfigs/IT_Function_TCPIP_04.yml
  64. 4 4
      components/idf_test/integration_test/CIConfigs/IT_Function_WIFI_01.yml
  65. 3 3
      components/idf_test/integration_test/CIConfigs/IT_Function_WIFI_02.yml
  66. 2 3
      components/idf_test/integration_test/CIConfigs/IT_Function_WIFI_06.yml
  67. 40 0
      components/idf_test/integration_test/KnownIssues
  68. 157 236
      components/idf_test/integration_test/TestCaseAll.yml
  69. 4 0
      components/idf_test/integration_test/TestEnvAll.yml
  70. 4 0
      components/idf_test/uint_test/TestEnvAll.yml
  71. 1 1
      components/log/log.c
  72. 2 1
      components/lwip/Kconfig
  73. 3 18
      components/lwip/api/api_lib.c
  74. 7 27
      components/lwip/api/api_msg.c
  75. 3 0
      components/lwip/api/lwip_debug.c
  76. 0 5
      components/lwip/api/netbuf.c
  77. 0 5
      components/lwip/api/netdb.c
  78. 57 59
      components/lwip/api/sockets.c
  79. 6 14
      components/lwip/api/tcpip.c
  80. 1 5
      components/lwip/apps/dhcpserver.c
  81. 2 6
      components/lwip/core/dns.c
  82. 17 19
      components/lwip/core/init.c
  83. 0 5
      components/lwip/core/ipv4/autoip.c
  84. 3 7
      components/lwip/core/ipv4/dhcp.c
  85. 0 5
      components/lwip/core/ipv4/icmp.c
  86. 0 5
      components/lwip/core/ipv4/igmp.c
  87. 2 7
      components/lwip/core/ipv4/ip4.c
  88. 2 12
      components/lwip/core/ipv4/ip4_addr.c
  89. 0 5
      components/lwip/core/ipv4/ip_frag.c
  90. 0 4
      components/lwip/core/ipv6/icmp6.c
  91. 0 4
      components/lwip/core/ipv6/ip6.c
  92. 0 5
      components/lwip/core/ipv6/ip6_frag.c
  93. 0 5
      components/lwip/core/ipv6/mld6.c
  94. 0 5
      components/lwip/core/ipv6/nd6.c
  95. 0 4
      components/lwip/core/mem.c
  96. 0 4
      components/lwip/core/memp.c
  97. 4 9
      components/lwip/core/netif.c
  98. 7 52
      components/lwip/core/pbuf.c
  99. 0 4
      components/lwip/core/raw.c
  100. 0 4
      components/lwip/core/stats.c

+ 0 - 3
.gitignore

@@ -19,6 +19,3 @@ GPATH
 examples/*/sdkconfig
 examples/*/sdkconfig.old
 examples/*/build
-
-# Bootloader files
-components/bootloader/src/sdkconfig.old

+ 6 - 0
.gitlab-ci.yml

@@ -37,6 +37,12 @@ build_template_app:
     # branch
     - git checkout ${CI_BUILD_REF_NAME} || echo "Using esp-idf-template default branch..."
     - make defconfig
+    # Test debug build (default)
+    - make all V=1
+    # Now test release build
+    - make clean
+    - sed -i.bak -e's/CONFIG_OPTIMIZATION_LEVEL_DEBUG\=y/CONFIG_OPTIMIZATION_LEVEL_RELEASE=y/' sdkconfig
+    - make defconfig
     - make all V=1
 
 

+ 20 - 0
Kconfig

@@ -23,6 +23,26 @@ endmenu
 
 source "$COMPONENT_KCONFIGS_PROJBUILD"
 
+choice OPTIMIZATION_LEVEL
+    prompt "Optimization level"
+    default OPTIMIZATION_LEVEL_DEBUG
+    help
+        This option sets optimization level.
+        
+        - for "Release" setting, -Os flag is added to CFLAGS,
+         and -DNDEBUG flag is added to CPPFLAGS.
+         
+        - for "Debug" setting, -Og flag is added to CFLAGS.
+        
+        To override any of these settings, set CFLAGS and/or CPPFLAGS
+        in project makefile, before including $(IDF_PATH)/make/project.mk.
+        
+config OPTIMIZATION_LEVEL_DEBUG
+    bool "Debug"
+config OPTIMIZATION_LEVEL_RELEASE
+    bool "Release"
+endchoice
+
 menu "Component config"
 source "$COMPONENT_KCONFIGS"
 endmenu

+ 20 - 14
components/bootloader/Makefile.projbuild

@@ -8,23 +8,26 @@
 # basically runs Make in the src/ directory but it needs to zero some variables
 # the ESP-IDF project.mk makefile exports first, to not let them interfere.
 #
-ifeq ("$(IS_BOOTLOADER_BUILD)","")
+ifndef IS_BOOTLOADER_BUILD
 
 BOOTLOADER_COMPONENT_PATH := $(COMPONENT_PATH)
-BOOTLOADER_BUILD_DIR=$(BUILD_DIR_BASE)/bootloader
+BOOTLOADER_BUILD_DIR=$(abspath $(BUILD_DIR_BASE)/bootloader)
 BOOTLOADER_BIN=$(BOOTLOADER_BUILD_DIR)/bootloader.bin
+BOOTLOADER_SDKCONFIG=$(BOOTLOADER_BUILD_DIR)/sdkconfig
+
+# Custom recursive make for bootloader sub-project
+BOOTLOADER_MAKE=+$(MAKE) -C $(BOOTLOADER_COMPONENT_PATH)/src \
+	V=$(V) SDKCONFIG=$(BOOTLOADER_SDKCONFIG) \
+	BUILD_DIR_BASE=$(BOOTLOADER_BUILD_DIR) \
 
 .PHONY: bootloader-clean bootloader-flash bootloader $(BOOTLOADER_BIN)
 
-$(BOOTLOADER_BIN): $(COMPONENT_PATH)/src/sdkconfig
-	$(Q) PROJECT_PATH= \
-	BUILD_DIR_BASE=$(BOOTLOADER_BUILD_DIR) \
-	$(MAKE) -C $(BOOTLOADER_COMPONENT_PATH)/src MAKEFLAGS= V=$(V) TARGET_BIN_LAYOUT="$(BOOTLOADER_TARGET_BIN_LAYOUT)" $(BOOTLOADER_BIN)
+$(BOOTLOADER_BIN): | $(BOOTLOADER_BUILD_DIR)/sdkconfig
+	$(Q) $(BOOTLOADER_MAKE) $@
 
 bootloader-clean:
-	$(Q) PROJECT_PATH= \
-	BUILD_DIR_BASE=$(BOOTLOADER_BUILD_DIR) \
-	$(MAKE) -C $(BOOTLOADER_COMPONENT_PATH)/src app-clean MAKEFLAGS= V=$(V)
+	$(Q) $(BOOTLOADER_MAKE) app-clean config-clean
+	$(Q) rm -f $(BOOTLOADER_SDKCONFIG) $(BOOTLOADER_SDKCONFIG).old
 
 clean: bootloader-clean
 
@@ -36,14 +39,17 @@ all_binaries: $(BOOTLOADER_BIN)
 
 ESPTOOL_ALL_FLASH_ARGS += 0x1000 $(BOOTLOADER_BIN)
 
-# synchronise the project level config to the component's
+# bootloader-flash calls flash in the bootloader dummy project
+bootloader-flash: $(BOOTLOADER_BIN)
+	$(BOOTLOADER_MAKE) flash
+
+# synchronise the project level config to the bootloader's
 # config
-$(COMPONENT_PATH)/src/sdkconfig: $(PROJECT_PATH)/sdkconfig
+$(BOOTLOADER_SDKCONFIG): $(PROJECT_PATH)/sdkconfig | $(BOOTLOADER_BUILD_DIR)
 	$(Q) cp $< $@
 
-# bootloader-flash calls flash in the bootloader dummy project
-bootloader-flash: $(BOOTLOADER_BIN)
-	$(MAKE) -C $(BOOTLOADER_COMPONENT_PATH)/src flash MAKEFLAGS= V=$(V)
+$(BOOTLOADER_BUILD_DIR):
+	$(Q) mkdir -p $@
 
 else
 CFLAGS += -D BOOTLOADER_BUILD=1 -I $(IDF_PATH)/components/esp32/include 

+ 2 - 1
components/bootloader/src/Makefile

@@ -4,12 +4,13 @@
 #
 
 PROJECT_NAME := bootloader
-COMPONENTS := esptool_py bootloader log
+COMPONENTS := esptool_py bootloader log spi_flash
 
 # The bootloader pseudo-component is also included in this build, for its Kconfig.projbuild to be included.
 #
 # IS_BOOTLOADER_BUILD tells the component Makefile.projbuild to be a no-op
 IS_BOOTLOADER_BUILD := 1
+export IS_BOOTLOADER_BUILD
 
 #We cannot include the esp32 component directly but we need its includes. 
 #This is fixed by adding CFLAGS from Makefile.projbuild

+ 7 - 73
components/bootloader/src/main/bootloader_config.h

@@ -20,12 +20,13 @@
 extern "C"
 {
 #endif
+
+#include "esp_flash_data_types.h"
+
 #define BOOT_VERSION "V0.1"
 #define SPI_SEC_SIZE 0x1000
 #define MEM_CACHE(offset)   (uint8_t *)(0x3f400000 + (offset))
 #define CACHE_READ_32(offset)   ((uint32_t *)(0x3f400000 + (offset)))
-#define PARTITION_ADD 0x4000
-#define PARTITION_MAGIC 0x50AA
 #define IROM_LOW    0x400D0000
 #define IROM_HIGH   0x40400000
 #define DROM_LOW    0x3F400000
@@ -35,73 +36,6 @@ extern "C"
 #define RTC_DATA_LOW  0x50000000
 #define RTC_DATA_HIGH 0x50002000
 
-/*spi mode,saved in third byte in flash */
-enum {
-    SPI_MODE_QIO,
-    SPI_MODE_QOUT,
-    SPI_MODE_DIO,
-    SPI_MODE_DOUT,
-    SPI_MODE_FAST_READ,
-    SPI_MODE_SLOW_READ
-};
-/* spi speed*/
-enum {
-    SPI_SPEED_40M,
-    SPI_SPEED_26M,
-    SPI_SPEED_20M,
-    SPI_SPEED_80M = 0xF
-};
-/*suppport flash size in esp32 */
-enum {
-    SPI_SIZE_1MB = 0,
-    SPI_SIZE_2MB,
-    SPI_SIZE_4MB,
-    SPI_SIZE_8MB,
-    SPI_SIZE_16MB,
-    SPI_SIZE_MAX
-};
-
-
-struct flash_hdr {
-    char magic;
-    char blocks;
-    char spi_mode;      /* flag of flash read mode in unpackage and usage in future */
-    char spi_speed: 4;  /* low bit */
-    char spi_size: 4;
-    unsigned int entry_addr;
-    uint8_t encrypt_flag;    /* encrypt flag */
-    uint8_t secury_boot_flag; /* secury boot flag */
-    char extra_header[14]; /* ESP32 additional header, unused by second bootloader */
-};
-
-/* each header of flash bin block */
-struct block_hdr {
-    unsigned int load_addr;
-    unsigned int data_len;
-};
-
-/* OTA selection structure (two copies in the OTA data partition.)
-
-   Size of 32 bytes is friendly to flash encryption */
-typedef struct {
-    uint32_t ota_seq;
-    uint8_t  seq_label[24];
-    uint32_t crc; /* CRC32 of ota_seq field only */
-} ota_select;
-
-typedef struct {
-    uint32_t offset;
-    uint32_t size;
-} partition_pos_t;
-
-typedef struct {
-	uint16_t magic;
-	uint8_t  type;        /* partition Type */
-    uint8_t  subtype;     /* part_subtype */
-    partition_pos_t pos;
-	uint8_t  label[16];    /* label for the partition */
-    uint8_t  reserved[4];     /* reserved */
-} partition_info_t;
 
 #define PART_TYPE_APP 0x00
 #define PART_SUBTYPE_FACTORY  0x00
@@ -120,10 +54,10 @@ typedef struct {
 #define SPI_ERROR_LOG "spi flash error"
 
 typedef struct {
-    partition_pos_t ota_info;
-    partition_pos_t factory;
-    partition_pos_t test;
-    partition_pos_t ota[16];
+    esp_partition_pos_t ota_info;
+    esp_partition_pos_t factory;
+    esp_partition_pos_t test;
+    esp_partition_pos_t ota[16];
     uint32_t app_count;
     uint32_t selected_subtype;
 } bootloader_state_t;

+ 80 - 67
components/bootloader/src/main/bootloader_start.c

@@ -3,7 +3,7 @@
 // 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
@@ -49,8 +49,8 @@ flash cache is down and the app CPU is in reset. We do have a stack, so we can d
 extern void Cache_Flush(int);
 
 void bootloader_main();
-void unpack_load_app(const partition_pos_t *app_node);
-void print_flash_info(struct flash_hdr* pfhdr);
+void unpack_load_app(const esp_partition_pos_t *app_node);
+void print_flash_info(const esp_image_header_t* pfhdr);
 void IRAM_ATTR set_cache_and_start_app(uint32_t drom_addr,
     uint32_t drom_load_addr,
     uint32_t drom_size,
@@ -58,6 +58,7 @@ void IRAM_ATTR set_cache_and_start_app(uint32_t drom_addr,
     uint32_t irom_load_addr,
     uint32_t irom_size,
     uint32_t entry_addr);
+static void update_flash_config(const esp_image_header_t* pfhdr);
 
 
 void IRAM_ATTR call_start_cpu0()
@@ -153,7 +154,7 @@ void boot_cache_redirect( uint32_t pos, size_t size )
  */
 bool load_partition_table(bootloader_state_t* bs, uint32_t addr)
 {
-    partition_info_t partition;
+    esp_partition_info_t partition;
     uint32_t end = addr + 0x1000;
     int index = 0;
     char *partition_usage;
@@ -167,7 +168,7 @@ bool load_partition_table(bootloader_state_t* bs, uint32_t addr)
         ESP_LOGD(TAG, "type=%x subtype=%x", partition.type, partition.subtype);
         partition_usage = "unknown";
 
-        if (partition.magic == PARTITION_MAGIC) { /* valid partition definition */
+        if (partition.magic == ESP_PARTITION_MAGIC) { /* valid partition definition */
             switch(partition.type) {
             case PART_TYPE_APP: /* app partition */
                 switch(partition.subtype) {
@@ -230,12 +231,12 @@ bool load_partition_table(bootloader_state_t* bs, uint32_t addr)
     return true;
 }
 
-static uint32_t ota_select_crc(const ota_select *s)
+static uint32_t ota_select_crc(const esp_ota_select_entry_t *s)
 {
   return crc32_le(UINT32_MAX, (uint8_t*)&s->ota_seq, 4);
 }
 
-static bool ota_select_valid(const ota_select *s)
+static bool ota_select_valid(const esp_ota_select_entry_t *s)
 {
   return s->ota_seq != UINT32_MAX && s->crc == ota_select_crc(s);
 }
@@ -251,30 +252,32 @@ void bootloader_main()
 {
     ESP_LOGI(TAG, "Espressif ESP32 2nd stage bootloader v. %s", BOOT_VERSION);
 
-    struct flash_hdr    fhdr;
+    esp_image_header_t fhdr;
     bootloader_state_t bs;
     SpiFlashOpResult spiRet1,spiRet2;    
-    ota_select sa,sb;
+    esp_ota_select_entry_t sa,sb;
     memset(&bs, 0, sizeof(bs));
 
     ESP_LOGI(TAG, "compile time " __TIME__ );
-    /* close watch dog here */
+    /* 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 );
     SPIUnlock();
     /*register first sector in drom0 page 0 */
     boot_cache_redirect( 0, 0x5000 );
 
-    memcpy((unsigned int *) &fhdr, MEM_CACHE(0x1000), sizeof(struct flash_hdr) );
+    memcpy((unsigned int *) &fhdr, MEM_CACHE(0x1000), sizeof(esp_image_header_t) );
 
     print_flash_info(&fhdr);
 
-    if (!load_partition_table(&bs, PARTITION_ADD)) {
+    update_flash_config(&fhdr);
+
+    if (!load_partition_table(&bs, ESP_PARTITION_TABLE_ADDR)) {
         ESP_LOGE(TAG, "load partition table error!");
         return;
     }
 
-    partition_pos_t load_part_pos;
+    esp_partition_pos_t load_part_pos;
 
     if (bs.ota_info.offset != 0) {              // check if partition table has OTA info partition
         //ESP_LOGE("OTA info sector handling is not implemented");
@@ -290,14 +293,14 @@ void bootloader_main()
             sb.crc = ota_select_crc(&sb);
 
             Cache_Read_Disable(0);  
-            spiRet1 = SPIEraseSector(bs.ota_info.offset/0x1000);       
-            spiRet2 = SPIEraseSector(bs.ota_info.offset/0x1000+1);       
+            spiRet1 = SPIEraseSector(bs.ota_info.offset/0x1000);
+            spiRet2 = SPIEraseSector(bs.ota_info.offset/0x1000+1);
             if (spiRet1 != SPI_FLASH_RESULT_OK || spiRet2 != SPI_FLASH_RESULT_OK ) {  
                 ESP_LOGE(TAG, SPI_ERROR_LOG);
                 return;
             } 
-            spiRet1 = SPIWrite(bs.ota_info.offset,(uint32_t *)&sa,sizeof(ota_select));
-            spiRet2 = SPIWrite(bs.ota_info.offset + 0x1000,(uint32_t *)&sb,sizeof(ota_select));
+            spiRet1 = SPIWrite(bs.ota_info.offset,(uint32_t *)&sa,sizeof(esp_ota_select_entry_t));
+            spiRet2 = SPIWrite(bs.ota_info.offset + 0x1000,(uint32_t *)&sb,sizeof(esp_ota_select_entry_t));
             if (spiRet1 != SPI_FLASH_RESULT_OK || spiRet2 != SPI_FLASH_RESULT_OK ) {  
                 ESP_LOGE(TAG, SPI_ERROR_LOG);
                 return;
@@ -326,7 +329,7 @@ void bootloader_main()
     }
 
     ESP_LOGI(TAG, "Loading app partition at offset %08x", load_part_pos);
-    if(fhdr.secury_boot_flag == 0x01) {
+    if(fhdr.secure_boot_flag == 0x01) {
         /* protect the 2nd_boot  */    
         if(false == secure_boot()){
             ESP_LOGE(TAG, "secure boot failed");
@@ -347,12 +350,12 @@ void bootloader_main()
 }
 
 
-void unpack_load_app(const partition_pos_t* partition)
+void unpack_load_app(const esp_partition_pos_t* partition)
 {
     boot_cache_redirect(partition->offset, partition->size);
 
     uint32_t pos = 0;
-    struct flash_hdr image_header;
+    esp_image_header_t image_header;
     memcpy(&image_header, MEM_CACHE(pos), sizeof(image_header));
     pos += sizeof(image_header);
 
@@ -364,7 +367,7 @@ void unpack_load_app(const partition_pos_t* partition)
     uint32_t irom_size = 0;
 
     /* Reload the RTC memory sections whenever a non-deepsleep reset
-       is occuring */
+       is occurring */
     bool load_rtc_memory = rtc_get_reset_reason(0) != DEEPSLEEP_RESET;
 
     ESP_LOGD(TAG, "bin_header: %u %u %u %u %08x", image_header.magic,
@@ -376,7 +379,7 @@ void unpack_load_app(const partition_pos_t* partition)
     for (uint32_t section_index = 0;
             section_index < image_header.blocks;
             ++section_index) {
-        struct block_hdr section_header = {0};
+        esp_image_section_header_t section_header = {0};
         memcpy(&section_header, MEM_CACHE(pos), sizeof(section_header));
         pos += sizeof(section_header);
 
@@ -482,67 +485,84 @@ void IRAM_ATTR set_cache_and_start_app(
     (*entry)();
 }
 
+static void update_flash_config(const esp_image_header_t* pfhdr)
+{
+    uint32_t size;
+    switch(pfhdr->spi_size) {
+        case ESP_IMAGE_FLASH_SIZE_1MB:
+            size = 1;
+            break;
+        case ESP_IMAGE_FLASH_SIZE_2MB:
+            size = 2;
+            break;
+        case ESP_IMAGE_FLASH_SIZE_4MB:
+            size = 4;
+            break;
+        case ESP_IMAGE_FLASH_SIZE_8MB:
+            size = 8;
+            break;
+        case ESP_IMAGE_FLASH_SIZE_16MB:
+            size = 16;
+            break;
+        default:
+            size = 2;
+    }
+    Cache_Read_Disable( 0 );
+    // Set flash chip size
+    SPIParamCfg(g_rom_flashchip.deviceId, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff);
+    // TODO: set mode
+    // TODO: set frequency
+    Cache_Flush(0);
+    Cache_Read_Enable( 0 );
+}
 
-void print_flash_info(struct flash_hdr* pfhdr)
+void print_flash_info(const esp_image_header_t* phdr)
 {
 #if (BOOT_LOG_LEVEL >= BOOT_LOG_LEVEL_NOTICE)
 
-    struct flash_hdr fhdr = *pfhdr;
-
-    ESP_LOGD(TAG, "magic %02x", fhdr.magic );
-    ESP_LOGD(TAG, "blocks %02x", fhdr.blocks );
-    ESP_LOGD(TAG, "spi_mode %02x", fhdr.spi_mode );
-    ESP_LOGD(TAG, "spi_speed %02x", fhdr.spi_speed );
-    ESP_LOGD(TAG, "spi_size %02x", fhdr.spi_size );
+    ESP_LOGD(TAG, "magic %02x", phdr->magic );
+    ESP_LOGD(TAG, "blocks %02x", phdr->blocks );
+    ESP_LOGD(TAG, "spi_mode %02x", phdr->spi_mode );
+    ESP_LOGD(TAG, "spi_speed %02x", phdr->spi_speed );
+    ESP_LOGD(TAG, "spi_size %02x", phdr->spi_size );
 
     const char* str;
-    switch ( fhdr.spi_speed ) {
-    case SPI_SPEED_40M:
+    switch ( phdr->spi_speed ) {
+    case ESP_IMAGE_SPI_SPEED_40M:
         str = "40MHz";
         break;
-
-    case SPI_SPEED_26M:
+    case ESP_IMAGE_SPI_SPEED_26M:
         str = "26.7MHz";
         break;
-
-    case SPI_SPEED_20M:
+    case ESP_IMAGE_SPI_SPEED_20M:
         str = "20MHz";
         break;
-
-    case SPI_SPEED_80M:
+    case ESP_IMAGE_SPI_SPEED_80M:
         str = "80MHz";
         break;
-
     default:
         str = "20MHz";
         break;
     }
     ESP_LOGI(TAG, "SPI Speed      : %s", str );
 
-    
-
-    switch ( fhdr.spi_mode ) {
-    case SPI_MODE_QIO:
+    switch ( phdr->spi_mode ) {
+    case ESP_IMAGE_SPI_MODE_QIO:
         str = "QIO";
         break;
-
-    case SPI_MODE_QOUT:
+    case ESP_IMAGE_SPI_MODE_QOUT:
         str = "QOUT";
         break;
-
-    case SPI_MODE_DIO:
+    case ESP_IMAGE_SPI_MODE_DIO:
         str = "DIO";
         break;
-
-    case SPI_MODE_DOUT:
+    case ESP_IMAGE_SPI_MODE_DOUT:
         str = "DOUT";
         break;
-
-    case SPI_MODE_FAST_READ:
+    case ESP_IMAGE_SPI_MODE_FAST_READ:
         str = "FAST READ";
         break;
-
-    case SPI_MODE_SLOW_READ:
+    case ESP_IMAGE_SPI_MODE_SLOW_READ:
         str = "SLOW READ";
         break;
     default:
@@ -551,31 +571,24 @@ void print_flash_info(struct flash_hdr* pfhdr)
     }
     ESP_LOGI(TAG, "SPI Mode       : %s", str );
 
-    
-
-    switch ( fhdr.spi_size ) {
-    case SPI_SIZE_1MB:
+    switch ( phdr->spi_size ) {
+    case ESP_IMAGE_FLASH_SIZE_1MB:
         str = "1MB";
         break;
-
-    case SPI_SIZE_2MB:
+    case ESP_IMAGE_FLASH_SIZE_2MB:
         str = "2MB";
         break;
-
-    case SPI_SIZE_4MB:
+    case ESP_IMAGE_FLASH_SIZE_4MB:
         str = "4MB";
         break;
-
-    case SPI_SIZE_8MB:
+    case ESP_IMAGE_FLASH_SIZE_8MB:
         str = "8MB";
         break;
-
-    case SPI_SIZE_16MB:
+    case ESP_IMAGE_FLASH_SIZE_16MB:
         str = "16MB";
         break;
-
     default:
-        str = "1MB";
+        str = "2MB";
         break;
     }
     ESP_LOGI(TAG, "SPI Flash Size : %s", str );

+ 1 - 1
components/bootloader/src/main/flash_encrypt.c

@@ -128,7 +128,7 @@ bool flash_encrypt(bootloader_state_t *bs)
            return false;
        }
         /* encrypt partition table */
-       if (false ==  flash_encrypt_write(PARTITION_ADD, SPI_SEC_SIZE)) {
+       if (false ==  flash_encrypt_write(ESP_PARTITION_TABLE_ADDR, SPI_SEC_SIZE)) {
            ESP_LOGE(TAG, "encrypt partition table error");
            return false;
        }

+ 1 - 1
components/bt/lib

@@ -1 +1 @@
-Subproject commit 0c3df46cb357b795ff217e68f7a8fb56d68c537f
+Subproject commit 116bca54958c21b8b5b5f79a427744131e21f12a

+ 182 - 1
components/esp32/Kconfig

@@ -63,14 +63,28 @@ config MEMMAP_TRACEMEM
         of memory that can't be used for general purposes anymore. Disable this if you do not know
         what this is.
 
+config MEMMAP_TRACEMEM_TWOBANKS
+    bool "Reserve memory for tracing both pro as well as app cpu execution"
+    default "n"
+    depends on MEMMAP_TRACEMEM && MEMMAP_SMP
+    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
     hex
-    default 0x8000 if MEMMAP_TRACEMEM
+    default 0x8000 if MEMMAP_TRACEMEM && MEMMAP_TRACEMEM_TWOBANKS
+    default 0x4000 if MEMMAP_TRACEMEM && !MEMMAP_TRACEMEM_TWOBANKS
     default 0x0
 
+# Not implemented and/or needs new silicon rev to work
 config MEMMAP_SPISRAM
     bool "Use external SPI SRAM chip as main memory"
+    depends on ESP32_NEEDS_NEW_SILICON_REV
     default "n"
     help
         The ESP32 can control an external SPI SRAM chip, adding the memory it contains to the 
@@ -140,4 +154,171 @@ config ULP_COPROC_RESERVE_MEM
     default 0
     depends on !ULP_COPROC_ENABLED
 
+
+choice ESP32_PANIC
+    prompt "Panic handler behaviour"
+    default ESP32_PANIC_PRINT_REBOOT
+    help
+        If FreeRTOS detects unexpected behaviour or an unhandled exception, the panic handler is 
+        invoked. Configure the panic handlers action here.
+
+config ESP32_PANIC_PRINT_HALT
+    bool "Print registers and halt"
+    help
+        Outputs the relevant registers over the serial port and halt the 
+        processor. Needs a manual reset to restart.
+
+config ESP32_PANIC_PRINT_REBOOT
+    bool "Print registers and reboot"
+    help
+        Outputs the relevant registers over the serial port and immediately
+        reset the processor.
+
+config ESP32_PANIC_SILENT_REBOOT
+    bool "Silent reboot"
+    help
+        Just resets the processor without outputting anything
+
+config ESP32_PANIC_GDBSTUB
+    bool "Invoke GDBStub"
+    help
+        Invoke gdbstub on the serial port, allowing for gdb to attach to it to do a postmortem
+        of the crash.
+endchoice
+
+config ESP32_DEBUG_OCDAWARE
+    bool "Make exception and panic handlers JTAG/OCD aware"
+    default y
+    help
+        The FreeRTOS panic and unhandled exception handers can detect a JTAG OCD debugger and
+        instead of panicking, have the debugger stop on the offending instruction.
+
+
+config INT_WDT
+    bool "Interrupt watchdog"
+    default y
+    help
+        This watchdog timer can detect if the FreeRTOS tick interrupt has not been called for a certain time,
+        either because a task turned off interrupts and did not turn them on for a long time, or because an
+        interrupt handler did not return. It will try to invoke the panic handler first and failing that
+        reset the SoC.
+
+config INT_WDT_TIMEOUT_MS
+    int "Interrupt watchdog timeout (ms)"
+    depends on INT_WDT
+    default 300
+    range 10 10000
+    help
+        The timeout of the watchdog, in miliseconds. Make this higher than the FreeRTOS tick rate.
+
+config INT_WDT_CHECK_CPU1
+    bool "Also watch CPU1 tick interrupt"
+    depends on INT_WDT && !FREERTOS_UNICORE
+    default y
+    help
+        Also detect if interrupts on CPU 1 are disabled for too long.
+
+config TASK_WDT
+    bool "Task watchdog"
+    default y
+    help
+        This watchdog timer can be used to make sure individual tasks are still running.
+
+config TASK_WDT_PANIC
+    bool "Invoke panic handler when Task Watchdog is triggered"
+    depends on TASK_WDT
+    default n
+    help
+        Normally, the Task Watchdog will only print out a warning if it detects it has not
+        been fed. If this is enabled, it will invoke the panic handler instead, which
+        can then halt or reboot the chip.
+
+config TASK_WDT_TIMEOUT_S
+    int "Task watchdog timeout (seconds)"
+    depends on TASK_WDT
+    range 1 60
+    default 5
+    help
+        Timeout for the task WDT, in seconds.
+
+config TASK_WDT_CHECK_IDLE_TASK
+    bool "Task watchdog watches CPU0 idle task"
+    depends on TASK_WDT
+    default y
+    help
+        With this turned on, the task WDT can detect if the idle task is not called within the task
+        watchdog timeout period. The idle task not being called usually is a symptom of another
+        task hoarding the CPU. It is also a bad thing because FreeRTOS household tasks depend on the 
+        idle task getting some runtime every now and then. Take Care: With this disabled, this 
+        watchdog will trigger if no tasks register themselves within the timeout value.
+
+config TASK_WDT_CHECK_IDLE_TASK_CPU1
+    bool "Task watchdog also watches CPU1 idle task"
+    depends on TASK_WDT_CHECK_IDLE_TASK && !FREERTOS_UNICORE
+    default y
+    help
+        Also check the idle task that runs on CPU1.
+
+#The brownout detector code is disabled (by making it depend on a nonexisting symbol) because the current revision of ESP32
+#silicon has a bug in the brown-out detector, rendering it unusable for resetting the CPU.
+config BROWNOUT_DET
+    bool "Hardware brownout detect & reset"
+    default y
+    depends on NEEDS_ESP32_NEW_SILICON_REV
+    help
+        The ESP32 has a built-in brownout detector which can detect if the voltage is lower than 
+        a specific value. If this happens, it will reset the chip in order to prevent unintended
+        behaviour.
+
+choice BROWNOUT_DET_LVL_SEL
+    prompt "Brownout voltage level"
+    depends on BROWNOUT_DET
+    default BROWNOUT_DET_LVL_SEL_25
+    help
+        The brownout detector will reset the chip when the supply voltage is below this level.
+
+#The voltage levels here are estimates, more work needs to be done to figure out the exact voltages
+#of the brownout threshold levels.
+config BROWNOUT_DET_LVL_SEL_0
+    bool "2.1V"
+config BROWNOUT_DET_LVL_SEL_1
+    bool "2.2V"
+config BROWNOUT_DET_LVL_SEL_2
+    bool "2.3V"
+config BROWNOUT_DET_LVL_SEL_3
+    bool "2.4V"
+config BROWNOUT_DET_LVL_SEL_4
+    bool "2.5V"
+config BROWNOUT_DET_LVL_SEL_5
+    bool "2.6V"
+config BROWNOUT_DET_LVL_SEL_6
+    bool "2.7V"
+config BROWNOUT_DET_LVL_SEL_7
+    bool "2.8V"
+endchoice
+
+config BROWNOUT_DET_LVL
+    int
+    default 0 if BROWNOUT_DET_LVL_SEL_0
+    default 1 if BROWNOUT_DET_LVL_SEL_1
+    default 2 if BROWNOUT_DET_LVL_SEL_2
+    default 3 if BROWNOUT_DET_LVL_SEL_3
+    default 4 if BROWNOUT_DET_LVL_SEL_4
+    default 5 if BROWNOUT_DET_LVL_SEL_5
+    default 6 if BROWNOUT_DET_LVL_SEL_6
+    default 7 if BROWNOUT_DET_LVL_SEL_7
+
+
+config BROWNOUT_DET_RESETDELAY
+    int "Brownout reset delay (in uS)"
+    depends on BROWNOUT_DET
+    range 0 6820
+    default 1000
+    help
+        The brownout detector can reset the chip after a certain delay, in order to make sure e.g. a voltage dip has entirely passed
+        before trying to restart the chip. You can set the delay here.
+
+
+
+
 endmenu

+ 39 - 0
components/esp32/brownout.c

@@ -0,0 +1,39 @@
+// 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 <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include "sdkconfig.h"
+#include "soc/soc.h"
+#include "soc/rtc_cntl_reg.h"
+
+
+#if CONFIG_BROWNOUT_DET
+/*
+This file is included in esp-idf, but the menuconfig option for this is disabled because a silicon bug
+prohibits the brownout detector from functioning correctly on the ESP32.
+*/
+
+void esp_brownout_init() {
+    WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 
+            RTC_CNTL_BROWN_OUT_ENA | (CONFIG_BROWNOUT_DET_LVL << RTC_CNTL_DBROWN_OUT_THRES_S) |
+            RTC_CNTL_BROWN_OUT_RST_ENA | (((CONFIG_BROWNOUT_DET_RESETDELAY*150)/1000) << RTC_CNTL_BROWN_OUT_RST_WAIT_S) |
+            RTC_CNTL_BROWN_OUT_PD_RF_ENA|RTC_CNTL_BROWN_OUT_CLOSE_FLASH_ENA);
+
+}
+
+#endif

+ 3 - 1
components/esp32/component.mk

@@ -6,7 +6,7 @@
 # lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable,
 # please read the esp-idf build system document if you need to do this.
 #
--include $(PROJECT_PATH)/build/include/config/auto.conf
+-include include/config/auto.conf
 
 COMPONENT_SRCDIRS := . hwcrypto
 
@@ -44,6 +44,8 @@ $(COMPONENT_LIBRARY): $(ALL_LIB_FILES)
 # saves us from having to add the target to a Makefile.projbuild
 $(COMPONENT_LIBRARY): esp32_out.ld
 
+# .. is BUILD_DIR_BASE here, as component makefiles
+# are evaluated with CWD=component build dir
 esp32_out.ld: $(COMPONENT_PATH)/ld/esp32.ld ../include/sdkconfig.h
 	$(CC) -I ../include -C -P -x c -E $< -o $@
 

+ 44 - 2
components/esp32/cpu_start.c

@@ -41,7 +41,14 @@
 #include "esp_event.h"
 #include "esp_spi_flash.h"
 #include "esp_ipc.h"
+#include "esp_crosscore_int.h"
 #include "esp_log.h"
+#include "esp_vfs_dev.h"
+#include "esp_newlib.h"
+#include "esp_brownout.h"
+#include "esp_int_wdt.h"
+#include "esp_task_wdt.h"
+#include "trax.h"
 
 void start_cpu0(void) __attribute__((weak, alias("start_cpu0_default")));
 void start_cpu0_default(void) IRAM_ATTR;
@@ -54,7 +61,6 @@ static bool app_cpu_started = false;
 
 static void do_global_ctors(void);
 static void main_task(void* args);
-extern void ets_setup_syscalls(void);
 extern void app_main(void);
 
 extern int _bss_start;
@@ -97,6 +103,10 @@ void IRAM_ATTR call_start_cpu0()
 #if !CONFIG_FREERTOS_UNICORE
     ESP_EARLY_LOGI(TAG, "Starting app cpu, entry point is %p", call_start_cpu1);
 
+    //Un-stall the app cpu; the panic handler may have stalled it.
+    CLEAR_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, RTC_CNTL_SW_STALL_APPCPU_C1_M);
+    CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_STALL_APPCPU_C0_M);
+    //Enable clock gating and reset the app cpu.
     SET_PERI_REG_MASK(DPORT_APPCPU_CTRL_B_REG, DPORT_APPCPU_CLKGATE_EN);
     CLEAR_PERI_REG_MASK(DPORT_APPCPU_CTRL_C_REG, DPORT_APPCPU_RUNSTALL);
     SET_PERI_REG_MASK(DPORT_APPCPU_CTRL_A_REG, DPORT_APPCPU_RESETTING);
@@ -131,12 +141,40 @@ void IRAM_ATTR call_start_cpu1()
 
 void start_cpu0_default(void)
 {
+//Enable trace memory and immediately start trace.
+#if CONFIG_MEMMAP_TRACEMEM
+#if CONFIG_MEMMAP_TRACEMEM_TWOBANKS
+    trax_enable(TRAX_ENA_PRO_APP);
+#else
+    trax_enable(TRAX_ENA_PRO);
+#endif
+    trax_start_trace(TRAX_DOWNCOUNT_WORDS);
+#endif
     esp_set_cpu_freq();     // set CPU frequency configured in menuconfig
     uart_div_modify(0, (APB_CLK_FREQ << 4) / 115200);
-    ets_setup_syscalls();
+#if CONFIG_BROWNOUT_DET
+    esp_brownout_init();
+#endif
+#if CONFIG_INT_WDT
+    esp_int_wdt_init();
+#endif
+#if CONFIG_TASK_WDT
+    esp_task_wdt_init();
+#endif
+    esp_setup_syscalls();
+    esp_vfs_dev_uart_register();
+    esp_reent_init(_GLOBAL_REENT);
+    const char* default_uart_dev = "/dev/uart/0";
+    _GLOBAL_REENT->_stdout = fopen(default_uart_dev, "w");
+    _GLOBAL_REENT->_stderr = fopen(default_uart_dev, "w");
+    _GLOBAL_REENT->_stdin  = fopen(default_uart_dev, "r");
     do_global_ctors();
+#if !CONFIG_FREERTOS_UNICORE
+    esp_crosscore_int_init();
+#endif
     esp_ipc_init();
     spi_flash_init();
+
     xTaskCreatePinnedToCore(&main_task, "main",
             ESP_TASK_MAIN_STACK, NULL,
             ESP_TASK_MAIN_PRIO, NULL, 0);
@@ -147,10 +185,14 @@ void start_cpu0_default(void)
 #if !CONFIG_FREERTOS_UNICORE
 void start_cpu1_default(void)
 {
+#if CONFIG_MEMMAP_TRACEMEM_TWOBANKS
+    trax_start_trace(TRAX_DOWNCOUNT_WORDS);
+#endif
     // Wait for FreeRTOS initialization to finish on PRO CPU
     while (port_xSchedulerRunning[0] == 0) {
         ;
     }
+    esp_crosscore_int_init();
     ESP_LOGI(TAG, "Starting scheduler on APP CPU.");
     xPortStartScheduler();
 }

+ 103 - 0
components/esp32/crosscore_int.c

@@ -0,0 +1,103 @@
+// 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 <stdint.h>
+#include <string.h>
+
+#include "esp_attr.h"
+#include "esp_err.h"
+#include "esp_intr.h"
+
+#include "rom/ets_sys.h"
+#include "rom/uart.h"
+
+#include "soc/cpu.h"
+#include "soc/dport_reg.h"
+#include "soc/io_mux_reg.h"
+#include "soc/rtc_cntl_reg.h"
+
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "freertos/semphr.h"
+#include "freertos/queue.h"
+#include "freertos/portmacro.h"
+
+
+#define REASON_YIELD (1<<0)
+
+static portMUX_TYPE reasonSpinlock = portMUX_INITIALIZER_UNLOCKED;
+static volatile uint32_t reason[ portNUM_PROCESSORS ];
+
+
+/*
+ToDo: There is a small chance the CPU already has yielded when this ISR is serviced. In that case, it's running the intended task but
+the ISR will cause it to switch _away_ from it. portYIELD_FROM_ISR will probably just schedule the task again, but have to check that.
+*/
+static void esp_crosscore_isr(void *arg) {
+    uint32_t myReasonVal;
+#if 0
+    //A pointer to the correct reason array item is passed to this ISR.
+    volatile uint32_t *myReason=arg;
+#else
+    //The previous line does not work yet, the interrupt code needs work to understand two separate interrupt and argument
+    //tables... this is a valid but slightly less optimal replacement.
+    volatile uint32_t *myReason=&reason[xPortGetCoreID()];
+#endif
+    //Clear the interrupt first.
+    if (xPortGetCoreID()==0) {
+        WRITE_PERI_REG(DPORT_CPU_INTR_FROM_CPU_0_REG, 0);
+    } else {
+        WRITE_PERI_REG(DPORT_CPU_INTR_FROM_CPU_1_REG, 0);
+    }
+    //Grab the reason and clear it.
+    portENTER_CRITICAL(&reasonSpinlock);
+    myReasonVal=*myReason;
+    *myReason=0;
+    portEXIT_CRITICAL(&reasonSpinlock);
+
+    //Check what we need to do.
+    if (myReasonVal&REASON_YIELD) {
+        portYIELD_FROM_ISR();
+    }
+}
+
+//Initialize the crosscore interrupt on this core. Call this once
+//on each active core.
+void esp_crosscore_int_init() {
+    portENTER_CRITICAL(&reasonSpinlock);
+    reason[xPortGetCoreID()]=0;
+    portEXIT_CRITICAL(&reasonSpinlock);
+    ESP_INTR_DISABLE(ETS_FROM_CPU_INUM);
+    if (xPortGetCoreID()==0) {
+        intr_matrix_set(xPortGetCoreID(), ETS_FROM_CPU_INTR0_SOURCE, ETS_FROM_CPU_INUM);
+    } else {
+        intr_matrix_set(xPortGetCoreID(), ETS_FROM_CPU_INTR1_SOURCE, ETS_FROM_CPU_INUM);
+    }
+    xt_set_interrupt_handler(ETS_FROM_CPU_INUM, esp_crosscore_isr, (void*)&reason[xPortGetCoreID()]);
+    ESP_INTR_ENABLE(ETS_FROM_CPU_INUM);
+}
+
+void esp_crosscore_int_send_yield(int coreId) {
+    assert(coreId<portNUM_PROCESSORS);
+    //Mark the reason we interrupt the other CPU
+    portENTER_CRITICAL(&reasonSpinlock);
+    reason[coreId]|=REASON_YIELD;
+    portEXIT_CRITICAL(&reasonSpinlock);
+    //Poke the other CPU.
+    if (coreId==0) {
+        WRITE_PERI_REG(DPORT_CPU_INTR_FROM_CPU_0_REG, DPORT_CPU_INTR_FROM_CPU_0);
+    } else {
+        WRITE_PERI_REG(DPORT_CPU_INTR_FROM_CPU_1_REG, DPORT_CPU_INTR_FROM_CPU_1);
+    }
+}
+

+ 1 - 1
components/freertos/gdbstub.c → components/esp32/gdbstub.c

@@ -24,7 +24,7 @@
 #include "soc/uart_reg.h"
 #include "soc/io_mux_reg.h"
 
-#include "gdbstub.h"
+#include "esp_gdbstub.h"
 
 //Length of buffer used to reserve GDB commands. Has to be at least able to fit the G command, which
 //implies a minimum size of about 320 bytes.

+ 4 - 0
components/esp32/heap_alloc_caps.c

@@ -186,7 +186,11 @@ void heap_alloc_caps_init() {
 #endif
 
 #if CONFIG_MEMMAP_TRACEMEM
+#if CONFIG_MEMMAP_TRACEMEM_TWOBANKS
     disable_mem_region((void*)0x3fff8000, (void*)0x40000000); //knock out trace mem region
+#else
+    disable_mem_region((void*)0x3fff8000, (void*)0x3fffc000); //knock out trace mem region
+#endif
 #endif
 
 #if 0

+ 21 - 0
components/esp32/include/esp_brownout.h

@@ -0,0 +1,21 @@
+// 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 __ESP_BROWNOUT_H
+#define __ESP_BROWNOUT_H
+
+void esp_brownout_init();
+
+#endif

+ 42 - 0
components/esp32/include/esp_crosscore_int.h

@@ -0,0 +1,42 @@
+// 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 __ESP_CROSSCORE_INT_H
+#define __ESP_CROSSCORE_INT_H
+
+
+/**
+ * Initialize the crosscore interrupt system for this CPU.
+ * This needs to be called once on every CPU that is used
+ * by FreeRTOS.
+ *
+ * If multicore FreeRTOS support is enabled, this will be
+ * called automatically by the startup code and should not
+ * be called manually.
+ */
+void esp_crosscore_int_init();
+
+
+/**
+ * Send an interrupt to a CPU indicating it should yield its
+ * currently running task in favour of a higher-priority task
+ * that presumably just woke up.
+ *
+ * This is used internally by FreeRTOS in multicore mode
+ * and should not be called by the user.
+ *
+ * @param coreID Core that should do the yielding
+ */
+void esp_crosscore_int_send_yield(int coreId);
+
+#endif

+ 2 - 0
components/esp32/include/esp_err.h

@@ -31,6 +31,8 @@ typedef int32_t esp_err_t;
 #define ESP_ERR_NO_MEM          0x101
 #define ESP_ERR_INVALID_ARG     0x102
 #define ESP_ERR_INVALID_STATE   0x103
+#define ESP_ERR_INVALID_SIZE    0x104
+#define ESP_ERR_NOT_FOUND       0x105
 
 /**
  * Macro which can be used to check the error code,

+ 106 - 0
components/esp32/include/esp_flash_data_types.h

@@ -0,0 +1,106 @@
+// 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 __ESP_BIN_TYPES_H__
+#define __ESP_BIN_TYPES_H__
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define ESP_PARTITION_TABLE_ADDR 0x4000
+#define ESP_PARTITION_MAGIC 0x50AA
+
+/* SPI flash mode, used in esp_image_header_t */
+typedef enum {
+    ESP_IMAGE_SPI_MODE_QIO,
+    ESP_IMAGE_SPI_MODE_QOUT,
+    ESP_IMAGE_SPI_MODE_DIO,
+    ESP_IMAGE_SPI_MODE_DOUT,
+    ESP_IMAGE_SPI_MODE_FAST_READ,
+    ESP_IMAGE_SPI_MODE_SLOW_READ
+} esp_image_spi_mode_t;
+
+/* SPI flash clock frequency */
+enum {
+    ESP_IMAGE_SPI_SPEED_40M,
+    ESP_IMAGE_SPI_SPEED_26M,
+    ESP_IMAGE_SPI_SPEED_20M,
+    ESP_IMAGE_SPI_SPEED_80M = 0xF
+} esp_image_spi_freq_t;
+
+/* Supported SPI flash sizes */
+typedef enum {
+    ESP_IMAGE_FLASH_SIZE_1MB = 0,
+    ESP_IMAGE_FLASH_SIZE_2MB,
+    ESP_IMAGE_FLASH_SIZE_4MB,
+    ESP_IMAGE_FLASH_SIZE_8MB,
+    ESP_IMAGE_FLASH_SIZE_16MB,
+    ESP_IMAGE_FLASH_SIZE_MAX
+} esp_image_flash_size_t;
+
+/* Main header of binary image */
+typedef struct {
+    uint8_t magic;
+    uint8_t blocks;
+    uint8_t spi_mode;      /* flash read mode (esp_image_spi_mode_t as uint8_t) */
+    uint8_t spi_speed: 4;  /* flash frequency (esp_image_spi_freq_t as uint8_t) */
+    uint8_t spi_size: 4;   /* flash chip size (esp_image_flash_size_t as uint8_t) */
+    uint32_t entry_addr;
+    uint8_t encrypt_flag;    /* encrypt flag */
+    uint8_t secure_boot_flag; /* secure boot flag */
+    uint8_t extra_header[14]; /* ESP32 additional header, unused by second bootloader */
+}  esp_image_header_t;
+
+/* Header of binary image segment */
+typedef struct {
+    uint32_t load_addr;
+    uint32_t data_len;
+} esp_image_section_header_t;
+
+
+/* OTA selection structure (two copies in the OTA data partition.)
+   Size of 32 bytes is friendly to flash encryption */
+typedef struct {
+    uint32_t ota_seq;
+    uint8_t  seq_label[24];
+    uint32_t crc; /* CRC32 of ota_seq field only */
+} esp_ota_select_entry_t;
+
+
+typedef struct {
+    uint32_t offset;
+    uint32_t size;
+} esp_partition_pos_t;
+
+/* Structure which describes the layout of partition table entry.
+ * See docs/partition_tables.rst for more information about individual fields.
+ */
+typedef struct {
+	uint16_t magic;
+	uint8_t  type;
+    uint8_t  subtype;
+    esp_partition_pos_t pos;
+	uint8_t  label[16];
+    uint8_t  reserved[4];
+} esp_partition_info_t;
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //__ESP_BIN_TYPES_H__

+ 1 - 1
components/freertos/gdbstub.h → components/esp32/include/esp_gdbstub.h

@@ -17,6 +17,6 @@
 #include <xtensa/config/core.h>
 #include "freertos/xtensa_api.h"
 
-void gdbstubPanicHandler(XtExcFrame *frame);
+void esp_gdbstub_panic_handler(XtExcFrame *frame);
 
 #endif

+ 60 - 0
components/esp32/include/esp_int_wdt.h

@@ -0,0 +1,60 @@
+// 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 __ESP_INT_WDT_H
+#define __ESP_INT_WDT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @addtogroup Watchdog_APIs
+  * @{
+  */
+
+/*
+This routine enables a watchdog to catch instances of processes disabling
+interrupts for too long, or code within interrupt handlers taking too long. 
+It does this by setting up a watchdog which gets fed from the FreeRTOS
+task switch interrupt. When this watchdog times out, initially it will call
+a high-level interrupt routine that will panic FreeRTOS in order to allow
+for forensic examination of the state of the CPU. When this interrupt 
+handler is not called and the watchdog times out a second time, it will 
+reset the SoC.
+
+This uses the TIMERG1 WDT.
+*/
+
+
+/**
+  * @brief  Initialize the interrupt watchdog. This is called in the init code if
+  *         the interrupt watchdog is enabled in menuconfig.
+  *
+  * @param  null
+  *
+  * @return null
+  */
+void esp_int_wdt_init();
+
+
+/**
+  * @}
+  */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 21 - 0
components/esp32/include/esp_panic.h

@@ -0,0 +1,21 @@
+#ifndef PANIC_H
+#define PANIC_H
+
+
+#define PANIC_RSN_NONE 0
+#define PANIC_RSN_DEBUGEXCEPTION 1
+#define PANIC_RSN_DOUBLEEXCEPTION 2
+#define PANIC_RSN_KERNELEXCEPTION 3
+#define PANIC_RSN_COPROCEXCEPTION 4
+#define PANIC_RSN_INTWDT_CPU0 5
+#define PANIC_RSN_INTWDT_CPU1 6
+#define PANIC_RSN_MAX 6
+
+
+#ifndef __ASSEMBLER__
+
+void esp_set_breakpoint_if_jtag(void *fn);
+
+#endif
+
+#endif

+ 83 - 0
components/esp32/include/esp_task_wdt.h

@@ -0,0 +1,83 @@
+// 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 __ESP_TASK_WDT_H
+#define __ESP_TASK_WDT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/** \defgroup Watchdog_APIs Watchdog APIs
+  * @brief Watchdog APIs
+  */
+
+/** @addtogroup Watchdog_APIs
+  * @{
+  */
+
+/*
+This routine enables a more general-purpose task watchdog: tasks can individually
+feed the watchdog and the watchdog will bark if one or more tasks haven't fed the
+watchdog within the specified time. Optionally, the idle tasks can also configured
+to feed the watchdog in a similar fashion, to detect CPU starvation.
+
+This uses the TIMERG0 WDT.
+*/
+
+
+/**
+  * @brief  Initialize the task watchdog. This is called in the init code, if the
+  *         task watchdog is enabled in menuconfig.
+  *
+  * @param  null
+  *
+  * @return null
+  */
+void esp_task_wdt_init();
+
+/**
+  * @brief  Feed the watchdog. After the first feeding session, the watchdog will expect the calling
+  *         task to keep feeding the watchdog until task_wdt_delete() is called.
+  *
+  * @param  null
+  *
+  * @return null
+  */
+
+void esp_task_wdt_feed();
+
+
+/**
+  * @brief  Delete the watchdog for the current task.
+  *
+  * @param  null
+  *
+  * @return null
+  */
+void esp_task_wdt_delete();
+
+/**
+  * @}
+  */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+#endif

+ 20 - 10
components/esp32/include/esp_wifi.h

@@ -191,14 +191,14 @@ esp_err_t esp_wifi_disconnect(void);
 esp_err_t esp_wifi_clear_fast_connect(void);
 
 /**
-  * @brief     Kick the all station or associated id equals to aid
+  * @brief     deauthenticate all stations or associated id equals to aid
   *
-  * @param     uint16_t aid : when aid is 0, kick all stations, otherwise kick station whose associated id is aid
+  * @param     uint16_t aid : when aid is 0, deauthenticate all stations, otherwise deauthenticate station whose associated id is aid
   *
   * @return    ESP_OK : succeed
   * @return    others : fail
   */
-esp_err_t esp_wifi_kick_station(uint16_t aid);
+esp_err_t esp_wifi_deauth_sta(uint16_t aid);
 
 /**
   * @brief     Scan all available APs.
@@ -235,19 +235,30 @@ esp_err_t esp_wifi_scan_stop(void);
   * @return    ESP_OK : succeed
   * @return    others : fail
   */
-esp_err_t esp_wifi_get_ap_num(uint16_t *number);
+esp_err_t esp_wifi_scan_get_ap_num(uint16_t *number);
 
 /**
   * @brief     Get AP list found in last scan
   *
-  * @param     uint16_t *number : as input param, it stores max AP number ap_list can hold, as output param, it store
+  * @param     uint16_t *number : as input param, it stores max AP number ap_records can hold, as output param, it store
                                   the actual AP number this API returns
-  * @param     wifi_ap_list_t *ap_list : a list to hold the found APs
+  * @param     wifi_ap_record_t *ap_records: wifi_ap_record_t array to hold the found APs
   *
   * @return    ESP_OK : succeed
   * @return    others : fail
   */
-esp_err_t esp_wifi_get_ap_list(uint16_t *number, wifi_ap_list_t *ap_list);
+esp_err_t esp_wifi_scan_get_ap_records(uint16_t *number, wifi_ap_record_t *ap_records);
+
+
+/**
+  * @brief     Get information of AP associated with ESP32 station
+  *
+  * @param     wifi_ap_record_t *ap_info: the wifi_ap_record_t to hold station assocated AP
+  *
+  * @return    ESP_OK : succeed
+  * @return    others : fail
+  */
+esp_err_t esp_wifi_sta_get_ap_info(wifi_ap_record_t *ap_info);
 
 /**
   * @brief     Set current power save type
@@ -471,14 +482,13 @@ esp_err_t esp_wifi_get_config(wifi_interface_t ifx, wifi_config_t *conf);
   *
   * @attention SSC only API
   *
-  * @param     struct station_info **station :  station list
+  * @param     wifi_sta_list_t *sta:  station list
   *
   * @return    ESP_OK : succeed
   * @return    others : fail
   */
-esp_err_t esp_wifi_get_station_list(struct station_info **station);
+esp_err_t esp_wifi_ap_get_sta_list(wifi_sta_list_t *sta);
 
-esp_err_t esp_wifi_free_station_list(void);
 
 /**
   * @brief     Set the WiFi API configuration storage type

+ 80 - 0
components/esp32/include/esp_wifi_internal.h

@@ -0,0 +1,80 @@
+// 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.
+
+/*
+ * All the APIs declared here are internal only APIs, it can only be used by 
+ * espressif internal modules, such as SSC, LWIP, TCPIP adapter etc, espressif 
+ * customers are not recommended to use them.
+ *
+ * If someone really want to use specified APIs declared in here, please contact
+ * espressif AE/developer to make sure you know the limitations or risk of 
+ * the API, otherwise you may get unexpected behavior!!!
+ *
+ */
+
+
+#ifndef __ESP_WIFI_INTERNAL_H__
+#define __ESP_WIFI_INTERNAL_H__
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "freertos/FreeRTOS.h"
+#include "freertos/queue.h"
+#include "rom/queue.h"
+#include "esp_err.h"
+#include "esp_wifi_types.h"
+#include "esp_event.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+  * @brief  get whether the wifi driver is allowed to transmit data or not
+  *
+  * @param  none
+  *
+  * @return    true  : upper layer should stop to transmit data to wifi driver
+  * @return    false : upper layer can transmit data to wifi driver
+  */
+bool esp_wifi_internal_tx_is_stop(void);
+
+/**
+  * @brief  free the rx buffer which allocated by wifi driver
+  *
+  * @param  void* buffer: rx buffer pointer
+  *
+  * @return    nonoe
+  */
+void esp_wifi_internal_free_rx_buffer(void* buffer);
+
+/**
+  * @brief  transmit the buffer via wifi driver
+  *
+  * @attention1 TODO should modify the return type from bool to int
+  * 
+  * @param  wifi_interface_t wifi_if : wifi interface id
+  * @param  void *buffer : the buffer to be tansmit
+  * @param  u16_t len : the length of buffer
+  *
+  * @return True : success transmit the buffer to wifi driver
+  *         False : failed to transmit the buffer to wifi driver
+  */
+bool esp_wifi_internal_tx(wifi_interface_t wifi_if, void *buffer, u16_t len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ESP_WIFI_H__ */

+ 10 - 5
components/esp32/include/esp_wifi_types.h

@@ -109,7 +109,7 @@ typedef struct {
     wifi_second_chan_t second;            /**< second channel of AP */
     int8_t  rssi;                         /**< signal strength of AP */
     wifi_auth_mode_t authmode;            /**< authmode of AP */
-} wifi_ap_list_t;
+} wifi_ap_record_t;
 
 typedef enum {
     WIFI_PS_NONE,    /**< No power save */
@@ -150,10 +150,15 @@ typedef union {
     wifi_sta_config_t sta; /**< configuration of STA */
 } wifi_config_t;
 
-struct station_info {
-    STAILQ_ENTRY(station_info) next;
-    uint8_t bssid[6];
-};
+typedef struct {
+    uint8_t mac[6];  /**< mac address of sta that associated with ESP32 soft-AP */
+}wifi_sta_info_t;
+
+#define ESP_WIFI_MAX_CONN_NUM  (10)       /**< max number of stations which can connect to ESP32 soft-AP */
+typedef struct {
+    wifi_sta_info_t sta[ESP_WIFI_MAX_CONN_NUM]; /**< station list */
+    int       num; /**< number of station that associated with ESP32 soft-AP */
+}wifi_sta_list_t;
 
 typedef enum {
     WIFI_STORAGE_FLASH,  /**< all configuration will strore in both memory and flash */

+ 9 - 3
components/esp32/include/rom/spi_flash.h

@@ -218,7 +218,7 @@ void SelectSpiFunction(uint32_t ishspi);
 void spi_flash_attach(uint32_t ishspi, bool legacy);
 
 /**
-  * @brief SPI Read Flash status register. We use CMD 0x05.
+  * @brief SPI Read Flash status register. We use CMD 0x05 (RDSR).
   *    Please do not call this function in SDK.
   *
   * @param  SpiFlashChip *spi : The information for Flash, which is exported from ld file.
@@ -232,7 +232,7 @@ void spi_flash_attach(uint32_t ishspi, bool legacy);
 SpiFlashOpResult SPI_read_status(SpiFlashChip *spi, uint32_t *status);
 
 /**
-  * @brief SPI Read Flash status register high 16 bit. We use CMD 0x35.
+  * @brief SPI Read Flash status register bits 8-15. We use CMD 0x35 (RDSR2).
   *        Please do not call this function in SDK.
   *
   * @param  SpiFlashChip *spi : The information for Flash, which is exported from ld file.
@@ -243,7 +243,7 @@ SpiFlashOpResult SPI_read_status(SpiFlashChip *spi, uint32_t *status);
   *         SPI_FLASH_RESULT_ERR : read error.
   *         SPI_FLASH_RESULT_TIMEOUT : read timeout.
   */
-SpiFlashOpResult SPI_read_status_high(SpiFlashChip *spi, uint32_t *status);
+SpiFlashOpResult SPI_read_status_high(uint32_t *status);
 
 /**
   * @brief Write status to Falsh status register.
@@ -503,6 +503,12 @@ void SPI_Write_Encrypt_Disable(void);
   */
 SpiFlashOpResult SPI_Encrypt_Write(uint32_t flash_addr, uint32_t *data, uint32_t len);
 
+
+/** @brief Global SpiFlashChip structure used by ROM functions
+ *
+ */
+extern SpiFlashChip g_rom_flashchip;
+
 /**
   * @}
   */

+ 3 - 0
components/esp32/include/soc/cpu.h

@@ -15,6 +15,9 @@
 #ifndef _SOC_CPU_H
 #define _SOC_CPU_H
 
+#include <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
 #include "xtensa/corebits.h"
 
 /* C macros for xtensa special register read/write/exchange */

+ 5 - 0
components/esp32/include/soc/dport_reg.h

@@ -3830,6 +3830,11 @@
 #define DPORT_DATE_S  0
 #define DPORT_DPORT_DATE_VERSION 0x1605190
 
+/* Flash MMU table for PRO CPU */
+#define DPORT_PRO_FLASH_MMU_TABLE ((volatile uint32_t*) 0x3FF10000)
+
+/* Flash MMU table for APP CPU */
+#define DPORT_APP_FLASH_MMU_TABLE ((volatile uint32_t*) 0x3FF12000)
 
 
 

+ 3 - 0
components/esp32/include/soc/rtc_cntl_reg.h

@@ -14,6 +14,9 @@
 #ifndef _SOC_RTC_CNTL_REG_H_
 #define _SOC_RTC_CNTL_REG_H_
 
+/* The value that needs to be written to RTC_CNTL_WDT_WKEY to write-enable the wdt registers */
+#define RTC_CNTL_WDT_WKEY_VALUE 0x50D83AA1
+
 
 #include "soc.h"
 #define RTC_CNTL_OPTIONS0_REG          (DR_REG_RTCCNTL_BASE + 0x0)

+ 4 - 4
components/esp32/include/soc/soc.h

@@ -210,10 +210,10 @@
 #define ETS_TG1_LACT_LEVEL_INTR_SOURCE          21/**< interrupt of TIMER_GROUP1, LACT, level*/
 #define ETS_GPIO_INTR_SOURCE                    22/**< interrupt of GPIO, level*/
 #define ETS_GPIO_NMI_SOURCE                     23/**< interrupt of GPIO, NMI*/
-#define ETS_FROM_CPU_INTR0_SOURCE               24/**< interrupt0 generated from a CPU, level*/
-#define ETS_FROM_CPU_INTR1_SOURCE               25/**< interrupt1 generated from a CPU, level*/
-#define ETS_FROM_CPU_INTR2_SOURCE               26/**< interrupt2 generated from a CPU, level*/
-#define ETS_FROM_CPU_INTR3_SOURCE               27/**< interrupt3 generated from a CPU, level*/
+#define ETS_FROM_CPU_INTR0_SOURCE               24/**< interrupt0 generated from a CPU, level*/ /* Used for FreeRTOS */
+#define ETS_FROM_CPU_INTR1_SOURCE               25/**< interrupt1 generated from a CPU, level*/ /* Used for FreeRTOS */
+#define ETS_FROM_CPU_INTR2_SOURCE               26/**< interrupt2 generated from a CPU, level*/ /* Used for VHCI */
+#define ETS_FROM_CPU_INTR3_SOURCE               27/**< interrupt3 generated from a CPU, level*/ /* Reserved */
 #define ETS_SPI0_INTR_SOURCE                    28/**< interrupt of SPI0, level, SPI0 is for Cache Access, do not use this*/
 #define ETS_SPI1_INTR_SOURCE                    29/**< interrupt of SPI1, level, SPI1 is for flash read/write, do not use this*/
 #define ETS_SPI2_INTR_SOURCE                    30/**< interrupt of SPI2, level*/

+ 10 - 0
components/esp32/include/soc/timer_group_reg.h

@@ -15,6 +15,16 @@
 #define __TIMG_REG_H__
 #include "soc.h"
 
+/* The value that needs to be written to TIMG_WDT_WKEY to write-enable the wdt registers */
+#define TIMG_WDT_WKEY_VALUE 0x50D83AA1
+
+/* Possible values for TIMG_WDT_STGx */
+#define TIMG_WDT_STG_SEL_OFF 0
+#define TIMG_WDT_STG_SEL_INT 1
+#define TIMG_WDT_STG_SEL_RESET_CPU 2
+#define TIMG_WDT_STG_SEL_RESET_SYSTEM 3
+
+
 #define REG_TIMG_BASE(i)       (DR_REG_TIMERGROUP0_BASE + i*0x1000)
 #define TIMG_T0CONFIG_REG(i)          (REG_TIMG_BASE(i) + 0x0000)
 /* TIMG_T0_EN : R/W ;bitpos:[31] ;default: 1'h0 ; */

+ 96 - 0
components/esp32/int_wdt.c

@@ -0,0 +1,96 @@
+// 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 "sdkconfig.h"
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include <esp_types.h>
+#include "esp_err.h"
+#include "esp_intr.h"
+#include "esp_attr.h"
+#include "soc/timer_group_struct.h"
+#include "soc/timer_group_reg.h"
+
+#include "esp_int_wdt.h"
+
+#if CONFIG_INT_WDT
+
+
+#define WDT_INT_NUM 24
+
+
+void esp_int_wdt_init() {
+    TIMERG1.wdt_wprotect=TIMG_WDT_WKEY_VALUE;
+    TIMERG1.wdt_config0.sys_reset_length=7;                 //3.2uS
+    TIMERG1.wdt_config0.cpu_reset_length=7;                 //3.2uS
+    TIMERG1.wdt_config0.level_int_en=1;
+    TIMERG1.wdt_config0.stg0=TIMG_WDT_STG_SEL_INT;          //1st stage timeout: interrupt
+    TIMERG1.wdt_config0.stg1=TIMG_WDT_STG_SEL_RESET_SYSTEM; //2nd stage timeout: reset system
+    TIMERG1.wdt_config1.clk_prescale=80*500;                //Prescaler: wdt counts in ticks of 0.5mS
+    //The timer configs initially are set to 5 seconds, to make sure the CPU can start up. The tick hook sets
+    //it to their actual value.
+    TIMERG1.wdt_config2=10000;
+    TIMERG1.wdt_config3=10000;
+    TIMERG1.wdt_config0.en=1;
+    TIMERG1.wdt_feed=1;
+    TIMERG1.wdt_wprotect=0;
+    TIMERG1.int_clr_timers.wdt=1;
+    TIMERG1.int_ena.wdt=1;
+    ESP_INTR_DISABLE(WDT_INT_NUM);
+    intr_matrix_set(xPortGetCoreID(), ETS_TG1_WDT_LEVEL_INTR_SOURCE, WDT_INT_NUM);
+    //We do not register a handler for the interrupt because it is interrupt level 4 which
+    //is not servicable from C. Instead, xtensa_vectors.S has a call to the panic handler for
+    //this interrupt.
+    ESP_INTR_ENABLE(WDT_INT_NUM);
+}
+
+
+//Take care: the tick hook can also be called before esp_int_wdt_init() is called.
+#if CONFIG_INT_WDT_CHECK_CPU1
+//Not static; the ISR assembly checks this.
+bool int_wdt_app_cpu_ticked=false;
+
+void IRAM_ATTR vApplicationTickHook(void) {
+    if (xPortGetCoreID()!=0) {
+        int_wdt_app_cpu_ticked=true;
+    } else {
+        //Only feed wdt if app cpu also ticked.
+        if (int_wdt_app_cpu_ticked) {
+            TIMERG1.wdt_wprotect=TIMG_WDT_WKEY_VALUE;
+            TIMERG1.wdt_config2=CONFIG_INT_WDT_TIMEOUT_MS*2;        //Set timeout before interrupt
+            TIMERG1.wdt_config3=CONFIG_INT_WDT_TIMEOUT_MS*4;        //Set timeout before reset
+            TIMERG1.wdt_feed=1;
+            TIMERG1.wdt_wprotect=0;
+            int_wdt_app_cpu_ticked=false;
+        }
+    }
+}
+#else
+void IRAM_ATTR vApplicationTickHook(void) {
+    if (xPortGetCoreID()!=0) return;
+    TIMERG1.wdt_wprotect=TIMG_WDT_WKEY_VALUE;
+    TIMERG1.wdt_config2=CONFIG_INT_WDT_TIMEOUT_MS*2;        //Set timeout before interrupt
+    TIMERG1.wdt_config3=CONFIG_INT_WDT_TIMEOUT_MS*4;        //Set timeout before reset
+    TIMERG1.wdt_feed=1;
+    TIMERG1.wdt_wprotect=0;
+}
+#endif
+
+#endif

+ 2 - 0
components/esp32/ld/esp32.common.ld

@@ -47,6 +47,7 @@ SECTIONS
     _iram_text_start = ABSOLUTE(.);
     *(.iram1 .iram1.*)
     *libfreertos.a:(.literal .text .literal.* .text.*)
+    *libesp32.a:panic.o(.literal .text .literal.* .text.*)
     *libphy.a:(.literal .text .literal.* .text.*)
     *librtc.a:(.literal .text .literal.* .text.*)
     *libpp.a:(.literal .text .literal.* .text.*)
@@ -92,6 +93,7 @@ SECTIONS
     KEEP(*(.gnu.linkonce.s2.*))
     KEEP(*(.jcr))
     *(.dram1 .dram1.*)
+    *libesp32.a:panic.o(.rodata .rodata.*)
     _data_end = ABSOLUTE(.);
     . = ALIGN(4);
     _heap_start = ABSOLUTE(.);

+ 4 - 2
components/esp32/ld/esp32.rom.ld

@@ -286,6 +286,7 @@ PROVIDE ( _global_impure_ptr = 0x3ffae0b0 );
 PROVIDE ( gmtime = 0x40059848 );
 PROVIDE ( gmtime_r = 0x40059868 );
 PROVIDE ( g_phyFuns_instance = 0x3ffae0c4 );
+PROVIDE ( g_rom_flashchip = 0x3ffae270 );
 PROVIDE ( gpio_init = 0x40009c20 );
 PROVIDE ( gpio_input_get = 0x40009b88 );
 PROVIDE ( gpio_input_get_high = 0x40009b9c );
@@ -1584,6 +1585,8 @@ PROVIDE ( SPIEraseBlock = 0x40062c4c );
 PROVIDE ( SPIEraseChip = 0x40062c14 );
 PROVIDE ( SPIEraseSector = 0x40062ccc );
 PROVIDE ( spi_flash_attach = 0x40062a6c );
+/* NB: SPIUnlock @ 0x400628b0 has been replaced with an updated
+    version in the "spi_flash" component */
 PROVIDE ( SPILock = 0x400628f0 );
 PROVIDE ( SPIMasterReadModeCnfig = 0x40062b64 );
 PROVIDE ( spi_modes = 0x3ff99270 );
@@ -1595,9 +1598,8 @@ PROVIDE ( SPIReadModeCnfig = 0x40062944 );
 PROVIDE ( SPI_read_status = 0x4006226c );
 /* This is static function, but can be used, not generated by script*/
 PROVIDE ( SPI_read_status_high = 0x40062448 );
-PROVIDE ( SPIUnlock = 0x400628b0 );
 PROVIDE ( SPI_user_command_read = 0x400621b0 );
-PROVIDE ( spi_w25q16 = 0x3ffae270 );
+PROVIDE ( SPI_flashchip_data = 0x3ffae270 );
 PROVIDE ( SPIWrite = 0x40062d50 );
 /* This is static function, but can be used, not generated by script*/
 PROVIDE ( SPI_write_enable = 0x40062320 );

+ 1 - 1
components/esp32/lib

@@ -1 +1 @@
-Subproject commit 0ee9babfd9a9c95ff0395d442153df894df550f2
+Subproject commit 01d2e6e22e439edcdc289991b667d13a0908128d

+ 83 - 17
components/freertos/panic.c → components/esp32/panic.c

@@ -25,8 +25,12 @@
 #include "soc/io_mux_reg.h"
 #include "soc/dport_reg.h"
 #include "soc/rtc_cntl_reg.h"
+#include "soc/timer_group_struct.h"
+#include "soc/timer_group_reg.h"
 
-#include "gdbstub.h"
+#include "esp_gdbstub.h"
+#include "esp_panic.h"
+#include "esp_attr.h"
 
 /*
 Panic handlers; these get called when an unhandled exception occurs or the assembly-level
@@ -34,7 +38,11 @@ task switching / interrupt code runs into an unrecoverable error. The default ta
 overflow handler also is in here.
 */
 
-#if !CONFIG_FREERTOS_PANIC_SILENT_REBOOT
+/*
+Note: The linker script will put everything in this file in IRAM/DRAM, so it also works with flash cache disabled.
+*/
+
+#if !CONFIG_ESP32_PANIC_SILENT_REBOOT
 //printf may be broken, so we fix our own printing fns...
 inline static void panicPutchar(char c) {
 	while (((READ_PERI_REG(UART_STATUS_REG(0))>>UART_TXFIFO_CNT_S)&UART_TXFIFO_CNT)>=126) ;
@@ -76,7 +84,6 @@ inline static void panicPutHex(int a) { }
 inline static void panicPutDec(int a) { }
 #endif
 
-int xPortGetCoreID();
 
 void  __attribute__((weak)) vApplicationStackOverflowHook( TaskHandle_t xTask, signed char *pcTaskName ) {
 	panicPutStr("***ERROR*** A stack overflow in task ");
@@ -105,22 +112,22 @@ void commonErrorHandler(XtExcFrame *frame);
 static void haltOtherCore() {
 	if (xPortGetCoreID()==0) {
 		//Kill app cpu
-		CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_STALL_APPCPU_C1<<RTC_CNTL_SW_STALL_APPCPU_C1_S);
-		SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, 0x21<<RTC_CNTL_SW_STALL_APPCPU_C1_S);
-		CLEAR_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, RTC_CNTL_SW_STALL_APPCPU_C0<<RTC_CNTL_SW_STALL_APPCPU_C0_S);
-		SET_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, 2<<RTC_CNTL_SW_STALL_APPCPU_C0_S);
+		CLEAR_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, RTC_CNTL_SW_STALL_APPCPU_C1_M);
+		SET_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, 0x21<<RTC_CNTL_SW_STALL_APPCPU_C1_S);
+		CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_STALL_APPCPU_C0_M);
+		SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, 2<<RTC_CNTL_SW_STALL_APPCPU_C0_S);
 	} else {
 		//Kill pro cpu
-		CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_STALL_PROCPU_C1<<RTC_CNTL_SW_STALL_PROCPU_C1_S);
-		SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, 0x21<<RTC_CNTL_SW_STALL_PROCPU_C1_S);
-		CLEAR_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, RTC_CNTL_SW_STALL_PROCPU_C0<<RTC_CNTL_SW_STALL_PROCPU_C0_S);
-		SET_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, 2<<RTC_CNTL_SW_STALL_PROCPU_C0_S);
+		CLEAR_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, RTC_CNTL_SW_STALL_PROCPU_C1_M);
+		SET_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, 0x21<<RTC_CNTL_SW_STALL_PROCPU_C1_S);
+		CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_STALL_PROCPU_C0_M);
+		SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, 2<<RTC_CNTL_SW_STALL_PROCPU_C0_S);
 	}
 }
 
 //Returns true when a debugger is attached using JTAG.
 static int inOCDMode() {
-#if CONFIG_FREERTOS_DEBUG_OCDAWARE
+#if CONFIG_ESP32_DEBUG_OCDAWARE
 	int dcr;
 	int reg=0x10200C; //DSRSET register
 	asm("rer %0,%1":"=r"(dcr):"r"(reg));
@@ -131,10 +138,26 @@ static int inOCDMode() {
 }
 
 void panicHandler(XtExcFrame *frame) {
+	int *regs=(int*)frame;
+	//Please keep in sync with PANIC_RSN_* defines
+	const char *reasons[]={
+			"Unknown reason",
+			"Unhandled debug exception",
+			"Double exception",
+			"Unhandled kernel exception",
+			"Coprocessor exception",
+			"Interrupt wdt timeout on CPU0",
+			"Interrupt wdt timeout on CPU1",
+		};
+	const char *reason=reasons[0];
+	//The panic reason is stored in the EXCCAUSE register.
+	if (regs[20]<=PANIC_RSN_MAX) reason=reasons[regs[20]];
 	haltOtherCore();
 	panicPutStr("Guru Meditation Error: Core ");
 	panicPutDec(xPortGetCoreID());
-	panicPutStr(" panic'ed.\r\n");
+	panicPutStr(" panic'ed (");
+	panicPutStr(reason);
+	panicPutStr(")\r\n");
 
 	if (inOCDMode()) {
 		asm("break.n 1");
@@ -176,6 +199,44 @@ void xt_unhandled_exception(XtExcFrame *frame) {
 }
 
 
+/*
+If watchdogs are enabled, the panic handler runs the risk of getting aborted pre-emptively because
+an overzealous watchdog decides to reset it. On the other hand, if we disable all watchdogs, we run
+the risk of somehow halting in the panic handler and not resetting. That is why this routine kills 
+all watchdogs except the timer group 0 watchdog, and it reconfigures that to reset the chip after
+one second.
+*/
+static void reconfigureAllWdts() {
+	TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE;
+	TIMERG0.wdt_feed=1;
+	TIMERG0.wdt_config0.sys_reset_length=7;				//3.2uS
+	TIMERG0.wdt_config0.cpu_reset_length=7;				//3.2uS
+	TIMERG0.wdt_config0.stg0=TIMG_WDT_STG_SEL_RESET_SYSTEM;	//1st stage timeout: reset system
+	TIMERG0.wdt_config1.clk_prescale=80*500;			//Prescaler: wdt counts in ticks of 0.5mS
+	TIMERG0.wdt_config2=2000;							//1 second before reset
+	TIMERG0.wdt_config0.en=1;
+	TIMERG0.wdt_wprotect=0;
+	//Disable wdt 1
+	TIMERG1.wdt_wprotect=TIMG_WDT_WKEY_VALUE;
+	TIMERG1.wdt_config0.en=0;
+	TIMERG1.wdt_wprotect=0;
+}
+
+#if CONFIG_ESP32_PANIC_GDBSTUB || CONFIG_ESP32_PANIC_PRINT_HALT
+/*
+This disables all the watchdogs for when we call the gdbstub.
+*/
+static void disableAllWdts() {
+	TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE;
+	TIMERG0.wdt_config0.en=0;
+	TIMERG0.wdt_wprotect=0;
+	TIMERG1.wdt_wprotect=TIMG_WDT_WKEY_VALUE;
+	TIMERG1.wdt_config0.en=0;
+	TIMERG0.wdt_wprotect=0;
+}
+
+#endif
+
 /*
 We arrive here after a panic or unhandled exception, when no OCD is detected. Dump the registers to the
 serial port and either jump to the gdb stub, halt the CPU or reboot.
@@ -188,6 +249,9 @@ void commonErrorHandler(XtExcFrame *frame) {
 		"A6      ","A7      ","A8      ","A9      ","A10     ","A11     ","A12     ","A13     ",
 		"A14     ","A15     ","SAR     ","EXCCAUSE","EXCVADDR","LBEG    ","LEND    ","LCOUNT  "};
 
+	//Feed the watchdogs, so they will give us time to print out debug info
+	reconfigureAllWdts();
+
 	panicPutStr("Register dump:\r\n");
 
 	for (x=0; x<24; x+=4) {
@@ -201,21 +265,23 @@ void commonErrorHandler(XtExcFrame *frame) {
 		}
 		panicPutStr("\r\n");
 	}
-#if CONFIG_FREERTOS_PANIC_GDBSTUB
+#if CONFIG_ESP32_PANIC_GDBSTUB
+	disableAllWdts();
 	panicPutStr("Entering gdb stub now.\r\n");
-	gdbstubPanicHandler(frame);
-#elif CONFIG_FREERTOS_PANIC_PRINT_REBOOT || CONFIG_FREERTOS_PANIC_SILENT_REBOOT
+	esp_gdbstub_panic_handler(frame);
+#elif CONFIG_ESP32_PANIC_PRINT_REBOOT || CONFIG_ESP32_PANIC_SILENT_REBOOT
 	panicPutStr("Rebooting...\r\n");
 	for (x=0; x<100; x++) ets_delay_us(1000);
 	software_reset();
 #else
+	disableAllWdts();
 	panicPutStr("CPU halted.\r\n");
 	while(1);
 #endif
 }
 
 
-void setBreakpointIfJtag(void *fn) {
+void esp_set_breakpoint_if_jtag(void *fn) {
 	if (!inOCDMode()) return;
 	setFirstBreakpoint((uint32_t)fn);
 }

+ 173 - 0
components/esp32/task_wdt.c

@@ -0,0 +1,173 @@
+// 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 <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include "sdkconfig.h"
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include <esp_types.h>
+#include "esp_err.h"
+#include "esp_intr.h"
+#include "esp_attr.h"
+#include "soc/timer_group_struct.h"
+#include "soc/timer_group_reg.h"
+#include "esp_log.h"
+
+#include "esp_task_wdt.h"
+
+#if CONFIG_TASK_WDT
+
+static const char* TAG = "task_wdt";
+
+typedef struct wdt_task_t wdt_task_t;
+struct wdt_task_t {
+    TaskHandle_t task_handle;
+    bool fed_watchdog;
+    wdt_task_t *next;
+};
+
+static wdt_task_t *wdt_task_list=NULL;
+
+static void IRAM_ATTR task_wdt_isr(void *arg) {
+    wdt_task_t *wdttask;
+    const char *cpu;
+    //Feed the watchdog so we do not reset
+    TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE;
+    TIMERG0.wdt_feed=1;
+    TIMERG0.wdt_wprotect=0;
+    //Ack interrupt
+    TIMERG0.int_clr_timers.wdt=1;
+    //Watchdog got triggered because at least one task did not report in.
+    ets_printf("Task watchdog got triggered. The following tasks did not feed the watchdog in time:\n");
+    for (wdttask=wdt_task_list; wdttask!=NULL; wdttask=wdttask->next) {
+        if (!wdttask->fed_watchdog) {
+            cpu=xTaskGetAffinity(wdttask->task_handle)==0?"CPU 0":"CPU 1";
+            if (xTaskGetAffinity(wdttask->task_handle)==tskNO_AFFINITY) cpu="CPU 0/1";
+            printf(" - %s (%s)\n", pcTaskGetTaskName(wdttask->task_handle), cpu);
+        }
+    }
+    ets_printf("Tasks currently running:\n");
+    for (int x=0; x<portNUM_PROCESSORS; x++) {
+        ets_printf("CPU %d: %s\n", x, pcTaskGetTaskName(xTaskGetCurrentTaskHandleForCPU(x)));
+    }
+
+#if CONFIG_TASK_WDT_PANIC
+    ets_printf("Aborting.\n");
+    abort();
+#endif
+}
+
+
+void esp_task_wdt_feed() {
+    wdt_task_t *wdttask=wdt_task_list;
+    bool found_task=false, do_feed_wdt=true;
+    TaskHandle_t handle=xTaskGetCurrentTaskHandle();
+    //Walk the linked list of wdt tasks to find this one, as well as see if we need to feed
+    //the real watchdog timer.
+    for (wdttask=wdt_task_list; wdttask!=NULL; wdttask=wdttask->next) {
+        //See if we are at the current task.
+        if (wdttask->task_handle == handle) {
+            wdttask->fed_watchdog=true;
+            found_task=true;
+        }
+        //If even one task in the list doesn't have the do_feed_wdt var set, we do not feed the watchdog.
+        if (!wdttask->fed_watchdog) do_feed_wdt=false;
+    }
+    
+    if (!found_task) {
+        //This is the first time the task calls the task_wdt_feed function. Create a new entry for it in
+        //the linked list.
+        wdt_task_t *newtask=malloc(sizeof(wdt_task_t));
+        memset(newtask, 0, sizeof(wdt_task_t));
+        newtask->task_handle=handle;
+        newtask->fed_watchdog=true;
+        if (wdt_task_list == NULL) {
+            wdt_task_list=newtask;
+        } else {
+            for (wdttask=wdt_task_list; wdttask->next!=NULL; wdttask=wdttask->next) ;
+            wdttask->next=newtask;
+        }
+    }
+    if (do_feed_wdt) {
+        //All tasks have checked in; time to feed the hw watchdog.
+        TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE;
+        TIMERG0.wdt_feed=1;
+        TIMERG0.wdt_wprotect=0;
+        //Reset fed_watchdog status
+        for (wdttask=wdt_task_list; wdttask->next!=NULL; wdttask=wdttask->next) wdttask->fed_watchdog=false;
+    }
+}
+
+void esp_task_wdt_delete() {
+    TaskHandle_t handle=xTaskGetCurrentTaskHandle();
+    wdt_task_t *wdttask=wdt_task_list;
+    //Wdt task list can't be empty
+    if (!wdt_task_list) {
+        ESP_LOGE(TAG, "task_wdt_delete: No tasks in list?");
+        return;
+    }
+    if (handle==wdt_task_list) {
+        //Current task is first on list.
+        wdt_task_list=wdt_task_list->next;
+        free(wdttask);
+    } else {
+        //Find current task in list
+        while (wdttask->next!=NULL && wdttask->next->task_handle!=handle) wdttask=wdttask->next;
+        if (!wdttask->next) {
+            ESP_LOGE(TAG, "task_wdt_delete: Task never called task_wdt_feed!");
+            return;
+        }
+        wdt_task_t *freeme=wdttask->next;
+        wdttask->next=wdttask->next->next;
+        free(freeme);
+    }
+}
+
+void esp_task_wdt_init() {
+    TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE;
+    TIMERG0.wdt_config0.sys_reset_length=7;                 //3.2uS
+    TIMERG0.wdt_config0.cpu_reset_length=7;                 //3.2uS
+    TIMERG0.wdt_config0.level_int_en=1;
+    TIMERG0.wdt_config0.stg0=TIMG_WDT_STG_SEL_INT;          //1st stage timeout: interrupt
+    TIMERG0.wdt_config0.stg1=TIMG_WDT_STG_SEL_RESET_SYSTEM; //2nd stage timeout: reset system
+    TIMERG0.wdt_config1.clk_prescale=80*500;                //Prescaler: wdt counts in ticks of 0.5mS
+    TIMERG0.wdt_config2=CONFIG_TASK_WDT_TIMEOUT_S*2000;     //Set timeout before interrupt
+    TIMERG0.wdt_config3=CONFIG_TASK_WDT_TIMEOUT_S*4000;     //Set timeout before reset
+    TIMERG0.wdt_config0.en=1;
+    TIMERG0.wdt_feed=1;
+    TIMERG0.wdt_wprotect=0;
+    ESP_INTR_DISABLE(ETS_T0_WDT_INUM);
+    intr_matrix_set(xPortGetCoreID(), ETS_TG0_WDT_LEVEL_INTR_SOURCE, ETS_T0_WDT_INUM);
+    xt_set_interrupt_handler(ETS_T0_WDT_INUM, task_wdt_isr, NULL);
+    TIMERG0.int_clr_timers.wdt=1;
+    TIMERG0.int_ena.wdt=1;
+    ESP_INTR_ENABLE(ETS_T0_WDT_INUM);
+}
+
+#if CONFIG_TASK_WDT_CHECK_IDLE_TASK
+void vApplicationIdleHook(void) {
+#if !CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1
+    if (xPortGetCoreID()!=0) return;
+#endif
+    esp_task_wdt_feed();
+}
+#endif
+
+#endif

+ 27 - 0
components/esptool_py/Kconfig.projbuild

@@ -94,4 +94,31 @@ config ESPTOOLPY_FLASHFREQ
 	default "26m" if ESPTOOLPY_FLASHFREQ_26M
 	default "20m" if ESPTOOLPY_FLASHFREQ_20M
 
+
+choice ESPTOOLPY_FLASHSIZE
+	prompt "Flash size"
+	default ESPTOOLPY_FLASHSIZE_2MB
+	help
+		SPI flash size, in megabytes
+
+config ESPTOOLPY_FLASHSIZE_1MB
+	bool "1 MB"
+config ESPTOOLPY_FLASHSIZE_2MB
+	bool "2 MB"
+config ESPTOOLPY_FLASHSIZE_4MB
+	bool "4 MB"
+config ESPTOOLPY_FLASHSIZE_8MB
+	bool "8 MB"
+config ESPTOOLPY_FLASHSIZE_16MB
+	bool "16 MB"
+endchoice
+
+config ESPTOOLPY_FLASHSIZE
+	string
+	default "1MB" if ESPTOOLPY_FLASHSIZE_1MB
+	default "2MB" if ESPTOOLPY_FLASHSIZE_2MB
+	default "4MB" if ESPTOOLPY_FLASHSIZE_4MB
+	default "8MB" if ESPTOOLPY_FLASHSIZE_8MB
+	default "16MB" if ESPTOOLPY_FLASHSIZE_16MB
+
 endmenu

+ 5 - 2
components/esptool_py/Makefile.projbuild

@@ -4,6 +4,7 @@ ESPPORT ?= $(CONFIG_ESPTOOLPY_PORT)
 ESPBAUD ?= $(CONFIG_ESPTOOLPY_BAUD)
 ESPFLASHMODE ?= $(CONFIG_ESPTOOLPY_FLASHMODE)
 ESPFLASHFREQ ?= $(CONFIG_ESPTOOLPY_FLASHFREQ)
+ESPFLASHSIZE ?= $(CONFIG_ESPTOOLPY_FLASHSIZE)
 
 PYTHON ?= $(call dequote,$(CONFIG_PYTHON))
 
@@ -15,13 +16,15 @@ ESPTOOLPY_SRC := $(COMPONENT_PATH)/esptool/esptool.py
 ESPTOOLPY := $(PYTHON) $(ESPTOOLPY_SRC) --chip esp32
 ESPTOOLPY_SERIAL := $(ESPTOOLPY) --port $(ESPPORT) --baud $(ESPBAUD)
 
+ESPTOOL_FLASH_OPTIONS := --flash_mode $(ESPFLASHMODE) --flash_freq $(ESPFLASHFREQ) --flash_size $(ESPFLASHSIZE)
+
 # the no-stub argument is temporary until esptool.py fully supports compressed uploads
-ESPTOOLPY_WRITE_FLASH=$(ESPTOOLPY_SERIAL) write_flash $(if $(CONFIG_ESPTOOLPY_COMPRESSED),-z) --flash_mode $(ESPFLASHMODE) --flash_freq $(ESPFLASHFREQ)
+ESPTOOLPY_WRITE_FLASH=$(ESPTOOLPY_SERIAL) write_flash $(if $(CONFIG_ESPTOOLPY_COMPRESSED),-z) $(ESPTOOL_FLASH_OPTIONS)
 
 ESPTOOL_ALL_FLASH_ARGS += $(CONFIG_APP_OFFSET) $(APP_BIN)
 
 $(APP_BIN): $(APP_ELF) $(ESPTOOLPY_SRC)
-	$(Q) $(ESPTOOLPY) elf2image --flash_mode $(ESPFLASHMODE) --flash_freq $(ESPFLASHFREQ) -o $@ $<
+	$(Q) $(ESPTOOLPY) elf2image $(ESPTOOL_FLASH_OPTIONS) -o $@ $<
 
 flash: all_binaries $(ESPTOOLPY_SRC)
 	@echo "Flashing binaries to serial port $(ESPPORT) (app at offset $(CONFIG_APP_OFFSET))..."

+ 1 - 1
components/esptool_py/esptool

@@ -1 +1 @@
-Subproject commit 197ba605fe0c05e16bf4c5ec07b726adc8d86abc
+Subproject commit 5c6962e894e0a118c9a4b5760876433493449260

+ 1 - 1
components/freertos/FreeRTOS-openocd.c

@@ -18,6 +18,6 @@
 #define USED
 #endif
 
-#ifdef CONFIG_FREERTOS_DEBUG_OCDAWARE
+#ifdef CONFIG_ESP32_DEBUG_OCDAWARE
 const int USED uxTopUsedPriority = configMAX_PRIORITIES - 1;
 #endif

+ 11 - 40
components/freertos/Kconfig

@@ -93,45 +93,6 @@ config FREERTOS_THREAD_LOCAL_STORAGE_POINTERS
 
         If using the WiFi stack, this value must be at least 1.
 
-#This still needs to be implemented.
-choice FREERTOS_PANIC
-    prompt "Panic handler behaviour"
-    default FREERTOS_PANIC_PRINT_REBOOT
-    help
-        If FreeRTOS detects unexpected behaviour or an unhandled exception, the panic handler is 
-        invoked. Configure the panic handlers action here.
-
-config FREERTOS_PANIC_PRINT_HALT
-    bool "Print registers and halt"
-    help
-        Outputs the relevant registers over the serial port and halt the 
-        processor. Needs a manual reset to restart.
-
-config FREERTOS_PANIC_PRINT_REBOOT
-    bool "Print registers and reboot"
-    help
-        Outputs the relevant registers over the serial port and immediately
-        reset the processor.
-
-config FREERTOS_PANIC_SILENT_REBOOT
-    bool "Silent reboot"
-    help
-        Just resets the processor without outputting anything
-
-config FREERTOS_PANIC_GDBSTUB
-    bool "Invoke GDBStub"
-    help
-        Invoke gdbstub on the serial port, allowing for gdb to attach to it to do a postmortem
-        of the crash.
-endchoice
-
-config FREERTOS_DEBUG_OCDAWARE
-    bool "Make exception and panic handlers JTAG/OCD aware"
-    default y
-    help
-        The FreeRTOS panic and unhandled exception handers can detect a JTAG OCD debugger and
-        instead of panicking, have the debugger stop on the offending instruction.
-
 choice FREERTOS_ASSERT
     prompt "FreeRTOS assertions"
     default FREERTOS_ASSERT_FAIL_ABORT
@@ -160,7 +121,7 @@ endchoice
 
 config FREERTOS_BREAK_ON_SCHEDULER_START_JTAG
     bool "Stop program on scheduler start when JTAG/OCD is detected"
-    depends on FREERTOS_DEBUG_OCDAWARE
+    depends on ESP32_DEBUG_OCDAWARE
     default y
     help
         If JTAG/OCD is connected, stop execution when the scheduler is started and the first
@@ -172,6 +133,14 @@ menuconfig ENABLE_MEMORY_DEBUG
     help
         Enable this option to show malloc heap block and memory crash detect
 
+config FREERTOS_ISR_STACKSIZE
+    int "ISR stack size"
+    range 1536 32768
+    default 1536
+    help
+        The interrupt handlers have their own stack. The size of the stack can be defined here. 
+        Each processor has its own stack, so the total size occupied will be twice this.
+
 menuconfig FREERTOS_DEBUG_INTERNALS
     bool "Debug FreeRTOS internals"
     default n
@@ -197,6 +166,8 @@ config FREERTOS_PORTMUX_DEBUG_RECURSIVE
         If enabled, additional debug information will be printed for recursive
         portMUX usage.
 
+
+
 endif # FREERTOS_DEBUG_INTERNALS
 
 endmenu

+ 162 - 0
components/freertos/include/freertos/FreeRTOS.h

@@ -74,6 +74,7 @@
  * Include the generic headers required for the FreeRTOS port being used.
  */
 #include <stddef.h>
+#include "sys/reent.h"
 
 /*
  * If stdint.h cannot be located then:
@@ -739,6 +740,20 @@ extern "C" {
 	#define portTICK_TYPE_IS_ATOMIC 0
 #endif
 
+#ifndef configSUPPORT_STATIC_ALLOCATION
+	/* Defaults to 0 for backward compatibility. */
+	#define configSUPPORT_STATIC_ALLOCATION 0
+#endif
+
+#ifndef configSUPPORT_DYNAMIC_ALLOCATION
+	/* Defaults to 1 for backward compatibility. */
+	#define configSUPPORT_DYNAMIC_ALLOCATION 1
+#endif
+
+#if( ( configSUPPORT_STATIC_ALLOCATION == 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 0 ) )
+	#error configSUPPORT_STATIC_ALLOCATION and configSUPPORT_DYNAMIC_ALLOCATION cannot both be 0, but can both be 1.
+#endif
+
 #if( portTICK_TYPE_IS_ATOMIC == 0 )
 	/* Either variables of tick type cannot be read atomically, or
 	portTICK_TYPE_IS_ATOMIC was not set - map the critical sections used when
@@ -791,6 +806,153 @@ V8 if desired. */
 	#define configESP32_PER_TASK_DATA 1
 #endif
 
+/*
+ * In line with software engineering best practice, FreeRTOS implements a strict
+ * data hiding policy, so the real structures used by FreeRTOS to maintain the
+ * state of tasks, queues, semaphores, etc. are not accessible to the application
+ * code.  However, if the application writer wants to statically allocate such
+ * an object then the size of the object needs to be know.  Dummy structures
+ * that are guaranteed to have the same size and alignment requirements of the
+ * real objects are used for this purpose.  The dummy list and list item
+ * structures below are used for inclusion in such a dummy structure.
+ */
+struct xSTATIC_LIST_ITEM
+{
+	TickType_t xDummy1;
+	void *pvDummy2[ 4 ];
+};
+typedef struct xSTATIC_LIST_ITEM StaticListItem_t;
+
+/* See the comments above the struct xSTATIC_LIST_ITEM definition. */
+struct xSTATIC_MINI_LIST_ITEM
+{
+	TickType_t xDummy1;
+	void *pvDummy2[ 2 ];
+};
+typedef struct xSTATIC_MINI_LIST_ITEM StaticMiniListItem_t;
+
+/* See the comments above the struct xSTATIC_LIST_ITEM definition. */
+typedef struct xSTATIC_LIST
+{
+	UBaseType_t uxDummy1;
+	void *pvDummy2;
+	StaticMiniListItem_t xDummy3;
+} StaticList_t;
+
+/*
+ * In line with software engineering best practice, especially when supplying a
+ * library that is likely to change in future versions, FreeRTOS implements a
+ * strict data hiding policy.  This means the Task structure used internally by
+ * FreeRTOS is not accessible to application code.  However, if the application
+ * writer wants to statically allocate the memory required to create a task then
+ * the size of the task object needs to be know.  The StaticTask_t structure
+ * below is provided for this purpose.  Its sizes and alignment requirements are
+ * guaranteed to match those of the genuine structure, no matter which
+ * architecture is being used, and no matter how the values in FreeRTOSConfig.h
+ * are set.  Its contents are somewhat obfuscated in the hope users will
+ * recognise that it would be unwise to make direct use of the structure members.
+ */
+typedef struct xSTATIC_TCB
+{
+	void				*pxDummy1;
+	#if ( portUSING_MPU_WRAPPERS == 1 )
+		xMPU_SETTINGS	xDummy2;
+	#endif
+	StaticListItem_t	xDummy3[ 2 ];
+	UBaseType_t			uxDummy5;
+	void				*pxDummy6;
+	uint8_t				ucDummy7[ configMAX_TASK_NAME_LEN ];
+    UBaseType_t			uxDummyCoreId;
+	#if ( portSTACK_GROWTH > 0 )
+		void			*pxDummy8;
+	#endif
+	#if ( portCRITICAL_NESTING_IN_TCB == 1 )
+		UBaseType_t		uxDummy9;
+        uint32_t        OldInterruptState;
+	#endif
+	#if ( configUSE_TRACE_FACILITY == 1 )
+		UBaseType_t		uxDummy10[ 2 ];
+	#endif
+	#if ( configUSE_MUTEXES == 1 )
+		UBaseType_t		uxDummy12[ 2 ];
+	#endif
+	#if ( configUSE_APPLICATION_TASK_TAG == 1 )
+		void			*pxDummy14;
+	#endif
+	#if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 )
+		void			*pvDummy15[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];
+    #if ( configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS )
+		void			*pvDummyLocalStorageCallBack[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];
+	#endif
+	#endif
+	#if ( configGENERATE_RUN_TIME_STATS == 1 )
+		uint32_t		ulDummy16;
+	#endif
+	#if ( configUSE_NEWLIB_REENTRANT == 1 )
+		struct	_reent	xDummy17;
+	#endif
+	#if ( configUSE_TASK_NOTIFICATIONS == 1 )
+		uint32_t 		ulDummy18;
+		uint32_t 		ucDummy19;
+	#endif
+	#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
+		uint8_t			uxDummy20;
+	#endif
+
+} StaticTask_t;
+
+/*
+ * In line with software engineering best practice, especially when supplying a
+ * library that is likely to change in future versions, FreeRTOS implements a
+ * strict data hiding policy.  This means the Queue structure used internally by
+ * FreeRTOS is not accessible to application code.  However, if the application
+ * writer wants to statically allocate the memory required to create a queue
+ * then the size of the queue object needs to be know.  The StaticQueue_t
+ * structure below is provided for this purpose.  Its sizes and alignment
+ * requirements are guaranteed to match those of the genuine structure, no
+ * matter which architecture is being used, and no matter how the values in
+ * FreeRTOSConfig.h are set.  Its contents are somewhat obfuscated in the hope
+ * users will recognise that it would be unwise to make direct use of the
+ * structure members.
+ */
+typedef struct xSTATIC_QUEUE
+{
+	void *pvDummy1[ 3 ];
+
+	union
+	{
+		void *pvDummy2;
+		UBaseType_t uxDummy2;
+	} u;
+
+	StaticList_t xDummy3[ 2 ];
+	UBaseType_t uxDummy4[ 3 ];
+	BaseType_t ucDummy5[ 2 ];
+
+	#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
+		uint8_t ucDummy6;
+	#endif
+
+	#if ( configUSE_QUEUE_SETS == 1 )
+		void *pvDummy7;
+	#endif
+
+	#if ( configUSE_TRACE_FACILITY == 1 )
+		UBaseType_t uxDummy8;
+		uint8_t ucDummy9;
+	#endif
+
+    struct {
+	    volatile uint32_t mux;
+    #ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
+	    const char *lastLockedFn;
+	    int lastLockedLine;
+    #endif
+    } mux;
+
+} StaticQueue_t;
+typedef StaticQueue_t StaticSemaphore_t;
+
 #ifdef __cplusplus
 }
 #endif

+ 6 - 3
components/freertos/include/freertos/FreeRTOSConfig.h

@@ -152,9 +152,9 @@
  *----------------------------------------------------------*/
 
 #define configUSE_PREEMPTION			1
-#define configUSE_IDLE_HOOK				0
+#define configUSE_IDLE_HOOK				( CONFIG_TASK_WDT_CHECK_IDLE_TASK )
 
-#define configUSE_TICK_HOOK				0
+#define configUSE_TICK_HOOK				( CONFIG_INT_WDT )
 
 #define configTICK_RATE_HZ				( CONFIG_FREERTOS_HZ )
 
@@ -180,7 +180,7 @@
 /* The Xtensa port uses a separate interrupt stack. Adjust the stack size */
 /* to suit the needs of your specific application.                        */
 #ifndef configISR_STACK_SIZE
-#define configISR_STACK_SIZE			1024//2048
+#define configISR_STACK_SIZE			CONFIG_FREERTOS_ISR_STACKSIZE
 #endif
 
 /* Minimal heap size to make sure examples can run on memory limited
@@ -231,6 +231,7 @@
 #define INCLUDE_vTaskDelayUntil				1
 #define INCLUDE_vTaskDelay					1
 #define INCLUDE_uxTaskGetStackHighWaterMark	1
+#define INCLUDE_pcTaskGetTaskName			1
 
 #if CONFIG_ENABLE_MEMORY_DEBUG
 #define configENABLE_MEMORY_DEBUG 1
@@ -251,6 +252,8 @@
 
 #define configUSE_NEWLIB_REENTRANT		1
 
+#define configSUPPORT_DYNAMIC_ALLOCATION    1
+
 /* Test FreeRTOS timers (with timer task) and more. */
 /* Some files don't compile if this flag is disabled */
 #define configUSE_TIMERS                    1

+ 0 - 7
components/freertos/include/freertos/panic.h

@@ -1,7 +0,0 @@
-#ifndef PANIC_H
-#define PANIC_H
-
-void setBreakpointIfJtag(void *fn);
-
-
-#endif

+ 16 - 2
components/freertos/include/freertos/portable.h

@@ -179,6 +179,14 @@ BaseType_t xPortStartScheduler( void ) PRIVILEGED_FUNCTION;
  */
 void vPortEndScheduler( void ) PRIVILEGED_FUNCTION;
 
+
+/*
+ * Send an interrupt to another core in order to make the task running
+ * on it yield for a higher-priority task.
+ */
+
+void vPortYieldOtherCore( BaseType_t coreid) PRIVILEGED_FUNCTION;
+
 /*
  * The structures and methods of manipulating the MPU are contained within the
  * port layer.
@@ -192,8 +200,14 @@ void vPortEndScheduler( void ) PRIVILEGED_FUNCTION;
 #endif
 
 /* Multi-core: get current core ID */
-int xPortGetCoreID( void );
-
+static inline uint32_t xPortGetCoreID() {
+    int id;
+    asm volatile(
+        "rsr.prid %0\n"
+        " extui %0,%0,13,1"
+        :"=r"(id));
+    return id;
+}
 
 #ifdef __cplusplus
 }

+ 20 - 0
components/freertos/include/freertos/portmacro.h

@@ -225,6 +225,26 @@ static inline unsigned portENTER_CRITICAL_NESTED() { unsigned state = XTOS_SET_I
 #define portCLEAR_INTERRUPT_MASK_FROM_ISR(state)     portEXIT_CRITICAL_NESTED(state)
 
 
+/*
+ * Wrapper for the Xtensa compare-and-set instruction. This subroutine will atomically compare
+ * *mux to compare, and if it's the same, will set *mux to set. It will return the old value
+ * of *addr in *set.
+ *
+ * Warning: From the ISA docs: in some (unspecified) cases, the s32c1i instruction may return the
+ * *bitwise inverse* of the old mem if the mem wasn't written. This doesn't seem to happen on the
+ * ESP32, though. (Would show up directly if it did because the magic wouldn't match.)
+ */
+static inline void uxPortCompareSet(volatile uint32_t *addr, uint32_t compare, uint32_t *set) {
+    __asm__ __volatile__(
+        "WSR 	    %2,SCOMPARE1 \n"
+        "ISYNC      \n"
+        "S32C1I     %0, %1, 0	 \n"
+        :"=r"(*set)
+        :"r"(addr), "r"(compare), "0"(*set)
+        );
+}
+
+
 /*-----------------------------------------------------------*/
 
 /* Architecture specifics. */

+ 106 - 4
components/freertos/include/freertos/queue.h

@@ -170,7 +170,95 @@ typedef void * QueueSetMemberHandle_t;
  * \defgroup xQueueCreate xQueueCreate
  * \ingroup QueueManagement
  */
-#define xQueueCreate( uxQueueLength, uxItemSize ) xQueueGenericCreate( uxQueueLength, uxItemSize, queueQUEUE_TYPE_BASE )
+#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+	#define xQueueCreate( uxQueueLength, uxItemSize ) xQueueGenericCreate( ( uxQueueLength ), ( uxItemSize ), ( queueQUEUE_TYPE_BASE ) )
+#endif
+
+/**
+ * queue. h
+ * <pre>
+ QueueHandle_t xQueueCreateStatic(
+							  UBaseType_t uxQueueLength,
+							  UBaseType_t uxItemSize,
+							  uint8_t *pucQueueStorageBuffer,
+							  StaticQueue_t *pxQueueBuffer
+						  );
+ * </pre>
+ *
+ * Creates a new queue instance, and returns a handle by which the new queue
+ * can be referenced.
+ *
+ * Internally, within the FreeRTOS implementation, queues use two blocks of
+ * memory.  The first block is used to hold the queue's data structures.  The
+ * second block is used to hold items placed into the queue.  If a queue is
+ * created using xQueueCreate() then both blocks of memory are automatically
+ * dynamically allocated inside the xQueueCreate() function.  (see
+ * http://www.freertos.org/a00111.html).  If a queue is created using
+ * xQueueCreateStatic() then the application writer must provide the memory that
+ * will get used by the queue.  xQueueCreateStatic() therefore allows a queue to
+ * be created without using any dynamic memory allocation.
+ *
+ * http://www.FreeRTOS.org/Embedded-RTOS-Queues.html
+ *
+ * @param uxQueueLength The maximum number of items that the queue can contain.
+ *
+ * @param uxItemSize The number of bytes each item in the queue will require.
+ * Items are queued by copy, not by reference, so this is the number of bytes
+ * that will be copied for each posted item.  Each item on the queue must be
+ * the same size.
+ *
+ * @param pucQueueStorageBuffer If uxItemSize is not zero then
+ * pucQueueStorageBuffer must point to a uint8_t array that is at least large
+ * enough to hold the maximum number of items that can be in the queue at any
+ * one time - which is ( uxQueueLength * uxItemsSize ) bytes.  If uxItemSize is
+ * zero then pucQueueStorageBuffer can be NULL.
+ *
+ * @param pxQueueBuffer Must point to a variable of type StaticQueue_t, which
+ * will be used to hold the queue's data structure.
+ *
+ * @return If the queue is created then a handle to the created queue is
+ * returned.  If pxQueueBuffer is NULL then NULL is returned.
+ *
+ * Example usage:
+   <pre>
+ struct AMessage
+ {
+	char ucMessageID;
+	char ucData[ 20 ];
+ };
+
+ #define QUEUE_LENGTH 10
+ #define ITEM_SIZE sizeof( uint32_t )
+
+ // xQueueBuffer will hold the queue structure.
+ StaticQueue_t xQueueBuffer;
+
+ // ucQueueStorage will hold the items posted to the queue.  Must be at least
+ // [(queue length) * ( queue item size)] bytes long.
+ uint8_t ucQueueStorage[ QUEUE_LENGTH * ITEM_SIZE ];
+
+ void vATask( void *pvParameters )
+ {
+ QueueHandle_t xQueue1;
+
+	// Create a queue capable of containing 10 uint32_t values.
+	xQueue1 = xQueueCreate( QUEUE_LENGTH, // The number of items the queue can hold.
+							ITEM_SIZE	  // The size of each item in the queue
+							&( ucQueueStorage[ 0 ] ), // The buffer that will hold the items in the queue.
+							&xQueueBuffer ); // The buffer that will hold the queue structure.
+
+	// The queue is guaranteed to be created successfully as no dynamic memory
+	// allocation is used.  Therefore xQueue1 is now a handle to a valid queue.
+
+	// ... Rest of task code.
+ }
+ </pre>
+ * \defgroup xQueueCreateStatic xQueueCreateStatic
+ * \ingroup QueueManagement
+ */
+#if( configSUPPORT_STATIC_ALLOCATION == 1 )
+	#define xQueueCreateStatic( uxQueueLength, uxItemSize, pucQueueStorage, pxQueueBuffer ) xQueueGenericCreateStatic( ( uxQueueLength ), ( uxItemSize ), ( pucQueueStorage ), ( pxQueueBuffer ), ( queueQUEUE_TYPE_BASE ) )
+#endif /* configSUPPORT_STATIC_ALLOCATION */
 
 /**
  * queue. h
@@ -1479,7 +1567,9 @@ BaseType_t xQueueCRReceive( QueueHandle_t xQueue, void *pvBuffer, TickType_t xTi
  * these functions directly.
  */
 QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType ) PRIVILEGED_FUNCTION;
+QueueHandle_t xQueueCreateMutexStatic( const uint8_t ucQueueType, StaticQueue_t *pxStaticQueue ) PRIVILEGED_FUNCTION;
 QueueHandle_t xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount ) PRIVILEGED_FUNCTION;
+QueueHandle_t xQueueCreateCountingSemaphoreStatic( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount, StaticQueue_t *pxStaticQueue ) PRIVILEGED_FUNCTION;
 void* xQueueGetMutexHolder( QueueHandle_t xSemaphore ) PRIVILEGED_FUNCTION;
 
 /*
@@ -1538,10 +1628,22 @@ BaseType_t xQueueGiveMutexRecursive( QueueHandle_t pxMutex ) PRIVILEGED_FUNCTION
 #endif
 
 /*
- * Generic version of the queue creation function, which is in turn called by
- * any queue, semaphore or mutex creation function or macro.
+ * Generic version of the function used to creaet a queue using dynamic memory
+ * allocation.  This is called by other functions and macros that create other
+ * RTOS objects that use the queue structure as their base.
+ */
+#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+	QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, const uint8_t ucQueueType ) PRIVILEGED_FUNCTION;
+#endif
+
+/*
+ * Generic version of the function used to creaet a queue using dynamic memory
+ * allocation.  This is called by other functions and macros that create other
+ * RTOS objects that use the queue structure as their base.
  */
-QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, const uint8_t ucQueueType ) PRIVILEGED_FUNCTION;
+#if( configSUPPORT_STATIC_ALLOCATION == 1 )
+	QueueHandle_t xQueueGenericCreateStatic( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, uint8_t *pucQueueStorage, StaticQueue_t *pxStaticQueue, const uint8_t ucQueueType ) PRIVILEGED_FUNCTION;
+#endif
 
 /*
  * Queue sets provide a mechanism to allow a task to block (pend) on a read

+ 361 - 21
components/freertos/include/freertos/semphr.h

@@ -128,19 +128,37 @@ typedef QueueHandle_t SemaphoreHandle_t;
  * \defgroup vSemaphoreCreateBinary vSemaphoreCreateBinary
  * \ingroup Semaphores
  */
-#define vSemaphoreCreateBinary( xSemaphore )																							\
-	{																																	\
-		( xSemaphore ) = xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE );	\
-		if( ( xSemaphore ) != NULL )																									\
-		{																																\
-			( void ) xSemaphoreGive( ( xSemaphore ) );																					\
-		}																																\
-	}
+#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+	#define vSemaphoreCreateBinary( xSemaphore )																							\
+		{																																	\
+			( xSemaphore ) = xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE );	\
+			if( ( xSemaphore ) != NULL )																									\
+			{																																\
+				( void ) xSemaphoreGive( ( xSemaphore ) );																					\
+			}																																\
+		}
+#endif
 
 /**
  * semphr. h
  * <pre>SemaphoreHandle_t xSemaphoreCreateBinary( void )</pre>
  *
+ * Creates a new binary semaphore instance, and returns a handle by which the
+ * new semaphore can be referenced.
+ *
+ * In many usage scenarios it is faster and more memory efficient to use a
+ * direct to task notification in place of a binary semaphore!
+ * http://www.freertos.org/RTOS-task-notifications.html
+ *
+ * Internally, within the FreeRTOS implementation, binary semaphores use a block
+ * of memory, in which the semaphore structure is stored.  If a binary semaphore
+ * is created using xSemaphoreCreateBinary() then the required memory is
+ * automatically dynamically allocated inside the xSemaphoreCreateBinary()
+ * function.  (see http://www.freertos.org/a00111.html).  If a binary semaphore
+ * is created using xSemaphoreCreateBinaryStatic() then the application writer
+ * must provide the memory.  xSemaphoreCreateBinaryStatic() therefore allows a
+ * binary semaphore to be created without using any dynamic memory allocation.
+ *
  * The old vSemaphoreCreateBinary() macro is now deprecated in favour of this
  * xSemaphoreCreateBinary() function.  Note that binary semaphores created using
  * the vSemaphoreCreateBinary() macro are created in a state such that the
@@ -182,7 +200,68 @@ typedef QueueHandle_t SemaphoreHandle_t;
  * \defgroup vSemaphoreCreateBinary vSemaphoreCreateBinary
  * \ingroup Semaphores
  */
-#define xSemaphoreCreateBinary() xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE )
+#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+	#define xSemaphoreCreateBinary() xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE )
+#endif
+
+/**
+ * semphr. h
+ * <pre>SemaphoreHandle_t xSemaphoreCreateBinaryStatic( StaticSemaphore_t *pxSemaphoreBuffer )</pre>
+ *
+ * Creates a new binary semaphore instance, and returns a handle by which the
+ * new semaphore can be referenced.
+ *
+ * NOTE: In many usage scenarios it is faster and more memory efficient to use a
+ * direct to task notification in place of a binary semaphore!
+ * http://www.freertos.org/RTOS-task-notifications.html
+ *
+ * Internally, within the FreeRTOS implementation, binary semaphores use a block
+ * of memory, in which the semaphore structure is stored.  If a binary semaphore
+ * is created using xSemaphoreCreateBinary() then the required memory is
+ * automatically dynamically allocated inside the xSemaphoreCreateBinary()
+ * function.  (see http://www.freertos.org/a00111.html).  If a binary semaphore
+ * is created using xSemaphoreCreateBinaryStatic() then the application writer
+ * must provide the memory.  xSemaphoreCreateBinaryStatic() therefore allows a
+ * binary semaphore to be created without using any dynamic memory allocation.
+ *
+ * This type of semaphore can be used for pure synchronisation between tasks or
+ * between an interrupt and a task.  The semaphore need not be given back once
+ * obtained, so one task/interrupt can continuously 'give' the semaphore while
+ * another continuously 'takes' the semaphore.  For this reason this type of
+ * semaphore does not use a priority inheritance mechanism.  For an alternative
+ * that does use priority inheritance see xSemaphoreCreateMutex().
+ *
+ * @param pxSemaphoreBuffer Must point to a variable of type StaticSemaphore_t,
+ * which will then be used to hold the semaphore's data structure, removing the
+ * need for the memory to be allocated dynamically.
+ *
+ * @return If the semaphore is created then a handle to the created semaphore is
+ * returned.  If pxSemaphoreBuffer is NULL then NULL is returned.
+ *
+ * Example usage:
+ <pre>
+ SemaphoreHandle_t xSemaphore = NULL;
+ StaticSemaphore_t xSemaphoreBuffer;
+
+ void vATask( void * pvParameters )
+ {
+    // Semaphore cannot be used before a call to xSemaphoreCreateBinary().
+    // The semaphore's data structures will be placed in the xSemaphoreBuffer
+    // variable, the address of which is passed into the function.  The
+    // function's parameter is not NULL, so the function will not attempt any
+    // dynamic memory allocation, and therefore the function will not return
+    // return NULL.
+    xSemaphore = xSemaphoreCreateBinary( &xSemaphoreBuffer );
+
+    // Rest of task code goes here.
+ }
+ </pre>
+ * \defgroup xSemaphoreCreateBinaryStatic xSemaphoreCreateBinaryStatic
+ * \ingroup Semaphores
+ */
+#if( configSUPPORT_STATIC_ALLOCATION == 1 )
+	#define xSemaphoreCreateBinaryStatic( pxStaticSemaphore ) xQueueGenericCreateStatic( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, NULL, pxStaticSemaphore, queueQUEUE_TYPE_BINARY_SEMAPHORE )
+#endif /* configSUPPORT_STATIC_ALLOCATION */
 
 /**
  * semphr. h
@@ -652,9 +731,18 @@ typedef QueueHandle_t SemaphoreHandle_t;
  * <i>Macro</i> that implements a mutex semaphore by using the existing queue
  * mechanism.
  *
- * Mutexes created using this macro can be accessed using the xSemaphoreTake()
+ * Internally, within the FreeRTOS implementation, mutex semaphores use a block
+ * of memory, in which the mutex structure is stored.  If a mutex is created
+ * using xSemaphoreCreateMutex() then the required memory is automatically
+ * dynamically allocated inside the xSemaphoreCreateMutex() function.  (see
+ * http://www.freertos.org/a00111.html).  If a mutex is created using
+ * xSemaphoreCreateMutexStatic() then the application writer must provided the
+ * memory.  xSemaphoreCreateMutexStatic() therefore allows a mutex to be created
+ * without using any dynamic memory allocation.
+ *
+ * Mutexes created using this function can be accessed using the xSemaphoreTake()
  * and xSemaphoreGive() macros.  The xSemaphoreTakeRecursive() and
- * xSemaphoreGiveRecursive() macros should not be used.
+ * xSemaphoreGiveRecursive() macros must not be used.
  *
  * This type of semaphore uses a priority inheritance mechanism so a task
  * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the
@@ -667,8 +755,9 @@ typedef QueueHandle_t SemaphoreHandle_t;
  * semaphore and another always 'takes' the semaphore) and from within interrupt
  * service routines.
  *
- * @return xSemaphore Handle to the created mutex semaphore.  Should be of type
- *		SemaphoreHandle_t.
+ * @return If the mutex was successfully created then a handle to the created
+ * semaphore is returned.  If there was not enough heap to allocate the mutex
+ * data structures then NULL is returned.
  *
  * Example usage:
  <pre>
@@ -690,19 +779,93 @@ typedef QueueHandle_t SemaphoreHandle_t;
  * \defgroup vSemaphoreCreateMutex vSemaphoreCreateMutex
  * \ingroup Semaphores
  */
-#define xSemaphoreCreateMutex() xQueueCreateMutex( queueQUEUE_TYPE_MUTEX )
+#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+	#define xSemaphoreCreateMutex() xQueueCreateMutex( queueQUEUE_TYPE_MUTEX )
+#endif
+
+/**
+ * semphr. h
+ * <pre>SemaphoreHandle_t xSemaphoreCreateMutexStatic( StaticSemaphore_t *pxMutexBuffer )</pre>
+ *
+ * Creates a new mutex type semaphore instance, and returns a handle by which
+ * the new mutex can be referenced.
+ *
+ * Internally, within the FreeRTOS implementation, mutex semaphores use a block
+ * of memory, in which the mutex structure is stored.  If a mutex is created
+ * using xSemaphoreCreateMutex() then the required memory is automatically
+ * dynamically allocated inside the xSemaphoreCreateMutex() function.  (see
+ * http://www.freertos.org/a00111.html).  If a mutex is created using
+ * xSemaphoreCreateMutexStatic() then the application writer must provided the
+ * memory.  xSemaphoreCreateMutexStatic() therefore allows a mutex to be created
+ * without using any dynamic memory allocation.
+ *
+ * Mutexes created using this function can be accessed using the xSemaphoreTake()
+ * and xSemaphoreGive() macros.  The xSemaphoreTakeRecursive() and
+ * xSemaphoreGiveRecursive() macros must not be used.
+ *
+ * This type of semaphore uses a priority inheritance mechanism so a task
+ * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the
+ * semaphore it is no longer required.
+ *
+ * Mutex type semaphores cannot be used from within interrupt service routines.
+ *
+ * See xSemaphoreCreateBinary() for an alternative implementation that can be
+ * used for pure synchronisation (where one task or interrupt always 'gives' the
+ * semaphore and another always 'takes' the semaphore) and from within interrupt
+ * service routines.
+ *
+ * @param pxMutexBuffer Must point to a variable of type StaticSemaphore_t,
+ * which will be used to hold the mutex's data structure, removing the need for
+ * the memory to be allocated dynamically.
+ *
+ * @return If the mutex was successfully created then a handle to the created
+ * mutex is returned.  If pxMutexBuffer was NULL then NULL is returned.
+ *
+ * Example usage:
+ <pre>
+ SemaphoreHandle_t xSemaphore;
+ StaticSemaphore_t xMutexBuffer;
+
+ void vATask( void * pvParameters )
+ {
+    // A mutex cannot be used before it has been created.  xMutexBuffer is
+    // into xSemaphoreCreateMutexStatic() so no dynamic memory allocation is
+    // attempted.
+    xSemaphore = xSemaphoreCreateMutexStatic( &xMutexBuffer );
+
+    // As no dynamic memory allocation was performed, xSemaphore cannot be NULL,
+    // so there is no need to check it.
+ }
+ </pre>
+ * \defgroup xSemaphoreCreateMutexStatic xSemaphoreCreateMutexStatic
+ * \ingroup Semaphores
+ */
+ #if( configSUPPORT_STATIC_ALLOCATION == 1 )
+	#define xSemaphoreCreateMutexStatic( pxMutexBuffer ) xQueueCreateMutexStatic( queueQUEUE_TYPE_MUTEX, ( pxMutexBuffer ) )
+#endif /* configSUPPORT_STATIC_ALLOCATION */
 
 
 /**
  * semphr. h
  * <pre>SemaphoreHandle_t xSemaphoreCreateRecursiveMutex( void )</pre>
  *
- * <i>Macro</i> that implements a recursive mutex by using the existing queue
- * mechanism.
+ * Creates a new recursive mutex type semaphore instance, and returns a handle
+ * by which the new recursive mutex can be referenced.
+ *
+ * Internally, within the FreeRTOS implementation, recursive mutexs use a block
+ * of memory, in which the mutex structure is stored.  If a recursive mutex is
+ * created using xSemaphoreCreateRecursiveMutex() then the required memory is
+ * automatically dynamically allocated inside the
+ * xSemaphoreCreateRecursiveMutex() function.  (see
+ * http://www.freertos.org/a00111.html).  If a recursive mutex is created using
+ * xSemaphoreCreateRecursiveMutexStatic() then the application writer must
+ * provide the memory that will get used by the mutex.
+ * xSemaphoreCreateRecursiveMutexStatic() therefore allows a recursive mutex to
+ * be created without using any dynamic memory allocation.
  *
  * Mutexes created using this macro can be accessed using the
  * xSemaphoreTakeRecursive() and xSemaphoreGiveRecursive() macros.  The
- * xSemaphoreTake() and xSemaphoreGive() macros should not be used.
+ * xSemaphoreTake() and xSemaphoreGive() macros must not be used.
  *
  * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex
  * doesn't become available again until the owner has called
@@ -745,14 +908,104 @@ typedef QueueHandle_t SemaphoreHandle_t;
  * \defgroup vSemaphoreCreateMutex vSemaphoreCreateMutex
  * \ingroup Semaphores
  */
-#define xSemaphoreCreateRecursiveMutex() xQueueCreateMutex( queueQUEUE_TYPE_RECURSIVE_MUTEX )
+#if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configUSE_RECURSIVE_MUTEXES == 1 ) )
+	#define xSemaphoreCreateRecursiveMutex() xQueueCreateMutex( queueQUEUE_TYPE_RECURSIVE_MUTEX )
+#endif
+
+/**
+ * semphr. h
+ * <pre>SemaphoreHandle_t xSemaphoreCreateRecursiveMutexStatic( StaticSemaphore_t *pxMutexBuffer )</pre>
+ *
+ * Creates a new recursive mutex type semaphore instance, and returns a handle
+ * by which the new recursive mutex can be referenced.
+ *
+ * Internally, within the FreeRTOS implementation, recursive mutexs use a block
+ * of memory, in which the mutex structure is stored.  If a recursive mutex is
+ * created using xSemaphoreCreateRecursiveMutex() then the required memory is
+ * automatically dynamically allocated inside the
+ * xSemaphoreCreateRecursiveMutex() function.  (see
+ * http://www.freertos.org/a00111.html).  If a recursive mutex is created using
+ * xSemaphoreCreateRecursiveMutexStatic() then the application writer must
+ * provide the memory that will get used by the mutex.
+ * xSemaphoreCreateRecursiveMutexStatic() therefore allows a recursive mutex to
+ * be created without using any dynamic memory allocation.
+ *
+ * Mutexes created using this macro can be accessed using the
+ * xSemaphoreTakeRecursive() and xSemaphoreGiveRecursive() macros.  The
+ * xSemaphoreTake() and xSemaphoreGive() macros must not be used.
+ *
+ * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex
+ * doesn't become available again until the owner has called
+ * xSemaphoreGiveRecursive() for each successful 'take' request.  For example,
+ * if a task successfully 'takes' the same mutex 5 times then the mutex will
+ * not be available to any other task until it has also  'given' the mutex back
+ * exactly five times.
+ *
+ * This type of semaphore uses a priority inheritance mechanism so a task
+ * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the
+ * semaphore it is no longer required.
+ *
+ * Mutex type semaphores cannot be used from within interrupt service routines.
+ *
+ * See xSemaphoreCreateBinary() for an alternative implementation that can be
+ * used for pure synchronisation (where one task or interrupt always 'gives' the
+ * semaphore and another always 'takes' the semaphore) and from within interrupt
+ * service routines.
+ *
+ * @param pxMutexBuffer Must point to a variable of type StaticSemaphore_t,
+ * which will then be used to hold the recursive mutex's data structure,
+ * removing the need for the memory to be allocated dynamically.
+ *
+ * @return If the recursive mutex was successfully created then a handle to the
+ * created recursive mutex is returned.  If pxMutexBuffer was NULL then NULL is
+ * returned.
+ *
+ * Example usage:
+ <pre>
+ SemaphoreHandle_t xSemaphore;
+ StaticSemaphore_t xMutexBuffer;
+
+ void vATask( void * pvParameters )
+ {
+    // A recursive semaphore cannot be used before it is created.  Here a
+    // recursive mutex is created using xSemaphoreCreateRecursiveMutexStatic().
+    // The address of xMutexBuffer is passed into the function, and will hold
+    // the mutexes data structures - so no dynamic memory allocation will be
+    // attempted.
+    xSemaphore = xSemaphoreCreateRecursiveMutexStatic( &xMutexBuffer );
+
+    // As no dynamic memory allocation was performed, xSemaphore cannot be NULL,
+    // so there is no need to check it.
+ }
+ </pre>
+ * \defgroup xSemaphoreCreateRecursiveMutexStatic xSemaphoreCreateRecursiveMutexStatic
+ * \ingroup Semaphores
+ */
+#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configUSE_RECURSIVE_MUTEXES == 1 ) )
+	#define xSemaphoreCreateRecursiveMutexStatic( pxStaticSemaphore ) xQueueCreateMutexStatic( queueQUEUE_TYPE_RECURSIVE_MUTEX, pxStaticSemaphore )
+#endif /* configSUPPORT_STATIC_ALLOCATION */
 
 /**
  * semphr. h
  * <pre>SemaphoreHandle_t xSemaphoreCreateCounting( UBaseType_t uxMaxCount, UBaseType_t uxInitialCount )</pre>
  *
- * <i>Macro</i> that creates a counting semaphore by using the existing
- * queue mechanism.
+ * Creates a new counting semaphore instance, and returns a handle by which the
+ * new counting semaphore can be referenced.
+ *
+ * In many usage scenarios it is faster and more memory efficient to use a
+ * direct to task notification in place of a counting semaphore!
+ * http://www.freertos.org/RTOS-task-notifications.html
+ *
+ * Internally, within the FreeRTOS implementation, counting semaphores use a
+ * block of memory, in which the counting semaphore structure is stored.  If a
+ * counting semaphore is created using xSemaphoreCreateCounting() then the
+ * required memory is automatically dynamically allocated inside the
+ * xSemaphoreCreateCounting() function.  (see
+ * http://www.freertos.org/a00111.html).  If a counting semaphore is created
+ * using xSemaphoreCreateCountingStatic() then the application writer can
+ * instead optionally provide the memory that will get used by the counting
+ * semaphore.  xSemaphoreCreateCountingStatic() therefore allows a counting
+ * semaphore to be created without using any dynamic memory allocation.
  *
  * Counting semaphores are typically used for two things:
  *
@@ -808,7 +1061,94 @@ typedef QueueHandle_t SemaphoreHandle_t;
  * \defgroup xSemaphoreCreateCounting xSemaphoreCreateCounting
  * \ingroup Semaphores
  */
-#define xSemaphoreCreateCounting( uxMaxCount, uxInitialCount ) xQueueCreateCountingSemaphore( ( uxMaxCount ), ( uxInitialCount ) )
+#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+	#define xSemaphoreCreateCounting( uxMaxCount, uxInitialCount ) xQueueCreateCountingSemaphore( ( uxMaxCount ), ( uxInitialCount ) )
+#endif
+
+/**
+ * semphr. h
+ * <pre>SemaphoreHandle_t xSemaphoreCreateCountingStatic( UBaseType_t uxMaxCount, UBaseType_t uxInitialCount, StaticSemaphore_t *pxSemaphoreBuffer )</pre>
+ *
+ * Creates a new counting semaphore instance, and returns a handle by which the
+ * new counting semaphore can be referenced.
+ *
+ * In many usage scenarios it is faster and more memory efficient to use a
+ * direct to task notification in place of a counting semaphore!
+ * http://www.freertos.org/RTOS-task-notifications.html
+ *
+ * Internally, within the FreeRTOS implementation, counting semaphores use a
+ * block of memory, in which the counting semaphore structure is stored.  If a
+ * counting semaphore is created using xSemaphoreCreateCounting() then the
+ * required memory is automatically dynamically allocated inside the
+ * xSemaphoreCreateCounting() function.  (see
+ * http://www.freertos.org/a00111.html).  If a counting semaphore is created
+ * using xSemaphoreCreateCountingStatic() then the application writer must
+ * provide the memory.  xSemaphoreCreateCountingStatic() therefore allows a
+ * counting semaphore to be created without using any dynamic memory allocation.
+ *
+ * Counting semaphores are typically used for two things:
+ *
+ * 1) Counting events.
+ *
+ *    In this usage scenario an event handler will 'give' a semaphore each time
+ *    an event occurs (incrementing the semaphore count value), and a handler
+ *    task will 'take' a semaphore each time it processes an event
+ *    (decrementing the semaphore count value).  The count value is therefore
+ *    the difference between the number of events that have occurred and the
+ *    number that have been processed.  In this case it is desirable for the
+ *    initial count value to be zero.
+ *
+ * 2) Resource management.
+ *
+ *    In this usage scenario the count value indicates the number of resources
+ *    available.  To obtain control of a resource a task must first obtain a
+ *    semaphore - decrementing the semaphore count value.  When the count value
+ *    reaches zero there are no free resources.  When a task finishes with the
+ *    resource it 'gives' the semaphore back - incrementing the semaphore count
+ *    value.  In this case it is desirable for the initial count value to be
+ *    equal to the maximum count value, indicating that all resources are free.
+ *
+ * @param uxMaxCount The maximum count value that can be reached.  When the
+ *        semaphore reaches this value it can no longer be 'given'.
+ *
+ * @param uxInitialCount The count value assigned to the semaphore when it is
+ *        created.
+ *
+ * @param pxSemaphoreBuffer Must point to a variable of type StaticSemaphore_t,
+ * which will then be used to hold the semaphore's data structure, removing the
+ * need for the memory to be allocated dynamically.
+ *
+ * @return If the counting semaphore was successfully created then a handle to
+ * the created counting semaphore is returned.  If pxSemaphoreBuffer was NULL
+ * then NULL is returned.
+ *
+ * Example usage:
+ <pre>
+ SemaphoreHandle_t xSemaphore;
+ StaticSemaphore_t xSemaphoreBuffer;
+
+ void vATask( void * pvParameters )
+ {
+ SemaphoreHandle_t xSemaphore = NULL;
+
+    // Counting semaphore cannot be used before they have been created.  Create
+    // a counting semaphore using xSemaphoreCreateCountingStatic().  The max
+    // value to which the semaphore can count is 10, and the initial value
+    // assigned to the count will be 0.  The address of xSemaphoreBuffer is
+    // passed in and will be used to hold the semaphore structure, so no dynamic
+    // memory allocation will be used.
+    xSemaphore = xSemaphoreCreateCounting( 10, 0, &xSemaphoreBuffer );
+
+    // No memory allocation was attempted so xSemaphore cannot be NULL, so there
+    // is no need to check its value.
+ }
+ </pre>
+ * \defgroup xSemaphoreCreateCountingStatic xSemaphoreCreateCountingStatic
+ * \ingroup Semaphores
+ */
+#if( configSUPPORT_STATIC_ALLOCATION == 1 )
+	#define xSemaphoreCreateCountingStatic( uxMaxCount, uxInitialCount, pxSemaphoreBuffer ) xQueueCreateCountingSemaphoreStatic( ( uxMaxCount ), ( uxInitialCount ), ( pxSemaphoreBuffer ) )
+#endif /* configSUPPORT_STATIC_ALLOCATION */
 
 /**
  * semphr. h

+ 161 - 11
components/freertos/include/freertos/task.h

@@ -177,6 +177,7 @@ typedef struct xTASK_STATUS
 	UBaseType_t uxCurrentPriority;	/* The priority at which the task was running (may be inherited) when the structure was populated. */
 	UBaseType_t uxBasePriority;		/* The priority to which the task will return if the task's current priority has been inherited to avoid unbounded priority inversion when obtaining a mutex.  Only valid if configUSE_MUTEXES is defined as 1 in FreeRTOSConfig.h. */
 	uint32_t ulRunTimeCounter;		/* The total run time allocated to the task so far, as defined by the run time stats clock.  See http://www.freertos.org/rtos-run-time-stats.html.  Only valid when configGENERATE_RUN_TIME_STATS is defined as 1 in FreeRTOSConfig.h. */
+	StackType_t *pxStackBase;		/* Points to the lowest address of the task's stack area. */
 	uint16_t usStackHighWaterMark;	/* The minimum amount of stack space that has remained for the task since the task was created.  The closer this value is to zero the closer the task has come to overflowing its stack. */
 } TaskStatus_t;
 
@@ -281,8 +282,19 @@ is used in assert() statements. */
 						  );</pre>
  *
  * Create a new task and add it to the list of tasks that are ready to run.
- * On multicore environments, this will give no specific affinity to the task.
- * Use xTaskCreatePinnedToCore to give affinity.
+ *
+ * Internally, within the FreeRTOS implementation, tasks use two blocks of
+ * memory.  The first block is used to hold the task's data structures.  The
+ * second block is used by the task as its stack.  If a task is created using
+ * xTaskCreate() then both blocks of memory are automatically dynamically
+ * allocated inside the xTaskCreate() function.  (see
+ * http://www.freertos.org/a00111.html).  If a task is created using
+ * xTaskCreateStatic() then the application writer must provide the required
+ * memory.  xTaskCreateStatic() therefore allows a task to be created without
+ * using any dynamic memory allocation.
+ *
+ * See xTaskCreateStatic() for a version that does not use any dynamic memory
+ * allocation.
  *
  * xTaskCreate() can only be used to create a task that has unrestricted
  * access to the entire microcontroller memory map.  Systems that include MPU
@@ -350,8 +362,139 @@ is used in assert() statements. */
  * \defgroup xTaskCreate xTaskCreate
  * \ingroup Tasks
  */
-#define xTaskCreate( pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask ) xTaskGenericCreate( ( pvTaskCode ), ( pcName ), ( usStackDepth ), ( pvParameters ), ( uxPriority ), ( pxCreatedTask ), ( NULL ), ( NULL ), tskNO_AFFINITY )
-#define xTaskCreatePinnedToCore( pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask, xCoreID ) xTaskGenericCreate( ( pvTaskCode ), ( pcName ), ( usStackDepth ), ( pvParameters ), ( uxPriority ), ( pxCreatedTask ), ( NULL ), ( NULL ), xCoreID )
+#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+    BaseType_t xTaskCreatePinnedToCore(	TaskFunction_t pxTaskCode,
+							            const char * const pcName,
+							            const uint16_t usStackDepth,
+							            void * const pvParameters,
+							            UBaseType_t uxPriority,
+							            TaskHandle_t * const pxCreatedTask,
+							            const BaseType_t xCoreID);
+
+#define xTaskCreate( pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask ) xTaskCreatePinnedToCore( ( pvTaskCode ), ( pcName ), ( usStackDepth ), ( pvParameters ), ( uxPriority ), ( pxCreatedTask ), tskNO_AFFINITY )
+#endif
+
+/**
+ * task. h
+ *<pre>
+ TaskHandle_t xTaskCreateStatic( TaskFunction_t pvTaskCode,
+								 const char * const pcName,
+								 uint32_t ulStackDepth,
+								 void *pvParameters,
+								 UBaseType_t uxPriority,
+								 StackType_t *pxStackBuffer,
+								 StaticTask_t *pxTaskBuffer,
+                                 const BaseType_t xCoreID );</pre>
+
+ *
+ * Create a new task and add it to the list of tasks that are ready to run.
+ *
+ * Internally, within the FreeRTOS implementation, tasks use two blocks of
+ * memory.  The first block is used to hold the task's data structures.  The
+ * second block is used by the task as its stack.  If a task is created using
+ * xTaskCreate() then both blocks of memory are automatically dynamically
+ * allocated inside the xTaskCreate() function.  (see
+ * http://www.freertos.org/a00111.html).  If a task is created using
+ * xTaskCreateStatic() then the application writer must provide the required
+ * memory.  xTaskCreateStatic() therefore allows a task to be created without
+ * using any dynamic memory allocation.
+ *
+ * @param pvTaskCode Pointer to the task entry function.  Tasks
+ * must be implemented to never return (i.e. continuous loop).
+ *
+ * @param pcName A descriptive name for the task.  This is mainly used to
+ * facilitate debugging.  The maximum length of the string is defined by
+ * configMAX_TASK_NAME_LEN in FreeRTOSConfig.h.
+ *
+ * @param ulStackDepth The size of the task stack specified as the number of
+ * variables the stack can hold - not the number of bytes.  For example, if
+ * the stack is 32-bits wide and ulStackDepth is defined as 100 then 400 bytes
+ * will be allocated for stack storage.
+ *
+ * @param pvParameters Pointer that will be used as the parameter for the task
+ * being created.
+ *
+ * @param uxPriority The priority at which the task will run.
+ *
+ * @param pxStackBuffer Must point to a StackType_t array that has at least
+ * ulStackDepth indexes - the array will then be used as the task's stack,
+ * removing the need for the stack to be allocated dynamically.
+ *
+ * @param pxTaskBuffer Must point to a variable of type StaticTask_t, which will
+ * then be used to hold the task's data structures, removing the need for the
+ * memory to be allocated dynamically.
+ *
+ * @return If neither pxStackBuffer or pxTaskBuffer are NULL, then the task will
+ * be created and pdPASS is returned.  If either pxStackBuffer or pxTaskBuffer
+ * are NULL then the task will not be created and
+ * errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY is returned.
+ *
+ * Example usage:
+   <pre>
+
+    // Dimensions the buffer that the task being created will use as its stack.
+    // NOTE:  This is the number of words the stack will hold, not the number of
+    // bytes.  For example, if each stack item is 32-bits, and this is set to 100,
+    // then 400 bytes (100 * 32-bits) will be allocated.
+    #define STACK_SIZE 200
+
+    // Structure that will hold the TCB of the task being created.
+    StaticTask_t xTaskBuffer;
+
+    // Buffer that the task being created will use as its stack.  Note this is
+    // an array of StackType_t variables.  The size of StackType_t is dependent on
+    // the RTOS port.
+    StackType_t xStack[ STACK_SIZE ];
+
+    // Function that implements the task being created.
+    void vTaskCode( void * pvParameters )
+    {
+        // The parameter value is expected to be 1 as 1 is passed in the
+        // pvParameters value in the call to xTaskCreateStatic().
+        configASSERT( ( uint32_t ) pvParameters == 1UL );
+
+        for( ;; )
+        {
+            // Task code goes here.
+        }
+    }
+
+    // Function that creates a task.
+    void vOtherFunction( void )
+    {
+        TaskHandle_t xHandle = NULL;
+
+        // Create the task without using any dynamic memory allocation.
+        xHandle = xTaskCreateStatic(
+                      vTaskCode,       // Function that implements the task.
+                      "NAME",          // Text name for the task.
+                      STACK_SIZE,      // Stack size in words, not bytes.
+                      ( void * ) 1,    // Parameter passed into the task.
+                      tskIDLE_PRIORITY,// Priority at which the task is created.
+                      xStack,          // Array to use as the task's stack.
+                      &xTaskBuffer );  // Variable to hold the task's data structure.
+
+        // puxStackBuffer and pxTaskBuffer were not NULL, so the task will have
+        // been created, and xHandle will be the task's handle.  Use the handle
+        // to suspend the task.
+        vTaskSuspend( xHandle );
+    }
+   </pre>
+ * \defgroup xTaskCreateStatic xTaskCreateStatic
+ * \ingroup Tasks
+ */
+#if( configSUPPORT_STATIC_ALLOCATION == 1 )
+	TaskHandle_t xTaskCreateStaticPinnedToCore(	TaskFunction_t pxTaskCode,
+									            const char * const pcName,
+									            const uint32_t ulStackDepth,
+									            void * const pvParameters,
+									            UBaseType_t uxPriority,
+									            StackType_t * const puxStackBuffer,
+									            StaticTask_t * const pxTaskBuffer,
+                                                const BaseType_t xCoreID );
+
+#define xTaskCreateStatic( pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxStackBuffer, pxTaskBuffer ) xTaskCreateStaticPinnedToCore( ( pvTaskCode ), ( pcName ), ( usStackDepth ), ( pvParameters ), ( uxPriority ), ( pxStackBuffer ), ( pxTaskBuffer ), tskNO_AFFINITY )
+#endif /* configSUPPORT_STATIC_ALLOCATION */
 
 /**
  * task. h
@@ -420,7 +563,9 @@ TaskHandle_t xHandle;
  * \defgroup xTaskCreateRestricted xTaskCreateRestricted
  * \ingroup Tasks
  */
-#define xTaskCreateRestricted( x, pxCreatedTask ) xTaskGenericCreate( ((x)->pvTaskCode), ((x)->pcName), ((x)->usStackDepth), ((x)->pvParameters), ((x)->uxPriority), (pxCreatedTask), ((x)->puxStackBuffer), ((x)->xRegions) )
+#if( portUSING_MPU_WRAPPERS == 1 )
+	BaseType_t xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask ) PRIVILEGED_FUNCTION;
+#endif
 
 /**
  * task. h
@@ -1933,6 +2078,17 @@ TickType_t uxTaskResetEventItemValue( void ) PRIVILEGED_FUNCTION;
  */
 TaskHandle_t xTaskGetCurrentTaskHandle( void ) PRIVILEGED_FUNCTION;
 
+
+
+/*
+ * Return the handle of the task running on a certain CPU. Because of
+ * the nature of SMP processing, there is no guarantee that this
+ * value will still be valid on return and should only be used for
+ * debugging purposes.
+ */
+TaskHandle_t xTaskGetCurrentTaskHandleForCPU( BaseType_t cpuid );
+
+
 /*
  * Capture the current time status for future reference.
  */
@@ -1968,12 +2124,6 @@ void vTaskPriorityInherit( TaskHandle_t const pxMutexHolder ) PRIVILEGED_FUNCTIO
  */
 BaseType_t xTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder ) PRIVILEGED_FUNCTION;
 
-/*
- * Generic version of the task creation function which is in turn called by the
- * xTaskCreate() and xTaskCreateRestricted() macros.
- */
-BaseType_t xTaskGenericCreate( TaskFunction_t pxTaskCode, const char * const pcName, const uint16_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask, StackType_t * const puxStackBuffer, const MemoryRegion_t * const xRegions, const BaseType_t xCoreID) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
-
 /*
  * Get the uxTCBNumber assigned to the task referenced by the xTask parameter.
  */

+ 1 - 6
components/freertos/include/freertos/xtensa_context.h

@@ -322,12 +322,7 @@ STRUCT_END(XtSolFrame)
 #ifdef __ASSEMBLER__
 	.macro getcoreid reg
 	rsr.prid \reg
-	bbci \reg,1,1f
-	movi \reg,1
-	j 2f
-1:
-	movi \reg,0
-2:
+	extui \reg,\reg,13,1
 	.endm
 #endif
 

+ 27 - 36
components/freertos/port.c

@@ -101,7 +101,9 @@
 #include "FreeRTOS.h"
 #include "task.h"
 
-#include "panic.h"
+#include "esp_panic.h"
+
+#include "esp_crosscore_int.h"
 
 /* Defined in portasm.h */
 extern void _frxt_tick_timer_init(void);
@@ -228,6 +230,12 @@ BaseType_t xPortSysTickHandler( void )
 
 	return ret;
 }
+
+
+void vPortYieldOtherCore( BaseType_t coreid ) {
+	esp_crosscore_int_send_yield( coreid );
+}
+
 /*-----------------------------------------------------------*/
 
 /*
@@ -253,28 +261,6 @@ void vPortAssertIfInISR()
 	configASSERT(port_interruptNesting[xPortGetCoreID()]==0)
 }
 
-
-/*
- * Wrapper for the Xtensa compare-and-set instruction. This subroutine will atomically compare
- * *mux to compare, and if it's the same, will set *mux to set. It will return the old value
- * of *addr.
- *
- * Warning: From the ISA docs: in some (unspecified) cases, the s32c1i instruction may return the
- * *bitwise inverse* of the old mem if the mem wasn't written. This doesn't seem to happen on the
- * ESP32, though. (Would show up directly if it did because the magic wouldn't match.)
- */
-uint32_t uxPortCompareSet(volatile uint32_t *mux, uint32_t compare, uint32_t set)
-{
-	__asm__ __volatile__ (
-		"WSR 	    %2,SCOMPARE1 \n" //initialize SCOMPARE1
-		"ISYNC      \n" //wait sync
-		"S32C1I     %0, %1, 0	 \n" //store id into the lock, if the lock is the same as comparel. Otherwise, no write-access
-		:"=r"(set) \
-		:"r"(mux), "r"(compare), "0"(set) \
-		);
-	return set;
-}
-
 /*
  * For kernel use: Initialize a per-CPU mux. Mux will be initialized unlocked.
  */
@@ -310,7 +296,8 @@ void vPortCPUAcquireMutex(portMUX_TYPE *mux) {
 	irqStatus=portENTER_CRITICAL_NESTED();
 	do {
 		//Lock mux if it's currently unlocked
-		res=uxPortCompareSet(&mux->mux, portMUX_FREE_VAL, (xPortGetCoreID()<<portMUX_VAL_SHIFT)|portMUX_MAGIC_VAL);
+		res=(xPortGetCoreID()<<portMUX_VAL_SHIFT)|portMUX_MAGIC_VAL;
+		uxPortCompareSet(&mux->mux, portMUX_FREE_VAL, &res);
 		//If it wasn't free and we're the owner of the lock, we are locking recursively.
 		if ( (res != portMUX_FREE_VAL) && (((res&portMUX_VAL_MASK)>>portMUX_VAL_SHIFT) == xPortGetCoreID()) ) {
 			//Mux was already locked by us. Just bump the recurse count by one.
@@ -362,29 +349,33 @@ portBASE_TYPE vPortCPUReleaseMutex(portMUX_TYPE *mux) {
 	if ( (mux->mux & portMUX_MAGIC_MASK) != portMUX_MAGIC_VAL ) ets_printf("ERROR: vPortCPUReleaseMutex: mux %p is uninitialized (0x%X)!\n", mux, mux->mux);
 #endif
 	//Unlock mux if it's currently locked with a recurse count of 0
-	res=uxPortCompareSet(&mux->mux, (xPortGetCoreID()<<portMUX_VAL_SHIFT)|portMUX_MAGIC_VAL, portMUX_FREE_VAL);
+	res=portMUX_FREE_VAL;
+	uxPortCompareSet(&mux->mux, (xPortGetCoreID()<<portMUX_VAL_SHIFT)|portMUX_MAGIC_VAL, &res);
 
-	if ( res == portMUX_FREE_VAL ) {
+	if ( ((res&portMUX_VAL_MASK)>>portMUX_VAL_SHIFT) == xPortGetCoreID() ) {
+		//Lock is valid, we can return safely. Just need to check if it's a recursive lock; if so we need to decrease the refcount.
+		 if ( ((res&portMUX_CNT_MASK)>>portMUX_CNT_SHIFT)!=0) {
+			//We locked this, but the reccount isn't zero. Decrease refcount and continue.
+			recCnt=(res&portMUX_CNT_MASK)>>portMUX_CNT_SHIFT;
+			recCnt--;
+#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG_RECURSIVE
+			ets_printf("Recursive unlock: recCnt=%d last locked %s line %d, curr %s line %d\n", recCnt, lastLockedFn, lastLockedLine, fnName, line);
+#endif
+			mux->mux=portMUX_MAGIC_VAL|(recCnt<<portMUX_CNT_SHIFT)|(xPortGetCoreID()<<portMUX_VAL_SHIFT);
+		}
+	} else if ( res == portMUX_FREE_VAL ) {
 #ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
 		ets_printf("ERROR: vPortCPUReleaseMutex: mux %p was already unlocked!\n", mux);
 		ets_printf("Last non-recursive unlock %s line %d, curr unlock %s line %d\n", lastLockedFn, lastLockedLine, fnName, line);
 #endif
 		ret=pdFALSE;
-	} else if ( ((res&portMUX_VAL_MASK)>>portMUX_VAL_SHIFT) != xPortGetCoreID() ) {
+	} else {
 #ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
 		ets_printf("ERROR: vPortCPUReleaseMutex: mux %p wasn't locked by this core (%d) but by core %d (ret=%x, mux=%x).\n", mux, xPortGetCoreID(), ((res&portMUX_VAL_MASK)>>portMUX_VAL_SHIFT), res, mux->mux);
 		ets_printf("Last non-recursive lock %s line %d\n", lastLockedFn, lastLockedLine);
 		ets_printf("Called by %s line %d\n", fnName, line);
 #endif
 		ret=pdFALSE;
-	} else if ( ((res&portMUX_CNT_MASK)>>portMUX_CNT_SHIFT)!=0) {
-		//We locked this, but the reccount isn't zero. Decrease refcount and continue.
-		recCnt=(res&portMUX_CNT_MASK)>>portMUX_CNT_SHIFT;
-		recCnt--;
-#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG_RECURSIVE
-		ets_printf("Recursive unlock: recCnt=%d last locked %s line %d, curr %s line %d\n", recCnt, lastLockedFn, lastLockedLine, fnName, line);
-#endif
-		mux->mux=portMUX_MAGIC_VAL|(recCnt<<portMUX_CNT_SHIFT)|(xPortGetCoreID()<<portMUX_VAL_SHIFT);
 	}
 	portEXIT_CRITICAL_NESTED(irqStatus);
 	return ret;
@@ -392,7 +383,7 @@ portBASE_TYPE vPortCPUReleaseMutex(portMUX_TYPE *mux) {
 
 #if CONFIG_FREERTOS_BREAK_ON_SCHEDULER_START_JTAG
 void vPortFirstTaskHook(TaskFunction_t function) {
-	setBreakpointIfJtag(function);
+	esp_set_breakpoint_if_jtag(function);
 }
 #endif
 

+ 19 - 41
components/freertos/portasm.S

@@ -51,18 +51,6 @@ port_switch_flag:
 
     .text
 
-
-
-/* C function to get proc ID.*/
-	.global xPortGetCoreID
-	.type xPortGetCoreID,@function
-	.align 4
-xPortGetCoreID:
-	ENTRY(16)
-	getcoreid a2
-	RET(16)
-
-
 /*
 *******************************************************************************
 * _frxt_setup_switch
@@ -81,9 +69,8 @@ _frxt_setup_switch:
     ENTRY(16)
 
 	getcoreid a3
-	slli	a3,  a3, 2
     movi    a2, port_switch_flag
-	add		a2,  a2, a3
+	addx4	a2,  a3, a2
 
     movi    a3, 1
     s32i    a3, a2, 0
@@ -128,12 +115,11 @@ _frxt_int_enter:
     Manage nesting directly rather than call the generic IntEnter()
     (in windowed ABI we can't call a C function here anyway because PS.EXCM is still set).
     */
-	getcoreid a3
-	slli	a4,  a3, 2					/* a4 = cpuid * 4 */
+	getcoreid a4
     movi    a2,  port_xSchedulerRunning
-	add		a2,  a2, a4
+	addx4	a2,  a4, a2
     movi    a3,  port_interruptNesting
-	add		a3,  a3, a4
+	addx4	a3,  a4, a3
     l32i    a2,  a2, 0                  /* a2 = port_xSchedulerRunning     */
     beqz    a2,  1f                     /* scheduler not running, no tasks */
     l32i    a2,  a3, 0                  /* a2 = port_interruptNesting      */
@@ -142,14 +128,13 @@ _frxt_int_enter:
     bnei    a2,  1, .Lnested            /* !=0 before incr, so nested      */
 
     movi    a2,  pxCurrentTCB
-	add		a2,  a2, a4
+	addx4	a2,  a4, a2
     l32i    a2,  a2, 0                  /* a2 = current TCB                */
     beqz    a2,  1f
     s32i    a1,  a2, TOPOFSTACK_OFFS    /* pxCurrentTCB->pxTopOfStack = SP */
     movi    a1,  port_IntStackTop       /* a1 = top of intr stack          */
 	movi	a2,  configISR_STACK_SIZE
-	getcoreid a3
-	mull	a2,  a3, a2
+	mull	a2,  a4, a2
 	add     a1,  a1, a2					/* for current proc */
 
 .Lnested:
@@ -177,12 +162,11 @@ _frxt_int_enter:
     .align  4
 _frxt_int_exit:
 
-	getcoreid a3
-	slli	a4,  a3, 2					/* a4 is core * 4 */
+	getcoreid a4
     movi    a2,  port_xSchedulerRunning
-	add		a2,  a2, a4
+	addx4	a2,  a4, a2
     movi    a3,  port_interruptNesting
-	add		a3,  a3, a4
+	addx4	a3,  a4, a3
     rsil    a0,  XCHAL_EXCM_LEVEL       /* lock out interrupts             */
     l32i    a2,  a2, 0                  /* a2 = port_xSchedulerRunning     */
     beqz    a2,  .Lnoswitch             /* scheduler not running, no tasks */
@@ -192,13 +176,13 @@ _frxt_int_exit:
     bnez    a2,  .Lnesting              /* !=0 after decr so still nested  */
 
     movi    a2,  pxCurrentTCB
-	add		a2,  a2, a4
+	addx4	a2,  a4, a2
     l32i    a2,  a2, 0                  /* a2 = current TCB                */
     beqz    a2,  1f                     /* no task ? go to dispatcher      */
     l32i    a1,  a2, TOPOFSTACK_OFFS    /* SP = pxCurrentTCB->pxTopOfStack */
 
     movi    a2,  port_switch_flag       /* address of switch flag          */
-	add		a2,  a2, a4					/* point to flag for this cpu      */
+	addx4	a2,  a4, a2					/* point to flag for this cpu      */
     l32i    a3,  a2, 0                  /* a3 = port_switch_flag           */
     beqz    a3,  .Lnoswitch             /* flag = 0 means no switch reqd   */
     movi    a3,  0
@@ -404,14 +388,12 @@ _frxt_dispatch:
     call0   vTaskSwitchContext  // Get next TCB to resume
     movi    a2, pxCurrentTCB
 	getcoreid a3
-	slli	a3,  a3, 2
-	add		a2,  a2, a3
+	addx4	a2,  a3, a2
     #else
     call4   vTaskSwitchContext  // Get next TCB to resume
     movi    a2, pxCurrentTCB
 	getcoreid a3
-	slli	a3,  a3, 2
-	add		a2,  a2, a3
+	addx4	a2,  a3, a2
     #endif
     l32i    a3,  a2, 0
     l32i    sp,  a3, TOPOFSTACK_OFFS     /* SP = next_TCB->pxTopOfStack;  */
@@ -451,8 +433,7 @@ _frxt_dispatch:
     /* Restore CPENABLE from task's co-processor save area. */
     movi    a3, pxCurrentTCB            /* cp_state =                       */
 	getcoreid a2
-	slli	a2,  a2, 2
-	add		a3,  a2, a3
+	addx4	a3,  a2, a3
     l32i    a3, a3, 0
     l32i    a2, a3, CP_TOPOFSTACK_OFFS     /* StackType_t                       *pxStack; */
     l16ui   a3, a2, XT_CPENABLE         /* CPENABLE = cp_state->cpenable;   */
@@ -541,8 +522,7 @@ vPortYield:
 
     movi    a2,  pxCurrentTCB
 	getcoreid a3
-	slli	a3,  a3, 2
-	add		a2,  a2, a3
+	addx4	a2,  a3, a2
     l32i    a2,  a2, 0                  /* a2 = pxCurrentTCB                */
     movi    a3,  0
     s32i    a3,  sp, XT_SOL_EXIT        /* 0 to flag as solicited frame     */
@@ -593,8 +573,7 @@ vPortYieldFromInt:
     /* Save CPENABLE in task's co-processor save area, and clear CPENABLE.  */
     movi    a3, pxCurrentTCB            /* cp_state =                       */
 	getcoreid a2
-	slli	a2,  a2, 2
-	add		a3,  a2, a3
+	addx4	a3,  a2, a3
     l32i    a3, a3, 0
 
     l32i    a2, a3, CP_TOPOFSTACK_OFFS
@@ -637,18 +616,17 @@ _frxt_task_coproc_state:
 
 	/* We can use a3 as a scratchpad, the instances of code calling XT_RTOS_CP_STATE don't seem to need it saved. */
 	getcoreid a3
-	slli	a3,  a3, 2			/* a3=coreid*4 */
     movi    a15, port_xSchedulerRunning /* if (port_xSchedulerRunning              */
-	add		a15, a15, a3
+	addx4	a15, a3,a15
     l32i    a15, a15, 0
     beqz    a15, 1f
     movi    a15, port_interruptNesting  /* && port_interruptNesting == 0           */
-	add		a15, a15, a3
+	addx4	a15, a3, a15
     l32i    a15, a15, 0
     bnez    a15, 1f
 
     movi    a15, pxCurrentTCB
-	add		a15,  a3, a15
+	addx4	a15, a3, a15
     l32i    a15, a15, 0                 /* && pxCurrentTCB != 0) {                 */
 
 

+ 236 - 97
components/freertos/queue.c

@@ -158,15 +158,19 @@ typedef struct QueueDefinition
 	UBaseType_t uxLength;			/*< The length of the queue defined as the number of items it will hold, not the number of bytes. */
 	UBaseType_t uxItemSize;			/*< The size of each items that the queue will hold. */
 
-	#if ( configUSE_TRACE_FACILITY == 1 )
-		UBaseType_t uxQueueNumber;
-		uint8_t ucQueueType;
+	#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
+		uint8_t ucStaticallyAllocated;	/*< Set to pdTRUE if the memory used by the queue was statically allocated to ensure no attempt is made to free the memory. */
 	#endif
 
 	#if ( configUSE_QUEUE_SETS == 1 )
 		struct QueueDefinition *pxQueueSetContainer;
 	#endif
 
+    #if ( configUSE_TRACE_FACILITY == 1 )
+		UBaseType_t uxQueueNumber;
+		uint8_t ucQueueType;
+	#endif
+
 	portMUX_TYPE mux;
 
 } xQUEUE;
@@ -238,6 +242,21 @@ static void prvCopyDataFromQueue( Queue_t * const pxQueue, void * const pvBuffer
 	static BaseType_t prvNotifyQueueSetContainer( const Queue_t * const pxQueue, const BaseType_t xCopyPosition ) PRIVILEGED_FUNCTION;
 #endif
 
+/*
+ * Called after a Queue_t structure has been allocated either statically or
+ * dynamically to fill in the structure's members.
+ */
+static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, uint8_t *pucQueueStorage, const uint8_t ucQueueType, Queue_t *pxNewQueue ) PRIVILEGED_FUNCTION;
+
+/*
+ * Mutexes are a special type of queue.  When a mutex is created, first the
+ * queue is created, then prvInitialiseMutex() is called to configure the queue
+ * as a mutex.
+ */
+#if( configUSE_MUTEXES == 1 )
+	static void prvInitialiseMutex( Queue_t *pxNewQueue ) PRIVILEGED_FUNCTION;
+#endif
+
 BaseType_t xQueueGenericReset( QueueHandle_t xQueue, BaseType_t xNewQueue )
 {
 Queue_t * const pxQueue = ( Queue_t * ) xQueue;
@@ -293,132 +312,165 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
 }
 /*-----------------------------------------------------------*/
 
-QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, const uint8_t ucQueueType )
-{
-Queue_t *pxNewQueue;
-size_t xQueueSizeInBytes;
-QueueHandle_t xReturn = NULL;
-int8_t *pcAllocatedBuffer;
+#if( configSUPPORT_STATIC_ALLOCATION == 1 )
 
-	/* Remove compiler warnings about unused parameters should
-	configUSE_TRACE_FACILITY not be set to 1. */
-	( void ) ucQueueType;
+	QueueHandle_t xQueueGenericCreateStatic( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, uint8_t *pucQueueStorage, StaticQueue_t *pxStaticQueue, const uint8_t ucQueueType )
+	{
+	Queue_t *pxNewQueue;
 
-	configASSERT( uxQueueLength > ( UBaseType_t ) 0 );
+		configASSERT( uxQueueLength > ( UBaseType_t ) 0 );
 
-	if( uxItemSize == ( UBaseType_t ) 0 )
-	{
-		/* There is not going to be a queue storage area. */
-		xQueueSizeInBytes = ( size_t ) 0;
-	}
-	else
-	{
-		/* The queue is one byte longer than asked for to make wrap checking
-		easier/faster. */
-		xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ) + ( size_t ) 1; /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
+		/* The StaticQueue_t structure and the queue storage area must be
+		supplied. */
+		configASSERT( pxStaticQueue != NULL );
+
+		/* A queue storage area should be provided if the item size is not 0, and
+		should not be provided if the item size is 0. */
+		configASSERT( !( ( pucQueueStorage != NULL ) && ( uxItemSize == 0 ) ) );
+		configASSERT( !( ( pucQueueStorage == NULL ) && ( uxItemSize != 0 ) ) );
+
+		#if( configASSERT_DEFINED == 1 )
+		{
+			/* Sanity check that the size of the structure used to declare a
+			variable of type StaticQueue_t or StaticSemaphore_t equals the size of
+			the real queue and semaphore structures. */
+			volatile size_t xSize = sizeof( StaticQueue_t );
+			configASSERT( xSize == sizeof( Queue_t ) );
+		}
+		#endif /* configASSERT_DEFINED */
+
+		/* The address of a statically allocated queue was passed in, use it.
+		The address of a statically allocated storage area was also passed in
+		but is already set. */
+		pxNewQueue = ( Queue_t * ) pxStaticQueue; /*lint !e740 Unusual cast is ok as the structures are designed to have the same alignment, and the size is checked by an assert. */
+
+		if( pxNewQueue != NULL )
+		{
+			#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+			{
+				/* Queues can be allocated wither statically or dynamically, so
+				note this queue was allocated statically in case the queue is
+				later deleted. */
+				pxNewQueue->ucStaticallyAllocated = pdTRUE;
+			}
+			#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
+
+			prvInitialiseNewQueue( uxQueueLength, uxItemSize, pucQueueStorage, ucQueueType, pxNewQueue );
+		}
+
+		return pxNewQueue;
 	}
 
-	/* Allocate the new queue structure and storage area. */
-	pcAllocatedBuffer = ( int8_t * ) pvPortMalloc( sizeof( Queue_t ) + xQueueSizeInBytes );
+#endif /* configSUPPORT_STATIC_ALLOCATION */
+/*-----------------------------------------------------------*/
+
+#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
 
-	if( pcAllocatedBuffer != NULL )
+	QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, const uint8_t ucQueueType )
 	{
-		pxNewQueue = ( Queue_t * ) pcAllocatedBuffer; /*lint !e826 MISRA The buffer cannot be to small because it was dimensioned by sizeof( Queue_t ) + xQueueSizeInBytes. */
+	Queue_t *pxNewQueue;
+	size_t xQueueSizeInBytes;
+	uint8_t *pucQueueStorage;
+
+		configASSERT( uxQueueLength > ( UBaseType_t ) 0 );
 
 		if( uxItemSize == ( UBaseType_t ) 0 )
 		{
-			/* No RAM was allocated for the queue storage area, but PC head
-			cannot be set to NULL because NULL is used as a key to say the queue
-			is used as a mutex.  Therefore just set pcHead to point to the queue
-			as a benign value that is known to be within the memory map. */
-			pxNewQueue->pcHead = ( int8_t * ) pxNewQueue;
+			/* There is not going to be a queue storage area. */
+			xQueueSizeInBytes = ( size_t ) 0;
 		}
 		else
 		{
-			/* Jump past the queue structure to find the location of the queue
-			storage area - adding the padding bytes to get a better alignment. */
-			pxNewQueue->pcHead = pcAllocatedBuffer + sizeof( Queue_t );
+			/* Allocate enough space to hold the maximum number of items that
+			can be in the queue at any time. */
+			xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
 		}
 
-		/* Initialise the queue members as described above where the queue type
-		is defined. */
-		pxNewQueue->uxLength = uxQueueLength;
-		pxNewQueue->uxItemSize = uxItemSize;
-		( void ) xQueueGenericReset( pxNewQueue, pdTRUE );
+		pxNewQueue = ( Queue_t * ) pvPortMalloc( sizeof( Queue_t ) + xQueueSizeInBytes );
 
-		#if ( configUSE_TRACE_FACILITY == 1 )
+		if( pxNewQueue != NULL )
 		{
-			pxNewQueue->ucQueueType = ucQueueType;
-		}
-		#endif /* configUSE_TRACE_FACILITY */
+			/* Jump past the queue structure to find the location of the queue
+			storage area. */
+			pucQueueStorage = ( ( uint8_t * ) pxNewQueue ) + sizeof( Queue_t );
 
-		#if( configUSE_QUEUE_SETS == 1 )
-		{
-			pxNewQueue->pxQueueSetContainer = NULL;
+			#if( configSUPPORT_STATIC_ALLOCATION == 1 )
+			{
+				/* Queues can be created either statically or dynamically, so
+				note this task was created dynamically in case it is later
+				deleted. */
+				pxNewQueue->ucStaticallyAllocated = pdFALSE;
+			}
+			#endif /* configSUPPORT_STATIC_ALLOCATION */
+
+			prvInitialiseNewQueue( uxQueueLength, uxItemSize, pucQueueStorage, ucQueueType, pxNewQueue );
 		}
-		#endif /* configUSE_QUEUE_SETS */
 
-		traceQUEUE_CREATE( pxNewQueue );
-		xReturn = pxNewQueue;
+		return pxNewQueue;
+	}
+
+#endif /* configSUPPORT_STATIC_ALLOCATION */
+/*-----------------------------------------------------------*/
+
+static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, uint8_t *pucQueueStorage, const uint8_t ucQueueType, Queue_t *pxNewQueue )
+{
+	/* Remove compiler warnings about unused parameters should
+	configUSE_TRACE_FACILITY not be set to 1. */
+	( void ) ucQueueType;
+
+	if( uxItemSize == ( UBaseType_t ) 0 )
+	{
+		/* No RAM was allocated for the queue storage area, but PC head cannot
+		be set to NULL because NULL is used as a key to say the queue is used as
+		a mutex.  Therefore just set pcHead to point to the queue as a benign
+		value that is known to be within the memory map. */
+		pxNewQueue->pcHead = ( int8_t * ) pxNewQueue;
 	}
 	else
 	{
-		mtCOVERAGE_TEST_MARKER();
+		/* Set the head to the start of the queue storage area. */
+		pxNewQueue->pcHead = ( int8_t * ) pucQueueStorage;
 	}
 
-	configASSERT( xReturn );
+	/* Initialise the queue members as described where the queue type is
+	defined. */
+	pxNewQueue->uxLength = uxQueueLength;
+	pxNewQueue->uxItemSize = uxItemSize;
+	( void ) xQueueGenericReset( pxNewQueue, pdTRUE );
 
-	return xReturn;
+	#if ( configUSE_TRACE_FACILITY == 1 )
+	{
+		pxNewQueue->ucQueueType = ucQueueType;
+	}
+	#endif /* configUSE_TRACE_FACILITY */
+
+	#if( configUSE_QUEUE_SETS == 1 )
+	{
+		pxNewQueue->pxQueueSetContainer = NULL;
+	}
+	#endif /* configUSE_QUEUE_SETS */
+
+	traceQUEUE_CREATE( pxNewQueue );
 }
 /*-----------------------------------------------------------*/
 
-#if ( configUSE_MUTEXES == 1 )
+#if( configUSE_MUTEXES == 1 )
 
-	QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType )
+	static void prvInitialiseMutex( Queue_t *pxNewQueue )
 	{
-	Queue_t *pxNewQueue;
-
-		/* Prevent compiler warnings about unused parameters if
-		configUSE_TRACE_FACILITY does not equal 1. */
-		( void ) ucQueueType;
-
-		/* Allocate the new queue structure. */
-		pxNewQueue = ( Queue_t * ) pvPortMalloc( sizeof( Queue_t ) );
 		if( pxNewQueue != NULL )
 		{
-			/* Information required for priority inheritance. */
+			/* The queue create function will set all the queue structure members
+			correctly for a generic queue, but this function is creating a
+			mutex.  Overwrite those members that need to be set differently -
+			in particular the information required for priority inheritance. */
 			pxNewQueue->pxMutexHolder = NULL;
 			pxNewQueue->uxQueueType = queueQUEUE_IS_MUTEX;
 
-			/* Queues used as a mutex no data is actually copied into or out
-			of the queue. */
-			pxNewQueue->pcWriteTo = NULL;
-			pxNewQueue->u.pcReadFrom = NULL;
-
-			/* Each mutex has a length of 1 (like a binary semaphore) and
-			an item size of 0 as nothing is actually copied into or out
-			of the mutex. */
-			pxNewQueue->uxMessagesWaiting = ( UBaseType_t ) 0U;
-			pxNewQueue->uxLength = ( UBaseType_t ) 1U;
-			pxNewQueue->uxItemSize = ( UBaseType_t ) 0U;
-
-			#if ( configUSE_TRACE_FACILITY == 1 )
-			{
-				pxNewQueue->ucQueueType = ucQueueType;
-			}
-			#endif
+			/* In case this is a recursive mutex. */
+			pxNewQueue->u.uxRecursiveCallCount = 0;
 
-			#if ( configUSE_QUEUE_SETS == 1 )
-			{
-				pxNewQueue->pxQueueSetContainer = NULL;
-			}
-			#endif
-
-			/* Ensure the event queues start with the correct state. */
-			vListInitialise( &( pxNewQueue->xTasksWaitingToSend ) );
-			vListInitialise( &( pxNewQueue->xTasksWaitingToReceive ) );
-
-			vPortCPUInitializeMutex(&pxNewQueue->mux);
+            vPortCPUInitializeMutex(&pxNewQueue->mux);
 
 			traceCREATE_MUTEX( pxNewQueue );
 
@@ -429,8 +481,41 @@ int8_t *pcAllocatedBuffer;
 		{
 			traceCREATE_MUTEX_FAILED();
 		}
+	}
+
+#endif /* configUSE_MUTEXES */
+/*-----------------------------------------------------------*/
+
+#if( ( configUSE_MUTEXES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
+
+	QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType )
+	{
+	Queue_t *pxNewQueue;
+	const UBaseType_t uxMutexLength = ( UBaseType_t ) 1, uxMutexSize = ( UBaseType_t ) 0;
+
+		pxNewQueue = ( Queue_t * ) xQueueGenericCreate( uxMutexLength, uxMutexSize, ucQueueType );
+		prvInitialiseMutex( pxNewQueue );
+
+		return pxNewQueue;
+	}
+
+#endif /* configUSE_MUTEXES */
+/*-----------------------------------------------------------*/
+
+#if( ( configUSE_MUTEXES == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
+
+	QueueHandle_t xQueueCreateMutexStatic( const uint8_t ucQueueType, StaticQueue_t *pxStaticQueue )
+	{
+	Queue_t *pxNewQueue;
+	const UBaseType_t uxMutexLength = ( UBaseType_t ) 1, uxMutexSize = ( UBaseType_t ) 0;
+
+		/* Prevent compiler warnings about unused parameters if
+		configUSE_TRACE_FACILITY does not equal 1. */
+		( void ) ucQueueType;
+
+		pxNewQueue = ( Queue_t * ) xQueueGenericCreateStatic( uxMutexLength, uxMutexSize, NULL, pxStaticQueue, ucQueueType );
+		prvInitialiseMutex( pxNewQueue );
 
-		configASSERT( pxNewQueue );
 		return pxNewQueue;
 	}
 
@@ -565,7 +650,35 @@ int8_t *pcAllocatedBuffer;
 #endif /* configUSE_RECURSIVE_MUTEXES */
 /*-----------------------------------------------------------*/
 
-#if ( configUSE_COUNTING_SEMAPHORES == 1 )
+#if( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
+
+	QueueHandle_t xQueueCreateCountingSemaphoreStatic( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount, StaticQueue_t *pxStaticQueue )
+	{
+	QueueHandle_t xHandle;
+
+		configASSERT( uxMaxCount != 0 );
+		configASSERT( uxInitialCount <= uxMaxCount );
+
+		xHandle = xQueueGenericCreateStatic( uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH, NULL, pxStaticQueue, queueQUEUE_TYPE_COUNTING_SEMAPHORE );
+
+		if( xHandle != NULL )
+		{
+			( ( Queue_t * ) xHandle )->uxMessagesWaiting = uxInitialCount;
+
+			traceCREATE_COUNTING_SEMAPHORE();
+		}
+		else
+		{
+			traceCREATE_COUNTING_SEMAPHORE_FAILED();
+		}
+
+		return xHandle;
+	}
+
+#endif /* ( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) */
+/*-----------------------------------------------------------*/
+
+#if( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
 
 	QueueHandle_t xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount )
 	{
@@ -591,7 +704,7 @@ int8_t *pcAllocatedBuffer;
 		return xHandle;
 	}
 
-#endif /* configUSE_COUNTING_SEMAPHORES */
+#endif /* ( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) */
 /*-----------------------------------------------------------*/
 
 BaseType_t xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, const BaseType_t xCopyPosition )
@@ -1685,7 +1798,33 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
 		vQueueUnregisterQueue( pxQueue );
 	}
 	#endif
-	vPortFree( pxQueue );
+
+	#if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) )
+	{
+		/* The queue can only have been allocated dynamically - free it
+		again. */
+		vPortFree( pxQueue );
+	}
+	#elif( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
+	{
+		/* The queue could have been allocated statically or dynamically, so
+		check before attempting to free the memory. */
+		if( pxQueue->ucStaticallyAllocated == ( uint8_t ) pdFALSE )
+		{
+			vPortFree( pxQueue );
+		}
+		else
+		{
+			mtCOVERAGE_TEST_MARKER();
+		}
+	}
+	#else
+	{
+		/* The queue must have been statically allocated, so is not going to be
+		deleted.  Avoid compiler warnings about the unused parameter. */
+		( void ) pxQueue;
+	}
+	#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
 }
 /*-----------------------------------------------------------*/
 
@@ -2263,7 +2402,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
 #endif /* configUSE_TIMERS */
 /*-----------------------------------------------------------*/
 
-#if ( configUSE_QUEUE_SETS == 1 )
+#if( ( configUSE_QUEUE_SETS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
 
 	QueueSetHandle_t xQueueCreateSet( const UBaseType_t uxEventQueueLength )
 	{

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 555 - 143
components/freertos/tasks.c


+ 66 - 38
components/freertos/xtensa_vectors.S

@@ -91,12 +91,13 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *******************************************************************************/
 
 #include "xtensa_rtos.h"
-
+#include "esp_panic.h"
+#include "sdkconfig.h"
 /*
   Define for workaround: pin no-cpu-affinity tasks to a cpu when fpu is used.
   Please change this when the tcb structure is changed
 */
-#define TASKTCB_XCOREID_OFFSET (0x3C+configMAX_TASK_NAME_LEN+3)&~3
+#define TASKTCB_XCOREID_OFFSET (0x38+configMAX_TASK_NAME_LEN+3)&~3
 .extern pxCurrentTCB
 
 /* Enable stack backtrace across exception/interrupt - see below */
@@ -302,12 +303,12 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
 
     .section .iram1,"ax"
-	.global panicHandler
+    .global panicHandler
 
     .global     _xt_panic
     .type       _xt_panic,@function
     .align      4
-	.literal_position
+    .literal_position
     .align      4
 
 _xt_panic:
@@ -339,45 +340,45 @@ _xt_panic:
     rsr     a0, EXCSAVE_1                   /* save interruptee's a0 */
     s32i    a0, sp, XT_STK_A0
 
-    /* Set up PS for C, reenable hi-pri interrupts, and clear EXCM. */
-    movi    a0, PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM | PS_WOE
+    /* Set up PS for C, disable all interrupts, and clear EXCM. */
+    movi    a0, PS_INTLEVEL(7) | PS_UM | PS_WOE
     wsr     a0, PS
 
-	//Call panic handler
-	mov		a2,sp
-	call4 panicHandler
+    //Call panic handler
+    mov     a6,sp
+    call4 panicHandler
 
 1:  j       1b                              /* loop infinitely */
 
-	retw
+    retw
 
 
-	.align 4
+    .align 4
 //Call using call0. Prints the hex char in a2. Kills a3, a4, a5
 panic_print_hex:
-	movi a3,0x60000000
-	movi a4,8
+    movi a3,0x60000000
+    movi a4,8
 panic_print_hex_loop:
-	l32i a5, a3, 0x1c
-	extui a5, a5, 16, 8
-	bgei a5,64,panic_print_hex_loop
-
-	srli a5,a2,28
-	bgei a5,10,panic_print_hex_a
-	addi a5,a5,'0'
-	j panic_print_hex_ok
+    l32i a5, a3, 0x1c
+    extui a5, a5, 16, 8
+    bgei a5,64,panic_print_hex_loop
+
+    srli a5,a2,28
+    bgei a5,10,panic_print_hex_a
+    addi a5,a5,'0'
+    j panic_print_hex_ok
 panic_print_hex_a:
-	addi a5,a5,'A'-10
+    addi a5,a5,'A'-10
 panic_print_hex_ok:
-	s32i a5,a3,0
-	slli a2,a2,4
-	
-	addi a4,a4,-1
-	bnei a4,0,panic_print_hex_loop
-	movi a5,' '
-	s32i a5,a3,0
+    s32i a5,a3,0
+    slli a2,a2,4
+    
+    addi a4,a4,-1
+    bnei a4,0,panic_print_hex_loop
+    movi a5,' '
+    s32i a5,a3,0
 
-	ret
+    ret
 
 
 
@@ -462,6 +463,8 @@ _DebugExceptionVector:
     jx      a3
     #else
     wsr     a0, EXCSAVE+XCHAL_DEBUGLEVEL    /* save original a0 somewhere */
+    movi    a0,PANIC_RSN_DEBUGEXCEPTION
+    wsr     a0,EXCCAUSE
     call0   _xt_panic                       /* does not return */
     rfi     XCHAL_DEBUGLEVEL                /* make a0 point here not later */
     #endif
@@ -489,6 +492,8 @@ _DoubleExceptionVector:
     #if XCHAL_HAVE_DEBUG
     break   1, 4                            /* unhandled double exception */
     #endif
+    movi    a0,PANIC_RSN_DOUBLEEXCEPTION
+    wsr     a0,EXCCAUSE
     call0   _xt_panic                       /* does not return */
     rfde                                    /* make a0 point here not later */
 
@@ -522,6 +527,8 @@ _xt_kernel_exc:
     #if XCHAL_HAVE_DEBUG
     break   1, 0                            /* unhandled kernel exception */
     #endif
+    movi    a0,PANIC_RSN_KERNELEXCEPTION
+    wsr     a0,EXCCAUSE
     call0   _xt_panic                       /* does not return */
     rfe                                     /* make a0 point here not there */
 
@@ -904,19 +911,16 @@ _xt_coproc_exc:
        core we're running on now. */
     movi    a2, pxCurrentTCB
     getcoreid a3
-    slli    a3,  a3, 2
-    add     a2,  a2, a3
+    addx4     a2,  a3, a2
     l32i    a2, a2, 0                       /* a2 = start of pxCurrentTCB[cpuid] */
     addi    a2, a2, TASKTCB_XCOREID_OFFSET  /* offset to xCoreID in tcb struct */
-    getcoreid a3
     s32i    a3, a2, 0                       /* store current cpuid */
 
-	/* Grab correct xt_coproc_owner_sa for this core */
-	getcoreid a2
-	movi    a3, XCHAL_CP_MAX << 2
-	mull    a2, a2, a3
+    /* Grab correct xt_coproc_owner_sa for this core */
+    movi    a2, XCHAL_CP_MAX << 2
+    mull    a2, a2, a3
     movi    a3, _xt_coproc_owner_sa         /* a3 = base of owner array */
-	add     a3, a3, a2
+    add     a3, a3, a2
 
     extui   a2, a0, 0, 16                   /* coprocessor bitmask portion */
     or      a4, a4, a2                      /* a4 = CPENABLE | (1 << n) */
@@ -1027,6 +1031,8 @@ _xt_coproc_exc:
     #if XCHAL_HAVE_DEBUG
     break   1, 1                            /* unhandled user exception */
     #endif
+    movi    a0,PANIC_RSN_COPROCEXCEPTION
+    wsr     a0,EXCCAUSE
     call0   _xt_panic                       /* not in a thread (invalid) */
     /* never returns */
 
@@ -1610,6 +1616,28 @@ _xt_highint4:
     ADD HIGH PRIORITY LEVEL 4 INTERRUPT HANDLER CODE HERE.
     */
 
+
+
+    /* On the ESP32, this level is used for the INT_WDT handler. If that triggers, the program is stuck with interrupts
+       off and the CPU should panic. */
+    rsr     a0, EXCSAVE_4
+    wsr     a0, EXCSAVE_1 /* panic handler reads this register */
+    /* Set EXCCAUSE to reflect cause of the wdt int trigger */
+    movi    a0,PANIC_RSN_INTWDT_CPU0
+    wsr     a0,EXCCAUSE
+#if CONFIG_INT_WDT_CHECK_CPU1
+    /* Check if the cause is the app cpu failing to tick.*/
+    movi    a0, int_wdt_app_cpu_ticked
+    l32i    a0, a0, 0
+    bnez    a0, 1f
+    /* It is. Modify cause. */
+    movi    a0,PANIC_RSN_INTWDT_CPU1
+    wsr     a0,EXCCAUSE
+1:
+#endif
+    call0 _xt_panic
+
+
     .align  4
 .L_xt_highint4_exit:
     rsr     a0, EXCSAVE_4                   /* restore a0 */

+ 0 - 1915
components/freertos/xtensa_vectors.S-new

@@ -1,1915 +0,0 @@
-/*******************************************************************************
-Copyright (c) 2006-2015 Cadence Design Systems Inc.
-
-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.
---------------------------------------------------------------------------------
-
-        XTENSA VECTORS AND LOW LEVEL HANDLERS FOR AN RTOS
-
-  Xtensa low level exception and interrupt vectors and handlers for an RTOS.
-
-  Interrupt handlers and user exception handlers support interaction with
-  the RTOS by calling XT_RTOS_INT_ENTER and XT_RTOS_INT_EXIT before and
-  after user's specific interrupt handlers. These macros are defined in
-  xtensa_<rtos>.h to call suitable functions in a specific RTOS.
-
-  Users can install application-specific interrupt handlers for low and
-  medium level interrupts, by calling xt_set_interrupt_handler(). These
-  handlers can be written in C, and must obey C calling convention. The
-  handler table is indexed by the interrupt number. Each handler may be
-  provided with an argument. 
-
-  Note that the system timer interrupt is handled specially, and is
-  dispatched to the RTOS-specific handler. This timer cannot be hooked
-  by application code.
-
-  Optional hooks are also provided to install a handler per level at 
-  run-time, made available by compiling this source file with 
-  '-DXT_INTEXC_HOOKS' (useful for automated testing).
-
-!!  This file is a template that usually needs to be modified to handle       !!
-!!  application specific interrupts. Search USER_EDIT for helpful comments    !!
-!!  on where to insert handlers and how to write them.                        !!
-
-  Users can also install application-specific exception handlers in the
-  same way, by calling xt_set_exception_handler(). One handler slot is
-  provided for each exception type. Note that some exceptions are handled
-  by the porting layer itself, and cannot be taken over by application
-  code in this manner. These are the alloca, syscall, and coprocessor
-  exceptions.
-
-  The exception handlers can be written in C, and must follow C calling
-  convention. Each handler is passed a pointer to an exception frame as
-  its single argument. The exception frame is created on the stack, and
-  holds the saved context of the thread that took the exception. If the
-  handler returns, the context will be restored and the instruction that
-  caused the exception will be retried. If the handler makes any changes
-  to the saved state in the exception frame, the changes will be applied
-  when restoring the context.
-
-  Because Xtensa is a configurable architecture, this port supports all user
-  generated configurations (except restrictions stated in the release notes).
-  This is accomplished by conditional compilation using macros and functions
-  defined in the Xtensa HAL (hardware adaptation layer) for your configuration.
-  Only the relevant parts of this file will be included in your RTOS build.
-  For example, this file provides interrupt vector templates for all types and
-  all priority levels, but only the ones in your configuration are built.
-
-  NOTES on the use of 'call0' for long jumps instead of 'j':
-   1. This file should be assembled with the -mlongcalls option to xt-xcc.
-   2. The -mlongcalls compiler option causes 'call0 dest' to be expanded to
-      a sequence 'l32r a0, dest' 'callx0 a0' which works regardless of the
-      distance from the call to the destination. The linker then relaxes
-      it back to 'call0 dest' if it determines that dest is within range.
-      This allows more flexibility in locating code without the performance
-      overhead of the 'l32r' literal data load in cases where the destination
-      is in range of 'call0'. There is an additional benefit in that 'call0'
-      has a longer range than 'j' due to the target being word-aligned, so 
-      the 'l32r' sequence is less likely needed.
-   3. The use of 'call0' with -mlongcalls requires that register a0 not be 
-      live at the time of the call, which is always the case for a function 
-      call but needs to be ensured if 'call0' is used as a jump in lieu of 'j'.
-   4. This use of 'call0' is independent of the C function call ABI.
-
-*******************************************************************************/
-
-#include "xtensa_rtos.h"
-
-
-/* Enable stack backtrace across exception/interrupt - see below */
-#define XT_DEBUG_BACKTRACE    1
-
-
-/*
---------------------------------------------------------------------------------
-  Defines used to access _xtos_interrupt_table.
---------------------------------------------------------------------------------
-*/
-#define XIE_HANDLER     0
-#define XIE_ARG         4
-#define XIE_SIZE        8
-
-/*
---------------------------------------------------------------------------------
-  Macro extract_msb - return the input with only the highest bit set.
-
-  Input  : "ain"  - Input value, clobbered.
-  Output : "aout" - Output value, has only one bit set, MSB of "ain".
-  The two arguments must be different AR registers.
---------------------------------------------------------------------------------
-*/
-
-    .macro  extract_msb     aout ain
-1:
-    addi    \aout, \ain, -1         /* aout = ain - 1        */
-    and     \ain, \ain, \aout       /* ain  = ain & aout     */
-    bnez    \ain, 1b                /* repeat until ain == 0 */
-    addi    \aout, \aout, 1         /* return aout + 1       */
-    .endm
-
-/*
---------------------------------------------------------------------------------
-  Macro dispatch_c_isr - dispatch interrupts to user ISRs.
-  This will dispatch to user handlers (if any) that are registered in the
-  XTOS dispatch table (_xtos_interrupt_table). These handlers would have
-  been registered by calling _xtos_set_interrupt_handler(). There is one
-  exception - the timer interrupt used by the OS will not be dispatched
-  to a user handler - this must be handled by the caller of this macro.
-
-  Level triggered and software interrupts are automatically deasserted by
-  this code.
-
-  ASSUMPTIONS:
-    -- PS.INTLEVEL is set to "level" at entry
-    -- PS.EXCM = 0, C calling enabled
-
-  NOTE: For CALL0 ABI, a12-a15 have not yet been saved.
-
-  NOTE: This macro will use registers a0 and a2-a6. The arguments are:
-    level -- interrupt level
-    mask  -- interrupt bitmask for this level
---------------------------------------------------------------------------------
-*/
-
-    .macro  dispatch_c_isr    level  mask
-
-    /* Get mask of pending, enabled interrupts at this level into a2. */
-
-.L_xt_user_int_&level&:
-    rsr     a2, INTENABLE
-    rsr     a3, INTERRUPT
-    movi    a4, \mask
-    and     a2, a2, a3
-    and     a2, a2, a4
-    beqz    a2, 9f                          /* nothing to do */
-
-    /* This bit of code provides a nice debug backtrace in the debugger.
-       It does take a few more instructions, so undef XT_DEBUG_BACKTRACE
-       if you want to save the cycles.
-    */
-    #if XT_DEBUG_BACKTRACE
-    #ifndef __XTENSA_CALL0_ABI__
-    rsr     a0, EPC_1 + \level - 1          /* return address */
-    movi    a4, 0xC0000000                  /* constant with top 2 bits set (call size) */
-    or      a0, a0, a4                      /* set top 2 bits */
-    addx2   a0, a4, a0                      /* clear top bit -- simulating call4 size   */
-    #endif
-    #endif
-
-    #ifdef XT_INTEXC_HOOKS
-    /* Call interrupt hook if present to (pre)handle interrupts. */
-    movi    a4, _xt_intexc_hooks
-    l32i    a4, a4, \level << 2
-    beqz    a4, 2f
-    #ifdef __XTENSA_CALL0_ABI__
-    callx0  a4
-    beqz    a2, 9f
-    #else
-    mov     a6, a2
-    callx4  a4
-    beqz    a6, 9f
-    mov     a2, a6
-    #endif
-2:
-    #endif
-
-    /* Now look up in the dispatch table and call user ISR if any. */
-    /* If multiple bits are set then MSB has highest priority.     */
-
-    extract_msb  a4, a2                     /* a4 = MSB of a2, a2 trashed */
-
-    #ifdef XT_USE_SWPRI
-    /* Enable all interrupts at this level that are numerically higher
-       than the one we just selected, since they are treated as higher
-       priority.
-    */
-    movi    a3, \mask                       /* a3 = all interrupts at this level */
-    add     a2, a4, a4                      /* a2 = a4 << 1 */
-    addi    a2, a2, -1                      /* a2 = mask of 1's <= a4 bit */
-    and     a2, a2, a3                      /* a2 = mask of all bits <= a4 at this level */
-    movi    a3, _xt_intdata
-    l32i    a6, a3, 4                       /* a6 = _xt_vpri_mask */
-    neg     a2, a2
-    addi    a2, a2, -1                      /* a2 = mask to apply */
-    and     a5, a6, a2                      /* mask off all bits <= a4 bit */
-    s32i    a5, a3, 4                       /* update _xt_vpri_mask */
-    rsr     a3, INTENABLE
-    and     a3, a3, a2                      /* mask off all bits <= a4 bit */
-    wsr     a3, INTENABLE
-    rsil    a3, \level - 1                  /* lower interrupt level by 1 */
-    #endif
-
-    movi    a3, XT_TIMER_INTEN              /* a3 = timer interrupt bit */
-    wsr     a4, INTCLEAR                    /* clear sw or edge-triggered interrupt */
-    beq     a3, a4, 7f                      /* if timer interrupt then skip table */
-
-    find_ms_setbit a3, a4, a3, 0            /* a3 = interrupt number */
-
-    movi    a4, _xt_interrupt_table
-    addx8   a3, a3, a4                      /* a3 = address of interrupt table entry */
-    l32i    a4, a3, XIE_HANDLER             /* a4 = handler address */
-    #ifdef __XTENSA_CALL0_ABI__
-    mov     a12, a6                         /* save in callee-saved reg */
-    l32i    a2, a3, XIE_ARG                 /* a2 = handler arg */
-    callx0  a4                              /* call handler */
-    mov     a2, a12
-    #else
-    mov     a2, a6                          /* save in windowed reg */
-    l32i    a6, a3, XIE_ARG                 /* a6 = handler arg */
-    callx4  a4                              /* call handler */
-    #endif
-
-    #ifdef XT_USE_SWPRI
-    j       8f
-    #else
-    j       .L_xt_user_int_&level&          /* check for more interrupts */
-    #endif
-
-7:
-
-    .ifeq XT_TIMER_INTPRI - \level
-.L_xt_user_int_timer_&level&:
-    /*
-    Interrupt handler for the RTOS tick timer if at this level.
-    We'll be reading the interrupt state again after this call
-    so no need to preserve any registers except a6 (vpri_mask).
-    */
-
-    #ifdef __XTENSA_CALL0_ABI__
-    mov     a12, a6
-    call0   XT_RTOS_TIMER_INT
-    mov     a2, a12
-    #else
-    mov     a2, a6
-    call4   XT_RTOS_TIMER_INT
-    #endif
-    .endif
-
-    #ifdef XT_USE_SWPRI
-    j       8f
-    #else
-    j       .L_xt_user_int_&level&          /* check for more interrupts */
-    #endif
-
-    #ifdef XT_USE_SWPRI
-8:
-    /* Restore old value of _xt_vpri_mask from a2. Also update INTENABLE from
-       virtual _xt_intenable which _could_ have changed during interrupt
-       processing. */
-
-    movi    a3, _xt_intdata
-    l32i    a4, a3, 0                       /* a4 = _xt_intenable    */
-    s32i    a2, a3, 4                       /* update _xt_vpri_mask  */
-    and     a4, a4, a2                      /* a4 = masked intenable */
-    wsr     a4, INTENABLE                   /* update INTENABLE      */
-    #endif
-
-9:
-    /* done */
-
-    .endm
-
-
-/*
---------------------------------------------------------------------------------
-  Panic handler.
-  Should be reached by call0 (preferable) or jump only. If call0, a0 says where 
-  from. If on simulator, display panic message and abort, else loop indefinitely.
---------------------------------------------------------------------------------
-*/
-
-    .text
-    .global     _xt_panic
-    .type       _xt_panic,@function
-    .align      4
-
-_xt_panic:
-    #ifdef XT_SIMULATOR
-    addi    a4, a0, -3                      /* point to call0 */
-    movi    a3, _xt_panic_message
-    movi    a2, SYS_log_msg
-    simcall
-    movi    a2, SYS_gdb_abort
-    simcall
-    #else
-    rsil    a2, XCHAL_EXCM_LEVEL            /* disable all low & med ints */
-1:  j       1b                              /* loop infinitely */
-    #endif
-
-    .section    .rodata, "a"
-    .align      4
-
-_xt_panic_message:
-    .string "\n*** _xt_panic() was called from 0x%08x or jumped to. ***\n"
-
-
-/*
---------------------------------------------------------------------------------
-    Hooks to dynamically install handlers for exceptions and interrupts.
-    Allows automated regression frameworks to install handlers per test.
-    Consists of an array of function pointers indexed by interrupt level, 
-    with index 0 containing the entry for user exceptions.
-    Initialized with all 0s, meaning no handler is installed at each level.
-    See comment in xtensa_rtos.h for more details.
---------------------------------------------------------------------------------
-*/
-
-    #ifdef XT_INTEXC_HOOKS
-    .data
-    .global     _xt_intexc_hooks
-    .type       _xt_intexc_hooks,@object
-    .align      4
-
-_xt_intexc_hooks:
-    .fill       XT_INTEXC_HOOK_NUM, 4, 0
-    #endif
-
-
-/*
---------------------------------------------------------------------------------
-  EXCEPTION AND LEVEL 1 INTERRUPT VECTORS AND LOW LEVEL HANDLERS
-  (except window exception vectors).
-
-  Each vector goes at a predetermined location according to the Xtensa
-  hardware configuration, which is ensured by its placement in a special
-  section known to the Xtensa linker support package (LSP). It performs
-  the minimum necessary before jumping to the handler in the .text section.
-
-  The corresponding handler goes in the normal .text section. It sets up
-  the appropriate stack frame, saves a few vector-specific registers and
-  calls XT_RTOS_INT_ENTER to save the rest of the interrupted context
-  and enter the RTOS, then sets up a C environment. It then calls the
-  user's interrupt handler code (which may be coded in C) and finally 
-  calls XT_RTOS_INT_EXIT to transfer control to the RTOS for scheduling.
-
-  While XT_RTOS_INT_EXIT does not return directly to the interruptee,
-  eventually the RTOS scheduler will want to dispatch the interrupted
-  task or handler. The scheduler will return to the exit point that was
-  saved in the interrupt stack frame at XT_STK_EXIT.
---------------------------------------------------------------------------------
-*/
-
-
-/*
---------------------------------------------------------------------------------
-Debug Exception.
---------------------------------------------------------------------------------
-*/
-
-#if XCHAL_HAVE_DEBUG
-
-    .begin      literal_prefix .DebugExceptionVector
-    .section    .DebugExceptionVector.text, "ax"
-    .global     _DebugExceptionVector
-    .align      4
-
-_DebugExceptionVector:
-
-    #ifdef XT_SIMULATOR
-    /*
-    In the simulator, let the debugger (if any) handle the debug exception,
-    or simply stop the simulation:
-    */
-    wsr     a2, EXCSAVE+XCHAL_DEBUGLEVEL    /* save a2 where sim expects it */
-    movi    a2, SYS_gdb_enter_sktloop
-    simcall                                 /* have ISS handle debug exc. */
-    #elif 0 /* change condition to 1 to use the HAL minimal debug handler */
-    wsr     a3, EXCSAVE+XCHAL_DEBUGLEVEL
-    movi    a3, xthal_debugexc_defhndlr_nw  /* use default debug handler */
-    jx      a3
-    #else
-    wsr     a0, EXCSAVE+XCHAL_DEBUGLEVEL    /* save original a0 somewhere */
-    call0   _xt_panic                       /* does not return */
-    rfi     XCHAL_DEBUGLEVEL                /* make a0 point here not later */
-    #endif
-
-    .end        literal_prefix
-
-#endif
-
-/*
---------------------------------------------------------------------------------
-Double Exception.
-Double exceptions are not a normal occurrence. They indicate a bug of some kind.
---------------------------------------------------------------------------------
-*/
-
-#ifdef XCHAL_DOUBLEEXC_VECTOR_VADDR
-
-    .begin      literal_prefix .DoubleExceptionVector
-    .section    .DoubleExceptionVector.text, "ax"
-    .global     _DoubleExceptionVector
-    .align      4
-
-_DoubleExceptionVector:
-
-    #if XCHAL_HAVE_DEBUG
-    break   1, 4                            /* unhandled double exception */
-    #endif
-    call0   _xt_panic                       /* does not return */
-    rfde                                    /* make a0 point here not later */
-
-    .end        literal_prefix
-
-#endif /* XCHAL_DOUBLEEXC_VECTOR_VADDR */
-
-/*
---------------------------------------------------------------------------------
-Kernel Exception (including Level 1 Interrupt from kernel mode).
---------------------------------------------------------------------------------
-*/
-
-    .begin      literal_prefix .KernelExceptionVector
-    .section    .KernelExceptionVector.text, "ax"
-    .global     _KernelExceptionVector
-    .align      4
-
-_KernelExceptionVector:
-
-    wsr     a0, EXCSAVE_1                   /* preserve a0 */
-    call0   _xt_kernel_exc                  /* kernel exception handler */
-    /* never returns here - call0 is used as a jump (see note at top) */
-
-    .end        literal_prefix
-
-    .text
-    .align      4
-
-_xt_kernel_exc:
-    #if XCHAL_HAVE_DEBUG
-    break   1, 0                            /* unhandled kernel exception */
-    #endif
-    call0   _xt_panic                       /* does not return */
-    rfe                                     /* make a0 point here not there */
-
-
-/*
---------------------------------------------------------------------------------
-User Exception (including Level 1 Interrupt from user mode).
---------------------------------------------------------------------------------
-*/
-
-    .begin      literal_prefix .UserExceptionVector
-    .section    .UserExceptionVector.text, "ax"
-    .global     _UserExceptionVector
-    .type       _UserExceptionVector,@function
-    .align      4
-
-_UserExceptionVector:
-
-    wsr     a0, EXCSAVE_1                   /* preserve a0 */
-    call0   _xt_user_exc                    /* user exception handler */
-    /* never returns here - call0 is used as a jump (see note at top) */
-
-    .end        literal_prefix
-
-/*
---------------------------------------------------------------------------------
-  Insert some waypoints for jumping beyond the signed 8-bit range of
-  conditional branch instructions, so the conditional branchces to specific
-  exception handlers are not taken in the mainline. Saves some cycles in the
-  mainline.
---------------------------------------------------------------------------------
-*/
-
-    .text
-
-    #if XCHAL_HAVE_WINDOWED
-    .align      4
-_xt_to_alloca_exc:
-    call0   _xt_alloca_exc                  /* in window vectors section */
-    /* never returns here - call0 is used as a jump (see note at top) */
-    #endif
-
-    .align      4
-_xt_to_syscall_exc:
-    call0   _xt_syscall_exc
-    /* never returns here - call0 is used as a jump (see note at top) */
-
-    #if XCHAL_CP_NUM > 0
-    .align      4
-_xt_to_coproc_exc:
-    call0   _xt_coproc_exc
-    /* never returns here - call0 is used as a jump (see note at top) */
-    #endif
-
-
-/*
---------------------------------------------------------------------------------
-  User exception handler.
---------------------------------------------------------------------------------
-*/
-
-    .type       _xt_user_exc,@function
-    .align      4
-
-_xt_user_exc:
-
-    /* If level 1 interrupt then jump to the dispatcher */
-    rsr     a0, EXCCAUSE
-    beqi    a0, EXCCAUSE_LEVEL1INTERRUPT, _xt_lowint1
-
-    /* Handle any coprocessor exceptions. Rely on the fact that exception
-       numbers above EXCCAUSE_CP0_DISABLED all relate to the coprocessors.
-    */
-    #if XCHAL_CP_NUM > 0
-    bgeui   a0, EXCCAUSE_CP0_DISABLED, _xt_to_coproc_exc
-    #endif
-
-    /* Handle alloca and syscall exceptions */
-    #if XCHAL_HAVE_WINDOWED
-    beqi    a0, EXCCAUSE_ALLOCA,  _xt_to_alloca_exc
-    #endif
-    beqi    a0, EXCCAUSE_SYSCALL, _xt_to_syscall_exc
-
-    /* Handle all other exceptions. All can have user-defined handlers. */
-    /* NOTE: we'll stay on the user stack for exception handling.       */
-
-    /* Allocate exception frame and save minimal context. */
-    mov     a0, sp
-    addi    sp, sp, -XT_STK_FRMSZ
-    s32i    a0, sp, XT_STK_A1
-    #if XCHAL_HAVE_WINDOWED
-    s32e    a0, sp, -12                     /* for debug backtrace */
-    #endif
-    rsr     a0, PS                          /* save interruptee's PS */
-    s32i    a0, sp, XT_STK_PS
-    rsr     a0, EPC_1                       /* save interruptee's PC */
-    s32i    a0, sp, XT_STK_PC
-    rsr     a0, EXCSAVE_1                   /* save interruptee's a0 */
-    s32i    a0, sp, XT_STK_A0
-    #if XCHAL_HAVE_WINDOWED
-    s32e    a0, sp, -16                     /* for debug backtrace */
-    #endif
-    s32i    a12, sp, XT_STK_A12             /* _xt_context_save requires A12- */
-    s32i    a13, sp, XT_STK_A13             /* A13 to have already been saved */
-    call0   _xt_context_save
-
-    /* Save exc cause and vaddr into exception frame */
-    rsr     a0, EXCCAUSE
-    s32i    a0, sp, XT_STK_EXCCAUSE
-    rsr     a0, EXCVADDR
-    s32i    a0, sp, XT_STK_EXCVADDR
-
-    /* Set up PS for C, reenable hi-pri interrupts, and clear EXCM. */
-    #ifdef __XTENSA_CALL0_ABI__
-    movi    a0, PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM
-    #else
-    movi    a0, PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM | PS_WOE
-    #endif
-    wsr     a0, PS
-
-    #ifdef XT_DEBUG_BACKTRACE
-    #ifndef __XTENSA_CALL0_ABI__
-    rsr     a0, EPC_1                       /* return address for debug backtrace */
-    movi    a5, 0xC0000000                  /* constant with top 2 bits set (call size) */
-    rsync                                   /* wait for WSR.PS to complete */
-    or      a0, a0, a5                      /* set top 2 bits */
-    addx2   a0, a5, a0                      /* clear top bit -- thus simulating call4 size */
-    #else
-    rsync                                   /* wait for WSR.PS to complete */
-    #endif
-    #endif
-
-    rsr     a2, EXCCAUSE                    /* recover exc cause */
-
-    #ifdef XT_INTEXC_HOOKS
-    /*
-    Call exception hook to pre-handle exceptions (if installed).
-    Pass EXCCAUSE in a2, and check result in a2 (if -1, skip default handling).
-    */
-    movi    a4, _xt_intexc_hooks
-    l32i    a4, a4, 0                       /* user exception hook index 0 */
-    beqz    a4, 1f
-.Ln_xt_user_exc_call_hook:
-    #ifdef __XTENSA_CALL0_ABI__
-    callx0  a4
-    beqi    a2, -1, .L_xt_user_done
-    #else
-    mov     a6, a2
-    callx4  a4
-    beqi    a6, -1, .L_xt_user_done
-    mov     a2, a6
-    #endif
-1:
-    #endif
-
-    rsr     a2, EXCCAUSE                    /* recover exc cause */
-    movi    a3, _xt_exception_table
-    addx4   a4, a2, a3                      /* a4 = address of exception table entry */
-    l32i    a4, a4, 0                       /* a4 = handler address */
-    #ifdef __XTENSA_CALL0_ABI__
-    mov     a2, sp                          /* a2 = pointer to exc frame */
-    callx0  a4                              /* call handler */
-    #else
-    mov     a6, sp                          /* a6 = pointer to exc frame */
-    callx4  a4                              /* call handler */
-    #endif
-
-.L_xt_user_done:
-
-    /* Restore context and return */
-    call0   _xt_context_restore
-    l32i    a0, sp, XT_STK_PS               /* retrieve interruptee's PS */
-    wsr     a0, PS
-    l32i    a0, sp, XT_STK_PC               /* retrieve interruptee's PC */
-    wsr     a0, EPC_1
-    l32i    a0, sp, XT_STK_A0               /* retrieve interruptee's A0 */
-    l32i    sp, sp, XT_STK_A1               /* remove exception frame */
-    rsync                                   /* ensure PS and EPC written */
-    rfe                                     /* PS.EXCM is cleared */
-
-
-/*
---------------------------------------------------------------------------------
-  Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT
-  on entry and used to return to a thread or interrupted interrupt handler.
---------------------------------------------------------------------------------
-*/
-
-    .global     _xt_user_exit
-    .type       _xt_user_exit,@function
-    .align      4
-_xt_user_exit:
-    l32i    a0, sp, XT_STK_PS               /* retrieve interruptee's PS */
-    wsr     a0, PS
-    l32i    a0, sp, XT_STK_PC               /* retrieve interruptee's PC */
-    wsr     a0, EPC_1
-    l32i    a0, sp, XT_STK_A0               /* retrieve interruptee's A0 */
-    l32i    sp, sp, XT_STK_A1               /* remove interrupt stack frame */
-    rsync                                   /* ensure PS and EPC written */
-    rfe                                     /* PS.EXCM is cleared */
-
-
-/*
---------------------------------------------------------------------------------
-Syscall Exception Handler (jumped to from User Exception Handler).
-Syscall 0 is required to spill the register windows (no-op in Call 0 ABI).
-Only syscall 0 is handled here. Other syscalls return -1 to caller in a2.
---------------------------------------------------------------------------------
-*/
-
-    .text
-    .type       _xt_syscall_exc,@function
-    .align      4
-_xt_syscall_exc:
-
-    #ifdef __XTENSA_CALL0_ABI__
-    /*
-    Save minimal regs for scratch. Syscall 0 does nothing in Call0 ABI.
-    Use a minimal stack frame (16B) to save A2 & A3 for scratch.
-    PS.EXCM could be cleared here, but unlikely to improve worst-case latency.
-    rsr     a0, PS
-    addi    a0, a0, -PS_EXCM_MASK
-    wsr     a0, PS
-    */
-    addi    sp, sp, -16
-    s32i    a2, sp, 8
-    s32i    a3, sp, 12
-    #else   /* Windowed ABI */
-    /*
-    Save necessary context and spill the register windows.
-    PS.EXCM is still set and must remain set until after the spill.
-    Reuse context save function though it saves more than necessary.
-    For this reason, a full interrupt stack frame is allocated.
-    */
-    addi    sp, sp, -XT_STK_FRMSZ           /* allocate interrupt stack frame */
-    s32i    a12, sp, XT_STK_A12             /* _xt_context_save requires A12- */
-    s32i    a13, sp, XT_STK_A13             /* A13 to have already been saved */
-    call0   _xt_context_save
-    #endif
-
-    /*
-    Grab the interruptee's PC and skip over the 'syscall' instruction.
-    If it's at the end of a zero-overhead loop and it's not on the last
-    iteration, decrement loop counter and skip to beginning of loop.
-    */
-    rsr     a2, EPC_1                       /* a2 = PC of 'syscall' */
-    addi    a3, a2, 3                       /* ++PC                 */
-    #if XCHAL_HAVE_LOOPS
-    rsr     a0, LEND                        /* if (PC == LEND       */
-    bne     a3, a0, 1f
-    rsr     a0, LCOUNT                      /*     && LCOUNT != 0)  */
-    beqz    a0, 1f                          /* {                    */
-    addi    a0, a0, -1                      /*   --LCOUNT           */
-    rsr     a3, LBEG                        /*   PC = LBEG          */
-    wsr     a0, LCOUNT                      /* }                    */
-    #endif
-1:  wsr     a3, EPC_1                       /* update PC            */
-
-    /* Restore interruptee's context and return from exception. */
-    #ifdef __XTENSA_CALL0_ABI__
-    l32i    a2, sp, 8
-    l32i    a3, sp, 12
-    addi    sp, sp, 16
-    #else
-    call0   _xt_context_restore
-    addi    sp, sp, XT_STK_FRMSZ
-    #endif
-    movi    a0, -1
-    movnez  a2, a0, a2                      /* return -1 if not syscall 0 */
-    rsr     a0, EXCSAVE_1
-    rfe
-
-/*
---------------------------------------------------------------------------------
-Co-Processor Exception Handler (jumped to from User Exception Handler).
-These exceptions are generated by co-processor instructions, which are only
-allowed in thread code (not in interrupts or kernel code). This restriction is 
-deliberately imposed to reduce the burden of state-save/restore in interrupts.
---------------------------------------------------------------------------------
-*/
-#if XCHAL_CP_NUM > 0
-
-    .section .rodata, "a"
-
-/* Offset to CP n save area in thread's CP save area. */
-    .global _xt_coproc_sa_offset
-    .type   _xt_coproc_sa_offset,@object
-    .align  16                      /* minimize crossing cache boundaries */
-_xt_coproc_sa_offset:
-    .word   XT_CP0_SA, XT_CP1_SA, XT_CP2_SA, XT_CP3_SA
-    .word   XT_CP4_SA, XT_CP5_SA, XT_CP6_SA, XT_CP7_SA
-
-/* Bitmask for CP n's CPENABLE bit. */
-    .type   _xt_coproc_mask,@object
-    .align  16,,8                   /* try to keep it all in one cache line */
-    .set    i, 0
-_xt_coproc_mask:
-    .rept   XCHAL_CP_MAX
-    .long   (i<<16) | (1<<i)    // upper 16-bits = i, lower = bitmask
-    .set    i, i+1
-    .endr
-
-    .data
-
-/* Owner thread of CP n, identified by thread's CP save area (0 = unowned). */
-    .global _xt_coproc_owner_sa
-    .type   _xt_coproc_owner_sa,@object
-    .align  16,,XCHAL_CP_MAX<<2     /* minimize crossing cache boundaries */
-_xt_coproc_owner_sa:
-    .space  XCHAL_CP_MAX << 2
-
-    .text
-
-
-    .align  4
-.L_goto_invalid:
-    j   .L_xt_coproc_invalid    /* not in a thread (invalid) */
-    .align  4
-.L_goto_done:
-    j   .L_xt_coproc_done
-
-
-/*
---------------------------------------------------------------------------------
-  Coprocessor exception handler.
-  At entry, only a0 has been saved (in EXCSAVE_1).
---------------------------------------------------------------------------------
-*/
-
-    .type   _xt_coproc_exc,@function
-    .align  4
-
-_xt_coproc_exc:
-
-    /* Allocate interrupt stack frame and save minimal context. */
-    mov     a0, sp                          /* sp == a1 */
-    addi    sp, sp, -XT_STK_FRMSZ           /* allocate interrupt stack frame */
-    s32i    a0, sp, XT_STK_A1               /* save pre-interrupt SP */
-    #if XCHAL_HAVE_WINDOWED
-    s32e    a0, sp, -12                     /* for debug backtrace */
-    #endif
-    rsr     a0, PS                          /* save interruptee's PS */
-    s32i    a0, sp, XT_STK_PS
-    rsr     a0, EPC_1                       /* save interruptee's PC */
-    s32i    a0, sp, XT_STK_PC
-    rsr     a0, EXCSAVE_1                   /* save interruptee's a0 */
-    s32i    a0, sp, XT_STK_A0
-    #if XCHAL_HAVE_WINDOWED
-    s32e    a0, sp, -16                     /* for debug backtrace */
-    #endif
-    movi    a0, _xt_user_exit               /* save exit point for dispatch */
-    s32i    a0, sp, XT_STK_EXIT
-
-    rsr     a0, EXCCAUSE
-    s32i    a5, sp, XT_STK_A5               /* save a5 */
-    addi    a5, a0, -EXCCAUSE_CP0_DISABLED  /* a5 = CP index */
-
-    /* Save a few more of interruptee's registers (a5 was already saved). */
-    s32i    a2,  sp, XT_STK_A2
-    s32i    a3,  sp, XT_STK_A3
-    s32i    a4,  sp, XT_STK_A4
-    s32i    a15, sp, XT_STK_A15
-
-    /* Get co-processor state save area of new owner thread. */
-    call0   XT_RTOS_CP_STATE                /* a15 = new owner's save area */
-    beqz    a15, .L_goto_invalid            /* not in a thread (invalid) */
-
-    /* Enable the co-processor's bit in CPENABLE. */
-    movi    a0, _xt_coproc_mask
-    rsr     a4, CPENABLE                    /* a4 = CPENABLE */
-    addx4   a0, a5, a0                      /* a0 = &_xt_coproc_mask[n] */
-    l32i    a0, a0, 0                       /* a0 = (n << 16) | (1 << n) */
-    movi    a3, _xt_coproc_owner_sa     /* (placed here for load slot) */
-    extui   a2, a0, 0, 16                   /* coprocessor bitmask portion */
-    or      a4, a4, a2                      /* a4 = CPENABLE | (1 << n) */
-    wsr     a4, CPENABLE
-
-    /* Get old coprocessor owner thread (save area ptr) and assign new one.  */
-    addx4   a3,  a5, a3                      /* a3 = &_xt_coproc_owner_sa[n] */
-    l32i    a2,  a3, 0                       /* a2 = old owner's save area */
-    s32i    a15, a3, 0                       /* _xt_coproc_owner_sa[n] = new */
-    rsync                                    /* ensure wsr.CPENABLE is complete */
-
-    /* Only need to context switch if new owner != old owner. */
-    beq     a15, a2, .L_goto_done           /* new owner == old, we're done */
-
-    /* If no old owner then nothing to save. */
-    beqz    a2, .L_check_new
-
-    /* If old owner not actively using CP then nothing to save. */
-    l16ui   a4,  a2,  XT_CPENABLE           /* a4 = old owner's CPENABLE */
-    bnone   a4,  a0,  .L_check_new          /* old owner not using CP    */
-
-.L_save_old:
-    /* Save old owner's coprocessor state. */
-
-    movi    a5, _xt_coproc_sa_offset
-
-    /* Mark old owner state as no longer active (CPENABLE bit n clear). */
-    xor     a4,  a4,  a0                    /* clear CP bit in CPENABLE    */
-    s16i    a4,  a2,  XT_CPENABLE           /* update old owner's CPENABLE */
-
-    extui   a4,  a0,  16,  5                /* a4 = CP index = n */
-    addx4   a5,  a4,  a5                    /* a5 = &_xt_coproc_sa_offset[n] */
-
-    /* Mark old owner state as saved (CPSTORED bit n set). */
-    l16ui   a4,  a2,  XT_CPSTORED           /* a4 = old owner's CPSTORED */
-    l32i    a5,  a5,  0                     /* a5 = XT_CP[n]_SA offset */
-    or      a4,  a4,  a0                    /* set CP in old owner's CPSTORED */
-    s16i    a4,  a2,  XT_CPSTORED           /* update old owner's CPSTORED */
-    l32i    a2, a2, XT_CP_ASA               /* ptr to actual (aligned) save area */
-    extui   a3, a0, 16, 5                   /* a3 = CP index = n */
-    add     a2, a2, a5                      /* a2 = old owner's area for CP n */
-
-    /*
-    The config-specific HAL macro invoked below destroys a2-5, preserves a0-1.
-    It is theoretically possible for Xtensa processor designers to write TIE 
-    that causes more address registers to be affected, but it is generally 
-    unlikely. If that ever happens, more registers needs to be saved/restored
-    around this macro invocation, and the value in a15 needs to be recomputed.
-    */
-    xchal_cpi_store_funcbody
-
-.L_check_new:
-    /* Check if any state has to be restored for new owner. */
-    /* NOTE: a15 = new owner's save area, cannot be zero when we get here. */
-
-    l16ui   a3,  a15, XT_CPSTORED           /* a3 = new owner's CPSTORED */
-    movi    a4, _xt_coproc_sa_offset
-    bnone   a3,  a0,  .L_check_cs           /* full CP not saved, check callee-saved */
-    xor     a3,  a3,  a0                    /* CPSTORED bit is set, clear it */
-    s16i    a3,  a15, XT_CPSTORED           /* update new owner's CPSTORED */
-
-    /* Adjust new owner's save area pointers to area for CP n. */
-    extui   a3,  a0, 16, 5                  /* a3 = CP index = n */
-    addx4   a4,  a3, a4                     /* a4 = &_xt_coproc_sa_offset[n] */
-    l32i    a4,  a4, 0                      /* a4 = XT_CP[n]_SA */
-    l32i    a5, a15, XT_CP_ASA              /* ptr to actual (aligned) save area */
-    add     a2,  a4, a5                     /* a2 = new owner's area for CP */
-
-    /*
-    The config-specific HAL macro invoked below destroys a2-5, preserves a0-1.
-    It is theoretically possible for Xtensa processor designers to write TIE 
-    that causes more address registers to be affected, but it is generally 
-    unlikely. If that ever happens, more registers needs to be saved/restored
-    around this macro invocation.
-    */
-    xchal_cpi_load_funcbody
-
-    /* Restore interruptee's saved registers. */
-    /* Can omit rsync for wsr.CPENABLE here because _xt_user_exit does it. */
-.L_xt_coproc_done:
-    l32i    a15, sp, XT_STK_A15
-    l32i    a5,  sp, XT_STK_A5
-    l32i    a4,  sp, XT_STK_A4
-    l32i    a3,  sp, XT_STK_A3
-    l32i    a2,  sp, XT_STK_A2
-    call0   _xt_user_exit                   /* return via exit dispatcher */
-    /* Never returns here - call0 is used as a jump (see note at top) */
-
-.L_check_cs:
-    /* a0 = CP mask in low bits, a15 = new owner's save area */
-    l16ui   a2, a15, XT_CP_CS_ST            /* a2 = mask of CPs saved    */
-    bnone   a2,  a0, .L_xt_coproc_done      /* if no match then done     */
-    and     a2,  a2, a0                     /* a2 = which CPs to restore */
-    extui   a2,  a2, 0, 8                   /* extract low 8 bits        */
-    s32i    a6,  sp, XT_STK_A6              /* save extra needed regs    */
-    s32i    a7,  sp, XT_STK_A7
-    s32i    a13, sp, XT_STK_A13
-    s32i    a14, sp, XT_STK_A14
-    call0   _xt_coproc_restorecs            /* restore CP registers      */
-    l32i    a6,  sp, XT_STK_A6              /* restore saved registers   */
-    l32i    a7,  sp, XT_STK_A7
-    l32i    a13, sp, XT_STK_A13
-    l32i    a14, sp, XT_STK_A14
-    j       .L_xt_coproc_done
-
-    /* Co-processor exception occurred outside a thread (not supported). */
-.L_xt_coproc_invalid:
-    #if XCHAL_HAVE_DEBUG
-    break   1, 1                            /* unhandled user exception */
-    #endif
-    call0   _xt_panic                       /* not in a thread (invalid) */
-    /* never returns */
-
-
-#endif /* XCHAL_CP_NUM */
-
-
-/*
--------------------------------------------------------------------------------
-  Level 1 interrupt dispatch. Assumes stack frame has not been allocated yet.
--------------------------------------------------------------------------------
-*/
-
-    .text   
-    .type       _xt_lowint1,@function
-    .align      4
-
-_xt_lowint1:
-    mov     a0, sp                          /* sp == a1 */
-    addi    sp, sp, -XT_STK_FRMSZ           /* allocate interrupt stack frame */
-    s32i    a0, sp, XT_STK_A1               /* save pre-interrupt SP */
-    rsr     a0, PS                          /* save interruptee's PS */
-    s32i    a0, sp, XT_STK_PS
-    rsr     a0, EPC_1                       /* save interruptee's PC */
-    s32i    a0, sp, XT_STK_PC
-    rsr     a0, EXCSAVE_1                   /* save interruptee's a0 */
-    s32i    a0, sp, XT_STK_A0
-    movi    a0, _xt_user_exit               /* save exit point for dispatch */
-    s32i    a0, sp, XT_STK_EXIT
-
-    /* Save rest of interrupt context and enter RTOS. */
-    call0   XT_RTOS_INT_ENTER               /* common RTOS interrupt entry */
-
-    /* !! We are now on the RTOS system stack !! */ 
-
-    /* Set up PS for C, enable interrupts above this level and clear EXCM. */
-    #ifdef __XTENSA_CALL0_ABI__
-    movi    a0, PS_INTLEVEL(1) | PS_UM
-    #else 
-    movi    a0, PS_INTLEVEL(1) | PS_UM | PS_WOE
-    #endif
-    wsr     a0, PS
-    rsync
-
-    /* OK to call C code at this point, dispatch user ISRs */
-
-    dispatch_c_isr 1 XCHAL_INTLEVEL1_MASK
-
-    /* Done handling interrupts, transfer control to OS */
-    call0   XT_RTOS_INT_EXIT                /* does not return directly here */
-
-
-/*
--------------------------------------------------------------------------------
-  MEDIUM PRIORITY (LEVEL 2+) INTERRUPT VECTORS AND LOW LEVEL HANDLERS.
-
-  Medium priority interrupts are by definition those with priority greater
-  than 1 and not greater than XCHAL_EXCM_LEVEL. These are disabled by
-  setting PS.EXCM and therefore can easily support a C environment for
-  handlers in C, and interact safely with an RTOS.
-
-  Each vector goes at a predetermined location according to the Xtensa
-  hardware configuration, which is ensured by its placement in a special
-  section known to the Xtensa linker support package (LSP). It performs
-  the minimum necessary before jumping to the handler in the .text section.
-
-  The corresponding handler goes in the normal .text section. It sets up
-  the appropriate stack frame, saves a few vector-specific registers and
-  calls XT_RTOS_INT_ENTER to save the rest of the interrupted context
-  and enter the RTOS, then sets up a C environment. It then calls the
-  user's interrupt handler code (which may be coded in C) and finally 
-  calls XT_RTOS_INT_EXIT to transfer control to the RTOS for scheduling.
-
-  While XT_RTOS_INT_EXIT does not return directly to the interruptee,
-  eventually the RTOS scheduler will want to dispatch the interrupted
-  task or handler. The scheduler will return to the exit point that was
-  saved in the interrupt stack frame at XT_STK_EXIT.
--------------------------------------------------------------------------------
-*/
-
-#if XCHAL_EXCM_LEVEL >= 2
-
-    .begin      literal_prefix .Level2InterruptVector
-    .section    .Level2InterruptVector.text, "ax"
-    .global     _Level2Vector
-    .type       _Level2Vector,@function
-    .align      4
-_Level2Vector:
-    wsr     a0, EXCSAVE_2                   /* preserve a0 */
-    call0   _xt_medint2                     /* load interrupt handler */
-    /* never returns here - call0 is used as a jump (see note at top) */
-
-    .end        literal_prefix
-
-    .text
-    .type       _xt_medint2,@function
-    .align      4
-_xt_medint2:
-    mov     a0, sp                          /* sp == a1 */
-    addi    sp, sp, -XT_STK_FRMSZ           /* allocate interrupt stack frame */
-    s32i    a0, sp, XT_STK_A1               /* save pre-interrupt SP */
-    rsr     a0, EPS_2                       /* save interruptee's PS */
-    s32i    a0, sp, XT_STK_PS
-    rsr     a0, EPC_2                       /* save interruptee's PC */
-    s32i    a0, sp, XT_STK_PC
-    rsr     a0, EXCSAVE_2                   /* save interruptee's a0 */
-    s32i    a0, sp, XT_STK_A0
-    movi    a0, _xt_medint2_exit            /* save exit point for dispatch */
-    s32i    a0, sp, XT_STK_EXIT
-
-    /* Save rest of interrupt context and enter RTOS. */
-    call0   XT_RTOS_INT_ENTER               /* common RTOS interrupt entry */
-
-    /* !! We are now on the RTOS system stack !! */
-
-    /* Set up PS for C, enable interrupts above this level and clear EXCM. */
-    #ifdef __XTENSA_CALL0_ABI__
-    movi    a0, PS_INTLEVEL(2) | PS_UM
-    #else
-    movi    a0, PS_INTLEVEL(2) | PS_UM | PS_WOE
-    #endif
-    wsr     a0, PS
-    rsync
-
-    /* OK to call C code at this point, dispatch user ISRs */
-
-    dispatch_c_isr 2 XCHAL_INTLEVEL2_MASK
-
-    /* Done handling interrupts, transfer control to OS */
-    call0   XT_RTOS_INT_EXIT                /* does not return directly here */
-
-    /*
-    Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT
-    on entry and used to return to a thread or interrupted interrupt handler.
-    */
-    .global     _xt_medint2_exit
-    .type       _xt_medint2_exit,@function
-    .align      4
-_xt_medint2_exit:
-    /* Restore only level-specific regs (the rest were already restored) */
-    l32i    a0, sp, XT_STK_PS               /* retrieve interruptee's PS */
-    wsr     a0, EPS_2
-    l32i    a0, sp, XT_STK_PC               /* retrieve interruptee's PC */
-    wsr     a0, EPC_2
-    l32i    a0, sp, XT_STK_A0               /* retrieve interruptee's A0 */
-    l32i    sp, sp, XT_STK_A1               /* remove interrupt stack frame */
-    rsync                                   /* ensure EPS and EPC written */
-    rfi     2
-
-#endif  /* Level 2 */
-
-#if XCHAL_EXCM_LEVEL >= 3
-
-    .begin      literal_prefix .Level3InterruptVector
-    .section    .Level3InterruptVector.text, "ax"
-    .global     _Level3Vector
-    .type       _Level3Vector,@function
-    .align      4
-_Level3Vector:
-    wsr     a0, EXCSAVE_3                   /* preserve a0 */
-    call0   _xt_medint3                     /* load interrupt handler */
-    /* never returns here - call0 is used as a jump (see note at top) */
-
-    .end        literal_prefix
-
-    .text
-    .type       _xt_medint3,@function
-    .align      4
-_xt_medint3:
-    mov     a0, sp                          /* sp == a1 */
-    addi    sp, sp, -XT_STK_FRMSZ           /* allocate interrupt stack frame */
-    s32i    a0, sp, XT_STK_A1               /* save pre-interrupt SP */
-    rsr     a0, EPS_3                       /* save interruptee's PS */
-    s32i    a0, sp, XT_STK_PS
-    rsr     a0, EPC_3                       /* save interruptee's PC */
-    s32i    a0, sp, XT_STK_PC
-    rsr     a0, EXCSAVE_3                   /* save interruptee's a0 */
-    s32i    a0, sp, XT_STK_A0
-    movi    a0, _xt_medint3_exit            /* save exit point for dispatch */
-    s32i    a0, sp, XT_STK_EXIT
-
-    /* Save rest of interrupt context and enter RTOS. */
-    call0   XT_RTOS_INT_ENTER               /* common RTOS interrupt entry */
-
-    /* !! We are now on the RTOS system stack !! */
-
-    /* Set up PS for C, enable interrupts above this level and clear EXCM. */
-    #ifdef __XTENSA_CALL0_ABI__
-    movi    a0, PS_INTLEVEL(3) | PS_UM
-    #else
-    movi    a0, PS_INTLEVEL(3) | PS_UM | PS_WOE
-    #endif
-    wsr     a0, PS
-    rsync
-
-    /* OK to call C code at this point, dispatch user ISRs */
-
-    dispatch_c_isr 3 XCHAL_INTLEVEL3_MASK
-
-    /* Done handling interrupts, transfer control to OS */
-    call0   XT_RTOS_INT_EXIT                /* does not return directly here */
-
-    /*
-    Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT
-    on entry and used to return to a thread or interrupted interrupt handler.
-    */
-    .global     _xt_medint3_exit
-    .type       _xt_medint3_exit,@function
-    .align      4
-_xt_medint3_exit:
-    /* Restore only level-specific regs (the rest were already restored) */
-    l32i    a0, sp, XT_STK_PS               /* retrieve interruptee's PS */
-    wsr     a0, EPS_3
-    l32i    a0, sp, XT_STK_PC               /* retrieve interruptee's PC */
-    wsr     a0, EPC_3
-    l32i    a0, sp, XT_STK_A0               /* retrieve interruptee's A0 */
-    l32i    sp, sp, XT_STK_A1               /* remove interrupt stack frame */
-    rsync                                   /* ensure EPS and EPC written */
-    rfi     3
-
-#endif  /* Level 3 */
-
-#if XCHAL_EXCM_LEVEL >= 4
-
-    .begin      literal_prefix .Level4InterruptVector
-    .section    .Level4InterruptVector.text, "ax"
-    .global     _Level4Vector
-    .type       _Level4Vector,@function
-    .align      4
-_Level4Vector:
-    wsr     a0, EXCSAVE_4                   /* preserve a0 */
-    call0   _xt_medint4                     /* load interrupt handler */
-
-    .end        literal_prefix
-
-    .text
-    .type       _xt_medint4,@function
-    .align      4
-_xt_medint4:
-    mov     a0, sp                          /* sp == a1 */
-    addi    sp, sp, -XT_STK_FRMSZ           /* allocate interrupt stack frame */
-    s32i    a0, sp, XT_STK_A1               /* save pre-interrupt SP */
-    rsr     a0, EPS_4                       /* save interruptee's PS */
-    s32i    a0, sp, XT_STK_PS
-    rsr     a0, EPC_4                       /* save interruptee's PC */
-    s32i    a0, sp, XT_STK_PC
-    rsr     a0, EXCSAVE_4                   /* save interruptee's a0 */
-    s32i    a0, sp, XT_STK_A0
-    movi    a0, _xt_medint4_exit            /* save exit point for dispatch */
-    s32i    a0, sp, XT_STK_EXIT
-
-    /* Save rest of interrupt context and enter RTOS. */
-    call0   XT_RTOS_INT_ENTER               /* common RTOS interrupt entry */
-
-    /* !! We are now on the RTOS system stack !! */
-
-    /* Set up PS for C, enable interrupts above this level and clear EXCM. */
-    #ifdef __XTENSA_CALL0_ABI__
-    movi    a0, PS_INTLEVEL(4) | PS_UM
-    #else
-    movi    a0, PS_INTLEVEL(4) | PS_UM | PS_WOE
-    #endif
-    wsr     a0, PS
-    rsync
-
-    /* OK to call C code at this point, dispatch user ISRs */
-
-    dispatch_c_isr 4 XCHAL_INTLEVEL4_MASK
-
-    /* Done handling interrupts, transfer control to OS */
-    call0   XT_RTOS_INT_EXIT                /* does not return directly here */
-
-    /*
-    Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT
-    on entry and used to return to a thread or interrupted interrupt handler.
-    */
-    .global     _xt_medint4_exit
-    .type       _xt_medint4_exit,@function
-    .align      4
-_xt_medint4_exit:
-    /* Restore only level-specific regs (the rest were already restored) */
-    l32i    a0, sp, XT_STK_PS               /* retrieve interruptee's PS */
-    wsr     a0, EPS_4
-    l32i    a0, sp, XT_STK_PC               /* retrieve interruptee's PC */
-    wsr     a0, EPC_4
-    l32i    a0, sp, XT_STK_A0               /* retrieve interruptee's A0 */
-    l32i    sp, sp, XT_STK_A1               /* remove interrupt stack frame */
-    rsync                                   /* ensure EPS and EPC written */
-    rfi     4
-
-#endif  /* Level 4 */
-
-#if XCHAL_EXCM_LEVEL >= 5
-
-    .begin      literal_prefix .Level5InterruptVector
-    .section    .Level5InterruptVector.text, "ax"
-    .global     _Level5Vector
-    .type       _Level5Vector,@function
-    .align      4
-_Level5Vector:
-    wsr     a0, EXCSAVE_5                   /* preserve a0 */
-    call0   _xt_medint5                     /* load interrupt handler */
-
-    .end        literal_prefix
-
-    .text
-    .type       _xt_medint5,@function
-    .align      4
-_xt_medint5:
-    mov     a0, sp                          /* sp == a1 */
-    addi    sp, sp, -XT_STK_FRMSZ           /* allocate interrupt stack frame */
-    s32i    a0, sp, XT_STK_A1               /* save pre-interrupt SP */
-    rsr     a0, EPS_5                       /* save interruptee's PS */
-    s32i    a0, sp, XT_STK_PS
-    rsr     a0, EPC_5                       /* save interruptee's PC */
-    s32i    a0, sp, XT_STK_PC
-    rsr     a0, EXCSAVE_5                   /* save interruptee's a0 */
-    s32i    a0, sp, XT_STK_A0
-    movi    a0, _xt_medint5_exit            /* save exit point for dispatch */
-    s32i    a0, sp, XT_STK_EXIT
-
-    /* Save rest of interrupt context and enter RTOS. */
-    call0   XT_RTOS_INT_ENTER               /* common RTOS interrupt entry */
-
-    /* !! We are now on the RTOS system stack !! */
-
-    /* Set up PS for C, enable interrupts above this level and clear EXCM. */
-    #ifdef __XTENSA_CALL0_ABI__
-    movi    a0, PS_INTLEVEL(5) | PS_UM
-    #else
-    movi    a0, PS_INTLEVEL(5) | PS_UM | PS_WOE
-    #endif
-    wsr     a0, PS
-    rsync
-
-    /* OK to call C code at this point, dispatch user ISRs */
-
-    dispatch_c_isr 5 XCHAL_INTLEVEL5_MASK
-
-    /* Done handling interrupts, transfer control to OS */
-    call0   XT_RTOS_INT_EXIT                /* does not return directly here */
-
-    /*
-    Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT
-    on entry and used to return to a thread or interrupted interrupt handler.
-    */
-    .global     _xt_medint5_exit
-    .type       _xt_medint5_exit,@function
-    .align      4
-_xt_medint5_exit:
-    /* Restore only level-specific regs (the rest were already restored) */
-    l32i    a0, sp, XT_STK_PS               /* retrieve interruptee's PS */
-    wsr     a0, EPS_5
-    l32i    a0, sp, XT_STK_PC               /* retrieve interruptee's PC */
-    wsr     a0, EPC_5
-    l32i    a0, sp, XT_STK_A0               /* retrieve interruptee's A0 */
-    l32i    sp, sp, XT_STK_A1               /* remove interrupt stack frame */
-    rsync                                   /* ensure EPS and EPC written */
-    rfi     5
-
-#endif  /* Level 5 */
-
-#if XCHAL_EXCM_LEVEL >= 6
-
-    .begin      literal_prefix .Level6InterruptVector
-    .section    .Level6InterruptVector.text, "ax"
-    .global     _Level6Vector
-    .type       _Level6Vector,@function
-    .align      4
-_Level6Vector:
-    wsr     a0, EXCSAVE_6                   /* preserve a0 */
-    call0   _xt_medint6                     /* load interrupt handler */
-
-    .end        literal_prefix
-
-    .text
-    .type       _xt_medint6,@function
-    .align      4
-_xt_medint6:
-    mov     a0, sp                          /* sp == a1 */
-    addi    sp, sp, -XT_STK_FRMSZ           /* allocate interrupt stack frame */
-    s32i    a0, sp, XT_STK_A1               /* save pre-interrupt SP */
-    rsr     a0, EPS_6                       /* save interruptee's PS */
-    s32i    a0, sp, XT_STK_PS
-    rsr     a0, EPC_6                       /* save interruptee's PC */
-    s32i    a0, sp, XT_STK_PC
-    rsr     a0, EXCSAVE_6                   /* save interruptee's a0 */
-    s32i    a0, sp, XT_STK_A0
-    movi    a0, _xt_medint6_exit            /* save exit point for dispatch */
-    s32i    a0, sp, XT_STK_EXIT
-
-    /* Save rest of interrupt context and enter RTOS. */
-    call0   XT_RTOS_INT_ENTER               /* common RTOS interrupt entry */
-
-    /* !! We are now on the RTOS system stack !! */
-
-    /* Set up PS for C, enable interrupts above this level and clear EXCM. */
-    #ifdef __XTENSA_CALL0_ABI__
-    movi    a0, PS_INTLEVEL(6) | PS_UM
-    #else
-    movi    a0, PS_INTLEVEL(6) | PS_UM | PS_WOE
-    #endif
-    wsr     a0, PS
-    rsync
-
-    /* OK to call C code at this point, dispatch user ISRs */
-
-    dispatch_c_isr 6 XCHAL_INTLEVEL6_MASK
-
-    /* Done handling interrupts, transfer control to OS */
-    call0   XT_RTOS_INT_EXIT                /* does not return directly here */
-
-    /*
-    Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT
-    on entry and used to return to a thread or interrupted interrupt handler.
-    */
-    .global     _xt_medint6_exit
-    .type       _xt_medint6_exit,@function
-    .align      4
-_xt_medint6_exit:
-    /* Restore only level-specific regs (the rest were already restored) */
-    l32i    a0, sp, XT_STK_PS               /* retrieve interruptee's PS */
-    wsr     a0, EPS_6
-    l32i    a0, sp, XT_STK_PC               /* retrieve interruptee's PC */
-    wsr     a0, EPC_6
-    l32i    a0, sp, XT_STK_A0               /* retrieve interruptee's A0 */
-    l32i    sp, sp, XT_STK_A1               /* remove interrupt stack frame */
-    rsync                                   /* ensure EPS and EPC written */
-    rfi     6
-
-#endif  /* Level 6 */
-
-
-/*******************************************************************************
-
-HIGH PRIORITY (LEVEL > XCHAL_EXCM_LEVEL) INTERRUPT VECTORS AND HANDLERS
-
-High priority interrupts are by definition those with priorities greater
-than XCHAL_EXCM_LEVEL. This includes non-maskable (NMI). High priority
-interrupts cannot interact with the RTOS, that is they must save all regs
-they use and not call any RTOS function.
-
-A further restriction imposed by the Xtensa windowed architecture is that
-high priority interrupts must not modify the stack area even logically
-"above" the top of the interrupted stack (they need to provide their
-own stack or static save area).
-
-Cadence Design Systems recommends high priority interrupt handlers be coded in assembly
-and used for purposes requiring very short service times.
-
-Here are templates for high priority (level 2+) interrupt vectors.
-They assume only one interrupt per level to avoid the burden of identifying
-which interrupts at this level are pending and enabled. This allows for 
-minimum latency and avoids having to save/restore a2 in addition to a0.
-If more than one interrupt per high priority level is configured, this burden
-is on the handler which in any case must provide a way to save and restore
-registers it uses without touching the interrupted stack.
-
-Each vector goes at a predetermined location according to the Xtensa
-hardware configuration, which is ensured by its placement in a special
-section known to the Xtensa linker support package (LSP). It performs
-the minimum necessary before jumping to the handler in the .text section.
-
-*******************************************************************************/
-
-/*
-Currently only shells for high priority interrupt handlers are provided
-here. However a template and example can be found in the Cadence Design Systems tools
-documentation: "Microprocessor Programmer's Guide".
-*/
-
-#if XCHAL_NUM_INTLEVELS >=2 && XCHAL_EXCM_LEVEL <2 && XCHAL_DEBUGLEVEL !=2
-
-    .begin      literal_prefix .Level2InterruptVector
-    .section    .Level2InterruptVector.text, "ax"
-    .global     _Level2Vector
-    .type       _Level2Vector,@function
-    .align      4
-_Level2Vector:
-    wsr     a0, EXCSAVE_2                   /* preserve a0 */
-    call0   _xt_highint2                    /* load interrupt handler */
-
-    .end        literal_prefix
-
-    .text
-    .type       _xt_highint2,@function
-    .align      4
-_xt_highint2:
-
-    #ifdef XT_INTEXC_HOOKS
-    /* Call interrupt hook if present to (pre)handle interrupts. */
-    movi    a0, _xt_intexc_hooks
-    l32i    a0, a0, 2<<2
-    beqz    a0, 1f
-.Ln_xt_highint2_call_hook:
-    callx0  a0                              /* must NOT disturb stack! */
-1:
-    #endif
-
-    /* USER_EDIT:
-    ADD HIGH PRIORITY LEVEL 2 INTERRUPT HANDLER CODE HERE.
-    */
-
-    .align  4
-.L_xt_highint2_exit:
-    rsr     a0, EXCSAVE_2                   /* restore a0 */
-    rfi     2
-
-#endif  /* Level 2 */
-
-#if XCHAL_NUM_INTLEVELS >=3 && XCHAL_EXCM_LEVEL <3 && XCHAL_DEBUGLEVEL !=3
-
-    .begin      literal_prefix .Level3InterruptVector
-    .section    .Level3InterruptVector.text, "ax"
-    .global     _Level3Vector
-    .type       _Level3Vector,@function
-    .align      4
-_Level3Vector:
-    wsr     a0, EXCSAVE_3                   /* preserve a0 */
-    call0   _xt_highint3                    /* load interrupt handler */
-    /* never returns here - call0 is used as a jump (see note at top) */
-
-    .end        literal_prefix
-
-    .text
-    .type       _xt_highint3,@function
-    .align      4
-_xt_highint3:
-
-    #ifdef XT_INTEXC_HOOKS
-    /* Call interrupt hook if present to (pre)handle interrupts. */
-    movi    a0, _xt_intexc_hooks
-    l32i    a0, a0, 3<<2
-    beqz    a0, 1f
-.Ln_xt_highint3_call_hook:
-    callx0  a0                              /* must NOT disturb stack! */
-1:
-    #endif
-
-    /* USER_EDIT:
-    ADD HIGH PRIORITY LEVEL 3 INTERRUPT HANDLER CODE HERE.
-    */
-
-    .align  4
-.L_xt_highint3_exit:
-    rsr     a0, EXCSAVE_3                   /* restore a0 */
-    rfi     3
-
-#endif  /* Level 3 */
-
-#if XCHAL_NUM_INTLEVELS >=4 && XCHAL_EXCM_LEVEL <4 && XCHAL_DEBUGLEVEL !=4
-
-    .begin      literal_prefix .Level4InterruptVector
-    .section    .Level4InterruptVector.text, "ax"
-    .global     _Level4Vector
-    .type       _Level4Vector,@function
-    .align      4
-_Level4Vector:
-    wsr     a0, EXCSAVE_4                   /* preserve a0 */
-    call0   _xt_highint4                    /* load interrupt handler */
-    /* never returns here - call0 is used as a jump (see note at top) */
-
-    .end        literal_prefix
-
-    .text
-    .type       _xt_highint4,@function
-    .align      4
-_xt_highint4:
-
-    #ifdef XT_INTEXC_HOOKS
-    /* Call interrupt hook if present to (pre)handle interrupts. */
-    movi    a0, _xt_intexc_hooks
-    l32i    a0, a0, 4<<2
-    beqz    a0, 1f
-.Ln_xt_highint4_call_hook:
-    callx0  a0                              /* must NOT disturb stack! */
-1:
-    #endif
-
-    /* USER_EDIT:
-    ADD HIGH PRIORITY LEVEL 4 INTERRUPT HANDLER CODE HERE.
-    */
-
-    .align  4
-.L_xt_highint4_exit:
-    rsr     a0, EXCSAVE_4                   /* restore a0 */
-    rfi     4
-
-#endif  /* Level 4 */
-
-#if XCHAL_NUM_INTLEVELS >=5 && XCHAL_EXCM_LEVEL <5 && XCHAL_DEBUGLEVEL !=5
-
-    .begin      literal_prefix .Level5InterruptVector
-    .section    .Level5InterruptVector.text, "ax"
-    .global     _Level5Vector
-    .type       _Level5Vector,@function
-    .align      4
-_Level5Vector:
-    wsr     a0, EXCSAVE_5                   /* preserve a0 */
-    call0   _xt_highint5                    /* load interrupt handler */
-    /* never returns here - call0 is used as a jump (see note at top) */
-
-    .end        literal_prefix
-
-    .text
-    .type       _xt_highint5,@function
-    .align      4
-_xt_highint5:
-
-    #ifdef XT_INTEXC_HOOKS
-    /* Call interrupt hook if present to (pre)handle interrupts. */
-    movi    a0, _xt_intexc_hooks
-    l32i    a0, a0, 5<<2
-    beqz    a0, 1f
-.Ln_xt_highint5_call_hook:
-    callx0  a0                              /* must NOT disturb stack! */
-1:
-    #endif
-
-    /* USER_EDIT:
-    ADD HIGH PRIORITY LEVEL 5 INTERRUPT HANDLER CODE HERE.
-    */
-
-    .align  4
-.L_xt_highint5_exit:
-    rsr     a0, EXCSAVE_5                   /* restore a0 */
-    rfi     5
-
-#endif  /* Level 5 */
-
-#if XCHAL_NUM_INTLEVELS >=6 && XCHAL_EXCM_LEVEL <6 && XCHAL_DEBUGLEVEL !=6
-
-    .begin      literal_prefix .Level6InterruptVector
-    .section    .Level6InterruptVector.text, "ax"
-    .global     _Level6Vector
-    .type       _Level6Vector,@function
-    .align      4
-_Level6Vector:
-    wsr     a0, EXCSAVE_6                   /* preserve a0 */
-    call0   _xt_highint6                    /* load interrupt handler */
-    /* never returns here - call0 is used as a jump (see note at top) */
-
-    .end        literal_prefix
-
-    .text
-    .type       _xt_highint6,@function
-    .align      4
-_xt_highint6:
-
-    #ifdef XT_INTEXC_HOOKS
-    /* Call interrupt hook if present to (pre)handle interrupts. */
-    movi    a0, _xt_intexc_hooks
-    l32i    a0, a0, 6<<2
-    beqz    a0, 1f
-.Ln_xt_highint6_call_hook:
-    callx0  a0                              /* must NOT disturb stack! */
-1:
-    #endif
-
-    /* USER_EDIT:
-    ADD HIGH PRIORITY LEVEL 6 INTERRUPT HANDLER CODE HERE.
-    */
-
-    .align  4
-.L_xt_highint6_exit:
-    rsr     a0, EXCSAVE_6                   /* restore a0 */
-    rfi     6
-
-#endif  /* Level 6 */
-
-#if XCHAL_HAVE_NMI
-
-    .begin      literal_prefix .NMIExceptionVector
-    .section    .NMIExceptionVector.text, "ax"
-    .global     _NMIExceptionVector
-    .type       _NMIExceptionVector,@function
-    .align      4
-_NMIExceptionVector:
-    wsr     a0, EXCSAVE + XCHAL_NMILEVEL  _ /* preserve a0 */
-    call0   _xt_nmi                         /* load interrupt handler */
-    /* never returns here - call0 is used as a jump (see note at top) */
-
-    .end        literal_prefix
-
-    .text
-    .type       _xt_nmi,@function
-    .align      4
-_xt_nmi:
-
-    #ifdef XT_INTEXC_HOOKS
-    /* Call interrupt hook if present to (pre)handle interrupts. */
-    movi    a0, _xt_intexc_hooks
-    l32i    a0, a0, XCHAL_NMILEVEL<<2
-    beqz    a0, 1f
-.Ln_xt_nmi_call_hook:
-    callx0  a0                              /* must NOT disturb stack! */
-1:
-    #endif
-
-    /* USER_EDIT:
-    ADD HIGH PRIORITY NON-MASKABLE INTERRUPT (NMI) HANDLER CODE HERE.
-    */
-
-    .align  4
-.L_xt_nmi_exit:
-    rsr     a0, EXCSAVE + XCHAL_NMILEVEL    /* restore a0 */
-    rfi     XCHAL_NMILEVEL
-
-#endif  /* NMI */
-
-
-/*******************************************************************************
-
-WINDOW OVERFLOW AND UNDERFLOW EXCEPTION VECTORS AND ALLOCA EXCEPTION HANDLER
-
-Here is the code for each window overflow/underflow exception vector and 
-(interspersed) efficient code for handling the alloca exception cause.
-Window exceptions are handled entirely in the vector area and are very
-tight for performance. The alloca exception is also handled entirely in 
-the window vector area so comes at essentially no cost in code size.
-Users should never need to modify them and Cadence Design Systems recommends 
-they do not.
-
-Window handlers go at predetermined vector locations according to the
-Xtensa hardware configuration, which is ensured by their placement in a
-special section known to the Xtensa linker support package (LSP). Since
-their offsets in that section are always the same, the LSPs do not define
-a section per vector.
-
-These things are coded for XEA2 only (XEA1 is not supported).
-
-Note on Underflow Handlers:
-The underflow handler for returning from call[i+1] to call[i]
-must preserve all the registers from call[i+1]'s window.
-In particular, a0 and a1 must be preserved because the RETW instruction
-will be reexecuted (and may even underflow if an intervening exception
-has flushed call[i]'s registers).
-Registers a2 and up may contain return values.
-
-*******************************************************************************/
-
-#if XCHAL_HAVE_WINDOWED
-
-    .section .WindowVectors.text, "ax"
-
-/*
---------------------------------------------------------------------------------
-Window Overflow Exception for Call4.
-
-Invoked if a call[i] referenced a register (a4-a15)
-that contains data from ancestor call[j];
-call[j] had done a call4 to call[j+1].
-On entry here:
-    window rotated to call[j] start point;
-        a0-a3 are registers to be saved;
-        a4-a15 must be preserved;
-        a5 is call[j+1]'s stack pointer.
---------------------------------------------------------------------------------
-*/
-
-    .org    0x0
-    .global _WindowOverflow4
-_WindowOverflow4:
-
-    s32e    a0, a5, -16     /* save a0 to call[j+1]'s stack frame */
-    s32e    a1, a5, -12     /* save a1 to call[j+1]'s stack frame */
-    s32e    a2, a5,  -8     /* save a2 to call[j+1]'s stack frame */
-    s32e    a3, a5,  -4     /* save a3 to call[j+1]'s stack frame */
-    rfwo                    /* rotates back to call[i] position */
-
-/*
---------------------------------------------------------------------------------
-Window Underflow Exception for Call4
-
-Invoked by RETW returning from call[i+1] to call[i]
-where call[i]'s registers must be reloaded (not live in ARs);
-where call[i] had done a call4 to call[i+1].
-On entry here:
-        window rotated to call[i] start point;
-        a0-a3 are undefined, must be reloaded with call[i].reg[0..3];
-        a4-a15 must be preserved (they are call[i+1].reg[0..11]);
-        a5 is call[i+1]'s stack pointer.
---------------------------------------------------------------------------------
-*/
-
-    .org    0x40
-    .global _WindowUnderflow4
-_WindowUnderflow4:
-
-    l32e    a0, a5, -16     /* restore a0 from call[i+1]'s stack frame */
-    l32e    a1, a5, -12     /* restore a1 from call[i+1]'s stack frame */
-    l32e    a2, a5,  -8     /* restore a2 from call[i+1]'s stack frame */
-    l32e    a3, a5,  -4     /* restore a3 from call[i+1]'s stack frame */
-    rfwu
-
-/*
---------------------------------------------------------------------------------
-Handle alloca exception generated by interruptee executing 'movsp'.
-This uses space between the window vectors, so is essentially "free".
-All interruptee's regs are intact except a0 which is saved in EXCSAVE_1,
-and PS.EXCM has been set by the exception hardware (can't be interrupted).
-The fact the alloca exception was taken means the registers associated with
-the base-save area have been spilled and will be restored by the underflow
-handler, so those 4 registers are available for scratch.
-The code is optimized to avoid unaligned branches and minimize cache misses.
---------------------------------------------------------------------------------
-*/
-
-    .align  4
-    .global _xt_alloca_exc
-_xt_alloca_exc:
-
-    rsr     a0, WINDOWBASE  /* grab WINDOWBASE before rotw changes it */
-    rotw    -1              /* WINDOWBASE goes to a4, new a0-a3 are scratch */
-    rsr     a2, PS
-    extui   a3, a2, XCHAL_PS_OWB_SHIFT, XCHAL_PS_OWB_BITS
-    xor     a3, a3, a4      /* bits changed from old to current windowbase */
-    rsr     a4, EXCSAVE_1   /* restore original a0 (now in a4) */
-    slli    a3, a3, XCHAL_PS_OWB_SHIFT
-    xor     a2, a2, a3      /* flip changed bits in old window base */
-    wsr     a2, PS          /* update PS.OWB to new window base */
-    rsync
-
-    _bbci.l a4, 31, _WindowUnderflow4
-    rotw    -1              /* original a0 goes to a8 */
-    _bbci.l a8, 30, _WindowUnderflow8
-    rotw    -1
-    j               _WindowUnderflow12
-
-/*
---------------------------------------------------------------------------------
-Window Overflow Exception for Call8
-
-Invoked if a call[i] referenced a register (a4-a15)
-that contains data from ancestor call[j];
-call[j] had done a call8 to call[j+1].
-On entry here:
-    window rotated to call[j] start point;
-        a0-a7 are registers to be saved;
-        a8-a15 must be preserved;
-        a9 is call[j+1]'s stack pointer.
---------------------------------------------------------------------------------
-*/
-
-    .org    0x80
-    .global _WindowOverflow8
-_WindowOverflow8:
-
-    s32e    a0, a9, -16     /* save a0 to call[j+1]'s stack frame */
-    l32e    a0, a1, -12     /* a0 <- call[j-1]'s sp
-                               (used to find end of call[j]'s frame) */
-    s32e    a1, a9, -12     /* save a1 to call[j+1]'s stack frame */
-    s32e    a2, a9,  -8     /* save a2 to call[j+1]'s stack frame */
-    s32e    a3, a9,  -4     /* save a3 to call[j+1]'s stack frame */
-    s32e    a4, a0, -32     /* save a4 to call[j]'s stack frame */
-    s32e    a5, a0, -28     /* save a5 to call[j]'s stack frame */
-    s32e    a6, a0, -24     /* save a6 to call[j]'s stack frame */
-    s32e    a7, a0, -20     /* save a7 to call[j]'s stack frame */
-    rfwo                    /* rotates back to call[i] position */
-
-/*
---------------------------------------------------------------------------------
-Window Underflow Exception for Call8
-
-Invoked by RETW returning from call[i+1] to call[i]
-where call[i]'s registers must be reloaded (not live in ARs);
-where call[i] had done a call8 to call[i+1].
-On entry here:
-        window rotated to call[i] start point;
-        a0-a7 are undefined, must be reloaded with call[i].reg[0..7];
-        a8-a15 must be preserved (they are call[i+1].reg[0..7]);
-        a9 is call[i+1]'s stack pointer.
---------------------------------------------------------------------------------
-*/
-
-    .org    0xC0
-    .global _WindowUnderflow8
-_WindowUnderflow8:
-
-    l32e    a0, a9, -16     /* restore a0 from call[i+1]'s stack frame */
-    l32e    a1, a9, -12     /* restore a1 from call[i+1]'s stack frame */
-    l32e    a2, a9,  -8     /* restore a2 from call[i+1]'s stack frame */
-    l32e    a7, a1, -12     /* a7 <- call[i-1]'s sp
-                               (used to find end of call[i]'s frame) */
-    l32e    a3, a9,  -4     /* restore a3 from call[i+1]'s stack frame */
-    l32e    a4, a7, -32     /* restore a4 from call[i]'s stack frame */
-    l32e    a5, a7, -28     /* restore a5 from call[i]'s stack frame */
-    l32e    a6, a7, -24     /* restore a6 from call[i]'s stack frame */
-    l32e    a7, a7, -20     /* restore a7 from call[i]'s stack frame */
-    rfwu
-
-/*
---------------------------------------------------------------------------------
-Window Overflow Exception for Call12
-
-Invoked if a call[i] referenced a register (a4-a15)
-that contains data from ancestor call[j];
-call[j] had done a call12 to call[j+1].
-On entry here:
-    window rotated to call[j] start point;
-        a0-a11 are registers to be saved;
-        a12-a15 must be preserved;
-        a13 is call[j+1]'s stack pointer.
---------------------------------------------------------------------------------
-*/
-
-    .org    0x100
-    .global _WindowOverflow12
-_WindowOverflow12:
-
-    s32e    a0,  a13, -16   /* save a0 to call[j+1]'s stack frame */
-    l32e    a0,  a1,  -12   /* a0 <- call[j-1]'s sp
-                               (used to find end of call[j]'s frame) */
-    s32e    a1,  a13, -12   /* save a1 to call[j+1]'s stack frame */
-    s32e    a2,  a13,  -8   /* save a2 to call[j+1]'s stack frame */
-    s32e    a3,  a13,  -4   /* save a3 to call[j+1]'s stack frame */
-    s32e    a4,  a0,  -48   /* save a4 to end of call[j]'s stack frame */
-    s32e    a5,  a0,  -44   /* save a5 to end of call[j]'s stack frame */
-    s32e    a6,  a0,  -40   /* save a6 to end of call[j]'s stack frame */
-    s32e    a7,  a0,  -36   /* save a7 to end of call[j]'s stack frame */
-    s32e    a8,  a0,  -32   /* save a8 to end of call[j]'s stack frame */
-    s32e    a9,  a0,  -28   /* save a9 to end of call[j]'s stack frame */
-    s32e    a10, a0,  -24   /* save a10 to end of call[j]'s stack frame */
-    s32e    a11, a0,  -20   /* save a11 to end of call[j]'s stack frame */
-    rfwo                    /* rotates back to call[i] position */
-
-/*
---------------------------------------------------------------------------------
-Window Underflow Exception for Call12
-
-Invoked by RETW returning from call[i+1] to call[i]
-where call[i]'s registers must be reloaded (not live in ARs);
-where call[i] had done a call12 to call[i+1].
-On entry here:
-        window rotated to call[i] start point;
-        a0-a11 are undefined, must be reloaded with call[i].reg[0..11];
-        a12-a15 must be preserved (they are call[i+1].reg[0..3]);
-        a13 is call[i+1]'s stack pointer.
---------------------------------------------------------------------------------
-*/
-
-    .org 0x140
-    .global _WindowUnderflow12
-_WindowUnderflow12:
-
-    l32e    a0,  a13, -16   /* restore a0 from call[i+1]'s stack frame */
-    l32e    a1,  a13, -12   /* restore a1 from call[i+1]'s stack frame */
-    l32e    a2,  a13,  -8   /* restore a2 from call[i+1]'s stack frame */
-    l32e    a11, a1,  -12   /* a11 <- call[i-1]'s sp
-                               (used to find end of call[i]'s frame) */
-    l32e    a3,  a13,  -4   /* restore a3 from call[i+1]'s stack frame */
-    l32e    a4,  a11, -48   /* restore a4 from end of call[i]'s stack frame */
-    l32e    a5,  a11, -44   /* restore a5 from end of call[i]'s stack frame */
-    l32e    a6,  a11, -40   /* restore a6 from end of call[i]'s stack frame */
-    l32e    a7,  a11, -36   /* restore a7 from end of call[i]'s stack frame */
-    l32e    a8,  a11, -32   /* restore a8 from end of call[i]'s stack frame */
-    l32e    a9,  a11, -28   /* restore a9 from end of call[i]'s stack frame */
-    l32e    a10, a11, -24   /* restore a10 from end of call[i]'s stack frame */
-    l32e    a11, a11, -20   /* restore a11 from end of call[i]'s stack frame */
-    rfwu
-
-#endif /* XCHAL_HAVE_WINDOWED */
-
-    .section    .UserEnter.text, "ax"
-    .global     call_user_start
-    .type       call_user_start,@function
-    .align      4
-    .literal_position
-
-
-call_user_start:
-
-	movi	a2, 0x40040000	/* note: absolute symbol, not a ptr */
-	wsr	a2, vecbase
-	call0   user_start                    /* user exception handler */

+ 0 - 2064
components/freertos/xtensa_vectors.S-old

@@ -1,2064 +0,0 @@
-/*******************************************************************************
-Copyright (c) 2006-2015 Cadence Design Systems Inc.
-
-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.
---------------------------------------------------------------------------------
-
-        XTENSA VECTORS AND LOW LEVEL HANDLERS FOR AN RTOS
-
-  Xtensa low level exception and interrupt vectors and handlers for an RTOS.
-
-  Interrupt handlers and user exception handlers support interaction with
-  the RTOS by calling XT_RTOS_INT_ENTER and XT_RTOS_INT_EXIT before and
-  after user's specific interrupt handlers. These macros are defined in
-  xtensa_<rtos>.h to call suitable functions in a specific RTOS.
-
-  Users can install application-specific interrupt handlers for low and
-  medium level interrupts, by calling xt_set_interrupt_handler(). These
-  handlers can be written in C, and must obey C calling convention. The
-  handler table is indexed by the interrupt number. Each handler may be
-  provided with an argument. 
-
-  Note that the system timer interrupt is handled specially, and is
-  dispatched to the RTOS-specific handler. This timer cannot be hooked
-  by application code.
-
-  Optional hooks are also provided to install a handler per level at 
-  run-time, made available by compiling this source file with 
-  '-DXT_INTEXC_HOOKS' (useful for automated testing).
-
-!!  This file is a template that usually needs to be modified to handle       !!
-!!  application specific interrupts. Search USER_EDIT for helpful comments    !!
-!!  on where to insert handlers and how to write them.                        !!
-
-  Users can also install application-specific exception handlers in the
-  same way, by calling xt_set_exception_handler(). One handler slot is
-  provided for each exception type. Note that some exceptions are handled
-  by the porting layer itself, and cannot be taken over by application
-  code in this manner. These are the alloca, syscall, and coprocessor
-  exceptions.
-
-  The exception handlers can be written in C, and must follow C calling
-  convention. Each handler is passed a pointer to an exception frame as
-  its single argument. The exception frame is created on the stack, and
-  holds the saved context of the thread that took the exception. If the
-  handler returns, the context will be restored and the instruction that
-  caused the exception will be retried. If the handler makes any changes
-  to the saved state in the exception frame, the changes will be applied
-  when restoring the context.
-
-  Because Xtensa is a configurable architecture, this port supports all user
-  generated configurations (except restrictions stated in the release notes).
-  This is accomplished by conditional compilation using macros and functions
-  defined in the Xtensa HAL (hardware adaptation layer) for your configuration.
-  Only the relevant parts of this file will be included in your RTOS build.
-  For example, this file provides interrupt vector templates for all types and
-  all priority levels, but only the ones in your configuration are built.
-
-  NOTES on the use of 'call0' for long jumps instead of 'j':
-   1. This file should be assembled with the -mlongcalls option to xt-xcc.
-   2. The -mlongcalls compiler option causes 'call0 dest' to be expanded to
-      a sequence 'l32r a0, dest' 'callx0 a0' which works regardless of the
-      distance from the call to the destination. The linker then relaxes
-      it back to 'call0 dest' if it determines that dest is within range.
-      This allows more flexibility in locating code without the performance
-      overhead of the 'l32r' literal data load in cases where the destination
-      is in range of 'call0'. There is an additional benefit in that 'call0'
-      has a longer range than 'j' due to the target being word-aligned, so 
-      the 'l32r' sequence is less likely needed.
-   3. The use of 'call0' with -mlongcalls requires that register a0 not be 
-      live at the time of the call, which is always the case for a function 
-      call but needs to be ensured if 'call0' is used as a jump in lieu of 'j'.
-   4. This use of 'call0' is independent of the C function call ABI.
-
-*******************************************************************************/
-
-#include "xtensa_rtos.h"
-
-
-/* Enable stack backtrace across exception/interrupt - see below */
-#define XT_DEBUG_BACKTRACE    0
-
-
-/*
---------------------------------------------------------------------------------
-  Defines used to access _xtos_interrupt_table.
---------------------------------------------------------------------------------
-*/
-#define XIE_HANDLER     0
-#define XIE_ARG         4
-#define XIE_SIZE        8
-
-/*
---------------------------------------------------------------------------------
-  Macro extract_msb - return the input with only the highest bit set.
-
-  Input  : "ain"  - Input value, clobbered.
-  Output : "aout" - Output value, has only one bit set, MSB of "ain".
-  The two arguments must be different AR registers.
---------------------------------------------------------------------------------
-*/
-
-    .macro  extract_msb     aout ain
-1:
-    addi    \aout, \ain, -1         /* aout = ain - 1        */
-    and     \ain, \ain, \aout       /* ain  = ain & aout     */
-    bnez    \ain, 1b                /* repeat until ain == 0 */
-    addi    \aout, \aout, 1         /* return aout + 1       */
-    .endm
-
-/*
---------------------------------------------------------------------------------
-  Macro dispatch_c_isr - dispatch interrupts to user ISRs.
-  This will dispatch to user handlers (if any) that are registered in the
-  XTOS dispatch table (_xtos_interrupt_table). These handlers would have
-  been registered by calling _xtos_set_interrupt_handler(). There is one
-  exception - the timer interrupt used by the OS will not be dispatched
-  to a user handler - this must be handled by the caller of this macro.
-
-  Level triggered and software interrupts are automatically deasserted by
-  this code.
-
-  ASSUMPTIONS:
-    -- PS.INTLEVEL is set to "level" at entry
-    -- PS.EXCM = 0, C calling enabled
-
-  NOTE: For CALL0 ABI, a12-a15 have not yet been saved.
-
-  NOTE: This macro will use registers a0 and a2-a6. The arguments are:
-    level -- interrupt level
-    mask  -- interrupt bitmask for this level
---------------------------------------------------------------------------------
-*/
-
-    .macro  dispatch_c_isr    level  mask
-
-    /* Get mask of pending, enabled interrupts at this level into a2. */
-
-.L_xt_user_int_&level&:
-    rsr     a2, INTENABLE
-    rsr     a3, INTERRUPT
-    movi    a4, \mask
-    and     a2, a2, a3
-    and     a2, a2, a4
-    beqz    a2, 9f                          /* nothing to do */
-
-    /* This bit of code provides a nice debug backtrace in the debugger.
-       It does take a few more instructions, so undef XT_DEBUG_BACKTRACE
-       if you want to save the cycles.
-    */
-    #if XT_DEBUG_BACKTRACE
-    #ifndef __XTENSA_CALL0_ABI__
-    rsr     a0, EPC_1 + \level - 1          /* return address */
-    movi    a4, 0xC0000000                  /* constant with top 2 bits set (call size) */
-    or      a0, a0, a4                      /* set top 2 bits */
-    addx2   a0, a4, a0                      /* clear top bit -- simulating call4 size   */
-    #endif
-    #endif
-
-    #ifdef XT_INTEXC_HOOKS
-    /* Call interrupt hook if present to (pre)handle interrupts. */
-    movi    a4, _xt_intexc_hooks
-    l32i    a4, a4, \level << 2
-    beqz    a4, 2f
-    #ifdef __XTENSA_CALL0_ABI__
-    callx0  a4
-    beqz    a2, 9f
-    #else
-    mov     a6, a2
-    callx4  a4
-    beqz    a6, 9f
-    mov     a2, a6
-    #endif
-2:
-    #endif
-
-    /* Now look up in the dispatch table and call user ISR if any. */
-    /* If multiple bits are set then MSB has highest priority.     */
-
-    extract_msb  a4, a2                     /* a4 = MSB of a2, a2 trashed */
-
-    #ifdef XT_USE_SWPRI
-    /* Enable all interrupts at this level that are numerically higher
-       than the one we just selected, since they are treated as higher
-       priority.
-    */
-    movi    a3, \mask                       /* a3 = all interrupts at this level */
-    add     a2, a4, a4                      /* a2 = a4 << 1 */
-    addi    a2, a2, -1                      /* a2 = mask of 1's <= a4 bit */
-    and     a2, a2, a3                      /* a2 = mask of all bits <= a4 at this level */
-    movi    a3, _xt_intdata
-    l32i    a6, a3, 4                       /* a6 = _xt_vpri_mask */
-    neg     a2, a2
-    addi    a2, a2, -1                      /* a2 = mask to apply */
-    and     a5, a6, a2                      /* mask off all bits <= a4 bit */
-    s32i    a5, a3, 4                       /* update _xt_vpri_mask */
-    rsr     a3, INTENABLE
-    and     a3, a3, a2                      /* mask off all bits <= a4 bit */
-    wsr     a3, INTENABLE
-    rsil    a3, \level - 1                  /* lower interrupt level by 1 */
-    #endif
-
-    movi    a3, XT_TIMER_INTEN              /* a3 = timer interrupt bit */
-    wsr     a4, INTCLEAR                    /* clear sw or edge-triggered interrupt */
-    beq     a3, a4, 7f                      /* if timer interrupt then skip table */
-
-    find_ms_setbit a3, a4, a3, 0            /* a3 = interrupt number */
-
-    movi    a4, _xt_interrupt_table
-    addx8   a3, a3, a4                      /* a3 = address of interrupt table entry */
-    l32i    a4, a3, XIE_HANDLER             /* a4 = handler address */
-    #ifdef __XTENSA_CALL0_ABI__
-    mov     a12, a6                         /* save in callee-saved reg */
-    l32i    a2, a3, XIE_ARG                 /* a2 = handler arg */
-    callx0  a4                              /* call handler */
-    mov     a2, a12
-    #else
-    mov     a2, a6                          /* save in windowed reg */
-    l32i    a6, a3, XIE_ARG                 /* a6 = handler arg */
-    callx4  a4                              /* call handler */
-    #endif
-
-    #ifdef XT_USE_SWPRI
-    j       8f
-    #else
-    j       .L_xt_user_int_&level&          /* check for more interrupts */
-    #endif
-
-7:
-
-    .ifeq XT_TIMER_INTPRI - \level
-.L_xt_user_int_timer_&level&:
-    /*
-    Interrupt handler for the RTOS tick timer if at this level.
-    We'll be reading the interrupt state again after this call
-    so no need to preserve any registers except a6 (vpri_mask).
-    */
-
-    #ifdef __XTENSA_CALL0_ABI__
-    mov     a12, a6
-    call0   XT_RTOS_TIMER_INT
-    mov     a2, a12
-    #else
-    mov     a2, a6
-    call4   XT_RTOS_TIMER_INT
-    #endif
-    .endif
-
-    #ifdef XT_USE_SWPRI
-    j       8f
-    #else
-    j       .L_xt_user_int_&level&          /* check for more interrupts */
-    #endif
-
-    #ifdef XT_USE_SWPRI
-8:
-    /* Restore old value of _xt_vpri_mask from a2. Also update INTENABLE from
-       virtual _xt_intenable which _could_ have changed during interrupt
-       processing. */
-
-    movi    a3, _xt_intdata
-    l32i    a4, a3, 0                       /* a4 = _xt_intenable    */
-    s32i    a2, a3, 4                       /* update _xt_vpri_mask  */
-    and     a4, a4, a2                      /* a4 = masked intenable */
-    wsr     a4, INTENABLE                   /* update INTENABLE      */
-    #endif
-
-9:
-    /* done */
-
-    .endm
-
-
-/*
---------------------------------------------------------------------------------
-  Panic handler.
-  Should be reached by call0 (preferable) or jump only. If call0, a0 says where 
-  from. If on simulator, display panic message and abort, else loop indefinitely.
---------------------------------------------------------------------------------
-*/
-
-    .text
-	.global panicHandlerRegs
-	.global panicHandler
-	.global panicStack
-
-    .global     _xt_panic
-    .type       _xt_panic,@function
-    .align      4
-
-_xt_panic:
-	//ToDo: save registers
-	movi a2, panicHandlerRegs
-	s32i a0,a2,0
-	s32i a1,a2,4
-	s32i a2,a2,8
-	s32i a3,a2,12
-	s32i a4,a2,16
-	s32i a5,a2,20
-	s32i a6,a2,24
-	s32i a7,a2,28
-	s32i a8,a2,32
-	s32i a9,a2,36
-	s32i a10,a2,40
-	s32i a11,a2,44
-	s32i a12,a2,48
-	s32i a13,a2,52
-	s32i a14,a2,56
-	s32i a15,a2,60
-
-	rsr a3, EXCSAVE
-	s32i a3,a2,64
-	rsr a3, EXCSAVE+1
-	s32i a3,a2,68
-	rsr a3, EXCSAVE+2
-	s32i a3,a2,72
-	rsr a3, EXCSAVE+3
-	s32i a3,a2,76
-	rsr a3, EXCSAVE+4
-	s32i a3,a2,80
-	rsr a3, EXCSAVE+5
-	s32i a3,a2,84
-	rsr a3, EXCSAVE+6
-	s32i a3,a2,88
-	rsr a3, EXCSAVE+7
-	s32i a3,a2,92
-
-	rsr a3, EPC
-	s32i a3,a2,96
-	rsr a3, EPC+1
-	s32i a3,a2,100
-	rsr a3, EPC+2
-	s32i a3,a2,104
-	rsr a3, EPC+3
-	s32i a3,a2,108
-	rsr a3, EPC+4
-	s32i a3,a2,112
-	rsr a3, EPC+5
-	s32i a3,a2,116
-	rsr a3, EPC+6
-	s32i a3,a2,120
-	rsr a3, EPC+7
-	s32i a3,a2,124
-
-	rsr a3, DEPC
-	s32i a3,a2,128
-	rsr a3, EXCVADDR
-	s32i a3,a2,132
-
-	//Reset window start / base to 0
-	movi	a2, 1
-	wsr	a2, windowstart
-	movi	a2, 0
-	wsr	a2, windowbase
-	rsync
-
-	//Clear EXCM, set WOE flags
-	rsr	a2, ps
-	movi a3, ~(PS_EXCM_MASK)
-	and	a2, a2, a3
-	movi a3, PS_WOE_MASK
-	or a2, a2, a3
-	wsr	a2, ps
-	rsync
-
-	//Switch to private stack
-	movi a1,panicStack+(255*4)
-	rsil    a2, XCHAL_EXCM_LEVEL            /* disable all low & med ints */
-
-
-	// Debug: output '!' on serport
-	movi a2,0x60000000
-	movi a3,'!'
-	s32i a3,a2,0
-
-	movi a3, panicHandlerRegs
-	l32i a2,a3,0
-	call0 panic_print_hex
-	rsr a2, EXCCAUSE
-	call0 panic_print_hex
-	rsr a2, EXCVADDR
-	call0 panic_print_hex
-	rsr a2,EPC+1
-	call0 panic_print_hex
-	rsr a2,EPC+2
-	call0 panic_print_hex
-	rsr a2,EPC+3
-	call0 panic_print_hex
-	rsr a2,EPC+6
-	call0 panic_print_hex
-	rsr a2,EXCSAVE_1
-	call0 panic_print_hex
-	rsr a2,DEPC
-	call0 panic_print_hex
-
-	//Call panic handler
-//	movi a4, panicHandler
-//	callx4 a4
-	call4 panicHandler
-
-	movi a2,0x60000000
-	movi a3,'d'
-	s32i a3,a2,0
-
-
-1:  j       1b                              /* loop infinitely */
-
-	.align 4
-panicHandlerz:
-	entry a1,32
-	movi a2,0x60000000
-	movi a3,'h'
-	memw
-	s32i a3,a2,0
-	
-	retw
-
-
-	.align 4
-//Call using call0. Prints the hex char in a2. Kills a3, a4, a5
-panic_print_hex:
-	movi a3,0x60000000
-	movi a4,8
-panic_print_hex_loop:
-	l32i a5, a3, 0x1c
-	extui a5, a5, 16, 8
-	bgei a5,64,panic_print_hex_loop
-
-	srli a5,a2,28
-	bgei a5,10,panic_print_hex_a
-	addi a5,a5,'0'
-	j panic_print_hex_ok
-panic_print_hex_a:
-	addi a5,a5,'A'-10
-panic_print_hex_ok:
-	s32i a5,a3,0
-	slli a2,a2,4
-	
-	addi a4,a4,-1
-	bnei a4,0,panic_print_hex_loop
-	movi a5,' '
-	s32i a5,a3,0
-
-	ret
-
-
-
-    .section    .rodata, "a"
-    .align      4
-
-
-
-/*
---------------------------------------------------------------------------------
-    Hooks to dynamically install handlers for exceptions and interrupts.
-    Allows automated regression frameworks to install handlers per test.
-    Consists of an array of function pointers indexed by interrupt level, 
-    with index 0 containing the entry for user exceptions.
-    Initialized with all 0s, meaning no handler is installed at each level.
-    See comment in xtensa_rtos.h for more details.
---------------------------------------------------------------------------------
-*/
-
-    #ifdef XT_INTEXC_HOOKS
-    .data
-    .global     _xt_intexc_hooks
-    .type       _xt_intexc_hooks,@object
-    .align      4
-
-_xt_intexc_hooks:
-    .fill       XT_INTEXC_HOOK_NUM, 4, 0
-    #endif
-
-
-/*
---------------------------------------------------------------------------------
-  EXCEPTION AND LEVEL 1 INTERRUPT VECTORS AND LOW LEVEL HANDLERS
-  (except window exception vectors).
-
-  Each vector goes at a predetermined location according to the Xtensa
-  hardware configuration, which is ensured by its placement in a special
-  section known to the Xtensa linker support package (LSP). It performs
-  the minimum necessary before jumping to the handler in the .text section.
-
-  The corresponding handler goes in the normal .text section. It sets up
-  the appropriate stack frame, saves a few vector-specific registers and
-  calls XT_RTOS_INT_ENTER to save the rest of the interrupted context
-  and enter the RTOS, then sets up a C environment. It then calls the
-  user's interrupt handler code (which may be coded in C) and finally 
-  calls XT_RTOS_INT_EXIT to transfer control to the RTOS for scheduling.
-
-  While XT_RTOS_INT_EXIT does not return directly to the interruptee,
-  eventually the RTOS scheduler will want to dispatch the interrupted
-  task or handler. The scheduler will return to the exit point that was
-  saved in the interrupt stack frame at XT_STK_EXIT.
---------------------------------------------------------------------------------
-*/
-
-
-/*
---------------------------------------------------------------------------------
-Debug Exception.
---------------------------------------------------------------------------------
-*/
-
-#if XCHAL_HAVE_DEBUG
-
-    .begin      literal_prefix .DebugExceptionVector
-    .section    .DebugExceptionVector.text, "ax"
-    .global     _DebugExceptionVector
-    .align      4
-
-_DebugExceptionVector:
-
-    #ifdef XT_SIMULATOR
-    /*
-    In the simulator, let the debugger (if any) handle the debug exception,
-    or simply stop the simulation:
-    */
-    wsr     a2, EXCSAVE+XCHAL_DEBUGLEVEL    /* save a2 where sim expects it */
-    movi    a2, SYS_gdb_enter_sktloop
-    simcall                                 /* have ISS handle debug exc. */
-    #elif 0 /* change condition to 1 to use the HAL minimal debug handler */
-    wsr     a3, EXCSAVE+XCHAL_DEBUGLEVEL
-    movi    a3, xthal_debugexc_defhndlr_nw  /* use default debug handler */
-    jx      a3
-    #else
-    wsr     a0, EXCSAVE+XCHAL_DEBUGLEVEL    /* save original a0 somewhere */
-    call0   _xt_panic                       /* does not return */
-    rfi     XCHAL_DEBUGLEVEL                /* make a0 point here not later */
-    #endif
-
-    .end        literal_prefix
-
-#endif
-
-/*
---------------------------------------------------------------------------------
-Double Exception.
-Double exceptions are not a normal occurrence. They indicate a bug of some kind.
---------------------------------------------------------------------------------
-*/
-
-#ifdef XCHAL_DOUBLEEXC_VECTOR_VADDR
-
-    .begin      literal_prefix .DoubleExceptionVector
-    .section    .DoubleExceptionVector.text, "ax"
-    .global     _DoubleExceptionVector
-    .align      4
-
-_DoubleExceptionVector:
-
-    #if XCHAL_HAVE_DEBUG
-    break   1, 4                            /* unhandled double exception */
-    #endif
-    call0   _xt_panic                       /* does not return */
-    rfde                                    /* make a0 point here not later */
-
-    .end        literal_prefix
-
-#endif /* XCHAL_DOUBLEEXC_VECTOR_VADDR */
-
-/*
---------------------------------------------------------------------------------
-Kernel Exception (including Level 1 Interrupt from kernel mode).
---------------------------------------------------------------------------------
-*/
-
-    .begin      literal_prefix .KernelExceptionVector
-    .section    .KernelExceptionVector.text, "ax"
-    .global     _KernelExceptionVector
-    .align      4
-
-_KernelExceptionVector:
-
-    wsr     a0, EXCSAVE_1                   /* preserve a0 */
-    call0   _xt_kernel_exc                  /* kernel exception handler */
-    /* never returns here - call0 is used as a jump (see note at top) */
-
-    .end        literal_prefix
-
-    .text
-    .align      4
-
-_xt_kernel_exc:
-    #if XCHAL_HAVE_DEBUG
-    break   1, 0                            /* unhandled kernel exception */
-    #endif
-    call0   _xt_panic                       /* does not return */
-    rfe                                     /* make a0 point here not there */
-
-
-/*
---------------------------------------------------------------------------------
-User Exception (including Level 1 Interrupt from user mode).
---------------------------------------------------------------------------------
-*/
-
-    .begin      literal_prefix .UserExceptionVector
-    .section    .UserExceptionVector.text, "ax"
-    .global     _UserExceptionVector
-    .type       _UserExceptionVector,@function
-    .align      4
-
-_UserExceptionVector:
-
-    wsr     a0, EXCSAVE_1                   /* preserve a0 */
-    call0   _xt_user_exc                    /* user exception handler */
-    /* never returns here - call0 is used as a jump (see note at top) */
-
-    .end        literal_prefix
-
-/*
---------------------------------------------------------------------------------
-  Insert some waypoints for jumping beyond the signed 8-bit range of
-  conditional branch instructions, so the conditional branchces to specific
-  exception handlers are not taken in the mainline. Saves some cycles in the
-  mainline.
---------------------------------------------------------------------------------
-*/
-
-    .text
-
-    #if XCHAL_HAVE_WINDOWED
-    .align      4
-_xt_to_alloca_exc:
-    call0   _xt_alloca_exc                  /* in window vectors section */
-    /* never returns here - call0 is used as a jump (see note at top) */
-    #endif
-
-    .align      4
-_xt_to_syscall_exc:
-    call0   _xt_syscall_exc
-    /* never returns here - call0 is used as a jump (see note at top) */
-
-    #if XCHAL_CP_NUM > 0
-    .align      4
-_xt_to_coproc_exc:
-    call0   _xt_coproc_exc
-    /* never returns here - call0 is used as a jump (see note at top) */
-    #endif
-
-
-/*
---------------------------------------------------------------------------------
-  User exception handler.
---------------------------------------------------------------------------------
-*/
-
-    .type       _xt_user_exc,@function
-    .align      4
-
-_xt_user_exc:
-
-    /* If level 1 interrupt then jump to the dispatcher */
-    rsr     a0, EXCCAUSE
-    beqi    a0, EXCCAUSE_LEVEL1INTERRUPT, _xt_lowint1
-
-    /* Handle any coprocessor exceptions. Rely on the fact that exception
-       numbers above EXCCAUSE_CP0_DISABLED all relate to the coprocessors.
-    */
-    #if XCHAL_CP_NUM > 0
-    bgeui   a0, EXCCAUSE_CP0_DISABLED, _xt_to_coproc_exc
-    #endif
-
-    /* Handle alloca and syscall exceptions */
-    #if XCHAL_HAVE_WINDOWED
-    beqi    a0, EXCCAUSE_ALLOCA,  _xt_to_alloca_exc
-    #endif
-    beqi    a0, EXCCAUSE_SYSCALL, _xt_to_syscall_exc
-
-	//HACK! No custom vector stuff, just call panic handler directly. ToDo: remove this when possible. -JD
-	call0 _xt_panic
-
-    /* Handle all other exceptions. All can have user-defined handlers. */
-    /* NOTE: we'll stay on the user stack for exception handling.       */
-
-    /* Allocate exception frame and save minimal context. */
-    mov     a0, sp
-    addi    sp, sp, -XT_STK_FRMSZ
-    s32i    a0, sp, XT_STK_A1
-    #if XCHAL_HAVE_WINDOWED
-    s32e    a0, sp, -12                     /* for debug backtrace */
-    #endif
-    rsr     a0, PS                          /* save interruptee's PS */
-    s32i    a0, sp, XT_STK_PS
-    rsr     a0, EPC_1                       /* save interruptee's PC */
-    s32i    a0, sp, XT_STK_PC
-    rsr     a0, EXCSAVE_1                   /* save interruptee's a0 */
-    s32i    a0, sp, XT_STK_A0
-    #if XCHAL_HAVE_WINDOWED
-    s32e    a0, sp, -16                     /* for debug backtrace */
-    #endif
-    s32i    a12, sp, XT_STK_A12             /* _xt_context_save requires A12- */
-    s32i    a13, sp, XT_STK_A13             /* A13 to have already been saved */
-    call0   _xt_context_save
-
-    /* Save exc cause and vaddr into exception frame */
-    rsr     a0, EXCCAUSE
-    s32i    a0, sp, XT_STK_EXCCAUSE
-    rsr     a0, EXCVADDR
-    s32i    a0, sp, XT_STK_EXCVADDR
-
-    /* Set up PS for C, reenable hi-pri interrupts, and clear EXCM. */
-    #ifdef __XTENSA_CALL0_ABI__
-    movi    a0, PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM
-    #else
-    movi    a0, PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM | PS_WOE
-    #endif
-    wsr     a0, PS
-
-    #ifdef XT_DEBUG_BACKTRACE
-    #ifndef __XTENSA_CALL0_ABI__
-    rsr     a0, EPC_1                       /* return address for debug backtrace */
-    movi    a5, 0xC0000000                  /* constant with top 2 bits set (call size) */
-    rsync                                   /* wait for WSR.PS to complete */
-    or      a0, a0, a5                      /* set top 2 bits */
-    addx2   a0, a5, a0                      /* clear top bit -- thus simulating call4 size */
-    #else
-    rsync                                   /* wait for WSR.PS to complete */
-    #endif
-    #endif
-
-    rsr     a2, EXCCAUSE                    /* recover exc cause */
-
-    #ifdef XT_INTEXC_HOOKS
-    /*
-    Call exception hook to pre-handle exceptions (if installed).
-    Pass EXCCAUSE in a2, and check result in a2 (if -1, skip default handling).
-    */
-    movi    a4, _xt_intexc_hooks
-    l32i    a4, a4, 0                       /* user exception hook index 0 */
-    beqz    a4, 1f
-.Ln_xt_user_exc_call_hook:
-    #ifdef __XTENSA_CALL0_ABI__
-    callx0  a4
-    beqi    a2, -1, .L_xt_user_done
-    #else
-    mov     a6, a2
-    callx4  a4
-    beqi    a6, -1, .L_xt_user_done
-    mov     a2, a6
-    #endif
-1:
-    #endif
-
-    rsr     a2, EXCCAUSE                    /* recover exc cause */
-    movi    a3, _xt_exception_table
-    addx4   a4, a2, a3                      /* a4 = address of exception table entry */
-    l32i    a4, a4, 0                       /* a4 = handler address */
-    #ifdef __XTENSA_CALL0_ABI__
-    mov     a2, sp                          /* a2 = pointer to exc frame */
-    callx0  a4                              /* call handler */
-    #else
-    mov     a6, sp                          /* a6 = pointer to exc frame */
-    callx4  a4                              /* call handler */
-    #endif
-
-.L_xt_user_done:
-
-    /* Restore context and return */
-    call0   _xt_context_restore
-    l32i    a0, sp, XT_STK_PS               /* retrieve interruptee's PS */
-    wsr     a0, PS
-    l32i    a0, sp, XT_STK_PC               /* retrieve interruptee's PC */
-    wsr     a0, EPC_1
-    l32i    a0, sp, XT_STK_A0               /* retrieve interruptee's A0 */
-    l32i    sp, sp, XT_STK_A1               /* remove exception frame */
-    rsync                                   /* ensure PS and EPC written */
-    rfe                                     /* PS.EXCM is cleared */
-
-
-/*
---------------------------------------------------------------------------------
-  Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT
-  on entry and used to return to a thread or interrupted interrupt handler.
---------------------------------------------------------------------------------
-*/
-
-    .global     _xt_user_exit
-    .type       _xt_user_exit,@function
-    .align      4
-_xt_user_exit:
-    l32i    a0, sp, XT_STK_PS               /* retrieve interruptee's PS */
-    wsr     a0, PS
-    l32i    a0, sp, XT_STK_PC               /* retrieve interruptee's PC */
-    wsr     a0, EPC_1
-    l32i    a0, sp, XT_STK_A0               /* retrieve interruptee's A0 */
-    l32i    sp, sp, XT_STK_A1               /* remove interrupt stack frame */
-    rsync                                   /* ensure PS and EPC written */
-    rfe                                     /* PS.EXCM is cleared */
-
-
-/*
---------------------------------------------------------------------------------
-Syscall Exception Handler (jumped to from User Exception Handler).
-Syscall 0 is required to spill the register windows (no-op in Call 0 ABI).
-Only syscall 0 is handled here. Other syscalls return -1 to caller in a2.
---------------------------------------------------------------------------------
-*/
-
-    .text
-    .type       _xt_syscall_exc,@function
-    .align      4
-_xt_syscall_exc:
-
-    #ifdef __XTENSA_CALL0_ABI__
-    /*
-    Save minimal regs for scratch. Syscall 0 does nothing in Call0 ABI.
-    Use a minimal stack frame (16B) to save A2 & A3 for scratch.
-    PS.EXCM could be cleared here, but unlikely to improve worst-case latency.
-    rsr     a0, PS
-    addi    a0, a0, -PS_EXCM_MASK
-    wsr     a0, PS
-    */
-    addi    sp, sp, -16
-    s32i    a2, sp, 8
-    s32i    a3, sp, 12
-    #else   /* Windowed ABI */
-    /*
-    Save necessary context and spill the register windows.
-    PS.EXCM is still set and must remain set until after the spill.
-    Reuse context save function though it saves more than necessary.
-    For this reason, a full interrupt stack frame is allocated.
-    */
-    addi    sp, sp, -XT_STK_FRMSZ           /* allocate interrupt stack frame */
-    s32i    a12, sp, XT_STK_A12             /* _xt_context_save requires A12- */
-    s32i    a13, sp, XT_STK_A13             /* A13 to have already been saved */
-    call0   _xt_context_save
-    #endif
-
-    /*
-    Grab the interruptee's PC and skip over the 'syscall' instruction.
-    If it's at the end of a zero-overhead loop and it's not on the last
-    iteration, decrement loop counter and skip to beginning of loop.
-    */
-    rsr     a2, EPC_1                       /* a2 = PC of 'syscall' */
-    addi    a3, a2, 3                       /* ++PC                 */
-    #if XCHAL_HAVE_LOOPS
-    rsr     a0, LEND                        /* if (PC == LEND       */
-    bne     a3, a0, 1f
-    rsr     a0, LCOUNT                      /*     && LCOUNT != 0)  */
-    beqz    a0, 1f                          /* {                    */
-    addi    a0, a0, -1                      /*   --LCOUNT           */
-    rsr     a3, LBEG                        /*   PC = LBEG          */
-    wsr     a0, LCOUNT                      /* }                    */
-    #endif
-1:  wsr     a3, EPC_1                       /* update PC            */
-
-    /* Restore interruptee's context and return from exception. */
-    #ifdef __XTENSA_CALL0_ABI__
-    l32i    a2, sp, 8
-    l32i    a3, sp, 12
-    addi    sp, sp, 16
-    #else
-    call0   _xt_context_restore
-    addi    sp, sp, XT_STK_FRMSZ
-    #endif
-    movi    a0, -1
-    movnez  a2, a0, a2                      /* return -1 if not syscall 0 */
-    rsr     a0, EXCSAVE_1
-    rfe
-
-/*
---------------------------------------------------------------------------------
-Co-Processor Exception Handler (jumped to from User Exception Handler).
-These exceptions are generated by co-processor instructions, which are only
-allowed in thread code (not in interrupts or kernel code). This restriction is 
-deliberately imposed to reduce the burden of state-save/restore in interrupts.
---------------------------------------------------------------------------------
-*/
-#if XCHAL_CP_NUM > 0
-
-    .section .rodata, "a"
-
-/* Offset to CP n save area in thread's CP save area. */
-    .global _xt_coproc_sa_offset
-    .type   _xt_coproc_sa_offset,@object
-    .align  16                      /* minimize crossing cache boundaries */
-_xt_coproc_sa_offset:
-    .word   XT_CP0_SA, XT_CP1_SA, XT_CP2_SA, XT_CP3_SA
-    .word   XT_CP4_SA, XT_CP5_SA, XT_CP6_SA, XT_CP7_SA
-
-/* Bitmask for CP n's CPENABLE bit. */
-    .type   _xt_coproc_mask,@object
-    .align  16,,8                   /* try to keep it all in one cache line */
-    .set    i, 0
-_xt_coproc_mask:
-    .rept   XCHAL_CP_MAX
-    .long   (i<<16) | (1<<i)    // upper 16-bits = i, lower = bitmask
-    .set    i, i+1
-    .endr
-
-    .data
-
-/* Owner thread of CP n, identified by thread's CP save area (0 = unowned). */
-    .global _xt_coproc_owner_sa
-    .type   _xt_coproc_owner_sa,@object
-    .align  16,,XCHAL_CP_MAX<<2     /* minimize crossing cache boundaries */
-_xt_coproc_owner_sa:
-    .space  XCHAL_CP_MAX << 2
-
-    .text
-
-
-    .align  4
-.L_goto_invalid:
-    j   .L_xt_coproc_invalid    /* not in a thread (invalid) */
-    .align  4
-.L_goto_done:
-    j   .L_xt_coproc_done
-
-
-/*
---------------------------------------------------------------------------------
-  Coprocessor exception handler.
-  At entry, only a0 has been saved (in EXCSAVE_1).
---------------------------------------------------------------------------------
-*/
-
-    .type   _xt_coproc_exc,@function
-    .align  4
-
-_xt_coproc_exc:
-
-    /* Allocate interrupt stack frame and save minimal context. */
-    mov     a0, sp                          /* sp == a1 */
-    addi    sp, sp, -XT_STK_FRMSZ           /* allocate interrupt stack frame */
-    s32i    a0, sp, XT_STK_A1               /* save pre-interrupt SP */
-    #if XCHAL_HAVE_WINDOWED
-    s32e    a0, sp, -12                     /* for debug backtrace */
-    #endif
-    rsr     a0, PS                          /* save interruptee's PS */
-    s32i    a0, sp, XT_STK_PS
-    rsr     a0, EPC_1                       /* save interruptee's PC */
-    s32i    a0, sp, XT_STK_PC
-    rsr     a0, EXCSAVE_1                   /* save interruptee's a0 */
-    s32i    a0, sp, XT_STK_A0
-    #if XCHAL_HAVE_WINDOWED
-    s32e    a0, sp, -16                     /* for debug backtrace */
-    #endif
-    movi    a0, _xt_user_exit               /* save exit point for dispatch */
-    s32i    a0, sp, XT_STK_EXIT
-
-    rsr     a0, EXCCAUSE
-    s32i    a5, sp, XT_STK_A5               /* save a5 */
-    addi    a5, a0, -EXCCAUSE_CP0_DISABLED  /* a5 = CP index */
-
-    /* Save a few more of interruptee's registers (a5 was already saved). */
-    s32i    a2,  sp, XT_STK_A2
-    s32i    a3,  sp, XT_STK_A3
-    s32i    a4,  sp, XT_STK_A4
-    s32i    a15, sp, XT_STK_A15
-
-    /* Get co-processor state save area of new owner thread. */
-    call0   XT_RTOS_CP_STATE                /* a15 = new owner's save area */
-    beqz    a15, .L_goto_invalid            /* not in a thread (invalid) */
-
-    /* Enable the co-processor's bit in CPENABLE. */
-    movi    a0, _xt_coproc_mask
-    rsr     a4, CPENABLE                    /* a4 = CPENABLE */
-    addx4   a0, a5, a0                      /* a0 = &_xt_coproc_mask[n] */
-    l32i    a0, a0, 0                       /* a0 = (n << 16) | (1 << n) */
-    movi    a3, _xt_coproc_owner_sa     /* (placed here for load slot) */
-    extui   a2, a0, 0, 16                   /* coprocessor bitmask portion */
-    or      a4, a4, a2                      /* a4 = CPENABLE | (1 << n) */
-    wsr     a4, CPENABLE
-
-    /* Get old coprocessor owner thread (save area ptr) and assign new one.  */
-    addx4   a3,  a5, a3                      /* a3 = &_xt_coproc_owner_sa[n] */
-    l32i    a2,  a3, 0                       /* a2 = old owner's save area */
-    s32i    a15, a3, 0                       /* _xt_coproc_owner_sa[n] = new */
-    rsync                                    /* ensure wsr.CPENABLE is complete */
-
-    /* Only need to context switch if new owner != old owner. */
-    beq     a15, a2, .L_goto_done           /* new owner == old, we're done */
-
-    /* If no old owner then nothing to save. */
-    beqz    a2, .L_check_new
-
-    /* If old owner not actively using CP then nothing to save. */
-    l16ui   a4,  a2,  XT_CPENABLE           /* a4 = old owner's CPENABLE */
-    bnone   a4,  a0,  .L_check_new          /* old owner not using CP    */
-
-.L_save_old:
-    /* Save old owner's coprocessor state. */
-
-    movi    a5, _xt_coproc_sa_offset
-
-    /* Mark old owner state as no longer active (CPENABLE bit n clear). */
-    xor     a4,  a4,  a0                    /* clear CP bit in CPENABLE    */
-    s16i    a4,  a2,  XT_CPENABLE           /* update old owner's CPENABLE */
-
-    extui   a4,  a0,  16,  5                /* a4 = CP index = n */
-    addx4   a5,  a4,  a5                    /* a5 = &_xt_coproc_sa_offset[n] */
-
-    /* Mark old owner state as saved (CPSTORED bit n set). */
-    l16ui   a4,  a2,  XT_CPSTORED           /* a4 = old owner's CPSTORED */
-    l32i    a5,  a5,  0                     /* a5 = XT_CP[n]_SA offset */
-    or      a4,  a4,  a0                    /* set CP in old owner's CPSTORED */
-    s16i    a4,  a2,  XT_CPSTORED           /* update old owner's CPSTORED */
-    l32i    a2, a2, XT_CP_ASA               /* ptr to actual (aligned) save area */
-    extui   a3, a0, 16, 5                   /* a3 = CP index = n */
-    add     a2, a2, a5                      /* a2 = old owner's area for CP n */
-
-    /*
-    The config-specific HAL macro invoked below destroys a2-5, preserves a0-1.
-    It is theoretically possible for Xtensa processor designers to write TIE 
-    that causes more address registers to be affected, but it is generally 
-    unlikely. If that ever happens, more registers needs to be saved/restored
-    around this macro invocation, and the value in a15 needs to be recomputed.
-    */
-    xchal_cpi_store_funcbody
-
-.L_check_new:
-    /* Check if any state has to be restored for new owner. */
-    /* NOTE: a15 = new owner's save area, cannot be zero when we get here. */
-
-    l16ui   a3,  a15, XT_CPSTORED           /* a3 = new owner's CPSTORED */
-    movi    a4, _xt_coproc_sa_offset
-    bnone   a3,  a0,  .L_check_cs           /* full CP not saved, check callee-saved */
-    xor     a3,  a3,  a0                    /* CPSTORED bit is set, clear it */
-    s16i    a3,  a15, XT_CPSTORED           /* update new owner's CPSTORED */
-
-    /* Adjust new owner's save area pointers to area for CP n. */
-    extui   a3,  a0, 16, 5                  /* a3 = CP index = n */
-    addx4   a4,  a3, a4                     /* a4 = &_xt_coproc_sa_offset[n] */
-    l32i    a4,  a4, 0                      /* a4 = XT_CP[n]_SA */
-    l32i    a5, a15, XT_CP_ASA              /* ptr to actual (aligned) save area */
-    add     a2,  a4, a5                     /* a2 = new owner's area for CP */
-
-    /*
-    The config-specific HAL macro invoked below destroys a2-5, preserves a0-1.
-    It is theoretically possible for Xtensa processor designers to write TIE 
-    that causes more address registers to be affected, but it is generally 
-    unlikely. If that ever happens, more registers needs to be saved/restored
-    around this macro invocation.
-    */
-    xchal_cpi_load_funcbody
-
-    /* Restore interruptee's saved registers. */
-    /* Can omit rsync for wsr.CPENABLE here because _xt_user_exit does it. */
-.L_xt_coproc_done:
-    l32i    a15, sp, XT_STK_A15
-    l32i    a5,  sp, XT_STK_A5
-    l32i    a4,  sp, XT_STK_A4
-    l32i    a3,  sp, XT_STK_A3
-    l32i    a2,  sp, XT_STK_A2
-    call0   _xt_user_exit                   /* return via exit dispatcher */
-    /* Never returns here - call0 is used as a jump (see note at top) */
-
-.L_check_cs:
-    /* a0 = CP mask in low bits, a15 = new owner's save area */
-    l16ui   a2, a15, XT_CP_CS_ST            /* a2 = mask of CPs saved    */
-    bnone   a2,  a0, .L_xt_coproc_done      /* if no match then done     */
-    and     a2,  a2, a0                     /* a2 = which CPs to restore */
-    extui   a2,  a2, 0, 8                   /* extract low 8 bits        */
-    s32i    a6,  sp, XT_STK_A6              /* save extra needed regs    */
-    s32i    a7,  sp, XT_STK_A7
-    s32i    a13, sp, XT_STK_A13
-    s32i    a14, sp, XT_STK_A14
-    call0   _xt_coproc_restorecs            /* restore CP registers      */
-    l32i    a6,  sp, XT_STK_A6              /* restore saved registers   */
-    l32i    a7,  sp, XT_STK_A7
-    l32i    a13, sp, XT_STK_A13
-    l32i    a14, sp, XT_STK_A14
-    j       .L_xt_coproc_done
-
-    /* Co-processor exception occurred outside a thread (not supported). */
-.L_xt_coproc_invalid:
-    #if XCHAL_HAVE_DEBUG
-    break   1, 1                            /* unhandled user exception */
-    #endif
-    call0   _xt_panic                       /* not in a thread (invalid) */
-    /* never returns */
-
-
-#endif /* XCHAL_CP_NUM */
-
-
-/*
--------------------------------------------------------------------------------
-  Level 1 interrupt dispatch. Assumes stack frame has not been allocated yet.
--------------------------------------------------------------------------------
-*/
-
-    .text   
-    .type       _xt_lowint1,@function
-    .align      4
-
-_xt_lowint1:
-    mov     a0, sp                          /* sp == a1 */
-    addi    sp, sp, -XT_STK_FRMSZ           /* allocate interrupt stack frame */
-    s32i    a0, sp, XT_STK_A1               /* save pre-interrupt SP */
-    rsr     a0, PS                          /* save interruptee's PS */
-    s32i    a0, sp, XT_STK_PS
-    rsr     a0, EPC_1                       /* save interruptee's PC */
-    s32i    a0, sp, XT_STK_PC
-    rsr     a0, EXCSAVE_1                   /* save interruptee's a0 */
-    s32i    a0, sp, XT_STK_A0
-    movi    a0, _xt_user_exit               /* save exit point for dispatch */
-    s32i    a0, sp, XT_STK_EXIT
-
-    /* Save rest of interrupt context and enter RTOS. */
-    call0   XT_RTOS_INT_ENTER               /* common RTOS interrupt entry */
-
-    /* !! We are now on the RTOS system stack !! */ 
-
-    /* Set up PS for C, enable interrupts above this level and clear EXCM. */
-    #ifdef __XTENSA_CALL0_ABI__
-    movi    a0, PS_INTLEVEL(1) | PS_UM
-    #else 
-    movi    a0, PS_INTLEVEL(1) | PS_UM | PS_WOE
-    #endif
-    wsr     a0, PS
-    rsync
-
-    /* OK to call C code at this point, dispatch user ISRs */
-
-    dispatch_c_isr 1 XCHAL_INTLEVEL1_MASK
-
-    /* Done handling interrupts, transfer control to OS */
-    call0   XT_RTOS_INT_EXIT                /* does not return directly here */
-
-
-/*
--------------------------------------------------------------------------------
-  MEDIUM PRIORITY (LEVEL 2+) INTERRUPT VECTORS AND LOW LEVEL HANDLERS.
-
-  Medium priority interrupts are by definition those with priority greater
-  than 1 and not greater than XCHAL_EXCM_LEVEL. These are disabled by
-  setting PS.EXCM and therefore can easily support a C environment for
-  handlers in C, and interact safely with an RTOS.
-
-  Each vector goes at a predetermined location according to the Xtensa
-  hardware configuration, which is ensured by its placement in a special
-  section known to the Xtensa linker support package (LSP). It performs
-  the minimum necessary before jumping to the handler in the .text section.
-
-  The corresponding handler goes in the normal .text section. It sets up
-  the appropriate stack frame, saves a few vector-specific registers and
-  calls XT_RTOS_INT_ENTER to save the rest of the interrupted context
-  and enter the RTOS, then sets up a C environment. It then calls the
-  user's interrupt handler code (which may be coded in C) and finally 
-  calls XT_RTOS_INT_EXIT to transfer control to the RTOS for scheduling.
-
-  While XT_RTOS_INT_EXIT does not return directly to the interruptee,
-  eventually the RTOS scheduler will want to dispatch the interrupted
-  task or handler. The scheduler will return to the exit point that was
-  saved in the interrupt stack frame at XT_STK_EXIT.
--------------------------------------------------------------------------------
-*/
-
-#if XCHAL_EXCM_LEVEL >= 2
-
-    .begin      literal_prefix .Level2InterruptVector
-    .section    .Level2InterruptVector.text, "ax"
-    .global     _Level2Vector
-    .type       _Level2Vector,@function
-    .align      4
-_Level2Vector:
-    wsr     a0, EXCSAVE_2                   /* preserve a0 */
-    call0   _xt_medint2                     /* load interrupt handler */
-    /* never returns here - call0 is used as a jump (see note at top) */
-
-    .end        literal_prefix
-
-    .text
-    .type       _xt_medint2,@function
-    .align      4
-_xt_medint2:
-    mov     a0, sp                          /* sp == a1 */
-    addi    sp, sp, -XT_STK_FRMSZ           /* allocate interrupt stack frame */
-    s32i    a0, sp, XT_STK_A1               /* save pre-interrupt SP */
-    rsr     a0, EPS_2                       /* save interruptee's PS */
-    s32i    a0, sp, XT_STK_PS
-    rsr     a0, EPC_2                       /* save interruptee's PC */
-    s32i    a0, sp, XT_STK_PC
-    rsr     a0, EXCSAVE_2                   /* save interruptee's a0 */
-    s32i    a0, sp, XT_STK_A0
-    movi    a0, _xt_medint2_exit            /* save exit point for dispatch */
-    s32i    a0, sp, XT_STK_EXIT
-
-    /* Save rest of interrupt context and enter RTOS. */
-    call0   XT_RTOS_INT_ENTER               /* common RTOS interrupt entry */
-
-    /* !! We are now on the RTOS system stack !! */
-
-    /* Set up PS for C, enable interrupts above this level and clear EXCM. */
-    #ifdef __XTENSA_CALL0_ABI__
-    movi    a0, PS_INTLEVEL(2) | PS_UM
-    #else
-    movi    a0, PS_INTLEVEL(2) | PS_UM | PS_WOE
-    #endif
-    wsr     a0, PS
-    rsync
-
-    /* OK to call C code at this point, dispatch user ISRs */
-
-    dispatch_c_isr 2 XCHAL_INTLEVEL2_MASK
-
-    /* Done handling interrupts, transfer control to OS */
-    call0   XT_RTOS_INT_EXIT                /* does not return directly here */
-
-    /*
-    Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT
-    on entry and used to return to a thread or interrupted interrupt handler.
-    */
-    .global     _xt_medint2_exit
-    .type       _xt_medint2_exit,@function
-    .align      4
-_xt_medint2_exit:
-    /* Restore only level-specific regs (the rest were already restored) */
-    l32i    a0, sp, XT_STK_PS               /* retrieve interruptee's PS */
-    wsr     a0, EPS_2
-    l32i    a0, sp, XT_STK_PC               /* retrieve interruptee's PC */
-    wsr     a0, EPC_2
-    l32i    a0, sp, XT_STK_A0               /* retrieve interruptee's A0 */
-    l32i    sp, sp, XT_STK_A1               /* remove interrupt stack frame */
-    rsync                                   /* ensure EPS and EPC written */
-    rfi     2
-
-#endif  /* Level 2 */
-
-#if XCHAL_EXCM_LEVEL >= 3
-
-    .begin      literal_prefix .Level3InterruptVector
-    .section    .Level3InterruptVector.text, "ax"
-    .global     _Level3Vector
-    .type       _Level3Vector,@function
-    .align      4
-_Level3Vector:
-    wsr     a0, EXCSAVE_3                   /* preserve a0 */
-    call0   _xt_medint3                     /* load interrupt handler */
-    /* never returns here - call0 is used as a jump (see note at top) */
-
-    .end        literal_prefix
-
-    .text
-    .type       _xt_medint3,@function
-    .align      4
-_xt_medint3:
-    mov     a0, sp                          /* sp == a1 */
-    addi    sp, sp, -XT_STK_FRMSZ           /* allocate interrupt stack frame */
-    s32i    a0, sp, XT_STK_A1               /* save pre-interrupt SP */
-    rsr     a0, EPS_3                       /* save interruptee's PS */
-    s32i    a0, sp, XT_STK_PS
-    rsr     a0, EPC_3                       /* save interruptee's PC */
-    s32i    a0, sp, XT_STK_PC
-    rsr     a0, EXCSAVE_3                   /* save interruptee's a0 */
-    s32i    a0, sp, XT_STK_A0
-    movi    a0, _xt_medint3_exit            /* save exit point for dispatch */
-    s32i    a0, sp, XT_STK_EXIT
-
-    /* Save rest of interrupt context and enter RTOS. */
-    call0   XT_RTOS_INT_ENTER               /* common RTOS interrupt entry */
-
-    /* !! We are now on the RTOS system stack !! */
-
-    /* Set up PS for C, enable interrupts above this level and clear EXCM. */
-    #ifdef __XTENSA_CALL0_ABI__
-    movi    a0, PS_INTLEVEL(3) | PS_UM
-    #else
-    movi    a0, PS_INTLEVEL(3) | PS_UM | PS_WOE
-    #endif
-    wsr     a0, PS
-    rsync
-
-    /* OK to call C code at this point, dispatch user ISRs */
-
-    dispatch_c_isr 3 XCHAL_INTLEVEL3_MASK
-
-    /* Done handling interrupts, transfer control to OS */
-    call0   XT_RTOS_INT_EXIT                /* does not return directly here */
-
-    /*
-    Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT
-    on entry and used to return to a thread or interrupted interrupt handler.
-    */
-    .global     _xt_medint3_exit
-    .type       _xt_medint3_exit,@function
-    .align      4
-_xt_medint3_exit:
-    /* Restore only level-specific regs (the rest were already restored) */
-    l32i    a0, sp, XT_STK_PS               /* retrieve interruptee's PS */
-    wsr     a0, EPS_3
-    l32i    a0, sp, XT_STK_PC               /* retrieve interruptee's PC */
-    wsr     a0, EPC_3
-    l32i    a0, sp, XT_STK_A0               /* retrieve interruptee's A0 */
-    l32i    sp, sp, XT_STK_A1               /* remove interrupt stack frame */
-    rsync                                   /* ensure EPS and EPC written */
-    rfi     3
-
-#endif  /* Level 3 */
-
-#if XCHAL_EXCM_LEVEL >= 4
-
-    .begin      literal_prefix .Level4InterruptVector
-    .section    .Level4InterruptVector.text, "ax"
-    .global     _Level4Vector
-    .type       _Level4Vector,@function
-    .align      4
-_Level4Vector:
-    wsr     a0, EXCSAVE_4                   /* preserve a0 */
-    call0   _xt_medint4                     /* load interrupt handler */
-
-    .end        literal_prefix
-
-    .text
-    .type       _xt_medint4,@function
-    .align      4
-_xt_medint4:
-    mov     a0, sp                          /* sp == a1 */
-    addi    sp, sp, -XT_STK_FRMSZ           /* allocate interrupt stack frame */
-    s32i    a0, sp, XT_STK_A1               /* save pre-interrupt SP */
-    rsr     a0, EPS_4                       /* save interruptee's PS */
-    s32i    a0, sp, XT_STK_PS
-    rsr     a0, EPC_4                       /* save interruptee's PC */
-    s32i    a0, sp, XT_STK_PC
-    rsr     a0, EXCSAVE_4                   /* save interruptee's a0 */
-    s32i    a0, sp, XT_STK_A0
-    movi    a0, _xt_medint4_exit            /* save exit point for dispatch */
-    s32i    a0, sp, XT_STK_EXIT
-
-    /* Save rest of interrupt context and enter RTOS. */
-    call0   XT_RTOS_INT_ENTER               /* common RTOS interrupt entry */
-
-    /* !! We are now on the RTOS system stack !! */
-
-    /* Set up PS for C, enable interrupts above this level and clear EXCM. */
-    #ifdef __XTENSA_CALL0_ABI__
-    movi    a0, PS_INTLEVEL(4) | PS_UM
-    #else
-    movi    a0, PS_INTLEVEL(4) | PS_UM | PS_WOE
-    #endif
-    wsr     a0, PS
-    rsync
-
-    /* OK to call C code at this point, dispatch user ISRs */
-
-    dispatch_c_isr 4 XCHAL_INTLEVEL4_MASK
-
-    /* Done handling interrupts, transfer control to OS */
-    call0   XT_RTOS_INT_EXIT                /* does not return directly here */
-
-    /*
-    Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT
-    on entry and used to return to a thread or interrupted interrupt handler.
-    */
-    .global     _xt_medint4_exit
-    .type       _xt_medint4_exit,@function
-    .align      4
-_xt_medint4_exit:
-    /* Restore only level-specific regs (the rest were already restored) */
-    l32i    a0, sp, XT_STK_PS               /* retrieve interruptee's PS */
-    wsr     a0, EPS_4
-    l32i    a0, sp, XT_STK_PC               /* retrieve interruptee's PC */
-    wsr     a0, EPC_4
-    l32i    a0, sp, XT_STK_A0               /* retrieve interruptee's A0 */
-    l32i    sp, sp, XT_STK_A1               /* remove interrupt stack frame */
-    rsync                                   /* ensure EPS and EPC written */
-    rfi     4
-
-#endif  /* Level 4 */
-
-#if XCHAL_EXCM_LEVEL >= 5
-
-    .begin      literal_prefix .Level5InterruptVector
-    .section    .Level5InterruptVector.text, "ax"
-    .global     _Level5Vector
-    .type       _Level5Vector,@function
-    .align      4
-_Level5Vector:
-    wsr     a0, EXCSAVE_5                   /* preserve a0 */
-    call0   _xt_medint5                     /* load interrupt handler */
-
-    .end        literal_prefix
-
-    .text
-    .type       _xt_medint5,@function
-    .align      4
-_xt_medint5:
-    mov     a0, sp                          /* sp == a1 */
-    addi    sp, sp, -XT_STK_FRMSZ           /* allocate interrupt stack frame */
-    s32i    a0, sp, XT_STK_A1               /* save pre-interrupt SP */
-    rsr     a0, EPS_5                       /* save interruptee's PS */
-    s32i    a0, sp, XT_STK_PS
-    rsr     a0, EPC_5                       /* save interruptee's PC */
-    s32i    a0, sp, XT_STK_PC
-    rsr     a0, EXCSAVE_5                   /* save interruptee's a0 */
-    s32i    a0, sp, XT_STK_A0
-    movi    a0, _xt_medint5_exit            /* save exit point for dispatch */
-    s32i    a0, sp, XT_STK_EXIT
-
-    /* Save rest of interrupt context and enter RTOS. */
-    call0   XT_RTOS_INT_ENTER               /* common RTOS interrupt entry */
-
-    /* !! We are now on the RTOS system stack !! */
-
-    /* Set up PS for C, enable interrupts above this level and clear EXCM. */
-    #ifdef __XTENSA_CALL0_ABI__
-    movi    a0, PS_INTLEVEL(5) | PS_UM
-    #else
-    movi    a0, PS_INTLEVEL(5) | PS_UM | PS_WOE
-    #endif
-    wsr     a0, PS
-    rsync
-
-    /* OK to call C code at this point, dispatch user ISRs */
-
-    dispatch_c_isr 5 XCHAL_INTLEVEL5_MASK
-
-    /* Done handling interrupts, transfer control to OS */
-    call0   XT_RTOS_INT_EXIT                /* does not return directly here */
-
-    /*
-    Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT
-    on entry and used to return to a thread or interrupted interrupt handler.
-    */
-    .global     _xt_medint5_exit
-    .type       _xt_medint5_exit,@function
-    .align      4
-_xt_medint5_exit:
-    /* Restore only level-specific regs (the rest were already restored) */
-    l32i    a0, sp, XT_STK_PS               /* retrieve interruptee's PS */
-    wsr     a0, EPS_5
-    l32i    a0, sp, XT_STK_PC               /* retrieve interruptee's PC */
-    wsr     a0, EPC_5
-    l32i    a0, sp, XT_STK_A0               /* retrieve interruptee's A0 */
-    l32i    sp, sp, XT_STK_A1               /* remove interrupt stack frame */
-    rsync                                   /* ensure EPS and EPC written */
-    rfi     5
-
-#endif  /* Level 5 */
-
-#if XCHAL_EXCM_LEVEL >= 6
-
-    .begin      literal_prefix .Level6InterruptVector
-    .section    .Level6InterruptVector.text, "ax"
-    .global     _Level6Vector
-    .type       _Level6Vector,@function
-    .align      4
-_Level6Vector:
-    wsr     a0, EXCSAVE_6                   /* preserve a0 */
-    call0   _xt_medint6                     /* load interrupt handler */
-
-    .end        literal_prefix
-
-    .text
-    .type       _xt_medint6,@function
-    .align      4
-_xt_medint6:
-    mov     a0, sp                          /* sp == a1 */
-    addi    sp, sp, -XT_STK_FRMSZ           /* allocate interrupt stack frame */
-    s32i    a0, sp, XT_STK_A1               /* save pre-interrupt SP */
-    rsr     a0, EPS_6                       /* save interruptee's PS */
-    s32i    a0, sp, XT_STK_PS
-    rsr     a0, EPC_6                       /* save interruptee's PC */
-    s32i    a0, sp, XT_STK_PC
-    rsr     a0, EXCSAVE_6                   /* save interruptee's a0 */
-    s32i    a0, sp, XT_STK_A0
-    movi    a0, _xt_medint6_exit            /* save exit point for dispatch */
-    s32i    a0, sp, XT_STK_EXIT
-
-    /* Save rest of interrupt context and enter RTOS. */
-    call0   XT_RTOS_INT_ENTER               /* common RTOS interrupt entry */
-
-    /* !! We are now on the RTOS system stack !! */
-
-    /* Set up PS for C, enable interrupts above this level and clear EXCM. */
-    #ifdef __XTENSA_CALL0_ABI__
-    movi    a0, PS_INTLEVEL(6) | PS_UM
-    #else
-    movi    a0, PS_INTLEVEL(6) | PS_UM | PS_WOE
-    #endif
-    wsr     a0, PS
-    rsync
-
-    /* OK to call C code at this point, dispatch user ISRs */
-
-    dispatch_c_isr 6 XCHAL_INTLEVEL6_MASK
-
-    /* Done handling interrupts, transfer control to OS */
-    call0   XT_RTOS_INT_EXIT                /* does not return directly here */
-
-    /*
-    Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT
-    on entry and used to return to a thread or interrupted interrupt handler.
-    */
-    .global     _xt_medint6_exit
-    .type       _xt_medint6_exit,@function
-    .align      4
-_xt_medint6_exit:
-    /* Restore only level-specific regs (the rest were already restored) */
-    l32i    a0, sp, XT_STK_PS               /* retrieve interruptee's PS */
-    wsr     a0, EPS_6
-    l32i    a0, sp, XT_STK_PC               /* retrieve interruptee's PC */
-    wsr     a0, EPC_6
-    l32i    a0, sp, XT_STK_A0               /* retrieve interruptee's A0 */
-    l32i    sp, sp, XT_STK_A1               /* remove interrupt stack frame */
-    rsync                                   /* ensure EPS and EPC written */
-    rfi     6
-
-#endif  /* Level 6 */
-
-
-/*******************************************************************************
-
-HIGH PRIORITY (LEVEL > XCHAL_EXCM_LEVEL) INTERRUPT VECTORS AND HANDLERS
-
-High priority interrupts are by definition those with priorities greater
-than XCHAL_EXCM_LEVEL. This includes non-maskable (NMI). High priority
-interrupts cannot interact with the RTOS, that is they must save all regs
-they use and not call any RTOS function.
-
-A further restriction imposed by the Xtensa windowed architecture is that
-high priority interrupts must not modify the stack area even logically
-"above" the top of the interrupted stack (they need to provide their
-own stack or static save area).
-
-Cadence Design Systems recommends high priority interrupt handlers be coded in assembly
-and used for purposes requiring very short service times.
-
-Here are templates for high priority (level 2+) interrupt vectors.
-They assume only one interrupt per level to avoid the burden of identifying
-which interrupts at this level are pending and enabled. This allows for 
-minimum latency and avoids having to save/restore a2 in addition to a0.
-If more than one interrupt per high priority level is configured, this burden
-is on the handler which in any case must provide a way to save and restore
-registers it uses without touching the interrupted stack.
-
-Each vector goes at a predetermined location according to the Xtensa
-hardware configuration, which is ensured by its placement in a special
-section known to the Xtensa linker support package (LSP). It performs
-the minimum necessary before jumping to the handler in the .text section.
-
-*******************************************************************************/
-
-/*
-Currently only shells for high priority interrupt handlers are provided
-here. However a template and example can be found in the Cadence Design Systems tools
-documentation: "Microprocessor Programmer's Guide".
-*/
-
-#if XCHAL_NUM_INTLEVELS >=2 && XCHAL_EXCM_LEVEL <2 && XCHAL_DEBUGLEVEL !=2
-
-    .begin      literal_prefix .Level2InterruptVector
-    .section    .Level2InterruptVector.text, "ax"
-    .global     _Level2Vector
-    .type       _Level2Vector,@function
-    .align      4
-_Level2Vector:
-    wsr     a0, EXCSAVE_2                   /* preserve a0 */
-    call0   _xt_highint2                    /* load interrupt handler */
-
-    .end        literal_prefix
-
-    .text
-    .type       _xt_highint2,@function
-    .align      4
-_xt_highint2:
-
-    #ifdef XT_INTEXC_HOOKS
-    /* Call interrupt hook if present to (pre)handle interrupts. */
-    movi    a0, _xt_intexc_hooks
-    l32i    a0, a0, 2<<2
-    beqz    a0, 1f
-.Ln_xt_highint2_call_hook:
-    callx0  a0                              /* must NOT disturb stack! */
-1:
-    #endif
-
-    /* USER_EDIT:
-    ADD HIGH PRIORITY LEVEL 2 INTERRUPT HANDLER CODE HERE.
-    */
-
-    .align  4
-.L_xt_highint2_exit:
-    rsr     a0, EXCSAVE_2                   /* restore a0 */
-    rfi     2
-
-#endif  /* Level 2 */
-
-#if XCHAL_NUM_INTLEVELS >=3 && XCHAL_EXCM_LEVEL <3 && XCHAL_DEBUGLEVEL !=3
-
-    .begin      literal_prefix .Level3InterruptVector
-    .section    .Level3InterruptVector.text, "ax"
-    .global     _Level3Vector
-    .type       _Level3Vector,@function
-    .align      4
-_Level3Vector:
-    wsr     a0, EXCSAVE_3                   /* preserve a0 */
-    call0   _xt_highint3                    /* load interrupt handler */
-    /* never returns here - call0 is used as a jump (see note at top) */
-
-    .end        literal_prefix
-
-    .text
-    .type       _xt_highint3,@function
-    .align      4
-_xt_highint3:
-
-    #ifdef XT_INTEXC_HOOKS
-    /* Call interrupt hook if present to (pre)handle interrupts. */
-    movi    a0, _xt_intexc_hooks
-    l32i    a0, a0, 3<<2
-    beqz    a0, 1f
-.Ln_xt_highint3_call_hook:
-    callx0  a0                              /* must NOT disturb stack! */
-1:
-    #endif
-
-    /* USER_EDIT:
-    ADD HIGH PRIORITY LEVEL 3 INTERRUPT HANDLER CODE HERE.
-    */
-
-    .align  4
-.L_xt_highint3_exit:
-    rsr     a0, EXCSAVE_3                   /* restore a0 */
-    rfi     3
-
-#endif  /* Level 3 */
-
-#if XCHAL_NUM_INTLEVELS >=4 && XCHAL_EXCM_LEVEL <4 && XCHAL_DEBUGLEVEL !=4
-
-    .begin      literal_prefix .Level4InterruptVector
-    .section    .Level4InterruptVector.text, "ax"
-    .global     _Level4Vector
-    .type       _Level4Vector,@function
-    .align      4
-_Level4Vector:
-    wsr     a0, EXCSAVE_4                   /* preserve a0 */
-    call0   _xt_highint4                    /* load interrupt handler */
-    /* never returns here - call0 is used as a jump (see note at top) */
-
-    .end        literal_prefix
-
-    .text
-    .type       _xt_highint4,@function
-    .align      4
-_xt_highint4:
-
-    #ifdef XT_INTEXC_HOOKS
-    /* Call interrupt hook if present to (pre)handle interrupts. */
-    movi    a0, _xt_intexc_hooks
-    l32i    a0, a0, 4<<2
-    beqz    a0, 1f
-.Ln_xt_highint4_call_hook:
-    callx0  a0                              /* must NOT disturb stack! */
-1:
-    #endif
-
-    /* USER_EDIT:
-    ADD HIGH PRIORITY LEVEL 4 INTERRUPT HANDLER CODE HERE.
-    */
-
-    .align  4
-.L_xt_highint4_exit:
-    rsr     a0, EXCSAVE_4                   /* restore a0 */
-    rfi     4
-
-#endif  /* Level 4 */
-
-#if XCHAL_NUM_INTLEVELS >=5 && XCHAL_EXCM_LEVEL <5 && XCHAL_DEBUGLEVEL !=5
-
-    .begin      literal_prefix .Level5InterruptVector
-    .section    .Level5InterruptVector.text, "ax"
-    .global     _Level5Vector
-    .type       _Level5Vector,@function
-    .align      4
-_Level5Vector:
-    wsr     a0, EXCSAVE_5                   /* preserve a0 */
-    call0   _xt_highint5                    /* load interrupt handler */
-    /* never returns here - call0 is used as a jump (see note at top) */
-
-    .end        literal_prefix
-
-    .text
-    .type       _xt_highint5,@function
-    .align      4
-_xt_highint5:
-
-    #ifdef XT_INTEXC_HOOKS
-    /* Call interrupt hook if present to (pre)handle interrupts. */
-    movi    a0, _xt_intexc_hooks
-    l32i    a0, a0, 5<<2
-    beqz    a0, 1f
-.Ln_xt_highint5_call_hook:
-    callx0  a0                              /* must NOT disturb stack! */
-1:
-    #endif
-
-    /* USER_EDIT:
-    ADD HIGH PRIORITY LEVEL 5 INTERRUPT HANDLER CODE HERE.
-    */
-
-    .align  4
-.L_xt_highint5_exit:
-    rsr     a0, EXCSAVE_5                   /* restore a0 */
-    rfi     5
-
-#endif  /* Level 5 */
-
-#if XCHAL_NUM_INTLEVELS >=6 && XCHAL_EXCM_LEVEL <6 && XCHAL_DEBUGLEVEL !=6
-
-    .begin      literal_prefix .Level6InterruptVector
-    .section    .Level6InterruptVector.text, "ax"
-    .global     _Level6Vector
-    .type       _Level6Vector,@function
-    .align      4
-_Level6Vector:
-    wsr     a0, EXCSAVE_6                   /* preserve a0 */
-    call0   _xt_highint6                    /* load interrupt handler */
-    /* never returns here - call0 is used as a jump (see note at top) */
-
-    .end        literal_prefix
-
-    .text
-    .type       _xt_highint6,@function
-    .align      4
-_xt_highint6:
-
-    #ifdef XT_INTEXC_HOOKS
-    /* Call interrupt hook if present to (pre)handle interrupts. */
-    movi    a0, _xt_intexc_hooks
-    l32i    a0, a0, 6<<2
-    beqz    a0, 1f
-.Ln_xt_highint6_call_hook:
-    callx0  a0                              /* must NOT disturb stack! */
-1:
-    #endif
-
-    /* USER_EDIT:
-    ADD HIGH PRIORITY LEVEL 6 INTERRUPT HANDLER CODE HERE.
-    */
-
-    .align  4
-.L_xt_highint6_exit:
-    rsr     a0, EXCSAVE_6                   /* restore a0 */
-    rfi     6
-
-#endif  /* Level 6 */
-
-#if XCHAL_HAVE_NMI
-
-    .begin      literal_prefix .NMIExceptionVector
-    .section    .NMIExceptionVector.text, "ax"
-    .global     _NMIExceptionVector
-    .type       _NMIExceptionVector,@function
-    .align      4
-_NMIExceptionVector:
-    wsr     a0, EXCSAVE + XCHAL_NMILEVEL  _ /* preserve a0 */
-    call0   _xt_nmi                         /* load interrupt handler */
-    /* never returns here - call0 is used as a jump (see note at top) */
-
-    .end        literal_prefix
-
-    .text
-    .type       _xt_nmi,@function
-    .align      4
-_xt_nmi:
-
-    #ifdef XT_INTEXC_HOOKS
-    /* Call interrupt hook if present to (pre)handle interrupts. */
-    movi    a0, _xt_intexc_hooks
-    l32i    a0, a0, XCHAL_NMILEVEL<<2
-    beqz    a0, 1f
-.Ln_xt_nmi_call_hook:
-    callx0  a0                              /* must NOT disturb stack! */
-1:
-    #endif
-
-    /* USER_EDIT:
-    ADD HIGH PRIORITY NON-MASKABLE INTERRUPT (NMI) HANDLER CODE HERE.
-    */
-
-    .align  4
-.L_xt_nmi_exit:
-    rsr     a0, EXCSAVE + XCHAL_NMILEVEL    /* restore a0 */
-    rfi     XCHAL_NMILEVEL
-
-#endif  /* NMI */
-
-
-/*******************************************************************************
-
-WINDOW OVERFLOW AND UNDERFLOW EXCEPTION VECTORS AND ALLOCA EXCEPTION HANDLER
-
-Here is the code for each window overflow/underflow exception vector and 
-(interspersed) efficient code for handling the alloca exception cause.
-Window exceptions are handled entirely in the vector area and are very
-tight for performance. The alloca exception is also handled entirely in 
-the window vector area so comes at essentially no cost in code size.
-Users should never need to modify them and Cadence Design Systems recommends 
-they do not.
-
-Window handlers go at predetermined vector locations according to the
-Xtensa hardware configuration, which is ensured by their placement in a
-special section known to the Xtensa linker support package (LSP). Since
-their offsets in that section are always the same, the LSPs do not define
-a section per vector.
-
-These things are coded for XEA2 only (XEA1 is not supported).
-
-Note on Underflow Handlers:
-The underflow handler for returning from call[i+1] to call[i]
-must preserve all the registers from call[i+1]'s window.
-In particular, a0 and a1 must be preserved because the RETW instruction
-will be reexecuted (and may even underflow if an intervening exception
-has flushed call[i]'s registers).
-Registers a2 and up may contain return values.
-
-*******************************************************************************/
-
-#if XCHAL_HAVE_WINDOWED
-
-    .section .WindowVectors.text, "ax"
-
-/*
---------------------------------------------------------------------------------
-Window Overflow Exception for Call4.
-
-Invoked if a call[i] referenced a register (a4-a15)
-that contains data from ancestor call[j];
-call[j] had done a call4 to call[j+1].
-On entry here:
-    window rotated to call[j] start point;
-        a0-a3 are registers to be saved;
-        a4-a15 must be preserved;
-        a5 is call[j+1]'s stack pointer.
---------------------------------------------------------------------------------
-*/
-
-    .org    0x0
-    .global _WindowOverflow4
-_WindowOverflow4:
-
-    s32e    a0, a5, -16     /* save a0 to call[j+1]'s stack frame */
-    s32e    a1, a5, -12     /* save a1 to call[j+1]'s stack frame */
-    s32e    a2, a5,  -8     /* save a2 to call[j+1]'s stack frame */
-    s32e    a3, a5,  -4     /* save a3 to call[j+1]'s stack frame */
-    rfwo                    /* rotates back to call[i] position */
-
-/*
---------------------------------------------------------------------------------
-Window Underflow Exception for Call4
-
-Invoked by RETW returning from call[i+1] to call[i]
-where call[i]'s registers must be reloaded (not live in ARs);
-where call[i] had done a call4 to call[i+1].
-On entry here:
-        window rotated to call[i] start point;
-        a0-a3 are undefined, must be reloaded with call[i].reg[0..3];
-        a4-a15 must be preserved (they are call[i+1].reg[0..11]);
-        a5 is call[i+1]'s stack pointer.
---------------------------------------------------------------------------------
-*/
-
-    .org    0x40
-    .global _WindowUnderflow4
-_WindowUnderflow4:
-
-    l32e    a0, a5, -16     /* restore a0 from call[i+1]'s stack frame */
-    l32e    a1, a5, -12     /* restore a1 from call[i+1]'s stack frame */
-    l32e    a2, a5,  -8     /* restore a2 from call[i+1]'s stack frame */
-    l32e    a3, a5,  -4     /* restore a3 from call[i+1]'s stack frame */
-    rfwu
-
-/*
---------------------------------------------------------------------------------
-Handle alloca exception generated by interruptee executing 'movsp'.
-This uses space between the window vectors, so is essentially "free".
-All interruptee's regs are intact except a0 which is saved in EXCSAVE_1,
-and PS.EXCM has been set by the exception hardware (can't be interrupted).
-The fact the alloca exception was taken means the registers associated with
-the base-save area have been spilled and will be restored by the underflow
-handler, so those 4 registers are available for scratch.
-The code is optimized to avoid unaligned branches and minimize cache misses.
---------------------------------------------------------------------------------
-*/
-
-    .align  4
-    .global _xt_alloca_exc
-_xt_alloca_exc:
-
-    rsr     a0, WINDOWBASE  /* grab WINDOWBASE before rotw changes it */
-    rotw    -1              /* WINDOWBASE goes to a4, new a0-a3 are scratch */
-    rsr     a2, PS
-    extui   a3, a2, XCHAL_PS_OWB_SHIFT, XCHAL_PS_OWB_BITS
-    xor     a3, a3, a4      /* bits changed from old to current windowbase */
-    rsr     a4, EXCSAVE_1   /* restore original a0 (now in a4) */
-    slli    a3, a3, XCHAL_PS_OWB_SHIFT
-    xor     a2, a2, a3      /* flip changed bits in old window base */
-    wsr     a2, PS          /* update PS.OWB to new window base */
-    rsync
-
-    _bbci.l a4, 31, _WindowUnderflow4
-    rotw    -1              /* original a0 goes to a8 */
-    _bbci.l a8, 30, _WindowUnderflow8
-    rotw    -1
-    j               _WindowUnderflow12
-
-/*
---------------------------------------------------------------------------------
-Window Overflow Exception for Call8
-
-Invoked if a call[i] referenced a register (a4-a15)
-that contains data from ancestor call[j];
-call[j] had done a call8 to call[j+1].
-On entry here:
-    window rotated to call[j] start point;
-        a0-a7 are registers to be saved;
-        a8-a15 must be preserved;
-        a9 is call[j+1]'s stack pointer.
---------------------------------------------------------------------------------
-*/
-
-    .org    0x80
-    .global _WindowOverflow8
-_WindowOverflow8:
-
-    s32e    a0, a9, -16     /* save a0 to call[j+1]'s stack frame */
-    l32e    a0, a1, -12     /* a0 <- call[j-1]'s sp
-                               (used to find end of call[j]'s frame) */
-    s32e    a1, a9, -12     /* save a1 to call[j+1]'s stack frame */
-    s32e    a2, a9,  -8     /* save a2 to call[j+1]'s stack frame */
-    s32e    a3, a9,  -4     /* save a3 to call[j+1]'s stack frame */
-    s32e    a4, a0, -32     /* save a4 to call[j]'s stack frame */
-    s32e    a5, a0, -28     /* save a5 to call[j]'s stack frame */
-    s32e    a6, a0, -24     /* save a6 to call[j]'s stack frame */
-    s32e    a7, a0, -20     /* save a7 to call[j]'s stack frame */
-    rfwo                    /* rotates back to call[i] position */
-
-/*
---------------------------------------------------------------------------------
-Window Underflow Exception for Call8
-
-Invoked by RETW returning from call[i+1] to call[i]
-where call[i]'s registers must be reloaded (not live in ARs);
-where call[i] had done a call8 to call[i+1].
-On entry here:
-        window rotated to call[i] start point;
-        a0-a7 are undefined, must be reloaded with call[i].reg[0..7];
-        a8-a15 must be preserved (they are call[i+1].reg[0..7]);
-        a9 is call[i+1]'s stack pointer.
---------------------------------------------------------------------------------
-*/
-
-    .org    0xC0
-    .global _WindowUnderflow8
-_WindowUnderflow8:
-
-    l32e    a0, a9, -16     /* restore a0 from call[i+1]'s stack frame */
-    l32e    a1, a9, -12     /* restore a1 from call[i+1]'s stack frame */
-    l32e    a2, a9,  -8     /* restore a2 from call[i+1]'s stack frame */
-    l32e    a7, a1, -12     /* a7 <- call[i-1]'s sp
-                               (used to find end of call[i]'s frame) */
-    l32e    a3, a9,  -4     /* restore a3 from call[i+1]'s stack frame */
-    l32e    a4, a7, -32     /* restore a4 from call[i]'s stack frame */
-    l32e    a5, a7, -28     /* restore a5 from call[i]'s stack frame */
-    l32e    a6, a7, -24     /* restore a6 from call[i]'s stack frame */
-    l32e    a7, a7, -20     /* restore a7 from call[i]'s stack frame */
-    rfwu
-
-/*
---------------------------------------------------------------------------------
-Window Overflow Exception for Call12
-
-Invoked if a call[i] referenced a register (a4-a15)
-that contains data from ancestor call[j];
-call[j] had done a call12 to call[j+1].
-On entry here:
-    window rotated to call[j] start point;
-        a0-a11 are registers to be saved;
-        a12-a15 must be preserved;
-        a13 is call[j+1]'s stack pointer.
---------------------------------------------------------------------------------
-*/
-
-    .org    0x100
-    .global _WindowOverflow12
-_WindowOverflow12:
-
-    s32e    a0,  a13, -16   /* save a0 to call[j+1]'s stack frame */
-    l32e    a0,  a1,  -12   /* a0 <- call[j-1]'s sp
-                               (used to find end of call[j]'s frame) */
-    s32e    a1,  a13, -12   /* save a1 to call[j+1]'s stack frame */
-    s32e    a2,  a13,  -8   /* save a2 to call[j+1]'s stack frame */
-    s32e    a3,  a13,  -4   /* save a3 to call[j+1]'s stack frame */
-    s32e    a4,  a0,  -48   /* save a4 to end of call[j]'s stack frame */
-    s32e    a5,  a0,  -44   /* save a5 to end of call[j]'s stack frame */
-    s32e    a6,  a0,  -40   /* save a6 to end of call[j]'s stack frame */
-    s32e    a7,  a0,  -36   /* save a7 to end of call[j]'s stack frame */
-    s32e    a8,  a0,  -32   /* save a8 to end of call[j]'s stack frame */
-    s32e    a9,  a0,  -28   /* save a9 to end of call[j]'s stack frame */
-    s32e    a10, a0,  -24   /* save a10 to end of call[j]'s stack frame */
-    s32e    a11, a0,  -20   /* save a11 to end of call[j]'s stack frame */
-    rfwo                    /* rotates back to call[i] position */
-
-/*
---------------------------------------------------------------------------------
-Window Underflow Exception for Call12
-
-Invoked by RETW returning from call[i+1] to call[i]
-where call[i]'s registers must be reloaded (not live in ARs);
-where call[i] had done a call12 to call[i+1].
-On entry here:
-        window rotated to call[i] start point;
-        a0-a11 are undefined, must be reloaded with call[i].reg[0..11];
-        a12-a15 must be preserved (they are call[i+1].reg[0..3]);
-        a13 is call[i+1]'s stack pointer.
---------------------------------------------------------------------------------
-*/
-
-    .org 0x140
-    .global _WindowUnderflow12
-_WindowUnderflow12:
-
-    l32e    a0,  a13, -16   /* restore a0 from call[i+1]'s stack frame */
-    l32e    a1,  a13, -12   /* restore a1 from call[i+1]'s stack frame */
-    l32e    a2,  a13,  -8   /* restore a2 from call[i+1]'s stack frame */
-    l32e    a11, a1,  -12   /* a11 <- call[i-1]'s sp
-                               (used to find end of call[i]'s frame) */
-    l32e    a3,  a13,  -4   /* restore a3 from call[i+1]'s stack frame */
-    l32e    a4,  a11, -48   /* restore a4 from end of call[i]'s stack frame */
-    l32e    a5,  a11, -44   /* restore a5 from end of call[i]'s stack frame */
-    l32e    a6,  a11, -40   /* restore a6 from end of call[i]'s stack frame */
-    l32e    a7,  a11, -36   /* restore a7 from end of call[i]'s stack frame */
-    l32e    a8,  a11, -32   /* restore a8 from end of call[i]'s stack frame */
-    l32e    a9,  a11, -28   /* restore a9 from end of call[i]'s stack frame */
-    l32e    a10, a11, -24   /* restore a10 from end of call[i]'s stack frame */
-    l32e    a11, a11, -20   /* restore a11 from end of call[i]'s stack frame */
-    rfwu
-
-#endif /* XCHAL_HAVE_WINDOWED */
-
-    .section    .UserEnter.text, "ax"
-    .global     call_user_start
-    .type       call_user_start,@function
-    .align      4
-    .literal_position
-
-
-call_user_start:
-
-	movi	a2, 0x40040000	/* note: absolute symbol, not a ptr */
-	wsr	a2, vecbase
-	call0   user_start                    /* user exception handler */

+ 4 - 4
components/idf_test/integration_test/CIConfigs/IT_Function_TCPIP_02.yml

@@ -4,7 +4,7 @@ Filter:
 - Add:
     ID: [TCPIP_IGMP_0203, ^TCPIP_TCP_0403, ^TCPIP_TCP_0408, TCPIP_UDP_0201, TCPIP_UDP_0202,
       ^TCPIP_DHCP_0301, ^TCPIP_TCP_0101, ^TCPIP_TCP_0103, ^TCPIP_TCP_0105, ^TCPIP_TCP_0104,
-      ^TCPIP_TCP_0107, ^TCPIP_TCP_0106, ^TCPIP_DHCP_0210, ^TCPIP_DHCP_0211, ^TCPIP_TCP_0404,
-      TCPIP_TCP_0212, TCPIP_TCP_0210, ^TCPIP_TCP_0406, ^TCPIP_TCP_0407, ^TCPIP_TCP_0401,
-      ^TCPIP_TCP_0210, ^TCPIP_TCP_0212, TCPIP_DHCP_0211, TCPIP_DHCP_0210, TCPIP_DHCP_0101,
-      TCPIP_DHCP_0103, TCPIP_DHCP_0102, TCPIP_DHCP_0206, TCPIP_DHCP_0207, ^TCPIP_IP_0102]
+      ^TCPIP_TCP_0107, ^TCPIP_TCP_0106, ^TCPIP_DHCP_0210, ^TCPIP_DHCP_0211, ^TCPIP_DHCP_0212,
+      ^TCPIP_TCP_0404, TCPIP_TCP_0212, TCPIP_TCP_0210, ^TCPIP_TCP_0406, ^TCPIP_TCP_0407,
+      ^TCPIP_TCP_0401, ^TCPIP_TCP_0210, ^TCPIP_TCP_0212, TCPIP_DHCP_0211, TCPIP_DHCP_0210,
+      TCPIP_DHCP_0212, TCPIP_DHCP_0101, TCPIP_DHCP_0103, TCPIP_DHCP_0206, TCPIP_DHCP_0207]

+ 1 - 1
components/idf_test/integration_test/CIConfigs/IT_Function_TCPIP_03.yml

@@ -2,7 +2,7 @@ Config: {execute count: 1, execute order: in order}
 DUT: [SSC2, SSC1]
 Filter:
 - Add:
-    ID: [^TCPIP_UDP_0105, ^TCPIP_UDP_0107, ^TCPIP_UDP_0106, ^TCPIP_UDP_0101, TCPIP_TCP_0203,
+    ID: [^TCPIP_IP_0102, ^TCPIP_UDP_0105, ^TCPIP_UDP_0107, ^TCPIP_UDP_0106, ^TCPIP_UDP_0101,
       TCPIP_TCP_0202, ^TCPIP_UDP_0108, ^TCPIP_IGMP_0201, ^TCPIP_IGMP_0203, ^TCPIP_IGMP_0202,
       ^TCPIP_IGMP_0103, TCPIP_UDP_0114, TCPIP_UDP_0113, TCPIP_UDP_0112, TCPIP_DHCP_0205,
       TCPIP_DHCP_0202, TCPIP_DHCP_0203, ^TCPIP_TCP_0102, TCPIP_TCP_0106, TCPIP_TCP_0107,

+ 1 - 1
components/idf_test/integration_test/CIConfigs/IT_Function_TCPIP_04.yml

@@ -5,6 +5,6 @@ Filter:
     ID: [^TCPIP_TCP_0110, ^TCPIP_TCP_0111, TCPIP_DHCP_0209, ^TCPIP_DHCP_0209, ^TCPIP_DHCP_0207,
       ^TCPIP_DHCP_0206, ^TCPIP_DHCP_0205, ^TCPIP_DHCP_0204, ^TCPIP_DHCP_0203, ^TCPIP_DHCP_0202,
       ^TCPIP_DHCP_0201, TCPIP_TCP_0204, TCPIP_TCP_0207, TCPIP_TCP_0206, TCPIP_TCP_0201,
-      ^TCPIP_DHCP_0101, ^TCPIP_DHCP_0102, ^TCPIP_DHCP_0103, ^TCPIP_DHCP_0208, TCPIP_TCP_0208,
+      ^TCPIP_DHCP_0101, TCPIP_TCP_0203, ^TCPIP_DHCP_0103, ^TCPIP_DHCP_0208, TCPIP_TCP_0208,
       ^TCPIP_TCP_0202, ^TCPIP_TCP_0203, TCPIP_DHCP_0204, ^TCPIP_TCP_0201, ^TCPIP_TCP_0206,
       ^TCPIP_TCP_0207, ^TCPIP_TCP_0204, TCPIP_DHCP_0201, ^TCPIP_TCP_0208, TCPIP_DHCP_0208]

+ 4 - 4
components/idf_test/integration_test/CIConfigs/IT_Function_WIFI_01.yml

@@ -4,7 +4,7 @@ Filter:
 - Add:
     ID: [^WIFI_CONN_0601, ^WIFI_ADDR_0101, WIFI_SCAN_0103, WIFI_SCAN_0102, WIFI_SCAN_0101,
       WIFI_SCAN_0105, WIFI_SCAN_0104, ^WIFI_CONN_0103, WIFI_CONN_0201, WIFI_CONN_0904,
-      ^WIFI_SCAN_0102, ^WIFI_SCAN_0103, ^WIFI_SCAN_0104, ^WIFI_SCAN_0105, WIFI_CONN_0401,
-      WIFI_ADDR_0101, WIFI_ADDR_0102, WIFI_CONN_0301, ^WIFI_CONN_0801, ^WIFI_CONN_0301,
-      WIFI_CONN_0501, WIFI_CONN_0502, ^WIFI_CONN_0401, WIFI_MODE_0101, WIFI_MODE_0103,
-      WIFI_MODE_0102, ^WIFI_CONN_0904, ^WIFI_CONN_0901, WIFI_CONN_0601, ^WIFI_CONN_0201]
+      ^WIFI_SCAN_0102, ^WIFI_SCAN_0103, ^WIFI_SCAN_0104, WIFI_CONN_0401, WIFI_ADDR_0101,
+      WIFI_ADDR_0102, WIFI_CONN_0301, WIFI_SCAN_0301, WIFI_SCAN_0303, ^WIFI_CONN_0801,
+      WIFI_SCAN_0304, ^WIFI_CONN_0301, WIFI_CONN_0501, WIFI_CONN_0502, ^WIFI_CONN_0401,
+      WIFI_MODE_0101, WIFI_MODE_0103, WIFI_MODE_0102, ^WIFI_CONN_0904, ^WIFI_CONN_0901]

+ 3 - 3
components/idf_test/integration_test/CIConfigs/IT_Function_WIFI_02.yml

@@ -2,6 +2,6 @@ Config: {execute count: 1, execute order: in order}
 DUT: [SSC2, SSC1]
 Filter:
 - Add:
-    ID: [^WIFI_ADDR_0102, WIFI_CONN_0901, WIFI_CONN_0801, ^WIFI_CONN_0104, WIFI_CONN_0104,
-      WIFI_CONN_0101, WIFI_CONN_0102, WIFI_CONN_0103, ^WIFI_SCAN_0101, ^WIFI_CONN_0101,
-      ^WIFI_CONN_0502, ^WIFI_CONN_0501]
+    ID: [WIFI_SCAN_0302, WIFI_CONN_0601, ^WIFI_CONN_0201, ^WIFI_ADDR_0102, WIFI_CONN_0901,
+      WIFI_CONN_0801, ^WIFI_CONN_0104, WIFI_CONN_0104, WIFI_CONN_0101, WIFI_CONN_0102,
+      WIFI_CONN_0103, ^WIFI_SCAN_0101, ^WIFI_CONN_0101, ^WIFI_CONN_0502, ^WIFI_CONN_0501]

+ 2 - 3
components/idf_test/integration_test/CIConfigs/IT_Function_WIFI_06.yml

@@ -2,6 +2,5 @@ Config: {execute count: 1, execute order: in order}
 DUT: [SSC2, SSC1]
 Filter:
 - Add:
-    ID: [WIFI_SCAN_0301, WIFI_SCAN_0303, WIFI_SCAN_0304, WIFI_SCAN_0302, WIFI_SCAN_0201,
-      WIFI_PHY_0403, WIFI_PHY_0402, WIFI_PHY_0401, WIFI_PHY_0407, WIFI_PHY_0406, WIFI_PHY_0405,
-      WIFI_PHY_0404, WIFI_PHY_0408]
+    ID: [WIFI_SCAN_0201, WIFI_PHY_0403, WIFI_PHY_0402, WIFI_PHY_0401, WIFI_PHY_0407,
+      WIFI_PHY_0406, WIFI_PHY_0405, WIFI_PHY_0404, WIFI_PHY_0408]

+ 40 - 0
components/idf_test/integration_test/KnownIssues

@@ -23,10 +23,29 @@ TCPIP_IGMP_0204
 ^TCPIP_IGMP_0203
 ^TCPIP_IGMP_0204
 
+# don't support PHY mode command
+WIFI_SCAN_0201
+WIFI_SCAN_0302
+WIFI_PHY_0401
+WIFI_PHY_0402
+WIFI_PHY_0403
+WIFI_PHY_0404
+WIFI_PHY_0405
+WIFI_PHY_0407
+WIFI_PHY_0406
+WIFI_PHY_0408
+WIFI_PHY_0501
+WIFI_PHY_0502
+WIFI_PHY_0503
+WIFI_PHY_0504
+WIFI_PHY_0505
+WIFI_PHY_0506
+
 # BUG
 
 # auth change event
 WIFI_CONN_0801
+^WIFI_CONN_0801
 
 # disconnect reason
 WIFI_CONN_0904
@@ -37,6 +56,16 @@ WIFI_CONN_0901
 # Wifi connect issue
 WIFI_CONN_0104
 ^WIFI_CONN_0104
+^WIFI_CONN_0601
+
+# Wifi scan issue
+WIFI_SCAN_0303
+^WIFI_SCAN_0103
+^WIFI_SCAN_0105
+
+# set mac address may lead to exception
+WIFI_ADDR_0101
+^WIFI_ADDR_0101
 
 # DHCP issues
 ^TCPIP_DHCP_0301
@@ -46,6 +75,10 @@ TCPIP_DHCP_0207
 ^TCPIP_DHCP_0207
 TCPIP_DHCP_0208
 ^TCPIP_DHCP_0208
+TCPIP_DHCP_0205
+^TCPIP_DHCP_0205
+TCPIP_DHCP_0209
+^TCPIP_DHCP_0209
 
 # TCP issue
 TCPIP_TCP_0402
@@ -54,6 +87,9 @@ TCPIP_TCP_0402
 TCPIP_TCP_0210
 ^TCPIP_TCP_0210
 TCPIP_TCP_0103
+^TCPIP_TCP_0103
+TCPIP_TCP_0112
+^TCPIP_TCP_0112
 
 
 # UDP issue
@@ -61,6 +97,10 @@ TCPIP_UDP_0103
 ^TCPIP_UDP_0103
 TCPIP_UDP_0110
 ^TCPIP_UDP_0110
+TCPIP_UDP_0305
+^TCPIP_UDP_0305
+^TCPIP_UDP_0304
+TCPIP_UDP_0104
 
 
 

+ 157 - 236
components/idf_test/integration_test/TestCaseAll.yml

@@ -87,7 +87,7 @@ test cases:
   - - SSC SSC1 dhcp -E -o 1
     - ['R SSC1 C +DHCP:STA,OK']
   - - SSC SSC1 ip -S -i 0.0.0.0
-    - ['R SSC1 C +IP:OK']
+    - [R SSC1 C +IP]
   - - SSC SSC1 sta -C -s <ap_ssid> -p <ap_password>
     - ['']
   - - DELAY 20
@@ -121,54 +121,7 @@ test cases:
     1 SSC target connect with PC by UART.'
   test point 1: basic function
   test point 2: DHCP client function test
-  version: v1 (2016-8-15)
-- CI ready: 'Yes'
-  ID: TCPIP_DHCP_0102
-  SDK: '8266_NonOS
-
-    8266_RTOS
-
-    ESP32_IDF'
-  Test App: SSC
-  allow fail: ''
-  auto test: 'Yes'
-  category: Function
-  cmd set:
-  - ''
-  - - SSC SSC1 ap -S -s <target_ssid> -p <target_password> -t <target_auth_enum>
-    - ['R SSC1 C +SAP:OK']
-  - - SSC SSC1 dhcp -E -o 2
-    - ['R SSC1 C +DHCP:AP,OK']
-  - - SSC SSC2 sta -C -s <target_ssid> -p <target_password>
-    - ['']
-  - - DELAY 20
-    - [P PC_COM C +DELAYDONE, 'P SSC2 NC +JAP:CONNECTED']
-  - - SSC SSC1 dhcp -S -o 2
-    - ['R SSC1 C +DHCP:AP,OK']
-  - - SSC SSC2 sta -C -s <target_ssid> -p <target_password>
-    - ['R SSC2 C +JAP:CONNECTED']
-  comment: ''
-  execution time: 0.0
-  expected result: "1.target1 set AP OK \n2.target1 关闭DHCP OK\n3.target2 jap target\
-    \ 1,FAIL \n4.target1 打开DHCP OK\n5.target2 jap target 1,ok"
-  initial condition: T2_1
-  initial condition description (auto): target 1 as SoftAP, target 2 as STA, will
-    autogen a TC with initial condition T2_2
-  level: Integration
-  module: TCPIP
-  steps: "1.target1 set AP OK \n2.target1 关闭DHCP OK\n3.target2 jap target 1,FAIL \n\
-    4.target1 打开DHCP OK\n5.target2 jap target 1,ok"
-  sub module: DHCP
-  summary: dhcp server function test
-  test environment: SSC_T2_1
-  test environment description (auto): 'PC has 1 wired NIC connected to AP.
-
-    PC has 1 WiFi NIC.
-
-    2 SSC target connect with PC by UART.'
-  test point 1: basic function
-  test point 2: DHCP client function test
-  version: v1 (2016-8-15)
+  version: v2 (2016-10-19)
 - CI ready: 'Yes'
   ID: TCPIP_DHCP_0103
   SDK: '8266_NonOS
@@ -927,7 +880,7 @@ test cases:
     - ['R SSC1 C +DHCP:AP,OK']
   - - SSC SSC2 sta -C -s <random_string> -p <random_string>
     - ['R SSC2 C +JAP:CONNECTED']
-  - - DELAY 10
+  - - DELAY 30
     - ['']
   - - SSC SSC1 ap -L
     - [R SSC1 C 192.168.4.2 C 192.168.4.3 P <pc_wifi_nic_mac> P <target2_mac>]
@@ -967,6 +920,53 @@ test cases:
   test point 1: basic function
   test point 2: DHCP server function test
   version: v1 (2016-8-15)
+- CI ready: 'Yes'
+  ID: TCPIP_DHCP_0212
+  SDK: '8266_NonOS
+
+    8266_RTOS
+
+    ESP32_IDF'
+  Test App: SSC
+  allow fail: ''
+  auto test: 'Yes'
+  category: Function
+  cmd set:
+  - ''
+  - - SSC SSC1 ap -S -s <target_ssid> -p <target_password> -t <target_auth_enum>
+    - ['R SSC1 C +SAP:OK']
+  - - SSC SSC1 dhcp -E -o 2
+    - ['R SSC1 C +DHCP:AP,OK']
+  - - SSC SSC2 sta -C -s <target_ssid> -p <target_password>
+    - ['']
+  - - DELAY 20
+    - [P PC_COM C +DELAYDONE, 'P SSC2 NC +JAP:CONNECTED']
+  - - SSC SSC1 dhcp -S -o 2
+    - ['R SSC1 C +DHCP:AP,OK']
+  - - SSC SSC2 sta -C -s <target_ssid> -p <target_password>
+    - ['R SSC2 C +JAP:CONNECTED']
+  comment: ''
+  execution time: 0.0
+  expected result: "1.target1 set AP OK \n2.target1 关闭DHCP OK\n3.target2 jap target\
+    \ 1,FAIL \n4.target1 打开DHCP OK\n5.target2 jap target 1,ok"
+  initial condition: T2_1
+  initial condition description (auto): target 1 as SoftAP, target 2 as STA, will
+    autogen a TC with initial condition T2_2
+  level: Integration
+  module: TCPIP
+  steps: "1.target1 set AP OK \n2.target1 关闭DHCP OK\n3.target2 jap target 1,FAIL \n\
+    4.target1 打开DHCP OK\n5.target2 jap target 1,ok"
+  sub module: DHCP
+  summary: dhcp server function test
+  test environment: SSC_T2_1
+  test environment description (auto): 'PC has 1 wired NIC connected to AP.
+
+    PC has 1 WiFi NIC.
+
+    2 SSC target connect with PC by UART.'
+  test point 1: basic function
+  test point 2: DHCP server function test
+  version: v2 (2016-10-19)
 - CI ready: 'Yes'
   ID: TCPIP_DHCP_0301
   SDK: '8266_NonOS
@@ -987,7 +987,7 @@ test cases:
   - - SSC SSC1 sta -C -s <ap_ssid> -p <ap_password>
     - ['R SSC1 C +JAP:CONNECTED']
   - - SSC SSC1 ip -S -i 0.0.0.0 -o 1
-    - ['R SSC1 C +IP:OK']
+    - [R SSC1 C +IP]
   - - SSC SSC1 sta -C -s <ap_ssid> -p <ap_password>
     - ['']
   - - DELAY 10
@@ -1027,7 +1027,7 @@ test cases:
     1 SSC target connect with PC by UART.'
   test point 1: interaction
   test point 2: static IP and DHCP interaction test
-  version: v1 (2016-8-15)
+  version: v2 (2016-10-19)
 - CI ready: 'Yes'
   ID: TCPIP_DHCP_0302
   SDK: '8266_NonOS
@@ -1143,7 +1143,7 @@ test cases:
   category: Function
   cmd set:
   - ''
-  - - SSC SSC1 soc -H -d iot.espressif.cn
+  - - SSC SSC1 soc -H -d factory.espressif.cn
     - ['R SSC1 A <ip_addr>:\+HOSTIP:OK,(.+)\r\n']
   - - SSC SSC1 soc -B -t TCP
     - ['R SSC1 A <sock1>:\+BIND:(\d+),OK']
@@ -1178,7 +1178,7 @@ test cases:
     1 SSC target connect with PC by UART.'
   test point 1: basic function
   test point 2: DNS function test
-  version: v1 (2016-8-15)
+  version: v2 (2016-10-19)
 - CI ready: 'Yes'
   ID: TCPIP_DNS_0103
   SDK: '8266_NonOS
@@ -1192,7 +1192,7 @@ test cases:
   category: Function
   cmd set:
   - ''
-  - - SSC SSC1 soc -H -d iot.espressif.cn
+  - - SSC SSC1 soc -H -d factory.espressif.cn
     - ['R SSC1 A <ip_addr>:\+HOSTIP:OK,(.+)\r\n']
   - - SSC SSC1 soc -B -t UDP
     - ['R SSC1 A <sock1>:\+BIND:(\d+),OK']
@@ -1223,7 +1223,7 @@ test cases:
     1 SSC target connect with PC by UART.'
   test point 1: basic function
   test point 2: DNS function test
-  version: v1 (2016-8-15)
+  version: v2 (2016-10-19)
 - CI ready: 'Yes'
   ID: TCPIP_ICMP_0101
   SDK: '8266_NonOS
@@ -3189,14 +3189,12 @@ test cases:
   - ''
   - - SOC SOC1 LISTEN <test_tcp_port1>
     - [R SOC_COM L OK]
-  - - SSC SSC1 soc -B -t TCP
+  - - SSC SSC1 soc -B -t TCP -w 0
     - ['R SSC1 A <sock1>:BIND:(\d+),OK']
   - - SSC SSC1 soc -C -s <sock1> -i <pc_ip> -p <test_tcp_port1>
     - ['R SSC1 RE CONNECT:\d+,OK']
   - - SOC SOC1 ACCEPT SOC2
     - [R SOC_COM L OK]
-  - - SSC SSC1 soc -W -s <sock1> -o 0
-    - ['R SSC1 RE WORKTHREAD:\d+,OK']
   - - SOC SOC2 SEND 146000
     - [P SOC_COM R *]
   - - SSC SSC1 soc -W -s <sock1> -o 1
@@ -3246,7 +3244,7 @@ test cases:
     1 SSC target connect with PC by UART.'
   test point 1: basic function
   test point 2: use TCP SAP (socket/espconn API) in different state
-  version: v1 (2016-8-15)
+  version: v2 (2016-10-19)
 - CI ready: 'Yes'
   ID: TCPIP_TCP_0206
   SDK: '8266_NonOS
@@ -3280,7 +3278,7 @@ test cases:
     - ['R SSC1 A <sock4>:ACCEPT:(\d+),\d+,.+,\d+']
   - - SSC SSC1 soc -I
     - ['P SSC1 RE "SOCINFO:%%s,2,%%s,\d+,%%s,%%d"%%(<sock1>,<target_ip>,<pc_ip>,<test_tcp_port1>)',
-      'P SSC1 RE "SOCINFO:%%s,2,.+,\d+,.+,\d+"%%(<sock2>)', 'P SSC1 RE "SOCINFO:%%s,82,.+,%%d,.+,\d+"%%(<sock3>,<random_port>)',
+      'P SSC1 RE "SOCINFO:%%s,2,.+,\d+,.+,\d+"%%(<sock2>)', 'P SSC1 RE "SOCINFO:%%s,82,.+,%%d"%%(<sock3>,<random_port>)',
       'P SSC1 RE "SOCINFO:%%s,2,%%s,%%d,%%s,\d+"%%(<sock4>,<target_ip>,<random_port>,<pc_ip>)']
   comment: ''
   execution time: 0.0
@@ -3531,14 +3529,12 @@ test cases:
   - ''
   - - SOC SOC1 LISTEN <test_tcp_port1> <pc_ip_wifi>
     - [R SOC_COM L OK]
-  - - SSC SSC1 soc -B -t TCP
+  - - SSC SSC1 soc -B -t TCP -w 0
     - ['R SSC1 A <sock1>:BIND:(\d+),OK']
   - - SSC SSC1 soc -C -s <sock1> -i <pc_ip_wifi> -p <test_tcp_port1>
     - ['R SSC1 RE CONNECT:\d+,OK']
   - - SOC SOC1 ACCEPT SOC2
     - [R SOC_COM L OK]
-  - - SSC SSC1 soc -W -s <sock1> -o 0
-    - ['R SSC1 RE WORKTHREAD:\d+,OK']
   - - SOC SOC2 SEND 146000
     - [P SOC_COM R *]
   - - SSC SSC1 soc -W -s <sock1> -o 1
@@ -3586,7 +3582,7 @@ test cases:
     1 SSC target connect with PC by UART.'
   test point 1: basic function
   test point 2: use TCP SAP (socket/espconn API) in different state
-  version: v1 (2016-8-15)
+  version: v2 (2016-10-19)
 - CI ready: 'Yes'
   ID: TCPIP_TCP_0212
   SDK: '8266_NonOS
@@ -3620,7 +3616,7 @@ test cases:
     - ['R SSC1 A <sock4>:ACCEPT:(\d+),\d+,.+,\d+']
   - - SSC SSC1 soc -I
     - ['P SSC1 RE "SOCINFO:%%s,2,%%s,\d+,%%s,%%d"%%(<sock1>,<target_ap_ip>,<pc_ip_wifi>,<test_tcp_port1>)',
-      'P SSC1 RE "SOCINFO:%%s,2,.+,\d+,.+,\d+"%%(<sock2>)', 'P SSC1 RE "SOCINFO:%%s,82,.+,%%d,.+,\d+"%%(<sock3>,<random_port>)',
+      'P SSC1 RE "SOCINFO:%%s,2,.+,\d+,.+,\d+"%%(<sock2>)', 'P SSC1 RE "SOCINFO:%%s,82,.+,%%d"%%(<sock3>,<random_port>)',
       'P SSC1 RE "SOCINFO:%%s,2,%%s,%%d,%%s,\d+"%%(<sock4>,<target_ap_ip>,<random_port>,<pc_ip_wifi>)']
   comment: ''
   execution time: 0.0
@@ -5119,10 +5115,8 @@ test cases:
   - ''
   - - SOC SOC1 BIND <test_udp_port1> <pc_ip>
     - [R SOC_COM L OK]
-  - - SSC SSC1 soc -B -t UDP -p <test_udp_port1>
+  - - SSC SSC1 soc -B -t UDP -p <test_udp_port1> -w 0
     - ['R SSC1 A <sock1>:BIND:(\d+),OK']
-  - - SSC SSC1 soc -W -s <sock1> -o 0
-    - ['R SSC1 RE WORKTHREAD:\d+,OK']
   - - SOC SOC1 SENDTO 1472 <test_udp_port1> <target_ip>
     - ['']
   - - SOC SOC1 SENDTO 1472 <test_udp_port1> <target_ip>
@@ -5180,7 +5174,7 @@ test cases:
     1 SSC target connect with PC by UART.'
   test point 1: abnormal/special use
   test point 2: use UDP SAP (socket/espconn API) in different state
-  version: v1 (2016-8-15)
+  version: v2 (2016-10-19)
 - CI ready: 'Yes'
   ID: TCPIP_UDP_0202
   SDK: '8266_NonOS
@@ -5198,8 +5192,8 @@ test cases:
     - [R SOC_COM L OK]
   - - SSC SSC1 soc -B -t UDP -p <test_udp_port1>
     - ['R SSC1 A <sock1>:BIND:(\d+),OK']
-  - - SSC SSC1 soc -W -s <sock1> -o 0
-    - ['R SSC1 RE WORKTHREAD:\d+,OK']
+  - - SOC SOC1 SENDTO 1472 <test_udp_port1> <target_ap_ip>
+    - ['']
   - - SOC SOC1 SENDTO 1472 <test_udp_port1> <target_ap_ip>
     - ['']
   - - SOC SOC1 SENDTO 1472 <test_udp_port1> <target_ap_ip>
@@ -5257,7 +5251,7 @@ test cases:
     1 SSC target connect with PC by UART.'
   test point 1: abnormal/special use
   test point 2: use UDP SAP (socket/espconn API) in different state
-  version: v1 (2016-8-15)
+  version: v2 (2016-10-19)
 - CI ready: 'Yes'
   ID: TCPIP_UDP_0301
   SDK: '8266_NonOS
@@ -5874,6 +5868,8 @@ test cases:
     - ['R SSC2 RE "\+JAP:CONNECTED,%%s"%%(<target_ssid>)']
   - - SSC SSC1 ap -S -s <target_ssid> -n 15
     - ['R SSC1 C +SAP:OK']
+  - - SSC SSC2 sta -C -s <target_ssid> -p <target_password>
+    - ['R SSC2 RE "\+JAP:CONNECTED,%%s"%%(<target_ssid>)']
   - - SSC SSC2 sta -S
     - ['R SSC2 RE "\+SCAN:%%s,.+,\d+,1"%%(<target_ssid>)']
   comment: ''
@@ -7915,7 +7911,7 @@ test cases:
   - - SSC SSC1 sta -S
     - ['']
   - - SSC SSC1 sta -S
-    - [P SSC1 C +SCANFAIL, 'P SSC1 P +SCAN:', R SSC1 C +SCANDONE]
+    - [P SSC1 C +SCANFAIL, 'P SSC1 C +SCAN:', R SSC1 C +SCANDONE]
   comment: ''
   execution time: 0.0
   expected result: '1. second scan failed
@@ -7931,14 +7927,12 @@ test cases:
     2. do scan before scan finished'
   sub module: WIFI Scan
   summary: reject scan request before scan finished
-  test environment: SSC_T2_PhyMode
-  test environment description (auto): '2 SSC target connect with PC by UART.
-
-    PC has one WiFi NIC support capture wlan packet using libpcap.
+  test environment: SSC_T1_1
+  test environment description (auto): 'PC has 2 wired NIC connected to AP.
 
-    Set 4 AP with phy mode 11b, 11g, 11n HT20, 11n HT40.
+    PC has 1 WiFi NIC.
 
-    Put 4 APs near SSC targets.'
+    1 SSC target connect with PC by UART.'
   test point 1: interaction
   test point 2: Scan interact with other WiFi operation
   version: v1 (2015-8-15)
@@ -7987,14 +7981,12 @@ test cases:
     3. target 2 scan in AP channel in 11b.g,n,ht40 mode'
   sub module: WIFI Scan
   summary: scan in congest channel
-  test environment: SSC_T2_PhyMode
-  test environment description (auto): '2 SSC target connect with PC by UART.
-
-    PC has one WiFi NIC support capture wlan packet using libpcap.
+  test environment: SSC_T2_1
+  test environment description (auto): 'PC has 1 wired NIC connected to AP.
 
-    Set 4 AP with phy mode 11b, 11g, 11n HT20, 11n HT40.
+    PC has 1 WiFi NIC.
 
-    Put 4 APs near SSC targets.'
+    2 SSC target connect with PC by UART.'
   test point 1: interaction
   test point 2: Scan interact with other WiFi operation
   version: v1 (2015-8-15)
@@ -8022,8 +8014,9 @@ test cases:
   expected result: '2. scan succeed, JAP succeed
 
     5. JAP succeed, scan succeed'
-  initial condition: T2_2
-  initial condition description (auto): target 1 as AP+STA, target 2 as AP+STA (autogen)
+  initial condition: STAM1
+  initial condition description (auto): sta mode, quit AP, DHCP on, will autogen a
+    TC with initial condition STAAP1
   level: Integration
   module: WIFI MAC
   steps: '1. target 1 STA join AP
@@ -8037,14 +8030,12 @@ test cases:
     5. target 1 JAP before scan succeed'
   sub module: WIFI Scan
   summary: scan during JAP
-  test environment: SSC_T2_PhyMode
-  test environment description (auto): '2 SSC target connect with PC by UART.
-
-    PC has one WiFi NIC support capture wlan packet using libpcap.
+  test environment: SSC_T1_1
+  test environment description (auto): 'PC has 2 wired NIC connected to AP.
 
-    Set 4 AP with phy mode 11b, 11g, 11n HT20, 11n HT40.
+    PC has 1 WiFi NIC.
 
-    Put 4 APs near SSC targets.'
+    1 SSC target connect with PC by UART.'
   test point 1: interaction
   test point 2: Scan interact with other WiFi operation
   version: v1 (2015-8-15)
@@ -8057,6 +8048,8 @@ test cases:
   category: Function
   cmd set:
   - ''
+  - - SSC SSC1 ap -S -s <target_ssid> -p <target_password> -t <target_auth_enum>
+    - ['R SSC1 C +SAP:OK']
   - - SSC SSC2 sta -C -s <target_ssid> -p <target_password>
     - ['R SSC2 C +JAP:OK']
   - - SSC SSC1 sta -S
@@ -8087,14 +8080,12 @@ test cases:
     5. target 2 STA JAP before target 1 STA scan succeed'
   sub module: WIFI Scan
   summary: scan during ext STA join SoftAP
-  test environment: SSC_T2_PhyMode
-  test environment description (auto): '2 SSC target connect with PC by UART.
-
-    PC has one WiFi NIC support capture wlan packet using libpcap.
+  test environment: SSC_T2_1
+  test environment description (auto): 'PC has 1 wired NIC connected to AP.
 
-    Set 4 AP with phy mode 11b, 11g, 11n HT20, 11n HT40.
+    PC has 1 WiFi NIC.
 
-    Put 4 APs near SSC targets.'
+    2 SSC target connect with PC by UART.'
   test point 1: interaction
   test point 2: Scan interact with other WiFi operation
   version: v1 (2015-8-15)
@@ -8114,7 +8105,7 @@ test cases:
   - - SSC SSC1 dhcp -E -o 1
     - ['R SSC1 C +DHCP:STA,OK']
   - - SSC SSC1 ip -S -i 0.0.0.0
-    - ['R SSC1 C +IP:OK']
+    - [R SSC1 C +IP]
   - - SSC SSC1 sta -C -s <ap_ssid> -p <ap_password>
     - ['']
   - - DELAY 20
@@ -8148,53 +8139,7 @@ test cases:
     1 SSC target connect with PC by UART.'
   test point 1: basic function
   test point 2: DHCP client function test
-  version: v1 (2016-8-15)
-- CI ready: 'Yes'
-  ID: ^TCPIP_DHCP_0102
-  SDK: '8266_NonOS
-
-    8266_RTOS
-
-    ESP32_IDF'
-  Test App: SSC
-  allow fail: ''
-  auto test: 'Yes'
-  category: Function
-  cmd set:
-  - ''
-  - - SSC SSC1 ap -S -s <target_ssid> -p <target_password> -t <target_auth_enum>
-    - ['R SSC1 C +SAP:OK']
-  - - SSC SSC1 dhcp -E -o 2
-    - ['R SSC1 C +DHCP:AP,OK']
-  - - SSC SSC2 sta -C -s <target_ssid> -p <target_password>
-    - ['']
-  - - DELAY 20
-    - [P PC_COM C +DELAYDONE, 'P SSC2 NC +JAP:CONNECTED']
-  - - SSC SSC1 dhcp -S -o 2
-    - ['R SSC1 C +DHCP:AP,OK']
-  - - SSC SSC2 sta -C -s <target_ssid> -p <target_password>
-    - ['R SSC2 C +JAP:CONNECTED']
-  comment: ''
-  execution time: 0.0
-  expected result: "1.target1 set AP OK \n2.target1 关闭DHCP OK\n3.target2 jap target\
-    \ 1,FAIL \n4.target1 打开DHCP OK\n5.target2 jap target 1,ok"
-  initial condition: T2_2
-  initial condition description (auto): target 1 as AP+STA, target 2 as AP+STA (autogen)
-  level: Integration
-  module: TCPIP
-  steps: "1.target1 set AP OK \n2.target1 关闭DHCP OK\n3.target2 jap target 1,FAIL \n\
-    4.target1 打开DHCP OK\n5.target2 jap target 1,ok"
-  sub module: DHCP
-  summary: dhcp server function test
-  test environment: SSC_T2_1
-  test environment description (auto): 'PC has 1 wired NIC connected to AP.
-
-    PC has 1 WiFi NIC.
-
-    2 SSC target connect with PC by UART.'
-  test point 1: basic function
-  test point 2: DHCP client function test
-  version: v1 (2016-8-15)
+  version: v2 (2016-10-19)
 - CI ready: 'Yes'
   ID: ^TCPIP_DHCP_0103
   SDK: '8266_NonOS
@@ -8943,7 +8888,7 @@ test cases:
     - ['R SSC1 C +DHCP:AP,OK']
   - - SSC SSC2 sta -C -s <random_string> -p <random_string>
     - ['R SSC2 C +JAP:CONNECTED']
-  - - DELAY 10
+  - - DELAY 30
     - ['']
   - - SSC SSC1 ap -L
     - [R SSC1 C 192.168.4.2 C 192.168.4.3 P <pc_wifi_nic_mac> P <target2_mac>]
@@ -8982,6 +8927,52 @@ test cases:
   test point 1: basic function
   test point 2: DHCP server function test
   version: v1 (2016-8-15)
+- CI ready: 'Yes'
+  ID: ^TCPIP_DHCP_0212
+  SDK: '8266_NonOS
+
+    8266_RTOS
+
+    ESP32_IDF'
+  Test App: SSC
+  allow fail: ''
+  auto test: 'Yes'
+  category: Function
+  cmd set:
+  - ''
+  - - SSC SSC1 ap -S -s <target_ssid> -p <target_password> -t <target_auth_enum>
+    - ['R SSC1 C +SAP:OK']
+  - - SSC SSC1 dhcp -E -o 2
+    - ['R SSC1 C +DHCP:AP,OK']
+  - - SSC SSC2 sta -C -s <target_ssid> -p <target_password>
+    - ['']
+  - - DELAY 20
+    - [P PC_COM C +DELAYDONE, 'P SSC2 NC +JAP:CONNECTED']
+  - - SSC SSC1 dhcp -S -o 2
+    - ['R SSC1 C +DHCP:AP,OK']
+  - - SSC SSC2 sta -C -s <target_ssid> -p <target_password>
+    - ['R SSC2 C +JAP:CONNECTED']
+  comment: ''
+  execution time: 0.0
+  expected result: "1.target1 set AP OK \n2.target1 关闭DHCP OK\n3.target2 jap target\
+    \ 1,FAIL \n4.target1 打开DHCP OK\n5.target2 jap target 1,ok"
+  initial condition: T2_2
+  initial condition description (auto): target 1 as AP+STA, target 2 as AP+STA (autogen)
+  level: Integration
+  module: TCPIP
+  steps: "1.target1 set AP OK \n2.target1 关闭DHCP OK\n3.target2 jap target 1,FAIL \n\
+    4.target1 打开DHCP OK\n5.target2 jap target 1,ok"
+  sub module: DHCP
+  summary: dhcp server function test
+  test environment: SSC_T2_1
+  test environment description (auto): 'PC has 1 wired NIC connected to AP.
+
+    PC has 1 WiFi NIC.
+
+    2 SSC target connect with PC by UART.'
+  test point 1: basic function
+  test point 2: DHCP server function test
+  version: v2 (2016-10-19)
 - CI ready: 'Yes'
   ID: ^TCPIP_DHCP_0301
   SDK: '8266_NonOS
@@ -9002,7 +8993,7 @@ test cases:
   - - SSC SSC1 sta -C -s <ap_ssid> -p <ap_password>
     - ['R SSC1 C +JAP:CONNECTED']
   - - SSC SSC1 ip -S -i 0.0.0.0 -o 1
-    - ['R SSC1 C +IP:OK']
+    - [R SSC1 C +IP]
   - - SSC SSC1 sta -C -s <ap_ssid> -p <ap_password>
     - ['']
   - - DELAY 10
@@ -9042,7 +9033,7 @@ test cases:
     1 SSC target connect with PC by UART.'
   test point 1: interaction
   test point 2: static IP and DHCP interaction test
-  version: v1 (2016-8-15)
+  version: v2 (2016-10-19)
 - CI ready: 'Yes'
   ID: ^TCPIP_DHCP_0302
   SDK: '8266_NonOS
@@ -9157,7 +9148,7 @@ test cases:
   category: Function
   cmd set:
   - ''
-  - - SSC SSC1 soc -H -d iot.espressif.cn
+  - - SSC SSC1 soc -H -d factory.espressif.cn
     - ['R SSC1 A <ip_addr>:\+HOSTIP:OK,(.+)\r\n']
   - - SSC SSC1 soc -B -t TCP
     - ['R SSC1 A <sock1>:\+BIND:(\d+),OK']
@@ -9192,7 +9183,7 @@ test cases:
     1 SSC target connect with PC by UART.'
   test point 1: basic function
   test point 2: DNS function test
-  version: v1 (2016-8-15)
+  version: v2 (2016-10-19)
 - CI ready: 'Yes'
   ID: ^TCPIP_DNS_0103
   SDK: '8266_NonOS
@@ -9206,7 +9197,7 @@ test cases:
   category: Function
   cmd set:
   - ''
-  - - SSC SSC1 soc -H -d iot.espressif.cn
+  - - SSC SSC1 soc -H -d factory.espressif.cn
     - ['R SSC1 A <ip_addr>:\+HOSTIP:OK,(.+)\r\n']
   - - SSC SSC1 soc -B -t UDP
     - ['R SSC1 A <sock1>:\+BIND:(\d+),OK']
@@ -9237,7 +9228,7 @@ test cases:
     1 SSC target connect with PC by UART.'
   test point 1: basic function
   test point 2: DNS function test
-  version: v1 (2016-8-15)
+  version: v2 (2016-10-19)
 - CI ready: 'Yes'
   ID: ^TCPIP_ICMP_0101
   SDK: '8266_NonOS
@@ -11199,14 +11190,12 @@ test cases:
   - ''
   - - SOC SOC1 LISTEN <test_tcp_port1>
     - [R SOC_COM L OK]
-  - - SSC SSC1 soc -B -t TCP
+  - - SSC SSC1 soc -B -t TCP -w 0
     - ['R SSC1 A <sock1>:BIND:(\d+),OK']
   - - SSC SSC1 soc -C -s <sock1> -i <pc_ip> -p <test_tcp_port1>
     - ['R SSC1 RE CONNECT:\d+,OK']
   - - SOC SOC1 ACCEPT SOC2
     - [R SOC_COM L OK]
-  - - SSC SSC1 soc -W -s <sock1> -o 0
-    - ['R SSC1 RE WORKTHREAD:\d+,OK']
   - - SOC SOC2 SEND 146000
     - [P SOC_COM R *]
   - - SSC SSC1 soc -W -s <sock1> -o 1
@@ -11254,7 +11243,7 @@ test cases:
     1 SSC target connect with PC by UART.'
   test point 1: basic function
   test point 2: use TCP SAP (socket/espconn API) in different state
-  version: v1 (2016-8-15)
+  version: v2 (2016-10-19)
 - CI ready: 'Yes'
   ID: ^TCPIP_TCP_0206
   SDK: '8266_NonOS
@@ -11288,7 +11277,7 @@ test cases:
     - ['R SSC1 A <sock4>:ACCEPT:(\d+),\d+,.+,\d+']
   - - SSC SSC1 soc -I
     - ['P SSC1 RE "SOCINFO:%%s,2,%%s,\d+,%%s,%%d"%%(<sock1>,<target_ip>,<pc_ip>,<test_tcp_port1>)',
-      'P SSC1 RE "SOCINFO:%%s,2,.+,\d+,.+,\d+"%%(<sock2>)', 'P SSC1 RE "SOCINFO:%%s,82,.+,%%d,.+,\d+"%%(<sock3>,<random_port>)',
+      'P SSC1 RE "SOCINFO:%%s,2,.+,\d+,.+,\d+"%%(<sock2>)', 'P SSC1 RE "SOCINFO:%%s,82,.+,%%d"%%(<sock3>,<random_port>)',
       'P SSC1 RE "SOCINFO:%%s,2,%%s,%%d,%%s,\d+"%%(<sock4>,<target_ip>,<random_port>,<pc_ip>)']
   comment: ''
   execution time: 0.0
@@ -11539,14 +11528,12 @@ test cases:
   - ''
   - - SOC SOC1 LISTEN <test_tcp_port1> <pc_ip_wifi>
     - [R SOC_COM L OK]
-  - - SSC SSC1 soc -B -t TCP
+  - - SSC SSC1 soc -B -t TCP -w 0
     - ['R SSC1 A <sock1>:BIND:(\d+),OK']
   - - SSC SSC1 soc -C -s <sock1> -i <pc_ip_wifi> -p <test_tcp_port1>
     - ['R SSC1 RE CONNECT:\d+,OK']
   - - SOC SOC1 ACCEPT SOC2
     - [R SOC_COM L OK]
-  - - SSC SSC1 soc -W -s <sock1> -o 0
-    - ['R SSC1 RE WORKTHREAD:\d+,OK']
   - - SOC SOC2 SEND 146000
     - [P SOC_COM R *]
   - - SSC SSC1 soc -W -s <sock1> -o 1
@@ -11592,7 +11579,7 @@ test cases:
     1 SSC target connect with PC by UART.'
   test point 1: basic function
   test point 2: use TCP SAP (socket/espconn API) in different state
-  version: v1 (2016-8-15)
+  version: v2 (2016-10-19)
 - CI ready: 'Yes'
   ID: ^TCPIP_TCP_0212
   SDK: '8266_NonOS
@@ -11626,7 +11613,7 @@ test cases:
     - ['R SSC1 A <sock4>:ACCEPT:(\d+),\d+,.+,\d+']
   - - SSC SSC1 soc -I
     - ['P SSC1 RE "SOCINFO:%%s,2,%%s,\d+,%%s,%%d"%%(<sock1>,<target_ap_ip>,<pc_ip_wifi>,<test_tcp_port1>)',
-      'P SSC1 RE "SOCINFO:%%s,2,.+,\d+,.+,\d+"%%(<sock2>)', 'P SSC1 RE "SOCINFO:%%s,82,.+,%%d,.+,\d+"%%(<sock3>,<random_port>)',
+      'P SSC1 RE "SOCINFO:%%s,2,.+,\d+,.+,\d+"%%(<sock2>)', 'P SSC1 RE "SOCINFO:%%s,82,.+,%%d"%%(<sock3>,<random_port>)',
       'P SSC1 RE "SOCINFO:%%s,2,%%s,%%d,%%s,\d+"%%(<sock4>,<target_ap_ip>,<random_port>,<pc_ip_wifi>)']
   comment: ''
   execution time: 0.0
@@ -12981,10 +12968,8 @@ test cases:
   - ''
   - - SOC SOC1 BIND <test_udp_port1> <pc_ip>
     - [R SOC_COM L OK]
-  - - SSC SSC1 soc -B -t UDP -p <test_udp_port1>
+  - - SSC SSC1 soc -B -t UDP -p <test_udp_port1> -w 0
     - ['R SSC1 A <sock1>:BIND:(\d+),OK']
-  - - SSC SSC1 soc -W -s <sock1> -o 0
-    - ['R SSC1 RE WORKTHREAD:\d+,OK']
   - - SOC SOC1 SENDTO 1472 <test_udp_port1> <target_ip>
     - ['']
   - - SOC SOC1 SENDTO 1472 <test_udp_port1> <target_ip>
@@ -13042,7 +13027,7 @@ test cases:
     1 SSC target connect with PC by UART.'
   test point 1: abnormal/special use
   test point 2: use UDP SAP (socket/espconn API) in different state
-  version: v1 (2016-8-15)
+  version: v2 (2016-10-19)
 - CI ready: 'Yes'
   ID: ^TCPIP_UDP_0202
   SDK: '8266_NonOS
@@ -13060,8 +13045,8 @@ test cases:
     - [R SOC_COM L OK]
   - - SSC SSC1 soc -B -t UDP -p <test_udp_port1>
     - ['R SSC1 A <sock1>:BIND:(\d+),OK']
-  - - SSC SSC1 soc -W -s <sock1> -o 0
-    - ['R SSC1 RE WORKTHREAD:\d+,OK']
+  - - SOC SOC1 SENDTO 1472 <test_udp_port1> <target_ap_ip>
+    - ['']
   - - SOC SOC1 SENDTO 1472 <test_udp_port1> <target_ap_ip>
     - ['']
   - - SOC SOC1 SENDTO 1472 <test_udp_port1> <target_ap_ip>
@@ -13119,7 +13104,7 @@ test cases:
     1 SSC target connect with PC by UART.'
   test point 1: abnormal/special use
   test point 2: use UDP SAP (socket/espconn API) in different state
-  version: v1 (2016-8-15)
+  version: v2 (2016-10-19)
 - CI ready: 'Yes'
   ID: ^TCPIP_UDP_0301
   SDK: '8266_NonOS
@@ -14652,67 +14637,3 @@ test cases:
   test point 1: basic function
   test point 2: scan with different config
   version: v1 (2016-8-15)
-- CI ready: 'Yes'
-  ID: ^WIFI_SCAN_0105
-  SDK: '8266_NonOS
-
-    8266_RTOS
-
-    ESP32_IDF'
-  Test App: SSC
-  allow fail: ''
-  auto test: 'Yes'
-  category: Function
-  cmd set:
-  - ''
-  - - SSC SSC1 sta -D
-    - ['R SSC1 C +QAP:']
-  - - SSC SSC1 ap -S -s <target_tmp_ssid> -p 123456789 -t 3 -h 0 -n 11
-    - ['R SSC1 C +SAP:OK']
-  - - SSC SSC2 sta -S -s <target_tmp_ssid> -b <target_ap_mac> -n 11
-    - [R SSC2 P <target_tmp_ssid> C +SCANDONE]
-  - - SSC SSC2 sta -S -s <target_ssid> -b <target_ap_mac> -n 11
-    - [R SSC2 NP <target_tmp_ssid> C +SCANDONE]
-  - - SSC SSC2 sta -S -s <target_tmp_ssid> -b ff:ff:ff:ff:ff:11 -n 11
-    - [R SSC2 P <target_tmp_ssid>, R SSC2 NP <target_tmp_ssid> C +SCANDONE]
-  - - SSC SSC2 sta -S -s <target_tmp_ssid> -b <target_ap_mac> -n 10
-    - [R SSC2 P <target_tmp_ssid>, R SSC2 NP <target_tmp_ssid> C +SCANDONE]
-  comment: ''
-  execution time: 0.0
-  expected result: '1.target1 QAP
-
-    2. target1 set AP,set ssid broad cast,set channel 11
-
-    3.target2 上查询到<target_tmp_ssid>
-
-    4.target2 上查询不到<target_tmp_ssid>
-
-    5.target2 上查询不到<target_tmp_ssid>
-
-    6.target2 上查询不到<target_tmp_ssid>'
-  initial condition: T2_2
-  initial condition description (auto): target 1 as AP+STA, target 2 as AP+STA (autogen)
-  level: Integration
-  module: WIFI MAC
-  steps: '1.target1 QAP
-
-    2. target1 set AP,set ssid broad cast,set channel 11
-
-    3.target2 上查询到<target_tmp_ssid>
-
-    4.target2 上查询不到<target_tmp_ssid>
-
-    5.target2 上查询不到<target_tmp_ssid>
-
-    6.target2 上查询不到<target_tmp_ssid>'
-  sub module: WIFI Scan
-  summary: scan with several configs
-  test environment: SSC_T2_1
-  test environment description (auto): 'PC has 1 wired NIC connected to AP.
-
-    PC has 1 WiFi NIC.
-
-    2 SSC target connect with PC by UART.'
-  test point 1: basic function
-  test point 2: scan with different config
-  version: v1 (2016-8-15)

+ 4 - 0
components/idf_test/integration_test/TestEnvAll.yml

@@ -229,6 +229,10 @@ test environment:
     Put 4 APs near SSC targets.', test script: EnvBase}
 - {PC OS: '', Special: N, Target Count: 5.0, script path: EnvBase.py, tag: SSC_T5_1,
   test environment detail: 5 SSC target connect with PC by UART., test script: EnvBase}
+- {PC OS: '', Special: Y, Target Count: 5.0, script path: EnvBase.py, tag: SSC_T5_IOT1,
+  test environment detail: '5 SSC targets connect with PC by UART.
+
+    some Android smart phone are placed near SSC targets.', test script: EnvBase}
 - {PC OS: '', Special: N, Target Count: 1.0, script path: EnvBase.py, tag: SSC_T6_1,
   test environment detail: 'PC has 1 wired NIC connected to AP.
 

+ 4 - 0
components/idf_test/uint_test/TestEnvAll.yml

@@ -229,6 +229,10 @@ test environment:
     Put 4 APs near SSC targets.', test script: EnvBase}
 - {PC OS: '', Special: N, Target Count: 5.0, script path: EnvBase.py, tag: SSC_T5_1,
   test environment detail: 5 SSC target connect with PC by UART., test script: EnvBase}
+- {PC OS: '', Special: Y, Target Count: 5.0, script path: EnvBase.py, tag: SSC_T5_IOT1,
+  test environment detail: '5 SSC targets connect with PC by UART.
+
+    some Android smart phone are placed near SSC targets.', test script: EnvBase}
 - {PC OS: '', Special: N, Target Count: 1.0, script path: EnvBase.py, tag: SSC_T6_1,
   test environment detail: 'PC has 1 wired NIC connected to AP.
 

+ 1 - 1
components/log/log.c

@@ -284,7 +284,7 @@ static inline void heap_swap(int i, int j)
 }
 #endif //BOOTLOADER_BUILD
 
-inline IRAM_ATTR uint32_t esp_log_early_timestamp()
+IRAM_ATTR uint32_t esp_log_early_timestamp()
 {
     return xthal_get_ccount() / (CPU_CLK_FREQ_ROM / 1000);
 }

+ 2 - 1
components/lwip/Kconfig

@@ -7,7 +7,8 @@ config LWIP_MAX_SOCKETS
     help
         Sockets take up a certain amount of memory, and allowing fewer
         sockets to be open at the same time conserves memory. Specify
-        the maximum amount of sockets here.
+        the maximum amount of sockets here. The valid value is from 1
+        to 16.
 
 config LWIP_THREAD_LOCAL_STORAGE_INDEX
     int "Index for thread-local-storage pointer for lwip"

+ 3 - 18
components/lwip/api/api_lib.c

@@ -55,11 +55,6 @@
 
 #include <string.h>
 
-#ifdef MEMLEAK_DEBUG
-static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__;
-#endif
-
-
 #define API_MSG_VAR_REF(name)             API_VAR_REF(name)
 #define API_MSG_VAR_DECLARE(name)         API_VAR_DECLARE(struct api_msg, name)
 #define API_MSG_VAR_ALLOC(name)           API_VAR_ALLOC(struct api_msg, MEMP_API_MSG, name)
@@ -178,8 +173,8 @@ netconn_delete(struct netconn *conn)
     return err;
   }
 
-#if !LWIP_THREAD_SAFE
-  LWIP_DEBUGF(THREAD_SAFE_DEBUG, ("netconn_delete - free conn\n"));
+#if !ESP_THREAD_SAFE
+  LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("netconn_delete - free conn\n"));
   netconn_free(conn);
 #endif
 
@@ -502,7 +497,7 @@ netconn_recv_data(struct netconn *conn, void **new_buf)
 #endif /* LWIP_TCP && (LWIP_UDP || LWIP_RAW) */
 #if (LWIP_UDP || LWIP_RAW)
   {
-#if LWIP_THREAD_SAFE
+#if ESP_THREAD_SAFE
     if (buf == NULL){
       API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0);
       return ERR_CLSD;
@@ -710,17 +705,7 @@ netconn_write_partly(struct netconn *conn, const void *dataptr, size_t size,
   }
   dontblock = netconn_is_nonblocking(conn) || (apiflags & NETCONN_DONTBLOCK);
 
-#ifdef LWIP_ESP8266
-
-#ifdef FOR_XIAOMI
-    if (dontblock && bytes_written) {
-#else
-    if (dontblock && !bytes_written) {
-#endif
-    
-#else
   if (dontblock && !bytes_written) {
-#endif
     /* This implies netconn_write() cannot be used for non-blocking send, since
        it has no way to return the number of bytes written. */
     return ERR_VAL;

+ 7 - 27
components/lwip/api/api_msg.c

@@ -55,10 +55,6 @@
 
 #include <string.h>
 
-#ifdef MEMLEAK_DEBUG
-static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__;
-#endif
-
 /* netconns are polled once per second (e.g. continue write on memory error) */
 #define NETCONN_TCP_POLL_INTERVAL 2
 
@@ -314,8 +310,8 @@ poll_tcp(void *arg, struct tcp_pcb *pcb)
   if (conn->flags & NETCONN_FLAG_CHECK_WRITESPACE) {
     /* If the queued byte- or pbuf-count drops below the configured low-water limit,
        let select mark this pcb as writable again. */
-    if ((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT) &&
-      (tcp_sndqueuelen(conn->pcb.tcp) < TCP_SNDQUEUELOWAT)) {
+    if ((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT(conn->pcb.tcp)) &&
+      (tcp_sndqueuelen(conn->pcb.tcp) < TCP_SNDQUEUELOWAT(conn->pcb.tcp))) {
       conn->flags &= ~NETCONN_FLAG_CHECK_WRITESPACE;
       API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0);
     }
@@ -348,8 +344,8 @@ sent_tcp(void *arg, struct tcp_pcb *pcb, u16_t len)
 
     /* If the queued byte- or pbuf-count drops below the configured low-water limit,
        let select mark this pcb as writable again. */
-    if ((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT) &&
-      (tcp_sndqueuelen(conn->pcb.tcp) < TCP_SNDQUEUELOWAT)) {
+    if ((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT(conn->pcb.tcp) &&
+      (tcp_sndqueuelen(conn->pcb.tcp) < TCP_SNDQUEUELOWAT(conn->pcb.tcp)))) {
       conn->flags &= ~NETCONN_FLAG_CHECK_WRITESPACE;
       API_EVENT(conn, NETCONN_EVT_SENDPLUS, len);
     }
@@ -1216,16 +1212,7 @@ lwip_netconn_do_connect(void *m)
       if (msg->conn->state == NETCONN_CONNECT) {
         msg->err = ERR_ALREADY;
       } else if (msg->conn->state != NETCONN_NONE) {
-
-#ifdef LWIP_ESP8266
-    if( msg->conn->pcb.tcp->state == ESTABLISHED )
         msg->err = ERR_ISCONN;
-    else
-        msg->err = ERR_ALREADY;
-#else
-        msg->err = ERR_ISCONN;
-#endif
-
       } else {
         setup_tcp(msg->conn);
         msg->err = tcp_connect(msg->conn->pcb.tcp, API_EXPR_REF(msg->msg.bc.ipaddr),
@@ -1540,8 +1527,8 @@ err_mem:
            and let poll_tcp check writable space to mark the pcb writable again */
         API_EVENT(conn, NETCONN_EVT_SENDMINUS, len);
         conn->flags |= NETCONN_FLAG_CHECK_WRITESPACE;
-      } else if ((tcp_sndbuf(conn->pcb.tcp) <= TCP_SNDLOWAT) ||
-                 (tcp_sndqueuelen(conn->pcb.tcp) >= TCP_SNDQUEUELOWAT)) {
+      } else if ((tcp_sndbuf(conn->pcb.tcp) <= TCP_SNDLOWAT(conn->pcb.tcp)) ||
+                 (tcp_sndqueuelen(conn->pcb.tcp) >= TCP_SNDQUEUELOWAT(conn->pcb.tcp))) {
         /* The queued byte- or pbuf-count exceeds the configured low-water limit,
            let select mark this pcb as non-writable. */
         API_EVENT(conn, NETCONN_EVT_SENDMINUS, len);
@@ -1646,14 +1633,7 @@ lwip_netconn_do_write(void *m)
         if (lwip_netconn_do_writemore(msg->conn, 0) != ERR_OK) {
           LWIP_ASSERT("state!", msg->conn->state == NETCONN_WRITE);
           UNLOCK_TCPIP_CORE();
-
-#ifdef LWIP_ESP8266
-//#if 0
-            sys_arch_sem_wait( LWIP_API_MSG_SND_SEM(msg), 0);
-#else
-            sys_arch_sem_wait(LWIP_API_MSG_SEM(msg), 0);
-#endif
-                
+          sys_arch_sem_wait(LWIP_API_MSG_SEM(msg), 0);
           LOCK_TCPIP_CORE();
           LWIP_ASSERT("state!", msg->conn->state != NETCONN_WRITE);
         }

+ 3 - 0
components/lwip/api/lwip_debug.c

@@ -48,6 +48,9 @@ static void dbg_lwip_tcp_pcb_one_show(struct tcp_pcb* pcb)
     printf("rttest=%d rtseq=%d sa=%d sv=%d\n", pcb->rttest, pcb->rtseq, pcb->sa, pcb->sv);
     printf("rto=%d nrtx=%d\n", pcb->rto, pcb->nrtx);
     printf("dupacks=%d lastack=%d\n", pcb->dupacks, pcb->lastack);
+#if ESP_PER_SOC_TCP_WND
+    printf("per_soc_window=%d per_soc_snd_buf=%d\n", pcb->per_soc_tcp_wnd, pcb->per_soc_tcp_snd_buf);
+#endif
     printf("cwnd=%d ssthreash=%d\n", pcb->cwnd, pcb->ssthresh);
     printf("snd_next=%d snd_wl1=%d snd_wl2=%d\n", pcb->snd_nxt, pcb->snd_wl1, pcb->snd_wl2);
     printf("snd_lbb=%d snd_wnd=%d snd_wnd_max=%d\n", pcb->snd_lbb, pcb->snd_wnd, pcb->snd_wnd_max);

+ 0 - 5
components/lwip/api/netbuf.c

@@ -45,11 +45,6 @@
 
 #include <string.h>
 
-#ifdef MEMLEAK_DEBUG
-static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__;
-#endif
-
-
 /**
  * Create (allocate) and initialize a new netbuf.
  * The netbuf doesn't yet contain a packet buffer!

+ 0 - 5
components/lwip/api/netdb.c

@@ -47,11 +47,6 @@
 #include <string.h>
 #include <stdlib.h>
 
-#ifdef MEMLEAK_DEBUG
-static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__;
-#endif
-
-
 /** helper struct for gethostbyname_r to access the char* buffer */
 struct gethostbyname_r_helper {
   ip_addr_t *addr_list[2];

+ 57 - 59
components/lwip/api/sockets.c

@@ -61,11 +61,6 @@
 
 #include <string.h>
 
-#ifdef MEMLEAK_DEBUG
-static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__;
-#endif
-
-
 /* If the netconn API is not required publicly, then we include the necessary
    files here to get the implementation */
 #if !LWIP_NETCONN
@@ -216,7 +211,7 @@ struct lwip_sock {
   /** last error that occurred on this socket (in fact, all our errnos fit into an u8_t) */
   u8_t err;
 
-#if LWIP_THREAD_SAFE
+#if ESP_THREAD_SAFE
   /* lock is used to protect state/ref field, however this lock is not a perfect lock, e.g
    * taskA and taskB can access sock X, then taskA freed sock X, before taskB detect 
    * this, taskC reuse sock X, then when taskB try to access sock X, problem may happen.
@@ -239,7 +234,7 @@ struct lwip_sock {
   SELWAIT_T select_waiting;
 };
 
-#if LWIP_THREAD_SAFE
+#if ESP_THREAD_SAFE
 
 #define LWIP_SOCK_OPEN    0
 #define LWIP_SOCK_CLOSING 1
@@ -247,25 +242,25 @@ struct lwip_sock {
 
 #define LWIP_SOCK_LOCK(sock) \
 do{\
-  /*LWIP_DEBUGF(THREAD_SAFE_DEBUG, ("l\n"));*/\
+  /*LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("l\n"));*/\
     sys_mutex_lock(&sock->lock);\
-  /*LWIP_DEBUGF(THREAD_SAFE_DEBUG, ("l ok\n"));*/\
+  /*LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("l ok\n"));*/\
 }while(0)
 
 
 #define LWIP_SOCK_UNLOCK(sock) \
 do{\
   sys_mutex_unlock(&sock->lock);\
-  /*LWIP_DEBUGF(THREAD_SAFE_DEBUG1, ("unl\n"));*/\
+  /*LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG1, ("unl\n"));*/\
 }while(0)
 
 #define LWIP_FREE_SOCK(sock) \
 do{\
   if(sock->conn && NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP){\
-    LWIP_DEBUGF(THREAD_SAFE_DEBUG, ("LWIP_FREE_SOCK:free tcp sock\n"));\
+    LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("LWIP_FREE_SOCK:free tcp sock\n"));\
     free_socket(sock, 1);\
   } else {\
-    LWIP_DEBUGF(THREAD_SAFE_DEBUG, ("LWIP_FREE_SOCK:free non-tcp sock\n"));\
+    LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("LWIP_FREE_SOCK:free non-tcp sock\n"));\
     free_socket(sock, 0);\
   }\
 }while(0)
@@ -273,7 +268,7 @@ do{\
 #define LWIP_SET_CLOSE_FLAG() \
 do{\
   LWIP_SOCK_LOCK(__sock);\
-  LWIP_DEBUGF(THREAD_SAFE_DEBUG, ("mark sock closing\n"));\
+  LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("mark sock closing\n"));\
   __sock->state = LWIP_SOCK_CLOSING;\
   LWIP_SOCK_UNLOCK(__sock);\
 }while(0)
@@ -291,7 +286,7 @@ do{\
   LWIP_SOCK_LOCK(__sock);\
   __sock->ref ++;\
   if (__sock->state != LWIP_SOCK_OPEN) {\
-    LWIP_DEBUGF(THREAD_SAFE_DEBUG, ("LWIP_API_LOCK:soc is %d, return\n", __sock->state));\
+    LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("LWIP_API_LOCK:soc is %d, return\n", __sock->state));\
     __sock->ref --;\
     LWIP_SOCK_UNLOCK(__sock);\
     return -1;\
@@ -306,12 +301,12 @@ do{\
   __sock->ref --;\
   if (__sock->state == LWIP_SOCK_CLOSING) {\
     if (__sock->ref == 0){\
-      LWIP_DEBUGF(THREAD_SAFE_DEBUG, ("LWIP_API_UNLOCK:ref 0, free __sock\n"));\
+      LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("LWIP_API_UNLOCK:ref 0, free __sock\n"));\
       LWIP_FREE_SOCK(__sock);\
       LWIP_SOCK_UNLOCK(__sock);\
       return __ret;\
     }\
-    LWIP_DEBUGF(THREAD_SAFE_DEBUG, ("LWIP_API_UNLOCK: soc state is closing, return\n"));\
+    LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("LWIP_API_UNLOCK: soc state is closing, return\n"));\
     LWIP_SOCK_UNLOCK(__sock);\
     return __ret;\
   }\
@@ -387,11 +382,9 @@ static void lwip_socket_unregister_membership(int s, const ip4_addr_t *if_addr,
 static void lwip_socket_drop_registered_memberships(int s);
 #endif /* LWIP_IGMP */
 
-#ifdef LWIP_ESP8266
-
-/* Since esp_wifi_tx_is_stop/system_get_free_heap_size are not an public wifi API, so extern them here*/
-extern size_t system_get_free_heap_size(void);
-extern bool esp_wifi_tx_is_stop(void);
+#if ESP_LWIP
+#include "esp_wifi_internal.h"
+#include "esp_system.h"
 
 /* Please be notified that this flow control is just a workaround for fixing wifi Q full issue. 
  * Under UDP/TCP pressure test, we found that the sockets may cause wifi tx queue full if the socket
@@ -402,9 +395,9 @@ extern bool esp_wifi_tx_is_stop(void);
  */ 
 static inline void esp32_tx_flow_ctrl(void)
 {
-  uint8_t _wait_delay = 0;
+  uint8_t _wait_delay = 1;
 
-  while ((system_get_free_heap_size() < HEAP_HIGHWAT) || esp_wifi_tx_is_stop()){
+  while ((system_get_free_heap_size() < HEAP_HIGHWAT) || esp_wifi_internal_tx_is_stop()){
      vTaskDelay(_wait_delay/portTICK_RATE_MS);
      if (_wait_delay < 64) _wait_delay *= 2;
   }
@@ -416,7 +409,7 @@ static inline void esp32_tx_flow_ctrl(void)
 
 /** The global array of available sockets */
 static struct lwip_sock sockets[NUM_SOCKETS];
-#if LWIP_THREAD_SAFE
+#if ESP_THREAD_SAFE
 static bool sockets_init_flag = false;
 #endif
 /** The global list of tasks waiting for select */
@@ -427,13 +420,7 @@ static volatile int select_cb_ctr;
 
 /** Table to quickly map an lwIP error (err_t) to a socket error
   * by using -err as an index */
-#ifdef LWIP_ESP8266
-//TO_DO
-//static const int err_to_errno_table[] ICACHE_RODATA_ATTR STORE_ATTR = {
-static const int err_to_errno_table[] = {
-#else
 static const int err_to_errno_table[] = {
-#endif
   0,             /* ERR_OK          0      No error, everything OK. */
   ENOMEM,        /* ERR_MEM        -1      Out of memory error.     */
   ENOBUFS,       /* ERR_BUF        -2      Buffer error.            */
@@ -444,7 +431,7 @@ static const int err_to_errno_table[] = {
   EWOULDBLOCK,   /* ERR_WOULDBLOCK -7      Operation would block.   */
   EADDRINUSE,    /* ERR_USE        -8      Address in use.          */
 
-#ifdef LWIP_ESP8266
+#if ESP_LWIP
   EALREADY,      /* ERR_ALREADY    -9      Already connected.       */
   EISCONN,		 /* ERR_ISCONN     -10	   Conn already established */
   ECONNABORTED,  /* ERR_ABRT       -11     Connection aborted.      */
@@ -585,7 +572,7 @@ alloc_socket(struct netconn *newconn, int accepted)
   int i;
   SYS_ARCH_DECL_PROTECT(lev);
 
-#if LWIP_THREAD_SAFE
+#if ESP_THREAD_SAFE
   bool    found        = false;
   int     oldest       = -1;
 
@@ -641,16 +628,16 @@ alloc_socket(struct netconn *newconn, int accepted)
     if (!sockets[oldest].lock){
       /* one time init and never free */
       if (sys_mutex_new(&sockets[oldest].lock) != ERR_OK){
-        LWIP_DEBUGF(THREAD_SAFE_DEBUG, ("new sock lock fail\n"));
+        LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("new sock lock fail\n"));
         return -1;
       }
     }
-    LWIP_DEBUGF(THREAD_SAFE_DEBUG, ("alloc_socket: alloc %d ok\n", oldest));
+    LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("alloc_socket: alloc %d ok\n", oldest));
 
     return oldest + LWIP_SOCKET_OFFSET;
   }
 
-  LWIP_DEBUGF(THREAD_SAFE_DEBUG, ("alloc_socket: failed\n"));
+  LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("alloc_socket: failed\n"));
  
 #else
 
@@ -695,12 +682,12 @@ free_socket(struct lwip_sock *sock, int is_tcp)
   void *lastdata;
   SYS_ARCH_DECL_PROTECT(lev);
 
-  LWIP_DEBUGF(THREAD_SAFE_DEBUG, ("free_sockset:free socket s=%p is_tcp=%d\n", sock, is_tcp));
+  LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("free_sockset:free socket s=%p is_tcp=%d\n", sock, is_tcp));
   lastdata         = sock->lastdata;
   sock->lastdata   = NULL;
   sock->lastoffset = 0;
   sock->err        = 0;
-#if LWIP_THREAD_SAFE
+#if ESP_THREAD_SAFE
   if (sock->conn){
     netconn_free(sock->conn);
   }
@@ -718,10 +705,10 @@ free_socket(struct lwip_sock *sock, int is_tcp)
 
   if (lastdata != NULL) {
     if (is_tcp) {
-      LWIP_DEBUGF(THREAD_SAFE_DEBUG, ("free_sockset:free lastdata pbuf=%p\n", lastdata));
+      LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("free_sockset:free lastdata pbuf=%p\n", lastdata));
       pbuf_free((struct pbuf *)lastdata);
     } else {
-      LWIP_DEBUGF(THREAD_SAFE_DEBUG, ("free_sockset:free lastdata, netbuf=%p\n", lastdata));
+      LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("free_sockset:free lastdata, netbuf=%p\n", lastdata));
       netbuf_delete((struct netbuf *)lastdata);
     }
   }
@@ -874,19 +861,19 @@ lwip_close(int s)
   int is_tcp = 0;
   err_t err;
 
-  LWIP_DEBUGF(SOCKETS_DEBUG|THREAD_SAFE_DEBUG, ("lwip_close: (%d)\n", s));
+  LWIP_DEBUGF(SOCKETS_DEBUG|ESP_THREAD_SAFE_DEBUG, ("lwip_close: (%d)\n", s));
 
   sock = get_socket(s);
   if (!sock) {
-    LWIP_DEBUGF(SOCKETS_DEBUG|THREAD_SAFE_DEBUG, ("lwip_close: sock is null, return -1\n"));
+    LWIP_DEBUGF(SOCKETS_DEBUG|ESP_THREAD_SAFE_DEBUG, ("lwip_close: sock is null, return -1\n"));
     return -1;
   }
 
   if (sock->conn != NULL) {
     is_tcp = NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP;
-    LWIP_DEBUGF(SOCKETS_DEBUG|THREAD_SAFE_DEBUG, ("lwip_close: is_tcp=%d\n", is_tcp));
+    LWIP_DEBUGF(SOCKETS_DEBUG|ESP_THREAD_SAFE_DEBUG, ("lwip_close: is_tcp=%d\n", is_tcp));
   } else {
-    LWIP_DEBUGF(SOCKETS_DEBUG|THREAD_SAFE_DEBUG, ("conn is null\n"));
+    LWIP_DEBUGF(SOCKETS_DEBUG|ESP_THREAD_SAFE_DEBUG, ("conn is null\n"));
     LWIP_ASSERT("lwip_close: sock->lastdata == NULL", sock->lastdata == NULL);
   }
 
@@ -897,12 +884,12 @@ lwip_close(int s)
 
   err = netconn_delete(sock->conn);
   if (err != ERR_OK) {
-    LWIP_DEBUGF(SOCKETS_DEBUG|THREAD_SAFE_DEBUG, ("netconn_delete fail, ret=%d\n", err));
+    LWIP_DEBUGF(SOCKETS_DEBUG|ESP_THREAD_SAFE_DEBUG, ("netconn_delete fail, ret=%d\n", err));
     sock_set_errno(sock, err_to_errno(err));
     return -1;
   }
 
-#if !LWIP_THREAD_SAFE
+#if !ESP_THREAD_SAFE
   free_socket(sock, is_tcp);
 #endif
 
@@ -1132,22 +1119,13 @@ lwip_recvfrom(int s, void *mem, size_t len, int flags,
         ip_addr_debug_print(SOCKETS_DEBUG, fromaddr);
         LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F" len=%d\n", port, off));
 
-#ifdef LWIP_ESP8266        
         if (from && fromlen)
-#else
-
-#if SOCKETS_DEBUG
-        if (from && fromlen)
-#endif /* SOCKETS_DEBUG */
-
-#endif
         {
               if (*fromlen > saddr.sa.sa_len) {
                 *fromlen = saddr.sa.sa_len;
               }
               MEMCPY(from, &saddr, *fromlen);
-          
-#ifdef LWIP_ESP8266
+#if ESP_LWIP
         } else {
         	/*fix the code for setting the UDP PROTO's remote infomation by liuh at 2014.8.27*/
         	if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_UDP){
@@ -1439,7 +1417,7 @@ lwip_sendto(int s, const void *data, size_t size, int flags,
     SOCKADDR_TO_IPADDR_PORT(to, &buf.addr, remote_port);
   } else {
   
-#ifdef LWIP_ESP8266
+#if ESP_LWIP
         /*fix the code for getting the UDP proto's remote information by liuh at 2014.8.27*/
         if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_UDP){
             if(NETCONNTYPE_ISIPV6(netconn_type(sock->conn))) {
@@ -1455,7 +1433,7 @@ lwip_sendto(int s, const void *data, size_t size, int flags,
 #endif
             remote_port = 0;
             ip_addr_set_any(NETCONNTYPE_ISIPV6(netconn_type(sock->conn)), &buf.addr);
-#ifdef LWIP_ESP8266
+#if ESP_LWIP
         }
 #endif
         
@@ -1988,7 +1966,7 @@ again:
 int
 lwip_shutdown(int s, int how)
 {
-#ifndef LWIP_ESP8266
+#if ! ESP_LWIP
 
   struct lwip_sock *sock;
   err_t err;
@@ -2395,6 +2373,16 @@ lwip_getsockopt_impl(int s, int level, int optname, void *optval, socklen_t *opt
                   s, *(int *)optval));
       break;
 #endif /* LWIP_TCP_KEEPALIVE */
+
+#if ESP_PER_SOC_TCP_WND
+    case TCP_WINDOW:
+    *(int*)optval = (int)sock->conn->pcb.tcp->per_soc_tcp_wnd;
+    break;
+    case TCP_SNDBUF:
+    *(int*)optval = (int)sock->conn->pcb.tcp->per_soc_tcp_snd_buf;
+    break;
+#endif
+
     default:
       LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n",
                   s, optname));
@@ -2792,6 +2780,16 @@ lwip_setsockopt_impl(int s, int level, int optname, const void *optval, socklen_
                   s, sock->conn->pcb.tcp->keep_cnt));
       break;
 #endif /* LWIP_TCP_KEEPALIVE */
+
+#if ESP_PER_SOC_TCP_WND
+    case TCP_WINDOW:
+    sock->conn->pcb.tcp->per_soc_tcp_wnd = ((u32_t)(*(const int*)optval)) * TCP_MSS;
+    break;
+    case TCP_SNDBUF:
+    sock->conn->pcb.tcp->per_soc_tcp_snd_buf = ((u32_t)(*(const int*)optval)) * TCP_MSS;
+    break;
+#endif
+
     default:
       LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n",
                   s, optname));
@@ -3108,7 +3106,7 @@ static void lwip_socket_drop_registered_memberships(int s)
 }
 #endif /* LWIP_IGMP */
 
-#if LWIP_THREAD_SAFE
+#if ESP_THREAD_SAFE
 
 int
 lwip_sendto_r(int s, const void *data, size_t size, int flags,

+ 6 - 14
components/lwip/api/tcpip.c

@@ -50,18 +50,13 @@
 #include "lwip/pbuf.h"
 #include "netif/etharp.h"
 
-#ifdef MEMLEAK_DEBUG
-static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__;
-#endif
-
-
 #define TCPIP_MSG_VAR_REF(name)     API_VAR_REF(name)
 #define TCPIP_MSG_VAR_DECLARE(name) API_VAR_DECLARE(struct tcpip_msg, name)
 #define TCPIP_MSG_VAR_ALLOC(name)   API_VAR_ALLOC(struct tcpip_msg, MEMP_TCPIP_MSG_API, name)
 #define TCPIP_MSG_VAR_FREE(name)    API_VAR_FREE(MEMP_TCPIP_MSG_API, name)
 
 /* global variables */
-#ifdef PERF
+#if ESP_PERF
 uint32_t g_rx_post_mbox_fail_cnt = 0;
 #endif
 static tcpip_init_done_fn tcpip_init_done;
@@ -144,13 +139,11 @@ tcpip_thread(void *arg)
     case TCPIP_MSG_INPKT:
       LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: PACKET %p\n", (void *)msg));
 
-#ifdef LWIP_ESP8266
-//#if 0
+#if ESP_LWIP
         if(msg->msg.inp.p != NULL && msg->msg.inp.netif != NULL) {
 #endif
             msg->msg.inp.input_fn(msg->msg.inp.p, msg->msg.inp.netif);
-#ifdef LWIP_ESP8266
-//#if 0
+#if ESP_LWIP
         }
 #endif
 
@@ -230,7 +223,7 @@ tcpip_inpkt(struct pbuf *p, struct netif *inp, netif_input_fn input_fn)
   msg->msg.inp.netif = inp;
   msg->msg.inp.input_fn = input_fn;
   if (sys_mbox_trypost(&mbox, msg) != ERR_OK) {
-#ifdef PERF
+#if ESP_PERF
     g_rx_post_mbox_fail_cnt ++; 
 #endif
     memp_free(MEMP_TCPIP_MSG_INPKT, msg);
@@ -503,7 +496,7 @@ tcpip_init(tcpip_init_done_fn initfunc, void *arg)
 #endif /* LWIP_TCPIP_CORE_LOCKING */
 
 
-#ifdef LWIP_ESP8266
+#if ESP_LWIP
   sys_thread_t xLwipTaskHandle = sys_thread_new(TCPIP_THREAD_NAME
                 , tcpip_thread, NULL, TCPIP_THREAD_STACKSIZE, TCPIP_THREAD_PRIO);
 
@@ -548,8 +541,7 @@ pbuf_free_callback(struct pbuf *p)
  * @return ERR_OK if callback could be enqueued, an err_t if not
  */
  
-#ifdef LWIP_ESP8266
-//#if 0
+#if ESP_LWIP
 static void mem_free_local(void *arg)
 {
 	mem_free(arg);

+ 1 - 5
components/lwip/apps/dhcpserver.c

@@ -24,7 +24,7 @@
 
 #include "apps/dhcpserver.h"
 
-#ifdef LWIP_ESP8266
+#if ESP_DHCP
 
 #define BOOTP_BROADCAST 0x8000
 
@@ -71,10 +71,6 @@
 #define DHCPS_STATE_IDLE 5
 #define DHCPS_STATE_RELEASE 6
 
-#ifdef MEMLEAK_DEBUG
-static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__;
-#endif
-
 ////////////////////////////////////////////////////////////////////////////////////
 
 static const u32_t magic_cookie  = 0x63538263;

+ 2 - 6
components/lwip/core/dns.c

@@ -85,10 +85,6 @@
 
 #include <string.h>
 
-#ifdef MEMLEAK_DEBUG
-static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__;
-#endif
-
 /** Random generator function to create random TXIDs and source ports for queries */
 #ifndef DNS_RAND_TXID
 #if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_XID) != 0)
@@ -1091,7 +1087,7 @@ dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr,
         u8_t dns_err;
         /* This entry is now completed. */
         
-#ifndef LWIP_ESP8266
+#if ! ESP_DNS
         entry->state = DNS_STATE_DONE;
 #endif
         dns_err = hdr.flags2 & DNS_FLAG2_ERR_MASK;
@@ -1105,7 +1101,7 @@ dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr,
         if (((hdr.flags1 & DNS_FLAG1_RESPONSE) == 0) || (dns_err != 0) || (nquestions != 1)) {
           LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": error in flags\n", entry->name));
           /* call callback to indicate error, clean up memory and return */
-#ifndef LWIP_ESP8266
+#if ! ESP_DNS
                 goto responseerr;
         }
 #else

+ 17 - 19
components/lwip/core/init.c

@@ -61,7 +61,7 @@
 #include "lwip/api.h"
 #include "netif/ppp/ppp_impl.h"
 
-#ifndef PERF
+#if ! ESP_PERF
 /* Compile-time sanity checks for configuration errors.
  * These can be done independently of LWIP_DEBUG, without penalty.
  */
@@ -135,21 +135,22 @@
 //#endif
 #else /* LWIP_WND_SCALE */
 
-#ifndef LWIP_ESP8266
+#if ! ESP_PER_SOC_TCP_WND
 #if (LWIP_TCP && (TCP_WND > 0xffff))
   #error "If you want to use TCP, TCP_WND must fit in an u16_t, so, you have to reduce it in your lwipopts.h (or enable window scaling)"
 #endif
 #endif
 
 #endif /* LWIP_WND_SCALE */
-#if (LWIP_TCP && (TCP_SND_QUEUELEN > 0xffff))
+
+#if ! ESP_PER_SOC_TCP_WND
+#if (LWIP_TCP && (TCP_SND_QUEUELEN(0) > 0xffff))
   #error "If you want to use TCP, TCP_SND_QUEUELEN must fit in an u16_t, so, you have to reduce it in your lwipopts.h"
 #endif
-#if (LWIP_TCP && (TCP_SND_QUEUELEN < 2))
+#if (LWIP_TCP && (TCP_SND_QUEUELEN(0) < 2))
   #error "TCP_SND_QUEUELEN must be at least 2 for no-copy TCP writes to work"
 #endif
 
-#ifndef LWIP_ESP8266
 #if (LWIP_TCP && ((TCP_MAXRTX > 12) || (TCP_SYNMAXRTX > 12)))
   #error "If you want to use TCP, TCP_MAXRTX and TCP_SYNMAXRTX must less or equal to 12 (due to tcp_backoff table), so, you have to reduce them in your lwipopts.h"
 #endif
@@ -285,30 +286,34 @@
 
 /* TCP sanity checks */
 #if !LWIP_DISABLE_TCP_SANITY_CHECKS
+#if ! ESP_PER_SOC_TCP_WND
 #if LWIP_TCP
-#if !MEMP_MEM_MALLOC && (MEMP_NUM_TCP_SEG < TCP_SND_QUEUELEN)
+#if !MEMP_MEM_MALLOC && (MEMP_NUM_TCP_SEG < TCP_SND_QUEUELEN(0))
   #error "lwip_sanity_check: WARNING: MEMP_NUM_TCP_SEG should be at least as big as TCP_SND_QUEUELEN. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
 #endif
-#if TCP_SND_BUF < (2 * TCP_MSS)
+
+#if TCP_SND_BUF(0) < (2 * TCP_MSS)
   #error "lwip_sanity_check: WARNING: TCP_SND_BUF must be at least as much as (2 * TCP_MSS) for things to work smoothly. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
 #endif
-#if TCP_SND_QUEUELEN < (2 * (TCP_SND_BUF / TCP_MSS))
-  #error "lwip_sanity_check: WARNING: TCP_SND_QUEUELEN must be at least as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
+#if TCP_SND_QUEUELEN(0) < (2 * (TCP_SND_BUF(0) / TCP_MSS))
+  #error "lwip_sanity_check: WARNING: TCP_SND_QUEUELEN must be at least as much as (2 * TCP_SND_BUF(0)/TCP_MSS) for things to work. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
 #endif
-#if TCP_SNDLOWAT >= TCP_SND_BUF
+#if TCP_SNDLOWAT >= TCP_SND_BUF(0)
   #error "lwip_sanity_check: WARNING: TCP_SNDLOWAT must be less than TCP_SND_BUF. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
 #endif
 #if TCP_SNDLOWAT >= (0xFFFF - (4 * TCP_MSS))
   #error "lwip_sanity_check: WARNING: TCP_SNDLOWAT must at least be 4*MSS below u16_t overflow!"
 #endif
-#if TCP_SNDQUEUELOWAT >= TCP_SND_QUEUELEN
+#if TCP_SNDQUEUELOWAT >= TCP_SND_QUEUELEN(0)
   #error "lwip_sanity_check: WARNING: TCP_SNDQUEUELOWAT must be less than TCP_SND_QUEUELEN. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
 #endif
+#endif
+
 #if !MEMP_MEM_MALLOC && (PBUF_POOL_BUFSIZE <= (PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN))
   #error "lwip_sanity_check: WARNING: PBUF_POOL_BUFSIZE does not provide enough space for protocol headers. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
 #endif
 
-#ifndef LWIP_ESP8266
+#if ! ESP_LWIP
 #if !MEMP_MEM_MALLOC && (TCP_WND > (PBUF_POOL_SIZE * (PBUF_POOL_BUFSIZE - (PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN))))
   #error "lwip_sanity_check: WARNING: TCP_WND is larger than space provided by PBUF_POOL_SIZE * (PBUF_POOL_BUFSIZE - protocol headers). If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
 #endif
@@ -328,13 +333,6 @@
 void
 lwip_init(void)
 {
-#ifdef LWIP_ESP8266
-//  MEMP_NUM_TCP_PCB = 5;
-//  TCP_WND = (4 * TCP_MSS);
-//  TCP_MAXRTX = 12;
-//  TCP_SYNMAXRTX = 6;
-#endif
-
   /* Modules initialization */
   stats_init();
 #if !NO_SYS

+ 0 - 5
components/lwip/core/ipv4/autoip.c

@@ -76,11 +76,6 @@
 #include <stdlib.h>
 #include <string.h>
 
-#ifdef MEMLEAK_DEBUG
-static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__;
-#endif
-
-
 /* 169.254.0.0 */
 #define AUTOIP_NET         0xA9FE0000
 /* 169.254.1.0 */

+ 3 - 7
components/lwip/core/ipv4/dhcp.c

@@ -82,10 +82,6 @@
 
 #include <string.h>
 
-#ifdef MEMLEAK_DEBUG
-static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__;
-#endif
-
 /** DHCP_CREATE_RAND_XID: if this is set to 1, the xid is created using
  * LWIP_RAND() (this overrides DHCP_GLOBAL_XID)
  */
@@ -146,7 +142,7 @@ static u8_t dhcp_discover_select_options[] = {
   DHCP_OPTION_BROADCAST,
   DHCP_OPTION_DNS_SERVER
   
-#ifdef LWIP_ESP8266
+#if ESP_DHCP
 /**add options for support more router by liuHan**/
    , DHCP_OPTION_DOMAIN_NAME, 
     DHCP_OPTION_NB_TINS, 
@@ -454,7 +450,7 @@ dhcp_fine_tmr(void)
     /* only act on DHCP configured interfaces */
     if (netif->dhcp != NULL) {
         
-//#ifdef LWIP_ESP8266
+//#if ESP_DHCP
       /*add DHCP retries processing by LiuHan*/
 #if 0
       if (DHCP_MAXRTX != 0) {
@@ -997,7 +993,7 @@ dhcp_discover(struct netif *netif)
     dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
     dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif));
 
-#ifdef LWIP_ESP8266
+#if ESP_DHCP
 #if LWIP_NETIF_HOSTNAME
     dhcp_option_hostname(dhcp, netif);
 #endif /* LWIP_NETIF_HOSTNAME */

+ 0 - 5
components/lwip/core/ipv4/icmp.c

@@ -51,11 +51,6 @@
 
 #include <string.h>
 
-#ifdef MEMLEAK_DEBUG
-static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__;
-#endif
-
-
 /** Small optimization: set to 0 if incoming PBUF_POOL pbuf always can be
  * used to modify and send a response packet (and to 1 if this is not the case,
  * e.g. when link header is stripped of when receiving) */

+ 0 - 5
components/lwip/core/ipv4/igmp.c

@@ -92,11 +92,6 @@ Steve Reynolds
 
 #include "string.h"
 
-#ifdef MEMLEAK_DEBUG
-static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__;
-#endif
-
-
 /*
  * IGMP constants
  */

+ 2 - 7
components/lwip/core/ipv4/ip4.c

@@ -59,11 +59,6 @@
 
 #include <string.h>
 
-#ifdef MEMLEAK_DEBUG
-static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__;
-#endif
-
-
 /** Set this to 0 in the rare case of wanting to call an extra function to
  * generate the IP checksum (in contrast to calculating it on-the-fly). */
 #ifndef LWIP_INLINE_IP_CHKSUM
@@ -150,7 +145,7 @@ ip4_route_src(const ip4_addr_t *dest, const ip4_addr_t *src)
 struct netif *
 ip4_route(const ip4_addr_t *dest)
 {
-#ifdef LWIP_ESP8266
+#if ESP_LWIP
   struct netif *non_default_netif = NULL;
 #endif
   struct netif *netif;
@@ -183,7 +178,7 @@ ip4_route(const ip4_addr_t *dest)
     }
   }
 
-#ifdef LWIP_ESP8266
+#if ESP_LWIP
   if (non_default_netif && !ip4_addr_isbroadcast(dest, non_default_netif)){
     return non_default_netif;
   }

+ 2 - 12
components/lwip/core/ipv4/ip4_addr.c

@@ -45,17 +45,8 @@
 
 /* used by IP_ADDR_ANY and IP_ADDR_BROADCAST in ip_addr.h */
 
-#ifdef LWIP_ESP8266
-//TO_DO
-//const ip_addr_t ip_addr_any ICACHE_RODATA_ATTR STORE_ATTR = IPADDR4_INIT(IPADDR_ANY);
-//const ip_addr_t ip_addr_broadcast ICACHE_RODATA_ATTR STORE_ATTR = IPADDR4_INIT(IPADDR_BROADCAST);
 const ip_addr_t ip_addr_any = IPADDR4_INIT(IPADDR_ANY);
 const ip_addr_t ip_addr_broadcast = IPADDR4_INIT(IPADDR_BROADCAST);
-#else
-const ip_addr_t ip_addr_any = IPADDR4_INIT(IPADDR_ANY);
-const ip_addr_t ip_addr_broadcast = IPADDR4_INIT(IPADDR_BROADCAST);
-#endif
-
 
 /**
  * Determine if an address is a broadcast address on a network interface
@@ -170,7 +161,7 @@ ip4addr_aton(const char *cp, ip4_addr_t *addr)
   u32_t parts[4];
   u32_t *pp = parts;
 
-#ifdef LWIP_ESP8266
+#if ESP_LWIP
 //#if 0
   char ch;
   unsigned long cutoff;
@@ -199,8 +190,7 @@ ip4addr_aton(const char *cp, ip4_addr_t *addr)
       }
     }
     
-#ifdef LWIP_ESP8266
-//#if 0
+#if ESP_IP4_ATON
     cutoff =(unsigned long)0xffffffff / (unsigned long)base;
     cutlim =(unsigned long)0xffffffff % (unsigned long)base;
     for (;;) {

+ 0 - 5
components/lwip/core/ipv4/ip_frag.c

@@ -51,11 +51,6 @@
 
 #include <string.h>
 
-#ifdef MEMLEAK_DEBUG
-static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__;
-#endif
-
-
 #if IP_REASSEMBLY
 /**
  * The IP reassembly code currently has the following limitations:

+ 0 - 4
components/lwip/core/ipv6/icmp6.c

@@ -56,10 +56,6 @@
 
 #include <string.h>
 
-#ifdef MEMLEAK_DEBUG
-static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__;
-#endif
-
 #ifndef LWIP_ICMP6_DATASIZE
 #define LWIP_ICMP6_DATASIZE   8
 #endif

+ 0 - 4
components/lwip/core/ipv6/ip6.c

@@ -59,10 +59,6 @@
 #include "lwip/debug.h"
 #include "lwip/stats.h"
 
-#ifdef MEMLEAK_DEBUG
-static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__;
-#endif
-
 /**
  * Finds the appropriate network interface for a given IPv6 address. It tries to select
  * a netif following a sequence of heuristics:

+ 0 - 5
components/lwip/core/ipv6/ip6_frag.c

@@ -52,11 +52,6 @@
 
 #include <string.h>
 
-#ifdef MEMLEAK_DEBUG
-static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__;
-#endif
-
-
 #if LWIP_IPV6 && LWIP_IPV6_REASS  /* don't build if not configured for use in lwipopts.h */
 
 

+ 0 - 5
components/lwip/core/ipv6/mld6.c

@@ -59,11 +59,6 @@
 
 #include <string.h>
 
-#ifdef MEMLEAK_DEBUG
-static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__;
-#endif
-
-
 /*
  * MLD constants
  */

+ 0 - 5
components/lwip/core/ipv6/nd6.c

@@ -60,11 +60,6 @@
 
 #include <string.h>
 
-#ifdef MEMLEAK_DEBUG
-static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__;
-#endif
-
-
 /* Router tables. */
 struct nd6_neighbor_cache_entry neighbor_cache[LWIP_ND6_NUM_NEIGHBORS];
 struct nd6_destination_cache_entry destination_cache[LWIP_ND6_NUM_DESTINATIONS];

+ 0 - 4
components/lwip/core/mem.c

@@ -65,10 +65,6 @@
 
 #include <string.h>
 
-#ifdef MEMLEAK_DEBUG
-static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__;
-#endif
-
 #if MEM_USE_POOLS
 
 #if MEMP_MEM_MALLOC

+ 0 - 4
components/lwip/core/memp.c

@@ -70,10 +70,6 @@
 
 #include <string.h>
 
-#ifdef MEMLEAK_DEBUG
-static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__;
-#endif
-
 #define LWIP_MEMPOOL(name,num,size,desc) LWIP_MEMPOOL_DECLARE(name,num,size,desc)
 #include "lwip/priv/memp_std.h"
 

+ 4 - 9
components/lwip/core/netif.c

@@ -81,10 +81,6 @@
 #define NETIF_LINK_CALLBACK(n)
 #endif /* LWIP_NETIF_LINK_CALLBACK */
 
-#ifdef MEMLEAK_DEBUG
-static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__;
-#endif
-
 struct netif *netif_list;
 struct netif *netif_default;
 
@@ -220,7 +216,7 @@ netif_add(struct netif *netif,
   /* netif not under DHCP control by default */
   netif->dhcp = NULL;
 
-#ifdef LWIP_ESP8266
+#if ESP_DHCP
   netif->dhcps_pcb = NULL;
 #endif
 
@@ -233,8 +229,7 @@ netif_add(struct netif *netif,
 #endif /* LWIP_AUTOIP */
 #if LWIP_IPV6_AUTOCONFIG
 
-#ifdef LWIP_ESP8266
-//#if 0
+#if ESP_IPV6_AUTOCONFIG
   netif->ip6_autoconfig_enabled = 1;
 #else
   /* IPv6 address autoconfiguration not enabled by default */
@@ -973,7 +968,7 @@ netif_create_ip6_linklocal_address(struct netif *netif, u8_t from_mac_48bit)
     }
   }
   
-#ifdef LWIP_ESP8266
+#if ESP_LWIP
     ip6_addr_set( ip_2_ip6(&netif->link_local_addr), ip_2_ip6(&netif->ip6_addr[0]) );
 #endif
 
@@ -1028,7 +1023,7 @@ netif_add_ip6_address(struct netif *netif, const ip6_addr_t *ip6addr, s8_t *chos
 }
 
 
-#ifdef LWIP_ESP8266
+#if ESP_LWIP
 void
 netif_create_ip4_linklocal_address(struct netif * netif)
 {

+ 7 - 52
components/lwip/core/pbuf.c

@@ -78,12 +78,8 @@
 
 #include <string.h>
 
-#ifdef MEMLEAK_DEBUG
-static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__;
-#endif
-
-#ifdef LWIP_ESP8266
-#define EP_OFFSET 0
+#if ESP_LWIP
+#include "esp_wifi_internal.h"
 #endif
 
 #define SIZEOF_STRUCT_PBUF        LWIP_MEM_ALIGN_SIZE(sizeof(struct pbuf))
@@ -207,12 +203,7 @@ struct pbuf *
 pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
 {
   struct pbuf *p, *q, *r;
-  
-#ifdef LWIP_ESP8266
-    u16_t offset = 0;
-#else
-    u16_t offset;
-#endif
+  u16_t offset = 0;
   
   s32_t rem_len; /* remaining length */
   LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc(length=%"U16_F")\n", length));
@@ -223,48 +214,16 @@ pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
     /* add room for transport (often TCP) layer header */
     offset = PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN;
 
-#ifdef LWIP_ESP8266    //TO_DO
-    offset += EP_OFFSET;
-#endif
-    
     break;
   case PBUF_IP:
     /* add room for IP layer header */
     offset = PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN;
 
-#ifdef LWIP_ESP8266    //TO_DO
-    offset += EP_OFFSET;
-#endif
-    
     break;
   case PBUF_LINK:
     /* add room for link layer header */
     offset = PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN;
 
-#ifdef LWIP_ESP8266    //TO_DO
-    /*
-     * 1. LINK_HLEN 14Byte will be remove in WLAN layer
-     * 2. IEEE80211_HDR_MAX_LEN needs 40 bytes.
-     * 3. encryption needs exra 4 bytes ahead of actual data payload, and require
-     *     DAddr and SAddr to be 4-byte aligned.
-     * 4. TRANSPORT and IP are all 20, 4 bytes aligned, nice...
-     * 5. LCC add 6 bytes more, We don't consider WAPI yet...
-     * 6. define LWIP_MEM_ALIGN to be 4 Byte aligned, pbuf struct is 16B, Only thing may be
-     *     matter is ether_hdr is not 4B aligned.
-     *
-     * So, we need extra (40 + 4 - 14) = 30 and it's happen to be 4-Byte aligned
-     *
-     *    1. lwip
-     *         | empty 30B    | eth_hdr (14B)  | payload ...|
-     *              total: 44B ahead payload
-     *    2. net80211
-     *         | max 80211 hdr, 32B | ccmp/tkip iv (8B) | sec rsv(4B) | payload ...|
-     *              total: 40B ahead sec_rsv and 44B ahead payload
-     *
-     */
-    offset += EP_OFFSET;                //remove LINK hdr in wlan
-#endif   
-
     break;
   case PBUF_RAW_TX:
     /* add room for encapsulating link layer headers (e.g. 802.11) */
@@ -273,10 +232,6 @@ pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
   case PBUF_RAW:
     offset = 0;
 
-#ifdef LWIP_ESP8266    //TO_DO
-    offset += EP_OFFSET;  
-#endif
-
     break;
   default:
     LWIP_ASSERT("pbuf_alloc: bad pbuf layer", 0);
@@ -395,9 +350,10 @@ pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
   /* set flags */
   p->flags = 0;
   
-#ifdef LWIP_ESP8266
+#if ESP_LWIP
   p->eb = NULL; 
 #endif
+
   LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc(length=%"U16_F") == %p\n", length, (void *)p));
   return p;
 }
@@ -763,9 +719,8 @@ pbuf_free(struct pbuf *p)
         /* is this a ROM or RAM referencing pbuf? */
         } else if (type == PBUF_ROM || type == PBUF_REF) {
         
-#ifdef LWIP_ESP8266
-          extern void system_pp_recycle_rx_pkt(void*);
-          if (type == PBUF_REF && p->eb != NULL ) system_pp_recycle_rx_pkt(p->eb);
+#if ESP_LWIP
+          if (type == PBUF_REF && p->eb != NULL ) esp_wifi_internal_free_rx_buffer(p->eb);
 #endif
 
             memp_free(MEMP_PBUF, p);

+ 0 - 4
components/lwip/core/raw.c

@@ -54,10 +54,6 @@
 
 #include <string.h>
 
-#ifdef MEMLEAK_DEBUG
-static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__;
-#endif
-
 /** The list of RAW PCBs */
 static struct raw_pcb *raw_pcbs;
 

+ 0 - 4
components/lwip/core/stats.c

@@ -47,10 +47,6 @@
 
 #include <string.h>
 
-#ifdef MEMLEAK_DEBUG
-static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__;
-#endif
-
 struct stats_ lwip_stats;
 
 #if defined(LWIP_DEBUG) || LWIP_STATS_DISPLAY

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio