Adafruit_SPIFlash/examples/SdFat_circuitpython_backupFiles/SdFat_circuitpython_backupFiles.ino
2025-03-11 15:43:46 +00:00

162 lines
4.3 KiB
C++

// Adafruit M0 Express CircuitPython Repair
// Author: Limor Fried
//
/*
* This script can be useful if you seriously bork up your CircuitPython
* install. It will find any files named main.py, boot.py, main.txt, code.py
* or code.txt and move them to backup files. its a tad slow but then you
* can reload circuitpython safely. This example right now is only for
* the Metro M0 Express & Circuit Playground M0 but i have a...
*
* TODO: automagically detect if it's Feather/Metro/CircuitPlayground!
*/
#include "SdFat_Adafruit_Fork.h"
#include <SPI.h>
#include <Adafruit_NeoPixel.h>
#include <Adafruit_SPIFlash.h>
// for flashTransport definition
#include "flash_config.h"
Adafruit_SPIFlash flash(&flashTransport);
// file system object from SdFat
FatVolume fatfs;
#define NEOPIN 40 // neopixel pin
#define BUFFERSIZ 200
Adafruit_NeoPixel pixel = Adafruit_NeoPixel(1, NEOPIN, NEO_GRB + NEO_KHZ800);
void setup() {
Serial.begin(115200);
// while (!Serial);
delay(1000); // small delay in case we want to watch it on the serial port
Serial.println("Adafruit Express CircuitPython Flash Repair");
pixel.begin(); // This initializes the NeoPixel library
pixel.setBrightness(30); // not too bright!
// Initialize flash library and check its chip ID.
if (!flash.begin()) {
Serial.println("Error, failed to initialize flash chip!");
error(1);
}
Serial.print("Flash chip JEDEC ID: 0x");
Serial.println(flash.getJEDECID(), HEX);
// First call begin to mount the filesystem. Check that it returns true
// to make sure the filesystem was mounted.
if (!fatfs.begin(&flash)) {
Serial.println("Failed to mount filesystem!");
Serial.println("Was CircuitPython loaded on the board first to create the "
"filesystem?");
error(3);
}
Serial.println("Mounted filesystem!");
moveFile("boot.py", "bootpy.bak");
moveFile("main.py", "mainpy.bak");
moveFile("main.txt", "maintxt.bak");
moveFile("code.py", "codepy.bak");
moveFile("code.txt", "codetxt.bak");
Serial.println("Finished!");
}
uint8_t i = 0;
void loop() {
// white pixel pulse -> we're done
pixel.setPixelColor(0, pixel.Color(i, i, i));
pixel.show();
i++;
delay(5);
}
boolean moveFile(const char *file, const char *dest) {
if (!fatfs.exists(file)) {
Serial.print(file);
Serial.println(" not found");
return false;
}
if (fatfs.exists(dest)) {
Serial.println("Found old backup, removing...");
if (!fatfs.remove(dest)) {
Serial.println("Error, couldn't delete ");
Serial.print(dest);
Serial.println(" file!");
error(4);
}
}
pixel.setPixelColor(0, pixel.Color(100, 100, 0));
pixel.show();
File32 source = fatfs.open(file, FILE_READ);
File32 backup = fatfs.open(dest, FILE_WRITE);
Serial.println("Making backup!");
Serial.println("\n---------------------\n");
while (1) {
int avail = source.available();
// Serial.print("**Available bytes: "); Serial.print(avail);
// Serial.print("**");
if (avail == 0) {
Serial.println("\n---------------------\n");
break;
}
int toread = min(BUFFERSIZ - 1, avail);
char buffer[BUFFERSIZ];
int numread = source.read(buffer, toread);
if (numread != toread) {
Serial.print("Failed to read ");
Serial.print(toread);
Serial.print(" bytes, got ");
Serial.print(numread);
error(5);
}
buffer[toread] = 0;
Serial.print(buffer);
if ((int)backup.write(buffer, toread) != toread) {
Serial.println("Error, couldn't write data to backup file!");
error(6);
}
}
pixel.setPixelColor(0, pixel.Color(100, 0, 100));
pixel.show();
Serial.print("Original file size: ");
Serial.println(source.size());
Serial.print("Backup file size: ");
Serial.println(backup.size());
backup.close();
if (source.size() == backup.size()) {
if (!fatfs.remove(file)) {
Serial.print("Error, couldn't delete ");
Serial.println(file);
error(10);
}
}
pixel.setPixelColor(0, pixel.Color(0, 100, 0));
pixel.show();
delay(100);
return true;
}
void error(uint8_t i) {
while (1) {
for (int x = 0; x < i; x++) {
pixel.setPixelColor(0, pixel.Color(100, 0, 0));
pixel.show();
delay(200);
pixel.setPixelColor(0, pixel.Color(0, 0, 0));
pixel.show();
delay(200);
}
delay(1000);
}
}