at86rf2xx: implement CSMA settings

This commit is contained in:
daniel-k 2015-06-01 15:51:50 +02:00
parent eac7f3e3ce
commit 6f705a5189
7 changed files with 220 additions and 10 deletions

View File

@ -16,6 +16,7 @@
* @author Thomas Eichinger <thomas.eichinger@fu-berlin.de> * @author Thomas Eichinger <thomas.eichinger@fu-berlin.de>
* @author Hauke Petersen <hauke.petersen@fu-berlin.de> * @author Hauke Petersen <hauke.petersen@fu-berlin.de>
* @author Baptiste Clenet <bapclenet@gmail.com> * @author Baptiste Clenet <bapclenet@gmail.com>
* @author Daniel Krebs <github@daniel-krebs.net>
* *
* @} * @}
*/ */
@ -254,6 +255,56 @@ void at86rf2xx_set_max_retries(at86rf2xx_t *dev, uint8_t max)
at86rf2xx_reg_write(dev, AT86RF2XX_REG__XAH_CTRL_0, tmp); at86rf2xx_reg_write(dev, AT86RF2XX_REG__XAH_CTRL_0, tmp);
} }
uint8_t at86rf2xx_get_csma_max_retries(at86rf2xx_t *dev)
{
uint8_t tmp;
tmp = at86rf2xx_reg_read(dev, AT86RF2XX_REG__XAH_CTRL_0);
tmp &= AT86RF2XX_XAH_CTRL_0__MAX_CSMA_RETRIES;
tmp >>= 1;
return tmp;
}
void at86rf2xx_set_csma_max_retries(at86rf2xx_t *dev, int8_t retries)
{
retries = (retries > 5) ? 5 : retries; /* valid values: 0-5 */
retries = (retries < 0) ? 7 : retries; /* max < 0 => disable CSMA (set to 7) */
DEBUG("[at86rf2xx] opt: Set CSMA retries to %u\n", retries);
uint8_t tmp = at86rf2xx_reg_read(dev, AT86RF2XX_REG__XAH_CTRL_0);
tmp &= ~(AT86RF2XX_XAH_CTRL_0__MAX_CSMA_RETRIES);
tmp |= (retries << 1);
at86rf2xx_reg_write(dev, AT86RF2XX_REG__XAH_CTRL_0, tmp);
}
void at86rf2xx_set_csma_backoff_exp(at86rf2xx_t *dev, uint8_t min, uint8_t max)
{
max = (max > 8) ? 8 : max;
min = (min > max) ? max : min;
DEBUG("[at86rf2xx] opt: Set min BE=%u, max BE=%u\n", min, max);
at86rf2xx_reg_write(dev,
AT86RF2XX_REG__CSMA_BE,
(max << 4) | (min));
}
void at86rf2xx_set_csma_seed(at86rf2xx_t *dev, uint8_t entropy[2])
{
if(entropy == NULL) {
DEBUG("[at86rf2xx] opt: CSMA seed entropy is nullpointer\n");
return;
}
DEBUG("[at86rf2xx] opt: Set CSMA seed to 0x%x 0x%x\n", entropy[0], entropy[1]);
at86rf2xx_reg_write(dev,
AT86RF2XX_REG__CSMA_SEED_0,
entropy[0]);
uint8_t tmp = at86rf2xx_reg_read(dev, AT86RF2XX_REG__CSMA_SEED_1);
tmp &= ~(AT86RF2XX_CSMA_SEED_1__CSMA_SEED_1);
tmp |= entropy[1] & AT86RF2XX_CSMA_SEED_1__CSMA_SEED_1;
at86rf2xx_reg_write(dev, AT86RF2XX_REG__CSMA_SEED_1, tmp);
}
void at86rf2xx_set_option(at86rf2xx_t *dev, uint16_t option, bool state) void at86rf2xx_set_option(at86rf2xx_t *dev, uint16_t option, bool state)
{ {
uint8_t tmp; uint8_t tmp;
@ -266,8 +317,12 @@ void at86rf2xx_set_option(at86rf2xx_t *dev, uint16_t option, bool state)
/* trigger option specific actions */ /* trigger option specific actions */
switch (option) { switch (option) {
case AT86RF2XX_OPT_CSMA: case AT86RF2XX_OPT_CSMA:
DEBUG("[at86rf2xx] opt: enabling CSMA mode (NOT IMPLEMENTED)\n"); DEBUG("[at86rf2xx] opt: enabling CSMA mode" \
/* TODO: en/disable csma */ "(4 retries, min BE: 3 max BE: 5)\n");
/* Initialize CSMA seed with hardware address */
at86rf2xx_set_csma_seed(dev, dev->addr_long);
at86rf2xx_set_csma_max_retries(dev, 4);
at86rf2xx_set_csma_backoff_exp(dev, 3, 5);
break; break;
case AT86RF2XX_OPT_PROMISCUOUS: case AT86RF2XX_OPT_PROMISCUOUS:
DEBUG("[at86rf2xx] opt: enabling PROMISCUOUS mode\n"); DEBUG("[at86rf2xx] opt: enabling PROMISCUOUS mode\n");
@ -302,8 +357,9 @@ void at86rf2xx_set_option(at86rf2xx_t *dev, uint16_t option, bool state)
/* trigger option specific actions */ /* trigger option specific actions */
switch (option) { switch (option) {
case AT86RF2XX_OPT_CSMA: case AT86RF2XX_OPT_CSMA:
DEBUG("[at86rf2xx] opt: disabling CSMA mode (NOT IMPLEMENTED)\n"); DEBUG("[at86rf2xx] opt: disabling CSMA mode\n");
/* TODO: en/disable csma */ /* setting retries to -1 means CSMA disabled */
at86rf2xx_set_csma_max_retries(dev, -1);
break; break;
case AT86RF2XX_OPT_PROMISCUOUS: case AT86RF2XX_OPT_PROMISCUOUS:
DEBUG("[at86rf2xx] opt: disabling PROMISCUOUS mode\n"); DEBUG("[at86rf2xx] opt: disabling PROMISCUOUS mode\n");

View File

@ -528,6 +528,18 @@ static int _get(gnrc_netdev_t *device, netopt_t opt, void *val, size_t max_len)
!!(dev->options & AT86RF2XX_OPT_TELL_TX_END); !!(dev->options & AT86RF2XX_OPT_TELL_TX_END);
return sizeof(netopt_enable_t); return sizeof(netopt_enable_t);
case NETOPT_CSMA:
*((netopt_enable_t *)val) =
!!(dev->options & AT86RF2XX_OPT_CSMA);
return sizeof(netopt_enable_t);
case NETOPT_CSMA_RETRIES:
if (max_len < sizeof(uint8_t)) {
return -EOVERFLOW;
}
*((uint8_t *)val) = at86rf2xx_get_csma_max_retries(dev);
return sizeof(uint8_t);
default: default:
return -ENOTSUP; return -ENOTSUP;
} }
@ -654,6 +666,23 @@ static int _set(gnrc_netdev_t *device, netopt_t opt, void *val, size_t len)
((bool *)val)[0]); ((bool *)val)[0]);
return sizeof(netopt_enable_t); return sizeof(netopt_enable_t);
case NETOPT_CSMA:
at86rf2xx_set_option(dev, AT86RF2XX_OPT_CSMA,
((bool *)val)[0]);
return sizeof(netopt_enable_t);
case NETOPT_CSMA_RETRIES:
if( (len > sizeof(uint8_t)) ||
(*((uint8_t *)val) > 5) ) {
return -EOVERFLOW;
}
/* If CSMA is disabled, don't allow setting retries */
if( !(dev->options & AT86RF2XX_OPT_CSMA) ) {
return -ENOTSUP;
}
at86rf2xx_set_csma_max_retries(dev, *((uint8_t *)val));
return sizeof(uint8_t);
default: default:
return -ENOTSUP; return -ENOTSUP;
} }

View File

@ -317,6 +317,7 @@ extern "C" {
#define AT86RF2XX_CSMA_SEED_1__AACK_SET_PD (0x20) #define AT86RF2XX_CSMA_SEED_1__AACK_SET_PD (0x20)
#define AT86RF2XX_CSMA_SEED_1__AACK_DIS_ACK (0x10) #define AT86RF2XX_CSMA_SEED_1__AACK_DIS_ACK (0x10)
#define AT86RF2XX_CSMA_SEED_1__AACK_I_AM_COORD (0x08) #define AT86RF2XX_CSMA_SEED_1__AACK_I_AM_COORD (0x08)
#define AT86RF2XX_CSMA_SEED_1__CSMA_SEED_1 (0x07)
/** @} */ /** @} */
/** /**

View File

@ -21,6 +21,7 @@
* @author Thomas Eichinger <thomas.eichinger@fu-berlin.de> * @author Thomas Eichinger <thomas.eichinger@fu-berlin.de>
* @author Hauke Petersen <hauke.petersen@fu-berlin.de> * @author Hauke Petersen <hauke.petersen@fu-berlin.de>
* @author Kaspar Schleiser <kaspar@schleiser.de> * @author Kaspar Schleiser <kaspar@schleiser.de>
* @author Daniel Krebs <github@daniel-krebs.net>
*/ */
#ifndef AT86RF2XX_H_ #ifndef AT86RF2XX_H_
@ -334,6 +335,48 @@ uint8_t at86rf2xx_get_max_retries(at86rf2xx_t *dev);
*/ */
void at86rf2xx_set_max_retries(at86rf2xx_t *dev, uint8_t max); void at86rf2xx_set_max_retries(at86rf2xx_t *dev, uint8_t max);
/**
* @brief Get the maximum number of channel access attempts per frame (CSMA)
*
* @param[in] dev device to read from
*
* @return configured number of retries
*/
uint8_t at86rf2xx_get_csma_max_retries(at86rf2xx_t *dev);
/**
* @brief Set the maximum number of channel access attempts per frame (CSMA)
*
* This setting specifies the number of attempts to access the channel to
* transmit a frame. If the channel is busy @p retries times, then frame
* transmission fails.
* Valid values: 0 to 5, -1 means CSMA disabled
*
* @param[in] dev device to write to
* @param[in] max the maximum number of retries
*/
void at86rf2xx_set_csma_max_retries(at86rf2xx_t *dev, int8_t retries);
/**
* @brief Set the min and max backoff exponent for CSMA/CA
*
* - Maximum BE: 0 - 8
* - Minimum BE: 0 - [max]
*
* @param[in] dev device to write to
* @param[in] min the minimum BE
* @param[in] max the maximum BE
*/
void at86rf2xx_set_csma_backoff_exp(at86rf2xx_t *dev, uint8_t min, uint8_t max);
/**
* @brief Set seed for CSMA random backoff
*
* @param[in] dev device to write to
* @param[in] entropy 11 bit of entropy as seed for random backoff
*/
void at86rf2xx_set_csma_seed(at86rf2xx_t *dev, uint8_t entropy[2]);
/** /**
* @brief Enable or disable driver specific options * @brief Enable or disable driver specific options
* *

View File

@ -137,9 +137,31 @@ typedef enum {
* @note not all transceivers may support this interrupt * @note not all transceivers may support this interrupt
*/ */
NETOPT_TX_END_IRQ, NETOPT_TX_END_IRQ,
NETOPT_AUTOCCA, /**< en/disable to check automatically
* before sending the channel is clear. */
/**
* @brief Check automatically before sending if the channel is clear.
*
* This may be a hardware feature of the given transceiver, or might be
* otherwise implemented in software. If the device supports CSMA this
* option will enable CSMA with a certain set of parameters to emulate the
* desired behaviour.
*
* @note Be sure not to set NETCONF_OPT_CSMA simultaneously.
*
* TODO: How to get feedback?
*/
NETOPT_AUTOCCA,
/**
* @brief en/disable CSMA/CA support
*
* If the device supports CSMA in hardware, this option enables it with
* default parameters. For further configuration refer to the other
* NETCONF_OPT_CSMA_* options.
*/
NETOPT_CSMA,
NETOPT_CSMA_RETRIES, /**< get/set the number of retries when
when channel is busy */
/** /**
* @brief read-only check for a wired interface. * @brief read-only check for a wired interface.
* *

View File

@ -46,6 +46,8 @@ static const char *_netopt_strmap[] = {
[NETOPT_TX_START_IRQ] = "NETOPT_TX_START_IRQ", [NETOPT_TX_START_IRQ] = "NETOPT_TX_START_IRQ",
[NETOPT_TX_END_IRQ] = "NETOPT_TX_END_IRQ", [NETOPT_TX_END_IRQ] = "NETOPT_TX_END_IRQ",
[NETOPT_AUTOCCA] = "NETOPT_AUTOCCA", [NETOPT_AUTOCCA] = "NETOPT_AUTOCCA",
[NETOPT_CSMA] = "NETOPT_CSMA",
[NETOPT_CSMA_RETRIES] = "NETOPT_CSMA_RETRIES",
[NETOPT_IS_WIRED] = "NETOPT_IS_WIRED", [NETOPT_IS_WIRED] = "NETOPT_IS_WIRED",
[NETOPT_NUMOF] = "NETOPT_NUMOF", [NETOPT_NUMOF] = "NETOPT_NUMOF",
}; };

View File

@ -80,7 +80,8 @@ static void _set_usage(char *cmd_name)
" * \"addr_long\" - sets long address\n" " * \"addr_long\" - sets long address\n"
" * \"addr_short\" - alias for \"addr\"\n" " * \"addr_short\" - alias for \"addr\"\n"
" * \"channel\" - sets the frequency channel\n" " * \"channel\" - sets the frequency channel\n"
" * \"chan\" - alias for \"channel\"" " * \"chan\" - alias for \"channel\"\n"
" * \"csma_retries\" - set max. number of channel access attempts\n"
" * \"nid\" - sets the network identifier (or the PAN ID)\n" " * \"nid\" - sets the network identifier (or the PAN ID)\n"
" * \"pan\" - alias for \"nid\"\n" " * \"pan\" - alias for \"nid\"\n"
" * \"pan_id\" - alias for \"nid\"\n" " * \"pan_id\" - alias for \"nid\"\n"
@ -96,7 +97,7 @@ static void _mtu_usage(char *cmd_name)
static void _flag_usage(char *cmd_name) static void _flag_usage(char *cmd_name)
{ {
printf("usage: %s <if_id> [-]{promisc|autoack|preload|6lo|iphc}\n", cmd_name); printf("usage: %s <if_id> [-]{promisc|autoack|csma|autocca|preload|6lo|iphc}\n", cmd_name);
} }
static void _add_usage(char *cmd_name) static void _add_usage(char *cmd_name)
@ -138,6 +139,10 @@ static void _print_netopt(netopt_t opt)
printf("TX power [in dBm]"); printf("TX power [in dBm]");
break; break;
case NETOPT_CSMA_RETRIES:
printf("CSMA retries");
break;
default: default:
/* we don't serve these options here */ /* we don't serve these options here */
break; break;
@ -176,6 +181,7 @@ static void _netif_list(kernel_pid_t dev)
uint8_t hwaddr[MAX_ADDR_LEN]; uint8_t hwaddr[MAX_ADDR_LEN];
uint16_t u16; uint16_t u16;
int16_t i16; int16_t i16;
uint8_t u8;
int res; int res;
netopt_state_t state; netopt_state_t state;
netopt_enable_t enable; netopt_enable_t enable;
@ -232,9 +238,19 @@ static void _netif_list(kernel_pid_t dev)
printf("Long HWaddr: "); printf("Long HWaddr: ");
printf("%s ", gnrc_netif_addr_to_str(hwaddr_str, sizeof(hwaddr_str), printf("%s ", gnrc_netif_addr_to_str(hwaddr_str, sizeof(hwaddr_str),
hwaddr, res)); hwaddr, res));
printf("\n ");
} }
res = gnrc_netapi_get(dev, NETOPT_CSMA_RETRIES, 0, &u8, sizeof(u8));
if (res >= 0) {
res = gnrc_netapi_get(dev, NETOPT_CSMA, 0, &enable, sizeof(enable));
if ((res >= 0) && (enable == NETOPT_ENABLE)) {
printf(" CSMA Retries: %" PRIu8 " ", *((uint8_t*) &u8));
}
}
printf("\n ");
res = gnrc_netapi_get(dev, NETOPT_PROMISCUOUSMODE, 0, &enable, sizeof(enable)); res = gnrc_netapi_get(dev, NETOPT_PROMISCUOUSMODE, 0, &enable, sizeof(enable));
if ((res >= 0) && (enable == NETOPT_ENABLE)) { if ((res >= 0) && (enable == NETOPT_ENABLE)) {
@ -263,6 +279,20 @@ static void _netif_list(kernel_pid_t dev)
linebreak = true; linebreak = true;
} }
res = gnrc_netapi_get(dev, NETOPT_CSMA, 0, &enable, sizeof(enable));
if ((res >= 0) && (enable == NETOPT_ENABLE)) {
printf("CSMA ");
linebreak = true;
}
res = gnrc_netapi_get(dev, NETOPT_AUTOCCA, 0, &enable, sizeof(enable));
if ((res >= 0) && (enable == NETOPT_ENABLE)) {
printf("AUTOCCA ");
linebreak = true;
}
#ifdef MODULE_GNRC_IPV6_NETIF #ifdef MODULE_GNRC_IPV6_NETIF
if (entry != NULL) { if (entry != NULL) {
printf("MTU:%" PRIu16 " ", entry->mtu); printf("MTU:%" PRIu16 " ", entry->mtu);
@ -401,6 +431,24 @@ static int _netif_set_i16(kernel_pid_t dev, netopt_t opt, char *i16_str)
return 0; return 0;
} }
static int _netif_set_u8(kernel_pid_t dev, netopt_t opt, char *u8_str)
{
uint8_t val = (uint8_t)atoi(u8_str);
if (gnrc_netapi_set(dev, opt, 0, (uint8_t *)&val, sizeof(uint8_t)) < 0) {
printf("error: unable to set ");
_print_netopt(opt);
puts("");
return 1;
}
printf("success: set ");
_print_netopt(opt);
printf(" on interface %" PRIkernel_pid " to %i\n", dev, val);
return 0;
}
static int _netif_set_flag(kernel_pid_t dev, netopt_t opt, static int _netif_set_flag(kernel_pid_t dev, netopt_t opt,
netopt_enable_t set) netopt_enable_t set)
{ {
@ -498,6 +546,9 @@ static int _netif_set(char *cmd_name, kernel_pid_t dev, char *key, char *value)
else if (strcmp("state", key) == 0) { else if (strcmp("state", key) == 0) {
return _netif_set_state(dev, value); return _netif_set_state(dev, value);
} }
else if (strcmp("csma_retries", key) == 0) {
return _netif_set_u8(dev, NETOPT_CSMA_RETRIES, value);
}
_set_usage(cmd_name); _set_usage(cmd_name);
return 1; return 1;
@ -524,6 +575,12 @@ static int _netif_flag(char *cmd, kernel_pid_t dev, char *flag)
else if (strcmp(flag, "raw") == 0) { else if (strcmp(flag, "raw") == 0) {
return _netif_set_flag(dev, NETOPT_RAWMODE, set); return _netif_set_flag(dev, NETOPT_RAWMODE, set);
} }
else if (strcmp(flag, "csma") == 0) {
return _netif_set_flag(dev, NETOPT_CSMA, set);
}
else if (strcmp(flag, "autocca") == 0) {
return _netif_set_flag(dev, NETOPT_AUTOCCA, set);
}
else if (strcmp(flag, "6lo") == 0) { else if (strcmp(flag, "6lo") == 0) {
#ifdef MODULE_GNRC_IPV6_NETIF #ifdef MODULE_GNRC_IPV6_NETIF
gnrc_ipv6_netif_t *entry = gnrc_ipv6_netif_get(dev); gnrc_ipv6_netif_t *entry = gnrc_ipv6_netif_get(dev);