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:
commit
d11a358b1d
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
13
dist/tools/doccheck/exclude_patterns
vendored
13
dist/tools/doccheck/exclude_patterns
vendored
@ -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\.
|
||||
|
@ -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)))
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
* @{
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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,
|
||||
};
|
374
drivers/mrf24j40/mrf24j40_radio_hal.c
Normal file
374
drivers/mrf24j40/mrf24j40_radio_hal.c
Normal 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,
|
||||
};
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
/** @} */
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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
|
||||
|
17
sys/test_utils/netdev_ieee802154_minimal/Kconfig
Normal file
17
sys/test_utils/netdev_ieee802154_minimal/Kconfig
Normal 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
|
11
tests/driver_mrf24j40/Kconfig
Normal file
11
tests/driver_mrf24j40/Kconfig
Normal 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
|
@ -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
|
||||
|
5
tests/driver_mrf24j40/app.config.test
Normal file
5
tests/driver_mrf24j40/app.config.test
Normal 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
|
1
tests/driver_mrf24j40/common.h
Symbolic link
1
tests/driver_mrf24j40/common.h
Symbolic link
@ -0,0 +1 @@
|
||||
../ieee802154_hal/common.h
|
1
tests/driver_mrf24j40/init_dev.c
Symbolic link
1
tests/driver_mrf24j40/init_dev.c
Symbolic link
@ -0,0 +1 @@
|
||||
../ieee802154_hal/init_devs.c
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
11
tests/ieee802154_hal/Makefile.ci
Normal file
11
tests/ieee802154_hal/Makefile.ci
Normal 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 \
|
||||
#
|
@ -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,
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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, ®);
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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(".");
|
||||
|
Loading…
Reference in New Issue
Block a user