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

📄 halstack.c

📁 * "Copyright (c) 2006 Robert B. Reese ("AUTHOR")" * All rights reserved. * (R. Reese, reese@ece.
💻 C
字号:
/*
  V0.1 Initial Release   10/July/2006  RBR

*/
#include <stdio.h>


#include "lrwpan_config.h"
#include "hal.h"
#include "halstack.h"
#include "console.h"
#include "debug.h"
#include "ieee_lrwpan_defs.h"
#include "memalloc.h"



static RADIO_FLAGS local_radio_flags;



static UINT16 radio_panid;
static SADDR radio_saddr;
static BYTE current_channel;  //channels 11 to 16



typedef enum _RADIO_STATE_ENUM {
  RADIO_STATE_OFF,
  RADIO_STATE_ON
}RADIO_STATE_ENUM;

RADIO_STATE_ENUM radio_state;

#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){
    radio_state = RADIO_STATE_OFF;
	local_radio_flags.val = 0;
	halInitUart();
	halInitMACTimer();
  }


//we are going to initialize the console to single character
//input, and no echo to emulate the micro

void halInitUart(void) {
 
  TX9 = 0;  TXEN = 1; // transmit enable  SYNC = 0; // async mode   BRGH = 1; // hi speed mode   halSetBaud(LRWPAN_DEFAULT_BAUDRATE);  TRISC7=1; // RC7 input    TRISC6=0; // RC6 output   RX9 = 0;  // 8-bit reception    SPEN = 1; // serial port enable    CREN = 0; // clear enable first   CREN = 1; // now enable first     
#ifdef LRWPAN_ASYNC_INTIO
  RCIE = 0; 
  serio_rxHead = 0;
  serio_rxTail = 0;
  RCIE = 1; 
  RCIP = 1;
  PEIE = 1; 
#endif
}

#ifdef  LRWPAN_ASYNC_INTIO
//get a character from serial port, uses interrupt driven IO
char halGetch(void){
    while(serio_rxTail == serio_rxHead);
    serio_rxTail++;
   if (serio_rxTail == LRWPAN_ASYNC_RX_BUFSIZE) serio_rxTail = 0;
   return (serio_rxBuff[serio_rxTail]);
}

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


#else

char halGetch(void){
  while(!RCIF);
  return(RCREG);
}

BOOL halGetchRdy(void){
 return(RCIF);
 }

#endif


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

void halPutch(char c){
  while(!TXIF);
  TXREG = c;	
}

void halRawPut(char c){
  while(!TXIF);
  TXREG = c;	
}


//defined such that timer0 has a period of 1 symbol, or 16 us
//FOSC assumed to be some multiple of 4 MHZ

#define SYMBOL_FREQ  62500      //equals to symbols period of 16us




#define T0_PRESCALE ((FOSC/(SYMBOL_FREQ/SYMBOLS_PER_MAC_TICK()))/4)

#define MAX_WAIT_MS  (TO_PRESCALE*4*65536*1000)/FOSC  //maximum wait in milliseconds

#if T0_PRESCALE > 256
#error "Timer 0 PRESCALE TOO LARGE"
#endif

#if (T0_PRESCALE == 256) 
  #define T0_PREBITS 7
#elif (T0_PRESCALE == 128) 
  #define T0_PREBITS 6
#elif (T0_PRESCALE == 64) 
  #define T0_PREBITS 5
#elif (T0_PRESCALE == 32) 
  #define T0_PREBITS 4
#elif (T0_PRESCALE == 16) 
  #define T0_PREBITS 3
#elif (T0_PRESCALE == 8) 
  #define T0_PREBITS 2
#elif (T0_PRESCALE == 4) 
  #define T0_PREBITS 1
#elif (T0_PRESCALE == 2) 
  #define T0_PREBITS 0
#else
  #error "Illegal Timer0 prescale!"
#endif

#define T3_PRESCALE 8
#if (T3_PRESCALE == 8) 
  #define T3_PREBITS (3 << 4)
#elif (T3_PRESCALE == 4) 
  #define T3_PREBITS  (2<< 4)
#elif (T3_PRESCALE == 2) 
  #define T0_PREBITS  (1 << 4)
#elif (T3_PRESCALE == 1)
   #define T3_PREBITS  0
#else
  #error "Illegal Timer0 prescale!"
#endif


#define T3PERIOD   ((FOSC/4)/T3_PRESCALE)/SLOWTICKS_PER_SECOND

#if (T3PERIOD > 65535) 
 #error "slow_tics_per_second define is too small!"
#endif


UINT8 halMacTimerOflow;   //assumed incremented by interrupt service

//Timer0 used as MAC timer, Timer3/CCP1 capture compare as theuser periodic interrupt timer

void halInitMACTimer(void) {
   halMacTimerOflow =0;
   //setup Timer0
   T0CON = T0_PREBITS ; //convenient that all other bits beside prescale are '0'
   TMR0H = 0;
   TMR0L = 0;
   TMR0IF = 0;

#ifdef LRWPAN_ENABLE_SLOW_TIMER
   //setup Timer3, will use compare mode with CCP1
  T3CON = 0xC0 | T3_PREBITS;   //uses TMR3 as clock source for compare modules
  TMR3H = 0;
  TMR3L = 0;
  TMR3IF = 0;
   //configure CCP1 as period register for Timer3
   CCP1IF = 0;
   CCP1CON = 0; //reset
   CCP1CON = 0x0A;   //software interrupt on timer match
   T3CCP1 = 0;
   T3CCP2 = 1;           //select timer3 as match source
  //setup the first match with CCP1
   //now configure interrupts
   TMR3IE = 0;
   CCPR1 = T3PERIOD;
   CCP1IP = 1;
   CCP1IE = 1;
   TMR3ON = 1;
 #endif
 
 
   TMR0IE = 1;
   //turn on the timers
   TMR0ON = 1;
   IPEN = 0;    //disable priorities
   GIEL = 1;


}

void halShutdown(void){
  //disable timer interrupts so that they don't wake us up
   TMR0IE = 0;
#ifdef LRWPAN_ENABLE_SLOW_TIMER
    CCP1IE = 0;
 #endif
   halDisableRadio();
}

void halWarmstart(void){
//enable timer interrupts 
  TMR0IE = 1;
#ifdef LRWPAN_ENABLE_SLOW_TIMER
    CCP1IE =1;
 #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);
}



//read the macTimer, assumes interrupts, Timer0 are enabled!
UINT32 halGetMACTimer(void)
{
     UINT8   iStatus;
     UINT32  rval;
    

   do {
     rval = TMR0L;      //freeze timer 0
     rval  +=  ((UINT16) TMR0H  << 8);
    SAVE_AND_DISABLE_GLOBAL_INTERRUPT(iStatus) ; 
    if (rval > 2) { //ok, trust that the Oflow byte is correctly incremented by ISR
      break;
    }
   RESTORE_GLOBAL_INTERRUPT(iStatus) ;  //renable global interrupt, allow to tick some more
  }
    while(1);
   //at this point, global interrupts are disabled, read overflow value
    rval  += ((UINT32) halMacTimerOflow) << 16;
   RESTORE_GLOBAL_INTERRUPT(iStatus) ;
   return (rval);
}


#ifdef LRWPAN_COMPILER_NO_RECURSION
UINT32 halISRGetMACTimer(void)
{
     UINT8   iStatus;
     UINT32  rval;
    

   do {
     rval = TMR0L;      //freeze timer 0
     rval  +=  ((UINT16) TMR0H  << 8);
    SAVE_AND_DISABLE_GLOBAL_INTERRUPT(iStatus) ; 
    if (rval > 2) { //ok, trust that the Oflow byte is correctly incremented by ISR
      break;
    }
   RESTORE_GLOBAL_INTERRUPT(iStatus) ;  //renable global interrupt, allow to tick some more
  }
    while(1);
   //at this point, global interrupts are disabled, read overflow value
    rval  += ((UINT32) halMacTimerOflow) << 16;
   RESTORE_GLOBAL_INTERRUPT(iStatus) ;
   return (rval);
}
#endif





UINT32 halMACTimerNowDelta(UINT32 x){
   UINT32 now;
   now = halGetMACTimer();
   now = (now - x);
   now = now & (UINT32) MACTIMER_MAX_VALUE;
   return(now);
}




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




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;

}

//this is a software delay loop, not meant for precision
void halWaitMs (UINT32 msecs){	UINT32	i, cnt;
 
      cnt = msecs;	do {		i = 20;		do {			halWaitUs(50);		} while(--i);	} while(--cnt);}



void halIdle(void) {
  CLRWDT(); //clear the watchdog timer	
}

//simple implementation that ignores the argument and that simply
//sleeps for the duration of the of the watchdog timer timeout
void halSleep(UINT32 msecs) {
   ENABLE_WDT() ;
   IDLEN = 0;
   SLEEP();
   NOP();
   DISABLE_WDT();
}



//ISR stuff



#ifdef MCC18
#pragma interruptlow HighISR
void HighISR(void)
#endif
#ifdef HI_TECH_C
void interrupt HighISR(void)
#endif
{
    //handle Timer0 interrupt first, mac timer overflow
   if (TMR0IF && TMR0IE) {
    TMR0IF=0;
     halMacTimerOflow++;
  }

#ifdef LRWPAN_ENABLE_SLOW_TIMER
  //CCP1IF use for period interrupt generation with TIMER3
  if (CCP1IF && CCP1IE) {
     CCP1IF = 0;
     CCPR1 = CCPR1 + T3PERIOD; //setup next interrupt
     evbIntCallback(); // call evb 
     //call the usrInterrupt
    usrSlowTimerInt();
   }
#endif

#ifdef  LRWPAN_ASYNC_INTIO
  if (RCIF && RCIE) {
     serio_rxHead++;
     if (serio_rxHead == LRWPAN_ASYNC_RX_BUFSIZE ) serio_rxHead = 0;
     serio_rxBuff[serio_rxHead] = RCREG;
  }

#endif

   
  evbRadioIntCallback();
  usrIntCallback();
   
}



//vector everything to high priority interrup
#if defined(MCC18)
#pragma code HighVector=0x08
void HighVector (void)
{
    _asm goto HighISR _endasm
}
#pragma code /* return to default code section */
#endif

#if defined(MCC18)
#pragma code lowhVector=0x18
void LowVector (void)
{
    _asm goto HighISR _endasm
}
#pragma code /* return to default code section */
#endif

⌨️ 快捷键说明

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