📄 halstack.c
字号:
/*
V0.1 Initial Release 10/July/2006 RBR
*/
#include "hal.h"
#include "halstack.h"
#include "console.h"
#include "ieee_lrwpan_defs.h"
#include "phy.h"
#include "mac.h"
extern BYTE UART0rcvBuf[200];
extern BYTE datalen;
RADIO_FLAGS local_radio_flags;
//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();
URX0IE=INT_ON;
U0CSR |=UART_ENABLE_RECEIVE;
UTX0IF = 1;
}
//get a character from serial port
char halGetch(void){
char c;
// Turning on reception
U0CSR |= UART_ENABLE_RECEIVE;
while (!URX0IF);
c = U0DBUF;
URX0IF = FALSE;
return c;
}
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 = (BYTE) (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_UNION t;
BOOL gie_status;
SAVE_AND_DISABLE_GLOBAL_INTERRUPT(gie_status);
t.bytes[UINT32_LOWORD_LSB] = T2OF0;
t.bytes[UINT32_LOWORD_MSB] = T2OF1;
t.bytes[UINT32_HIWORD_LSB] = T2OF2 & 0x0F;
t.bytes[UINT32_HIWORD_MSB] = 0;
RESTORE_GLOBAL_INTERRUPT(gie_status);
return (t.val);
}
//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;
}
//set the radio frequency
LRWPAN_STATUS_ENUM halSetRadioIEEEFrequency(PHY_FREQ_ENUM frequency, BYTE channel)
{
UINT16 afreq;
//DEBUG_STRING(DBG_TX,"halSetRadioIEEEFrequency() -set channel:");
//DEBUG_UINT8(DBG_TX,channel); DEBUG_STRING(DBG_TX,"\n");
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));
}
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] = *(unsigned char __code *)(IEEE_ADDRESS_ARRAY+0);
buf[6] = *(unsigned char __code *)(IEEE_ADDRESS_ARRAY+1);
buf[5] = *(unsigned char __code *)(IEEE_ADDRESS_ARRAY+2);
buf[4] = *(unsigned char __code *)(IEEE_ADDRESS_ARRAY+3);
buf[3] = *(unsigned char __code *)(IEEE_ADDRESS_ARRAY+4);
buf[2] = *(unsigned char __code *)(IEEE_ADDRESS_ARRAY+5);
buf[1] = *(unsigned char __code *)(IEEE_ADDRESS_ARRAY+6);
buf[0] = *(unsigned char __code *)(IEEE_ADDRESS_ARRAY+7);
#if (CC2430_FLASH_SIZE == 128)
//resore old bank settings
MEMCTR = bank;
#endif
}
void halGetProcessorIEEEAddress_ASC(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[0] = *(unsigned char __code *)(IEEE_ADDRESS_ARRAY+0);
buf[1] = *(unsigned char __code *)(IEEE_ADDRESS_ARRAY+1);
buf[2] = *(unsigned char __code *)(IEEE_ADDRESS_ARRAY+2);
buf[3] = *(unsigned char __code *)(IEEE_ADDRESS_ARRAY+3);
buf[4] = *(unsigned char __code *)(IEEE_ADDRESS_ARRAY+4);
buf[5] = *(unsigned char __code *)(IEEE_ADDRESS_ARRAY+5);
buf[6] = *(unsigned char __code *)(IEEE_ADDRESS_ARRAY+6);
buf[7] = *(unsigned char __code *)(IEEE_ADDRESS_ARRAY+7);
#if (CC2430_FLASH_SIZE == 128)
//resore old bank settings
MEMCTR = bank;
#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);
}
void halSetTxPower(BYTE val)
{
//val:0~7 ;0-min 7-max
BYTE VALTAB[]={0xE3,0xE7,0xEB,0xEF,0xF3,0xF7,0xFB,0xFF};
if(val>7)return;
TXCTRLL=VALTAB[val];
}
LRWPAN_STATUS_ENUM halInitRadio(PHY_FREQ_ENUM frequency, BYTE channel, RADIO_FLAGS radio_flags)
{
LRWPAN_STATUS_ENUM status;
//DEBUG_STRING(DBG_TX,"halInitRadio()\n");
// 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;
SACKPEND; //routers/
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,state;
LRWPAN_STATUS_ENUM res;
//if you print out the packet, this can cause timeouts on waits
//dbgPrintPacket(frm,flen+2);
//total length, does not include length byte itself
//last two bytes are the FCS bytes that are added automatically
len = flen + PACKET_FOOTER_SIZE;
// Clearing RF interrupt flags and enabling RF interrupts.
if(FSMSTATE == 6 && RXFIFOCNT > 0)
{
ISFLUSHRX;
ISFLUSHRX;
}
RFIF &= ~IRQ_TXDONE; //Clear the RF TXDONE flag
INT_SETFLAG_RF(INT_CLR); //Clear processor interrupt flag
//write packet length
RFD = len;
//DEBUG_STRING(DBG_TX,"halSendPacket()-len:");
//DEBUG_UINT8(DBG_TX,flen); DEBUG_STRING(DBG_TX," data:");
while (flen)
{
RFD = *frm;
//DEBUG_UINT8(DBG_TX,*frm); DEBUG_STRING(DBG_TX,",");
frm++;
flen--;
}
//DEBUG_STRING(DBG_TX,"\n");
// If the RSSI value is not valid, enable receiver
if(RSSIL == 0x80)
{
ISRXON;
// Turning on Rx and waiting 320u-sec to make the RSSI value become valid.
halWait(1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -