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 20:01:58 2014 +0000
Revision:
8:8e840a036116
Parent:
7:a7efbae7e02e
Child:
9:73067ef14c30
Documentation and rearranging a few files for easier maintenance.

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 3:c69fff55fc60 80 parseCount = sscanf(buf, "%d,%d,%d", &latest_ver, &cksum, &fsize);
WiredHome 3:c69fff55fc60 81 if (parseCount == 3) {
WiredHome 3:c69fff55fc60 82 INFO(" web version: %d", latest_ver);
WiredHome 3:c69fff55fc60 83 INFO(" checksum: %d", cksum);
WiredHome 3:c69fff55fc60 84 INFO(" file size: %d", fsize);
WiredHome 3:c69fff55fc60 85 if (inst_ver != latest_ver) {
WiredHome 3:c69fff55fc60 86 INFO(" Downloading firmware ver %d ...", latest_ver);
WiredHome 3:c69fff55fc60 87 sprintf(fwfn, "/local/%s%d.BIN", name, latest_ver);
WiredHome 3:c69fff55fc60 88 snprintf(fqurl, 150, "%s/%s.bin", url, name);
WiredHome 3:c69fff55fc60 89
WiredHome 3:c69fff55fc60 90 HTTPFile latest(fwfn);
WiredHome 3:c69fff55fc60 91 r = http.get(fqurl, &latest);
WiredHome 3:c69fff55fc60 92 if (r == HTTP_OK) {
WiredHome 3:c69fff55fc60 93 // Check the integrity of the freshly downloaded file,
WiredHome 3:c69fff55fc60 94 // before swapping out the old version.
WiredHome 3:c69fff55fc60 95 // ... to appear here ...
WiredHome 3:c69fff55fc60 96 if (PassesIntegrityCheck(fwfn, cksum, fsize)) {
WiredHome 3:c69fff55fc60 97 sprintf(fwfn, "/local/%s%d.BIN", name, inst_ver);
WiredHome 3:c69fff55fc60 98 INFO(" Firmware downloaded, removing old version (%s).", fwfn);
WiredHome 3:c69fff55fc60 99 if (remove(fwfn)) {
WiredHome 3:c69fff55fc60 100 ERR(" *** Failed to remove old version. ***");
WiredHome 3:c69fff55fc60 101 }
WiredHome 3:c69fff55fc60 102 INFO("Updating stored version number.");
WiredHome 3:c69fff55fc60 103 fv = fopen(verfn, "w");
WiredHome 3:c69fff55fc60 104 if (fv) {
WiredHome 3:c69fff55fc60 105 int fr = fputs(buf, fv);
WiredHome 3:c69fff55fc60 106 if (fr < 0) {
WiredHome 3:c69fff55fc60 107 ERR("Failed (%d) to update stored version number.", fr);
WiredHome 3:c69fff55fc60 108 fclose( fv );
WiredHome 3:c69fff55fc60 109 } else {
WiredHome 3:c69fff55fc60 110 fclose( fv );
WiredHome 3:c69fff55fc60 111 if (reboot == AUTO_REBOOT) {
WiredHome 3:c69fff55fc60 112 WARN("Resetting...\n");
WiredHome 3:c69fff55fc60 113 wait_ms(200);
WiredHome 3:c69fff55fc60 114 mbed_reset();
WiredHome 3:c69fff55fc60 115 }
WiredHome 3:c69fff55fc60 116 result = true;
WiredHome 3:c69fff55fc60 117 }
WiredHome 1:208de08b1a19 118 } else {
WiredHome 3:c69fff55fc60 119 WARN("Failed to update local version info in %s.", verfn);
WiredHome 1:208de08b1a19 120 }
WiredHome 0:e221363f7942 121 } else {
WiredHome 3:c69fff55fc60 122 WARN("New file {%s} did not pass integrity check.", fwfn);
WiredHome 0:e221363f7942 123 }
WiredHome 1:208de08b1a19 124 } else {
WiredHome 3:c69fff55fc60 125 WARN("Failed to download lastest firmware.");
WiredHome 0:e221363f7942 126 }
WiredHome 0:e221363f7942 127 } else {
WiredHome 7:a7efbae7e02e 128 INFO("Online version is same as installed version.", parseCount);
WiredHome 0:e221363f7942 129 }
WiredHome 0:e221363f7942 130 }
WiredHome 0:e221363f7942 131 } else {
WiredHome 1:208de08b1a19 132 WARN("Failed to download online firmware version number.");
WiredHome 0:e221363f7942 133 }
WiredHome 0:e221363f7942 134 return result;
WiredHome 0:e221363f7942 135 }