Radio and 802.15.4 MAC code for the Atmel AVR Raven board
This commit is contained in:
parent
2e8264010b
commit
db7d9bb131
16 changed files with 4957 additions and 0 deletions
337
cpu/avr/radio/rf230/frame.c
Normal file
337
cpu/avr/radio/rf230/frame.c
Normal file
|
@ -0,0 +1,337 @@
|
|||
/*
|
||||
*
|
||||
* Copyright (c) 2008, Swedish Institute of Computer Science
|
||||
* All rights reserved.
|
||||
*
|
||||
* Additional fixes for AVR contributed by:
|
||||
*
|
||||
* Colin O'Flynn coflynn@newae.com
|
||||
* Eric Gnoske egnoske@gmail.com
|
||||
* Blake Leverett bleverett@gmail.com
|
||||
* Mike Vidales mavida404@gmail.com
|
||||
* Kevin Brown kbrown3@uccs.edu
|
||||
* Nate Bohlmann nate@elfwerks.com
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of the copyright holders nor the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $Id: frame.c,v 1.1 2008/10/14 09:43:40 adamdunkels Exp $
|
||||
*/
|
||||
/*
|
||||
* \brief This file is where the main functions that relate to frame
|
||||
* manipulation will reside.
|
||||
*/
|
||||
/**
|
||||
* \addtogroup wireless
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* \defgroup frame RF230 Frame handling
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
* \brief 802.15.4 frame creation and parsing functions
|
||||
*
|
||||
* This file converts to and from a structure to a packed 802.15.4
|
||||
* frame.
|
||||
*/
|
||||
|
||||
/* Includes */
|
||||
#if defined( __GNUC__ )
|
||||
#include <avr/io.h>
|
||||
#include <util/delay.h>
|
||||
#else /* IAR */
|
||||
#include <iom1284.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "at86rf230_registermap.h"
|
||||
#include "radio.h"
|
||||
#include "frame.h"
|
||||
//#include "mac_event.h"
|
||||
#include "mac.h"
|
||||
#include "process.h"
|
||||
#include "sicslowmac.h"
|
||||
|
||||
|
||||
|
||||
/* Macros & Defines */
|
||||
|
||||
/* Some version of radio chip need this set to 2, so define it in Makefile */
|
||||
#ifndef AUTO_CRC_PADDING
|
||||
#define AUTO_CRC_PADDING 0
|
||||
#endif
|
||||
|
||||
|
||||
/* Protoypes */
|
||||
|
||||
/* Globals */
|
||||
|
||||
/* Frame handling global variables. */
|
||||
//FRAME_t rx_frame; /**< Structure that holds received frames. */
|
||||
static uint8_t tx_frame_buffer[130];
|
||||
|
||||
/* Implementation */
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief Creates a frame for transmission over the air. This function is
|
||||
* meant to be called by a higher level function, that interfaces to a MAC.
|
||||
*
|
||||
* \param p Pointer to frame_create_params_t struct, which specifies the
|
||||
* frame to send.
|
||||
*
|
||||
* \param frame_result Pointer to frame_result_t struct, which will
|
||||
* receive the results of this function, a pointer to the frame
|
||||
* created, and the length of the frame.
|
||||
*
|
||||
* \return Nothing directly, though the frame_result structure will be filled
|
||||
* in with a pointer to the frame and the frame length.
|
||||
*/
|
||||
void
|
||||
frame_tx_create(frame_create_params_t *p,frame_result_t *frame_result)
|
||||
{
|
||||
field_length_t flen;
|
||||
uint8_t index=0;
|
||||
|
||||
/* init flen to zeros */
|
||||
memset(&flen, 0, sizeof(field_length_t));
|
||||
|
||||
/* Determine lengths of each field based on fcf and other args */
|
||||
if (p->fcf.destAddrMode){
|
||||
flen.dest_pid_len = 2;
|
||||
}
|
||||
if (p->fcf.srcAddrMode){
|
||||
flen.src_pid_len = 2;
|
||||
}
|
||||
/* Set PAN ID compression bit it src pan if matches dest pan id. */
|
||||
if(p->fcf.destAddrMode == p->fcf.srcAddrMode){
|
||||
p->fcf.panIdCompression = 1;
|
||||
}
|
||||
if (p->fcf.panIdCompression){
|
||||
/* compressed header, only do dest pid */
|
||||
flen.src_pid_len = 0;
|
||||
}
|
||||
/* determine address lengths */
|
||||
switch (p->fcf.destAddrMode){
|
||||
case 2: /* 16-bit address */
|
||||
flen.dest_addr_len = 2;
|
||||
break;
|
||||
case 3: /* 64-bit address */
|
||||
flen.dest_addr_len = 8;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch (p->fcf.srcAddrMode){
|
||||
case 2: /* 16-bit address */
|
||||
flen.src_addr_len = 2;
|
||||
break;
|
||||
case 3: /* 64-bit address */
|
||||
flen.src_addr_len = 8;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
/* Aux security header */
|
||||
if (p->fcf.securityEnabled){
|
||||
switch (p->aux_hdr.security_control.key_id_mode){
|
||||
case 0:
|
||||
flen.aux_sec_len = 5; /* minimum value */
|
||||
break;
|
||||
case 1:
|
||||
flen.aux_sec_len = 6;
|
||||
break;
|
||||
case 2:
|
||||
flen.aux_sec_len = 10;
|
||||
break;
|
||||
case 3:
|
||||
flen.aux_sec_len = 14;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* OK, now we have field lengths. Time to actually construct */
|
||||
/* the outgoing frame, and store it in tx_frame_buffer */
|
||||
*(uint16_t *)tx_frame_buffer = p->fcf.word_val; /* FCF */
|
||||
index = 2;
|
||||
tx_frame_buffer[index++] = p->seq; /* sequence number */
|
||||
/* Destination PAN ID */
|
||||
if (flen.dest_pid_len == 2){
|
||||
*(uint16_t *)&tx_frame_buffer[index] = p->dest_pid;
|
||||
index += 2;
|
||||
}
|
||||
/* Destination address */
|
||||
switch (flen.dest_addr_len){
|
||||
case 2: /* two-byte address */
|
||||
*(uint16_t *)&tx_frame_buffer[index] = p->dest_addr.addr16;
|
||||
index += 2;
|
||||
break;
|
||||
case 8: /* 8-byte address */
|
||||
*(uint64_t *)&tx_frame_buffer[index] = p->dest_addr.addr64;
|
||||
index += 8;
|
||||
break;
|
||||
case 0:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
/* Source PAN ID */
|
||||
if (flen.src_pid_len == 2){
|
||||
*(uint16_t *)&tx_frame_buffer[index] = p->src_pid;
|
||||
index += 2;
|
||||
}
|
||||
/* Source address */
|
||||
switch (flen.src_addr_len){
|
||||
case 2: /* two-byte address */
|
||||
*(uint16_t *)&tx_frame_buffer[index] = p->src_addr.addr16;
|
||||
index += 2;
|
||||
break;
|
||||
case 8: /* 8-byte address */
|
||||
*(uint64_t *)&tx_frame_buffer[index] = p->src_addr.addr64;
|
||||
index += 8;
|
||||
break;
|
||||
case 0:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
/* Aux header */
|
||||
if (flen.aux_sec_len){
|
||||
memcpy((char *)&tx_frame_buffer[index],
|
||||
(char *)&p->aux_hdr,
|
||||
flen.aux_sec_len);
|
||||
index += flen.aux_sec_len;
|
||||
}
|
||||
/* Frame payload */
|
||||
memcpy((char *)&tx_frame_buffer[index],
|
||||
(char *)p->payload,
|
||||
p->payload_len);
|
||||
index += p->payload_len;
|
||||
|
||||
/* return results */
|
||||
frame_result->length = index + AUTO_CRC_PADDING;
|
||||
frame_result->frame = tx_frame_buffer;
|
||||
return;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief Parses an input frame. Scans the input frame to find each
|
||||
* section, and stores the resulting addresses of each section in a
|
||||
* parsed_frame_t structure.
|
||||
*
|
||||
* \param rx_frame The input data from the radio chip.
|
||||
* \param pf The parsed_frame_t struct that stores a pointer to each
|
||||
* section of the frame payload.
|
||||
*/
|
||||
void rx_frame_parse(hal_rx_frame_t *rx_frame, parsed_frame_t *pf)
|
||||
{
|
||||
/* Pointer to start of AT86RF2xx frame */
|
||||
uint8_t *p = rx_frame->data;
|
||||
fcf_t *fcf = (fcf_t *)&rx_frame->data;
|
||||
static uint8_t frame_dropped = 0;
|
||||
|
||||
/* Uh-oh... please don't overwrite me! */
|
||||
if (pf->in_use) {
|
||||
|
||||
/* Only post this once when buffer is busy, otherwise you get many postings... */
|
||||
if (!frame_dropped) {
|
||||
event_object_t event;
|
||||
event.event = MAC_EVENT_DROPPED;
|
||||
event.data = NULL;
|
||||
mac_put_event(&event);
|
||||
process_post(&mac_process, event.event, event.data);
|
||||
}
|
||||
frame_dropped = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (fcf->frameType == ACKFRAME)
|
||||
return; /* Don't bother with ACK frames */
|
||||
|
||||
pf->fcf = (fcf_t *)p;
|
||||
pf->seqNum = p+2;
|
||||
p += 3; /* Skip first three bytes */
|
||||
/* Destination PID, if any */
|
||||
if (fcf->frameType != BEACONFRAME){ /* No destination addresses in Beacon frame */
|
||||
pf->dest_pid = (uint16_t *)p;
|
||||
p += 2;
|
||||
/* Destination address */
|
||||
pf->dest_addr = 0;
|
||||
if (fcf->destAddrMode == SHORTADDRMODE ||
|
||||
fcf->destAddrMode == LONGADDRMODE){
|
||||
pf->dest_addr = (addr_t *)p;
|
||||
/* Update pointer to account for possible missing addr field */
|
||||
if (fcf->destAddrMode == SHORTADDRMODE){
|
||||
p += 2;
|
||||
}
|
||||
if (fcf->destAddrMode == LONGADDRMODE){
|
||||
p += 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Source PANID */
|
||||
pf->src_pid = 0;
|
||||
if (!fcf->panIdCompression){
|
||||
pf->src_pid = (uint16_t *)p;
|
||||
p += 2;
|
||||
}
|
||||
/* Source address */
|
||||
pf->src_addr = (addr_t *)p;
|
||||
if (fcf->srcAddrMode == SHORTADDRMODE){
|
||||
p += 2;
|
||||
}
|
||||
if (fcf->srcAddrMode == LONGADDRMODE){
|
||||
p += 8;
|
||||
}
|
||||
/* aux security header, not yet implemented */
|
||||
pf->aux_sec_hdr = 0;
|
||||
/* payload length */
|
||||
pf->payload_length = rx_frame->length - (p - (uint8_t*)&rx_frame->data) - 2;
|
||||
/* payload */
|
||||
pf->payload = p;
|
||||
|
||||
pf->lqi = rx_frame->lqi;
|
||||
pf->fcs = rx_frame->crc;
|
||||
|
||||
/* pass frame to sicslowmac layer */
|
||||
event_object_t event;
|
||||
event.event = MAC_EVENT_RX;
|
||||
event.data = (uint8_t*)pf;
|
||||
pf->in_use = 1;
|
||||
mac_put_event(&event);
|
||||
process_poll(&mac_process);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
/** \} */
|
Loading…
Add table
Add a link
Reference in a new issue