Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 44d354b

Browse filesBrowse files
authored
Merge pull request #534 from Rocketct/GSMOTA
SSU support for OTA on SaraU210 module
2 parents 6e049f7 + 970877b commit 44d354b
Copy full SHA for 44d354b

File tree

Expand file treeCollapse file tree

12 files changed

+3161
-0
lines changed
Filter options
Expand file treeCollapse file tree

12 files changed

+3161
-0
lines changed
+227Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
/*
2+
Small example sketch demonstrating how to perform OTA via HTTP/S
3+
utilizing a MKRGSM 1400 and the storage on the integrated
4+
SARA U-201 GSM module.
5+
6+
Please, be careful because no verification is done on the
7+
received OTA file, apart size verification of the transmitted
8+
bytes using the HTTP Content-Length header.
9+
10+
For production-grade OTA procedure you might want to implement
11+
a content verification procedure using a CRC calculation
12+
or an hash (eg. MD5 or SHA256) comparison.
13+
14+
Circuit:
15+
* MKR GSM 1400 board
16+
* Antenna
17+
* SIM card with a data plan
18+
19+
Steps to update a sketch:
20+
21+
1) Create a new sketch or update an existing one to be updated over-the-air.
22+
The sketch needs to contain also the code below for future OTAs.
23+
The sketch must include the SSU library via
24+
#include <SSU.h>
25+
26+
2) In the IDE select: Sketch -> Export compiled Binary.
27+
28+
3) Open the location of the sketch (Sketch -> Show Sketch Folder) and upload
29+
the .bin file to your HTTP/S server.
30+
31+
4) Upload this sketch after configuring the server, port and filename variables.
32+
33+
The sketch will download the OTA file, store it into the U-201 storage, and
34+
will reset the board to trigger the SSU update procedure.
35+
36+
37+
created 25 June 2020
38+
by Giampaolo Mancini
39+
*/
40+
41+
#include <MKRGSM.h>
42+
43+
// This includes triggers the firmware update procedure
44+
// in the bootloader after reset.
45+
#include <SSU.h>
46+
47+
// Do not change! SSU will look for these files!
48+
constexpr char UPDATE_FILE_NAME[] = "UPDATE.BIN";
49+
static constexpr char CHECK_FILE_NAME[] = "UPDATE.OK";
50+
51+
#include "arduino_secrets.h"
52+
const char PINNUMBER[] = SECRET_PINNUMBER;
53+
// APN data
54+
const char GPRS_APN[] = SECRET_GPRS_APN;
55+
const char GPRS_LOGIN[] = SECRET_GPRS_LOGIN;
56+
const char GPRS_PASSWORD[] = SECRET_GPRS_PASSWORD;
57+
58+
// Change to GSMClient for non-SSL/TLS connection.
59+
// Not recommended.
60+
GSMSSLClient client;
61+
GPRS gprs;
62+
GSM gsmAccess;
63+
64+
GSMFileUtils fileUtils;
65+
66+
bool isHeaderComplete = false;
67+
String httpHeader;
68+
69+
bool isDownloadComplete = false;
70+
unsigned int fileSize = 0;
71+
unsigned int totalWritten = 0;
72+
73+
constexpr char server[] = "example.org";
74+
constexpr int port = 443;
75+
76+
// Name of the new firmware file to be updated.
77+
constexpr char filename[] = "update.bin";
78+
79+
80+
void setup()
81+
{
82+
unsigned long timeout = millis();
83+
84+
Serial.begin(9600);
85+
while (!Serial && millis() - timeout < 5000)
86+
;
87+
88+
Serial.println("Starting OTA Update via HTTP and Arduino SSU.");
89+
Serial.println();
90+
91+
bool connected = false;
92+
93+
Serial.print("Connecting to cellular network... ");
94+
while (!connected) {
95+
if ((gsmAccess.begin(PINNUMBER) == GSM_READY) && (gprs.attachGPRS(GPRS_APN, GPRS_LOGIN, GPRS_PASSWORD) == GPRS_READY)) {
96+
connected = true;
97+
} else {
98+
Serial.println("Not connected");
99+
delay(1000);
100+
}
101+
}
102+
103+
Serial.println("Connected.");
104+
Serial.println();
105+
106+
// Modem has already been initialized in the sketch:
107+
// begin FileUtils without MODEM initialization.
108+
fileUtils.begin(false);
109+
110+
Serial.print("Connecting to ");
111+
Serial.print(server);
112+
Serial.print(":");
113+
Serial.print(port);
114+
Serial.print("... ");
115+
if (client.connect(server, port)) {
116+
Serial.println("Connected.");
117+
Serial.print("Downloading ");
118+
Serial.println(filename);
119+
Serial.print("... ");
120+
// Make the HTTP request:
121+
client.print("GET /");
122+
client.print(filename);
123+
client.println(" HTTP/1.1");
124+
client.print("Host: ");
125+
client.println(server);
126+
client.println("Connection: close");
127+
client.println();
128+
} else {
129+
Serial.println("Connection failed");
130+
}
131+
}
132+
133+
void loop()
134+
{
135+
while (client.available()) {
136+
// Skip the HTTP header
137+
if (!isHeaderComplete) {
138+
const char c = client.read();
139+
httpHeader += c;
140+
if (httpHeader.endsWith("\r\n\r\n")) {
141+
isHeaderComplete = true;
142+
143+
// Get the size of the OTA file from the
144+
// HTTP Content-Length header.
145+
fileSize = getContentLength();
146+
147+
Serial.println();
148+
Serial.print("HTTP header complete. ");
149+
Serial.print("OTA file size is ");
150+
Serial.print(fileSize);
151+
Serial.println(" bytes.");
152+
if (fileSize == 0) {
153+
Serial.println("Unable to get OTA file size.");
154+
while (true)
155+
;
156+
}
157+
}
158+
} else {
159+
// Read the OTA file in len-bytes blocks to preserve RAM.
160+
constexpr size_t len { 512 };
161+
char buf[len] { 0 };
162+
163+
// Read len bytes from HTTP client...
164+
uint32_t read = client.readBytes(buf, len);
165+
// and append them to the update file.
166+
uint32_t written = fileUtils.appendFile(UPDATE_FILE_NAME, buf, read);
167+
168+
if (written != read) {
169+
Serial.println("Error while saving data.");
170+
while (true)
171+
;
172+
}
173+
174+
// Update the received byte counter
175+
totalWritten += written;
176+
177+
// Check for full file received and stored
178+
isDownloadComplete = totalWritten == fileSize;
179+
180+
Serial.print("Received: ");
181+
Serial.print(totalWritten);
182+
Serial.print("/");
183+
Serial.println(fileSize);
184+
}
185+
}
186+
if (isDownloadComplete) {
187+
Serial.println();
188+
Serial.println("Download complete.");
189+
Serial.println("Enabling checkpoint.");
190+
Serial.println();
191+
192+
// Create the checkpoint file: will be removed by SSU
193+
// after successful update.
194+
auto status = fileUtils.downloadFile(CHECK_FILE_NAME, { 0 }, 1);
195+
if (status != 1) {
196+
Serial.println("Unable to create checkpoint file.");
197+
while (true)
198+
;
199+
}
200+
201+
Serial.println("Resetting MCU in order to trigger SSU...");
202+
Serial.println();
203+
delay(500);
204+
NVIC_SystemReset();
205+
}
206+
}
207+
208+
int getContentLength()
209+
{
210+
const String contentLengthHeader = "Content-Length:";
211+
const auto contentLengthHeaderLen = contentLengthHeader.length();
212+
213+
auto indexContentLengthStart = httpHeader.indexOf(contentLengthHeader);
214+
if (indexContentLengthStart < 0) {
215+
Serial.println("Unable to find Content-Length header (Start)");
216+
return 0;
217+
}
218+
auto indexContentLengthStop = httpHeader.indexOf("\r\n", indexContentLengthStart);
219+
if (indexContentLengthStart < 0) {
220+
Serial.println("Unable to find Content-Length header (Stop)");
221+
return 0;
222+
}
223+
auto contentLength = httpHeader.substring(indexContentLengthStart + contentLengthHeaderLen + 1, indexContentLengthStop);
224+
225+
contentLength.trim();
226+
return contentLength.toInt();
227+
}
+4Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#define SECRET_PINNUMBER ""
2+
#define SECRET_GPRS_APN "GPRS_APN" // replace your GPRS APN
3+
#define SECRET_GPRS_LOGIN "login" // replace with your GPRS login
4+
#define SECRET_GPRS_PASSWORD "password" // replace with your GPRS password

‎libraries/SSU/examples/SSU_LoadBinary/Binary.h

Copy file name to clipboardExpand all lines: libraries/SSU/examples/SSU_LoadBinary/Binary.h
Whitespace-only changes.
+57Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/**************************************************************************************
2+
* INCLUDE
3+
**************************************************************************************/
4+
5+
6+
#include <MKRGSM.h>
7+
8+
9+
/**************************************************************************************
10+
* CONSTANTS
11+
**************************************************************************************/
12+
13+
static char const BINARY[] =
14+
15+
{
16+
#include "Binary.h"
17+
};
18+
19+
20+
GSMFileUtils fileUtils;
21+
22+
23+
/**************************************************************************************
24+
* SETUP/LOOP
25+
**************************************************************************************/
26+
27+
void setup() {
28+
Serial.begin(9600);
29+
30+
unsigned long const start = millis();
31+
for(unsigned long now = millis(); !Serial && ((now - start) < 5000); now = millis()) { };
32+
33+
Serial.print("Accessing SARA U-201 Filesystem... ");
34+
if(!fileUtils.begin()) {
35+
Serial.println("failed.");
36+
return;
37+
38+
}
39+
Serial.println("OK");
40+
Serial.print("Writing \"UPDATE.BIN\" ... ");
41+
42+
uint32_t bytes_to_write = sizeof(BINARY);
43+
auto bytes_written = fileUtils.downloadFile("UPDATE.BIN", BINARY, bytes_to_write);
44+
45+
if(bytes_written != bytes_to_write) {
46+
Serial.println("downloadFile failed.");return;
47+
48+
} else {
49+
Serial.print("OK (");
50+
Serial.print(bytes_written);
51+
Serial.println(" bytes written)");
52+
}
53+
}
54+
55+
void loop() {
56+
57+
}
+49Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
Usage
3+
This example demonstrates how to use the SAMD SSU library to update a
4+
sketch on any Arduino MKR board via the storage on the SARA U-201 GSM module.
5+
This sketch prints out the date and time the sketch was compiled.
6+
Steps to update sketch:
7+
1) Upload this sketch or another sketch that includes the SSU library
8+
via #include <SSU.h>
9+
2) Update the sketch as desired. For this example the sketch prints out
10+
the compiled date and time so no updates are needed.
11+
3) In the IDE select: Sketch -> Export compiled Binary
12+
4) Open the location of the sketch and convert the .bin file to a C byte array.
13+
cat SKETCH.bin | xxd --include > Binary.h
14+
5) Copy Binary.h file from the sketch's folder to the SSU_LoadBinary sketch
15+
and load it to the U-201 via SSU_LoadBinary sketch.
16+
*/
17+
18+
/*
19+
Include the SSU library
20+
21+
This will add some code to the sketch before setup() is called
22+
to check if UPDATE.BIN and UPDATE.OK are present on the storage of
23+
the U-201 module. If this theck is positive UPDATE.BIN is used to update
24+
the sketch running on the board.
25+
After this UPDATE.BIN and UPDATE.OK are deleted from the flash.
26+
*/
27+
28+
29+
#include <SSU.h>
30+
31+
void setup()
32+
{
33+
Serial.begin(9600);
34+
while (!Serial) { }
35+
// wait a bit
36+
delay(1000);
37+
String message;
38+
message += "Sketch compile date and time: ";
39+
message += __DATE__;
40+
message += " ";
41+
message += __TIME__;
42+
// print out the sketch compile date and time on the serial port
43+
Serial.println(message);
44+
}
45+
46+
void loop()
47+
{
48+
// add you own code here
49+
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.