From 46ccf53bab2e30e000630b056e7b447d797da46a Mon Sep 17 00:00:00 2001 From: Yilin Sun Date: Mon, 6 Mar 2023 00:28:25 +0800 Subject: [PATCH] Added basic compiler with FreeRTOS. Signed-off-by: Yilin Sun --- .clang-format | 12 +++ .gitmodules | 3 + CMakeLists.txt | 15 ++- app_flash.ld | 2 +- include/FreeRTOSConfig.h | 167 +++++++++++++++++++++++++++++ include/app_syscalls.h | 6 ++ lib/freertos | 1 + lib/mruby | 2 +- src/app_syscalls.c | 224 +++++++++++++++++++++++++++++++++++++++ src/main.c | 56 +++++++--- 10 files changed, 471 insertions(+), 17 deletions(-) create mode 100644 .clang-format create mode 100644 include/FreeRTOSConfig.h create mode 100644 include/app_syscalls.h create mode 160000 lib/freertos create mode 100644 src/app_syscalls.c diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..f54fc18 --- /dev/null +++ b/.clang-format @@ -0,0 +1,12 @@ +BasedOnStyle: Google +IndentWidth: 4 +AlignConsecutiveMacros: Consecutive +AlignConsecutiveDeclarations: Consecutive +AlignConsecutiveAssignments: AcrossEmptyLinesAndComments +AllowShortFunctionsOnASingleLine: None +BreakBeforeBraces: Custom +BraceWrapping: + AfterEnum: false + AfterStruct: false + SplitEmptyFunction: false +ColumnLimit: 120 \ No newline at end of file diff --git a/.gitmodules b/.gitmodules index 73435ed..b0f9218 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "lib/mruby"] path = lib/mruby url = https://git.minori.work/Embedded_Projects/MRuby_MCUXpresso.git +[submodule "lib/freertos"] + path = lib/freertos + url = https://github.com/FreeRTOS/FreeRTOS-Kernel.git diff --git a/CMakeLists.txt b/CMakeLists.txt index d32a982..865cbc0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,11 +55,13 @@ set(TARGET_SOURCES "SDK/devices/LPC55S69/gcc/startup_LPC55S69_cm33_core0.S" "SDK/devices/LPC55S69/system_LPC55S69_cm33_core0.c" "SDK/devices/LPC55S69/utilities/debug_console/fsl_debug_console.c" + "SDK/devices/LPC55S69/utilities/fsl_sbrk.c" "SDK/devices/LPC55S69/utilities/str/fsl_str.c" "board/board.c" "board/clock_config.c" "board/peripherals.c" "board/pin_mux.c" + "src/app_syscalls.c" "src/main.c" ) @@ -86,6 +88,8 @@ set(TARGET_C_INCLUDES # Shared libraries linked with application set(TARGET_LIBS "mruby_mcux" + "freertos_kernel" + "fro_calib_hardabi" "c" "m" "nosys" @@ -98,9 +102,9 @@ set(TARGET_LIB_DIRECTORIES # Conditional flags # DEBUG -set(CMAKE_C_FLAGS_DEBUG "-DDEBUG -O -g") -set(CMAKE_CXX_FLAGS_DEBUG "-DDEBUG -O -g") -set(CMAKE_ASM_FLAGS_DEBUG "-DDEBUG -O -g") +set(CMAKE_C_FLAGS_DEBUG "-DDEBUG -O0 -g") +set(CMAKE_CXX_FLAGS_DEBUG "-DDEBUG -O0 -g") +set(CMAKE_ASM_FLAGS_DEBUG "-DDEBUG -O0 -g") # RELEASE set(CMAKE_C_FLAGS_RELEASE "-DNDEBUG -O2 -flto") @@ -117,6 +121,11 @@ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") set(MRUBY_MCUX_TARGET "lpc55s69") add_subdirectory(lib/mruby) +set(FREERTOS_PORT "GCC_ARM_CM33_NTZ_NONSECURE" CACHE STRING "") +set(FREERTOS_CONFIG_FILE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include" CACHE STRING "") +set(FREERTOS_HEAP "4" CACHE STRING "") +add_subdirectory(lib/freertos) + # Shared sources, includes and definitions add_compile_definitions(${TARGET_C_DEFINES}) include_directories(${TARGET_C_INCLUDES}) diff --git a/app_flash.ld b/app_flash.ld index 15400e4..68582e7 100644 --- a/app_flash.ld +++ b/app_flash.ld @@ -1,4 +1,4 @@ __stack_size__ = 0x4000; -__heap_size__ = 0x8000; +__heap_size__ = 0x20000; INCLUDE LPC55S69_cm33_core0_flash.ld \ No newline at end of file diff --git a/include/FreeRTOSConfig.h b/include/FreeRTOSConfig.h new file mode 100644 index 0000000..63b1989 --- /dev/null +++ b/include/FreeRTOSConfig.h @@ -0,0 +1,167 @@ +/* + * FreeRTOS Kernel V10.4.3 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +/*----------------------------------------------------------- + * Application specific definitions. + * + * These definitions should be adjusted for your particular hardware and + * application requirements. + * + * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE + * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. + * + * See http://www.freertos.org/a00110.html. + *----------------------------------------------------------*/ + +#define configUSE_PREEMPTION 1 +#define configUSE_TICKLESS_IDLE 0 +#define configCPU_CLOCK_HZ (SystemCoreClock) +#define configTICK_RATE_HZ ((TickType_t)250) +#define configMAX_PRIORITIES 5 +#define configMINIMAL_STACK_SIZE ((unsigned short)90) +#define configMAX_TASK_NAME_LEN 20 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 1 +#define configUSE_TASK_NOTIFICATIONS 1 +#define configUSE_MUTEXES 1 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configUSE_ALTERNATIVE_API 0 /* Deprecated! */ +#define configQUEUE_REGISTRY_SIZE 8 +#define configUSE_QUEUE_SETS 0 +#define configUSE_TIME_SLICING 0 +#define configUSE_NEWLIB_REENTRANT 1 +#define configENABLE_BACKWARD_COMPATIBILITY 0 +#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 5 + +/* Memory allocation related definitions. */ +#define configSUPPORT_STATIC_ALLOCATION 0 +#define configSUPPORT_DYNAMIC_ALLOCATION 1 +#define configTOTAL_HEAP_SIZE ((size_t)(32 * 1024)) +#define configAPPLICATION_ALLOCATED_HEAP 0 + +/* Hook function related definitions. */ +#define configUSE_IDLE_HOOK 0 +#define configUSE_TICK_HOOK 0 +#define configCHECK_FOR_STACK_OVERFLOW 0 +#define configUSE_MALLOC_FAILED_HOOK 0 +#define configUSE_DAEMON_TASK_STARTUP_HOOK 0 + +/* Run time and task stats gathering related definitions. */ +#define configGENERATE_RUN_TIME_STATS 0 +#define configUSE_TRACE_FACILITY 1 +#define configUSE_STATS_FORMATTING_FUNCTIONS 0 + +/* Task aware debugging. */ +#define configRECORD_STACK_HIGH_ADDRESS 1 + +/* Co-routine related definitions. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES 2 + +/* Software timer related definitions. */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES - 1) +#define configTIMER_QUEUE_LENGTH 10 +#define configTIMER_TASK_STACK_DEPTH (configMINIMAL_STACK_SIZE * 2) + +/* Define to trap errors during development. */ +#define configASSERT(x) if(( x) == 0) {taskDISABLE_INTERRUPTS(); for (;;);} + +/* Optional functions - most linkers will remove unused functions anyway. */ +#define INCLUDE_vTaskPrioritySet 1 +#define INCLUDE_uxTaskPriorityGet 1 +#define INCLUDE_vTaskDelete 1 +#define INCLUDE_vTaskSuspend 1 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_xTaskGetSchedulerState 1 +#define INCLUDE_xTaskGetCurrentTaskHandle 1 +#define INCLUDE_uxTaskGetStackHighWaterMark 0 +#define INCLUDE_xTaskGetIdleTaskHandle 0 +#define INCLUDE_eTaskGetState 0 +#define INCLUDE_xTimerPendFunctionCall 1 +#define INCLUDE_xTaskAbortDelay 0 +#define INCLUDE_xTaskGetHandle 0 +#define INCLUDE_xTaskResumeFromISR 1 + + + +#if defined(__ICCARM__)||defined(__CC_ARM)||defined(__GNUC__) +/* Clock manager provides in this variable system core clock frequency */ +#include +extern uint32_t SystemCoreClock; +#endif + + +#ifndef configENABLE_FPU +#define configENABLE_FPU 1 +#endif +#ifndef configENABLE_MPU +#define configENABLE_MPU 0 +#endif +#ifndef configENABLE_TRUSTZONE +#define configENABLE_TRUSTZONE 0 +#endif +#ifndef configRUN_FREERTOS_SECURE_ONLY +#define configRUN_FREERTOS_SECURE_ONLY 1 +#endif + +/* Interrupt nesting behaviour configuration. Cortex-M specific. */ +#ifdef __NVIC_PRIO_BITS +/* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */ +#define configPRIO_BITS __NVIC_PRIO_BITS +#else +#define configPRIO_BITS 3 /* 8 priority levels */ +#endif + +/* The lowest interrupt priority that can be used in a call to a "set priority" +function. */ +#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1U << (configPRIO_BITS)) - 1) + +/* The highest interrupt priority that can be used by any interrupt service +routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL +INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER +PRIORITY THAN THIS! (higher priorities are lower numeric values. */ +#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 2 + +/* Interrupt priorities used by the kernel port layer itself. These are generic +to all Cortex-M ports, and do not rely on any particular library functions. */ +#define configKERNEL_INTERRUPT_PRIORITY (configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS)) +/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!! +See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */ +#define configMAX_SYSCALL_INTERRUPT_PRIORITY (configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS)) + +/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS +standard names. */ +#define vPortSVCHandler SVC_Handler +#define vPortPendSVHandler PendSV_Handler +#define vPortSysTickHandler SysTick_Handler + +#endif /* FREERTOS_CONFIG_H */ diff --git a/include/app_syscalls.h b/include/app_syscalls.h new file mode 100644 index 0000000..905d9ff --- /dev/null +++ b/include/app_syscalls.h @@ -0,0 +1,6 @@ +#ifndef APP_SYSCALLS_H +#define APP_SYSCALLS_H + +int app_syscalls_init(void); + +#endif //APP_SYSCALLS_H diff --git a/lib/freertos b/lib/freertos new file mode 160000 index 0000000..def7d2d --- /dev/null +++ b/lib/freertos @@ -0,0 +1 @@ +Subproject commit def7d2df2b0506d3d249334974f51e427c17a41c diff --git a/lib/mruby b/lib/mruby index d31acdb..05ebbc3 160000 --- a/lib/mruby +++ b/lib/mruby @@ -1 +1 @@ -Subproject commit d31acdb6fa8e857bb6de4a0bbb630c14dac25e00 +Subproject commit 05ebbc3a9baec28ed4acfe4b84495d272c74456a diff --git a/src/app_syscalls.c b/src/app_syscalls.c new file mode 100644 index 0000000..7d80985 --- /dev/null +++ b/src/app_syscalls.c @@ -0,0 +1,224 @@ +#include +#include +#include +#include + +/* Board */ +#include "pin_mux.h" + +/* SDK drivers */ +#include "fsl_usart.h" + +/* FreeRTOS */ +#include "FreeRTOS.h" +#include "event_groups.h" +#include "semphr.h" +#include "task.h" + +#define APP_STDIO_UART_ID 0 +#define APP_STDIO_UART_INSTANCE USART0 +#define APP_STDIO_UART_CLOCK_ATTACH kFRO12M_to_FLEXCOMM0 +#define APP_STDIO_UART_TX_FIFO_SIZE 16 +#define APP_STDIO_UART_RX_FIFO_SIZE 16 +#define APP_STDIO_UART_TX_BEAT_SIZE (APP_STDIO_UART_TX_FIFO_SIZE - 1) +#define APP_STDIO_UART_RX_BEAT_SIZE (APP_STDIO_UART_RX_FIFO_SIZE - 4) /* Save room for delayed reception */ + +#define APP_STDIO_UART_IRQ_NR FLEXCOMM0_IRQn +#define APP_STDIO_UART_IRQ_PRIO (configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY + 1) +#define APP_STDIO_UART_IRQ_HANDLER FLEXCOMM0_IRQHandler + +#define APP_STDIO_UART_EVENT_TX_DONE (1 << 0U) +#define APP_STDIO_UART_EVENT_RX_DONE (1 << 1U) +#define APP_STDIO_UART_EVENT_ERROR (1 << 2U) + +static SemaphoreHandle_t s_malloc_lock = NULL; + +static SemaphoreHandle_t s_stdio_tx_lock = NULL; +static SemaphoreHandle_t s_stdio_rx_lock = NULL; +static EventGroupHandle_t s_stdio_event = NULL; + +/* ========== Internal Use Functions ========== */ +static int app_stdio_init(void) { + int ret = 0; + + s_stdio_tx_lock = xSemaphoreCreateMutex(); + if (s_stdio_tx_lock == NULL) { + return -1; + } + + s_stdio_rx_lock = xSemaphoreCreateMutex(); + if (s_stdio_rx_lock == NULL) { + ret = -1; + goto free_tx_sem_exit; + } + + s_stdio_event = xEventGroupCreate(); + if (s_stdio_event == NULL) { + ret = -1; + goto free_rx_sem_exit; + } + + CLOCK_AttachClk(APP_STDIO_UART_CLOCK_ATTACH); + + usart_config_t usart_config; + USART_GetDefaultConfig(&usart_config); + + usart_config.baudRate_Bps = 115200U; + usart_config.txWatermark = 0U; + usart_config.rxWatermark = APP_STDIO_UART_RX_BEAT_SIZE; + usart_config.enableTx = true; + usart_config.enableRx = true; + usart_config.bitCountPerChar = kUSART_8BitsPerChar; + usart_config.stopBitCount = kUSART_OneStopBit; + usart_config.parityMode = kUSART_ParityDisabled; + + uint32_t stdio_fc_clk_freq = CLOCK_GetFlexCommClkFreq(APP_STDIO_UART_ID); + if (USART_Init(APP_STDIO_UART_INSTANCE, &usart_config, stdio_fc_clk_freq) != kStatus_Success) { + ret = -1; + goto free_event_exit; + } + + USART_SetTxFifoWatermark(APP_STDIO_UART_INSTANCE, 0); /* Has to be set to 0 to detect TX done condition */ + USART_SetRxFifoWatermark(APP_STDIO_UART_INSTANCE, APP_STDIO_UART_RX_BEAT_SIZE); /* Might be adjusted on-the-fly */ + + NVIC_SetPriority(APP_STDIO_UART_IRQ_NR, APP_STDIO_UART_IRQ_PRIO); + EnableIRQ(APP_STDIO_UART_IRQ_NR); + + return ret; + +free_event_exit: + vEventGroupDelete(s_stdio_event); + +free_rx_sem_exit: + vSemaphoreDelete(s_stdio_rx_lock); + +free_tx_sem_exit: + vSemaphoreDelete(s_stdio_tx_lock); + + return ret; +} + +void APP_STDIO_UART_IRQ_HANDLER(void) { + uint32_t event_flag = 0UL; + + uint32_t interrupts_enabled = USART_GetEnabledInterrupts(APP_STDIO_UART_INSTANCE); + uint32_t fifo_int_status = APP_STDIO_UART_INSTANCE->FIFOINTSTAT; + + USART_ClearStatusFlags(APP_STDIO_UART_INSTANCE, kUSART_AllClearFlags); + + if ((interrupts_enabled & kUSART_TxLevelInterruptEnable) && (fifo_int_status & USART_FIFOINTSTAT_TXLVL_MASK)) { + USART_DisableInterrupts(APP_STDIO_UART_INSTANCE, kUSART_TxLevelInterruptEnable); + event_flag |= APP_STDIO_UART_EVENT_TX_DONE; + } + + if ((interrupts_enabled & kUSART_RxLevelInterruptEnable) && (fifo_int_status & USART_FIFOINTSTAT_RXLVL_MASK)) { + USART_DisableInterrupts(APP_STDIO_UART_INSTANCE, kUSART_RxLevelInterruptEnable); + event_flag |= APP_STDIO_UART_EVENT_RX_DONE; + } + + BaseType_t higher_prio_task_woken = pdFALSE; + + xEventGroupSetBitsFromISR(s_stdio_event, event_flag, &higher_prio_task_woken); + portYIELD_FROM_ISR(higher_prio_task_woken); +} + +int app_syscalls_init(void) { + s_malloc_lock = xSemaphoreCreateRecursiveMutex(); + if (s_malloc_lock == NULL) { + return -1; + } + + if (app_stdio_init() != 0) { + return -2; + } + + return 0; +} + +void __malloc_lock(struct _reent *reent) { + xSemaphoreTakeRecursive(s_malloc_lock, portMAX_DELAY); +} + +void __malloc_unlock(struct _reent *reent) { + xSemaphoreGiveRecursive(s_malloc_lock); +} + +int _read(int file, char *ptr, int len) { + xSemaphoreTake(s_stdio_rx_lock, portMAX_DELAY); + + xSemaphoreGive(s_stdio_rx_lock); + return 0; +} + +int _write(int file, char *buf, int len) { + xSemaphoreTake(s_stdio_tx_lock, portMAX_DELAY); + + int xfer_count = len / APP_STDIO_UART_TX_BEAT_SIZE; + int bytes_remaining = len % APP_STDIO_UART_TX_BEAT_SIZE; + if (bytes_remaining) { + xfer_count++; + } + + for (int i = 0; i < xfer_count; i++) { + uint32_t tx_bytes = APP_STDIO_UART_TX_BEAT_SIZE; + + if (i == xfer_count - 1) { + if (bytes_remaining) { + tx_bytes = bytes_remaining; + } + } + + /* Hold TX operation before enabling level interrupt, otherwise a level interrupt will fire instantly */ + APP_STDIO_UART_INSTANCE->CTL |= USART_CTL_TXDIS_MASK; + + /* Fill FIFO */ + for (uint32_t j = 0; j < tx_bytes; j++) { + USART_WriteByte(APP_STDIO_UART_INSTANCE, buf[i * APP_STDIO_UART_TX_BEAT_SIZE + j]); + } + + USART_EnableInterrupts(APP_STDIO_UART_INSTANCE, kUSART_TxLevelInterruptEnable); + + /* Begin TX transfer */ + APP_STDIO_UART_INSTANCE->CTL &= ~(USART_CTL_TXDIS_MASK); + + /* Wait for TX complete */ + xEventGroupWaitBits(s_stdio_event, APP_STDIO_UART_EVENT_TX_DONE, pdTRUE, pdFALSE, portMAX_DELAY); + } + + xSemaphoreGive(s_stdio_tx_lock); + + return len; +} + +int _close(int file) { + errno = -EBADF; + return -1; +} + +int _fstat(int file, struct stat *st) { + if ((STDOUT_FILENO == file) || (STDERR_FILENO == file)) { + st->st_mode = S_IFCHR; + return 0; + } else { + errno = EBADF; + return -1; + } +} + +int _getpid() { + return 1; +} + +int _isatty(int file) { + return 1; +} + +int _kill(int pid, int sig) { + errno = -EINVAL; + + return -1; +} + +int _lseek(int file, int offset, int whence) { + return 0; +} \ No newline at end of file diff --git a/src/main.c b/src/main.c index 3358c51..7433742 100644 --- a/src/main.c +++ b/src/main.c @@ -1,32 +1,64 @@ -#include - +/* Board */ #include "board.h" #include "clock_config.h" #include "peripherals.h" #include "pin_mux.h" -#include "fsl_debug_console.h" - +/* mRuby */ #include "mruby.h" #include "mruby/compile.h" +/* FreeRTOS */ +#include "FreeRTOS.h" +#include "task.h" + +/* App */ +#include "app_syscalls.h" + +static void app_mrb_runtime_task(void *parameters); + int main(void) { BOARD_InitBootPins(); - BOARD_BootClockFROHF96M(); + BOARD_InitBootClocks(); BOARD_InitBootPeripherals(); - BOARD_InitDebugConsole(); + if (app_syscalls_init() != 0) { + goto dead_loop; + } - mrb_state* mrb = mrb_open(); + if (xTaskCreate(app_mrb_runtime_task, "MRB_RT", 1536, NULL, 2, NULL) != pdPASS) { + goto dead_loop; + } + + vTaskStartScheduler(); + +dead_loop: + for (;;) { + __WFI(); + } +} + +static void app_mrb_runtime_task(void *parameters) { + mrb_state *mrb = mrb_open(); mrbc_context *cxt = mrbc_context_new(mrb); - PRINTF("MRuby Version: %s\r\n", MRUBY_RUBY_VERSION); + 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); + + for (;;) { + /* Wait for REPL commands */ + vTaskDelay(pdMS_TO_TICKS(500)); + } mrbc_cleanup_local_variables(mrb, cxt); mrbc_context_free(mrb, cxt); mrb_close(mrb); - for(;;) { - __WFI(); - } -} \ No newline at end of file + vTaskDelete(NULL); +}