handle bad power on reset better
This commit is contained in:
parent
4dd9e0da2c
commit
74a6edff4d
@ -48,7 +48,7 @@
|
||||
#define TC_H_INCLUDED
|
||||
|
||||
/**
|
||||
* \defgroup asfdoc_sam0_tc_group SAM Timer/Counter (TC) Driver
|
||||
* \defgroup asfdoc_sam0_tc_group SAM Timer/Counter (TC) Driver
|
||||
*
|
||||
* This driver for Atmel® | SMART ARM®-based microcontrollers provides an interface for the configuration
|
||||
* and management of the timer modules within the device, for waveform
|
||||
@ -1146,12 +1146,14 @@ static inline void tc_enable_events(
|
||||
/* Sanity check arguments */
|
||||
Assert(module_inst);
|
||||
Assert(module_inst->hw);
|
||||
Assert(events);
|
||||
Assert(events);
|
||||
|
||||
Tc *const tc_module = module_inst->hw;
|
||||
|
||||
uint32_t event_mask = 0;
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
|
||||
if (events->invert_event_input == true) {
|
||||
event_mask |= TC_EVCTRL_TCINV;
|
||||
}
|
||||
@ -1171,6 +1173,7 @@ static inline void tc_enable_events(
|
||||
}
|
||||
|
||||
tc_module->COUNT8.EVCTRL.reg |= event_mask | events->event_action;
|
||||
#pragma GCC diagnostic pop
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -27,8 +27,10 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "flash_api.h"
|
||||
#include "main.h"
|
||||
#include "py/mperrno.h"
|
||||
#include "py/runtime.h"
|
||||
#include "shared-bindings/microcontroller/__init__.h"
|
||||
#include "shared-bindings/storage/__init__.h"
|
||||
|
||||
extern volatile bool mp_msc_enabled;
|
||||
@ -44,3 +46,9 @@ void common_hal_storage_remount(const char* mount_path, bool readonly) {
|
||||
|
||||
flash_set_usb_writeable(readonly);
|
||||
}
|
||||
|
||||
void common_hal_storage_erase_filesystem(void) {
|
||||
init_flash_fs(false, true); // Force a re-format.
|
||||
common_hal_mcu_reset();
|
||||
// We won't actually get here, since we're resetting.
|
||||
}
|
||||
|
@ -66,6 +66,7 @@
|
||||
|
||||
#include "autoreload.h"
|
||||
#include "flash_api.h"
|
||||
#include "main.h"
|
||||
#include "mpconfigboard.h"
|
||||
#include "rgb_led_status.h"
|
||||
#include "shared_dma.h"
|
||||
@ -110,7 +111,7 @@ void do_str(const char *src, mp_parse_input_kind_t input_kind) {
|
||||
|
||||
// we don't make this function static because it needs a lot of stack and we
|
||||
// want it to be executed without using stack within main() function
|
||||
void init_flash_fs(bool create_allowed) {
|
||||
void init_flash_fs(bool create_allowed, bool force_create) {
|
||||
// init the vfs object
|
||||
fs_user_mount_t *vfs_fat = &fs_user_mount_flash;
|
||||
vfs_fat->flags = 0;
|
||||
@ -119,8 +120,8 @@ void init_flash_fs(bool create_allowed) {
|
||||
// try to mount the flash
|
||||
FRESULT res = f_mount(&vfs_fat->fatfs);
|
||||
|
||||
if (res == FR_NO_FILESYSTEM && create_allowed) {
|
||||
// no filesystem so create a fresh one
|
||||
if ((res == FR_NO_FILESYSTEM && create_allowed) || force_create) {
|
||||
// No filesystem so create a fresh one, or reformat has been requested.
|
||||
|
||||
// Wait two seconds before creating. Jittery power might
|
||||
// fail before we're ready. This can happen if someone
|
||||
@ -129,10 +130,10 @@ void init_flash_fs(bool create_allowed) {
|
||||
|
||||
// Then try one more time to mount the flash in case it was late coming up.
|
||||
res = f_mount(&vfs_fat->fatfs);
|
||||
if (res == FR_NO_FILESYSTEM) {
|
||||
if (res == FR_NO_FILESYSTEM || force_create) {
|
||||
uint8_t working_buf[_MAX_SS];
|
||||
res = f_mkfs(&vfs_fat->fatfs, FM_FAT, 0, working_buf, sizeof(working_buf));
|
||||
// Flush the new file system to make sure its repaired immediately.
|
||||
// Flush the new file system to make sure it's repaired immediately.
|
||||
flash_flush();
|
||||
if (res != FR_OK) {
|
||||
return;
|
||||
@ -528,6 +529,14 @@ void load_serial_number(void) {
|
||||
extern uint32_t _ezero;
|
||||
|
||||
safe_mode_t samd21_init(void) {
|
||||
|
||||
// Set brownout detection to ~2.7V. Default from factory is 1.7V,
|
||||
// which is too low for proper operation of external SPI flash chips (they are 2.7-3.6V).
|
||||
// Disable while changing level.
|
||||
SYSCTRL->BOD33.bit.ENABLE = 0;
|
||||
SYSCTRL->BOD33.bit.LEVEL = 39; // 2.77V with hysteresis off. Table 37.20 in datasheet.
|
||||
SYSCTRL->BOD33.bit.ENABLE = 1;
|
||||
|
||||
#ifdef ENABLE_MICRO_TRACE_BUFFER
|
||||
REG_MTB_POSITION = ((uint32_t) (mtb - REG_MTB_BASE)) & 0xFFFFFFF8;
|
||||
REG_MTB_FLOW = (((uint32_t) mtb - REG_MTB_BASE) + TRACE_BUFFER_SIZE_BYTES) & 0xFFFFFFF8;
|
||||
@ -683,9 +692,9 @@ int main(void) {
|
||||
// Create a new filesystem only if we're not in a safe mode.
|
||||
// A power brownout here could make it appear as if there's
|
||||
// no SPI flash filesystem, and we might erase the existing one.
|
||||
init_flash_fs(safe_mode == NO_SAFE_MODE);
|
||||
init_flash_fs(safe_mode == NO_SAFE_MODE, false);
|
||||
|
||||
// Reset everything and prep MicroPython to run boot.py.
|
||||
// Reset everything and prep to run boot.py.
|
||||
reset_samd21();
|
||||
reset_board();
|
||||
reset_mp();
|
||||
@ -694,38 +703,83 @@ int main(void) {
|
||||
autoreload_enable();
|
||||
|
||||
// By default our internal flash is readonly to local python code and
|
||||
// writeable over USB. Set it here so that boot.py can change it.
|
||||
// writable over USB.
|
||||
flash_set_usb_writeable(true);
|
||||
|
||||
// If not in safe mode, run boot before initing USB and capture output in a
|
||||
// file.
|
||||
if (safe_mode == NO_SAFE_MODE && MP_STATE_VM(vfs_mount_table) != NULL) {
|
||||
new_status_color(BOOT_RUNNING);
|
||||
|
||||
// Run the first of these files found at boot time (if any).
|
||||
static char const* BOOT_PY_FILENAMES[] = {
|
||||
"settings.txt",
|
||||
"settings.py",
|
||||
"boot.py",
|
||||
"boot.txt",
|
||||
};
|
||||
|
||||
// Check for existance of any of the BOOT_PY_FILENAMES.
|
||||
char const* boot_py_to_use = NULL;
|
||||
for (size_t i = 0; i < MP_ARRAY_SIZE(BOOT_PY_FILENAMES); i++) {
|
||||
if (mp_import_stat(BOOT_PY_FILENAMES[i]) == MP_IMPORT_STAT_FILE) {
|
||||
boot_py_to_use = BOOT_PY_FILENAMES[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CIRCUITPY_BOOT_OUTPUT_FILE
|
||||
// Since USB isn't up yet we can cheat and let ourselves write the boot
|
||||
// output file.
|
||||
flash_set_usb_writeable(false);
|
||||
FIL file_pointer;
|
||||
boot_output_file = &file_pointer;
|
||||
f_open(&((fs_user_mount_t *) MP_STATE_VM(vfs_mount_table)->obj)->fatfs,
|
||||
boot_output_file, CIRCUITPY_BOOT_OUTPUT_FILE, FA_WRITE | FA_CREATE_ALWAYS);
|
||||
flash_set_usb_writeable(true);
|
||||
// Write version info to boot_out.txt.
|
||||
mp_hal_stdout_tx_str(MICROPY_FULL_VERSION_INFO);
|
||||
mp_hal_stdout_tx_str("\r\n");
|
||||
|
||||
// Get the base filesystem.
|
||||
FATFS *fs = &((fs_user_mount_t *) MP_STATE_VM(vfs_mount_table)->obj)->fatfs;
|
||||
|
||||
char file_contents[512];
|
||||
UINT chars_read = 0;
|
||||
bool skip_boot_output = false;
|
||||
|
||||
// If there's no boot.py file that might write some changing output,
|
||||
// read the existing copy of CIRCUITPY_BOOT_OUTPUT_FILE and see if its contents
|
||||
// match the version info we would print anyway. If so, skip writing CIRCUITPY_BOOT_OUTPUT_FILE.
|
||||
// This saves wear and tear on the flash and also prevents filesystem damage if power is lost
|
||||
// during the write, which may happen due to bobbling the power connector or weak power.
|
||||
|
||||
if (!boot_py_to_use && f_open(fs, boot_output_file, CIRCUITPY_BOOT_OUTPUT_FILE, FA_READ) == FR_OK) {
|
||||
f_read(boot_output_file, file_contents, 512, &chars_read);
|
||||
f_close(boot_output_file);
|
||||
skip_boot_output =
|
||||
// + 2 accounts for \r\n.
|
||||
chars_read == strlen(MICROPY_FULL_VERSION_INFO) + 2 &&
|
||||
strncmp(file_contents, MICROPY_FULL_VERSION_INFO, strlen(MICROPY_FULL_VERSION_INFO)) == 0;
|
||||
}
|
||||
|
||||
if (!skip_boot_output) {
|
||||
// Wait 1.5 seconds before opening CIRCUITPY_BOOT_OUTPUT_FILE for write,
|
||||
// in case power is momentary or will fail shortly due to, say a low, battery.
|
||||
mp_hal_delay_ms(1500);
|
||||
|
||||
// USB isn't up, so we can write the file.
|
||||
flash_set_usb_writeable(false);
|
||||
f_open(fs, boot_output_file, CIRCUITPY_BOOT_OUTPUT_FILE, FA_WRITE | FA_CREATE_ALWAYS);
|
||||
// Write version info to boot_out.txt.
|
||||
mp_hal_stdout_tx_str(MICROPY_FULL_VERSION_INFO);
|
||||
mp_hal_stdout_tx_str("\r\n");
|
||||
}
|
||||
#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;
|
||||
if (boot_py_to_use) {
|
||||
maybe_run(boot_py_to_use, NULL);
|
||||
}
|
||||
|
||||
#ifdef CIRCUITPY_BOOT_OUTPUT_FILE
|
||||
f_close(boot_output_file);
|
||||
flash_flush();
|
||||
boot_output_file = NULL;
|
||||
if (!skip_boot_output) {
|
||||
f_close(boot_output_file);
|
||||
flash_flush();
|
||||
boot_output_file = NULL;
|
||||
}
|
||||
flash_set_usb_writeable(true);
|
||||
#endif
|
||||
|
||||
// Reset to remove any state that boot.py setup. It should only be used to
|
||||
|
30
atmel-samd/main.h
Normal file
30
atmel-samd/main.h
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 Dan Halbert 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.
|
||||
*/
|
||||
|
||||
// Functions defined in main.c that are useful elsewhere.
|
||||
// Eventually they should be factored out.
|
||||
|
||||
void init_flash_fs(bool create_allowed, bool force_create);
|
@ -32,3 +32,7 @@
|
||||
void common_hal_storage_remount(const char* mount_path, bool readonly) {
|
||||
mp_raise_NotImplementedError("");
|
||||
}
|
||||
|
||||
void common_hal_storage_erase_filesystem() {
|
||||
mp_raise_NotImplementedError("Use esptool to erase flash and re-upload Python instead");
|
||||
}
|
||||
|
@ -115,12 +115,32 @@ mp_obj_t storage_remount(mp_obj_t mount_path, mp_obj_t readonly) {
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(storage_remount_obj, storage_remount);
|
||||
|
||||
//| .. function:: erase_filesystem()
|
||||
//|
|
||||
//| Erase and re-create the ``CIRCUITPY`` filesystem. Then call
|
||||
//| `microcontroller.reset()` to restart CircuitPython and have the
|
||||
//| host computer remount CIRCUITPY.
|
||||
//|
|
||||
//| This function can be called from the REPL when ``CIRCUITPY``
|
||||
//| has become corrupted.
|
||||
//|
|
||||
//| .. warning:: All the data on ``CIRCUITPY`` will be lost, and
|
||||
//| CircuitPython will restart.
|
||||
|
||||
mp_obj_t storage_erase_filesystem(void) {
|
||||
common_hal_storage_erase_filesystem();
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(storage_erase_filesystem_obj, storage_erase_filesystem);
|
||||
|
||||
|
||||
STATIC const mp_rom_map_elem_t storage_module_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_storage) },
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&storage_mount_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&storage_umount_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_remount), MP_ROM_PTR(&storage_remount_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_erase_filesystem), MP_ROM_PTR(&storage_erase_filesystem_obj) },
|
||||
|
||||
//| .. class:: VfsFat(block_device)
|
||||
//|
|
||||
|
@ -34,5 +34,6 @@ void common_hal_storage_mount(mp_obj_t vfs_obj, const char* path, bool readonly)
|
||||
void common_hal_storage_umount_path(const char* path);
|
||||
void common_hal_storage_umount_object(mp_obj_t vfs_obj);
|
||||
void common_hal_storage_remount(const char* path, bool readonly);
|
||||
void common_hal_storage_erase_filesystem(void);
|
||||
|
||||
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_STORAGE___INIT___H
|
||||
|
Loading…
Reference in New Issue
Block a user