Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
fwupdate.c
00001 /*! 00002 * \file 00003 * \copyright Copyright (C) Xsens Technologies B.V., 2015. 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 00006 * use this file except in compliance with the License. You may obtain a copy 00007 * of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 00013 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 00014 * License for the specific language governing permissions and limitations 00015 * under the License. 00016 */ 00017 #include "fwupdate.h " 00018 #include "string.h" 00019 00020 #ifndef LOG 00021 static void defaultLogFunction(char const* format, ...) { } 00022 #define LOG defaultLogFunction 00023 #endif 00024 00025 #define XMID_FIRMWARE_UPDATE (0xF2) 00026 00027 #define FWUP_DEFAULT_SLICE_SIZE (64) 00028 00029 00030 /*! \brief Firmware updater commands 00031 */ 00032 #define FWUP_READY (unsigned char)0x52 //'R' 00033 #define FWUP_OK (unsigned char)0x53 //'S' 00034 #define FWUP_CSERROR (unsigned char)0x45 //'E' 00035 #define FWUP_CRITICAL (unsigned char)0x46 //'F' 00036 #define FWUP_FINISHED (unsigned char)0x46 //'F' 00037 #define FWUP_PAGE (unsigned char)0x50 //'P' 00038 #define FWUP_HEADER (unsigned char)0x53 //'S' 00039 #define FWUP_PAGESLICE (unsigned char)0x54 //'T' 00040 #define FWUP_STARTED (unsigned char)0x41 //'A' 00041 #define FWUP_OTHER (unsigned char)0x4F //'O' 00042 00043 00044 /*! \brief Helper function for converting a firmware updater command to a string 00045 */ 00046 const char *commandToString(uint8_t command) 00047 { 00048 switch (command) 00049 { 00050 case FWUP_READY: return("FWUP_READY"); 00051 case FWUP_HEADER: return("FWUP_HEADER"); 00052 case FWUP_FINISHED: return("FWUP_FINISHED"); 00053 case FWUP_PAGE: return("FWUP_PAGE"); 00054 case FWUP_PAGESLICE: return("FWUP_PAGESLICE"); 00055 case FWUP_STARTED: return("FWUP_STARTED"); 00056 case FWUP_OTHER: return("FWUP_OTHER"); 00057 default: return("unknown"); 00058 } 00059 } 00060 00061 00062 /*! \brief Helper function for converting a firmware updater command acknowledge to a string 00063 */ 00064 const char *ackToString(uint8_t command) 00065 { 00066 switch (command) 00067 { 00068 case FWUP_READY: return "FWUP_READY"; 00069 case FWUP_OK: return "FWUP_OK"; 00070 case FWUP_CSERROR: return "FWUP_CSERROR"; 00071 case FWUP_CRITICAL: return "FWUP_CRITICAL"; 00072 case FWUP_PAGE: return "FWUP_PAGE"; 00073 case FWUP_PAGESLICE: return "FWUP_PAGESLICE"; 00074 case FWUP_STARTED: return "FWUP_STARTED"; 00075 case FWUP_OTHER: return "FWUP_OTHER"; 00076 default: return "unknown"; 00077 } 00078 } 00079 00080 00081 /*! \brief Read a uint32_t from the current position in the xff 00082 */ 00083 uint32_t readUint32(FwUpdate *thisPtr) 00084 { 00085 uint32_t result; 00086 uint8_t buffer[4]; 00087 int n = thisPtr->m_readXffData(buffer, thisPtr->m_readIndex, 4); 00088 thisPtr->m_readIndex += n; 00089 if (n == 4) 00090 { 00091 result = buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3]; 00092 } 00093 else 00094 { 00095 thisPtr->m_endOfFile = 1; 00096 result = 0; 00097 } 00098 return result; 00099 } 00100 00101 00102 /*! \brief Read a uint16_t from the current position in the xff 00103 */ 00104 uint16_t readUint16(FwUpdate *thisPtr) 00105 { 00106 uint16_t result; 00107 uint8_t buffer[2]; 00108 int n = thisPtr->m_readXffData(buffer, thisPtr->m_readIndex, 2); 00109 thisPtr->m_readIndex += n; 00110 if (n == 2) 00111 { 00112 result = buffer[0] << 8 | buffer[1]; 00113 } 00114 else 00115 { 00116 thisPtr->m_endOfFile = 1; 00117 result = 0; 00118 } 00119 return result; 00120 } 00121 00122 00123 /*! \brief Read a uint8_t from the current position in the xff 00124 */ 00125 uint8_t readUint8(FwUpdate *thisPtr) 00126 { 00127 uint8_t result; 00128 uint8_t buffer[1]; 00129 int n = thisPtr->m_readXffData(buffer, thisPtr->m_readIndex, 1); 00130 thisPtr->m_readIndex += n; 00131 if (n == 1) 00132 { 00133 result = buffer[0]; 00134 } 00135 else 00136 { 00137 thisPtr->m_endOfFile = 1; 00138 result = 0; 00139 } 00140 return result; 00141 } 00142 00143 00144 /*! \brief Read an Xff header from the current position in the xff 00145 */ 00146 static void readXffHeader(FwUpdate *thisPtr) 00147 { 00148 LOG("Fwu: readXffHeader()\n"); 00149 00150 thisPtr->m_xffHeader.m_globalId = readUint32(thisPtr); 00151 thisPtr->m_xffHeader.m_sectionSize = readUint32(thisPtr); 00152 thisPtr->m_xffHeader.m_firmwareRevision[0] = readUint8(thisPtr); 00153 thisPtr->m_xffHeader.m_firmwareRevision[1] = readUint8(thisPtr); 00154 thisPtr->m_xffHeader.m_firmwareRevision[2] = readUint8(thisPtr); 00155 thisPtr->m_xffHeader.m_xffVersion[0] = readUint8(thisPtr); 00156 thisPtr->m_xffHeader.m_xffVersion[1] = readUint8(thisPtr); 00157 thisPtr->m_xffHeader.m_chipId = readUint8(thisPtr); 00158 thisPtr->m_xffHeader.m_numberOfSections = readUint8(thisPtr); 00159 thisPtr->m_xffHeader.m_addressLength = readUint8(thisPtr); 00160 thisPtr->m_xffHeader.m_pageSize = readUint16(thisPtr); 00161 if (thisPtr->m_xffHeader.m_xffVersion[0] >= 2) 00162 thisPtr->m_xffHeader.m_sliceSize = readUint16(thisPtr); 00163 else 00164 thisPtr->m_xffHeader.m_sliceSize = FWUP_DEFAULT_SLICE_SIZE; 00165 } 00166 00167 00168 /*! \brief Send an XMID_FIRMWARE_UPDATE xbus message 00169 \param data Pointer to the xbus message payload data 00170 \param length Number of payload bytes 00171 */ 00172 static void sendFirmwareUpdateCommand(FwUpdate *thisPtr, uint8_t *data, uint16_t length) 00173 { 00174 struct XbusMessage xbusMessage; 00175 xbusMessage.m_mid = XMID_FIRMWARE_UPDATE; 00176 xbusMessage.m_length = length; 00177 xbusMessage.m_data = data; 00178 thisPtr->m_sendXbusMessage(&xbusMessage); 00179 } 00180 00181 00182 /*! \brief Send a FWUP_READY command 00183 */ 00184 static void sendReady(FwUpdate *thisPtr) 00185 { 00186 thisPtr->m_txBuffer[0] = FWUP_READY; 00187 sendFirmwareUpdateCommand(thisPtr, thisPtr->m_txBuffer, 1); 00188 } 00189 00190 00191 /*! \brief Send a FWUP_HEADER command 00192 */ 00193 static void sendHeader(FwUpdate *thisPtr) 00194 { 00195 int n; 00196 thisPtr->m_txBuffer[0] = FWUP_HEADER; 00197 n = thisPtr->m_readXffData(&thisPtr->m_txBuffer[1], thisPtr->m_readIndex, thisPtr->m_xffHeader.m_addressLength); 00198 thisPtr->m_readIndex += n; 00199 if (n == thisPtr->m_xffHeader.m_addressLength) 00200 { 00201 memcpy(&thisPtr->m_txBuffer[1 + thisPtr->m_xffHeader.m_addressLength], &thisPtr->m_nofSlicesPerPage, 2); 00202 sendFirmwareUpdateCommand(thisPtr, thisPtr->m_txBuffer, 1 + thisPtr->m_xffHeader.m_addressLength + 2); 00203 } 00204 else 00205 { 00206 thisPtr->m_endOfFile = 1; 00207 } 00208 } 00209 00210 00211 /*! \brief Send a page slice 00212 */ 00213 static void sendSlice(FwUpdate *thisPtr) 00214 { 00215 int n; 00216 thisPtr->m_txBuffer[0] = FWUP_PAGESLICE; 00217 n = thisPtr->m_readXffData(&thisPtr->m_txBuffer[1], thisPtr->m_readIndex, thisPtr->m_xffHeader.m_sliceSize); 00218 thisPtr->m_readIndex += n; 00219 if (n == thisPtr->m_xffHeader.m_sliceSize) 00220 { 00221 sendFirmwareUpdateCommand(thisPtr, thisPtr->m_txBuffer, 1 + thisPtr->m_xffHeader.m_sliceSize); 00222 } 00223 else 00224 { 00225 thisPtr->m_endOfFile = 1; 00226 } 00227 } 00228 00229 00230 /*! \brief Send a FWUP_OTHER command 00231 */ 00232 static void sendOther(FwUpdate *thisPtr) 00233 { 00234 thisPtr->m_txBuffer[0] = FWUP_OTHER; 00235 thisPtr->m_txBuffer[1] = thisPtr->m_xffHeader.m_chipId; 00236 LOG("Fwu: Send FWUP_OTHER\n"); 00237 sendFirmwareUpdateCommand(thisPtr, thisPtr->m_txBuffer, 2); 00238 } 00239 00240 00241 /*! \brief Send a FWUP_FINISHED command 00242 */ 00243 static void sendFinished(FwUpdate *thisPtr) 00244 { 00245 thisPtr->m_txBuffer[0] = FWUP_FINISHED; 00246 LOG("Fwu: Send FWUP_FINISHED\n"); 00247 sendFirmwareUpdateCommand(thisPtr, thisPtr->m_txBuffer, 1); 00248 } 00249 00250 00251 /*! \brief Enter the next section of the xff file 00252 */ 00253 static void enterNewSection(FwUpdate *thisPtr) 00254 { 00255 LOG("\nFwu: enterNewSection()\n"); 00256 readXffHeader(thisPtr); 00257 thisPtr->m_nofPages = thisPtr->m_xffHeader.m_sectionSize / (thisPtr->m_xffHeader.m_pageSize + thisPtr->m_xffHeader.m_addressLength); 00258 thisPtr->m_nofSlicesPerPage = thisPtr->m_xffHeader.m_pageSize / thisPtr->m_xffHeader.m_sliceSize; 00259 thisPtr->m_pageCounter = 0; 00260 thisPtr->m_sliceCounter = 0; 00261 sendOther(thisPtr); 00262 } 00263 00264 00265 /* \brief Public interface of the firmware updater: 00266 */ 00267 00268 /*! \brief Initialize a FwUpdate instance 00269 */ 00270 void FwUpdate_init(FwUpdate *thisPtr) 00271 { 00272 LOG("Fwu: init()\n"); 00273 thisPtr->m_state = STATE_Idle; 00274 } 00275 00276 00277 /*! \brief Start a firmware update 00278 */ 00279 void FwUpdate_start(FwUpdate *thisPtr) 00280 { 00281 if (thisPtr->m_state == STATE_Idle) 00282 { 00283 LOG("Fwu: start() --> Send FWUP_READY\n"); 00284 thisPtr->m_readIndex = 0; 00285 thisPtr->m_endOfFile = 0; 00286 thisPtr->m_state = STATE_Start; 00287 sendReady(thisPtr); 00288 } 00289 else 00290 { 00291 thisPtr->m_readyHandler(FWU_Failed); 00292 LOG("Fwu: start() failed\n"); 00293 } 00294 } 00295 00296 00297 /*! \brief Handle xbus message coming from the module 00298 \param xbusMessage The xbus message from the module to be handled 00299 */ 00300 void FwUpdate_handleXbus(FwUpdate* thisPtr, struct XbusMessage* xbusMessage) 00301 { 00302 uint8_t ack; 00303 if (xbusMessage->m_mid != XMID_FIRMWARE_UPDATE) 00304 { 00305 LOG("Fwu: Got unhandled xbus message 0x%02X (ignored)\n", xbusMessage->m_mid); 00306 return; 00307 } 00308 00309 ack = xbusMessage->m_data[0]; 00310 00311 switch (thisPtr->m_state) 00312 { 00313 case STATE_Idle: 00314 { 00315 LOG("Fwu: Got %s in STATE_Idle (ignored)\n", ackToString(ack)); 00316 } break; 00317 00318 case STATE_Start: 00319 { 00320 if (ack == FWUP_READY) 00321 { 00322 LOG("Fwu: FWUP_READY in STATE_Start --> Enter new section\n"); 00323 enterNewSection(thisPtr); 00324 thisPtr->m_state = STATE_WaitReady; 00325 } 00326 else 00327 { 00328 LOG("Fwu: Got %s in STATE_Start (ignored)\n", ackToString(ack)); 00329 } 00330 } break; 00331 00332 case STATE_WaitReady: 00333 { 00334 if (ack == FWUP_READY) 00335 { 00336 LOG("Fwu: FWUP_READY in STATE_WaitReady --> Send header\n"); 00337 sendHeader(thisPtr); 00338 thisPtr->m_state = STATE_WaitHeaderResult; 00339 } 00340 else 00341 { 00342 LOG("Fwu: Got %s in STATE_WaitReady --> Failed\n", ackToString(ack)); 00343 thisPtr->m_readyHandler(FWU_Failed); 00344 thisPtr->m_state = STATE_Idle; 00345 } 00346 } break; 00347 00348 case STATE_WaitHeaderResult: 00349 { 00350 if (ack == FWUP_READY) 00351 { 00352 LOG("Fwu: FWUP_READY in STATE_WaitHeaderResult --> Send first slice\n"); 00353 sendSlice(thisPtr); 00354 thisPtr->m_sliceCounter = 1; 00355 thisPtr->m_state = STATE_WaitSliceReady; 00356 } 00357 else 00358 { 00359 LOG("Fwu: Got %s in STATE_WaitHeaderResult --> Failed\n", ackToString(ack)); 00360 thisPtr->m_readyHandler(FWU_Failed); 00361 thisPtr->m_state = STATE_Idle; 00362 } 00363 } break; 00364 00365 case STATE_WaitSliceReady: 00366 { 00367 if (ack == FWUP_READY) 00368 { 00369 if (thisPtr->m_sliceCounter < thisPtr->m_nofSlicesPerPage) 00370 { 00371 LOG("Fwu: FWUP_READY in STATE_WaitSliceReady --> Send slice %d\n", thisPtr->m_sliceCounter); 00372 sendSlice(thisPtr); 00373 thisPtr->m_sliceCounter++; 00374 } 00375 else 00376 { 00377 LOG("Fwu: All slices sent --> STATE_WaitPageOk\n"); 00378 thisPtr->m_state = STATE_WaitPageOk; 00379 } 00380 } 00381 else 00382 { 00383 LOG("Fwu: Got %s in STATE_WaitSliceReady --> Failed\n", ackToString(ack)); 00384 thisPtr->m_readyHandler(FWU_Failed); 00385 thisPtr->m_state = STATE_Idle; 00386 } 00387 } break; 00388 00389 case STATE_WaitPageOk: 00390 { 00391 if (ack == FWUP_OK) 00392 { 00393 LOG("Fwu: FWUP_OK in STATE_WaitPageOk --> STATE_WaitPageReady\n"); 00394 thisPtr->m_state = STATE_WaitPageReady; 00395 } 00396 else 00397 { 00398 LOG("Fwu: Got %s in STATE_WaitPageOk --> Failed\n", ackToString(ack)); 00399 thisPtr->m_readyHandler(FWU_Failed); 00400 thisPtr->m_state = STATE_Idle; 00401 } 00402 } break; 00403 00404 case STATE_WaitPageReady: 00405 { 00406 if (ack == FWUP_READY) 00407 { 00408 thisPtr->m_pageCounter++; 00409 if (thisPtr->m_nofPages != 0 && thisPtr->m_pageCounter == thisPtr->m_nofPages) 00410 { 00411 LOG("Fwu: All pages sent --> Enter new section\n"); 00412 enterNewSection(thisPtr); 00413 thisPtr->m_state = STATE_WaitReady; 00414 } 00415 else 00416 { 00417 sendHeader(thisPtr); 00418 if (thisPtr->m_endOfFile) 00419 { 00420 LOG("Fwu: End of file --> Firmware update done\n"); 00421 sendFinished(thisPtr); 00422 thisPtr->m_readyHandler(FWU_Success); 00423 thisPtr->m_state = STATE_Idle; 00424 } 00425 else 00426 { 00427 LOG("Fwu: FWUP_READY in STATE_WaitPageReady --> Send header\n"); 00428 thisPtr->m_state = STATE_WaitHeaderResult; 00429 } 00430 } 00431 } 00432 else 00433 { 00434 LOG("Fwu: Got %s in STATE_WaitPageReady --> Failed\n", ackToString(ack)); 00435 thisPtr->m_readyHandler(FWU_Failed); 00436 thisPtr->m_state = STATE_Idle; 00437 } 00438 } break; 00439 00440 default: 00441 { 00442 } 00443 } 00444 } 00445 00446
Generated on Wed Jul 13 2022 07:56:15 by
1.7.2