diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index d90a7c2e4f..943acd4943 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -229,6 +229,7 @@ SRC_C = \ systick.c \ powerctrl.c \ pybthread.c \ + factoryreset.c \ timer.c \ led.c \ pin.c \ diff --git a/ports/stm32/factoryreset.c b/ports/stm32/factoryreset.c new file mode 100644 index 0000000000..6b0c289a78 --- /dev/null +++ b/ports/stm32/factoryreset.c @@ -0,0 +1,98 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013-2019 Damien P. George + * + * 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/runtime.h" +#include "factoryreset.h" + +#if MICROPY_HW_ENABLE_STORAGE + +static const char fresh_boot_py[] = +"# boot.py -- run on boot-up\r\n" +"# can run arbitrary Python, but best to keep it minimal\r\n" +"\r\n" +"import machine\r\n" +"import pyb\r\n" +"#pyb.main('main.py') # main script to run after this one\r\n" +#if MICROPY_HW_ENABLE_USB +"#pyb.usb_mode('VCP+MSC') # act as a serial and a storage device\r\n" +"#pyb.usb_mode('VCP+HID') # act as a serial device and a mouse\r\n" +#endif +; + +static const char fresh_main_py[] = +"# main.py -- put your code here!\r\n" +; + +#if MICROPY_HW_ENABLE_USB +static const char fresh_pybcdc_inf[] = +#include "genhdr/pybcdc_inf.h" +; + +static const char fresh_readme_txt[] = +"This is a MicroPython board\r\n" +"\r\n" +"You can get started right away by writing your Python code in 'main.py'.\r\n" +"\r\n" +"For a serial prompt:\r\n" +" - Windows: you need to go to 'Device manager', right click on the unknown device,\r\n" +" then update the driver software, using the 'pybcdc.inf' file found on this drive.\r\n" +" Then use a terminal program like Hyperterminal or putty.\r\n" +" - Mac OS X: use the command: screen /dev/tty.usbmodem*\r\n" +" - Linux: use the command: screen /dev/ttyACM0\r\n" +"\r\n" +"Please visit http://micropython.org/help/ for further help.\r\n" +; +#endif + +typedef struct _factory_file_t { + const char *name; + size_t len; + const char *data; +} factory_file_t; + +static const factory_file_t factory_files[] = { + {"boot.py", sizeof(fresh_boot_py) - 1, fresh_boot_py}, + {"main.py", sizeof(fresh_main_py) - 1, fresh_main_py}, + #if MICROPY_HW_ENABLE_USB + {"pybcdc.inf", sizeof(fresh_pybcdc_inf) - 1, fresh_pybcdc_inf}, + {"README.txt", sizeof(fresh_readme_txt) - 1, fresh_readme_txt}, + #endif +}; + +MP_WEAK void factory_reset_make_files(FATFS *fatfs) { + for (int i = 0; i < MP_ARRAY_SIZE(factory_files); ++i) { + const factory_file_t *f = &factory_files[i]; + FIL fp; + FRESULT res = f_open(fatfs, &fp, f->name, FA_WRITE | FA_CREATE_ALWAYS); + if (res == FR_OK) { + UINT n; + f_write(&fp, f->data, f->len, &n); + f_close(&fp); + } + } +} + +#endif // MICROPY_HW_ENABLE_STORAGE diff --git a/ports/stm32/factoryreset.h b/ports/stm32/factoryreset.h new file mode 100644 index 0000000000..85226f880b --- /dev/null +++ b/ports/stm32/factoryreset.h @@ -0,0 +1,33 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Damien P. George + * + * 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. + */ +#ifndef MICROPY_INCLUDED_STM32_FACTORYRESET_H +#define MICROPY_INCLUDED_STM32_FACTORYRESET_H + +#include "lib/oofatfs/ff.h" + +void factory_reset_make_files(FATFS *fatfs); + +#endif // MICROPY_INCLUDED_STM32_FACTORYRESET_H diff --git a/ports/stm32/main.c b/ports/stm32/main.c index a37c6f8979..ff4589f9d4 100644 --- a/ports/stm32/main.c +++ b/ports/stm32/main.c @@ -45,6 +45,7 @@ #include "pendsv.h" #include "pybthread.h" #include "gccollect.h" +#include "factoryreset.h" #include "modmachine.h" #include "i2c.h" #include "spi.h" @@ -148,42 +149,6 @@ STATIC mp_obj_t pyb_main(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_a MP_DEFINE_CONST_FUN_OBJ_KW(pyb_main_obj, 1, pyb_main); #if MICROPY_HW_ENABLE_STORAGE -static const char fresh_boot_py[] = -"# boot.py -- run on boot-up\r\n" -"# can run arbitrary Python, but best to keep it minimal\r\n" -"\r\n" -"import machine\r\n" -"import pyb\r\n" -"#pyb.main('main.py') # main script to run after this one\r\n" -#if MICROPY_HW_ENABLE_USB -"#pyb.usb_mode('VCP+MSC') # act as a serial and a storage device\r\n" -"#pyb.usb_mode('VCP+HID') # act as a serial device and a mouse\r\n" -#endif -; - -static const char fresh_main_py[] = -"# main.py -- put your code here!\r\n" -; - -static const char fresh_pybcdc_inf[] = -#include "genhdr/pybcdc_inf.h" -; - -static const char fresh_readme_txt[] = -"This is a MicroPython board\r\n" -"\r\n" -"You can get started right away by writing your Python code in 'main.py'.\r\n" -"\r\n" -"For a serial prompt:\r\n" -" - Windows: you need to go to 'Device manager', right click on the unknown device,\r\n" -" then update the driver software, using the 'pybcdc.inf' file found on this drive.\r\n" -" Then use a terminal program like Hyperterminal or putty.\r\n" -" - Mac OS X: use the command: screen /dev/tty.usbmodem*\r\n" -" - Linux: use the command: screen /dev/ttyACM0\r\n" -"\r\n" -"Please visit http://micropython.org/help/ for further help.\r\n" -; - // avoid inlining to avoid stack usage within main() MP_NOINLINE STATIC bool init_flash_fs(uint reset_mode) { // init the vfs object @@ -213,23 +178,8 @@ MP_NOINLINE STATIC bool init_flash_fs(uint reset_mode) { // set label f_setlabel(&vfs_fat->fatfs, MICROPY_HW_FLASH_FS_LABEL); - // create empty main.py - FIL fp; - f_open(&vfs_fat->fatfs, &fp, "/main.py", FA_WRITE | FA_CREATE_ALWAYS); - UINT n; - f_write(&fp, fresh_main_py, sizeof(fresh_main_py) - 1 /* don't count null terminator */, &n); - // TODO check we could write n bytes - f_close(&fp); - - // create .inf driver file - f_open(&vfs_fat->fatfs, &fp, "/pybcdc.inf", FA_WRITE | FA_CREATE_ALWAYS); - f_write(&fp, fresh_pybcdc_inf, sizeof(fresh_pybcdc_inf) - 1 /* don't count null terminator */, &n); - f_close(&fp); - - // create readme file - f_open(&vfs_fat->fatfs, &fp, "/README.txt", FA_WRITE | FA_CREATE_ALWAYS); - f_write(&fp, fresh_readme_txt, sizeof(fresh_readme_txt) - 1 /* don't count null terminator */, &n); - f_close(&fp); + // populate the filesystem with factory files + factory_reset_make_files(&vfs_fat->fatfs); // keep LED on for at least 200ms systick_wait_at_least(start_tick, 200); @@ -258,28 +208,6 @@ MP_NOINLINE STATIC bool init_flash_fs(uint reset_mode) { // It is set to the internal flash filesystem by default. MP_STATE_PORT(vfs_cur) = vfs; - // Make sure we have a /flash/boot.py. Create it if needed. - FILINFO fno; - res = f_stat(&vfs_fat->fatfs, "/boot.py", &fno); - if (res != FR_OK) { - // doesn't exist, create fresh file - - // LED on to indicate creation of boot.py - led_state(PYB_LED_GREEN, 1); - uint32_t start_tick = HAL_GetTick(); - - FIL fp; - f_open(&vfs_fat->fatfs, &fp, "/boot.py", FA_WRITE | FA_CREATE_ALWAYS); - UINT n; - f_write(&fp, fresh_boot_py, sizeof(fresh_boot_py) - 1 /* don't count null terminator */, &n); - // TODO check we could write n bytes - f_close(&fp); - - // keep LED on for at least 200ms - systick_wait_at_least(start_tick, 200); - led_state(PYB_LED_GREEN, 0); - } - return true; } #endif