atmel-samd: Rework boot, main and REPL order.

Boot will only run once now before USB is started. Its output goes to
boot_out.txt. After main and REPL will run with VM and hardware resets
between each.
This commit is contained in:
Scott Shawcroft 2017-05-12 18:26:14 -07:00
parent 7672bf7736
commit 790c38e18c
10 changed files with 118 additions and 29 deletions

View File

@ -183,6 +183,7 @@ SRC_C = \
autoreload.c \
builtin_open.c \
fatfs_port.c \
flash_api.c \
main.c \
moduos.c \
mphalport.c \

47
atmel-samd/flash_api.c Normal file
View File

@ -0,0 +1,47 @@
/*
* This file is part of the Micro Python project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
*
* 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 "flash_api.h"
#include "py/mpstate.h"
#define VFS_INDEX 0
void flash_set_usb_writeable(bool usb_writeable) {
if (VFS_INDEX >= MP_ARRAY_SIZE(MP_STATE_PORT(fs_user_mount))) {
return;
}
fs_user_mount_t *vfs = MP_STATE_PORT(fs_user_mount)[VFS_INDEX];
if (vfs == NULL) {
return;
}
if (usb_writeable) {
vfs->flags |= FSUSER_USB_WRITEABLE;
} else {
vfs->flags &= ~FSUSER_USB_WRITEABLE;
}
}

View File

@ -26,7 +26,11 @@
#ifndef __MICROPY_INCLUDED_ATMEL_SAMD_FLASH_API_H__
#define __MICROPY_INCLUDED_ATMEL_SAMD_FLASH_API_H__
#include "extmod/fsusermount.h"
extern void flash_init_vfs(fs_user_mount_t *vfs);
extern void flash_flush(void);
void flash_set_usb_writeable(bool usb_writeable);
#endif // __MICROPY_INCLUDED_ATMEL_SAMD_FLASH_API_H__

View File

@ -293,7 +293,7 @@ const mp_obj_type_t internal_flash_type = {
};
void flash_init_vfs(fs_user_mount_t *vfs) {
vfs->flags |= FSUSER_NATIVE | FSUSER_HAVE_IOCTL | FSUSER_USB_WRITEABLE;
vfs->flags |= FSUSER_NATIVE | FSUSER_HAVE_IOCTL;
vfs->readblocks[0] = (mp_obj_t)&internal_flash_obj_readblocks_obj;
vfs->readblocks[1] = (mp_obj_t)&internal_flash_obj;
vfs->readblocks[2] = (mp_obj_t)internal_flash_read_blocks; // native version

View File

@ -86,11 +86,6 @@ void init_flash_fs(void) {
if (res == FR_NO_FILESYSTEM) {
// no filesystem so create a fresh one
// We are before USB initializes so temporarily undo the USB_WRITEABLE
// requirement.
bool usb_writeable = (vfs->flags & FSUSER_USB_WRITEABLE) > 0;
vfs->flags &= ~FSUSER_USB_WRITEABLE;
res = f_mkfs("/flash", 0, 0);
// Flush the new file system to make sure its repaired immediately.
flash_flush();
@ -101,10 +96,6 @@ void init_flash_fs(void) {
// set label
f_setlabel("CIRCUITPY");
if (usb_writeable) {
vfs->flags |= FSUSER_USB_WRITEABLE;
}
} else if (res != FR_OK) {
MP_STATE_PORT(fs_user_mount)[0] = NULL;
return;
@ -251,21 +242,13 @@ bool start_mp(void) {
mp_hal_stdout_tx_str("Auto-reload is on. Simply save files over USB to run them or enter REPL to disable.\r\n");
}
#endif
new_status_color(BOOT_RUNNING);
pyexec_result_t result;
bool found_boot = maybe_run("settings.txt", &result) ||
maybe_run("settings.py", &result) ||
maybe_run("boot.py", &result) ||
maybe_run("boot.txt", &result);
bool found_main = false;
if (!found_boot || !(result.return_code & PYEXEC_FORCED_EXIT)) {
new_status_color(MAIN_RUNNING);
found_main = maybe_run("code.txt", &result) ||
maybe_run("code.py", &result) ||
maybe_run("main.py", &result) ||
maybe_run("main.txt", &result);
}
pyexec_result_t result;
new_status_color(MAIN_RUNNING);
found_main = maybe_run("code.txt", &result) ||
maybe_run("code.py", &result) ||
maybe_run("main.py", &result) ||
maybe_run("main.txt", &result);
reset_status_led();
if (result.return_code & PYEXEC_FORCED_EXIT) {
@ -520,6 +503,36 @@ int main(void) {
// as current dir.
init_flash_fs();
// Reset everything and prep MicroPython to run boot.py.
reset_samd21();
reset_mp();
// Run boot before initing USB and capture output in a file.
new_status_color(BOOT_RUNNING);
#ifdef CIRCUITPY_BOOT_OUTPUT_FILE
FIL file_pointer;
boot_output_file = &file_pointer;
FRESULT result = f_open(boot_output_file, CIRCUITPY_BOOT_OUTPUT_FILE, FA_WRITE | FA_CREATE_ALWAYS);
if (result != FR_OK) {
while (true) {}
}
#endif
// TODO(tannewt): Re-add support for flashing boot error output.
bool found_boot = maybe_run("settings.txt", NULL) ||
maybe_run("settings.py", NULL) ||
maybe_run("boot.py", NULL) ||
maybe_run("boot.txt", NULL);
(void) found_boot;
#ifdef CIRCUITPY_BOOT_OUTPUT_FILE
f_close(boot_output_file);
boot_output_file = NULL;
#endif
// Turn off local writing in favor of USB writing prior to initializing USB.
flash_set_usb_writeable(true);
usb_hid_init();
// Start USB after getting everything going.
@ -527,14 +540,18 @@ int main(void) {
udc_start();
#endif
// Reset to remove any state that boot.py setup. It should only be used to
// change internal state thats not in the heap.
reset_samd21();
reset_mp();
// Main script is finished, so now go into REPL mode.
// The REPL mode can change, or it can request a reload.
// Boot script is finished, so now go into REPL/main mode.
int exit_code = PYEXEC_FORCED_EXIT;
bool skip_repl = true;
bool first_run = true;
for (;;) {
if (!skip_repl) {
// The REPL mode can change, or it can request a reload.
autoreload_disable();
new_status_color(REPL_RUNNING);
if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) {
@ -542,15 +559,17 @@ int main(void) {
} else {
exit_code = pyexec_friendly_repl();
}
reset_samd21();
reset_mp();
}
if (exit_code == PYEXEC_FORCED_EXIT) {
if (!first_run) {
mp_hal_stdout_tx_str("soft reboot\r\n");
}
reset_samd21();
reset_mp();
first_run = false;
skip_repl = start_mp();
reset_samd21();
reset_mp();
} else if (exit_code != 0) {
break;
}

View File

@ -204,5 +204,6 @@ bool udi_msc_process_trans(void);
#define MICROPY_VM_HOOK_RETURN udi_msc_process_trans();
#define CIRCUITPY_AUTORELOAD_DELAY_MS 500
#define CIRCUITPY_BOOT_OUTPUT_FILE "/flash/boot_out.txt"
#endif // __INCLUDED_MPCONFIGPORT_H

View File

@ -191,6 +191,13 @@ void mp_hal_stdout_tx_strn(const char *str, size_t len) {
usart_write_buffer_wait(&usart_instance, (uint8_t*) str, len);
#endif
#ifdef CIRCUITPY_BOOT_OUTPUT_FILE
if (boot_output_file != NULL) {
UINT bytes_written = 0;
f_write(boot_output_file, str, len, &bytes_written);
}
#endif
#ifdef USB_REPL
// Always make sure there is enough room in the usb buffer for the outgoing
// string. If there isn't we risk getting caught in a loop within the usb

View File

@ -29,6 +29,8 @@
#include "py/obj.h"
#include "lib/fatfs/ff.h"
#define USB_RX_BUF_SIZE 128
// Global millisecond tick count (driven by SysTick interrupt).
@ -41,6 +43,8 @@ static inline mp_uint_t mp_hal_ticks_ms(void) {
volatile uint8_t usb_rx_count;
volatile bool mp_cdc_enabled;
FIL* boot_output_file;
int receive_usb(void);
void mp_hal_set_interrupt_char(int c);

View File

@ -661,7 +661,7 @@ const mp_obj_type_t spi_flash_type = {
};
void flash_init_vfs(fs_user_mount_t *vfs) {
vfs->flags |= FSUSER_NATIVE | FSUSER_HAVE_IOCTL | FSUSER_USB_WRITEABLE;
vfs->flags |= FSUSER_NATIVE | FSUSER_HAVE_IOCTL;
vfs->readblocks[0] = (mp_obj_t)&spi_flash_obj_readblocks_obj;
vfs->readblocks[1] = (mp_obj_t)&spi_flash_obj;
vfs->readblocks[2] = (mp_obj_t)spi_flash_read_blocks; // native version

View File

@ -24,6 +24,10 @@
* THE SOFTWARE.
*/
#ifndef __MICROPY_INCLUDED_EXTMOD_FSUSERMOUNT_H__
#define __MICROPY_INCLUDED_EXTMOD_FSUSERMOUNT_H__
#include "lib/fatfs/ff.h"
#include "py/obj.h"
@ -65,3 +69,5 @@ mp_obj_t fatfs_umount(mp_obj_t bdev_or_path_in);
MP_DECLARE_CONST_FUN_OBJ_KW(fsuser_mount_obj);
MP_DECLARE_CONST_FUN_OBJ_1(fsuser_umount_obj);
MP_DECLARE_CONST_FUN_OBJ_KW(fsuser_mkfs_obj);
#endif // __MICROPY_INCLUDED_EXTMOD_FSUSERMOUNT_H__