Merge pull request #2012 from cetic/jn516-hw-mac
JN516x: Add support for hardware MAC
This commit is contained in:
commit
c5c1979d37
4 changed files with 190 additions and 32 deletions
|
@ -183,7 +183,7 @@ frame802154_has_panid(frame802154_fcf_t *fcf, int *has_src_pan_id, int *has_dest
|
|||
} else {
|
||||
/* No PAN ID in ACK */
|
||||
if(fcf->frame_type != FRAME802154_ACKFRAME) {
|
||||
if(!fcf->panid_compression && fcf->src_addr_mode & 3) {
|
||||
if(!fcf->panid_compression && (fcf->src_addr_mode & 3)) {
|
||||
/* If compressed, don't include source PAN ID */
|
||||
src_pan_id = 1;
|
||||
}
|
||||
|
@ -304,7 +304,7 @@ field_len(frame802154_t *p, field_length_t *flen)
|
|||
* up to the caller. */
|
||||
if(p->fcf.frame_version < FRAME802154_IEEE802154E_2012) {
|
||||
/* Set PAN ID compression bit if src pan id matches dest pan id. */
|
||||
if(p->fcf.dest_addr_mode & 3 && p->fcf.src_addr_mode & 3 &&
|
||||
if((p->fcf.dest_addr_mode & 3) && (p->fcf.src_addr_mode & 3) &&
|
||||
p->src_pid == p->dest_pid) {
|
||||
p->fcf.panid_compression = 1;
|
||||
} else {
|
||||
|
@ -362,6 +362,20 @@ frame802154_hdrlen(frame802154_t *p)
|
|||
return 2 + flen.seqno_len + flen.dest_pid_len + flen.dest_addr_len +
|
||||
flen.src_pid_len + flen.src_addr_len + flen.aux_sec_len;
|
||||
}
|
||||
void
|
||||
frame802154_create_fcf(frame802154_fcf_t *fcf, uint8_t *buf)
|
||||
{
|
||||
buf[0] = (fcf->frame_type & 7) |
|
||||
((fcf->security_enabled & 1) << 3) |
|
||||
((fcf->frame_pending & 1) << 4) |
|
||||
((fcf->ack_required & 1) << 5) |
|
||||
((fcf->panid_compression & 1) << 6);
|
||||
buf[1] = ((fcf->sequence_number_suppression & 1)) |
|
||||
((fcf->ie_list_present & 1)) << 1 |
|
||||
((fcf->dest_addr_mode & 3) << 2) |
|
||||
((fcf->frame_version & 3) << 4) |
|
||||
((fcf->src_addr_mode & 3) << 6);
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief Creates a frame for transmission over the air. This function is
|
||||
|
@ -388,17 +402,7 @@ frame802154_create(frame802154_t *p, uint8_t *buf)
|
|||
|
||||
/* OK, now we have field lengths. Time to actually construct */
|
||||
/* the outgoing frame, and store it in buf */
|
||||
buf[0] = (p->fcf.frame_type & 7) |
|
||||
((p->fcf.security_enabled & 1) << 3) |
|
||||
((p->fcf.frame_pending & 1) << 4) |
|
||||
((p->fcf.ack_required & 1) << 5) |
|
||||
((p->fcf.panid_compression & 1) << 6);
|
||||
buf[1] = ((p->fcf.sequence_number_suppression & 1)) |
|
||||
((p->fcf.ie_list_present & 1)) << 1 |
|
||||
((p->fcf.dest_addr_mode & 3) << 2) |
|
||||
((p->fcf.frame_version & 3) << 4) |
|
||||
((p->fcf.src_addr_mode & 3) << 6);
|
||||
|
||||
frame802154_create_fcf(&p->fcf, buf);
|
||||
pos = 2;
|
||||
|
||||
/* Sequence number */
|
||||
|
@ -460,6 +464,28 @@ frame802154_create(frame802154_t *p, uint8_t *buf)
|
|||
|
||||
return (int)pos;
|
||||
}
|
||||
|
||||
void
|
||||
frame802154_parse_fcf(uint8_t *data, frame802154_fcf_t *pfcf)
|
||||
{
|
||||
frame802154_fcf_t fcf;
|
||||
|
||||
/* decode the FCF */
|
||||
fcf.frame_type = data[0] & 7;
|
||||
fcf.security_enabled = (data[0] >> 3) & 1;
|
||||
fcf.frame_pending = (data[0] >> 4) & 1;
|
||||
fcf.ack_required = (data[0] >> 5) & 1;
|
||||
fcf.panid_compression = (data[0] >> 6) & 1;
|
||||
|
||||
fcf.sequence_number_suppression = data[1] & 1;
|
||||
fcf.ie_list_present = (data[1] >> 1) & 1;
|
||||
fcf.dest_addr_mode = (data[1] >> 2) & 3;
|
||||
fcf.frame_version = (data[1] >> 4) & 3;
|
||||
fcf.src_addr_mode = (data[1] >> 6) & 3;
|
||||
|
||||
/* copy fcf */
|
||||
memcpy(pfcf, &fcf, sizeof(frame802154_fcf_t));
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief Parses an input frame. Scans the input frame to find each
|
||||
|
@ -489,19 +515,7 @@ frame802154_parse(uint8_t *data, int len, frame802154_t *pf)
|
|||
p = data;
|
||||
|
||||
/* decode the FCF */
|
||||
fcf.frame_type = p[0] & 7;
|
||||
fcf.security_enabled = (p[0] >> 3) & 1;
|
||||
fcf.frame_pending = (p[0] >> 4) & 1;
|
||||
fcf.ack_required = (p[0] >> 5) & 1;
|
||||
fcf.panid_compression = (p[0] >> 6) & 1;
|
||||
|
||||
fcf.sequence_number_suppression = p[1] & 1;
|
||||
fcf.ie_list_present = (p[1] >> 1) & 1;
|
||||
fcf.dest_addr_mode = (p[1] >> 2) & 3;
|
||||
fcf.frame_version = (p[1] >> 4) & 3;
|
||||
fcf.src_addr_mode = (p[1] >> 6) & 3;
|
||||
|
||||
/* copy fcf and seqNum */
|
||||
frame802154_parse_fcf(p, &fcf);
|
||||
memcpy(&pf->fcf, &fcf, sizeof(frame802154_fcf_t));
|
||||
p += 2; /* Skip first two bytes */
|
||||
|
||||
|
|
|
@ -207,8 +207,10 @@ typedef struct {
|
|||
/* Prototypes */
|
||||
|
||||
int frame802154_hdrlen(frame802154_t *p);
|
||||
void frame802154_create_fcf(frame802154_fcf_t *fcf, uint8_t *buf);
|
||||
int frame802154_create(frame802154_t *p, uint8_t *buf);
|
||||
int frame802154_parse(uint8_t *data, int length, frame802154_t *pf);
|
||||
void frame802154_parse_fcf(uint8_t *data, frame802154_fcf_t *pfcf);
|
||||
|
||||
/* Get current PAN ID */
|
||||
uint16_t frame802154_get_pan_id(void);
|
||||
|
|
|
@ -112,6 +112,16 @@
|
|||
/* Configure NullRDC for when it is selected */
|
||||
#define NULLRDC_CONF_802154_AUTOACK_HW 1
|
||||
|
||||
/* Configure ContikiMAC for when it's selected */
|
||||
#define CONTIKIMAC_CONF_WITH_CONTIKIMAC_HEADER 0
|
||||
#define CONTIKIMAC_CONF_WITH_PHASE_OPTIMIZATION 0
|
||||
#define WITH_FAST_SLEEP 1
|
||||
|
||||
#ifndef NETSTACK_CONF_RDC_CHANNEL_CHECK_RATE
|
||||
#define NETSTACK_CONF_RDC_CHANNEL_CHECK_RATE 8
|
||||
#endif
|
||||
#define RDC_CONF_HARDWARE_ACK 1
|
||||
|
||||
#define UIP_CONF_LL_802154 1
|
||||
#define UIP_CONF_LLH_LEN 0
|
||||
|
||||
|
|
|
@ -63,6 +63,18 @@
|
|||
#define DEBUG DEBUG_NONE
|
||||
#include "net/ip/uip-debug.h"
|
||||
|
||||
#ifdef MICROMAC_CONF_RADIO_MAC
|
||||
#define MICROMAC_RADIO_MAC MICROMAC_CONF_RADIO_MAC
|
||||
#else
|
||||
#define MICROMAC_RADIO_MAC 0
|
||||
#endif
|
||||
|
||||
#if MICROMAC_RADIO_MAC
|
||||
#define MICROMAC_FRAME tsMacFrame
|
||||
#else
|
||||
#define MICROMAC_FRAME tsPhyFrame
|
||||
#endif
|
||||
|
||||
/* Perform CRC check for received packets in SW,
|
||||
* since we use PHY mode which does not calculate CRC in HW */
|
||||
#define CRC_SW 1
|
||||
|
@ -165,17 +177,17 @@ static volatile uint8_t listen_on = 0;
|
|||
static uint8_t in_ack_transmission = 0;
|
||||
|
||||
/* TX frame buffer */
|
||||
static tsPhyFrame tx_frame_buffer;
|
||||
static MICROMAC_FRAME tx_frame_buffer;
|
||||
|
||||
/* RX frame buffer */
|
||||
static tsPhyFrame *rx_frame_buffer;
|
||||
static MICROMAC_FRAME *rx_frame_buffer;
|
||||
|
||||
/* Frame buffer pointer to read from */
|
||||
static tsPhyFrame *input_frame_buffer = NULL;
|
||||
static MICROMAC_FRAME *input_frame_buffer = NULL;
|
||||
|
||||
/* Ringbuffer for received packets in interrupt enabled mode */
|
||||
static struct ringbufindex input_ringbuf;
|
||||
static tsPhyFrame input_array[MIRCOMAC_CONF_BUF_NUM];
|
||||
static MICROMAC_FRAME input_array[MIRCOMAC_CONF_BUF_NUM];
|
||||
|
||||
/* SFD timestamp in RTIMER ticks */
|
||||
static volatile uint32_t last_packet_timestamp = 0;
|
||||
|
@ -183,7 +195,9 @@ static volatile uint32_t last_packet_timestamp = 0;
|
|||
/* Local functions prototypes */
|
||||
static int on(void);
|
||||
static int off(void);
|
||||
#if !MICROMAC_RADIO_MAC
|
||||
static int is_packet_for_us(uint8_t *buf, int len, int do_send_ack);
|
||||
#endif
|
||||
static void set_frame_filtering(uint8_t enable);
|
||||
static rtimer_clock_t get_packet_timestamp(void);
|
||||
static void set_txpower(int8_t power);
|
||||
|
@ -305,10 +319,21 @@ on(void)
|
|||
{
|
||||
/* No address matching or frame decoding */
|
||||
if(rx_frame_buffer != NULL) {
|
||||
#if MICROMAC_RADIO_MAC
|
||||
vMMAC_StartMacReceive(rx_frame_buffer,
|
||||
(uint16_t)(E_MMAC_RX_START_NOW
|
||||
| E_MMAC_RX_USE_AUTO_ACK
|
||||
| E_MMAC_RX_NO_MALFORMED
|
||||
| E_MMAC_RX_NO_FCS_ERROR
|
||||
| E_MMAC_RX_ADDRESS_MATCH
|
||||
| E_MMAC_RX_ALIGN_NORMAL)
|
||||
);
|
||||
#else
|
||||
vMMAC_StartPhyReceive(rx_frame_buffer,
|
||||
(uint16_t)(E_MMAC_RX_START_NOW
|
||||
| E_MMAC_RX_NO_FCS_ERROR) /* means: reject FCS errors */
|
||||
);
|
||||
#endif
|
||||
} else {
|
||||
missed_radio_on_request = 1;
|
||||
}
|
||||
|
@ -347,10 +372,16 @@ transmit(unsigned short payload_len)
|
|||
ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);
|
||||
|
||||
/* Transmit and wait */
|
||||
#if MICROMAC_RADIO_MAC
|
||||
vMMAC_StartMacTransmit(&tx_frame_buffer,
|
||||
E_MMAC_TX_START_NOW |
|
||||
E_MMAC_TX_USE_AUTO_ACK |
|
||||
(send_on_cca ? E_MMAC_TX_USE_CCA : E_MMAC_TX_NO_CCA));
|
||||
#else
|
||||
vMMAC_StartPhyTransmit(&tx_frame_buffer,
|
||||
E_MMAC_TX_START_NOW |
|
||||
(send_on_cca ? E_MMAC_TX_USE_CCA : E_MMAC_TX_NO_CCA));
|
||||
|
||||
#endif
|
||||
if(poll_mode) {
|
||||
BUSYWAIT_UNTIL(u32MMAC_PollInterruptSource(E_MMAC_INT_TX_COMPLETE), MAX_PACKET_DURATION);
|
||||
} else {
|
||||
|
@ -394,8 +425,10 @@ transmit(unsigned short payload_len)
|
|||
static int
|
||||
prepare(const void *payload, unsigned short payload_len)
|
||||
{
|
||||
#if !MICROMAC_RADIO_MAC
|
||||
uint8_t i;
|
||||
uint16_t checksum;
|
||||
#endif
|
||||
|
||||
RIMESTATS_ADD(lltx);
|
||||
|
||||
|
@ -405,6 +438,30 @@ prepare(const void *payload, unsigned short payload_len)
|
|||
if(payload_len > 127 || payload == NULL) {
|
||||
return 1;
|
||||
}
|
||||
#if MICROMAC_RADIO_MAC
|
||||
frame802154_t info154;
|
||||
int hdr_len = frame802154_parse((unsigned char *)payload, payload_len, &info154);
|
||||
//TODO: hdr_len contains security header, which are not managed by micromac
|
||||
tx_frame_buffer.u8PayloadLength = payload_len - hdr_len;
|
||||
tx_frame_buffer.u8SequenceNum = info154.seq;
|
||||
tx_frame_buffer.u16FCF = ((uint8_t*)payload)[0] | (((uint8_t*)payload)[1] << 8);
|
||||
tx_frame_buffer.u16DestPAN = info154.dest_pid;
|
||||
tx_frame_buffer.u16SrcPAN = info154.src_pid;
|
||||
if(info154.fcf.dest_addr_mode == FRAME802154_SHORTADDRMODE) {
|
||||
tx_frame_buffer.uDestAddr.u16Short = info154.dest_addr[0] | (info154.dest_addr[0] << 8);
|
||||
} else if(info154.fcf.dest_addr_mode == FRAME802154_LONGADDRMODE) {
|
||||
tx_frame_buffer.uDestAddr.sExt.u32L = *(uint32_t*)(&info154.dest_addr[4]);
|
||||
tx_frame_buffer.uDestAddr.sExt.u32H = *(uint32_t*)(&info154.dest_addr[0]);
|
||||
}
|
||||
if(info154.fcf.src_addr_mode == FRAME802154_SHORTADDRMODE) {
|
||||
tx_frame_buffer.uSrcAddr.u16Short = info154.src_addr[0] | (info154.src_addr[0] << 8);
|
||||
} else if(info154.fcf.src_addr_mode == FRAME802154_LONGADDRMODE) {
|
||||
tx_frame_buffer.uSrcAddr.sExt.u32L = *(uint32_t*)(&info154.src_addr[4]);
|
||||
tx_frame_buffer.uSrcAddr.sExt.u32H = *(uint32_t*)(&info154.src_addr[0]);
|
||||
}
|
||||
tx_frame_buffer.u16FCS = crc16_data(payload, payload_len, 0);
|
||||
memcpy(tx_frame_buffer.uPayload.au8Byte, info154.payload, info154.payload_len);
|
||||
#else
|
||||
/* Copy payload to (soft) Ttx buffer */
|
||||
memcpy(tx_frame_buffer.uPayload.au8Byte, payload, payload_len);
|
||||
i = payload_len;
|
||||
|
@ -416,6 +473,7 @@ prepare(const void *payload, unsigned short payload_len)
|
|||
tx_frame_buffer.u8PayloadLength = payload_len + CHECKSUM_LEN;
|
||||
#else
|
||||
tx_frame_buffer.u8PayloadLength = payload_len;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
@ -445,6 +503,7 @@ set_channel(int c)
|
|||
vMMAC_SetChannel(current_channel);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#if !MICROMAC_RADIO_MAC
|
||||
static int
|
||||
is_broadcast_addr(uint8_t mode, uint8_t *addr)
|
||||
{
|
||||
|
@ -504,11 +563,59 @@ is_packet_for_us(uint8_t *buf, int len, int do_send_ack)
|
|||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
read(void *buf, unsigned short bufsize)
|
||||
{
|
||||
int len = 0;
|
||||
#if MICROMAC_RADIO_MAC
|
||||
frame802154_fcf_t fcf;
|
||||
uint8_t *p = (uint8_t*)buf;
|
||||
int has_src_panid;
|
||||
int has_dest_panid;
|
||||
int c;
|
||||
|
||||
p[len++] = input_frame_buffer->u16FCF & 0xff;
|
||||
p[len++] = (input_frame_buffer->u16FCF >> 8) & 0xff;
|
||||
frame802154_parse_fcf(p, &fcf);
|
||||
p[len++] = input_frame_buffer->u8SequenceNum;
|
||||
frame802154_has_panid(&fcf, &has_src_panid, &has_dest_panid);
|
||||
if(has_dest_panid) {
|
||||
p[len++] = input_frame_buffer->u16DestPAN & 0xff;
|
||||
p[len++] = (input_frame_buffer->u16DestPAN >> 8) & 0xff;
|
||||
}
|
||||
if(fcf.dest_addr_mode == FRAME802154_SHORTADDRMODE) {
|
||||
p[len++] = input_frame_buffer->uDestAddr.u16Short & 0xff;
|
||||
p[len++] = (input_frame_buffer->uDestAddr.u16Short >> 8) & 0xff;
|
||||
} else if(fcf.dest_addr_mode == FRAME802154_LONGADDRMODE) {
|
||||
for(c = 0; c < 4; c++) {
|
||||
p[len + c] = ((uint8_t*)(&input_frame_buffer->uDestAddr.sExt.u32L))[3 - c];
|
||||
}
|
||||
for(c = 0; c < 4; c++) {
|
||||
p[len + c + 4] = ((uint8_t*)(&input_frame_buffer->uDestAddr.sExt.u32H))[3 - c];
|
||||
}
|
||||
len += 8;
|
||||
}
|
||||
if(has_src_panid) {
|
||||
p[len++] = input_frame_buffer->u16SrcPAN & 0xff;
|
||||
p[len++] = (input_frame_buffer->u16SrcPAN >> 8) & 0xff;
|
||||
}
|
||||
if(fcf.src_addr_mode == FRAME802154_SHORTADDRMODE) {
|
||||
p[len++] = input_frame_buffer->uSrcAddr.u16Short & 0xff;
|
||||
p[len++] = (input_frame_buffer->uSrcAddr.u16Short >> 8) & 0xff;
|
||||
} else if(fcf.src_addr_mode == FRAME802154_LONGADDRMODE) {
|
||||
for(c = 0; c < 4; c++) {
|
||||
p[len + c] = ((uint8_t*)(&input_frame_buffer->uSrcAddr.sExt.u32L))[3 - c];
|
||||
}
|
||||
for(c = 0; c < 4; c++) {
|
||||
p[len + c + 4] = ((uint8_t*)(&input_frame_buffer->uSrcAddr.sExt.u32H))[3 - c];
|
||||
}
|
||||
len += 8;
|
||||
}
|
||||
memcpy(&p[len], input_frame_buffer->uPayload.au8Byte, input_frame_buffer->u8PayloadLength);
|
||||
len += input_frame_buffer->u8PayloadLength;
|
||||
#else
|
||||
uint16_t radio_last_rx_crc;
|
||||
uint8_t radio_last_rx_crc_ok = 1;
|
||||
|
||||
|
@ -556,7 +663,7 @@ read(void *buf, unsigned short bufsize)
|
|||
/* Disable further read attempts */
|
||||
input_frame_buffer->u8PayloadLength = 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
return len;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
@ -670,7 +777,9 @@ radio_interrupt_handler(uint32 mac_event)
|
|||
uint8_t overflow = 0;
|
||||
int get_index;
|
||||
int put_index;
|
||||
#if !MICROMAC_RADIO_MAC
|
||||
int packet_for_me = 0;
|
||||
#endif
|
||||
|
||||
if(mac_event & E_MMAC_INT_TX_COMPLETE) {
|
||||
/* Transmission attempt has finished */
|
||||
|
@ -683,6 +792,28 @@ radio_interrupt_handler(uint32 mac_event)
|
|||
last_packet_timestamp = get_packet_timestamp();
|
||||
|
||||
if(!poll_mode && (mac_event & E_MMAC_INT_RX_COMPLETE)) {
|
||||
#if MICROMAC_RADIO_MAC
|
||||
/* read and cache RSSI and LQI values */
|
||||
read_last_rssi();
|
||||
/* Put received frame in queue */
|
||||
ringbufindex_put(&input_ringbuf);
|
||||
|
||||
if((get_index = ringbufindex_peek_get(&input_ringbuf)) != -1) {
|
||||
input_frame_buffer = &input_array[get_index];
|
||||
}
|
||||
process_poll(µmac_radio_process);
|
||||
|
||||
/* get pointer to next input slot */
|
||||
put_index = ringbufindex_peek_put(&input_ringbuf);
|
||||
/* is there space? */
|
||||
if(put_index != -1) {
|
||||
/* move rx_frame_buffer to next empty slot */
|
||||
rx_frame_buffer = &input_array[put_index];
|
||||
} else {
|
||||
overflow = 1;
|
||||
rx_frame_buffer = NULL;
|
||||
}
|
||||
#else
|
||||
if(rx_frame_buffer->u8PayloadLength > CHECKSUM_LEN) {
|
||||
if(frame_filtering) {
|
||||
/* Check RX address */
|
||||
|
@ -716,6 +847,7 @@ radio_interrupt_handler(uint32 mac_event)
|
|||
rx_frame_buffer = NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
} else { /* if rx is not successful */
|
||||
if(rx_status & E_MMAC_RXSTAT_ABORTED) {
|
||||
|
|
Loading…
Reference in a new issue