diff --git a/components/shell/CMakeLists.txt b/components/shell/CMakeLists.txt index 5d96f8f6..3a23c215 100644 --- a/components/shell/CMakeLists.txt +++ b/components/shell/CMakeLists.txt @@ -1,7 +1,6 @@ ################# Add global include ################# list(APPEND ADD_INCLUDE "${CMAKE_CURRENT_SOURCE_DIR}" - ) ####################################################### @@ -16,7 +15,6 @@ file(GLOB_RECURSE sources "${CMAKE_CURRENT_SOURCE_DIR}/*.c") #aux_source_directory(. sources) list(APPEND ADD_SRCS ${sources}) -#list(REMOVE_ITEM ADD_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/libc/src/strtox.c" "${CMAKE_CURRENT_SOURCE_DIR}/libc/src/atox.c") ####################################################### ########### Add required/dependent components ######### diff --git a/components/shell/shell.c b/components/shell/shell.c new file mode 100644 index 00000000..c983c75b --- /dev/null +++ b/components/shell/shell.c @@ -0,0 +1,781 @@ +/** + * @file shell.c + * @brief + * + * Copyright (c) 2021 Bouffalolab team + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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 "shell.h" + +struct shell_syscall *_syscall_table_begin = NULL; +struct shell_syscall *_syscall_table_end = NULL; +struct shell_sysvar *_sysvar_table_begin = NULL; +struct shell_sysvar *_sysvar_table_end = NULL; + +struct shell _shell; +static struct shell *shell; + +int shell_help(int argc, char **argv) +{ + SHELL_PRINTF("shell commands list:\r\n"); + { + struct shell_syscall *index; + + for (index = _syscall_table_begin; index < _syscall_table_end; index++) { + if (strncmp(index->name, "__cmd_", 6) != 0) { + continue; + } + +#if defined(SHELL_USING_DESCRIPTION) + SHELL_PRINTF("%-16s - %s\r\n", &index->name[6], index->desc); +#else + SHELL_PRINTF("%s\r\n", &index->name[6]); +#endif + } + } + SHELL_PRINTF("\r\n"); + + return 0; +} +SHELL_CMD_EXPORT_ALIAS(shell_help, help, shell help.); + +static char *shell_get_prompt(void) +{ + static char shell_prompt[SHELL_CONSOLEBUF_SIZE + 1] = { 0 }; + + strcpy(shell_prompt, SHELL_NAME); + +#if defined(SHELL_USING_FS) + /* get current working directory */ + getcwd(&shell_prompt[strlen(shell_prompt)], + SHELL_CONSOLEBUF_SIZE - strlen(shell_prompt)); +#endif + + strcat(shell_prompt, "/>"); + + return shell_prompt; +} + +static int str_common(const char *str1, const char *str2) +{ + const char *str = str1; + + while ((*str != 0) && (*str2 != 0) && (*str == *str2)) { + str++; + str2++; + } + + return (str - str1); +} + +static void shell_handle_history(struct shell *shell) +{ + SHELL_PRINTF("\033[2K\r"); + SHELL_PRINTF("%s%s", shell_get_prompt(), shell->line); +} + +static void shell_push_history(struct shell *shell) +{ + if (shell->line_position != 0) { + /* push history */ + if (shell->history_count >= SHELL_HISTORY_LINES) { + /* if current cmd is same as last cmd, don't push */ + if (memcmp(&shell->cmd_history[SHELL_HISTORY_LINES - 1], shell->line, + SHELL_CMD_SIZE)) { + /* move history */ + int index; + + for (index = 0; index < SHELL_HISTORY_LINES - 1; index++) { + memcpy(&shell->cmd_history[index][0], + &shell->cmd_history[index + 1][0], SHELL_CMD_SIZE); + } + + memset(&shell->cmd_history[index][0], 0, SHELL_CMD_SIZE); + memcpy(&shell->cmd_history[index][0], shell->line, + shell->line_position); + + /* it's the maximum history */ + shell->history_count = SHELL_HISTORY_LINES; + } + } else { + /* if current cmd is same as last cmd, don't push */ + if (shell->history_count == 0 || + memcmp(&shell->cmd_history[shell->history_count - 1], shell->line, + SHELL_CMD_SIZE)) { + shell->current_history = shell->history_count; + memset(&shell->cmd_history[shell->history_count][0], 0, SHELL_CMD_SIZE); + memcpy(&shell->cmd_history[shell->history_count][0], shell->line, + shell->line_position); + + /* increase count and set current history position */ + shell->history_count++; + } + } + } + + shell->current_history = shell->history_count; +} + +#ifdef SHELL_USING_FS + +void shell_auto_complete_path(char *path) +{ + DIR *dir = RT_NULL; + struct dirent *dirent = RT_NULL; + char *full_path, *ptr, *index; + + if (!path) + return; + + full_path = (char *)rt_malloc(256); + if (full_path == RT_NULL) + return; /* out of memory */ + + if (*path != '/') { + getcwd(full_path, 256); + if (full_path[rt_strlen(full_path) - 1] != '/') + strcat(full_path, "/"); + } else + *full_path = '\0'; + + index = RT_NULL; + ptr = path; + for (;;) { + if (*ptr == '/') + index = ptr + 1; + if (!*ptr) + break; + + ptr++; + } + if (index == RT_NULL) + index = path; + + if (index != RT_NULL) { + char *dest = index; + + /* fill the parent path */ + ptr = full_path; + while (*ptr) + ptr++; + + for (index = path; index != dest;) + *ptr++ = *index++; + *ptr = '\0'; + + dir = opendir(full_path); + if (dir == RT_NULL) /* open directory failed! */ + { + rt_free(full_path); + return; + } + + /* restore the index position */ + index = dest; + } + + /* auto complete the file or directory name */ + if (*index == '\0') /* display all of files and directories */ + { + for (;;) { + dirent = readdir(dir); + if (dirent == RT_NULL) + break; + + SHELL_PRINTF("%s\n", dirent->d_name); + } + } else { + rt_size_t length, min_length; + + min_length = 0; + for (;;) { + dirent = readdir(dir); + if (dirent == RT_NULL) + break; + + /* matched the prefix string */ + if (strncmp(index, dirent->d_name, rt_strlen(index)) == 0) { + if (min_length == 0) { + min_length = rt_strlen(dirent->d_name); + /* save dirent name */ + strcpy(full_path, dirent->d_name); + } + + length = str_common(dirent->d_name, full_path); + + if (length < min_length) { + min_length = length; + } + } + } + + if (min_length) { + if (min_length < rt_strlen(full_path)) { + /* list the candidate */ + rewinddir(dir); + + for (;;) { + dirent = readdir(dir); + if (dirent == RT_NULL) + break; + + if (strncmp(index, dirent->d_name, rt_strlen(index)) == 0) + SHELL_PRINTF("%s\n", dirent->d_name); + } + } + + length = index - path; + memcpy(index, full_path, min_length); + path[length + min_length] = '\0'; + } + } + + closedir(dir); + rt_free(full_path); +} +#endif + +static void shell_auto_complete(char *prefix) +{ + int length, min_length; + const char *name_ptr, *cmd_name; + struct shell_syscall *index; + + min_length = 0; + name_ptr = NULL; + + SHELL_PRINTF("\r\n"); + + if (*prefix == '\0') { + shell_help(0, NULL); + return; + } + +#ifdef SHELL_USING_FS + /* check whether a spare in the command */ + { + char *ptr; + + ptr = prefix + strlen(prefix); + + while (ptr != prefix) { + if (*ptr == ' ') { + shell_auto_complete_path(ptr + 1); + break; + } + + ptr--; + } + } +#endif + + /* checks in internal command */ + { + for (index = _syscall_table_begin; index < _syscall_table_end; index++) { + /* skip finsh shell function */ + if (strncmp(index->name, "__cmd_", 6) != 0) { + continue; + } + + cmd_name = (const char *)&index->name[6]; + + if (strncmp(prefix, cmd_name, strlen(prefix)) == 0) { + if (min_length == 0) { + /* set name_ptr */ + name_ptr = cmd_name; + /* set initial length */ + min_length = strlen(name_ptr); + } + + length = str_common(name_ptr, cmd_name); + + if (length < min_length) { + min_length = length; + } + + SHELL_PRINTF("%s\r\n", cmd_name); + } + } + } + + /* auto complete string */ + if (name_ptr != NULL) { + strncpy(prefix, name_ptr, min_length); + } + + SHELL_PRINTF("%s%s", shell_get_prompt(), prefix); + return; +} + +static int shell_split(char *cmd, uint32_t length, char *argv[SHELL_ARG_NUM]) +{ + char *ptr; + uint32_t position; + uint32_t argc; + uint32_t i; + + ptr = cmd; + position = 0; + argc = 0; + + while (position < length) { + /* strip bank and tab */ + while ((*ptr == ' ' || *ptr == '\t') && position < length) { + *ptr = '\0'; + ptr++; + position++; + } + + if (argc >= SHELL_ARG_NUM) { + SHELL_PRINTF("Too many args ! We only Use:\n"); + + for (i = 0; i < argc; i++) { + SHELL_PRINTF("%s ", argv[i]); + } + + SHELL_PRINTF("\r\n"); + break; + } + + if (position >= length) { + break; + } + + /* handle string */ + if (*ptr == '"') { + ptr++; + position++; + argv[argc] = ptr; + argc++; + + /* skip this string */ + while (*ptr != '"' && position < length) { + if (*ptr == '\\') { + if (*(ptr + 1) == '"') { + ptr++; + position++; + } + } + + ptr++; + position++; + } + + if (position >= length) { + break; + } + + /* skip '"' */ + *ptr = '\0'; + ptr++; + position++; + } else { + argv[argc] = ptr; + argc++; + + while ((*ptr != ' ' && *ptr != '\t') && position < length) { + ptr++; + position++; + } + + if (position >= length) { + break; + } + } + } + + return argc; +} + +static cmd_function_t shell_get_cmd(char *cmd, int size) +{ + struct shell_syscall *index; + cmd_function_t cmd_func = NULL; + + for (index = _syscall_table_begin; index < _syscall_table_end; index++) { + if (strncmp(index->name, "__cmd_", 6) != 0) { + continue; + } + + if (strncmp(&index->name[6], cmd, size) == 0 && + index->name[6 + size] == '\0') { + cmd_func = (cmd_function_t)index->func; + break; + } + } + + return cmd_func; +} + +static int shell_exec_cmd(char *cmd, uint32_t length, int *retp) +{ + int argc; + uint32_t cmd0_size = 0; + cmd_function_t cmd_func; + char *argv[SHELL_ARG_NUM]; + + // ASSERT(cmd); + // ASSERT(retp); + + /* find the size of first command */ + while ((cmd[cmd0_size] != ' ' && cmd[cmd0_size] != '\t') && + cmd0_size < length) { + cmd0_size++; + } + + if (cmd0_size == 0) { + return -1; + } + + cmd_func = shell_get_cmd(cmd, cmd0_size); + + if (cmd_func == NULL) { + return -1; + } + + /* split arguments */ + memset(argv, 0x00, sizeof(argv)); + argc = shell_split(cmd, length, argv); + + if (argc == 0) { + return -1; + } + + /* exec this command */ + *retp = cmd_func(argc, argv); + return 0; +} + +#if defined(SHELL_USING_LWIP) && defined(SHELL_USING_FS) +static int shell_exec_lwp(char *cmd, uint32_t length) +{ + int argc; + int cmd0_size = 0; + char *argv[SHELL_ARG_NUM]; + int fd = -1; + char *pg_name; + + extern int exec(char *, int, char **); + + /* find the size of first command */ + while ((cmd[cmd0_size] != ' ' && cmd[cmd0_size] != '\t') && + cmd0_size < length) { + cmd0_size++; + } + + if (cmd0_size == 0) { + return -1; + } + + /* split arguments */ + rt_memset(argv, 0x00, sizeof(argv)); + argc = msh_split(cmd, length, argv); + + if (argc == 0) { + return -1; + } + + pg_name = argv[0]; + /* try to open program */ + fd = open(pg_name, O_RDONLY, 0); + + if (fd < 0) { + return -1; + } + + /* found program */ + close(fd); + exec(pg_name, argc, argv); + + return 0; +} +#endif + +int shell_exec(char *cmd, uint32_t length) +{ + int cmd_ret; + + /* strim the beginning of command */ + while (*cmd == ' ' || *cmd == '\t') { + cmd++; + length--; + } + + if (length == 0) { + return 0; + } + + /* Exec sequence: + * 1. built-in command + * 2. module(if enabled) + */ + if (shell_exec_cmd(cmd, length, &cmd_ret) == 0) { + return cmd_ret; + } + +#ifdef SHELL_USING_FS + extern int shell_exec_script(char *cmd, uint32_t length); + + if (shell_exec_script(cmd, length) == 0) { + return 0; + } + +#endif + +#ifdef SHELL_USING_LWIP + + if (shell_exec_lwp(cmd, length) == 0) { + return 0; + } + +#endif + + /* truncate the cmd at the first space. */ + { + char *tcmd; + tcmd = cmd; + + while (*tcmd != ' ' && *tcmd != '\0') { + tcmd++; + } + + *tcmd = '\0'; + } + SHELL_PRINTF("%s: command not found.\r\n", cmd); + return -1; +} + +void shell_handler(uint8_t data) +{ + /* + * handle control key + * up key : 0x1b 0x5b 0x41 + * down key: 0x1b 0x5b 0x42 + * right key:0x1b 0x5b 0x43 + * left key: 0x1b 0x5b 0x44 + */ + if (data == 0x1b) { + shell->stat = WAIT_SPEC_KEY; + return; + } else if (shell->stat == WAIT_SPEC_KEY) { + if (data == 0x5b) { + shell->stat = WAIT_FUNC_KEY; + return; + } + + shell->stat = WAIT_NORMAL; + } else if (shell->stat == WAIT_FUNC_KEY) { + shell->stat = WAIT_NORMAL; + + if (data == 0x41) /* up key */ + { + /* prev history */ + if (shell->current_history > 0) { + shell->current_history--; + } else { + shell->current_history = 0; + return; + } + + /* copy the history command */ + memcpy(shell->line, &shell->cmd_history[shell->current_history][0], + SHELL_CMD_SIZE); + shell->line_curpos = shell->line_position = strlen(shell->line); + shell_handle_history(shell); + + return; + } else if (data == 0x42) /* down key */ + { + /* next history */ + if (shell->current_history < shell->history_count - 1) { + shell->current_history++; + } else { + /* set to the end of history */ + if (shell->history_count != 0) { + shell->current_history = shell->history_count - 1; + } else { + return; + } + } + + memcpy(shell->line, &shell->cmd_history[shell->current_history][0], + SHELL_CMD_SIZE); + shell->line_curpos = shell->line_position = strlen(shell->line); + shell_handle_history(shell); + + return; + } else if (data == 0x44) /* left key */ + { + if (shell->line_curpos) { + SHELL_PRINTF("\b"); + shell->line_curpos--; + } + + return; + } else if (data == 0x43) /* right key */ + { + if (shell->line_curpos < shell->line_position) { + SHELL_PRINTF("%c", shell->line[shell->line_curpos]); + shell->line_curpos++; + } + + return; + } + } + + /* received null or error */ + if (data == '\0' || data == 0xFF) { + return; + } + /* handle tab key */ + else if (data == '\t') { + int i; + + /* move the cursor to the beginning of line */ + for (i = 0; i < shell->line_curpos; i++) { + SHELL_PRINTF("\b"); + } + + /* auto complete */ + shell_auto_complete(&shell->line[0]); + /* re-calculate position */ + shell->line_curpos = shell->line_position = strlen(shell->line); + + return; + } + /* handle backspace key */ + else if (data == 0x7f || data == 0x08) { + /* note that shell->line_curpos >= 0 */ + if (shell->line_curpos == 0) { + return; + } + + shell->line_position--; + shell->line_curpos--; + + if (shell->line_position > shell->line_curpos) { + int i; + + memmove(&shell->line[shell->line_curpos], + &shell->line[shell->line_curpos + 1], + shell->line_position - shell->line_curpos); + shell->line[shell->line_position] = 0; + + SHELL_PRINTF("\b%s \b", &shell->line[shell->line_curpos]); + + /* move the cursor to the origin position */ + for (i = shell->line_curpos; i <= shell->line_position; i++) { + SHELL_PRINTF("\b"); + } + } else { + SHELL_PRINTF("\b \b"); + shell->line[shell->line_position] = 0; + } + + return; + } + + /* handle end of line, break */ + if (data == '\r' || data == '\n') { + shell_push_history(shell); + + SHELL_PRINTF("\r\n"); + shell_exec(shell->line, shell->line_position); + + SHELL_PRINTF(shell_get_prompt()); + memset(shell->line, 0, sizeof(shell->line)); + shell->line_curpos = shell->line_position = 0; + return; + } + + /* it's a large line, discard it */ + if (shell->line_position >= SHELL_CMD_SIZE) { + shell->line_position = 0; + } + + /* normal character */ + if (shell->line_curpos < shell->line_position) { + int i; + + memmove(&shell->line[shell->line_curpos + 1], + &shell->line[shell->line_curpos], + shell->line_position - shell->line_curpos); + shell->line[shell->line_curpos] = data; + + SHELL_PRINTF("%s", &shell->line[shell->line_curpos]); + + /* move the cursor to new position */ + for (i = shell->line_curpos; i < shell->line_position; i++) { + SHELL_PRINTF("\b"); + } + } else { + shell->line[shell->line_position] = data; + SHELL_PRINTF("%c", data); + } + + data = 0; + shell->line_position++; + shell->line_curpos++; + + if (shell->line_position >= SHELL_CMD_SIZE) { + /* clear command line */ + shell->line_position = 0; + shell->line_curpos = 0; + } +} + +static void shell_function_init(const void *begin, const void *end) +{ + _syscall_table_begin = (struct shell_syscall *)begin; + _syscall_table_end = (struct shell_syscall *)end; +} + +static void shell_var_init(const void *begin, const void *end) +{ + _sysvar_table_begin = (struct shell_sysvar *)begin; + _sysvar_table_end = (struct shell_sysvar *)end; +} + +/* + * @ingroup shell + * + * This function will initialize shell + */ +void shell_init(void) +{ +#if defined(__CC_ARM) || defined(__CLANG_ARM) /* ARM C Compiler */ + extern const int FSymTab$$Base; + extern const int FSymTab$$Limit; + extern const int VSymTab$$Base; + extern const int VSymTab$$Limit; + shell_function_init(&FSymTab$$Base, &FSymTab$$Limit); + shell_var_init(&VSymTab$$Base, &VSymTab$$Limit); +#elif defined(__ICCARM__) || defined(__ICCRX__) /* for IAR Compiler */ + shell_function_init(__section_begin("FSymTab"), __section_end("FSymTab")); + shell_var_init(__section_begin("VSymTab"), __section_end("VSymTab")); +#elif defined(__GNUC__) + /* GNU GCC Compiler and TI CCS */ + extern const int __fsymtab_start; + extern const int __fsymtab_end; + extern const int __vsymtab_start; + extern const int __vsymtab_end; + shell_function_init(&__fsymtab_start, &__fsymtab_end); + shell_var_init(&__vsymtab_start, &__vsymtab_end); +#endif + shell = &_shell; +} \ No newline at end of file diff --git a/components/shell/shell.h b/components/shell/shell.h new file mode 100644 index 00000000..520eb072 --- /dev/null +++ b/components/shell/shell.h @@ -0,0 +1,132 @@ +/** + * @file shell.h + * @brief + * + * Copyright (c) 2021 Bouffalolab team + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ +#ifndef __SHELL_H__ +#define __SHELL_H__ + +#include "stdint.h" +#include "string.h" +#include "shell_config.h" +#include "bflb_platform.h" + +#define SHELL_PRINTF bflb_platform_printf + +typedef int (*syscall_func)(void); +typedef int (*cmd_function_t)(int argc, char **argv); + +enum input_stat { + WAIT_NORMAL, + WAIT_SPEC_KEY, + WAIT_FUNC_KEY, +}; + +struct shell { + enum input_stat stat; + + uint16_t current_history; + uint16_t history_count; + char cmd_history[SHELL_HISTORY_LINES][SHELL_CMD_SIZE]; + + char line[SHELL_CMD_SIZE]; + uint16_t line_position; + uint16_t line_curpos; + +#ifdef SHELL_USING_AUTH + char password[SHELL_PASSWORD_MAX]; +#endif + +#if defined(SHELL_USING_FS) + +#endif +}; + +/* system call table */ +struct shell_syscall { + const char *name; /* the name of system call */ +#if defined(SHELL_USING_DESCRIPTION) + const char *desc; /* description of system call */ +#endif + syscall_func func; /* the function address of system call */ +}; + +/* system variable table */ +struct shell_sysvar { + const char *name; /* the name of variable */ +#if defined(SHELL_USING_DESCRIPTION) + const char *desc; /* description of system variable */ +#endif + uint8_t type; /* the type of variable */ + void *var; /* the address of variable */ +}; + +#ifdef SHELL_USING_DESCRIPTION +#define SHELL_FUNCTION_EXPORT_CMD(name, cmd, desc) \ + const char __fsym_##cmd##_name[] __attribute__((section(".rodata.name"))) = #cmd; \ + const char __fsym_##cmd##_desc[] __attribute__((section(".rodata.name"))) = #desc; \ + __attribute__((used)) const struct shell_syscall __fsym_##cmd __attribute__((section("FSymTab"))) = { \ + __fsym_##cmd##_name, \ + __fsym_##cmd##_desc, \ + (syscall_func)&name \ + }; + +#define SHELL_VAR_EXPORT(name, type, desc) \ + const char __vsym_##name##_name[] __attribute__((section(".rodata.name"))) = #name; \ + const char __vsym_##name##_desc[] __attribute__((section(".rodata.name"))) = #desc; \ + __attribute__((used)) const struct shell_sysvar __vsym_##name __attribute__((section("VSymTab"))) = { \ + __vsym_##name##_name, \ + __vsym_##name##_desc, \ + type, \ + (void *)&name \ + }; +#else +#define SHELL_FUNCTION_EXPORT_CMD(name, cmd, desc) \ + const char __fsym_##cmd##_name[] = #cmd; \ + __attribute__((used)) const struct shell_syscall __fsym_##cmd __attribute__((section("FSymTab"))) = { \ + __fsym_##cmd##_name, \ + (syscall_func)&name \ + }; + +#define SHELL_VAR_EXPORT(name, type, desc) \ + const char __vsym_##name##_name[] = #name; \ + __attribute__((used)) const struct shell_sysvar __vsym_##name __attribute__((section("VSymTab"))) = { \ + __vsym_##name##_name, \ + type, \ + (void *)&name \ + }; +#endif /* end of SHELL_USING_DESCRIPTION */ + +/** + * @ingroup shell + * + * This macro exports a command to module shell. + * + * @param command the name of command. + * @param desc the description of command, which will show in help. + */ +#define SHELL_CMD_EXPORT(command, desc) \ + SHELL_FUNCTION_EXPORT_CMD(command, __cmd_##command, desc) +#define SHELL_CMD_EXPORT_ALIAS(command, alias, desc) \ + SHELL_FUNCTION_EXPORT_CMD(command, __cmd_##alias, desc) + +void shell_handler(uint8_t data); +void shell_init(void); +#endif \ No newline at end of file diff --git a/components/shell/shell_config.h b/components/shell/shell_config.h new file mode 100644 index 00000000..a9404a48 --- /dev/null +++ b/components/shell/shell_config.h @@ -0,0 +1,13 @@ +#ifndef __SHELL_CONFIG_H__ +#define __SHELL_CONFIG_H__ + +#define SHELL_NAME "bouffalolab " +#define SHELL_CONSOLEBUF_SIZE 128 + +#define SHELL_HISTORY_LINES 5 +#define SHELL_CMD_SIZE 50 +#define SHELL_ARG_NUM 8 + +//#define SHELL_USING_FS + +#endif \ No newline at end of file diff --git a/examples/shell/CMakeLists.txt b/examples/shell/CMakeLists.txt new file mode 100644 index 00000000..27d34535 --- /dev/null +++ b/examples/shell/CMakeLists.txt @@ -0,0 +1,4 @@ +set(TARGET_REQUIRED_LIBS shell) +set(mains main.c) +generate_bin() + diff --git a/examples/shell/cdk/shell.cdkproj b/examples/shell/cdk/shell.cdkproj new file mode 100644 index 00000000..b59f9a42 --- /dev/null +++ b/examples/shell/cdk/shell.cdkproj @@ -0,0 +1,921 @@ + + + CPU: RV32IMAFC +Chip: bl70x +Board: bl70x_iot + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 76 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ;;; + ;;MHZ; + + 1 + 1 + + 100:8;100:8;100:8;100:8; + + + + + + + + no + 0x23000000 + 0x100000 + + + no + 0x22014000 + 0x4000 + + + no + 0x42018000 + 0x8000 + + + no + + + + + no + + + + + + + yes + 0x42020000 + 0xc000 + yes + + + no + + + yes + + + no + + + yes + + + no + + + yes + + + no + + + yes + + + rv32imafc + no + little + no + no + no + no + + + $(ProjectName) + Executable + no + yes + no + yes + no + yes + + + + no + + + + no + + + + no + $(ProjectPath)../../../tools/bflb_flash_tool/bflb_mcu_tool.exe --chipname=bl702 --interface=openocd --firmware="$(ProjectPath)/Obj/$(ProjectName).bin" + + + + ARCH_RISCV; + + Optimize more (-O2) + Default (-g) + $(ProjectPath);$(ProjectPath)../;$(ProjectPath)../../../components/fatfs;$(ProjectPath)../../../components/freertos/Source/include;$(ProjectPath)../../../components/shell;$(ProjectPath)../../../components/usb_stack/class/audio;$(ProjectPath)../../../components/usb_stack/class/cdc;$(ProjectPath)../../../components/usb_stack/class/hid;$(ProjectPath)../../../components/usb_stack/class/msc;$(ProjectPath)../../../components/usb_stack/class/video;$(ProjectPath)../../../components/usb_stack/class/webusb;$(ProjectPath)../../../components/usb_stack/class/winusb;$(ProjectPath)../../../components/usb_stack/common;$(ProjectPath)../../../components/usb_stack/core;$(ProjectPath)../../../bsp/board/bl706_iot;$(ProjectPath)../../../bsp/bsp_common/platform;$(ProjectPath)../../../common/libc/inc;$(ProjectPath)../../../common/libc/inc/arm_gcc;$(ProjectPath)../../../common/libc/inc/bits;$(ProjectPath)../../../common/libc/inc/sys;$(ProjectPath)../../../common/libc/src;$(ProjectPath)../../../common/device;$(ProjectPath)../../../common/list;$(ProjectPath)../../../common/memheap;$(ProjectPath)../../../common/misc;$(ProjectPath)../../../common/ring_buffer;$(ProjectPath)../../../common/soft_crc;$(ProjectPath)../../../components/shell;$(ProjectPath)../../../drivers/bl702_driver/hal_drv/default_config;$(ProjectPath)../../../drivers/bl702_driver/hal_drv/inc;$(ProjectPath)../../../drivers/bl702_driver/risc-v/Core/Include;$(ProjectPath)../../../drivers/bl702_driver/regs;$(ProjectPath)../../../drivers/bl702_driver/startup;$(ProjectPath)../../../drivers/bl702_driver/std_drv/inc;$(ProjectPath)../../../drivers/bl602_driver/risc-v/Core/Include;$(ProjectPath)../../../drivers/bl602_driver/startup;$(ProjectPath)../../../drivers/bl602_driver/hal_drv/inc;$(ProjectPath)../../../drivers/bl602_driver/hal_drv/default_config;$(ProjectPath)../../../drivers/bl602_driver/regs;$(ProjectPath)../../../drivers/bl602_driver/std_drv/inc + -fshort-enums -fno-common -fms-extensions -ffunction-sections -fdata-sections -fstrict-volatile-bitfields -Wall -Wshift-negative-value -Wchar-subscripts -Wformat -Wuninitialized -Winit-self -fno-jump-tables -Wignored-qualifiers -Wswitch-default -Wunused -Wundef -msmall-data-limit=4 + no + no + no + no + no + no + yes + no + yes + no + + + + + $(ProjectPath);$(ProjectPath)../;$(ProjectPath)../../../components/fatfs;$(ProjectPath)../../../components/freertos/Source/include;$(ProjectPath)../../../components/shell;$(ProjectPath)../../../components/usb_stack/class/audio;$(ProjectPath)../../../components/usb_stack/class/cdc;$(ProjectPath)../../../components/usb_stack/class/hid;$(ProjectPath)../../../components/usb_stack/class/msc;$(ProjectPath)../../../components/usb_stack/class/video;$(ProjectPath)../../../components/usb_stack/class/webusb;$(ProjectPath)../../../components/usb_stack/class/winusb;$(ProjectPath)../../../components/usb_stack/common;$(ProjectPath)../../../components/usb_stack/core;$(ProjectPath)../../../bsp/board/bl706_iot;$(ProjectPath)../../../bsp/bsp_common/platform;$(ProjectPath)../../../common/device;$(ProjectPath)../../../common/list;$(ProjectPath)../../../common/memheap;$(ProjectPath)../../../common/misc;$(ProjectPath)../../../common/ring_buffer;$(ProjectPath)../../../common/soft_crc;$(ProjectPath)../../../components/shell;$(ProjectPath)../../../drivers/bl702_driver/hal_drv/default_config;$(ProjectPath)../../../drivers/bl702_driver/hal_drv/inc;$(ProjectPath)../../../drivers/bl702_driver/risc-v/Core/Include;$(ProjectPath)../../../drivers/bl702_driver/regs;$(ProjectPath)../../../drivers/bl702_driver/startup;$(ProjectPath)../../../drivers/bl702_driver/std_drv/inc;$(ProjectPath)../../../drivers/bl602_driver/risc-v/Core/Include;$(ProjectPath)../../../drivers/bl602_driver/startup;$(ProjectPath)../../../drivers/bl602_driver/hal_drv/inc;$(ProjectPath)../../../drivers/bl602_driver/hal_drv/default_config;$(ProjectPath)../../../drivers/bl602_driver/regs;$(ProjectPath)../../../drivers/bl602_driver/std_drv/inc + + gdwarf2 + + + yes + yes + $(ProjectPath)../../../drivers/bl702_driver/bl702_flash.ld + + + + no + + + + yes + OpenOCD + yes + main + + $(ProjectPath)../../../tools/openocd/bl70x_gdb.init + yes + Hard Reset + 23000000 + no + no + $(ProjectPath)/$(ProjectName).cdkcore + + localhost + 1025 + 0 + 2000 + 10 + 50 + yes + no + no + Normal + Hard Reset + 21000000 + Bare Metal + yes + yes + + Local + -arch riscv + + + + + yes + no + no + + + openocd-hifive + no + 4444 + no + 6666 + -f ../../../tools/openocd/if_rv_dbg_plus.cfg -f ../../../tools/openocd/tgt_702.cfg + + + + + Erase Sectors + bl70x_flasher.elf + yes + yes + no + Hard Reset + + no + + + + + + + + + no + 0x23000000 + 0x100000 + + + no + 0x22014000 + 0x4000 + + + no + 0x42018000 + 0x8000 + + + no + + + + + no + + + + + + + yes + 0x42020000 + 0xc000 + yes + + + no + + + yes + + + no + + + yes + + + no + + + yes + + + no + + + yes + + + rv32imac + no + little + no + no + no + no + + + $(ProjectName) + Executable + no + yes + no + yes + no + yes + + + + no + + + + no + + + + no + $(ProjectPath)../../../tools/bflb_flash_tool/bflb_mcu_tool.exe --chipname=bl702 --firmware="$(ProjectPath)/Obj/$(ProjectName).bin" + + + + ARCH_RISCV; + + Optimize more (-O2) + Default (-g) + $(ProjectPath);$(ProjectPath)../;$(ProjectPath)../../../components/fatfs;$(ProjectPath)../../../components/freertos/Source/include;$(ProjectPath)../../../components/shell;$(ProjectPath)../../../components/usb_stack/class/audio;$(ProjectPath)../../../components/usb_stack/class/cdc;$(ProjectPath)../../../components/usb_stack/class/hid;$(ProjectPath)../../../components/usb_stack/class/msc;$(ProjectPath)../../../components/usb_stack/class/video;$(ProjectPath)../../../components/usb_stack/class/webusb;$(ProjectPath)../../../components/usb_stack/class/winusb;$(ProjectPath)../../../components/usb_stack/common;$(ProjectPath)../../../components/usb_stack/core;$(ProjectPath)../../../bsp/board/bl706_iot;$(ProjectPath)../../../bsp/bsp_common/platform;$(ProjectPath)../../../common/libc/inc;$(ProjectPath)../../../common/libc/inc/arm_gcc;$(ProjectPath)../../../common/libc/inc/bits;$(ProjectPath)../../../common/libc/inc/sys;$(ProjectPath)../../../common/libc/src;$(ProjectPath)../../../common/device;$(ProjectPath)../../../common/list;$(ProjectPath)../../../common/memheap;$(ProjectPath)../../../common/misc;$(ProjectPath)../../../common/ring_buffer;$(ProjectPath)../../../common/soft_crc;$(ProjectPath)../../../components/shell;$(ProjectPath)../../../drivers/bl702_driver/hal_drv/default_config;$(ProjectPath)../../../drivers/bl702_driver/hal_drv/inc;$(ProjectPath)../../../drivers/bl702_driver/risc-v/Core/Include;$(ProjectPath)../../../drivers/bl702_driver/regs;$(ProjectPath)../../../drivers/bl702_driver/startup;$(ProjectPath)../../../drivers/bl702_driver/std_drv/inc;$(ProjectPath)../../../drivers/bl602_driver/risc-v/Core/Include;$(ProjectPath)../../../drivers/bl602_driver/startup;$(ProjectPath)../../../drivers/bl602_driver/hal_drv/inc;$(ProjectPath)../../../drivers/bl602_driver/hal_drv/default_config;$(ProjectPath)../../../drivers/bl602_driver/regs;$(ProjectPath)../../../drivers/bl602_driver/std_drv/inc + -fshort-enums -fno-common -fms-extensions -ffunction-sections -fdata-sections -fstrict-volatile-bitfields -Wall -Wshift-negative-value -Wchar-subscripts -Wformat -Wuninitialized -Winit-self -fno-jump-tables -Wignored-qualifiers -Wswitch-default -Wunused -Wundef -msmall-data-limit=4 + no + no + no + no + no + no + yes + no + yes + no + + + + + $(ProjectPath);$(ProjectPath)../;$(ProjectPath)../../../components/fatfs;$(ProjectPath)../../../components/freertos/Source/include;$(ProjectPath)../../../components/shell;$(ProjectPath)../../../components/usb_stack/class/audio;$(ProjectPath)../../../components/usb_stack/class/cdc;$(ProjectPath)../../../components/usb_stack/class/hid;$(ProjectPath)../../../components/usb_stack/class/msc;$(ProjectPath)../../../components/usb_stack/class/video;$(ProjectPath)../../../components/usb_stack/class/webusb;$(ProjectPath)../../../components/usb_stack/class/winusb;$(ProjectPath)../../../components/usb_stack/common;$(ProjectPath)../../../components/usb_stack/core;$(ProjectPath)../../../bsp/board/bl706_iot;$(ProjectPath)../../../bsp/bsp_common/platform;$(ProjectPath)../../../common/device;$(ProjectPath)../../../common/list;$(ProjectPath)../../../common/memheap;$(ProjectPath)../../../common/misc;$(ProjectPath)../../../common/ring_buffer;$(ProjectPath)../../../common/soft_crc;$(ProjectPath)../../../components/shell;$(ProjectPath)../../../drivers/bl702_driver/hal_drv/default_config;$(ProjectPath)../../../drivers/bl702_driver/hal_drv/inc;$(ProjectPath)../../../drivers/bl702_driver/risc-v/Core/Include;$(ProjectPath)../../../drivers/bl702_driver/regs;$(ProjectPath)../../../drivers/bl702_driver/startup;$(ProjectPath)../../../drivers/bl702_driver/std_drv/inc;$(ProjectPath)../../../drivers/bl602_driver/risc-v/Core/Include;$(ProjectPath)../../../drivers/bl602_driver/startup;$(ProjectPath)../../../drivers/bl602_driver/hal_drv/inc;$(ProjectPath)../../../drivers/bl602_driver/hal_drv/default_config;$(ProjectPath)../../../drivers/bl602_driver/regs;$(ProjectPath)../../../drivers/bl602_driver/std_drv/inc + + gdwarf2 + + + yes + yes + $(ProjectPath)../../../drivers/bl702_driver/bl702_flash.ld + + + + no + + + + no + ICE + yes + main + $(ProjectPath)/../../../tools/openocd/bl70x_gdb.init + + yes + Hard Reset + 21000000 + no + no + $(ProjectPath)/$(ProjectName).cdkcore + + localhost + 1025 + 0 + 2000 + 10 + 50 + yes + yes + no + with Pre-reset + Hard Reset + 21000000 + Bare Metal + no + yes + + Local + -arch riscv + + + + + yes + no + no + + + openocd-hifive + no + 4444 + no + 6666 + -f ../../../tools/openocd/if_rv_dbg_plus.cfg -f ../../../tools/openocd/tgt_702.cfg + + + + $(ProjectPath)/flash.init + Erase Sectors + + no + no + no + Soft Reset + + yes + + + + + + + + ;;; + ;;MHZ; + + glb + uart + + 1 + 1 + + 100:8;100:8;100:8;100:8; + + + + ;;; + ;;MHZ; + + glb + uart + + 1 + 1 + + 100:8;100:8;100:8;100:8; + + diff --git a/examples/shell/main.c b/examples/shell/main.c new file mode 100644 index 00000000..80192cbe --- /dev/null +++ b/examples/shell/main.c @@ -0,0 +1,67 @@ +/** + * @file main.c + * @brief + * + * Copyright (c) 2021 Bouffalolab team + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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 "hal_uart.h" +#include "shell.h" + +void shell_irq_callback(struct device *dev, void *args, uint32_t size, uint32_t state) +{ + uint8_t data; + if (state == UART_EVENT_RX_FIFO) { + data = *(uint8_t *)args; + shell_handler(data); + } +} + +int main(void) +{ + bflb_platform_init(0); + shell_init(); + struct device *uart = device_find("debug_log"); + if (uart) { + device_set_callback(uart, shell_irq_callback); + device_control(uart, DEVICE_CTRL_SET_INT, (void *)(UART_RX_FIFO_IT)); + } + + while (1) { + __asm volatile("nop"); + } +} + +void hellowd() +{ + MSG("hello World\r\n"); +} + +int echo(int argc, char *argv[]) +{ + MSG("%dparameter(s)\r\n", argc); + + for (uint8_t i = 1; i < argc; i++) { + MSG("%s\r\n", argv[i]); + } + + return 0; +} + +SHELL_CMD_EXPORT(hellowd, hellowd test) +SHELL_CMD_EXPORT(echo, echo test) \ No newline at end of file diff --git a/examples/shell/readme.md b/examples/shell/readme.md new file mode 100644 index 00000000..62a45921 --- /dev/null +++ b/examples/shell/readme.md @@ -0,0 +1,5 @@ +```bash + +$ make APP=shell BOARD=bl706_iot + +``` \ No newline at end of file