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.

Revision:
17:1d318666246c
Parent:
16:de99e872fc9d
Child:
18:5f7667d63a27
--- a/SWUpdate.cpp	Sat Jul 05 16:06:55 2014 +0000
+++ b/SWUpdate.cpp	Sat Jul 05 22:27:09 2014 +0000
@@ -1,10 +1,10 @@
 
-// Software Update via Ethernet from forum - 
+// Software Update via Ethernet from forum -
 // http://mbed.org/forum/mbed/topic/1183/
 //
 #include "mbed.h"
 #include "SWUpdate.h"
-#include "HTTPClient.h"
+//#include "HTTPClient.h"
 #include "HTTPText.h"
 #include "HTTPFile.h"
 #include <stdio.h>
@@ -25,12 +25,15 @@
 #define INFO(x, ...)
 #endif
 
-static bool PassesIntegrityCheck(const char * fname, int cksum, int fsize) {
+static HTTPResult HTTPErrorCode;
+
+static bool PassesIntegrityCheck(const char * fname, int cksum, int fsize)
+{
     int res = false;    // assume things go wrong...
     int newCksum = 0;
     int newFSize = 0;
     FILE *fh = fopen(fname, "rb");
-    
+
     INFO("IntegrityCheck(%s,%d,%d)", fname, cksum, fsize);
     if (fh) {
         char buf;
@@ -53,10 +56,13 @@
 /// This takes a character and if it is upper-case, it converts it to
 /// lower-case and returns it.
 ///
+/// @note this only works for characters in the range 'A' - 'Z'.
+///
 /// @param a is the character to convert
-/// @returns the lower case equivalent to a
+/// @returns the lower case equivalent to the supplied character.
 ///
-static char mytolower(char a) {
+static char mytolower(char a)
+{
     if (a >= 'A' && a <= 'Z')
         return (a - 'A' + 'a');
     else
@@ -75,7 +81,8 @@
 /// @returns 0 if l == r
 /// @returns +1 if l > r
 ///
-static int mystrnicmp(const char *l, const char *r, size_t n) {
+static int mystrnicmp(const char *l, const char *r, size_t n)
+{
     int result = 0;
 
     if (n != 0) {
@@ -91,7 +98,7 @@
 }
 
 
-// Scan the local file system for any .bin files and 
+// Scan the local file system for any .bin files and
 // if they don't match the current one, remove them.
 //
 static bool RemoveOtherBinFiles(const char * name, int ver)
@@ -100,8 +107,8 @@
     DIR *d;
     struct dirent *p;
     bool noFailed = true;
-   
-    snprintf(curbin, SW_MAX_FQFN, "%s%02d.bin", name, ver);
+
+    snprintf(curbin, SW_MAX_FQFN, "%s%02d.bin", name, (ver % 100));
     INFO("Remove bin files excluding {%s}", curbin);
     d = opendir("/local/");
     // Get a directory handle
@@ -111,7 +118,7 @@
             INFO("  check {%s}", p->d_name);
             // if the file is .bin and not curbin
             if (0 == mystrnicmp(p->d_name + strlen(p->d_name) - 4, ".bin", 4)
-            && (0 != mystrnicmp(p->d_name, curbin, strlen(curbin)))) {
+                    && (0 != mystrnicmp(p->d_name, curbin, strlen(curbin)))) {
                 // remove the file
                 char toremove[SW_MAX_FQFN];
                 snprintf(toremove, SW_MAX_FQFN, "/local/%s", p->d_name);
@@ -127,16 +134,22 @@
     return noFailed;
 }
 
-SWUpdate_T SoftwareUpdate(const char *url, const char * name, Reboot_T action) {
+HTTPResult SoftwareUpdateGetHTTPErrorCode(void)
+{
+    return HTTPErrorCode;
+}
+
+SWUpdate_T SoftwareUpdate(const char *url, const char * name, Reboot_T action)
+{
     HTTPClient http;
-    //http.setTimeout( 15000 ); 
+    //http.setTimeout( 15000 );
     char fqurl[SW_MAX_URL];    // fully qualified url
     char verfn[SW_MAX_FQFN];     // local version file
     char fwfn[SW_MAX_FQFN];
     char nameroot[7];
     uint16_t result = SWUP_OK;    // starting out quite optimistic, for all the things that can go wrong
     char buf[50];           // long enough for 3 comma separated numbers...
-        
+
     INFO("SoftwareUpdate(%s,%s)", url, name);
     strncpy(nameroot, name, 6);
     nameroot[6] = '\0';
@@ -150,12 +163,12 @@
         fclose(fv);
     }
     INFO("  Installed version: %d", inst_ver);
-    
+
     /* Download latest version string */
     HTTPText server_ver("test message");
     snprintf(fqurl, SW_MAX_URL, "%s/%s.txt", url, name);
-    HTTPResult r = http.get(fqurl, buf, sizeof(buf));
-    if (r == HTTP_OK) {
+    HTTPErrorCode = http.get(fqurl, buf, sizeof(buf));
+    if (HTTPErrorCode == HTTP_OK) {
         int latest_ver = -1;
         int cksum = 0;
         int fsize = 0;
@@ -169,10 +182,10 @@
                 INFO("  Downloading firmware ver %d ...", latest_ver);
                 sprintf(fwfn, "/local/%s%02d.BIN", nameroot, (latest_ver % 100));
                 snprintf(fqurl, 150, "%s/%s.bin", url, name);
-        
+
                 HTTPFile latest(fwfn);
-                r = http.get(fqurl, &latest);
-                if (r == HTTP_OK) {
+                HTTPErrorCode = http.get(fqurl, &latest);
+                if (HTTPErrorCode == HTTP_OK) {
                     if (PassesIntegrityCheck(fwfn, cksum, fsize)) {
                         if (!RemoveOtherBinFiles(nameroot, latest_ver)) {
                             ERR("  *** Failed to remove old version(s). ***");
@@ -204,7 +217,7 @@
                     }
                 } else {
                     WARN("Failed to download lastest firmware.");
-                    result |= SWUP_BAD_URL;
+                    result |= SWUP_HTTP_BIN;
                 }
             } else {
                 INFO("Online version is same as installed version.");
@@ -212,8 +225,8 @@
             }
         }
     } else {
-        WARN("Failed to download online firmware version number. r= %d", r);
-        result |= SWUP_HTTP_ERR;
+        WARN("Failed accessing server. Extended Error Code = %d", HTTPErrorCode);
+        result |= SWUP_HTTP_VER;
     }
     return (SWUpdate_T)result;
 }