Thanks to visit codestin.com
Credit goes to github.com

Skip to content

2.x: handle bad power on reset better #802

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 4, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions atmel-samd/asf/sam0/drivers/tc/tc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
}
Expand All @@ -1171,6 +1173,7 @@ static inline void tc_enable_events(
}

tc_module->COUNT8.EVCTRL.reg |= event_mask | events->event_action;
#pragma GCC diagnostic pop
}

/**
Expand Down
8 changes: 8 additions & 0 deletions atmel-samd/common-hal/storage/__init__.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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.
}
104 changes: 79 additions & 25 deletions atmel-samd/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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;
Expand All @@ -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
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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();
Expand All @@ -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
Expand Down
30 changes: 30 additions & 0 deletions atmel-samd/main.h
Original file line number Diff line number Diff line change
@@ -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);
4 changes: 4 additions & 0 deletions esp8266/common-hal/storage/__init__.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}
20 changes: 20 additions & 0 deletions shared-bindings/storage/__init__.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
//|
Expand Down
1 change: 1 addition & 0 deletions shared-bindings/storage/__init__.h
Original file line number Diff line number Diff line change
Expand Up @@ -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