From af888fb6dd5428b09ec100ca22bdf1ba5ceaee7a Mon Sep 17 00:00:00 2001 From: Yilin Sun Date: Tue, 7 Mar 2023 23:23:01 +0800 Subject: [PATCH] Fixed LN de-init and re-init, added testing REPL. Signed-off-by: Yilin Sun --- .clang-format | 2 +- CMakeLists.txt | 1 + arm-none-eabi.cmake | 2 +- include/FreeRTOSConfig.h | 2 +- include/app_mrb_repl.h | 10 +++++ lib/linenoise/linenoise.c | 7 ++- lib/linenoise/linenoise.h | 1 + src/app_mrb_repl.c | 85 ++++++++++++++++++++++++++++++++++++ src/app_syscalls.c | 2 +- src/main.c | 92 ++++++++++----------------------------- 10 files changed, 128 insertions(+), 76 deletions(-) create mode 100644 include/app_mrb_repl.h create mode 100644 src/app_mrb_repl.c diff --git a/.clang-format b/.clang-format index f54fc18..214adf0 100644 --- a/.clang-format +++ b/.clang-format @@ -2,7 +2,7 @@ BasedOnStyle: Google IndentWidth: 4 AlignConsecutiveMacros: Consecutive AlignConsecutiveDeclarations: Consecutive -AlignConsecutiveAssignments: AcrossEmptyLinesAndComments +AlignConsecutiveAssignments: Consecutive AllowShortFunctionsOnASingleLine: None BreakBeforeBraces: Custom BraceWrapping: diff --git a/CMakeLists.txt b/CMakeLists.txt index 20c7f62..ec22ed8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -62,6 +62,7 @@ set(TARGET_SOURCES "board/peripherals.c" "board/pin_mux.c" "lib/linenoise/linenoise.c" + "src/app_mrb_repl.c" "src/app_syscalls.c" "src/main.c" ) diff --git a/arm-none-eabi.cmake b/arm-none-eabi.cmake index 7c89918..be73908 100644 --- a/arm-none-eabi.cmake +++ b/arm-none-eabi.cmake @@ -11,7 +11,7 @@ set(TARGET_TOOLCHAIN_SIZE arm-none-eabi-size) set(CMAKE_C_FLAGS_INIT "-mcpu=cortex-m33 -mthumb -mfloat-abi=hard -mfpu=fpv5-sp-d16") set(CMAKE_CXX_FLAGS_INIT "-mcpu=cortex-m33 -mthumb -mfloat-abi=hard -mfpu=fpv5-sp-d16") -set(CMAKE_EXE_LINKER_FLAGS_INIT "-specs=nano.specs -specs=nosys.specs -Wl,--print-memory-usage -Wl,--no-warn-rwx-segments") +set(CMAKE_EXE_LINKER_FLAGS_INIT "-specs=nano.specs -specs=nosys.specs -u _printf_float -Wl,--print-memory-usage -Wl,--no-warn-rwx-segments") # Make CMake happy about those compilers set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY") diff --git a/include/FreeRTOSConfig.h b/include/FreeRTOSConfig.h index 63b1989..d82c71f 100644 --- a/include/FreeRTOSConfig.h +++ b/include/FreeRTOSConfig.h @@ -103,7 +103,7 @@ #define INCLUDE_vTaskDelay 1 #define INCLUDE_xTaskGetSchedulerState 1 #define INCLUDE_xTaskGetCurrentTaskHandle 1 -#define INCLUDE_uxTaskGetStackHighWaterMark 0 +#define INCLUDE_uxTaskGetStackHighWaterMark 1 #define INCLUDE_xTaskGetIdleTaskHandle 0 #define INCLUDE_eTaskGetState 0 #define INCLUDE_xTimerPendFunctionCall 1 diff --git a/include/app_mrb_repl.h b/include/app_mrb_repl.h new file mode 100644 index 0000000..63e9151 --- /dev/null +++ b/include/app_mrb_repl.h @@ -0,0 +1,10 @@ +#ifndef APP_MRB_REPL_H +#define APP_MRB_REPL_H + +#include + +int app_mrb_repl_init(void); +int app_mrb_repl_deinit(void); +int app_mrb_repl_exec(bool *exit); + +#endif // APP_MRB_REPL_H diff --git a/lib/linenoise/linenoise.c b/lib/linenoise/linenoise.c index 2244ceb..4c24a44 100644 --- a/lib/linenoise/linenoise.c +++ b/lib/linenoise/linenoise.c @@ -124,7 +124,6 @@ static linenoiseFreeHintsCallback *freeHintsCallback = NULL; static int maskmode = 0; /* Show "***" instead of input. For passwords. */ static int mlmode = 0; /* Multi line mode. Default is single line. */ -static int atexit_registered = 0; /* Register atexit just 1 time. */ static int history_max_len = LINENOISE_DEFAULT_HISTORY_MAX_LEN; static int history_len = 0; static char **history = NULL; @@ -169,8 +168,6 @@ enum KEY_ACTION{ BACKSPACE = 127 /* Backspace */ }; -static void linenoiseAtExit(void); -int linenoiseHistoryAdd(const char *line); static void refreshLine(struct linenoiseState *l); /* Debugging macro. */ @@ -1051,11 +1048,13 @@ static void freeHistory(void) { for (j = 0; j < history_len; j++) free(history[j]); free(history); + + history = NULL; } } /* At exit we'll try to fix the terminal to the initial conditions. */ -static void linenoiseAtExit(void) { +void linenoiseAtExit(void) { freeHistory(); } diff --git a/lib/linenoise/linenoise.h b/lib/linenoise/linenoise.h index 6dfee73..c760ae3 100644 --- a/lib/linenoise/linenoise.h +++ b/lib/linenoise/linenoise.h @@ -67,6 +67,7 @@ void linenoiseSetMultiLine(int ml); void linenoisePrintKeyCodes(void); void linenoiseMaskModeEnable(void); void linenoiseMaskModeDisable(void); +void linenoiseAtExit(void); #ifdef __cplusplus } diff --git a/src/app_mrb_repl.c b/src/app_mrb_repl.c new file mode 100644 index 0000000..d797826 --- /dev/null +++ b/src/app_mrb_repl.c @@ -0,0 +1,85 @@ +#include + +/* FreeRTOS */ +#include "FreeRTOS.h" +#include "task.h" + +/* LN */ +#include "linenoise.h" + +/* mruby */ +#include "mruby.h" +#include "mruby/compile.h" + +/* Private */ +#include "app_mrb_repl.h" + +static mrb_state *mrb; +static mrbc_context *cxt; +static struct mrb_parser_state *parser_state; + +static char *prompt_str; + +#define APP_B_TO_KF(x) ((float)x / 1024.0f) + +static void app_mrb_repl_heap_usage(uint32_t *used, uint32_t *total) { + struct mallinfo m_info = mallinfo(); + + *used = m_info.uordblks; + *total = m_info.fordblks + m_info.uordblks; +} + +int app_mrb_repl_init(void) { + prompt_str = malloc(64); + if (prompt_str == NULL) { + return -1; + } + + mrb = mrb_open(); + cxt = mrbc_context_new(mrb); + + mrb_show_version(mrb); + mrb_show_copyright(mrb); + + char mrb_code[] = "name = 'LPCXpresso55S69'\nputs \"Greetings #{name}, from MRuby #{RUBY_VERSION}.\""; + + parser_state = mrb_parse_string(mrb, mrb_code, cxt); + + mrb_load_exec(mrb, parser_state, cxt); + + return 0; +} + +int app_mrb_repl_deinit(void) { + linenoiseAtExit(); + + free(prompt_str); + + mrbc_cleanup_local_variables(mrb, cxt); + mrbc_context_free(mrb, cxt); + mrb_close(mrb); + + return 0; +} + +int app_mrb_repl_exec(bool *exit) { + char *line; + uint32_t heap_used, heap_total; + + app_mrb_repl_heap_usage(&heap_used, &heap_total); + snprintf(prompt_str, 64, "[%4.02lfkiB/%4.02lfkiB](irb)> ", APP_B_TO_KF(heap_used), APP_B_TO_KF(heap_total)); + + line = linenoise(prompt_str); + + if(line == NULL) { + *exit = true; + return 0; + } + + linenoiseHistoryAdd(line); + printf("You entered: %s\n", line); + free(line); + + *exit = false; + return 0; +} \ No newline at end of file diff --git a/src/app_syscalls.c b/src/app_syscalls.c index 6d37e66..dec230f 100644 --- a/src/app_syscalls.c +++ b/src/app_syscalls.c @@ -170,7 +170,7 @@ int _read(int file, char *ptr, int len) { } int _write(int file, char *buf, int len) { - if (file != STDOUT_FILENO) { + if (file != STDOUT_FILENO && file != STDERR_FILENO) { return 0; } diff --git a/src/main.c b/src/main.c index 97b7593..0337a51 100644 --- a/src/main.c +++ b/src/main.c @@ -1,22 +1,18 @@ +#include + /* Board */ #include "board.h" #include "clock_config.h" #include "peripherals.h" #include "pin_mux.h" -/* mRuby */ -#include "mruby.h" -#include "mruby/compile.h" - /* FreeRTOS */ #include "FreeRTOS.h" #include "task.h" -/* LineNoise */ -#include "linenoise.h" - /* App */ #include "app_syscalls.h" +#include "app_mrb_repl.h" #ifndef APP_LOG_SUCCESSFUL_ALLOC #define APP_LOG_SUCCESSFUL_ALLOC false @@ -33,7 +29,7 @@ int main(void) { goto dead_loop; } - if (xTaskCreate(app_mrb_runtime_task, "MRB_RT", 1536, NULL, 2, NULL) != pdPASS) { + if (xTaskCreate(app_mrb_runtime_task, "MRB_RT", 3072, NULL, 2, NULL) != pdPASS) { goto dead_loop; } @@ -45,72 +41,32 @@ dead_loop: } } -static void app_mrb_alloc_fail_hook(void) { +static void app_mrb_runtime_task(void *parameters) { + bool exit_repl = false; + for (;;) { - __WFI(); - } -} - -static void *app_mrb_allocf(mrb_state *mrb, void *ptr, size_t len, void *user) { - void *res = realloc(ptr, len); - - if (ptr == NULL) { - if (res == NULL) { - printf("[ALLOC] malloc() failed, size: %d\n", len); - app_mrb_alloc_fail_hook(); - } else { -#if APP_LOG_SUCCESSFUL_ALLOC - printf("[ALLOC] malloced %d bytes to ptr %p\n", len, res); -#endif + if(app_mrb_repl_init() != 0){ + printf("Failed to initialize mruby REPL engine.\n"); + goto task_fail; } - } else { - if (len == 0) { -#if APP_LOG_SUCCESSFUL_ALLOC - printf("[ALLOC] freed ptr %p\n", ptr); -#endif - } else { - if (res == NULL) { - printf("[ALLOC] malloc-copy-free failed, orig ptr: %p, new size: %d\n", ptr, len); - app_mrb_alloc_fail_hook(); - } else { -#if APP_LOG_SUCCESSFUL_ALLOC - printf("[ALLOC] malloc-copy-free done, orig ptr: %p, new size: %d, new ptr: %p\n", ptr, len, res); -#endif + + while(!exit_repl) { + if(app_mrb_repl_exec(&exit_repl) != 0) { + printf("REPL execution failed.\n"); + + goto deinit_fail; } } + + if(app_mrb_repl_deinit() != 0) { + printf("Failed to deinitialize murby REPL engine.\n"); + goto task_fail; + } } - return res; -} - -static void app_mrb_runtime_task(void *parameters) { - mrb_state *mrb = mrb_open_allocf(app_mrb_allocf, NULL); - mrbc_context *cxt = mrbc_context_new(mrb); - - mrb_show_version(mrb); - mrb_show_copyright(mrb); - - char mrb_code[] = "name = 'LPCXpresso55S69'\nputs \"Greetings #{name}, from MRuby #{RUBY_VERSION}.\""; - - struct mrb_parser_state *parser_state = mrb_parse_string(mrb, mrb_code, cxt); - - mrb_load_exec(mrb, parser_state, cxt); - - char *line; - - while ((line = linenoise("hello> ")) != NULL) { - linenoiseHistoryAdd(line); - printf("You entered: %s\n", line); - free(line); - } - - printf("REPL thread received ^D, cleaning up...\n"); - - /* User pressed ^D */ - - mrbc_cleanup_local_variables(mrb, cxt); - mrbc_context_free(mrb, cxt); - mrb_close(mrb); +deinit_fail: + app_mrb_repl_deinit(); +task_fail: vTaskDelete(NULL); }