hal_oad.c 17 KB

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