net: ieee802154_radio: Allow to specify TX mode
Even though radio driver can report in its capabilities that it does support CSMA CA, there's no way in the driver to select how the frame should be transmitted (with CSMA or without). As layers above radio driver (Thread, Zigbee) can expect that both TX modes are available, we need to extend the API to allow either of these modes. This commits extends the API `tx` function with an extra parameter, `ieee802154_tx_mode`, which informs the driver how the packet should be transmitted. Currently, the following modes are specified: * direct (regular tx, no cca, just how it worked so far), * CCA before transmission, * CSMA CA before transmission, * delayed TX, * delayed TX with CCA Assume that radios that reported CSMA CA capability transmit in CSMA CA mode by default, all others will support direct mode. Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
This commit is contained in:
parent
9b627a4cea
commit
1fb418df4c
17 changed files with 94 additions and 17 deletions
|
@ -592,6 +592,7 @@ static int cc1200_set_txpower(struct device *dev, s16_t dbm)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cc1200_tx(struct device *dev,
|
static int cc1200_tx(struct device *dev,
|
||||||
|
enum ieee802154_tx_mode mode,
|
||||||
struct net_pkt *pkt,
|
struct net_pkt *pkt,
|
||||||
struct net_buf *frag)
|
struct net_buf *frag)
|
||||||
{
|
{
|
||||||
|
@ -600,6 +601,11 @@ static int cc1200_tx(struct device *dev,
|
||||||
u8_t len = frag->len;
|
u8_t len = frag->len;
|
||||||
bool status = false;
|
bool status = false;
|
||||||
|
|
||||||
|
if (mode != IEEE802154_TX_MODE_DIRECT) {
|
||||||
|
NET_ERR("TX mode %d not supported", mode);
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
LOG_DBG("%p (%u)", frag, len);
|
LOG_DBG("%p (%u)", frag, len);
|
||||||
|
|
||||||
/* ToDo:
|
/* ToDo:
|
||||||
|
|
|
@ -188,7 +188,9 @@ static int ieee802154_cc13xx_cc26xx_set_txpower(struct device *dev, s16_t dbm)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* See IEEE 802.15.4 section 6.2.5.1 and TRM section 25.5.4.3 */
|
/* See IEEE 802.15.4 section 6.2.5.1 and TRM section 25.5.4.3 */
|
||||||
static int ieee802154_cc13xx_cc26xx_tx(struct device *dev, struct net_pkt *pkt,
|
static int ieee802154_cc13xx_cc26xx_tx(struct device *dev,
|
||||||
|
enum ieee802154_tx_mode mode,
|
||||||
|
struct net_pkt *pkt,
|
||||||
struct net_buf *frag)
|
struct net_buf *frag)
|
||||||
{
|
{
|
||||||
struct ieee802154_cc13xx_cc26xx_data *drv_data = get_dev_data(dev);
|
struct ieee802154_cc13xx_cc26xx_data *drv_data = get_dev_data(dev);
|
||||||
|
@ -196,6 +198,11 @@ static int ieee802154_cc13xx_cc26xx_tx(struct device *dev, struct net_pkt *pkt,
|
||||||
int retry = CONFIG_NET_L2_IEEE802154_RADIO_TX_RETRIES;
|
int retry = CONFIG_NET_L2_IEEE802154_RADIO_TX_RETRIES;
|
||||||
u32_t status;
|
u32_t status;
|
||||||
|
|
||||||
|
if (mode != IEEE802154_TX_MODE_CSMA_CA) {
|
||||||
|
NET_ERR("TX mode %d not supported", mode);
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
drv_data->cmd_ieee_csma.status = IDLE;
|
drv_data->cmd_ieee_csma.status = IDLE;
|
||||||
drv_data->cmd_ieee_csma.randomState = sys_rand32_get();
|
drv_data->cmd_ieee_csma.randomState = sys_rand32_get();
|
||||||
|
|
||||||
|
|
|
@ -793,6 +793,7 @@ error:
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cc2520_tx(struct device *dev,
|
static int cc2520_tx(struct device *dev,
|
||||||
|
enum ieee802154_tx_mode mode,
|
||||||
struct net_pkt *pkt,
|
struct net_pkt *pkt,
|
||||||
struct net_buf *frag)
|
struct net_buf *frag)
|
||||||
{
|
{
|
||||||
|
@ -802,6 +803,11 @@ static int cc2520_tx(struct device *dev,
|
||||||
u8_t retry = 2U;
|
u8_t retry = 2U;
|
||||||
bool status;
|
bool status;
|
||||||
|
|
||||||
|
if (mode != IEEE802154_TX_MODE_DIRECT) {
|
||||||
|
NET_ERR("TX mode %d not supported", mode);
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
LOG_DBG("%p (%u)", frag, len);
|
LOG_DBG("%p (%u)", frag, len);
|
||||||
|
|
||||||
if (!write_reg_excflag0(cc2520, EXCFLAG0_RESET_TX_FLAGS) ||
|
if (!write_reg_excflag0(cc2520, EXCFLAG0_RESET_TX_FLAGS) ||
|
||||||
|
|
|
@ -612,8 +612,8 @@ out:
|
||||||
net_pkt_unref(ack_pkt);
|
net_pkt_unref(ack_pkt);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kw41z_tx(struct device *dev, struct net_pkt *pkt,
|
static int kw41z_tx(struct device *dev, enum ieee802154_tx_mode mode,
|
||||||
struct net_buf *frag)
|
struct net_pkt *pkt, struct net_buf *frag)
|
||||||
{
|
{
|
||||||
struct kw41z_context *kw41z = dev->driver_data;
|
struct kw41z_context *kw41z = dev->driver_data;
|
||||||
u8_t payload_len = frag->len;
|
u8_t payload_len = frag->len;
|
||||||
|
@ -621,6 +621,11 @@ static int kw41z_tx(struct device *dev, struct net_pkt *pkt,
|
||||||
u8_t xcvseq;
|
u8_t xcvseq;
|
||||||
int key;
|
int key;
|
||||||
|
|
||||||
|
if (mode != IEEE802154_TX_MODE_DIRECT) {
|
||||||
|
NET_ERR("TX mode %d not supported", mode);
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The transmit requests are preceded by the CCA request. On
|
* The transmit requests are preceded by the CCA request. On
|
||||||
* completion of the CCA the sequencer should be in the IDLE
|
* completion of the CCA the sequencer should be in the IDLE
|
||||||
|
|
|
@ -1082,6 +1082,7 @@ static inline bool write_txfifo_content(struct mcr20a_context *dev,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mcr20a_tx(struct device *dev,
|
static int mcr20a_tx(struct device *dev,
|
||||||
|
enum ieee802154_tx_mode mode,
|
||||||
struct net_pkt *pkt,
|
struct net_pkt *pkt,
|
||||||
struct net_buf *frag)
|
struct net_buf *frag)
|
||||||
{
|
{
|
||||||
|
@ -1090,6 +1091,11 @@ static int mcr20a_tx(struct device *dev,
|
||||||
MCR20A_XCVSEQ_TX;
|
MCR20A_XCVSEQ_TX;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
|
if (mode != IEEE802154_TX_MODE_DIRECT) {
|
||||||
|
NET_ERR("TX mode %d not supported", mode);
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
k_mutex_lock(&mcr20a->phy_mutex, K_FOREVER);
|
k_mutex_lock(&mcr20a->phy_mutex, K_FOREVER);
|
||||||
|
|
||||||
LOG_DBG("%p (%u)", frag, frag->len);
|
LOG_DBG("%p (%u)", frag, frag->len);
|
||||||
|
|
|
@ -322,6 +322,7 @@ free_nrf_ack:
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nrf5_tx(struct device *dev,
|
static int nrf5_tx(struct device *dev,
|
||||||
|
enum ieee802154_tx_mode mode,
|
||||||
struct net_pkt *pkt,
|
struct net_pkt *pkt,
|
||||||
struct net_buf *frag)
|
struct net_buf *frag)
|
||||||
{
|
{
|
||||||
|
@ -329,6 +330,11 @@ static int nrf5_tx(struct device *dev,
|
||||||
u8_t payload_len = frag->len;
|
u8_t payload_len = frag->len;
|
||||||
u8_t *payload = frag->data;
|
u8_t *payload = frag->data;
|
||||||
|
|
||||||
|
if (mode != IEEE802154_TX_MODE_DIRECT) {
|
||||||
|
NET_ERR("TX mode %d not supported", mode);
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
LOG_DBG("%p (%u)", payload, payload_len);
|
LOG_DBG("%p (%u)", payload, payload_len);
|
||||||
|
|
||||||
nrf5_radio->tx_psdu[0] = payload_len + NRF5_FCS_LENGTH;
|
nrf5_radio->tx_psdu[0] = payload_len + NRF5_FCS_LENGTH;
|
||||||
|
|
|
@ -473,6 +473,7 @@ static void rf2xx_handle_ack(struct rf2xx_context *ctx, struct net_buf *frag)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int rf2xx_tx(struct device *dev,
|
static int rf2xx_tx(struct device *dev,
|
||||||
|
enum ieee802154_tx_mode mode,
|
||||||
struct net_pkt *pkt,
|
struct net_pkt *pkt,
|
||||||
struct net_buf *frag)
|
struct net_buf *frag)
|
||||||
{
|
{
|
||||||
|
@ -481,6 +482,11 @@ static int rf2xx_tx(struct device *dev,
|
||||||
struct rf2xx_context *ctx = dev->driver_data;
|
struct rf2xx_context *ctx = dev->driver_data;
|
||||||
int response = 0;
|
int response = 0;
|
||||||
|
|
||||||
|
if (mode != IEEE802154_TX_MODE_CSMA_CA) {
|
||||||
|
NET_ERR("TX mode %d not supported", mode);
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
rf2xx_trx_set_tx_state(dev);
|
rf2xx_trx_set_tx_state(dev);
|
||||||
rf2xx_iface_reg_read(dev, RF2XX_IRQ_STATUS_REG);
|
rf2xx_iface_reg_read(dev, RF2XX_IRQ_STATUS_REG);
|
||||||
|
|
||||||
|
|
|
@ -266,6 +266,7 @@ static int upipe_set_txpower(struct device *dev, s16_t dbm)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int upipe_tx(struct device *dev,
|
static int upipe_tx(struct device *dev,
|
||||||
|
enum ieee802154_tx_mode mode,
|
||||||
struct net_pkt *pkt,
|
struct net_pkt *pkt,
|
||||||
struct net_buf *frag)
|
struct net_buf *frag)
|
||||||
{
|
{
|
||||||
|
@ -274,6 +275,11 @@ static int upipe_tx(struct device *dev,
|
||||||
u8_t len = frag->len;
|
u8_t len = frag->len;
|
||||||
u8_t i, data;
|
u8_t i, data;
|
||||||
|
|
||||||
|
if (mode != IEEE802154_TX_MODE_DIRECT) {
|
||||||
|
NET_ERR("TX mode %d not supported", mode);
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
LOG_DBG("%p (%u)", frag, len);
|
LOG_DBG("%p (%u)", frag, len);
|
||||||
|
|
||||||
if (upipe->stopped) {
|
if (upipe->stopped) {
|
||||||
|
|
|
@ -36,7 +36,8 @@ enum ieee802154_hw_caps {
|
||||||
IEEE802154_HW_2_4_GHZ = BIT(4), /* 2.4Ghz radio supported */
|
IEEE802154_HW_2_4_GHZ = BIT(4), /* 2.4Ghz radio supported */
|
||||||
IEEE802154_HW_TX_RX_ACK = BIT(5), /* Handles ACK request on TX */
|
IEEE802154_HW_TX_RX_ACK = BIT(5), /* Handles ACK request on TX */
|
||||||
IEEE802154_HW_SUB_GHZ = BIT(6), /* Sub-GHz radio supported */
|
IEEE802154_HW_SUB_GHZ = BIT(6), /* Sub-GHz radio supported */
|
||||||
IEEE802154_HW_ENERGY_SCAN = BIT(7) /* Energy scan supported */
|
IEEE802154_HW_ENERGY_SCAN = BIT(7), /* Energy scan supported */
|
||||||
|
IEEE802154_HW_TXTIME = BIT(8), /* TX at specified time supported */
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ieee802154_filter_type {
|
enum ieee802154_filter_type {
|
||||||
|
@ -57,6 +58,24 @@ struct ieee802154_filter {
|
||||||
/* @endcond */
|
/* @endcond */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** IEEE802.15.4 Transmission mode. */
|
||||||
|
enum ieee802154_tx_mode {
|
||||||
|
/** Transmit packet immediately, no CCA. */
|
||||||
|
IEEE802154_TX_MODE_DIRECT,
|
||||||
|
|
||||||
|
/** Perform CCA before packet transmission. */
|
||||||
|
IEEE802154_TX_MODE_CCA,
|
||||||
|
|
||||||
|
/** Perform full CSMA CA procedure before packet transmission. */
|
||||||
|
IEEE802154_TX_MODE_CSMA_CA,
|
||||||
|
|
||||||
|
/** Transmit packet in the future, at specified time, no CCA. */
|
||||||
|
IEEE802154_TX_MODE_TXTIME,
|
||||||
|
|
||||||
|
/** Transmit packet in the future, perform CCA before transmission. */
|
||||||
|
IEEE802154_TX_MODE_TXTIME_CCA,
|
||||||
|
};
|
||||||
|
|
||||||
/** IEEE802.15.4 driver configuration types. */
|
/** IEEE802.15.4 driver configuration types. */
|
||||||
enum ieee802154_config_type {
|
enum ieee802154_config_type {
|
||||||
/** Indicates how radio driver should set Frame Pending bit in ACK
|
/** Indicates how radio driver should set Frame Pending bit in ACK
|
||||||
|
@ -137,9 +156,8 @@ struct ieee802154_radio_api {
|
||||||
int (*set_txpower)(struct device *dev, s16_t dbm);
|
int (*set_txpower)(struct device *dev, s16_t dbm);
|
||||||
|
|
||||||
/** Transmit a packet fragment */
|
/** Transmit a packet fragment */
|
||||||
int (*tx)(struct device *dev,
|
int (*tx)(struct device *dev, enum ieee802154_tx_mode mode,
|
||||||
struct net_pkt *pkt,
|
struct net_pkt *pkt, struct net_buf *frag);
|
||||||
struct net_buf *frag);
|
|
||||||
|
|
||||||
/** Start the device */
|
/** Start the device */
|
||||||
int (*start)(struct device *dev);
|
int (*start)(struct device *dev);
|
||||||
|
|
|
@ -248,7 +248,8 @@ static void process_data(struct net_pkt *pkt)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Transmit data through radio */
|
/* Transmit data through radio */
|
||||||
ret = radio_api->tx(ieee802154_dev, pkt, buf);
|
ret = radio_api->tx(ieee802154_dev, IEEE802154_TX_MODE_DIRECT,
|
||||||
|
pkt, buf);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
LOG_ERR("Error transmit data");
|
LOG_ERR("Error transmit data");
|
||||||
}
|
}
|
||||||
|
|
|
@ -260,7 +260,8 @@ static int tx(struct net_pkt *pkt)
|
||||||
LOG_DBG("len %d seq %u", buf->len, seq);
|
LOG_DBG("len %d seq %u", buf->len, seq);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
ret = radio_api->tx(ieee802154_dev, pkt, buf);
|
ret = radio_api->tx(ieee802154_dev, IEEE802154_TX_MODE_DIRECT,
|
||||||
|
pkt, buf);
|
||||||
} while (ret && retries--);
|
} while (ret && retries--);
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
|
|
@ -81,7 +81,8 @@ static inline void ieee802154_acknowledge(struct net_if *iface,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ieee802154_create_ack_frame(iface, pkt, mpdu->mhr.fs->sequence)) {
|
if (ieee802154_create_ack_frame(iface, pkt, mpdu->mhr.fs->sequence)) {
|
||||||
ieee802154_tx(iface, pkt, pkt->buffer);
|
ieee802154_tx(iface, IEEE802154_TX_MODE_DIRECT,
|
||||||
|
pkt, pkt->buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
net_pkt_unref(pkt);
|
net_pkt_unref(pkt);
|
||||||
|
@ -276,7 +277,8 @@ static int ieee802154_send(struct net_if *iface, struct net_pkt *pkt)
|
||||||
if (IS_ENABLED(CONFIG_NET_L2_IEEE802154_RADIO_CSMA_CA) &&
|
if (IS_ENABLED(CONFIG_NET_L2_IEEE802154_RADIO_CSMA_CA) &&
|
||||||
ieee802154_get_hw_capabilities(iface) &
|
ieee802154_get_hw_capabilities(iface) &
|
||||||
IEEE802154_HW_CSMA) {
|
IEEE802154_HW_CSMA) {
|
||||||
ret = ieee802154_tx(iface, pkt, &frame_buf);
|
ret = ieee802154_tx(iface, IEEE802154_TX_MODE_CSMA_CA,
|
||||||
|
pkt, &frame_buf);
|
||||||
} else {
|
} else {
|
||||||
ret = ieee802154_radio_send(iface, pkt, &frame_buf);
|
ret = ieee802154_radio_send(iface, pkt, &frame_buf);
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,8 @@ static inline int aloha_radio_send(struct net_if *iface,
|
||||||
while (retries) {
|
while (retries) {
|
||||||
retries--;
|
retries--;
|
||||||
|
|
||||||
ret = ieee802154_tx(iface, pkt, frag);
|
ret = ieee802154_tx(iface, IEEE802154_TX_MODE_DIRECT,
|
||||||
|
pkt, frag);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,7 +57,8 @@ loop:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = ieee802154_tx(iface, pkt, frag);
|
ret = ieee802154_tx(iface, IEEE802154_TX_MODE_DIRECT,
|
||||||
|
pkt, frag);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,7 +64,9 @@ static inline int ieee802154_set_tx_power(struct net_if *iface, s16_t dbm)
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int ieee802154_tx(struct net_if *iface,
|
static inline int ieee802154_tx(struct net_if *iface,
|
||||||
struct net_pkt *pkt, struct net_buf *buf)
|
enum ieee802154_tx_mode mode,
|
||||||
|
struct net_pkt *pkt,
|
||||||
|
struct net_buf *buf)
|
||||||
{
|
{
|
||||||
const struct ieee802154_radio_api *radio =
|
const struct ieee802154_radio_api *radio =
|
||||||
net_if_get_device(iface)->driver_api;
|
net_if_get_device(iface)->driver_api;
|
||||||
|
@ -73,7 +75,7 @@ static inline int ieee802154_tx(struct net_if *iface,
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
return radio->tx(net_if_get_device(iface), pkt, buf);
|
return radio->tx(net_if_get_device(iface), mode, pkt, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int ieee802154_start(struct net_if *iface)
|
static inline int ieee802154_start(struct net_if *iface)
|
||||||
|
|
|
@ -190,11 +190,13 @@ void platformRadioProcess(otInstance *aInstance)
|
||||||
|
|
||||||
if (sTransmitFrame.mInfo.mTxInfo.mCsmaCaEnabled) {
|
if (sTransmitFrame.mInfo.mTxInfo.mCsmaCaEnabled) {
|
||||||
if (radio_api->cca(radio_dev) ||
|
if (radio_api->cca(radio_dev) ||
|
||||||
radio_api->tx(radio_dev, tx_pkt, tx_payload)) {
|
radio_api->tx(radio_dev, IEEE802154_TX_MODE_DIRECT,
|
||||||
|
tx_pkt, tx_payload)) {
|
||||||
result = OT_ERROR_CHANNEL_ACCESS_FAILURE;
|
result = OT_ERROR_CHANNEL_ACCESS_FAILURE;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (radio_api->tx(radio_dev, tx_pkt, tx_payload)) {
|
if (radio_api->tx(radio_dev, IEEE802154_TX_MODE_DIRECT,
|
||||||
|
tx_pkt, tx_payload)) {
|
||||||
result = OT_ERROR_CHANNEL_ACCESS_FAILURE;
|
result = OT_ERROR_CHANNEL_ACCESS_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,6 +60,7 @@ static inline void insert_frag(struct net_pkt *pkt, struct net_buf *frag)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fake_tx(struct device *dev,
|
static int fake_tx(struct device *dev,
|
||||||
|
enum ieee802154_tx_mode mode,
|
||||||
struct net_pkt *pkt,
|
struct net_pkt *pkt,
|
||||||
struct net_buf *frag)
|
struct net_buf *frag)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue