📄 halstack.c
字号:
/*
* "Copyright (c) 2006 Robert B. Reese ("AUTHOR")"
* All rights reserved.
* (R. Reese, reese@ece.msstate.edu, Mississippi State University)
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice, the following
* two paragraphs and the author appear in all copies of this software.
*
* IN NO EVENT SHALL THE "AUTHOR" BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE "AUTHOR"
* HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE "AUTHOR" SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE "AUTHOR" HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
*
* Please maintain this header in its entirety when copying/modifying
* these files.
*
* Files in this software distribution may have different usage
* permissions, see the header in each file. Some files have NO permission
* headers since parts of the original sources in these files
* came from vendor sources with no usage restrictions.
*
*/
/*
V0.1 Initial Release 10/July/2006 RBR
*/
#include <stdio.h>
#include <string.h>
#include <stdio.h>
#include <memory.h>
#include <windows.h>
#include <string.h>
#include <process.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"
BOOL block_radio_rx; //set by EVB to block radio TX
static RADIO_FLAGS local_radio_flags;
static void InitSharedMemory(void);
static LARGE_INTEGER lpFrequency;
static UINT32 tics_per_second;
static UINT16 radio_panid;
static SADDR radio_saddr;
static BYTE current_channel; //channels 11 to 16
static TCHAR szName[]=TEXT("RadioSharedMemoryObject"); // name for shared memory
static TCHAR mutexName[]=TEXT("RADIOMUTEX123"); //name for mutex that controls shared memory
#define PKTBUF_SIZE (sizeof(UINT32)+1+128)
#define NUMBER_OF_CHANNELS 16
#define SHARED_MEM_HDR (3*sizeof(UINT32))
#define SHARED_MEM_SIZE ((NUMBER_OF_CHANNELS*PKTBUF_SIZE)+SHARED_MEM_HDR )
//The shared memory header contains the following:
//UINT32 one-bit flag to indicate TX in progress
//UINT32 the global message ID
//UINT32 start tick of the TX, used for collision detection
//shared memory contains space for 16 channels
//Each channel is PKTBUF_SIZE, format of each pktbuf is:
//UINT32 pid: BYTE msgid: BYTE pktlen: PKT
static BYTE pktbuf[PKTBUF_SIZE];
static HANDLE hMapFile = NULL; //shared memory file handle
static BYTE *pSharedMem; //pointer to shared memory
static HANDLE hMutex = NULL; //pointer to the mutex used to coordinate access to shared memory
//variables used by message passing in shared memory
static BYTE tx_msgid = 1; //msg id of last message written to shared memory
static int last_rx_pid;
static BYTE last_rx_msgid;
static UINT32 mypid;
#define MIN_MSG_DURATION 1 //minimum amount of time a msg will be free of collision, in MILLISECONDS!!!
#define RANDOM_BACKOFF_INTERVAL 4 //will backoff 0 to RANDOM_BACKOFF_INTERVAL msecs on collision
#define MAX_BACKOFFS 3
static UINT32 global_msg_id; //incremented each time ANY node sends a message
static UINT32 last_global_msg_id;
//console handles
HANDLE hStdout, hStdin;
typedef enum _RADIO_STATE_ENUM {
RADIO_STATE_OFF,
RADIO_STATE_ON
}RADIO_STATE_ENUM;
RADIO_STATE_ENUM radio_state;
//shared memory used to emulate radio channel
//the coordinator node creates this memory
void InitSharedMemory(void){
mypid = (UINT32) _getpid(); //used in shared memory
last_global_msg_id = 0;
//Create shared memory if not created yet
if (hMapFile == NULL) {
#ifdef LRWPAN_COORDINATOR
//create the shared memory segment
DEBUG_STRING(DBG_INFO,"In InitSharedMemory(), Coordinator creating shared memory\n");
hMapFile = CreateFileMapping(
INVALID_HANDLE_VALUE, // use paging file
NULL, // default security
PAGE_READWRITE, // read/write access
0, // max. object size
SHARED_MEM_SIZE, // buffer size
szName); // name of mapping object
if (hMapFile == NULL || hMapFile == INVALID_HANDLE_VALUE)
{
printf("Could not create file mapping object (%d).\n",
GetLastError());
return;
}
DEBUG_STRING(DBG_INFO,"Created shared memory segment\n");
#else
//other nodes try to connect to this
DEBUG_STRING(DBG_INFO,"In InitSharedMemory(), Router/RFD connecting to shared memory\n");
hMapFile = OpenFileMapping(
FILE_MAP_ALL_ACCESS, // read/write access
FALSE, // do not inherit the name
szName); // name of mapping object
if (hMapFile == NULL)
{
printf("Could not open file mapping object (%d).\n",
GetLastError());
return;
}
#endif
}
pSharedMem = (BYTE *) MapViewOfFile(hMapFile, // handle to map object
FILE_MAP_ALL_ACCESS, // read/write permission
0,
0,
SHARED_MEM_SIZE);
if (pSharedMem == NULL)
{
printf("Could not map view of file (%d).\n",
GetLastError());
return;
}
//now initialize the shared memory
#ifdef LRWPAN_COORDINATOR
//initialize to zero
memset(pSharedMem,0,SHARED_MEM_SIZE);
#endif
if (hMutex == NULL) {
//create the mutex
hMutex = CreateMutex(NULL, FALSE,mutexName);
if(!hMutex) {
printf("Mutex creation failed, exiting.\n");
GetLastError();
}
DEBUG_STRING(DBG_INFO,"Mutex created\n");
}
}
//parse the header, and see if we should reject this packet in the
//same way as the CC2430 does.
static BOOL util_accept_packet(BYTE *ptr) {
BYTE i,fcflsb, fcfmsb,plen;
BYTE srcmode, dstmode;
BYTE addr[8];
BYTE len;
UINT16 destPANID, srcPANID;
SADDR srcSADDR,dstSADDR;
BYTE srcLADDR[8],dstLADDR[8];
if (block_radio_rx) return FALSE; //reject all packets.
srcSADDR = 0xFFFE;
dstSADDR = 0xFFFE;
destPANID = 0x0000;
srcPANID = 0x0000;
memset(&srcLADDR[0],0,8);
memset(&dstLADDR[0],0,8);
plen = *ptr;ptr++;
fcflsb = *ptr;ptr++;
fcfmsb = *ptr;ptr++;
//skip dsn
ptr++;
if (LRWPAN_IS_ACK(fcflsb)) return TRUE;
dstmode = LRWPAN_GET_DST_ADDR(fcfmsb);
srcmode = LRWPAN_GET_SRC_ADDR(fcfmsb);
//do address checking
if (dstmode != LRWPAN_ADDRMODE_NOADDR){
addr[0] = *ptr; ptr++;
addr[1] = *ptr; ptr++;
destPANID = ((UINT16)addr[1]) << 8;
destPANID = destPANID + addr[0];
//see if we should reject
if ((destPANID != radio_panid) && (destPANID != 0xFFFF)) {
//reject this packet as it does not match our PANID and is not the broadcast PAN
return (FALSE);
}
}
if (dstmode == LRWPAN_ADDRMODE_SADDR || dstmode == LRWPAN_ADDRMODE_LADDR) {
if (dstmode == LRWPAN_ADDRMODE_SADDR) {
addr[0] = *ptr; ptr++;
addr[1] = *ptr; ptr++;
dstSADDR = ((UINT16)addr[1]) << 8;
dstSADDR = dstSADDR + addr[0];
if ((dstSADDR != radio_saddr) && (dstSADDR != 0xFFFF)) {
//reject this packet as it does not match our SADDR and is not the broadcast PAN
return(FALSE);
}
} else {
memcpy(dstLADDR,ptr,8);
halGetProcessorIEEEAddress(&addr[0]);
//compare dst address to our address
for(i=0;i<8;i++) {
if (dstLADDR[i] != addr[i]) {
//reject, does not match
return(FALSE);
}
}
ptr = ptr + 8;
}
}
if ( !LRWPAN_GET_INTRAPAN(fcflsb) &&
srcmode != LRWPAN_ADDRMODE_NOADDR
) {
//get SRC PANID
addr[0] = *ptr; ptr++;
addr[1] = *ptr; ptr++;
srcPANID = ((UINT16)addr[1]) << 8;
srcPANID = srcPANID + addr[0];
//unusual to have SRC PANID
if (LRWPAN_IS_BCN(fcflsb)) {
if ((srcPANID != radio_panid) && (srcPANID != 0xFFFF)){
//reject
return(FALSE);
}
} else {
//data or MAC frame with srcPANID
if (dstmode == LRWPAN_ADDRMODE_NOADDR) {
//only src addressing mode present
if (!((srcPANID == radio_panid) && local_radio_flags.bits.pan_coordinator))
return FALSE;
}
}
}
return(TRUE);
}
//utility function
//format shmem_hdr
static void write_shmem_hdr(BYTE *ptr, UINT32 pid, BYTE msgid, BYTE len) {
*(ptr+0) = (BYTE) (pid);
*(ptr+1) = (BYTE) (pid>>8);
*(ptr+2) = (BYTE) (pid>>16);
*(ptr+3) = (BYTE) (pid>>24);
*(ptr+4) = msgid;
*(ptr+5) = len;
}
//when doing RF TX, these supply rssi, crc
static BYTE util_get_rssi(void){
#ifdef LRWPAN_RSSI
return(LRWPAN_RSSI); //use this to simulate distance
#else
return( 0x7F); //about midrange
#endif
}
static BYTE util_get_CRC(void){
return( 0x80);
}
//transmit the packet
/*
Simulating RF transmission with
Writing a RF packet to shared memory
To receive:
a. Look at first UINT32 in shared memory header. If this is
a '1', then a transmission is in progress, suspend, keep trying
until it becomes a '0'.
b. Look at the 2nd UINT32 in the shared memory header. This is
the global MSG id. If this is not different from last time, exit.
c. Since the global_msg_id is different, then grab the mutex.
d. Read the data
e. Release
To Transmit:
a. Check for collision before grabbing mutex by reading 3rd UINT32 and seeing
if collision interval has expired. If not, then do random backoff, and
then try again. Once backoff succeeds, grab the mutex.
a. Grab mutex
b. Set the first UINT32 word to '1' indicating a transmit in progress.
c. increment msgid, copy sender_pid, msgid
to header, copy packet
d. read the global MSG id, increment, write it back.
e. Clear the transmit in progress.
c. Release mutex
*/
//rx flag is true if we want to check for reception
//if rx_flag is false, then we do transmit and do not do reception
void DoSharedMemTxRx(BOOL rx_flag, BYTE *pload,BYTE plen){
DWORD rc;
UINT32 sender_pid;
BYTE sender_msgid;
BYTE pktlen;
BYTE len;
BYTE *pBuf;
BYTE *newpkt;
BYTE fcflsb,fcfmsb,dsn;
UINT32 *hdr;
UINT32 my_timer;
UINT8 backoffs;
if (radio_state != RADIO_STATE_ON) {
return;
}
hdr = (UINT32 *) &pSharedMem[0];
if (rx_flag) {
while ((volatile UINT32) *hdr) { Sleep(0);} //wait until the TX in progress flag is cleared.
//read the new id
if ((volatile UINT32) *(hdr+1) == last_global_msg_id) return; //nothing to do
}else {
//check for collision before TX
backoffs = 0;
do {
while ((volatile UINT32)*hdr) { Sleep(0);} //wait until the TX in progress flag is cleared.
if (halMACTimerNowDelta((volatile UINT32)*(hdr+2)) > MSECS_TO_MACTICKS(MIN_MSG_DURATION)) break; //can transmit
//have a collision, need to wait.
backoffs++;
halSleep(MIN_MSG_DURATION + (halGetRandomByte()%RANDOM_BACKOFF_INTERVAL));
}while(backoffs < MAX_BACKOFFS);
}
//if reach here, either there is a new message for RX or we are TXing.
rc = WaitForSingleObject(hMutex,INFINITE);
switch(rc) {
case WAIT_OBJECT_0:
break;
case WAIT_FAILED:
case WAIT_ABANDONED:
case WAIT_TIMEOUT:
printf("Radio shared mem Wait failed!\n");
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -