at86rf2xx: implement CSMA settings

dev/timer
daniel-k 8 years ago
parent eac7f3e3ce
commit 6f705a5189

@ -16,6 +16,7 @@
* @author Thomas Eichinger <thomas.eichinger@fu-berlin.de>
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
* @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);
}
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)
{
uint8_t tmp;
@ -266,8 +317,12 @@ void at86rf2xx_set_option(at86rf2xx_t *dev, uint16_t option, bool state)
/* trigger option specific actions */
switch (option) {
case AT86RF2XX_OPT_CSMA:
DEBUG("[at86rf2xx] opt: enabling CSMA mode (NOT IMPLEMENTED)\n");
/* TODO: en/disable csma */
DEBUG("[at86rf2xx] opt: enabling CSMA mode" \
"(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;
case AT86RF2XX_OPT_PROMISCUOUS:
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 */
switch (option) {
case AT86RF2XX_OPT_CSMA:
DEBUG("[at86rf2xx] opt: disabling CSMA mode (NOT IMPLEMENTED)\n");
/* TODO: en/disable csma */
DEBUG("[at86rf2xx] opt: disabling CSMA mode\n");
/* setting retries to -1 means CSMA disabled */
at86rf2xx_set_csma_max_retries(dev, -1);
break;
case AT86RF2XX_OPT_PROMISCUOUS:
DEBUG("[at86rf2xx] opt: disabling PROMISCUOUS mode\n");

@ -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);
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:
return -ENOTSUP;
}
@ -654,6 +666,23 @@ static int _set(gnrc_netdev_t *device, netopt_t opt, void *val, size_t len)
((bool *)val)[0]);
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:
return -ENOTSUP;
}

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

@ -21,6 +21,7 @@
* @author Thomas Eichinger <thomas.eichinger@fu-berlin.de>
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
* @author Kaspar Schleiser <kaspar@schleiser.de>
* @author Daniel Krebs <github@daniel-krebs.net>
*/
#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);
/**
* @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
*

@ -137,9 +137,31 @@ typedef enum {
* @note not all transceivers may support this interrupt
*/
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.
*

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

@ -80,7 +80,8 @@ static void _set_usage(char *cmd_name)
" * \"addr_long\" - sets long address\n"
" * \"addr_short\" - alias for \"addr\"\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"
" * \"pan\" - 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)
{
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)
@ -138,6 +139,10 @@ static void _print_netopt(netopt_t opt)
printf("TX power [in dBm]");
break;
case NETOPT_CSMA_RETRIES:
printf("CSMA retries");
break;
default:
/* we don't serve these options here */
break;
@ -176,6 +181,7 @@ static void _netif_list(kernel_pid_t dev)
uint8_t hwaddr[MAX_ADDR_LEN];
uint16_t u16;
int16_t i16;
uint8_t u8;
int res;
netopt_state_t state;
netopt_enable_t enable;
@ -230,11 +236,21 @@ static void _netif_list(kernel_pid_t dev)
if (res >= 0) {
char hwaddr_str[res * 3];
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));
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));
if ((res >= 0) && (enable == NETOPT_ENABLE)) {
@ -263,6 +279,20 @@ static void _netif_list(kernel_pid_t dev)
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
if (entry != NULL) {
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;
}
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,
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) {
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);
return 1;
@ -524,6 +575,12 @@ static int _netif_flag(char *cmd, kernel_pid_t dev, char *flag)
else if (strcmp(flag, "raw") == 0) {
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) {
#ifdef MODULE_GNRC_IPV6_NETIF
gnrc_ipv6_netif_t *entry = gnrc_ipv6_netif_get(dev);

Loading…
Cancel
Save