From dec846a9530a395c164c95484cff8ab7053db964 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Wed, 24 Aug 2016 18:01:01 +0800 Subject: [PATCH 01/51] components/spi_flash: make spi_flash APIs dual-core-compatible See esp_spi_flash.c for implementation notes. --- components/spi_flash/esp_spi_flash.c | 258 ++++++++++++++----- components/spi_flash/include/esp_spi_flash.h | 9 + 2 files changed, 197 insertions(+), 70 deletions(-) diff --git a/components/spi_flash/esp_spi_flash.c b/components/spi_flash/esp_spi_flash.c index df919bc2d0..e3d09acaf0 100644 --- a/components/spi_flash/esp_spi_flash.c +++ b/components/spi_flash/esp_spi_flash.c @@ -21,6 +21,194 @@ #include #include #include +#include "sdkconfig.h" + +/* + Driver for SPI flash read/write/erase operations + + In order to perform some flash operations, we need to make sure both CPUs + are not running any code from flash for the duration of the flash operation. + In a single-core setup this is easy: we disable interrupts/scheduler and do + the flash operation. In the dual-core setup this is slightly more complicated. + We need to make sure that the other CPU doesn't run any code from flash. + + SPI flash driver starts two tasks (spi_flash_op_block_task), one pinned to + each CPU. Each task is associated with its own semaphore. + + When SPI flash API is called on CPU A (can be PRO or APP), we wake up the task + on CPU B by "giving" the semaphore associated with it. Tasks resumes, disables + cache on CPU B, and acknowledges that it has taken the semaphore by setting + a flag (s_flash_op_can_start). Flash API function running on CPU A waits for + this flag to be set. Once the flag is set, it disables cache on CPU A and + starts flash operation. + + While flash operation is running, interrupts can still run on CPU B. + We assume that all interrupt code is placed into RAM. + + Once flash operation is complete, function on CPU A sets another flag, + s_flash_op_complete, to let the task on CPU B know that it can re-enable + cache and release the CPU. Then the function on CPU A re-enables the cache on + CPU A as well and returns control to the calling code. Task on CPU B returns + to suspended state by "taking" the semaphore. + + Additionally, all API functions are protected with a mutex (s_flash_op_mutex). + + In a single core environment (CONFIG_FREERTOS_UNICORE enabled), we simply + disable both caches, no inter-CPU communication takes place. +*/ + +static esp_err_t spi_flash_translate_rc(SpiFlashOpResult rc); +extern void Cache_Flush(int); + +#ifndef CONFIG_FREERTOS_UNICORE + +static TaskHandle_t s_flash_op_tasks[2]; +static SemaphoreHandle_t s_flash_op_mutex; +static SemaphoreHandle_t s_flash_op_sem[2]; +static bool s_flash_op_can_start = false; +static bool s_flash_op_complete = false; + + +// Task whose duty is to block other tasks from running on a given CPU +static void IRAM_ATTR spi_flash_op_block_task(void* arg) +{ + uint32_t cpuid = (uint32_t) arg; + while (true) { + // Wait for flash operation to be initiated. + // This will be indicated by giving the semaphore corresponding to + // this CPU. + if (xSemaphoreTake(s_flash_op_sem[cpuid], portMAX_DELAY) != pdTRUE) { + // TODO: when can this happen? + abort(); + } + // Disable cache on this CPU + Cache_Read_Disable(cpuid); + // Signal to the flash API function that flash operation can start + s_flash_op_can_start = true; + while (!s_flash_op_complete) { + // until we have a way to use interrupts for inter-CPU communication, + // busy loop here and wait for the other CPU to finish flash operation + } + // Flash operation is complete, re-enable cache + Cache_Read_Enable(cpuid); + } + // TODO: currently this is unreachable code. Introduce spi_flash_uninit + // function which will signal to both tasks that they can shut down. + // Not critical at this point, we don't have a use case for stopping + // SPI flash driver yet. + // Also need to delete the semaphore here. + vTaskDelete(NULL); +} + +void spi_flash_init() +{ + s_flash_op_can_start = false; + s_flash_op_complete = false; + s_flash_op_sem[0] = xSemaphoreCreateBinary(); + s_flash_op_sem[1] = xSemaphoreCreateBinary(); + s_flash_op_mutex = xSemaphoreCreateMutex(); + // Start two tasks, one on each CPU, with max priorities + // TODO: optimize stack usage. Stack size 512 is too small. + xTaskCreatePinnedToCore(spi_flash_op_block_task, "flash_op_pro", 1024, (void*) 0, + configMAX_PRIORITIES - 1, &s_flash_op_tasks[0], 0); + xTaskCreatePinnedToCore(spi_flash_op_block_task, "flash_op_app", 1024, (void*) 1, + configMAX_PRIORITIES - 1, &s_flash_op_tasks[1], 1); +} + +static void IRAM_ATTR spi_flash_disable_interrupts_caches_and_other_cpu() +{ + // Take the API lock + xSemaphoreTake(s_flash_op_mutex, portMAX_DELAY); + const uint32_t cpuid = xPortGetCoreID(); + uint32_t other_cpuid = !cpuid; + s_flash_op_can_start = false; + s_flash_op_complete = false; + // Signal to the spi_flash_op_block_task on the other CPU that we need it to + // disable cache there and block other tasks from executing. + xSemaphoreGive(s_flash_op_sem[other_cpuid]); + while (!s_flash_op_can_start) { + // Busy loop and wait for spi_flash_op_block_task to take the semaphore on the + // other CPU. + } + vTaskSuspendAll(); + // Disable cache on this CPU as well + Cache_Read_Disable(cpuid); +} + +static void IRAM_ATTR spi_flash_enable_interrupts_caches_and_other_cpu() +{ + uint32_t cpuid = xPortGetCoreID(); + // Signal to spi_flash_op_block_task that flash operation is complete + s_flash_op_complete = true; + // Re-enable cache on this CPU + Cache_Read_Enable(cpuid); + // Release API lock + xSemaphoreGive(s_flash_op_mutex); + xTaskResumeAll(); +} + +#else // CONFIG_FREERTOS_UNICORE + +void spi_flash_init() +{ + // No-op in single core mode +} + +static void IRAM_ATTR spi_flash_disable_interrupts_caches_and_other_cpu() +{ + vTaskSuspendAll(); + Cache_Read_Disable(0); + Cache_Read_Disable(1); +} + +static void IRAM_ATTR spi_flash_enable_interrupts_caches_and_other_cpu() +{ + Cache_Read_Enable(0); + Cache_Read_Enable(1); + xTaskResumeAll(); +} + +#endif // CONFIG_FREERTOS_UNICORE + + +esp_err_t IRAM_ATTR spi_flash_erase_sector(uint16_t sec) +{ + spi_flash_disable_interrupts_caches_and_other_cpu(); + SpiFlashOpResult rc; + rc = SPIUnlock(); + if (rc == SPI_FLASH_RESULT_OK) { + rc = SPIEraseSector(sec); + } + Cache_Flush(0); + Cache_Flush(1); + spi_flash_enable_interrupts_caches_and_other_cpu(); + return spi_flash_translate_rc(rc); +} + +esp_err_t IRAM_ATTR spi_flash_write(uint32_t dest_addr, const uint32_t *src, uint32_t size) +{ + spi_flash_disable_interrupts_caches_and_other_cpu(); + SpiFlashOpResult rc; + rc = SPIUnlock(); + if (rc == SPI_FLASH_RESULT_OK) { + rc = SPIWrite(dest_addr, src, (int32_t) size); + } + Cache_Flush(0); + Cache_Flush(1); + spi_flash_enable_interrupts_caches_and_other_cpu(); + return spi_flash_translate_rc(rc); +} + +esp_err_t IRAM_ATTR spi_flash_read(uint32_t src_addr, uint32_t *dest, uint32_t size) +{ + spi_flash_disable_interrupts_caches_and_other_cpu(); + SpiFlashOpResult rc; + rc = SPIRead(src_addr, dest, (int32_t) size); + Cache_Flush(0); + Cache_Flush(1); + spi_flash_enable_interrupts_caches_and_other_cpu(); + return spi_flash_translate_rc(rc); +} static esp_err_t spi_flash_translate_rc(SpiFlashOpResult rc) { @@ -34,73 +222,3 @@ static esp_err_t spi_flash_translate_rc(SpiFlashOpResult rc) return ESP_ERR_FLASH_OP_FAIL; } } - -extern void Cache_Flush(int); - -static void IRAM_ATTR spi_flash_disable_interrupts_caches_and_app_cpu() -{ - vTaskSuspendAll(); - // SET_PERI_REG_MASK(APPCPU_CTRL_REG_C, DPORT_APPCPU_RUNSTALL); - Cache_Read_Disable(0); - Cache_Read_Disable(1); -} - -static void IRAM_ATTR spi_flash_enable_interrupts_caches_and_app_cpu() -{ - Cache_Read_Enable(0); - Cache_Read_Enable(1); - // CLEAR_PERI_REG_MASK(APPCPU_CTRL_REG_C, DPORT_APPCPU_RUNSTALL); - xTaskResumeAll(); -} - -esp_err_t IRAM_ATTR spi_flash_erase_sector(uint16_t sec) -{ - spi_flash_disable_interrupts_caches_and_app_cpu(); - SpiFlashOpResult rc; - if (xPortGetCoreID() == 1) { - rc = SPI_FLASH_RESULT_ERR; - } - else { - rc = SPIUnlock(); - if (rc == SPI_FLASH_RESULT_OK) { - rc = SPIEraseSector(sec); - } - } - Cache_Flush(0); - Cache_Flush(1); - spi_flash_enable_interrupts_caches_and_app_cpu(); - return spi_flash_translate_rc(rc); -} - -esp_err_t IRAM_ATTR spi_flash_write(uint32_t dest_addr, const uint32_t *src, uint32_t size) -{ - spi_flash_disable_interrupts_caches_and_app_cpu(); - SpiFlashOpResult rc; - if (xPortGetCoreID() == 1) { - rc = SPI_FLASH_RESULT_ERR; - } - else { - rc = SPIUnlock(); - if (rc == SPI_FLASH_RESULT_OK) { - rc = SPIWrite(dest_addr, src, (int32_t) size); - } - } - Cache_Flush(0); - Cache_Flush(1); - spi_flash_enable_interrupts_caches_and_app_cpu(); - return spi_flash_translate_rc(rc); -} - -esp_err_t IRAM_ATTR spi_flash_read(uint32_t src_addr, uint32_t *dest, uint32_t size) -{ - spi_flash_disable_interrupts_caches_and_app_cpu(); - SpiFlashOpResult rc; - if (xPortGetCoreID() == 1) { - rc = SPI_FLASH_RESULT_ERR; - } - else { - rc = SPIRead(src_addr, dest, (int32_t) size); - } - spi_flash_enable_interrupts_caches_and_app_cpu(); - return spi_flash_translate_rc(rc); -} diff --git a/components/spi_flash/include/esp_spi_flash.h b/components/spi_flash/include/esp_spi_flash.h index aa12b2aa42..da6b03c0d1 100644 --- a/components/spi_flash/include/esp_spi_flash.h +++ b/components/spi_flash/include/esp_spi_flash.h @@ -28,6 +28,15 @@ extern "C" { #define SPI_FLASH_SEC_SIZE 4096 /**< SPI Flash sector size */ +/** + * @brief Initialize SPI flash access driver + * + * This function must be called exactly once, before any other + * spi_flash_* functions are called. + * + */ +void spi_flash_init(); + /** * @brief Erase the Flash sector. * From d793d23b94ff93c08354912ec6ed9e5c75c083a3 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Thu, 1 Sep 2016 18:27:51 +1000 Subject: [PATCH 02/51] Remove bin/ directory in favour of an add_path.sh script that can be sourced Remaining file in bin/ will be moved out as part of !34 --- add_path.sh | 17 +++++++++++++++++ components/esptool_py/Makefile.projbuild | 2 +- {bin => components/esptool_py}/esptool.py | 0 components/partition_table/Makefile.projbuild | 2 +- .../partition_table}/gen_esp32part.py | 0 5 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 add_path.sh rename {bin => components/esptool_py}/esptool.py (100%) rename {bin => components/partition_table}/gen_esp32part.py (100%) diff --git a/add_path.sh b/add_path.sh new file mode 100644 index 0000000000..681c2e94bd --- /dev/null +++ b/add_path.sh @@ -0,0 +1,17 @@ +# This shell snippet appends useful esp-idf tools to your PATH environment +# variable. This means you can run esp-idf tools without needing to give the +# full path. +# +# Use this script like this: +# +# source ${IDF_PATH}/add_path.sh +# +if [ -z ${IDF_PATH} ]; then + echo "IDF_PATH must be set before including this script." +else + IDF_ADD_PATHS_EXTRAS="${IDF_PATH}/components/esptool_py/:${IDF_PATH}/components/partition_table/" + export PATH="${PATH}:${IDF_ADD_PATHS_EXTRAS}" + echo "Added to PATH: ${IDF_ADD_PATHS_EXTRAS}" +fi + + diff --git a/components/esptool_py/Makefile.projbuild b/components/esptool_py/Makefile.projbuild index 576e526d56..44dcf62ecf 100644 --- a/components/esptool_py/Makefile.projbuild +++ b/components/esptool_py/Makefile.projbuild @@ -9,7 +9,7 @@ PYTHON ?= $(call dequote,$(CONFIG_PYTHON)) # to invoke esptool.py (with or without serial port args) # # NB: esptool.py lives in the sdk/bin directory not the component directory -ESPTOOLPY := $(PYTHON) $(IDF_PATH)/bin/esptool.py --chip esp32 +ESPTOOLPY := $(PYTHON) $(IDF_PATH)/components/esptool_py/esptool.py --chip esp32 ESPTOOLPY_SERIAL := $(ESPTOOLPY) --port $(ESPPORT) --baud $(ESPBAUD) ESPTOOLPY_WRITE_FLASH=$(ESPTOOLPY_SERIAL) write_flash $(if $(CONFIG_ESPTOOLPY_COMPRESSED),-z) diff --git a/bin/esptool.py b/components/esptool_py/esptool.py similarity index 100% rename from bin/esptool.py rename to components/esptool_py/esptool.py diff --git a/components/partition_table/Makefile.projbuild b/components/partition_table/Makefile.projbuild index 0790733ac6..98631cc854 100644 --- a/components/partition_table/Makefile.projbuild +++ b/components/partition_table/Makefile.projbuild @@ -9,7 +9,7 @@ .PHONY: partition_table partition_table-flash partition_table-clean # NB: gen_esp32part.py lives in the sdk/bin/ dir not component dir -GEN_ESP32PART := $(PYTHON) $(IDF_PATH)/bin/gen_esp32part.py -q +GEN_ESP32PART := $(PYTHON) $(COMPONENT_PATH)/gen_esp32part.py -q # Path to partition CSV file is relative to project path for custom # partition CSV files, but relative to component dir otherwise.$ diff --git a/bin/gen_esp32part.py b/components/partition_table/gen_esp32part.py similarity index 100% rename from bin/gen_esp32part.py rename to components/partition_table/gen_esp32part.py From 96852d49c2809e48aeb040368a14e9829e7476f7 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Thu, 1 Sep 2016 18:30:57 +1000 Subject: [PATCH 03/51] Load esptool.py from submodule, currently WIP esptool.py v2.0 More details at https://github.com/themadinventor/esptool/pull/121 --- .gitmodules | 3 + add_path.sh | 2 +- components/esptool_py/Makefile.projbuild | 5 +- components/esptool_py/esptool | 1 + components/esptool_py/esptool.py | 1810 ---------------------- 5 files changed, 8 insertions(+), 1813 deletions(-) create mode 160000 components/esptool_py/esptool delete mode 100755 components/esptool_py/esptool.py diff --git a/.gitmodules b/.gitmodules index bd27e209be..1a0e6b94f1 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "components/esp32/lib"] path = components/esp32/lib url = https://github.com/espressif/esp32-wifi-lib.git +[submodule "components/esptool_py/esptool"] + path = components/esptool_py/esptool + url = https://github.com/themadinventor/esptool.git diff --git a/add_path.sh b/add_path.sh index 681c2e94bd..e2ef40c44b 100644 --- a/add_path.sh +++ b/add_path.sh @@ -9,7 +9,7 @@ if [ -z ${IDF_PATH} ]; then echo "IDF_PATH must be set before including this script." else - IDF_ADD_PATHS_EXTRAS="${IDF_PATH}/components/esptool_py/:${IDF_PATH}/components/partition_table/" + IDF_ADD_PATHS_EXTRAS="${IDF_PATH}/components/esptool_py/esptool:${IDF_PATH}/components/partition_table/" export PATH="${PATH}:${IDF_ADD_PATHS_EXTRAS}" echo "Added to PATH: ${IDF_ADD_PATHS_EXTRAS}" fi diff --git a/components/esptool_py/Makefile.projbuild b/components/esptool_py/Makefile.projbuild index 44dcf62ecf..4ddb51e6ac 100644 --- a/components/esptool_py/Makefile.projbuild +++ b/components/esptool_py/Makefile.projbuild @@ -9,10 +9,11 @@ PYTHON ?= $(call dequote,$(CONFIG_PYTHON)) # to invoke esptool.py (with or without serial port args) # # NB: esptool.py lives in the sdk/bin directory not the component directory -ESPTOOLPY := $(PYTHON) $(IDF_PATH)/components/esptool_py/esptool.py --chip esp32 +ESPTOOLPY := $(PYTHON) $(COMPONENT_PATH)/esptool/esptool.py --chip esp32 ESPTOOLPY_SERIAL := $(ESPTOOLPY) --port $(ESPPORT) --baud $(ESPBAUD) -ESPTOOLPY_WRITE_FLASH=$(ESPTOOLPY_SERIAL) write_flash $(if $(CONFIG_ESPTOOLPY_COMPRESSED),-z) +# the no-stub argument is temporary until esptool.py fully supports compressed uploads +ESPTOOLPY_WRITE_FLASH=$(ESPTOOLPY_SERIAL) $(if $(CONFIG_ESPTOOLPY_COMPRESSED),--no-stub) write_flash $(if $(CONFIG_ESPTOOLPY_COMPRESSED),-z) ESPTOOL_ALL_FLASH_ARGS += $(CONFIG_APP_OFFSET) $(APP_BIN) diff --git a/components/esptool_py/esptool b/components/esptool_py/esptool new file mode 160000 index 0000000000..7c84dd4335 --- /dev/null +++ b/components/esptool_py/esptool @@ -0,0 +1 @@ +Subproject commit 7c84dd433512bac80e4c01c569e42b4fe76646a7 diff --git a/components/esptool_py/esptool.py b/components/esptool_py/esptool.py deleted file mode 100755 index 284d9e95dd..0000000000 --- a/components/esptool_py/esptool.py +++ /dev/null @@ -1,1810 +0,0 @@ -#!/usr/bin/env python -# NB: Before sending a PR to change the above line to '#!/usr/bin/env python2', please read https://github.com/themadinventor/esptool/issues/21 -# -# ESP8266 ROM Bootloader Utility -# https://github.com/themadinventor/esptool -# -# Copyright (C) 2014-2016 Fredrik Ahlberg, Angus Gratton, other contributors as noted. -# ESP31/32 support Copyright (C) 2016 Angus Gratton, based in part on work Copyright -# (C) 2015-2016 Espressif Systems. -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free Software -# Foundation; either version 2 of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., 51 Franklin -# Street, Fifth Floor, Boston, MA 02110-1301 USA. - -import argparse -import hashlib -import inspect -import json -import os -import serial -import struct -import subprocess -import sys -import time -import zlib - -__version__ = "2.0-dev" - - -MAX_UINT32 = 0xffffffff -MAX_UINT24 = 0xffffff - - -class ESPROM(object): - """ Base class providing access to ESP ROM bootloader. Subclasses provide - ESP8266, ESP31 & ESP32 specific functionality. - - Don't instantiate this base class directly, either instantiate a subclass or - call ESPROM.detect_chip() which will interrogate the chip and return the - appropriate subclass instance. - - """ - CHIP_NAME = "Espressif device" - - DEFAULT_PORT = "/dev/ttyUSB0" - - # These are the currently known commands supported by the ROM - ESP_FLASH_BEGIN = 0x02 - ESP_FLASH_DATA = 0x03 - ESP_FLASH_END = 0x04 - ESP_MEM_BEGIN = 0x05 - ESP_MEM_END = 0x06 - ESP_MEM_DATA = 0x07 - ESP_SYNC = 0x08 - ESP_WRITE_REG = 0x09 - ESP_READ_REG = 0x0a - - # Maximum block sized for RAM and Flash writes, respectively. - ESP_RAM_BLOCK = 0x1800 - ESP_FLASH_BLOCK = 0x400 - - # Default baudrate. The ROM auto-bauds, so we can use more or less whatever we want. - ESP_ROM_BAUD = 115200 - - # First byte of the application image - ESP_IMAGE_MAGIC = 0xe9 - - # Initial state for the checksum routine - ESP_CHECKSUM_MAGIC = 0xef - - # Flash sector size, minimum unit of erase. - ESP_FLASH_SECTOR = 0x1000 - - UART_DATA_REG_ADDR = 0x60000078 - - # SPI peripheral "command" bitmasks - SPI_CMD_READ_ID = 0x10000000 - - # Memory addresses - IROM_MAP_START = 0x40200000 - IROM_MAP_END = 0x40300000 - - # The number of bytes in the response that signify command status - STATUS_BYTES_LENGTH = 2 - - def __init__(self, port=DEFAULT_PORT, baud=ESP_ROM_BAUD, do_connect=True): - """Base constructor for ESPROM objects - - Don't call this constructor, either instantiate ESP8266ROM, - ESP31ROM, or ESP32ROM, or use ESPROM.detect_chip(). - - """ - self._port = serial.Serial(port) - self._slip_reader = slip_reader(self._port) - # setting baud rate in a separate step is a workaround for - # CH341 driver on some Linux versions (this opens at 9600 then - # sets), shouldn't matter for other platforms/drivers. See - # https://github.com/themadinventor/esptool/issues/44#issuecomment-107094446 - self._port.baudrate = baud - if do_connect: - self.connect() - - @staticmethod - def detect_chip(port=DEFAULT_PORT, baud=ESP_ROM_BAUD): - """Use serial access to detect the chip type. - - We use the UART's datecode register for this, it's mapped at - the same address on ESP8266 & ESP31/32 so we can use one - memory read and compare to the datecode register for each chip - type. - - """ - detect_port = ESPROM(port, baud, True) - sys.stdout.write('Detecting chip type... ') - date_reg = detect_port.read_reg(ESPROM.UART_DATA_REG_ADDR) - for cls in [ESP8266ROM, ESP31ROM, ESP32ROM]: - if date_reg == cls.DATE_REG_VALUE: - inst = cls(port, baud, False) # don't connect a second time - print '%s' % inst.CHIP_NAME - return inst - print '' - raise FatalError("Unexpected UART datecode value 0x%08x. Failed to autodetect chip type." % date_reg) - - """ Read a SLIP packet from the serial port """ - def read(self): - return self._slip_reader.next() - - """ Write bytes to the serial port while performing SLIP escaping """ - def write(self, packet): - buf = '\xc0' \ - + (packet.replace('\xdb','\xdb\xdd').replace('\xc0','\xdb\xdc')) \ - + '\xc0' - self._port.write(buf) - - """ Calculate checksum of a blob, as it is defined by the ROM """ - @staticmethod - def checksum(data, state=ESP_CHECKSUM_MAGIC): - for b in data: - state ^= ord(b) - return state - - """ Send a request and read the response """ - def command(self, op=None, data=None, chk=0): - if op is not None: - pkt = struct.pack(' self.STATUS_BYTES_LENGTH: - return data[:-self.STATUS_BYTES_LENGTH] - else: # otherwise, just return the 'val' field which comes from the reply header (this is used by read_reg) - return val - - def flush_input(self): - self._port.flushInput() - self._slip_reader = slip_reader(self._port) - - def sync(self): - """ Perform a connection test """ - self.command(ESPROM.ESP_SYNC, '\x07\x07\x12\x20' + 32 * '\x55') - for i in xrange(7): - self.command() - - def connect(self): - """ Try connecting repeatedly until successful, or giving up """ - print 'Connecting...' - - for _ in xrange(4): - # issue reset-to-bootloader: - # RTS = either CH_PD or nRESET (both active low = chip in reset) - # DTR = GPIO0 (active low = boot to flasher) - self._port.setDTR(False) - self._port.setRTS(True) - time.sleep(0.05) - self._port.setDTR(True) - self._port.setRTS(False) - time.sleep(0.05) - self._port.setDTR(False) - - # worst-case latency timer should be 255ms (probably <20ms) - self._port.timeout = 0.3 - last_exception = None - for _ in xrange(4): - try: - self.flush_input() - self._port.flushOutput() - self.sync() - self._port.timeout = 5 - return - except FatalError as e: - last_exception = e - time.sleep(0.05) - raise FatalError('Failed to connect to %s: %s' % (self.CHIP_NAME, last_exception)) - - """ Read memory address in target """ - def read_reg(self, addr): - # we don't call check_command here because read_reg() function is called - # when detecting chip type, and the way we check for success (STATUS_BYTES_LENGTH) is different - # for different chip types (!) - val, data = self.command(ESPROM.ESP_READ_REG, struct.pack('> 24) | ((id1 & MAX_UINT24) << 8) - - def read_mac(self): - """ Read MAC from OTP ROM """ - mac0 = self.read_reg(self.ESP_OTP_MAC0) - mac1 = self.read_reg(self.ESP_OTP_MAC1) - mac3 = self.read_reg(self.ESP_OTP_MAC3) - if (mac3 != 0): - oui = ((mac3 >> 16) & 0xff, (mac3 >> 8) & 0xff, mac3 & 0xff) - elif ((mac1 >> 16) & 0xff) == 0: - oui = (0x18, 0xfe, 0x34) - elif ((mac1 >> 16) & 0xff) == 1: - oui = (0xac, 0xd0, 0x74) - else: - raise FatalError("Unknown OUI") - return oui + ((mac1 >> 8) & 0xff, mac1 & 0xff, (mac0 >> 24) & 0xff) - - def get_erase_size(self, size): - """ Calculate an erase size given a specific size in bytes. - - Provides a workaround for the bootloader erase bug.""" - - sectors_per_block = 16 - sector_size = self.ESP_FLASH_SECTOR - num_sectors = (size + sector_size - 1) / sector_size - start_sector = offset / sector_size - - head_sectors = sectors_per_block - (start_sector % sectors_per_block) - if num_sectors < head_sectors: - head_sectors = num_sectors - - if num_sectors < 2 * head_sectors: - return (num_sectors + 1) / 2 * sector_size - else: - return (num_sectors - head_sectors) * sector_size - -class ESP31ROM(ESPROM): - """ Access class for ESP31 ROM bootloader - """ - CHIP_NAME = "ESP31" - - DATE_REG_VALUE = 0x15052100 - - SPI_CMD_REG_ADDR = 0x60003000 - SPI_W0_REG_ADDR = 0x60003040 - - EFUSE_BASE = 0x6001a000 - - FLASH_SIZES = { - '1MB':0x00, - '2MB':0x10, - '4MB':0x20, - '8MB':0x30, - '16MB':0x40 - } - - def read_efuse(self, n): - """ Read the nth word of the ESP3x EFUSE region. """ - return self.read_reg(self.EFUSE_BASE + (4 * n)) - - def chip_id(self): - word16 = self.read_efuse(16) - word17 = self.read_efuse(17) - return ((word17 & MAX_UINT24) << 24) | (word16 >> 8) & MAX_UINT24 - - def read_mac(self): - """ Read MAC from EFUSE region """ - word16 = self.read_efuse(16) - word17 = self.read_efuse(17) - word18 = self.read_efuse(18) - word19 = self.read_efuse(19) - wifi_mac = (((word17 >> 16) & 0xff), ((word17 >> 8) & 0xff), ((word17 >> 0) & 0xff), - ((word16 >> 24) & 0xff), ((word16 >> 16) & 0xff), ((word16 >> 8) & 0xff)) - bt_mac = (((word19 >> 16) & 0xff), ((word19 >> 8) & 0xff), ((word19 >> 0) & 0xff), - ((word18 >> 24) & 0xff), ((word18 >> 16) & 0xff), ((word18 >> 8) & 0xff)) - return (wifi_mac,bt_mac) - - def get_erase_size(self, size): - return size - -class ESP32ROM(ESP31ROM): - """Access class for ESP32 ROM bootloader - - """ - CHIP_NAME = "ESP32" - - DATE_REG_VALUE = 0x15122500 - - # ESP32-only commands - ESP_SPI_FLASH_SET = 0xb - - ESP_SPI_ATTACH_REQ = 0xD - - ESP_CHANGE_BAUDRATE = 0x0F - ESP_FLASH_DEFL_BEGIN = 0x10 - ESP_FLASH_DEFL_DATA = 0x11 - ESP_FLASH_DEFL_END = 0x12 - - ESP_SPI_FLASH_MD5 = 0x13 - - IROM_MAP_START = 0x400d0000 - IROM_MAP_END = 0x40400000 - DROM_MAP_START = 0x3F400000 - DROM_MAP_END = 0x3F700000 - - # ESP32 uses a 4 byte status reply - STATUS_BYTES_LENGTH = 4 - - def flash_defl_begin(self, size, compsize, offset): - """ Start downloading compressed data to Flash (performs an erase) """ - old_tmo = self._port.timeout - num_blocks = (compsize + self.ESP_FLASH_BLOCK - 1) / self.ESP_FLASH_BLOCK - erase_blocks = (size + self.ESP_FLASH_BLOCK - 1) / self.ESP_FLASH_BLOCK - - erase_size = size - if erase_size > 0 and (offset + erase_size) >= (16 / 8) * 1024 * 1024: - self.flash_spi_param_set() - - self._port.timeout = 20 - t = time.time() - print "Unc size %d comp size %d comp blocks %d" % (size, compsize, num_blocks) - self.check_command("enter compressed flash mode", self.ESP_FLASH_DEFL_BEGIN, - struct.pack(' 16: - raise FatalError('Invalid firmware image magic=%d segments=%d' % (magic, segments)) - return segments - - def load_segment(self, f, is_irom_segment=False): - """ Load the next segment from the image file """ - file_offs = f.tell() - (offset, size) = struct.unpack(' 0x40200000 or offset < 0x3ffe0000 or size > 65536: - print('WARNING: Suspicious segment 0x%x, length %d' % (offset, size)) - segment_data = f.read(size) - if len(segment_data) < size: - raise FatalError('End of file reading segment 0x%x, length %d (actual length %d)' % (offset, size, len(segment_data))) - segment = ImageSegment(offset, segment_data, file_offs) - self.segments.append(segment) - return segment - - def save_segment(self, f, segment, checksum=None): - """ Save the next segment to the image file, return next checksum value if provided """ - f.write(struct.pack(' 0: - if len(irom_segments) != 1: - raise FatalError('Found %d segments that could be irom0. Bad ELF file?' % len(irom_segments)) - return irom_segments[0] - return None - - def get_non_irom_segments(self): - irom_segment = self.get_irom_segment() - return [s for s in self.segments if s != irom_segment] - - -class ESPFirmwareImage(BaseFirmwareImage): - """ 'Version 1' firmware image, segments loaded directly by the ROM bootloader. """ - def __init__(self, load_file=None): - super(ESPFirmwareImage, self).__init__() - self.flash_mode = 0 - self.flash_size_freq = 0 - self.version = 1 - - if load_file is not None: - segments = self.load_common_header(load_file, ESPROM.ESP_IMAGE_MAGIC) - - for _ in xrange(segments): - self.load_segment(load_file) - self.checksum = self.read_checksum(load_file) - - def default_output_name(self, input_file): - """ Derive a default output name from the ELF name. """ - return input_file + '-' - - def save(self, basename): - """ Save a set of V1 images for flashing. Parameter is a base filename. """ - # IROM data goes in its own plain binary file - irom_segment = self.get_irom_segment() - if irom_segment is not None: - with open("%s0x%05x.bin" % (basename, irom_segment.addr), "wb") as f: - f.write(irom_segment.data) - - # everything but IROM goes at 0x00000 in an image file - normal_segments = self.get_non_irom_segments() - with open("%s0x00000.bin" % basename, 'wb') as f: - self.write_common_header(f, normal_segments) - checksum = ESPROM.ESP_CHECKSUM_MAGIC - for segment in self.segments: - checksum = self.save_segment(f, segment, checksum) - self.append_checksum(f, checksum) - - -class OTAFirmwareImage(BaseFirmwareImage): - """ 'Version 2' firmware image, segments loaded by software bootloader stub - (ie Espressif bootloader or rboot) - """ - def __init__(self, load_file=None): - super(OTAFirmwareImage, self).__init__() - self.version = 2 - if load_file is not None: - segments = self.load_common_header(load_file, ESPBOOTLOADER.IMAGE_V2_MAGIC) - if segments != ESPBOOTLOADER.IMAGE_V2_SEGMENT: - # segment count is not really segment count here, but we expect to see '4' - print 'Warning: V2 header has unexpected "segment" count %d (usually 4)' % segments - - # irom segment comes before the second header - # - # the file is saved in the image with a zero load address - # in the header, so we need to calculate a load address - irom_offs = load_file.tell() - irom_segment = self.load_segment(load_file, True) - irom_segment.addr = irom_offs + ESPROM.IROM_MAP_START - - first_flash_mode = self.flash_mode - first_flash_size_freq = self.flash_size_freq - first_entrypoint = self.entrypoint - # load the second header - self.load_common_header(load_file, ESPROM.ESP_IMAGE_MAGIC) - (magic, segments, self.flash_mode, self.flash_size_freq, self.entrypoint) = struct.unpack(' 0: - #print("Calculated pad length %08x to place next header @ %08x" % (pad_len, f.tell()+pad_len)) - null = ImageSegment(0, '\x00' * pad_len, f.tell()) - checksum = self.save_segment(f, null, checksum) - #print("After padding, at file offset %08x" % f.tell()) - padding_segments += 1 - #print "Comparing file offs %x (data @ %x) with segment load addr %x" % (f.tell(), f.tell() + 8, segment.addr) - # verify that after the 8 byte header is added, were are at the correct offset relative to the segment's vaddr - assert (f.tell() + 8) % IROM_ALIGN == segment.addr % IROM_ALIGN - checksum = self.save_segment(f, segment, checksum) - self.append_checksum(f, checksum) - # kinda hacky: go back to the initial header and write the new segment count - # that includes padding segments. Luckily(?) this header is not checksummed - f.seek(1) - f.write(chr(len(self.segments) + padding_segments)) - - -class ELFFile(object): - SEC_TYPE_PROGBITS = 0x01 - SEC_TYPE_STRTAB = 0x03 - - def __init__(self, name): - # Load sections from the ELF file - self.name = name - with open(self.name, 'rb') as f: - self._read_elf_file(f) - - def _read_elf_file(self, f): - # read the ELF file header - LEN_FILE_HEADER = 0x34 - try: - (ident,_type,machine,_version, - self.entrypoint,_phoff,shoff,_flags, - _ehsize, _phentsize,_phnum,_shentsize, - _shnum,shstrndx) = struct.unpack("<16sHHLLLLLHHHHHH", f.read(LEN_FILE_HEADER)) - except struct.error as e: - raise FatalError("Failed to read a valid ELF header from %s: %s" % (self.name, e)) - - if ident[0] != '\x7f' or ident[1:4] != 'ELF': - raise FatalError("%s has invalid ELF magic header" % self.name) - if machine != 0x5e: - raise FatalError("%s does not appear to be an Xtensa ELF file. e_machine=%04x" % (self.name, machine)) - self._read_sections(f, shoff, shstrndx) - - def _read_sections(self, f, section_header_offs, shstrndx): - f.seek(section_header_offs) - section_header = f.read() - LEN_SEC_HEADER = 0x28 - if len(section_header) == 0: - raise FatalError("No section header found at offset %04x in ELF file." % section_header_offs) - if len(section_header) % LEN_SEC_HEADER != 0: - print 'WARNING: Unexpected ELF section header length %04x is not mod-%02x' % (len(section_header),LEN_SEC_HEADER) - - # walk through the section header and extract all sections - section_header_offsets = range(0, len(section_header), LEN_SEC_HEADER) - - def read_section_header(offs): - name_offs,sec_type,_flags,lma,sec_offs,size = struct.unpack_from(" 0: - esp._port.baudrate = baud_rate - # Read the greeting. - p = esp.read() - if p != 'OHAI': - raise FatalError('Failed to connect to the flasher (got %s)' % hexify(p)) - - def flash_write(self, addr, data, show_progress=False): - assert addr % self._esp.ESP_FLASH_SECTOR == 0, 'Address must be sector-aligned' - assert len(data) % self._esp.ESP_FLASH_SECTOR == 0, 'Length must be sector-aligned' - sys.stdout.write('Writing %d @ 0x%x... ' % (len(data), addr)) - sys.stdout.flush() - self._esp.write(struct.pack(' length: - raise FatalError('Read more than expected') - p = self._esp.read() - if len(p) != 16: - raise FatalError('Expected digest, got: %s' % hexify(p)) - expected_digest = hexify(p).upper() - digest = hashlib.md5(data).hexdigest().upper() - print - if digest != expected_digest: - raise FatalError('Digest mismatch: expected %s, got %s' % (expected_digest, digest)) - p = self._esp.read() - if len(p) != 1: - raise FatalError('Expected status, got: %s' % hexify(p)) - status_code = struct.unpack(', ) or a single -# argument. - -def load_ram(esp, args): - image = LoadFirmwareImage(esp, args.filename) - - print 'RAM boot...' - for (offset, size, data) in image.segments: - print 'Downloading %d bytes at %08x...' % (size, offset), - sys.stdout.flush() - esp.mem_begin(size, div_roundup(size, esp.ESP_RAM_BLOCK), esp.ESP_RAM_BLOCK, offset) - - seq = 0 - while len(data) > 0: - esp.mem_block(data[0:esp.ESP_RAM_BLOCK], seq) - data = data[esp.ESP_RAM_BLOCK:] - seq += 1 - print 'done!' - - print 'All segments done, executing at %08x' % image.entrypoint - esp.mem_finish(image.entrypoint) - - -def read_mem(esp, args): - print '0x%08x = 0x%08x' % (args.address, esp.read_reg(args.address)) - - -def write_mem(esp, args): - esp.write_reg(args.address, args.value, args.mask, 0) - print 'Wrote %08x, mask %08x to %08x' % (args.value, args.mask, args.address) - - -def dump_mem(esp, args): - f = file(args.filename, 'wb') - for i in xrange(args.size / 4): - d = esp.read_reg(args.address + (i * 4)) - f.write(struct.pack(' 0: - print '\rWriting at 0x%08x... (%d %%)' % (address + seq * esp.ESP_FLASH_BLOCK, 100 * (seq + 1) / blocks), - sys.stdout.flush() - block = image[0:esp.ESP_FLASH_BLOCK] - if args.compress: - esp.flash_defl_block(block, seq) - else: - # Pad the last block - block = block + '\xff' * (esp.ESP_FLASH_BLOCK - len(block)) - # Fix sflash config data - if address == 0 and seq == 0 and block[0] == '\xe9': - block = block[0:2] + flash_info + block[4:] - header_block = block - esp.flash_block(block, seq) - image = image[esp.ESP_FLASH_BLOCK:] - seq += 1 - written += len(block) - t = time.time() - t - print '\rWrote %d bytes at 0x%08x in %.1f seconds (%.1f kbit/s)...' % (written, address, t, written / t * 8 / 1000) - res = esp.flash_md5sum(address, uncsize) - if res != calcmd5: - print 'File md5: %s' % calcmd5 - print 'Flash md5: %s' % res - raise FatalError("MD5 of file does not match data in flash!") - else: - print 'Hash of data verified.' - print '\nLeaving...' - if args.flash_mode == 'dio': - esp.flash_unlock_dio() - else: - esp.flash_begin(0, 0) - if args.compress: - esp.flash_defl_finish(False) - else: - esp.flash_finish(False) - if args.verify: - print 'Verifying just-written flash...' - verify_flash(esp, args, header_block) - - -def image_info(args): - image = LoadFirmwareImage(args.chip, args.filename) - print('Image version: %d' % image.version) - print('Entry point: %08x' % image.entrypoint) if image.entrypoint != 0 else 'Entry point not set' - print '%d segments' % len(image.segments) - print - checksum = ESPROM.ESP_CHECKSUM_MAGIC - idx = 0 - for seg in image.segments: - idx += 1 - print 'Segment %d: %r' % (idx, seg) - checksum = ESPROM.checksum(seg.data, checksum) - print - print 'Checksum: %02x (%s)' % (image.checksum, 'valid' if image.checksum == checksum else 'invalid!') - - -def make_image(args): - image = ESPFirmwareImage() - if len(args.segfile) == 0: - raise FatalError('No segments specified') - if len(args.segfile) != len(args.segaddr): - raise FatalError('Number of specified files does not match number of specified addresses') - for (seg, addr) in zip(args.segfile, args.segaddr): - data = file(seg, 'rb').read() - image.segments.append(ImageSegment(addr, data)) - image.entrypoint = args.entrypoint - image.save(args.output) - - -def elf2image(args): - e = ELFFile(args.input) - if args.chip == 'auto': # Default to ESP8266 for backwards compatibility - print "Creating image for ESP8266..." - args.chip == 'esp8266' - - if args.chip == 'esp31': - raise FatalError("No elf2image support for ESP31. Use gen_appimage.py from the ESP31 SDK") - elif args.chip == 'esp32': - image = ESP32FirmwareImage() - elif args.version == '1': # ESP8266 - image = ESPFirmwareImage() - else: - image = OTAFirmwareImage() - image.entrypoint = e.entrypoint - image.segments = e.sections # ELFSection is a subclass of ImageSegment - image.flash_mode = {'qio':0, 'qout':1, 'dio':2, 'dout': 3}[args.flash_mode] - image.flash_size_freq = ESP8266ROM.FLASH_SIZES[args.flash_size] - image.flash_size_freq += {'40m':0, '26m':1, '20m':2, '80m': 0xf}[args.flash_freq] - - if args.output is None: - args.output = image.default_output_name(args.input) - image.save(args.output) - - -def read_mac(esp, args): - mac = esp.read_mac() - print 'MAC: %s' % ':'.join(map(lambda x: '%02x' % x, mac)) - - -def chip_id(esp, args): - chipid = esp.chip_id() - print 'Chip ID: 0x%08x' % chipid - - -def erase_flash(esp, args): - print 'Erasing flash (this may take a while)...' - flasher = CesantaFlasher(esp, args.baud) - flasher.flash_erase() - print 'Erase completed successfully.' - - -def run(esp, args): - esp.run() - - -def flash_id(esp, args): - flash_id = esp.flash_id() - print 'Manufacturer: %02x' % (flash_id & 0xff) - print 'Device: %02x%02x' % ((flash_id >> 8) & 0xff, (flash_id >> 16) & 0xff) - - -def read_flash(esp, args): - flasher = CesantaFlasher(esp, args.baud) - t = time.time() - data = flasher.flash_read(args.address, args.size, not args.no_progress) - t = time.time() - t - print ('\rRead %d bytes at 0x%x in %.1f seconds (%.1f kbit/s)...' - % (len(data), args.address, t, len(data) / t * 8 / 1000)) - file(args.filename, 'wb').write(data) - - -def _verify_flash(flasher, args, flash_params=None): - differences = False - for address, argfile in args.addr_filename: - image = argfile.read() - argfile.seek(0) # rewind in case we need it again - if address == 0 and image[0] == '\xe9' and flash_params is not None: - image = image[0:2] + flash_params + image[4:] - image_size = len(image) - print 'Verifying 0x%x (%d) bytes @ 0x%08x in flash against %s...' % (image_size, image_size, address, argfile.name) - # Try digest first, only read if there are differences. - digest, _ = flasher.flash_digest(address, image_size) - digest = hexify(digest).upper() - expected_digest = hashlib.md5(image).hexdigest().upper() - if digest == expected_digest: - print '-- verify OK (digest matched)' - continue - else: - differences = True - if getattr(args, 'diff', 'no') != 'yes': - print '-- verify FAILED (digest mismatch)' - continue - - flash = flasher.flash_read(address, image_size) - assert flash != image - diff = [i for i in xrange(image_size) if flash[i] != image[i]] - print '-- verify FAILED: %d differences, first @ 0x%08x' % (len(diff), address + diff[0]) - for d in diff: - print ' %08x %02x %02x' % (address + d, ord(flash[d]), ord(image[d])) - if differences: - raise FatalError("Verify failed.") - - -def verify_flash(esp, args, flash_params=None): - flasher = CesantaFlasher(esp) - _verify_flash(flasher, args, flash_params) - - -def version(args): - print __version__ - -# -# End of operations functions -# - - -def main(): - parser = argparse.ArgumentParser(description='esptool.py v%s - ESP8266 ROM Bootloader Utility' % __version__, prog='esptool') - - parser.add_argument('--chip', '-c', - help='Target chip type', - choices=['auto', 'esp8266', 'esp31', 'esp32'], - default=os.environ.get('ESPTOOL_CHIP', 'auto')) - - parser.add_argument( - '--port', '-p', - help='Serial port device', - default=os.environ.get('ESPTOOL_PORT', ESPROM.DEFAULT_PORT)) - - parser.add_argument( - '--baud', '-b', - help='Serial port baud rate used when flashing/reading', - type=arg_auto_int, - default=os.environ.get('ESPTOOL_BAUD', ESPROM.ESP_ROM_BAUD)) - - subparsers = parser.add_subparsers( - dest='operation', - help='Run esptool {command} -h for additional help') - - parser_load_ram = subparsers.add_parser( - 'load_ram', - help='Download an image to RAM and execute') - parser_load_ram.add_argument('filename', help='Firmware image') - - parser_dump_mem = subparsers.add_parser( - 'dump_mem', - help='Dump arbitrary memory to disk') - parser_dump_mem.add_argument('address', help='Base address', type=arg_auto_int) - parser_dump_mem.add_argument('size', help='Size of region to dump', type=arg_auto_int) - parser_dump_mem.add_argument('filename', help='Name of binary dump') - - parser_read_mem = subparsers.add_parser( - 'read_mem', - help='Read arbitrary memory location') - parser_read_mem.add_argument('address', help='Address to read', type=arg_auto_int) - - parser_write_mem = subparsers.add_parser( - 'write_mem', - help='Read-modify-write to arbitrary memory location') - parser_write_mem.add_argument('address', help='Address to write', type=arg_auto_int) - parser_write_mem.add_argument('value', help='Value', type=arg_auto_int) - parser_write_mem.add_argument('mask', help='Mask of bits to write', type=arg_auto_int) - - def add_spi_flash_subparsers(parent): - """ Add common parser arguments for SPI flash properties """ - parent.add_argument('--flash_freq', '-ff', help='SPI Flash frequency', - choices=['40m', '26m', '20m', '80m'], - default=os.environ.get('ESPTOOL_FF', '40m')) - parent.add_argument('--flash_mode', '-fm', help='SPI Flash mode', - choices=['qio', 'qout', 'dio', 'dout'], - default=os.environ.get('ESPTOOL_FM', 'qio')) - parent.add_argument('--flash_size', '-fs', help='SPI Flash size in MegaBytes (1MB, 2MB, 4MB, 8MB, 16M)' - ' plus ESP8266-only (256KB, 512KB, 2MB-c1, 4MB-c1, 4MB-2)', - action=FlashSizeAction, - default=os.environ.get('ESPTOOL_FS', '1MB')) - - parser_write_flash = subparsers.add_parser( - 'write_flash', - help='Write a binary blob to flash') - parser_write_flash.add_argument('addr_filename', metavar='
', help='Address followed by binary filename, separated by space', - action=AddrFilenamePairAction) - add_spi_flash_subparsers(parser_write_flash) - parser_write_flash.add_argument('--no-progress', '-p', help='Suppress progress output', action="store_true") - parser_write_flash.add_argument('--verify', help='Verify just-written data (only necessary if very cautious, data is already CRCed', action='store_true') - parser_write_flash.add_argument('--ucIsHspi', '-ih', help='Config SPI PORT/PINS (Espressif internal feature)',default='0') - parser_write_flash.add_argument('--ucIsLegacy', '-il', help='Config SPI LEGACY (Espressif internal feature)',default='0') - parser_write_flash.add_argument('--compress', '-z', help='Compress data in transfer',action="store_true") - - subparsers.add_parser( - 'run', - help='Run application code in flash') - - parser_image_info = subparsers.add_parser( - 'image_info', - help='Dump headers from an application image') - parser_image_info.add_argument('filename', help='Image file to parse') - - parser_make_image = subparsers.add_parser( - 'make_image', - help='Create an application image from binary files') - parser_make_image.add_argument('output', help='Output image file') - parser_make_image.add_argument('--segfile', '-f', action='append', help='Segment input file') - parser_make_image.add_argument('--segaddr', '-a', action='append', help='Segment base address', type=arg_auto_int) - parser_make_image.add_argument('--entrypoint', '-e', help='Address of entry point', type=arg_auto_int, default=0) - - parser_elf2image = subparsers.add_parser( - 'elf2image', - help='Create an application image from ELF file') - parser_elf2image.add_argument('input', help='Input ELF file') - parser_elf2image.add_argument('--output', '-o', help='Output filename prefix (for version 1 image), or filename (for version 2 single image)', type=str) - parser_elf2image.add_argument('--version', '-e', help='Output image version', choices=['1','2'], default='1') - add_spi_flash_subparsers(parser_elf2image) - - subparsers.add_parser( - 'read_mac', - help='Read MAC address from OTP ROM') - - subparsers.add_parser( - 'chip_id', - help='Read Chip ID from OTP ROM') - - subparsers.add_parser( - 'flash_id', - help='Read SPI flash manufacturer and device ID') - - parser_read_flash = subparsers.add_parser( - 'read_flash', - help='Read SPI flash content') - parser_read_flash.add_argument('address', help='Start address', type=arg_auto_int) - parser_read_flash.add_argument('size', help='Size of region to dump', type=arg_auto_int) - parser_read_flash.add_argument('filename', help='Name of binary dump') - parser_read_flash.add_argument('--no-progress', '-p', help='Suppress progress output', action="store_true") - - parser_verify_flash = subparsers.add_parser( - 'verify_flash', - help='Verify a binary blob against flash') - parser_verify_flash.add_argument('addr_filename', help='Address and binary file to verify there, separated by space', - action=AddrFilenamePairAction) - parser_verify_flash.add_argument('--diff', '-d', help='Show differences', - choices=['no', 'yes'], default='no') - - subparsers.add_parser( - 'erase_flash', - help='Perform Chip Erase on SPI flash') - - subparsers.add_parser( - 'version', help='Print esptool version') - - # internal sanity check - every operation matches a module function of the same name - for operation in subparsers.choices.keys(): - assert operation in globals(), "%s should be a module function" % operation - - args = parser.parse_args() - - print 'esptool.py v%s' % __version__ - - # operation function can take 1 arg (args), 2 args (esp, arg) - # or be a member function of the ESPROM class. - - operation_func = globals()[args.operation] - operation_args,_,_,_ = inspect.getargspec(operation_func) - if operation_args[0] == 'esp': # operation function takes an ESPROM connection object - initial_baud = min(ESPROM.ESP_ROM_BAUD, args.baud) # don't sync faster than the default baud rate - chip_constructor_fun = { - 'auto': ESPROM.detect_chip, - 'esp8266': ESP8266ROM, - 'esp31': ESP31ROM, - 'esp32': ESP32ROM, - }[args.chip] - esp = chip_constructor_fun(args.port, initial_baud) - # try to set a higher baud, this is a no-op if we need to - # wait for the flasher stub to kick in before doing this. - esp.change_baud(args.baud) - - operation_func(esp, args) - else: - operation_func(args) - - -class FlashSizeAction(argparse.Action): - """ Custom flash size parser class to support backwards compatibility with megabit size arguments. - - (At next major relase, remove deprecated sizes and this can become a 'normal' choices= argument again.) - """ - def __init__(self, option_strings, dest, nargs=1, **kwargs): - super(FlashSizeAction, self).__init__(option_strings, dest, nargs, **kwargs) - - def __call__(self, parser, namespace, values, option_string=None): - try: - value = { - '2m': '256KB', - '4m': '512KB', - '8m': '1MB', - '16m': '2MB', - '32m': '4MB', - '16m-c1': '2MB-c1', - '32m-c1': '4MB-c1', - '32m-c2': '4MB-c2' - }[values[0]] - print("WARNING: Flash size arguments in megabits like '%s' are deprecated." % (values[0])) - print("Please use the equivalent size '%s'." % (value)) - print("Megabit arguments may be removed in a future release.") - except KeyError: - values = values[0] - - known_sizes = dict(ESP8266ROM.FLASH_SIZES) - known_sizes.update(ESP32ROM.FLASH_SIZES) - if value not in known_sizes: - raise argparse.ArgumentError(self, '%s is not a known flash size. Known sizes: %s' % (value, ", ".join(known_sizes.keys()))) - setattr(namespace, self.dest, value) - - -class AddrFilenamePairAction(argparse.Action): - """ Custom parser class for the address/filename pairs passed as arguments """ - def __init__(self, option_strings, dest, nargs='+', **kwargs): - super(AddrFilenamePairAction, self).__init__(option_strings, dest, nargs, **kwargs) - - def __call__(self, parser, namespace, values, option_string=None): - # validate pair arguments - pairs = [] - for i in range(0,len(values),2): - try: - address = int(values[i],0) - except ValueError as e: - raise argparse.ArgumentError(self,'Address "%s" must be a number' % values[i]) - try: - argfile = open(values[i + 1], 'rb') - except IOError as e: - raise argparse.ArgumentError(self, e) - except IndexError: - raise argparse.ArgumentError(self,'Must be pairs of an address and the binary filename to write there') - pairs.append((address, argfile)) - setattr(namespace, self.dest, pairs) - -# This is "wrapped" stub_flasher.c, to be loaded using run_stub. -_CESANTA_FLASHER_STUB = """\ -{"code_start": 1074790404, "code": "080000601C000060000000601000006031FCFF71FCFF\ -81FCFFC02000680332D218C020004807404074DCC48608005823C0200098081BA5A9239245005803\ -1B555903582337350129230B446604DFC6F3FF21EEFFC0200069020DF0000000010078480040004A\ -0040B449004012C1F0C921D911E901DD0209312020B4ED033C2C56C2073020B43C3C56420701F5FF\ -C000003C4C569206CD0EEADD860300202C4101F1FFC0000056A204C2DCF0C02DC0CC6CCAE2D1EAFF\ -0606002030F456D3FD86FBFF00002020F501E8FFC00000EC82D0CCC0C02EC0C73DEB2ADC46030020\ -2C4101E1FFC00000DC42C2DCF0C02DC056BCFEC602003C5C8601003C6C4600003C7C08312D0CD811\ -C821E80112C1100DF0000C180000140010400C0000607418000064180000801800008C1800008418\ -0000881800009018000018980040880F0040A80F0040349800404C4A0040740F0040800F0040980F\ -00400099004012C1E091F5FFC961CD0221EFFFE941F9310971D9519011C01A223902E2D1180C0222\ -6E1D21E4FF31E9FF2AF11A332D0F42630001EAFFC00000C030B43C2256A31621E1FF1A2228022030\ -B43C3256B31501ADFFC00000DD023C4256ED1431D6FF4D010C52D90E192E126E0101DDFFC0000021\ -D2FF32A101C020004802303420C0200039022C0201D7FFC00000463300000031CDFF1A333803D023\ -C03199FF27B31ADC7F31CBFF1A3328030198FFC0000056C20E2193FF2ADD060E000031C6FF1A3328\ -030191FFC0000056820DD2DD10460800000021BEFF1A2228029CE231BCFFC020F51A33290331BBFF\ -C02C411A332903C0F0F4222E1D22D204273D9332A3FFC02000280E27B3F721ABFF381E1A2242A400\ -01B5FFC00000381E2D0C42A40001B3FFC0000056120801B2FFC00000C02000280EC2DC0422D2FCC0\ -2000290E01ADFFC00000222E1D22D204226E1D281E22D204E7B204291E860000126E012198FF32A0\ -042A21C54C003198FF222E1D1A33380337B202C6D6FF2C02019FFFC000002191FF318CFF1A223A31\ -019CFFC00000218DFF1C031A22C549000C02060300003C528601003C624600003C72918BFF9A1108\ -71C861D851E841F83112C1200DF00010000068100000581000007010000074100000781000007C10\ -0000801000001C4B0040803C004091FDFF12C1E061F7FFC961E941F9310971D9519011C01A662906\ -21F3FFC2D1101A22390231F2FF0C0F1A33590331EAFFF26C1AED045C2247B3028636002D0C016DFF\ -C0000021E5FF41EAFF2A611A4469040622000021E4FF1A222802F0D2C0D7BE01DD0E31E0FF4D0D1A\ -3328033D0101E2FFC00000561209D03D2010212001DFFFC000004D0D2D0C3D01015DFFC0000041D5\ -FFDAFF1A444804D0648041D2FF1A4462640061D1FF106680622600673F1331D0FF10338028030C43\ -853A002642164613000041CAFF222C1A1A444804202FC047328006F6FF222C1A273F3861C2FF222C\ -1A1A6668066732B921BDFF3D0C1022800148FFC0000021BAFF1C031A2201BFFFC000000C02460300\ -5C3206020000005C424600005C5291B7FF9A110871C861D851E841F83112C1200DF0B0100000C010\ -0000D010000012C1E091FEFFC961D951E9410971F931CD039011C0ED02DD0431A1FF9C1422A06247\ -B302062D0021F4FF1A22490286010021F1FF1A223902219CFF2AF12D0F011FFFC00000461C0022D1\ -10011CFFC0000021E9FFFD0C1A222802C7B20621E6FF1A22F8022D0E3D014D0F0195FFC000008C52\ -22A063C6180000218BFF3D01102280F04F200111FFC00000AC7D22D1103D014D0F010DFFC0000021\ -D6FF32D110102280010EFFC0000021D3FF1C031A220185FFC00000FAEEF0CCC056ACF821CDFF317A\ -FF1A223A310105FFC0000021C9FF1C031A22017CFFC000002D0C91C8FF9A110871C861D851E841F8\ -3112C1200DF0000200600000001040020060FFFFFF0012C1E00C02290131FAFF21FAFF026107C961\ -C02000226300C02000C80320CC10564CFF21F5FFC02000380221F4FF20231029010C432D010163FF\ -C0000008712D0CC86112C1200DF00080FE3F8449004012C1D0C9A109B17CFC22C1110C13C51C0026\ -1202463000220111C24110B68202462B0031F5FF3022A02802A002002D011C03851A0066820A2801\ -32210105A6FF0607003C12C60500000010212032A01085180066A20F2221003811482105B3FF2241\ -10861A004C1206FDFF2D011C03C5160066B20E280138114821583185CFFF06F7FF005C1286F5FF00\ -10212032A01085140066A20D2221003811482105E1FF06EFFF0022A06146EDFF45F0FFC6EBFF0000\ -01D2FFC0000006E9FF000C022241100C1322C110C50F00220111060600000022C1100C13C50E0022\ -011132C2FA303074B6230206C8FF08B1C8A112C1300DF0000000000010404F484149007519031027\ -000000110040A8100040BC0F0040583F0040CC2E00401CE20040D83900408000004021F4FF12C1E0\ -C961C80221F2FF097129010C02D951C91101F4FFC0000001F3FFC00000AC2C22A3E801F2FFC00000\ -21EAFFC031412A233D0C01EFFFC000003D0222A00001EDFFC00000C1E4FF2D0C01E8FFC000002D01\ -32A004450400C5E7FFDD022D0C01E3FFC00000666D1F4B2131DCFF4600004B22C0200048023794F5\ -31D9FFC0200039023DF08601000001DCFFC000000871C861D85112C1200DF000000012C1F0026103\ -01EAFEC00000083112C1100DF000643B004012C1D0E98109B1C9A1D991F97129013911E2A0C001FA\ -FFC00000CD02E792F40C0DE2A0C0F2A0DB860D00000001F4FFC00000204220E71240F7921C226102\ -01EFFFC0000052A0DC482157120952A0DD571205460500004D0C3801DA234242001BDD3811379DC5\ -C6000000000C0DC2A0C001E3FFC00000C792F608B12D0DC8A1D891E881F87112C1300DF00000", "\ -entry": 1074792180, "num_params": 1, "params_start": 1074790400, "data": "FE0510\ -401A0610403B0610405A0610407A061040820610408C0610408C061040", "data_start": 10736\ -43520} -""" - -if __name__ == '__main__': - try: - main() - except FatalError as e: - print '\nA fatal error occurred: %s' % e - sys.exit(2) From 2ddd05a3faed9ec00ed272af566a1f31a0191214 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Tue, 30 Aug 2016 18:10:30 +1000 Subject: [PATCH 04/51] Eclipse docs: Prepend IDF paths to beginning of PATH Avoids problem when a different incompatible make (MSYS1 or other) is already on PATH. --- docs/eclipse-setup.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/eclipse-setup.rst b/docs/eclipse-setup.rst index 07c8c2538e..2f36a5fc9d 100644 --- a/docs/eclipse-setup.rst +++ b/docs/eclipse-setup.rst @@ -39,7 +39,7 @@ Project Properties *Windows users only, follow these two additional steps:* -* On the same Environment property page, edit the PATH environment variable and append ``;C:\msys32\usr\bin;C:\msys32\mingw32\bin;C:\msys32\opt\xtensa-esp32-elf\bin`` to the end of the default value. (If you installed msys32 to a different directory then you'll need to change these paths to match.) +* On the same Environment property page, edit the PATH environment variable and prepend ``C:\msys32\usr\bin;C:\msys32\mingw32\bin;C:\msys32\opt\xtensa-esp32-elf\bin;`` at the **beginning** of the default value. (If you installed msys32 to a different directory then you'll need to change these paths to match.) * Click on the "C/C++ Build" top-level properties page then uncheck "Use default build command" and enter this for the custom build command: ``bash ${IDF_PATH}/bin/eclipse_windows_make.sh``. From 144ebe5d53e217d8241321018d5a6856162e0ae6 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Wed, 31 Aug 2016 11:03:44 +1000 Subject: [PATCH 05/51] Move bin/eclipse_windows_make.sh to tools/windows_eclipse_make.sh Moving as bin directory is going away soon --- docs/eclipse-setup.rst | 2 +- bin/eclipse_windows_make.sh => tools/windows/eclipse_make.sh | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename bin/eclipse_windows_make.sh => tools/windows/eclipse_make.sh (100%) diff --git a/docs/eclipse-setup.rst b/docs/eclipse-setup.rst index 2f36a5fc9d..86966a1571 100644 --- a/docs/eclipse-setup.rst +++ b/docs/eclipse-setup.rst @@ -41,7 +41,7 @@ Project Properties * On the same Environment property page, edit the PATH environment variable and prepend ``C:\msys32\usr\bin;C:\msys32\mingw32\bin;C:\msys32\opt\xtensa-esp32-elf\bin;`` at the **beginning** of the default value. (If you installed msys32 to a different directory then you'll need to change these paths to match.) -* Click on the "C/C++ Build" top-level properties page then uncheck "Use default build command" and enter this for the custom build command: ``bash ${IDF_PATH}/bin/eclipse_windows_make.sh``. +* Click on the "C/C++ Build" top-level properties page then uncheck "Use default build command" and enter this for the custom build command: ``bash ${IDF_PATH}/tools/windows/eclipse_make.sh``. *All users, continue with these steps:* diff --git a/bin/eclipse_windows_make.sh b/tools/windows/eclipse_make.sh similarity index 100% rename from bin/eclipse_windows_make.sh rename to tools/windows/eclipse_make.sh From 3e9a76f04d982c35a250c5f332cfd4d4f3e80ea2 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Wed, 31 Aug 2016 11:04:24 +1000 Subject: [PATCH 06/51] eclipse_make.sh: Fix printing of make directory --- tools/windows/eclipse_make.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/windows/eclipse_make.sh b/tools/windows/eclipse_make.sh index 115ecac2fa..200d798ffa 100755 --- a/tools/windows/eclipse_make.sh +++ b/tools/windows/eclipse_make.sh @@ -5,5 +5,5 @@ # process uses MinGW paths of the form /c/dir/dir/file. So parse these out... # # (regexp deliberate only matches after a space character to try and avoid false-positives.) -echo "Running make in $(dirname $0)" +echo "Running make in $(pwd)" make $@ V=1 | sed -E "s@ /([a-z])/(.+)/@ \1:/\2/@g" | sed -E "s@-I/([a-z])/(.+)/@-I\1:/\2/@g" | sed -E "s@-L/([a-z])/(.+)/@-L\1:/\2/@g" From 71785378bc02ce65940252daca177b95e005fcee Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Wed, 31 Aug 2016 11:13:00 +1000 Subject: [PATCH 07/51] Eclipse doc: Add troubleshooting note about Makefile directories --- docs/eclipse-setup.rst | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/eclipse-setup.rst b/docs/eclipse-setup.rst index 86966a1571..3dc281142d 100644 --- a/docs/eclipse-setup.rst +++ b/docs/eclipse-setup.rst @@ -60,7 +60,7 @@ Flash from Eclipse You can integrate the "make flash" target into your Eclipse project to flash using esptool.py from the Eclipse UI: -* Right-click your project in Project Explorer (important to make sure you don't select a subdirectory of the project or Eclipse may find the wrong Makefile.) +* Right-click your project in Project Explorer (important to make sure you select the project, not a directory in the project, or Eclipse may find the wrong Makefile.) * Select Make Targets -> Create from the context menu. @@ -73,3 +73,8 @@ Note that you will need to use "make menuconfig" to set the serial port and othe Follow the same steps to add ``bootloader`` and ``partition_table`` targets, if necessary. .. _eclipse.org: http://www.eclipse.org/ + +Eclipse Troubleshooting +----------------------- + +* ``*** Make was invoked from ... However please do not run make from the sdk or a component directory; ...`` - Eclipse will detect any directory with a Makefile in it as being a possible directory to run "make" in. All component directories also contain a Makefile (the wrong one), so it is important when using Project -> Make Target to always select the top-level project directory in Project Explorer. From 3b1c3dab4b7b40fe805b39bd572da38540cf8441 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Thu, 1 Sep 2016 09:19:06 +1000 Subject: [PATCH 08/51] Name component makefiles component.mk instead of Makefile Fixes problems with Eclipse trying to build in directories it shouldn't. This is a breaking change for existing repositories, they need to rename any component Makefiles to component.mk and rename their references to $(IDF_PATH)/make/component.mk to $(IDF_PATH)/make/component_common.mk --- README.buildenv | 14 ++++++------ .../src/main/{Makefile => component.mk} | 4 ++-- components/esp32/{Makefile => component.mk} | 4 ++-- .../freertos/{Makefile => component.mk} | 2 +- components/lwip/{Makefile => component.mk} | 2 +- components/newlib/{Makefile => component.mk} | 2 +- .../nvs_flash/{Makefile => component.mk} | 2 +- components/spi_flash/Makefile | 3 --- components/spi_flash/component.mk | 3 +++ .../tcpip_adapter/{Makefile => component.mk} | 2 +- make/{component.mk => component_common.mk} | 0 make/project.mk | 22 +++++++++---------- 12 files changed, 30 insertions(+), 30 deletions(-) rename components/bootloader/src/main/{Makefile => component.mk} (86%) rename components/esp32/{Makefile => component.mk} (96%) rename components/freertos/{Makefile => component.mk} (80%) rename components/lwip/{Makefile => component.mk} (84%) rename components/newlib/{Makefile => component.mk} (77%) rename components/nvs_flash/{Makefile => component.mk} (66%) delete mode 100755 components/spi_flash/Makefile create mode 100755 components/spi_flash/component.mk rename components/tcpip_adapter/{Makefile => component.mk} (56%) rename make/{component.mk => component_common.mk} (100%) diff --git a/README.buildenv b/README.buildenv index fd68300055..0fc007e0ca 100644 --- a/README.buildenv +++ b/README.buildenv @@ -127,7 +127,7 @@ all components and make the elf target depend on this. The targets invoke Make on the makefiles of the components in a subshell: this way the components have full freedom to do whatever is necessary to build the library without influencing other components. By default, the -component includes the utility makefile $(IDF_PATH)/make/component.mk. +component includes the utility makefile $(IDF_PATH)/make/component_common.mk. This provides default targets and configurations that will work out-of-the-box for most projects. @@ -158,7 +158,7 @@ minimum, it will just include the ESP-IDF component makefile, which adds component functionality: ----8<---- -include $(IDF_PATH)/make/component.mk +include $(IDF_PATH)/make/component_common.mk ---->8---- This will take all the .c and .S files in the component root and compile @@ -169,7 +169,7 @@ system by setting COMPONENT_SRCDIRS: ----8<---- COMPONENT_SRCDIRS := src1 src2 -include $(IDF_PATH)/make/component.mk +include $(IDF_PATH)/make/component_common.mk ---->8---- This will compile all source files in the src1/ and src2/ subdirectories @@ -183,7 +183,7 @@ objects that need to be generated: ----8<---- COMPONENT_OBJS := file1.o file2.o thing/filea.o thing/fileb.o anotherthing/main.o -include $(IDF_PATH)/make/component.mk +include $(IDF_PATH)/make/component_common.mk ---->8---- This can also be used in order to conditionally compile some files @@ -200,7 +200,7 @@ config FOO_ENABLE_BAR Makefile: ----8<---- COMPONENT_OBJS := foo_a.o foo_b.o $(if $(CONFIG_FOO_ENABLE_BAR),foo_bar.o foo_bar_interface.o) -include $(IDF_PATH)/make/component.mk +include $(IDF_PATH)/make/component_common.mk ---->8---- Some components will have a situation where a source file isn't supplied @@ -217,7 +217,7 @@ graphics_lib.o: logo.h logo.h: $(COMPONENT_PATH)/logo.bmp bmp2h -i $^ -o $@ -include $(IDF_PATH)/make/component.mk +include $(IDF_PATH)/make/component_common.mk ---->8---- In this example, graphics_lib.o and logo.h will be generated in the @@ -242,7 +242,7 @@ logo.h: $(COMPONENT_PATH)/logo.bmp $(summary) BMP2H $@ $(Q) bmp2h -i $^ -o $@ -include $(IDF_PATH)/make/component.mk +include $(IDF_PATH)/make/component_common.mk ---->8---- Obviously, there are cases where all these recipes are insufficient for a diff --git a/components/bootloader/src/main/Makefile b/components/bootloader/src/main/component.mk similarity index 86% rename from components/bootloader/src/main/Makefile rename to components/bootloader/src/main/component.mk index 2bb773b9c6..1671095f1b 100644 --- a/components/bootloader/src/main/Makefile +++ b/components/bootloader/src/main/component.mk @@ -1,7 +1,7 @@ # # Main Makefile. This is basically the same as a component makefile. # -# This Makefile should, at the very least, just include $(IDF_PATH)/make/component.mk. By default, +# This Makefile should, at the very least, just include $(IDF_PATH)/make/component_common.mk. By default, # this will take the sources in the src/ directory, compile them and link them into # lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable, # please read the esp-idf build system document if you need to do this. @@ -10,4 +10,4 @@ COMPONENT_ADD_LDFLAGS := -L $(abspath .) -lmain -T esp32.bootloader.ld -T $(IDF_PATH)/components/esp32/ld/esp32.rom.ld COMPONENT_EXTRA_INCLUDES := $(IDF_PATH)/components/esp32/include -include $(IDF_PATH)/make/component.mk +include $(IDF_PATH)/make/component_common.mk diff --git a/components/esp32/Makefile b/components/esp32/component.mk similarity index 96% rename from components/esp32/Makefile rename to components/esp32/component.mk index 1d55d0ff63..1699a238c6 100644 --- a/components/esp32/Makefile +++ b/components/esp32/component.mk @@ -1,7 +1,7 @@ # # Component Makefile # -# This Makefile should, at the very least, just include $(IDF_PATH)/make/component.mk. By default, +# This Makefile should, at the very least, just include $(IDF_PATH)/make/component_common.mk. By default, # this will take the sources in this directory, compile them and link them into # lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable, # please read the esp-idf build system document if you need to do this. @@ -33,7 +33,7 @@ COMPONENT_ADD_LDFLAGS := -lesp32 \ -L $(abspath ld) \ $(LINKER_SCRIPTS) -include $(IDF_PATH)/make/component.mk +include $(IDF_PATH)/make/component_common.mk ALL_LIB_FILES := $(patsubst %,$(COMPONENT_PATH)/lib/lib%.a,$(LIBS)) diff --git a/components/freertos/Makefile b/components/freertos/component.mk similarity index 80% rename from components/freertos/Makefile rename to components/freertos/component.mk index e4003eb146..6702d1b95c 100644 --- a/components/freertos/Makefile +++ b/components/freertos/component.mk @@ -6,4 +6,4 @@ COMPONENT_ADD_LDFLAGS = -l$(COMPONENT_NAME) -Wl,--undefined=uxTopUsedPriority COMPONENT_ADD_INCLUDEDIRS := include COMPONENT_PRIV_INCLUDEDIRS := include/freertos -include $(IDF_PATH)/make/component.mk +include $(IDF_PATH)/make/component_common.mk diff --git a/components/lwip/Makefile b/components/lwip/component.mk similarity index 84% rename from components/lwip/Makefile rename to components/lwip/component.mk index e159c25c2d..23c9fc160e 100644 --- a/components/lwip/Makefile +++ b/components/lwip/component.mk @@ -8,4 +8,4 @@ COMPONENT_SRCDIRS := api apps/sntp apps core/ipv4 core/ipv6 core netif port/free EXTRA_CFLAGS := -Wno-error=address -Waddress -DLWIP_ESP8266 -include $(IDF_PATH)/make/component.mk +include $(IDF_PATH)/make/component_common.mk diff --git a/components/newlib/Makefile b/components/newlib/component.mk similarity index 77% rename from components/newlib/Makefile rename to components/newlib/component.mk index 970461698a..7c8c74debe 100644 --- a/components/newlib/Makefile +++ b/components/newlib/component.mk @@ -5,4 +5,4 @@ define COMPONENT_BUILDRECIPE #Nothing to do; this does not generate a library. endef -include $(IDF_PATH)/make/component.mk +include $(IDF_PATH)/make/component_common.mk diff --git a/components/nvs_flash/Makefile b/components/nvs_flash/component.mk similarity index 66% rename from components/nvs_flash/Makefile rename to components/nvs_flash/component.mk index 58232cc89b..02ff8cf038 100755 --- a/components/nvs_flash/Makefile +++ b/components/nvs_flash/component.mk @@ -6,4 +6,4 @@ COMPONENT_ADD_INCLUDEDIRS := include COMPONENT_SRCDIRS := src -include $(IDF_PATH)/make/component.mk +include $(IDF_PATH)/make/component_common.mk diff --git a/components/spi_flash/Makefile b/components/spi_flash/Makefile deleted file mode 100755 index fc41e5f430..0000000000 --- a/components/spi_flash/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -COMPONENT_ADD_INCLUDEDIRS := include - -include $(IDF_PATH)/make/component.mk diff --git a/components/spi_flash/component.mk b/components/spi_flash/component.mk new file mode 100755 index 0000000000..ef497a7ecb --- /dev/null +++ b/components/spi_flash/component.mk @@ -0,0 +1,3 @@ +COMPONENT_ADD_INCLUDEDIRS := include + +include $(IDF_PATH)/make/component_common.mk diff --git a/components/tcpip_adapter/Makefile b/components/tcpip_adapter/component.mk similarity index 56% rename from components/tcpip_adapter/Makefile rename to components/tcpip_adapter/component.mk index 4028caf4a3..cb863d1b7d 100755 --- a/components/tcpip_adapter/Makefile +++ b/components/tcpip_adapter/component.mk @@ -4,4 +4,4 @@ EXTRA_CFLAGS := -DLWIP_ESP8266 -include $(IDF_PATH)/make/component.mk +include $(IDF_PATH)/make/component_common.mk diff --git a/make/component.mk b/make/component_common.mk similarity index 100% rename from make/component.mk rename to make/component_common.mk diff --git a/make/project.mk b/make/project.mk index ac2b3e59d3..ca80697cb6 100644 --- a/make/project.mk +++ b/make/project.mk @@ -1,13 +1,13 @@ # # Main Project Makefile -# This Makefile is included directly from the user project Makefile in order to call the Makefiles of all the -# components (in a separate make process) to build all the libraries, then links them together -# into the final file. If so, PWD is the project dir (we assume). +# This Makefile is included directly from the user project Makefile in order to call the component.mk +# makefiles of all components (in a separate make process) to build all the libraries, then links them +# together into the final file. If so, PWD is the project dir (we assume). # # -# This Makefile requires the environment variable IDF_PATH to be set to the directory where this -# Makefile is located. +# This makefile requires the environment variable IDF_PATH to be set to the top-level esp-idf directory +# where this file is located. # .PHONY: build-components menuconfig defconfig all build clean all_binaries @@ -77,9 +77,9 @@ SRCDIRS ?= main COMPONENT_PATHS := $(foreach comp,$(COMPONENTS),$(firstword $(foreach dir,$(COMPONENT_DIRS),$(wildcard $(dir)/$(comp))))) COMPONENT_PATHS += $(abspath $(SRCDIRS)) -#A component is buildable if it has a Makefile; we assume that a 'make -C $(component dir) build' results in a -#lib$(componentname).a. -COMPONENT_PATHS_BUILDABLE := $(foreach cp,$(COMPONENT_PATHS),$(if $(wildcard $(cp)/Makefile),$(cp))) +#A component is buildable if it has a component.mk makefile; we assume that a +# 'make -C $(component dir) -f component.mk build' results in a lib$(componentname).a +COMPONENT_PATHS_BUILDABLE := $(foreach cp,$(COMPONENT_PATHS),$(if $(wildcard $(cp)/component.mk),$(cp))) # Assemble global list of include dirs (COMPONENT_INCLUDES), and # LDFLAGS args (COMPONENT_LDFLAGS) supplied by each component. @@ -98,7 +98,7 @@ COMPONENT_LDFLAGS := # # Debugging this? Replace $(shell with $(error and you'll see the full command as-run. define GetVariable -$(shell "$(MAKE)" -s --no-print-directory -C $(1) get_variable PROJECT_PATH=$(PROJECT_PATH) GET_VARIABLE=$(2) | sed -En "s/^$(2)=(.+)/\1/p" ) +$(shell "$(MAKE)" -s --no-print-directory -C $(1) -f component.mk get_variable PROJECT_PATH=$(PROJECT_PATH) GET_VARIABLE=$(2) | sed -En "s/^$(2)=(.+)/\1/p" ) endef COMPONENT_INCLUDES := $(abspath $(foreach comp,$(COMPONENT_PATHS_BUILDABLE),$(addprefix $(comp)/, \ @@ -193,7 +193,7 @@ define GenerateComponentPhonyTarget # $(2) - target to generate (build, clean) .PHONY: $(notdir $(1))-$(2) $(notdir $(1))-$(2): | $(BUILD_DIR_BASE)/$(notdir $(1)) - @+$(MAKE) -C $(BUILD_DIR_BASE)/$(notdir $(1)) -f $(1)/Makefile COMPONENT_BUILD_DIR=$(BUILD_DIR_BASE)/$(notdir $(1)) $(2) + @+$(MAKE) -C $(BUILD_DIR_BASE)/$(notdir $(1)) -f $(1)/component.mk COMPONENT_BUILD_DIR=$(BUILD_DIR_BASE)/$(notdir $(1)) $(2) endef define GenerateComponentTargets @@ -206,7 +206,7 @@ $(BUILD_DIR_BASE)/$(notdir $(1)): # only invoked for the targets whose libraries appear in COMPONENT_LIBRARIES and hence the # APP_ELF dependencies.) $(BUILD_DIR_BASE)/$(notdir $(1))/lib$(notdir $(1)).a: $(notdir $(1))-build - $(details) echo "$$^ responsible for $$@" # echo which build target built this file + $(details) "Target '$$^' responsible for '$$@'" # echo which build target built this file endef $(foreach component,$(COMPONENT_PATHS_BUILDABLE),$(eval $(call GenerateComponentTargets,$(component)))) From b8634ae08b5c6fc951be8d6047b7a47749d5956b Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Thu, 1 Sep 2016 09:29:11 +1000 Subject: [PATCH 09/51] test_build_system: Print ESP_IDF_TEMPLATE_GIT for easier debugging --- make/test_build_system.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make/test_build_system.sh b/make/test_build_system.sh index 5de216dea3..015328bbbc 100755 --- a/make/test_build_system.sh +++ b/make/test_build_system.sh @@ -26,7 +26,7 @@ function run_tests() print_status "Checking prerequisites" [ -z ${IDF_PATH} ] && echo "IDF_PATH is not set. Need path to esp-idf installation." && exit 2 - print_status "Cloning template..." + print_status "Cloning template from ${ESP_IDF_TEMPLATE_GIT}..." git clone ${ESP_IDF_TEMPLATE_GIT} template cd template From c50f7aa07b2add26ce82a6c321ebbd62654af8c3 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Thu, 1 Sep 2016 09:39:54 +1000 Subject: [PATCH 10/51] Eclipse docs: Easier to just replace entire PATH, msys32 has everything we need to build/flash --- docs/eclipse-setup.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/eclipse-setup.rst b/docs/eclipse-setup.rst index 3dc281142d..21d83a7f06 100644 --- a/docs/eclipse-setup.rst +++ b/docs/eclipse-setup.rst @@ -39,7 +39,7 @@ Project Properties *Windows users only, follow these two additional steps:* -* On the same Environment property page, edit the PATH environment variable and prepend ``C:\msys32\usr\bin;C:\msys32\mingw32\bin;C:\msys32\opt\xtensa-esp32-elf\bin;`` at the **beginning** of the default value. (If you installed msys32 to a different directory then you'll need to change these paths to match.) +* On the same Environment property page, edit the PATH environment variable. Delete the existing value and replace it with ``C:\msys32\usr\bin;C:\msys32\mingw32\bin;C:\msys32\opt\xtensa-esp32-elf\bin`` (If you installed msys32 to a different directory then you'll need to change these paths to match). * Click on the "C/C++ Build" top-level properties page then uncheck "Use default build command" and enter this for the custom build command: ``bash ${IDF_PATH}/tools/windows/eclipse_make.sh``. From 1d8eece8348fa2f45f9a396ad75a6d9590b6e98e Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Thu, 1 Sep 2016 09:58:47 +1000 Subject: [PATCH 11/51] Rename README.buildenv to docs/build_system.rst and ReST-ify it --- README.buildenv | 265 ------------------------------------ docs/build_system.rst | 302 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 302 insertions(+), 265 deletions(-) delete mode 100644 README.buildenv create mode 100644 docs/build_system.rst diff --git a/README.buildenv b/README.buildenv deleted file mode 100644 index 0fc007e0ca..0000000000 --- a/README.buildenv +++ /dev/null @@ -1,265 +0,0 @@ -The build structure of the Espressif IoT Development Framework explained. - -An ESP-IDF project can be seen as an almagation of a number of components. -For example, for a webserver that shows the current humidity, we would -have: -- The ESP32 base libraries (libc, rom bindings etc) -- The WiFi drivers -- A TCP/IP stack -- The FreeRTOS operating system -- A webserver -- A driver for an humidity sensor -- Main code tying it all together - -ESP-IDF makes these components explicit and configurable. To do that, when a project -is compiled, the build environment will look up all the components in the -ESP-IDF directories, the project directories and optionally custom other component -directories. It then allows the user to configure compile-time options using -a friendly text-based menu system to customize the ESP-IDF as well as other components -to the requirements of the project. After the components are customized, the -build process will compile everything into an output file, which can then be uploaded -into a board in a way that can also be defined by components. - -A project in this sense is defined as a directory under which all the files required -to build it live, excluding the ESP-IDF files and the toolchain. A simple project -tree looks like this: - -- myProject/ - build/ - - components/ - component1/ - Makefile - - Kconfig - - src1.c - - component2/ - Makefile - - Kconfig - - src1.c - - main/ - src1.c - - src2.c - - Makefile - - -As we can see, a project consists of a components/ subdirectory containing its -components as well as one or more directories containing the project-specific -sources; by default a single directory called 'main' is assumed. The project -directory will also have a Makefile where the projects name as well as optionally -other options are defined. After compilation, the project directory will contain -a 'build'-directory containing all of the objects, libraries and other generated -files as well as the final binary. - -Components also have a Makefile containing various definititions influencing -the build process of the component as well as the project it's used in, as -well as a Kconfig file defining the compile-time options that are settable -by means of the menu system. - - -Project makefile variables that can be set by the programmer: -PROJECT_NAME: Mandatory. Name for the project -BUILD_DIR_BASE: Set the directory where all objects/libraries/binaries end up in. - Defaults to $(PROJECT_PATH)/build -COMPONENT_DIRS: Search path for components. Defaults to the component/ directories - in the ESP-IDF path and the project path. -COMPONENTS: A list of component names. Defaults to all the component found in the - COMPONENT_DIRS directory -EXTRA_COMPONENT_DIRS: Defaults to unset. Use this to add directories to the default - COMPONENT_DIRS. -SRCDIRS: Directories under the project dir containing project-specific sources. - Defaults to 'main'. These are treated as 'lite' components: they do not have - include directories that are passed to the compilation pass of all components and - they do not have a Kconfig option. - - -Component makefile variables that can be set by the programmer: -COMPONENT_ADD_INCLUDEDIRS: Relative path to include directories to be added to - the entire project -COMPONENT_PRIV_INCLUDEDIRS: Relative path to include directories that are only used - when compiling this specific component -COMPONENT_DEPENDS: Names of any components that need to be compiled before this component. -COMPONENT_ADD_LDFLAGS: Ld flags to add for this project. Defaults to -l$(COMPONENT_NAME). - Add libraries etc in the current directory as $(abspath libwhatever.a) -COMPONENT_EXTRA_INCLUDES: Any extra include paths. These will be prefixed with '-I' and - passed to the compiler; please put absolute paths here. -COMPONENT_SRCDIRS: Relative directories to look in for sources. Defaults to '.', the current - directory (the root of the component) only. Use this to specify any subdirectories. Note - that specifying this overwrites the default action of compiling everything in the - components root dir; to keep this behaviour please also add '.' as a directory in this - list. -COMPONENT_OBJS: Object files to compile. Defaults to the .o variants of all .c and .S files - that are found in COMPONENT_SRCDIRS. -COMPONENT_EXTRA_CLEAN: Files that are generated using rules in the components Makefile - that also need to be cleaned -COMPONENT_BUILDRECIPE: Recipe to build the component. Optional. Defaults to building all - COMPONENT_OBJS and linking them into lib(componentname).a -COMPONENT_CLEANRECIPE: Recipe to clean the component. Optional. Defaults to removing - all built objects and libraries. -COMPONENT_BUILD_DIR: Equals the cwd of the component build, which is the build dir - of the component (where all the .o etc files should be created). - - -These variables are already set early on in the Makefile and the values in it will -be usable in component or project Makefiles: -CC, LD, AR, OBJCOPY: Xtensa gcc tools -HOSTCC, HOSTLD etc: Host gcc tools -LDFLAGS, CFLAGS: Set to usable values as defined in ESP-IDF Makefile -PROJECT_NAME: Name of the project, as set in project makefile -PROJECT_PATH: Path to the root of the project folder -COMPONENTS: Name of the components to be included -CONFIG_*: Values set by 'make menuconfig' also have corresponding Makefile variables. - -For components, there also are these defines: -COMPONENT_PATH: Absolute path to the root of the source tree of the component we're - compiling -COMPONENT_LIBRARY: The full path to the static library the components compilation pass - is supposed to generate - - -How this works: -The Make process is always invoked from the project directory by the -user; invoking it anywhere else gives an error. This is what happens if -we build a binary: - -The Makefile first determines how it was included. It determines it was -included as a project file in this case and will continue to figure out -various paths as well as the components available to it. It will also -collect the ldflags and includes that the components specify they need. -It does this by running a dummy Make on the components with a target that -will output these values. - -The Makefile will then create targets to build the lib*.a libraries of -all components and make the elf target depend on this. The targets -invoke Make on the makefiles of the components in a subshell: this way -the components have full freedom to do whatever is necessary to build -the library without influencing other components. By default, the -component includes the utility makefile $(IDF_PATH)/make/component_common.mk. -This provides default targets and configurations that will work -out-of-the-box for most projects. - -For components that have parts that need to be run when building of the -project is done, you can create a file called Makefile.projbuild in the -component root directory. This file will be included in the main -Makefile. For the menu, there's an equivalent: if you want to include -options not in the 'components' submenu, create a Kconfig.projbuild and -it will be included in the main menu of menuconfig. Take good care when -(re)defining stuff here: because it's included with all the other -.projbuild files, it's possible to overwrite variables or re-declare -targets defined in the ESP-IDF makefile/Kconfig and other .projbuild files - - -WRITING COMPONENT MAKEFILES - -A component consists of a directory which doubles as the name for the -component: a component named 'httpd' lives in a directory called 'httpd' -Because components usually live under the project directory (although -they can also reside in an other folder), the path to this may be -something like /home/myuser/projects/myprojects/components/httpd . - -One of the things that most components will have is a Makefile, -containing instructions on how to build the component. Because the -build environment tries to set reasonable defaults that will work most -of the time, a component Makefile can be pretty small. At the absolute -minimum, it will just include the ESP-IDF component makefile, which adds -component functionality: - -----8<---- -include $(IDF_PATH)/make/component_common.mk ----->8---- - -This will take all the .c and .S files in the component root and compile -them into object files, finally linking them into a library. -Subdirectories are ignored; if your project has sources in subdirectories -instead of in the root of the component, you can tell that to the build -system by setting COMPONENT_SRCDIRS: - -----8<---- -COMPONENT_SRCDIRS := src1 src2 -include $(IDF_PATH)/make/component_common.mk ----->8---- - -This will compile all source files in the src1/ and src2/ subdirectories -instead. - -The standard component.mk logic adds all .S and .c files in the source -directories as sources to be compiled unconditionally. It is possible -to circumvent that logic and hardcode the objects to be compiled by -manually setting the COMPONENT_OBJS variable to the name of the -objects that need to be generated: - -----8<---- -COMPONENT_OBJS := file1.o file2.o thing/filea.o thing/fileb.o anotherthing/main.o -include $(IDF_PATH)/make/component_common.mk ----->8---- - -This can also be used in order to conditionally compile some files -dependent on the options selected in the Makefile: - -Kconfig: -----8<---- -config FOO_ENABLE_BAR - bool "Enable the BAR feature." - help - This enables the BAR feature of the FOO component. ----->8---- - -Makefile: -----8<---- -COMPONENT_OBJS := foo_a.o foo_b.o $(if $(CONFIG_FOO_ENABLE_BAR),foo_bar.o foo_bar_interface.o) -include $(IDF_PATH)/make/component_common.mk ----->8---- - -Some components will have a situation where a source file isn't supplied -with the component itself but has to be generated from another file. Say -our component has a header file that consists of the converted binary -data of a BMP file, converted using a hypothetical tool called bmp2h. The -header file is then included in as C source file called graphics_lib.c. - -----8<---- -COMPONENT_EXTRA_CLEAN := logo.h - -graphics_lib.o: logo.h - -logo.h: $(COMPONENT_PATH)/logo.bmp - bmp2h -i $^ -o $@ - -include $(IDF_PATH)/make/component_common.mk ----->8---- - -In this example, graphics_lib.o and logo.h will be generated in the -current directory (the build directory) while logo.bmp comes with the -component and resides under the component path. Because logo.h is a -generated file, it needs to be cleaned when make clean is called which -why it is added to the COMPONENT_EXTRA_CLEAN variable. - - -This will work just fine, but there's one last cosmetic improvement that -can be done. The make system tries to make the make process somewhat -easier on the eyes by hiding the commands (unless you run make with the -V=1 switch) and this does not do that yet. Here's an improved version -that will output in the same style as the rest of the make process: - -----8<---- -COMPONENT_EXTRA_CLEAN := test_tjpgd_logo.h - -graphics_lib.o: logo.h - -logo.h: $(COMPONENT_PATH)/logo.bmp - $(summary) BMP2H $@ - $(Q) bmp2h -i $^ -o $@ - -include $(IDF_PATH)/make/component_common.mk ----->8---- - -Obviously, there are cases where all these recipes are insufficient for a -certain component, for example when the component is basically a wrapper -around another third-party component not originally intended to be -compiled under this build system. In that case, it's possible to forego -the build system entirely by setting COMPONENT_OWNBUILDTARGET and -possibly COMPONENT_OWNCLEANTARGET and defining your own build- and clean -target. The build target can do anything as long as it creates -$(COMPONENT_LIBRARY) for the main file to link into the project binary, -and even that is not necessary: if the COMPONENT_ADD_LDFLAGS variable -is set, the component can instruct the linker to do anything else as well. - - - - - - - - diff --git a/docs/build_system.rst b/docs/build_system.rst new file mode 100644 index 0000000000..24381019b5 --- /dev/null +++ b/docs/build_system.rst @@ -0,0 +1,302 @@ +Build System +------------ + +This document explains the Espressif IoT Development Framework build system and the +concept of "components" + +Read this document if you want to know how to organise a new ESP-IDF project. + +We recommend using the esp-idf-template_ project as a starting point for your project. + +Overview +======== + +An ESP-IDF project can be seen as an almagation of a number of components. +For example, for a webserver that shows the current humidity, we would +have: + +- The ESP32 base libraries (libc, rom bindings etc) +- The WiFi drivers +- A TCP/IP stack +- The FreeRTOS operating system +- A webserver +- A driver for an humidity sensor +- Main code tying it all together + +ESP-IDF makes these components explicit and configurable. To do that, when a project +is compiled, the build environment will look up all the components in the +ESP-IDF directories, the project directories and optionally custom other component +directories. It then allows the user to configure compile-time options using +a friendly text-based menu system to customize the ESP-IDF as well as other components +to the requirements of the project. After the components are customized, the +build process will compile everything into an output file, which can then be uploaded +into a board in a way that can also be defined by components. + +A project in this sense is defined as a directory under which all the files required +to build it live, excluding the ESP-IDF files and the toolchain. A simple project +tree might look like this:: + + - myProject/ - build/ + - components/ - component1/ - component.mk + - Kconfig + - src1.c + - component2/ - component.mk + - Kconfig + - src1.c + - main/ - src1.c + - src2.c + - Makefile + +As we can see, a project consists of a components/ subdirectory containing its +components as well as one or more directories containing the project-specific +sources; by default a single directory called 'main' is assumed. The project +directory will also have a Makefile where the projects name as well as optionally +other options are defined. After compilation, the project directory will contain +a 'build'-directory containing all of the objects, libraries and other generated +files as well as the final binary. + +Components also have a custom makefile - ``component.mk``. This contains various definititions +influencing the build process of the component as well as the project it's used +in. Components may also include a Kconfig file defining the compile-time options that are +settable by means of the menu system. + +Project makefile variables that can be set by the programmer:: + + PROJECT_NAME: Mandatory. Name for the project + BUILD_DIR_BASE: Set the directory where all objects/libraries/binaries end up in. + Defaults to $(PROJECT_PATH)/build + COMPONENT_DIRS: Search path for components. Defaults to the component/ directories + in the ESP-IDF path and the project path. + COMPONENTS: A list of component names. Defaults to all the component found in the + COMPONENT_DIRS directory + EXTRA_COMPONENT_DIRS: Defaults to unset. Use this to add directories to the default + COMPONENT_DIRS. + SRCDIRS: Directories under the project dir containing project-specific sources. + Defaults to 'main'. These are treated as 'lite' components: they do not have + include directories that are passed to the compilation pass of all components and + they do not have a Kconfig option. + +Component makefile variables that can be set by the programmer:: + + COMPONENT_ADD_INCLUDEDIRS: Relative path to include directories to be added to + the entire project + COMPONENT_PRIV_INCLUDEDIRS: Relative path to include directories that are only used + when compiling this specific component + COMPONENT_DEPENDS: Names of any components that need to be compiled before this component. + COMPONENT_ADD_LDFLAGS: Ld flags to add for this project. Defaults to -l$(COMPONENT_NAME). + Add libraries etc in the current directory as $(abspath libwhatever.a) + COMPONENT_EXTRA_INCLUDES: Any extra include paths. These will be prefixed with '-I' and + passed to the compiler; please put absolute paths here. + COMPONENT_SRCDIRS: Relative directories to look in for sources. Defaults to '.', the current + directory (the root of the component) only. Use this to specify any subdirectories. Note + that specifying this overwrites the default action of compiling everything in the + components root dir; to keep this behaviour please also add '.' as a directory in this + list. + COMPONENT_OBJS: Object files to compile. Defaults to the .o variants of all .c and .S files + that are found in COMPONENT_SRCDIRS. + COMPONENT_EXTRA_CLEAN: Files that are generated using rules in the components Makefile + that also need to be cleaned + COMPONENT_BUILDRECIPE: Recipe to build the component. Optional. Defaults to building all + COMPONENT_OBJS and linking them into lib(componentname).a + COMPONENT_CLEANRECIPE: Recipe to clean the component. Optional. Defaults to removing + all built objects and libraries. + COMPONENT_BUILD_DIR: Equals the cwd of the component build, which is the build dir + of the component (where all the .o etc files should be created). + +These variables are already set early on in the Makefile and the values in it will +be usable in component or project Makefiles:: + + CC, LD, AR, OBJCOPY: Xtensa gcc tools + HOSTCC, HOSTLD etc: Host gcc tools + LDFLAGS, CFLAGS: Set to usable values as defined in ESP-IDF Makefile + PROJECT_NAME: Name of the project, as set in project makefile + PROJECT_PATH: Path to the root of the project folder + COMPONENTS: Name of the components to be included + CONFIG_*: All values set by 'make menuconfig' have corresponding Makefile variables. + +For components, there also are these defines:: + + COMPONENT_PATH: Absolute path to the root of the source tree of the component we're + compiling + COMPONENT_LIBRARY: The full path to the static library the components compilation pass + is supposed to generate + +Make Process +------------ + +The Make process is always invoked from the project directory by the +user; invoking it anywhere else gives an error. This is what happens if +we build a binary: + +The Makefile first determines how it was included. It figures out +various paths as well as the components available to it. It will also +collect the ldflags and includes that the components specify they need. +It does this by running a dummy make on the components with a "get_variable" +target that will output these values. + +The Makefile will then create targets to build the lib*.a libraries of +all components and make the elf target depend on this. The main Makefile +invokes Make on the componen.mk of each components inside a sub-mke: this way +the components have full freedom to do whatever is necessary to build +the library without influencing other components. By default, the +component.mk includes the utility makefile $(IDF_PATH)/make/component_common.mk. +This provides default targets and configurations that will work +out-of-the-box for most projects. + +KConfig +------- + +Each component can also have a Kconfig file, alongside the component.mk, that contains +details to add to "menuconfig" for this component. + +Makefile.projbuild +------------------ + +For components that have parts that need to be run when building of the +project is done, you can create a file called Makefile.projbuild in the +component root directory. This file will be included in the main +Makefile. + + +KConfig.projbuild +----------------- + +There's an equivalent to Makefile.projbuild for KConfig: if you want to include +options at the top-level, not inside the 'components' submenu then create a Kconfig.projbuild and +it will be included in the main menu of menuconfig. + +Take good care when (re)defining stuff here: because it's included with all the other +.projbuild files, it's possible to overwrite variables or re-declare targets defined in +the ESP-IDF makefile/Kconfig and other .projbuild files. It's generally better to just +create a KConfig file, if you can. + + +Writing Component Makefiles +--------------------------- + +A component consists of a directory which doubles as the name for the +component: a component named 'httpd' lives in a directory called 'httpd' +Because components usually live under the project directory (although +they can also reside in an other folder), the path to this may be +something like /home/myuser/projects/myprojects/components/httpd . + +One of the things that most components will have is a component.mk makefile, +containing instructions on how to build the component. Because the +build environment tries to set reasonable defaults that will work most +of the time, component.mk can be very small. + +Simplest component.mk +===================== + +At the minimum, component.mk will just include the ESP-IDF component "common" makefile, +which adds common component functionality:: + + include $(IDF_PATH)/make/component_common.mk + +This will take all the .c and .S files in the component root and compile +them into object files, finally linking them into a library. + + +Adding source directories +========================= + +By default, subdirectories are ignored. If your project has sources in subdirectories +instead of in the root of the component then you can tell that to the build +system by setting COMPONENT_SRCDIRS:: + + COMPONENT_SRCDIRS := src1 src2 + include $(IDF_PATH)/make/component_common.mk + +This will compile all source files in the src1/ and src2/ subdirectories +instead. + +Specifying source files +======================= + +The standard component.mk logic adds all .S and .c files in the source +directories as sources to be compiled unconditionally. It is possible +to circumvent that logic and hardcode the objects to be compiled by +manually setting the COMPONENT_OBJS variable to the name of the +objects that need to be generated:: + + COMPONENT_OBJS := file1.o file2.o thing/filea.o thing/fileb.o anotherthing/main.o + include $(IDF_PATH)/make/component_common.mk + + +Adding conditional configuration +================================ + +The configuration system can be used to conditionally compile some files +dependending on the options selected in ``make menuconfig``: + +Kconfig:: + config FOO_ENABLE_BAR + bool "Enable the BAR feature." + help + This enables the BAR feature of the FOO component. + +Makefile:: + COMPONENT_OBJS := foo_a.o foo_b.o $(if $(CONFIG_FOO_ENABLE_BAR),foo_bar.o foo_bar_interface.o) + include $(IDF_PATH)/make/component_common.mk + + +Source Code Generation +====================== + +Some components will have a situation where a source file isn't supplied +with the component itself but has to be generated from another file. Say +our component has a header file that consists of the converted binary +data of a BMP file, converted using a hypothetical tool called bmp2h. The +header file is then included in as C source file called graphics_lib.c:: + + COMPONENT_EXTRA_CLEAN := logo.h + + graphics_lib.o: logo.h + + logo.h: $(COMPONENT_PATH)/logo.bmp + bmp2h -i $^ -o $@ + + include $(IDF_PATH)/make/component_common.mk + +In this example, graphics_lib.o and logo.h will be generated in the +current directory (the build directory) while logo.bmp comes with the +component and resides under the component path. Because logo.h is a +generated file, it needs to be cleaned when make clean is called which +why it is added to the COMPONENT_EXTRA_CLEAN variable. + +Cosmetic Improvements +===================== + +The above example will work just fine, but there's one last cosmetic +improvement that can be done. The make system tries to make the make +process somewhat easier on the eyes by hiding the commands (unless you +run make with the V=1 switch) and this does not do that yet. Here's an +improved version that will output in the same style as the rest of the +make process:: + + COMPONENT_EXTRA_CLEAN := test_tjpgd_logo.h + + graphics_lib.o: logo.h + + logo.h: $(COMPONENT_PATH)/logo.bmp + $(summary) BMP2H $@ + $(Q) bmp2h -i $^ -o $@ + + include $(IDF_PATH)/make/component_common.mk + +Fully Overriding The Component Makefile +--------------------------------------- + +Obviously, there are cases where all these recipes are insufficient for a +certain component, for example when the component is basically a wrapper +around another third-party component not originally intended to be +compiled under this build system. In that case, it's possible to forego +the build system entirely by setting COMPONENT_OWNBUILDTARGET and +possibly COMPONENT_OWNCLEANTARGET and defining your own build- and clean +target. The build target can do anything as long as it creates +$(COMPONENT_LIBRARY) for the main file to link into the project binary, +and even that is not necessary: if the COMPONENT_ADD_LDFLAGS variable +is set, the component can instruct the linker to do anything else as well. + + +.. _esp-idf-template: https://github.com/espressif/esp-idf-template From b9a853c90358cf82081fee6b57c9bfa198892746 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Thu, 1 Sep 2016 10:04:30 +1000 Subject: [PATCH 12/51] README: Add Resources section with some links --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 0c7d437e2d..10fd72a3c3 100644 --- a/README.md +++ b/README.md @@ -49,3 +49,11 @@ The simplest way to use the partition table is to `make menuconfig` and choose o In both cases the factory app is flashed at offset 0x10000. If you `make partition_table` then it will print a summary of the partition table. For more details about partition tables and how to create custom variations, view the `docs/partition_tables.rst` file. + +# Resources + +* The [docs directory of the esp-idf repository](https://github.com/espressif/esp-idf/tree/master/docs) contains esp-idf documentation. + +* The [esp32.com forum](http://esp32.com/) is a place to ask questions and find community resources. + +* [Check the Issues section on github](https://github.com/espressif/esp-idf/issues) if you find a bug or have a feature request. Please check existing Issues before opening a new one. From 02543ee89522c49b7e0c990420ca18f12003e0d2 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Thu, 1 Sep 2016 18:58:06 +1000 Subject: [PATCH 13/51] CI: Build the esp-idf-template with the matching branch name, if it exists --- .gitlab-ci.yml | 4 ++++ make/test_build_system.sh | 1 + 2 files changed, 5 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 225b48f948..15a1db2fc0 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -18,6 +18,10 @@ build_template_app: script: - git clone https://github.com/espressif/esp-idf-template.git - cd esp-idf-template + # Try to use the same branch name for esp-idf-template that we're + # using on esp-idf. If it doesn't exist then just stick to the default + # branch + - git checkout ${CI_BUILD_REF_NAME} || echo "Using esp-idf-template default branch..." - make defconfig - make all diff --git a/make/test_build_system.sh b/make/test_build_system.sh index 015328bbbc..cb42356f05 100755 --- a/make/test_build_system.sh +++ b/make/test_build_system.sh @@ -29,6 +29,7 @@ function run_tests() print_status "Cloning template from ${ESP_IDF_TEMPLATE_GIT}..." git clone ${ESP_IDF_TEMPLATE_GIT} template cd template + git checkout ${CI_BUILD_REF_NAME} || echo "Using esp-idf-template default branch..." print_status "Updating template config..." make defconfig || exit $? From 04aea7f98743c78a2b8f00a3fb785a771a3c7d27 Mon Sep 17 00:00:00 2001 From: Yinling Date: Fri, 9 Sep 2016 10:49:03 +0800 Subject: [PATCH 14/51] update ci config file with 2 changes: 1. add build SSC and do sanity test config 2. add tags to each job as sanity test need to be executed on special runner --- .gitlab-ci.yml | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 15a1db2fc0..23f1a16d8d 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -9,6 +9,8 @@ before_script: build_template_app: stage: build image: espressif/esp32-ci-env + tags: + - build variables: SDK_PATH: "$CI_PROJECT_DIR" @@ -25,9 +27,54 @@ build_template_app: - make defconfig - make all + +.build_gitlab: &build_template + stage: build + tags: + - build + image: espressif/esp32-ci-env + + variables: + SDK_PATH: "$CI_PROJECT_DIR" + IDF_PATH: "$CI_PROJECT_DIR" + GIT_STRATEGY: clone + + # add gitlab key to build docker + before_script: + - mkdir -p ~/.ssh + - chmod 700 ~/.ssh + - echo -n $GITLAB_KEY >> ~/.ssh/id_rsa_base64 + - base64 --decode --ignore-garbage ~/.ssh/id_rsa_base64 > ~/.ssh/id_rsa + - chmod 600 ~/.ssh/id_rsa + - echo -e "Host gitlab.espressif.cn\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config + +build_ssc: + <<: *build_template + artifacts: + paths: + - ./SSC/build/*.bin + - ./SSC/build/*.elf + - ./SSC/build/*.map + - ./SSC/build/bootloader/*.bin + expire_in: 6 mos + + script: + # use gitlab wifi lib instead of github wifi lib + - git clone ssh://git@gitlab.espressif.cn:27227/idf/esp32-wifi-lib.git + - cp esp32-wifi-lib/* components/esp32/lib/ + - git clone ssh://git@gitlab.espressif.cn:27227/yinling/SSC.git + - cd SSC + - make defconfig + - chmod +x gen_misc_ng.sh + - ./gen_misc_ng.sh + + + test_nvs_on_host: stage: test image: espressif/esp32-ci-env + tags: + - nvs_host_test script: - cd components/nvs_flash/test - make test @@ -35,15 +82,58 @@ test_nvs_on_host: test_build_system: stage: test image: espressif/esp32-ci-env + tags: + - build_test variables: IDF_PATH: "$CI_PROJECT_DIR" script: - ./make/test_build_system.sh + + +# template for test jobs +.test_template: &test_template + stage: test + when: on_success + only: + - master + + variables: + # need user to set SDK_NAME and CONFIG_FILE (may need to set BIN_PATH and APP_NAME later) in before_script + SCRIPT_PATH: /home/gitlab-runner/auto_test_script + BIN_PATH: ${CI_PROJECT_DIR}/SSC/build/ + APP_NAME: ssc + LOG_PATH: $CI_PROJECT_DIR/$CI_BUILD_REF + + artifacts: + when: always + paths: + - $LOG_PATH + expire_in: 6 mos + + script: + - cd $SCRIPT_PATH + - python CIRunner.py -l $LOG_PATH -c $SDK_NAME/$CONFIG_FILE bin_path $APP_NAME $BIN_PATH + +sanity_test: + <<: *test_template + tags: + - ESP32 + - SSC_T1_1 + - SSC_T2_1 + - SSC_T1_WAN + before_script: + - SDK_NAME=ESP32_IDF + - CONFIG_FILE=sanity_test.yml + + + push_master_to_github: stage: deploy only: - master + tags: + - deploy when: on_success image: espressif/esp32-ci-env variables: From 1d355b93df0fd42499ab83fb8c0a5f6db357fbce Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Fri, 9 Sep 2016 13:53:38 +1000 Subject: [PATCH 15/51] lwip: Define LWIP_ESP8266 in port lwipopts.h not gcc command line --- components/lwip/component.mk | 2 +- components/lwip/include/lwip/port/lwipopts.h | 2 ++ components/tcpip_adapter/component.mk | 2 -- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/components/lwip/component.mk b/components/lwip/component.mk index 23c9fc160e..4fb0be5b63 100644 --- a/components/lwip/component.mk +++ b/components/lwip/component.mk @@ -6,6 +6,6 @@ COMPONENT_ADD_INCLUDEDIRS := include/lwip include/lwip/port COMPONENT_SRCDIRS := api apps/sntp apps core/ipv4 core/ipv6 core netif port/freertos port/netif port -EXTRA_CFLAGS := -Wno-error=address -Waddress -DLWIP_ESP8266 +EXTRA_CFLAGS := -Wno-error=address -Waddress include $(IDF_PATH)/make/component_common.mk diff --git a/components/lwip/include/lwip/port/lwipopts.h b/components/lwip/include/lwip/port/lwipopts.h index 00151a2ff9..26d3c8dcbd 100755 --- a/components/lwip/include/lwip/port/lwipopts.h +++ b/components/lwip/include/lwip/port/lwipopts.h @@ -34,6 +34,8 @@ #include +/* Enable all Espressif-only options */ +#define LWIP_ESP8266 /* ----------------------------------------------- diff --git a/components/tcpip_adapter/component.mk b/components/tcpip_adapter/component.mk index cb863d1b7d..a57ae0b12b 100755 --- a/components/tcpip_adapter/component.mk +++ b/components/tcpip_adapter/component.mk @@ -2,6 +2,4 @@ # Component Makefile # -EXTRA_CFLAGS := -DLWIP_ESP8266 - include $(IDF_PATH)/make/component_common.mk From 47db66e4953969fc9e0be805ee25910fbe42f4ed Mon Sep 17 00:00:00 2001 From: liuhan Date: Thu, 8 Sep 2016 10:50:52 +0800 Subject: [PATCH 16/51] esp32: modify realloc behaves just like malloc when pass a null pointer for ptr. --- components/esp32/syscalls.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/components/esp32/syscalls.c b/components/esp32/syscalls.c index 636e32670e..1aff0167aa 100644 --- a/components/esp32/syscalls.c +++ b/components/esp32/syscalls.c @@ -44,10 +44,17 @@ void _free_r(struct _reent *r, void* ptr) { return vPortFree(ptr); } -// TODO: improve realloc to grow buffer in place if possible void* _realloc_r(struct _reent *r, void* ptr, size_t size) { - void* new_chunk = pvPortMalloc(size); - if (new_chunk) { + void* new_chunk; + if (size == 0) { + if (ptr) { + vPortFree(ptr); + } + return NULL; + } + + new_chunk = pvPortMalloc(size); + if (new_chunk && ptr) { memcpy(new_chunk, ptr, size); vPortFree(ptr); } From 08ec33c6a2c244582d4735deb1a91b4ecc2cf9ac Mon Sep 17 00:00:00 2001 From: Jeroen Domburg Date: Mon, 5 Sep 2016 11:46:08 +0800 Subject: [PATCH 17/51] Make vTaskEnterCritical callable from ISR --- components/freertos/tasks.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/components/freertos/tasks.c b/components/freertos/tasks.c index f9ad8ff8cd..a7850ba2a6 100644 --- a/components/freertos/tasks.c +++ b/components/freertos/tasks.c @@ -163,6 +163,7 @@ typedef struct tskTaskControlBlock #if ( portCRITICAL_NESTING_IN_TCB == 1 ) UBaseType_t uxCriticalNesting; /*< Holds the critical section nesting depth for ports that do not maintain their own count in the port layer. */ + uint32_t uxOldInterruptState; /*< Interrupt state before the outer taskEnterCritical was called */ #endif #if ( configUSE_TRACE_FACILITY == 1 ) @@ -2595,8 +2596,7 @@ BaseType_t xReturn; /* THIS FUNCTION MUST BE CALLED FROM A CRITICAL SECTION. It can also be called from a critical section within an ISR. */ -//That makes the taskENTER_CRITICALs here unnecessary, right? -JD -// taskENTER_CRITICAL(&xTaskQueueMutex); + taskENTER_CRITICAL_ISR(&xTaskQueueMutex); /* The event list is sorted in priority order, so the first in the list can be removed as it is known to be the highest priority. Remove the TCB from the delayed list, and add it to the ready list. @@ -2654,7 +2654,7 @@ BaseType_t xReturn; prvResetNextTaskUnblockTime(); } #endif -// taskEXIT_CRITICAL(&xTaskQueueMutex); + taskEXIT_CRITICAL_ISR(&xTaskQueueMutex); return xReturn; } @@ -3761,7 +3761,7 @@ scheduler will re-enable the interrupts instead. */ void vTaskEnterCritical( portMUX_TYPE *mux ) #endif { - portDISABLE_INTERRUPTS(); + portENTER_CRITICAL_NESTED(uxOldInterruptState); #ifdef CONFIG_FREERTOS_PORTMUX_DEBUG vPortCPUAcquireMutex( mux, function, line ); #else @@ -3814,7 +3814,7 @@ scheduler will re-enable the interrupts instead. */ if( pxCurrentTCB[ xPortGetCoreID() ]->uxCriticalNesting == 0U ) { - portENABLE_INTERRUPTS(); + portEXIT_CRITICAL_NESTED(uxOldInterruptState); } else { From 128bb77c5acd661c7ac14d72f2c5ef38d1e66ddc Mon Sep 17 00:00:00 2001 From: Jeroen Domburg Date: Mon, 5 Sep 2016 11:58:40 +0800 Subject: [PATCH 18/51] Fix prev code to not crash horribly when scheduler is not running yet --- components/freertos/tasks.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/components/freertos/tasks.c b/components/freertos/tasks.c index a7850ba2a6..92970b582a 100644 --- a/components/freertos/tasks.c +++ b/components/freertos/tasks.c @@ -3761,7 +3761,10 @@ scheduler will re-enable the interrupts instead. */ void vTaskEnterCritical( portMUX_TYPE *mux ) #endif { - portENTER_CRITICAL_NESTED(uxOldInterruptState); + if( xSchedulerRunning != pdFALSE ) + { + portENTER_CRITICAL_NESTED(pxCurrentTCB[ xPortGetCoreID() ]->uxOldInterruptState); + } #ifdef CONFIG_FREERTOS_PORTMUX_DEBUG vPortCPUAcquireMutex( mux, function, line ); #else @@ -3814,7 +3817,7 @@ scheduler will re-enable the interrupts instead. */ if( pxCurrentTCB[ xPortGetCoreID() ]->uxCriticalNesting == 0U ) { - portEXIT_CRITICAL_NESTED(uxOldInterruptState); + portEXIT_CRITICAL_NESTED(pxCurrentTCB[ xPortGetCoreID() ]->uxOldInterruptState); } else { From 9664de6867f05579a3907ed1c225793085dde6a8 Mon Sep 17 00:00:00 2001 From: Jeroen Domburg Date: Mon, 5 Sep 2016 12:30:57 +0800 Subject: [PATCH 19/51] Add working portASSERT_IF_IN_ISR function, fix enter_critical thing even better. --- components/freertos/include/freertos/portmacro.h | 4 ++++ components/freertos/port.c | 7 +++++-- components/freertos/tasks.c | 9 ++++++++- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/components/freertos/include/freertos/portmacro.h b/components/freertos/include/freertos/portmacro.h index 908206eb37..ab83b0e05a 100644 --- a/components/freertos/include/freertos/portmacro.h +++ b/components/freertos/include/freertos/portmacro.h @@ -167,6 +167,9 @@ typedef struct { #define portDISABLE_INTERRUPTS() do { XTOS_SET_INTLEVEL(XCHAL_EXCM_LEVEL); portbenchmarkINTERRUPT_DISABLE(); } while (0) #define portENABLE_INTERRUPTS() do { portbenchmarkINTERRUPT_RESTORE(0); XTOS_SET_INTLEVEL(0); } while (0) +#define portASSERT_IF_IN_ISR() vPortAssertIfInISR() +void vPortAssertIfInISR(); + #define portCRITICAL_NESTING_IN_TCB 1 /* @@ -213,6 +216,7 @@ portBASE_TYPE vPortCPUReleaseMutex(portMUX_TYPE *mux); // Cleaner and preferred solution allows nested interrupts disabling and restoring via local registers or stack. // They can be called from interrupts too. +//NOT SMP-COMPATIBLE! Use only if all you want is to disable the interrupts locally! static inline unsigned portENTER_CRITICAL_NESTED() { unsigned state = XTOS_SET_INTLEVEL(XCHAL_EXCM_LEVEL); portbenchmarkINTERRUPT_DISABLE(); return state; } #define portEXIT_CRITICAL_NESTED(state) do { portbenchmarkINTERRUPT_RESTORE(state); XTOS_RESTORE_JUST_INTLEVEL(state); } while (0) diff --git a/components/freertos/port.c b/components/freertos/port.c index afa4978639..6117a2804e 100644 --- a/components/freertos/port.c +++ b/components/freertos/port.c @@ -248,14 +248,17 @@ void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMOR #endif +void vPortAssertIfInISR() +{ + configASSERT(port_interruptNesting[xPortGetCoreID()]==0) +} + /* * Wrapper for the Xtensa compare-and-set instruction. This subroutine will atomically compare * *mux to compare, and if it's the same, will set *mux to set. It will return the old value * of *addr. * - * Note: the NOPs are needed on the ESP31 processor but superfluous on the ESP32. - * * Warning: From the ISA docs: in some (unspecified) cases, the s32c1i instruction may return the * *bitwise inverse* of the old mem if the mem wasn't written. This doesn't seem to happen on the * ESP32, though. (Would show up directly if it did because the magic wouldn't match.) diff --git a/components/freertos/tasks.c b/components/freertos/tasks.c index 92970b582a..153fa3f03f 100644 --- a/components/freertos/tasks.c +++ b/components/freertos/tasks.c @@ -3763,7 +3763,7 @@ scheduler will re-enable the interrupts instead. */ { if( xSchedulerRunning != pdFALSE ) { - portENTER_CRITICAL_NESTED(pxCurrentTCB[ xPortGetCoreID() ]->uxOldInterruptState); + pxCurrentTCB[ xPortGetCoreID() ]->uxOldInterruptState=portENTER_CRITICAL_NESTED(); } #ifdef CONFIG_FREERTOS_PORTMUX_DEBUG vPortCPUAcquireMutex( mux, function, line ); @@ -3775,16 +3775,23 @@ scheduler will re-enable the interrupts instead. */ { ( pxCurrentTCB[ xPortGetCoreID() ]->uxCriticalNesting )++; + /* This is not the interrupt safe version of the enter critical function so assert() if it is being called from an interrupt context. Only API functions that end in "FromISR" can be used in an interrupt. Only assert if the critical nesting count is 1 to protect against recursive calls if the assert function also uses a critical section. */ + /* DISABLED in the esp32 port - because of SMP, vTaskEnterCritical + has to be used in way more places than before, and some are called + both from ISR as well as non-ISR code, thus we re-organized + vTaskEnterCritical to also work in ISRs. */ +#if 0 if( pxCurrentTCB[ xPortGetCoreID() ]->uxCriticalNesting == 1 ) { portASSERT_IF_IN_ISR(); } +#endif } else From a28ef1776ed35c6eb975808075aedb89e1ab146d Mon Sep 17 00:00:00 2001 From: liuzhifu Date: Wed, 7 Sep 2016 13:07:30 +0800 Subject: [PATCH 20/51] lwip: add socket tx flow control --- components/lwip/api/sockets.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/components/lwip/api/sockets.c b/components/lwip/api/sockets.c index 5b109eb375..3616ce2940 100755 --- a/components/lwip/api/sockets.c +++ b/components/lwip/api/sockets.c @@ -389,18 +389,18 @@ static void lwip_socket_drop_registered_memberships(int s); #ifdef LWIP_ESP8266 extern size_t system_get_free_heap_size(void); - -#define DELAY_WHEN_MEMORY_NOT_ENOUGH() \ +extern bool esp_wifi_tx_is_stop(void); +#define ESP32_TX_FLOW_CTRL() \ do{\ uint8_t _wait_delay = 0;\ - while (system_get_free_heap_size() < HEAP_HIGHWAT){\ + while ((system_get_free_heap_size() < HEAP_HIGHWAT) || esp_wifi_tx_is_stop()){\ vTaskDelay(_wait_delay/portTICK_RATE_MS);\ if (_wait_delay < 64) _wait_delay *= 2;\ }\ }while(0) #else -#define DELAY_WHEN_MEMORY_NOT_ENOUGH() +#define ESP32_TX_FLOW_CTRL() #endif /** The global array of available sockets */ @@ -1219,7 +1219,7 @@ lwip_send(int s, const void *data, size_t size, int flags) #endif /* (LWIP_UDP || LWIP_RAW) */ } - DELAY_WHEN_MEMORY_NOT_ENOUGH(); + ESP32_TX_FLOW_CTRL(); write_flags = NETCONN_COPY | ((flags & MSG_MORE) ? NETCONN_MORE : 0) | @@ -1402,7 +1402,7 @@ lwip_sendto(int s, const void *data, size_t size, int flags, #endif /* LWIP_TCP */ } - DELAY_WHEN_MEMORY_NOT_ENOUGH(); + ESP32_TX_FLOW_CTRL(); if ((to != NULL) && !SOCK_ADDR_TYPE_MATCH(to, sock)) { /* sockaddr does not match socket type (IPv4/IPv6) */ From 19c8476344d30daaf81dac90420731cae53f317f Mon Sep 17 00:00:00 2001 From: liuzhifu Date: Fri, 9 Sep 2016 10:20:14 +0800 Subject: [PATCH 21/51] modify macro ESP32_TX_FLOW_CTRL to inline function --- components/lwip/api/sockets.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/components/lwip/api/sockets.c b/components/lwip/api/sockets.c index 3616ce2940..4123712c15 100755 --- a/components/lwip/api/sockets.c +++ b/components/lwip/api/sockets.c @@ -390,17 +390,18 @@ static void lwip_socket_drop_registered_memberships(int s); #ifdef LWIP_ESP8266 extern size_t system_get_free_heap_size(void); extern bool esp_wifi_tx_is_stop(void); -#define ESP32_TX_FLOW_CTRL() \ -do{\ - uint8_t _wait_delay = 0;\ - while ((system_get_free_heap_size() < HEAP_HIGHWAT) || esp_wifi_tx_is_stop()){\ - vTaskDelay(_wait_delay/portTICK_RATE_MS);\ - if (_wait_delay < 64) _wait_delay *= 2;\ - }\ -}while(0) +inline void esp32_tx_flow_ctrl(void) +{ + uint8_t _wait_delay = 0; + + while ((system_get_free_heap_size() < HEAP_HIGHWAT) || esp_wifi_tx_is_stop()){ + vTaskDelay(_wait_delay/portTICK_RATE_MS); + if (_wait_delay < 64) _wait_delay *= 2; + } +} #else -#define ESP32_TX_FLOW_CTRL() +#define esp32_tx_flow_ctrl() #endif /** The global array of available sockets */ @@ -1219,7 +1220,7 @@ lwip_send(int s, const void *data, size_t size, int flags) #endif /* (LWIP_UDP || LWIP_RAW) */ } - ESP32_TX_FLOW_CTRL(); + esp32_tx_flow_ctrl(); write_flags = NETCONN_COPY | ((flags & MSG_MORE) ? NETCONN_MORE : 0) | @@ -1402,7 +1403,7 @@ lwip_sendto(int s, const void *data, size_t size, int flags, #endif /* LWIP_TCP */ } - ESP32_TX_FLOW_CTRL(); + esp32_tx_flow_ctrl(); if ((to != NULL) && !SOCK_ADDR_TYPE_MATCH(to, sock)) { /* sockaddr does not match socket type (IPv4/IPv6) */ From e38c4b0365b495f19cf3079f4e6d2fdf27539b7c Mon Sep 17 00:00:00 2001 From: liuzhifu Date: Fri, 9 Sep 2016 14:31:10 +0800 Subject: [PATCH 22/51] modify esp32_tx_flow_ctrl to static function and move extern api to header file --- components/lwip/api/sockets.c | 6 +++--- components/lwip/include/lwip/port/arch/sys_arch.h | 4 +++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/components/lwip/api/sockets.c b/components/lwip/api/sockets.c index 4123712c15..851915877d 100755 --- a/components/lwip/api/sockets.c +++ b/components/lwip/api/sockets.c @@ -388,9 +388,9 @@ static void lwip_socket_drop_registered_memberships(int s); #endif /* LWIP_IGMP */ #ifdef LWIP_ESP8266 -extern size_t system_get_free_heap_size(void); -extern bool esp_wifi_tx_is_stop(void); -inline void esp32_tx_flow_ctrl(void) +//extern size_t system_get_free_heap_size(void); +//extern bool esp_wifi_tx_is_stop(void); +static inline void esp32_tx_flow_ctrl(void) { uint8_t _wait_delay = 0; diff --git a/components/lwip/include/lwip/port/arch/sys_arch.h b/components/lwip/include/lwip/port/arch/sys_arch.h index 945b4e170a..3895f23b3b 100644 --- a/components/lwip/include/lwip/port/arch/sys_arch.h +++ b/components/lwip/include/lwip/port/arch/sys_arch.h @@ -69,6 +69,8 @@ sys_sem_t* sys_thread_sem_init(void); void sys_thread_sem_deinit(void); sys_sem_t* sys_thread_sem_get(void); - +size_t system_get_free_heap_size(void); +bool esp_wifi_tx_is_stop(void); + #endif /* __SYS_ARCH_H__ */ From 32f01c61a2d3d6226bb44f297cedf24d4427f241 Mon Sep 17 00:00:00 2001 From: liuzhifu Date: Fri, 9 Sep 2016 17:54:13 +0800 Subject: [PATCH 23/51] add comments about current tx flow control --- components/lwip/api/sockets.c | 14 ++++++++++++-- components/lwip/include/lwip/port/arch/sys_arch.h | 4 ---- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/components/lwip/api/sockets.c b/components/lwip/api/sockets.c index 851915877d..91a5222e68 100755 --- a/components/lwip/api/sockets.c +++ b/components/lwip/api/sockets.c @@ -388,8 +388,18 @@ static void lwip_socket_drop_registered_memberships(int s); #endif /* LWIP_IGMP */ #ifdef LWIP_ESP8266 -//extern size_t system_get_free_heap_size(void); -//extern bool esp_wifi_tx_is_stop(void); + +/* Since esp_wifi_tx_is_stop/system_get_free_heap_size are not an public wifi API, so extern them here*/ +extern size_t system_get_free_heap_size(void); +extern bool esp_wifi_tx_is_stop(void); + +/* Please be notified that this flow control is just a workaround for fixing wifi Q full issue. + * Under UDP/TCP pressure test, we found that the sockets may cause wifi tx queue full if the socket + * sending speed is faster than the wifi sending speed, it will finally cause the packet to be dropped + * in wifi layer, it's not acceptable in some application. That's why we introdue the tx flow control here. + * However, current solution is just a workaround, we need to consider the return value of wifi tx interface, + * and feedback the return value to lwip and let lwip do the flow control itself. + */ static inline void esp32_tx_flow_ctrl(void) { uint8_t _wait_delay = 0; diff --git a/components/lwip/include/lwip/port/arch/sys_arch.h b/components/lwip/include/lwip/port/arch/sys_arch.h index 3895f23b3b..be8ff72260 100644 --- a/components/lwip/include/lwip/port/arch/sys_arch.h +++ b/components/lwip/include/lwip/port/arch/sys_arch.h @@ -68,9 +68,5 @@ void sys_delay_ms(uint32_t ms); sys_sem_t* sys_thread_sem_init(void); void sys_thread_sem_deinit(void); sys_sem_t* sys_thread_sem_get(void); - -size_t system_get_free_heap_size(void); -bool esp_wifi_tx_is_stop(void); - #endif /* __SYS_ARCH_H__ */ From 1c6859573b42df4a303935a653c3af11ac41b04b Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Mon, 5 Sep 2016 10:22:37 +0800 Subject: [PATCH 24/51] freertos: protect calls to prvAddTaskToReadyList with xTaskQueueMutex --- components/freertos/tasks.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/components/freertos/tasks.c b/components/freertos/tasks.c index 153fa3f03f..f53c67d4b5 100644 --- a/components/freertos/tasks.c +++ b/components/freertos/tasks.c @@ -3614,6 +3614,7 @@ In fact, nothing below this line has/is. { if( pxTCB->uxPriority < pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ) { + taskENTER_CRITICAL(&xTaskQueueMutex); /* Adjust the mutex holder state to account for its new priority. Only reset the event list item value if the value is not being used for anything else. */ @@ -3649,6 +3650,8 @@ In fact, nothing below this line has/is. pxTCB->uxPriority = pxCurrentTCB[ xPortGetCoreID() ]->uxPriority; } + taskEXIT_CRITICAL(&xTaskQueueMutex); + traceTASK_PRIORITY_INHERIT( pxTCB, pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ); } else @@ -3686,6 +3689,7 @@ In fact, nothing below this line has/is. /* Only disinherit if no other mutexes are held. */ if( pxTCB->uxMutexesHeld == ( UBaseType_t ) 0 ) { + taskENTER_CRITICAL(&xTaskQueueMutex); /* A task can only have an inhertied priority if it holds the mutex. If the mutex is held by a task then it cannot be given from an interrupt, and if a mutex is given by the @@ -3720,6 +3724,7 @@ In fact, nothing below this line has/is. switch should occur when the last mutex is returned whether a task is waiting on it or not. */ xReturn = pdTRUE; + taskEXIT_CRITICAL(&xTaskQueueMutex); } else { From 7c607e4d6313aff5c79764cc149b095acf1368a1 Mon Sep 17 00:00:00 2001 From: xiaxiaotian Date: Mon, 12 Sep 2016 11:38:13 +0800 Subject: [PATCH 25/51] Change the enum of wifi_storage_t to be the same as that in wifi lib. --- components/esp32/include/esp_wifi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/esp32/include/esp_wifi.h b/components/esp32/include/esp_wifi.h index 357788225a..d21eb1b851 100755 --- a/components/esp32/include/esp_wifi.h +++ b/components/esp32/include/esp_wifi.h @@ -235,8 +235,8 @@ esp_err_t esp_wifi_get_station_list(struct station_info **station); esp_err_t esp_wifi_free_station_list(void); typedef enum { - WIFI_STORAGE_RAM, WIFI_STORAGE_FLASH, + WIFI_STORAGE_RAM, } wifi_storage_t; esp_err_t esp_wifi_set_storage(wifi_storage_t storage); From f293d530f8b39ba8dbdf2fb3f69ce13407a2e38d Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Mon, 12 Sep 2016 17:31:43 +1000 Subject: [PATCH 26/51] esp32/lib: Bump WiFi revision --- components/esp32/lib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/esp32/lib b/components/esp32/lib index b95a359c34..dcd9c6c626 160000 --- a/components/esp32/lib +++ b/components/esp32/lib @@ -1 +1 @@ -Subproject commit b95a359c344cd052f45e3c38515e4613dd29f298 +Subproject commit dcd9c6c6263ea3e3cb31559aaa76e5be9151e397 From 5810dbef0509bf020e67018677ce677fd9e59f1f Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Mon, 12 Sep 2016 17:48:40 +1000 Subject: [PATCH 27/51] make: Add macro to test for & try to fix up files required for submodules Now applied to both esptool.py & esp32 wifi libs --- components/esp32/Makefile | 11 +++-------- components/esptool_py/Makefile.projbuild | 11 +++++++---- make/common.mk | 17 +++++++++++++++++ 3 files changed, 27 insertions(+), 12 deletions(-) diff --git a/components/esp32/Makefile b/components/esp32/Makefile index 2331f286c6..d67f50211c 100644 --- a/components/esp32/Makefile +++ b/components/esp32/Makefile @@ -37,14 +37,9 @@ include $(IDF_PATH)/make/component.mk ALL_LIB_FILES := $(patsubst %,$(COMPONENT_PATH)/lib/lib%.a,$(LIBS)) -# The binary libraries are in a git submodule, so this target will -# be invoked if any modules are missing (probably because -# git submodule update --init needs to be run). -$(ALL_LIB_FILES): - $(Q) [ -d ${IDF_PATH}/.git ] || ( @echo "ERROR: Missing libraries in esp32 component. esp-idf must be cloned from git to work."; exit 1 ) - $(Q) [ -x $(which git) ] || ( @echo "ERROR: Missing libraries in esp32 component. Need to run 'git submodule update --init' in esp-idf root directory."; exit 1 ) - @echo "Warning: Missing libraries in components/esp32/lib/ submodule. Going to try running 'git submodule update --init' in esp-idf root directory..." - cd ${IDF_PATH} && git submodule update --init +# automatically trigger a git submodule update +# if any libraries are missing +$(eval $(call SubmoduleRequiredForFiles,$(ALL_LIB_FILES))) # adding $(ALL_LIB_FILES) as a build dependency here is a hack to make # sure they get evaluated. Once TW6630 lands and we have library file diff --git a/components/esptool_py/Makefile.projbuild b/components/esptool_py/Makefile.projbuild index 4ddb51e6ac..9711929379 100644 --- a/components/esptool_py/Makefile.projbuild +++ b/components/esptool_py/Makefile.projbuild @@ -9,7 +9,8 @@ PYTHON ?= $(call dequote,$(CONFIG_PYTHON)) # to invoke esptool.py (with or without serial port args) # # NB: esptool.py lives in the sdk/bin directory not the component directory -ESPTOOLPY := $(PYTHON) $(COMPONENT_PATH)/esptool/esptool.py --chip esp32 +ESPTOOLPY_SRC := $(COMPONENT_PATH)/esptool/esptool.py +ESPTOOLPY := $(PYTHON) $(ESPTOOLPY_SRC) --chip esp32 ESPTOOLPY_SERIAL := $(ESPTOOLPY) --port $(ESPPORT) --baud $(ESPBAUD) # the no-stub argument is temporary until esptool.py fully supports compressed uploads @@ -17,12 +18,14 @@ ESPTOOLPY_WRITE_FLASH=$(ESPTOOLPY_SERIAL) $(if $(CONFIG_ESPTOOLPY_COMPRESSED),-- ESPTOOL_ALL_FLASH_ARGS += $(CONFIG_APP_OFFSET) $(APP_BIN) -$(APP_BIN): $(APP_ELF) +$(APP_BIN): $(APP_ELF) $(ESPTOOLPY_SRC) $(Q) $(ESPTOOLPY) elf2image -o $@ $< -flash: all_binaries +flash: all_binaries $(ESPTOOLPY_SRC) @echo "Flashing project app to $(CONFIG_APP_OFFSET)..." $(Q) $(ESPTOOLPY_WRITE_FLASH) $(ESPTOOL_ALL_FLASH_ARGS) -app-flash: $(APP_BIN) +app-flash: $(APP_BIN) $(ESPTOOLPY_SRC) $(Q) $(ESPTOOLPY_WRITE_FLASH) $(CONFIG_APP_OFFSET) $(APP_BIN) + +$(eval $(call SubmoduleRequiredForFiles,$(ESPTOOLPY_SRC))) diff --git a/make/common.mk b/make/common.mk index 7f372cc305..adae46738e 100644 --- a/make/common.mk +++ b/make/common.mk @@ -49,6 +49,23 @@ summary := @echo details := @true endif +# Pseudo-target to handle the case where submodules need to be +# re-initialised. +# +# $(eval $(call SubmoduleRequiredForFiles,FILENAMES)) to create a target that +# automatically runs 'git submodule update --init' if those files +# are missing, and fails if this is not possible. +define SubmoduleRequiredForFiles +$(1): + @echo "WARNING: Missing submodule for $$@..." + $(Q) [ -d ${IDF_PATH}/.git ] || ( echo "ERROR: esp-idf must be cloned from git to work."; exit 1) + $(Q) [ -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 +endef + + + # General make utilities # convenience variable for printing an 80 asterisk wide separator line From bdc4ecb9ddb7fb40dddcd8bd4257e7b9a9444c4a Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Mon, 12 Sep 2016 18:04:09 +1000 Subject: [PATCH 28/51] CI for SSC: Allow for submodules & using the gitlab repo's libraries --- .gitlab-ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 23f1a16d8d..9bb2fe175b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -59,8 +59,10 @@ build_ssc: expire_in: 6 mos script: + - git submodule update --init # use gitlab wifi lib instead of github wifi lib - git clone ssh://git@gitlab.espressif.cn:27227/idf/esp32-wifi-lib.git + - rm -rf components/esp32/lib/* - cp esp32-wifi-lib/* components/esp32/lib/ - git clone ssh://git@gitlab.espressif.cn:27227/yinling/SSC.git - cd SSC From bab3faba58be405d5634c1fa1e6c4d6ae6de0d09 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Mon, 12 Sep 2016 18:39:13 +1000 Subject: [PATCH 29/51] add_path.sh: Use non-bash-specific instructions --- add_path.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/add_path.sh b/add_path.sh index e2ef40c44b..6b69f8d44f 100644 --- a/add_path.sh +++ b/add_path.sh @@ -4,7 +4,7 @@ # # Use this script like this: # -# source ${IDF_PATH}/add_path.sh +# . ${IDF_PATH}/add_path.sh # if [ -z ${IDF_PATH} ]; then echo "IDF_PATH must be set before including this script." From 24011ddd057b6941321ae3422db312db53a05e25 Mon Sep 17 00:00:00 2001 From: jack Date: Wed, 31 Aug 2016 21:53:23 +0800 Subject: [PATCH 30/51] header files: modify rom code and soc header files 1. timer reg file for both time group 0 and time group 1, not only timer group 0 2. fix bug that io mux header file mismatch with chip 3. fix bug that some BASE address not correct 4. add some static function to eagle.fpga32.rom.addr.v7.ld 5. add interrupts usage table 6. add some comments for rom code functions --- .../bootloader/src/main/bootloader_start.c | 2 +- components/esp32/include/esp_intr.h | 12 +- components/esp32/include/rom/aes.h | 1 + components/esp32/include/rom/bigint.h | 1 + components/esp32/include/rom/cache.h | 143 +++- components/esp32/include/rom/crc.h | 90 +++ components/esp32/include/rom/efuse.h | 63 +- components/esp32/include/rom/ets_sys.h | 673 +++++++++++++----- components/esp32/include/rom/gpio.h | 293 ++++++-- components/esp32/include/rom/rtc.h | 182 +++-- components/esp32/include/rom/secure_boot.h | 4 + components/esp32/include/rom/spi_flash.h | 421 ++++++++++- components/esp32/include/rom/ssc.h | 85 --- components/esp32/include/rom/uart.h | 266 ++++++- components/esp32/include/rom/wdt.h | 40 -- components/esp32/include/soc/io_mux_reg.h | 30 +- components/esp32/include/soc/soc.h | 275 +++---- components/esp32/include/soc/timers_reg.h | 88 +-- components/esp32/ld/esp32.rom.ld | 12 +- 19 files changed, 1944 insertions(+), 737 deletions(-) delete mode 100755 components/esp32/include/rom/ssc.h delete mode 100644 components/esp32/include/rom/wdt.h diff --git a/components/bootloader/src/main/bootloader_start.c b/components/bootloader/src/main/bootloader_start.c index b9df64012a..a25a266c08 100644 --- a/components/bootloader/src/main/bootloader_start.c +++ b/components/bootloader/src/main/bootloader_start.c @@ -294,7 +294,7 @@ void bootloader_main() log_notice( "compile time %s\n", __TIME__ ); /* close watch dog here */ REG_CLR_BIT( RTC_WDTCONFIG0, RTC_CNTL_WDT_FLASHBOOT_MOD_EN ); - REG_CLR_BIT( WDTCONFIG0, TIMERS_WDT_FLASHBOOT_MOD_EN ); + REG_CLR_BIT( WDTCONFIG0(0), TIMERS_WDT_FLASHBOOT_MOD_EN ); SPIUnlock(); /*register first sector in drom0 page 0 */ boot_cache_redirect( 0, 0x5000 ); diff --git a/components/esp32/include/esp_intr.h b/components/esp32/include/esp_intr.h index fc20838897..e138133f64 100644 --- a/components/esp32/include/esp_intr.h +++ b/components/esp32/include/esp_intr.h @@ -61,8 +61,8 @@ extern "C" { #define ESP_GPIO_INTR_ATTACH(func, arg) \ xt_set_interrupt_handler(ETS_GPIO_INUM, (func), (void *)(arg)) -#define ESP_UART_INTR_ATTACH(func, arg) \ - xt_set_interrupt_handler(ETS_UART_INUM, (func), (void *)(arg)) +#define ESP_UART0_INTR_ATTACH(func, arg) \ + xt_set_interrupt_handler(ETS_UART0_INUM, (func), (void *)(arg)) #define ESP_WDT_INTR_ATTACH(func, arg) \ xt_set_interrupt_handler(ETS_WDT_INUM, (func), (void *)(arg)) @@ -142,11 +142,11 @@ extern "C" { #define ESP_BB_INTR_DISABLE() \ ESP_INTR_DISABLE(ETS_BB_INUM) -#define ESP_UART_INTR_ENABLE() \ - ESP_INTR_ENABLE(ETS_UART_INUM) +#define ESP_UART0_INTR_ENABLE() \ + ESP_INTR_ENABLE(ETS_UART0_INUM) -#define ESP_UART_INTR_DISABLE() \ - ESP_INTR_DISABLE(ETS_UART_INUM) +#define ESP_UART0_INTR_DISABLE() \ + ESP_INTR_DISABLE(ETS_UART0_INUM) #define ESP_LEDC_INTR_ENABLE() \ ESP_INTR_ENABLE(ETS_LEDC_INUM) diff --git a/components/esp32/include/rom/aes.h b/components/esp32/include/rom/aes.h index 9fd0e5baea..950ce2e4af 100644 --- a/components/esp32/include/rom/aes.h +++ b/components/esp32/include/rom/aes.h @@ -21,6 +21,7 @@ extern "C" { #endif +//TODO, add comment for aes apis enum AES_BITS { AES128, AES192, diff --git a/components/esp32/include/rom/bigint.h b/components/esp32/include/rom/bigint.h index 461469cacd..2a6c2b82a1 100644 --- a/components/esp32/include/rom/bigint.h +++ b/components/esp32/include/rom/bigint.h @@ -21,6 +21,7 @@ extern "C" { #endif +//TODO: add comment here void ets_bigint_enable(void); void ets_bigint_disable(void); diff --git a/components/esp32/include/rom/cache.h b/components/esp32/include/rom/cache.h index b9e59448f1..d5df8d1a6c 100644 --- a/components/esp32/include/rom/cache.h +++ b/components/esp32/include/rom/cache.h @@ -18,50 +18,127 @@ extern "C" { #endif -//=========================================== -// function : cache_init -// description: initialise cache mmu, mark all entries as invalid. -// conditions: -// Call Cache_Read_Disable() before calling this function. -// inputs: -// cpu_no is CPU number,0(PRO CPU) or 1(APP CPU), -// output: NONE -//=========================================== +/** \defgroup uart_apis, uart configuration and communication related apis + * @brief uart apis + */ + +/** @addtogroup uart_apis + * @{ + */ + +/** + * @brief Initialise cache mmu, mark all entries as invalid. + * Please do not call this function in your SDK application. + * + * @param int cpu_no : 0 for PRO cpu, 1 for APP cpu. + * + * @return None + */ void mmu_init(int cpu_no); -//=========================================== -// function : cache_flash_mmu_set -// description: Configure MMU to cache a flash region. -// conditions: -// Call this function to configure the flash cache before enabling it. -// Check return value to verify MMU was set correctly. -// inputs: -// cpu_no is CPU number,0(PRO CPU) or 1(APP CPU), -// pid is process identifier. Range 0~7 -// vaddr is "virtual" address in CPU address space. Can be IRam0, IRam1, IRom0 and DRom0 memory address. -// Should be aligned by psize -// paddr is "physical" address in flash controller's address space. -// ie for 16M flash the range is 0x000000~0xFFFFFF. Should be aligned by psize -// psize is page size of flash, in kilobytes. Can be 64, 32, 16. -// num is number of pages to be set, valid range 0 ~ (flash size)/(page size) -// output: error status -// 0 : mmu set success -// 1 : vaddr or paddr is not aligned -// 2 : pid error -// 3 : psize error -// 4 : mmu table to be written is out of range -// 5 : vaddr is out of range -//=========================================== +/** + * @brief Set Flash-Cache mmu mapping. + * Please do not call this function in your SDK application. + * + * @param int cpu_no : CPU number, 0 for PRO cpu, 1 for APP cpu. + * + * @param int pod : process identifier. Range 0~7. + * + * @param unsigned int vaddr : virtual address in CPU address space. + * Can be IRam0, IRam1, IRom0 and DRom0 memory address. + * Should be aligned by psize. + * + * @param unsigned int paddr : physical address in Flash. + * Should be aligned by psize. + * + * @param int psize : page size of flash, in kilobytes. Should be 64 here. + * + * @param int num : pages to be set. + * + * @return unsigned int: error status + * 0 : mmu set success + * 1 : vaddr or paddr is not aligned + * 2 : pid error + * 3 : psize error + * 4 : mmu table to be written is out of range + * 5 : vaddr is out of range + */ unsigned int cache_flash_mmu_set(int cpu_no, int pid, unsigned int vaddr, unsigned int paddr, int psize, int num); -unsigned int cache_sram_mmu_set(int cpu_no, int pid,unsigned int vaddr, unsigned int paddr, int psize, int num); +/** + * @brief Set Ext-SRAM-Cache mmu mapping. + * Please do not call this function in your SDK application. + * + * @param int cpu_no : CPU number, 0 for PRO cpu, 1 for APP cpu. + * + * @param int pod : process identifier. Range 0~7. + * + * @param unsigned int vaddr : virtual address in CPU address space. + * Can be IRam0, IRam1, IRom0 and DRom0 memory address. + * Should be aligned by psize. + * + * @param unsigned int paddr : physical address in Ext-SRAM. + * Should be aligned by psize. + * + * @param int psize : page size of flash, in kilobytes. Should be 32 here. + * + * @param int num : pages to be set. + * + * @return unsigned int: error status + * 0 : mmu set success + * 1 : vaddr or paddr is not aligned + * 2 : pid error + * 3 : psize error + * 4 : mmu table to be written is out of range + * 5 : vaddr is out of range + */ +unsigned int cache_sram_mmu_set(int cpu_no, int pid, unsigned int vaddr, unsigned int paddr, int psize, int num); + +/** + * @brief Initialise cache access for the cpu. + * Please do not call this function in your SDK application. + * + * @param int cpu_no : 0 for PRO cpu, 1 for APP cpu. + * + * @return None + */ void Cache_Read_Init(int cpu_no); +/** + * @brief Flush the cache value for the cpu. + * Please do not call this function in your SDK application. + * + * @param int cpu_no : 0 for PRO cpu, 1 for APP cpu. + * + * @return None + */ +void Cache_Flush(int cpu_no); + +/** + * @brief Disable Cache access for the cpu. + * Please do not call this function in your SDK application. + * + * @param int cpu_no : 0 for PRO cpu, 1 for APP cpu. + * + * @return None + */ void Cache_Read_Disable(int cpu_no); +/** + * @brief Enable Cache access for the cpu. + * Please do not call this function in your SDK application. + * + * @param int cpu_no : 0 for PRO cpu, 1 for APP cpu. + * + * @return None + */ void Cache_Read_Enable(int cpu_no); +/** + * @} + */ + #ifdef __cplusplus } #endif diff --git a/components/esp32/include/rom/crc.h b/components/esp32/include/rom/crc.h index be763d7dc5..509f22cd0b 100644 --- a/components/esp32/include/rom/crc.h +++ b/components/esp32/include/rom/crc.h @@ -18,14 +18,104 @@ extern "C" { #endif +/** \defgroup uart_apis, uart configuration and communication related apis + * @brief uart apis + */ + +/** @addtogroup uart_apis + * @{ + */ + + /* Standard CRC8/16/32 algorithms. */ +// CRC-8 x8+x2+x1+1 0x07 +// CRC16-CCITT x16+x12+x5+1 1021 ISO HDLC, ITU X.25, V.34/V.41/V.42, PPP-FCS +// CRC32: +//G(x) = x32 +x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x1 + 1 +//If your buf is not continuous, you can use the first result to be the second parameter. + +/** + * @brief Crc32 value that is in little endian. + * + * @param uint32_t crc : init crc value, use 0 at the first use. + * + * @param uint8_t const * buf : buffer to start calculate crc. + * + * @param uint32_t len : buffer length in byte. + * + * @return None + */ uint32_t crc32_le(uint32_t crc, uint8_t const * buf, uint32_t len); + +/** + * @brief Crc32 value that is in big endian. + * + * @param uint32_t crc : init crc value, use 0 at the first use. + * + * @param uint8_t const * buf : buffer to start calculate crc. + * + * @param uint32_t len : buffer length in byte. + * + * @return None + */ uint32_t crc32_be(uint32_t crc, uint8_t const * buf, uint32_t len); + +/** + * @brief Crc16 value that is in little endian. + * + * @param uint16_t crc : init crc value, use 0 at the first use. + * + * @param uint8_t const * buf : buffer to start calculate crc. + * + * @param uint32_t len : buffer length in byte. + * + * @return None + */ uint16_t crc16_le(uint16_t crc, uint8_t const * buf, uint32_t len); + +/** + * @brief Crc16 value that is in big endian. + * + * @param uint16_t crc : init crc value, use 0 at the first use. + * + * @param uint8_t const * buf : buffer to start calculate crc. + * + * @param uint32_t len : buffer length in byte. + * + * @return None + */ uint16_t crc16_be(uint16_t crc, uint8_t const * buf, uint32_t len); + +/** + * @brief Crc8 value that is in little endian. + * + * @param uint8_t crc : init crc value, use 0 at the first use. + * + * @param uint8_t const * buf : buffer to start calculate crc. + * + * @param uint32_t len : buffer length in byte. + * + * @return None + */ uint8_t crc8_le(uint8_t crc, uint8_t const * buf, uint32_t len); + +/** + * @brief Crc8 value that is in big endian. + * + * @param uint32_t crc : init crc value, use 0 at the first use. + * + * @param uint8_t const * buf : buffer to start calculate crc. + * + * @param uint32_t len : buffer length in byte. + * + * @return None + */ uint8_t crc8_be(uint8_t crc, uint8_t const * buf, uint32_t len); +/** + * @} + */ + #ifdef __cplusplus } #endif diff --git a/components/esp32/include/rom/efuse.h b/components/esp32/include/rom/efuse.h index 6d0252b5e4..0fa6fb9a40 100644 --- a/components/esp32/include/rom/efuse.h +++ b/components/esp32/include/rom/efuse.h @@ -18,10 +18,71 @@ extern "C" { #endif -void ets_efuse_read_op(void); +/** \defgroup efuse_APIs efuse APIs + * @brief ESP32 efuse read/write APIs + * @attention + * + */ +/** @addtogroup efuse_APIs + * @{ + */ + +/** + * @brief Do a efuse read operation, to update the efuse value to efuse read registers. + * + * @param null + * + * @return null + */ +void ets_efuse_read_op(viid); + +/** + * @brief Do a efuse write operation, to update efuse write registers to efuse, then you need call ets_efuse_read_op again. + * + * @param null + * + * @return null + */ void ets_efuse_program_op(void); +/** + * @brief Read 8M Analog Clock value(8 bit) in efuse, the analog clock will not change with temperature. + * It can be used to test the external xtal frequency, do not touch this efuse field. + * + * @param null + * + * @return u32: 1 for 100KHZ. + */ +u32 ets_efuse_get_8M_clock(void); + +/** + * @brief Read spi pad configuration, show gpio number of flash pad, includes 5 pads. + * + * @param null + * + * @return uint32_t: 0, invalid, flash pad decided by strapping + * else, bit[5:0] spiclk, bit[11:6] spiq, bit[17:12] spid, bit[23:18] spics0, bit[29:24] spihd + */ + +uint32_t ets_efuse_get_spiconfig(void); + +/** + * @brief A crc8 algorithm used in efuse check. + * + * @param unsigned char const * p : Pointer to original data. + * + * @param unsigned int len : Data length in byte. + * + * @return unsigned char: Crc value. + */ +unsigned char esp_crc8(unsigned char const * p, unsigned int len); + +/** + * @} + */ + + #ifdef __cplusplus } #endif diff --git a/components/esp32/include/rom/ets_sys.h b/components/esp32/include/rom/ets_sys.h index fd7bbdb9c4..04915c1b24 100644 --- a/components/esp32/include/rom/ets_sys.h +++ b/components/esp32/include/rom/ets_sys.h @@ -24,82 +24,243 @@ extern "C" { #endif -#define ETS_DEBUG -#define ETS_SERIAL_ENABLED() (1) +/** \defgroup ets_sys_apis, ets system related apis + * @brief ets system apis + */ + +/** @addtogroup ets_sys_apis + * @{ + */ + +/************************************************************************ + * NOTE + * Many functions in this header files can't be run in FreeRTOS. + * Please see the comment of the Functions. + * There are also some functions that doesn't work on FreeRTOS + * without listed in the header, such as: + * xtos functions start with "_xtos_" in ld file. + * + *********************************************************************** + */ + +/** \defgroup ets_apis, Espressif Task Scheduler related apis + * @brief ets apis + */ + +/** @addtogroup ets_apis + * @{ + */ + typedef enum { - ETS_OK = 0, - ETS_FAILED = 1 + ETS_OK = 0,/**< return successful in ets*/ + ETS_FAILED = 1/**< return failed in ets*/ } ETS_STATUS; typedef uint32_t ETSSignal; typedef uint32_t ETSParam; -typedef struct ETSEventTag ETSEvent; +typedef struct ETSEventTag ETSEvent;/**< Event transmit/receive in ets*/ struct ETSEventTag { - ETSSignal sig; - ETSParam par; + ETSSignal sig;/**< Event signal, in same task, different Event with different signal*/ + ETSParam par;/**< Event parameter, sometimes without usage, then will be set as 0*/ }; -typedef void (*ETSTask)(ETSEvent *e); - -enum ETS_User_Priorities { - /* task priorities... */ - TICK_TASK_A_PRIO = 2, - KBD_TASK_PRIO = 5, - MAX_ETS_USER_PRIO = 16, - - /* ISR priorities... */ - MAX_ETS_USER_ISR_PRIO = 0xFF - 16 -}; - -/* ETS interrupt entry and exit */ -/* actually we don't need the following 2 macros any more since we won't exit - * isr until it is finised, more over, we don't do nest interrupt - */ +typedef void (*ETSTask)(ETSEvent *e);/**< Type of the Task processer*/ +typedef void (* ets_idle_cb_t)(void *arg);/**< Type of the system idle callback*/ +/** + * @brief Start the Espressif Task Scheduler, which is an infinit loop. Please do not add code after it. + * + * @param none + * + * @return none + */ void ets_run(void); +/** + * @brief Set the Idle callback, when Tasks are processed, will call the callback before CPU goto sleep. + * + * @param ets_idle_cb_t func : The callback function. + * + * @param void *arg : Argument of the callback. + * + * @return None + */ +void ets_set_idle_cb(ets_idle_cb_t func, void *arg); + +/** + * @brief Init a task with processer, priority, queue to receive Event, queue length. + * + * @param ETSTask task : The task processer. + * + * @param uint8_t prio : Task priority, 0-31, bigger num with high priority, one priority with one task. + * + * @param ETSEvent *queue : Queue belongs to the task, task always receives Events, Queue is circular used. + * + * @param uint8_t qlen : Queue length. + * + * @return None + */ void ets_task(ETSTask task, uint8_t prio, ETSEvent *queue, uint8_t qlen); +/** + * @brief Post an event to an Task. + * + * @param uint8_t prio : Priority of the Task. + * + * @param ETSSignal sig : Event signal. + * + * @param ETSParam par : Event parameter + * + * @return ETS_OK : post successful + * @return ETS_FAILED : post failed + */ ETS_STATUS ets_post(uint8_t prio, ETSSignal sig, ETSParam par); +/** + * @} + */ -/* - * now things become complicated, print could be directed to uart and/or SDIO - */ +/** \defgroup ets_boot_apis, Boot routing related apis + * @brief ets boot apis + */ + +/** @addtogroup ets_apis + * @{ + */ + + +extern const char* const exc_cause_table[40];///**< excption cause that defined by the core.*/ + +/** + * @brief Set Pro cpu Entry code, code can be called in PRO CPU when booting is not completed. + * When Pro CPU booting is completed, Pro CPU will call the Entry code if not NULL. + * + * @param uint32_t start : the PRO Entry code address value in uint32_t + * + * @return None + */ +void ets_set_user_start(uint32_t start); + +/** + * @brief Set Pro cpu Startup code, code can be called when booting is not completed, or in Entry code. + * When Entry code completed, CPU will call the Startup code if not NULL, else call ets_run. + * + * @param uint32_t callback : the Startup code address value in uint32_t + * + * @return None : post successful + */ +void ets_set_startup_callback(uint32_t callback); + +/** + * @brief Set App cpu Entry code, code can be called in PRO CPU. + * When APP booting is completed, APP CPU will call the Entry code if not NULL. + * + * @param uint32_t start : the APP Entry code address value in uint32_t, stored in register APPCPU_CTRL_REG_D. + * + * @return None + */ +void ets_set_appcpu_boot_addr(uint32_t start); + +/** + * @brief unpack the image in flash to iram and dram, no using cache. + * + * @param uint32_t pos : Flash physical address. + * + * @param uint32_t* entry_addr: the pointer of an variable that can store Entry code address. + * + * @param bool jump : Jump into the code in the function or not. + * + * @param bool config : Config the flash when unpacking the image, config should be done only once. + * + * @return ETS_OK : unpack successful + * @return ETS_FAILED : unpack failed + */ +ETS_STATUS ets_unpack_flash_code_legacy(uint32_t pos, uint32_t *entry_addr, bool jump, bool config); + +/** + * @brief unpack the image in flash to iram and dram, using cache, maybe decrypting. + * + * @param uint32_t pos : Flash physical address. + * + * @param uint32_t* entry_addr: the pointer of an variable that can store Entry code address. + * + * @param bool jump : Jump into the code in the function or not. + * + * @param bool sb_need_check : Do security boot check or not. + * + * @param bool config : Config the flash when unpacking the image, config should be done only once. + * + * @return ETS_OK : unpack successful + * @return ETS_FAILED : unpack failed + */ +ETS_STATUS ets_unpack_flash_code(uint32_t pos, uint32_t *entry_addr, bool jump, bool sb_need_check, bool config); +/** + * @} + */ + + +/** \defgroup ets_printf_apis, ets_printf related apis used in ets + * @brief ets printf apis + */ + +/** @addtogroup ets_printf_apis + * @{ + */ + +/** + * @brief Printf the strings to uart or other devices, similar with printf, simple than printf. + * Can not print float point data format, or longlong data format. + * So we maybe only use this in ROM. + * + * @param const char* fmt : See printf. + * + * @param ... : See printf. + * + * @return int : the length printed to the output device. + */ int ets_printf(const char *fmt, ...); -/* by default it's UART, just install_uart_printf, set putc1 to NULL to disable */ +/** + * @brief Output a char to uart, which uart to output(which is in uart module in ROM) is not in scope of the function. + * Can not print float point data format, or longlong data format + * + * @param char c : char to output. + * + * @return None + */ +void ets_write_char_uart(char c); + +/** + * @brief Ets_printf have two output functions: putc1 and putc2, both of which will be called if need ouput. + * To install putc1, which is defaulted installed as ets_write_char_uart in none silent boot mode, as NULL in silent mode. + * + * @param void (*)(char) p: Output function to install. + * + * @return None + */ void ets_install_putc1(void (*p)(char c)); -void ets_install_uart_printf(void); -/* no need to install, call directly */ -int ets_uart_printf(const char *fmt, ...); - -/* usually we don't need to call this, unless we want to disable SDIO print */ +/** + * @brief Ets_printf have two output functions: putc1 and putc2, both of which will be called if need ouput. + * To install putc2, which is defaulted installed as NULL. + * + * @param void (*)(char) p: Output function to install. + * + * @return None + */ void ets_install_putc2(void (*p)(char c)); -/* @prepare_buf: allocate buffer for printf internal writting - * @putc: just set to NULL, let printf write to to buffer, unless if you want more fancy stuff - * @post_printf: will be called every time printf finish write buffer - * - * main idea of external printf is re-directing content to an external buffer. - * e.g. sip module allocates an event buffer in prepare_buf() and send the event to host in post_printf() - * moreover, you can check printf_buf_remain_len in post_printf(), send the event to host till buf is - * about to full. - * - * TBD: Another approach is sending printf parameter to host and let host to decode, which could save some bytes. - */ -void ets_install_external_printf(void (*prepare_buf)(char ** bufptr, uint16_t *buflen, uint32_t *cookie), - void (*putc)(char c), - void (*post_printf)(uint32_t cookie)); - -uint16_t est_get_printf_buf_remain_len(void); -void est_reset_printf_buf_len(void); - -/* external (SDIO) printf only, still need to install*/ -int ets_external_printf(const char *fmt, ...); +/** + * @brief Install putc1 as ets_write_char_uart. + * In silent boot mode(to void interfere the UART attached MCU), we can call this function, after booting ok. + * + * @param None + * + * @return None + */ +void ets_install_uart_printf(void); #define ETS_PRINTF(...) ets_printf(...) @@ -110,82 +271,254 @@ int ets_external_printf(const char *fmt, ...); } \ } while (0); -/* memory and string support */ -int8_t ets_char2xdigit(char ch); -uint8_t * ets_str2macaddr(uint8_t *macaddr, char *str); -void ets_getc(char *c); -void ets_putc(char c); +/** + * @} + */ -/* timer related */ -typedef uint32_t ETSHandle; -typedef void ETSTimerFunc(void *timer_arg); + +/** \defgroup ets_timer_apis, ets_timer related apis used in ets + * @brief ets timer apis + */ + +/** @addtogroup ets_timer_apis + * @{ + */ +typedef void ETSTimerFunc(void *timer_arg);/**< timer handler*/ typedef struct _ETSTIMER_ { - struct _ETSTIMER_ *timer_next; - uint32_t timer_expire; - uint32_t timer_period; - ETSTimerFunc *timer_func; - void *timer_arg; + struct _ETSTIMER_ *timer_next;/**< timer linker*/ + uint32_t timer_expire;/**< abstruct time when timer expire*/ + uint32_t timer_period;/**< timer period, 0 means timer is not periodic repeated*/ + ETSTimerFunc *timer_func;/**< timer handler*/ + void *timer_arg;/**< timer handler argument*/ } ETSTimer; +/** + * @brief Init ets timer, this timer range is 640 us to 429496 ms + * In FreeRTOS, please call FreeRTOS apis, never call this api. + * + * @param None + * + * @return None + */ void ets_timer_init(void); + +/** + * @brief Arm an ets timer, this timer range is 640 us to 429496 ms. + * In FreeRTOS, please call FreeRTOS apis, never call this api. + * + * @param ETSTimer *timer : Timer struct pointer. + * + * @param uint32_t tmout : Timer value in ms, range is 1 to 429496. + * + * @param bool repeat : Timer is periodic repeated. + * + * @return None + */ void ets_timer_arm(ETSTimer *timer, uint32_t tmout, bool repeat); + +/** + * @brief Arm an ets timer, this timer range is 640 us to 429496 ms. + * In FreeRTOS, please call FreeRTOS apis, never call this api. + * + * @param ETSTimer *timer : Timer struct pointer. + * + * @param uint32_t tmout : Timer value in us, range is 1 to 429496729. + * + * @param bool repeat : Timer is periodic repeated. + * + * @return None + */ +void ets_timer_arm_us(ETSTimer *ptimer, uint32_t us, bool repeat); + +/** + * @brief Disarm an ets timer. + * In FreeRTOS, please call FreeRTOS apis, never call this api. + * + * @param ETSTimer *timer : Timer struct pointer. + * + * @return None + */ void ets_timer_disarm(ETSTimer *timer); -void ets_timer_done(ETSTimer *ptimer); + +/** + * @brief Set timer callback and argument. + * In FreeRTOS, please call FreeRTOS apis, never call this api. + * + * @param ETSTimer *timer : Timer struct pointer. + * + * @param ETSTimerFunc *pfunction : Timer callback. + * + * @param void *parg : Timer callback argument. + * + * @return None + */ void ets_timer_setfn(ETSTimer *ptimer, ETSTimerFunc *pfunction, void *parg); -/* watchdog related */ -typedef enum { - WDT_NONE = -1, - WDT_DISABLED = 0, - WDT_CONTROL_RESET = 1, - WDT_CONTROL_INTR = 2, /* usually we use this mode? */ - WDT_CONTROL_EXTERNAL_FEED = 3, - WDT_TESET_OVERFLOW = 4, // intend to make watchdog overflow to test -} WDT_MODE; +/** + * @brief Unset timer callback and argument to NULL. + * In FreeRTOS, please call FreeRTOS apis, never call this api. + * + * @param ETSTimer *timer : Timer struct pointer. + * + * @return None + */ +void ets_timer_done(ETSTimer *ptimer); -typedef enum{ - WDT_INTERVAL_THREE_SEC = 3, - WDT_INTERVAL_SIX_SEC = 6, - WDT_INTERVAL_TWELVE_SEC = 12, -} WDT_INTERVAL_TIME; +/** + * @brief CPU do while loop for some time. + * In FreeRTOS task, please call FreeRTOS apis. + * + * @param uint32_t us : Delay time in us. + * + * @return None + */ +void ets_delay_us(uint32_t us); -void ets_wdt_init(void); -WDT_MODE ets_wdt_get_mode(void); -void ets_wdt_enable(WDT_MODE mode, WDT_INTERVAL_TIME feed_interval, - WDT_INTERVAL_TIME expire_interval); -WDT_MODE ets_wdt_disable(void); -void ets_wdt_restore(WDT_MODE old_mode); +/** + * @brief Set the real CPU ticks per us to the ets, so that ets_delay_us will be accurate. + * Call this function when CPU frequency is changed. + * + * @param uint32_t ticks_per_us : CPU ticks per us. + * + * @return None + */ +void ets_update_cpu_frequency(uint32_t ticks_per_us); -/* interrupt related */ -typedef void (* ets_isr_t)(void *); +/** + * @brief Get the real CPU ticks per us to the ets. + * This function do not return real CPU ticks per us, just the record in ets. It can be used to check with the real CPU frequency. + * + * @param None + * + * @return uint32_t : CPU ticks per us record in ets. + */ +uint32_t ets_get_cpu_frequency(); -#define ETS_WMAC_SOURCE 0 -#define ETS_SLC_SOURCE 1 -#define ETS_UART_SOURCE 13 -#define ETS_UART1_SOURCE 14 -#define ETS_FRC_TIMER2_SOURCE 43 +/** + * @brief Get xtal_freq/analog_8M*256 value calibrated in rtc module. + * + * @param None + * + * @return uint32_t : xtal_freq/analog_8M*256. + */ +uint32_t ets_get_xtal_scale(); -#define ETS_WMAC_INUM 0 -#define ETS_SLC_INUM 1 -#define ETS_SPI_INUM 2 -#define ETS_HSIP_INUM 2 -#define ETS_I2S_INUM 2 -#define ETS_RTC_INUM 3 -#define ETS_FRC_TIMER1_INUM 9 /* use edge*/ -#define ETS_FRC_TIMER2_INUM 10 /* use edge*/ -#define ETS_WDT_INUM 8 /* use edge*/ -#define ETS_GPIO_INUM 4 -#define ETS_UART_INUM 5 -#define ETS_UART1_INUM 5 -#define ETS_MAX_INUM 6 +/** + * @brief Get xtal_freq value, If value not stored in RTC_STORE5, than store. + * + * @param None + * + * @return uint32_t : if rtc store the value (RTC_STORE5 high 16 bits and low 16 bits with same value), read from rtc register. + * clock = (REG_READ(RTC_STORE5) & 0xffff) << 12; + * else if analog_8M in efuse + * clock = ets_get_xtal_scale() * 15625 * ets_efuse_get_8M_clock() / 40; + * else clock = 26M. + */ +uint32_t ets_get_detected_xtal_freq(); + +/** + * @} + */ + +/** \defgroup ets_intr_apis, ets interrupt configure related apis + * @brief ets intr apis + */ + +/** @addtogroup ets_intr_apis + * @{ + */ + +typedef void (* ets_isr_t)(void *);/**< interrupt handler type*/ + +/** + * @brief Attach a interrupt handler to a CPU interrupt number. + * This function equals to _xtos_set_interrupt_handler_arg(i, func, arg). + * In FreeRTOS, please call FreeRTOS apis, never call this api. + * + * @param int i : CPU interrupt number. + * + * @param ets_isr_t func : Interrupt handler. + * + * @param void *arg : argument of the handler. + * + * @return None + */ void ets_isr_attach(int i, ets_isr_t func, void *arg); + +/** + * @brief Mask the interrupts which show in mask bits. + * This function equals to _xtos_ints_off(mask). + * In FreeRTOS, please call FreeRTOS apis, never call this api. + * + * @param uint32_t mask : BIT(i) means mask CPU interrupt number i. + * + * @return None + */ void ets_isr_mask(uint32_t mask); + +/** + * @brief Unmask the interrupts which show in mask bits. + * This function equals to _xtos_ints_on(mask). + * In FreeRTOS, please call FreeRTOS apis, never call this api. + * + * @param uint32_t mask : BIT(i) means mask CPU interrupt number i. + * + * @return None + */ void ets_isr_unmask(uint32_t unmask); + +/** + * @brief Lock the interrupt to level 2. + * This function direct set the CPU registers. + * In FreeRTOS, please call FreeRTOS apis, never call this api. + * + * @param None + * + * @return None + */ void ets_intr_lock(void); + +/** + * @brief Unlock the interrupt to level 0. + * This function direct set the CPU registers. + * In FreeRTOS, please call FreeRTOS apis, never call this api. + * + * @param None + * + * @return None + */ void ets_intr_unlock(void); + +/** + * @brief Unlock the interrupt to level 0, and CPU will go into power save mode(wait interrupt). + * This function direct set the CPU registers. + * In FreeRTOS, please call FreeRTOS apis, never call this api. + * + * @param None + * + * @return None + */ +void ets_waiti0(void); + +/** + * @brief Attach an CPU interrupt to a hardware source. + * We have 4 steps to use an interrupt: + * 1.Attach hardware interrupt source to CPU. intr_matrix_set(0, ETS_WIFI_MAC_INTR_SOURCE, ETS_WMAC_INUM); + * 2.Set interrupt handler. xt_set_interrupt_handler(ETS_WMAC_INUM, func, NULL); + * 3.Enable interrupt for CPU. xt_ints_on(1 << ETS_WMAC_INUM); + * 4.Enable interrupt in the module. + * + * @param int cpu_no : The CPU which the interrupt number belongs. + * + * @param uint32_t model_num : The interrupt hardware source number, please see the interrupt hardware source table. + * + * @param uint32_t intr_num : The interrupt number CPU, please see the interrupt cpu using table. + * + * @return None + */ void intr_matrix_set(int cpu_no, uint32_t model_num, uint32_t intr_num); #define _ETSTR(v) # v @@ -194,125 +527,80 @@ void intr_matrix_set(int cpu_no, uint32_t model_num, uint32_t intr_num); : "=a" (__tmp) : : "memory" ); \ }) +#ifdef CONFIG_NONE_OS #define ETS_INTR_LOCK() \ - ets_intr_lock() + ets_intr_lock() #define ETS_INTR_UNLOCK() \ - ets_intr_unlock() - -#define ETS_CCOMPARE_INTR_ATTACH(func, arg) \ - ets_isr_attach(ETS_CCOMPARE_INUM, (func), (void *)(arg)) - -#define ETS_PWM_INTR_ATTACH(func, arg) \ - ets_isr_attach(ETS_PWM_INUM, (func), (void *)(arg)) - -#define ETS_WMAC_INTR_ATTACH(func, arg) \ - ets_isr_attach(ETS_WMAC_INUM, (func), (void *)(arg)) - -#define ETS_FRC_TIMER1_INTR_ATTACH(func, arg) \ - ets_isr_attach(ETS_FRC_TIMER1_INUM, (func), (void *)(arg)) - -#define ETS_FRC_TIMER2_INTR_ATTACH(func, arg) \ - ets_isr_attach(ETS_FRC_TIMER2_INUM, (func), (void *)(arg)) - -#define ETS_GPIO_INTR_ATTACH(func, arg) \ - ets_isr_attach(ETS_GPIO_INUM, (func), (void *)(arg)) - -#define ETS_UART_INTR_ATTACH(func, arg) \ - ets_isr_attach(ETS_UART_INUM, (func), (void *)(arg)) - -#define ETS_WDT_INTR_ATTACH(func, arg) \ - ets_isr_attach(ETS_WDT_INUM, (func), (void *)(arg)) - -#define ETS_RTC_INTR_ATTACH(func, arg) \ - ets_isr_attach(ETS_RTC_INUM, (func), (void *)(arg)) - -#define ETS_SLC_INTR_ATTACH(func, arg) \ - ets_isr_attach(ETS_SLC_INUM, (func), (void *)(arg)) + ets_intr_unlock() +#define ETS_ISR_ATTACH \ + ets_isr_attach #define ETS_INTR_ENABLE(inum) \ - xt_ints_on((1<= '0') && (c <= '9')) - -#define isxdigit(c) (((c >= '0') && (c <= '9')) || \ - ((c >= 'a') && (c <= 'f')) || \ - ((c >= 'A') && (c <= 'F')) ) - -#define isblank(c) ((c == ' ') || (c == '\t')) - -#define isupper(c) ((c >= 'A') && (c <= 'Z')) #endif +/** + * @} + */ #ifndef MAC2STR @@ -321,6 +609,9 @@ uint32_t ets_get_detected_xtal_freq(); #endif #define ETS_MEM_BAR() asm volatile ( "" : : : "memory" ) +/** + * @} + */ #ifdef __cplusplus } diff --git a/components/esp32/include/rom/gpio.h b/components/esp32/include/rom/gpio.h index afb8e20184..fee7aff2a6 100644 --- a/components/esp32/include/rom/gpio.h +++ b/components/esp32/include/rom/gpio.h @@ -25,6 +25,15 @@ extern "C" { #endif +/** \defgroup gpio_apis, uart configuration and communication related apis + * @brief gpio apis + */ + +/** @addtogroup gpio_apis + * @{ + */ + + #define GPIO_REG_READ(reg) READ_PERI_REG(reg) #define GPIO_REG_WRITE(reg, val) WRITE_PERI_REG(reg, val) #define GPIO_PIN_COUNT 40 @@ -46,9 +55,6 @@ typedef enum{ GPIO_PIN_INTR_HILEVEL = 5 }GPIO_INT_TYPE; -#define GREEN_LED_ON() GPIO_OUTPUT_SET(GPIO_ID_PIN(1) , 0) -#define GREEN_LED_OFF() GPIO_OUTPUT_SET(GPIO_ID_PIN(1) , 1) - #define GPIO_OUTPUT_SET(gpio_no, bit_value) \ ((gpio_no < 32) ? gpio_output_set(bit_value<BIT(0). + * There is no particular ordering guaranteed; so if the order of writes is significant, + * calling code should divide a single call into multiple calls. + * + * @param uint32_t set_mask : the gpios that need high level. + * + * @param uint32_t clear_mask : the gpios that need low level. + * + * @param uint32_t enable_mask : the gpios that need be changed. + * + * @param uint32_t disable_mask : the gpios that need diable output. + * + * @return None + */ +void gpio_output_set(uint32_t set_mask, uint32_t clear_mask, uint32_t enable_mask, uint32_t disable_mask); -/* - * Change GPIO pin output by setting, clearing, or disabling pins. - * In general, it is expected that a bit will be set in at most one - * of these masks. If a bit is clear in all masks, the output state - * remains unchanged. - * - * There is no particular ordering guaranteed; so if the order of - * writes is significant, calling code should divide a single call - * into multiple calls. - */ -void gpio_output_set(uint32_t set_mask, - uint32_t clear_mask, - uint32_t enable_mask, - uint32_t disable_mask) ROMFN_ATTR; -void gpio_output_set_high(uint32_t set_mask, - uint32_t clear_mask, - uint32_t enable_mask, - uint32_t disable_mask) ROMFN_ATTR; -/* - * Sample the value of GPIO input pins and returns a bitmask. - */ -uint32_t gpio_input_get(void) ROMFN_ATTR; -uint32_t gpio_input_get_high(void) ROMFN_ATTR; +/** + * @brief Change GPIO(32-39) pin output by setting, clearing, or disabling pins, GPIO32<->BIT(0). + * There is no particular ordering guaranteed; so if the order of writes is significant, + * calling code should divide a single call into multiple calls. + * + * @param uint32_t set_mask : the gpios that need high level. + * + * @param uint32_t clear_mask : the gpios that need low level. + * + * @param uint32_t enable_mask : the gpios that need be changed. + * + * @param uint32_t disable_mask : the gpios that need diable output. + * + * @return None + */ +void gpio_output_set_high(uint32_t set_mask, uint32_t clear_mask, uint32_t enable_mask, uint32_t disable_mask); -/* - * Set the specified GPIO register to the specified value. - * This is a very general and powerful interface that is not - * expected to be used during normal operation. It is intended - * mainly for debug, or for unusual requirements. - */ -void gpio_register_set(uint32_t reg_id, uint32_t value) ROMFN_ATTR; +/** + * @brief Sample the value of GPIO input pins(0-31) and returns a bitmask. + * + * @param None + * + * @return uint32_t : bitmask for GPIO input pins, BIT(0) for GPIO0. + */ +uint32_t gpio_input_get(void); -/* Get the current value of the specified GPIO register. */ -uint32_t gpio_register_get(uint32_t reg_id) ROMFN_ATTR; +/** + * @brief Sample the value of GPIO input pins(32-39) and returns a bitmask. + * + * @param None + * + * @return uint32_t : bitmask for GPIO input pins, BIT(0) for GPIO32. + */ +uint32_t gpio_input_get_high(void); -/* - * Register an application-specific interrupt handler for GPIO pin - * interrupts. Once the interrupt handler is called, it will not - * be called again until after a call to gpio_intr_ack. Any GPIO - * interrupts that occur during the interim are masked. - * - * The application-specific handler is called with a mask of - * pending GPIO interrupts. After processing pin interrupts, the - * application-specific handler may wish to use gpio_intr_pending - * to check for any additional pending interrupts before it returns. - */ -void gpio_intr_handler_register(gpio_intr_handler_fn_t fn, void *arg) ROMFN_ATTR; +/** + * @brief Register an application-specific interrupt handler for GPIO pin interrupts. + * Once the interrupt handler is called, it will not be called again until after a call to gpio_intr_ack. + * Please do not call this function in SDK. + * + * @param gpio_intr_handler_fn_t fn : gpio application-specific interrupt handler + * + * @param void *arg : gpio application-specific interrupt handler argument. + * + * @return None + */ +void gpio_intr_handler_register(gpio_intr_handler_fn_t fn, void *arg); -/* Determine which GPIO interrupts are pending. */ -uint32_t gpio_intr_pending(void) ROMFN_ATTR; -uint32_t gpio_intr_pending_high(void) ROMFN_ATTR; +/** + * @brief Get gpio interrupts which happens but not processed. + * Please do not call this function in SDK. + * + * @param None + * + * @return uint32_t : bitmask for GPIO pending interrupts, BIT(0) for GPIO0. + */ +uint32_t gpio_intr_pending(void); -/* - * Acknowledge GPIO interrupts. - * Intended to be called from the gpio_intr_handler_fn. - */ -void gpio_intr_ack(uint32_t ack_mask) ROMFN_ATTR; -void gpio_intr_ack_high(uint32_t ack_mask) ROMFN_ATTR; +/** + * @brief Get gpio interrupts which happens but not processed. + * Please do not call this function in SDK. + * + * @param None + * + * @return uint32_t : bitmask for GPIO pending interrupts, BIT(0) for GPIO32. + */ +uint32_t gpio_intr_pending_high(void); -void gpio_pin_wakeup_enable(uint32_t i, GPIO_INT_TYPE intr_state) ROMFN_ATTR; +/** + * @brief Ack gpio interrupts to process pending interrupts. + * Please do not call this function in SDK. + * + * @param uint32_t ack_mask: bitmask for GPIO ack interrupts, BIT(0) for GPIO0. + * + * @return None + */ +void gpio_intr_ack(uint32_t ack_mask); -void gpio_pin_wakeup_disable() ROMFN_ATTR; +/** + * @brief Ack gpio interrupts to process pending interrupts. + * Please do not call this function in SDK. + * + * @param uint32_t ack_mask: bitmask for GPIO ack interrupts, BIT(0) for GPIO32. + * + * @return None + */ +void gpio_intr_ack_high(uint32_t ack_mask); -//extern void gpio_module_install(struct gpio_api *api); +/** + * @brief Set GPIO to wakeup the ESP32. + * Please do not call this function in SDK. + * + * @param uint32_t i: gpio number. + * + * @param GPIO_INT_TYPE intr_state : only GPIO_PIN_INTR_LOLEVEL\GPIO_PIN_INTR_HILEVEL can be used + * + * @return None + */ +void gpio_pin_wakeup_enable(uint32_t i, GPIO_INT_TYPE intr_state); -void gpio_matrix_in(uint32_t gpio, uint32_t signal_idx, bool inv) ROMFN_ATTR; +/** + * @brief disable GPIOs to wakeup the ESP32. + * Please do not call this function in SDK. + * + * @param None + * + * @return None + */ +void gpio_pin_wakeup_disable(); -void gpio_matrix_out(uint32_t gpio, uint32_t signal_idx, bool out_inv, bool oen_inv) ROMFN_ATTR; +/** + * @brief set gpio input to a signal, one gpio can input to several signals. + * + * @param uint32_t gpio : gpio number, 0~0x27 + * gpio == 0x30, input 0 to signal + * gpio == 0x34, ??? + * gpio == 0x38, input 1 to signal + * + * @param uint32_t signal_idx : signal index. + * + * @param bool inv : the signal is inv or not + * + * @return None + */ +void gpio_matrix_in(uint32_t gpio, uint32_t signal_idx, bool inv); + +/** + * @brief set signal output to gpio, one signal can output to several gpios. + * + * @param uint32_t gpio : gpio number, 0~0x27 + * + * @param uint32_t signal_idx : signal index. + * signal_idx == 0x100, cancel output put to the gpio + * + * @param bool out_inv : the signal output is inv or not + * + * @param bool oen_inv : the signal output enable is inv or not + * + * @return None + */ +void gpio_matrix_out(uint32_t gpio, uint32_t signal_idx, bool out_inv, bool oen_inv); + +/** + * @brief Select pad as a gpio function from IOMUX. + * + * @param uint32_t gpio_num : gpio number, 0~0x27 + * + * @return None + */ +void gpio_pad_select_gpio(uint8_t gpio_num); + +/** + * @brief Set pad driver capability. + * + * @param uint32_t gpio_num : gpio number, 0~0x27 + * + * @param uint8_t drv : 0-3 + * + * @return None + */ +void gpio_pad_set_drv(uint8_t gpio_num, uint8_t drv); + +/** + * @brief Pull up the pad from gpio number. + * + * @param uint32_t gpio_num : gpio number, 0~0x27 + * + * @return None + */ +void gpio_pad_pullup(uint8_t gpio_num); + +/** + * @brief Pull down the pad from gpio number. + * + * @param uint32_t gpio_num : gpio number, 0~0x27 + * + * @return None + */ +void gpio_pad_pulldown(uint8_t gpio_num); + +/** + * @brief Unhold the pad from gpio number. + * + * @param uint32_t gpio_num : gpio number, 0~0x27 + * + * @return None + */ +void gpio_pad_unhold(uint8_t gpio_num); + +/** + * @brief Hold the pad from gpio number. + * + * @param uint32_t gpio_num : gpio number, 0~0x27 + * + * @return None + */ +void gpio_pad_hold(uint8_t gpio_num); + +/** + * @} + */ #ifdef __cplusplus } diff --git a/components/esp32/include/rom/rtc.h b/components/esp32/include/rom/rtc.h index 31323646f0..b5c6abe81c 100644 --- a/components/esp32/include/rom/rtc.h +++ b/components/esp32/include/rom/rtc.h @@ -26,30 +26,68 @@ extern "C" { #endif +/** \defgroup rtc_apis, rtc registers and memory related apis + * @brief rtc apis + */ + +/** @addtogroup rtc_apis + * @{ + */ + +/************************************************************************************** + * Note: * + * Some Rtc memory and registers are used, in ROM or in internal library. * + * Please do not use reserved or used rtc memory or registers. * + * * + ************************************************************************************* + * RTC Memory & Store Register usage + ************************************************************************************* + * rtc memory addr type size usage + * 0x3ff61000(0x50000000) Slow SIZE_CP Co-Processor code/Reset Entry + * 0x3ff61000+SIZE_CP Slow 7936-SIZE_CP + * 0x3ff62f00 Slow 256 Reserved + * + * 0x3ff80000(0x400c0000) Fast 8192 deep sleep entry code + * + ************************************************************************************* + * Rtc store registers usage + * RTC_STORE0 + * RTC_STORE1 + * RTC_STORE2 + * RTC_STORE3 + * RTC_STORE4 Reserved + * RTC_STORE5 External Xtal Frequency + * RTC_STORE6 FAST_RTC_MEMORY_ENTRY + * RTC_STORE7 FAST_RTC_MEMORY_CRC + ************************************************************************************* + */ +#define RTC_ENTRY_ADDR RTC_STORE6 +#define RTC_MEMORY_CRC RTC_STORE7 + + typedef enum { - AWAKE = 0, //CPU ON + AWAKE = 0, // 1 : skip (n - 1) commands. + */ +uint16_t SPI_Common_Command(SpiCommonCmd * cmd); + +/** + * @brief Unlock SPI write protect. + * Please do not call this function in SDK. + * + * @param None. + * + * @return SPI_FLASH_RESULT_OK : Unlock OK. + * SPI_FLASH_RESULT_ERR : Unlock error. + * SPI_FLASH_RESULT_TIMEOUT : Unlock timeout. + */ +SpiFlashOpResult SPIUnlock(); + +/** + * @brief SPI write protect. + * Please do not call this function in SDK. + * + * @param None. + * + * @return SPI_FLASH_RESULT_OK : Lock OK. + * SPI_FLASH_RESULT_ERR : Lock error. + * SPI_FLASH_RESULT_TIMEOUT : Lock timeout. + */ +SpiFlashOpResult SPILock(); + +/** + * @brief Update SPI Flash parameter. + * Please do not call this function in SDK. + * + * @param uint32_t deviceId : Device ID read from SPI, the low 32 bit. + * + * @param uint32_t chip_size : The Flash size. + * + * @param uint32_t block_size : The Flash block size. + * + * @param uint32_t sector_size : The Flash sector size. + * + * @param uint32_t page_size : The Flash page size. + * + * @param uint32_t status_mask : The Mask used when read status from Flash(use single CMD). + * + * @return SPI_FLASH_RESULT_OK : Update OK. + * SPI_FLASH_RESULT_ERR : Update error. + * SPI_FLASH_RESULT_TIMEOUT : Update timeout. + */ +SpiFlashOpResult SPIParamCfg(uint32_t deviceId, uint32_t chip_size, uint32_t block_size, uint32_t sector_size, uint32_t page_size, uint32_t status_mask); + +/** + * @brief Erase whole flash chip. + * Please do not call this function in SDK. + * + * @param None + * + * @return SPI_FLASH_RESULT_OK : Erase OK. + * SPI_FLASH_RESULT_ERR : Erase error. + * SPI_FLASH_RESULT_TIMEOUT : Erase timeout. + */ +SpiFlashOpResult SPIEraseChip(void); + +/** + * @brief Erase a block of flash. + * Please do not call this function in SDK. + * + * @param uint32_t block_num : Which block to erase. + * + * @return SPI_FLASH_RESULT_OK : Erase OK. + * SPI_FLASH_RESULT_ERR : Erase error. + * SPI_FLASH_RESULT_TIMEOUT : Erase timeout. + */ +SpiFlashOpResult SPIEraseBlock(uint32_t block_num); + +/** + * @brief Erase a sector of flash. + * Please do not call this function in SDK. + * + * @param uint32_t sector_num : Which sector to erase. + * + * @return SPI_FLASH_RESULT_OK : Erase OK. + * SPI_FLASH_RESULT_ERR : Erase error. + * SPI_FLASH_RESULT_TIMEOUT : Erase timeout. + */ +SpiFlashOpResult SPIEraseSector(uint32_t sector_num); + +/** + * @brief Erase some sectors. + * Please do not call this function in SDK. + * + * @param uint32_t start_addr : Start addr to erase, should be sector aligned. + * + * @param uint32_t area_len : Length to erase, should be sector aligned. + * + * @return SPI_FLASH_RESULT_OK : Erase OK. + * SPI_FLASH_RESULT_ERR : Erase error. + * SPI_FLASH_RESULT_TIMEOUT : Erase timeout. + */ +SpiFlashOpResult SPIEraseArea(uint32_t start_addr, uint32_t area_len); + +/** + * @brief Write Data to Flash, you should Erase it yourself if need. + * Please do not call this function in SDK. + * + * @param uint32_t dest_addr : Address to write, should be 4 bytes aligned. + * + * @param const uint32_t* src : The pointer to data which is to write. + * + * @param uint32_t len : Length to write, should be 4 bytes aligned. + * + * @return SPI_FLASH_RESULT_OK : Write OK. + * SPI_FLASH_RESULT_ERR : Write error. + * SPI_FLASH_RESULT_TIMEOUT : Write timeout. + */ +SpiFlashOpResult SPIWrite(uint32_t dest_addr, const uint32_t* src, int32_t len); + +/** + * @brief Read Data from Flash, you should Erase it yourself if need. + * Please do not call this function in SDK. + * + * @param uint32_t src_addr : Address to read, should be 4 bytes aligned. + * + * @param uint32_t* data : The buf to read the data. + * + * @param uint32_t len : Length to read, should be 4 bytes aligned. + * + * @return SPI_FLASH_RESULT_OK : Read OK. + * SPI_FLASH_RESULT_ERR : Read error. + * SPI_FLASH_RESULT_TIMEOUT : Read timeout. + */ +SpiFlashOpResult SPIRead(uint32_t src_addr, uint32_t* dest, int32_t len); + +/** + * @brief SPI1 go into encrypto mode. + * Please do not call this function in SDK. + * + * @param None + * + * @return None + */ +void SPI_Write_Encrypt_Enable(); + +/** + * @brief Prepare 32 Bytes data to encrpto writing, you should Erase it yourself if need. + * Please do not call this function in SDK. + * + * @param uint32_t flash_addr : Address to write, should be 32 bytes aligned. + * + * @param uint32_t* data : The pointer to data which is to write. + * + * @return SPI_FLASH_RESULT_OK : Prepare OK. + * SPI_FLASH_RESULT_ERR : Prepare error. + * SPI_FLASH_RESULT_TIMEOUT : Prepare timeout. + */ +SpiFlashOpResult SPI_Prepare_Encrypt_Data(uint32_t flash_addr, uint32_t* data); + +/** + * @brief SPI1 go out of encrypto mode. + * Please do not call this function in SDK. + * + * @param None + * + * @return None + */ +void SPI_Write_Encrypt_Disable(); + +/** + * @brief Encrpto writing data to flash, you should Erase it yourself if need. + * Please do not call this function in SDK. + * + * @param uint32_t flash_addr : Address to write, should be 32 bytes aligned. + * + * @param uint32_t* data : The pointer to data which is to write. + * + * @param uint32_t len : Length to write, should be 32 bytes aligned. + * + * @return SPI_FLASH_RESULT_OK : Encrypto write OK. + * SPI_FLASH_RESULT_ERR : Encrypto write error. + * SPI_FLASH_RESULT_TIMEOUT : Encrypto write timeout. + */ +SpiFlashOpResult SPI_Encrypt_Write(uint32_t flash_addr, uint32_t* data, uint32_t len); + +/** + * @} + */ #ifdef __cplusplus } diff --git a/components/esp32/include/rom/ssc.h b/components/esp32/include/rom/ssc.h deleted file mode 100755 index 509e0da2f8..0000000000 --- a/components/esp32/include/rom/ssc.h +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright 2011-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef _ROM_SSC_H_ -#define _ROM_SSC_H_ - -#include "esp_types.h" - -#include "esp_attr.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct cmd_s { - char *cmd_str; -#define CMD_T_ASYNC 0x01 -#define CMD_T_SYNC 0x02 - uint8_t flag; - uint8_t id; - void (* cmd_func)(void); - void (* cmd_callback)(void *arg); -} ssc_cmd_t; - -#define ssc_printf ets_printf -#define SSC_CMD_N 10 //since the command not added in ssc_cmd.c -#define MAX_LINE_N 40 -#define PROMPT ":>" -#define SSC_EVT_N 4 - - -#define SSC_PRIO 30 -enum { - CMD_SET_SSID = 0, - CMD_SCAN, - CMD_CONNECT, - CMD_DISCONNECT, - CMD_SET_MACADDR, - CMD_PING, - CMD_PING_COUNT, - CMD_PING_LENGTH, - CMD_SET_IP, -// CMD_RD_I2C, -// CMD_SET_NULL, it's just for solving the old rom bug -// CMD_SET_I2C, -// CMD_RD_I2CM, -// CMD_SET_I2CM, -// CMD_SET_PBUS, -// CMD_SET_TXTONE, -// CMD_SET_STOPTONE, - CMD_END, -}; - -enum { - SIG_SSC_RUNCMD, - SIG_SSC_CMDDONE, - SIG_SSC_RESTART, - SIG_SSC_UART_RX_CHAR, -}; - -void ssc_attach(void) ROMFN_ATTR; -void ssc_cmd_done(int cmd_id, STATUS status) ROMFN_ATTR; -int ssc_param_len(void) ROMFN_ATTR; -char * ssc_param_str(void) ROMFN_ATTR; -void ssc_register(ssc_cmd_t *cmdset, uint8_t cmdnum, void (* help)(void)) ROMFN_ATTR; - -extern ssc_cmd_t sscCmdSet[]; -void ssc_help(void); - -#ifdef __cplusplus -} -#endif - -#endif /* _ROM_SSC_H_ */ diff --git a/components/esp32/include/rom/uart.h b/components/esp32/include/rom/uart.h index b295697730..ee0e01d3cf 100755 --- a/components/esp32/include/rom/uart.h +++ b/components/esp32/include/rom/uart.h @@ -22,6 +22,14 @@ extern "C" { #endif +/** \defgroup uart_apis, uart configuration and communication related apis + * @brief uart apis + */ + +/** @addtogroup uart_apis + * @{ + */ + #define RX_BUFF_SIZE 0x100 #define TX_BUFF_SIZE 100 @@ -153,33 +161,251 @@ typedef struct{ int received; } UartDevice; -void Uart_Init(uint8_t uart_no, uint32_t clock) ROMFN_ATTR; -STATUS UartTxString(uint8_t* pString) ROMFN_ATTR; -STATUS UartRxString(uint8_t* pString, uint8_t MaxStrlen) ROMFN_ATTR; +/** + * @brief Init uart device struct value and reset uart0/uart1 rx. + * Please do not call this function in SDK. + * + * @param None + * + * @return None + */ +void uartAttach(); -STATUS uart_tx_one_char(uint8_t TxChar) ROMFN_ATTR;//for print -STATUS uart_tx_one_char2(uint8_t TxChar) ROMFN_ATTR;//for send message -STATUS uart_rx_one_char(uint8_t* pRxChar) ROMFN_ATTR; -char uart_rx_one_char_block(void) ROMFN_ATTR; -void uart_rx_intr_handler(void * para) ROMFN_ATTR; -STATUS uart_rx_readbuff( RcvMsgBuff* pRxBuff, uint8_t* pRxByte) ROMFN_ATTR; -STATUS UartGetCmdLn(uint8_t * pCmdLn) ROMFN_ATTR; -UartDevice * GetUartDevice() ROMFN_ATTR; +/** + * @brief Init uart0 or uart1 for UART download booting mode. + * Please do not call this function in SDK. + * + * @param uint8_t uart_no : 0 for UART0, else for UART1. + * + * @param uint32_t clock : clock used by uart module, to adjust baudrate. + * + * @return None + */ +void Uart_Init(uint8_t uart_no, uint32_t clock); -void uartToggleInterrupt(bool en) ROMFN_ATTR; +/** + * @brief Modify uart baudrate. + * This function will reset RX/TX fifo for uart. + * + * @param uint8_t uart_no : 0 for UART0, 1 for UART1. + * + * @param uint32_t DivLatchValue : (clock << 4)/baudrate. + * + * @return None + */ +void uart_div_modify(uint8_t uart_no, uint32_t DivLatchValue); -STATUS SendMsg(uint8_t *pData, uint16_t DataLen) ROMFN_ATTR; +/** + * @brief Init uart0 or uart1 for UART download booting mode. + * Please do not call this function in SDK. + * + * @param uint8_t uart_no : 0 for UART0, 1 for UART1. + * + * @param uint8_t is_sync : 0, only one UART module, easy to detect, wait until detected; + * 1, two UART modules, hard to detect, detect and return. + * + * @return None + */ +int uart_baudrate_detect(uint8_t uart_no, uint8_t is_sync); -STATUS RcvMsg(uint8_t *pData, uint16_t MaxDataLen, uint8_t is_sync) ROMFN_ATTR; +/** + * @brief Switch printf channel of uart_tx_one_char. + * Please do not call this function when printf. + * + * @param uint8_t uart_no : 0 for UART0, 1 for UART1. + * + * @return None + */ +void uart_tx_switch(uint8_t uart_no); + +/** + * @brief Switch message exchange channel for UART download booting. + * Please do not call this function in SDK. + * + * @param uint8_t uart_no : 0 for UART0, 1 for UART1. + * + * @return None + */ +void uart_buff_switch(uint8_t uart_no); + +/** + * @brief Output a char to printf channel, wait until fifo not full. + * + * @param None + * + * @return OK. + */ +STATUS uart_tx_one_char(uint8_t TxChar); + +/** + * @brief Output a char to message exchange channel, wait until fifo not full. + * Please do not call this function in SDK. + * + * @param None + * + * @return OK. + */ +STATUS uart_tx_one_char2(uint8_t TxChar);//for send message + +/** + * @brief Wait until uart tx full empty. + * + * @param uint8_t uart_no : 0 for UART0, 1 for UART1. + * + * @return None. + */ +void uart_tx_flush(uint8_t uart_no); + +/** + * @brief Wait until uart tx full empty and the last char send ok. + * + * @param uint8_t uart_no : 0 for UART0, 1 for UART1. + * + * @return None. + */ +void uart_tx_wait_idle(uint8_t uart_no); + +/** + * @brief Get an input char from message channel. + * Please do not call this function in SDK. + * + * @param uint8_t* pRxChar : the pointer to store the char. + * + * @return OK for successful. + * FAIL for failed. + */ +STATUS uart_rx_one_char(uint8_t* pRxChar); + +/** + * @brief Get an input char to message channel, wait until successful. + * Please do not call this function in SDK. + * + * @param None + * + * @return char : input char value. + */ +char uart_rx_one_char_block(void); + +/** + * @brief Get an input string line from message channel. + * Please do not call this function in SDK. + * + * @param uint8_t* pString : the pointer to store the string. + * + * @param uint8_t MaxStrlen : the max string length, incude '\0'. + * + * @return OK. + */ +STATUS UartRxString(uint8_t* pString, uint8_t MaxStrlen); + +/** + * @brief Process uart recevied information in the interrupt handler. + * Please do not call this function in SDK. + * + * @param void * para : the message receive buffer. + * + * @return None + */ +void uart_rx_intr_handler(void * para); + +/** + * @brief Get an char from receive buffer. + * Please do not call this function in SDK. + * + * @param RcvMsgBuff* pRxBuff : the pointer to the struct that include receive buffer. + * + * @param uint8_t* pRxByte : the pointer to store the char. + * + * @return OK for successful. + * FAIL for failed. + */ +STATUS uart_rx_readbuff( RcvMsgBuff* pRxBuff, uint8_t* pRxByte); + +/** + * @brief Get all chars from receive buffer. + * Please do not call this function in SDK. + * + * @param uint8_t * pCmdLn : the pointer to store the string. + * + * @return OK for successful. + * FAIL for failed. + */ +STATUS UartGetCmdLn(uint8_t * pCmdLn); + +/** + * @brief Get uart configuration struct. + * Please do not call this function in SDK. + * + * @param None + * + * @return UartDevice * : uart configuration struct pointer. + */ +UartDevice * GetUartDevice(); + +/** + * @brief Send an packet to download tool, with ESC char. + * Please do not call this function in SDK. + * + * @param uint8_t * p : the pointer to output string. + * + * @param int len : the string length. + * + * @return None. + */ +void send_packet(uint8_t *p, int len); + +/** + * @brief Receive an packet from download tool, with ESC char. + * Please do not call this function in SDK. + * + * @param uint8_t * p : the pointer to input string. + * + * @param int len : If string length > len, the string will be truncated. + * + * @param uint8_t is_sync : 0, only one UART module; + * 1, two UART modules. + * + * @return int : the length of the string. + */ +int recv_packet(uint8_t *p, int len, uint8_t is_sync); + + +/** + * @brief Send an packet to download tool, with ESC char. + * Please do not call this function in SDK. + * + * @param uint8_t * pData : the pointer to input string. + * + * @param uint16_t DataLen : the string length. + * + * @return OK for successful. + * FAIL for failed. + */ +STATUS SendMsg(uint8_t *pData, uint16_t DataLen); + + +/** + * @brief Receive an packet from download tool, with ESC char. + * Please do not call this function in SDK. + * + * @param uint8_t * pData : the pointer to input string. + * + * @param uint16_t MaxDataLen : If string length > MaxDataLen, the string will be truncated. + * + * @param uint8_t is_sync : 0, only one UART module; + * 1, two UART modules. + * + * @return OK for successful. + * FAIL for failed. + */ +STATUS RcvMsg(uint8_t *pData, uint16_t MaxDataLen, uint8_t is_sync); -void uartAttach() ROMFN_ATTR; -void uart_div_modify(uint8_t uart_no, uint32_t DivLatchValue) ROMFN_ATTR; -int uart_baudrate_detect(uint8_t uart_no, uint8_t is_sync) ROMFN_ATTR; -void uart_buff_switch(uint8_t uart_no) ROMFN_ATTR; -void uart_tx_flush(uint8_t uart_no) ROMFN_ATTR; -void uart_tx_wait_idle(uint8_t uart_no) ROMFN_ATTR; extern UartDevice UartDev; +/** + * @} + */ + #ifdef __cplusplus } #endif diff --git a/components/esp32/include/rom/wdt.h b/components/esp32/include/rom/wdt.h deleted file mode 100644 index 04a31c3293..0000000000 --- a/components/esp32/include/rom/wdt.h +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2010-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef _ROM_WDT_H_ -#define _ROM_WDT_H_ - -#include "soc.h" -#include "ets_sys.h" - -#define WDT_RESET_VALUE 0x73 -#define WDT_RESET_LEN 7 //real time: (1<<(WDT_RESET_LEN+1))*pclk -#define WDT_CONTROL_ENABLED BIT0 -#define WDT_MODE_SET(v) (v) -#define WDT_TARGET_SET(v) (v) -#define WDT_ADDRESS 0 - -#define SEC_TO_WDT_TICK(s) (s * WDT_CLK_FREQ) //it's Pclk clock,44MHz - -typedef enum{ - NEXT_OVERFLOW_RESET = 0, - NEXT_OVERFLOW_NO_RESET = 1, - EACH_OVERFLOW_RESET = 2, -} WDT_RESP_MODE; - -#define WDT_DEFAULT_FEED_INTERVAL WDT_INTERVAL_SIX_SEC /* 6 seconds */ -#define WDT_DEFAULT_EXPIRE_INTERVAL WDT_INTERVAL_TWELVE_SEC /* 12 seconds */ - -#endif /* _ROM_WDT_H_ */ - diff --git a/components/esp32/include/soc/io_mux_reg.h b/components/esp32/include/soc/io_mux_reg.h index bc9f769b73..7be453e095 100644 --- a/components/esp32/include/soc/io_mux_reg.h +++ b/components/esp32/include/soc/io_mux_reg.h @@ -80,21 +80,24 @@ #define FUNC_GPIO33_GPIO33_0 0 #define PERIPHS_IO_MUX_GPIO25_U (DR_REG_IO_MUX_BASE +0x24) +#define FUNC_GPIO25_EMAC_RXD0 5 #define FUNC_GPIO25_GPIO25 2 #define FUNC_GPIO25_GPIO25_0 0 #define PERIPHS_IO_MUX_GPIO26_U (DR_REG_IO_MUX_BASE +0x28) +#define FUNC_GPIO26_EMAC_RXD1 5 #define FUNC_GPIO26_GPIO26 2 #define FUNC_GPIO26_GPIO26_0 0 #define PERIPHS_IO_MUX_GPIO27_U (DR_REG_IO_MUX_BASE +0x2c) -#define FUNC_GPIO27_EMAC_RXD2 5 +#define FUNC_GPIO27_EMAC_RX_DV 5 #define FUNC_GPIO27_GPIO27 2 #define FUNC_GPIO27_GPIO27_0 0 #define PERIPHS_IO_MUX_MTMS_U (DR_REG_IO_MUX_BASE +0x30) #define FUNC_MTMS_EMAC_TXD2 5 #define FUNC_MTMS_SD_CLK 4 +#define FUNC_MTMS_HS2_CLk 3 #define FUNC_MTMS_GPIO14 2 #define FUNC_MTMS_HSPICLK 1 #define FUNC_MTMS_MTMS 0 @@ -102,6 +105,7 @@ #define PERIPHS_IO_MUX_MTDI_U (DR_REG_IO_MUX_BASE +0x34) #define FUNC_MTDI_EMAC_TXD3 5 #define FUNC_MTDI_SD_DATA2 4 +#define FUNC_MTDI_HS2_DATA2 3 #define FUNC_MTDI_GPIO12 2 #define FUNC_MTDI_HSPIQ 1 #define FUNC_MTDI_MTDI 0 @@ -109,7 +113,7 @@ #define PERIPHS_IO_MUX_MTCK_U (DR_REG_IO_MUX_BASE +0x38) #define FUNC_MTCK_EMAC_RX_ER 5 #define FUNC_MTCK_SD_DATA3 4 -#define FUNC_MTCK_U0CTS 3 +#define FUNC_MTCK_HS2_DATA3 3 #define FUNC_MTCK_GPIO13 2 #define FUNC_MTCK_HSPID 1 #define FUNC_MTCK_MTCK 0 @@ -117,21 +121,20 @@ #define PERIPHS_IO_MUX_MTDO_U (DR_REG_IO_MUX_BASE +0x3c) #define FUNC_MTDO_EMAC_RXD3 5 #define FUNC_MTDO_SD_CMD 4 -#define FUNC_MTDO_U0RTS 3 +#define FUNC_MTDO_HS2_CMD 3 #define FUNC_MTDO_GPIO15 2 #define FUNC_MTDO_HSPICS0 1 #define FUNC_MTDO_MTDO 0 #define PERIPHS_IO_MUX_GPIO2_U (DR_REG_IO_MUX_BASE +0x40) -#define FUNC_GPIO2_EMAC_RX_DV 5 #define FUNC_GPIO2_SD_DATA0 4 +#define FUNC_GPIO2_HS2_DATA0 3 #define FUNC_GPIO2_GPIO2 2 #define FUNC_GPIO2_HSPIWP 1 #define FUNC_GPIO2_GPIO2_0 0 #define PERIPHS_IO_MUX_GPIO0_U (DR_REG_IO_MUX_BASE +0x44) #define FUNC_GPIO0_EMAC_TX_CLK 5 -#define FUNC_GPIO0_HS2_CMD 3 #define FUNC_GPIO0_GPIO0 2 #define FUNC_GPIO0_CLK_OUT1 1 #define FUNC_GPIO0_GPIO0_0 0 @@ -139,6 +142,7 @@ #define PERIPHS_IO_MUX_GPIO4_U (DR_REG_IO_MUX_BASE +0x48) #define FUNC_GPIO4_EMAC_TX_ER 5 #define FUNC_GPIO4_SD_DATA1 4 +#define FUNC_GPIO4_HS2_DATA1 3 #define FUNC_GPIO4_GPIO4 2 #define FUNC_GPIO4_HSPIHD 1 #define FUNC_GPIO4_GPIO4_0 0 @@ -207,15 +211,14 @@ #define FUNC_GPIO5_GPIO5_0 0 #define PERIPHS_IO_MUX_GPIO18_U (DR_REG_IO_MUX_BASE +0x70) -#define FUNC_GPIO18_EMAC_TXD0 5 #define FUNC_GPIO18_HS1_DATA7 3 #define FUNC_GPIO18_GPIO18 2 #define FUNC_GPIO18_VSPICLK 1 #define FUNC_GPIO18_GPIO18_0 0 #define PERIPHS_IO_MUX_GPIO19_U (DR_REG_IO_MUX_BASE +0x74) -#define FUNC_GPIO19_EMAC_TXD1 5 -#define FUNC_GPIO19_HS2_DATA2 3 +#define FUNC_GPIO19_EMAC_TXD0 5 +#define FUNC_GPIO19_U0CTS 3 #define FUNC_GPIO19_GPIO19 2 #define FUNC_GPIO19_VSPIQ 1 #define FUNC_GPIO19_GPIO19_0 0 @@ -225,33 +228,30 @@ #define FUNC_GPIO20_GPIO20_0 0 #define PERIPHS_IO_MUX_GPIO21_U (DR_REG_IO_MUX_BASE +0x7c) -#define FUNC_GPIO21_EMAC_RXD0 5 -#define FUNC_GPIO21_HS2_DATA3 3 +#define FUNC_GPIO21_EMAC_TX_EN 5 #define FUNC_GPIO21_GPIO21 2 #define FUNC_GPIO21_VSPIHD 1 #define FUNC_GPIO21_GPIO21_0 0 #define PERIPHS_IO_MUX_GPIO22_U (DR_REG_IO_MUX_BASE +0x80) -#define FUNC_GPIO22_EMAC_RXD1 5 -#define FUNC_GPIO22_HS2_CLK 3 +#define FUNC_GPIO22_EMAC_TXD1 5 +#define FUNC_GPIO22_U0RTS 3 #define FUNC_GPIO22_GPIO22 2 #define FUNC_GPIO22_VSPIWP 1 #define FUNC_GPIO22_GPIO22_0 0 #define PERIPHS_IO_MUX_U0RXD_U (DR_REG_IO_MUX_BASE +0x84) -#define FUNC_U0RXD_HS2_DATA0 3 #define FUNC_U0RXD_GPIO3 2 #define FUNC_U0RXD_CLK_OUT2 1 #define FUNC_U0RXD_U0RXD 0 #define PERIPHS_IO_MUX_U0TXD_U (DR_REG_IO_MUX_BASE +0x88) -#define FUNC_U0TXD_HS2_DATA1 3 +#define FUNC_U0TXD_EMAC_RXD2 3 #define FUNC_U0TXD_GPIO1 2 #define FUNC_U0TXD_CLK_OUT3 1 #define FUNC_U0TXD_U0TXD 0 #define PERIPHS_IO_MUX_GPIO23_U (DR_REG_IO_MUX_BASE +0x8c) -#define FUNC_GPIO23_EMAC_TX_EN 5 #define FUNC_GPIO23_HS1_STROBE 3 #define FUNC_GPIO23_GPIO23 2 #define FUNC_GPIO23_VSPID 1 diff --git a/components/esp32/include/soc/soc.h b/components/esp32/include/soc/soc.h index d542efe28e..46389106c5 100755 --- a/components/esp32/include/soc/soc.h +++ b/components/esp32/include/soc/soc.h @@ -61,10 +61,15 @@ #define REG_WRITE(_r, _v) (*(volatile uint32_t *)(_r)) = (_v) #define REG_READ(_r) (*(volatile uint32_t *)(_r)) +//get bit or get bits #define REG_GET_BIT(_r, _b) (*(volatile uint32_t*)(_r) & (_b)) +//set bit or set bits #define REG_SET_BIT(_r, _b) (*(volatile uint32_t*)(_r) |= (_b)) +//clear bit or clear bits #define REG_CLR_BIT(_r, _b) (*(volatile uint32_t*)(_r) &= ~(_b)) +//set bits controll by mask #define REG_SET_BITS(_r, _b, _m) (*(volatile uint32_t*)(_r) = (*(volatile uint32_t*)(_r) & ~(_m)) | ((_b) & (_m))) + #define VALUE_GET_FIELD(_r, _f) (((_r) >> (_f##_S)) & (_f)) #define VALUE_GET_FIELD2(_r, _f) (((_r) & (_f))>> (_f##_S)) #define VALUE_SET_FIELD(_r, _f, _v) ((_r)=(((_r) & ~((_f) << (_f##_S)))|((_v)<<(_f##_S)))) @@ -86,70 +91,25 @@ //}} //Periheral Clock {{ -#define APB_CLK_FREQ_ROM 13*1000000 +#define APB_CLK_FREQ_ROM 26*1000000 #define CPU_CLK_FREQ_ROM APB_CLK_FREQ_ROM #define CPU_CLK_FREQ APB_CLK_FREQ #define APB_CLK_FREQ 80*1000000 //unit: Hz #define UART_CLK_FREQ APB_CLK_FREQ -//#define WDT_CLK_FREQ APB_CLK_FREQ +#define WDT_CLK_FREQ APB_CLK_FREQ #define TIMER_CLK_FREQ (80000000>>4) //80MHz divided by 16 #define SPI_CLK_DIV 4 -//#define RTC_CLK_FREQ 32768 //unit:Hz -//#define RTC_CLK_FREQ 100000 //unit:Hz -//#define CALIB_CLK_MHZ 40 -#define TICKS_PER_US 13 // CPU is 80MHz +#define TICKS_PER_US_ROM 26 // CPU is 80MHz //}} -#if 0 -//Peripheral device base address define{{ -#define DR_REG_DPORT_BASE 0x3ff00000 -#define DR_REG_UART_BASE 0x60000000 -#define DR_REG_SPI1_BASE 0x60002000 //no -#define DR_REG_SPI0_BASE 0x60003000 //no -#define DR_REG_GPIO_BASE 0x60004000 //no -#define DR_REG_FE2_BASE 0x60005000 -#define DR_REG_FE_BASE 0x60006000 -#define DR_REG_TIMER_BASE 0x60007000 //no -#define DR_REG_RTCCNTL_BASE 0x60008000 -#define DR_REG_RTCIO_BASE 0x60008400 - -#define DR_REG_RTCMEM0_BASE 0x60021000 -#define DR_REG_RTCMEM1_BASE 0x60022000 -#define DR_REG_RTCMEM2_BASE 0x60023000 - -#define DR_REG_IO_MUX_BASE 0x60009000 //no -#define DR_REG_WDG_BASE 0x6000A000 //no -#define DR_REG_HINF_BASE 0x6000B000 //no -#define DR_REG_UHCI1_BASE 0x6000C000 -//#define DR_REG_MISC_BASE 0x6000D000 //no use -#define DR_REG_I2C_BASE 0x6000E000 //no -#define DR_REG_I2S_BASE 0x6000F000 -#define DR_REG_UART1_BASE 0x60010000 -#define DR_REG_BT_BASE 0x60011000 -//#define DR_REG_BT_BUFFER_BASE 0x60012000 //no use -#define DR_REG_I2C_EXT_BASE 0x60013000 //no -#define DR_REG_UHCI0_BASE 0x60014000 -#define DR_REG_SLCHOST_BASE 0x60015000 -#define DR_REG_RMT_BASE 0x60016000 -#define DR_REG_PCNT_BASE 0x60017000 -#define DR_REG_SLC_BASE 0x60018000 -#define DR_REG_LEDC_BASE 0x60019000 -#define DR_REG_EFUSE_BASE 0x6001A000 -#define DR_REG_SPI_ENCRYPT_BASE 0x6001B000 -#define DR_REG_PWM_BASE 0x6001C000 //no -#define DR_REG_TIMERGROUP_BASE 0x6001D000 //no -#define DR_REG_TIMERGROUP1_BASE 0x6001E000 //no -#define DR_REG_BB_BASE 0x6001F000 -#define DR_REG_GPIO_SD_BASE 0x60004f00 -#else #define DR_REG_DPORT_BASE 0x3ff00000 #define DR_REG_UART_BASE 0x3ff40000 -#define DR_REG_SPI1_BASE 0x3ff42000 //no -#define DR_REG_SPI0_BASE 0x3ff43000 //no -#define DR_REG_GPIO_BASE 0x3ff44000 //no +#define DR_REG_SPI1_BASE 0x3ff42000 +#define DR_REG_SPI0_BASE 0x3ff43000 +#define DR_REG_GPIO_BASE 0x3ff44000 #define DR_REG_FE2_BASE 0x3ff45000 #define DR_REG_FE_BASE 0x3ff46000 -#define DR_REG_TIMER_BASE 0x3ff47000 //no +#define DR_REG_TIMER_BASE 0x3ff47000 #define DR_REG_RTCCNTL_BASE 0x3ff48000 #define DR_REG_RTCIO_BASE 0x3ff48400 @@ -157,18 +117,16 @@ #define DR_REG_RTCMEM1_BASE 0x3ff62000 #define DR_REG_RTCMEM2_BASE 0x3ff63000 -#define DR_REG_IO_MUX_BASE 0x3ff49000 //no -#define DR_REG_WDG_BASE 0x3ff4A000 //no -#define DR_REG_HINF_BASE 0x3ff4B000 //no +#define DR_REG_IO_MUX_BASE 0x3ff49000 +#define DR_REG_WDG_BASE 0x3ff4A000 +#define DR_REG_HINF_BASE 0x3ff4B000 #define DR_REG_UHCI1_BASE 0x3ff4C000 -//#define DR_REG_MISC_BASE 0x6000D000 //no use -#define DR_REG_I2C_BASE 0x3ff4E000 //no +#define DR_REG_I2C_BASE 0x3ff4E000 #define DR_REG_I2S_BASE 0x3ff4F000 #define DR_REG_I2S1_BASE 0x3ff6D000 #define DR_REG_UART1_BASE 0x3ff50000 #define DR_REG_BT_BASE 0x3ff51000 -//#define DR_REG_BT_BUFFER_BASE 0x60012000 //no use -#define DR_REG_I2C_EXT_BASE 0x3ff53000 //no +#define DR_REG_I2C_EXT_BASE 0x3ff53000 #define DR_REG_UHCI0_BASE 0x3ff54000 #define DR_REG_SLCHOST_BASE 0x3ff55000 #define DR_REG_RMT_BASE 0x3ff56000 @@ -177,94 +135,139 @@ #define DR_REG_LEDC_BASE 0x3ff59000 #define DR_REG_EFUSE_BASE 0x3ff5A000 #define DR_REG_SPI_ENCRYPT_BASE 0x3ff5B000 -#define DR_REG_PWM_BASE 0x3ff5C000 //no -#define DR_REG_TIMERS_BASE 0x3ff5F000 //no -#define DR_REG_TIMERGROUP1_BASE 0x3ff5E000 //no -#define DR_REG_BB_BASE 0x3ff5F000 +#define DR_REG_BB_BASE 0x3ff5C000 +#define DR_REG_PWM_BASE 0x3ff5E000 +#define DR_REG_TIMERS_BASE(i) (0x3ff5F000 + i * (0x1000)) #define DR_REG_GPIO_SD_BASE 0x3ff44f00 -#endif //}} #define REG_SPI_BASE(i) (DR_REG_SPI0_BASE - i*(0x1000)) #define PERIPHS_TIMER_BASEDDR DR_REG_TIMER_BASE #define PERIPHS_SPI_ENCRYPT_BASEADDR DR_REG_SPI_ENCRYPT_BASE -#define UART0_UNHOLD_MASK 0x3 -#define UART1_UNHOLD_MASK 0x60 -#define SDIO_UNHOLD_MASK 0xfc -#define SPI_UNHOLD_MASK 0xfc +//Interrupt hardware source table +//This table is decided by hardware, don't touch this. +#define ETS_WIFI_MAC_INTR_SOURCE 0/**< interrupt of WiFi MAC, level*/ +#define ETS_WIFI_MAC_NMI_SOURCE 1/**< interrupt of WiFi MAC, NMI, use if MAC have bug to fix in NMI*/ +#define ETS_WIFI_BB_INTR_SOURCE 2/**< interrupt of WiFi BB, level, we can do some calibartion*/ +#define ETS_BT_MAC_INTR_SOURCE 3/**< will be cancelled*/ +#define ETS_BT_BB_INTR_SOURCE 4/**< interrupt of BT BB, level*/ +#define ETS_BT_BB_NMI_SOURCE 5/**< interrupt of BT BB, NMI, use if BB have bug to fix in NMI*/ +#define ETS_RWBT_INTR_SOURCE 6/**< interrupt of RWBT, level*/ +#define ETS_RWBLE_INTR_SOURCE 7/**< interrupt of RWBLE, level*/ +#define ETS_RWBT_NMI_SOURCE 8/**< interrupt of RWBT, NMI, use if RWBT have bug to fix in NMI*/ +#define ETS_RWBLE_NMI_SOURCE 9/**< interrupt of RWBLE, NMI, use if RWBT have bug to fix in NMI*/ +#define ETS_SLC0_INTR_SOURCE 10/**< interrupt of SLC0, level*/ +#define ETS_SLC1_INTR_SOURCE 11/**< interrupt of SLC1, level*/ +#define ETS_UHCI0_INTR_SOURCE 12/**< interrupt of UHCI0, level*/ +#define ETS_UHCI1_INTR_SOURCE 13/**< interrupt of UHCI1, level*/ +#define ETS_TG0_T0_LEVEL_INTR_SOURCE 14/**< interrupt of TIMER_GROUP0, TIMER0, level, we would like use EDGE for timer if permission*/ +#define ETS_TG0_T1_LEVEL_INTR_SOURCE 15/**< interrupt of TIMER_GROUP0, TIMER1, level, we would like use EDGE for timer if permission*/ +#define ETS_TG0_WDT_LEVEL_INTR_SOURCE 16/**< interrupt of TIMER_GROUP0, WATCHDOG, level*/ +#define ETS_TG0_LACT_LEVEL_INTR_SOURCE 17/**< interrupt of TIMER_GROUP0, LACT, level*/ +#define ETS_TG1_T0_LEVEL_INTR_SOURCE 18/**< interrupt of TIMER_GROUP1, TIMER0, level, we would like use EDGE for timer if permission*/ +#define ETS_TG1_T1_LEVEL_INTR_SOURCE 19/**< interrupt of TIMER_GROUP1, TIMER1, level, we would like use EDGE for timer if permission*/ +#define ETS_TG1_WDT_LEVEL_INTR_SOURCE 20/**< interrupt of TIMER_GROUP1, WATCHDOG, level*/ +#define ETS_TG1_LACT_LEVEL_INTR_SOURCE 21/**< interrupt of TIMER_GROUP1, LACT, level*/ +#define ETS_GPIO_INTR_SOURCE 22/**< interrupt of GPIO, level*/ +#define ETS_GPIO_NMI_SOURCE 23/**< interrupt of GPIO, NMI*/ +#define ETS_FROM_CPU_INTR0_SOURCE 24/**< interrupt0 generated from a CPU, level*/ +#define ETS_FROM_CPU_INTR1_SOURCE 25/**< interrupt1 generated from a CPU, level*/ +#define ETS_FROM_CPU_INTR2_SOURCE 26/**< interrupt2 generated from a CPU, level*/ +#define ETS_FROM_CPU_INTR3_SOURCE 27/**< interrupt3 generated from a CPU, level*/ +#define ETS_SPI0_INTR_SOURCE 28/**< interrupt of SPI0, level, SPI0 is for Cache Access, do not use this*/ +#define ETS_SPI1_INTR_SOURCE 29/**< interrupt of SPI1, level, SPI1 is for flash read/write, do not use this*/ +#define ETS_SPI2_INTR_SOURCE 30/**< interrupt of SPI2, level*/ +#define ETS_SPI3_INTR_SOURCE 31/**< interrupt of SPI3, level*/ +#define ETS_I2S0_INTR_SOURCE 32/**< interrupt of I2S0, level*/ +#define ETS_I2S1_INTR_SOURCE 33/**< interrupt of I2S1, level*/ +#define ETS_UART0_INTR_SOURCE 34/**< interrupt of UART0, level*/ +#define ETS_UART1_INTR_SOURCE 35/**< interrupt of UART1, level*/ +#define ETS_UART2_INTR_SOURCE 36/**< interrupt of UART2, level*/ +#define ETS_SDIO_HOST_INTR_SOURCE 37/**< interrupt of SD/SDIO/MMC HOST, level*/ +#define ETS_ETH_MAC_INTR_SOURCE 38/**< interrupt of ethernet mac, level*/ +#define ETS_PWM0_INTR_SOURCE 39/**< interrupt of PWM0, level, Reserved*/ +#define ETS_PWM1_INTR_SOURCE 40/**< interrupt of PWM1, level, Reserved*/ +#define ETS_PWM2_INTR_SOURCE 41/**< interrupt of PWM2, level*/ +#define ETS_PWM3_INTR_SOURCE 42/**< interruot of PWM3, level*/ +#define ETS_LEDC_INTR_SOURCE 43/**< interrupt of LED PWM, level*/ +#define ETS_EFUSE_INTR_SOURCE 44/**< interrupt of efuse, level, not likely to use*/ +#define ETS_CAN_INTR_SOURCE 45/**< interrupt of can, level*/ +#define ETS_RTC_CORE_INTR_SOURCE 46/**< interrupt of rtc core, level, include rtc watchdog*/ +#define ETS_RMT_INTR_SOURCE 47/**< interrupt of remote controller, level*/ +#define ETS_PCNT_INTR_SOURCE 48/**< interrupt of pluse count, level*/ +#define ETS_I2C_EXT0_INTR_SOURCE 49/**< interrupt of I2C controller1, level*/ +#define ETS_I2C_EXT1_INTR_SOURCE 50/**< interrupt of I2C controller0, level*/ +#define ETS_RSA_INTR_SOURCE 51/**< interrupt of RSA accelerator, level*/ +#define ETS_SPI1_DMA_INTR_SOURCE 52/**< interrupt of SPI1 DMA, SPI1 is for flash read/write, do not use this*/ +#define ETS_SPI2_DMA_INTR_SOURCE 53/**< interrupt of SPI2 DMA, level*/ +#define ETS_SPI3_DMA_INTR_SOURCE 54/**< interrupt of SPI3 DMA, level*/ +#define ETS_WDT_INTR_SOURCE 55/**< will be cancelled*/ +#define ETS_TIMER1_INTR_SOURCE 56/**< will be cancelled*/ +#define ETS_TIMER2_INTR_SOURCE 57/**< will be cancelled*/ +#define ETS_TG0_T0_EDGE_INTR_SOURCE 58/**< interrupt of TIMER_GROUP0, TIMER0, EDGE*/ +#define ETS_TG0_T1_EDGE_INTR_SOURCE 59/**< interrupt of TIMER_GROUP0, TIMER1, EDGE*/ +#define ETS_TG0_WDT_EDGE_INTR_SOURCE 60/**< interrupt of TIMER_GROUP0, WATCH DOG, EDGE*/ +#define ETS_TG0_LACT_EDGE_INTR_SOURCE 61/**< interrupt of TIMER_GROUP0, LACT, EDGE*/ +#define ETS_TG1_T0_EDGE_INTR_SOURCE 62/**< interrupt of TIMER_GROUP1, TIMER0, EDGE*/ +#define ETS_TG1_T1_EDGE_INTR_SOURCE 63/**< interrupt of TIMER_GROUP1, TIMER1, EDGE*/ +#define ETS_TG1_WDT_EDGE_INTR_SOURCE 64/**< interrupt of TIMER_GROUP1, WATCHDOG, EDGE*/ +#define ETS_TG1_LACT_EDGE_INTR_SOURCE 65/**< interrupt of TIMER_GROUP0, LACT, EDGE*/ +#define ETS_MMU_IA_INTR_SOURCE 66/**< interrupt of MMU Invalid Access, LEVEL*/ +#define ETS_MPU_IA_INTR_SOURCE 67/**< interrupt of MPU Invalid Access, LEVEL*/ +#define ETS_CACHE_IA_INTR_SOURCE 68/**< interrupt of Cache Invalied Access, LEVEL*/ -// TIMER reg {{ -#define TIMER_REG_READ(addr) READ_PERI_REG(addr) -#define TIMER_REG_WRITE(addr, val) WRITE_PERI_REG(addr, val) -#define TIMER_SET_REG_MASK(reg, mask) WRITE_PERI_REG(reg, (READ_PERI_REG(reg)|(mask))) -/* Returns the current time according to the timer timer. */ -#define NOW() TIMER_REG_READ(FRC2_COUNT_ADDRESS) -//load initial_value to timer1 -#define FRC1_LOAD_ADDRESS (PERIPHS_TIMER_BASEDDR +0x00) -#define FRC1_LOAD_DATA_MSB 22 -#define FRC1_LOAD_DATA_LSB 0 -#define FRC1_LOAD_DATA_MASK 0x007fffff +//interrupt cpu using table, Please see the core-isa.h +/************************************************************************************************************* + * Intr num Level Type PRO CPU usage APP CPU uasge + * 0 1 extern level WMAC Reserved + * 1 1 extern level BT/BLE Host Reserved + * 2 1 extern level FROM_CPU FROM_CPU + * 3 1 extern level TG0_WDT Reserved + * 4 1 extern level WBB + * 5 1 extern level Reserved + * 6 1 timer FreeRTOS Tick(L1) FreeRTOS Tick(L1) + * 7 1 software Reserved Reserved + * 8 1 extern level Reserved + * 9 1 extern level + * 10 1 extern edge Internal Timer + * 11 3 profiling + * 12 1 extern level + * 13 1 extern level + * 14 7 nmi Reserved Reserved + * 15 3 timer FreeRTOS Tick(L3) FreeRTOS Tick(L3) + * 16 5 timer + * 17 1 extern level + * 18 1 extern level + * 19 2 extern level + * 20 2 extern level + * 21 2 extern level + * 22 3 extern edge + * 23 3 extern level + * 24 4 extern level + * 25 4 extern level Reserved Reserved + * 26 5 extern level Reserved Reserved + * 27 3 extern level Reserved Reserved + * 28 4 extern edge + * 29 3 software Reserved Reserved + * 30 4 extern edge Reserved Reserved + * 31 5 extern level Reserved Reserved + ************************************************************************************************************* + */ -//timer1's counter value(count from initial_value to 0) -#define FRC1_COUNT_ADDRESS (PERIPHS_TIMER_BASEDDR +0x04) -#define FRC1_COUNT_DATA_MSB 22 -#define FRC1_COUNT_DATA_LSB 0 -#define FRC1_COUNT_DATA_MASK 0x007fffff +//CPU0 Interrupt number reserved, not touch this. +#define ETS_WMAC_INUM 0 +#define ETS_BT_HOST_INUM 1 +#define ETS_FROM_CPU_INUM 2 +#define ETS_T0_WDT_INUM 3 +#define ETS_WBB_INUM 4 +#define ETS_TG0_T1_INUM 10 /**< use edge interrupt*/ -#define FRC1_CTRL_ADDRESS (PERIPHS_TIMER_BASEDDR +0x08) -#define FRC1_CTRL_DATA_MSB 7 -#define FRC1_CTRL_DATA_LSB 0 -#define FRC1_CTRL_DATA_MASK 0x000000ff +//CPU0 Intrrupt number used in ROM, should be cancelled in SDK +#define ETS_SLC_INUM 1 +#define ETS_UART0_INUM 5 +#define ETS_UART1_INUM 5 -//clear timer1's interrupt when write this address -#define FRC1_INT_ADDRESS (PERIPHS_TIMER_BASEDDR +0x0c) -#define FRC1_INT_CLR_MSB 0 -#define FRC1_INT_CLR_LSB 0 -#define FRC1_INT_CLR_MASK 0x00000001 -//only used for simulation -#define FRC1_TEST_ADDRESS (PERIPHS_TIMER_BASEDDR +0x10) -#define FRC1_TEST_MODE_MSB 0 -#define FRC1_TEST_MODE_LSB 0 -#define FRC1_TEST_MODE_MASK 0x00000001 - -//load initial_value to timer2 -#define FRC2_LOAD_ADDRESS (PERIPHS_TIMER_BASEDDR +0x20) -#define FRC2_LOAD_DATA_MSB 31 -#define FRC2_LOAD_DATA_LSB 0 -#define FRC2_LOAD_DATA_MASK 0xffffffff - -//timer2's counter value(count from initial_value to 0) -#define FRC2_COUNT_ADDRESS (PERIPHS_TIMER_BASEDDR +0x24) -#define FRC2_COUNT_DATA_MSB 31 -#define FRC2_COUNT_DATA_LSB 0 -#define FRC2_COUNT_DATA_MASK 0xffffffff - -#define FRC2_CTRL_ADDRESS (PERIPHS_TIMER_BASEDDR +0x28) -#define FRC2_CTRL_DATA_MSB 7 -#define FRC2_CTRL_DATA_LSB 0 -#define FRC2_CTRL_DATA_MASK 0x000000ff - -//clear interrupt when write this address -#define FRC2_INT_ADDRESS (PERIPHS_TIMER_BASEDDR +0x2c) -#define FRC2_INT_CLR_MSB 0 -#define FRC2_INT_CLR_LSB 0 -#define FRC2_INT_CLR_MASK 0x00000001 - -//set Alarm_value for timer2 to generate interrupt -#define FRC2_ALARM_ADDRESS (PERIPHS_TIMER_BASEDDR +0x30) -#define FRC2_ALARM_DATA_MSB 31 -#define FRC2_ALARM_DATA_LSB 0 -#define FRC2_ALARM_DATA_MASK 0xffffffff -// }} - -#define SPI_ENCRYPT_CNTL (PERIPHS_SPI_ENCRYPT_BASEADDR + 0x20) -#define SPI_ENCRYPT_CNTL_ENA BIT(0) - -#define SPI_ENCRYPT_ADDR (PERIPHS_SPI_ENCRYPT_BASEADDR + 0x24) - -#define SPI_ENCRYPT_CHECKDONE (PERIPHS_SPI_ENCRYPT_BASEADDR + 0x28) -#define SPI_ENCRYPT_CHECKDONE_STATUS BIT(0) #endif /* _ESP32_SOC_H_ */ diff --git a/components/esp32/include/soc/timers_reg.h b/components/esp32/include/soc/timers_reg.h index 577f375aa7..21ddfafcb6 100644 --- a/components/esp32/include/soc/timers_reg.h +++ b/components/esp32/include/soc/timers_reg.h @@ -16,7 +16,7 @@ #include "soc.h" -#define T0CONFIG (DR_REG_TIMERS_BASE + 0x0000) +#define T0CONFIG(i) (DR_REG_TIMERS_BASE(i) + 0x0000) #define TIMERS_T0_EN (BIT(31)) #define TIMERS_T0_EN_S 31 #define TIMERS_T0_INCREASE (BIT(30)) @@ -32,39 +32,39 @@ #define TIMERS_T0_ALARM_EN (BIT(10)) #define TIMERS_T0_ALARM_EN_S 10 -#define T0LO (DR_REG_TIMERS_BASE + 0x0004) +#define T0LO(i) (DR_REG_TIMERS_BASE(i) + 0x0004) #define TIMERS_T0_LO 0xFFFFFFFF #define TIMERS_T0_LO_S 0 -#define T0HI (DR_REG_TIMERS_BASE + 0x0008) +#define T0HI(i) (DR_REG_TIMERS_BASE(i) + 0x0008) #define TIMERS_T0_HI 0xFFFFFFFF #define TIMERS_T0_HI_S 0 -#define T0UPDATE (DR_REG_TIMERS_BASE + 0x000c) +#define T0UPDATE(i) (DR_REG_TIMERS_BASE(i) + 0x000c) #define TIMERS_T0_UPDATE 0xFFFFFFFF #define TIMERS_T0_UPDATE_S 0 -#define T0ALARMLO (DR_REG_TIMERS_BASE + 0x0010) +#define T0ALARMLO(i) (DR_REG_TIMERS_BASE(i) + 0x0010) #define TIMERS_T0_ALARM_LO 0xFFFFFFFF #define TIMERS_T0_ALARM_LO_S 0 -#define T0ALARMHI (DR_REG_TIMERS_BASE + 0x0014) +#define T0ALARMHI(i) (DR_REG_TIMERS_BASE(i) + 0x0014) #define TIMERS_T0_ALARM_HI 0xFFFFFFFF #define TIMERS_T0_ALARM_HI_S 0 -#define T0LOADLO (DR_REG_TIMERS_BASE + 0x0018) +#define T0LOADLO(i) (DR_REG_TIMERS_BASE(i) + 0x0018) #define TIMERS_T0_LOAD_LO 0xFFFFFFFF #define TIMERS_T0_LOAD_LO_S 0 -#define T0LOADHI (DR_REG_TIMERS_BASE + 0x001c) +#define T0LOADHI(i) (DR_REG_TIMERS_BASE(i) + 0x001c) #define TIMERS_T0_LOAD_HI 0xFFFFFFFF #define TIMERS_T0_LOAD_HI_S 0 -#define T0LOAD (DR_REG_TIMERS_BASE + 0x0020) +#define T0LOAD(i) (DR_REG_TIMERS_BASE(i) + 0x0020) #define TIMERS_T0_LOAD 0xFFFFFFFF #define TIMERS_T0_LOAD_S 0 -#define T1CONFIG (DR_REG_TIMERS_BASE + 0x0024) +#define T1CONFIG(i) (DR_REG_TIMERS_BASE(i) + 0x0024) #define TIMERS_T1_EN (BIT(31)) #define TIMERS_T1_EN_S 31 #define TIMERS_T1_INCREASE (BIT(30)) @@ -80,39 +80,39 @@ #define TIMERS_T1_ALARM_EN (BIT(10)) #define TIMERS_T1_ALARM_EN_S 10 -#define T1LO (DR_REG_TIMERS_BASE + 0x0028) +#define T1LO(i) (DR_REG_TIMERS_BASE(i) + 0x0028) #define TIMERS_T1_LO 0xFFFFFFFF #define TIMERS_T1_LO_S 0 -#define T1HI (DR_REG_TIMERS_BASE + 0x002c) +#define T1HI(i) (DR_REG_TIMERS_BASE(i) + 0x002c) #define TIMERS_T1_HI 0xFFFFFFFF #define TIMERS_T1_HI_S 0 -#define T1UPDATE (DR_REG_TIMERS_BASE + 0x0030) +#define T1UPDATE(i) (DR_REG_TIMERS_BASE(i) + 0x0030) #define TIMERS_T1_UPDATE 0xFFFFFFFF #define TIMERS_T1_UPDATE_S 0 -#define T1ALARMLO (DR_REG_TIMERS_BASE + 0x0034) +#define T1ALARMLO(i) (DR_REG_TIMERS_BASE(i) + 0x0034) #define TIMERS_T1_ALARM_LO 0xFFFFFFFF #define TIMERS_T1_ALARM_LO_S 0 -#define T1ALARMHI (DR_REG_TIMERS_BASE + 0x0038) +#define T1ALARMHI(i) (DR_REG_TIMERS_BASE(i) + 0x0038) #define TIMERS_T1_ALARM_HI 0xFFFFFFFF #define TIMERS_T1_ALARM_HI_S 0 -#define T1LOADLO (DR_REG_TIMERS_BASE + 0x003c) +#define T1LOADLO(i) (DR_REG_TIMERS_BASE(i) + 0x003c) #define TIMERS_T1_LOAD_LO 0xFFFFFFFF #define TIMERS_T1_LOAD_LO_S 0 -#define T1LOADHI (DR_REG_TIMERS_BASE + 0x0040) +#define T1LOADHI(i) (DR_REG_TIMERS_BASE(i) + 0x0040) #define TIMERS_T1_LOAD_HI 0xFFFFFFFF #define TIMERS_T1_LOAD_HI_S 0 -#define T1LOAD (DR_REG_TIMERS_BASE + 0x0044) +#define T1LOAD(i) (DR_REG_TIMERS_BASE(i) + 0x0044) #define TIMERS_T1_LOAD 0xFFFFFFFF #define TIMERS_T1_LOAD_S 0 -#define WDTCONFIG0 (DR_REG_TIMERS_BASE + 0x0048) +#define WDTCONFIG0(i) (DR_REG_TIMERS_BASE(i) + 0x0048) #define TIMERS_WDT_EN (BIT(31)) #define TIMERS_WDT_EN_S 31 #define TIMERS_WDT_STG0 0x00000003 @@ -134,35 +134,35 @@ #define TIMERS_WDT_FLASHBOOT_MOD_EN (BIT(14)) #define TIMERS_WDT_FLASHBOOT_MOD_EN_S 14 -#define WDTCONFIG1 (DR_REG_TIMERS_BASE + 0x004c) +#define WDTCONFIG1(i) (DR_REG_TIMERS_BASE(i) + 0x004c) #define TIMERS_WDT_CLK_PRESCALE 0x0000FFFF #define TIMERS_WDT_CLK_PRESCALE_S 16 -#define WDTCONFIG2 (DR_REG_TIMERS_BASE + 0x0050) +#define WDTCONFIG2(i) (DR_REG_TIMERS_BASE(i) + 0x0050) #define TIMERS_WDT_STG0_HOLD 0xFFFFFFFF #define TIMERS_WDT_STG0_HOLD_S 0 -#define WDTCONFIG3 (DR_REG_TIMERS_BASE + 0x0054) +#define WDTCONFIG3(i) (DR_REG_TIMERS_BASE(i) + 0x0054) #define TIMERS_WDT_STG1_HOLD 0xFFFFFFFF #define TIMERS_WDT_STG1_HOLD_S 0 -#define WDTCONFIG4 (DR_REG_TIMERS_BASE + 0x0058) +#define WDTCONFIG4(i) (DR_REG_TIMERS_BASE(i) + 0x0058) #define TIMERS_WDT_STG2_HOLD 0xFFFFFFFF #define TIMERS_WDT_STG2_HOLD_S 0 -#define WDTCONFIG5 (DR_REG_TIMERS_BASE + 0x005c) +#define WDTCONFIG5(i) (DR_REG_TIMERS_BASE(i) + 0x005c) #define TIMERS_WDT_STG3_HOLD 0xFFFFFFFF #define TIMERS_WDT_STG3_HOLD_S 0 -#define WDTFEED (DR_REG_TIMERS_BASE + 0x0060) +#define WDTFEED(i) (DR_REG_TIMERS_BASE(i) + 0x0060) #define TIMERS_WDT_FEED 0xFFFFFFFF #define TIMERS_WDT_FEED_S 0 -#define WDTWPROTECT (DR_REG_TIMERS_BASE + 0x0064) +#define WDTWPROTECT(i) (DR_REG_TIMERS_BASE(i) + 0x0064) #define TIMERS_WDT_WKEY 0xFFFFFFFF #define TIMERS_WDT_WKEY_S 0 -#define RTCCALICFG (DR_REG_TIMERS_BASE + 0x0068) +#define RTCCALICFG(i) (DR_REG_TIMERS_BASE(i) + 0x0068) #define TIMERS_RTC_CALI_START (BIT(31)) #define TIMERS_RTC_CALI_START_S 31 #define TIMERS_RTC_CALI_MAX 0x00007FFF @@ -174,11 +174,11 @@ #define TIMERS_RTC_CALI_START_CYCLING (BIT(12)) #define TIMERS_RTC_CALI_START_CYCLING_S 12 -#define RTCCALICFG1 (DR_REG_TIMERS_BASE + 0x006c) +#define RTCCALICFG1(i) (DR_REG_TIMERS_BASE(i) + 0x006c) #define TIMERS_RTC_CALI_VALUE 0x01FFFFFF #define TIMERS_RTC_CALI_VALUE_S 7 -#define LACTCONFIG (DR_REG_TIMERS_BASE + 0x0070) +#define LACTCONFIG(i) (DR_REG_TIMERS_BASE(i) + 0x0070) #define TIMERS_LACT_EN (BIT(31)) #define TIMERS_LACT_EN_S 31 #define TIMERS_LACT_INCREASE (BIT(30)) @@ -200,43 +200,43 @@ #define TIMERS_LACT_RTC_ONLY (BIT(7)) #define TIMERS_LACT_RTC_ONLY_S 7 -#define LACTRTC (DR_REG_TIMERS_BASE + 0x0074) +#define LACTRTC(i) (DR_REG_TIMERS_BASE(i) + 0x0074) #define TIMERS_LACT_RTC_STEP_LEN 0x03FFFFFF #define TIMERS_LACT_RTC_STEP_LEN_S 6 -#define LACTLO (DR_REG_TIMERS_BASE + 0x0078) +#define LACTLO(i) (DR_REG_TIMERS_BASE(i) + 0x0078) #define TIMERS_LACT_LO 0xFFFFFFFF #define TIMERS_LACT_LO_S 0 -#define LACTHI (DR_REG_TIMERS_BASE + 0x007c) +#define LACTHI(i) (DR_REG_TIMERS_BASE(i) + 0x007c) #define TIMERS_LACT_HI 0xFFFFFFFF #define TIMERS_LACT_HI_S 0 -#define LACTUPDATE (DR_REG_TIMERS_BASE + 0x0080) +#define LACTUPDATE(i) (DR_REG_TIMERS_BASE(i) + 0x0080) #define TIMERS_LACT_UPDATE 0xFFFFFFFF #define TIMERS_LACT_UPDATE_S 0 -#define LACTALARMLO (DR_REG_TIMERS_BASE + 0x0084) +#define LACTALARMLO(i) (DR_REG_TIMERS_BASE(i) + 0x0084) #define TIMERS_LACT_ALARM_LO 0xFFFFFFFF #define TIMERS_LACT_ALARM_LO_S 0 -#define LACTALARMHI (DR_REG_TIMERS_BASE + 0x0088) +#define LACTALARMHI(i) (DR_REG_TIMERS_BASE(i) + 0x0088) #define TIMERS_LACT_ALARM_HI 0xFFFFFFFF #define TIMERS_LACT_ALARM_HI_S 0 -#define LACTLOADLO (DR_REG_TIMERS_BASE + 0x008c) +#define LACTLOADLO(i) (DR_REG_TIMERS_BASE(i) + 0x008c) #define TIMERS_LACT_LOAD_LO 0xFFFFFFFF #define TIMERS_LACT_LOAD_LO_S 0 -#define LACTLOADHI (DR_REG_TIMERS_BASE + 0x0090) +#define LACTLOADHI(i) (DR_REG_TIMERS_BASE(i) + 0x0090) #define TIMERS_LACT_LOAD_HI 0xFFFFFFFF #define TIMERS_LACT_LOAD_HI_S 0 -#define LACTLOAD (DR_REG_TIMERS_BASE + 0x0094) +#define LACTLOAD(i) (DR_REG_TIMERS_BASE(i) + 0x0094) #define TIMERS_LACT_LOAD 0xFFFFFFFF #define TIMERS_LACT_LOAD_S 0 -#define INT_ENA_TIMERS (DR_REG_TIMERS_BASE + 0x0098) +#define INT_ENA_TIMERS(i) (DR_REG_TIMERS_BASE(i) + 0x0098) #define TIMERS_LACT_INT_ENA (BIT(3)) #define TIMERS_LACT_INT_ENA_S 3 #define TIMERS_WDT_INT_ENA (BIT(2)) @@ -246,7 +246,7 @@ #define TIMERS_T0_INT_ENA (BIT(0)) #define TIMERS_T0_INT_ENA_S 0 -#define INT_RAW_TIMERS (DR_REG_TIMERS_BASE + 0x009c) +#define INT_RAW_TIMERS(i) (DR_REG_TIMERS_BASE(i) + 0x009c) #define TIMERS_LACT_INT_RAW (BIT(3)) #define TIMERS_LACT_INT_RAW_S 3 #define TIMERS_WDT_INT_RAW (BIT(2)) @@ -256,7 +256,7 @@ #define TIMERS_T0_INT_RAW (BIT(0)) #define TIMERS_T0_INT_RAW_S 0 -#define INT_ST_TIMERS (DR_REG_TIMERS_BASE + 0x00a0) +#define INT_ST_TIMERS(i) (DR_REG_TIMERS_BASE(i) + 0x00a0) #define TIMERS_LACT_INT_ST (BIT(3)) #define TIMERS_LACT_INT_ST_S 3 #define TIMERS_WDT_INT_ST (BIT(2)) @@ -266,7 +266,7 @@ #define TIMERS_T0_INT_ST (BIT(0)) #define TIMERS_T0_INT_ST_S 0 -#define INT_CLR_TIMERS (DR_REG_TIMERS_BASE + 0x00a4) +#define INT_CLR_TIMERS(i) (DR_REG_TIMERS_BASE(i) + 0x00a4) #define TIMERS_LACT_INT_CLR (BIT(3)) #define TIMERS_LACT_INT_CLR_S 3 #define TIMERS_WDT_INT_CLR (BIT(2)) @@ -276,12 +276,12 @@ #define TIMERS_T0_INT_CLR (BIT(0)) #define TIMERS_T0_INT_CLR_S 0 -#define NTIMERS_DATE (DR_REG_TIMERS_BASE + 0x00f8) +#define NTIMERS_DATE(i) (DR_REG_TIMERS_BASE(i) + 0x00f8) #define TIMERS_NTIMERS_DATE 0x0FFFFFFF #define TIMERS_NTIMERS_DATE_S 0 #define TIMERS_NTIMERS_DATE_VERSION 0x1604290 -#define REGCLK (DR_REG_TIMERS_BASE + 0x00fc) +#define REGCLK(i) (DR_REG_TIMERS_BASE(i) + 0x00fc) #define TIMERS_CLK_EN (BIT(31)) #define TIMERS_CLK_EN_S 31 diff --git a/components/esp32/ld/esp32.rom.ld b/components/esp32/ld/esp32.rom.ld index 3777405fe4..823ca4c6e8 100644 --- a/components/esp32/ld/esp32.rom.ld +++ b/components/esp32/ld/esp32.rom.ld @@ -64,6 +64,8 @@ PROVIDE ( Cache_Read_Disable = 0x40009ab8 ); PROVIDE ( Cache_Read_Enable = 0x40009a84 ); PROVIDE ( Cache_Read_Init = 0x40009950 ); PROVIDE ( cache_sram_mmu_set = 0x400097f4 ); +/* This is static function, but can be used, not generated by script*/ +PROVIDE ( calc_rtc_memory_crc = 0x40008170 ); PROVIDE ( calloc = 0x4000bee4 ); PROVIDE ( _calloc_r = 0x4000bbf8 ); PROVIDE ( check_pos = 0x400068b8 ); @@ -1585,12 +1587,20 @@ PROVIDE ( SPIParamCfg = 0x40063238 ); PROVIDE ( SPI_Prepare_Encrypt_Data = 0x40062e1c ); PROVIDE ( SPIRead = 0x40062ed8 ); PROVIDE ( SPIReadModeCnfig = 0x40062944 ); +/* This is static function, but can be used, not generated by script*/ +PROVIDE ( SPI_read_status = 0x4006226c ); +/* This is static function, but can be used, not generated by script*/ +PROVIDE ( SPI_read_status_high = 0x40062448 ); PROVIDE ( SPIUnlock = 0x400628b0 ); PROVIDE ( SPI_user_command_read = 0x400621b0 ); PROVIDE ( spi_w25q16 = 0x3ffae270 ); PROVIDE ( SPIWrite = 0x40062d50 ); +/* This is static function, but can be used, not generated by script*/ +PROVIDE ( SPI_write_enable = 0x40062320 ); PROVIDE ( SPI_Write_Encrypt_Disable = 0x40062e60 ); PROVIDE ( SPI_Write_Encrypt_Enable = 0x40062df4 ); +/* This is static function, but can be used, not generated by script*/ +PROVIDE ( SPI_write_status = 0x400622f0 ); PROVIDE ( sprintf = 0x40056c08 ); PROVIDE ( _sprintf_r = 0x40056bbc ); PROVIDE ( __sprint_r = 0x400577e4 ); @@ -1826,4 +1836,4 @@ PROVIDE ( _xtos_unhandled_exception = 0x4000c024 ); PROVIDE ( _xtos_unhandled_interrupt = 0x4000c01c ); PROVIDE ( _xtos_vpri_enabled = 0x3ffe0654 ); -PROVIDE ( I2S0 = 0x6000F000 ); \ No newline at end of file +PROVIDE ( I2S0 = 0x6000F000 ); From 04b53643efbe5947defeb2f4430bcc109e138e45 Mon Sep 17 00:00:00 2001 From: Wu Jian Gang Date: Mon, 5 Sep 2016 16:20:26 +0800 Subject: [PATCH 31/51] header files: clean up 1. format; 2. Slow RTC memory reverse 2KB; --- components/esp32/include/rom/aes.h | 5 +- components/esp32/include/rom/bigint.h | 1 + components/esp32/include/rom/cache.h | 6 +- components/esp32/include/rom/crc.h | 31 ++--- components/esp32/include/rom/efuse.h | 21 ++-- components/esp32/include/rom/ets_sys.h | 68 +++++------ components/esp32/include/rom/gpio.h | 109 +++++++++-------- components/esp32/include/rom/rtc.h | 10 +- components/esp32/include/rom/secure_boot.h | 1 + components/esp32/include/rom/spi_flash.h | 132 ++++++++++----------- components/esp32/include/rom/uart.h | 62 +++++----- components/esp32/include/soc/io_mux_reg.h | 2 +- 12 files changed, 223 insertions(+), 225 deletions(-) mode change 100755 => 100644 components/esp32/include/rom/uart.h diff --git a/components/esp32/include/rom/aes.h b/components/esp32/include/rom/aes.h index 950ce2e4af..d81d8f6f9b 100644 --- a/components/esp32/include/rom/aes.h +++ b/components/esp32/include/rom/aes.h @@ -11,6 +11,7 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. + #ifndef _ROM_AES_H_ #define _ROM_AES_H_ @@ -33,8 +34,8 @@ void ets_aes_enable(void); void ets_aes_disable(void); void ets_aes_set_endian(bool key_word_swap, bool key_byte_swap, - bool in_word_swap, bool in_byte_swap, - bool out_word_swap, bool out_byte_swap); + bool in_word_swap, bool in_byte_swap, + bool out_word_swap, bool out_byte_swap); bool ets_aes_setkey_enc(const uint8_t *key, enum AES_BITS bits); diff --git a/components/esp32/include/rom/bigint.h b/components/esp32/include/rom/bigint.h index 2a6c2b82a1..ab4246c6da 100644 --- a/components/esp32/include/rom/bigint.h +++ b/components/esp32/include/rom/bigint.h @@ -11,6 +11,7 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. + #ifndef _ROM_BIGINT_H_ #define _ROM_BIGINT_H_ diff --git a/components/esp32/include/rom/cache.h b/components/esp32/include/rom/cache.h index d5df8d1a6c..fb84bca03c 100644 --- a/components/esp32/include/rom/cache.h +++ b/components/esp32/include/rom/cache.h @@ -11,6 +11,7 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. + #ifndef _ROM_CACHE_H_ #define _ROM_CACHE_H_ @@ -44,7 +45,7 @@ void mmu_init(int cpu_no); * * @param int pod : process identifier. Range 0~7. * - * @param unsigned int vaddr : virtual address in CPU address space. + * @param unsigned int vaddr : virtual address in CPU address space. * Can be IRam0, IRam1, IRom0 and DRom0 memory address. * Should be aligned by psize. * @@ -73,7 +74,7 @@ unsigned int cache_flash_mmu_set(int cpu_no, int pid, unsigned int vaddr, unsign * * @param int pod : process identifier. Range 0~7. * - * @param unsigned int vaddr : virtual address in CPU address space. + * @param unsigned int vaddr : virtual address in CPU address space. * Can be IRam0, IRam1, IRom0 and DRom0 memory address. * Should be aligned by psize. * @@ -92,7 +93,6 @@ unsigned int cache_flash_mmu_set(int cpu_no, int pid, unsigned int vaddr, unsign * 4 : mmu table to be written is out of range * 5 : vaddr is out of range */ - unsigned int cache_sram_mmu_set(int cpu_no, int pid, unsigned int vaddr, unsigned int paddr, int psize, int num); /** diff --git a/components/esp32/include/rom/crc.h b/components/esp32/include/rom/crc.h index 509f22cd0b..84e17882de 100644 --- a/components/esp32/include/rom/crc.h +++ b/components/esp32/include/rom/crc.h @@ -11,9 +11,12 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. + #ifndef ROM_CRC_H #define ROM_CRC_H +#include + #ifdef __cplusplus extern "C" { #endif @@ -28,9 +31,9 @@ extern "C" { /* Standard CRC8/16/32 algorithms. */ -// CRC-8 x8+x2+x1+1 0x07 +// CRC-8 x8+x2+x1+1 0x07 // CRC16-CCITT x16+x12+x5+1 1021 ISO HDLC, ITU X.25, V.34/V.41/V.42, PPP-FCS -// CRC32: +// CRC32: //G(x) = x32 +x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x1 + 1 //If your buf is not continuous, you can use the first result to be the second parameter. @@ -39,78 +42,78 @@ extern "C" { * * @param uint32_t crc : init crc value, use 0 at the first use. * - * @param uint8_t const * buf : buffer to start calculate crc. + * @param uint8_t const *buf : buffer to start calculate crc. * * @param uint32_t len : buffer length in byte. * * @return None */ -uint32_t crc32_le(uint32_t crc, uint8_t const * buf, uint32_t len); +uint32_t crc32_le(uint32_t crc, uint8_t const *buf, uint32_t len); /** * @brief Crc32 value that is in big endian. * * @param uint32_t crc : init crc value, use 0 at the first use. * - * @param uint8_t const * buf : buffer to start calculate crc. + * @param uint8_t const *buf : buffer to start calculate crc. * * @param uint32_t len : buffer length in byte. * * @return None */ -uint32_t crc32_be(uint32_t crc, uint8_t const * buf, uint32_t len); +uint32_t crc32_be(uint32_t crc, uint8_t const *buf, uint32_t len); /** * @brief Crc16 value that is in little endian. * * @param uint16_t crc : init crc value, use 0 at the first use. * - * @param uint8_t const * buf : buffer to start calculate crc. + * @param uint8_t const *buf : buffer to start calculate crc. * * @param uint32_t len : buffer length in byte. * * @return None */ -uint16_t crc16_le(uint16_t crc, uint8_t const * buf, uint32_t len); +uint16_t crc16_le(uint16_t crc, uint8_t const *buf, uint32_t len); /** * @brief Crc16 value that is in big endian. * * @param uint16_t crc : init crc value, use 0 at the first use. * - * @param uint8_t const * buf : buffer to start calculate crc. + * @param uint8_t const *buf : buffer to start calculate crc. * * @param uint32_t len : buffer length in byte. * * @return None */ -uint16_t crc16_be(uint16_t crc, uint8_t const * buf, uint32_t len); +uint16_t crc16_be(uint16_t crc, uint8_t const *buf, uint32_t len); /** * @brief Crc8 value that is in little endian. * * @param uint8_t crc : init crc value, use 0 at the first use. * - * @param uint8_t const * buf : buffer to start calculate crc. + * @param uint8_t const *buf : buffer to start calculate crc. * * @param uint32_t len : buffer length in byte. * * @return None */ -uint8_t crc8_le(uint8_t crc, uint8_t const * buf, uint32_t len); +uint8_t crc8_le(uint8_t crc, uint8_t const *buf, uint32_t len); /** * @brief Crc8 value that is in big endian. * * @param uint32_t crc : init crc value, use 0 at the first use. * - * @param uint8_t const * buf : buffer to start calculate crc. + * @param uint8_t const *buf : buffer to start calculate crc. * * @param uint32_t len : buffer length in byte. * * @return None */ -uint8_t crc8_be(uint8_t crc, uint8_t const * buf, uint32_t len); +uint8_t crc8_be(uint8_t crc, uint8_t const *buf, uint32_t len); /** * @} diff --git a/components/esp32/include/rom/efuse.h b/components/esp32/include/rom/efuse.h index 0fa6fb9a40..62692c3098 100644 --- a/components/esp32/include/rom/efuse.h +++ b/components/esp32/include/rom/efuse.h @@ -11,17 +11,20 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. + #ifndef _ROM_EFUSE_H_ #define _ROM_EFUSE_H_ +#include + #ifdef __cplusplus extern "C" { #endif /** \defgroup efuse_APIs efuse APIs * @brief ESP32 efuse read/write APIs - * @attention - * + * @attention + * */ /** @addtogroup efuse_APIs @@ -35,7 +38,7 @@ extern "C" { * * @return null */ -void ets_efuse_read_op(viid); +void ets_efuse_read_op(void); /** * @brief Do a efuse write operation, to update efuse write registers to efuse, then you need call ets_efuse_read_op again. @@ -54,35 +57,33 @@ void ets_efuse_program_op(void); * * @return u32: 1 for 100KHZ. */ -u32 ets_efuse_get_8M_clock(void); +uint32_t ets_efuse_get_8M_clock(void); /** * @brief Read spi pad configuration, show gpio number of flash pad, includes 5 pads. * * @param null * - * @return uint32_t: 0, invalid, flash pad decided by strapping - * else, bit[5:0] spiclk, bit[11:6] spiq, bit[17:12] spid, bit[23:18] spics0, bit[29:24] spihd + * @return uint32_t: 0, invalid, flash pad decided by strapping + * else, bit[5:0] spiclk, bit[11:6] spiq, bit[17:12] spid, bit[23:18] spics0, bit[29:24] spihd */ - uint32_t ets_efuse_get_spiconfig(void); /** * @brief A crc8 algorithm used in efuse check. * - * @param unsigned char const * p : Pointer to original data. + * @param unsigned char const *p : Pointer to original data. * * @param unsigned int len : Data length in byte. * * @return unsigned char: Crc value. */ -unsigned char esp_crc8(unsigned char const * p, unsigned int len); +unsigned char esp_crc8(unsigned char const *p, unsigned int len); /** * @} */ - #ifdef __cplusplus } #endif diff --git a/components/esp32/include/rom/ets_sys.h b/components/esp32/include/rom/ets_sys.h index 04915c1b24..c412c9b41f 100644 --- a/components/esp32/include/rom/ets_sys.h +++ b/components/esp32/include/rom/ets_sys.h @@ -36,10 +36,10 @@ extern "C" { * NOTE * Many functions in this header files can't be run in FreeRTOS. * Please see the comment of the Functions. - * There are also some functions that doesn't work on FreeRTOS + * There are also some functions that doesn't work on FreeRTOS * without listed in the header, such as: * xtos functions start with "_xtos_" in ld file. - * + * *********************************************************************** */ @@ -51,24 +51,23 @@ extern "C" { * @{ */ - typedef enum { - ETS_OK = 0,/**< return successful in ets*/ - ETS_FAILED = 1/**< return failed in ets*/ + ETS_OK = 0, /**< return successful in ets*/ + ETS_FAILED = 1 /**< return failed in ets*/ } ETS_STATUS; typedef uint32_t ETSSignal; typedef uint32_t ETSParam; -typedef struct ETSEventTag ETSEvent;/**< Event transmit/receive in ets*/ +typedef struct ETSEventTag ETSEvent; /**< Event transmit/receive in ets*/ struct ETSEventTag { - ETSSignal sig;/**< Event signal, in same task, different Event with different signal*/ - ETSParam par;/**< Event parameter, sometimes without usage, then will be set as 0*/ + ETSSignal sig; /**< Event signal, in same task, different Event with different signal*/ + ETSParam par; /**< Event parameter, sometimes without usage, then will be set as 0*/ }; -typedef void (*ETSTask)(ETSEvent *e);/**< Type of the Task processer*/ -typedef void (* ets_idle_cb_t)(void *arg);/**< Type of the system idle callback*/ +typedef void (*ETSTask)(ETSEvent *e); /**< Type of the Task processer*/ +typedef void (* ets_idle_cb_t)(void *arg); /**< Type of the system idle callback*/ /** * @brief Start the Espressif Task Scheduler, which is an infinit loop. Please do not add code after it. @@ -117,7 +116,8 @@ void ets_task(ETSTask task, uint8_t prio, ETSEvent *queue, uint8_t qlen); * @return ETS_OK : post successful * @return ETS_FAILED : post failed */ -ETS_STATUS ets_post(uint8_t prio, ETSSignal sig, ETSParam par); +ETS_STATUS ets_post(uint8_t prio, ETSSignal sig, ETSParam par); + /** * @} */ @@ -130,8 +130,7 @@ ETS_STATUS ets_post(uint8_t prio, ETSSignal sig, ETSParam par); * @{ */ - -extern const char* const exc_cause_table[40];///**< excption cause that defined by the core.*/ +extern const char *const exc_cause_table[40]; ///**< excption cause that defined by the core.*/ /** * @brief Set Pro cpu Entry code, code can be called in PRO CPU when booting is not completed. @@ -168,7 +167,7 @@ void ets_set_appcpu_boot_addr(uint32_t start); * * @param uint32_t pos : Flash physical address. * - * @param uint32_t* entry_addr: the pointer of an variable that can store Entry code address. + * @param uint32_t *entry_addr: the pointer of an variable that can store Entry code address. * * @param bool jump : Jump into the code in the function or not. * @@ -184,7 +183,7 @@ ETS_STATUS ets_unpack_flash_code_legacy(uint32_t pos, uint32_t *entry_addr, bool * * @param uint32_t pos : Flash physical address. * - * @param uint32_t* entry_addr: the pointer of an variable that can store Entry code address. + * @param uint32_t *entry_addr: the pointer of an variable that can store Entry code address. * * @param bool jump : Jump into the code in the function or not. * @@ -196,11 +195,11 @@ ETS_STATUS ets_unpack_flash_code_legacy(uint32_t pos, uint32_t *entry_addr, bool * @return ETS_FAILED : unpack failed */ ETS_STATUS ets_unpack_flash_code(uint32_t pos, uint32_t *entry_addr, bool jump, bool sb_need_check, bool config); + /** * @} */ - /** \defgroup ets_printf_apis, ets_printf related apis used in ets * @brief ets printf apis */ @@ -214,7 +213,7 @@ ETS_STATUS ets_unpack_flash_code(uint32_t pos, uint32_t *entry_addr, bool jump, * Can not print float point data format, or longlong data format. * So we maybe only use this in ROM. * - * @param const char* fmt : See printf. + * @param const char *fmt : See printf. * * @param ... : See printf. * @@ -275,7 +274,6 @@ void ets_install_uart_printf(void); * @} */ - /** \defgroup ets_timer_apis, ets_timer related apis used in ets * @brief ets timer apis */ @@ -286,11 +284,11 @@ void ets_install_uart_printf(void); typedef void ETSTimerFunc(void *timer_arg);/**< timer handler*/ typedef struct _ETSTIMER_ { - struct _ETSTIMER_ *timer_next;/**< timer linker*/ - uint32_t timer_expire;/**< abstruct time when timer expire*/ - uint32_t timer_period;/**< timer period, 0 means timer is not periodic repeated*/ - ETSTimerFunc *timer_func;/**< timer handler*/ - void *timer_arg;/**< timer handler argument*/ + struct _ETSTIMER_ *timer_next; /**< timer linker*/ + uint32_t timer_expire; /**< abstruct time when timer expire*/ + uint32_t timer_period; /**< timer period, 0 means timer is not periodic repeated*/ + ETSTimerFunc *timer_func; /**< timer handler*/ + void *timer_arg; /**< timer handler argument*/ } ETSTimer; /** @@ -393,7 +391,7 @@ void ets_update_cpu_frequency(uint32_t ticks_per_us); * * @return uint32_t : CPU ticks per us record in ets. */ -uint32_t ets_get_cpu_frequency(); +uint32_t ets_get_cpu_frequency(void); /** * @brief Get xtal_freq/analog_8M*256 value calibrated in rtc module. @@ -402,27 +400,25 @@ uint32_t ets_get_cpu_frequency(); * * @return uint32_t : xtal_freq/analog_8M*256. */ -uint32_t ets_get_xtal_scale(); +uint32_t ets_get_xtal_scale(void); /** * @brief Get xtal_freq value, If value not stored in RTC_STORE5, than store. * * @param None * - * @return uint32_t : if rtc store the value (RTC_STORE5 high 16 bits and low 16 bits with same value), read from rtc register. + * @return uint32_t : if rtc store the value (RTC_STORE5 high 16 bits and low 16 bits with same value), read from rtc register. * clock = (REG_READ(RTC_STORE5) & 0xffff) << 12; - * else if analog_8M in efuse + * else if analog_8M in efuse * clock = ets_get_xtal_scale() * 15625 * ets_efuse_get_8M_clock() / 40; * else clock = 26M. */ -uint32_t ets_get_detected_xtal_freq(); +uint32_t ets_get_detected_xtal_freq(void); /** * @} */ - - /** \defgroup ets_intr_apis, ets interrupt configure related apis * @brief ets intr apis */ @@ -506,7 +502,7 @@ void ets_waiti0(void); /** * @brief Attach an CPU interrupt to a hardware source. * We have 4 steps to use an interrupt: - * 1.Attach hardware interrupt source to CPU. intr_matrix_set(0, ETS_WIFI_MAC_INTR_SOURCE, ETS_WMAC_INUM); + * 1.Attach hardware interrupt source to CPU. intr_matrix_set(0, ETS_WIFI_MAC_INTR_SOURCE, ETS_WMAC_INUM); * 2.Set interrupt handler. xt_set_interrupt_handler(ETS_WMAC_INUM, func, NULL); * 3.Enable interrupt for CPU. xt_ints_on(1 << ETS_WMAC_INUM); * 4.Enable interrupt in the module. @@ -548,7 +544,7 @@ void intr_matrix_set(int cpu_no, uint32_t model_num, uint32_t intr_num); #define ETS_TG0_T0_INTR_ATTACH(func, arg) \ ETS_ISR_ATTACH(ETS_TG0_T0_INUM, (func), (void *)(arg)) - + #define ETS_GPIO_INTR_ATTACH(func, arg) \ ETS_ISR_ATTACH(ETS_GPIO_INUM, (func), (void *)(arg)) @@ -557,7 +553,7 @@ void intr_matrix_set(int cpu_no, uint32_t model_num, uint32_t intr_num); #define ETS_WDT_INTR_ATTACH(func, arg) \ ETS_ISR_ATTACH(ETS_WDT_INUM, (func), (void *)(arg)) - + #define ETS_SLC_INTR_ATTACH(func, arg) \ ETS_ISR_ATTACH(ETS_SLC_INUM, (func), (void *)(arg)) @@ -578,7 +574,7 @@ void intr_matrix_set(int cpu_no, uint32_t model_num, uint32_t intr_num); #define ETS_GPIO_INTR_DISABLE() \ ETS_INTR_DISABLE(ETS_GPIO_INUM) - + #define ETS_WDT_INTR_ENABLE() \ ETS_INTR_ENABLE(ETS_WDT_INUM) @@ -596,19 +592,19 @@ void intr_matrix_set(int cpu_no, uint32_t model_num, uint32_t intr_num); #define ETS_SLC_INTR_DISABLE() \ ETS_INTR_DISABLE(ETS_SLC_INUM) - #endif + /** * @} */ - #ifndef MAC2STR #define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] #define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x" #endif #define ETS_MEM_BAR() asm volatile ( "" : : : "memory" ) + /** * @} */ diff --git a/components/esp32/include/rom/gpio.h b/components/esp32/include/rom/gpio.h index fee7aff2a6..a6ca66f1de 100644 --- a/components/esp32/include/rom/gpio.h +++ b/components/esp32/include/rom/gpio.h @@ -33,7 +33,6 @@ extern "C" { * @{ */ - #define GPIO_REG_READ(reg) READ_PERI_REG(reg) #define GPIO_REG_WRITE(reg, val) WRITE_PERI_REG(reg, val) #define GPIO_PIN_COUNT 40 @@ -46,14 +45,14 @@ extern "C" { #define GPIO_REGID_TO_PINIDX(reg_id) ((reg_id) - GPIO_ID_PIN0) -typedef enum{ - GPIO_PIN_INTR_DISABLE = 0, - GPIO_PIN_INTR_POSEDGE = 1, - GPIO_PIN_INTR_NEGEDGE = 2, - GPIO_PIN_INTR_ANYEGDE = 3, - GPIO_PIN_INTR_LOLEVEL = 4, - GPIO_PIN_INTR_HILEVEL = 5 -}GPIO_INT_TYPE; +typedef enum { + GPIO_PIN_INTR_DISABLE = 0, + GPIO_PIN_INTR_POSEDGE = 1, + GPIO_PIN_INTR_NEGEDGE = 2, + GPIO_PIN_INTR_ANYEGDE = 3, + GPIO_PIN_INTR_LOLEVEL = 4, + GPIO_PIN_INTR_HILEVEL = 5 +} GPIO_INT_TYPE; #define GPIO_OUTPUT_SET(gpio_no, bit_value) \ ((gpio_no < 32) ? gpio_output_set(bit_value<BIT(0). - * There is no particular ordering guaranteed; so if the order of writes is significant, + * There is no particular ordering guaranteed; so if the order of writes is significant, * calling code should divide a single call into multiple calls. * * @param uint32_t set_mask : the gpios that need high level. @@ -94,7 +93,7 @@ void gpio_output_set(uint32_t set_mask, uint32_t clear_mask, uint32_t enable_mas /** * @brief Change GPIO(32-39) pin output by setting, clearing, or disabling pins, GPIO32<->BIT(0). - * There is no particular ordering guaranteed; so if the order of writes is significant, + * There is no particular ordering guaranteed; so if the order of writes is significant, * calling code should divide a single call into multiple calls. * * @param uint32_t set_mask : the gpios that need high level. @@ -111,18 +110,18 @@ void gpio_output_set_high(uint32_t set_mask, uint32_t clear_mask, uint32_t enabl /** * @brief Sample the value of GPIO input pins(0-31) and returns a bitmask. - * + * * @param None - * + * * @return uint32_t : bitmask for GPIO input pins, BIT(0) for GPIO0. */ uint32_t gpio_input_get(void); /** * @brief Sample the value of GPIO input pins(32-39) and returns a bitmask. - * + * * @param None - * + * * @return uint32_t : bitmask for GPIO input pins, BIT(0) for GPIO32. */ uint32_t gpio_input_get_high(void); @@ -131,11 +130,11 @@ uint32_t gpio_input_get_high(void); * @brief Register an application-specific interrupt handler for GPIO pin interrupts. * Once the interrupt handler is called, it will not be called again until after a call to gpio_intr_ack. * Please do not call this function in SDK. - * + * * @param gpio_intr_handler_fn_t fn : gpio application-specific interrupt handler - * + * * @param void *arg : gpio application-specific interrupt handler argument. - * + * * @return None */ void gpio_intr_handler_register(gpio_intr_handler_fn_t fn, void *arg); @@ -143,9 +142,9 @@ void gpio_intr_handler_register(gpio_intr_handler_fn_t fn, void *arg); /** * @brief Get gpio interrupts which happens but not processed. * Please do not call this function in SDK. - * + * * @param None - * + * * @return uint32_t : bitmask for GPIO pending interrupts, BIT(0) for GPIO0. */ uint32_t gpio_intr_pending(void); @@ -153,9 +152,9 @@ uint32_t gpio_intr_pending(void); /** * @brief Get gpio interrupts which happens but not processed. * Please do not call this function in SDK. - * + * * @param None - * + * * @return uint32_t : bitmask for GPIO pending interrupts, BIT(0) for GPIO32. */ uint32_t gpio_intr_pending_high(void); @@ -163,9 +162,9 @@ uint32_t gpio_intr_pending_high(void); /** * @brief Ack gpio interrupts to process pending interrupts. * Please do not call this function in SDK. - * + * * @param uint32_t ack_mask: bitmask for GPIO ack interrupts, BIT(0) for GPIO0. - * + * * @return None */ void gpio_intr_ack(uint32_t ack_mask); @@ -173,9 +172,9 @@ void gpio_intr_ack(uint32_t ack_mask); /** * @brief Ack gpio interrupts to process pending interrupts. * Please do not call this function in SDK. - * + * * @param uint32_t ack_mask: bitmask for GPIO ack interrupts, BIT(0) for GPIO32. - * + * * @return None */ void gpio_intr_ack_high(uint32_t ack_mask); @@ -183,11 +182,11 @@ void gpio_intr_ack_high(uint32_t ack_mask); /** * @brief Set GPIO to wakeup the ESP32. * Please do not call this function in SDK. - * + * * @param uint32_t i: gpio number. - * + * * @param GPIO_INT_TYPE intr_state : only GPIO_PIN_INTR_LOLEVEL\GPIO_PIN_INTR_HILEVEL can be used - * + * * @return None */ void gpio_pin_wakeup_enable(uint32_t i, GPIO_INT_TYPE intr_state); @@ -195,97 +194,97 @@ void gpio_pin_wakeup_enable(uint32_t i, GPIO_INT_TYPE intr_state); /** * @brief disable GPIOs to wakeup the ESP32. * Please do not call this function in SDK. - * + * * @param None - * + * * @return None */ -void gpio_pin_wakeup_disable(); +void gpio_pin_wakeup_disable(void); /** * @brief set gpio input to a signal, one gpio can input to several signals. - * + * * @param uint32_t gpio : gpio number, 0~0x27 * gpio == 0x30, input 0 to signal * gpio == 0x34, ??? * gpio == 0x38, input 1 to signal * * @param uint32_t signal_idx : signal index. - * - * @param bool inv : the signal is inv or not - * + * + * @param bool inv : the signal is inv or not + * * @return None */ void gpio_matrix_in(uint32_t gpio, uint32_t signal_idx, bool inv); /** * @brief set signal output to gpio, one signal can output to several gpios. - * + * * @param uint32_t gpio : gpio number, 0~0x27 * * @param uint32_t signal_idx : signal index. * signal_idx == 0x100, cancel output put to the gpio - * - * @param bool out_inv : the signal output is inv or not - * - * @param bool oen_inv : the signal output enable is inv or not - * + * + * @param bool out_inv : the signal output is inv or not + * + * @param bool oen_inv : the signal output enable is inv or not + * * @return None */ void gpio_matrix_out(uint32_t gpio, uint32_t signal_idx, bool out_inv, bool oen_inv); /** * @brief Select pad as a gpio function from IOMUX. - * + * * @param uint32_t gpio_num : gpio number, 0~0x27 - * + * * @return None */ void gpio_pad_select_gpio(uint8_t gpio_num); /** * @brief Set pad driver capability. - * + * * @param uint32_t gpio_num : gpio number, 0~0x27 - * + * * @param uint8_t drv : 0-3 - * + * * @return None */ void gpio_pad_set_drv(uint8_t gpio_num, uint8_t drv); /** * @brief Pull up the pad from gpio number. - * + * * @param uint32_t gpio_num : gpio number, 0~0x27 - * + * * @return None */ void gpio_pad_pullup(uint8_t gpio_num); /** * @brief Pull down the pad from gpio number. - * + * * @param uint32_t gpio_num : gpio number, 0~0x27 - * + * * @return None */ void gpio_pad_pulldown(uint8_t gpio_num); /** * @brief Unhold the pad from gpio number. - * + * * @param uint32_t gpio_num : gpio number, 0~0x27 - * + * * @return None */ void gpio_pad_unhold(uint8_t gpio_num); /** * @brief Hold the pad from gpio number. - * + * * @param uint32_t gpio_num : gpio number, 0~0x27 - * + * * @return None */ void gpio_pad_hold(uint8_t gpio_num); diff --git a/components/esp32/include/rom/rtc.h b/components/esp32/include/rom/rtc.h index b5c6abe81c..d8c0c789a3 100644 --- a/components/esp32/include/rom/rtc.h +++ b/components/esp32/include/rom/rtc.h @@ -40,12 +40,12 @@ extern "C" { * Please do not use reserved or used rtc memory or registers. * * * ************************************************************************************* - * RTC Memory & Store Register usage + * RTC Memory & Store Register usage ************************************************************************************* * rtc memory addr type size usage * 0x3ff61000(0x50000000) Slow SIZE_CP Co-Processor code/Reset Entry - * 0x3ff61000+SIZE_CP Slow 7936-SIZE_CP - * 0x3ff62f00 Slow 256 Reserved + * 0x3ff61000+SIZE_CP Slow 6144-SIZE_CP + * 0x3ff62800 Slow 2048 Reserved * * 0x3ff80000(0x400c0000) Fast 8192 deep sleep entry code * @@ -87,7 +87,7 @@ typedef enum { RTCWDT_CPU_RESET = 13, /**<13, RTC Watch dog Reset CPU*/ EXT_CPU_RESET = 14, /**<14, for APP CPU, reseted by PRO CPU*/ RTCWDT_BROWN_OUT_RESET = 15, /**<15, Reset when the vdd voltage is not stable*/ - RTCWDT_RTC_RESET = 16 /**<16, RTC Watch dog reset digital core and rtc module*/ + RTCWDT_RTC_RESET = 16 /**<16, RTC Watch dog reset digital core and rtc module*/ } RESET_REASON; typedef enum { @@ -136,7 +136,7 @@ typedef enum { SDIO_IDLE_INT_EN = SDIO_IDLE_INT, RTC_WDT_INT_EN = RTC_WDT_INT, RTC_TIME_VALID_INT_EN = RTC_TIME_VALID_INT -}RTC_INT_EN; +} RTC_INT_EN; /** * @brief Get the reset reason for CPU. diff --git a/components/esp32/include/rom/secure_boot.h b/components/esp32/include/rom/secure_boot.h index 56952381e6..cfeda08933 100644 --- a/components/esp32/include/rom/secure_boot.h +++ b/components/esp32/include/rom/secure_boot.h @@ -11,6 +11,7 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. + #ifndef _ROM_SECURE_BOOT_H_ #define _ROM_SECURE_BOOT_H_ diff --git a/components/esp32/include/rom/spi_flash.h b/components/esp32/include/rom/spi_flash.h index 7206d013e9..ec71cfe85e 100644 --- a/components/esp32/include/rom/spi_flash.h +++ b/components/esp32/include/rom/spi_flash.h @@ -11,6 +11,7 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. + #ifndef _ROM_SPI_FLASH_H_ #define _ROM_SPI_FLASH_H_ @@ -36,31 +37,31 @@ extern "C" { /************************************************************* * Note ************************************************************* - * 1. ESP32 chip have 4 SPI slave/master, however, SPI0 is - * used as an SPI master to access Flash and ext-SRAM by - * Cache module. It will support Decryto read for Flash, - * read/write for ext-SRAM. And SPI1 is also used as an - * SPI master for Flash read/write and ext-SRAM read/write. + * 1. ESP32 chip have 4 SPI slave/master, however, SPI0 is + * used as an SPI master to access Flash and ext-SRAM by + * Cache module. It will support Decryto read for Flash, + * read/write for ext-SRAM. And SPI1 is also used as an + * SPI master for Flash read/write and ext-SRAM read/write. * It will support Encrypto write for Flash. * 2. As an SPI master, SPI support Highest clock to 80M, - * however, Flash with 80M Clock should be configured - * for different Flash chips. If you want to use 80M - * clock We should use the SPI that is certified by - * Espressif. However, the certification is not started + * however, Flash with 80M Clock should be configured + * for different Flash chips. If you want to use 80M + * clock We should use the SPI that is certified by + * Espressif. However, the certification is not started * at the time, so please use 40M clock at the moment. - * 3. SPI Flash can use 2 lines or 4 lines mode. If you - * use 2 lines mode, you can save two pad SPIHD and - * SPIWP for gpio. ESP32 support configured SPI pad for - * Flash, the configuration is stored in efuse and flash. + * 3. SPI Flash can use 2 lines or 4 lines mode. If you + * use 2 lines mode, you can save two pad SPIHD and + * SPIWP for gpio. ESP32 support configured SPI pad for + * Flash, the configuration is stored in efuse and flash. * However, the configurations of pads should be certified - * by Espressif. If you use this function, please use 40M + * by Espressif. If you use this function, please use 40M * clock at the moment. - * 4. ESP32 support to use Common SPI command to configure + * 4. ESP32 support to use Common SPI command to configure * Flash to QIO mode, if you failed to configure with fix * command. With Common SPI Command, ESP32 can also provide * a way to use same Common SPI command groups on different * Flash chips. - * 5. This functions are not protected by packeting, Please use the + * 5. This functions are not protected by packeting, Please use the ************************************************************* */ @@ -131,7 +132,7 @@ typedef enum { SPI_FLASH_RESULT_TIMEOUT } SpiFlashOpResult; -typedef struct{ +typedef struct { uint32_t deviceId; uint32_t chip_size; // chip size in bytes uint32_t block_size; @@ -151,7 +152,7 @@ typedef struct { /** * @brief Fix the bug in SPI hardware communication with Flash/Ext-SRAM in High Speed. - * Please do not call this function in SDK. + * Please do not call this function in SDK. * * @param uint8_t spi: 0 for SPI0(Cache Access), 1 for SPI1(Flash read/write). * @@ -163,11 +164,11 @@ void spi_dummy_len_fix(uint8_t spi, uint8_t freqdiv); /** * @brief Select SPI Flash to QIO mode when WP pad is read from Flash. - * Please do not call this function in SDK. + * Please do not call this function in SDK. * * @param uint8_t wp_gpio_num: WP gpio number. * - * @param uint32_t ishspi: 0 for spi, 1 for hspi, flash pad decided by strapping + * @param uint32_t ishspi: 0 for spi, 1 for hspi, flash pad decided by strapping * else, bit[5:0] spiclk, bit[11:6] spiq, bit[17:12] spid, bit[23:18] spics0, bit[29:24] spihd * * @return None @@ -176,27 +177,27 @@ void SelectSpiQIO(uint8_t wp_gpio_num, uint32_t ishspi); /** * @brief Set SPI Flash pad drivers. - * Please do not call this function in SDK. + * Please do not call this function in SDK. * * @param uint8_t wp_gpio_num: WP gpio number. * - * @param uint32_t ishspi: 0 for spi, 1 for hspi, flash pad decided by strapping + * @param uint32_t ishspi: 0 for spi, 1 for hspi, flash pad decided by strapping * else, bit[5:0] spiclk, bit[11:6] spiq, bit[17:12] spid, bit[23:18] spics0, bit[29:24] spihd * - * @param uint8_t* drvs: drvs[0]-bit[3:0] for cpiclk, bit[7:4] for spiq, drvs[1]-bit[3:0] for spid, drvs[1]-bit[7:4] for spid - * drvs[2]-bit[3:0] for spihd, drvs[2]-bit[7:4] for spiwp. + * @param uint8_t *drvs: drvs[0]-bit[3:0] for cpiclk, bit[7:4] for spiq, drvs[1]-bit[3:0] for spid, drvs[1]-bit[7:4] for spid + * drvs[2]-bit[3:0] for spihd, drvs[2]-bit[7:4] for spiwp. * Values usually read from falsh by rom code, function usually callde by rom code. * if value with bit(3) set, the value is valid, bit[2:0] is the real value. * * @return None */ -void SetSpiDrvs(uint8_t wp_gpio_num, uint32_t ishspi, uint8_t* drvs); +void SetSpiDrvs(uint8_t wp_gpio_num, uint32_t ishspi, uint8_t *drvs); /** * @brief Select SPI Flash function for pads. - * Please do not call this function in SDK. + * Please do not call this function in SDK. * - * @param uint32_t ishspi: 0 for spi, 1 for hspi, flash pad decided by strapping + * @param uint32_t ishspi: 0 for spi, 1 for hspi, flash pad decided by strapping * else, bit[5:0] spiclk, bit[11:6] spiq, bit[17:12] spid, bit[23:18] spics0, bit[29:24] spihd * * @return None @@ -205,9 +206,9 @@ void SelectSpiFunction(uint32_t ishspi); /** * @brief SPI Flash init, clock divisor is 4, use 1 line Slow read mode. - * Please do not call this function in SDK. + * Please do not call this function in SDK. * - * @param uint32_t ishspi: 0 for spi, 1 for hspi, flash pad decided by strapping + * @param uint32_t ishspi: 0 for spi, 1 for hspi, flash pad decided by strapping * else, bit[5:0] spiclk, bit[11:6] spiq, bit[17:12] spid, bit[23:18] spics0, bit[29:24] spihd * * @param uint8_t legacy: In legacy mode, more SPI command is used in line. @@ -216,64 +217,61 @@ void SelectSpiFunction(uint32_t ishspi); */ void spi_flash_attach(uint32_t ishspi, bool legacy); - -//void spi_cache_sram_init(); - /** * @brief SPI Read Flash status register. We use CMD 0x05. - * Please do not call this function in SDK. + * Please do not call this function in SDK. * - * @param SpiFlashChip * spi : The information for Flash, which is exported from ld file. + * @param SpiFlashChip *spi : The information for Flash, which is exported from ld file. * - * @param uint32_t* status : The pointer to which to return the Flash status value. + * @param uint32_t *status : The pointer to which to return the Flash status value. * * @return SPI_FLASH_RESULT_OK : read OK. * SPI_FLASH_RESULT_ERR : read error. * SPI_FLASH_RESULT_TIMEOUT : read timeout. */ -SpiFlashOpResult SPI_read_status(SpiFlashChip * spi, uint32_t * status); +SpiFlashOpResult SPI_read_status(SpiFlashChip *spi, uint32_t *status); /** * @brief SPI Read Flash status register high 16 bit. We use CMD 0x35. * Please do not call this function in SDK. * - * @param SpiFlashChip * spi : The information for Flash, which is exported from ld file. + * @param SpiFlashChip *spi : The information for Flash, which is exported from ld file. * - * @param uint32_t* status : The pointer to which to return the Flash status value. + * @param uint32_t *status : The pointer to which to return the Flash status value. * * @return SPI_FLASH_RESULT_OK : read OK. * SPI_FLASH_RESULT_ERR : read error. * SPI_FLASH_RESULT_TIMEOUT : read timeout. */ -SpiFlashOpResult SPI_read_status_high(SpiFlashChip * spi, uint32_t * status); +SpiFlashOpResult SPI_read_status_high(SpiFlashChip *spi, uint32_t *status); /** * @brief Write status to Falsh status register. * Please do not call this function in SDK. * - * @param SpiFlashChip * spi : The information for Flash, which is exported from ld file. + * @param SpiFlashChip *spi : The information for Flash, which is exported from ld file. * - * @param uint32_t status_value : Value to . + * @param uint32_t status_value : Value to . * * @return SPI_FLASH_RESULT_OK : write OK. * SPI_FLASH_RESULT_ERR : write error. * SPI_FLASH_RESULT_TIMEOUT : write timeout. */ -SpiFlashOpResult SPI_write_status(SpiFlashChip * spi, uint32_t status_value); +SpiFlashOpResult SPI_write_status(SpiFlashChip *spi, uint32_t status_value); /** - * @brief Use a command to Read Flash status register. + * @brief Use a command to Read Flash status register. * Please do not call this function in SDK. * - * @param SpiFlashChip * spi : The information for Flash, which is exported from ld file. + * @param SpiFlashChip *spi : The information for Flash, which is exported from ld file. * - * @param uint32_t* status : The pointer to which to return the Flash status value. + * @param uint32_t*status : The pointer to which to return the Flash status value. * * @return SPI_FLASH_RESULT_OK : read OK. * SPI_FLASH_RESULT_ERR : read error. * SPI_FLASH_RESULT_TIMEOUT : read timeout. */ -SpiFlashOpResult SPI_user_command_read(uint32_t * status, uint8_t cmd); +SpiFlashOpResult SPI_user_command_read(uint32_t *status, uint8_t cmd); /** * @brief Config SPI Flash read mode when init. @@ -319,13 +317,13 @@ SpiFlashOpResult SPIClkConfig(uint8_t freqdiv, uint8_t spi); * @brief Send CommonCmd to Flash so that is can go into QIO mode, some Flash use different CMD. * Please do not call this function in SDK. * - * @param SpiCommonCmd * cmd : A struct to show the action of a command. + * @param SpiCommonCmd *cmd : A struct to show the action of a command. * * @return uint16_t 0 : do not send command any more. * 1 : go to the next command. - * n > 1 : skip (n - 1) commands. + * n > 1 : skip (n - 1) commands. */ -uint16_t SPI_Common_Command(SpiCommonCmd * cmd); +uint16_t SPI_Common_Command(SpiCommonCmd *cmd); /** * @brief Unlock SPI write protect. @@ -337,7 +335,7 @@ uint16_t SPI_Common_Command(SpiCommonCmd * cmd); * SPI_FLASH_RESULT_ERR : Unlock error. * SPI_FLASH_RESULT_TIMEOUT : Unlock timeout. */ -SpiFlashOpResult SPIUnlock(); +SpiFlashOpResult SPIUnlock(void); /** * @brief SPI write protect. @@ -349,7 +347,7 @@ SpiFlashOpResult SPIUnlock(); * SPI_FLASH_RESULT_ERR : Lock error. * SPI_FLASH_RESULT_TIMEOUT : Lock timeout. */ -SpiFlashOpResult SPILock(); +SpiFlashOpResult SPILock(void); /** * @brief Update SPI Flash parameter. @@ -425,11 +423,11 @@ SpiFlashOpResult SPIEraseArea(uint32_t start_addr, uint32_t area_len); /** * @brief Write Data to Flash, you should Erase it yourself if need. - * Please do not call this function in SDK. + * Please do not call this function in SDK. * * @param uint32_t dest_addr : Address to write, should be 4 bytes aligned. * - * @param const uint32_t* src : The pointer to data which is to write. + * @param const uint32_t *src : The pointer to data which is to write. * * @param uint32_t len : Length to write, should be 4 bytes aligned. * @@ -437,15 +435,15 @@ SpiFlashOpResult SPIEraseArea(uint32_t start_addr, uint32_t area_len); * SPI_FLASH_RESULT_ERR : Write error. * SPI_FLASH_RESULT_TIMEOUT : Write timeout. */ -SpiFlashOpResult SPIWrite(uint32_t dest_addr, const uint32_t* src, int32_t len); +SpiFlashOpResult SPIWrite(uint32_t dest_addr, const uint32_t *src, int32_t len); /** * @brief Read Data from Flash, you should Erase it yourself if need. - * Please do not call this function in SDK. + * Please do not call this function in SDK. * * @param uint32_t src_addr : Address to read, should be 4 bytes aligned. * - * @param uint32_t* data : The buf to read the data. + * @param uint32_t *dest : The buf to read the data. * * @param uint32_t len : Length to read, should be 4 bytes aligned. * @@ -453,49 +451,49 @@ SpiFlashOpResult SPIWrite(uint32_t dest_addr, const uint32_t* src, int32_t len); * SPI_FLASH_RESULT_ERR : Read error. * SPI_FLASH_RESULT_TIMEOUT : Read timeout. */ -SpiFlashOpResult SPIRead(uint32_t src_addr, uint32_t* dest, int32_t len); +SpiFlashOpResult SPIRead(uint32_t src_addr, uint32_t *dest, int32_t len); /** * @brief SPI1 go into encrypto mode. - * Please do not call this function in SDK. + * Please do not call this function in SDK. * * @param None * * @return None */ -void SPI_Write_Encrypt_Enable(); +void SPI_Write_Encrypt_Enable(void); /** * @brief Prepare 32 Bytes data to encrpto writing, you should Erase it yourself if need. - * Please do not call this function in SDK. + * Please do not call this function in SDK. * * @param uint32_t flash_addr : Address to write, should be 32 bytes aligned. * - * @param uint32_t* data : The pointer to data which is to write. + * @param uint32_t *data : The pointer to data which is to write. * * @return SPI_FLASH_RESULT_OK : Prepare OK. * SPI_FLASH_RESULT_ERR : Prepare error. * SPI_FLASH_RESULT_TIMEOUT : Prepare timeout. */ -SpiFlashOpResult SPI_Prepare_Encrypt_Data(uint32_t flash_addr, uint32_t* data); +SpiFlashOpResult SPI_Prepare_Encrypt_Data(uint32_t flash_addr, uint32_t *data); /** * @brief SPI1 go out of encrypto mode. - * Please do not call this function in SDK. + * Please do not call this function in SDK. * * @param None * * @return None */ -void SPI_Write_Encrypt_Disable(); +void SPI_Write_Encrypt_Disable(void); /** * @brief Encrpto writing data to flash, you should Erase it yourself if need. - * Please do not call this function in SDK. + * Please do not call this function in SDK. * * @param uint32_t flash_addr : Address to write, should be 32 bytes aligned. * - * @param uint32_t* data : The pointer to data which is to write. + * @param uint32_t *data : The pointer to data which is to write. * * @param uint32_t len : Length to write, should be 32 bytes aligned. * @@ -503,7 +501,7 @@ void SPI_Write_Encrypt_Disable(); * SPI_FLASH_RESULT_ERR : Encrypto write error. * SPI_FLASH_RESULT_TIMEOUT : Encrypto write timeout. */ -SpiFlashOpResult SPI_Encrypt_Write(uint32_t flash_addr, uint32_t* data, uint32_t len); +SpiFlashOpResult SPI_Encrypt_Write(uint32_t flash_addr, uint32_t *data, uint32_t len); /** * @} diff --git a/components/esp32/include/rom/uart.h b/components/esp32/include/rom/uart.h old mode 100755 new mode 100644 index ee0e01d3cf..8e3125133c --- a/components/esp32/include/rom/uart.h +++ b/components/esp32/include/rom/uart.h @@ -60,9 +60,9 @@ extern "C" { #define UART_RCV_ERR_FLAG BIT7 //send and receive message frame head -#define FRAME_FLAG 0x7E +#define FRAME_FLAG 0x7E -typedef enum{ +typedef enum { UART_LINE_STATUS_INT_FLAG = 0x06, UART_RCV_FIFO_INT_FLAG = 0x04, UART_RCV_TMOUT_INT_FLAG = 0x0C, @@ -90,9 +90,9 @@ typedef enum { } UartStopBitsNum; typedef enum { - NONE_BITS = 0, - ODD_BITS = 2, - EVEN_BITS = 3 + NONE_BITS = 0, + ODD_BITS = 2, + EVEN_BITS = 3 } UartParityMode; @@ -121,7 +121,7 @@ typedef enum { typedef enum { EMPTY, UNDER_WRITE, - WRITE_OVER + WRITE_OVER } RcvMsgBuffState; typedef struct { @@ -129,9 +129,9 @@ typedef struct { uint8_t *pRcvMsgBuff; uint8_t *pWritePos; uint8_t *pReadPos; - uint8_t TrigLvl; //JLU: may need to pad + uint8_t TrigLvl; RcvMsgBuffState BuffState; -}RcvMsgBuff; +} RcvMsgBuff; typedef struct { uint32_t TrxBuffSize; @@ -146,7 +146,7 @@ typedef enum { RCV_ESC_CHAR, } RcvMsgState; -typedef struct{ +typedef struct { UartBautRate baut_rate; UartBitsNum4Char data_bits; UartExistParity exist_parity; @@ -169,7 +169,7 @@ typedef struct{ * * @return None */ -void uartAttach(); +void uartAttach(void); /** * @brief Init uart0 or uart1 for UART download booting mode. @@ -269,12 +269,12 @@ void uart_tx_wait_idle(uint8_t uart_no); * @brief Get an input char from message channel. * Please do not call this function in SDK. * - * @param uint8_t* pRxChar : the pointer to store the char. + * @param uint8_t *pRxChar : the pointer to store the char. * * @return OK for successful. * FAIL for failed. */ -STATUS uart_rx_one_char(uint8_t* pRxChar); +STATUS uart_rx_one_char(uint8_t *pRxChar); /** * @brief Get an input char to message channel, wait until successful. @@ -290,47 +290,47 @@ char uart_rx_one_char_block(void); * @brief Get an input string line from message channel. * Please do not call this function in SDK. * - * @param uint8_t* pString : the pointer to store the string. + * @param uint8_t *pString : the pointer to store the string. * * @param uint8_t MaxStrlen : the max string length, incude '\0'. * * @return OK. */ -STATUS UartRxString(uint8_t* pString, uint8_t MaxStrlen); +STATUS UartRxString(uint8_t *pString, uint8_t MaxStrlen); /** * @brief Process uart recevied information in the interrupt handler. * Please do not call this function in SDK. * - * @param void * para : the message receive buffer. + * @param void *para : the message receive buffer. * * @return None */ -void uart_rx_intr_handler(void * para); +void uart_rx_intr_handler(void *para); /** * @brief Get an char from receive buffer. * Please do not call this function in SDK. * - * @param RcvMsgBuff* pRxBuff : the pointer to the struct that include receive buffer. + * @param RcvMsgBuff *pRxBuff : the pointer to the struct that include receive buffer. * - * @param uint8_t* pRxByte : the pointer to store the char. + * @param uint8_t *pRxByte : the pointer to store the char. * * @return OK for successful. * FAIL for failed. */ -STATUS uart_rx_readbuff( RcvMsgBuff* pRxBuff, uint8_t* pRxByte); +STATUS uart_rx_readbuff( RcvMsgBuff *pRxBuff, uint8_t *pRxByte); /** * @brief Get all chars from receive buffer. * Please do not call this function in SDK. * - * @param uint8_t * pCmdLn : the pointer to store the string. + * @param uint8_t *pCmdLn : the pointer to store the string. * * @return OK for successful. * FAIL for failed. */ -STATUS UartGetCmdLn(uint8_t * pCmdLn); +STATUS UartGetCmdLn(uint8_t *pCmdLn); /** * @brief Get uart configuration struct. @@ -340,13 +340,13 @@ STATUS UartGetCmdLn(uint8_t * pCmdLn); * * @return UartDevice * : uart configuration struct pointer. */ -UartDevice * GetUartDevice(); +UartDevice *GetUartDevice(void); /** - * @brief Send an packet to download tool, with ESC char. + * @brief Send an packet to download tool, with SLIP escaping. * Please do not call this function in SDK. * - * @param uint8_t * p : the pointer to output string. + * @param uint8_t *p : the pointer to output string. * * @param int len : the string length. * @@ -355,10 +355,10 @@ UartDevice * GetUartDevice(); void send_packet(uint8_t *p, int len); /** - * @brief Receive an packet from download tool, with ESC char. + * @brief Receive an packet from download tool, with SLIP escaping. * Please do not call this function in SDK. * - * @param uint8_t * p : the pointer to input string. + * @param uint8_t *p : the pointer to input string. * * @param int len : If string length > len, the string will be truncated. * @@ -369,12 +369,11 @@ void send_packet(uint8_t *p, int len); */ int recv_packet(uint8_t *p, int len, uint8_t is_sync); - /** - * @brief Send an packet to download tool, with ESC char. + * @brief Send an packet to download tool, with SLIP escaping. * Please do not call this function in SDK. * - * @param uint8_t * pData : the pointer to input string. + * @param uint8_t *pData : the pointer to input string. * * @param uint16_t DataLen : the string length. * @@ -383,12 +382,11 @@ int recv_packet(uint8_t *p, int len, uint8_t is_sync); */ STATUS SendMsg(uint8_t *pData, uint16_t DataLen); - /** - * @brief Receive an packet from download tool, with ESC char. + * @brief Receive an packet from download tool, with SLIP escaping. * Please do not call this function in SDK. * - * @param uint8_t * pData : the pointer to input string. + * @param uint8_t *pData : the pointer to input string. * * @param uint16_t MaxDataLen : If string length > MaxDataLen, the string will be truncated. * diff --git a/components/esp32/include/soc/io_mux_reg.h b/components/esp32/include/soc/io_mux_reg.h index 7be453e095..e5027a71d3 100644 --- a/components/esp32/include/soc/io_mux_reg.h +++ b/components/esp32/include/soc/io_mux_reg.h @@ -105,7 +105,7 @@ #define PERIPHS_IO_MUX_MTDI_U (DR_REG_IO_MUX_BASE +0x34) #define FUNC_MTDI_EMAC_TXD3 5 #define FUNC_MTDI_SD_DATA2 4 -#define FUNC_MTDI_HS2_DATA2 3 +#define FUNC_MTDI_HS2_DATA2 3 #define FUNC_MTDI_GPIO12 2 #define FUNC_MTDI_HSPIQ 1 #define FUNC_MTDI_MTDI 0 From d0442602c7a1be11cc07f5a686601c40edf99a90 Mon Sep 17 00:00:00 2001 From: Jack Date: Tue, 6 Sep 2016 20:21:47 +0800 Subject: [PATCH 32/51] add comments to register read/write operations --- components/esp32/include/soc/soc.h | 57 ++++++++++++++++++++++++------ 1 file changed, 46 insertions(+), 11 deletions(-) diff --git a/components/esp32/include/soc/soc.h b/components/esp32/include/soc/soc.h index 46389106c5..2deab13e53 100755 --- a/components/esp32/include/soc/soc.h +++ b/components/esp32/include/soc/soc.h @@ -58,35 +58,70 @@ #define BIT(nr) (1UL << (nr)) +//write value to register #define REG_WRITE(_r, _v) (*(volatile uint32_t *)(_r)) = (_v) + +//read value from register #define REG_READ(_r) (*(volatile uint32_t *)(_r)) -//get bit or get bits +//get bit or get bits from register #define REG_GET_BIT(_r, _b) (*(volatile uint32_t*)(_r) & (_b)) -//set bit or set bits + +//set bit or set bits to register #define REG_SET_BIT(_r, _b) (*(volatile uint32_t*)(_r) |= (_b)) -//clear bit or clear bits + +//clear bit or clear bits of register #define REG_CLR_BIT(_r, _b) (*(volatile uint32_t*)(_r) &= ~(_b)) -//set bits controll by mask + +//set bits of register controlled by mask #define REG_SET_BITS(_r, _b, _m) (*(volatile uint32_t*)(_r) = (*(volatile uint32_t*)(_r) & ~(_m)) | ((_b) & (_m))) -#define VALUE_GET_FIELD(_r, _f) (((_r) >> (_f##_S)) & (_f)) -#define VALUE_GET_FIELD2(_r, _f) (((_r) & (_f))>> (_f##_S)) -#define VALUE_SET_FIELD(_r, _f, _v) ((_r)=(((_r) & ~((_f) << (_f##_S)))|((_v)<<(_f##_S)))) -#define VALUE_SET_FIELD2(_r, _f, _v) ((_r)=(((_r) & ~(_f))|((_v)<<(_f##_S)))) -#define FIELD_TO_VALUE(_f, _v) (((_v)&(_f))<<_f##_S) -#define FIELD_TO_VALUE2(_f, _v) (((_v)<<_f##_S) & (_f)) +//get field from register, used when _f is not left shifted by _f##_S #define REG_GET_FIELD(_r, _f) ((REG_READ(_r) >> (_f##_S)) & (_f)) + +//set field to register, used when _f is not left shifted by _f##_S #define REG_SET_FIELD(_r, _f, _v) (REG_WRITE((_r),((REG_READ(_r) & ~((_f) << (_f##_S)))|(((_v) & (_f))<<(_f##_S))))) +//get field value from a variable, used when _f is not left shifted by _f##_S +#define VALUE_GET_FIELD(_r, _f) (((_r) >> (_f##_S)) & (_f)) +//get field value from a variable, used when _f is left shifted by _f##_S +#define VALUE_GET_FIELD2(_r, _f) (((_r) & (_f))>> (_f##_S)) + +//set field value to a variable, used when _f is not left shifted by _f##_S +#define VALUE_SET_FIELD(_r, _f, _v) ((_r)=(((_r) & ~((_f) << (_f##_S)))|((_v)<<(_f##_S)))) + +//set field value to a variable, used when _f is left shifted by _f##_S +#define VALUE_SET_FIELD2(_r, _f, _v) ((_r)=(((_r) & ~(_f))|((_v)<<(_f##_S)))) + +//generate a value from a field value, used when _f is not left shifted by _f##_S +#define FIELD_TO_VALUE(_f, _v) (((_v)&(_f))<<_f##_S) + +//generate a value from a field value, used when _f is left shifted by _f##_S +#define FIELD_TO_VALUE2(_f, _v) (((_v)<<_f##_S) & (_f)) + +//read value from register #define READ_PERI_REG(addr) (*((volatile uint32_t *)ETS_UNCACHED_ADDR(addr))) + +//write value to register #define WRITE_PERI_REG(addr, val) (*((volatile uint32_t *)ETS_UNCACHED_ADDR(addr))) = (uint32_t)(val) + +//clear bits of register controlled by mask #define CLEAR_PERI_REG_MASK(reg, mask) WRITE_PERI_REG((reg), (READ_PERI_REG(reg)&(~(mask)))) + +//set bits of register controlled by mask #define SET_PERI_REG_MASK(reg, mask) WRITE_PERI_REG((reg), (READ_PERI_REG(reg)|(mask))) + +//get bits of register controlled by mask #define GET_PERI_REG_MASK(reg, mask) (READ_PERI_REG(reg) & (mask)) -#define GET_PERI_REG_BITS(reg, hipos,lowpos) ((READ_PERI_REG(reg)>>(lowpos))&((1<<((hipos)-(lowpos)+1))-1)) + +//get bits of register controlled by highest bit and lowest bit +#define GET_PERI_REG_BITS(reg, hipos,lowpos) ((READ_PERI_REG(reg)>>(lowpos))&((1<<((hipos)-(lowpos)+1))-1)) + +//set bits of register controlled by mask and shift #define SET_PERI_REG_BITS(reg,bit_map,value,shift) (WRITE_PERI_REG((reg),(READ_PERI_REG(reg)&(~((bit_map)<<(shift))))|(((value) & bit_map)<<(shift)) )) + +//get field of register #define GET_PERI_REG_BITS2(reg, mask,shift) ((READ_PERI_REG(reg)>>(shift))&(mask)) //}} From bd8febe58c11faa52e1d06c9506d1f8614998de4 Mon Sep 17 00:00:00 2001 From: Jack Date: Mon, 12 Sep 2016 13:54:08 +0800 Subject: [PATCH 33/51] add MACRO to get flash pad number from efuse value --- components/esp32/include/rom/efuse.h | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/components/esp32/include/rom/efuse.h b/components/esp32/include/rom/efuse.h index 62692c3098..58cfdb20bc 100644 --- a/components/esp32/include/rom/efuse.h +++ b/components/esp32/include/rom/efuse.h @@ -55,7 +55,7 @@ void ets_efuse_program_op(void); * * @param null * - * @return u32: 1 for 100KHZ. + * @return u32: 1 for 100KHZ, range is 0 to 255. */ uint32_t ets_efuse_get_8M_clock(void); @@ -69,6 +69,27 @@ uint32_t ets_efuse_get_8M_clock(void); */ uint32_t ets_efuse_get_spiconfig(void); +#define EFUSE_SPICONFIG_RET_SPICLK_MASK 0x3f +#define EFUSE_SPICONFIG_RET_SPICLK_SHIFT 0 +#define EFUSE_SPICONFIG_RET_SPICLK(ret) (((ret) >> EFUSE_SPICONFIG_RET_SPICLK_SHIFT) & EFUSE_SPICONFIG_RET_SPICLK_MASK) + +#define EFUSE_SPICONFIG_RET_SPIQ_MASK 0x3f +#define EFUSE_SPICONFIG_RET_SPIQ_SHIFT 6 +#define EFUSE_SPICONFIG_RET_SPIQ(ret) (((ret) >> EFUSE_SPICONFIG_RET_SPIQ_SHIFT) & EFUSE_SPICONFIG_RET_SPIQ_MASK) + +#define EFUSE_SPICONFIG_RET_SPID_MASK 0x3f +#define EFUSE_SPICONFIG_RET_SPID_SHIFT 12 +#define EFUSE_SPICONFIG_RET_SPID(ret) (((ret) >> EFUSE_SPICONFIG_RET_SPID_SHIFT) & EFUSE_SPICONFIG_RET_SPID_MASK) + +#define EFUSE_SPICONFIG_RET_SPICS0_MASK 0x3f +#define EFUSE_SPICONFIG_RET_SPICS0_SHIFT 18 +#define EFUSE_SPICONFIG_RET_SPICS0(ret) (((ret) >> EFUSE_SPICONFIG_RET_SPICS0_SHIFT) & EFUSE_SPICONFIG_RET_SPICS0_MASK) + + +#define EFUSE_SPICONFIG_RET_SPIHD_MASK 0x3f +#define EFUSE_SPICONFIG_RET_SPIHD_SHIFT 24 +#define EFUSE_SPICONFIG_RET_SPIHD(ret) (((ret) >> EFUSE_SPICONFIG_RET_SPIHD_SHIFT) & EFUSE_SPICONFIG_RET_SPIHD_MASK) + /** * @brief A crc8 algorithm used in efuse check. * From e9f2645b210544e3ddb3977de7ea03f6f59c2089 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Mon, 12 Sep 2016 18:54:45 +0800 Subject: [PATCH 34/51] components/esp32: add inter-processor call API and implement spi_flash through it With this change, flash operations can run on both cores. NVS and WiFi stack can also run in dual core mode now. --- components/esp32/cpu_start.c | 25 ++-- components/esp32/include/esp_err.h | 5 +- components/esp32/include/esp_ipc.h | 84 +++++++++++++ components/esp32/ipc.c | 117 ++++++++++++++++++ components/spi_flash/esp_spi_flash.c | 175 ++++++++++++++++----------- 5 files changed, 321 insertions(+), 85 deletions(-) create mode 100644 components/esp32/include/esp_ipc.h create mode 100644 components/esp32/ipc.c diff --git a/components/esp32/cpu_start.c b/components/esp32/cpu_start.c index 85d3009ef3..d58ba43f88 100644 --- a/components/esp32/cpu_start.c +++ b/components/esp32/cpu_start.c @@ -36,6 +36,8 @@ #include "esp_spi_flash.h" #include "nvs_flash.h" #include "esp_event.h" +#include "esp_spi_flash.h" +#include "esp_ipc.h" static void IRAM_ATTR user_start_cpu0(void); static void IRAM_ATTR call_user_start_cpu1(); @@ -180,37 +182,39 @@ void IRAM_ATTR call_user_start_cpu1() { user_start_cpu1(); } -extern volatile int port_xSchedulerRunning; -extern int xPortStartScheduler(); +extern volatile int port_xSchedulerRunning[2]; -void user_start_cpu1(void) { - //Wait for the freertos initialization is finished on CPU0 - while (port_xSchedulerRunning == 0) ; - ets_printf("Core0 started initializing FreeRTOS. Jumping to scheduler.\n"); - //Okay, start the scheduler! +void IRAM_ATTR user_start_cpu1(void) { + // Wait for FreeRTOS initialization to finish on PRO CPU + while (port_xSchedulerRunning[0] == 0) { + ; + } + ets_printf("Starting scheduler on APP CPU.\n"); + // Start the scheduler on APP CPU xPortStartScheduler(); } extern void (*__init_array_start)(void); extern void (*__init_array_end)(void); -extern esp_err_t app_main(); static void do_global_ctors(void) { void (**p)(void); for(p = &__init_array_start; p != &__init_array_end; ++p) (*p)(); } +extern esp_err_t app_main(); void user_start_cpu0(void) { ets_setup_syscalls(); do_global_ctors(); + esp_ipc_init(); + spi_flash_init(); #if CONFIG_WIFI_ENABLED - ets_printf("nvs_flash_init\n"); esp_err_t ret = nvs_flash_init(5, 3); if (ret != ESP_OK) { - ets_printf("nvs_flash_init fail, ret=%d\n", ret); + printf("nvs_flash_init failed, ret=%d\n", ret); } system_init(); @@ -227,6 +231,7 @@ void user_start_cpu0(void) { app_main(); #endif + ets_printf("Starting scheduler on PRO CPU.\n"); vTaskStartScheduler(); } diff --git a/components/esp32/include/esp_err.h b/components/esp32/include/esp_err.h index 39b60a905a..6ea176991c 100644 --- a/components/esp32/include/esp_err.h +++ b/components/esp32/include/esp_err.h @@ -27,7 +27,10 @@ typedef int32_t esp_err_t; #define ESP_OK 0 #define ESP_FAIL -1 -#define ESP_ERR_NO_MEM 0x101 +#define ESP_ERR_NO_MEM 0x101 +#define ESP_ERR_INVALID_ARG 0x102 +#define ESP_ERR_INVALID_STATE 0x103 + #ifdef __cplusplus } diff --git a/components/esp32/include/esp_ipc.h b/components/esp32/include/esp_ipc.h new file mode 100644 index 0000000000..b28df31285 --- /dev/null +++ b/components/esp32/include/esp_ipc.h @@ -0,0 +1,84 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef __ESP_IPC_H__ +#define __ESP_IPC_H__ + +#include + +typedef void (*esp_ipc_func_t)(void* arg); + +/** + * @brief Inter-processor call APIs + * + * FreeRTOS provides several APIs which can be used to communicate between + * different tasks, including tasks running on different CPUs. + * This module provides additional APIs to run some code on the other CPU. + */ + + +/** + * @brief Initialize inter-processor call module. + * + * This function start two tasks, one on each CPU. These tasks are started + * with high priority. These tasks are normally inactive, waiting until one of + * the esp_ipc_call_* functions to be used. One of these tasks will be + * woken up to execute the callback provided to esp_ipc_call_nonblocking or + * esp_ipc_call_blocking. + */ +void esp_ipc_init(); + + +/** + * @brief Execute function on the given CPU + * + * This will wake a high-priority task on CPU indicated by cpu_id argument, + * and run func(arg) in the context of that task. + * This function returns as soon as the high-priority task is woken up. + * If another IPC call is already being executed, this function will also wait + * for it to complete. + * + * In single-core mode, returns ESP_ERR_INVALID_ARG for cpu_id 1. + * + * @param cpu_id CPU where function should be executed (0 or 1) + * @param func pointer to a function which should be executed + * @param arg arbitrary argument to be passed into function + * + * @return ESP_ERR_INVALID_ARG if cpu_id is invalid + * ESP_OK otherwise + */ +esp_err_t esp_ipc_call(uint32_t cpu_id, esp_ipc_func_t func, void* arg); + + +/** + * @brief Execute function on the given CPU and wait for it to finish + * + * This will wake a high-priority task on CPU indicated by cpu_id argument, + * and run func(arg) in the context of that task. + * This function waits for func to return. + * + * In single-core mode, returns ESP_ERR_INVALID_ARG for cpu_id 1. + * + * @param cpu_id CPU where function should be executed (0 or 1) + * @param func pointer to a function which should be executed + * @param arg arbitrary argument to be passed into function + * + * @return ESP_ERR_INVALID_ARG if cpu_id is invalid + * ESP_OK otherwise + */ +esp_err_t esp_ipc_call_blocking(uint32_t cpu_id, esp_ipc_func_t func, void* arg); + + + +#endif /* __ESP_IPC_H__ */ diff --git a/components/esp32/ipc.c b/components/esp32/ipc.c new file mode 100644 index 0000000000..b7524cae68 --- /dev/null +++ b/components/esp32/ipc.c @@ -0,0 +1,117 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include +#include "esp_err.h" +#include "esp_ipc.h" +#include "esp_attr.h" + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" + + +static TaskHandle_t s_ipc_tasks[portNUM_PROCESSORS]; // Two high priority tasks, one for each CPU +static SemaphoreHandle_t s_ipc_mutex; // This mutex is used as a global lock for esp_ipc_* APIs +static SemaphoreHandle_t s_ipc_sem[portNUM_PROCESSORS]; // Two semaphores used to wake each of s_ipc_tasks +static SemaphoreHandle_t s_ipc_ack; // Semaphore used to acknowledge that task was woken up, + // or function has finished running +static volatile esp_ipc_func_t s_func; // Function which should be called by high priority task +static void * volatile s_func_arg; // Argument to pass into s_func +typedef enum { + IPC_WAIT_FOR_START, + IPC_WAIT_FOR_END +} esp_ipc_wait_t; + +static volatile esp_ipc_wait_t s_ipc_wait; // This variable tells high priority task when it should give + // s_ipc_ack semaphore: before s_func is called, or + // after it returns + +static void IRAM_ATTR ipc_task(void* arg) +{ + const uint32_t cpuid = (uint32_t) arg; + assert(cpuid == xPortGetCoreID()); + while (true) { + // Wait for IPC to be initiated. + // This will be indicated by giving the semaphore corresponding to + // this CPU. + if (xSemaphoreTake(s_ipc_sem[cpuid], portMAX_DELAY) != pdTRUE) { + // TODO: when can this happen? + abort(); + } + + esp_ipc_func_t func = s_func; + void* arg = s_func_arg; + + if (s_ipc_wait == IPC_WAIT_FOR_START) { + xSemaphoreGive(s_ipc_ack); + } + (*func)(arg); + if (s_ipc_wait == IPC_WAIT_FOR_END) { + xSemaphoreGive(s_ipc_ack); + } + } + // TODO: currently this is unreachable code. Introduce esp_ipc_uninit + // function which will signal to both tasks that they can shut down. + // Not critical at this point, we don't have a use case for stopping + // IPC yet. + // Also need to delete the semaphore here. + vTaskDelete(NULL); +} + +void esp_ipc_init() +{ + s_ipc_mutex = xSemaphoreCreateMutex(); + s_ipc_ack = xSemaphoreCreateBinary(); + const char* task_names[2] = {"ipc0", "ipc1"}; + for (int i = 0; i < portNUM_PROCESSORS; ++i) { + s_ipc_sem[i] = xSemaphoreCreateBinary(); + xTaskCreatePinnedToCore(ipc_task, task_names[i], XT_STACK_MIN_SIZE, (void*) i, + configMAX_PRIORITIES - 1, &s_ipc_tasks[i], i); + } +} + +static esp_err_t esp_ipc_call_and_wait(uint32_t cpu_id, esp_ipc_func_t func, void* arg, esp_ipc_wait_t wait_for) +{ + if (cpu_id >= portNUM_PROCESSORS) { + return ESP_ERR_INVALID_ARG; + } + if (xTaskGetSchedulerState() != taskSCHEDULER_RUNNING) { + return ESP_ERR_INVALID_STATE; + } + + xSemaphoreTake(s_ipc_mutex, portMAX_DELAY); + + s_func = func; + s_func_arg = arg; + s_ipc_wait = IPC_WAIT_FOR_START; + xSemaphoreGive(s_ipc_sem[cpu_id]); + xSemaphoreTake(s_ipc_ack, portMAX_DELAY); + xSemaphoreGive(s_ipc_mutex); + return ESP_OK; +} + +esp_err_t esp_ipc_call(uint32_t cpu_id, esp_ipc_func_t func, void* arg) +{ + return esp_ipc_call_and_wait(cpu_id, func, arg, IPC_WAIT_FOR_START); +} + +esp_err_t esp_ipc_call_blocking(uint32_t cpu_id, esp_ipc_func_t func, void* arg) +{ + return esp_ipc_call_and_wait(cpu_id, func, arg, IPC_WAIT_FOR_END); +} + diff --git a/components/spi_flash/esp_spi_flash.c b/components/spi_flash/esp_spi_flash.c index e3d09acaf0..fb34a44872 100644 --- a/components/spi_flash/esp_spi_flash.c +++ b/components/spi_flash/esp_spi_flash.c @@ -12,16 +12,20 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include +#include #include #include #include - -#include #include #include -#include +#include #include #include "sdkconfig.h" +#include "esp_ipc.h" +#include "esp_attr.h" +#include "esp_spi_flash.h" + /* Driver for SPI flash read/write/erase operations @@ -42,7 +46,7 @@ this flag to be set. Once the flag is set, it disables cache on CPU A and starts flash operation. - While flash operation is running, interrupts can still run on CPU B. + While flash operation is running, interrupts can still run on CPU B. We assume that all interrupt code is placed into RAM. Once flash operation is complete, function on CPU A sets another flag, @@ -58,93 +62,94 @@ */ static esp_err_t spi_flash_translate_rc(SpiFlashOpResult rc); -extern void Cache_Flush(int); +static void IRAM_ATTR spi_flash_disable_cache(uint32_t cpuid, uint32_t* saved_state); +static void IRAM_ATTR spi_flash_restore_cache(uint32_t cpuid, uint32_t saved_state); + +static uint32_t s_flash_op_cache_state[2]; + +#ifndef CONFIG_FREERTOS_UNICORE +static SemaphoreHandle_t s_flash_op_mutex; +static bool s_flash_op_can_start = false; +static bool s_flash_op_complete = false; +#endif //CONFIG_FREERTOS_UNICORE + #ifndef CONFIG_FREERTOS_UNICORE -static TaskHandle_t s_flash_op_tasks[2]; -static SemaphoreHandle_t s_flash_op_mutex; -static SemaphoreHandle_t s_flash_op_sem[2]; -static bool s_flash_op_can_start = false; -static bool s_flash_op_complete = false; - - -// Task whose duty is to block other tasks from running on a given CPU -static void IRAM_ATTR spi_flash_op_block_task(void* arg) +static void IRAM_ATTR spi_flash_op_block_func(void* arg) { + // Disable scheduler on this CPU + vTaskSuspendAll(); uint32_t cpuid = (uint32_t) arg; - while (true) { - // Wait for flash operation to be initiated. - // This will be indicated by giving the semaphore corresponding to - // this CPU. - if (xSemaphoreTake(s_flash_op_sem[cpuid], portMAX_DELAY) != pdTRUE) { - // TODO: when can this happen? - abort(); - } - // Disable cache on this CPU - Cache_Read_Disable(cpuid); - // Signal to the flash API function that flash operation can start - s_flash_op_can_start = true; - while (!s_flash_op_complete) { - // until we have a way to use interrupts for inter-CPU communication, - // busy loop here and wait for the other CPU to finish flash operation - } - // Flash operation is complete, re-enable cache - Cache_Read_Enable(cpuid); + // Disable cache so that flash operation can start + spi_flash_disable_cache(cpuid, &s_flash_op_cache_state[cpuid]); + s_flash_op_can_start = true; + while (!s_flash_op_complete) { + // until we have a way to use interrupts for inter-CPU communication, + // busy loop here and wait for the other CPU to finish flash operation } - // TODO: currently this is unreachable code. Introduce spi_flash_uninit - // function which will signal to both tasks that they can shut down. - // Not critical at this point, we don't have a use case for stopping - // SPI flash driver yet. - // Also need to delete the semaphore here. - vTaskDelete(NULL); + // Flash operation is complete, re-enable cache + spi_flash_restore_cache(cpuid, s_flash_op_cache_state[cpuid]); + // Re-enable scheduler + xTaskResumeAll(); } void spi_flash_init() { - s_flash_op_can_start = false; - s_flash_op_complete = false; - s_flash_op_sem[0] = xSemaphoreCreateBinary(); - s_flash_op_sem[1] = xSemaphoreCreateBinary(); s_flash_op_mutex = xSemaphoreCreateMutex(); - // Start two tasks, one on each CPU, with max priorities - // TODO: optimize stack usage. Stack size 512 is too small. - xTaskCreatePinnedToCore(spi_flash_op_block_task, "flash_op_pro", 1024, (void*) 0, - configMAX_PRIORITIES - 1, &s_flash_op_tasks[0], 0); - xTaskCreatePinnedToCore(spi_flash_op_block_task, "flash_op_app", 1024, (void*) 1, - configMAX_PRIORITIES - 1, &s_flash_op_tasks[1], 1); } static void IRAM_ATTR spi_flash_disable_interrupts_caches_and_other_cpu() { // Take the API lock xSemaphoreTake(s_flash_op_mutex, portMAX_DELAY); + const uint32_t cpuid = xPortGetCoreID(); - uint32_t other_cpuid = !cpuid; - s_flash_op_can_start = false; - s_flash_op_complete = false; - // Signal to the spi_flash_op_block_task on the other CPU that we need it to - // disable cache there and block other tasks from executing. - xSemaphoreGive(s_flash_op_sem[other_cpuid]); - while (!s_flash_op_can_start) { - // Busy loop and wait for spi_flash_op_block_task to take the semaphore on the - // other CPU. + const uint32_t other_cpuid = !cpuid; + + if (xTaskGetSchedulerState() == taskSCHEDULER_NOT_STARTED) { + // Scheduler hasn't been started yet, so we don't need to worry + // about cached code running on the APP CPU. + spi_flash_disable_cache(other_cpuid, &s_flash_op_cache_state[other_cpuid]); + } else { + // Signal to the spi_flash_op_block_task on the other CPU that we need it to + // disable cache there and block other tasks from executing. + s_flash_op_can_start = false; + s_flash_op_complete = false; + esp_ipc_call(other_cpuid, &spi_flash_op_block_func, (void*) other_cpuid); + while (!s_flash_op_can_start) { + // Busy loop and wait for spi_flash_op_block_func to disable cache + // on the other CPU + } + // Disable scheduler on CPU cpuid + vTaskSuspendAll(); + // This is guaranteed to run on CPU because the other CPU is now + // occupied by highest priority task + assert(xPortGetCoreID() == cpuid); } - vTaskSuspendAll(); // Disable cache on this CPU as well - Cache_Read_Disable(cpuid); + spi_flash_disable_cache(cpuid, &s_flash_op_cache_state[cpuid]); } static void IRAM_ATTR spi_flash_enable_interrupts_caches_and_other_cpu() { - uint32_t cpuid = xPortGetCoreID(); - // Signal to spi_flash_op_block_task that flash operation is complete - s_flash_op_complete = true; + const uint32_t cpuid = xPortGetCoreID(); + const uint32_t other_cpuid = !cpuid; + // Re-enable cache on this CPU - Cache_Read_Enable(cpuid); + spi_flash_restore_cache(cpuid, s_flash_op_cache_state[cpuid]); + + if (xTaskGetSchedulerState() == taskSCHEDULER_NOT_STARTED) { + // Scheduler is not running yet — just re-enable cache on APP CPU + spi_flash_restore_cache(other_cpuid, s_flash_op_cache_state[other_cpuid]); + } else { + // Signal to spi_flash_op_block_task that flash operation is complete + s_flash_op_complete = true; + // Resume tasks on the current CPU + xTaskResumeAll(); + } // Release API lock xSemaphoreGive(s_flash_op_mutex); - xTaskResumeAll(); } #else // CONFIG_FREERTOS_UNICORE @@ -157,14 +162,12 @@ void spi_flash_init() static void IRAM_ATTR spi_flash_disable_interrupts_caches_and_other_cpu() { vTaskSuspendAll(); - Cache_Read_Disable(0); - Cache_Read_Disable(1); + spi_flash_disable_cache(0, &s_flash_op_cache_state[0]); } static void IRAM_ATTR spi_flash_enable_interrupts_caches_and_other_cpu() { - Cache_Read_Enable(0); - Cache_Read_Enable(1); + spi_flash_restore_cache(0, s_flash_op_cache_state[0]); xTaskResumeAll(); } @@ -179,8 +182,6 @@ esp_err_t IRAM_ATTR spi_flash_erase_sector(uint16_t sec) if (rc == SPI_FLASH_RESULT_OK) { rc = SPIEraseSector(sec); } - Cache_Flush(0); - Cache_Flush(1); spi_flash_enable_interrupts_caches_and_other_cpu(); return spi_flash_translate_rc(rc); } @@ -193,8 +194,6 @@ esp_err_t IRAM_ATTR spi_flash_write(uint32_t dest_addr, const uint32_t *src, uin if (rc == SPI_FLASH_RESULT_OK) { rc = SPIWrite(dest_addr, src, (int32_t) size); } - Cache_Flush(0); - Cache_Flush(1); spi_flash_enable_interrupts_caches_and_other_cpu(); return spi_flash_translate_rc(rc); } @@ -204,8 +203,6 @@ esp_err_t IRAM_ATTR spi_flash_read(uint32_t src_addr, uint32_t *dest, uint32_t s spi_flash_disable_interrupts_caches_and_other_cpu(); SpiFlashOpResult rc; rc = SPIRead(src_addr, dest, (int32_t) size); - Cache_Flush(0); - Cache_Flush(1); spi_flash_enable_interrupts_caches_and_other_cpu(); return spi_flash_translate_rc(rc); } @@ -222,3 +219,33 @@ static esp_err_t spi_flash_translate_rc(SpiFlashOpResult rc) return ESP_ERR_FLASH_OP_FAIL; } } + +static void IRAM_ATTR spi_flash_disable_cache(uint32_t cpuid, uint32_t* saved_state) +{ + uint32_t ret = 0; + if (cpuid == 0) { + ret |= GET_PERI_REG_BITS2(PRO_CACHE_CTRL1_REG, 0x1f, 0); + while (GET_PERI_REG_BITS2(PRO_DCACHE_DBUG_REG0, DPORT_PRO_CACHE_STATE, DPORT_PRO_CACHE_STATE_S) != 1) { + ; + } + SET_PERI_REG_BITS(PRO_CACHE_CTRL_REG, 1, 0, DPORT_PRO_CACHE_ENABLE_S); + } else { + ret |= GET_PERI_REG_BITS2(APP_CACHE_CTRL1_REG, 0x1f, 0); + while (GET_PERI_REG_BITS2(APP_DCACHE_DBUG_REG0, DPORT_APP_CACHE_STATE, DPORT_APP_CACHE_STATE_S) != 1) { + ; + } + SET_PERI_REG_BITS(APP_CACHE_CTRL_REG, 1, 0, DPORT_APP_CACHE_ENABLE_S); + } + *saved_state = ret; +} + +static void IRAM_ATTR spi_flash_restore_cache(uint32_t cpuid, uint32_t saved_state) +{ + if (cpuid == 0) { + SET_PERI_REG_BITS(PRO_CACHE_CTRL_REG, 1, 1, DPORT_PRO_CACHE_ENABLE_S); + SET_PERI_REG_BITS(PRO_CACHE_CTRL1_REG, 0x1f, saved_state, 0); + } else { + SET_PERI_REG_BITS(APP_CACHE_CTRL_REG, 1, 1, DPORT_APP_CACHE_ENABLE_S); + SET_PERI_REG_BITS(APP_CACHE_CTRL1_REG, 0x1f, saved_state, 0); + } +} From 19bbe64a56eab2ee08b3f939ddce7580d0735d60 Mon Sep 17 00:00:00 2001 From: Yinling Date: Mon, 12 Sep 2016 19:09:28 +0800 Subject: [PATCH 35/51] update ci: build ssc with idf submodule wifi lib --- .gitlab-ci.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 23f1a16d8d..bae6ab9b71 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -59,9 +59,7 @@ build_ssc: expire_in: 6 mos script: - # use gitlab wifi lib instead of github wifi lib - - git clone ssh://git@gitlab.espressif.cn:27227/idf/esp32-wifi-lib.git - - cp esp32-wifi-lib/* components/esp32/lib/ + - git submodule update --init --recursive - git clone ssh://git@gitlab.espressif.cn:27227/yinling/SSC.git - cd SSC - make defconfig From 4598f9fc882ea45827b274b67155a056d1b2a8dc Mon Sep 17 00:00:00 2001 From: Wu Jian Gang Date: Mon, 12 Sep 2016 19:32:05 +0800 Subject: [PATCH 36/51] esp32/lib: Bump WiFi revision --- components/esp32/lib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/esp32/lib b/components/esp32/lib index dcd9c6c626..e793e8ac04 160000 --- a/components/esp32/lib +++ b/components/esp32/lib @@ -1 +1 @@ -Subproject commit dcd9c6c6263ea3e3cb31559aaa76e5be9151e397 +Subproject commit e793e8ac04cae3a5ca87bbccc46021a93288df05 From 1b6022bd07a513089fb83b0407a942dff909d2ef Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Mon, 12 Sep 2016 19:53:38 +0800 Subject: [PATCH 37/51] components/esp32: remove dependency of WIFI_ENABLED on FREERTOS_UNICORE --- components/esp32/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/components/esp32/Kconfig b/components/esp32/Kconfig index af34c4a336..154ee4150e 100644 --- a/components/esp32/Kconfig +++ b/components/esp32/Kconfig @@ -7,7 +7,6 @@ config WIFI_ENABLED This compiles in the low-level WiFi stack. Temporarily, this option requires that FreeRTOS runs in single core mode. - depends on FREERTOS_UNICORE config WIFI_AUTO_STARTUP bool "Start WiFi with system startup" From 23d5c7579bebb5c69b4beee0b41cd8618ad7c72b Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Mon, 12 Sep 2016 19:54:35 +0800 Subject: [PATCH 38/51] components/esp32,spi_flash: update some comments --- components/esp32/cpu_start.c | 1 - components/esp32/include/esp_ipc.h | 4 ++++ components/spi_flash/esp_spi_flash.c | 18 ++++++++---------- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/components/esp32/cpu_start.c b/components/esp32/cpu_start.c index d58ba43f88..4e922891c3 100644 --- a/components/esp32/cpu_start.c +++ b/components/esp32/cpu_start.c @@ -190,7 +190,6 @@ void IRAM_ATTR user_start_cpu1(void) { ; } ets_printf("Starting scheduler on APP CPU.\n"); - // Start the scheduler on APP CPU xPortStartScheduler(); } diff --git a/components/esp32/include/esp_ipc.h b/components/esp32/include/esp_ipc.h index b28df31285..a77b4932fe 100644 --- a/components/esp32/include/esp_ipc.h +++ b/components/esp32/include/esp_ipc.h @@ -25,6 +25,8 @@ typedef void (*esp_ipc_func_t)(void* arg); * FreeRTOS provides several APIs which can be used to communicate between * different tasks, including tasks running on different CPUs. * This module provides additional APIs to run some code on the other CPU. + * + * These APIs can only be used when FreeRTOS scheduler is running. */ @@ -56,6 +58,7 @@ void esp_ipc_init(); * @param arg arbitrary argument to be passed into function * * @return ESP_ERR_INVALID_ARG if cpu_id is invalid + * ESP_ERR_INVALID_STATE if FreeRTOS scheduler is not running * ESP_OK otherwise */ esp_err_t esp_ipc_call(uint32_t cpu_id, esp_ipc_func_t func, void* arg); @@ -75,6 +78,7 @@ esp_err_t esp_ipc_call(uint32_t cpu_id, esp_ipc_func_t func, void* arg); * @param arg arbitrary argument to be passed into function * * @return ESP_ERR_INVALID_ARG if cpu_id is invalid + * ESP_ERR_INVALID_STATE if FreeRTOS scheduler is not running * ESP_OK otherwise */ esp_err_t esp_ipc_call_blocking(uint32_t cpu_id, esp_ipc_func_t func, void* arg); diff --git a/components/spi_flash/esp_spi_flash.c b/components/spi_flash/esp_spi_flash.c index fb34a44872..a4e6c4c3ea 100644 --- a/components/spi_flash/esp_spi_flash.c +++ b/components/spi_flash/esp_spi_flash.c @@ -36,15 +36,14 @@ the flash operation. In the dual-core setup this is slightly more complicated. We need to make sure that the other CPU doesn't run any code from flash. - SPI flash driver starts two tasks (spi_flash_op_block_task), one pinned to - each CPU. Each task is associated with its own semaphore. - When SPI flash API is called on CPU A (can be PRO or APP), we wake up the task - on CPU B by "giving" the semaphore associated with it. Tasks resumes, disables - cache on CPU B, and acknowledges that it has taken the semaphore by setting - a flag (s_flash_op_can_start). Flash API function running on CPU A waits for - this flag to be set. Once the flag is set, it disables cache on CPU A and - starts flash operation. + When SPI flash API is called on CPU A (can be PRO or APP), we start + spi_flash_op_block_func function on CPU B using esp_ipc_call API. This API + wakes up high priority task on CPU B and tells it to execute given function, + in this case spi_flash_op_block_func. This function disables cache on CPU B and + signals that cache is disabled by setting s_flash_op_can_start flag. + Then the task on CPU A disables cache as well, and proceeds to execute flash + operation. While flash operation is running, interrupts can still run on CPU B. We assume that all interrupt code is placed into RAM. @@ -52,8 +51,7 @@ Once flash operation is complete, function on CPU A sets another flag, s_flash_op_complete, to let the task on CPU B know that it can re-enable cache and release the CPU. Then the function on CPU A re-enables the cache on - CPU A as well and returns control to the calling code. Task on CPU B returns - to suspended state by "taking" the semaphore. + CPU A as well and returns control to the calling code. Additionally, all API functions are protected with a mutex (s_flash_op_mutex). From 417dcee450a73ede6dee0e7be9cbcdaa5bf5f2d3 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Tue, 13 Sep 2016 11:34:28 +1000 Subject: [PATCH 39/51] ci: Use github repo for wifi libraries on master branch, gitlab repo otherwise --- .gitlab-ci.yml | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index bae6ab9b71..b4e62e1fed 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -4,6 +4,18 @@ stages: - deploy before_script: + # add gitlab ssh key + - mkdir -p ~/.ssh + - chmod 700 ~/.ssh + - echo -n $GITLAB_KEY >> ~/.ssh/id_rsa_base64 + - base64 --decode --ignore-garbage ~/.ssh/id_rsa_base64 > ~/.ssh/id_rsa + - chmod 600 ~/.ssh/id_rsa + - echo -e "Host gitlab.espressif.cn\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config + + # if testing master branch, use github wifi libs. + # if testing other branches, use gitlab wifi libs (as maybe changes aren't merged to master yet) + - test "${CI_BUILD_REF_NAME}" = "master" || sed -i "s%https://github.com/espressif/esp32-wifi-lib%ssh://git@gitlab.espressif.cn:27227/idf/esp32-wifi-lib%" .gitmodules + # fetch all submodules - git submodule update --init --recursive build_template_app: @@ -59,7 +71,6 @@ build_ssc: expire_in: 6 mos script: - - git submodule update --init --recursive - git clone ssh://git@gitlab.espressif.cn:27227/yinling/SSC.git - cd SSC - make defconfig From 1f6fca672d00d4f09a019d6dc2efac876a4d4ec6 Mon Sep 17 00:00:00 2001 From: Yinling Date: Tue, 13 Sep 2016 10:06:09 +0800 Subject: [PATCH 40/51] installed gitlab key in global before_script, don't need to overwrite in template before_script --- .gitlab-ci.yml | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b4e62e1fed..96006f8c8c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -51,15 +51,6 @@ build_template_app: IDF_PATH: "$CI_PROJECT_DIR" GIT_STRATEGY: clone - # add gitlab key to build docker - before_script: - - mkdir -p ~/.ssh - - chmod 700 ~/.ssh - - echo -n $GITLAB_KEY >> ~/.ssh/id_rsa_base64 - - base64 --decode --ignore-garbage ~/.ssh/id_rsa_base64 > ~/.ssh/id_rsa - - chmod 600 ~/.ssh/id_rsa - - echo -e "Host gitlab.espressif.cn\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config - build_ssc: <<: *build_template artifacts: @@ -77,8 +68,6 @@ build_ssc: - chmod +x gen_misc_ng.sh - ./gen_misc_ng.sh - - test_nvs_on_host: stage: test image: espressif/esp32-ci-env From 174a0e3f8b6033b565965bca8f8b0b1521d2f10c Mon Sep 17 00:00:00 2001 From: Jeroen Domburg Date: Tue, 13 Sep 2016 10:22:38 +0800 Subject: [PATCH 41/51] Fix bug where nesting vTaskEnterCritical calls would not re-enable interrupts after vTaskExitCritical sections. --- components/freertos/tasks.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/components/freertos/tasks.c b/components/freertos/tasks.c index f53c67d4b5..a4595154ed 100644 --- a/components/freertos/tasks.c +++ b/components/freertos/tasks.c @@ -3766,9 +3766,13 @@ scheduler will re-enable the interrupts instead. */ void vTaskEnterCritical( portMUX_TYPE *mux ) #endif { + BaseType_t oldInterruptLevel=0; if( xSchedulerRunning != pdFALSE ) { - pxCurrentTCB[ xPortGetCoreID() ]->uxOldInterruptState=portENTER_CRITICAL_NESTED(); + //Interrupts may already be disabled (because we're doing this recursively) but we can't get the interrupt level after + //vPortCPUAquireMutex, because it also may mess with interrupts. Get it here first, then later figure out if we're nesting + //and save for real there. + oldInterruptLevel=portENTER_CRITICAL_NESTED(); } #ifdef CONFIG_FREERTOS_PORTMUX_DEBUG vPortCPUAcquireMutex( mux, function, line ); @@ -3780,13 +3784,20 @@ scheduler will re-enable the interrupts instead. */ { ( pxCurrentTCB[ xPortGetCoreID() ]->uxCriticalNesting )++; + if( xSchedulerRunning != pdFALSE && pxCurrentTCB[ xPortGetCoreID() ]->uxCriticalNesting == 1 ) + { + //This is the first time we get called. Save original interrupt level. + pxCurrentTCB[ xPortGetCoreID() ]->uxOldInterruptState=oldInterruptLevel; + } - /* This is not the interrupt safe version of the enter critical + /* Original FreeRTOS comment, saved for reference: + This is not the interrupt safe version of the enter critical function so assert() if it is being called from an interrupt context. Only API functions that end in "FromISR" can be used in an interrupt. Only assert if the critical nesting count is 1 to protect against recursive calls if the assert function also uses a critical section. */ + /* DISABLED in the esp32 port - because of SMP, vTaskEnterCritical has to be used in way more places than before, and some are called both from ISR as well as non-ISR code, thus we re-organized From 3061ae40c0ef8902f3148a5c322bdc4f69902bf1 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Tue, 13 Sep 2016 13:46:51 +1000 Subject: [PATCH 42/51] bootloader: Add bootloader Kconfig Allow debug level & colour highlighting to be configured --- components/bootloader/Kconfig.projbuild | 33 +++++++++ components/bootloader/Makefile.projbuild | 3 + components/bootloader/src/Makefile | 7 +- .../bootloader/src/main/bootloader_log.h | 67 +++++++++++++------ .../bootloader/src/main/bootloader_start.c | 2 - 5 files changed, 88 insertions(+), 24 deletions(-) create mode 100644 components/bootloader/Kconfig.projbuild diff --git a/components/bootloader/Kconfig.projbuild b/components/bootloader/Kconfig.projbuild new file mode 100644 index 0000000000..74028b6e90 --- /dev/null +++ b/components/bootloader/Kconfig.projbuild @@ -0,0 +1,33 @@ +menu "Bootloader config" + +choice BOOTLOADER_LOG_LEVEL + bool "Bootloader log verbosity" + default BOOTLOADER_LOG_LEVEL_NOTICE + help + Specify how much output to see in the bootloader logs. + + Note that if MTDO is HIGH on reset, all early boot output + (including bootloader logs) are suppressed. +config BOOTLOADER_LOG_LEVEL_NONE + bool "No output" +config BOOTLOADER_LOG_LEVEL_ERROR + bool "Error" +config BOOTLOADER_LOG_LEVEL_WARN + bool "Warning" +config BOOTLOADER_LOG_LEVEL_INFO + bool "Info" +config BOOTLOADER_LOG_LEVEL_NOTICE + bool "Notice" +config BOOTLOADER_LOG_LEVEL_DEBUG + bool "Debug" +endchoice + +config BOOTLOADER_LOG_COLORS + bool "Use ANSI terminal colors in bootloader log output" + default "y" + help + Enable ANSI terminal color codes in bootloader output. + + In order to view these, your terminal program must support ANSI color codes. + +endmenu diff --git a/components/bootloader/Makefile.projbuild b/components/bootloader/Makefile.projbuild index 48c09d4816..aaebd4d263 100644 --- a/components/bootloader/Makefile.projbuild +++ b/components/bootloader/Makefile.projbuild @@ -8,6 +8,7 @@ # basically runs Make in the src/ directory but it needs to zero some variables # the ESP-IDF project.mk makefile exports first, to not let them interfere. # +ifeq ("$(IS_BOOTLOADER_BUILD)","") BOOTLOADER_COMPONENT_PATH := $(COMPONENT_PATH) BOOTLOADER_BUILD_DIR=$(BUILD_DIR_BASE)/bootloader @@ -47,3 +48,5 @@ $(COMPONENT_PATH)/src/sdkconfig: $(PROJECT_PATH)/sdkconfig # bootloader-flash calls flash in the bootloader dummy project bootloader-flash: $(BOOTLOADER_BIN) $(MAKE) -C $(BOOTLOADER_COMPONENT_PATH)/src flash MAKEFLAGS= V=$(V) + +endif diff --git a/components/bootloader/src/Makefile b/components/bootloader/src/Makefile index 191fbef110..b6b0c1af02 100644 --- a/components/bootloader/src/Makefile +++ b/components/bootloader/src/Makefile @@ -4,7 +4,12 @@ # PROJECT_NAME := bootloader -COMPONENTS := esptool_py +COMPONENTS := esptool_py bootloader + +# The bootloader pseudo-component is also included in this build, for its Kconfig.projbuild to be included. +# +# IS_BOOTLOADER_BUILD tells the component Makefile.projbuild to be a no-op +IS_BOOTLOADER_BUILD := 1 #We cannot include the esp32 component directly but we need its includes. This is fixed by #adding it in the main/Makefile directory. diff --git a/components/bootloader/src/main/bootloader_log.h b/components/bootloader/src/main/bootloader_log.h index 32bc4852e2..1f7ec62ad5 100644 --- a/components/bootloader/src/main/bootloader_log.h +++ b/components/bootloader/src/main/bootloader_log.h @@ -19,39 +19,64 @@ extern "C" { #endif +#include "sdkconfig.h" +#define BOOT_LOG_LEVEL_NONE (0) #define BOOT_LOG_LEVEL_ERROR (1) #define BOOT_LOG_LEVEL_WARN (2) #define BOOT_LOG_LEVEL_INFO (3) #define BOOT_LOG_LEVEL_NOTICE (4) #define BOOT_LOG_LEVEL_DEBUG (5) -#define Black 0;30 -#define Red 0;31 -#define Green 0;32 -#define Brown 0;33 -#define Blue 0;34 -#define Purple 0;35 -#define Cyan 0;36 +#define Black "30" +#define Red "31" +#define Green "32" +#define Brown "33" +#define Blue "34" +#define Purple "35" +#define Cyan "36" -// TODO: move BOOT_LOG_LEVEL into menuconfig -//#define BOOT_LOG_LEVEL BOOT_LOG_LEVEL_ERROR -#define BOOT_LOG_LEVEL BOOT_LOG_LEVEL_NOTICE +#if CONFIG_BOOTLOADER_LOG_COLORS +#define LOG_COLOR(COLOR) "\033[0;"COLOR"m" +#define LOG_BOLD(COLOR) "\033[1;"COLOR"m" +#define LOG_RESET_COLOR "\033[0m" +#else +#define LOG_COLOR(...) +#define LOG_BOLD(...) +#define LOG_RESET_COLOR "" +#endif + +// BOOT_LOG_LEVEL defined by make menuconfig +#if CONFIG_BOOTLOADER_LOG_LEVEL_NONE +#define BOOT_LOG_LEVEL BOOT_LOG_LEVEL_NONE +#elif CONFIG_BOOTLOADER_LOG_LEVEL_ERROR +#define BOOT_LOG_LEVEL BOOT_LOG_LEVEL_ERROR +#elif CONFIG_BOOTLOADER_LOG_LEVEL_WARN +#define BOOT_LOG_LEVEL BOOT_LOG_LEVEL_WARN +#elif CONFIG_BOOTLOADER_LOG_LEVEL_INFO +#define BOOT_LOG_LEVEL BOOT_LOG_LEVEL_INFO +#elif CONFIG_BOOTLOADER_LOG_LEVEL_NOTICE +#define BOOT_LOG_LEVEL BOOT_LOG_LEVEL_NOTICE +#elif CONFIG_BOOTLOADER_LOG_LEVEL_DEBUG +#define BOOT_LOG_LEVEL BOOT_LOG_LEVEL_DEBUG +#else +#error "No bootloader log level set in menuconfig!" +#endif //printf("\033[0;36m[NOTICE][%s][%s][%d]\n" format "\r\n", __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__); #define log_notice(format, ...) \ do{\ if(BOOT_LOG_LEVEL >= BOOT_LOG_LEVEL_NOTICE){\ - ets_printf("\033[0;36m" format "\r\n", ##__VA_ARGS__);\ - ets_printf("\033[0m"); \ + ets_printf(LOG_COLOR(Cyan) format "\r\n", ##__VA_ARGS__); \ + ets_printf(LOG_RESET_COLOR); \ }\ }while(0) #define log_info(format, ...) \ do{\ if(BOOT_LOG_LEVEL >= BOOT_LOG_LEVEL_INFO){\ - ets_printf("\033[1;36m" format "\r\n", ##__VA_ARGS__);\ - ets_printf("\033[0m"); \ + ets_printf(LOG_BOLD(Cyan) format "\r\n", ##__VA_ARGS__); \ + ets_printf(LOG_RESET_COLOR); \ }\ }while(0) @@ -59,8 +84,8 @@ extern "C" #define log_error(format, ...) \ do{\ if(BOOT_LOG_LEVEL >= BOOT_LOG_LEVEL_ERROR){\ - ets_printf("\033[0;31m[ERROR][%s][%s][%d]\n" format "\r\n", __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__);\ - ets_printf("\033[0m"); \ + ets_printf(LOG_COLOR(Red) "[ERROR][%s][%s][%d]\n" format "\r\n", __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ + ets_printf(LOG_RESET_COLOR); \ }\ }while(0) @@ -68,8 +93,8 @@ extern "C" #define log_warn(format, ...) \ do{\ if(BOOT_LOG_LEVEL >= BOOT_LOG_LEVEL_WARN){\ - ets_printf("\033[1;33m[WARN][%s][%s][%d]\n" format "\r\n", __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__);\ - ets_printf("\033[0m"); \ + ets_printf(LOG_BOLD(Brown) "[WARN][%s][%s][%d]\n" format "\r\n", __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ + ets_printf(LOG_RESET_COLOR); \ }\ }while(0) @@ -77,8 +102,8 @@ extern "C" #define log_debug(format, ...) \ do{\ if(BOOT_LOG_LEVEL >= BOOT_LOG_LEVEL_DEBUG){\ - ets_printf("\033[1;32m[DEBUG][%s][%s][%d]\n" format "\r\n", __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ - ets_printf("\033[0m"); \ + ets_printf(LOG_BOLD(Green) "[DEBUG][%s][%s][%d]\n" format "\r\n", __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ + ets_printf(LOG_RESET_COLOR); \ }\ }while(0) @@ -86,4 +111,4 @@ extern "C" } #endif -#endif /* __BOOT_LOGGING_H__ */ \ No newline at end of file +#endif /* __BOOT_LOGGING_H__ */ diff --git a/components/bootloader/src/main/bootloader_start.c b/components/bootloader/src/main/bootloader_start.c index a25a266c08..2dbf0e8269 100644 --- a/components/bootloader/src/main/bootloader_start.c +++ b/components/bootloader/src/main/bootloader_start.c @@ -276,8 +276,6 @@ void bootloader_main() { //Run start routine. /*ESP32 2ND bootload start here*/ - - log_info( "\n" ); log_info( "**************************************" ); log_info( "* hello espressif ESP32! *" ); From 7ba471d53149635891fe58160ade22dbba9ee7e7 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Tue, 13 Sep 2016 13:48:28 +1000 Subject: [PATCH 43/51] esp32 cpu_start: Include rom/uart.h, remove inline ROM function declarations --- components/esp32/cpu_start.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/components/esp32/cpu_start.c b/components/esp32/cpu_start.c index 85d3009ef3..5d0b81e01d 100644 --- a/components/esp32/cpu_start.c +++ b/components/esp32/cpu_start.c @@ -18,6 +18,7 @@ #include "esp_err.h" #include "rom/ets_sys.h" +#include "rom/uart.h" #include "soc/dport_reg.h" #include "soc/io_mux_reg.h" @@ -59,11 +60,6 @@ We arrive here after the bootloader finished loading the program from flash. The flash cache is down and the app CPU is in reset. We do have a stack, so we can do the initialization in C. */ -void Uart_Init(int no); -void uartAttach(); -void ets_set_appcpu_boot_addr(uint32_t ent); -int ets_getAppEntry(); - static bool app_cpu_started = false; void IRAM_ATTR call_user_start_cpu0() { From ce2153c447d263df021f5f55bb351e62bb4231a7 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 13 Sep 2016 12:47:21 +0800 Subject: [PATCH 44/51] components/spi_flash: improve comments and readability --- components/spi_flash/esp_spi_flash.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/components/spi_flash/esp_spi_flash.c b/components/spi_flash/esp_spi_flash.c index a4e6c4c3ea..65d4c709dd 100644 --- a/components/spi_flash/esp_spi_flash.c +++ b/components/spi_flash/esp_spi_flash.c @@ -103,11 +103,14 @@ static void IRAM_ATTR spi_flash_disable_interrupts_caches_and_other_cpu() xSemaphoreTake(s_flash_op_mutex, portMAX_DELAY); const uint32_t cpuid = xPortGetCoreID(); - const uint32_t other_cpuid = !cpuid; + const uint32_t other_cpuid = (cpuid == 0) ? 1 : 0; if (xTaskGetSchedulerState() == taskSCHEDULER_NOT_STARTED) { - // Scheduler hasn't been started yet, so we don't need to worry - // about cached code running on the APP CPU. + // Scheduler hasn't been started yet, it means that spi_flash API is being + // called from the 2nd stage bootloader or from user_start_cpu0, i.e. from + // PRO CPU. APP CPU is either in reset or spinning inside user_start_cpu1, + // which is in IRAM. So it is safe to disable cache for the other_cpuid here. + assert(other_cpuid == 1); spi_flash_disable_cache(other_cpuid, &s_flash_op_cache_state[other_cpuid]); } else { // Signal to the spi_flash_op_block_task on the other CPU that we need it to @@ -132,13 +135,16 @@ static void IRAM_ATTR spi_flash_disable_interrupts_caches_and_other_cpu() static void IRAM_ATTR spi_flash_enable_interrupts_caches_and_other_cpu() { const uint32_t cpuid = xPortGetCoreID(); - const uint32_t other_cpuid = !cpuid; + const uint32_t other_cpuid = (cpuid == 0) ? 1 : 0; // Re-enable cache on this CPU spi_flash_restore_cache(cpuid, s_flash_op_cache_state[cpuid]); if (xTaskGetSchedulerState() == taskSCHEDULER_NOT_STARTED) { - // Scheduler is not running yet — just re-enable cache on APP CPU + // Scheduler is not running yet — this means we are running on PRO CPU. + // other_cpuid is APP CPU, and it is either in reset or is spinning in + // user_start_cpu1, which is in IRAM. So we can simply reenable cache. + assert(other_cpuid == 1); spi_flash_restore_cache(other_cpuid, s_flash_op_cache_state[other_cpuid]); } else { // Signal to spi_flash_op_block_task that flash operation is complete @@ -218,17 +224,21 @@ static esp_err_t spi_flash_translate_rc(SpiFlashOpResult rc) } } +static const uint32_t cache_mask = DPORT_APP_CACHE_MASK_OPSDRAM | DPORT_APP_CACHE_MASK_DROM0 | + DPORT_APP_CACHE_MASK_DRAM1 | DPORT_APP_CACHE_MASK_IROM0 | + DPORT_APP_CACHE_MASK_IRAM1 | DPORT_APP_CACHE_MASK_IRAM0; + static void IRAM_ATTR spi_flash_disable_cache(uint32_t cpuid, uint32_t* saved_state) { uint32_t ret = 0; if (cpuid == 0) { - ret |= GET_PERI_REG_BITS2(PRO_CACHE_CTRL1_REG, 0x1f, 0); + ret |= GET_PERI_REG_BITS2(PRO_CACHE_CTRL1_REG, cache_mask, 0); while (GET_PERI_REG_BITS2(PRO_DCACHE_DBUG_REG0, DPORT_PRO_CACHE_STATE, DPORT_PRO_CACHE_STATE_S) != 1) { ; } SET_PERI_REG_BITS(PRO_CACHE_CTRL_REG, 1, 0, DPORT_PRO_CACHE_ENABLE_S); } else { - ret |= GET_PERI_REG_BITS2(APP_CACHE_CTRL1_REG, 0x1f, 0); + ret |= GET_PERI_REG_BITS2(APP_CACHE_CTRL1_REG, cache_mask, 0); while (GET_PERI_REG_BITS2(APP_DCACHE_DBUG_REG0, DPORT_APP_CACHE_STATE, DPORT_APP_CACHE_STATE_S) != 1) { ; } @@ -241,9 +251,9 @@ static void IRAM_ATTR spi_flash_restore_cache(uint32_t cpuid, uint32_t saved_sta { if (cpuid == 0) { SET_PERI_REG_BITS(PRO_CACHE_CTRL_REG, 1, 1, DPORT_PRO_CACHE_ENABLE_S); - SET_PERI_REG_BITS(PRO_CACHE_CTRL1_REG, 0x1f, saved_state, 0); + SET_PERI_REG_BITS(PRO_CACHE_CTRL1_REG, cache_mask, saved_state, 0); } else { SET_PERI_REG_BITS(APP_CACHE_CTRL_REG, 1, 1, DPORT_APP_CACHE_ENABLE_S); - SET_PERI_REG_BITS(APP_CACHE_CTRL1_REG, 0x1f, saved_state, 0); + SET_PERI_REG_BITS(APP_CACHE_CTRL1_REG, cache_mask, saved_state, 0); } } From 29c6eab6dc93a0a9e4f00ca47fa311f663a84149 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 13 Sep 2016 15:16:36 +0800 Subject: [PATCH 45/51] components/spi_flash: call SPIUnlock only once This fixes the performance impact for spi_flash_write and spi_flash_erase. With this change, NVS init in single core mode takes about 50ms (compared to >2seconds before that). --- components/spi_flash/esp_spi_flash.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/components/spi_flash/esp_spi_flash.c b/components/spi_flash/esp_spi_flash.c index 65d4c709dd..b0a31e8201 100644 --- a/components/spi_flash/esp_spi_flash.c +++ b/components/spi_flash/esp_spi_flash.c @@ -178,11 +178,24 @@ static void IRAM_ATTR spi_flash_enable_interrupts_caches_and_other_cpu() #endif // CONFIG_FREERTOS_UNICORE +SpiFlashOpResult IRAM_ATTR spi_flash_unlock() +{ + static bool unlocked = false; + if (!unlocked) { + SpiFlashOpResult rc = SPIUnlock(); + if (rc != SPI_FLASH_RESULT_OK) { + return rc; + } + unlocked = true; + } + return SPI_FLASH_RESULT_OK; +} + esp_err_t IRAM_ATTR spi_flash_erase_sector(uint16_t sec) { spi_flash_disable_interrupts_caches_and_other_cpu(); SpiFlashOpResult rc; - rc = SPIUnlock(); + rc = spi_flash_unlock(); if (rc == SPI_FLASH_RESULT_OK) { rc = SPIEraseSector(sec); } @@ -194,7 +207,7 @@ esp_err_t IRAM_ATTR spi_flash_write(uint32_t dest_addr, const uint32_t *src, uin { spi_flash_disable_interrupts_caches_and_other_cpu(); SpiFlashOpResult rc; - rc = SPIUnlock(); + rc = spi_flash_unlock(); if (rc == SPI_FLASH_RESULT_OK) { rc = SPIWrite(dest_addr, src, (int32_t) size); } From b86e06064757bdd0698da1d325bf76189371e14c Mon Sep 17 00:00:00 2001 From: liuzhifu Date: Wed, 7 Sep 2016 17:29:08 +0800 Subject: [PATCH 46/51] add wifi api comments --- components/esp32/include/esp_wifi.h | 440 ++++++++++++++++++++++++++-- 1 file changed, 418 insertions(+), 22 deletions(-) diff --git a/components/esp32/include/esp_wifi.h b/components/esp32/include/esp_wifi.h index d21eb1b851..90ce0743fe 100755 --- a/components/esp32/include/esp_wifi.h +++ b/components/esp32/include/esp_wifi.h @@ -40,10 +40,10 @@ typedef enum { } wifi_interface_t; typedef enum { - WIFI_COUNTRY_CN = 0, - WIFI_COUNTRY_JP, - WIFI_COUNTRY_US, - WIFI_COUNTRY_EU, + WIFI_COUNTRY_CN = 0, /**< country China, channel range [1, 14] */ + WIFI_COUNTRY_JP, /**< country Japan, channel range [1, 14] */ + WIFI_COUNTRY_US, /**< country USA, channel range [1, 11] */ + WIFI_COUNTRY_EU, /**< country Europe, channel rane [1, 13] */ WIFI_COUNTRY_MAX } wifi_country_t; @@ -89,54 +89,203 @@ enum { }; typedef enum { - WIFI_SECOND_CHAN_NONE = 0, - WIFI_SECOND_CHAN_ABOVE, - WIFI_SECOND_CHAN_BELOW, + WIFI_SECOND_CHAN_NONE = 0, /**< the channel width is HT20 */ + WIFI_SECOND_CHAN_ABOVE, /**< the channel width is HT40 and the second channel is above the primary channel */ + WIFI_SECOND_CHAN_BELOW, /**< the channel width is HT40 and the second channel is below the primary channel */ } wifi_second_chan_t; +/** + * @brief startup wifi driver and register application specific callback function + * + * @attention 1. This API should be called in application startup code to init wifi driver + * @attention 2. The callback fuction is used to provide application specific wifi configuration, + * such as, set the wifi mode, register the event callback, set ap ssid etc before + * wifi is startup + * @attention 3. Avoid to create application task in the callback, otherwise you may get wrong behavior + * @attention 4. If the callback return is not ESP_OK, the startup will fail! + * @attention 5. Before this API can be called, system_init()/esp_event_init()/tcpip_adapter_init() should + * be called firstly + * + * @param wifi_startup_cb_t cb : application specific callback function + * + * @return ESP_OK : succeed + * @return others : fail + */ typedef esp_err_t (* wifi_startup_cb_t)(void); - void esp_wifi_startup(wifi_startup_cb_t cb); typedef struct { - void *event_q; + void *event_q; /**< Wifi event q handler, it's a freertos queue */ uint8_t rx_ba_win; /**< TBC */ uint8_t tx_ba_win; /**< TBC */ uint8_t rx_buf_cnt; /**< TBC */ uint8_t tx_buf_cnt; /**< TBC */ } wifi_init_config_t; +/** + * @brief Init wifi + * Alloc resource for wifi driver, such as wifi control structure, rx/tx buffer, + * wifi nvs structure etc, this wifi also start wifi task + * + * @attention 1. This API must be called before all other wifi api can be called + * @attention 2. Generally we should init event_q in *config, wifi driver will post the event + * to this queue when event happens, such as, when sta connects to api, wifi driver + * will post sta connected event to this queue. If the queue is not initialized, wifi + * will not post any events + * @attention 3. For other paramters, currently it's not ready, just ignore it. + * + * @param wifi_init_config_t *config : provide wifi init configuration + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_init(wifi_init_config_t *config); +/** + * @brief Deinit wifi + * Free all resource allocated in esp_wifi_init and stop wifi task + * + * @attention 1. This API should be called if you want to remove wifi driver from the system + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_deinit(void); +/** + * @brief Set the WiFi operating mode + * + * 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: + * + * @return ESP_OK : succeed + * @return others : fail + */ 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 + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_get_mode(wifi_mode_t *mode); +/** + * @brief Start wifi according to current configuration + * If mode is WIFI_MODE_STA, it create sta control block and start sta + * If mode is WIFI_MODE_AP, it create ap control block and start ap + * If mode is WIFI_MODE_APSTA, it create apd and sta control block and start ap and sta + * + * @param null + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_start(void); +/** + * @brief Stop wifi + If mode is WIFI_MODE_STA, it stop sta and free sta control block + * If mode is WIFI_MODE_AP, it stop ap and free ap control block + * If mode is WIFI_MODE_APSTA, it stop sta/ap and free sta/ap control block + * + * @param null + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_stop(void); +/** + * @brief Connect the ESP32 WiFi sta to the AP. + * + * @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 + * @return others : fail + */ esp_err_t esp_wifi_connect(void); +/** + * @brief Disconnect the ESP32 WiFi sta from the AP. + * + * @param null + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_disconnect(void); +/** + * @brief Currently this API is just an stub API + * + * @param null + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_clear_fast_connect(void); +/** + * @brief Kick the all sta or associated id equals to aid + * + * @param uint16_t aid : when aid is 0, kick all sta, otherwise kick sta whose associated id is aid + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_kick_station(uint16_t aid); typedef struct { char *ssid; /**< SSID of AP */ uint8_t *bssid; /**< MAC address of AP */ uint8_t channel; /**< channel, scan the specific channel */ - bool show_hidden; /**< enable to scan AP whose SSID is hidden */ + bool show_hidden; /**< enable to scan AP whose SSID is hidden */ } wifi_scan_config_t; +/** + * @brief Scan all available APs. + * + * @attention If this API is called, the found APs are stored in wifi driver dynamic allocated memory and the + * 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 + * it will return immeidately + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_scan_start(wifi_scan_config_t *conf, bool block); +/** + * @brief Stop the scan in process + * + * @param null + * @return ESP_OK : succeed + * @return others : fail + */ 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 + * + * @attention This API can only be called when the scan is completed, otherwise it may get wrong value + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_get_ap_num(uint16_t *number); typedef struct { @@ -148,54 +297,222 @@ typedef struct { wifi_auth_mode_t authmode; /**< authmode of AP */ }wifi_ap_list_t; +/** + * @brief Get AP list found in last scan + * + * @param uint16_t *number : as input param, it stores max AP number ap_list can hold, as output param, it store + the actual AP number this API returns + * @param wifi_ap_list_t *ap_list : a list to hold the found APs + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_get_ap_list(uint16_t *number, wifi_ap_list_t *ap_list); typedef enum { - WIFI_PS_NONE, - WIFI_PS_MODEM, - WIFI_PS_LIGHT, - WIFI_PS_MAC, + WIFI_PS_NONE, /**< No power save */ + WIFI_PS_MODEM, /**< Modem power save */ + WIFI_PS_LIGHT, /**< Light power save */ + WIFI_PS_MAC, /**< MAC power save */ } wifi_ps_type_t; +/** + * @brief Set current power save type + * + * @param wifi_ps_type_t type : power save type + * + * @return ESP_OK : succeed + * @return others : fail + */ 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 + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_get_ps(wifi_ps_type_t *type); #define WIFI_PROTOCOL_11B 1 #define WIFI_PROTOCOL_11G 2 #define WIFI_PROTOCOL_11N 4 -esp_err_t esp_wifi_set_protocol(wifi_interface_t ifx, uint8_t protocol); +/** + * @brief Set protocol type of specified interface + * The default protocol is (WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G|WIFI_PROTOCOL_11N) + * + * @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 + * + * @return ESP_OK : succeed + * @return others : fail + */ +esp_err_t esp_wifi_set_protocol(wifi_interface_t ifx, uint8_t protocol_bitmap); -esp_err_t esp_wifi_get_protocol(wifi_interface_t ifx, uint8_t *protocol); +/** + * @brief Get the current protocol bitmap of specified ifx + * + * @param wifi_interface_t ifx : interfaces + * @param uint8_t protocol : store current wifi protocol bitmap of interface ifx + * + * @return ESP_OK : succeed + * @return others : fail + */ +esp_err_t esp_wifi_get_protocol(wifi_interface_t ifx, uint8_t *protocol_bitmap); typedef enum { - WIFI_BW_HT20 = 0, - WIFI_BW_HT40, + WIFI_BW_HT20 = 0, /* Bandwidth is HT20 */ + WIFI_BW_HT40, /* Bandwidth is HT40 */ } wifi_bandwidth_t; +/** + * @brief Set the bandwidth of ESP32 specified interface + * + * @attention 1. API return false if try to configure a interface that is not enable + * @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 + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_set_bandwidth(wifi_interface_t ifx, wifi_bandwidth_t bw); +/** + * @brief Get the bandwidth of ESP32 specified interface + * + * @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 + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_get_bandwidth(wifi_interface_t ifx, wifi_bandwidth_t *bw); +/** + * @brief Set primary/second 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 + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_set_channel(uint8_t primary, wifi_second_chan_t second); +/** + * @brief Get the primary/second 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 + * + * @return ESP_OK : succeed + * @return others : fail + */ 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 + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_set_country(wifi_country_t country); +/** + * @brief Get country code + * + * @param wifi_country_t country : store current country + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_get_country(wifi_country_t *country); +/** + * @brief Set MAC address of the ESP32 WiFi station or the soft-AP interface. + * + * @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 + * 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. + * + * @return true : succeed + * @return false : fail + */ 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 + * + * @return ESP_OK : succeed + * @return others : fail + */ 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. + * + * @param uint8 *buf : the data received + * @param uint16 len : data length + * + * @return ESP_OK : succeed + * @return others : fail + */ 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. + * + * @param wifi_promiscuous_cb_t cb : callback + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_set_promiscuous_rx_cb(wifi_promiscuous_cb_t cb); +/** + * @brief Enable the promiscuous mode. + * + * @param uint8 promiscuous : 0 - disable / 1 - enable + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_set_promiscuous(uint8_t enable); +/** + * @brief Get the promiscuous mode. + * + * @param uint8 *enable : store the current status of promiscuous mode + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_get_promiscuous(uint8_t *enable); typedef struct { @@ -217,12 +534,35 @@ typedef struct { } wifi_sta_config_t; typedef union { - wifi_ap_config_t ap; - wifi_sta_config_t sta; + wifi_ap_config_t ap; /**< configuration of AP */ + wifi_sta_config_t sta; /**< configuration of STA */ } wifi_config_t; +/** + * @brief Set the configuration of the ESP32 STA or AP + * + * @attention 1. This api can be called only when specified interface is enabled, otherwise, API fail + * @attention 2. For sta configuration, bssid_set needs to be 0; and it needs to be 1 only when users need to check the MAC address of the AP. + * @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 : sta or ap configuration + * + * @return ESP_OK : succeed + * @return others : fail + */ 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 : sta or ap configuration + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_get_config(wifi_interface_t ifx, wifi_config_t *conf); struct station_info { @@ -230,23 +570,79 @@ struct station_info { uint8_t bssid[6]; }; +/** + * @brief Get STAs associated with soft-AP + * + * @attention SSC only API + * + * @param struct station_info **station : sta list + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_get_station_list(struct station_info **station); esp_err_t esp_wifi_free_station_list(void); typedef enum { - WIFI_STORAGE_FLASH, - WIFI_STORAGE_RAM, + WIFI_STORAGE_FLASH, /**< all configuration will strore in both memory and flash */ + WIFI_STORAGE_RAM, /**< all configuration will only store in the memory */ } wifi_storage_t; +/** + * @brief Set the wifi API configuration storage type + * + * @attention 1. The default value is WIFI_STORAGE_FLASH + * + * @param wifi_storage_t storage : storage type + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_set_storage(wifi_storage_t storage); +/** + * @brief Set the wifi API configuration storage type + * + * Each time the wifi need to forward the packets to high layer, the callback function will be called + * + */ typedef esp_err_t (*wifi_rxcb_t)(void *buffer, uint16_t len, void* eb); +/** + * @brief Set the wifi rx callback + * + * @attention 1. Currently we support only one rx callback for each interface + * + * @param wifi_interface_t ifx : interface + * @param wifi_rxcb_t fn : wifi rx callback + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_reg_rxcb(wifi_interface_t ifx, wifi_rxcb_t fn); +/** + * @brief Set auto connect + * The default value is true + * + * @attention 1. + * + * @param bool en : true - enable auto connect / false - disable auto connect + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_set_auto_connect(bool en); +/** + * @brief Get the auto connect flag + * + * @param bool *en : store current auto connect configuration + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_get_auto_connect(bool *en); #ifdef __cplusplus From ded5df7513e397c4e5cfe13fa34f4e9498cd3200 Mon Sep 17 00:00:00 2001 From: liuzhifu Date: Wed, 7 Sep 2016 20:33:13 +0800 Subject: [PATCH 47/51] add wifi api comments --- components/esp32/include/esp_event.h | 54 ++++++++++++++++++++++++++++ components/esp32/include/esp_wifi.h | 42 ++++++++++++++++++++++ 2 files changed, 96 insertions(+) diff --git a/components/esp32/include/esp_event.h b/components/esp32/include/esp_event.h index 04a53636bb..3fac1434f6 100755 --- a/components/esp32/include/esp_event.h +++ b/components/esp32/include/esp_event.h @@ -105,10 +105,64 @@ typedef struct { system_event_info_t event_info; /**< event information */ } system_event_t; +/** + * @brief Application specified event callback function + * + * @param system_event_t *event : event type defined in this file + * + * @return ESP_OK : succeed + * @return others : fail + */ typedef esp_err_t (*system_event_cb_t)(system_event_t *event); + +/** + * @brief Set application specified event callback function + * + * @attention 1. If cb is NULL, means application don't need to handle + * If cb is not NULL, it will be call when a event is received, after the default event callback is completed + * + * @param system_event_cb_t cb : callback + * + * @return ESP_OK : succeed + * @return others : fail + */ system_event_cb_t esp_event_set_cb(system_event_cb_t cb); + +/** + * @brief Send a event to event task + * + * @attention 1. Other task/module, such as TCPIP modudle, can call this API to send a event to event task + * + * + * @param system_event_t * event : event + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_event_send(system_event_t * event); + + +/** + * @brief Get the event handler + * + * @attention : currently this API returns event queue handler, generally this handler is used to + * + * + * @param null + * + * @return void* : event queue pointer + */ void* esp_event_get_handler(void); + +/** + * @brief Init the event module + * Create the event handler and task + * + * @param system_event_cb_t cb : application specified event callback, it can be modified by call esp_event_set_cb + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_event_init(system_event_cb_t cb); #ifdef __cplusplus diff --git a/components/esp32/include/esp_wifi.h b/components/esp32/include/esp_wifi.h index 90ce0743fe..faae0f95ac 100755 --- a/components/esp32/include/esp_wifi.h +++ b/components/esp32/include/esp_wifi.h @@ -12,6 +12,48 @@ // See the License for the specific language governing permissions and // limitations under the License. + +/* Notes about WiFi Programming + * + * The esp32 wifi programming model can be dipcts as following picture: + * + * + * default handler user handler + * ------------- --------------- --------------- + * | | event | | callback or | | + * | tcpip | ---------> | event | ----------> | application | + * | stack | | task | event | task | + * |-----------| |-------------| |-------------| + * /|\ | + * | | + * event | | + * | | + * | | + * --------------- | + * | | | + * | WiFi Driver |/__________________| + * | |\ API call + * | | + * |-------------| + * + * The wifi driver can be consider as black box, it knows nothing about the high layer code, such as + * TCPIP stack, application task, event task etc, all it can do is to receive API call from high laeyer + * or post event queue to a specified Queue, which is initilized by API esp_wifi_init(). + * + * The event task is a daemon task, which receives events from WiFi driver or from other subsystem, such + * as TCPIP stack, event task will call the default callback function on receiving the event. For example, + * on receiving event SYSTEM_EVENT_STA_CONNECTED, it will call tcpip_adapter_start() to start the DHCP + * client in it's default handler. + * + * Application can register it's owner event callback function by API esp_event_init, then the application callback + * function will be called after the default callback. Also, if application don't want to excute the callback + * in event task, what it need to do is to post the related event to application task in the application callback function. + * + * The application task (code) generally mix all these thing together, it call APIs to init the system/wifi and + * handle the events when necessary. + * + */ + #ifndef __ESP_WIFI_H__ #define __ESP_WIFI_H__ From c5f8396df4e1d3a25de24b9ba909b5249cf69f49 Mon Sep 17 00:00:00 2001 From: Wu Jian Gang Date: Mon, 12 Sep 2016 16:43:32 +0800 Subject: [PATCH 48/51] header: format and fix typos SYSTEM_EVENT_STA_GOTIP to SYSTEM_EVENT_STA_GOT_IP --- components/esp32/event.c | 6 +- components/esp32/include/esp_event.h | 39 ++--- components/esp32/include/esp_wifi.h | 164 +++++++++--------- components/tcpip_adapter/tcpip_adapter_lwip.c | 2 +- 4 files changed, 105 insertions(+), 106 deletions(-) mode change 100755 => 100644 components/esp32/include/esp_event.h mode change 100755 => 100644 components/esp32/include/esp_wifi.h diff --git a/components/esp32/event.c b/components/esp32/event.c index 92b751038d..811c76f7d4 100644 --- a/components/esp32/event.c +++ b/components/esp32/event.c @@ -65,7 +65,7 @@ static system_event_handle_t g_system_event_handle_table[] = { {SYSTEM_EVENT_STA_CONNECTED, system_event_sta_connected_handle_default}, {SYSTEM_EVENT_STA_DISCONNECTED, system_event_sta_disconnected_handle_default}, {SYSTEM_EVENT_STA_AUTHMODE_CHANGE, NULL}, - {SYSTEM_EVENT_STA_GOTIP, system_event_sta_gotip_default}, + {SYSTEM_EVENT_STA_GOT_IP, system_event_sta_gotip_default}, {SYSTEM_EVENT_AP_START, system_event_ap_start_handle_default}, {SYSTEM_EVENT_AP_STOP, system_event_ap_stop_handle_default}, {SYSTEM_EVENT_AP_STACONNECTED, NULL}, @@ -150,7 +150,7 @@ esp_err_t system_event_sta_connected_handle_default(system_event_t *event) system_event_t evt; //notify event - evt.event_id = SYSTEM_EVENT_STA_GOTIP; + evt.event_id = SYSTEM_EVENT_STA_GOT_IP; memcpy(&evt.event_info.got_ip.ip_info, &sta_ip, sizeof(tcpip_adapter_ip_info_t)); esp_event_send(&evt); @@ -234,7 +234,7 @@ static esp_err_t esp_system_event_debug(system_event_t *event) WIFI_DEBUG("SYSTEM_EVENT_STA_AUTHMODE_CHNAGE\nold_mode:%d, new_mode:%d\n", auth_change->old_mode, auth_change->new_mode); break; } - case SYSTEM_EVENT_STA_GOTIP: + case SYSTEM_EVENT_STA_GOT_IP: { system_event_sta_got_ip_t *got_ip; got_ip = &event->event_info.got_ip; diff --git a/components/esp32/include/esp_event.h b/components/esp32/include/esp_event.h old mode 100755 new mode 100644 index 3fac1434f6..145bea5913 --- a/components/esp32/include/esp_event.h +++ b/components/esp32/include/esp_event.h @@ -28,24 +28,24 @@ extern "C" { #endif typedef enum { - SYSTEM_EVENT_WIFI_READY = 0, /**< ESP32 wifi ready */ + SYSTEM_EVENT_WIFI_READY = 0, /**< ESP32 WiFi ready */ SYSTEM_EVENT_SCAN_DONE, /**< ESP32 finish scanning AP */ SYSTEM_EVENT_STA_START, /**< ESP32 station start */ - SYSTEM_EVENT_STA_STOP, /**< ESP32 station start */ + SYSTEM_EVENT_STA_STOP, /**< ESP32 station stop */ SYSTEM_EVENT_STA_CONNECTED, /**< ESP32 station connected to AP */ - SYSTEM_EVENT_STA_DISCONNECTED, /**< ESP32 station disconnected to AP */ + SYSTEM_EVENT_STA_DISCONNECTED, /**< ESP32 station disconnected from AP */ SYSTEM_EVENT_STA_AUTHMODE_CHANGE, /**< the auth mode of AP connected by ESP32 station changed */ - SYSTEM_EVENT_STA_GOTIP, /**< ESP32 station received IP address */ - SYSTEM_EVENT_AP_START, /**< ESP32 softap start */ - SYSTEM_EVENT_AP_STOP, /**< ESP32 softap start */ + SYSTEM_EVENT_STA_GOT_IP, /**< ESP32 station got IP from connected AP */ + SYSTEM_EVENT_AP_START, /**< ESP32 soft-AP start */ + SYSTEM_EVENT_AP_STOP, /**< ESP32 soft-AP stop */ SYSTEM_EVENT_AP_STACONNECTED, /**< a station connected to ESP32 soft-AP */ - SYSTEM_EVENT_AP_STADISCONNECTED, /**< a station disconnected to ESP32 soft-AP */ + SYSTEM_EVENT_AP_STADISCONNECTED, /**< a station disconnected from ESP32 soft-AP */ SYSTEM_EVENT_AP_PROBEREQRECVED, /**< Receive probe request packet in soft-AP interface */ SYSTEM_EVENT_MAX } system_event_id_t; typedef struct { - uint32_t status; /**< status of scanning APs*/ + uint32_t status; /**< status of scanning APs */ uint8_t number; uint8_t scan_id; } system_event_sta_scan_done_t; @@ -94,10 +94,10 @@ typedef union { system_event_sta_disconnected_t disconnected; /**< ESP32 station disconnected to AP */ system_event_sta_scan_done_t scan_done; /**< ESP32 station scan (APs) done */ system_event_sta_authmode_change_t auth_change; /**< the auth mode of AP ESP32 station connected to changed */ - system_event_sta_got_ip_t got_ip; + system_event_sta_got_ip_t got_ip; /**< ESP32 station got IP */ system_event_ap_staconnected_t sta_connected; /**< a station connected to ESP32 soft-AP */ system_event_ap_stadisconnected_t sta_disconnected; /**< a station disconnected to ESP32 soft-AP */ - system_event_ap_probe_req_rx_t ap_probereqrecved; /**< ESP32 softAP receive probe request packet */ + system_event_ap_probe_req_rx_t ap_probereqrecved; /**< ESP32 soft-AP receive probe request packet */ } system_event_info_t; typedef struct { @@ -118,8 +118,8 @@ typedef esp_err_t (*system_event_cb_t)(system_event_t *event); /** * @brief Set application specified event callback function * - * @attention 1. If cb is NULL, means application don't need to handle - * If cb is not NULL, it will be call when a event is received, after the default event callback is completed + * @attention 1. If cb is NULL, means application don't need to handle + * If cb is not NULL, it will be call when an event is received, after the default event callback is completed * * @param system_event_cb_t cb : callback * @@ -131,28 +131,27 @@ system_event_cb_t esp_event_set_cb(system_event_cb_t cb); /** * @brief Send a event to event task * - * @attention 1. Other task/module, such as TCPIP modudle, can call this API to send a event to event task - * + * @attention 1. Other task/modules, such as the TCPIP module, can call this API to send an event to event task + * * * @param system_event_t * event : event * * @return ESP_OK : succeed * @return others : fail */ -esp_err_t esp_event_send(system_event_t * event); - +esp_err_t esp_event_send(system_event_t *event); /** * @brief Get the event handler * - * @attention : currently this API returns event queue handler, generally this handler is used to - * + * @attention : currently this API returns event queue handler, generally this handler is used to + * * * @param null * - * @return void* : event queue pointer + * @return void* : event queue pointer */ -void* esp_event_get_handler(void); +void *esp_event_get_handler(void); /** * @brief Init the event module diff --git a/components/esp32/include/esp_wifi.h b/components/esp32/include/esp_wifi.h old mode 100755 new mode 100644 index faae0f95ac..cb7df6dcca --- a/components/esp32/include/esp_wifi.h +++ b/components/esp32/include/esp_wifi.h @@ -15,13 +15,13 @@ /* Notes about WiFi Programming * - * The esp32 wifi programming model can be dipcts as following picture: + * The esp32 WiFi programming model can be depicted as following picture: * * * default handler user handler - * ------------- --------------- --------------- - * | | event | | callback or | | - * | tcpip | ---------> | event | ----------> | application | + * ------------- --------------- --------------- + * | | event | | callback or | | + * | tcpip | ---------> | event | ----------> | application | * | stack | | task | event | task | * |-----------| |-------------| |-------------| * /|\ | @@ -35,23 +35,23 @@ * | |\ API call * | | * |-------------| - * - * The wifi driver can be consider as black box, it knows nothing about the high layer code, such as - * TCPIP stack, application task, event task etc, all it can do is to receive API call from high laeyer - * or post event queue to a specified Queue, which is initilized by API esp_wifi_init(). + * + * The WiFi driver can be consider as black box, it knows nothing about the high layer code, such as + * TCPIP stack, application task, event task etc, all it can do is to receive API call from high layer + * or post event queue to a specified Queue, which is initialized by API esp_wifi_init(). * * The event task is a daemon task, which receives events from WiFi driver or from other subsystem, such * as TCPIP stack, event task will call the default callback function on receiving the event. For example, * on receiving event SYSTEM_EVENT_STA_CONNECTED, it will call tcpip_adapter_start() to start the DHCP - * client in it's default handler. + * client in it's default handler. * - * Application can register it's owner event callback function by API esp_event_init, then the application callback - * function will be called after the default callback. Also, if application don't want to excute the callback - * in event task, what it need to do is to post the related event to application task in the application callback function. - * - * The application task (code) generally mix all these thing together, it call APIs to init the system/wifi and + * Application can register it's own event callback function by API esp_event_init, then the application callback + * function will be called after the default callback. Also, if application doesn't want to execute the callback + * in the event task, what it needs to do is to post the related event to application task in the application callback function. + * + * The application task (code) generally mixes all these thing together, it calls APIs to init the system/WiFi and * handle the events when necessary. - * + * */ #ifndef __ESP_WIFI_H__ @@ -85,7 +85,7 @@ typedef enum { WIFI_COUNTRY_CN = 0, /**< country China, channel range [1, 14] */ WIFI_COUNTRY_JP, /**< country Japan, channel range [1, 14] */ WIFI_COUNTRY_US, /**< country USA, channel range [1, 11] */ - WIFI_COUNTRY_EU, /**< country Europe, channel rane [1, 13] */ + WIFI_COUNTRY_EU, /**< country Europe, channel range [1, 13] */ WIFI_COUNTRY_MAX } wifi_country_t; @@ -137,12 +137,12 @@ typedef enum { } wifi_second_chan_t; /** - * @brief startup wifi driver and register application specific callback function + * @brief startup WiFi driver and register application specific callback function * - * @attention 1. This API should be called in application startup code to init wifi driver - * @attention 2. The callback fuction is used to provide application specific wifi configuration, - * such as, set the wifi mode, register the event callback, set ap ssid etc before - * wifi is startup + * @attention 1. This API should be called in application startup code to init WiFi driver + * @attention 2. The callback function is used to provide application specific WiFi configuration, + * such as, set the WiFi mode, register the event callback, set AP SSID etc before + * WiFi is startup * @attention 3. Avoid to create application task in the callback, otherwise you may get wrong behavior * @attention 4. If the callback return is not ESP_OK, the startup will fail! * @attention 5. Before this API can be called, system_init()/esp_event_init()/tcpip_adapter_init() should @@ -157,7 +157,7 @@ typedef esp_err_t (* wifi_startup_cb_t)(void); void esp_wifi_startup(wifi_startup_cb_t cb); typedef struct { - void *event_q; /**< Wifi event q handler, it's a freertos queue */ + void *event_q; /**< WiFi event q handler, it's a freeRTOS queue */ uint8_t rx_ba_win; /**< TBC */ uint8_t tx_ba_win; /**< TBC */ uint8_t rx_buf_cnt; /**< TBC */ @@ -165,29 +165,29 @@ typedef struct { } wifi_init_config_t; /** - * @brief Init wifi - * Alloc resource for wifi driver, such as wifi control structure, rx/tx buffer, - * wifi nvs structure etc, this wifi also start wifi task + * @brief Init WiFi + * Alloc resource for WiFi driver, such as WiFi control structure, RX/TX buffer, + * WiFi NVS structure etc, this WiFi also start WiFi task * - * @attention 1. This API must be called before all other wifi api can be called - * @attention 2. Generally we should init event_q in *config, wifi driver will post the event - * to this queue when event happens, such as, when sta connects to api, wifi driver - * will post sta connected event to this queue. If the queue is not initialized, wifi + * @attention 1. This API must be called before all other WiFi API can be called + * @attention 2. Generally we should init event_q in *config, WiFi driver will post the event + * to this queue when event happens, such as, when station connects to WiFi, WiFi driver + * will post station connected event to this queue. If the queue is not initialized, WiFi * will not post any events - * @attention 3. For other paramters, currently it's not ready, just ignore it. + * @attention 3. For other parameters, currently it's not ready, just ignore it. + * + * @param wifi_init_config_t *config : provide WiFi init configuration * - * @param wifi_init_config_t *config : provide wifi init configuration - * * @return ESP_OK : succeed * @return others : fail */ esp_err_t esp_wifi_init(wifi_init_config_t *config); /** - * @brief Deinit wifi - * Free all resource allocated in esp_wifi_init and stop wifi task + * @brief Deinit WiFi + * Free all resource allocated in esp_wifi_init and stop WiFi task * - * @attention 1. This API should be called if you want to remove wifi driver from the system + * @attention 1. This API should be called if you want to remove WiFi driver from the system * * @return ESP_OK : succeed * @return others : fail @@ -210,7 +210,7 @@ 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 wifi_mode_t *mode : store current WiFi mode * * @return ESP_OK : succeed * @return others : fail @@ -218,10 +218,10 @@ esp_err_t esp_wifi_set_mode(wifi_mode_t mode); esp_err_t esp_wifi_get_mode(wifi_mode_t *mode); /** - * @brief Start wifi according to current configuration - * If mode is WIFI_MODE_STA, it create sta control block and start sta - * If mode is WIFI_MODE_AP, it create ap control block and start ap - * If mode is WIFI_MODE_APSTA, it create apd and sta control block and start ap and sta + * @brief Start WiFi according to current configuration + * If mode is WIFI_MODE_STA, it create station control block and start station + * 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 * @@ -231,10 +231,10 @@ esp_err_t esp_wifi_get_mode(wifi_mode_t *mode); esp_err_t esp_wifi_start(void); /** - * @brief Stop wifi - If mode is WIFI_MODE_STA, it stop sta and free sta control block - * If mode is WIFI_MODE_AP, it stop ap and free ap control block - * If mode is WIFI_MODE_APSTA, it stop sta/ap and free sta/ap control block + * @brief Stop WiFi + 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 * @@ -244,7 +244,7 @@ esp_err_t esp_wifi_start(void); esp_err_t esp_wifi_stop(void); /** - * @brief Connect the ESP32 WiFi sta to the AP. + * @brief Connect the ESP32 WiFi station to the AP. * * @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. @@ -257,7 +257,7 @@ esp_err_t esp_wifi_stop(void); esp_err_t esp_wifi_connect(void); /** - * @brief Disconnect the ESP32 WiFi sta from the AP. + * @brief Disconnect the ESP32 WiFi station from the AP. * * @param null * @@ -277,9 +277,9 @@ esp_err_t esp_wifi_disconnect(void); esp_err_t esp_wifi_clear_fast_connect(void); /** - * @brief Kick the all sta or associated id equals to aid + * @brief Kick the all station or associated id equals to aid * - * @param uint16_t aid : when aid is 0, kick all sta, otherwise kick sta whose associated id is aid + * @param uint16_t aid : when aid is 0, kick all stations, otherwise kick station whose associated id is aid * * @return ESP_OK : succeed * @return others : fail @@ -296,13 +296,13 @@ typedef struct { /** * @brief Scan all available APs. * - * @attention If this API is called, the found APs are stored in wifi driver dynamic allocated memory and the + * @attention If this API is called, the found APs are stored in WiFi driver dynamic allocated memory and the * 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 - * it will return immeidately + * @param bool 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 * @return others : fail @@ -335,9 +335,9 @@ typedef struct { uint8_t ssid[32]; /**< SSID of AP */ uint8_t primary; /**< channel of AP */ wifi_second_chan_t second; /**< second channel of AP */ - signed char rssi; /**< signal strength of AP */ + int8_t rssi; /**< signal strength of AP */ wifi_auth_mode_t authmode; /**< authmode of AP */ -}wifi_ap_list_t; +} wifi_ap_list_t; /** * @brief Get AP list found in last scan @@ -359,7 +359,7 @@ typedef enum { } wifi_ps_type_t; /** - * @brief Set current power save type + * @brief Set current power save type * * @param wifi_ps_type_t type : power save type * @@ -387,9 +387,9 @@ esp_err_t esp_wifi_get_ps(wifi_ps_type_t *type); * The default protocol is (WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G|WIFI_PROTOCOL_11N) * * @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 wifi_interface_t ifx : interfaces + * @param uint8_t protocol : WiFi protocol bitmap * * @return ESP_OK : succeed * @return others : fail @@ -399,8 +399,8 @@ esp_err_t esp_wifi_set_protocol(wifi_interface_t ifx, uint8_t protocol_bitmap); /** * @brief Get the current protocol bitmap of specified ifx * - * @param wifi_interface_t ifx : interfaces - * @param uint8_t protocol : store current wifi protocol bitmap of interface ifx + * @param wifi_interface_t ifx : interfaces + * @param uint8_t protocol : store current WiFi protocol bitmap of interface ifx * * @return ESP_OK : succeed * @return others : fail @@ -494,7 +494,7 @@ esp_err_t esp_wifi_get_country(wifi_country_t *country); * - The bit0 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 wifi_interface_t ifx : interface * @param uint8 mac[6]: the MAC address. * * @return true : succeed @@ -517,8 +517,8 @@ esp_err_t esp_wifi_get_mac(wifi_interface_t ifx, uint8_t mac[6]); * * Each time a packet is received, the callback function will be called. * - * @param uint8 *buf : the data received - * @param uint16 len : data length + * @param void *buf : the data received + * @param uint16_t len : data length * * @return ESP_OK : succeed * @return others : fail @@ -540,7 +540,7 @@ esp_err_t esp_wifi_set_promiscuous_rx_cb(wifi_promiscuous_cb_t cb); /** * @brief Enable the promiscuous mode. * - * @param uint8 promiscuous : 0 - disable / 1 - enable + * @param uint8 promiscuous : 0 - disable / 1 - enable * * @return ESP_OK : succeed * @return others : fail @@ -565,7 +565,7 @@ typedef struct { wifi_auth_mode_t authmode; /**< Auth mode of ESP32 soft-AP. Do not support AUTH_WEP in soft-AP mode */ uint8_t ssid_hidden; /**< Broadcast SSID or not, default 0, broadcast the SSID */ uint8_t max_connection; /**< Max number of stations allowed to connect in, default 4, max 4 */ - uint16_t beacon_interval; /**< Beacon interval, 100 ~ 60000 ms, default 100 */ + uint16_t beacon_interval; /**< Beacon interval, 100 ~ 60000 ms, default 100 ms */ } wifi_ap_config_t; typedef struct { @@ -583,13 +583,13 @@ typedef union { /** * @brief Set the configuration of the ESP32 STA or AP * - * @attention 1. This api can be called only when specified interface is enabled, otherwise, API fail - * @attention 2. For sta configuration, bssid_set needs to be 0; and it needs to be 1 only when users need to check the MAC address of the AP. + * @attention 1. This API can be called only when specified interface is enabled, otherwise, API fail + * @attention 2. For station configuration, bssid_set needs to be 0; and it needs to be 1 only when users need to check the MAC address of the AP. * @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 : sta or ap configuration + * @param wifi_interface_t ifx : interface + * @param wifi_config_t *conf : station or soft-AP configuration * * @return ESP_OK : succeed * @return others : fail @@ -599,8 +599,8 @@ 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 : sta or ap configuration + * @param wifi_interface_t ifx : interface + * @param wifi_config_t *conf : station or soft-AP configuration * * @return ESP_OK : succeed * @return others : fail @@ -613,11 +613,11 @@ struct station_info { }; /** - * @brief Get STAs associated with soft-AP + * @brief Get STAs associated with soft-AP * * @attention SSC only API * - * @param struct station_info **station : sta list + * @param struct station_info **station : station list * * @return ESP_OK : succeed * @return others : fail @@ -632,7 +632,7 @@ typedef enum { } wifi_storage_t; /** - * @brief Set the wifi API configuration storage type + * @brief Set the WiFi API configuration storage type * * @attention 1. The default value is WIFI_STORAGE_FLASH * @@ -644,20 +644,20 @@ typedef enum { esp_err_t esp_wifi_set_storage(wifi_storage_t storage); /** - * @brief Set the wifi API configuration storage type + * @brief The WiFi RX callback function * - * Each time the wifi need to forward the packets to high layer, the callback function will be called + * Each time the WiFi need to forward the packets to high layer, the callback function will be called * */ -typedef esp_err_t (*wifi_rxcb_t)(void *buffer, uint16_t len, void* eb); +typedef esp_err_t (*wifi_rxcb_t)(void *buffer, uint16_t len, void *eb); /** - * @brief Set the wifi rx callback + * @brief Set the WiFi RX callback * - * @attention 1. Currently we support only one rx callback for each interface + * @attention 1. Currently we support only one RX callback for each interface * - * @param wifi_interface_t ifx : interface - * @param wifi_rxcb_t fn : wifi rx callback + * @param wifi_interface_t ifx : interface + * @param wifi_rxcb_t fn : WiFi RX callback * * @return ESP_OK : succeed * @return others : fail @@ -665,10 +665,10 @@ typedef esp_err_t (*wifi_rxcb_t)(void *buffer, uint16_t len, void* eb); esp_err_t esp_wifi_reg_rxcb(wifi_interface_t ifx, wifi_rxcb_t fn); /** - * @brief Set auto connect + * @brief Set auto connect * The default value is true * - * @attention 1. + * @attention 1. * * @param bool en : true - enable auto connect / false - disable auto connect * diff --git a/components/tcpip_adapter/tcpip_adapter_lwip.c b/components/tcpip_adapter/tcpip_adapter_lwip.c index 2facea578c..0f681d9135 100644 --- a/components/tcpip_adapter/tcpip_adapter_lwip.c +++ b/components/tcpip_adapter/tcpip_adapter_lwip.c @@ -454,7 +454,7 @@ static void tcpip_adapter_dhcpc_cb(void) ip4_addr_set(&ip_info->gw, ip_2_ip4(&netif->gw)); //notify event - evt.event_id = SYSTEM_EVENT_STA_GOTIP; + evt.event_id = SYSTEM_EVENT_STA_GOT_IP; memcpy(&evt.event_info.got_ip.ip_info, ip_info, sizeof(tcpip_adapter_ip_info_t)); esp_event_send(&evt); From c56a790f64b84d04b9e5dfec6d0f667f51bbaf8a Mon Sep 17 00:00:00 2001 From: Wu Jian Gang Date: Mon, 12 Sep 2016 17:25:51 +0800 Subject: [PATCH 49/51] header: callbacks use "void *" as arguments --- components/esp32/cpu_start.c | 4 ++-- components/esp32/include/esp_event.h | 7 +++---- components/esp32/include/esp_wifi.h | 2 +- components/esp32/wifi.c | 2 +- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/components/esp32/cpu_start.c b/components/esp32/cpu_start.c index e66ed10cb5..ec032c580b 100644 --- a/components/esp32/cpu_start.c +++ b/components/esp32/cpu_start.c @@ -198,7 +198,7 @@ static void do_global_ctors(void) { (*p)(); } -extern esp_err_t app_main(); +extern esp_err_t app_main(void *param); void user_start_cpu0(void) { ets_setup_syscalls(); @@ -223,7 +223,7 @@ void user_start_cpu0(void) { #include "esp_wifi.h" esp_wifi_startup(app_main); #else - app_main(); + app_main(NULL); #endif ets_printf("Starting scheduler on PRO CPU.\n"); diff --git a/components/esp32/include/esp_event.h b/components/esp32/include/esp_event.h index 145bea5913..b35d46e484 100644 --- a/components/esp32/include/esp_event.h +++ b/components/esp32/include/esp_event.h @@ -108,12 +108,12 @@ typedef struct { /** * @brief Application specified event callback function * - * @param system_event_t *event : event type defined in this file + * @param void *param : parameter passed to callback function * * @return ESP_OK : succeed * @return others : fail */ -typedef esp_err_t (*system_event_cb_t)(system_event_t *event); +typedef esp_err_t (*system_event_cb_t)(void *param); /** * @brief Set application specified event callback function @@ -123,8 +123,7 @@ typedef esp_err_t (*system_event_cb_t)(system_event_t *event); * * @param system_event_cb_t cb : callback * - * @return ESP_OK : succeed - * @return others : fail + * @return system_event_cb_t : old callback */ system_event_cb_t esp_event_set_cb(system_event_cb_t cb); diff --git a/components/esp32/include/esp_wifi.h b/components/esp32/include/esp_wifi.h index cb7df6dcca..8c127a1ff4 100644 --- a/components/esp32/include/esp_wifi.h +++ b/components/esp32/include/esp_wifi.h @@ -153,7 +153,7 @@ typedef enum { * @return ESP_OK : succeed * @return others : fail */ -typedef esp_err_t (* wifi_startup_cb_t)(void); +typedef esp_err_t (* wifi_startup_cb_t)(void *param); void esp_wifi_startup(wifi_startup_cb_t cb); typedef struct { diff --git a/components/esp32/wifi.c b/components/esp32/wifi.c index 5ac3c990b8..8a2a09376d 100644 --- a/components/esp32/wifi.c +++ b/components/esp32/wifi.c @@ -54,7 +54,7 @@ static void esp_wifi_task(void *pvParameters) } if (startup_cb) { - err = (*startup_cb)(); + err = (*startup_cb)(NULL); if (err != ESP_OK) { WIFI_DEBUG("startup_cb fail, ret=%d\n", err); break; From bf5e83a6ed1d4b36d2f00f897721c93831c7c4c3 Mon Sep 17 00:00:00 2001 From: Wu Jian Gang Date: Tue, 13 Sep 2016 15:57:11 +0800 Subject: [PATCH 50/51] callback: add a void* pointer with each callback also format event.c/wifi.c/esp_event.h/esp_wifi.h --- components/esp32/cpu_start.c | 6 +- components/esp32/event.c | 242 ++++++++++++++------------- components/esp32/include/esp_event.h | 13 +- components/esp32/include/esp_wifi.h | 6 +- components/esp32/wifi.c | 22 ++- 5 files changed, 155 insertions(+), 134 deletions(-) diff --git a/components/esp32/cpu_start.c b/components/esp32/cpu_start.c index ec032c580b..e1a5f027b7 100644 --- a/components/esp32/cpu_start.c +++ b/components/esp32/cpu_start.c @@ -198,7 +198,7 @@ static void do_global_ctors(void) { (*p)(); } -extern esp_err_t app_main(void *param); +extern esp_err_t app_main(void *ctx); void user_start_cpu0(void) { ets_setup_syscalls(); @@ -214,14 +214,14 @@ void user_start_cpu0(void) { system_init(); - esp_event_init(NULL); + esp_event_init(NULL, NULL); tcpip_adapter_init(); #endif #if CONFIG_WIFI_ENABLED && CONFIG_WIFI_AUTO_STARTUP #include "esp_wifi.h" - esp_wifi_startup(app_main); + esp_wifi_startup(app_main, NULL); #else app_main(NULL); #endif diff --git a/components/esp32/event.c b/components/esp32/event.c index 811c76f7d4..53ffd642eb 100644 --- a/components/esp32/event.c +++ b/components/esp32/event.c @@ -11,6 +11,7 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. + #include #include #include @@ -29,10 +30,13 @@ #define ESP32_WORKAROUND 1 #if CONFIG_WIFI_ENABLED +static bool event_init_flag = false; static xQueueHandle g_event_handler = NULL; -static system_event_cb_t g_event_handler_cb; -#define WIFI_DEBUG(...) +static system_event_cb_t g_event_handler_cb; +static void *g_event_ctx; + +#define WIFI_DEBUG(...) #define WIFI_API_CALL_CHECK(info, api_call, ret) \ do{\ esp_err_t __err = (api_call);\ @@ -43,6 +47,7 @@ do{\ } while(0) typedef esp_err_t (*system_event_handle_fn_t)(system_event_t *e); + typedef struct { system_event_id_t event_id; system_event_handle_fn_t event_handle; @@ -55,7 +60,7 @@ static esp_err_t system_event_sta_start_handle_default(system_event_t *event); static esp_err_t system_event_sta_stop_handle_default(system_event_t *event); static esp_err_t system_event_sta_connected_handle_default(system_event_t *event); static esp_err_t system_event_sta_disconnected_handle_default(system_event_t *event); -static esp_err_t system_event_sta_gotip_default(system_event_t *event); +static esp_err_t system_event_sta_got_ip_default(system_event_t *event); static system_event_handle_t g_system_event_handle_table[] = { {SYSTEM_EVENT_WIFI_READY, NULL}, @@ -65,7 +70,7 @@ static system_event_handle_t g_system_event_handle_table[] = { {SYSTEM_EVENT_STA_CONNECTED, system_event_sta_connected_handle_default}, {SYSTEM_EVENT_STA_DISCONNECTED, system_event_sta_disconnected_handle_default}, {SYSTEM_EVENT_STA_AUTHMODE_CHANGE, NULL}, - {SYSTEM_EVENT_STA_GOT_IP, system_event_sta_gotip_default}, + {SYSTEM_EVENT_STA_GOT_IP, system_event_sta_got_ip_default}, {SYSTEM_EVENT_AP_START, system_event_ap_start_handle_default}, {SYSTEM_EVENT_AP_STOP, system_event_ap_stop_handle_default}, {SYSTEM_EVENT_AP_STACONNECTED, NULL}, @@ -74,15 +79,15 @@ static system_event_handle_t g_system_event_handle_table[] = { {SYSTEM_EVENT_MAX, NULL}, }; -static esp_err_t system_event_sta_gotip_default(system_event_t *event) +static esp_err_t system_event_sta_got_ip_default(system_event_t *event) { extern esp_err_t esp_wifi_set_sta_ip(void); WIFI_API_CALL_CHECK("esp_wifi_set_sta_ip", esp_wifi_set_sta_ip(), ESP_OK); printf("ip: " IPSTR ", mask: " IPSTR ", gw: " IPSTR "\n", - IP2STR(&event->event_info.got_ip.ip_info.ip), - IP2STR(&event->event_info.got_ip.ip_info.netmask), - IP2STR(&event->event_info.got_ip.ip_info.gw)); + IP2STR(&event->event_info.got_ip.ip_info.ip), + IP2STR(&event->event_info.got_ip.ip_info.netmask), + IP2STR(&event->event_info.got_ip.ip_info.gw)); return ESP_OK; } @@ -132,7 +137,7 @@ esp_err_t system_event_sta_stop_handle_default(system_event_t *event) esp_err_t system_event_sta_connected_handle_default(system_event_t *event) { tcpip_adapter_dhcp_status_t status; - + WIFI_API_CALL_CHECK("esp_wifi_reg_rxcb", esp_wifi_reg_rxcb(WIFI_IF_STA, (wifi_rxcb_t)tcpip_adapter_sta_input), ESP_OK); tcpip_adapter_up(TCPIP_ADAPTER_IF_STA); @@ -172,7 +177,7 @@ esp_err_t system_event_sta_disconnected_handle_default(system_event_t *event) static esp_err_t esp_wifi_post_event_to_user(system_event_t *event) { if (g_event_handler_cb) { - return (*g_event_handler_cb)(event); + return (*g_event_handler_cb)(g_event_ctx, event); } return ESP_OK; @@ -187,102 +192,88 @@ static esp_err_t esp_system_event_debug(system_event_t *event) WIFI_DEBUG("received event: "); switch (event->event_id) { - case SYSTEM_EVENT_WIFI_READY: - { - WIFI_DEBUG("SYSTEM_EVENT_WIFI_READY\n"); - break; - } - case SYSTEM_EVENT_SCAN_DONE: - { - system_event_sta_scan_done_t *scan_done; - scan_done = &event->event_info.scan_done; - WIFI_DEBUG("SYSTEM_EVENT_SCAN_DONE\nstatus:%d, number:%d\n", scan_done->status, scan_done->number); - break; - } - case SYSTEM_EVENT_STA_START: - { - WIFI_DEBUG("SYSTEM_EVENT_STA_START\n"); - break; - } - case SYSTEM_EVENT_STA_STOP: - { - WIFI_DEBUG("SYSTEM_EVENT_STA_STOP\n"); - break; - } - case SYSTEM_EVENT_STA_CONNECTED: - { - system_event_sta_connected_t *connected; - connected = &event->event_info.connected; - WIFI_DEBUG("SYSTEM_EVENT_STA_CONNECTED\nssid:%s, ssid_len:%d, bssid:%02x:%02x:%02x:%02x:%02x:%02x, channel:%d, authmode:%d\n", \ - connected->ssid, connected->ssid_len, connected->bssid[0], connected->bssid[0], connected->bssid[1], \ - connected->bssid[3], connected->bssid[4], connected->bssid[5], connected->channel, connected->authmode); - break; - } - case SYSTEM_EVENT_STA_DISCONNECTED: - { - system_event_sta_disconnected_t *disconnected; - disconnected = &event->event_info.disconnected; - WIFI_DEBUG("SYSTEM_EVENT_STA_DISCONNECTED\nssid:%s, ssid_len:%d, bssid:%02x:%02x:%02x:%02x:%02x:%02x, reason:%d\n", \ - disconnected->ssid, disconnected->ssid_len, disconnected->bssid[0], disconnected->bssid[0], disconnected->bssid[1], \ - disconnected->bssid[3], disconnected->bssid[4], disconnected->bssid[5], disconnected->reason); - break; - } - case SYSTEM_EVENT_STA_AUTHMODE_CHANGE: - { - system_event_sta_authmode_change_t *auth_change; - auth_change = &event->event_info.auth_change; - WIFI_DEBUG("SYSTEM_EVENT_STA_AUTHMODE_CHNAGE\nold_mode:%d, new_mode:%d\n", auth_change->old_mode, auth_change->new_mode); - break; - } - case SYSTEM_EVENT_STA_GOT_IP: - { - system_event_sta_got_ip_t *got_ip; - got_ip = &event->event_info.got_ip; - WIFI_DEBUG("SYSTEM_EVENT_STA_GOTIP\n"); - break; - } - case SYSTEM_EVENT_AP_START: - { - WIFI_DEBUG("SYSTEM_EVENT_AP_START\n"); - break; - } - case SYSTEM_EVENT_AP_STOP: - { - WIFI_DEBUG("SYSTEM_EVENT_AP_STOP\n"); - break; - } - case SYSTEM_EVENT_AP_STACONNECTED: - { - system_event_ap_staconnected_t *staconnected; - staconnected = &event->event_info.sta_connected; - WIFI_DEBUG("SYSTEM_EVENT_AP_STACONNECTED\nmac:%02x:%02x:%02x:%02x:%02x:%02x, aid:%d\n", \ - staconnected->mac[0], staconnected->mac[0], staconnected->mac[1], \ - staconnected->mac[3], staconnected->mac[4], staconnected->mac[5], staconnected->aid); - break; - } - case SYSTEM_EVENT_AP_STADISCONNECTED: - { - system_event_ap_stadisconnected_t *stadisconnected; - stadisconnected = &event->event_info.sta_disconnected; - WIFI_DEBUG("SYSTEM_EVENT_AP_STADISCONNECTED\nmac:%02x:%02x:%02x:%02x:%02x:%02x, aid:%d\n", \ - stadisconnected->mac[0], stadisconnected->mac[0], stadisconnected->mac[1], \ - stadisconnected->mac[3], stadisconnected->mac[4], stadisconnected->mac[5], stadisconnected->aid); - break; - } - case SYSTEM_EVENT_AP_PROBEREQRECVED: - { - system_event_ap_probe_req_rx_t *ap_probereqrecved; - ap_probereqrecved = &event->event_info.ap_probereqrecved; - WIFI_DEBUG("SYSTEM_EVENT_AP_PROBEREQRECVED\nrssi:%d, mac:%02x:%02x:%02x:%02x:%02x:%02x\n", \ - ap_probereqrecved->rssi, ap_probereqrecved->mac[0], ap_probereqrecved->mac[0], ap_probereqrecved->mac[1], \ - ap_probereqrecved->mac[3], ap_probereqrecved->mac[4], ap_probereqrecved->mac[5]); - break; - } - default: - { - printf("Error: no such kind of event!\n"); - break; - } + case SYSTEM_EVENT_WIFI_READY: { + WIFI_DEBUG("SYSTEM_EVENT_WIFI_READY\n"); + break; + } + case SYSTEM_EVENT_SCAN_DONE: { + system_event_sta_scan_done_t *scan_done; + scan_done = &event->event_info.scan_done; + WIFI_DEBUG("SYSTEM_EVENT_SCAN_DONE\nstatus:%d, number:%d\n", scan_done->status, scan_done->number); + break; + } + case SYSTEM_EVENT_STA_START: { + WIFI_DEBUG("SYSTEM_EVENT_STA_START\n"); + break; + } + case SYSTEM_EVENT_STA_STOP: { + WIFI_DEBUG("SYSTEM_EVENT_STA_STOP\n"); + break; + } + case SYSTEM_EVENT_STA_CONNECTED: { + system_event_sta_connected_t *connected; + connected = &event->event_info.connected; + WIFI_DEBUG("SYSTEM_EVENT_STA_CONNECTED\nssid:%s, ssid_len:%d, bssid:%02x:%02x:%02x:%02x:%02x:%02x, channel:%d, authmode:%d\n", \ + connected->ssid, connected->ssid_len, connected->bssid[0], connected->bssid[0], connected->bssid[1], \ + connected->bssid[3], connected->bssid[4], connected->bssid[5], connected->channel, connected->authmode); + break; + } + case SYSTEM_EVENT_STA_DISCONNECTED: { + system_event_sta_disconnected_t *disconnected; + disconnected = &event->event_info.disconnected; + WIFI_DEBUG("SYSTEM_EVENT_STA_DISCONNECTED\nssid:%s, ssid_len:%d, bssid:%02x:%02x:%02x:%02x:%02x:%02x, reason:%d\n", \ + disconnected->ssid, disconnected->ssid_len, disconnected->bssid[0], disconnected->bssid[0], disconnected->bssid[1], \ + disconnected->bssid[3], disconnected->bssid[4], disconnected->bssid[5], disconnected->reason); + break; + } + case SYSTEM_EVENT_STA_AUTHMODE_CHANGE: { + system_event_sta_authmode_change_t *auth_change; + auth_change = &event->event_info.auth_change; + WIFI_DEBUG("SYSTEM_EVENT_STA_AUTHMODE_CHNAGE\nold_mode:%d, new_mode:%d\n", auth_change->old_mode, auth_change->new_mode); + break; + } + case SYSTEM_EVENT_STA_GOT_IP: { + system_event_sta_got_ip_t *got_ip; + got_ip = &event->event_info.got_ip; + WIFI_DEBUG("SYSTEM_EVENT_STA_GOTIP\n"); + break; + } + case SYSTEM_EVENT_AP_START: { + WIFI_DEBUG("SYSTEM_EVENT_AP_START\n"); + break; + } + case SYSTEM_EVENT_AP_STOP: { + WIFI_DEBUG("SYSTEM_EVENT_AP_STOP\n"); + break; + } + case SYSTEM_EVENT_AP_STACONNECTED: { + system_event_ap_staconnected_t *staconnected; + staconnected = &event->event_info.sta_connected; + WIFI_DEBUG("SYSTEM_EVENT_AP_STACONNECTED\nmac:%02x:%02x:%02x:%02x:%02x:%02x, aid:%d\n", \ + staconnected->mac[0], staconnected->mac[0], staconnected->mac[1], \ + staconnected->mac[3], staconnected->mac[4], staconnected->mac[5], staconnected->aid); + break; + } + case SYSTEM_EVENT_AP_STADISCONNECTED: { + system_event_ap_stadisconnected_t *stadisconnected; + stadisconnected = &event->event_info.sta_disconnected; + WIFI_DEBUG("SYSTEM_EVENT_AP_STADISCONNECTED\nmac:%02x:%02x:%02x:%02x:%02x:%02x, aid:%d\n", \ + stadisconnected->mac[0], stadisconnected->mac[0], stadisconnected->mac[1], \ + stadisconnected->mac[3], stadisconnected->mac[4], stadisconnected->mac[5], stadisconnected->aid); + break; + } + case SYSTEM_EVENT_AP_PROBEREQRECVED: { + system_event_ap_probe_req_rx_t *ap_probereqrecved; + ap_probereqrecved = &event->event_info.ap_probereqrecved; + WIFI_DEBUG("SYSTEM_EVENT_AP_PROBEREQRECVED\nrssi:%d, mac:%02x:%02x:%02x:%02x:%02x:%02x\n", \ + ap_probereqrecved->rssi, ap_probereqrecved->mac[0], ap_probereqrecved->mac[0], ap_probereqrecved->mac[1], \ + ap_probereqrecved->mac[3], ap_probereqrecved->mac[4], ap_probereqrecved->mac[5]); + break; + } + default: { + printf("Error: no such kind of event!\n"); + break; + } } return ESP_OK; @@ -296,8 +287,8 @@ static esp_err_t esp_system_event_handler(system_event_t *event) } esp_system_event_debug(event); - if ((event->event_id < SYSTEM_EVENT_MAX) && (event->event_id == g_system_event_handle_table[event->event_id].event_id)){ - if (g_system_event_handle_table[event->event_id].event_handle){ + if ((event->event_id < SYSTEM_EVENT_MAX) && (event->event_id == g_system_event_handle_table[event->event_id].event_id)) { + if (g_system_event_handle_table[event->event_id].event_handle) { WIFI_DEBUG("enter default callback\n"); g_system_event_handle_table[event->event_id].event_handle(event); WIFI_DEBUG("exit default callback\n"); @@ -317,42 +308,57 @@ static void esp_system_event_task(void *pvParameters) while (1) { if (xQueueReceive(g_event_handler, &evt, portMAX_DELAY) == pdPASS) { ret = esp_system_event_handler(&evt); - if (ret == ESP_FAIL) + if (ret == ESP_FAIL) { printf("esp wifi post event to user fail!\n"); + } } } } -system_event_cb_t esp_event_set_cb(system_event_cb_t cb) +system_event_cb_t esp_event_set_cb(system_event_cb_t cb, void *ctx) { system_event_cb_t old_cb = g_event_handler_cb; + g_event_handler_cb = cb; + g_event_ctx = ctx; + return old_cb; } esp_err_t esp_event_send(system_event_t *event) { portBASE_TYPE ret; - + ret = xQueueSendToBack((xQueueHandle)g_event_handler, event, 0); - if (pdPASS != ret){ - if (event) printf("e=%d f\n", event->event_id); - else printf("e null\n"); + + if (pdPASS != ret) { + if (event) { + printf("e=%d f\n", event->event_id); + } else { + printf("e null\n"); + } return ESP_FAIL; } return ESP_OK; } -void* esp_event_get_handler(void) +void *esp_event_get_handler(void) { - return (void*)g_event_handler; + return (void *)g_event_handler; } -esp_err_t esp_event_init(system_event_cb_t cb) +esp_err_t esp_event_init(system_event_cb_t cb, void *ctx) { - g_event_handler_cb = (system_event_cb_t)cb; + if (event_init_flag) { + return ESP_FAIL; + } + + g_event_handler_cb = cb; + g_event_ctx = ctx; + g_event_handler = xQueueCreate(CONFIG_WIFI_ENENT_QUEUE_SIZE, sizeof(system_event_t)); + xTaskCreatePinnedToCore(esp_system_event_task, "eventTask", CONFIG_WIFI_EVENT_TASK_STACK_SIZE, NULL, 5, NULL, 0); // TODO: rearrange task priority return ESP_OK; } diff --git a/components/esp32/include/esp_event.h b/components/esp32/include/esp_event.h index b35d46e484..5618139d40 100644 --- a/components/esp32/include/esp_event.h +++ b/components/esp32/include/esp_event.h @@ -108,12 +108,13 @@ typedef struct { /** * @brief Application specified event callback function * - * @param void *param : parameter passed to callback function + * @param void *ctx : reversed for user + * @param system_event_t *event : event type defined in this file * * @return ESP_OK : succeed * @return others : fail */ -typedef esp_err_t (*system_event_cb_t)(void *param); +typedef esp_err_t (*system_event_cb_t)(void *ctx, system_event_t *event); /** * @brief Set application specified event callback function @@ -122,17 +123,17 @@ typedef esp_err_t (*system_event_cb_t)(void *param); * If cb is not NULL, it will be call when an event is received, after the default event callback is completed * * @param system_event_cb_t cb : callback + * @param void *ctx : reversed for user * * @return system_event_cb_t : old callback */ -system_event_cb_t esp_event_set_cb(system_event_cb_t cb); +system_event_cb_t esp_event_set_cb(system_event_cb_t cb, void *ctx); /** * @brief Send a event to event task * * @attention 1. Other task/modules, such as the TCPIP module, can call this API to send an event to event task * - * * @param system_event_t * event : event * * @return ESP_OK : succeed @@ -145,7 +146,6 @@ esp_err_t esp_event_send(system_event_t *event); * * @attention : currently this API returns event queue handler, generally this handler is used to * - * * @param null * * @return void* : event queue pointer @@ -157,11 +157,12 @@ void *esp_event_get_handler(void); * Create the event handler and task * * @param system_event_cb_t cb : application specified event callback, it can be modified by call esp_event_set_cb + * @param void *ctx : reversed for user * * @return ESP_OK : succeed * @return others : fail */ -esp_err_t esp_event_init(system_event_cb_t cb); +esp_err_t esp_event_init(system_event_cb_t cb, void *ctx); #ifdef __cplusplus } diff --git a/components/esp32/include/esp_wifi.h b/components/esp32/include/esp_wifi.h index 8c127a1ff4..d44497afef 100644 --- a/components/esp32/include/esp_wifi.h +++ b/components/esp32/include/esp_wifi.h @@ -149,12 +149,14 @@ typedef enum { * be called firstly * * @param wifi_startup_cb_t cb : application specific callback function + * @param void *ctx : reversed for user * * @return ESP_OK : succeed * @return others : fail */ -typedef esp_err_t (* wifi_startup_cb_t)(void *param); -void esp_wifi_startup(wifi_startup_cb_t cb); +typedef esp_err_t (* wifi_startup_cb_t)(void *ctx); + +esp_err_t esp_wifi_startup(wifi_startup_cb_t cb, void *ctx); typedef struct { void *event_q; /**< WiFi event q handler, it's a freeRTOS queue */ diff --git a/components/esp32/wifi.c b/components/esp32/wifi.c index 8a2a09376d..9900069759 100644 --- a/components/esp32/wifi.c +++ b/components/esp32/wifi.c @@ -11,6 +11,7 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. + #include #include #include @@ -26,9 +27,12 @@ #if CONFIG_WIFI_ENABLED -static wifi_startup_cb_t startup_cb; +static bool wifi_startup_flag = false; -#define WIFI_DEBUG(...) +static wifi_startup_cb_t startup_cb; +static void *startup_ctx; + +#define WIFI_DEBUG(...) #define WIFI_API_CALL_CHECK(info, api_call, ret) \ do{\ esp_err_t __err = (api_call);\ @@ -54,7 +58,7 @@ static void esp_wifi_task(void *pvParameters) } if (startup_cb) { - err = (*startup_cb)(NULL); + err = (*startup_cb)(startup_ctx); if (err != ESP_OK) { WIFI_DEBUG("startup_cb fail, ret=%d\n", err); break; @@ -71,7 +75,7 @@ static void esp_wifi_task(void *pvParameters) wifi_mode_t mode; bool auto_connect; err = esp_wifi_get_mode(&mode); - if (err != ESP_OK){ + if (err != ESP_OK) { WIFI_DEBUG("esp_wifi_get_mode fail, ret=%d\n", err); } @@ -94,9 +98,17 @@ static void esp_wifi_task(void *pvParameters) vTaskDelete(NULL); } -void esp_wifi_startup(wifi_startup_cb_t cb) +esp_err_t esp_wifi_startup(wifi_startup_cb_t cb, void *ctx) { + if (wifi_startup_flag) { + return ESP_FAIL; + } + startup_cb = cb; + startup_ctx = ctx; + xTaskCreatePinnedToCore(esp_wifi_task, "wifiTask", 4096, NULL, 5, NULL, 0);// TODO: rearrange task priority + + return ESP_OK; } #endif From ed8e8848e3d7727ad83ff6589eff42c77f64ab1d Mon Sep 17 00:00:00 2001 From: Wu Jian Gang Date: Tue, 13 Sep 2016 20:54:20 +0800 Subject: [PATCH 51/51] fix typos --- components/esp32/include/esp_event.h | 11 ++++++----- components/esp32/include/esp_wifi.h | 2 +- components/lwip/core/ipv4/dhcp.c | 4 ++-- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/components/esp32/include/esp_event.h b/components/esp32/include/esp_event.h index 5618139d40..0b61b70219 100644 --- a/components/esp32/include/esp_event.h +++ b/components/esp32/include/esp_event.h @@ -108,7 +108,7 @@ typedef struct { /** * @brief Application specified event callback function * - * @param void *ctx : reversed for user + * @param void *ctx : reserved for user * @param system_event_t *event : event type defined in this file * * @return ESP_OK : succeed @@ -123,7 +123,7 @@ typedef esp_err_t (*system_event_cb_t)(void *ctx, system_event_t *event); * If cb is not NULL, it will be call when an event is received, after the default event callback is completed * * @param system_event_cb_t cb : callback - * @param void *ctx : reversed for user + * @param void *ctx : reserved for user * * @return system_event_cb_t : old callback */ @@ -144,11 +144,12 @@ esp_err_t esp_event_send(system_event_t *event); /** * @brief Get the event handler * - * @attention : currently this API returns event queue handler, generally this handler is used to + * @attention : currently this API returns event queue handler, by this event queue, + * users can notice when WiFi has done something like scanning done, connected to AP or disconnected from AP. * * @param null * - * @return void* : event queue pointer + * @return void * : event queue pointer */ void *esp_event_get_handler(void); @@ -157,7 +158,7 @@ void *esp_event_get_handler(void); * Create the event handler and task * * @param system_event_cb_t cb : application specified event callback, it can be modified by call esp_event_set_cb - * @param void *ctx : reversed for user + * @param void *ctx : reserved for user * * @return ESP_OK : succeed * @return others : fail diff --git a/components/esp32/include/esp_wifi.h b/components/esp32/include/esp_wifi.h index d44497afef..19ba856dea 100644 --- a/components/esp32/include/esp_wifi.h +++ b/components/esp32/include/esp_wifi.h @@ -149,7 +149,7 @@ typedef enum { * be called firstly * * @param wifi_startup_cb_t cb : application specific callback function - * @param void *ctx : reversed for user + * @param void *ctx : reserved for user * * @return ESP_OK : succeed * @return others : fail diff --git a/components/lwip/core/ipv4/dhcp.c b/components/lwip/core/ipv4/dhcp.c index cd780d00ae..1f3758fa91 100755 --- a/components/lwip/core/ipv4/dhcp.c +++ b/components/lwip/core/ipv4/dhcp.c @@ -712,10 +712,10 @@ void dhcp_cleanup(struct netif *netif) /* Espressif add start. */ -/** Set callback for dhcp, reversed parameter for future use. +/** Set callback for dhcp, reserved parameter for future use. * * @param netif the netif from which to remove the struct dhcp - * @param cb callback for chcp + * @param cb callback for dhcp */ void dhcp_set_cb(struct netif *netif, void (*cb)(void)) {