feat(factory_test): add factory test and document

This commit is contained in:
dongheng
2019-02-21 19:59:56 +08:00
parent f49b40e79d
commit 9c19b1eedb
18 changed files with 1230 additions and 6 deletions

View File

@ -82,7 +82,7 @@ CFLAGS += -D__ESP_FILE__='"null"'
CXXFLAGS += -D__ESP_FILE__='"null"'
endif
.PHONY: ota ota-clean
.PHONY: ota ota-clean app2 app2-flash app2-flash-all
RAW_BIN := ./build/$(PROJECT_NAME).bin
OTA_BIN := ./build/$(PROJECT_NAME).ota.bin
@ -97,6 +97,20 @@ __COMBILE_OTA_BIN := 1
endif
endif
app2: all
ifdef CONFIG_ESPTOOLPY_FLASHSIZE_1MB
@rm -f ./build/esp8266/esp8266_out.ld
@export CFLAGS= && export CXXFLAGS= && make APP_OFFSET=$(APP2_OFFSET) APP_SIZE=$(APP2_SIZE)
endif
@echo "To flash all build output, run 'make flash' or:"
@echo $(ESPTOOLPY_WRITE_FLASH) $(APP2_OFFSET) $(APP_BIN)
app2-flash: app2
@$(ESPTOOLPY_WRITE_FLASH) $(APP2_OFFSET) $(APP_BIN)
app2-flash-all: app2
@$(ESPTOOLPY_WRITE_FLASH) $(patsubst $(APP_OFFSET),$(APP2_OFFSET),$(ESPTOOL_ALL_FLASH_ARGS))
$(OTA1_BIN): all_binaries
@cp $(RAW_BIN) $(OTA1_BIN)
@echo [GEN] $(OTA1_BIN)

View File

@ -248,22 +248,42 @@ void show_critical_info(void)
ets_printf("SWReq:%u\n", SWReq);
}
#ifdef ESP_DPORT_CLOSE_NMI
static int s_nmi_is_closed;
void esp_dport_close_nmi(void)
{
vPortEnterCritical();
REG_WRITE(PERIPHS_DPORT_BASEADDR, REG_READ(PERIPHS_DPORT_BASEADDR) & ~0x1);
s_nmi_is_closed = 1;
vPortExitCritical();
}
#define ESP_NMI_IS_CLOSED() s_nmi_is_closed
#else
#define ESP_NMI_IS_CLOSED() 0
#endif
void IRAM_ATTR vPortETSIntrLock(void)
{
if (NMIIrqIsOn == 0) {
vPortEnterCritical();
do {
REG_WRITE(INT_ENA_WDEV, WDEV_TSF0_REACH_INT);
} while(REG_READ(INT_ENA_WDEV) != WDEV_TSF0_REACH_INT);
if (!ESP_NMI_IS_CLOSED()) {
do {
REG_WRITE(INT_ENA_WDEV, WDEV_TSF0_REACH_INT);
} while(REG_READ(INT_ENA_WDEV) != WDEV_TSF0_REACH_INT);
}
}
}
void IRAM_ATTR vPortETSIntrUnlock(void)
{
if (NMIIrqIsOn == 0) {
extern uint32_t WDEV_INTEREST_EVENT;
if (!ESP_NMI_IS_CLOSED()) {
extern uint32_t WDEV_INTEREST_EVENT;
REG_WRITE(INT_ENA_WDEV, WDEV_INTEREST_EVENT);
REG_WRITE(INT_ENA_WDEV, WDEV_INTEREST_EVENT);
}
vPortExitCritical();
}
}

View File

@ -0,0 +1,190 @@
Factory Test
************
1. Overview
===========
The document introduces how to develop, compile, download and run the factory test firmware.
The factory test software development kit is also an example of the SDK, and it is located at :example:`examples/system/factory-test`.
2. Development
==============
Users can use ready-to-use applications directly, or can also add custom application code into the factory test software development kit.
More details of adding customer components, please refer to :doc:`Documentation for the GNU Make based build system <build-system>`.
Users can just develop the factory test application as normal examples of the SDK.
2.1 Application code
--------------------
Just like other applications, the entry function of factory test application is ``app_main``. It should be added into the source code file of users.
For example, users can add the ``app_main`` into ``main.c`` of the above sample project.
Users can refer to the source code in file :idf_file:`/examples/system/factory-test/main/main.c` to build custom project.
2.2 Linking address
-------------------
The SDK's partition only supports two applications that named as ``ota_0`` and ``ota_1``.
In this case, we link the factory test firmware to the partition of ``ota_1``.
So, please do not flash the factory test firmware into the partition of ``ota_0``.
3. Compile
==========
To make the bootloader run the ``ota_1(factory test firmware)``,
please enable the ``GPIO triggers boot from test app partition`` and set the ``correct`` GPIO of your development board in menuconfig::
Bootloader config --->
[*] GPIO triggers boot from test app partition
(12) Number of the GPIO input to boot TEST partition
Using the partition table file which has two "OTA" definitions partition::
Partition Table --->
Partition Table (Factory app, two OTA definitions) --->
(X) Factory app, two OTA definitions
Enable the console which is used for human-computer interaction::
Component config --->
Virtual file system --->
[*] Using espressif VFS
Enable pthread for this function::
Component config --->
PThreads --->
[*] Enable pthread
Then call command ``make app2`` in the terminal to compile the firmware which is able to run at ``ota_1`` partition.
The ``Make System`` will start compiling bootloader, partition table file, factory test firmware and so on one by one.
3.1 Special Commands
====================
1. ``make app2``: only compile factory test firmware which is able to run at ``ota_1``, ``with`` bootloader, partition table file and so on
2. ``make app2-flash``: flash(download) only the factory test firmware which is able to run at ``ota_1``, ``without`` bootloader, partition table file and so on
3. ``make app2-flash-all``: flash(download) the factory test firmware which is able to run at ``ota_1``, ``with`` bootloader, partition table file and so on
4. Download
===========
Input command ``make app2-flash-all`` in the terminal to download bootloader, partition table file and factory test firmware which is located at ``ota_1`` one by one.
If users only want to download factory test firmware, please use command ``make app2-flash`` instead.
5. Run
======
Please hold the ``correct`` GPIO, which is configured in the menuconfig in Section 3 ``Compile``, to be low level and power on.
Input command ``make monitor`` in the terminal, and then logs will appear like following::
ets Jan 8 2013,rst cause:1, boot mode:(3,6)
load 0x40100000, len 7872, room 16
0x40100000: _stext at ??:?
tail 0
chksum 0xf1
load 0x3ffe8408, len 24, room 8
tail 0
chksum 0x78
load 0x3ffe8420, len 3604, room 8
tail 12
chksum 0x1b
I (64) boot: ESP-IDF v3.2-dev-354-gba1f90cd-dirty 2nd stage bootloader
I (64) boot: compile time 13:56:17
I (72) qio_mode: Enabling default flash chip QIO
I (73) boot: SPI Speed : 40MHz
I (80) boot: SPI Mode : QIO
I (86) boot: SPI Flash Size : 2MB
I (92) boot: Partition Table:
I (98) boot: ## Label Usage Type ST Offset Length
I (109) boot: 0 nvs WiFi data 01 02 00009000 00004000
I (120) boot: 1 otadata OTA data 01 00 0000d000 00002000
I (132) boot: 2 phy_init RF data 01 01 0000f000 00001000
I (144) boot: 3 ota_0 OTA app 00 10 00010000 000f0000
I (155) boot: 4 ota_1 OTA app 00 11 00110000 000f0000
I (167) boot: End of partition table
I (173) boot: No factory image, trying OTA 0
I (5180) boot: Detect a boot condition of the test firmware
I (5180) esp_image: segment 0: paddr=0x00110010 vaddr=0x40210010 size=0x37b18 (228120) map
I (5263) esp_image: segment 1: paddr=0x00147b30 vaddr=0x3ffe8000 size=0x00718 ( 1816) load
I (5264) esp_image: segment 2: paddr=0x00148250 vaddr=0x3ffe8718 size=0x0019c ( 412) load
I (5275) esp_image: segment 3: paddr=0x001483f4 vaddr=0x40100000 size=0x084b0 ( 33968) load
0x40100000: _stext at ??:?
I (5299) boot: Loaded app from partition at offset 0x110000
I (5340) system_api: Base MAC address is not set, read default base MAC address from BLK0 of EFUSE
I (5340) system_api: Base MAC address is not set, read default base MAC address from BLK0 of EFUSE
I (5530) phy_init: phy ver: 1055_12
I (5530) reset_reason: RTC reset 1 wakeup 0 store 0, reason is 1
I (5530) factory-test: SDK factory test firmware version:v3.2-dev-354-gba1f90cd-dirty
Then users can input test commands to start factory testing.
6. Test Commands
================
1. ``rftest_init``::
parameters: no
function: initialize RF to prepare for test
2. ``tx_contin_func <parameter 1>``::
parameter 1: value 1 means that chip transmits packets continuously with 92% duty cycle,
value 0 means that "iqview" test mode
function: set test mode
3. ``esp_tx <parameter 1> <parameter 2> <parameter 3>``::
parameter 1: transmit channel which ranges from 1 to 14
parameter 2: transmit rate which ranges from 0 to 23
parameter 2: transmit power attenuation which ranges from -127 to 127, unit is 0.25dB
function: start transmitting Wi-Fi packets
note 1: command "wifitxout" is the same as "esp_tx"
note 2: the function can be stopped by command "cmdstop"
4. ``esp_rx <parameter 1> <parameter 2>``::
parameter 1: transmit channel which ranges from 1 to 14
parameter 2: transmit rate which ranges from 0 to 23
function: start receiving Wi-Fi packets
note 1: the function can be stopped by command "cmdstop"
5. ``wifiscwout <parameter 1> <parameter 2> <parameter 3>``::
parameter 1: enable signal, value 1 means enable, value 0 means disable
parameter 2: transmit channel which ranges from 1 to 14
parameter 3: transmit power attenuation which ranges from -127 to 127, unit is 0.25dB
function: start transmitting single carrier Wi-Fi packets
note 1: the function can be stopped by command "cmdstop"
6. ``cmdstop``::
parameters: no
function: stop transmitting or receiving Wi-Fi packets
note 1: command "CmdStop" is the same as "cmdstop"

View File

@ -9,3 +9,4 @@ API Guides
System Task <system-tasks>
PWM and Sniffer Coexists <pwm-and-sniffer-coexists>
FOTA from an Old SDK to the New ESP8266 RTOS SDK (IDF Style) <fota-from-old-new>
Factory Test <factory-test>

View File

@ -0,0 +1,10 @@
menu "Factory-test config"
config FACTORY_TEST
bool "Enable factory test"
default n
select BOOTLOADER_INIT_SPI_FLASH
help
Enable this option, project compiling script will generate factory test firmware.
endmenu

View File

@ -0,0 +1,4 @@
PROJECT_NAME := factory-test
include $(IDF_PATH)/make/project.mk

View File

@ -0,0 +1,4 @@
# Important
Please refer to the document at *docs/en/api-guides/factory-test.rst*.

View File

@ -0,0 +1,9 @@
menu "Nano Console"
config NC_ECHO_CMD
bool "echo input command"
default y
help
Enable this option, the console terminal will echo the input command.
endmenu

View File

@ -0,0 +1,2 @@
CFLAGS += -DESP_DPORT_CLOSE_NMI

View File

@ -0,0 +1,8 @@
#
# Component Makefile
#
LIBS := rftest
COMPONENT_ADD_LDFLAGS += -L$(COMPONENT_PATH)/lib $(addprefix -l,$(LIBS))
COMPONENT_ADD_LINKER_DEPS += $(patsubst %,$(COMPONENT_PATH)/lib/lib%.a,$(LIBS))

View File

@ -0,0 +1,81 @@
// Copyright 2019-2020 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 <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Initialize RF test module
*/
void rftest_init(void);
/**
* @brief Set TX testing mode
*
* @param mode testing mode, 1 means continuous Wi-Fi packets transmission with 92% duty cycle
* 0 means default mode for iqview testing
*/
void tx_contin_func(uint8_t mode);
/**
* @brief TX testing function, continuously sending Wi-Fi packets at "while(1)" loop
*
* @param channel Wi-Fi TX channel, it ranges from 1 to 14
* @param rate Wi-Fi TX rate, it ranges from 1 to 23
* @param attenuation Wi-Fi TX power attenuation, it ranges from 1 to 127 and its unit is 0.25dB.
* For example, 1 means 0.25dB, 2 means 0.5 dB and so on.
*/
void esp_tx_func(uint32_t channel, uint32_t rate, uint32_t attenuation);
/**
* @brief RX testing function, continuously receiving Wi-Fi packets at "while(1)" loop
*
* @param channel Wi-Fi RX channel, it ranges from 1 to 14
* @param rate Wi-Fi RX rate, it ranges from 1 to 23
*/
void esp_rx_func(uint32_t channel, uint32_t rate);
/**
* @brief Single carrier TX testing function
*
* @param enable enable signal, 1 means starting sending, 0 means stopping sending
* @param channel Wi-Fi RX channel, it ranges from 1 to 14
* @param attenuation Wi-Fi TX power attenuation, it ranges from 1 to 127 and its unit is 0.25dB.
* For example, 1 means 0.25dB, 2 means 0.5 dB and so on.
*/
void wifiscwout_func(uint32_t enable, uint32_t channel, uint32_t attenuation);
/**
* @brief Stop sending or recieving Wi-Fi packets
*
* @return
* - 0 receiving stop TX commands "cmdstop" or "CmdStop" and TX is stopped
* - 2 receiving error commands and TX will not stop
* - 3 receiving no commands
*/
int cmdstop_callback(void);
/**
* @brief Register RF test command for console
*/
void esp_console_register_rftest_command(void);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,69 @@
// Copyright 2019-2020 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>
#include <sys/queue.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef int (*nc_func_t)(int argc, char **argv);
/**
* @brief Command data structure
*/
typedef struct _nc_cmd {
SLIST_ENTRY(_nc_cmd) entries; //!< queue entry
const char *name; //!< command name
nc_func_t func; //!< command callback function
} nc_cmd_t;
typedef nc_cmd_t* nc_cmd_handle_t;
/**
* @brief Initialize nano console
*
* @return 0 if success or others if fail
*/
int nc_init(void);
/**
* @brief Register a command to nano console core
*
* @param[out] handle created command handle to users
* @param[in] name command name
* @param[in] func command callback function
*
* @return 0 if success or others if fail
*
* @note The function only can be called before "nc_init"
*/
int nc_register_cmd(nc_cmd_handle_t *handle, const char *name, nc_func_t func);
/**
* @brief Output formated string through nano console I/O stream
*
* @param[in] fmt format string
* @param[in] ... command arguments' value list
*
* @return output string number or negative value if fail
*/
int nc_printf(const char *fmt, ...);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,296 @@
// Copyright 2019-2020 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.
#define LOG_LOCAL_LEVEL ESP_LOG_NONE
#include <stdint.h>
#include <string.h>
#include <assert.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdbool.h>
#include <ctype.h>
#include <sys/errno.h>
#include "esp_log.h"
#include "nano_console.h"
#define TAG "nano_console"
#define NC_READ_BUF 128
static SLIST_HEAD(_nc_cmd_head , _nc_cmd) s_nc_cmd = SLIST_HEAD_INITIALIZER(s_nc_cmd);
static inline nc_cmd_t *get_cmd(const char *buf)
{
nc_cmd_t *it;
SLIST_FOREACH(it, &s_nc_cmd, entries) {
if (!strcmp(it->name, buf)) {
ESP_LOGD(TAG, "%s finds command %s", __func__, buf);
return it;
}
}
ESP_LOGD(TAG, "%s has not found command %s", __func__, buf);
return NULL;
}
static void free_args(uintptr_t *argv)
{
int num = (int)argv[0];
for (int i = 1; i < num; i++) {
if (argv[i])
free((void *)argv[i]);
else {
ESP_LOGD(TAG, "%s checks command input arguments number %d is empty", __func__, i);
}
}
free(argv);
}
static uintptr_t *alloc_args(const char *buf, int num)
{
const char *p = buf;
uintptr_t *argv_buf;
int cnt = 0;
for (int i = 0; i < num; i++) {
if (p[i] == '\0')
cnt++;
}
argv_buf = calloc(1, (cnt + 1) * sizeof(uintptr_t));
if (!argv_buf) {
ESP_LOGE(TAG, "%s allocates memory for arguments table fail", __func__);
return NULL;
}
argv_buf[0] = (uintptr_t)cnt + 1;
for (int i = 0; i < cnt; i++) {
int len = strlen(p) + 1;
char *s = malloc(len);
if (!s) {
ESP_LOGE(TAG, "%s allocates memory for arguments %d fail", __func__, i);
goto fail;
}
memcpy(s, p, len);
p += len;
argv_buf[i + 1] = (uintptr_t)s;
}
return argv_buf;
fail:
free_args(argv_buf);
return NULL;
}
static void *nc_thread_entry(void *p)
{
int num = 0;
char *pbuf;
pbuf = malloc(NC_READ_BUF);
if (!pbuf) {
ESP_LOGE(TAG, "%s malloc %d bytes buffer fail", __func__, NC_READ_BUF);
goto nomem;
}
while (1) {
int ret;
size_t rbytes;
char c;
rbytes = fread(&c, 1, 1, stdin);
if (rbytes != 1) {
ESP_LOGE(TAG, "%s read character fail", __func__);
goto io_err;
}
if (num >= NC_READ_BUF - 1) {
ESP_LOGD(TAG, "%s input stream overflows, reset the buffer", __func__);
num = 0;
continue;
}
if (!isascii(c)) {
ESP_LOGD(TAG, "%s input character is not ASCII", __func__);
continue;
}
if (c == '\r' || c == '\n') {
nc_cmd_t *cmd;
#ifdef CONFIG_NC_ECHO_CMD
ret = fwrite(&c, 1, 1, stdout);
if (ret != 1) {
ESP_LOGE(TAG, "%s %d write character fail %d", __func__, __LINE__, ret);
goto io_err;
}
#endif
if (!num) {
ESP_LOGD(TAG, "%s gets command %s argument fail", __func__, cmd->name);
continue;
}
if (pbuf[num - 1] != '\0')
pbuf[num++] = '\0';
cmd = get_cmd(pbuf);
if (cmd) {
uintptr_t *argv;
argv = alloc_args(pbuf, num);
if (!argv) {
ESP_LOGE(TAG, "%s gets command %s argument fail", __func__, cmd->name);
num = 0;
continue;
}
cmd->func((int)argv[0] - 1, (char **)(&argv[1]));
free_args(argv);
}
num = 0;
} else if (c == ' ') {
if (num && pbuf[num] != ' ') {
pbuf[num++] = '\0';
#ifdef CONFIG_NC_ECHO_CMD
ret = fwrite(&c, 1, 1, stdout);
if (ret != 1) {
ESP_LOGE(TAG, "%s %d write character fail %d", __func__, __LINE__, ret);
goto io_err;
}
#endif
}
} else if (c == 0x8 || c == 0x7f) {
if (num) {
num--;
#ifdef CONFIG_NC_ECHO_CMD
char tmp[3] = {c, ' ', c};
ret = fwrite(&tmp, 1, 3, stdout);
if (ret != 3) {
ESP_LOGE(TAG, "%s %d write character fail %d", __func__, __LINE__, ret);
goto io_err;
}
#endif
}
} else {
pbuf[num++] = c;
#ifdef CONFIG_NC_ECHO_CMD
ret = fwrite(&c, 1, 1, stdout);
if (ret != 1) {
ESP_LOGE(TAG, "%s %d write character fail %d", __func__, __LINE__, ret);
goto io_err;
}
#endif
}
}
io_err:
free(pbuf);
nomem:
return (void *)(-ENOMEM);
}
/**
* @brief Initialize nano console
*/
int nc_init(void)
{
int ret;
pthread_t tid;
ret = pthread_create(&tid, NULL, nc_thread_entry, NULL);
if (ret) {
ESP_LOGE(TAG, "%s creates thread fail %d", __func__, ret);
return -1;
}
return 0;
}
/**
* @brief Register a command to nano console core
*/
int nc_register_cmd(nc_cmd_handle_t *handle, const char *name, nc_func_t func)
{
int len;
va_list ap;
nc_cmd_t *cmd;
cmd = malloc(sizeof(nc_cmd_t));
if (!cmd) {
ESP_LOGE(TAG, "%s alloc memory %d fail", __func__, __LINE__);
return -ENOMEM;
}
len = strlen(name) + 1;
cmd->name = malloc(len);
if (!cmd->name) {
ESP_LOGE(TAG, "%s alloc memory %d fail", __func__, __LINE__);
goto nomem;
}
memcpy((char *)cmd->name, name, len);
cmd->func = func;
SLIST_INSERT_HEAD(&s_nc_cmd, cmd, entries);
*handle = cmd;
va_end(ap);
return 0;
nomem:
free(cmd);
return -ENOMEM;
}
/**
* @brief Output formated string through nano console I/O stream
*/
int nc_printf(const char *fmt, ...)
{
va_list ap;
char *pbuf;
va_start(ap, fmt);
int ret = vasprintf(&pbuf, fmt, ap);
if (ret < 0)
goto fail;
ret = fwrite(pbuf, 1, ret, stdout);
free(pbuf);
va_end(ap);
return ret;
fail:
va_end(ap);
return -ENOMEM;
}

View File

@ -0,0 +1,417 @@
// Copyright 2019-2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stdio.h>
#include <stdlib.h>
#include <sys/errno.h>
#include "esp_rftest.h"
#include "esp_log.h"
#include "esp_wifi.h"
#include "esp8266/eagle_soc.h"
#include "FreeRTOS.h"
#include "task.h"
#include "driver/soc.h"
#include "nano_console.h"
#define TAG "factory-test"
typedef struct tx_param {
uint32_t channel;
uint32_t rate;
uint32_t attenuation;
} tx_param_t;
typedef struct rx_param {
uint32_t channel;
uint32_t rate;
} rx_param_t;
typedef struct wifiscwout_param {
uint32_t en;
uint32_t channel;
uint32_t attenuation;
} wifiscwout_param_t;
static int s_cmdstop = 0;
static int set_wifi_work(void)
{
int ret;
esp_irqflag_t flag;
flag = soc_save_local_irq();
if (s_cmdstop == 0) {
s_cmdstop = 3;
ret = 0;
} else
ret = -EINPROGRESS;
soc_restore_local_irq(flag);
return ret;
}
static int set_wifi_free(void)
{
esp_irqflag_t flag;
flag = soc_save_local_irq();
s_cmdstop = 0;
soc_restore_local_irq(flag);
return 0;
}
static int test_rftest_init(int argc, char **argv)
{
if (argc != 1) {
ESP_LOGE(TAG, "%s %d command is error", __func__, __LINE__);
return -EINVAL;
}
ESP_LOGD(__func__, "%s start initializing WiFi test", __func__);
if (set_wifi_work())
goto exit;
rftest_init();
set_wifi_free();
ESP_LOGD(__func__, "%s end initializing WiFi test", __func__);
return 0;
exit:
ESP_LOGD(__func__, "%s fail to initialize WiFi test", __func__);
return -EINPROGRESS;
}
static int test_tx_contin_en(int argc, char **argv)
{
if (argc != 2) {
ESP_LOGE(TAG, "%s %d command is error", __func__, __LINE__);
return -EINVAL;
}
int mode = atoi(argv[1]);
if (mode < 0 || mode > 1) {
ESP_LOGE(TAG, "%s %d command is error", __func__, __LINE__);
return -EINVAL;
}
ESP_LOGD(__func__, "%s start setting mode '%d'", __func__ , mode);
if (set_wifi_work())
goto exit;
tx_contin_func(mode);
set_wifi_free();
ESP_LOGD(__func__, "%s end setting mode '%d'", __func__ , mode);
return 0;
exit:
ESP_LOGD(__func__, "%s fail to set mode '%d'", __func__ , mode);
return -EINPROGRESS;
}
static void test_wifi_tx_thread(void *param)
{
tx_param_t *tx_param = (tx_param_t *)param;
esp_tx_func(tx_param->channel, tx_param->rate, tx_param->attenuation);
free(tx_param);
set_wifi_free();
vTaskDelete(NULL);
}
static int test_esp_tx_func(int argc, char **argv)
{
if (argc != 4) {
ESP_LOGE(TAG, "%s %d command is error", __func__, __LINE__);
return -EINVAL;
}
int channel = atoi(argv[1]);
if (channel <= 0 || channel > 14) {
ESP_LOGE(TAG, "%s %d command is error", __func__, __LINE__);
return -EINVAL;
}
int rate = atoi(argv[2]);
if (rate < 0 || rate > 23) {
ESP_LOGE(TAG, "%s %d command is error", __func__, __LINE__);
return -EINVAL;
}
int attenuation = atoi(argv[3]);
if (attenuation < -127 || attenuation > 127) {
ESP_LOGE(TAG, "%s %d command is error", __func__, __LINE__);
return -EINVAL;
}
ESP_LOGD(__func__, "%s start creating task with channel '%d' rate '%d' attenuation '%d'", __func__, channel, rate, attenuation);
if (set_wifi_work())
goto exit;
tx_param_t *tx_param = malloc(sizeof(tx_param_t));
if (!tx_param)
goto exit;
tx_param->channel = channel;
tx_param->rate = rate;
tx_param->attenuation = attenuation;
const size_t wifi_tx_stk_size = 4096;
const size_t wifi_tx_priority = 3;
BaseType_t ret = xTaskCreate(test_wifi_tx_thread, "wifi_tx", wifi_tx_stk_size, tx_param, wifi_tx_priority, NULL);
if (ret != pdPASS)
goto task_err;
ESP_LOGD(__func__, "%s end creating task with channel '%d' rate '%d' attenuation '%d'", __func__, channel, rate, attenuation);
return 0;
task_err:
free(tx_param);
exit:
ESP_LOGD(__func__, "%s fail to create task with channel '%d' rate '%d' attenuation '%d'", __func__, channel, rate, attenuation);
return -ENOMEM;
}
static void test_wifi_rx_thread(void *param)
{
rx_param_t *rx_param = (rx_param_t *)param;
esp_rx_func(rx_param->channel, rx_param->rate);
free(rx_param);
set_wifi_free();
vTaskDelete(NULL);
}
static int test_esp_rx_func(int argc, char **argv)
{
if (argc != 3) {
ESP_LOGE(TAG, "%s %d command is error", __func__, __LINE__);
return -EINVAL;
}
int channel = atoi(argv[1]);
if (channel <= 0 || channel > 14) {
ESP_LOGE(TAG, "%s %d command is error", __func__, __LINE__);
return -EINVAL;
}
int rate = atoi(argv[2]);
if (rate < 0 || rate > 23) {
ESP_LOGE(TAG, "%s %d command is error", __func__, __LINE__);
return -EINVAL;
}
ESP_LOGD(__func__, "%s start creating task with channel '%d' rate '%d'", __func__, channel, rate);
if (set_wifi_work())
goto exit;
rx_param_t *rx_param = malloc(sizeof(rx_param_t));
if (!rx_param)
goto exit;
rx_param->channel = channel;
rx_param->rate = rate;
const size_t wifi_rx_stk_size = 4096;
const size_t wifi_rx_priority = 3;
BaseType_t ret = xTaskCreate(test_wifi_rx_thread, "wifi_rx", wifi_rx_stk_size, rx_param, wifi_rx_priority, NULL);
if (ret != pdPASS)
goto task_err;
ESP_LOGD(__func__, "%s end creating task with channel '%d' rate '%d'", __func__, channel, rate);
return 0;
task_err:
free(rx_param);
exit:
ESP_LOGD(__func__, "%s fail to create task with channel '%d' rate '%d'", __func__, channel, rate);
return -ENOMEM;
}
static void test_wifi_wifiscwout_thread(void *param)
{
wifiscwout_param_t *wifiscwout_param = (wifiscwout_param_t *)param;
wifiscwout_func(wifiscwout_param->en, wifiscwout_param->channel, wifiscwout_param->attenuation);
free(wifiscwout_param);
set_wifi_free();
vTaskDelete(NULL);
}
static int test_wifiscwout_func(int argc, char **argv)
{
if (argc != 4) {
ESP_LOGE(TAG, "%s %d command is error", __func__, __LINE__);
return -EINVAL;
}
int en = atoi(argv[1]);
if (en < 0 || en > 2) {
ESP_LOGE(TAG, "%s %d command is error", __func__, __LINE__);
return -EINVAL;
}
int channel = atoi(argv[2]);
if (channel <= 0 || channel > 14) {
ESP_LOGE(TAG, "%s %d command is error", __func__, __LINE__);
return -EINVAL;
}
int attenuation = atoi(argv[3]);
if (attenuation < -127 || attenuation > 127) {
ESP_LOGE(TAG, "%s %d command is error", __func__, __LINE__);
return -EINVAL;
}
ESP_LOGD(__func__, "%s start creating task with enable '%d' channel '%d' attenuation '%d'", __func__, en, channel, attenuation);
if (set_wifi_work())
goto exit;
wifiscwout_param_t *wifiscwout_param = malloc(sizeof(wifiscwout_param_t));
if (!wifiscwout_param)
goto exit;
wifiscwout_param->en = en;
wifiscwout_param->channel = channel;
wifiscwout_param->attenuation = attenuation;
const size_t wifi_wifiscwout_stk_size = 4096;
const size_t wifi_wifiscwout_priority = 3;
BaseType_t ret = xTaskCreate(test_wifi_wifiscwout_thread, "wifi_tx", wifi_wifiscwout_stk_size, wifiscwout_param, wifi_wifiscwout_priority, NULL);
if (ret != pdPASS)
goto task_err;
ESP_LOGD(__func__, "%s end creating task with enable '%d' channel '%d' attenuation '%d'", __func__, en, channel, attenuation);
return 0;
task_err:
free(wifiscwout_param);
exit:
ESP_LOGD(__func__, "%s fail to create task with enable '%d' channel '%d' attenuation '%d'", __func__, en, channel, attenuation);
return -ENOMEM;
}
static int test_cmdstop_func(int argc, char **argv)
{
if (argc != 1) {
ESP_LOGE(TAG, "%s %d command is error", __func__, __LINE__);
return -EINVAL;
}
ESP_LOGD(__func__, "%s cmdstop '%d'", __func__, s_cmdstop);
s_cmdstop = 0;
ESP_LOGD(__func__, "status is %x\n", REG_READ(INT_ENA_WDEV));
return 0;
}
static void register_rftest_init(void)
{
nc_cmd_t *nc_cmd;
ESP_ERROR_CHECK(nc_register_cmd(&nc_cmd, "rftest_init", test_rftest_init));
}
static void register_tx_contin_en(void)
{
nc_cmd_handle_t nc_cmd;
ESP_ERROR_CHECK(nc_register_cmd(&nc_cmd, "tx_contin_en", test_tx_contin_en));
}
static void register_esp_tx_func(void)
{
nc_cmd_handle_t nc_cmd;
ESP_ERROR_CHECK(nc_register_cmd(&nc_cmd, "esp_tx", test_esp_tx_func));
ESP_ERROR_CHECK(nc_register_cmd(&nc_cmd, "wifitxout", test_esp_tx_func));
}
static void register_esp_rx_func(void)
{
nc_cmd_handle_t nc_cmd;
ESP_ERROR_CHECK(nc_register_cmd(&nc_cmd, "esp_rx", test_esp_rx_func));
}
static void register_wifiscwout_func(void)
{
nc_cmd_handle_t nc_cmd;
ESP_ERROR_CHECK(nc_register_cmd(&nc_cmd, "wifiscwout", test_wifiscwout_func));
}
static void register_cmdstop_func(void)
{
nc_cmd_handle_t nc_cmd;
ESP_ERROR_CHECK(nc_register_cmd(&nc_cmd, "cmdstop", test_cmdstop_func));
ESP_ERROR_CHECK(nc_register_cmd(&nc_cmd, "CmdStop", test_cmdstop_func));
}
void esp_console_register_rftest_command(void)
{
extern void esp_dport_close_nmi(void);
esp_dport_close_nmi();
register_rftest_init();
register_tx_contin_en();
register_esp_tx_func();
register_esp_rx_func();
register_wifiscwout_func();
register_cmdstop_func();
}
int __attribute__((weak)) cmdstop_callback(void)
{
return s_cmdstop;
}

View File

@ -0,0 +1,6 @@
#
# Main factory-test Makefile.
#
# This is basically the same as a component makefile, but in the case of the factory-test
# we pull in factory-test-specific linker arguments.
#

View File

@ -0,0 +1,72 @@
// Copyright 2019-2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stdio.h>
#include <assert.h>
#include "esp_system.h"
#include "esp_rftest.h"
#include "esp_log.h"
#include "esp_vfs_dev.h"
#include "FreeRTOS.h"
#include "driver/uart.h"
#include "nano_console.h"
#include "esp_libc.h"
#ifndef ESP_FACTORY_TEST_EXTRA_COMPONENTS
#define CONFIG_CONSOLE_UART_NUM 0
#define TAG "factory-test"
static void initialize_console()
{
/* Disable buffering on stdin */
setvbuf(stdin, NULL, _IONBF, 0);
/* Minicom, screen, idf_monitor send CR when ENTER key is pressed */
esp_vfs_dev_uart_set_rx_line_endings(ESP_LINE_ENDINGS_CR);
/* Move the caret to the beginning of the next line on '\n' */
esp_vfs_dev_uart_set_tx_line_endings(ESP_LINE_ENDINGS_CRLF);
/* Configure UART. Note that REF_TICK is used so that the baud rate remains
* correct while APB frequency is changing in light sleep mode.
*/
uart_config_t uart_config = {
.baud_rate = CONFIG_CONSOLE_UART_BAUDRATE,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
};
ESP_ERROR_CHECK(uart_param_config(CONFIG_CONSOLE_UART_NUM, &uart_config));
/* Install UART driver for interrupt-driven reads and writes */
ESP_ERROR_CHECK(uart_driver_install(CONFIG_CONSOLE_UART_NUM,
256, 0, 0, NULL));
/* Tell VFS to use UART driver */
esp_vfs_dev_uart_use_driver(CONFIG_CONSOLE_UART_NUM);
esp_console_register_rftest_command();
ESP_ERROR_CHECK(nc_init());
}
void __attribute__((weak)) app_main(void)
{
ESP_LOGI(TAG, "SDK factory test firmware version:%s\n", esp_get_idf_version());
initialize_console();
}
#endif /* ESP_FACTORY_TEST_EXTRA_COMPONENTS */

View File

@ -0,0 +1,21 @@
#
# Virtual file system
#
CONFIG_USING_ESP_VFS=y
#
# PThreads
#
CONFIG_ENABLE_PTHREAD=y
#
# Partition Table
#
CONFIG_PARTITION_TABLE_TWO_OTA=y
#
# Bootloader config
#
CONFIG_BOOTLOADER_APP_TEST=y
CONFIG_BOOTLOADER_APP_TEST_IN_OTA_1=y
CONFIG_BOOTLOADER_NUM_PIN_APP_TEST=12