1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
18472: drivers/mrf24j40: add support for IEEE 802.15.4 Radio HAL r=benpicco a=jia200x



19175: drivers/periph_common/flashpage: fix silent error r=benpicco a=Enoch247

### Contribution description

This patch removes a test that silently hides failed writes to NULL. Instead, assert is used to ensure that the address is not NULL.


### Testing procedure

I am not certain how to update the tests to catch asserts. If this is possible, I will add a test, if someone will point me to a good example to learn from.


### Issues/PRs references

- none


Co-authored-by: Jose Alamos <jose@alamos.cc>
Co-authored-by: Joshua DeWeese <jdeweese@primecontrols.com>
This commit is contained in:
bors[bot] 2023-01-19 18:17:13 +00:00 committed by GitHub
commit d11a358b1d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 818 additions and 1048 deletions

View File

@ -87,6 +87,32 @@ static const motor_driver_config_t motor_driver_config[] = {
#define MOTOR_DRIVER_NUMOF ARRAY_SIZE(motor_driver_config)
/** @} */
/**
* @name Describe MRF24J40 radio
* @{
*/
#ifndef MRF24J40_PARAM_SPI
#define MRF24J40_PARAM_SPI SPI_DEV(0)
#endif
#ifndef MRF24J40_PARAM_SPI_CLK
#define MRF24J40_PARAM_SPI_CLK SPI_CLK_5MHZ
#endif
#ifndef MRF24J40_PARAM_CS
#define MRF24J40_PARAM_CS ARDUINO_PIN_10
#endif
#ifndef MRF24J40_PARAM_INT
#define MRF24J40_PARAM_INT ARDUINO_PIN_7
#endif
#ifndef MRF24J40_PARAM_RESET
#define MRF24J40_PARAM_RESET ARDUINO_PIN_5
#endif
/** @} */
#ifdef __cplusplus
}
#endif

View File

@ -66,6 +66,8 @@ extern "C" {
#define BIT7 0x00000080 /**< Bit 7 set define */
#define BIT8 0x00000100 /**< Bit 8 set define */
#define BIT9 0x00000200 /**< Bit 9 set define */
#endif
#ifndef BIT10
#define BIT10 0x00000400 /**< Bit 10 set define */
#define BIT11 0x00000800 /**< Bit 11 set define */
#define BIT12 0x00001000 /**< Bit 12 set define */

View File

@ -11,6 +11,7 @@ config CPU_MODEL_ATMEGA128RFA1
select CPU_FAM_ATMEGA128
select HAS_CPU_ATMEGA128RFA1
select HAS_ATMEGA_PCINT1
select HAVE_AT86RFA1
## Definition of specific features
config HAS_CPU_ATMEGA128RFA1

View File

@ -15,6 +15,7 @@ config CPU_MODEL_ATMEGA256RFR2
select CPU_FAM_ATMEGA256RF
select HAS_ATMEGA_PCINT1
select HAS_CPU_ATMEGA256RFR2
select HAVE_AT86RFR2
## Definition of specific features
config HAS_CPU_ATMEGA256RFR2

View File

@ -902,6 +902,12 @@ boards/common/nucleo64/include/arduino_pinmap\.h:[0-9]+: warning: Member ARDUINO
boards/common/nucleo64/include/arduino_pinmap\.h:[0-9]+: warning: Member ARDUINO_PIN_A5 \(macro definition\) of file arduino_pinmap\.h is not documented\.
boards/common/nucleo64/include/board\.h:[0-9]+: warning: Member MOTOR_DRIVER_NUMOF \(macro definition\) of group boards_common_nucleo64 is not documented\.
boards/common/nucleo64/include/board\.h:[0-9]+: warning: Member motor_driver_config\[\] \(variable\) of group boards_common_nucleo64 is not documented\.
boards/common/nucleo64/include/board\.h:[0-9]+: warning: Member MRF24J40_PARAMS \(macro definition\) of group boards_common_nucleo64 is not documented\.
boards/common/nucleo64/include/board\.h:[0-9]+: warning: Member MRF24J40_PARAM_CS \(macro definition\) of group boards_common_nucleo64 is not documented\.
boards/common/nucleo64/include/board\.h:[0-9]+: warning: Member MRF24J40_PARAM_INT \(macro definition\) of group boards_common_nucleo64 is not documented\.
boards/common/nucleo64/include/board\.h:[0-9]+: warning: Member MRF24J40_PARAM_RESET \(macro definition\) of group boards_common_nucleo64 is not documented\.
boards/common/nucleo64/include/board\.h:[0-9]+: warning: Member MRF24J40_PARAM_SPI \(macro definition\) of group boards_common_nucleo64 is not documented\.
boards/common/nucleo64/include/board\.h:[0-9]+: warning: Member MRF24J40_PARAM_SPI_CLK \(macro definition\) of group boards_common_nucleo64 is not documented\.
boards/common/particle\-mesh/include/board\.h:[0-9]+: warning: Member LED_MASK \(macro definition\) of file board\.h is not documented\.
boards/common/particle\-mesh/include/board\.h:[0-9]+: warning: Member LED_PORT \(macro definition\) of file board\.h is not documented\.
boards/common/particle\-mesh/include/periph_conf_common\.h:[0-9]+: warning: Member PWM_NUMOF \(macro definition\) of file periph_conf_common\.h is not documented\.
@ -9100,6 +9106,13 @@ drivers/mrf24j40/include/mrf24j40_registers\.h:[0-9]+: warning: Member MRF24J40_
drivers/mrf24j40/include/mrf24j40_registers\.h:[0-9]+: warning: Member MRF24J40_PACON2_TXONTS2 \(macro definition\) of file mrf24j40_registers\.h is not documented\.
drivers/mrf24j40/include/mrf24j40_registers\.h:[0-9]+: warning: Member MRF24J40_PACON2_TXONTS3 \(macro definition\) of file mrf24j40_registers\.h is not documented\.
drivers/mrf24j40/include/mrf24j40_registers\.h:[0-9]+: warning: Member MRF24J40_REG_ACKTMOUT \(macro definition\) of file mrf24j40_registers\.h is not documented\.
drivers/mrf24j40/include/mrf24j40_registers\.h:[0-9]+: warning: Member MRF24J40_ACKTMOUT_MAWD0 \(macro definition\) of file mrf24j40_registers\.h is not documented\.
drivers/mrf24j40/include/mrf24j40_registers\.h:[0-9]+: warning: Member MRF24J40_ACKTMOUT_MAWD1 \(macro definition\) of file mrf24j40_registers\.h is not documented\.
drivers/mrf24j40/include/mrf24j40_registers\.h:[0-9]+: warning: Member MRF24J40_ACKTMOUT_MAWD2 \(macro definition\) of file mrf24j40_registers\.h is not documented\.
drivers/mrf24j40/include/mrf24j40_registers\.h:[0-9]+: warning: Member MRF24J40_ACKTMOUT_MAWD3 \(macro definition\) of file mrf24j40_registers\.h is not documented\.
drivers/mrf24j40/include/mrf24j40_registers\.h:[0-9]+: warning: Member MRF24J40_ACKTMOUT_MAWD4 \(macro definition\) of file mrf24j40_registers\.h is not documented\.
drivers/mrf24j40/include/mrf24j40_registers\.h:[0-9]+: warning: Member MRF24J40_ACKTMOUT_MAWD5 \(macro definition\) of file mrf24j40_registers\.h is not documented\.
drivers/mrf24j40/include/mrf24j40_registers\.h:[0-9]+: warning: Member MRF24J40_ACKTMOUT_MAWD6 \(macro definition\) of file mrf24j40_registers\.h is not documented\.
drivers/mrf24j40/include/mrf24j40_registers\.h:[0-9]+: warning: Member MRF24J40_REG_ASSOEADR0 \(macro definition\) of file mrf24j40_registers\.h is not documented\.
drivers/mrf24j40/include/mrf24j40_registers\.h:[0-9]+: warning: Member MRF24J40_REG_ASSOEADR1 \(macro definition\) of file mrf24j40_registers\.h is not documented\.
drivers/mrf24j40/include/mrf24j40_registers\.h:[0-9]+: warning: Member MRF24J40_REG_ASSOEADR2 \(macro definition\) of file mrf24j40_registers\.h is not documented\.

View File

@ -122,7 +122,6 @@ endif
ifneq (,$(filter nrfmin,$(USEMODULE)))
FEATURES_REQUIRED += radio_nrfmin
FEATURES_REQUIRED += periph_cpuid
USEMODULE += netif
endif
ifneq (,$(filter nrf24l01p_ng_%,$(USEMODULE)))

View File

@ -71,6 +71,7 @@
#include "net/netdev.h"
#include "net/netdev/ieee802154.h"
#include "net/gnrc/nettype.h"
#include "net/ieee802154/radio.h"
#ifdef __cplusplus
extern "C" {
@ -105,6 +106,11 @@ extern "C" {
#define MRF24J40_MAX_FRAME_RETRIES (3U) /**< Number of frame retries (fixed) */
#define MRF24J40_MAX_MINBE (3U) /**< Maximum value of minimum
exponential backoff */
#define MRF24J40_MIN_TXPOWER (-36) /**< Minimum transmission power (dBm) */
#define MRF24J40_MAX_TXPOWER (0) /**< Maximum transmission power (dBm) */
/**
* @defgroup drivers_mrf24j40_config mrf24j40 driver compile configuration
* @ingroup drivers_mrf24j40
@ -151,29 +157,13 @@ typedef struct mrf24j40_params {
* @brief Device descriptor for MRF24J40 radio devices
*/
typedef struct {
netdev_ieee802154_t netdev; /**< netdev parent struct */
/* device specific fields */
mrf24j40_params_t params; /**< parameters for initialization */
uint8_t state; /**< current state of the radio */
uint8_t idle_state; /**< state to return to after sending */
uint8_t tx_frame_len; /**< length of the current TX frame */
uint8_t header_len; /**< length of the header */
const mrf24j40_params_t *params; /**< parameters for initialization */
uint8_t fcf_low; /**< Low 8 FCF bits of the current TX frame. */
uint8_t pending; /**< Flags for pending tasks */
uint8_t irq_flag; /**< Flags for IRQs */
uint8_t tx_retries; /**< Number of retries needed for last transmission */
bool tx_pending; /**< Whether a transmission is pending or not */
} mrf24j40_t;
/**
* @brief Setup an MRF24J40 based device state
*
* @param[out] dev device descriptor
* @param[in] params parameters for device initialization
* @param[in] index index of @p params in a global parameter struct array.
* If initialized manually, pass a unique identifier instead.
*/
void mrf24j40_setup(mrf24j40_t *dev, const mrf24j40_params_t *params, uint8_t index);
/**
* @brief Trigger a hardware reset and configure radio with default values
*
@ -183,26 +173,6 @@ void mrf24j40_setup(mrf24j40_t *dev, const mrf24j40_params_t *params, uint8_t in
*/
int mrf24j40_reset(mrf24j40_t *dev);
/**
* @brief Trigger a clear channel assessment & retrieve RSSI
*
* @param[in] dev device to use
* @param[in] rssi RSSI value from register in dBm
*
* @return true if channel is clear
* @return false if channel is busy
*/
bool mrf24j40_cca(mrf24j40_t *dev, int8_t *rssi);
/**
* @brief Get the short address of the given device
*
* @param[in] dev device to read from
*
* @return the currently set (2-byte) short address
*/
uint16_t mrf24j40_get_addr_short(mrf24j40_t *dev);
/**
* @brief Set the short address of the given device
*
@ -211,14 +181,6 @@ uint16_t mrf24j40_get_addr_short(mrf24j40_t *dev);
*/
void mrf24j40_set_addr_short(mrf24j40_t *dev, uint16_t addr);
/**
* @brief Get the configured long address of the given device
*
* @param[in] dev device to read from
* @param[out] addr the currently set (8-byte) long address
*/
void mrf24j40_get_addr_long(mrf24j40_t *dev, uint8_t *addr);
/**
* @brief Set the long address of the given device
*
@ -261,15 +223,6 @@ uint16_t mrf24j40_get_pan(mrf24j40_t *dev);
*/
void mrf24j40_set_pan(mrf24j40_t *dev, uint16_t pan);
/**
* @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 mrf24j40_get_txpower(mrf24j40_t *dev);
/**
* @brief Set the transmission power of the given device [in dBm]
*
@ -283,15 +236,6 @@ int16_t mrf24j40_get_txpower(mrf24j40_t *dev);
*/
void mrf24j40_set_txpower(mrf24j40_t *dev, int16_t txpower);
/**
* @brief Get the maximum number of channel access attempts per frame (CSMA)
*
* @param[in] dev device to read from
*
* @return configured number of retries
*/
uint8_t mrf24j40_get_csma_max_retries(mrf24j40_t *dev);
/**
* @brief Set the maximum number of channel access attempts per frame (CSMA)
*
@ -317,15 +261,6 @@ void mrf24j40_set_csma_max_retries(mrf24j40_t *dev, int8_t retries);
*/
void mrf24j40_set_csma_backoff_exp(mrf24j40_t *dev, uint8_t min, uint8_t max);
/**
* @brief Get the CCA threshold value
*
* @param[in] dev device to read value from
*
* @return the current CCA threshold value
*/
int8_t mrf24j40_get_cca_threshold(mrf24j40_t *dev);
/**
* @brief Set the CCA threshold value
*
@ -364,14 +299,6 @@ void mrf24j40_set_state(mrf24j40_t *dev, uint8_t state);
*/
void mrf24j40_set_turbo(mrf24j40_t *dev, bool enable);
/**
* @brief Query the state of the turbo mode
*
* @param[in] dev device to query
* @return true if Turbo Mode is enabled
*/
bool mrf24j40_get_turbo(mrf24j40_t *dev);
/**
* @brief Put in sleep mode
*
@ -379,19 +306,12 @@ bool mrf24j40_get_turbo(mrf24j40_t *dev);
*/
void mrf24j40_sleep(mrf24j40_t *dev);
/**
* @brief Put in sleep mode if idle_state is sleep
*
* @param[in] dev device to put to sleep
*/
void mrf24j40_assert_sleep(mrf24j40_t *dev);
/**
* @brief Wake up from sleep mode
*
* @param[in] dev device to eventually wake up
*/
void mrf24j40_assert_awake(mrf24j40_t *dev);
void mrf24j40_wake_up(mrf24j40_t *dev);
/**
* @brief Reset the internal state machine to TRX_OFF mode.
@ -452,6 +372,27 @@ size_t mrf24j40_tx_load(mrf24j40_t *dev, uint8_t *data, size_t len,
*/
void mrf24j40_tx_exec(mrf24j40_t *dev);
/**
* @brief IRQ Handler for the MRF24J40 device
*
* @param[in] dev pointer to the IEEE 802.15.4 Radio HAL descriptor
*/
void mrf24j40_radio_irq_handler(void *dev);
/**
* @brief Initialize the given MRF24J40 device
* @param[out] dev device descriptor
* @param[in] params parameters for device initialization
* @param[in] hal pointer to IEEE 802.15.4 Radio HAL descriptor
* @param[in] cb ISR callback
* @param[in] ctx context pointer handed to isr
*
* @return 0 on success
* @return <0 on error
*/
int mrf24j40_init(mrf24j40_t *dev, const mrf24j40_params_t *params, ieee802154_dev_t *hal,
gpio_cb_t cb, void *ctx);
#ifdef __cplusplus
}
#endif

View File

@ -13,14 +13,14 @@ menuconfig MODULE_MRF24J40
depends on HAS_PERIPH_GPIO
depends on HAS_PERIPH_GPIO_IRQ
depends on HAS_PERIPH_SPI
select MODULE_IEEE802154
select MODULE_NETDEV
select MODULE_NETDEV_IEEE802154
select MODULE_NETDEV_LEGACY_API
select MODULE_PERIPH_GPIO
select MODULE_PERIPH_GPIO_IRQ
select MODULE_PERIPH_SPI
select MODULE_XTIMER
select MODULE_IEEE802154
select MODULE_ZTIMER_USEC
select HAVE_BHP_IRQ_HANDLER
select HAVE_IEEE802154_RADIO_HAL_INTERFACE
select MRF24J40_OQPSK if MODULE_NETDEV
if MODULE_MRF24J40

View File

@ -1,11 +1,12 @@
USEMODULE += ztimer_usec
USEMODULE += ieee802154
USEMODULE += netdev_ieee802154
USEMODULE += netdev_legacy_api
USEMODULE += xtimer
USEMODULE += bhp
FEATURES_REQUIRED += periph_gpio
FEATURES_REQUIRED += periph_gpio_irq
FEATURES_REQUIRED += periph_spi
ifneq (,$(filter mrf24j40m%,$(USEMODULE)))
ifneq (,$(filter netdev,$(USEMODULE)))
USEMODULE += netdev_ieee802154_submac
DEFAULT_MODULE += netdev_ieee802154_oqpsk
endif

View File

@ -37,7 +37,7 @@ extern "C" {
*
* @return 0 on success, error otherwise
*/
int mrf24j40_init(mrf24j40_t *dev);
int mrf24j40_init_hw(mrf24j40_t *dev);
/**
* @brief Read from a register with a at address `addr` from device `dev`. Register with 8bit address
@ -151,6 +151,13 @@ void mrf24j40_enable_lna(mrf24j40_t *dev);
static inline void mrf24j40_enable_lna(mrf24j40_t *dev) { (void) dev; }
#endif
/**
* @brief Flush the RX FIFO
*
* @param[in] dev device to flush the RX FIFO
*/
void mrf24j40_flush_rx(mrf24j40_t *dev);
#ifdef __cplusplus
}
#endif

View File

@ -219,6 +219,28 @@ extern "C" {
/** @} */
/**
* @brief Shift offsets for TXMCR register (0x11)
* @{
*/
#define MRF24J40_TXMCR_MACMINBE_SHIFT (3U)
/** @} */
/**
* @brief Bitfield definitions for the ACKTMOUT register (0x12)
* @{
*/
#define MRF24J40_ACKTMOUT_DRPACK (0x80)
#define MRF24J40_ACKTMOUT_MAWD6 (0x40)
#define MRF24J40_ACKTMOUT_MAWD5 (0x20)
#define MRF24J40_ACKTMOUT_MAWD4 (0x10)
#define MRF24J40_ACKTMOUT_MAWD3 (0x08)
#define MRF24J40_ACKTMOUT_MAWD2 (0x04)
#define MRF24J40_ACKTMOUT_MAWD1 (0x02)
#define MRF24J40_ACKTMOUT_MAWD0 (0x01)
/** @} */
/**
* @name Bitfield definitions for the PACON2 register (0x18)
* @{

View File

@ -24,138 +24,37 @@
#include "mrf24j40_registers.h"
#include "mrf24j40_internal.h"
#include "mrf24j40_netdev.h"
#include "xtimer.h"
#include "ztimer.h"
#define ENABLE_DEBUG 0
#include "debug.h"
void mrf24j40_setup(mrf24j40_t *dev, const mrf24j40_params_t *params, uint8_t index)
{
netdev_t *netdev = &dev->netdev.netdev;
netdev->driver = &mrf24j40_driver;
/* initialize device descriptor */
dev->params = *params;
netdev_register(netdev, NETDEV_MRF24J40, index);
}
int mrf24j40_reset(mrf24j40_t *dev)
{
int res = mrf24j40_init(dev);
int res = mrf24j40_init_hw(dev);
if (res < 0) {
return res;
}
netdev_ieee802154_reset(&dev->netdev);
/* set device address */
netdev_ieee802154_setup(&dev->netdev);
/* set short and long address */
mrf24j40_set_addr_long(dev, dev->netdev.long_addr);
mrf24j40_set_addr_short(dev, unaligned_get_u16(dev->netdev.short_addr));
mrf24j40_set_chan(dev, CONFIG_IEEE802154_DEFAULT_CHANNEL);
/* configure Immediate Sleep and Wake-Up mode */
mrf24j40_reg_write_short(dev, MRF24J40_REG_WAKECON, MRF24J40_WAKECON_IMMWAKE);
/* set default options */
mrf24j40_set_option(dev, IEEE802154_FCF_PAN_COMP, true);
mrf24j40_set_option(dev, NETDEV_IEEE802154_SRC_MODE_LONG, true);
mrf24j40_set_option(dev, NETDEV_IEEE802154_ACK_REQ, true);
mrf24j40_set_option(dev, MRF24J40_OPT_CSMA, true);
/* go into RX state */
mrf24j40_reset_tasks(dev);
dev->state = 0;
mrf24j40_set_state(dev, MRF24J40_PSEUDO_STATE_IDLE);
DEBUG("mrf24j40_reset(): reset complete.\n");
return 0;
}
bool mrf24j40_cca(mrf24j40_t *dev, int8_t *rssi)
{
uint8_t tmp_ccaedth;
uint8_t status;
uint8_t tmp_rssi;
mrf24j40_assert_awake(dev);
mrf24j40_enable_lna(dev);
/* trigger CCA measurement */
/* take a look onto datasheet chapter 3.6.1 */
mrf24j40_reg_write_short(dev, MRF24J40_REG_BBREG6, MRF24J40_BBREG6_RSSIMODE1);
/* wait for result to be ready */
do {
status = mrf24j40_reg_read_short(dev, MRF24J40_REG_BBREG6);
} while (!(status & MRF24J40_BBREG2_RSSIRDY));
mrf24j40_assert_sleep(dev);
/* return according to measurement */
tmp_ccaedth = mrf24j40_reg_read_short(dev, MRF24J40_REG_CCAEDTH); /* Energy detection threshold */
tmp_rssi = mrf24j40_reg_read_long(dev, MRF24J40_REG_RSSI);
if (rssi != NULL) {
*rssi = mrf24j40_dbm_from_reg(tmp_rssi);
}
mrf24j40_enable_auto_pa_lna(dev);
if (tmp_rssi < tmp_ccaedth) {
/* channel is clear */
return true; /* idle */
}
else {
/* channel is busy */
return false;
}
}
void mrf24j40_tx_prepare(mrf24j40_t *dev)
{
DEBUG("[mrf24j40] TX_Prepare, Current state: %x\n", dev->state);
do {
mrf24j40_update_tasks(dev);
} while (!(dev->pending & MRF24J40_TASK_TX_DONE));
mrf24j40_assert_awake(dev);
dev->pending &= ~(MRF24J40_TASK_TX_DONE);
dev->tx_frame_len = IEEE802154_FCS_LEN;
}
size_t mrf24j40_tx_load(mrf24j40_t *dev, uint8_t *data, size_t len, size_t offset)
{
DEBUG("[mrf24j40] TX_load, Current state: %x\n", dev->state);
dev->tx_frame_len += (uint8_t)len;
DEBUG("[mrf24j40] TX_load\n");
mrf24j40_tx_normal_fifo_write(dev, MRF24J40_TX_NORMAL_FIFO + offset + 2, data, len);
return offset + len;
}
void mrf24j40_tx_exec(mrf24j40_t *dev)
{
netdev_t *netdev = &dev->netdev.netdev;
dev->tx_frame_len = dev->tx_frame_len - IEEE802154_FCS_LEN;
/* write frame length field in FIFO */
mrf24j40_tx_normal_fifo_write(dev, MRF24J40_TX_NORMAL_FIFO + 1, &(dev->tx_frame_len), 1);
/* write header length to FIFO address 0x00 */
/* from figure 3-11 datasheet: header length = 2 Bytes Frame Control
* + 1 Byte Seq. No.
* + 4 to 20 Bytes Addressing Fields
*/
mrf24j40_reg_write_long(dev, MRF24J40_TX_NORMAL_FIFO, dev->header_len);
if (dev->fcf_low & IEEE802154_FCF_ACK_REQ) {
mrf24j40_reg_write_short(dev, MRF24J40_REG_TXNCON, MRF24J40_TXNCON_TXNACKREQ | MRF24J40_TXNCON_TXNTRIG);
}
else {
mrf24j40_reg_write_short(dev, MRF24J40_REG_TXNCON, MRF24J40_TXNCON_TXNTRIG);
}
if (netdev->event_callback) {
netdev->event_callback(netdev, NETDEV_EVENT_TX_STARTED);
}
}

View File

@ -24,7 +24,7 @@
#include "mrf24j40.h"
#include "mrf24j40_internal.h"
#include "mrf24j40_registers.h"
#include "xtimer.h"
#include "ztimer.h"
#define ENABLE_DEBUG 0
#include "debug.h"
@ -64,11 +64,6 @@
* 0b11111000 -> -36.3dB-> -36
*/
static const int16_t tx_pow_to_dbm[] = { 0, 0, -1, -2, -3, -4, -5, -6,
-10, -10, -11, -12, -13, -14, -15, -16,
-20, -20, -21, -22, -23, -24, -25, -26,
-30, -30, -31, -32, -33, -34, -35, -36 };
static const uint8_t dbm_to_tx_pow[] = { 0x00, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38, 0x38, 0x38, 0x40,
0x40, 0x50, 0x58, 0x60, 0x68, 0x70, 0x78, 0x78, 0x78, 0x80,
0x80, 0x90, 0x98, 0xa0, 0xa8, 0xb0, 0xb8, 0xb8, 0xb8, 0xc0,
@ -130,15 +125,6 @@ static void mrf24j40_baseband_reset(mrf24j40_t *dev)
} while (softrst != 0); /* wait until soft-reset has finished */
}
uint16_t mrf24j40_get_addr_short(mrf24j40_t *dev)
{
network_uint16_t naddr;
naddr.u8[1] = mrf24j40_reg_read_short(dev, MRF24J40_REG_SADRL);
naddr.u8[0] = mrf24j40_reg_read_short(dev, MRF24J40_REG_SADRH);
return naddr.u16;
}
void mrf24j40_set_addr_short(mrf24j40_t *dev, uint16_t addr)
{
network_uint16_t naddr;
@ -156,13 +142,6 @@ void mrf24j40_set_addr_short(mrf24j40_t *dev, uint16_t addr)
naddr.u8[0]);
}
void mrf24j40_get_addr_long(mrf24j40_t *dev, uint8_t *addr)
{
for (int i = 0; i < 8; i++) {
addr[7 - i] = mrf24j40_reg_read_short(dev, MRF24J40_REG_EADR0 + i);
}
}
void mrf24j40_set_addr_long(mrf24j40_t *dev, const uint8_t *addr)
{
for (int i = 0; i < 8; i++) {
@ -170,11 +149,6 @@ void mrf24j40_set_addr_long(mrf24j40_t *dev, const uint8_t *addr)
}
}
uint8_t mrf24j40_get_chan(mrf24j40_t *dev)
{
return dev->netdev.chan;
}
void mrf24j40_set_chan(mrf24j40_t *dev, uint8_t channel)
{
uint8_t channel_value;
@ -184,8 +158,6 @@ void mrf24j40_set_chan(mrf24j40_t *dev, uint8_t channel)
return;
}
dev->netdev.chan = channel;
/* Channel settings
* 11 -> Value = 0x03
* 12 -> Value = 0x13
@ -251,11 +223,6 @@ void mrf24j40_set_chan(mrf24j40_t *dev, uint8_t channel)
mrf24j40_reset_state_machine(dev);
}
uint16_t mrf24j40_get_pan(mrf24j40_t *dev)
{
return dev->netdev.pan;
}
void mrf24j40_set_pan(mrf24j40_t *dev, uint16_t pan)
{
le_uint16_t le_pan = byteorder_htols(pan);
@ -265,14 +232,6 @@ void mrf24j40_set_pan(mrf24j40_t *dev, uint16_t pan)
mrf24j40_reg_write_short(dev, MRF24J40_REG_PANIDH, le_pan.u8[1]);
}
int16_t mrf24j40_get_txpower(mrf24j40_t *dev)
{
uint8_t txpower;
txpower = (mrf24j40_reg_read_long(dev, MRF24J40_REG_RFCON3) >> 3) & 0x1F;
return tx_pow_to_dbm[txpower];
}
void mrf24j40_set_txpower(mrf24j40_t *dev, int16_t txpower)
{
uint8_t txpower_reg_value;
@ -286,15 +245,6 @@ void mrf24j40_set_txpower(mrf24j40_t *dev, int16_t txpower)
}
uint8_t mrf24j40_get_csma_max_retries(mrf24j40_t *dev)
{
uint8_t tmp;
tmp = mrf24j40_reg_read_short(dev, MRF24J40_REG_TXMCR);
tmp &= MRF24J40_TXMCR_CSMA_BACKOFF_MASK;
return tmp;
}
void mrf24j40_set_csma_max_retries(mrf24j40_t *dev, int8_t retries)
{
uint8_t tmp;
@ -308,15 +258,6 @@ void mrf24j40_set_csma_max_retries(mrf24j40_t *dev, int8_t retries)
mrf24j40_reg_write_short(dev, MRF24J40_REG_TXMCR, tmp);
}
int8_t mrf24j40_get_cca_threshold(mrf24j40_t *dev)
{
int8_t tmp;
tmp = mrf24j40_reg_read_short(dev, MRF24J40_REG_CCAEDTH); /* Energy detection threshold */
return(dBm_value[tmp]); /* in dBm */
}
void mrf24j40_set_cca_threshold(mrf24j40_t *dev, int8_t value)
{
/* ensure the given value is negative, since a CCA threshold > 0 is
@ -350,11 +291,6 @@ void mrf24j40_set_turbo(mrf24j40_t *dev, bool on)
mrf24j40_baseband_reset(dev);
}
bool mrf24j40_get_turbo(mrf24j40_t *dev)
{
return mrf24j40_reg_read_short(dev, MRF24J40_REG_BBREG0);
}
void mrf24j40_set_option(mrf24j40_t *dev, uint16_t option, bool state)
{
uint8_t tmp;
@ -363,7 +299,6 @@ void mrf24j40_set_option(mrf24j40_t *dev, uint16_t option, bool state)
/* set option field */
if (state) {
dev->netdev.flags |= option;
/* trigger option specific actions */
switch (option) {
case MRF24J40_OPT_CSMA:
@ -396,7 +331,6 @@ void mrf24j40_set_option(mrf24j40_t *dev, uint16_t option, bool state)
}
/* clear option field */
else {
dev->netdev.flags &= ~(option);
/* trigger option specific actions */
switch (option) {
case MRF24J40_OPT_CSMA:
@ -415,10 +349,8 @@ void mrf24j40_set_option(mrf24j40_t *dev, uint16_t option, bool state)
tmp &= ~MRF24J40_RXMCR_PROMI;
tmp &= ~MRF24J40_RXMCR_ERRPKT;
/* re-enable AUTOACK only if the option is set */
if (dev->netdev.flags & NETDEV_IEEE802154_ACK_REQ) {
tmp &= ~(MRF24J40_RXMCR_NOACKRSP);
mrf24j40_reg_write_short(dev, MRF24J40_REG_RXMCR, tmp);
}
tmp &= ~(MRF24J40_RXMCR_NOACKRSP);
mrf24j40_reg_write_short(dev, MRF24J40_REG_RXMCR, tmp);
break;
case NETDEV_IEEE802154_ACK_REQ:
DEBUG("[mrf24j40] opt: disabling auto ACKs\n");
@ -433,28 +365,6 @@ void mrf24j40_set_option(mrf24j40_t *dev, uint16_t option, bool state)
}
}
void mrf24j40_set_state(mrf24j40_t *dev, uint8_t state)
{
uint8_t old_state;
old_state = dev->state;
if (state == old_state) {
return;
}
/* check if asked to wake up from sleep mode */
if (old_state == MRF24J40_PSEUDO_STATE_SLEEP) {
mrf24j40_assert_awake(dev);
}
if (state == MRF24J40_PSEUDO_STATE_SLEEP) {
mrf24j40_sleep(dev);
}
if (state == MRF24J40_PSEUDO_STATE_IDLE) {
dev->state = state;
}
dev->idle_state = state;
}
void mrf24j40_sleep(mrf24j40_t *dev)
{
DEBUG("[mrf24j40] Putting into sleep mode\n");
@ -466,44 +376,33 @@ void mrf24j40_sleep(mrf24j40_t *dev)
mrf24j40_reg_write_short(dev, MRF24J40_REG_SOFTRST, MRF24J40_SOFTRST_RSTPWR);
/* Go to SLEEP mode */
mrf24j40_reg_write_short(dev, MRF24J40_REG_SLPACK, MRF24J40_SLPACK_SLPACK);
dev->state = MRF24J40_PSEUDO_STATE_SLEEP;
}
void mrf24j40_assert_sleep(mrf24j40_t *dev)
void mrf24j40_wake_up(mrf24j40_t *dev)
{
if (dev->idle_state == MRF24J40_PSEUDO_STATE_SLEEP) {
mrf24j40_sleep(dev);
}
}
void mrf24j40_assert_awake(mrf24j40_t *dev)
{
if (dev->state == MRF24J40_PSEUDO_STATE_SLEEP) {
DEBUG("[mrf24j40] Waking up from sleep mode\n");
/* Wake mrf up */
mrf24j40_reg_write_short(dev, MRF24J40_REG_WAKECON, MRF24J40_WAKECON_IMMWAKE | MRF24J40_WAKECON_REGWAKE);
/* undocumented delay, needed for stable wakeup */
xtimer_usleep(MRF24J40_DELAY_SLEEP_TOGGLE);
mrf24j40_reg_write_short(dev, MRF24J40_REG_WAKECON, MRF24J40_WAKECON_IMMWAKE);
/* reset state machine */
mrf24j40_reg_write_short(dev, MRF24J40_REG_RFCTL, MRF24J40_RFCTL_RFRST);
mrf24j40_reg_write_short(dev, MRF24J40_REG_RFCTL, 0x00);
/* After wake-up, delay at least 2 ms to allow 20 MHz main
* oscillator time to stabilize before transmitting or receiving.
*/
xtimer_usleep(MRF24J40_WAKEUP_DELAY);
/* reset interrupts */
mrf24j40_reg_read_short(dev, MRF24J40_REG_INTSTAT);
mrf24j40_enable_auto_pa_lna(dev);
dev->state = MRF24J40_PSEUDO_STATE_IDLE;
}
DEBUG("[mrf24j40] Waking up from sleep mode\n");
/* Wake mrf up */
mrf24j40_reg_write_short(dev, MRF24J40_REG_WAKECON, MRF24J40_WAKECON_IMMWAKE | MRF24J40_WAKECON_REGWAKE);
/* undocumented delay, needed for stable wakeup */
ztimer_sleep(ZTIMER_USEC, MRF24J40_DELAY_SLEEP_TOGGLE);
mrf24j40_reg_write_short(dev, MRF24J40_REG_WAKECON, MRF24J40_WAKECON_IMMWAKE);
/* reset state machine */
mrf24j40_reg_write_short(dev, MRF24J40_REG_RFCTL, MRF24J40_RFCTL_RFRST);
mrf24j40_reg_write_short(dev, MRF24J40_REG_RFCTL, 0x00);
/* After wake-up, delay at least 2 ms to allow 20 MHz main
* oscillator time to stabilize before transmitting or receiving.
*/
ztimer_sleep(ZTIMER_USEC, MRF24J40_WAKEUP_DELAY);
/* reset interrupts */
mrf24j40_reg_read_short(dev, MRF24J40_REG_INTSTAT);
mrf24j40_enable_auto_pa_lna(dev);
}
void mrf24j40_reset_state_machine(mrf24j40_t *dev)
{
mrf24j40_reg_write_short(dev, MRF24J40_REG_RFCTL, MRF24J40_RFCTL_RFRST);
mrf24j40_reg_write_short(dev, MRF24J40_REG_RFCTL, 0x00);
xtimer_usleep(MRF24J40_STATE_RESET_DELAY); /* Delay at least 192us */
ztimer_sleep(ZTIMER_USEC, MRF24J40_STATE_RESET_DELAY); /* Delay at least 192us */
}
void mrf24j40_software_reset(mrf24j40_t *dev)

View File

@ -21,7 +21,7 @@
*/
#include "periph/spi.h"
#include "periph/gpio.h"
#include "xtimer.h"
#include "ztimer.h"
#include "mrf24j40_internal.h"
#include "mrf24j40_registers.h"
#include "kernel_defines.h"
@ -29,12 +29,12 @@
#define ENABLE_DEBUG 0
#include "debug.h"
#define SPIDEV (dev->params.spi)
#define CSPIN (dev->params.cs_pin)
#define SPIDEV (dev->params->spi)
#define CSPIN (dev->params->cs_pin)
static inline void getbus(mrf24j40_t *dev)
{
spi_acquire(SPIDEV, CSPIN, SPI_MODE_0, dev->params.spi_clk);
spi_acquire(SPIDEV, CSPIN, SPI_MODE_0, dev->params->spi_clk);
}
#if IS_ACTIVE(CONFIG_MRF24J40_USE_EXT_PA_LNA)
@ -99,7 +99,7 @@ void mrf24j40_enable_lna(mrf24j40_t *dev)
}
#endif /* CONFIG_MRF24J40_USE_EXT_PA_LNA */
int mrf24j40_init(mrf24j40_t *dev)
int mrf24j40_init_hw(mrf24j40_t *dev)
{
if (IS_ACTIVE(CONFIG_MRF24J40_TEST_SPI_CONNECTION)) {
/* Check if MRF24J40 is available */
@ -263,36 +263,34 @@ void mrf24j40_reset_tasks(mrf24j40_t *dev)
void mrf24j40_update_tasks(mrf24j40_t *dev)
{
if (dev->irq_flag) {
uint8_t newpending = 0;
uint8_t instat = 0;
uint8_t newpending = 0;
uint8_t instat = 0;
dev->irq_flag = 0;
instat = mrf24j40_reg_read_short(dev, MRF24J40_REG_INTSTAT);
/* check if TX done */
if (instat & MRF24J40_INTSTAT_TXNIF) {
newpending |= MRF24J40_TASK_TX_DONE | MRF24J40_TASK_TX_READY;
/* transmit done, returning to configured idle state */
mrf24j40_assert_sleep(dev);
}
if (instat & MRF24J40_INTSTAT_RXIF) {
newpending |= MRF24J40_TASK_RX_READY;
}
/* check if RX pending */
dev->pending |= newpending;
instat = mrf24j40_reg_read_short(dev, MRF24J40_REG_INTSTAT);
/* check if TX done */
if (instat & MRF24J40_INTSTAT_TXNIF) {
newpending |= MRF24J40_TASK_TX_DONE | MRF24J40_TASK_TX_READY;
/* transmit done, returning to configured idle state */
}
if (instat & MRF24J40_INTSTAT_RXIF) {
newpending |= MRF24J40_TASK_RX_READY;
}
/* check if RX pending */
dev->pending |= newpending;
}
void mrf24j40_hardware_reset(mrf24j40_t *dev)
{
/* wake up from sleep in case radio is sleeping */
mrf24j40_assert_awake(dev);
/* trigger hardware reset */
gpio_clear(dev->params.reset_pin);
gpio_clear(dev->params->reset_pin);
/* Datasheet - Not specified */
xtimer_usleep(MRF24J40_RESET_PULSE_WIDTH);
gpio_set(dev->params.reset_pin);
ztimer_sleep(ZTIMER_USEC, MRF24J40_RESET_PULSE_WIDTH);
gpio_set(dev->params->reset_pin);
/* Datasheet - MRF24J40 ~2ms */
xtimer_usleep(MRF24J40_RESET_DELAY);
ztimer_sleep(ZTIMER_USEC, MRF24J40_RESET_DELAY);
}
void mrf24j40_flush_rx(mrf24j40_t *dev)
{
mrf24j40_reg_write_short(dev, MRF24J40_REG_RXFLUSH, MRF24J40_RXFLUSH_RXFLUSH);
}

View File

@ -1,581 +0,0 @@
/*
* Copyright (C) 2017 Neo Nenaco <neo@nenaco.de>
* Copyright (C) 2017 Koen Zandberg <koen@bergzand.net>
*
* 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_mrf24j40
* @{
*
* @file
* @brief Netdev adaption for the MRF24J40 drivers
*
* @author Koen Zandberg <koen@bergzand.net>
* @author Neo Nenaco <neo@nenaco.de>
*
* @}
*/
#include <string.h>
#include <assert.h>
#include <errno.h>
#include "net/eui64.h"
#include "net/ieee802154.h"
#include "net/netdev.h"
#include "net/netdev/ieee802154.h"
#include "mrf24j40.h"
#include "mrf24j40_netdev.h"
#include "mrf24j40_internal.h"
#include "mrf24j40_registers.h"
#define ENABLE_DEBUG 0
#include "debug.h"
static void _irq_handler(void *arg)
{
netdev_t *dev = arg;
netdev_ieee802154_t *netdev_ieee802154 = container_of(dev, netdev_ieee802154_t, netdev);
mrf24j40_t *mrf24j40 = container_of(netdev_ieee802154, mrf24j40_t, netdev);
netdev_trigger_event_isr(dev);
mrf24j40->irq_flag = 1;
}
static int _init(netdev_t *netdev)
{
netdev_ieee802154_t *netdev_ieee802154 = container_of(netdev, netdev_ieee802154_t, netdev);
mrf24j40_t *dev = container_of(netdev_ieee802154, mrf24j40_t, netdev);
/* initialize GPIOs */
spi_init_cs(dev->params.spi, dev->params.cs_pin);
gpio_init(dev->params.reset_pin, GPIO_OUT);
gpio_set(dev->params.reset_pin);
gpio_init_int(dev->params.int_pin, GPIO_IN, GPIO_RISING, _irq_handler, dev);
/* reset device to default values and put it into RX state */
if (mrf24j40_reset(dev)) {
return -ENODEV;
}
/* signal link UP */
netdev->event_callback(netdev, NETDEV_EVENT_LINK_UP);
return 0;
}
static int _send(netdev_t *netdev, const iolist_t *iolist)
{
netdev_ieee802154_t *netdev_ieee802154 = container_of(netdev, netdev_ieee802154_t, netdev);
mrf24j40_t *dev = container_of(netdev_ieee802154, mrf24j40_t, netdev);
size_t len = 0;
mrf24j40_tx_prepare(dev);
/* load packet data into FIFO */
for (const iolist_t *iol = iolist; iol; iol = iol->iol_next) {
/* Check if there is data to copy, prevents assertion failure in the
* SPI peripheral if there is no data to copy */
if (iol->iol_len) {
/* current packet data + FCS too long */
if ((len + iol->iol_len + 2) > IEEE802154_FRAME_LEN_MAX) {
DEBUG("[mrf24j40] error: packet too large (%u byte) to be send\n",
(unsigned)len + 2);
return -EOVERFLOW;
}
len = mrf24j40_tx_load(dev, iol->iol_base, iol->iol_len, len);
}
/* only on first iteration: */
if (iol == iolist) {
dev->header_len = len;
/* Grab the FCF bits from the frame header */
dev->fcf_low = *(uint8_t*)(iol->iol_base);
}
}
/* send data out directly if pre-loading is disabled */
if (!(dev->netdev.flags & MRF24J40_OPT_PRELOADING)) {
mrf24j40_tx_exec(dev);
}
/* return the number of bytes that were actually send out */
return (int)len;
}
static int _recv(netdev_t *netdev, void *buf, size_t len, void *info)
{
netdev_ieee802154_t *netdev_ieee802154 = container_of(netdev, netdev_ieee802154_t, netdev);
mrf24j40_t *dev = container_of(netdev_ieee802154, mrf24j40_t, netdev);
uint8_t phr;
size_t pkt_len;
int res = -ENOBUFS;
/* Disable receiving while reading the RX fifo (datasheet sec. 3.11.4) */
mrf24j40_reg_write_short(dev, MRF24J40_REG_BBREG1, MRF24J40_BBREG1_RXDECINV );
/* get the size of the received packet, this resets the receive FIFO to be
* ready for a new frame, so we have to disable RX first (see above) */
phr = mrf24j40_reg_read_long(dev, MRF24J40_RX_FIFO);
pkt_len = (phr & 0x7f) - 2;
/* just return length when buf == NULL */
if (buf == NULL && len == 0) {
return pkt_len;
}
/* Only fill buffer if it is supplied and is large enough */
if (buf && pkt_len <= len) {
/* copy payload */
mrf24j40_rx_fifo_read(dev, 1, (uint8_t *)buf, pkt_len);
if (info != NULL) {
netdev_ieee802154_rx_info_t *radio_info = info;
uint8_t rssi_scalar = 0;
/* Read LQI and RSSI values from the RX fifo */
mrf24j40_rx_fifo_read(dev, phr + 1, &(radio_info->lqi), 1);
mrf24j40_rx_fifo_read(dev, phr + 2, &(rssi_scalar), 1);
radio_info->rssi = mrf24j40_dbm_from_reg(rssi_scalar);
}
res = pkt_len;
}
/* Turn on reception of packets off the air */
mrf24j40_reg_write_short(dev, MRF24J40_REG_BBREG1, 0x00);
/* Return -ENOBUFS if a too small buffer is supplied. Return packet size
* otherwise */
return res;
}
static netopt_state_t _get_state(mrf24j40_t *dev)
{
if (!(dev->pending & MRF24J40_TASK_TX_DONE)) {
return NETOPT_STATE_TX;
}
if (dev->pending & MRF24J40_TASK_RX_READY) {
return NETOPT_STATE_RX;
}
switch (dev->state) {
case MRF24J40_PSEUDO_STATE_SLEEP:
return NETOPT_STATE_SLEEP;
}
return NETOPT_STATE_IDLE;
}
static int _get(netdev_t *netdev, netopt_t opt, void *val, size_t max_len)
{
netdev_ieee802154_t *netdev_ieee802154 = container_of(netdev, netdev_ieee802154_t, netdev);
mrf24j40_t *dev = container_of(netdev_ieee802154, mrf24j40_t, netdev);
if (netdev == NULL) {
return -ENODEV;
}
int res;
switch (opt) {
case NETOPT_ADDRESS:
if (max_len < sizeof(uint16_t)) {
res = -EOVERFLOW;
}
else {
*(uint16_t*)val = mrf24j40_get_addr_short(dev);
res = sizeof(uint16_t);
}
break;
case NETOPT_ADDRESS_LONG:
if (max_len < sizeof(uint64_t)) {
res = -EOVERFLOW;
}
else {
mrf24j40_get_addr_long(dev, val);
res = sizeof(uint64_t);
}
break;
case NETOPT_CHANNEL_PAGE:
if (max_len < sizeof(uint16_t)) {
res = -EOVERFLOW;
}
else {
((uint8_t *)val)[1] = 0;
((uint8_t *)val)[0] = 0;
res = sizeof(uint16_t);
}
break;
case NETOPT_STATE:
if (max_len < sizeof(netopt_state_t)) {
res = -EOVERFLOW;
}
else {
*((netopt_state_t *)val) = _get_state(dev);
res = sizeof(netopt_state_t);
}
break;
case NETOPT_PRELOADING:
if (dev->netdev.flags & MRF24J40_OPT_PRELOADING) {
*((netopt_enable_t *)val) = NETOPT_ENABLE;
}
else {
*((netopt_enable_t *)val) = NETOPT_DISABLE;
}
res = sizeof(netopt_enable_t);
break;
case NETOPT_PROMISCUOUSMODE:
if (dev->netdev.flags & MRF24J40_OPT_PROMISCUOUS) {
*((netopt_enable_t *)val) = NETOPT_ENABLE;
}
else {
*((netopt_enable_t *)val) = NETOPT_DISABLE;
}
res = sizeof(netopt_enable_t);
break;
case NETOPT_RX_START_IRQ:
case NETOPT_TX_START_IRQ:
case NETOPT_TX_END_IRQ:
*((netopt_enable_t *)val) = NETOPT_ENABLE;
res = sizeof(netopt_enable_t);
break;
case NETOPT_CSMA:
*((netopt_enable_t *)val) =
!!(dev->netdev.flags & MRF24J40_OPT_CSMA);
res = sizeof(netopt_enable_t);
break;
case NETOPT_TX_POWER:
if (max_len < sizeof(int16_t)) {
res = -EOVERFLOW;
}
else {
*((uint16_t *)val) = mrf24j40_get_txpower(dev);
res = sizeof(uint16_t);
}
break;
case NETOPT_RETRANS:
if (max_len < sizeof(uint8_t)) {
res = -EOVERFLOW;
}
else {
*((uint8_t *)val) = MRF24J40_MAX_FRAME_RETRIES;
res = sizeof(uint8_t);
}
break;
case NETOPT_IS_CHANNEL_CLR:
if (mrf24j40_cca(dev, NULL)) {
*((netopt_enable_t *)val) = NETOPT_ENABLE;
}
else {
*((netopt_enable_t *)val) = NETOPT_DISABLE;
}
res = sizeof(netopt_enable_t);
break;
case NETOPT_LAST_ED_LEVEL:
if (max_len < sizeof(int8_t)) {
res = -EOVERFLOW;
}
else {
mrf24j40_cca(dev, (int8_t *)val);
res = sizeof(int8_t);
}
break;
case NETOPT_CSMA_RETRIES:
if (max_len < sizeof(uint8_t)) {
res = -EOVERFLOW;
}
else {
*((uint8_t *)val) = mrf24j40_get_csma_max_retries(dev);
res = sizeof(uint8_t);
}
break;
case NETOPT_CCA_THRESHOLD:
if (max_len < sizeof(int8_t)) {
res = -EOVERFLOW;
}
else {
*((int8_t *)val) = mrf24j40_get_cca_threshold(dev);
res = sizeof(int8_t);
}
break;
case NETOPT_TX_RETRIES_NEEDED:
if (max_len < sizeof(uint8_t)) {
res = -EOVERFLOW;
}
else {
*((uint8_t *)val) = dev->tx_retries;
res = sizeof(int8_t);
}
break;
#ifdef MODULE_NETDEV_IEEE802154_OQPSK
case NETOPT_IEEE802154_PHY:
assert(max_len >= sizeof(int8_t));
*(uint8_t *)val = IEEE802154_PHY_OQPSK;
return sizeof(uint8_t);
case NETOPT_OQPSK_RATE:
assert(max_len >= sizeof(int8_t));
*(uint8_t *)val = mrf24j40_get_turbo(dev);
return sizeof(uint8_t);
#endif /* MODULE_NETDEV_IEEE802154_OQPSK */
default:
/* try netdev settings */
res = netdev_ieee802154_get(container_of(netdev, netdev_ieee802154_t, netdev),
opt, val, max_len);
}
return res;
}
static int _set_state(mrf24j40_t *dev, netopt_state_t state)
{
switch (state) {
case NETOPT_STATE_SLEEP:
mrf24j40_set_state(dev, MRF24J40_PSEUDO_STATE_SLEEP);
break;
case NETOPT_STATE_IDLE:
mrf24j40_set_state(dev, MRF24J40_PSEUDO_STATE_IDLE);
break;
case NETOPT_STATE_TX:
if (dev->netdev.flags & MRF24J40_OPT_PRELOADING) {
mrf24j40_tx_exec(dev);
}
break;
case NETOPT_STATE_RESET:
mrf24j40_reset(dev);
break;
default:
return -ENOTSUP;
}
return sizeof(netopt_state_t);
}
static int _set(netdev_t *netdev, netopt_t opt, const void *val, size_t len)
{
netdev_ieee802154_t *netdev_ieee802154 = container_of(netdev, netdev_ieee802154_t, netdev);
mrf24j40_t *dev = container_of(netdev_ieee802154, mrf24j40_t, netdev);
int res = -ENOTSUP;
if (dev == NULL) {
return -ENODEV;
}
switch (opt) {
case NETOPT_ADDRESS:
if (len > sizeof(uint16_t)) {
res = -EOVERFLOW;
}
else {
mrf24j40_set_addr_short(dev, *((const uint16_t *)val));
res = sizeof(uint16_t);
}
break;
case NETOPT_ADDRESS_LONG:
if (len > sizeof(uint64_t)) {
res = -EOVERFLOW;
}
else {
mrf24j40_set_addr_long(dev, val);
res = sizeof(uint64_t);
}
break;
case NETOPT_NID:
if (len > sizeof(uint16_t)) {
res = -EOVERFLOW;
}
else {
mrf24j40_set_pan(dev, *((const uint16_t *)val));
/* don't set res to set netdev_ieee802154_t::pan */
}
break;
case NETOPT_CHANNEL:
if (len != sizeof(uint16_t)) {
res = -EINVAL;
}
else {
uint8_t chan = ((const uint8_t *)val)[0];
if (chan < IEEE802154_CHANNEL_MIN ||
chan > IEEE802154_CHANNEL_MAX ||
dev->netdev.chan == chan) {
res = -EINVAL;
break;
}
mrf24j40_set_chan(dev, chan);
/* don't set res to set netdev_ieee802154_t::chan */
}
break;
case NETOPT_CHANNEL_PAGE:
if (len != sizeof(uint16_t)) {
res = -EINVAL;
}
else {
uint8_t page = ((const uint8_t *)val)[0];
/* mrf24j40 only supports page 0, no need to configure anything in the driver. */
if (page != 0) {
res = -EINVAL;
}
else {
res = sizeof(uint16_t);
}
}
break;
case NETOPT_TX_POWER:
if (len > sizeof(int16_t)) {
res = -EOVERFLOW;
}
else {
mrf24j40_set_txpower(dev, *((const int16_t *)val));
res = sizeof(uint16_t);
}
break;
case NETOPT_STATE:
if (len > sizeof(netopt_state_t)) {
res = -EOVERFLOW;
}
else {
res = _set_state(dev, *((const netopt_state_t *)val));
}
break;
case NETOPT_AUTOACK:
mrf24j40_set_option(dev, NETDEV_IEEE802154_ACK_REQ,
((const bool *)val)[0]);
/* don't set res to set netdev_ieee802154_t::flags */
break;
case NETOPT_PRELOADING:
mrf24j40_set_option(dev, MRF24J40_OPT_PRELOADING,
((const bool *)val)[0]);
res = sizeof(netopt_enable_t);
break;
case NETOPT_PROMISCUOUSMODE:
mrf24j40_set_option(dev, MRF24J40_OPT_PROMISCUOUS,
((const bool *)val)[0]);
res = sizeof(netopt_enable_t);
break;
case NETOPT_CSMA:
mrf24j40_set_option(dev, MRF24J40_OPT_CSMA,
((const bool *)val)[0]);
res = sizeof(netopt_enable_t);
break;
case NETOPT_CSMA_RETRIES:
if ((len > sizeof(uint8_t)) ||
(*((const uint8_t *)val) > 5)) {
res = -EOVERFLOW;
}
else if (dev->netdev.flags & MRF24J40_OPT_CSMA) {
/* only set if CSMA is enabled */
mrf24j40_set_csma_max_retries(dev, *((const uint8_t *)val));
res = sizeof(uint8_t);
}
break;
case NETOPT_CCA_THRESHOLD:
if (len > sizeof(int8_t)) {
res = -EOVERFLOW;
}
else {
mrf24j40_set_cca_threshold(dev, *((const int8_t *)val));
res = sizeof(int8_t);
}
break;
#ifdef MODULE_NETDEV_IEEE802154_OQPSK
case NETOPT_OQPSK_RATE:
res = !!*(uint8_t *)val;
mrf24j40_set_turbo(dev, res);
res = sizeof(uint8_t);
break;
#endif /* MODULE_NETDEV_IEEE802154_OQPSK */
default:
break;
}
/* try netdev building flags */
if (res == -ENOTSUP) {
res = netdev_ieee802154_set(container_of(netdev, netdev_ieee802154_t, netdev),
opt, val, len);
}
return res;
}
static void _isr(netdev_t *netdev)
{
netdev_ieee802154_t *netdev_ieee802154 = container_of(netdev, netdev_ieee802154_t, netdev);
mrf24j40_t *dev = container_of(netdev_ieee802154, mrf24j40_t, netdev);
/* update pending bits */
mrf24j40_update_tasks(dev);
DEBUG("[mrf24j40] INTERRUPT (pending: %x),\n", dev->pending);
/* Transmit interrupt occurred */
if (dev->pending & MRF24J40_TASK_TX_READY) {
dev->pending &= ~(MRF24J40_TASK_TX_READY);
DEBUG("[mrf24j40] EVT - TX_END\n");
#ifdef MODULE_NETSTATS_L2
if (netdev->event_callback) {
uint8_t txstat = mrf24j40_reg_read_short(dev, MRF24J40_REG_TXSTAT);
dev->tx_retries = (txstat >> MRF24J40_TXSTAT_MAX_FRAME_RETRIES_SHIFT);
/* transmission failed */
if (txstat & MRF24J40_TXSTAT_TXNSTAT) {
/* TX_NOACK - CCAFAIL */
if (txstat & MRF24J40_TXSTAT_CCAFAIL) {
netdev->event_callback(netdev, NETDEV_EVENT_TX_MEDIUM_BUSY);
DEBUG("[mrf24j40] TX_CHANNEL_ACCESS_FAILURE\n");
}
/* check max retries */
else if (txstat & MRF24J40_TXSTAT_MAX_FRAME_RETRIES) {
netdev->event_callback(netdev, NETDEV_EVENT_TX_NOACK);
DEBUG("[mrf24j40] TX NO_ACK\n");
}
}
else {
netdev->event_callback(netdev, NETDEV_EVENT_TX_COMPLETE);
}
}
#endif
}
/* Receive interrupt occurred */
if (dev->pending & MRF24J40_TASK_RX_READY) {
DEBUG("[mrf24j40] EVT - RX_END\n");
netdev->event_callback(netdev, NETDEV_EVENT_RX_COMPLETE);
dev->pending &= ~(MRF24J40_TASK_RX_READY);
}
DEBUG("[mrf24j40] END IRQ\n");
}
const netdev_driver_t mrf24j40_driver = {
.send = _send,
.recv = _recv,
.init = _init,
.isr = _isr,
.get = _get,
.set = _set,
};

View File

@ -0,0 +1,374 @@
#include "mrf24j40.h"
#include "mrf24j40_params.h"
#include "mrf24j40_internal.h"
#include "mrf24j40_registers.h"
#include "net/ieee802154/radio.h"
#define ENABLE_DEBUG 0
#include "debug.h"
static const ieee802154_radio_ops_t mrf24j40_ops;
void mrf24j40_radio_irq_handler(void *ctx)
{
ieee802154_dev_t *hal = ctx;
mrf24j40_t *dev = hal->priv;
/* update pending bits */
mrf24j40_update_tasks(dev);
DEBUG("[mrf24j40] INTERRUPT (pending: %x),\n", dev->pending);
/* Transmit interrupt occurred */
if (dev->pending & MRF24J40_TASK_TX_READY) {
hal->cb(hal, IEEE802154_RADIO_CONFIRM_TX_DONE);
}
/* Receive interrupt occurred */
if (dev->pending & MRF24J40_TASK_RX_READY) {
DEBUG("[mrf24j40] EVT - RX_END\n");
dev->pending &= ~(MRF24J40_TASK_RX_READY);
/* Prevent race condition if there is an ongoing transmission */
if (dev->tx_pending) {
mrf24j40_flush_rx(dev);
}
else {
hal->cb(hal, IEEE802154_RADIO_INDICATION_RX_DONE);
}
}
DEBUG("[mrf24j40] END IRQ\n");
}
static int _write(ieee802154_dev_t *hal, const iolist_t *iolist)
{
uint8_t len = 0;
mrf24j40_t *dev = hal->priv;
/* load packet data into FIFO */
for (const iolist_t *iol = iolist; iol; iol = iol->iol_next) {
/* Check if there is data to copy, prevents assertion failure in the
* SPI peripheral if there is no data to copy */
if (iol->iol_len) {
/* current packet data + FCS too long */
len = mrf24j40_tx_load(dev, iol->iol_base, iol->iol_len, len);
}
/* only on first iteration: */
if (iol == iolist) {
/* Grab the FCF bits from the frame header */
dev->fcf_low = *(uint8_t*)(iol->iol_base);
}
}
/* write frame length field in FIFO */
mrf24j40_tx_normal_fifo_write(dev, MRF24J40_TX_NORMAL_FIFO + 1, &len, 1);
return 0;
}
int mrf24j40_init(mrf24j40_t *dev, const mrf24j40_params_t *params, ieee802154_dev_t *hal,
gpio_cb_t cb, void *ctx)
{
hal->driver = &mrf24j40_ops;
hal->priv = dev;
dev->params = params;
/* initialize GPIOs */
spi_init_cs(dev->params->spi, dev->params->cs_pin);
gpio_init(dev->params->reset_pin, GPIO_OUT);
gpio_set(dev->params->reset_pin);
gpio_init_int(dev->params->int_pin, GPIO_IN, GPIO_RISING, cb, ctx);
/* reset device to default values */
if (mrf24j40_reset(dev)) {
return -ENODEV;
}
/* Set device to SLEEP */
mrf24j40_sleep(dev);
return 0;
}
static int _read(ieee802154_dev_t *hal, void *buf, size_t size, ieee802154_rx_info_t *info)
{
uint8_t phr;
size_t pkt_len;
int res = -ENOBUFS;
mrf24j40_t *dev = hal->priv;
phr = mrf24j40_reg_read_long(dev, MRF24J40_RX_FIFO);
pkt_len = (phr & 0x7f) - IEEE802154_FCS_LEN;
if (buf) {
if (pkt_len > size) {
mrf24j40_flush_rx(dev);
return -ENOBUFS;
}
mrf24j40_rx_fifo_read(dev, 1, (uint8_t *)buf, pkt_len);
if (info != NULL) {
uint8_t rssi_scalar = 0;
/* Read LQI and RSSI values from the RX fifo */
mrf24j40_rx_fifo_read(dev, phr + 1, &(info->lqi), 1);
mrf24j40_rx_fifo_read(dev, phr + 2, &(rssi_scalar), 1);
info->rssi = mrf24j40_dbm_from_reg(rssi_scalar);
}
res = pkt_len;
}
else {
mrf24j40_flush_rx(dev);
}
/* Return -ENOBUFS if a too small buffer is supplied. Return packet size
* otherwise */
return res;
}
static int _len(ieee802154_dev_t *hal)
{
mrf24j40_t *dev = hal->priv;
return (mrf24j40_reg_read_long(dev, MRF24J40_RX_FIFO) & 0x7f) - IEEE802154_FCS_LEN;
}
static int _off(ieee802154_dev_t *hal)
{
mrf24j40_t *dev = hal->priv;
mrf24j40_sleep(dev);
return -ENOTSUP;
}
static int _request_on(ieee802154_dev_t *hal)
{
mrf24j40_t *dev = hal->priv;
mrf24j40_wake_up(dev);
return 0;
}
static int _confirm_on(ieee802154_dev_t *hal)
{
(void) hal;
/* Nothing to do here */
return 0;
}
static int _request_op(ieee802154_dev_t *hal, ieee802154_hal_op_t op, void *ctx)
{
int res = -EBUSY;
mrf24j40_t *dev = hal->priv;
(void) ctx;
switch (op) {
case IEEE802154_HAL_OP_TRANSMIT:
if (dev->fcf_low & IEEE802154_FCF_ACK_REQ) {
mrf24j40_reg_write_short(dev, MRF24J40_REG_TXNCON, MRF24J40_TXNCON_TXNACKREQ | MRF24J40_TXNCON_TXNTRIG);
mrf24j40_reg_write_short(dev, MRF24J40_REG_BBREG1, 0x00);
}
else {
mrf24j40_reg_write_short(dev, MRF24J40_REG_TXNCON, MRF24J40_TXNCON_TXNTRIG);
}
dev->tx_pending = true;
res = 0;
break;
case IEEE802154_HAL_OP_SET_RX:
mrf24j40_reg_write_short(dev, MRF24J40_REG_BBREG1, 0x00);
res = 0;
mrf24j40_reg_write_short(dev, MRF24J40_REG_INTCON, ~(MRF24J40_INTCON_RXIE));
break;
case IEEE802154_HAL_OP_SET_IDLE:
mrf24j40_reg_write_short(dev, MRF24J40_REG_BBREG1, MRF24J40_BBREG1_RXDECINV );
mrf24j40_reg_write_short(dev, MRF24J40_REG_INTCON, ~(MRF24J40_INTCON_TXNIE));
res = 0;
break;
case IEEE802154_HAL_OP_CCA:
mrf24j40_enable_lna(dev);
mrf24j40_reg_write_short(dev, MRF24J40_REG_BBREG6, MRF24J40_BBREG6_RSSIMODE1);
mrf24j40_reg_write_short(dev, MRF24J40_REG_INTCON, 0xFF);
res = 0;
break;
}
return res;
}
static int _confirm_op(ieee802154_dev_t *hal, ieee802154_hal_op_t op, void *ctx)
{
int res = -EAGAIN;
mrf24j40_t *dev = hal->priv;
uint8_t tmp_ccaedth;
uint8_t tmp_rssi;
switch (op) {
case IEEE802154_HAL_OP_TRANSMIT:
if (dev->pending & MRF24J40_TASK_TX_READY) {
dev->pending &= ~(MRF24J40_TASK_TX_READY);
if (ctx) {
uint8_t txstat = mrf24j40_reg_read_short(dev, MRF24J40_REG_TXSTAT);
ieee802154_tx_info_t *info = ctx;
if (txstat & MRF24J40_TXSTAT_TXNSTAT) {
info->status = (txstat & MRF24J40_TXSTAT_CCAFAIL)
? TX_STATUS_MEDIUM_BUSY
: TX_STATUS_NO_ACK;
}
else {
info->status = TX_STATUS_SUCCESS;
}
info->retrans = txstat >> MRF24J40_TXSTAT_MAX_FRAME_RETRIES_SHIFT;
}
mrf24j40_reg_write_short(dev, MRF24J40_REG_BBREG1, MRF24J40_BBREG1_RXDECINV);
dev->tx_pending = false;
return 0;
}
break;
case IEEE802154_HAL_OP_SET_RX:
case IEEE802154_HAL_OP_SET_IDLE:
res = 0;
break;
case IEEE802154_HAL_OP_CCA:
if ((mrf24j40_reg_read_short(dev, MRF24J40_REG_BBREG6) & MRF24J40_BBREG2_RSSIRDY)) {
tmp_ccaedth = mrf24j40_reg_read_short(dev, MRF24J40_REG_CCAEDTH); /* Energy detection threshold */
tmp_rssi = mrf24j40_reg_read_long(dev, MRF24J40_REG_RSSI);
mrf24j40_enable_auto_pa_lna(dev);
*((bool*) ctx) = (tmp_rssi < tmp_ccaedth) ? true : false;
res = 0;
}
break;
}
return res;
}
static int _set_cca_threshold(ieee802154_dev_t *hal, int8_t threshold)
{
mrf24j40_t *dev = hal->priv;
mrf24j40_set_cca_threshold(dev, threshold);
return 0;
}
static int _set_cca_mode(ieee802154_dev_t *dev, ieee802154_cca_mode_t mode)
{
(void) dev;
(void) mode;
if (mode != IEEE802154_CCA_MODE_ED_THRESHOLD) {
return -ENOTSUP;
}
return 0;
}
static int _config_phy(ieee802154_dev_t *hal, const ieee802154_phy_conf_t *conf)
{
mrf24j40_t *dev = hal->priv;
int8_t pow = conf->pow;
uint8_t channel = conf->channel;
if (pow < MRF24J40_MIN_TXPOWER && pow > MRF24J40_MAX_TXPOWER) {
return -EINVAL;
}
mrf24j40_set_txpower(dev, pow);
mrf24j40_set_chan(dev, channel);
return 0;
}
static int _set_csma_params(ieee802154_dev_t *hal, const ieee802154_csma_be_t *bd, int8_t retries)
{
mrf24j40_t *dev = hal->priv;
uint8_t tmp;
if (bd->min > MRF24J40_MAX_MINBE) {
return -EINVAL;
}
tmp = mrf24j40_reg_read_short(dev, MRF24J40_REG_TXMCR) & ~MRF24J40_TXMCR_MACMINBE;
if (retries >= 0) {
tmp |= bd->min << MRF24J40_TXMCR_MACMINBE_SHIFT;
}
/* This radio ignores max_be */
mrf24j40_set_csma_max_retries(dev, retries);
return 0;
}
static int _config_addr_filter(ieee802154_dev_t *hal, ieee802154_af_cmd_t cmd, const void *value)
{
mrf24j40_t *dev = hal->priv;
switch (cmd) {
case IEEE802154_AF_SHORT_ADDR:
mrf24j40_set_addr_short(dev, *((const uint16_t *)value));
break;
case IEEE802154_AF_EXT_ADDR:
mrf24j40_set_addr_long(dev, value);
break;
case IEEE802154_AF_PANID:
mrf24j40_set_pan(dev, *((const uint16_t *)value));
break;
case IEEE802154_AF_PAN_COORD:
return -ENOTSUP;
}
return 0;
}
static int _config_src_addr_match(ieee802154_dev_t *hal, ieee802154_src_match_t cmd, const void *value)
{
mrf24j40_t *dev = hal->priv;
uint8_t tmp = mrf24j40_reg_read_short(dev, MRF24J40_REG_ACKTMOUT) & ~MRF24J40_ACKTMOUT_DRPACK;
bool en;
switch (cmd) {
case IEEE802154_SRC_MATCH_EN:
en = *((bool*) value);
tmp = en ? tmp | MRF24J40_ACKTMOUT_DRPACK : tmp;
mrf24j40_reg_write_short(dev, MRF24J40_REG_ACKTMOUT, tmp);
return 0;
default:
return -ENOTSUP;
}
}
static int _set_frame_filter_mode(ieee802154_dev_t *hal, ieee802154_filter_mode_t mode)
{
mrf24j40_t *dev = hal->priv;
switch (mode) {
case IEEE802154_FILTER_ACCEPT:
mrf24j40_set_option(dev, MRF24J40_OPT_PROMISCUOUS, false);
break;
case IEEE802154_FILTER_PROMISC:
mrf24j40_set_option(dev, MRF24J40_OPT_PROMISCUOUS, true);
break;
case IEEE802154_FILTER_ACK_ONLY:
default:
return -ENOTSUP;
}
return 0;
}
int _set_frame_retrans(ieee802154_dev_t *hal, uint8_t retrans)
{
(void) hal;
(void) retrans;
/* This radio does not allow to set the number of retransmission, but this
* must still be defined because this radio declares
* IEEE802154_CAP_FRAME_RETRANS */
return -ENOTSUP;
}
static const ieee802154_radio_ops_t mrf24j40_ops = {
.caps = IEEE802154_CAP_24_GHZ
| IEEE802154_CAP_IRQ_TX_DONE
| IEEE802154_CAP_FRAME_RETRANS
| IEEE802154_CAP_FRAME_RETRANS_INFO
| IEEE802154_CAP_PHY_OQPSK
| IEEE802154_CAP_REG_RETENTION,
.write = _write,
.read = _read,
.request_on = _request_on,
.confirm_on = _confirm_on,
.len = _len,
.off = _off,
.request_op = _request_op,
.confirm_op = _confirm_op,
.set_cca_threshold = _set_cca_threshold,
.set_cca_mode = _set_cca_mode,
.config_phy = _config_phy,
.set_csma_params = _set_csma_params,
.config_addr_filter = _config_addr_filter,
.config_src_addr_match = _config_src_addr_match,
.set_frame_filter_mode = _set_frame_filter_mode,
.set_frame_retrans = _set_frame_retrans,
};

View File

@ -63,13 +63,12 @@ int flashpage_write_and_verify(unsigned page, const void *data)
void flashpage_write_page(unsigned page, const void *data)
{
assert((unsigned) page < FLASHPAGE_NUMOF);
assert(data != NULL);
flashpage_erase(page);
/* write page */
if (data != NULL) {
flashpage_write(flashpage_addr(page), data, FLASHPAGE_SIZE);
}
flashpage_write(flashpage_addr(page), data, FLASHPAGE_SIZE);
}
#endif

View File

@ -22,6 +22,8 @@
#include "mrf24j40_params.h"
#include "lwip_init_devs.h"
#include "bhp/msg.h"
#include "net/netdev/ieee802154_submac.h"
#define ENABLE_DEBUG 0
#include "debug.h"
@ -30,12 +32,20 @@
static lwip_netif_t netif[NETIF_MRF24J40_NUMOF];
static mrf24j40_t mrf24j40_devs[NETIF_MRF24J40_NUMOF];
static netdev_ieee802154_submac_t mrf24j40_netdev[NETIF_MRF24J40_NUMOF];
static void auto_init_mrf24j40(void)
{
for (unsigned i = 0; i < NETIF_MRF24J40_NUMOF; i++) {
mrf24j40_setup(&mrf24j40_devs[i], &mrf24j40_params[i], i);
if (lwip_add_6lowpan(&netif[i], &mrf24j40_devs[i].netdev.netdev) == NULL) {
bhp_msg_init(&netif[i].bhp, &mrf24j40_radio_irq_handler, &mrf24j40_netdev[i].submac.dev);
mrf24j40_init(&mrf24j40_devs[i], &mrf24j40_params[i], &mrf24j40_netdev[i].submac.dev,
bhp_msg_isr_cb, &netif[i].bhp);
netdev_register(&mrf24j40_netdev[i].dev.netdev, NETDEV_MRF24J40, i);
netdev_ieee802154_submac_init(&mrf24j40_netdev[i]);
if (lwip_add_6lowpan(&netif[i], &mrf24j40_netdev[i].dev.netdev) == NULL) {
DEBUG("Could not add mrf24j40 device\n");
return;
}

View File

@ -1267,9 +1267,9 @@ static inline int ieee802154_radio_cca(ieee802154_dev_t *dev)
if (res < 0) {
return res;
}
while (ieee802154_radio_confirm_cca(dev) == -EAGAIN) {}
while ((res = ieee802154_radio_confirm_cca(dev)) == -EAGAIN) {}
return 0;
return res;
}
/**

View File

@ -22,6 +22,8 @@
#include "net/gnrc/netif/ieee802154.h"
#include "net/gnrc.h"
#include "include/init_devs.h"
#include "net/netdev/ieee802154_submac.h"
#include "bhp/event.h"
#include "mrf24j40.h"
#include "mrf24j40_params.h"
@ -38,20 +40,31 @@
#define MRF24J40_NUM ARRAY_SIZE(mrf24j40_params)
static mrf24j40_t mrf24j40_devs[MRF24J40_NUM];
static netdev_ieee802154_submac_t mrf24j40_netdev[MRF24J40_NUM];
static char _mrf24j40_stacks[MRF24J40_NUM][MRF24J40_MAC_STACKSIZE];
static gnrc_netif_t _netif[MRF24J40_NUM];
static bhp_event_t mrf24j40_bhp[MRF24J40_NUM];
void auto_init_mrf24j40(void)
{
for (unsigned i = 0; i < MRF24J40_NUM; i++) {
const mrf24j40_params_t *p = &mrf24j40_params[i];
LOG_DEBUG("[auto_init_netif] initializing mrf24j40 #%u\n", i);
mrf24j40_setup(&mrf24j40_devs[i], &mrf24j40_params[i], i);
/* Init Bottom Half Processor (with events module) and radio */
bhp_event_init(&mrf24j40_bhp[i], &_netif[i].evq[GNRC_NETIF_EVQ_INDEX_PRIO_HIGH], &mrf24j40_radio_irq_handler, &mrf24j40_netdev[i].submac.dev);
mrf24j40_init(&mrf24j40_devs[i], (mrf24j40_params_t*) p,&mrf24j40_netdev[i].submac.dev,
bhp_event_isr_cb, &mrf24j40_bhp[i]);
netdev_register(&mrf24j40_netdev[i].dev.netdev, NETDEV_MRF24J40, i);
netdev_ieee802154_submac_init(&mrf24j40_netdev[i]);
gnrc_netif_ieee802154_create(&_netif[i], _mrf24j40_stacks[i],
MRF24J40_MAC_STACKSIZE, MRF24J40_MAC_PRIO,
"mrf24j40",
&mrf24j40_devs[i].netdev.netdev);
&mrf24j40_netdev[i].dev.netdev);
}
}
/** @} */

View File

@ -19,7 +19,7 @@ config MODULE_IEEE802154_SECURITY
config MODULE_IEEE802154_SUBMAC
bool "IEEE 802.15.4 submac"
select MODULE_XTIMER
select ZTIMER_USEC
help
This module defines a common layer for handling the lower part of the IEEE 802.15.4 MAC layer.

View File

@ -11,6 +11,7 @@ menu "Test utilities"
rsource "dummy_thread/Kconfig"
rsource "interactive_sync/Kconfig"
rsource "netdev_eth_minimal/Kconfig"
rsource "netdev_ieee802154_minimal/Kconfig"
rsource "print_stack_usage/Kconfig"
rsource "result_output/Kconfig"
endmenu # Test utilities

View File

@ -0,0 +1,17 @@
# Copyright (c) 2022 HAW Hamburg
#
# 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.
#
config MODULE_TEST_UTILS_NETDEV_IEEE802154_MINIMAL
bool "Minimal netdev IEEE 802.15.4 device processing"
depends on TEST_KCONFIG
select MODULE_NETDEV
select MODULE_EVENT
select MODULE_EVENT_THREAD
select MODULE_L2UTIL
select MODULE_OD
select MODULE_OD_STRING
select MODULE_SHELL

View File

@ -0,0 +1,11 @@
# Copyright (c) 2022 HAW Hamburg
#
# 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.
#
config APPLICATION
bool
default y
select HAVE_MRF24J40

View File

@ -2,6 +2,31 @@ INCLUDES += -I$(APPDIR)
include ../Makefile.tests_common
# Due to missing Kconfig support, whitelist boards that are known to have a
# working Kconfig dependency resolution.
# Other boards should still work when running with CONTINUE_ON_EXPECTED_ERRORS=1
BOARD_WHITELIST += adafruit-clue \
adafruit-itsybitsy-nrf52 \
arduino-nano-33-ble \
cc2538dk \
feather-nrf52840 \
native \
nrf52840dk \
nrf52840dongle \
nrf52840-mdk \
nucleo-l152re \
nucleo-f303re \
nucleo-wl55jc \
omote \
openmote-cc2538 \
reel \
remote-pa \
remote-reva \
remote-revb \
pba-d-01-kw2x \
#
USEMODULE += test_utils_netdev_ieee802154_minimal
# select the driver to test
@ -10,3 +35,7 @@ USEMODULE += mrf24j40ma
CFLAGS += -DEVENT_THREAD_STACKSIZE_DEFAULT=1024
include $(RIOTBASE)/Makefile.include
ifneq (,$(filter bhp,$(USEMODULE)))
USEMODULE += bhp_event
endif

View File

@ -0,0 +1,5 @@
CONFIG_MODULE_MRF24J40=y
CONFIG_MODULE_MRF24J40MA=y
CONFIG_MODULE_SHELL=y
CONFIG_MODULE_TEST_UTILS_NETDEV_IEEE802154_MINIMAL=y
CONFIG_MODULE_NETDEV_IEEE802154_SUBMAC=y

View File

@ -0,0 +1 @@
../ieee802154_hal/common.h

View File

@ -0,0 +1 @@
../ieee802154_hal/init_devs.c

View File

@ -25,22 +25,37 @@
#include "mrf24j40_params.h"
#include "shell.h"
#include "test_utils/netdev_ieee802154_minimal.h"
#include "net/netdev/ieee802154_submac.h"
#include "common.h"
static mrf24j40_t mrf24j40[MRF24J40_NUM];
static netdev_ieee802154_submac_t mrf24j40_netdev[MRF24J40_NUM];
static ieee802154_dev_t *_reg_callback(ieee802154_dev_type_t type, void *opaque)
{
if (type != IEEE802154_DEV_TYPE_MRF24J40) {
assert(false);
}
int *c = opaque;
return &mrf24j40_netdev[(*(c))++].submac.dev;
}
int netdev_ieee802154_minimal_init_devs(netdev_event_cb_t cb) {
puts("Initializing MRF24J40 devices");
int c = 0;
/* This function will iterate through all kw2xrf radios */
ieee802154_hal_test_init_devs(_reg_callback, &c);
for (unsigned i = 0; i < MRF24J40_NUM; i++) {
printf("%d out of %d\n", i + 1, MRF24J40_NUM);
/* setup the specific driver */
mrf24j40_setup(&mrf24j40[i], &mrf24j40_params[i], i);
netdev_register(&mrf24j40_netdev[i].dev.netdev, NETDEV_MRF24J40, 0);
netdev_ieee802154_submac_init(&mrf24j40_netdev[i]);
/* set the application-provided callback */
mrf24j40[i].netdev.netdev.event_callback = cb;
mrf24j40_netdev[i].dev.netdev.event_callback = cb;
/* initialize the device driver */
int res = mrf24j40[i].netdev.netdev.driver->init(&mrf24j40[i].netdev.netdev);
int res = mrf24j40_netdev[i].dev.netdev.driver->init(&mrf24j40_netdev[i].dev.netdev);
if (res != 0) {
return -1;
}

View File

@ -1,25 +1,29 @@
include ../Makefile.tests_common
BOARD_WHITELIST := \
adafruit-clue \
adafruit-itsybitsy-nrf52 \
arduino-nano-33-ble \
cc2538dk \
feather-nrf52840 \
native \
nrf52840dk \
nrf52840dongle \
nrf52840-mdk \
omote \
openmote-cc2538 \
reel \
remote-pa \
remote-reva \
remote-revb \
pba-d-01-kw2x \
#
# Due to missing Kconfig support, whitelist boards that are known to have a
# working Kconfig dependency resolution.
# Other boards should still work when running with CONTINUE_ON_EXPECTED_ERRORS=1
DISABLE_MODULE += auto_init_at86rf2xx auto_init_nrf802154
BOARD_WHITELIST += adafruit-clue \
adafruit-itsybitsy-nrf52 \
arduino-nano-33-ble \
cc2538dk \
feather-nrf52840 \
native \
nrf52840dk \
nrf52840dongle \
nrf52840-mdk \
nucleo-l152re \
nucleo-f303re \
nucleo-wl55jc \
omote \
openmote-cc2538 \
reel \
remote-pa \
remote-reva \
remote-revb \
pba-d-01-kw2x \
#
ifeq ($(BOARD), native)
ZEP_PORT_BASE ?= 17754

View File

@ -0,0 +1,11 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-leonardo \
arduino-nano \
arduino-uno \
atmega328p \
atmega328p-xplained-mini\
nucleo-f031k6 \
nucleo-l011k4 \
stm32f030f4-demo \
#

View File

@ -28,12 +28,9 @@
#define RADIOS_NUMOF IS_USED(MODULE_CC2538_RF) + \
IS_USED(MODULE_NRF802154) + \
SOCKET_ZEP_MAX + \
IS_USED(MODULE_MRF24J40) + \
IS_USED(MODULE_KW2XRF)
#if RADIOS_NUMOF == 0
#error "Radio is not supported"
#endif
#ifdef __cplusplus
extern "C" {
#endif
@ -48,6 +45,7 @@ typedef enum {
IEEE802154_DEV_TYPE_NRF802154,
IEEE802154_DEV_TYPE_SOCKET_ZEP,
IEEE802154_DEV_TYPE_KW2XRF,
IEEE802154_DEV_TYPE_MRF24J40,
} ieee802154_dev_type_t;
typedef ieee802154_dev_t* (*ieee802154_dev_cb_t)(ieee802154_dev_type_t type,

View File

@ -18,6 +18,7 @@
* @}
*/
#include <stdio.h>
#include "assert.h"
#include "kernel_defines.h"
#include "net/ieee802154/radio.h"
@ -37,23 +38,43 @@
#include "socket_zep_params.h"
#endif
#include "event/thread.h"
extern void auto_init_event_thread(void);
#ifdef MODULE_KW2XRF
#include "kw2xrf.h"
#include "kw2xrf_params.h"
#include "event/thread.h"
#define KW2XRF_NUM ARRAY_SIZE(kw2xrf_params)
extern void auto_init_event_thread(void);
static kw2xrf_t kw2xrf_dev[KW2XRF_NUM];
static bhp_event_t kw2xrf_bhp[KW2XRF_NUM];
#endif
#ifdef MODULE_MRF24J40
#include "mrf24j40.h"
#include "mrf24j40_params.h"
#define MRF24J40_NUM ARRAY_SIZE(mrf24j40_params)
static mrf24j40_t mrf24j40_dev[MRF24J40_NUM];
static bhp_event_t mrf24j40_bhp[MRF24J40_NUM];
#endif
void ieee802154_hal_test_init_devs(ieee802154_dev_cb_t cb, void *opaque)
{
if (IS_USED(MODULE_EVENT_THREAD)) {
auto_init_event_thread();
}
/* Call the init function of the device (this should be handled by
* `auto_init`) */
ieee802154_dev_t *radio = NULL;
(void) radio;
(void) cb;
(void) opaque;
if (RADIOS_NUMOF == 0) {
puts("Radio is either not supported or not present");
assert(false);
}
#ifdef MODULE_CC2538_RF
if ((radio = cb(IEEE802154_DEV_TYPE_CC2538_RF, opaque)) ){
cc2538_rf_hal_setup(radio);
@ -69,7 +90,6 @@ void ieee802154_hal_test_init_devs(ieee802154_dev_cb_t cb, void *opaque)
#endif
#ifdef MODULE_KW2XRF
auto_init_event_thread();
if ((radio = cb(IEEE802154_DEV_TYPE_KW2XRF, opaque)) ){
for (unsigned i = 0; i < KW2XRF_NUM; i++) {
const kw2xrf_params_t *p = &kw2xrf_params[i];
@ -87,4 +107,15 @@ void ieee802154_hal_test_init_devs(ieee802154_dev_cb_t cb, void *opaque)
socket_zep_setup(&_socket_zeps[0], &socket_zep_params[0]);
}
#endif
#ifdef MODULE_MRF24J40
if ((radio = cb(IEEE802154_DEV_TYPE_MRF24J40, opaque)) ){
for (unsigned i = 0; i < MRF24J40_NUM; i++) {
const mrf24j40_params_t *p = &mrf24j40_params[i];
bhp_event_init(&mrf24j40_bhp[i], EVENT_PRIO_HIGHEST, &mrf24j40_radio_irq_handler, radio);
mrf24j40_init(&mrf24j40_dev[i], p, radio, bhp_event_isr_cb, &mrf24j40_bhp[i]);
break;
}
}
#endif
}

View File

@ -61,7 +61,7 @@ static eui64_t ext_addr;
static network_uint16_t short_addr;
static uint8_t seq;
static ieee802154_dev_t _radio[RADIOS_NUMOF];
static ieee802154_dev_t _radio;
static void _print_packet(size_t size, uint8_t lqi, int16_t rssi)
{
@ -89,7 +89,7 @@ static int print_addr(int argc, char **argv)
static void _ack_timeout(event_t *event)
{
(void) event;
ieee802154_dev_t *dev = &_radio[0];
ieee802154_dev_t *dev = &_radio;
ieee802154_radio_set_frame_filter_mode(dev, IEEE802154_FILTER_ACCEPT);
}
@ -112,7 +112,7 @@ void _crc_error_handler(event_t *event)
{
(void) event;
puts("Frame with invalid CRC received");
ieee802154_dev_t* dev = &_radio[0];
ieee802154_dev_t* dev = &_radio;
/* Force transition to IDLE before calling the read function */
ieee802154_radio_set_idle(dev, true);
@ -130,7 +130,7 @@ void _rx_done_handler(event_t *event)
{
(void) event;
ieee802154_rx_info_t info;
ieee802154_dev_t* dev = &_radio[0];
ieee802154_dev_t* dev = &_radio;
/* Force transition to IDLE before calling the read function */
ieee802154_radio_set_idle(dev, true);
@ -140,7 +140,7 @@ void _rx_done_handler(event_t *event)
* NOTE: It's possible to call `ieee802154_radio_len` to retrieve the packet
* length. Since the buffer is fixed in this test, we don't use it
*/
int size = ieee802154_radio_read(&_radio[0], buffer, 127, &info);
int size = ieee802154_radio_read(&_radio, buffer, 127, &info);
if (size > 0) {
/* Print packet while we wait for the state transition */
_print_packet(size, info.lqi, info.rssi);
@ -179,10 +179,10 @@ static void _tx_finish_handler(event_t *event)
(void) event;
/* The TX_DONE event indicates it's safe to call the confirm counterpart */
expect(ieee802154_radio_confirm_transmit(&_radio[0], &tx_info) >= 0);
expect(ieee802154_radio_confirm_transmit(&_radio, &tx_info) >= 0);
ieee802154_radio_set_rx(&_radio[0]);
if (!ieee802154_radio_has_irq_ack_timeout(&_radio[0]) && !ieee802154_radio_has_frame_retrans(&_radio[0])) {
ieee802154_radio_set_rx(&_radio);
if (!ieee802154_radio_has_irq_ack_timeout(&_radio) && !ieee802154_radio_has_frame_retrans(&_radio)) {
/* This is just to show how the MAC layer would handle ACKs... */
xtimer_set(&timer_ack, ACK_TIMEOUT_TIME);
}
@ -204,7 +204,7 @@ static void _tx_finish_handler(event_t *event)
puts("");
if (ieee802154_radio_has_frame_retrans_info(&_radio[0])) {
if (ieee802154_radio_has_frame_retrans_info(&_radio)) {
printf("Retransmission attempts: %i\n", tx_info.retrans);
}
@ -218,19 +218,19 @@ static event_t _tx_finish_ev = {
static void _send(iolist_t *pkt)
{
/* Request a state change to IDLE */
if (ieee802154_radio_request_set_idle(&_radio[0], false) < 0) {
if (ieee802154_radio_request_set_idle(&_radio, false) < 0) {
puts("Couldn't send frame");
return;
}
/* Write the packet to the radio while the radio is transitioning to IDLE */
ieee802154_radio_write(&_radio[0], pkt);
ieee802154_radio_write(&_radio, pkt);
/* Block until the radio confirms the state change */
while(ieee802154_radio_confirm_set_idle(&_radio[0]) == -EAGAIN);
while(ieee802154_radio_confirm_set_idle(&_radio) == -EAGAIN);
/* Set the frame filter to receive ACKs */
ieee802154_radio_set_frame_filter_mode(&_radio[0], IEEE802154_FILTER_ACK_ONLY);
ieee802154_radio_set_frame_filter_mode(&_radio, IEEE802154_FILTER_ACK_ONLY);
/* Trigger the transmit and wait for the mutex unlock (TX_DONE event).
* Spin if the radio is busy before transmission (this indicates the
@ -238,7 +238,7 @@ static void _send(iolist_t *pkt)
* This won't be necessary anymore when the upper layers take care
* of the IFS.
*/
while (ieee802154_radio_request_transmit(&_radio[0]) == -EBUSY) {}
while (ieee802154_radio_request_transmit(&_radio) == -EBUSY) {}
mutex_lock(&lock);
event_post(EVENT_PRIO_HIGHEST, &_tx_finish_ev);
@ -265,6 +265,9 @@ static ieee802154_dev_t *_reg_callback(ieee802154_dev_type_t type, void *opaque)
case IEEE802154_DEV_TYPE_KW2XRF:
printf("kw2xrf");
break;
case IEEE802154_DEV_TYPE_MRF24J40:
printf("mrf24j40");
break;
}
puts(".");
@ -273,8 +276,9 @@ static ieee802154_dev_t *_reg_callback(ieee802154_dev_type_t type, void *opaque)
return NULL;
}
reg->count++;
puts("Success");
return &_radio[reg->count++];
return &_radio;
}
static int _init(void)
@ -285,7 +289,7 @@ static int _init(void)
ieee802154_hal_test_init_devs(_reg_callback, &reg);
/* Set the Event Notification */
((ieee802154_dev_t*) &_radio[0])->cb = _hal_radio_cb;
((ieee802154_dev_t*) &_radio)->cb = _hal_radio_cb;
/* Note that addresses are not kept in the radio. This assumes MAC layers
* already have a copy of the address */
@ -294,39 +298,39 @@ static int _init(void)
/* Since the device was already initialized, turn on the radio.
* The transceiver state will be "TRX_OFF" */
res = ieee802154_radio_request_on(&_radio[0]);
res = ieee802154_radio_request_on(&_radio);
expect(res >= 0);
while(ieee802154_radio_confirm_on(&_radio[0]) == -EAGAIN) {}
while(ieee802154_radio_confirm_on(&_radio) == -EAGAIN) {}
ieee802154_radio_set_frame_filter_mode(&_radio[0], IEEE802154_FILTER_ACCEPT);
ieee802154_radio_set_frame_filter_mode(&_radio, IEEE802154_FILTER_ACCEPT);
uint16_t panid = CONFIG_IEEE802154_DEFAULT_PANID;
/* Set all IEEE addresses */
res = ieee802154_radio_config_addr_filter(&_radio[0],
res = ieee802154_radio_config_addr_filter(&_radio,
IEEE802154_AF_SHORT_ADDR, &short_addr);
expect(res >= 0);
res = ieee802154_radio_config_addr_filter(&_radio[0],
res = ieee802154_radio_config_addr_filter(&_radio,
IEEE802154_AF_EXT_ADDR, &ext_addr);
expect(res >= 0);
res = ieee802154_radio_config_addr_filter(&_radio[0],
res = ieee802154_radio_config_addr_filter(&_radio,
IEEE802154_AF_PANID, &panid);
expect(res >= 0);
/* Set PHY configuration */
ieee802154_phy_conf_t conf = {.channel=CONFIG_IEEE802154_DEFAULT_CHANNEL, .page=CONFIG_IEEE802154_DEFAULT_SUBGHZ_PAGE, .pow=CONFIG_IEEE802154_DEFAULT_TXPOWER};
res = ieee802154_radio_config_phy(&_radio[0], &conf);
res = ieee802154_radio_config_phy(&_radio, &conf);
expect(res >= 0);
/* ieee802154_radio_set_cca_mode*/
res = ieee802154_radio_set_cca_mode(&_radio[0], IEEE802154_CCA_MODE_ED_THRESHOLD);
res = ieee802154_radio_set_cca_mode(&_radio, IEEE802154_CCA_MODE_ED_THRESHOLD);
expect(res >= 0);
res = ieee802154_radio_set_cca_threshold(&_radio[0], CONFIG_IEEE802154_CCA_THRESH_DEFAULT);
res = ieee802154_radio_set_cca_threshold(&_radio, CONFIG_IEEE802154_CCA_THRESH_DEFAULT);
expect(res >= 0);
/* Set the transceiver state to RX_ON in order to receive packets */
ieee802154_radio_set_rx(&_radio[0]);
ieee802154_radio_set_rx(&_radio);
return 0;
}
@ -376,12 +380,20 @@ int _cca(int argc, char **argv)
{
(void) argc;
(void) argv;
if (ieee802154_radio_request_cca(&_radio[0]) < 0) {
puts("Couldn't perform CCA");
int res;
if (ieee802154_radio_has_irq_cca_done(&_radio)) {
if (ieee802154_radio_request_cca(&_radio) < 0) {
puts("Couldn't perform CCA");
return -ENODEV;
}
mutex_lock(&lock);
res = ieee802154_radio_confirm_cca(&_radio);
expect(res >= 0);
}
else {
res = ieee802154_radio_cca(&_radio);
}
mutex_lock(&lock);
int res = ieee802154_radio_confirm_cca(&_radio[0]);
expect(res >= 0);
if (res > 0) {
puts("CLEAR");
@ -402,12 +414,12 @@ int _test_states(int argc, char **argv)
xtimer_ticks32_t a;
/* Force transition to IDLE */
res = ieee802154_radio_set_idle(&_radio[0], true);
res = ieee802154_radio_set_idle(&_radio, true);
assert(res == 0);
printf("Testing TX<->RX transition time: ");
a = xtimer_now();
res = ieee802154_radio_set_rx(&_radio[0]);
res = ieee802154_radio_set_rx(&_radio);
assert(res == 0);
usecs = xtimer_usec_from_ticks(xtimer_diff(xtimer_now(), a));
printf("%" PRIu32 " us (%s)\n", usecs, usecs > MAX_TX_RX_TURNAROUND
@ -416,14 +428,14 @@ int _test_states(int argc, char **argv)
printf("Testing RX<->TX transition time");
a = xtimer_now();
res = ieee802154_radio_set_idle(&_radio[0], true);
res = ieee802154_radio_set_idle(&_radio, true);
assert(res == 0);
usecs = xtimer_usec_from_ticks(xtimer_diff(xtimer_now(), a));
printf("%" PRIu32 " us (%s)\n", usecs, usecs > MAX_TX_RX_TURNAROUND
? "FAIL"
: "PASS");
ieee802154_radio_set_rx(&_radio[0]);
ieee802154_radio_set_rx(&_radio);
return 0;
}
@ -470,7 +482,7 @@ static int promisc(int argc, char **argv)
puts("Disabled promiscuos mode");
}
return ieee802154_radio_set_frame_filter_mode(&_radio[0], conf);
return ieee802154_radio_set_frame_filter_mode(&_radio, conf);
}
int config_phy(int argc, char **argv)
@ -519,7 +531,7 @@ int config_phy(int argc, char **argv)
return 1;
}
ieee802154_dev_t *dev = &_radio[0];
ieee802154_dev_t *dev = &_radio;
ieee802154_radio_set_idle(dev, true);
ieee802154_phy_conf_t conf = {.phy_mode=phy_mode, .channel=channel, .page=0, .pow=tx_pow};
if (ieee802154_radio_config_phy(dev, &conf) < 0) {
@ -537,7 +549,7 @@ int config_phy(int argc, char **argv)
int txmode_cmd(int argc, char **argv)
{
ieee802154_dev_t *dev = &_radio[0];
ieee802154_dev_t *dev = &_radio;
int res = -EINVAL;
if (argc < 2) {
@ -570,7 +582,7 @@ int txmode_cmd(int argc, char **argv)
static int _config_cca_cmd(int argc, char **argv)
{
ieee802154_dev_t *dev = &_radio[0];
ieee802154_dev_t *dev = &_radio;
int res = -EINVAL;
ieee802154_cca_mode_t mode;
@ -633,63 +645,63 @@ static int _caps_cmd(int argc, char **argv)
bool has_phy_mr_ofdm = false;
bool has_phy_mr_fsk = false;
if (ieee802154_radio_has_frame_retrans(&_radio[0])) {
if (ieee802154_radio_has_frame_retrans(&_radio)) {
has_frame_retrans = true;
}
if (ieee802154_radio_has_auto_csma(&_radio[0])) {
if (ieee802154_radio_has_auto_csma(&_radio)) {
has_auto_csma = true;
}
if (ieee802154_radio_has_24_ghz(&_radio[0])) {
if (ieee802154_radio_has_24_ghz(&_radio)) {
has_24_ghz = true;
}
if (ieee802154_radio_has_sub_ghz(&_radio[0])) {
if (ieee802154_radio_has_sub_ghz(&_radio)) {
has_sub_ghz = true;
}
if (ieee802154_radio_has_irq_tx_done(&_radio[0])) {
if (ieee802154_radio_has_irq_tx_done(&_radio)) {
has_irq_tx_done = true;
}
if (ieee802154_radio_has_irq_rx_start(&_radio[0])) {
if (ieee802154_radio_has_irq_rx_start(&_radio)) {
has_irq_rx_start = true;
}
if (ieee802154_radio_has_irq_ack_timeout(&_radio[0])) {
if (ieee802154_radio_has_irq_ack_timeout(&_radio)) {
has_irq_ack_timeout = true;
}
if (ieee802154_radio_has_irq_cca_done(&_radio[0])) {
if (ieee802154_radio_has_irq_cca_done(&_radio)) {
has_irq_cca_done = true;
}
if (ieee802154_radio_has_frame_retrans_info(&_radio[0])) {
if (ieee802154_radio_has_frame_retrans_info(&_radio)) {
has_frame_retrans_info = true;
}
if (ieee802154_radio_has_phy_bpsk(&_radio[0])) {
if (ieee802154_radio_has_phy_bpsk(&_radio)) {
has_phy_bpsk = true;
}
if (ieee802154_radio_has_phy_ask(&_radio[0])) {
if (ieee802154_radio_has_phy_ask(&_radio)) {
has_phy_ask = true;
}
if (ieee802154_radio_has_phy_oqpsk(&_radio[0])) {
if (ieee802154_radio_has_phy_oqpsk(&_radio)) {
has_phy_oqpsk = true;
}
if (ieee802154_radio_has_phy_mr_oqpsk(&_radio[0])) {
if (ieee802154_radio_has_phy_mr_oqpsk(&_radio)) {
has_phy_mr_oqpsk = true;
}
if (ieee802154_radio_has_phy_mr_ofdm(&_radio[0])) {
if (ieee802154_radio_has_phy_mr_ofdm(&_radio)) {
has_phy_mr_ofdm = true;
}
if (ieee802154_radio_has_phy_mr_fsk(&_radio[0])) {
if (ieee802154_radio_has_phy_mr_fsk(&_radio)) {
has_phy_mr_fsk = true;
}

View File

@ -1,23 +1,30 @@
include ../Makefile.tests_common
#
# Due to missing Kconfig support, whitelist boards that are known to have a
# working Kconfig dependency resolution.
# Other boards should still work when running with CONTINUE_ON_EXPECTED_ERRORS=1
BOARD_WHITELIST += adafruit-clue \
adafruit-itsybitsy-nrf52 \
arduino-nano-33-ble \
cc2538dk \
feather-nrf52840 \
native \
nrf52840dk \
nrf52840dongle \
nrf52840-mdk \
nucleo-l152re \
nucleo-f303re \
nucleo-wl55jc \
omote \
openmote-cc2538 \
reel \
remote-pa \
remote-reva \
remote-revb \
pba-d-01-kw2x \
#
BOARD_WHITELIST := \
adafruit-clue \
adafruit-itsybitsy-nrf52 \
arduino-nano-33-ble \
cc2538dk \
feather-nrf52840 \
native \
nrf52840dk \
nrf52840dongle \
nrf52840-mdk \
omote \
openmote-cc2538 \
reel \
remote-pa \
remote-reva \
remote-revb \
pba-d-01-kw2x \
#
USEMODULE += od
USEMODULE += shell
USEMODULE += shell_cmds_default

View File

@ -192,6 +192,9 @@ static ieee802154_dev_t *_reg_callback(ieee802154_dev_type_t type, void *opaque)
case IEEE802154_DEV_TYPE_KW2XRF:
printf("kw2xrf");
break;
case IEEE802154_DEV_TYPE_MRF24J40:
printf("mrf24j40");
break;
}
puts(".");