Files
TencentOS-tiny/components/language/micropython/port/mpmain.c
2022-09-29 12:10:37 +08:00

232 lines
6.3 KiB
C

/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2022 KY-zhang-X
*
* 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.
*/
#include "py/mpconfig.h"
#include "py/mphal.h"
#include "py/mpthread.h"
#include "py/compile.h"
#include "py/gc.h"
#include "py/mperrno.h"
#include "py/stackctrl.h"
#include "py/builtin.h"
#include "shared/runtime/gchelper.h"
#include "shared/runtime/pyexec.h"
#include "modmachine.h"
#if MICROPY_PY_NETWORK
#include "extmod/modnetwork.h"
#endif
#if MICROPY_VFS_TOS
#include "extmod/vfs.h"
#include "vfs_tos.h"
#endif
#include "tos_k.h"
#define MP_HEAP_SIZE (8 * 1024)
// MicroPython GC heap
STATIC char *heap = NULL;
STATIC void *stack_top = NULL;
STATIC mp_obj_t uart_repl_obj;
int mp_main(void)
{
// Initialise the MicroPython runtime
// mp_stack_ctrl_init();
volatile int stack_dummy;
#if MICROPY_PY_THREAD
mp_thread_init();
#endif
stack_top = (void *)&stack_dummy;
#ifdef MICROPY_HW_UART_REPL
{
mp_obj_t args[7] = {
MP_OBJ_NEW_SMALL_INT(MICROPY_HW_UART_REPL),
MP_OBJ_NEW_QSTR(MP_QSTR_rxbuf), MP_OBJ_NEW_SMALL_INT(512),
MP_OBJ_NEW_QSTR(MP_QSTR_timeout), MP_OBJ_NEW_SMALL_INT(0),
MP_OBJ_NEW_QSTR(MP_QSTR_timeout_char), MP_OBJ_NEW_SMALL_INT(2),
};
uart_repl_obj = machine_uart_type.make_new(&machine_uart_type, 1, 3, args);
machine_uart_attach_to_repl(MP_OBJ_TO_PTR(uart_repl_obj), 1);
}
#endif /* MICROPY_HW_UART_REPL */
soft_reset:
mp_stack_set_top(stack_top);
mp_stack_set_limit(tos_task_curr_task_get()->stk_size - MP_THREAD_STACK_LIMIT_MARGIN);
if (!heap) {
heap = (char *)tos_mmheap_alloc(MP_HEAP_SIZE);
if (!heap) {
return -1;
}
}
gc_init(heap, heap + MP_HEAP_SIZE);
mp_init();
#ifdef MICROPY_HW_UART_REPL
MP_STATE_PORT(stdio_uart) = MP_OBJ_TO_PTR(uart_repl_obj);
#endif /* MICROPY_HW_UART_REPL */
#if MICROPY_VFS_TOS
{
mp_obj_t root = mp_obj_new_str("/fs", 3);
mp_obj_t args[2] = {
mp_type_vfs_tos.make_new(&mp_type_vfs_tos, 1, 0, &root),
MP_OBJ_NEW_QSTR(MP_QSTR__slash_),
};
mp_vfs_mount(2, args, (mp_map_t *)&mp_const_empty_map);
MP_STATE_VM(vfs_cur) = MP_STATE_VM(vfs_mount_table);
}
#endif
#if MICROPY_PY_MACHINE
machine_pins_init();
#endif /* MICROPY_PY_MACHINE */
#if MICROPY_PY_NETWORK
mod_network_init();
#endif
// run boot-up scripts
// pyexec_frozen_module("_boot.py");
pyexec_file_if_exists("boot.py");
if (pyexec_mode_kind == PYEXEC_MODE_FRIENDLY_REPL) {
int ret = pyexec_file_if_exists("main.py");
if (ret & PYEXEC_FORCED_EXIT) {
goto soft_reset_exit;
}
}
// start a normal REPL; will exit when ctrl-D is entered on a blank line.
for (;;) {
if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) {
if (pyexec_raw_repl() != 0) {
break;
}
} else {
if (pyexec_friendly_repl() != 0) {
break;
}
}
}
soft_reset_exit:
#if MICROPY_PY_MACHINE
machine_timer_deinit_all();
#endif
#if MICROPY_PY_THREAD
mp_thread_deinit();
#endif
// Deinitialise the runtime.
gc_sweep_all();
mp_hal_stdout_tx_str("MPY: soft reboot\r\n");
mp_deinit();
goto soft_reset;
}
// Handle uncaught exceptions (should never be reached in a correct C implemetation).
void nlr_jump_fail(void *val) {
printf("FATAL: uncaught exception %p\n", val);
mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(val));
for (;;) {
}
}
// Do a garbage collection cycle
void gc_collect(void) {
gc_collect_start();
uintptr_t stack_base = (uint32_t)tos_task_curr_task_get()->stk_base;
gc_collect_root((void **)stack_base, ((uintptr_t)MP_STATE_THREAD(stack_top) - (uintptr_t)stack_base) / sizeof(uintptr_t));
#if MICROPY_PY_THREAD
// trace root pointers from any threads
mp_thread_gc_others();
#endif
gc_collect_end();
// gc_dump_info();
}
#if !(MICROPY_VFS)
// There is no filesystem so stating returns noting
mp_import_stat_t mp_import_stat(const char *path) {
return MP_IMPORT_STAT_NO_EXIST;
}
#endif /* MICROPY_VFS */
#if !(MICROPY_READER_VFS)
mp_lexer_t *mp_lexer_new_from_file(const char *filename) {
mp_raise_OSError(MP_ENOENT);
}
#endif
#ifndef NDEBUG
#if defined(__CC_ARM)
void __aeabi_assert(const char *expr, const char *file, int line) {
printf("Assertion '%s' failed, at file %s:%d\n", expr, file, line);
for (;;) {
}
}
#endif
NORETURN void MP_WEAK __assert_func(const char *file, int line, const char *func, const char *expr) {
(void)func;
printf("Assertion '%s' failed, at file %s:%d\n", expr, file, line);
mp_raise_msg(&mp_type_AssertionError, MP_ERROR_TEXT("C-level assert"));
}
#endif
#if MICROPY_DEBUG_VERBOSE
#include <stdio.h>
#include <stdarg.h>
int DEBUG_printf(const char *format, ...)
{
static char log_buf[512];
va_list args;
/* args point to the first variable parameter */
va_start(args, format);
/* must use vprintf to print */
vsprintf(log_buf, format, args);
printf("%s", log_buf);
va_end(args);
return 0;
}
#endif