📄 halstack.c
字号:
//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;
DEBUG_STRING(DBG_INFO, "TX PKT Size: ");
DEBUG_UINT8(DBG_INFO,len);
DEBUG_STRING(DBG_INFO,"\n");
if (len > 127) {
//packet size is too large!
return(LRWPAN_STATUS_PHY_TX_PKT_TOO_BIG);
}
// 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;
//write the packet. Use 'flen' as the last two bytes are added automatically
//At some point, change this to use DMA
while (flen) {RFD = *frm; frm++; flen--;}
// 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);
}
doIEEE_backoff();
//Transmitting
ISTXONCCA; //TODO: replace this with IEEE Backoff
if(FSMSTATE > 30) //is TX active?
{
// Asserting the status flag and enabling ACK reception if expected.
phyTxStartCallBack();
res = LRWPAN_STATUS_SUCCESS;
RFIM |= IRQ_TXDONE; //enable IRQ_TXDONE interrupt
DEBUG_CHAR( DBG_TX,DBG_CHAR_TXSTART);
}
else
{
ISFLUSHTX; //empty buffer
res = LRWPAN_STATUS_PHY_CHANNEL_BUSY;
RFIM &= ~IRQ_TXDONE; //mask interrupt
DEBUG_CHAR( DBG_TX,DBG_CHAR_TXBUSY);
}
return(res);
}
#ifdef LRWPAN_ASYNC_INTIO
#if defined(IAR8051)
#pragma vector=URX0_VECTOR
#endif
#if defined(HI_TECH_C)
ROM_VECTOR(URX0_VECTOR,urx0_service_IRQ);
#endif
INTERRUPT_FUNC urx0_service_IRQ(void){
BYTE x,y;
serio_rxHead++;
if (serio_rxHead == LRWPAN_ASYNC_RX_BUFSIZE ) serio_rxHead = 0;
x = serio_rxHead; //use tmp variables because of Volatile decl
y = U0DBUF;
serio_rxBuff[x] = y;
}
#endif
//This timer interrupt is the periodic interrupt for
//evboard functions
#ifdef LRWPAN_ENABLE_SLOW_TIMER
#if defined(IAR8051)
#pragma vector=T2_VECTOR
#endif
#if defined(HI_TECH_C)
ROM_VECTOR(T2_VECTOR,t2_service_IRQ);
#endif
INTERRUPT_FUNC t2_service_IRQ(void){
UINT32 t;
INT_GLOBAL_ENABLE(INT_OFF);
INT_SETFLAG_T2(INT_CLR); //clear processor interrupt flag
//compute next compare value by reading current timer value, adding offset
t = 0x0FF & T2OF0;
t += (((UINT16)T2OF1)<<8);
t += (((UINT32) T2OF2 & 0x0F)<<16);
t += T2CMPVAL; //add offset
T2PEROF0 = t & 0xFF;
T2PEROF1 = (t >> 8) & 0xFF;
//enable overflow count compare interrupt
T2PEROF2 = ((t >> 16)&0x0F) | 0x20;
T2CNF = 0x03; //this clears the timer2 flags
evbIntCallback(); //Evaluation board callback
usrSlowTimerInt(); //user level interrupt callback
INT_GLOBAL_ENABLE(INT_ON);
}
#endif
//interrupt for RF error
//this interrupt is same priority as FIFOP interrupt,
//but is polled first, so will occur first.
#if defined(IAR8051)
#pragma vector=RFERR_VECTOR
#endif
#if defined(HI_TECH_C)
ROM_VECTOR(RFERR_VECTOR,rf_error_IRQ);
#endif
INTERRUPT_FUNC rf_error_IRQ(void)
{
INT_GLOBAL_ENABLE(INT_OFF);
// If Rx overflow occurs, the Rx FiFo is reset.
// The Rx DMA is reset and reception is started over.
if(FSMSTATE == 17)
{
DEBUG_CHAR( DBG_ITRACE,DBG_CHAR_TXBUSY);
STOP_RADIO();
ISFLUSHRX;
ISFLUSHRX;
ISRXON;
}
else if(FSMSTATE == 56)
{
DEBUG_CHAR( DBG_ITRACE,DBG_CHAR_RXOFLOW);
ISFLUSHTX;
}
INT_SETFLAG_RFERR(INT_CLR);
INT_GLOBAL_ENABLE(INT_ON);
}
//This interrupt used for both TX and RX
#if defined(IAR8051)
#pragma vector=RF_VECTOR
#endif
#if defined(HI_TECH_C)
ROM_VECTOR(RF_VECTOR,spp_rf_IRQ);
#endif
INTERRUPT_FUNC spp_rf_IRQ(void)
{
//used by spp_rf_IRQ
BYTE flen;
BYTE enabledAndActiveInterrupt;
BYTE *ptr, *rx_frame;
BYTE ack_bytes[5];
BYTE crc;
//define alternate names for readability in this function
#define fcflsb ack_bytes[0]
#define fcfmsb ack_bytes[1]
#define dstmode ack_bytes[2]
#define srcmode ack_bytes[3]
INT_GLOBAL_ENABLE(INT_OFF);
enabledAndActiveInterrupt = RFIF;
RFIF = 0x00; // Clear all radio interrupt flags
INT_SETFLAG_RF(INT_CLR); // Clear MCU interrupt flag
enabledAndActiveInterrupt &= RFIM;
// complete frame has arrived
if(enabledAndActiveInterrupt & IRQ_FIFOP)
{
DEBUG_CHAR( DBG_ITRACE,DBG_CHAR_RXRCV );
//if last packet has not been processed, we just
//read it but ignore it.
ptr = NULL; //temporary pointer
flen = RFD & 0x7f; //read the length
if (flen == LRWPAN_ACKFRAME_LENGTH) {
//this should be an ACK.
//read the packet, do not allocate space for it
DEBUG_CHAR( DBG_ITRACE,DBG_CHAR_ACKPKT );
ack_bytes[0]= flen;
ack_bytes[1] = RFD; //LSB Frame Control Field
ack_bytes[2] = RFD; //MSB Frame Control Field
ack_bytes[3] = RFD; //dsn
ack_bytes[4] = RFD; //RSSI
crc = RFD;
//check CRC
if (crc & 0x80){
// CRC ok, perform callback if this is an ACK
macRxCallback(ack_bytes, ack_bytes[4]);
}
}else {
//not an ack packet, lets do some more early rejection
// that the CC2430 seems to not do that we want to do.
//read the fcflsb, fcfmsb
fcflsb = RFD;
fcfmsb = RFD;
if (!local_radio_flags.bits.listen_mode) {
//only reject if not in listen mode
//get the src, dst addressing modes
srcmode = LRWPAN_GET_SRC_ADDR(fcfmsb);
dstmode = LRWPAN_GET_DST_ADDR(fcfmsb);
if ((srcmode == LRWPAN_ADDRMODE_NOADDR) && (dstmode == LRWPAN_ADDRMODE_NOADDR)) {
//reject this packet, no addressing info
goto do_rxflush;
}
}
if (!macRxBuffFull()) {
//MAC TX buffer has room
//allocate new memory space
//read the length
rx_frame = MemAlloc(flen+1);
ptr = rx_frame;
} else {
//MAC RX buffer is full
DEBUG_CHAR( DBG_ITRACE,DBG_CHAR_MACFULL );
}
// at this point, if ptr is null, then either
// the MAC RX buffer is full or there is no
// free memory for the new frame, or the packet is
// going to be rejected because of addressing info.
// In these cases, we need to
// throw the RX packet away
if (ptr == NULL) {
//just flush the bytes
goto do_rxflush;
}else {
//save packet, including the length
*ptr = flen; ptr++;
//save the fcflsb, fcfmsb bytes
*ptr = fcflsb; ptr++; flen--;
*ptr = fcfmsb; ptr++; flen--;
//get the rest of the bytes
while (flen) { *ptr = RFD; flen--; ptr++; }
//do RX callback
//check the CRC
if (*(ptr-1) & 0x80) {
//CRC good
//change the RSSI byte from 2's complement to unsigned number
*(ptr-2) = *(ptr-2) + 0x80;
phyRxCallback();
macRxCallback(rx_frame, *(ptr-2));
}else {
// CRC bad. Free the packet
MemFree(rx_frame);
}
}
}
//flush any remaining bytes
do_rxflush:
ISFLUSHRX;
ISFLUSHRX;
//don't know why, but the RF flags have to be cleared AFTER a read is done.
RFIF = 0x00;
INT_SETFLAG_RF(INT_CLR); // Clear MCU interrupt flag
//don't know why, but the interrupt mask has to be set again here for some reason.
//the processor receives packets, but does not generate an interrupt
RFIM |= IRQ_FIFOP;
}//end receive interrupt (FIFOP)
// Transmission of a packet is finished. Enabling reception of ACK if required.
if(enabledAndActiveInterrupt & IRQ_TXDONE)
{
//Finished TX, do call back
DEBUG_CHAR( DBG_ITRACE,DBG_CHAR_TXFIN );
phyTxEndCallBack();
macTxCallback();
// Clearing the tx done interrupt enable
RFIM &= ~IRQ_TXDONE;
}
usrIntCallback();
INT_GLOBAL_ENABLE(INT_ON);
#undef fcflsb
#undef fcfmsb
#undef dstmode
#undef srcmode
}
//software delay, waits is in milliseconds
void halWait(BYTE wait){
UINT32 largeWait;
if(wait == 0)
{return;}
largeWait = ((UINT16) (wait << 7));
largeWait += 114*wait;
largeWait = (largeWait >> CLKSPD);
while(largeWait--);
return;
}
void halWaitMs(const UINT32 msecs){
UINT32 towait;
towait = msecs;
while (towait > 100) {
halWait(100);
towait -= 100;
}
halWait(towait);
}
void halShutdown(void) {
//disable some interrupts
#ifdef LRWPAN_ENABLE_SLOW_TIMER
INT_ENABLE_T2(INT_OFF);
#endif
//disable RADIO interrupts
//Radio RF interrupt
INT_ENABLE_RF(INT_OFF);
//enable RX RFERR interrupt on processor
INT_ENABLE_RFERR(INT_OFF);
//shutoff the analog power to the radio
RFPWR = RFPWR | (1<<3); //RFPWR.RREG_RADIO_PD = 1;
}
void halWarmstart(void) {
UINT32 myticks;
//re-enable the timer interrupt
#ifdef LRWPAN_ENABLE_SLOW_TIMER
INT_ENABLE_T2(INT_ON);
#endif
//turn on the radio again
RFPWR = RFPWR & ~(1<<3); //RFPWR.RREG_RADIO_PD = 0;
//wait for power to stabilize
myticks = halGetMACTimer();
while (halMACTimerNowDelta(myticks) < MSECS_TO_MACTICKS(10)) {
//check the power up bit, max time is supposed to be 2 ms
if (!(RFPWR & ~(1<<4))) break;
}
}
//this is provided as an example
//will go into power mode 1, and use the sleep
//timer to wake up.
//Caution: Use of power down mode 2 caused erratic
//results after power up, I am not sure if was due
//to parts of RAM not retaining their value or what.
void halSleep(UINT32 msecs) {
UINT32 t;
UINT32 delta;
BOOL gie_status;
SAVE_AND_DISABLE_GLOBAL_INTERRUPT(gie_status);
//read the sleep timer
delta = (32768 * msecs)/1000;
t = 0xFF & ST0;
t += (((UINT16)ST1)<<8);
t += (((UINT32) ST2 & 0xFF)<<16);
//compute the compare value
t = (t + delta)&0x00FFFFFF;
//write the new sleep timer value
ST2 = (t >> 16)&0xFF;
ST1 = (t >> 8)&0xFF;
ST0 = t & 0xFF;
//clear the sleep flag, enable the interrupt
IRCON = IRCON & 0x7F; //clear the sleep flag IRCON.STIF = 0;
IEN0 = IEN0 | (1<<5); //enable the interrupt IEN0.STIE = 1;
ENABLE_GLOBAL_INTERRUPT(); //interrupts must be enabled to wakeup!
//configure the power mode and sleep
//SET_POWER_MODE(POWER_MODE_2);
SET_POWER_MODE(POWER_MODE_1);
//wake up!
//disable sleep interrupt
DISABLE_GLOBAL_INTERRUPT();
IEN0 = IEN0 & ~(1<<5); // IEN0.STIE = 0;
//wait for everything to power back up
while(!XOSC_STABLE); \
asm("NOP");
RESTORE_GLOBAL_INTERRUPT(gie_status);
};
INT16 halGetAdcValue(){
INT16 value;
value = ((INT16)ADCH) << 8;
value |= (INT16)ADCL;
return value;
}
//functions used by EVboard.
//-----------------------------------------------------------------------------
// See hal.h for a description of this function.
//-----------------------------------------------------------------------------
INT16 halAdcSampleSingle(BYTE reference, BYTE resolution, UINT8 input) {
BYTE volatile temp;
INT16 value;
//reading out any old conversion value
temp = ADCH;
temp = ADCL;
ADC_ENABLE_CHANNEL(input);
ADC_STOP();
ADC_SINGLE_CONVERSION(reference | resolution | input);
while (!ADC_SAMPLE_READY());
ADC_DISABLE_CHANNEL(input);
value = (((INT16)ADCH) << 8);
value |= ADCL;
resolution >>= 3;
return value >> (8 - resolution);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -