diff --git a/examples/platform/ameba/shell/launch_shell.cpp b/examples/platform/ameba/shell/launch_shell.cpp index d6feddb7dadf59..435966b27e89fa 100644 --- a/examples/platform/ameba/shell/launch_shell.cpp +++ b/examples/platform/ameba/shell/launch_shell.cpp @@ -21,6 +21,7 @@ #include "task.h" #include +#include namespace { @@ -35,7 +36,11 @@ namespace chip { void LaunchShell() { - chip::Shell::Engine::Root().Init(); + if (chip::Shell::Engine::Root().Init() < 0) + { + ChipLogError(DeviceLayer, "Failed to initialize shell engine!"); + return; + } xTaskCreate(MatterShellTask, "matter_shell", 2048, NULL, tskIDLE_PRIORITY + 1, NULL); } diff --git a/src/lib/shell/BUILD.gn b/src/lib/shell/BUILD.gn index 7f3d1d46cb62b1..68af8be17cb766 100644 --- a/src/lib/shell/BUILD.gn +++ b/src/lib/shell/BUILD.gn @@ -104,7 +104,7 @@ static_library("shell") { ] } else if (chip_device_platform == "ameba") { sources += [ - "MainLoopDefault.cpp", + "MainLoopAmeba.cpp", "streamer_ameba.cpp", ] } else if (chip_device_platform == "openiotsdk") { diff --git a/src/lib/shell/MainLoopAmeba.cpp b/src/lib/shell/MainLoopAmeba.cpp new file mode 100644 index 00000000000000..0526980e7f6080 --- /dev/null +++ b/src/lib/shell/MainLoopAmeba.cpp @@ -0,0 +1,153 @@ +/* + * + * Copyright (c) 2021 Project CHIP Authors + * + * 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 "streamer.h" +#include +#include +#include + +#include +#include + +using chip::FormatCHIPError; +using chip::Platform::MemoryAlloc; +using chip::Platform::MemoryFree; +using chip::Shell::Engine; +using chip::Shell::streamer_get; + +namespace { + +size_t ReadLine(char * buffer, size_t max) +{ + return streamer_read(streamer_get(), buffer, max); +} + +bool IsSeparator(char ch) +{ + return (ch == ' ') || (ch == '\t') || (ch == '\r') || (ch == '\n'); +} + +bool IsEscape(char ch) +{ + return (ch == '\\'); +} + +bool IsEscapable(char ch) +{ + return IsSeparator(ch) || IsEscape(ch); +} + +int TokenizeLine(char * buffer, char ** tokens, int max_tokens) +{ + size_t len = strlen(buffer); + int cursor = 0; + size_t i = 0; + + // Strip leading spaces + while (buffer[i] && buffer[i] == ' ') + { + i++; + } + + if (len <= i) + { + return 0; + } + + // The first token starts at the beginning. + tokens[cursor++] = &buffer[i]; + + for (; i < len && cursor < max_tokens; i++) + { + if (IsEscape(buffer[i]) && IsEscapable(buffer[i + 1])) + { + // include the null terminator: strlen(cmd) = strlen(cmd + 1) + 1 + memmove(&buffer[i], &buffer[i + 1], strlen(&buffer[i])); + } + else if (IsSeparator(buffer[i])) + { + buffer[i] = 0; + if (!IsSeparator(buffer[i + 1])) + { + tokens[cursor++] = &buffer[i + 1]; + } + } + } + // If for too many arguments, overwrite last entry with guard. + if (cursor >= max_tokens) + { + cursor = max_tokens - 1; + } + + tokens[cursor] = nullptr; + + return cursor; +} + +void ProcessShellLine(intptr_t args) +{ + int argc; + char * argv[CHIP_SHELL_MAX_TOKENS]; + + char * line = reinterpret_cast(args); + argc = TokenizeLine(line, argv, CHIP_SHELL_MAX_TOKENS); + + if (argc > 0) + { + CHIP_ERROR retval = Engine::Root().ExecCommand(argc, argv); + + if (retval != CHIP_NO_ERROR) + { + char errorStr[160]; + bool errorStrFound = FormatCHIPError(errorStr, sizeof(errorStr), retval); + if (!errorStrFound) + { + errorStr[0] = 0; + } + streamer_printf(streamer_get(), "Error %s: %s\r\n", argv[0], errorStr); + } + else + { + streamer_printf(streamer_get(), "Done\r\n", argv[0]); + } + } +} + +} // namespace + +namespace chip { +namespace Shell { + +void Engine::RunMainLoop() +{ + char line[CHIP_SHELL_MAX_LINE_SIZE]; + while (true) + { + memset(line, 0, CHIP_SHELL_MAX_LINE_SIZE); + if (ReadLine(line, CHIP_SHELL_MAX_LINE_SIZE) > 0u) + { +#if CONFIG_DEVICE_LAYER + DeviceLayer::PlatformMgr().ScheduleWork(ProcessShellLine, reinterpret_cast(line)); +#else + ProcessShellLine(reinterpret_cast(line)); +#endif + } + } +} + +} // namespace Shell +} // namespace chip diff --git a/src/lib/shell/streamer_ameba.cpp b/src/lib/shell/streamer_ameba.cpp index d585aa942a74fa..d553331e2fcbd9 100644 --- a/src/lib/shell/streamer_ameba.cpp +++ b/src/lib/shell/streamer_ameba.cpp @@ -22,59 +22,45 @@ #include #include +#include #include #include -#include "serial_api.h" - -#if defined(CONFIG_PLATFORM_8721D) -#define UART_TX PA_18 // UART0 TX -#define UART_RX PA_19 // UART0 RX -#elif defined(CONFIG_PLATFORM_8710C) -#define UART_TX PA_14 // UART0 TX -#define UART_RX PA_13 // UART0 RX -#endif +extern QueueHandle_t shell_queue; namespace chip { namespace Shell { namespace { -serial_t sobj; - int streamer_ameba_init(streamer_t * streamer) { - (void) streamer; - serial_init(&sobj, UART_TX, UART_RX); - serial_baud(&sobj, 115200); - serial_format(&sobj, 8, ParityNone, 1); + // freertos queue should be initialized in ameba sdk + if (shell_queue == NULL) + { + // queue not initialized + return -1; + } + return 0; } ssize_t streamer_ameba_read(streamer_t * streamer, char * buffer, size_t length) { - (void) streamer; - uint16_t len_read = 0; - - while (len_read < length) + BaseType_t lineReceived = xQueueReceive(shell_queue, buffer, pdMS_TO_TICKS(10)); + if (lineReceived == pdTRUE) { - *(buffer + len_read) = (char) serial_getc(&sobj); - len_read++; + return length; } - return len_read; + + return 0; } ssize_t streamer_ameba_write(streamer_t * streamer, const char * buffer, size_t length) { (void) streamer; - uint16_t len_written = 0; - - while (len_written < length) - { - serial_putc(&sobj, *(buffer + len_written)); - len_written++; - } - return len_written; + printf("[shell] %s\r\n", buffer); + return length; } static streamer_t streamer_ameba = {