Skip to content

Commit

Permalink
drivers: ieee802154: cc13/26xx_subg: improve CSMA/CA compliance
Browse files Browse the repository at this point in the history
Switch the driver to the soft CSMA/CA algorithm as an intermediate
compromise for improved standard compliance (namely expontential
backoff) until true hardware support can be implemented by chaining
radio commands.

Signed-off-by: Florian Grandel <fgrandel@code-for-humans.de>
  • Loading branch information
fgrandel committed Jun 2, 2023
1 parent e84af17 commit 78c47d6
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 60 deletions.
9 changes: 3 additions & 6 deletions drivers/ieee802154/Kconfig.cc13xx_cc26xx
Expand Up @@ -90,13 +90,10 @@ config IEEE802154_CC13XX_CC26XX_SUB_GHZ_INIT_PRIO
Set the initialization priority number.

config IEEE802154_CC13XX_CC26XX_SUB_GHZ_RADIO_TX_RETRIES
int "Radio Transmission attempts"
default NET_L2_IEEE802154_RADIO_TX_RETRIES if NET_L2_IEEE802154
default 3
range 1 7
bool
select DEPRECATED
help
Number of transmission attempts radio driver should do, before
replying it could not send the packet.
DEPRECATED - use NET_L2_IEEE802154_RADIO_TX_RETRIES instead

config IEEE802154_CC13XX_CC26XX_SUB_GHZ_CUSTOM_RADIO_SETUP
bool "Use custom radio setup structures (advanced)"
Expand Down
74 changes: 20 additions & 54 deletions drivers/ieee802154/ieee802154_cc13xx_cc26xx_subg.c
Expand Up @@ -358,9 +358,7 @@ static enum ieee802154_hw_caps
ieee802154_cc13xx_cc26xx_subg_get_capabilities(const struct device *dev)
{
/* TODO: enable IEEE802154_HW_FILTER */
/* TODO: remove or actually implement IEEE802154_HW_CSMA */
return IEEE802154_HW_FCS | IEEE802154_HW_CSMA
| IEEE802154_HW_SUB_GHZ;
return IEEE802154_HW_FCS | IEEE802154_HW_SUB_GHZ;
}

static int ieee802154_cc13xx_cc26xx_subg_cca(const struct device *dev)
Expand Down Expand Up @@ -509,13 +507,12 @@ static int ieee802154_cc13xx_cc26xx_subg_tx(const struct device *dev,
struct net_buf *buf)
{
struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data;
int retry = CONFIG_IEEE802154_CC13XX_CC26XX_SUB_GHZ_RADIO_TX_RETRIES;
RF_EventMask events;
int ret;

if (mode != IEEE802154_TX_MODE_CSMA_CA) {
NET_ERR("TX mode %d not supported", mode);
return -ENOTSUP;
if (mode != IEEE802154_TX_MODE_DIRECT) {
/* For backwards compatibility we only log an error but do not bail. */
NET_ERR("TX mode %d not supported - sending directly instead.", mode);
}

k_mutex_lock(&drv_data->tx_mutex, K_FOREVER);
Expand All @@ -530,67 +527,36 @@ static int ieee802154_cc13xx_cc26xx_subg_tx(const struct device *dev,
/* TODO: Zero-copy TX, see discussion in #49775. */
memcpy(&drv_data->tx_data[IEEE802154_PHY_SUN_FSK_PHR_LEN], buf->data, buf->len);

/* Chain commands */
drv_data->cmd_prop_cs.pNextOp =
(rfc_radioOp_t *) &drv_data->cmd_prop_tx_adv;
drv_data->cmd_prop_cs.condition.rule = COND_STOP_ON_TRUE;

/* Set TX data */
drv_data->cmd_prop_tx_adv.pktLen = buf->len + IEEE802154_PHY_SUN_FSK_PHR_LEN;
drv_data->cmd_prop_tx_adv.pPkt = drv_data->tx_data;

/* Reset command status */
drv_data->cmd_prop_tx_adv.status = IDLE;
drv_data->cmd_prop_tx_adv.pNextOp = NULL;

/* Abort FG and BG processes */
ret = ieee802154_cc13xx_cc26xx_subg_stop(dev);
if (ret < 0) {
ret = -EIO;
goto out;
}

do {
/* Reset command status */
drv_data->cmd_prop_cs.status = IDLE;
drv_data->cmd_prop_tx_adv.status = IDLE;

events = RF_runCmd(drv_data->rf_handle,
(RF_Op *)&drv_data->cmd_prop_cs,
RF_PriorityNormal, cmd_prop_tx_adv_callback,
RF_EventLastCmdDone);
if ((events & RF_EventLastCmdDone) == 0) {
LOG_DBG("Failed to run command (%" PRIx64 ")", events);
ret = -EIO;
goto out;
}

if (drv_data->cmd_prop_cs.status != PROP_DONE_IDLE) {
LOG_DBG("Channel access failure (0x%x)",
drv_data->cmd_prop_cs.status);
/* TODO: This is not a compliant CSMA/CA algorithm, use soft CSMA/CA
* instead as the SubGHz radio of this SoC has no HW CSMA/CA backoff
* algorithm support as required by IEEE 802.15.4, section 6.2.5.1.
* Alternatively construct compliant CSMA/CA with a combination
* of CMD_NOP, CMD_PROP_CS and CMD_COUNT_BRANCH commands, see
* SimpleLink SDK (rfListenBeforeTalk.c) or calculate proper backoff
* period as in the SimpleLink WiSUN stack's mac_tx.c.
* Currently, we just wait a random amount of us in the range [0,256).
*/
k_busy_wait(sys_rand32_get() & 0xff);
continue;
}

if (drv_data->cmd_prop_tx_adv.status != PROP_DONE_OK) {
LOG_DBG("Transmit failed (0x%x)",
drv_data->cmd_prop_tx_adv.status);
continue;
}

/* TODO: handle RX acknowledgment */
ret = 0;
events = RF_runCmd(drv_data->rf_handle, (RF_Op *)&drv_data->cmd_prop_tx_adv,
RF_PriorityNormal, cmd_prop_tx_adv_callback, RF_EventLastCmdDone);
if ((events & RF_EventLastCmdDone) == 0) {
LOG_DBG("Failed to run command (%" PRIx64 ")", events);
ret = -EIO;
goto out;
}

} while (retry-- > 0);
if (drv_data->cmd_prop_tx_adv.status != PROP_DONE_OK) {
LOG_DBG("Transmit failed (0x%x)", drv_data->cmd_prop_tx_adv.status);
ret = -EIO;
goto out;
}

LOG_DBG("Failed to TX");
ret = -EIO;
/* TODO: handle RX acknowledgment */

out:
(void)ieee802154_cc13xx_cc26xx_subg_rx(dev);
Expand Down

0 comments on commit 78c47d6

Please sign in to comment.