Merge pull request #2012 from cetic/jn516-hw-mac

JN516x: Add support for hardware MAC
This commit is contained in:
Simon Duquennoy 2017-03-09 08:53:47 +01:00 committed by GitHub
commit c5c1979d37
4 changed files with 190 additions and 32 deletions

View file

@ -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 */

View file

@ -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);

View file

@ -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

View file

@ -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(&micromac_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) {