1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-01-18 12:52:44 +01:00

Merge pull request #12537 from benpicco/at86rfmega

drivers/at86rf2xx: add support for ATmegaRF MCUs
This commit is contained in:
Marian Buschsieweke 2019-10-28 09:22:02 +01:00 committed by GitHub
commit 4cf2151248
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 436 additions and 38 deletions

View File

@ -3,4 +3,8 @@ ifneq (,$(filter atmega_pcint,$(USEMODULE)))
USEMODULE += atmega_pcint1 USEMODULE += atmega_pcint1
endif endif
ifneq (,$(filter gnrc_netdev_default netdev_default,$(USEMODULE)))
USEMODULE += at86rfa1
endif
include $(RIOTCPU)/atmega_common/Makefile.dep include $(RIOTCPU)/atmega_common/Makefile.dep

View File

@ -3,4 +3,8 @@ ifneq (,$(filter atmega_pcint,$(USEMODULE)))
USEMODULE += atmega_pcint1 USEMODULE += atmega_pcint1
endif endif
ifneq (,$(filter gnrc_netdev_default netdev_default,$(USEMODULE)))
USEMODULE += at86rfr2
endif
include $(RIOTCPU)/atmega_common/Makefile.dep include $(RIOTCPU)/atmega_common/Makefile.dep

View File

@ -41,16 +41,20 @@ ifneq (,$(filter at30tse75x,$(USEMODULE)))
FEATURES_REQUIRED += periph_i2c FEATURES_REQUIRED += periph_i2c
endif endif
ifneq (,$(filter at86rf2%,$(USEMODULE))) ifneq (,$(filter at86rf%,$(USEMODULE)))
USEMODULE += at86rf2xx USEMODULE += at86rf2xx
USEMODULE += xtimer USEMODULE += xtimer
USEMODULE += luid USEMODULE += luid
USEMODULE += netif USEMODULE += netif
USEMODULE += ieee802154 USEMODULE += ieee802154
USEMODULE += netdev_ieee802154 USEMODULE += netdev_ieee802154
FEATURES_REQUIRED += periph_gpio
FEATURES_REQUIRED += periph_gpio_irq # only needed for SPI based variants
FEATURES_REQUIRED += periph_spi ifeq (,$(filter at86rfa1 at86rfr2,$(USEMODULE)))
FEATURES_REQUIRED += periph_gpio
FEATURES_REQUIRED += periph_gpio_irq
FEATURES_REQUIRED += periph_spi
endif
endif endif
ifneq (,$(filter ata8520e,$(USEMODULE))) ifneq (,$(filter ata8520e,$(USEMODULE)))

View File

@ -42,13 +42,49 @@ void at86rf2xx_setup(at86rf2xx_t *dev, const at86rf2xx_params_t *params)
netdev_t *netdev = (netdev_t *)dev; netdev_t *netdev = (netdev_t *)dev;
netdev->driver = &at86rf2xx_driver; netdev->driver = &at86rf2xx_driver;
/* initialize device descriptor */
dev->params = *params;
/* State to return after receiving or transmitting */ /* State to return after receiving or transmitting */
dev->idle_state = AT86RF2XX_STATE_TRX_OFF; dev->idle_state = AT86RF2XX_STATE_TRX_OFF;
/* radio state is P_ON when first powered-on */ /* radio state is P_ON when first powered-on */
dev->state = AT86RF2XX_STATE_P_ON; dev->state = AT86RF2XX_STATE_P_ON;
dev->pending_tx = 0; dev->pending_tx = 0;
#if defined(MODULE_AT86RFA1) || defined(MODULE_AT86RFR2)
(void) params;
/* set all interrupts off */
at86rf2xx_reg_write(dev, AT86RF2XX_REG__IRQ_MASK, 0x00);
#else
/* initialize device descriptor */
dev->params = *params;
#endif
}
static void at86rf2xx_disable_clock_output(at86rf2xx_t *dev)
{
#if defined(MODULE_AT86RFA1) || defined(MODULE_AT86RFR2)
(void) dev;
#else
uint8_t tmp = at86rf2xx_reg_read(dev, AT86RF2XX_REG__TRX_CTRL_0);
tmp &= ~(AT86RF2XX_TRX_CTRL_0_MASK__CLKM_CTRL);
tmp &= ~(AT86RF2XX_TRX_CTRL_0_MASK__CLKM_SHA_SEL);
tmp |= (AT86RF2XX_TRX_CTRL_0_CLKM_CTRL__OFF);
at86rf2xx_reg_write(dev, AT86RF2XX_REG__TRX_CTRL_0, tmp);
#endif
}
static void at86rf2xx_enable_smart_idle(at86rf2xx_t *dev)
{
#if AT86RF2XX_SMART_IDLE_LISTENING
uint8_t tmp = at86rf2xx_reg_read(dev, AT86RF2XX_REG__TRX_RPC);
tmp |= (AT86RF2XX_TRX_RPC_MASK__RX_RPC_EN |
AT86RF2XX_TRX_RPC_MASK__PDT_RPC_EN |
AT86RF2XX_TRX_RPC_MASK__PLL_RPC_EN |
AT86RF2XX_TRX_RPC_MASK__XAH_TX_RPC_EN |
AT86RF2XX_TRX_RPC_MASK__IPAN_RPC_EN);
at86rf2xx_reg_write(dev, AT86RF2XX_REG__TRX_RPC, tmp);
at86rf2xx_set_rxsensitivity(dev, RSSI_BASE_VAL);
#else
(void) dev;
#endif
} }
void at86rf2xx_reset(at86rf2xx_t *dev) void at86rf2xx_reset(at86rf2xx_t *dev)
@ -92,29 +128,18 @@ void at86rf2xx_reset(at86rf2xx_t *dev)
at86rf2xx_set_page(dev, AT86RF2XX_DEFAULT_PAGE); at86rf2xx_set_page(dev, AT86RF2XX_DEFAULT_PAGE);
#endif #endif
#if !defined(MODULE_AT86RFA1) && !defined(MODULE_AT86RFR2)
/* don't populate masked interrupt flags to IRQ_STATUS register */ /* don't populate masked interrupt flags to IRQ_STATUS register */
uint8_t tmp = at86rf2xx_reg_read(dev, AT86RF2XX_REG__TRX_CTRL_1); uint8_t tmp = at86rf2xx_reg_read(dev, AT86RF2XX_REG__TRX_CTRL_1);
tmp &= ~(AT86RF2XX_TRX_CTRL_1_MASK__IRQ_MASK_MODE); tmp &= ~(AT86RF2XX_TRX_CTRL_1_MASK__IRQ_MASK_MODE);
at86rf2xx_reg_write(dev, AT86RF2XX_REG__TRX_CTRL_1, tmp); at86rf2xx_reg_write(dev, AT86RF2XX_REG__TRX_CTRL_1, tmp);
/* configure smart idle listening feature */
#if AT86RF2XX_SMART_IDLE_LISTENING
tmp = at86rf2xx_reg_read(dev, AT86RF2XX_REG__TRX_RPC);
tmp |= (AT86RF2XX_TRX_RPC_MASK__RX_RPC_EN |
AT86RF2XX_TRX_RPC_MASK__PDT_RPC_EN |
AT86RF2XX_TRX_RPC_MASK__PLL_RPC_EN |
AT86RF2XX_TRX_RPC_MASK__XAH_TX_RPC_EN |
AT86RF2XX_TRX_RPC_MASK__IPAN_RPC_EN);
at86rf2xx_reg_write(dev, AT86RF2XX_REG__TRX_RPC, tmp);
at86rf2xx_set_rxsensitivity(dev, RSSI_BASE_VAL);
#endif #endif
/* configure smart idle listening feature */
at86rf2xx_enable_smart_idle(dev);
/* disable clock output to save power */ /* disable clock output to save power */
tmp = at86rf2xx_reg_read(dev, AT86RF2XX_REG__TRX_CTRL_0); at86rf2xx_disable_clock_output(dev);
tmp &= ~(AT86RF2XX_TRX_CTRL_0_MASK__CLKM_CTRL);
tmp &= ~(AT86RF2XX_TRX_CTRL_0_MASK__CLKM_SHA_SEL);
tmp |= (AT86RF2XX_TRX_CTRL_0_CLKM_CTRL__OFF);
at86rf2xx_reg_write(dev, AT86RF2XX_REG__TRX_CTRL_0, tmp);
/* enable interrupts */ /* enable interrupts */
at86rf2xx_reg_write(dev, AT86RF2XX_REG__IRQ_MASK, at86rf2xx_reg_write(dev, AT86RF2XX_REG__IRQ_MASK,

View File

@ -522,7 +522,14 @@ uint8_t at86rf2xx_set_state(at86rf2xx_t *dev, uint8_t state)
/* Discard all IRQ flags, framebuffer is lost anyway */ /* Discard all IRQ flags, framebuffer is lost anyway */
at86rf2xx_reg_read(dev, AT86RF2XX_REG__IRQ_STATUS); at86rf2xx_reg_read(dev, AT86RF2XX_REG__IRQ_STATUS);
/* Go to SLEEP mode from TRX_OFF */ /* Go to SLEEP mode from TRX_OFF */
#if defined(MODULE_AT86RFA1) || defined(MODULE_AT86RFR2)
/* reset interrupts states in device */
dev->irq_status = 0;
/* Setting SLPTR bit brings radio transceiver to sleep in in TRX_OFF*/
*AT86RF2XX_REG__TRXPR |= (AT86RF2XX_TRXPR_SLPTR);
#else
gpio_set(dev->params.sleep_pin); gpio_set(dev->params.sleep_pin);
#endif
dev->state = state; dev->state = state;
} }
else { else {

View File

@ -21,12 +21,14 @@
* @} * @}
*/ */
#include "periph/spi.h"
#include "periph/gpio.h"
#include "xtimer.h" #include "xtimer.h"
#include "at86rf2xx_internal.h" #include "at86rf2xx_internal.h"
#include "at86rf2xx_registers.h" #include "at86rf2xx_registers.h"
#if !defined(MODULE_AT86RFA1) && !defined(MODULE_AT86RFR2)
#include "periph/spi.h"
#include "periph/gpio.h"
#define SPIDEV (dev->params.spi) #define SPIDEV (dev->params.spi)
#define CSPIN (dev->params.cs_pin) #define CSPIN (dev->params.cs_pin)
@ -101,6 +103,8 @@ void at86rf2xx_fb_stop(const at86rf2xx_t *dev)
spi_release(SPIDEV); spi_release(SPIDEV);
} }
#endif /* SPI based transceiver */
uint8_t at86rf2xx_get_status(const at86rf2xx_t *dev) uint8_t at86rf2xx_get_status(const at86rf2xx_t *dev)
{ {
/* if sleeping immediately return state */ /* if sleeping immediately return state */
@ -116,7 +120,13 @@ void at86rf2xx_assert_awake(at86rf2xx_t *dev)
{ {
if (at86rf2xx_get_status(dev) == AT86RF2XX_STATE_SLEEP) { if (at86rf2xx_get_status(dev) == AT86RF2XX_STATE_SLEEP) {
/* wake up and wait for transition to TRX_OFF */ /* wake up and wait for transition to TRX_OFF */
#if defined(MODULE_AT86RFA1) || defined(MODULE_AT86RFR2)
/* Setting SLPTR bit in TRXPR to 0 returns the radio transceiver
* to the TRX_OFF state */
*AT86RF2XX_REG__TRXPR &= ~(AT86RF2XX_TRXPR_SLPTR);
#else
gpio_clear(dev->params.sleep_pin); gpio_clear(dev->params.sleep_pin);
#endif
xtimer_usleep(AT86RF2XX_WAKEUP_DELAY); xtimer_usleep(AT86RF2XX_WAKEUP_DELAY);
/* update state: on some platforms, the timer behind xtimer /* update state: on some platforms, the timer behind xtimer
@ -134,9 +144,14 @@ void at86rf2xx_assert_awake(at86rf2xx_t *dev)
void at86rf2xx_hardware_reset(at86rf2xx_t *dev) void at86rf2xx_hardware_reset(at86rf2xx_t *dev)
{ {
/* trigger hardware reset */ /* trigger hardware reset */
#if defined(MODULE_AT86RFA1) || defined(MODULE_AT86RFR2)
/* set reset Bit */
*(AT86RF2XX_REG__TRXPR) |= AT86RF2XX_TRXPR_TRXRST;
#else
gpio_clear(dev->params.reset_pin); gpio_clear(dev->params.reset_pin);
xtimer_usleep(AT86RF2XX_RESET_PULSE_WIDTH); xtimer_usleep(AT86RF2XX_RESET_PULSE_WIDTH);
gpio_set(dev->params.reset_pin); gpio_set(dev->params.reset_pin);
#endif
xtimer_usleep(AT86RF2XX_RESET_DELAY); xtimer_usleep(AT86RF2XX_RESET_DELAY);
/* update state: if the radio state was P_ON (initialization phase), /* update state: if the radio state was P_ON (initialization phase),
@ -205,7 +220,7 @@ void at86rf2xx_configure_phy(at86rf2xx_t *dev)
at86rf2xx_set_state(dev, prev_state); at86rf2xx_set_state(dev, prev_state);
} }
#if defined(MODULE_AT86RF233) || defined(MODULE_AT86RF231) #if AT86RF2XX_RANDOM_NUMBER_GENERATOR
void at86rf2xx_get_random(const at86rf2xx_t *dev, uint8_t *data, size_t len) void at86rf2xx_get_random(const at86rf2xx_t *dev, uint8_t *data, size_t len)
{ {
for (size_t byteCount = 0; byteCount < len; ++byteCount) { for (size_t byteCount = 0; byteCount < len; ++byteCount) {

View File

@ -19,6 +19,7 @@
* @author Kévin Roussel <Kevin.Roussel@inria.fr> * @author Kévin Roussel <Kevin.Roussel@inria.fr>
* @author Martine Lenders <mlenders@inf.fu-berlin.de> * @author Martine Lenders <mlenders@inf.fu-berlin.de>
* @author Kaspar Schleiser <kaspar@schleiser.de> * @author Kaspar Schleiser <kaspar@schleiser.de>
* @author Josua Arndt <jarndt@ias.rwth-aachen.de>
* *
* @} * @}
*/ */
@ -58,6 +59,10 @@ const netdev_driver_t at86rf2xx_driver = {
.set = _set, .set = _set,
}; };
#if defined(MODULE_AT86RFA1) || defined(MODULE_AT86RFR2)
/* SOC has radio interrupts, store reference to netdev */
static netdev_t *at86rfmega_dev;
#else
static void _irq_handler(void *arg) static void _irq_handler(void *arg)
{ {
netdev_t *dev = (netdev_t *) arg; netdev_t *dev = (netdev_t *) arg;
@ -66,11 +71,15 @@ static void _irq_handler(void *arg)
dev->event_callback(dev, NETDEV_EVENT_ISR); dev->event_callback(dev, NETDEV_EVENT_ISR);
} }
} }
#endif
static int _init(netdev_t *netdev) static int _init(netdev_t *netdev)
{ {
at86rf2xx_t *dev = (at86rf2xx_t *)netdev; at86rf2xx_t *dev = (at86rf2xx_t *)netdev;
#if defined(MODULE_AT86RFA1) || defined(MODULE_AT86RFR2)
at86rfmega_dev = netdev;
#else
/* initialize GPIOs */ /* initialize GPIOs */
spi_init_cs(dev->params.spi, dev->params.cs_pin); spi_init_cs(dev->params.spi, dev->params.cs_pin);
gpio_init(dev->params.sleep_pin, GPIO_OUT); gpio_init(dev->params.sleep_pin, GPIO_OUT);
@ -87,6 +96,7 @@ static int _init(netdev_t *netdev)
return -EIO; return -EIO;
} }
spi_release(dev->params.spi); spi_release(dev->params.spi);
#endif
/* test if the device is responding */ /* test if the device is responding */
if (at86rf2xx_reg_read(dev, AT86RF2XX_REG__PART_NUM) != AT86RF2XX_PARTNUM) { if (at86rf2xx_reg_read(dev, AT86RF2XX_REG__PART_NUM) != AT86RF2XX_PARTNUM) {
@ -136,16 +146,20 @@ static int _recv(netdev_t *netdev, void *buf, size_t len, void *info)
size_t pkt_len; size_t pkt_len;
/* frame buffer protection will be unlocked as soon as at86rf2xx_fb_stop() is called, /* frame buffer protection will be unlocked as soon as at86rf2xx_fb_stop() is called,
* Set receiver to PLL_ON state to be able to free the SPI bus and avoid loosing data. */ * Set receiver to PLL_ON state to be able to free the SPI bus and avoid losing data. */
at86rf2xx_set_state(dev, AT86RF2XX_STATE_PLL_ON); at86rf2xx_set_state(dev, AT86RF2XX_STATE_PLL_ON);
/* start frame buffer access */ /* start frame buffer access */
at86rf2xx_fb_start(dev); at86rf2xx_fb_start(dev);
/* get the size of the received packet */ /* get the size of the received packet */
#if defined(MODULE_AT86RFA1) || defined(MODULE_AT86RFR2)
phr = TST_RX_LENGTH;
#else
at86rf2xx_fb_read(dev, &phr, 1); at86rf2xx_fb_read(dev, &phr, 1);
#endif
/* ignore MSB (refer p.80) and substract length of FCS field */ /* ignore MSB (refer p.80) and subtract length of FCS field */
pkt_len = (phr & 0x7f) - 2; pkt_len = (phr & 0x7f) - 2;
/* return length when buf == NULL */ /* return length when buf == NULL */
@ -184,7 +198,8 @@ static int _recv(netdev_t *netdev, void *buf, size_t len, void *info)
* AT86RF232 RSSI_BASE_VAL + ED, base -91dBm * AT86RF232 RSSI_BASE_VAL + ED, base -91dBm
* AT86RF233 RSSI_BASE_VAL + ED, base -94dBm * AT86RF233 RSSI_BASE_VAL + ED, base -94dBm
* AT86RF231 RSSI_BASE_VAL + ED, base -91dBm * AT86RF231 RSSI_BASE_VAL + ED, base -91dBm
* AT***RFR2 RSSI_BASE_VAL + ED, base -90dBm * AT86RFA1 RSSI_BASE_VAL + ED, base -90dBm
* AT86RFR2 RSSI_BASE_VAL + ED, base -90dBm
* *
* AT86RF231 MAN. p.92, 8.4.3 Data Interpretation * AT86RF231 MAN. p.92, 8.4.3 Data Interpretation
* AT86RF232 MAN. p.91, 8.4.3 Data Interpretation * AT86RF232 MAN. p.91, 8.4.3 Data Interpretation
@ -200,7 +215,7 @@ static int _recv(netdev_t *netdev, void *buf, size_t len, void *info)
netdev_ieee802154_rx_info_t *radio_info = info; netdev_ieee802154_rx_info_t *radio_info = info;
at86rf2xx_fb_read(dev, &(radio_info->lqi), 1); at86rf2xx_fb_read(dev, &(radio_info->lqi), 1);
#if defined(MODULE_AT86RF231) #if defined(MODULE_AT86RF231) || defined(MODULE_AT86RFA1) || defined(MODULE_AT86RFR2)
/* AT86RF231 does not provide ED at the end of the frame buffer, read /* AT86RF231 does not provide ED at the end of the frame buffer, read
* from separate register instead */ * from separate register instead */
at86rf2xx_fb_stop(dev); at86rf2xx_fb_stop(dev);
@ -628,7 +643,12 @@ static void _isr(netdev_t *netdev)
} }
/* read (consume) device status */ /* read (consume) device status */
#if defined(MODULE_AT86RFA1) || defined(MODULE_AT86RFR2)
irq_mask = dev->irq_status;
dev->irq_status = 0;
#else
irq_mask = at86rf2xx_reg_read(dev, AT86RF2XX_REG__IRQ_STATUS); irq_mask = at86rf2xx_reg_read(dev, AT86RF2XX_REG__IRQ_STATUS);
#endif
trac_status = at86rf2xx_reg_read(dev, AT86RF2XX_REG__TRX_STATE) trac_status = at86rf2xx_reg_read(dev, AT86RF2XX_REG__TRX_STATE)
& AT86RF2XX_TRX_STATE_MASK__TRAC; & AT86RF2XX_TRX_STATE_MASK__TRAC;
@ -699,3 +719,74 @@ static void _isr(netdev_t *netdev)
} }
} }
} }
#if defined(MODULE_AT86RFA1) || defined(MODULE_AT86RFR2)
/**
* @brief ISR for transceiver's receive end interrupt
*
* Is triggered when valid data is received. FCS check passed.
* Save IRQ status and inform upper layer of data reception.
*
* Flow Diagram Manual p. 52 / 63
*/
ISR(TRX24_RX_END_vect, ISR_BLOCK)
{
__enter_isr();
uint8_t status = *AT86RF2XX_REG__TRX_STATE & AT86RF2XX_TRX_STATUS_MASK__TRX_STATUS;
DEBUG("TRX24_RX_END 0x%x\n", status);
((at86rf2xx_t *)at86rfmega_dev)->irq_status |= AT86RF2XX_IRQ_STATUS_MASK__RX_END;
/* Call upper layer to process received data */
at86rfmega_dev->event_callback(at86rfmega_dev, NETDEV_EVENT_ISR);
__exit_isr();
}
/**
* @brief Transceiver Frame Address Match, indicates incoming frame
*
* Is triggered when Frame with valid Address is received.
* Can be used to wake up MCU from sleep, etc.
*
* Flow Diagram Manual p. 52 / 63
*/
ISR(TRX24_XAH_AMI_vect, ISR_BLOCK)
{
__enter_isr();
DEBUG("TRX24_XAH_AMI\n");
((at86rf2xx_t *)at86rfmega_dev)->irq_status |= AT86RF2XX_IRQ_STATUS_MASK__AMI;
__exit_isr();
}
/**
* @brief ISR for transceiver's transmit end interrupt
*
* Is triggered when data or when acknowledge frames where send.
*
* Flow Diagram Manual p. 52 / 63
*/
ISR(TRX24_TX_END_vect, ISR_BLOCK)
{
__enter_isr();
at86rf2xx_t *dev = (at86rf2xx_t *) at86rfmega_dev;
uint8_t status = *AT86RF2XX_REG__TRX_STATE & AT86RF2XX_TRX_STATUS_MASK__TRX_STATUS;
DEBUG("TRX24_TX_END 0x%x\n", status);
/* only inform upper layer when a transmission was done,
* not for sending acknowledge frames if data was received. */
if (status != AT86RF2XX_STATE_RX_AACK_ON) {
dev->irq_status |= AT86RF2XX_IRQ_STATUS_MASK__TX_END;
/* Call upper layer to process if data was send successful */
at86rfmega_dev->event_callback(at86rfmega_dev, NETDEV_EVENT_ISR);
}
__exit_isr();
}
#endif /* MODULE_AT86RFA1 || MODULE_AT86RFR2 */

View File

@ -28,6 +28,11 @@
#include "at86rf2xx.h" #include "at86rf2xx.h"
#if defined(MODULE_AT86RFA1) || defined(MODULE_AT86RFR2)
#include <string.h>
#include "at86rf2xx_registers.h"
#endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -81,7 +86,14 @@ extern "C" {
* *
* @return the value of the specified register * @return the value of the specified register
*/ */
#if defined(MODULE_AT86RFA1) || defined(MODULE_AT86RFR2)
static inline uint8_t at86rf2xx_reg_read(const at86rf2xx_t *dev, volatile uint8_t *addr) {
(void) dev;
return *addr;
}
#else
uint8_t at86rf2xx_reg_read(const at86rf2xx_t *dev, uint8_t addr); uint8_t at86rf2xx_reg_read(const at86rf2xx_t *dev, uint8_t addr);
#endif
/** /**
* @brief Write to a register at address `addr` from device `dev`. * @brief Write to a register at address `addr` from device `dev`.
@ -90,7 +102,15 @@ uint8_t at86rf2xx_reg_read(const at86rf2xx_t *dev, uint8_t addr);
* @param[in] addr address of the register to write * @param[in] addr address of the register to write
* @param[in] value value to write to the given register * @param[in] value value to write to the given register
*/ */
#if defined(MODULE_AT86RFA1) || defined(MODULE_AT86RFR2)
static inline void at86rf2xx_reg_write(const at86rf2xx_t *dev, volatile uint8_t *addr,
const uint8_t value) {
(void) dev;
*addr = value;
}
#else
void at86rf2xx_reg_write(const at86rf2xx_t *dev, uint8_t addr, uint8_t value); void at86rf2xx_reg_write(const at86rf2xx_t *dev, uint8_t addr, uint8_t value);
#endif
/** /**
* @brief Read a chunk of data from the SRAM of the given device * @brief Read a chunk of data from the SRAM of the given device
@ -100,9 +120,16 @@ void at86rf2xx_reg_write(const at86rf2xx_t *dev, uint8_t addr, uint8_t value);
* @param[out] data buffer to read data into * @param[out] data buffer to read data into
* @param[in] len number of bytes to read from SRAM * @param[in] len number of bytes to read from SRAM
*/ */
#if defined(MODULE_AT86RFA1) || defined(MODULE_AT86RFR2)
static inline void at86rf2xx_sram_read(const at86rf2xx_t *dev, uint8_t offset,
uint8_t *data, size_t len) {
(void)dev;
memcpy(data, (void*)(AT86RF2XX_REG__TRXFBST + offset), len);
}
#else
void at86rf2xx_sram_read(const at86rf2xx_t *dev, uint8_t offset, void at86rf2xx_sram_read(const at86rf2xx_t *dev, uint8_t offset,
uint8_t *data, size_t len); uint8_t *data, size_t len);
#endif
/** /**
* @brief Write a chunk of data into the SRAM of the given device * @brief Write a chunk of data into the SRAM of the given device
* *
@ -111,9 +138,16 @@ void at86rf2xx_sram_read(const at86rf2xx_t *dev, uint8_t offset,
* @param[in] data data to copy into SRAM * @param[in] data data to copy into SRAM
* @param[in] len number of bytes to write to SRAM * @param[in] len number of bytes to write to SRAM
*/ */
#if defined(MODULE_AT86RFA1) || defined(MODULE_AT86RFR2)
static inline void at86rf2xx_sram_write(const at86rf2xx_t *dev, uint8_t offset,
const uint8_t *data, size_t len) {
(void)dev;
memcpy((void*)(AT86RF2XX_REG__TRXFBST + offset), data, len);
}
#else
void at86rf2xx_sram_write(const at86rf2xx_t *dev, uint8_t offset, void at86rf2xx_sram_write(const at86rf2xx_t *dev, uint8_t offset,
const uint8_t *data, size_t len); const uint8_t *data, size_t len);
#endif
/** /**
* @brief Start a read transcation internal frame buffer of the given device * @brief Start a read transcation internal frame buffer of the given device
* *
@ -122,8 +156,13 @@ void at86rf2xx_sram_write(const at86rf2xx_t *dev, uint8_t offset,
* *
* @param[in] dev device to start read * @param[in] dev device to start read
*/ */
#if defined(MODULE_AT86RFA1) || defined(MODULE_AT86RFR2)
static inline void at86rf2xx_fb_start(const at86rf2xx_t *dev) {
(void) dev;
}
#else
void at86rf2xx_fb_start(const at86rf2xx_t *dev); void at86rf2xx_fb_start(const at86rf2xx_t *dev);
#endif
/** /**
* @brief Read the internal frame buffer of the given device * @brief Read the internal frame buffer of the given device
* *
@ -133,8 +172,14 @@ void at86rf2xx_fb_start(const at86rf2xx_t *dev);
* @param[out] data buffer to copy the data to * @param[out] data buffer to copy the data to
* @param[in] len number of bytes to read from the frame buffer * @param[in] len number of bytes to read from the frame buffer
*/ */
#if defined(MODULE_AT86RFA1) || defined(MODULE_AT86RFR2)
static inline void at86rf2xx_fb_read(const at86rf2xx_t *dev, uint8_t *data, size_t len) {
(void)dev;
memcpy(data, (void*)AT86RF2XX_REG__TRXFBST, len);
}
#else
void at86rf2xx_fb_read(const at86rf2xx_t *dev, uint8_t *data, size_t len); void at86rf2xx_fb_read(const at86rf2xx_t *dev, uint8_t *data, size_t len);
#endif
/** /**
* @brief Stop a read transcation internal frame buffer of the given device * @brief Stop a read transcation internal frame buffer of the given device
* *
@ -142,8 +187,13 @@ void at86rf2xx_fb_read(const at86rf2xx_t *dev, uint8_t *data, size_t len);
* *
* @param[in] dev device to stop read * @param[in] dev device to stop read
*/ */
#if defined(MODULE_AT86RFA1) || defined(MODULE_AT86RFR2)
static inline void at86rf2xx_fb_stop(const at86rf2xx_t *dev) {
(void) dev;
}
#else
void at86rf2xx_fb_stop(const at86rf2xx_t *dev); void at86rf2xx_fb_stop(const at86rf2xx_t *dev);
#endif
/** /**
* @brief Convenience function for reading the status of the given device * @brief Convenience function for reading the status of the given device
* *
@ -175,7 +225,7 @@ void at86rf2xx_hardware_reset(at86rf2xx_t *dev);
*/ */
void at86rf2xx_configure_phy(at86rf2xx_t *dev); void at86rf2xx_configure_phy(at86rf2xx_t *dev);
#if defined(MODULE_AT86RF233) || defined(MODULE_AT86RF231) || defined(DOXYGEN) #if AT86RF2XX_RANDOM_NUMBER_GENERATOR || defined(DOXYGEN)
/** /**
* @brief Read random data from the RNG * @brief Read random data from the RNG
* *

View File

@ -62,10 +62,17 @@ extern "C" {
/** /**
* @brief AT86RF231 configuration * @brief AT86RF231 configuration
*/ */
#if defined(MODULE_AT86RFA1) || defined(MODULE_AT86RFR2)
static const uint8_t at86rf2xx_params[] =
{
0 /* dummy value */
};
#else
static const at86rf2xx_params_t at86rf2xx_params[] = static const at86rf2xx_params_t at86rf2xx_params[] =
{ {
AT86RF2XX_PARAMS AT86RF2XX_PARAMS
}; };
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -38,6 +38,8 @@ extern "C" {
#define AT86RF231_PARTNUM (0x03) #define AT86RF231_PARTNUM (0x03)
#define AT86RF232_PARTNUM (0x0a) #define AT86RF232_PARTNUM (0x0a)
#define AT86RF233_PARTNUM (0x0b) #define AT86RF233_PARTNUM (0x0b)
#define AT86RFA1_PARTNUM (0x83)
#define AT86RFR2_PARTNUM (0x94)
/** @} */ /** @} */
/** /**
@ -50,11 +52,137 @@ extern "C" {
#define AT86RF2XX_PARTNUM AT86RF232_PARTNUM #define AT86RF2XX_PARTNUM AT86RF232_PARTNUM
#elif MODULE_AT86RF233 #elif MODULE_AT86RF233
#define AT86RF2XX_PARTNUM AT86RF233_PARTNUM #define AT86RF2XX_PARTNUM AT86RF233_PARTNUM
#elif MODULE_AT86RFA1
#define AT86RF2XX_PARTNUM AT86RFA1_PARTNUM
#elif MODULE_AT86RFR2
#define AT86RF2XX_PARTNUM AT86RFR2_PARTNUM
#else /* MODULE_AT86RF231 as default device */ #else /* MODULE_AT86RF231 as default device */
#define AT86RF2XX_PARTNUM AT86RF231_PARTNUM #define AT86RF2XX_PARTNUM AT86RF231_PARTNUM
#endif #endif
/** @} */ /** @} */
/*
* memory-mapped transceiver
*/
#if defined(MODULE_AT86RFA1) || defined(MODULE_AT86RFR2)
#include <avr/io.h>
/**
* @name Register addresses
* @{
*/
#define AT86RF2XX_REG__TRX_STATUS (&TRX_STATUS)
#define AT86RF2XX_REG__TRX_STATE (&TRX_STATE)
#define AT86RF2XX_REG__TRX_CTRL_0 (&TRX_CTRL_0)
#define AT86RF2XX_REG__TRX_CTRL_1 (&TRX_CTRL_1)
#define AT86RF2XX_REG__PHY_TX_PWR (&PHY_TX_PWR)
#define AT86RF2XX_REG__PHY_RSSI (&PHY_RSSI)
#define AT86RF2XX_REG__PHY_ED_LEVEL (&PHY_ED_LEVEL)
#define AT86RF2XX_REG__PHY_CC_CCA (&PHY_CC_CCA)
#define AT86RF2XX_REG__CCA_THRES (&CCA_THRES)
#define AT86RF2XX_REG__RX_CTRL (&RX_CTRL)
#define AT86RF2XX_REG__SFD_VALUE (&SFD_VALUE)
#define AT86RF2XX_REG__TRX_CTRL_2 (&TRX_CTRL_2)
#define AT86RF2XX_REG__ANT_DIV (&ANT_DIV)
#define AT86RF2XX_REG__IRQ_MASK (&IRQ_MASK)
#define AT86RF2XX_REG__IRQ_STATUS (&IRQ_STATUS)
#define AT86RF2XX_REG__IRQ_STATUS1 (&IRQ_STATUS1)
#define AT86RF2XX_REG__VREG_CTRL (&VREG_CTRL)
#define AT86RF2XX_REG__BATMON (&BATMON)
#define AT86RF2XX_REG__XOSC_CTRL (&XOSC_CTRL)
#define AT86RF2XX_REG__CC_CTRL_0 (&CC_CTRL_0)
#define AT86RF2XX_REG__CC_CTRL_1 (&CC_CTRL_1)
#define AT86RF2XX_REG__RX_SYN (&RX_SYN)
#define AT86RF2XX_REG__XAH_CTRL_1 (&XAH_CTRL_1)
#define AT86RF2XX_REG__FTN_CTRL (&FTN_CTRL)
#define AT86RF2XX_REG__PLL_CF (&PLL_CF)
#define AT86RF2XX_REG__PLL_DCU (&PLL_DCU)
#define AT86RF2XX_REG__PART_NUM (&PART_NUM)
#define AT86RF2XX_REG__VERSION_NUM (&VERSION_NUM)
#define AT86RF2XX_REG__MAN_ID_0 (&MAN_ID_0)
#define AT86RF2XX_REG__MAN_ID_1 (&MAN_ID_1)
#define AT86RF2XX_REG__SHORT_ADDR_0 (&SHORT_ADDR_0)
#define AT86RF2XX_REG__SHORT_ADDR_1 (&SHORT_ADDR_1)
#define AT86RF2XX_REG__PAN_ID_0 (&PAN_ID_0)
#define AT86RF2XX_REG__PAN_ID_1 (&PAN_ID_1)
#define AT86RF2XX_REG__IEEE_ADDR_0 (&IEEE_ADDR_0)
#define AT86RF2XX_REG__IEEE_ADDR_1 (&IEEE_ADDR_1)
#define AT86RF2XX_REG__IEEE_ADDR_2 (&IEEE_ADDR_2)
#define AT86RF2XX_REG__IEEE_ADDR_3 (&IEEE_ADDR_3)
#define AT86RF2XX_REG__IEEE_ADDR_4 (&IEEE_ADDR_4)
#define AT86RF2XX_REG__IEEE_ADDR_5 (&IEEE_ADDR_5)
#define AT86RF2XX_REG__IEEE_ADDR_6 (&IEEE_ADDR_6)
#define AT86RF2XX_REG__IEEE_ADDR_7 (&IEEE_ADDR_7)
#define AT86RF2XX_REG__XAH_CTRL_0 (&XAH_CTRL_0)
#define AT86RF2XX_REG__CSMA_SEED_0 (&CSMA_SEED_0)
#define AT86RF2XX_REG__CSMA_SEED_1 (&CSMA_SEED_1)
#define AT86RF2XX_REG__CSMA_BE (&CSMA_BE)
#define AT86RF2XX_REG__TST_CTRL_DIGI (&TST_CTRL_DIGI)
#define AT86RF2XX_REG__TRXFBST (&TRXFBST)
#define AT86RF2XX_REG__TRXFBEND (&TRXFBEND)
#define AT86RF2XX_REG__TRXPR (&TRXPR)
/** @} */
/**
* @name Bitfield definitions for the TRX_CTRL_0 register
* @{
*/
#define AT86RF2XX_TRX_CTRL_0_MASK__PMU_EN (0x40)
#define AT86RF2XX_TRX_CTRL_0_MASK__PMU_START (0x20)
#define AT86RF2XX_TRX_CTRL_0_MASK__PMU_IF_INV (0x10)
/** @} */
/**
* @name Bitfield definitions for the TRX_CTRL_1 register
* @{
*/
#define AT86RF2XX_TRX_CTRL_1_MASK__PA_EXT_EN (0x80)
#define AT86RF2XX_TRX_CTRL_1_MASK__IRQ_2_EXT_EN (0x40)
#define AT86RF2XX_TRX_CTRL_1_MASK__TX_AUTO_CRC_ON (0x20)
#define AT86RF2XX_TRX_CTRL_1_MASK__PLL_TX_FLT (0x10)
/** @} */
/**
* @name Bitfield definitions for the TRX_CTRL_2 register
* @{
*/
#define AT86RF2XX_TRX_CTRL_2_MASK__RX_SAFE_MODE (0x80)
#define AT86RF2XX_TRX_CTRL_2_MASK__OQPSK_DATA_RATE (0x03)
/** @} */
/**
* @name Bitfield definitions for the IRQ_MASK/IRQ_STATUS register
* @{
*/
#define AT86RF2XX_IRQ_STATUS_MASK__AWAKE (0x80)
#define AT86RF2XX_IRQ_STATUS_MASK__TX_END (0x40)
#define AT86RF2XX_IRQ_STATUS_MASK__AMI (0x20)
#define AT86RF2XX_IRQ_STATUS_MASK__CCA_ED_DONE (0x10)
#define AT86RF2XX_IRQ_STATUS_MASK__RX_END (0x08)
#define AT86RF2XX_IRQ_STATUS_MASK__RX_START (0x04)
#define AT86RF2XX_IRQ_STATUS_MASK__PLL_UNLOCK (0x02)
#define AT86RF2XX_IRQ_STATUS_MASK__PLL_LOCK (0x01)
/* Map TX_END and RX_END to TRX_END to be compatible to SPI Devices */
#define AT86RF2XX_IRQ_STATUS_MASK__TRX_END (0x48)
/**
* @name Bitfield definitions for the IRQ_MASK1/IRQ_STATUS1 register
* @{
*/
#define AT86RF2XX_IRQ_STATUS_MASK1__TX_START (0x01)
#define AT86RF2XX_IRQ_STATUS_MASK1__MAF_0_AMI (0x02)
#define AT86RF2XX_IRQ_STATUS_MASK1__MAF_1_AMI (0x04)
#define AT86RF2XX_IRQ_STATUS_MASK1__MAF_2_AMI (0x08)
#define AT86RF2XX_IRQ_STATUS_MASK1__MAF_3_AMI (0x10)
/** @} */
#else
/*
* SPI based transceiver
*/
/** /**
* @name SPI access specifiers * @name SPI access specifiers
* @{ * @{
@ -190,6 +318,7 @@ extern "C" {
#define AT86RF2XX_IRQ_STATUS_MASK__PLL_LOCK (0x01) #define AT86RF2XX_IRQ_STATUS_MASK__PLL_LOCK (0x01)
/** @} */ /** @} */
#endif /* END external spi transceiver */
/** /**
* @name Bitfield definitions for the TRX_STATUS register * @name Bitfield definitions for the TRX_STATUS register
* @{ * @{
@ -363,6 +492,18 @@ extern "C" {
#define AT86RF2XX_CSMA_SEED_1__CSMA_SEED_1 (0x07) #define AT86RF2XX_CSMA_SEED_1__CSMA_SEED_1 (0x07)
/** @} */ /** @} */
/**
* @name Bitfield definitions for the TRXPR Transceiver Pin Register
* @{
*/
#if defined(MODULE_AT86RFA1) || defined(MODULE_AT86RFR2)
#define AT86RF2XX_TRXPR_ATBE (0x08)
#define AT86RF2XX_TRXPR_TRXTST (0x04)
#define AT86RF2XX_TRXPR_SLPTR (0x02)
#define AT86RF2XX_TRXPR_TRXRST (0x01)
#endif
/** @} */
/** /**
* @name Bitfield definitions for the RF_CTRL_0 register * @name Bitfield definitions for the RF_CTRL_0 register
* @{ * @{

View File

@ -33,12 +33,16 @@
#include <stdbool.h> #include <stdbool.h>
#include "board.h" #include "board.h"
#include "periph/spi.h"
#include "periph/gpio.h"
#include "net/netdev.h" #include "net/netdev.h"
#include "net/netdev/ieee802154.h" #include "net/netdev/ieee802154.h"
#include "net/gnrc/nettype.h" #include "net/gnrc/nettype.h"
/* we need no peripherals for memory mapped radios */
#if !defined(MODULE_AT86RFA1) && !defined(MODULE_AT86RFR2)
#include "periph/spi.h"
#include "periph/gpio.h"
#endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -83,6 +87,8 @@ extern "C" {
* for other seetings this value may change. * for other seetings this value may change.
*/ */
# define RSSI_BASE_VAL (-98) # define RSSI_BASE_VAL (-98)
#elif MODULE_AT86RFA1 || MODULE_AT86RFR2
# define RSSI_BASE_VAL (-90)
#else #else
# define RSSI_BASE_VAL (-91) # define RSSI_BASE_VAL (-91)
#endif #endif
@ -94,6 +100,8 @@ extern "C" {
# define MAX_RX_SENSITIVITY (-52) # define MAX_RX_SENSITIVITY (-52)
#elif MODULE_AT86RF212B #elif MODULE_AT86RF212B
# define MAX_RX_SENSITIVITY (-54) # define MAX_RX_SENSITIVITY (-54)
#elif MODULE_AT86RFA1 || MODULE_AT86RFR2
# define MAX_RX_SENSITIVITY (-48)
#else #else
# define MAX_RX_SENSITIVITY (-49) # define MAX_RX_SENSITIVITY (-49)
#endif #endif
@ -105,6 +113,8 @@ extern "C" {
# define MIN_RX_SENSITIVITY (-101) # define MIN_RX_SENSITIVITY (-101)
#elif MODULE_AT86RF212B #elif MODULE_AT86RF212B
# define MIN_RX_SENSITIVITY (-110) # define MIN_RX_SENSITIVITY (-110)
#elif MODULE_AT86RFA1 || MODULE_AT86RFR2
# define MIN_RX_SENSITIVITY (-100)
#else #else
# define MIN_RX_SENSITIVITY (-101) # define MIN_RX_SENSITIVITY (-101)
#endif #endif
@ -123,6 +133,23 @@ extern "C" {
#define AT86RF2XX_HAVE_RETRIES (0) #define AT86RF2XX_HAVE_RETRIES (0)
#endif #endif
/**
* @brief Random Number Generator
*
* Most AT86RF radios have the option to use the highest bits of the RSSI
* register as a source of randomness.
* See Section 11.2 of the at86rf233 reference manual. (RND_VALUE)
*/
#if defined(MODULE_AT86RF233) || defined(MODULE_AT86RF231) || defined(MODULE_AT86RFA1) || defined(MODULE_AT86RFR2)
#ifndef AT86RF2XX_RANDOM_NUMBER_GENERATOR
#define AT86RF2XX_RANDOM_NUMBER_GENERATOR (1)
#endif
#else
#ifndef AT86RF2XX_RANDOM_NUMBER_GENERATOR
#define AT86RF2XX_RANDOM_NUMBER_GENERATOR (0)
#endif
#endif
/** /**
* @brief Smart idle listening feature * @brief Smart idle listening feature
* *
@ -180,6 +207,12 @@ extern "C" {
/** @} */ /** @} */
#if defined(MODULE_AT86RFA1) || defined(MODULE_AT86RFR2)
/**
* @brief memory mapped radio needs no parameters
*/
typedef void at86rf2xx_params_t;
#else
/** /**
* @brief struct holding all params needed for device initialization * @brief struct holding all params needed for device initialization
*/ */
@ -191,6 +224,7 @@ typedef struct at86rf2xx_params {
gpio_t sleep_pin; /**< GPIO pin connected to the sleep pin */ gpio_t sleep_pin; /**< GPIO pin connected to the sleep pin */
gpio_t reset_pin; /**< GPIO pin connected to the reset pin */ gpio_t reset_pin; /**< GPIO pin connected to the reset pin */
} at86rf2xx_params_t; } at86rf2xx_params_t;
#endif
/** /**
* @brief Device descriptor for AT86RF2XX radio devices * @brief Device descriptor for AT86RF2XX radio devices
@ -199,8 +233,19 @@ typedef struct at86rf2xx_params {
*/ */
typedef struct { typedef struct {
netdev_ieee802154_t netdev; /**< netdev parent struct */ netdev_ieee802154_t netdev; /**< netdev parent struct */
#if defined(MODULE_AT86RFA1) || defined(MODULE_AT86RFR2)
/* ATmega256rfr2 signals transceiver events with different interrupts
* they have to be stored to mimic the same flow as external transceiver
* Use irq_status to map saved interrupts of SOC transceiver,
* as they clear after IRQ callback.
*
* irq_status = IRQ_STATUS
*/
uint8_t irq_status; /**< save irq status */
#else
/* device specific fields */ /* device specific fields */
at86rf2xx_params_t params; /**< parameters for initialization */ at86rf2xx_params_t params; /**< parameters for initialization */
#endif
uint16_t flags; /**< Device specific flags */ uint16_t flags; /**< Device specific flags */
uint8_t state; /**< current state of the radio */ uint8_t state; /**< current state of the radio */
uint8_t tx_frame_len; /**< length of the current TX frame */ uint8_t tx_frame_len; /**< length of the current TX frame */

View File

@ -36,7 +36,7 @@ USEMODULE += saul_default
BOARD_PROVIDES_NETIF := acd52832 airfy-beacon b-l072z-lrwan1 cc2538dk fox \ BOARD_PROVIDES_NETIF := acd52832 airfy-beacon b-l072z-lrwan1 cc2538dk fox \
hamilton iotlab-m3 iotlab-a8-m3 lobaro-lorabox lsn50 mulle microbit msba2 \ hamilton iotlab-m3 iotlab-a8-m3 lobaro-lorabox lsn50 mulle microbit msba2 \
native nrf51dk nrf51dongle nrf52dk nrf52840dk nrf52840-mdk nrf6310 \ microduino-corerf native nrf51dk nrf51dongle nrf52dk nrf52840dk nrf52840-mdk nrf6310 \
nucleo-f767zi openmote-b openmote-cc2538 pba-d-01-kw2x remote-pa remote-reva \ nucleo-f767zi openmote-b openmote-cc2538 pba-d-01-kw2x remote-pa remote-reva \
ruuvitag samr21-xpro samr30-xpro spark-core telosb thingy52 yunjia-nrf51822 z1 ruuvitag samr21-xpro samr30-xpro spark-core telosb thingy52 yunjia-nrf51822 z1

View File

@ -9,6 +9,7 @@ BOARD_INSUFFICIENT_MEMORY := \
i-nucleo-lrwan1 \ i-nucleo-lrwan1 \
msb-430 \ msb-430 \
msb-430h \ msb-430h \
microduino-corerf \
nucleo-f030r8 \ nucleo-f030r8 \
nucleo-f031k6 \ nucleo-f031k6 \
nucleo-f042k6 \ nucleo-f042k6 \

View File

@ -94,6 +94,8 @@ PSEUDOMODULES += od_string
# include variants of the AT86RF2xx drivers as pseudo modules # include variants of the AT86RF2xx drivers as pseudo modules
PSEUDOMODULES += at86rf23% PSEUDOMODULES += at86rf23%
PSEUDOMODULES += at86rf21% PSEUDOMODULES += at86rf21%
PSEUDOMODULES += at86rfa1
PSEUDOMODULES += at86rfr2
# include variants of the BMX280 drivers as pseudo modules # include variants of the BMX280 drivers as pseudo modules
PSEUDOMODULES += bmp280 PSEUDOMODULES += bmp280

View File

@ -9,6 +9,7 @@ BOARD_INSUFFICIENT_MEMORY := \
i-nucleo-lrwan1 \ i-nucleo-lrwan1 \
msb-430 \ msb-430 \
msb-430h \ msb-430h \
microduino-corerf \
nucleo-f030r8 \ nucleo-f030r8 \
nucleo-f031k6 \ nucleo-f031k6 \
nucleo-f042k6 \ nucleo-f042k6 \

View File

@ -16,6 +16,7 @@ BOARD_INSUFFICIENT_MEMORY := \
nucleo-f334r8 \ nucleo-f334r8 \
nucleo-l031k6 \ nucleo-l031k6 \
nucleo-l053r8 \ nucleo-l053r8 \
microduino-corerf \
stm32f030f4-demo \ stm32f030f4-demo \
stm32f0discovery \ stm32f0discovery \
stm32l0538-disco \ stm32l0538-disco \