mirror of
https://github.com/espressif/ESP8266_RTOS_SDK.git
synced 2025-05-22 09:37:00 +08:00
Merge branch 'feature/esp_console' into 'master'
Bring console and its example from esp-idf See merge request sdk/ESP8266_RTOS_SDK!895
This commit is contained in:
15
components/console/CMakeLists.txt
Normal file
15
components/console/CMakeLists.txt
Normal file
@ -0,0 +1,15 @@
|
||||
if(CONFIG_USING_ESP_CONSOLE)
|
||||
set(COMPONENT_ADD_INCLUDEDIRS .)
|
||||
set(COMPONENT_SRCS "commands.c"
|
||||
"split_argv.c"
|
||||
"argtable3/argtable3.c"
|
||||
"linenoise/linenoise.c")
|
||||
else()
|
||||
set(COMPONENT_ADD_INCLUDEDIRS "")
|
||||
set(COMPONENT_SRCS "")
|
||||
endif()
|
||||
|
||||
set(COMPONENT_REQUIRES)
|
||||
|
||||
register_component()
|
||||
|
10
components/console/Kconfig
Normal file
10
components/console/Kconfig
Normal file
@ -0,0 +1,10 @@
|
||||
menu "Console"
|
||||
|
||||
config USING_ESP_CONSOLE
|
||||
bool "Using Espressif Console"
|
||||
default n
|
||||
select USING_ESP_VFS
|
||||
help
|
||||
Enable this option, espressif console can be used.
|
||||
|
||||
endmenu
|
26
components/console/argtable3/LICENSE
Normal file
26
components/console/argtable3/LICENSE
Normal file
@ -0,0 +1,26 @@
|
||||
Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann
|
||||
<sheitmann@users.sourceforge.net>
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of STEWART HEITMANN nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
4956
components/console/argtable3/argtable3.c
Normal file
4956
components/console/argtable3/argtable3.c
Normal file
File diff suppressed because it is too large
Load Diff
306
components/console/argtable3/argtable3.h
Normal file
306
components/console/argtable3/argtable3.h
Normal file
@ -0,0 +1,306 @@
|
||||
/*******************************************************************************
|
||||
* This file is part of the argtable3 library.
|
||||
*
|
||||
* Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann
|
||||
* <sheitmann@users.sourceforge.net>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of STEWART HEITMANN nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef ARGTABLE3
|
||||
#define ARGTABLE3
|
||||
|
||||
#include <stdio.h> /* FILE */
|
||||
#include <time.h> /* struct tm */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ARG_REX_ICASE 1
|
||||
|
||||
/* bit masks for arg_hdr.flag */
|
||||
enum
|
||||
{
|
||||
ARG_TERMINATOR=0x1,
|
||||
ARG_HASVALUE=0x2,
|
||||
ARG_HASOPTVALUE=0x4
|
||||
};
|
||||
|
||||
typedef void (arg_resetfn)(void *parent);
|
||||
typedef int (arg_scanfn)(void *parent, const char *argval);
|
||||
typedef int (arg_checkfn)(void *parent);
|
||||
typedef void (arg_errorfn)(void *parent, FILE *fp, int error, const char *argval, const char *progname);
|
||||
|
||||
|
||||
/*
|
||||
* The arg_hdr struct defines properties that are common to all arg_xxx structs.
|
||||
* The argtable library requires each arg_xxx struct to have an arg_hdr
|
||||
* struct as its first data member.
|
||||
* The argtable library functions then use this data to identify the
|
||||
* properties of the command line option, such as its option tags,
|
||||
* datatype string, and glossary strings, and so on.
|
||||
* Moreover, the arg_hdr struct contains pointers to custom functions that
|
||||
* are provided by each arg_xxx struct which perform the tasks of parsing
|
||||
* that particular arg_xxx arguments, performing post-parse checks, and
|
||||
* reporting errors.
|
||||
* These functions are private to the individual arg_xxx source code
|
||||
* and are the pointer to them are initiliased by that arg_xxx struct's
|
||||
* constructor function. The user could alter them after construction
|
||||
* if desired, but the original intention is for them to be set by the
|
||||
* constructor and left unaltered.
|
||||
*/
|
||||
struct arg_hdr
|
||||
{
|
||||
char flag; /* Modifier flags: ARG_TERMINATOR, ARG_HASVALUE. */
|
||||
const char *shortopts; /* String defining the short options */
|
||||
const char *longopts; /* String defiing the long options */
|
||||
const char *datatype; /* Description of the argument data type */
|
||||
const char *glossary; /* Description of the option as shown by arg_print_glossary function */
|
||||
int mincount; /* Minimum number of occurences of this option accepted */
|
||||
int maxcount; /* Maximum number of occurences if this option accepted */
|
||||
void *parent; /* Pointer to parent arg_xxx struct */
|
||||
arg_resetfn *resetfn; /* Pointer to parent arg_xxx reset function */
|
||||
arg_scanfn *scanfn; /* Pointer to parent arg_xxx scan function */
|
||||
arg_checkfn *checkfn; /* Pointer to parent arg_xxx check function */
|
||||
arg_errorfn *errorfn; /* Pointer to parent arg_xxx error function */
|
||||
void *priv; /* Pointer to private header data for use by arg_xxx functions */
|
||||
};
|
||||
|
||||
struct arg_rem
|
||||
{
|
||||
struct arg_hdr hdr; /* The mandatory argtable header struct */
|
||||
};
|
||||
|
||||
struct arg_lit
|
||||
{
|
||||
struct arg_hdr hdr; /* The mandatory argtable header struct */
|
||||
int count; /* Number of matching command line args */
|
||||
};
|
||||
|
||||
struct arg_int
|
||||
{
|
||||
struct arg_hdr hdr; /* The mandatory argtable header struct */
|
||||
int count; /* Number of matching command line args */
|
||||
int *ival; /* Array of parsed argument values */
|
||||
};
|
||||
|
||||
struct arg_dbl
|
||||
{
|
||||
struct arg_hdr hdr; /* The mandatory argtable header struct */
|
||||
int count; /* Number of matching command line args */
|
||||
double *dval; /* Array of parsed argument values */
|
||||
};
|
||||
|
||||
struct arg_str
|
||||
{
|
||||
struct arg_hdr hdr; /* The mandatory argtable header struct */
|
||||
int count; /* Number of matching command line args */
|
||||
const char **sval; /* Array of parsed argument values */
|
||||
};
|
||||
|
||||
struct arg_rex
|
||||
{
|
||||
struct arg_hdr hdr; /* The mandatory argtable header struct */
|
||||
int count; /* Number of matching command line args */
|
||||
const char **sval; /* Array of parsed argument values */
|
||||
};
|
||||
|
||||
struct arg_file
|
||||
{
|
||||
struct arg_hdr hdr; /* The mandatory argtable header struct */
|
||||
int count; /* Number of matching command line args*/
|
||||
const char **filename; /* Array of parsed filenames (eg: /home/foo.bar) */
|
||||
const char **basename; /* Array of parsed basenames (eg: foo.bar) */
|
||||
const char **extension; /* Array of parsed extensions (eg: .bar) */
|
||||
};
|
||||
|
||||
struct arg_date
|
||||
{
|
||||
struct arg_hdr hdr; /* The mandatory argtable header struct */
|
||||
const char *format; /* strptime format string used to parse the date */
|
||||
int count; /* Number of matching command line args */
|
||||
struct tm *tmval; /* Array of parsed time values */
|
||||
};
|
||||
|
||||
enum {ARG_ELIMIT=1, ARG_EMALLOC, ARG_ENOMATCH, ARG_ELONGOPT, ARG_EMISSARG};
|
||||
struct arg_end
|
||||
{
|
||||
struct arg_hdr hdr; /* The mandatory argtable header struct */
|
||||
int count; /* Number of errors encountered */
|
||||
int *error; /* Array of error codes */
|
||||
void **parent; /* Array of pointers to offending arg_xxx struct */
|
||||
const char **argval; /* Array of pointers to offending argv[] string */
|
||||
};
|
||||
|
||||
|
||||
/**** arg_xxx constructor functions *********************************/
|
||||
|
||||
struct arg_rem* arg_rem(const char* datatype, const char* glossary);
|
||||
|
||||
struct arg_lit* arg_lit0(const char* shortopts,
|
||||
const char* longopts,
|
||||
const char* glossary);
|
||||
struct arg_lit* arg_lit1(const char* shortopts,
|
||||
const char* longopts,
|
||||
const char *glossary);
|
||||
struct arg_lit* arg_litn(const char* shortopts,
|
||||
const char* longopts,
|
||||
int mincount,
|
||||
int maxcount,
|
||||
const char *glossary);
|
||||
|
||||
struct arg_key* arg_key0(const char* keyword,
|
||||
int flags,
|
||||
const char* glossary);
|
||||
struct arg_key* arg_key1(const char* keyword,
|
||||
int flags,
|
||||
const char* glossary);
|
||||
struct arg_key* arg_keyn(const char* keyword,
|
||||
int flags,
|
||||
int mincount,
|
||||
int maxcount,
|
||||
const char* glossary);
|
||||
|
||||
struct arg_int* arg_int0(const char* shortopts,
|
||||
const char* longopts,
|
||||
const char* datatype,
|
||||
const char* glossary);
|
||||
struct arg_int* arg_int1(const char* shortopts,
|
||||
const char* longopts,
|
||||
const char* datatype,
|
||||
const char *glossary);
|
||||
struct arg_int* arg_intn(const char* shortopts,
|
||||
const char* longopts,
|
||||
const char *datatype,
|
||||
int mincount,
|
||||
int maxcount,
|
||||
const char *glossary);
|
||||
|
||||
struct arg_dbl* arg_dbl0(const char* shortopts,
|
||||
const char* longopts,
|
||||
const char* datatype,
|
||||
const char* glossary);
|
||||
struct arg_dbl* arg_dbl1(const char* shortopts,
|
||||
const char* longopts,
|
||||
const char* datatype,
|
||||
const char *glossary);
|
||||
struct arg_dbl* arg_dbln(const char* shortopts,
|
||||
const char* longopts,
|
||||
const char *datatype,
|
||||
int mincount,
|
||||
int maxcount,
|
||||
const char *glossary);
|
||||
|
||||
struct arg_str* arg_str0(const char* shortopts,
|
||||
const char* longopts,
|
||||
const char* datatype,
|
||||
const char* glossary);
|
||||
struct arg_str* arg_str1(const char* shortopts,
|
||||
const char* longopts,
|
||||
const char* datatype,
|
||||
const char *glossary);
|
||||
struct arg_str* arg_strn(const char* shortopts,
|
||||
const char* longopts,
|
||||
const char* datatype,
|
||||
int mincount,
|
||||
int maxcount,
|
||||
const char *glossary);
|
||||
|
||||
struct arg_rex* arg_rex0(const char* shortopts,
|
||||
const char* longopts,
|
||||
const char* pattern,
|
||||
const char* datatype,
|
||||
int flags,
|
||||
const char* glossary);
|
||||
struct arg_rex* arg_rex1(const char* shortopts,
|
||||
const char* longopts,
|
||||
const char* pattern,
|
||||
const char* datatype,
|
||||
int flags,
|
||||
const char *glossary);
|
||||
struct arg_rex* arg_rexn(const char* shortopts,
|
||||
const char* longopts,
|
||||
const char* pattern,
|
||||
const char* datatype,
|
||||
int mincount,
|
||||
int maxcount,
|
||||
int flags,
|
||||
const char *glossary);
|
||||
|
||||
struct arg_file* arg_file0(const char* shortopts,
|
||||
const char* longopts,
|
||||
const char* datatype,
|
||||
const char* glossary);
|
||||
struct arg_file* arg_file1(const char* shortopts,
|
||||
const char* longopts,
|
||||
const char* datatype,
|
||||
const char *glossary);
|
||||
struct arg_file* arg_filen(const char* shortopts,
|
||||
const char* longopts,
|
||||
const char* datatype,
|
||||
int mincount,
|
||||
int maxcount,
|
||||
const char *glossary);
|
||||
|
||||
struct arg_date* arg_date0(const char* shortopts,
|
||||
const char* longopts,
|
||||
const char* format,
|
||||
const char* datatype,
|
||||
const char* glossary);
|
||||
struct arg_date* arg_date1(const char* shortopts,
|
||||
const char* longopts,
|
||||
const char* format,
|
||||
const char* datatype,
|
||||
const char *glossary);
|
||||
struct arg_date* arg_daten(const char* shortopts,
|
||||
const char* longopts,
|
||||
const char* format,
|
||||
const char* datatype,
|
||||
int mincount,
|
||||
int maxcount,
|
||||
const char *glossary);
|
||||
|
||||
struct arg_end* arg_end(int maxerrors);
|
||||
|
||||
|
||||
/**** other functions *******************************************/
|
||||
int arg_nullcheck(void **argtable);
|
||||
int arg_parse(int argc, char **argv, void **argtable);
|
||||
void arg_print_option(FILE *fp, const char *shortopts, const char *longopts, const char *datatype, const char *suffix);
|
||||
void arg_print_syntax(FILE *fp, void **argtable, const char *suffix);
|
||||
void arg_print_syntaxv(FILE *fp, void **argtable, const char *suffix);
|
||||
void arg_print_glossary(FILE *fp, void **argtable, const char *format);
|
||||
void arg_print_glossary_gnu(FILE *fp, void **argtable);
|
||||
void arg_print_errors(FILE* fp, struct arg_end* end, const char* progname);
|
||||
void arg_freetable(void **argtable, size_t n);
|
||||
void arg_print_formatted(FILE *fp, const unsigned lmargin, const unsigned rmargin, const char *text);
|
||||
|
||||
/**** deprecated functions, for back-compatibility only ********/
|
||||
void arg_free(void **argtable);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
243
components/console/commands.c
Normal file
243
components/console/commands.c
Normal file
@ -0,0 +1,243 @@
|
||||
// Copyright 2016-2017 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 <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/param.h>
|
||||
#include "esp_log.h"
|
||||
#include "esp_console.h"
|
||||
#include "linenoise/linenoise.h"
|
||||
#include "argtable3/argtable3.h"
|
||||
#include "rom/queue.h"
|
||||
|
||||
#define ANSI_COLOR_DEFAULT 39 /** Default foreground color */
|
||||
|
||||
typedef struct cmd_item_ {
|
||||
/**
|
||||
* Command name (statically allocated by application)
|
||||
*/
|
||||
const char *command;
|
||||
/**
|
||||
* Help text (statically allocated by application), may be NULL.
|
||||
*/
|
||||
const char *help;
|
||||
/**
|
||||
* Hint text, usually lists possible arguments, dynamically allocated.
|
||||
* May be NULL.
|
||||
*/
|
||||
char *hint;
|
||||
esp_console_cmd_func_t func; //!< pointer to the command handler
|
||||
void *argtable; //!< optional pointer to arg table
|
||||
SLIST_ENTRY(cmd_item_) next; //!< next command in the list
|
||||
} cmd_item_t;
|
||||
|
||||
/** linked list of command structures */
|
||||
static SLIST_HEAD(cmd_list_, cmd_item_) s_cmd_list;
|
||||
|
||||
/** run-time configuration options */
|
||||
static esp_console_config_t s_config;
|
||||
|
||||
/** temporary buffer used for command line parsing */
|
||||
static char *s_tmp_line_buf;
|
||||
|
||||
static const cmd_item_t *find_command_by_name(const char *name);
|
||||
|
||||
esp_err_t esp_console_init(const esp_console_config_t *config)
|
||||
{
|
||||
if (s_tmp_line_buf) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
memcpy(&s_config, config, sizeof(s_config));
|
||||
if (s_config.hint_color == 0) {
|
||||
s_config.hint_color = ANSI_COLOR_DEFAULT;
|
||||
}
|
||||
s_tmp_line_buf = calloc(config->max_cmdline_length, 1);
|
||||
if (s_tmp_line_buf == NULL) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_console_deinit()
|
||||
{
|
||||
if (!s_tmp_line_buf) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
free(s_tmp_line_buf);
|
||||
cmd_item_t *it, *tmp;
|
||||
SLIST_FOREACH_SAFE(it, &s_cmd_list, next, tmp) {
|
||||
free(it->hint);
|
||||
free(it);
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_console_cmd_register(const esp_console_cmd_t *cmd)
|
||||
{
|
||||
cmd_item_t *item = (cmd_item_t *) calloc(1, sizeof(*item));
|
||||
if (item == NULL) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
if (cmd->command == NULL) {
|
||||
free(item);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (strchr(cmd->command, ' ') != NULL) {
|
||||
free(item);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
item->command = cmd->command;
|
||||
item->help = cmd->help;
|
||||
if (cmd->hint) {
|
||||
/* Prepend a space before the hint. It separates command name and
|
||||
* the hint. arg_print_syntax below adds this space as well.
|
||||
*/
|
||||
int unused __attribute__((unused));
|
||||
unused = asprintf(&item->hint, " %s", cmd->hint);
|
||||
} else if (cmd->argtable) {
|
||||
/* Generate hint based on cmd->argtable */
|
||||
char *buf = NULL;
|
||||
size_t buf_size = 0;
|
||||
FILE *f = open_memstream(&buf, &buf_size);
|
||||
if (f != NULL) {
|
||||
arg_print_syntax(f, cmd->argtable, NULL);
|
||||
fclose(f);
|
||||
}
|
||||
item->hint = buf;
|
||||
}
|
||||
item->argtable = cmd->argtable;
|
||||
item->func = cmd->func;
|
||||
cmd_item_t *last = SLIST_FIRST(&s_cmd_list);
|
||||
if (last == NULL) {
|
||||
SLIST_INSERT_HEAD(&s_cmd_list, item, next);
|
||||
} else {
|
||||
cmd_item_t *it;
|
||||
while ((it = SLIST_NEXT(last, next)) != NULL) {
|
||||
last = it;
|
||||
}
|
||||
SLIST_INSERT_AFTER(last, item, next);
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void esp_console_get_completion(const char *buf, linenoiseCompletions *lc)
|
||||
{
|
||||
size_t len = strlen(buf);
|
||||
if (len == 0) {
|
||||
return;
|
||||
}
|
||||
cmd_item_t *it;
|
||||
SLIST_FOREACH(it, &s_cmd_list, next) {
|
||||
/* Check if command starts with buf */
|
||||
if (strncmp(buf, it->command, len) == 0) {
|
||||
linenoiseAddCompletion(lc, it->command);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char *esp_console_get_hint(const char *buf, int *color, int *bold)
|
||||
{
|
||||
int len = strlen(buf);
|
||||
cmd_item_t *it;
|
||||
SLIST_FOREACH(it, &s_cmd_list, next) {
|
||||
if (strlen(it->command) == len &&
|
||||
strncmp(buf, it->command, len) == 0) {
|
||||
*color = s_config.hint_color;
|
||||
*bold = s_config.hint_bold;
|
||||
return it->hint;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const cmd_item_t *find_command_by_name(const char *name)
|
||||
{
|
||||
const cmd_item_t *cmd = NULL;
|
||||
cmd_item_t *it;
|
||||
SLIST_FOREACH(it, &s_cmd_list, next) {
|
||||
if (strcmp(name, it->command) == 0) {
|
||||
cmd = it;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return cmd;
|
||||
}
|
||||
|
||||
esp_err_t esp_console_run(const char *cmdline, int *cmd_ret)
|
||||
{
|
||||
if (s_tmp_line_buf == NULL) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
char **argv = (char **) calloc(s_config.max_cmdline_args, sizeof(char *));
|
||||
if (argv == NULL) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
strlcpy(s_tmp_line_buf, cmdline, s_config.max_cmdline_length);
|
||||
|
||||
size_t argc = esp_console_split_argv(s_tmp_line_buf, argv,
|
||||
s_config.max_cmdline_args);
|
||||
if (argc == 0) {
|
||||
free(argv);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
const cmd_item_t *cmd = find_command_by_name(argv[0]);
|
||||
if (cmd == NULL) {
|
||||
free(argv);
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
*cmd_ret = (*cmd->func)(argc, argv);
|
||||
free(argv);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static int help_command(int argc, char **argv)
|
||||
{
|
||||
cmd_item_t *it;
|
||||
|
||||
/* Print summary of each command */
|
||||
SLIST_FOREACH(it, &s_cmd_list, next) {
|
||||
if (it->help == NULL) {
|
||||
continue;
|
||||
}
|
||||
/* First line: command name and hint
|
||||
* Pad all the hints to the same column
|
||||
*/
|
||||
const char *hint = (it->hint) ? it->hint : "";
|
||||
printf("%-s %s\n", it->command, hint);
|
||||
/* Second line: print help.
|
||||
* Argtable has a nice helper function for this which does line
|
||||
* wrapping.
|
||||
*/
|
||||
printf(" "); // arg_print_formatted does not indent the first line
|
||||
arg_print_formatted(stdout, 2, 78, it->help);
|
||||
/* Finally, print the list of arguments */
|
||||
if (it->argtable) {
|
||||
arg_print_glossary(stdout, (void **) it->argtable, " %12s %s\n");
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
esp_err_t esp_console_register_help_command()
|
||||
{
|
||||
esp_console_cmd_t command = {
|
||||
.command = "help",
|
||||
.help = "Print the list of registered commands",
|
||||
.func = &help_command
|
||||
};
|
||||
return esp_console_cmd_register(&command);
|
||||
}
|
8
components/console/component.mk
Normal file
8
components/console/component.mk
Normal file
@ -0,0 +1,8 @@
|
||||
|
||||
ifdef CONFIG_USING_ESP_CONSOLE
|
||||
COMPONENT_ADD_INCLUDEDIRS := .
|
||||
COMPONENT_SRCDIRS := linenoise argtable3 .
|
||||
else
|
||||
COMPONENT_ADD_INCLUDEDIRS :=
|
||||
COMPONENT_SRCDIRS :=
|
||||
endif
|
192
components/console/esp_console.h
Normal file
192
components/console/esp_console.h
Normal file
@ -0,0 +1,192 @@
|
||||
// Copyright 2016-2017 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
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
#include "esp_err.h"
|
||||
|
||||
// Forward declaration. Definition in linenoise/linenoise.h.
|
||||
typedef struct linenoiseCompletions linenoiseCompletions;
|
||||
|
||||
/**
|
||||
* @brief Parameters for console initialization
|
||||
*/
|
||||
typedef struct {
|
||||
size_t max_cmdline_length; //!< length of command line buffer, in bytes
|
||||
size_t max_cmdline_args; //!< maximum number of command line arguments to parse
|
||||
int hint_color; //!< ASCII color code of hint text
|
||||
int hint_bold; //!< Set to 1 to print hint text in bold
|
||||
} esp_console_config_t;
|
||||
|
||||
/**
|
||||
* @brief initialize console module
|
||||
* Call this once before using other console module features
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_NO_MEM if out of memory
|
||||
* - ESP_ERR_INVALID_STATE if already initialized
|
||||
*/
|
||||
esp_err_t esp_console_init(const esp_console_config_t* config);
|
||||
|
||||
|
||||
/**
|
||||
* @brief de-initialize console module
|
||||
* Call this once when done using console module functions
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_INVALID_STATE if not initialized yet
|
||||
*/
|
||||
esp_err_t esp_console_deinit();
|
||||
|
||||
|
||||
/**
|
||||
* @brief Console command main function
|
||||
* @param argc number of arguments
|
||||
* @param argv array with argc entries, each pointing to a zero-terminated string argument
|
||||
* @return console command return code, 0 indicates "success"
|
||||
*/
|
||||
typedef int (*esp_console_cmd_func_t)(int argc, char** argv);
|
||||
|
||||
/**
|
||||
* @brief Console command description
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* Command name. Must not be NULL, must not contain spaces.
|
||||
* The pointer must be valid until the call to esp_console_deinit.
|
||||
*/
|
||||
const char* command; //!< command name
|
||||
/**
|
||||
* Help text for the command, shown by help command.
|
||||
* If set, the pointer must be valid until the call to esp_console_deinit.
|
||||
* If not set, the command will not be listed in 'help' output.
|
||||
*/
|
||||
const char* help;
|
||||
/**
|
||||
* Hint text, usually lists possible arguments.
|
||||
* If set to NULL, and 'argtable' field is non-NULL, hint will be generated
|
||||
* automatically
|
||||
*/
|
||||
const char* hint;
|
||||
/**
|
||||
* Pointer to a function which implements the command.
|
||||
*/
|
||||
esp_console_cmd_func_t func;
|
||||
/**
|
||||
* Array or structure of pointers to arg_xxx structures, may be NULL.
|
||||
* Used to generate hint text if 'hint' is set to NULL.
|
||||
* Array/structure which this field points to must end with an arg_end.
|
||||
* Only used for the duration of esp_console_cmd_register call.
|
||||
*/
|
||||
void* argtable;
|
||||
} esp_console_cmd_t;
|
||||
|
||||
/**
|
||||
* @brief Register console command
|
||||
* @param cmd pointer to the command description; can point to a temporary value
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_NO_MEM if out of memory
|
||||
*/
|
||||
esp_err_t esp_console_cmd_register(const esp_console_cmd_t *cmd);
|
||||
|
||||
/**
|
||||
* @brief Run command line
|
||||
* @param cmdline command line (command name followed by a number of arguments)
|
||||
* @param[out] cmd_ret return code from the command (set if command was run)
|
||||
* @return
|
||||
* - ESP_OK, if command was run
|
||||
* - ESP_ERR_INVALID_ARG, if the command line is empty, or only contained
|
||||
* whitespace
|
||||
* - ESP_ERR_NOT_FOUND, if command with given name wasn't registered
|
||||
* - ESP_ERR_INVALID_STATE, if esp_console_init wasn't called
|
||||
*/
|
||||
esp_err_t esp_console_run(const char* cmdline, int* cmd_ret);
|
||||
|
||||
/**
|
||||
* @brief Split command line into arguments in place
|
||||
*
|
||||
* - This function finds whitespace-separated arguments in the given input line.
|
||||
*
|
||||
* 'abc def 1 20 .3' -> [ 'abc', 'def', '1', '20', '.3' ]
|
||||
*
|
||||
* - Argument which include spaces may be surrounded with quotes. In this case
|
||||
* spaces are preserved and quotes are stripped.
|
||||
*
|
||||
* 'abc "123 456" def' -> [ 'abc', '123 456', 'def' ]
|
||||
*
|
||||
* - Escape sequences may be used to produce backslash, double quote, and space:
|
||||
*
|
||||
* 'a\ b\\c\"' -> [ 'a b\c"' ]
|
||||
*
|
||||
* Pointers to at most argv_size - 1 arguments are returned in argv array.
|
||||
* The pointer after the last one (i.e. argv[argc]) is set to NULL.
|
||||
*
|
||||
* @param line pointer to buffer to parse; it is modified in place
|
||||
* @param argv array where the pointers to arguments are written
|
||||
* @param argv_size number of elements in argv_array (max. number of arguments)
|
||||
* @return number of arguments found (argc)
|
||||
*/
|
||||
size_t esp_console_split_argv(char *line, char **argv, size_t argv_size);
|
||||
|
||||
/**
|
||||
* @brief Callback which provides command completion for linenoise library
|
||||
*
|
||||
* When using linenoise for line editing, command completion support
|
||||
* can be enabled like this:
|
||||
*
|
||||
* linenoiseSetCompletionCallback(&esp_console_get_completion);
|
||||
*
|
||||
* @param buf the string typed by the user
|
||||
* @param lc linenoiseCompletions to be filled in
|
||||
*/
|
||||
void esp_console_get_completion(const char *buf, linenoiseCompletions *lc);
|
||||
|
||||
/**
|
||||
* @brief Callback which provides command hints for linenoise library
|
||||
*
|
||||
* When using linenoise for line editing, hints support can be enabled as
|
||||
* follows:
|
||||
*
|
||||
* linenoiseSetHintsCallback((linenoiseHintsCallback*) &esp_console_get_hint);
|
||||
*
|
||||
* The extra cast is needed because linenoiseHintsCallback is defined as
|
||||
* returning a char* instead of const char*.
|
||||
*
|
||||
* @param buf line typed by the user
|
||||
* @param[out] color ANSI color code to be used when displaying the hint
|
||||
* @param[out] bold set to 1 if hint has to be displayed in bold
|
||||
* @return string containing the hint text. This string is persistent and should
|
||||
* not be freed (i.e. linenoiseSetFreeHintsCallback should not be used).
|
||||
*/
|
||||
const char *esp_console_get_hint(const char *buf, int *color, int *bold);
|
||||
|
||||
/**
|
||||
* @brief Register a 'help' command
|
||||
* Default 'help' command prints the list of registered commands along with
|
||||
* hints and help strings.
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_INVALID_STATE, if esp_console_init wasn't called
|
||||
*/
|
||||
esp_err_t esp_console_register_help_command();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
25
components/console/linenoise/LICENSE
Normal file
25
components/console/linenoise/LICENSE
Normal file
@ -0,0 +1,25 @@
|
||||
Copyright (c) 2010-2014, Salvatore Sanfilippo <antirez at gmail dot com>
|
||||
Copyright (c) 2010-2013, Pieter Noordhuis <pcnoordhuis at gmail dot com>
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
1116
components/console/linenoise/linenoise.c
Normal file
1116
components/console/linenoise/linenoise.c
Normal file
File diff suppressed because it is too large
Load Diff
76
components/console/linenoise/linenoise.h
Normal file
76
components/console/linenoise/linenoise.h
Normal file
@ -0,0 +1,76 @@
|
||||
/* linenoise.h -- VERSION 1.0
|
||||
*
|
||||
* Guerrilla line editing library against the idea that a line editing lib
|
||||
* needs to be 20,000 lines of C code.
|
||||
*
|
||||
* See linenoise.c for more information.
|
||||
*
|
||||
* ------------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2010-2014, Salvatore Sanfilippo <antirez at gmail dot com>
|
||||
* Copyright (c) 2010-2013, Pieter Noordhuis <pcnoordhuis at gmail dot com>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __LINENOISE_H
|
||||
#define __LINENOISE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct linenoiseCompletions {
|
||||
size_t len;
|
||||
char **cvec;
|
||||
} linenoiseCompletions;
|
||||
|
||||
typedef void(linenoiseCompletionCallback)(const char *, linenoiseCompletions *);
|
||||
typedef char*(linenoiseHintsCallback)(const char *, int *color, int *bold);
|
||||
typedef void(linenoiseFreeHintsCallback)(void *);
|
||||
void linenoiseSetCompletionCallback(linenoiseCompletionCallback *);
|
||||
void linenoiseSetHintsCallback(linenoiseHintsCallback *);
|
||||
void linenoiseSetFreeHintsCallback(linenoiseFreeHintsCallback *);
|
||||
void linenoiseAddCompletion(linenoiseCompletions *, const char *);
|
||||
|
||||
int linenoiseProbe(void);
|
||||
char *linenoise(const char *prompt);
|
||||
void linenoiseFree(void *ptr);
|
||||
int linenoiseHistoryAdd(const char *line);
|
||||
int linenoiseHistorySetMaxLen(int len);
|
||||
int linenoiseHistorySave(const char *filename);
|
||||
int linenoiseHistoryLoad(const char *filename);
|
||||
void linenoiseHistoryFree();
|
||||
void linenoiseClearScreen(void);
|
||||
void linenoiseSetMultiLine(int ml);
|
||||
void linenoiseSetDumbMode(int set);
|
||||
void linenoisePrintKeyCodes(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __LINENOISE_H */
|
120
components/console/split_argv.c
Normal file
120
components/console/split_argv.c
Normal file
@ -0,0 +1,120 @@
|
||||
// Copyright 2016-2017 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 <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
#define SS_FLAG_ESCAPE 0x8
|
||||
|
||||
typedef enum {
|
||||
/* parsing the space between arguments */
|
||||
SS_SPACE = 0x0,
|
||||
/* parsing an argument which isn't quoted */
|
||||
SS_ARG = 0x1,
|
||||
/* parsing a quoted argument */
|
||||
SS_QUOTED_ARG = 0x2,
|
||||
/* parsing an escape sequence within unquoted argument */
|
||||
SS_ARG_ESCAPED = SS_ARG | SS_FLAG_ESCAPE,
|
||||
/* parsing an escape sequence within a quoted argument */
|
||||
SS_QUOTED_ARG_ESCAPED = SS_QUOTED_ARG | SS_FLAG_ESCAPE,
|
||||
} split_state_t;
|
||||
|
||||
size_t esp_console_split_argv(char *line, char **argv, size_t argv_size)
|
||||
{
|
||||
const int QUOTE = '"';
|
||||
const int ESCAPE = '\\';
|
||||
const int SPACE = ' ';
|
||||
split_state_t state = SS_SPACE;
|
||||
int argc = 0;
|
||||
char *next_arg_start = line;
|
||||
char *out_ptr = line;
|
||||
for (char *in_ptr = line; argc < argv_size - 1; ++in_ptr) {
|
||||
int char_in = (unsigned char) *in_ptr;
|
||||
if (char_in == 0) {
|
||||
break;
|
||||
}
|
||||
int char_out = -1;
|
||||
|
||||
/* helper function, called when done with an argument */
|
||||
void end_arg() {
|
||||
char_out = 0;
|
||||
argv[argc++] = next_arg_start;
|
||||
state = SS_SPACE;
|
||||
}
|
||||
|
||||
switch (state) {
|
||||
case SS_SPACE:
|
||||
if (char_in == SPACE) {
|
||||
/* skip space */
|
||||
} else if (char_in == QUOTE) {
|
||||
next_arg_start = out_ptr;
|
||||
state = SS_QUOTED_ARG;
|
||||
} else if (char_in == ESCAPE) {
|
||||
next_arg_start = out_ptr;
|
||||
state = SS_ARG_ESCAPED;
|
||||
} else {
|
||||
next_arg_start = out_ptr;
|
||||
state = SS_ARG;
|
||||
char_out = char_in;
|
||||
}
|
||||
break;
|
||||
|
||||
case SS_QUOTED_ARG:
|
||||
if (char_in == QUOTE) {
|
||||
end_arg();
|
||||
} else if (char_in == ESCAPE) {
|
||||
state = SS_QUOTED_ARG_ESCAPED;
|
||||
} else {
|
||||
char_out = char_in;
|
||||
}
|
||||
break;
|
||||
|
||||
case SS_ARG_ESCAPED:
|
||||
case SS_QUOTED_ARG_ESCAPED:
|
||||
if (char_in == ESCAPE || char_in == QUOTE || char_in == SPACE) {
|
||||
char_out = char_in;
|
||||
} else {
|
||||
/* unrecognized escape character, skip */
|
||||
}
|
||||
state = (split_state_t) (state & (~SS_FLAG_ESCAPE));
|
||||
break;
|
||||
|
||||
case SS_ARG:
|
||||
if (char_in == SPACE) {
|
||||
end_arg();
|
||||
} else if (char_in == ESCAPE) {
|
||||
state = SS_ARG_ESCAPED;
|
||||
} else {
|
||||
char_out = char_in;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* need to output anything? */
|
||||
if (char_out >= 0) {
|
||||
*out_ptr = char_out;
|
||||
++out_ptr;
|
||||
}
|
||||
}
|
||||
/* make sure the final argument is terminated */
|
||||
*out_ptr = 0;
|
||||
/* finalize the last argument */
|
||||
if (state != SS_SPACE && argc < argv_size - 1) {
|
||||
argv[argc++] = next_arg_start;
|
||||
}
|
||||
/* add a NULL at the end of argv */
|
||||
argv[argc] = NULL;
|
||||
|
||||
return argc;
|
||||
}
|
@ -208,13 +208,17 @@ typedef enum {
|
||||
* @brief Chip models
|
||||
*/
|
||||
typedef enum {
|
||||
CHIP_ESP8266 = 1, //!< ESP8266
|
||||
CHIP_ESP8266 = 0, //!< ESP8266
|
||||
CHIP_ESP32 = 1, //!< ESP32
|
||||
} esp_chip_model_t;
|
||||
|
||||
/**
|
||||
* Chip feature flags, used in esp_chip_info_t
|
||||
*/
|
||||
#define CHIP_FEATURE_WIFI_BGN (1 << 0)
|
||||
#define CHIP_FEATURE_EMB_FLASH BIT(0) //!< Chip has embedded flash memory
|
||||
#define CHIP_FEATURE_WIFI_BGN BIT(1) //!< Chip has 2.4GHz WiFi
|
||||
#define CHIP_FEATURE_BLE BIT(4) //!< Chip has Bluetooth LE
|
||||
#define CHIP_FEATURE_BT BIT(5) //!< Chip has Bluetooth Classic
|
||||
|
||||
/**
|
||||
* @brief The structure represents information about the chip
|
||||
|
@ -231,6 +231,31 @@ void esp_early_log_write(esp_log_level_t level, const char* tag, const char* for
|
||||
#define esp_log_buffer_hex ESP_LOG_BUFFER_HEX
|
||||
#define esp_log_buffer_char ESP_LOG_BUFFER_CHAR
|
||||
|
||||
#if CONFIG_LOG_COLORS
|
||||
#define LOG_COLOR_BLACK "30"
|
||||
#define LOG_COLOR_RED "31"
|
||||
#define LOG_COLOR_GREEN "32"
|
||||
#define LOG_COLOR_BROWN "33"
|
||||
#define LOG_COLOR_BLUE "34"
|
||||
#define LOG_COLOR_PURPLE "35"
|
||||
#define LOG_COLOR_CYAN "36"
|
||||
#define LOG_COLOR(COLOR) "\033[0;" COLOR "m"
|
||||
#define LOG_BOLD(COLOR) "\033[1;" COLOR "m"
|
||||
#define LOG_RESET_COLOR "\033[0m"
|
||||
#define LOG_COLOR_E LOG_COLOR(LOG_COLOR_RED)
|
||||
#define LOG_COLOR_W LOG_COLOR(LOG_COLOR_BROWN)
|
||||
#define LOG_COLOR_I LOG_COLOR(LOG_COLOR_GREEN)
|
||||
#define LOG_COLOR_D
|
||||
#define LOG_COLOR_V
|
||||
#else //CONFIG_LOG_COLORS
|
||||
#define LOG_COLOR_E
|
||||
#define LOG_COLOR_W
|
||||
#define LOG_COLOR_I
|
||||
#define LOG_COLOR_D
|
||||
#define LOG_COLOR_V
|
||||
#define LOG_RESET_COLOR
|
||||
#endif //CONFIG_LOG_COLORS
|
||||
|
||||
/** @endcond */
|
||||
|
||||
/// macro to output logs in startup code, before heap allocator and syscalls have been initialized. log at ``ESP_LOG_ERROR`` level. @see ``printf``,``ESP_LOGE``
|
||||
|
@ -30,9 +30,9 @@
|
||||
#include "esp_system.h"
|
||||
|
||||
#ifdef CONFIG_LOG_COLORS
|
||||
#define LOG_COLOR "\033[0;%dm"
|
||||
#define LOG_BOLD "\033[1;%dm"
|
||||
#define LOG_RESET_COLOR "\033[0m"
|
||||
#define LOG_COLOR_HEAD "\033[0;%dm"
|
||||
#define LOG_BOLD_HEAD "\033[1;%dm"
|
||||
#define LOG_COLOR_END "\033[0m"
|
||||
|
||||
static const uint32_t s_log_color[ESP_LOG_MAX] = {
|
||||
0, // ESP_LOG_NONE
|
||||
@ -214,7 +214,7 @@ void IRAM_ATTR esp_early_log_write(esp_log_level_t level, const char *tag, const
|
||||
uint32_t color = level >= ESP_LOG_MAX ? 0 : s_log_color[level];
|
||||
|
||||
if (color)
|
||||
ets_printf(LOG_COLOR, color);
|
||||
ets_printf(LOG_COLOR_HEAD, color);
|
||||
#endif
|
||||
|
||||
if (ets_printf("%c (%d) %s: ", prefix, esp_log_early_timestamp(), tag) < 0)
|
||||
@ -227,7 +227,7 @@ void IRAM_ATTR esp_early_log_write(esp_log_level_t level, const char *tag, const
|
||||
out:
|
||||
#ifdef CONFIG_LOG_COLORS
|
||||
if (color)
|
||||
ets_printf(LOG_RESET_COLOR);
|
||||
ets_printf(LOG_COLOR_END);
|
||||
#endif
|
||||
ets_printf("\n");
|
||||
}
|
||||
@ -255,7 +255,7 @@ void esp_log_write(esp_log_level_t level, const char *tag, const char *fmt, ...
|
||||
uint32_t color = level >= ESP_LOG_MAX ? 0 : s_log_color[level];
|
||||
|
||||
if (color) {
|
||||
sprintf(buf, LOG_COLOR, color);
|
||||
sprintf(buf, LOG_COLOR_HEAD, color);
|
||||
ret = esp_log_write_str(buf);
|
||||
if (ret == EOF)
|
||||
goto exit;
|
||||
@ -283,7 +283,7 @@ void esp_log_write(esp_log_level_t level, const char *tag, const char *fmt, ...
|
||||
out:
|
||||
#ifdef CONFIG_LOG_COLORS
|
||||
if (color) {
|
||||
ret = esp_log_write_str(LOG_RESET_COLOR);
|
||||
ret = esp_log_write_str(LOG_COLOR_END);
|
||||
if (ret == EOF)
|
||||
goto exit;
|
||||
}
|
||||
|
@ -49,6 +49,15 @@ typedef enum {
|
||||
typedef uint32_t spi_flash_mmap_handle_t;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Get flash chip size, as set in binary image header
|
||||
*
|
||||
* @note This value does not necessarily match real flash size.
|
||||
*
|
||||
* @return size of flash chip, in bytes
|
||||
*/
|
||||
size_t spi_flash_get_chip_size();
|
||||
|
||||
/**
|
||||
* @brief Erase the Flash sector.
|
||||
*
|
||||
|
@ -776,3 +776,8 @@ uintptr_t spi_flash_cache2phys(const void *cached)
|
||||
|
||||
return segment * CACHE_2M_SIZE + (addr + addr_offset - CACHE_BASE_ADDR);
|
||||
}
|
||||
|
||||
size_t spi_flash_get_chip_size()
|
||||
{
|
||||
return flashchip.chip_size;
|
||||
}
|
||||
|
6
examples/system/console/CMakeLists.txt
Normal file
6
examples/system/console/CMakeLists.txt
Normal file
@ -0,0 +1,6 @@
|
||||
# The following lines of boilerplate have to be in your project's CMakeLists
|
||||
# in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(console)
|
9
examples/system/console/Makefile
Normal file
9
examples/system/console/Makefile
Normal file
@ -0,0 +1,9 @@
|
||||
#
|
||||
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
|
||||
# project subdirectory.
|
||||
#
|
||||
|
||||
PROJECT_NAME := console
|
||||
|
||||
include $(IDF_PATH)/make/project.mk
|
||||
|
108
examples/system/console/README.md
Normal file
108
examples/system/console/README.md
Normal file
@ -0,0 +1,108 @@
|
||||
# Console example
|
||||
|
||||
This example illustrates usage of `console` component to create an interactive shell.
|
||||
|
||||
## Configuring UART and VFS
|
||||
|
||||
``initialize_console`` function configures some aspects of UART and VFS relevant to the operation of console:
|
||||
|
||||
- By default `stdin` and `stdout` are buffered streams. This means that the text written to `stdout` will not be immediately sent to UART. This is not the desirable behavior for the console, so buffering for `stdin` and `stdout` is disabled using `setvbuf` function.
|
||||
|
||||
- Line endings are configured to match those expected/generated by common serial monitor programs, such as `screen`, `minicom`, and the `idf_monitor.py` included in the SDK. The default behavior for these commands is:
|
||||
- When 'enter' key is pressed on the keyboard, `CR` (0x13) code is sent to the serial device.
|
||||
- To move the cursor to the beginning of the next line, serial device needs to send `CR LF` (0x13 0x10) sequence.
|
||||
|
||||
- UART driver is initialized, and VFS is configured to use UART driver's interrupt-driver read and write functions.
|
||||
|
||||
## Line editing
|
||||
|
||||
The main source file of the example illustrates how to use `linenoise` library, including line completion, hints, and history.
|
||||
|
||||
## Commands
|
||||
|
||||
Several commands are registered using `esp_console_cmd_register` function. See `register_wifi` and `register_system` functions in `cmd_wifi.c` and `cmd_system.c` files.
|
||||
|
||||
## Command handling
|
||||
|
||||
Main loop inside `app_main` function illustrates how to use `linenoise` and `esp_console_run` to implement read/eval loop.
|
||||
|
||||
## Argument parsing
|
||||
|
||||
Several commands implemented in `cmd_wifi.c` and `cmd_system.c` use Argtable3 library to parse and check the arguments.
|
||||
|
||||
## Command history
|
||||
|
||||
Each time a new command line is obtained from `linenoise`, it is written into history and the history is saved into a file in flash memory. On reset, history is initialized from that file.
|
||||
|
||||
# Example output
|
||||
|
||||
Here is an sample session with the console example. GPIO15 is connected to GND to remove boot log output.
|
||||
|
||||
```
|
||||
This is an example of ESP-IDF console component.
|
||||
Type 'help' to get the list of commands.
|
||||
Use UP/DOWN arrows to navigate through command history.
|
||||
Press TAB when typing command name to auto-complete.
|
||||
[esp32]> help
|
||||
help
|
||||
Print the list of registered commands
|
||||
|
||||
free
|
||||
Get the total size of heap memory available
|
||||
|
||||
restart
|
||||
Restart the program
|
||||
|
||||
deep_sleep [-t <t>] [--io=<n>] [--io_level=<0|1>]
|
||||
Enter deep sleep mode. Two wakeup modes are supported: timer and GPIO. If no
|
||||
wakeup option is specified, will sleep indefinitely.
|
||||
-t, --time=<t> Wake up time, ms
|
||||
--io=<n> If specified, wakeup using GPIO with given number
|
||||
--io_level=<0|1> GPIO level to trigger wakeup
|
||||
|
||||
join [--timeout=<t>] <ssid> [<pass>]
|
||||
Join WiFi AP as a station
|
||||
--timeout=<t> Connection timeout, ms
|
||||
<ssid> SSID of AP
|
||||
<pass> PSK of AP
|
||||
|
||||
[esp32]> free
|
||||
257200
|
||||
[esp32]> deep_sleep -t 1000
|
||||
I (146929) deep_sleep: Enabling timer wakeup, timeout=1000000us
|
||||
I (619) heap_init: Initializing. RAM available for dynamic allocation:
|
||||
I (620) heap_init: At 3FFAE2A0 len 00001D60 (7 KiB): DRAM
|
||||
I (626) heap_init: At 3FFB7EA0 len 00028160 (160 KiB): DRAM
|
||||
I (645) heap_init: At 3FFE0440 len 00003BC0 (14 KiB): D/IRAM
|
||||
I (664) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
|
||||
I (684) heap_init: At 40093EA8 len 0000C158 (48 KiB): IRAM
|
||||
|
||||
This is an example of ESP-IDF console component.
|
||||
Type 'help' to get the list of commands.
|
||||
Use UP/DOWN arrows to navigate through command history.
|
||||
Press TAB when typing command name to auto-complete.
|
||||
[esp32]> join --timeout 10000 test_ap test_password
|
||||
I (182639) connect: Connecting to 'test_ap'
|
||||
I (184619) connect: Connected
|
||||
[esp32]> free
|
||||
212328
|
||||
[esp32]> restart
|
||||
I (205639) restart: Restarting
|
||||
I (616) heap_init: Initializing. RAM available for dynamic allocation:
|
||||
I (617) heap_init: At 3FFAE2A0 len 00001D60 (7 KiB): DRAM
|
||||
I (623) heap_init: At 3FFB7EA0 len 00028160 (160 KiB): DRAM
|
||||
I (642) heap_init: At 3FFE0440 len 00003BC0 (14 KiB): D/IRAM
|
||||
I (661) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
|
||||
I (681) heap_init: At 40093EA8 len 0000C158 (48 KiB): IRAM
|
||||
|
||||
This is an example of ESP-IDF console component.
|
||||
Type 'help' to get the list of commands.
|
||||
Use UP/DOWN arrows to navigate through command history.
|
||||
Press TAB when typing command name to auto-complete.
|
||||
[esp32]>
|
||||
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
See the README.md file in the upper level 'examples' directory for more information about examples.
|
@ -0,0 +1,7 @@
|
||||
set(COMPONENT_ADD_INCLUDEDIRS .)
|
||||
|
||||
set(COMPONENT_SRCS "cmd_system.c")
|
||||
|
||||
set(COMPONENT_REQUIRES console spi_flash)
|
||||
|
||||
register_component()
|
274
examples/system/console/components/cmd_system/cmd_system.c
Normal file
274
examples/system/console/components/cmd_system/cmd_system.c
Normal file
@ -0,0 +1,274 @@
|
||||
/* Console example — various system commands
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include "esp_log.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_console.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_sleep.h"
|
||||
#include "esp_spi_flash.h"
|
||||
#include "argtable3/argtable3.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "driver/uart.h"
|
||||
#include "rom/uart.h"
|
||||
#include "cmd_system.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#ifdef CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS
|
||||
#define WITH_TASKS_INFO 1
|
||||
#endif
|
||||
|
||||
static const char *TAG = "cmd_system";
|
||||
|
||||
static void register_free();
|
||||
static void register_heap();
|
||||
static void register_version();
|
||||
static void register_restart();
|
||||
static void register_make();
|
||||
#if WITH_TASKS_INFO
|
||||
static void register_tasks();
|
||||
#endif
|
||||
|
||||
void register_system()
|
||||
{
|
||||
register_free();
|
||||
register_heap();
|
||||
register_version();
|
||||
register_restart();
|
||||
register_make();
|
||||
#if WITH_TASKS_INFO
|
||||
register_tasks();
|
||||
#endif
|
||||
}
|
||||
|
||||
/* 'version' command */
|
||||
static int get_version(int argc, char **argv)
|
||||
{
|
||||
esp_chip_info_t info;
|
||||
esp_chip_info(&info);
|
||||
printf("IDF Version:%s\r\n", esp_get_idf_version());
|
||||
printf("Chip info:\r\n");
|
||||
printf("\tmodel:%s\r\n", info.model == CHIP_ESP8266 ? "ESP8266" : "Unknow");
|
||||
printf("\tcores:%d\r\n", info.cores);
|
||||
printf("\tfeature:%s%s%s%s%d%s\r\n",
|
||||
info.features & CHIP_FEATURE_WIFI_BGN ? "/802.11bgn" : "",
|
||||
info.features & CHIP_FEATURE_BLE ? "/BLE" : "",
|
||||
info.features & CHIP_FEATURE_BT ? "/BT" : "",
|
||||
info.features & CHIP_FEATURE_EMB_FLASH ? "/Embedded-Flash:" : "/External-Flash:",
|
||||
spi_flash_get_chip_size() / (1024 * 1024), " MB");
|
||||
printf("\trevision number:%d\r\n", info.revision);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void register_version()
|
||||
{
|
||||
const esp_console_cmd_t cmd = {
|
||||
.command = "version",
|
||||
.help = "Get version of chip and SDK",
|
||||
.hint = NULL,
|
||||
.func = &get_version,
|
||||
};
|
||||
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) );
|
||||
}
|
||||
|
||||
/** 'restart' command restarts the program */
|
||||
|
||||
static int restart(int argc, char **argv)
|
||||
{
|
||||
ESP_LOGI(TAG, "Restarting");
|
||||
esp_restart();
|
||||
}
|
||||
|
||||
static void register_restart()
|
||||
{
|
||||
const esp_console_cmd_t cmd = {
|
||||
.command = "restart",
|
||||
.help = "Software reset of the chip",
|
||||
.hint = NULL,
|
||||
.func = &restart,
|
||||
};
|
||||
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) );
|
||||
}
|
||||
|
||||
/** 'free' command prints available heap memory */
|
||||
|
||||
static int free_mem(int argc, char **argv)
|
||||
{
|
||||
printf("%d\n", esp_get_free_heap_size());
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void register_free()
|
||||
{
|
||||
const esp_console_cmd_t cmd = {
|
||||
.command = "free",
|
||||
.help = "Get the current size of free heap memory",
|
||||
.hint = NULL,
|
||||
.func = &free_mem,
|
||||
};
|
||||
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) );
|
||||
}
|
||||
|
||||
/* 'heap' command prints minumum heap size */
|
||||
static int heap_size(int argc, char **argv)
|
||||
{
|
||||
uint32_t heap_size = heap_caps_get_minimum_free_size(MALLOC_CAP_32BIT);
|
||||
ESP_LOGI(TAG, "min heap size: %u", heap_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void register_heap()
|
||||
{
|
||||
const esp_console_cmd_t heap_cmd = {
|
||||
.command = "heap",
|
||||
.help = "Get minimum size of free heap memory that was available during program execution",
|
||||
.hint = NULL,
|
||||
.func = &heap_size,
|
||||
};
|
||||
ESP_ERROR_CHECK( esp_console_cmd_register(&heap_cmd) );
|
||||
|
||||
}
|
||||
|
||||
/** 'tasks' command prints the list of tasks and related information */
|
||||
#if WITH_TASKS_INFO
|
||||
|
||||
static int tasks_info(int argc, char **argv)
|
||||
{
|
||||
const size_t bytes_per_task = 40; /* see vTaskList description */
|
||||
char *task_list_buffer = malloc(uxTaskGetNumberOfTasks() * bytes_per_task);
|
||||
if (task_list_buffer == NULL) {
|
||||
ESP_LOGE(TAG, "failed to allocate buffer for vTaskList output");
|
||||
return 1;
|
||||
}
|
||||
fputs("Task Name\tStatus\tPrio\tHWM\tTask#", stdout);
|
||||
#ifdef CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID
|
||||
fputs("\tAffinity", stdout);
|
||||
#endif
|
||||
fputs("\n", stdout);
|
||||
vTaskList(task_list_buffer);
|
||||
fputs(task_list_buffer, stdout);
|
||||
free(task_list_buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void register_tasks()
|
||||
{
|
||||
const esp_console_cmd_t cmd = {
|
||||
.command = "tasks",
|
||||
.help = "Get information about running tasks",
|
||||
.hint = NULL,
|
||||
.func = &tasks_info,
|
||||
};
|
||||
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) );
|
||||
}
|
||||
|
||||
#endif // WITH_TASKS_INFO
|
||||
|
||||
/** This command helps maintain sanity when testing console example from a console */
|
||||
|
||||
static int make(int argc, char **argv)
|
||||
{
|
||||
const char *make_output =
|
||||
R"(LD build/console.elf
|
||||
esptool.py v2.1-beta1
|
||||
)";
|
||||
|
||||
const char* flash_output[] = {
|
||||
R"(Flashing binaries to serial port (*) (app at offset 0x10000)...
|
||||
esptool.py v2.1-beta1
|
||||
Connecting....
|
||||
)",
|
||||
R"(Chip is ESP32D0WDQ6 (revision 0)
|
||||
Uploading stub...
|
||||
Running stub...
|
||||
Stub running...
|
||||
Changing baud rate to 921600
|
||||
Changed.
|
||||
Configuring flash size...
|
||||
Auto-detected Flash size: 4MB
|
||||
Flash params set to 0x0220
|
||||
Compressed 15712 bytes to 9345...
|
||||
)",
|
||||
R"(Wrote 15712 bytes (9345 compressed) at 0x00001000 in 0.1 seconds (effective 1126.9 kbit/s)...
|
||||
Hash of data verified.
|
||||
Compressed 333776 bytes to 197830...
|
||||
)",
|
||||
R"(Wrote 333776 bytes (197830 compressed) at 0x00010000 in 3.3 seconds (effective 810.3 kbit/s)...
|
||||
Hash of data verified.
|
||||
Compressed 3072 bytes to 82...
|
||||
)",
|
||||
R"(Wrote 3072 bytes (82 compressed) at 0x00008000 in 0.0 seconds (effective 1588.4 kbit/s)...
|
||||
Hash of data verified.
|
||||
Leaving...
|
||||
Hard resetting...
|
||||
)"
|
||||
};
|
||||
|
||||
const char* monitor_output =
|
||||
R"(MONITOR
|
||||
)" LOG_COLOR_W R"(--- idf_monitor on (*) 115200 ---
|
||||
--- Quit: Ctrl+] | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H --
|
||||
)" LOG_RESET_COLOR;
|
||||
|
||||
bool need_make = false;
|
||||
bool need_flash = false;
|
||||
bool need_monitor = false;
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
if (strcmp(argv[i], "all") == 0) {
|
||||
need_make = true;
|
||||
} else if (strcmp(argv[i], "flash") == 0) {
|
||||
need_make = true;
|
||||
need_flash = true;
|
||||
} else if (strcmp(argv[i], "monitor") == 0) {
|
||||
need_monitor = true;
|
||||
} else if (argv[i][0] == '-') {
|
||||
/* probably -j option */
|
||||
} else if (isdigit((int) argv[i][0])) {
|
||||
/* might be an argument to -j */
|
||||
} else {
|
||||
printf("make: *** No rule to make target `%s'. Stop.\n", argv[i]);
|
||||
/* Technically this is an error, but let's not spoil the output */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (argc == 1) {
|
||||
need_make = true;
|
||||
}
|
||||
if (need_make) {
|
||||
printf("%s", make_output);
|
||||
}
|
||||
if (need_flash) {
|
||||
size_t n_items = sizeof(flash_output) / sizeof(flash_output[0]);
|
||||
for (int i = 0; i < n_items; ++i) {
|
||||
printf("%s", flash_output[i]);
|
||||
vTaskDelay(200/portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
if (need_monitor) {
|
||||
printf("%s", monitor_output);
|
||||
esp_restart();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void register_make()
|
||||
{
|
||||
const esp_console_cmd_t cmd = {
|
||||
.command = "make",
|
||||
.help = NULL, /* hide from 'help' output */
|
||||
.hint = "all | flash | monitor",
|
||||
.func = &make,
|
||||
};
|
||||
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) );
|
||||
}
|
||||
|
20
examples/system/console/components/cmd_system/cmd_system.h
Normal file
20
examples/system/console/components/cmd_system/cmd_system.h
Normal file
@ -0,0 +1,20 @@
|
||||
/* Console example — various system commands
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Register system functions
|
||||
void register_system();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
10
examples/system/console/components/cmd_system/component.mk
Normal file
10
examples/system/console/components/cmd_system/component.mk
Normal file
@ -0,0 +1,10 @@
|
||||
#
|
||||
# Component Makefile
|
||||
#
|
||||
# This Makefile should, at the very least, just include $(SDK_PATH)/Makefile. By default,
|
||||
# this will take the sources in the src/ directory, compile them and link them into
|
||||
# lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable,
|
||||
# please read the SDK documents if you need to do this.
|
||||
#
|
||||
|
||||
COMPONENT_ADD_INCLUDEDIRS := .
|
5
examples/system/console/main/CMakeLists.txt
Normal file
5
examples/system/console/main/CMakeLists.txt
Normal file
@ -0,0 +1,5 @@
|
||||
set(COMPONENT_SRCS "cmd_wifi.c"
|
||||
"console_example_main.c")
|
||||
set(COMPONENT_ADD_INCLUDEDIRS ".")
|
||||
|
||||
register_component()
|
11
examples/system/console/main/Kconfig.projbuild
Normal file
11
examples/system/console/main/Kconfig.projbuild
Normal file
@ -0,0 +1,11 @@
|
||||
menu "Example Configuration"
|
||||
|
||||
config STORE_HISTORY
|
||||
bool "Store command history in flash"
|
||||
default y
|
||||
help
|
||||
Linenoise line editing library provides functions to save and load
|
||||
command history. If this option is enabled, initalizes a FAT filesystem
|
||||
and uses it to store command history.
|
||||
|
||||
endmenu
|
20
examples/system/console/main/cmd_decl.h
Normal file
20
examples/system/console/main/cmd_decl.h
Normal file
@ -0,0 +1,20 @@
|
||||
/* Console example — declarations of command registration functions.
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "cmd_system.h"
|
||||
#include "cmd_wifi.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
124
examples/system/console/main/cmd_wifi.c
Normal file
124
examples/system/console/main/cmd_wifi.c
Normal file
@ -0,0 +1,124 @@
|
||||
/* Console example — WiFi commands
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "esp_log.h"
|
||||
#include "esp_console.h"
|
||||
#include "argtable3/argtable3.h"
|
||||
#include "cmd_decl.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/event_groups.h"
|
||||
#include "esp_wifi.h"
|
||||
#include "tcpip_adapter.h"
|
||||
#include "esp_event_loop.h"
|
||||
#include "cmd_wifi.h"
|
||||
|
||||
static EventGroupHandle_t wifi_event_group;
|
||||
const int CONNECTED_BIT = BIT0;
|
||||
|
||||
static esp_err_t event_handler(void *ctx, system_event_t *event)
|
||||
{
|
||||
switch(event->event_id) {
|
||||
case SYSTEM_EVENT_STA_GOT_IP:
|
||||
xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
|
||||
break;
|
||||
case SYSTEM_EVENT_STA_DISCONNECTED:
|
||||
esp_wifi_connect();
|
||||
xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void initialise_wifi(void)
|
||||
{
|
||||
esp_log_level_set("wifi", ESP_LOG_WARN);
|
||||
static bool initialized = false;
|
||||
if (initialized) {
|
||||
return;
|
||||
}
|
||||
tcpip_adapter_init();
|
||||
wifi_event_group = xEventGroupCreate();
|
||||
ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) );
|
||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||
ESP_ERROR_CHECK( esp_wifi_init(&cfg) );
|
||||
ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) );
|
||||
ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_NULL) );
|
||||
ESP_ERROR_CHECK( esp_wifi_start() );
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
static bool wifi_join(const char* ssid, const char* pass, int timeout_ms)
|
||||
{
|
||||
initialise_wifi();
|
||||
wifi_config_t wifi_config = { 0 };
|
||||
strncpy((char*) wifi_config.sta.ssid, ssid, sizeof(wifi_config.sta.ssid));
|
||||
if (pass) {
|
||||
strncpy((char*) wifi_config.sta.password, pass, sizeof(wifi_config.sta.password));
|
||||
}
|
||||
|
||||
ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) );
|
||||
ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) );
|
||||
ESP_ERROR_CHECK( esp_wifi_connect() );
|
||||
|
||||
int bits = xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT,
|
||||
1, 1, timeout_ms / portTICK_PERIOD_MS);
|
||||
return (bits & CONNECTED_BIT) != 0;
|
||||
}
|
||||
|
||||
/** Arguments used by 'join' function */
|
||||
static struct {
|
||||
struct arg_int *timeout;
|
||||
struct arg_str *ssid;
|
||||
struct arg_str *password;
|
||||
struct arg_end *end;
|
||||
} join_args;
|
||||
|
||||
static int connect(int argc, char** argv)
|
||||
{
|
||||
int nerrors = arg_parse(argc, argv, (void**) &join_args);
|
||||
if (nerrors != 0) {
|
||||
arg_print_errors(stderr, join_args.end, argv[0]);
|
||||
return 1;
|
||||
}
|
||||
ESP_LOGI(__func__, "Connecting to '%s'",
|
||||
join_args.ssid->sval[0]);
|
||||
|
||||
bool connected = wifi_join(join_args.ssid->sval[0],
|
||||
join_args.password->sval[0],
|
||||
join_args.timeout->ival[0]);
|
||||
if (!connected) {
|
||||
ESP_LOGW(__func__, "Connection timed out");
|
||||
return 1;
|
||||
}
|
||||
ESP_LOGI(__func__, "Connected");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void register_wifi()
|
||||
{
|
||||
join_args.timeout = arg_int0(NULL, "timeout", "<t>", "Connection timeout, ms");
|
||||
join_args.timeout->ival[0] = 5000; // set default value
|
||||
join_args.ssid = arg_str1(NULL, NULL, "<ssid>", "SSID of AP");
|
||||
join_args.password = arg_str0(NULL, NULL, "<pass>", "PSK of AP");
|
||||
join_args.end = arg_end(2);
|
||||
|
||||
const esp_console_cmd_t join_cmd = {
|
||||
.command = "join",
|
||||
.help = "Join WiFi AP as a station",
|
||||
.hint = NULL,
|
||||
.func = &connect,
|
||||
.argtable = &join_args
|
||||
};
|
||||
|
||||
ESP_ERROR_CHECK( esp_console_cmd_register(&join_cmd) );
|
||||
}
|
21
examples/system/console/main/cmd_wifi.h
Normal file
21
examples/system/console/main/cmd_wifi.h
Normal file
@ -0,0 +1,21 @@
|
||||
/* Console example — declarations of command registration functions.
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Register WiFi functions
|
||||
void register_wifi();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
5
examples/system/console/main/component.mk
Normal file
5
examples/system/console/main/component.mk
Normal file
@ -0,0 +1,5 @@
|
||||
#
|
||||
# "main" pseudo-component makefile.
|
||||
#
|
||||
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
|
||||
|
153
examples/system/console/main/console_example_main.c
Normal file
153
examples/system/console/main/console_example_main.c
Normal file
@ -0,0 +1,153 @@
|
||||
/* Console example
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "esp_system.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_console.h"
|
||||
#include "esp_vfs_dev.h"
|
||||
#include "FreeRTOS.h"
|
||||
#include "driver/uart.h"
|
||||
#include "linenoise/linenoise.h"
|
||||
#include "argtable3/argtable3.h"
|
||||
#include "cmd_decl.h"
|
||||
#include "nvs.h"
|
||||
#include "nvs_flash.h"
|
||||
|
||||
#define TAG "example"
|
||||
|
||||
static void initialize_nvs()
|
||||
{
|
||||
esp_err_t err = nvs_flash_init();
|
||||
if (err == ESP_ERR_NVS_NO_FREE_PAGES) {
|
||||
ESP_ERROR_CHECK( nvs_flash_erase() );
|
||||
err = nvs_flash_init();
|
||||
}
|
||||
ESP_ERROR_CHECK(err);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
/* Initialize the console */
|
||||
esp_console_config_t console_config = {
|
||||
.max_cmdline_args = 8,
|
||||
.max_cmdline_length = 256,
|
||||
#if CONFIG_LOG_COLORS
|
||||
.hint_color = atoi(LOG_COLOR_CYAN)
|
||||
#endif
|
||||
};
|
||||
ESP_ERROR_CHECK( esp_console_init(&console_config) );
|
||||
|
||||
/* Configure linenoise line completion library */
|
||||
/* Enable multiline editing. If not set, long commands will scroll within
|
||||
* single line.
|
||||
*/
|
||||
linenoiseSetMultiLine(1);
|
||||
|
||||
/* Tell linenoise where to get command completions and hints */
|
||||
linenoiseSetCompletionCallback(&esp_console_get_completion);
|
||||
linenoiseSetHintsCallback((linenoiseHintsCallback*) &esp_console_get_hint);
|
||||
|
||||
/* Set command history size */
|
||||
linenoiseHistorySetMaxLen(100);
|
||||
}
|
||||
|
||||
void app_main()
|
||||
{
|
||||
initialize_nvs();
|
||||
|
||||
initialize_console();
|
||||
|
||||
/* Register commands */
|
||||
esp_console_register_help_command();
|
||||
register_system();
|
||||
register_wifi();
|
||||
|
||||
/* Prompt to be printed before each line.
|
||||
* This can be customized, made dynamic, etc.
|
||||
*/
|
||||
const char* prompt = LOG_COLOR_I "esp8266> " LOG_RESET_COLOR;
|
||||
|
||||
printf("\n"
|
||||
"This is an example of ESP-IDF console component.\n"
|
||||
"Type 'help' to get the list of commands.\n"
|
||||
"Use UP/DOWN arrows to navigate through command history.\n"
|
||||
"Press TAB when typing command name to auto-complete.\n");
|
||||
|
||||
/* Figure out if the terminal supports escape sequences */
|
||||
int probe_status = linenoiseProbe();
|
||||
if (probe_status) { /* zero indicates success */
|
||||
printf("\n"
|
||||
"Your terminal application does not support escape sequences.\n"
|
||||
"Line editing and history features are disabled.\n"
|
||||
"On Windows, try using Putty instead.\n");
|
||||
linenoiseSetDumbMode(1);
|
||||
#if CONFIG_LOG_COLORS
|
||||
/* Since the terminal doesn't support escape sequences,
|
||||
* don't use color codes in the prompt.
|
||||
*/
|
||||
prompt = "esp8266> ";
|
||||
#endif //CONFIG_LOG_COLORS
|
||||
}
|
||||
|
||||
/* Main loop */
|
||||
while(true) {
|
||||
/* Get a line using linenoise.
|
||||
* The line is returned when ENTER is pressed.
|
||||
*/
|
||||
char* line = linenoise(prompt);
|
||||
if (line == NULL) { /* Ignore empty lines */
|
||||
continue;
|
||||
}
|
||||
/* Add the command to the history */
|
||||
linenoiseHistoryAdd(line);
|
||||
|
||||
/* Try to run the command */
|
||||
int ret;
|
||||
esp_err_t err = esp_console_run(line, &ret);
|
||||
if (err == ESP_ERR_NOT_FOUND) {
|
||||
printf("Unrecognized command\n");
|
||||
} else if (err == ESP_ERR_INVALID_ARG) {
|
||||
// command was empty
|
||||
} else if (err == ESP_OK && ret != ESP_OK) {
|
||||
printf("Command returned non-zero error code: 0x%x (%s)\n", ret, esp_err_to_name(err));
|
||||
} else if (err != ESP_OK) {
|
||||
printf("Internal error: %s\n", esp_err_to_name(err));
|
||||
}
|
||||
/* linenoise allocates line buffer on the heap, so need to free it */
|
||||
linenoiseFree(line);
|
||||
}
|
||||
}
|
5
examples/system/console/partitions_example.csv
Normal file
5
examples/system/console/partitions_example.csv
Normal file
@ -0,0 +1,5 @@
|
||||
# Name, Type, SubType, Offset, Size, Flags
|
||||
# Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild
|
||||
nvs, data, nvs, 0x9000, 0x6000,
|
||||
phy_init, data, phy, 0xf000, 0x1000,
|
||||
factory, app, factory, 0x10000, 1M,
|
|
15
examples/system/console/sdkconfig.defaults
Normal file
15
examples/system/console/sdkconfig.defaults
Normal file
@ -0,0 +1,15 @@
|
||||
# Reduce bootloader log verbosity
|
||||
CONFIG_LOG_BOOTLOADER_LEVEL_WARN=y
|
||||
CONFIG_LOG_BOOTLOADER_LEVEL=2
|
||||
|
||||
# Increase main task stack size
|
||||
CONFIG_MAIN_TASK_STACK_SIZE=7168
|
||||
|
||||
# Enable filesystem
|
||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_example.csv"
|
||||
CONFIG_PARTITION_TABLE_FILENAME="partitions_example.csv"
|
||||
|
||||
# Enable FreeRTOS stats formatting functions, needed for 'tasks' command
|
||||
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
|
||||
CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS=y
|
Reference in New Issue
Block a user