Skip to content

Commit

Permalink
gnrc_mac: add timeout module based on evtimer.
Browse files Browse the repository at this point in the history
  • Loading branch information
zhuoshuguo committed Nov 7, 2016
1 parent e6ad438 commit da3bdb4
Show file tree
Hide file tree
Showing 7 changed files with 352 additions and 0 deletions.
45 changes: 45 additions & 0 deletions sys/include/net/gnrc/mac/mac.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright (C) 2015 Daniel Krebs
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/

/**
* @defgroup net_gnrc_mac A common MAC type for providing key MAC parameters and helper functions
* @ingroup net
* @brief A common MAC type for providing key MAC parameters and helper functions.
*
* @{
*
* @file
* @brief Interface definition for the GNRC_MAC
*
* @author Daniel Krebs <[email protected]>
* @author Shuguo Zhuo <[email protected]>
*/

#ifndef GNRC_MAC_H
#define GNRC_MAC_H

#include <kernel_types.h>
#include <net/gnrc/netdev2.h>

#ifdef __cplusplus
extern "C" {
#endif

/**
* @brief Count of parallel MAC timeouts.
*/
#ifndef GNRC_MAC_TIMEOUT_COUNT
#define GNRC_MAC_TIMEOUT_COUNT (3U)
#endif

#ifdef __cplusplus
}
#endif

#endif /* GNRC_MAC_H */
/** @} */
130 changes: 130 additions & 0 deletions sys/include/net/gnrc/mac/timeout.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
/*
* Copyright (C) 2015 Daniel Krebs
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/

/**
* @{
* @ingroup net_gnrc_mac
* @file
* @brief Timeout setting and handling for GNRC_MAC.
*
* @author Daniel Krebs <[email protected]>
* @author Shuguo Zhuo <[email protected]>
* @}
*/

#ifndef GNRC_MAC_TIMEOUT_H
#define GNRC_MAC_TIMEOUT_H

#include <stdint.h>
#include <stdbool.h>
#include <msg.h>
#include <xtimer.h>
#include <evtimer.h>
#include <mac.h>

#ifdef __cplusplus
extern "C" {
#endif


/**
* @brief definition of GNRC_MAC timeout types.
*/
typedef enum {
TIMEOUT_DISABLED = 0, /* Timeout is disabled, not in used. */
/* MAC developers add their own timeout types below,
* and should #ifdef+MODULE_NEWMAC out their own MAC timeout types */
#ifdef MODULE_LWMAC
TIMEOUT_WR,s
TIMEOUT_NO_RESPONSE,
TIMEOUT_WA,
TIMEOUT_DATA,
TIMEOUT_WAIT_FOR_DEST_WAKEUP,
TIMEOUT_WAKEUP_PERIOD,
TIMEOUT_NEXT_BROADCAST,
TIMEOUT_BROADCAST_END,
#endif
} gnrc_mac_timeout_type_t;

/**
* @brief structure of the GNRC_MAC timeout event.
*/
typedef struct {
evtimer_msg_event_t msg_event; /* The timeout message event. */
gnrc_mac_timeout_type_t type; /* GNRC_MAC timeout type. */
} gnrc_mac_timeout_event_t;

/**
* @brief structure holding the GNRC_MAC timeouts.
*/
typedef struct {
evtimer_t evtimer; /* The evtimer entity which stores the timeout list. */
gnrc_mac_timeout_event_t timeouts[GNRC_MAC_TIMEOUT_COUNT]; /* The gnrc_mac timeout unites. */
} gnrc_mac_timeout_t;
//#define GNRC_MAC_TIMEOUT_INIT { {}, {}, false, TIMEOUT_DISABLED }

/**
* @brief Initialize the MAC timeout module of gnrc_mac inside netdev2 before using,
* set the timeout callback function.
*
* @param[in,out] netdev2 the netdev2 device
*/
void gnrc_mac_init_timeouts(gnrc_netdev2_t* netdev2);

/**
* @brief set a MAC timeout of @p type for the netdev2 device.
*
* @param[in,out] netdev2 the netdev2 device
* @param[in] type the MAC timeout type
* @param[in] offset the timeout offset
*/
void gnrc_mac_set_timeout(gnrc_netdev2_t* netdev2, gnrc_mac_timeout_type_t type, uint32_t offset);

/**
* @brief clear a MAC timeout of @p type for the netdev2 device.
*
* @param[in,out] netdev2 the netdev2 device
* @param[in] type the MAC timeout type
*/
void gnrc_mac_clear_timeout(gnrc_netdev2_t* netdev2, gnrc_mac_timeout_type_t type);

/**
* @brief check whether a MAC timeout of @p type is running or not.
*
* @param[in] netdev2 the netdev2 device
* @param[in] type the MAC timeout type
*
* @return true if the time of @p type is running, otherwise return false.
*/
bool gnrc_mac_timeout_is_running(gnrc_netdev2_t* netdev2, gnrc_mac_timeout_type_t type);

/**
* @brief check whether a MAC timeout of @p type is expired or not.
* Note that, this function will release the related 'gnrc_mac_timeout_event_t'
* unit inside @p netdev2, if it is found expired.
*
* @param[in,out] netdev2 the netdev2 device
* @param[in] type the MAC timeout type
*
* @return true if the MAC time of @p type is expired,
* otherwise return false.
*/
bool gnrc_mac_timeout_is_expired(gnrc_netdev2_t* netdev2, gnrc_mac_timeout_type_t type);

/**
* @brief reset all the MAC timeouts of @p netdev2.
*
* @param[in,out] netdev2 the netdev2 device
*/
void gnrc_mac_reset_timeouts(gnrc_netdev2_t* netdev2);

#ifdef __cplusplus
}
#endif

#endif /* GNRC_MAC_TIMEOUT_H */
5 changes: 5 additions & 0 deletions sys/include/net/gnrc/mac/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@
extern "C" {
#endif

/**
* @brief definition for GNRC_MAC timeout type
*/
#define GNRC_MAC_EVENT_TIMEOUT_TYPE (0x4400)

/**
* @brief definition for device transmission feedback types
*/
Expand Down
16 changes: 16 additions & 0 deletions sys/include/net/gnrc/netdev2.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include "net/netdev2.h"
#include "net/gnrc.h"
#include "net/gnrc/mac/types.h"
#include "net/gnrc/mac/timeout.h"

#ifdef __cplusplus
extern "C" {
Expand Down Expand Up @@ -102,6 +103,21 @@ typedef struct gnrc_netdev2 {
* @brief general information for the MAC protocol
*/
uint16_t mac_info;

/**
* @brief device's l2 address
*/
uint8_t l2_addr[GNRC_NETIF_HDR_L2ADDR_MAX_LEN];

/**
* @brief device's l2 address length
*/
uint8_t l2_addr_len;

/**
* @brief store timeouts used for MAC protocol
*/
gnrc_mac_timeout_t mac_timeout;
#endif
} gnrc_netdev2_t;

Expand Down
3 changes: 3 additions & 0 deletions sys/net/gnrc/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ endif
ifneq (,$(filter gnrc_nomac,$(USEMODULE)))
DIRS += link_layer/nomac
endif
ifneq (,$(filter gnrc_mac,$(USEMODULE)))
DIRS += link_layer/gnrc_mac
endif
ifneq (,$(filter gnrc_pkt,$(USEMODULE)))
DIRS += pkt
endif
Expand Down
3 changes: 3 additions & 0 deletions sys/net/gnrc/link_layer/gnrc_mac/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
MODULE = gnrc_mac

include $(RIOTBASE)/Makefile.base
150 changes: 150 additions & 0 deletions sys/net/gnrc/link_layer/gnrc_mac/timeout.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
/*
* Copyright (C) 2015 Daniel Krebs
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/

/**
* @{
* @ingroup net_gnrc_mac
* @file
* @brief Provide timeout set and handling.
*
* @author Daniel Krebs <[email protected]>
* @author Shuguo Zhuo <[email protected]>
* @}
*/

#include <xtimer.h>
#include <net/gnrc/mac/mac.h>
#include <net/gnrc/mac/timeout.h>
#include <net/gnrc/mac/types.h>


#define ENABLE_DEBUG (0)
#include "debug.h"

void gnrc_mac_init_timeouts(gnrc_netdev2_t* netdev2){

assert(netdev2);

for(int i=0;i<GNRC_MAC_TIMEOUT_COUNT;i++) {
netdev2->mac_timeout.timeouts.msg_event.event.next = NULL;
netdev2->mac_timeout.timeouts.type = TIMEOUT_DISABLED;
}

evtimer_init(&netdev2->mac_timeout.evtimer, evtimer_msg_handler);
}


/* Return index >= 0 if found, -ENONENT if not found */
static int _gnrc_mac_find_timeout(gnrc_netdev2_t* netdev2, gnrc_mac_timeout_type_t type)
{
assert(netdev2);

for(unsigned i = 0; i < GNRC_MAC_TIMEOUT_COUNT; i++)
{
if(netdev2->mac_timeout.timeouts[i].type == type)
return i;
}
return -ENOENT;
}

inline bool gnrc_mac_timeout_is_running(gnrc_netdev2_t* netdev2, gnrc_mac_timeout_type_t type)
{
assert(netdev2);
return (_gnrc_mac_find_timeout(netdev2, type) >= 0);

/*
int i;
i = _gnrc_mac_find_timeout2(netdev2, type);
if(i >= 0) {
return evtimer_is_event_sched(netdev2->mac_timeout.evtimer, netdev2->mac_timeout.timeouts[i]);
}
return false;
*/
}

gnrc_mac_timeout_event_t* _gnrc_mac_acquire_timeout(gnrc_netdev2_t* netdev2, gnrc_mac_timeout_type_t type)
{
assert(netdev2);

if(gnrc_mac_timeout_is_running(netdev2, type))
return NULL;

for(unsigned i = 0; i < GNRC_MAC_TIMEOUT_COUNT; i++)
{
if(netdev2->mac_timeout.timeouts[i].type == TIMEOUT_DISABLED)
{
netdev2->mac_timeout.timeouts[i].type = type;
return &netdev2->mac_timeout.timeouts[i];
}
}
return NULL;
}

static inline void _gnrc_mac_clear_timeout(gnrc_netdev2_t* netdev2, gnrc_mac_timeout_event_t* timeout)
{
assert(timeout);

timeout->type = TIMEOUT_DISABLED;
evtimer_del(&netdev2->mac_timeout.evtimer, (evtimer_event_t *)&timeout->msg_event);
}

void gnrc_mac_set_timeout(gnrc_netdev2_t* netdev2, gnrc_mac_timeout_type_t type, uint32_t offset)
{
assert(netdev2);

gnrc_mac_timeout_event_t* timeout_event;
if((timeout_event = _gnrc_mac_acquire_timeout(netdev2, type)))
{
DEBUG("[gnrc_mac] Set timeout %s in %"PRIu32" us\n",
gnrc_mac_timeout_names[type], offset);
timeout_event->msg_event.msg.type = GNRC_MAC_EVENT_TIMEOUT_TYPE;
timeout_event->msg_event.msg.content.ptr = (void*) timeout_event;
timeout_event->msg_event.msg.sender_pid = netdev2->pid;
evtimer_add(&netdev2->mac_timeout.evtimer, (evtimer_event_t *)&timeout_event->msg_event);
} else {
DEBUG("[gnrc_mac] Cannot set timeout %s, too many concurrent timeouts\n",
gnrc_mac_timeout_names[type]);
}
}

void gnrc_mac_clear_timeout(gnrc_netdev2_t* netdev2, gnrc_mac_timeout_type_t type)
{
assert(netdev2);

int index = _gnrc_mac_find_timeout(netdev2, type);
if(index >= 0)
_gnrc_mac_clear_timeout(&netdev2->mac_timeout.timeouts[index]);
}

bool gnrc_mac_timeout_is_expired(gnrc_netdev2_t* netdev2, gnrc_mac_timeout_type_t type)
{
assert(netdev2);

int index = _gnrc_mac_find_timeout(netdev2, type);
if(index >= 0) {
if(!evtimer_is_event_sched(&netdev2->mac_timeout.evtimer, &netdev2->mac_timeout.timeouts[index])){
netdev2->mac_timeout.timeouts[index].type = TIMEOUT_DISABLED;
//_gnrc_mac_clear_timeout2(&gnrc_mac->timeouts[index]);
return true;
}
return false;
}
return false;
}

void gnrc_mac_reset_timeouts(gnrc_netdev2_t* netdev2)
{
assert(netdev2);

for(unsigned i = 0; i < GNRC_MAC_TIMEOUT_COUNT; i++)
{
if(netdev2->mac_timeout.timeouts[i].type != TIMEOUT_DISABLED)
_gnrc_mac_clear_timeout(netdev2, &netdev2->mac_timeout.timeouts[i]);
}
}

0 comments on commit da3bdb4

Please sign in to comment.