找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1854|回复: 0
打印 上一主题 下一主题
收起左侧

cc2530协议栈单播_串口 源码

[复制链接]
跳转到指定楼层
楼主
协议栈单播_串口


单片机源程序如下:
  1. /**************************************************************************************************
  2.   Filename:       OSAL_Nv.c
  3.   Revised:        $Date: 2008-08-06 17:17:11 -0700 (Wed, 06 Aug 2008) $
  4.   Revision:       $Revision: 17715 $

  5.   Description:    This module contains the OSAL non-volatile memory functions.


  6.   Copyright 2006-2009 Texas Instruments Incorporated. All rights reserved.

  7.   IMPORTANT: Your use of this Software is limited to those specific rights
  8.   granted under the terms of a software license agreement between the user
  9.   who downloaded the software, his/her employer (which must be your employer)
  10.   and Texas Instruments Incorporated (the "License").  You may not use this
  11.   Software unless you agree to abide by the terms of the License. The License
  12.   limits your use, and you acknowledge, that the Software may not be modified,
  13.   copied or distributed unless embedded on a Texas Instruments microcontroller
  14.   or used solely and exclusively in conjunction with a Texas Instruments radio
  15.   frequency transceiver, which is integrated into your product.  Other than for
  16.   the foregoing purpose, you may not use, reproduce, copy, prepare derivative
  17.   works of, modify, distribute, perform, display or sell this Software and/or
  18.   its documentation for any purpose.

  19.   YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE
  20.   PROVIDED 揂S IS?WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,
  21.   INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE,
  22.   NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL
  23.   TEXAS INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT,
  24.   NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER
  25.   LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
  26.   INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE
  27.   OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT
  28.   OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
  29.   (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.

  30.   Should you have any questions regarding your right to use this Software,
  31.   contact Texas Instruments Incorporated at www.TI.com.
  32. **************************************************************************************************/

  33. /**************************************************************************************************
  34.   Notes:
  35.     - A trick buried deep in initPage() requires that the MSB of the NV Item Id is to
  36.       be reserved for use by this module.
  37. **************************************************************************************************/

  38. /*********************************************************************
  39. * INCLUDES
  40. */

  41. #include "hal_adc.h"
  42. #include "hal_flash.h"
  43. #include "hal_types.h"
  44. #include "ZComdef.h"
  45. #include "OSAL_Nv.h"

  46. /*********************************************************************
  47. * CONSTANTS
  48. */

  49. #define OSAL_NV_PAGE_SIZE       HAL_FLASH_PAGE_SIZE
  50. #define OSAL_NV_PAGES_USED      HAL_NV_PAGE_CNT
  51. #define OSAL_NV_PAGE_BEG        HAL_NV_PAGE_BEG
  52. #define OSAL_NV_PAGE_END       (OSAL_NV_PAGE_BEG + OSAL_NV_PAGES_USED - 1)

  53. #define OSAL_NV_ACTIVE          0x00
  54. #define OSAL_NV_ERASED          0xFF
  55. #define OSAL_NV_ERASED_ID       0xFFFF
  56. #define OSAL_NV_ZEROED_ID       0x0000
  57. // Reserve MSB of Id to signal a search for the "old" source copy (new write interrupted/failed.)
  58. #define OSAL_NV_SOURCE_ID       0x8000

  59. #define OSAL_NV_PAGE_FREE       HAL_FLASH_PAGE_SIZE

  60. // In case pages 0-1 are ever used, define a null page value.
  61. #define OSAL_NV_PAGE_NULL       0

  62. // In case item Id 0 is ever used, define a null item value.
  63. #define OSAL_NV_ITEM_NULL       0

  64. #define OSAL_NV_WORD_SIZE       HAL_FLASH_WORD_SIZE

  65. #define OSAL_NV_PAGE_HDR_OFFSET 0

  66. /*********************************************************************
  67. * MACROS
  68. */

  69. #define  OSAL_NV_CHECK_BUS_VOLTAGE  (HalAdcCheckVdd( HAL_ADC_VDD_LIMIT_4 ))

  70. #define OSAL_NV_DATA_SIZE( LEN )  \
  71.    ((((LEN) + OSAL_NV_WORD_SIZE - 1) / OSAL_NV_WORD_SIZE) * OSAL_NV_WORD_SIZE)

  72. #define OSAL_NV_ITEM_SIZE( LEN )  \
  73.   (((((LEN) + OSAL_NV_WORD_SIZE - 1) / OSAL_NV_WORD_SIZE) * OSAL_NV_WORD_SIZE) + OSAL_NV_HDR_SIZE)

  74. /*********************************************************************
  75. * TYPEDEFS
  76. */

  77. typedef struct
  78. {
  79.   uint16 id;
  80.   uint16 len;   // Enforce Flash-WORD size on len.
  81.   uint16 chk;   // Byte-wise checksum of the 'len' data bytes of the item.
  82.   uint16 stat;  // Item status.
  83. } osalNvHdr_t;
  84. // Struct member offsets.
  85. #define OSAL_NV_HDR_ID    0
  86. #define OSAL_NV_HDR_LEN   2
  87. #define OSAL_NV_HDR_CHK   4
  88. #define OSAL_NV_HDR_STAT  6

  89. #define OSAL_NV_HDR_ITEM  2  // Length of any item of a header struct.
  90. #define OSAL_NV_HDR_SIZE  8
  91. #define OSAL_NV_HDR_HALF (OSAL_NV_HDR_SIZE / 2)

  92. typedef struct
  93. {
  94.   uint16 active;
  95.   uint16 inUse;
  96.   uint16 xfer;
  97.   uint16 spare;
  98. } osalNvPgHdr_t;
  99. // Struct member offsets.
  100. #define OSAL_NV_PG_ACTIVE 0
  101. #define OSAL_NV_PG_INUSE  2
  102. #define OSAL_NV_PG_XFER   4
  103. #define OSAL_NV_PG_SPARE  6

  104. #define OSAL_NV_PAGE_HDR_SIZE  8
  105. #define OSAL_NV_PAGE_HDR_HALF (OSAL_NV_PAGE_HDR_SIZE / 2)

  106. typedef enum
  107. {
  108.   eNvXfer,
  109.   eNvZero
  110. } eNvHdrEnum;

  111. typedef enum
  112. {
  113.   ePgActive,
  114.   ePgInUse,
  115.   ePgXfer,
  116.   ePgSpare
  117. } ePgHdrEnum;

  118. /*********************************************************************
  119. * EXTERNAL FUNCTIONS
  120. */

  121. extern bool HalAdcCheckVdd(uint8 limit);

  122. /*********************************************************************
  123. * GLOBAL VARIABLES
  124. */

  125. #ifndef OAD_KEEP_NV_PAGES
  126. // When NV pages are to remain intact during OAD download,
  127. // the image itself should not include NV pages.
  128. #pragma location="ZIGNV_ADDRESS_SPACE"
  129. __no_init uint8 _nvBuf[OSAL_NV_PAGES_USED * OSAL_NV_PAGE_SIZE];
  130. #pragma required=_nvBuf
  131. #pragma location="IEEE_ADDRESS_SPACE"
  132. __no_init uint8 _nvIEEE[Z_EXTADDR_LEN];
  133. #pragma required=_nvIEEE
  134. #endif // OAD_KEEP_NV_PAGES

  135. /*********************************************************************
  136. * LOCAL VARIABLES
  137. */

  138. // Offset into the page of the first available erased space.
  139. static uint16 pgOff[OSAL_NV_PAGES_USED];

  140. // Count of the bytes lost for the zeroed-out items.
  141. static uint16 pgLost[OSAL_NV_PAGES_USED];

  142. static uint8 pgRes;  // Page reserved for item compacting transfer.

  143. // Saving ~100 code bytes to move a uint8* parameter/return value from findItem() to a global.
  144. static uint8 findPg;

  145. /* Immediately before the voltage critical operations of a page erase or
  146. * a word write, check bus voltage. If less than min, set global flag & abort.
  147. * Since this is to be done at the lowest level, many void functions would have to be changed to
  148. * return a value and code added to check that value before proceeding, resulting in a very
  149. * expensive code size hit for implementing this properly. Therefore, use this global as follows:
  150. * at the start of osal_nv_item_init/osal_nv_write, set to FALSE, and at the end, before returning,
  151. * check the value. Thus, the global is an accumulator of any error that occurred in any of the
  152. * attempts to modify Flash with a low bus voltage during the complicated sequence of events that
  153. * may occur on any item init or write. This is much more expedient and code saving than adding
  154. * return values and checking return values to early out. No matter which method is used, an NV
  155. * data record may end up mangled due to the low VCC conditions. The strategy is that the headers
  156. * and checksums will detect and allow recovery from such a condition.
  157. *
  158. * One unfortunate side-effect of using the global fail flag vice adding and checking return
  159. * values, is that when setting an item Id to zero has failed due to the low VCC check,
  160. * the page lost-bytes counter is still updated. Having an artificially high lost-byte
  161. * count makes it look like there are more bytes to recover from compacting a page than there may
  162. * actually be. The easy work-around implemented is it to invoke initNV() from osal_nv_item_init or
  163. * osal_nv_write anytime that the failF gets set - this will re-walk all of the pages and set the
  164. * page offset count and page lost bytes count to their actual values.
  165. */
  166. static uint8 failF;

  167. /*********************************************************************
  168. * LOCAL FUNCTIONS
  169. */

  170. static uint8  initNV( void );

  171. static void   setPageUse( uint8 pg, uint8 inUse );
  172. static uint16 initPage( uint8 pg, uint16 id, uint8 findDups );
  173. static void   erasePage( uint8 pg );
  174. static void   compactPage( uint8 pg );

  175. static uint16 findItem( uint16 id );
  176. static uint8  initItem( uint8 flag, uint16 id, uint16 len, void *buf );
  177. static void   setItem( uint8 pg, uint16 offset, eNvHdrEnum stat );

  178. static uint16 calcChkB( uint16 len, uint8 *buf );
  179. static uint16 calcChkF( byte pg, uint16 offset, uint16 len );

  180. static void   writeWord( uint8 pg, uint16 offset, uint8 *buf );
  181. static void   writeWordH( uint8 pg, uint16 offset, uint8 *buf );
  182. static void   writeWordM( uint8 pg, uint16 offset, uint8 *buf, uint16 cnt );
  183. static void   writeBuf( uint8 pg, uint16 offset, uint16 len, uint8 *buf );
  184. static void   xferBuf( uint8 srcPg, uint16 srcOff, uint8 dstPg, uint16 dstOff, uint16 len );

  185. static uint8  writeItem( uint8 pg, uint16 id, uint16 len, void *buf, uint8 flag );

  186. /*********************************************************************
  187. * @fn      initNV
  188. *
  189. * @brief   Initialize the NV flash pages.
  190. *
  191. * @param   none
  192. *
  193. * @return  TRUE
  194. */
  195. static uint8 initNV( void )
  196. {
  197.   osalNvPgHdr_t pgHdr;
  198.   uint8 oldPg = OSAL_NV_PAGE_NULL;
  199.   uint8 newPg = OSAL_NV_PAGE_NULL;
  200.   uint8 findDups = FALSE;
  201.   uint8 pg;

  202.   pgRes = OSAL_NV_PAGE_NULL;

  203.   for ( pg = OSAL_NV_PAGE_BEG; pg <= OSAL_NV_PAGE_END; pg++ )
  204.   {
  205.     HalFlashRead(pg, OSAL_NV_PAGE_HDR_OFFSET, (uint8 *)(&pgHdr), OSAL_NV_HDR_SIZE);

  206.     if ( pgHdr.active == OSAL_NV_ERASED_ID )
  207.     {
  208.       if ( pgRes == OSAL_NV_PAGE_NULL )
  209.       {
  210.         pgRes = pg;
  211.       }
  212.       else
  213.       {
  214.         setPageUse( pg, TRUE );
  215.       }
  216.     }
  217.     else  // Page is active.
  218.     {
  219.       // If the page is not yet in use, it is the tgt of items from an xfer.
  220.       if ( pgHdr.inUse == OSAL_NV_ERASED_ID )
  221.       {
  222.         newPg = pg;
  223.       }
  224.       // An Xfer from this page was in progress.
  225.       else if ( pgHdr.xfer != OSAL_NV_ERASED_ID )
  226.       {
  227.         oldPg = pg;
  228.       }
  229.     }

  230.     // Calculate page offset and lost bytes - any "old" item triggers an N^2 re-scan from start.
  231.     if ( initPage( pg, OSAL_NV_ITEM_NULL, findDups ) != OSAL_NV_ITEM_NULL )
  232.     {
  233.       findDups = TRUE;
  234.       pg = OSAL_NV_PAGE_BEG-1;
  235.       continue;
  236.     }
  237.   }  // for ( pg = OSAL_NV_PAGE_BEG; pg <= OSAL_NV_PAGE_END; pg++ )

  238.   /* First the old page is erased, and then the new page is put into use.
  239.    * So if a transfer was in progress, the new page will always not yet be
  240.    * marked as in use, since that is the last step to ending a transfer.
  241.    */
  242.   if ( newPg != OSAL_NV_PAGE_NULL )
  243.   {
  244.     /* If there is already a fallow page reserved, keep it and put the newPg in use.
  245.      * An unfinished compaction will finish to the new reserve page and the old page
  246.      * will be erased and reserved.
  247.      */
  248.     if ( pgRes != OSAL_NV_PAGE_NULL )
  249.     {
  250.       setPageUse( newPg, TRUE );
  251.     }
  252.     else if ( oldPg != OSAL_NV_PAGE_NULL )
  253.     {
  254.       pgRes = newPg;
  255.     }

  256.     /* If a page compaction was interrupted and the page being compacted is not
  257.      * yet erased, then there may be items remaining to xfer before erasing.
  258.      */
  259.     if ( oldPg != OSAL_NV_PAGE_NULL )
  260.     {
  261.       compactPage( oldPg );
  262.     }
  263.   }

  264.   /* If no page met the criteria to be the reserve page:
  265.    *  - A compactPage() failed or board reset before doing so.
  266.    *  - Perhaps the user changed which Flash pages are dedicated to NV and downloaded the code
  267.    *    without erasing Flash?
  268.    */
  269.   if ( pgRes == OSAL_NV_PAGE_NULL )
  270.   {
  271.     for ( pg = OSAL_NV_PAGE_BEG; pg <= OSAL_NV_PAGE_END; pg++ )
  272.     {
  273.       erasePage( pg );
  274.     }
  275.     initNV();
  276.   }

  277.   return TRUE;
  278. }

  279. /*********************************************************************
  280. * @fn      setPageUse
  281. *
  282. * @brief   Set page header active/inUse state according to 'inUse'.
  283. *
  284. * @param   pg - Valid NV page to verify and init.
  285. * @param   inUse - Boolean TRUE if inUse, FALSE if only active.
  286. *
  287. * @return  none
  288. */
  289. static void setPageUse( uint8 pg, uint8 inUse )
  290. {
  291.   osalNvPgHdr_t pgHdr;

  292.   pgHdr.active = OSAL_NV_ZEROED_ID;

  293.   if ( inUse )
  294.   {
  295.     pgHdr.inUse = OSAL_NV_ZEROED_ID;
  296.   }
  297.   else
  298.   {
  299.     pgHdr.inUse = OSAL_NV_ERASED_ID;
  300.   }

  301.   writeWord( pg, OSAL_NV_PAGE_HDR_OFFSET, (uint8*)(&pgHdr) );
  302. }

  303. /*********************************************************************
  304. * @fn      initPage
  305. *
  306. * @brief   Walk the page items; calculate checksums, lost bytes & page offset.
  307. *
  308. * @param   pg - Valid NV page to verify and init.
  309. * @param   id - Valid NV item Id to use function as a "findItem".
  310. *               If set to NULL then just perform the page initialization.
  311. *
  312. * @return  If 'id' is non-NULL and good checksums are found, return the offset
  313. *          of the data corresponding to item Id; else OSAL_NV_ITEM_NULL.
  314. */
  315. static uint16 initPage( uint8 pg, uint16 id, uint8 findDups )
  316. {
  317.   uint16 offset = OSAL_NV_PAGE_HDR_SIZE;
  318.   uint16 sz, lost = 0;
  319.   osalNvHdr_t hdr;

  320.   do
  321.   {
  322.     HalFlashRead(pg, offset, (uint8 *)(&hdr), OSAL_NV_HDR_SIZE);

  323.     if ( hdr.id == OSAL_NV_ERASED_ID )
  324.     {
  325.       break;
  326.     }
  327.     offset += OSAL_NV_HDR_SIZE;
  328.     sz = OSAL_NV_DATA_SIZE( hdr.len );

  329.     // A bad 'len' write has blown away the rest of the page.
  330.     if ( (offset + sz) > OSAL_NV_PAGE_FREE )
  331.     {
  332.       lost += (OSAL_NV_PAGE_FREE - offset + OSAL_NV_HDR_SIZE);
  333.       offset = OSAL_NV_PAGE_FREE;
  334.       break;
  335.     }

  336.     if ( hdr.id != OSAL_NV_ZEROED_ID )
  337.     {
  338.       /* This trick allows function to do double duty for findItem() without
  339.        * compromising its essential functionality at powerup initialization.
  340.        */
  341.       if ( id != OSAL_NV_ITEM_NULL )
  342.       {
  343.         /* This trick allows asking to find the old/transferred item in case
  344.          * of a successful new item write that gets interrupted before the
  345.          * old item can be zeroed out.
  346.          */
  347.         if ( (id & 0x7fff) == hdr.id )
  348.         {
  349.           if ( (((id & OSAL_NV_SOURCE_ID) == 0) && (hdr.stat == OSAL_NV_ERASED_ID)) ||
  350.                (((id & OSAL_NV_SOURCE_ID) != 0) && (hdr.stat != OSAL_NV_ERASED_ID)) )
  351.           {
  352.             return offset;
  353.           }
  354.         }
  355.       }
  356.       // When invoked from the osal_nv_init(), verify checksums and find & zero any duplicates.
  357.       else
  358.       {
  359.         if ( hdr.chk == calcChkF( pg, offset, hdr.len ) )
  360.         {
  361.           if ( findDups )
  362.           {
  363.             if ( hdr.stat == OSAL_NV_ERASED_ID )
  364.             {
  365.               /* The trick of setting the MSB of the item Id causes the logic
  366.                * immediately above to return a valid page only if the header 'stat'
  367.                * indicates that it was the older item being transferred.
  368.                */
  369.               uint16 off = findItem( (hdr.id | OSAL_NV_SOURCE_ID) );

  370.               if ( off != OSAL_NV_ITEM_NULL )
  371.               {
  372.                 setItem( findPg, off, eNvZero );  // Mark old duplicate as invalid.
  373.               }
  374.             }
  375.           }
  376.           // Any "old" item immediately exits and triggers the N^2 exhaustive initialization.
  377.           else if ( hdr.stat != OSAL_NV_ERASED_ID )
  378.           {
  379.             return OSAL_NV_ERASED_ID;
  380.           }
  381.         }
  382.         else
  383.         {
  384.           setItem( pg, offset, eNvZero );  // Mark bad checksum as invalid.
  385.           lost += (OSAL_NV_HDR_SIZE + sz);
  386.         }
  387.       }
  388.     }
  389.     else
  390.     {
  391.       lost += (OSAL_NV_HDR_SIZE + sz);
  392.     }
  393.     offset += sz;

  394.   } while ( TRUE );

  395.   pgOff[pg - OSAL_NV_PAGE_BEG] = offset;
  396.   pgLost[pg - OSAL_NV_PAGE_BEG] = lost;

  397.   return OSAL_NV_ITEM_NULL;
  398. }

  399. /*********************************************************************
  400. * @fn      erasePage
  401. *
  402. * @brief   Erases a page in Flash.
  403. *
  404. * @param   pg - Valid NV page to erase.
  405. *
  406. * @return  none
  407. */
  408. static void erasePage( uint8 pg )
  409. {
  410.   if ( !OSAL_NV_CHECK_BUS_VOLTAGE )
  411.   {
  412.     failF = TRUE;
  413.     return;
  414.   }

  415.   HalFlashErase(pg);

  416.   pgOff[pg - OSAL_NV_PAGE_BEG] = OSAL_NV_PAGE_HDR_SIZE;
  417.   pgLost[pg - OSAL_NV_PAGE_BEG] = 0;
  418. }

  419. /*********************************************************************
  420. * @fn      compactPage
  421. *
  422. * @brief   Compacts the page specified.
  423. *
  424. * @param   srcPg - Valid NV page to erase.
  425. *
  426. * @return  none
  427. */
  428. static void compactPage( uint8 srcPg )
  429. {
  430.   uint16 dstOff = pgOff[pgRes-OSAL_NV_PAGE_BEG];
  431.   uint16 srcOff = OSAL_NV_ZEROED_ID;
  432.   osalNvHdr_t hdr;

  433.   // Mark page as being in process of compaction.
  434.   writeWordH( srcPg, OSAL_NV_PG_XFER, (uint8*)(&srcOff) );

  435.   srcOff = OSAL_NV_PAGE_HDR_SIZE;

  436.   do
  437.   {
  438.     uint16 sz;
  439.     HalFlashRead(srcPg, srcOff, (uint8 *)(&hdr), OSAL_NV_HDR_SIZE);

  440.     if ( hdr.id == OSAL_NV_ERASED_ID )
  441.     {
  442.       break;
  443.     }

  444.     srcOff += OSAL_NV_HDR_SIZE;

  445.     if ( (srcOff + hdr.len) > OSAL_NV_PAGE_FREE )
  446.     {
  447.       break;
  448.     }

  449.     sz = OSAL_NV_DATA_SIZE( hdr.len );

  450.     if ( hdr.id != OSAL_NV_ZEROED_ID )
  451.     {
  452.       if ( hdr.chk == calcChkF( srcPg, srcOff, hdr.len ) )
  453.       {
  454.         setItem( srcPg, srcOff, eNvXfer );
  455.         writeBuf( pgRes, dstOff, OSAL_NV_HDR_SIZE, (byte *)(&hdr) );
  456.         dstOff += OSAL_NV_HDR_SIZE;
  457.         xferBuf( srcPg, srcOff, pgRes, dstOff, sz );
  458.         dstOff += sz;
  459.       }

  460.       setItem( srcPg, srcOff, eNvZero );  // Mark old location as invalid.
  461.     }

  462.     srcOff += sz;

  463.   } while ( TRUE );

  464.   pgOff[pgRes-OSAL_NV_PAGE_BEG] = dstOff;

  465.   /* In order to recover from a page compaction that is interrupted,
  466.    * the logic in osal_nv_init() depends upon the following order:
  467.    * 1. Compacted page is erased.
  468.    * 2. State of the target of compaction is changed ePgActive to ePgInUse.
  469.    */
  470.   erasePage( srcPg );

  471.   // Mark the reserve page as being in use.
  472.   setPageUse( pgRes, TRUE );

  473.   // Set the reserve page to be the newly erased page.
  474.   pgRes = srcPg;
  475. }

  476. /*********************************************************************
  477. * @fn      findItem
  478. *
  479. * @brief   Find an item Id in NV and return the page and offset to its data.
  480. *
  481. * @param   id - Valid NV item Id.
  482. *
  483. * @return  Offset of data corresponding to item Id, if found;
  484. *          otherwise OSAL_NV_ITEM_NULL.
  485. *
  486. *          The page containing the item, if found;
  487. *          otherwise no valid assignment made - left equal to item Id.
  488. *
  489. */
  490. static uint16 findItem( uint16 id )
  491. {
  492.   uint16 off;
  493.   uint8 pg;

  494.   for ( pg = OSAL_NV_PAGE_BEG; pg <= OSAL_NV_PAGE_END; pg++ )
  495.   {
  496.     if ( (off = initPage( pg, id, FALSE )) != OSAL_NV_ITEM_NULL )
  497.     {
  498.       findPg = pg;
  499.       return off;
  500.     }
  501.   }

  502.   // Now attempt to find the item as the "old" item of a failed/interrupted NV write.
  503.   if ( (id & OSAL_NV_SOURCE_ID) == 0 )
  504.   {
  505.     return findItem( id | OSAL_NV_SOURCE_ID );
  506.   }
  507.   else
  508.   {
  509.     findPg = OSAL_NV_PAGE_NULL;
  510.     return OSAL_NV_ITEM_NULL;
  511.   }
  512. }

  513. /*********************************************************************
  514. * @fn      initItem
  515. *
  516. * @brief   An NV item is created and initialized with the data passed to the function, if any.
  517. *
  518. * @param   id  - Valid NV item Id.
  519. * @param   len - Item data length.
  520. * @param  *buf - Pointer to item initalization data. Set to NULL if none.
  521. *
  522. * @return  TRUE if item write and read back checksums ok; FALSE otherwise.
  523. */
  524. static uint8 initItem( uint8 flag, uint16 id, uint16 len, void *buf )
  525. {
  526.   uint16 sz = OSAL_NV_ITEM_SIZE( len );
  527.   uint8 rtrn = FALSE;
  528.   uint8 cnt = OSAL_NV_PAGES_USED;
  529.   uint8 pg = pgRes+1;  // Set to 1 after the reserve page to even wear across all available pages.
  530.   uint8 idx = 0;

  531.   do {
  532.     if (pg >= OSAL_NV_PAGE_BEG+OSAL_NV_PAGES_USED)
  533.     {
  534.       pg = OSAL_NV_PAGE_BEG;
  535.     }
  536.     if ( pg != pgRes )
  537.     {
  538.       idx = pg - OSAL_NV_PAGE_BEG;
  539.       if ( (pgOff[idx] - pgLost[idx] + sz) <= OSAL_NV_PAGE_FREE )
  540.       {
  541.         break;
  542.       }
  543.     }
  544.     pg++;
  545.   } while (--cnt);

  546.   if (cnt)
  547.   {
  548.     // Item fits if an old page is compacted.
  549.     if ( (pgOff[idx] + sz) > OSAL_NV_PAGE_FREE )
  550.     {
  551.       pg = pgRes;
  552.     }

  553.     // New item is the first one written to the reserved page, then the old page is compacted.
  554.     rtrn = writeItem( pg, id, len, buf, flag );

  555.     if ( pg == pgRes )
  556.     {
  557.       if ( flag )
  558.       {
  559.         compactPage( OSAL_NV_PAGE_BEG+idx );
  560.       }
  561.       else
  562.       {
  563.         *(uint8 *)buf = OSAL_NV_PAGE_BEG+idx;
  564.       }
  565.     }
  566.   }

  567.   return rtrn;
  568. }

  569. /*********************************************************************
  570. * @fn      setItem
  571. *
  572. * @brief   Set an item Id or status to mark its state.
  573. *
  574. * @param   pg - Valid NV page.
  575. * @param   offset - Valid offset into the page of the item data - the header
  576. *                   offset is calculated from this.
  577. * @param   stat - Valid enum value for the item status.
  578. *
  579. * @return  none
  580. */
  581. static void setItem( uint8 pg, uint16 offset, eNvHdrEnum stat )
  582. {
  583.   osalNvHdr_t hdr;

  584.   offset -= OSAL_NV_HDR_SIZE;
  585.   HalFlashRead(pg, offset, (uint8 *)(&hdr), OSAL_NV_HDR_SIZE);

  586.   if ( stat == eNvXfer )
  587.   {
  588.     hdr.stat = OSAL_NV_ACTIVE;
  589.     writeWord( pg, offset+OSAL_NV_HDR_CHK, (uint8*)(&(hdr.chk)) );
  590. }
  591.   else // if ( stat == eNvZero )
  592.   {
  593.     uint16 sz = ((hdr.len + (OSAL_NV_WORD_SIZE-1)) / OSAL_NV_WORD_SIZE) * OSAL_NV_WORD_SIZE +
  594.                                                                           OSAL_NV_HDR_SIZE;
  595.     hdr.id = 0;
  596.     writeWord( pg, offset, (uint8 *)(&hdr) );
  597.     pgLost[pg-OSAL_NV_PAGE_BEG] += sz;
  598.   }
  599. }

  600. /*********************************************************************
  601. * @fn      calcChkB
  602. *
  603. * @brief   Calculates the data checksum over the 'buf' parameter.
  604. *
  605. * @param   pg - A valid NV Flash page.
  606. * @param   offset - A valid offset into the page.
  607. * @param   len - Byte count of the data to be checksummed.
  608. *
  609. * @return  Calculated checksum of the data bytes.
  610. */
  611. static uint16 calcChkB( uint16 len, uint8 *buf )
  612. {
  613.   uint8 fill = len % OSAL_NV_WORD_SIZE;
  614.   uint16 chk;

  615.   if ( !buf )
  616.   {
  617.     chk = len * OSAL_NV_ERASED;
  618.   }
  619.   else
  620.   {
  621.     chk = 0;
  622.     while ( len-- )
  623.     {
  624.       chk += *buf++;
  625.     }
  626.   }

  627.   // calcChkF() will calculate over OSAL_NV_WORD_SIZE alignment.
  628.   if ( fill )
  629.   {
  630.     chk += (OSAL_NV_WORD_SIZE - fill) * OSAL_NV_ERASED;
  631.   }

  632.   return chk;
  633. }

  634. /*********************************************************************
  635. * @fn      calcChkF
  636. *
  637. * @brief   Calculates the data checksum by reading the data bytes from NV.
  638. *
  639. * @param   pg - A valid NV Flash page.
  640. * @param   offset - A valid offset into the page.
  641. * @param   len - Byte count of the data to be checksummed.
  642. *
  643. * @return  Calculated checksum of the data bytes.
  644. */
  645. static uint16 calcChkF( byte pg, uint16 offset, uint16 len )
  646. {
  647.   uint16 chk = 0;

  648.   len = (len + (OSAL_NV_WORD_SIZE-1)) / OSAL_NV_WORD_SIZE;

  649.   while ( len-- )
  650.   {
  651.     uint8 cnt, tmp[OSAL_NV_WORD_SIZE];

  652.     HalFlashRead(pg, offset, tmp, OSAL_NV_WORD_SIZE);
  653.     offset += OSAL_NV_WORD_SIZE;

  654.     for ( cnt = 0; cnt < OSAL_NV_WORD_SIZE; cnt++ )
  655.     {
  656.       chk += tmp[cnt];
  657.     }
  658.   }

  659.   return chk;
  660. }

  661. /*********************************************************************
  662. * @fn      writeWord
  663. *
  664. * @brief   Writes a Flash-WORD to NV.
  665. *
  666. * @param   pg - A valid NV Flash page.
  667. * @param   offset - A valid offset into the page.
  668. * @param   buf - Pointer to source buffer.
  669. *
  670. * @return  none
  671. */
  672. static void writeWord( uint8 pg, uint16 offset, uint8 *buf )
  673. {
  674.   offset = (offset >> 2) + ((uint16)pg << 9);

  675.   if ( OSAL_NV_CHECK_BUS_VOLTAGE )
  676.   {
  677.     HalFlashWrite(offset, buf, 1);
  678.   }
  679.   else
  680.   {
  681.     failF = TRUE;
  682.   }
  683. }

  684. /*********************************************************************
  685. * @fn      writeWordM
  686. *
  687. * @brief   Writes multiple Flash-WORDs to NV.
  688. *
  689. * @param   pg - A valid NV Flash page.
  690. * @param   offset - A valid offset into the page.
  691. * @param   buf - Pointer to source buffer.
  692. * @param   cnt - Number of 4-byte blocks to write.
  693. *
  694. * @return  none
  695. */
  696. static void writeWordM( uint8 pg, uint16 offset, uint8 *buf, uint16 cnt )
  697. {
  698.   offset = (offset >> 2) + ((uint16)pg << 9);

  699.   if ( OSAL_NV_CHECK_BUS_VOLTAGE )
  700.   {
  701.     HalFlashWrite(offset, buf, cnt);
  702.   }
  703.   else
  704.   {
  705.     failF = TRUE;
  706.   }
  707. }

  708. /*********************************************************************
  709. * @fn      writeWordH
  710. *
  711. * @brief   Writes the 1st half of a Flash-WORD to NV (filling 2nd half with 0xffff).
  712. *
  713. * @param   pg - A valid NV Flash page.
  714. * @param   offset - A valid offset into the page.
  715. * @param   buf - Pointer to source buffer.
  716. *
  717. * @return  none
  718. */
  719. static void writeWordH( uint8 pg, uint16 offset, uint8 *buf )
  720. {
  721.   uint8 tmp[4];

  722.   tmp[0] = buf[0];
  723.   tmp[1] = buf[1];
  724.   tmp[2] = OSAL_NV_ERASED;
  725.   tmp[3] = OSAL_NV_ERASED;

  726.   writeWord( pg, offset, tmp );
  727. }

  728. /*********************************************************************
  729. * @fn      writeBuf
  730. *
  731. * @brief   Writes a data buffer to NV.
  732. *
  733. * @param   dstPg - A valid NV Flash page.
  734. * @param   offset - A valid offset into the page.
  735. * @param   len  - Byte count of the data to write.
  736. * @param   buf  - The data to write.
  737. *
  738. * @return  TRUE if data buf checksum matches read back checksum, else FALSE.
  739. */
  740. static void writeBuf( uint8 dstPg, uint16 dstOff, uint16 len, uint8 *buf )
  741. {
  742.   uint8 rem = dstOff % OSAL_NV_WORD_SIZE;
  743.   uint8 tmp[OSAL_NV_WORD_SIZE];

  744.   if ( rem )
  745.   {
  746.     dstOff = (dstOff / OSAL_NV_WORD_SIZE) * OSAL_NV_WORD_SIZE;
  747.     HalFlashRead(dstPg, dstOff, tmp, OSAL_NV_WORD_SIZE);

  748.     while ( (rem < OSAL_NV_WORD_SIZE) && len )
  749.     {
  750.       tmp[rem++] = *buf++;
  751.       len--;
  752.     }

  753.     writeWord( dstPg, dstOff, tmp );
  754.     dstOff += OSAL_NV_WORD_SIZE;
  755.   }

  756.   rem = len % OSAL_NV_WORD_SIZE;
  757.   len /= OSAL_NV_WORD_SIZE;

  758.   if ( len )
  759.   {
  760.     writeWordM( dstPg, dstOff, buf, len );
  761.     dstOff += OSAL_NV_WORD_SIZE * len;
  762.     buf += OSAL_NV_WORD_SIZE * len;
  763.   }

  764.   if ( rem )
  765.   {
  766.     uint8 idx = 0;
  767.     HalFlashRead(dstPg, dstOff, tmp, OSAL_NV_WORD_SIZE);
  768.     while ( rem-- )
  769.     {
  770.       tmp[idx++] = *buf++;
  771.     }
  772.     writeWord( dstPg, dstOff, tmp );
  773.   }
  774. }

  775. /*********************************************************************
  776. * @fn      xferBuf
  777. *
  778. * @brief   Xfers an NV buffer from one location to another, enforcing OSAL_NV_WORD_SIZE writes.
  779. *
  780. * @return  none
  781. */
  782. static void xferBuf( uint8 srcPg, uint16 srcOff, uint8 dstPg, uint16 dstOff, uint16 len )
  783. {
  784.   uint8 rem = dstOff % OSAL_NV_WORD_SIZE;
  785.   uint8 tmp[OSAL_NV_WORD_SIZE];

  786.   if ( rem )
  787.   {
  788.     dstOff -= rem;
  789.     HalFlashRead(dstPg, dstOff, tmp, OSAL_NV_WORD_SIZE);

  790.     while ( (rem < OSAL_NV_WORD_SIZE) && len )
  791.     {
  792.       HalFlashRead(srcPg, srcOff, tmp+rem, 1);
  793.       srcOff++;
  794.       rem++;
  795.       len--;
  796.     }

  797.     writeWord( dstPg, dstOff, tmp );
  798.     dstOff += OSAL_NV_WORD_SIZE;
  799.   }

  800.   rem = len % OSAL_NV_WORD_SIZE;
  801.   len /= OSAL_NV_WORD_SIZE;

  802.   while ( len-- )
  803.   {
  804.     HalFlashRead(srcPg, srcOff, tmp, OSAL_NV_WORD_SIZE);
  805.     srcOff += OSAL_NV_WORD_SIZE;
  806.     writeWord( dstPg, dstOff, tmp );
  807.     dstOff += OSAL_NV_WORD_SIZE;
  808.   }

  809.   if ( rem )
  810.   {
  811.     uint8 idx = 0;
  812.     HalFlashRead(dstPg, dstOff, tmp, OSAL_NV_WORD_SIZE);
  813.     while ( rem-- )
  814.     {
  815.       HalFlashRead(srcPg, srcOff, tmp+idx, 1);
  816.       srcOff++;
  817.       idx++;
  818.     }
  819.     writeWord( dstPg, dstOff, tmp );
  820.   }
  821. }

  822. /*********************************************************************
  823. * @fn      writeItem
  824. *
  825. * @brief   Writes an item header/data combo to the specified NV page.
  826. *
  827. * @param   pg - Valid NV Flash page.
  828. * @param   id - Valid NV item Id.
  829. * @param   len  - Byte count of the data to write.
  830. * @param   buf  - The data to write. If NULL, no data/checksum write.
  831. * @param   flag - TRUE if the checksum should be written, FALSE otherwise.
  832. *
  833. * @return  TRUE if header/data to write matches header/data read back, else FALSE.
  834. */
  835. static uint8 writeItem( uint8 pg, uint16 id, uint16 len, void *buf, uint8 flag )
  836. {
  837.   uint16 offset = pgOff[pg-OSAL_NV_PAGE_BEG];
  838.   uint8 rtrn = FALSE;
  839.   osalNvHdr_t hdr;

  840.   if ( pg == pgRes )
  841.   {
  842.     /* Mark reserve page as being active, in process of receiving items.
  843.      * Invoking function must effect a page compaction.
  844.      */
  845.     setPageUse( pg, FALSE );
  846.   }

  847.   hdr.id = id;
  848.   hdr.len = len;

  849.   writeWord( pg, offset, (uint8 *)&hdr );
  850.   HalFlashRead(pg, offset, (uint8 *)(&hdr), OSAL_NV_HDR_SIZE);

  851.   if ( (hdr.id == id) && (hdr.len == len) )
  852.   {
  853.     if ( flag )
  854.     {
  855.       uint16 chk = calcChkB( len, buf );

  856.       offset += OSAL_NV_HDR_SIZE;
  857.       if ( buf != NULL )
  858.       {
  859.         writeBuf( pg, offset, len, buf );
  860.       }

  861.       if ( chk == calcChkF( pg, offset, len ) )
  862.       {
  863.         writeWordH(pg, (offset-OSAL_NV_WORD_SIZE), (uint8 *)&chk);
  864.         HalFlashRead(pg, (offset-OSAL_NV_HDR_SIZE), (uint8 *)(&hdr), OSAL_NV_HDR_SIZE);

  865.         if ( chk == hdr.chk )
  866.         {
  867.           rtrn = pg;
  868.         }
  869.       }
  870.     }
  871.     else
  872.     {
  873.       rtrn = pg;
  874.     }
  875.   }

  876.   len = OSAL_NV_ITEM_SIZE( hdr.len );
  877.   pgOff[pg-OSAL_NV_PAGE_BEG] += len;

  878.   return rtrn;
  879. }

  880. ……………………

  881. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

所有资料51hei提供下载:
Components.rar (876.54 KB, 下载次数: 8)



分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表