mac_mcu.c 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016
  1. /**************************************************************************************************
  2. Filename: mac_mcu.c
  3. Revised: $Date: 2012-03-07 16:55:44 -0800 (Wed, 07 Mar 2012) $
  4. Revision: $Revision: 29672 $
  5. Description: Describe the purpose and contents of the file.
  6. Copyright 2006-2012 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 “AS 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. * Includes
  35. * ------------------------------------------------------------------------------------------------
  36. */
  37. /* hal */
  38. #include "hal_defs.h"
  39. #include "hal_mcu.h"
  40. /* low-level specific */
  41. #include "mac_rx.h"
  42. #include "mac_tx.h"
  43. #include "mac_backoff_timer.h"
  44. #include "mac_csp_tx.h"
  45. #include "mac_rx_onoff.h"
  46. #include "mac_low_level.h"
  47. /* target specific */
  48. #include "mac_mcu.h"
  49. #include "mac_radio_defs.h"
  50. /* debug */
  51. #include "mac_assert.h"
  52. /* ------------------------------------------------------------------------------------------------
  53. * Defines
  54. * ------------------------------------------------------------------------------------------------
  55. */
  56. /* for optimized indexing of uint32's */
  57. #if HAL_MCU_LITTLE_ENDIAN()
  58. #define UINT32_NDX0 0
  59. #define UINT32_NDX1 1
  60. #define UINT32_NDX2 2
  61. #define UINT32_NDX3 3
  62. #else
  63. #define UINT32_NDX0 3
  64. #define UINT32_NDX1 2
  65. #define UINT32_NDX2 1
  66. #define UINT32_NDX3 0
  67. #endif
  68. /* ------------------------------------------------------------------------------------------------
  69. * Local Variables
  70. * ------------------------------------------------------------------------------------------------
  71. */
  72. uint8 macChipVersion = 0;
  73. static int8 maxRssi;
  74. static uint32 prevAccumulatedOverflowCount = 0;
  75. static bool updateRolloverflag = FALSE;
  76. static uint32 prevoverflowCount = 0;
  77. /*
  78. * This number is used to calculate the precision count for OSAL timer update. In Beacon mode,
  79. * the overflow count may be initialized to zero or to a constant. The "skip" in overflow count
  80. * needs to be accounted for in this variable.
  81. */
  82. static uint32 accumulatedOverflowCount = 0;
  83. /* Function pointer for the random seed callback */
  84. static macRNGFcn_t pRandomSeedCB = NULL;
  85. /* ------------------------------------------------------------------------------------------------
  86. * Local Prototypes
  87. * ------------------------------------------------------------------------------------------------
  88. */
  89. static void mcuRecordMaxRssiIsr(void);
  90. static uint32 macMcuOverflowGetCompare(void);
  91. void MAC_SetRandomSeedCB(macRNGFcn_t pCBFcn);
  92. /**************************************************************************************************
  93. * @fn MAC_SetRandomSeedCB
  94. *
  95. * @brief Set the function pointer for the random seed callback.
  96. *
  97. * @param pCBFcn - function pointer of the random seed callback
  98. *
  99. * @return none
  100. **************************************************************************************************
  101. */
  102. void MAC_SetRandomSeedCB(macRNGFcn_t pCBFcn)
  103. {
  104. pRandomSeedCB = pCBFcn;
  105. }
  106. /**************************************************************************************************
  107. * @fn macMcuInit
  108. *
  109. * @brief Initialize the MCU.
  110. *
  111. * @param none
  112. *
  113. * @return none
  114. **************************************************************************************************
  115. */
  116. MAC_INTERNAL_API void macMcuInit(void)
  117. {
  118. halIntState_t s;
  119. /* This CORR_THR value should be changed to 0x14 before attempting RX. Testing has shown that
  120. * too many false frames are received if the reset value is used. Make it more likely to detect
  121. * sync by removing the requirement that both symbols in the SFD must have a correlation value
  122. * above the correlation threshold, and make sync word detection less likely by raising the
  123. * correlation threshold.
  124. */
  125. MDMCTRL1 = CORR_THR;
  126. #ifdef FEATURE_CC253X_LOW_POWER_RX
  127. /* Reduce RX power consumption current to 20mA at the cost of some sensitivity
  128. * Note: This feature can be applied to CC2530 and CC2533 only.
  129. */
  130. RXCTRL = 0x00;
  131. FSCTRL = 0x50;
  132. #else
  133. /* tuning adjustments for optimal radio performance; details available in datasheet */
  134. RXCTRL = 0x3F;
  135. /* Adjust current in synthesizer; details available in datasheet. */
  136. FSCTRL = 0x55;
  137. #endif /* #ifdef FEATURE_CC253X_LOW_POWER_RX */
  138. #if !(defined HAL_PA_LNA || defined HAL_PA_LNA_CC2590)
  139. /* Raises the CCA threshold from about -108 dBm to about -80 dBm input level.
  140. */
  141. CCACTRL0 = CCA_THR;
  142. #endif
  143. #ifdef CC2591_COMPRESSION_WORKAROUND
  144. /* For Coordinators/Routers with CC2591, increase preamble from 4 to 12 bytes */
  145. MDMCTRL0 = 0x95;
  146. /* For End devices without CC2591, increase preamble from 4 to 8 bytes */
  147. /* MDMCTRL0 = 0x8D; */
  148. #else
  149. /* Makes sync word detection less likely by requiring two zero symbols before the sync word.
  150. * details available in datasheet.
  151. */
  152. MDMCTRL0 = 0x85;
  153. #endif /* CC2591_COMPRESSION_WORKAROUND */
  154. if (*(uint8 *)(P_INFOPAGE+0x03) == 0x95) // Device is a CC2533
  155. {
  156. /* In case the device is a 2533, just update the IVCTRL regoster which is 2533 specific */
  157. #define IVCTRL XREG( 0x6265 )
  158. IVCTRL = 0xF;
  159. }
  160. /* Adjust current in VCO; details available in datasheet. */
  161. FSCAL1 = 0x00;
  162. /* Adjust target value for AGC control loop; details available in datasheet. */
  163. AGCCTRL1 = 0x15;
  164. /* Disable source address matching an autopend for now */
  165. SRCMATCH = 0;
  166. /* Tune ADC performance, details available in datasheet. */
  167. ADCTEST0 = 0x10;
  168. ADCTEST1 = 0x0E;
  169. ADCTEST2 = 0x03;
  170. /* Sets TX anti-aliasing filter to appropriate bandwidth.
  171. * Reduces spurious emissions close to signal.
  172. */
  173. TXFILTCFG = TXFILTCFG_RESET_VALUE;
  174. /* disable the CSPT register compare function */
  175. CSPT = 0xFF;
  176. /* enable general RF interrupts */
  177. IEN2 |= RFIE;
  178. /* enable general REERR interrupts */
  179. IEN0 |= RFERRIE;
  180. /* set RF interrupts one notch above lowest priority (four levels available) */
  181. IP0 |= IP_RFERR_RF_DMA_BV;
  182. IP1 &= ~IP_RFERR_RF_DMA_BV;
  183. /* set T2 interrupts one notch above lowest priority (four levels available)
  184. * This effectively turned off nested interrupt between T2 and RF.
  185. */
  186. IP0 |= IP_RXTX0_T2_BV;
  187. IP1 &= ~IP_RXTX0_T2_BV;
  188. /* read chip version */
  189. macChipVersion = CHVER;
  190. /*-------------------------------------------------------------------------------
  191. * Initialize MAC timer.
  192. */
  193. /* set timer rollover */
  194. HAL_ENTER_CRITICAL_SECTION(s);
  195. MAC_MCU_T2_ACCESS_PERIOD_VALUE();
  196. T2M0 = MAC_RADIO_TIMER_TICKS_PER_BACKOFF() & 0xFF;
  197. T2M1 = MAC_RADIO_TIMER_TICKS_PER_BACKOFF() >> 8;
  198. HAL_EXIT_CRITICAL_SECTION(s);
  199. /* start timer */
  200. MAC_RADIO_TIMER_WAKE_UP();
  201. /* Enable latch mode and T2 SYNC start. OSAL timer is based on MAC timer.
  202. * The SYNC start msut be on when POWER_SAVING is on for this design to work.
  203. */
  204. T2CTRL |= (LATCH_MODE | TIMER2_SYNC);
  205. /* enable timer interrupts */
  206. T2IE = 1;
  207. /*----------------------------------------------------------------------------------------------
  208. * Initialize random seed value.
  209. */
  210. /*
  211. * Set radio for infinite reception. Once radio reaches this state,
  212. * it will stay in receive mode regardless RF activity.
  213. */
  214. FRMCTRL0 = FRMCTRL0_RESET_VALUE | RX_MODE_INFINITE_RECEPTION;
  215. /* turn on the receiver */
  216. macRxOn();
  217. /*
  218. * Wait for radio to reach infinite reception state by checking RSSI valid flag.
  219. * Once it does, the least significant bit of ADTSTH should be pretty random.
  220. */
  221. while (!(RSSISTAT & 0x01));
  222. /* put 16 random bits into the seed value */
  223. {
  224. uint16 rndSeed;
  225. uint8 i;
  226. rndSeed = 0;
  227. for(i=0; i<16; i++)
  228. {
  229. /* use most random bit of analog to digital receive conversion to populate the random seed */
  230. rndSeed = (rndSeed << 1) | (RFRND & 0x01);
  231. }
  232. /*
  233. * The seed value must not be zero or 0x0380 (0x8003 in the polynomial). If it is, the psuedo
  234. * random sequence won’t be random. There is an extremely small chance this seed could randomly
  235. * be zero or 0x0380. The following check makes sure this does not happen.
  236. */
  237. if (rndSeed == 0x0000 || rndSeed == 0x0380)
  238. {
  239. rndSeed = 0xBABE; /* completely arbitrary "random" value */
  240. }
  241. /*
  242. * Two writes to RNDL will set the random seed. A write to RNDL copies current contents
  243. * of RNDL to RNDH before writing new the value to RNDL.
  244. */
  245. RNDL = rndSeed & 0xFF;
  246. RNDL = rndSeed >> 8;
  247. }
  248. /* Read 16*8 random bits and store them in flash for future use in random
  249. key generation for CBKE key establishment */
  250. if( pRandomSeedCB )
  251. {
  252. uint8 randomSeed[MAC_RANDOM_SEED_LEN];
  253. uint8 i,j;
  254. for(i = 0; i < 16; i++)
  255. {
  256. uint8 rndByte = 0;
  257. for(j = 0; j < 8; j++)
  258. {
  259. /* use most random bit of analog to digital receive conversion to
  260. populate the random seed */
  261. rndByte = (rndByte << 1) | (RFRND & 0x01);
  262. }
  263. randomSeed[i] = rndByte;
  264. }
  265. pRandomSeedCB( randomSeed );
  266. }
  267. /* turn off the receiver */
  268. macRxOff();
  269. /* take receiver out of infinite reception mode; set back to normal operation */
  270. FRMCTRL0 = FRMCTRL0_RESET_VALUE | RX_MODE_NORMAL_OPERATION;
  271. /* Turn on autoack */
  272. MAC_RADIO_TURN_ON_AUTO_ACK();
  273. /* Initialize SRCEXTPENDEN and SRCSHORTPENDEN to zeros */
  274. MAC_RADIO_SRC_MATCH_INIT_EXTPENDEN();
  275. MAC_RADIO_SRC_MATCH_INIT_SHORTPENDEN();
  276. }
  277. /**************************************************************************************************
  278. * @fn macMcuRandomByte
  279. *
  280. * @brief Returns a random byte using a special hardware feature that generates new
  281. * random values based on the truly random seed set earlier.
  282. *
  283. * @param none
  284. *
  285. * @return a random byte
  286. **************************************************************************************************
  287. */
  288. MAC_INTERNAL_API uint8 macMcuRandomByte(void)
  289. {
  290. /* clock the random generator to get a new random value */
  291. ADCCON1 = (ADCCON1 & ~RCTRL_BITS) | RCTRL_CLOCK_LFSR;
  292. /* return new randomized value from hardware */
  293. return(RNDH);
  294. }
  295. /**************************************************************************************************
  296. * @fn macMcuRandomWord
  297. *
  298. * @brief Returns a random word using a special hardware feature that generates new
  299. * random values based on the truly random seed set earlier.
  300. *
  301. * @param none
  302. *
  303. * @return a random word
  304. **************************************************************************************************
  305. */
  306. MAC_INTERNAL_API uint16 macMcuRandomWord(void)
  307. {
  308. uint16 random_word;
  309. /* clock the random generator to get a new random value */
  310. ADCCON1 = (ADCCON1 & ~RCTRL_BITS) | RCTRL_CLOCK_LFSR;
  311. /* read random word */
  312. random_word = (RNDH << 8);
  313. random_word += RNDL;
  314. /* return new randomized value from hardware */
  315. return(random_word);
  316. }
  317. /**************************************************************************************************
  318. * @fn macMcuTimerForceDelay
  319. *
  320. * @brief Delay the timer by the requested number of ticks.
  321. *
  322. * @param none
  323. *
  324. * @return none
  325. **************************************************************************************************
  326. */
  327. MAC_INTERNAL_API void macMcuTimerForceDelay(uint16 x)
  328. {
  329. halIntState_t s;
  330. HAL_ENTER_CRITICAL_SECTION(s);
  331. MAC_MCU_T2_ACCESS_COUNT_VALUE();
  332. T2M0 = (x) & 0xFF;
  333. T2M1 = (x) >> 8;
  334. HAL_EXIT_CRITICAL_SECTION(s);
  335. }
  336. /**************************************************************************************************
  337. * @fn macMcuTimerCapture
  338. *
  339. * @brief Returns the last timer capture. This capture should have occurred at the
  340. * receive time of the last frame (the last time SFD transitioned to active).
  341. *
  342. * @param none
  343. *
  344. * @return last capture of hardware timer (full 16-bit value)
  345. **************************************************************************************************
  346. */
  347. MAC_INTERNAL_API uint16 macMcuTimerCapture(void)
  348. {
  349. uint16 timerCapture;
  350. halIntState_t s;
  351. HAL_ENTER_CRITICAL_SECTION(s);
  352. MAC_MCU_T2_ACCESS_CAPTURE_VALUE();
  353. timerCapture = T2M1 << 8;
  354. timerCapture |= T2M0;
  355. HAL_EXIT_CRITICAL_SECTION(s);
  356. return (timerCapture);
  357. }
  358. /**************************************************************************************************
  359. * @fn macMcuOverflowCount
  360. *
  361. * @brief Returns the value of the overflow counter which is a special hardware feature.
  362. * The overflow count actually is 24 bits of information.
  363. *
  364. * @param none
  365. *
  366. * @return value of overflow counter
  367. **************************************************************************************************
  368. */
  369. MAC_INTERNAL_API uint32 macMcuOverflowCount(void)
  370. {
  371. uint32 overflowCount;
  372. halIntState_t s;
  373. /* for efficiency, the 32-bit value is encoded using endian abstracted indexing */
  374. HAL_ENTER_CRITICAL_SECTION(s);
  375. /* This T2 access macro allows accessing both T2MOVFx and T2Mx */
  376. MAC_MCU_T2_ACCESS_OVF_COUNT_VALUE();
  377. /* Latch the entire T2MOVFx first by reading T2M0. */
  378. T2M0;
  379. ((uint8 *)&overflowCount)[UINT32_NDX0] = T2MOVF0;
  380. ((uint8 *)&overflowCount)[UINT32_NDX1] = T2MOVF1;
  381. ((uint8 *)&overflowCount)[UINT32_NDX2] = T2MOVF2;
  382. ((uint8 *)&overflowCount)[UINT32_NDX3] = 0;
  383. HAL_EXIT_CRITICAL_SECTION(s);
  384. return (overflowCount);
  385. }
  386. /**************************************************************************************************
  387. * @fn macMcuOverflowCapture
  388. *
  389. * @brief Returns the last capture of the overflow counter. A special hardware feature
  390. * captures the overflow counter when the regular hardware timer is captured.
  391. *
  392. * @param none
  393. *
  394. * @return last capture of overflow count
  395. **************************************************************************************************
  396. */
  397. MAC_INTERNAL_API uint32 macMcuOverflowCapture(void)
  398. {
  399. uint32 overflowCapture;
  400. halIntState_t s;
  401. /* for efficiency, the 32-bit value is encoded using endian abstracted indexing */
  402. HAL_ENTER_CRITICAL_SECTION(s);
  403. MAC_MCU_T2_ACCESS_OVF_CAPTURE_VALUE();
  404. ((uint8 *)&overflowCapture)[UINT32_NDX0] = T2MOVF0;
  405. ((uint8 *)&overflowCapture)[UINT32_NDX1] = T2MOVF1;
  406. ((uint8 *)&overflowCapture)[UINT32_NDX2] = T2MOVF2;
  407. ((uint8 *)&overflowCapture)[UINT32_NDX3] = 0;
  408. HAL_EXIT_CRITICAL_SECTION(s);
  409. return (overflowCapture);
  410. }
  411. /**************************************************************************************************
  412. * @fn macMcuOverflowSetCount
  413. *
  414. * @brief Sets the value of the hardware overflow counter.
  415. *
  416. * @param count - new overflow count value
  417. *
  418. * @return none
  419. **************************************************************************************************
  420. */
  421. MAC_INTERNAL_API void macMcuOverflowSetCount(uint32 count)
  422. {
  423. halIntState_t s;
  424. MAC_ASSERT(! (count >> 24) ); /* illegal count value */
  425. /* save the current overflow count */
  426. accumulatedOverflowCount += macMcuOverflowCount();
  427. /* deduct the initial count */
  428. accumulatedOverflowCount -= count;
  429. HAL_ENTER_CRITICAL_SECTION(s);
  430. MAC_MCU_T2_ACCESS_OVF_COUNT_VALUE();
  431. /* for efficiency, the 32-bit value is decoded using endian abstracted indexing */
  432. /* T2OF2 must be written last */
  433. T2MOVF0 = ((uint8 *)&count)[UINT32_NDX0];
  434. T2MOVF1 = ((uint8 *)&count)[UINT32_NDX1];
  435. T2MOVF2 = ((uint8 *)&count)[UINT32_NDX2];
  436. HAL_EXIT_CRITICAL_SECTION(s);
  437. }
  438. /**************************************************************************************************
  439. * @fn macMcuOverflowSetCompare
  440. *
  441. * @brief Set overflow count compare value. An interrupt is triggered when the overflow
  442. * count equals this compare value.
  443. *
  444. * @param count - overflow count compare value
  445. *
  446. * @return none
  447. **************************************************************************************************
  448. */
  449. MAC_INTERNAL_API void macMcuOverflowSetCompare(uint32 count)
  450. {
  451. halIntState_t s;
  452. uint8 enableCompareInt = 0;
  453. MAC_ASSERT( !(count >> 24) ); /* illegal count value */
  454. HAL_ENTER_CRITICAL_SECTION(s);
  455. /* Disable overflow compare interrupts. */
  456. if (T2IRQM & TIMER2_OVF_COMPARE1M)
  457. {
  458. enableCompareInt = 1;
  459. T2IRQM &= ~TIMER2_OVF_COMPARE1M;
  460. }
  461. MAC_MCU_T2_ACCESS_OVF_CMP1_VALUE();
  462. /* for efficiency, the 32-bit value is decoded using endian abstracted indexing */
  463. T2MOVF0 = ((uint8 *)&count)[UINT32_NDX0];
  464. T2MOVF1 = ((uint8 *)&count)[UINT32_NDX1];
  465. T2MOVF2 = ((uint8 *)&count)[UINT32_NDX2];
  466. /*
  467. * Now that new compare value is stored, clear the interrupt flag. This is important just
  468. * in case a false match was generated as the multi-byte compare value was written.
  469. */
  470. T2IRQF = ~TIMER2_OVF_COMPARE1F;
  471. /* re-enable overflow compare interrupts if they were previously enabled */
  472. if (enableCompareInt)
  473. {
  474. T2IRQM |= TIMER2_OVF_COMPARE1M;
  475. }
  476. HAL_EXIT_CRITICAL_SECTION(s);
  477. }
  478. /**************************************************************************************************
  479. * @fn macMcuOverflowSetPeriod
  480. *
  481. * @brief Set overflow count period value. An interrupt is triggered when the overflow
  482. * count equals this period value.
  483. *
  484. * @param count - overflow count compare value
  485. *
  486. * @return none
  487. **************************************************************************************************
  488. */
  489. MAC_INTERNAL_API void macMcuOverflowSetPeriod(uint32 count)
  490. {
  491. halIntState_t s;
  492. uint8 enableCompareInt = 0;
  493. MAC_ASSERT( !(count >> 24) ); /* illegal count value */
  494. HAL_ENTER_CRITICAL_SECTION(s);
  495. /* Disable overflow compare interrupts. */
  496. if (T2IRQM & TIMER2_OVF_PERM)
  497. {
  498. enableCompareInt = 1;
  499. T2IRQM &= ~TIMER2_OVF_PERM;
  500. }
  501. MAC_MCU_T2_ACCESS_OVF_PERIOD_VALUE();
  502. /* for efficiency, the 32-bit value is decoded using endian abstracted indexing */
  503. T2MOVF0 = ((uint8 *)&count)[UINT32_NDX0];
  504. T2MOVF1 = ((uint8 *)&count)[UINT32_NDX1];
  505. T2MOVF2 = ((uint8 *)&count)[UINT32_NDX2];
  506. /*
  507. * Now that new compare value is stored, clear the interrupt flag. This is important just
  508. * in case a false match was generated as the multi-byte compare value was written.
  509. */
  510. T2IRQF &= ~TIMER2_OVF_PERF;
  511. /* re-enable overflow compare interrupts if they were previously enabled */
  512. if (enableCompareInt)
  513. {
  514. T2IRQM |= TIMER2_OVF_PERM;
  515. }
  516. halSetMaxSleepLoopTime(count);
  517. HAL_EXIT_CRITICAL_SECTION(s);
  518. }
  519. /**************************************************************************************************
  520. * @fn macMcuOverflowGetCompare
  521. *
  522. * @brief Get overflow count compare value.
  523. *
  524. * @param none
  525. *
  526. * @return overflow count compare value
  527. **************************************************************************************************
  528. */
  529. MAC_INTERNAL_API uint32 macMcuOverflowGetCompare(void)
  530. {
  531. halIntState_t s;
  532. uint32 compare;
  533. HAL_ENTER_CRITICAL_SECTION(s);
  534. MAC_MCU_T2_ACCESS_OVF_CMP1_VALUE();
  535. /* for efficiency, the 32-bit value is decoded using endian abstracted indexing */
  536. ((uint8 *)&compare)[UINT32_NDX0] = T2MOVF0;
  537. ((uint8 *)&compare)[UINT32_NDX1] = T2MOVF1;
  538. ((uint8 *)&compare)[UINT32_NDX2] = T2MOVF2;
  539. ((uint8 *)&compare)[UINT32_NDX3] = 0;
  540. HAL_EXIT_CRITICAL_SECTION(s);
  541. return(compare);
  542. }
  543. /**************************************************************************************************
  544. * @fn macMcuTimer2Isr
  545. *
  546. * @brief Interrupt service routine for timer2, the MAC timer.
  547. *
  548. * @param none
  549. *
  550. * @return none
  551. **************************************************************************************************
  552. */
  553. HAL_ISR_FUNCTION( macMcuTimer2Isr, T2_VECTOR )
  554. {
  555. uint8 t2irqm;
  556. uint8 t2irqf;
  557. HAL_ENTER_ISR();
  558. t2irqm = T2IRQM;
  559. t2irqf = T2IRQF;
  560. /*------------------------------------------------------------------------------------------------
  561. * Overflow compare interrupt - triggers when then overflow counter is
  562. * equal to the overflow compare register.
  563. */
  564. if ((t2irqf & TIMER2_OVF_COMPARE1F) & t2irqm)
  565. {
  566. /* call function for dealing with the timer compare interrupt */
  567. macBackoffTimerCompareIsr();
  568. /* clear overflow compare interrupt flag */
  569. T2IRQF = ~TIMER2_OVF_COMPARE1F;
  570. }
  571. /*------------------------------------------------------------------------------------------------
  572. * Overflow compare interrupt - triggers when then overflow counter is
  573. * equal to the overflow compare register.
  574. */
  575. if ((t2irqf & TIMER2_OVF_PERF) & t2irqm)
  576. {
  577. /* call function for dealing with the timer compare interrupt */
  578. macBackoffTimerPeriodIsr();
  579. /* clear overflow compare interrupt flag */
  580. T2IRQF = ~TIMER2_OVF_PERF;
  581. }
  582. /*------------------------------------------------------------------------------------------------
  583. * Overflow interrupt - triggers when the hardware timer rolls over.
  584. */
  585. else if ((t2irqf & TIMER2_PERF) & t2irqm)
  586. {
  587. /* call energy detect interrupt function, this interrupt not used for any other functionality */
  588. mcuRecordMaxRssiIsr();
  589. /* clear the interrupt flag */
  590. T2IRQF = ~TIMER2_PERF;
  591. }
  592. CLEAR_SLEEP_MODE();
  593. HAL_EXIT_ISR();
  594. }
  595. /**************************************************************************************************
  596. * @fn macMcuTimer2OverflowWorkaround
  597. *
  598. * @brief For CC2530, T2 interrupt won’t be generated when the current count is greater than
  599. * the comparator. The interrupt is only generated when the current count is equal to
  600. * the comparator. When the CC2530 is waking up from sleep, there is a small window
  601. * that the count may be grater than the comparator, therefore, missing the interrupt.
  602. * This workaround will call the T2 ISR when the current T2 count is greater than the
  603. * comparator.
  604. *
  605. * @param none
  606. *
  607. * @return none
  608. **************************************************************************************************
  609. */
  610. void macMcuTimer2OverflowWorkaround(void)
  611. {
  612. if (T2IRQM & TIMER2_OVF_COMPARE1F)
  613. {
  614. /* T2 comapre 1 interrupt is enabled but T2 compare 1 intererrupt is not generated */
  615. if (!(T2IRQF & TIMER2_OVF_COMPARE1F))
  616. {
  617. if (MAC_RADIO_BACKOFF_COUNT() > macMcuOverflowGetCompare())
  618. {
  619. /* Set the flag to trigger the timer compare interrupt */
  620. macBackoffTimerCompareIsr();
  621. T2IRQF = ~TIMER2_OVF_COMPARE1F;
  622. }
  623. }
  624. }
  625. }
  626. /**************************************************************************************************
  627. * @fn macMcuPrecisionCount
  628. *
  629. * @brief This function is used by higher layer to read a free running counter driven by
  630. * MAC timer.
  631. *
  632. * @param none
  633. *
  634. * @return overflowCount
  635. **************************************************************************************************
  636. */
  637. uint32 macMcuPrecisionCount(void)
  638. {
  639. uint32 overflowCount = 0;
  640. halIntState_t s;
  641. HAL_ENTER_CRITICAL_SECTION(s);
  642. /* This T2 access macro allows accessing both T2MOVFx and T2Mx */
  643. MAC_MCU_T2_ACCESS_OVF_COUNT_VALUE();
  644. /* Latch the entire T2MOVFx first by reading T2M0.
  645. * T2M0 is discarded.
  646. */
  647. T2M0;
  648. ((uint8 *)&overflowCount)[UINT32_NDX0] = T2MOVF0;
  649. ((uint8 *)&overflowCount)[UINT32_NDX1] = T2MOVF1;
  650. ((uint8 *)&overflowCount)[UINT32_NDX2] = T2MOVF2;
  651. /* the overflowCount needs to account for the accumulated overflow count in Beacon mode.
  652. */
  653. overflowCount += accumulatedOverflowCount;
  654. /*
  655. * Workaround to take care of the case where a rollover just occured and the call to
  656. * macBackoffTimerPeriodIsr() hasn't yet occured or if one rollover occured during
  657. * sleep then update the accumulatedoverflowCount with the rollover
  658. */
  659. if((prevoverflowCount > overflowCount) && (prevAccumulatedOverflowCount == accumulatedOverflowCount))
  660. {
  661. accumulatedOverflowCount += macGetBackOffTimerRollover();
  662. overflowCount += macGetBackOffTimerRollover();
  663. /*don't update the rollover since it has been updated already */
  664. updateRolloverflag = TRUE;
  665. }
  666. /* store the current value of overflowcount and accumulatedOverflowCount */
  667. prevoverflowCount = overflowCount;
  668. prevAccumulatedOverflowCount = accumulatedOverflowCount;
  669. HAL_EXIT_CRITICAL_SECTION(s);
  670. return(overflowCount);
  671. }
  672. /**************************************************************************************************
  673. * @fn macMcuRfIsr
  674. *
  675. * @brief Interrupt service routine that handles all RF interrupts. There are a number
  676. * of conditions "ganged" onto this one ISR so each condition must be tested for.
  677. *
  678. * @param none
  679. *
  680. * @return none
  681. **************************************************************************************************
  682. */
  683. HAL_ISR_FUNCTION( macMcuRfIsr, RF_VECTOR )
  684. {
  685. uint8 rfim;
  686. HAL_ENTER_ISR();
  687. rfim = RFIRQM1;
  688. /* The CPU level RF interrupt flag must be cleared here (before clearing RFIRQFx).
  689. * to allow the interrupts to be nested.
  690. */
  691. S1CON = 0x00;
  692. if ((RFIRQF1 & IRQ_CSP_MANINT) & rfim)
  693. {
  694. /*
  695. * Important! Because of how the CSP programs are written, CSP_INT interrupts should
  696. * be processed before CSP_STOP interrupts. This becomes an issue when there are
  697. * long critical sections.
  698. */
  699. /* clear flag */
  700. RFIRQF1 = ~IRQ_CSP_MANINT;
  701. macCspTxIntIsr();
  702. }
  703. else if ((RFIRQF1 & IRQ_CSP_STOP) & rfim)
  704. {
  705. /* clear flag */
  706. RFIRQF1 = ~IRQ_CSP_STOP;
  707. macCspTxStopIsr();
  708. }
  709. else if ((RFIRQF1 & IRQ_TXACKDONE) & rfim)
  710. {
  711. /* disable interrupt - set up is for "one shot" operation */
  712. RFIRQM1 &= ~IM_TXACKDONE;
  713. macRxAckTxDoneCallback();
  714. }
  715. rfim = RFIRQM0;
  716. /* process RFIRQF0 next */
  717. if ((RFIRQF0 & IRQ_FIFOP) & rfim)
  718. {
  719. /* continue to execute interrup t handler as long as FIFOP is active */
  720. do
  721. {
  722. macRxThresholdIsr();
  723. RFIRQF0 = ~IRQ_FIFOP;
  724. } while (FSMSTAT1 & FIFOP);
  725. }
  726. CLEAR_SLEEP_MODE();
  727. HAL_EXIT_ISR();
  728. }
  729. /**************************************************************************************************
  730. * @fn macMcuRfErrIsr
  731. *
  732. * @brief Interrupt service routine that handles all RF Error interrupts. Only the RX FIFO
  733. * overflow condition is handled.
  734. *
  735. * @param none
  736. *
  737. * @return none
  738. **************************************************************************************************
  739. */
  740. HAL_ISR_FUNCTION( macMcuRfErrIsr, RFERR_VECTOR )
  741. {
  742. uint8 rferrm;
  743. HAL_ENTER_ISR();
  744. rferrm = RFERRM;
  745. if ((RFERRF & RFERR_RXOVERF) & rferrm)
  746. {
  747. RFERRF = ~RFERR_RXOVERF;
  748. macRxFifoOverflowIsr();
  749. }
  750. CLEAR_SLEEP_MODE();
  751. HAL_EXIT_ISR();
  752. }
  753. /**************************************************************************************************
  754. * @fn macMcuRecordMaxRssiStart
  755. *
  756. * @brief Starts recording of the maximum received RSSI value.
  757. *
  758. * @param none
  759. *
  760. * @return none
  761. **************************************************************************************************
  762. */
  763. MAC_INTERNAL_API void macMcuRecordMaxRssiStart(void)
  764. {
  765. /* start maximum recorded value at the lowest possible value */
  766. maxRssi = -128;
  767. /* enable timer overflow interrupt */
  768. T2IRQM |= TIMER2_PERM;
  769. }
  770. /**************************************************************************************************
  771. * @fn macMcuRecordMaxRssiStop
  772. *
  773. * @brief Stops recording of the maximum received RSSI. It returns the maximum value
  774. * received since starting the recording.
  775. *
  776. * @param none
  777. *
  778. * @return maximum received RSSI value
  779. **************************************************************************************************
  780. */
  781. MAC_INTERNAL_API int8 macMcuRecordMaxRssiStop(void)
  782. {
  783. /* disable timer overflow interrupt */
  784. T2IRQM &= ~TIMER2_PERM;
  785. return(maxRssi);
  786. }
  787. /*=================================================================================================
  788. * @fn macMcuRecordMaxRssiIsr
  789. *
  790. * @brief Interrupt service routine called during recording of max RSSI value.
  791. *
  792. * @param none
  793. *
  794. * @return none
  795. *=================================================================================================
  796. */
  797. static void mcuRecordMaxRssiIsr(void)
  798. {
  799. int8 rssi;
  800. /* read latest RSSI value */
  801. rssi = RSSI;
  802. /* if new RSSI value is greater than the maximum already received, it is the new maximum */
  803. if (rssi > maxRssi)
  804. {
  805. maxRssi = rssi;
  806. }
  807. }
  808. /**************************************************************************************************
  809. * @fn macMcuAccumulatedOverFlow
  810. *
  811. * @brief This function is used to accumulate timer 2 overflow if applicable
  812. * on the relevant platform
  813. *
  814. * @param none
  815. *
  816. * @return none
  817. **************************************************************************************************
  818. */
  819. MAC_INTERNAL_API void macMcuAccumulatedOverFlow(void)
  820. {
  821. halIntState_t s;
  822. HAL_ENTER_CRITICAL_SECTION(s);
  823. if(updateRolloverflag == FALSE)
  824. {
  825. accumulatedOverflowCount += macGetBackOffTimerRollover();
  826. }
  827. else
  828. {
  829. updateRolloverflag = FALSE;
  830. }
  831. HAL_EXIT_CRITICAL_SECTION(s);
  832. }
  833. /**************************************************************************************************
  834. * Compile Time Integrity Checks
  835. **************************************************************************************************
  836. */
  837. #if ((IRQ_SFD != IM_SFD) || (IRQ_FIFOP != IM_FIFOP) || (IRQ_TXACKDONE != IM_TXACKDONE))
  838. #error "ERROR: Compile time error with RFIRQFx vs RFIRQMx register defines."
  839. #endif
  840. #if defined (FEATURE_CC253X_LOW_POWER_RX) && !(defined (HAL_MCU_CC2530) || defined (HAL_MCU_CC2533))
  841. #error "ERROR: FEATURE_CC253X_LOW_POWER_RX can only be used with CC2530 or CC2533."
  842. #endif
  843. /**************************************************************************************************
  844. */