Merged in merlin17/nuttx/ieee802154 (pull request #331)

wireless/ieee802154: Simplifies TX completion interface.  Documents and cleans up some functions

Approved-by: Gregory Nutt <gnutt@nuttx.org>
This commit is contained in:
Anthony Merlino 2017-04-21 19:16:17 +00:00 committed by Gregory Nutt
commit a31b555b72
3 changed files with 269 additions and 89 deletions

View File

@ -1520,7 +1520,7 @@ static void mrf24j40_irqwork_txnorm(FAR struct mrf24j40_radio_s *dev)
/* Inform the next layer of the transmission success/failure */
dev->radiocb->txdone_csma(dev->radiocb, &dev->csma_desc.pub);
dev->radiocb->txdone(dev->radiocb, &dev->csma_desc.pub);
/* We are now done with the transaction */
@ -1566,7 +1566,7 @@ static void mrf24j40_irqwork_txgts(FAR struct mrf24j40_radio_s *dev,
/* Inform the next layer of the transmission success/failure */
dev->radiocb->txdone_gts(dev->radiocb, &dev->gts_desc[gts].pub);
dev->radiocb->txdone(dev->radiocb, &dev->gts_desc[gts].pub);
/* We are now done with the transaction */

View File

@ -180,9 +180,7 @@ struct ieee802154_radiocb_s
FAR struct ieee802154_txdesc_s *tx_desc, FAR uint8_t *buf);
CODE int (*poll_gts) (FAR struct ieee802154_radiocb_s *radiocb,
FAR struct ieee802154_txdesc_s *tx_desc, FAR uint8_t *buf);
CODE int (*txdone_csma) (FAR struct ieee802154_radiocb_s *radiocb,
FAR const struct ieee802154_txdesc_s *tx_desc);
CODE int (*txdone_gts) (FAR struct ieee802154_radiocb_s *radiocb,
CODE int (*txdone) (FAR struct ieee802154_radiocb_s *radiocb,
FAR const struct ieee802154_txdesc_s *tx_desc);
CODE int (*rx_frame) (FAR struct ieee802154_radiocb_s *radiocb,
FAR const struct ieee8021254_rxdesc_s *rx_desc,

View File

@ -105,6 +105,9 @@ struct ieee802154_privmac_s
sem_t exclsem; /* Support exclusive access */
struct work_s tx_work;
struct work_s rx_work;
/* Support a singly linked list of transactions that will be sent using the
* CSMA algorithm. On a non-beacon enabled PAN, these transactions will be
* sent whenever. On a beacon-enabled PAN, these transactions will be sent
@ -125,6 +128,10 @@ struct ieee802154_privmac_s
FAR struct mac802154_trans_s *indirect_head;
FAR struct mac802154_trans_s *indirect_tail;
FAR struct ieee802154_txdesc_s *txhead; /* Next TX descriptor to handle */
FAR struct ieee802154_txdesc_s *txtail; /* Location to push TX descriptor */
struct ieee802154_txdesc_s txtable[CONFIG_IEEE802154_NTXDESC];
/* MAC PIB attributes, grouped to save memory */
/* Holds all address information (Extended, Short, and PAN ID) for the MAC. */
@ -262,6 +269,9 @@ static int mac802154_poll_gts(FAR struct ieee802154_radiocb_s *radiocb,
FAR struct ieee802154_txdesc_s *tx_desc,
FAR uint8_t *buf);
static int mac802154_txdone(FAR struct ieee802154_radiocb_s *radiocb,
FAR struct ieee802154_txdesc_s *tx_desc);
/****************************************************************************
* Private Data
****************************************************************************/
@ -325,6 +335,258 @@ static int mac802154_applymib(FAR struct ieee802154_privmac_s *priv)
return OK;
}
/****************************************************************************
* Name: mac802154_poll_csma
*
* Description:
* Called from the radio driver through the callback struct. This function is
* called when the radio has room for another CSMA transaction. If the MAC
* layer has a CSMA transaction, it copies it into the supplied buffer and
* returns the length. A descriptor is also populated with the transaction.
*
****************************************************************************/
static int mac802154_poll_csma(FAR struct ieee802154_radiocb_s *radiocb,
FAR struct ieee802154_txdesc_s *tx_desc,
FAR uint8_t *buf)
{
FAR struct mac802154_radiocb_s *cb =
(FAR struct mac802154_radiocb_s *)radiocb;
FAR struct ieee802154_privmac_s *priv;
FAR struct mac802154_trans_s *trans;
DEBUGASSERT(cb != NULL && cb->priv != NULL);
priv = cb->priv;
/* Get exclusive access to the driver structure. We don't care about any
* signals so if we see one, just go back to trying to get access again.
*/
while (mac802154_takesem(&priv->exclsem) != 0);
/* Check to see if there are any CSMA transactions waiting */
if (priv->csma_head)
{
/* Pop a CSMA transaction off the list */
trans = priv->csma_head;
priv->csma_head = priv->csma_head->flink;
mac802154_givesem(&priv->exclsem);
/* Setup the transmit descriptor */
tx_desc->psdu_handle = trans->msdu_handle;
tx_desc->psdu_length = trans->mhr_len + trans->d_len;
/* Copy the frame into the buffer */
memcpy(&buf[0], trans->mhr_buf, trans->mhr_len);
memcpy(&buf[trans->mhr_len], trans->d_buf, trans->d_len);
/* Now that we've passed off the data, notify the waiting thread.
* NOTE: The transaction was allocated on the waiting thread's stack so
* it will be automatically deallocated when that thread awakens and
* returns.
*/
sem_post(&trans->sem);
return tx_desc->psdu_length;
}
mac802154_givesem(&priv->exclsem);
return 0;
}
/****************************************************************************
* Name: mac802154_poll_gts
*
* Description:
* Called from the radio driver through the callback struct. This function is
* called when the radio has room for another GTS transaction. If the MAC
* layer has a GTS transaction, it copies it into the supplied buffer and
* returns the length. A descriptor is also populated with the transaction.
*
****************************************************************************/
static int mac802154_poll_gts(FAR struct ieee802154_radiocb_s *radiocb,
FAR struct ieee802154_txdesc_s *tx_desc,
FAR uint8_t *buf)
{
FAR struct mac802154_radiocb_s *cb =
(FAR struct mac802154_radiocb_s *)radiocb;
FAR struct ieee802154_privmac_s *priv;
FAR struct mac802154_trans_s *trans;
int ret = 0;
DEBUGASSERT(cb != NULL && cb->priv != NULL);
priv = cb->priv;
/* Get exclusive access to the driver structure. We don't care about any
* signals so if we see one, just go back to trying to get access again.
*/
while (mac802154_takesem(&priv->exclsem) != 0);
#warning Missing logic.
mac802154_givesem(&priv->exclsem);
return 0;
}
/****************************************************************************
* Name: mac802154_txdone
*
* Description:
* Called from the radio driver through the callback struct. This function is
* called when the radio has completed a transaction. The txdesc passed gives
* provides information about the completed transaction including the original
* handle provided when the transaction was created and the status of the
* transaction. This function copies the descriptor and schedules work to
* handle the transaction without blocking the radio.
*
****************************************************************************/
static int mac802154_txdone(FAR struct ieee802154_radiocb_s *radiocb,
FAR const struct ieee802154_txdesc_s *tx_desc)
{
FAR struct mac802154_radiocb_s *cb =
(FAR struct mac802154_radiocb_s *)radiocb;
FAR struct ieee802154_privmac_s *priv;
FAR struct ieee802154_txdesc_s *desc;
int ret = 0;
DEBUGASSERT(cb != NULL && cb->priv != NULL);
priv = cb->priv;
/* Get exclusive access to the driver structure. We don't care about any
* signals so if we see one, just go back to trying to get access again.
*/
while (mac802154_takesem(&priv->exclsem) != 0);
/* Allocate a tx_desc */
desc = kmm_zalloc(sizeof(struct ieee802154_txdesc_s));
if (desc == NULL)
{
mac802154_givesem(&priv->exclsem);
return -ENOMEM;
}
/* Copy the txdesc over and link it into our list */
memcpy(desc, tx_desc, sizeof(ieee802154_txdesc_s));
/* Link the descriptor */
#warning Missing Logic!
mac802154_givesem(&priv->exclsem);
/* Schedule work with the work queue to process the completion further */
if (work_available(&priv->tx_work))
{
work_queue(MAC802154_WORK, &priv->tx_work, mac802154_txdone_worker,
(FAR void *)dev, 0);
}
}
/****************************************************************************
* Name: mac802154_txdone_worker
*
* Description:
* Worker function scheduled from mac802154_txdone. This function pops any
* TX descriptors off of the list and calls the next highest layers callback
* to inform the layer of the completed transaction and the status of it.
*
****************************************************************************/
static void mac802154_txdone_worker(FAR void *arg)
{
FAR struct ieee802154_privmanc_s *priv =
(FAR struct ieee802154_privmanc_s *)arg;
}
/****************************************************************************
* Name: mac802154_rxframe
*
* Description:
* Called from the radio driver through the callback struct. This function is
* called when the radio has received a frame. The frame is passed in an iob,
* so that we can free it when we are done processing. A pointer to the RX
* descriptor is passed along with the iob, but it must be copied here as it
* is allocated directly on the caller's stack. We simply link the frame,
* copy the RX descriptor, and schedule a worker to process the frame later so
* that we do not hold up the radio.
*
****************************************************************************/
static void mac802154_rxframe(FAR struct ieee802154_radiocb_s *radiocb,
FAR struct ieee802154_rxdesc_s *rx_desc,
FAR struct iob_s *frame)
{
FAR struct mac802154_radiocb_s *cb =
(FAR struct mac802154_radiocb_s *)radiocb;
FAR struct ieee802154_privmac_s *priv;
FAR struct ieee802154_txdesc_s *desc;
int ret = 0;
DEBUGASSERT(cb != NULL && cb->priv != NULL);
priv = cb->priv;
/* Get exclusive access to the driver structure. We don't care about any
* signals so if we see one, just go back to trying to get access again.
*/
while (mac802154_takesem(&priv->exclsem) != 0);
/* TODO: Copy the frame descriptor to some type of list */
/* Push the iob onto the tail of the frame list for processing */
priv->rxframes_tail->io_flink = iob;
priv->rxframes_tail = iob;
mac802154_givesem(&priv->exclsem);
/* Schedule work with the work queue to process the completion further */
if (work_available(&priv->rx_work))
{
work_queue(MAC802154_WORK, &priv->rx_work, mac802154_rxframe_worker,
(FAR void *)priv, 0);
}
}
/****************************************************************************
* Name: mac802154_rxframe_worker
*
* Description:
* Worker function scheduled from mac802154_rxframe. This function processes
* any frames in the list. Frames intended to be consumed by the MAC layer
* will not produce any callbacks to the next highest layer. Frames intended
* for the application layer will be forwarded to them.
*
****************************************************************************/
static void mac802154_rxframe_worker(FAR void *arg)
{
FAR struct ieee802154_privmac_s *priv =
(FAR struct ieee802154_privmac_s *)arg;
/* The radio layer is responsible for handling all ACKs and retries. If for
* some reason an ACK gets here, just throw it out */
}
/****************************************************************************
* Public Functions
****************************************************************************/
@ -379,9 +641,10 @@ MACHANDLE mac802154_create(FAR struct ieee802154_radio_s *radiodev)
mac->radiocb.priv = mac;
radiocb = &mac->radiocb.cb;
radiocb->poll_csma = mac802154_poll_csma;
radiocb->poll_gts = mac802154_poll_gts;
radiocb = &mac->radiocb.cb;
radiocb->poll_csma = mac802154_poll_csma;
radiocb->poll_gts = mac802154_poll_gts;
radiocb->txdone = mac802154_txdone;
/* Bind our callback structure */
@ -710,87 +973,6 @@ int mac802154_req_data(MACHANDLE mac, FAR struct ieee802154_data_req_s *req)
return OK;
}
/* Called from interrupt level or worker thread with interrupts disabled */
static int mac802154_poll_csma(FAR struct ieee802154_radiocb_s *radiocb,
FAR struct ieee802154_txdesc_s *tx_desc,
FAR uint8_t *buf)
{
FAR struct mac802154_radiocb_s *cb =
(FAR struct mac802154_radiocb_s *)radiocb;
FAR struct ieee802154_privmac_s *priv;
FAR struct mac802154_trans_s *trans;
int ret = 0;
DEBUGASSERT(cb != NULL && cb->priv != NULL);
priv = cb->priv;
/* Get exclusive access to the driver structure. We don't care about any
* signals so if we see one, just go back to trying to get access again.
*/
while (mac802154_takesem(&priv->exclsem) != 0);
/* Check to see if there are any CSMA transactions waiting */
if (priv->csma_head)
{
/* Pop a CSMA transaction off the list */
trans = priv->csma_head;
priv->csma_head = priv->csma_head->flink;
/* Setup the transmit descriptor */
tx_desc->psdu_handle = trans->msdu_handle;
tx_desc->psdu_length = trans->mhr_len + trans->d_len;
/* Copy the frame into the buffer */
memcpy(&buf[0], trans->mhr_buf, trans->mhr_len);
memcpy(&buf[trans->mhr_len], trans->d_buf, trans->d_len);
/* Now that we've passed off the data, notify the waiting thread.
* NOTE: The transaction was allocated on the waiting thread's stack so
* it will be automatically deallocated when that thread awakens and
* returns.
*/
sem_post(&trans->sem);
ret = tx_desc->psdu_length;
}
mac802154_givesem(&priv->exclsem);
return ret;
}
static int mac802154_poll_gts(FAR struct ieee802154_radiocb_s *radiocb,
FAR struct ieee802154_txdesc_s *tx_desc,
FAR uint8_t *buf)
{
FAR struct mac802154_radiocb_s *cb =
(FAR struct mac802154_radiocb_s *)radiocb;
FAR struct ieee802154_privmac_s *priv;
FAR struct mac802154_trans_s *trans;
int ret = 0;
DEBUGASSERT(cb != NULL && cb->priv != NULL);
priv = cb->priv;
/* Get exclusive access to the driver structure. We don't care about any
* signals so if we see one, just go back to trying to get access again.
*/
while (mac802154_takesem(&priv->exclsem) != 0);
#warning Missing logic.
mac802154_givesem(&priv->exclsem);
return 0;
}
/****************************************************************************
* Name: mac802154_req_purge