drivers: ieee802154: rf2xx: Add support to Sub-Giga
Add support to at86rf212[b] sub-giga devices. This work enables use of pages 0, 2 and 5 in accordance with IEEE-802.15.4/2003/2006/2011. The proprietary speeds can be object of future work. Note: It is recommended that user define a power table for better performance, low emissions and to save power. A reference power table can be found in the datasheet and should be used for tests only and not on a final product. Signed-off-by: Gerson Fernando Budke <nandojve@gmail.com>
This commit is contained in:
parent
65960c4d32
commit
6d5cdc17b4
|
@ -134,6 +134,26 @@ static void rf2xx_trx_set_rx_state(const struct device *dev)
|
|||
rf2xx_trx_set_state(dev, RF2XX_TRX_PHY_STATE_CMD_RX_AACK_ON);
|
||||
}
|
||||
|
||||
static void rf2xx_set_rssi_base(const struct device *dev, uint16_t channel)
|
||||
{
|
||||
struct rf2xx_context *ctx = dev->data;
|
||||
int8_t base;
|
||||
|
||||
if (ctx->cc_page == RF2XX_TRX_CC_PAGE_0) {
|
||||
base = channel == 0
|
||||
? RF2XX_RSSI_BPSK_20
|
||||
: RF2XX_RSSI_BPSK_40;
|
||||
} else if (ctx->cc_page == RF2XX_TRX_CC_PAGE_2) {
|
||||
base = channel == 0
|
||||
? RF2XX_RSSI_OQPSK_SIN_RC_100
|
||||
: RF2XX_RSSI_OQPSK_SIN_250;
|
||||
} else {
|
||||
base = RF2XX_RSSI_OQPSK_RC_250;
|
||||
}
|
||||
|
||||
ctx->trx_rssi_base = base;
|
||||
}
|
||||
|
||||
static void rf2xx_trx_rx(const struct device *dev)
|
||||
{
|
||||
struct rf2xx_context *ctx = dev->data;
|
||||
|
@ -334,30 +354,99 @@ static inline uint8_t *get_mac(const struct device *dev)
|
|||
|
||||
static enum ieee802154_hw_caps rf2xx_get_capabilities(const struct device *dev)
|
||||
{
|
||||
ARG_UNUSED(dev);
|
||||
struct rf2xx_context *ctx = dev->data;
|
||||
|
||||
LOG_DBG("HW Caps");
|
||||
|
||||
return IEEE802154_HW_FCS |
|
||||
IEEE802154_HW_PROMISC |
|
||||
IEEE802154_HW_FILTER |
|
||||
IEEE802154_HW_CSMA |
|
||||
IEEE802154_HW_TX_RX_ACK |
|
||||
IEEE802154_HW_2_4_GHZ;
|
||||
(ctx->trx_model == RF2XX_TRX_MODEL_212
|
||||
? IEEE802154_HW_SUB_GHZ
|
||||
: IEEE802154_HW_2_4_GHZ);
|
||||
}
|
||||
|
||||
static int rf2xx_configure_sub_channel(const struct device *dev, uint16_t channel)
|
||||
{
|
||||
struct rf2xx_context *ctx = dev->data;
|
||||
uint8_t reg;
|
||||
uint8_t cc_mask;
|
||||
|
||||
if (ctx->cc_page == RF2XX_TRX_CC_PAGE_0) {
|
||||
cc_mask = channel == 0
|
||||
? RF2XX_CC_BPSK_20
|
||||
: RF2XX_CC_BPSK_40;
|
||||
} else if (ctx->cc_page == RF2XX_TRX_CC_PAGE_2) {
|
||||
cc_mask = channel == 0
|
||||
? RF2XX_CC_OQPSK_SIN_RC_100
|
||||
: RF2XX_CC_OQPSK_SIN_250;
|
||||
} else {
|
||||
cc_mask = RF2XX_CC_OQPSK_RC_250;
|
||||
}
|
||||
|
||||
reg = rf2xx_iface_reg_read(dev, RF2XX_TRX_CTRL_2_REG)
|
||||
& ~RF2XX_SUB_CHANNEL_MASK;
|
||||
rf2xx_iface_reg_write(dev, RF2XX_TRX_CTRL_2_REG, reg | cc_mask);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int rf2xx_configure_trx_path(const struct device *dev)
|
||||
{
|
||||
struct rf2xx_context *ctx = dev->data;
|
||||
uint8_t reg;
|
||||
uint8_t gc_tx_offset;
|
||||
|
||||
if (ctx->cc_page == RF2XX_TRX_CC_PAGE_0) {
|
||||
gc_tx_offset = 0x03;
|
||||
} else {
|
||||
gc_tx_offset = 0x02;
|
||||
}
|
||||
|
||||
reg = rf2xx_iface_reg_read(dev, RF2XX_RF_CTRL_0_REG)
|
||||
& ~RF2XX_GC_TX_OFFS_MASK;
|
||||
rf2xx_iface_reg_write(dev, RF2XX_RF_CTRL_0_REG, reg | gc_tx_offset);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rf2xx_cca(const struct device *dev)
|
||||
{
|
||||
ARG_UNUSED(dev);
|
||||
|
||||
LOG_DBG("CCA");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rf2xx_set_channel(const struct device *dev, uint16_t channel)
|
||||
{
|
||||
struct rf2xx_context *ctx = dev->data;
|
||||
uint8_t reg;
|
||||
|
||||
if (channel < 11 || channel > 26) {
|
||||
LOG_ERR("Unsupported channel %u", channel);
|
||||
return -EINVAL;
|
||||
LOG_DBG("Set Channel %d", channel);
|
||||
|
||||
if (ctx->trx_model == RF2XX_TRX_MODEL_212) {
|
||||
if ((ctx->cc_page == RF2XX_TRX_CC_PAGE_0
|
||||
&& ctx->cc_page == RF2XX_TRX_CC_PAGE_2)
|
||||
&& channel > 10) {
|
||||
LOG_ERR("Unsupported channel %u", channel);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (ctx->cc_page == RF2XX_TRX_CC_PAGE_5 && channel > 3) {
|
||||
LOG_ERR("Unsupported channel %u", channel);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rf2xx_configure_sub_channel(dev, channel);
|
||||
rf2xx_configure_trx_path(dev);
|
||||
rf2xx_set_rssi_base(dev, channel);
|
||||
} else {
|
||||
if (channel < 11 || channel > 26) {
|
||||
LOG_ERR("Unsupported channel %u", channel);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
reg = rf2xx_iface_reg_read(dev, RF2XX_PHY_CC_CCA_REG) & ~0x1f;
|
||||
|
@ -555,6 +644,8 @@ static int rf2xx_tx(const struct device *dev,
|
|||
struct rf2xx_context *ctx = dev->data;
|
||||
int response = 0;
|
||||
|
||||
LOG_DBG("TX");
|
||||
|
||||
if (ctx->tx_mode != mode) {
|
||||
switch (mode) {
|
||||
case IEEE802154_TX_MODE_DIRECT:
|
||||
|
@ -629,6 +720,8 @@ static int rf2xx_start(const struct device *dev)
|
|||
{
|
||||
const struct rf2xx_config *conf = dev->config;
|
||||
|
||||
LOG_DBG("Start");
|
||||
|
||||
rf2xx_trx_set_state(dev, RF2XX_TRX_PHY_STATE_CMD_TRX_OFF);
|
||||
rf2xx_iface_reg_read(dev, RF2XX_IRQ_STATUS_REG);
|
||||
gpio_pin_interrupt_configure_dt(&conf->irq_gpio,
|
||||
|
@ -642,6 +735,8 @@ static int rf2xx_stop(const struct device *dev)
|
|||
{
|
||||
const struct rf2xx_config *conf = dev->config;
|
||||
|
||||
LOG_DBG("Stop");
|
||||
|
||||
gpio_pin_interrupt_configure_dt(&conf->irq_gpio, GPIO_INT_DISABLE);
|
||||
rf2xx_trx_set_state(dev, RF2XX_TRX_PHY_STATE_CMD_TRX_OFF);
|
||||
rf2xx_iface_reg_read(dev, RF2XX_IRQ_STATUS_REG);
|
||||
|
@ -697,6 +792,8 @@ int rf2xx_configure(const struct device *dev,
|
|||
{
|
||||
int ret = -EINVAL;
|
||||
|
||||
LOG_DBG("Configure %d", type);
|
||||
|
||||
switch (type) {
|
||||
case IEEE802154_CONFIG_AUTO_ACK_FPB:
|
||||
case IEEE802154_CONFIG_ACK_FPB:
|
||||
|
@ -718,6 +815,13 @@ int rf2xx_configure(const struct device *dev,
|
|||
return ret;
|
||||
}
|
||||
|
||||
uint16_t rf2xx_get_subgiga_channel_count(const struct device *dev)
|
||||
{
|
||||
struct rf2xx_context *ctx = dev->data;
|
||||
|
||||
return ctx->cc_page == RF2XX_TRX_CC_PAGE_5 ? 4 : 11;
|
||||
}
|
||||
|
||||
static int power_on_and_setup(const struct device *dev)
|
||||
{
|
||||
const struct rf2xx_config *conf = dev->config;
|
||||
|
@ -745,19 +849,19 @@ static int power_on_and_setup(const struct device *dev)
|
|||
* 233-Rev-A (Version 0x01) (Warning)
|
||||
* 233-Rev-B (Version 0x02)
|
||||
*/
|
||||
if (ctx->trx_model != RF2XX_TRX_MODEL_231 &&
|
||||
ctx->trx_model != RF2XX_TRX_MODEL_232 &&
|
||||
ctx->trx_model != RF2XX_TRX_MODEL_233) {
|
||||
if (ctx->trx_model <= RF2XX_TRX_MODEL_230) {
|
||||
LOG_DBG("Invalid or not supported transceiver");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (ctx->trx_version < 0x02) {
|
||||
if (ctx->trx_model == RF2XX_TRX_MODEL_233 && ctx->trx_version == 0x01) {
|
||||
LOG_DBG("Transceiver is old and unstable release");
|
||||
}
|
||||
|
||||
/* Set RSSI base */
|
||||
if (ctx->trx_model == RF2XX_TRX_MODEL_233) {
|
||||
if (ctx->trx_model == RF2XX_TRX_MODEL_212) {
|
||||
ctx->trx_rssi_base = -100;
|
||||
} else if (ctx->trx_model == RF2XX_TRX_MODEL_233) {
|
||||
ctx->trx_rssi_base = -94;
|
||||
} else if (ctx->trx_model == RF2XX_TRX_MODEL_231) {
|
||||
ctx->trx_rssi_base = -91;
|
||||
|
@ -765,6 +869,10 @@ static int power_on_and_setup(const struct device *dev)
|
|||
ctx->trx_rssi_base = -90;
|
||||
}
|
||||
|
||||
/* Disable All Features of TRX_CTRL_0 */
|
||||
config = 0;
|
||||
rf2xx_iface_reg_write(dev, RF2XX_TRX_CTRL_0_REG, config);
|
||||
|
||||
/* Configure PHY behaviour */
|
||||
config = (1 << RF2XX_TX_AUTO_CRC_ON) |
|
||||
(3 << RF2XX_SPI_CMD_MODE) |
|
||||
|
@ -777,6 +885,11 @@ static int power_on_and_setup(const struct device *dev)
|
|||
}
|
||||
rf2xx_iface_reg_write(dev, RF2XX_TRX_CTRL_2_REG, config);
|
||||
|
||||
if (ctx->trx_model == RF2XX_TRX_MODEL_212) {
|
||||
rf2xx_configure_trx_path(dev);
|
||||
rf2xx_iface_reg_write(dev, RF2XX_CC_CTRL_1_REG, 0);
|
||||
}
|
||||
|
||||
ctx->tx_mode = IEEE802154_TX_MODE_CSMA_CA;
|
||||
|
||||
/* Configure INT behaviour */
|
||||
|
@ -784,7 +897,8 @@ static int power_on_and_setup(const struct device *dev)
|
|||
(1 << RF2XX_TRX_END);
|
||||
rf2xx_iface_reg_write(dev, RF2XX_IRQ_MASK_REG, config);
|
||||
|
||||
gpio_init_callback(&ctx->irq_cb, trx_isr_handler, BIT(conf->irq_gpio.pin));
|
||||
gpio_init_callback(&ctx->irq_cb, trx_isr_handler,
|
||||
BIT(conf->irq_gpio.pin));
|
||||
gpio_add_callback(conf->irq_gpio.port, &ctx->irq_cb);
|
||||
|
||||
return 0;
|
||||
|
@ -887,6 +1001,8 @@ static int rf2xx_init(const struct device *dev)
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
LOG_DBG("RADIO configured");
|
||||
|
||||
k_thread_create(&ctx->trx_thread,
|
||||
ctx->trx_stack,
|
||||
CONFIG_IEEE802154_RF2XX_RX_STACK_SIZE,
|
||||
|
@ -898,6 +1014,8 @@ static int rf2xx_init(const struct device *dev)
|
|||
"rf2xx_trx [%d]", conf->inst);
|
||||
k_thread_name_set(&ctx->trx_thread, thread_name);
|
||||
|
||||
LOG_DBG("Thread OK");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -915,17 +1033,18 @@ static void rf2xx_iface_init(struct net_if *iface)
|
|||
}
|
||||
|
||||
static struct ieee802154_radio_api rf2xx_radio_api = {
|
||||
.iface_api.init = rf2xx_iface_init,
|
||||
.iface_api.init = rf2xx_iface_init,
|
||||
|
||||
.get_capabilities = rf2xx_get_capabilities,
|
||||
.cca = rf2xx_cca,
|
||||
.set_channel = rf2xx_set_channel,
|
||||
.filter = rf2xx_filter,
|
||||
.set_txpower = rf2xx_set_txpower,
|
||||
.tx = rf2xx_tx,
|
||||
.start = rf2xx_start,
|
||||
.stop = rf2xx_stop,
|
||||
.configure = rf2xx_configure,
|
||||
.get_capabilities = rf2xx_get_capabilities,
|
||||
.cca = rf2xx_cca,
|
||||
.set_channel = rf2xx_set_channel,
|
||||
.filter = rf2xx_filter,
|
||||
.set_txpower = rf2xx_set_txpower,
|
||||
.tx = rf2xx_tx,
|
||||
.start = rf2xx_start,
|
||||
.stop = rf2xx_stop,
|
||||
.configure = rf2xx_configure,
|
||||
.get_subg_channel_count = rf2xx_get_subgiga_channel_count,
|
||||
};
|
||||
|
||||
#if !defined(CONFIG_IEEE802154_RAW_MODE)
|
||||
|
@ -973,7 +1092,8 @@ static struct ieee802154_radio_api rf2xx_radio_api = {
|
|||
|
||||
#define IEEE802154_RF2XX_DEVICE_DATA(n) \
|
||||
static struct rf2xx_context rf2xx_ctx_data_##n = { \
|
||||
.mac_addr = DRV_INST_LOCAL_MAC_ADDRESS(n) \
|
||||
.mac_addr = { DRV_INST_LOCAL_MAC_ADDRESS(n) }, \
|
||||
.cc_page = DT_INST_ENUM_IDX_OR(n, channel_page, 0), \
|
||||
}
|
||||
|
||||
#define IEEE802154_RF2XX_RAW_DEVICE_INIT(n) \
|
||||
|
|
|
@ -74,6 +74,12 @@ enum rf2xx_trx_model_t {
|
|||
RF2XX_TRX_MODEL_233 = 0x0B,
|
||||
};
|
||||
|
||||
enum rf2xx_trx_channel_page_t {
|
||||
RF2XX_TRX_CC_PAGE_0 = 0x00,
|
||||
RF2XX_TRX_CC_PAGE_2 = 0x02,
|
||||
RF2XX_TRX_CC_PAGE_5 = 0x05,
|
||||
};
|
||||
|
||||
struct rf2xx_config {
|
||||
struct gpio_dt_spec irq_gpio;
|
||||
struct gpio_dt_spec reset_gpio;
|
||||
|
@ -106,6 +112,7 @@ struct rf2xx_context {
|
|||
struct k_sem trx_tx_sync;
|
||||
|
||||
enum rf2xx_trx_model_t trx_model;
|
||||
enum rf2xx_trx_channel_page_t cc_page;
|
||||
enum rf2xx_trx_state_trac_t trx_trac;
|
||||
|
||||
enum ieee802154_tx_mode tx_mode;
|
||||
|
|
|
@ -24,6 +24,12 @@
|
|||
#define RF2XX_MAX_PSDU_LENGTH 127
|
||||
#define RX2XX_MAX_FRAME_SIZE 132
|
||||
|
||||
#define RF2XX_RSSI_BPSK_20 -100
|
||||
#define RF2XX_RSSI_BPSK_40 -99
|
||||
#define RF2XX_RSSI_OQPSK_SIN_RC_100 -98
|
||||
#define RF2XX_RSSI_OQPSK_SIN_250 -97
|
||||
#define RF2XX_RSSI_OQPSK_RC_250 -97
|
||||
|
||||
/*- Types ------------------------------------------------------------------*/
|
||||
#define RF2XX_TRX_STATUS_REG 0x01
|
||||
#define RF2XX_TRX_STATE_REG 0x02
|
||||
|
@ -148,6 +154,12 @@
|
|||
#define RF2XX_BPSK_OQPSK 3
|
||||
#define RF2XX_SUB_MODE 2
|
||||
#define RF2XX_OQPSK_DATA_RATE 0
|
||||
#define RF2XX_SUB_CHANNEL_MASK 0x3F
|
||||
#define RF2XX_CC_BPSK_20 0x00
|
||||
#define RF2XX_CC_BPSK_40 0x04
|
||||
#define RF2XX_CC_OQPSK_SIN_RC_100 0x08
|
||||
#define RF2XX_CC_OQPSK_SIN_250 0x0C
|
||||
#define RF2XX_CC_OQPSK_RC_250 0x1C
|
||||
|
||||
/* ANT_DIV */
|
||||
#define RF2XX_ANT_SEL 7
|
||||
|
@ -201,6 +213,7 @@
|
|||
#define RF2XX_PA_CHIP_LT 6
|
||||
#define RF2XX_F_SHIFT_MODE 2
|
||||
#define RF2XX_GC_TX_OFFS 0
|
||||
#define RF2XX_GC_TX_OFFS_MASK 3
|
||||
|
||||
/* XAH_CTRL_1 */
|
||||
#define RF2XX_ARET_TX_TS_EN 7
|
||||
|
|
|
@ -39,6 +39,23 @@ properties:
|
|||
Specifies the MAC address that was assigned to the network
|
||||
device
|
||||
|
||||
channel-page:
|
||||
type: int
|
||||
enum:
|
||||
- 0
|
||||
- 2
|
||||
- 5
|
||||
description: |
|
||||
Selects Channel Page accordingly with IEEE 802.15.4 standard. The Page 0
|
||||
is used in both Sub-Giga and 2.4GHz. It allows select channels 0-10 in
|
||||
Sub-Giga band (0: BPSK-20, 1-10: BPSK-40) and 11-26 in 2.4GHz band
|
||||
(11-26: O-QPSK-250). Channel 2 is for Sub-Giga and selects
|
||||
(0: OQPSK-SIN-RC-100, 1-10: OQPSK-SIN-250). Channel 5 is for Sub-Giga
|
||||
(JAPAN) and selects (0-3: OQPSK-RC-250) .
|
||||
0: Page 0 - BPSK-20 [0], BPSK-40 [1-10], O-QPSK-250 [11-26].
|
||||
2: Page 2 - OQPSK-SIN-RC-100 [0], OQPSK-SIN-250 [1-10].
|
||||
5: Page 5 - OQPSK-RC-250 [0-3].
|
||||
|
||||
tx-pwr-table:
|
||||
type: uint8-array
|
||||
default: [ 0x00 ]
|
||||
|
|
Loading…
Reference in a new issue