Fixed LN de-init and re-init, added testing REPL.

Signed-off-by: Yilin Sun <imi415@imi.moe>
This commit is contained in:
Yilin Sun 2023-03-07 23:23:01 +08:00
parent d4f9291ad1
commit af888fb6dd
Signed by: imi415
GPG Key ID: 17F01E106F9F5E0A
10 changed files with 128 additions and 76 deletions

View File

@ -2,7 +2,7 @@ BasedOnStyle: Google
IndentWidth: 4
AlignConsecutiveMacros: Consecutive
AlignConsecutiveDeclarations: Consecutive
AlignConsecutiveAssignments: AcrossEmptyLinesAndComments
AlignConsecutiveAssignments: Consecutive
AllowShortFunctionsOnASingleLine: None
BreakBeforeBraces: Custom
BraceWrapping:

View File

@ -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"
)

View File

@ -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")

View File

@ -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

10
include/app_mrb_repl.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef APP_MRB_REPL_H
#define APP_MRB_REPL_H
#include <stdbool.h>
int app_mrb_repl_init(void);
int app_mrb_repl_deinit(void);
int app_mrb_repl_exec(bool *exit);
#endif // APP_MRB_REPL_H

View File

@ -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();
}

View File

@ -67,6 +67,7 @@ void linenoiseSetMultiLine(int ml);
void linenoisePrintKeyCodes(void);
void linenoiseMaskModeEnable(void);
void linenoiseMaskModeDisable(void);
void linenoiseAtExit(void);
#ifdef __cplusplus
}

85
src/app_mrb_repl.c Normal file
View File

@ -0,0 +1,85 @@
#include <malloc.h>
/* 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;
}

View File

@ -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;
}

View File

@ -1,22 +1,18 @@
#include <stdio.h>
/* 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);
}