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 Sep 13 14:53:10 2020 +0000
Revision:
29:f67a7f54c173
Parent:
27:3d3089b8212d
Minor revision to debug macros

Who changed what in which revision?

UserRevisionLine numberNew contents of line
WiredHome 12:f1fdf8cabbc4 1 /// @file
WiredHome 12:f1fdf8cabbc4 2 /// Automatic Software Update via the network.
WiredHome 9:73067ef14c30 3 ///
WiredHome 20:cf73b0d75bb7 4 /// Supported Platforms: mbed LPC1768.
WiredHome 20:cf73b0d75bb7 5 ///
WiredHome 9:73067ef14c30 6 /// This library provides a reasonably simple interface to updating sofware
WiredHome 10:78d727e8d0de 7 /// semi-automatically via the network. It does that by querying a web server
WiredHome 10:78d727e8d0de 8 /// upon which you have placed an updated version of the embedded software
WiredHome 10:78d727e8d0de 9 /// application. Upon finding something there, it will determine if it is
WiredHome 10:78d727e8d0de 10 /// a different version than the one you current have installed and it
WiredHome 10:78d727e8d0de 11 /// will try to download the software. If that succeeds, then it can
WiredHome 10:78d727e8d0de 12 /// optionally reboot to activate the new software.
WiredHome 10:78d727e8d0de 13 ///
WiredHome 20:cf73b0d75bb7 14 /// @code
WiredHome 20:cf73b0d75bb7 15 /// +-----------+
WiredHome 20:cf73b0d75bb7 16 /// | Compiler |
WiredHome 20:cf73b0d75bb7 17 /// +-----------+
WiredHome 20:cf73b0d75bb7 18 /// V +------------------+
WiredHome 20:cf73b0d75bb7 19 /// +-----------+ |Web Server |
WiredHome 20:cf73b0d75bb7 20 /// |myprog.bin |------------------->| /mbed/myprog.bin |
WiredHome 20:cf73b0d75bb7 21 /// +-----------+ +-----------| |
WiredHome 20:cf73b0d75bb7 22 /// V | |
WiredHome 20:cf73b0d75bb7 23 /// +-----------+ | |
WiredHome 20:cf73b0d75bb7 24 /// |perl script|---->| /mbed/myprog.txt |
WiredHome 20:cf73b0d75bb7 25 /// +-----------+ +------------------+
WiredHome 20:cf73b0d75bb7 26 /// A
WiredHome 20:cf73b0d75bb7 27 /// +---------------+ #
WiredHome 20:cf73b0d75bb7 28 /// |mbed appliance |<====== network =========#======...
WiredHome 20:cf73b0d75bb7 29 /// +---------------+
WiredHome 20:cf73b0d75bb7 30 ///
WiredHome 20:cf73b0d75bb7 31 /// mbed server
WiredHome 20:cf73b0d75bb7 32 /// | |
WiredHome 20:cf73b0d75bb7 33 /// +-- http Get(myprog.txt) -->|
WiredHome 20:cf73b0d75bb7 34 /// |<-- file(myprog.txt) ------+
WiredHome 20:cf73b0d75bb7 35 /// | |
WiredHome 20:cf73b0d75bb7 36 /// |---+ |
WiredHome 20:cf73b0d75bb7 37 /// | v58 newer than v57 |
WiredHome 20:cf73b0d75bb7 38 /// |<--+ |
WiredHome 20:cf73b0d75bb7 39 /// | |
WiredHome 20:cf73b0d75bb7 40 /// +-- http Get(myprog.bin) -->|
WiredHome 20:cf73b0d75bb7 41 /// |<-- file(myprog.bin) ------+
WiredHome 20:cf73b0d75bb7 42 /// |<-- file(myprog.bin) ------+
WiredHome 20:cf73b0d75bb7 43 /// |<-- file(myprog.bin) ------+
WiredHome 20:cf73b0d75bb7 44 /// | (save as myprog58.bin) |
WiredHome 20:cf73b0d75bb7 45 /// | |
WiredHome 20:cf73b0d75bb7 46 /// |---+ |
WiredHome 20:cf73b0d75bb7 47 /// | integrity ck ok? |
WiredHome 20:cf73b0d75bb7 48 /// |<--+ |
WiredHome 20:cf73b0d75bb7 49 /// | |
WiredHome 20:cf73b0d75bb7 50 /// |---+ |
WiredHome 20:cf73b0d75bb7 51 /// | unlink other .bin files |
WiredHome 20:cf73b0d75bb7 52 /// | and reboot |
WiredHome 20:cf73b0d75bb7 53 /// |<--+ |
WiredHome 20:cf73b0d75bb7 54 /// | |
WiredHome 20:cf73b0d75bb7 55 /// @endcode
WiredHome 20:cf73b0d75bb7 56 ///
WiredHome 10:78d727e8d0de 57 /// While the name shown in the examples here is "myprog", this is unimportant.
WiredHome 10:78d727e8d0de 58 /// Your application will have a name of your choosing, which you will
WiredHome 10:78d727e8d0de 59 /// use in the API.
WiredHome 10:78d727e8d0de 60 ///
WiredHome 14:0e012d53c6df 61 /// @note Your binary file name should not exceed 6 characters. This leaves
WiredHome 14:0e012d53c6df 62 /// room for a 2-digit sequence number. Since this is using the local
WiredHome 14:0e012d53c6df 63 /// file system, it does not support long filenames when accessed from
WiredHome 14:0e012d53c6df 64 /// the mbed. So, SomeLongFile23.bin becomes somefi~1.bin and is then
WiredHome 14:0e012d53c6df 65 /// erased, leaving no file.
WiredHome 14:0e012d53c6df 66 ///
WiredHome 15:49cc43dcbbf6 67 /// @note This was tested with firmware version 16457. Others may/not work.
WiredHome 15:49cc43dcbbf6 68 /// To check your version, open the mbed.htm file in a text editor,
WiredHome 15:49cc43dcbbf6 69 /// and look for "&firmware=16457&"
WiredHome 15:49cc43dcbbf6 70 ///
WiredHome 10:78d727e8d0de 71 /// Local File System Files:
WiredHome 10:78d727e8d0de 72 ///
WiredHome 10:78d727e8d0de 73 /// The files of interest on the local file system are as follows:
WiredHome 10:78d727e8d0de 74 ///
WiredHome 20:cf73b0d75bb7 75 /// @li myprog58.bin - The actual application binary file that is currently
WiredHome 20:cf73b0d75bb7 76 /// executing. In this case, this is the 58th version that
WiredHome 10:78d727e8d0de 77 /// has been installed. You can go to 99 after which you might
WiredHome 10:78d727e8d0de 78 /// want to start over.
WiredHome 10:78d727e8d0de 79 /// @li myprog.ver - A text file, maintained by this software update
WiredHome 10:78d727e8d0de 80 /// application, that was downloaded from the server with
WiredHome 20:cf73b0d75bb7 81 /// application version 58.
WiredHome 10:78d727e8d0de 82 ///
WiredHome 10:78d727e8d0de 83 /// If "myprog.ver" does not exist, it will assume that the server has a
WiredHome 10:78d727e8d0de 84 /// newer application, so it will be downloaded and activated (even if all
WiredHome 20:cf73b0d75bb7 85 /// it does is to replace the existing myprog58.bin file).
WiredHome 10:78d727e8d0de 86 ///
WiredHome 10:78d727e8d0de 87 /// Web Server Files:
WiredHome 10:78d727e8d0de 88 ///
WiredHome 10:78d727e8d0de 89 /// The files on the web server are as follows.
WiredHome 10:78d727e8d0de 90 ///
WiredHome 10:78d727e8d0de 91 /// @li myprog.bin - The latest version of the application binary file.
WiredHome 10:78d727e8d0de 92 /// Note that this file does not have any version number
WiredHome 10:78d727e8d0de 93 /// embedded into its filename as is the case on the local
WiredHome 10:78d727e8d0de 94 /// file system.
WiredHome 10:78d727e8d0de 95 /// @li myprog.txt - A corresponding text file. The root name must match
WiredHome 10:78d727e8d0de 96 /// that of the binary file.
WiredHome 10:78d727e8d0de 97 ///
WiredHome 10:78d727e8d0de 98 /// The myprog.txt file shall have 3 comma-separated numbers in it.
WiredHome 20:cf73b0d75bb7 99 /// version,checksum,filesize (e.g. "58,41384,107996").
WiredHome 10:78d727e8d0de 100 ///
WiredHome 10:78d727e8d0de 101 /// @li version is a simple number. If the number is different than
WiredHome 10:78d727e8d0de 102 /// what is stored on the local file system, then the program
WiredHome 10:78d727e8d0de 103 /// will be updated (even if the server number is lower).
WiredHome 10:78d727e8d0de 104 /// This bidirectional "update" can let you downgrade.
WiredHome 10:78d727e8d0de 105 /// @li checksum is the decimal representation of a simple 16-bit checksum.
WiredHome 10:78d727e8d0de 106 /// @li filesize is the decimal representation of the size of the file.
WiredHome 10:78d727e8d0de 107 ///
WiredHome 10:78d727e8d0de 108 /// Variations:
WiredHome 10:78d727e8d0de 109 ///
WiredHome 10:78d727e8d0de 110 /// Within that single web server folder, you could have several apps -
WiredHome 14:0e012d53c6df 111 /// @li Sensor.bin, Sensor.txt
WiredHome 14:0e012d53c6df 112 /// @li SensrB.bin, SensrB.txt
WiredHome 14:0e012d53c6df 113 /// @li SensrD.bin, SensrD.txt
WiredHome 10:78d727e8d0de 114 ///
WiredHome 10:78d727e8d0de 115 /// In this example, perhaps your first version was called SensorNode, but
WiredHome 10:78d727e8d0de 116 /// with a small hardware design change, you have a new "model B" version.
WiredHome 10:78d727e8d0de 117 /// This example also assumes that you have a need to maintain two separate
WiredHome 10:78d727e8d0de 118 /// applications, one for each hardware version.
WiredHome 10:78d727e8d0de 119 ///
WiredHome 13:cf76c2bd3dfc 120 /// Creating the Version and Integrity Check data:
WiredHome 13:cf76c2bd3dfc 121 ///
WiredHome 10:78d727e8d0de 122 /// You can create the server "myprog.txt" file with this perl script (not
WiredHome 10:78d727e8d0de 123 /// every detail is shown, but it should be easy to figure out).
WiredHome 10:78d727e8d0de 124 /// @code
WiredHome 10:78d727e8d0de 125 /// # Read current .txt file
WiredHome 10:78d727e8d0de 126 /// open (FT, "<$txt") || die("Can't read $txt.");
WiredHome 10:78d727e8d0de 127 /// $ver = <FT>; chomp $ver; close FT;
WiredHome 10:78d727e8d0de 128 /// $ver =~ s/(\d+),.*/$1/;
WiredHome 10:78d727e8d0de 129 /// print "Current Version is {$ver}\n";
WiredHome 10:78d727e8d0de 130 ///
WiredHome 10:78d727e8d0de 131 /// # Read the [assumed new] .bin file
WiredHome 10:78d727e8d0de 132 /// open (FB, "<$bin") || die("Can't read $bin.");
WiredHome 10:78d727e8d0de 133 /// binmode FB;
WiredHome 10:78d727e8d0de 134 /// while (sysread(FB, $c, 1))
WiredHome 10:78d727e8d0de 135 /// {
WiredHome 10:78d727e8d0de 136 /// $cksum = ($cksum + ord($c)) & 0xFFFF;
WiredHome 10:78d727e8d0de 137 /// $byteCount++;
WiredHome 10:78d727e8d0de 138 /// }
WiredHome 10:78d727e8d0de 139 /// close FB;
WiredHome 10:78d727e8d0de 140 /// # Advance version number and write the new .txt file
WiredHome 10:78d727e8d0de 141 /// $ver++; print "$ver Checksum is $cksum over $byteCount bytes.\n";
WiredHome 10:78d727e8d0de 142 /// open (FT, ">$txt") || die("Can't write update to $txt.");
WiredHome 10:78d727e8d0de 143 /// printf(FT "%d,%d,%d\n", $ver, $cksum,$byteCount);
WiredHome 10:78d727e8d0de 144 /// close FT;
WiredHome 10:78d727e8d0de 145 /// @endcode
WiredHome 4:1a3656ae80dc 146 ///
WiredHome 0:e221363f7942 147
WiredHome 0:e221363f7942 148 #ifndef SWUPDATE_H
WiredHome 0:e221363f7942 149 #define SWUPDATE_H
WiredHome 0:e221363f7942 150
WiredHome 17:1d318666246c 151 #include "mbed.h"
WiredHome 17:1d318666246c 152 #include "HTTPClient.h"
WiredHome 17:1d318666246c 153
WiredHome 9:73067ef14c30 154 // This defines the maximum string length for a fully qualified
WiredHome 9:73067ef14c30 155 // filename. Usually, this will be pretty short
WiredHome 16:de99e872fc9d 156 // (e.g. "/local/myprog.bin"), which should be 19 max with 8.3 filename.
WiredHome 16:de99e872fc9d 157 #define SW_MAX_FQFN 20
WiredHome 9:73067ef14c30 158
WiredHome 9:73067ef14c30 159 // This defines the maximum string length for the url, including
WiredHome 9:73067ef14c30 160 // the base filename of interest.
WiredHome 9:73067ef14c30 161 #define SW_MAX_URL 150
WiredHome 9:73067ef14c30 162
WiredHome 1:208de08b1a19 163 /// After downloading, the user can choose what happens next.
WiredHome 0:e221363f7942 164 typedef enum {
WiredHome 6:6025fddc1af9 165 DEFER_REBOOT, ///< Do not reboot to activate the new firmware.
WiredHome 6:6025fddc1af9 166 AUTO_REBOOT ///< Automatically reboot to activate the new firmware.
WiredHome 0:e221363f7942 167 } Reboot_T;
WiredHome 0:e221363f7942 168
WiredHome 27:3d3089b8212d 169 /// Value return code from the SoftwareUpdate API.
WiredHome 9:73067ef14c30 170 ///
WiredHome 9:73067ef14c30 171 /// Various things can go wrong in the software update process. The return
WiredHome 27:3d3089b8212d 172 /// value indicates the error.
WiredHome 17:1d318666246c 173 ///
WiredHome 9:73067ef14c30 174 typedef enum {
WiredHome 9:73067ef14c30 175 SWUP_OK = 0x00, ///< Software Update succeeded as planned.
WiredHome 9:73067ef14c30 176 SWUP_SAME_VER = 0x01, ///< Online version is the same as the installed version.
WiredHome 17:1d318666246c 177 SWUP_HTTP_BIN = 0x02, ///< HTTP get returned an error while trying to fetch the bin file.
WiredHome 27:3d3089b8212d 178 SWUP_OLD_STUCK = 0x03, ///< Old file could not be removed.
WiredHome 27:3d3089b8212d 179 SWUP_VER_STUCK = 0x04, ///< Old version number could not be updated.
WiredHome 27:3d3089b8212d 180 SWUP_VWRITE_FAILED = 0x05, ///< Can't open for write the version tracking file.
WiredHome 27:3d3089b8212d 181 SWUP_INTEGRITY_FAILED = 0x06, ///< Integrity check of downloaded file failed.
WiredHome 27:3d3089b8212d 182 SWUP_HTTP_VER = 0x07, ///< HTTP get returned an error while trying to fetch the version file.
WiredHome 27:3d3089b8212d 183 SWUP_NO_SPACE = 0x08, ///< No space on file system for new version.
WiredHome 27:3d3089b8212d 184 SWUP_NO_FILE = 0x09, ///< Specified file on the server does not exist
WiredHome 9:73067ef14c30 185 } SWUpdate_T;
WiredHome 9:73067ef14c30 186
WiredHome 10:78d727e8d0de 187
WiredHome 10:78d727e8d0de 188 /// To perform the software update, we simply give this API the web
WiredHome 10:78d727e8d0de 189 /// server URL that is hosting the embedded software. We also give it
WiredHome 10:78d727e8d0de 190 /// the "root" name of the file of interest, which permits you to
WiredHome 10:78d727e8d0de 191 /// have different applications served from the same location.
WiredHome 16:de99e872fc9d 192 ///
WiredHome 16:de99e872fc9d 193 /// Note that the root name can be a long filename, as is typically
WiredHome 16:de99e872fc9d 194 /// produced from the cloud-based build process. This name will
WiredHome 16:de99e872fc9d 195 /// be truncated to the first 6 characters when installed on the
WiredHome 16:de99e872fc9d 196 /// mbed local file system, in order to retain space for a 2-digit
WiredHome 16:de99e872fc9d 197 /// version number.
WiredHome 16:de99e872fc9d 198 ///
WiredHome 10:78d727e8d0de 199 /// One optional parameter lets you decide what happens if a new
WiredHome 10:78d727e8d0de 200 /// version is installed - automatically reboot to launch it, or
WiredHome 10:78d727e8d0de 201 /// return to the calling program which may perform a more orderly
WiredHome 10:78d727e8d0de 202 /// reboot.
WiredHome 9:73067ef14c30 203 ///
WiredHome 9:73067ef14c30 204 /// @code
WiredHome 9:73067ef14c30 205 /// ...
WiredHome 9:73067ef14c30 206 /// if (NowIsTheTimeToCheckForSoftwareUpdates()) {
WiredHome 16:de99e872fc9d 207 /// if (SWUP_OK == SoftwareUpdate("http://192.168.1.200/path/to/file", "myprog_LPC1768", DEFER_REBOOT)) {
WiredHome 9:73067ef14c30 208 /// printf("Software updated, rebooting now...\r\n");
WiredHome 9:73067ef14c30 209 /// wait_ms(5000);
WiredHome 9:73067ef14c30 210 /// mbed_reset();
WiredHome 9:73067ef14c30 211 /// }
WiredHome 9:73067ef14c30 212 /// }
WiredHome 9:73067ef14c30 213 /// ...
WiredHome 9:73067ef14c30 214 /// @endcode
WiredHome 9:73067ef14c30 215 ///
WiredHome 18:5f7667d63a27 216 /// @param[in] url is a pointer to a text string of the url from which to download.
WiredHome 18:5f7667d63a27 217 /// @param[in] name is the base filename of the binary file.
WiredHome 18:5f7667d63a27 218 /// @param[in] action determines whether to automatically reboot to activate the new bin.
WiredHome 13:cf76c2bd3dfc 219 /// @return SWUpdate_T code indicating if the update succeeded, otherwise it returns a bitmask
WiredHome 13:cf76c2bd3dfc 220 /// of failure flags. Also, note that if it succeeded, and it was set for AUTO_REBOOT
WiredHome 13:cf76c2bd3dfc 221 /// that it will not return from this function.
WiredHome 1:208de08b1a19 222 ///
WiredHome 9:73067ef14c30 223 SWUpdate_T SoftwareUpdate(const char *url, const char * name, Reboot_T action = AUTO_REBOOT);
WiredHome 0:e221363f7942 224
WiredHome 17:1d318666246c 225 /// Get the HTTP transaction return code.
WiredHome 17:1d318666246c 226 ///
WiredHome 17:1d318666246c 227 /// If something goes wrong with the communications with the server, SoftwareUpdate will
WiredHome 17:1d318666246c 228 /// respond with an SWUP_HTTP_VER or SWUP_HTTP_BIN return value. To learn more about
WiredHome 17:1d318666246c 229 /// what went wrong, this API will provide the actual return code from the HTTP transaction.
WiredHome 17:1d318666246c 230 ///
WiredHome 17:1d318666246c 231 /// @returns @ref HTTPResult code from the server transaction.
WiredHome 17:1d318666246c 232 ///
WiredHome 17:1d318666246c 233 HTTPResult SoftwareUpdateGetHTTPErrorCode(void);
WiredHome 17:1d318666246c 234
WiredHome 24:e400edb8d2ee 235 /// Get the error message from a return code
WiredHome 24:e400edb8d2ee 236 ///
WiredHome 24:e400edb8d2ee 237 /// @param[in] r is the result code to translate into a message
WiredHome 24:e400edb8d2ee 238 /// @returns a pointer to a text string of the message
WiredHome 24:e400edb8d2ee 239 ///
WiredHome 27:3d3089b8212d 240 const char * SoftwareUpdateGetHTTPErrorMsg(SWUpdate_T r);
WiredHome 17:1d318666246c 241
WiredHome 26:f2bb6061dcb3 242 /// Get the installed software version number.
WiredHome 26:f2bb6061dcb3 243 ///
WiredHome 26:f2bb6061dcb3 244 /// If the installed version has a version number, retrieve that number and return it.
WiredHome 26:f2bb6061dcb3 245 ///
WiredHome 26:f2bb6061dcb3 246 /// @param name is the base filename of the binary file.
WiredHome 26:f2bb6061dcb3 247 /// @returns the installed version number, or -1 if it cannot be identified.
WiredHome 26:f2bb6061dcb3 248 ///
WiredHome 26:f2bb6061dcb3 249 int GetSoftwareVersionNumber(const char * name);
WiredHome 26:f2bb6061dcb3 250
WiredHome 0:e221363f7942 251 #endif // SWUPDATE_H