Merge branch 'master' into feature/freertos_static_buffers

This commit is contained in:
Ivan Grokhotkov 2016-10-27 12:38:35 +08:00
commit 50bd28353d
62 changed files with 1098 additions and 422 deletions

3
.gitignore vendored
View File

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

View File

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

20
Kconfig
View File

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

View File

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

View File

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

View File

@ -51,7 +51,7 @@ enum {
SPI_SPEED_20M, SPI_SPEED_20M,
SPI_SPEED_80M = 0xF SPI_SPEED_80M = 0xF
}; };
/*suppport flash size in esp32 */ /*supported flash sizes*/
enum { enum {
SPI_SIZE_1MB = 0, SPI_SIZE_1MB = 0,
SPI_SIZE_2MB, SPI_SIZE_2MB,

View File

@ -58,6 +58,7 @@ void IRAM_ATTR set_cache_and_start_app(uint32_t drom_addr,
uint32_t irom_load_addr, uint32_t irom_load_addr,
uint32_t irom_size, uint32_t irom_size,
uint32_t entry_addr); uint32_t entry_addr);
static void update_flash_config(struct flash_hdr* pfhdr);
void IRAM_ATTR call_start_cpu0() void IRAM_ATTR call_start_cpu0()
@ -258,7 +259,7 @@ void bootloader_main()
memset(&bs, 0, sizeof(bs)); memset(&bs, 0, sizeof(bs));
ESP_LOGI(TAG, "compile time " __TIME__ ); ESP_LOGI(TAG, "compile time " __TIME__ );
/* close watch dog here */ /* disable watch dog here */
REG_CLR_BIT( RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_FLASHBOOT_MOD_EN ); REG_CLR_BIT( RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_FLASHBOOT_MOD_EN );
REG_CLR_BIT( TIMG_WDTCONFIG0_REG(0), TIMG_WDT_FLASHBOOT_MOD_EN ); REG_CLR_BIT( TIMG_WDTCONFIG0_REG(0), TIMG_WDT_FLASHBOOT_MOD_EN );
SPIUnlock(); SPIUnlock();
@ -269,6 +270,8 @@ void bootloader_main()
print_flash_info(&fhdr); print_flash_info(&fhdr);
update_flash_config(&fhdr);
if (!load_partition_table(&bs, PARTITION_ADD)) { if (!load_partition_table(&bs, PARTITION_ADD)) {
ESP_LOGE(TAG, "load partition table error!"); ESP_LOGE(TAG, "load partition table error!");
return; return;
@ -364,7 +367,7 @@ void unpack_load_app(const partition_pos_t* partition)
uint32_t irom_size = 0; uint32_t irom_size = 0;
/* Reload the RTC memory sections whenever a non-deepsleep reset /* Reload the RTC memory sections whenever a non-deepsleep reset
is occuring */ is occurring */
bool load_rtc_memory = rtc_get_reset_reason(0) != DEEPSLEEP_RESET; bool load_rtc_memory = rtc_get_reset_reason(0) != DEEPSLEEP_RESET;
ESP_LOGD(TAG, "bin_header: %u %u %u %u %08x", image_header.magic, ESP_LOGD(TAG, "bin_header: %u %u %u %u %08x", image_header.magic,
@ -482,6 +485,36 @@ void IRAM_ATTR set_cache_and_start_app(
(*entry)(); (*entry)();
} }
static void update_flash_config(struct flash_hdr* pfhdr)
{
uint32_t size;
switch(pfhdr->spi_size) {
case SPI_SIZE_1MB:
size = 1;
break;
case SPI_SIZE_2MB:
size = 2;
break;
case SPI_SIZE_4MB:
size = 4;
break;
case SPI_SIZE_8MB:
size = 8;
break;
case SPI_SIZE_16MB:
size = 16;
break;
default:
size = 2;
}
Cache_Read_Disable( 0 );
// Set flash chip size
SPIParamCfg(g_rom_flashchip.deviceId, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff);
// TODO: set mode
// TODO: set frequency
Cache_Flush(0);
Cache_Read_Enable( 0 );
}
void print_flash_info(struct flash_hdr* pfhdr) void print_flash_info(struct flash_hdr* pfhdr)
{ {

View File

@ -63,10 +63,22 @@ config MEMMAP_TRACEMEM
of memory that can't be used for general purposes anymore. Disable this if you do not know of memory that can't be used for general purposes anymore. Disable this if you do not know
what this is. what this is.
config MEMMAP_TRACEMEM_TWOBANKS
bool "Reserve memory for tracing both pro as well as app cpu execution"
default "n"
depends on MEMMAP_TRACEMEM && MEMMAP_SMP
help
The ESP32 contains a feature which allows you to trace the execution path the processor
has taken through the program. This is stored in a chunk of 32K (16K for single-processor)
of memory that can't be used for general purposes anymore. Disable this if you do not know
what this is.
# Memory to reverse for trace, used in linker script # Memory to reverse for trace, used in linker script
config TRACEMEM_RESERVE_DRAM config TRACEMEM_RESERVE_DRAM
hex hex
default 0x8000 if MEMMAP_TRACEMEM default 0x8000 if MEMMAP_TRACEMEM && MEMMAP_TRACEMEM_TWOBANKS
default 0x4000 if MEMMAP_TRACEMEM && !MEMMAP_TRACEMEM_TWOBANKS
default 0x0 default 0x0
config MEMMAP_SPISRAM config MEMMAP_SPISRAM

View File

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

View File

@ -43,6 +43,8 @@
#include "esp_ipc.h" #include "esp_ipc.h"
#include "esp_log.h" #include "esp_log.h"
#include "trax.h"
void start_cpu0(void) __attribute__((weak, alias("start_cpu0_default"))); void start_cpu0(void) __attribute__((weak, alias("start_cpu0_default")));
void start_cpu0_default(void) IRAM_ATTR; void start_cpu0_default(void) IRAM_ATTR;
#if !CONFIG_FREERTOS_UNICORE #if !CONFIG_FREERTOS_UNICORE
@ -131,6 +133,15 @@ void IRAM_ATTR call_start_cpu1()
void start_cpu0_default(void) void start_cpu0_default(void)
{ {
//Enable trace memory and immediately start trace.
#if CONFIG_MEMMAP_TRACEMEM
#if CONFIG_MEMMAP_TRACEMEM_TWOBANKS
trax_enable(TRAX_ENA_PRO_APP);
#else
trax_enable(TRAX_ENA_PRO);
#endif
trax_start_trace(TRAX_DOWNCOUNT_WORDS);
#endif
esp_set_cpu_freq(); // set CPU frequency configured in menuconfig esp_set_cpu_freq(); // set CPU frequency configured in menuconfig
uart_div_modify(0, (APB_CLK_FREQ << 4) / 115200); uart_div_modify(0, (APB_CLK_FREQ << 4) / 115200);
ets_setup_syscalls(); ets_setup_syscalls();
@ -147,6 +158,9 @@ void start_cpu0_default(void)
#if !CONFIG_FREERTOS_UNICORE #if !CONFIG_FREERTOS_UNICORE
void start_cpu1_default(void) void start_cpu1_default(void)
{ {
#if CONFIG_MEMMAP_TRACEMEM_TWOBANKS
trax_start_trace(TRAX_DOWNCOUNT_WORDS);
#endif
// Wait for FreeRTOS initialization to finish on PRO CPU // Wait for FreeRTOS initialization to finish on PRO CPU
while (port_xSchedulerRunning[0] == 0) { while (port_xSchedulerRunning[0] == 0) {
; ;

View File

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

View File

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

View File

@ -0,0 +1,80 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*
* All the APIs declared here are internal only APIs, it can only be used by
* espressif internal modules, such as SSC, LWIP, TCPIP adapter etc, espressif
* customers are not recommended to use them.
*
* If someone really want to use specified APIs declared in here, please contact
* espressif AE/developer to make sure you know the limitations or risk of
* the API, otherwise you may get unexpected behavior!!!
*
*/
#ifndef __ESP_WIFI_INTERNAL_H__
#define __ESP_WIFI_INTERNAL_H__
#include <stdint.h>
#include <stdbool.h>
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "rom/queue.h"
#include "esp_err.h"
#include "esp_wifi_types.h"
#include "esp_event.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief get whether the wifi driver is allowed to transmit data or not
*
* @param none
*
* @return true : upper layer should stop to transmit data to wifi driver
* @return false : upper layer can transmit data to wifi driver
*/
bool esp_wifi_internal_tx_is_stop(void);
/**
* @brief free the rx buffer which allocated by wifi driver
*
* @param void* buffer: rx buffer pointer
*
* @return nonoe
*/
void esp_wifi_internal_free_rx_buffer(void* buffer);
/**
* @brief transmit the buffer via wifi driver
*
* @attention1 TODO should modify the return type from bool to int
*
* @param wifi_interface_t wifi_if : wifi interface id
* @param void *buffer : the buffer to be tansmit
* @param u16_t len : the length of buffer
*
* @return True : success transmit the buffer to wifi driver
* False : failed to transmit the buffer to wifi driver
*/
bool esp_wifi_internal_tx(wifi_interface_t wifi_if, void *buffer, u16_t len);
#ifdef __cplusplus
}
#endif
#endif /* __ESP_WIFI_H__ */

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

@ -192,8 +192,14 @@ void vPortEndScheduler( void ) PRIVILEGED_FUNCTION;
#endif #endif
/* Multi-core: get current core ID */ /* Multi-core: get current core ID */
int xPortGetCoreID( void ); static inline uint32_t xPortGetCoreID() {
int id;
asm volatile(
"rsr.prid %0\n"
" extui %0,%0,13,1"
:"=r"(id));
return id;
}
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

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

View File

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

View File

@ -76,7 +76,6 @@ inline static void panicPutHex(int a) { }
inline static void panicPutDec(int a) { } inline static void panicPutDec(int a) { }
#endif #endif
int xPortGetCoreID();
void __attribute__((weak)) vApplicationStackOverflowHook( TaskHandle_t xTask, signed char *pcTaskName ) { void __attribute__((weak)) vApplicationStackOverflowHook( TaskHandle_t xTask, signed char *pcTaskName ) {
panicPutStr("***ERROR*** A stack overflow in task "); panicPutStr("***ERROR*** A stack overflow in task ");

View File

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

View File

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

View File

@ -3913,9 +3913,8 @@ In fact, nothing below this line has/is.
/* Gotcha (which seems to be deliberate in FreeRTOS, according to /* Gotcha (which seems to be deliberate in FreeRTOS, according to
http://www.freertos.org/FreeRTOS_Support_Forum_Archive/December_2012/freertos_PIC32_Bug_-_vTaskEnterCritical_6400806.html http://www.freertos.org/FreeRTOS_Support_Forum_Archive/December_2012/freertos_PIC32_Bug_-_vTaskEnterCritical_6400806.html
) is that calling vTaskEnterCritical followed by vTaskExitCritical will leave the interrupts DISABLED! Re-enabling the ) is that calling vTaskEnterCritical followed by vTaskExitCritical will leave the interrupts DISABLED when the scheduler
scheduler will re-enable the interrupts instead. */ is not running. Re-enabling the scheduler will re-enable the interrupts instead. */
#if ( portCRITICAL_NESTING_IN_TCB == 1 ) #if ( portCRITICAL_NESTING_IN_TCB == 1 )

View File

@ -904,16 +904,13 @@ _xt_coproc_exc:
core we're running on now. */ core we're running on now. */
movi a2, pxCurrentTCB movi a2, pxCurrentTCB
getcoreid a3 getcoreid a3
slli a3, a3, 2 addx4 a2, a3, a2
add a2, a2, a3
l32i a2, a2, 0 /* a2 = start of pxCurrentTCB[cpuid] */ l32i a2, a2, 0 /* a2 = start of pxCurrentTCB[cpuid] */
addi a2, a2, TASKTCB_XCOREID_OFFSET /* offset to xCoreID in tcb struct */ addi a2, a2, TASKTCB_XCOREID_OFFSET /* offset to xCoreID in tcb struct */
getcoreid a3
s32i a3, a2, 0 /* store current cpuid */ s32i a3, a2, 0 /* store current cpuid */
/* Grab correct xt_coproc_owner_sa for this core */ /* Grab correct xt_coproc_owner_sa for this core */
getcoreid a2 movi a2, XCHAL_CP_MAX << 2
movi a3, XCHAL_CP_MAX << 2
mull a2, a2, a3 mull a2, a2, a3
movi a3, _xt_coproc_owner_sa /* a3 = base of owner array */ movi a3, _xt_coproc_owner_sa /* a3 = base of owner array */
add a3, a3, a2 add a3, a3, a2

View File

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

View File

@ -314,8 +314,8 @@ poll_tcp(void *arg, struct tcp_pcb *pcb)
if (conn->flags & NETCONN_FLAG_CHECK_WRITESPACE) { if (conn->flags & NETCONN_FLAG_CHECK_WRITESPACE) {
/* If the queued byte- or pbuf-count drops below the configured low-water limit, /* If the queued byte- or pbuf-count drops below the configured low-water limit,
let select mark this pcb as writable again. */ let select mark this pcb as writable again. */
if ((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT) && if ((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT(conn->pcb.tcp)) &&
(tcp_sndqueuelen(conn->pcb.tcp) < TCP_SNDQUEUELOWAT)) { (tcp_sndqueuelen(conn->pcb.tcp) < TCP_SNDQUEUELOWAT(conn->pcb.tcp))) {
conn->flags &= ~NETCONN_FLAG_CHECK_WRITESPACE; conn->flags &= ~NETCONN_FLAG_CHECK_WRITESPACE;
API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0);
} }
@ -348,8 +348,8 @@ sent_tcp(void *arg, struct tcp_pcb *pcb, u16_t len)
/* If the queued byte- or pbuf-count drops below the configured low-water limit, /* If the queued byte- or pbuf-count drops below the configured low-water limit,
let select mark this pcb as writable again. */ let select mark this pcb as writable again. */
if ((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT) && if ((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT(conn->pcb.tcp) &&
(tcp_sndqueuelen(conn->pcb.tcp) < TCP_SNDQUEUELOWAT)) { (tcp_sndqueuelen(conn->pcb.tcp) < TCP_SNDQUEUELOWAT(conn->pcb.tcp)))) {
conn->flags &= ~NETCONN_FLAG_CHECK_WRITESPACE; conn->flags &= ~NETCONN_FLAG_CHECK_WRITESPACE;
API_EVENT(conn, NETCONN_EVT_SENDPLUS, len); API_EVENT(conn, NETCONN_EVT_SENDPLUS, len);
} }
@ -1540,8 +1540,8 @@ err_mem:
and let poll_tcp check writable space to mark the pcb writable again */ and let poll_tcp check writable space to mark the pcb writable again */
API_EVENT(conn, NETCONN_EVT_SENDMINUS, len); API_EVENT(conn, NETCONN_EVT_SENDMINUS, len);
conn->flags |= NETCONN_FLAG_CHECK_WRITESPACE; conn->flags |= NETCONN_FLAG_CHECK_WRITESPACE;
} else if ((tcp_sndbuf(conn->pcb.tcp) <= TCP_SNDLOWAT) || } else if ((tcp_sndbuf(conn->pcb.tcp) <= TCP_SNDLOWAT(conn->pcb.tcp)) ||
(tcp_sndqueuelen(conn->pcb.tcp) >= TCP_SNDQUEUELOWAT)) { (tcp_sndqueuelen(conn->pcb.tcp) >= TCP_SNDQUEUELOWAT(conn->pcb.tcp))) {
/* The queued byte- or pbuf-count exceeds the configured low-water limit, /* The queued byte- or pbuf-count exceeds the configured low-water limit,
let select mark this pcb as non-writable. */ let select mark this pcb as non-writable. */
API_EVENT(conn, NETCONN_EVT_SENDMINUS, len); API_EVENT(conn, NETCONN_EVT_SENDMINUS, len);

View File

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

View File

@ -388,10 +388,8 @@ static void lwip_socket_drop_registered_memberships(int s);
#endif /* LWIP_IGMP */ #endif /* LWIP_IGMP */
#ifdef LWIP_ESP8266 #ifdef LWIP_ESP8266
#include "esp_wifi_internal.h"
/* Since esp_wifi_tx_is_stop/system_get_free_heap_size are not an public wifi API, so extern them here*/ #include "esp_system.h"
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. /* 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 * Under UDP/TCP pressure test, we found that the sockets may cause wifi tx queue full if the socket
@ -402,9 +400,9 @@ extern bool esp_wifi_tx_is_stop(void);
*/ */
static inline void esp32_tx_flow_ctrl(void) static inline void esp32_tx_flow_ctrl(void)
{ {
uint8_t _wait_delay = 0; uint8_t _wait_delay = 1;
while ((system_get_free_heap_size() < HEAP_HIGHWAT) || esp_wifi_tx_is_stop()){ while ((system_get_free_heap_size() < HEAP_HIGHWAT) || esp_wifi_internal_tx_is_stop()){
vTaskDelay(_wait_delay/portTICK_RATE_MS); vTaskDelay(_wait_delay/portTICK_RATE_MS);
if (_wait_delay < 64) _wait_delay *= 2; if (_wait_delay < 64) _wait_delay *= 2;
} }
@ -2395,6 +2393,16 @@ lwip_getsockopt_impl(int s, int level, int optname, void *optval, socklen_t *opt
s, *(int *)optval)); s, *(int *)optval));
break; break;
#endif /* LWIP_TCP_KEEPALIVE */ #endif /* LWIP_TCP_KEEPALIVE */
#if ESP_PER_SOC_TCP_WND
case TCP_WINDOW:
*(int*)optval = (int)sock->conn->pcb.tcp->per_soc_tcp_wnd;
break;
case TCP_SNDBUF:
*(int*)optval = (int)sock->conn->pcb.tcp->per_soc_tcp_snd_buf;
break;
#endif
default: default:
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n", LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n",
s, optname)); s, optname));
@ -2792,6 +2800,16 @@ lwip_setsockopt_impl(int s, int level, int optname, const void *optval, socklen_
s, sock->conn->pcb.tcp->keep_cnt)); s, sock->conn->pcb.tcp->keep_cnt));
break; break;
#endif /* LWIP_TCP_KEEPALIVE */ #endif /* LWIP_TCP_KEEPALIVE */
#if ESP_PER_SOC_TCP_WND
case TCP_WINDOW:
sock->conn->pcb.tcp->per_soc_tcp_wnd = ((u32_t)(*(const int*)optval)) * TCP_MSS;
break;
case TCP_SNDBUF:
sock->conn->pcb.tcp->per_soc_tcp_snd_buf = ((u32_t)(*(const int*)optval)) * TCP_MSS;
break;
#endif
default: default:
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n", LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n",
s, optname)); s, optname));

View File

@ -135,13 +135,15 @@
//#endif //#endif
#else /* LWIP_WND_SCALE */ #else /* LWIP_WND_SCALE */
#ifndef LWIP_ESP8266 #if (ESP_PER_SOC_TCP_WND == 0)
#if (LWIP_TCP && (TCP_WND > 0xffff)) #if (LWIP_TCP && (TCP_WND > 0xffff))
#error "If you want to use TCP, TCP_WND must fit in an u16_t, so, you have to reduce it in your lwipopts.h (or enable window scaling)" #error "If you want to use TCP, TCP_WND must fit in an u16_t, so, you have to reduce it in your lwipopts.h (or enable window scaling)"
#endif #endif
#endif #endif
#endif /* LWIP_WND_SCALE */ #endif /* LWIP_WND_SCALE */
#if (ESP_PER_SOC_TCP_WND == 0)
#if (LWIP_TCP && (TCP_SND_QUEUELEN > 0xffff)) #if (LWIP_TCP && (TCP_SND_QUEUELEN > 0xffff))
#error "If you want to use TCP, TCP_SND_QUEUELEN must fit in an u16_t, so, you have to reduce it in your lwipopts.h" #error "If you want to use TCP, TCP_SND_QUEUELEN must fit in an u16_t, so, you have to reduce it in your lwipopts.h"
#endif #endif
@ -149,7 +151,6 @@
#error "TCP_SND_QUEUELEN must be at least 2 for no-copy TCP writes to work" #error "TCP_SND_QUEUELEN must be at least 2 for no-copy TCP writes to work"
#endif #endif
#ifndef LWIP_ESP8266
#if (LWIP_TCP && ((TCP_MAXRTX > 12) || (TCP_SYNMAXRTX > 12))) #if (LWIP_TCP && ((TCP_MAXRTX > 12) || (TCP_SYNMAXRTX > 12)))
#error "If you want to use TCP, TCP_MAXRTX and TCP_SYNMAXRTX must less or equal to 12 (due to tcp_backoff table), so, you have to reduce them in your lwipopts.h" #error "If you want to use TCP, TCP_MAXRTX and TCP_SYNMAXRTX must less or equal to 12 (due to tcp_backoff table), so, you have to reduce them in your lwipopts.h"
#endif #endif
@ -289,6 +290,8 @@
#if !MEMP_MEM_MALLOC && (MEMP_NUM_TCP_SEG < TCP_SND_QUEUELEN) #if !MEMP_MEM_MALLOC && (MEMP_NUM_TCP_SEG < TCP_SND_QUEUELEN)
#error "lwip_sanity_check: WARNING: MEMP_NUM_TCP_SEG should be at least as big as TCP_SND_QUEUELEN. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." #error "lwip_sanity_check: WARNING: MEMP_NUM_TCP_SEG should be at least as big as TCP_SND_QUEUELEN. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
#endif #endif
#if (ESP_PER_SOC_TCP_WND == 0)
#if TCP_SND_BUF < (2 * TCP_MSS) #if TCP_SND_BUF < (2 * TCP_MSS)
#error "lwip_sanity_check: WARNING: TCP_SND_BUF must be at least as much as (2 * TCP_MSS) for things to work smoothly. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." #error "lwip_sanity_check: WARNING: TCP_SND_BUF must be at least as much as (2 * TCP_MSS) for things to work smoothly. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
#endif #endif
@ -304,6 +307,8 @@
#if TCP_SNDQUEUELOWAT >= TCP_SND_QUEUELEN #if TCP_SNDQUEUELOWAT >= TCP_SND_QUEUELEN
#error "lwip_sanity_check: WARNING: TCP_SNDQUEUELOWAT must be less than TCP_SND_QUEUELEN. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." #error "lwip_sanity_check: WARNING: TCP_SNDQUEUELOWAT must be less than TCP_SND_QUEUELEN. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
#endif #endif
#endif
#if !MEMP_MEM_MALLOC && (PBUF_POOL_BUFSIZE <= (PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN)) #if !MEMP_MEM_MALLOC && (PBUF_POOL_BUFSIZE <= (PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN))
#error "lwip_sanity_check: WARNING: PBUF_POOL_BUFSIZE does not provide enough space for protocol headers. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." #error "lwip_sanity_check: WARNING: PBUF_POOL_BUFSIZE does not provide enough space for protocol headers. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
#endif #endif
@ -328,13 +333,6 @@
void void
lwip_init(void) lwip_init(void)
{ {
#ifdef LWIP_ESP8266
// MEMP_NUM_TCP_PCB = 5;
// TCP_WND = (4 * TCP_MSS);
// TCP_MAXRTX = 12;
// TCP_SYNMAXRTX = 6;
#endif
/* Modules initialization */ /* Modules initialization */
stats_init(); stats_init();
#if !NO_SYS #if !NO_SYS

View File

@ -83,6 +83,7 @@ static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__;
#endif #endif
#ifdef LWIP_ESP8266 #ifdef LWIP_ESP8266
#include "esp_wifi_internal.h"
#define EP_OFFSET 0 #define EP_OFFSET 0
#endif #endif
@ -764,8 +765,7 @@ pbuf_free(struct pbuf *p)
} else if (type == PBUF_ROM || type == PBUF_REF) { } else if (type == PBUF_ROM || type == PBUF_REF) {
#ifdef LWIP_ESP8266 #ifdef LWIP_ESP8266
extern void system_pp_recycle_rx_pkt(void*); if (type == PBUF_REF && p->eb != NULL ) esp_wifi_internal_free_rx_buffer(p->eb);
if (type == PBUF_REF && p->eb != NULL ) system_pp_recycle_rx_pkt(p->eb);
#endif #endif
memp_free(MEMP_PBUF, p); memp_free(MEMP_PBUF, p);

View File

@ -638,7 +638,7 @@ u32_t tcp_update_rcv_ann_wnd(struct tcp_pcb *pcb)
{ {
u32_t new_right_edge = pcb->rcv_nxt + pcb->rcv_wnd; u32_t new_right_edge = pcb->rcv_nxt + pcb->rcv_wnd;
if (TCP_SEQ_GEQ(new_right_edge, pcb->rcv_ann_right_edge + LWIP_MIN((TCP_WND / 2), pcb->mss))) { if (TCP_SEQ_GEQ(new_right_edge, pcb->rcv_ann_right_edge + LWIP_MIN((TCP_WND(pcb) / 2), pcb->mss))) {
/* we can advertise more window */ /* we can advertise more window */
pcb->rcv_ann_wnd = pcb->rcv_wnd; pcb->rcv_ann_wnd = pcb->rcv_wnd;
return new_right_edge - pcb->rcv_ann_right_edge; return new_right_edge - pcb->rcv_ann_right_edge;
@ -694,10 +694,10 @@ tcp_recved(struct tcp_pcb *pcb, u16_t len)
wnd_inflation = tcp_update_rcv_ann_wnd(pcb); wnd_inflation = tcp_update_rcv_ann_wnd(pcb);
/* If the change in the right edge of window is significant (default /* If the change in the right edge of window is significant (default
* watermark is TCP_WND/4), then send an explicit update now. * watermark is TCP_WND(pcb)/4), then send an explicit update now.
* Otherwise wait for a packet to be sent in the normal course of * Otherwise wait for a packet to be sent in the normal course of
* events (or more window to be available later) */ * events (or more window to be available later) */
if (wnd_inflation >= TCP_WND_UPDATE_THRESHOLD) { if (wnd_inflation >= TCP_WND_UPDATE_THRESHOLD(pcb)) {
tcp_ack_now(pcb); tcp_ack_now(pcb);
tcp_output(pcb); tcp_output(pcb);
} }
@ -827,9 +827,9 @@ tcp_connect(struct tcp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port,
pcb->snd_lbb = iss - 1; pcb->snd_lbb = iss - 1;
/* Start with a window that does not need scaling. When window scaling is /* Start with a window that does not need scaling. When window scaling is
enabled and used, the window is enlarged when both sides agree on scaling. */ enabled and used, the window is enlarged when both sides agree on scaling. */
pcb->rcv_wnd = pcb->rcv_ann_wnd = TCPWND_MIN16(TCP_WND); pcb->rcv_wnd = pcb->rcv_ann_wnd = TCPWND_MIN16(TCP_WND(pcb));
pcb->rcv_ann_right_edge = pcb->rcv_nxt; pcb->rcv_ann_right_edge = pcb->rcv_nxt;
pcb->snd_wnd = TCP_WND; pcb->snd_wnd = TCP_WND(pcb);
/* As initial send MSS, we use TCP_MSS but limit it to 536. /* As initial send MSS, we use TCP_MSS but limit it to 536.
The send MSS is updated when an MSS option is received. */ The send MSS is updated when an MSS option is received. */
pcb->mss = (TCP_MSS > 536) ? 536 : TCP_MSS; pcb->mss = (TCP_MSS > 536) ? 536 : TCP_MSS;
@ -837,7 +837,7 @@ tcp_connect(struct tcp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port,
pcb->mss = tcp_eff_send_mss(pcb->mss, &pcb->local_ip, &pcb->remote_ip); pcb->mss = tcp_eff_send_mss(pcb->mss, &pcb->local_ip, &pcb->remote_ip);
#endif /* TCP_CALCULATE_EFF_SEND_MSS */ #endif /* TCP_CALCULATE_EFF_SEND_MSS */
pcb->cwnd = 1; pcb->cwnd = 1;
pcb->ssthresh = TCP_WND; pcb->ssthresh = TCP_WND(pcb);
#if LWIP_CALLBACK_API #if LWIP_CALLBACK_API
pcb->connected = connected; pcb->connected = connected;
#else /* LWIP_CALLBACK_API */ #else /* LWIP_CALLBACK_API */
@ -1581,11 +1581,11 @@ tcp_alloc(u8_t prio)
if (pcb != NULL) { if (pcb != NULL) {
memset(pcb, 0, sizeof(struct tcp_pcb)); memset(pcb, 0, sizeof(struct tcp_pcb));
pcb->prio = prio; pcb->prio = prio;
pcb->snd_buf = TCP_SND_BUF; pcb->snd_buf = TCP_SND_BUF_DEFAULT;
pcb->snd_queuelen = 0; pcb->snd_queuelen = 0;
/* Start with a window that does not need scaling. When window scaling is /* Start with a window that does not need scaling. When window scaling is
enabled and used, the window is enlarged when both sides agree on scaling. */ enabled and used, the window is enlarged when both sides agree on scaling. */
pcb->rcv_wnd = pcb->rcv_ann_wnd = TCPWND_MIN16(TCP_WND); pcb->rcv_wnd = pcb->rcv_ann_wnd = TCPWND_MIN16(TCP_WND(pcb));
#if LWIP_WND_SCALE #if LWIP_WND_SCALE
/* snd_scale and rcv_scale are zero unless both sides agree to use scaling */ /* snd_scale and rcv_scale are zero unless both sides agree to use scaling */
pcb->snd_scale = 0; pcb->snd_scale = 0;
@ -1608,7 +1608,6 @@ tcp_alloc(u8_t prio)
pcb->snd_lbb = iss; pcb->snd_lbb = iss;
pcb->tmr = tcp_ticks; pcb->tmr = tcp_ticks;
pcb->last_timer = tcp_timer_ctr; pcb->last_timer = tcp_timer_ctr;
pcb->polltmr = 0; pcb->polltmr = 0;
#if LWIP_CALLBACK_API #if LWIP_CALLBACK_API
@ -1624,7 +1623,13 @@ tcp_alloc(u8_t prio)
#endif /* LWIP_TCP_KEEPALIVE */ #endif /* LWIP_TCP_KEEPALIVE */
pcb->keep_cnt_sent = 0; pcb->keep_cnt_sent = 0;
#if ESP_PER_SOC_TCP_WND
pcb->per_soc_tcp_wnd = TCP_WND_DEFAULT;
pcb->per_soc_tcp_snd_buf = TCP_SND_BUF_DEFAULT;
#endif
} }
return pcb; return pcb;
} }

View File

@ -1745,9 +1745,9 @@ tcp_parseopt(struct tcp_pcb *pcb)
pcb->rcv_scale = TCP_RCV_SCALE; pcb->rcv_scale = TCP_RCV_SCALE;
pcb->flags |= TF_WND_SCALE; pcb->flags |= TF_WND_SCALE;
/* window scaling is enabled, we can use the full receive window */ /* window scaling is enabled, we can use the full receive window */
LWIP_ASSERT("window not at default value", pcb->rcv_wnd == TCPWND_MIN16(TCP_WND)); LWIP_ASSERT("window not at default value", pcb->rcv_wnd == TCPWND_MIN16(TCP_WND(pcb)));
LWIP_ASSERT("window not at default value", pcb->rcv_ann_wnd == TCPWND_MIN16(TCP_WND)); LWIP_ASSERT("window not at default value", pcb->rcv_ann_wnd == TCPWND_MIN16(TCP_WND(pcb)));
pcb->rcv_wnd = pcb->rcv_ann_wnd = TCP_WND; pcb->rcv_wnd = pcb->rcv_ann_wnd = TCP_WND(pcb);
} }
break; break;
#endif #endif

View File

@ -336,9 +336,9 @@ tcp_write_checks(struct tcp_pcb *pcb, u16_t len)
/* If total number of pbufs on the unsent/unacked queues exceeds the /* If total number of pbufs on the unsent/unacked queues exceeds the
* configured maximum, return an error */ * configured maximum, return an error */
/* check for configured max queuelen and possible overflow */ /* check for configured max queuelen and possible overflow */
if ((pcb->snd_queuelen >= TCP_SND_QUEUELEN) || (pcb->snd_queuelen > TCP_SNDQUEUELEN_OVERFLOW)) { if ((pcb->snd_queuelen >= TCP_SND_QUEUELEN(pcb)) || (pcb->snd_queuelen > TCP_SNDQUEUELEN_OVERFLOW)) {
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("tcp_write: too long queue %"U16_F" (max %"U16_F")\n", LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("tcp_write: too long queue %"U16_F" (max %"U16_F")\n",
pcb->snd_queuelen, TCP_SND_QUEUELEN)); pcb->snd_queuelen, TCP_SND_QUEUELEN(pcb)));
TCP_STATS_INC(tcp.memerr); TCP_STATS_INC(tcp.memerr);
pcb->flags |= TF_NAGLEMEMERR; pcb->flags |= TF_NAGLEMEMERR;
return ERR_MEM; return ERR_MEM;
@ -606,9 +606,9 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
/* Now that there are more segments queued, we check again if the /* Now that there are more segments queued, we check again if the
* length of the queue exceeds the configured maximum or * length of the queue exceeds the configured maximum or
* overflows. */ * overflows. */
if ((queuelen > TCP_SND_QUEUELEN) || (queuelen > TCP_SNDQUEUELEN_OVERFLOW)) { if ((queuelen > TCP_SND_QUEUELEN(pcb)) || (queuelen > TCP_SNDQUEUELEN_OVERFLOW)) {
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_write: queue too long %"U16_F" (%d)\n", LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_write: queue too long %"U16_F" (%d)\n",
queuelen, (int)TCP_SND_QUEUELEN)); queuelen, (int)TCP_SND_QUEUELEN(pcb)));
pbuf_free(p); pbuf_free(p);
goto memerr; goto memerr;
} }
@ -766,10 +766,10 @@ tcp_enqueue_flags(struct tcp_pcb *pcb, u8_t flags)
(flags & (TCP_SYN | TCP_FIN)) != 0); (flags & (TCP_SYN | TCP_FIN)) != 0);
/* check for configured max queuelen and possible overflow (FIN flag should always come through!) */ /* check for configured max queuelen and possible overflow (FIN flag should always come through!) */
if (((pcb->snd_queuelen >= TCP_SND_QUEUELEN) || (pcb->snd_queuelen > TCP_SNDQUEUELEN_OVERFLOW)) && if (((pcb->snd_queuelen >= TCP_SND_QUEUELEN(pcb)) || (pcb->snd_queuelen > TCP_SNDQUEUELEN_OVERFLOW)) &&
((flags & TCP_FIN) == 0)) { ((flags & TCP_FIN) == 0)) {
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("tcp_enqueue_flags: too long queue %"U16_F" (max %"U16_F")\n", LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("tcp_enqueue_flags: too long queue %"U16_F" (max %"U16_F")\n",
pcb->snd_queuelen, TCP_SND_QUEUELEN)); pcb->snd_queuelen, TCP_SND_QUEUELEN(pcb)));
TCP_STATS_INC(tcp.memerr); TCP_STATS_INC(tcp.memerr);
pcb->flags |= TF_NAGLEMEMERR; pcb->flags |= TF_NAGLEMEMERR;
return ERR_MEM; return ERR_MEM;
@ -1301,6 +1301,7 @@ tcp_rst(u32_t seqno, u32_t ackno,
struct pbuf *p; struct pbuf *p;
struct tcp_hdr *tcphdr; struct tcp_hdr *tcphdr;
struct netif *netif; struct netif *netif;
p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM); p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
if (p == NULL) { if (p == NULL) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_rst: could not allocate memory for pbuf\n")); LWIP_DEBUGF(TCP_DEBUG, ("tcp_rst: could not allocate memory for pbuf\n"));
@ -1315,10 +1316,18 @@ tcp_rst(u32_t seqno, u32_t ackno,
tcphdr->seqno = htonl(seqno); tcphdr->seqno = htonl(seqno);
tcphdr->ackno = htonl(ackno); tcphdr->ackno = htonl(ackno);
TCPH_HDRLEN_FLAGS_SET(tcphdr, TCP_HLEN/4, TCP_RST | TCP_ACK); TCPH_HDRLEN_FLAGS_SET(tcphdr, TCP_HLEN/4, TCP_RST | TCP_ACK);
#if ESP_PER_SOC_TCP_WND
#if LWIP_WND_SCALE
tcphdr->wnd = PP_HTONS(((TCP_WND_DEFAULT >> TCP_RCV_SCALE) & 0xFFFF));
#else
tcphdr->wnd = PP_HTONS(TCP_WND_DEFAULT);
#endif
#else
#if LWIP_WND_SCALE #if LWIP_WND_SCALE
tcphdr->wnd = PP_HTONS(((TCP_WND >> TCP_RCV_SCALE) & 0xFFFF)); tcphdr->wnd = PP_HTONS(((TCP_WND >> TCP_RCV_SCALE) & 0xFFFF));
#else #else
tcphdr->wnd = PP_HTONS(TCP_WND); tcphdr->wnd = PP_HTONS(TCP_WND);
#endif
#endif #endif
tcphdr->chksum = 0; tcphdr->chksum = 0;
tcphdr->urgp = 0; tcphdr->urgp = 0;

View File

@ -986,7 +986,7 @@
* (2 * TCP_MSS) for things to work well * (2 * TCP_MSS) for things to work well
*/ */
#ifndef TCP_WND #ifndef TCP_WND
#define TCP_WND (4 * TCP_MSS) #define TCP_WND(pcb) (4 * TCP_MSS)
#endif #endif
/** /**
@ -1040,7 +1040,7 @@
* To achieve good performance, this should be at least 2 * TCP_MSS. * To achieve good performance, this should be at least 2 * TCP_MSS.
*/ */
#ifndef TCP_SND_BUF #ifndef TCP_SND_BUF
#define TCP_SND_BUF (2 * TCP_MSS) #define TCP_SND_BUF(pcb) (2 * TCP_MSS)
#endif #endif
/** /**
@ -1048,7 +1048,7 @@
* as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. * as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work.
*/ */
#ifndef TCP_SND_QUEUELEN #ifndef TCP_SND_QUEUELEN
#define TCP_SND_QUEUELEN ((4 * (TCP_SND_BUF) + (TCP_MSS - 1))/(TCP_MSS)) #define TCP_SND_QUEUELEN(pcb) ((4 * (TCP_SND_BUF((pcb))) + (TCP_MSS - 1))/(TCP_MSS))
#endif #endif
/** /**
@ -1057,7 +1057,7 @@
* TCP snd_buf for select to return writable (combined with TCP_SNDQUEUELOWAT). * TCP snd_buf for select to return writable (combined with TCP_SNDQUEUELOWAT).
*/ */
#ifndef TCP_SNDLOWAT #ifndef TCP_SNDLOWAT
#define TCP_SNDLOWAT LWIP_MIN(LWIP_MAX(((TCP_SND_BUF)/2), (2 * TCP_MSS) + 1), (TCP_SND_BUF) - 1) #define TCP_SNDLOWAT(pcb) LWIP_MIN(LWIP_MAX(((TCP_SND_BUF((pcb)))/2), (2 * TCP_MSS) + 1), (TCP_SND_BUF((pcb))) - 1)
#endif #endif
/** /**
@ -1066,7 +1066,7 @@
* this number, select returns writable (combined with TCP_SNDLOWAT). * this number, select returns writable (combined with TCP_SNDLOWAT).
*/ */
#ifndef TCP_SNDQUEUELOWAT #ifndef TCP_SNDQUEUELOWAT
#define TCP_SNDQUEUELOWAT LWIP_MAX(((TCP_SND_QUEUELEN)/2), 5) #define TCP_SNDQUEUELOWAT(pcb) LWIP_MAX(((TCP_SND_QUEUELEN((pcb)))/2), 5)
#endif #endif
/** /**
@ -1134,7 +1134,7 @@
* explicit window update * explicit window update
*/ */
#ifndef TCP_WND_UPDATE_THRESHOLD #ifndef TCP_WND_UPDATE_THRESHOLD
#define TCP_WND_UPDATE_THRESHOLD LWIP_MIN((TCP_WND / 4), (TCP_MSS * 4)) #define TCP_WND_UPDATE_THRESHOLD(pcb) LWIP_MIN((TCP_WND((pcb)) / 4), (TCP_MSS * 4))
#endif #endif
/** /**

View File

@ -92,7 +92,7 @@ err_t tcp_process_refused_data(struct tcp_pcb *pcb);
((tpcb)->flags & (TF_NODELAY | TF_INFR)) || \ ((tpcb)->flags & (TF_NODELAY | TF_INFR)) || \
(((tpcb)->unsent != NULL) && (((tpcb)->unsent->next != NULL) || \ (((tpcb)->unsent != NULL) && (((tpcb)->unsent->next != NULL) || \
((tpcb)->unsent->len >= (tpcb)->mss))) || \ ((tpcb)->unsent->len >= (tpcb)->mss))) || \
((tcp_sndbuf(tpcb) == 0) || (tcp_sndqueuelen(tpcb) >= TCP_SND_QUEUELEN)) \ ((tcp_sndbuf(tpcb) == 0) || (tcp_sndqueuelen(tpcb) >= TCP_SND_QUEUELEN(tpcb))) \
) ? 1 : 0) ) ? 1 : 0)
#define tcp_output_nagle(tpcb) (tcp_do_output_nagle(tpcb) ? tcp_output(tpcb) : ERR_OK) #define tcp_output_nagle(tpcb) (tcp_do_output_nagle(tpcb) ? tcp_output(tpcb) : ERR_OK)

View File

@ -190,7 +190,6 @@ struct msghdr {
#define SO_CONTIMEO 0x1009 /* Unimplemented: connect timeout */ #define SO_CONTIMEO 0x1009 /* Unimplemented: connect timeout */
#define SO_NO_CHECK 0x100a /* don't create UDP checksum */ #define SO_NO_CHECK 0x100a /* don't create UDP checksum */
/* /*
* Structure used for manipulating linger option. * Structure used for manipulating linger option.
*/ */
@ -250,6 +249,11 @@ struct linger {
#define TCP_KEEPIDLE 0x03 /* set pcb->keep_idle - Same as TCP_KEEPALIVE, but use seconds for get/setsockopt */ #define TCP_KEEPIDLE 0x03 /* set pcb->keep_idle - Same as TCP_KEEPALIVE, but use seconds for get/setsockopt */
#define TCP_KEEPINTVL 0x04 /* set pcb->keep_intvl - Use seconds for get/setsockopt */ #define TCP_KEEPINTVL 0x04 /* set pcb->keep_intvl - Use seconds for get/setsockopt */
#define TCP_KEEPCNT 0x05 /* set pcb->keep_cnt - Use number of probes sent for get/setsockopt */ #define TCP_KEEPCNT 0x05 /* set pcb->keep_cnt - Use number of probes sent for get/setsockopt */
#if ESP_PER_SOC_TCP_WND
#define TCP_WINDOW 0x06 /* set pcb->per_soc_tcp_wnd */
#define TCP_SNDBUF 0x07 /* set pcb->per_soc_tcp_snd_buf */
#endif
#endif /* LWIP_TCP */ #endif /* LWIP_TCP */
#if LWIP_IPV6 #if LWIP_IPV6

View File

@ -129,14 +129,14 @@ typedef err_t (*tcp_connected_fn)(void *arg, struct tcp_pcb *tpcb, err_t err);
#define RCV_WND_SCALE(pcb, wnd) (((wnd) >> (pcb)->rcv_scale)) #define RCV_WND_SCALE(pcb, wnd) (((wnd) >> (pcb)->rcv_scale))
#define SND_WND_SCALE(pcb, wnd) (((wnd) << (pcb)->snd_scale)) #define SND_WND_SCALE(pcb, wnd) (((wnd) << (pcb)->snd_scale))
#define TCPWND16(x) ((u16_t)LWIP_MIN((x), 0xFFFF)) #define TCPWND16(x) ((u16_t)LWIP_MIN((x), 0xFFFF))
#define TCP_WND_MAX(pcb) ((tcpwnd_size_t)(((pcb)->flags & TF_WND_SCALE) ? TCP_WND : TCPWND16(TCP_WND))) #define TCP_WND_MAX(pcb) ((tcpwnd_size_t)(((pcb)->flags & TF_WND_SCALE) ? TCP_WND(pcb) : TCPWND16(TCP_WND(pcb))))
typedef u32_t tcpwnd_size_t; typedef u32_t tcpwnd_size_t;
typedef u16_t tcpflags_t; typedef u16_t tcpflags_t;
#else #else
#define RCV_WND_SCALE(pcb, wnd) (wnd) #define RCV_WND_SCALE(pcb, wnd) (wnd)
#define SND_WND_SCALE(pcb, wnd) (wnd) #define SND_WND_SCALE(pcb, wnd) (wnd)
#define TCPWND16(x) (x) #define TCPWND16(x) (x)
#define TCP_WND_MAX(pcb) TCP_WND #define TCP_WND_MAX(pcb) TCP_WND(pcb)
typedef u16_t tcpwnd_size_t; typedef u16_t tcpwnd_size_t;
typedef u8_t tcpflags_t; typedef u8_t tcpflags_t;
#endif #endif
@ -236,6 +236,11 @@ struct tcp_pcb {
u8_t dupacks; u8_t dupacks;
u32_t lastack; /* Highest acknowledged seqno. */ u32_t lastack; /* Highest acknowledged seqno. */
#if ESP_PER_SOC_TCP_WND
tcpwnd_size_t per_soc_tcp_wnd; /* per tcp socket tcp window size */
tcpwnd_size_t per_soc_tcp_snd_buf; /* per tcp socket tcp send buffer size */
#endif
/* congestion avoidance/control variables */ /* congestion avoidance/control variables */
tcpwnd_size_t cwnd; tcpwnd_size_t cwnd;
tcpwnd_size_t ssthresh; tcpwnd_size_t ssthresh;
@ -402,6 +407,10 @@ const char* tcp_debug_state_str(enum tcp_state s);
/* for compatibility with older implementation */ /* for compatibility with older implementation */
#define tcp_new_ip6() tcp_new_ip_type(IPADDR_TYPE_V6) #define tcp_new_ip6() tcp_new_ip_type(IPADDR_TYPE_V6)
#if ESP_PER_SOC_TCP_WND
#define PER_SOC_WND(pcb) (pcb->per_soc_wnd)
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -225,18 +225,21 @@ extern unsigned long os_random(void);
* TCP_WND: The size of a TCP window. This must be at least * TCP_WND: The size of a TCP window. This must be at least
* (2 * TCP_MSS) for things to work well * (2 * TCP_MSS) for things to work well
*/ */
#define PERF 1
#define ESP_PER_SOC_TCP_WND 1
#if ESP_PER_SOC_TCP_WND
#define TCP_WND_DEFAULT (4*TCP_MSS)
#define TCP_SND_BUF_DEFAULT (2*TCP_MSS)
#define TCP_WND(pcb) (pcb->per_soc_tcp_wnd)
#define TCP_SND_BUF(pcb) (pcb->per_soc_tcp_snd_buf)
#else
#ifdef PERF #ifdef PERF
extern unsigned char misc_prof_get_tcpw(void); extern unsigned char misc_prof_get_tcpw(void);
extern unsigned char misc_prof_get_tcp_snd_buf(void); extern unsigned char misc_prof_get_tcp_snd_buf(void);
#define TCP_WND (misc_prof_get_tcpw()*TCP_MSS) #define TCP_WND(pcb) (misc_prof_get_tcpw()*TCP_MSS)
#define TCP_SND_BUF (misc_prof_get_tcp_snd_buf()*TCP_MSS) #define TCP_SND_BUF(pcb) (misc_prof_get_tcp_snd_buf()*TCP_MSS)
#endif
#else
#define TCP_WND (4 * TCP_MSS)
#define TCP_SND_BUF (2 * TCP_MSS)
#endif #endif

View File

@ -8,6 +8,8 @@
#include "esp_wifi.h" #include "esp_wifi.h"
#include "esp_wifi_internal.h"
#include "lwip/err.h" #include "lwip/err.h"
#ifdef __cplusplus #ifdef __cplusplus
@ -18,8 +20,6 @@ err_t wlanif_init(struct netif *netif);
void wlanif_input(struct netif *netif, void *buffer, u16_t len, void* eb); void wlanif_input(struct netif *netif, void *buffer, u16_t len, void* eb);
bool ieee80211_output(wifi_interface_t wifi_if, void *buffer, u16_t len);
wifi_interface_t wifi_get_interface(void *dev); wifi_interface_t wifi_get_interface(void *dev);
void netif_reg_addr_change_cb(void* cb); void netif_reg_addr_change_cb(void* cb);

View File

@ -150,12 +150,12 @@ low_level_output(struct netif *netif, struct pbuf *p)
} }
} }
ieee80211_output(wifi_if, q->payload, pbuf_x_len); esp_wifi_internal_tx(wifi_if, q->payload, pbuf_x_len);
return ERR_OK; return ERR_OK;
#else #else
for(q = p; q != NULL; q = q->next) { for(q = p; q != NULL; q = q->next) {
ieee80211_output(wifi_if, q->payload, q->len); esp_wifi_internal_tx(wifi_if, q->payload, q->len);
} }
#endif #endif

View File

@ -7177,7 +7177,7 @@ uint32_t nghttp2_session_get_remote_settings(nghttp2_session *session,
return session->remote_settings.max_header_list_size; return session->remote_settings.max_header_list_size;
} }
assert(0); abort();
} }
static int nghttp2_session_upgrade_internal(nghttp2_session *session, static int nghttp2_session_upgrade_internal(nghttp2_session *session,

View File

@ -769,7 +769,7 @@ void Page::invalidateCache()
void Page::debugDump() const void Page::debugDump() const
{ {
printf("state=%x addr=%x seq=%d\nfirstUsed=%d nextFree=%d used=%d erased=%d\n", mState, mBaseAddress, mSeqNumber, static_cast<int>(mFirstUsedEntry), static_cast<int>(mNextFreeEntry), mUsedEntryCount, mErasedEntryCount); printf("state=%x addr=%x seq=%d\nfirstUsed=%d nextFree=%d used=%d erased=%d\n", (int) mState, mBaseAddress, mSeqNumber, static_cast<int>(mFirstUsedEntry), static_cast<int>(mNextFreeEntry), mUsedEntryCount, mErasedEntryCount);
size_t skip = 0; size_t skip = 0;
for (size_t i = 0; i < ENTRY_COUNT; ++i) { for (size_t i = 0; i < ENTRY_COUNT; ++i) {
printf("%3d: ", static_cast<int>(i)); printf("%3d: ", static_cast<int>(i));

View File

@ -49,7 +49,7 @@ esp_err_t PageManager::load(uint32_t baseSector, uint32_t sectorCount)
return activatePage(); return activatePage();
} else { } else {
uint32_t lastSeqNo; uint32_t lastSeqNo;
assert(mPageList.back().getSeqNumber(lastSeqNo) == ESP_OK); ESP_ERROR_CHECK( mPageList.back().getSeqNumber(lastSeqNo) );
mSeqNumber = lastSeqNo + 1; mSeqNumber = lastSeqNo + 1;
} }
@ -142,7 +142,9 @@ esp_err_t PageManager::requestNewPage()
Page* newPage = &mPageList.back(); Page* newPage = &mPageList.back();
Page* erasedPage = maxErasedItemsPageIt; Page* erasedPage = maxErasedItemsPageIt;
#ifndef NDEBUG
size_t usedEntries = erasedPage->getUsedEntryCount(); size_t usedEntries = erasedPage->getUsedEntryCount();
#endif
err = erasedPage->markFreeing(); err = erasedPage->markFreeing();
if (err != ESP_OK) { if (err != ESP_OK) {
return err; return err;

View File

@ -123,8 +123,7 @@ esp_err_t Storage::writeItem(uint8_t nsIndex, ItemType datatype, const char* key
if (findPage) { if (findPage) {
if (findPage->state() == Page::PageState::UNINITIALIZED || if (findPage->state() == Page::PageState::UNINITIALIZED ||
findPage->state() == Page::PageState::INVALID) { findPage->state() == Page::PageState::INVALID) {
auto err = findItem(nsIndex, datatype, key, findPage, item); ESP_ERROR_CHECK( findItem(nsIndex, datatype, key, findPage, item) );
assert(err == ESP_OK);
} }
err = findPage->eraseItem(nsIndex, datatype, key); err = findPage->eraseItem(nsIndex, datatype, key);
if (err == ESP_ERR_FLASH_OP_FAIL) { if (err == ESP_ERR_FLASH_OP_FAIL) {

View File

@ -1,3 +1,8 @@
COMPONENT_ADD_INCLUDEDIRS := include COMPONENT_ADD_INCLUDEDIRS := include
ifdef IS_BOOTLOADER_BUILD
# Bootloader needs updated SPIUnlock from this file
COMPONENT_OBJS := spi_flash_rom_patch.o
endif
include $(IDF_PATH)/make/component_common.mk include $(IDF_PATH)/make/component_common.mk

View File

@ -0,0 +1,72 @@
// 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 "rom/spi_flash.h"
#include "soc/spi_reg.h"
static const uint32_t STATUS_QIE_BIT = (1 << 9); /* Quad Enable */
#define SPI_IDX 1
#define OTH_IDX 0
extern SpiFlashChip SPI_flashchip_data;
static void IRAM_ATTR Wait_SPI_Idle(void)
{
/* Wait for SPI state machine to be idle */
while((REG_READ(SPI_EXT2_REG(SPI_IDX)) & SPI_ST)) {
}
while(REG_READ(SPI_EXT2_REG(OTH_IDX)) & SPI_ST) {
}
}
/* Modified version of SPIUnlock() that replaces version in ROM.
This works around a bug where SPIUnlock sometimes reads the wrong
high status byte (RDSR2 result) and then copies it back to the
flash status, which can cause the CMP bit or Status Register
Protect bit to become set.
Like other ROM SPI functions, this function is not designed to be
called directly from an RTOS environment without taking precautions
about interrupts, CPU coordination, flash mapping. However some of
the functions in esp_spi_flash.c call it.
*/
SpiFlashOpResult IRAM_ATTR SPIUnlock(void)
{
uint32_t status;
Wait_SPI_Idle();
if (SPI_read_status_high(&status) != SPI_FLASH_RESULT_OK) {
return SPI_FLASH_RESULT_ERR;
}
/* Clear all bits except QIE, if it is set.
(This is different from ROM SPIUnlock, which keeps all bits as-is.)
*/
status &= STATUS_QIE_BIT;
Wait_SPI_Idle();
REG_WRITE(SPI_CMD_REG(SPI_IDX), SPI_FLASH_WREN);
while(REG_READ(SPI_CMD_REG(SPI_IDX)) != 0) {
}
Wait_SPI_Idle();
SET_PERI_REG_MASK(SPI_CTRL_REG(SPI_IDX), SPI_WRSR_2B);
if (SPI_write_status(&SPI_flashchip_data, status) != SPI_FLASH_RESULT_OK) {
return SPI_FLASH_RESULT_ERR;
}
return SPI_FLASH_RESULT_OK;
}

View File

@ -67,11 +67,15 @@ typedef struct {
typedef dhcps_lease_t tcpip_adapter_dhcps_lease_t; typedef dhcps_lease_t tcpip_adapter_dhcps_lease_t;
#if CONFIG_DHCP_STA_LIST #if CONFIG_DHCP_STA_LIST
struct station_list { typedef struct {
STAILQ_ENTRY(station_list) next;
uint8_t mac[6]; uint8_t mac[6];
ip4_addr_t ip; ip4_addr_t ip;
}; }tcpip_adapter_sta_info_t;
typedef struct {
tcpip_adapter_sta_info_t sta[ESP_WIFI_MAX_CONN_NUM+2];
uint8_t num;
}tcpip_adapter_sta_list_t;
#endif #endif
#endif #endif
@ -359,26 +363,14 @@ wifi_interface_t tcpip_adapter_get_wifi_if(void *dev);
/** /**
* @brief Get the station information list * @brief Get the station information list
* *
* @note This function should be called in AP mode and dhcp server started, and the list should * @param[in] wifi_sta_list_t *wifi_sta_list: station list info
* be by using tcpip_adapter_free_sta_list. * @param[out] tcpip_adapter_sta_list_t *tcpip_sta_list: station list info
*
* @param[in] sta_info: station information
* @param[out] sta_list: station information list
* *
* @return ESP_OK * @return ESP_OK
* ESP_ERR_TCPIP_ADAPTER_NO_MEM * ESP_ERR_TCPIP_ADAPTER_NO_MEM
* ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS * ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS
*/ */
esp_err_t tcpip_adapter_get_sta_list(struct station_info *sta_info, struct station_list **sta_list); esp_err_t tcpip_adapter_get_sta_list(wifi_sta_list_t *wifi_sta_list, tcpip_adapter_sta_list_t *tcpip_sta_list);
/**
* @brief Free the station information list's memory
*
* @param sta_list: station information list
*
* @return ESP_OK
*/
esp_err_t tcpip_adapter_free_sta_list(struct station_list *sta_list);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -103,7 +103,9 @@ esp_err_t tcpip_adapter_stop(tcpip_adapter_if_t tcpip_if)
if (tcpip_if == TCPIP_ADAPTER_IF_AP) { if (tcpip_if == TCPIP_ADAPTER_IF_AP) {
dhcps_stop(esp_netif[tcpip_if]); // TODO: dhcps checks status by its self dhcps_stop(esp_netif[tcpip_if]); // TODO: dhcps checks status by its self
dhcps_status = TCPIP_ADAPTER_DHCP_INIT; if (TCPIP_ADAPTER_DHCP_STOPPED != dhcps_status){
dhcps_status = TCPIP_ADAPTER_DHCP_INIT;
}
} else if (tcpip_if == TCPIP_ADAPTER_IF_STA) { } else if (tcpip_if == TCPIP_ADAPTER_IF_STA) {
dhcp_release(esp_netif[tcpip_if]); dhcp_release(esp_netif[tcpip_if]);
dhcp_stop(esp_netif[tcpip_if]); dhcp_stop(esp_netif[tcpip_if]);
@ -588,45 +590,17 @@ wifi_interface_t tcpip_adapter_get_wifi_if(void *dev)
return WIFI_IF_MAX; return WIFI_IF_MAX;
} }
esp_err_t tcpip_adapter_get_sta_list(struct station_info *sta_info, struct station_list **sta_list) esp_err_t tcpip_adapter_get_sta_list(wifi_sta_list_t *wifi_sta_list, tcpip_adapter_sta_list_t *tcpip_sta_list)
{ {
struct station_info *info = sta_info; int i;
struct station_list *list;
STAILQ_HEAD(, station_list) list_head;
if (sta_list == NULL) if ((wifi_sta_list == NULL) || (tcpip_sta_list == NULL))
return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS;
STAILQ_INIT(&list_head); memset(tcpip_sta_list, 0, sizeof(tcpip_adapter_sta_list_t));
for (i=0; i<wifi_sta_list->num; i++){
while (info != NULL) { memcpy(tcpip_sta_list->sta[i].mac, wifi_sta_list->sta[i].mac, 6);
list = (struct station_list *)malloc(sizeof(struct station_list)); dhcp_search_ip_on_mac(tcpip_sta_list->sta[i].mac, &tcpip_sta_list->sta[i].ip);
memset(list, 0, sizeof (struct station_list));
if (list == NULL) {
return ESP_ERR_TCPIP_ADAPTER_NO_MEM;
}
memcpy(list->mac, info->bssid, 6);
dhcp_search_ip_on_mac(list->mac, &list->ip);
STAILQ_INSERT_TAIL(&list_head, list, next);
info = STAILQ_NEXT(info, next);
}
*sta_list = STAILQ_FIRST(&list_head);
return ESP_OK;
}
esp_err_t tcpip_adapter_free_sta_list(struct station_list *sta_list)
{
struct station_list *list = sta_list;
while (sta_list != NULL) {
list = sta_list;
sta_list = STAILQ_NEXT(sta_list, next);
free(list);
} }
return ESP_OK; return ESP_OK;

View File

@ -0,0 +1,5 @@
#
# Component Makefile
#
include $(IDF_PATH)/make/component_common.mk

View File

@ -0,0 +1,32 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stdint.h>
#include "eri.h"
uint32_t eri_read(int addr) {
uint32_t ret;
asm(
"RER %0,%1"
:"=r"(ret):"r"(addr)
);
return ret;
}
void eri_write(int addr, uint32_t data) {
asm volatile (
"WER %0,%1"
::"r"(data),"r"(addr)
);
}

View File

@ -0,0 +1,31 @@
#ifndef ERI_H
#define ERI_H
#include <stdint.h>
/*
The ERI is a bus internal to each Xtensa core. It connects, amongst others, to the debug interface, where it
allows reading/writing the same registers as available over JTAG.
*/
/**
* @brief Perform an ERI read
* @param addr : ERI register to read from
*
* @return Value read
*/
uint32_t eri_read(int addr);
/**
* @brief Perform an ERI write
* @param addr : ERI register to write to
* @param data : Value to write
*
* @return Value read
*/
void eri_write(int addr, uint32_t data);
#endif

View File

@ -0,0 +1,62 @@
#include "soc/dport_reg.h"
#include "sdkconfig.h"
#include "esp_err.h"
#include "eri.h"
#include "xtensa-debug-module.h"
typedef enum {
TRAX_DOWNCOUNT_WORDS,
TRAX_DOWNCOUNT_INSTRUCTIONS
} trax_downcount_unit_t;
typedef enum {
TRAX_ENA_NONE = 0,
TRAX_ENA_PRO,
TRAX_ENA_APP,
TRAX_ENA_PRO_APP,
TRAX_ENA_PRO_APP_SWAP
} trax_ena_select_t;
/**
* @brief Enable the trax memory blocks to be used as Trax memory.
*
* @param pro_cpu_enable : true if Trax needs to be enabled for the pro CPU
* @param app_cpu_enable : true if Trax needs to be enabled for the pro CPU
* @param swap_regions : Normally, the pro CPU writes to Trax mem block 0 while
* the app cpu writes to block 1. Setting this to true
* inverts this.
*
* @return esp_err_t. Fails with ESP_ERR_NO_MEM if Trax enable is requested for 2 CPUs
* but memmap only has room for 1, or if Trax memmap is disabled
* entirely.
*/
int trax_enable(trax_ena_select_t ena);
/**
* @brief Start a Trax trace on the current CPU
*
* @param units_until_stop : Set the units of the delay that gets passed to
* trax_trigger_traceend_after_delay. One of TRAX_DOWNCOUNT_WORDS
* or TRAX_DOWNCOUNT_INSTRUCTIONS.
*
* @return esp_err_t. Fails with ESP_ERR_NO_MEM if Trax is disabled.
*/
int trax_start_trace(trax_downcount_unit_t units_until_stop);
/**
* @brief Trigger a Trax trace stop after the indicated delay. If this is called
* before and the previous delay hasn't ended yet, this will overwrite
* that delay with the new value. The delay will always start at the time
* the function is called.
*
* @param delay : The delay to stop the trace in, in the unit indicated to
* trax_start_trace. Note: the trace memory has 4K words available.
*
* @return esp_err_t
*/
int trax_trigger_traceend_after_delay(int delay);

View File

@ -0,0 +1,75 @@
#ifndef XTENSA_DEBUG_MODULE_H
#define XTENSA_DEBUG_MODULE_H
/*
ERI registers / OCD offsets and field definitions
*/
#define ERI_DEBUG_OFFSET 0x100000
#define ERI_TRAX_OFFSET (ERI_DEBUG_OFFSET+0)
#define ERI_PERFMON_OFFSET (ERI_DEBUG_OFFSET+0x1000)
#define ERI_OCDREG_OFFSET (ERI_DEBUG_OFFSET+0x2000)
#define ERI_MISCDBG_OFFSET (ERI_DEBUG_OFFSET+0x3000)
#define ERI_CORESIGHT_OFFSET (ERI_DEBUG_OFFSET+0x3F00)
#define ERI_TRAX_TRAXID (ERI_TRAX_OFFSET+0x00)
#define ERI_TRAX_TRAXCTRL (ERI_TRAX_OFFSET+0x04)
#define ERI_TRAX_TRAXSTAT (ERI_TRAX_OFFSET+0x08)
#define ERI_TRAX_TRAXDATA (ERI_TRAX_OFFSET+0x0C)
#define ERI_TRAX_TRAXADDR (ERI_TRAX_OFFSET+0x10)
#define ERI_TRAX_TRIGGERPC (ERI_TRAX_OFFSET+0x14)
#define ERI_TRAX_PCMATCHCTRL (ERI_TRAX_OFFSET+0x18)
#define ERI_TRAX_DELAYCNT (ERI_TRAX_OFFSET+0x1C)
#define ERI_TRAX_MEMADDRSTART (ERI_TRAX_OFFSET+0x20)
#define ERI_TRAX_MEMADDREND (ERI_TRAX_OFFSET+0x24)
#define TRAXCTRL_TREN (1<<0) //Trace enable. Tracing starts on 0->1
#define TRAXCTRL_TRSTP (1<<1) //Trace Stop. Make 1 to stop trace.
#define TRAXCTRL_PCMEN (1<<2) //PC match enable
#define TRAXCTRL_PTIEN (1<<4) //Processor-trigger enable
#define TRAXCTRL_CTIEN (1<<5) //Cross-trigger enable
#define TRAXCTRL_TMEN (1<<7) //Tracemem Enable. Always set.
#define TRAXCTRL_CNTU (1<<9) //Post-stop-trigger countdown units; selects when DelayCount-- happens.
//0 - every 32-bit word written to tracemem, 1 - every cpu instruction
#define TRAXCTRL_TSEN (1<<11) //Undocumented/deprecated?
#define TRAXCTRL_SMPER_SHIFT 12 //Send sync every 2^(9-smper) messages. 7=reserved, 0=no sync msg
#define TRAXCTRL_SMPER_MASK 0x7 //Synchronization message period
#define TRAXCTRL_PTOWT (1<<16) //Processor Trigger Out (OCD halt) enabled when stop triggered
#define TRAXCTRL_PTOWS (1<<17) //Processor Trigger Out (OCD halt) enabled when trace stop completes
#define TRAXCTRL_CTOWT (1<<20) //Cross-trigger Out enabled when stop triggered
#define TRAXCTRL_CTOWS (1<<21) //Cross-trigger Out enabled when trace stop completes
#define TRAXCTRL_ITCTO (1<<22) //Integration mode: cross-trigger output
#define TRAXCTRL_ITCTIA (1<<23) //Integration mode: cross-trigger ack
#define TRAXCTRL_ITATV (1<<24) //replaces ATID when in integration mode: ATVALID output
#define TRAXCTRL_ATID_MASK 0x7F //ARB source ID
#define TRAXCTRL_ATID_SHIFT 24
#define TRAXCTRL_ATEN (1<<31) //ATB interface enable
#define TRAXSTAT_TRACT (1<<0) //Trace active flag.
#define TRAXSTAT_TRIG (1<<1) //Trace stop trigger. Clears on TREN 1->0
#define TRAXSTAT_PCMTG (1<<2) //Stop trigger caused by PC match. Clears on TREN 1->0
#define TRAXSTAT_PJTR (1<<3) //JTAG transaction result. 1=err in preceding jtag transaction.
#define TRAXSTAT_PTITG (1<<4) //Stop trigger caused by Processor Trigger Input. Clears on TREN 1->0
#define TRAXSTAT_CTITG (1<<5) //Stop trigger caused by Cross-Trigger Input. Clears on TREN 1->0
#define TRAXSTAT_MEMSZ_SHIFT 8 //Traceram size inducator. Usable trace ram is 2^MEMSZ bytes.
#define TRAXSTAT_MEMSZ_MASK 0x1F
#define TRAXSTAT_PTO (1<<16) //Processor Trigger Output: current value
#define TRAXSTAT_CTO (1<<17) //Cross-Trigger Output: current value
#define TRAXSTAT_ITCTOA (1<<22) //Cross-Trigger Out Ack: current value
#define TRAXSTAT_ITCTI (1<<23) //Cross-Trigger Input: current value
#define TRAXSTAT_ITATR (1<<24) //ATREADY Input: current value
#define TRAXADDR_TADDR_SHIFT 0 //Trax memory address, in 32-bit words.
#define TRAXADDR_TADDR_MASK 0x1FFFFF //Actually is only as big as the trace buffer size max addr.
#define TRAXADDR_TWRAP_SHIFT 21 //Amount of times TADDR has overflown
#define TRAXADDR_TWRAP_MASK 0x3FF
#define TRAXADDR_TWSAT (1<<31) //1 if TWRAP has overflown, clear by disabling tren.
#define PCMATCHCTRL_PCML_SHIFT 0 //Amount of lower bits to ignore in pc trigger register
#define PCMATCHCTRL_PCML_MASK 0x1F
#define PCMATCHCTRL_PCMS (1<<31) //PC Match Sense, 0 - match when procs PC is in-range, 1 - match when
//out-of-range
#endif

View File

@ -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.
#include <stdio.h>
#include "soc/dport_reg.h"
#include "sdkconfig.h"
#include "esp_err.h"
#include "eri.h"
#include "xtensa-debug-module.h"
#include "trax.h"
#include "esp_log.h"
#define TRACEMEM_MUX_PROBLK0_APPBLK1 0
#define TRACEMEM_MUX_BLK0_ONLY 1
#define TRACEMEM_MUX_BLK1_ONLY 2
#define TRACEMEM_MUX_PROBLK1_APPBLK0 3
static const char* TAG = "trax";
int trax_enable(trax_ena_select_t which)
{
#if !CONFIG_MEMMAP_TRACEMEM
ESP_LOGE(TAG, "Trax_enable called, but trax is disabled in menuconfig!");
return ESP_ERR_NO_MEM;
#endif
#if !CONFIG_MEMMAP_TRACEMEM_TWOBANKS
if (which == TRAX_ENA_PRO_APP || which == TRAX_ENA_PRO_APP_SWAP) return ESP_ERR_NO_MEM;
#endif
if (which == TRAX_ENA_PRO_APP || which == TRAX_ENA_PRO_APP_SWAP) {
WRITE_PERI_REG(DPORT_TRACEMEM_MUX_MODE_REG, (which == TRAX_ENA_PRO_APP_SWAP)?TRACEMEM_MUX_PROBLK1_APPBLK0:TRACEMEM_MUX_PROBLK0_APPBLK1);
} else {
WRITE_PERI_REG(DPORT_TRACEMEM_MUX_MODE_REG, TRACEMEM_MUX_BLK0_ONLY);
}
WRITE_PERI_REG(DPORT_PRO_TRACEMEM_ENA_REG, (which == TRAX_ENA_PRO_APP || which == TRAX_ENA_PRO_APP_SWAP || which == TRAX_ENA_PRO));
WRITE_PERI_REG(DPORT_APP_TRACEMEM_ENA_REG, (which == TRAX_ENA_PRO_APP || which == TRAX_ENA_PRO_APP_SWAP || which == TRAX_ENA_APP));
return ESP_OK;
}
int trax_start_trace(trax_downcount_unit_t units_until_stop)
{
#if !CONFIG_MEMMAP_TRACEMEM
ESP_LOGE(TAG, "Trax_start_trace called, but trax is disabled in menuconfig!");
return ESP_ERR_NO_MEM;
#endif
uint32_t v;
if (eri_read(ERI_TRAX_TRAXSTAT)&TRAXSTAT_TRACT) {
ESP_LOGI(TAG, "Stopping active trace first.");
//Trace is active. Stop trace.
eri_write(ERI_TRAX_DELAYCNT, 0);
eri_write(ERI_TRAX_TRAXCTRL, eri_read(ERI_TRAX_TRAXCTRL)|TRAXCTRL_TRSTP);
//ToDo: This will probably trigger a trace done interrupt. ToDo: Fix, but how? -JD
eri_write(ERI_TRAX_TRAXCTRL, 0);
}
eri_write(ERI_TRAX_PCMATCHCTRL, 31); //do not stop at any pc match
v=TRAXCTRL_TREN | TRAXCTRL_TMEN | TRAXCTRL_PTOWS | (1<<TRAXCTRL_SMPER_SHIFT);
if (units_until_stop == TRAX_DOWNCOUNT_INSTRUCTIONS) v|=TRAXCTRL_CNTU;
//Enable trace. This trace has no stop condition and will just keep on running.
eri_write(ERI_TRAX_TRAXCTRL, v);
return ESP_OK;
}
int trax_trigger_traceend_after_delay(int delay)
{
#if !CONFIG_MEMMAP_TRACEMEM
ESP_LOGE(TAG, "Trax_trigger_traceend_after_delay called, but trax is disabled in menuconfig!");
return ESP_ERR_NO_MEM;
#endif
eri_write(ERI_TRAX_DELAYCNT, delay);
eri_write(ERI_TRAX_TRAXCTRL, eri_read(ERI_TRAX_TRAXCTRL)|TRAXCTRL_TRSTP);
return ESP_OK;
}

View File

@ -6,7 +6,7 @@
# #
# (Note that we only rebuild auto.conf automatically for some targets, # (Note that we only rebuild auto.conf automatically for some targets,
# see project_config.mk for details.) # see project_config.mk for details.)
-include $(PROJECT_PATH)/build/include/config/auto.conf -include $(BUILD_DIR_BASE)/include/config/auto.conf
#Handling of V=1/VERBOSE=1 flag #Handling of V=1/VERBOSE=1 flag
# #

View File

@ -91,15 +91,15 @@ define GenerateCompileTargets
# $(1) - directory containing source files, relative to $(COMPONENT_PATH) # $(1) - directory containing source files, relative to $(COMPONENT_PATH)
$(1)/%.o: $$(COMPONENT_PATH)/$(1)/%.c | $(1) $(1)/%.o: $$(COMPONENT_PATH)/$(1)/%.c | $(1)
$$(summary) CC $$@ $$(summary) CC $$@
$$(Q) $$(CC) $$(CFLAGS) $$(addprefix -I ,$$(COMPONENT_INCLUDES)) $$(addprefix -I ,$$(COMPONENT_EXTRA_INCLUDES)) -I$(1) -c $$< -o $$@ $$(Q) $$(CC) $$(CFLAGS) $(CPPFLAGS) $$(addprefix -I ,$$(COMPONENT_INCLUDES)) $$(addprefix -I ,$$(COMPONENT_EXTRA_INCLUDES)) -I$(1) -c $$< -o $$@
$(1)/%.o: $$(COMPONENT_PATH)/$(1)/%.cpp | $(1) $(1)/%.o: $$(COMPONENT_PATH)/$(1)/%.cpp | $(1)
$$(summary) CC $$@ $$(summary) CXX $$@
$$(Q) $$(CXX) $$(CXXFLAGS) $$(addprefix -I,$$(COMPONENT_INCLUDES)) $$(addprefix -I,$$(COMPONENT_EXTRA_INCLUDES)) -I$(1) -c $$< -o $$@ $$(Q) $$(CXX) $$(CXXFLAGS) $(CPPFLAGS) $$(addprefix -I,$$(COMPONENT_INCLUDES)) $$(addprefix -I,$$(COMPONENT_EXTRA_INCLUDES)) -I$(1) -c $$< -o $$@
$(1)/%.o: $$(COMPONENT_PATH)/$(1)/%.S | $(1) $(1)/%.o: $$(COMPONENT_PATH)/$(1)/%.S | $(1)
$$(summary) CC $$@ $$(summary) AS $$@
$$(Q) $$(CC) $$(CFLAGS) $$(addprefix -I ,$$(COMPONENT_INCLUDES)) $$(addprefix -I ,$$(COMPONENT_EXTRA_INCLUDES)) -I$(1) -c $$< -o $$@ $$(Q) $$(CC) $$(CFLAGS) $(CPPFLAGS) $$(addprefix -I ,$$(COMPONENT_INCLUDES)) $$(addprefix -I ,$$(COMPONENT_EXTRA_INCLUDES)) -I$(1) -c $$< -o $$@
# CWD is build dir, create the build subdirectory if it doesn't exist # CWD is build dir, create the build subdirectory if it doesn't exist
$(1): $(1):

View File

@ -37,6 +37,7 @@ help:
@echo "'make partition_table', etc, etc." @echo "'make partition_table', etc, etc."
# disable built-in make rules, makes debugging saner # disable built-in make rules, makes debugging saner
MAKEFLAGS_OLD := $(MAKEFLAGS)
MAKEFLAGS +=-rR MAKEFLAGS +=-rR
# Figure out PROJECT_PATH if not set # Figure out PROJECT_PATH if not set
@ -50,6 +51,7 @@ endif
#The directory where we put all objects/libraries/binaries. The project Makefile can #The directory where we put all objects/libraries/binaries. The project Makefile can
#configure this if needed. #configure this if needed.
BUILD_DIR_BASE ?= $(PROJECT_PATH)/build BUILD_DIR_BASE ?= $(PROJECT_PATH)/build
export BUILD_DIR_BASE
#Component directories. These directories are searched for components. #Component directories. These directories are searched for components.
#The project Makefile can override these component dirs, or define extra component directories. #The project Makefile can override these component dirs, or define extra component directories.
@ -105,7 +107,7 @@ COMPONENT_INCLUDES := $(abspath $(foreach comp,$(COMPONENT_PATHS_BUILDABLE),$(ad
$(call GetVariable,$(comp),COMPONENT_ADD_INCLUDEDIRS)))) $(call GetVariable,$(comp),COMPONENT_ADD_INCLUDEDIRS))))
#Also add project include path, for sdk includes #Also add project include path, for sdk includes
COMPONENT_INCLUDES += $(PROJECT_PATH)/build/include/ COMPONENT_INCLUDES += $(abspath $(BUILD_DIR_BASE)/include/)
export COMPONENT_INCLUDES export COMPONENT_INCLUDES
#COMPONENT_LDFLAGS has a list of all flags that are needed to link the components together. It's collected #COMPONENT_LDFLAGS has a list of all flags that are needed to link the components together. It's collected
@ -149,23 +151,61 @@ LDFLAGS ?= -nostdlib \
-Wl,-EL -Wl,-EL
# Set default CPPFLAGS, CFLAGS, CXXFLAGS # Set default CPPFLAGS, CFLAGS, CXXFLAGS
#
# These are exported so that components can use them when compiling. # These are exported so that components can use them when compiling.
#
# If you need your component to add CFLAGS/etc for it's own source compilation only, set CFLAGS += in your component's Makefile. # If you need your component to add CFLAGS/etc for it's own source compilation only, set CFLAGS += in your component's Makefile.
#
# If you need your component to add CFLAGS/etc globally for all source # If you need your component to add CFLAGS/etc globally for all source
# files, set CFLAGS += in your component's Makefile.projbuild # files, set CFLAGS += in your component's Makefile.projbuild
# If you need to set CFLAGS/CPPFLAGS/CXXFLAGS at project level, set them in application Makefile
# before including project.mk. Default flags will be added before the ones provided in application Makefile.
# CPPFLAGS used by an compile pass that uses the C preprocessor # CPPFLAGS used by C preprocessor
CPPFLAGS = -DESP_PLATFORM -Og -g3 -Wpointer-arith -Werror -Wno-error=unused-function -Wno-error=unused-but-set-variable \ # If any flags are defined in application Makefile, add them at the end.
-Wno-error=unused-variable -Wall -ffunction-sections -fdata-sections -mlongcalls -nostdlib -MMD -MP CPPFLAGS := -DESP_PLATFORM $(CPPFLAGS)
# C flags use by C only # Warnings-related flags relevant both for C and C++
CFLAGS = $(CPPFLAGS) -std=gnu99 -g3 -fstrict-volatile-bitfields COMMON_WARNING_FLAGS = -Wall -Werror \
-Wno-error=unused-function \
-Wno-error=unused-but-set-variable \
-Wno-error=unused-variable
# CXXFLAGS uses by C++ only # Flags which control code generation and dependency generation, both for C and C++
CXXFLAGS = $(CPPFLAGS) -Og -std=gnu++11 -g3 -fno-exceptions -fstrict-volatile-bitfields -fno-rtti COMMON_FLAGS = \
-ffunction-sections -fdata-sections \
-fstrict-volatile-bitfields \
-mlongcalls \
-nostdlib \
-MMD -MP
# Optimization flags are set based on menuconfig choice
ifneq ("$(CONFIG_OPTIMIZATION_LEVEL_RELEASE)","")
OPTIMIZATION_FLAGS = -Os
CPPFLAGS += -DNDEBUG
else
OPTIMIZATION_FLAGS = -Og
endif
# Enable generation of debugging symbols
OPTIMIZATION_FLAGS += -ggdb
# List of flags to pass to C compiler
# If any flags are defined in application Makefile, add them at the end.
CFLAGS := $(strip \
-std=gnu99 \
$(OPTIMIZATION_FLAGS) \
$(COMMON_FLAGS) \
$(COMMON_WARNING_FLAGS) \
$(CFLAGS))
# List of flags to pass to C++ compiler
# If any flags are defined in application Makefile, add them at the end.
CXXFLAGS := $(strip \
-std=gnu++11 \
-fno-exceptions \
-fno-rtti \
$(OPTIMIZATION_FLAGS) \
$(COMMON_FLAGS) \
$(COMMON_WARNING_FLAGS) \
$(CXXFLAGS))
export CFLAGS CPPFLAGS CXXFLAGS export CFLAGS CPPFLAGS CXXFLAGS
@ -174,6 +214,7 @@ HOSTCC := $(CC)
HOSTLD := $(LD) HOSTLD := $(LD)
HOSTAR := $(AR) HOSTAR := $(AR)
HOSTOBJCOPY := $(OBJCOPY) HOSTOBJCOPY := $(OBJCOPY)
export HOSTCC HOSTLD HOSTAR HOSTOBJCOPY
#Set target compiler. Defaults to whatever the user has #Set target compiler. Defaults to whatever the user has
#configured as prefix + yer olde gcc commands #configured as prefix + yer olde gcc commands
@ -230,7 +271,7 @@ define GenerateComponentPhonyTarget
# $(2) - target to generate (build, clean) # $(2) - target to generate (build, clean)
.PHONY: $(notdir $(1))-$(2) .PHONY: $(notdir $(1))-$(2)
$(notdir $(1))-$(2): | $(BUILD_DIR_BASE)/$(notdir $(1)) $(notdir $(1))-$(2): | $(BUILD_DIR_BASE)/$(notdir $(1))
@+$(MAKE) -C $(BUILD_DIR_BASE)/$(notdir $(1)) -f $(1)/component.mk COMPONENT_BUILD_DIR=$(BUILD_DIR_BASE)/$(notdir $(1)) $(2) $(Q) +$(MAKE) -C $(BUILD_DIR_BASE)/$(notdir $(1)) -f $(1)/component.mk COMPONENT_BUILD_DIR=$(BUILD_DIR_BASE)/$(notdir $(1)) $(2)
endef endef
define GenerateComponentTargets define GenerateComponentTargets

View File

@ -7,38 +7,38 @@ COMPONENT_KCONFIGS_PROJBUILD := $(foreach component,$(COMPONENT_PATHS),$(wildcar
#For doing make menuconfig etc #For doing make menuconfig etc
KCONFIG_TOOL_DIR=$(IDF_PATH)/tools/kconfig KCONFIG_TOOL_DIR=$(IDF_PATH)/tools/kconfig
# clear MAKEFLAGS as the menuconfig makefile uses implicit compile rules # set SDKCONFIG to the project's sdkconfig,
# unless it's overriden (happens for bootloader)
SDKCONFIG ?= $(PROJECT_PATH)/sdkconfig
# reset MAKEFLAGS as the menuconfig makefile uses implicit compile rules
$(KCONFIG_TOOL_DIR)/mconf $(KCONFIG_TOOL_DIR)/conf: $(KCONFIG_TOOL_DIR)/mconf $(KCONFIG_TOOL_DIR)/conf:
MAKEFLAGS="" \ MAKEFLAGS=$(ORIGINAL_MAKEFLAGS) CC=$(HOSTCC) LD=$(HOSTLD) \
CC=$(HOSTCC) LD=$(HOSTLD) \
$(MAKE) -C $(KCONFIG_TOOL_DIR) $(MAKE) -C $(KCONFIG_TOOL_DIR)
# use a wrapper environment for where we run Kconfig tools
KCONFIG_TOOL_ENV=KCONFIG_AUTOHEADER=$(abspath $(BUILD_DIR_BASE)/include/sdkconfig.h) \
COMPONENT_KCONFIGS="$(COMPONENT_KCONFIGS)" KCONFIG_CONFIG=$(SDKCONFIG) \
COMPONENT_KCONFIGS_PROJBUILD="$(COMPONENT_KCONFIGS_PROJBUILD)"
menuconfig: $(KCONFIG_TOOL_DIR)/mconf $(IDF_PATH)/Kconfig $(BUILD_DIR_BASE) menuconfig: $(KCONFIG_TOOL_DIR)/mconf $(IDF_PATH)/Kconfig $(BUILD_DIR_BASE)
$(summary) MENUCONFIG $(summary) MENUCONFIG
$(Q) KCONFIG_AUTOHEADER=$(PROJECT_PATH)/build/include/sdkconfig.h \ $(Q) $(KCONFIG_TOOL_ENV) $(KCONFIG_TOOL_DIR)/mconf $(IDF_PATH)/Kconfig
KCONFIG_CONFIG=$(PROJECT_PATH)/sdkconfig \
COMPONENT_KCONFIGS="$(COMPONENT_KCONFIGS)" \
COMPONENT_KCONFIGS_PROJBUILD="$(COMPONENT_KCONFIGS_PROJBUILD)" \
$(KCONFIG_TOOL_DIR)/mconf $(IDF_PATH)/Kconfig
ifeq ("$(wildcard $(PROJECT_PATH)/sdkconfig)","") ifeq ("$(wildcard $(SDKCONFIG))","")
#No sdkconfig found. Need to run menuconfig to make this if we need it. #No sdkconfig found. Need to run menuconfig to make this if we need it.
$(PROJECT_PATH)/sdkconfig: menuconfig $(SDKCONFIG): menuconfig
endif endif
defconfig: $(KCONFIG_TOOL_DIR)/mconf $(IDF_PATH)/Kconfig $(BUILD_DIR_BASE) defconfig: $(KCONFIG_TOOL_DIR)/mconf $(IDF_PATH)/Kconfig $(BUILD_DIR_BASE)
$(summary) DEFCONFIG $(summary) DEFCONFIG
$(Q) mkdir -p $(PROJECT_PATH)/build/include/config $(Q) mkdir -p $(BUILD_DIR_BASE)/include/config
$(Q) KCONFIG_AUTOHEADER=$(PROJECT_PATH)/build/include/sdkconfig.h \ $(Q) $(KCONFIG_TOOL_ENV) $(KCONFIG_TOOL_DIR)/conf --olddefconfig $(IDF_PATH)/Kconfig
KCONFIG_CONFIG=$(PROJECT_PATH)/sdkconfig \
COMPONENT_KCONFIGS="$(COMPONENT_KCONFIGS)" \
COMPONENT_KCONFIGS_PROJBUILD="$(COMPONENT_KCONFIGS_PROJBUILD)" \
$(KCONFIG_TOOL_DIR)/conf --olddefconfig $(IDF_PATH)/Kconfig
# Work out of whether we have to build the Kconfig makefile # Work out of whether we have to build the Kconfig makefile
# (auto.conf), or if we're in a situation where we don't need it # (auto.conf), or if we're in a situation where we don't need it
NON_CONFIG_TARGETS := clean %-clean get_variable help menuconfig defconfig NON_CONFIG_TARGETS := clean %-clean get_variable help menuconfig defconfig
AUTO_CONF_REGEN_TARGET := $(PROJECT_PATH)/build/include/config/auto.conf AUTO_CONF_REGEN_TARGET := $(BUILD_DIR_BASE)/include/config/auto.conf
# disable AUTO_CONF_REGEN_TARGET if all targets are non-config targets # disable AUTO_CONF_REGEN_TARGET if all targets are non-config targets
# (and not building default target) # (and not building default target)
@ -46,19 +46,15 @@ ifneq ("$(MAKECMDGOALS)","")
ifeq ($(filter $(NON_CONFIG_TARGETS), $(MAKECMDGOALS)),$(MAKECMDGOALS)) ifeq ($(filter $(NON_CONFIG_TARGETS), $(MAKECMDGOALS)),$(MAKECMDGOALS))
AUTO_CONF_REGEN_TARGET := AUTO_CONF_REGEN_TARGET :=
# dummy target # dummy target
$(PROJECT_PATH)/build/include/config/auto.conf: $(BUILD_DIR_BASE)/include/config/auto.conf:
endif endif
endif endif
$(AUTO_CONF_REGEN_TARGET) $(PROJECT_PATH)/build/include/sdkconfig.h: $(PROJECT_PATH)/sdkconfig $(KCONFIG_TOOL_DIR)/conf $(COMPONENT_KCONFIGS) $(COMPONENT_KCONFIGS_PROJBUILD) $(AUTO_CONF_REGEN_TARGET) $(BUILD_DIR_BASE)/include/sdkconfig.h: $(SDKCONFIG) $(KCONFIG_TOOL_DIR)/conf $(COMPONENT_KCONFIGS) $(COMPONENT_KCONFIGS_PROJBUILD)
$(summary) GENCONFIG $(summary) GENCONFIG
$(Q) mkdir -p $(PROJECT_PATH)/build/include/config $(Q) mkdir -p $(BUILD_DIR_BASE)/include/config
$(Q) cd build; KCONFIG_AUTOHEADER="$(PROJECT_PATH)/build/include/sdkconfig.h" \ $(Q) cd $(BUILD_DIR_BASE); $(KCONFIG_TOOL_ENV) $(KCONFIG_TOOL_DIR)/conf --silentoldconfig $(IDF_PATH)/Kconfig
KCONFIG_CONFIG=$(PROJECT_PATH)/sdkconfig \ $(Q) touch $(AUTO_CONF_REGEN_TARGET) $(BUILD_DIR_BASE)/include/sdkconfig.h
COMPONENT_KCONFIGS="$(COMPONENT_KCONFIGS)" \
COMPONENT_KCONFIGS_PROJBUILD="$(COMPONENT_KCONFIGS_PROJBUILD)" \
$(KCONFIG_TOOL_DIR)/conf --silentoldconfig $(IDF_PATH)/Kconfig
$(Q) touch $(AUTO_CONF_REGEN_TARGET) $(PROJECT_PATH)/build/include/sdkconfig.h
# touch to ensure both output files are newer - as 'conf' can also update sdkconfig (a dependency). Without this, # touch to ensure both output files are newer - as 'conf' can also update sdkconfig (a dependency). Without this,
# sometimes you can get an infinite make loop on Windows where sdkconfig always gets regenerated newer # sometimes you can get an infinite make loop on Windows where sdkconfig always gets regenerated newer
# than the target(!) # than the target(!)
@ -68,4 +64,4 @@ clean: config-clean
config-clean: config-clean:
$(summary RM CONFIG) $(summary RM CONFIG)
$(MAKE) -C $(KCONFIG_TOOL_DIR) clean $(MAKE) -C $(KCONFIG_TOOL_DIR) clean
$(Q) rm -rf $(PROJECT_PATH)/build/include/config $(PROJECT_PATH)/build/include/sdkconfig.h $(Q) rm -rf $(BUILD_DIR_BASE)/include/config $(BUILD_DIR_BASE)/include/sdkconfig.h

View File

@ -2,7 +2,7 @@
# #
# Test the build system for basic consistency # Test the build system for basic consistency
# #
# Just a bash script that tests some likely make failure scenarios in a row # A bash script that tests some likely make failure scenarios in a row
# Creates its own test build directory under TMP and cleans it up when done. # Creates its own test build directory under TMP and cleans it up when done.
# #
# Environment variables: # Environment variables:
@ -11,6 +11,18 @@
# ESP_IDF_TEMPLATE_GIT - Can override git clone source for template app. Otherwise github. # ESP_IDF_TEMPLATE_GIT - Can override git clone source for template app. Otherwise github.
# NOCLEANUP - Set to '1' if you want the script to leave its temporary directory when done, for post-mortem. # NOCLEANUP - Set to '1' if you want the script to leave its temporary directory when done, for post-mortem.
# #
#
# Internals:
# * The tests run in sequence & the system keeps track of all failures to print at the end.
# * BUILD directory is set to default BUILD_DIR_BASE
# * The "print_status" function both prints a status line to the log and keeps track of which test is running.
# * Calling the "failure" function prints a failure message to the log and also adds to the list of failures to print at the end.
# * The function "assert_built" tests for a file relative to the BUILD directory.
# * The function "take_build_snapshot" can be paired with the functions "assert_rebuilt" and "assert_not_rebuilt" to compare file timestamps and verify if they were rebuilt or not since the snapshot was taken.
#
# To add a new test case, add it to the end of the run_tests function. Note that not all test cases do comprehensive cleanup
# (although very invasive ones like appending CRLFs to all files take a copy of the esp-idf tree), however the clean_build_dir
# function can be used to force-delete all files from the build output directory.
# Set up some variables # Set up some variables
# #
@ -21,103 +33,137 @@ export V=1
function run_tests() function run_tests()
{ {
FAILURES= FAILURES=
STATUS="Starting" STATUS="Starting"
print_status "Checking prerequisites" print_status "Checking prerequisites"
[ -z ${IDF_PATH} ] && echo "IDF_PATH is not set. Need path to esp-idf installation." && exit 2 [ -z ${IDF_PATH} ] && echo "IDF_PATH is not set. Need path to esp-idf installation." && exit 2
print_status "Cloning template from ${ESP_IDF_TEMPLATE_GIT}..." print_status "Cloning template from ${ESP_IDF_TEMPLATE_GIT}..."
git clone ${ESP_IDF_TEMPLATE_GIT} template git clone ${ESP_IDF_TEMPLATE_GIT} template
cd template cd template
git checkout ${CI_BUILD_REF_NAME} || echo "Using esp-idf-template default branch..." git checkout ${CI_BUILD_REF_NAME} || echo "Using esp-idf-template default branch..."
print_status "Updating template config..." print_status "Updating template config..."
make defconfig || exit $? make defconfig || exit $?
BOOTLOADER_BINS="bootloader/bootloader.elf bootloader/bootloader.bin" BOOTLOADER_BINS="bootloader/bootloader.elf bootloader/bootloader.bin"
APP_BINS="app-template.elf app-template.bin" APP_BINS="app-template.elf app-template.bin"
print_status "Initial clean build" print_status "Initial clean build"
# if make fails here, everything fails # if make fails here, everything fails
make || exit $? make || exit $?
# check all the expected build artifacts from the clean build # check all the expected build artifacts from the clean build
assert_built ${APP_BINS} ${BOOTLOADER_BINS} partitions_singleapp.bin assert_built ${APP_BINS} ${BOOTLOADER_BINS} partitions_singleapp.bin
[ -f ${BUILD}/partition*.bin ] || failure "A partition table should have been built" [ -f ${BUILD}/partition*.bin ] || failure "A partition table should have been built"
print_status "Updating component source file rebuilds component" print_status "Updating component source file rebuilds component"
# touch a file & do a build # touch a file & do a build
take_build_snapshot take_build_snapshot
touch ${IDF_PATH}/components/esp32/syscalls.c touch ${IDF_PATH}/components/esp32/syscalls.c
make || failure "Failed to partial build" make || failure "Failed to partial build"
assert_rebuilt ${APP_BINS} esp32/libesp32.a esp32/syscalls.o assert_rebuilt ${APP_BINS} esp32/libesp32.a esp32/syscalls.o
assert_not_rebuilt lwip/liblwip.a freertos/libfreertos.a ${BOOTLOADER_BINS} partitions_singleapp.bin assert_not_rebuilt lwip/liblwip.a freertos/libfreertos.a ${BOOTLOADER_BINS} partitions_singleapp.bin
print_status "Bootloader source file rebuilds bootloader" print_status "Bootloader source file rebuilds bootloader"
take_build_snapshot take_build_snapshot
touch ${IDF_PATH}/components/bootloader/src/main/bootloader_start.c touch ${IDF_PATH}/components/bootloader/src/main/bootloader_start.c
make bootloader || failure "Failed to partial build bootloader" make bootloader || failure "Failed to partial build bootloader"
assert_rebuilt ${BOOTLOADER_BINS} bootloader/main/bootloader_start.o assert_rebuilt ${BOOTLOADER_BINS} bootloader/main/bootloader_start.o
assert_not_rebuilt ${APP_BINS} partitions_singleapp.bin assert_not_rebuilt ${APP_BINS} partitions_singleapp.bin
print_status "Partition CSV file rebuilds partitions" print_status "Partition CSV file rebuilds partitions"
take_build_snapshot take_build_snapshot
touch ${IDF_PATH}/components/partition_table/partitions_singleapp.csv touch ${IDF_PATH}/components/partition_table/partitions_singleapp.csv
make partition_table make partition_table || failure "Failed to build partition table"
assert_rebuilt partitions_singleapp.bin assert_rebuilt partitions_singleapp.bin
assert_not_rebuilt app-template.bin app-template.elf ${BOOTLOADER_BINS} assert_not_rebuilt app-template.bin app-template.elf ${BOOTLOADER_BINS}
print_status "Partial build doesn't compile anything by default" print_status "Partial build doesn't compile anything by default"
take_build_snapshot take_build_snapshot
# verify no build files are refreshed by a partial make # verify no build files are refreshed by a partial make
ALL_BUILD_FILES=$(find ${BUILD} -type f | sed "s@${BUILD}/@@") ALL_BUILD_FILES=$(find ${BUILD} -type f | sed "s@${BUILD}/@@")
make make || failure "Partial build failed"
assert_not_rebuilt ${ALL_BUILD_FILES} assert_not_rebuilt ${ALL_BUILD_FILES}
print_status "Cleaning should remove all files from build" print_status "Cleaning should remove all files from build"
make clean make clean || failure "Failed to make clean"
ALL_BUILD_FILES=$(find ${BUILD} -type f) ALL_BUILD_FILES=$(find ${BUILD} -type f)
if [ -n "${ALL_BUILD_FILES}" ]; then if [ -n "${ALL_BUILD_FILES}" ]; then
failure "Files weren't cleaned: ${ALL_BUILD_FILES}" failure "Files weren't cleaned: ${ALL_BUILD_FILES}"
fi fi
print_status "Can still clean build if all text files are CRLFs" print_status "Bootloader build shouldn't leave build output anywhere else"
make clean clean_build_dir
find . -exec unix2dos {} \; # CRLFify template dir make bootloader
# make a copy of esp-idf and CRLFify it # find wizardry: find any file not named sdkconfig.h that
CRLF_ESPIDF=${TESTDIR}/esp-idf-crlf # isn't in the "bootloader" or "config" directories
mkdir -p ${CRLF_ESPIDF} find ${BUILD} -type d \( -name bootloader -o -name config \) -prune , -type f ! -name sdkconfig.h || failure "Bootloader built files outside the bootloader or config directories"
cp -rv ${IDF_PATH}/* ${CRLF_ESPIDF}
# don't CRLFify executable files, as Linux will fail to execute them
find ${CRLF_ESPIDF} -type f ! -perm 755 -exec unix2dos {} \;
make IDF_PATH=${CRLF_ESPIDF}
# do the same checks we do for the clean build
assert_built ${APP_BINS} ${BOOTLOADER_BINS} partitions_singleapp.bin
[ -f ${BUILD}/partition*.bin ] || failure "A partition table should have been built in CRLF mode"
# NOTE: If adding new tests, add them above this CRLF test... print_status "Moving BUILD_DIR_BASE out of tree"
clean_build_dir
OUTOFTREE_BUILD=${TESTDIR}/alt_build
make BUILD_DIR_BASE=${OUTOFTREE_BUILD} || failure "Failed to build with BUILD_DIR_BASE overriden"
NEW_BUILD_FILES=$(find ${OUTOFREE_BUILD} -type f)
if [ -z "${NEW_BUILD_FILES}" ]; then
failure "No files found in new build directory!"
fi
DEFAULT_BUILD_FILES=$(find ${BUILD} -mindepth 1)
if [ -n "${DEFAULT_BUILD_FILES}" ]; then
failure "Some files were incorrectly put into the default build directory: ${DEFAULT_BUILD_FILES}"
fi
print_status "All tests completed" print_status "BUILD_DIR_BASE inside default build directory"
if [ -n "${FAILURES}" ]; then clean_build_dir
echo "Some failures were detected:" make BUILD_DIR_BASE=build/subdirectory || failure "Failed to build with BUILD_DIR_BASE as subdir"
echo -e "${FAILURES}" NEW_BUILD_FILES=$(find ${BUILD}/subdirectory -type f)
exit 1 if [ -z "${NEW_BUILD_FILES}" ]; then
else failure "No files found in new build directory!"
echo "Build tests passed." fi
fi
print_status "Parallel builds should work OK"
clean_build_dir
(make -j5 2>&1 | tee ${TESTDIR}/parallel_build.log) || failure "Failed to build in parallel"
if grep -q "warning: jobserver unavailable" ${TESTDIR}/parallel_build.log; then
failure "Parallel build prints 'warning: jobserver unavailable' errors"
fi
print_status "Can still clean build if all text files are CRLFs"
make clean || failure "Unexpected failure to make clean"
find . -exec unix2dos {} \; # CRLFify template dir
# make a copy of esp-idf and CRLFify it
CRLF_ESPIDF=${TESTDIR}/esp-idf-crlf
mkdir -p ${CRLF_ESPIDF}
cp -rv ${IDF_PATH}/* ${CRLF_ESPIDF}
# don't CRLFify executable files, as Linux will fail to execute them
find ${CRLF_ESPIDF} -type f ! -perm 755 -exec unix2dos {} \;
make IDF_PATH=${CRLF_ESPIDF} || failure "Failed to build with CRLFs in source"
# do the same checks we do for the clean build
assert_built ${APP_BINS} ${BOOTLOADER_BINS} partitions_singleapp.bin
[ -f ${BUILD}/partition*.bin ] || failure "A partition table should have been built in CRLF mode"
print_status "All tests completed"
if [ -n "${FAILURES}" ]; then
echo "Some failures were detected:"
echo -e "${FAILURES}"
exit 1
else
echo "Build tests passed."
fi
} }
function print_status() function print_status()
{ {
echo "******** $1" echo "******** $1"
STATUS="$1" STATUS="$1"
} }
function failure() function failure()
{ {
echo "!!!!!!!!!!!!!!!!!!!" echo "!!!!!!!!!!!!!!!!!!!"
echo "FAILURE: $1" echo "FAILURE: $1"
echo "!!!!!!!!!!!!!!!!!!!" echo "!!!!!!!!!!!!!!!!!!!"
FAILURES="${FAILURES}${STATUS} :: $1\n" FAILURES="${FAILURES}${STATUS} :: $1\n"
} }
TESTDIR=${TMP}/build_system_tests_$$ TESTDIR=${TMP}/build_system_tests_$$
@ -133,62 +179,68 @@ BUILD=${TESTDIR}/template/build
# copy all the build output to a snapshot directory # copy all the build output to a snapshot directory
function take_build_snapshot() function take_build_snapshot()
{ {
rm -rf ${SNAPSHOT} rm -rf ${SNAPSHOT}
cp -ap ${TESTDIR}/template/build ${SNAPSHOT} cp -ap ${TESTDIR}/template/build ${SNAPSHOT}
} }
# verify that all the arguments are present in the build output directory # verify that all the arguments are present in the build output directory
function assert_built() function assert_built()
{ {
until [ -z "$1" ]; do until [ -z "$1" ]; do
if [ ! -f "${BUILD}/$1" ]; then if [ ! -f "${BUILD}/$1" ]; then
failure "File $1 should be in the build output directory" failure "File $1 should be in the build output directory"
fi fi
shift shift
done done
} }
# Test if a file has been rebuilt. # Test if a file has been rebuilt.
function file_was_rebuilt() function file_was_rebuilt()
{ {
# can't use [ a -ot b ] here as -ot only gives second resolution # can't use [ a -ot b ] here as -ot only gives second resolution
# but stat -c %y seems to be microsecond at least for tmpfs, ext4.. # but stat -c %y seems to be microsecond at least for tmpfs, ext4..
if [ "$(stat -c %y ${SNAPSHOT}/$1)" != "$(stat -c %y ${BUILD}/$1)" ]; then if [ "$(stat -c %y ${SNAPSHOT}/$1)" != "$(stat -c %y ${BUILD}/$1)" ]; then
return 0 return 0
else else
return 1 return 1
fi fi
} }
# verify all the arguments passed in were rebuilt relative to the snapshot # verify all the arguments passed in were rebuilt relative to the snapshot
function assert_rebuilt() function assert_rebuilt()
{ {
until [ -z "$1" ]; do until [ -z "$1" ]; do
assert_built "$1" assert_built "$1"
if [ ! -f "${SNAPSHOT}/$1" ]; then if [ ! -f "${SNAPSHOT}/$1" ]; then
failure "File $1 should have been original build snapshot" failure "File $1 should have been original build snapshot"
fi fi
if ! file_was_rebuilt "$1"; then if ! file_was_rebuilt "$1"; then
failure "File $1 should have been rebuilt" failure "File $1 should have been rebuilt"
fi fi
shift shift
done done
} }
# verify all the arguments are in the build directory & snapshot, # verify all the arguments are in the build directory & snapshot,
# but were not rebuilt # but were not rebuilt
function assert_not_rebuilt() function assert_not_rebuilt()
{ {
until [ -z "$1" ]; do until [ -z "$1" ]; do
assert_built "$1" assert_built "$1"
if [ ! -f "${SNAPSHOT}/$1" ]; then if [ ! -f "${SNAPSHOT}/$1" ]; then
failure "File $1 should be in snapshot build directory" failure "File $1 should be in snapshot build directory"
fi fi
if file_was_rebuilt "$1"; then if file_was_rebuilt "$1"; then
failure "File $1 should not have been rebuilt" failure "File $1 should not have been rebuilt"
fi fi
shift shift
done done
}
# do a "clean" that doesn't depend on 'make clean'
function clean_build_dir()
{
rm -rf --preserve-root ${BUILD}/*
} }
cd ${TESTDIR} cd ${TESTDIR}