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) #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 #ifdef __cplusplus
} }
#endif #endif

View File

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

View File

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

View File

@ -15,6 +15,7 @@ config CPU_MODEL_ATMEGA256RFR2
select CPU_FAM_ATMEGA256RF select CPU_FAM_ATMEGA256RF
select HAS_ATMEGA_PCINT1 select HAS_ATMEGA_PCINT1
select HAS_CPU_ATMEGA256RFR2 select HAS_CPU_ATMEGA256RFR2
select HAVE_AT86RFR2
## Definition of specific features ## Definition of specific features
config HAS_CPU_ATMEGA256RFR2 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/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_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 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_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/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\. 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_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_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_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_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_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\. 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))) ifneq (,$(filter nrfmin,$(USEMODULE)))
FEATURES_REQUIRED += radio_nrfmin FEATURES_REQUIRED += radio_nrfmin
FEATURES_REQUIRED += periph_cpuid FEATURES_REQUIRED += periph_cpuid
USEMODULE += netif
endif endif
ifneq (,$(filter nrf24l01p_ng_%,$(USEMODULE))) ifneq (,$(filter nrf24l01p_ng_%,$(USEMODULE)))

View File

@ -71,6 +71,7 @@
#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"
#include "net/ieee802154/radio.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -105,6 +106,11 @@ extern "C" {
#define MRF24J40_MAX_FRAME_RETRIES (3U) /**< Number of frame retries (fixed) */ #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 * @defgroup drivers_mrf24j40_config mrf24j40 driver compile configuration
* @ingroup drivers_mrf24j40 * @ingroup drivers_mrf24j40
@ -151,29 +157,13 @@ typedef struct mrf24j40_params {
* @brief Device descriptor for MRF24J40 radio devices * @brief Device descriptor for MRF24J40 radio devices
*/ */
typedef struct { typedef struct {
netdev_ieee802154_t netdev; /**< netdev parent struct */
/* device specific fields */ /* device specific fields */
mrf24j40_params_t params; /**< parameters for initialization */ const 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 */
uint8_t fcf_low; /**< Low 8 FCF bits of the current TX frame. */ uint8_t fcf_low; /**< Low 8 FCF bits of the current TX frame. */
uint8_t pending; /**< Flags for pending tasks */ uint8_t pending; /**< Flags for pending tasks */
uint8_t irq_flag; /**< Flags for IRQs */ bool tx_pending; /**< Whether a transmission is pending or not */
uint8_t tx_retries; /**< Number of retries needed for last transmission */
} mrf24j40_t; } 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 * @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); 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 * @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); 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 * @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); 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] * @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); 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) * @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); 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 * @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); 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 * @brief Put in sleep mode
* *
@ -379,19 +306,12 @@ bool mrf24j40_get_turbo(mrf24j40_t *dev);
*/ */
void mrf24j40_sleep(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 * @brief Wake up from sleep mode
* *
* @param[in] dev device to eventually wake up * @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. * @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); 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 #ifdef __cplusplus
} }
#endif #endif

View File

@ -13,14 +13,14 @@ menuconfig MODULE_MRF24J40
depends on HAS_PERIPH_GPIO depends on HAS_PERIPH_GPIO
depends on HAS_PERIPH_GPIO_IRQ depends on HAS_PERIPH_GPIO_IRQ
depends on HAS_PERIPH_SPI 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
select MODULE_PERIPH_GPIO_IRQ select MODULE_PERIPH_GPIO_IRQ
select MODULE_PERIPH_SPI 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 if MODULE_MRF24J40

View File

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

View File

@ -37,7 +37,7 @@ extern "C" {
* *
* @return 0 on success, error otherwise * @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 * @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; } static inline void mrf24j40_enable_lna(mrf24j40_t *dev) { (void) dev; }
#endif #endif
/**
* @brief Flush the RX FIFO
*
* @param[in] dev device to flush the RX FIFO
*/
void mrf24j40_flush_rx(mrf24j40_t *dev);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #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) * @name Bitfield definitions for the PACON2 register (0x18)
* @{ * @{

View File

@ -24,138 +24,37 @@
#include "mrf24j40_registers.h" #include "mrf24j40_registers.h"
#include "mrf24j40_internal.h" #include "mrf24j40_internal.h"
#include "mrf24j40_netdev.h" #include "mrf24j40_netdev.h"
#include "xtimer.h" #include "ztimer.h"
#define ENABLE_DEBUG 0 #define ENABLE_DEBUG 0
#include "debug.h" #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 mrf24j40_reset(mrf24j40_t *dev)
{ {
int res = mrf24j40_init(dev); int res = mrf24j40_init_hw(dev);
if (res < 0) { if (res < 0) {
return res; 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 */ /* configure Immediate Sleep and Wake-Up mode */
mrf24j40_reg_write_short(dev, MRF24J40_REG_WAKECON, MRF24J40_WAKECON_IMMWAKE); mrf24j40_reg_write_short(dev, MRF24J40_REG_WAKECON, MRF24J40_WAKECON_IMMWAKE);
/* set default options */ /* 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, NETDEV_IEEE802154_ACK_REQ, true);
mrf24j40_set_option(dev, MRF24J40_OPT_CSMA, true); mrf24j40_set_option(dev, MRF24J40_OPT_CSMA, true);
/* go into RX state */
mrf24j40_reset_tasks(dev); mrf24j40_reset_tasks(dev);
dev->state = 0;
mrf24j40_set_state(dev, MRF24J40_PSEUDO_STATE_IDLE);
DEBUG("mrf24j40_reset(): reset complete.\n"); DEBUG("mrf24j40_reset(): reset complete.\n");
return 0; 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) 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); DEBUG("[mrf24j40] TX_load\n");
dev->tx_frame_len += (uint8_t)len;
mrf24j40_tx_normal_fifo_write(dev, MRF24J40_TX_NORMAL_FIFO + offset + 2, data, len); mrf24j40_tx_normal_fifo_write(dev, MRF24J40_TX_NORMAL_FIFO + offset + 2, data, len);
return offset + 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.h"
#include "mrf24j40_internal.h" #include "mrf24j40_internal.h"
#include "mrf24j40_registers.h" #include "mrf24j40_registers.h"
#include "xtimer.h" #include "ztimer.h"
#define ENABLE_DEBUG 0 #define ENABLE_DEBUG 0
#include "debug.h" #include "debug.h"
@ -64,11 +64,6 @@
* 0b11111000 -> -36.3dB-> -36 * 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, 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, 0x40, 0x50, 0x58, 0x60, 0x68, 0x70, 0x78, 0x78, 0x78, 0x80,
0x80, 0x90, 0x98, 0xa0, 0xa8, 0xb0, 0xb8, 0xb8, 0xb8, 0xc0, 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 */ } 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) void mrf24j40_set_addr_short(mrf24j40_t *dev, uint16_t addr)
{ {
network_uint16_t naddr; network_uint16_t naddr;
@ -156,13 +142,6 @@ void mrf24j40_set_addr_short(mrf24j40_t *dev, uint16_t addr)
naddr.u8[0]); 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) void mrf24j40_set_addr_long(mrf24j40_t *dev, const uint8_t *addr)
{ {
for (int i = 0; i < 8; i++) { 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) void mrf24j40_set_chan(mrf24j40_t *dev, uint8_t channel)
{ {
uint8_t channel_value; uint8_t channel_value;
@ -184,8 +158,6 @@ void mrf24j40_set_chan(mrf24j40_t *dev, uint8_t channel)
return; return;
} }
dev->netdev.chan = channel;
/* Channel settings /* Channel settings
* 11 -> Value = 0x03 * 11 -> Value = 0x03
* 12 -> Value = 0x13 * 12 -> Value = 0x13
@ -251,11 +223,6 @@ void mrf24j40_set_chan(mrf24j40_t *dev, uint8_t channel)
mrf24j40_reset_state_machine(dev); 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) void mrf24j40_set_pan(mrf24j40_t *dev, uint16_t pan)
{ {
le_uint16_t le_pan = byteorder_htols(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]); 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) void mrf24j40_set_txpower(mrf24j40_t *dev, int16_t txpower)
{ {
uint8_t txpower_reg_value; 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) void mrf24j40_set_csma_max_retries(mrf24j40_t *dev, int8_t retries)
{ {
uint8_t tmp; 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); 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) void mrf24j40_set_cca_threshold(mrf24j40_t *dev, int8_t value)
{ {
/* ensure the given value is negative, since a CCA threshold > 0 is /* 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); 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) void mrf24j40_set_option(mrf24j40_t *dev, uint16_t option, bool state)
{ {
uint8_t tmp; uint8_t tmp;
@ -363,7 +299,6 @@ void mrf24j40_set_option(mrf24j40_t *dev, uint16_t option, bool state)
/* set option field */ /* set option field */
if (state) { if (state) {
dev->netdev.flags |= option;
/* trigger option specific actions */ /* trigger option specific actions */
switch (option) { switch (option) {
case MRF24J40_OPT_CSMA: case MRF24J40_OPT_CSMA:
@ -396,7 +331,6 @@ void mrf24j40_set_option(mrf24j40_t *dev, uint16_t option, bool state)
} }
/* clear option field */ /* clear option field */
else { else {
dev->netdev.flags &= ~(option);
/* trigger option specific actions */ /* trigger option specific actions */
switch (option) { switch (option) {
case MRF24J40_OPT_CSMA: 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_PROMI;
tmp &= ~MRF24J40_RXMCR_ERRPKT; tmp &= ~MRF24J40_RXMCR_ERRPKT;
/* re-enable AUTOACK only if the option is set */ /* re-enable AUTOACK only if the option is set */
if (dev->netdev.flags & NETDEV_IEEE802154_ACK_REQ) { tmp &= ~(MRF24J40_RXMCR_NOACKRSP);
tmp &= ~(MRF24J40_RXMCR_NOACKRSP); mrf24j40_reg_write_short(dev, MRF24J40_REG_RXMCR, tmp);
mrf24j40_reg_write_short(dev, MRF24J40_REG_RXMCR, tmp);
}
break; break;
case NETDEV_IEEE802154_ACK_REQ: case NETDEV_IEEE802154_ACK_REQ:
DEBUG("[mrf24j40] opt: disabling auto ACKs\n"); 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) void mrf24j40_sleep(mrf24j40_t *dev)
{ {
DEBUG("[mrf24j40] Putting into sleep mode\n"); 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); mrf24j40_reg_write_short(dev, MRF24J40_REG_SOFTRST, MRF24J40_SOFTRST_RSTPWR);
/* Go to SLEEP mode */ /* Go to SLEEP mode */
mrf24j40_reg_write_short(dev, MRF24J40_REG_SLPACK, MRF24J40_SLPACK_SLPACK); 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) { DEBUG("[mrf24j40] Waking up from sleep mode\n");
mrf24j40_sleep(dev); /* 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);
void mrf24j40_assert_awake(mrf24j40_t *dev) mrf24j40_reg_write_short(dev, MRF24J40_REG_WAKECON, MRF24J40_WAKECON_IMMWAKE);
{ /* reset state machine */
if (dev->state == MRF24J40_PSEUDO_STATE_SLEEP) { mrf24j40_reg_write_short(dev, MRF24J40_REG_RFCTL, MRF24J40_RFCTL_RFRST);
DEBUG("[mrf24j40] Waking up from sleep mode\n"); mrf24j40_reg_write_short(dev, MRF24J40_REG_RFCTL, 0x00);
/* Wake mrf up */ /* After wake-up, delay at least 2 ms to allow 20 MHz main
mrf24j40_reg_write_short(dev, MRF24J40_REG_WAKECON, MRF24J40_WAKECON_IMMWAKE | MRF24J40_WAKECON_REGWAKE); * oscillator time to stabilize before transmitting or receiving.
/* undocumented delay, needed for stable wakeup */ */
xtimer_usleep(MRF24J40_DELAY_SLEEP_TOGGLE); ztimer_sleep(ZTIMER_USEC, MRF24J40_WAKEUP_DELAY);
mrf24j40_reg_write_short(dev, MRF24J40_REG_WAKECON, MRF24J40_WAKECON_IMMWAKE); /* reset interrupts */
/* reset state machine */ mrf24j40_reg_read_short(dev, MRF24J40_REG_INTSTAT);
mrf24j40_reg_write_short(dev, MRF24J40_REG_RFCTL, MRF24J40_RFCTL_RFRST); mrf24j40_enable_auto_pa_lna(dev);
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;
}
} }
void mrf24j40_reset_state_machine(mrf24j40_t *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, MRF24J40_RFCTL_RFRST);
mrf24j40_reg_write_short(dev, MRF24J40_REG_RFCTL, 0x00); 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) void mrf24j40_software_reset(mrf24j40_t *dev)

View File

@ -21,7 +21,7 @@
*/ */
#include "periph/spi.h" #include "periph/spi.h"
#include "periph/gpio.h" #include "periph/gpio.h"
#include "xtimer.h" #include "ztimer.h"
#include "mrf24j40_internal.h" #include "mrf24j40_internal.h"
#include "mrf24j40_registers.h" #include "mrf24j40_registers.h"
#include "kernel_defines.h" #include "kernel_defines.h"
@ -29,12 +29,12 @@
#define ENABLE_DEBUG 0 #define ENABLE_DEBUG 0
#include "debug.h" #include "debug.h"
#define SPIDEV (dev->params.spi) #define SPIDEV (dev->params->spi)
#define CSPIN (dev->params.cs_pin) #define CSPIN (dev->params->cs_pin)
static inline void getbus(mrf24j40_t *dev) 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) #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 */ #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)) { if (IS_ACTIVE(CONFIG_MRF24J40_TEST_SPI_CONNECTION)) {
/* Check if MRF24J40 is available */ /* Check if MRF24J40 is available */
@ -263,36 +263,34 @@ void mrf24j40_reset_tasks(mrf24j40_t *dev)
void mrf24j40_update_tasks(mrf24j40_t *dev) void mrf24j40_update_tasks(mrf24j40_t *dev)
{ {
if (dev->irq_flag) { uint8_t newpending = 0;
uint8_t newpending = 0; uint8_t instat = 0;
uint8_t instat = 0;
dev->irq_flag = 0; instat = mrf24j40_reg_read_short(dev, MRF24J40_REG_INTSTAT);
instat = mrf24j40_reg_read_short(dev, MRF24J40_REG_INTSTAT); /* check if TX done */
/* check if TX done */ if (instat & MRF24J40_INTSTAT_TXNIF) {
if (instat & MRF24J40_INTSTAT_TXNIF) { newpending |= MRF24J40_TASK_TX_DONE | MRF24J40_TASK_TX_READY;
newpending |= MRF24J40_TASK_TX_DONE | MRF24J40_TASK_TX_READY; /* transmit done, returning to configured idle state */
/* 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;
} }
if (instat & MRF24J40_INTSTAT_RXIF) {
newpending |= MRF24J40_TASK_RX_READY;
}
/* check if RX pending */
dev->pending |= newpending;
} }
void mrf24j40_hardware_reset(mrf24j40_t *dev) void mrf24j40_hardware_reset(mrf24j40_t *dev)
{ {
/* wake up from sleep in case radio is sleeping */
mrf24j40_assert_awake(dev);
/* trigger hardware reset */ /* trigger hardware reset */
gpio_clear(dev->params.reset_pin); gpio_clear(dev->params->reset_pin);
/* Datasheet - Not specified */ /* Datasheet - Not specified */
xtimer_usleep(MRF24J40_RESET_PULSE_WIDTH); ztimer_sleep(ZTIMER_USEC, MRF24J40_RESET_PULSE_WIDTH);
gpio_set(dev->params.reset_pin); gpio_set(dev->params->reset_pin);
/* Datasheet - MRF24J40 ~2ms */ /* 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) void flashpage_write_page(unsigned page, const void *data)
{ {
assert((unsigned) page < FLASHPAGE_NUMOF); assert((unsigned) page < FLASHPAGE_NUMOF);
assert(data != NULL);
flashpage_erase(page); flashpage_erase(page);
/* write page */ /* write page */
if (data != NULL) { flashpage_write(flashpage_addr(page), data, FLASHPAGE_SIZE);
flashpage_write(flashpage_addr(page), data, FLASHPAGE_SIZE);
}
} }
#endif #endif

View File

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

View File

@ -1267,9 +1267,9 @@ static inline int ieee802154_radio_cca(ieee802154_dev_t *dev)
if (res < 0) { if (res < 0) {
return res; 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/netif/ieee802154.h"
#include "net/gnrc.h" #include "net/gnrc.h"
#include "include/init_devs.h" #include "include/init_devs.h"
#include "net/netdev/ieee802154_submac.h"
#include "bhp/event.h"
#include "mrf24j40.h" #include "mrf24j40.h"
#include "mrf24j40_params.h" #include "mrf24j40_params.h"
@ -38,20 +40,31 @@
#define MRF24J40_NUM ARRAY_SIZE(mrf24j40_params) #define MRF24J40_NUM ARRAY_SIZE(mrf24j40_params)
static mrf24j40_t mrf24j40_devs[MRF24J40_NUM]; 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 char _mrf24j40_stacks[MRF24J40_NUM][MRF24J40_MAC_STACKSIZE];
static gnrc_netif_t _netif[MRF24J40_NUM]; static gnrc_netif_t _netif[MRF24J40_NUM];
static bhp_event_t mrf24j40_bhp[MRF24J40_NUM];
void auto_init_mrf24j40(void) void auto_init_mrf24j40(void)
{ {
for (unsigned i = 0; i < MRF24J40_NUM; i++) { 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); 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], gnrc_netif_ieee802154_create(&_netif[i], _mrf24j40_stacks[i],
MRF24J40_MAC_STACKSIZE, MRF24J40_MAC_PRIO, MRF24J40_MAC_STACKSIZE, MRF24J40_MAC_PRIO,
"mrf24j40", "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 config MODULE_IEEE802154_SUBMAC
bool "IEEE 802.15.4 submac" bool "IEEE 802.15.4 submac"
select MODULE_XTIMER select ZTIMER_USEC
help help
This module defines a common layer for handling the lower part of the IEEE 802.15.4 MAC layer. 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 "dummy_thread/Kconfig"
rsource "interactive_sync/Kconfig" rsource "interactive_sync/Kconfig"
rsource "netdev_eth_minimal/Kconfig" rsource "netdev_eth_minimal/Kconfig"
rsource "netdev_ieee802154_minimal/Kconfig"
rsource "print_stack_usage/Kconfig" rsource "print_stack_usage/Kconfig"
rsource "result_output/Kconfig" rsource "result_output/Kconfig"
endmenu # Test utilities 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 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 USEMODULE += test_utils_netdev_ieee802154_minimal
# select the driver to test # select the driver to test
@ -10,3 +35,7 @@ USEMODULE += mrf24j40ma
CFLAGS += -DEVENT_THREAD_STACKSIZE_DEFAULT=1024 CFLAGS += -DEVENT_THREAD_STACKSIZE_DEFAULT=1024
include $(RIOTBASE)/Makefile.include 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 "mrf24j40_params.h"
#include "shell.h" #include "shell.h"
#include "test_utils/netdev_ieee802154_minimal.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) { int netdev_ieee802154_minimal_init_devs(netdev_event_cb_t cb) {
puts("Initializing MRF24J40 devices"); 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++) { for (unsigned i = 0; i < MRF24J40_NUM; i++) {
printf("%d out of %d\n", i + 1, MRF24J40_NUM); printf("%d out of %d\n", i + 1, MRF24J40_NUM);
/* setup the specific driver */ netdev_register(&mrf24j40_netdev[i].dev.netdev, NETDEV_MRF24J40, 0);
mrf24j40_setup(&mrf24j40[i], &mrf24j40_params[i], i); netdev_ieee802154_submac_init(&mrf24j40_netdev[i]);
/* set the application-provided callback */ /* set the application-provided callback */
mrf24j40[i].netdev.netdev.event_callback = cb; mrf24j40_netdev[i].dev.netdev.event_callback = cb;
/* initialize the device driver */ /* 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) { if (res != 0) {
return -1; return -1;
} }

View File

@ -1,25 +1,29 @@
include ../Makefile.tests_common include ../Makefile.tests_common
BOARD_WHITELIST := \ # Due to missing Kconfig support, whitelist boards that are known to have a
adafruit-clue \ # working Kconfig dependency resolution.
adafruit-itsybitsy-nrf52 \ # Other boards should still work when running with CONTINUE_ON_EXPECTED_ERRORS=1
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 \
#
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) ifeq ($(BOARD), native)
ZEP_PORT_BASE ?= 17754 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) + \ #define RADIOS_NUMOF IS_USED(MODULE_CC2538_RF) + \
IS_USED(MODULE_NRF802154) + \ IS_USED(MODULE_NRF802154) + \
SOCKET_ZEP_MAX + \ SOCKET_ZEP_MAX + \
IS_USED(MODULE_MRF24J40) + \
IS_USED(MODULE_KW2XRF) IS_USED(MODULE_KW2XRF)
#if RADIOS_NUMOF == 0
#error "Radio is not supported"
#endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -48,6 +45,7 @@ typedef enum {
IEEE802154_DEV_TYPE_NRF802154, IEEE802154_DEV_TYPE_NRF802154,
IEEE802154_DEV_TYPE_SOCKET_ZEP, IEEE802154_DEV_TYPE_SOCKET_ZEP,
IEEE802154_DEV_TYPE_KW2XRF, IEEE802154_DEV_TYPE_KW2XRF,
IEEE802154_DEV_TYPE_MRF24J40,
} ieee802154_dev_type_t; } ieee802154_dev_type_t;
typedef ieee802154_dev_t* (*ieee802154_dev_cb_t)(ieee802154_dev_type_t type, 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 "assert.h"
#include "kernel_defines.h" #include "kernel_defines.h"
#include "net/ieee802154/radio.h" #include "net/ieee802154/radio.h"
@ -37,23 +38,43 @@
#include "socket_zep_params.h" #include "socket_zep_params.h"
#endif #endif
#include "event/thread.h"
extern void auto_init_event_thread(void);
#ifdef MODULE_KW2XRF #ifdef MODULE_KW2XRF
#include "kw2xrf.h" #include "kw2xrf.h"
#include "kw2xrf_params.h" #include "kw2xrf_params.h"
#include "event/thread.h"
#define KW2XRF_NUM ARRAY_SIZE(kw2xrf_params) #define KW2XRF_NUM ARRAY_SIZE(kw2xrf_params)
extern void auto_init_event_thread(void);
static kw2xrf_t kw2xrf_dev[KW2XRF_NUM]; static kw2xrf_t kw2xrf_dev[KW2XRF_NUM];
static bhp_event_t kw2xrf_bhp[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 #endif
void ieee802154_hal_test_init_devs(ieee802154_dev_cb_t cb, void *opaque) 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 /* Call the init function of the device (this should be handled by
* `auto_init`) */ * `auto_init`) */
ieee802154_dev_t *radio = NULL; ieee802154_dev_t *radio = NULL;
(void) radio; (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 #ifdef MODULE_CC2538_RF
if ((radio = cb(IEEE802154_DEV_TYPE_CC2538_RF, opaque)) ){ if ((radio = cb(IEEE802154_DEV_TYPE_CC2538_RF, opaque)) ){
cc2538_rf_hal_setup(radio); cc2538_rf_hal_setup(radio);
@ -69,7 +90,6 @@ void ieee802154_hal_test_init_devs(ieee802154_dev_cb_t cb, void *opaque)
#endif #endif
#ifdef MODULE_KW2XRF #ifdef MODULE_KW2XRF
auto_init_event_thread();
if ((radio = cb(IEEE802154_DEV_TYPE_KW2XRF, opaque)) ){ if ((radio = cb(IEEE802154_DEV_TYPE_KW2XRF, opaque)) ){
for (unsigned i = 0; i < KW2XRF_NUM; i++) { for (unsigned i = 0; i < KW2XRF_NUM; i++) {
const kw2xrf_params_t *p = &kw2xrf_params[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]); socket_zep_setup(&_socket_zeps[0], &socket_zep_params[0]);
} }
#endif #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 network_uint16_t short_addr;
static uint8_t seq; 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) 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) static void _ack_timeout(event_t *event)
{ {
(void) event; (void) event;
ieee802154_dev_t *dev = &_radio[0]; ieee802154_dev_t *dev = &_radio;
ieee802154_radio_set_frame_filter_mode(dev, IEEE802154_FILTER_ACCEPT); ieee802154_radio_set_frame_filter_mode(dev, IEEE802154_FILTER_ACCEPT);
} }
@ -112,7 +112,7 @@ void _crc_error_handler(event_t *event)
{ {
(void) event; (void) event;
puts("Frame with invalid CRC received"); 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 */ /* Force transition to IDLE before calling the read function */
ieee802154_radio_set_idle(dev, true); ieee802154_radio_set_idle(dev, true);
@ -130,7 +130,7 @@ void _rx_done_handler(event_t *event)
{ {
(void) event; (void) event;
ieee802154_rx_info_t info; 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 */ /* Force transition to IDLE before calling the read function */
ieee802154_radio_set_idle(dev, true); 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 * 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 * 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) { if (size > 0) {
/* Print packet while we wait for the state transition */ /* Print packet while we wait for the state transition */
_print_packet(size, info.lqi, info.rssi); _print_packet(size, info.lqi, info.rssi);
@ -179,10 +179,10 @@ static void _tx_finish_handler(event_t *event)
(void) event; (void) event;
/* The TX_DONE event indicates it's safe to call the confirm counterpart */ /* 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]); ieee802154_radio_set_rx(&_radio);
if (!ieee802154_radio_has_irq_ack_timeout(&_radio[0]) && !ieee802154_radio_has_frame_retrans(&_radio[0])) { 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... */ /* This is just to show how the MAC layer would handle ACKs... */
xtimer_set(&timer_ack, ACK_TIMEOUT_TIME); xtimer_set(&timer_ack, ACK_TIMEOUT_TIME);
} }
@ -204,7 +204,7 @@ static void _tx_finish_handler(event_t *event)
puts(""); 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); printf("Retransmission attempts: %i\n", tx_info.retrans);
} }
@ -218,19 +218,19 @@ static event_t _tx_finish_ev = {
static void _send(iolist_t *pkt) static void _send(iolist_t *pkt)
{ {
/* Request a state change to IDLE */ /* 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"); puts("Couldn't send frame");
return; return;
} }
/* Write the packet to the radio while the radio is transitioning to IDLE */ /* 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 */ /* 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 */ /* 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). /* Trigger the transmit and wait for the mutex unlock (TX_DONE event).
* Spin if the radio is busy before transmission (this indicates the * 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 * This won't be necessary anymore when the upper layers take care
* of the IFS. * of the IFS.
*/ */
while (ieee802154_radio_request_transmit(&_radio[0]) == -EBUSY) {} while (ieee802154_radio_request_transmit(&_radio) == -EBUSY) {}
mutex_lock(&lock); mutex_lock(&lock);
event_post(EVENT_PRIO_HIGHEST, &_tx_finish_ev); 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: case IEEE802154_DEV_TYPE_KW2XRF:
printf("kw2xrf"); printf("kw2xrf");
break; break;
case IEEE802154_DEV_TYPE_MRF24J40:
printf("mrf24j40");
break;
} }
puts("."); puts(".");
@ -273,8 +276,9 @@ static ieee802154_dev_t *_reg_callback(ieee802154_dev_type_t type, void *opaque)
return NULL; return NULL;
} }
reg->count++;
puts("Success"); puts("Success");
return &_radio[reg->count++]; return &_radio;
} }
static int _init(void) static int _init(void)
@ -285,7 +289,7 @@ static int _init(void)
ieee802154_hal_test_init_devs(_reg_callback, &reg); ieee802154_hal_test_init_devs(_reg_callback, &reg);
/* Set the Event Notification */ /* 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 /* Note that addresses are not kept in the radio. This assumes MAC layers
* already have a copy of the address */ * 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. /* Since the device was already initialized, turn on the radio.
* The transceiver state will be "TRX_OFF" */ * The transceiver state will be "TRX_OFF" */
res = ieee802154_radio_request_on(&_radio[0]); res = ieee802154_radio_request_on(&_radio);
expect(res >= 0); 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; uint16_t panid = CONFIG_IEEE802154_DEFAULT_PANID;
/* Set all IEEE addresses */ /* 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); IEEE802154_AF_SHORT_ADDR, &short_addr);
expect(res >= 0); expect(res >= 0);
res = ieee802154_radio_config_addr_filter(&_radio[0], res = ieee802154_radio_config_addr_filter(&_radio,
IEEE802154_AF_EXT_ADDR, &ext_addr); IEEE802154_AF_EXT_ADDR, &ext_addr);
expect(res >= 0); expect(res >= 0);
res = ieee802154_radio_config_addr_filter(&_radio[0], res = ieee802154_radio_config_addr_filter(&_radio,
IEEE802154_AF_PANID, &panid); IEEE802154_AF_PANID, &panid);
expect(res >= 0); expect(res >= 0);
/* Set PHY configuration */ /* Set PHY configuration */
ieee802154_phy_conf_t conf = {.channel=CONFIG_IEEE802154_DEFAULT_CHANNEL, .page=CONFIG_IEEE802154_DEFAULT_SUBGHZ_PAGE, .pow=CONFIG_IEEE802154_DEFAULT_TXPOWER}; 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); expect(res >= 0);
/* ieee802154_radio_set_cca_mode*/ /* 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); 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); expect(res >= 0);
/* Set the transceiver state to RX_ON in order to receive packets */ /* 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; return 0;
} }
@ -376,12 +380,20 @@ int _cca(int argc, char **argv)
{ {
(void) argc; (void) argc;
(void) argv; (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) { if (res > 0) {
puts("CLEAR"); puts("CLEAR");
@ -402,12 +414,12 @@ int _test_states(int argc, char **argv)
xtimer_ticks32_t a; xtimer_ticks32_t a;
/* Force transition to IDLE */ /* Force transition to IDLE */
res = ieee802154_radio_set_idle(&_radio[0], true); res = ieee802154_radio_set_idle(&_radio, true);
assert(res == 0); assert(res == 0);
printf("Testing TX<->RX transition time: "); printf("Testing TX<->RX transition time: ");
a = xtimer_now(); a = xtimer_now();
res = ieee802154_radio_set_rx(&_radio[0]); res = ieee802154_radio_set_rx(&_radio);
assert(res == 0); assert(res == 0);
usecs = xtimer_usec_from_ticks(xtimer_diff(xtimer_now(), a)); usecs = xtimer_usec_from_ticks(xtimer_diff(xtimer_now(), a));
printf("%" PRIu32 " us (%s)\n", usecs, usecs > MAX_TX_RX_TURNAROUND 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"); printf("Testing RX<->TX transition time");
a = xtimer_now(); a = xtimer_now();
res = ieee802154_radio_set_idle(&_radio[0], true); res = ieee802154_radio_set_idle(&_radio, true);
assert(res == 0); assert(res == 0);
usecs = xtimer_usec_from_ticks(xtimer_diff(xtimer_now(), a)); usecs = xtimer_usec_from_ticks(xtimer_diff(xtimer_now(), a));
printf("%" PRIu32 " us (%s)\n", usecs, usecs > MAX_TX_RX_TURNAROUND printf("%" PRIu32 " us (%s)\n", usecs, usecs > MAX_TX_RX_TURNAROUND
? "FAIL" ? "FAIL"
: "PASS"); : "PASS");
ieee802154_radio_set_rx(&_radio[0]); ieee802154_radio_set_rx(&_radio);
return 0; return 0;
} }
@ -470,7 +482,7 @@ static int promisc(int argc, char **argv)
puts("Disabled promiscuos mode"); 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) int config_phy(int argc, char **argv)
@ -519,7 +531,7 @@ int config_phy(int argc, char **argv)
return 1; return 1;
} }
ieee802154_dev_t *dev = &_radio[0]; ieee802154_dev_t *dev = &_radio;
ieee802154_radio_set_idle(dev, true); ieee802154_radio_set_idle(dev, true);
ieee802154_phy_conf_t conf = {.phy_mode=phy_mode, .channel=channel, .page=0, .pow=tx_pow}; ieee802154_phy_conf_t conf = {.phy_mode=phy_mode, .channel=channel, .page=0, .pow=tx_pow};
if (ieee802154_radio_config_phy(dev, &conf) < 0) { 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) int txmode_cmd(int argc, char **argv)
{ {
ieee802154_dev_t *dev = &_radio[0]; ieee802154_dev_t *dev = &_radio;
int res = -EINVAL; int res = -EINVAL;
if (argc < 2) { if (argc < 2) {
@ -570,7 +582,7 @@ int txmode_cmd(int argc, char **argv)
static int _config_cca_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; int res = -EINVAL;
ieee802154_cca_mode_t mode; 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_ofdm = false;
bool has_phy_mr_fsk = 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; has_frame_retrans = true;
} }
if (ieee802154_radio_has_auto_csma(&_radio[0])) { if (ieee802154_radio_has_auto_csma(&_radio)) {
has_auto_csma = true; has_auto_csma = true;
} }
if (ieee802154_radio_has_24_ghz(&_radio[0])) { if (ieee802154_radio_has_24_ghz(&_radio)) {
has_24_ghz = true; has_24_ghz = true;
} }
if (ieee802154_radio_has_sub_ghz(&_radio[0])) { if (ieee802154_radio_has_sub_ghz(&_radio)) {
has_sub_ghz = true; 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; 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; 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; 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; 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; has_frame_retrans_info = true;
} }
if (ieee802154_radio_has_phy_bpsk(&_radio[0])) { if (ieee802154_radio_has_phy_bpsk(&_radio)) {
has_phy_bpsk = true; has_phy_bpsk = true;
} }
if (ieee802154_radio_has_phy_ask(&_radio[0])) { if (ieee802154_radio_has_phy_ask(&_radio)) {
has_phy_ask = true; has_phy_ask = true;
} }
if (ieee802154_radio_has_phy_oqpsk(&_radio[0])) { if (ieee802154_radio_has_phy_oqpsk(&_radio)) {
has_phy_oqpsk = true; 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; 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; 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; has_phy_mr_fsk = true;
} }

View File

@ -1,23 +1,30 @@
include ../Makefile.tests_common 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 += od
USEMODULE += shell USEMODULE += shell
USEMODULE += shell_cmds_default 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: case IEEE802154_DEV_TYPE_KW2XRF:
printf("kw2xrf"); printf("kw2xrf");
break; break;
case IEEE802154_DEV_TYPE_MRF24J40:
printf("mrf24j40");
break;
} }
puts("."); puts(".");