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

📄 halstack.c

📁 本程序是基于Zigbee协议的无线温度传感器网络系统
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
  V0.1 Initial Release   10/July/2006

*/

#include "hal.h"
#include "halStack.h"
#include "console.h"
#include "debug.h"
#include "ieee_lrwpan_defs.h"
#include "memalloc.h"
#include "phy.h"
#include "mac.h"

/*
V0.2.2.
  8/2/2006 Fixed problem with checking of CRC byte.
*/


RADIO_FLAGS local_radio_flags;

#ifdef  LRWPAN_ASYNC_INTIO

static volatile BYTE serio_rxBuff[LRWPAN_ASYNC_RX_BUFSIZE];
static volatile BYTE serio_rxHead, serio_rxTail;

#endif




//halInit contains both processor specific initialization
void halInit(void){
  //Set clock source
  local_radio_flags.val = 0;
  SET_MAIN_CLOCK_SOURCE(CRYSTAL);
  halInitUart();
  halSetBaud(LRWPAN_DEFAULT_BAUDRATE);
  halInitMACTimer();
}


//initialize UART to be used by
void halInitUart(void) {
  // Setup for UART0
   IO_PER_LOC_UART0_AT_PORT0_PIN2345();
   UTX0IF = 1;

#ifdef LRWPAN_ASYNC_INTIO
  serio_rxHead = 0;
  serio_rxTail = 0;
  INT_ENABLE_URX0(INT_ON);
#endif

}

#ifdef  LRWPAN_ASYNC_INTIO

//get a character from serial port, uses interrupt driven IO
char halGetch(void){
    char x;
    do {
      x = serio_rxHead;  //use tmp because of volt decl
    }  while(serio_rxTail == x);
    serio_rxTail++;
   if (serio_rxTail == LRWPAN_ASYNC_RX_BUFSIZE) serio_rxTail = 0;
   return (serio_rxBuff[serio_rxTail]);
}

 BOOL halGetchRdy(void){
   char x;
   x = serio_rxHead;
   return(serio_rxTail != x);
 }

#else
//get a character from serial port
char halGetch(void){
   char c;

   while (!URX0IF);
   c = U0DBUF;
   URX0IF = FALSE;

   return c;
}

BOOL halGetchRdy(void){

  if (URX0IF) return (1);
  else return(0);

}

#endif


void halUtilMemCopy(BYTE *dst, BYTE *src, BYTE len) {
  while (len) {
    *dst = *src;
    dst++;src++;
    len--;
  }
}

// assuming 16us period, have 1/16us = 62500 tics per seocnd
#define T2CMPVAL (62500/SLOWTICKS_PER_SECOND)

//use timer2, will set it up for one tick per symbol
//assuming 2.4GHZ and a 32 MHZ clock.
// this is a 20 bit counter, will overflow in ~16 seconds
//should be long enough for MAC timeout cases
void halInitMACTimer(void) {

  T2CNF = 0x00; //ensure timer is idle

  T2CAPHPH = 0x02;  // setting for 16 u-second periods
  T2CAPLPL = 0x00;  // (0x0200) / 32 = 16 u-seconds
  //set the interrupt compare to its maximum value

#ifdef LRWPAN_ENABLE_SLOW_TIMER
  T2PEROF0 = 0xFF & (T2CMPVAL);
  T2PEROF1 = (BYTE) (T2CMPVAL>>8);
  //enable overflow count compare interrupt
  T2PEROF2 = ((BYTE) (T2CMPVAL>>16)) | 0x20;
#endif

  //turn on timer
  //configure timer
  T2CNF = 0x03; //start timer

  INT_SETFLAG_T2(INT_CLR); //clear processor interrupt flag
  //enable T2 processor interrupt
#ifdef LRWPAN_ENABLE_SLOW_TIMER
  INT_ENABLE_T2(INT_ON);
#endif

}

UINT32 halGetMACTimer(void){
  UINT32 t;
  BOOL gie_status;

  SAVE_AND_DISABLE_GLOBAL_INTERRUPT(gie_status);
  t = 0x0FF & T2OF0;
  t += (((UINT16)T2OF1)<<8);
  t += (((UINT32) T2OF2 & 0x0F)<<16);
  RESTORE_GLOBAL_INTERRUPT(gie_status);
  return (t);
}

#ifdef LRWPAN_COMPILER_NO_RECURSION
UINT32 halISRGetMACTimer(void){
  UINT32 t;
  BOOL gie_status;

  SAVE_AND_DISABLE_GLOBAL_INTERRUPT(gie_status);
  t = 0x0FF & T2OF0;
  t += (((UINT16)T2OF1)<<8);
  t += (((UINT32) T2OF2 & 0x0F)<<16);
  RESTORE_GLOBAL_INTERRUPT(gie_status);
  return (t);
}

#endif




//only works as long as SYMBOLS_PER_MAC_TICK is not less than 1
UINT32 halMacTicksToUs(UINT32 ticks){

   UINT32 rval;

   rval =  (ticks/SYMBOLS_PER_MAC_TICK())* (1000000/LRWPAN_SYMBOLS_PER_SECOND);
   return(rval);
}

//assumes that Timer2 has been initialized and is running
UINT8 halGetRandomByte(void) {
  return(T2OF0);
}

//write a character to serial port
// Uses UART initialized by halInitUart

void halPutch(char c){
  while (!UTX0IF);
  UTX0IF = 0;
  U0DBUF = c;
}

void halRawPut(char c){
  while (!UTX0IF);
  UTX0IF = 0;
  U0DBUF = c;
}





//set the radio frequency
LRWPAN_STATUS_ENUM halSetRadioIEEEFrequency(PHY_FREQ_ENUM frequency, BYTE channel)
{
   UINT16 afreq;

   if (frequency != PHY_FREQ_2405M) return(LRWPAN_STATUS_PHY_FAILED);
   if ((channel < 11) || (channel > 26)) return(LRWPAN_STATUS_PHY_FAILED);
   afreq = 357 + 5*(channel - 11);
   FSCTRLL = (BYTE) afreq;
   FSCTRLH = ((FSCTRLH & ~0x03) | (BYTE)((afreq >> 8) & 0x03));
   return(LRWPAN_STATUS_SUCCESS);
}

//this assumes 2.4GHz frequency
LRWPAN_STATUS_ENUM halSetChannel(BYTE channel){
 return(halSetRadioIEEEFrequency(PHY_FREQ_2405M, channel));
}


#if defined(IAR8051)
//this uses the IEEE address stored in program memory.
//ensure that the flash programmer is configured to retain
//the IEEE address
void halGetProcessorIEEEAddress(BYTE *buf) {
#if (CC2430_FLASH_SIZE == 128)
  unsigned char bank;
  bank = MEMCTR;
  //switch to bank 3
  MEMCTR |= 0x30;
#endif
  //note that the flash programmer stores these in BIG ENDIAN order for some reason!!!
  buf[7] = *(ROMCHAR *)(IEEE_ADDRESS_ARRAY+0);
  buf[6] = *(ROMCHAR *)(IEEE_ADDRESS_ARRAY+1);
  buf[5] = *(ROMCHAR *)(IEEE_ADDRESS_ARRAY+2);
  buf[4] = *(ROMCHAR *)(IEEE_ADDRESS_ARRAY+3);
  buf[3] = *(ROMCHAR *)(IEEE_ADDRESS_ARRAY+4);
  buf[2] = *(ROMCHAR *)(IEEE_ADDRESS_ARRAY+5);
  buf[1] = *(ROMCHAR *)(IEEE_ADDRESS_ARRAY+6);
  buf[0] = *(ROMCHAR *)(IEEE_ADDRESS_ARRAY+7);
 #if (CC2430_FLASH_SIZE == 128)
  //resore old bank settings
  MEMCTR = bank;
#endif
}

#endif


#if defined(HI_TECH_C)
//cannot figure out how to get the Hi-Tech C51 compiler to support
//banking, so can't access the IEEE address stored in memory

//use this if you don't want to use the IEEE Address stored in program memory
//by the flash memory
void halGetProcessorIEEEAddress(BYTE *buf) {
	buf[0] = aExtendedAddress_B0;
	buf[1] = aExtendedAddress_B1;
	buf[2] = aExtendedAddress_B2;
	buf[3] = aExtendedAddress_B3;
	buf[4] = aExtendedAddress_B4;
	buf[5] = aExtendedAddress_B5;
	buf[6] = aExtendedAddress_B6;
	buf[7] = aExtendedAddress_B7;
}
#endif



void halSetRadioIEEEAddress(void) {
  BYTE buf[8];
  halGetProcessorIEEEAddress(buf);
  IEEE_ADDR0 = buf[0];
  IEEE_ADDR1 = buf[1];
  IEEE_ADDR2 = buf[2];
  IEEE_ADDR3 = buf[3];
  IEEE_ADDR4 = buf[4];
  IEEE_ADDR5 = buf[5];
  IEEE_ADDR6 = buf[6];
  IEEE_ADDR7 = buf[7];
}

void halSetRadioPANID(UINT16 panid){
  PANIDL = (BYTE) (panid);
  PANIDH = (BYTE) (panid>>8);
 }

void halSetRadioShortAddr(SADDR saddr){
  SHORTADDRL = (BYTE) (saddr);
  SHORTADDRH = (BYTE) (saddr>>8);
}



//return value of non-zero indicates failure
//Turn on Radio, initialize for RF mode
//assumes that auto-ack is enabled
//this function based on sppInit example from ChipCon
//also sets the IEEE address
//if listen_flag is true, then radio is configured for
//listen only (no auto-ack, no address recognition)

/*
Eventually, change this so that auto-ack can be configured as
on or off. When Coordinator is trying to start a network,
auto-ack, addr decoding will be off as Coordinator will be doing an energy
scan and detecting PAN collisions, and thus will not be doing
any acking of packets. After the network is started, then
will enable auto-acking.
Routers and End devices will always auto-ack

i
*/



LRWPAN_STATUS_ENUM halInitRadio(PHY_FREQ_ENUM frequency, BYTE channel, RADIO_FLAGS radio_flags)
{
  LRWPAN_STATUS_ENUM status;


  // Setting the frequency
  status = halSetRadioIEEEFrequency(frequency, channel);
  if (status != LRWPAN_STATUS_SUCCESS) return(status);

  //turning on power to analog part of radio and waiting for voltage regulator.
  RFPWR = 0x04;
  while((RFPWR & 0x10)){}
  //radio_flags.listen_mode=1; //debug
  if (radio_flags.bits.listen_mode) {
    //corresponds to promiscuous modes
    //radio accepts all packets, the HUSSY!
    MDMCTRL0H &= ~ADR_DECODE;    //no address decode
    MDMCTRL0L &= ~AUTO_ACK;       //no auto ack
  } else {
    // Turning on Address Decoding
    MDMCTRL0H |= ADR_DECODE;
    //enable auto_ack
    MDMCTRL0L |= AUTO_ACK;
  }
  local_radio_flags = radio_flags;  //save this for later
  // Setting for AUTO CRC
  MDMCTRL0L |= AUTO_CRC;

  //pan
  if (radio_flags.bits.pan_coordinator) {
    MDMCTRL0H |= PAN_COORDINATOR;  //accepts frames with only source addressing modes
  } else {
    MDMCTRL0H &= ~PAN_COORDINATOR;  //rejects frames with only source addressing modes
  }

  // Turning on AUTO_TX2RX
  FSMTC1 = ((FSMTC1 & (~AUTO_TX2RX_OFF & ~RX2RX_TIME_OFF))  | ACCEPT_ACKPKT);

  // Turning off abortRxOnSrxon.
  FSMTC1 &= ~0x20;

  //now configure the RX, TX systems.
  // Setting the number of bytes to assert the FIFOP flag
  IOCFG0 = 127;  //set to max value as the FIFOP flag goes high when complete packet received

  // Flushing both Tx and Rx FiFo. The flush-Rx is issued twice to reset the SFD.
  // Calibrating the radio and turning on Rx to evaluate the CCA.
  SRXON;
  SFLUSHTX;
  SFLUSHRX;
  SFLUSHRX;
  STXCALN;
  ISSTART;

//this controls the frame pending bit in ACK frames.
//because of auto-ack, we will not have time to determine if data
//is actually pending or not.
#if defined(LWRPAN_RFD)
  SACK;  //RFDs never have data pending for FFDs
#else
  SACKPEND;  //routers/
#endif

  halSetRadioIEEEAddress();

   //Radio can interrupt when
   //RX configuration
   //clear flags/mask in radio
   RFIF = 0;
   RFIM = 0;   //all interrupts are masked.
   //enable RX interrupt on processor
   INT_SETFLAG_RF(INT_CLR);
   INT_ENABLE_RF(INT_ON);

   //enable RX RFERR interrupt on processor
   INT_SETFLAG_RFERR(INT_CLR);
   INT_ENABLE_RFERR(INT_ON);

   //do not use DMA at this point
   //enable the RX receive interrupt here.
   RFIM |= IRQ_FIFOP;

   return(LRWPAN_STATUS_SUCCESS);
}

#define PIN_CCA   CCA    //CCA is defined in hal.h

//regardless of what happens here, we will try TXONCCA after this returns.
void  doIEEE_backoff(void) {
     BYTE be, nb, tmp, rannum;
    UINT32  delay, start_tick;

   be = aMinBE;
   nb = 0;
  do {
      if (be) {
        //do random delay
        tmp = be;
        //compute new delay
        delay = 1;
        while (tmp) {
          delay = delay << 1;  //delay = 2**be;
           tmp--;
         }
        rannum =  halGetRandomByte() & (delay-1); //rannum will be between 0 and delay-1
        delay = 0;
        while (rannum) {
            delay  += SYMBOLS_TO_MACTICKS(aUnitBackoffPeriod);
            rannum--;
         }//delay = aUnitBackoff * rannum
        //now do backoff
       start_tick = halGetMACTimer();
        while (halMACTimerNowDelta(start_tick) < delay);
      }
      //check CCA
      if (PIN_CCA)  break;
      nb++;
      be++;
      if (be > aMaxBE) be =aMaxBE;
   }while (nb <= macMaxCSMABackoffs);
  return;
}

//transmit packet
//hdrlen - header lenth
//hdr - pointer to header data
//plen - payload length
//pload - pointer to payload

LRWPAN_STATUS_ENUM halSendPacket(BYTE flen, BYTE *frm)
{
  BYTE len;
  LRWPAN_STATUS_ENUM res;

  //if you print out the packet, this can cause timeouts on waits

⌨️ 快捷键说明

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