📄 halstack.c
字号:
/*
V0.1 Initial Release 10/July/2006 RBR
Port over Tmote 23/December/2006 RS
*/
#include "lrwpan_config.h"
#include "hal.h"
#include "halStack.h"
#include "clock_hal.h"
#include "console.h"
#include "debug.h"
#include "ieee_lrwpan_defs.h"
#include "memalloc.h"
#include <stdio.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(); //set uart
halInitMACTimer(); //set timer
}
//Uart init()...USART1 x USART0 for SPI
//we are going to initialize the console to single character
//input, and no echo to emulate the micro
void halInitUart(void) {
/* RS232 */
P3DIR &= ~0x80; /* Select P37 for input (UART1RX) */
P3DIR |= 0x40; /* Select P36 for output (UART1TX) */
P3SEL |= 0xC0; /* Select P36,P37 for UART1{TX,RX} */
UCTL1 = SWRST | CHAR; /* 8-bit character, UART mode */
/* U1RCTL &= ~URXEIE; /\* even erroneous characters trigger interrupts *\/ */
UTCTL1 = SSEL1; //SMCLK as source
//halSetBaud(LRWPAN_DEFAULT_BAUDRATE);
UBR01 = SMCLK_BAUD_57_6k_UBR0;
UBR11 = SMCLK_BAUD_57_6k_UBR1;
UMCTL1 = SMCLK_BAUD_57_6k_UMCTL;
ME2 &= ~USPIE1; /* USART1 SPI module disable */
ME2 |= (UTXE1 | URXE1); /* Enable USART1 TXD/RXD */
UCTL1 &= ~SWRST;
/* XXX Clear pending interrupts before enable!!! */
IE2 |= URXIE1; /* Enable USART1 RX interrupt */
#ifdef LRWPAN_ASYNC_INTIO
serio_rxHead = 0;
serio_rxTail = 0;
#endif
}
//TMote Sky: support just for ASYNC
#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);
}
#endif
//write a character to serial port
//Uses UART initialized by halInitUart
void halPutch(char c){
/* Loop until the transmission buffer is available. */
while ((IFG2 & UTXIFG1) == 0);
/* Transmit the data. */
TXBUF1 = c;
}
void halRawPut(char c){
/* Loop until the transmission buffer is available. */
while ((IFG2 & UTXIFG1) == 0);
/* Transmit the data. */
TXBUF1 = c;
}
//MAC Init()
//defined such that timerA has a period of 1 symbol, or 16 us
//FOSC assumed to be some multiple of 4 MHZ
//Tmote Sky MCLK running at 4MHz
#define SYMBOL_FREQ 62500 //equals to symbols period of 16us
/*
* Incremented after overflow of TimerA
* TimerA...SMCLK/8...16us
* interrupt after 2^16*16us=1s
*/
UINT16 halMacTimerOflow;
//TimerA used as MAC timer
//17012007...go for HW tick every 16us and check overflow for increment halMacTimerOflow
//This greatly release the uC
void halInitMACTimer(void) {
/* DCO calibration */
clock_hal_init();
//For testing
//RTC TimerB ... 0.5Hz...2s
//Overflow...ACLK...Continous
//TBCTL = TBSSEL_1 + MC_2 + TBIE;
//Don't need this...I go with overflow
/* Initialize ccr1 to create the X us interval. */
/* CCR1 interrupt enabled, interrupt occurs when timer equals CCR1. */
//TACCTL1 = CCIE;
/* Interrupt after X us. */
//TACCR1 = INTERVAL;
//Older setting
//TACTL = TBSSEL_2 + MC_2 + TAIE;
/* start ticking */
//Overflow...SMCLK/8=16us...Continous
TACTL = TBSSEL_2 + ID_3 + MC_2 + TAIE;
/* Keeping track of overflow */
halMacTimerOflow=0;
}
void halShutdown(void){
//disable timer interrupts so that they don't wake us up
//Old approach
// TACCR1 = 0;
TACTL &= ~TAIE;
halDisableRadio();
}
void halWarmstart(void){
//enable timer interrupt
//Old approach
// TACCTL1 = CCIE;
TACTL |= TAIE;
}
//only works as long as SYMBOLS_PER_MAC_TICK is not less than 1
//TMote Sky...I use HW tick as indicator of 16us...SYMBOLS_PER_MAC_TICK=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!
//New: TMote Sky...I use HW tick in TAR as indicator of 16us
UINT32 halGetMACTimer(void)
{
UINT8 iStatus;
UINT32 rval;
do {
//Old
//rval = halMacTimerOflow; //check if we're running
//New 17012007
rval = (UINT16) TAR;
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
//Old
//rval = halMacTimerOflow;
//New 17012007
rval += ((UINT32) halMacTimerOflow) << 16;
RESTORE_GLOBAL_INTERRUPT(iStatus);
return (rval);
}
#ifdef LRWPAN_COMPILER_NO_RECURSION
UINT32 halISRGetMACTimer(void)
{
UINT8 iStatus;
UINT32 rval;
do {
//Old
//rval = halMacTimerOflow; //check if we're running
//New 17012007
rval = (UINT16) TAR;
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
//Old
//rval = halMacTimerOflow;
//New 17012007
rval += ((UINT32) halMacTimerOflow) << 16;
RESTORE_GLOBAL_INTERRUPT(iStatus);
return (rval);
}
#endif
UINT32 halMACTimerNowDelta(UINT32 x){
UINT32 now;
now = halGetMACTimer();
now = (now - x);
//TimerA is 16bit + I use UINT16 halMacTimerOflow = 32 bits
//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;
}
//ms precision
void halWaitMs(UINT32 msecs){ UINT16 i, j, cnt;
cnt = msecs; do { i = 20; do {
j = TAR;
while((TAR - j) <= 2); } while(--i); } while(--cnt);}
//us precision
void halWaitUs(UINT16 usecs)
{
UINT16 i;
if (usecs < 500)
for (i=2; i < usecs; i++) {
asm volatile("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
::);
}
else
for (i=0; i < usecs; i++) {
asm volatile("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
::);
}
}
//just for demo
void halIdle(void) {
NOP();
//TODO: it could go to sleep mode over here???
}
//sleeps for the duration of the of the watchdog timer timeout
//just for demo
void halSleep(UINT32 msecs) {
//WDT_ADLY_1000;
//WDT_ADLY_250;
//WDT_ADLY_16;
//WDT_ADLY_1_9;
WDTCTL = WDT_ADLY_1000; // WDT 1s, ACLK, interval timer
IE1 |= WDTIE; // Enable WDT interrupt
_BIS_SR(LPM1_bits + GIE); // Enter LPM1 w/interrupt
}
//ISR stuff
//UART receive
interrupt(UART1RX_VECTOR) uart1_intr(void) {
/* Check status register for receive errors. */
if (URCTL1 & RXERR) {
volatile unsigned dummy;
dummy = RXBUF1; /* Clear error flags by forcing a dummy read. */
} else {
#ifdef LRWPAN_ASYNC_INTIO
serio_rxHead++;
if (serio_rxHead == LRWPAN_ASYNC_RX_BUFSIZE ) serio_rxHead = 0;
serio_rxBuff[serio_rxHead] = RXBUF1;
#endif
}
}
// MAC Timer
// Timer_A3 Interrupt Vector Handler
interrupt(TIMERA1_VECTOR) timera1 (void) {
/*
* 17012007
* New approach...look for overflow
*
*/
switch(TAIV) {
case 0x02: break; // CCR1 not used
case 0x04: break; // CCR2 not used
case 0x0A: { halMacTimerOflow++; break; } // overflow
}
//Callback for receiving packets
//Let's see if TMote can handle this...not sure about it
//Trying to use interrupt priority...see PORT1_VECTOR below
//evbRadioIntCallback();
/* not yet implemented
#ifdef LRWPAN_ENABLE_SLOW_TIMER
evbIntCallback(); // call evb
usrSlowTimerInt(); // call the usrInterrupt
#endif
*/
}
interrupt(PORT1_VECTOR) fifop (void) {
//receiving packets
//led_blue_toggle();
evbRadioIntCallback();
//TODO: it could go to sleep mode over here???
}
// Timer_B7 Interrupt Vector (TBIV) handler
interrupt(TIMERB1_VECTOR) timerb1 (void) {
switch( TBIV )
{
case 0x02: break; // CCR1 not used
case 0x04: break; // CCR2 not used
case 0x0E: { //conPrintUINT32(halMacTimerOflow);
//conPrintROMString("\n");
break;
} // overflow
}
}
// Watchdog Timer interrupt service routine
interrupt(WDT_VECTOR) watchdog_timer(void) {
//exit from sleep mode
IE1 &= ~WDTIE;
DISABLE_WDT();
LPM1_EXIT;
//led_red_toggle();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -