hal_ota.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532
  1. /******************************************************************************
  2. Filename: hal_ota.c
  3. Revised: $Date: 2010-11-18 08:22:50 -0800 (Thu, 18 Nov 2010) $
  4. Revision: $Revision: 24438 $
  5. Description: This module contains optionally-compiled Boot Code to support
  6. OTA. The rest of the functionality is the H/W specific drivers
  7. to read/write the flash/NV containing the ACTIVE and the
  8. DOWNLOADED images.
  9. Notes: Targets the Texas Instruments CC253x family of processors.
  10. Copyright 2010 Texas Instruments Incorporated. All rights reserved.
  11. IMPORTANT: Your use of this Software is limited to those specific rights
  12. granted under the terms of a software license agreement between the user
  13. who downloaded the software, his/her employer (which must be your employer)
  14. and Texas Instruments Incorporated (the "License"). You may not use this
  15. Software unless you agree to abide by the terms of the License. The License
  16. limits your use, and you acknowledge, that the Software may not be modified,
  17. copied or distributed unless embedded on a Texas Instruments microcontroller
  18. or used solely and exclusively in conjunction with a Texas Instruments radio
  19. frequency transceiver, which is integrated into your product. Other than for
  20. the foregoing purpose, you may not use, reproduce, copy, prepare derivative
  21. works of, modify, distribute, perform, display or sell this Software and/or
  22. its documentation for any purpose.
  23. YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE
  24. PROVIDED “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,
  25. INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE,
  26. NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL
  27. TEXAS INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT,
  28. NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER
  29. LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
  30. INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE
  31. OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT
  32. OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
  33. (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
  34. Should you have any questions regarding your right to use this Software,
  35. contact Texas Instruments Incorporated at www.TI.com.
  36. ******************************************************************************/
  37. /******************************************************************************
  38. * INCLUDES
  39. */
  40. #include "comdef.h"
  41. #include "hal_board_cfg.h"
  42. #include "hal_dma.h"
  43. #include "hal_flash.h"
  44. #include "hal_ota.h"
  45. #include "hal_types.h"
  46. #include "ota_common.h"
  47. /******************************************************************************
  48. * CONSTANTS
  49. */
  50. #if HAL_OTA_XNV_IS_SPI
  51. #define XNV_STAT_CMD 0x05
  52. #define XNV_WREN_CMD 0x06
  53. #define XNV_WRPG_CMD 0x0A
  54. #define XNV_READ_CMD 0x0B
  55. #define XNV_STAT_WIP 0x01
  56. #endif
  57. /******************************************************************************
  58. * TYPEDEFS
  59. */
  60. typedef struct
  61. {
  62. uint16 crc[2];
  63. uint32 programSize;
  64. } OTA_CrcControl_t;
  65. /******************************************************************************
  66. * LOCAL VARIABLES
  67. */
  68. OTA_CrcControl_t OTA_crcControl;
  69. #if HAL_OTA_BOOT_CODE
  70. halDMADesc_t dmaCh0;
  71. #endif
  72. /******************************************************************************
  73. * LOCAL FUNCTIONS
  74. */
  75. static uint16 runPoly(uint16 crc, uint8 val);
  76. #if HAL_OTA_XNV_IS_SPI
  77. static void HalSPIRead(uint32 addr, uint8 *pBuf, uint16 len);
  78. static void HalSPIWrite(uint32 addr, uint8 *pBuf, uint16 len);
  79. static void xnvSPIWrite(uint8 ch);
  80. #endif
  81. #if HAL_OTA_BOOT_CODE
  82. static void dl2rc(void);
  83. static uint16 crcCalc(void);
  84. /******************************************************************************
  85. * @fn main
  86. *
  87. * @brief ISR for the reset vector.
  88. *
  89. * @param None.
  90. *
  91. * @return None.
  92. */
  93. #pragma location="NEAR_CODE"
  94. void main(void)
  95. {
  96. HAL_BOARD_INIT();
  97. #if HAL_OTA_XNV_IS_SPI
  98. XNV_SPI_INIT();
  99. #endif
  100. /* This is in place of calling HalDmaInit() which would require init of the
  101. * other 4 DMA descriptors in addition to just Channel 0.
  102. */
  103. HAL_DMA_SET_ADDR_DESC0( &dmaCh0 );
  104. while (1)
  105. {
  106. HalFlashRead(HAL_OTA_CRC_ADDR / HAL_FLASH_PAGE_SIZE,
  107. HAL_OTA_CRC_ADDR % HAL_FLASH_PAGE_SIZE,
  108. (uint8 *)&OTA_crcControl, sizeof(OTA_crcControl));
  109. if (OTA_crcControl.crc[0] == OTA_crcControl.crc[1])
  110. {
  111. break;
  112. }
  113. else if ((OTA_crcControl.crc[0] != 0) && (OTA_crcControl.crc[0] == crcCalc()))
  114. {
  115. OTA_crcControl.crc[1] = OTA_crcControl.crc[0];
  116. HalFlashWrite((HAL_OTA_CRC_ADDR / HAL_FLASH_WORD_SIZE), (uint8 *)OTA_crcControl.crc, 1);
  117. }
  118. else
  119. {
  120. dl2rc();
  121. }
  122. }
  123. // Simulate a reset for the Application code by an absolute jump to location 0x0800.
  124. asm("LJMP 0x800\n");
  125. }
  126. /******************************************************************************
  127. * @fn dl2rc
  128. *
  129. * @brief Copy the DL image to the RC image location.
  130. *
  131. * NOTE: Assumes that DL image ends on a flash word boundary.
  132. *
  133. * @param None.
  134. *
  135. * @return None.
  136. */
  137. static void dl2rc(void)
  138. {
  139. uint32 oset;
  140. OTA_SubElementHdr_t subElement;
  141. OTA_ImageHeader_t header;
  142. uint16 addr = HAL_OTA_RC_START / HAL_FLASH_WORD_SIZE;
  143. uint8 buf[4];
  144. // Determine the length and starting point of the upgrade image
  145. HalOTARead(0, (uint8 *)&header, sizeof(OTA_ImageHeader_t), HAL_OTA_DL);
  146. HalOTARead(header.headerLength, (uint8*)&subElement, OTA_SUB_ELEMENT_HDR_LEN, HAL_OTA_DL);
  147. for (oset = 0; oset < subElement.length; oset += HAL_FLASH_WORD_SIZE)
  148. {
  149. HalOTARead(oset + header.headerLength + OTA_SUB_ELEMENT_HDR_LEN, buf, HAL_FLASH_WORD_SIZE, HAL_OTA_DL);
  150. if ((addr % (HAL_FLASH_PAGE_SIZE / HAL_FLASH_WORD_SIZE)) == 0)
  151. {
  152. HalFlashErase(addr / (HAL_FLASH_PAGE_SIZE / HAL_FLASH_WORD_SIZE));
  153. }
  154. HalFlashWrite(addr++, buf, 1);
  155. }
  156. }
  157. /******************************************************************************
  158. * @fn crcCalc
  159. *
  160. * @brief Run the CRC16 Polynomial calculation over the RC image.
  161. *
  162. * @param None.
  163. *
  164. * @return The CRC16 calculated.
  165. */
  166. static uint16 crcCalc()
  167. {
  168. uint32 oset;
  169. uint16 crc = 0;
  170. // Run the CRC calculation over the active body of code.
  171. for (oset = 0; oset < OTA_crcControl.programSize; oset++)
  172. {
  173. if ((oset < HAL_OTA_CRC_OSET) || (oset >= HAL_OTA_CRC_OSET + 4))
  174. {
  175. uint8 buf;
  176. HalOTARead(oset, &buf, 1, HAL_OTA_RC);
  177. crc = runPoly(crc, buf);
  178. }
  179. }
  180. return crc;
  181. }
  182. #endif //HAL_OTA_BOOT_CODE
  183. /******************************************************************************
  184. * @fn runPoly
  185. *
  186. * @brief Run the CRC16 Polynomial calculation over the byte parameter.
  187. *
  188. * @param crc - Running CRC calculated so far.
  189. * @param val - Value on which to run the CRC16.
  190. *
  191. * @return crc - Updated for the run.
  192. */
  193. static uint16 runPoly(uint16 crc, uint8 val)
  194. {
  195. const uint16 poly = 0x1021;
  196. uint8 cnt;
  197. for (cnt = 0; cnt < 8; cnt++, val <<= 1)
  198. {
  199. uint8 msb = (crc & 0x8000) ? 1 : 0;
  200. crc <<= 1;
  201. if (val & 0x80) crc |= 0x0001;
  202. if (msb) crc ^= poly;
  203. }
  204. return crc;
  205. }
  206. /******************************************************************************
  207. * @fn HalOTAChkDL
  208. *
  209. * @brief Run the CRC16 Polynomial calculation over the DL image.
  210. *
  211. * @param None
  212. *
  213. * @return SUCCESS or FAILURE.
  214. */
  215. uint8 HalOTAChkDL(uint8 dlImagePreambleOffset)
  216. {
  217. (void)dlImagePreambleOffset; // Intentionally unreferenced parameter
  218. uint32 oset;
  219. uint16 crc = 0;
  220. OTA_CrcControl_t crcControl;
  221. OTA_ImageHeader_t header;
  222. uint32 programStart;
  223. #if HAL_OTA_XNV_IS_SPI
  224. XNV_SPI_INIT();
  225. #endif
  226. // Read the OTA File Header
  227. HalOTARead(0, (uint8 *)&header, sizeof(OTA_ImageHeader_t), HAL_OTA_DL);
  228. // Calculate the update image start address
  229. programStart = header.headerLength + OTA_SUB_ELEMENT_HDR_LEN;
  230. // Get the CRC Control structure
  231. HalOTARead(programStart + HAL_OTA_CRC_OSET, (uint8 *)&crcControl, sizeof(crcControl), HAL_OTA_DL);
  232. if ((crcControl.programSize > HAL_OTA_DL_MAX) || (crcControl.programSize == 0))
  233. {
  234. return FAILURE;
  235. }
  236. // Run the CRC calculation over the downloaded image.
  237. for (oset = 0; oset < crcControl.programSize; oset++)
  238. {
  239. if ((oset < HAL_OTA_CRC_OSET) || (oset >= HAL_OTA_CRC_OSET+4))
  240. {
  241. uint8 buf;
  242. HalOTARead(oset + programStart, &buf, 1, HAL_OTA_DL);
  243. crc = runPoly(crc, buf);
  244. }
  245. }
  246. return (crcControl.crc[0] == crc) ? SUCCESS : FAILURE;
  247. }
  248. /******************************************************************************
  249. * @fn HalOTAInvRC
  250. *
  251. * @brief Invalidate the active image so that the boot code will instantiate
  252. * the DL image on the next reset.
  253. *
  254. * @param None.
  255. *
  256. * @return None.
  257. */
  258. void HalOTAInvRC(void)
  259. {
  260. uint16 crc[2] = {0,0xFFFF};
  261. HalFlashWrite((HAL_OTA_CRC_ADDR / HAL_FLASH_WORD_SIZE), (uint8 *)crc, 1);
  262. }
  263. /******************************************************************************
  264. * @fn HalOTARead
  265. *
  266. * @brief Read from the storage medium according to image type.
  267. *
  268. * @param oset - Offset into the monolithic image.
  269. * @param pBuf - Pointer to the buffer in which to copy the bytes read.
  270. * @param len - Number of bytes to read.
  271. * @param type - Which image: HAL_OTA_RC or HAL_OTA_DL.
  272. *
  273. * @return None.
  274. */
  275. void HalOTARead(uint32 oset, uint8 *pBuf, uint16 len, image_t type)
  276. {
  277. if (HAL_OTA_RC != type)
  278. {
  279. #if HAL_OTA_XNV_IS_INT
  280. preamble_t preamble;
  281. HalOTARead(PREAMBLE_OFFSET, (uint8 *)&preamble, sizeof(preamble_t), HAL_OTA_RC);
  282. oset += HAL_OTA_RC_START + HAL_OTA_DL_OSET;
  283. #elif HAL_OTA_XNV_IS_SPI
  284. oset += HAL_OTA_DL_OSET;
  285. HalSPIRead(oset, pBuf, len);
  286. return;
  287. #endif
  288. }
  289. else
  290. {
  291. oset += HAL_OTA_RC_START;
  292. }
  293. HalFlashRead(oset / HAL_FLASH_PAGE_SIZE, oset % HAL_FLASH_PAGE_SIZE, pBuf, len);
  294. }
  295. /******************************************************************************
  296. * @fn HalOTAWrite
  297. *
  298. * @brief Write to the storage medium according to the image type.
  299. *
  300. * NOTE: Destructive write on page boundary! When writing to the first flash word
  301. * of a page boundary, the page is erased without saving/restoring the bytes not written.
  302. * Writes anywhere else on a page assume that the location written to has been erased.
  303. *
  304. * @param oset - Offset into the monolithic image, aligned to HAL_FLASH_WORD_SIZE.
  305. * @param pBuf - Pointer to the buffer in from which to write.
  306. * @param len - Number of bytes to write. If not an even multiple of HAL_FLASH_WORD_SIZE,
  307. * remainder bytes are overwritten with garbage.
  308. * @param type - Which image: HAL_OTA_RC or HAL_OTA_DL.
  309. *
  310. * @return None.
  311. */
  312. void HalOTAWrite(uint32 oset, uint8 *pBuf, uint16 len, image_t type)
  313. {
  314. if (HAL_OTA_RC != type)
  315. {
  316. #if HAL_OTA_XNV_IS_INT
  317. oset += HAL_OTA_RC_START + HAL_OTA_DL_OSET;
  318. #elif HAL_OTA_XNV_IS_SPI
  319. oset += HAL_OTA_DL_OSET;
  320. HalSPIWrite(oset, pBuf, len);
  321. return;
  322. #endif
  323. }
  324. else
  325. {
  326. oset += HAL_OTA_RC_START;
  327. }
  328. if ((oset % HAL_FLASH_PAGE_SIZE) == 0)
  329. {
  330. HalFlashErase(oset / HAL_FLASH_PAGE_SIZE);
  331. }
  332. HalFlashWrite(oset / HAL_FLASH_WORD_SIZE, pBuf, len / HAL_FLASH_WORD_SIZE);
  333. }
  334. /******************************************************************************
  335. * @fn HalOTAAvail
  336. *
  337. * @brief Determine the space available for downloading an image.
  338. *
  339. * @param None.
  340. *
  341. * @return Number of bytes available for storing an OTA image.
  342. */
  343. uint32 HalOTAAvail(void)
  344. {
  345. return HAL_OTA_DL_MAX - HAL_OTA_DL_OSET;
  346. }
  347. #if HAL_OTA_XNV_IS_SPI
  348. /******************************************************************************
  349. * @fn xnvSPIWrite
  350. *
  351. * @brief SPI write sequence for code size savings.
  352. *
  353. * @param ch - The byte to write to the SPI.
  354. *
  355. * @return None.
  356. */
  357. static void xnvSPIWrite(uint8 ch)
  358. {
  359. XNV_SPI_TX(ch);
  360. XNV_SPI_WAIT_RXRDY();
  361. }
  362. /******************************************************************************
  363. * @fn HalSPIRead
  364. *
  365. * @brief Read from the external NV storage via SPI.
  366. *
  367. * @param addr - Offset into the external NV.
  368. * @param pBuf - Pointer to buffer to copy the bytes read from external NV.
  369. * @param len - Number of bytes to read from external NV.
  370. *
  371. * @return None.
  372. *****************************************************************************/
  373. static void HalSPIRead(uint32 addr, uint8 *pBuf, uint16 len)
  374. {
  375. #if !HAL_OTA_BOOT_CODE
  376. uint8 shdw = P1DIR;
  377. halIntState_t his;
  378. HAL_ENTER_CRITICAL_SECTION(his);
  379. P1DIR |= BV(3);
  380. #endif
  381. XNV_SPI_BEGIN();
  382. do
  383. {
  384. xnvSPIWrite(XNV_STAT_CMD);
  385. } while (XNV_SPI_RX() & XNV_STAT_WIP);
  386. XNV_SPI_END();
  387. asm("NOP"); asm("NOP");
  388. XNV_SPI_BEGIN();
  389. xnvSPIWrite(XNV_READ_CMD);
  390. xnvSPIWrite(addr >> 16);
  391. xnvSPIWrite(addr >> 8);
  392. xnvSPIWrite(addr);
  393. xnvSPIWrite(0);
  394. while (len--)
  395. {
  396. xnvSPIWrite(0);
  397. *pBuf++ = XNV_SPI_RX();
  398. }
  399. XNV_SPI_END();
  400. #if !HAL_OTA_BOOT_CODE
  401. P1DIR = shdw;
  402. HAL_EXIT_CRITICAL_SECTION(his);
  403. #endif
  404. }
  405. /******************************************************************************
  406. * @fn HalSPIWrite
  407. *
  408. * @brief Write to the external NV storage via SPI.
  409. *
  410. * @param addr - Offset into the external NV.
  411. * @param pBuf - Pointer to the buffer in from which to write bytes to external NV.
  412. * @param len - Number of bytes to write to external NV.
  413. *
  414. * @return None.
  415. *****************************************************************************/
  416. static void HalSPIWrite(uint32 addr, uint8 *pBuf, uint16 len)
  417. {
  418. uint8 cnt;
  419. #if !HAL_OTA_BOOT_CODE
  420. uint8 shdw = P1DIR;
  421. halIntState_t his;
  422. HAL_ENTER_CRITICAL_SECTION(his);
  423. P1DIR |= BV(3);
  424. #endif
  425. while (len)
  426. {
  427. XNV_SPI_BEGIN();
  428. do
  429. {
  430. xnvSPIWrite(XNV_STAT_CMD);
  431. } while (XNV_SPI_RX() & XNV_STAT_WIP);
  432. XNV_SPI_END();
  433. asm("NOP"); asm("NOP");
  434. XNV_SPI_BEGIN();
  435. xnvSPIWrite(XNV_WREN_CMD);
  436. XNV_SPI_END();
  437. asm("NOP"); asm("NOP");
  438. XNV_SPI_BEGIN();
  439. xnvSPIWrite(XNV_WRPG_CMD);
  440. xnvSPIWrite(addr >> 16);
  441. xnvSPIWrite(addr >> 8);
  442. xnvSPIWrite(addr);
  443. // Can only write within any one page boundary, so prepare for next page write if bytes remain.
  444. cnt = 0 - (uint8)addr;
  445. if (cnt)
  446. {
  447. addr += cnt;
  448. }
  449. else
  450. {
  451. addr += 256;
  452. }
  453. do
  454. {
  455. xnvSPIWrite(*pBuf++);
  456. cnt--;
  457. len--;
  458. } while (len && cnt);
  459. XNV_SPI_END();
  460. }
  461. #if !HAL_OTA_BOOT_CODE
  462. P1DIR = shdw;
  463. HAL_EXIT_CRITICAL_SECTION(his);
  464. #endif
  465. }
  466. #elif !HAL_OTA_XNV_IS_INT
  467. #error Invalid Xtra-NV for OTA.
  468. #endif
  469. /******************************************************************************
  470. */