Merge pull request #2029 from openmv/refactor_boot_script_code

ports/all: Refactor common boot code.
This commit is contained in:
Ibrahim Abdelkader 2023-11-29 18:34:22 +02:00 committed by GitHub
commit 1e454f4022
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 226 additions and 311 deletions

View File

@ -17,16 +17,16 @@ SRCS += $(addprefix alloc/, \
SRCS += $(addprefix common/, \ SRCS += $(addprefix common/, \
array.c \ array.c \
file_utils.c \
ini.c \ ini.c \
ringbuf.c \ ringbuf.c \
trace.c \ trace.c \
mutex.c \ mutex.c \
vospi.c \
usbdbg.c \ usbdbg.c \
tinyusb_debug.c \ tinyusb_debug.c \
file_utils.c \
boot_utils.c \
sensor_utils.c \ sensor_utils.c \
factoryreset.c \
vospi.c \
) )
SRCS += $(addprefix sensors/, \ SRCS += $(addprefix sensors/, \

View File

@ -15,8 +15,7 @@
//#define IMLIB_ENABLE_IMAGE_IO //#define IMLIB_ENABLE_IMAGE_IO
// Enable Image File I/O // Enable Image File I/O
// Not filesystem yet #define IMLIB_ENABLE_IMAGE_FILE_IO
//#define IMLIB_ENABLE_IMAGE_FILE_IO
// Enable LAB LUT // Enable LAB LUT
//#define IMLIB_ENABLE_LAB_LUT //#define IMLIB_ENABLE_LAB_LUT

View File

@ -1,34 +1,38 @@
/* /*
* This file is part of the OpenMV project. * This file is part of the OpenMV project.
* *
* Copyright (c) 2013-2022 Ibrahim Abdelkader <iabdalkader@openmv.io> * Copyright (c) 2013-2023 Ibrahim Abdelkader <iabdalkader@openmv.io>
* Copyright (c) 2013-2022 Kwabena W. Agyeman <kwagyeman@openmv.io> * Copyright (c) 2013-2023 Kwabena W. Agyeman <kwagyeman@openmv.io>
* *
* This work is licensed under the MIT license, see the file LICENSE for details. * This work is licensed under the MIT license, see the file LICENSE for details.
* *
* Factory reset util functions. * Boot util functions.
*/ */
#include <stdio.h> #include <stdio.h>
#include "py/runtime.h" #include "py/runtime.h"
#include "py/mperrno.h" #include "py/mperrno.h"
#include "py/mphal.h" #include "py/mphal.h"
#include "omv_boardconfig.h" #include "py/objstr.h"
#include "shared/runtime/pyexec.h"
#if MICROPY_HW_USB_MSC #if MICROPY_HW_USB_MSC
#include "extmod/vfs.h" #include "extmod/vfs.h"
#include "extmod/vfs_fat.h" #include "extmod/vfs_fat.h"
#include "common/factoryreset.h"
// Fresh filesystem templates. // Fresh filesystem templates.
#include "main_py.h" #include "main_py.h"
#include "readme_txt.h" #include "readme_txt.h"
#if (OMV_ENABLE_SELFTEST == 1)
#include "selftest_py.h"
#endif #endif
#include "omv_boardconfig.h"
#include "usbdbg.h"
#if OMV_ENABLE_WIFIDBG
#include "wifidbg.h"
#endif
#include "file_utils.h"
#include "boot_utils.h"
#if MICROPY_VFS_FAT
extern void __fatal_error(); extern void __fatal_error();
int factoryreset_create_filesystem(fs_user_mount_t *vfs) { int bootutils_init_filesystem(fs_user_mount_t *vfs) {
FIL fp; UINT n; FIL fp; UINT n;
uint8_t working_buf[FF_MAX_SS]; uint8_t working_buf[FF_MAX_SS];
if (f_mkfs(&vfs->fatfs, FM_FAT, 0, working_buf, sizeof(working_buf)) != FR_OK) { if (f_mkfs(&vfs->fatfs, FM_FAT, 0, working_buf, sizeof(working_buf)) != FR_OK) {
@ -51,13 +55,41 @@ int factoryreset_create_filesystem(fs_user_mount_t *vfs) {
f_write(&fp, fresh_readme_txt, sizeof(fresh_readme_txt) - 1 /* don't count null terminator */, &n); f_write(&fp, fresh_readme_txt, sizeof(fresh_readme_txt) - 1 /* don't count null terminator */, &n);
f_close(&fp); f_close(&fp);
#if (OMV_ENABLE_SELFTEST == 1)
// Create default selftest.py
f_open(&vfs->fatfs, &fp, "/selftest.py", FA_WRITE | FA_CREATE_ALWAYS);
f_write(&fp, fresh_selftest_py, sizeof(fresh_selftest_py) - 1 /* don't count null terminator */, &n);
f_close(&fp);
#endif
return 0; return 0;
} }
#endif #endif
bool bootutils_exec_bootscript(const char *path, bool interruptible, bool wifidbg_enabled) {
nlr_buf_t nlr;
bool interrupted = false;
if (nlr_push(&nlr) == 0) {
// Enable IDE interrupts if allowed.
if (interruptible) {
usbdbg_set_irq_enabled(true);
usbdbg_set_script_running(true);
#if OMV_ENABLE_WIFIDBG
wifidbg_set_irq_enabled(wifidbg_enabled);
#endif
}
// Parse, compile and execute the script.
pyexec_file_if_exists(path, true);
nlr_pop();
} else {
interrupted = true;
}
// Disable IDE interrupts
usbdbg_set_irq_enabled(false);
usbdbg_set_script_running(false);
#if OMV_ENABLE_WIFIDBG
wifidbg_set_irq_enabled(false);
#endif
if (interrupted) {
mp_obj_print_exception(&mp_plat_print, (mp_obj_t) nlr.ret_val);
}
return interrupted;
}

View File

@ -0,0 +1,16 @@
/*
* This file is part of the OpenMV project.
*
* Copyright (c) 2013-2023 Ibrahim Abdelkader <iabdalkader@openmv.io>
* Copyright (c) 2013-2023 Kwabena W. Agyeman <kwagyeman@openmv.io>
*
* This work is licensed under the MIT license, see the file LICENSE for details.
*
* Boot util functions.
*/
#ifndef __BOOT_UTILS_H__
#define __BOOT_UTILS_H__
typedef struct _fs_user_mount_t fs_user_mount_t;
int bootutils_init_filesystem(fs_user_mount_t *vfs);
bool bootutils_exec_bootscript(const char *path, bool interruptible, bool wifidbg_enabled);
#endif // __BOOT_UTILS_H__

View File

@ -1,14 +0,0 @@
/*
* This file is part of the OpenMV project.
*
* Copyright (c) 2013-2022 Ibrahim Abdelkader <iabdalkader@openmv.io>
* Copyright (c) 2013-2022 Kwabena W. Agyeman <kwagyeman@openmv.io>
*
* This work is licensed under the MIT license, see the file LICENSE for details.
*
* Factory reset util functions.
*/
#ifndef __FACTORY_RESET_H__
#define __FACTORY_RESET_H__
int factoryreset_create_filesystem(fs_user_mount_t *vfs);
#endif /* __FACTORY_RESET_H__ */

View File

@ -50,7 +50,6 @@
#include "extmod/vfs.h" #include "extmod/vfs.h"
#include "extmod/vfs_fat.h" #include "extmod/vfs_fat.h"
#include "common/factoryreset.h"
#include "omv_boardconfig.h" #include "omv_boardconfig.h"
#include "framebuffer.h" #include "framebuffer.h"
@ -60,36 +59,11 @@
#include "fb_alloc.h" #include "fb_alloc.h"
#include "dma_alloc.h" #include "dma_alloc.h"
#include "file_utils.h" #include "file_utils.h"
#include "boot_utils.h"
#include "mimxrt_hal.h" #include "mimxrt_hal.h"
extern uint8_t _sstack, _estack, _heap_start, _heap_end; extern uint8_t _sstack, _estack, _heap_start, _heap_end;
void exec_boot_script(const char *path, bool interruptible) {
nlr_buf_t nlr;
bool interrupted = false;
if (nlr_push(&nlr) == 0) {
// Enable IDE interrupts if allowed.
if (interruptible) {
usbdbg_set_irq_enabled(true);
usbdbg_set_script_running(true);
}
// Parse, compile and execute the script.
pyexec_file_if_exists(path, true);
nlr_pop();
} else {
interrupted = true;
}
// Disable IDE interrupts
usbdbg_set_irq_enabled(false);
usbdbg_set_script_running(false);
if (interrupted) {
mp_obj_print_exception(&mp_plat_print, (mp_obj_t) nlr.ret_val);
}
}
int main(void) { int main(void) {
bool sdcard_detected = false; bool sdcard_detected = false;
bool sdcard_mounted = false; bool sdcard_mounted = false;
@ -101,9 +75,7 @@ int main(void) {
pendsv_init(); pendsv_init();
soft_reset: soft_reset:
#if defined(MICROPY_HW_LED1)
led_init(); led_init();
#endif
// Initialise stack extents and GC heap. // Initialise stack extents and GC heap.
mp_stack_set_top(&_estack); mp_stack_set_top(&_estack);
@ -178,9 +150,8 @@ soft_reset:
#endif #endif
#if MICROPY_PY_SENSOR #if MICROPY_PY_SENSOR
if (first_soft_reset if (first_soft_reset) {
&& sensor_init() != 0) { sensor_init();
printf("sensor init failed!\n");
} }
#endif #endif
@ -211,7 +182,7 @@ soft_reset:
} else { } else {
// Create a fresh filesystem. // Create a fresh filesystem.
fs_user_mount_t *vfs = MP_OBJ_TYPE_GET_SLOT(&mp_fat_vfs_type, make_new) (&mp_fat_vfs_type, 1, 0, &bdev); fs_user_mount_t *vfs = MP_OBJ_TYPE_GET_SLOT(&mp_fat_vfs_type, make_new) (&mp_fat_vfs_type, 1, 0, &bdev);
if (factoryreset_create_filesystem(vfs) == 0) { if (bootutils_init_filesystem(vfs) == 0) {
if (mp_vfs_mount_and_chdir_protected(bdev, mount_point) == 0) { if (mp_vfs_mount_and_chdir_protected(bdev, mount_point) == 0) {
mimxrt_msc_medium = &mimxrt_flash_type; mimxrt_msc_medium = &mimxrt_flash_type;
} }
@ -219,19 +190,21 @@ soft_reset:
} }
} }
// Deferred tusb_init to allow the filesystem to be mounted/created before MSC. // Mark the filesystem as an OpenMV storage.
file_ll_touch(".openmv_disk");
// Initialize TinyUSB after the filesystem is mounted.
if (!tusb_inited()) { if (!tusb_inited()) {
tusb_init(); tusb_init();
} }
// Mark FS as OpenMV disk. // Run boot.py script.
file_ll_touch(".openmv_disk"); bool interrupted = bootutils_exec_bootscript("boot.py", true, false);
// Execute user scripts. // Run main.py script on first soft-reset.
exec_boot_script("boot.py", false); if (first_soft_reset && !interrupted && mp_vfs_import_stat("main.py")) {
bootutils_exec_bootscript("main.py", true, false);
if (first_soft_reset) { goto soft_reset_exit;
exec_boot_script("main.py", true);
} }
// If there's no script ready, just re-exec REPL // If there's no script ready, just re-exec REPL
@ -279,6 +252,7 @@ soft_reset:
} }
} }
soft_reset_exit:
mp_printf(MP_PYTHON_PRINTER, "MPY: soft reboot\n"); mp_printf(MP_PYTHON_PRINTER, "MPY: soft reboot\n");
machine_pin_irq_deinit(); machine_pin_irq_deinit();
machine_rtc_irq_deinit(); machine_rtc_irq_deinit();
@ -300,7 +274,6 @@ soft_reset:
mp_deinit(); mp_deinit();
first_soft_reset = false; first_soft_reset = false;
goto soft_reset; goto soft_reset;
return 0;
} }
void gc_collect(void) { void gc_collect(void) {

View File

@ -41,6 +41,7 @@ MPY_CFLAGS += -I$(TOP_DIR)/$(MICROPY_DIR)/lib/lwip/src/include/
MPY_CFLAGS += -I$(TOP_DIR)/$(MICROPY_DIR)/ports/mimxrt/ MPY_CFLAGS += -I$(TOP_DIR)/$(MICROPY_DIR)/ports/mimxrt/
MPY_CFLAGS += -I$(TOP_DIR)/$(MICROPY_DIR)/ports/mimxrt/lwip_inc/ MPY_CFLAGS += -I$(TOP_DIR)/$(MICROPY_DIR)/ports/mimxrt/lwip_inc/
MPY_CFLAGS += -I$(TOP_DIR)/$(MICROPY_DIR)/shared/runtime/ MPY_CFLAGS += -I$(TOP_DIR)/$(MICROPY_DIR)/shared/runtime/
MPY_CFLAGS += -DMICROPY_VFS_FAT=1
ifeq ($(MICROPY_PY_LWIP), 0) ifeq ($(MICROPY_PY_LWIP), 0)
MICROPY_ARGS += MICROPY_PY_LWIP=0 MICROPY_PY_USSL=0 MICROPY_ARGS += MICROPY_PY_LWIP=0 MICROPY_PY_USSL=0
@ -127,7 +128,6 @@ FIRM_OBJ += $(addprefix $(BUILD)/$(OMV_DIR)/alloc/, \
FIRM_OBJ += $(addprefix $(BUILD)/$(OMV_DIR)/common/, \ FIRM_OBJ += $(addprefix $(BUILD)/$(OMV_DIR)/common/, \
array.o \ array.o \
file_utils.o \
ini.o \ ini.o \
ringbuf.o \ ringbuf.o \
trace.o \ trace.o \
@ -135,8 +135,9 @@ FIRM_OBJ += $(addprefix $(BUILD)/$(OMV_DIR)/common/, \
vospi.o \ vospi.o \
usbdbg.o \ usbdbg.o \
tinyusb_debug.o \ tinyusb_debug.o \
file_utils.o \
boot_utils.o \
sensor_utils.o \ sensor_utils.o \
factoryreset.o \
) )
FIRM_OBJ += $(addprefix $(BUILD)/$(OMV_DIR)/sensors/, \ FIRM_OBJ += $(addprefix $(BUILD)/$(OMV_DIR)/sensors/, \

View File

@ -90,6 +90,7 @@
#include "omv_boardconfig.h" #include "omv_boardconfig.h"
#include "omv_i2c.h" #include "omv_i2c.h"
#include "sensor.h" #include "sensor.h"
#include "boot_utils.h"
uint32_t HAL_GetHalVersion() { uint32_t HAL_GetHalVersion() {
// Hard-coded because it's not defined in SDK // Hard-coded because it's not defined in SDK
@ -122,6 +123,8 @@ STATIC int vfs_mount_and_chdir(mp_obj_t bdev, mp_obj_t mount_point) {
#endif #endif
int main(int argc, char **argv) { int main(int argc, char **argv) {
bool first_soft_reset = true;
soft_reset: soft_reset:
#if defined(MICROPY_BOARD_EARLY_INIT) #if defined(MICROPY_BOARD_EARLY_INIT)
MICROPY_BOARD_EARLY_INIT(); MICROPY_BOARD_EARLY_INIT();
@ -132,50 +135,41 @@ soft_reset:
#endif #endif
led_init(); led_init();
led_state(1, 1); // MICROPY_HW_LED_1 aka MICROPY_HW_LED_RED led_state(1, 1); // MICROPY_HW_LED_1 aka MICROPY_HW_LED_RED
mp_stack_set_top(&_ram_end); mp_stack_set_top(&_ram_end);
// Stack limit should be less than real stack size, so we have a chance // Stack limit should be less than real stack size, so we have a chance
// to recover from limit hit. (Limit is measured in bytes.) // to recover from limit hit. (Limit is measured in bytes.)
mp_stack_set_limit((char *) &_ram_end - (char *) &_heap_end - 400); mp_stack_set_limit((char *) &_ram_end - (char *) &_heap_end - 400);
machine_init(); // GC init
gc_init(&_heap_start, &_heap_end); gc_init(&_heap_start, &_heap_end);
machine_init();
mp_init(); mp_init();
readline_init0(); readline_init0();
#if MICROPY_PY_MACHINE_HW_SPI #if MICROPY_PY_MACHINE_HW_SPI
spi_init0(); spi_init0();
#endif #endif
#if MICROPY_PY_MACHINE_I2C #if MICROPY_PY_MACHINE_I2C
i2c_init0(); i2c_init0();
#endif #endif
#if MICROPY_PY_MACHINE_ADC #if MICROPY_PY_MACHINE_ADC
adc_init0(); adc_init0();
#endif #endif
#if MICROPY_PY_MACHINE_HW_PWM #if MICROPY_PY_MACHINE_HW_PWM
pwm_init0(); pwm_init0();
#endif #endif
#if MICROPY_PY_MACHINE_RTCOUNTER #if MICROPY_PY_MACHINE_RTCOUNTER
rtc_init0(); rtc_init0();
#endif #endif
#if MICROPY_PY_MACHINE_TIMER #if MICROPY_PY_MACHINE_TIMER
timer_init0(); timer_init0();
#endif #endif
#if MICROPY_PY_MACHINE_UART #if MICROPY_PY_MACHINE_UART
uart_init0(); uart_init0();
#endif #endif
pin_init0();
fb_alloc_init0(); fb_alloc_init0();
framebuffer_init0(); framebuffer_init0();
@ -185,18 +179,14 @@ soft_reset:
#endif #endif
#if (MICROPY_PY_BLE_NUS == 0) && (MICROPY_HW_USB_CDC == 0) #if (MICROPY_PY_BLE_NUS == 0) && (MICROPY_HW_USB_CDC == 0)
{ mp_obj_t args[2] = {
mp_obj_t args[2] = { MP_OBJ_NEW_SMALL_INT(0),
MP_OBJ_NEW_SMALL_INT(0), MP_OBJ_NEW_SMALL_INT(115200),
MP_OBJ_NEW_SMALL_INT(115200), };
}; MP_STATE_PORT(board_stdio_uart) = machine_hard_uart_type.make_new(
MP_STATE_PORT(board_stdio_uart) = machine_hard_uart_type.make_new( (mp_obj_t) &machine_hard_uart_type, MP_ARRAY_SIZE(args), 0, args);
(mp_obj_t) &machine_hard_uart_type, MP_ARRAY_SIZE(args), 0, args);
}
#endif #endif
pin_init0();
#if MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE #if MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE
flashbdev_init(); flashbdev_init();
@ -280,15 +270,20 @@ soft_reset:
usb_cdc_init(); usb_cdc_init();
#endif #endif
#if MICROPY_VFS || MICROPY_MBFS || MICROPY_MODULE_FROZEN
// run boot.py and main.py if they exist.
pyexec_file_if_exists("boot.py", false);
pyexec_file_if_exists("main.py", false);
#endif
usbdbg_init(); usbdbg_init();
pendsv_init(); pendsv_init();
#if MICROPY_VFS || MICROPY_MBFS || MICROPY_MODULE_FROZEN
// Run boot.py script.
bool interrupted = bootutils_exec_bootscript("boot.py", true, false);
// Run main.py script on first soft-reset.
if (first_soft_reset && !interrupted && mp_vfs_import_stat("main.py")) {
bootutils_exec_bootscript("main.py", true, false);
goto soft_reset_exit;
}
#endif
// If there's no script ready, just re-exec REPL // If there's no script ready, just re-exec REPL
while (!usbdbg_script_ready()) { while (!usbdbg_script_ready()) {
nlr_buf_t nlr; nlr_buf_t nlr;
@ -337,6 +332,7 @@ soft_reset:
} }
} }
soft_reset_exit:
printf("MPY: soft reboot\n"); printf("MPY: soft reboot\n");
#if MICROPY_PY_MACHINE_HW_PWM #if MICROPY_PY_MACHINE_HW_PWM
pwm_deinit_all(); pwm_deinit_all();
@ -351,9 +347,9 @@ soft_reset:
MICROPY_BOARD_DEINIT(); MICROPY_BOARD_DEINIT();
#endif #endif
mp_deinit(); mp_deinit();
goto soft_reset;
return 0; first_soft_reset = false;
goto soft_reset;
} }
#if !MICROPY_VFS #if !MICROPY_VFS

View File

@ -100,13 +100,14 @@ FIRM_OBJ += $(addprefix $(BUILD)/$(OMV_DIR)/alloc/, \
FIRM_OBJ += $(addprefix $(BUILD)/$(OMV_DIR)/common/, \ FIRM_OBJ += $(addprefix $(BUILD)/$(OMV_DIR)/common/, \
array.o \ array.o \
file_utils.o \
ini.o \ ini.o \
ringbuf.o \ ringbuf.o \
trace.o \ trace.o \
mutex.o \ mutex.o \
usbdbg.o \ usbdbg.o \
tinyusb_debug.o \ tinyusb_debug.o \
file_utils.o \
boot_utils.o \
sensor_utils.o \ sensor_utils.o \
) )

View File

@ -74,8 +74,8 @@
#if MICROPY_VFS_FAT && MICROPY_HW_USB_MSC #if MICROPY_VFS_FAT && MICROPY_HW_USB_MSC
#include "extmod/vfs.h" #include "extmod/vfs.h"
#include "extmod/vfs_fat.h" #include "extmod/vfs_fat.h"
#include "common/factoryreset.h"
#endif #endif
#include "boot_utils.h"
extern uint8_t __StackTop, __StackBottom; extern uint8_t __StackTop, __StackBottom;
static char OMV_ATTR_SECTION(OMV_ATTR_ALIGNED(gc_heap[OMV_HEAP_SIZE], 4), ".heap"); static char OMV_ATTR_SECTION(OMV_ATTR_ALIGNED(gc_heap[OMV_HEAP_SIZE], 4), ".heap");
@ -108,32 +108,6 @@ void pico_reset_to_bootloader(size_t n_args, const void *args_in) {
reset_usb_boot(0, 0); reset_usb_boot(0, 0);
} }
void exec_boot_script(const char *path, bool interruptible) {
nlr_buf_t nlr;
bool interrupted = false;
if (nlr_push(&nlr) == 0) {
// Enable IDE interrupts if allowed.
if (interruptible) {
usbdbg_set_irq_enabled(true);
usbdbg_set_script_running(true);
}
// Parse, compile and execute the script.
pyexec_file_if_exists(path, true);
nlr_pop();
} else {
interrupted = true;
}
// Disable IDE interrupts
usbdbg_set_irq_enabled(false);
usbdbg_set_script_running(false);
if (interrupted) {
mp_obj_print_exception(&mp_plat_print, (mp_obj_t) nlr.ret_val);
}
}
int main(int argc, char **argv) { int main(int argc, char **argv) {
bool first_soft_reset = true; bool first_soft_reset = true;
@ -145,7 +119,6 @@ int main(int argc, char **argv) {
#if MICROPY_HW_ENABLE_USBDEV #if MICROPY_HW_ENABLE_USBDEV
bi_decl(bi_program_feature("USB REPL")) bi_decl(bi_program_feature("USB REPL"))
tusb_init();
#endif #endif
#if MICROPY_PY_THREAD #if MICROPY_PY_THREAD
@ -170,12 +143,6 @@ int main(int argc, char **argv) {
OMV_UNIQUE_ID_ADDR = pico_unique_id.id; OMV_UNIQUE_ID_ADDR = pico_unique_id.id;
pico_get_unique_board_id(&pico_unique_id); pico_get_unique_board_id(&pico_unique_id);
// Install Tinyusb CDC debugger IRQ handler.
irq_set_enabled(USBCTRL_IRQ, false);
irq_remove_handler(USBCTRL_IRQ, irq_get_vtable_handler(USBCTRL_IRQ));
irq_set_exclusive_handler(USBCTRL_IRQ, OMV_USB1_IRQ_HANDLER);
irq_set_enabled(USBCTRL_IRQ, true);
soft_reset: soft_reset:
// Initialise stack extents and GC heap. // Initialise stack extents and GC heap.
mp_stack_set_top(&__StackTop); mp_stack_set_top(&__StackTop);
@ -219,7 +186,7 @@ soft_reset:
if (mp_vfs_mount_and_chdir_protected(bdev, mount_point) == -MP_ENODEV) { if (mp_vfs_mount_and_chdir_protected(bdev, mount_point) == -MP_ENODEV) {
// Create a fresh filesystem. // Create a fresh filesystem.
fs_user_mount_t *vfs = MP_OBJ_TYPE_GET_SLOT(&mp_fat_vfs_type, make_new) (&mp_fat_vfs_type, 1, 0, &bdev); fs_user_mount_t *vfs = MP_OBJ_TYPE_GET_SLOT(&mp_fat_vfs_type, make_new) (&mp_fat_vfs_type, 1, 0, &bdev);
if (factoryreset_create_filesystem(vfs) == 0) { if (bootutils_init_filesystem(vfs) == 0) {
mp_vfs_mount_and_chdir_protected(bdev, mount_point); mp_vfs_mount_and_chdir_protected(bdev, mount_point);
} }
} }
@ -227,11 +194,26 @@ soft_reset:
pyexec_frozen_module("_boot.py", false); pyexec_frozen_module("_boot.py", false);
#endif #endif
// Execute user scripts. // Mark the filesystem as an OpenMV storage.
exec_boot_script("boot.py", false); file_ll_touch(".openmv_disk");
if (first_soft_reset) { // Initialize TinyUSB after the filesystem has been mounted.
exec_boot_script("main.py", true); if (!tusb_inited()) {
tusb_init();
// Install Tinyusb CDC debugger IRQ handler.
irq_set_enabled(USBCTRL_IRQ, false);
irq_remove_handler(USBCTRL_IRQ, irq_get_vtable_handler(USBCTRL_IRQ));
irq_set_exclusive_handler(USBCTRL_IRQ, OMV_USB1_IRQ_HANDLER);
}
// Run boot.py script.
bool interrupted = bootutils_exec_bootscript("boot.py", true, false);
// Run main.py script on first soft-reset.
if (first_soft_reset && !interrupted && mp_vfs_import_stat("main.py")) {
bootutils_exec_bootscript("main.py", true, false);
goto soft_reset_exit;
} }
// If there's no script ready, just re-exec REPL // If there's no script ready, just re-exec REPL
@ -282,6 +264,7 @@ soft_reset:
} }
} }
soft_reset_exit:
mp_printf(MP_PYTHON_PRINTER, "MPY: soft reboot\n"); mp_printf(MP_PYTHON_PRINTER, "MPY: soft reboot\n");
#if MICROPY_PY_AUDIO #if MICROPY_PY_AUDIO
py_audio_deinit(); py_audio_deinit();

View File

@ -93,15 +93,15 @@ target_sources(${MICROPY_TARGET} PRIVATE
${TOP_DIR}/${OMV_DIR}/alloc/unaligned_memcpy.c ${TOP_DIR}/${OMV_DIR}/alloc/unaligned_memcpy.c
${TOP_DIR}/${OMV_DIR}/common/array.c ${TOP_DIR}/${OMV_DIR}/common/array.c
${TOP_DIR}/${OMV_DIR}/common/file_utils.c
${TOP_DIR}/${OMV_DIR}/common/ini.c ${TOP_DIR}/${OMV_DIR}/common/ini.c
${TOP_DIR}/${OMV_DIR}/common/ringbuf.c ${TOP_DIR}/${OMV_DIR}/common/ringbuf.c
${TOP_DIR}/${OMV_DIR}/common/trace.c ${TOP_DIR}/${OMV_DIR}/common/trace.c
${TOP_DIR}/${OMV_DIR}/common/mutex.c ${TOP_DIR}/${OMV_DIR}/common/mutex.c
${TOP_DIR}/${OMV_DIR}/common/usbdbg.c ${TOP_DIR}/${OMV_DIR}/common/usbdbg.c
${TOP_DIR}/${OMV_DIR}/common/tinyusb_debug.c ${TOP_DIR}/${OMV_DIR}/common/tinyusb_debug.c
${TOP_DIR}/${OMV_DIR}/common/file_utils.c
${TOP_DIR}/${OMV_DIR}/common/boot_utils.c
${TOP_DIR}/${OMV_DIR}/common/sensor_utils.c ${TOP_DIR}/${OMV_DIR}/common/sensor_utils.c
${TOP_DIR}/${OMV_DIR}/common/factoryreset.c
${TOP_DIR}/${OMV_DIR}/sensors/ov2640.c ${TOP_DIR}/${OMV_DIR}/sensors/ov2640.c
${TOP_DIR}/${OMV_DIR}/sensors/ov5640.c ${TOP_DIR}/${OMV_DIR}/sensors/ov5640.c

View File

@ -92,7 +92,7 @@
#include "extmod/vfs.h" #include "extmod/vfs.h"
#include "extmod/vfs_fat.h" #include "extmod/vfs_fat.h"
#include "common/factoryreset.h" #include "boot_utils.h"
int errno; int errno;
extern char _vfs_buf[]; extern char _vfs_buf[];
@ -215,73 +215,6 @@ int ini_handler_callback(void *user, const char *section, const char *name, cons
#undef MATCH #undef MATCH
} }
FRESULT exec_boot_script(const char *path, bool selftest, bool interruptible, bool wifidbg_enabled) {
nlr_buf_t nlr;
bool interrupted = false;
FRESULT f_res = FR_NO_FILE;
if (nlr_push(&nlr) == 0) {
// Enable IDE interrupts if allowed.
if (interruptible) {
usbdbg_set_irq_enabled(true);
usbdbg_set_script_running(true);
#if OMV_ENABLE_WIFIDBG && MICROPY_PY_WINC1500
wifidbg_set_irq_enabled(wifidbg_enabled);
#endif
}
// Try to run the frozen module first.
if (pyexec_frozen_module(path, true) == false) {
// No frozen module, try the filesystem.
f_res = file_ll_stat(path, NULL);
if (f_res == FR_OK) {
// Parse, compile and execute the script.
pyexec_file(path, true);
}
}
nlr_pop();
} else {
interrupted = true;
}
// Disable IDE interrupts
usbdbg_set_irq_enabled(false);
usbdbg_set_script_running(false);
#if OMV_ENABLE_WIFIDBG && MICROPY_PY_WINC1500
wifidbg_set_irq_enabled(false);
#endif
if (interrupted) {
if (selftest) {
// Get the exception message. TODO: might be a hack.
mp_obj_str_t *str = mp_obj_exception_get_value((mp_obj_t) nlr.ret_val);
// If any of the self-tests fail log the exception message
// and loop forever. Note: IDE exceptions will not be caught.
__fatal_error((const char *) str->data);
} else {
mp_obj_print_exception(&mp_plat_print, (mp_obj_t) nlr.ret_val);
if (nlr_push(&nlr) == 0) {
flash_error(3);
nlr_pop();
}// If this gets interrupted again ignore it.
}
}
if (selftest && f_res == FR_OK) {
// Remove self tests script and flush cache
file_ll_unlink(path);
storage_flush();
#ifdef OMV_SELF_TEST_SWD_ADDR
// Set flag for SWD debugger.
// Note: main.py does not use the frame buffer.
OMV_SELF_TEST_SWD_ADDR = 0xDEADBEEF;
#endif
}
return f_res;
}
int main(void) { int main(void) {
#if MICROPY_HW_SDRAM_SIZE #if MICROPY_HW_SDRAM_SIZE
bool sdram_ok = false; bool sdram_ok = false;
@ -470,7 +403,7 @@ soft_reset:
if (res == FR_NO_FILESYSTEM) { if (res == FR_NO_FILESYSTEM) {
// Create a fresh filesystem. // Create a fresh filesystem.
led_state(LED_RED, 1); led_state(LED_RED, 1);
factoryreset_create_filesystem(vfs_fat); bootutils_init_filesystem(vfs_fat);
led_state(LED_RED, 0); led_state(LED_RED, 0);
// Flush storage // Flush storage
storage_flush(); storage_flush();
@ -505,7 +438,7 @@ else {
MP_STATE_VM(vfs_mount_table) = vfs; MP_STATE_VM(vfs_mount_table) = vfs;
MP_STATE_PORT(vfs_cur) = vfs; MP_STATE_PORT(vfs_cur) = vfs;
// Mark FS as OpenMV disk. // Mark the filesystem as an OpenMV storage.
file_ll_touch("/.openmv_disk"); file_ll_touch("/.openmv_disk");
// Parse OpenMV configuration file. // Parse OpenMV configuration file.
@ -523,21 +456,6 @@ else {
openmv_config.wifidbg = false; openmv_config.wifidbg = false;
#endif #endif
// Execute frozen _boot.py (if any) for early system setup.
pyexec_frozen_module("_boot.py", false);
// Run boot script(s)
if (first_soft_reset) {
// Execute the boot.py script before initializing the USB dev to
// override the USB mode if required, otherwise VCP+MSC is used.
exec_boot_script("boot.py", false, false, false);
#if (OMV_ENABLE_SELFTEST == 1)
// Execute the selftests.py script before the filesystem is mounted
// to avoid corrupting the filesystem when selftests.py is removed.
exec_boot_script("selftest.py", true, false, false);
#endif
}
// Init USB device to default setting if it was not already configured // Init USB device to default setting if it was not already configured
if (!(pyb_usb_flags & PYB_USB_FLAG_USB_MODE_CALLED)) { if (!(pyb_usb_flags & PYB_USB_FLAG_USB_MODE_CALLED)) {
pyb_usb_dev_init(pyb_usb_dev_detect(), MICROPY_HW_USB_VID, pyb_usb_dev_init(pyb_usb_dev_detect(), MICROPY_HW_USB_VID,
@ -558,80 +476,89 @@ else {
led_state(LED_GREEN, 0); led_state(LED_GREEN, 0);
led_state(LED_BLUE, 0); led_state(LED_BLUE, 0);
// Run main script if it exists.
if (first_soft_reset) {
exec_boot_script("main.py", false, true, openmv_config.wifidbg);
} else {
do {
usbdbg_init();
if (openmv_config.wifidbg == true) { // Run boot.py script.
// Need to reinit imlib in WiFi debug mode. bool interrupted = bootutils_exec_bootscript("boot.py", true, false);
imlib_deinit_all();
imlib_init_all();
}
// If there's no script ready, just re-exec REPL // Run main.py script on first soft-reset.
while (!usbdbg_script_ready()) { if (first_soft_reset && !interrupted && mp_vfs_import_stat("main.py")) {
nlr_buf_t nlr; bootutils_exec_bootscript("main.py", true, openmv_config.wifidbg);
goto soft_reset_exit;
if (nlr_push(&nlr) == 0) {
// enable IDE interrupt
usbdbg_set_irq_enabled(true);
#if OMV_ENABLE_WIFIDBG && MICROPY_PY_WINC1500
wifidbg_set_irq_enabled(openmv_config.wifidbg);
#endif
// run REPL
if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) {
if (pyexec_raw_repl() != 0) {
break;
}
} else {
if (pyexec_friendly_repl() != 0) {
break;
}
}
nlr_pop();
}
}
if (usbdbg_script_ready()) {
nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) {
// Enable IDE interrupts
usbdbg_set_irq_enabled(true);
#if OMV_ENABLE_WIFIDBG && MICROPY_PY_WINC1500
wifidbg_set_irq_enabled(openmv_config.wifidbg);
#endif
// Execute the script.
pyexec_str(usbdbg_get_script(), true);
// Disable IDE interrupts
usbdbg_set_irq_enabled(false);
nlr_pop();
} else {
mp_obj_print_exception(&mp_plat_print, (mp_obj_t) nlr.ret_val);
}
if (usbdbg_is_busy() && nlr_push(&nlr) == 0) {
// Enable IDE interrupt
usbdbg_set_irq_enabled(true);
#if OMV_ENABLE_WIFIDBG && MICROPY_PY_WINC1500
wifidbg_set_irq_enabled(openmv_config.wifidbg);
#endif
// Wait for the current command to finish.
usbdbg_wait_for_command(1000);
// Disable IDE interrupts
usbdbg_set_irq_enabled(false);
nlr_pop();
}
}
} while (openmv_config.wifidbg == true);
} }
do {
usbdbg_init();
if (openmv_config.wifidbg == true) {
// Need to reinit imlib in WiFi debug mode.
imlib_deinit_all();
imlib_init_all();
}
// If there's no script ready, just re-exec REPL
while (!usbdbg_script_ready()) {
nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) {
// enable IDE interrupt
usbdbg_set_irq_enabled(true);
#if OMV_ENABLE_WIFIDBG && MICROPY_PY_WINC1500
wifidbg_set_irq_enabled(openmv_config.wifidbg);
#endif
// run REPL
if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) {
if (pyexec_raw_repl() != 0) {
break;
}
} else {
if (pyexec_friendly_repl() != 0) {
break;
}
}
nlr_pop();
}
}
if (usbdbg_script_ready()) {
nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) {
// Enable IDE interrupts
usbdbg_set_irq_enabled(true);
#if OMV_ENABLE_WIFIDBG && MICROPY_PY_WINC1500
wifidbg_set_irq_enabled(openmv_config.wifidbg);
#endif
// Execute the script.
pyexec_str(usbdbg_get_script(), true);
// Disable IDE interrupts
usbdbg_set_irq_enabled(false);
nlr_pop();
} else {
mp_obj_print_exception(&mp_plat_print, (mp_obj_t) nlr.ret_val);
}
if (usbdbg_is_busy() && nlr_push(&nlr) == 0) {
// Enable IDE interrupt
usbdbg_set_irq_enabled(true);
#if OMV_ENABLE_WIFIDBG && MICROPY_PY_WINC1500
wifidbg_set_irq_enabled(openmv_config.wifidbg);
#endif
// Wait for the current command to finish.
usbdbg_wait_for_command(1000);
// Disable IDE interrupts
usbdbg_set_irq_enabled(false);
nlr_pop();
}
}
} while (openmv_config.wifidbg == true);
soft_reset_exit:
// soft reset // soft reset
mp_printf(&mp_plat_print, "MPY: soft reboot\n");
// Flush filesystem storage.
storage_flush(); storage_flush();
// Call GC sweep first, before deinitializing networking drivers // Call GC sweep first, before deinitializing networking drivers

View File

@ -27,7 +27,8 @@ MPY_CFLAGS += -I$(TOP_DIR)/$(MICROPY_DIR)/ports/stm32/usbdev/core/inc/
MPY_CFLAGS += -I$(TOP_DIR)/$(MICROPY_DIR)/ports/stm32/usbdev/class/inc/ MPY_CFLAGS += -I$(TOP_DIR)/$(MICROPY_DIR)/ports/stm32/usbdev/class/inc/
MPY_CFLAGS += -I$(TOP_DIR)/$(MICROPY_DIR)/ports/stm32/lwip_inc/ MPY_CFLAGS += -I$(TOP_DIR)/$(MICROPY_DIR)/ports/stm32/lwip_inc/
MPY_CFLAGS += -I$(TOP_DIR)/$(MICROPY_DIR)/shared/runtime/ MPY_CFLAGS += -I$(TOP_DIR)/$(MICROPY_DIR)/shared/runtime/
MPY_CFLAGS += -DMICROPY_PY_USSL=1 -DMICROPY_SSL_MBEDTLS=1 -DMICROPY_STREAMS_POSIX_API=1 MPY_CFLAGS += -DMICROPY_PY_USSL=1 -DMICROPY_SSL_MBEDTLS=1 -DMICROPY_STREAMS_POSIX_API=1 -DMICROPY_VFS_FAT=1
MICROPY_ARGS += MICROPY_PY_USSL=1 MICROPY_SSL_MBEDTLS=1 MICROPY_PY_BTREE=1\ MICROPY_ARGS += MICROPY_PY_USSL=1 MICROPY_SSL_MBEDTLS=1 MICROPY_PY_BTREE=1\
STM32LIB_CMSIS_DIR=$(TOP_DIR)/$(CMSIS_DIR) STM32LIB_HAL_DIR=$(TOP_DIR)/$(HAL_DIR) STM32LIB_CMSIS_DIR=$(TOP_DIR)/$(CMSIS_DIR) STM32LIB_HAL_DIR=$(TOP_DIR)/$(HAL_DIR)
@ -144,15 +145,15 @@ FIRM_OBJ += $(addprefix $(BUILD)/$(OMV_DIR)/alloc/, \
FIRM_OBJ += $(addprefix $(BUILD)/$(OMV_DIR)/common/, \ FIRM_OBJ += $(addprefix $(BUILD)/$(OMV_DIR)/common/, \
array.o \ array.o \
file_utils.o \
ini.o \ ini.o \
ringbuf.o \ ringbuf.o \
trace.o \ trace.o \
mutex.o \ mutex.o \
usbdbg.o \
sensor_utils.o \
factoryreset.o \
vospi.o \ vospi.o \
usbdbg.o \
file_utils.o \
boot_utils.o \
sensor_utils.o \
) )
FIRM_OBJ += $(addprefix $(BUILD)/$(OMV_DIR)/sensors/, \ FIRM_OBJ += $(addprefix $(BUILD)/$(OMV_DIR)/sensors/, \