⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mac_mcu.c

📁 Zigbee2006入门源代码,包括了Zigbee的入门介绍,和源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/**************************************************************************************************
    Filename:
    Revised:        $Date: 2007-05-15 15:37:47 -0700 (Tue, 15 May 2007) $
    Revision:       $Revision: 14304 $

    Description:

    Describe the purpose and contents of the file.

    Copyright (c) 2006 by Texas Instruments, Inc.
    All Rights Reserved.  Permission to use, reproduce, copy, prepare
    derivative works, modify, distribute, perform, display or sell this
    software and/or its documentation for any purpose is prohibited
    without the express written consent of Texas Instruments, Inc.
**************************************************************************************************/

   ///////////////////////////////////////////////////////////////////////////////////
   //  REV_B_WORKAROUND : Place holder as a reminder to optimize the bank select code
   //  once Rev B obsoleted.  Currently the bank select bits share a register with
   //  other functionality.  This will be *mirrored* to a new location where it
   //  is the only thing in the register.
   ///////////////////////////////////////////////////////////////////////////////////


/* ------------------------------------------------------------------------------------------------
 *                                          Includes
 * ------------------------------------------------------------------------------------------------
 */

/* hal */
#include "hal_defs.h"
#include "hal_mcu.h"

/* low-level specific */
#include "mac_rx.h"
#include "mac_tx.h"
#include "mac_backoff_timer.h"
#include "mac_csp_tx.h"
#include "mac_rx_onoff.h"

/* target specific */
#include "mac_mcu.h"
#include "mac_radio_defs.h"

/* debug */
#include "mac_assert.h"


/* ------------------------------------------------------------------------------------------------
 *                                           Defines
 * ------------------------------------------------------------------------------------------------
 */
#define T2CNF_BASE_VALUE    (RUN | SYNC)

/* for optimized indexing of uint32's */
#if HAL_MCU_LITTLE_ENDIAN()
#define UINT32_NDX0   0
#define UINT32_NDX1   1
#define UINT32_NDX2   2
#define UINT32_NDX3   3
#else
#define UINT32_NDX0   3
#define UINT32_NDX1   2
#define UINT32_NDX2   1
#define UINT32_NDX3   0
#endif

/* 32 kHz clock source select in CLKCON */
#if !defined (OSC32K_CRYSTAL_INSTALLED) || (defined (OSC32K_CRYSTAL_INSTALLED) && (OSC32K_CRYSTAL_INSTALLED == TRUE))
#define OSC_32KHZ  0x00 /* external 32 KHz xosc */
#else
#define OSC_32KHZ  0x80 /* internal 32 KHz rcosc */
#endif


/* ------------------------------------------------------------------------------------------------
 *                                        Local Variables
 * ------------------------------------------------------------------------------------------------
 */
static int8 maxRssi;

/*
 *  A shadow variable is required for the lower four bits of T2PEROF2.  These bits have different
 *  functionality for read versus write.  This would fine except the upper bits of T2PEROF2 are
 *  used to enable and disable interrupts and must be set independently of the lower four bits.
 *  Since the original value of the lower four bits is lost (it reads as something else) these
 *  bits must be stored in a shadow variable.  This shadow variable is declared here and is
 *  used where needed in this module.
 */
static uint8 shadowPerof2;


/* ------------------------------------------------------------------------------------------------
 *                                       Local Prototypes
 * ------------------------------------------------------------------------------------------------
 */
static void mcuRecordMaxRssiIsr(void);


/**************************************************************************************************
 * @fn          macMcuInit
 *
 * @brief       Initialize the MCU.
 *
 * @param       none
 *
 * @return      none
 **************************************************************************************************
 */
void macMcuInit(void)
{
  uint16 i;

  MAC_ASSERT(CHVER != 0x00); /* chip version A is obsolete */
///////////////////////////////////////////////////////////////////////////////////
//  REV_B_WORKAROUND : replace with line below when Rev B is obsoleted
#ifndef _REMOVE_REV_B_WORKAROUNDS
#else
//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
//  keep this code, delete the rest
  MAC_ASSERT(CHVER != 0x01); /* chip version B is obsolete */
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#endif
///////////////////////////////////////////////////////////////////////////////////
  MAC_ASSERT(CHVER != 0x02); /* chip version C is obsolete */

///////////////////////////////////////////////////////////////////////////////////
//  REV_B_WORKAROUND : workaround for chip bug #51, remove when fixed
#ifndef _REMOVE_REV_B_WORKAROUNDS
  FSCTRLH = 0x41;
  FSTST1L = 0x32;
  FSTST2H = 0x20;
#endif
///////////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////////
//  REV_B_WORKAROUND : workaround for chip bug #267, remove when fixed
#ifndef _REMOVE_REV_B_WORKAROUNDS
  MDMCTRL0L |= AUTOACK;  /* enable autoack */
#endif
///////////////////////////////////////////////////////////////////////////////////

  /* tuning adjustments for optimal radio performance; details available in datasheet */
  RXCTRL0H = 0x32;
  RXCTRL0L = 0xF5;
 
///////////////////////////////////////////////////////////////////////////////////
//  REV_B_WORKAROUND : workaround for chip bug #267, update when fixed
#ifndef _REMOVE_REV_B_WORKAROUNDS
  /* do nothing */
#else
// this part can go away once new .h file is shipping
#ifndef IRQSRC
#define IRQSRC    XREG( 0xDF64 )
#endif
//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
//  keep this code, delete the rest
  /* enable TX_DONE interrupts for ACK transmits */
  IRQSRC = TXACK;
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#endif
///////////////////////////////////////////////////////////////////////////////////

  /* disable the CSPT register compare function */
  CSPT = 0xFF;

  /* enable general RF interrupts */
  IEN2 |= RFIE;

  /* intialize shadow register */
  shadowPerof2 = 0;

  /* set RF interrupts one notch above lowest priority (four levels available) */
  IP0 |=  IP_RFERR_RF_DMA_BV;
  IP1 &= ~IP_RFERR_RF_DMA_BV;

  /*-------------------------------------------------------------------------------
   *  Initialize MAC timer.
   */

  /* set timer rollover */
  T2CAPLPL = MAC_RADIO_TIMER_TICKS_PER_BACKOFF() & 0xFF;
  T2CAPHPH = MAC_RADIO_TIMER_TICKS_PER_BACKOFF() >> 8;

  /* start timer */
  T2CNF |= RUN;

  /* enable timer interrupts */
  T2IE = 1;

  /* configure clock to use XOSC */
  SLEEP &= ~OSC_PD;                       /* turn on 16MHz RC and 32MHz XOSC */
  while (!(SLEEP & XOSC_STB));            /* wait for 32MHz XOSC stable */
  asm("NOP");                             /* chip bug workaround */
  for (i=0; i<504; i++) asm("NOP");       /* Require 63us delay for Rev B */
  CLKCON = (0x00 | OSC_32KHZ);            /* 32MHz XOSC */
  while (CLKCON != (0x00 | OSC_32KHZ));
  SLEEP |= OSC_PD;                        /* turn off 16MHz RC */
  
  
 /*----------------------------------------------------------------------------------------------
  *  Initialize random seed value.
  */

  /* turn on radio power */
  RFPWR &= ~RREG_RADIO_PD;
  while((RFPWR & ADI_RADIO_PD));
 
  /*
   *  Set radio for infinite reception.  Once radio reaches this state,
   *  it will stay in receive mode regardless RF activity.
   */
  MDMCTRL1L = MDMCTRL1L_RESET_VALUE | RX_MODE_INFINITE_RECEPTION;
  
  /* turn on the receiver */
  macRxOn();

  /*
   *  Wait for radio to reach infinite reception state.  Once it does,
   *  The least significant bit of ADTSTH should be pretty random.
   */
  while (FSMSTATE != FSM_FFCTRL_STATE_RX_INF)

  /* put 16 random bits into the seed value */
  {
    uint16 rndSeed;
    uint8  i;
    
    rndSeed = 0;
    
    for(i=0; i<16; i++)
    {
      /* use most random bit of analog to digital receive conversion to populate the random seed */
      rndSeed = (rndSeed << 1) | (ADCTSTH & 0x01);
    }

    /*
     *  The seed value must not be zero.  If it is, the psuedo random sequence will be always be zero.
     *  There is an extremely small chance this seed could randomly be zero (more likely some type of
     *  hardware problem would cause this).  The following check makes sure this does not happen.
     */
    if (rndSeed == 0x0000)
    {
      rndSeed = 0xBEEF; /* completely arbitrary "random" value */
    }

    /*
     *  Two writes to RNDL will set the random seed.  A write to RNDL copies current contents
     *  of RNDL to RNDH before writing new the value to RNDL.
     */
    RNDL = rndSeed & 0xFF;
    RNDL = rndSeed >> 8;
  }

  /* turn off the receiver */
  macRxOff();

  /* take receiver out of infinite reception mode; set back to normal operation */
  MDMCTRL1L = MDMCTRL1L_RESET_VALUE | RX_MODE_NORMAL_OPERATION;
  
  /* turn radio back off */
  RFPWR |= RREG_RADIO_PD;
}


/**************************************************************************************************
 * @fn          macMcuRandomByte
 *
 * @brief       Returns a random byte using a special hardware feature that generates new
 *              random values based on the truly random seed set earlier.
 *
 * @param       none
 *
 * @return      a random byte
 **************************************************************************************************
 */
uint8 macMcuRandomByte(void)
{
  /* clock the random generator to get a new random value */
  ADCCON1 = (ADCCON1 & ~RCTRL_BITS) | RCTRL_CLOCK_LFSR;

  /* return new randomized value from hardware */
  return(RNDH);
}


/**************************************************************************************************
 * @fn          macMcuTimerCount
 *
 * @brief       Returns the upper eight bits of hardware timer count.  The full 16-bit timer
 *              count is not returned because the timer compare feature only compares one byte.
 *
 * @param       none
 *
 * @return      upper eight bits of hardware timer count
 **************************************************************************************************
 */
uint8 macMcuTimerCount(void)
{
  uint8 volatile temp;

  /* reading T2TLD latches T2THD */
  temp = T2TLD;
  return(T2THD);
}


/**************************************************************************************************
 * @fn          macMcuTimerCapture
 *
 * @brief       Returns the last timer capture.  This capture should have occurred at the
 *              receive time of the last frame (the last time SFD transitioned to active).
 *
 * @param       none
 *
 * @return      last capture of hardware timer (full 16-bit value)
 **************************************************************************************************
 */
uint16 macMcuTimerCapture(void)
{
  uint16 timerCapture;

  timerCapture = T2CAPLPL;
  timerCapture |= T2CAPHPH << 8;

  return (timerCapture);
}


/**************************************************************************************************
 * @fn          macMcuOverflowCount
 *
 * @brief       Returns the value of the overflow counter which is a special hardware feature.
 *              The overflow count actually is only 20 bits of information.
 *
 * @param       none
 *
 * @return      value of overflow counter
 **************************************************************************************************
 */
uint32 macMcuOverflowCount(void)
{
  uint32 overflowCount;

  /* for efficiency, the 32-bit value is encoded using endian abstracted indexing */

  /* must read T2OF0 first, this latches T2OF1 and T2OF2 */
  ((uint8 *)&overflowCount)[UINT32_NDX0] = T2OF0;
  ((uint8 *)&overflowCount)[UINT32_NDX1] = T2OF1;
  ((uint8 *)&overflowCount)[UINT32_NDX2] = T2OF2;
  ((uint8 *)&overflowCount)[UINT32_NDX3] = 0;

  return (overflowCount);
}


/**************************************************************************************************
 * @fn          macMcuOverflowCapture
 *
 * @brief       Returns the last capture of the overflow counter.  A special hardware feature
 *              captures the overflow counter when the regular hardware timer is captured.
 *
 * @param       none
 *
 * @return      last capture of overflow count
 **************************************************************************************************
 */
uint32 macMcuOverflowCapture(void)
{
  uint32 overflowCapture;

  /* for efficiency, the 32-bit value is encoded using endian abstracted indexing */

  ((uint8 *)&overflowCapture)[UINT32_NDX0] = T2PEROF0;
  ((uint8 *)&overflowCapture)[UINT32_NDX1] = T2PEROF1;
  ((uint8 *)&overflowCapture)[UINT32_NDX2] = T2PEROF2 & PEROF2_BITS;
  ((uint8 *)&overflowCapture)[UINT32_NDX3] = 0;

  return (overflowCapture);
}


/**************************************************************************************************
 * @fn          macMcuOverflowSetCount
 *
 * @brief       Sets the value of the hardware overflow counter.
 *
 * @param       count - new overflow count value
 *
 * @return      none
 **************************************************************************************************
 */
void macMcuOverflowSetCount(uint32 count)
{
  MAC_ASSERT(!((count >> 16) & ~PEROF2_BITS));   /* illegal count value */

  /* for efficiency, the 32-bit value is decoded using endian abstracted indexing */

  /* T2OF2 must be written last */
  T2OF0 = ((uint8 *)&count)[UINT32_NDX0];
  T2OF1 = ((uint8 *)&count)[UINT32_NDX1];
  T2OF2 = ((uint8 *)&count)[UINT32_NDX2];
}


/**************************************************************************************************
 * @fn          macMcuOverflowSetCompare
 *
 * @brief       Set overflow count compare value.  An interrupt is triggered when the overflow
 *              count equals this compare value.
 *
 * @param       count - overflow count compare value
 *

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -