From 9b89776103f8fc3f42fc28e3af9119437b959113 Mon Sep 17 00:00:00 2001 From: HuakeZhBo Date: Fri, 13 Aug 2021 13:20:45 +0000 Subject: [PATCH] implement shell and command demo --- .../sipeed_keyboard_68/CMakeLists.txt | 3 +- .../sipeed_keyboard_68/bl702_flash_ble.ld | 250 +++++++ .../sipeed_keyboard_68/include/shell_config.h | 13 + .../sipeed_keyboard_68/include/smk_command.h | 20 + .../sipeed_keyboard_68/include/smk_shell.h | 132 ++++ .../sipeed_keyboard_68/include/smk_usb.h | 1 + .../keyboard/sipeed_keyboard_68/main.c | 5 +- .../keyboard/sipeed_keyboard_68/smk_cdc.c | 38 +- .../keyboard/sipeed_keyboard_68/smk_shell.c | 611 ++++++++++++++++++ .../keyboard/sipeed_keyboard_68/smk_usb.c | 30 +- 10 files changed, 1069 insertions(+), 34 deletions(-) create mode 100644 firmware/bl_mcu_sdk/examples/keyboard/sipeed_keyboard_68/bl702_flash_ble.ld create mode 100644 firmware/bl_mcu_sdk/examples/keyboard/sipeed_keyboard_68/include/shell_config.h create mode 100644 firmware/bl_mcu_sdk/examples/keyboard/sipeed_keyboard_68/include/smk_command.h create mode 100644 firmware/bl_mcu_sdk/examples/keyboard/sipeed_keyboard_68/include/smk_shell.h create mode 100644 firmware/bl_mcu_sdk/examples/keyboard/sipeed_keyboard_68/smk_shell.c diff --git a/firmware/bl_mcu_sdk/examples/keyboard/sipeed_keyboard_68/CMakeLists.txt b/firmware/bl_mcu_sdk/examples/keyboard/sipeed_keyboard_68/CMakeLists.txt index b37cc4e..c93048b 100644 --- a/firmware/bl_mcu_sdk/examples/keyboard/sipeed_keyboard_68/CMakeLists.txt +++ b/firmware/bl_mcu_sdk/examples/keyboard/sipeed_keyboard_68/CMakeLists.txt @@ -8,12 +8,13 @@ set(TARGET_REQUIRED_SRCS ${CMAKE_CURRENT_LIST_DIR}/ble_peripheral_tp_server.c ${CMAKE_CURRENT_LIST_DIR}/smk_cdc.c ${CMAKE_CURRENT_LIST_DIR}/smk_msc.c ${CMAKE_CURRENT_LIST_DIR}/smk_keyscan.c + ${CMAKE_CURRENT_LIST_DIR}/smk_shell.c ${BSP_COMMON_DIR}/usb/usb_dc.c ${BSP_COMMON_DIR}/usb/uart_interface.c ${BSP_COMMON_DIR}/spi_sd/bsp_spi_sd.c) set(TARGET_REQUIRED_PRIVATE_INCLUDE ${BSP_COMMON_DIR}/usb ${BSP_COMMON_DIR}/spi_sd) set(mains main.c) -set(LINKER_SCRIPT ${CMAKE_SOURCE_DIR}/examples/ble/bl702_flash_ble.ld) +set(LINKER_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/bl702_flash_ble.ld) generate_bin() diff --git a/firmware/bl_mcu_sdk/examples/keyboard/sipeed_keyboard_68/bl702_flash_ble.ld b/firmware/bl_mcu_sdk/examples/keyboard/sipeed_keyboard_68/bl702_flash_ble.ld new file mode 100644 index 0000000..d320ad3 --- /dev/null +++ b/firmware/bl_mcu_sdk/examples/keyboard/sipeed_keyboard_68/bl702_flash_ble.ld @@ -0,0 +1,250 @@ +/**************************************************************************************** +* @file bl702_flash.ld +* +* @brief This file is the map file (gnuarm or armgcc). +* +* Copyright (C) BouffaloLab 2021 +* +**************************************************************************************** +*/ + +/* configure the CPU type */ +OUTPUT_ARCH( "riscv" ) +/* link with the standard c library */ +/* INPUT(-lc) */ +/* link with the standard GCC library */ +/* INPUT(-lgcc) */ +/* configure the entry point */ +ENTRY(_enter) + +StackSize = 0x1000; /* 4KB */ +HeapSize = 0x1000; /* 4KB */ +__EM_SIZE = DEFINED(ble_controller_init) ? 8K : 0K; + +MEMORY +{ + xip_memory (rx) : ORIGIN = 0x23000000, LENGTH = 1024K + itcm_memory (rx) : ORIGIN = 0x22014000, LENGTH = 16K + dtcm_memory (rx) : ORIGIN = 0x42018000, LENGTH = 32K + ram_memory (!rx) : ORIGIN = 0x42020000, LENGTH = 32K + rsvd_memory (!rx) : ORIGIN = 0x42028000, LENGTH = 1K + ram2_memory (!rx) : ORIGIN = 0x42028400, LENGTH = (31K - __EM_SIZE) +} + +SECTIONS +{ + PROVIDE(__metal_chicken_bit = 0); + + .text : + { + . = ALIGN(4); + __text_code_start__ = .; + + KEEP (*(.text.metal.init.enter)) + KEEP (*(SORT_NONE(.init))) + /* section information for finsh shell */ + /*. = ALIGN(4); + _shell_command_start = .; + KEEP(*(shellCommand)) + _shell_command_end = .;*/ + /* section information for shell */ + . = ALIGN(4); + __fsymtab_start = .; + KEEP(*(FSymTab)) + __fsymtab_end = .; + + . = ALIGN(4); + __vsymtab_start = .; + KEEP(*(VSymTab)) + __vsymtab_end = .; + + /* section information for usb desc */ + . = ALIGN(4); + _usb_desc_start = .; + KEEP(*(usb_desc)) + . = ALIGN(4); + _usb_desc_end = .; + + *(.text) + *(.text.*) + + /*put .rodata**/ + *(EXCLUDE_FILE( *bl702_glb.o \ + *bl702_pds.o \ + *bl702_common.o \ + *bl702_sf_cfg.o \ + *bl702_sf_ctrl.o \ + *bl702_sflash.o \ + *bl702_xip_sflash.o \ + *bl702_ef_ctrl.o) .rodata*) + *(.rodata) + *(.rodata.*) + + *(.srodata) + *(.srodata.*) + + _bt_gatt_service_static_list_start = .; + KEEP(*(SORT_BY_NAME("._bt_gatt_service_static.static.*"))) + _bt_gatt_service_static_list_end = .; + _bt_l2cap_fixed_chan_list_start = .; + KEEP(*(SORT_BY_NAME("._bt_l2cap_fixed_chan.static.*"))) + _bt_l2cap_fixed_chan_list_end = .; + + . = ALIGN(4); + __text_code_end__ = .; + } > xip_memory + + . = ALIGN(4); + __itcm_load_addr = .; + + .itcm_region : AT (__itcm_load_addr) + { + . = ALIGN(4); + __tcm_code_start__ = .; + + *(.tcm_code) + *(.tcm_const) + *(.sclock_rlt_code) + *(.sclock_rlt_const) + + *bl702_glb.o*(.rodata*) + *bl702_pds.o*(.rodata*) + *bl702_common.o*(.rodata*) + *bl702_sf_cfg.o*(.rodata*) + *bl702_sf_ctrl.o*(.rodata*) + *bl702_sflash.o*(.rodata*) + *bl702_xip_sflash.o*(.rodata*) + *bl702_ef_ctrl.o*(.rodata*) + + . = ALIGN(4); + __tcm_code_end__ = .; + } > itcm_memory + + __dtcm_load_addr = __itcm_load_addr + SIZEOF(.itcm_region); + + .dtcm_region : AT (__dtcm_load_addr) + { + . = ALIGN(4); + __tcm_data_start__ = .; + + *(.tcm_data) + /* *finger_print.o(.data*) */ + + . = ALIGN(4); + __tcm_data_end__ = .; + } > dtcm_memory + + /* .heap_dummy section doesn't contains any symbols. It is only + * used for linker to calculate size of heap sections, and assign + * values to heap symbols later */ + .heap_dummy (NOLOAD): + { + . = ALIGN(0x4); + . = . + HeapSize; + . = ALIGN(0x4); + } > dtcm_memory + + _HeapBase = ORIGIN(dtcm_memory) + LENGTH(dtcm_memory) - StackSize - HeapSize; + _HeapSize = HeapSize; + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(_HeapBase >= __tcm_data_end__, "region RAM overflowed with stack") + + /*************************************************************************/ + /* .stack_dummy section doesn't contains any symbols. It is only + * used for linker to calculate size of stack sections, and assign + * values to stack symbols later */ + .stack_dummy (NOLOAD): + { + . = ALIGN(0x4); + . = . + StackSize; + . = ALIGN(0x4); + } > dtcm_memory + + /* Set stack top to end of RAM, and stack limit move down by + * size of stack_dummy section */ + __StackTop = ORIGIN(dtcm_memory) + LENGTH(dtcm_memory); + PROVIDE( __freertos_irq_stack_top = __StackTop); + __StackLimit = __StackTop - SIZEOF(.stack_dummy); + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __tcm_data_end__, "region RAM overflowed with stack") + /*************************************************************************/ + + __system_ram_load_addr = __dtcm_load_addr + SIZEOF(.dtcm_region); + + .system_ram_data_region : AT (__system_ram_load_addr) + { + . = ALIGN(4); + __system_ram_data_start__ = .; + + *(.system_ram) + + . = ALIGN(4); + __system_ram_data_end__ = .; + } > ram_memory + + __ram_load_addr = __system_ram_load_addr + SIZEOF(.system_ram_data_region); + + /* Data section */ + RAM_DATA : AT (__ram_load_addr) + { + . = ALIGN(4); + __ram_data_start__ = .; + + PROVIDE( __global_pointer$ = . + 0x800 ); + + *(.data) + *(.data.*) + *(.sdata) + *(.sdata.*) + *(.sdata2) + *(.sdata2.*) + + . = ALIGN(4); + __ram_data_end__ = .; + } > ram_memory + + .bss (NOLOAD) : + { + . = ALIGN(4); + __bss_start__ = .; + + *(.bss*) + *(.sbss*) + *(COMMON) + + . = ALIGN(4); + __bss_end__ = .; + } > ram_memory + + .noinit_data (NOLOAD) : + { + . = ALIGN(4); + __noinit_data_start__ = .; + + *(.noinit_data*) + + . = ALIGN(4); + __noinit_data_end__ = .; + } > ram_memory + + .heap (NOLOAD): + { + . = ALIGN(4); + __HeapBase = .; + + /*__end__ = .;*/ + /*end = __end__;*/ + KEEP(*(.heap*)) + + . = ALIGN(4); + __HeapLimit = .; + } > ram_memory + __HeapLimit = ORIGIN(ram_memory) + LENGTH(ram_memory); + + PROVIDE( _heap_start = ORIGIN(ram2_memory) ); + PROVIDE( _heap_size = LENGTH(ram2_memory) ); + +} + diff --git a/firmware/bl_mcu_sdk/examples/keyboard/sipeed_keyboard_68/include/shell_config.h b/firmware/bl_mcu_sdk/examples/keyboard/sipeed_keyboard_68/include/shell_config.h new file mode 100644 index 0000000..df3dca7 --- /dev/null +++ b/firmware/bl_mcu_sdk/examples/keyboard/sipeed_keyboard_68/include/shell_config.h @@ -0,0 +1,13 @@ +#ifndef __SHELL_CONFIG_H__ +#define __SHELL_CONFIG_H__ + +#define SHELL_NAME "sipeed" +#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/firmware/bl_mcu_sdk/examples/keyboard/sipeed_keyboard_68/include/smk_command.h b/firmware/bl_mcu_sdk/examples/keyboard/sipeed_keyboard_68/include/smk_command.h new file mode 100644 index 0000000..37b5cae --- /dev/null +++ b/firmware/bl_mcu_sdk/examples/keyboard/sipeed_keyboard_68/include/smk_command.h @@ -0,0 +1,20 @@ +#include "smk_shell.h" + +void hellowd() +{ + acm_printf("hello World\r\n"); +} + +int echo(int argc, char *argv[]) +{ + acm_printf("%dparameter(s)\r\n", argc); + + for (uint8_t i = 1; i < argc; i++) { + acm_printf("%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/firmware/bl_mcu_sdk/examples/keyboard/sipeed_keyboard_68/include/smk_shell.h b/firmware/bl_mcu_sdk/examples/keyboard/sipeed_keyboard_68/include/smk_shell.h new file mode 100644 index 0000000..b549ab4 --- /dev/null +++ b/firmware/bl_mcu_sdk/examples/keyboard/sipeed_keyboard_68/include/smk_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 acm_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 +}; + +/* 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 acm_printf(char *fmt, ...); +void shell_handler(uint8_t data); +void shell_init(void); +#endif \ No newline at end of file diff --git a/firmware/bl_mcu_sdk/examples/keyboard/sipeed_keyboard_68/include/smk_usb.h b/firmware/bl_mcu_sdk/examples/keyboard/sipeed_keyboard_68/include/smk_usb.h index 470c3cc..9d75d03 100644 --- a/firmware/bl_mcu_sdk/examples/keyboard/sipeed_keyboard_68/include/smk_usb.h +++ b/firmware/bl_mcu_sdk/examples/keyboard/sipeed_keyboard_68/include/smk_usb.h @@ -4,6 +4,7 @@ #include "hal_usb.h" #include "usbd_core.h" #include "usbd_msc.h" +#include "usbd_cdc.h" #include "smk_msc.h" #include "smk_cdc.h" #include "smk_hid.h" diff --git a/firmware/bl_mcu_sdk/examples/keyboard/sipeed_keyboard_68/main.c b/firmware/bl_mcu_sdk/examples/keyboard/sipeed_keyboard_68/main.c index 2773e46..fd5e66a 100644 --- a/firmware/bl_mcu_sdk/examples/keyboard/sipeed_keyboard_68/main.c +++ b/firmware/bl_mcu_sdk/examples/keyboard/sipeed_keyboard_68/main.c @@ -26,7 +26,8 @@ #include "bl702.h" #include "smk_ble.h" #include "smk_usb.h" - +#include "smk_shell.h" +#include "smk_command.h" extern uint8_t _heap_start; extern uint8_t _heap_size; // @suppress("Type cannot be resolved") @@ -135,7 +136,7 @@ int main(void) static StaticTask_t usb_init_task_h; bflb_platform_init(0); - + shell_init(); MSG("Sipeed Machine Keyboard start...\r\n"); HBN_Set_XCLK_CLK_Sel(HBN_XCLK_CLK_XTAL); diff --git a/firmware/bl_mcu_sdk/examples/keyboard/sipeed_keyboard_68/smk_cdc.c b/firmware/bl_mcu_sdk/examples/keyboard/sipeed_keyboard_68/smk_cdc.c index 363cc04..69c124b 100644 --- a/firmware/bl_mcu_sdk/examples/keyboard/sipeed_keyboard_68/smk_cdc.c +++ b/firmware/bl_mcu_sdk/examples/keyboard/sipeed_keyboard_68/smk_cdc.c @@ -1,7 +1,7 @@ #include "smk_cdc.h" +#include "smk_shell.h" #include "usbd_cdc.h" #include "usbd_core.h" -#include "uart_interface.h" #include "hal_usb.h" #include "stdint.h" @@ -10,30 +10,25 @@ extern struct usbd_interface_cfg usb_cdc; void usbd_cdc_acm_bulk_out(uint8_t ep) { - usb_dc_receive_to_ringbuffer(usb_fs, &usb_rx_rb, ep); + uint32_t actual_read_length = 0; + uint8_t out_buffer[64]; + uint8_t data; + + if (usbd_ep_read(ep, out_buffer, 64, &actual_read_length) < 0) { + USBD_LOG_DBG("Read DATA Packet failed\r\n"); + usbd_ep_set_stall(ep); + return; + } + usbd_ep_read(ep, NULL, 0, NULL); + data = *(uint8_t *)out_buffer; + shell_handler(data); } void usbd_cdc_acm_bulk_in(uint8_t ep) { - usb_dc_send_from_ringbuffer(usb_fs, &uart1_rx_rb, ep); -} -void usbd_cdc_acm_set_line_coding(uint32_t baudrate, uint8_t databits, uint8_t parity, uint8_t stopbits) -{ - uart1_config(baudrate, databits, parity, stopbits); -} - -void usbd_cdc_acm_set_dtr(bool dtr) -{ - dtr_pin_set(dtr); -} - -void usbd_cdc_acm_set_rts(bool rts) -{ - rts_pin_set(rts); } usbd_class_t cdc_class; - usbd_interface_t cdc_cmd_intf; usbd_interface_t cdc_data_intf; @@ -44,16 +39,11 @@ usbd_endpoint_t cdc_out_ep = { usbd_endpoint_t cdc_in_ep = { .ep_addr = CDC_IN_EP, - .ep_cb = usbd_cdc_acm_bulk_in + .ep_cb = NULL }; void smk_cdc_init() { - uart_ringbuffer_init(); - uart1_init(); - uart1_dtr_init(); - uart1_rts_init(); - usbd_cdc_add_acm_interface(&cdc_class, &cdc_cmd_intf); usbd_cdc_add_acm_interface(&cdc_class, &cdc_data_intf); usbd_interface_add_endpoint(&cdc_data_intf, &cdc_out_ep); diff --git a/firmware/bl_mcu_sdk/examples/keyboard/sipeed_keyboard_68/smk_shell.c b/firmware/bl_mcu_sdk/examples/keyboard/sipeed_keyboard_68/smk_shell.c new file mode 100644 index 0000000..cc13d9c --- /dev/null +++ b/firmware/bl_mcu_sdk/examples/keyboard/sipeed_keyboard_68/smk_shell.c @@ -0,0 +1,611 @@ +/** + * @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 "smk_shell.h" +#include "smk_cdc.h" +#include "hal_usb.h" +#include "usbd_core.h" +#include "usbd_cdc.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) +{ + // 输出 help 信息 + SHELL_PRINTF("shell commands list:\r\n"); + { + struct shell_syscall *index; + + // 存储命令名称的字符串前6位为__cmd_ + 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) +{ + // 输出 shell 头:bouffalo/> + static char shell_prompt[SHELL_CONSOLEBUF_SIZE + 1] = { 0 }; + + strcpy(shell_prompt, "\r\n"); + strcat(shell_prompt, SHELL_NAME); + + 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"); // ANSI控制码:删除当前行 + 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; +} + + +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; + } + + /* 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; +} + +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_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; +} + +void acm_printf(char *fmt, ...) +{ + char print_buf[64]; + va_list ap; + + va_start(ap, fmt); + vsnprintf(print_buf, sizeof(print_buf) - 1, fmt, ap); + va_end(ap); +#if ((defined BOOTROM) || (defined BFLB_EFLASH_LOADER)) + uint32_t len = strlen(print_buf); + if (log_len + len < sizeof(eflash_loader_logbuf)) { + memcpy(eflash_loader_logbuf + log_len, print_buf, len); + log_len += len; + } +#endif + usbd_ep_write(CDC_IN_EP,(uint8_t *)print_buf,strlen(print_buf),NULL); +} \ No newline at end of file diff --git a/firmware/bl_mcu_sdk/examples/keyboard/sipeed_keyboard_68/smk_usb.c b/firmware/bl_mcu_sdk/examples/keyboard/sipeed_keyboard_68/smk_usb.c index 5b9629e..d8758db 100644 --- a/firmware/bl_mcu_sdk/examples/keyboard/sipeed_keyboard_68/smk_usb.c +++ b/firmware/bl_mcu_sdk/examples/keyboard/sipeed_keyboard_68/smk_usb.c @@ -9,18 +9,33 @@ #define USBD_MAX_POWER 100 #define USBD_LANGID_STRING 1033 -#define USB_CONFIG_HID_KEYBOARD_SIZE (9 + HID_DESCRIPTOR_LEN) +// #define USB_CONFIG_HID_KEYBOARD_SIZE (9 + HID_DESCRIPTOR_LEN) +#define USB_CONFIG_SIZE (9 + CDC_ACM_DESCRIPTOR_LEN + 8 + HID_DESCRIPTOR_LEN) +USB_DESC_SECTION const uint8_t sipeed_keyboard_descriptor[] = { // single hid keyboard device desc + USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x02, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01), + // USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0200, 0x01), + USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x03, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER), + // USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_HID_KEYBOARD_SIZE, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER), + CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, 0x02), + /////////////////////////////////////// + /// interface association descriptor + /////////////////////////////////////// + 0x08, /* bLength */ + USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, /* bDescriptorType */ + 0x02, /* bFirstInterface */ + 0x01, /* bInterfaceCount */ + 0x03, /* bFunctionClass */ + 0x01, /* bFunctionSubClass */ + 0x01, /* bFunctionProtocol */ + 0x00, /* iFunction */ -USB_DESC_SECTION const uint8_t smk_hid_keyboard_descriptor[] = { // single hid keyboard device desc - USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0200, 0x01), - USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_HID_KEYBOARD_SIZE, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER), // MSC_DESCRIPTOR_INIT(0x00, MSC_OUT_EP, MSC_IN_EP, 0x02), /************** Descriptor of Joystick Mouse interface ****************/ /* 09 */ 0x09, /* bLength: Interface Descriptor size */ USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */ - 0x00, /* bInterfaceNumber: Number of Interface */ + 0x02, /* bInterfaceNumber: Number of Interface */ 0x00, /* bAlternateSetting: Alternate setting */ 0x01, /* bNumEndpoints */ 0x03, /* bInterfaceClass: HID */ @@ -122,13 +137,14 @@ struct device *usb_fs; extern struct device *usb_dc_init(void); void usb_init(){ //task init - usbd_desc_register(smk_hid_keyboard_descriptor); + usbd_desc_register(sipeed_keyboard_descriptor); smk_hid_usb_init(); + smk_cdc_init(); usb_fs = usb_dc_init(); if (usb_fs) { - device_control(usb_fs, DEVICE_CTRL_SET_INT, (void *)(USB_EP1_DATA_IN_IT | USB_EP4_DATA_OUT_IT | USB_EP5_DATA_IN_IT)); + device_control(usb_fs, DEVICE_CTRL_SET_INT, (void *)(USB_EP1_DATA_IN_IT | USB_EP3_DATA_OUT_IT | USB_EP5_DATA_IN_IT)); } while (!usb_device_is_configured()) {