diff --git a/boards/common/nucleo64/include/board.h b/boards/common/nucleo64/include/board.h index f19f3e3ee6..7aedd553e6 100644 --- a/boards/common/nucleo64/include/board.h +++ b/boards/common/nucleo64/include/board.h @@ -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 diff --git a/core/lib/include/bitarithm.h b/core/lib/include/bitarithm.h index fece5ae8c2..f02cfcc51d 100644 --- a/core/lib/include/bitarithm.h +++ b/core/lib/include/bitarithm.h @@ -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 */ diff --git a/cpu/atmega128rfa1/Kconfig b/cpu/atmega128rfa1/Kconfig index c7f8d5eea1..ef5f54399a 100644 --- a/cpu/atmega128rfa1/Kconfig +++ b/cpu/atmega128rfa1/Kconfig @@ -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 diff --git a/cpu/atmega256rfr2/Kconfig b/cpu/atmega256rfr2/Kconfig index 6b7fa25632..2f1ebe61d1 100644 --- a/cpu/atmega256rfr2/Kconfig +++ b/cpu/atmega256rfr2/Kconfig @@ -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 diff --git a/dist/tools/doccheck/exclude_patterns b/dist/tools/doccheck/exclude_patterns index 3d855356f7..5dab3a8853 100644 --- a/dist/tools/doccheck/exclude_patterns +++ b/dist/tools/doccheck/exclude_patterns @@ -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\. diff --git a/drivers/Makefile.dep b/drivers/Makefile.dep index a190ffeb82..421f98adad 100644 --- a/drivers/Makefile.dep +++ b/drivers/Makefile.dep @@ -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))) diff --git a/drivers/include/mrf24j40.h b/drivers/include/mrf24j40.h index 9eb9358b5a..87ab8d335f 100644 --- a/drivers/include/mrf24j40.h +++ b/drivers/include/mrf24j40.h @@ -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 diff --git a/drivers/mrf24j40/Kconfig b/drivers/mrf24j40/Kconfig index d6da36cfa3..c818218a2d 100644 --- a/drivers/mrf24j40/Kconfig +++ b/drivers/mrf24j40/Kconfig @@ -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 diff --git a/drivers/mrf24j40/Makefile.dep b/drivers/mrf24j40/Makefile.dep index 4035b1963c..6133165947 100644 --- a/drivers/mrf24j40/Makefile.dep +++ b/drivers/mrf24j40/Makefile.dep @@ -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 diff --git a/drivers/mrf24j40/include/mrf24j40_internal.h b/drivers/mrf24j40/include/mrf24j40_internal.h index 81bc299e3c..c022209ef2 100644 --- a/drivers/mrf24j40/include/mrf24j40_internal.h +++ b/drivers/mrf24j40/include/mrf24j40_internal.h @@ -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 diff --git a/drivers/mrf24j40/include/mrf24j40_registers.h b/drivers/mrf24j40/include/mrf24j40_registers.h index 4f750bb548..b677b628a4 100644 --- a/drivers/mrf24j40/include/mrf24j40_registers.h +++ b/drivers/mrf24j40/include/mrf24j40_registers.h @@ -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) * @{ diff --git a/drivers/mrf24j40/mrf24j40.c b/drivers/mrf24j40/mrf24j40.c index 5ff6d55de8..cef2e517d4 100644 --- a/drivers/mrf24j40/mrf24j40.c +++ b/drivers/mrf24j40/mrf24j40.c @@ -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); - } -} diff --git a/drivers/mrf24j40/mrf24j40_getset.c b/drivers/mrf24j40/mrf24j40_getset.c index b890be2512..1a3d904513 100644 --- a/drivers/mrf24j40/mrf24j40_getset.c +++ b/drivers/mrf24j40/mrf24j40_getset.c @@ -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) diff --git a/drivers/mrf24j40/mrf24j40_internal.c b/drivers/mrf24j40/mrf24j40_internal.c index e3eec52332..f8bfbf5f52 100644 --- a/drivers/mrf24j40/mrf24j40_internal.c +++ b/drivers/mrf24j40/mrf24j40_internal.c @@ -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); } diff --git a/drivers/mrf24j40/mrf24j40_netdev.c b/drivers/mrf24j40/mrf24j40_netdev.c deleted file mode 100644 index e11fa4064f..0000000000 --- a/drivers/mrf24j40/mrf24j40_netdev.c +++ /dev/null @@ -1,581 +0,0 @@ -/* - * Copyright (C) 2017 Neo Nenaco - * Copyright (C) 2017 Koen Zandberg - * - * 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 - * @author Neo Nenaco - * - * @} - */ - -#include -#include -#include - -#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, -}; diff --git a/drivers/mrf24j40/mrf24j40_radio_hal.c b/drivers/mrf24j40/mrf24j40_radio_hal.c new file mode 100644 index 0000000000..765d23a429 --- /dev/null +++ b/drivers/mrf24j40/mrf24j40_radio_hal.c @@ -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, +}; diff --git a/drivers/periph_common/flashpage.c b/drivers/periph_common/flashpage.c index 4ccb422972..23d66d4d77 100644 --- a/drivers/periph_common/flashpage.c +++ b/drivers/periph_common/flashpage.c @@ -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 diff --git a/pkg/lwip/init_devs/auto_init_mrf24j40.c b/pkg/lwip/init_devs/auto_init_mrf24j40.c index 1fb59decad..7fcc646df1 100644 --- a/pkg/lwip/init_devs/auto_init_mrf24j40.c +++ b/pkg/lwip/init_devs/auto_init_mrf24j40.c @@ -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; } diff --git a/sys/include/net/ieee802154/radio.h b/sys/include/net/ieee802154/radio.h index c15eb3ada2..c8f71afa90 100644 --- a/sys/include/net/ieee802154/radio.h +++ b/sys/include/net/ieee802154/radio.h @@ -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; } /** diff --git a/sys/net/gnrc/netif/init_devs/auto_init_mrf24j40.c b/sys/net/gnrc/netif/init_devs/auto_init_mrf24j40.c index adb3910501..862130fc47 100644 --- a/sys/net/gnrc/netif/init_devs/auto_init_mrf24j40.c +++ b/sys/net/gnrc/netif/init_devs/auto_init_mrf24j40.c @@ -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); } } /** @} */ diff --git a/sys/net/link_layer/ieee802154/Kconfig b/sys/net/link_layer/ieee802154/Kconfig index dd2c4a37c3..ab29071285 100644 --- a/sys/net/link_layer/ieee802154/Kconfig +++ b/sys/net/link_layer/ieee802154/Kconfig @@ -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. diff --git a/sys/test_utils/Kconfig b/sys/test_utils/Kconfig index 251cc46476..72bf1e6e40 100644 --- a/sys/test_utils/Kconfig +++ b/sys/test_utils/Kconfig @@ -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 diff --git a/sys/test_utils/netdev_ieee802154_minimal/Kconfig b/sys/test_utils/netdev_ieee802154_minimal/Kconfig new file mode 100644 index 0000000000..1ee15aa297 --- /dev/null +++ b/sys/test_utils/netdev_ieee802154_minimal/Kconfig @@ -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 diff --git a/tests/driver_mrf24j40/Kconfig b/tests/driver_mrf24j40/Kconfig new file mode 100644 index 0000000000..b5b170263a --- /dev/null +++ b/tests/driver_mrf24j40/Kconfig @@ -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 diff --git a/tests/driver_mrf24j40/Makefile b/tests/driver_mrf24j40/Makefile index 92ef43837d..c153ec487f 100644 --- a/tests/driver_mrf24j40/Makefile +++ b/tests/driver_mrf24j40/Makefile @@ -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 diff --git a/tests/driver_mrf24j40/app.config.test b/tests/driver_mrf24j40/app.config.test new file mode 100644 index 0000000000..bcc446eee5 --- /dev/null +++ b/tests/driver_mrf24j40/app.config.test @@ -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 diff --git a/tests/driver_mrf24j40/common.h b/tests/driver_mrf24j40/common.h new file mode 120000 index 0000000000..e95bd2d8c6 --- /dev/null +++ b/tests/driver_mrf24j40/common.h @@ -0,0 +1 @@ +../ieee802154_hal/common.h \ No newline at end of file diff --git a/tests/driver_mrf24j40/init_dev.c b/tests/driver_mrf24j40/init_dev.c new file mode 120000 index 0000000000..ddf5f5ff33 --- /dev/null +++ b/tests/driver_mrf24j40/init_dev.c @@ -0,0 +1 @@ +../ieee802154_hal/init_devs.c \ No newline at end of file diff --git a/tests/driver_mrf24j40/main.c b/tests/driver_mrf24j40/main.c index 1a0b3ea887..9783083ceb 100644 --- a/tests/driver_mrf24j40/main.c +++ b/tests/driver_mrf24j40/main.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; } diff --git a/tests/ieee802154_hal/Makefile b/tests/ieee802154_hal/Makefile index 3253c8fde1..7cb7cb8c24 100644 --- a/tests/ieee802154_hal/Makefile +++ b/tests/ieee802154_hal/Makefile @@ -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 diff --git a/tests/ieee802154_hal/Makefile.ci b/tests/ieee802154_hal/Makefile.ci new file mode 100644 index 0000000000..d220123487 --- /dev/null +++ b/tests/ieee802154_hal/Makefile.ci @@ -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 \ + # diff --git a/tests/ieee802154_hal/common.h b/tests/ieee802154_hal/common.h index 4b30dc5d46..e2ce68d3ed 100644 --- a/tests/ieee802154_hal/common.h +++ b/tests/ieee802154_hal/common.h @@ -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, diff --git a/tests/ieee802154_hal/init_devs.c b/tests/ieee802154_hal/init_devs.c index eeb838629e..acb44862bd 100644 --- a/tests/ieee802154_hal/init_devs.c +++ b/tests/ieee802154_hal/init_devs.c @@ -18,6 +18,7 @@ * @} */ +#include #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 } diff --git a/tests/ieee802154_hal/main.c b/tests/ieee802154_hal/main.c index accbc682ee..ab382e3db9 100644 --- a/tests/ieee802154_hal/main.c +++ b/tests/ieee802154_hal/main.c @@ -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; } diff --git a/tests/ieee802154_submac/Makefile b/tests/ieee802154_submac/Makefile index a213e7ac75..8f4b22467a 100644 --- a/tests/ieee802154_submac/Makefile +++ b/tests/ieee802154_submac/Makefile @@ -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 diff --git a/tests/ieee802154_submac/main.c b/tests/ieee802154_submac/main.c index 595d3c3746..212e387168 100644 --- a/tests/ieee802154_submac/main.c +++ b/tests/ieee802154_submac/main.c @@ -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(".");