Skip to content

Commit 8e7b7ad

Browse files
committed
Add firmware update from SD example
1 parent d132e48 commit 8e7b7ad

File tree

5 files changed

+411
-0
lines changed

5 files changed

+411
-0
lines changed
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
Demonstrates reading a binary file from SD and reprogramming ESP32.
3+
4+
To work, we must the use a partition scheme that includes OTA.
5+
For RTK Surveyor, 'Minimal SPIFFS (1.9MB with OTA/190KB SPIFFS)' works well.
6+
*/
7+
8+
#include <Update.h>
9+
10+
#include "settings.h"
11+
12+
const byte PIN_MICROSD_CHIP_SELECT = 25;
13+
14+
//microSD Interface
15+
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
16+
#include <SPI.h>
17+
#include <SdFat.h> //SdFat (FAT32) by Bill Greiman: http://librarymanager/All#SdFat
18+
SdFat sd;
19+
SdFile gnssDataFile; //File that all gnss data is written to
20+
21+
char settingsFileName[40] = "SFE_Surveyor_Settings.txt"; //File to read/write system settings to
22+
23+
unsigned long lastDataLogSyncTime = 0; //Used to record to SD every half second
24+
long startLogTime_minutes = 0; //Mark when we start logging so we can stop logging after maxLogTime_minutes
25+
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
26+
27+
const byte menuTimeout = 15; //Menus will exit/timeout after this number of seconds
28+
29+
int binCount = 0;
30+
char binFileNames[10][50];
31+
const char* forceFirmwareFileName = "RTK_Surveyor_Firmware_Force.bin";
32+
33+
void setup() {
34+
Serial.begin(115200);
35+
delay(100);
36+
Serial.println("SD Update");
37+
38+
beginSD(); //Test if SD is present
39+
40+
if (online.microSD == true)
41+
{
42+
Serial.println("SD online");
43+
scanForFirmware();
44+
}
45+
}
46+
47+
48+
void loop() {
49+
if (Serial.available())
50+
{
51+
byte incoming = Serial.read();
52+
53+
if (incoming == '1')
54+
{
55+
menuFirmware();
56+
}
57+
else
58+
{
59+
Serial.println("Unknown command");
60+
}
61+
62+
delay(10);
63+
while (Serial.available()) Serial.read(); //Remote extra chars
64+
}
65+
66+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
void beginSD()
2+
{
3+
pinMode(PIN_MICROSD_CHIP_SELECT, OUTPUT);
4+
digitalWrite(PIN_MICROSD_CHIP_SELECT, HIGH); //Be sure SD is deselected
5+
6+
if (settings.enableSD == true)
7+
{
8+
//Max power up time is 250ms: https://www.kingston.com/datasheets/SDCIT-specsheet-64gb_en.pdf
9+
//Max current is 200mA average across 1s, peak 300mA
10+
delay(10);
11+
12+
if (sd.begin(PIN_MICROSD_CHIP_SELECT, SD_SCK_MHZ(24)) == false) //Standard SdFat
13+
{
14+
Serial.println("SD init failed (first attempt). Trying again...\r\n");
15+
//Give SD more time to power up, then try again
16+
delay(250);
17+
if (sd.begin(PIN_MICROSD_CHIP_SELECT, SD_SCK_MHZ(24)) == false) //Standard SdFat
18+
{
19+
Serial.println(F("SD init failed (second attempt). Is card present? Formatted?"));
20+
digitalWrite(PIN_MICROSD_CHIP_SELECT, HIGH); //Be sure SD is deselected
21+
online.microSD = false;
22+
return;
23+
}
24+
}
25+
26+
//Change to root directory. All new file creation will be in root.
27+
if (sd.chdir() == false)
28+
{
29+
Serial.println(F("SD change directory failed"));
30+
online.microSD = false;
31+
return;
32+
}
33+
34+
online.microSD = true;
35+
}
36+
else
37+
{
38+
online.microSD = false;
39+
}
40+
}
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
//Update firmware if bin files found
2+
void menuFirmware()
3+
{
4+
if (online.microSD == false)
5+
{
6+
Serial.println(F("No SD card detected"));
7+
}
8+
9+
if (binCount == 0)
10+
{
11+
Serial.println("No valid binary files found.");
12+
delay(2000);
13+
return;
14+
}
15+
16+
while (1)
17+
{
18+
Serial.println();
19+
Serial.println(F("Menu: Update Firmware Menu"));
20+
21+
for (int x = 0 ; x < binCount ; x++)
22+
{
23+
Serial.printf("%d) Load %s\n", x + 1, binFileNames[x]);
24+
}
25+
26+
Serial.println(F("x) Exit"));
27+
28+
int incoming = getNumber(menuTimeout); //Timeout after x seconds
29+
30+
if (incoming > 0 && incoming < (binCount + 1))
31+
{
32+
//Adjust incoming to match array
33+
incoming--;
34+
Serial.printf("Loading %s\n", binFileNames[incoming]);
35+
updateFromSD(binFileNames[incoming]);
36+
}
37+
else if (incoming == STATUS_PRESSED_X)
38+
break;
39+
else if (incoming == STATUS_GETNUMBER_TIMEOUT)
40+
break;
41+
else
42+
Serial.printf("Bad value: %d\n", incoming);
43+
}
44+
45+
while (Serial.available()) Serial.read(); //Empty buffer of any newline chars
46+
}
47+
48+
//Looks for matching binary files in root
49+
//Loads a global called binCount
50+
void scanForFirmware()
51+
{
52+
if (online.microSD == true)
53+
{
54+
//Count available binaries
55+
SdFile tempFile;
56+
SdFile dir;
57+
const char* BIN_EXT = "bin";
58+
const char* BIN_HEADER = "RTK_Surveyor_Firmware";
59+
char fname[50]; //Handle long file names
60+
61+
dir.open("/"); //Open root
62+
63+
while (tempFile.openNext(&dir, O_READ))
64+
{
65+
if (tempFile.isFile())
66+
{
67+
tempFile.getName(fname, sizeof(fname));
68+
69+
if (strcmp(forceFirmwareFileName, fname) == 0)
70+
updateFromSD((char *)forceFirmwareFileName);
71+
72+
//Check for 'sfe_rtk' and 'bin' extension
73+
if (strcmp(BIN_EXT, &fname[strlen(fname) - strlen(BIN_EXT)]) == 0)
74+
{
75+
if (strstr(fname, BIN_HEADER) != NULL)
76+
{
77+
strcpy(binFileNames[binCount++], fname); //Add this to the array
78+
}
79+
else
80+
Serial.printf("Unknown: %s\n", fname);
81+
}
82+
}
83+
tempFile.close();
84+
}
85+
}
86+
}
87+
88+
//Look for firmware file on SD card and update as needed
89+
void updateFromSD(char *firmwareFileName)
90+
{
91+
Serial.printf("Loading %s\n", firmwareFileName);
92+
if (sd.exists(firmwareFileName))
93+
{
94+
SdFile firmwareFile;
95+
firmwareFile.open(firmwareFileName, O_READ);
96+
97+
size_t updateSize = firmwareFile.fileSize();
98+
if (updateSize == 0)
99+
{
100+
Serial.println(F("Error: Binary is empty"));
101+
firmwareFile.close();
102+
return;
103+
}
104+
105+
if (Update.begin(updateSize) == false)
106+
{
107+
Serial.println(F("Update begin failed. Not enough partition space available."));
108+
firmwareFile.close();
109+
return;
110+
}
111+
112+
Serial.print(F("Moving file to OTA section"));
113+
114+
const int pageSize = 512;
115+
byte dataArray[pageSize];
116+
int bytesWritten = 0;
117+
118+
//Bulk write from the SD file to the EEPROM
119+
while (firmwareFile.available())
120+
{
121+
int bytesToWrite = pageSize; //Max number of bytes to read
122+
if (firmwareFile.available() < bytesToWrite) bytesToWrite = firmwareFile.available(); //Trim this read size as needed
123+
124+
firmwareFile.read(dataArray, bytesToWrite); //Read the next set of bytes from file into our temp array
125+
126+
if (Update.write(dataArray, bytesToWrite) != bytesToWrite)
127+
Serial.println(F("Write failed"));
128+
else
129+
bytesWritten += bytesToWrite;
130+
131+
if (bytesWritten % (512 * 32) == 0) Serial.print("."); //Indicate progress
132+
}
133+
Serial.println(F("\nFile move complete"));
134+
135+
if (Update.end())
136+
{
137+
if (Update.isFinished())
138+
{
139+
Serial.println(F("Firmware updated successfully. Rebooting. Good bye!"));
140+
delay(1000);
141+
ESP.restart();
142+
}
143+
else
144+
Serial.println(F("Update not finished? Something went wrong!"));
145+
}
146+
else
147+
{
148+
Serial.print(F("Error Occurred. Error #: "));
149+
Serial.println(String(Update.getError()));
150+
}
151+
152+
firmwareFile.close();
153+
}
154+
else
155+
{
156+
Serial.println(F("No firmware file found"));
157+
}
158+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
//Return values for getByteChoice()
2+
enum returnStatus {
3+
STATUS_GETBYTE_TIMEOUT = 255,
4+
STATUS_GETNUMBER_TIMEOUT = -123455555,
5+
STATUS_PRESSED_X,
6+
};
7+
8+
//This is all the settings that can be set on RTK Surveyor. It's recorded to NVM and the config file.
9+
struct struct_settings {
10+
int sizeOfSettings = 0; //sizeOfSettings **must** be the first entry and must be int
11+
//int rtkIdentifier = RTK_IDENTIFIER; // rtkIdentifier **must** be the second entry
12+
uint8_t gnssMeasurementFrequency = 4; //Number of fixes per second
13+
bool printDebugMessages = false;
14+
bool enableSD = true;
15+
bool enableDisplay = true;
16+
bool zedOutputLogging = false;
17+
bool gnssRAWOutput = false;
18+
bool frequentFileAccessTimestamps = false;
19+
int maxLogTime_minutes = 60*10; //Default to 10 hours
20+
int observationSeconds = 60; //Default survey in time of 60 seconds
21+
float observationPositionAccuracy = 5.0; //Default survey in pos accy of 5m
22+
bool fixedBase = false; //Use survey-in by default
23+
//bool fixedBaseCoordinateType = COORD_TYPE_ECEF;
24+
double fixedEcefX = 0.0;
25+
double fixedEcefY = 0.0;
26+
double fixedEcefZ = 0.0;
27+
double fixedLat = 0.0;
28+
double fixedLong = 0.0;
29+
double fixedAltitude = 0.0;
30+
uint32_t dataPortBaud = 115200; //Default to 115200bps
31+
uint32_t radioPortBaud = 57600; //Default to 57600bps to support connection to SiK1000 radios
32+
bool outputSentenceGGA = true;
33+
bool outputSentenceGSA = true;
34+
bool outputSentenceGSV = true;
35+
bool outputSentenceRMC = true;
36+
bool outputSentenceGST = true;
37+
bool enableSBAS = false; //Bug in ZED-F9P v1.13 firmware causes RTK LED to not light when RTK Floating with SBAS on.
38+
bool enableNtripServer = false;
39+
char casterHost[50] = "rtk2go.com"; //It's free...
40+
uint16_t casterPort = 2101;
41+
char mountPoint[50] = "bldr_dwntwn2";
42+
char mountPointPW[50] = "WR5wRo4H";
43+
char wifiSSID[50] = "TRex";
44+
char wifiPW[50] = "parachutes";
45+
} settings;
46+
47+
//These are the devices on board RTK Surveyor that may be on or offline.
48+
struct struct_online {
49+
bool microSD = false;
50+
bool display = false;
51+
bool dataLogging = false;
52+
bool serialOutput = false;
53+
bool eeprom = false;
54+
} online;

0 commit comments

Comments
 (0)