Software Update via Ethernet - the mbed application can pull down an updated application binary from a web server and activate that binary. This library works only with the LPC1768, as it relies on the magic-chip boot-loader mechanism.

Dependents:   WattEye X10Svr PUB_SWUpdate

Success!! With this library, a network connection, and a web server hosting a new binary image, you can update the mbed firmware over the air (FOTA) - well, at least via Ethernet so far.

As of March 2015, it has been tested with the following mbed official libraries:

And a custom derivation:

  • HTTPClient v33, v32, which includes a custom HTTPFile.

Part of the update process involves checking the integrity of the downloaded binary file, for both a checksum and the program (file) size. To create this additional information, a small perl script is used (the important part is only 20 lines of code). See the documentation in the header file.

After the new binary is successfully downloaded, the checksum and the size are evaluated and if correct, then the old binary file is removed (this is the only way to cause the new binary to activate).

The mbed can then be automatically reset to activate the new image, or this may be deferred in case there is some other process necessary for an orderly restart.

Details are in the SWUpdate header file, and PUB_SWUpdate is a publicly accessible demonstration program for this library.

Committer:
WiredHome
Date:
Sun Jun 15 00:46:34 2014 +0000
Revision:
7:a7efbae7e02e
Parent:
3:c69fff55fc60
Child:
8:8e840a036116
Minor update to a debug diagnostic, and turned off debug.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
WiredHome 0:e221363f7942 1
WiredHome 0:e221363f7942 2 // Software Update via Ethernet from forum -
WiredHome 0:e221363f7942 3 // http://mbed.org/forum/mbed/topic/1183/
WiredHome 1:208de08b1a19 4 //
WiredHome 0:e221363f7942 5 #include "mbed.h"
WiredHome 0:e221363f7942 6 #include "SWUpdate.h"
WiredHome 0:e221363f7942 7 #include "HTTPClient.h"
WiredHome 0:e221363f7942 8 #include "HTTPText.h"
WiredHome 0:e221363f7942 9 #include "HTTPFile.h"
WiredHome 0:e221363f7942 10 #include <stdio.h>
WiredHome 0:e221363f7942 11
WiredHome 0:e221363f7942 12 extern "C" void mbed_reset();
WiredHome 0:e221363f7942 13
WiredHome 7:a7efbae7e02e 14 //#define DEBUG "SWup"
WiredHome 0:e221363f7942 15 #include <cstdio>
WiredHome 0:e221363f7942 16 #if (defined(DEBUG) && !defined(TARGET_LPC11U24))
WiredHome 0:e221363f7942 17 #define DBG(x, ...) std::printf("[DBG %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
WiredHome 0:e221363f7942 18 #define WARN(x, ...) std::printf("[WRN %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
WiredHome 0:e221363f7942 19 #define ERR(x, ...) std::printf("[ERR %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
WiredHome 0:e221363f7942 20 #define INFO(x, ...) std::printf("[INF %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
WiredHome 0:e221363f7942 21 #else
WiredHome 0:e221363f7942 22 #define DBG(x, ...)
WiredHome 0:e221363f7942 23 #define WARN(x, ...)
WiredHome 0:e221363f7942 24 #define ERR(x, ...)
WiredHome 0:e221363f7942 25 #define INFO(x, ...)
WiredHome 0:e221363f7942 26 #endif
WiredHome 0:e221363f7942 27
WiredHome 3:c69fff55fc60 28 static bool PassesIntegrityCheck(const char * fname, int cksum, int fsize) {
WiredHome 3:c69fff55fc60 29 int res = false; // assume things go wrong...
WiredHome 3:c69fff55fc60 30 int newCksum = 0;
WiredHome 3:c69fff55fc60 31 int newFSize = 0;
WiredHome 3:c69fff55fc60 32 FILE *fh = fopen(fname, "rb");
WiredHome 3:c69fff55fc60 33 INFO("IntegrityCheck(%s,%d,%d)", fname, cksum, fsize);
WiredHome 3:c69fff55fc60 34 if (fh) {
WiredHome 3:c69fff55fc60 35 char buf;
WiredHome 3:c69fff55fc60 36 while (fread(&buf, 1, 1, fh)) {
WiredHome 3:c69fff55fc60 37 newCksum = (newCksum + buf) & 0xFFFF;
WiredHome 3:c69fff55fc60 38 newFSize++;
WiredHome 3:c69fff55fc60 39 }
WiredHome 3:c69fff55fc60 40 fclose(fh);
WiredHome 3:c69fff55fc60 41 INFO(" Check(...,%d,%d)", newCksum, newFSize);
WiredHome 3:c69fff55fc60 42 if (newCksum == cksum && newFSize == fsize)
WiredHome 3:c69fff55fc60 43 res = true;
WiredHome 3:c69fff55fc60 44 } else {
WiredHome 3:c69fff55fc60 45 WARN("failed to open %s.", fname);
WiredHome 3:c69fff55fc60 46 }
WiredHome 3:c69fff55fc60 47 return res;
WiredHome 1:208de08b1a19 48 }
WiredHome 1:208de08b1a19 49
WiredHome 0:e221363f7942 50 bool SoftwareUpdate(const char *url, const char * name, Reboot_T reboot) {
WiredHome 0:e221363f7942 51 HTTPClient http;
WiredHome 0:e221363f7942 52 //http.setTimeout( 15000 );
WiredHome 0:e221363f7942 53 char fqurl[150]; // fully qualified url
WiredHome 0:e221363f7942 54 char verfn[32]; // local version file
WiredHome 0:e221363f7942 55 char fwfn[32];
WiredHome 0:e221363f7942 56 bool result = false; // many things can go wrong, assume failure
WiredHome 0:e221363f7942 57 char buf[50];
WiredHome 0:e221363f7942 58
WiredHome 0:e221363f7942 59 INFO("SoftwareUpdate(%s,%s)", url, name);
WiredHome 0:e221363f7942 60 snprintf(verfn, 32, "/local/%s.ver", name);
WiredHome 0:e221363f7942 61
WiredHome 0:e221363f7942 62 /* Read installed version string */
WiredHome 0:e221363f7942 63 int inst_ver = -1;
WiredHome 0:e221363f7942 64 FILE *fv = fopen(verfn, "r");
WiredHome 0:e221363f7942 65 if (fv) {
WiredHome 0:e221363f7942 66 fscanf(fv, "%d", &inst_ver);
WiredHome 0:e221363f7942 67 fclose(fv);
WiredHome 0:e221363f7942 68 }
WiredHome 0:e221363f7942 69 INFO(" Installed version: %d", inst_ver);
WiredHome 0:e221363f7942 70
WiredHome 0:e221363f7942 71 /* Download latest version string */
WiredHome 0:e221363f7942 72 HTTPText server_ver("test message");
WiredHome 0:e221363f7942 73 snprintf(fqurl, 150, "%s/%s.txt", url, name);
WiredHome 0:e221363f7942 74 HTTPResult r = http.get(fqurl, buf, sizeof(buf));
WiredHome 0:e221363f7942 75 if (r == HTTP_OK) {
WiredHome 0:e221363f7942 76 int latest_ver = -1;
WiredHome 3:c69fff55fc60 77 int cksum = 0;
WiredHome 3:c69fff55fc60 78 int fsize = 0;
WiredHome 3:c69fff55fc60 79 int parseCount;
WiredHome 0:e221363f7942 80 INFO(" read {%s}", buf);
WiredHome 3:c69fff55fc60 81 parseCount = sscanf(buf, "%d,%d,%d", &latest_ver, &cksum, &fsize);
WiredHome 3:c69fff55fc60 82 if (parseCount == 3) {
WiredHome 3:c69fff55fc60 83 INFO(" web version: %d", latest_ver);
WiredHome 3:c69fff55fc60 84 INFO(" checksum: %d", cksum);
WiredHome 3:c69fff55fc60 85 INFO(" file size: %d", fsize);
WiredHome 3:c69fff55fc60 86 if (inst_ver != latest_ver) {
WiredHome 3:c69fff55fc60 87 INFO(" Downloading firmware ver %d ...", latest_ver);
WiredHome 3:c69fff55fc60 88 sprintf(fwfn, "/local/%s%d.BIN", name, latest_ver);
WiredHome 3:c69fff55fc60 89 snprintf(fqurl, 150, "%s/%s.bin", url, name);
WiredHome 3:c69fff55fc60 90
WiredHome 3:c69fff55fc60 91 HTTPFile latest(fwfn);
WiredHome 3:c69fff55fc60 92 r = http.get(fqurl, &latest);
WiredHome 3:c69fff55fc60 93 if (r == HTTP_OK) {
WiredHome 3:c69fff55fc60 94 // Check the integrity of the freshly downloaded file,
WiredHome 3:c69fff55fc60 95 // before swapping out the old version.
WiredHome 3:c69fff55fc60 96 // ... to appear here ...
WiredHome 3:c69fff55fc60 97 if (PassesIntegrityCheck(fwfn, cksum, fsize)) {
WiredHome 3:c69fff55fc60 98 sprintf(fwfn, "/local/%s%d.BIN", name, inst_ver);
WiredHome 3:c69fff55fc60 99 INFO(" Firmware downloaded, removing old version (%s).", fwfn);
WiredHome 3:c69fff55fc60 100 if (remove(fwfn)) {
WiredHome 3:c69fff55fc60 101 ERR(" *** Failed to remove old version. ***");
WiredHome 3:c69fff55fc60 102 }
WiredHome 3:c69fff55fc60 103 INFO("Updating stored version number.");
WiredHome 3:c69fff55fc60 104 fv = fopen(verfn, "w");
WiredHome 3:c69fff55fc60 105 if (fv) {
WiredHome 3:c69fff55fc60 106 int fr = fputs(buf, fv);
WiredHome 3:c69fff55fc60 107 if (fr < 0) {
WiredHome 3:c69fff55fc60 108 ERR("Failed (%d) to update stored version number.", fr);
WiredHome 3:c69fff55fc60 109 fclose( fv );
WiredHome 3:c69fff55fc60 110 } else {
WiredHome 3:c69fff55fc60 111 fclose( fv );
WiredHome 3:c69fff55fc60 112 if (reboot == AUTO_REBOOT) {
WiredHome 3:c69fff55fc60 113 WARN("Resetting...\n");
WiredHome 3:c69fff55fc60 114 wait_ms(200);
WiredHome 3:c69fff55fc60 115 mbed_reset();
WiredHome 3:c69fff55fc60 116 }
WiredHome 3:c69fff55fc60 117 result = true;
WiredHome 3:c69fff55fc60 118 }
WiredHome 1:208de08b1a19 119 } else {
WiredHome 3:c69fff55fc60 120 WARN("Failed to update local version info in %s.", verfn);
WiredHome 1:208de08b1a19 121 }
WiredHome 0:e221363f7942 122 } else {
WiredHome 3:c69fff55fc60 123 WARN("New file {%s} did not pass integrity check.", fwfn);
WiredHome 0:e221363f7942 124 }
WiredHome 1:208de08b1a19 125 } else {
WiredHome 3:c69fff55fc60 126 WARN("Failed to download lastest firmware.");
WiredHome 0:e221363f7942 127 }
WiredHome 0:e221363f7942 128 } else {
WiredHome 7:a7efbae7e02e 129 INFO("Online version is same as installed version.", parseCount);
WiredHome 0:e221363f7942 130 }
WiredHome 0:e221363f7942 131 }
WiredHome 0:e221363f7942 132 } else {
WiredHome 1:208de08b1a19 133 WARN("Failed to download online firmware version number.");
WiredHome 0:e221363f7942 134 }
WiredHome 0:e221363f7942 135 return result;
WiredHome 0:e221363f7942 136 }