Просмотр исходного кода

Merge with master; merge Doxygen config

Jeroen Domburg 9 лет назад
Родитель
Сommit
f3a44aa4db
49 измененных файлов с 1070 добавлено и 655 удалено
  1. 3 0
      .gitlab-ci.yml
  2. 1 1
      components/bootloader_support/src/esp_image_format.c
  3. 5 2
      components/bootloader_support/src/secure_boot_signatures.c
  4. 1 2
      components/bt/component.mk
  5. 2 5
      components/bt/include/bt.h
  6. 7 1
      components/driver/include/driver/gpio.h
  7. 8 0
      components/driver/include/driver/ledc.h
  8. 184 199
      components/driver/include/driver/uart.h
  9. 30 11
      components/driver/uart.c
  10. 1 3
      components/esp32/component.mk
  11. 209 224
      components/esp32/include/esp_wifi.h
  12. 1 1
      components/esp32/lib
  13. 3 1
      components/esptool_py/Makefile.projbuild
  14. 32 31
      components/expat/port/minicheck.c
  15. 16 6
      components/freertos/ringbuf.c
  16. 1 3
      components/freertos/tasks.c
  17. 16 0
      components/lwip/Kconfig
  18. 7 0
      components/lwip/include/lwip/lwip/opt.h
  19. 1 0
      components/lwip/include/lwip/port/lwipopts.h
  20. 18 21
      components/lwip/port/netif/wlanif.c
  21. 2 0
      components/micro-ecc/component.mk
  22. 84 21
      components/nvs_flash/include/nvs.h
  23. 1 1
      components/nvs_flash/include/nvs_flash.h
  24. 1 1
      components/nvs_flash/src/nvs_api.cpp
  25. 61 40
      components/spi_flash/include/esp_partition.h
  26. 3 3
      components/spi_flash/include/esp_spi_flash.h
  27. 5 5
      components/vfs/include/esp_vfs.h
  28. 10 5
      docs/Doxyfile
  29. 4 1
      docs/api/nvs_flash.rst
  30. 67 0
      docs/api/spi_flash.rst
  31. 8 0
      docs/build_system.rst
  32. 56 0
      docs/doxygen_xml_to_rst.xslt
  33. 125 0
      docs/general-notes.rst
  34. 2 1
      docs/index.rst
  35. 1 3
      docs/openocd.rst
  36. 1 1
      docs/partition-tables.rst
  37. 6 6
      docs/security/secure-boot.rst
  38. 1 1
      examples/01_hello_world/main/component.mk
  39. 1 1
      examples/02_blink/main/component.mk
  40. 1 1
      examples/03_http_request/main/component.mk
  41. 1 1
      examples/04_https_request/main/component.mk
  42. 1 1
      examples/05_ble_adv/main/component.mk
  43. 1 1
      examples/06_sntp/main/component.mk
  44. 4 1
      examples/07_nvs_rw_value/main/component.mk
  45. 4 1
      examples/08_nvs_rw_blob/main/component.mk
  46. 7 2
      make/build_examples.sh
  47. 0 25
      make/common.mk
  48. 23 11
      make/component_wrapper.mk
  49. 43 10
      make/project.mk

+ 3 - 0
.gitlab-ci.yml

@@ -118,6 +118,9 @@ build_docs:
     - build_docs
   script:
     - cd docs
+    - doxygen
+    # If not building master branch, and there are Doxygen warnings, print them and bail out
+    - test "${CI_BUILD_REF_NAME}" = "master" || test $(cat doxygen-warning-log.txt | wc -l) -eq 0 || ( echo "Doxygen pass had some warnings:" && cat doxygen-warning-log.txt && false )
     - make html
   artifacts:
     paths:

+ 1 - 1
components/bootloader_support/src/esp_image_format.c

@@ -17,7 +17,7 @@
 #include <esp_log.h>
 #include <bootloader_flash.h>
 
-const static char *TAG = "esp_image";
+static const char *TAG = "esp_image";
 
 #define SIXTEEN_MB 0x1000000
 #define ESP_ROM_CHECKSUM_INITIAL 0xEF

+ 5 - 2
components/bootloader_support/src/secure_boot_signatures.c

@@ -45,10 +45,13 @@ esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
     sha_context sha;
     uint8_t digest[32];
     ptrdiff_t keylen;
-    const uint8_t *data, *digest_data;
-    uint32_t digest_len;
+    const uint8_t *data;
     const signature_block_t *sigblock;
     bool is_valid;
+#ifdef BOOTLOADER_BUILD
+    const uint8_t *digest_data;
+    uint32_t digest_len;
+#endif
 
     ESP_LOGD(TAG, "verifying signature src_addr 0x%x length 0x%x", src_addr, length);
 

+ 1 - 2
components/bt/component.mk

@@ -15,5 +15,4 @@ COMPONENT_ADD_LDFLAGS := -lbt -L $(COMPONENT_PATH)/lib \
 ALL_LIB_FILES := $(patsubst %,$(COMPONENT_PATH)/lib/lib%.a,$(LIBS))
 $(COMPONENT_LIBRARY): $(ALL_LIB_FILES)
 
-# automatically trigger a git submodule update if BT library is missing
-$(eval $(call SubmoduleCheck,$(ALL_LIB_FILES),$(COMPONENT_PATH)/lib))
+COMPONENT_SUBMODULES += lib

+ 2 - 5
components/bt/include/bt.h

@@ -32,13 +32,10 @@ void bt_controller_init(void);
 
 /** @brief vhci_host_callback
  *  used for vhci call host function to notify what host need to do
- *  
- *  notify_host_send_available: notify host can send packet to controller
- *  notify_host_recv: notify host that controller has packet send to host
  */
 typedef struct vhci_host_callback {
-    void (*notify_host_send_available)(void);
-    int (*notify_host_recv)(uint8_t *data, uint16_t len);
+    void (*notify_host_send_available)(void);               /*!< callback used to notify that the host can send packet to controller */
+    int (*notify_host_recv)(uint8_t *data, uint16_t len);   /*!< callback used to notify that the controller has a packet to send to the host*/
 } vhci_host_callback_t;
 
 /** @brief API_vhci_host_check_send_available

+ 7 - 1
components/driver/include/driver/gpio.h

@@ -117,6 +117,9 @@ extern const uint32_t GPIO_PIN_MUX_REG[GPIO_PIN_COUNT];
 #define GPIO_IS_VALID_GPIO(gpio_num)      ((gpio_num < GPIO_PIN_COUNT && GPIO_PIN_MUX_REG[gpio_num] != 0))   //to decide whether it is a valid GPIO number
 #define GPIO_IS_VALID_OUTPUT_GPIO(gpio_num)      ((GPIO_IS_VALID_GPIO(gpio_num)) && (gpio_num < 34))         //to decide whether it can be a valid GPIO number of output mode
 
+/**
+ * @brief Pullup/pulldown information for a single GPIO pad
+ */
 typedef struct {
     uint32_t reg;       /*!< Register to modify to enable or disable pullups or pulldowns */
     uint32_t pu;        /*!< Bit to set or clear in the above register to enable or disable the pullup, respectively */
@@ -208,6 +211,9 @@ typedef enum {
     GPIO_PULLDOWN_ENABLE = 0x1,    /*!< Enable GPIO pull-down resistor  */
 } gpio_pulldown_t;
 
+/**
+ * @brief Configuration parameters of GPIO pad for gpio_config function
+ */
 typedef struct {
     uint64_t pin_bit_mask;          /*!< GPIO pin: set with bit mask, each bit maps to a GPIO */
     gpio_mode_t mode;               /*!< GPIO mode: set input/output mode                     */
@@ -337,7 +343,7 @@ esp_err_t gpio_set_pull_mode(gpio_num_t gpio_num, gpio_pull_mode_t pull);
   *
   * @param gpio_num GPIO number.
   *
-  * @param intr_type GPIO wake-up type. Only GPIO_INTR_LOW_LEVEL\GPIO_INTR_HIGH_LEVEL can be used.
+  * @param intr_type GPIO wake-up type. Only GPIO_INTR_LOW_LEVEL or GPIO_INTR_HIGH_LEVEL can be used.
   *
   * @return
   *     - ESP_OK Success

+ 8 - 0
components/driver/include/driver/ledc.h

@@ -78,6 +78,9 @@ typedef enum {
     LEDC_TIMER_15_BIT = 15, /*!< LEDC PWM depth 15Bit */
 } ledc_timer_bit_t;
 
+/**
+ * @brief Configuration parameters of LEDC channel for ledc_channel_config function
+ */
 typedef struct {
     int gpio_num;                   /*!< the LEDC output gpio_num, if you want to use gpio16, gpio_num = 16*/
     ledc_mode_t speed_mode;         /*!< LEDC speed speed_mode, high-speed mode or low-speed mode*/
@@ -87,6 +90,9 @@ typedef struct {
     uint32_t duty;                  /*!< LEDC channel duty, the duty range is [0, (2**bit_num) - 1], */
 } ledc_channel_config_t;
 
+/**
+ * @brief Configuration parameters of LEDC Timer timer for ledc_timer_config function
+ */
 typedef struct {
     ledc_mode_t speed_mode;         /*!< LEDC speed speed_mode, high-speed mode or low-speed mode*/
     ledc_timer_bit_t bit_num;       /*!< LEDC channel duty depth*/
@@ -150,6 +156,8 @@ esp_err_t ledc_update_duty(ledc_mode_t speed_mode, ledc_channel_t channel);
  *
  * @param  channel LEDC channel(0-7), select from ledc_channel_t
  *
+ * @param  idle_level Set output idle level after LEDC stops.
+ *
  * @return
  *     - ESP_OK Success
  *     - ESP_ERR_INVALID_ARG Parameter error

+ 184 - 199
components/driver/include/driver/uart.h

@@ -32,11 +32,11 @@ extern "C" {
 #include "freertos/ringbuf.h"
 #include <esp_types.h>
 
-#define UART_FIFO_LEN           (128)   /*< Length of the hardware FIFO buffers */
-#define UART_INTR_MASK          0x1ff
-#define UART_LINE_INV_MASK      (0x3f << 19)
-#define UART_BITRATE_MAX        5000000
-#define UART_PIN_NO_CHANGE      (-1)
+#define UART_FIFO_LEN           (128)        /*!< Length of the hardware FIFO buffers */
+#define UART_INTR_MASK          0x1ff        /*!< mask of all UART interrupts */
+#define UART_LINE_INV_MASK      (0x3f << 19) /*!< TBD */
+#define UART_BITRATE_MAX        5000000      /*!< Max bit rate supported by UART */
+#define UART_PIN_NO_CHANGE      (-1)         /*!< Constant for uart_set_pin function which indicates that UART pin should not be changed */
 
 #define UART_INVERSE_DISABLE  (0x0)            /*!< Disable UART signal inverse*/
 #define UART_INVERSE_RXD   (UART_RXD_INV_M)    /*!< UART RXD input inverse*/
@@ -44,6 +44,9 @@ extern "C" {
 #define UART_INVERSE_TXD   (UART_TXD_INV_M)    /*!< UART TXD output inverse*/
 #define UART_INVERSE_RTS   (UART_RTS_INV_M)    /*!< UART RTS output inverse*/
 
+/**
+ * @brief UART word length constants
+ */
 typedef enum {
     UART_DATA_5_BITS = 0x0,    /*!< word length: 5bits*/
     UART_DATA_6_BITS = 0x1,    /*!< word length: 6bits*/
@@ -52,6 +55,9 @@ typedef enum {
     UART_DATA_BITS_MAX = 0X4,
 } uart_word_length_t;
 
+/**
+ * @brief UART stop bits number
+ */
 typedef enum {
     UART_STOP_BITS_1   = 0x1,  /*!< stop bit: 1bit*/
     UART_STOP_BITS_1_5 = 0x2,  /*!< stop bit: 1.5bits*/
@@ -59,6 +65,9 @@ typedef enum {
     UART_STOP_BITS_MAX = 0x4,
 } uart_stop_bits_t;
 
+/**
+ * @brief UART peripheral number
+ */
 typedef enum {
     UART_NUM_0 = 0x0,  /*!< UART base address 0x3ff40000*/
     UART_NUM_1 = 0x1,  /*!< UART base address 0x3ff50000*/
@@ -66,12 +75,18 @@ typedef enum {
     UART_NUM_MAX,
 } uart_port_t;
 
+/**
+ * @brief UART parity constants
+ */
 typedef enum {
     UART_PARITY_DISABLE = 0x0,   /*!< Disable UART parity*/
-    UART_PARITY_EVEN = 0x10,     /*!< Enable UART even parity*/
-    UART_PARITY_ODD  = 0x11      /*!< Enable UART odd parity*/
+    UART_PARITY_EVEN = 0x2,     /*!< Enable UART even parity*/
+    UART_PARITY_ODD  = 0x3      /*!< Enable UART odd parity*/
 } uart_parity_t;
 
+/**
+ * @brief UART hardware flow control modes
+ */
 typedef enum {
     UART_HW_FLOWCTRL_DISABLE = 0x0,   /*!< disable hardware flow control*/
     UART_HW_FLOWCTRL_RTS     = 0x1,   /*!< enable RX hardware flow control (rts)*/
@@ -80,6 +95,9 @@ typedef enum {
     UART_HW_FLOWCTRL_MAX     = 0x4,
 } uart_hw_flowcontrol_t;
 
+/**
+ * @brief UART configuration parameters for uart_param_config function
+ */
 typedef struct {
     int baud_rate;                      /*!< UART baudrate*/
     uart_word_length_t data_bits;       /*!< UART byte size*/
@@ -89,6 +107,9 @@ typedef struct {
     uint8_t rx_flow_ctrl_thresh ;       /*!< UART HW RTS threshold*/
 } uart_config_t;
 
+/**
+ * @brief UART interrupt configuration parameters for uart_intr_config function
+ */
 typedef struct {
     uint32_t intr_enable_mask;          /*!< UART interrupt enable mask, choose from UART_XXXX_INT_ENA_M under UART_INT_ENA_REG(i), connect with bit-or operator*/
     uint8_t  rx_timeout_thresh;         /*!< UART timeout interrupt threshold(unit: time of sending one byte)*/
@@ -96,6 +117,9 @@ typedef struct {
     uint8_t  rxfifo_full_thresh;        /*!< UART RX full interrupt threshold.*/
 } uart_intr_config_t;
 
+/**
+ * @brief UART event types used in the ringbuffer
+ */
 typedef enum {
     UART_DATA,              /*!< UART data event*/
     UART_BREAK,             /*!< UART break event*/
@@ -107,17 +131,19 @@ typedef enum {
     UART_EVENT_MAX,         /*!< UART event max index*/
 } uart_event_type_t;
 
+/**
+ * @brief Event structure used in UART event queue
+ */
 typedef struct {
     uart_event_type_t type; /*!< UART event type */
     size_t size;            /*!< UART data size for UART_DATA event*/
 } uart_event_t;
 
 /**
- * @brief   Set UART data bits.
- *
- * @param   uart_no  UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @brief Set UART data bits.
  *
- * @param   data_bit UART data bits
+ * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param data_bit UART data bits
  *
  * @return
  *     - ESP_OK   Success
@@ -126,9 +152,10 @@ typedef struct {
 esp_err_t uart_set_word_length(uart_port_t uart_num, uart_word_length_t data_bit);
 
 /**
- * @brief   Get UART data bits.
+ * @brief Get UART data bits.
  *
- * @param   uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param data_bit Pointer to accept value of UART data bits.
  *
  * @return
  *     - ESP_FAIL  Parameter error
@@ -137,22 +164,22 @@ esp_err_t uart_set_word_length(uart_port_t uart_num, uart_word_length_t data_bit
 esp_err_t uart_get_word_length(uart_port_t uart_num, uart_word_length_t* data_bit);
 
 /**
- * @brief   Set UART stop bits.
+ * @brief Set UART stop bits.
  *
- * @param   uart_no  UART_NUM_0, UART_NUM_1 or UART_NUM_2
- *
- * @param   bit_num  UART stop bits
+ * @param uart_num  UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param bit_num  UART stop bits
  *
  * @return
  *     - ESP_OK   Success
  *     - ESP_FAIL Fail
  */
-esp_err_t uart_set_stop_bits(uart_port_t uart_no, uart_stop_bits_t bit_num);
+esp_err_t uart_set_stop_bits(uart_port_t uart_num, uart_stop_bits_t bit_num);
 
 /**
- * @brief   Set UART stop bits.
+ * @brief Set UART stop bits.
  *
- * @param   uart_no  UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param uart_num  UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param stop_bit  Pointer to accept value of UART stop bits.
  *
  * @return
  *     - ESP_FAIL Parameter error
@@ -161,22 +188,22 @@ esp_err_t uart_set_stop_bits(uart_port_t uart_no, uart_stop_bits_t bit_num);
 esp_err_t uart_get_stop_bits(uart_port_t uart_num, uart_stop_bits_t* stop_bit);
 
 /**
- * @brief   Set UART parity.
- *
- * @param   uart_no     UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @brief Set UART parity.
  *
- * @param   parity_mode the enum of uart parity configuration
+ * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param parity_mode the enum of uart parity configuration
  *
  * @return
  *     - ESP_FAIL  Parameter error
  *     - ESP_OK    Success
  */
-esp_err_t uart_set_parity(uart_port_t uart_no, uart_parity_t parity_mode);
+esp_err_t uart_set_parity(uart_port_t uart_num, uart_parity_t parity_mode);
 
 /**
- * @brief   Get UART parity mode.
+ * @brief Get UART parity mode.
  *
- * @param   uart_no  UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param uart_num  UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param parity_mode Pointer to accept value of UART parity mode.
  *
  * @return
  *     - ESP_FAIL  Parameter error
@@ -186,22 +213,22 @@ esp_err_t uart_set_parity(uart_port_t uart_no, uart_parity_t parity_mode);
 esp_err_t uart_get_parity(uart_port_t uart_num, uart_parity_t* parity_mode);
 
 /**
- * @brief   Set UART baud rate.
+ * @brief Set UART baud rate.
  *
- * @param   uart_no   UART_NUM_0, UART_NUM_1 or UART_NUM_2
- *
- * @param   baud_rate UART baud-rate.
+ * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param baud_rate UART baud-rate.
  *
  * @return
  *     - ESP_FAIL Parameter error
  *     - ESP_OK   Success
  */
-esp_err_t uart_set_baudrate(uart_port_t uart_no, uint32_t baud_rate);
+esp_err_t uart_set_baudrate(uart_port_t uart_num, uint32_t baud_rate);
 
 /**
- * @brief   Get UART bit-rate.
+ * @brief Get UART bit-rate.
  *
- * @param   uart_no: UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param baudrate Pointer to accept value of UART baud rate
  *
  * @return
  *     - ESP_FAIL Parameter error
@@ -211,41 +238,37 @@ esp_err_t uart_set_baudrate(uart_port_t uart_no, uint32_t baud_rate);
 esp_err_t uart_get_baudrate(uart_port_t uart_num, uint32_t* baudrate);
 
 /**
- * @brief   Set UART line inverse mode
- *
- * @param   uart_no  UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @brief Set UART line inverse mode
  *
- * @param   inverse_mask Choose the wires that need to be inversed.
- *
- *          (inverse_mask should be chosen from UART_INVERSE_RXD/UART_INVERSE_TXD/UART_INVERSE_RTS/UART_INVERSE_CTS, combine with OR-OPERATION)
+ * @param uart_num  UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param inverse_mask Choose the wires that need to be inversed.
+ *        Inverse_mask should be chosen from UART_INVERSE_RXD/UART_INVERSE_TXD/UART_INVERSE_RTS/UART_INVERSE_CTS, combine with OR operation.
  *
  * @return
  *     - ESP_OK   Success
  *     - ESP_FAIL Parameter error
  */
-esp_err_t uart_set_line_inverse(uart_port_t uart_no, uint32_t inverse_mask);
+esp_err_t uart_set_line_inverse(uart_port_t uart_num, uint32_t inverse_mask);
 
 /**
- * @brief   Set hardware flow control.
- *
- * @param   uart_no   UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @brief Set hardware flow control.
  *
- * @param   flow_ctrl Hardware flow control mode
- *
- * @param   rx_thresh Threshold of Hardware RX flow control(0 ~ UART_FIFO_LEN)
- *
- *          Only when UART_HW_FLOWCTRL_RTS is set , will the rx_thresh value be set.
+ * @param uart_num   UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param flow_ctrl Hardware flow control mode
+ * @param rx_thresh Threshold of Hardware RX flow control(0 ~ UART_FIFO_LEN).
+ *          Only when UART_HW_FLOWCTRL_RTS is set, will the rx_thresh value be set.
  *
  * @return
  *     - ESP_OK   Success
  *     - ESP_FAIL Parameter error
  */
-esp_err_t uart_set_hw_flow_ctrl(uart_port_t uart_no, uart_hw_flowcontrol_t flow_ctrl, uint8_t rx_thresh);
+esp_err_t uart_set_hw_flow_ctrl(uart_port_t uart_num, uart_hw_flowcontrol_t flow_ctrl, uint8_t rx_thresh);
 
 /**
- * @brief   Get hardware flow control mode
+ * @brief Get hardware flow control mode
  *
- * @param   uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param flow_ctrl Option for different flow control mode.
  *
  * @return
  *     - ESP_FAIL Parameter error
@@ -254,13 +277,11 @@ esp_err_t uart_set_hw_flow_ctrl(uart_port_t uart_no, uart_hw_flowcontrol_t flow_
 esp_err_t uart_get_hw_flow_ctrl(uart_port_t uart_num, uart_hw_flowcontrol_t* flow_ctrl);
 
 /**
- * @brief   Clear UART interrupt status
- *
- * @param   uart_no   UART_NUM_0, UART_NUM_1 or UART_NUM_2
- *
- * @param   clr_mask  Bit mask of the status that to be cleared.
+ * @brief Clear UART interrupt status
  *
- *                    (enable_mask should be chosen from the fields of register UART_INT_CLR_REG)
+ * @param uart_num   UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param clr_mask  Bit mask of the status that to be cleared.
+ *                  enable_mask should be chosen from the fields of register UART_INT_CLR_REG.
  *
  * @return
  *     - ESP_OK   Success
@@ -269,13 +290,11 @@ esp_err_t uart_get_hw_flow_ctrl(uart_port_t uart_num, uart_hw_flowcontrol_t* flo
 esp_err_t uart_clear_intr_status(uart_port_t uart_num, uint32_t clr_mask);
 
 /**
- * @brief   Set UART interrupt enable
+ * @brief Set UART interrupt enable
  *
- * @param   uart_no      UART_NUM_0, UART_NUM_1 or UART_NUM_2
- *
- * @param   enable_mask  Bit mask of the enable bits.
- *
- *                       (enable_mask should be chosen from the fields of register UART_INT_ENA_REG)
+ * @param uart_num      UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param enable_mask  Bit mask of the enable bits.
+ *                     enable_mask should be chosen from the fields of register UART_INT_ENA_REG.
  *
  * @return
  *     - ESP_OK   Success
@@ -284,13 +303,11 @@ esp_err_t uart_clear_intr_status(uart_port_t uart_num, uint32_t clr_mask);
 esp_err_t uart_enable_intr_mask(uart_port_t uart_num, uint32_t enable_mask);
 
 /**
- * @brief   Clear UART interrupt enable bits
- *
- * @param   uart_no       UART_NUM_0, UART_NUM_1 or UART_NUM_2
- *
- * @param   disable_mask  Bit mask of the disable bits.
+ * @brief Clear UART interrupt enable bits
  *
- *                        (disable_mask should be chosen from the fields of register UART_INT_ENA_REG)
+ * @param uart_num       UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param disable_mask  Bit mask of the disable bits.
+ *                      disable_mask should be chosen from the fields of register UART_INT_ENA_REG.
  *
  * @return
  *     - ESP_OK   Success
@@ -300,9 +317,9 @@ esp_err_t uart_disable_intr_mask(uart_port_t uart_num, uint32_t disable_mask);
 
 
 /**
- * @brief   Enable UART RX interrupt(RX_FULL & RX_TIMEOUT INTERRUPT)
+ * @brief Enable UART RX interrupt(RX_FULL & RX_TIMEOUT INTERRUPT)
  *
- * @param   uart_no  UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param uart_num  UART_NUM_0, UART_NUM_1 or UART_NUM_2
  *
  * @return
  *     - ESP_OK   Success
@@ -311,9 +328,9 @@ esp_err_t uart_disable_intr_mask(uart_port_t uart_num, uint32_t disable_mask);
 esp_err_t uart_enable_rx_intr(uart_port_t uart_num);
 
 /**
- * @brief   Disable UART RX interrupt(RX_FULL & RX_TIMEOUT INTERRUPT)
+ * @brief Disable UART RX interrupt(RX_FULL & RX_TIMEOUT INTERRUPT)
  *
- * @param   uart_no  UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param uart_num  UART_NUM_0, UART_NUM_1 or UART_NUM_2
  *
  * @return
  *     - ESP_OK   Success
@@ -322,9 +339,9 @@ esp_err_t uart_enable_rx_intr(uart_port_t uart_num);
 esp_err_t uart_disable_rx_intr(uart_port_t uart_num);
 
 /**
- * @brief   Disable UART TX interrupt(RX_FULL & RX_TIMEOUT INTERRUPT)
+ * @brief Disable UART TX interrupt(RX_FULL & RX_TIMEOUT INTERRUPT)
  *
- * @param   uart_no  UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param uart_num  UART_NUM_0, UART_NUM_1 or UART_NUM_2
  *
  * @return
  *     - ESP_OK   Success
@@ -333,13 +350,11 @@ esp_err_t uart_disable_rx_intr(uart_port_t uart_num);
 esp_err_t uart_disable_tx_intr(uart_port_t uart_num);
 
 /**
- * @brief   Enable UART TX interrupt(RX_FULL & RX_TIMEOUT INTERRUPT)
+ * @brief Enable UART TX interrupt(RX_FULL & RX_TIMEOUT INTERRUPT)
  *
- * @param   uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2
- *
- * @param   enable  1: enable; 0: disable
- *
- * @param   thresh  Threshold of TX interrupt, 0 ~ UART_FIFO_LEN
+ * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param enable  1: enable; 0: disable
+ * @param thresh  Threshold of TX interrupt, 0 ~ UART_FIFO_LEN
  *
  * @return
  *     - ESP_OK   Success
@@ -348,21 +363,18 @@ esp_err_t uart_disable_tx_intr(uart_port_t uart_num);
 esp_err_t uart_enable_tx_intr(uart_port_t uart_num, int enable, int thresh);
 
 /**
-* @brief   register UART interrupt handler(ISR).
-*           @note
- *          UART ISR handler will be attached to the same CPU core that this function is running on.
- *          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.
+ * @brief register UART interrupt handler(ISR).
  *
+ * @note UART ISR handler will be attached to the same CPU core that this function is running on.
+ * 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   uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @attention The ISR handler function MUST be defined with attribution of "IRAM_ATTR" for now.
  *
- * @param   uart_intr_num UART interrupt number,check the info in soc.h, and please refer to core-isa.h for more details
- *
- * @param   fn  Interrupt handler function.
- * @attention
- *          The ISR handler function MUST be defined with attribution of "IRAM_ATTR" for now.
- * @param   arg parameter for handler function
+ * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param uart_intr_num UART interrupt number,check the info in soc.h, and please refer to core-isa.h for more details
+ * @param fn  Interrupt handler function.
+ * @param arg parameter for handler function
  *
  * @return
  *     - ESP_OK   Success
@@ -371,21 +383,16 @@ esp_err_t uart_enable_tx_intr(uart_port_t uart_num, int enable, int thresh);
 esp_err_t uart_isr_register(uart_port_t uart_num, uint8_t uart_intr_num, void (*fn)(void*), void * arg);
 
 /**
- * @brief   Set UART pin number
- *
- *          @note
- *          Internal signal can be output to multiple GPIO pads
- *          Only one GPIO pad can connect with input signal
+ * @brief Set UART pin number
  *
- * @param   uart_no    UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @note Internal signal can be output to multiple GPIO pads.
+ * Only one GPIO pad can connect with input signal.
  *
- * @param   tx_io_num  UART TX pin GPIO number, if set to UART_PIN_NO_CHANGE, use the current pin.
- *
- * @param   rx_io_num  UART RX pin GPIO number, if set to UART_PIN_NO_CHANGE, use the current pin.
- *
- * @param   rts_io_num UART RTS pin GPIO number, if set to UART_PIN_NO_CHANGE, use the current pin.
- *
- * @param   cts_io_num UART CTS pin GPIO number, if set to UART_PIN_NO_CHANGE, use the current pin.
+ * @param uart_num    UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param tx_io_num  UART TX pin GPIO number, if set to UART_PIN_NO_CHANGE, use the current pin.
+ * @param rx_io_num  UART RX pin GPIO number, if set to UART_PIN_NO_CHANGE, use the current pin.
+ * @param rts_io_num UART RTS pin GPIO number, if set to UART_PIN_NO_CHANGE, use the current pin.
+ * @param cts_io_num UART CTS pin GPIO number, if set to UART_PIN_NO_CHANGE, use the current pin.
  *
  * @return
  *     - ESP_OK   Success
@@ -394,12 +401,11 @@ esp_err_t uart_isr_register(uart_port_t uart_num, uint8_t uart_intr_num, void (*
 esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int rts_io_num, int cts_io_num);
 
 /**
- * @brief   UART set RTS level (before inverse)
+ * @brief UART set RTS level (before inverse)
  *          UART rx hardware flow control should not be set.
  *
- * @param   uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2
- *
- * @param   level   1: RTS output low(active); 0: RTS output high(block)
+ * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param level   1: RTS output low(active); 0: RTS output high(block)
  *
  * @return
  *     - ESP_OK   Success
@@ -408,11 +414,10 @@ esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int r
 esp_err_t uart_set_rts(uart_port_t uart_num, int level);
 
 /**
- * @brief   UART set DTR level (before inverse)
+ * @brief UART set DTR level (before inverse)
  *
- * @param   uart_no  UART_NUM_0, UART_NUM_1 or UART_NUM_2
- *
- * @param   level    1: DTR output low; 0: DTR output high
+ * @param uart_num  UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param level    1: DTR output low; 0: DTR output high
  *
  * @return
  *     - ESP_OK   Success
@@ -421,11 +426,10 @@ esp_err_t uart_set_rts(uart_port_t uart_num, int level);
 esp_err_t uart_set_dtr(uart_port_t uart_num, int level);
 
 /**
-* @brief   UART parameter configure
- *
- * @param   uart_no     UART_NUM_0, UART_NUM_1 or UART_NUM_2
+* @brief UART parameter configure
  *
- * @param   uart_config UART parameter settings
+ * @param uart_num     UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param uart_config UART parameter settings
  *
  * @return
  *     - ESP_OK   Success
@@ -434,11 +438,10 @@ esp_err_t uart_set_dtr(uart_port_t uart_num, int level);
 esp_err_t uart_param_config(uart_port_t uart_num, const uart_config_t *uart_config);
 
 /**
-* @brief   UART interrupt configure
+* @brief UART interrupt configure
  *
- * @param   uart_no     UART_NUM_0, UART_NUM_1 or UART_NUM_2
- *
- * @param   intr_conf UART interrupt settings
+ * @param uart_num     UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param intr_conf UART interrupt settings
  *
  * @return
  *     - ESP_OK   Success
@@ -447,25 +450,19 @@ esp_err_t uart_param_config(uart_port_t uart_num, const uart_config_t *uart_conf
 esp_err_t uart_intr_config(uart_port_t uart_num, const uart_intr_config_t *intr_conf);
 
 /**
- * @brief   Install UART driver.
- *
- *          UART ISR handler will be attached to the same CPU core that this function is running on.
- *          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   uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2
- *
- * @param   rx_buffer_size UART RX ring buffer size
- *
- * @param   tx_buffer_size UART TX ring buffer size.
- *
- *          If set to zero, driver will not use TX buffer, TX function will block task until all data have been sent out..
+ * @brief Install UART driver.
  *
- * @param   queue_size UART event queue size/depth.
+ * UART ISR handler will be attached to the same CPU core that this function is running on.
+ * 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   uart_intr_num UART interrupt number,check the info in soc.h, and please refer to core-isa.h for more details
- *
- * @param   uart_queue UART event queue handle, if set NULL, driver will not use an event queue.
+ * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param rx_buffer_size UART RX ring buffer size
+ * @param tx_buffer_size UART TX ring buffer size.
+ *        If set to zero, driver will not use TX buffer, TX function will block task until all data have been sent out..
+ * @param queue_size UART event queue size/depth.
+ * @param uart_intr_num UART interrupt number,check the info in soc.h, and please refer to core-isa.h for more details
+ * @param uart_queue UART event queue handle, if set NULL, driver will not use an event queue.
  *
  * @return
  *     - ESP_OK   Success
@@ -474,9 +471,9 @@ esp_err_t uart_intr_config(uart_port_t uart_num, const uart_intr_config_t *intr_
 esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_buffer_size, int queue_size, int uart_intr_num, void* uart_queue);
 
 /**
- * @brief   Uninstall UART driver.
+ * @brief Uninstall UART driver.
  *
- * @param   uart_no  UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param uart_num  UART_NUM_0, UART_NUM_1 or UART_NUM_2
  *
  * @return
  *     - ESP_OK   Success
@@ -485,11 +482,10 @@ esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_b
 esp_err_t uart_driver_delete(uart_port_t uart_num);
 
 /**
- * @brief   Wait UART TX FIFO empty
- *
- * @param   uart_no       UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @brief Wait UART TX FIFO empty
  *
- * @param   ticks_to_wait Timeout, count in RTOS ticks
+ * @param uart_num       UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param ticks_to_wait Timeout, count in RTOS ticks
  *
  * @return
  *     - ESP_OK   Success
@@ -499,38 +495,33 @@ esp_err_t uart_driver_delete(uart_port_t uart_num);
 esp_err_t uart_wait_tx_done(uart_port_t uart_num, TickType_t ticks_to_wait);
 
 /**
- * @brief   Send data to the UART port from a given buffer and length,
- *          This function will not wait for the space in TX FIFO, just fill the TX FIFO and return when the FIFO is full.
- *          @note
- *          This function should only be used when UART TX buffer is not enabled.
- *
- *
- * @param   uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @brief Send data to the UART port from a given buffer and length.
+ * 
+ * This function will not wait for the space in TX FIFO, just fill the TX FIFO and return when the FIFO is full.
+ * @note This function should only be used when UART TX buffer is not enabled.
  *
- * @param   buffer data buffer address
- *
- * @param   len    data length to send
+ * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param buffer data buffer address
+ * @param len    data length to send
  *
  * @return
  *     - (-1)  Parameter error
  *     - OTHERS(>=0)  The number of data that pushed to the TX FIFO
  */
-int uart_tx_chars(uart_port_t uart_no, const char* buffer, uint32_t len);
+int uart_tx_chars(uart_port_t uart_num, const char* buffer, uint32_t len);
 
 /**
- * @brief   Send data to the UART port from a given buffer and length,
- *
- *          If parameter tx_buffer_size is set to zero:
- *          This function will not return until all the data have been sent out, or at least pushed into TX FIFO.
+ * @brief Send data to the UART port from a given buffer and length,
  *
- *          Otherwise, if tx_buffer_size > 0, this function will return after copying all the data to tx ringbuffer,
- *          then, UART ISR will move data from ring buffer to TX FIFO gradually.
+ * If parameter tx_buffer_size is set to zero:
+ * This function will not return until all the data have been sent out, or at least pushed into TX FIFO.
  *
- * @param   uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * Otherwise, if tx_buffer_size > 0, this function will return after copying all the data to tx ringbuffer,
+ * then, UART ISR will move data from ring buffer to TX FIFO gradually.
  *
- * @param   src   data buffer address
- *
- * @param   size  data length to send
+ * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param src   data buffer address
+ * @param size  data length to send
  *
  * @return
  *     - (-1) Parameter error
@@ -539,25 +530,20 @@ int uart_tx_chars(uart_port_t uart_no, const char* buffer, uint32_t len);
 int uart_write_bytes(uart_port_t uart_num, const char* src, size_t size);
 
 /**
- * @brief   Send data to the UART port from a given buffer and length,
- *
- *          If parameter tx_buffer_size is set to zero:
- *          This function will not return until all the data and the break signal have been sent out.
- *          After all data send out, send a break signal.
+ * @brief Send data to the UART port from a given buffer and length,
  *
- *          Otherwise, if tx_buffer_size > 0, this function will return after copying all the data to tx ringbuffer,
- *          then, UART ISR will move data from ring buffer to TX FIFO gradually.
- *          After all data send out, send a break signal.
+ * If parameter tx_buffer_size is set to zero:
+ * This function will not return until all the data and the break signal have been sent out.
+ * After all data send out, send a break signal.
  *
+ * Otherwise, if tx_buffer_size > 0, this function will return after copying all the data to tx ringbuffer,
+ * then, UART ISR will move data from ring buffer to TX FIFO gradually.
+ * After all data send out, send a break signal.
  *
- *
- * @param   uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2
- *
- * @param   src   data buffer address
- *
- * @param   size  data length to send
- *
- * @param   brk_len break signal length (unit: one bit's time@current_baudrate)
+ * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param src   data buffer address
+ * @param size  data length to send
+ * @param brk_len break signal length (unit: time of one data bit at current_baudrate)
  *
  * @return
  *     - (-1) Parameter error
@@ -567,16 +553,12 @@ int uart_write_bytes(uart_port_t uart_num, const char* src, size_t size);
 int uart_write_bytes_with_break(uart_port_t uart_num, const char* src, size_t size, int brk_len);
 
 /**
-* @brief   UART read bytes from UART buffer
- *
- * @param   uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2
- *
- * @param   buf     pointer to the buffer.
- *
- * @param   length  data length
- *
- * @param   ticks_to_wait sTimeout, count in RTOS ticks
+ * @brief UART read bytes from UART buffer
  *
+ * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param buf     pointer to the buffer.
+ * @param length  data length
+ * @param ticks_to_wait sTimeout, count in RTOS ticks
  *
  * @return
  *     - (-1) Error
@@ -585,9 +567,9 @@ int uart_write_bytes_with_break(uart_port_t uart_num, const char* src, size_t si
 int uart_read_bytes(uart_port_t uart_num, uint8_t* buf, uint32_t length, TickType_t ticks_to_wait);
 
 /**
- * @brief   UART ring buffer flush
+ * @brief UART ring buffer flush
  *
- * @param   uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
  *
  * @return
  *     - ESP_OK Success
@@ -686,13 +668,14 @@ esp_err_t uart_flush(uart_port_t uart_num);
  * {
  *     int uart_num = (int)pvParameters;
  *     uart_event_t event;
- *     uint8_t dtmp[1000];
+ *     size_t size = 1024;
+ *     uint8_t* dtmp = (uint8_t*)malloc(size);
  *     for(;;) {
  *         //Waiting for UART event.
  *         if(xQueueReceive(uart0_queue, (void * )&event, (portTickType)portMAX_DELAY)) {
  *             ESP_LOGI(TAG, "uart[%d] event:", uart_num);
  *             switch(event.type) {
- *                 memset(dtmp, 0, sizeof(dtmp));
+ *                 memset(dtmp, 0, size);
  *                 //Event of UART receving data
  *                 case UART_DATA:
  *                     ESP_LOGI(TAG,"data, len: %d", event.size);
@@ -727,6 +710,8 @@ esp_err_t uart_flush(uart_port_t uart_num);
  *             }
  *        }
  *     }
+ *     free(dtmp);
+ *     dtmp = NULL;
  *     vTaskDelete(NULL);
  * }
  *
@@ -744,13 +729,13 @@ esp_err_t uart_flush(uart_port_t uart_num);
  *     //Set UART parameters
  *     uart_param_config(uart_num, &uart_config);
  *     //Set UART pins,(-1: default pin, no change.)
- *     uart_set_pin(uart_num, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, 15, 13);
+ *     uart_set_pin(uart_num, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
  *     //Set UART log level
  *     esp_log_level_set(TAG, ESP_LOG_INFO);
  *     //Install UART driver, and get the queue.
- *     uart_driver_install(uart_num, 1024 * 2, 1024*4, 10, 17, &uart0_queue, RINGBUF_TYPE_BYTEBUF);
+ *     uart_driver_install(uart_num, 1024 * 2, 1024*4, 10, 17, &uart0_queue);
  *     //Create a task to handler UART event from ISR
- *     xTaskCreate(uart_task, "uTask", 2048*8, (void*)uart_num, 10, NULL);
+ *     xTaskCreate(uart_task, "uTask", 1024, (void*)uart_num, 10, NULL);
  * }
  * @endcode
  *

+ 30 - 11
components/driver/uart.c

@@ -23,11 +23,9 @@
 #include "freertos/task.h"
 #include "freertos/ringbuf.h"
 #include "soc/dport_reg.h"
-#include "rom/ets_sys.h"
 #include "soc/uart_struct.h"
 #include "driver/uart.h"
 #include "driver/gpio.h"
-#include "soc/uart_struct.h"
 
 static const char* UART_TAG = "UART";
 #define UART_CHECK(a, str, ret) if (!(a)) {                                             \
@@ -458,17 +456,20 @@ static void IRAM_ATTR uart_rx_intr_handler_default(void *param)
             uart_reg->int_clr.txfifo_empty = 1;
             UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]);
             if(p_uart->tx_waiting_brk) {
-                return;
+                continue;
             }
             //TX semaphore will only be used when tx_buf_size is zero.
             if(p_uart->tx_waiting_fifo == true && p_uart->tx_buf_size == 0) {
                 p_uart->tx_waiting_fifo = false;
-                xSemaphoreGiveFromISR(p_uart->tx_fifo_sem, NULL);
+                xSemaphoreGiveFromISR(p_uart->tx_fifo_sem, &HPTaskAwoken);
+                if(HPTaskAwoken == pdTRUE) {
+                    portYIELD_FROM_ISR() ;
+                }
             }
             else {
-                //We don't use TX ring buffer, because the size if zero.
+                //We don't use TX ring buffer, because the size is zero.
                 if(p_uart->tx_buf_size == 0) {
-                    return;
+                    continue;
                 }
                 int tx_fifo_rem = UART_FIFO_LEN - UART[uart_num]->status.txfifo_cnt;
                 bool en_tx_flg = false;
@@ -492,6 +493,9 @@ static void IRAM_ATTR uart_rx_intr_handler_default(void *param)
                                 }
                                 //We have saved the data description from the 1st item, return buffer.
                                 vRingbufferReturnItemFromISR(p_uart->tx_ring_buf, p_uart->tx_head, &HPTaskAwoken);
+                                if(HPTaskAwoken == pdTRUE) {
+                                    portYIELD_FROM_ISR() ;
+                                }
                             }else if(p_uart->tx_ptr == NULL) {
                                 //Update the TX item pointer, we will need this to return item to buffer.
                                 p_uart->tx_ptr =  (uint8_t*) p_uart->tx_head;
@@ -501,7 +505,7 @@ static void IRAM_ATTR uart_rx_intr_handler_default(void *param)
                         }
                         else {
                             //Can not get data from ring buffer, return;
-                            return;
+                            break;
                         }
                     }
                     if(p_uart->tx_len_tot > 0 && p_uart->tx_ptr && p_uart->tx_len_cur > 0) {
@@ -516,6 +520,9 @@ static void IRAM_ATTR uart_rx_intr_handler_default(void *param)
                         if(p_uart->tx_len_cur == 0) {
                             //Return item to ring buffer.
                             vRingbufferReturnItemFromISR(p_uart->tx_ring_buf, p_uart->tx_head, &HPTaskAwoken);
+                            if(HPTaskAwoken == pdTRUE) {
+                                portYIELD_FROM_ISR() ;
+                            }
                             p_uart->tx_head = NULL;
                             p_uart->tx_ptr = NULL;
                             //Sending item done, now we need to send break if there is a record.
@@ -529,7 +536,6 @@ static void IRAM_ATTR uart_rx_intr_handler_default(void *param)
                                 uart_reg->int_ena.tx_brk_done = 1;
                                 UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]);
                                 p_uart->tx_waiting_brk = 1;
-                                return;
                             } else {
                                 //enable TX empty interrupt
                                 en_tx_flg = true;
@@ -576,6 +582,9 @@ static void IRAM_ATTR uart_rx_intr_handler_default(void *param)
                 } else {
                     uart_event.type = UART_DATA;
                 }
+                if(HPTaskAwoken == pdTRUE) {
+                    portYIELD_FROM_ISR() ;
+                }
             } else {
                 UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]);
                 uart_reg->int_ena.rxfifo_full = 0;
@@ -594,10 +603,10 @@ static void IRAM_ATTR uart_rx_intr_handler_default(void *param)
         } else if(uart_intr_status & UART_BRK_DET_INT_ST_M) {
             uart_reg->int_clr.brk_det = 1;
             uart_event.type = UART_BREAK;
-        } else if(uart_intr_status & UART_FRM_ERR_INT_ST_M) {
+        } else if(uart_intr_status & UART_PARITY_ERR_INT_ST_M ) {
             uart_reg->int_clr.parity_err = 1;
             uart_event.type = UART_FRAME_ERR;
-        } else if(uart_intr_status & UART_PARITY_ERR_INT_ST_M) {
+        } else if(uart_intr_status & UART_FRM_ERR_INT_ST_M) {
             uart_reg->int_clr.frm_err = 1;
             uart_event.type = UART_PARITY_ERR;
         } else if(uart_intr_status & UART_TX_BRK_DONE_INT_ST_M) {
@@ -614,6 +623,9 @@ static void IRAM_ATTR uart_rx_intr_handler_default(void *param)
                 p_uart->tx_waiting_brk = 0;
             } else {
                 xSemaphoreGiveFromISR(p_uart->tx_brk_sem, &HPTaskAwoken);
+                if(HPTaskAwoken == pdTRUE) {
+                    portYIELD_FROM_ISR() ;
+                }
             }
         } else if(uart_intr_status & UART_TX_BRK_IDLE_DONE_INT_ST_M) {
             UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]);
@@ -626,6 +638,9 @@ static void IRAM_ATTR uart_rx_intr_handler_default(void *param)
             uart_reg->int_clr.tx_done = 1;
             UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]);
             xSemaphoreGiveFromISR(p_uart_obj[uart_num]->tx_done_sem, &HPTaskAwoken);
+            if(HPTaskAwoken == pdTRUE) {
+                portYIELD_FROM_ISR() ;
+            }
         }
         else {
             uart_reg->int_clr.val = uart_intr_status; /*simply clear all other intr status*/
@@ -634,6 +649,9 @@ static void IRAM_ATTR uart_rx_intr_handler_default(void *param)
 
         if(uart_event.type != UART_EVENT_MAX && p_uart->xQueueUart) {
             xQueueSendFromISR(p_uart->xQueueUart, (void * )&uart_event, &HPTaskAwoken);
+            if(HPTaskAwoken == pdTRUE) {
+                portYIELD_FROM_ISR() ;
+            }
         }
         uart_intr_status = uart_reg->int_st.val;
     }
@@ -946,7 +964,8 @@ esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_b
                             | UART_RXFIFO_TOUT_INT_ENA_M
                             | UART_FRM_ERR_INT_ENA_M
                             | UART_RXFIFO_OVF_INT_ENA_M
-                            | UART_BRK_DET_INT_ENA_M,
+                            | UART_BRK_DET_INT_ENA_M
+                            | UART_PARITY_ERR_INT_ENA_M,
         .rxfifo_full_thresh = UART_FULL_THRESH_DEFAULT,
         .rx_timeout_thresh = UART_TOUT_THRESH_DEFAULT,
         .txfifo_empty_intr_thresh = UART_EMPTY_THRESH_DEFAULT

+ 1 - 3
components/esp32/component.mk

@@ -17,9 +17,7 @@ COMPONENT_ADD_LDFLAGS := -lesp32 \
 
 ALL_LIB_FILES := $(patsubst %,$(COMPONENT_PATH)/lib/lib%.a,$(LIBS))
 
-# automatically trigger a git submodule update
-# if any libraries are missing
-$(eval $(call SubmoduleCheck,$(ALL_LIB_FILES),$(COMPONENT_PATH)/lib))
+COMPONENT_SUBMODULES += lib
 
 # this is a hack to make sure the app is re-linked if the binary
 # libraries change or are updated. If they change, the main esp32

+ 209 - 224
components/esp32/include/esp_wifi.h

@@ -88,6 +88,9 @@ extern "C" {
 #define ESP_ERR_WIFI_PASSWORD    (ESP_ERR_WIFI_BASE + 10)  /*!< Passord is invalid */
 #define ESP_ERR_WIFI_TIMEOUT     (ESP_ERR_WIFI_BASE + 11)  /*!< Timeout error */
 
+/**
+ * @brief WiFi stack configuration parameters passed to esp_wifi_init call.
+ */
 typedef struct {
     system_event_handler_t event_handler;  /**< WiFi event handler */
 } wifi_init_config_t;
@@ -108,12 +111,12 @@ typedef struct {
   *               will post station connected event to this queue. If the queue is not initialized, WiFi
   *               will not post any events
   *
-  * @param  wifi_init_config_t *config : provide WiFi init configuration
+  * @param  config provide WiFi init configuration
   *
   * @return
-  *    - ESP_OK : succeed
-  *    - ESP_ERR_WIFI_NO_MEM : out of memory
-  *    - others : refer to error code esp_err.h 
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NO_MEM: out of memory
+  *    - others: refer to error code esp_err.h 
   */
 esp_err_t esp_wifi_init(wifi_init_config_t *config);
 
@@ -123,7 +126,7 @@ esp_err_t esp_wifi_init(wifi_init_config_t *config);
   *
   * @attention 1. This API should be called if you want to remove WiFi driver from the system
   *
-  * @return ESP_OK : succeed
+  * @return ESP_OK: succeed
   */
 esp_err_t esp_wifi_deinit(void);
 
@@ -133,25 +136,25 @@ esp_err_t esp_wifi_deinit(void);
   *            Set the WiFi operating mode as station, soft-AP or station+soft-AP,
   *            The default mode is soft-AP mode.
   *
-  * @param     wifi_mode_t mode : WiFi operating modes:
+  * @param     mode  WiFi operating mode
   *
   * @return
-  *    - ESP_OK : succeed
-  *    - ESP_ERR_WIFI_NOT_INIT : WiFi is not initialized by eps_wifi_init
-  *    - ESP_ERR_WIFI_ARG : invalid argument
-  *    - others : refer to error code in esp_err.h
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
+  *    - ESP_ERR_WIFI_ARG: invalid argument
+  *    - others: refer to error code in esp_err.h
   */
 esp_err_t esp_wifi_set_mode(wifi_mode_t mode);
 
 /**
   * @brief  Get current operating mode of WiFi
   *
-  * @param  wifi_mode_t *mode : store current WiFi mode
+  * @param[out]  mode  store current WiFi mode
   *
   * @return
-  *    - ESP_OK : succeed
-  *    - ESP_ERR_WIFI_NOT_INIT : WiFi is not initialized by eps_wifi_init
-  *    - ESP_ERR_WIFI_ARG : invalid argument
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
+  *    - ESP_ERR_WIFI_ARG: invalid argument
   */
 esp_err_t esp_wifi_get_mode(wifi_mode_t *mode);
 
@@ -161,29 +164,25 @@ esp_err_t esp_wifi_get_mode(wifi_mode_t *mode);
   *         If mode is WIFI_MODE_AP, it create soft-AP control block and start soft-AP
   *         If mode is WIFI_MODE_APSTA, it create soft-AP and station control block and start soft-AP and station
   *
-  * @param  null
-  *
   * @return
-  *    - ESP_OK : succeed
-  *    - ESP_ERR_WIFI_NOT_INIT : WiFi is not initialized by eps_wifi_init
-  *    - ESP_ERR_WIFI_ARG : invalid argument
-  *    - ESP_ERR_WIFI_NO_MEM : out of memory
-  *    - ESP_ERR_WIFI_CONN : WiFi internal error, station or soft-AP control block wrong
-  *    - ESP_ERR_WIFI_FAIL : other WiFi internal errors
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
+  *    - ESP_ERR_WIFI_ARG: invalid argument
+  *    - ESP_ERR_WIFI_NO_MEM: out of memory
+  *    - ESP_ERR_WIFI_CONN: WiFi internal error, station or soft-AP control block wrong
+  *    - ESP_ERR_WIFI_FAIL: other WiFi internal errors
   */
 esp_err_t esp_wifi_start(void);
 
 /**
   * @brief  Stop WiFi
-            If mode is WIFI_MODE_STA, it stop station and free station control block
+  *         If mode is WIFI_MODE_STA, it stop station and free station control block
   *         If mode is WIFI_MODE_AP, it stop soft-AP and free soft-AP control block
   *         If mode is WIFI_MODE_APSTA, it stop station/soft-AP and free station/soft-AP control block
   *
-  * @param  null
-  *
   * @return
-  *    - ESP_OK : succeed
-  *    - ESP_ERR_WIFI_NOT_INIT : WiFi is not initialized by eps_wifi_init
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
   */
 esp_err_t esp_wifi_stop(void);
 
@@ -193,52 +192,47 @@ esp_err_t esp_wifi_stop(void);
   * @attention 1. This API only impact WIFI_MODE_STA or WIFI_MODE_APSTA mode
   * @attention 2. If the ESP32 is connected to an AP, call esp_wifi_disconnect to disconnect.
   *
-  * @param     null
-  *
   * @return 
-  *    - ESP_OK : succeed
-  *    - ESP_ERR_WIFI_NOT_INIT  : WiFi is not initialized by eps_wifi_init
-  *    - ESP_ERR_WIFI_NOT_START : WiFi is not started by esp_wifi_start
-  *    - ESP_ERR_WIFI_CONN : WiFi internal error, station or soft-AP control block wrong
-  *    - ESP_ERR_WIFI_SSID : SSID of AP which station connects is invalid
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
+  *    - ESP_ERR_WIFI_NOT_START: WiFi is not started by esp_wifi_start
+  *    - ESP_ERR_WIFI_CONN: WiFi internal error, station or soft-AP control block wrong
+  *    - ESP_ERR_WIFI_SSID: SSID of AP which station connects is invalid
   */
 esp_err_t esp_wifi_connect(void);
 
 /**
   * @brief     Disconnect the ESP32 WiFi station from the AP.
   *
-  * @param     null
-  *
   * @return
-  *    - ESP_OK : succeed
-  *    - ESP_ERR_WIFI_NOT_INIT  : WiFi is not initialized by eps_wifi_init
-  *    - ESP_ERR_WIFI_NOT_START : WiFi is not started by esp_wifi_start
-  *    - ESP_ERR_WIFI_FAIL : other WiFi internal errors
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
+  *    - ESP_ERR_WIFI_NOT_START: WiFi is not started by esp_wifi_start
+  *    - ESP_ERR_WIFI_FAIL: other WiFi internal errors
   */
 esp_err_t esp_wifi_disconnect(void);
 
 /**
   * @brief     Currently this API is just an stub API
   *
-  * @param     null
-  *
+
   * @return
-  *    - ESP_OK : succeed
-  *    - others : fail
+  *    - ESP_OK: succeed
+  *    - others: fail
   */
 esp_err_t esp_wifi_clear_fast_connect(void);
 
 /**
   * @brief     deauthenticate all stations or associated id equals to aid
   *
-  * @param     uint16_t aid : when aid is 0, deauthenticate all stations, otherwise deauthenticate station whose associated id is aid
+  * @param     aid  when aid is 0, deauthenticate all stations, otherwise deauthenticate station whose associated id is aid
   *
   * @return
-  *    - ESP_OK : succeed
-  *    - ESP_ERR_WIFI_NOT_INIT  : WiFi is not initialized by eps_wifi_init
-  *    - ESP_ERR_WIFI_NOT_START : WiFi is not started by esp_wifi_start
-  *    - ESP_ERR_WIFI_ARG : invalid argument
-  *    - ESP_ERR_WIFI_MODE : WiFi mode is wrong
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
+  *    - ESP_ERR_WIFI_NOT_START: WiFi is not started by esp_wifi_start
+  *    - ESP_ERR_WIFI_ARG: invalid argument
+  *    - ESP_ERR_WIFI_MODE: WiFi mode is wrong
   */
 esp_err_t esp_wifi_deauth_sta(uint16_t aid);
 
@@ -249,88 +243,87 @@ esp_err_t esp_wifi_deauth_sta(uint16_t aid);
   *            will be freed in esp_wifi_get_ap_list, so generally, call esp_wifi_get_ap_list to cause
   *            the memory to be freed once the scan is done
   *
-  * @param     struct scan_config *config : configuration of scanning
-  * @param     bool block : if block is true, this API will block the caller until the scan is done, otherwise
+  * @param     config  configuration of scanning
+  * @param     block if block is true, this API will block the caller until the scan is done, otherwise
   *                         it will return immediately
   *
   * @return
-  *    - ESP_OK : succeed
-  *    - ESP_ERR_WIFI_NOT_INIT  : WiFi is not initialized by eps_wifi_init
-  *    - ESP_ERR_WIFI_NOT_START : WiFi is not started by esp_wifi_start
-  *    - ESP_ERR_WIFI_TIMEOUT : blocking scan is timeout
-  *    - others : refer to error code in esp_err.h
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
+  *    - ESP_ERR_WIFI_NOT_START: WiFi is not started by esp_wifi_start
+  *    - ESP_ERR_WIFI_TIMEOUT: blocking scan is timeout
+  *    - others: refer to error code in esp_err.h
   */
-esp_err_t esp_wifi_scan_start(wifi_scan_config_t *conf, bool block);
+esp_err_t esp_wifi_scan_start(wifi_scan_config_t *config, bool block);
 
 /**
   * @brief     Stop the scan in process
   *
-  * @param     null
   * @return
-  *    - ESP_OK : succeed
-  *    - ESP_ERR_WIFI_NOT_INIT  : WiFi is not initialized by eps_wifi_init
-  *    - ESP_ERR_WIFI_NOT_START : WiFi is not started by esp_wifi_start
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
+  *    - ESP_ERR_WIFI_NOT_START: WiFi is not started by esp_wifi_start
   */
 esp_err_t esp_wifi_scan_stop(void);
 
 /**
   * @brief     Get number of APs found in last scan
   *
-  * @param     uint16_t *number : store number of APIs found in last scan
+  * @param[out] number  store number of APIs found in last scan
   *
-  * @attention This API can only be called when the scan is completed, otherwise it may get wrong value
+  * @attention This API can only be called when the scan is completed, otherwise it may get wrong value.
   *
   * @return
-  *    - ESP_OK : succeed
-  *    - ESP_ERR_WIFI_NOT_INIT  : WiFi is not initialized by eps_wifi_init
-  *    - ESP_ERR_WIFI_NOT_START : WiFi is not started by esp_wifi_start
-  *    - ESP_ERR_WIFI_ARG : invalid argument
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
+  *    - ESP_ERR_WIFI_NOT_START: WiFi is not started by esp_wifi_start
+  *    - ESP_ERR_WIFI_ARG: invalid argument
   */
 esp_err_t esp_wifi_scan_get_ap_num(uint16_t *number);
 
 /**
   * @brief     Get AP list found in last scan
   *
-  * @param     uint16_t *number : as input param, it stores max AP number ap_records can hold, as output param, it store
-                                  the actual AP number this API returns
-  * @param     wifi_ap_record_t *ap_records: wifi_ap_record_t array to hold the found APs
+  * @param[inout]  number As input param, it stores max AP number ap_records can hold. 
+  *                As output param, it receives the actual AP number this API returns.
+  * @param         ap_records  wifi_ap_record_t array to hold the found APs
   *
   * @return
-  *    - ESP_OK : succeed
-  *    - ESP_ERR_WIFI_NOT_INIT  : WiFi is not initialized by eps_wifi_init
-  *    - ESP_ERR_WIFI_NOT_START : WiFi is not started by esp_wifi_start
-  *    - ESP_ERR_WIFI_ARG : invalid argument
-  *    - ESP_ERR_WIFI_NO_MEM : out of memory
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
+  *    - ESP_ERR_WIFI_NOT_START: WiFi is not started by esp_wifi_start
+  *    - ESP_ERR_WIFI_ARG: invalid argument
+  *    - ESP_ERR_WIFI_NO_MEM: out of memory
   */
 esp_err_t esp_wifi_scan_get_ap_records(uint16_t *number, wifi_ap_record_t *ap_records);
 
 
 /**
-  * @brief     Get information of AP associated with ESP32 station
+  * @brief     Get information of AP which the ESP32 station is associated with
   *
-  * @param     wifi_ap_record_t *ap_info: the wifi_ap_record_t to hold station assocated AP
+  * @param     ap_info  the wifi_ap_record_t to hold AP information
   *
   * @return
-  *    - ESP_OK : succeed
-  *    - others : fail
+  *    - ESP_OK: succeed
+  *    - others: fail
   */
 esp_err_t esp_wifi_sta_get_ap_info(wifi_ap_record_t *ap_info);
 
 /**
   * @brief     Set current power save type
   *
-  * @param     wifi_ps_type_t type : power save type
+  * @param     type  power save type
   *
-  * @return    ESP_ERR_WIFI_NOT_SUPPORT : not support yet
+  * @return    ESP_ERR_WIFI_NOT_SUPPORT: not supported yet
   */
 esp_err_t esp_wifi_set_ps(wifi_ps_type_t type);
 
 /**
   * @brief     Get current power save type
   *
-  * @param     wifi_ps_type_t *type : store current power save type
+  * @param[out]  type: store current power save type
   *
-  * @return    ESP_ERR_WIFI_NOT_SUPPORT : not support yet
+  * @return    ESP_ERR_WIFI_NOT_SUPPORT: not supported yet
   */
 esp_err_t esp_wifi_get_ps(wifi_ps_type_t *type);
 
@@ -340,47 +333,47 @@ esp_err_t esp_wifi_get_ps(wifi_ps_type_t *type);
   *
   * @attention Currently we only support 802.11b or 802.11bg or 802.11bgn mode
   *
-  * @param     wifi_interface_t ifx : interfaces
-  * @param     uint8_t protocol : WiFi protocol bitmap
+  * @param     ifx  interfaces
+  * @param     protocol_bitmap  WiFi protocol bitmap
   *
   * @return
-  *    - ESP_OK : succeed
-  *    - ESP_ERR_WIFI_NOT_INIT  : WiFi is not initialized by eps_wifi_init
-  *    - ESP_ERR_WIFI_IF : invalid interface
-  *    - others : refer to erro code in esp_err.h
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
+  *    - ESP_ERR_WIFI_IF: invalid interface
+  *    - others: refer to error codes in esp_err.h
   */
 esp_err_t esp_wifi_set_protocol(wifi_interface_t ifx, uint8_t protocol_bitmap);
 
 /**
-  * @brief     Get the current protocol bitmap of specified ifx
+  * @brief     Get the current protocol bitmap of the specified interface
   *
-  * @param     wifi_interface_t ifx : interfaces
-  * @param     uint8_t protocol : store current WiFi protocol bitmap of interface ifx
+  * @param     ifx  interface
+  * @param[out] protocol_bitmap  store current WiFi protocol bitmap of interface ifx
   *
   * @return
-  *    - ESP_OK : succeed
-  *    - ESP_ERR_WIFI_NOT_INIT  : WiFi is not initialized by eps_wifi_init
-  *    - ESP_ERR_WIFI_IF : invalid interface
-  *    - ESP_ERR_WIFI_ARG : invalid argument
-  *    - others : refer to error code in esp_err.h
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
+  *    - ESP_ERR_WIFI_IF: invalid interface
+  *    - ESP_ERR_WIFI_ARG: invalid argument
+  *    - others: refer to error codes in esp_err.h
   */
 esp_err_t esp_wifi_get_protocol(wifi_interface_t ifx, uint8_t *protocol_bitmap);
 
 /**
   * @brief     Set the bandwidth of ESP32 specified interface
   *
-  * @attention 1. API return false if try to configure a interface that is not enable
+  * @attention 1. API return false if try to configure an interface that is not enabled
   * @attention 2. WIFI_BW_HT40 is supported only when the interface support 11N
   *
-  * @param     wifi_interface_t ifx : interface to be configured
-  * @param     wifi_bandwidth_t bw : bandwidth
+  * @param     ifx  interface to be configured
+  * @param     bw  bandwidth
   *
   * @return
-  *    - ESP_OK : succeed
-  *    - ESP_ERR_WIFI_NOT_INIT  : WiFi is not initialized by eps_wifi_init
-  *    - ESP_ERR_WIFI_IF : invalid interface
-  *    - ESP_ERR_WIFI_ARG : invalid argument
-  *    - others : refer to error code in esp_err.h
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
+  *    - ESP_ERR_WIFI_IF: invalid interface
+  *    - ESP_ERR_WIFI_ARG: invalid argument
+  *    - others: refer to error codes in esp_err.h
   */
 esp_err_t esp_wifi_set_bandwidth(wifi_interface_t ifx, wifi_bandwidth_t bw);
 
@@ -389,45 +382,45 @@ esp_err_t esp_wifi_set_bandwidth(wifi_interface_t ifx, wifi_bandwidth_t bw);
   *
   * @attention 1. API return false if try to get a interface that is not enable
   *
-  * @param     wifi_interface_t ifx : interface to be configured
-  * @param     wifi_bandwidth_t *bw : store bandwidth  of interface ifx
+  * @param     ifx interface to be configured
+  * @param[out] bw  store bandwidth of interface ifx
   *
   * @return
-  *    - ESP_OK : succeed
-  *    - ESP_ERR_WIFI_NOT_INIT  : WiFi is not initialized by eps_wifi_init
-  *    - ESP_ERR_WIFI_IF : invalid interface
-  *    - ESP_ERR_WIFI_ARG : invalid argument
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
+  *    - ESP_ERR_WIFI_IF: invalid interface
+  *    - ESP_ERR_WIFI_ARG: invalid argument
   */
 esp_err_t esp_wifi_get_bandwidth(wifi_interface_t ifx, wifi_bandwidth_t *bw);
 
 /**
-  * @brief     Set primary/second channel of ESP32
+  * @brief     Set primary/secondary channel of ESP32
   *
   * @attention 1. This is a special API for sniffer
   *
-  * @param     uint8_t primary : for HT20, primary is the channel number, for HT40, primary is the primary channel
-  * @param     wifi_second_chan_t second : for HT20, second is ignored, for HT40, second is the second channel
+  * @param     primary  for HT20, primary is the channel number, for HT40, primary is the primary channel
+  * @param     second   for HT20, second is ignored, for HT40, second is the second channel
   *
   * @return
-  *    - ESP_OK : succeed
-  *    - ESP_ERR_WIFI_NOT_INIT  : WiFi is not initialized by eps_wifi_init
-  *    - ESP_ERR_WIFI_IF : invalid interface
-  *    - ESP_ERR_WIFI_ARG : invalid argument
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
+  *    - ESP_ERR_WIFI_IF: invalid interface
+  *    - ESP_ERR_WIFI_ARG: invalid argument
   */
 esp_err_t esp_wifi_set_channel(uint8_t primary, wifi_second_chan_t second);
 
 /**
-  * @brief     Get the primary/second channel of ESP32
+  * @brief     Get the primary/secondary channel of ESP32
   *
   * @attention 1. API return false if try to get a interface that is not enable
   *
-  * @param     uint8_t *primary : store current primary channel
-  * @param     wifi_second_chan_t *second : store current second channel
+  * @param     primary   store current primary channel
+  * @param[out]  second  store current second channel
   *
   * @return
-  *    - ESP_OK : succeed
-  *    - ESP_ERR_WIFI_NOT_INIT  : WiFi is not initialized by eps_wifi_init
-  *    - ESP_ERR_WIFI_ARG : invalid argument
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
+  *    - ESP_ERR_WIFI_ARG: invalid argument
   */
 esp_err_t esp_wifi_get_channel(uint8_t *primary, wifi_second_chan_t *second);
 
@@ -435,25 +428,25 @@ esp_err_t esp_wifi_get_channel(uint8_t *primary, wifi_second_chan_t *second);
   * @brief     Set country code
   *            The default value is WIFI_COUNTRY_CN
   *
-  * @param     wifi_country_t country : country type
+  * @param     country  country type
   *
   * @return
-  *    - ESP_OK : succeed
-  *    - ESP_ERR_WIFI_NOT_INIT  : WiFi is not initialized by eps_wifi_init
-  *    - ESP_ERR_WIFI_ARG : invalid argument
-  *    - others : refer to error code in esp_err.h
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
+  *    - ESP_ERR_WIFI_ARG: invalid argument
+  *    - others: refer to error code in esp_err.h
   */
 esp_err_t esp_wifi_set_country(wifi_country_t country);
 
 /**
   * @brief     Get country code
   *
-  * @param     wifi_country_t country : store current country
+  * @param     country  store current country
   *
   * @return
-  *    - ESP_OK : succeed
-  *    - ESP_ERR_WIFI_NOT_INIT  : WiFi is not initialized by eps_wifi_init
-  *    - ESP_ERR_WIFI_ARG : invalid argument
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
+  *    - ESP_ERR_WIFI_ARG: invalid argument
   */
 esp_err_t esp_wifi_get_country(wifi_country_t *country);
 
@@ -462,43 +455,44 @@ esp_err_t esp_wifi_get_country(wifi_country_t *country);
   *
   * @attention 1. This API can only be called when the interface is disabled
   * @attention 2. ESP32 soft-AP and station have different MAC addresses, do not set them to be the same.
-  *    - The bit0 of the first byte of ESP32 MAC address can not be 1. For example, the MAC address
+  * @attention 3. The bit 0 of the first byte of ESP32 MAC address can not be 1. For example, the MAC address
   *      can set to be "1a:XX:XX:XX:XX:XX", but can not be "15:XX:XX:XX:XX:XX".
   *
-  * @param     wifi_interface_t ifx : interface
-  * @param     uint8 mac[6]: the MAC address.
+  * @param     ifx  interface
+  * @param     mac  the MAC address
   *
   * @return
-  *    - ESP_OK : succeed
-  *    - ESP_ERR_WIFI_NOT_INIT  : WiFi is not initialized by eps_wifi_init
-  *    - ESP_ERR_WIFI_ARG : invalid argument
-  *    - ESP_ERR_WIFI_IF : invalid interface
-  *    - ESP_ERR_WIFI_MAC : invalid mac address
-  *    - ESP_ERR_WIFI_MODE : WiFi mode is wrong
-  *    - others : refer to error code in esp_err.h
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
+  *    - ESP_ERR_WIFI_ARG: invalid argument
+  *    - ESP_ERR_WIFI_IF: invalid interface
+  *    - ESP_ERR_WIFI_MAC: invalid mac address
+  *    - ESP_ERR_WIFI_MODE: WiFi mode is wrong
+  *    - others: refer to error codes in esp_err.h
   */
 esp_err_t esp_wifi_set_mac(wifi_interface_t ifx, uint8_t mac[6]);
 
 /**
   * @brief     Get mac of specified interface
   *
-  * @param     uint8_t mac[6] : store mac of this interface ifx
+  * @param      ifx  interface
+  * @param[out] mac  store mac of the interface ifx
   *
   * @return
-  *    - ESP_OK : succeed
-  *    - ESP_ERR_WIFI_NOT_INIT  : WiFi is not initialized by eps_wifi_init
-  *    - ESP_ERR_WIFI_ARG : invalid argument
-  *    - ESP_ERR_WIFI_IF : invalid interface
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
+  *    - ESP_ERR_WIFI_ARG: invalid argument
+  *    - ESP_ERR_WIFI_IF: invalid interface
   */
 esp_err_t esp_wifi_get_mac(wifi_interface_t ifx, uint8_t mac[6]);
 
 /**
   * @brief The RX callback function in the promiscuous mode.
   *
-  *        Each time a packet is received, the callback function will be called.
+  * Each time a packet is received, the callback function will be called.
   *
-  * @param void *buf : the data received
-  * @param uint16_t len : data length
+  * @param buf  the data received
+  * @param len  data length
   *
   * @return    none
   */
@@ -507,36 +501,36 @@ typedef void (* wifi_promiscuous_cb_t)(void *buf, uint16_t len);
 /**
   * @brief Register the RX callback function in the promiscuous mode.
   *
-  *        Each time a packet is received, the registered callback function will be called.
+  * Each time a packet is received, the registered callback function will be called.
   *
-  * @param wifi_promiscuous_cb_t cb : callback
+  * @param cb  callback
   *
   * @return
-  *    - ESP_OK : succeed
-  *    - ESP_ERR_WIFI_NOT_INIT  : WiFi is not initialized by eps_wifi_init
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
   */
 esp_err_t esp_wifi_set_promiscuous_rx_cb(wifi_promiscuous_cb_t cb);
 
 /**
   * @brief     Enable the promiscuous mode.
   *
-  * @param     bool promiscuous : false - disable / true - enable
+  * @param     en  false - disable, true - enable
   *
   * @return
-  *    - ESP_OK : succeed
-  *    - ESP_ERR_WIFI_NOT_INIT  : WiFi is not initialized by eps_wifi_init
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
   */
 esp_err_t esp_wifi_set_promiscuous(bool en);
 
 /**
   * @brief     Get the promiscuous mode.
   *
-  * @param     bool *enable : store the current status of promiscuous mode
+  * @param[out] en  store the current status of promiscuous mode
   *
   * @return
-  *    - ESP_OK : succeed
-  *    - ESP_ERR_WIFI_NOT_INIT  : WiFi is not initialized by eps_wifi_init
-  *    - ESP_ERR_WIFI_ARG : invalid argument
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
+  *    - ESP_ERR_WIFI_ARG: invalid argument
   */
 esp_err_t esp_wifi_get_promiscuous(bool *en);
 
@@ -548,32 +542,32 @@ esp_err_t esp_wifi_get_promiscuous(bool *en);
   * @attention 3. ESP32 is limited to only one channel, so when in the soft-AP+station mode, the soft-AP will adjust its channel automatically to be the same as
   *               the channel of the ESP32 station.
   *
-  * @param     wifi_interface_t ifx : interface
-  * @param     wifi_config_t *conf : station or soft-AP configuration
+  * @param     ifx  interface
+  * @param     conf  station or soft-AP configuration
   *
   * @return
-  *    - ESP_OK : succeed
-  *    - ESP_ERR_WIFI_NOT_INIT : WiFi is not initialized by eps_wifi_init
-  *    - ESP_ERR_WIFI_ARG : invalid argument
-  *    - ESP_ERR_WIFI_IF : invalid interface
-  *    - ESP_ERR_WIFI_MODE : invalid mode
-  *    - ESP_ERR_WIFI_PASSWORD : invalid password
-  *    - ESP_ERR_WIFI_NVS : WiFi internal NVS error
-  *    - others : refer to the erro code in esp_err.h
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
+  *    - ESP_ERR_WIFI_ARG: invalid argument
+  *    - ESP_ERR_WIFI_IF: invalid interface
+  *    - ESP_ERR_WIFI_MODE: invalid mode
+  *    - ESP_ERR_WIFI_PASSWORD: invalid password
+  *    - ESP_ERR_WIFI_NVS: WiFi internal NVS error
+  *    - others: refer to the erro code in esp_err.h
   */
 esp_err_t esp_wifi_set_config(wifi_interface_t ifx, wifi_config_t *conf);
 
 /**
   * @brief     Get configuration of specified interface
   *
-  * @param     wifi_interface_t ifx : interface
-  * @param     wifi_config_t *conf : station or soft-AP configuration
+  * @param     ifx  interface
+  * @param[out]  conf  station or soft-AP configuration
   *
   * @return
-  *    - ESP_OK : succeed
-  *    - ESP_ERR_WIFI_NOT_INIT : WiFi is not initialized by eps_wifi_init
-  *    - ESP_ERR_WIFI_ARG : invalid argument
-  *    - ESP_ERR_WIFI_IF : invalid interface
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
+  *    - ESP_ERR_WIFI_ARG: invalid argument
+  *    - ESP_ERR_WIFI_IF: invalid interface
   */
 esp_err_t esp_wifi_get_config(wifi_interface_t ifx, wifi_config_t *conf);
 
@@ -582,14 +576,14 @@ esp_err_t esp_wifi_get_config(wifi_interface_t ifx, wifi_config_t *conf);
   *
   * @attention SSC only API
   *
-  * @param     wifi_sta_list_t *sta:  station list
+  * @param[out] sta  station list
   *
   * @return
-  *    - ESP_OK : succeed
-  *    - ESP_ERR_WIFI_NOT_INIT : WiFi is not initialized by eps_wifi_init
-  *    - ESP_ERR_WIFI_ARG : invalid argument
-  *    - ESP_ERR_WIFI_MODE : WiFi mode is wrong
-  *    - ESP_ERR_WIFI_CONN : WiFi internal error, the station/soft-AP control block is invalid
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
+  *    - ESP_ERR_WIFI_ARG: invalid argument
+  *    - ESP_ERR_WIFI_MODE: WiFi mode is wrong
+  *    - ESP_ERR_WIFI_CONN: WiFi internal error, the station/soft-AP control block is invalid
   */
 esp_err_t esp_wifi_ap_get_sta_list(wifi_sta_list_t *sta);
 
@@ -599,12 +593,12 @@ esp_err_t esp_wifi_ap_get_sta_list(wifi_sta_list_t *sta);
   *
   * @attention 1. The default value is WIFI_STORAGE_FLASH
   *
-  * @param     wifi_storage_t storage : storage type
+  * @param     storage : storage type
   *
   * @return
-  *   - ESP_OK : succeed
-  *   - ESP_ERR_WIFI_NOT_INIT : WiFi is not initialized by eps_wifi_init
-  *   - ESP_ERR_WIFI_ARG : invalid argument
+  *   - ESP_OK: succeed
+  *   - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
+  *   - ESP_ERR_WIFI_ARG: invalid argument
   */
 esp_err_t esp_wifi_set_storage(wifi_storage_t storage);
 
@@ -612,72 +606,63 @@ esp_err_t esp_wifi_set_storage(wifi_storage_t storage);
   * @brief     Set auto connect
   *            The default value is true
   *
-  * @param     bool en : true - enable auto connect / false - disable auto connect
+  * @param     en : true - enable auto connect / false - disable auto connect
   *
   * @return
-  *    - ESP_OK : succeed
-  *    - ESP_ERR_WIFI_NOT_INIT : WiFi is not initialized by eps_wifi_init
-  *    - ESP_ERR_WIFI_MODE : WiFi internal error, the station/soft-AP control block is invalid
-  *    - others : refer to error code in esp_err.h
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
+  *    - ESP_ERR_WIFI_MODE: WiFi internal error, the station/soft-AP control block is invalid
+  *    - others: refer to error code in esp_err.h
   */
 esp_err_t esp_wifi_set_auto_connect(bool en);
 
 /**
   * @brief     Get the auto connect flag
   *
-  * @param     bool *en : store current auto connect configuration
+  * @param[out] en  store current auto connect configuration
   *
   * @return
-  *    - ESP_OK : succeed
-  *    - ESP_ERR_WIFI_NOT_INIT : WiFi is not initialized by eps_wifi_init
-  *    - ESP_ERR_WIFI_ARG : invalid argument
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
+  *    - ESP_ERR_WIFI_ARG: invalid argument
   */
 esp_err_t esp_wifi_get_auto_connect(bool *en);
 
 /**
   * @brief     Set vendor specific element
   *
-  * @param     bool enable : enable or not
-  * @param     wifi_vendor_ie_type_t type : 0 - WIFI_VND_IE_TYPE_BEACON
-  *                           1 - WIFI_VND_IE_TYPE_PROBE_REQ
-  *                           2 - WIFI_VND_IE_TYPE_PROBE_RESP
-  *                           3 - WIFI_VND_IE_TYPE_ASSOC_REQ
-  *                           4 - WIFI_VND_IE_TYPE_ASSOC_RESP
-  * @param     wifi_vendor_ie_id_t idx : 0 - WIFI_VND_IE_ID_0
-                                    1 - WIFI_VND_IE_ID_1
-  * @param     uint8_t *vnd_ie : pointer to a vendor specific element
+  * @param     enable  enable or not
+  * @param     type  information element type
+  * @param     idx  information element index
+  * @param     vnd_ie  pointer to a vendor specific element
   *
   * @return
-  *    - ESP_OK : succeed
-  *    - ESP_ERR_WIFI_NOT_INIT : WiFi is not initialized by eps_wifi_init
-  *    - ESP_ERR_WIFI_ARG : invalid argument
-  *    - ESP_ERR_WIFI_NO_MEM : out of memory
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
+  *    - ESP_ERR_WIFI_ARG: invalid argument
+  *    - ESP_ERR_WIFI_NO_MEM: out of memory
   */
 esp_err_t esp_wifi_set_vendor_ie(bool enable, wifi_vendor_ie_type_t type, wifi_vendor_ie_id_t idx, uint8_t *vnd_ie);
 
 /**
   * @brief     Define function pointer for vendor specific element callback
-  * @param     void *ctx : reserved
-  * @param     wifi_vendor_ie_type_t type : 0 - WIFI_VND_IE_TYPE_BEACON
-  *                           1 - WIFI_VND_IE_TYPE_PROBE_REQ
-  *                           2 - WIFI_VND_IE_TYPE_PROBE_RESP
-  *                           3 - WIFI_VND_IE_TYPE_ASSOC_REQ
-  *                           4 - WIFI_VND_IE_TYPE_ASSOC_RESP
-  * @param     const uint8_t sa[6] : source address
-  * @param     const uint8_t *vnd_ie : pointer to a vendor specific element
-  * @param     int rssi : received signal strength indication
+  * @param     ctx  reserved
+  * @param     type  information element type 
+  * @param     sa  source address
+  * @param     vnd_ie  pointer to a vendor specific element
+  * @param     rssi  received signal strength indication
   */
 typedef void (*esp_vendor_ie_cb_t) (void *ctx, wifi_vendor_ie_type_t type, const uint8_t sa[6], const uint8_t *vnd_ie, int rssi);
 
 /**
   * @brief     Set vendor specific element callback
   *
-  * @param     esp_vendor_ie_cb_t cb : callback function
-  * @param     void *ctx : reserved
+  * @param     cb   callback function
+  * @param     ctx  reserved
   *
   * @return
-  *    - ESP_OK : succeed
-  *    - ESP_ERR_WIFI_NOT_INIT : WiFi is not initialized by eps_wifi_init
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
   */
 esp_err_t esp_wifi_set_vendor_ie_cb(esp_vendor_ie_cb_t cb, void *ctx);
 

+ 1 - 1
components/esp32/lib

@@ -1 +1 @@
-Subproject commit 41da160a5dbf9e13b4fb51f31acf372f50c28270
+Subproject commit e188536a6315cc3ce4f1006ac3a4450faea6abc6

+ 3 - 1
components/esptool_py/Makefile.projbuild

@@ -54,4 +54,6 @@ app-flash: $(APP_BIN) $(ESPTOOLPY_SRC)
 	@echo "Flashing app to serial port $(ESPPORT), offset $(CONFIG_APP_OFFSET)..."
 	$(ESPTOOLPY_WRITE_FLASH) $(CONFIG_APP_OFFSET) $(APP_BIN)
 
-$(eval $(call SubmoduleCheck,$(ESPTOOLPY_SRC),$(COMPONENT_PATH)/esptool))
+# Submodules normally added in component.mk, but can be added
+# at the project level as long as qualified path
+COMPONENT_SUBMODULES += $(COMPONENT_PATH)/esptool

+ 32 - 31
components/expat/port/minicheck.c

@@ -108,44 +108,45 @@ add_failure(SRunner *runner, int verbosity)
     }
 }
 
+static void run_test(SRunner *runner, int verbosity, TCase *tc, int i)
+{
+  if (tc->setup != NULL) {
+    /* setup */
+    if (setjmp(env)) {
+      add_failure(runner, verbosity);
+      return;
+    }
+    tc->setup();
+  }
+  /* test */
+  if (setjmp(env)) {
+    add_failure(runner, verbosity);
+    return;
+  }
+  (tc->tests[i])();
+
+  /* teardown */
+  if (tc->teardown != NULL) {
+    if (setjmp(env)) {
+      add_failure(runner, verbosity);
+      return;
+    }
+    tc->teardown();
+  }
+}
+
 void
 srunner_run_all(SRunner *runner, int verbosity)
 {
-    Suite *suite;
-    TCase *tc;
     assert(runner != NULL);
-    suite = runner->suite;
-    tc = suite->tests;
+    assert(runner->suite != NULL);
+    TCase *tc = runner->suite->tests;
     while (tc != NULL) {
-        int i;
-        for (i = 0; i < tc->ntests; ++i) {
+        for (int i = 0; i < tc->ntests; ++i) {
             runner->nchecks++;
-
-            if (tc->setup != NULL) {
-                /* setup */
-                if (setjmp(env)) {
-                    add_failure(runner, verbosity);
-                    continue;
-                }
-                tc->setup();
-            }
-            /* test */
-            if (setjmp(env)) {
-                add_failure(runner, verbosity);
-                continue;
-            }
-            (tc->tests[i])();
-
-            /* teardown */
-            if (tc->teardown != NULL) {
-                if (setjmp(env)) {
-                    add_failure(runner, verbosity);
-                    continue;
-                }
-                tc->teardown();
-            }
+            run_test(runner, verbosity, tc, i);
+            tc = tc->next_tcase;
         }
-        tc = tc->next_tcase;
     }
     if (verbosity) {
         int passed = runner->nchecks - runner->nfailures;

+ 16 - 6
components/freertos/ringbuf.c

@@ -471,7 +471,8 @@ BaseType_t xRingbufferSend(RingbufHandle_t ringbuf, void *data, size_t dataSize,
     ringbuf_t *rb=(ringbuf_t *)ringbuf;
     size_t needed_size=dataSize+sizeof(buf_entry_hdr_t);
     BaseType_t done=pdFALSE;
-    portTickType ticks_end=xTaskGetTickCount() + ticks_to_wait;
+    TickType_t ticks_end = xTaskGetTickCount() + ticks_to_wait;
+    TickType_t ticks_remaining = ticks_to_wait;
 
     configASSERT(rb);
 
@@ -486,17 +487,26 @@ BaseType_t xRingbufferSend(RingbufHandle_t ringbuf, void *data, size_t dataSize,
             if (ringbufferFreeMem(rb) < needed_size) {
                 //Data does not fit yet. Wait until the free_space_sem is given, then re-evaluate.
 
-                BaseType_t r = xSemaphoreTake(rb->free_space_sem, ticks_to_wait);
+                BaseType_t r = xSemaphoreTake(rb->free_space_sem, ticks_remaining);
                 if (r == pdFALSE) {
                     //Timeout.
                     return pdFALSE;
                 }
-                //Adjust ticks_to_wait; we may have waited less than that and in the case the free memory still is not enough,
+                //Adjust ticks_remaining; we may have waited less than that and in the case the free memory still is not enough,
                 //we will need to wait some more.
-                ticks_to_wait = ticks_end - xTaskGetTickCount();
+                if (ticks_to_wait != portMAX_DELAY) {
+                    ticks_remaining = ticks_end - xTaskGetTickCount();
+                }
+
+                // ticks_remaining will always be less than or equal to the original ticks_to_wait,
+                // unless the timeout is reached - in which case it unsigned underflows to a much
+                // higher value.
+                //
+                // (Check is written this non-intuitive way to allow for the case where xTaskGetTickCount()
+                // has overflowed but the ticks_end value has not overflowed.)
             }
-        } while (ringbufferFreeMem(rb) < needed_size && ticks_to_wait>=0);
-        
+        } while (ringbufferFreeMem(rb) < needed_size && ticks_remaining > 0 && ticks_remaining <= ticks_to_wait);
+
         //Lock the mux in order to make sure no one else is messing with the ringbuffer and do the copy.
         portENTER_CRITICAL(&rb->mux);
         //Another thread may have been able to sneak its write first. Check again now we locked the ringbuff, and retry

+ 1 - 3
components/freertos/tasks.c

@@ -2704,7 +2704,7 @@ void vTaskSwitchContext( void )
 		taskENTER_CRITICAL_ISR(&xTaskQueueMutex);
 		
 		unsigned portBASE_TYPE foundNonExecutingWaiter = pdFALSE, ableToSchedule = pdFALSE, resetListHead;
-		unsigned portBASE_TYPE uxDynamicTopReady = uxTopReadyPriority;
+		portBASE_TYPE uxDynamicTopReady = uxTopReadyPriority;
 		unsigned portBASE_TYPE holdTop=pdFALSE;
 		
 		/*
@@ -2717,8 +2717,6 @@ void vTaskSwitchContext( void )
 		
 		while ( ableToSchedule == pdFALSE && uxDynamicTopReady >= 0 )
 		{
-			configASSERT( uxTopReadyPriority>=0 );
-			configASSERT( uxDynamicTopReady>=0 );
 			resetListHead = pdFALSE;
 			// Nothing to do for empty lists
 			if (!listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxDynamicTopReady ] ) )) {

+ 16 - 0
components/lwip/Kconfig

@@ -1,5 +1,21 @@
 menu "LWIP"
 
+config L2_TO_L3_COPY
+    bool "Enable copy between Layer2 and Layer3 packets"
+    default 0
+    help
+        If this feature is enabled, all traffic from layer2(WIFI Driver) will be
+        copied to a new buffer before sending it to layer3(LWIP stack), freeing
+        the layer2 buffer.
+        Please be notified that the total layer2 receiving buffer is fixed and 
+        ESP32 currently supports 25 layer2 receiving buffer, when layer2 buffer 
+        runs out of memory, then the incoming packets will be dropped in hardware. 
+        The layer3 buffer is allocated from the heap, so the total layer3 receiving
+        buffer depends on the available heap size, when heap runs out of memory,  
+        no copy will be sent to layer3 and packet will be dropped in layer2. 
+        Please make sure you fully understand the impact of this feature before 
+        enabling it.
+
 config LWIP_MAX_SOCKETS
     int "Max number of open sockets"
     range 1 16

+ 7 - 0
components/lwip/include/lwip/lwip/opt.h

@@ -3008,6 +3008,13 @@
 #define LWIP_PERF                       0
 #endif
 
+/**
+ * ESP_L2_TO_L3_COPY: enable memcpy when receiving packet from L2
+ */
+#ifndef ESP_L2_TO_L3_COPY
+#define ESP_L2_TO_L3_COPY                   0
+#endif
+
 #ifndef ESP_THREAD_SAFE_DEBUG
 #define ESP_THREAD_SAFE_DEBUG               0
 #endif

+ 1 - 0
components/lwip/include/lwip/port/lwipopts.h

@@ -525,6 +525,7 @@ extern unsigned long os_random(void);
 #define ESP_RANDOM_TCP_PORT             1
 #define ESP_IP4_ATON                    1
 #define ESP_LIGHT_SLEEP                 1
+#define ESP_L2_TO_L3_COPY               CONFIG_L2_TO_L3_COPY
 
 #define TCP_WND_DEFAULT                      (4*TCP_MSS)
 #define TCP_SND_BUF_DEFAULT                  (2*TCP_MSS)

+ 18 - 21
components/lwip/port/netif/wlanif.c

@@ -161,40 +161,37 @@ low_level_output(struct netif *netif, struct pbuf *p)
  * @param netif the lwip network interface structure for this ethernetif
  */
 void
-#if ESP_LWIP
 wlanif_input(struct netif *netif, void *buffer, u16_t len, void* eb)
-#else
-wlanif_input(struct netif *netif, void *buffer, uint16 len)
-#endif
 {
   struct pbuf *p;
   
-#if ESP_LWIP
-    if(buffer== NULL)
-    	goto _exit;
-    if(netif == NULL)
+  if(!buffer || !netif)
     	goto _exit;
-#endif
 
-#if ESP_LWIP
+#if (ESP_L2_TO_L3_COPY == 1)
+  //p = pbuf_alloc(PBUF_IP, len, PBUF_POOL);
+  p = pbuf_alloc(PBUF_RAW, len, PBUF_RAM);
+  if (p == NULL) {
+    #if ESP_PERF
+    g_rx_alloc_pbuf_fail_cnt++;
+    #endif
+    esp_wifi_internal_free_rx_buffer(eb);
+    return;
+  }
+  memcpy(p->payload, buffer, len);
+  esp_wifi_internal_free_rx_buffer(eb);
+#else
   p = pbuf_alloc(PBUF_RAW, len, PBUF_REF);
   if (p == NULL){
-#if ESP_PERF
-      g_rx_alloc_pbuf_fail_cnt++;
-#endif
-      return;
+    #if ESP_PERF
+    g_rx_alloc_pbuf_fail_cnt++;
+    #endif
+    return;
   }
   p->payload = buffer;
   p->eb = eb;
-#else
-  p = pbuf_alloc(PBUF_IP, len, PBUF_POOL);
-  if (p == NULL) {
-    return;
-  }
-  memcpy(p->payload, buffer, len);
 #endif
 
-
   /* full packet send to tcpip_thread to process */
   if (netif->input(p, netif) != ERR_OK) {
     LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));

+ 2 - 0
components/micro-ecc/component.mk

@@ -4,3 +4,5 @@ COMPONENT_SRCDIRS := micro-ecc
 COMPONENT_OBJS := micro-ecc/uECC.o
 
 COMPONENT_ADD_INCLUDEDIRS := micro-ecc
+
+COMPONENT_SUBMODULES := micro-ecc

+ 84 - 21
components/nvs_flash/include/nvs.h

@@ -77,8 +77,9 @@ typedef enum {
  */
 esp_err_t nvs_open(const char* name, nvs_open_mode open_mode, nvs_handle *out_handle);
 
+/**@{*/
 /**
- * @brief      nvs_set_X - set value for given key
+ * @brief      set value for given key
  *
  * This family of functions set value for the key, given its name. Note that
  * actual storage will not be updated until nvs_commit function is called.
@@ -89,7 +90,6 @@ esp_err_t nvs_open(const char* name, nvs_open_mode open_mode, nvs_handle *out_ha
  *                     implementation, but is guaranteed to be at least
  *                     16 characters. Shouldn't be empty.
  * @param[in]  value   The value to set.
- * @param[in]  length  For nvs_set_blob: length of binary value to set, in bytes.
  *
  * @return
  *             - ESP_OK if value was set successfully
@@ -112,10 +112,39 @@ esp_err_t nvs_set_u32 (nvs_handle handle, const char* key, uint32_t value);
 esp_err_t nvs_set_i64 (nvs_handle handle, const char* key, int64_t value);
 esp_err_t nvs_set_u64 (nvs_handle handle, const char* key, uint64_t value);
 esp_err_t nvs_set_str (nvs_handle handle, const char* key, const char* value);
+/**@}*/ 
+
+/**
+ * @brief       set variable length binary value for given key
+ *
+ * This family of functions set value for the key, given its name. Note that
+ * actual storage will not be updated until nvs_commit function is called.
+ *
+ * @param[in]  handle  Handle obtained from nvs_open function.
+ *                     Handles that were opened read only cannot be used.
+ * @param[in]  key     Key name. Maximal length is determined by the underlying
+ *                     implementation, but is guaranteed to be at least
+ *                     16 characters. Shouldn't be empty.
+ * @param[in]  value   The value to set.
+ * @param[in]  length  length of binary value to set, in bytes.
+ *
+ * @return
+ *             - ESP_OK if value was set successfully
+ *             - ESP_ERR_NVS_INVALID_HANDLE if handle has been closed or is NULL
+ *             - ESP_ERR_NVS_READ_ONLY if storage handle was opened as read only
+ *             - ESP_ERR_NVS_INVALID_NAME if key name doesn't satisfy constraints
+ *             - ESP_ERR_NVS_NOT_ENOUGH_SPACE if there is not enough space in the
+ *               underlying storage to save the value
+ *             - ESP_ERR_NVS_REMOVE_FAILED if the value wasn't updated because flash
+ *               write operation has failed. The value was written however, and
+ *               update will be finished after re-initialization of nvs, provided that
+ *               flash operation doesn't fail again.
+ */
 esp_err_t nvs_set_blob(nvs_handle handle, const char* key, const void* value, size_t length);
 
+/**@{*/
 /**
- * @brief      nvs_get_X - get value for given key
+ * @brief      get value for given key
  *
  * These functions retrieve value for the key, given its name. If key does not
  * exist, or the requested variable type doesn't match the type which was used
@@ -125,7 +154,55 @@ esp_err_t nvs_set_blob(nvs_handle handle, const char* key, const void* value, si
  *
  * All functions expect out_value to be a pointer to an already allocated variable
  * of the given type.
- * Additionally, nvs_get_str and nvs_get_blob support WinAPI-style length queries.
+ *
+ * \code{c}
+ * // Example of using nvs_get_i32:
+ * int32_t max_buffer_size = 4096; // default value
+ * esp_err_t err = nvs_get_i32(my_handle, "max_buffer_size", &max_buffer_size);
+ * assert(err == ESP_OK || err == ESP_ERR_NVS_NOT_FOUND);
+ * // if ESP_ERR_NVS_NOT_FOUND was returned, max_buffer_size will still
+ * // have its default value.
+ *
+ * \endcode
+ *
+ * @param[in]     handle     Handle obtained from nvs_open function.
+ * @param[in]     key        Key name. Maximal length is determined by the underlying
+ *                           implementation, but is guaranteed to be at least
+ *                           16 characters. Shouldn't be empty.
+ * @param         out_value  Pointer to the output value.
+ *                           May be NULL for nvs_get_str and nvs_get_blob, in this
+ *                           case required length will be returned in length argument.
+ *
+ * @return
+ *             - ESP_OK if the value was retrieved successfully
+ *             - ESP_ERR_NVS_NOT_FOUND if the requested key doesn't exist
+ *             - ESP_ERR_NVS_INVALID_HANDLE if handle has been closed or is NULL
+ *             - ESP_ERR_NVS_INVALID_NAME if key name doesn't satisfy constraints
+ *             - ESP_ERR_NVS_INVALID_LENGTH if length is not sufficient to store data
+ */
+esp_err_t nvs_get_i8  (nvs_handle handle, const char* key, int8_t* out_value);
+esp_err_t nvs_get_u8  (nvs_handle handle, const char* key, uint8_t* out_value);
+esp_err_t nvs_get_i16 (nvs_handle handle, const char* key, int16_t* out_value);
+esp_err_t nvs_get_u16 (nvs_handle handle, const char* key, uint16_t* out_value);
+esp_err_t nvs_get_i32 (nvs_handle handle, const char* key, int32_t* out_value);
+esp_err_t nvs_get_u32 (nvs_handle handle, const char* key, uint32_t* out_value);
+esp_err_t nvs_get_i64 (nvs_handle handle, const char* key, int64_t* out_value);
+esp_err_t nvs_get_u64 (nvs_handle handle, const char* key, uint64_t* out_value);
+/**@}*/ 
+
+/**
+ * @brief      get value for given key
+ *
+ * These functions retrieve value for the key, given its name. If key does not
+ * exist, or the requested variable type doesn't match the type which was used
+ * when setting a value, an error is returned.
+ *
+ * In case of any error, out_value is not modified.
+ *
+ * All functions expect out_value to be a pointer to an already allocated variable
+ * of the given type.
+ * 
+ * nvs_get_str and nvs_get_blob functions support WinAPI-style length queries.
  * To get the size necessary to store the value, call nvs_get_str or nvs_get_blob
  * with zero out_value and non-zero pointer to length. Variable pointed to
  * by length argument will be set to the required length. For nvs_get_str,
@@ -136,13 +213,6 @@ esp_err_t nvs_set_blob(nvs_handle handle, const char* key, const void* value, si
  * nvs_get/set_blob used for arbitrary data structures.
  *
  * \code{c}
- * // Example of using nvs_get_i32:
- * int32_t max_buffer_size = 4096; // default value
- * esp_err_t err = nvs_get_i32(my_handle, "max_buffer_size", &max_buffer_size);
- * assert(err == ESP_OK || err == ESP_ERR_NVS_NOT_FOUND);
- * // if ESP_ERR_NVS_NOT_FOUND was returned, max_buffer_size will still
- * // have its default value.
- *
  * // Example (without error checking) of using nvs_get_str to get a string into dynamic array:
  * size_t required_size;
  * nvs_get_str(my_handle, "server_name", NULL, &required_size);
@@ -163,8 +233,7 @@ esp_err_t nvs_set_blob(nvs_handle handle, const char* key, const void* value, si
  * @param         out_value  Pointer to the output value.
  *                           May be NULL for nvs_get_str and nvs_get_blob, in this
  *                           case required length will be returned in length argument.
- * @param[inout]  length     For nvs_get_str and nvs_get_blob, non-zero pointer
- *                           to the variable holding the length of out_value.
+ * @param[inout]  length     A non-zero pointer to the variable holding the length of out_value.
  *                           In case out_value a zero, will be set to the length
  *                           required to hold the value. In case out_value is not
  *                           zero, will be set to the actual length of the value
@@ -177,16 +246,10 @@ esp_err_t nvs_set_blob(nvs_handle handle, const char* key, const void* value, si
  *             - ESP_ERR_NVS_INVALID_NAME if key name doesn't satisfy constraints
  *             - ESP_ERR_NVS_INVALID_LENGTH if length is not sufficient to store data
  */
-esp_err_t nvs_get_i8  (nvs_handle handle, const char* key, int8_t* out_value);
-esp_err_t nvs_get_u8  (nvs_handle handle, const char* key, uint8_t* out_value);
-esp_err_t nvs_get_i16 (nvs_handle handle, const char* key, int16_t* out_value);
-esp_err_t nvs_get_u16 (nvs_handle handle, const char* key, uint16_t* out_value);
-esp_err_t nvs_get_i32 (nvs_handle handle, const char* key, int32_t* out_value);
-esp_err_t nvs_get_u32 (nvs_handle handle, const char* key, uint32_t* out_value);
-esp_err_t nvs_get_i64 (nvs_handle handle, const char* key, int64_t* out_value);
-esp_err_t nvs_get_u64 (nvs_handle handle, const char* key, uint64_t* out_value);
+/**@{*/
 esp_err_t nvs_get_str (nvs_handle handle, const char* key, char* out_value, size_t* length);
 esp_err_t nvs_get_blob(nvs_handle handle, const char* key, void* out_value, size_t* length);
+/**@}*/
 
 /**
  * @brief      Erase key-value pair with given key name.

+ 1 - 1
components/nvs_flash/include/nvs_flash.h

@@ -21,7 +21,7 @@ extern "C" {
 /** Initialise NVS flash storage with default flash sector layout
 
     Temporarily, this region is hardcoded as a 12KB (0x3000 byte)
-    region starting at 24KB (0x6000 byte) offset in flash.
+    region starting at 36KB (0x9000 byte) offset in flash.
 
     @return ESP_OK if flash was successfully initialised.
 */

+ 1 - 1
components/nvs_flash/src/nvs_api.cpp

@@ -63,7 +63,7 @@ extern "C" void nvs_dump()
 
 extern "C" esp_err_t nvs_flash_init(void)
 {
-    return nvs_flash_init_custom(6, 3);
+    return nvs_flash_init_custom(9, 3);
 }
 
 extern "C" esp_err_t nvs_flash_init_custom(uint32_t baseSector, uint32_t sectorCount)

+ 61 - 40
components/spi_flash/include/esp_partition.h

@@ -25,57 +25,78 @@
 extern "C" {
 #endif
 
+/**
+ * @file esp_partition.h
+ * @brief Partition APIs
+ */
+
+
+/**
+ * @brief Partition type
+ * @note Keep this enum in sync with PartitionDefinition class gen_esp32part.py
+ */
 typedef enum {
-    ESP_PARTITION_TYPE_APP = 0x00,
-    ESP_PARTITION_TYPE_DATA = 0x01,
-    ESP_PARTITION_TYPE_FILESYSTEM = 0x02,
+    ESP_PARTITION_TYPE_APP = 0x00,       //!< Application partition type
+    ESP_PARTITION_TYPE_DATA = 0x01,      //!< Data partition type
 } esp_partition_type_t;
 
+/**
+ * @brief Partition subtype
+ * @note Keep this enum in sync with PartitionDefinition class gen_esp32part.py
+ */
 typedef enum {
-    ESP_PARTITION_SUBTYPE_APP_FACTORY = 0x00,
-    ESP_PARTITION_SUBTYPE_APP_OTA_MIN = 0x10,
-    ESP_PARTITION_SUBTYPE_APP_OTA_0 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 0,
-    ESP_PARTITION_SUBTYPE_APP_OTA_1 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 1,
-    ESP_PARTITION_SUBTYPE_APP_OTA_2 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 2,
-    ESP_PARTITION_SUBTYPE_APP_OTA_3 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 3,
-    ESP_PARTITION_SUBTYPE_APP_OTA_4 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 4,
-    ESP_PARTITION_SUBTYPE_APP_OTA_5 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 5,
-    ESP_PARTITION_SUBTYPE_APP_OTA_6 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 6,
-    ESP_PARTITION_SUBTYPE_APP_OTA_7 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 7,
-    ESP_PARTITION_SUBTYPE_APP_OTA_8 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 8,
-    ESP_PARTITION_SUBTYPE_APP_OTA_9 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 9,
-    ESP_PARTITION_SUBTYPE_APP_OTA_10 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 10,
-    ESP_PARTITION_SUBTYPE_APP_OTA_11 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 11,
-    ESP_PARTITION_SUBTYPE_APP_OTA_12 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 12,
-    ESP_PARTITION_SUBTYPE_APP_OTA_13 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 13,
-    ESP_PARTITION_SUBTYPE_APP_OTA_14 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 14,
-    ESP_PARTITION_SUBTYPE_APP_OTA_15 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 15,
-    ESP_PARTITION_SUBTYPE_APP_OTA_MAX = 15,
-    ESP_PARTITION_SUBTYPE_APP_TEST = 0x20,
-
-    ESP_PARTITION_SUBTYPE_DATA_OTA = 0x00,
-    ESP_PARTITION_SUBTYPE_DATA_RF =  0x01,
-    ESP_PARTITION_SUBTYPE_DATA_NVS = 0x02,
-
-    ESP_PARTITION_SUBTYPE_FILESYSTEM_ESPHTTPD = 0x00,
-    ESP_PARTITION_SUBTYPE_FILESYSTEM_FAT = 0x01,
-    ESP_PARTITION_SUBTYPE_FILESYSTEM_SPIFFS = 0x02,
-
-    ESP_PARTITION_SUBTYPE_ANY = 0xff,
+    ESP_PARTITION_SUBTYPE_APP_FACTORY = 0x00,                                 //!< Factory application partition
+    ESP_PARTITION_SUBTYPE_APP_OTA_MIN = 0x10,                                 //!< Base for OTA partition subtypes
+    ESP_PARTITION_SUBTYPE_APP_OTA_0 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 0,  //!< OTA partition 0
+    ESP_PARTITION_SUBTYPE_APP_OTA_1 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 1,  //!< OTA partition 1
+    ESP_PARTITION_SUBTYPE_APP_OTA_2 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 2,  //!< OTA partition 2
+    ESP_PARTITION_SUBTYPE_APP_OTA_3 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 3,  //!< OTA partition 3
+    ESP_PARTITION_SUBTYPE_APP_OTA_4 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 4,  //!< OTA partition 4
+    ESP_PARTITION_SUBTYPE_APP_OTA_5 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 5,  //!< OTA partition 5
+    ESP_PARTITION_SUBTYPE_APP_OTA_6 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 6,  //!< OTA partition 6
+    ESP_PARTITION_SUBTYPE_APP_OTA_7 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 7,  //!< OTA partition 7
+    ESP_PARTITION_SUBTYPE_APP_OTA_8 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 8,  //!< OTA partition 8
+    ESP_PARTITION_SUBTYPE_APP_OTA_9 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 9,  //!< OTA partition 9
+    ESP_PARTITION_SUBTYPE_APP_OTA_10 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 10,//!< OTA partition 10
+    ESP_PARTITION_SUBTYPE_APP_OTA_11 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 11,//!< OTA partition 11
+    ESP_PARTITION_SUBTYPE_APP_OTA_12 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 12,//!< OTA partition 12
+    ESP_PARTITION_SUBTYPE_APP_OTA_13 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 13,//!< OTA partition 13
+    ESP_PARTITION_SUBTYPE_APP_OTA_14 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 14,//!< OTA partition 14
+    ESP_PARTITION_SUBTYPE_APP_OTA_15 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 15,//!< OTA partition 15
+    ESP_PARTITION_SUBTYPE_APP_OTA_MAX = 15,                                   //!< Max subtype of OTA partition
+    ESP_PARTITION_SUBTYPE_APP_TEST = 0x20,                                    //!< Test application partition
+
+    ESP_PARTITION_SUBTYPE_DATA_OTA = 0x00,                                    //!< OTA selection partition
+    ESP_PARTITION_SUBTYPE_DATA_PHY = 0x01,                                    //!< PHY init data partition
+    ESP_PARTITION_SUBTYPE_DATA_NVS = 0x02,                                    //!< NVS partition
+
+    ESP_PARTITION_SUBTYPE_DATA_ESPHTTPD = 0x80,                               //!< ESPHTTPD partition
+    ESP_PARTITION_SUBTYPE_DATA_FAT = 0x81,                                    //!< FAT partition
+    ESP_PARTITION_SUBTYPE_DATA_SPIFFS = 0x82,                                 //!< SPIFFS partition
+
+    ESP_PARTITION_SUBTYPE_ANY = 0xff,                                         //!< Used to search for partitions with any subtype
 } esp_partition_subtype_t;
 
+/**
+ * @brief Convenience macro to get esp_partition_subtype_t value for the i-th OTA partition
+ */
 #define ESP_PARTITION_SUBTYPE_OTA(i) ((esp_partition_subtype_t)(ESP_PARTITION_SUBTYPE_APP_OTA_MIN + ((i) & 0xf)))
 
-
+/**
+ * @brief Opaque partition iterator type
+ */
 typedef struct esp_partition_iterator_opaque_* esp_partition_iterator_t;
 
+/**
+ * @brief partition information structure
+ */
 typedef struct {
-    esp_partition_type_t type;
-    esp_partition_subtype_t subtype;
-    uint32_t address;
-    uint32_t size;
-    char label[17];
-    bool encrypted;
+    esp_partition_type_t type;          /*!< partition type (app/data) */
+    esp_partition_subtype_t subtype;    /*!< partition subtype */
+    uint32_t address;                   /*!< starting address of the partition in flash */
+    uint32_t size;                      /*!< size of the partition, in bytes */
+    char label[17];                     /*!< partition label, zero-terminated ASCII string */
+    bool encrypted;                     /*!< flag is set to true if partition is encrypted */
 } esp_partition_t;
 
 /**

+ 3 - 3
components/spi_flash/include/esp_spi_flash.h

@@ -62,13 +62,13 @@ esp_err_t spi_flash_erase_sector(size_t sector);
 /**
  * @brief  Erase a range of flash sectors
  *
- * @param  uint32_t start_address : Address where erase operation has to start.
+ * @param  start_address  Address where erase operation has to start.
  *                                  Must be 4kB-aligned
- * @param  uint32_t size : Size of erased range, in bytes. Must be divisible by 4kB.
+ * @param  size  Size of erased range, in bytes. Must be divisible by 4kB.
  *
  * @return esp_err_t
  */
-esp_err_t spi_flash_erase_range(size_t start_addr, size_t size);
+esp_err_t spi_flash_erase_range(size_t start_address, size_t size);
 
 
 /**

+ 5 - 5
components/vfs/include/esp_vfs.h

@@ -57,15 +57,15 @@ extern "C" {
  * flags member to ESP_VFS_FLAG_CONTEXT_PTR and provide the context pointer
  * to esp_vfs_register function.
  * If the implementation doesn't use this extra argument, populate the
- * members without _p suffix and set flags memeber to ESP_VFS_FLAG_DEFAULT.
+ * members without _p suffix and set flags member to ESP_VFS_FLAG_DEFAULT.
  *
  * If the FS driver doesn't provide some of the functions, set corresponding
  * members to NULL.
  */
 typedef struct
 {
-    int fd_offset;
-    int flags;
+    int fd_offset;  /*!< file descriptor offset, determined by the FS driver */
+    int flags;      /*!< ESP_VFS_FLAG_CONTEXT_PTR or ESP_VFS_FLAG_DEFAULT */
     union {
         size_t (*write_p)(void* p, int fd, const void * data, size_t size);
         size_t (*write)(int fd, const void * data, size_t size);
@@ -135,7 +135,7 @@ esp_err_t esp_vfs_register(const char* base_path, const esp_vfs_t* vfs, void* ct
  * These functions are to be used in newlib syscall table. They will be called by
  * newlib when it needs to use any of the syscalls.
  */
-
+/**@{*/
 ssize_t esp_vfs_write(struct _reent *r, int fd, const void * data, size_t size);
 off_t esp_vfs_lseek(struct _reent *r, int fd, off_t size, int mode);
 ssize_t esp_vfs_read(struct _reent *r, int fd, void * dst, size_t size);
@@ -146,7 +146,7 @@ int esp_vfs_stat(struct _reent *r, const char * path, struct stat * st);
 int esp_vfs_link(struct _reent *r, const char* n1, const char* n2);
 int esp_vfs_unlink(struct _reent *r, const char *path);
 int esp_vfs_rename(struct _reent *r, const char *src, const char *dst);
-
+/**@}*/
 
 
 #ifdef __cplusplus

+ 10 - 5
docs/Doxyfile

@@ -1,8 +1,14 @@
 PROJECT_NAME = "ESP32 Programming Guide"
 
-INPUT = ../components/esp32/include/esp_wifi.h ../components/driver/include/driver ../components/bt/include \
-		../components/nvs_flash/include ../components/log/include ../components/vfs/include \
-		../components/esp32/include/esp_int_wdt.h ../components/esp32/include/esp_task_wdt.h
+INPUT = ../components/esp32/include/esp_wifi.h \
+	../components/driver/include/driver \
+	../components/bt/include \
+	../components/nvs_flash/include \
+	../components/log/include \
+	../components/vfs/include \
+	../components/spi_flash/include \
+	../components/esp32/include/esp_int_wdt.h \
+	../components/esp32/include/esp_task_wdt.h
 
 WARN_NO_PARAMDOC	= YES
 
@@ -16,9 +22,8 @@ XML_OUTPUT		= xml
 GENERATE_HTML		= NO
 HAVE_DOT		= NO
 GENERATE_LATEX		= NO
-GENERATE_MAN		= NO
+GENERATE_MAN		= YES
 GENERATE_RTF		= NO
 
-QUIET = YES
 WARN_LOGFILE = "doxygen-warning-log.txt"
 

+ 4 - 1
docs/api/nvs_flash.rst

@@ -3,7 +3,10 @@
 Application Example
 -------------------
 
-`Instructions <http://esp-idf.readthedocs.io/en/latest/api/template.html>`_
+Two examples are provided in ESP-IDF examples directory:
+
+- `07_nvs_rw_value <https://github.com/espressif/esp-idf/tree/master/examples/07_nvs_rw_value>`_ demostrates how to read and write integer values
+- `08_nvs_rw_blob <https://github.com/espressif/esp-idf/tree/master/examples/08_nvs_rw_blob>`_ demostrates how to read and write variable length binary values
 
 API Reference
 -------------

+ 67 - 0
docs/api/spi_flash.rst

@@ -0,0 +1,67 @@
+.. include:: ../../components/spi_flash/README.rst
+
+Application Example
+-------------------
+
+`Instructions`_
+
+.. _Instructions: template.html
+
+API Reference
+-------------
+
+Header Files
+^^^^^^^^^^^^
+
+  * `spi_flash/include/esp_spi_flash.h <https://github.com/espressif/esp-idf/blob/master/components/spi_flash/include/esp_spi_flash.h>`_
+  * `spi_flash/include/esp_partition.h <https://github.com/espressif/esp-idf/blob/master/components/spi_flash/include/esp_partition.h>`_
+
+Macros
+^^^^^^
+
+.. doxygendefine:: ESP_ERR_FLASH_BASE
+.. doxygendefine:: ESP_ERR_FLASH_OP_FAIL
+.. doxygendefine:: ESP_ERR_FLASH_OP_TIMEOUT
+.. doxygendefine:: SPI_FLASH_SEC_SIZE
+.. doxygendefine:: ESP_PARTITION_SUBTYPE_OTA
+
+Type Definitions
+^^^^^^^^^^^^^^^^
+
+.. doxygentypedef:: spi_flash_mmap_handle_t
+.. doxygentypedef:: esp_partition_iterator_t
+
+Enumerations
+^^^^^^^^^^^^
+
+.. doxygenenum:: spi_flash_mmap_memory_t
+.. doxygenenum:: esp_partition_type_t
+.. doxygenenum:: esp_partition_subtype_t
+
+Structures
+^^^^^^^^^^
+
+.. doxygenstruct:: esp_partition_t
+
+Functions
+^^^^^^^^^
+
+.. doxygenfunction:: spi_flash_init
+.. doxygenfunction:: spi_flash_get_chip_size
+.. doxygenfunction:: spi_flash_erase_sector
+.. doxygenfunction:: spi_flash_erase_range
+.. doxygenfunction:: spi_flash_write
+.. doxygenfunction:: spi_flash_read
+.. doxygenfunction:: spi_flash_mmap
+.. doxygenfunction:: spi_flash_munmap
+.. doxygenfunction:: spi_flash_mmap_dump
+.. doxygenfunction:: esp_partition_find
+.. doxygenfunction:: esp_partition_find_first
+.. doxygenfunction:: esp_partition_get
+.. doxygenfunction:: esp_partition_next
+.. doxygenfunction:: esp_partition_iterator_release
+.. doxygenfunction:: esp_partition_read
+.. doxygenfunction:: esp_partition_write
+.. doxygenfunction:: esp_partition_erase_range
+.. doxygenfunction:: esp_partition_mmap
+

+ 8 - 0
docs/build_system.rst

@@ -186,6 +186,14 @@ The following variables can be set inside ``component.mk`` to control build sett
   generates an include file which you then want to include in another
   component. Most components do not need to set this variable.
 
+The following variable only works for components that are part of esp-idf itself:
+
+- ``COMPONENT_SUBMODULES``: Optional list of git submodule paths
+  (relative to COMPONENT_PATH) used by the component. These will be
+  checked (and initialised if necessary) by the build process. This
+  variable is ignored if the component is outside the IDF_PATH
+  directory.
+
 
 Optional Component-Specific Variables
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

+ 56 - 0
docs/doxygen_xml_to_rst.xslt

@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- This XSL transform converts Doxygen XML output for a header file into Sphinx/Breathe compatible list of APIs -->
+<!-- Usage:  xsltproc doxygen_xml_to_rst.xslt xml/esp__xxxx_8h.xml -->
+
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+    <xsl:output method="text" encoding="UTF-8"/>
+    <xsl:template match="/">
+        <xsl:text>Macros&#xA;</xsl:text>
+        <xsl:text>^^^^^^&#xA;&#xA;</xsl:text>
+        <xsl:for-each select="doxygen/compounddef/sectiondef/memberdef[@kind='define']">
+            <xsl:text>.. doxygendefine:: </xsl:text>
+            <xsl:value-of select="name"/>
+            <xsl:text>&#xA;</xsl:text>
+        </xsl:for-each>
+        <xsl:text>&#xA;</xsl:text>
+
+        <xsl:text>Type Definitions&#xA;</xsl:text>
+        <xsl:text>^^^^^^^^^^^^^^^^&#xA;&#xA;</xsl:text>
+        <xsl:for-each select="doxygen/compounddef/sectiondef/memberdef[@kind='typedef']">
+            <xsl:text>.. doxygentypedef:: </xsl:text>
+            <xsl:value-of select="name"/>
+            <xsl:text>&#xA;</xsl:text>
+        </xsl:for-each>
+        <xsl:text>&#xA;</xsl:text>
+
+        <xsl:text>Enumerations&#xA;</xsl:text>
+        <xsl:text>^^^^^^^^^^^^&#xA;&#xA;</xsl:text>
+        <xsl:for-each select="doxygen/compounddef/sectiondef/memberdef[@kind='enum']">
+            <xsl:text>.. doxygenenum:: </xsl:text>
+            <xsl:value-of select="name"/>
+            <xsl:text>&#xA;</xsl:text>
+        </xsl:for-each>
+        <xsl:text>&#xA;</xsl:text>
+
+        <!-- TODO: figure out why structures are listed as innerclass instances -->
+        <xsl:text>Structures&#xA;</xsl:text>
+        <xsl:text>^^^^^^^^^^&#xA;&#xA;</xsl:text>
+        <xsl:for-each select="doxygen/compounddef/innerclass">
+            <xsl:text>.. doxygenstruct:: </xsl:text>
+            <xsl:value-of select="."/>
+            <xsl:text>&#xA;</xsl:text>
+        </xsl:for-each>
+        <xsl:text>&#xA;</xsl:text>
+
+        <xsl:text>Functions&#xA;</xsl:text>
+        <xsl:text>^^^^^^^^^&#xA;&#xA;</xsl:text>
+        <xsl:for-each select="doxygen/compounddef/sectiondef/memberdef[@kind='function']">
+            <xsl:text>.. doxygenfunction:: </xsl:text>
+            <xsl:value-of select="name"/>
+            <xsl:text>&#xA;</xsl:text>
+        </xsl:for-each>
+        <xsl:text>&#xA;</xsl:text>
+
+    </xsl:template>
+</xsl:stylesheet>

+ 125 - 0
docs/general-notes.rst

@@ -0,0 +1,125 @@
+General Notes About ESP-IDF Programming
+=======================================
+
+Application startup flow
+------------------------
+
+This note explains various steps which happen before ``app_main`` function of an ESP-IDF application is called.
+
+The high level view of startup process is as follows:
+
+1. First-stage bootloader in ROM loads second-stage bootloader image to RAM (IRAM & DRAM) from flash offset 0x1000.
+2. Second-stage bootloader loads partition table and main app image from flash. Main app incorporates both RAM segments and read-only segments mapped via flash cache.
+3. Main app image executes. At this point the second CPU and RTOS scheduler can be started.
+
+This process is explained in detail in the following sections.
+
+First stage bootloader
+^^^^^^^^^^^^^^^^^^^^^^
+
+After SoC reset, PRO CPU will start running immediately, executing reset vector code, while APP CPU will be held in reset. During startup process, PRO CPU does all the initialization. APP CPU reset is de-asserted in the ``call_start_cpu0`` function of application startup code. Reset vector code is located at address 0x40000400 in the mask ROM of the ESP32 chip and can not be modified.
+
+Startup code called from the reset vector determines the boot mode by checking ``GPIO_STRAP_REG`` register for bootstrap pin states. Depending on the reset reason, the following takes place:
+
+1. Reset from deep sleep: if the value in ``RTC_CNTL_STORE6_REG`` is non-zero, and CRC value of RTC memory in ``RTC_CNTL_STORE7_REG`` is valid, use ``RTC_CNTL_STORE6_REG`` as an entry point address and jump immediately to it. If ``RTC_CNTL_STORE6_REG`` is zero, or ``RTC_CNTL_STORE7_REG`` contains invalid CRC, or once the code called via ``RTC_CNTL_STORE6_REG`` returns, proceed with boot as if it was a power-on reset. **Note**: to run customized code at this point, a deep sleep stub mechanism is provided. Please see :doc:`deep sleep <deep-sleep-stub>` documentation for this.
+
+2. For power-on reset, software SOC reset, and watchdog SOC reset: check the ``GPIO_STRAP_REG`` register if UART or SDIO download mode is requested. If this is the case, configure UART or SDIO, and wait for code to be downloaded. Otherwise, proceed with boot as if it was due to software CPU reset.
+
+3. For software CPU reset and watchdog CPU reset: configure SPI flash based on EFUSE values, and attempt to load the code from flash. This step is described in more detail in the next paragraphs. If loading code from flash fails, unpack BASIC interpreter into the RAM and start it. Note that RTC watchdog is still enabled when this happens, so unless any input is received by the interpreter, watchdog will reset the SOC in a few hundred milliseconds, repeating the whole process. If the interpreter receives any input from the UART, it disables the watchdog.
+
+Application binary image is loaded from flash starting at address 0x1000. First 4kB sector of flash is used to store secure boot IV and signature of the application image. Please check secure boot documentation for details about this. 
+
+.. TODO: describe application binary image format, describe optional flash configuration commands.
+
+Second stage bootloader
+^^^^^^^^^^^^^^^^^^^^^^^
+
+In ESP-IDF, the binary image which resides at offset 0x1000 in flash is the second stage bootloader. Second stage bootloader source code is available in components/bootloader directory of ESP-IDF. Note that this arrangement is not the only one possible with the ESP32 chip. It is possible to write a fully featured application which would work when flashed to offset 0x1000, but this is out of scope of this document. Second stage bootloader is used in ESP-IDF to add flexibility to flash layout (using partition tables), and allow for various flows associated with flash encryption, secure boot, and over-the-air updates (OTA) to take place.
+
+When the first stage bootloader is finished checking and loading the second stage bootloader, it jumps to the second stage bootloader entry point found in the binary image header.
+
+Second stage bootloader reads the partition table found at offset 0x8000. See :doc:`partition tables <partition-tables>` documentation for more information. The bootloader finds factory and OTA partitions, and decides which one to boot based on data found in *OTA info* partition. 
+
+For the selected partition, second stage bootloader copies data and code sections which are mapped into IRAM and DRAM to their load addresses. For sections which have load addresses in DROM and IROM regions, flash MMU is configured to provide the correct mapping. Note that the second stage bootloader configures flash MMU for both PRO and APP CPUs, but it only enables flash MMU for PRO CPU. Reason for this is that second stage bootloader code is loaded into the memory region used by APP CPU cache. The duty of enabling cache for APP CPU is passed on to the application. Once code is loaded and flash MMU is set up, second stage bootloader jumps to the application entry point found in the binary image header.
+
+Currently it is not possible to add application-defined hooks to the bootloader to customize application partition selection logic. This may be required to load different application image depending on a state of a GPIO, for example. Such customization features will be added to ESP-IDF in the future. For now, bootloader can be customized by copying bootloader component into application directory and making necessary changes there. ESP-IDF build system will compile the component in application directory instead of ESP-IDF components directory in this case.
+
+Application startup
+^^^^^^^^^^^^^^^^^^^
+
+ESP-IDF application entry point is ``call_start_cpu0`` function found in ``components/esp32/cpu_start.c``. Two main things this function does are to enable heap allocator and to make APP CPU jump to its entry point, ``call_start_cpu1``. The code on PRO CPU sets the entry point for APP CPU, de-asserts APP CPU reset, and waits for a global flag to be set by the code running on APP CPU, indicating that it has started. Once this is done, PRO CPU jumps to ``start_cpu0`` function, and APP CPU jumps to ``start_cpu1`` function.
+
+Both ``start_cpu0`` and ``start_cpu1`` are weak functions, meaning that they can be overridden in the application, if some application-specific change to initialization sequence is needed. Default implementation of ``start_cpu0`` enables or initializes components depending on choices made in ``menuconfig``. Please see source code of this function in ``components/esp32/cpu_start.c`` for an up to date list of steps performed. Note that any C++ global constructors present in the application will be called at this stage. Once all essential components are initialized, *main task* is created and FreeRTOS scheduler is started. 
+
+While PRO CPU does initialization in ``start_cpu0`` function, APP CPU spins in ``start_cpu1`` function, waiting for the scheduler to be started on the PRO CPU. Once the scheduler is started on the PRO CPU, code on the APP CPU starts the scheduler as well.
+
+Main task is the task which runs ``app_main`` function. Main task stack size and priority can be configured in ``menuconfig``. Application can use this task for initial application-specific setup, for example to launch other tasks. Application can also use main task for event loops and other general purpose activities. If ``app_main`` function returns, main task is deleted.
+
+
+Application memory layout
+-------------------------
+
+ESP32 chip has flexible memory mapping features. This section describes how ESP-IDF uses these features by default.
+
+Application code in ESP-IDF can be placed into one of the following memory regions.
+
+IRAM (instruction RAM)
+^^^^^^^^^^^^^^^^^^^^^^
+
+ESP-IDF allocates part of `Internal SRAM0` region (defined in the Technical Reference Manual) for instruction RAM. Except for the first 64 kB block which is used for PRO and APP CPU caches, the rest of this memory range (i.e. from ``0x40080000`` to ``0x400A0000``) is used to store parts of application which need to run from RAM.
+
+A few components of ESP-IDF and parts of WiFi stack are placed into this region using the linker script.
+
+If some application code needs to be placed into IRAM, it can be done using ``IRAM_ATTR`` define::
+
+	#include "esp_attr.h"
+	
+	void IRAM_ATTR gpio_isr_handler(void* arg)
+	{
+		// ...		
+	}
+
+Here are the cases when parts of application may or should be placed into IRAM.
+
+- ISR handlers must always be placed into IRAM. Furthermore, ISR handlers may only call functions placed into IRAM or functions present in ROM. *Note 1:* all FreeRTOS APIs are currently placed into IRAM, so are safe to call from ISR handlers. *Note 1:* all constant data used by ISR handlers and functions called from ISR handlers (including, but not limited to, ``const char`` arrays), must be placed into DRAM using ``DRAM_ATTR``.
+
+- Some timing critical code may be placed into IRAM to reduce the penalty associated with loading the code from flash. ESP32 reads code and data from flash via a 32 kB cache. In some cases, placing a function into IRAM may reduce delays caused by a cache miss.
+
+IROM (code executed from Flash)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+If a function is not explicitly placed into IRAM or RTC memory, it is placed into flash. The mechanism by which Flash MMU is used to allow code execution from flash is described in the Technical Reference Manual. ESP-IDF places the code which should be executed from flash starting from the beginning of ``0x400D0000 — 0x40400000`` region. Upon startup, second stage bootloader initializes Flash MMU to map the location in flash where code is located into the beginning of this region. Access to this region is transparently cached using two 32kB blocks in ``0x40070000`` — ``0x40080000`` range.
+
+Note that the code outside ``0x40000000 — 0x40400000`` region may not be reachable with Window ABI ``CALLx`` instructions, so special care is required if ``0x40400000 — 0x40800000`` or ``0x40800000 — 0x40C00000`` regions are used by the application. ESP-IDF doesn't use these regions by default.
+
+RTC fast memory
+^^^^^^^^^^^^^^^
+
+The code which has to run after wake-up from deep sleep mode has to be placed into RTC memory. Please check detailed description in :doc:`deep sleep <deep-sleep-stub>` documentation.
+
+DRAM (data RAM)
+^^^^^^^^^^^^^^^
+
+Non-constant static data and zero-initialized data is placed by the linker into 200 kB ``0x3FFB0000 — 0x3FFF0000`` region. Note that this region is reduced by 64kB (by shifting start address to ``0x3FFC0000``) if Bluetooth stack is used. Length of this region is also reduced by 16 kB or 32kB if trace memory is used. All space which is left in this region after placing static data there is used for the runtime heap.
+
+Constant data may also be placed into DRAM, for example if it is used in an ISR handler (see notes in IRAM section above). To do that, ``DRAM_ATTR`` define can be used::
+
+	DRAM_ATTR const char[] format_string = "%p %x";
+	char buffer[64];
+	sprintf(buffer, format_string, ptr, val);
+
+Needless to say, it is not advised to use ``printf`` and other output functions in ISR handlers. For debugging purposes, use ``ESP_EARLY_LOGx`` macros when logging from ISR handlers. Make sure that both ``TAG`` and format string are placed into ``DRAM`` in that case.
+
+DROM (data stored in Flash)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+By default, constant data is placed by the linker into a 4 MB region (``0x3F400000 — 0x3F800000``) which is used to access external flash memory via Flash MMU and cache. Exceptions to this are literal constants which are embedded by the compiler into application code.
+
+RTC slow memory
+^^^^^^^^^^^^^^^
+
+Global and static variables used by code which runs from RTC memory (i.e. deep sleep stub code) must be placed into RTC slow memory. Please check detailed description in :doc:`deep sleep <deep-sleep-stub>` documentation.
+
+
+
+

+ 2 - 1
docs/index.rst

@@ -28,6 +28,7 @@ Contents:
    :caption: What Else?
    :maxdepth: 1
    
+   General Notes <general-notes>
    partition-tables
    build_system
    openocd
@@ -97,7 +98,7 @@ Contents:
    api/gpio
    api/uart
    api/ledc
- 
+   SPI Flash and Partition APIs <api/spi_flash>
    Logging <api/log>
    Non-Volatile Storage <api/nvs_flash>
    Virtual Filesystem <api/vfs>

+ 1 - 3
docs/openocd.rst

@@ -40,10 +40,8 @@ Installing OpenOCD
 The sources for the ESP32-enabled variant of OpenOCD are available from `Espressifs Github <https://github.com/espressif/openocd-esp32>`_. 
 To download the source, use the following commands::
 
-    git clone https://github.com/espressif/openocd-esp32.git
+    git clone --recursive https://github.com/espressif/openocd-esp32.git
     cd openocd-esp32
-    git submodule init
-    git submodule update
 
 For compilation of OpenOCD, please refer to the README, README.OSX and README.Windows file in the openocd-esp32 directory. You can skip
 the ``make install`` step if you want.

+ 1 - 1
docs/partition-tables.rst

@@ -23,7 +23,7 @@ Known Issues
 The below design document outlines the goals for the partition table system. At the moment, only some features are used:
 
 - data partition types "rf" & "wifi" are unused and can be entirely omitted to save space.
-- NVS (non-volatile-storage) uses a hardcoded 12KB (0x3000 byte) region at offset 0x6000.
+- NVS (non-volatile-storage) uses a hardcoded 12KB (0x3000 byte) region at offset 0x9000.
 
 Once a full user API is in place for partition access, these limitations will be resolved and you'll be able to use the partition mechanism fully for storing data in flash.
 

+ 6 - 6
docs/security/secure-boot.rst

@@ -14,7 +14,7 @@ Background
 
 - Efuses are used to store the secure bootloader key (in efuse block 2), and also a single Efuse bit (ABS_DONE_0) is burned (written to 1) to permanently enable secure boot on the chip. For more details about efuse, see the (forthcoming) chapter in the Technical Reference Manual.
 
-- To understand the secure boot process, first familiarise yourself with the standard `esp-idf boot process`.
+- To understand the secure boot process, first familiarise yourself with the standard :doc:`ESP-IDF boot process <../general-notes>`.
 
 - Both stages of the boot process (initial software bootloader load, and subsequent partition & app loading) are verified by the secure boot process, in a "chain of trust" relationship.
 
@@ -30,10 +30,11 @@ This is a high level overview of the secure boot process. Step by step instructi
 2. The software bootloader image is built by esp-idf with secure boot support enabled and the public key (signature verification) portion of the secure boot signing key compiled in. This software bootloader image is flashed at offset 0x1000.
 
 3. On first boot, the software bootloader follows the following process to enable secure boot:
-  - Hardware secure boot support generates a device secure bootloader key (generated via hardware RNG, then stored read/write protected in efuse), and a secure digest. The digest is derived from the key, an IV, and the bootloader image contents.
-  - The secure digest is flashed at offset 0x0 in the flash.
-  - Depending on Secure Boot Configuration, efuses are burned to disable JTAG and the ROM BASIC interpreter (it is strongly recommended these options are turned on.)
-  - Bootloader permanently enables secure boot by burning the ABS_DONE_0 efuse. The software bootloader then becomes protected (the chip will only boot a bootloader image if the digest matches.)
+
+   - Hardware secure boot support generates a device secure bootloader key (generated via hardware RNG, then stored read/write protected in efuse), and a secure digest. The digest is derived from the key, an IV, and the bootloader image contents.
+   - The secure digest is flashed at offset 0x0 in the flash.
+   - Depending on Secure Boot Configuration, efuses are burned to disable JTAG and the ROM BASIC interpreter (it is strongly recommended these options are turned on.)
+   - Bootloader permanently enables secure boot by burning the ABS_DONE_0 efuse. The software bootloader then becomes protected (the chip will only boot a bootloader image if the digest matches.)
 
 4. On subsequent boots the ROM bootloader sees that the secure boot efuse is burned, reads the saved digest at 0x0 and uses hardware secure boot support to compare it with a newly calculated digest. If the digest does not match then booting will not continue. The digest and comparison are performed entirely by hardware, and the calculated digest is not readable by software. For technical details see `Hardware Secure Boot Support`.
 
@@ -175,5 +176,4 @@ Deterministic ECDSA as specified by `RFC6979`.
 - Image signature is 68 bytes - a 4 byte version word (currently zero), followed by a 64 bytes of signature data. These 68 bytes are appended to an app image or partition table data.
 
 
-.. _esp-idf boot process: ../boot-process.rst
 .. _RFC6979: https://tools.ietf.org/html/rfc6979

+ 1 - 1
examples/01_hello_world/main/component.mk

@@ -1,5 +1,5 @@
 #
-# Main Makefile. This is basically the same as a component makefile.
+# "main" pseudo-component makefile.
 #
 # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
 

+ 1 - 1
examples/02_blink/main/component.mk

@@ -1,4 +1,4 @@
 #
-# Main Makefile. This is basically the same as a component makefile.
+# "main" pseudo-component makefile.
 #
 # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)

+ 1 - 1
examples/03_http_request/main/component.mk

@@ -1,4 +1,4 @@
 #
-# Main Makefile. This is basically the same as a component makefile.
+# "main" pseudo-component makefile.
 #
 # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)

+ 1 - 1
examples/04_https_request/main/component.mk

@@ -1,5 +1,5 @@
 #
-# Main Makefile. This is basically the same as a component makefile.
+# "main" pseudo-component makefile.
 #
 # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
 

+ 1 - 1
examples/05_ble_adv/main/component.mk

@@ -1,4 +1,4 @@
 #
-# Main Makefile. This is basically the same as a component makefile.
+# "main" pseudo-component makefile.
 #
 # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)

+ 1 - 1
examples/06_sntp/main/component.mk

@@ -1,4 +1,4 @@
 #
-# Main Makefile. This is basically the same as a component makefile.
+# "main" pseudo-component makefile.
 #
 # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)

+ 4 - 1
examples/07_nvs_rw_value/main/component.mk

@@ -1,2 +1,5 @@
+#
+# "main" pseudo-component makefile.
+#
+# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
 
-include $(IDF_PATH)/make/component_common.mk

+ 4 - 1
examples/08_nvs_rw_blob/main/component.mk

@@ -1,2 +1,5 @@
+#
+# "main" pseudo-component makefile.
+#
+# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
 
-include $(IDF_PATH)/make/component_common.mk

+ 7 - 2
make/build_examples.sh

@@ -20,8 +20,13 @@ for example in ${IDF_PATH}/examples/*; do
     mkdir ${EXAMPLE_NUM}
     cp -r ${example} ${EXAMPLE_NUM}
     pushd ${EXAMPLE_NUM}/`basename ${example}`
-    # build non-verbose first, only build verbose if there's an error
-    make defconfig all || (RESULT=$?; make V=1)
+
+   # be stricter in the CI build than the default IDF settings
+   export EXTRA_CFLAGS="-Werror -Werror=deprecated-declarations"
+   export EXTRA_CXXFLAGS=${EXTRA_CFLAGS}
+
+   # build non-verbose first, only build verbose if there's an error
+    (make clean defconfig && make all ) || (RESULT=$?; make V=1)
     popd
     EXAMPLE_NUM=$(( $EXAMPLE_NUM + 1 ))
 done

+ 0 - 25
make/common.mk

@@ -26,31 +26,6 @@ details := @true
 MAKEFLAGS += --silent
 endif
 
-# Pseudo-target to check a git submodule has been properly initialised
-#
-# $(eval $(call SubmoduleCheck,FILENAMES,SUBMODULE_PATH)) to create a target that
-# automatically runs 'git submodule update --init SUBMODULE_PATH' if any of
-# the files in FILENAMES are missing, and fails if this is not possible.
-#
-# Will also print a WARNING if the submodule at SUBMODULE_PATH appears
-# to require an update.
-define SubmoduleCheck
-$(1):
-	@echo "WARNING: Missing submodule $(2) for $$@..."
-	[ -d ${IDF_PATH}/.git ] || ( echo "ERROR: esp-idf must be cloned from git to work."; exit 1)
-	[ -x $(which git) ] || ( echo "ERROR: Need to run 'git submodule --init' in esp-idf root directory."; exit 1)
-	@echo "Attempting 'git submodule update --init' in esp-idf root directory..."
-	cd ${IDF_PATH} && git submodule update --init $(2)
-
-# Parse 'git submodule status' output for out-of-date submodule.
-# Status output prefixes status line with '+' if the submodule commit doesn't match
-ifneq ("$(shell cd ${IDF_PATH} && git submodule status $(2) | grep '^+')","")
-$$(info WARNING: git submodule $2 may be out of date. Run 'git submodule update' to update.)
-endif
-endef
-
-
-
 # General make utilities
 
 # convenience variable for printing an 80 asterisk wide separator line

+ 23 - 11
make/component_wrapper.mk

@@ -103,8 +103,8 @@ endef
 
 # component_project_vars.mk target for the component. This is used to
 # take component.mk variables COMPONENT_ADD_INCLUDEDIRS,
-# COMPONENT_ADD_LDFLAGS and COMPONENT_DEPENDS and inject those into
-# the project make pass.
+# COMPONENT_ADD_LDFLAGS, COMPONENT_DEPENDS and COMPONENT_SUBMODULES
+# and inject those into the project make pass.
 #
 # The target here has no dependencies, as the parent target in
 # project.mk evaluates dependencies before calling down to here. See
@@ -119,6 +119,7 @@ component_project_vars.mk::
 	@echo '# Automatically generated build file. Do not edit.' > $@
 	@echo 'COMPONENT_INCLUDES += $(call MakeVariablePath,$(addprefix $(COMPONENT_PATH)/,$(COMPONENT_ADD_INCLUDEDIRS)))' >> $@
 	@echo 'COMPONENT_LDFLAGS += $(call MakeVariablePath,$(COMPONENT_ADD_LDFLAGS))' >> $@
+	@echo 'COMPONENT_SUBMODULES += $(call MakeVariablePath,$(addprefix $(COMPONENT_PATH)/,$(COMPONENT_SUBMODULES)))' >> $@
 	@echo '$(COMPONENT_NAME)-build: $(addsuffix -build,$(COMPONENT_DEPENDS))' >> $@
 
 
@@ -179,7 +180,7 @@ $(foreach srcdir,$(COMPONENT_SRCDIRS), $(eval $(call GenerateCompileTargets,$(sr
 
 ## Support for embedding binary files into the ELF as symbols
 
-OBJCOPY_EMBED_ARGS := --input binary --output elf32-xtensa-le --binary-architecture xtensa --rename-section .data=.rodata.embedded
+OBJCOPY_EMBED_ARGS := --input-target binary --output-target elf32-xtensa-le --binary-architecture xtensa --rename-section .data=.rodata.embedded
 
 # Generate pattern for embedding text or binary files into the app
 # $(1) is name of file (as relative path inside component)
@@ -188,18 +189,29 @@ OBJCOPY_EMBED_ARGS := --input binary --output elf32-xtensa-le --binary-architect
 # txt files are null-terminated before being embedded (otherwise
 # identical behaviour.)
 #
-# Files are temporarily copied to the build directory before objcopy,
-# because objcopy generates the symbol name from the full command line
-# path to the input file.
 define GenerateEmbedTarget
-$(1).$(2).o: $(call resolvepath,$(1),$(COMPONENT_PATH)) | $$(dir $(1))
+
+# copy the input file into the build dir (using a subdirectory
+# in case the file already exists elsewhere in the build dir)
+embed_bin/$$(notdir $(1)): $(call resolvepath,$(1),$(COMPONENT_PATH)) | embed_bin
+	cp $$< $$@
+
+embed_txt/$$(notdir $(1)): $(call resolvepath,$(1),$(COMPONENT_PATH)) | embed_txt
+	cp $$< $$@
+	echo -ne '\0' >> $$@  # null-terminate text files
+
+# messing about with the embed_X subdirectory then using 'cd' for objcopy is because the
+# full path passed to OBJCOPY makes it into the name of the symbols in the .o file
+$(1).$(2).o: embed_$(2)/$$(notdir $(1)) | $$(dir $(1))
 	$(summary) EMBED $$@
-	$$(if $$(filter-out $$(notdir $$(abspath $$<)),$$(abspath $$(notdir $$<))), cp $$< $$(notdir $$<) )  # copy input file to build dir, unless already in build dir
-	$$(if $$(subst bin,,$(2)),echo -ne '\0' >> $$(notdir $$<) )  # trailing NUL byte on text output
-	$(OBJCOPY) $(OBJCOPY_EMBED_ARGS) $$(notdir $$<) $$@
-	rm $$(notdir $$<)
+	cd embed_$(2); $(OBJCOPY) $(OBJCOPY_EMBED_ARGS) $$(notdir $$<) ../$$@
+
+CLEAN_FILES += embed_$(2)/$$(notdir $(1))
 endef
 
+embed_txt embed_bin:
+	mkdir -p $@
+
 # generate targets to embed binary & text files
 $(foreach binfile,$(COMPONENT_EMBED_FILES), $(eval $(call GenerateEmbedTarget,$(binfile),bin)))
 

+ 43 - 10
make/project.mk

@@ -10,7 +10,7 @@
 # where this file is located.
 #
 
-.PHONY: build-components menuconfig defconfig all build clean all_binaries
+.PHONY: build-components menuconfig defconfig all build clean all_binaries check-submodules
 all: all_binaries
 # see below for recipe of 'all' target
 #
@@ -94,13 +94,16 @@ COMPONENT_PATHS += $(abspath $(SRCDIRS))
 # A component is buildable if it has a component.mk makefile in it
 COMPONENT_PATHS_BUILDABLE := $(foreach cp,$(COMPONENT_PATHS),$(if $(wildcard $(cp)/component.mk),$(cp)))
 
-# Initialise a project-wide list of include dirs (COMPONENT_INCLUDES),
-# and LDFLAGS args (COMPONENT_LDFLAGS) supplied by each component.
+# Initialise project-wide variables which can be added to by
+# each component.
 #
 # These variables are built up via the component_project_vars.mk
 # generated makefiles (one per component).
+#
+# See docs/build-system.rst for more details.
 COMPONENT_INCLUDES :=
 COMPONENT_LDFLAGS :=
+COMPONENT_SUBMODULES :=
 
 # COMPONENT_PROJECT_VARS is the list of component_project_vars.mk generated makefiles
 # for each component.
@@ -158,14 +161,16 @@ LDFLAGS ?= -nostdlib \
 
 # CPPFLAGS used by C preprocessor
 # If any flags are defined in application Makefile, add them at the end. 
-CPPFLAGS := -DESP_PLATFORM $(CPPFLAGS)
+CPPFLAGS := -DESP_PLATFORM $(CPPFLAGS) $(EXTRA_CPPFLAGS)
 
 # Warnings-related flags relevant both for C and C++
-COMMON_WARNING_FLAGS = -Wall -Werror \
+COMMON_WARNING_FLAGS = -Wall -Werror=all \
 	-Wno-error=unused-function \
 	-Wno-error=unused-but-set-variable \
 	-Wno-error=unused-variable \
-	-Wno-error=deprecated-declarations
+	-Wno-error=deprecated-declarations \
+	-Wextra \
+	-Wno-unused-parameter -Wno-sign-compare
 
 # Flags which control code generation and dependency generation, both for C and C++
 COMMON_FLAGS = \
@@ -192,8 +197,9 @@ CFLAGS := $(strip \
 	-std=gnu99 \
 	$(OPTIMIZATION_FLAGS) \
 	$(COMMON_FLAGS) \
-	$(COMMON_WARNING_FLAGS) \
-	$(CFLAGS))
+	$(COMMON_WARNING_FLAGS) -Wno-old-style-declaration \
+	$(CFLAGS) \
+	$(EXTRA_CFLAGS))
 
 # List of flags to pass to C++ compiler
 # If any flags are defined in application Makefile, add them at the end.
@@ -204,7 +210,8 @@ CXXFLAGS := $(strip \
 	$(OPTIMIZATION_FLAGS) \
 	$(COMMON_FLAGS) \
 	$(COMMON_WARNING_FLAGS) \
-	$(CXXFLAGS))
+	$(CXXFLAGS) \
+	$(EXTRA_CXXFLAGS))
 
 export CFLAGS CPPFLAGS CXXFLAGS
 
@@ -285,7 +292,7 @@ endef
 define GenerateComponentTargets
 .PHONY: $(2)-build $(2)-clean
 
-$(2)-build:
+$(2)-build: check-submodules
 	$(call ComponentMake,$(1),$(2)) build
 
 $(2)-clean:
@@ -328,4 +335,30 @@ app-clean: $(addsuffix -clean,$(notdir $(COMPONENT_PATHS_BUILDABLE)))
 config-clean: app-clean
 clean: config-clean
 
+# phony target to check if any git submodule listed in COMPONENT_SUBMODULES are missing
+# or out of date, and exit if so. Components can add paths to this variable.
+#
+# This only works for components inside IDF_PATH
+check-submodules:
+
+# Generate a target to check this submodule
+# $(1) - submodule directory, relative to IDF_PATH
+define GenerateSubmoduleCheckTarget
+check-submodules: $(IDF_PATH)/$(1)/.git
+$(IDF_PATH)/$(1)/.git:
+	@echo "WARNING: Missing submodule $(1)..."
+	[ -d ${IDF_PATH}/.git ] || ( echo "ERROR: esp-idf must be cloned from git to work."; exit 1)
+	[ -x $(which git) ] || ( echo "ERROR: Need to run 'git submodule init $(1)' in esp-idf root directory."; exit 1)
+	@echo "Attempting 'git submodule update --init $(1)' in esp-idf root directory..."
+	cd ${IDF_PATH} && git submodule update --init $(1)
+
+# Parse 'git submodule status' output for out-of-date submodule.
+# Status output prefixes status line with '+' if the submodule commit doesn't match
+ifneq ("$(shell cd ${IDF_PATH} && git submodule status $(1) | grep '^+')","")
+$$(info WARNING: git submodule $(1) may be out of date. Run 'git submodule update' to update.)
+endif
+endef
 
+# filter/subst in expression ensures all submodule paths begin with $(IDF_PATH), and then strips that prefix
+# so the argument is suitable for use with 'git submodule' commands
+$(foreach submodule,$(subst $(IDF_PATH)/,,$(filter $(IDF_PATH)/%,$(COMPONENT_SUBMODULES))),$(eval $(call GenerateSubmoduleCheckTarget,$(submodule))))