123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577 |
- /**************************************************************************************************
- Filename: _hal_oad.c
- Revised: $Date: 2010-07-08 18:39:25 -0700 (Thu, 08 Jul 2010) $
- Revision: $Revision: 22957 $
- Description: This module contains optionally-compiled Boot Code to support OAD.
- The rest of the functionality is the H/W specific drivers to read/write
- the flash/NV containing the ACTIVE and the DOWNLOADED images.
- Notes: This version targets the Texas Instruments CC253x family of processors.
- Copyright 2008-2010 Texas Instruments Incorporated. All rights reserved.
- IMPORTANT: Your use of this Software is limited to those specific rights
- granted under the terms of a software license agreement between the user
- who downloaded the software, his/her employer (which must be your employer)
- and Texas Instruments Incorporated (the "License"). You may not use this
- Software unless you agree to abide by the terms of the License. The License
- limits your use, and you acknowledge, that the Software may not be modified,
- copied or distributed unless embedded on a Texas Instruments microcontroller
- or used solely and exclusively in conjunction with a Texas Instruments radio
- frequency transceiver, which is integrated into your product. Other than for
- the foregoing purpose, you may not use, reproduce, copy, prepare derivative
- works of, modify, distribute, perform, display or sell this Software and/or
- its documentation for any purpose.
- YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE
- PROVIDED “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,
- INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE,
- NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL
- TEXAS INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT,
- NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER
- LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
- INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE
- OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT
- OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
- (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
- Should you have any questions regarding your right to use this Software,
- contact Texas Instruments Incorporated at www.TI.com.
- **************************************************************************************************/
- /* ------------------------------------------------------------------------------------------------
- * Includes
- * ------------------------------------------------------------------------------------------------
- */
- #include "comdef.h"
- #include "hal_board_cfg.h"
- #include "hal_dma.h"
- #include "hal_flash.h"
- #include "hal_oad.h"
- #include "hal_types.h"
- /* ------------------------------------------------------------------------------------------------
- * Local Variables
- * ------------------------------------------------------------------------------------------------
- */
- #if HAL_OAD_BOOT_CODE
- halDMADesc_t dmaCh0;
- #endif
- /* ------------------------------------------------------------------------------------------------
- * Local Functions
- * ------------------------------------------------------------------------------------------------
- */
- static uint16 runPoly(uint16 crc, uint8 val);
- #if HAL_OAD_XNV_IS_SPI
- static void HalSPIRead(uint32 addr, uint8 *pBuf, uint16 len);
- static void HalSPIWrite(uint32 addr, uint8 *pBuf, uint16 len);
- #endif
- #if HAL_OAD_BOOT_CODE
- static void vddWait(uint8 vdd);
- static void dl2rc(void);
- static uint16 crcCalc(void);
- /**************************************************************************************************
- * @fn main
- *
- * @brief ISR for the reset vector.
- *
- * input parameters
- *
- * None.
- *
- * output parameters
- *
- * None.
- *
- * @return None.
- **************************************************************************************************
- */
- #pragma location="NEAR_CODE"
- void main(void)
- {
- HAL_BOARD_INIT();
- vddWait(VDD_MIN_RUN);
-
- #if HAL_OAD_XNV_IS_SPI
- XNV_SPI_INIT();
- #endif
- /* This is in place of calling HalDmaInit() which would require init of the other 4 DMA
- * descriptors in addition to just Channel 0.
- */
- HAL_DMA_SET_ADDR_DESC0( &dmaCh0 );
- while (1)
- {
- uint16 crc[2];
- HalFlashRead(HAL_OAD_CRC_ADDR / HAL_FLASH_PAGE_SIZE,
- HAL_OAD_CRC_ADDR % HAL_FLASH_PAGE_SIZE,
- (uint8 *)crc, sizeof(crc));
- if (crc[0] == crc[1])
- {
- break;
- }
- else if ((crc[0] != 0) && (crc[0] == crcCalc()))
- {
- crc[1] = crc[0];
- HalFlashWrite((HAL_OAD_CRC_ADDR / HAL_FLASH_WORD_SIZE), (uint8 *)crc, 1);
- }
- else
- {
- dl2rc();
- }
- }
- // Simulate a reset for the Application code by an absolute jump to location 0x0800.
- asm("LJMP 0x800\n");
- }
- /*********************************************************************
- * @fn vddWait
- *
- * @brief Loop waiting for 256 reads of the Vdd over the requested limit.
- *
- * @param vdd - Vdd level to wait for.
- *
- * @return None.
- *********************************************************************/
- static void vddWait(uint8 vdd)
- {
- uint8 cnt = 16;
- do {
- do {
- ADCCON3 = 0x0F;
- while (!(ADCCON1 & 0x80));
- } while (ADCH < vdd);
- } while (--cnt);
- }
- /*********************************************************************
- * @fn dl2rc
- *
- * @brief Copy the DL image to the RC image location.
- *
- * NOTE: Assumes that DL image ends on a flash word boundary.
- *
- * @param None.
- *
- * @return None.
- *********************************************************************/
- static void dl2rc(void)
- {
- preamble_t preamble;
- uint32 oset;
- uint16 addr = HAL_OAD_RC_START / HAL_FLASH_WORD_SIZE;
- uint8 buf[4];
- vddWait(VDD_MIN_OAD);
- HalOADRead(PREAMBLE_OFFSET, (uint8 *)&preamble, sizeof(preamble_t), HAL_OAD_DL);
- for (oset = 0; oset < preamble.len; oset += HAL_FLASH_WORD_SIZE)
- {
- HalOADRead(oset, buf, HAL_FLASH_WORD_SIZE, HAL_OAD_DL);
- if ((addr % (HAL_FLASH_PAGE_SIZE / HAL_FLASH_WORD_SIZE)) == 0)
- {
- HalFlashErase(addr / (HAL_FLASH_PAGE_SIZE / HAL_FLASH_WORD_SIZE));
- }
- HalFlashWrite(addr++, buf, 1);
- }
- }
- /*********************************************************************
- * @fn crcCalc
- *
- * @brief Run the CRC16 Polynomial calculation over the RC image.
- *
- * @param None.
- *
- * @return The CRC16 calculated.
- */
- static uint16 crcCalc(void)
- {
- preamble_t preamble;
- uint32 oset;
- uint16 crc = 0;
- HalOADRead(PREAMBLE_OFFSET, (uint8 *)&preamble, sizeof(preamble_t), HAL_OAD_RC);
- if (preamble.len > HAL_OAD_DL_SIZE)
- {
- return 0;
- }
- // Run the CRC calculation over the active body of code.
- for (oset = 0; oset < preamble.len; oset++)
- {
- if (oset == HAL_OAD_CRC_OSET)
- {
- oset += 3;
- }
- else
- {
- uint8 buf;
- HalOADRead(oset, &buf, 1, HAL_OAD_RC);
- crc = runPoly(crc, buf);
- }
- }
- // IAR note explains that poly must be run with value zero for each byte of crc.
- crc = runPoly(crc, 0);
- crc = runPoly(crc, 0);
- return crc;
- }
- #endif
- /*********************************************************************
- * @fn runPoly
- *
- * @brief Run the CRC16 Polynomial calculation over the byte parameter.
- *
- * @param crc - Running CRC calculated so far.
- * @param val - Value on which to run the CRC16.
- *
- * @return crc - Updated for the run.
- */
- static uint16 runPoly(uint16 crc, uint8 val)
- {
- const uint16 poly = 0x1021;
- uint8 cnt;
- for (cnt = 0; cnt < 8; cnt++, val <<= 1)
- {
- uint8 msb = (crc & 0x8000) ? 1 : 0;
- crc <<= 1;
- if (val & 0x80) crc |= 0x0001;
- if (msb) crc ^= poly;
- }
- return crc;
- }
- /*********************************************************************
- * @fn HalOADChkDL
- *
- * @brief Run the CRC16 Polynomial calculation over the DL image.
- *
- * @param dlImagePreambleOffset - Offset into the monolithic DL image to read the preamble.
- *
- * @return SUCCESS or FAILURE.
- *********************************************************************/
- uint8 HalOADChkDL(uint8 dlImagePreambleOffset)
- {
- preamble_t preamble;
- uint32 oset;
- uint16 crc = 0, crc2;
- HalOADRead(dlImagePreambleOffset, (uint8 *)&preamble, sizeof(preamble_t), HAL_OAD_DL);
- // Run the CRC calculation over the downloaded image.
- for (oset = 0; oset < preamble.len; oset++)
- {
- if ((oset < HAL_OAD_CRC_OSET) || (oset >= HAL_OAD_CRC_OSET+4))
- {
- uint8 buf;
- HalOADRead(oset, &buf, 1, HAL_OAD_DL);
- crc = runPoly(crc, buf);
- }
- }
- // IAR note explains that poly must be run with value zero for each byte of crc.
- crc = runPoly(crc, 0);
- crc = runPoly(crc, 0);
- HalOADRead(HAL_OAD_CRC_OSET, (uint8 *)&crc2, sizeof(crc2), HAL_OAD_DL);
- return (crc2 == crc) ? SUCCESS : FAILURE;
- }
- /*********************************************************************
- * @fn HalOADInvRC
- *
- * @brief Invalidate the active image so that the boot code will instantiate the DL image on the
- * next reset.
- *
- * @param None.
- *
- * @return None.
- *********************************************************************/
- void HalOADInvRC(void)
- {
- uint16 crc[2] = {0,0xFFFF};
- HalFlashWrite((HAL_OAD_CRC_ADDR / HAL_FLASH_WORD_SIZE), (uint8 *)crc, 1);
- }
- /*********************************************************************
- * @fn HalOADRead
- *
- * @brief Read from the storage medium according to image type.
- *
- * @param oset - Offset into the monolithic image.
- * @param pBuf - Pointer to the buffer in which to copy the bytes read.
- * @param len - Number of bytes to read.
- * @param type - Which image: HAL_OAD_RC or HAL_OAD_DL.
- *
- * @return None.
- *********************************************************************/
- void HalOADRead(uint32 oset, uint8 *pBuf, uint16 len, image_t type)
- {
- if (HAL_OAD_RC != type)
- {
- #if HAL_OAD_XNV_IS_INT
- preamble_t preamble;
- HalOADRead(PREAMBLE_OFFSET, (uint8 *)&preamble, sizeof(preamble_t), HAL_OAD_RC);
- //oset += HAL_OAD_RC_START + preamble.len;
- oset += HAL_OAD_RC_START + HAL_OAD_DL_OSET;
- #elif HAL_OAD_XNV_IS_SPI
- oset += HAL_OAD_DL_OSET;
- HalSPIRead(oset, pBuf, len);
- return;
- #endif
- }
- else
- {
- oset += HAL_OAD_RC_START;
- }
- HalFlashRead(oset / HAL_FLASH_PAGE_SIZE, oset % HAL_FLASH_PAGE_SIZE, pBuf, len);
- }
- /*********************************************************************
- * @fn HalOADWrite
- *
- * @brief Write to the storage medium according to the image type.
- *
- * NOTE: Destructive write on page boundary! When writing to the first flash word
- * of a page boundary, the page is erased without saving/restoring the bytes not written.
- * Writes anywhere else on a page assume that the location written to has been erased.
- *
- * @param oset - Offset into the monolithic image, aligned to HAL_FLASH_WORD_SIZE.
- * @param pBuf - Pointer to the buffer in from which to write.
- * @param len - Number of bytes to write. If not an even multiple of HAL_FLASH_WORD_SIZE,
- * remainder bytes are overwritten with garbage.
- * @param type - Which image: HAL_OAD_RC or HAL_OAD_DL.
- *
- * @return None.
- *********************************************************************/
- void HalOADWrite(uint32 oset, uint8 *pBuf, uint16 len, image_t type)
- {
- if (HAL_OAD_RC != type)
- {
- #if HAL_OAD_XNV_IS_INT
- preamble_t preamble;
- HalOADRead(PREAMBLE_OFFSET, (uint8 *)&preamble, sizeof(preamble_t), HAL_OAD_RC);
- //oset += HAL_OAD_RC_START + preamble.len;
- oset += HAL_OAD_RC_START + HAL_OAD_DL_OSET;
- #elif HAL_OAD_XNV_IS_SPI
- oset += HAL_OAD_DL_OSET;
- HalSPIWrite(oset, pBuf, len);
- return;
- #endif
- }
- else
- {
- oset += HAL_OAD_RC_START;
- }
- if ((oset % HAL_FLASH_PAGE_SIZE) == 0)
- {
- HalFlashErase(oset / HAL_FLASH_PAGE_SIZE);
- }
- HalFlashWrite(oset / HAL_FLASH_WORD_SIZE, pBuf, len / HAL_FLASH_WORD_SIZE);
- }
- #if HAL_OAD_XNV_IS_INT
- /*********************************************************************
- * @fn HalOADAvail
- *
- * @brief Determine the space available for downloading an image.
- *
- * @param None.
- *
- * @return Number of bytes available for storing an OAD image.
- *********************************************************************/
- uint32 HalOADAvail(void)
- {
- /*
- preamble_t preamble;
- HalOADRead(PREAMBLE_OFFSET, (uint8 *)&preamble, sizeof(preamble_t), HAL_OAD_RC);
- return HAL_OAD_DL_MAX - preamble.len;
- */
- return HAL_OAD_DL_MAX - HAL_OAD_DL_OSET;
- }
- #elif HAL_OAD_XNV_IS_SPI
- /*********************************************************************
- * CONSTANTS
- */
- #define XNV_STAT_CMD 0x05
- #define XNV_WREN_CMD 0x06
- #define XNV_WRPG_CMD 0x0A
- #define XNV_READ_CMD 0x0B
- #define XNV_STAT_WIP 0x01
- /*********************************************************************
- * @fn xnvSPIWrite
- *
- * @brief SPI write sequence for code size savings.
- *
- * @param ch - The byte to write to the SPI.
- *
- * @return None.
- *********************************************************************/
- static void xnvSPIWrite(uint8 ch);
- static void xnvSPIWrite(uint8 ch)
- {
- XNV_SPI_TX(ch);
- XNV_SPI_WAIT_RXRDY();
- }
- /*********************************************************************
- * @fn HalOADAvail
- *
- * @brief Determine the space available for downloading an image.
- *
- * @param None.
- *
- * @return Number of bytes available for storing an OAD image.
- *********************************************************************/
- uint32 HalOADAvail(void)
- {
- return HAL_OAD_DL_MAX - HAL_OAD_DL_OSET;
- }
- /*********************************************************************
- * @fn HalSPIRead
- *
- * @brief Read from the external NV storage via SPI.
- *
- * @param addr - Offset into the external NV.
- * @param pBuf - Pointer to the buffer in which to copy the bytes read from external NV.
- * @param len - Number of bytes to read from external NV.
- *
- * @return None.
- *********************************************************************/
- static void HalSPIRead(uint32 addr, uint8 *pBuf, uint16 len)
- {
- #if !HAL_OAD_BOOT_CODE
- uint8 shdw = P1DIR;
- halIntState_t his;
- HAL_ENTER_CRITICAL_SECTION(his);
- P1DIR |= BV(3);
- #endif
- XNV_SPI_BEGIN();
- do {
- xnvSPIWrite(XNV_STAT_CMD);
- } while (XNV_SPI_RX() & XNV_STAT_WIP);
- XNV_SPI_END();
- asm("NOP"); asm("NOP");
- XNV_SPI_BEGIN();
- xnvSPIWrite(XNV_READ_CMD);
- xnvSPIWrite(addr >> 16);
- xnvSPIWrite(addr >> 8);
- xnvSPIWrite(addr);
- xnvSPIWrite(0);
- while (len--)
- {
- xnvSPIWrite(0);
- *pBuf++ = XNV_SPI_RX();
- }
- XNV_SPI_END();
- #if !HAL_OAD_BOOT_CODE
- P1DIR = shdw;
- HAL_EXIT_CRITICAL_SECTION(his);
- #endif
- }
- /*********************************************************************
- * @fn HalSPIWrite
- *
- * @brief Write to the external NV storage via SPI.
- *
- * @param addr - Offset into the external NV.
- * @param pBuf - Pointer to the buffer in from which to write bytes to external NV.
- * @param len - Number of bytes to write to external NV.
- *
- * @return None.
- *********************************************************************/
- static void HalSPIWrite(uint32 addr, uint8 *pBuf, uint16 len)
- {
- uint8 cnt;
- #if !HAL_OAD_BOOT_CODE
- uint8 shdw = P1DIR;
- halIntState_t his;
- HAL_ENTER_CRITICAL_SECTION(his);
- P1DIR |= BV(3);
- #endif
- while (len)
- {
- XNV_SPI_BEGIN();
- do {
- xnvSPIWrite(XNV_STAT_CMD);
- } while (XNV_SPI_RX() & XNV_STAT_WIP);
- XNV_SPI_END();
- asm("NOP"); asm("NOP");
- XNV_SPI_BEGIN();
- xnvSPIWrite(XNV_WREN_CMD);
- XNV_SPI_END();
- asm("NOP"); asm("NOP");
- XNV_SPI_BEGIN();
- xnvSPIWrite(XNV_WRPG_CMD);
- xnvSPIWrite(addr >> 16);
- xnvSPIWrite(addr >> 8);
- xnvSPIWrite(addr);
- // Can only write within any one page boundary, so prepare for next page write if bytes remain.
- cnt = 0 - (uint8)addr;
- if (cnt)
- {
- addr += cnt;
- }
- else
- {
- addr += 256;
- }
- do
- {
- xnvSPIWrite(*pBuf++);
- cnt--;
- len--;
- } while (len && cnt);
- XNV_SPI_END();
- }
- #if !HAL_OAD_BOOT_CODE
- P1DIR = shdw;
- HAL_EXIT_CRITICAL_SECTION(his);
- #endif
- }
- #else
- #error Invalid Xtra-NV for OAD.
- #endif
- /**************************************************************************************************
- */
|