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:
- mbed v95, v85 thru v89
- mbed-rtos v64, v32 thru v44
- EthernetInterface v47, v41 thru v43
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.
SWUpdate.cpp@7:a7efbae7e02e, 2014-06-15 (annotated)
- 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?
User | Revision | Line number | New 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 | } |