Explorar el Código

Merge branch 'master' into driver_merge_tmp/merge_timer

# Conflicts:
#	docs/index.rst
Wangjialin hace 9 años
padre
commit
a5ad8090cf
Se han modificado 100 ficheros con 4218 adiciones y 275 borrados
  1. 5 0
      .gitignore
  2. 12 9
      .gitlab-ci.yml
  3. 1 1
      components/bootloader/Makefile.projbuild
  4. 1 1
      components/bt/bt.c
  5. 359 0
      components/driver/include/driver/pcnt.h
  6. 1 0
      components/driver/include/driver/periph_ctrl.h
  7. 7 7
      components/driver/include/driver/uart.h
  8. 1 0
      components/driver/ledc.c
  9. 278 0
      components/driver/pcnt.c
  10. 12 0
      components/driver/periph_ctrl.c
  11. 1 0
      components/driver/rmt.c
  12. 2 1
      components/driver/uart.c
  13. 4 21
      components/esp32/cpu_freq.c
  14. 2 4
      components/esp32/cpu_start.c
  15. 44 0
      components/esp32/cpu_util.c
  16. 19 0
      components/esp32/deepsleep.c
  17. 41 0
      components/esp32/hw_random.c
  18. 23 14
      components/esp32/include/esp_deepsleep.h
  19. 49 108
      components/esp32/include/esp_system.h
  20. 0 48
      components/esp32/include/esp_types.h
  21. 15 0
      components/esp32/include/esp_wifi.h
  22. 9 13
      components/esp32/include/esp_wifi_internal.h
  23. 8 0
      components/esp32/include/rom/ets_sys.h
  24. 1 0
      components/esp32/include/rom/uart.h
  25. 17 4
      components/esp32/include/soc/cpu.h
  26. 30 0
      components/esp32/include/soc/pcnt_reg.h
  27. 12 1
      components/esp32/include/soc/pcnt_struct.h
  28. 2 2
      components/esp32/include/soc/soc.h
  29. 18 0
      components/esp32/include/soc/wdev_reg.h
  30. 1 1
      components/esp32/include/xtensa/core-macros.h
  31. 1 1
      components/esp32/lib
  32. 124 0
      components/esp32/lib_printf.c
  33. 5 15
      components/esp32/panic.c
  34. 2 2
      components/esp32/phy_init.c
  35. 142 0
      components/esp32/rtc.h
  36. 158 0
      components/esp32/system_api.c
  37. 17 0
      components/esp32/test/component.mk
  38. BIN
      components/esp32/test/logo.jpg
  39. 293 0
      components/esp32/test/test_ahb_arb.c
  40. 51 0
      components/esp32/test/test_ahb_arb_asm.S
  41. 132 0
      components/esp32/test/test_fastbus.c
  42. 32 0
      components/esp32/test/test_fastbus_asm.S
  43. 193 0
      components/esp32/test/test_fp.c
  44. 77 0
      components/esp32/test/test_miniz.c
  45. 91 0
      components/esp32/test/test_tjpgd.c
  46. 205 0
      components/esp32/test/test_unal_dma.c
  47. 6 6
      components/freertos/include/freertos/FreeRTOS.h
  48. 1 2
      components/freertos/include/freertos/FreeRTOSConfig.h
  49. 13 0
      components/freertos/include/freertos/list.h
  50. 5 0
      components/freertos/queue.c
  51. 4 0
      components/freertos/tasks.c
  52. 5 0
      components/freertos/test/component.mk
  53. 229 0
      components/freertos/test/test_freertos.c
  54. 105 0
      components/freertos/test/test_freertos_eventgroups.c
  55. 22 0
      components/freertos/test/test_freertos_task_delete.c
  56. 60 0
      components/freertos/test/test_newlib_reent.c
  57. 26 0
      components/freertos/test/test_panic.c
  58. 197 0
      components/freertos/test/test_ringbuf.c
  59. 58 0
      components/freertos/test/test_tls_deletecb.c
  60. 3 4
      components/idf_test/unit_test/CIConfigs/UT_Function_SYS_01.yml
  61. 0 3
      components/log/include/esp_log.h
  62. 1 0
      components/mbedtls/port/esp_bignum.c
  63. 5 0
      components/mbedtls/test/component.mk
  64. 134 0
      components/mbedtls/test/test_mbedtls.c
  65. 5 0
      components/newlib/test/component.mk
  66. 102 0
      components/newlib/test/test_newlib.c
  67. 26 0
      components/newlib/time.c
  68. 5 0
      components/nvs_flash/test/component.mk
  69. 51 0
      components/nvs_flash/test/test_nvs.c
  70. 0 0
      components/nvs_flash/test_nvs_host/Makefile
  71. 0 0
      components/nvs_flash/test_nvs_host/catch.hpp
  72. 0 0
      components/nvs_flash/test_nvs_host/crc.cpp
  73. 0 0
      components/nvs_flash/test_nvs_host/crc.h
  74. 0 0
      components/nvs_flash/test_nvs_host/main.cpp
  75. 0 0
      components/nvs_flash/test_nvs_host/sdkconfig.h
  76. 0 0
      components/nvs_flash/test_nvs_host/spi_flash_emulation.cpp
  77. 0 0
      components/nvs_flash/test_nvs_host/spi_flash_emulation.h
  78. 0 0
      components/nvs_flash/test_nvs_host/test_compressed_enum_table.cpp
  79. 0 0
      components/nvs_flash/test_nvs_host/test_intrusive_list.cpp
  80. 0 0
      components/nvs_flash/test_nvs_host/test_nvs.cpp
  81. 0 0
      components/nvs_flash/test_nvs_host/test_spi_flash_emulation.cpp
  82. 1 1
      components/openssl/platform/ssl_pm.c
  83. 5 0
      components/partition_table/test/component.mk
  84. 95 0
      components/partition_table/test/test_partition.c
  85. 5 0
      components/spi_flash/test/component.mk
  86. 83 0
      components/spi_flash/test/test_mmap.c
  87. 92 0
      components/spi_flash/test/test_spi_flash.c
  88. 1 1
      components/wpa_supplicant/component.mk
  89. 1 0
      components/wpa_supplicant/port/include/endian.h
  90. 64 0
      components/wpa_supplicant/port/os_xtensa.c
  91. 66 0
      docs/api/pcnt.rst
  92. 1 1
      docs/index.rst
  93. 1 1
      examples/01_hello_world/main/hello_world_main.c
  94. 1 0
      examples/04_https_request/main/https_request_main.c
  95. 1 1
      examples/06_sntp/main/sntp_main.c
  96. 1 1
      examples/07_nvs_rw_value/main/nvs_rw_value.c
  97. 1 1
      examples/08_nvs_rw_blob/main/nvs_rw_blob.c
  98. 9 0
      examples/12_pcnt/Makefile
  99. 3 0
      examples/12_pcnt/main/component.mk
  100. 226 0
      examples/12_pcnt/main/pcnt_test.c

+ 5 - 0
.gitignore

@@ -24,3 +24,8 @@ examples/*/build
 docs/_build/
 docs/doxygen-warning-log.txt
 docs/xml/
+
+# Unit test app files
+tools/unit-test-app/sdkconfig
+tools/unit-test-app/sdkconfig.old
+tools/unit-test-app/build

+ 12 - 9
.gitlab-ci.yml

@@ -46,6 +46,10 @@ build_template_app:
     - sed -i.bak -e's/CONFIG_OPTIMIZATION_LEVEL_DEBUG\=y/CONFIG_OPTIMIZATION_LEVEL_RELEASE=y/' sdkconfig
     - make defconfig
     - make all V=1
+    # Check if there are any stray printf/ets_printf references in WiFi libs
+    - cd ../components/esp32/lib
+    - test $(xtensa-esp32-elf-nm *.a | grep -w printf | wc -l) -eq 0
+    - test $(xtensa-esp32-elf-nm *.a | grep -w ets_printf | wc -l) -eq 0
 
 
 .build_gitlab: &build_template
@@ -78,18 +82,17 @@ build_esp_idf_tests:
   <<: *build_template
   artifacts:
     paths:
-      - ./esp-idf-tests/build/*.bin
-      - ./esp-idf-tests/build/*.elf
-      - ./esp-idf-tests/build/*.map
-      - ./esp-idf-tests/build/bootloader/*.bin
+      - ./tools/unit-test-app/build/*.bin
+      - ./tools/unit-test-app/build/*.elf
+      - ./tools/unit-test-app/build/*.map
+      - ./tools/unit-test-app/build/bootloader/*.bin
     expire_in: 6 mos
 
   script:
-    - git clone $GITLAB_SSH_SERVER/idf/esp-idf-tests.git
-    - cd esp-idf-tests
+    - cd tools/unit-test-app
     - git checkout ${CI_BUILD_REF_NAME} || echo "Using default branch..."
     - make defconfig
-    - make
+    - make TESTS_ALL=1
 
 build_examples:
   <<: *build_template
@@ -131,7 +134,7 @@ test_nvs_on_host:
   tags:
     - nvs_host_test
   script:
-    - cd components/nvs_flash/test
+    - cd components/nvs_flash/test_nvs_host
     - make test
 
 test_build_system:
@@ -289,7 +292,7 @@ deploy_docs:
   variables:
     # jobs MUST set CONFIG_FILE in before_script, and overwrite the variables above if necessary
     LOCAL_ENV_CONFIG_PATH: /home/gitlab-runner/LocalConfig/ESP32_IDF
-    BIN_PATH: "$CI_PROJECT_DIR/esp-idf-tests/build/"
+    BIN_PATH: "$CI_PROJECT_DIR/tools/unit-test-app/build/"
     LOG_PATH: "$CI_PROJECT_DIR/$CI_BUILD_REF"
     APP_NAME: "ut"
     TEST_CASE_FILE_PATH: "$CI_PROJECT_DIR/components/idf_test/unit_test"

+ 1 - 1
components/bootloader/Makefile.projbuild

@@ -20,7 +20,7 @@ export SECURE_BOOT_SIGNING_KEY  # used by bootloader_support component
 
 # Custom recursive make for bootloader sub-project
 BOOTLOADER_MAKE=+$(MAKE) -C $(BOOTLOADER_COMPONENT_PATH)/src \
-	V=$(V) BUILD_DIR_BASE=$(BOOTLOADER_BUILD_DIR)
+	V=$(V) BUILD_DIR_BASE=$(BOOTLOADER_BUILD_DIR) TEST_COMPONENTS=
 
 .PHONY: bootloader-clean bootloader-flash bootloader $(BOOTLOADER_BIN)
 

+ 1 - 1
components/bt/bt.c

@@ -115,7 +115,7 @@ static struct osi_funcs_t osi_funcs = {
     ._mutex_create = mutex_create_wrapper,
     ._mutex_lock = mutex_lock_wrapper,
     ._mutex_unlock = mutex_unlock_wrapper,
-    ._read_efuse_mac = system_efuse_read_mac,
+    ._read_efuse_mac = esp_efuse_read_mac,
 };
 
 static void bt_controller_task(void *pvParam)

+ 359 - 0
components/driver/include/driver/pcnt.h

@@ -0,0 +1,359 @@
+#ifndef __PCNT_H__
+#define __PCNT_H__
+
+#include <esp_types.h>
+#include "esp_intr.h"
+#include "esp_err.h"
+#include "freertos/FreeRTOS.h"
+#include "freertos/semphr.h"
+#include "freertos/xtensa_api.h"
+#include "soc/soc.h"
+#include "soc/pcnt_reg.h"
+#include "soc/pcnt_struct.h"
+#include "soc/gpio_sig_map.h"
+#include "driver/gpio.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PCNT_PIN_NOT_USED     (-1)  /*!< Pin are not used */
+
+typedef enum {
+    PCNT_MODE_KEEP = 0,             /*!< Control mode: won't change counter mode*/
+    PCNT_MODE_REVERSE = 1,          /*!< Control mode: invert counter mode(increase -> decrease, decrease -> increase);*/
+    PCNT_MODE_DISABLE = 2,          /*!< Control mode: Inhibit counter(counter value will not change in this condition)*/
+    PCNT_MODE_MAX
+} pcnt_ctrl_mode_t;
+
+typedef enum {
+    PCNT_COUNT_DIS = 0,            /*!< Counter mode: Decrease counter value*/
+    PCNT_COUNT_INC = 1,            /*!< Counter mode: Increase counter value*/
+    PCNT_COUNT_DEC = 2,            /*!< Counter mode: Inhibit counter(counter value will not change in this condition)*/
+    PCNT_COUNT_MAX
+} pcnt_count_mode_t;
+
+typedef enum {
+    PCNT_UNIT_0 = 0,                 /*!< PCNT unit0 */
+    PCNT_UNIT_1 = 1,                 /*!< PCNT unit1 */
+    PCNT_UNIT_2 = 2,                 /*!< PCNT unit2 */
+    PCNT_UNIT_3 = 3,                 /*!< PCNT unit3 */
+    PCNT_UNIT_4 = 4,                 /*!< PCNT unit4 */
+    PCNT_UNIT_5 = 5,                 /*!< PCNT unit5 */
+    PCNT_UNIT_6 = 6,                 /*!< PCNT unit6 */
+    PCNT_UNIT_7 = 7,                 /*!< PCNT unit7 */
+    PCNT_UNIT_MAX,
+} pcnt_unit_t; 
+
+typedef enum{
+    PCNT_CHANNEL_0 = 0x00,           /*!< PCNT channel0 */
+    PCNT_CHANNEL_1 = 0x01,           /*!< PCNT channel1 */
+    PCNT_CHANNEL_MAX,
+} pcnt_channel_t;
+
+typedef enum {
+    PCNT_EVT_L_LIM = 0,             /*!< PCNT watch point event: Minimum counter value */
+    PCNT_EVT_H_LIM = 1,             /*!< PCNT watch point event: Maximum counter value*/
+    PCNT_EVT_THRES_0 = 2,            /*!< PCNT watch point event: threshold0 value event*/
+    PCNT_EVT_THRES_1 = 3,            /*!< PCNT watch point event: threshold1 value event*/
+    PCNT_EVT_ZERO = 4,              /*!< PCNT watch point event: counter value zero event*/
+    PCNT_EVT_MAX
+} pcnt_evt_type_t;
+
+/**
+ * @brief Pulse Counter configure struct
+ */
+typedef struct {
+    int pulse_gpio_num;             /*!< Pulse input gpio_num, if you want to use gpio16, pulse_gpio_num = 16, a negative value will be ignored */
+    int ctrl_gpio_num;              /*!< Contol signal input gpio_num, a negative value will be ignored*/
+    pcnt_ctrl_mode_t lctrl_mode;    /*!< PCNT low control mode*/
+    pcnt_ctrl_mode_t hctrl_mode;    /*!< PCNT high control mode*/
+    pcnt_count_mode_t pos_mode;     /*!< PCNT positive edge count mode*/
+    pcnt_count_mode_t neg_mode;     /*!< PCNT negative edge count mode*/
+    int16_t counter_h_lim;          /*!< Maximum counter value */
+    int16_t counter_l_lim;          /*!< Minimum counter value */
+    pcnt_unit_t unit;               /*!< PCNT unit number */
+    pcnt_channel_t channel;         /*!< the PCNT channel */
+} pcnt_config_t;
+
+/**
+ * @brief Configure Pulse Counter unit
+ *
+ * @param pcnt_config Pointer of Pulse Counter unit configure parameter
+ *
+ * @return
+ *     - ESP_OK Success
+ *     - ESP_ERR_INVALID_ARG Parameter error
+ */
+esp_err_t pcnt_unit_config(pcnt_config_t *pcnt_config);
+
+/**
+ * @brief Get pulse counter value
+ *
+ * @param pcnt_unit  Pulse Counter unit number
+ * @param count Pointer to accept counter value
+ *
+ * @return  
+ *     - ESP_OK Success
+ *     - ESP_ERR_INVALID_ARG Parameter error
+ */
+esp_err_t pcnt_get_counter_value(pcnt_unit_t pcnt_unit, int16_t* count);
+
+/**
+ * @brief Pause PCNT counter of PCNT unit
+ *
+ * @param pcnt_unit PCNT unit number
+ *
+ * @return
+ *     - ESP_OK Success
+ *     - ESP_ERR_INVALID_ARG Parameter error
+ */
+esp_err_t pcnt_counter_pause(pcnt_unit_t pcnt_unit);
+
+/**
+ * @brief Resume counting for PCNT counter
+ *
+ * @param pcnt_unit PCNT unit number, select from pcnt_unit_t
+ *
+ * @return
+ *     - ESP_OK Success
+ *     - ESP_ERR_INVALID_ARG Parameter error
+ */
+esp_err_t pcnt_counter_resume(pcnt_unit_t pcnt_unit);
+
+/**
+ * @brief Clear and reset PCNT counter value to zero
+ *
+ * @param  pcnt_unit PCNT unit number, select from pcnt_unit_t
+ *
+ * @return
+ *     - ESP_OK Success
+ *     - ESP_ERR_INVALID_ARG Parameter error
+ */
+esp_err_t pcnt_counter_clear(pcnt_unit_t pcnt_unit);
+
+/**
+ * @brief Enable PCNT interrupt for PCNT unit
+ *        @note
+ *        Each Pulse counter unit has five watch point events that share the same interrupt.
+ *        Configure events with pcnt_event_enable() and pcnt_event_disable()
+ *
+ * @param pcnt_unit PCNT unit number
+ *
+ * @return
+ *     - ESP_OK Success
+ *     - ESP_ERR_INVALID_ARG Parameter error
+ */
+esp_err_t pcnt_intr_enable(pcnt_unit_t pcnt_unit);
+
+/**
+ * @brief Disable PCNT interrupt for PCNT uint
+ *
+ * @param pcnt_unit PCNT unit number
+ *
+ * @return
+ *     - ESP_OK Success
+ *     - ESP_ERR_INVALID_ARG Parameter error
+ */
+esp_err_t pcnt_intr_disable(pcnt_unit_t pcnt_unit);
+
+/**
+ * @brief Enable PCNT event of PCNT unit
+ *
+ * @param unit PCNT unit number
+ * @param evt_type Watch point event type.
+ *                 All enabled events share the same interrupt (one interrupt per pulse counter unit).
+ * @return
+ *     - ESP_OK Success
+ *     - ESP_ERR_INVALID_ARG Parameter error
+ */
+esp_err_t pcnt_event_enable(pcnt_unit_t unit, pcnt_evt_type_t evt_type);
+
+/**
+ * @brief Disable PCNT event of PCNT unit
+ *
+ * @param unit PCNT unit number
+ * @param evt_type Watch point event type.
+ *                 All enabled events share the same interrupt (one interrupt per pulse counter unit).
+ * @return
+ *     - ESP_OK Success
+ *     - ESP_ERR_INVALID_ARG Parameter error
+ */
+esp_err_t pcnt_event_disable(pcnt_unit_t unit, pcnt_evt_type_t evt_type);
+
+/**
+ * @brief Set PCNT event value of PCNT unit
+ *
+ * @param unit PCNT unit number
+ * @param evt_type Watch point event type.
+ *                 All enabled events share the same interrupt (one interrupt per pulse counter unit).
+ *
+ * @param value Counter value for PCNT event
+ *
+ * @return
+ *     - ESP_OK Success
+ *     - ESP_ERR_INVALID_ARG Parameter error
+ */
+esp_err_t pcnt_set_event_value(pcnt_unit_t unit, pcnt_evt_type_t evt_type, int16_t value);
+
+/**
+ * @brief Get PCNT event value of PCNT unit
+ *
+ * @param unit PCNT unit number
+ * @param evt_type Watch point event type.
+ *                 All enabled events share the same interrupt (one interrupt per pulse counter unit).
+ * @param value Pointer to accept counter value for PCNT event
+ *
+ * @return
+ *     - ESP_OK Success
+ *     - ESP_ERR_INVALID_ARG Parameter error
+ */
+esp_err_t pcnt_get_event_value(pcnt_unit_t unit, pcnt_evt_type_t evt_type, int16_t *value);
+
+/**
+ * @brief Register PCNT interrupt handler, the handler is an ISR.
+ *        The handler will be attached to the same CPU core that this function is running on.
+ *        @note
+ *        Users should know that which CPU is running and then pick a INUM that is not used by system.
+ *        We can find the information of INUM and interrupt level in soc.h.
+ *
+ * @param pcnt_intr_num PCNT interrupt number, check the info in soc.h, and please see the core-isa.h for more details
+ * @param fn Interrupt handler function.
+ *        @note
+ *        Note that the handler function MUST be defined with attribution of "IRAM_ATTR".
+ * @param arg Parameter for handler function
+ *
+ * @return
+ *     - ESP_OK Success
+ *     - ESP_ERR_INVALID_ARG Function pointer error.
+ */
+esp_err_t pcnt_isr_register(uint32_t pcnt_intr_num, void (*fn)(void*), void * arg);
+
+/**
+ * @brief Configure PCNT pulse signal input pin and control input pin
+ *
+ * @param unit PCNT unit number
+ * @param channel PCNT channel number
+ * @param pulse_io Pulse signal input GPIO
+ *        @note
+ *        Set to PCNT_PIN_NOT_USED if unused.
+ * @param ctrl_io Control signal input GPIO
+ *        @note
+ *        Set to PCNT_PIN_NOT_USED if unused.
+ *
+ * @return
+ *     - ESP_OK Success
+ *     - ESP_ERR_INVALID_ARG Parameter error
+ */
+esp_err_t pcnt_set_pin(pcnt_unit_t unit, pcnt_channel_t channel, int pulse_io, int ctrl_io);
+
+/**
+ * @brief Enable PCNT input filter
+ *
+ * @param unit PCNT unit number
+ *
+ * @return
+ *     - ESP_OK Success
+ *     - ESP_ERR_INVALID_ARG Parameter error
+ */
+esp_err_t pcnt_filter_enable(pcnt_unit_t unit);
+
+/**
+ * @brief Disable PCNT input filter
+ *
+ * @param unit PCNT unit number
+ *
+ * @return
+ *     - ESP_OK Success
+ *     - ESP_ERR_INVALID_ARG Parameter error
+ */
+esp_err_t pcnt_filter_disable(pcnt_unit_t unit);
+
+/**
+ * @brief Set PCNT filter value
+ *
+ * @param unit PCNT unit number
+ * @param filter_val PCNT signal filter value, counter in APB_CLK cycles.
+ *        Any pulses lasting shorter than this will be ignored when the filter is enabled.
+ *        @note
+ *        filter_val is a 10-bit value, so the maximum filter_val should be limited to 1023.
+ *
+ * @return
+ *     - ESP_OK Success
+ *     - ESP_ERR_INVALID_ARG Parameter error
+ */
+esp_err_t pcnt_set_filter_value(pcnt_unit_t unit, uint16_t filter_val);
+
+/**
+ * @brief Get PCNT filter value
+ *
+ * @param unit PCNT unit number
+ * @param filter_val Pointer to accept PCNT filter value.
+ *
+ * @return
+ *     - ESP_OK Success
+ *     - ESP_ERR_INVALID_ARG Parameter error
+ */
+esp_err_t pcnt_get_filter_value(pcnt_unit_t unit, uint16_t *filter_val);
+
+/**
+ * @brief Set PCNT counter mode
+ *
+ * @param unit PCNT unit number
+ * @param channel PCNT channel number
+ * @param pos_mode Counter mode when detecting positive edge
+ * @param neg_mode Counter mode when detecting negative edge
+ * @param hctrl_mode Counter mode when control signal is high level
+ * @param lctrl_mode Counter mode when control signal is low level
+ *
+ * @return
+ *     - ESP_OK Success
+ *     - ESP_ERR_INVALID_ARG Parameter error
+ */
+esp_err_t pcnt_set_mode(pcnt_unit_t unit, pcnt_channel_t channel,
+                        pcnt_count_mode_t pos_mode, pcnt_count_mode_t neg_mode,
+                        pcnt_ctrl_mode_t hctrl_mode, pcnt_ctrl_mode_t lctrl_mode);
+
+
+/**
+ * @addtogroup pcnt-examples
+ *
+ * @{
+ *
+ * EXAMPLE OF PCNT CONFIGURATION
+ * ==============================
+ * @code{c}
+ * //1. Config PCNT unit
+ * pcnt_config_t pcnt_config = {
+ *     .pulse_gpio_num = 4,         //set gpio4 as pulse input gpio
+ *     .ctrl_gpio_num = 5,          //set gpio5 as control gpio
+ *     .channel = PCNT_CHANNEL_0,         //use unit 0 channel 0
+ *     .lctrl_mode = PCNT_MODE_REVERSE,   //when control signal is low ,reverse the primary counter mode(inc->dec/dec->inc)
+ *     .hctrl_mode = PCNT_MODE_KEEP,      //when control signal is high,keep the primary counter mode
+ *     .pos_mode = PCNT_COUNT_INC,        //increment the counter
+ *     .neg_mode = PCNT_COUNT_DIS,        //keep the counter value
+ *     .counter_h_lim = 10,
+ *     .counter_l_lim = -10,
+ * };
+ * pcnt_unit_config(&pcnt_config);        //init unit
+ * @endcode
+ *
+ * EXAMPLE OF PCNT EVENT SETTING
+ * ==============================
+ * @code{c}
+ * //2. Configure PCNT watchpoint event.
+ * pcnt_set_event_value(PCNT_UNIT_0, PCNT_EVT_THRES_1, 5);   //set thres1 value
+ * pcnt_event_enable(PCNT_UNIT_0, PCNT_EVT_THRES_1);         //enable thres1 event
+ * @endcode
+ *
+ * For more examples please refer to PCNT example code in IDF_PATH/examples
+ *
+ * @}
+ */
+
+#ifdef __cplusplus 
+}
+#endif
+
+
+#endif

+ 1 - 0
components/driver/include/driver/periph_ctrl.h

@@ -40,6 +40,7 @@ typedef enum {
     PERIPH_UHCI0_MODULE,
     PERIPH_UHCI1_MODULE,
     PERIPH_RMT_MODULE,
+    PERIPH_PCNT_MODULE,
 } periph_module_t;
 
 /**

+ 7 - 7
components/driver/include/driver/uart.h

@@ -167,25 +167,25 @@ esp_err_t uart_get_word_length(uart_port_t uart_num, uart_word_length_t* data_bi
  * @brief Set UART stop bits.
  *
  * @param uart_num  UART_NUM_0, UART_NUM_1 or UART_NUM_2
- * @param bit_num  UART stop bits
+ * @param stop_bits  UART stop bits
  *
  * @return
  *     - ESP_OK   Success
  *     - ESP_FAIL Fail
  */
-esp_err_t uart_set_stop_bits(uart_port_t uart_num, uart_stop_bits_t bit_num);
+esp_err_t uart_set_stop_bits(uart_port_t uart_num, uart_stop_bits_t stop_bits);
 
 /**
  * @brief Set UART stop bits.
  *
  * @param uart_num  UART_NUM_0, UART_NUM_1 or UART_NUM_2
- * @param stop_bit  Pointer to accept value of UART stop bits.
+ * @param stop_bits  Pointer to accept value of UART stop bits.
  *
  * @return
  *     - ESP_FAIL Parameter error
  *     - ESP_OK   Success, result will be put in (*stop_bit)
  */
-esp_err_t uart_get_stop_bits(uart_port_t uart_num, uart_stop_bits_t* stop_bit);
+esp_err_t uart_get_stop_bits(uart_port_t uart_num, uart_stop_bits_t* stop_bits);
 
 /**
  * @brief Set UART parity.
@@ -216,13 +216,13 @@ esp_err_t uart_get_parity(uart_port_t uart_num, uart_parity_t* parity_mode);
  * @brief Set UART baud rate.
  *
  * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
- * @param baud_rate UART baud-rate.
+ * @param baudrate UART baud rate.
  *
  * @return
  *     - ESP_FAIL Parameter error
  *     - ESP_OK   Success
  */
-esp_err_t uart_set_baudrate(uart_port_t uart_num, uint32_t baud_rate);
+esp_err_t uart_set_baudrate(uart_port_t uart_num, uint32_t baudrate);
 
 /**
  * @brief Get UART bit-rate.
@@ -241,7 +241,7 @@ esp_err_t uart_get_baudrate(uart_port_t uart_num, uint32_t* baudrate);
  * @brief Set UART line inverse mode
  *
  * @param uart_num  UART_NUM_0, UART_NUM_1 or UART_NUM_2
- * @param inverse_mask Choose the wires that need to be inversed.
+ * @param inverse_mask Choose the wires that need to be inverted.
  *        Inverse_mask should be chosen from UART_INVERSE_RXD/UART_INVERSE_TXD/UART_INVERSE_RTS/UART_INVERSE_CTS, combine with OR operation.
  *
  * @return

+ 1 - 0
components/driver/ledc.c

@@ -191,6 +191,7 @@ esp_err_t ledc_channel_config(ledc_channel_config_t* ledc_conf)
     LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error", ESP_ERR_INVALID_ARG);
     LEDC_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "ledc GPIO output number error", ESP_ERR_INVALID_ARG);
     LEDC_CHECK(timer_select <= LEDC_TIMER_3, "ledc timer error", ESP_ERR_INVALID_ARG);
+    periph_module_enable(PERIPH_LEDC_MODULE);
     esp_err_t ret = ESP_OK;
     /*set channel parameters*/
     /*   channel parameters decide how the waveform looks like in one period*/

+ 278 - 0
components/driver/pcnt.c

@@ -0,0 +1,278 @@
+// 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 "esp_log.h"
+#include "driver/pcnt.h"
+#include "driver/periph_ctrl.h"
+
+#define PCNT_CHANNEL_ERR_STR  "PCNT CHANNEL ERROR"
+#define PCNT_UNIT_ERR_STR  "PCNT UNIT ERROR"
+#define PCNT_GPIO_ERR_STR  "PCNT GPIO NUM ERROR"
+#define PCNT_ADDRESS_ERR_STR  "PCNT ADDRESS ERROR"
+#define PCNT_PARAM_ERR_STR   "PCNT PARAM ERROR"
+#define PCNT_COUNT_MODE_ERR_STR "PCNT COUNTER MODE ERROR"
+#define PCNT_CTRL_MODE_ERR_STR  "PCNT CTRL MODE ERROR"
+#define PCNT_EVT_TYPE_ERR_STR   "PCNT value type error"
+#define PCNT_CHECK(a,str,ret_val) if(!(a)) { \
+	    ESP_LOGE(PCNT_TAG,"%s:%d (%s):%s", __FILE__, __LINE__, __FUNCTION__, str); \
+		return (ret_val); \
+        }
+
+static const char* PCNT_TAG = "PCNT";
+static portMUX_TYPE pcnt_spinlock = portMUX_INITIALIZER_UNLOCKED;
+
+#define PCNT_ENTER_CRITICAL(mux)    portENTER_CRITICAL(mux)
+#define PCNT_EXIT_CRITICAL(mux)     portEXIT_CRITICAL(mux)
+#define PCNT_ENTER_CRITICAL_ISR(mux)    portENTER_CRITICAL_ISR(mux)
+#define PCNT_EXIT_CRITICAL_ISR(mux)     portEXIT_CRITICAL_ISR(mux)
+
+esp_err_t pcnt_unit_config(pcnt_config_t *pcnt_config)
+{
+    uint8_t unit = pcnt_config->channel;
+    uint8_t channel = pcnt_config->unit;
+    int input_io = pcnt_config->pulse_gpio_num;
+    int ctrl_io = pcnt_config->ctrl_gpio_num;
+
+    PCNT_CHECK(unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
+    PCNT_CHECK(channel < PCNT_CHANNEL_MAX, PCNT_CHANNEL_ERR_STR, ESP_ERR_INVALID_ARG);
+    PCNT_CHECK(input_io < 0 || (GPIO_IS_VALID_GPIO(input_io) && (input_io != ctrl_io)), "PCNT pluse input io error", ESP_ERR_INVALID_ARG);
+    PCNT_CHECK(ctrl_io < 0 || GPIO_IS_VALID_GPIO(ctrl_io), "PCNT ctrl io error", ESP_ERR_INVALID_ARG);
+    PCNT_CHECK((pcnt_config->pos_mode < PCNT_COUNT_MAX) && (pcnt_config->neg_mode < PCNT_COUNT_MAX), PCNT_COUNT_MODE_ERR_STR, ESP_ERR_INVALID_ARG);
+    PCNT_CHECK((pcnt_config->hctrl_mode < PCNT_MODE_MAX) && (pcnt_config->lctrl_mode < PCNT_MODE_MAX), PCNT_CTRL_MODE_ERR_STR, ESP_ERR_INVALID_ARG);
+    /*Enalbe hardware module*/
+    periph_module_enable(PERIPH_PCNT_MODULE);
+    /*Set counter range*/
+    pcnt_set_event_value(unit, PCNT_EVT_H_LIM, pcnt_config->counter_h_lim);
+    pcnt_set_event_value(unit, PCNT_EVT_L_LIM, pcnt_config->counter_l_lim);
+    /*Default value after reboot is positive, we disable these events like others*/
+    pcnt_event_disable(unit, PCNT_EVT_H_LIM);
+    pcnt_event_disable(unit, PCNT_EVT_L_LIM);
+    pcnt_event_disable(unit, PCNT_EVT_ZERO);
+    pcnt_filter_disable(unit);
+    /*set pulse input and control mode*/
+    pcnt_set_mode(unit, channel, pcnt_config->pos_mode, pcnt_config->neg_mode, pcnt_config->hctrl_mode, pcnt_config->lctrl_mode);
+    /*Set pulse input and control pins*/
+    pcnt_set_pin(unit, channel, input_io, ctrl_io);
+    return ESP_OK;
+}
+
+esp_err_t pcnt_set_mode(pcnt_unit_t unit, pcnt_channel_t channel, pcnt_count_mode_t pos_mode, pcnt_count_mode_t neg_mode, pcnt_ctrl_mode_t hctrl_mode, pcnt_ctrl_mode_t lctrl_mode)
+{
+    PCNT_CHECK(unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
+    PCNT_CHECK(channel < PCNT_CHANNEL_MAX, PCNT_CHANNEL_ERR_STR, ESP_ERR_INVALID_ARG);
+    PCNT_CHECK((pos_mode < PCNT_COUNT_MAX) && (neg_mode < PCNT_COUNT_MAX), PCNT_COUNT_MODE_ERR_STR, ESP_ERR_INVALID_ARG);
+    PCNT_CHECK((hctrl_mode < PCNT_MODE_MAX) && (lctrl_mode < PCNT_MODE_MAX), PCNT_CTRL_MODE_ERR_STR, ESP_ERR_INVALID_ARG);
+
+    if(channel == 0) {
+        PCNT.conf_unit[unit].conf0.ch0_pos_mode = pos_mode;
+        PCNT.conf_unit[unit].conf0.ch0_neg_mode = neg_mode;
+        PCNT.conf_unit[unit].conf0.ch0_hctrl_mode = hctrl_mode;
+        PCNT.conf_unit[unit].conf0.ch0_lctrl_mode = lctrl_mode;
+    } else {
+        PCNT.conf_unit[unit].conf0.ch1_pos_mode = pos_mode;
+        PCNT.conf_unit[unit].conf0.ch1_neg_mode = neg_mode;
+        PCNT.conf_unit[unit].conf0.ch1_hctrl_mode = hctrl_mode;
+        PCNT.conf_unit[unit].conf0.ch1_lctrl_mode = lctrl_mode;
+    }
+    return ESP_OK;
+}
+
+esp_err_t pcnt_set_pin(pcnt_unit_t unit, pcnt_channel_t channel, int pulse_io, int ctrl_io)
+{
+    PCNT_CHECK(unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
+    PCNT_CHECK(channel < PCNT_CHANNEL_MAX, PCNT_CHANNEL_ERR_STR, ESP_ERR_INVALID_ARG);
+    PCNT_CHECK(GPIO_IS_VALID_GPIO(pulse_io) || pulse_io < 0, PCNT_GPIO_ERR_STR, ESP_ERR_INVALID_ARG);
+    PCNT_CHECK(GPIO_IS_VALID_GPIO(ctrl_io) || ctrl_io < 0, PCNT_GPIO_ERR_STR, ESP_ERR_INVALID_ARG);
+    int input_sig_index = (channel == 0 ? PCNT_SIG_CH0_IN0_IDX + 4 * unit : PCNT_SIG_CH1_IN0_IDX + 4 * unit);
+    int ctrl_sig_index = (channel == 0 ? PCNT_CTRL_CH0_IN0_IDX + 4 * unit : PCNT_CTRL_CH1_IN0_IDX + 4 * unit);
+    if(pulse_io >= 0) {
+        PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[pulse_io], PIN_FUNC_GPIO);
+        gpio_set_direction(pulse_io, GPIO_MODE_INPUT);
+        gpio_set_pull_mode(pulse_io, GPIO_PULLUP_ONLY);
+        gpio_matrix_in(pulse_io, input_sig_index, 0);
+    }
+    if(ctrl_io >= 0) {
+        PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[ctrl_io], PIN_FUNC_GPIO);
+        gpio_set_direction(ctrl_io, GPIO_MODE_INPUT);
+        gpio_set_pull_mode(ctrl_io, GPIO_PULLUP_ONLY);
+        gpio_matrix_in(ctrl_io, ctrl_sig_index, 0);
+    }
+    return ESP_OK;
+}
+
+esp_err_t pcnt_get_counter_value(pcnt_unit_t pcnt_unit, int16_t* count)
+{
+    PCNT_CHECK(pcnt_unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
+    PCNT_CHECK(count != NULL, PCNT_ADDRESS_ERR_STR, ESP_ERR_INVALID_ARG);
+    *count = (int16_t) PCNT.cnt_unit[pcnt_unit].cnt_val;
+    return ESP_OK;
+}
+
+esp_err_t pcnt_counter_pause(pcnt_unit_t pcnt_unit)
+{
+    PCNT_CHECK(pcnt_unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
+    PCNT_ENTER_CRITICAL(&pcnt_spinlock);
+    PCNT.ctrl.val |= BIT(PCNT_CNT_PAUSE_U0_S + (pcnt_unit * 2));
+    PCNT_EXIT_CRITICAL(&pcnt_spinlock);
+    return ESP_OK;
+}
+
+esp_err_t pcnt_counter_resume(pcnt_unit_t pcnt_unit)
+{
+    PCNT_CHECK(pcnt_unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
+    PCNT_ENTER_CRITICAL(&pcnt_spinlock);
+    PCNT.ctrl.val &= (~(BIT(PCNT_CNT_PAUSE_U0_S + (pcnt_unit * 2))));
+    PCNT_EXIT_CRITICAL(&pcnt_spinlock);
+    return ESP_OK;
+}
+
+esp_err_t pcnt_counter_clear(pcnt_unit_t pcnt_unit)
+{
+    PCNT_CHECK(pcnt_unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
+    PCNT_ENTER_CRITICAL(&pcnt_spinlock);
+    PCNT.ctrl.val &= (~(BIT(PCNT_PLUS_CNT_RST_U0_S + (pcnt_unit * 2))));
+    PCNT_EXIT_CRITICAL(&pcnt_spinlock);
+    return ESP_OK;
+}
+
+esp_err_t pcnt_intr_enable(pcnt_unit_t pcnt_unit)
+{
+    PCNT_CHECK(pcnt_unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
+    PCNT_ENTER_CRITICAL(&pcnt_spinlock);
+    PCNT.int_ena.val |= BIT(PCNT_CNT_THR_EVENT_U0_INT_ENA_S + pcnt_unit);
+    PCNT_EXIT_CRITICAL(&pcnt_spinlock);
+    return ESP_OK;
+}
+
+esp_err_t pcnt_intr_disable(pcnt_unit_t pcnt_unit)
+{
+    PCNT_CHECK(pcnt_unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
+    PCNT_ENTER_CRITICAL(&pcnt_spinlock);
+    PCNT.int_ena.val &= (~(BIT(PCNT_CNT_THR_EVENT_U0_INT_ENA_S + pcnt_unit)));
+    PCNT_EXIT_CRITICAL(&pcnt_spinlock);
+    return ESP_OK;
+}
+
+esp_err_t pcnt_event_enable(pcnt_unit_t unit, pcnt_evt_type_t evt_type)
+{
+    PCNT_CHECK(unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
+    PCNT_CHECK(evt_type < PCNT_EVT_MAX, PCNT_EVT_TYPE_ERR_STR, ESP_ERR_INVALID_ARG);
+    if(evt_type == PCNT_EVT_L_LIM) {
+        PCNT.conf_unit[unit].conf0.thr_l_lim_en = 1;
+    } else if(evt_type == PCNT_EVT_H_LIM) {
+        PCNT.conf_unit[unit].conf0.thr_h_lim_en = 1;
+    } else if(evt_type == PCNT_EVT_THRES_0) {
+        PCNT.conf_unit[unit].conf0.thr_thres0_en = 1;
+    } else if(evt_type == PCNT_EVT_THRES_1) {
+        PCNT.conf_unit[unit].conf0.thr_thres1_en = 1;
+    } else if(evt_type == PCNT_EVT_ZERO) {
+        PCNT.conf_unit[unit].conf0.thr_zero_en = 1;
+    }
+    return ESP_OK;
+}
+
+esp_err_t pcnt_event_disable(pcnt_unit_t unit, pcnt_evt_type_t evt_type)
+{
+    PCNT_CHECK(unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
+    PCNT_CHECK(evt_type < PCNT_EVT_MAX, PCNT_EVT_TYPE_ERR_STR, ESP_ERR_INVALID_ARG);
+    if(evt_type == PCNT_EVT_L_LIM) {
+        PCNT.conf_unit[unit].conf0.thr_l_lim_en = 0;
+    } else if(evt_type == PCNT_EVT_H_LIM) {
+        PCNT.conf_unit[unit].conf0.thr_h_lim_en = 0;
+    } else if(evt_type == PCNT_EVT_THRES_0) {
+        PCNT.conf_unit[unit].conf0.thr_thres0_en = 0;
+    } else if(evt_type == PCNT_EVT_THRES_1) {
+        PCNT.conf_unit[unit].conf0.thr_thres1_en = 0;
+    } else if(evt_type == PCNT_EVT_ZERO) {
+        PCNT.conf_unit[unit].conf0.thr_zero_en = 0;
+    }
+    return ESP_OK;
+}
+
+esp_err_t pcnt_set_event_value(pcnt_unit_t unit, pcnt_evt_type_t evt_type, int16_t value)
+{
+    PCNT_CHECK(unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
+    PCNT_CHECK(evt_type < PCNT_EVT_MAX, PCNT_EVT_TYPE_ERR_STR, ESP_ERR_INVALID_ARG);
+    if(evt_type == PCNT_EVT_L_LIM) {
+        PCNT.conf_unit[unit].conf2.cnt_l_lim = value;
+    } else if(evt_type == PCNT_EVT_H_LIM) {
+        PCNT.conf_unit[unit].conf2.cnt_h_lim = value;
+    } else if(evt_type == PCNT_EVT_THRES_0) {
+        PCNT.conf_unit[unit].conf1.cnt_thres0 = value;
+    } else if(evt_type == PCNT_EVT_THRES_1) {
+        PCNT.conf_unit[unit].conf1.cnt_thres1 = value;
+    }
+    return ESP_OK;
+}
+
+esp_err_t pcnt_get_event_value(pcnt_unit_t unit, pcnt_evt_type_t evt_type, int16_t *value)
+{
+    PCNT_CHECK(unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
+    PCNT_CHECK(evt_type < PCNT_EVT_MAX, PCNT_EVT_TYPE_ERR_STR, ESP_ERR_INVALID_ARG);
+    PCNT_CHECK(value != NULL, PCNT_ADDRESS_ERR_STR, ESP_ERR_INVALID_ARG);
+
+    if(evt_type == PCNT_EVT_L_LIM) {
+        *value = (int16_t) PCNT.conf_unit[unit].conf2.cnt_l_lim;
+    } else if(evt_type == PCNT_EVT_H_LIM) {
+        *value = (int16_t) PCNT.conf_unit[unit].conf2.cnt_h_lim;
+    } else if(evt_type == PCNT_EVT_THRES_0) {
+        *value = (int16_t) PCNT.conf_unit[unit].conf1.cnt_thres0;
+    } else if(evt_type == PCNT_EVT_THRES_1) {
+        *value = (int16_t) PCNT.conf_unit[unit].conf1.cnt_thres1;
+    } else {
+        *value = 0;
+    }
+    return ESP_OK;
+}
+
+esp_err_t pcnt_set_filter_value(pcnt_unit_t unit, uint16_t filter_val)
+{
+    PCNT_CHECK(unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
+    PCNT_CHECK(filter_val < 1024, PCNT_PARAM_ERR_STR, ESP_ERR_INVALID_ARG);
+    PCNT.conf_unit[unit].conf0.filter_thres = filter_val;
+    return ESP_OK;
+}
+
+esp_err_t pcnt_get_filter_value(pcnt_unit_t unit, uint16_t *filter_val)
+{
+    PCNT_CHECK(unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
+    PCNT_CHECK(filter_val != NULL, PCNT_ADDRESS_ERR_STR, ESP_ERR_INVALID_ARG);
+
+    *filter_val = PCNT.conf_unit[unit].conf0.filter_thres;
+    return ESP_OK;
+}
+
+esp_err_t pcnt_filter_enable(pcnt_unit_t unit)
+{
+    PCNT_CHECK(unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
+    PCNT.conf_unit[unit].conf0.filter_en = 1;
+    return ESP_OK;
+}
+
+esp_err_t pcnt_filter_disable(pcnt_unit_t unit)
+{
+    PCNT_CHECK(unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
+    PCNT.conf_unit[unit].conf0.filter_en = 0;
+    return ESP_OK;
+}
+
+esp_err_t pcnt_isr_register(uint32_t pcnt_intr_num, void (*fun)(void*), void * arg)
+{
+    PCNT_CHECK(fun != NULL, PCNT_ADDRESS_ERR_STR, ESP_ERR_INVALID_ARG);
+    ESP_INTR_DISABLE(pcnt_intr_num);
+    intr_matrix_set(xPortGetCoreID(), ETS_PCNT_INTR_SOURCE, pcnt_intr_num);
+    xt_set_interrupt_handler(pcnt_intr_num, fun, arg);
+    ESP_INTR_ENABLE(pcnt_intr_num);
+    return ESP_OK;
+}
+

+ 12 - 0
components/driver/periph_ctrl.c

@@ -93,6 +93,10 @@ void periph_module_enable(periph_module_t periph)
             SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_UHCI1_CLK_EN);
             CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UHCI1_RST);
             break;
+        case PERIPH_PCNT_MODULE:
+            SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_PCNT_CLK_EN);
+            CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_PCNT_RST);
+            break;
         default:
             break;
     }
@@ -103,6 +107,10 @@ void periph_module_disable(periph_module_t periph)
 {
     portENTER_CRITICAL(&periph_spinlock);
     switch(periph) {
+        case PERIPH_RMT_MODULE:
+            CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_RMT_CLK_EN);
+            SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_RMT_RST);
+            break;
         case PERIPH_LEDC_MODULE:
             CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_LEDC_CLK_EN);
             SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_LEDC_RST);
@@ -167,6 +175,10 @@ void periph_module_disable(periph_module_t periph)
             CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_UHCI1_CLK_EN);
             SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UHCI1_RST);
             break;
+        case PERIPH_PCNT_MODULE:
+            CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_PCNT_CLK_EN);
+            SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_PCNT_RST);
+            break;
         default:
             break;
     }

+ 1 - 0
components/driver/rmt.c

@@ -13,6 +13,7 @@
 // limitations under the License.
 #include <esp_types.h>
 #include <string.h>
+#include <stdlib.h>
 #include "freertos/FreeRTOS.h"
 #include "freertos/semphr.h"
 #include "freertos/xtensa_api.h"

+ 2 - 1
components/driver/uart.c

@@ -84,7 +84,8 @@ typedef struct {
 
 
 static uart_obj_t *p_uart_obj[UART_NUM_MAX] = {0};
-static uart_dev_t* UART[UART_NUM_MAX] = {&UART0, &UART1, &UART2};
+/* DRAM_ATTR is required to avoid UART array placed in flash, due to accessed from ISR */
+static DRAM_ATTR uart_dev_t* const UART[UART_NUM_MAX] = {&UART0, &UART1, &UART2};
 static portMUX_TYPE uart_spinlock[UART_NUM_MAX] = {portMUX_INITIALIZER_UNLOCKED, portMUX_INITIALIZER_UNLOCKED, portMUX_INITIALIZER_UNLOCKED};
 
 esp_err_t uart_set_word_length(uart_port_t uart_num, uart_word_length_t data_bit)

+ 4 - 21
components/esp32/cpu_freq.c

@@ -16,25 +16,8 @@
 #include "rom/ets_sys.h"
 #include "rom/uart.h"
 #include "sdkconfig.h"
-
-typedef enum{
-    XTAL_40M = 40,
-    XTAL_26M = 26,
-    XTAL_24M = 24,
-    XTAL_AUTO = 0
-} xtal_freq_t;
-
-typedef enum{
-    CPU_80M = 1,
-    CPU_160M = 2,
-    CPU_240M = 3,
-} cpu_freq_t;
-
-extern void phy_get_romfunc_addr();
-
-// TODO: these functions need to be moved from librtc to ESP-IDF
-extern void rtc_init_lite();
-extern void rtc_set_cpu_freq(xtal_freq_t xtal_freq, cpu_freq_t cpu_freq);
+#include "phy.h"
+#include "rtc.h"
 
 /*
  * This function is not exposed as an API at this point,
@@ -52,7 +35,7 @@ void esp_set_cpu_freq(void)
     // wait uart tx finish, otherwise some uart output will be lost
     uart_tx_wait_idle(0);
 
-    rtc_init_lite();
+    rtc_init_lite(XTAL_AUTO);
     cpu_freq_t freq = CPU_80M;
     switch(freq_mhz) {
         case 240:
@@ -73,7 +56,7 @@ void esp_set_cpu_freq(void)
     // wait uart tx finish, otherwise some uart output will be lost
     uart_tx_wait_idle(0);
 
-    rtc_set_cpu_freq(XTAL_AUTO, freq);
+    rtc_set_cpu_freq(freq);
     ets_update_cpu_frequency(freq_mhz);
 }
 

+ 2 - 4
components/esp32/cpu_start.c

@@ -116,9 +116,7 @@ void IRAM_ATTR call_start_cpu0()
     //Flush and enable icache for APP CPU
     Cache_Flush(1);
     Cache_Read_Enable(1);
-    //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);
+    esp_cpu_unstall(1);
     //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);
@@ -154,6 +152,7 @@ void IRAM_ATTR call_start_cpu1()
 
 void start_cpu0_default(void)
 {
+    esp_setup_syscall_table();
 //Enable trace memory and immediately start trace.
 #if CONFIG_MEMMAP_TRACEMEM
 #if CONFIG_MEMMAP_TRACEMEM_TWOBANKS
@@ -174,7 +173,6 @@ void start_cpu0_default(void)
 #if CONFIG_TASK_WDT
     esp_task_wdt_init();
 #endif
-    esp_setup_syscall_table();
     esp_setup_time_syscalls();
     esp_vfs_dev_uart_register();
     esp_reent_init(_GLOBAL_REENT);

+ 44 - 0
components/esp32/cpu_util.c

@@ -0,0 +1,44 @@
+// Copyright 2013-2016 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "esp_attr.h"
+#include "soc/cpu.h"
+#include "soc/soc.h"
+#include "soc/rtc_cntl_reg.h"
+
+void IRAM_ATTR esp_cpu_stall(int cpu_id)
+{
+    if (cpu_id == 1) {
+        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 {
+        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);
+    }
+}
+
+void IRAM_ATTR esp_cpu_unstall(int cpu_id)
+{
+    if (cpu_id == 1) {
+        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);
+    } else {
+        CLEAR_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, RTC_CNTL_SW_STALL_PROCPU_C1_M);
+        CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_STALL_PROCPU_C0_M);
+    }
+}

+ 19 - 0
components/esp32/deepsleep.c

@@ -10,6 +10,7 @@
 #include "soc/dport_reg.h"
 #include "esp_attr.h"
 #include "esp_deepsleep.h"
+#include "rtc.h"
 
 /* Updating RTC_MEMORY_CRC_REG register via set_rtc_memory_crc()
    is not thread-safe. */
@@ -46,3 +47,21 @@ void RTC_IRAM_ATTR esp_default_wake_deep_sleep(void) {
 }
 
 void __attribute__((weak, alias("esp_default_wake_deep_sleep"))) esp_wake_deep_sleep(void);
+
+void esp_deep_sleep(uint64_t time_in_us)
+{
+    rtc_set_cpu_freq(CPU_XTAL);
+    if (esp_get_deep_sleep_wake_stub() == NULL) {
+        esp_set_deep_sleep_wake_stub(esp_wake_deep_sleep);
+    }
+    uint32_t period = rtc_slowck_cali(CALI_RTC_MUX, 128);
+    uint32_t cycle_l, cycle_h;
+    rtc_usec2rtc(time_in_us >> 32, time_in_us, period, &cycle_h, &cycle_l);
+    rtc_slp_prep_lite(1, 0);
+    rtc_sleep(cycle_h, cycle_l, TIMER_EXPIRE_EN, 0);
+    while (1) {
+        ;
+    }
+}
+
+void system_deep_sleep(uint64_t) __attribute__((alias("esp_deep_sleep")));

+ 41 - 0
components/esp32/hw_random.c

@@ -0,0 +1,41 @@
+// Copyright 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 <stddef.h>
+#include <string.h>
+#include "esp_attr.h"
+#include "soc/wdev_reg.h"
+#include "freertos/FreeRTOSConfig.h"
+#include "xtensa/core-macros.h"
+
+uint32_t IRAM_ATTR esp_random(void)
+{
+    /* The PRNG which implements WDEV_RANDOM register gets 2 bits
+     * of extra entropy from a hardware randomness source every APB clock cycle.
+     * To make sure entropy is not drained faster than it is added,
+     * this function needs to wait for at least 16 APB clock cycles after reading
+     * previous word. This implementation may actually wait a bit longer
+     * due to extra time spent in arithmetic and branch statements.
+     */
+
+    static uint32_t last_ccount = 0;
+    uint32_t ccount;
+    do {
+        ccount = XTHAL_GET_CCOUNT();
+    } while (ccount - last_ccount < XT_CLOCK_FREQ / APB_CLK_FREQ * 16);
+    last_ccount = ccount;
+    return REG_READ(WDEV_RND_REG);
+}

+ 23 - 14
components/esp32/include/esp_deepsleep.h

@@ -30,25 +30,34 @@ extern "C" {
   */
 
 /**
-  * @brief     Set the chip to deep-sleep mode.
-  *
-  *            The device will automatically wake up after the deep-sleep time set
-  *            by the users. Upon waking up, the device boots up from user_init.
-  *
-  * @attention  The parameter time_in_us to be "uint64" is for further development.
-  *                  Only the low 32 bits of parameter time_in_us are avalable now.
-  *
-  * @param     uint64 time_in_us : deep-sleep time, only the low 32bits are avalable now. unit: microsecond
-  *
-  * @return    null
-  */
-void system_deep_sleep(uint64_t time_in_us);
+ * @brief Enter deep-sleep mode
+ *
+ * The device will automatically wake up after the deep-sleep time
+ * Upon waking up, the device calls deep sleep wake stub, and then proceeds
+ * to load application.
+ *
+ * This function does not return.
+ *
+ * @param time_in_us  deep-sleep time, unit: microsecond
+ */
+void esp_deep_sleep(uint64_t time_in_us) __attribute__((noreturn));
+
+
+/**
+ * @brief Enter deep-sleep mode
+ *
+ * Function has been renamed to esp_deep_sleep.
+ * This name is deprecated and will be removed in a future version.
+ *
+ * @param time_in_us  deep-sleep time, unit: microsecond
+ */
+void system_deep_sleep(uint64_t time_in_us) __attribute__((noreturn, deprecated));
 
 /**
  * @brief Default stub to run on wake from deep sleep.
  *
  * Allows for executing code immediately on wake from sleep, before
- * the software bootloader or esp-idf app has started up.
+ * the software bootloader or ESP-IDF app has started up.
  *
  * This function is weak-linked, so you can implement your own version
  * to run code immediately when the chip wakes from

+ 49 - 108
components/esp32/include/esp_system.h

@@ -16,7 +16,7 @@
 #define __ESP_SYSTEM_H__
 
 #include <stdint.h>
-
+#include <stdbool.h>
 #include "esp_err.h"
 #include "esp_deepsleep.h"
 
@@ -24,166 +24,107 @@
 extern "C" {
 #endif
 
-/** \defgroup System_APIs System APIs
-  * @brief System APIs
-  */
-
-/** @addtogroup System_APIs
-  * @{
-  */
-
 /**
   * @attention  application don't need to call this function anymore. It do nothing and will
   *             be removed in future version.
   */
 void system_init(void) __attribute__ ((deprecated));
 
-
 /**
-  * @brief  Get information of the SDK version.
-  *
-  * @param  null
+  * @brief  Reset to default settings.
   *
-  * @return Information of the SDK version.
+  * Function has been deprecated, please use esp_wifi_restore instead.
+  * This name will be removed in a future release.
   */
-const char *system_get_sdk_version(void);
+void system_restore(void) __attribute__ ((deprecated));
 
 /**
-  * @brief  Reset to default settings.
-  *
-  *         Reset to default settings of the following APIs : wifi_station_set_auto_connect,
-  *         wifi_set_phy_mode, wifi_softap_set_config related, wifi_station_set_config
-  *         related, and wifi_set_opmode.
-  *
-  * @param  null
+  * @brief  Restart PRO and APP CPUs.
   *
-  * @return null
+  * This function can be called both from PRO and APP CPUs.
+  * After successful restart, CPU reset reason will be SW_CPU_RESET.
+  * Peripherals (except for WiFi, BT, UART0, SPI1, and legacy timers) are not reset.
+  * This function does not return.
   */
-void system_restore(void);
+void esp_restart(void) __attribute__ ((noreturn));
 
 /**
   * @brief  Restart system.
   *
-  * @param  null
-  *
-  * @return null
+  * Function has been renamed to esp_restart.
+  * This name will be removed in a future release.
   */
-void system_restart(void);
+void system_restart(void) __attribute__ ((deprecated, noreturn));
 
 /**
   * @brief  Get system time, unit: microsecond.
   *
-  * @param  null
-  *
-  * @return System time, unit: microsecond.
+  * This function is deprecated. Use 'gettimeofday' function for 64-bit precision.
+  * This definition will be removed in a future release.
   */
-uint32_t system_get_time(void);
+uint32_t system_get_time(void)  __attribute__ ((deprecated));
 
 /**
   * @brief  Get the size of available heap.
   *
-  * @param  null
-  *
-  * @return Available heap size.
-  */
-uint32_t system_get_free_heap_size(void);
-
-/**
-  * @brief     Get RTC time, unit: RTC clock cycle.
-  *
-  * @param     null
+  * Note that the returned value may be larger than the maximum contiguous block
+  * which can be allocated.
   *
-  * @return    RTC time.
+  * @return Available heap size, in bytes.
   */
-uint64_t system_get_rtc_time(void);
+uint32_t esp_get_free_heap_size(void);
 
 /**
-  * @brief     Read user data from the RTC memory.
-  *
-  *            The user data segment (1024 bytes, as shown below) is used to store user data.
-  *
-  *             |<---- system data(512 bytes) ---->|<----------- user data(1024 bytes) --------->|
-  *
-  * @attention Read and write unit for data stored in the RTC memory is 4 bytes.
-  * @attention src_addr is the block number (4 bytes per block). So when reading data
-  *            at the beginning of the user data segment, src_addr will be 512/4 = 128,
-  *            n will be data length.
+  * @brief  Get the size of available heap.
   *
-  * @param     uint16 src : source address of rtc memory, src_addr >= 128
-  * @param     void *dst : data pointer
-  * @param     uint16 n : data length, unit: byte
+  * Function has been renamed to esp_get_free_heap_size.
+  * This name will be removed in a future release.
   *
-  * @return    true  : succeed
-  * @return    false : fail
+  * @return Available heap size, in bytes.
   */
-bool system_rtc_mem_read(uint16_t src, void *dst, uint16_t n);
+uint32_t system_get_free_heap_size(void)  __attribute__ ((deprecated));
 
 /**
-  * @brief     Write user data to  the RTC memory.
-  *
-  *            During deep-sleep, only RTC is working. So users can store their data
-  *            in RTC memory if it is needed. The user data segment below (1024 bytes)
-  *            is used to store the user data.
-  *
-  *            |<---- system data(512 bytes) ---->|<----------- user data(1024 bytes) --------->|
-  *
-  * @attention Read and write unit for data stored in the RTC memory is 4 bytes.
-  * @attention src_addr is the block number (4 bytes per block). So when storing data
-  *            at the beginning of the user data segment, src_addr will be 512/4 = 128,
-  *            n will be data length.
-  *
-  * @param     uint16 src : source address of rtc memory, src_addr >= 128
-  * @param     void *dst : data pointer
-  * @param     uint16 n : data length, unit: byte
-  *
-  * @return    true  : succeed
-  * @return    false : fail
-  */
-bool system_rtc_mem_write(uint16_t dst, const void *src, uint16_t n);
-
-/** \defgroup System_boot_APIs Boot APIs
-  * @brief boot APIs
-  */
-
-/** @addtogroup System_boot_APIs
-  * @{
-  */
+ * @brief  Get one random 32-bit word from hardware RNG
+ *
+ * @return random value between 0 and UINT32_MAX
+ */
+uint32_t esp_random(void);
 
 /**
-  * @}
-  */
-  
-/** \defgroup Hardware_MAC_APIs Hardware MAC APIs
-  * @brief Hardware MAC address APIs
+  * @brief  Read hardware MAC address.
   *
   * In WiFi MAC, only ESP32 station MAC is the hardware MAC, ESP32 softAP MAC is a software MAC 
   * calculated from ESP32 station MAC. 
-  * So users need to call wifi_get_macaddr to query the ESP32 softAP MAC if ESP32 station MAC changed.
+  * So users need to call esp_wifi_get_macaddr to query the ESP32 softAP MAC if ESP32 station MAC changed.
   *
+  * @param  mac  hardware MAC address, length: 6 bytes.
+  *
+  * @return ESP_OK on success
   */
-
-/** @addtogroup Hardware_MAC_APIs
-  * @{
-  */
+esp_err_t esp_efuse_read_mac(uint8_t* mac);
 
 /**
   * @brief  Read hardware MAC address.
   *
-  * @param  uint8 mac[6] : the hardware MAC address, length: 6 bytes.
+  * Function has been renamed to esp_efuse_read_mac.
+  * This name will be removed in a future release.
   *
-  * @return esp_err_t
+  * @param  mac  hardware MAC address, length: 6 bytes.
+  * @return ESP_OK on success
   */
-esp_err_t system_efuse_read_mac(uint8_t mac[6]);
-
+esp_err_t system_efuse_read_mac(uint8_t mac[6]) __attribute__ ((deprecated));
 
 /**
-  * @}
-  */
+ * Get SDK version
+ *
+ * This function is deprecated and will be removed in a future release.
+ *
+ * @return constant string "master"
+ */
+const char* system_get_sdk_version(void)  __attribute__ ((deprecated));
 
 
-/**
-  * @}
-  */
 
 #ifdef __cplusplus
 }

+ 0 - 48
components/esp32/include/esp_types.h

@@ -22,52 +22,4 @@
 #include <stdbool.h>
 #include <stddef.h>
 
-#define __ATTRIB_PACK           __attribute__ ((packed))
-#define __ATTRIB_PRINTF         __attribute__ ((format (printf, 1, 2)))
-#define __ATTRIB_NORETURN       __attribute__ ((noreturn))
-#define __ATTRIB_ALIGN(x)       __attribute__ ((aligned((x))))
-#define INLINE                  __inline__
-
-#define LOCAL       static
-
-/* probably should not put STATUS here */
-typedef enum {
-    OK = 0,
-    FAIL,
-    PENDING,
-    BUSY,
-    CANCEL,
-} STATUS;
-
-//#define _LITTLE_ENDIAN  1234
-//#define _BYTE_ORDER == _LITTLE_ENDIAN
-
-#define ASSERT( x ) do { \
-    if (!(x)) {          \
-        printf("%s %u\n", __FILE__, __LINE__); \
-        while (1) { \
-            asm volatile("nop"); \
-        };              \
-    }                   \
-} while (0)
-
-/* #if __GNUC_PREREQ__(4, 1) */
-#ifndef __GNUC__
-#if 1
-#define __offsetof(type, field)  __builtin_offsetof(type, field)
-#else
-#define __offsetof(type, field) ((size_t)(&((type *)0)->field))
-#endif
-#endif /* __GNUC__ */
-
-
-/* Macros for counting and rounding. */
-#ifndef howmany
-#define howmany(x, y)   (((x)+((y)-1))/(y))
-#endif
-
-#define container_of(ptr, type, member) ({                      \
-        const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
-        (type *)( (char *)__mptr - __offsetof(type,member) );})
-
 #endif /* __ESP_TYPES_H__ */

+ 15 - 0
components/esp32/include/esp_wifi.h

@@ -186,6 +186,21 @@ esp_err_t esp_wifi_start(void);
   */
 esp_err_t esp_wifi_stop(void);
 
+/**
+ * @brief  Restore WiFi stack persistent settings to default values
+ *
+ * This function will reset settings made using the following APIs:
+ * - esp_wifi_get_auto_connect,
+ * - esp_wifi_set_protocol,
+ * - esp_wifi_set_config related
+ * - esp_wifi_set_mode
+ *
+ * @return
+ *    - ESP_OK: succeed
+ *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
+ */
+esp_err_t esp_wifi_restore(void);
+
 /**
   * @brief     Connect the ESP32 WiFi station to the AP.
   *

+ 9 - 13
components/esp32/include/esp_wifi_internal.h

@@ -43,10 +43,9 @@ extern "C" {
 /**
   * @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
+  * @return
+  *     - true  : upper layer should stop to transmit data to wifi driver
+  *     - false : upper layer can transmit data to wifi driver
   */
 bool esp_wifi_internal_tx_is_stop(void);
 
@@ -54,8 +53,6 @@ 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);
 
@@ -78,7 +75,6 @@ int esp_wifi_internal_tx(wifi_interface_t wifi_if, void *buffer, u16_t len);
   * @brief     The WiFi RX callback function
   *
   *            Each time the WiFi need to forward the packets to high layer, the callback function will be called
-  *
   */
 typedef esp_err_t (*wifi_rxcb_t)(void *buffer, uint16_t len, void *eb);
 
@@ -90,18 +86,18 @@ typedef esp_err_t (*wifi_rxcb_t)(void *buffer, uint16_t len, void *eb);
   * @param     wifi_interface_t ifx : interface
   * @param     wifi_rxcb_t fn : WiFi RX callback
   *
-  * @return    ESP_OK : succeed
-  * @return    others : fail
+  * @return
+  *     - ESP_OK : succeed
+  *     - others : fail
   */
 esp_err_t esp_wifi_internal_reg_rxcb(wifi_interface_t ifx, wifi_rxcb_t fn);
 
 /**
   * @brief     Notify WIFI driver that the station got ip successfully
   *
-  * @param     none
-  *
-  * @return    ESP_OK : succeed
-  * @return    others : fail
+  * @return
+  *     - ESP_OK : succeed
+  *     - others : fail
   */
 esp_err_t esp_wifi_internal_set_sta_ip(void);
 

+ 8 - 0
components/esp32/include/rom/ets_sys.h

@@ -605,6 +605,14 @@ void intr_matrix_set(int cpu_no, uint32_t model_num, uint32_t intr_num);
 
 #define ETS_MEM_BAR() asm volatile ( "" : : : "memory" )
 
+typedef enum {
+    OK = 0,
+    FAIL,
+    PENDING,
+    BUSY,
+    CANCEL,
+} STATUS;
+
 /**
   * @}
   */

+ 1 - 0
components/esp32/include/rom/uart.h

@@ -17,6 +17,7 @@
 
 #include "esp_types.h"
 #include "esp_attr.h"
+#include "ets_sys.h"
 
 #ifdef __cplusplus
 extern "C" {

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

@@ -51,7 +51,10 @@ static inline void cpu_write_itlb(unsigned vpn, unsigned attr)
     asm volatile ("witlb  %1, %0; isync\n" :: "r" (vpn), "r" (attr));
 }
 
-/* Make page 0 access raise an exception.
+/**
+ * @brief Configure memory region protection
+ *
+ * Make page 0 access raise an exception.
  * Also protect some other unused pages so we can catch weirdness.
  * Useful attribute values:
  * 0 — cached, RW
@@ -70,9 +73,7 @@ static inline void cpu_configure_region_protection()
     cpu_write_itlb(0x20000000, 0);
 }
 
-
-
-/*
+/**
  * @brief Set CPU frequency to the value defined in menuconfig
  *
  * Called from cpu_start.c, not intended to be called from other places.
@@ -81,4 +82,16 @@ static inline void cpu_configure_region_protection()
  */
 void esp_set_cpu_freq(void);
 
+/**
+ * @brief Stall CPU using RTC controller
+ * @param cpu_id ID of the CPU to stall (0 = PRO, 1 = APP)
+ */
+void esp_cpu_stall(int cpu_id);
+
+/**
+ * @brief Un-stall CPU using RTC controller
+ * @param cpu_id ID of the CPU to un-stall (0 = PRO, 1 = APP)
+ */
+void esp_cpu_unstall(int cpu_id);
+
 #endif

+ 30 - 0
components/esp32/include/soc/pcnt_reg.h

@@ -1319,6 +1319,36 @@
 #define PCNT_CORE_STATUS_U0_M  ((PCNT_CORE_STATUS_U0_V)<<(PCNT_CORE_STATUS_U0_S))
 #define PCNT_CORE_STATUS_U0_V  0xFFFFFFFF
 #define PCNT_CORE_STATUS_U0_S  0
+/*0: positive value to zero; 1: negative value to zero; 2: counter value negative ; 3: counter value positive*/
+#define PCNT_STATUS_CNT_MODE    0x3
+#define PCNT_STATUS_CNT_MODE_M  ((PCNT_STATUS_CNT_MODE_V)<<(PCNT_STATUS_CNT_MODE_S))
+#define PCNT_STATUS_CNT_MODE_V  0x3
+#define PCNT_STATUS_CNT_MODE_S  0
+/* counter value equals to thresh1*/
+#define PCNT_STATUS_THRES1    BIT(2)
+#define PCNT_STATUS_THRES1_M  BIT(2)
+#define PCNT_STATUS_THRES1_V  0x1
+#define PCNT_STATUS_THRES1_S  2
+/* counter value equals to thresh0*/
+#define PCNT_STATUS_THRES0    BIT(3)
+#define PCNT_STATUS_THRES0_M  BIT(3)
+#define PCNT_STATUS_THRES0_V  0x1
+#define PCNT_STATUS_THRES0_S  3
+/* counter value reaches h_lim*/
+#define PCNT_STATUS_L_LIM    BIT(4)
+#define PCNT_STATUS_L_LIM_M  BIT(4)
+#define PCNT_STATUS_L_LIM_V  0x1
+#define PCNT_STATUS_L_LIM_S  4
+/* counter value reaches l_lim*/
+#define PCNT_STATUS_H_LIM    BIT(5)
+#define PCNT_STATUS_H_LIM_M  BIT(5)
+#define PCNT_STATUS_H_LIM_V  0x1
+#define PCNT_STATUS_H_LIM_S  5
+/* counter value equals to zero*/
+#define PCNT_STATUS_ZERO    BIT(6)
+#define PCNT_STATUS_ZERO_M  BIT(6)
+#define PCNT_STATUS_ZERO_V  0x1
+#define PCNT_STATUS_ZERO_S  6
 
 #define PCNT_U1_STATUS_REG          (DR_REG_PCNT_BASE + 0x0094)
 /* PCNT_CORE_STATUS_U1 : RO ;bitpos:[31:0] ;default: 32'h0 ; */

+ 12 - 1
components/esp32/include/soc/pcnt_struct.h

@@ -113,7 +113,18 @@ typedef volatile struct {
         };
         uint32_t val;
     } int_clr;
-    uint32_t status_unit[8];
+    union {
+        struct {
+            uint32_t cnt_mode:2;                    /*0: positive value to zero; 1: negative value to zero; 2: counter value negative ; 3: counter value positive*/
+            uint32_t thres1_lat:1;                  /* counter value equals to thresh1*/
+            uint32_t thres0_lat:1;                  /* counter value equals to thresh0*/
+            uint32_t l_lim_lat:1;                   /* counter value reaches h_lim*/
+            uint32_t h_lim_lat:1;                   /* counter value reaches l_lim*/
+            uint32_t zero_lat:1;                    /* counter value equals zero*/
+            uint32_t reserved7:25;
+        };
+        uint32_t val;
+    } status_unit[8];
     union {
         struct {
             uint32_t cnt_rst_u0:   1;               /*Set this bit to clear unit0's counter.*/

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

@@ -129,10 +129,10 @@
 //}}
 
 //Periheral Clock {{
-#define  APB_CLK_FREQ_ROM                            26*1000000
+#define  APB_CLK_FREQ_ROM                            ( 26*1000000 )
 #define  CPU_CLK_FREQ_ROM                            APB_CLK_FREQ_ROM
 #define  CPU_CLK_FREQ                                APB_CLK_FREQ
-#define  APB_CLK_FREQ                                80*1000000       //unit: Hz
+#define  APB_CLK_FREQ                                ( 80*1000000 )       //unit: Hz
 #define  UART_CLK_FREQ                               APB_CLK_FREQ
 #define  WDT_CLK_FREQ                                APB_CLK_FREQ
 #define  TIMER_CLK_FREQ                              (80000000>>4) //80MHz divided by 16

+ 18 - 0
components/esp32/include/soc/wdev_reg.h

@@ -0,0 +1,18 @@
+// Copyright 2010-2016 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once
+
+/* Hardware random number generator register */ 
+#define WDEV_RND_REG 0x60035144

+ 1 - 1
components/esp32/include/xtensa/core-macros.h

@@ -42,7 +42,7 @@
  * share the name with the existing functions from hal.h.
  * Including this header file will define XTHAL_USE_CACHE_MACROS 
  * which directs hal.h not to use the functions.
- *
+ */
 
 /*
  *  Single-cache-line operations in C-callable inline assembly.

+ 1 - 1
components/esp32/lib

@@ -1 +1 @@
-Subproject commit e2e5781dc27e638c5e63f85bc23590dd21af1619
+Subproject commit aa74ce27618c931fef8bdbdb683f80f4b364ba53

+ 124 - 0
components/esp32/lib_printf.c

@@ -0,0 +1,124 @@
+// Copyright 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.
+
+/**
+ * @file lib_printf.c
+ *
+ * This file contains library-specific printf functions
+ * used by WiFi libraries in the `lib` directory.
+ * These function are used to catch any output which gets printed
+ * by libraries, and redirect it to ESP_LOG macros.
+ *
+ * Eventually WiFi libraries will use ESP_LOG functions internally
+ * and these definitions will be removed.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "esp_log.h"
+#include "esp_attr.h"
+
+#define VPRINTF_STACK_BUFFER_SIZE 80
+
+static int lib_printf(const char* tag, const char* format, va_list arg)
+{
+    char temp[VPRINTF_STACK_BUFFER_SIZE];
+    int len = vsnprintf(temp, sizeof(temp) - 1, format, arg);
+    temp[sizeof(temp) - 1] = 0;
+    int i;
+    for (i = len - 1; i >= 0; --i) {
+        if (temp[i] != '\n' && temp[i] != '\r' && temp[i] != ' ') {
+            break;
+        }
+        temp[i] = 0;
+    }
+    if (i > 0) {
+        ESP_EARLY_LOGI(tag, "%s", temp);
+    }
+    va_end(arg);
+    return len;
+}
+
+int phy_printf(const char* format, ...)
+{
+    va_list arg;
+    va_start(arg, format);
+    int res = lib_printf("phy", format, arg);
+    va_end(arg);
+    return res;
+}
+
+
+int rtc_printf(const char* format, ...)
+{
+    va_list arg;
+    va_start(arg, format);
+    int res = lib_printf("rtc", format, arg);
+    va_end(arg);
+    return res;
+}
+
+int wpa_printf(const char* format, ...)
+{
+    va_list arg;
+    va_start(arg, format);
+    int res = lib_printf("wpa", format, arg);
+    va_end(arg);
+    return res;
+}
+
+int wps_printf(const char* format, ...)
+{
+    va_list arg;
+    va_start(arg, format);
+    int res = lib_printf("wps", format, arg);
+    va_end(arg);
+    return res;
+}
+
+int pp_printf(const char* format, ...)
+{
+    va_list arg;
+    va_start(arg, format);
+    int res = lib_printf("pp", format, arg);
+    va_end(arg);
+    return res;
+}
+
+int sc_printf(const char* format, ...)
+{
+    va_list arg;
+    va_start(arg, format);
+    int res = lib_printf("smartconfig", format, arg);
+    va_end(arg);
+    return res;
+}
+
+int core_printf(const char* format, ...)
+{
+    va_list arg;
+    va_start(arg, format);
+    int res = lib_printf("core", format, arg);
+    va_end(arg);
+    return res;
+}
+
+int net80211_printf(const char* format, ...)
+{
+    va_list arg;
+    va_start(arg, format);
+    int res = lib_printf("net80211", format, arg);
+    va_end(arg);
+    return res;
+}

+ 5 - 15
components/esp32/panic.c

@@ -27,6 +27,7 @@
 #include "soc/rtc_cntl_reg.h"
 #include "soc/timer_group_struct.h"
 #include "soc/timer_group_reg.h"
+#include "soc/cpu.h"
 
 #include "esp_gdbstub.h"
 #include "esp_panic.h"
@@ -108,21 +109,10 @@ static const char *edesc[]={
 void commonErrorHandler(XtExcFrame *frame);
 
 //The fact that we've panic'ed probably means the other CPU is now running wild, possibly
-//messing up the serial output, so we kill it here.
-static void haltOtherCore() {
-	if (xPortGetCoreID()==0) {
-		//Kill app cpu
-		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_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);
-	}
+//messing up the serial output, so we stall it here.
+static void haltOtherCore()
+{
+    esp_cpu_stall( xPortGetCoreID() == 0 ? 1 : 0 );
 }
 
 //Returns true when a debugger is attached using JTAG.

+ 2 - 2
components/esp32/phy_init.c

@@ -179,7 +179,7 @@ static esp_err_t load_cal_data_from_nvs_handle(nvs_handle handle,
         return ESP_ERR_INVALID_SIZE;
     }
     uint8_t sta_mac[6];
-    system_efuse_read_mac(sta_mac);
+    esp_efuse_read_mac(sta_mac);
     if (memcmp(sta_mac, cal_data_mac, sizeof(sta_mac)) != 0) {
         ESP_LOGE(TAG, "%s: calibration data MAC check failed: expected " \
                 MACSTR ", found " MACSTR,
@@ -210,7 +210,7 @@ static esp_err_t store_cal_data_to_nvs_handle(nvs_handle handle,
         return err;
     }
     uint8_t sta_mac[6];
-    system_efuse_read_mac(sta_mac);
+    esp_efuse_read_mac(sta_mac);
     err = nvs_set_blob(handle, PHY_CAL_MAC_KEY, sta_mac, sizeof(sta_mac));
     if (err != ESP_OK) {
         return err;

+ 142 - 0
components/esp32/rtc.h

@@ -0,0 +1,142 @@
+// 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.
+
+/**
+ * @file rtc.h
+ * @brief Declarations of APIs provided by librtc.a
+ *
+ * This file is not in the include directory of esp32 component, so it is not
+ * part of the public API. As the source code of librtc.a is gradually moved
+ * into the ESP-IDF, some of these APIs will be exposed to applications.
+ *
+ * For now, only esp_deep_sleep function declared in esp_deepsleep.h
+ * is part of public API.
+ */
+
+#pragma once
+#include <stdint.h>
+#include <stddef.h>
+#include "soc/soc.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef enum{
+    XTAL_40M = 40,
+    XTAL_26M = 26,
+    XTAL_24M = 24,
+    XTAL_AUTO = 0
+} xtal_freq_t;
+
+typedef enum{
+    CPU_XTAL = 0,
+    CPU_80M = 1,
+    CPU_160M = 2,
+    CPU_240M = 3,
+    CPU_2M = 4
+} cpu_freq_t;
+
+typedef enum {
+    CALI_RTC_MUX = 0,
+    CALI_8MD256 = 1,
+    CALI_32K_XTAL = 2
+} cali_clk_t;
+
+/**
+ * This function must be called to initialize RTC library
+ * @param xtal_freq  Frequency of main crystal
+ */
+void rtc_init_lite(xtal_freq_t xtal_freq);
+
+/**
+ * Switch CPU frequency
+ * @param cpu_freq  new CPU frequency
+ */
+void rtc_set_cpu_freq(cpu_freq_t cpu_freq);
+
+/**
+ * @brief Return RTC slow clock's period
+ * @param cali_clk  clock to calibrate
+ * @param slow_clk_cycles  number of slow clock cycles to average
+ * @param xtal_freq  chip's main XTAL freq
+ * @return average slow clock period in microseconds, Q13.19 fixed point format
+ */
+uint32_t rtc_slowck_cali(cali_clk_t cali_clk, uint32_t slow_clk_cycles);
+
+/**
+ * @brief Convert from microseconds to slow clock cycles
+ * @param time_in_us_h Time in microseconds, higher 32 bit part
+ * @param time_in_us_l Time in microseconds, lower 32 bit part
+ * @param slow_clk_period  Period of slow clock in microseconds, Q13.19 fixed point format (as returned by rtc_slowck_cali).
+ * @param[out] cylces_h  output, higher 32 bit part of number of slow clock cycles
+ * @param[out] cycles_l  output, lower 32 bit part of number of slow clock cycles
+ */
+void rtc_usec2rtc(uint32_t time_in_us_h, uint32_t time_in_us_l, uint32_t slow_clk_period, uint32_t *cylces_h, uint32_t *cycles_l);
+
+
+#define DEEP_SLEEP_PD_NORMAL         BIT(0)   /*!< Base deep sleep mode */
+#define DEEP_SLEEP_PD_RTC_PERIPH     BIT(1)   /*!< Power down RTC peripherals */
+#define DEEP_SLEEP_PD_RTC_SLOW_MEM   BIT(2)   /*!< Power down RTC SLOW memory */
+#define DEEP_SLEEP_PD_RTC_FAST_MEM   BIT(3)   /*!< Power down RTC FAST memory */
+
+/**
+ * @brief Prepare for entering sleep mode
+ * @param deep_slp   DEEP_SLEEP_PD_ flags combined with OR (DEEP_SLEEP_PD_NORMAL must be included)
+ * @param cpu_lp_mode  for deep sleep, should be 0
+ */
+void rtc_slp_prep_lite(uint32_t deep_slp, uint32_t cpu_lp_mode);
+
+
+#define RTC_EXT_EVENT0_TRIG     BIT(0)
+#define RTC_EXT_EVENT1_TRIG     BIT(1)
+#define RTC_GPIO_TRIG           BIT(2)
+#define RTC_TIMER_EXPIRE        BIT(3)
+#define RTC_SDIO_TRIG           BIT(4)
+#define RTC_MAC_TRIG            BIT(5)
+#define RTC_UART0_TRIG          BIT(6)
+#define RTC_UART1_TRIG          BIT(7)
+#define RTC_TOUCH_TRIG          BIT(8)
+#define RTC_SAR_TRIG            BIT(9)
+#define RTC_BT_TRIG             BIT(10)
+
+
+#define RTC_EXT_EVENT0_TRIG_EN  RTC_EXT_EVENT0_TRIG
+#define RTC_EXT_EVENT1_TRIG_EN  RTC_EXT_EVENT1_TRIG
+#define RTC_GPIO_TRIG_EN        RTC_GPIO_TRIG
+#define RTC_TIMER_EXPIRE_EN     RTC_TIMER_EXPIRE
+#define RTC_SDIO_TRIG_EN        RTC_SDIO_TRIG
+#define RTC_MAC_TRIG_EN         RTC_MAC_TRIG
+#define RTC_UART0_TRIG_EN       RTC_UART0_TRIG
+#define RTC_UART1_TRIG_EN       RTC_UART1_TRIG
+#define RTC_TOUCH_TRIG_EN       RTC_TOUCH_TRIG
+#define RTC_SAR_TRIG_EN         RTC_SAR_TRIG
+#define RTC_BT_TRIG_EN          RTC_BT_TRIG
+
+/**
+ * @brief Enter sleep mode for given number of cycles
+ * @param cycles_h  higher 32 bit part of number of slow clock cycles
+ * @param cycles_l  lower 32 bit part of number of slow clock cycles
+ * @param wakeup_opt  wake up reason to enable (RTC_xxx_EN flags combined with OR)
+ * @param reject_opt  reserved, should be 0
+ * @return TBD
+ */
+uint32_t rtc_sleep(uint32_t cycles_h, uint32_t cycles_l, uint32_t wakeup_opt, uint32_t reject_opt);
+
+
+#ifdef __cplusplus
+}
+#endif
+

+ 158 - 0
components/esp32/system_api.c

@@ -0,0 +1,158 @@
+// Copyright 2013-2016 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "esp_system.h"
+#include "esp_attr.h"
+#include "esp_wifi.h"
+#include "esp_wifi_internal.h"
+#include "esp_log.h"
+#include "rom/efuse.h"
+#include "rom/cache.h"
+#include "rom/uart.h"
+#include "soc/dport_reg.h"
+#include "soc/efuse_reg.h"
+#include "soc/rtc_cntl_reg.h"
+#include "soc/timer_group_reg.h"
+#include "soc/timer_group_struct.h"
+#include "soc/cpu.h"
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "freertos/xtensa_api.h"
+
+static const char* TAG = "system_api";
+
+void system_init()
+{
+}
+
+esp_err_t esp_efuse_read_mac(uint8_t* mac)
+{
+    uint8_t efuse_crc;
+    uint8_t calc_crc;
+    uint32_t mac_low = REG_READ(EFUSE_BLK0_RDATA1_REG);
+    uint32_t mac_high = REG_READ(EFUSE_BLK0_RDATA2_REG);
+
+    mac[0] = mac_high >> 8;
+    mac[1] = mac_high;
+    mac[2] = mac_low >> 24;
+    mac[3] = mac_low >> 16;
+    mac[4] = mac_low >> 8;
+    mac[5] = mac_low;
+
+    efuse_crc = mac_high >> 16;
+    calc_crc = esp_crc8(mac, 6);
+
+    if (efuse_crc != calc_crc) {
+         // Small range of MAC addresses are accepted even if CRC is invalid.
+         // These addresses are reserved for Espressif internal use.
+        if ((mac_high & 0xFFFF) == 0x18fe) {
+            if ((mac_low >= 0x346a85c7) && (mac_low <= 0x346a85f8)) {
+                return ESP_OK;
+            }
+        } else {
+            ESP_LOGE(TAG, "MAC address CRC error, efuse_crc = 0x%02x; calc_crc = 0x%02x", efuse_crc, calc_crc);
+            abort();
+        }
+    }
+    return ESP_OK;
+}
+
+esp_err_t system_efuse_read_mac(uint8_t mac[6]) __attribute__((alias("esp_efuse_read_mac")));
+
+
+void IRAM_ATTR esp_restart(void)
+{
+    esp_wifi_stop();
+
+    // Disable scheduler on this core.
+    vTaskSuspendAll();
+    const uint32_t core_id = xPortGetCoreID();
+    const uint32_t other_core_id = core_id == 0 ? 1 : 0;
+    esp_cpu_stall(other_core_id);
+
+    // We need to disable TG0/TG1 watchdogs
+    // First enable RTC watchdog to be on the safe side
+    REG_WRITE(RTC_CNTL_WDTWPROTECT_REG, RTC_CNTL_WDT_WKEY_VALUE);
+    REG_WRITE(RTC_CNTL_WDTCONFIG0_REG,
+            RTC_CNTL_WDT_FLASHBOOT_MOD_EN_M |
+            (1 << RTC_CNTL_WDT_SYS_RESET_LENGTH_S) |
+            (1 << RTC_CNTL_WDT_CPU_RESET_LENGTH_S) );
+    REG_WRITE(RTC_CNTL_WDTCONFIG1_REG, 128000);
+
+    // Disable TG0/TG1 watchdogs
+    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;
+    TIMERG1.wdt_wprotect=0;
+
+    // Disable all interrupts
+    xt_ints_off(0xFFFFFFFF);
+
+    // Disable cache
+    Cache_Read_Disable(0);
+    Cache_Read_Disable(1);
+
+    // Flush any data left in UART FIFO
+    uart_tx_flush(0);
+    uart_tx_flush(1);
+    uart_tx_flush(2);
+
+    // Reset wifi/bluetooth (bb/mac)
+    SET_PERI_REG_MASK(DPORT_WIFI_RST_EN_REG, 0x1f);
+    REG_WRITE(DPORT_WIFI_RST_EN_REG, 0);
+
+    // Reset timer/spi/uart
+    SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG,
+            DPORT_TIMERS_RST | DPORT_SPI_RST_1 | DPORT_UART_RST);
+    REG_WRITE(DPORT_PERIP_RST_EN_REG, 0);
+
+    // Reset CPUs
+    if (core_id == 0) {
+        // Running on PRO CPU: APP CPU is stalled. Can reset both CPUs.
+        SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG,
+                RTC_CNTL_SW_PROCPU_RST_M | RTC_CNTL_SW_APPCPU_RST_M);
+    } else {
+        // Running on APP CPU: need to reset PRO CPU and unstall it,
+        // then stall APP CPU
+        SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_PROCPU_RST_M);
+        esp_cpu_unstall(0);
+        esp_cpu_stall(1);
+    }
+    while(true) {
+        ;
+    }
+}
+
+void system_restart(void) __attribute__((alias("esp_restart")));
+
+void system_restore(void)
+{
+    esp_wifi_restore();
+}
+
+uint32_t esp_get_free_heap_size(void)
+{
+    return xPortGetFreeHeapSize();
+}
+
+uint32_t system_get_free_heap_size(void) __attribute__((alias("esp_get_free_heap_size")));
+
+const char* system_get_sdk_version(void)
+{
+    return "master";
+}
+
+

+ 17 - 0
components/esp32/test/component.mk

@@ -0,0 +1,17 @@
+#
+#Component Makefile
+#
+
+COMPONENT_EXTRA_CLEAN := test_tjpgd_logo.h
+
+COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive
+
+COMPONENT_SRCDIRS := . test_vectors
+
+include $(IDF_PATH)/make/component_common.mk
+
+test_tjpgd.o: test_tjpgd_logo.h
+
+test_tjpgd_logo.h: $(COMPONENT_PATH)/logo.jpg
+	$(summary) XXD logo.jpg
+	$(Q) cd $(COMPONENT_PATH); xxd -i logo.jpg $(COMPONENT_BUILD_DIR)/test_tjpgd_logo.h

BIN
components/esp32/test/logo.jpg


+ 293 - 0
components/esp32/test/test_ahb_arb.c

@@ -0,0 +1,293 @@
+
+#include <esp_types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "rom/ets_sys.h"
+#include "rom/lldesc.h"
+#include "rom/gpio.h"
+
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "freertos/semphr.h"
+#include "freertos/queue.h"
+#include "freertos/xtensa_api.h"
+
+#include "unity.h"
+
+#include "soc/uart_reg.h"
+#include "soc/dport_reg.h"
+#include "soc/io_mux_reg.h"
+#include "soc/gpio_sig_map.h"
+#include "soc/gpio_reg.h"
+#include "soc/i2s_reg.h"
+
+
+#define DPORT_I2S0_CLK_EN   (BIT(4))
+#define DPORT_I2S0_RST   (BIT(4))
+
+
+/*
+This test tests the s32c1i instruction when the AHB bus is also used. To create some AHB traffic, we use the I2S interface
+to copy bytes over from one memory location to another. DO NOT USE the i2s routines inhere, they've been trial-and-error'ed until
+the point where they happened to do what I want.
+*/
+
+static void lcdIfaceInit()
+{
+    SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S0_CLK_EN);
+    CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S0_RST);
+
+    //Init pins to i2s functions
+    SET_PERI_REG_MASK(GPIO_ENABLE_W1TS_REG, (1 << 11) | (1 << 3) | (1 << 0) | (1 << 2) | (1 << 5) | (1 << 16) | (1 << 17) | (1 << 18) | (1 << 19) | (1 << 20)); //ENABLE GPIO oe_enable
+
+    PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, 0);
+    PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, 0);
+    PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO5_U, 0);
+    PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO16_U, 0);
+    PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO17_U, 0);
+    PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO18_U, 0);
+    PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO19_U, 0);
+    PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO20_U, 0);
+    PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CMD_U, 2); //11
+    PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO26_U, 0); //RS
+
+    WRITE_PERI_REG(GPIO_FUNC0_OUT_SEL_CFG_REG, (148 << GPIO_FUNC0_OUT_SEL_S));
+    WRITE_PERI_REG(GPIO_FUNC2_OUT_SEL_CFG_REG, (149 << GPIO_FUNC0_OUT_SEL_S));
+    WRITE_PERI_REG(GPIO_FUNC5_OUT_SEL_CFG_REG, (150 << GPIO_FUNC0_OUT_SEL_S));
+    WRITE_PERI_REG(GPIO_FUNC16_OUT_SEL_CFG_REG, (151 << GPIO_FUNC0_OUT_SEL_S));
+    WRITE_PERI_REG(GPIO_FUNC17_OUT_SEL_CFG_REG, (152 << GPIO_FUNC0_OUT_SEL_S));
+    WRITE_PERI_REG(GPIO_FUNC18_OUT_SEL_CFG_REG, (153 << GPIO_FUNC0_OUT_SEL_S));
+    WRITE_PERI_REG(GPIO_FUNC19_OUT_SEL_CFG_REG, (154 << GPIO_FUNC0_OUT_SEL_S));
+    WRITE_PERI_REG(GPIO_FUNC20_OUT_SEL_CFG_REG, (155 << GPIO_FUNC0_OUT_SEL_S));
+    WRITE_PERI_REG(GPIO_FUNC26_OUT_SEL_CFG_REG, (156 << GPIO_FUNC0_OUT_SEL_S)); //RS
+    WRITE_PERI_REG(GPIO_FUNC11_OUT_SEL_CFG_REG, (I2S0O_WS_OUT_IDX << GPIO_FUNC0_OUT_SEL_S));
+//  WRITE_PERI_REG(GPIO_FUNC11_OUT_SEL_CFG, (I2S0O_BCK_OUT_IDX<<GPIO_GPIO_FUNC0_OUT_SEL_S));
+
+    //GPIO_SET_GPIO_FUNC11_OUT_INV_SEL(1); //old
+    WRITE_PERI_REG(GPIO_FUNC11_OUT_SEL_CFG_REG, READ_PERI_REG(GPIO_FUNC11_OUT_SEL_CFG_REG) | GPIO_FUNC11_OUT_INV_SEL);
+
+    //Reset I2S subsystem
+    CLEAR_PERI_REG_MASK(I2S_CONF_REG(0), I2S_RX_RESET | I2S_TX_RESET);
+    SET_PERI_REG_MASK(I2S_CONF_REG(0), I2S_RX_RESET | I2S_TX_RESET);
+    CLEAR_PERI_REG_MASK(I2S_CONF_REG(0), I2S_RX_RESET | I2S_TX_RESET);
+
+    WRITE_PERI_REG(I2S_CONF_REG(0), 0);//I2S_SIG_LOOPBACK);
+    WRITE_PERI_REG(I2S_CONF2_REG(0), 0);
+
+    WRITE_PERI_REG(I2S_SAMPLE_RATE_CONF_REG(0),
+                   (16 << I2S_RX_BITS_MOD_S) |
+                   (16 << I2S_TX_BITS_MOD_S) |
+                   (1 << I2S_RX_BCK_DIV_NUM_S) |
+                   (1 << I2S_TX_BCK_DIV_NUM_S));
+    WRITE_PERI_REG(I2S_CLKM_CONF_REG(0),
+                   I2S_CLKA_ENA | I2S_CLK_EN |
+                   (1 << I2S_CLKM_DIV_A_S) |
+                   (1 << I2S_CLKM_DIV_B_S) |
+                   (1 << I2S_CLKM_DIV_NUM_S));
+    WRITE_PERI_REG(I2S_FIFO_CONF_REG(0),
+                   (32 << I2S_TX_DATA_NUM_S) |     //Low watermark for IRQ
+                   (32 << I2S_RX_DATA_NUM_S));
+
+    WRITE_PERI_REG(I2S_CONF1_REG(0), I2S_RX_PCM_BYPASS | I2S_TX_PCM_BYPASS);
+
+    WRITE_PERI_REG(I2S_CONF_CHAN_REG(0), (2 << I2S_TX_CHAN_MOD_S) | (2 << I2S_RX_CHAN_MOD_S));
+
+    //Invert WS to active-low
+    SET_PERI_REG_MASK(I2S_CONF_REG(0), I2S_TX_RIGHT_FIRST | I2S_RX_RIGHT_FIRST);
+    WRITE_PERI_REG(I2S_TIMING_REG(0), 0);
+}
+
+
+static volatile lldesc_t dmaDesc[2];
+
+static void finishDma()
+{
+    //No need to finish if no DMA transfer going on
+    if (!(READ_PERI_REG(I2S_FIFO_CONF_REG(0))&I2S_DSCR_EN)) {
+        return;
+    }
+
+    //Wait till fifo done
+    while (!(READ_PERI_REG(I2S_INT_RAW_REG(0))&I2S_TX_REMPTY_INT_RAW)) ;
+    //Wait for last bytes to leave i2s xmit thing
+    //ToDo: poll bit in next hw
+//  for (i=0; i<(1<<8); i++);
+    while (!(READ_PERI_REG(I2S_STATE_REG(0))&I2S_TX_IDLE));
+
+    //Reset I2S for next transfer
+    CLEAR_PERI_REG_MASK(I2S_CONF_REG(0), I2S_TX_START | I2S_RX_START);
+    CLEAR_PERI_REG_MASK(I2S_OUT_LINK_REG(0), I2S_OUTLINK_START | I2S_INLINK_START);
+
+    SET_PERI_REG_MASK(I2S_CONF_REG(0), I2S_TX_RESET | I2S_TX_FIFO_RESET | I2S_RX_RESET | I2S_RX_FIFO_RESET);
+    CLEAR_PERI_REG_MASK(I2S_CONF_REG(0), I2S_TX_RESET | I2S_TX_FIFO_RESET | I2S_RX_RESET | I2S_RX_FIFO_RESET);
+
+//  for (i=0; i<(1<<8); i++);
+    while ((READ_PERI_REG(I2S_STATE_REG(0))&I2S_TX_FIFO_RESET_BACK));
+}
+
+
+/*
+This is a very, very, very hacked up LCD routine which ends up basically doing a memcpy from sbuf to rbuf.
+*/
+static void sendRecvBufDma(uint16_t *sbuf, uint16_t *rbuf, int len)
+{
+    //Fill DMA descriptor
+    dmaDesc[0].length = len * 2;
+    dmaDesc[0].size = len * 2;
+    dmaDesc[0].owner = 1;
+    dmaDesc[0].sosf = 0;
+    dmaDesc[0].buf = (uint8_t *)sbuf;
+    dmaDesc[0].offset = 0; //unused in hw
+    dmaDesc[0].empty = 0;
+    dmaDesc[0].eof = 1;
+    dmaDesc[1].length = len * 2;
+    dmaDesc[1].size = len * 2;
+    dmaDesc[1].owner = 1;
+    dmaDesc[1].sosf = 0;
+    dmaDesc[1].buf = (uint8_t *)rbuf;
+    dmaDesc[1].offset = 0; //unused in hw
+    dmaDesc[1].empty = 0;
+    dmaDesc[1].eof = 1;
+
+    //Reset DMA
+    SET_PERI_REG_MASK(I2S_LC_CONF_REG(0), I2S_IN_RST | I2S_OUT_RST | I2S_AHBM_RST | I2S_AHBM_FIFO_RST);
+    CLEAR_PERI_REG_MASK(I2S_LC_CONF_REG(0), I2S_IN_RST | I2S_OUT_RST | I2S_AHBM_RST | I2S_AHBM_FIFO_RST);
+
+    //Reset I2S FIFO
+    SET_PERI_REG_MASK(I2S_CONF_REG(0), I2S_RX_RESET | I2S_TX_RESET | I2S_TX_FIFO_RESET | I2S_RX_FIFO_RESET);
+    CLEAR_PERI_REG_MASK(I2S_CONF_REG(0), I2S_RX_RESET | I2S_TX_RESET | I2S_TX_FIFO_RESET | I2S_RX_FIFO_RESET);
+
+    //Set desc addr
+    CLEAR_PERI_REG_MASK(I2S_OUT_LINK_REG(0), I2S_OUTLINK_ADDR);
+    SET_PERI_REG_MASK(I2S_OUT_LINK_REG(0), ((uint32_t)(&dmaDesc[0]))&I2S_OUTLINK_ADDR);
+    CLEAR_PERI_REG_MASK(I2S_IN_LINK_REG(0), I2S_INLINK_ADDR);
+    SET_PERI_REG_MASK(I2S_IN_LINK_REG(0), ((uint32_t)(&dmaDesc[1]))&I2S_INLINK_ADDR);
+
+    SET_PERI_REG_MASK(I2S_FIFO_CONF_REG(0), I2S_DSCR_EN); //Enable DMA mode
+
+    WRITE_PERI_REG(I2S_RXEOF_NUM_REG(0), len);
+
+    //Enable and configure DMA
+    WRITE_PERI_REG(I2S_LC_CONF_REG(0), I2S_OUT_DATA_BURST_EN  |
+                   I2S_OUT_EOF_MODE | I2S_OUTDSCR_BURST_EN | I2S_OUT_DATA_BURST_EN |
+                   I2S_INDSCR_BURST_EN | I2S_MEM_TRANS_EN);
+
+    //Start transmission
+    SET_PERI_REG_MASK(I2S_OUT_LINK_REG(0), I2S_OUTLINK_START);
+    SET_PERI_REG_MASK(I2S_IN_LINK_REG(0), I2S_INLINK_START);
+
+    SET_PERI_REG_MASK(I2S_CONF_REG(0), I2S_TX_START | I2S_RX_START);
+    //Clear int flags
+    WRITE_PERI_REG(I2S_INT_CLR_REG(0), 0xFFFFFFFF);
+}
+
+
+#define DMALEN (2048-2)
+
+static void tskLcd(void *pvParameters)
+{
+    uint16_t *sbuf = malloc(DMALEN * 2);
+    uint16_t *rbuf = malloc(DMALEN * 2);
+    uint16_t xorval = 0;
+    int x;
+    lcdIfaceInit();
+//  lcdFlush();
+    while (1) {
+        for (x = 0; x < DMALEN; x++) {
+            sbuf[x] = x ^ xorval;
+        }
+        for (x = 0; x < DMALEN; x++) {
+            rbuf[x] = 0;    //clear rbuf
+        }
+        sendRecvBufDma(sbuf, rbuf, DMALEN);
+        vTaskDelay(20 / portTICK_PERIOD_MS);
+        finishDma();
+        for (x = 0; x < DMALEN; x++) if (rbuf[x] != (x ^ xorval)) {
+                printf("Rxbuf err! pos %d val %x xor %x", x, (int)rbuf[x], (int)xorval);
+            }
+        printf(".");
+        fflush(stdout);
+        xorval++;
+    }
+}
+
+
+
+void test_s32c1i_lock(volatile int *lockvar, int lockval, int unlockval, volatile int *ctr);
+
+static volatile int ctr = 0, state = 0;
+static volatile int lock = 0;
+
+static void tskOne(void *pvParameters)
+{
+    int x;
+    int err = 0, run = 0;
+    while (1) {
+        ctr = 0; lock = 0;
+        state = 1;
+        for (x = 0; x < 16 * 1024; x++) {
+            test_s32c1i_lock(&lock, 1, 0, &ctr);
+        }
+        vTaskDelay(60 / portTICK_PERIOD_MS);
+        state = 2;
+        if (ctr != 16 * 1024 * 2) {
+            printf("Lock malfunction detected! Ctr=0x%x instead of %x\n", ctr, 16 * 1024 * 2);
+            err++;
+        }
+        run++;
+        printf("Run %d err %d\n", run, err);
+        vTaskDelay(20 / portTICK_PERIOD_MS);
+    }
+}
+
+#define FB2ADDR 0x40098000
+
+static void tskTwo(void *pvParameters)
+{
+    int x;
+    int *p = (int *)FB2ADDR;
+    int *s = (int *)test_s32c1i_lock;
+    void (*test_s32c1i_lock2)(volatile int * lockvar, int lockval, int unlockval, volatile int * ctr) = (void *)FB2ADDR;
+    volatile int w;
+    int delay;
+    for (x = 0; x < 100; x++) {
+        *p++ = *s++;    //copy routine to different pool
+    }
+
+    while (1) {
+        while (state != 1) ;
+        for (x = 0; x < 16 * 1024; x++) {
+            test_s32c1i_lock2(&lock, 2, 0, &ctr);
+            //Some random delay to increase chance of weirdness
+            if ((x & 0x1f) == 0) {
+                delay = rand() & 0x1f;
+                for (w = 0; w < delay; w++);
+            }
+        }
+        while (state != 2);
+    }
+}
+
+
+TEST_CASE("S32C1I vs AHB test (needs I2S)", "[hw]")
+{
+    int i;
+    TaskHandle_t th[3];
+    state = 0;
+
+    printf("Creating tasks\n");
+    xTaskCreatePinnedToCore(tskTwo  , "tsktwo"  , 2048, NULL, 3, &th[1], 1);
+    xTaskCreatePinnedToCore(tskOne  , "tskone"  , 2048, NULL, 3, &th[0], 0);
+    xTaskCreatePinnedToCore(tskLcd  , "tsklcd"  , 2048, NULL, 3, &th[2], 0);
+
+    // Let stuff run for 20s
+    while (1) {
+        vTaskDelay(20000 / portTICK_PERIOD_MS);
+    }
+
+    //Shut down all the tasks
+    for (i = 0; i < 3; i++) {
+        vTaskDelete(th[i]);
+    }
+}
+

+ 51 - 0
components/esp32/test/test_ahb_arb_asm.S

@@ -0,0 +1,51 @@
+/*
+This little bit of code is executed in-place by one CPU, but copied to a different memory region
+by the other CPU. Make sure it stays position-independent.
+*/
+    .text
+    .align  4
+    .global test_s32c1i_lock
+    .type   test_s32c1i_lock,@function
+//Args:
+//a2 - lock addr
+//a3 - val to lock with
+//a4 - val to unlock with
+//a5 - addr to increase
+test_s32c1i_lock:
+	entry a1, 64
+	wsr a4, SCOMPARE1
+lockloop:
+	mov a6, a3
+	s32c1i a6, a2, 0
+	bne a4, a6, lockloop
+
+	l32i a6, a5, 0
+	//Give other CPU the time to mess up the inc if the lock somehow malfunctions
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	addi a6, a6, 1
+	s32i a6, a5, 0
+
+
+//No need to actually let this loop but hey, a hang indicates an error, right?
+	wsr a3, SCOMPARE1
+unlockloop:
+	mov a6, a4
+	s32c1i a6, a2, 0
+	bne a3, a6, unlockloop
+	
+	retw

+ 132 - 0
components/esp32/test/test_fastbus.c

@@ -0,0 +1,132 @@
+
+#include <esp_types.h>
+#include <stdio.h>
+#include "rom/ets_sys.h"
+
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "freertos/semphr.h"
+#include "freertos/queue.h"
+#include "freertos/xtensa_api.h"
+#include "unity.h"
+#include "soc/uart_reg.h"
+#include "soc/dport_reg.h"
+#include "soc/io_mux_reg.h"
+
+
+/*
+This test tests the 'fast' peripherial bus at 0x3ff40000. This bus is connected directly to the core, and as such
+can receive 'speculative' reads, that is, reads that may or may not actually be executed in the code flow. This
+may mess with any FIFOs mapped in the region: if a byte gets dropped due to a missed speculative read, the fifo
+may advance to the next byte anyway.
+
+This code tests reading/writing from the UART1 FIFO, using both cores. For this to work, it's required that the
+UARTs RX and TX lines are connected.
+*/
+
+
+void test_fastbus_cp(int fifo_addr, unsigned char *buf, int len, int *dummy);
+
+static volatile int state = 0;
+static volatile int xor = 0;
+static unsigned char res[128];
+
+static void tskOne(void *pvParameters)
+{
+    int run = 0, err = 0;
+    int x;
+    int ct[256];
+    volatile int w;
+    int dummy;
+    while (1) {
+        state = 1;
+        for (x = 0; x < 64; x++) {
+            WRITE_PERI_REG(UART_FIFO_REG(1), x ^ xor);
+        }
+        for (w = 0; w < (1 << 14); w++); //delay
+        state = 2;
+        test_fastbus_cp(UART_FIFO_REG(1), &res[0], 64, &dummy);
+        for (w = 0; w < (1 << 10); w++);    //delay
+        for (x = 0; x < 255; x++) {
+            ct[x] = 0;    //zero ctrs
+        }
+        for (x = 0; x < 128; x++) {
+            ct[(int)res[x]^xor]++;    //count values
+        }
+        for (x = 0; x < 255; x++) {         //check counts
+            if (ct[x] != (x < 128 ? 1 : 0)) {
+                //Disregard first few loops; there may be crap in the fifo.
+                if (run > 2) {
+                    err++;
+                    printf("Error! Received value %d %d times!\n", x, ct[x]);
+                }
+            }
+        }
+        run++;
+        if ((run & 255) == 0) {
+            printf("Loop %d errct %d\n", run, err);
+        }
+        xor = (xor + 1) & 0xff;
+    }
+}
+
+#define FB2ADDR 0x40098000
+
+static void tskTwo(void *pvParameters)
+{
+    int x;
+    int dummy;
+    int *p = (int *)FB2ADDR;
+    int *s = (int *)test_fastbus_cp;
+    for (x = 0; x < 100; x++) {
+        *p++ = *s++;
+    }
+    void (*test_fastbus_cp2)(int fifo_addr, unsigned char * buf, int len, int * dummy) = (void *)FB2ADDR;
+
+
+    while (1) {
+        while (state != 1) ;
+        for (x = 64; x < 128; x++) {
+            WRITE_PERI_REG(UART_FIFO_REG(1), x ^ xor);
+        }
+        while (state != 2);
+        test_fastbus_cp2(UART_FIFO_REG(1), &res[64], 64, &dummy);
+    }
+}
+
+
+// TODO: split this thing into separate orthogonal tests
+TEST_CASE("Fast I/O bus test", "[hw]")
+{
+    int i;
+    if ((REG_UART_BASE(0) >> 16) != 0x3ff4) {
+        printf("Error! Uart base isn't on fast bus.\n");
+        TEST_ASSERT(0);
+    }
+
+    PIN_PULLUP_DIS(PERIPHS_IO_MUX_SD_DATA3_U);
+    PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA2_U, FUNC_SD_DATA2_U1RXD);
+    PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA3_U, FUNC_SD_DATA3_U1TXD);
+
+    int reg_val = (1 << UART_RXFIFO_FULL_THRHD_S);
+    WRITE_PERI_REG(UART_CONF1_REG(1), reg_val);
+    WRITE_PERI_REG(UART_CLKDIV_REG(1), 0x30); //semi-random
+//  CLEAR_PERI_REG_MASK(UART_INT_ENA_REG(1), UART_TXFIFO_EMPTY_INT_ENA|UART_RXFIFO_TOUT_INT_ENA);
+
+    TaskHandle_t th[2];
+    printf("Creating tasks\n");
+    xTaskCreatePinnedToCore(tskOne  , "tskone"  , 2048, NULL, 3, &th[0], 0);
+    xTaskCreatePinnedToCore(tskTwo  , "tsktwo"  , 2048, NULL, 3, &th[1], 1);
+
+    // Let stuff run for 20s
+    while (1) {
+        vTaskDelay(20000 / portTICK_PERIOD_MS);
+    }
+
+    //Shut down all the tasks
+    for (i = 0; i < 2; i++) {
+        vTaskDelete(th[i]);
+    }
+    xt_ints_off(1 << ETS_UART0_INUM);
+}
+

+ 32 - 0
components/esp32/test/test_fastbus_asm.S

@@ -0,0 +1,32 @@
+/*
+This little bit of code is executed in-place by one CPU, but copied to a different memory region
+by the other CPU. Make sure it stays position-independent.
+*/
+    .text
+    .align  4
+    .global test_fastbus_cp
+    .type   test_fastbus_cp,@function
+//Args:
+//a2 - fifo addr
+//a3 - buf addr
+//a4 - len
+//a5 - ptr to int to use
+test_fastbus_cp:
+	entry a1,64
+back:
+	beqi a4, 0, out		//check if loop done
+	s32i a4, a5, 0		//store value, for shits and/or giggles
+	memw				//make sure write happens
+	l32i a4, a5, 0		//load value again, to thwart any prediction in the pipeline
+	bbsi a4, 0, pred	//Random jump to check predictive reads. Both branches should do the same.
+	l32i a6, a2, 0		//read from fifo 1
+	j predout
+pred:
+	l32i a6, a2, 0		//read from fifo 2
+predout:
+	s8i a6, a3, 0		//store result
+	addi a3, a3, 1		//inc ptr
+	addi a4, a4, -1		//next
+	j back				//loop again
+out:
+	retw				//and we are done

+ 193 - 0
components/esp32/test/test_fp.c

@@ -0,0 +1,193 @@
+#include <math.h>
+#include <stdio.h>
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "unity.h"
+
+static float addsf(float a, float b)
+{
+    float result;
+    asm volatile (
+        "wfr f0, %1\n"
+        "wfr f1, %2\n"
+        "add.s f2, f0, f1\n"
+        "rfr %0, f2\n"
+        :"=r"(result):"r"(a), "r"(b)
+    );
+    return result;
+}
+
+static float mulsf(float a, float b)
+{
+    float result;
+    asm volatile (
+        "wfr f0, %1\n"
+        "wfr f1, %2\n"
+        "mul.s f2, f0, f1\n"
+        "rfr %0, f2\n"
+        :"=r"(result):"r"(a), "r"(b)
+    );
+    return result;
+}
+
+static float divsf(float a, float b)
+{
+    float result;
+    asm volatile (
+        "wfr f0, %1\n"
+        "wfr f1, %2\n"
+        "div0.s f3, f1 \n"
+        "nexp01.s f4, f1 \n"
+        "const.s f5, 1 \n"
+        "maddn.s f5, f4, f3 \n"
+        "mov.s f6, f3 \n"
+        "mov.s f7, f1 \n"
+        "nexp01.s f8, f0 \n"
+        "maddn.s f6, f5, f3 \n"
+        "const.s f5, 1 \n"
+        "const.s f2, 0 \n"
+        "neg.s f9, f8 \n"
+        "maddn.s f5,f4,f6 \n"
+        "maddn.s f2, f0, f3 \n"
+        "mkdadj.s f7, f0 \n"
+        "maddn.s f6,f5,f6 \n"
+        "maddn.s f9,f4,f2 \n"
+        "const.s f5, 1 \n"
+        "maddn.s f5,f4,f6 \n"
+        "maddn.s f2,f9,f6 \n"
+        "neg.s f9, f8 \n"
+        "maddn.s f6,f5,f6 \n"
+        "maddn.s f9,f4,f2 \n"
+        "addexpm.s f2, f7 \n"
+        "addexp.s f6, f7 \n"
+        "divn.s f2,f9,f6\n"
+        "rfr %0, f2\n"
+        :"=r"(result):"r"(a), "r"(b)
+    );
+    return result;
+}
+
+static float sqrtsf(float a)
+{
+    float result;
+    asm volatile (
+        "wfr f0, %1\n"
+        "sqrt0.s f2, f0\n"
+        "const.s f5, 0\n"
+        "maddn.s f5, f2, f2\n"
+        "nexp01.s f3, f0\n"
+        "const.s f4, 3\n"
+        "addexp.s f3, f4\n"
+        "maddn.s f4, f5, f3\n"
+        "nexp01.s f5, f0\n"
+        "neg.s f6, f5\n"
+        "maddn.s f2, f4, f2\n"
+        "const.s f1, 0\n"
+        "const.s f4, 0\n"
+        "const.s f7, 0\n"
+        "maddn.s f1, f6, f2\n"
+        "maddn.s f4, f2, f3\n"
+        "const.s f6, 3\n"
+        "maddn.s f7, f6, f2\n"
+        "maddn.s f5, f1, f1\n"
+        "maddn.s f6, f4, f2\n"
+        "neg.s f3, f7\n"
+        "maddn.s f1, f5, f3\n"
+        "maddn.s f7, f6, f7\n"
+        "mksadj.s f2, f0\n"
+        "nexp01.s f5, f0\n"
+        "maddn.s f5, f1, f1\n"
+        "neg.s f3, f7\n"
+        "addexpm.s f1, f2\n"
+        "addexp.s f3, f2\n"
+        "divn.s f1, f5, f3\n"
+        "rfr %0, f1\n"
+        :"=r"(result):"r"(a)
+    );
+    return result;
+}
+
+TEST_CASE("test FP add", "[fp]")
+{
+    float a = 100.0f;
+    float b = 0.5f;
+    float c = addsf(a, b);
+    float eps = c - 100.5f;
+    printf("a=%g b=%g c=%g eps=%g\r\n", a, b, c, eps);
+    TEST_ASSERT_TRUE(fabs(eps) < 0.000001);
+}
+
+TEST_CASE("test FP mul", "[fp]")
+{
+    float a = 100.0f;
+    float b = 0.05f;
+    float c = mulsf(a, b);
+    float eps = c - 5.0f;
+    printf("a=%g b=%g c=%g eps=%g\r\n", a, b, c, eps);
+    TEST_ASSERT_TRUE(fabs(eps) < 0.000001);
+}
+
+TEST_CASE("test FP div", "[fp]")
+{
+    float a = 100.0f;
+    float b = 5.0f;
+    float c = divsf(a, b);
+    float eps = c - 20.0f;
+    printf("a=%g b=%g c=%g eps=%g\r\n", a, b, c, eps);
+    TEST_ASSERT_TRUE(fabs(eps) < 0.000001);
+}
+
+TEST_CASE("test FP sqrt", "[fp]")
+{
+    float a = 100.0f;
+    float c = sqrtsf(a);
+    float eps = c - 10.0f;
+    printf("a=%g c=%g eps=%g\r\n", a, c, eps);
+    TEST_ASSERT_TRUE(fabs(eps) < 0.000001);
+}
+
+
+struct TestFPState {
+    int fail;
+    int done;
+};
+
+static const int testFpIter = 100000;
+
+static void tskTestFP(void *pvParameters)
+{
+    struct TestFPState *state = (struct TestFPState *) pvParameters;
+    for (int i = 0; i < testFpIter; ++i) {
+        // calculate zero in a slightly obscure way
+        float y = sqrtsf(addsf(1.0f, divsf(mulsf(sqrtsf(2), sqrtsf(2)), 2.0f)));
+        y = mulsf(y, y);
+        y = addsf(y, -2.0f);
+        // check that result is not far from zero
+        float eps = fabs(y);
+        if (eps > 1e-6f) {
+            state->fail++;
+            printf("%s: i=%d y=%f eps=%f\r\n", __func__, i, y, eps);
+        }
+    }
+    state->done++;
+    vTaskDelete(NULL);
+}
+
+TEST_CASE("context switch saves FP registers", "[fp]")
+{
+    struct TestFPState state;
+    state.done = 0;
+    state.fail = 0;
+    xTaskCreatePinnedToCore(tskTestFP, "tsk1", 2048, &state, 3, NULL, 0);
+    xTaskCreatePinnedToCore(tskTestFP, "tsk2", 2048, &state, 3, NULL, 0);
+    xTaskCreatePinnedToCore(tskTestFP, "tsk3", 2048, &state, 3, NULL, 1);
+    xTaskCreatePinnedToCore(tskTestFP, "tsk4", 2048, &state, 3, NULL, 0);
+    while (state.done != 4) {
+        vTaskDelay(100 / portTICK_PERIOD_MS);
+    }
+    if (state.fail) {
+        const int total = testFpIter * 4;
+        printf("Failed: %d, total: %d\r\n", state.fail, total);
+    }
+    TEST_ASSERT(state.fail == 0);
+}

+ 77 - 0
components/esp32/test/test_miniz.c

@@ -0,0 +1,77 @@
+
+
+#include <stdio.h>
+#include "rom/miniz.h"
+#include "unity.h"
+
+
+#define DATASIZE (1024*64)
+
+TEST_CASE("Test miniz compression/decompression", "[miniz]")
+{
+    int x;
+    char b;
+    char *inbuf, *outbuf;
+    tdefl_compressor *comp;
+    tinfl_decompressor *decomp;
+    tdefl_status status;
+    size_t inbytes = 0, outbytes = 0, inpos = 0, outpos = 0, compsz;
+    printf("Allocating data buffer and filling it with semi-random data\n");
+    inbuf = malloc(DATASIZE);
+    TEST_ASSERT(inbuf != NULL);
+    srand(0);
+    for (x = 0; x < DATASIZE; x++) {
+        inbuf[x] = (x & 1) ? rand() & 0xff : 0;
+    }
+    printf("Allocating compressor & outbuf (%d bytes)\n", sizeof(tdefl_compressor));
+    comp = malloc(sizeof(tdefl_compressor));
+    TEST_ASSERT(comp != NULL);
+    outbuf = malloc(DATASIZE);
+    TEST_ASSERT(outbuf != NULL);
+    printf("Compressing...\n");
+    status = tdefl_init(comp, NULL, NULL, TDEFL_WRITE_ZLIB_HEADER | 1500);
+    TEST_ASSERT(status == TDEFL_STATUS_OKAY);
+    while (inbytes != DATASIZE) {
+        outbytes = DATASIZE - outpos;
+        inbytes = DATASIZE - inpos;
+        tdefl_compress(comp, &inbuf[inpos], &inbytes, &outbuf[outpos], &outbytes, TDEFL_FINISH);
+        printf("...Compressed %d into %d bytes\n", inbytes, outbytes);
+        inpos += inbytes; outpos += outbytes;
+    }
+    compsz = outpos;
+    free(comp);
+    //Kill inbuffer
+    for (x = 0; x < DATASIZE; x++) {
+        inbuf[x] = 0;
+    }
+    free(inbuf);
+
+    inbuf = outbuf;
+    outbuf = malloc(DATASIZE);
+    TEST_ASSERT(outbuf != NULL);
+    printf("Reinflating...\n");
+    decomp = malloc(sizeof(tinfl_decompressor));
+    TEST_ASSERT(decomp != NULL);
+    tinfl_init(decomp);
+    inpos = 0; outpos = 0;
+    while (inbytes != compsz) {
+        outbytes = DATASIZE - outpos;
+        inbytes = compsz - inpos;
+        tinfl_decompress(decomp, (const mz_uint8 *)&inbuf[inpos], &inbytes, (uint8_t *)outbuf, (mz_uint8 *)&outbuf[outpos], &outbytes, TINFL_FLAG_PARSE_ZLIB_HEADER);
+        printf("...Decompressed %d into %d bytes\n", inbytes, outbytes);
+        inpos += inbytes; outpos += outbytes;
+    }
+    printf("Checking if same...\n");
+    srand(0);
+    for (x = 0; x < DATASIZE; x++) {
+        b = (x & 1) ? rand() & 0xff : 0;
+        if (outbuf[x] != b) {
+            printf("Pos %x: %hhx!=%hhx\n", x, outbuf[x], b);
+            TEST_ASSERT(0);
+        }
+    }
+    printf("Great Success!\n");
+    free(inbuf);
+    free(outbuf);
+    free(decomp);
+}

+ 91 - 0
components/esp32/test/test_tjpgd.c

@@ -0,0 +1,91 @@
+
+
+#include <stdio.h>
+#include "rom/tjpgd.h"
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "unity.h"
+
+#include "test_tjpgd_logo.h"
+
+typedef struct {
+    const unsigned char *inData;
+    int inPos;
+    unsigned char *outData;
+    int outW;
+    int outH;
+} JpegDev;
+
+
+static UINT infunc(JDEC *decoder, BYTE *buf, UINT len)
+{
+    JpegDev *jd = (JpegDev *)decoder->device;
+    printf("Reading %d bytes from pos %d\n", len, jd->inPos);
+    if (buf != NULL) {
+        memcpy(buf, jd->inData + jd->inPos, len);
+    }
+    jd->inPos += len;
+    return len;
+}
+
+
+static UINT outfunc(JDEC *decoder, void *bitmap, JRECT *rect)
+{
+    unsigned char *in = (unsigned char *)bitmap;
+    unsigned char *out;
+    int y;
+    printf("Rect %d,%d - %d,%d\n", rect->top, rect->left, rect->bottom, rect->right);
+    JpegDev *jd = (JpegDev *)decoder->device;
+    for (y = rect->top; y <= rect->bottom; y++) {
+        out = jd->outData + ((jd->outW * y) + rect->left) * 3;
+        memcpy(out, in, ((rect->right - rect->left) + 1) * 3);
+        in += ((rect->right - rect->left) + 1) * 3;
+    }
+    return 1;
+}
+
+#define TESTW 48
+#define TESTH 48
+#define WORKSZ 3100
+
+TEST_CASE("Test JPEG decompression library", "[tjpgd]")
+{
+    char aapix[] = " .:;+=xX$$";
+    unsigned char *decoded, *p;
+    char *work;
+    int r;
+    int x, y, v;
+    JDEC decoder;
+    JpegDev jd;
+    decoded = malloc(48 * 48 * 3);
+    for (x = 0; x < 48 * 48 * 3; x += 2) {
+        decoded[x] = 0; decoded[x + 1] = 0xff;
+    }
+    work = malloc(WORKSZ);
+    memset(work, 0, WORKSZ);
+
+    jd.inData = logo_jpg;
+    jd.inPos = 0;
+    jd.outData = decoded;
+    jd.outW = TESTW;
+    jd.outH = TESTH;
+
+    r = jd_prepare(&decoder, infunc, work, WORKSZ, (void *)&jd);
+    TEST_ASSERT_EQUAL(r, JDR_OK);
+    r = jd_decomp(&decoder, outfunc, 0);
+    TEST_ASSERT_EQUAL(r, JDR_OK);
+
+    p = decoded + 2;
+    for (y = 0; y < TESTH; y++) {
+        for (x = 0; x < TESTH; x++) {
+            v = ((*p) * (sizeof(aapix) - 2) * 2) / 256;
+            printf("%c%c", aapix[v / 2], aapix[(v + 1) / 2]);
+            p += 3;
+        }
+        printf("%c%c", ' ', '\n');
+    }
+
+    free(work);
+    free(decoded);
+}

+ 205 - 0
components/esp32/test/test_unal_dma.c

@@ -0,0 +1,205 @@
+
+#include <esp_types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "rom/ets_sys.h"
+#include "rom/lldesc.h"
+#include "rom/gpio.h"
+
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "freertos/semphr.h"
+#include "freertos/queue.h"
+#include "freertos/xtensa_api.h"
+#include "unity.h"
+
+#include "soc/uart_reg.h"
+#include "soc/dport_reg.h"
+#include "soc/io_mux_reg.h"
+#include "soc/gpio_sig_map.h"
+#include "soc/gpio_reg.h"
+#include "soc/i2s_reg.h"
+
+
+#define DPORT_I2S0_CLK_EN   (BIT(4))
+#define DPORT_I2S0_RST   (BIT(4))
+
+static volatile lldesc_t dmaDesc[2];
+
+
+//hacked up routine to essentially do a memcpy() using dma. Supports max 4K-1 bytes.
+static void dmaMemcpy(void *in, void *out, int len)
+{
+    volatile int i;
+    SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S0_CLK_EN);
+    CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S0_RST);
+
+    //Init pins to i2s functions
+    SET_PERI_REG_MASK(GPIO_ENABLE_W1TS_REG, (1 << 11) | (1 << 3) | (1 << 0) | (1 << 2) | (1 << 5) | (1 << 16) | (1 << 17) | (1 << 18) | (1 << 19) | (1 << 20)); //ENABLE GPIO oe_enable
+
+    PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, 0);
+    PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, 0);
+    PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO5_U, 0);
+    PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO16_U, 0);
+    PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO17_U, 0);
+    PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO18_U, 0);
+    PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO19_U, 0);
+    PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO20_U, 0);
+    PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CMD_U, 2); //11
+    PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO26_U, 0); //RS
+
+    WRITE_PERI_REG(GPIO_FUNC0_OUT_SEL_CFG_REG, (148 << GPIO_FUNC0_OUT_SEL_S));
+    WRITE_PERI_REG(GPIO_FUNC2_OUT_SEL_CFG_REG, (149 << GPIO_FUNC0_OUT_SEL_S));
+    WRITE_PERI_REG(GPIO_FUNC5_OUT_SEL_CFG_REG, (150 << GPIO_FUNC0_OUT_SEL_S));
+    WRITE_PERI_REG(GPIO_FUNC16_OUT_SEL_CFG_REG, (151 << GPIO_FUNC0_OUT_SEL_S));
+    WRITE_PERI_REG(GPIO_FUNC17_OUT_SEL_CFG_REG, (152 << GPIO_FUNC0_OUT_SEL_S));
+    WRITE_PERI_REG(GPIO_FUNC18_OUT_SEL_CFG_REG, (153 << GPIO_FUNC0_OUT_SEL_S));
+    WRITE_PERI_REG(GPIO_FUNC19_OUT_SEL_CFG_REG, (154 << GPIO_FUNC0_OUT_SEL_S));
+    WRITE_PERI_REG(GPIO_FUNC20_OUT_SEL_CFG_REG, (155 << GPIO_FUNC0_OUT_SEL_S));
+    WRITE_PERI_REG(GPIO_FUNC26_OUT_SEL_CFG_REG, (156 << GPIO_FUNC0_OUT_SEL_S)); //RS
+    WRITE_PERI_REG(GPIO_FUNC11_OUT_SEL_CFG_REG, (I2S0O_WS_OUT_IDX << GPIO_FUNC0_OUT_SEL_S));
+//  WRITE_PERI_REG(GPIO_FUNC11_OUT_SEL_CFG, (I2S0O_BCK_OUT_IDX<<GPIO_GPIO_FUNC0_OUT_SEL_S));
+
+    //GPIO_SET_GPIO_FUNC11_OUT_INV_SEL(1); //old
+    WRITE_PERI_REG(GPIO_FUNC11_OUT_SEL_CFG_REG, READ_PERI_REG(GPIO_FUNC11_OUT_SEL_CFG_REG) | GPIO_FUNC11_OUT_INV_SEL);
+
+    //Reset I2S subsystem
+    CLEAR_PERI_REG_MASK(I2S_CONF_REG(0), I2S_RX_RESET | I2S_TX_RESET);
+    SET_PERI_REG_MASK(I2S_CONF_REG(0), I2S_RX_RESET | I2S_TX_RESET);
+    CLEAR_PERI_REG_MASK(I2S_CONF_REG(0), I2S_RX_RESET | I2S_TX_RESET);
+
+    WRITE_PERI_REG(I2S_CONF_REG(0), 0);//I2S_I2S_SIG_LOOPBACK);
+    WRITE_PERI_REG(I2S_CONF2_REG(0), 0);
+
+    WRITE_PERI_REG(I2S_SAMPLE_RATE_CONF_REG(0),
+                   (16 << I2S_RX_BITS_MOD_S) |
+                   (16 << I2S_TX_BITS_MOD_S) |
+                   (1 << I2S_RX_BCK_DIV_NUM_S) |
+                   (1 << I2S_TX_BCK_DIV_NUM_S));
+    WRITE_PERI_REG(I2S_CLKM_CONF_REG(0),
+                   I2S_CLKA_ENA | I2S_CLK_EN |
+                   (1 << I2S_CLKM_DIV_A_S) |
+                   (1 << I2S_CLKM_DIV_B_S) |
+                   (1 << I2S_CLKM_DIV_NUM_S));
+    WRITE_PERI_REG(I2S_FIFO_CONF_REG(0),
+                   (32 << I2S_TX_DATA_NUM_S) |     //Low watermark for IRQ
+                   (32 << I2S_RX_DATA_NUM_S));
+
+    WRITE_PERI_REG(I2S_CONF1_REG(0), I2S_RX_PCM_BYPASS | I2S_TX_PCM_BYPASS);
+
+    WRITE_PERI_REG(I2S_CONF_CHAN_REG(0), (2 << I2S_TX_CHAN_MOD_S) | (2 << I2S_RX_CHAN_MOD_S));
+
+    //Invert WS to active-low
+    SET_PERI_REG_MASK(I2S_CONF_REG(0), I2S_TX_RIGHT_FIRST | I2S_RX_RIGHT_FIRST);
+    WRITE_PERI_REG(I2S_TIMING_REG(0), 0);
+
+//--
+    //Fill DMA descriptor
+    dmaDesc[0].length = len;
+    dmaDesc[0].size = len;
+    dmaDesc[0].owner = 1;
+    dmaDesc[0].sosf = 0;
+    dmaDesc[0].buf = (uint8_t *)in;
+    dmaDesc[0].offset = 0; //unused in hw
+    dmaDesc[0].empty = 0;
+    dmaDesc[0].eof = 1;
+    dmaDesc[1].length = len;
+    dmaDesc[1].size = len;
+    dmaDesc[1].owner = 1;
+    dmaDesc[1].sosf = 0;
+    dmaDesc[1].buf = (uint8_t *)out;
+    dmaDesc[1].offset = 0; //unused in hw
+    dmaDesc[1].empty = 0;
+    dmaDesc[1].eof = 1;
+
+    //Reset DMA
+    SET_PERI_REG_MASK(I2S_LC_CONF_REG(0), I2S_IN_RST | I2S_OUT_RST | I2S_AHBM_RST | I2S_AHBM_FIFO_RST);
+    CLEAR_PERI_REG_MASK(I2S_LC_CONF_REG(0), I2S_IN_RST | I2S_OUT_RST | I2S_AHBM_RST | I2S_AHBM_FIFO_RST);
+
+    //Reset I2S FIFO
+    SET_PERI_REG_MASK(I2S_CONF_REG(0), I2S_RX_RESET | I2S_TX_RESET | I2S_TX_FIFO_RESET | I2S_RX_FIFO_RESET);
+    CLEAR_PERI_REG_MASK(I2S_CONF_REG(0), I2S_RX_RESET | I2S_TX_RESET | I2S_TX_FIFO_RESET | I2S_RX_FIFO_RESET);
+
+    //Set desc addr
+    CLEAR_PERI_REG_MASK(I2S_OUT_LINK_REG(0), I2S_OUTLINK_ADDR);
+    SET_PERI_REG_MASK(I2S_OUT_LINK_REG(0), ((uint32_t)(&dmaDesc[0]))&I2S_OUTLINK_ADDR);
+    CLEAR_PERI_REG_MASK(I2S_IN_LINK_REG(0), I2S_INLINK_ADDR);
+    SET_PERI_REG_MASK(I2S_IN_LINK_REG(0), ((uint32_t)(&dmaDesc[1]))&I2S_INLINK_ADDR);
+
+    SET_PERI_REG_MASK(I2S_FIFO_CONF_REG(0), I2S_DSCR_EN); //Enable DMA mode
+
+    WRITE_PERI_REG(I2S_RXEOF_NUM_REG(0), len);
+
+    //Enable and configure DMA
+    WRITE_PERI_REG(I2S_LC_CONF_REG(0), I2S_OUT_DATA_BURST_EN  |
+                   I2S_OUT_EOF_MODE | I2S_OUTDSCR_BURST_EN | I2S_OUT_DATA_BURST_EN |
+                   I2S_INDSCR_BURST_EN | I2S_MEM_TRANS_EN);
+
+    //Start transmission
+    SET_PERI_REG_MASK(I2S_OUT_LINK_REG(0), I2S_OUTLINK_START);
+    SET_PERI_REG_MASK(I2S_IN_LINK_REG(0), I2S_INLINK_START);
+
+    SET_PERI_REG_MASK(I2S_CONF_REG(0), I2S_TX_START | I2S_RX_START);
+    //Clear int flags
+    WRITE_PERI_REG(I2S_INT_CLR_REG(0), 0xFFFFFFFF);
+//--
+    //No need to finish if no DMA transfer going on
+    if (!(READ_PERI_REG(I2S_FIFO_CONF_REG(0))&I2S_DSCR_EN)) {
+        return;
+    }
+
+    //Wait till fifo done
+    while (!(READ_PERI_REG(I2S_INT_RAW_REG(0))&I2S_TX_REMPTY_INT_RAW)) ;
+    //Wait for last bytes to leave i2s xmit thing
+    //ToDo: poll bit in next hw
+    for (i = 0; i < (1 << 8); i++);
+    while (!(READ_PERI_REG(I2S_STATE_REG(0))&I2S_TX_IDLE));
+
+    //Reset I2S for next transfer
+    CLEAR_PERI_REG_MASK(I2S_CONF_REG(0), I2S_TX_START | I2S_RX_START);
+    CLEAR_PERI_REG_MASK(I2S_OUT_LINK_REG(0), I2S_OUTLINK_START | I2S_INLINK_START);
+
+    SET_PERI_REG_MASK(I2S_CONF_REG(0), I2S_TX_RESET | I2S_TX_FIFO_RESET | I2S_RX_RESET | I2S_RX_FIFO_RESET);
+    CLEAR_PERI_REG_MASK(I2S_CONF_REG(0), I2S_TX_RESET | I2S_TX_FIFO_RESET | I2S_RX_RESET | I2S_RX_FIFO_RESET);
+
+//  for (i=0; i<(1<<8); i++);
+    while ((READ_PERI_REG(I2S_STATE_REG(0))&I2S_TX_FIFO_RESET_BACK));
+
+}
+
+
+int mymemcmp(char *a, char *b, int len)
+{
+    int x;
+    for (x = 0; x < len; x++) {
+        if (a[x] != b[x]) {
+            printf("Not equal at byte %d. a=%x, b=%x\n", x, (int)a[x], (int)b[x]);
+            return 1;
+        }
+    }
+    return 0;
+}
+
+
+
+TEST_CASE("Unaligned DMA test (needs I2S)", "[hw]")
+{
+    int x;
+    char src[2049], dest[2049];
+    for (x = 0; x < sizeof(src); x++) {
+        src[x] = x & 0xff;
+    }
+
+    printf("Aligned dma\n");
+    memset(dest, 0, 2049);
+    dmaMemcpy(src, dest, 2048 + 1);
+    TEST_ASSERT(mymemcmp(src, dest, 2048) == 0);
+    printf("Src unaligned\n");
+    dmaMemcpy(src + 1, dest, 2048 + 1);
+    TEST_ASSERT(mymemcmp(src + 1, dest, 2048) == 0);
+    printf("Dst unaligned\n");
+    dmaMemcpy(src, dest + 1, 2048 + 2);
+    TEST_ASSERT(mymemcmp(src, dest + 1, 2048) == 0);
+}
+

+ 6 - 6
components/freertos/include/freertos/FreeRTOS.h

@@ -895,7 +895,8 @@ typedef struct xSTATIC_TCB
 		uint32_t 		ulDummy18;
 		uint32_t 		ucDummy19;
 	#endif
-	#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
+	#if( ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) \
+		 || ( portUSING_MPU_WRAPPERS == 1 ) )
 		uint8_t			uxDummy20;
 	#endif
 
@@ -927,7 +928,6 @@ typedef struct xSTATIC_QUEUE
 
 	StaticList_t xDummy3[ 2 ];
 	UBaseType_t uxDummy4[ 3 ];
-	BaseType_t ucDummy5[ 2 ];
 
 	#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
 		uint8_t ucDummy6;
@@ -943,12 +943,12 @@ typedef struct xSTATIC_QUEUE
 	#endif
 
     struct {
-	    volatile uint32_t mux;
+	    volatile uint32_t ucDummy10;
     #ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
-	    const char *lastLockedFn;
-	    int lastLockedLine;
+	    void *pvDummy8;
+	    UBaseType_t uxDummy11;
     #endif
-    } mux;
+    } sDummy12;
 
 } StaticQueue_t;
 typedef StaticQueue_t StaticSemaphore_t;

+ 1 - 2
components/freertos/include/freertos/FreeRTOSConfig.h

@@ -108,6 +108,7 @@
 
 /* configASSERT behaviour */
 #ifndef __ASSEMBLER__
+#include <stdlib.h> /* for abort() */
 #include "rom/ets_sys.h"
 
 #if defined(CONFIG_FREERTOS_ASSERT_DISABLE)
@@ -126,8 +127,6 @@
 #endif
 
 #if CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION
-#include <stdlib.h>
-#include "rom/ets_sys.h"
 #define UNTESTED_FUNCTION() { ets_printf("Untested FreeRTOS function %s\r\n", __FUNCTION__); configASSERT(false); } while(0)
 #else
 #define UNTESTED_FUNCTION()

+ 13 - 0
components/freertos/include/freertos/list.h

@@ -190,6 +190,10 @@ struct xLIST_ITEM
 };
 typedef struct xLIST_ITEM ListItem_t;					/* For some reason lint wants this as two separate definitions. */
 
+#if __GNUC_PREREQ(4, 6)
+_Static_assert(sizeof(StaticListItem_t) == sizeof(ListItem_t), "StaticListItem_t != ListItem_t");
+#endif
+
 struct xMINI_LIST_ITEM
 {
 	listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE				/*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
@@ -199,6 +203,11 @@ struct xMINI_LIST_ITEM
 };
 typedef struct xMINI_LIST_ITEM MiniListItem_t;
 
+#if __GNUC_PREREQ(4, 6)
+_Static_assert(sizeof(StaticMiniListItem_t) == sizeof(MiniListItem_t), "StaticMiniListItem_t != MiniListItem_t");
+#endif
+
+
 /*
  * Definition of the type of queue used by the scheduler.
  */
@@ -211,6 +220,10 @@ typedef struct xLIST
 	listSECOND_LIST_INTEGRITY_CHECK_VALUE				/*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
 } List_t;
 
+#if __GNUC_PREREQ(4, 6)
+_Static_assert(sizeof(StaticList_t) == sizeof(List_t), "StaticList_t != List_t");
+#endif
+
 /*
  * Access macro to set the owner of a list item.  The owner of a list item
  * is the object (usually a TCB) that contains the list item.

+ 5 - 0
components/freertos/queue.c

@@ -179,6 +179,11 @@ typedef struct QueueDefinition
 name below to enable the use of older kernel aware debuggers. */
 typedef xQUEUE Queue_t;
 
+#if __GNUC_PREREQ(4, 6)
+_Static_assert(sizeof(StaticQueue_t) == sizeof(Queue_t), "StaticQueue_t != Queue_t");
+#endif
+
+
 /*-----------------------------------------------------------*/
 
 /*

+ 4 - 0
components/freertos/tasks.c

@@ -242,6 +242,10 @@ typedef struct tskTaskControlBlock
 below to enable the use of older kernel aware debuggers. */
 typedef tskTCB TCB_t;
 
+#if __GNUC_PREREQ(4, 6)
+_Static_assert(sizeof(StaticTask_t) == sizeof(TCB_t), "StaticTask_t != TCB_t");
+#endif
+
 /*
  * Some kernel aware debuggers require the data the debugger needs access to to
  * be global, rather than file scope.

+ 5 - 0
components/freertos/test/component.mk

@@ -0,0 +1,5 @@
+#
+#Component Makefile
+#
+
+COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive

+ 229 - 0
components/freertos/test/test_freertos.c

@@ -0,0 +1,229 @@
+/*
+ Test for multicore FreeRTOS. This test spins up threads, fiddles with queues etc.
+*/
+
+#include <esp_types.h>
+#include <stdio.h>
+#include "rom/ets_sys.h"
+
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "freertos/semphr.h"
+#include "freertos/queue.h"
+#include "freertos/xtensa_api.h"
+#include "unity.h"
+#include "soc/uart_reg.h"
+#include "soc/dport_reg.h"
+#include "soc/io_mux_reg.h"
+
+
+void ets_isr_unmask(uint32_t unmask);
+
+static xQueueHandle myQueue;
+static xQueueHandle uartRxQueue;
+
+int ctr;
+
+#if 1
+//Idle-loop for delay. Tests involuntary yielding
+static void cvTaskDelay(int dummy)
+{
+    volatile int i;
+    for (i = 0; i < (1 << 17); i++);
+}
+#else
+//Delay task execution using FreeRTOS methods. Tests voluntary yielding.
+#define cvTaskDelay(x) vTaskDelay(x)
+#endif
+
+#if 0
+static void dosegfault3(int i)
+{
+    volatile char *p = (volatile char *)0;
+    *p = i;
+}
+
+static void dosegfault2(int i)
+{
+    if (i > 3) {
+        dosegfault3(i);
+    }
+}
+
+static void dosegfault(int i)
+{
+    if (i < 5) {
+        dosegfault(i + 1);
+    }
+    dosegfault2(i);
+}
+#endif
+
+static void queueSender(void *pvParameters)
+{
+    int myCtr = xPortGetCoreID() * 100000;
+    while (1) {
+        printf("Core %d: Send to queue: %d\n", xPortGetCoreID(), myCtr);
+        xQueueSend(myQueue, (void *)(&myCtr), portMAX_DELAY);
+        printf("Send to queue done.\n");
+        cvTaskDelay(100);
+        myCtr++;
+    }
+}
+
+static void queueReceiver(void *pvParameters)
+{
+    int theCtr;
+    while (1) {
+        xQueueReceive(myQueue, &theCtr, portMAX_DELAY);
+        printf("Core %d: Receive from queue: %d\n", xPortGetCoreID(), theCtr);
+    }
+}
+
+
+static void tskone(void *pvParameters)
+{
+//  char *p=(char *)0;
+    while (1) {
+        ctr++;
+//      if (ctr>60) dosegfault(3);
+        printf("Task1, core %d, ctr=%d\n", xPortGetCoreID(), ctr);
+        cvTaskDelay(500);
+    }
+}
+
+static void tsktwo(void *pvParameters)
+{
+    while (1) {
+        ctr++;
+        printf("Task2, core %d, ctr=%d\n", xPortGetCoreID(), ctr);
+        cvTaskDelay(500);
+    }
+}
+
+static void tskthree(void *pvParameters)
+{
+    while (1) {
+        ctr++;
+        printf("Task3, core %d, ctr=%d\n", xPortGetCoreID(), ctr);
+        cvTaskDelay(500);
+    }
+}
+
+static void tskfour(void *pvParameters)
+{
+    while (1) {
+        ctr++;
+        printf("Task4, core %d, ctr=%d\n", xPortGetCoreID(), ctr);
+        cvTaskDelay(500);
+    }
+}
+
+static void tskfive(void *pvParameters)
+{
+    while (1) {
+        ctr++;
+        printf("Task5, core %d, ctr=%d\n", xPortGetCoreID(), ctr);
+        cvTaskDelay(500);
+    }
+}
+
+static void tskyield(void *pvParameters)
+{
+    while (1) {
+        portYIELD();
+    }
+}
+
+static void  tskUartRecv(void *pvParameters)
+{
+    char c;
+    while (1) {
+        xQueueReceive(uartRxQueue, &c, portMAX_DELAY);
+        printf("Uart received %c!\n", c);
+    }
+}
+
+
+static void uartIsrHdl(void *arg)
+{
+    char c;
+    BaseType_t xHigherPriorityTaskWoken;
+    SET_PERI_REG_MASK(UART_INT_CLR_REG(0), UART_RXFIFO_FULL_INT_CLR);
+    while (READ_PERI_REG(UART_STATUS_REG(0)) & (UART_RXFIFO_CNT << UART_RXFIFO_CNT_S)) {
+        c = READ_PERI_REG(UART_FIFO_REG(0));
+        xQueueSendFromISR(uartRxQueue, &c, &xHigherPriorityTaskWoken);
+        printf("ISR: %c\n", c);
+    }
+    if (xHigherPriorityTaskWoken) {
+        portYIELD_FROM_ISR();
+    }
+}
+
+static void uartRxInit(xQueueHandle q)
+{
+    uint32_t reg_val;
+
+    PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U);
+    PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD_U0RXD);
+    PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD_U0TXD);
+
+
+    PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD_U0RXD);
+
+//  reg_val = READ_PERI_REG(UART_CONF1(0));
+    reg_val = (1 << UART_RXFIFO_FULL_THRHD_S);
+    WRITE_PERI_REG(UART_CONF1_REG(0), reg_val);
+    CLEAR_PERI_REG_MASK(UART_INT_ENA_REG(0), UART_TXFIFO_EMPTY_INT_ENA | UART_RXFIFO_TOUT_INT_ENA);
+    SET_PERI_REG_MASK(UART_INT_ENA_REG(0), UART_RXFIFO_FULL_INT_ENA);
+
+    printf("Enabling int %d\n", ETS_UART0_INUM);
+    REG_SET_FIELD(DPORT_PRO_UART_INTR_MAP_REG, DPORT_PRO_UART_INTR_MAP, ETS_UART0_INUM);
+    REG_SET_FIELD(DPORT_PRO_UART1_INTR_MAP_REG, DPORT_PRO_UART1_INTR_MAP, ETS_UART0_INUM);
+
+    xt_set_interrupt_handler(ETS_UART0_INUM, uartIsrHdl, NULL);
+    xt_ints_on(1 << ETS_UART0_INUM);
+
+}
+
+// TODO: split this thing into separate orthogonal tests
+TEST_CASE("Bunch of FreeRTOS tests", "[freertos]")
+{
+    char *tst;
+    TaskHandle_t th[12];
+    int i;
+    printf("%s\n", __FUNCTION__);
+    tst = pvPortMalloc(16);
+    printf("Test malloc returns addr %p\n", tst);
+    printf("Free heap: %u\n", xPortGetFreeHeapSize());
+    myQueue = xQueueCreate(10, sizeof(int));
+    uartRxQueue = xQueueCreate(256, sizeof(char));
+    printf("Free heap: %u\n", xPortGetFreeHeapSize());
+
+    printf("Creating tasks\n");
+    xTaskCreatePinnedToCore(tskyield  , "tskyield1"  , 2048, NULL, 3, &th[0], 0);
+    xTaskCreatePinnedToCore(tskyield  , "tskyield2"  , 2048, NULL, 3, &th[1], 1);
+
+    xTaskCreatePinnedToCore(tskone  , "tskone"  , 2048, NULL, 3, &th[2], 0);
+    xTaskCreatePinnedToCore(tsktwo  , "tsktwo"  , 2048, NULL, 3, &th[3], 1);
+    xTaskCreatePinnedToCore(tskthree, "tskthree", 2048, NULL, 3, &th[4], 0);
+    xTaskCreatePinnedToCore(tskfour , "tskfour" , 2048, NULL, 3, &th[5], tskNO_AFFINITY);
+    xTaskCreatePinnedToCore(tskfive , "tskfive" , 2048, NULL, 3, &th[6], tskNO_AFFINITY);
+    xTaskCreatePinnedToCore(queueSender , "qsend1" , 2048, NULL, 3, &th[7], 0);
+    xTaskCreatePinnedToCore(queueSender , "qsend2" , 2048, NULL, 3, &th[8], 1);
+    xTaskCreatePinnedToCore(queueReceiver , "qrecv1" , 2048, NULL, 3, &th[9], 1);
+    xTaskCreatePinnedToCore(queueReceiver , "qrecv2" , 2048, NULL, 3, &th[10], 0);
+    xTaskCreatePinnedToCore(tskUartRecv , "tskuart" , 2048, NULL, 4, &th[11], 1);
+    printf("Free heap: %u\n", xPortGetFreeHeapSize());
+    uartRxInit(uartRxQueue);
+
+    // Let stuff run for 20s
+    vTaskDelay(20000 / portTICK_PERIOD_MS);
+
+    //Shut down all the tasks
+    for (i = 0; i < 12; i++) {
+        vTaskDelete(th[i]);
+    }
+    xt_ints_off(1 << ETS_UART0_INUM);
+}
+

+ 105 - 0
components/freertos/test/test_freertos_eventgroups.c

@@ -0,0 +1,105 @@
+#include <stdio.h>
+
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "freertos/semphr.h"
+#include "freertos/queue.h"
+#include "freertos/event_groups.h"
+#include "unity.h"
+
+#define BIT_CALL (1 << 0)
+#define BIT_RESPONSE(TASK) (1 << (TASK+1))
+#define ALL_RESPONSE_BITS (((1 << NUM_TASKS) - 1) << 1)
+
+static const int NUM_TASKS = 4;
+static const int COUNT = 4000;
+static EventGroupHandle_t eg;
+
+static void task_event_group_call_response(void *param)
+{
+    int task_num = (int)param;
+
+    printf("Started %d\n", task_num);
+
+    for (int i = 0; i < COUNT; i++) {
+        /* Wait until the common "call" bit is set, starts off all tasks
+           (clear on return) */
+        while (!xEventGroupWaitBits(eg, BIT_CALL, true, false, portMAX_DELAY)) {
+        }
+
+        /* Set our individual "response" bit */
+        xEventGroupSetBits(eg, BIT_RESPONSE(task_num));
+    }
+
+    printf("Task %d done\n", task_num);
+
+    /* Delay is due to not-yet-fixed bug with deleting tasks at same time */
+    vTaskDelay(100 / portTICK_RATE_MS);
+    vTaskDelete(NULL);
+}
+
+TEST_CASE("FreeRTOS Event Groups", "[freertos]")
+{
+    eg = xEventGroupCreate();
+
+    /* Note: task_event_group_call_response all have higher priority than us, so will block together.
+
+       This is important because we need to know they'll all have blocked on BIT_CALL each time we
+       signal it, or they get out of sync.
+     */
+    for (int c = 0; c < NUM_TASKS; c++) {
+        xTaskCreatePinnedToCore(task_event_group_call_response, "tsk_call_resp", 4096, (void *)c, configMAX_PRIORITIES - 1, NULL, c % portNUM_PROCESSORS);
+    }
+    /* Scheduler weirdness, if we don't sleep a few ticks here then the tasks on the other CPU aren't running yet... */
+    vTaskDelay(10);
+
+    for (int i = 0; i < COUNT; i++) {
+        if (i % 100 == 0) {
+            //printf("Call %d\n", i);
+        }
+        /* signal all tasks with "CALL" bit... */
+        xEventGroupSetBits(eg, BIT_CALL);
+
+        while (xEventGroupWaitBits(eg, ALL_RESPONSE_BITS, true, true, portMAX_DELAY) != ALL_RESPONSE_BITS) {
+        }
+    }
+}
+
+
+#define BIT_DONE(X) (1<<(NUM_TASKS+1+X))
+
+static void task_test_sync(void *param)
+{
+    int task_num = (int)param;
+
+    printf("Started %d\n", task_num);
+
+    for (int i = 0; i < COUNT; i++) {
+        /* set our bit, and wait on all tasks to set their bits */
+        xEventGroupSync(eg, BIT_RESPONSE(task_num), ALL_RESPONSE_BITS, portMAX_DELAY);
+        /* clear our bit */
+        xEventGroupClearBits(eg, BIT_RESPONSE(task_num));
+    }
+    int after_done = xEventGroupSetBits(eg, BIT_DONE(task_num));
+
+    printf("Done %d = %x\n", task_num, after_done);
+
+    /* Delay is due to not-yet-fixed bug with deleting tasks at same time */
+    vTaskDelay(100 / portTICK_RATE_MS);
+    vTaskDelete(NULL);
+}
+
+TEST_CASE("FreeRTOS Event Group Sync", "[freertos]")
+{
+    eg = xEventGroupCreate();
+
+    for (int c = 0; c < NUM_TASKS; c++) {
+        xTaskCreatePinnedToCore(task_test_sync, "task_test_sync", 4096, (void *)c, configMAX_PRIORITIES - 1, NULL, c % portNUM_PROCESSORS);
+    }
+
+    for (int c = 0; c < NUM_TASKS; c++) {
+        printf("Waiting on %d (%x)\n", c, BIT_DONE(c));
+        xEventGroupWaitBits(eg, BIT_DONE(c), false, false, portMAX_DELAY);
+    }
+}
+

+ 22 - 0
components/freertos/test/test_freertos_task_delete.c

@@ -0,0 +1,22 @@
+#include <stdio.h>
+
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "freertos/semphr.h"
+#include "freertos/queue.h"
+#include "freertos/event_groups.h"
+#include "unity.h"
+
+static void task_delete_self(void *param)
+{
+    printf("Task %p running on core %d. Deleting shortly...\n", xTaskGetCurrentTaskHandle(), xPortGetCoreID());
+    vTaskDelete(NULL);
+}
+
+TEST_CASE("FreeRTOS Delete Tasks", "[freertos]")
+{
+    xTaskCreatePinnedToCore(task_delete_self, "tsk_self_a", 4096, NULL, configMAX_PRIORITIES - 1, NULL, 0);
+    xTaskCreatePinnedToCore(task_delete_self, "tsk_self_a", 4096, NULL, configMAX_PRIORITIES - 1, NULL, 0);
+    vTaskDelay(200 / portTICK_PERIOD_MS);
+    printf("Done?\n");
+}

+ 60 - 0
components/freertos/test/test_newlib_reent.c

@@ -0,0 +1,60 @@
+/*
+ Test for multicore FreeRTOS. This test spins up threads, fiddles with queues etc.
+*/
+
+#include <esp_types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "rom/ets_sys.h"
+
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "freertos/semphr.h"
+#include "freertos/queue.h"
+#include "freertos/xtensa_api.h"
+#include "unity.h"
+#include "soc/uart_reg.h"
+#include "soc/dport_reg.h"
+#include "soc/io_mux_reg.h"
+
+
+volatile static int done;
+volatile static int error;
+
+static void tskTestRand(void *pvParameters)
+{
+    int l;
+    srand(0x1234);
+    vTaskDelay((int)pvParameters / portTICK_PERIOD_MS);
+    l = rand();
+    printf("Rand1: %d\n", l);
+    if (l != 869320854) {
+        error++;
+    }
+    vTaskDelay((int)pvParameters / portTICK_PERIOD_MS);
+    l = rand();
+    printf("Rand2: %d\n", l);
+    if (l != 1148737841) {
+        error++;
+    }
+    done++;
+    vTaskDelete(NULL);
+}
+
+
+
+// TODO: split this thing into separate orthogonal tests
+TEST_CASE("Test for per-task non-reentrant tasks", "[freertos]")
+{
+    done = 0;
+    error = 0;
+    xTaskCreatePinnedToCore(tskTestRand, "tsk1", 2048, (void *)100, 3, NULL, 0);
+    xTaskCreatePinnedToCore(tskTestRand, "tsk2", 2048, (void *)200, 3, NULL, 0);
+    xTaskCreatePinnedToCore(tskTestRand, "tsk3", 2048, (void *)300, 3, NULL, 1);
+    xTaskCreatePinnedToCore(tskTestRand, "tsk4", 2048, (void *)400, 3, NULL, 0);
+    while (done != 4) {
+        vTaskDelay(1000 / portTICK_PERIOD_MS);
+    }
+    TEST_ASSERT(error == 0);
+}
+

+ 26 - 0
components/freertos/test/test_panic.c

@@ -0,0 +1,26 @@
+/*
+ Test for multicore FreeRTOS. This test spins up threads, fiddles with queues etc.
+*/
+
+#include <esp_types.h>
+#include <stdio.h>
+#include "rom/ets_sys.h"
+
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "freertos/semphr.h"
+#include "freertos/queue.h"
+#include "freertos/xtensa_api.h"
+#include "unity.h"
+#include "soc/uart_reg.h"
+#include "soc/dport_reg.h"
+#include "soc/io_mux_reg.h"
+
+
+TEST_CASE("Panic handler", "[freertos]")
+{
+    volatile int *i;
+    i = (volatile int *)0x0;
+    *i = 1;
+}
+

+ 197 - 0
components/freertos/test/test_ringbuf.c

@@ -0,0 +1,197 @@
+/*
+ Test for multicore FreeRTOS ringbuffer.
+*/
+
+#include <esp_types.h>
+#include <stdio.h>
+#include "rom/ets_sys.h"
+
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "freertos/semphr.h"
+#include "freertos/queue.h"
+#include "freertos/ringbuf.h"
+#include "freertos/xtensa_api.h"
+#include "unity.h"
+#include "soc/uart_reg.h"
+#include "soc/dport_reg.h"
+#include "soc/io_mux_reg.h"
+
+#include <string.h>
+#include <stdio.h>
+
+void ets_isr_unmask(uint32_t unmask);
+
+static RingbufHandle_t rb;
+typedef enum {
+    TST_MOSTLYFILLED,
+    TST_MOSTLYEMPTY,
+    TST_INTTOTASK,
+    TST_TASKTOINT,
+} testtype_t;
+
+static volatile testtype_t testtype;
+
+static void task1(void *arg)
+{
+    testtype_t oldtest;
+    char buf[100];
+    int i = 0;
+    int x, r;
+    while (1) {
+        oldtest = testtype;
+        if (testtype == TST_MOSTLYFILLED || testtype == TST_MOSTLYEMPTY) {
+            for (x = 0; x < 10; x++) {
+                sprintf(buf, "This is test %d item %d.", (int)testtype,  i++);
+                ets_printf("TSK w");
+                xRingbufferPrintInfo(rb);
+                r = xRingbufferSend(rb, buf, strlen(buf) + 1, 2000 / portTICK_PERIOD_MS);
+                if (!r) {
+                    printf("Test %d: Timeout on send!\n", (int)testtype);
+                }
+                if (testtype == TST_MOSTLYEMPTY) {
+                    vTaskDelay(1000 / portTICK_PERIOD_MS);
+                }
+            }
+            //Send NULL event to stop other side.
+            r = xRingbufferSend(rb, NULL, 0, 10000 / portTICK_PERIOD_MS);
+        }
+        while (oldtest == testtype) {
+            vTaskDelay(1000 / portTICK_PERIOD_MS);
+        }
+    }
+}
+
+static void task2(void *arg)
+{
+    testtype_t oldtest;
+    char *buf;
+    size_t len;
+    while (1) {
+        oldtest = testtype;
+        if (testtype == TST_MOSTLYFILLED || testtype == TST_MOSTLYEMPTY) {
+            while (1) {
+                ets_printf("TSK r");
+                xRingbufferPrintInfo(rb);
+                buf = xRingbufferReceive(rb, &len, 2000 / portTICK_PERIOD_MS);
+                if (buf == NULL) {
+                    printf("Test %d: Timeout on recv!\n", (int)testtype);
+                } else if (len == 0) {
+                    printf("End packet received.\n");
+                    vRingbufferReturnItem(rb, buf);
+                    break;
+                } else {
+                    printf("Received: %s (%d bytes, %p)\n", buf, len, buf);
+                    vRingbufferReturnItem(rb, buf);
+                }
+                if (testtype == TST_MOSTLYFILLED) {
+                    vTaskDelay(1000 / portTICK_PERIOD_MS);
+                }
+            }
+        }
+        while (oldtest == testtype) {
+            vTaskDelay(1000 / portTICK_PERIOD_MS);
+        }
+    }
+}
+
+
+
+static void uartIsrHdl(void *arg)
+{
+    char c;
+    char buf[50];
+    char *item;
+    int r;
+    size_t len;
+    BaseType_t xHigherPriorityTaskWoken;
+    SET_PERI_REG_MASK(UART_INT_CLR_REG(0), UART_RXFIFO_FULL_INT_CLR);
+    while (READ_PERI_REG(UART_STATUS_REG(0)) & (UART_RXFIFO_CNT << UART_RXFIFO_CNT_S)) {
+        c = READ_PERI_REG(UART_FIFO_REG(0));
+        if (c == 'r') {
+            ets_printf("ISR r");
+            xRingbufferPrintInfo(rb);
+            item = xRingbufferReceiveFromISR(rb, &len);
+            if (item == NULL) {
+                ets_printf("ISR recv fail!\n");
+            } else if (len == 0) {
+                ets_printf("ISR recv NULL!\n");
+                vRingbufferReturnItemFromISR(rb, item, &xHigherPriorityTaskWoken);
+            } else {
+                ets_printf("ISR recv '%s' (%d bytes, %p)\n", buf, len, buf);
+                vRingbufferReturnItemFromISR(rb, item, &xHigherPriorityTaskWoken);
+            }
+        } else {
+            sprintf(buf, "UART: %c", c);
+            ets_printf("ISR w");
+            xRingbufferPrintInfo(rb);
+            r = xRingbufferSendFromISR(rb, buf, strlen(buf) + 1, &xHigherPriorityTaskWoken);
+            if (!r) {
+                ets_printf("ISR send fail\n");
+            }
+        }
+    }
+    if (xHigherPriorityTaskWoken) {
+        portYIELD_FROM_ISR();
+    }
+}
+
+static void uartRxInit()
+{
+    uint32_t reg_val;
+    PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U);
+    PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD_U0RXD);
+    PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD_U0TXD);
+
+//  reg_val = READ_PERI_REG(UART_CONF1(0));
+    reg_val = (1 << UART_RXFIFO_FULL_THRHD_S);
+    WRITE_PERI_REG(UART_CONF1_REG(0), reg_val);
+    CLEAR_PERI_REG_MASK(UART_INT_ENA_REG(0), UART_TXFIFO_EMPTY_INT_ENA | UART_RXFIFO_TOUT_INT_ENA);
+    SET_PERI_REG_MASK(UART_INT_ENA_REG(0), UART_RXFIFO_FULL_INT_ENA);
+
+    printf("Enabling int %d\n", ETS_UART0_INUM);
+    REG_SET_FIELD(DPORT_PRO_UART_INTR_MAP_REG, DPORT_PRO_UART_INTR_MAP, ETS_UART0_INUM);
+    REG_SET_FIELD(DPORT_PRO_UART1_INTR_MAP_REG, DPORT_PRO_UART1_INTR_MAP, ETS_UART0_INUM);
+
+    xt_set_interrupt_handler(ETS_UART0_INUM, uartIsrHdl, NULL);
+    xt_ints_on(1 << ETS_UART0_INUM);
+
+}
+
+static void testRingbuffer(int type)
+{
+    TaskHandle_t th[2];
+    int i;
+    rb = xRingbufferCreate(32 * 3, type);
+
+    testtype = TST_MOSTLYFILLED;
+
+    xTaskCreatePinnedToCore(task1  , "tskone"  , 2048, NULL, 3, &th[0], 0);
+    xTaskCreatePinnedToCore(task2  , "tsktwo"  , 2048, NULL, 3, &th[1], 0);
+    uartRxInit();
+
+    printf("Press 'r' to read an event in isr, any other key to write one.\n");
+    printf("Test: mostlyfilled; putting 10 items in ringbuff ASAP, reading 1 a second\n");
+    vTaskDelay(15000 / portTICK_PERIOD_MS);
+    printf("Test: mostlyempty; putting 10 items in ringbuff @ 1/sec, reading as fast as possible\n");
+    testtype = TST_MOSTLYEMPTY;
+    vTaskDelay(15000 / portTICK_PERIOD_MS);
+
+    //Shut down all the tasks
+    for (i = 0; i < 2; i++) {
+        vTaskDelete(th[i]);
+    }
+    xt_ints_off(1 << ETS_UART0_INUM);
+}
+
+// TODO: split this thing into separate orthogonal tests
+TEST_CASE("FreeRTOS ringbuffer test, no splitting items", "[freertos]")
+{
+    testRingbuffer(0);
+}
+
+TEST_CASE("FreeRTOS ringbuffer test, w/ splitting items", "[freertos]")
+{
+    testRingbuffer(1);
+}
+

+ 58 - 0
components/freertos/test/test_tls_deletecb.c

@@ -0,0 +1,58 @@
+#include <esp_types.h>
+#include <stdio.h>
+#include "rom/ets_sys.h"
+
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "freertos/semphr.h"
+#include "freertos/queue.h"
+#include "freertos/xtensa_api.h"
+#include "unity.h"
+#include "soc/uart_reg.h"
+#include "soc/dport_reg.h"
+#include "soc/io_mux_reg.h"
+
+
+
+static void tskdelcb(int no, void *arg)
+{
+    printf("Delete callback: %d = %p!\n", no,  arg);
+}
+
+
+static void tska(void *pvParameters)
+{
+    vTaskSetThreadLocalStoragePointerAndDelCallback(xTaskGetCurrentTaskHandle(), 0, (void *)0xAAAAAAAA, tskdelcb);
+    while (1) {
+        vTaskDelay(10000000 / portTICK_PERIOD_MS);
+    }
+}
+
+static void tskb(void *pvParameters)
+{
+    vTaskSetThreadLocalStoragePointerAndDelCallback(xTaskGetCurrentTaskHandle(), 0, (void *)0xBBBBBBBB, tskdelcb);
+    vTaskDelay(2000 / portTICK_PERIOD_MS);
+    TaskHandle_t a = (TaskHandle_t)pvParameters;
+    printf("Killing task A\n");
+    vTaskDelete(a);
+    while (1) {
+        vTaskDelay(10000000 / portTICK_PERIOD_MS);
+    }
+}
+
+
+// TODO: split this thing into separate orthogonal tests
+TEST_CASE("Freertos TLS delete cb", "[freertos]")
+{
+    TaskHandle_t a, b;
+
+    xTaskCreatePinnedToCore(tska  , "tska"  , 2048, NULL, 3, &a, 0);
+    xTaskCreatePinnedToCore(tskb  , "tska"  , 2048, a, 3, &b, 0);
+
+    // Let stuff run for 20s
+    vTaskDelay(5000 / portTICK_PERIOD_MS);
+    printf("Killing task B\n");
+    //Shut down b
+    vTaskDelete(b);
+}
+

+ 3 - 4
components/idf_test/unit_test/CIConfigs/UT_Function_SYS_01.yml

@@ -2,7 +2,6 @@ Config: {execute count: 1, execute order: in order}
 DUT: [UT1]
 Filter:
 - Add:
-    ID: [SYS_OS_0102, SYS_MISC_0103, SYS_MISC_0102, SYS_MISC_0105, SYS_MISC_0104,
-      SYS_MISC_0107, SYS_MISC_0106, SYS_MISC_0109, SYS_MISC_0108, SYS_MISC_0112, SYS_MISC_0113,
-      SYS_MISC_0110, SYS_MISC_0111, SYS_MISC_0115, SYS_LIB_0103, SYS_LIB_0102, SYS_LIB_0101,
-      SYS_LIB_0106, SYS_LIB_0105, SYS_LIB_0104]
+    ID: [SYS_OS_0102, SYS_MISC_0102, SYS_MISC_0107, SYS_MISC_0106, SYS_MISC_0109,
+      SYS_MISC_0108, SYS_MISC_0112, SYS_MISC_0113, SYS_MISC_0110, SYS_MISC_0111, SYS_LIB_0103,
+      SYS_LIB_0102, SYS_LIB_0101, SYS_LIB_0106, SYS_LIB_0105, SYS_LIB_0104]

+ 0 - 3
components/log/include/esp_log.h

@@ -18,10 +18,7 @@
 #include <stdint.h>
 #include <stdarg.h>
 #include "sdkconfig.h"
-
-#ifdef BOOTLOADER_BUILD
 #include <rom/ets_sys.h>
-#endif
 
 #ifdef __cplusplus
 extern "C" {

+ 1 - 0
components/mbedtls/port/esp_bignum.c

@@ -25,6 +25,7 @@
 #include <malloc.h>
 #include <limits.h>
 #include <assert.h>
+#include <stdlib.h>
 #include "mbedtls/bignum.h"
 #include "rom/bigint.h"
 #include "soc/hwcrypto_reg.h"

+ 5 - 0
components/mbedtls/test/component.mk

@@ -0,0 +1,5 @@
+#
+#Component Makefile
+#
+
+COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive

+ 134 - 0
components/mbedtls/test/test_mbedtls.c

@@ -0,0 +1,134 @@
+/* mbedTLS internal tests wrapped into Unity
+
+   Focus on testing functionality where we use ESP32 hardware
+   accelerated crypto features.
+
+   See also test_hwcrypto.c
+*/
+#include <string.h>
+#include <stdio.h>
+#include "mbedtls/sha1.h"
+#include "mbedtls/sha256.h"
+#include "mbedtls/sha512.h"
+#include "mbedtls/aes.h"
+#include "mbedtls/bignum.h"
+#include "unity.h"
+
+static int mbedtls_alt_sha256_self_test( int verbose );
+
+TEST_CASE("mbedtls SHA self-tests", "[mbedtls]")
+{
+    TEST_ASSERT_FALSE_MESSAGE(mbedtls_sha1_self_test(1), "SHA1 self-tests should pass.");
+    TEST_ASSERT_FALSE_MESSAGE(mbedtls_alt_sha256_self_test(1), "SHA256 self-tests should pass.");
+    TEST_ASSERT_FALSE_MESSAGE(mbedtls_sha512_self_test(1), "SHA512 self-tests should pass.");
+}
+
+TEST_CASE("mbedtls AES self-tests", "[aes]")
+{
+    TEST_ASSERT_FALSE_MESSAGE(mbedtls_aes_self_test(1), "AES self-tests should pass.");
+}
+
+TEST_CASE("mbedtls MPI self-tests", "[bignum]")
+{
+    TEST_ASSERT_FALSE_MESSAGE(mbedtls_mpi_self_test(1), "MPI self-tests should pass.");
+}
+
+
+/* Following code is a copy of the mbedtls_sha256 test vectors,
+   with the SHA-224 support removed as we don't currently support this hash.
+*/
+
+/*
+ * FIPS-180-2 test vectors
+ */
+static const unsigned char sha256_test_buf[3][57] = {
+    { "abc" },
+    { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" },
+    { "" }
+};
+
+static const int sha256_test_buflen[3] = {
+    3, 56, 1000
+};
+
+static const unsigned char sha256_test_sum[6][32] = {
+    /*
+     * SHA-256 test vectors
+     */
+    {
+        0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA,
+        0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23,
+        0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C,
+        0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD
+    },
+    {
+        0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8,
+        0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E, 0x60, 0x39,
+        0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67,
+        0xF6, 0xEC, 0xED, 0xD4, 0x19, 0xDB, 0x06, 0xC1
+    },
+    {
+        0xCD, 0xC7, 0x6E, 0x5C, 0x99, 0x14, 0xFB, 0x92,
+        0x81, 0xA1, 0xC7, 0xE2, 0x84, 0xD7, 0x3E, 0x67,
+        0xF1, 0x80, 0x9A, 0x48, 0xA4, 0x97, 0x20, 0x0E,
+        0x04, 0x6D, 0x39, 0xCC, 0xC7, 0x11, 0x2C, 0xD0
+    }
+};
+
+/*
+ * Checkup routine
+ */
+static int mbedtls_alt_sha256_self_test( int verbose )
+{
+    int j, n, buflen, ret = 0;
+    unsigned char buf[1024];
+    unsigned char sha256sum[32];
+    mbedtls_sha256_context ctx;
+
+    for ( j = 0; j < 3; j++ ) {
+        mbedtls_sha256_init( &ctx );
+
+        if ( verbose != 0 ) {
+            printf( "  SHA-%d test #%d: ", 256, j + 1 );
+        }
+
+        mbedtls_sha256_starts( &ctx, 0 );
+
+        if ( j == 2 ) {
+            memset( buf, 'a', buflen = 1000 );
+
+            for ( n = 0; n < 1000; n++ ) {
+                mbedtls_sha256_update( &ctx, buf, buflen );
+            }
+        } else
+            mbedtls_sha256_update( &ctx, sha256_test_buf[j],
+                                   sha256_test_buflen[j] );
+
+        mbedtls_sha256_finish( &ctx, sha256sum );
+
+        if ( memcmp( sha256sum, sha256_test_sum[j], 32 ) != 0 ) {
+            if ( verbose != 0 ) {
+                printf( "failed\n" );
+            }
+
+            mbedtls_sha256_free( &ctx );
+
+            ret = 1;
+            goto exit;
+        }
+
+        if ( verbose != 0 ) {
+            printf( "passed\n" );
+        }
+
+        mbedtls_sha256_free( &ctx );
+    }
+
+    if ( verbose != 0 ) {
+        printf( "\n" );
+    }
+
+exit:
+
+    return ( ret );
+}

+ 5 - 0
components/newlib/test/component.mk

@@ -0,0 +1,5 @@
+#
+#Component Makefile
+#
+
+COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive

+ 102 - 0
components/newlib/test/test_newlib.c

@@ -0,0 +1,102 @@
+#include <stdio.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <time.h>
+#include "unity.h"
+
+
+TEST_CASE("test ctype functions", "[newlib]")
+{
+    TEST_ASSERT_TRUE( isalnum('a') && isalnum('A') && isalnum('z') && isalnum('Z') && isalnum('0') && isalnum('9') );
+    TEST_ASSERT_FALSE( isalnum('(') || isalnum('-') || isalnum(' ') || isalnum('\x81') || isalnum('.') || isalnum('\\') );
+    TEST_ASSERT_TRUE( isalpha('a') && isalpha('A') && isalpha('z') && isalpha('Z') );
+    TEST_ASSERT_FALSE( isalpha('0') || isalpha('9') || isalpha(')') || isalpha('\t') || isalpha(' ') || isalpha('\x81') );
+    TEST_ASSERT_TRUE( isspace(' ') && isspace('\t') && isspace('\n') && isspace('\r') );
+    TEST_ASSERT_FALSE( isspace('0') || isspace('9') || isspace(')') || isspace('A') || isspace('*') || isspace('\x81') || isspace('a'));
+}
+
+TEST_CASE("test atoX functions", "[newlib]")
+{
+    TEST_ASSERT_EQUAL_INT(-2147483648, atoi("-2147483648"));
+    TEST_ASSERT_EQUAL_INT(2147483647, atoi("2147483647"));
+    TEST_ASSERT_EQUAL_INT(42, atoi("000000042"));
+    TEST_ASSERT_EQUAL_INT(0, strtol("foo", NULL, 10));
+}
+
+TEST_CASE("test sprintf function", "[newlib]")
+{
+    char *res = NULL;
+    asprintf(&res, "%d %011i %lu %p %x %c %.4f\n", 42, 2147483647, 2147483648UL, (void *) 0x40010000, 0x40020000, 'Q', 1.0f / 137.0f);
+    TEST_ASSERT_NOT_NULL(res);
+    TEST_ASSERT_EQUAL_STRING(res, "42 02147483647 2147483648 0x40010000 40020000 Q 0.0073\n");
+    free(res);
+}
+
+TEST_CASE("test sscanf function", "[newlib]")
+{
+    const char *src = "42 02147483647 2147483648 0x40010000 40020000 Q 0.0073\n";
+    int fourty_two;
+    int int_max;
+    unsigned long int_max_plus_one;
+    void *iram_ptr;
+    int irom_ptr;
+    char department;
+    float inv_fine_structure_constant;
+    int res = sscanf(src, "%d %d %lu %p %x %c %f", &fourty_two, &int_max, &int_max_plus_one, &iram_ptr, &irom_ptr, &department, &inv_fine_structure_constant);
+    TEST_ASSERT_EQUAL(7, res);
+    TEST_ASSERT_EQUAL(42, fourty_two);
+    TEST_ASSERT_EQUAL(2147483647, int_max);
+    TEST_ASSERT_EQUAL_UINT32(2147483648UL, int_max_plus_one);
+    TEST_ASSERT_EQUAL(0x40010000, iram_ptr);
+    TEST_ASSERT_EQUAL(0x40020000, irom_ptr);
+    TEST_ASSERT_EQUAL('Q', department);
+    TEST_ASSERT_TRUE(1.0f / inv_fine_structure_constant > 136 && 1.0f / inv_fine_structure_constant < 138);
+}
+
+TEST_CASE("test time functions", "[newlib]")
+{
+    time_t now = 1464248488;
+    setenv("TZ", "UTC-8", 1);
+    struct tm *tm_utc = gmtime(&now);
+    TEST_ASSERT_EQUAL( 28, tm_utc->tm_sec);
+    TEST_ASSERT_EQUAL( 41, tm_utc->tm_min);
+    TEST_ASSERT_EQUAL(  7, tm_utc->tm_hour);
+    TEST_ASSERT_EQUAL( 26, tm_utc->tm_mday);
+    TEST_ASSERT_EQUAL(  4, tm_utc->tm_mon);
+    TEST_ASSERT_EQUAL(116, tm_utc->tm_year);
+    TEST_ASSERT_EQUAL(  4, tm_utc->tm_wday);
+    TEST_ASSERT_EQUAL(146, tm_utc->tm_yday);
+
+    struct tm *tm_local = localtime(&now);
+    TEST_ASSERT_EQUAL( 28, tm_local->tm_sec);
+    TEST_ASSERT_EQUAL( 41, tm_local->tm_min);
+    TEST_ASSERT_EQUAL( 15, tm_local->tm_hour);
+    TEST_ASSERT_EQUAL( 26, tm_local->tm_mday);
+    TEST_ASSERT_EQUAL(  4, tm_local->tm_mon);
+    TEST_ASSERT_EQUAL(116, tm_local->tm_year);
+    TEST_ASSERT_EQUAL(  4, tm_local->tm_wday);
+    TEST_ASSERT_EQUAL(146, tm_local->tm_yday);
+
+}
+
+
+static int checkFnRom(void *fn, char *name)
+{
+    int fnaddr = (int)fn;
+    printf("%s: 0X%x\n", name, fnaddr);
+    if ((fnaddr >= 0x40000000) && (fnaddr < 0x40070000)) {
+        return 1;
+    } else {
+        return 0;
+    }
+}
+
+
+TEST_CASE("check if ROM is used for functions", "[newlib]")
+{
+    TEST_ASSERT(checkFnRom(printf, "printf"));
+    TEST_ASSERT(checkFnRom(sscanf, "sscanf"));
+    TEST_ASSERT(checkFnRom(atoi, "atoi"));
+    TEST_ASSERT(checkFnRom(strtol, "strtol"));
+}

+ 26 - 0
components/newlib/time.c

@@ -184,3 +184,29 @@ int settimeofday(const struct timeval *tv, const struct timezone *tz)
     return -1;
 #endif
 }
+
+uint32_t system_get_time(void)
+{
+#if defined( WITH_FRC1 ) || defined( WITH_RTC )
+    return get_time_since_boot();
+#else
+    return 0;
+#endif
+}
+
+uint32_t system_get_current_time(void) __attribute__((alias("system_get_time")));
+
+uint32_t system_relative_time(uint32_t current_time)
+{
+    return system_get_time() - current_time;
+}
+
+uint64_t system_get_rtc_time(void)
+{
+#ifdef WITH_RTC
+    return get_rtc_time_us();
+#else
+    return 0;
+#endif
+}
+

+ 5 - 0
components/nvs_flash/test/component.mk

@@ -0,0 +1,5 @@
+#
+#Component Makefile
+#
+
+COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive

+ 51 - 0
components/nvs_flash/test/test_nvs.c

@@ -0,0 +1,51 @@
+#include <stdio.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <time.h>
+#include "unity.h"
+#include "nvs.h"
+#include "nvs_flash.h"
+#include "esp_spi_flash.h"
+#include <string.h>
+
+
+TEST_CASE("various nvs tests", "[nvs]")
+{
+    nvs_handle handle_1;
+    TEST_ESP_OK(nvs_flash_init());
+    TEST_ESP_ERR(nvs_open("test_namespace1", NVS_READONLY, &handle_1), ESP_ERR_NVS_NOT_FOUND);
+
+    TEST_ESP_ERR(nvs_set_i32(handle_1, "foo", 0x12345678), ESP_ERR_NVS_INVALID_HANDLE);
+    nvs_close(handle_1);
+
+    TEST_ESP_OK(nvs_open("test_namespace2", NVS_READWRITE, &handle_1));
+    TEST_ESP_OK(nvs_erase_all(handle_1));
+    TEST_ESP_OK(nvs_set_i32(handle_1, "foo", 0x12345678));
+    TEST_ESP_OK(nvs_set_i32(handle_1, "foo", 0x23456789));
+
+    nvs_handle handle_2;
+    TEST_ESP_OK(nvs_open("test_namespace3", NVS_READWRITE, &handle_2));
+    TEST_ESP_OK(nvs_erase_all(handle_2));
+    TEST_ESP_OK(nvs_set_i32(handle_2, "foo", 0x3456789a));
+    const char* str = "value 0123456789abcdef0123456789abcdef";
+    TEST_ESP_OK(nvs_set_str(handle_2, "key", str));
+
+    int32_t v1;
+    TEST_ESP_OK(nvs_get_i32(handle_1, "foo", &v1));
+    TEST_ASSERT_EQUAL_INT32(0x23456789, v1);
+
+    int32_t v2;
+    TEST_ESP_OK(nvs_get_i32(handle_2, "foo", &v2));
+    TEST_ASSERT_EQUAL_INT32(0x3456789a, v2);
+
+    char buf[strlen(str) + 1];
+    size_t buf_len = sizeof(buf);
+
+    TEST_ESP_OK(nvs_get_str(handle_2, "key", buf, &buf_len));
+
+    TEST_ASSERT_EQUAL_INT32(0, strcmp(buf, str));
+
+    nvs_close(handle_1);
+    nvs_close(handle_2);
+}

+ 0 - 0
components/nvs_flash/test/Makefile → components/nvs_flash/test_nvs_host/Makefile


+ 0 - 0
components/nvs_flash/test/catch.hpp → components/nvs_flash/test_nvs_host/catch.hpp


+ 0 - 0
components/nvs_flash/test/crc.cpp → components/nvs_flash/test_nvs_host/crc.cpp


+ 0 - 0
components/nvs_flash/test/crc.h → components/nvs_flash/test_nvs_host/crc.h


+ 0 - 0
components/nvs_flash/test/main.cpp → components/nvs_flash/test_nvs_host/main.cpp


+ 0 - 0
components/nvs_flash/test/sdkconfig.h → components/nvs_flash/test_nvs_host/sdkconfig.h


+ 0 - 0
components/nvs_flash/test/spi_flash_emulation.cpp → components/nvs_flash/test_nvs_host/spi_flash_emulation.cpp


+ 0 - 0
components/nvs_flash/test/spi_flash_emulation.h → components/nvs_flash/test_nvs_host/spi_flash_emulation.h


+ 0 - 0
components/nvs_flash/test/test_compressed_enum_table.cpp → components/nvs_flash/test_nvs_host/test_compressed_enum_table.cpp


+ 0 - 0
components/nvs_flash/test/test_intrusive_list.cpp → components/nvs_flash/test_nvs_host/test_intrusive_list.cpp


+ 0 - 0
components/nvs_flash/test/test_nvs.cpp → components/nvs_flash/test_nvs_host/test_nvs.cpp


+ 0 - 0
components/nvs_flash/test/test_spi_flash_emulation.cpp → components/nvs_flash/test_nvs_host/test_spi_flash_emulation.cpp


+ 1 - 1
components/openssl/platform/ssl_pm.c

@@ -215,7 +215,7 @@ static int ssl_pm_reload_crt(SSL *ssl)
  * Perform the mbedtls SSL handshake instead of mbedtls_ssl_handshake.
  * We can add debug here.
  */
-LOCAL int mbedtls_handshake( mbedtls_ssl_context *ssl )
+static int mbedtls_handshake( mbedtls_ssl_context *ssl )
 {
     int ret = 0;
 

+ 5 - 0
components/partition_table/test/component.mk

@@ -0,0 +1,5 @@
+#
+#Component Makefile
+#
+
+COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive

+ 95 - 0
components/partition_table/test/test_partition.c

@@ -0,0 +1,95 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "unity.h"
+#include "esp_partition.h"
+
+
+TEST_CASE("Can read partition table", "[partition]")
+{
+
+    const esp_partition_t *p = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_ANY, NULL);
+    TEST_ASSERT_NOT_NULL(p);
+    TEST_ASSERT_EQUAL(p->address, 0x10000);
+    TEST_ASSERT_EQUAL(p->subtype, ESP_PARTITION_SUBTYPE_APP_FACTORY);
+
+    esp_partition_iterator_t it = esp_partition_find(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, NULL);
+    TEST_ASSERT_NOT_NULL(it);
+    int count = 0;
+    for (; it != NULL; it = esp_partition_next(it)) {
+        const esp_partition_t *p = esp_partition_get(it);
+        TEST_ASSERT_NOT_NULL(p);
+        ++count;
+    }
+    esp_partition_iterator_release(it);
+    TEST_ASSERT_EQUAL(count, 2);
+
+    printf("%d\n", __builtin_clz(count));
+}
+
+TEST_CASE("Can write, read, mmap partition", "[partition]")
+{
+    const esp_partition_t *p = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, NULL);
+    TEST_ASSERT_NOT_NULL(p);
+    const size_t max_size = 2 * SPI_FLASH_SEC_SIZE;
+    uint8_t *data = (uint8_t *) malloc(max_size);
+    TEST_ASSERT_NOT_NULL(data);
+
+    TEST_ASSERT_EQUAL(ESP_OK, esp_partition_erase_range(p, 0, p->size));
+
+    srand(0);
+    size_t block_size;
+    for (size_t offset = 0; offset < p->size; offset += block_size) {
+        block_size = ((rand() + 4) % max_size) & (~0x3);
+        size_t left = p->size - offset;
+        if (block_size > left) {
+            block_size = left;
+        }
+        for (size_t i = 0; i < block_size / 4; ++i) {
+            ((uint32_t *) (data))[i] = rand();
+            if (i == 0 && offset == 0) {
+                printf("write: %08x\n", ((uint32_t *) (data))[i]);
+            }
+        }
+        TEST_ASSERT_EQUAL(ESP_OK, esp_partition_write(p, offset, data, block_size));
+    }
+
+    srand(0);
+    for (size_t offset = 0; offset < p->size; offset += block_size) {
+        block_size = ((rand() + 4) % max_size) & (~0x3);
+        size_t left = p->size - offset;
+        if (block_size > left) {
+            block_size = left;
+        }
+        TEST_ASSERT_EQUAL(ESP_OK, esp_partition_read(p, offset, data, block_size));
+        for (size_t i = 0; i < block_size / 4; ++i) {
+            TEST_ASSERT_EQUAL(rand(), ((uint32_t *) data)[i]);
+        }
+    }
+
+    free(data);
+
+    const uint32_t *mmap_data;
+    spi_flash_mmap_handle_t mmap_handle;
+    size_t begin = 3000;
+    size_t size = 12000;
+    TEST_ASSERT_EQUAL(ESP_OK, esp_partition_mmap(p, begin, size, SPI_FLASH_MMAP_DATA,
+                      (const void **)&mmap_data, &mmap_handle));
+    srand(0);
+    for (size_t offset = 0; offset < p->size; offset += block_size) {
+        block_size = ((rand() + 4) % max_size) & (~0x3);
+        size_t left = p->size - offset;
+        if (block_size > left) {
+            block_size = left;
+        }
+        for (size_t i = 0; i < block_size / 4; ++i) {
+            size_t pos = offset + i * 4;
+            uint32_t expected = rand();
+            if (pos < begin || pos >= (begin + size)) {
+                continue;
+            }
+            TEST_ASSERT_EQUAL(expected, mmap_data[(pos - begin) / 4]);
+        }
+    }
+
+    spi_flash_munmap(mmap_handle);
+}

+ 5 - 0
components/spi_flash/test/component.mk

@@ -0,0 +1,5 @@
+#
+#Component Makefile
+#
+
+COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive

+ 83 - 0
components/spi_flash/test/test_mmap.c

@@ -0,0 +1,83 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <freertos/FreeRTOS.h>
+#include <freertos/task.h>
+#include <freertos/semphr.h>
+
+#include <unity.h>
+#include <esp_spi_flash.h>
+#include <esp_attr.h>
+
+uint32_t buffer[1024];
+
+static const uint32_t start = 0x200000;
+static const uint32_t end = 0x300000;
+
+
+
+TEST_CASE("Prepare data for mmap tests", "[mmap]")
+{
+    srand(0);
+    for (int block = start / 0x10000; block < end / 0x10000; ++block) {
+        printf("Writing block %d\n", block);
+        for (int sector = 0; sector < 16; ++sector) {
+            for (uint32_t word = 0; word < 1024; ++word) {
+                uint32_t val = rand();
+                if (block == start / 0x10000 && sector == 0 && word == 0) {
+                    printf("first word: %08x\n", val);
+                }
+                buffer[word] = val;
+            }
+            uint32_t abs_sector = (block) * 16 + sector;
+            printf("Writing sector %d\n", abs_sector);
+            ESP_ERROR_CHECK( spi_flash_erase_sector((uint16_t) abs_sector) );
+            ESP_ERROR_CHECK( spi_flash_write(abs_sector * SPI_FLASH_SEC_SIZE, (const uint8_t *) buffer, sizeof(buffer)) );
+        }
+    }
+}
+
+TEST_CASE("Can mmap into data address space", "[mmap]")
+{
+
+    printf("Mapping %x (+%x)\n", start, end - start);
+    spi_flash_mmap_handle_t handle1;
+    const void *ptr1;
+    ESP_ERROR_CHECK( spi_flash_mmap(start, end - start, SPI_FLASH_MMAP_DATA, &ptr1, &handle1) );
+    printf("mmap_res: handle=%d ptr=%p\n", handle1, ptr1);
+
+    spi_flash_mmap_dump();
+
+    srand(0);
+    const uint32_t *data = (const uint32_t *) ptr1;
+    for (int block = 0; block < (end - start) / 0x10000; ++block) {
+        for (int sector = 0; sector < 16; ++sector) {
+            for (uint32_t word = 0; word < 1024; ++word) {
+                TEST_ASSERT_EQUAL_UINT32(rand(), data[(block * 16 + sector) * 1024 + word]);
+            }
+        }
+    }
+    printf("Mapping %x (+%x)\n", start - 0x10000, 0x20000);
+    spi_flash_mmap_handle_t handle2;
+    const void *ptr2;
+    ESP_ERROR_CHECK( spi_flash_mmap(start - 0x10000, 0x20000, SPI_FLASH_MMAP_DATA, &ptr2, &handle2) );
+    printf("mmap_res: handle=%d ptr=%p\n", handle2, ptr2);
+    spi_flash_mmap_dump();
+
+    printf("Mapping %x (+%x)\n", start, 0x10000);
+    spi_flash_mmap_handle_t handle3;
+    const void *ptr3;
+    ESP_ERROR_CHECK( spi_flash_mmap(start, 0x10000, SPI_FLASH_MMAP_DATA, &ptr3, &handle3) );
+    printf("mmap_res: handle=%d ptr=%p\n", handle3, ptr3);
+    spi_flash_mmap_dump();
+
+    printf("Unmapping handle1\n");
+    spi_flash_munmap(handle1);
+    spi_flash_mmap_dump();
+
+    printf("Unmapping handle2\n");
+    spi_flash_munmap(handle2);
+    spi_flash_mmap_dump();
+
+    printf("Unmapping handle3\n");
+    spi_flash_munmap(handle3);
+}

+ 92 - 0
components/spi_flash/test/test_spi_flash.c

@@ -0,0 +1,92 @@
+#include <stdio.h>
+#include <freertos/FreeRTOS.h>
+#include <freertos/task.h>
+#include <freertos/semphr.h>
+
+#include <unity.h>
+#include <esp_spi_flash.h>
+#include <esp_attr.h>
+
+struct flash_test_ctx {
+    uint32_t offset[2];
+    bool fail[2];
+    SemaphoreHandle_t done;
+};
+
+static void flash_test_task(void *arg)
+{
+    const uint32_t coreid = xPortGetCoreID();
+    ets_printf("t%d\n", coreid);
+    struct flash_test_ctx *ctx = (struct flash_test_ctx *) arg;
+    vTaskDelay(100 / portTICK_PERIOD_MS);
+    const uint32_t sector = ctx->offset[coreid];
+    ets_printf("es%d\n", coreid);
+    if (spi_flash_erase_sector(sector) != ESP_OK) {
+        ctx->fail[coreid] = true;
+        ets_printf("Erase failed\r\n");
+        xSemaphoreGive(ctx->done);
+        vTaskDelete(NULL);
+    }
+    ets_printf("ed%d\n", coreid);
+
+    vTaskDelay(0 / portTICK_PERIOD_MS);
+
+    uint32_t val = 0xabcd1234;
+    const uint32_t n = 4096;
+    for (uint32_t offset = 0; offset < n; offset += 4) {
+        if (spi_flash_write(sector * SPI_FLASH_SEC_SIZE + offset, (const uint8_t *) &val, 4) != ESP_OK) {
+            ets_printf("Write failed at offset=%d\r\n", offset);
+            ctx->fail[coreid] = true;
+            break;
+        }
+    }
+    ets_printf("wd%d\n", coreid);
+
+    vTaskDelay(0 / portTICK_PERIOD_MS);
+
+    uint32_t val_read;
+    for (uint32_t offset = 0; offset < n; offset += 4) {
+        if (spi_flash_read(sector * SPI_FLASH_SEC_SIZE + offset, (uint8_t *) &val_read, 4) != ESP_OK) {
+            ets_printf("Read failed at offset=%d\r\n", offset);
+            ctx->fail[coreid] = true;
+            break;
+        }
+        if (val_read != val) {
+            ets_printf("Read invalid value=%08x at offset=%d\r\n", val_read, offset);
+            ctx->fail[coreid] = true;
+            break;
+        }
+    }
+    ets_printf("td%d\n", coreid);
+    xSemaphoreGive(ctx->done);
+    vTaskDelete(NULL);
+}
+
+TEST_CASE("flash write and erase work both on PRO CPU and on APP CPU", "[spi_flash]")
+{
+    TaskHandle_t procpu_task;
+    TaskHandle_t appcpu_task;
+    struct flash_test_ctx ctx;
+
+    ctx.offset[0] = 6;
+    ctx.offset[1] = 7;
+    ctx.fail[0] = 0;
+    ctx.fail[1] = 0;
+    ctx.done = xSemaphoreCreateBinary();
+
+    xTaskCreatePinnedToCore(flash_test_task, "1", 2048, &ctx, 3, &procpu_task, 0);
+    if (portNUM_PROCESSORS == 2) {
+        xTaskCreatePinnedToCore(flash_test_task, "2", 2048, &ctx, 3, &appcpu_task, 1);
+    }
+
+    xSemaphoreTake(ctx.done, portMAX_DELAY);
+    if (portNUM_PROCESSORS == 2) {
+        xSemaphoreTake(ctx.done, portMAX_DELAY);
+    }
+
+    TEST_ASSERT_EQUAL(false, ctx.fail[0]);
+    if (portNUM_PROCESSORS == 2) {
+        TEST_ASSERT_EQUAL(false, ctx.fail[1]);
+    }
+}
+

+ 1 - 1
components/wpa_supplicant/component.mk

@@ -1,4 +1,4 @@
 COMPONENT_ADD_INCLUDEDIRS := include port/include
-COMPONENT_SRCDIRS := src/crypto
+COMPONENT_SRCDIRS := src/crypto port
 
 CFLAGS += -DEMBEDDED_SUPP -D__ets__ -Wno-strict-aliasing

+ 1 - 0
components/wpa_supplicant/port/include/endian.h

@@ -119,6 +119,7 @@ typedef	__uint64_t	uint64_t;
 #endif /* _BYTE_ORDER == _LITTLE_ENDIAN */
 
 /* Alignment-agnostic encode/decode bytestream to/from little/big endian. */
+#define INLINE                  __inline__
 
 static INLINE uint16_t
 be16dec(const void *pp)

+ 64 - 0
components/wpa_supplicant/port/os_xtensa.c

@@ -0,0 +1,64 @@
+/*
+ * wpa_supplicant/hostapd / Internal implementation of OS specific functions
+ * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ *
+ * This file is an example of operating system specific  wrapper functions.
+ * This version implements many of the functions internally, so it can be used
+ * to fill in missing functions from the target system C libraries.
+ *
+ * Some of the functions are using standard C library calls in order to keep
+ * this file in working condition to allow the functions to be tested on a
+ * Linux target. Please note that OS_NO_C_LIB_DEFINES needs to be defined for
+ * this file to work correctly. Note that these implementations are only
+ * examples and are not optimized for speed.
+ */
+
+#include "crypto/common.h"
+#include "os.h"
+#include <stdlib.h>
+#include <time.h>
+#include <sys/time.h>
+#include "esp_system.h"
+
+int os_get_time(struct os_time *t)
+{
+    return gettimeofday((struct timeval*) t, NULL);
+}
+
+unsigned long os_random(void)
+{
+    return esp_random();
+}
+
+unsigned long r_rand(void) __attribute__((alias("os_random")));
+
+
+int os_get_random(unsigned char *buf, size_t len)
+{
+    int i, j;
+    unsigned long tmp;
+
+    for (i = 0; i < ((len + 3) & ~3) / 4; i++) {
+        tmp = r_rand();
+
+        for (j = 0; j < 4; j++) {
+            if ((i * 4 + j) < len) {
+                buf[i * 4 + j] = (uint8_t)(tmp >> (j * 8));
+            } else {
+                break;
+            }
+        }
+    }
+
+    return 0;
+}
+

+ 66 - 0
docs/api/pcnt.rst

@@ -0,0 +1,66 @@
+Pulse Counter
+========
+
+Overview
+--------
+
+The PCNT (Pulse Counter) module is designed to count the number of rising and/or falling edges of an input signal. Each pulse counter unit has a 16-bit signed counter register and two channels that can be configured to either increment or decrement the counter. Each channel has a signal input that accepts signal edges to be detected, as well as a control input that can be used to enable or disable the signal input. The inputs have optional filters that can be used to discard unwanted glitches in the signal.
+
+Application Example
+-------------------
+
+Pulse counter with control signal and event interrupt example: `examples/12_pcnt <https://github.com/espressif/esp-idf/tree/master/examples/12_pcnt>`_.
+
+API Reference
+-------------
+
+Header Files
+^^^^^^^^^^^^
+
+  * `driver/pcnt.h <https://github.com/espressif/esp-idf/blob/master/components/driver/include/driver/pcnt.h>`_
+
+
+Macros
+^^^^^^
+
+
+Type Definitions
+^^^^^^^^^^^^^^^^
+
+
+Enumerations
+^^^^^^^^^^^^
+
+.. doxygenenum:: pcnt_ctrl_mode_t
+.. doxygenenum:: pcnt_count_mode_t
+.. doxygenenum:: pcnt_unit_t
+.. doxygenenum:: pcnt_channel_t
+.. doxygenenum:: pcnt_evt_type_t
+
+Structures
+^^^^^^^^^^
+
+.. doxygenstruct:: pcnt_config_t
+
+Functions
+^^^^^^^^^
+
+.. doxygenfunction:: pcnt_unit_config
+.. doxygenfunction:: pcnt_get_counter_value
+.. doxygenfunction:: pcnt_counter_pause
+.. doxygenfunction:: pcnt_counter_resume
+.. doxygenfunction:: pcnt_counter_clear
+.. doxygenfunction:: pcnt_intr_enable
+.. doxygenfunction:: pcnt_intr_disable
+.. doxygenfunction:: pcnt_event_enable
+.. doxygenfunction:: pcnt_event_disable
+.. doxygenfunction:: pcnt_set_event_value
+.. doxygenfunction:: pcnt_get_event_value
+.. doxygenfunction:: pcnt_isr_register
+.. doxygenfunction:: pcnt_set_pin
+.. doxygenfunction:: pcnt_filter_enable
+.. doxygenfunction:: pcnt_filter_disable
+.. doxygenfunction:: pcnt_set_filter_value
+.. doxygenfunction:: pcnt_get_filter_value
+.. doxygenfunction:: pcnt_set_mode
+

+ 1 - 1
docs/index.rst

@@ -97,12 +97,12 @@ Contents:
    Wi-Fi <api/esp_wifi>
    Bluetooth <api/bt>
    Watchdogs <api/wdts>
-
    GPIO <api/gpio>
    UART <api/uart>
    LED Control <api/ledc>
    Remote Control <api/rmt>
    Timer <api/timer>
+   Pulse Counter <api/pcnt>
    SPI Flash and Partition APIs <api/spi_flash>
    Logging <api/log>
    Non-Volatile Storage <api/nvs_flash>

+ 1 - 1
examples/01_hello_world/main/hello_world_main.c

@@ -21,7 +21,7 @@ void hello_task(void *pvParameter)
     }
     printf("Restarting now.\n");
     fflush(stdout);
-    system_restart();
+    esp_restart();
 }
 
 void app_main()

+ 1 - 0
examples/04_https_request/main/https_request_main.c

@@ -22,6 +22,7 @@
  * limitations under the License.
  */
 #include <string.h>
+#include <stdlib.h>
 #include "freertos/FreeRTOS.h"
 #include "freertos/task.h"
 #include "freertos/event_groups.h"

+ 1 - 1
examples/06_sntp/main/sntp_main.c

@@ -88,7 +88,7 @@ void app_main()
 
     const int deep_sleep_sec = 10;
     ESP_LOGI(TAG, "Entering deep sleep for %d seconds", deep_sleep_sec);
-    system_deep_sleep(1000000LL * deep_sleep_sec);
+    esp_deep_sleep(1000000LL * deep_sleep_sec);
 }
 
 static void obtain_time(void)

+ 1 - 1
examples/07_nvs_rw_value/main/nvs_rw_value.c

@@ -76,5 +76,5 @@ void app_main()
     }
     printf("Restarting now.\n");
     fflush(stdout);
-    system_restart();
+    esp_restart();
 }

+ 1 - 1
examples/08_nvs_rw_blob/main/nvs_rw_blob.c

@@ -170,7 +170,7 @@ void app_main()
                 if (err != ESP_OK) printf("Error (%d) saving run time blob to NVS!\n", err);
                 printf("Restarting...\n");
                 fflush(stdout);
-                system_restart();
+                esp_restart();
             }
         }
         vTaskDelay(200 / portTICK_RATE_MS);

+ 9 - 0
examples/12_pcnt/Makefile

@@ -0,0 +1,9 @@
+#
+# This is a project Makefile. It is assumed the directory this Makefile resides in is a
+# project subdirectory.
+#
+
+PROJECT_NAME := pcnt
+
+include $(IDF_PATH)/make/project.mk
+

+ 3 - 0
examples/12_pcnt/main/component.mk

@@ -0,0 +1,3 @@
+#
+# Main Makefile. This is basically the same as a component makefile.
+#

+ 226 - 0
examples/12_pcnt/main/pcnt_test.c

@@ -0,0 +1,226 @@
+/* Pulse counter module - Example
+
+   For other examples please check:
+   https://github.com/espressif/esp-idf/tree/master/examples
+
+   This example code is in the Public Domain (or CC0 licensed, at your option.)
+
+   Unless required by applicable law or agreed to in writing, this
+   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+   CONDITIONS OF ANY KIND, either express or implied.
+*/
+#include <stdio.h>
+#include "freertos/FreeRTOS.h"
+#include "freertos/portmacro.h"
+#include "freertos/task.h"
+#include "freertos/queue.h"
+#include "driver/periph_ctrl.h"
+#include "driver/ledc.h"
+#include "driver/gpio.h"
+#include "driver/pcnt.h"
+#include "esp_attr.h"
+#include "esp_log.h"
+#include "soc/gpio_sig_map.h"
+
+/**
+ * TEST CODE BRIEF
+ * Use PCNT module to count rising edges generated by LEDC module.
+ * GPIO18 is used as output pin, GPIO4 is used as pulse input pin and GPIO5 is used as control input pin
+ *
+ * Open serial port to view the message printed on your screen
+ *
+ * To do this test, you should connect GPIO18 with GPIO4
+ * GPIO5 is the control signal, you can leave it floating with internal pulled up, or connect it to ground.
+ * If you connect gpio5 to GND ,you will found the count value decreasing.
+ *
+ * When counter value reaches thresh1 or thresh0 value, it will trigger interrupt.
+ * When counter value reaches l_lim value or h_lim value, counter value will be reset to zero and trigger interrupt.
+ */
+static const char* TAG = "PCNT_TEST";
+#define PCNT_TEST_UNIT    PCNT_UNIT_0
+#define PCNT_H_LIM_VAL    (10)
+#define PCNT_L_LIM_VAL    (-10)
+#define PCNT_THRESH1_VAL  (5)
+#define PCNT_THRESH0_VAL  (-5)
+#define PCNT_INTR_NUM     (18)
+#define PCNT_INPUT_SIG_IO   (4)
+#define PCNT_INPUT_CTRL_IO  (5)
+#define LEDC_OUPUT_IO      (18)
+
+xQueueHandle pcnt_evt_queue;  /*A queue to handle pulse counter event*/
+
+
+typedef struct {
+    int unit;        /*pulse counter unit*/
+    uint32_t status; /*pulse counter internal status*/
+} pcnt_evt_t;
+
+void IRAM_ATTR pcnt_intr_handler(void* arg)
+{
+    uint32_t intr_status = PCNT.int_st.val;
+    int i;
+    pcnt_evt_t evt;
+    portBASE_TYPE HPTaskAwoken = pdFALSE;
+
+    for(i = 0; i < PCNT_UNIT_MAX; i++) {
+        if(intr_status & (BIT(i))) {
+            evt.unit = i;
+            evt.status = PCNT.status_unit[i].val;
+            PCNT.int_clr.val = BIT(i);
+            /*H LIM EVT*/
+            if(PCNT.status_unit[i].h_lim_lat) {
+                //do something
+            }
+            /*L LIM EVT*/
+            if(PCNT.status_unit[i].l_lim_lat) {
+                //do something
+            }
+            /*THRES0 EVT*/
+            if(PCNT.status_unit[i].thres0_lat) {
+                //do something
+            }
+            /*THRES1 EVT*/
+            if(PCNT.status_unit[i].thres1_lat) {
+                //do something
+            }
+            /*ZERO EVT*/
+            if(PCNT.status_unit[i].zero_lat) {
+                //do something
+            }
+            xQueueSendFromISR(pcnt_evt_queue, &evt, &HPTaskAwoken);
+            if(HPTaskAwoken == pdTRUE) {
+                portYIELD_FROM_ISR();
+            }
+        }
+    }
+}
+
+static void ledc_init(void)
+{
+    ledc_channel_config_t ledc_channel;
+    /*use GPIO18 as output pin*/
+    ledc_channel.gpio_num = LEDC_OUPUT_IO;
+    /*LEDC high speed mode */
+    ledc_channel.speed_mode = LEDC_HIGH_SPEED_MODE;
+    /*use LEDC channel 1*/
+    ledc_channel.channel = LEDC_CHANNEL_1;
+    /*Disable LEDC interrupt*/
+    ledc_channel.intr_type = LEDC_INTR_DISABLE;
+    /*Select LEDC timer 1 */
+    ledc_channel.timer_sel = LEDC_TIMER_1;
+    /*Set duty 100 */
+    ledc_channel.duty = 100;
+    ledc_channel_config(&ledc_channel); //ledc config
+
+    ledc_timer_config_t ledc_timer;
+    /*LEDC timer high speed mode*/
+    ledc_timer.speed_mode = LEDC_HIGH_SPEED_MODE;
+    /*10 bit PWM*/
+    ledc_timer.bit_num = LEDC_TIMER_10_BIT;
+    /*Select timer 1*/
+    ledc_timer.timer_num = LEDC_TIMER_1;
+    /*Set frequency 1 Hz  */
+    ledc_timer.freq_hz = 1;
+    ledc_timer_config(&ledc_timer);
+}
+
+static void pcnt_init(void)
+{
+    pcnt_config_t pcnt_config = {
+        /*Set GPIO4 as pulse input gpio */
+        .pulse_gpio_num = PCNT_INPUT_SIG_IO,
+        /*set gpio5 as control gpio */
+        .ctrl_gpio_num = PCNT_INPUT_CTRL_IO,
+        /*Choose channel 0 */
+        .channel = PCNT_CHANNEL_0,
+        /*Choose unit 0 */
+        .unit = PCNT_TEST_UNIT,
+        /*Set counter and control mode*/
+        /*Counter increase for positive edge on pulse input GPIO*/
+        .pos_mode = PCNT_COUNT_INC,
+        /*Counter decrease for negative edge on pulse input GPIO*/
+        .neg_mode = PCNT_COUNT_DIS,      //keep the counter value
+        /*Counter mode reverse when control input is low level*/
+        .lctrl_mode = PCNT_MODE_REVERSE,
+        /*Counter mode does not change when control input is high level*/
+        .hctrl_mode = PCNT_MODE_KEEP,      //when control signal is high,keep the primary counter mode
+        /*Set maximum value for increasing counter*/
+        .counter_h_lim = PCNT_H_LIM_VAL,
+        /*Set minimum value for decreasing counter*/
+        .counter_l_lim = PCNT_L_LIM_VAL,
+    };
+    /*Initialize PCNT unit */
+    pcnt_unit_config(&pcnt_config);
+
+    /*Configure input filter value*/
+    pcnt_set_filter_value(PCNT_TEST_UNIT, 100);
+    /*Enable input filter*/
+    pcnt_filter_enable(PCNT_TEST_UNIT);
+
+    /*Set value for watch point thresh1*/
+    pcnt_set_event_value(PCNT_TEST_UNIT, PCNT_EVT_THRES_1, PCNT_THRESH1_VAL);
+    /*Enable watch point event of thresh1*/
+    pcnt_event_enable(PCNT_TEST_UNIT, PCNT_EVT_THRES_1);
+    /*Set value for watch point thresh0*/
+    pcnt_set_event_value(PCNT_TEST_UNIT, PCNT_EVT_THRES_0, PCNT_THRESH0_VAL);
+    /*Enable watch point event of thresh0*/
+    pcnt_event_enable(PCNT_TEST_UNIT, PCNT_EVT_THRES_0);
+    /*Enable watch point event of h_lim*/
+    pcnt_event_enable(PCNT_TEST_UNIT, PCNT_EVT_H_LIM);
+    /*Enable watch point event of l_lim*/
+    pcnt_event_enable(PCNT_TEST_UNIT, PCNT_EVT_L_LIM);
+    /*Enable watch point event of zero*/
+    pcnt_event_enable(PCNT_TEST_UNIT, PCNT_EVT_ZERO);
+
+    /*Pause counter*/
+    pcnt_counter_pause(PCNT_TEST_UNIT);
+    /*Reset counter value*/
+    pcnt_counter_clear(PCNT_TEST_UNIT);
+    /*Register ISR handler*/
+    pcnt_isr_register(PCNT_INTR_NUM, pcnt_intr_handler, NULL);
+    /*Enable interrupt for PCNT unit*/
+    pcnt_intr_enable(PCNT_TEST_UNIT);
+    /*Resume counting*/
+    pcnt_counter_resume(PCNT_TEST_UNIT);
+}
+
+void app_main()
+{
+    /*Init LEDC for pulse input signal */
+    ledc_init();
+    /*Init PCNT event queue */
+    pcnt_evt_queue = xQueueCreate(10, sizeof(pcnt_evt_t));
+    /*Init PCNT functions*/
+    pcnt_init();
+
+    int16_t count = 0;
+    pcnt_evt_t evt;
+    portBASE_TYPE res;
+    while(1)
+    {
+        res = xQueueReceive(pcnt_evt_queue, &evt, 1000 / portTICK_RATE_MS);
+        if(res == pdTRUE) {
+            pcnt_get_counter_value(PCNT_TEST_UNIT, &count);
+            printf("Event PCNT unit[%d]; cnt: %d\n", evt.unit, count);
+            if(evt.status & PCNT_STATUS_THRES1_M) {
+                printf("THRES1 EVT\n");
+            }
+            if(evt.status & PCNT_STATUS_THRES0_M) {
+                printf("THRES0 EVT\n");
+            }
+            if(evt.status & PCNT_STATUS_L_LIM_M) {
+                printf("L_LIM EVT\n");
+            }
+            if(evt.status & PCNT_STATUS_H_LIM_M) {
+                printf("H_LIM EVT\n");
+            }
+            if(evt.status & PCNT_STATUS_ZERO_M) {
+                printf("ZERO EVT\n");
+            }
+        } else {
+            pcnt_get_counter_value(PCNT_TEST_UNIT, &count);
+            printf("Current counter value :%d\n", count);
+        }
+    }
+}
+

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio