66
66
67
67
#include "autoreload.h"
68
68
#include "flash_api.h"
69
+ #include "main.h"
69
70
#include "mpconfigboard.h"
70
71
#include "rgb_led_status.h"
71
72
#include "shared_dma.h"
@@ -110,7 +111,7 @@ void do_str(const char *src, mp_parse_input_kind_t input_kind) {
110
111
111
112
// we don't make this function static because it needs a lot of stack and we
112
113
// want it to be executed without using stack within main() function
113
- void init_flash_fs (bool create_allowed ) {
114
+ void init_flash_fs (bool create_allowed , bool force_create ) {
114
115
// init the vfs object
115
116
fs_user_mount_t * vfs_fat = & fs_user_mount_flash ;
116
117
vfs_fat -> flags = 0 ;
@@ -119,8 +120,8 @@ void init_flash_fs(bool create_allowed) {
119
120
// try to mount the flash
120
121
FRESULT res = f_mount (& vfs_fat -> fatfs );
121
122
122
- if (res == FR_NO_FILESYSTEM && create_allowed ) {
123
- // no filesystem so create a fresh one
123
+ if (( res == FR_NO_FILESYSTEM && create_allowed ) || force_create ) {
124
+ // No filesystem so create a fresh one, or reformat has been requested.
124
125
125
126
// Wait two seconds before creating. Jittery power might
126
127
// fail before we're ready. This can happen if someone
@@ -129,10 +130,10 @@ void init_flash_fs(bool create_allowed) {
129
130
130
131
// Then try one more time to mount the flash in case it was late coming up.
131
132
res = f_mount (& vfs_fat -> fatfs );
132
- if (res == FR_NO_FILESYSTEM ) {
133
+ if (res == FR_NO_FILESYSTEM || force_create ) {
133
134
uint8_t working_buf [_MAX_SS ];
134
135
res = f_mkfs (& vfs_fat -> fatfs , FM_FAT , 0 , working_buf , sizeof (working_buf ));
135
- // Flush the new file system to make sure its repaired immediately.
136
+ // Flush the new file system to make sure it's repaired immediately.
136
137
flash_flush ();
137
138
if (res != FR_OK ) {
138
139
return ;
@@ -528,6 +529,14 @@ void load_serial_number(void) {
528
529
extern uint32_t _ezero ;
529
530
530
531
safe_mode_t samd21_init (void ) {
532
+
533
+ // Set brownout detection to ~2.7V. Default from factory is 1.7V,
534
+ // which is too low for proper operation of external SPI flash chips (they are 2.7-3.6V).
535
+ // Disable while changing level.
536
+ SYSCTRL -> BOD33 .bit .ENABLE = 0 ;
537
+ SYSCTRL -> BOD33 .bit .LEVEL = 39 ; // 2.77V with hysteresis off. Table 37.20 in datasheet.
538
+ SYSCTRL -> BOD33 .bit .ENABLE = 1 ;
539
+
531
540
#ifdef ENABLE_MICRO_TRACE_BUFFER
532
541
REG_MTB_POSITION = ((uint32_t ) (mtb - REG_MTB_BASE )) & 0xFFFFFFF8 ;
533
542
REG_MTB_FLOW = (((uint32_t ) mtb - REG_MTB_BASE ) + TRACE_BUFFER_SIZE_BYTES ) & 0xFFFFFFF8 ;
@@ -683,9 +692,9 @@ int main(void) {
683
692
// Create a new filesystem only if we're not in a safe mode.
684
693
// A power brownout here could make it appear as if there's
685
694
// no SPI flash filesystem, and we might erase the existing one.
686
- init_flash_fs (safe_mode == NO_SAFE_MODE );
695
+ init_flash_fs (safe_mode == NO_SAFE_MODE , false );
687
696
688
- // Reset everything and prep MicroPython to run boot.py.
697
+ // Reset everything and prep to run boot.py.
689
698
reset_samd21 ();
690
699
reset_board ();
691
700
reset_mp ();
@@ -694,38 +703,83 @@ int main(void) {
694
703
autoreload_enable ();
695
704
696
705
// By default our internal flash is readonly to local python code and
697
- // writeable over USB. Set it here so that boot.py can change it .
706
+ // writable over USB.
698
707
flash_set_usb_writeable (true);
699
708
700
709
// If not in safe mode, run boot before initing USB and capture output in a
701
710
// file.
702
711
if (safe_mode == NO_SAFE_MODE && MP_STATE_VM (vfs_mount_table ) != NULL ) {
703
712
new_status_color (BOOT_RUNNING );
713
+
714
+ // Run the first of these files found at boot time (if any).
715
+ static char const * BOOT_PY_FILENAMES [] = {
716
+ "settings.txt" ,
717
+ "settings.py" ,
718
+ "boot.py" ,
719
+ "boot.txt" ,
720
+ };
721
+
722
+ // Check for existance of any of the BOOT_PY_FILENAMES.
723
+ char const * boot_py_to_use = NULL ;
724
+ for (size_t i = 0 ; i < MP_ARRAY_SIZE (BOOT_PY_FILENAMES ); i ++ ) {
725
+ if (mp_import_stat (BOOT_PY_FILENAMES [i ]) == MP_IMPORT_STAT_FILE ) {
726
+ boot_py_to_use = BOOT_PY_FILENAMES [i ];
727
+ break ;
728
+ }
729
+ }
730
+
704
731
#ifdef CIRCUITPY_BOOT_OUTPUT_FILE
705
- // Since USB isn't up yet we can cheat and let ourselves write the boot
706
- // output file.
707
- flash_set_usb_writeable (false);
708
732
FIL file_pointer ;
709
733
boot_output_file = & file_pointer ;
710
- f_open (& ((fs_user_mount_t * ) MP_STATE_VM (vfs_mount_table )-> obj )-> fatfs ,
711
- boot_output_file , CIRCUITPY_BOOT_OUTPUT_FILE , FA_WRITE | FA_CREATE_ALWAYS );
712
- flash_set_usb_writeable (true);
713
- // Write version info to boot_out.txt.
714
- mp_hal_stdout_tx_str (MICROPY_FULL_VERSION_INFO );
715
- mp_hal_stdout_tx_str ("\r\n" );
734
+
735
+ // Get the base filesystem.
736
+ FATFS * fs = & ((fs_user_mount_t * ) MP_STATE_VM (vfs_mount_table )-> obj )-> fatfs ;
737
+
738
+ char file_contents [512 ];
739
+ UINT chars_read = 0 ;
740
+ bool skip_boot_output = false;
741
+
742
+ // If there's no boot.py file that might write some changing output,
743
+ // read the existing copy of CIRCUITPY_BOOT_OUTPUT_FILE and see if its contents
744
+ // match the version info we would print anyway. If so, skip writing CIRCUITPY_BOOT_OUTPUT_FILE.
745
+ // This saves wear and tear on the flash and also prevents filesystem damage if power is lost
746
+ // during the write, which may happen due to bobbling the power connector or weak power.
747
+
748
+ if (!boot_py_to_use && f_open (fs , boot_output_file , CIRCUITPY_BOOT_OUTPUT_FILE , FA_READ ) == FR_OK ) {
749
+ f_read (boot_output_file , file_contents , 512 , & chars_read );
750
+ f_close (boot_output_file );
751
+ skip_boot_output =
752
+ // + 2 accounts for \r\n.
753
+ chars_read == strlen (MICROPY_FULL_VERSION_INFO ) + 2 &&
754
+ strncmp (file_contents , MICROPY_FULL_VERSION_INFO , strlen (MICROPY_FULL_VERSION_INFO )) == 0 ;
755
+ }
756
+
757
+ if (!skip_boot_output ) {
758
+ // Wait 1.5 seconds before opening CIRCUITPY_BOOT_OUTPUT_FILE for write,
759
+ // in case power is momentary or will fail shortly due to, say a low, battery.
760
+ mp_hal_delay_ms (1500 );
761
+
762
+ // USB isn't up, so we can write the file.
763
+ flash_set_usb_writeable (false);
764
+ f_open (fs , boot_output_file , CIRCUITPY_BOOT_OUTPUT_FILE , FA_WRITE | FA_CREATE_ALWAYS );
765
+ // Write version info to boot_out.txt.
766
+ mp_hal_stdout_tx_str (MICROPY_FULL_VERSION_INFO );
767
+ mp_hal_stdout_tx_str ("\r\n" );
768
+ }
716
769
#endif
717
770
718
771
// TODO(tannewt): Re-add support for flashing boot error output.
719
- bool found_boot = maybe_run ("settings.txt" , NULL ) ||
720
- maybe_run ("settings.py" , NULL ) ||
721
- maybe_run ("boot.py" , NULL ) ||
722
- maybe_run ("boot.txt" , NULL );
723
- (void ) found_boot ;
772
+ if (boot_py_to_use ) {
773
+ maybe_run (boot_py_to_use , NULL );
774
+ }
724
775
725
776
#ifdef CIRCUITPY_BOOT_OUTPUT_FILE
726
- f_close (boot_output_file );
727
- flash_flush ();
728
- boot_output_file = NULL ;
777
+ if (!skip_boot_output ) {
778
+ f_close (boot_output_file );
779
+ flash_flush ();
780
+ boot_output_file = NULL ;
781
+ }
782
+ flash_set_usb_writeable (true);
729
783
#endif
730
784
731
785
// Reset to remove any state that boot.py setup. It should only be used to
0 commit comments