Merge branch 'master' into bugfix/btdm_bluedroid

This commit is contained in:
Tian Hao 2016-12-15 14:40:29 +08:00
commit 5a2033c4e3
142 changed files with 9240 additions and 911 deletions

View File

@ -247,6 +247,8 @@ deploy_docs:
expire_in: 6 mos
script:
# remove artifacts from last stage (UT logs)
- rm -rf $LOG_PATH
# add gitlab ssh key
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
@ -268,6 +270,8 @@ deploy_docs:
# can only be triggered
- triggers
script:
# remove artifacts from last stage (UT logs)
- rm -rf $LOG_PATH
# must be night build triggers, otherwise exit without test
- test $NIGHT_BUILD = "Yes" || exit 0
# add gitlab ssh key
@ -345,7 +349,6 @@ IT_Function_TCPIP_02:
tags:
- ESP32_IDF
- SSC_T1_1
- SSC_T2_1
before_script:
- CONFIG_FILE=$TEST_CASE_FILE_PATH/CIConfigs/IT_Function_TCPIP_02.yml
@ -372,10 +375,73 @@ IT_Function_TCPIP_05:
tags:
- ESP32_IDF
- SSC_T1_1
- SSC_T2_1
before_script:
- CONFIG_FILE=$TEST_CASE_FILE_PATH/CIConfigs/IT_Function_TCPIP_05.yml
IT_Stress_WIFI_01:
<<: *test_template_night
tags:
- ESP32_IDF
- SSC_T5_1
before_script:
- CONFIG_FILE=$TEST_CASE_FILE_PATH/CIConfigs/IT_Stress_WIFI_01.yml
IT_Stress_TCPIP_01:
<<: *test_template_night
tags:
- ESP32_IDF
- SSC_T1_1
before_script:
- CONFIG_FILE=$TEST_CASE_FILE_PATH/CIConfigs/IT_Stress_TCPIP_01.yml
IT_Stress_TCPIP_02:
<<: *test_template_night
tags:
- ESP32_IDF
- SSC_T2_1
before_script:
- CONFIG_FILE=$TEST_CASE_FILE_PATH/CIConfigs/IT_Stress_TCPIP_02.yml
IT_Stress_TCPIP_03:
<<: *test_template_night
tags:
- ESP32_IDF
- SSC_T1_1
before_script:
- CONFIG_FILE=$TEST_CASE_FILE_PATH/CIConfigs/IT_Stress_TCPIP_03.yml
IT_Stress_TCPIP_04:
<<: *test_template_night
tags:
- ESP32_IDF
- SSC_T2_1
before_script:
- CONFIG_FILE=$TEST_CASE_FILE_PATH/CIConfigs/IT_Stress_TCPIP_04.yml
IT_Stable_TCPIP_01:
<<: *test_template_night
tags:
- ESP32_IDF
- SSC_T5_1
before_script:
- CONFIG_FILE=$TEST_CASE_FILE_PATH/CIConfigs/IT_Stable_TCPIP_01.yml
IT_Stable_TCPIP_02:
<<: *test_template_night
tags:
- ESP32_IDF
- SSC_T1_1
before_script:
- CONFIG_FILE=$TEST_CASE_FILE_PATH/CIConfigs/IT_Stable_TCPIP_02.yml
IT_Stable_TCPIP_03:
<<: *test_template_night
tags:
- ESP32_IDF
- SSC_T5_1
before_script:
- CONFIG_FILE=$TEST_CASE_FILE_PATH/CIConfigs/IT_Stable_TCPIP_03.yml
IT_Function_TCPIP_06:
<<: *test_template_night
tags:
@ -388,7 +454,7 @@ IT_Function_WIFI_03:
<<: *test_template
tags:
- ESP32_IDF
- SSC_T3_PhyMode
- SSC_T1_APC
before_script:
- CONFIG_FILE=$TEST_CASE_FILE_PATH/CIConfigs/IT_Function_WIFI_03.yml
@ -396,7 +462,7 @@ IT_Function_WIFI_04:
<<: *test_template
tags:
- ESP32_IDF
- SSC_T1_APC
- SSC_T3_PhyMode
before_script:
- CONFIG_FILE=$TEST_CASE_FILE_PATH/CIConfigs/IT_Function_WIFI_04.yml
@ -422,7 +488,6 @@ IT_Function_TCPIP_07:
- ESP32_IDF
- SSC_T1_1
- SSC_T1_2
- SSC_T2_1
before_script:
- CONFIG_FILE=$TEST_CASE_FILE_PATH/CIConfigs/IT_Function_TCPIP_07.yml
@ -431,6 +496,7 @@ IT_Function_TCPIP_08:
tags:
- ESP32_IDF
- SSC_T1_1
- SSC_T2_1
before_script:
- CONFIG_FILE=$TEST_CASE_FILE_PATH/CIConfigs/IT_Function_TCPIP_08.yml
@ -439,6 +505,7 @@ IT_Function_TCPIP_09:
tags:
- ESP32_IDF
- SSC_T1_1
- SSC_T1_2
before_script:
- CONFIG_FILE=$TEST_CASE_FILE_PATH/CIConfigs/IT_Function_TCPIP_09.yml
@ -448,7 +515,6 @@ IT_Function_TCPIP_10:
- ESP32_IDF
- SSC_T1_1
- SSC_T1_2
- SSC_T2_1
before_script:
- CONFIG_FILE=$TEST_CASE_FILE_PATH/CIConfigs/IT_Function_TCPIP_10.yml
@ -457,7 +523,6 @@ IT_Function_TCPIP_11:
tags:
- ESP32_IDF
- SSC_T1_1
- SSC_T1_2
before_script:
- CONFIG_FILE=$TEST_CASE_FILE_PATH/CIConfigs/IT_Function_TCPIP_11.yml
@ -468,3 +533,4 @@ IT_Function_TCPIP_12:
- SSC_T1_1
before_script:
- CONFIG_FILE=$TEST_CASE_FILE_PATH/CIConfigs/IT_Function_TCPIP_12.yml

View File

@ -1,7 +1,7 @@
menu "Bootloader config"
choice LOG_BOOTLOADER_LEVEL
bool "Bootloader log verbosity"
default LOG_BOOTLOADER_LEVEL_WARN
default LOG_BOOTLOADER_LEVEL_INFO
help
Specify how much output to see in bootloader logs.
@ -32,23 +32,24 @@ endmenu
menu "Secure boot configuration"
menu "Security features"
choice SECURE_BOOTLOADER
bool "Secure bootloader"
default SECURE_BOOTLOADER_DISABLED
config SECURE_BOOT_ENABLED
bool "Enable secure boot in bootloader"
default N
help
Build a bootloader with the secure boot flag enabled.
Build a bootloader which enables secure boot on first boot.
Secure bootloader can be one-time-flash (chip will only ever
boot that particular bootloader), or a digest key can be used
to allow the secure bootloader to be re-flashed with
modifications. Secure boot also permanently disables JTAG.
Once enabled, secure boot will not boot a modified bootloader. The bootloader will only load a partition table or boot an app if the data has a verified digital signature.
When enabling secure boot, JTAG and ROM BASIC Interpreter are permanently disabled by default.
See docs/security/secure-boot.rst for details.
config SECURE_BOOTLOADER_DISABLED
bool "Disabled"
choice SECURE_BOOTLOADER_MODE
bool "Secure bootloader mode"
depends on SECURE_BOOT_ENABLED
default SECURE_BOOTLOADER_ONE_TIME_FLASH
config SECURE_BOOTLOADER_ONE_TIME_FLASH
bool "One-time flash"
@ -62,7 +63,7 @@ config SECURE_BOOTLOADER_REFLASHABLE
help
Generate a reusable secure bootloader key, derived (via SHA-256) from the secure boot signing key.
This allows the secure bootloader to be re-flashed by anyone with access to the secure boot signing key.
This allows the secure bootloader to be re-flashed by anyone with access to the secure boot signing key.
This option is less secure than one-time flash, because a leak of the digest key from one device allows reflashing of any device that uses it.
@ -70,10 +71,10 @@ endchoice
config SECURE_BOOT_SIGNING_KEY
string "Secure boot signing key"
depends on SECURE_BOOTLOADER_ENABLED
default secure_boot_signing_key.pem
depends on SECURE_BOOT_ENABLED
default secure_boot_signing_key.pem
help
Path to the key file used to sign partition tables and app images for secure boot.
Path to the key file used to sign partition tables and app images for secure boot. Once secure boot is enabled, bootloader will only boot if partition table and app image are signed.
Key file is an ECDSA private key (NIST256p curve) in PEM format.
@ -84,35 +85,106 @@ config SECURE_BOOT_SIGNING_KEY
See docs/security/secure-boot.rst for details.
config SECURE_BOOT_DISABLE_JTAG
bool "First boot: Permanently disable JTAG"
depends on SECURE_BOOTLOADER_ENABLED
default Y
config SECURE_BOOT_INSECURE
bool "Allow potentially insecure options"
depends on SECURE_BOOT_ENABLED
default N
help
You can disable some of the default protections offered by secure boot, in order to enable testing or a custom combination of security features.
Only enable these options if you are very sure.
Refer to docs/security/secure-boot.rst and docs/security/flash-encryption.rst for details.
config FLASH_ENCRYPTION_ENABLED
bool "Enable flash encryption on boot"
default N
help
If this option is set, flash contents will be encrypted by the bootloader on first boot.
Note: After first boot, the system will be permanently encrypted.
See docs/securityflash-encryption.rst for details.
config FLASH_ENCRYPTION_INSECURE
bool "Allow potentially insecure options"
depends on FLASH_ENCRYPTION_ENABLED
default N
help
You can disable some of the default protections offered by flash encryption, in order to enable testing or a custom combination of security features.
Only enable these options if you are very sure.
Refer to docs/security/secure-boot.rst and docs/security/flash-encryption.rst for details.
menu "Potentially insecure options"
visible if FLASH_ENCRYPTION_INSECURE || SECURE_BOOT_INSECURE
# NOTE: Options in this menu NEED to have SECURE_BOOT_INSECURE
# and/or FLASH_ENCRYPTION_INSECURE in "depends on", as the menu
# itself doesn't enable/disable its children (if it's not set,
# it's possible for the insecure menu to be disabled but the insecure option
# to remain on which is very bad.)
config SECURE_BOOT_ALLOW_ROM_BASIC
bool "Leave ROM BASIC Interpreter available on reset"
depends on SECURE_BOOT_INSECURE
default N
help
Bootloader permanently disable JTAG (across entire chip) when enabling secure boot. This happens on first boot of the bootloader.
If not set (default), bootloader permanently disables ROM BASIC (on UART console) as a fallback if the bootloader image becomes invalid. This happens on first boot.
It is recommended this option remains set for production environments.
Only set this option in testing environments.
config SECURE_BOOT_DISABLE_ROM_BASIC
bool "First boot: Permanently disable ROM BASIC fallback"
depends on SECURE_BOOTLOADER_ENABLED
default Y
config SECURE_BOOT_ALLOW_JTAG
bool "Allow JTAG Debugging"
depends on SECURE_BOOT_INSECURE || FLASH_ENCRYPTION_INSECURE
default N
help
Bootloader permanently disables ROM BASIC (on UART console) as a fallback if the bootloader image becomes invalid. This happens on first boot.
If not set (default), the bootloader will permanently disable JTAG (across entire chip) on first boot when either secure boot or flash encryption is enabled.
It is recommended this option remains set in production environments.
Setting this option leaves JTAG on for debugging, which negates all protections of flash encryption and some of the protections of secure boot.
Only set this option in testing environments.
config FLASH_ENCRYPTION_UART_BOOTLOADER_ALLOW_ENCRYPT
bool "Leave UART bootloader encryption enabled"
depends on FLASH_ENCRYPTION_INSECURE
default N
help
If not set (default), the bootloader will permanently disable UART bootloader encryption access on first boot. If set, the UART bootloader will still be able to access hardware encryption.
It is recommended to only set this option in testing environments.
config FLASH_ENCRYPTION_UART_BOOTLOADER_ALLOW_DECRYPT
bool "Leave UART bootloader decryption enabled"
depends on FLASH_ENCRYPTION_INSECURE
default N
help
If not set (default), the bootloader will permanently disable UART bootloader decryption access on first boot. If set, the UART bootloader will still be able to access hardware decryption.
Only set this option in testing environments. Setting this option allows complete bypass of flash encryption.
config FLASH_ENCRYPTION_UART_BOOTLOADER_ALLOW_CACHE
bool "Leave UART bootloader flash cache enabled"
depends on FLASH_ENCRYPTION_INSECURE
default N
help
If not set (default), the bootloader will permanently disable UART bootloader flash cache access on first boot. If set, the UART bootloader will still be able to access the flash cache.
Only set this option in testing environments.
config SECURE_BOOT_TEST_MODE
bool "Test mode: don't actually enable secure boot"
depends on SECURE_BOOTLOADER_ENABLED
bool "Secure boot test mode: don't permanently set any efuses"
depends on SECURE_BOOT_INSECURE
default N
help
If this option is set, all permanent secure boot changes (via Efuse) are disabled.
This option is for testing purposes only - it effectively completely disables secure boot protection.
Log output will state changes which would be applied, but they will not be.
config SECURE_BOOTLOADER_ENABLED
bool
default SECURE_BOOTLOADER_ONE_TIME_FLASH || SECURE_BOOTLOADER_REFLASHABLE
This option is for testing purposes only - it completely disables secure boot protection.
endmenu # potentially insecure
endmenu

View File

@ -18,6 +18,9 @@ BOOTLOADER_BIN=$(BOOTLOADER_BUILD_DIR)/bootloader.bin
SECURE_BOOT_SIGNING_KEY=$(abspath $(call dequote,$(CONFIG_SECURE_BOOT_SIGNING_KEY)))
export SECURE_BOOT_SIGNING_KEY # used by bootloader_support component
# Has a matching value in bootloader_support esp_flash_partitions.h
BOOTLOADER_OFFSET := 0x1000
# Custom recursive make for bootloader sub-project
BOOTLOADER_MAKE=+$(MAKE) -C $(BOOTLOADER_COMPONENT_PATH)/src \
V=$(V) BUILD_DIR_BASE=$(BOOTLOADER_BUILD_DIR) TEST_COMPONENTS=
@ -29,55 +32,36 @@ $(BOOTLOADER_BIN): $(SDKCONFIG_MAKEFILE)
clean: bootloader-clean
ifdef CONFIG_SECURE_BOOTLOADER_DISABLED
ifndef CONFIG_SECURE_BOOT_ENABLED
# If secure boot disabled, bootloader flashing is integrated
# with 'make flash' and no warnings are printed.
bootloader: $(BOOTLOADER_BIN)
@echo $(SEPARATOR)
@echo "Bootloader built. Default flash command is:"
@echo "$(ESPTOOLPY_WRITE_FLASH) 0x1000 $^"
@echo "$(ESPTOOLPY_WRITE_FLASH) $(BOOTLOADER_OFFSET) $^"
ESPTOOL_ALL_FLASH_ARGS += 0x1000 $(BOOTLOADER_BIN)
ESPTOOL_ALL_FLASH_ARGS += $(BOOTLOADER_OFFSET) $(BOOTLOADER_BIN)
bootloader-flash: $(BOOTLOADER_BIN)
$(ESPTOOLPY_WRITE_FLASH) 0x1000 $^
else ifdef CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH
#### TEMPORARILY DISABLE THIS OPTION
ifneq ("$(IDF_INSECURE_SECURE_BOOT)","1")
bootloader:
@echo "Secure boot features are not yet mature, so the current secure bootloader will not properly secure the device"
@echo "If you flash this bootloader, you will be left with an non-updateable bootloader that is missing features."
@echo "If you really want to do this, set the environment variable IDF_INSECURE_SECURE_BOOT=1 and rerun make."
exit 1
else
# One time flashing requires user to run esptool.py command themselves,
# and warning is printed about inability to reflash.
bootloader: $(BOOTLOADER_BIN)
@echo $(SEPARATOR)
@echo "Bootloader built. One-time flash command is:"
@echo "$(ESPTOOLPY_WRITE_FLASH) 0x1000 $(BOOTLOADER_BIN)"
@echo "$(ESPTOOLPY_WRITE_FLASH) $(BOOTLOADER_OFFSET) $(BOOTLOADER_BIN)"
@echo $(SEPARATOR)
@echo "* IMPORTANT: After first boot, BOOTLOADER CANNOT BE RE-FLASHED on same device"
endif # IDF_INSECURE_SECURE_BOOT
else ifdef CONFIG_SECURE_BOOTLOADER_REFLASHABLE
# Reflashable secure bootloader
# generates a digest binary (bootloader + digest)
#### TEMPORARILY DISABLE THIS OPTION
ifneq ("$(IDF_INSECURE_SECURE_BOOT)","1")
bootloader:
@echo "Secure boot features are not yet mature, so the current secure bootloader will not properly secure the device."
@echo "If using this feature, expect to reflash the bootloader at least one more time."
@echo "If you really want to do this, set the environment variable IDF_INSECURE_SECURE_BOOT=1 and rerun make."
exit 1
else
BOOTLOADER_DIGEST_BIN := $(BOOTLOADER_BUILD_DIR)/bootloader-reflash-digest.bin
SECURE_BOOTLOADER_KEY := $(BOOTLOADER_BUILD_DIR)/secure-bootloader-key.bin
@ -88,7 +72,7 @@ bootloader: $(BOOTLOADER_DIGEST_BIN)
@echo $(SEPARATOR)
@echo "Bootloader built and secure digest generated. First time flash command is:"
@echo "$(ESPEFUSEPY) burn_key secure_boot $(SECURE_BOOTLOADER_KEY)"
@echo "$(ESPTOOLPY_WRITE_FLASH) 0x1000 $(BOOTLOADER_BIN)"
@echo "$(ESPTOOLPY_WRITE_FLASH) $(BOOTLOADER_OFFSET) $(BOOTLOADER_BIN)"
@echo $(SEPARATOR)
@echo "To reflash the bootloader after initial flash:"
@echo "$(ESPTOOLPY_WRITE_FLASH) 0x0 $(BOOTLOADER_DIGEST_BIN)"
@ -100,14 +84,16 @@ $(BOOTLOADER_DIGEST_BIN): $(BOOTLOADER_BIN) $(SECURE_BOOTLOADER_KEY)
@echo "DIGEST $(notdir $@)"
$(Q) $(ESPSECUREPY) digest_secure_bootloader -k $(SECURE_BOOTLOADER_KEY) -o $@ $<
endif # IDF_INSECURE_SECURE_BOOT
else
bootloader:
@echo "Invalid bootloader target: bad sdkconfig?"
@exit 1
endif
ifndef CONFIG_SECURE_BOOT_ENABLED
# don't build bootloader by default is secure boot is enabled
all_binaries: $(BOOTLOADER_BIN)
endif
bootloader-clean:
$(BOOTLOADER_MAKE) app-clean

View File

@ -34,20 +34,6 @@ extern "C"
#define RTC_DATA_LOW 0x50000000
#define RTC_DATA_HIGH 0x50002000
#define PART_TYPE_APP 0x00
#define PART_SUBTYPE_FACTORY 0x00
#define PART_SUBTYPE_OTA_FLAG 0x10
#define PART_SUBTYPE_OTA_MASK 0x0f
#define PART_SUBTYPE_TEST 0x20
#define PART_TYPE_DATA 0x01
#define PART_SUBTYPE_DATA_OTA 0x00
#define PART_SUBTYPE_DATA_RF 0x01
#define PART_SUBTYPE_DATA_WIFI 0x02
#define PART_TYPE_END 0xff
#define PART_SUBTYPE_END 0xff
#define SPI_ERROR_LOG "spi flash error"
typedef struct {

View File

@ -39,6 +39,7 @@
#include "sdkconfig.h"
#include "esp_image_format.h"
#include "esp_secure_boot.h"
#include "esp_flash_encrypt.h"
#include "bootloader_flash.h"
#include "bootloader_config.h"
@ -121,7 +122,7 @@ bool load_partition_table(bootloader_state_t* bs)
ESP_LOGI(TAG, "Partition Table:");
ESP_LOGI(TAG, "## Label Usage Type ST Offset Length");
#ifdef CONFIG_SECURE_BOOTLOADER_ENABLED
#ifdef CONFIG_SECURE_BOOT_ENABLED
if(esp_secure_boot_enabled()) {
ESP_LOGI(TAG, "Verifying partition table signature...");
esp_err_t err = esp_secure_boot_verify_signature(ESP_PARTITION_TABLE_ADDR, ESP_PARTITION_TABLE_DATA_LEN);
@ -230,7 +231,9 @@ void bootloader_main()
{
uart_console_configure();
ESP_LOGI(TAG, "Espressif ESP32 2nd stage bootloader v. %s", BOOT_VERSION);
#if defined(CONFIG_SECURE_BOOT_ENABLED) || defined(CONFIG_FLASH_ENCRYPTION_ENABLED)
esp_err_t err;
#endif
esp_image_header_t fhdr;
bootloader_state_t bs;
SpiFlashOpResult spiRet1,spiRet2;
@ -245,7 +248,7 @@ void bootloader_main()
REG_CLR_BIT( TIMG_WDTCONFIG0_REG(0), TIMG_WDT_FLASHBOOT_MOD_EN );
SPIUnlock();
if(esp_image_load_header(0x1000, &fhdr) != ESP_OK) {
if(esp_image_load_header(0x1000, true, &fhdr) != ESP_OK) {
ESP_LOGE(TAG, "failed to load bootloader header!");
return;
}
@ -324,12 +327,11 @@ void bootloader_main()
return;
}
ESP_LOGI(TAG, "Loading app partition at offset %08x", load_part_pos);
#ifdef CONFIG_SECURE_BOOTLOADER_ENABLED
#ifdef CONFIG_SECURE_BOOT_ENABLED
/* Generate secure digest from this bootloader to protect future
modifications */
esp_err_t err = esp_secure_boot_permanently_enable();
ESP_LOGI(TAG, "Checking secure boot...");
err = esp_secure_boot_permanently_enable();
if (err != ESP_OK) {
ESP_LOGE(TAG, "Bootloader digest generation failed (%d). SECURE BOOT IS NOT ENABLED.", err);
/* Allow booting to continue, as the failure is probably
@ -338,15 +340,28 @@ void bootloader_main()
}
#endif
if(fhdr.encrypt_flag == 0x01) {
/* encrypt flash */
if (false == flash_encrypt(&bs)) {
ESP_LOGE(TAG, "flash encrypt failed");
return;
}
#ifdef CONFIG_FLASH_ENCRYPTION_ENABLED
/* encrypt flash */
ESP_LOGI(TAG, "Checking flash encryption...");
bool flash_encryption_enabled = esp_flash_encryption_enabled();
err = esp_flash_encrypt_check_and_update();
if (err != ESP_OK) {
ESP_LOGE(TAG, "Flash encryption check failed (%d).", err);
return;
}
if (!flash_encryption_enabled && esp_flash_encryption_enabled()) {
/* Flash encryption was just enabled for the first time,
so issue a system reset to ensure flash encryption
cache resets properly */
ESP_LOGI(TAG, "Resetting with flash encryption enabled...");
REG_WRITE(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_SYS_RST);
return;
}
#endif
// copy loaded segments to RAM, set up caches for mapped segments, and start application
ESP_LOGI(TAG, "Loading app partition at offset %08x", load_part_pos);
unpack_load_app(&load_part_pos);
}
@ -358,13 +373,13 @@ static void unpack_load_app(const esp_partition_pos_t* partition)
uint32_t image_length;
/* TODO: verify the app image as part of OTA boot decision, so can have fallbacks */
err = esp_image_basic_verify(partition->offset, &image_length);
err = esp_image_basic_verify(partition->offset, true, &image_length);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to verify app image @ 0x%x (%d)", partition->offset, err);
return;
}
#ifdef CONFIG_SECURE_BOOTLOADER_ENABLED
#ifdef CONFIG_SECURE_BOOT_ENABLED
if (esp_secure_boot_enabled()) {
ESP_LOGI(TAG, "Verifying app signature @ 0x%x (length 0x%x)", partition->offset, image_length);
err = esp_secure_boot_verify_signature(partition->offset, image_length);
@ -376,7 +391,7 @@ static void unpack_load_app(const esp_partition_pos_t* partition)
}
#endif
if (esp_image_load_header(partition->offset, &image_header) != ESP_OK) {
if (esp_image_load_header(partition->offset, true, &image_header) != ESP_OK) {
ESP_LOGE(TAG, "Failed to load app image header @ 0x%x", partition->offset);
return;
}
@ -402,8 +417,8 @@ static void unpack_load_app(const esp_partition_pos_t* partition)
esp_image_segment_header_t segment_header;
uint32_t data_offs;
if(esp_image_load_segment_header(segment, partition->offset,
&image_header, &segment_header,
&data_offs) != ESP_OK) {
&image_header, true,
&segment_header, &data_offs) != ESP_OK) {
ESP_LOGE(TAG, "failed to load segment header #%d", segment);
return;
}
@ -622,6 +637,7 @@ void print_flash_info(const esp_image_header_t* phdr)
#endif
}
#if CONFIG_CONSOLE_UART_CUSTOM
static uint32_t get_apb_freq(void)
{
// Get the value of APB clock from RTC memory.
@ -639,6 +655,7 @@ static uint32_t get_apb_freq(void)
return APB_CLK_FREQ_ROM;
}
}
#endif
static void uart_console_configure(void)
{

View File

@ -5,5 +5,8 @@
# we pull in bootloader-specific linker arguments.
#
COMPONENT_ADD_LDFLAGS := -L $(COMPONENT_PATH) -lmain -T esp32.bootloader.ld -T $(IDF_PATH)/components/esp32/ld/esp32.rom.ld
LINKER_SCRIPTS := esp32.bootloader.ld $(IDF_PATH)/components/esp32/ld/esp32.rom.ld
COMPONENT_ADD_LDFLAGS := -L $(COMPONENT_PATH) -lmain $(addprefix -T ,$(LINKER_SCRIPTS))
COMPONENT_ADD_LINKER_DEPS := $(LINKER_SCRIPTS)

View File

@ -1,188 +0,0 @@
// 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 <string.h>
#include "esp_types.h"
#include "esp_attr.h"
#include "esp_log.h"
#include "esp_err.h"
#include "rom/cache.h"
#include "rom/ets_sys.h"
#include "rom/spi_flash.h"
#include "soc/dport_reg.h"
#include "soc/io_mux_reg.h"
#include "soc/efuse_reg.h"
#include "soc/rtc_cntl_reg.h"
#include "sdkconfig.h"
#include "bootloader_config.h"
#include "esp_image_format.h"
static const char* TAG = "flash_encrypt";
/**
* @function : bitcount
* @description: calculate bit 1 in flash_crypt_cnt
* if it's even number, need encrypt flash data, and burn efuse
*
* @inputs: n flash_crypt_cnt
* @return: number of 1 in flash_crypt_cnt
*
*/
int bitcount(int n){
int count = 0;
while (n > 0) {
count += n & 1;
n >>= 1;
}
return count;
}
/**
* @function : flash_encrypt_write
* @description: write encrypted data in flash
*
* @inputs: pos address in flash
* len size of data need encrypt
* @return: return true, if the write flash success
*
*/
bool flash_encrypt_write(uint32_t pos, uint32_t len)
{
SpiFlashOpResult spiRet;
uint32_t buf[1024];
int i = 0;
Cache_Read_Disable(0);
for (i = 0;i<((len-1)/0x1000 + 1);i++) {
spiRet = SPIRead(pos, buf, SPI_SEC_SIZE);
if (spiRet != SPI_FLASH_RESULT_OK) {
Cache_Read_Enable(0);
ESP_LOGE(TAG, SPI_ERROR_LOG);
return false;
}
spiRet = SPIEraseSector(pos/SPI_SEC_SIZE);
if (spiRet != SPI_FLASH_RESULT_OK) {
Cache_Read_Enable(0);
ESP_LOGE(TAG, SPI_ERROR_LOG);
return false;
}
spiRet = SPI_Encrypt_Write(pos, buf, SPI_SEC_SIZE);
if (spiRet != SPI_FLASH_RESULT_OK) {
Cache_Read_Enable(0);
ESP_LOGE(TAG, SPI_ERROR_LOG);
return false;
}
pos += SPI_SEC_SIZE;
}
Cache_Read_Enable(0);
return true;
}
/**
* @function : flash_encrypt
* @description: encrypt 2nd boot ,partition table ,factory bin <EFBFBD><EFBFBD>test bin (if use)<EFBFBD><EFBFBD>ota bin
* <EFBFBD><EFBFBD>OTA info sector.
*
* @inputs: bs bootloader state structure used to save the data
*
* @return: return true, if the encrypt flash success
*
*/
bool flash_encrypt(bootloader_state_t *bs)
{
esp_err_t err;
uint32_t image_len = 0;
uint32_t flash_crypt_cnt = REG_GET_FIELD(EFUSE_BLK0_RDATA0_REG, EFUSE_FLASH_CRYPT_CNT);
uint8_t count = bitcount(flash_crypt_cnt);
ESP_LOGD(TAG, "flash encrypt cnt %x, bitcount %d", flash_crypt_cnt, count);
if ((count % 2) == 0) {
/* encrypt iv and abstract */
if (false == flash_encrypt_write(0, SPI_SEC_SIZE)) {
ESP_LOGE(TAG, "encrypt iv and abstract error");
return false;
}
/* encrypt bootloader image */
err = esp_image_basic_verify(0x1000, &image_len);
if(err == ESP_OK && image_len != 0) {
if (false == flash_encrypt_write(0x1000, image_len)) {
ESP_LOGE(TAG, "encrypt 2nd boot error");
return false;
}
} else {
ESP_LOGE(TAG, "2nd boot len error");
return false;
}
/* encrypt partition table */
if (false == flash_encrypt_write(ESP_PARTITION_TABLE_ADDR, SPI_SEC_SIZE)) {
ESP_LOGE(TAG, "encrypt partition table error");
return false;
}
/* encrypt write factory bin */
if(bs->factory.offset != 0 && bs->factory.size != 0) {
ESP_LOGD(TAG, "have factory bin");
if (false == flash_encrypt_write(bs->factory.offset, bs->factory.size)) {
ESP_LOGE(TAG, "encrypt factory bin error");
return false;
}
}
/* encrypt write test bin */
if(bs->test.offset != 0 && bs->test.size != 0) {
ESP_LOGD(TAG, "have test bin");
if (false == flash_encrypt_write(bs->test.offset, bs->test.size)) {
ESP_LOGE(TAG, "encrypt test bin error");
return false;
}
}
/* encrypt write ota bin */
for (int i = 0; i < 16; i++) {
if(bs->ota[i].offset != 0 && bs->ota[i].size != 0) {
ESP_LOGD(TAG, "have ota[%d] bin",i);
if (false == flash_encrypt_write(bs->ota[i].offset, bs->ota[i].size)) {
ESP_LOGE(TAG, "encrypt ota bin error");
return false;
}
}
}
/* encrypt write ota info bin */
if (false == flash_encrypt_write(bs->ota_info.offset, 2*SPI_SEC_SIZE)) {
ESP_LOGE(TAG, "encrypt ota info error");
return false;
}
REG_SET_FIELD(EFUSE_BLK0_WDATA0_REG, EFUSE_FLASH_CRYPT_CNT, 0x04);
REG_WRITE(EFUSE_CONF_REG, 0x5A5A); /* efuse_pgm_op_ena, force no rd/wr disable */
REG_WRITE(EFUSE_CMD_REG, 0x02); /* efuse_pgm_cmd */
while (REG_READ(EFUSE_CMD_REG)); /* wait for efuse_pagm_cmd=0 */
ESP_LOGW(TAG, "burn flash_crypt_cnt");
REG_WRITE(EFUSE_CONF_REG, 0x5AA5); /* efuse_read_op_ena, release force */
REG_WRITE(EFUSE_CMD_REG, 0x01); /* efuse_read_cmd */
while (REG_READ(EFUSE_CMD_REG)); /* wait for efuse_read_cmd=0 */
return true;
} else {
ESP_LOGI(TAG, "flash already encrypted.");
return true;
}
}

View File

@ -0,0 +1,7 @@
$(SECURE_BOOT_SIGNING_KEY):
@echo "Need to generate secure boot signing key."
@echo "One way is to run this command:"
@echo "$(ESPSECUREPY) generate_signing_key $@"
@echo "Keep key file safe after generating."
@echo "(See secure boot documentation for risks & alternatives.)"
@exit 1

View File

@ -12,19 +12,11 @@ COMPONENT_SRCDIRS := src
#
# Secure boot signing key support
#
ifdef CONFIG_SECURE_BOOTLOADER_ENABLED
ifdef CONFIG_SECURE_BOOT_ENABLED
# this path is created relative to the component build directory
SECURE_BOOT_VERIFICATION_KEY := $(abspath signature_verification_key.bin)
$(SECURE_BOOT_SIGNING_KEY):
@echo "Need to generate secure boot signing key."
@echo "One way is to run this command:"
@echo "$(ESPSECUREPY) generate_signing_key $@"
@echo "Keep key file safe after generating."
@echo "(See secure boot documentation for risks & alternatives.)"
@exit 1
$(SECURE_BOOT_VERIFICATION_KEY): $(SECURE_BOOT_SIGNING_KEY)
$(ESPSECUREPY) extract_public_key --keyfile $< $@

View File

@ -0,0 +1,56 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef _ESP_EFUSE_H
#define _ESP_EFUSE_H
#include "soc/efuse_reg.h"
#ifdef __cplusplus
extern "C" {
#endif
/* @brief Permanently update values written to the efuse write registers
*
* After updating EFUSE_BLKx_WDATAx_REG registers with new values to
* write, call this function to permanently write them to efuse.
*
* @note Setting bits in efuse is permanent, they cannot be unset.
*
* @note Due to this restriction you don't need to copy values to
* Efuse write registers from the matching read registers, bits which
* are set in the read register but unset in the matching write
* register will be unchanged when new values are burned.
*
* @note This function is not threadsafe, if calling code updates
* efuse values from multiple tasks then this is caller's
* responsibility to serialise.
*
* After burning new efuses, the read registers are updated to match
* the new efuse values.
*/
void esp_efuse_burn_new_values(void);
/* @brief Reset efuse write registers
*
* Efuse write registers are written to zero, to negate
* any changes that have been staged here.
*/
void esp_efuse_reset(void);
#ifdef __cplusplus
}
#endif
#endif /* __ESP_EFUSE_H */

View File

@ -0,0 +1,91 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef __ESP32_FLASH_ENCRYPT_H
#define __ESP32_FLASH_ENCRYPT_H
#include <stdbool.h>
#include <esp_err.h>
#include "esp_spi_flash.h"
#include "soc/efuse_reg.h"
/* Support functions for flash encryption features.
Can be compiled as part of app or bootloader code.
*/
/** @brief Is flash encryption currently enabled in hardware?
*
* Flash encryption is enabled if the FLASH_CRYPT_CNT efuse has an odd number of bits set.
*
* @return true if flash encryption is enabled.
*/
static inline bool esp_flash_encryption_enabled(void) {
uint32_t flash_crypt_cnt = REG_GET_FIELD(EFUSE_BLK0_RDATA0_REG, EFUSE_RD_FLASH_CRYPT_CNT);
return __builtin_parity(flash_crypt_cnt) == 1;
}
/* @brief Update on-device flash encryption
*
* Intended to be called as part of the bootloader process if flash
* encryption is enabled in device menuconfig.
*
* If FLASH_CRYPT_CNT efuse parity is 1 (ie odd number of bits set),
* then return ESP_OK immediately (indicating flash encryption is enabled
* and functional).
*
* If FLASH_CRYPT_CNT efuse parity is 0 (ie even number of bits set),
* assume the flash has just been written with plaintext that needs encrypting.
*
* The following regions of flash are encrypted in place:
*
* - The bootloader image, if a valid plaintext image is found.[*]
* - The partition table, if a valid plaintext table is found.
* - Any app partition that contains a valid plaintext app image.
* - Any other partitions with the "encrypt" flag set. [**]
*
* After the re-encryption process completes, a '1' bit is added to the
* FLASH_CRYPT_CNT value (setting the parity to 1) and the EFUSE is re-burned.
*
* [*] If reflashing bootloader with secure boot enabled, pre-encrypt
* the bootloader before writing it to flash or secure boot will fail.
*
* [**] For this reason, if serial re-flashing a previous flashed
* device with secure boot enabled and using FLASH_CRYPT_CNT to
* trigger re-encryption, you must simultaneously re-flash plaintext
* content to all partitions with the "encrypt" flag set or this
* data will be corrupted (encrypted twice).
*
* @note The post-condition of this function is that all
* partitions that should be encrypted are encrypted.
*
* @note Take care not to power off the device while this function
* is running, or the partition currently being encrypted will be lost.
*
* @return ESP_OK if all operations succeeded, ESP_ERR_INVALID_STATE
* if a fatal error occured during encryption of all partitions.
*/
esp_err_t esp_flash_encrypt_check_and_update(void);
/** @brief Encrypt-in-place a block of flash sectors
*
* @param src_addr Source offset in flash. Should be multiple of 4096 bytes.
* @param data_length Length of data to encrypt in bytes. Will be rounded up to next multiple of 4096 bytes.
*
* @return ESP_OK if all operations succeeded, ESP_ERR_FLASH_OP_FAIL
* if SPI flash fails, ESP_ERR_FLASH_OP_TIMEOUT if flash times out.
*/
esp_err_t esp_flash_encrypt_region(uint32_t src_addr, size_t data_length);
#endif

View File

@ -0,0 +1,39 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef __ESP_FLASH_PARTITIONS_H
#define __ESP_FLASH_PARTITIONS_H
#include "esp_err.h"
#include "esp_flash_data_types.h"
#include <stdbool.h>
/* Pre-partition table fixed flash offsets */
#define ESP_BOOTLOADER_DIGEST_OFFSET 0x0
#define ESP_BOOTLOADER_OFFSET 0x1000 /* Offset of bootloader image. Has matching value in bootloader KConfig.projbuild file. */
#define ESP_PARTITION_TABLE_OFFSET 0x8000 /* Offset of partition table. Has matching value in partition_table Kconfig.projbuild file. */
#define ESP_PARTITION_TABLE_MAX_LEN 0xC00 /* Maximum length of partition table data */
#define ESP_PARTITION_TABLE_MAX_ENTRIES (ESP_PARTITION_TABLE_MAX_LEN / sizeof(esp_partition_info_t)) /* Maximum length of partition table data, including terminating entry */
/* @brief Verify the partition table (does not include verifying secure boot cryptographic signature)
*
* @param partition_table Pointer to at least ESP_PARTITION_TABLE_MAX_ENTRIES of potential partition table data. (ESP_PARTITION_TABLE_MAX_LEN bytes.)
* @param log_errors Log errors if the partition table is invalid.
* @param num_partitions If result is ESP_OK, num_partitions is updated with total number of partitions (not including terminating entry).
*
* @return ESP_OK on success, ESP_ERR_INVALID_STATE if partition table is not valid.
*/
esp_err_t esp_partition_table_basic_verify(const esp_partition_info_t *partition_table, bool log_errors, int *num_partitions);
#endif

View File

@ -77,33 +77,40 @@ typedef struct {
/**
* @brief Read an ESP image header from flash.
*
* If encryption is enabled, data will be transparently decrypted.
*
* @param src_addr Address in flash to load image header. Must be 4 byte aligned.
* @param log_errors Log error output if image header appears invalid.
* @param[out] image_header Pointer to an esp_image_header_t struture to be filled with data. If the function fails, contents are undefined.
*
* @return ESP_OK if image header was loaded, ESP_ERR_IMAGE_FLASH_FAIL
* if a SPI flash error occurs, ESP_ERR_IMAGE_INVALID if the image header
* appears invalid.
*/
esp_err_t esp_image_load_header(uint32_t src_addr, esp_image_header_t *image_header);
esp_err_t esp_image_load_header(uint32_t src_addr, bool log_errors, esp_image_header_t *image_header);
/**
* @brief Read the segment header and data offset of a segment in the image.
*
* If encryption is enabled, data will be transparently decrypted.
*
* @param index Index of the segment to load information for.
* @param src_addr Base address in flash of the image.
* @param[in] image_header Pointer to the flash image header, already loaded by @ref esp_image_load_header().
* @param log_errors Log errors reading the segment header.
* @param[out] segment_header Pointer to a segment header structure to be filled with data. If the function fails, contents are undefined.
* @param[out] segment_data_offset Pointer to the data offset of the segment.
*
* @return ESP_OK if segment_header & segment_data_offset were loaded successfully, ESP_ERR_IMAGE_FLASH_FAIL if a SPI flash error occurs, ESP_ERR_IMAGE_INVALID if the image header appears invalid, ESP_ERR_INVALID_ARG if the index is invalid.
*/
esp_err_t esp_image_load_segment_header(uint8_t index, uint32_t src_addr, const esp_image_header_t *image_header, esp_image_segment_header_t *segment_header, uint32_t *segment_data_offset);
esp_err_t esp_image_load_segment_header(uint8_t index, uint32_t src_addr, const esp_image_header_t *image_header, bool log_errors, esp_image_segment_header_t *segment_header, uint32_t *segment_data_offset);
/**
* @brief Return length of an image in flash. Non-cryptographically validates image integrity in the process.
* @brief Non-cryptographically validate app image integrity. On success, length of image is provided to caller.
*
* If the image has a secure boot signature appended, the signature is not checked and this length is not included in the result.
* If the image has a secure boot signature appended, the signature is not checked and this length is not included in the
* output value.
*
* Image validation checks:
* - Magic byte
@ -111,13 +118,17 @@ esp_err_t esp_image_load_segment_header(uint8_t index, uint32_t src_addr, const
* - Total image no longer than 16MB
* - 8 bit image checksum is valid
*
* If flash encryption is enabled, the image will be tranpsarently decrypted.
*
* @param src_addr Offset of the start of the image in flash. Must be 4 byte aligned.
* @param allow_decrypt If true and flash encryption is enabled, the image will be transparently decrypted.
* @param log_errors Log errors verifying the image.
* @param[out] length Length of the image, set to a value if the image is valid. Can be null.
*
* @return ESP_OK if image is valid, ESP_FAIL or ESP_ERR_IMAGE_INVALID on errors.
*
*/
esp_err_t esp_image_basic_verify(uint32_t src_addr, uint32_t *length);
esp_err_t esp_image_basic_verify(uint32_t src_addr, bool log_errors, uint32_t *length);
typedef struct {

View File

@ -67,9 +67,25 @@ esp_err_t esp_secure_boot_permanently_enable(void);
* @param src_addr Starting offset of the data in flash.
* @param length Length of data in bytes. Signature is appended -after- length bytes.
*
* If flash encryption is enabled, the image will be transparently decrypted while being verified.
*
* @return ESP_OK if signature is valid, ESP_ERR_INVALID_STATE if
* signature fails, ESP_FAIL for other failures (ie can't read flash).
*/
esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length);
/** @brief Secure boot verification block, on-flash data format. */
typedef struct {
uint32_t version;
uint8_t signature[64];
} esp_secure_boot_sig_block_t;
#define FLASH_OFFS_SECURE_BOOT_IV_DIGEST 0
/** @brief Secure boot IV+digest header */
typedef struct {
uint8_t iv[128];
uint8_t digest[64];
} esp_secure_boot_iv_digest_t;
#endif

View File

@ -18,6 +18,9 @@
#include <stdbool.h>
#include <stdint.h>
#include <esp_err.h>
#include "esp_spi_flash.h"
#define FLASH_SECTOR_SIZE 0x1000
/* Provide a Flash API for bootloader_support code,
that can be used from bootloader or app code.
@ -56,14 +59,45 @@ void bootloader_munmap(const void *mapping);
/**
* @brief Read data from Flash.
*
* @note Both src and dest have to be 4-byte aligned.
*
* @note All of src, dest and size have to be 4-byte aligned.
*
* @param src source address of the data in Flash.
* @param dest pointer to the destination buffer
* @param size length of data
* @param allow_decrypt If true and flash encryption is enabled, data on flash
* will be decrypted transparently as part of the read.
*
* @return ESP_OK on success, ESP_ERR_FLASH_OP_FAIL on SPI failure,
* ESP_ERR_FLASH_OP_TIMEOUT on SPI timeout.
*/
esp_err_t bootloader_flash_read(size_t src_addr, void *dest, size_t size, bool allow_decrypt);
/**
* @brief Write data to Flash.
*
* @note All of dest_addr, src and size have to be 4-byte aligned. If write_encrypted is set, dest_addr and size must be 32-byte aligned.
*
* Note: In bootloader, when write_encrypted == true, the src buffer is encrypted in place.
*
* @param dest_addr Destination address to write in Flash.
* @param src Pointer to the data to write to flash
* @param size Length of data in bytes.
* @param write_encrypted If true, data will be written encrypted on flash.
*
* @return ESP_OK on success, ESP_ERR_FLASH_OP_FAIL on SPI failure,
* ESP_ERR_FLASH_OP_TIMEOUT on SPI timeout.
*/
esp_err_t bootloader_flash_write(size_t dest_addr, void *src, size_t size, bool write_encrypted);
/**
* @brief Erase the Flash sector.
*
* @param sector Sector number, the count starts at sector 0, 4KB per sector.
*
* @return esp_err_t
*/
esp_err_t bootloader_flash_read(size_t src_addr, void *dest, size_t size);
esp_err_t bootloader_flash_erase_sector(size_t sector);
#endif

View File

@ -0,0 +1,25 @@
// Copyright 2010-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include <stddef.h>
/**
* @brief Fill buffer with 'length' random bytes
*
* @param buffer Pointer to buffer
* @param length This many bytes of random data will be copied to buffer
*/
void bootloader_fill_random(void *buffer, size_t length);

View File

@ -46,38 +46,68 @@ void bootloader_munmap(const void *mapping)
map = 0;
}
esp_err_t bootloader_flash_read(size_t src, void *dest, size_t size)
esp_err_t bootloader_flash_read(size_t src, void *dest, size_t size, bool allow_decrypt)
{
return spi_flash_read(src, dest, size);
}
esp_err_t bootloader_flash_write(size_t dest_addr, void *src, size_t size, bool write_encrypted)
{
if (write_encrypted) {
return spi_flash_write_encrypted(dest_addr, src, size);
} else {
return spi_flash_write(dest_addr, src, size);
}
}
esp_err_t bootloader_flash_erase_sector(size_t sector)
{
return spi_flash_erase_sector(sector);
}
#else
/* Bootloader version, uses ROM functions only */
#include <soc/dport_reg.h>
#include <rom/spi_flash.h>
#include <rom/cache.h>
static const char *TAG = "bootloader_flash";
/* Use first 50 blocks in MMU for bootloader_mmap,
50th block for bootloader_flash_read
*/
#define MMU_BLOCK0_VADDR 0x3f400000
#define MMU_BLOCK50_VADDR 0x3f720000
#define MMU_FLASH_MASK 0xffff0000
#define MMU_BLOCK_SIZE 0x00010000
static bool mapped;
static uint32_t current_read_mapping = UINT32_MAX;
const void *bootloader_mmap(uint32_t src_addr, uint32_t size)
{
if (mapped) {
ESP_LOGE(TAG, "tried to bootloader_mmap twice");
return NULL; /* can't map twice */
}
if (size > 0x320000) {
/* Allow mapping up to 50 of the 51 available MMU blocks (last one used for reads) */
ESP_LOGE(TAG, "bootloader_mmap excess size %x", size);
return NULL;
}
uint32_t src_addr_aligned = src_addr & 0xffff0000;
uint32_t count = (size + (src_addr - src_addr_aligned) + 0xffff) / 0x10000;
uint32_t src_addr_aligned = src_addr & MMU_FLASH_MASK;
uint32_t count = (size + (src_addr - src_addr_aligned) + 0xffff) / MMU_BLOCK_SIZE;
Cache_Read_Disable(0);
Cache_Flush(0);
ESP_LOGD(TAG, "mmu set paddr=%08x count=%d", src_addr_aligned, count );
cache_flash_mmu_set( 0, 0, 0x3f400000, src_addr_aligned, 64, count );
cache_flash_mmu_set( 0, 0, MMU_BLOCK0_VADDR, src_addr_aligned, 64, count );
Cache_Read_Enable( 0 );
mapped = true;
return (void *)(0x3f400000 + (src_addr - src_addr_aligned));
return (void *)(MMU_BLOCK0_VADDR + (src_addr - src_addr_aligned));
}
void bootloader_munmap(const void *mapping)
@ -88,25 +118,12 @@ void bootloader_munmap(const void *mapping)
Cache_Flush(0);
mmu_init(0);
mapped = false;
current_read_mapping = UINT32_MAX;
}
}
esp_err_t bootloader_flash_read(size_t src_addr, void *dest, size_t size)
static esp_err_t spi_to_esp_err(SpiFlashOpResult r)
{
if(src_addr & 3) {
ESP_LOGE(TAG, "bootloader_flash_read src_addr 0x%x not 4-byte aligned", src_addr);
return ESP_FAIL;
}
if((intptr_t)dest & 3) {
ESP_LOGE(TAG, "bootloader_flash_read dest 0x%x not 4-byte aligned", (intptr_t)dest);
return ESP_FAIL;
}
Cache_Read_Disable(0);
Cache_Flush(0);
SpiFlashOpResult r = SPIRead(src_addr, dest, size);
Cache_Read_Enable(0);
switch(r) {
case SPI_FLASH_RESULT_OK:
return ESP_OK;
@ -119,4 +136,101 @@ esp_err_t bootloader_flash_read(size_t src_addr, void *dest, size_t size)
}
}
static esp_err_t bootloader_flash_read_no_decrypt(size_t src_addr, void *dest, size_t size)
{
Cache_Read_Disable(0);
Cache_Flush(0);
SpiFlashOpResult r = SPIRead(src_addr, dest, size);
Cache_Read_Enable(0);
return spi_to_esp_err(r);
}
static esp_err_t bootloader_flash_read_allow_decrypt(size_t src_addr, void *dest, size_t size)
{
uint32_t *dest_words = (uint32_t *)dest;
/* Use the 51st MMU mapping to read from flash in 64KB blocks.
(MMU will transparently decrypt if encryption is enabled.)
*/
for (int word = 0; word < size / 4; word++) {
uint32_t word_src = src_addr + word * 4; /* Read this offset from flash */
uint32_t map_at = word_src & MMU_FLASH_MASK; /* Map this 64KB block from flash */
uint32_t *map_ptr;
if (map_at != current_read_mapping) {
/* Move the 64KB mmu mapping window to fit map_at */
Cache_Read_Disable(0);
Cache_Flush(0);
ESP_LOGD(TAG, "mmu set block paddr=0x%08x (was 0x%08x)", map_at, current_read_mapping);
int e = cache_flash_mmu_set(0, 0, MMU_BLOCK50_VADDR, map_at, 64, 1);
if (e != 0) {
ESP_LOGE(TAG, "cache_flash_mmu_set failed: %d\n", e);
Cache_Read_Enable(0);
return ESP_FAIL;
}
current_read_mapping = map_at;
Cache_Read_Enable(0);
}
map_ptr = (uint32_t *)(MMU_BLOCK50_VADDR + (word_src - map_at));
dest_words[word] = *map_ptr;
}
return ESP_OK;
}
esp_err_t bootloader_flash_read(size_t src_addr, void *dest, size_t size, bool allow_decrypt)
{
if (src_addr & 3) {
ESP_LOGE(TAG, "bootloader_flash_read src_addr 0x%x not 4-byte aligned", src_addr);
return ESP_FAIL;
}
if (size & 3) {
ESP_LOGE(TAG, "bootloader_flash_read size 0x%x not 4-byte aligned", size);
return ESP_FAIL;
}
if ((intptr_t)dest & 3) {
ESP_LOGE(TAG, "bootloader_flash_read dest 0x%x not 4-byte aligned", (intptr_t)dest);
return ESP_FAIL;
}
if (allow_decrypt) {
return bootloader_flash_read_allow_decrypt(src_addr, dest, size);
} else {
return bootloader_flash_read_no_decrypt(src_addr, dest, size);
}
}
esp_err_t bootloader_flash_write(size_t dest_addr, void *src, size_t size, bool write_encrypted)
{
esp_err_t err;
size_t alignment = write_encrypted ? 32 : 4;
if ((dest_addr % alignment) != 0) {
ESP_LOGE(TAG, "bootloader_flash_write dest_addr 0x%x not %d-byte aligned", dest_addr, alignment);
return ESP_FAIL;
}
if ((size % alignment) != 0) {
ESP_LOGE(TAG, "bootloader_flash_write size 0x%x not %d-byte aligned", size, alignment);
return ESP_FAIL;
}
if (((intptr_t)src % 4) != 0) {
ESP_LOGE(TAG, "bootloader_flash_write src 0x%x not 4 byte aligned", (intptr_t)src);
return ESP_FAIL;
}
err = spi_to_esp_err(SPIUnlock());
if (err != ESP_OK) {
return err;
}
if (write_encrypted) {
return spi_to_esp_err(SPI_Encrypt_Write(dest_addr, src, size));
} else {
return spi_to_esp_err(SPIWrite(dest_addr, src, size));
}
}
esp_err_t bootloader_flash_erase_sector(size_t sector)
{
return spi_to_esp_err(SPIEraseSector(sector));
}
#endif

View File

@ -0,0 +1,53 @@
// Copyright 2010-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "bootloader_random.h"
#include "soc/wdev_reg.h"
#ifndef BOOTLOADER_BUILD
#include "esp_system.h"
#endif
void bootloader_fill_random(void *buffer, size_t length)
{
uint8_t *buffer_bytes = (uint8_t *)buffer;
uint32_t random;
/* TODO: enable HW RNG clock
Until this clock is enabled, this is not secure
*/
for (int i = 0; i < length; i++) {
if (i == 0 || i % 4 == 0) { /* redundant check is for a compiler warning */
#ifdef BOOTLOADER_BUILD
/* HW RNG generates 32 bits entropy per 16 APB cycles,
in bootloader CPU clock == APB clock.
We are being conservative here and waiting at least
that long, as loop shift overhead, etc will add more
cycles.
*/
asm volatile("nop; nop; nop; nop;");
asm volatile("nop; nop; nop; nop;");
asm volatile("nop; nop; nop; nop;");
asm volatile("nop; nop; nop; nop;");
random = REG_READ(WDEV_RND_REG);
#else
random = esp_random();
#endif
}
buffer_bytes[i] = random >> ((i % 4) * 8);
}
}

View File

@ -0,0 +1,47 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "esp_efuse.h"
#define EFUSE_CONF_WRITE 0x5A5A /* efuse_pgm_op_ena, force no rd/wr disable */
#define EFUSE_CONF_READ 0x5AA5 /* efuse_read_op_ena, release force */
#define EFUSE_CMD_PGM 0x02
#define EFUSE_CMD_READ 0x01
void esp_efuse_burn_new_values(void)
{
REG_WRITE(EFUSE_CONF_REG, EFUSE_CONF_WRITE);
REG_WRITE(EFUSE_CMD_REG, EFUSE_CMD_PGM);
while (REG_READ(EFUSE_CMD_REG) != 0) {
}
REG_WRITE(EFUSE_CONF_REG, EFUSE_CONF_READ);
REG_WRITE(EFUSE_CMD_REG, EFUSE_CMD_READ);
while (REG_READ(EFUSE_CMD_REG) != 0) {
}
esp_efuse_reset();
}
void esp_efuse_reset(void)
{
REG_WRITE(EFUSE_CONF_REG, EFUSE_CONF_READ);
const uint32_t block_start[4] = { EFUSE_BLK0_WDATA0_REG, EFUSE_BLK1_WDATA0_REG,
EFUSE_BLK2_WDATA0_REG, EFUSE_BLK3_WDATA0_REG };
const uint32_t block_end[4] = { EFUSE_BLK0_WDATA6_REG, EFUSE_BLK1_WDATA7_REG,
EFUSE_BLK2_WDATA7_REG, EFUSE_BLK3_WDATA7_REG };
for (int i = 0; i < 4; i++) {
for (uint32_t r = block_start[i]; r <= block_end[i]; r+= 4) {
REG_WRITE(r, 0);
}
}
}

View File

@ -22,26 +22,30 @@ static const char *TAG = "esp_image";
#define SIXTEEN_MB 0x1000000
#define ESP_ROM_CHECKSUM_INITIAL 0xEF
esp_err_t esp_image_load_header(uint32_t src_addr, esp_image_header_t *image_header)
esp_err_t esp_image_load_header(uint32_t src_addr, bool log_errors, esp_image_header_t *image_header)
{
esp_err_t err;
ESP_LOGD(TAG, "reading image header @ 0x%x", src_addr);
err = bootloader_flash_read(src_addr, image_header, sizeof(esp_image_header_t));
err = bootloader_flash_read(src_addr, image_header, sizeof(esp_image_header_t), true);
if (err == ESP_OK) {
if (image_header->magic != ESP_IMAGE_HEADER_MAGIC) {
ESP_LOGE(TAG, "image at 0x%x has invalid magic byte", src_addr);
if (log_errors) {
ESP_LOGE(TAG, "image at 0x%x has invalid magic byte", src_addr);
}
err = ESP_ERR_IMAGE_INVALID;
}
if (image_header->spi_mode > ESP_IMAGE_SPI_MODE_SLOW_READ) {
ESP_LOGW(TAG, "image at 0x%x has invalid SPI mode %d", src_addr, image_header->spi_mode);
}
if (image_header->spi_speed > ESP_IMAGE_SPI_SPEED_80M) {
ESP_LOGW(TAG, "image at 0x%x has invalid SPI speed %d", src_addr, image_header->spi_speed);
}
if (image_header->spi_size > ESP_IMAGE_FLASH_SIZE_MAX) {
ESP_LOGW(TAG, "image at 0x%x has invalid SPI size %d", src_addr, image_header->spi_size);
if (log_errors) {
if (image_header->spi_mode > ESP_IMAGE_SPI_MODE_SLOW_READ) {
ESP_LOGW(TAG, "image at 0x%x has invalid SPI mode %d", src_addr, image_header->spi_mode);
}
if (image_header->spi_speed > ESP_IMAGE_SPI_SPEED_80M) {
ESP_LOGW(TAG, "image at 0x%x has invalid SPI speed %d", src_addr, image_header->spi_speed);
}
if (image_header->spi_size > ESP_IMAGE_FLASH_SIZE_MAX) {
ESP_LOGW(TAG, "image at 0x%x has invalid SPI size %d", src_addr, image_header->spi_size);
}
}
}
@ -51,23 +55,27 @@ esp_err_t esp_image_load_header(uint32_t src_addr, esp_image_header_t *image_hea
return err;
}
esp_err_t esp_image_load_segment_header(uint8_t index, uint32_t src_addr, const esp_image_header_t *image_header, esp_image_segment_header_t *segment_header, uint32_t *segment_data_offset)
esp_err_t esp_image_load_segment_header(uint8_t index, uint32_t src_addr, const esp_image_header_t *image_header, bool log_errors, esp_image_segment_header_t *segment_header, uint32_t *segment_data_offset)
{
esp_err_t err = ESP_OK;
uint32_t next_addr = src_addr + sizeof(esp_image_header_t);
if(index >= image_header->segment_count) {
ESP_LOGE(TAG, "index %d higher than segment count %d", index, image_header->segment_count);
if (log_errors) {
ESP_LOGE(TAG, "index %d higher than segment count %d", index, image_header->segment_count);
}
return ESP_ERR_INVALID_ARG;
}
for(int i = 0; i <= index && err == ESP_OK; i++) {
ESP_LOGV(TAG, "loading segment header %d at offset 0x%x", i, next_addr);
err = bootloader_flash_read(next_addr, segment_header, sizeof(esp_image_segment_header_t));
err = bootloader_flash_read(next_addr, segment_header, sizeof(esp_image_segment_header_t), true);
if (err == ESP_OK) {
if ((segment_header->data_len & 3) != 0
|| segment_header->data_len >= SIXTEEN_MB) {
ESP_LOGE(TAG, "invalid segment length 0x%x", segment_header->data_len);
if (log_errors) {
ESP_LOGE(TAG, "invalid segment length 0x%x", segment_header->data_len);
}
err = ESP_ERR_IMAGE_INVALID;
}
next_addr += sizeof(esp_image_segment_header_t);
@ -85,15 +93,14 @@ esp_err_t esp_image_load_segment_header(uint8_t index, uint32_t src_addr, const
return err;
}
esp_err_t esp_image_basic_verify(uint32_t src_addr, uint32_t *p_length)
esp_err_t esp_image_basic_verify(uint32_t src_addr, bool log_errors, uint32_t *p_length)
{
esp_err_t err;
uint8_t buf[16];
uint8_t buf[128];
uint8_t checksum = ESP_ROM_CHECKSUM_INITIAL;
esp_image_header_t image_header;
esp_image_segment_header_t segment_header = { 0 };
uint32_t segment_data_offs = 0;
const uint8_t *segment_data;
uint32_t end_addr;
uint32_t length;
@ -101,7 +108,7 @@ esp_err_t esp_image_basic_verify(uint32_t src_addr, uint32_t *p_length)
*p_length = 0;
}
err = esp_image_load_header(src_addr, &image_header);
err = esp_image_load_header(src_addr, log_errors, &image_header);
if (err != ESP_OK) {
return err;
}
@ -110,34 +117,38 @@ esp_err_t esp_image_basic_verify(uint32_t src_addr, uint32_t *p_length)
/* Checksum each segment's data */
for (int i = 0; i < image_header.segment_count; i++) {
err = esp_image_load_segment_header(i, src_addr, &image_header,
err = esp_image_load_segment_header(i, src_addr, &image_header, log_errors,
&segment_header, &segment_data_offs);
if (err != ESP_OK) {
return err;
}
segment_data = bootloader_mmap(segment_data_offs, segment_header.data_len);
if (segment_data == NULL) {
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", segment_data_offs, segment_header.data_len);
return ESP_FAIL;
for (int i = 0; i < segment_header.data_len; i += sizeof(buf)) {
err = bootloader_flash_read(segment_data_offs + i, buf, sizeof(buf), true);
if (err != ESP_OK) {
return err;
}
for (int j = 0; j < sizeof(buf) && i + j < segment_header.data_len; j++) {
checksum ^= buf[j];
}
}
for(int i = 0; i < segment_header.data_len; i++) {
checksum ^= segment_data[i];
}
bootloader_munmap(segment_data);
}
/* End of image, verify checksum */
end_addr = segment_data_offs + segment_header.data_len;
if (end_addr < src_addr) {
ESP_LOGE(TAG, "image offset has wrapped");
if (log_errors) {
ESP_LOGE(TAG, "image offset has wrapped");
}
return ESP_ERR_IMAGE_INVALID;
}
length = end_addr - src_addr;
if (length >= SIXTEEN_MB) {
ESP_LOGE(TAG, "invalid total length 0x%x", length);
if (log_errors) {
ESP_LOGE(TAG, "invalid total length 0x%x", length);
}
return ESP_ERR_IMAGE_INVALID;
}
@ -147,10 +158,12 @@ esp_err_t esp_image_basic_verify(uint32_t src_addr, uint32_t *p_length)
length = length - (length % 16);
ESP_LOGV(TAG, "padded image length 0x%x", length);
ESP_LOGD(TAG, "reading checksum block at 0x%x", src_addr + length - 16);
bootloader_flash_read(src_addr + length - 16, buf, 16);
bootloader_flash_read(src_addr + length - 16, buf, 16, true);
if (checksum != buf[15]) {
ESP_LOGE(TAG, "checksum failed. Calculated 0x%x read 0x%x",
checksum, buf[15]);
if (log_errors) {
ESP_LOGE(TAG, "checksum failed. Calculated 0x%x read 0x%x",
checksum, buf[15]);
}
return ESP_ERR_IMAGE_INVALID;
}

View File

@ -0,0 +1,329 @@
// 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 <strings.h>
#include "bootloader_flash.h"
#include "bootloader_random.h"
#include "esp_image_format.h"
#include "esp_flash_encrypt.h"
#include "esp_flash_partitions.h"
#include "esp_flash_data_types.h"
#include "esp_secure_boot.h"
#include "esp_efuse.h"
#include "esp_log.h"
#include "rom/secure_boot.h"
#include "rom/cache.h"
#include "rom/spi_flash.h" /* TODO: Remove this */
static const char *TAG = "flash_encrypt";
/* Static functions for stages of flash encryption */
static esp_err_t initialise_flash_encryption(void);
static esp_err_t encrypt_flash_contents(uint32_t flash_crypt_cnt, bool flash_crypt_wr_dis);
static esp_err_t encrypt_bootloader();
static esp_err_t encrypt_and_load_partition_table(esp_partition_info_t *partition_table, int *num_partitions);
static esp_err_t encrypt_partition(int index, const esp_partition_info_t *partition);
esp_err_t esp_flash_encrypt_check_and_update(void)
{
uint32_t efuse_blk0 = REG_READ(EFUSE_BLK0_RDATA0_REG);
ESP_LOGV(TAG, "efuse_blk0 raw value %08x", efuse_blk0);
uint32_t flash_crypt_cnt = (efuse_blk0 & EFUSE_RD_FLASH_CRYPT_CNT_M) >> EFUSE_RD_FLASH_CRYPT_CNT_S;
bool flash_crypt_wr_dis = efuse_blk0 & EFUSE_WR_DIS_FLASH_CRYPT_CNT;
ESP_LOGV(TAG, "efuse FLASH_CRYPT_CNT 0x%x WR_DIS_FLASH_CRYPT_CNT 0x%x", flash_crypt_cnt, flash_crypt_wr_dis);
if (__builtin_parity(flash_crypt_cnt) == 1) {
/* Flash is already encrypted */
int left = (7 - __builtin_popcount(flash_crypt_cnt)) / 2;
if (flash_crypt_wr_dis) {
left = 0; /* can't update FLASH_CRYPT_CNT, no more flashes */
}
ESP_LOGI(TAG, "flash encryption is enabled (%d plaintext flashes left)", left);
return ESP_OK;
}
else {
/* Flash is not encrypted, so encrypt it! */
return encrypt_flash_contents(flash_crypt_cnt, flash_crypt_wr_dis);
}
}
static esp_err_t initialise_flash_encryption(void)
{
/* Before first flash encryption pass, need to initialise key & crypto config */
/* Generate key */
uint32_t dis_reg = REG_READ(EFUSE_BLK0_RDATA0_REG);
bool efuse_key_read_protected = dis_reg & EFUSE_RD_DIS_BLK1;
bool efuse_key_write_protected = dis_reg & EFUSE_WR_DIS_BLK1;
if (efuse_key_read_protected == false
&& efuse_key_write_protected == false
&& REG_READ(EFUSE_BLK1_RDATA0_REG) == 0
&& REG_READ(EFUSE_BLK1_RDATA1_REG) == 0
&& REG_READ(EFUSE_BLK1_RDATA2_REG) == 0
&& REG_READ(EFUSE_BLK1_RDATA3_REG) == 0
&& REG_READ(EFUSE_BLK1_RDATA4_REG) == 0
&& REG_READ(EFUSE_BLK1_RDATA5_REG) == 0
&& REG_READ(EFUSE_BLK1_RDATA6_REG) == 0
&& REG_READ(EFUSE_BLK1_RDATA7_REG) == 0) {
/* On-device key generation is temporarily disabled, until
* RNG operation during bootloader is qualified.
* See docs/security/flash-encryption.rst for details. */
ESP_LOGE(TAG, "On-device key generation is not yet available.");
return ESP_ERR_NOT_SUPPORTED;
} else {
if(!(efuse_key_read_protected && efuse_key_write_protected)) {
ESP_LOGE(TAG, "Flash encryption key has to be either unset or both read and write protected");
return ESP_ERR_INVALID_STATE;
}
ESP_LOGW(TAG, "Using pre-loaded flash encryption key in EFUSE block 1");
}
/* CRYPT_CONFIG determines which bits of the AES block key are XORed
with bits from the flash address, to provide the key tweak.
CRYPT_CONFIG == 0 is effectively AES ECB mode (NOT SUPPORTED)
For now this is hardcoded to XOR all 256 bits of the key.
If you need to override it, you can pre-burn this efuse to the
desired value and then write-protect it, in which case this
operation does nothing. Please note this is not recommended!
*/
ESP_LOGI(TAG, "Setting CRYPT_CONFIG efuse to 0xF");
REG_WRITE(EFUSE_BLK0_WDATA5_REG, EFUSE_FLASH_CRYPT_CONFIG_M);
esp_efuse_burn_new_values();
uint32_t new_wdata6 = 0;
#ifndef CONFIG_FLASH_ENCRYPTION_UART_BOOTLOADER_ALLOW_ENCRYPT
ESP_LOGI(TAG, "Disable UART bootloader encryption...");
new_wdata6 |= EFUSE_DISABLE_DL_ENCRYPT;
#else
ESP_LOGW(TAG, "Not disabling UART bootloader encryption");
#endif
#ifndef CONFIG_FLASH_ENCRYPTION_UART_BOOTLOADER_ALLOW_DECRYPT
ESP_LOGI(TAG, "Disable UART bootloader decryption...");
new_wdata6 |= EFUSE_DISABLE_DL_DECRYPT;
#else
ESP_LOGW(TAG, "Not disabling UART bootloader decryption - SECURITY COMPROMISED");
#endif
#ifndef CONFIG_FLASH_ENCRYPTION_UART_BOOTLOADER_ALLOW_CACHE
ESP_LOGI(TAG, "Disable UART bootloader MMU cache...");
new_wdata6 |= EFUSE_DISABLE_DL_CACHE;
#else
ESP_LOGW(TAG, "Not disabling UART bootloader MMU cache - SECURITY COMPROMISED");
#endif
#ifndef CONFIG_SECURE_BOOT_ALLOW_JTAG
ESP_LOGI(TAG, "Disable JTAG...");
new_wdata6 |= EFUSE_RD_DISABLE_JTAG;
#else
ESP_LOGW(TAG, "Not disabling JTAG - SECURITY COMPROMISED");
#endif
if (new_wdata6 != 0) {
REG_WRITE(EFUSE_BLK0_WDATA6_REG, new_wdata6);
esp_efuse_burn_new_values();
}
return ESP_OK;
}
/* Encrypt all flash data that should be encrypted */
static esp_err_t encrypt_flash_contents(uint32_t flash_crypt_cnt, bool flash_crypt_wr_dis)
{
esp_err_t err;
esp_partition_info_t partition_table[ESP_PARTITION_TABLE_MAX_ENTRIES];
int num_partitions;
/* If the last flash_crypt_cnt bit is burned or write-disabled, the
device can't re-encrypt itself. */
if (flash_crypt_wr_dis || flash_crypt_cnt == 0xFF) {
ESP_LOGE(TAG, "Cannot re-encrypt data (FLASH_CRYPT_CNT 0x%02x write disabled %d", flash_crypt_cnt, flash_crypt_wr_dis);
return ESP_FAIL;
}
if (flash_crypt_cnt == 0) {
/* Very first flash of encrypted data: generate keys, etc. */
err = initialise_flash_encryption();
if (err != ESP_OK) {
return err;
}
}
err = encrypt_bootloader();
if (err != ESP_OK) {
return err;
}
err = encrypt_and_load_partition_table(partition_table, &num_partitions);
if (err != ESP_OK) {
return err;
}
/* Now iterate the just-loaded partition table, looking for entries to encrypt
*/
/* Go through each partition and encrypt if necessary */
for (int i = 0; i < num_partitions; i++) {
err = encrypt_partition(i, &partition_table[i]);
if (err != ESP_OK) {
return err;
}
}
ESP_LOGD(TAG, "All flash regions checked for encryption pass");
/* Set least significant 0-bit in flash_crypt_cnt */
int ffs_inv = __builtin_ffs((~flash_crypt_cnt) & 0xFF);
/* ffs_inv shouldn't be zero, as zero implies flash_crypt_cnt == 0xFF */
uint32_t new_flash_crypt_cnt = flash_crypt_cnt + (1 << (ffs_inv - 1));
ESP_LOGD(TAG, "FLASH_CRYPT_CNT 0x%x -> 0x%x", flash_crypt_cnt, new_flash_crypt_cnt);
REG_SET_FIELD(EFUSE_BLK0_WDATA0_REG, EFUSE_FLASH_CRYPT_CNT, new_flash_crypt_cnt);
esp_efuse_burn_new_values();
ESP_LOGI(TAG, "Flash encryption completed");
return ESP_OK;
}
static esp_err_t encrypt_bootloader()
{
esp_err_t err;
uint32_t image_length;
/* Check for plaintext bootloader */
if (esp_image_basic_verify(ESP_BOOTLOADER_OFFSET, false, &image_length) == ESP_OK) {
ESP_LOGD(TAG, "bootloader is plaintext. Encrypting...");
err = esp_flash_encrypt_region(ESP_BOOTLOADER_OFFSET, image_length);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to encrypt bootloader in place: 0x%x", err);
return err;
}
if (esp_secure_boot_enabled()) {
/* If secure boot is enabled and bootloader was plaintext, also
need to encrypt secure boot IV+digest.
*/
ESP_LOGD(TAG, "Encrypting secure bootloader IV & digest...");
err = esp_flash_encrypt_region(FLASH_OFFS_SECURE_BOOT_IV_DIGEST,
FLASH_SECTOR_SIZE);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to encrypt bootloader IV & digest in place: 0x%x", err);
return err;
}
}
}
else {
ESP_LOGW(TAG, "no valid bootloader was found");
}
return ESP_OK;
}
static esp_err_t encrypt_and_load_partition_table(esp_partition_info_t *partition_table, int *num_partitions)
{
esp_err_t err;
/* Check for plaintext partition table */
err = bootloader_flash_read(ESP_PARTITION_TABLE_OFFSET, partition_table, ESP_PARTITION_TABLE_MAX_LEN, false);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to read partition table data");
return err;
}
if (esp_partition_table_basic_verify(partition_table, false, num_partitions) == ESP_OK) {
ESP_LOGD(TAG, "partition table is plaintext. Encrypting...");
esp_err_t err = esp_flash_encrypt_region(ESP_PARTITION_TABLE_OFFSET,
FLASH_SECTOR_SIZE);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to encrypt partition table in place. %x", err);
return err;
}
}
else {
ESP_LOGE(TAG, "Failed to read partition table data - not plaintext?");
return ESP_ERR_INVALID_STATE;
}
/* Valid partition table loded */
return ESP_OK;
}
static esp_err_t encrypt_partition(int index, const esp_partition_info_t *partition)
{
esp_err_t err;
uint32_t image_len = partition->pos.size;
bool should_encrypt = (partition->flags & PART_FLAG_ENCRYPTED);
if (partition->type == PART_TYPE_APP) {
/* check if the partition holds an unencrypted app */
if (esp_image_basic_verify(partition->pos.offset, false, &image_len) == ESP_OK) {
if(image_len > partition->pos.size) {
ESP_LOGE(TAG, "partition entry %d has image longer than partition (%d vs %d)", index, image_len, partition->pos.size);
should_encrypt = false;
} else {
should_encrypt = true;
}
} else {
should_encrypt = false;
}
}
if (!should_encrypt) {
return ESP_OK;
}
else {
/* should_encrypt */
ESP_LOGI(TAG, "Encrypting partition %d at offset 0x%x...", index, partition->pos.offset);
err = esp_flash_encrypt_region(partition->pos.offset, partition->pos.size);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to encrypt partition %d", index);
}
return err;
}
}
esp_err_t esp_flash_encrypt_region(uint32_t src_addr, size_t data_length)
{
esp_err_t err;
uint32_t buf[FLASH_SECTOR_SIZE / sizeof(uint32_t)];
if (src_addr % FLASH_SECTOR_SIZE != 0) {
ESP_LOGE(TAG, "esp_flash_encrypt_region bad src_addr 0x%x",src_addr);
return ESP_FAIL;
}
for (size_t i = 0; i < data_length; i += FLASH_SECTOR_SIZE) {
uint32_t sec_start = i + src_addr;
err = bootloader_flash_read(sec_start, buf, FLASH_SECTOR_SIZE, false);
if (err != ESP_OK) {
goto flash_failed;
}
err = bootloader_flash_erase_sector(sec_start / FLASH_SECTOR_SIZE);
if (err != ESP_OK) {
goto flash_failed;
}
err = bootloader_flash_write(sec_start, buf, FLASH_SECTOR_SIZE, true);
if (err != ESP_OK) {
goto flash_failed;
}
}
return ESP_OK;
flash_failed:
ESP_LOGE(TAG, "flash operation failed: 0x%x", err);
return err;
}

View File

@ -0,0 +1,49 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "esp_flash_partitions.h"
#include "esp_log.h"
static const char *TAG = "flash_parts";
esp_err_t esp_partition_table_basic_verify(const esp_partition_info_t *partition_table, bool log_errors, int *num_partitions)
{
int num_parts;
*num_partitions = 0;
for(num_parts = 0; num_parts < ESP_PARTITION_TABLE_MAX_ENTRIES; num_parts++) {
const esp_partition_info_t *part = &partition_table[num_parts];
if(part->magic == 0xFFFF
&& part->type == PART_TYPE_END
&& part->subtype == PART_SUBTYPE_END) {
/* TODO: check md5 */
ESP_LOGD(TAG, "partition table verified, %d entries", num_parts);
*num_partitions = num_parts;
return ESP_OK;
}
if(part->magic != ESP_PARTITION_MAGIC) {
if (log_errors) {
ESP_LOGE(TAG, "partition %d invalid magic number 0x%x", num_parts, part->magic);
}
return ESP_ERR_INVALID_STATE;
}
}
if (log_errors) {
ESP_LOGE(TAG, "partition table has no terminating entry, not valid");
}
return ESP_ERR_INVALID_STATE;
}

View File

@ -20,7 +20,6 @@
#include "rom/cache.h"
#include "rom/ets_sys.h"
#include "rom/spi_flash.h"
#include "rom/secure_boot.h"
#include "soc/dport_reg.h"
@ -31,15 +30,14 @@
#include "sdkconfig.h"
#include "bootloader_flash.h"
#include "bootloader_random.h"
#include "esp_image_format.h"
#include "esp_secure_boot.h"
#include "esp_flash_encrypt.h"
#include "esp_efuse.h"
static const char* TAG = "secure_boot";
#define HASH_BLOCK_SIZE 128
#define IV_LEN HASH_BLOCK_SIZE
#define DIGEST_LEN 64
/**
* @function : secure_boot_generate
* @description: generate boot digest (aka "abstract") & iv
@ -47,39 +45,26 @@ static const char* TAG = "secure_boot";
* @inputs: image_len - length of image to calculate digest for
*/
static bool secure_boot_generate(uint32_t image_len){
SpiFlashOpResult spiRet;
/* buffer is uint32_t not uint8_t to meet ROM SPI API signature */
uint32_t buf[IV_LEN / sizeof(uint32_t)];
const void *image;
esp_err_t err;
esp_secure_boot_iv_digest_t digest;
const uint32_t *image;
/* hardware secure boot engine only takes full blocks, so round up the
image length. The additional data should all be 0xFF.
*/
if (image_len % HASH_BLOCK_SIZE != 0) {
image_len = (image_len / HASH_BLOCK_SIZE + 1) * HASH_BLOCK_SIZE;
if (image_len % sizeof(digest.iv) != 0) {
image_len = (image_len / sizeof(digest.iv) + 1) * sizeof(digest.iv);
}
ets_secure_boot_start();
ets_secure_boot_rd_iv(buf);
ets_secure_boot_rd_iv((uint32_t *)digest.iv);
ets_secure_boot_hash(NULL);
Cache_Read_Disable(0);
/* iv stored in sec 0 */
spiRet = SPIEraseSector(0);
if (spiRet != SPI_FLASH_RESULT_OK)
err = bootloader_flash_erase_sector(0);
if (err != ESP_OK)
{
ESP_LOGE(TAG, "SPI erase failed %d", spiRet);
ESP_LOGE(TAG, "SPI erase failed: 0x%x", err);
return false;
}
Cache_Read_Enable(0);
/* write iv to flash, 0x0000, 128 bytes (1024 bits) */
ESP_LOGD(TAG, "write iv to flash.");
spiRet = SPIWrite(0, buf, IV_LEN);
if (spiRet != SPI_FLASH_RESULT_OK)
{
ESP_LOGE(TAG, "SPI write failed %d", spiRet);
return false;
}
bzero(buf, sizeof(buf));
/* generate digest from image contents */
image = bootloader_mmap(0x1000, image_len);
@ -87,22 +72,22 @@ static bool secure_boot_generate(uint32_t image_len){
ESP_LOGE(TAG, "bootloader_mmap(0x1000, 0x%x) failed", image_len);
return false;
}
for (int i = 0; i < image_len; i+= HASH_BLOCK_SIZE) {
ets_secure_boot_hash(image + i/sizeof(void *));
for (int i = 0; i < image_len; i+= sizeof(digest.iv)) {
ets_secure_boot_hash(&image[i/sizeof(uint32_t)]);
}
bootloader_munmap(image);
ets_secure_boot_obtain();
ets_secure_boot_rd_abstract(buf);
ets_secure_boot_rd_abstract((uint32_t *)digest.digest);
ets_secure_boot_finish();
ESP_LOGD(TAG, "write digest to flash.");
spiRet = SPIWrite(0x80, buf, DIGEST_LEN);
if (spiRet != SPI_FLASH_RESULT_OK) {
ESP_LOGE(TAG, "SPI write failed %d", spiRet);
ESP_LOGD(TAG, "write iv+digest to flash");
err = bootloader_flash_write(FLASH_OFFS_SECURE_BOOT_IV_DIGEST, &digest,
sizeof(digest), esp_flash_encryption_enabled());
if (err != ESP_OK) {
ESP_LOGE(TAG, "SPI write failed: 0x%x", err);
return false;
}
ESP_LOGD(TAG, "write digest to flash.");
Cache_Read_Enable(0);
return true;
}
@ -111,14 +96,9 @@ static bool secure_boot_generate(uint32_t image_len){
static inline void burn_efuses()
{
#ifdef CONFIG_SECURE_BOOT_TEST_MODE
ESP_LOGE(TAG, "SECURE BOOT TEST MODE. Not really burning any efuses!");
ESP_LOGE(TAG, "SECURE BOOT TEST MODE. Not really burning any efuses! NOT SECURE");
#else
REG_WRITE(EFUSE_CONF_REG, 0x5A5A); /* efuse_pgm_op_ena, force no rd/wr disable */
REG_WRITE(EFUSE_CMD_REG, 0x02); /* efuse_pgm_cmd */
while (REG_READ(EFUSE_CMD_REG)); /* wait for efuse_pagm_cmd=0 */
REG_WRITE(EFUSE_CONF_REG, 0x5AA5); /* efuse_read_op_ena, release force */
REG_WRITE(EFUSE_CMD_REG, 0x01); /* efuse_read_cmd */
while (REG_READ(EFUSE_CMD_REG)); /* wait for efuse_read_cmd=0 */
esp_efuse_burn_new_values();
#endif
}
@ -131,7 +111,7 @@ esp_err_t esp_secure_boot_permanently_enable(void) {
return ESP_OK;
}
err = esp_image_basic_verify(0x1000, &image_len);
err = esp_image_basic_verify(0x1000, true, &image_len);
if (err != ESP_OK) {
ESP_LOGE(TAG, "bootloader image appears invalid! error %d", err);
return err;
@ -150,25 +130,12 @@ esp_err_t esp_secure_boot_permanently_enable(void) {
&& REG_READ(EFUSE_BLK2_RDATA5_REG) == 0
&& REG_READ(EFUSE_BLK2_RDATA6_REG) == 0
&& REG_READ(EFUSE_BLK2_RDATA7_REG) == 0) {
ESP_LOGI(TAG, "Generating new secure boot key...");
/* reuse the secure boot IV generation function to generate
the key, as this generator uses the hardware RNG. */
uint32_t buf[32];
ets_secure_boot_start();
ets_secure_boot_rd_iv(buf);
ets_secure_boot_finish();
for (int i = 0; i < 8; i++) {
ESP_LOGV(TAG, "EFUSE_BLK2_WDATA%d_REG = 0x%08x", i, buf[i]);
REG_WRITE(EFUSE_BLK2_WDATA0_REG + 4*i, buf[i]);
}
bzero(buf, sizeof(buf));
burn_efuses();
ESP_LOGI(TAG, "Read & write protecting new key...");
REG_WRITE(EFUSE_BLK0_WDATA0_REG, EFUSE_WR_DIS_BLK2 | EFUSE_RD_DIS_BLK2);
burn_efuses();
efuse_key_read_protected = true;
efuse_key_write_protected = true;
/* On-device key generation is temporarily disabled, until
* RNG operation during bootloader is qualified.
* See docs/security/secure-boot.rst for details. */
ESP_LOGE(TAG, "On-device key generation is not yet available.");
return ESP_ERR_NOT_SUPPORTED;
} else {
ESP_LOGW(TAG, "Using pre-loaded secure boot key in EFUSE block 2");
}
@ -180,6 +147,7 @@ esp_err_t esp_secure_boot_permanently_enable(void) {
}
ESP_LOGI(TAG, "Digest generation complete.");
#ifndef CONFIG_SECURE_BOOT_TEST_MODE
if (!efuse_key_read_protected) {
ESP_LOGE(TAG, "Pre-loaded key is not read protected. Refusing to blow secure boot efuse.");
return ESP_ERR_INVALID_STATE;
@ -188,21 +156,26 @@ esp_err_t esp_secure_boot_permanently_enable(void) {
ESP_LOGE(TAG, "Pre-loaded key is not write protected. Refusing to blow secure boot efuse.");
return ESP_ERR_INVALID_STATE;
}
#endif
ESP_LOGI(TAG, "blowing secure boot efuse...");
ESP_LOGD(TAG, "before updating, EFUSE_BLK0_RDATA6 %x", REG_READ(EFUSE_BLK0_RDATA6_REG));
uint32_t new_wdata6 = EFUSE_RD_ABS_DONE_0;
#ifdef CONFIG_SECURE_BOOT_DISABLE_JTAG
ESP_LOGI(TAG, "disabling JTAG...");
#ifndef CONFIG_SECURE_BOOT_ALLOW_JTAG
ESP_LOGI(TAG, "Disable JTAG...");
new_wdata6 |= EFUSE_RD_DISABLE_JTAG;
#endif
#else
ESP_LOGW(TAG, "Not disabling JTAG - SECURITY COMPROMISED");
#endif
#ifdef CONFIG_SECURE_BOOT_DISABLE_UART_BOOTLOADER
ESP_LOGI(TAG, "disabling UART bootloader...");
new_wdata6 |= EFUSE_RD_CONSOLE_DEBUG_DISABLE_S;
#endif
#ifndef CONFIG_SECURE_BOOT_ALLOW_ROM_BASIC
ESP_LOGI(TAG, "Disable ROM BASIC interpreter fallback...");
new_wdata6 |= EFUSE_RD_CONSOLE_DEBUG_DISABLE;
#else
ESP_LOGW(TAG, "Not disabling ROM BASIC fallback - SECURITY COMPROMISED");
#endif
REG_WRITE(EFUSE_BLK0_WDATA6_REG, new_wdata6);
burn_efuses();

View File

@ -27,11 +27,6 @@ typedef SHA_CTX sha_context;
#include "hwcrypto/sha.h"
#endif
typedef struct {
uint32_t version;
uint8_t signature[64];
} signature_block_t;
static const char* TAG = "secure_boot";
extern const uint8_t signature_verification_key_start[] asm("_binary_signature_verification_key_bin_start");
@ -47,7 +42,7 @@ esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
uint8_t digest[32];
ptrdiff_t keylen;
const uint8_t *data;
const signature_block_t *sigblock;
const esp_secure_boot_sig_block_t *sigblock;
bool is_valid;
#ifdef BOOTLOADER_BUILD
const uint8_t *digest_data;
@ -56,13 +51,13 @@ esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
ESP_LOGD(TAG, "verifying signature src_addr 0x%x length 0x%x", src_addr, length);
data = bootloader_mmap(src_addr, length + sizeof(signature_block_t));
data = bootloader_mmap(src_addr, length + sizeof(esp_secure_boot_sig_block_t));
if(data == NULL) {
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", src_addr, length+sizeof(signature_block_t));
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", src_addr, length+sizeof(esp_secure_boot_sig_block_t));
return ESP_FAIL;
}
sigblock = (const signature_block_t *)(data + length);
sigblock = (const esp_secure_boot_sig_block_t *)(data + length);
if (sigblock->version != 0) {
ESP_LOGE(TAG, "src 0x%x has invalid signature version field 0x%08x", src_addr, sigblock->version);

View File

@ -33,8 +33,10 @@ COMPONENT_ADD_INCLUDEDIRS := bluedroid/bta/include \
LIBS := btdm_app
COMPONENT_ADD_LDFLAGS := -lbt -L $(COMPONENT_PATH)/lib \
$(addprefix -l,$(LIBS)) \
$(LINKER_SCRIPTS)
$(addprefix -l,$(LIBS))
# re-link program if BT binary libs change
COMPONENT_ADD_LINKER_DEPS := $(patsubst %,$(COMPONENT_PATH)/lib/lib%.a,$(LIBS))
COMPONENT_SRCDIRS := bluedroid/bta/dm \
bluedroid/bta/gatt \
@ -68,7 +70,4 @@ COMPONENT_SRCDIRS := bluedroid/bta/dm \
bluedroid \
.
ALL_LIB_FILES := $(patsubst %,$(COMPONENT_PATH)/lib/lib%.a,$(LIBS))
$(COMPONENT_LIBRARY): $(ALL_LIB_FILES)
COMPONENT_SUBMODULES += lib

View File

@ -14,6 +14,7 @@
#include <esp_types.h>
#include "esp_err.h"
#include "esp_intr.h"
#include "esp_intr_alloc.h"
#include "freertos/FreeRTOS.h"
#include "freertos/xtensa_api.h"
#include "driver/gpio.h"
@ -21,11 +22,12 @@
#include "soc/soc.h"
#include "esp_log.h"
static const char* GPIO_TAG = "GPIO";
#define GPIO_CHECK(a, str, ret_val) if (!(a)) { \
ESP_LOGE(GPIO_TAG,"%s:%d (%s):%s", __FILE__, __LINE__, __FUNCTION__, str); \
return (ret_val); \
}
static const char* GPIO_TAG = "gpio";
#define GPIO_CHECK(a, str, ret_val) \
if (!(a)) { \
ESP_LOGE(GPIO_TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \
return (ret_val); \
}
const uint32_t GPIO_PIN_MUX_REG[GPIO_PIN_COUNT] = {
GPIO_PIN_REG_0,
@ -320,14 +322,10 @@ esp_err_t gpio_config(gpio_config_t *pGPIOConfig)
return ESP_OK;
}
esp_err_t gpio_isr_register(uint32_t gpio_intr_num, void (*fn)(void*), void * arg)
esp_err_t gpio_isr_register(void (*fn)(void*), void * arg, int intr_alloc_flags, gpio_isr_handle_t *handle)
{
GPIO_CHECK(fn, "GPIO ISR null", ESP_ERR_INVALID_ARG);
ESP_INTR_DISABLE(gpio_intr_num);
intr_matrix_set(xPortGetCoreID(), ETS_GPIO_INTR_SOURCE, gpio_intr_num);
xt_set_interrupt_handler(gpio_intr_num, fn, arg);
ESP_INTR_ENABLE(gpio_intr_num);
return ESP_OK;
return esp_intr_alloc(ETS_GPIO_INTR_SOURCE, intr_alloc_flags, fn, arg, handle);
}
/*only level interrupt can be used for wake-up function*/

View File

@ -23,6 +23,7 @@
#include "soc/gpio_sig_map.h"
#include "rom/gpio.h"
#include "esp_attr.h"
#include "esp_intr_alloc.h"
#ifdef __cplusplus
extern "C" {
@ -203,6 +204,9 @@ typedef enum {
GPIO_FLOATING, /*!< Pad floating */
} gpio_pull_mode_t;
typedef intr_handle_t gpio_isr_handle_t;
typedef void (*gpio_event_callback)(gpio_num_t gpio_intr_num);
/**
@ -343,19 +347,18 @@ esp_err_t gpio_wakeup_disable(gpio_num_t gpio_num);
* Users should know that which CPU is running and then pick a INUM that is not used by system.
* We can find the information of INUM and interrupt level in soc.h.
*
* @param gpio_intr_num GPIO interrupt number,check the info in soc.h, and please see the core-isa.h for more details
* @param fn Interrupt handler function.
*
* @note
* Note that the handler function MUST be defined with attribution of "IRAM_ATTR".
*
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
* ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
* @param arg Parameter for handler function
* @param handle Pointer to return handle. If non-NULL, a handle for the interrupt will
* be returned here.
*
* @return
* - ESP_OK Success ;
* - ESP_ERR_INVALID_ARG GPIO error
*/
esp_err_t gpio_isr_register(uint32_t gpio_intr_num, void (*fn)(void*), void * arg);
esp_err_t gpio_isr_register(void (*fn)(void*), void * arg, int intr_alloc_flags, gpio_isr_handle_t *handle);
@ -415,7 +418,7 @@ esp_err_t gpio_pulldown_dis(gpio_num_t gpio_num);
*/
/**
*----------EXAMPLE TO CONIFGURE GPIO AS OUTPUT ------------ *
*----------EXAMPLE TO CONFIGURE GPIO AS OUTPUT ------------ *
* @code{c}
* gpio_config_t io_conf;
* io_conf.intr_type = GPIO_INTR_DISABLE; //disable interrupt
@ -428,7 +431,7 @@ esp_err_t gpio_pulldown_dis(gpio_num_t gpio_num);
**/
/**
*----------EXAMPLE TO CONIFGURE GPIO AS OUTPUT ------------ *
*----------EXAMPLE TO CONFIGURE GPIO AS OUTPUT ------------ *
* @code{c}
* io_conf.intr_type = GPIO_INTR_POSEDGE; //set posedge interrupt
* io_conf.mode = GPIO_MODE_INPUT; //set as input
@ -441,8 +444,7 @@ esp_err_t gpio_pulldown_dis(gpio_num_t gpio_num);
/**
*----------EXAMPLE TO SET ISR HANDLER ----------------------
* @code{c}
* //the first parameter is INUM, you can pick one form interrupt level 1/2 which is not used by the system.
* gpio_isr_register(18,gpio_intr_test,NULL); //hook the isr handler for GPIO interrupt
* gpio_isr_register(gpio_intr_test,NULL, 0); //hook the isr handler for GPIO interrupt
* @endcode
* @note
* 1. user should arrange the INUMs that used, better not to use a same INUM for different interrupt.

View File

@ -21,6 +21,7 @@
#include "soc/ledc_struct.h"
#include "driver/gpio.h"
#include "driver/periph_ctrl.h"
#include "esp_intr_alloc.h"
#ifdef __cplusplus
extern "C" {
@ -100,6 +101,7 @@ typedef struct {
uint32_t freq_hz; /*!< LEDC timer frequency(Hz)*/
} ledc_timer_config_t;
typedef intr_handle_t ledc_isr_handle_t;
/**
* @brief LEDC channel configuration
@ -257,20 +259,20 @@ esp_err_t ledc_set_fade(ledc_mode_t speed_mode, uint32_t channel, uint32_t duty,
/**
* @brief register LEDC interrupt handler, the handler is an ISR.
* The handler will be attached to the same CPU core that this function is running on.
* @note
* Users should know that which CPU is running and then pick a INUM that is not used by system.
* We can find the information of INUM and interrupt level in soc.h.
* @param ledc_intr_num LEDC interrupt number, check the info in soc.h, and please see the core-isa.h for more details
*
* @param fn Interrupt handler function.
* @note
* Note that the handler function MUST be defined with attribution of "IRAM_ATTR".
* @param arg User-supplied argument passed to the handler function.
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
* ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
* @param arg Parameter for handler function
* @param handle Pointer to return handle. If non-NULL, a handle for the interrupt will
* be returned here.
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Function pointer error.
*/
esp_err_t ledc_isr_register(uint32_t ledc_intr_num, void (*fn)(void*), void * arg);
esp_err_t ledc_isr_register(void (*fn)(void*), void * arg, int intr_alloc_flags, ledc_isr_handle_t *handle);
/**
* @brief configure LEDC settings
@ -398,13 +400,8 @@ esp_err_t ledc_bind_channel_timer(ledc_mode_t speed_mode, uint32_t channel, uint
* ----------------EXAMPLE OF LEDC INTERRUPT ------------------
* @code{c}
* //we have fade_end interrupt and counter overflow interrupt. we just give an example of fade_end interrupt here.
* ledc_isr_register(18, ledc_isr_handler, NULL); //hook the isr handler for LEDC interrupt
* ledc_isr_register(ledc_isr_handler, NULL, 0); //hook the isr handler for LEDC interrupt
* @endcode
* @note
* 1. the first parameter is INUM, you can pick one form interrupt level 1/2 which is not used by the system.
* 2. user should arrange the INUMs that used, better not to use a same INUM for different interrupt source.
* 3. do not pick the INUM that already occupied by the system.
* 4. refer to soc.h to check which INUMs that can be used.
*
* ----------------EXAMPLE OF INTERRUPT HANDLER ---------------
* @code{c}

View File

@ -12,6 +12,7 @@
#include "soc/pcnt_struct.h"
#include "soc/gpio_sig_map.h"
#include "driver/gpio.h"
#include "esp_intr_alloc.h"
#ifdef __cplusplus
extern "C" {
@ -76,6 +77,8 @@ typedef struct {
pcnt_channel_t channel; /*!< the PCNT channel */
} pcnt_config_t;
typedef intr_handle_t pcnt_isr_handle_t;
/**
* @brief Configure Pulse Counter unit
*
@ -213,21 +216,19 @@ esp_err_t pcnt_get_event_value(pcnt_unit_t unit, pcnt_evt_type_t evt_type, int16
/**
* @brief Register PCNT interrupt handler, the handler is an ISR.
* The handler will be attached to the same CPU core that this function is running on.
* @note
* Users should know that which CPU is running and then pick a INUM that is not used by system.
* We can find the information of INUM and interrupt level in soc.h.
*
* @param pcnt_intr_num PCNT interrupt number, check the info in soc.h, and please see the core-isa.h for more details
* @param fn Interrupt handler function.
* @note
* Note that the handler function MUST be defined with attribution of "IRAM_ATTR".
* @param arg Parameter for handler function
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
* ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
* @param handle Pointer to return handle. If non-NULL, a handle for the interrupt will
* be returned here.
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Function pointer error.
*/
esp_err_t pcnt_isr_register(uint32_t pcnt_intr_num, void (*fn)(void*), void * arg);
esp_err_t pcnt_isr_register(void (*fn)(void*), void * arg, int intr_alloc_flags, pcnt_isr_handle_t *handle);
/**
* @brief Configure PCNT pulse signal input pin and control input pin

View File

@ -117,6 +117,8 @@ typedef struct {
};
} rmt_config_t;
typedef intr_handle_t rmt_isr_handle_t;
/**
* @brief Set RMT clock divider, channel clock is divided from source clock.
*
@ -566,27 +568,32 @@ esp_err_t rmt_config(rmt_config_t* rmt_param);
* @brief register RMT interrupt handler, the handler is an ISR.
*
* The handler will be attached to the same CPU core that this function is running on.
* Users should know that which CPU is running and then pick a INUM that is not used by system.
* We can find the information of INUM and interrupt level in soc.h.
* @note
* If you already called rmt_driver_install to use system RMT driver,
* @note If you already called rmt_driver_install to use system RMT driver,
* please do not register ISR handler again.
*
* @param rmt_intr_num RMT interrupt number, check the info in soc.h, and please see the core-isa.h for more details
*
* @param fn Interrupt handler function.
*
* @note
* the handler function MUST be defined with attribution of "IRAM_ATTR".
*
* @param arg Parameter for handler function
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
* ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
* @param handle If non-zero, a handle to later clean up the ISR gets stored here.
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Function pointer error.
* - ESP_FAIL System driver installed, can not register ISR handler for RMT
*/
esp_err_t rmt_isr_register(uint8_t rmt_intr_num, void (* fn)(void* ), void * arg);
esp_err_t rmt_isr_register(void (* fn)(void* ), void * arg, int intr_alloc_flags, rmt_isr_handle_t *handle);
/**
* @brief Deregister previously registered RMT interrupt handler
*
* @param handle Handle obtained from rmt_isr_register
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Handle invalid
*/
esp_err_t rmt_isr_deregister(rmt_isr_handle_t handle);
/**
* @brief Fill memory data of channel with given RMT items.
@ -727,7 +734,7 @@ esp_err_t rmt_get_ringbuf_handler(rmt_channel_t channel, RingbufHandle_t* buf_ha
* rmt_config(&rmt_tx);
*
* //install system RMT driver, disable rx ringbuffer for transmitter.
* rmt_driver_install(rmt_tx.channel, 0, RMT_INTR_NUM);
* rmt_driver_install(rmt_tx.channel, 0, 0);
* }
*
* @endcode
@ -747,25 +754,20 @@ esp_err_t rmt_get_ringbuf_handler(rmt_channel_t channel, RingbufHandle_t* buf_ha
* rmt_config(&rmt_rx);
*
* //install system RMT driver.
* rmt_driver_install(rmt_rx.channel, 1000, RMT_INTR_NUM);
* rmt_driver_install(rmt_rx.channel, 1000, 0);
* }
*
* ----------------EXAMPLE OF RMT INTERRUPT ------------------
* @code{c}
*
* rmt_isr_register(RMT_INTR_NUM, rmt_isr, NULL); //hook the ISR handler for RMT interrupt
* rmt_isr_register(rmt_isr, NULL, 0); //hook the ISR handler for RMT interrupt
* @endcode
* @note
* 0. If you have called rmt_driver_install, you don't need to set ISR handler any more.
* 1. the first parameter is INUM, you can pick one form interrupt level 1/2 which is not used by the system.
* 2. user should arrange the INUMs that used, better not to use a same INUM for different interrupt source.
* 3. do not pick the INUM that already occupied by the system.
* 4. refer to soc.h to check which INUMs that can be used.
*
* ----------------EXAMPLE OF INTERRUPT HANDLER ---------------
* @code{c}
* #include "esp_attr.h"
* //we should add 'IRAM_ATTR' attribution when we declare the isr function
* void IRAM_ATTR rmt_isr_handler(void* arg)
* {
* //read RMT interrupt status.

View File

@ -19,6 +19,7 @@
#include "soc/soc.h"
#include "soc/timer_group_reg.h"
#include "soc/timer_group_struct.h"
#include "esp_intr_alloc.h"
#ifdef __cplusplus
extern "C" {
@ -94,12 +95,19 @@ typedef enum {
typedef struct {
bool alarm_en; /*!< Timer alarm enable */
bool counter_en; /*!< Counter enable */
timer_count_dir_t counter_dir; /*!< Counter direction */
timer_intr_mode_t intr_type; /*!< Interrupt mode */
timer_count_dir_t counter_dir; /*!< Counter direction */
bool auto_reload; /*!< Timer auto-reload */
uint16_t divider; /*!< Counter clock divider*/
} timer_config_t;
/**
* @brief Interrupt handle, used in order to free the isr after use.
* Aliases to an int handle for now.
*/
typedef intr_handle_t timer_isr_handle_t;
/**
* @brief Read the counter value of hardware timer.
*
@ -245,21 +253,20 @@ esp_err_t timer_set_alarm(timer_group_t group_num, timer_idx_t timer_num, timer_
/**
* @brief register Timer interrupt handler, the handler is an ISR.
* The handler will be attached to the same CPU core that this function is running on.
* @note
* Users should know that which CPU is running and then pick a INUM that is not used by system.
* We can find the information of INUM and interrupt level in soc.h.
*
* @param group_num Timer group number
* @param timer_num Timer index of timer group
* @param timer_intr_num TIMER interrupt number, check the info in soc.h, and please see the core-isa.h for more details
* @param intr_type Timer interrupt type
* @param fn Interrupt handler function.
* @note
* Code inside the handler function can only call functions in IRAM, so cannot call other timer APIs.
* Use direct register access to access timers from inside the ISR.
* In case the this is called with the INIRAM flag, code inside the handler function can
* only call functions in IRAM, so it cannot call other timer APIs.
* Use direct register access to access timers from inside the ISR in this case.
*
* @param arg Parameter for handler function
*
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
* ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
* @param handle Pointer to return handle. If non-NULL, a handle for the interrupt will
* be returned here.
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Function pointer error.
@ -268,7 +275,7 @@ esp_err_t timer_set_alarm(timer_group_t group_num, timer_idx_t timer_num, timer_
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t timer_isr_register(timer_group_t group_num, timer_idx_t timer_num, int timer_intr_num, timer_intr_mode_t intr_type, void (*fn)(void*), void * arg);
esp_err_t timer_isr_register(timer_group_t group_num, timer_idx_t timer_num, void (*fn)(void*), void * arg, int intr_alloc_flags, timer_isr_handle_t *handle);
/** @brief Initializes and configure the timer.
*

View File

@ -19,6 +19,7 @@ extern "C" {
#endif
#include "esp_intr.h"
#include "esp_err.h"
#include "esp_intr_alloc.h"
#define TOUCH_PAD_SLEEP_CYCLE_CONFIG (0x1000)//The Time is 150Khz,the Max value is 0xffff
#define TOUCH_PAD_MEASURE_CYCLE_CONFIG (0xffff)//The Time is 8Mhz,the Max value is 0xffff
typedef enum {
@ -34,6 +35,9 @@ typedef enum {
TOUCH_PAD_NUM9, /*!< Touch pad channel 0 is GPIO32*/
TOUCH_PAD_MAX,
} touch_pad_t;
typedef intr_handle_t touch_isr_handle_t;
/**
* @brief Initialize touch module.
*
@ -79,44 +83,40 @@ esp_err_t touch_pad_read(touch_pad_t touch_num, uint16_t * touch_value);
/**
* @brief register TouchPad interrupt handler, the handler is an ISR.
* The handler will be attached to the same CPU core that this function is running on.
* @note
* Users should know that which CPU is running and then pick a INUM that is not used by system.
* We can find the information of INUM and interrupt level in soc.h.
*
* @param touch_intr_num Touch interrupt number,check the info in soc.h, and please see the core-isa.h for more details
* @param fn Interrupt handler function.
*
* @note
* Note that the handler function MUST be defined with attribution of "IRAM_ATTR".
*
* @param arg Parameter for handler function
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
* ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
* @param handle Pointer to return handle. If non-NULL, a handle for the interrupt will
* be returned here.
*
* @return
* - ESP_OK Success ;
* - ESP_ERR_INVALID_ARG GPIO error
*/
esp_err_t touch_pad_isr_handler_register(uint32_t touch_intr_num, void(*fn)(void*), void *arg);
esp_err_t touch_pad_isr_handler_register(void(*fn)(void *), void *arg, int intr_alloc_flags, touch_isr_handle_t *handle);
/**
* *************** ATTENTION ********************/
/**
*@attention
*Touch button is through the body's capacitive characteristics,
*there is a charge discharge circuit inside the. When the hands touch,
*the charge and discharge time will be slow.
*Because of the different hardware, each pad needs to be calibrated at the factory.
*We use touch_pad_read to determine factory parament.
*/
*Touch button is through the body's capacitive characteristics,
*there is a charge discharge circuit inside the. When the hands touch,
*the charge and discharge time will be slow.
*Because of the different hardware, each pad needs to be calibrated at the factory.
*We use touch_pad_read to determine factory parameters.
*/
/**
*----------EXAMPLE TO CONIFGURE GPIO AS OUTPUT ------------ *
*----------EXAMPLE TO CONFIGURE GPIO AS OUTPUT ------------ *
* @code{c}
* touch_pad_init();
* void taskA(void* arg)
* {
* for(;;){
* vtaskDelay(20/portTICK_PERIOD_MS);
* ets_printf("tocuch pad value %u\n",touch_pad_read(0));//Take the touched status and untouched status value
* ets_printf("touch pad value %u\n",touch_pad_read(0));//Take the touched status and untouched status value
* }
* }
* @endcode
@ -124,22 +124,17 @@ esp_err_t touch_pad_isr_handler_register(uint32_t touch_intr_num, void(*fn)(void
/**
*----------EXAMPLE TO SET ISR HANDLER ----------------------
* @code{c}
* //the first parameter is INUM, you can pick one form interrupt level 1/2 which is not used by the system.
* touch_pad_isr_handler_register(19,rtc_intr,NULL); //hook the isr handler for TouchPad interrupt
* touch_pad_isr_handler_register(rtc_intr,NULL, 0, NULL) //hook the isr handler for TouchPad interrupt
* @endcode
* @note
* 1. user should arrange the INUMs that used, better not to use a same INUM for different interrupt.
* 2. do not pick the INUM that already occupied by the system.
* 3. refer to soc.h to check which INUMs that can be used.
*/
/**
*----------EXAMPLE TO USE TOUCH_PAD------------ *
* @code{c}
* touch_pad_init();//only init one time
* touch_pad_config(0,300);//set the intr threshold,use touch_pad_read to determine this threshold
* touch_pad_isr_handler_register(19,rtc_intr,NULL)
* touch_pad_isr_handler_register(rtc_intr,NULL, 0, NULL)
* #include "esp_attr.h"
* void IRAM_ATTR rtc_intr(void * arg)
* void rtc_intr(void * arg)
* {
* uint32_t pad_intr = READ_PERI_REG(SARADC_SAR_TOUCH_CTRL2_REG) & 0x3ff;
* uint8_t i = 0;

View File

@ -366,21 +366,31 @@ esp_err_t uart_enable_tx_intr(uart_port_t uart_num, int enable, int thresh);
* @brief register UART interrupt handler(ISR).
*
* @note UART ISR handler will be attached to the same CPU core that this function is running on.
* Users should know that which CPU is running and then pick a INUM that is not used by system.
* We can find the information of INUM and interrupt level in soc.h.
*
* @attention The ISR handler function MUST be defined with attribution of "IRAM_ATTR" for now.
*
* @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
* @param uart_intr_num UART interrupt number,check the info in soc.h, and please refer to core-isa.h for more details
* @param fn Interrupt handler function.
* @param arg parameter for handler function
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
* ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
*
* @return
* - ESP_OK Success
* - ESP_FAIL Parameter error
*/
esp_err_t uart_isr_register(uart_port_t uart_num, uint8_t uart_intr_num, void (*fn)(void*), void * arg);
esp_err_t uart_isr_register(uart_port_t uart_num, void (*fn)(void*), void * arg, int intr_alloc_flags);
/**
* @brief Free UART interrupt handler registered by uart_isr_register. Must be called on the same core as
* uart_isr_register was called.
*
* @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
*
* @return
* - ESP_OK Success
* - ESP_FAIL Parameter error
*/
esp_err_t uart_isr_free(uart_port_t uart_num);
/**
* @brief Set UART pin number
@ -461,14 +471,15 @@ esp_err_t uart_intr_config(uart_port_t uart_num, const uart_intr_config_t *intr_
* @param tx_buffer_size UART TX ring buffer size.
* If set to zero, driver will not use TX buffer, TX function will block task until all data have been sent out..
* @param queue_size UART event queue size/depth.
* @param uart_intr_num UART interrupt number,check the info in soc.h, and please refer to core-isa.h for more details
* @param uart_queue UART event queue handle, if set NULL, driver will not use an event queue.
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
* ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
*
* @return
* - ESP_OK Success
* - ESP_FAIL Parameter error
*/
esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_buffer_size, int queue_size, int uart_intr_num, void* uart_queue);
esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_buffer_size, int queue_size, void* uart_queue, int intr_alloc_flags);
/**
* @brief Uninstall UART driver.
@ -733,7 +744,7 @@ esp_err_t uart_flush(uart_port_t uart_num);
* //Set UART log level
* esp_log_level_set(TAG, ESP_LOG_INFO);
* //Install UART driver, and get the queue.
* uart_driver_install(uart_num, 1024 * 2, 1024*4, 10, 17, &uart0_queue);
* uart_driver_install(uart_num, 1024 * 2, 1024*4, 10, &uart0_queue, 0);
* //Create a task to handler UART event from ISR
* xTaskCreate(uart_task, "uTask", 1024, (void*)uart_num, 10, NULL);
* }

View File

@ -13,6 +13,7 @@
// limitations under the License.
#include <esp_types.h>
#include "esp_intr.h"
#include "esp_intr_alloc.h"
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#include "freertos/xtensa_api.h"
@ -20,12 +21,13 @@
#include "driver/ledc.h"
#include "esp_log.h"
static const char* LEDC_TAG = "LEDC";
static const char* LEDC_TAG = "ledc";
static portMUX_TYPE ledc_spinlock = portMUX_INITIALIZER_UNLOCKED;
#define LEDC_CHECK(a, str, ret_val) if (!(a)) { \
ESP_LOGE(LEDC_TAG,"%s:%d (%s):%s", __FILE__, __LINE__, __FUNCTION__, str); \
return (ret_val); \
}
#define LEDC_CHECK(a, str, ret_val) \
if (!(a)) { \
ESP_LOGE(LEDC_TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \
return (ret_val); \
}
esp_err_t ledc_timer_set(ledc_mode_t speed_mode, ledc_timer_t timer_sel, uint32_t div_num, uint32_t bit_num, ledc_clk_src_t clk_src)
{
@ -113,16 +115,14 @@ static esp_err_t ledc_enable_intr_type(ledc_mode_t speed_mode, uint32_t channel,
return ESP_OK;
}
esp_err_t ledc_isr_register(uint32_t ledc_intr_num, void (*fn)(void*), void * arg)
esp_err_t ledc_isr_register(void (*fn)(void*), void * arg, int intr_alloc_flags, ledc_isr_handle_t *handle)
{
esp_err_t ret;
LEDC_CHECK(fn, "ledc isr null", ESP_ERR_INVALID_ARG);
portENTER_CRITICAL(&ledc_spinlock);
ESP_INTR_DISABLE(ledc_intr_num);
intr_matrix_set(xPortGetCoreID(), ETS_LEDC_INTR_SOURCE, ledc_intr_num);
xt_set_interrupt_handler(ledc_intr_num, fn, arg);
ESP_INTR_ENABLE(ledc_intr_num);
ret=esp_intr_alloc(ETS_LEDC_INTR_SOURCE, intr_alloc_flags, fn, arg, handle);
portEXIT_CRITICAL(&ledc_spinlock);
return ESP_OK;
return ret;
}
esp_err_t ledc_timer_config(ledc_timer_config_t* timer_conf)

View File

@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include "esp_log.h"
#include "esp_intr_alloc.h"
#include "driver/pcnt.h"
#include "driver/periph_ctrl.h"
@ -23,12 +24,14 @@
#define PCNT_COUNT_MODE_ERR_STR "PCNT COUNTER MODE ERROR"
#define PCNT_CTRL_MODE_ERR_STR "PCNT CTRL MODE ERROR"
#define PCNT_EVT_TYPE_ERR_STR "PCNT value type error"
#define PCNT_CHECK(a,str,ret_val) if(!(a)) { \
ESP_LOGE(PCNT_TAG,"%s:%d (%s):%s", __FILE__, __LINE__, __FUNCTION__, str); \
return (ret_val); \
}
static const char* PCNT_TAG = "PCNT";
static const char* PCNT_TAG = "pcnt";
#define PCNT_CHECK(a, str, ret_val) \
if (!(a)) { \
ESP_LOGE(PCNT_TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \
return (ret_val); \
}
static portMUX_TYPE pcnt_spinlock = portMUX_INITIALIZER_UNLOCKED;
#define PCNT_ENTER_CRITICAL(mux) portENTER_CRITICAL(mux)
@ -266,13 +269,9 @@ esp_err_t pcnt_filter_disable(pcnt_unit_t unit)
return ESP_OK;
}
esp_err_t pcnt_isr_register(uint32_t pcnt_intr_num, void (*fun)(void*), void * arg)
esp_err_t pcnt_isr_register(void (*fun)(void*), void * arg, int intr_alloc_flags, pcnt_isr_handle_t *handle)
{
PCNT_CHECK(fun != NULL, PCNT_ADDRESS_ERR_STR, ESP_ERR_INVALID_ARG);
ESP_INTR_DISABLE(pcnt_intr_num);
intr_matrix_set(xPortGetCoreID(), ETS_PCNT_INTR_SOURCE, pcnt_intr_num);
xt_set_interrupt_handler(pcnt_intr_num, fun, arg);
ESP_INTR_ENABLE(pcnt_intr_num);
return ESP_OK;
return esp_intr_alloc(ETS_PCNT_INTR_SOURCE, intr_alloc_flags, fun, arg, handle);
}

View File

@ -21,6 +21,7 @@
#include "esp_intr.h"
#include "esp_log.h"
#include "esp_err.h"
#include "esp_intr_alloc.h"
#include "soc/gpio_sig_map.h"
#include "soc/rmt_struct.h"
#include "driver/periph_ctrl.h"
@ -43,13 +44,16 @@
#define RMT_DRIVER_ERROR_STR "RMT DRIVER ERR"
#define RMT_DRIVER_LENGTH_ERROR_STR "RMT PARAM LEN ERROR"
static const char* RMT_TAG = "RMT";
static const char* RMT_TAG = "rmt";
static bool s_rmt_driver_installed = false;
static rmt_isr_handle_t s_rmt_driver_intr_handle;
#define RMT_CHECK(a, str, ret_val) \
if (!(a)) { \
ESP_LOGE(RMT_TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \
return (ret_val); \
}
#define RMT_CHECK(a, str, ret) if (!(a)) { \
ESP_LOGE(RMT_TAG,"%s:%d (%s):%s", __FILE__, __LINE__, __FUNCTION__, str); \
return (ret); \
}
static portMUX_TYPE rmt_spinlock = portMUX_INITIALIZER_UNLOCKED;
typedef struct {
@ -472,17 +476,21 @@ esp_err_t rmt_fill_tx_items(rmt_channel_t channel, rmt_item32_t* item, uint16_t
return ESP_OK;
}
esp_err_t rmt_isr_register(uint8_t rmt_intr_num, void (*fn)(void*), void * arg)
esp_err_t rmt_isr_register(void (*fn)(void*), void * arg, int intr_alloc_flags, rmt_isr_handle_t *handle)
{
esp_err_t ret;
RMT_CHECK((fn != NULL), RMT_ADDR_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_CHECK(s_rmt_driver_installed == false, "RMT DRIVER INSTALLED, CAN NOT REG ISR HANDLER", ESP_FAIL);
portENTER_CRITICAL(&rmt_spinlock);
ESP_INTR_DISABLE(rmt_intr_num);
intr_matrix_set(xPortGetCoreID(), ETS_RMT_INTR_SOURCE, rmt_intr_num);
xt_set_interrupt_handler(rmt_intr_num, fn, arg);
ESP_INTR_ENABLE(rmt_intr_num);
ret=esp_intr_alloc(ETS_RMT_INTR_SOURCE, intr_alloc_flags, fn, arg, handle);
portEXIT_CRITICAL(&rmt_spinlock);
return ESP_OK;
return ret;
}
esp_err_t rmt_isr_deregister(rmt_isr_handle_t handle)
{
return esp_intr_free(handle);
}
static int IRAM_ATTR rmt_get_mem_len(rmt_channel_t channel)
@ -616,10 +624,10 @@ esp_err_t rmt_driver_uninstall(rmt_channel_t channel)
free(p_rmt_obj[channel]);
p_rmt_obj[channel] = NULL;
s_rmt_driver_installed = false;
return ESP_OK;
return rmt_isr_deregister(s_rmt_driver_intr_handle);
}
esp_err_t rmt_driver_install(rmt_channel_t channel, size_t rx_buf_size, int rmt_intr_num)
esp_err_t rmt_driver_install(rmt_channel_t channel, size_t rx_buf_size, int intr_alloc_flags)
{
RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
if(p_rmt_obj[channel] != NULL) {
@ -627,7 +635,6 @@ esp_err_t rmt_driver_install(rmt_channel_t channel, size_t rx_buf_size, int rmt_
return ESP_FAIL;
}
ESP_INTR_DISABLE(rmt_intr_num);
p_rmt_obj[channel] = (rmt_obj_t*) malloc(sizeof(rmt_obj_t));
if(p_rmt_obj[channel] == NULL) {
@ -652,11 +659,10 @@ esp_err_t rmt_driver_install(rmt_channel_t channel, size_t rx_buf_size, int rmt_
rmt_set_err_intr_en(channel, 1);
}
if(s_rmt_driver_installed == false) {
rmt_isr_register(rmt_intr_num, rmt_driver_isr_default, NULL);
rmt_isr_register(rmt_driver_isr_default, NULL, intr_alloc_flags, &s_rmt_driver_intr_handle);
s_rmt_driver_installed = true;
}
rmt_set_tx_intr_en(channel, 1);
ESP_INTR_ENABLE(rmt_intr_num);
return ESP_OK;
}

View File

@ -264,15 +264,10 @@ esp_err_t rtc_gpio_pulldown_dis(gpio_num_t gpio_num)
/*---------------------------------------------------------------
Touch Pad
---------------------------------------------------------------*/
esp_err_t touch_pad_isr_handler_register(uint32_t touch_intr_num, void(*fn)(void *), void *arg)
esp_err_t touch_pad_isr_handler_register(void(*fn)(void *), void *arg, int intr_alloc_flags, touch_isr_handle_t *handle)
{
RTC_MODULE_CHECK(fn, "Touch_Pad ISR null", ESP_ERR_INVALID_ARG);
ESP_INTR_DISABLE(touch_intr_num);
intr_matrix_set(xPortGetCoreID(), ETS_RTC_CORE_INTR_SOURCE, touch_intr_num);
xt_set_interrupt_handler(touch_intr_num, fn, arg);
ESP_INTR_ENABLE(touch_intr_num);
return ESP_OK;
return esp_intr_alloc(ETS_RTC_CORE_INTR_SOURCE, intr_alloc_flags, fn, arg, handle);
}
static esp_err_t touch_pad_get_io_num(touch_pad_t touch_num, gpio_num_t *gpio_num)
@ -383,21 +378,6 @@ static esp_err_t touch_start(touch_pad_t touch_num)
return ESP_OK;
}
static esp_err_t touch_stop(touch_pad_t touch_num)
{
RTC_MODULE_CHECK(touch_num < TOUCH_PAD_MAX, "Touch_Pad Num Err", ESP_ERR_INVALID_ARG);
portENTER_CRITICAL(&rtc_spinlock);
//Disable Digital rtc control :work mode and out mode
CLEAR_PERI_REG_MASK(SENS_SAR_TOUCH_ENABLE_REG, (1 << (touch_num + SENS_TOUCH_PAD_WORKEN_S)) | \
(1 << (touch_num + SENS_TOUCH_PAD_OUTEN2_S)) | \
(1 << (touch_num + SENS_TOUCH_PAD_OUTEN1_S)));
portEXIT_CRITICAL(&rtc_spinlock);
return ESP_OK;
}
esp_err_t touch_pad_config(touch_pad_t touch_num, uint16_t threshold)
{
RTC_MODULE_CHECK(touch_num < TOUCH_PAD_MAX, "Touch_Pad Num Err", ESP_ERR_INVALID_ARG);
@ -533,7 +513,6 @@ esp_err_t adc1_config_width(adc_bits_width_t width_bit)
int adc1_get_voltage(adc1_channel_t channel)
{
uint16_t adc_value;
uint8_t atten = 0;
RTC_MODULE_CHECK(channel < ADC1_CHANNEL_MAX, "ADC Channel Err", ESP_ERR_INVALID_ARG);
portENTER_CRITICAL(&rtc_spinlock);
@ -613,23 +592,6 @@ static esp_err_t dac_out_enable(dac_channel_t channel)
return ESP_OK;
}
static esp_err_t dac_out_disable(dac_channel_t channel)
{
if (channel == DAC_CHANNEL_1) {
portENTER_CRITICAL(&rtc_spinlock);
CLEAR_PERI_REG_MASK(RTC_IO_PAD_DAC1_REG, RTC_IO_PDAC1_XPD_DAC | RTC_IO_PDAC1_DAC_XPD_FORCE);
portEXIT_CRITICAL(&rtc_spinlock);
} else if (channel == DAC_CHANNEL_2) {
portENTER_CRITICAL(&rtc_spinlock);
CLEAR_PERI_REG_MASK(RTC_IO_PAD_DAC2_REG, RTC_IO_PDAC2_XPD_DAC | RTC_IO_PDAC2_DAC_XPD_FORCE);
portEXIT_CRITICAL(&rtc_spinlock);
} else {
return ESP_ERR_INVALID_ARG;
}
return ESP_OK;
}
esp_err_t dac_out_voltage(dac_channel_t channel, uint8_t dac_value)
{
RTC_MODULE_CHECK(channel < DAC_CHANNEL_MAX, "DAC Channel Err", ESP_ERR_INVALID_ARG);

View File

@ -15,16 +15,19 @@
#include "esp_log.h"
#include "esp_err.h"
#include "esp_intr.h"
#include "esp_intr_alloc.h"
#include "freertos/FreeRTOS.h"
#include "freertos/xtensa_api.h"
#include "driver/timer.h"
#include "driver/periph_ctrl.h"
static const char* TIMER_TAG = "TIMER_GROUP";
#define TIMER_CHECK(a, str, ret_val) if (!(a)) { \
ESP_LOGE(TIMER_TAG,"%s:%d (%s):%s", __FILE__, __LINE__, __FUNCTION__, str); \
return (ret_val); \
}
static const char* TIMER_TAG = "timer_group";
#define TIMER_CHECK(a, str, ret_val) \
if (!(a)) { \
ESP_LOGE(TIMER_TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \
return (ret_val); \
}
#define TIMER_GROUP_NUM_ERROR "TIMER GROUP NUM ERROR"
#define TIMER_NUM_ERROR "HW TIMER NUM ERROR"
#define TIMER_PARAM_ADDR_ERROR "HW TIMER PARAM ADDR ERROR"
@ -167,36 +170,38 @@ esp_err_t timer_set_alarm(timer_group_t group_num, timer_idx_t timer_num, timer_
return ESP_OK;
}
esp_err_t timer_isr_register(timer_group_t group_num, timer_idx_t timer_num, int timer_intr_num,
timer_intr_mode_t intr_type, void (*fn)(void*), void * arg)
esp_err_t timer_isr_register(timer_group_t group_num, timer_idx_t timer_num,
void (*fn)(void*), void * arg, int intr_alloc_flags, timer_isr_handle_t *handle)
{
TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);
TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);
TIMER_CHECK(fn != NULL, TIMER_PARAM_ADDR_ERROR, ESP_ERR_INVALID_ARG);
ESP_INTR_DISABLE(timer_intr_num);
int intr_source = 0;
uint32_t status_reg = 0;
int mask = 0;
switch(group_num) {
case TIMER_GROUP_0:
default:
if(intr_type == TIMER_INTR_LEVEL) {
if((intr_alloc_flags & ESP_INTR_FLAG_EDGE) == 0) {
intr_source = ETS_TG0_T0_LEVEL_INTR_SOURCE + timer_num;
} else {
intr_source = ETS_TG0_T0_EDGE_INTR_SOURCE + timer_num;
}
status_reg = TIMG_INT_ST_TIMERS_REG(0);
mask = 1<<timer_num;
break;
case TIMER_GROUP_1:
if(intr_type == TIMER_INTR_LEVEL) {
if((intr_alloc_flags & ESP_INTR_FLAG_EDGE) == 0) {
intr_source = ETS_TG1_T0_LEVEL_INTR_SOURCE + timer_num;
} else {
intr_source = ETS_TG1_T0_EDGE_INTR_SOURCE + timer_num;
}
status_reg = TIMG_INT_ST_TIMERS_REG(1);
mask = 1<<timer_num;
break;
}
intr_matrix_set(xPortGetCoreID(), intr_source, timer_intr_num);
xt_set_interrupt_handler(timer_intr_num, fn, arg);
ESP_INTR_ENABLE(timer_intr_num);
return ESP_OK;
return esp_intr_alloc_intrstatus(intr_source, intr_alloc_flags, status_reg, mask, fn, arg, handle);
}
esp_err_t timer_init(timer_group_t group_num, timer_idx_t timer_num, timer_config_t *config)

View File

@ -15,7 +15,9 @@
#include "esp_types.h"
#include "esp_attr.h"
#include "esp_intr.h"
#include "esp_intr_alloc.h"
#include "esp_log.h"
#include "esp_err.h"
#include "malloc.h"
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
@ -27,11 +29,13 @@
#include "driver/uart.h"
#include "driver/gpio.h"
static const char* UART_TAG = "UART";
#define UART_CHECK(a, str, ret) if (!(a)) { \
ESP_LOGE(UART_TAG,"%s:%d (%s):%s", __FILE__, __LINE__, __FUNCTION__, str); \
return (ret); \
}
static const char* UART_TAG = "uart";
#define UART_CHECK(a, str, ret_val) \
if (!(a)) { \
ESP_LOGE(UART_TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \
return (ret_val); \
}
#define UART_EMPTY_THRESH_DEFAULT (10)
#define UART_FULL_THRESH_DEFAULT (120)
#define UART_TOUT_THRESH_DEFAULT (10)
@ -53,7 +57,7 @@ typedef struct {
uart_port_t uart_num; /*!< UART port number*/
int queue_size; /*!< UART event queue size*/
QueueHandle_t xQueueUart; /*!< UART queue handler*/
int intr_num; /*!< UART interrupt number*/
intr_handle_t intr_handle; /*!< UART interrupt handle*/
//rx parameters
SemaphoreHandle_t rx_mux; /*!< UART RX data mutex*/
int rx_buf_size; /*!< RX ring buffer size */
@ -283,31 +287,41 @@ esp_err_t uart_enable_tx_intr(uart_port_t uart_num, int enable, int thresh)
UART[uart_num]->conf1.txfifo_empty_thrhd = thresh & UART_TXFIFO_EMPTY_THRHD_V;
UART[uart_num]->int_ena.txfifo_empty = enable & 0x1;
UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);
ESP_INTR_ENABLE(p_uart_obj[uart_num]->intr_num);
return ESP_OK;
}
esp_err_t uart_isr_register(uart_port_t uart_num, uint8_t uart_intr_num, void (*fn)(void*), void * arg)
esp_err_t uart_isr_register(uart_port_t uart_num, void (*fn)(void*), void * arg, int intr_alloc_flags)
{
int ret;
UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);
UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
ESP_INTR_DISABLE(uart_intr_num);
switch(uart_num) {
case UART_NUM_1:
intr_matrix_set(xPortGetCoreID(), ETS_UART1_INTR_SOURCE, uart_intr_num);
ret=esp_intr_alloc(ETS_UART1_INTR_SOURCE, intr_alloc_flags, fn, arg, &p_uart_obj[uart_num]->intr_handle);
break;
case UART_NUM_2:
intr_matrix_set(xPortGetCoreID(), ETS_UART2_INTR_SOURCE, uart_intr_num);
ret=esp_intr_alloc(ETS_UART2_INTR_SOURCE, intr_alloc_flags, fn, arg, &p_uart_obj[uart_num]->intr_handle);
break;
case UART_NUM_0:
default:
intr_matrix_set(xPortGetCoreID(), ETS_UART0_INTR_SOURCE, uart_intr_num);
ret=esp_intr_alloc(ETS_UART0_INTR_SOURCE, intr_alloc_flags, fn, arg, &p_uart_obj[uart_num]->intr_handle);
break;
}
xt_set_interrupt_handler(uart_intr_num, fn, arg);
ESP_INTR_ENABLE(uart_intr_num);
UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);
return ESP_OK;
return ret;
}
esp_err_t uart_isr_free(uart_port_t uart_num)
{
esp_err_t ret;
UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);
if (p_uart_obj[uart_num]->intr_handle==NULL) return ESP_ERR_INVALID_ARG;
UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
ret=esp_intr_free(p_uart_obj[uart_num]->intr_handle);
p_uart_obj[uart_num]->intr_handle=NULL;
UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);
return ret;
}
//internal signal can be output to multiple GPIO pads
@ -859,7 +873,7 @@ esp_err_t uart_flush(uart_port_t uart_num)
//rx sem protect the ring buffer read related functions
xSemaphoreTake(p_uart->rx_mux, (portTickType)portMAX_DELAY);
ESP_INTR_DISABLE(p_uart->intr_num);
esp_intr_disable(p_uart->intr_handle);
while(true) {
if(p_uart->rx_head_ptr) {
vRingbufferReturnItem(p_uart->rx_ring_buf, p_uart->rx_head_ptr);
@ -876,12 +890,12 @@ esp_err_t uart_flush(uart_port_t uart_num)
p_uart->rx_ptr = NULL;
p_uart->rx_cur_remain = 0;
p_uart->rx_head_ptr = NULL;
ESP_INTR_ENABLE(p_uart->intr_num);
esp_intr_enable(p_uart->intr_handle);
xSemaphoreGive(p_uart->rx_mux);
if(p_uart->tx_buf_size > 0) {
xSemaphoreTake(p_uart->tx_mux, (portTickType)portMAX_DELAY);
ESP_INTR_DISABLE(p_uart->intr_num);
esp_intr_disable(p_uart->intr_handle);
UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
UART[uart_num]->int_ena.txfifo_empty = 0;
UART[uart_num]->int_clr.txfifo_empty = 1;
@ -901,19 +915,18 @@ esp_err_t uart_flush(uart_port_t uart_num)
p_uart->tx_ptr = NULL;
p_uart->tx_waiting_brk = 0;
p_uart->tx_waiting_fifo = false;
ESP_INTR_ENABLE(p_uart->intr_num);
esp_intr_enable(p_uart->intr_handle);
xSemaphoreGive(p_uart->tx_mux);
}
uart_reset_fifo(uart_num);
return ESP_OK;
}
esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_buffer_size, int queue_size, int uart_intr_num, void* uart_queue)
esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_buffer_size, int queue_size, void* uart_queue, int intr_alloc_flags)
{
UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);
UART_CHECK((rx_buffer_size > 0), "uart rx buffer length error", ESP_FAIL);
if(p_uart_obj[uart_num] == NULL) {
ESP_INTR_DISABLE(uart_intr_num);
p_uart_obj[uart_num] = (uart_obj_t*) malloc(sizeof(uart_obj_t));
if(p_uart_obj[uart_num] == NULL) {
ESP_LOGE(UART_TAG, "UART driver malloc error");
@ -926,7 +939,6 @@ esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_b
p_uart_obj[uart_num]->tx_brk_sem = xSemaphoreCreateBinary();
p_uart_obj[uart_num]->tx_mux = xSemaphoreCreateMutex();
p_uart_obj[uart_num]->rx_mux = xSemaphoreCreateMutex();
p_uart_obj[uart_num]->intr_num = uart_intr_num;
p_uart_obj[uart_num]->queue_size = queue_size;
p_uart_obj[uart_num]->tx_ptr = NULL;
p_uart_obj[uart_num]->tx_head = NULL;
@ -959,7 +971,7 @@ esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_b
ESP_LOGE(UART_TAG, "UART driver already installed");
return ESP_FAIL;
}
uart_isr_register(uart_num, uart_intr_num, uart_rx_intr_handler_default, p_uart_obj[uart_num]);
uart_isr_register(uart_num, uart_rx_intr_handler_default, p_uart_obj[uart_num], intr_alloc_flags);
uart_intr_config_t uart_intr = {
.intr_enable_mask = UART_RXFIFO_FULL_INT_ENA_M
| UART_RXFIFO_TOUT_INT_ENA_M
@ -972,7 +984,6 @@ esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_b
.txfifo_empty_intr_thresh = UART_EMPTY_THRESH_DEFAULT
};
uart_intr_config(uart_num, &uart_intr);
ESP_INTR_ENABLE(uart_intr_num);
return ESP_OK;
}
@ -984,10 +995,9 @@ esp_err_t uart_driver_delete(uart_port_t uart_num)
ESP_LOGI(UART_TAG, "ALREADY NULL");
return ESP_OK;
}
ESP_INTR_DISABLE(p_uart_obj[uart_num]->intr_num);
esp_intr_free(p_uart_obj[uart_num]->intr_handle);
uart_disable_rx_intr(uart_num);
uart_disable_tx_intr(uart_num);
uart_isr_register(uart_num, p_uart_obj[uart_num]->intr_num, NULL, NULL);
if(p_uart_obj[uart_num]->tx_fifo_sem) {
vSemaphoreDelete(p_uart_obj[uart_num]->tx_fifo_sem);

View File

@ -6,31 +6,27 @@ COMPONENT_SRCDIRS := . hwcrypto
LIBS := core net80211 phy rtc pp wpa smartconfig coexist wps wpa2
LINKER_SCRIPTS += -T esp32_out.ld -T esp32.common.ld -T esp32.rom.ld -T esp32.peripherals.ld
LINKER_SCRIPTS += esp32.common.ld esp32.rom.ld esp32.peripherals.ld
ifeq ("$(CONFIG_NEWLIB_NANO_FORMAT)","y")
LINKER_SCRIPTS += -T esp32.rom.nanofmt.ld
LINKER_SCRIPTS += esp32.rom.nanofmt.ld
endif
COMPONENT_ADD_LDFLAGS := -lesp32 \
$(COMPONENT_PATH)/libhal.a \
-L$(COMPONENT_PATH)/lib \
$(addprefix -l,$(LIBS)) \
-L $(COMPONENT_PATH)/ld \
$(LINKER_SCRIPTS)
$(COMPONENT_PATH)/libhal.a \
-L$(COMPONENT_PATH)/lib \
$(addprefix -l,$(LIBS)) \
-L $(COMPONENT_PATH)/ld \
-T esp32_out.ld \
$(addprefix -T ,$(LINKER_SCRIPTS))
ALL_LIB_FILES := $(patsubst %,$(COMPONENT_PATH)/lib/lib%.a,$(LIBS))
COMPONENT_SUBMODULES += lib
# this is a hack to make sure the app is re-linked if the binary
# libraries change or are updated. If they change, the main esp32
# library will be rebuild by AR andthis will trigger a re-linking of
# the entire app.
#
# It would be better for components to be able to expose any of these
# non-standard dependencies via get_variable, but this will do for now.
$(COMPONENT_LIBRARY): $(ALL_LIB_FILES)
# final linking of project ELF depends on all binary libraries, and
# all linker scripts (except esp32_out.ld, as this is code generated here.)
COMPONENT_ADD_LINKER_DEPS := $(ALL_LIB_FILES) $(addprefix ld/,$(LINKER_SCRIPTS))
# Preprocess esp32.ld linker script into esp32_out.ld
#

View File

@ -173,12 +173,6 @@ void start_cpu0_default(void)
uart_div_modify(CONFIG_CONSOLE_UART_NUM, (APB_CLK_FREQ << 4) / CONFIG_CONSOLE_UART_BAUDRATE);
#if CONFIG_BROWNOUT_DET
esp_brownout_init();
#endif
#if CONFIG_INT_WDT
esp_int_wdt_init();
#endif
#if CONFIG_TASK_WDT
esp_task_wdt_init();
#endif
esp_setup_time_syscalls();
esp_vfs_dev_uart_register();
@ -194,6 +188,12 @@ void start_cpu0_default(void)
_GLOBAL_REENT->_stderr = (FILE*) &__sf_fake_stderr;
#endif
do_global_ctors();
#if CONFIG_INT_WDT
esp_int_wdt_init();
#endif
#if CONFIG_TASK_WDT
esp_task_wdt_init();
#endif
#if !CONFIG_FREERTOS_UNICORE
esp_crosscore_int_init();
#endif
@ -228,8 +228,11 @@ void start_cpu1_default(void)
while (port_xSchedulerRunning[0] == 0) {
;
}
//Take care putting stuff here: if asked, FreeRTOS will happily tell you the scheduler
//has started, but it isn't active *on this CPU* yet.
esp_crosscore_int_init();
ESP_LOGI(TAG, "Starting scheduler on APP CPU.");
ESP_EARLY_LOGI(TAG, "Starting scheduler on APP CPU.");
xPortStartScheduler();
}
#endif //!CONFIG_FREERTOS_UNICORE

View File

@ -17,6 +17,7 @@
#include "esp_attr.h"
#include "esp_err.h"
#include "esp_intr.h"
#include "esp_intr_alloc.h"
#include "rom/ets_sys.h"
#include "rom/uart.h"
@ -72,14 +73,11 @@ void esp_crosscore_int_init() {
portENTER_CRITICAL(&reasonSpinlock);
reason[xPortGetCoreID()]=0;
portEXIT_CRITICAL(&reasonSpinlock);
ESP_INTR_DISABLE(ETS_FROM_CPU_INUM);
if (xPortGetCoreID()==0) {
intr_matrix_set(xPortGetCoreID(), ETS_FROM_CPU_INTR0_SOURCE, ETS_FROM_CPU_INUM);
esp_intr_alloc(ETS_FROM_CPU_INTR0_SOURCE, ESP_INTR_FLAG_IRAM, esp_crosscore_isr, (void*)&reason[xPortGetCoreID()], NULL);
} else {
intr_matrix_set(xPortGetCoreID(), ETS_FROM_CPU_INTR1_SOURCE, ETS_FROM_CPU_INUM);
esp_intr_alloc(ETS_FROM_CPU_INTR1_SOURCE, ESP_INTR_FLAG_IRAM, esp_crosscore_isr, (void*)&reason[xPortGetCoreID()], NULL);
}
xt_set_interrupt_handler(ETS_FROM_CPU_INUM, esp_crosscore_isr, (void*)&reason[xPortGetCoreID()]);
ESP_INTR_ENABLE(ETS_FROM_CPU_INUM);
}
void esp_crosscore_int_send_yield(int coreId) {

View File

@ -47,9 +47,24 @@ typedef struct {
uint8_t subtype;
esp_partition_pos_t pos;
uint8_t label[16];
uint8_t reserved[4];
uint32_t flags;
} esp_partition_info_t;
#define PART_TYPE_APP 0x00
#define PART_SUBTYPE_FACTORY 0x00
#define PART_SUBTYPE_OTA_FLAG 0x10
#define PART_SUBTYPE_OTA_MASK 0x0f
#define PART_SUBTYPE_TEST 0x20
#define PART_TYPE_DATA 0x01
#define PART_SUBTYPE_DATA_OTA 0x00
#define PART_SUBTYPE_DATA_RF 0x01
#define PART_SUBTYPE_DATA_WIFI 0x02
#define PART_TYPE_END 0xff
#define PART_SUBTYPE_END 0xff
#define PART_FLAG_ENCRYPTED (1<<0)
#ifdef __cplusplus
}

View File

@ -14,18 +14,18 @@
#ifndef HEAP_ALLOC_CAPS_H
#define HEAP_ALLOC_CAPS_H
#define MALLOC_CAP_EXEC (1<<0) //Memory must be able to run executable code
#define MALLOC_CAP_32BIT (1<<1) //Memory must allow for aligned 32-bit data accesses
#define MALLOC_CAP_8BIT (1<<2) //Memory must allow for 8/16/...-bit data accesses
#define MALLOC_CAP_DMA (1<<3) //Memory must be able to accessed by DMA
#define MALLOC_CAP_PID2 (1<<4) //Memory must be mapped to PID2 memory space
#define MALLOC_CAP_PID3 (1<<5) //Memory must be mapped to PID3 memory space
#define MALLOC_CAP_PID4 (1<<6) //Memory must be mapped to PID4 memory space
#define MALLOC_CAP_PID5 (1<<7) //Memory must be mapped to PID5 memory space
#define MALLOC_CAP_PID6 (1<<8) //Memory must be mapped to PID6 memory space
#define MALLOC_CAP_PID7 (1<<9) //Memory must be mapped to PID7 memory space
#define MALLOC_CAP_SPISRAM (1<<10) //Memory must be in SPI SRAM
#define MALLOC_CAP_INVALID (1<<31) //Memory can't be used / list end marker
#define MALLOC_CAP_EXEC (1<<0) //Memory must be able to run executable code
#define MALLOC_CAP_32BIT (1<<1) //Memory must allow for aligned 32-bit data accesses
#define MALLOC_CAP_8BIT (1<<2) //Memory must allow for 8/16/...-bit data accesses
#define MALLOC_CAP_DMA (1<<3) //Memory must be able to accessed by DMA
#define MALLOC_CAP_PID2 (1<<4) //Memory must be mapped to PID2 memory space
#define MALLOC_CAP_PID3 (1<<5) //Memory must be mapped to PID3 memory space
#define MALLOC_CAP_PID4 (1<<6) //Memory must be mapped to PID4 memory space
#define MALLOC_CAP_PID5 (1<<7) //Memory must be mapped to PID5 memory space
#define MALLOC_CAP_PID6 (1<<8) //Memory must be mapped to PID6 memory space
#define MALLOC_CAP_PID7 (1<<9) //Memory must be mapped to PID7 memory space
#define MALLOC_CAP_SPISRAM (1<<10) //Memory must be in SPI SRAM
#define MALLOC_CAP_INVALID (1<<31) //Memory can't be used / list end marker
void heap_alloc_caps_init();

View File

@ -0,0 +1,267 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef __ESP_INTR_ALLOC_H__
#define __ESP_INTR_ALLOC_H__
#include <stdint.h>
#include <stdbool.h>
#include "esp_err.h"
#ifdef __cplusplus
extern "C" {
#endif
/** @addtogroup Intr_Alloc
* @{
*/
/** @brief Interrupt allocation flags
*
* These flags can be used to specify which interrupt qualities the
* code calling esp_intr_alloc* needs.
*
*/
//Keep the LEVELx values as they are here; they match up with (1<<level)
#define ESP_INTR_FLAG_LEVEL1 (1<<1) ///< Accept a Level 1 interrupt vector
#define ESP_INTR_FLAG_LEVEL2 (1<<2) ///< Accept a Level 2 interrupt vector
#define ESP_INTR_FLAG_LEVEL3 (1<<3) ///< Accept a Level 3 interrupt vector
#define ESP_INTR_FLAG_LEVEL4 (1<<4) ///< Accept a Level 4 interrupt vector
#define ESP_INTR_FLAG_LEVEL5 (1<<5) ///< Accept a Level 5 interrupt vector
#define ESP_INTR_FLAG_LEVEL6 (1<<6) ///< Accept a Level 6 interrupt vector
#define ESP_INTR_FLAG_NMI (1<<7) ///< Accept a Level 7 interrupt vector
#define ESP_INTR_FLAG_SHARED (1<<8) ///< Interrupt can be shared between ISRs
#define ESP_INTR_FLAG_EDGE (1<<9) ///< Edge-triggered interrupt
#define ESP_INTR_FLAG_IRAM (1<<10) ///< ISR can be called if cache is disabled
#define ESP_INTR_FLAG_INTRDISABLED (1<<11) ///< Return with this interrupt disabled
#define ESP_INTR_FLAG_LOWMED (ESP_INTR_FLAG_LEVEL1|ESP_INTR_FLAG_LEVEL2|ESP_INTR_FLAG_LEVEL3) ///< Low and medium prio interrupts. These can be handled in C.
#define ESP_INTR_FLAG_HIGH (ESP_INTR_FLAG_LEVEL4|ESP_INTR_FLAG_LEVEL5|ESP_INTR_FLAG_LEVEL6|ESP_INTR_FLAG_NMI) ///< High level interrupts. Need to be handled in assembly.
#define ESP_INTR_FLAG_LEVELMASK (ESP_INTR_FLAG_LEVEL1|ESP_INTR_FLAG_LEVEL2|ESP_INTR_FLAG_LEVEL3| \
ESP_INTR_FLAG_LEVEL4|ESP_INTR_FLAG_LEVEL5|ESP_INTR_FLAG_LEVEL6| \
ESP_INTR_FLAG_NMI) ///< Mask for all level flags
/**@}*/
/** @addtogroup Intr_Alloc_Pseudo_Src
* @{
*/
/**
* The esp_intr_alloc* functions can allocate an int for all ETS_*_INTR_SOURCE interrupt sources that
* are routed through the interrupt mux. Apart from these sources, each core also has some internal
* sources that do not pass through the interrupt mux. To allocate an interrupt for these sources,
* pass these pseudo-sources to the functions.
*/
#define ETS_INTERNAL_TIMER0_INTR_SOURCE -1 ///< Xtensa timer 0 interrupt source
#define ETS_INTERNAL_TIMER1_INTR_SOURCE -2 ///< Xtensa timer 1 interrupt source
#define ETS_INTERNAL_TIMER2_INTR_SOURCE -3 ///< Xtensa timer 2 interrupt source
#define ETS_INTERNAL_SW0_INTR_SOURCE -4 ///< Software int source 1
#define ETS_INTERNAL_SW1_INTR_SOURCE -5 ///< Software int source 2
#define ETS_INTERNAL_PROFILING_INTR_SOURCE -6 ///< Int source for profiling
/**@}*/
typedef void (*intr_handler_t)(void *arg);
typedef struct intr_handle_data_t intr_handle_data_t;
typedef intr_handle_data_t* intr_handle_t ;
/**
* @brief Mark an interrupt as a shared interrupt
*
* This will mark a certain interrupt on the specified CPU as
* an interrupt that can be used to hook shared interrupt handlers
* to.
*
* @param intno The number of the interrupt (0-31)
* @param cpu CPU on which the interrupt should be marked as shared (0 or 1)
* @param is_in_iram Shared interrupt is for handlers that reside in IRAM and
* the int can be left enabled while the flash cache is disabled.
*
* @return ESP_ERR_INVALID_ARG if cpu or intno is invalid
* ESP_OK otherwise
*/
esp_err_t esp_intr_mark_shared(int intno, int cpu, bool is_in_iram);
/**
* @brief Reserve an interrupt to be used outside of this framewoek
*
* This will mark a certain interrupt on the specified CPU as
* reserved, not to be allocated for any reason.
*
* @param intno The number of the interrupt (0-31)
* @param cpu CPU on which the interrupt should be marked as shared (0 or 1)
*
* @return ESP_ERR_INVALID_ARG if cpu or intno is invalid
* ESP_OK otherwise
*/
esp_err_t esp_intr_reserve(int intno, int cpu);
/**
* @brief Allocate an interrupt with the given parameters.
*
* This finds an interrupt that matches the restrictions as given in the flags
* parameter, maps the given interrupt source to it and hooks up the given
* interrupt handler (with optional argument) as well. If needed, it can return
* a handle for the interrupt as well.
*
* The interrupt will always be allocated on the core that runs this function.
*
* @param source The interrupt source. One of the ETS_*_INTR_SOURCE interrupt mux
* sources, as defined in soc/soc.h, or one of the internal
* ETS_INTERNAL_*_INTR_SOURCE sources as defined in this header.
* @param flags An ORred mask of the ESP_INTR_FLAG_* defines. These restrict the
* choice of interrupts that this routine can choose from. If this value
* is 0, it will default to allocating a non-shared interrupt of level
* 1, 2 or 3. If this is ESP_INTR_FLAG_SHARED, it will allocate a shared
* interrupt of level 1. Setting ESP_INTR_FLAG_INTRDISABLED will return
* from this function with the interrupt disabled.
* @param handler The interrupt handler. Must be NULL when an interrupt of level >3
* is requested, because these types of interrupts aren't C-callable.
* @param arg Optional argument for passed to the interrupt handler
* @param ret_handle Pointer to an intr_handle_t to store a handle that can later be
* used to request details or free the interrupt. Can be NULL if no handle
* is required.
*
* @return ESP_ERR_INVALID_ARG if the combination of arguments is invalid.
* ESP_ERR_NOT_FOUND No free interrupt found with the specified flags
* ESP_OK otherwise
*/
esp_err_t esp_intr_alloc(int source, int flags, intr_handler_t handler, void *arg, intr_handle_t *ret_handle);
/**
* @brief Allocate an interrupt with the given parameters.
*
*
* This essentially does the same as esp_intr_alloc, but allows specifying a register and mask
* combo. For shared interrupts, the handler is only called if a read from the specified
* register, ANDed with the mask, returns non-zero. By passing an interrupt status register
* address and a fitting mask, this can be used to accelerate interrupt handling in the case
* a shared interrupt is triggered; by checking the interrupt statuses first, the code can
* decide which ISRs can be skipped
*
* @param source The interrupt source. One of the ETS_*_INTR_SOURCE interrupt mux
* sources, as defined in soc/soc.h, or one of the internal
* ETS_INTERNAL_*_INTR_SOURCE sources as defined in this header.
* @param flags An ORred mask of the ESP_INTR_FLAG_* defines. These restrict the
* choice of interrupts that this routine can choose from. If this value
* is 0, it will default to allocating a non-shared interrupt of level
* 1, 2 or 3. If this is ESP_INTR_FLAG_SHARED, it will allocate a shared
* interrupt of level 1. Setting ESP_INTR_FLAG_INTRDISABLED will return
* from this function with the interrupt disabled.
* @param intrstatusreg The address of an interrupt status register
* @param intrstatusmask A mask. If a read of address intrstatusreg has any of the bits
* that are 1 in the mask set, the ISR will be called. If not, it will be
* skipped.
* @param handler The interrupt handler. Must be NULL when an interrupt of level >3
* is requested, because these types of interrupts aren't C-callable.
* @param arg Optional argument for passed to the interrupt handler
* @param ret_handle Pointer to an intr_handle_t to store a handle that can later be
* used to request details or free the interrupt. Can be NULL if no handle
* is required.
*
* @return ESP_ERR_INVALID_ARG if the combination of arguments is invalid.
* ESP_ERR_NOT_FOUND No free interrupt found with the specified flags
* ESP_OK otherwise
*/
esp_err_t esp_intr_alloc_intrstatus(int source, int flags, uint32_t intrstatusreg, uint32_t intrstatusmask, intr_handler_t handler, void *arg, intr_handle_t *ret_handle);
/**
* @brief Disable and free an interrupt.
*
* Use an interrupt handle to disable the interrupt and release the resources
* associated with it.
*
* @param handle The handle, as obtained by esp_intr_alloc or esp_intr_alloc_intrstatus
*
* @return ESP_ERR_INVALID_ARG if handle is invalid, or esp_intr_free runs on another core than
* where the interrupt is allocated on.
* ESP_OK otherwise
*/
esp_err_t esp_intr_free(intr_handle_t handle);
/**
* @brief Get CPU number an interrupt is tied to
*
* @param handle The handle, as obtained by esp_intr_alloc or esp_intr_alloc_intrstatus
*
* @return The core number where the interrupt is allocated
*/
int esp_intr_get_cpu(intr_handle_t handle);
/**
* @brief Get the allocated interrupt for a certain handle
*
* @param handle The handle, as obtained by esp_intr_alloc or esp_intr_alloc_intrstatus
*
* @return The interrupt number
*/
int esp_intr_get_intno(intr_handle_t handle);
/**
* @brief Disable the interrupt associated with the handle
*
* @note For local interrupts (ESP_INTERNAL_* sources), this function has to be called on the
* CPU the interrupt is allocated on. Other interrupts have no such restriction.
*
* @param handle The handle, as obtained by esp_intr_alloc or esp_intr_alloc_intrstatus
*
* @return ESP_ERR_INVALID_ARG if the combination of arguments is invalid.
* ESP_OK otherwise
*/
esp_err_t esp_intr_disable(intr_handle_t handle);
/**
* @brief Ensable the interrupt associated with the handle
*
* @note For local interrupts (ESP_INTERNAL_* sources), this function has to be called on the
* CPU the interrupt is allocated on. Other interrupts have no such restriction.
*
* @param handle The handle, as obtained by esp_intr_alloc or esp_intr_alloc_intrstatus
*
* @return ESP_ERR_INVALID_ARG if the combination of arguments is invalid.
* ESP_OK otherwise
*/
esp_err_t esp_intr_enable(intr_handle_t handle);
/**
* @brief Disable interrupts that aren't specifically marked as running from IRAM
*/
void esp_intr_noniram_disable();
/**
* @brief Re-enable interrupts disabled by esp_intr_noniram_disable
*/
void esp_intr_noniram_enable();
/**@}*/
#ifdef __cplusplus
}
#endif
#endif

View File

@ -490,16 +490,20 @@ SpiFlashOpResult SPI_Prepare_Encrypt_Data(uint32_t flash_addr, uint32_t *data);
void SPI_Write_Encrypt_Disable(void);
/**
* @brief Encrpto writing data to flash, you should Erase it yourself if need.
* Please do not call this function in SDK.
* @brief Write data to flash with transparent encryption.
* @note Sectors to be written should already be erased.
*
* @param uint32_t flash_addr : Address to write, should be 32 bytes aligned.
* @note Please do not call this function in SDK.
*
* @param uint32_t *data : The pointer to data which is to write.
* @param uint32_t flash_addr : Address to write, should be 32 byte aligned.
*
* @param uint32_t *data : The pointer to data to write. Note, this pointer must
* be 32 bit aligned and the content of the data will be
* modified by the encryption function.
*
* @param uint32_t len : Length to write, should be 32 bytes aligned.
*
* @return SPI_FLASH_RESULT_OK : Encrypto write OK.
* @return SPI_FLASH_RESULT_OK : Data written successfully.
* SPI_FLASH_RESULT_ERR : Encrypto write error.
* SPI_FLASH_RESULT_TIMEOUT : Encrypto write timeout.
*/

View File

@ -79,8 +79,8 @@
//set bits of register controlled by mask
#define REG_SET_BITS(_r, _b, _m) (*(volatile uint32_t*)(_r) = (*(volatile uint32_t*)(_r) & ~(_m)) | ((_b) & (_m)))
//get field from register, used when _f is not left shifted by _f##_S
#define REG_GET_FIELD(_r, _f) ((REG_READ(_r) >> (_f##_S)) & (_f))
//get field from register, uses field _S & _V to determine mask
#define REG_GET_FIELD(_r, _f) ((REG_READ(_r) >> (_f##_S)) & (_f##_V))
//set field to register, used when _f is not left shifted by _f##_S
#define REG_SET_FIELD(_r, _f, _v) (REG_WRITE((_r),((REG_READ(_r) & ~((_f) << (_f##_S)))|(((_v) & (_f))<<(_f##_S)))))
@ -264,14 +264,14 @@
* Intr num Level Type PRO CPU usage APP CPU uasge
* 0 1 extern level WMAC Reserved
* 1 1 extern level BT/BLE Host VHCI Reserved
* 2 1 extern level FROM_CPU FROM_CPU
* 3 1 extern level TG0_WDT Reserved
* 2 1 extern level
* 3 1 extern level
* 4 1 extern level WBB
* 5 1 extern level BT Controller
* 6 1 timer FreeRTOS Tick(L1) FreeRTOS Tick(L1)
* 7 1 software Reserved Reserved
* 8 1 extern level BLE Controller
* 9 1 extern level EMAC
* 9 1 extern level
* 10 1 extern edge Internal Timer
* 11 3 profiling
* 12 1 extern level
@ -300,10 +300,7 @@
//CPU0 Interrupt number reserved, not touch this.
#define ETS_WMAC_INUM 0
#define ETS_BT_HOST_INUM 1
#define ETS_FROM_CPU_INUM 2
#define ETS_T0_WDT_INUM 3
#define ETS_WBB_INUM 4
#define ETS_EMAC_INUM 9
#define ETS_TG0_T1_INUM 10 /**< use edge interrupt*/
#define ETS_FRC1_INUM 22
#define ETS_T1_WDT_INUM 24

View File

@ -14,5 +14,7 @@
#pragma once
#include "soc.h"
/* Hardware random number generator register */
#define WDEV_RND_REG 0x60035144

View File

@ -0,0 +1,739 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "sdkconfig.h"
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include <esp_types.h>
#include "esp_err.h"
#include "esp_log.h"
#include "esp_intr.h"
#include "esp_attr.h"
#include "esp_intr_alloc.h"
#include <limits.h>
#include <assert.h>
static const char* TAG = "intr_alloc";
#define ETS_INTERNAL_TIMER0_INTR_NO 6
#define ETS_INTERNAL_TIMER1_INTR_NO 15
#define ETS_INTERNAL_TIMER2_INTR_NO 16
#define ETS_INTERNAL_SW0_INTR_NO 7
#define ETS_INTERNAL_SW1_INTR_NO 29
#define ETS_INTERNAL_PROFILING_INTR_NO 11
/*
Define this to debug the choices made when allocating the interrupt. This leads to much debugging
output within a critical region, which can lead to weird effects like e.g. the interrupt watchdog
being triggered, that is why it is separate from the normal LOG* scheme.
*/
//define DEBUG_INT_ALLOC_DECISIONS
#ifdef DEBUG_INT_ALLOC_DECISIONS
# define ALCHLOG(...) ESP_EARLY_LOGD(TAG, __VA_ARGS__)
#else
# define ALCHLOG(...) do {} while (0)
#endif
typedef enum {
INTDESC_NORMAL=0,
INTDESC_RESVD,
INTDESC_SPECIAL //for xtensa timers / software ints
} int_desc_flag_t;
typedef enum {
INTTP_LEVEL=0,
INTTP_EDGE,
INTTP_NA
} int_type_t;
typedef struct {
int level;
int_type_t type;
int_desc_flag_t cpuflags[2];
} int_desc_t;
//We should mark the interrupt for the timer used by FreeRTOS as reserved. The specific timer
//is selectable using menuconfig; we use these cpp bits to convert that into something we can use in
//the table below.
#if CONFIG_FREERTOS_CORETIMER_0
#define INT6RES INTDESC_RESVD
#else
#define INT6RES INTDESC_SPECIAL
#endif
#if CONFIG_FREERTOS_CORETIMER_1
#define INT15RES INTDESC_RESVD
#else
#define INT15RES INTDESC_SPECIAL
#endif
#if CONFIG_FREERTOS_CORETIMER_2
#define INT16RES INTDESC_RESVD
#else
#define INT16RES INTDESC_SPECIAL
#endif
//This is basically a software-readable version of the interrupt usage table in include/soc/soc.h
const static int_desc_t int_desc[32]={
{ 1, INTTP_LEVEL, {INTDESC_RESVD, INTDESC_RESVD } }, //0
{ 1, INTTP_LEVEL, {INTDESC_RESVD, INTDESC_RESVD } }, //1
{ 1, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //2
{ 1, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //3
{ 1, INTTP_LEVEL, {INTDESC_RESVD, INTDESC_NORMAL} }, //4
{ 1, INTTP_LEVEL, {INTDESC_RESVD, INTDESC_NORMAL} }, //5
{ 1, INTTP_NA, {INT6RES, INT6RES } }, //6
{ 1, INTTP_NA, {INTDESC_SPECIAL,INTDESC_SPECIAL}}, //7
{ 1, INTTP_LEVEL, {INTDESC_RESVD, INTDESC_RESVD } }, //8
{ 1, INTTP_LEVEL, {INTDESC_RESVD, INTDESC_RESVD } }, //9 //FRC1
{ 1, INTTP_EDGE , {INTDESC_RESVD, INTDESC_RESVD } }, //10 //FRC2
{ 3, INTTP_NA, {INTDESC_SPECIAL,INTDESC_SPECIAL}}, //11
{ 1, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //12
{ 1, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //13
{ 7, INTTP_LEVEL, {INTDESC_RESVD, INTDESC_RESVD } }, //14, NMI
{ 3, INTTP_NA, {INT15RES, INT15RES } }, //15
{ 5, INTTP_NA, {INT16RES, INT16RES } }, //16
{ 1, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //17
{ 1, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //18
{ 2, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //19
{ 2, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //20
{ 2, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //21
{ 3, INTTP_EDGE, {INTDESC_RESVD, INTDESC_NORMAL} }, //22
{ 3, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //23
{ 4, INTTP_LEVEL, {INTDESC_RESVD, INTDESC_NORMAL} }, //24
{ 4, INTTP_LEVEL, {INTDESC_RESVD, INTDESC_RESVD } }, //25
{ 5, INTTP_LEVEL, {INTDESC_RESVD, INTDESC_RESVD } }, //26
{ 3, INTTP_LEVEL, {INTDESC_RESVD, INTDESC_RESVD } }, //27
{ 4, INTTP_EDGE, {INTDESC_NORMAL, INTDESC_NORMAL} }, //28
{ 3, INTTP_NA, {INTDESC_SPECIAL,INTDESC_SPECIAL}}, //29
{ 4, INTTP_EDGE, {INTDESC_RESVD, INTDESC_RESVD } }, //30
{ 5, INTTP_LEVEL, {INTDESC_RESVD, INTDESC_RESVD } }, //31
};
typedef struct shared_vector_desc_t shared_vector_desc_t;
typedef struct vector_desc_t vector_desc_t;
struct shared_vector_desc_t {
int disabled: 1;
int source: 8;
volatile uint32_t *statusreg;
uint32_t statusmask;
intr_handler_t isr;
void *arg;
shared_vector_desc_t *next;
};
#define VECDESC_FL_RESERVED (1<<0)
#define VECDESC_FL_INIRAM (1<<1)
#define VECDESC_FL_SHARED (1<<2)
#define VECDESC_FL_NONSHARED (1<<3)
//Pack using bitfields for better memory use
struct vector_desc_t {
int flags: 16; //OR of VECDESC_FLAG_* defines
unsigned int cpu: 1;
unsigned int intno: 5;
int source: 8; //Interrupt mux flags, used when not shared
shared_vector_desc_t *shared_vec_info; //used when VECDESC_FL_SHARED
vector_desc_t *next;
};
struct intr_handle_data_t {
vector_desc_t *vector_desc;
shared_vector_desc_t *shared_vector_desc;
};
//Linked list of vector descriptions, sorted by cpu.intno value
static vector_desc_t *vector_desc_head;
//This bitmask has an 1 if the int should be disabled when the flash is disabled.
static uint32_t non_iram_int_mask[portNUM_PROCESSORS];
//This bitmask has 1 in it if the int was disabled using esp_intr_noniram_disable.
static uint32_t non_iram_int_disabled[portNUM_PROCESSORS];
static bool non_iram_int_disabled_flag[portNUM_PROCESSORS];
static portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED;
//Inserts an item into vector_desc list so that the list is sorted
//with an incrementing cpu.intno value.
static void insert_vector_desc(vector_desc_t *to_insert)
{
vector_desc_t *vd=vector_desc_head;
vector_desc_t *prev=NULL;
while(vd!=NULL) {
if (vd->cpu > to_insert->cpu) break;
if (vd->cpu == to_insert->cpu && vd->intno >= to_insert->intno) break;
prev=vd;
vd=vd->next;
}
if (vd==NULL && prev==NULL) {
//First item
vector_desc_head=to_insert;
vector_desc_head->next=NULL;
} else {
prev->next=to_insert;
to_insert->next=vd;
}
}
//Returns a vector_desc entry for an intno/cpu, or NULL if none exists.
static vector_desc_t *find_desc_for_int(int intno, int cpu)
{
vector_desc_t *vd=vector_desc_head;
while(vd!=NULL) {
if (vd->cpu==cpu && vd->intno==intno) break;
vd=vd->next;
}
return vd;
}
//Returns a vector_desc entry for an intno/cpu.
//Either returns a preexisting one or allocates a new one and inserts
//it into the list. Returns NULL on malloc fail.
static vector_desc_t *get_desc_for_int(int intno, int cpu)
{
vector_desc_t *vd=find_desc_for_int(intno, cpu);
if (vd==NULL) {
vector_desc_t *newvd=malloc(sizeof(vector_desc_t));
if (newvd==NULL) return NULL;
memset(newvd, 0, sizeof(vector_desc_t));
newvd->intno=intno;
newvd->cpu=cpu;
insert_vector_desc(newvd);
return newvd;
} else {
return vd;
}
}
esp_err_t esp_intr_mark_shared(int intno, int cpu, bool is_int_ram)
{
if (intno>31) return ESP_ERR_INVALID_ARG;
if (cpu>=portNUM_PROCESSORS) return ESP_ERR_INVALID_ARG;
portENTER_CRITICAL(&spinlock);
vector_desc_t *vd=get_desc_for_int(intno, cpu);
if (vd==NULL) {
portEXIT_CRITICAL(&spinlock);
return ESP_ERR_NO_MEM;
}
vd->flags=VECDESC_FL_SHARED;
if (is_int_ram) vd->flags|=VECDESC_FL_INIRAM;
portEXIT_CRITICAL(&spinlock);
return ESP_OK;
}
esp_err_t esp_intr_reserve(int intno, int cpu)
{
if (intno>31) return ESP_ERR_INVALID_ARG;
if (cpu>=portNUM_PROCESSORS) return ESP_ERR_INVALID_ARG;
portENTER_CRITICAL(&spinlock);
vector_desc_t *vd=get_desc_for_int(intno, cpu);
if (vd==NULL) {
portEXIT_CRITICAL(&spinlock);
return ESP_ERR_NO_MEM;
}
vd->flags=VECDESC_FL_RESERVED;
portEXIT_CRITICAL(&spinlock);
return ESP_OK;
}
//Interrupt handler table and unhandled uinterrupt routine. Duplicated
//from xtensa_intr.c... it's supposed to be private, but we need to look
//into it in order to see if someone allocated an int using
//xt_set_interrupt_handler.
typedef struct xt_handler_table_entry {
void * handler;
void * arg;
} xt_handler_table_entry;
extern xt_handler_table_entry _xt_interrupt_table[XCHAL_NUM_INTERRUPTS*portNUM_PROCESSORS];
extern void xt_unhandled_interrupt(void * arg);
//Returns true if handler for interrupt is not the default unhandled interrupt handler
static bool int_has_handler(int intr, int cpu)
{
return (_xt_interrupt_table[intr*portNUM_PROCESSORS+cpu].handler != xt_unhandled_interrupt);
}
//Locate a free interrupt compatible with the flags given.
//The 'force' argument can be -1, or 0-31 to force checking a certain interrupt.
//When a CPU is forced, the INTDESC_SPECIAL marked interrupts are also accepted.
static int get_free_int(int flags, int cpu, int force)
{
int x;
int best=-1;
int bestLevel=9;
int bestSharedCt=INT_MAX;
//Default vector desc, for vectors not in the linked list
vector_desc_t empty_vect_desc;
memset(&empty_vect_desc, 0, sizeof(vector_desc_t));
//Level defaults to any low/med interrupt
if (!(flags&ESP_INTR_FLAG_LEVELMASK)) flags|=ESP_INTR_FLAG_LOWMED;
ALCHLOG(TAG, "get_free_int: start looking. Current cpu: %d", cpu);
//Iterate over the 32 possible interrupts
for (x=0; x<32; x++) {
//Grab the vector_desc for this vector.
vector_desc_t *vd=find_desc_for_int(x, cpu);
if (vd==NULL) vd=&empty_vect_desc;
//See if we have a forced interrupt; if so, bail out if this is not it.
if (force!=-1 && force!=x) {
ALCHLOG(TAG, "Ignoring int %d: forced to %d", x, force);
continue;
}
ALCHLOG(TAG, "Int %d reserved %d level %d %s hasIsr %d",
x, int_desc[x].cpuflags[cpu]==INTDESC_RESVD, int_desc[x].level,
int_desc[x].type==INTTP_LEVEL?"LEVEL":"EDGE", int_has_handler(x, cpu));
//Check if interrupt is not reserved by design
if (int_desc[x].cpuflags[cpu]==INTDESC_RESVD) {
ALCHLOG(TAG, "....Unusable: reserved");
continue;
}
if (int_desc[x].cpuflags[cpu]==INTDESC_SPECIAL && force==-1) {
ALCHLOG(TAG, "....Unusable: special-purpose int");
continue;
}
//Check if the interrupt level is acceptable
if (!(flags&(1<<int_desc[x].level))) {
ALCHLOG(TAG, "....Unusable: incompatible level");
continue;
}
//check if edge/level type matches what we want
if (((flags&ESP_INTR_FLAG_EDGE) && (int_desc[x].type==INTTP_LEVEL)) ||
(((!(flags&ESP_INTR_FLAG_EDGE)) && (int_desc[x].type==INTTP_EDGE)))) {
ALCHLOG(TAG, "....Unusable: incompatible trigger type");
continue;
}
//Check if interrupt already is allocated by xt_set_interrupt_handler
if (int_has_handler(x, cpu) && !(vd->flags&VECDESC_FL_SHARED)) {
ALCHLOG(TAG, "....Unusable: already allocated");
continue;
}
//Ints can't be both shared and non-shared.
assert(!((vd->flags&VECDESC_FL_SHARED)&&(vd->flags&VECDESC_FL_NONSHARED)));
//check if interrupt is reserved at runtime
if (vd->flags&VECDESC_FL_RESERVED) {
ALCHLOG(TAG, "....Unusable: reserved at runtime.");
continue;
}
//check if interrupt already is in use by a non-shared interrupt
if (vd->flags&VECDESC_FL_NONSHARED) {
ALCHLOG(TAG, "....Unusable: already in (non-shared) use.");
continue;
}
if (flags&ESP_INTR_FLAG_SHARED) {
//We're allocating a shared int.
bool in_iram_flag=((flags&ESP_INTR_FLAG_IRAM)!=0);
bool desc_in_iram_flag=((vd->flags&VECDESC_FL_INIRAM)!=0);
//Bail out if int is shared, but iram property doesn't match what we want.
if ((vd->flags&VECDESC_FL_SHARED) && (desc_in_iram_flag!=in_iram_flag)) {
ALCHLOG(TAG, "....Unusable: shared but iram prop doesn't match");
continue;
}
//See if int already is used as a shared interrupt.
if (vd->flags&VECDESC_FL_SHARED) {
//We can use this already-marked-as-shared interrupt. Count the already attached isrs in order to see
//how useful it is.
int no=0;
shared_vector_desc_t *svdesc=vd->shared_vec_info;
while (svdesc!=NULL) {
no++;
svdesc=svdesc->next;
}
if (no<bestSharedCt || bestLevel>int_desc[x].level) {
//Seems like this shared vector is both okay and has the least amount of ISRs already attached to it.
best=x;
bestSharedCt=no;
bestLevel=int_desc[x].level;
ALCHLOG(TAG, "...int %d more usable as a shared int: has %d existing vectors", x, no);
} else {
ALCHLOG(TAG, "...worse than int %d", best);
}
} else {
if (best==-1) {
//We haven't found a feasible shared interrupt yet. This one is still free and usable, even if
//not marked as shared.
//Remember it in case we don't find any other shared interrupt that qualifies.
if (bestLevel>int_desc[x].level) {
best=x;
bestLevel=int_desc[x].level;
ALCHLOG(TAG, "...int %d usable as a new shared int", x);
}
} else {
ALCHLOG(TAG, "...already have a shared int");
}
}
} else {
//We need an unshared IRQ; can't use shared ones; bail out if this is shared.
if (vd->flags&VECDESC_FL_SHARED) {
ALCHLOG(TAG, "...Unusable: int is shared, we need non-shared.");
continue;
}
//Seems this interrupt is feasible. Select it and break out of the loop; no need to search further.
if (bestLevel>int_desc[x].level) {
best=x;
bestLevel=int_desc[x].level;
} else {
ALCHLOG(TAG, "...worse than int %d", best);
}
}
}
ALCHLOG(TAG, "get_free_int: using int %d", best);
//Okay, by now we have looked at all potential interrupts and hopefully have selected the best one in best.
return best;
}
//Common shared isr handler. Chain-call all ISRs.
static void IRAM_ATTR shared_intr_isr(void *arg)
{
vector_desc_t *vd=(vector_desc_t*)arg;
shared_vector_desc_t *sh_vec=vd->shared_vec_info;
portENTER_CRITICAL(&spinlock);
while(sh_vec) {
if (!sh_vec->disabled) {
if ((sh_vec->statusreg == NULL) || (*sh_vec->statusreg & sh_vec->statusmask)) {
sh_vec->isr(sh_vec->arg);
}
}
sh_vec=sh_vec->next;
}
portEXIT_CRITICAL(&spinlock);
}
//We use ESP_EARLY_LOG* here because this can be called before the scheduler is running.
esp_err_t esp_intr_alloc_intrstatus(int source, int flags, uint32_t intrstatusreg, uint32_t intrstatusmask, intr_handler_t handler,
void *arg, intr_handle_t *ret_handle)
{
intr_handle_data_t *ret=NULL;
int force=-1;
ESP_EARLY_LOGV(TAG, "esp_intr_alloc_intrstatus (cpu %d): checking args", xPortGetCoreID());
//Shared interrupts should be level-triggered.
if ((flags&ESP_INTR_FLAG_SHARED) && (flags&ESP_INTR_FLAG_EDGE)) return ESP_ERR_INVALID_ARG;
//You can't set an handler / arg for a non-C-callable interrupt.
if ((flags&ESP_INTR_FLAG_HIGH) && (handler)) return ESP_ERR_INVALID_ARG;
//Shared ints should have handler and non-processor-local source
if ((flags&ESP_INTR_FLAG_SHARED) && (!handler || source<0)) return ESP_ERR_INVALID_ARG;
//Statusreg should have a mask
if (intrstatusreg && !intrstatusmask) return ESP_ERR_INVALID_ARG;
//Default to prio 1 for shared interrupts. Default to prio 1, 2 or 3 for non-shared interrupts.
if ((flags&ESP_INTR_FLAG_LEVELMASK)==0) {
if (flags&ESP_INTR_FLAG_SHARED) {
flags|=ESP_INTR_FLAG_LEVEL1;
} else {
flags|=ESP_INTR_FLAG_LOWMED;
}
}
ESP_EARLY_LOGV(TAG, "esp_intr_alloc_intrstatus (cpu %d): Args okay. Resulting flags 0x%X", xPortGetCoreID(), flags);
//Check 'special' interrupt sources. These are tied to one specific interrupt, so we
//have to force get_free_int to only look at that.
if (source==ETS_INTERNAL_TIMER0_INTR_SOURCE) force=ETS_INTERNAL_TIMER0_INTR_NO;
if (source==ETS_INTERNAL_TIMER1_INTR_SOURCE) force=ETS_INTERNAL_TIMER1_INTR_NO;
if (source==ETS_INTERNAL_TIMER2_INTR_SOURCE) force=ETS_INTERNAL_TIMER2_INTR_NO;
if (source==ETS_INTERNAL_SW0_INTR_SOURCE) force=ETS_INTERNAL_SW0_INTR_NO;
if (source==ETS_INTERNAL_SW1_INTR_SOURCE) force=ETS_INTERNAL_SW1_INTR_NO;
if (source==ETS_INTERNAL_PROFILING_INTR_SOURCE) force=ETS_INTERNAL_PROFILING_INTR_NO;
//Allocate a return handle. If we end up not needing it, we'll free it later on.
ret=malloc(sizeof(intr_handle_data_t));
if (ret==NULL) return ESP_ERR_NO_MEM;
portENTER_CRITICAL(&spinlock);
int cpu=xPortGetCoreID();
//See if we can find an interrupt that matches the flags.
int intr=get_free_int(flags, cpu, force);
if (intr==-1) {
//None found. Bail out.
portEXIT_CRITICAL(&spinlock);
free(ret);
return ESP_ERR_NOT_FOUND;
}
//Get an int vector desc for int.
vector_desc_t *vd=get_desc_for_int(intr, cpu);
if (vd==NULL) {
portEXIT_CRITICAL(&spinlock);
free(ret);
return ESP_ERR_NO_MEM;
}
//Allocate that int!
if (flags&ESP_INTR_FLAG_SHARED) {
//Populate vector entry and add to linked list.
shared_vector_desc_t *sh_vec=malloc(sizeof(shared_vector_desc_t));
if (sh_vec==NULL) {
portEXIT_CRITICAL(&spinlock);
free(ret);
return ESP_ERR_NO_MEM;
}
memset(sh_vec, 0, sizeof(shared_vector_desc_t));
sh_vec->statusreg=(uint32_t*)intrstatusreg;
sh_vec->statusmask=intrstatusmask;
sh_vec->isr=handler;
sh_vec->arg=arg;
sh_vec->next=vd->shared_vec_info;
sh_vec->source=source;
sh_vec->disabled=0;
vd->shared_vec_info=sh_vec;
vd->flags|=VECDESC_FL_SHARED;
//(Re-)set shared isr handler to new value.
xt_set_interrupt_handler(intr, shared_intr_isr, vd);
} else {
//Mark as unusable for other interrupt sources. This is ours now!
vd->flags=VECDESC_FL_NONSHARED;
if (handler) {
xt_set_interrupt_handler(intr, handler, arg);
}
if (flags&ESP_INTR_FLAG_EDGE) xthal_set_intclear(1 << intr);
vd->source=source;
}
if (flags&ESP_INTR_FLAG_IRAM) {
vd->flags|=VECDESC_FL_INIRAM;
non_iram_int_mask[cpu]&=~(1<<intr);
} else {
vd->flags&=~VECDESC_FL_INIRAM;
non_iram_int_mask[cpu]|=(1<<intr);
}
if (source>=0) {
intr_matrix_set(cpu, source, intr);
}
//Fill return handle data.
ret->vector_desc=vd;
ret->shared_vector_desc=vd->shared_vec_info;
//Enable int at CPU-level;
ESP_INTR_ENABLE(intr);
//If interrupt has to be started disabled, do that now; ints won't be enabled for real until the end
//of the critical section.
if (flags&ESP_INTR_FLAG_INTRDISABLED) {
esp_intr_disable(ret);
}
portEXIT_CRITICAL(&spinlock);
//Fill return handle if needed, otherwise free handle.
if (ret_handle!=NULL) {
*ret_handle=ret;
} else {
free(ret);
}
ESP_EARLY_LOGD(TAG, "Connected src %d to int %d (cpu %d)", source, intr, cpu);
return ESP_OK;
}
esp_err_t esp_intr_alloc(int source, int flags, intr_handler_t handler, void *arg, intr_handle_t *ret_handle)
{
/*
As an optimization, we can create a table with the possible interrupt status registers and masks for every single
source there is. We can then add code here to look up an applicable value and pass that to the
esp_intr_alloc_intrstatus function.
*/
return esp_intr_alloc_intrstatus(source, flags, 0, 0, handler, arg, ret_handle);
}
esp_err_t esp_intr_free(intr_handle_t handle)
{
bool free_shared_vector=false;
if (!handle) return ESP_ERR_INVALID_ARG;
//This routine should be called from the interrupt the task is scheduled on.
if (handle->vector_desc->cpu!=xPortGetCoreID()) return ESP_ERR_INVALID_ARG;
portENTER_CRITICAL(&spinlock);
esp_intr_disable(handle);
if (handle->vector_desc->flags&VECDESC_FL_SHARED) {
//Find and kill the shared int
shared_vector_desc_t *svd=handle->vector_desc->shared_vec_info;
shared_vector_desc_t *prevsvd=NULL;
assert(svd); //should be something in there for a shared int
while (svd!=NULL) {
if (svd==handle->shared_vector_desc) {
//Found it. Now kill it.
if (prevsvd) {
prevsvd->next=svd->next;
} else {
handle->vector_desc->shared_vec_info=svd->next;
}
free(svd);
break;
}
prevsvd=svd;
svd=svd->next;
}
//If nothing left, disable interrupt.
if (handle->vector_desc->shared_vec_info==NULL) free_shared_vector=true;
ESP_LOGV(TAG, "esp_intr_free: Deleting shared int: %s. Shared int is %s", svd?"not found or last one":"deleted", free_shared_vector?"empty now.":"still in use");
}
if ((handle->vector_desc->flags&VECDESC_FL_NONSHARED) || free_shared_vector) {
ESP_LOGV(TAG, "esp_intr_free: Disabling int, killing handler");
//Reset to normal handler
xt_set_interrupt_handler(handle->vector_desc->intno, xt_unhandled_interrupt, (void*)((int)handle->vector_desc->intno));
//Theoretically, we could free the vector_desc... not sure if that's worth the few bytes of memory
//we save.(We can also not use the same exit path for empty shared ints anymore if we delete
//the desc.) For now, just mark it as free.
handle->vector_desc->flags&=!(VECDESC_FL_NONSHARED|VECDESC_FL_RESERVED);
//Also kill non_iram mask bit.
non_iram_int_mask[handle->vector_desc->cpu]&=~(1<<(handle->vector_desc->intno));
}
portEXIT_CRITICAL(&spinlock);
free(handle);
return ESP_OK;
}
int esp_intr_get_intno(intr_handle_t handle)
{
return handle->vector_desc->intno;
}
int esp_intr_get_cpu(intr_handle_t handle)
{
return handle->vector_desc->cpu;
}
/*
Interrupt disabling strategy:
If the source is >=0 (meaning a muxed interrupt), we disable it by muxing the interrupt to a non-connected
interrupt. If the source is <0 (meaning an internal, per-cpu interrupt), we disable it using ESP_INTR_DISABLE.
This allows us to, for the muxed CPUs, disable an int from the other core. It also allows disabling shared
interrupts.
*/
//Muxing an interrupt source to interrupt 6, 7, 11, 15, 16 or 29 cause the interrupt to effectively be disabled.
#define INT_MUX_DISABLED_INTNO 6
esp_err_t esp_intr_enable(intr_handle_t handle)
{
if (!handle) return ESP_ERR_INVALID_ARG;
portENTER_CRITICAL(&spinlock);
int source;
if (handle->shared_vector_desc) {
handle->shared_vector_desc->disabled=0;
source=handle->shared_vector_desc->source;
} else {
source=handle->vector_desc->source;
}
if (source >= 0) {
//Disabled using int matrix; re-connect to enable
intr_matrix_set(handle->vector_desc->cpu, source, handle->vector_desc->intno);
} else {
//Re-enable using cpu int ena reg
if (handle->vector_desc->cpu!=xPortGetCoreID()) return ESP_ERR_INVALID_ARG; //Can only enable these ints on this cpu
ESP_INTR_ENABLE(handle->vector_desc->intno);
}
portEXIT_CRITICAL(&spinlock);
return ESP_OK;
}
esp_err_t esp_intr_disable(intr_handle_t handle)
{
if (!handle) return ESP_ERR_INVALID_ARG;
portENTER_CRITICAL(&spinlock);
int source;
if (handle->shared_vector_desc) {
handle->shared_vector_desc->disabled=1;
source=handle->shared_vector_desc->source;
} else {
source=handle->vector_desc->source;
}
if (source >= 0) {
//Disable using int matrix
intr_matrix_set(handle->vector_desc->cpu, source, INT_MUX_DISABLED_INTNO);
} else {
//Disable using per-cpu regs
if (handle->vector_desc->cpu!=xPortGetCoreID()) {
portEXIT_CRITICAL(&spinlock);
return ESP_ERR_INVALID_ARG; //Can only enable these ints on this cpu
}
ESP_INTR_DISABLE(handle->vector_desc->intno);
}
portEXIT_CRITICAL(&spinlock);
return ESP_OK;
}
void esp_intr_noniram_disable()
{
int oldint;
int cpu=xPortGetCoreID();
int intmask=~non_iram_int_mask[cpu];
assert(non_iram_int_disabled_flag[cpu]==false);
non_iram_int_disabled_flag[cpu]=true;
asm volatile (
"movi %0,0\n"
"xsr %0,INTENABLE\n" //disable all ints first
"rsync\n"
"and a3,%0,%1\n" //mask ints that need disabling
"wsr a3,INTENABLE\n" //write back
"rsync\n"
:"=r"(oldint):"r"(intmask):"a3");
//Save which ints we did disable
non_iram_int_disabled[cpu]=oldint&non_iram_int_mask[cpu];
}
void esp_intr_noniram_enable()
{
int cpu=xPortGetCoreID();
int intmask=non_iram_int_disabled[cpu];
assert(non_iram_int_disabled_flag[cpu]==true);
non_iram_int_disabled_flag[cpu]=false;
asm volatile (
"movi a3,0\n"
"xsr a3,INTENABLE\n"
"rsync\n"
"or a3,a3,%0\n"
"wsr a3,INTENABLE\n"
"rsync\n"
::"r"(intmask):"a3");
}
//These functions are provided in ROM, but the ROM-based functions use non-multicore-capable
//virtualized interrupt levels. Thus, we disable them in the ld file and provide working
//equivalents here.
void IRAM_ATTR ets_isr_unmask(unsigned int mask) {
xt_ints_on(mask);
}
void IRAM_ATTR ets_isr_mask(unsigned int mask) {
xt_ints_off(mask);
}

View File

@ -169,12 +169,6 @@ PROVIDE ( ets_get_xtal_scale = 0x4000856c );
PROVIDE ( ets_install_putc1 = 0x40007d18 );
PROVIDE ( ets_install_putc2 = 0x40007d38 );
PROVIDE ( ets_install_uart_printf = 0x40007d28 );
PROVIDE ( ets_intr_count = 0x3ffe03fc );
PROVIDE ( ets_intr_lock = 0x400067b0 );
PROVIDE ( ets_intr_unlock = 0x400067c4 );
PROVIDE ( ets_isr_attach = 0x400067ec );
PROVIDE ( ets_isr_mask = 0x400067fc );
PROVIDE ( ets_isr_unmask = 0x40006808 );
PROVIDE ( ets_post = 0x4000673c );
PROVIDE ( ets_printf = 0x40007d54 );
PROVIDE ( ets_readySet_ = 0x3ffe01f0 );
@ -1730,6 +1724,13 @@ PROVIDE ( Xthal_intlevel = 0x3ff9c2b4 );
PROVIDE ( xthal_memcpy = 0x4000c0bc );
PROVIDE ( xthal_set_ccompare = 0x4000c058 );
PROVIDE ( xthal_set_intclear = 0x4000c1ec );
PROVIDE ( _xtos_set_intlevel = 0x4000bfdc );
/*
These functions are xtos-related (or call xtos-related functions) and do not play well
with multicore FreeRTOS. Where needed, we provide alternatives that are multicore
compatible.
*/
/*
PROVIDE ( _xtos_alloca_handler = 0x40000010 );
PROVIDE ( _xtos_cause3_handler = 0x40000dd8 );
PROVIDE ( _xtos_c_handler_table = 0x3ffe0548 );
@ -1748,13 +1749,19 @@ PROVIDE ( _xtos_return_from_exc = 0x4000c034 );
PROVIDE ( _xtos_set_exception_handler = 0x4000074c );
PROVIDE ( _xtos_set_interrupt_handler = 0x4000bf78 );
PROVIDE ( _xtos_set_interrupt_handler_arg = 0x4000bf34 );
PROVIDE ( _xtos_set_intlevel = 0x4000bfdc );
PROVIDE ( _xtos_set_min_intlevel = 0x4000bff8 );
PROVIDE ( _xtos_set_vpri = 0x40000934 );
PROVIDE ( _xtos_syscall_handler = 0x40000790 );
PROVIDE ( _xtos_unhandled_exception = 0x4000c024 );
PROVIDE ( _xtos_unhandled_interrupt = 0x4000c01c );
PROVIDE ( _xtos_vpri_enabled = 0x3ffe0654 );
PROVIDE ( ets_intr_count = 0x3ffe03fc );
PROVIDE ( ets_intr_lock = 0x400067b0 );
PROVIDE ( ets_intr_unlock = 0x400067c4 );
PROVIDE ( ets_isr_attach = 0x400067ec );
PROVIDE ( ets_isr_mask = 0x400067fc );
PROVIDE ( ets_isr_unmask = 0x40006808 );
*/
/* Following are static data, but can be used, not generated by script <<<<< btdm data */
PROVIDE ( ld_acl_env = 0x3ffb8258 );
PROVIDE ( ld_active_ch_map = 0x3ffb8334 );

View File

@ -27,6 +27,7 @@
#include <esp_types.h>
#include "esp_err.h"
#include "esp_intr.h"
#include "esp_intr_alloc.h"
#include "esp_attr.h"
#include "esp_freertos_hooks.h"
#include "soc/timer_group_struct.h"
@ -51,7 +52,7 @@ static wdt_task_t *wdt_task_list=NULL;
static portMUX_TYPE taskwdt_spinlock = portMUX_INITIALIZER_UNLOCKED;
static void IRAM_ATTR task_wdt_isr(void *arg) {
static void task_wdt_isr(void *arg) {
wdt_task_t *wdttask;
const char *cpu;
//Feed the watchdog so we do not reset
@ -71,21 +72,21 @@ static void IRAM_ATTR task_wdt_isr(void *arg) {
return;
}
//Watchdog got triggered because at least one task did not report in.
ets_printf(DRAM_STR("Task watchdog got triggered. The following tasks did not feed the watchdog in time:\n"));
ets_printf("Task watchdog got triggered. The following tasks did not feed the watchdog in time:\n");
for (wdttask=wdt_task_list; wdttask!=NULL; wdttask=wdttask->next) {
if (!wdttask->fed_watchdog) {
cpu=xTaskGetAffinity(wdttask->task_handle)==0?DRAM_STR("CPU 0"):DRAM_STR("CPU 1");
if (xTaskGetAffinity(wdttask->task_handle)==tskNO_AFFINITY) cpu=DRAM_STR("CPU 0/1");
ets_printf(DRAM_STR(" - %s (%s)\n"), pcTaskGetTaskName(wdttask->task_handle), cpu);
ets_printf(" - %s (%s)\n", pcTaskGetTaskName(wdttask->task_handle), cpu);
}
}
ets_printf(DRAM_STR("Tasks currently running:\n"));
for (int x=0; x<portNUM_PROCESSORS; x++) {
ets_printf(DRAM_STR("CPU %d: %s\n"), x, pcTaskGetTaskName(xTaskGetCurrentTaskHandleForCPU(x)));
ets_printf("CPU %d: %s\n", x, pcTaskGetTaskName(xTaskGetCurrentTaskHandleForCPU(x)));
}
#if CONFIG_TASK_WDT_PANIC
ets_printf(DRAM_STR("Aborting.\n"));
ets_printf("Aborting.\n");
abort();
#endif
portEXIT_CRITICAL(&taskwdt_spinlock);
@ -201,12 +202,7 @@ void esp_task_wdt_init() {
#if CONFIG_TASK_WDT_CHECK_IDLE_TASK
esp_register_freertos_idle_hook(idle_hook);
#endif
ESP_INTR_DISABLE(ETS_T0_WDT_INUM);
intr_matrix_set(xPortGetCoreID(), ETS_TG0_WDT_LEVEL_INTR_SOURCE, ETS_T0_WDT_INUM);
xt_set_interrupt_handler(ETS_T0_WDT_INUM, task_wdt_isr, NULL);
TIMERG0.int_clr_timers.wdt=1;
timer_group_intr_enable(TIMER_GROUP_0, TIMG_WDT_INT_ENA_M);
ESP_INTR_ENABLE(ETS_T0_WDT_INUM);
esp_intr_alloc(ETS_TG0_WDT_LEVEL_INTR_SOURCE, 0, task_wdt_isr, NULL, NULL);
}

View File

@ -0,0 +1,203 @@
/*
Tests for the interrupt allocator.
*/
#include <esp_types.h>
#include <stdio.h>
#include "rom/ets_sys.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "freertos/queue.h"
#include "freertos/xtensa_api.h"
#include "unity.h"
#include "soc/uart_reg.h"
#include "soc/dport_reg.h"
#include "soc/io_mux_reg.h"
#include "esp_intr_alloc.h"
#include "driver/timer.h"
#define TIMER_DIVIDER 16 /*!< Hardware timer clock divider */
#define TIMER_SCALE (TIMER_BASE_CLK / TIMER_DIVIDER) /*!< used to calculate counter value */
#define TIMER_INTERVAL0_SEC (3.4179) /*!< test interval for timer 0 */
#define TIMER_INTERVAL1_SEC (5.78) /*!< test interval for timer 1 */
static void my_timer_init(int timer_group, int timer_idx, int ival)
{
timer_config_t config;
config.alarm_en = 1;
config.auto_reload = 1;
config.counter_dir = TIMER_COUNT_UP;
config.divider = TIMER_DIVIDER;
config.intr_type = TIMER_INTR_LEVEL;
config.counter_en = TIMER_PAUSE;
/*Configure timer*/
timer_init(timer_group, timer_idx, &config);
/*Stop timer counter*/
timer_pause(timer_group, timer_idx);
/*Load counter value */
timer_set_counter_value(timer_group, timer_idx, 0x00000000ULL);
/*Set alarm value*/
timer_set_alarm_value(timer_group, timer_idx, ival);
/*Enable timer interrupt*/
timer_enable_intr(timer_group, timer_idx);
}
static volatile int count[4]={0,0,0,0};
static void timer_isr(void *arg)
{
int timer_idx = (int)arg;
count[timer_idx]++;
if (timer_idx==0) {
TIMERG0.int_clr_timers.t0 = 1;
TIMERG0.hw_timer[0].update=1;
TIMERG0.hw_timer[0].config.alarm_en = 1;
}
if (timer_idx==1) {
TIMERG0.int_clr_timers.t1 = 1;
TIMERG0.hw_timer[1].update=1;
TIMERG0.hw_timer[1].config.alarm_en = 1;
}
if (timer_idx==2) {
TIMERG1.int_clr_timers.t0 = 1;
TIMERG1.hw_timer[0].update=1;
TIMERG1.hw_timer[0].config.alarm_en = 1;
}
if (timer_idx==3) {
TIMERG1.int_clr_timers.t1 = 1;
TIMERG1.hw_timer[1].update=1;
TIMERG1.hw_timer[1].config.alarm_en = 1;
}
// ets_printf("int %d\n", timer_idx);
}
static void timer_test(int flags) {
int x;
timer_isr_handle_t inth[4];
my_timer_init(TIMER_GROUP_0, TIMER_0, 110000);
my_timer_init(TIMER_GROUP_0, TIMER_1, 120000);
my_timer_init(TIMER_GROUP_1, TIMER_0, 130000);
my_timer_init(TIMER_GROUP_1, TIMER_1, 140000);
timer_isr_register(TIMER_GROUP_0, TIMER_0, timer_isr, (void*)0, flags|ESP_INTR_FLAG_INTRDISABLED, &inth[0]);
timer_isr_register(TIMER_GROUP_0, TIMER_1, timer_isr, (void*)1, flags, &inth[1]);
timer_isr_register(TIMER_GROUP_1, TIMER_0, timer_isr, (void*)2, flags, &inth[2]);
timer_isr_register(TIMER_GROUP_1, TIMER_1, timer_isr, (void*)3, flags, &inth[3]);
timer_start(TIMER_GROUP_0, TIMER_0);
timer_start(TIMER_GROUP_0, TIMER_1);
timer_start(TIMER_GROUP_1, TIMER_0);
timer_start(TIMER_GROUP_1, TIMER_1);
for (x=0; x<4; x++) count[x]=0;
printf("Interrupts allocated: %d (dis) %d %d %d\n",
esp_intr_get_intno(inth[0]), esp_intr_get_intno(inth[1]),
esp_intr_get_intno(inth[2]), esp_intr_get_intno(inth[3]));
printf("Timer values on start: %d %d %d %d\n", count[0], count[1], count[2], count[3]);
vTaskDelay(1000 / portTICK_RATE_MS);
printf("Timer values after 1 sec: %d %d %d %d\n", count[0], count[1], count[2], count[3]);
TEST_ASSERT(count[0]==0);
TEST_ASSERT(count[1]!=0);
TEST_ASSERT(count[2]!=0);
TEST_ASSERT(count[3]!=0);
printf("Disabling timers 1 and 2...\n");
esp_intr_enable(inth[0]);
esp_intr_disable(inth[1]);
esp_intr_disable(inth[2]);
for (x=0; x<4; x++) count[x]=0;
vTaskDelay(1000 / portTICK_RATE_MS);
printf("Timer values after 1 sec: %d %d %d %d\n", count[0], count[1], count[2], count[3]);
TEST_ASSERT(count[0]!=0);
TEST_ASSERT(count[1]==0);
TEST_ASSERT(count[2]==0);
TEST_ASSERT(count[3]!=0);
printf("Disabling other half...\n");
esp_intr_enable(inth[1]);
esp_intr_enable(inth[2]);
esp_intr_disable(inth[0]);
esp_intr_disable(inth[3]);
for (x=0; x<4; x++) count[x]=0;
vTaskDelay(1000 / portTICK_RATE_MS);
printf("Timer values after 1 sec: %d %d %d %d\n", count[0], count[1], count[2], count[3]);
TEST_ASSERT(count[0]==0);
TEST_ASSERT(count[1]!=0);
TEST_ASSERT(count[2]!=0);
TEST_ASSERT(count[3]==0);
printf("Done.\n");
esp_intr_free(inth[0]);
esp_intr_free(inth[1]);
esp_intr_free(inth[2]);
esp_intr_free(inth[3]);
}
static volatile int int_timer_ctr;
void int_timer_handler(void *arg) {
xthal_set_ccompare(1, xthal_get_ccount()+8000000);
int_timer_ctr++;
}
void local_timer_test()
{
intr_handle_t ih;
esp_err_t r;
r=esp_intr_alloc(ETS_INTERNAL_TIMER1_INTR_SOURCE, 0, int_timer_handler, NULL, &ih);
TEST_ASSERT(r==ESP_OK);
printf("Int timer 1 intno %d\n", esp_intr_get_intno(ih));
xthal_set_ccompare(1, xthal_get_ccount()+8000000);
int_timer_ctr=0;
vTaskDelay(1000 / portTICK_RATE_MS);
printf("Timer val after 1 sec: %d\n", int_timer_ctr);
TEST_ASSERT(int_timer_ctr!=0);
printf("Disabling int\n");
esp_intr_disable(ih);
int_timer_ctr=0;
vTaskDelay(1000 / portTICK_RATE_MS);
printf("Timer val after 1 sec: %d\n", int_timer_ctr);
TEST_ASSERT(int_timer_ctr==0);
printf("Re-enabling\n");
esp_intr_enable(ih);
vTaskDelay(1000 / portTICK_RATE_MS);
printf("Timer val after 1 sec: %d\n", int_timer_ctr);
TEST_ASSERT(int_timer_ctr!=0);
printf("Free int, re-alloc disabled\n");
r=esp_intr_free(ih);
TEST_ASSERT(r==ESP_OK);
r=esp_intr_alloc(ETS_INTERNAL_TIMER1_INTR_SOURCE, ESP_INTR_FLAG_INTRDISABLED, int_timer_handler, NULL, &ih);
TEST_ASSERT(r==ESP_OK);
int_timer_ctr=0;
vTaskDelay(1000 / portTICK_RATE_MS);
printf("Timer val after 1 sec: %d\n", int_timer_ctr);
TEST_ASSERT(int_timer_ctr==0);
printf("Re-enabling\n");
esp_intr_enable(ih);
vTaskDelay(1000 / portTICK_RATE_MS);
printf("Timer val after 1 sec: %d\n", int_timer_ctr);
TEST_ASSERT(int_timer_ctr!=0);
r=esp_intr_free(ih);
TEST_ASSERT(r==ESP_OK);
printf("Done.\n");
}
TEST_CASE("Intr_alloc test, CPU-local int source", "[esp32]")
{
local_timer_test();
}
TEST_CASE("Intr_alloc test, private ints", "[esp32]")
{
timer_test(0);
}
TEST_CASE("Intr_alloc test, shared ints", "[esp32]")
{
timer_test(ESP_INTR_FLAG_SHARED);
}

View File

@ -28,13 +28,13 @@ ESPTOOLPY_WRITE_FLASH=$(ESPTOOLPY_SERIAL) write_flash $(if $(CONFIG_ESPTOOLPY_CO
ESPTOOL_ALL_FLASH_ARGS += $(CONFIG_APP_OFFSET) $(APP_BIN)
ifdef CONFIG_SECURE_BOOTLOADER_ENABLED
ifdef CONFIG_SECURE_BOOT_ENABLED
ifndef IS_BOOTLOADER_BUILD
# for secure boot, add a signing step to get from unsiged app to signed app
APP_BIN_UNSIGNED := $(APP_BIN:.bin=-unsigned.bin)
$(APP_BIN): $(APP_BIN_UNSIGNED)
$(ESPSECUREPY) sign_data --keyfile $(SECURE_BOOT_SIGNING_KEY) -o $@ $^ # signed in-place
$(APP_BIN): $(APP_BIN_UNSIGNED) $(SECURE_BOOT_SIGNING_KEY)
$(ESPSECUREPY) sign_data --keyfile $(SECURE_BOOT_SIGNING_KEY) -o $@ $<
endif
endif
# non-secure boot (or bootloader), both these files are the same
@ -45,7 +45,7 @@ $(APP_BIN_UNSIGNED): $(APP_ELF) $(ESPTOOLPY_SRC)
flash: all_binaries $(ESPTOOLPY_SRC)
@echo "Flashing binaries to serial port $(ESPPORT) (app at offset $(CONFIG_APP_OFFSET))..."
ifdef CONFIG_SECURE_BOOTLOADER_ENABLED
ifdef CONFIG_SECURE_BOOT_ENABLED
@echo "(Secure boot enabled, so bootloader not flashed automatically. See 'make bootloader' output)"
endif
$(ESPTOOLPY_WRITE_FLASH) $(ESPTOOL_ALL_FLASH_ARGS)

@ -1 +1 @@
Subproject commit 5c6962e894e0a118c9a4b5760876433493449260
Subproject commit adc914b91ac6d2cfd1ace56307b4374eb9439e14

View File

@ -35,6 +35,7 @@
#include "esp_err.h"
#include "esp_log.h"
#include "esp_eth.h"
#include "esp_intr_alloc.h"
#include "emac_common.h"
#include "emac_desc.h"
@ -305,19 +306,16 @@ static void IRAM_ATTR emac_process_intr(void *arg)
}
}
//ToDo: this should only be called once because this allocates the interrupt as well.
static void emac_enable_intr()
{
//init emac intr
REG_SET_FIELD(DPORT_PRO_EMAC_INT_MAP_REG, DPORT_PRO_EMAC_INT_MAP, ETS_EMAC_INUM);
xt_set_interrupt_handler(ETS_EMAC_INUM, emac_process_intr, NULL);
xt_ints_on(1 << ETS_EMAC_INUM);
esp_intr_alloc(ETS_ETH_MAC_INTR_SOURCE, 0, emac_process_intr, NULL, NULL);
REG_WRITE(EMAC_DMAINTERRUPT_EN_REG, EMAC_INTR_ENABLE_BIT);
}
static void emac_disable_intr()
{
xt_ints_off(1 << ETS_EMAC_INUM);
REG_WRITE(EMAC_DMAINTERRUPT_EN_REG, 0);
}

View File

@ -16,7 +16,7 @@
static void tskdelcb(int no, void *arg)
{
printf("Delete callback: %d = %p!\n", no, arg);
ets_printf("Delete callback: %d = %p!\n", no, arg);
}

View File

@ -39,7 +39,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#if XCHAL_HAVE_EXCEPTIONS
/* Handler table is in xtensa_intr_asm.S */
// Todo: Make multicore - JD
extern xt_exc_handler _xt_exception_table[XCHAL_EXCCAUSE_NUM*portNUM_PROCESSORS];

View File

@ -40,6 +40,9 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-------------------------------------------------------------------------------
*/
#if XT_USE_SWPRI
/* Warning - this is not multicore-compatible. */
.data
.global _xt_intdata
.align 8
@ -53,7 +56,7 @@ _xt_intdata:
_xt_intenable: .word 0 /* Virtual INTENABLE */
_xt_vpri_mask: .word 0xFFFFFFFF /* Virtual priority mask */
#endif
/*
-------------------------------------------------------------------------------
@ -124,7 +127,8 @@ _xt_exception_table:
unsigned int xt_ints_on ( unsigned int mask )
Enables a set of interrupts. Does not simply set INTENABLE directly, but
computes it as a function of the current virtual priority.
computes it as a function of the current virtual priority if XT_USE_SWPRI is
enabled.
Can be called from interrupt handlers.
-------------------------------------------------------------------------------
*/
@ -137,7 +141,9 @@ _xt_exception_table:
xt_ints_on:
ENTRY0
#if XCHAL_HAVE_INTERRUPTS
#if XT_USE_SWPRI
movi a3, 0
movi a4, _xt_intdata
xsr a3, INTENABLE /* Disables all interrupts */
@ -149,6 +155,15 @@ xt_ints_on:
and a5, a5, a6 /* a5 = _xt_intenable & _xt_vpri_mask */
wsr a5, INTENABLE /* Reenable interrupts */
mov a2, a3 /* Previous mask */
#else
movi a3, 0
xsr a3, INTENABLE /* Disables all interrupts */
rsync
or a2, a3, a2 /* set bits in mask */
wsr a2, INTENABLE /* Re-enable ints */
rsync
mov a2, a3 /* return prev mask */
#endif
#else
movi a2, 0 /* Return zero */
#endif
@ -162,7 +177,8 @@ xt_ints_on:
unsigned int xt_ints_off ( unsigned int mask )
Disables a set of interrupts. Does not simply set INTENABLE directly,
but computes it as a function of the current virtual priority.
but computes it as a function of the current virtual priority if XT_USE_SWPRI is
enabled.
Can be called from interrupt handlers.
-------------------------------------------------------------------------------
*/
@ -176,6 +192,7 @@ xt_ints_off:
ENTRY0
#if XCHAL_HAVE_INTERRUPTS
#if XT_USE_SWPRI
movi a3, 0
movi a4, _xt_intdata
xsr a3, INTENABLE /* Disables all interrupts */
@ -188,6 +205,16 @@ xt_ints_off:
and a5, a5, a6 /* a5 = _xt_intenable & _xt_vpri_mask */
wsr a5, INTENABLE /* Reenable interrupts */
mov a2, a3 /* Previous mask */
#else
movi a4, 0
xsr a4, INTENABLE /* Disables all interrupts */
rsync
or a3, a4, a2 /* set bits in mask */
xor a3, a3, a2 /* invert bits in mask set in mask, essentially clearing them */
wsr a3, INTENABLE /* Re-enable ints */
rsync
mov a2, a4 /* return prev mask */
#endif
#else
movi a2, 0 /* return zero */
#endif

View File

@ -2,4 +2,6 @@ Config: {execute count: 1, execute order: in order}
DUT: [SSC1]
Filter:
- Add:
ID: [SYS_MISC_0101, SYS_MISC_0201]
ID:
- SYS_MISC_0101 # test reboot function
- SYS_MISC_0201 # get heap size test

View File

@ -2,9 +2,34 @@ Config: {execute count: 1, execute order: in order}
DUT: [SSC2, SSC1]
Filter:
- Add:
ID: [^TCPIP_DHCP_0302, TCPIP_DHCP_0302, TCPIP_DHCP_0301, TCPIP_TCP_0403, TCPIP_TCP_0402,
TCPIP_TCP_0401, TCPIP_TCP_0407, TCPIP_TCP_0406, ^TCPIP_TCP_0411, TCPIP_TCP_0404,
TCPIP_TCP_0408, TCPIP_TCP_0110, ^TCPIP_TCP_0111, TCPIP_TCP_0115, TCPIP_IP_0101,
TCPIP_IP_0102, ^TCPIP_IGMP_0102, ^TCPIP_IGMP_0101, ^TCPIP_IGMP_0104, TCPIP_IGMP_0104,
TCPIP_IGMP_0103, TCPIP_IGMP_0102, TCPIP_IGMP_0101, TCPIP_UDP_0108, TCPIP_UDP_0106,
TCPIP_UDP_0107, TCPIP_UDP_0105, TCPIP_UDP_0101, TCPIP_IGMP_0204, TCPIP_IGMP_0201]
ID:
- TCPIP_DHCP_0101 # dhcp client function test
- TCPIP_DHCP_0103 # dhcp status query
- TCPIP_DHCP_0201 # server dhcp lease test
- TCPIP_DHCP_0202 # dhcp server ip pool
- TCPIP_DHCP_0203 # dhcp server ip pool empty
- TCPIP_DHCP_0204 # dhcp server timeout test
- TCPIP_DHCP_0205 # disconnect STA if config dhcp server
- TCPIP_DHCP_0206 # dhcp server assign same IP to same MAC when it's not released
- TCPIP_DHCP_0207 # dhcp server prefer assign released IP to new client
- TCPIP_DHCP_0208 # dhcp server reconfig and new client able to get first IP in pool
- TCPIP_DHCP_0209 # dhcp server reconfig, old client and new client able to get IP
- TCPIP_DHCP_0210 # dhcp server reconfig, old client able to get IP (discover with requested IP)
- TCPIP_DHCP_0211 # dhcp server reconfig, old client able to renew IP (direct send request)
- TCPIP_DHCP_0212 # dhcp server function test
- TCPIP_DHCP_0301 # sta dhcp static ip interaction
- TCPIP_DHCP_0302 # ap dhcp static ip interaction
- TCPIP_IGMP_0101 # station IGMP join group address check
- TCPIP_IGMP_0102 # station IGMP leave group address check
- TCPIP_IGMP_0103 # softAP IGMP join group address check
- TCPIP_IGMP_0104 # softAP IGMP leave group address check
- TCPIP_IGMP_0201 # station IGMP recv packets
- TCPIP_IGMP_0202 # station send multicast packets
- TCPIP_IGMP_0203 # softAP IGMP recv packets
- TCPIP_IGMP_0204 # softAP send multicast packets
- TCPIP_IP_0101 # sta set and query static ip test
- TCPIP_IP_0102 # ap set and query static ip test
- TCPIP_TCP_0101 # STA mode, connect test. use different ip, port
- TCPIP_TCP_0102 # STA mode, server listen test. use different kinds of port
- TCPIP_TCP_0103 # STA mode, send/recv basic test
- TCPIP_TCP_0104 # STA mode, shutdown basic test

View File

@ -1,10 +1,35 @@
Config: {execute count: 1, execute order: in order}
DUT: [SSC2, SSC1]
DUT: [SSC1]
Filter:
- Add:
ID: [TCPIP_IGMP_0202, TCPIP_IGMP_0203, ^TCPIP_TCP_0403, ^TCPIP_TCP_0408, TCPIP_UDP_0201,
^TCPIP_DHCP_0301, ^TCPIP_TCP_0101, ^TCPIP_TCP_0103, ^TCPIP_TCP_0105, ^TCPIP_TCP_0104,
^TCPIP_TCP_0107, ^TCPIP_TCP_0106, ^TCPIP_DHCP_0210, ^TCPIP_DHCP_0211, ^TCPIP_DHCP_0212,
^TCPIP_TCP_0404, TCPIP_TCP_0212, TCPIP_TCP_0210, ^TCPIP_TCP_0406, ^TCPIP_TCP_0407,
^TCPIP_TCP_0401, ^TCPIP_TCP_0210, ^TCPIP_TCP_0212, TCPIP_DHCP_0211, TCPIP_DHCP_0210,
TCPIP_DHCP_0212, TCPIP_DHCP_0101, TCPIP_DHCP_0103, TCPIP_DHCP_0206, TCPIP_DHCP_0207]
ID:
- TCPIP_TCP_0105 # STA mode, close for different types of TCP sockets test
- TCPIP_TCP_0106 # STA mode, create max TCP sockets test
- TCPIP_TCP_0107 # STA mode, accept max TCP client by server test
- TCPIP_TCP_0110 # AP mode, connect test. use different ip, port
- TCPIP_TCP_0111 # AP mode, server listen test. use different kinds of port
- TCPIP_TCP_0112 # AP mode, send/recv basic test
- TCPIP_TCP_0113 # AP mode, shutdown basic test
- TCPIP_TCP_0114 # AP mode, close for different types of TCP sockets test
- TCPIP_TCP_0115 # AP mode, create max TCP sockets test
- TCPIP_TCP_0116 # AP mode, accept max TCP client by server test
- TCPIP_TCP_0201 # STA mode, connect test. use socket in state that can't connect
- TCPIP_TCP_0202 # STA mode, server listen test. use socket in state that can't listen
- TCPIP_TCP_0203 # send test. use socket in state that can't send
- TCPIP_TCP_0204 # STA mode, recv buffer test
- TCPIP_TCP_0206 # STA mode, get active socket info test
- TCPIP_TCP_0207 # AP mode, connect test. use socket in state that can't connect
- TCPIP_TCP_0208 # AP mode, server listen test. use socket in state that can't listen
- TCPIP_TCP_0210 # AP mode, recv buffer test
- TCPIP_TCP_0212 # AP mode, get active socket info test
- TCPIP_TCP_0401 # do TCP send after WIFI disconnected
- TCPIP_TCP_0402 # close TCP socket after WIFI disconnected
- TCPIP_TCP_0403 # do TCP send after mode changed
- TCPIP_TCP_0404 # close TCP socket after mode changed
- TCPIP_TCP_0406 # close TCP socket after PC NIC disabled
- TCPIP_TCP_0407 # do TCP send after IP changed
- TCPIP_TCP_0408 # close TCP socket after IP changed
- TCPIP_TCP_0411 # do TCP send after socket changed
- TCPIP_TCP_0412 # close TCP send after socket changed
- TCPIP_UDP_0101 # STA mode, udp bind test. use different ip, port
- TCPIP_UDP_0105 # STA mode, close UDP sockets test

View File

@ -2,9 +2,34 @@ Config: {execute count: 1, execute order: in order}
DUT: [SSC2, SSC1]
Filter:
- Add:
ID: [^TCPIP_IP_0102, ^TCPIP_UDP_0105, ^TCPIP_UDP_0107, ^TCPIP_UDP_0106, ^TCPIP_UDP_0101,
TCPIP_TCP_0202, ^TCPIP_UDP_0108, ^TCPIP_IGMP_0201, ^TCPIP_IGMP_0203, ^TCPIP_IGMP_0202,
^TCPIP_IGMP_0103, TCPIP_UDP_0114, TCPIP_UDP_0113, TCPIP_UDP_0112, TCPIP_UDP_0202,
TCPIP_DHCP_0205, TCPIP_DHCP_0202, TCPIP_DHCP_0203, ^TCPIP_TCP_0102, TCPIP_TCP_0106,
TCPIP_TCP_0107, TCPIP_TCP_0104, TCPIP_TCP_0105, TCPIP_TCP_0102, TCPIP_TCP_0103,
TCPIP_TCP_0101, ^TCPIP_TCP_0116, ^TCPIP_TCP_0114, ^TCPIP_TCP_0115, ^TCPIP_TCP_0112]
ID:
- TCPIP_UDP_0106 # STA mode, create max udp socket test
- TCPIP_UDP_0107 # STA mode, get active socket info test
- TCPIP_UDP_0108 # AP mode, udp bind test. use different ip, port
- TCPIP_UDP_0112 # AP mode, close UDP sockets test
- TCPIP_UDP_0113 # AP mode, create max udp socket test
- TCPIP_UDP_0114 # AP mode, get active socket info test
- TCPIP_UDP_0201 # STA mode, recv buffer test
- TCPIP_UDP_0202 # AP mode, recv buffer test
- ^TCPIP_DHCP_0101 # dhcp client function test
- ^TCPIP_DHCP_0103 # dhcp status query
- ^TCPIP_DHCP_0201 # server dhcp lease test
- ^TCPIP_DHCP_0202 # dhcp server ip pool
- ^TCPIP_DHCP_0203 # dhcp server ip pool empty
- ^TCPIP_DHCP_0204 # dhcp server timeout test
- ^TCPIP_DHCP_0205 # disconnect STA if config dhcp server
- ^TCPIP_DHCP_0206 # dhcp server assign same IP to same MAC when it's not released
- ^TCPIP_DHCP_0207 # dhcp server prefer assign released IP to new client
- ^TCPIP_DHCP_0208 # dhcp server reconfig and new client able to get first IP in pool
- ^TCPIP_DHCP_0209 # dhcp server reconfig, old client and new client able to get IP
- ^TCPIP_DHCP_0210 # dhcp server reconfig, old client able to get IP (discover with requested IP)
- ^TCPIP_DHCP_0211 # dhcp server reconfig, old client able to renew IP (direct send request)
- ^TCPIP_DHCP_0212 # dhcp server function test
- ^TCPIP_DHCP_0301 # sta dhcp static ip interaction
- ^TCPIP_DHCP_0302 # ap dhcp static ip interaction
- ^TCPIP_IGMP_0101 # station IGMP join group address check
- ^TCPIP_IGMP_0102 # station IGMP leave group address check
- ^TCPIP_IGMP_0103 # softAP IGMP join group address check
- ^TCPIP_IGMP_0104 # softAP IGMP leave group address check
- ^TCPIP_IGMP_0201 # station IGMP recv packets
- ^TCPIP_IGMP_0202 # station send multicast packets

View File

@ -2,9 +2,34 @@ Config: {execute count: 1, execute order: in order}
DUT: [SSC2, SSC1]
Filter:
- Add:
ID: [^TCPIP_TCP_0113, ^TCPIP_TCP_0110, TCPIP_DHCP_0209, ^TCPIP_DHCP_0209, ^TCPIP_DHCP_0207,
^TCPIP_DHCP_0206, ^TCPIP_DHCP_0205, ^TCPIP_DHCP_0204, ^TCPIP_DHCP_0203, ^TCPIP_DHCP_0202,
^TCPIP_DHCP_0201, TCPIP_TCP_0204, TCPIP_TCP_0207, TCPIP_TCP_0206, TCPIP_TCP_0201,
^TCPIP_DHCP_0101, TCPIP_TCP_0203, ^TCPIP_DHCP_0103, ^TCPIP_DHCP_0208, TCPIP_TCP_0208,
^TCPIP_TCP_0202, ^TCPIP_TCP_0203, TCPIP_DHCP_0204, ^TCPIP_TCP_0201, ^TCPIP_TCP_0206,
^TCPIP_TCP_0207, ^TCPIP_TCP_0204, TCPIP_DHCP_0201, ^TCPIP_TCP_0208, TCPIP_DHCP_0208]
ID:
- ^TCPIP_IGMP_0203 # softAP IGMP recv packets
- ^TCPIP_IGMP_0204 # softAP send multicast packets
- ^TCPIP_IP_0101 # sta set and query static ip test
- ^TCPIP_IP_0102 # ap set and query static ip test
- ^TCPIP_TCP_0101 # STA mode, connect test. use different ip, port
- ^TCPIP_TCP_0102 # STA mode, server listen test. use different kinds of port
- ^TCPIP_TCP_0103 # STA mode, send/recv basic test
- ^TCPIP_TCP_0104 # STA mode, shutdown basic test
- ^TCPIP_TCP_0105 # STA mode, close for different types of TCP sockets test
- ^TCPIP_TCP_0106 # STA mode, create max TCP sockets test
- ^TCPIP_TCP_0107 # STA mode, accept max TCP client by server test
- ^TCPIP_TCP_0110 # AP mode, connect test. use different ip, port
- ^TCPIP_TCP_0111 # AP mode, server listen test. use different kinds of port
- ^TCPIP_TCP_0112 # AP mode, send/recv basic test
- ^TCPIP_TCP_0113 # AP mode, shutdown basic test
- ^TCPIP_TCP_0114 # AP mode, close for different types of TCP sockets test
- ^TCPIP_TCP_0115 # AP mode, create max TCP sockets test
- ^TCPIP_TCP_0116 # AP mode, accept max TCP client by server test
- ^TCPIP_TCP_0201 # STA mode, connect test. use socket in state that can't connect
- ^TCPIP_TCP_0202 # STA mode, server listen test. use socket in state that can't listen
- ^TCPIP_TCP_0203 # send test. use socket in state that can't send
- ^TCPIP_TCP_0204 # STA mode, recv buffer test
- ^TCPIP_TCP_0206 # STA mode, get active socket info test
- ^TCPIP_TCP_0207 # AP mode, connect test. use socket in state that can't connect
- ^TCPIP_TCP_0208 # AP mode, server listen test. use socket in state that can't listen
- ^TCPIP_TCP_0210 # AP mode, recv buffer test
- ^TCPIP_TCP_0212 # AP mode, get active socket info test
- ^TCPIP_TCP_0401 # do TCP send after WIFI disconnected
- ^TCPIP_TCP_0402 # close TCP socket after WIFI disconnected
- ^TCPIP_TCP_0403 # do TCP send after mode changed

View File

@ -1,8 +1,21 @@
Config: {execute count: 1, execute order: in order}
DUT: [SSC2, SSC1]
DUT: [SSC1]
Filter:
- Add:
ID: [^TCPIP_IGMP_0204, ^TCPIP_TCP_0412, TCPIP_TCP_0411, TCPIP_TCP_0412, ^TCPIP_UDP_0112,
^TCPIP_UDP_0113, ^TCPIP_UDP_0114, ^TCPIP_UDP_0202, ^TCPIP_UDP_0201, ^TCPIP_IP_0101,
^TCPIP_TCP_0402, TCPIP_TCP_0114, TCPIP_TCP_0116, TCPIP_TCP_0111, TCPIP_TCP_0113,
TCPIP_TCP_0112]
ID:
- ^TCPIP_TCP_0404 # close TCP socket after mode changed
- ^TCPIP_TCP_0406 # close TCP socket after PC NIC disabled
- ^TCPIP_TCP_0407 # do TCP send after IP changed
- ^TCPIP_TCP_0408 # close TCP socket after IP changed
- ^TCPIP_TCP_0411 # do TCP send after socket changed
- ^TCPIP_TCP_0412 # close TCP send after socket changed
- ^TCPIP_UDP_0101 # STA mode, udp bind test. use different ip, port
- ^TCPIP_UDP_0105 # STA mode, close UDP sockets test
- ^TCPIP_UDP_0106 # STA mode, create max udp socket test
- ^TCPIP_UDP_0107 # STA mode, get active socket info test
- ^TCPIP_UDP_0108 # AP mode, udp bind test. use different ip, port
- ^TCPIP_UDP_0112 # AP mode, close UDP sockets test
- ^TCPIP_UDP_0113 # AP mode, create max udp socket test
- ^TCPIP_UDP_0114 # AP mode, get active socket info test
- ^TCPIP_UDP_0201 # STA mode, recv buffer test
- ^TCPIP_UDP_0202 # AP mode, recv buffer test

View File

@ -2,4 +2,6 @@ Config: {execute count: 1, execute order: in order}
DUT: [SSC1]
Filter:
- Add:
ID: [TCPIP_TCP_0405, ^TCPIP_TCP_0405]
ID:
- TCPIP_TCP_0405 # do TCP send after PC NIC disabled
- ^TCPIP_TCP_0405 # do TCP send after PC NIC disabled

View File

@ -1,10 +1,35 @@
Config: {execute count: 1, execute order: in order}
DUT: [SSC2, SSC1]
DUT: [SSC1]
Filter:
- Add:
ID: [TCPIP_UDP_0303, TCPIP_UDP_0303, TCPIP_UDP_0303, TCPIP_UDP_0303, TCPIP_UDP_0303,
TCPIP_ICMP_0101, TCPIP_ICMP_0101, TCPIP_ICMP_0101, TCPIP_ICMP_0101, TCPIP_ICMP_0101,
TCPIP_DNS_0102, TCPIP_DNS_0102, TCPIP_DNS_0102, TCPIP_DNS_0102, TCPIP_DNS_0102,
TCPIP_DNS_0101, TCPIP_DNS_0101, TCPIP_DNS_0101, TCPIP_DNS_0101, TCPIP_DNS_0101,
^TCPIP_ICMP_0101, ^TCPIP_ICMP_0101, ^TCPIP_ICMP_0101, ^TCPIP_ICMP_0101, ^TCPIP_ICMP_0101,
TCPIP_UDP_0109, TCPIP_UDP_0109, TCPIP_UDP_0109, TCPIP_UDP_0109, TCPIP_UDP_0109]
ID:
- TCPIP_DNS_0101 # get host by name test
- TCPIP_DNS_0101 # get host by name test
- TCPIP_DNS_0101 # get host by name test
- TCPIP_DNS_0101 # get host by name test
- TCPIP_DNS_0101 # get host by name test
- TCPIP_DNS_0102 # TCP connect to iot.espressif.com
- TCPIP_DNS_0102 # TCP connect to iot.espressif.com
- TCPIP_DNS_0102 # TCP connect to iot.espressif.com
- TCPIP_DNS_0102 # TCP connect to iot.espressif.com
- TCPIP_DNS_0102 # TCP connect to iot.espressif.com
- TCPIP_DNS_0103 # UDP send to iot.expressif.com
- TCPIP_DNS_0103 # UDP send to iot.expressif.com
- TCPIP_DNS_0103 # UDP send to iot.expressif.com
- TCPIP_DNS_0103 # UDP send to iot.expressif.com
- TCPIP_DNS_0103 # UDP send to iot.expressif.com
- TCPIP_ICMP_0101 # ping function test
- TCPIP_ICMP_0101 # ping function test
- TCPIP_ICMP_0101 # ping function test
- TCPIP_ICMP_0101 # ping function test
- TCPIP_ICMP_0101 # ping function test
- TCPIP_UDP_0102 # STA mode, sendto test. use different ip, port
- TCPIP_UDP_0102 # STA mode, sendto test. use different ip, port
- TCPIP_UDP_0102 # STA mode, sendto test. use different ip, port
- TCPIP_UDP_0102 # STA mode, sendto test. use different ip, port
- TCPIP_UDP_0102 # STA mode, sendto test. use different ip, port
- TCPIP_UDP_0103 # STA mode, sendto test with different length
- TCPIP_UDP_0103 # STA mode, sendto test with different length
- TCPIP_UDP_0103 # STA mode, sendto test with different length
- TCPIP_UDP_0103 # STA mode, sendto test with different length
- TCPIP_UDP_0103 # STA mode, sendto test with different length

View File

@ -1,10 +1,35 @@
Config: {execute count: 1, execute order: in order}
DUT: [SSC1]
DUT: [SSC2, SSC1]
Filter:
- Add:
ID: [TCPIP_UDP_0104, TCPIP_UDP_0104, TCPIP_UDP_0104, TCPIP_UDP_0104, TCPIP_UDP_0104,
TCPIP_UDP_0102, TCPIP_UDP_0102, TCPIP_UDP_0102, TCPIP_UDP_0102, TCPIP_UDP_0102,
TCPIP_UDP_0103, TCPIP_UDP_0103, TCPIP_UDP_0103, TCPIP_UDP_0103, TCPIP_UDP_0103,
^TCPIP_UDP_0307, ^TCPIP_UDP_0307, ^TCPIP_UDP_0307, ^TCPIP_UDP_0307, ^TCPIP_UDP_0307,
^TCPIP_UDP_0306, ^TCPIP_UDP_0306, ^TCPIP_UDP_0306, ^TCPIP_UDP_0306, ^TCPIP_UDP_0306,
^TCPIP_UDP_0305, ^TCPIP_UDP_0305, ^TCPIP_UDP_0305, ^TCPIP_UDP_0305, ^TCPIP_UDP_0305]
ID:
- TCPIP_UDP_0104 # STA mode, recvfrom basic test
- TCPIP_UDP_0104 # STA mode, recvfrom basic test
- TCPIP_UDP_0104 # STA mode, recvfrom basic test
- TCPIP_UDP_0104 # STA mode, recvfrom basic test
- TCPIP_UDP_0104 # STA mode, recvfrom basic test
- TCPIP_UDP_0109 # AP mode, sendto test. use different ip, port
- TCPIP_UDP_0109 # AP mode, sendto test. use different ip, port
- TCPIP_UDP_0109 # AP mode, sendto test. use different ip, port
- TCPIP_UDP_0109 # AP mode, sendto test. use different ip, port
- TCPIP_UDP_0109 # AP mode, sendto test. use different ip, port
- TCPIP_UDP_0110 # AP mode, sendto test with different length
- TCPIP_UDP_0110 # AP mode, sendto test with different length
- TCPIP_UDP_0110 # AP mode, sendto test with different length
- TCPIP_UDP_0110 # AP mode, sendto test with different length
- TCPIP_UDP_0110 # AP mode, sendto test with different length
- TCPIP_UDP_0111 # AP mode, recvfrom basic test
- TCPIP_UDP_0111 # AP mode, recvfrom basic test
- TCPIP_UDP_0111 # AP mode, recvfrom basic test
- TCPIP_UDP_0111 # AP mode, recvfrom basic test
- TCPIP_UDP_0111 # AP mode, recvfrom basic test
- TCPIP_UDP_0301 # do UDP send after WIFI disconnected
- TCPIP_UDP_0301 # do UDP send after WIFI disconnected
- TCPIP_UDP_0301 # do UDP send after WIFI disconnected
- TCPIP_UDP_0301 # do UDP send after WIFI disconnected
- TCPIP_UDP_0301 # do UDP send after WIFI disconnected
- TCPIP_UDP_0302 # close UDP socket after WIFI disconnected
- TCPIP_UDP_0302 # close UDP socket after WIFI disconnected
- TCPIP_UDP_0302 # close UDP socket after WIFI disconnected
- TCPIP_UDP_0302 # close UDP socket after WIFI disconnected
- TCPIP_UDP_0302 # close UDP socket after WIFI disconnected

View File

@ -2,9 +2,34 @@ Config: {execute count: 1, execute order: in order}
DUT: [SSC1]
Filter:
- Add:
ID: [^TCPIP_UDP_0304, ^TCPIP_UDP_0304, ^TCPIP_UDP_0304, ^TCPIP_UDP_0304, ^TCPIP_UDP_0304,
^TCPIP_UDP_0302, ^TCPIP_UDP_0302, ^TCPIP_UDP_0302, ^TCPIP_UDP_0302, ^TCPIP_UDP_0302,
^TCPIP_UDP_0301, ^TCPIP_UDP_0301, ^TCPIP_UDP_0301, ^TCPIP_UDP_0301, ^TCPIP_UDP_0301,
^TCPIP_UDP_0104, ^TCPIP_UDP_0104, ^TCPIP_UDP_0104, ^TCPIP_UDP_0104, ^TCPIP_UDP_0104,
^TCPIP_UDP_0103, ^TCPIP_UDP_0103, ^TCPIP_UDP_0103, ^TCPIP_UDP_0103, ^TCPIP_UDP_0103,
^TCPIP_UDP_0102, ^TCPIP_UDP_0102, ^TCPIP_UDP_0102, ^TCPIP_UDP_0102, ^TCPIP_UDP_0102]
ID:
- TCPIP_UDP_0303 # do UDP send after mode changed
- TCPIP_UDP_0303 # do UDP send after mode changed
- TCPIP_UDP_0303 # do UDP send after mode changed
- TCPIP_UDP_0303 # do UDP send after mode changed
- TCPIP_UDP_0303 # do UDP send after mode changed
- TCPIP_UDP_0304 # close UDP socket after mode changed
- TCPIP_UDP_0304 # close UDP socket after mode changed
- TCPIP_UDP_0304 # close UDP socket after mode changed
- TCPIP_UDP_0304 # close UDP socket after mode changed
- TCPIP_UDP_0304 # close UDP socket after mode changed
- TCPIP_UDP_0305 # close UDP socket after PC NIC disabled
- TCPIP_UDP_0305 # close UDP socket after PC NIC disabled
- TCPIP_UDP_0305 # close UDP socket after PC NIC disabled
- TCPIP_UDP_0305 # close UDP socket after PC NIC disabled
- TCPIP_UDP_0305 # close UDP socket after PC NIC disabled
- TCPIP_UDP_0306 # do UDP send after IP changed
- TCPIP_UDP_0306 # do UDP send after IP changed
- TCPIP_UDP_0306 # do UDP send after IP changed
- TCPIP_UDP_0306 # do UDP send after IP changed
- TCPIP_UDP_0306 # do UDP send after IP changed
- TCPIP_UDP_0307 # close UDP socket after IP changed
- TCPIP_UDP_0307 # close UDP socket after IP changed
- TCPIP_UDP_0307 # close UDP socket after IP changed
- TCPIP_UDP_0307 # close UDP socket after IP changed
- TCPIP_UDP_0307 # close UDP socket after IP changed
- ^TCPIP_DNS_0101 # get host by name test
- ^TCPIP_DNS_0101 # get host by name test
- ^TCPIP_DNS_0101 # get host by name test
- ^TCPIP_DNS_0101 # get host by name test
- ^TCPIP_DNS_0101 # get host by name test

View File

@ -1,10 +1,35 @@
Config: {execute count: 1, execute order: in order}
DUT: [SSC2, SSC1]
DUT: [SSC1]
Filter:
- Add:
ID: [TCPIP_UDP_0111, TCPIP_UDP_0111, TCPIP_UDP_0111, TCPIP_UDP_0111, TCPIP_UDP_0111,
TCPIP_UDP_0110, TCPIP_UDP_0110, TCPIP_UDP_0110, TCPIP_UDP_0110, TCPIP_UDP_0110,
^TCPIP_DNS_0101, ^TCPIP_DNS_0101, ^TCPIP_DNS_0101, ^TCPIP_DNS_0101, ^TCPIP_DNS_0101,
^TCPIP_DNS_0103, ^TCPIP_DNS_0103, ^TCPIP_DNS_0103, ^TCPIP_DNS_0103, ^TCPIP_DNS_0103,
^TCPIP_DNS_0102, ^TCPIP_DNS_0102, ^TCPIP_DNS_0102, ^TCPIP_DNS_0102, ^TCPIP_DNS_0102,
TCPIP_UDP_0304, TCPIP_UDP_0304, TCPIP_UDP_0304, TCPIP_UDP_0304, TCPIP_UDP_0304]
ID:
- ^TCPIP_DNS_0102 # TCP connect to iot.espressif.com
- ^TCPIP_DNS_0102 # TCP connect to iot.espressif.com
- ^TCPIP_DNS_0102 # TCP connect to iot.espressif.com
- ^TCPIP_DNS_0102 # TCP connect to iot.espressif.com
- ^TCPIP_DNS_0102 # TCP connect to iot.espressif.com
- ^TCPIP_DNS_0103 # UDP send to iot.expressif.com
- ^TCPIP_DNS_0103 # UDP send to iot.expressif.com
- ^TCPIP_DNS_0103 # UDP send to iot.expressif.com
- ^TCPIP_DNS_0103 # UDP send to iot.expressif.com
- ^TCPIP_DNS_0103 # UDP send to iot.expressif.com
- ^TCPIP_ICMP_0101 # ping function test
- ^TCPIP_ICMP_0101 # ping function test
- ^TCPIP_ICMP_0101 # ping function test
- ^TCPIP_ICMP_0101 # ping function test
- ^TCPIP_ICMP_0101 # ping function test
- ^TCPIP_UDP_0102 # STA mode, sendto test. use different ip, port
- ^TCPIP_UDP_0102 # STA mode, sendto test. use different ip, port
- ^TCPIP_UDP_0102 # STA mode, sendto test. use different ip, port
- ^TCPIP_UDP_0102 # STA mode, sendto test. use different ip, port
- ^TCPIP_UDP_0102 # STA mode, sendto test. use different ip, port
- ^TCPIP_UDP_0103 # STA mode, sendto test with different length
- ^TCPIP_UDP_0103 # STA mode, sendto test with different length
- ^TCPIP_UDP_0103 # STA mode, sendto test with different length
- ^TCPIP_UDP_0103 # STA mode, sendto test with different length
- ^TCPIP_UDP_0103 # STA mode, sendto test with different length
- ^TCPIP_UDP_0104 # STA mode, recvfrom basic test
- ^TCPIP_UDP_0104 # STA mode, recvfrom basic test
- ^TCPIP_UDP_0104 # STA mode, recvfrom basic test
- ^TCPIP_UDP_0104 # STA mode, recvfrom basic test
- ^TCPIP_UDP_0104 # STA mode, recvfrom basic test

View File

@ -2,9 +2,34 @@ Config: {execute count: 1, execute order: in order}
DUT: [SSC1]
Filter:
- Add:
ID: [TCPIP_UDP_0305, TCPIP_UDP_0305, TCPIP_UDP_0305, TCPIP_UDP_0305, TCPIP_UDP_0305,
TCPIP_UDP_0306, TCPIP_UDP_0306, TCPIP_UDP_0306, TCPIP_UDP_0306, TCPIP_UDP_0306,
TCPIP_UDP_0307, TCPIP_UDP_0307, TCPIP_UDP_0307, TCPIP_UDP_0307, TCPIP_UDP_0307,
TCPIP_UDP_0301, TCPIP_UDP_0301, TCPIP_UDP_0301, TCPIP_UDP_0301, TCPIP_UDP_0301,
TCPIP_UDP_0302, TCPIP_UDP_0302, TCPIP_UDP_0302, TCPIP_UDP_0302, TCPIP_UDP_0302,
TCPIP_DNS_0103, TCPIP_DNS_0103, TCPIP_DNS_0103, TCPIP_DNS_0103, TCPIP_DNS_0103]
ID:
- ^TCPIP_UDP_0110 # AP mode, sendto test with different length
- ^TCPIP_UDP_0110 # AP mode, sendto test with different length
- ^TCPIP_UDP_0110 # AP mode, sendto test with different length
- ^TCPIP_UDP_0110 # AP mode, sendto test with different length
- ^TCPIP_UDP_0110 # AP mode, sendto test with different length
- ^TCPIP_UDP_0301 # do UDP send after WIFI disconnected
- ^TCPIP_UDP_0301 # do UDP send after WIFI disconnected
- ^TCPIP_UDP_0301 # do UDP send after WIFI disconnected
- ^TCPIP_UDP_0301 # do UDP send after WIFI disconnected
- ^TCPIP_UDP_0301 # do UDP send after WIFI disconnected
- ^TCPIP_UDP_0302 # close UDP socket after WIFI disconnected
- ^TCPIP_UDP_0302 # close UDP socket after WIFI disconnected
- ^TCPIP_UDP_0302 # close UDP socket after WIFI disconnected
- ^TCPIP_UDP_0302 # close UDP socket after WIFI disconnected
- ^TCPIP_UDP_0302 # close UDP socket after WIFI disconnected
- ^TCPIP_UDP_0303 # do UDP send after mode changed
- ^TCPIP_UDP_0303 # do UDP send after mode changed
- ^TCPIP_UDP_0303 # do UDP send after mode changed
- ^TCPIP_UDP_0303 # do UDP send after mode changed
- ^TCPIP_UDP_0303 # do UDP send after mode changed
- ^TCPIP_UDP_0304 # close UDP socket after mode changed
- ^TCPIP_UDP_0304 # close UDP socket after mode changed
- ^TCPIP_UDP_0304 # close UDP socket after mode changed
- ^TCPIP_UDP_0304 # close UDP socket after mode changed
- ^TCPIP_UDP_0304 # close UDP socket after mode changed
- ^TCPIP_UDP_0305 # close UDP socket after PC NIC disabled
- ^TCPIP_UDP_0305 # close UDP socket after PC NIC disabled
- ^TCPIP_UDP_0305 # close UDP socket after PC NIC disabled
- ^TCPIP_UDP_0305 # close UDP socket after PC NIC disabled
- ^TCPIP_UDP_0305 # close UDP socket after PC NIC disabled

View File

@ -2,5 +2,14 @@ Config: {execute count: 1, execute order: in order}
DUT: [SSC1]
Filter:
- Add:
ID: [^TCPIP_UDP_0303, ^TCPIP_UDP_0303, ^TCPIP_UDP_0303, ^TCPIP_UDP_0303, ^TCPIP_UDP_0303,
^TCPIP_UDP_0110, ^TCPIP_UDP_0110, ^TCPIP_UDP_0110, ^TCPIP_UDP_0110, ^TCPIP_UDP_0110]
ID:
- ^TCPIP_UDP_0306 # do UDP send after IP changed
- ^TCPIP_UDP_0306 # do UDP send after IP changed
- ^TCPIP_UDP_0306 # do UDP send after IP changed
- ^TCPIP_UDP_0306 # do UDP send after IP changed
- ^TCPIP_UDP_0306 # do UDP send after IP changed
- ^TCPIP_UDP_0307 # close UDP socket after IP changed
- ^TCPIP_UDP_0307 # close UDP socket after IP changed
- ^TCPIP_UDP_0307 # close UDP socket after IP changed
- ^TCPIP_UDP_0307 # close UDP socket after IP changed
- ^TCPIP_UDP_0307 # close UDP socket after IP changed

View File

@ -2,9 +2,34 @@ Config: {execute count: 1, execute order: in order}
DUT: [SSC2, SSC1]
Filter:
- Add:
ID: [^WIFI_CONN_0601, ^WIFI_ADDR_0101, WIFI_SCAN_0103, WIFI_SCAN_0102, WIFI_SCAN_0101,
WIFI_SCAN_0105, WIFI_SCAN_0104, ^WIFI_CONN_0103, WIFI_CONN_0201, WIFI_CONN_0904,
^WIFI_SCAN_0102, ^WIFI_SCAN_0103, ^WIFI_SCAN_0104, WIFI_CONN_0401, WIFI_ADDR_0101,
WIFI_ADDR_0102, WIFI_CONN_0301, WIFI_SCAN_0301, WIFI_SCAN_0303, ^WIFI_CONN_0801,
WIFI_SCAN_0304, ^WIFI_CONN_0301, WIFI_CONN_0501, WIFI_CONN_0502, ^WIFI_CONN_0401,
WIFI_MODE_0101, WIFI_MODE_0103, WIFI_MODE_0102, ^WIFI_CONN_0904, ^WIFI_CONN_0901]
ID:
- WIFI_ADDR_0101 # set mac, query mac
- WIFI_ADDR_0102 # set mac and do scan/JAP/SAP
- WIFI_CONN_0101 # station SAP+JAP test, different encryption
- WIFI_CONN_0102 # station SAP+JAP test, different channel
- WIFI_CONN_0103 # station SAP+JAP test, ssid hidden
- WIFI_CONN_0104 # station SAP test, max allowed sta
- WIFI_CONN_0201 # JAP query test
- WIFI_CONN_0301 # AP config query test
- WIFI_CONN_0401 # auto reconnect test
- WIFI_CONN_0501 # reconnect policy test
- WIFI_CONN_0502 # will not do reconnect after manually disconnected
- WIFI_CONN_0601 # list stations connected to soft ap test
- WIFI_CONN_0801 # test auth change event
- WIFI_CONN_0901 # test wifi disconnect reason REASON_ASSOC_LEAVE, REASON_4WAY_HANDSHAKE_TIMEOUT, REASON_NO_AP_FOUND
- WIFI_CONN_0904 # test wifi disconnect reason REASON_ASSOC_TOOMANY, REASON_HANDSHAKE_TIMEOUT, REASON_ASSOC_EXPIRE
- WIFI_MODE_0101 # mode switch test (sta mode)
- WIFI_MODE_0102 # mode switch test (AP mode)
- WIFI_MODE_0103 # mode switch test (STA+AP mode)
- WIFI_SCAN_0101 # scan with scan config ssid
- WIFI_SCAN_0102 # scan with scan config bssid
- WIFI_SCAN_0103 # scan with scan config channel
- WIFI_SCAN_0104 # scan with scan config show hidden
- WIFI_SCAN_0105 # scan with several configs
- WIFI_SCAN_0301 # reject scan request before scan finished
- WIFI_SCAN_0302 # scan in congest channel
- WIFI_SCAN_0303 # scan during JAP
- WIFI_SCAN_0304 # scan during ext STA join SoftAP
- ^WIFI_ADDR_0101 # set mac, query mac
- ^WIFI_ADDR_0102 # set mac and do scan/JAP/SAP
- ^WIFI_CONN_0101 # station SAP+JAP test, different encryption

View File

@ -2,6 +2,19 @@ Config: {execute count: 1, execute order: in order}
DUT: [SSC2, SSC1]
Filter:
- Add:
ID: [WIFI_SCAN_0302, WIFI_CONN_0601, ^WIFI_CONN_0201, ^WIFI_ADDR_0102, WIFI_CONN_0901,
WIFI_CONN_0801, ^WIFI_CONN_0104, WIFI_CONN_0104, WIFI_CONN_0101, WIFI_CONN_0102,
WIFI_CONN_0103, ^WIFI_SCAN_0101, ^WIFI_CONN_0101, ^WIFI_CONN_0502, ^WIFI_CONN_0501]
ID:
- ^WIFI_CONN_0103 # station SAP+JAP test, ssid hidden
- ^WIFI_CONN_0104 # station SAP test, max allowed sta
- ^WIFI_CONN_0201 # JAP query test
- ^WIFI_CONN_0301 # AP config query test
- ^WIFI_CONN_0401 # auto reconnect test
- ^WIFI_CONN_0501 # reconnect policy test
- ^WIFI_CONN_0502 # will not do reconnect after manually disconnected
- ^WIFI_CONN_0601 # list stations connected to soft ap test
- ^WIFI_CONN_0801 # test auth change event
- ^WIFI_CONN_0901 # test wifi disconnect reason REASON_ASSOC_LEAVE, REASON_4WAY_HANDSHAKE_TIMEOUT, REASON_NO_AP_FOUND
- ^WIFI_CONN_0904 # test wifi disconnect reason REASON_ASSOC_TOOMANY, REASON_HANDSHAKE_TIMEOUT, REASON_ASSOC_EXPIRE
- ^WIFI_SCAN_0101 # scan with scan config ssid
- ^WIFI_SCAN_0102 # scan with scan config bssid
- ^WIFI_SCAN_0103 # scan with scan config channel
- ^WIFI_SCAN_0104 # scan with scan config show hidden

View File

@ -1,6 +1,7 @@
Config: {execute count: 1, execute order: in order}
DUT: [SSC3, SSC2, SSC1]
DUT: [SSC1]
Filter:
- Add:
ID: [WIFI_PHY_0502, WIFI_PHY_0503, WIFI_PHY_0501, WIFI_PHY_0506, WIFI_PHY_0505,
WIFI_PHY_0504]
ID:
- WIFI_CONN_0902 # test wifi disconnect reason REASON_BEACON_TIMEOUT
- ^WIFI_CONN_0902 # test wifi disconnect reason REASON_BEACON_TIMEOUT

View File

@ -1,5 +1,11 @@
Config: {execute count: 1, execute order: in order}
DUT: [SSC1]
DUT: [SSC3, SSC2, SSC1]
Filter:
- Add:
ID: [^WIFI_CONN_0902, WIFI_CONN_0902]
ID:
- WIFI_PHY_0501 # SoftAP STA in channel1 20M, STA changed to channel2 20M
- WIFI_PHY_0502 # SoftAP STA in channel1 20M, STA changed to channel2 40M
- WIFI_PHY_0503 # SoftAP STA in channel1, SoftAP 20M, STA 40M, STA changed to channel2 20M
- WIFI_PHY_0504 # SoftAP STA in channel1, SoftAP 20M, STA 40M, STA changed to channel2 40M
- WIFI_PHY_0505 # SoftAP STA in channel1, SoftAP 40M, STA 40M, STA changed to channel2 20M
- WIFI_PHY_0506 # SoftAP STA in channel1, SoftAP 40M, STA 40M, STA changed to channel2 40M

View File

@ -2,4 +2,6 @@ Config: {execute count: 1, execute order: in order}
DUT: [SSC1]
Filter:
- Add:
ID: [^WIFI_CONN_0903, WIFI_CONN_0903]
ID:
- WIFI_CONN_0903 # test wifi disconnect reason REASON_AUTH_EXPIRE
- ^WIFI_CONN_0903 # test wifi disconnect reason REASON_AUTH_EXPIRE

View File

@ -2,5 +2,13 @@ Config: {execute count: 1, execute order: in order}
DUT: [SSC2, SSC1]
Filter:
- Add:
ID: [WIFI_SCAN_0201, WIFI_PHY_0403, WIFI_PHY_0402, WIFI_PHY_0401, WIFI_PHY_0407,
WIFI_PHY_0406, WIFI_PHY_0405, WIFI_PHY_0404, WIFI_PHY_0408]
ID:
- WIFI_PHY_0401 # SoftAP ext AP in defferent channel, both bandwidth 20M, STA connect to AP then Softap get connected
- WIFI_PHY_0402 # SoftAP ext AP in defferent channel, both bandwidth 20M, Softap get connected than STA connect to AP
- WIFI_PHY_0403 # SoftAP ext AP in defferent channel, SoftAP 20M, ext AP 40M, STA connect to AP then Softap get connected
- WIFI_PHY_0404 # SoftAP ext AP in defferent channel, SoftAP 20M, ext AP 40M, Softap get connected than STA connect to AP
- WIFI_PHY_0405 # SoftAP ext AP in defferent channel, both bandwidth 40M, STA connect to AP then Softap get connected
- WIFI_PHY_0406 # SoftAP ext AP in defferent channel, both bandwidth 40M, Softap get connected than STA connect to AP
- WIFI_PHY_0407 # SoftAP ext AP in defferent channel, SoftAP 40M, ext AP 20M, STA connect to AP then Softap get connected
- WIFI_PHY_0408 # SoftAP ext AP in defferent channel, SoftAP 40M, ext AP 20M, Softap get connected than STA connect to AP
- WIFI_SCAN_0201 # STA in differnt PHY mode to scan AP in different PHY mode

View File

@ -0,0 +1,6 @@
Config: {execute count: 1, execute order: in order}
DUT: [SSC3, SSC2, SSC1, SSC5, SSC4]
Filter:
- Add:
ID:
- TCPIP_TCP_5101 # 1 AP 4 STA TCP stable test

View File

@ -0,0 +1,6 @@
Config: {execute count: 1, execute order: in order}
DUT: [SSC1]
Filter:
- Add:
ID:
- TCPIP_TCP_5102 # send random length segment to target

View File

@ -0,0 +1,6 @@
Config: {execute count: 1, execute order: in order}
DUT: [SSC3, SSC2, SSC1, SSC5, SSC4]
Filter:
- Add:
ID:
- TCPIP_TCP_5103 # TCP SoftSTA send/recv stress test

View File

@ -0,0 +1,6 @@
Config: {execute count: 1, execute order: in order}
DUT: [SSC1]
Filter:
- Add:
ID:
- TCPIP_TCP_5001 # test possible TCP connect/disconnect method

View File

@ -0,0 +1,6 @@
Config: {execute count: 1, execute order: in order}
DUT: [SSC2, SSC1]
Filter:
- Add:
ID:
- TCPIP_TCP_5201 # TCP send/recv stress test

View File

@ -0,0 +1,6 @@
Config: {execute count: 1, execute order: in order}
DUT: [SSC1]
Filter:
- Add:
ID:
- TCPIP_TCP_5202 # TCP send/recv data validation

View File

@ -0,0 +1,6 @@
Config: {execute count: 1, execute order: in order}
DUT: [SSC2, SSC1]
Filter:
- Add:
ID:
- TCPIP_UDP_5001 # UDP send/recv stress test

View File

@ -0,0 +1,6 @@
Config: {execute count: 1, execute order: in order}
DUT: [SSC3, SSC2, SSC1, SSC5, SSC4]
Filter:
- Add:
ID:
- WIFI_CONN_5101 # max sta connect to SotfAP and disconnect

View File

@ -4307,6 +4307,287 @@ test cases:
test point 1: abnormal/special use
test point 2: TCP handling abnormal event
version: v1 (2016-8-15)
- CI ready: 'Yes'
ID: TCPIP_TCP_5001
SDK: '8266_NonOS
8266_RTOS
ESP32_IDF'
Test App: SSC
auto test: 'Yes'
category: Stress
cmd set:
- TCPStress/TCPConnection
- - max_connection = 5
- [dummy]
- - execute_time = 300
- ['']
- - connect_method = ["C_01", "C_02", "C_05", "C_07"]
- ['']
- - disconnect_method = ["D_01", "D_03", "D_05", "D_06"]
- ['']
- - pc_ip = "pc_ip"
- ['']
- - target_ip = "target_ip"
- ['']
comment: ''
execution time: 5.0
expected result: 1. succeed
initial condition: STAM2
initial condition description (auto): sta mode, join AP, DHCP on
level: Integration
module: TCPIP
steps: '1. random choose connect method to do connect, random choose a method to
close
Loop executing step 1'
sub module: TCP
summary: test possible TCP connect/disconnect method
test environment: SSC_T1_1
test environment description (auto): 'PC has 2 wired NIC connected to AP.
PC has 1 WiFi NIC.
1 SSC target connect with PC by UART.'
test point 1: function + stress
test point 2: TCP connect and disconnect test
version: v2 (2016-11-15)
- CI ready: 'Yes'
ID: TCPIP_TCP_5101
SDK: '8266_NonOS
8266_RTOS
ESP32_IDF'
Test App: SSC
auto test: 'Yes'
category: Stable
cmd set:
- TCPStress/TCPAPNSTA
- - send_len = 1460
- [dummy]
- - test_time = 720
- ['']
- - server_port = "<test_tcp_port1>"
- ['']
- - server_echo = True
- ['']
- - sta_number = 4
- ['']
- - send_delay = 50
- ['']
- - ap_ip = "<target_ap_ip>"
- ['']
comment: ''
execution time: 12.0
expected result: '1. succeed
2. succeed
3. succeed
4. all TCP connection not disconnected'
initial condition: None
initial condition description (auto): none
level: Integration
module: TCPIP
steps: '1. all sta connect to softap
2. create tcp server on softap
3. all sta connect to softap tcp server
4. do bi-direction send on all tcp connections'
sub module: TCP
summary: 1 AP 4 STA TCP stable test
test environment: SSC_T5_1
test environment description (auto): 5 SSC target connect with PC by UART.
test point 1: stable
test point 2: TCP stable test
version: v2 (2016-11-15)
- CI ready: 'Yes'
ID: TCPIP_TCP_5102
SDK: '8266_NonOS
8266_RTOS
ESP32_IDF'
Test App: SSC
auto test: 'Yes'
category: Stable
cmd set:
- TCPStress/TCPRandomSend
- - delay_config = [0, 0.01, 0.1, 0.5, 1]
- [dummy]
- - send_count = 1000
- ['']
- - test_time = 300
- ['']
comment: ''
execution time: 12.0
expected result: '1. succeed
2. succeed'
initial condition: STAM2
initial condition description (auto): sta mode, join AP, DHCP on
level: Integration
module: TCPIP
steps: '1. create TCP connection
2. PC send random length data to target'
sub module: TCP
summary: send random length segment to target
test environment: SSC_T1_1
test environment description (auto): 'PC has 2 wired NIC connected to AP.
PC has 1 WiFi NIC.
1 SSC target connect with PC by UART.'
test point 1: stable
test point 2: TCP stable test
version: v2 (2016-11-15)
- CI ready: 'Yes'
ID: TCPIP_TCP_5103
SDK: '8266_NonOS
8266_RTOS
ESP32_IDF'
Test App: SSC
auto test: 'Yes'
category: Stable
cmd set:
- TCPStress/TCPSoftAPSTASendRecv
- - send_len = 1460
- [dummy]
- - test_time = 720
- ['']
- - server_port = "<test_tcp_port1>"
- ['']
- - server_port_2 = "<test_tcp_port2>"
- ['']
- - server_echo = True
- ['']
- - sta_number = 3
- ['']
- - send_delay = 50
- ['']
- - ap_ip = "<target_ap_ip>"
- ['']
comment: ''
execution time: 12.0
expected result: '1. succeed
2. verify reciveid data on target and PC succeed'
initial condition: None
initial condition description (auto): none
level: Integration
module: TCPIP
steps: '1. create TCP connection
2. send specified pattern on both direction'
sub module: TCP
summary: TCP SoftSTA send/recv stress test
test environment: SSC_T5_1
test environment description (auto): 5 SSC target connect with PC by UART.
test point 1: stable
test point 2: TCP stable test
version: v2 (2016-11-15)
- CI ready: 'Yes'
ID: TCPIP_TCP_5201
SDK: '8266_NonOS
8266_RTOS
ESP32_IDF'
Test App: SSC
auto test: 'Yes'
category: Stress
cmd set:
- TCPStress/TCPSendRecv
- - send_len = 1460
- [dummy]
- - test_time = 300
- ['']
- - duplex = True
- ['']
- - conn_num = 5
- ['']
- - send_delay = 20
- ['']
comment: ''
execution time: 12.0
expected result: '1. succeed
2. succeed
3. all TCP connection not disconnected'
initial condition: T2_1
initial condition description (auto): target 1 as SoftAP, target 2 as STA
level: Integration
module: TCPIP
steps: '1. sta connect to softap
2. create multiple tcp connection
3. do send/recv on all tcp connections'
sub module: TCP
summary: TCP send/recv stress test
test environment: SSC_T2_1
test environment description (auto): 'PC has 1 wired NIC connected to AP.
PC has 1 WiFi NIC.
2 SSC target connect with PC by UART.'
test point 1: stress
test point 2: TCP stress test
version: v2 (2016-11-15)
- CI ready: 'Yes'
ID: TCPIP_TCP_5202
SDK: '8266_NonOS
8266_RTOS
ESP32_IDF'
Test App: SSC
auto test: 'Yes'
category: Stress
cmd set:
- TCPStress/TCPDataValidation
- - test_time = 1440
- [dummy]
- - tx_enable = True
- ['']
- - rx_enable = True
- ['']
- - conn_num = 1
- ['']
- - send_len = 1024
- ['']
comment: ''
execution time: 24.0
expected result: '1. succeed
2. verify reciveid data on target and PC succeed'
initial condition: STAM2
initial condition description (auto): sta mode, join AP, DHCP on
level: Integration
module: TCPIP
steps: '1. create TCP connection
2. send specified pattern on both direction'
sub module: TCP
summary: TCP send/recv data validation
test environment: SSC_T1_1
test environment description (auto): 'PC has 2 wired NIC connected to AP.
PC has 1 WiFi NIC.
1 SSC target connect with PC by UART.'
test point 1: stress
test point 2: TCP stress test
version: v2 (2016-11-15)
- CI ready: 'Yes'
ID: TCPIP_UDP_0101
SDK: '8266_NonOS
@ -5653,6 +5934,55 @@ test cases:
test point 1: abnormal/special use
test point 2: UDP handling abnormal event
version: v1 (2016-8-15)
- CI ready: 'Yes'
ID: TCPIP_UDP_5001
SDK: '8266_NonOS
8266_RTOS
ESP32_IDF'
Test App: SSC
auto test: 'Yes'
category: Stress
cmd set:
- UDPStress/UDPSendRecv
- - send_len = 1460
- [dummy]
- - test_time = 300
- ['']
- - duplex = True
- ['']
- - conn_num = 5
- ['']
- - send_delay = 20
- ['']
comment: ''
execution time: 12.0
expected result: '1. succeed
2. succeed
3. succeed'
initial condition: T2_1
initial condition description (auto): target 1 as SoftAP, target 2 as STA
level: Integration
module: TCPIP
steps: '1. sta connect to softap
2. create multiple udp
3. do send/recv on all udp'
sub module: UDP
summary: UDP send/recv stress test
test environment: SSC_T2_1
test environment description (auto): 'PC has 1 wired NIC connected to AP.
PC has 1 WiFi NIC.
2 SSC target connect with PC by UART.'
test point 1: stress
test point 2: UDP stress test
version: v2 (2016-11-15)
- CI ready: 'Yes'
ID: WIFI_ADDR_0101
SDK: '8266_NonOS
@ -6666,6 +6996,53 @@ test cases:
test point 1: basic function
test point 2: wifi disconnect reason test
version: v1 (2016-8-15)
- CI ready: 'Yes'
ID: WIFI_CONN_5101
SDK: '8266_NonOS
8266_RTOS
ESP32_IDF'
Test App: SSC
auto test: 'Yes'
category: Stress
cmd set:
- WiFiStress/SoftAPNSTA
- - sta_num = 4
- [dummy]
- - max_sta = 4
- ['']
- - test_time = 300
- ['']
- - delay1 = [0, 1]
- ['']
- - delay2 = [0, 1]
- ['']
- - change_mac = True
- ['']
- - channel = 1
- ['']
comment: ''
execution time: 5.0
expected result: '1. succeed
2. JAP succeed'
initial condition: None
initial condition description (auto): none
level: Integration
module: WIFI MAC
steps: '1. 1 target set to softap mode and rest set to sta mode
2. all sta random join and disconnect from softap
Loop step 2'
sub module: WIFI Connect
summary: max sta connect to SotfAP and disconnect
test environment: SSC_T5_1
test environment description (auto): 5 SSC target connect with PC by UART.
test point 1: stress
test point 2: SoftAP WIFI connect/disconnect stress test
version: v2 (2016-11-15)
- CI ready: 'Yes'
ID: WIFI_MODE_0101
SDK: '8266_NonOS

View File

@ -0,0 +1,223 @@
from TCAction import TCActionBase
from NativeLog import NativeLog
import time
import random
import string
TEST_COUNT_ONE_ROUND = 500
class TestCase(TCActionBase.CommonTCActionBase):
def __init__(self, test_case, test_env, timeout=30, log_path=TCActionBase.LOG_PATH):
TCActionBase.CommonTCActionBase.__init__(self, test_case, test_env, timeout=timeout, log_path=log_path)
self.send_len = 1460
self.server_echo = True
self.sta_number = 4
self.test_time = 12 * 60
self.send_delay = 50
# load param from excel
cmd_set = test_case["cmd set"]
for i in range(1, len(cmd_set)):
if cmd_set[i][0] != "dummy":
cmd_string = "self." + cmd_set[i][0]
exec cmd_string
self.result_cntx = TCActionBase.ResultCheckContext(self, test_env, self.tc_name)
pass
def cleanup(self):
checker_stings = []
test_action_strings = []
for i in range(self.sta_number + 1):
checker_stings.append("R SSC%s C +RECVPRINT:1" % (i+1))
test_action_strings.append("SSC SSC%s soc -R -o 1" % (i+1))
fail_string = "Fail, Fail to turn on recv print"
self.load_and_exe_one_step(checker_stings, test_action_strings, fail_string)
pass
def execute(self):
TCActionBase.TCActionBase.execute(self)
self.result_cntx.start()
try:
# configurable params
send_len = self.send_len
server_echo = self.server_echo
sta_number = self.sta_number
test_time = self.test_time * 60
send_delay = self.send_delay
ap_ip = self.get_parameter("target_ap_ip")
# configurable params
except StandardError, e:
NativeLog.add_trace_critical("Error configuration for TCPTransparent script, error is %s" % e)
raise StandardError("Error configuration")
# step0 reboot
checker_stings = []
test_action_string = []
for i in range(sta_number+1):
checker_stings.append("P SSC%d C !!!ready!!!" % (i+1))
test_action_string.append("SSCC SSC%d reboot" % (i+1))
fail_string = "Fail, Fail to reboot"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
# switch off recv print
checker_stings = []
test_action_strings = []
for i in range(self.sta_number + 1):
checker_stings.append("R SSC%s C +RECVPRINT:0" % (i+1))
test_action_strings.append("SSC SSC%s soc -R -o 0" % (i+1))
fail_string = "Fail, Fail to turn off recv print"
self.load_and_exe_one_step(checker_stings, test_action_strings, fail_string)
# step1 set ap on SSC1, create server
checker_stings = ["R SSC1 C +MODE:OK"]
test_action_string = ["SSCC SSC1 op -S -o 2"]
fail_string = "Fail, Fail set mode"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
ssid = "".join([random.choice(string.lowercase) for m in range(10)])
password = "".join([random.choice(string.lowercase) for m in range(10)])
tcp_port = random.randint(10000, 20000)
checker_stings = ["R SSC1 C +SAP:OK"]
test_action_string = ["SSCC SSC1 ap -S -s %s -p %s -t 3 -m 8" % (ssid, password)]
fail_string = "Fail, Fail set ap"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
checker_stings = ["R SSC1 A <server_sock>:BIND:(\d+),OK"]
test_action_string = ["SSCC SSC1 soc -B -t TCP -p %s" % tcp_port]
fail_string = "Fail, Fail create server"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
checker_stings = ["R SSC1 RE LISTEN:(\d+),OK"]
test_action_string = ["SSCC SSC1 soc -L -s <server_sock>"]
fail_string = "Fail, Fail create server"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
# step 2, 8 SSC target(SSC2 - SSC9) join SSC1 soft AP
checker_stings = []
test_action_string = []
for i in range(sta_number):
checker_stings.append("P SSC%d C +MODE:OK" % (i+2))
test_action_string.append("SSCC SSC%d op -S -o 1" % (i+2))
fail_string = "Fail, Fail set mode"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
checker_stings = []
test_action_string = []
for i in range(sta_number):
checker_stings.append("P SSC%d C +JAP:CONNECTED,%s" % (i+2, ssid))
test_action_string.append("SSCC SSC%d ap -C -s %s -p %s" % (i+2, ssid, password))
fail_string = "Fail, Fail to connect to server"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
# step 3, create client on SSC2 - SSC9
checker_stings = []
test_action_string = []
for i in range(sta_number):
checker_stings.append("P SSC%d A <client_sock%d>:BIND:(\d+),OK" % (i+2, i+2))
test_action_string.append("SSCC SSC%d soc -B -t TCP" % (i+2))
fail_string = "Fail, Fail to connect to server"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
for i in range(sta_number):
checker_stings = ["P SSC%d RE CONNECT:(\d+),OK" % (i+2),
"P SSC1 A <accept_sock%d>:ACCEPT:(\d+),.+" % (i+2)]
test_action_string = ["SSCC SSC%d soc -C -s <client_sock%d> -i %s -p %s" %
(i+2, i+2, ap_ip, tcp_port)]
fail_string = "Fail, Fail to connect to server"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
start_time = time.time()
# step 4, do send/recv
while time.time() - start_time < test_time:
checker_stings = []
test_action_string = []
for i in range(sta_number):
checker_stings.append("P SSC%d RE \+SEND:\d+,OK NC CLOSED" % (i+2))
test_action_string.append("SSC SSC%d soc -S -s <client_sock%d> -l %d -n %d -j %d" %
(i+2, i+2, send_len, TEST_COUNT_ONE_ROUND, send_delay))
if server_echo is True:
test_action_string.append("SSC SSC1 soc -S -s <accept_sock%d> -l %d -n %d -j %d" %
(i+2, send_len, TEST_COUNT_ONE_ROUND, send_delay))
checker_stings.append("P SSC1 RE \"\+SEND:%%%%s,OK\"%%%%(<accept_sock%d>) NC CLOSED)" %
(i+2))
fail_string = "Fail, Failed to send/recv data"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string,
check_freq=1, check_time=300) is False:
break
NativeLog.add_prompt_trace("time escape: %s" % (time.time() - start_time))
if (time.time() - start_time) >= test_time:
self.result_cntx.set_result("Succeed")
else:
self.result_cntx.set_result("Failed")
# TODO: create a function to create TCP connections. reuse not copy paste code
checker_stings = []
test_action_string = []
for i in range(sta_number + 1):
checker_stings.append("P SSC%d C CLOSEALL" % (i + 1))
test_action_string.append("SSCC SSC%d soc -T" % (i + 1))
fail_string = "Fail, Fail to close socket"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
server_port = random.randint(20000, 30000)
checker_stings = ["R SSC1 A <server_sock>:BIND:(\d+),OK"]
test_action_string = ["SSCC SSC1 soc -B -t TCP -p %s" % server_port]
fail_string = "Fail, Fail to bind socket"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
checker_stings = ["R SSC1 RE LISTEN:(\d+),OK"]
test_action_string = ["SSCC SSC1 soc -L -s <server_sock>"]
fail_string = "Fail, Fail to listen"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
checker_stings = []
test_action_string = []
for i in range(sta_number):
checker_stings.append("P SSC%d A <client_sock%d>:BIND:(\d+),OK" % (i + 2, i + 2))
test_action_string.append("SSCC SSC%d soc -B -t TCP" % (i + 2))
fail_string = "Fail, Fail to connect to server"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
for i in range(sta_number):
checker_stings = ["P SSC%d RE CONNECT:(\d+),OK" % (i + 2),
"P SSC1 A <accept_sock%d>:ACCEPT:(\d+),.+" % (i + 2)]
test_action_string = ["SSCC SSC%d soc -C -s <client_sock%d> -i %s -p %s" %
(i + 2, i + 2, ap_ip, server_port)]
fail_string = "Fail, Fail to connect to server"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
# finally, execute done
def result_check(self, port_name, data):
TCActionBase.CommonTCActionBase.result_check(self, port_name, data)
self.result_cntx.append_data(port_name, data)
def main():
pass
if __name__ == '__main__':
main()

View File

@ -0,0 +1,335 @@
import random
import re
import socket
import threading
import time
import TCPConnectionUtility
from NativeLog import NativeLog
from TCAction import PerformanceTCBase
DELAY_RANGE = [10, 3000]
CONNECTION_STRUCTURE = ("Connection handler", "PC socket", "Target socket id",
"Target port", "PC port", "PC state", "Target state")
# max fail count for one connection during test
MAX_FAIL_COUNT = 10
class CheckerBase(threading.Thread):
CHECK_ITEM = ("CONDITION", "NOTIFIER", "ID", "DATA")
SLEEP_TIME = 0.1 # sleep 100ms between each check action
def __init__(self):
threading.Thread.__init__(self)
self.setDaemon(True)
self.exit_event = threading.Event()
self.sync_lock = threading.Lock()
self.check_item_list = []
self.check_item_id = 0
def run(self):
while self.exit_event.isSet() is False:
self.process()
pass
def process(self):
pass
def add_check_item(self, condition, notifier):
with self.sync_lock:
check_item_id = self.check_item_id
self.check_item_id += 1
self.check_item_list.append(dict(zip(self.CHECK_ITEM, (condition, notifier, check_item_id, str()))))
return check_item_id
def remove_check_item(self, check_item_id):
ret = None
with self.sync_lock:
check_items = filter(lambda x: x["ID"] == check_item_id, self.check_item_list)
if len(check_items) > 0:
self.check_item_list.remove(check_items[0])
ret = check_items[0]["DATA"]
return ret
def exit(self):
self.exit_event.set()
pass
# check on serial port
class SerialPortChecker(CheckerBase):
def __init__(self, serial_reader):
CheckerBase.__init__(self)
self.serial_reader = serial_reader
pass
# check condition for serial is compiled regular expression pattern
@staticmethod
def do_check(check_item, data):
match = check_item["CONDITION"].search(data)
if match is not None:
pos = data.find(match.group()) + len(match.group())
# notify user
check_item["NOTIFIER"]("serial", match)
else:
pos = -1
return pos
def process(self):
# do check
with self.sync_lock:
# read data
new_data = self.serial_reader()
# NativeLog.add_trace_info("[debug][read data] %s" % new_data)
# do check each item
for check_item in self.check_item_list:
# NativeLog.add_trace_info("[debug][read data][ID][%s]" % check_item["ID"])
check_item["DATA"] += new_data
self.do_check(check_item, check_item["DATA"])
time.sleep(self.SLEEP_TIME)
# handle PC TCP server accept and notify user
class TCPServerChecker(CheckerBase):
def __init__(self, server_sock):
CheckerBase.__init__(self)
self.server_sock = server_sock
server_sock.settimeout(self.SLEEP_TIME)
self.accepted_socket_list = []
# check condition for tcp accepted sock is tcp source port
@staticmethod
def do_check(check_item, data):
for sock_addr_pair in data:
addr = sock_addr_pair[1]
if addr[1] == check_item["CONDITION"]:
# same port, so this is the socket that matched, notify and remove it from list
check_item["NOTIFIER"]("tcp", sock_addr_pair[0])
data.remove(sock_addr_pair)
def process(self):
# do accept
try:
client_sock, addr = self.server_sock.accept()
self.accepted_socket_list.append((client_sock, addr))
except socket.error:
pass
# do check
with self.sync_lock:
check_item_list = self.check_item_list
for check_item in check_item_list:
self.do_check(check_item, self.accepted_socket_list)
pass
# this thread handles one tcp connection.
class ConnectionHandler(threading.Thread):
CHECK_FREQ = CheckerBase.SLEEP_TIME/2
def __init__(self, utility, serial_checker, tcp_checker, connect_method, disconnect_method, test_case):
threading.Thread.__init__(self)
self.setDaemon(True)
self.utility = utility
self.connect_method = connect_method
self.disconnect_method = disconnect_method
self.exit_event = threading.Event()
# following members are used in communication with checker threads
self.serial_checker = serial_checker
self.tcp_checker = tcp_checker
self.serial_notify_event = threading.Event()
self.tcp_notify_event = threading.Event()
self.serial_result = None
self.tcp_result = None
self.serial_check_item_id = None
self.tcp_check_item_id = None
self.data_cache = None
self.fail_count = 0
self.test_case = test_case
pass
def log_error(self):
self.fail_count += 1
if self.fail_count > MAX_FAIL_COUNT:
self.test_case.error_detected()
def new_connection_structure(self):
connection = dict.fromkeys(CONNECTION_STRUCTURE, None)
connection["Connection handler"] = self
return connection
def run(self):
while self.exit_event.isSet() is False:
connection = self.new_connection_structure()
# do connect
connect_method_choice = random.choice(self.connect_method)
if self.utility.execute_tcp_method(connect_method_choice, connection) is False:
self.log_error()
# check if established
if self.utility.is_established_state(connection) is True:
time.sleep(float(random.randint(DELAY_RANGE[0], DELAY_RANGE[1]))/1000)
# do disconnect if established
disconnect_method_choice = random.choice(self.disconnect_method)
if self.utility.execute_tcp_method(disconnect_method_choice, connection) is False:
self.log_error()
# make sure target socket closed
self.utility.close_connection(connection)
time.sleep(float(random.randint(DELAY_RANGE[0], DELAY_RANGE[1]))/1000)
pass
# serial_condition: re string
# tcp_condition: target local port
def add_checkers(self, serial_condition=None, tcp_condition=None):
# cleanup
self.serial_result = None
self.tcp_result = None
self.serial_notify_event.clear()
self.tcp_notify_event.clear()
# serial_checker
if serial_condition is not None:
pattern = re.compile(serial_condition)
self.serial_check_item_id = self.serial_checker.add_check_item(pattern, self.notifier)
else:
# set event so that serial check always pass
self.serial_notify_event.set()
if tcp_condition is not None:
self.tcp_check_item_id = self.tcp_checker.add_check_item(tcp_condition, self.notifier)
else:
# set event so that tcp check always pass
self.tcp_notify_event.set()
# NativeLog.add_trace_info("[Debug] add check item %s, connection is %s" % (self.serial_check_item_id, self))
pass
def get_checker_results(self, timeout=5):
time1 = time.time()
while time.time() - time1 < timeout:
# if one type of checker is not set, its event will be set in add_checkers
if self.serial_notify_event.isSet() is True and self.tcp_notify_event.isSet() is True:
break
time.sleep(self.CHECK_FREQ)
# do cleanup
# NativeLog.add_trace_info("[Debug] remove check item %s, connection is %s" % (self.serial_check_item_id, self))
self.data_cache = self.serial_checker.remove_check_item(self.serial_check_item_id)
self.tcp_checker.remove_check_item(self.tcp_check_item_id)
# self.serial_check_item_id = None
# self.tcp_check_item_id = None
return self.serial_result, self.tcp_result
def notifier(self, typ, result):
if typ == "serial":
self.serial_notify_event.set()
self.serial_result = result
elif typ == "tcp":
self.tcp_notify_event.set()
self.tcp_result = result
def exit(self):
self.exit_event.set()
pass
class TestCase(PerformanceTCBase.PerformanceTCBase):
def __init__(self, test_case, test_env, timeout=120, log_path=None):
PerformanceTCBase.PerformanceTCBase.__init__(self, test_case, test_env,
timeout=timeout, log_path=log_path)
self.max_connection = 5
self.execute_time = 120 # execute time default 120 minutes
self.pc_ip = "pc_ip"
self.target_ip = "target_ip"
self.connect_method = ["C_01"]
self.disconnect_method = ["D_05"]
cmd_set = test_case["cmd set"]
# load param from excel
for i in range(1, len(cmd_set)):
if cmd_set[i][0] != "dummy":
cmd_string = "self." + cmd_set[i][0]
exec cmd_string
self.error_event = threading.Event()
self.serial_lock = threading.Lock()
pass
def serial_reader(self):
return self.serial_read_data("SSC1")
def send_ssc_command(self, data):
with self.serial_lock:
time.sleep(0.05)
self.serial_write_line("SSC1", data)
def error_detected(self):
self.error_event.set()
def process(self):
# parameters
max_connection = self.max_connection
execute_time = self.execute_time * 60
pc_ip = self.get_parameter(self.pc_ip)
target_ip = self.get_parameter(self.target_ip)
connect_method = self.connect_method
disconnect_method = self.disconnect_method
server_port = random.randint(30000, 50000)
# step 1, create TCP server on target and PC
# create TCP server on target
self.serial_write_line("SSC1", "soc -B -t TCP -p %s" % server_port)
match = self.check_regular_expression("SSC1", re.compile("BIND:(\d+),OK"))
if match is None:
NativeLog.add_prompt_trace("Failed to create TCP server on target")
return
target_sock_id = match.group(1)
self.serial_write_line("SSC1", "soc -L -s %s" % target_sock_id)
if self.check_response("SSC1", "+LISTEN:%s,OK" % target_sock_id) is False:
NativeLog.add_prompt_trace("Failed to create TCP server on target")
return
# create TCP server on PC
try:
server_sock = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
server_sock.bind((pc_ip, server_port))
server_sock.listen(5)
except StandardError:
NativeLog.add_prompt_trace("Failed to create TCP server on PC")
return
# step 2, create checker
serial_port_checker = SerialPortChecker(self.serial_reader)
tcp_server_checker = TCPServerChecker(server_sock)
serial_port_checker.start()
tcp_server_checker.start()
# step 3, create 5 thread and do connection
utility = TCPConnectionUtility.Utility(self, server_port, server_port, pc_ip, target_ip)
work_thread = []
for i in range(max_connection):
t = ConnectionHandler(utility, serial_port_checker, tcp_server_checker,
connect_method, disconnect_method, self)
work_thread.append(t)
t.start()
# step 4, wait and exit
self.error_event.wait(execute_time)
# close all threads
for t in work_thread:
t.exit()
t.join()
serial_port_checker.exit()
tcp_server_checker.exit()
serial_port_checker.join()
tcp_server_checker.join()
if self.error_event.isSet() is False:
# no error detected
self.set_result("Succeed")
pass
def main():
pass
if __name__ == '__main__':
main()

View File

@ -0,0 +1,251 @@
import random
import socket
import threading
from NativeLog import NativeLog
# from NativeLog import NativeLog
# make sure target do not listen on this port
ERROR_PORT = 62685
class Utility(object):
METHOD_RESULT = {"C_01": ("ESTABLISHED", "ESTABLISHED"), # target TCP peer state, PC TCP peer state
"C_02": ("SYNC_SENT", "CLOSED"),
"C_03": ("CLOSED", "CLOSED"),
"C_04": ("SYN_RCVD", "ESTABLISHED"),
"C_05": ("ESTABLISHED", "ESTABLISHED"),
"C_06": ("CLOSED", "CLOSED"),
"C_07": ("CLOSED", "CLOSED"),
"C_08": ("CLOSED", "CLOSED"),
"D_01": ("TIME_WAIT", "CLOSED"),
"D_02": ("TIME_WAIT", "TIME_WAIT"),
"D_03": ("FIN_WAIT_2", "CLOSE_WAIT"),
"D_04": ("FIN_WAIT_1", "CLOSE_WAIT"),
"D_05": ("CLOSED", "TIME_WAIT"),
"D_06": ("CLOSED", "CLOSED"),
"D_07": ("CLOSE_WAIT", "FIN_WAIT2"),
"D_08": ("TIME_WAIT", "CLOSED"), }
SOC_CLOSED_STATE = ("FIN_WAIT_1", "FIN_WAIT_2", "CLOSING", "TIME_WAIT", "LAST_ACK", "CLOSED")
SOC_CREATED_STATE = ("SYNC_RCVD", "ESTABLISHED")
SOC_SEND_DATA_STATE = ("ESTABLISHED", "CLOSE_WAIT")
SOC_ESTABLISHED_STATE = ("ESTABLISHED", )
def __init__(self, tc_action, pc_server_port, target_server_port, pc_ip, target_ip):
self.tc_action = tc_action
self.pc_server_port = pc_server_port
self.target_server_port = target_server_port
self.pc_ip = pc_ip
self.target_ip = target_ip
self.pc_close_wait_socket_list = []
self.sync_lock = threading.Lock()
pass
# create a tcp socket, return True or False
def __create_tcp_socket(self, connection):
connection_handler = connection["Connection handler"]
connection["Target port"] = random.randint(10000, 60000)
connection_handler.add_checkers("BIND:(\d+),OK,%s,%s"
% (self.target_ip, connection["Target port"]))
self.tc_action.send_ssc_command("soc -B -t TCP -i %s -p %s" % (self.target_ip, connection["Target port"]))
serial_result, tcp_result = connection_handler.get_checker_results()
if serial_result is not None:
connection["Target socket id"] = serial_result.group(1)
return True
else:
return False
# target do connect, return True or False
def __target_do_connect(self, connection, dest_ip, dest_port, timeout=20):
connection_handler = connection["Connection handler"]
connection_handler.add_checkers("CONNECT:%s,OK" % connection["Target socket id"],
connection["Target port"])
self.tc_action.send_ssc_command("soc -C -s %s -i %s -p %s"
% (connection["Target socket id"], dest_ip, dest_port))
serial_result, tcp_result = connection_handler.get_checker_results(timeout)
if serial_result is not None and tcp_result is not None:
connection["PC socket"] = tcp_result
return True
else:
return False
pass
# pc do connect, return True or False
def __pc_do_connect(self, connection, dest_ip, dest_port, timeout=20):
connection_handler = connection["Connection handler"]
sock = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
while True:
connection["PC port"] = random.randint(10000, 60000)
try:
sock.bind((self.pc_ip, connection["PC port"]))
break
except socket.error, e:
if e.errno == 10048: # socket port reuse
continue
sock.settimeout(timeout)
connection["PC socket"] = sock
connection_handler.add_checkers("ACCEPT:(\d+),\d+,%s,%s"
% (self.pc_ip, connection["PC port"]))
try:
sock.connect((dest_ip, dest_port))
except socket.error:
pass
serial_result, tcp_result = connection_handler.get_checker_results()
if serial_result is not None:
connection["Target socket id"] = serial_result.group(1)
return True
else:
return False
pass
def connect_c_01(self, connection):
if self.__create_tcp_socket(connection) is True:
return self.__target_do_connect(connection, self.pc_ip, self.pc_server_port)
else:
return False
def connect_c_02(self, connection):
if self.__create_tcp_socket(connection) is True:
return not self.__target_do_connect(connection, self.pc_ip, ERROR_PORT, timeout=5)
else:
return False
def connect_c_03(self, connection):
return False
def connect_c_04(self, connection):
return False
def connect_c_05(self, connection):
return self.__pc_do_connect(connection, self.target_ip, self.target_server_port)
def connect_c_06(self, connection):
return False
def connect_c_07(self, connection):
return not self.__pc_do_connect(connection, self.target_ip, ERROR_PORT)
def connect_c_08(self, connection):
return False
def __target_socket_close(self, connection):
connection_handler = connection["Connection handler"]
if connection["Target socket id"] is not None:
connection_handler.add_checkers("CLOSE:%s" % connection["Target socket id"])
self.tc_action.send_ssc_command("soc -T -s %s" % connection["Target socket id"])
serial_result, tcp_result = connection_handler.get_checker_results()
connection["Target socket id"] = None
else:
serial_result = None
return True if serial_result is not None else False
@staticmethod
def __pc_socket_close(connection):
connection_handler = connection["Connection handler"]
if connection["PC socket"] is not None:
connection_handler.add_checkers("CLOSED:%s" % connection["Target socket id"])
connection["PC socket"].close()
serial_result, tcp_result = connection_handler.get_checker_results()
connection["PC socket"] = None
else:
serial_result = None
return True if serial_result is not None else False
def close_d_01(self, connection):
connection["PC socket"] = None
return self.__target_socket_close(connection)
def close_d_02(self, connection):
pass
def close_d_03(self, connection):
with self.sync_lock:
self.pc_close_wait_socket_list.append(connection["PC socket"])
return self.__target_socket_close(connection)
pass
def close_d_04(self, connection):
pass
def close_d_05(self, connection):
return self.__pc_socket_close(connection)
def close_d_06(self, connection):
# target send data to PC, PC don't recv and close socket
connection_handler = connection["Connection handler"]
connection_handler.add_checkers("SEND:%s,OK" % connection["Target socket id"])
self.tc_action.send_ssc_command("soc -S -s %s -l 100" % connection["Target socket id"])
serial_result, tcp_result = connection_handler.get_checker_results()
if serial_result is None:
return False
return self.__pc_socket_close(connection)
def close_d_07(self, connection):
# PC shutdown WR
result = False
try:
connection["PC socket"].shutdown(socket.SHUT_WR)
result = True
except StandardError:
pass
return result
def close_d_08(self, connection):
pass
def close_connection(self, connection):
self.__target_socket_close(connection)
pass
TCP_ACTION_DICT = {"C_01": connect_c_01,
"C_02": connect_c_02,
"C_03": connect_c_03,
"C_04": connect_c_04,
"C_05": connect_c_05,
"C_06": connect_c_06,
"C_07": connect_c_07,
"C_08": connect_c_08,
"D_01": close_d_01,
"D_02": close_d_02,
"D_03": close_d_03,
"D_04": close_d_04,
"D_05": close_d_05,
"D_06": close_d_06,
"D_07": close_d_07,
"D_08": close_d_08,
}
def get_method_destination_state(self, method):
return self.METHOD_RESULT[method]
def execute_tcp_method(self, method, connection):
if method in self.METHOD_RESULT:
result = self.TCP_ACTION_DICT[method](self, connection)
if result is True:
state = self.get_method_destination_state(method)
connection["Target state"] = state[0]
connection["PC state"] = state[1]
else:
NativeLog.add_prompt_trace("[TCPConnection] tcp method %s fail, connection is %s"
% (method, connection))
NativeLog.add_trace_info("[TCPConnection][data cache][check item %s] %s"
% (connection["Connection handler"].serial_check_item_id,
connection["Connection handler"].data_cache))
else:
raise StandardError("Not TCP connection method")
return result
def is_established_state(self, connection):
return True if connection["Target state"] in self.SOC_CREATED_STATE else False
def is_closed_state(self, connection):
return True if connection["Target state"] in self.SOC_CLOSED_STATE else False
def main():
pass
if __name__ == '__main__':
main()

View File

@ -0,0 +1,243 @@
import os
import random
import threading
import socket
import time
import re
from TCAction import TCActionBase
from TCAction import PerformanceTCBase
from NativeLog import NativeLog
def calc_hash(index):
return (index & 0xffffffff) % 83 + (index & 0xffffffff) % 167
def verify_data(data, start_index):
for i, c in enumerate(data):
if ord(c) != calc_hash(start_index + i):
NativeLog.add_trace_critical("[Data Validation Error] target sent data index %u is error."
" Sent data is %x, should be %x"
% (start_index + i, ord(c), calc_hash(start_index + i)))
return False
return True
def make_validation_data(length, start_index):
return bytes().join([chr(calc_hash(start_index + i)) for i in range(length)])
class SendThread(threading.Thread):
def __init__(self, sock, send_len):
threading.Thread.__init__(self)
self.setDaemon(True)
self.sock = sock
self.send_len = send_len
self.exit_event = threading.Event()
pass
def exit(self):
self.exit_event.set()
def run(self):
index = 0
while self.exit_event.isSet() is False:
data = make_validation_data(self.send_len, index)
try:
self.sock.send(data)
index += self.send_len
except StandardError:
# pass but not exit thread
time.sleep(1)
continue
pass
class RecvThread(threading.Thread):
def __init__(self, sock):
threading.Thread.__init__(self)
self.setDaemon(True)
self.sock = sock
self.exit_event = threading.Event()
def exit(self):
self.exit_event.set()
def run(self):
index = 0
while self.exit_event.isSet() is False:
if self.sock is not None:
try:
data = self.sock.recv(8*1024)
except StandardError, e:
NativeLog.add_exception_log(e)
NativeLog.add_trace_critical("recv error, connection closed")
break
if verify_data(data, index) is not True:
break
index += len(data)
else:
time.sleep(1)
pass
class ValidationThread(threading.Thread):
def __init__(self, tc_action):
threading.Thread.__init__(self)
self.setDaemon(True)
self.tc_action = tc_action
self.exit_event = threading.Event()
def exit(self):
self.exit_event.set()
def run(self):
while self.exit_event.isSet() is False:
if self.tc_action.check_response("SSC1", "DATA_ERROR", 5) is True:
NativeLog.add_trace_critical("[Data Validation Error] target recv data error")
break
pass
class TestCase(PerformanceTCBase.PerformanceTCBase):
def __init__(self, test_case, test_env, timeout=30, log_path=TCActionBase.LOG_PATH):
PerformanceTCBase.PerformanceTCBase.__init__(self, test_case, test_env, timeout=timeout, log_path=log_path)
self.send_len = 0
self.tx_enable = None
self.rx_enable = None
self.conn_num = 0
self.test_time = 0
# load param from excel
cmd_set = test_case["cmd set"]
for i in range(1, len(cmd_set)):
if cmd_set[i][0] != "dummy":
cmd_string = "self." + cmd_set[i][0]
exec cmd_string
pass
def execute(self):
TCActionBase.TCActionBase.execute(self)
try:
# configurable params
send_len = self.send_len
tx_enable = self.tx_enable
rx_enable = self.rx_enable
conn_num = self.conn_num
test_time = self.test_time * 60 # convert minutes to seconds
# configurable params
except StandardError, e:
NativeLog.add_trace_critical("Error configuration for TCPThroughput script, error is %s" % e)
raise StandardError("Error configuration")
# init throughput result data
test_item = ""
if tx_enable is True:
test_item += "Tx"
if rx_enable is True:
test_item += "Rx"
if test_item == "":
raise StandardError("no throughput test item")
pc_ip = self.get_parameter("pc_ip")
tcp_port = random.randint(10000, 50000)
# disable recv print during throughput test
self.serial_write_line("SSC1", "soc -R -o 0")
if self.check_response("SSC1", "+RECVPRINT", 2) is False:
NativeLog.add_trace_critical("Fail, Fail to disable recv print")
# create server
server_sock = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
server_sock.bind((pc_ip, tcp_port))
server_sock.settimeout(5)
server_sock.listen(5)
sock_id_list = []
send_thread_list = []
recv_thread_list = []
# step 4 create tcp connection
for i in range(conn_num):
self.serial_write_line("SSC1", "soc -B -t TCP")
match = self.check_regular_expression("SSC1", re.compile("\+BIND:(\d+),OK"), 2)
if match is None:
NativeLog.add_trace_critical("Fail, Fail to bind")
return
else:
sock_id_list.append(int(match.group(1)))
self.serial_write_line("SSC1", "soc -V -s %s -o 3" % sock_id_list[-1])
if self.check_regular_expression("SSC1", re.compile("\+DATA_VALIDATION:\d+,OK"), 2) is None:
NativeLog.add_trace_critical("Fail, Failed to enable validation")
return
self.serial_write_line("SSC1", "soc -C -s %s -i %s -p %s" % (sock_id_list[-1], pc_ip, tcp_port))
try:
sock, addr = server_sock.accept()
except socket.error, e:
NativeLog.add_trace_critical("%s" % e)
raise e
if self.check_regular_expression("SSC1", re.compile("\+CONNECT:\d+,OK"), 5) is None:
NativeLog.add_trace_critical("Fail, Failed to connect")
return
sock.settimeout(10)
send_thread_list.append(SendThread(sock if rx_enable is True else None, send_len))
recv_thread_list.append(RecvThread(sock if tx_enable is True else None))
recv_thread_list[-1].start()
# step 5 do test
validation_thread = ValidationThread(self)
validation_thread.start()
for send_thread in send_thread_list:
send_thread.start()
if tx_enable is True:
# do send from target
for sock_id in sock_id_list:
self.serial_write_line("SSC1", "soc -S -s %s -l %s -n 10000000" % (sock_id, send_len))
time1 = time.time()
exit_flag = False
while time.time() - time1 < test_time and exit_flag is False:
for i in sock_id_list:
send_thread_list[i].join(0.5)
recv_thread_list[i].join(0.5)
validation_thread.join(0.5)
if send_thread_list[i].isAlive() is False \
or recv_thread_list[i].isAlive() is False \
or validation_thread.isAlive() is False:
NativeLog.add_trace_critical("validation error found")
exit_flag = True
break
NativeLog.add_prompt_trace("time escape: %s" % (time.time() - time1))
if time.time() - time1 >= test_time:
self.set_result("Succeed")
else:
self.set_result("Failed")
# exit all thread
for i in sock_id_list:
send_thread_list[i].exit()
recv_thread_list[i].exit()
send_thread_list[i].join()
send_thread_list[i].join()
validation_thread.exit()
validation_thread.join()
def main():
pass
if __name__ == '__main__':
main()

View File

@ -0,0 +1,165 @@
from TCAction import TCActionBase
from NativeLog import NativeLog
import time
import random
import string
TEST_COUNT_ONE_ROUND = 500
class TestCase(TCActionBase.CommonTCActionBase):
def __init__(self, test_case, test_env, timeout=45, log_path=TCActionBase.LOG_PATH):
TCActionBase.CommonTCActionBase.__init__(self, test_case, test_env, timeout=timeout, log_path=log_path)
# load param from excel
cmd_set = test_case["cmd set"]
for i in range(1, len(cmd_set)):
if cmd_set[i][0] != "dummy":
cmd_string = "self." + cmd_set[i][0]
exec cmd_string
self.result_cntx = TCActionBase.ResultCheckContext(self, test_env, self.tc_name)
pass
def execute(self):
TCActionBase.TCActionBase.execute(self)
self.result_cntx.start()
try:
# configurable params
send_len = self.send_len
test_time = self.test_time * 60
server_echo = self.server_echo
sta_number = self.sta_number
send_delay = self.send_delay
# configurable params
except StandardError, e:
NativeLog.add_trace_critical("Error configuration for TCPTransparent script, error is %s" % e)
raise StandardError("Error configuration")
# step0 reboot
for i in range(sta_number + 1):
checker_stings = ["P SSC%d C ready!!!" % (i + 1)]
test_action_string = ["SSCC SSC%d restore" % (i + 1)]
fail_string = "Fail, Fail to restore"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
# turn off recv print
for i in range(sta_number + 1):
checker_stings = ["P SSC%d C +RECVPRINT:0" % (i + 1)]
test_action_string = ["SSCC SSC%d soc -R -o 0" % (i + 1)]
fail_string = "Fail, Fail to turn off recv print"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
# step1, set softap mode on SSC1
checker_stings = ["R SSC1 C +MODE:OK"]
test_action_string = ["SSCC SSC1 op -S -o 2"]
fail_string = "Fail, Fail to set mode on SSC1"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
# step2, set STA mode on SSC2-SSCn
for i in range(sta_number):
checker_stings = ["R SSC%d C +MODE:OK" % (i + 2)]
test_action_string = ["SSCC SSC%d op -S -o 1" % (i + 2)]
fail_string = "Fail, Fail to set mode on SSC%d" % (i + 2)
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
ssid = "".join([random.choice(string.lowercase) for m in range(10)])
password = "".join([random.choice(string.lowercase) for m in range(10)])
tcp_port = random.randint(40000, 50000)
# step3, set ssid/password on SSC1
checker_stings = ["R SSC1 C +SAP:OK"]
test_action_string = ["SSCC SSC1 ap -S -s %s -p %s -n 10 -t 0 -m 10" % (ssid, password)]
fail_string = "Fail, Fail to set ssid/password on SSC1"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
# step4, SSC2-SSCn join SSC1(soft AP)
for i in range(sta_number):
checker_stings = ["P SSC%d C +JAP:CONNECTED,%s" % (i + 2, ssid)]
test_action_string = ["SSCC SSC%d ap -C -s %s -p %s" % (i + 2, ssid, password)]
fail_string = "Fail, SSC%d Fail to connect to SSC1" % (i + 2)
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string, check_time=450) is False:
return
# step5, create server on SSC2
checker_stings = ["R SSC2 A <server_sock>:BIND:(\d+),OK"]
test_action_string = ["SSCC SSC2 soc -B -t TCP -p %s" % tcp_port]
fail_string = "Fail, Fail to create server on SSC2 while binding"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
checker_stings = ["R SSC2 RE LISTEN:(\d+),OK"]
test_action_string = ["SSCC SSC2 soc -L -s <server_sock>"]
fail_string = "Fail, Fail to create server on SSC2 while listening"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
# step6, create client on SSC3-SSCn
for i in range(sta_number - 1):
checker_stings = ["P SSC%d A <client_sock%d>:BIND:(\d+),OK" % (i + 3, i + 3)]
test_action_string = ["SSCC SSC%d soc -B -t TCP" % (i + 3)]
fail_string = "Fail, SSC%d Fail to connect to TCP server while binding" % (i + 3)
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
for i in range(sta_number - 1):
checker_stings = ["P SSC%d RE CONNECT:(\d+),OK" % (i + 3), "P SSC2 A <accept_sock%d>:ACCEPT:(\d+),.+" % i]
test_action_string = [
"SSCC SSC%d soc -C -s <client_sock%d> -i 192.168.4.2 -p %s" % (i + 3, i + 3, tcp_port)]
fail_string = "Fail, SSC%d Fail to connect to TCP server while connecting" % (i + 3)
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
start_time = time.time()
# step7, do send/recv, SSC2<---->other STAs
while time.time() - start_time < test_time:
checker_stings = []
test_action_string = []
# SSC2 send packets to SSC3-SSCn
if server_echo is True:
for i in range(sta_number - 1):
test_action_string.append("SSC SSC2 soc -S -s <accept_sock%d> -l %d -n 1000 -j %d" %
(i, send_len, send_delay))
checker_stings.append(
"P SSC2 RE \+SEND:%s,OK NC CLOSED NC ERROR" % self.get_parameter("accept_sock%d" % (i + 3)))
# SSC3-SSCn send packets to SSC2
for i in range(sta_number - 1):
checker_stings.append(
"P SSC%d RE \+SEND:%s,OK NC CLOSED NC ERROR" % (i + 3, self.get_parameter("client_sock%d" % i)))
test_action_string.append("SSC SSC%d soc -S -s <client_sock%d> -l %d -n 1000 -j %d" %
(i + 3, i + 3, send_len, send_delay))
fail_string = "Fail, Failed to send/recv data"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string,
check_freq=1, check_time=900) is False:
break
# drop off the delay time if it's greater than 20ms
if send_delay > 20:
send_delay -= 10
NativeLog.add_trace_critical("Time escape: %d" % (time.time() - start_time))
if (time.time() - start_time) >= test_time:
self.result_cntx.set_result("Succeed")
else:
self.result_cntx.set_result("Failed")
# finally, execute done
def result_check(self, port_name, data):
TCActionBase.CommonTCActionBase.result_check(self, port_name, data)
self.result_cntx.append_data(port_name, data)
def main():
pass
if __name__ == '__main__':
main()

View File

@ -0,0 +1,109 @@
import os
import time
import random
import threading
import socket
from TCAction import TCActionBase
from NativeLog import NativeLog
from NativeLog import ThroughputResult
class TestCase(TCActionBase.CommonTCActionBase):
def __init__(self, test_case, test_env, timeout=30, log_path=TCActionBase.LOG_PATH):
TCActionBase.CommonTCActionBase.__init__(self, test_case, test_env, timeout=timeout, log_path=log_path)
self.send_len_config = range(1460)
self.delay_config = [0, 0.01, 0.1, 0.5, 1]
# load param from excel
cmd_set = test_case["cmd set"]
for i in range(1, len(cmd_set)):
if cmd_set[i][0] != "dummy":
cmd_string = "self." + cmd_set[i][0]
exec cmd_string
self.result_cntx = TCActionBase.ResultCheckContext(self, test_env, self.tc_name)
pass
def execute(self):
TCActionBase.TCActionBase.execute(self)
self.result_cntx.start()
try:
# configurable params
send_len_config = self.send_len_config
delay_config = self.delay_config
send_count = self.send_count
test_time = self.test_time * 60
# configurable params
except StandardError, e:
NativeLog.add_trace_critical("Error configuration for TCPThroughput script, error is %s" % e)
raise StandardError("Error configuration")
# disable recv print during random send test
checker_stings = ["R SSC1 C +RECVPRINT"]
test_action_string = ["SSC SSC1 soc -R -o 0"]
fail_string = "Fail, Fail to disable recv print"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
pc_ip = self.get_parameter("pc_ip")
tcp_port = random.randint(50000, 60000)
# step 0 create tcp connection
server_sock = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
server_sock.bind((pc_ip, tcp_port))
server_sock.settimeout(1)
server_sock.listen(5)
checker_stings = ["R SSC1 A <client_sock>:\+BIND:(\d+),OK"]
test_action_string = ["SSC SSC1 soc -B -t TCP"]
fail_string = "Fail, Fail bind"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
checker_stings = ["P SSC1 RE \+CONNECT:\d+,OK"]
test_action_string = ["SSC SSC1 soc -C -s <client_sock> -i %s -p %s" % (pc_ip, tcp_port)]
fail_string = "Fail, Fail to connect"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
sock, addr = server_sock.accept()
sock.settimeout(10)
# set no delay so that tcp segment will be send as soon as send called
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
# step 1 start send
start_time = time.time()
while time.time() - start_time < test_time:
for delay in delay_config:
for i in xrange(send_count):
send_len = random.choice(send_len_config)
data = "A" * (send_len+1)
try:
sock.send(data)
except socket.error, e:
NativeLog.add_exception_log(e)
NativeLog.add_trace_critical("Fail to send packets")
return
pass
time.sleep(delay)
NativeLog.add_prompt_trace("time escape: %s" % (time.time() - start_time))
if (time.time() - start_time) > test_time:
self.result_cntx.set_result("Succeed")
else:
self.result_cntx.set_result("Failed")
# finally, execute done
def result_check(self, port_name, data):
TCActionBase.CommonTCActionBase.result_check(self, port_name, data)
self.result_cntx.append_data(port_name, data)
def main():
pass
if __name__ == '__main__':
main()

View File

@ -0,0 +1,159 @@
from TCAction import TCActionBase
from NativeLog import NativeLog
import time
import random
import string
class TestCase(TCActionBase.CommonTCActionBase):
def __init__(self, test_case, test_env, timeout=45, log_path=TCActionBase.LOG_PATH):
TCActionBase.CommonTCActionBase.__init__(self, test_case, test_env, timeout, log_path)
# load param from excel
cmd_set = test_case["cmd set"]
for i in range(1, len(cmd_set)):
if cmd_set[i][0] != "dummy":
cmd_string = "self." + cmd_set[i][0]
exec cmd_string
self.result_cntx = TCActionBase.ResultCheckContext(self, test_env, self.tc_name)
pass
def execute(self):
TCActionBase.TCActionBase.execute(self)
self.result_cntx.start()
try:
# configurable params
send_len = self.send_len
server_echo = self.server_echo
conn_number = self.conn_number
sta_number = self.sta_number
test_time = self.test_time
send_delay = self.send_delay
# configurable params
except StandardError, e:
NativeLog.add_trace_critical("Error configuration for TCPTransparent script, error is %s" % e)
raise StandardError("Error configuration")
# step0 reboot
for i in range(sta_number + 1):
checker_stings = ["P SSC%d C !!!ready!!!" % (i + 1)]
test_action_string = ["SSCC SSC%d reboot" % (i + 1)]
fail_string = "Fail, Fail to reboot"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
# step1, set ap mode on SSC1, set STA mode on SSC2-SSC3
checker_stings = ["R SSC1 C +MODE:OK"]
test_action_string = ["SSCC SSC1 op -S -o 2"]
fail_string = "Fail, Fail to set mode on SSC1"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
for i in range(sta_number):
checker_stings = ["R SSC%d C +MODE:OK" % (i + 2)]
test_action_string = ["SSCC SSC%d op -S -o 1" % (i + 2)]
fail_string = "Fail, Fail to set mode on SSC%d" % (i + 2)
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
# turn off recv print
for i in range(sta_number + 1):
checker_stings = ["P SSC%d C +RECVPRINT:0" % (i + 1)]
test_action_string = ["SSCC SSC%d soc -R -o 0" % (i + 1)]
fail_string = "Fail, Fail to turn off recv print"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
# step2, set ssid/password on SSC1
ssid = "".join([random.choice(string.lowercase) for m in range(10)])
password = "".join([random.choice(string.lowercase) for m in range(10)])
tcp_port = random.randint(10000, 20000)
checker_stings = ["R SSC1 C +SAP:OK"]
test_action_string = ["SSCC SSC1 ap -S -s %s -p %s -t 3 -m 8" % (ssid, password)]
fail_string = "Fail, Fail to set ssid/password on SSC1"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
# step3, SSC2-SSC3 connect to SSC1
checker_stings = []
test_action_string = []
for i in range(sta_number):
checker_stings.append("P SSC%d C +JAP:CONNECTED,%s" % (i + 2, ssid))
test_action_string.append("SSCC SSC%d ap -C -s %s -p %s" % (i + 2, ssid, password))
fail_string = "Fail, SSC%d Fail to connect to SoftAP" % (i + 2)
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string, check_time=450) is False:
return
# step4, create tcp server on STA SSC2
checker_stings = ["R SSC2 A <server_sock>:BIND:(\d+),OK"]
test_action_string = ["SSCC SSC2 soc -B -t TCP -p %s" % tcp_port]
fail_string = "Fail, Fail to create server on SSC2 while binding"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
checker_stings = ["R SSC2 RE LISTEN:(\d+),OK"]
test_action_string = ["SSCC SSC2 soc -L -s <server_sock>"]
fail_string = "Fail, Fail to create server on SSC2 while listening"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
# step5, create multi client on SSC3
for i in range(conn_number):
checker_stings = ["P SSC3 A <client_sock%d>:BIND:(\d+),OK" % i]
test_action_string = ["SSCC SSC3 soc -B -t TCP"]
fail_string = "Fail, Fail to create client on SSC3"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
checker_stings = ["P SSC3 RE CONNECT:(\d+),OK", "P SSC2 A <accept_sock%d>:ACCEPT:(\d+),.+" % i]
test_action_string = ["SSCC SSC3 soc -C -s <client_sock%d> -i %s -p %s" % (i, "192.168.4.2", tcp_port)]
fail_string = "Fail, Fail to connect to SSC2 server while connecting"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
start_time = time.time()
# step6, do send/recv
while time.time() - start_time < test_time:
checker_stings = []
test_action_string = []
# SSC2 send packets to SSC3
if server_echo is True:
for i in range(conn_number):
checker_stings.append("P SSC2 RE \+SEND:\d+,OK NC CLOSED NC ERROR")
test_action_string.append("SSC SSC2 soc -S -s <accept_sock%d> -l %d -n 1000 -j %d" %
(i, send_len, send_delay))
# SSC3 send packets to SSC2
for i in range(conn_number):
test_action_string.append("SSC SSC3 soc -S -s <client_sock%d> -l %d -n 1000 -j %d" %
(i, send_len, send_delay))
checker_stings.append("P SSC3 RE \+SEND:\d+,OK NC CLOSED NC ERROR")
fail_string = "Fail, Failed to send/recv data"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string,
check_freq=1, check_time=600) is False:
break
if send_delay > 20:
send_delay -= 10
NativeLog.add_trace_critical("Time escape: %d" % (time.time() - start_time))
if (time.time() - start_time) > test_time:
self.result_cntx.set_result("Succeed")
else:
self.result_cntx.set_result("Failed")
# finally, execute done
def result_check(self, port_name, data):
TCActionBase.CommonTCActionBase.result_check(self, port_name, data)
self.result_cntx.append_data(port_name, data)
def main():
pass
if __name__ == '__main__':
main()

View File

@ -0,0 +1,167 @@
from TCAction import TCActionBase
from NativeLog import NativeLog
import time
import random
import string
class TestCase(TCActionBase.CommonTCActionBase):
def __init__(self, test_case, test_env, timeout=45, log_path=TCActionBase.LOG_PATH):
TCActionBase.CommonTCActionBase.__init__(self, test_case, test_env, timeout, log_path)
# load param from excel
cmd_set = test_case["cmd set"]
for i in range(1, len(cmd_set)):
if cmd_set[i][0] != "dummy":
cmd_string = "self." + cmd_set[i][0]
exec cmd_string
self.result_cntx = TCActionBase.ResultCheckContext(self, test_env, self.tc_name)
pass
def execute(self):
TCActionBase.TCActionBase.execute(self)
self.result_cntx.start()
try:
# configurable params
send_len = self.send_len
server_echo = self.server_echo
conn_number = self.conn_number
sta_number = self.sta_number
test_time = self.test_time * 60
send_delay = self.send_delay
# configurable params
except StandardError, e:
NativeLog.add_trace_critical("Error configuration for TCPTransparent script, error is %s" % e)
raise StandardError("Error configuration")
# step0 reboot
for i in range(sta_number + 1):
checker_stings = ["P SSC%d C ready!!!" % (i + 1)]
test_action_string = ["SSCC SSC%d restore" % (i + 1)]
fail_string = "Fail, Fail to restore"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
# step1, set ap mode on SSC1, set STA mode on SSC2-SSC3
checker_stings = ["R SSC1 C +MODE:OK"]
test_action_string = ["SSCC SSC1 op -S -o 2"]
fail_string = "Fail, Fail to set mode on SSC1"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
for i in range(sta_number):
checker_stings = ["R SSC%d C +MODE:OK" % (i + 2)]
test_action_string = ["SSCC SSC%d op -S -o 1" % (i + 2)]
fail_string = "Fail, Fail to set mode on SSC%d" % (i + 2)
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
# turn off recv print
for i in range(sta_number + 1):
checker_stings = ["P SSC%d C +RECVPRINT:0" % (i + 1)]
test_action_string = ["SSCC SSC%d soc -R -o 0" % (i + 1)]
fail_string = "Fail, Fail to turn off recv print"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
# step2, set ssid/password on SSC1
ssid = "".join([random.choice(string.lowercase) for m in range(10)])
password = "".join([random.choice(string.lowercase) for m in range(10)])
tcp_port = random.randint(10000, 20000)
checker_stings = ["R SSC1 C +SAP:OK"]
test_action_string = ["SSCC SSC1 ap -S -s %s -p %s -n 10 -t 0 -m 10" % (ssid, password)]
fail_string = "Fail, Fail to set ssid/password on SSC1"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
# step3, SSC2-SSC3 connect to SSC1
checker_stings = []
test_action_string = []
for i in range(sta_number):
checker_stings.append("P SSC%d C +JAP:CONNECTED,%s" % (i + 2, ssid))
test_action_string.append("SSCC SSC%d ap -C -s %s -p %s" % (i + 2, ssid, password))
fail_string = "Fail, SSC%d Fail to connect to SoftAP" % (i + 2)
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string, check_time=450) is False:
return
# step4, create tcp server on STA SSC2
checker_stings = ["R SSC2 A <server_sock>:BIND:(\d+),OK"]
test_action_string = ["SSCC SSC2 soc -B -t TCP -p %s" % tcp_port]
fail_string = "Fail, Fail to create server on SSC2 while binding"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
checker_stings = ["R SSC2 RE LISTEN:(\d+),OK"]
test_action_string = ["SSCC SSC2 soc -L -s <server_sock>"]
fail_string = "Fail, Fail to create server on SSC2 while listening"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
# step5, create multi client on SSC3
for i in range(conn_number):
checker_stings = ["P SSC3 A <client_sock%d>:BIND:(\d+),OK" % i]
test_action_string = ["SSCC SSC3 soc -B -t TCP"]
fail_string = "Fail, Fail to create client on SSC3"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
checker_stings = ["P SSC3 RE CONNECT:(\d+),OK", "P SSC2 A <accept_sock%d>:ACCEPT:(\d+),.+ NC ERROR" % i]
test_action_string = ["SSCC SSC3 soc -C -s <client_sock%d> -i %s -p %s" % (i, "192.168.4.2", tcp_port)]
fail_string = "Fail, Fail to connect to SSC2 server while connecting"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
start_time = time.time()
# step6, do send/recv
while time.time() - start_time < test_time:
checker_stings = []
test_action_string = []
# SSC2 send packets to SSC3
if server_echo is True:
for i in range(conn_number):
checker_stings.append(
"P SSC2 RE \+SEND:%s,OK NC CLOSED NC ERROR NC unexpected" % self.get_parameter(
"accept_sock%d" % i))
test_action_string.append("SSC SSC2 soc -S -s <accept_sock%d> -l %d -n 1000 -j %d" %
(i, send_len, send_delay))
# SSC3 send packets to SSC2
for i in range(conn_number):
test_action_string.append("SSC SSC3 soc -S -s <client_sock%d> -l %d -n 1000 -j %d" %
(i, send_len, send_delay))
checker_stings.append(
"P SSC3 RE \+SEND:%s,OK NC CLOSED NC ERROR" % self.get_parameter("client_sock%d" % i))
fail_string = "Fail, Failed to send/recv data"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string,
check_freq=1, check_time=900) is False:
# checker_stings = ["R SSC1 C +LSTADONE"]
# test_action_string = ["SSCC SSC1 ap -L"]
# fail_string = ""
# if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
# pass
break
if send_delay > 20:
send_delay -= 10
NativeLog.add_trace_critical("Time escape: %d" % (time.time() - start_time))
if (time.time() - start_time) > test_time:
self.result_cntx.set_result("Succeed")
else:
self.result_cntx.set_result("Failed")
# finally, execute done
def result_check(self, port_name, data):
TCActionBase.CommonTCActionBase.result_check(self, port_name, data)
self.result_cntx.append_data(port_name, data)
def main():
pass
if __name__ == '__main__':
main()

View File

@ -0,0 +1,154 @@
from TCAction import TCActionBase
from NativeLog import NativeLog
import time
import random
import string
TEST_COUNT_ONE_ROUND = 1000
class TestCase(TCActionBase.CommonTCActionBase):
def __init__(self, test_case, test_env, timeout=30, log_path=TCActionBase.LOG_PATH):
TCActionBase.CommonTCActionBase.__init__(self, test_case, test_env, timeout=timeout, log_path=log_path)
# load param from excel
cmd_set = test_case["cmd set"]
for i in range(1, len(cmd_set)):
if cmd_set[i][0] != "dummy":
cmd_string = "self." + cmd_set[i][0]
exec cmd_string
self.result_cntx = TCActionBase.ResultCheckContext(self, test_env, self.tc_name)
pass
def cleanup(self):
# step 0 turn on recv print
checker_stings = ["P SSC1 C +RECVPRINT:1", "P SSC2 C +RECVPRINT:1"]
test_action_string = ["SSC SSC1 soc -R -o 1", "SSC SSC2 soc -R -o 1"]
fail_string = "Fail, Fail to turn on recv print"
self.load_and_exe_one_step(checker_stings, test_action_string, fail_string)
pass
def execute(self):
TCActionBase.TCActionBase.execute(self)
self.result_cntx.start()
try:
# configurable params
send_len = self.send_len
test_time = self.test_time * 60
duplex = self.duplex
conn_num = self.conn_num
send_delay = self.send_delay
# configurable params
except StandardError, e:
NativeLog.add_trace_critical("Error configuration for TCPSendRecv script, error is %s" % e)
raise StandardError("Error configuration")
ssid = "".join([random.choice(string.lowercase) for m in range(10)])
password = "".join([random.choice(string.lowercase) for m in range(10)])
tcp_port = random.randint(10000, 50000)
# step 0 set ap
checker_stings = ["R SSC1 C +SAP:OK"]
test_action_string = ["SSC SSC1 ap -S -s %s -p %s -t 3" % (ssid, password)]
fail_string = "Fail, Fail to set ap"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
self.result_cntx.set_result("Fail")
return
# step 1 connect to ap and turn off recv print
checker_stings = ["R SSC2 C +JAP:CONNECTED"]
test_action_string = ["SSC SSC2 sta -C -s %s -p %s" % (ssid, password)]
fail_string = "Fail, Fail to connect to server"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string, check_time=200) is False:
self.result_cntx.set_result("Fail")
return
checker_stings = ["P SSC1 C +RECVPRINT:0", "P SSC2 C +RECVPRINT:0"]
test_action_string = ["SSC SSC1 soc -R -o 0", "SSC SSC2 soc -R -o 0"]
fail_string = "Fail, Fail to turn off recv print"
self.load_and_exe_one_step(checker_stings, test_action_string, fail_string)
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string, check_time=200) is False:
self.result_cntx.set_result("Fail")
return
# step 2 create server on AP
checker_stings = ["R SSC1 A <server_sock>:\+BIND:(\d+),OK"]
test_action_string = ["SSC SSC1 soc -B -t TCP -p %s" % tcp_port]
fail_string = "Fail, Fail to create server"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
self.result_cntx.set_result("Fail")
return
checker_stings = ["R SSC1 A <server_sock>:\+LISTEN:(\d+),OK"]
test_action_string = ["SSC SSC1 soc -L -s <server_sock>"]
fail_string = "Fail, Fail to create server"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
self.result_cntx.set_result("Fail")
return
# step 3 create conn_num tcp connections
for i in range(conn_num):
checker_stings = ["R SSC2 A <client_sock%s>:\+BIND:(\d+),OK" % i]
test_action_string = ["SSC SSC2 soc -B -t TCP"]
fail_string = "Fail, Fail to bind"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
self.result_cntx.set_result("Fail")
return
checker_stings = ["P SSC1 A <accept_sock%s>:\+ACCEPT:(\d+),\d+" % i,
"P SSC2 RE \+CONNECT:\d+,OK"]
test_action_string = ["SSC SSC2 soc -C -s <client_sock%s> -i <target_ap_ip> -p %s" % (i, tcp_port)]
fail_string = "Fail, Fail to connect"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
self.result_cntx.set_result("Fail")
return
start_time = time.time()
# step 4, do send/recv
while time.time()-start_time < test_time:
checker_stings = ["P SSC1 NC ERROR NC CLOSE NC ERROR"]
for i in range(conn_num):
test_action_string = ["SSC SSC2 soc -S -s <client_sock%d> -l %d -n %d -j %d" %
(i, send_len, TEST_COUNT_ONE_ROUND, send_delay)]
checker_stings.append("P SSC2 RE \"\+SEND:%%%%s,OK\"%%%%(<client_sock%d>) NC ERROR NC CLOSE" % i)
if duplex is True:
checker_stings.append("P SSC1 RE \"\+SEND:%%%%s,OK\"%%%%(<accept_sock%d>)" % i)
test_action_string.append("SSC SSC1 soc -S -s <accept_sock%d> -l %d -n %d -j %d" %
(i, send_len, TEST_COUNT_ONE_ROUND, send_delay))
fail_string = "Fail, Failed on send command"
if self.load_and_exe_one_step([], test_action_string, fail_string) is False:
self.result_cntx.set_result("Fail")
break
fail_string = "Fail, Failed to send/recv data"
if self.load_and_exe_one_step(checker_stings, ["DELAY 0.1"], fail_string,
check_freq=1, check_time=300) is False:
NativeLog.add_prompt_trace("time escape: %s" % (time.time() - start_time))
self.result_cntx.set_result("Fail")
return
NativeLog.add_prompt_trace("time escape: %s" % (time.time() - start_time))
if (time.time() - start_time) >= test_time:
self.result_cntx.set_result("Succeed")
else:
self.result_cntx.set_result("Failed")
# finally, execute done
def result_check(self, port_name, data):
TCActionBase.CommonTCActionBase.result_check(self, port_name, data)
self.result_cntx.append_data(port_name, data)
def main():
pass
if __name__ == '__main__':
main()

View File

@ -0,0 +1,339 @@
from TCAction import TCActionBase
from NativeLog import NativeLog
import time
import random
import string
TEST_COUNT_ONE_ROUND = 500
class TestCase(TCActionBase.CommonTCActionBase):
def __init__(self, test_case, test_env, timeout=45, log_path=TCActionBase.LOG_PATH):
TCActionBase.CommonTCActionBase.__init__(self, test_case, test_env,
timeout=timeout, log_path=log_path)
self.send_len = 1460
self.server_port = random.randint(10000, 50000)
self.server_port_2 = random.randint(10000, 50000)
self.server_echo = True
self.test_time = 12 * 60
self.sta_number = 3
self.send_delay = 50
# load param from excel
cmd_set = test_case["cmd set"]
for i in range(1, len(cmd_set)):
if cmd_set[i][0] != "dummy":
cmd_string = "self." + cmd_set[i][0]
exec cmd_string
self.result_cntx = TCActionBase.ResultCheckContext(self, test_env, self.tc_name)
pass
def cleanup(self):
checker_stings = []
test_action_strings = []
for i in range(self.sta_number + 2):
checker_stings.append("R SSC%s C +RECVPRINT:1" % (i+1))
test_action_strings.append("SSC SSC%s soc -R -o 1" % (i+1))
fail_string = "Fail, Fail to turn on recv print"
self.load_and_exe_one_step(checker_stings, test_action_strings, fail_string)
pass
def execute(self):
TCActionBase.TCActionBase.execute(self)
self.result_cntx.start()
try:
# configurable params
send_len = self.send_len
test_time = self.test_time * 60
# server port
server_port = self.server_port
server_port_t = self.server_port_2
# ap ip
# ap_ip = self.ap_ip
# server echo
server_echo = self.server_echo
# station number
sta_number = self.sta_number
# send delay
send_delay = self.send_delay
# configurable params
except StandardError, e:
NativeLog.add_trace_critical("Error configuration for TCPTransparent script, error is %s" % e)
raise StandardError("Error configuration")
# step0 reboot
checker_stings = []
test_action_string = []
for i in range(sta_number + 2):
checker_stings.append("P SSC%d C !!!ready!!!" % (i + 1))
test_action_string.append("SSCC SSC%d reboot" % (i + 1))
fail_string = "Fail, Fail to reboot"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
# switch off recv print
checker_stings = []
test_action_strings = []
for i in range(self.sta_number + 2):
checker_stings.append("R SSC%s C +RECVPRINT:0" % (i+1))
test_action_strings.append("SSC SSC%s soc -R -o 0" % (i+1))
fail_string = "Fail, Fail to turn off recv print"
self.load_and_exe_one_step(checker_stings, test_action_strings, fail_string)
# step1, set ap/STA mode on all target
for i in range(sta_number + 2):
checker_stings = ["R SSC%d C +MODE:OK" % (i + 1)]
test_action_string = ["SSCC SSC%d op -S -o 3" % (i + 1)]
fail_string = "Fail, Fail to set mode on SSC%d" % (i + 1)
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
# set different getway for SSC1 softAP
checker_stings = ["R SSC1 C +DHCP:AP,OK"]
test_action_string = ["SSCC SSC1 dhcp -E -o 2"]
fail_string = "Fail, SSC1 Fail to disable DHCP"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
checker_stings = ["R SSC1 C +IP:OK"]
test_action_string = ["SSCC SSC1 ip -S -o 2 -i 192.168.6.1"]
fail_string = "Fail, SSC1 Fail to set IP"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
checker_stings = ["R SSC1 C +DHCP:AP,OK"]
test_action_string = ["SSCC SSC1 dhcp -S -o 2"]
fail_string = "Fail, SSC1 Fail to enable DHCP"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
# set different getway for SSC2 softAP
checker_stings = ["R SSC2 C +DHCP:AP,OK"]
test_action_string = ["SSCC SSC2 dhcp -E -o 2"]
fail_string = "Fail, SSC2 Fail to disable DHCP"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
checker_stings = ["R SSC2 C +IP:OK"]
test_action_string = ["SSCC SSC2 ip -S -o 2 -i 192.168.5.1"]
fail_string = "Fail, SSC2 Fail to set IP"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
checker_stings = ["R SSC2 C +DHCP:AP,OK"]
test_action_string = ["SSCC SSC2 dhcp -S -o 2"]
fail_string = "Fail, SSC2 Fail to enable DHCP"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
# step2, set ssid/password on SSC1
ssid = "".join([random.choice(string.lowercase) for m in range(10)])
password = "".join([random.choice(string.lowercase) for m in range(10)])
checker_stings = ["R SSC1 C +SAP:OK"]
test_action_string = ["SSCC SSC1 ap -S -s %s -p %s -n 10 -t 0 -m 8" % (ssid, password)]
fail_string = "Fail, Fail to set ssid/password on SSC1"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
# step3, set ssid/password on SSC2
ssid_1 = "".join([random.choice(string.lowercase) for m in range(10)])
password_1 = "".join([random.choice(string.lowercase) for m in range(10)])
checker_stings = ["R SSC2 C +SAP:OK"]
test_action_string = ["SSCC SSC2 ap -S -s %s -p %s -n 10 -t 0 -m 8" % (ssid_1, password_1)]
fail_string = "Fail, Fail to set ap ssid/password on SSC2"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
# step4, SSC2 join SSC1(soft AP)
checker_stings = []
test_action_string = []
checker_stings.append("P SSC2 C +JAP:CONNECTED,%s" % ssid)
test_action_string.append("SSCC SSC2 ap -C -s %s -p %s" % (ssid, password))
fail_string = "Fail, Fail to connect to SSC1 SoftAP"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
# step5, create server on SSC1
checker_stings = ["R SSC1 A <server_sock>:BIND:(\d+),OK"]
test_action_string = ["SSCC SSC1 soc -B -t TCP -p %s" % server_port]
fail_string = "Fail, Fail to create server on SSC1 while binding"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
checker_stings = ["R SSC1 RE LISTEN:(\d+),OK"]
test_action_string = ["SSCC SSC1 soc -L -s <server_sock>"]
fail_string = "Fail, Fail to create server on SSC1 while listening"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
# step6, create client on SSC2
checker_stings = []
test_action_string = []
checker_stings.append("P SSC2 A <client_sock>:BIND:(\d+),OK")
test_action_string.append("SSCC SSC2 soc -B -t TCP")
fail_string = "Fail, SSC2 Fail to connect to server while binding"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
checker_stings = ["P SSC2 RE CONNECT:(\d+),OK", "P SSC1 A <accept_sock>:ACCEPT:(\d+),.+"]
test_action_string = ["SSCC SSC2 soc -C -s <client_sock> -i %s -p %s" % ("192.168.6.1", server_port)]
fail_string = "Fail, SSC2 Fail to connect to server while connecting"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
# step7, SSC3 - SSC5 join SSC2
checker_stings = []
test_action_string = []
for i in range(sta_number):
checker_stings.append("P SSC%d C +JAP:CONNECTED,%s" % (i + 3, ssid_1))
test_action_string.append("SSCC SSC%d ap -C -s %s -p %s" % (i + 3, ssid_1, password_1))
fail_string = "Fail, SSC%d Fail to connect to SSC2" % (i + 3)
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string, check_time=450) is False:
return
# step8, create server on SSC2
checker_stings = ["R SSC2 A <server_sock_t>:BIND:(\d+),OK"]
test_action_string = ["SSCC SSC2 soc -B -t TCP -p %s -i 192.168.5.1" % server_port_t]
fail_string = "Fail, Fail to create server one SSC2 while binding"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
checker_stings = ["R SSC2 RE LISTEN:(\d+),OK"]
test_action_string = ["SSCC SSC2 soc -L -s <server_sock_t>"]
fail_string = "Fail, Fail to create server one SSC2 while listening"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
# step9, create client on SSC3 - SSC5
checker_stings = []
test_action_string = []
for i in range(sta_number):
checker_stings.append("P SSC%d A <client_sock%d>:BIND:(\d+),OK" % (i + 3, i + 3))
test_action_string.append("SSCC SSC%d soc -B -t TCP" % (i + 3))
fail_string = "Fail, Fail to connect to SSC2 server while binding"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
for i in range(sta_number):
checker_stings = ["P SSC%d RE CONNECT:(\d+),OK" % (i + 3),
"P SSC2 A <accept_sock%d>:ACCEPT:(\d+),.+" % (i + 3)]
test_action_string = ["SSCC SSC%d soc -C -s <client_sock%d> -i %s -p %s" %
(i + 3, i + 3, "192.168.5.1", server_port_t)]
fail_string = "Fail, Fail to connect to SSC2 server while connecting"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
start_time = time.time()
# step 10, do send/recv
while time.time() - start_time < test_time:
checker_stings = []
test_action_string = []
if server_echo is True:
test_action_string.append("SSC SSC1 soc -S -s <accept_sock> -l %d -n %d -j %d" %
(send_len, TEST_COUNT_ONE_ROUND, send_delay))
checker_stings.append("P SSC1 RE \+SEND:\d+,OK NC CLOSED")
test_action_string.append("SSC SSC2 soc -S -s <server_sock> -l %d -n %d -j %d" %
(send_len, TEST_COUNT_ONE_ROUND, send_delay))
checker_stings.append("P SSC2 RE \+SEND:\d+,OK NC CLOSED")
for i in range(sta_number):
checker_stings.append("P SSC%d RE \+SEND:\d+,OK NC CLOSED" % (i + 3))
test_action_string.append("SSC SSC%d soc -S -s <client_sock%d> -l %d -n %d -j %d" %
(i + 3, i + 3, send_len, TEST_COUNT_ONE_ROUND, send_delay))
for i in range(sta_number):
test_action_string.append("SSC SSC2 soc -S -s <accept_sock%d> -l %d -n %d -j %d" %
(i + 3, send_len, TEST_COUNT_ONE_ROUND, send_delay))
checker_stings.append("P SSC2 RE \+SEND:\d+,OK NC CLOSED")
fail_string = "Fail, Failed to send/recv data"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string,
check_freq=1, check_time=300) is False:
break
pass
NativeLog.add_prompt_trace("time escape: %s" % (time.time() - start_time))
if (time.time() - start_time) > test_time:
self.result_cntx.set_result("Succeed")
else:
self.result_cntx.set_result("Failed")
checker_stings = []
test_action_string = []
for i in range(sta_number + 2):
checker_stings.append("P SSC%d C CLOSEALL" % (i + 1))
test_action_string.append("SSCC SSC%d soc -T" % (i + 1))
fail_string = "Fail, Fail to close socket"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
# re-set server on SSC1
server_port = random.randint(20000, 30000)
checker_stings = ["R SSC1 A <server_sock>:BIND:(\d+),OK"]
test_action_string = ["SSCC SSC1 soc -B -t TCP -p %s" % server_port]
fail_string = "Fail, Fail to bind socket"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
checker_stings = ["R SSC1 RE LISTEN:(\d+),OK"]
test_action_string = ["SSCC SSC1 soc -L -s <server_sock>"]
fail_string = "Fail, Fail to listen"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
# SSC2 connnect SSC1
checker_stings = []
test_action_string = []
checker_stings.append("P SSC2 A <client_sock>:BIND:(\d+),OK")
test_action_string.append("SSCC SSC2 soc -B -t TCP")
fail_string = "Fail, SSC2 Fail to bind sock"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
checker_stings = ["P SSC2 RE CONNECT:(\d+),OK", "P SSC1 A <accept_sock>:ACCEPT:(\d+),.+"]
test_action_string = ["SSCC SSC2 soc -C -s <client_sock> -i %s -p %s" % ("192.168.6.1", server_port)]
fail_string = "Fail, SSC2 Fail to connect to SSC1 server"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
# create server on SSC2
checker_stings = []
test_action_string = []
checker_stings.append("P SSC2 A <server_sock>:BIND:(\d+),OK")
test_action_string.append("SSCC SSC2 soc -B -t TCP -p %s -i 192.168.5.1" % server_port_t)
fail_string = "Fail, SSC2 Fail to bind"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
checker_stings = ["R SSC2 RE LISTEN:(\d+),OK"]
test_action_string = ["SSCC SSC2 soc -L -s <server_sock>"]
fail_string = "Fail, SSC2 Fail to listen"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
# create client on SSC3-SSC5
checker_stings = []
test_action_string = []
for i in range(sta_number):
checker_stings.append("P SSC%d A <client_sock%d>:BIND:(\d+),OK" % (i + 3, i + 3))
test_action_string.append("SSCC SSC%d soc -B -t TCP" % (i + 3))
fail_string = "Fail, Fail to connect to SSC2 server while binding"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
for i in range(sta_number):
checker_stings = ["P SSC%d RE CONNECT:(\d+),OK" % (i + 3),
"P SSC2 A <accept_sock%d>:ACCEPT:(\d+),.+" % (i + 3)]
test_action_string = ["SSCC SSC%d soc -C -s <client_sock%d> -i %s -p %s" %
(i + 3, i + 3, "192.168.5.1", server_port_t)]
fail_string = "Fail, Fail to connect to server"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
def result_check(self, port_name, data):
TCActionBase.CommonTCActionBase.result_check(self, port_name, data)
self.result_cntx.append_data(port_name, data)
def main():
pass
if __name__ == '__main__':
main()

View File

@ -0,0 +1,325 @@
import os
import time
import random
import threading
import socket
from TCAction import TCActionBase
from NativeLog import NativeLog
from NativeLog import ThroughputResult
from Utility import RSSICalibrator
LOG_FOLDER = os.path.join("Performance", "Throughput")
AP_PROP_KEY = ("ssid", "password", "apc")
class SendThread(threading.Thread):
def __init__(self, sock, send_len):
threading.Thread.__init__(self)
self.setDaemon(True)
self.sock = sock
self.send_len = send_len
self.exit_event = threading.Event()
self.calc_event = threading.Event()
self.bytes_sent = 0
pass
def start_calc(self):
self.calc_event.set()
def stop_calc(self):
self.calc_event.clear()
self.exit_event.set()
def run(self):
data = "A" * self.send_len
if self.sock is None:
return
while True:
if self.exit_event.isSet() is True:
break
try:
self.sock.send(data)
except StandardError:
break
if self.calc_event.isSet() is True:
self.bytes_sent += self.send_len
def get_bytes_sent(self):
return self.bytes_sent
pass
class RecvThread(threading.Thread):
def __init__(self, sock):
threading.Thread.__init__(self)
self.setDaemon(True)
self.sock = sock
self.exit_event = threading.Event()
self.calc_event = threading.Event()
self.bytes_recv = 0
def start_calc(self):
self.calc_event.set()
def stop_calc(self):
self.calc_event.clear()
self.exit_event.set()
def run(self):
if self.sock is None:
return
while True:
if self.exit_event.isSet() is True:
break
try:
data = self.sock.recv(8 * 1024)
except StandardError:
break
if self.calc_event.isSet() is True:
self.bytes_recv += len(data)
def get_bytes_recv(self):
return self.bytes_recv
pass
class TestCase(TCActionBase.CommonTCActionBase):
def __init__(self, test_case, test_env, timeout=30, log_path=TCActionBase.LOG_PATH):
TCActionBase.CommonTCActionBase.__init__(self, test_case, test_env, timeout=timeout, log_path=log_path)
self.performance_folder_path = log_path
self.att_test_list = range(60)
cmd_set = test_case["cmd set"]
# load param from excel
for i in range(1, len(cmd_set)):
if cmd_set[i][0] != "dummy":
cmd_string = "self." + cmd_set[i][0]
exec cmd_string
self.result_cntx = TCActionBase.ResultCheckContext(self, test_env, self.tc_name)
pass
def execute(self):
TCActionBase.TCActionBase.execute(self)
self.result_cntx.start()
try:
# configurable params
ap_list = self.get_parameter("shield_box_ap_list")
pc_ip = self.get_parameter("pc_ip")
send_len = self.send_len
att_test_list = self.att_test_list
tx_enable = self.tx_enable
rx_enable = self.rx_enable
measure_period = self.measure_period
# configurable params
except StandardError, e:
NativeLog.add_trace_critical("Error configuration for TCPThroughput script, error is %s" % e)
raise StandardError("Error configuration")
tcp_port = random.randint(40000, 50000)
# init throughput result data
test_item = ""
if tx_enable is True:
test_item += "Tx"
if rx_enable is True:
test_item += "Rx"
if test_item == "":
raise StandardError("no throughput test item")
folder_path = os.path.join(self.performance_folder_path, LOG_FOLDER)
file_name = os.path.join(folder_path,
"TCPThroughput_%s_%s" % (test_item, time.strftime("%d%H%M%S", time.localtime())))
result = ThroughputResult.ThroughputResult(file_name, standard_required=True)
# restart before executing throughput
checker_stings = ["R SSC1 C !!!ready!!!"]
test_action_string = ["SSC SSC1 reboot"]
fail_string = "Fail, Fail to reboot"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
self.result_cntx.set_result("Fail")
return
# disable recv print during throughput test
checker_stings = ["R SSC1 C +RECVPRINT"]
test_action_string = ["SSC SSC1 soc -R -o 0"]
fail_string = "Fail, Fail to disable recv print"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
self.result_cntx.set_result("Fail")
return
ret = True
for ap_prop in ap_list:
ssid = ap_prop[0]
password = ap_prop[1]
apc = ap_prop[2]
if ap_prop[1] == "":
# set a default string for open ap
password = "1"
# switch off all outlet, switch on AP outlet
outlet_config_dict = dict.fromkeys(range(1, 9), "OFF")
outlet_config_dict[apc] = "ON"
apc_cmd = "APC <APC1>"
for outlet in outlet_config_dict:
apc_cmd += " %s %s" % (outlet_config_dict[outlet], outlet)
checker_stings = ["P PC_COM L OK"]
fail_string = "Fail, Fail to switch apc"
if self.load_and_exe_one_step(checker_stings, [apc_cmd], fail_string) is False:
ret = False
break
# wait AP ready
time.sleep(20)
# create server
server_sock = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
server_sock.bind((pc_ip, tcp_port))
server_sock.settimeout(5)
server_sock.listen(5)
if tx_enable is True:
result.add_test_item(ssid + "_tx")
if rx_enable is True:
result.add_test_item(ssid + "_rx")
# create RSSI Calibrator
calibrator = RSSICalibrator.Calibrator()
for att_value in att_test_list:
# step 0 set att value
checker_stings = ["R PC_COM L OK"]
test_action_string = ["ATT <att_port> %s" % att_value]
fail_string = "Fail, Fail to set att value"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
ret = False
break
# continue
# step 1 get AP RSSI
checker_stings = ["R SSC1 A <rssi>:\+SCAN:%s,[:\d\w]+,\d+,\d+,([-\d]+)" % ssid]
test_action_string = ["SSC SSC1 sta -S -s %s" % ssid]
fail_string = "Fail, Fail to scan"
rssi = scan_count = 0
for i in range(3):
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
continue
rssi += int(self.test_env.get_variable_by_name("rssi")[1])
scan_count += 1
rssi = calibrator.calibrate_rssi(float(rssi) / scan_count if scan_count > 0 else 0, att_value)
# step 2 connect to AP
checker_stings = ["R SSC1 C +JAP:CONNECTED"]
test_action_string = ["SSC SSC1 sta -C -s %s -p %s" % (ssid, password)]
fail_string = "Fail, Fail to JAP"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string,
check_freq=1, check_time=30) is False:
if rssi < -89:
continue
else:
ret = False
break
# step 3 close all connections
checker_stings = ["R SSC1 C +CLOSEALL"]
test_action_string = ["SSC SSC1 soc -T"]
fail_string = "Fail, Fail to close socket"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
ret = False
break
# continue
# step 4 create tcp connection
checker_stings = ["R SSC1 A <client_sock>:\+BIND:(\d+),OK"]
test_action_string = ["SSC SSC1 soc -B -t TCP"]
fail_string = "Fail, Fail to bind"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
ret = False
break
# continue
checker_stings = ["P SSC1 RE \+CONNECT:\d+,OK"]
test_action_string = ["SSC SSC1 soc -C -s <client_sock> -i %s -p %s" % (pc_ip, tcp_port)]
fail_string = "Fail, Fail to connect socket"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
ret = False
break
# continue
try:
sock, addr = server_sock.accept()
except socket.error, e:
NativeLog.add_trace_critical("%s" % e)
continue
sock.settimeout(measure_period)
# step 5 do throughput test
send_thread = SendThread(sock if rx_enable is True else None, send_len)
send_thread.start()
recv_thread = RecvThread(sock if tx_enable is True else None)
recv_thread.start()
if tx_enable is True:
# do send from target
test_action_string = ["SSC SSC1 soc -S -s <client_sock> -l %s -n 10000000" % send_len]
fail_string = "Fail, Fail to send"
if self.load_and_exe_one_step([], test_action_string, fail_string) is False:
pass
# start throughput calculate
send_thread.start_calc()
recv_thread.start_calc()
# sleep for measure period
time.sleep(measure_period)
# stop throughput calculate
send_thread.stop_calc()
recv_thread.stop_calc()
send_thread.join()
recv_thread.join()
sock.close()
# output throughput result
# in Mbps
if send_thread.get_bytes_sent() > 0:
result.log_throughput(ssid + "_rx", rssi, att_value,
float(send_thread.get_bytes_sent() * 8) / (measure_period * 1000000))
if recv_thread.get_bytes_recv() > 0:
result.log_throughput(ssid + "_tx", rssi, att_value,
float(recv_thread.get_bytes_recv() * 8) / (measure_period * 1000000))
result.output_to_file()
pass
server_sock.close()
if not ret:
NativeLog.add_trace_critical("Test SUC for %s" % ssid)
elif ret:
NativeLog.add_trace_critical("Test FAIL for %s!!!" % ssid)
if ret:
self.result_cntx.set_result("Succeed")
else:
self.result_cntx.set_result("Fail")
# finally, execute done
def result_check(self, port_name, data):
TCActionBase.CommonTCActionBase.result_check(self, port_name, data)
self.result_cntx.append_data(port_name, data)
def main():
pass
if __name__ == '__main__':
main()

View File

@ -0,0 +1 @@
__all__ = ["TCPConnUtility", "TCPConnSingleMode", "TCPConnMixedMode"]

View File

@ -0,0 +1,342 @@
import time
import random
import threading
import socket
import re
from TCAction import PerformanceTCBase
from NativeLog import NativeLog
from Utility import Encoding
class SendThread(threading.Thread):
def __init__(self, sock, send_len, target_addr, delay):
threading.Thread.__init__(self)
self.sock = sock
self.send_len = send_len
self.target_addr = target_addr
self.delay = delay
self.exit_event = threading.Event()
self.send_count = 0
pass
def exit(self):
self.exit_event.set()
def run(self):
data = "A" * self.send_len
if self.sock is None:
return
while True:
if self.exit_event.isSet() is True:
break
try:
self.sock.sendto(data, self.target_addr)
except StandardError:
break
self.send_count += 1
time.sleep(self.delay * 0.001)
pass
def get_send_count(self):
return self.send_count
class RecvThread(threading.Thread):
def __init__(self, sock):
threading.Thread.__init__(self)
self.sock = sock
self.exit_event = threading.Event()
self.calc_event = threading.Event()
self.bytes_recv = 0
self.Max = 0.0
def start_calc(self):
self.calc_event.set()
def stop_calc(self):
self.calc_event.clear()
self.exit_event.set()
def run(self):
if self.sock is None:
return
while True:
if self.exit_event.isSet() is True:
break
try:
data, addr = self.sock.recvfrom(2048)
except StandardError:
break
if self.calc_event.isSet() is True:
self.bytes_recv += len(data)
if len(data) == 0:
start = time.time()
while True:
try:
data, addr = self.sock.recvfrom(2048)
except StandardError:
break
if len(data) > 0:
if self.calc_event.isSet() is True:
self.bytes_recv += len(data)
end = time.time()
break
if end - start > self.Max:
self.Max = end - start
def get_bytes_recv(self):
return self.bytes_recv
pass
def get_Max_time(self):
return self.Max
pass
class device_check(threading.Thread):
def __init__(self, port):
threading.Thread.__init__(self)
self.Max = 0.0
self.port = port
self.recv_data_cache = ""
self.cache_lock = threading.Lock()
self.exit_event = threading.Event()
def data_recv_callback(self, data):
with self.cache_lock:
self.recv_data_cache += data
pass
def exit(self):
self.exit_event.set()
pass
def run(self):
while self.exit_event.isSet() is False:
while True:
if self.recv_data_cache:
match = re.search("\+RECVFROM:\d+,\d+,\d+\.\d+\.\d+\.\d+,\d+", self.recv_data_cache)
if match is not None:
self.recv_data_cache = self.recv_data_cache[len(match.group()):]
else:
start = time.time()
end = 0.0
while True:
res = re.search("\+RECVFROM:\d+,\d+,\d+\.\d+\.\d+\.\d+,\d+", self.recv_data_cache)
if res is not None:
self.recv_data_cache = self.recv_data_cache[len(res.group()):]
end = time.time()
break
if end - start > self.Max:
self.Max = end - start
pass
def get_max_time(self):
return self.Max
class TestCase(PerformanceTCBase.PerformanceTCBase):
def __init__(self, test_case, test_env, timeout, log_path):
PerformanceTCBase.PerformanceTCBase.__init__(self, test_case, test_env, timeout, log_path)
self.send_len = 0
self.pc_send = 0
self.target_send = 0
self.test_time = 0
self.delay = 0
# load param from excel
cmd_set = test_case["cmd set"]
for i in range(1, len(cmd_set)):
if cmd_set[i][0] != "dummy":
cmd_string = "self." + cmd_set[i][0]
exec cmd_string
self.recv_cb_lock = threading.Lock()
self.recv_cb = dict.fromkeys(["SSC1"])
pass
def register_recv_callback(self, port_name, callback):
with self.recv_cb_lock:
if self.recv_cb[port_name] is None:
self.recv_cb[port_name] = [callback]
else:
self.recv_cb[port_name].append(callback)
pass
def process(self):
try:
# configurable params
send_len = self.send_len
pc_send = self.pc_send
target_send = self.target_send
test_time = self.test_time
delay = self.delay
ap_ssid = self.get_parameter("ap_ssid")
ap_password = self.get_parameter("ap_password")
pc_ip = self.get_parameter("pc_ip")
target_ip = self.get_parameter("target_ip")
except StandardError, e:
NativeLog.add_trace_critical("Error configuration for UDP script, error is %s" % e)
raise StandardError("Error configuration")
udp_port = random.randint(40000, 50000)
# reboot before executing
self.flush_data("SSC1")
self.serial_write_line("SSC1", "reboot")
if self.check_response("SSC1", "ready!!!", 5) is False:
NativeLog.add_trace_critical("Fail to reboot")
return
# set target as STA mode
self.flush_data("SSC1")
self.serial_write_line("SSC1", "op -S -o 1")
if self.check_response("SSC1", "+MODE:OK", 5) is False:
NativeLog.add_trace_critical("Fail to set mode")
return
# connect to AP
self.flush_data("SSC1")
self.serial_write_line("SSC1", "sta -C -s %s -p %s" % (ap_ssid, ap_password))
if self.check_response("SSC1", "+JAP:CONNECTED", 30) is False:
NativeLog.add_trace_critical("Fail to JAP")
return
# disable recv print on target
self.flush_data("SSC1")
self.serial_write_line("SSC1", "soc -R -o 0")
if self.check_response("SSC1", "+RECVPRINT", 5) is False:
NativeLog.add_trace_critical("Fail to disable recv print")
return
# get broadcast ip
res = re.search("(\d+\.\d+\.\d+\.)\d+", pc_ip)
if res is not None:
udp = res.group(1)
broadcast_ip = udp + "255"
else:
NativeLog.add_trace_critical("No ip addr found")
return
# close all connection on target
self.flush_data("SSC1")
self.serial_write_line("SSC1", "soc -T")
if self.check_response("SSC1", "+CLOSEALL", 5) is False:
NativeLog.add_trace_critical("Fail to close sock")
return
# create socket on pc
pc_sock = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
pc_sock.bind((pc_ip, udp_port))
pc_sock.settimeout(1)
# create socket on target
self.flush_data("SSC1")
self.serial_write_line("SSC1", "soc -B -t UDP -i %s -p %s" % (target_ip, udp_port))
if self.check_response("SSC1", "+BIND:0,OK,", 5) is False:
NativeLog.add_trace_critical("Fail to bind")
return
thread_dict = dict.fromkeys(["SSC1"])
thread_dict["SSC1"] = dict(zip(["check"], [None]))
thread_dict["SSC1"]["check"] = device_check(self.test_env.get_port_by_name("SSC1"))
self.register_recv_callback("SSC1", thread_dict["SSC1"]["check"].data_recv_callback)
send_thread = SendThread(pc_sock if pc_send is True else None, send_len, (broadcast_ip, udp_port), delay)
send_thread.start()
recv_thread = RecvThread(pc_sock if target_send is True else None)
recv_thread.start()
# start calculate
recv_thread.start_calc()
thread_dict["SSC1"]["check"].start()
send_count = 0
if target_send is True:
# do send from target
start = time.time()
while time.time() - start < test_time * 60:
self.flush_data("SSC1")
self.serial_write_line("SSC1", "soc -S -s 0 -l %s -n 1000 -i %s -p %s -j %s" % (
send_len, broadcast_ip, udp_port, delay))
if self.check_response("SSC1", "+SEND:0,OK", 300) is False:
NativeLog.add_trace_critical("Fail to send")
return
send_count += 1000
else:
time.sleep(test_time * 60)
send_thread.exit()
send_thread.join()
# stop throughput calculate
while True:
if recv_thread.isAlive() is False:
recv_thread.stop_calc()
recv_thread.join()
break
Max = 0.0
recv_count = 0
if pc_send is True:
send_count = send_thread.get_send_count()
start = time.time()
rx_data_len = 0
suc_time = 0
while time.time() - start < 30:
self.flush_data("SSC1")
self.serial_write_line("SSC1", "soc -Q -s 0 -o 1")
time.sleep(0.05)
data = self.serial_read_data("SSC1")
if data is not None:
res = re.search("\+RECVLEN:(\d+)", data)
if res is not None:
if rx_data_len < int(res.group(1)):
rx_data_len = int(res.group(1))
time.sleep(0.5)
else:
suc_time += 1
if suc_time > 5:
break
if (rx_data_len * 8 % send_len) > 0:
recv_count = rx_data_len / send_len + 1
else:
recv_count = rx_data_len / send_len
if recv_thread.get_bytes_recv() > 0:
if (recv_thread.get_bytes_recv() % send_len) > 0:
recv_count = recv_thread.get_bytes_recv() / send_len + 1
else:
recv_count = recv_thread.get_bytes_recv() / send_len
Max = recv_thread.get_Max_time()
thread_dict["SSC1"]["check"].exit()
pc_sock.close()
self.set_result("Succeed")
NativeLog.add_trace_critical("send_count is %s, recv_count is %s" % (send_count, recv_count))
NativeLog.add_trace_critical(
"UDP Broadcast lose rate is %.2f%%" % (float(send_count - recv_count) / send_count * 100))
NativeLog.add_trace_critical("UDP Broadcast lose test MAX time is %.4f" % Max)
@Encoding.encode_utf8(3)
def result_check(self, port_name, data):
PerformanceTCBase.PerformanceTCBase.result_check(self, port_name, data)
if port_name in self.recv_cb:
with self.recv_cb_lock:
callback_list = self.recv_cb[port_name]
if callback_list is not None:
for callback in callback_list:
callback(data)
pass
def main():
pass
if __name__ == '__main__':
main()

View File

@ -0,0 +1,156 @@
from TCAction import TCActionBase
from NativeLog import NativeLog
import time
import random
import string
class TestCase(TCActionBase.CommonTCActionBase):
def __init__(self, test_case, test_env, timeout=45, log_path=TCActionBase.LOG_PATH):
TCActionBase.CommonTCActionBase.__init__(self, test_case, test_env, timeout=timeout, log_path=log_path)
# load param from excel
cmd_set = test_case["cmd set"]
for i in range(1, len(cmd_set)):
if cmd_set[i][0] != "dummy":
cmd_string = "self." + cmd_set[i][0]
exec cmd_string
self.result_cntx = TCActionBase.ResultCheckContext(self, test_env, self.tc_name)
pass
def execute(self):
TCActionBase.TCActionBase.execute(self)
self.result_cntx.start()
try:
# configurable params
send_len = self.send_len
test_time = self.test_time * 60
server_echo = self.server_echo
sta_number = self.sta_number
send_delay = self.send_delay
# configurable params
except StandardError, e:
NativeLog.add_trace_critical("Error configuration for TCPTransparent script, error is %s" % e)
raise StandardError("Error configuration")
# step0 reboot
for i in range(sta_number + 1):
checker_stings = ["P SSC%d C ready!!!" % (i + 1)]
test_action_string = ["SSCC SSC%d restore" % (i + 1)]
fail_string = "Fail, Fail to restore"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
# turn off recv print
for i in range(sta_number + 1):
checker_stings = ["P SSC%d C +RECVPRINT:0" % (i + 1)]
test_action_string = ["SSCC SSC%d soc -R -o 0" % (i + 1)]
fail_string = "Fail, Fail to turn off recv print"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
# step1, set softAP mode on SSC1
checker_stings = ["R SSC1 C +MODE:OK"]
test_action_string = ["SSCC SSC1 op -S -o 2"]
fail_string = "Fail, Fail to set mode on SSC1"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
# step2, set STA mode on SSC2-SSCn
for i in range(sta_number):
checker_stings = ["R SSC%d C +MODE:OK" % (i + 2)]
test_action_string = ["SSCC SSC%d op -S -o 1" % (i + 2)]
fail_string = "Fail, Fail to set mode on SSC%d" % (i + 2)
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
# step3, set ssid/password on SSC1
ssid = "".join([random.choice(string.lowercase) for m in range(10)])
password = "".join([random.choice(string.lowercase) for m in range(10)])
udp_port = random.randint(10000, 20000)
checker_stings = ["R SSC1 C +SAP:OK"]
test_action_string = ["SSCC SSC1 ap -S -s %s -p %s -n 10 -t 0 -m 10" % (ssid, password)]
fail_string = "Fail, Fail to set ssid/password on SSC1"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
# step4, all STA join SSC1(soft AP)
for i in range(sta_number):
checker_stings = ["R SSC%d C +JAP:CONNECTED,%s" % (i + 2, ssid)]
test_action_string = ["SSCC SSC%d ap -C -s %s -p %s" % (i + 2, ssid, password)]
fail_string = "Fail, Fail to connect to SSC1"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string, check_time=450) is False:
return
# step5, get all the STA ip
for i in range(sta_number):
checker_stings = ["R SSC%d A <SSC%d_IP>:\+STAIP:192.168.4.(\d+)" % (i + 2, i + 2)]
test_action_string = ["SSCC SSC%d ip -Q" % (i + 2)]
fail_string = "Fail, Fail to get SSC%d ip" % (i + 2)
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
# else:
# print "SSC%d ip is:" % (i + 2), self.get_parameter("SSC%d_IP" % (i + 2))
# step6, create UDP socket on all targets
for i in range(sta_number):
checker_stings = ["R SSC%d A <sock%d>:\+BIND:(\d+),OK" % (i + 2, i + 2)]
test_action_string = ["SSCC SSC%d soc -B -t UDP -p %s" % (i + 2, udp_port + i + 2)]
fail_string = "Fail, SSC%d Fail to bind" % (i + 2)
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string) is False:
return
start_time = time.time()
# step7, do send/recv, SSC2<---->other STAs
while time.time() - start_time < test_time:
checker_stings = []
test_action_string = []
if server_echo is True:
# SSC2 send packets to SSC3-SSCn
for i in range(sta_number - 1):
ip = "192.168.4." + self.get_parameter("SSC%d_IP" % (i + 3))
test_action_string.append(
"SSC SSC2 soc -S -s <sock%d> -i %s -p %s -l %d -n 1000 -j %d" % (
i + 3, ip, udp_port + i + 3, send_len, send_delay))
checker_stings.append(
"P SSC2 RE \+SEND:%s,OK NC CLOSED NC ERROR" % self.get_parameter("sock%d" % (i + 3)))
# SSC3-SSCn send packets to SSC2
ssc2_ip = "192.168.4." + self.get_parameter("SSC2_IP")
for i in range(sta_number - 1):
test_action_string.append(
"SSC SSC%d soc -S -s <sock%d> -i %s -p %s -l %d -n 1000 -j %d" % (
i + 3, i + 3, ssc2_ip, udp_port + 2, send_len, send_delay))
checker_stings.append(
"P SSC%d RE \+SEND:%s,OK NC CLOSED NC ERROR" % (i + 3, self.get_parameter("sock%d" % (i + 3))))
fail_string = "Fail, Failed to send/recv data"
if self.load_and_exe_one_step(checker_stings, test_action_string, fail_string,
check_freq=1, check_time=300) is False:
break
# drop off the delay time if it's greater than 20ms
if send_delay > 20:
send_delay -= 10
NativeLog.add_trace_critical("time escape: %s" % (time.time() - start_time))
if (time.time() - start_time) >= test_time:
self.result_cntx.set_result("Succeed")
else:
self.result_cntx.set_result("Failed")
# finally, execute done
def result_check(self, port_name, data):
TCActionBase.CommonTCActionBase.result_check(self, port_name, data)
self.result_cntx.append_data(port_name, data)
def main():
pass
if __name__ == '__main__':
main()

Some files were not shown because too many files have changed in this diff Show More