From abc6b5ccdf22358b0cb42340293ee5e6fbbb71e5 Mon Sep 17 00:00:00 2001 From: Hauke Petersen Date: Thu, 14 Apr 2016 13:48:00 +0200 Subject: [PATCH 1/9] drivers: added support for CC2420 radio --- drivers/Makefile.dep | 14 + drivers/Makefile.include | 3 + drivers/cc2420/Makefile | 1 + drivers/cc2420/cc2420.c | 877 +++++++++++++++++++++++ drivers/cc2420/include/cc2420_internal.h | 250 +++++++ drivers/cc2420/include/cc2420_params.h | 88 +++ drivers/include/cc2420.h | 311 ++++++++ 7 files changed, 1544 insertions(+) create mode 100644 drivers/cc2420/Makefile create mode 100644 drivers/cc2420/cc2420.c create mode 100644 drivers/cc2420/include/cc2420_internal.h create mode 100644 drivers/cc2420/include/cc2420_params.h create mode 100644 drivers/include/cc2420.h diff --git a/drivers/Makefile.dep b/drivers/Makefile.dep index 1f7fb49575..127169145c 100644 --- a/drivers/Makefile.dep +++ b/drivers/Makefile.dep @@ -32,6 +32,20 @@ ifneq (,$(filter cc110x,$(USEMODULE))) endif endif +ifneq (,$(filter cc2420,$(USEMODULE))) + USEMODULE += xtimer + USEMODULE += netif + USEMODULE += ieee802154 + USEMODULE += netdev2_ieee802154 + ifneq (,$(filter gnrc_netdev_default,$(USEMODULE))) + # XXX: this can be modelled as a dependency for gnrc_netdev_default as soon + # as all drivers are ported to netdev2 + USEMODULE += gnrc_netdev2 + endif + FEATURES_REQUIRED += periph_gpio + FEATURES_REQUIRED += periph_spi +endif + ifneq (,$(filter dht,$(USEMODULE))) USEMODULE += xtimer FEATURES_REQUIRED += periph_gpio diff --git a/drivers/Makefile.include b/drivers/Makefile.include index c216f626fe..2328776d0b 100644 --- a/drivers/Makefile.include +++ b/drivers/Makefile.include @@ -61,3 +61,6 @@ endif ifneq (,$(filter bmp180,$(USEMODULE))) USEMODULE_INCLUDES += $(RIOTBASE)/drivers/bmp180/include endif +ifneq (,$(filter cc2420,$(USEMODULE))) + USEMODULE_INCLUDES += $(RIOTBASE)/drivers/cc2420/include +endif diff --git a/drivers/cc2420/Makefile b/drivers/cc2420/Makefile new file mode 100644 index 0000000000..48422e909a --- /dev/null +++ b/drivers/cc2420/Makefile @@ -0,0 +1 @@ +include $(RIOTBASE)/Makefile.base diff --git a/drivers/cc2420/cc2420.c b/drivers/cc2420/cc2420.c new file mode 100644 index 0000000000..22258e0e3d --- /dev/null +++ b/drivers/cc2420/cc2420.c @@ -0,0 +1,877 @@ +/* + * Copyright (C) 2015-2016 Freie Universität Berlin + * + * 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 drivers_cc2420 + * @{ + * + * @file + * @brief Implementation of public functions for CC2420 driver + * + * @author Thomas Eichinger + * @author Hauke Petersen + * + * @} + */ + +#include "board.h" +#include "xtimer.h" +#include "periph/cpuid.h" +#include "byteorder.h" +#include "panic.h" +#include "net/ieee802154.h" +#include "net/gnrc.h" + +#include "cc2420.h" +#include "cc2420_internal.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + +/** + * @brief Some constant hardware configuration values + */ +#define SPI_MODE (SPI_CONF_FIRST_RISING) + +extern const netdev2_driver_t cc2420_driver; + +/** + * @brief Translation from dBm to PA level + * + * Entry 0 in the array corresponds to -25dBm (min), entry 25 to 0dBm (max), so + * `PA_level = power_dbm_to_pa[DBM + 25]`. We use only the 3 MSB of the 5-bit + * level, leading to 8 distinct power settings (the 8 settings listed in the + * datasheet in section 28, page 51). + */ +static const uint8_t power_dbm_to_pa[26] = { + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 7, 7, + 7, 7, 11, 11, 11, 15, 15, 19, 19, 23, 23, 27, 31 +}; + +/** + * @brief Translate PA level to dBm + * + * As we use only the 3 MSB of the PA level value, we have 8 distinct settings. + * We get the dBm value with `DBM = power_pa_to_dbm(PA >> 2). + */ +static const int8_t power_pa_to_dbm[8] = { + -25, -15, -10, -7, -5, -3, -1, 0 +}; + + +static inline uint16_t to_u16(void *buf) +{ + return *((uint16_t *)buf); +} + +static inline int16_t to_i16(void *buf) +{ + return *((int16_t *)buf); +} + +static inline bool to_bool(void *buf) +{ + return *((bool *)buf); +} + +static inline int w_u16(void *buf, uint16_t val) +{ + memcpy(buf, &val, sizeof(uint16_t)); + return sizeof(uint16_t); +} + +static inline int w_i16(void *buf, int16_t val) +{ + memcpy(buf, &val, sizeof(int16_t)); + return sizeof(int16_t); +} + +static inline int opt_state(void *buf, bool cond) +{ + *((netopt_enable_t *)buf) = !!(cond); + return sizeof(netopt_enable_t); +} + + +static uint8_t strobe(const cc2420_t *dev, const uint8_t command) +{ + char res; + + spi_acquire(dev->params.spi); + gpio_clear(dev->params.pin_cs); + spi_transfer_byte(dev->params.spi, (char)command, (char *)&res); + gpio_set(dev->params.pin_cs); + spi_release(dev->params.spi); + + return res; +} + +static void reg_write(const cc2420_t *dev, + const uint8_t addr, + const uint16_t value) +{ + uint16_t tmp = byteorder_htons(value).u16; + + spi_acquire(dev->params.spi); + gpio_clear(dev->params.pin_cs); + spi_transfer_regs(dev->params.spi, CC2420_REG_WRITE | addr, + (char *)&tmp, NULL, 2); + gpio_set(dev->params.pin_cs); + spi_release(dev->params.spi); +} + +static uint16_t reg_read(const cc2420_t *dev, const uint8_t addr) +{ + network_uint16_t tmp; + + spi_acquire(dev->params.spi); + gpio_clear(dev->params.pin_cs); + spi_transfer_regs(dev->params.spi, CC2420_REG_READ | addr, + NULL, (char *)&tmp, 2); + gpio_set(dev->params.pin_cs); + spi_release(dev->params.spi); + + return byteorder_ntohs(tmp); +} + +static void ram_read(const cc2420_t *dev, const uint16_t addr, + uint8_t *data, const size_t len) +{ + char tmp[] = { (CC2420_RAM | (addr & 0x7f)), + (CC2420_RAM_READ | ((addr >> 1) & 0xc0)) }; + + spi_acquire(dev->params.spi); + gpio_clear(dev->params.pin_cs); + spi_transfer_bytes(dev->params.spi, tmp, NULL, 2); + spi_transfer_bytes(dev->params.spi, NULL, (char*)data, len); + gpio_set(dev->params.pin_cs); + spi_release(dev->params.spi); +} + +static void ram_write(const cc2420_t *dev, const uint16_t addr, + const uint8_t *data, const size_t len) +{ + char tmp[] = { (CC2420_RAM | (addr & 0x7f)), + (CC2420_RAM_WRITE | ((addr >> 1) & 0xc0)) }; + + spi_acquire(dev->params.spi); + gpio_clear(dev->params.pin_cs); + spi_transfer_bytes(dev->params.spi, tmp, NULL, 2); + spi_transfer_bytes(dev->params.spi, (char*)data, NULL, len); + gpio_set(dev->params.pin_cs); + spi_release(dev->params.spi); +} + +static void fifo_read(const cc2420_t *dev, uint8_t *data, const size_t len) +{ + spi_acquire(dev->params.spi); + gpio_clear(dev->params.pin_cs); + spi_transfer_regs(dev->params.spi, CC2420_FIFO_READ, + NULL, (char *)data, len); + gpio_set(dev->params.pin_cs); + spi_release(dev->params.spi); +} + +static void fifo_write(const cc2420_t *dev, uint8_t *data, const size_t len) +{ + spi_acquire(dev->params.spi); + gpio_clear(dev->params.pin_cs); + spi_transfer_regs(dev->params.spi, CC2420_FIFO_WRITE, + (char *)data, NULL, len); + gpio_set(dev->params.pin_cs); + spi_release(dev->params.spi); +} + +/** + * @brief Get the device's status byte + */ +static inline uint8_t status(cc2420_t *dev) +{ + return strobe(dev, CC2420_STROBE_NOP); +} + +/** + * @brief Get the device's current state + */ +static inline uint8_t state(cc2420_t *dev) +{ + return (uint8_t)reg_read(dev, CC2420_REG_FSMSTATE); +} + +static inline void en_xosc(cc2420_t *dev) +{ + strobe(dev, CC2420_STROBE_XOSCON); + xtimer_usleep(CC2420_XOSCON_DELAY); +} + +static void fifop_evt(void *arg) +{ + netdev2_t *dev = (netdev2_t *)arg; + dev->event_callback(dev, NETDEV2_EVENT_ISR, NULL); +} + +/** + * @todo Move this function to a global module + */ +#if CPUID_ID_LEN +static void addr_from_cpuid(uint8_t *addr) +{ + /* option 1: generate addresses from CPUID */ + uint8_t cpuid[CPUID_ID_LEN]; + + cpuid_get(cpuid); + memcpy(addr, cpuid, 8); + +#if CPUID_ID_LEN < 8 + /* in case CPUID_ID_LEN < 8, fill missing bytes with zeros */ + for (int i = CPUID_ID_LEN; i < 8; i++) { + addr_long[i] = 0; + } +#else + /* in case CPUID_ID_LEN > 8, XOR those bytes on top of the first 8 */ + for (int i = 8; i < CPUID_ID_LEN; i++) { + addr_long[i & 0x07] ^= cpuid[i]; + } +#endif + + /* make sure we mark the address as non-multicast and not globally unique */ + addr_long[0] &= ~(0x01); + addr_long[0] |= 0x02; +} +#endif + + +void cc2420_setup(cc2420_t * dev, const cc2420_params_t *params) +{ + /* set pointer to the devices netdev functions */ + dev->netdev.netdev.driver = &cc2420_driver; + /* TODO: remove once the netdev2/802154 shit is cleaned up */ + dev->netdev.seq = 0; + dev->netdev.flags = NETDEV2_IEEE802154_PAN_COMP; + /* pull in device configuration parameters */ + memcpy(&dev->params, params, sizeof(cc2420_params_t)); + /* reset device descriptor fields */ + dev->options = 0; +} + +int cc2420_init(cc2420_t *dev) +{ + uint16_t reg; + uint8_t addr[8] = CC2420_ADDR_FALLBACK; + + /* initialize power and reset pins -> put the device into reset state */ + gpio_init(dev->params.pin_reset, GPIO_OUT); + gpio_set(dev->params.pin_reset); + gpio_init(dev->params.pin_vrefen, GPIO_OUT); + gpio_clear(dev->params.pin_vrefen); + + /* initialize the input lines */ + gpio_init(dev->params.pin_cca, GPIO_IN); + gpio_init(dev->params.pin_sfd, GPIO_IN); + gpio_init(dev->params.pin_fifo, GPIO_IN); + gpio_init_int(dev->params.pin_fifop, GPIO_IN, GPIO_RISING, fifop_evt, dev); + + /* initialize the chip select line and the SPI bus */ + gpio_init(dev->params.pin_cs, GPIO_OUT); + gpio_set(dev->params.pin_cs); + spi_init_master(dev->params.spi, SPI_MODE, dev->params.spi_clk); + + /* power on and toggle reset */ + gpio_set(dev->params.pin_vrefen); + gpio_clear(dev->params.pin_reset); + xtimer_usleep(CC2420_RESET_DELAY); + gpio_set(dev->params.pin_reset); + + /* test the connection to the device by reading MANFIDL register */ + reg = reg_read(dev, CC2420_REG_MANFIDL); + if (reg != CC2420_MANFIDL_VAL) { + DEBUG("[cc2420] init: unable to communicate with device\n"); + return -1; + } + + /* turn on the oscillator and wait for it to be stable */ + en_xosc(dev); + if (!(status(dev) & CC2420_STATUS_XOSC_STABLE)) { + DEBUG("[cc2420] init: oscillator did not stabilize\n"); + return -1; + } + + /* set default address, channel, PAN ID, and TX power */ +#if CPUID_ID_LEN + addr_from_cpuid(addr); +#endif + cc2420_set_addr_short(dev, &addr[6]); + cc2420_set_addr_long(dev, addr); + cc2420_set_pan(dev, CC2420_PANID_DEFAULT); + cc2420_set_chan(dev, CC2420_CHAN_DEFAULT); + cc2420_set_txpower(dev, CC2420_TXPOWER_DEFAULT); + + + /* set default options */ + cc2420_set_option(dev, CC2420_OPT_AUTOACK, true); + cc2420_set_option(dev, CC2420_OPT_CSMA, true); + cc2420_set_option(dev, CC2420_OPT_TELL_TX_START, true); + cc2420_set_option(dev, CC2420_OPT_TELL_RX_END, true); + + /* change default RX bandpass filter to 1.3uA (as recommended) */ + reg = reg_read(dev, CC2420_REG_RXCTRL1); + reg |= CC2420_RXCTRL1_RXBPF_LOCUR; + reg_write(dev, CC2420_REG_RXCTRL1, reg); + + /* set the FIFOP threshold to maximum. */ + reg_write(dev, CC2420_REG_IOCFG0, CC2420_PKT_MAXLEN); + + /* turn off "Security enable" (page 33). */ + reg = reg_read(dev, CC2420_REG_SECCTRL0); + reg &= ~CC2420_SECCTRL0_RXFIFO_PROT; + reg_write(dev, CC2420_REG_SECCTRL0, reg); + + /* go into RX state */ + cc2420_set_state(dev, CC2420_GOTO_RX); + + /* set preamble length to 3 leading zero byte */ + reg = reg_read(dev, CC2420_REG_MDMCTRL0); + reg &= ~(CC2420_MDMCTRL0_PREAMBLE_M); + reg |= CC2420_MDMCTRL0_PREAMBLE_3B; + reg_write(dev, CC2420_REG_MDMCTRL0, reg); + + return 0; +} + +void cc2420_get_addr_short(cc2420_t *dev, uint8_t *addr) +{ + uint8_t tmp[2]; + + ram_read(dev, CC2420_RAM_SHORTADR, tmp, 2); + + addr[0] = tmp[1]; + addr[1] = tmp[0]; +} + +void cc2420_set_addr_short(cc2420_t *dev, uint8_t *addr) +{ + uint8_t tmp[2]; + tmp[0] = addr[1]; + tmp[1] = addr[0]; + + ram_write(dev, CC2420_RAM_SHORTADR, tmp, 2); + + /* TODO: remove after 802.15.4 / netdev2 cleanup */ + memcpy(dev->netdev.short_addr, addr, 2); +} + +void cc2420_get_addr_long(cc2420_t *dev, uint8_t *addr) +{ + ram_read(dev, CC2420_RAM_IEEEADR, addr, 8); +} + +void cc2420_set_addr_long(cc2420_t *dev, uint8_t *addr) +{ + ram_write(dev, CC2420_RAM_IEEEADR, addr, 8); + + /* TODO: remove after 802.15.4 / netdev2 cleanup */ + memcpy(dev->netdev.long_addr, addr, 8); +} + +uint16_t cc2420_get_pan(cc2420_t *dev) +{ + le_uint16_t pan; + + ram_read(dev, CC2420_RAM_PANID, pan.u8, 2); + return pan.u16; +} + +void cc2420_set_pan(cc2420_t *dev, uint16_t pan) +{ + ram_write(dev, CC2420_RAM_PANID, (uint8_t *)&pan, 2); + + /* TODO: remove after 802.15.4 / netdev2 cleanup */ + dev->netdev.pan = pan; +} + +uint16_t cc2420_get_chan(cc2420_t *dev) +{ + uint16_t chan; + uint16_t freq = reg_read(dev, CC2420_REG_FSCTRL); + + chan = (((freq & CC2420_FSCTRL_FREQ_MASK) - 357) / 5) + 11; + return chan; +} + +int cc2420_set_chan(cc2420_t *dev, uint16_t chan) +{ + if ((chan < CC2420_CHAN_MIN) || (chan > CC2420_CHAN_MAX)) { + DEBUG("[cc2420] set channel: given channel invalid\n"); + return -ENOTSUP; + } + + /* calculation from http://www.ti.com/lit/ds/symlink/cc2420.pdf p.50 */ + uint16_t freq = reg_read(dev, CC2420_REG_FSCTRL); + freq &= ~CC2420_FSCTRL_FREQ_MASK; + freq |= (357 + (5 * (chan - 11))); + reg_write(dev, CC2420_REG_FSCTRL, freq); + + /* TODO: remove after 802.15.4 / netdev2 cleanup */ + dev->netdev.chan = chan; + + return CC2420_RET_CHAN_OK; +} + +int16_t cc2420_get_txpower(cc2420_t *dev) +{ + uint16_t txctrl = reg_read(dev, CC2420_REG_TXCTRL); + return (int16_t)power_pa_to_dbm[(txctrl & CC2420_TXCTRL_PA_MASK) >> 2]; +} + +void cc2420_set_txpower(cc2420_t *dev, int16_t txpower) +{ + if (txpower > CC2420_TXPOWER_MAX) { + txpower = CC2420_TXPOWER_MAX; + } + else if (txpower < CC2420_TXPOWER_MIN) { + txpower = CC2420_TXPOWER_MIN; + } + + uint16_t txctrl = reg_read(dev, CC2420_REG_TXCTRL); + txctrl &= ~(CC2420_TXCTRL_PA_MASK); + txctrl |= power_dbm_to_pa[txpower + 25]; + reg_write(dev, CC2420_REG_TXCTRL, txctrl); +} + +int cc2420_set_option(cc2420_t *dev, uint16_t option, bool state) +{ + uint16_t reg; + + /* set option field */ + if (state) { + dev->options |= option; + /* trigger option specific actions */ + switch (option) { + case CC2420_OPT_AUTOACK: + DEBUG("[cc2420] set_opt: CC2420_OPT_AUTOACK\n"); + reg = reg_read(dev, CC2420_REG_MDMCTRL0); + reg |= CC2420_MDMCTRL0_AUTOACK; + reg_write(dev, CC2420_REG_MDMCTRL0, reg); + /* TODO: remove after netdev2 cleanup */ + dev->netdev.flags |= NETDEV2_IEEE802154_ACK_REQ; + break; + + case CC2420_OPT_CSMA: + DEBUG("[cc2420] set_opt: CC2420_OPT_CSMA\n"); + /* TODO: en/disable csma */ + break; + + case CC2420_OPT_PROMISCUOUS: + DEBUG("[cc2420] set_opt: CC2420_OPT_PROMISCUOUS\n"); + /* in promisc mode, AUTO ACKs are should be disabled */ + reg = reg_read(dev, CC2420_REG_MDMCTRL0); + reg &= ~(CC2420_MDMCTRL0_AUTOACK); + reg &= ~(CC2420_MDMCTRL0_ADR_DECODE); + reg_write(dev, CC2420_REG_MDMCTRL0, reg); + break; + + case CC2420_OPT_PRELOADING: + DEBUG("[cc2420] set_opt: CC2420_OPT_PRELOADING\n"); + break; + + case CC2420_OPT_TELL_TX_START: + case CC2420_OPT_TELL_TX_END: + case CC2420_OPT_TELL_RX_START: + case CC2420_OPT_TELL_RX_END: + DEBUG("[cc2420] set_opt: TX/RX START/END\n"); + break; + + default: + return -ENOTSUP; + } + } + else { + dev->options &= ~(option); + /* trigger option specific actions */ + switch (option) { + case CC2420_OPT_AUTOACK: + DEBUG("[cc2420] clr_opt: CC2420_OPT_AUTOACK\n"); + reg = reg_read(dev, CC2420_REG_MDMCTRL0); + reg &= ~(CC2420_MDMCTRL0_AUTOACK); + reg_write(dev, CC2420_REG_MDMCTRL0, reg); + /* TODO: remove after netdev cleanup */ + dev->netdev.flags &= ~(NETDEV2_IEEE802154_ACK_REQ); + break; + + case CC2420_OPT_CSMA: + DEBUG("[cc2420] clr_opt: CC2420_OPT_CSMA\n"); + /* TODO: en/disable csma */ + break; + + case CC2420_OPT_PROMISCUOUS: + DEBUG("[cc2420] clr_opt: CC2420_OPT_PROMISCUOUS\n"); + reg = reg_read(dev, CC2420_REG_MDMCTRL0); + reg |= CC2420_MDMCTRL0_ADR_DECODE; + /* re-enable AUTOACK only if the option was set */ + if (dev->options & CC2420_OPT_AUTOACK) { + reg |= CC2420_MDMCTRL0_AUTOACK; + } + reg_write(dev, CC2420_REG_MDMCTRL0, reg); + break; + + case CC2420_OPT_PRELOADING: + DEBUG("[cc2420] clr_opt: CC2420_OPT_PRELOADING\n"); + break; + + case CC2420_OPT_TELL_TX_START: + case CC2420_OPT_TELL_TX_END: + case CC2420_OPT_TELL_RX_START: + case CC2420_OPT_TELL_RX_END: + DEBUG("[cc2420] clr_opt: TX/RX START/END\n"); + /* TODO */ + break; + + default: + return -ENOTSUP; + } + } + return sizeof(netopt_enable_t); +} + +int cc2420_set_state(cc2420_t *dev, netopt_state_t cmd) +{ + if ((cc2420_get_state(dev) == NETOPT_STATE_OFF) && + (cmd != NETOPT_STATE_OFF)) { + en_xosc(dev); + } + switch (cmd) { + case NETOPT_STATE_OFF: + strobe(dev, CC2420_STROBE_XOSCOFF); + while (state(dev) != CC2420_STATE_PD) {} + break; + case NETOPT_STATE_SLEEP: + strobe(dev, CC2420_STROBE_RFOFF); + while (state(dev) != CC2420_STATE_IDLE) {} + break; + case NETOPT_STATE_IDLE: + strobe(dev, CC2420_STROBE_FLUSHRX); + strobe(dev, CC2420_STROBE_RXON); + break; + case NETOPT_STATE_TX: + cc2420_tx_exec(dev); + break; + case NETOPT_STATE_RESET: + cc2420_init(dev); + break; + case NETOPT_STATE_RX: + default: + DEBUG("[cc2420] set_state: called with invalid target state\n"); + return -ENOTSUP; + } + return sizeof(netopt_state_t); +} + +netopt_state_t cc2420_get_state(cc2420_t *dev) +{ + uint8_t cur_state = state(dev); + + if (cur_state == 0) { + return NETOPT_STATE_OFF; + } + else if (cur_state == 1) { + return NETOPT_STATE_SLEEP; + } + else if (((cur_state >= 32) && (cur_state <=39)) || (cur_state == 56)) { + return NETOPT_STATE_TX; + } + else if ((cur_state >= 3) && (cur_state <= 6)) { + return NETOPT_STATE_IDLE; + } + else { + return NETOPT_STATE_RX; + } +} + +bool cc2420_cca(cc2420_t *dev) +{ + while (!(status(dev) & CC2420_STATUS_RSSI_VALID)) {} + return gpio_read(dev->params.pin_cca); +} + +size_t cc2420_send(cc2420_t *dev, const struct iovec *data, int count) +{ + size_t n = cc2420_tx_prepare(dev, data, count); + + if ((n > 0) && !(dev->options & CC2420_OPT_PRELOADING)) { + cc2420_tx_exec(dev); + } + + return n; +} + +size_t cc2420_tx_prepare(cc2420_t *dev, const struct iovec *data, int count) +{ + size_t pkt_len = 2; /* include the FCS (frame check sequence) */ + + /* wait for any ongoing transmissions to be finished */ + while (cc2420_get_state(dev) & NETOPT_STATE_TX) {} + + /* get and check the length of the packet */ + for (int i = 0; i < count; i++) { + pkt_len += data[i].iov_len; + } + if (pkt_len >= CC2420_PKT_MAXLEN) { + DEBUG("[cc2420] tx_prep: unable to send, pkt too large\n"); + return 0; + } + + /* flush TX FIFO and write new packet to it */ + strobe(dev, CC2420_STROBE_FLUSHTX); + /* push packet length to TX FIFO */ + fifo_write(dev, (uint8_t *)&pkt_len, 1); + /* push packet to TX FIFO */ + for (int i = 0; i < count; i++) { + fifo_write(dev, (uint8_t *)data[i].iov_base, data[i].iov_len); + } + DEBUG("[cc2420] tx_prep: loaded %i byte into the TX FIFO\n", (int)pkt_len); + + return pkt_len; +} + +void cc2420_tx_exec(cc2420_t *dev) +{ + /* make sure, any ongoing transmission is finished */ + DEBUG("[cc2420] tx_exec: waiting for any ongoing transmission\n"); + while (cc2420_get_state(dev) & NETOPT_STATE_TX) {} + /* trigger the transmission */ + if (dev->options & CC2420_OPT_TELL_TX_START) { + dev->netdev.netdev.event_callback(&dev->netdev.netdev, + NETDEV2_EVENT_TX_STARTED, dev); + } + DEBUG("[cc2420] tx_exec: TX_START\n"); + if (dev->options & CC2420_OPT_CSMA) { + DEBUG("[cc2420] tx_exec: triggering TX with CCA\n"); + strobe(dev, CC2420_STROBE_TXONCCA); + } + else { + DEBUG("[cc2420] tx_exec: triggering TX without CCA\n"); + strobe(dev, CC2420_STROBE_TXON); + } + + while (gpio_read(dev->params.pin_sfd)) { + puts("\t...ongoing}"); + } + if (dev->options & CC2420_OPT_TELL_TX_END) { + dev->netdev.netdev.event_callback(&dev->netdev.netdev, + NETDEV2_EVENT_TX_COMPLETE, dev); + } + DEBUG("[cc2420] tx_exec: TX_DONE\n"); +} + +int cc2420_rx(cc2420_t *dev, uint8_t *buf, size_t max_len, void *info) +{ + uint8_t len; + + /* get the packet length (without dropping it) (first byte in RX FIFO */ + ram_read(dev, CC2420_RAM_RXFIFO, &len, 1); + len -= 2; /* subtract RSSI and FCF */ + + if (!buf) { + DEBUG("[cc2420] recv: packet of length %i in RX FIFO\n", (int)len); + } + + /* if a buffer is given, read (and drop) the packet */ + if (buf) { + len = (len > max_len) ? max_len : len; + + /* drop length byte */ + fifo_read(dev, NULL, 1); + /* read fifo contents */ + DEBUG("[cc2420] recv: reading %i byte of the packet\n", (int)len); + fifo_read(dev, buf, len); + + uint8_t rssi; + fifo_read(dev, &rssi, 1); + DEBUG("[cc2420] recv: RSSI is %i\n", (int)rssi); + /* finally flush the FIFO */ + strobe(dev, CC2420_STROBE_FLUSHRX); + strobe(dev, CC2420_STROBE_FLUSHRX); + } + + return (int)len; +} + +static int init(netdev2_t *dev) +{ + return cc2420_init((cc2420_t *)dev); +} + +static void isr(netdev2_t *netdev) +{ + netdev->event_callback(netdev, NETDEV2_EVENT_RX_COMPLETE, NULL); +} + +static int send(netdev2_t *netdev, const struct iovec *vector, int count) +{ + cc2420_t *dev = (cc2420_t *)netdev; + return (int)cc2420_send(dev, vector, count); +} + +static int recv(netdev2_t *netdev, char *buf, int len, void *info) +{ + cc2420_t *dev = (cc2420_t *)netdev; + return (int)cc2420_rx(dev, (uint8_t *)buf, len, info); +} + +static int get(netdev2_t *netdev, netopt_t opt, void *val, size_t max_len) +{ + if (netdev == NULL) { + return -ENODEV; + } + + cc2420_t *dev = (cc2420_t *)netdev; + + int ext = netdev2_ieee802154_get(&dev->netdev, opt, val, max_len); + if (ext > 0) { + return ext; + } + + switch (opt) { + + case NETOPT_ADDRESS: + assert(max_len >= sizeof(uint16_t)); + cc2420_get_addr_short(dev, val); + return sizeof(uint16_t); + + case NETOPT_ADDRESS_LONG: + assert(max_len >= 8); + cc2420_get_addr_long(dev, val); + return 8; + + case NETOPT_NID: + assert(max_len >= sizeof(uint16_t)); + return w_u16(val, cc2420_get_pan(dev)); + + case NETOPT_CHANNEL: + assert(max_len >= sizeof(uint16_t)); + return w_u16(val, cc2420_get_chan(dev)); + + case NETOPT_TX_POWER: + assert(max_len >= sizeof(int16_t)); + return w_i16(val, cc2420_get_txpower(dev)); + + case NETOPT_STATE: + assert(max_len >= sizeof(netopt_state_t)); + *((netopt_state_t *)val) = cc2420_get_state(dev); + return sizeof(netopt_state_t); + + case NETOPT_IS_CHANNEL_CLR: + return opt_state(val, cc2420_cca(dev)); + + case NETOPT_AUTOACK: + return opt_state(val, (dev->options & CC2420_OPT_AUTOACK)); + + case NETOPT_CSMA: + return opt_state(val, (dev->options & CC2420_OPT_CSMA)); + + case NETOPT_PRELOADING: + return opt_state(val, (dev->options & CC2420_OPT_PRELOADING)); + + case NETOPT_PROMISCUOUSMODE: + return opt_state(val, (dev->options & CC2420_OPT_PROMISCUOUS)); + + case NETOPT_RX_START_IRQ: + return opt_state(val, (dev->options & CC2420_OPT_TELL_RX_START)); + + case NETOPT_RX_END_IRQ: + return opt_state(val, (dev->options & CC2420_OPT_TELL_TX_END)); + + case NETOPT_TX_START_IRQ: + return opt_state(val, (dev->options & CC2420_OPT_TELL_RX_START)); + + case NETOPT_TX_END_IRQ: + return opt_state(val, (dev->options & CC2420_OPT_TELL_RX_END)); + + default: + return -ENOTSUP; + } +} + +static int set(netdev2_t *netdev, netopt_t opt, void *val, size_t val_len) +{ + if (netdev == NULL) { + return -ENODEV; + } + + cc2420_t *dev = (cc2420_t *)netdev; + + int ext = netdev2_ieee802154_set(&dev->netdev, opt, val, val_len); + + switch (opt) { + case NETOPT_ADDRESS: + assert(val_len == 2); + cc2420_set_addr_short(dev, (uint8_t *)val); + return 2; + + case NETOPT_ADDRESS_LONG: + assert(val_len == 8); + cc2420_set_addr_long(dev, (uint8_t *)val); + return 8; + + case NETOPT_NID: + assert(val_len == sizeof(uint16_t)); + cc2420_set_pan(dev, to_u16(val)); + return sizeof(uint16_t); + + case NETOPT_CHANNEL: + assert(val_len == sizeof(uint16_t)); + return cc2420_set_chan(dev, to_u16(val)); + + case NETOPT_TX_POWER: + assert(val_len == sizeof(int16_t)); + cc2420_set_txpower(dev, to_i16(val)); + return sizeof(int16_t); + + case NETOPT_STATE: + assert(val_len == sizeof(netopt_state_t)); + return cc2420_set_state(dev, *((netopt_state_t *)val)); + + case NETOPT_AUTOACK: + return cc2420_set_option(dev, CC2420_OPT_AUTOACK, to_bool(val)); + + case NETOPT_CSMA: + return cc2420_set_option(dev, CC2420_OPT_CSMA, to_bool(val)); + + case NETOPT_PRELOADING: + return cc2420_set_option(dev, CC2420_OPT_PRELOADING, to_bool(val)); + + case NETOPT_PROMISCUOUSMODE: + return cc2420_set_option(dev, CC2420_OPT_PROMISCUOUS, to_bool(val)); + + case NETOPT_RX_START_IRQ: + return cc2420_set_option(dev, CC2420_OPT_TELL_RX_START, to_bool(val)); + + case NETOPT_RX_END_IRQ: + return cc2420_set_option(dev, CC2420_OPT_TELL_RX_END, to_bool(val)); + + case NETOPT_TX_START_IRQ: + return cc2420_set_option(dev, CC2420_OPT_TELL_TX_START, to_bool(val)); + + case NETOPT_TX_END_IRQ: + return cc2420_set_option(dev, CC2420_OPT_TELL_TX_END, to_bool(val)); + + default: + return ext; + } + + return 0; +} + +const netdev2_driver_t cc2420_driver = { + .send = send, + .recv = recv, + .init = init, + .isr = isr, + .get = get, + .set = set, +}; diff --git a/drivers/cc2420/include/cc2420_internal.h b/drivers/cc2420/include/cc2420_internal.h new file mode 100644 index 0000000000..d6bb5a53bd --- /dev/null +++ b/drivers/cc2420/include/cc2420_internal.h @@ -0,0 +1,250 @@ +/* + * Copyright (C) 2014 Milan Babel and INRIA + * Copyright (C) 2015-2016 Freie Universität Berlin + * + * 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 drivers_cc2420 + * @{ + * + * @file + * @brief Definitions and settings for the CC2420 + * + * @author Milan Babel + * @author Kévin Roussel + * @author Thomas Eichinger + * @author Hauke Petersen + * + */ +#ifndef CC2420_REGISTERS_H +#define CC2420_REGISTERS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Delays for resetting and turning on the device + * @{ + */ +#define CC2420_RESET_DELAY (500U) +#define CC2420_XOSCON_DELAY (2000U) +/** @} */ + +/** + * @brief Internal device option flags + * @{ + */ +#define CC2420_OPT_AUTOACK (0x0001) /**< auto ACKs active */ +#define CC2420_OPT_CSMA (0x0002) /**< CSMA active */ +#define CC2420_OPT_PROMISCUOUS (0x0004) /**< promiscuous mode + * active */ +#define CC2420_OPT_PRELOADING (0x0008) /**< preloading enabled */ +#define CC2420_OPT_TELL_TX_START (0x0010) /**< notify MAC layer on TX + * start */ +#define CC2420_OPT_TELL_TX_END (0x0020) /**< notify MAC layer on TX + * finished */ +#define CC2420_OPT_TELL_RX_START (0x0040) /**< notify MAC layer on RX + * start */ +#define CC2420_OPT_TELL_RX_END (0x0080) /**< notify MAC layer on RX + * finished */ +/** @} */ + +/** + * @brief Possible device state change commands + * @{ + */ +enum { + CC2420_GOTO_PD, /**< power down */ + CC2420_GOTO_IDLE, /**< idle */ + CC2420_GOTO_RX, /**< receive state */ + CC2420_GOTO_TXON, /**< transmit packet without CCA */ + CC2420_GOTO_TXONCCA /**< transmit packet using CCA */ +}; + +/** + * @brief (Selected) device states + */ +enum { + CC2420_STATE_PD = 0, /**< power down */ + CC2420_STATE_IDLE = 1, /**< idle state */ + CC2420_STATE_TX_PRE = 34, /**< transmitting preamble */ + CC2420_STATE_RX_SEARCH = 6, /**< receive SFD search */ + CC2420_STATE_RX_OVERFLOW = 17 /**< receive buffer overflow */ +}; + +/** + * @brief CC2420 SPI commands + * @{ + */ +#define CC2420_REG_WRITE (0x00) /**< read register value */ +#define CC2420_REG_READ (0x40) /**< write register value */ +#define CC2420_RAM (0x80) /**< access the internal RAM */ +#define CC2420_RAM_WRITE (0x00) /**< write to RAM */ +#define CC2420_RAM_READ (0x20) /**< read from RAM */ +#define CC2420_FIFO_READ (CC2420_REG_RXFIFO | CC2420_REG_READ) +#define CC2420_FIFO_WRITE (CC2420_REG_TXFIFO | CC2420_REG_WRITE) +/** @} */ + + +/** + * @brief CC2420 strobe commands + * @see Datasheet section 37, pages 61--62 + * @{ + */ +#define CC2420_STROBE_NOP (0x00) /**< no operation */ +#define CC2420_STROBE_XOSCON (0x01) /**< turn transceiver on */ +#define CC2420_STROBE_TXCAL (0x02) /**< calibrate TX freq and wait */ +#define CC2420_STROBE_RXON (0x03) /**< switch to RX mode */ +#define CC2420_STROBE_TXON (0x04) /**< switch to TX mode */ +#define CC2420_STROBE_TXONCCA (0x05) /**< switch to TX after CCA*/ +#define CC2420_STROBE_RFOFF (0x06) /**< switch to IDLE mode */ +#define CC2420_STROBE_XOSCOFF (0x07) /**< power down */ +#define CC2420_STROBE_FLUSHRX (0x08) /**< flush RX FIFO */ +#define CC2420_STROBE_FLUSHTX (0x09) /**< flush TX FIFO */ +#define CC2420_STROBE_ACK (0x0A) /**< send ACK with pending cleared */ +#define CC2420_STROBE_ACKPEND (0x0B) /**< send ACK with pending set */ +#define CC2420_STROBE_RXDEC (0x0C) /**< start RX FIFO decrypt/verify */ +#define CC2420_STROBE_TXENC (0x0D) /**< start TX FIFO encrypt/auth */ +#define CC2420_STROBE_AES (0x0E) /**< start AES encryption */ +/** @} */ + +/** + * @brief CC2420 configuration registers + * @see Datasheet section 37, pages 61 to 80 + * @{ + */ +#define CC2420_REG_MAIN (0x10) /**< main control */ +#define CC2420_REG_MDMCTRL0 (0x11) /**< modem control 0 */ +#define CC2420_REG_MDMCTRL1 (0x12) /**< modem control 1 */ +#define CC2420_REG_RSSI (0x13) /**< RSSI and CCA control */ +#define CC2420_REG_SYNCWORD (0x14) /**< synchronization word control */ +#define CC2420_REG_TXCTRL (0x15) /**< transmit control */ +#define CC2420_REG_RXCTRL0 (0x16) /**< receive control 0 */ +#define CC2420_REG_RXCTRL1 (0x17) /**< receive control 1 */ +#define CC2420_REG_FSCTRL (0x18) /**< freq synthesizer control */ +#define CC2420_REG_SECCTRL0 (0x19) /**< security control 0 */ +#define CC2420_REG_SECCTRL1 (0x1A) /**< security control 1 */ +#define CC2420_REG_BATTMON (0x1B) /**< battery monitor control */ +#define CC2420_REG_IOCFG0 (0x1C) /**< I/O control 0 */ +#define CC2420_REG_IOCFG1 (0x1D) /**< I/O control 1 */ +#define CC2420_REG_MANFIDL (0x1e) /**< manufacturer ID low */ +#define CC2420_REG_MANFIDH (0x1F) /**< manufacturer ID high */ +#define CC2420_REG_FSMTC (0x20) /**< FSM timer constants */ +#define CC2420_REG_MANAND (0x21) /**< manual signal AND override */ +#define CC2420_REG_MANOR (0x22) /**< manual signal OR override */ +#define CC2420_REG_AGCCTRL (0x23) /**< AGC control */ +#define CC2420_REG_AGCTST0 (0x24) /**< AGC test 0 */ +#define CC2420_REG_AGCTST1 (0x25) /**< AGC test 1 */ +#define CC2420_REG_AGCTST2 (0x26) /**< AGC test 2 */ +#define CC2420_REG_FSTST0 (0x27) /**< freq synthesizer test 0 */ +#define CC2420_REG_FSTST1 (0x28) /**< freq synthesizer test 1 */ +#define CC2420_REG_FSTST2 (0x29) /**< freq synthesizer test 2 */ +#define CC2420_REG_FSTST3 (0x2A) /**< freq synthesizer test 3 */ +#define CC2420_REG_RXBPFTST (0x2B) /**< RX bandpass filter test */ +#define CC2420_REG_FSMSTATE (0x2C) /**< FSM status */ +#define CC2420_REG_ADCTST (0x2D) /**< ADC test */ +#define CC2420_REG_DACTST (0x2E) /**< DAC test */ +#define CC2420_REG_TOPTST (0x2F) /**< top level test */ +#define CC2420_REG_TXFIFO (0x3E) /**< TX FIFO byte */ +#define CC2420_REG_RXFIFO (0x3F) /**< RX FIFO byte */ +/** @} */ + +/** + * @brief CC2420 section address in RAM + * @see Datasheet section 13.5 page 31. + * @{ + */ +#define CC2420_RAM_TXFIFO (0x0000) +#define CC2420_RAM_RXFIFO (0x0080) +#define CC2420_RAM_KEY0 (0x0100) +#define CC2420_RAM_RXNONCE (0x0110) +#define CC2420_RAM_RXCTR (0x0110) +#define CC2420_RAM_SABUF (0x0120) +#define CC2420_RAM_KEY1 (0x0130) +#define CC2420_RAM_TXNONCE (0x0140) +#define CC2420_RAM_TXCTR (0x0140) +#define CC2420_RAM_CBCSTATE (0x0150) +#define CC2420_RAM_IEEEADR (0x0160) +#define CC2420_RAM_PANID (0x0168) +#define CC2420_RAM_SHORTADR (0x016A) +/** @} */ + +/** + * @brief Status byte bit fields + * @see Datasheet section 13.3, page 29 + * @{ + */ +#define CC2420_STATUS_XOSC_STABLE (0x40) +#define CC2420_STATUS_TX_UNDERFLOW (0x20) +#define CC2420_STATUS_ENC_BUSY (0x10) +#define CC2420_STATUS_TX_ACTIVE (0x08) +#define CC2420_STATUS_PLL_LOCK (0x04) +#define CC2420_STATUS_RSSI_VALID (0x02) +/** @} */ + +/** + * @brief Modem control 0 register bitfields + * @{ + */ +#define CC2420_MDMCTRL0_RES_FRM (0x2000 +#define CC2420_MDMCTRL0_ADR_DECODE (0x0800) +#define CC2420_MDMCTRL0_PAN_COORD (0x1000) +#define CC2420_MDMCTRL0_AUTOCRC (0x0020) +#define CC2420_MDMCTRL0_AUTOACK (0x0010) +#define CC2420_MDMCTRL0_PREAMBLE_M (0x000f) +#define CC2420_MDMCTRL0_PREAMBLE_3B (0x0002) +/** @} */ + +/** + * @brief Transmit control register bitfields + * @{ + */ +#define CC2420_TXCTRL_PA_MASK (0x001f) +/** @} */ + +/** + * @brief Receive control register 1 bitfields + * @{ + */ +#define CC2420_RXCTRL1_RXBPF_LOCUR (0x2000) +/** @} */ + +/** + * @brief Frequency synthesizer control and status register bitfields + * @{ + */ +#define CC2420_FSCTRL_LOCK_THR_MASK (0xc000) +#define CC2420_FSCTRL_CAL_DONE (0x2000) +#define CC2420_FSCTRL_CAL_RUNNING (0x1000) +#define CC2420_FSCTRL_LOCK_LENGTH (0x0800) +#define CC2420_FSCTRL_LOCK_STATUS (0x0400) +#define CC2420_FSCTRL_FREQ_MASK (0x03ff) +/** @} */ + +/** + * @brief Security control register 0 bitfields + * @{ + */ +#define CC2420_SECCTRL0_RXFIFO_PROT (0x0200) +/** @} */ + +/** + * @brief Manufacturer ID low register value + */ +#define CC2420_MANFIDL_VAL (0x233d) + +/** + * @brief Manufacturer ID high register value + */ +#define CC2420_MANFIDH_VAL (0x3000) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/drivers/cc2420/include/cc2420_params.h b/drivers/cc2420/include/cc2420_params.h new file mode 100644 index 0000000000..77d901aa5a --- /dev/null +++ b/drivers/cc2420/include/cc2420_params.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2016 Freie Universität Berlin + * + * 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 drivers_cc2420 + * + * @{ + * @file + * @brief Default configuration for the CC2420 driver + * + * @author Hauke Petersen + */ + +#ifndef CC2420_PARAMS_H +#define CC2420_PARAMS_H + +#include "board.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Set default configuration parameters for the CC2420 driver + * @{ + */ +#ifndef CC2420_PARAM_SPI +#define CC2420_PARAM_SPI (SPI_0) +#endif +#ifndef CC2420_PARAM_SPI_CLK +#define CC2420_PARAM_SPI_CLK (SPI_SPEED_5MHZ) +#endif +#ifndef CC2420_PARAM_CS +#define CC2420_PARAM_CS (GPIO_PIN(0, 0)) +#endif +#ifndef CC2420_PARAM_FIFO +#define CC2420_PARAM_FIFO (GPIO_PIN(0, 1)) +#endif +#ifndef CC2420_PARAM_FIFOP +#define CC2420_PARAM_FIFOP (GPIO_PIN(0, 2)) +#endif +#ifndef CC2420_PARAM_CCA +#define CC2420_PARAM_CCA (GPIO_PIN(0, 3)) +#endif +#ifndef CC2420_PARAM_SFD +#define CC2420_PARAM_SFD (GPIO_PIN(0, 3)) +#endif +#ifndef CC2420_PARAM_VREFEN +#define CC2420_PARAM_VREFEN (GPIO_PIN(0, 3)) +#endif +#ifndef CC2420_PARAM_RESET +#define CC2420_PARAM_RESET (GPIO_PIN(0, 3)) +#endif + +#define CC2420_PARAMS_DEFAULT {.spi = CC2420_PARAM_SPI, \ + .spi_clk = CC2420_PARAM_SPI_CLK, \ + .pin_cs = CC2420_PARAM_CS, \ + .pin_fifo = CC2420_PARAM_FIFO, \ + .pin_fifop = CC2420_PARAM_FIFOP, \ + .pin_cca = CC2420_PARAM_CCA, \ + .pin_sfd = CC2420_PARAM_SFD, \ + .pin_vrefen = CC2420_PARAM_VREFEN, \ + .pin_reset = CC2420_PARAM_RESET} +/**@}*/ + +/** + * @brief CC2420 configuration + */ +static const cc2420_params_t cc2420_params[] = +{ +#ifdef CC2420_PARAMS_BOARD + CC2420_PARAMS_BOARD, +#else + CC2420_PARAMS_DEFAULT, +#endif +}; + +#ifdef __cplusplus +} +#endif + +#endif /* CC2420_PARAMS_H */ +/** @} */ diff --git a/drivers/include/cc2420.h b/drivers/include/cc2420.h new file mode 100644 index 0000000000..1baac59598 --- /dev/null +++ b/drivers/include/cc2420.h @@ -0,0 +1,311 @@ +/* + * Copyright (C) 2015-2016 Freie Universität Berlin + * + * 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 drivers_cc2420 CC2420 driver + * @ingroup drivers + * @brief Implementation of the CC2420 radio driver + * @{ + * + * @file + * @brief Interface definition for the CC2420 driver + * + * @author Thomas Eichinger + * @author Hauke Petersen + */ + +#ifndef CC2420_H +#define CC2420_H + +#include + +#include "periph/spi.h" +#include "periph/gpio.h" + +#include "net/netdev2.h" +#include "net/netdev2/ieee802154.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Maximum possible packet size in byte + */ +#define CC2420_PKT_MAXLEN (127U) + +/** + * @brief Default addresses used if the CPUID module is not present + * + * In case this address is used, that short address will be created by using the + * last two bytes of the long address. + * @{ + */ +#define CC2420_ADDR_FALLBACK {0x12, 0x22, 0x33, 0x44, 0x55, 0x66, 0x08, 0x15} +/** @} */ + +/** + * @brief PAN ID configuration + */ +#define CC2420_PANID_DEFAULT (0x0023) + +/** + * @brief Channel configuration + * @{ + */ +#define CC2420_CHAN_MIN (11U) +#define CC2420_CHAN_MAX (26U) +#define CC2420_CHAN_DEFAULT (26U) +/** @} */ + +/** + * @brief Default TX power configuration [in dBm] + * @{ + */ +#define CC2420_TXPOWER_MIN (-25) +#define CC2420_TXPOWER_MAX (0) +#define CC2420_TXPOWER_DEFAULT (0) +/** @} */ + +/** + * @brief A couple of return values used in this driver + */ +enum { + CC2420_RET_CHAN_OK = 2, +}; + +/** + * @brief Struct holding all parameters needed for device initialization + */ +typedef struct cc2420_params { + spi_t spi; /**< SPI bus the device is connected to */ + spi_speed_t spi_clk; /**< SPI speed to use */ + gpio_t pin_cs; /**< pin connected to chip select */ + gpio_t pin_fifo; /**< pin connected to the FIFO interrupt pin */ + gpio_t pin_fifop; /**< pin connected to the FIFOP interrupt pin */ + gpio_t pin_cca; /**< pin connected to CCA */ + gpio_t pin_sfd; /**< pin connected to 'start of frame delimiter' */ + gpio_t pin_vrefen; /**< pin connected to the Vref enable pin */ + gpio_t pin_reset; /**< pin connected to the reset pin */ +} cc2420_params_t; + +/** + * @brief Device descriptor for CC2420 radio devices + */ +typedef struct { + /* netdev fields */ + netdev2_ieee802154_t netdev; + /* device specific fields */ + cc2420_params_t params; /**< hardware interface configuration */ + /* device state fields */ + uint8_t state; /**< current state of the radio */ + uint16_t options; /**< state of used options */ +} cc2420_t; + +/** + * @brief Setup the device descriptor for the given device + * + * @param[out] dev device descriptor + * @param[in] params device parameters + * + * @return 0 on success + * @return -1 on error + */ +void cc2420_setup(cc2420_t *dev, const cc2420_params_t *params); + +/** + * @brief Initialize a given CC2420 device + * + * @param[out] dev device descriptor + * + * @return 0 on success + * @return <0 on error + */ +int cc2420_init(cc2420_t *dev); + +/** + * @brief Trigger a hardware reset and configure radio with default values + * + * @param[in] dev device to reset + * + * @return TODO + */ +int cc2420_reset(cc2420_t *dev); + +/** + * @brief Trigger a clear channel assessment + * + * @param[in] dev device to use + * + * @return true if channel is clear + * @return false if channel is busy + */ +bool cc2420_cca(cc2420_t *dev); + +/** + * @brief Get the short address of the given device + * + * @param[in] dev device to read from + * @param[out] addr memory to write the 2 byte address into + */ +void cc2420_get_addr_short(cc2420_t *dev, uint8_t *addr); + +/** + * @brief Set the short address of the given device + * + * @param[in] dev device to write to + * @param[in] addr (2-byte) short address to set + */ +void cc2420_set_addr_short(cc2420_t *dev, uint8_t *addr); + +/** + * @brief Get the configured long address of the given device + * + * @param[in] dev device to read from + * + * @return the currently set (8-byte) long address + */ +void cc2420_get_addr_long(cc2420_t *dev, uint8_t *addr_long); + +/** + * @brief Set the long address of the given device + * + * @param[in] dev device to write to + * @param[in] addr (8-byte) long address to set + */ +void cc2420_set_addr_long(cc2420_t *dev, uint8_t *addr_long); + +/** + * @brief Get the configured PAN ID of the given device + * + * @param[in] dev device to read from + * + * @return the currently set PAN ID + */ +uint16_t cc2420_get_pan(cc2420_t *dev); + +/** + * @brief Set the PAN ID of the given device + * + * @param[in] dev device to write to + * @param[in] pan PAN ID to set + */ +void cc2420_set_pan(cc2420_t *dev, uint16_t pan); + +/** + * @brief Get the configured channel of the given device + * + * @param[in] dev device to read from + * + * @return the currently set channel + */ +uint16_t cc2420_get_chan(cc2420_t *dev); + +/** + * @brief Set the channel of the given device + * + * @param[in] dev device to write to + * @param[in] chan channel to set + */ +int cc2420_set_chan(cc2420_t *dev, uint16_t chan); + +/** + * @brief Get the configured transmission power of the given device [in dBm] + * + * @param[in] dev device to read from + * + * @return configured transmission power in dBm + */ +int16_t cc2420_get_txpower(cc2420_t *dev); + +/** + * @brief Set the transmission power of the given device [in dBm] + * + * If the device does not support the exact dBm value given, it will set a value + * as close as possible to the given value. If the given value is larger or + * lower then the maximal or minimal possible value, the min or max value is + * set, respectively. + * + * @param[in] dev device to write to + * @param[in] txpower transmission power in dBm + */ +void cc2420_set_txpower(cc2420_t *dev, int16_t txpower); + +/** + * @brief Enable or disable driver specific options + * + * @param[in] dev device to set/clear option flag for + * @param[in] option option to enable/disable + * @param[in] state true for enable, false for disable + */ +int cc2420_set_option(cc2420_t *dev, uint16_t option, bool state); + +/** + * @brief Set the state of the given device (trigger a state change) + * + * @param[in] dev device to change state of + * @param[in] state the targeted new state + */ +int cc2420_set_state(cc2420_t *dev, netopt_state_t state); + +/** + * @brief Get the state of the given device + * + * @param[in] dev device to change state of + * + * @return the device's current state + */ +netopt_state_t cc2420_get_state(cc2420_t *dev); + +/** + * @brief Convenience function for simply sending data + * + * @note This function ignores the PRELOADING option + * + * @param[in] dev device to use for sending + * @param[in] data data to send (must include IEEE802.15.4 header) + * @param[in] len length of @p data + * + * @return number of bytes that were actually send + * @return 0 on error + */ +size_t cc2420_send(cc2420_t *dev, const struct iovec *data, int count); + +/** + * @brief Prepare for sending of data + * + * This function puts the given device into the TX state, so no receiving of + * data is possible after it was called. + * + * @param[in] dev device to prepare for sending + */ +size_t cc2420_tx_prepare(cc2420_t *dev, const struct iovec *data, int count); + +/** + * @brief Trigger sending of data previously loaded into transmit buffer + * + * @param[in] dev device to trigger + */ +void cc2420_tx_exec(cc2420_t *dev); + +/** + * @brief Read a chunk of data from the receive buffer of the given device + * + * @param[in] dev device to read from + * @param[out] data buffer to write data to + * @param[in] len number of bytes to read from device + * @param[in] offset offset in the receive buffer + */ +int cc2420_rx(cc2420_t *dev, uint8_t *buf, size_t max_len, void *info); + +#ifdef __cplusplus +} +#endif + +#endif /* CC2420_H */ +/** @} */ From 8d3cb3ace922f1729d3c51444cf65f847f949e0a Mon Sep 17 00:00:00 2001 From: Hauke Petersen Date: Thu, 14 Apr 2016 13:48:17 +0200 Subject: [PATCH 2/9] sys/auto_init: added initialization for cc2420 --- sys/auto_init/auto_init.c | 5 ++ sys/auto_init/netif/auto_init_cc2420.c | 78 ++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100644 sys/auto_init/netif/auto_init_cc2420.c diff --git a/sys/auto_init/auto_init.c b/sys/auto_init/auto_init.c index 5d50ff14f1..b5da2796ee 100644 --- a/sys/auto_init/auto_init.c +++ b/sys/auto_init/auto_init.c @@ -175,6 +175,11 @@ void auto_init(void) auto_init_at86rf2xx(); #endif +#ifdef MODULE_CC2420 + extern void auto_init_cc2420(void); + auto_init_cc2420(); +#endif + #ifdef MODULE_ENCX24J600 extern void auto_init_encx24j600(void); auto_init_encx24j600(); diff --git a/sys/auto_init/netif/auto_init_cc2420.c b/sys/auto_init/netif/auto_init_cc2420.c new file mode 100644 index 0000000000..c0b7d74fff --- /dev/null +++ b/sys/auto_init/netif/auto_init_cc2420.c @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2016 Freie Universität Berlin + * + * 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 auto_init_gnrc_netif + * @{ + * + * @file + * @brief Auto initialization for CC2420 network devices + * + * @author Hauke Petersen + */ + +#ifdef MODULE_CC2420 + +#include "board.h" +#include "net/gnrc/netdev2.h" +#include "net/gnrc/netdev2/ieee802154.h" +#include "net/gnrc.h" + +#include "cc2420.h" +#include "cc2420_params.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + +/** + * @brief MAC layer stack parameters + * @{ + */ +// #define STACKSIZE (THREAD_STACKSIZE_DEFAULT) +#define STACKSIZE (THREAD_STACKSIZE_MAIN) +#define PRIO (THREAD_PRIORITY_MAIN - 4) +/** @} */ + +/** + * @brief Get the number of configured CC2420 devices + */ +#define CC2420_NUMOF (sizeof(cc2420_params) / sizeof(cc2420_params[0])) + +/** + * @brief Allocate memory for dev descriptors, stacks, and 802.15.4 adaption + * @{ + */ +static cc2420_t devs[CC2420_NUMOF]; +static gnrc_netdev2_t adpt[CC2420_NUMOF]; +static char stacks[CC2420_NUMOF][STACKSIZE]; +/** @} */ + +void auto_init_cc2420(void) +{ + for (unsigned i = 0; i < CC2420_NUMOF; i++) { + DEBUG("Initializing CC2420 radios #%u\n", i); + + cc2420_setup(&devs[i], &cc2420_params[i]); + int res = gnrc_netdev2_ieee802154_init(&adpt[i], + (netdev2_ieee802154_t *)&devs[i]); + + if (res < 0) { + DEBUG("Error initializing CC2420 radio device!\n"); + } + else { + gnrc_netdev2_init(stacks[i], STACKSIZE, PRIO, "cc2420", &adpt[i]); + } + } +} + +#else +typedef int dont_be_pedantic; +#endif /* MODULE_CC2420 */ + +/** @} */ From 204702897b77210dde98fb00708d5421c6592bb3 Mon Sep 17 00:00:00 2001 From: Hauke Petersen Date: Thu, 14 Apr 2016 13:44:57 +0200 Subject: [PATCH 3/9] boards/z1: add support for CC2420 radio --- boards/z1/Makefile.dep | 3 +++ boards/z1/Makefile.include | 3 +++ boards/z1/include/board.h | 13 +++++++++++++ 3 files changed, 19 insertions(+) create mode 100644 boards/z1/Makefile.dep diff --git a/boards/z1/Makefile.dep b/boards/z1/Makefile.dep new file mode 100644 index 0000000000..9c00f92efc --- /dev/null +++ b/boards/z1/Makefile.dep @@ -0,0 +1,3 @@ +ifneq (,$(filter gnrc_netdev_default netdev_default,$(USEMODULE))) + USEMODULE += cc2420 +endif diff --git a/boards/z1/Makefile.include b/boards/z1/Makefile.include index fa3dea543c..4cfb447176 100644 --- a/boards/z1/Makefile.include +++ b/boards/z1/Makefile.include @@ -8,6 +8,9 @@ PORT_DARWIN ?= $(firstword $(sort $(wildcard /dev/tty.SLAB_USBtoUART*))) # setup serial terminal include $(RIOTBOARD)/Makefile.include.serial +# setup the boards dependencies +include $(RIOTBOARD)/$(BOARD)/Makefile.dep + # setup flash tool export OFLAGS = -O ihex export FLASHER = $(RIOTBASE)/dist/tools/goodfet/goodfet.bsl diff --git a/boards/z1/include/board.h b/boards/z1/include/board.h index 4698181e04..fef9bad859 100644 --- a/boards/z1/include/board.h +++ b/boards/z1/include/board.h @@ -116,6 +116,19 @@ extern "C" { #define USER_BTN_RELEASED ((USER_BTN_PxIN & USER_BTN_MASK) != 0) /** @} */ +/** + * @brief Definition of the interface to the CC2420 radio + */ +#define CC2420_PARAMS_BOARD {.spi = SPI_0, \ + .spi_clk = SPI_SPEED_1MHZ, \ + .pin_cs = GPIO_PIN(P3, 0), \ + .pin_fifo = GPIO_PIN(P1, 3), \ + .pin_fifop = GPIO_PIN(P1, 2), \ + .pin_cca = GPIO_PIN(P1, 4), \ + .pin_sfd = GPIO_PIN(P4, 1), \ + .pin_vrefen = GPIO_PIN(P4, 5), \ + .pin_reset = GPIO_PIN(P4, 6)} + #ifdef __cplusplus } #endif From dfe52cfd8c7e9acf850c9de683eaaa750bd85c72 Mon Sep 17 00:00:00 2001 From: Hauke Petersen Date: Wed, 13 Apr 2016 16:38:30 +0200 Subject: [PATCH 4/9] boards/telosb: added support for CC2420 --- boards/telosb/Makefile.dep | 3 +++ boards/telosb/Makefile.features | 1 + boards/telosb/Makefile.include | 3 +++ 3 files changed, 7 insertions(+) create mode 100644 boards/telosb/Makefile.dep diff --git a/boards/telosb/Makefile.dep b/boards/telosb/Makefile.dep new file mode 100644 index 0000000000..9c00f92efc --- /dev/null +++ b/boards/telosb/Makefile.dep @@ -0,0 +1,3 @@ +ifneq (,$(filter gnrc_netdev_default netdev_default,$(USEMODULE))) + USEMODULE += cc2420 +endif diff --git a/boards/telosb/Makefile.features b/boards/telosb/Makefile.features index be3115c5de..57c25ac5c4 100644 --- a/boards/telosb/Makefile.features +++ b/boards/telosb/Makefile.features @@ -1,5 +1,6 @@ # Put defined MCU peripherals here (in alphabetical order) FEATURES_PROVIDED += periph_gpio +FEATURES_PROVIDED += periph_spi FEATURES_PROVIDED += periph_timer FEATURES_PROVIDED += periph_uart diff --git a/boards/telosb/Makefile.include b/boards/telosb/Makefile.include index c84cacd0bd..71e7292ed9 100644 --- a/boards/telosb/Makefile.include +++ b/boards/telosb/Makefile.include @@ -9,6 +9,9 @@ PORT_DARWIN ?= $(firstword $(sort $(wildcard /dev/tty.usbserial-MXV*))) export BAUD ?= 9600 include $(RIOTBOARD)/Makefile.include.serial +# setup the boards dependencies +include $(RIOTBOARD)/$(BOARD)/Makefile.dep + # flash tool configuration export OFLAGS = -O ihex export FLASHER = $(RIOTBASE)/dist/tools/goodfet/goodfet.bsl From 32be958eebb602562b35df9342981512edffad84 Mon Sep 17 00:00:00 2001 From: Hauke Petersen Date: Thu, 14 Apr 2016 13:45:32 +0200 Subject: [PATCH 5/9] examples/default: add z1 and telosb for radio --- examples/default/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/default/Makefile b/examples/default/Makefile index ec34ee23ca..266a5d0ab9 100644 --- a/examples/default/Makefile +++ b/examples/default/Makefile @@ -39,7 +39,7 @@ USEMODULE += auto_init_saul BOARD_PROVIDES_NETIF := airfy-beacon fox iotlab-m3 iotlab-a8-m3 mulle native nrf51dongle \ nrf6310 pba-d-01-kw2x pca10000 pca10005 saml21-xpro samr21-xpro spark-core \ - yunjia-nrf51822 + telosb yunjia-nrf51822 z1 ifneq (,$(filter $(BOARD),$(BOARD_PROVIDES_NETIF))) # Use modules for networking From 62d8b9a2683459eb51c23dc6b69c8e3ef4d5ba80 Mon Sep 17 00:00:00 2001 From: kYc0o Date: Fri, 1 Jul 2016 15:31:10 +0200 Subject: [PATCH 6/9] drivers/cc2420: factorise/reorganise overall code --- drivers/cc2420/cc2420.c | 732 ++-------------------- drivers/cc2420/cc2420_getset.c | 312 +++++++++ drivers/cc2420/cc2420_internal.c | 133 ++++ drivers/cc2420/cc2420_netdev.c | 308 +++++++++ drivers/cc2420/include/cc2420_internal.h | 246 ++------ drivers/cc2420/include/cc2420_netdev.h | 41 ++ drivers/cc2420/include/cc2420_registers.h | 241 +++++++ 7 files changed, 1147 insertions(+), 866 deletions(-) create mode 100644 drivers/cc2420/cc2420_getset.c create mode 100644 drivers/cc2420/cc2420_internal.c create mode 100644 drivers/cc2420/cc2420_netdev.c create mode 100644 drivers/cc2420/include/cc2420_netdev.h create mode 100644 drivers/cc2420/include/cc2420_registers.h diff --git a/drivers/cc2420/cc2420.c b/drivers/cc2420/cc2420.c index 22258e0e3d..12678f0dec 100644 --- a/drivers/cc2420/cc2420.c +++ b/drivers/cc2420/cc2420.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2015-2016 Freie Universität Berlin + * 2016 Inria * * 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 @@ -11,7 +12,7 @@ * @{ * * @file - * @brief Implementation of public functions for CC2420 driver + * @brief Implementation of public functions for cc2420 driver * * @author Thomas Eichinger * @author Hauke Petersen @@ -19,202 +20,18 @@ * @} */ -#include "board.h" -#include "xtimer.h" #include "periph/cpuid.h" #include "byteorder.h" -#include "panic.h" #include "net/ieee802154.h" #include "net/gnrc.h" -#include "cc2420.h" #include "cc2420_internal.h" +#include "cc2420_netdev.h" +#include "cc2420_registers.h" -#define ENABLE_DEBUG (0) +#define ENABLE_DEBUG (0) #include "debug.h" -/** - * @brief Some constant hardware configuration values - */ -#define SPI_MODE (SPI_CONF_FIRST_RISING) - -extern const netdev2_driver_t cc2420_driver; - -/** - * @brief Translation from dBm to PA level - * - * Entry 0 in the array corresponds to -25dBm (min), entry 25 to 0dBm (max), so - * `PA_level = power_dbm_to_pa[DBM + 25]`. We use only the 3 MSB of the 5-bit - * level, leading to 8 distinct power settings (the 8 settings listed in the - * datasheet in section 28, page 51). - */ -static const uint8_t power_dbm_to_pa[26] = { - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 7, 7, - 7, 7, 11, 11, 11, 15, 15, 19, 19, 23, 23, 27, 31 -}; - -/** - * @brief Translate PA level to dBm - * - * As we use only the 3 MSB of the PA level value, we have 8 distinct settings. - * We get the dBm value with `DBM = power_pa_to_dbm(PA >> 2). - */ -static const int8_t power_pa_to_dbm[8] = { - -25, -15, -10, -7, -5, -3, -1, 0 -}; - - -static inline uint16_t to_u16(void *buf) -{ - return *((uint16_t *)buf); -} - -static inline int16_t to_i16(void *buf) -{ - return *((int16_t *)buf); -} - -static inline bool to_bool(void *buf) -{ - return *((bool *)buf); -} - -static inline int w_u16(void *buf, uint16_t val) -{ - memcpy(buf, &val, sizeof(uint16_t)); - return sizeof(uint16_t); -} - -static inline int w_i16(void *buf, int16_t val) -{ - memcpy(buf, &val, sizeof(int16_t)); - return sizeof(int16_t); -} - -static inline int opt_state(void *buf, bool cond) -{ - *((netopt_enable_t *)buf) = !!(cond); - return sizeof(netopt_enable_t); -} - - -static uint8_t strobe(const cc2420_t *dev, const uint8_t command) -{ - char res; - - spi_acquire(dev->params.spi); - gpio_clear(dev->params.pin_cs); - spi_transfer_byte(dev->params.spi, (char)command, (char *)&res); - gpio_set(dev->params.pin_cs); - spi_release(dev->params.spi); - - return res; -} - -static void reg_write(const cc2420_t *dev, - const uint8_t addr, - const uint16_t value) -{ - uint16_t tmp = byteorder_htons(value).u16; - - spi_acquire(dev->params.spi); - gpio_clear(dev->params.pin_cs); - spi_transfer_regs(dev->params.spi, CC2420_REG_WRITE | addr, - (char *)&tmp, NULL, 2); - gpio_set(dev->params.pin_cs); - spi_release(dev->params.spi); -} - -static uint16_t reg_read(const cc2420_t *dev, const uint8_t addr) -{ - network_uint16_t tmp; - - spi_acquire(dev->params.spi); - gpio_clear(dev->params.pin_cs); - spi_transfer_regs(dev->params.spi, CC2420_REG_READ | addr, - NULL, (char *)&tmp, 2); - gpio_set(dev->params.pin_cs); - spi_release(dev->params.spi); - - return byteorder_ntohs(tmp); -} - -static void ram_read(const cc2420_t *dev, const uint16_t addr, - uint8_t *data, const size_t len) -{ - char tmp[] = { (CC2420_RAM | (addr & 0x7f)), - (CC2420_RAM_READ | ((addr >> 1) & 0xc0)) }; - - spi_acquire(dev->params.spi); - gpio_clear(dev->params.pin_cs); - spi_transfer_bytes(dev->params.spi, tmp, NULL, 2); - spi_transfer_bytes(dev->params.spi, NULL, (char*)data, len); - gpio_set(dev->params.pin_cs); - spi_release(dev->params.spi); -} - -static void ram_write(const cc2420_t *dev, const uint16_t addr, - const uint8_t *data, const size_t len) -{ - char tmp[] = { (CC2420_RAM | (addr & 0x7f)), - (CC2420_RAM_WRITE | ((addr >> 1) & 0xc0)) }; - - spi_acquire(dev->params.spi); - gpio_clear(dev->params.pin_cs); - spi_transfer_bytes(dev->params.spi, tmp, NULL, 2); - spi_transfer_bytes(dev->params.spi, (char*)data, NULL, len); - gpio_set(dev->params.pin_cs); - spi_release(dev->params.spi); -} - -static void fifo_read(const cc2420_t *dev, uint8_t *data, const size_t len) -{ - spi_acquire(dev->params.spi); - gpio_clear(dev->params.pin_cs); - spi_transfer_regs(dev->params.spi, CC2420_FIFO_READ, - NULL, (char *)data, len); - gpio_set(dev->params.pin_cs); - spi_release(dev->params.spi); -} - -static void fifo_write(const cc2420_t *dev, uint8_t *data, const size_t len) -{ - spi_acquire(dev->params.spi); - gpio_clear(dev->params.pin_cs); - spi_transfer_regs(dev->params.spi, CC2420_FIFO_WRITE, - (char *)data, NULL, len); - gpio_set(dev->params.pin_cs); - spi_release(dev->params.spi); -} - -/** - * @brief Get the device's status byte - */ -static inline uint8_t status(cc2420_t *dev) -{ - return strobe(dev, CC2420_STROBE_NOP); -} - -/** - * @brief Get the device's current state - */ -static inline uint8_t state(cc2420_t *dev) -{ - return (uint8_t)reg_read(dev, CC2420_REG_FSMSTATE); -} - -static inline void en_xosc(cc2420_t *dev) -{ - strobe(dev, CC2420_STROBE_XOSCON); - xtimer_usleep(CC2420_XOSCON_DELAY); -} - -static void fifop_evt(void *arg) -{ - netdev2_t *dev = (netdev2_t *)arg; - dev->event_callback(dev, NETDEV2_EVENT_ISR, NULL); -} - /** * @todo Move this function to a global module */ @@ -250,13 +67,12 @@ void cc2420_setup(cc2420_t * dev, const cc2420_params_t *params) { /* set pointer to the devices netdev functions */ dev->netdev.netdev.driver = &cc2420_driver; - /* TODO: remove once the netdev2/802154 shit is cleaned up */ - dev->netdev.seq = 0; - dev->netdev.flags = NETDEV2_IEEE802154_PAN_COMP; /* pull in device configuration parameters */ memcpy(&dev->params, params, sizeof(cc2420_params_t)); + dev->state = CC2420_STATE_IDLE; /* reset device descriptor fields */ dev->options = 0; + spi_init_master(dev->params.spi, SPI_CONF_FIRST_RISING, dev->params.spi_clk); } int cc2420_init(cc2420_t *dev) @@ -264,42 +80,9 @@ int cc2420_init(cc2420_t *dev) uint16_t reg; uint8_t addr[8] = CC2420_ADDR_FALLBACK; - /* initialize power and reset pins -> put the device into reset state */ - gpio_init(dev->params.pin_reset, GPIO_OUT); - gpio_set(dev->params.pin_reset); - gpio_init(dev->params.pin_vrefen, GPIO_OUT); - gpio_clear(dev->params.pin_vrefen); - - /* initialize the input lines */ - gpio_init(dev->params.pin_cca, GPIO_IN); - gpio_init(dev->params.pin_sfd, GPIO_IN); - gpio_init(dev->params.pin_fifo, GPIO_IN); - gpio_init_int(dev->params.pin_fifop, GPIO_IN, GPIO_RISING, fifop_evt, dev); - - /* initialize the chip select line and the SPI bus */ - gpio_init(dev->params.pin_cs, GPIO_OUT); - gpio_set(dev->params.pin_cs); - spi_init_master(dev->params.spi, SPI_MODE, dev->params.spi_clk); - - /* power on and toggle reset */ - gpio_set(dev->params.pin_vrefen); - gpio_clear(dev->params.pin_reset); - xtimer_usleep(CC2420_RESET_DELAY); - gpio_set(dev->params.pin_reset); - - /* test the connection to the device by reading MANFIDL register */ - reg = reg_read(dev, CC2420_REG_MANFIDL); - if (reg != CC2420_MANFIDL_VAL) { - DEBUG("[cc2420] init: unable to communicate with device\n"); - return -1; - } - - /* turn on the oscillator and wait for it to be stable */ - en_xosc(dev); - if (!(status(dev) & CC2420_STATUS_XOSC_STABLE)) { - DEBUG("[cc2420] init: oscillator did not stabilize\n"); - return -1; - } + /* reset options and sequence number */ + dev->netdev.seq = 0; + dev->netdev.flags = 0; /* set default address, channel, PAN ID, and TX power */ #if CPUID_ID_LEN @@ -318,283 +101,45 @@ int cc2420_init(cc2420_t *dev) cc2420_set_option(dev, CC2420_OPT_TELL_TX_START, true); cc2420_set_option(dev, CC2420_OPT_TELL_RX_END, true); +#ifdef MODULE_NETSTATS_L2 + cc2420_set_option(dev, CC2420_OPT_TELL_RX_END, true); +#endif + /* set default protocol*/ +#ifdef MODULE_GNRC_SIXLOWPAN + dev->netdev.proto = GNRC_NETTYPE_SIXLOWPAN; +#elif MODULE_GNRC + dev->netdev.proto = GNRC_NETTYPE_UNDEF; +#endif + /* change default RX bandpass filter to 1.3uA (as recommended) */ - reg = reg_read(dev, CC2420_REG_RXCTRL1); + reg = cc2420_reg_read(dev, CC2420_REG_RXCTRL1); reg |= CC2420_RXCTRL1_RXBPF_LOCUR; - reg_write(dev, CC2420_REG_RXCTRL1, reg); + cc2420_reg_write(dev, CC2420_REG_RXCTRL1, reg); /* set the FIFOP threshold to maximum. */ - reg_write(dev, CC2420_REG_IOCFG0, CC2420_PKT_MAXLEN); + cc2420_reg_write(dev, CC2420_REG_IOCFG0, CC2420_PKT_MAXLEN); /* turn off "Security enable" (page 33). */ - reg = reg_read(dev, CC2420_REG_SECCTRL0); + reg = cc2420_reg_read(dev, CC2420_REG_SECCTRL0); reg &= ~CC2420_SECCTRL0_RXFIFO_PROT; - reg_write(dev, CC2420_REG_SECCTRL0, reg); + cc2420_reg_write(dev, CC2420_REG_SECCTRL0, reg); /* go into RX state */ cc2420_set_state(dev, CC2420_GOTO_RX); /* set preamble length to 3 leading zero byte */ - reg = reg_read(dev, CC2420_REG_MDMCTRL0); + reg = cc2420_reg_read(dev, CC2420_REG_MDMCTRL0); reg &= ~(CC2420_MDMCTRL0_PREAMBLE_M); reg |= CC2420_MDMCTRL0_PREAMBLE_3B; - reg_write(dev, CC2420_REG_MDMCTRL0, reg); + cc2420_reg_write(dev, CC2420_REG_MDMCTRL0, reg); return 0; } -void cc2420_get_addr_short(cc2420_t *dev, uint8_t *addr) -{ - uint8_t tmp[2]; - - ram_read(dev, CC2420_RAM_SHORTADR, tmp, 2); - - addr[0] = tmp[1]; - addr[1] = tmp[0]; -} - -void cc2420_set_addr_short(cc2420_t *dev, uint8_t *addr) -{ - uint8_t tmp[2]; - tmp[0] = addr[1]; - tmp[1] = addr[0]; - - ram_write(dev, CC2420_RAM_SHORTADR, tmp, 2); - - /* TODO: remove after 802.15.4 / netdev2 cleanup */ - memcpy(dev->netdev.short_addr, addr, 2); -} - -void cc2420_get_addr_long(cc2420_t *dev, uint8_t *addr) -{ - ram_read(dev, CC2420_RAM_IEEEADR, addr, 8); -} - -void cc2420_set_addr_long(cc2420_t *dev, uint8_t *addr) -{ - ram_write(dev, CC2420_RAM_IEEEADR, addr, 8); - - /* TODO: remove after 802.15.4 / netdev2 cleanup */ - memcpy(dev->netdev.long_addr, addr, 8); -} - -uint16_t cc2420_get_pan(cc2420_t *dev) -{ - le_uint16_t pan; - - ram_read(dev, CC2420_RAM_PANID, pan.u8, 2); - return pan.u16; -} - -void cc2420_set_pan(cc2420_t *dev, uint16_t pan) -{ - ram_write(dev, CC2420_RAM_PANID, (uint8_t *)&pan, 2); - - /* TODO: remove after 802.15.4 / netdev2 cleanup */ - dev->netdev.pan = pan; -} - -uint16_t cc2420_get_chan(cc2420_t *dev) -{ - uint16_t chan; - uint16_t freq = reg_read(dev, CC2420_REG_FSCTRL); - - chan = (((freq & CC2420_FSCTRL_FREQ_MASK) - 357) / 5) + 11; - return chan; -} - -int cc2420_set_chan(cc2420_t *dev, uint16_t chan) -{ - if ((chan < CC2420_CHAN_MIN) || (chan > CC2420_CHAN_MAX)) { - DEBUG("[cc2420] set channel: given channel invalid\n"); - return -ENOTSUP; - } - - /* calculation from http://www.ti.com/lit/ds/symlink/cc2420.pdf p.50 */ - uint16_t freq = reg_read(dev, CC2420_REG_FSCTRL); - freq &= ~CC2420_FSCTRL_FREQ_MASK; - freq |= (357 + (5 * (chan - 11))); - reg_write(dev, CC2420_REG_FSCTRL, freq); - - /* TODO: remove after 802.15.4 / netdev2 cleanup */ - dev->netdev.chan = chan; - - return CC2420_RET_CHAN_OK; -} - -int16_t cc2420_get_txpower(cc2420_t *dev) -{ - uint16_t txctrl = reg_read(dev, CC2420_REG_TXCTRL); - return (int16_t)power_pa_to_dbm[(txctrl & CC2420_TXCTRL_PA_MASK) >> 2]; -} - -void cc2420_set_txpower(cc2420_t *dev, int16_t txpower) -{ - if (txpower > CC2420_TXPOWER_MAX) { - txpower = CC2420_TXPOWER_MAX; - } - else if (txpower < CC2420_TXPOWER_MIN) { - txpower = CC2420_TXPOWER_MIN; - } - - uint16_t txctrl = reg_read(dev, CC2420_REG_TXCTRL); - txctrl &= ~(CC2420_TXCTRL_PA_MASK); - txctrl |= power_dbm_to_pa[txpower + 25]; - reg_write(dev, CC2420_REG_TXCTRL, txctrl); -} - -int cc2420_set_option(cc2420_t *dev, uint16_t option, bool state) -{ - uint16_t reg; - - /* set option field */ - if (state) { - dev->options |= option; - /* trigger option specific actions */ - switch (option) { - case CC2420_OPT_AUTOACK: - DEBUG("[cc2420] set_opt: CC2420_OPT_AUTOACK\n"); - reg = reg_read(dev, CC2420_REG_MDMCTRL0); - reg |= CC2420_MDMCTRL0_AUTOACK; - reg_write(dev, CC2420_REG_MDMCTRL0, reg); - /* TODO: remove after netdev2 cleanup */ - dev->netdev.flags |= NETDEV2_IEEE802154_ACK_REQ; - break; - - case CC2420_OPT_CSMA: - DEBUG("[cc2420] set_opt: CC2420_OPT_CSMA\n"); - /* TODO: en/disable csma */ - break; - - case CC2420_OPT_PROMISCUOUS: - DEBUG("[cc2420] set_opt: CC2420_OPT_PROMISCUOUS\n"); - /* in promisc mode, AUTO ACKs are should be disabled */ - reg = reg_read(dev, CC2420_REG_MDMCTRL0); - reg &= ~(CC2420_MDMCTRL0_AUTOACK); - reg &= ~(CC2420_MDMCTRL0_ADR_DECODE); - reg_write(dev, CC2420_REG_MDMCTRL0, reg); - break; - - case CC2420_OPT_PRELOADING: - DEBUG("[cc2420] set_opt: CC2420_OPT_PRELOADING\n"); - break; - - case CC2420_OPT_TELL_TX_START: - case CC2420_OPT_TELL_TX_END: - case CC2420_OPT_TELL_RX_START: - case CC2420_OPT_TELL_RX_END: - DEBUG("[cc2420] set_opt: TX/RX START/END\n"); - break; - - default: - return -ENOTSUP; - } - } - else { - dev->options &= ~(option); - /* trigger option specific actions */ - switch (option) { - case CC2420_OPT_AUTOACK: - DEBUG("[cc2420] clr_opt: CC2420_OPT_AUTOACK\n"); - reg = reg_read(dev, CC2420_REG_MDMCTRL0); - reg &= ~(CC2420_MDMCTRL0_AUTOACK); - reg_write(dev, CC2420_REG_MDMCTRL0, reg); - /* TODO: remove after netdev cleanup */ - dev->netdev.flags &= ~(NETDEV2_IEEE802154_ACK_REQ); - break; - - case CC2420_OPT_CSMA: - DEBUG("[cc2420] clr_opt: CC2420_OPT_CSMA\n"); - /* TODO: en/disable csma */ - break; - - case CC2420_OPT_PROMISCUOUS: - DEBUG("[cc2420] clr_opt: CC2420_OPT_PROMISCUOUS\n"); - reg = reg_read(dev, CC2420_REG_MDMCTRL0); - reg |= CC2420_MDMCTRL0_ADR_DECODE; - /* re-enable AUTOACK only if the option was set */ - if (dev->options & CC2420_OPT_AUTOACK) { - reg |= CC2420_MDMCTRL0_AUTOACK; - } - reg_write(dev, CC2420_REG_MDMCTRL0, reg); - break; - - case CC2420_OPT_PRELOADING: - DEBUG("[cc2420] clr_opt: CC2420_OPT_PRELOADING\n"); - break; - - case CC2420_OPT_TELL_TX_START: - case CC2420_OPT_TELL_TX_END: - case CC2420_OPT_TELL_RX_START: - case CC2420_OPT_TELL_RX_END: - DEBUG("[cc2420] clr_opt: TX/RX START/END\n"); - /* TODO */ - break; - - default: - return -ENOTSUP; - } - } - return sizeof(netopt_enable_t); -} - -int cc2420_set_state(cc2420_t *dev, netopt_state_t cmd) -{ - if ((cc2420_get_state(dev) == NETOPT_STATE_OFF) && - (cmd != NETOPT_STATE_OFF)) { - en_xosc(dev); - } - switch (cmd) { - case NETOPT_STATE_OFF: - strobe(dev, CC2420_STROBE_XOSCOFF); - while (state(dev) != CC2420_STATE_PD) {} - break; - case NETOPT_STATE_SLEEP: - strobe(dev, CC2420_STROBE_RFOFF); - while (state(dev) != CC2420_STATE_IDLE) {} - break; - case NETOPT_STATE_IDLE: - strobe(dev, CC2420_STROBE_FLUSHRX); - strobe(dev, CC2420_STROBE_RXON); - break; - case NETOPT_STATE_TX: - cc2420_tx_exec(dev); - break; - case NETOPT_STATE_RESET: - cc2420_init(dev); - break; - case NETOPT_STATE_RX: - default: - DEBUG("[cc2420] set_state: called with invalid target state\n"); - return -ENOTSUP; - } - return sizeof(netopt_state_t); -} - -netopt_state_t cc2420_get_state(cc2420_t *dev) -{ - uint8_t cur_state = state(dev); - - if (cur_state == 0) { - return NETOPT_STATE_OFF; - } - else if (cur_state == 1) { - return NETOPT_STATE_SLEEP; - } - else if (((cur_state >= 32) && (cur_state <=39)) || (cur_state == 56)) { - return NETOPT_STATE_TX; - } - else if ((cur_state >= 3) && (cur_state <= 6)) { - return NETOPT_STATE_IDLE; - } - else { - return NETOPT_STATE_RX; - } -} bool cc2420_cca(cc2420_t *dev) { - while (!(status(dev) & CC2420_STATUS_RSSI_VALID)) {} + while (!(cc2420_status(dev) & CC2420_STATUS_RSSI_VALID)) {} return gpio_read(dev->params.pin_cca); } @@ -621,19 +166,19 @@ size_t cc2420_tx_prepare(cc2420_t *dev, const struct iovec *data, int count) pkt_len += data[i].iov_len; } if (pkt_len >= CC2420_PKT_MAXLEN) { - DEBUG("[cc2420] tx_prep: unable to send, pkt too large\n"); + DEBUG("cc2420: tx_prep: unable to send, pkt too large\n"); return 0; } /* flush TX FIFO and write new packet to it */ - strobe(dev, CC2420_STROBE_FLUSHTX); + cc2420_strobe(dev, CC2420_STROBE_FLUSHTX); /* push packet length to TX FIFO */ - fifo_write(dev, (uint8_t *)&pkt_len, 1); + cc2420_fifo_write(dev, (uint8_t *)&pkt_len, 1); /* push packet to TX FIFO */ for (int i = 0; i < count; i++) { - fifo_write(dev, (uint8_t *)data[i].iov_base, data[i].iov_len); + cc2420_fifo_write(dev, (uint8_t *)data[i].iov_base, data[i].iov_len); } - DEBUG("[cc2420] tx_prep: loaded %i byte into the TX FIFO\n", (int)pkt_len); + DEBUG("cc2420: tx_prep: loaded %i byte into the TX FIFO\n", (int)pkt_len); return pkt_len; } @@ -641,21 +186,21 @@ size_t cc2420_tx_prepare(cc2420_t *dev, const struct iovec *data, int count) void cc2420_tx_exec(cc2420_t *dev) { /* make sure, any ongoing transmission is finished */ - DEBUG("[cc2420] tx_exec: waiting for any ongoing transmission\n"); + DEBUG("cc2420: tx_exec: waiting for any ongoing transmission\n"); while (cc2420_get_state(dev) & NETOPT_STATE_TX) {} /* trigger the transmission */ if (dev->options & CC2420_OPT_TELL_TX_START) { dev->netdev.netdev.event_callback(&dev->netdev.netdev, - NETDEV2_EVENT_TX_STARTED, dev); + NETDEV2_EVENT_TX_STARTED); } - DEBUG("[cc2420] tx_exec: TX_START\n"); + DEBUG("cc2420: tx_exec: TX_START\n"); if (dev->options & CC2420_OPT_CSMA) { - DEBUG("[cc2420] tx_exec: triggering TX with CCA\n"); - strobe(dev, CC2420_STROBE_TXONCCA); + DEBUG("cc2420: tx_exec: triggering TX with CCA\n"); + cc2420_strobe(dev, CC2420_STROBE_TXONCCA); } else { - DEBUG("[cc2420] tx_exec: triggering TX without CCA\n"); - strobe(dev, CC2420_STROBE_TXON); + DEBUG("cc2420: tx_exec: triggering TX without CCA\n"); + cc2420_strobe(dev, CC2420_STROBE_TXON); } while (gpio_read(dev->params.pin_sfd)) { @@ -663,9 +208,9 @@ void cc2420_tx_exec(cc2420_t *dev) } if (dev->options & CC2420_OPT_TELL_TX_END) { dev->netdev.netdev.event_callback(&dev->netdev.netdev, - NETDEV2_EVENT_TX_COMPLETE, dev); + NETDEV2_EVENT_TX_COMPLETE); } - DEBUG("[cc2420] tx_exec: TX_DONE\n"); + DEBUG("cc2420: tx_exec: TX_DONE\n"); } int cc2420_rx(cc2420_t *dev, uint8_t *buf, size_t max_len, void *info) @@ -673,11 +218,11 @@ int cc2420_rx(cc2420_t *dev, uint8_t *buf, size_t max_len, void *info) uint8_t len; /* get the packet length (without dropping it) (first byte in RX FIFO */ - ram_read(dev, CC2420_RAM_RXFIFO, &len, 1); + cc2420_ram_read(dev, CC2420_RAM_RXFIFO, &len, 1); len -= 2; /* subtract RSSI and FCF */ if (!buf) { - DEBUG("[cc2420] recv: packet of length %i in RX FIFO\n", (int)len); + DEBUG("cc2420: recv: packet of length %i in RX FIFO\n", (int)len); } /* if a buffer is given, read (and drop) the packet */ @@ -685,193 +230,18 @@ int cc2420_rx(cc2420_t *dev, uint8_t *buf, size_t max_len, void *info) len = (len > max_len) ? max_len : len; /* drop length byte */ - fifo_read(dev, NULL, 1); + cc2420_fifo_read(dev, NULL, 1); /* read fifo contents */ - DEBUG("[cc2420] recv: reading %i byte of the packet\n", (int)len); - fifo_read(dev, buf, len); + DEBUG("cc2420: recv: reading %i byte of the packet\n", (int)len); + cc2420_fifo_read(dev, buf, len); uint8_t rssi; - fifo_read(dev, &rssi, 1); - DEBUG("[cc2420] recv: RSSI is %i\n", (int)rssi); + cc2420_fifo_read(dev, &rssi, 1); + DEBUG("cc2420: recv: RSSI is %i\n", (int)rssi); /* finally flush the FIFO */ - strobe(dev, CC2420_STROBE_FLUSHRX); - strobe(dev, CC2420_STROBE_FLUSHRX); + cc2420_strobe(dev, CC2420_STROBE_FLUSHRX); + cc2420_strobe(dev, CC2420_STROBE_FLUSHRX); } return (int)len; } - -static int init(netdev2_t *dev) -{ - return cc2420_init((cc2420_t *)dev); -} - -static void isr(netdev2_t *netdev) -{ - netdev->event_callback(netdev, NETDEV2_EVENT_RX_COMPLETE, NULL); -} - -static int send(netdev2_t *netdev, const struct iovec *vector, int count) -{ - cc2420_t *dev = (cc2420_t *)netdev; - return (int)cc2420_send(dev, vector, count); -} - -static int recv(netdev2_t *netdev, char *buf, int len, void *info) -{ - cc2420_t *dev = (cc2420_t *)netdev; - return (int)cc2420_rx(dev, (uint8_t *)buf, len, info); -} - -static int get(netdev2_t *netdev, netopt_t opt, void *val, size_t max_len) -{ - if (netdev == NULL) { - return -ENODEV; - } - - cc2420_t *dev = (cc2420_t *)netdev; - - int ext = netdev2_ieee802154_get(&dev->netdev, opt, val, max_len); - if (ext > 0) { - return ext; - } - - switch (opt) { - - case NETOPT_ADDRESS: - assert(max_len >= sizeof(uint16_t)); - cc2420_get_addr_short(dev, val); - return sizeof(uint16_t); - - case NETOPT_ADDRESS_LONG: - assert(max_len >= 8); - cc2420_get_addr_long(dev, val); - return 8; - - case NETOPT_NID: - assert(max_len >= sizeof(uint16_t)); - return w_u16(val, cc2420_get_pan(dev)); - - case NETOPT_CHANNEL: - assert(max_len >= sizeof(uint16_t)); - return w_u16(val, cc2420_get_chan(dev)); - - case NETOPT_TX_POWER: - assert(max_len >= sizeof(int16_t)); - return w_i16(val, cc2420_get_txpower(dev)); - - case NETOPT_STATE: - assert(max_len >= sizeof(netopt_state_t)); - *((netopt_state_t *)val) = cc2420_get_state(dev); - return sizeof(netopt_state_t); - - case NETOPT_IS_CHANNEL_CLR: - return opt_state(val, cc2420_cca(dev)); - - case NETOPT_AUTOACK: - return opt_state(val, (dev->options & CC2420_OPT_AUTOACK)); - - case NETOPT_CSMA: - return opt_state(val, (dev->options & CC2420_OPT_CSMA)); - - case NETOPT_PRELOADING: - return opt_state(val, (dev->options & CC2420_OPT_PRELOADING)); - - case NETOPT_PROMISCUOUSMODE: - return opt_state(val, (dev->options & CC2420_OPT_PROMISCUOUS)); - - case NETOPT_RX_START_IRQ: - return opt_state(val, (dev->options & CC2420_OPT_TELL_RX_START)); - - case NETOPT_RX_END_IRQ: - return opt_state(val, (dev->options & CC2420_OPT_TELL_TX_END)); - - case NETOPT_TX_START_IRQ: - return opt_state(val, (dev->options & CC2420_OPT_TELL_RX_START)); - - case NETOPT_TX_END_IRQ: - return opt_state(val, (dev->options & CC2420_OPT_TELL_RX_END)); - - default: - return -ENOTSUP; - } -} - -static int set(netdev2_t *netdev, netopt_t opt, void *val, size_t val_len) -{ - if (netdev == NULL) { - return -ENODEV; - } - - cc2420_t *dev = (cc2420_t *)netdev; - - int ext = netdev2_ieee802154_set(&dev->netdev, opt, val, val_len); - - switch (opt) { - case NETOPT_ADDRESS: - assert(val_len == 2); - cc2420_set_addr_short(dev, (uint8_t *)val); - return 2; - - case NETOPT_ADDRESS_LONG: - assert(val_len == 8); - cc2420_set_addr_long(dev, (uint8_t *)val); - return 8; - - case NETOPT_NID: - assert(val_len == sizeof(uint16_t)); - cc2420_set_pan(dev, to_u16(val)); - return sizeof(uint16_t); - - case NETOPT_CHANNEL: - assert(val_len == sizeof(uint16_t)); - return cc2420_set_chan(dev, to_u16(val)); - - case NETOPT_TX_POWER: - assert(val_len == sizeof(int16_t)); - cc2420_set_txpower(dev, to_i16(val)); - return sizeof(int16_t); - - case NETOPT_STATE: - assert(val_len == sizeof(netopt_state_t)); - return cc2420_set_state(dev, *((netopt_state_t *)val)); - - case NETOPT_AUTOACK: - return cc2420_set_option(dev, CC2420_OPT_AUTOACK, to_bool(val)); - - case NETOPT_CSMA: - return cc2420_set_option(dev, CC2420_OPT_CSMA, to_bool(val)); - - case NETOPT_PRELOADING: - return cc2420_set_option(dev, CC2420_OPT_PRELOADING, to_bool(val)); - - case NETOPT_PROMISCUOUSMODE: - return cc2420_set_option(dev, CC2420_OPT_PROMISCUOUS, to_bool(val)); - - case NETOPT_RX_START_IRQ: - return cc2420_set_option(dev, CC2420_OPT_TELL_RX_START, to_bool(val)); - - case NETOPT_RX_END_IRQ: - return cc2420_set_option(dev, CC2420_OPT_TELL_RX_END, to_bool(val)); - - case NETOPT_TX_START_IRQ: - return cc2420_set_option(dev, CC2420_OPT_TELL_TX_START, to_bool(val)); - - case NETOPT_TX_END_IRQ: - return cc2420_set_option(dev, CC2420_OPT_TELL_TX_END, to_bool(val)); - - default: - return ext; - } - - return 0; -} - -const netdev2_driver_t cc2420_driver = { - .send = send, - .recv = recv, - .init = init, - .isr = isr, - .get = get, - .set = set, -}; diff --git a/drivers/cc2420/cc2420_getset.c b/drivers/cc2420/cc2420_getset.c new file mode 100644 index 0000000000..bd5d749468 --- /dev/null +++ b/drivers/cc2420/cc2420_getset.c @@ -0,0 +1,312 @@ +/* + * Copyright (C) 2015 Freie Universität Berlin + * 2016 Inria + * + * 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 drivers_cc2420 + * @{ + * + * @file + * @brief Getter and setter functions for the cc2420 driver + * + * @author Hauke Petersen + * @author Francisco Acosta + * + * @} + */ + +#include + +#include "cc2420.h" +#include "cc2420_internal.h" +#include "cc2420_registers.h" +#include "periph/spi.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + +/** + * @brief Translation from dBm to PA level + * + * Entry 0 in the array corresponds to -25dBm (min), entry 25 to 0dBm (max), so + * `PA_level = power_dbm_to_pa[DBM + 25]`. We use only the 3 MSB of the 5-bit + * level, leading to 8 distinct power settings (the 8 settings listed in the + * datasheet in section 28, page 51). + */ +static const uint8_t power_dbm_to_pa[26] = { + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 7, 7, + 7, 7, 11, 11, 11, 15, 15, 19, 19, 23, 23, 27, 31 +}; + +/** + * @brief Translate PA level to dBm + * + * As we use only the 3 MSB of the PA level value, we have 8 distinct settings. + * We get the dBm value with `DBM = power_pa_to_dbm(PA >> 2). + */ +static const int8_t power_pa_to_dbm[8] = { + -25, -15, -10, -7, -5, -3, -1, 0 +}; + +void cc2420_get_addr_short(cc2420_t *dev, uint8_t *addr) +{ + uint8_t tmp[2]; + + cc2420_ram_read(dev, CC2420_RAM_SHORTADR, tmp, 2); + + addr[0] = tmp[1]; + addr[1] = tmp[0]; +} + +void cc2420_set_addr_short(cc2420_t *dev, uint8_t *addr) +{ + uint8_t tmp[2]; + tmp[0] = addr[1]; + tmp[1] = addr[0]; + + memcpy(dev->netdev.short_addr, addr, 2); + +#ifdef MODULE_SIXLOWPAN + /* https://tools.ietf.org/html/rfc4944#section-12 requires the first bit to + * 0 for unicast addresses */ + dev->netdev.short_addr[0] &= 0x7F; +#endif + + cc2420_ram_write(dev, CC2420_RAM_SHORTADR, tmp, 2); +} + +void cc2420_get_addr_long(cc2420_t *dev, uint8_t *addr) +{ + cc2420_ram_read(dev, CC2420_RAM_IEEEADR, addr, 8); + + uint8_t *ap = (uint8_t *)(&addr); + for (int i = 0; i < 8; i++) { + ap[i] = dev->netdev.long_addr[i]; + } +} + +void cc2420_set_addr_long(cc2420_t *dev, uint8_t *addr) +{ + int i, j; + uint8_t tmp[8]; + + for (i = 0, j = 7; i < 8; i++, j--) { + dev->netdev.long_addr[i] = addr[i]; + tmp[j] = addr[i]; + } + + cc2420_ram_write(dev, CC2420_RAM_IEEEADR, tmp, 8); +} + +uint16_t cc2420_get_pan(cc2420_t *dev) +{ + le_uint16_t pan; + + cc2420_ram_read(dev, CC2420_RAM_PANID, pan.u8, 2); + return pan.u16; +} + +void cc2420_set_pan(cc2420_t *dev, uint16_t pan) +{ + dev->netdev.pan = pan; + cc2420_ram_write(dev, CC2420_RAM_PANID, (uint8_t *)&pan, 2); +} + +uint16_t cc2420_get_chan(cc2420_t *dev) +{ + uint16_t chan; + uint16_t freq = cc2420_reg_read(dev, CC2420_REG_FSCTRL); + + chan = (((freq & CC2420_FSCTRL_FREQ_MASK) - 357) / 5) + 11; + return chan; +} + +int cc2420_set_chan(cc2420_t *dev, uint16_t chan) +{ + if ((chan < CC2420_CHAN_MIN) || (chan > CC2420_CHAN_MAX)) { + DEBUG("cc2420: set channel: given channel invalid\n"); + return -ENOTSUP; + } + + /* calculation from http://www.ti.com/lit/ds/symlink/cc2420.pdf p.50 */ + uint16_t freq = cc2420_reg_read(dev, CC2420_REG_FSCTRL); + freq &= ~CC2420_FSCTRL_FREQ_MASK; + freq |= (357 + (5 * (chan - 11))); + cc2420_reg_write(dev, CC2420_REG_FSCTRL, freq); + + dev->netdev.chan = chan; + + return CC2420_RET_CHAN_OK; +} + +int16_t cc2420_get_txpower(cc2420_t *dev) +{ + uint16_t txctrl = cc2420_reg_read(dev, CC2420_REG_TXCTRL); + return (int16_t)power_pa_to_dbm[(txctrl & CC2420_TXCTRL_PA_MASK) >> 2]; +} + +void cc2420_set_txpower(cc2420_t *dev, int16_t txpower) +{ + if (txpower > CC2420_TXPOWER_MAX) { + txpower = CC2420_TXPOWER_MAX; + } + else if (txpower < CC2420_TXPOWER_MIN) { + txpower = CC2420_TXPOWER_MIN; + } + + uint16_t txctrl = cc2420_reg_read(dev, CC2420_REG_TXCTRL); + txctrl &= ~(CC2420_TXCTRL_PA_MASK); + txctrl |= power_dbm_to_pa[txpower + 25]; + cc2420_reg_write(dev, CC2420_REG_TXCTRL, txctrl); +} + +int cc2420_set_option(cc2420_t *dev, uint16_t option, bool state) +{ + uint16_t reg; + + /* set option field */ + if (state) { + dev->options |= option; + /* trigger option specific actions */ + switch (option) { + case CC2420_OPT_AUTOACK: + DEBUG("cc2420: set_opt: CC2420_OPT_AUTOACK\n"); + reg = cc2420_reg_read(dev, CC2420_REG_MDMCTRL0); + reg |= CC2420_MDMCTRL0_AUTOACK; + cc2420_reg_write(dev, CC2420_REG_MDMCTRL0, reg); + break; + + case CC2420_OPT_CSMA: + DEBUG("cc2420: set_opt: CC2420_OPT_CSMA\n"); + /* TODO: en/disable csma */ + break; + + case CC2420_OPT_PROMISCUOUS: + DEBUG("cc2420: set_opt: CC2420_OPT_PROMISCUOUS\n"); + /* in promisc mode, AUTO ACKs are should be disabled */ + reg = cc2420_reg_read(dev, CC2420_REG_MDMCTRL0); + reg &= ~(CC2420_MDMCTRL0_AUTOACK); + reg &= ~(CC2420_MDMCTRL0_ADR_DECODE); + cc2420_reg_write(dev, CC2420_REG_MDMCTRL0, reg); + break; + + case CC2420_OPT_PRELOADING: + DEBUG("cc2420: set_opt: CC2420_OPT_PRELOADING\n"); + break; + + case CC2420_OPT_TELL_TX_START: + case CC2420_OPT_TELL_TX_END: + case CC2420_OPT_TELL_RX_START: + case CC2420_OPT_TELL_RX_END: + DEBUG("cc2420: set_opt: TX/RX START/END\n"); + /* TODO */ + break; + + default: + return -ENOTSUP; + } + } + else { + dev->options &= ~(option); + /* trigger option specific actions */ + switch (option) { + case CC2420_OPT_AUTOACK: + DEBUG("cc2420: clr_opt: CC2420_OPT_AUTOACK\n"); + reg = cc2420_reg_read(dev, CC2420_REG_MDMCTRL0); + reg &= ~(CC2420_MDMCTRL0_AUTOACK); + cc2420_reg_write(dev, CC2420_REG_MDMCTRL0, reg); + break; + + case CC2420_OPT_CSMA: + DEBUG("cc2420: clr_opt: CC2420_OPT_CSMA\n"); + /* TODO: en/disable csma */ + break; + + case CC2420_OPT_PROMISCUOUS: + DEBUG("cc2420: clr_opt: CC2420_OPT_PROMISCUOUS\n"); + reg = cc2420_reg_read(dev, CC2420_REG_MDMCTRL0); + reg |= CC2420_MDMCTRL0_ADR_DECODE; + /* re-enable AUTOACK only if the option was set */ + if (dev->options & CC2420_OPT_AUTOACK) { + reg |= CC2420_MDMCTRL0_AUTOACK; + } + cc2420_reg_write(dev, CC2420_REG_MDMCTRL0, reg); + break; + + case CC2420_OPT_PRELOADING: + DEBUG("cc2420: clr_opt: CC2420_OPT_PRELOADING\n"); + break; + + case CC2420_OPT_TELL_TX_START: + case CC2420_OPT_TELL_TX_END: + case CC2420_OPT_TELL_RX_START: + case CC2420_OPT_TELL_RX_END: + DEBUG("cc2420: clr_opt: TX/RX START/END\n"); + /* TODO */ + break; + + default: + return -ENOTSUP; + } + } + return sizeof(netopt_enable_t); +} + +int cc2420_set_state(cc2420_t *dev, netopt_state_t cmd) +{ + if ((cc2420_get_state(dev) == NETOPT_STATE_OFF) && + (cmd != NETOPT_STATE_OFF)) { + cc2420_en_xosc(dev); + } + switch (cmd) { + case NETOPT_STATE_OFF: + cc2420_strobe(dev, CC2420_STROBE_XOSCOFF); + while (cc2420_state(dev) != CC2420_STATE_PD) {} + break; + case NETOPT_STATE_SLEEP: + cc2420_strobe(dev, CC2420_STROBE_RFOFF); + while (cc2420_state(dev) != CC2420_STATE_IDLE) {} + break; + case NETOPT_STATE_IDLE: + cc2420_strobe(dev, CC2420_STROBE_FLUSHRX); + cc2420_strobe(dev, CC2420_STROBE_RXON); + break; + case NETOPT_STATE_TX: + cc2420_tx_exec(dev); + break; + case NETOPT_STATE_RESET: + cc2420_init(dev); + break; + case NETOPT_STATE_RX: + default: + DEBUG("cc2420: set_state: called with invalid target state\n"); + return -ENOTSUP; + } + return sizeof(netopt_state_t); +} + +netopt_state_t cc2420_get_state(cc2420_t *dev) +{ + uint8_t cur_state = cc2420_state(dev); + + if (cur_state == 0) { + return NETOPT_STATE_OFF; + } + else if (cur_state == 1) { + return NETOPT_STATE_SLEEP; + } + else if (((cur_state >= 32) && (cur_state <=39)) || (cur_state == 56)) { + return NETOPT_STATE_TX; + } + else if ((cur_state >= 3) && (cur_state <= 6)) { + return NETOPT_STATE_IDLE; + } + else { + return NETOPT_STATE_RX; + } +} diff --git a/drivers/cc2420/cc2420_internal.c b/drivers/cc2420/cc2420_internal.c new file mode 100644 index 0000000000..01ab024f29 --- /dev/null +++ b/drivers/cc2420/cc2420_internal.c @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2015-2016 Freie Universität Berlin + * 2016 Inria + * + * 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 drivers_cc2420 + * @{ + * + * @file + * @brief Implementation of driver internal functions + * + * @author Hauke Petersen + * @author Francisco Acosta + * + * @} + */ + +#include "periph/spi.h" +#include "periph/gpio.h" +#include "xtimer.h" + +#include "cc2420_internal.h" +#include "cc2420_registers.h" + +uint8_t cc2420_strobe(const cc2420_t *dev, const uint8_t command) +{ + char res; + + spi_acquire(dev->params.spi); + gpio_clear(dev->params.pin_cs); + spi_transfer_byte(dev->params.spi, (char)command, (char *)&res); + gpio_set(dev->params.pin_cs); + spi_release(dev->params.spi); + + return res; +} + +void cc2420_reg_write(const cc2420_t *dev, + const uint8_t addr, + const uint16_t value) +{ + uint16_t tmp = byteorder_htons(value).u16; + + spi_acquire(dev->params.spi); + gpio_clear(dev->params.pin_cs); + spi_transfer_regs(dev->params.spi, CC2420_REG_WRITE | addr, + (char *)&tmp, NULL, 2); + gpio_set(dev->params.pin_cs); + spi_release(dev->params.spi); +} + +uint16_t cc2420_reg_read(const cc2420_t *dev, const uint8_t addr) +{ + network_uint16_t tmp; + + spi_acquire(dev->params.spi); + gpio_clear(dev->params.pin_cs); + spi_transfer_regs(dev->params.spi, CC2420_REG_READ | addr, + NULL, (char *)&tmp, 2); + gpio_set(dev->params.pin_cs); + spi_release(dev->params.spi); + + return byteorder_ntohs(tmp); +} + +void cc2420_ram_read(const cc2420_t *dev, const uint16_t addr, + uint8_t *data, const size_t len) +{ + char tmp[] = { (CC2420_RAM | (addr & 0x7f)), + (CC2420_RAM_READ | ((addr >> 1) & 0xc0)) }; + + spi_acquire(dev->params.spi); + gpio_clear(dev->params.pin_cs); + spi_transfer_bytes(dev->params.spi, tmp, NULL, 2); + spi_transfer_bytes(dev->params.spi, NULL, (char*)data, len); + gpio_set(dev->params.pin_cs); + spi_release(dev->params.spi); +} + +void cc2420_ram_write(const cc2420_t *dev, const uint16_t addr, + const uint8_t *data, const size_t len) +{ + char tmp[] = { (CC2420_RAM | (addr & 0x7f)), + (CC2420_RAM_WRITE | ((addr >> 1) & 0xc0)) }; + + spi_acquire(dev->params.spi); + gpio_clear(dev->params.pin_cs); + spi_transfer_bytes(dev->params.spi, tmp, NULL, 2); + spi_transfer_bytes(dev->params.spi, (char*)data, NULL, len); + gpio_set(dev->params.pin_cs); + spi_release(dev->params.spi); +} + +void cc2420_fifo_read(const cc2420_t *dev, uint8_t *data, const size_t len) +{ + spi_acquire(dev->params.spi); + gpio_clear(dev->params.pin_cs); + spi_transfer_regs(dev->params.spi, CC2420_FIFO_READ, + NULL, (char *)data, len); + gpio_set(dev->params.pin_cs); + spi_release(dev->params.spi); +} + +void cc2420_fifo_write(const cc2420_t *dev, uint8_t *data, const size_t len) +{ + spi_acquire(dev->params.spi); + gpio_clear(dev->params.pin_cs); + spi_transfer_regs(dev->params.spi, CC2420_FIFO_WRITE, + (char *)data, NULL, len); + gpio_set(dev->params.pin_cs); + spi_release(dev->params.spi); +} + +uint8_t cc2420_status(cc2420_t *dev) +{ + return cc2420_strobe(dev, CC2420_STROBE_NOP); +} + +uint8_t cc2420_state(cc2420_t *dev) +{ + return (uint8_t)cc2420_reg_read(dev, CC2420_REG_FSMSTATE); +} + +void cc2420_en_xosc(cc2420_t *dev) +{ + cc2420_strobe(dev, CC2420_STROBE_XOSCON); + xtimer_usleep(CC2420_XOSCON_DELAY); +} diff --git a/drivers/cc2420/cc2420_netdev.c b/drivers/cc2420/cc2420_netdev.c new file mode 100644 index 0000000000..41cfd8e153 --- /dev/null +++ b/drivers/cc2420/cc2420_netdev.c @@ -0,0 +1,308 @@ +/* + * Copyright (C) 2015 Freie Universität Berlin + * 2016 Inria + * + * 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 drivers_cc2420 + * @{ + * + * @file + * @brief Netdev adaption for the cc2420 driver + * + * @author Hauke Petersen + * @author Francisco Acosta + * + * @} + */ + +#include +#include +#include + +#include "net/eui64.h" +#include "net/ieee802154.h" +#include "net/netdev2.h" +#include "net/netdev2/ieee802154.h" +#include "xtimer.h" + +#include "cc2420.h" +#include "cc2420_netdev.h" +#include "cc2420_internal.h" +#include "cc2420_registers.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + + +static int _send(netdev2_t *netdev, const struct iovec *vector, int count); +static int _recv(netdev2_t *netdev, char *buf, int len, void *info); +static int _init(netdev2_t *netdev); +static void _isr(netdev2_t *netdev); +static int _get(netdev2_t *netdev, netopt_t opt, void *val, size_t max_len); +static int _set(netdev2_t *netdev, netopt_t opt, void *val, size_t len); + +const netdev2_driver_t cc2420_driver = { + .send = _send, + .recv = _recv, + .init = _init, + .isr = _isr, + .get = _get, + .set = _set, +}; + +static void _irq_handler(void *arg) +{ + netdev2_t *dev = (netdev2_t *)arg; + + if(dev->event_callback) { + dev->event_callback(dev, NETDEV2_EVENT_ISR); + } +} + +static inline uint16_t to_u16(void *buf) +{ + return *((uint16_t *)buf); +} + +static inline int16_t to_i16(void *buf) +{ + return *((int16_t *)buf); +} + +static inline bool to_bool(void *buf) +{ + return *((bool *)buf); +} + +static inline int w_u16(void *buf, uint16_t val) +{ + memcpy(buf, &val, sizeof(uint16_t)); + return sizeof(uint16_t); +} + +static inline int w_i16(void *buf, int16_t val) +{ + memcpy(buf, &val, sizeof(int16_t)); + return sizeof(int16_t); +} + +static inline int opt_state(void *buf, bool cond) +{ + *((netopt_enable_t *)buf) = !!(cond); + return sizeof(netopt_enable_t); +} + +static int _init(netdev2_t *netdev) +{ + cc2420_t *dev = (cc2420_t *)netdev; + + uint16_t reg; + + /* initialize power and reset pins -> put the device into reset state */ + gpio_init(dev->params.pin_reset, GPIO_OUT); + gpio_set(dev->params.pin_reset); + gpio_init(dev->params.pin_vrefen, GPIO_OUT); + gpio_clear(dev->params.pin_vrefen); + + /* initialize the input lines */ + gpio_init(dev->params.pin_cca, GPIO_IN); + gpio_init(dev->params.pin_sfd, GPIO_IN); + gpio_init(dev->params.pin_fifo, GPIO_IN); + gpio_init_int(dev->params.pin_fifop, GPIO_IN, GPIO_RISING, _irq_handler, dev); + + /* initialize the chip select line and the SPI bus */ + gpio_init(dev->params.pin_cs, GPIO_OUT); + gpio_set(dev->params.pin_cs); + + /* power on and toggle reset */ + gpio_set(dev->params.pin_vrefen); + gpio_clear(dev->params.pin_reset); + xtimer_usleep(CC2420_RESET_DELAY); + gpio_set(dev->params.pin_reset); + + /* test the connection to the device by reading MANFIDL register */ + reg = cc2420_reg_read(dev, CC2420_REG_MANFIDL); + if (reg != CC2420_MANFIDL_VAL) { + DEBUG("cc2420: init: unable to communicate with device\n"); + return -1; + } + + /* turn on the oscillator and wait for it to be stable */ + cc2420_en_xosc(dev); + if (!(cc2420_status(dev) & CC2420_STATUS_XOSC_STABLE)) { + DEBUG("cc2420: init: oscillator did not stabilize\n"); + return -1; + } + +#ifdef MODULE_NETSTATS_L2 + memset(&netdev->stats, 0, sizeof(netstats_t)); +#endif + + return cc2420_init((cc2420_t *)dev); +} + +static void _isr(netdev2_t *netdev) +{ + netdev->event_callback(netdev, NETDEV2_EVENT_RX_COMPLETE); +} + +static int _send(netdev2_t *netdev, const struct iovec *vector, int count) +{ + cc2420_t *dev = (cc2420_t *)netdev; + return (int)cc2420_send(dev, vector, count); +} + +static int _recv(netdev2_t *netdev, char *buf, int len, void *info) +{ + cc2420_t *dev = (cc2420_t *)netdev; + return (int)cc2420_rx(dev, (uint8_t *)buf, len, info); +} + +static int _get(netdev2_t *netdev, netopt_t opt, void *val, size_t max_len) +{ + if (netdev == NULL) { + return -ENODEV; + } + + cc2420_t *dev = (cc2420_t *)netdev; + + int ext = netdev2_ieee802154_get(&dev->netdev, opt, val, max_len); + if (ext > 0) { + return ext; + } + + switch (opt) { + + case NETOPT_ADDRESS: + assert(max_len >= sizeof(uint16_t)); + cc2420_get_addr_short(dev, val); + return sizeof(uint16_t); + + case NETOPT_ADDRESS_LONG: + assert(max_len >= 8); + cc2420_get_addr_long(dev, val); + return 8; + + case NETOPT_NID: + assert(max_len >= sizeof(uint16_t)); + return w_u16(val, cc2420_get_pan(dev)); + + case NETOPT_CHANNEL: + assert(max_len >= sizeof(uint16_t)); + return w_u16(val, cc2420_get_chan(dev)); + + case NETOPT_TX_POWER: + assert(max_len >= sizeof(int16_t)); + return w_i16(val, cc2420_get_txpower(dev)); + + case NETOPT_STATE: + assert(max_len >= sizeof(netopt_state_t)); + *((netopt_state_t *)val) = cc2420_get_state(dev); + return sizeof(netopt_state_t); + + case NETOPT_IS_CHANNEL_CLR: + return opt_state(val, cc2420_cca(dev)); + + case NETOPT_AUTOACK: + return opt_state(val, (dev->options & CC2420_OPT_AUTOACK)); + + case NETOPT_CSMA: + return opt_state(val, (dev->options & CC2420_OPT_CSMA)); + + case NETOPT_PRELOADING: + return opt_state(val, (dev->options & CC2420_OPT_PRELOADING)); + + case NETOPT_PROMISCUOUSMODE: + return opt_state(val, (dev->options & CC2420_OPT_PROMISCUOUS)); + + case NETOPT_RX_START_IRQ: + return opt_state(val, (dev->options & CC2420_OPT_TELL_RX_START)); + + case NETOPT_RX_END_IRQ: + return opt_state(val, (dev->options & CC2420_OPT_TELL_TX_END)); + + case NETOPT_TX_START_IRQ: + return opt_state(val, (dev->options & CC2420_OPT_TELL_RX_START)); + + case NETOPT_TX_END_IRQ: + return opt_state(val, (dev->options & CC2420_OPT_TELL_RX_END)); + + default: + return -ENOTSUP; + } +} + +static int _set(netdev2_t *netdev, netopt_t opt, void *val, size_t val_len) +{ + if (netdev == NULL) { + return -ENODEV; + } + + cc2420_t *dev = (cc2420_t *)netdev; + + int ext = netdev2_ieee802154_set(&dev->netdev, opt, val, val_len); + + switch (opt) { + case NETOPT_ADDRESS: + assert(val_len == 2); + cc2420_set_addr_short(dev, (uint8_t *)val); + return 2; + + case NETOPT_ADDRESS_LONG: + assert(val_len == 8); + cc2420_set_addr_long(dev, (uint8_t *)val); + return 8; + + case NETOPT_NID: + assert(val_len == sizeof(uint16_t)); + cc2420_set_pan(dev, to_u16(val)); + return sizeof(uint16_t); + + case NETOPT_CHANNEL: + assert(val_len == sizeof(uint16_t)); + return cc2420_set_chan(dev, to_u16(val)); + + case NETOPT_TX_POWER: + assert(val_len == sizeof(int16_t)); + cc2420_set_txpower(dev, to_i16(val)); + return sizeof(int16_t); + + case NETOPT_STATE: + assert(val_len == sizeof(netopt_state_t)); + return cc2420_set_state(dev, *((netopt_state_t *)val)); + + case NETOPT_AUTOACK: + return cc2420_set_option(dev, CC2420_OPT_AUTOACK, to_bool(val)); + + case NETOPT_CSMA: + return cc2420_set_option(dev, CC2420_OPT_CSMA, to_bool(val)); + + case NETOPT_PRELOADING: + return cc2420_set_option(dev, CC2420_OPT_PRELOADING, to_bool(val)); + + case NETOPT_PROMISCUOUSMODE: + return cc2420_set_option(dev, CC2420_OPT_PROMISCUOUS, to_bool(val)); + + case NETOPT_RX_START_IRQ: + return cc2420_set_option(dev, CC2420_OPT_TELL_RX_START, to_bool(val)); + + case NETOPT_RX_END_IRQ: + return cc2420_set_option(dev, CC2420_OPT_TELL_RX_END, to_bool(val)); + + case NETOPT_TX_START_IRQ: + return cc2420_set_option(dev, CC2420_OPT_TELL_TX_START, to_bool(val)); + + case NETOPT_TX_END_IRQ: + return cc2420_set_option(dev, CC2420_OPT_TELL_TX_END, to_bool(val)); + + default: + return ext; + } + + return 0; +} diff --git a/drivers/cc2420/include/cc2420_internal.h b/drivers/cc2420/include/cc2420_internal.h index d6bb5a53bd..ebb7a4eb50 100644 --- a/drivers/cc2420/include/cc2420_internal.h +++ b/drivers/cc2420/include/cc2420_internal.h @@ -1,6 +1,7 @@ /* * Copyright (C) 2014 Milan Babel and INRIA - * Copyright (C) 2015-2016 Freie Universität Berlin + * 2015-2016 Freie Universität Berlin + * 2016 Inria * * 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 @@ -12,16 +13,21 @@ * @{ * * @file - * @brief Definitions and settings for the CC2420 + * @brief Definitions and settings for the cc2420 * * @author Milan Babel * @author Kévin Roussel * @author Thomas Eichinger * @author Hauke Petersen + * @author Francisco Acosta * */ -#ifndef CC2420_REGISTERS_H -#define CC2420_REGISTERS_H +#ifndef CC2420_INTERNAL_H +#define CC2420_INTERNAL_H + +#include + +#include "cc2420.h" #ifdef __cplusplus extern "C" { @@ -29,222 +35,92 @@ extern "C" { /** * @brief Delays for resetting and turning on the device - * @{ */ #define CC2420_RESET_DELAY (500U) #define CC2420_XOSCON_DELAY (2000U) -/** @} */ -/** - * @brief Internal device option flags - * @{ - */ -#define CC2420_OPT_AUTOACK (0x0001) /**< auto ACKs active */ -#define CC2420_OPT_CSMA (0x0002) /**< CSMA active */ -#define CC2420_OPT_PROMISCUOUS (0x0004) /**< promiscuous mode - * active */ -#define CC2420_OPT_PRELOADING (0x0008) /**< preloading enabled */ -#define CC2420_OPT_TELL_TX_START (0x0010) /**< notify MAC layer on TX - * start */ -#define CC2420_OPT_TELL_TX_END (0x0020) /**< notify MAC layer on TX - * finished */ -#define CC2420_OPT_TELL_RX_START (0x0040) /**< notify MAC layer on RX - * start */ -#define CC2420_OPT_TELL_RX_END (0x0080) /**< notify MAC layer on RX - * finished */ -/** @} */ -/** - * @brief Possible device state change commands - * @{ - */ -enum { - CC2420_GOTO_PD, /**< power down */ - CC2420_GOTO_IDLE, /**< idle */ - CC2420_GOTO_RX, /**< receive state */ - CC2420_GOTO_TXON, /**< transmit packet without CCA */ - CC2420_GOTO_TXONCCA /**< transmit packet using CCA */ -}; - -/** - * @brief (Selected) device states - */ -enum { - CC2420_STATE_PD = 0, /**< power down */ - CC2420_STATE_IDLE = 1, /**< idle state */ - CC2420_STATE_TX_PRE = 34, /**< transmitting preamble */ - CC2420_STATE_RX_SEARCH = 6, /**< receive SFD search */ - CC2420_STATE_RX_OVERFLOW = 17 /**< receive buffer overflow */ -}; - -/** - * @brief CC2420 SPI commands - * @{ - */ -#define CC2420_REG_WRITE (0x00) /**< read register value */ -#define CC2420_REG_READ (0x40) /**< write register value */ -#define CC2420_RAM (0x80) /**< access the internal RAM */ -#define CC2420_RAM_WRITE (0x00) /**< write to RAM */ -#define CC2420_RAM_READ (0x20) /**< read from RAM */ -#define CC2420_FIFO_READ (CC2420_REG_RXFIFO | CC2420_REG_READ) -#define CC2420_FIFO_WRITE (CC2420_REG_TXFIFO | CC2420_REG_WRITE) -/** @} */ +uint8_t cc2420_strobe(const cc2420_t *dev, const uint8_t command); /** - * @brief CC2420 strobe commands - * @see Datasheet section 37, pages 61--62 - * @{ + * @brief Read from a register at address `addr` from device `dev`. + * + * @param[in] dev device to read from + * @param[in] addr address of the register to read + * + * @return the value of the specified register */ -#define CC2420_STROBE_NOP (0x00) /**< no operation */ -#define CC2420_STROBE_XOSCON (0x01) /**< turn transceiver on */ -#define CC2420_STROBE_TXCAL (0x02) /**< calibrate TX freq and wait */ -#define CC2420_STROBE_RXON (0x03) /**< switch to RX mode */ -#define CC2420_STROBE_TXON (0x04) /**< switch to TX mode */ -#define CC2420_STROBE_TXONCCA (0x05) /**< switch to TX after CCA*/ -#define CC2420_STROBE_RFOFF (0x06) /**< switch to IDLE mode */ -#define CC2420_STROBE_XOSCOFF (0x07) /**< power down */ -#define CC2420_STROBE_FLUSHRX (0x08) /**< flush RX FIFO */ -#define CC2420_STROBE_FLUSHTX (0x09) /**< flush TX FIFO */ -#define CC2420_STROBE_ACK (0x0A) /**< send ACK with pending cleared */ -#define CC2420_STROBE_ACKPEND (0x0B) /**< send ACK with pending set */ -#define CC2420_STROBE_RXDEC (0x0C) /**< start RX FIFO decrypt/verify */ -#define CC2420_STROBE_TXENC (0x0D) /**< start TX FIFO encrypt/auth */ -#define CC2420_STROBE_AES (0x0E) /**< start AES encryption */ -/** @} */ +uint16_t cc2420_reg_read(const cc2420_t *dev, const uint8_t addr); /** - * @brief CC2420 configuration registers - * @see Datasheet section 37, pages 61 to 80 - * @{ + * @brief Write to a register at address `addr` from device `dev`. + * + * @param[in] dev device to write to + * @param[in] addr address of the register to write + * @param[in] value value to write to the given register */ -#define CC2420_REG_MAIN (0x10) /**< main control */ -#define CC2420_REG_MDMCTRL0 (0x11) /**< modem control 0 */ -#define CC2420_REG_MDMCTRL1 (0x12) /**< modem control 1 */ -#define CC2420_REG_RSSI (0x13) /**< RSSI and CCA control */ -#define CC2420_REG_SYNCWORD (0x14) /**< synchronization word control */ -#define CC2420_REG_TXCTRL (0x15) /**< transmit control */ -#define CC2420_REG_RXCTRL0 (0x16) /**< receive control 0 */ -#define CC2420_REG_RXCTRL1 (0x17) /**< receive control 1 */ -#define CC2420_REG_FSCTRL (0x18) /**< freq synthesizer control */ -#define CC2420_REG_SECCTRL0 (0x19) /**< security control 0 */ -#define CC2420_REG_SECCTRL1 (0x1A) /**< security control 1 */ -#define CC2420_REG_BATTMON (0x1B) /**< battery monitor control */ -#define CC2420_REG_IOCFG0 (0x1C) /**< I/O control 0 */ -#define CC2420_REG_IOCFG1 (0x1D) /**< I/O control 1 */ -#define CC2420_REG_MANFIDL (0x1e) /**< manufacturer ID low */ -#define CC2420_REG_MANFIDH (0x1F) /**< manufacturer ID high */ -#define CC2420_REG_FSMTC (0x20) /**< FSM timer constants */ -#define CC2420_REG_MANAND (0x21) /**< manual signal AND override */ -#define CC2420_REG_MANOR (0x22) /**< manual signal OR override */ -#define CC2420_REG_AGCCTRL (0x23) /**< AGC control */ -#define CC2420_REG_AGCTST0 (0x24) /**< AGC test 0 */ -#define CC2420_REG_AGCTST1 (0x25) /**< AGC test 1 */ -#define CC2420_REG_AGCTST2 (0x26) /**< AGC test 2 */ -#define CC2420_REG_FSTST0 (0x27) /**< freq synthesizer test 0 */ -#define CC2420_REG_FSTST1 (0x28) /**< freq synthesizer test 1 */ -#define CC2420_REG_FSTST2 (0x29) /**< freq synthesizer test 2 */ -#define CC2420_REG_FSTST3 (0x2A) /**< freq synthesizer test 3 */ -#define CC2420_REG_RXBPFTST (0x2B) /**< RX bandpass filter test */ -#define CC2420_REG_FSMSTATE (0x2C) /**< FSM status */ -#define CC2420_REG_ADCTST (0x2D) /**< ADC test */ -#define CC2420_REG_DACTST (0x2E) /**< DAC test */ -#define CC2420_REG_TOPTST (0x2F) /**< top level test */ -#define CC2420_REG_TXFIFO (0x3E) /**< TX FIFO byte */ -#define CC2420_REG_RXFIFO (0x3F) /**< RX FIFO byte */ -/** @} */ +void cc2420_reg_write(const cc2420_t *dev, const uint8_t addr, + const uint16_t value); /** - * @brief CC2420 section address in RAM - * @see Datasheet section 13.5 page 31. - * @{ + * @brief Read a chunk of data from the SRAM of the given device + * + * @param[in] dev device to read from + * @param[in] addr starting address to read from [valid 0x00-0x16B] + * @param[out] data buffer to read data into + * @param[in] len number of bytes to read from SRAM */ -#define CC2420_RAM_TXFIFO (0x0000) -#define CC2420_RAM_RXFIFO (0x0080) -#define CC2420_RAM_KEY0 (0x0100) -#define CC2420_RAM_RXNONCE (0x0110) -#define CC2420_RAM_RXCTR (0x0110) -#define CC2420_RAM_SABUF (0x0120) -#define CC2420_RAM_KEY1 (0x0130) -#define CC2420_RAM_TXNONCE (0x0140) -#define CC2420_RAM_TXCTR (0x0140) -#define CC2420_RAM_CBCSTATE (0x0150) -#define CC2420_RAM_IEEEADR (0x0160) -#define CC2420_RAM_PANID (0x0168) -#define CC2420_RAM_SHORTADR (0x016A) -/** @} */ +void cc2420_ram_read(const cc2420_t *dev, const uint16_t addr, + uint8_t *data, const size_t len); /** - * @brief Status byte bit fields - * @see Datasheet section 13.3, page 29 - * @{ + * @brief Write a chunk of data into the SRAM of the given device + * + * @param[in] dev device to write to + * @param[in] addr address in the SRAM to write to [valid 0x00-0x16B] + * @param[in] data data to copy into SRAM + * @param[in] len number of bytes to write to SRAM */ -#define CC2420_STATUS_XOSC_STABLE (0x40) -#define CC2420_STATUS_TX_UNDERFLOW (0x20) -#define CC2420_STATUS_ENC_BUSY (0x10) -#define CC2420_STATUS_TX_ACTIVE (0x08) -#define CC2420_STATUS_PLL_LOCK (0x04) -#define CC2420_STATUS_RSSI_VALID (0x02) -/** @} */ +void cc2420_ram_write(const cc2420_t *dev, const uint16_t addr, + const uint8_t *data, const size_t len); /** - * @brief Modem control 0 register bitfields - * @{ + * @brief Reads FIFO buffer from RAM at address 0x080 + * + * @param[in] dev device to write to + * @param[in] data data to copy into SRAM + * @param[in] len number of bytes to write to SRAM */ -#define CC2420_MDMCTRL0_RES_FRM (0x2000 -#define CC2420_MDMCTRL0_ADR_DECODE (0x0800) -#define CC2420_MDMCTRL0_PAN_COORD (0x1000) -#define CC2420_MDMCTRL0_AUTOCRC (0x0020) -#define CC2420_MDMCTRL0_AUTOACK (0x0010) -#define CC2420_MDMCTRL0_PREAMBLE_M (0x000f) -#define CC2420_MDMCTRL0_PREAMBLE_3B (0x0002) -/** @} */ +void cc2420_fifo_read(const cc2420_t *dev, uint8_t *data, const size_t len); /** - * @brief Transmit control register bitfields - * @{ + * @brief Writes FIFO buffer to RAM at address 0x000 + * + * @param[in] dev device to write to + * @param[in] data data to copy into SRAM + * @param[in] len number of bytes to write to SRAM */ -#define CC2420_TXCTRL_PA_MASK (0x001f) -/** @} */ +void cc2420_fifo_write(const cc2420_t *dev, uint8_t *data, const size_t len); /** - * @brief Receive control register 1 bitfields - * @{ + * @brief Get the device's status byte */ -#define CC2420_RXCTRL1_RXBPF_LOCUR (0x2000) -/** @} */ +uint8_t cc2420_status(cc2420_t *dev); /** - * @brief Frequency synthesizer control and status register bitfields - * @{ + * @brief Get the device's current state */ -#define CC2420_FSCTRL_LOCK_THR_MASK (0xc000) -#define CC2420_FSCTRL_CAL_DONE (0x2000) -#define CC2420_FSCTRL_CAL_RUNNING (0x1000) -#define CC2420_FSCTRL_LOCK_LENGTH (0x0800) -#define CC2420_FSCTRL_LOCK_STATUS (0x0400) -#define CC2420_FSCTRL_FREQ_MASK (0x03ff) -/** @} */ +uint8_t cc2420_state(cc2420_t *dev); /** - * @brief Security control register 0 bitfields - * @{ + * @brief Enable on-board oscillator */ -#define CC2420_SECCTRL0_RXFIFO_PROT (0x0200) -/** @} */ - -/** - * @brief Manufacturer ID low register value - */ -#define CC2420_MANFIDL_VAL (0x233d) - -/** - * @brief Manufacturer ID high register value - */ -#define CC2420_MANFIDH_VAL (0x3000) +void cc2420_en_xosc(cc2420_t *dev); #ifdef __cplusplus } #endif -#endif +#endif /* CC2420_INTERNAL_H_ */ +/** @} */ diff --git a/drivers/cc2420/include/cc2420_netdev.h b/drivers/cc2420/include/cc2420_netdev.h new file mode 100644 index 0000000000..2b260938ed --- /dev/null +++ b/drivers/cc2420/include/cc2420_netdev.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2016 Inria + * 2016 Freie Universität Berlin + * + * 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 drivers_cc2420 + * @{ + * + * @file + * @brief Netdev interface for the CC2420 + * + * @author Francisco Acosta + * @author Hauke Petersen + * + */ + +#ifndef CC2420_NETDEV_H_ +#define CC2420_NETDEV_H_ + +#include "net/netdev2.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Reference to the netdev device driver struct + */ +extern const netdev2_driver_t cc2420_driver; + +#ifdef __cplusplus +} +#endif + +#endif /* CC2420_NETDEV_H_ */ +/** @} */ diff --git a/drivers/cc2420/include/cc2420_registers.h b/drivers/cc2420/include/cc2420_registers.h new file mode 100644 index 0000000000..c4a318c593 --- /dev/null +++ b/drivers/cc2420/include/cc2420_registers.h @@ -0,0 +1,241 @@ +/* + * Copyright (C) 2015 Freie Universität Berlin + * 2016 Inria + * + * 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 drivers_cc2420 + * @{ + * + * @file + * @brief Register and command definitions for CC2420 + * + * @author Hauke Petersen + * @author Francisco Acosta + */ + +#ifndef CC2420_REGISTERS_H_ +#define CC2420_REGISTERS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Internal device option flags + * @{ + */ +#define CC2420_OPT_AUTOACK (0x0001) /**< auto ACKs active */ +#define CC2420_OPT_CSMA (0x0002) /**< CSMA active */ +#define CC2420_OPT_PROMISCUOUS (0x0004) /**< promiscuous mode + * active */ +#define CC2420_OPT_PRELOADING (0x0008) /**< preloading enabled */ +#define CC2420_OPT_TELL_TX_START (0x0010) /**< notify MAC layer on TX + * start */ +#define CC2420_OPT_TELL_TX_END (0x0020) /**< notify MAC layer on TX + * finished */ +#define CC2420_OPT_TELL_RX_START (0x0040) /**< notify MAC layer on RX + * start */ +#define CC2420_OPT_TELL_RX_END (0x0080) /**< notify MAC layer on RX + * finished */ +/** @} */ + +/** + * @brief Possible device state change commands + * @{ + */ +enum { + CC2420_GOTO_PD, /**< power down */ + CC2420_GOTO_IDLE, /**< idle */ + CC2420_GOTO_RX, /**< receive state */ + CC2420_GOTO_TXON, /**< transmit packet without CCA */ + CC2420_GOTO_TXONCCA /**< transmit packet using CCA */ +}; + +/** + * @brief (Selected) device states + */ +enum { + CC2420_STATE_PD = 0, /**< power down */ + CC2420_STATE_IDLE = 1, /**< idle state */ + CC2420_STATE_TX_PRE = 34, /**< transmitting preamble */ + CC2420_STATE_RX_SEARCH = 6, /**< receive SFD search */ + CC2420_STATE_RX_OVERFLOW = 17 /**< receive buffer overflow */ +}; + +/** + * @brief CC2420 SPI commands + * @{ + */ +#define CC2420_REG_WRITE (0x00) /**< read register value */ +#define CC2420_REG_READ (0x40) /**< write register value */ +#define CC2420_RAM (0x80) /**< access the internal RAM */ +#define CC2420_RAM_WRITE (0x00) /**< write to RAM */ +#define CC2420_RAM_READ (0x20) /**< read from RAM */ +#define CC2420_FIFO_READ (CC2420_REG_RXFIFO | CC2420_REG_READ) +#define CC2420_FIFO_WRITE (CC2420_REG_TXFIFO | CC2420_REG_WRITE) +/** @} */ + + +/** + * @brief CC2420 strobe commands + * @see Datasheet section 37, pages 61--62 + * @{ + */ +#define CC2420_STROBE_NOP (0x00) /**< no operation */ +#define CC2420_STROBE_XOSCON (0x01) /**< turn transceiver on */ +#define CC2420_STROBE_TXCAL (0x02) /**< calibrate TX freq and wait */ +#define CC2420_STROBE_RXON (0x03) /**< switch to RX mode */ +#define CC2420_STROBE_TXON (0x04) /**< switch to TX mode */ +#define CC2420_STROBE_TXONCCA (0x05) /**< switch to TX after CCA*/ +#define CC2420_STROBE_RFOFF (0x06) /**< switch to IDLE mode */ +#define CC2420_STROBE_XOSCOFF (0x07) /**< power down */ +#define CC2420_STROBE_FLUSHRX (0x08) /**< flush RX FIFO */ +#define CC2420_STROBE_FLUSHTX (0x09) /**< flush TX FIFO */ +#define CC2420_STROBE_ACK (0x0A) /**< send ACK with pending cleared */ +#define CC2420_STROBE_ACKPEND (0x0B) /**< send ACK with pending set */ +#define CC2420_STROBE_RXDEC (0x0C) /**< start RX FIFO decrypt/verify */ +#define CC2420_STROBE_TXENC (0x0D) /**< start TX FIFO encrypt/auth */ +#define CC2420_STROBE_AES (0x0E) /**< start AES encryption */ +/** @} */ + +/** + * @brief CC2420 configuration registers + * @see Datasheet section 37, pages 61 to 80 + * @{ + */ +#define CC2420_REG_MAIN (0x10) /**< main control */ +#define CC2420_REG_MDMCTRL0 (0x11) /**< modem control 0 */ +#define CC2420_REG_MDMCTRL1 (0x12) /**< modem control 1 */ +#define CC2420_REG_RSSI (0x13) /**< RSSI and CCA control */ +#define CC2420_REG_SYNCWORD (0x14) /**< synchronization word control */ +#define CC2420_REG_TXCTRL (0x15) /**< transmit control */ +#define CC2420_REG_RXCTRL0 (0x16) /**< receive control 0 */ +#define CC2420_REG_RXCTRL1 (0x17) /**< receive control 1 */ +#define CC2420_REG_FSCTRL (0x18) /**< freq synthesizer control */ +#define CC2420_REG_SECCTRL0 (0x19) /**< security control 0 */ +#define CC2420_REG_SECCTRL1 (0x1A) /**< security control 1 */ +#define CC2420_REG_BATTMON (0x1B) /**< battery monitor control */ +#define CC2420_REG_IOCFG0 (0x1C) /**< I/O control 0 */ +#define CC2420_REG_IOCFG1 (0x1D) /**< I/O control 1 */ +#define CC2420_REG_MANFIDL (0x1e) /**< manufacturer ID low */ +#define CC2420_REG_MANFIDH (0x1F) /**< manufacturer ID high */ +#define CC2420_REG_FSMTC (0x20) /**< FSM timer constants */ +#define CC2420_REG_MANAND (0x21) /**< manual signal AND override */ +#define CC2420_REG_MANOR (0x22) /**< manual signal OR override */ +#define CC2420_REG_AGCCTRL (0x23) /**< AGC control */ +#define CC2420_REG_AGCTST0 (0x24) /**< AGC test 0 */ +#define CC2420_REG_AGCTST1 (0x25) /**< AGC test 1 */ +#define CC2420_REG_AGCTST2 (0x26) /**< AGC test 2 */ +#define CC2420_REG_FSTST0 (0x27) /**< freq synthesizer test 0 */ +#define CC2420_REG_FSTST1 (0x28) /**< freq synthesizer test 1 */ +#define CC2420_REG_FSTST2 (0x29) /**< freq synthesizer test 2 */ +#define CC2420_REG_FSTST3 (0x2A) /**< freq synthesizer test 3 */ +#define CC2420_REG_RXBPFTST (0x2B) /**< RX bandpass filter test */ +#define CC2420_REG_FSMSTATE (0x2C) /**< FSM status */ +#define CC2420_REG_ADCTST (0x2D) /**< ADC test */ +#define CC2420_REG_DACTST (0x2E) /**< DAC test */ +#define CC2420_REG_TOPTST (0x2F) /**< top level test */ +#define CC2420_REG_TXFIFO (0x3E) /**< TX FIFO byte */ +#define CC2420_REG_RXFIFO (0x3F) /**< RX FIFO byte */ +/** @} */ + +/** + * @brief CC2420 section address in RAM + * @see Datasheet section 13.5 page 31. + * @{ + */ +#define CC2420_RAM_TXFIFO (0x0000) +#define CC2420_RAM_RXFIFO (0x0080) +#define CC2420_RAM_KEY0 (0x0100) +#define CC2420_RAM_RXNONCE (0x0110) +#define CC2420_RAM_RXCTR (0x0110) +#define CC2420_RAM_SABUF (0x0120) +#define CC2420_RAM_KEY1 (0x0130) +#define CC2420_RAM_TXNONCE (0x0140) +#define CC2420_RAM_TXCTR (0x0140) +#define CC2420_RAM_CBCSTATE (0x0150) +#define CC2420_RAM_IEEEADR (0x0160) +#define CC2420_RAM_PANID (0x0168) +#define CC2420_RAM_SHORTADR (0x016A) +/** @} */ + +/** + * @brief Status byte bit fields + * @see Datasheet section 13.3, page 29 + * @{ + */ +#define CC2420_STATUS_XOSC_STABLE (0x40) +#define CC2420_STATUS_TX_UNDERFLOW (0x20) +#define CC2420_STATUS_ENC_BUSY (0x10) +#define CC2420_STATUS_TX_ACTIVE (0x08) +#define CC2420_STATUS_PLL_LOCK (0x04) +#define CC2420_STATUS_RSSI_VALID (0x02) +/** @} */ + +/** + * @brief Modem control 0 register bitfields + * @{ + */ +#define CC2420_MDMCTRL0_RES_FRM (0x2000 +#define CC2420_MDMCTRL0_ADR_DECODE (0x0800) +#define CC2420_MDMCTRL0_PAN_COORD (0x1000) +#define CC2420_MDMCTRL0_AUTOCRC (0x0020) +#define CC2420_MDMCTRL0_AUTOACK (0x0010) +#define CC2420_MDMCTRL0_PREAMBLE_M (0x000f) +#define CC2420_MDMCTRL0_PREAMBLE_3B (0x0002) +/** @} */ + +/** + * @brief Transmit control register bitfields + * @{ + */ +#define CC2420_TXCTRL_PA_MASK (0x001f) +/** @} */ + +/** + * @brief Receive control register 1 bitfields + * @{ + */ +#define CC2420_RXCTRL1_RXBPF_LOCUR (0x2000) +/** @} */ + +/** + * @brief Frequency synthesizer control and status register bitfields + * @{ + */ +#define CC2420_FSCTRL_LOCK_THR_MASK (0xc000) +#define CC2420_FSCTRL_CAL_DONE (0x2000) +#define CC2420_FSCTRL_CAL_RUNNING (0x1000) +#define CC2420_FSCTRL_LOCK_LENGTH (0x0800) +#define CC2420_FSCTRL_LOCK_STATUS (0x0400) +#define CC2420_FSCTRL_FREQ_MASK (0x03ff) +/** @} */ + +/** + * @brief Security control register 0 bitfields + * @{ + */ +#define CC2420_SECCTRL0_RXFIFO_PROT (0x0200) +/** @} */ + +/** + * @brief Manufacturer ID low register value + */ +#define CC2420_MANFIDL_VAL (0x233d) + +/** + * @brief Manufacturer ID high register value + */ +#define CC2420_MANFIDH_VAL (0x3000) + + +#ifdef __cplusplus +} +#endif + +#endif /* CC2420_REGISTERS_H_ */ From 374f4a19812879d807766d4db85acd1250afa954 Mon Sep 17 00:00:00 2001 From: kYc0o Date: Tue, 5 Jul 2016 18:42:59 +0200 Subject: [PATCH 7/9] drivers/include: add cc2420 doxygen doc --- drivers/include/cc2420.h | 42 ++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/drivers/include/cc2420.h b/drivers/include/cc2420.h index 1baac59598..8fe23ad979 100644 --- a/drivers/include/cc2420.h +++ b/drivers/include/cc2420.h @@ -1,15 +1,14 @@ /* - * Copyright (C) 2015-2016 Freie Universität Berlin + * Copyright (C) 2015 Freie Universität Berlin * - * 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. + * 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 drivers_cc2420 CC2420 driver - * @ingroup drivers - * @brief Implementation of the CC2420 radio driver + * @ingroup drivers_netdev_netdev2 * @{ * * @file @@ -44,10 +43,8 @@ extern "C" { * * In case this address is used, that short address will be created by using the * last two bytes of the long address. - * @{ */ #define CC2420_ADDR_FALLBACK {0x12, 0x22, 0x33, 0x44, 0x55, 0x66, 0x08, 0x15} -/** @} */ /** * @brief PAN ID configuration @@ -81,6 +78,7 @@ enum { /** * @brief Struct holding all parameters needed for device initialization + * @{ */ typedef struct cc2420_params { spi_t spi; /**< SPI bus the device is connected to */ @@ -93,19 +91,22 @@ typedef struct cc2420_params { gpio_t pin_vrefen; /**< pin connected to the Vref enable pin */ gpio_t pin_reset; /**< pin connected to the reset pin */ } cc2420_params_t; +/** @} */ /** * @brief Device descriptor for CC2420 radio devices + * @{ */ typedef struct { /* netdev fields */ - netdev2_ieee802154_t netdev; + netdev2_ieee802154_t netdev; /**< netdev2 parent struct */ /* device specific fields */ - cc2420_params_t params; /**< hardware interface configuration */ + cc2420_params_t params; /**< hardware interface configuration */ /* device state fields */ - uint8_t state; /**< current state of the radio */ - uint16_t options; /**< state of used options */ + uint8_t state; /**< current state of the radio */ + uint16_t options; /**< state of used options */ } cc2420_t; +/** @} */ /** * @brief Setup the device descriptor for the given device @@ -166,7 +167,8 @@ void cc2420_set_addr_short(cc2420_t *dev, uint8_t *addr); /** * @brief Get the configured long address of the given device * - * @param[in] dev device to read from + * @param[in] dev device to read from + * @param[out] addr_long buffer to save the read address * * @return the currently set (8-byte) long address */ @@ -176,7 +178,7 @@ void cc2420_get_addr_long(cc2420_t *dev, uint8_t *addr_long); * @brief Set the long address of the given device * * @param[in] dev device to write to - * @param[in] addr (8-byte) long address to set + * @param[in] addr_long (8-byte) long address to set */ void cc2420_set_addr_long(cc2420_t *dev, uint8_t *addr_long); @@ -269,7 +271,7 @@ netopt_state_t cc2420_get_state(cc2420_t *dev); * * @param[in] dev device to use for sending * @param[in] data data to send (must include IEEE802.15.4 header) - * @param[in] len length of @p data + * @param[in] count length of @p data * * @return number of bytes that were actually send * @return 0 on error @@ -282,7 +284,9 @@ size_t cc2420_send(cc2420_t *dev, const struct iovec *data, int count); * This function puts the given device into the TX state, so no receiving of * data is possible after it was called. * - * @param[in] dev device to prepare for sending + * @param[in] dev device to prepare for sending + * @param[in] data data to prepare (must include IEEE802.15.4 header) + * @param[in] count length of @p data */ size_t cc2420_tx_prepare(cc2420_t *dev, const struct iovec *data, int count); @@ -297,9 +301,9 @@ void cc2420_tx_exec(cc2420_t *dev); * @brief Read a chunk of data from the receive buffer of the given device * * @param[in] dev device to read from - * @param[out] data buffer to write data to - * @param[in] len number of bytes to read from device - * @param[in] offset offset in the receive buffer + * @param[out] buf buffer to write data to + * @param[in] max_len number of bytes to read from device + * @param[in] info to be removed */ int cc2420_rx(cc2420_t *dev, uint8_t *buf, size_t max_len, void *info); From 124bddb72ce8961c1f0173e738d307404544215f Mon Sep 17 00:00:00 2001 From: kYc0o Date: Fri, 1 Jul 2016 15:41:31 +0200 Subject: [PATCH 8/9] auto_init/netif/auto_init_cc2420: change variable names --- sys/auto_init/netif/auto_init_cc2420.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/sys/auto_init/netif/auto_init_cc2420.c b/sys/auto_init/netif/auto_init_cc2420.c index c0b7d74fff..78f8de3878 100644 --- a/sys/auto_init/netif/auto_init_cc2420.c +++ b/sys/auto_init/netif/auto_init_cc2420.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2016 Freie Universität Berlin + * 2016 Inria * * 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 @@ -15,6 +16,7 @@ * @brief Auto initialization for CC2420 network devices * * @author Hauke Petersen + * @author Francisco Acosta */ #ifdef MODULE_CC2420 @@ -34,9 +36,8 @@ * @brief MAC layer stack parameters * @{ */ -// #define STACKSIZE (THREAD_STACKSIZE_DEFAULT) -#define STACKSIZE (THREAD_STACKSIZE_MAIN) -#define PRIO (THREAD_PRIORITY_MAIN - 4) +#define CC2420_MAC_STACKSIZE (THREAD_STACKSIZE_MAIN) +#define CC2420_MAC_PRIO (THREAD_PRIORITY_MAIN - 4) /** @} */ /** @@ -48,9 +49,9 @@ * @brief Allocate memory for dev descriptors, stacks, and 802.15.4 adaption * @{ */ -static cc2420_t devs[CC2420_NUMOF]; -static gnrc_netdev2_t adpt[CC2420_NUMOF]; -static char stacks[CC2420_NUMOF][STACKSIZE]; +static cc2420_t cc2420_devs[CC2420_NUMOF]; +static gnrc_netdev2_t gnrc_adpt[CC2420_NUMOF]; +static char _cc2420_stacks[CC2420_NUMOF][CC2420_MAC_STACKSIZE]; /** @} */ void auto_init_cc2420(void) @@ -58,15 +59,18 @@ void auto_init_cc2420(void) for (unsigned i = 0; i < CC2420_NUMOF; i++) { DEBUG("Initializing CC2420 radios #%u\n", i); - cc2420_setup(&devs[i], &cc2420_params[i]); - int res = gnrc_netdev2_ieee802154_init(&adpt[i], - (netdev2_ieee802154_t *)&devs[i]); + cc2420_setup(&cc2420_devs[i], &cc2420_params[i]); + int res = gnrc_netdev2_ieee802154_init(&gnrc_adpt[i], + (netdev2_ieee802154_t *)&cc2420_devs[i]); if (res < 0) { DEBUG("Error initializing CC2420 radio device!\n"); } else { - gnrc_netdev2_init(stacks[i], STACKSIZE, PRIO, "cc2420", &adpt[i]); + gnrc_netdev2_init(_cc2420_stacks[i], + CC2420_MAC_STACKSIZE, + CC2420_MAC_PRIO, + "cc2420", &gnrc_adpt[i]); } } } From 0a700944499cd0f8b5d896937351b55e22a78a39 Mon Sep 17 00:00:00 2001 From: kYc0o Date: Tue, 5 Jul 2016 13:55:06 +0200 Subject: [PATCH 9/9] tests: add telosb to memory insufficient boards --- tests/driver_enc28j60/Makefile | 3 ++- tests/driver_encx24j600/Makefile | 2 +- tests/emb6/Makefile | 2 +- tests/lwip/Makefile | 6 +++--- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/tests/driver_enc28j60/Makefile b/tests/driver_enc28j60/Makefile index c324d3c047..b879374800 100644 --- a/tests/driver_enc28j60/Makefile +++ b/tests/driver_enc28j60/Makefile @@ -3,7 +3,8 @@ include ../Makefile.tests_common FEATURES_REQUIRED = periph_spi periph_gpio -BOARD_INSUFFICIENT_MEMORY := msb-430h nucleo-f334 stm32f0discovery weio z1 +BOARD_INSUFFICIENT_MEMORY := msb-430h nucleo-f334 stm32f0discovery telosb \ + weio z1 USEMODULE += gnrc_netdev2 USEMODULE += gnrc_netdev_default diff --git a/tests/driver_encx24j600/Makefile b/tests/driver_encx24j600/Makefile index b770b94fa7..8b6b8ea2b8 100644 --- a/tests/driver_encx24j600/Makefile +++ b/tests/driver_encx24j600/Makefile @@ -3,7 +3,7 @@ include ../Makefile.tests_common FEATURES_REQUIRED = periph_spi periph_gpio -BOARD_INSUFFICIENT_MEMORY := msb-430h stm32f0discovery weio z1 +BOARD_INSUFFICIENT_MEMORY := msb-430h stm32f0discovery telosb weio z1 USEMODULE += gnrc_netdev2 USEMODULE += gnrc_netdev_default diff --git a/tests/emb6/Makefile b/tests/emb6/Makefile index 874ed139e1..df1e286881 100644 --- a/tests/emb6/Makefile +++ b/tests/emb6/Makefile @@ -6,7 +6,7 @@ BOARD ?= samr21-xpro RIOTBASE ?= $(CURDIR)/../.. -BOARD_INSUFFICIENT_MEMORY := msb-430h stm32f0discovery weio z1 +BOARD_INSUFFICIENT_MEMORY := msb-430h stm32f0discovery telosb weio z1 USEMODULE += emb6_router USEMODULE += emb6_conn_udp diff --git a/tests/lwip/Makefile b/tests/lwip/Makefile index f9fdcf2cb2..c004c6202f 100644 --- a/tests/lwip/Makefile +++ b/tests/lwip/Makefile @@ -4,10 +4,10 @@ BOARD ?= iotlab-m3 RIOTBASE ?= $(CURDIR)/../.. -BOARD_BLACKLIST := arduino-mega2560 msb-430h z1 waspmote-pro +BOARD_BLACKLIST := arduino-mega2560 msb-430h telosb waspmote-pro z1 BOARD_INSUFFICIENT_MEMORY := airfy-beacon arduino-mega2560 msb-430h nrf6310 \ - nucleo-f334 pca10005 stm32f0discovery weio \ - yunjia-nrf51822 z1 + nucleo-f334 pca10005 stm32f0discovery telosb \ + weio yunjia-nrf51822 z1 # including lwip_ipv6_mld would currently break this test on at86rf2xx radios USEMODULE += lwip lwip_ipv6_autoconfig lwip_conn_ip lwip_netdev2