diff --git a/wireless/ieee802154/mac802154.c b/wireless/ieee802154/mac802154.c index 3a7989e9d8a..cf7ebba2123 100644 --- a/wireless/ieee802154/mac802154.c +++ b/wireless/ieee802154/mac802154.c @@ -92,13 +92,6 @@ static void mac802154_sfevent(FAR const struct ieee802154_radiocb_s *radiocb, static void mac802154_purge_worker(FAR void *arg); -/* Watchdog Timeout Functions */ - -static void mac802154_timeout_expiry(int argc, wdparm_t arg, ...); - -static uint32_t mac802154_symtoticks(FAR struct ieee802154_privmac_s *priv, - uint32_t symbols); - static void mac802154_rxdatareq(FAR struct ieee802154_privmac_s *priv, FAR struct ieee802154_data_ind_s *ind); static void mac802154_rxdataframe(FAR struct ieee802154_privmac_s *priv, @@ -1918,125 +1911,6 @@ errout: mac802154_notif_free_locked(priv, notif); } -/**************************************************************************** - * Name: mac802154_symtoticks - * - * Description: - * Helper function for converting symbols to system clock ticks - * - * Assumptions: - * priv MAC struct is locked when calling. - * - ****************************************************************************/ - -static uint32_t mac802154_symtoticks(FAR struct ieee802154_privmac_s *priv, - uint32_t symbols) -{ - union ieee802154_attr_u attrval; - uint32_t ret; - - /* First, get the symbol duration from the radio layer. Symbol duration is - * returned in picoseconds to ensure precision is kept when multiplying to - * get overall times. - */ - - priv->radio->getattr(priv->radio, IEEE802154_ATTR_PHY_SYMBOL_DURATION, - &attrval); - - /* After this step, ret represents microseconds */ - - ret = ((uint64_t)attrval.phy.symdur_picosec * symbols) / (1000 * 1000); - - /* This method should only be used for things that can be late. For instance, - * it's always okay to wait a little longer before disabling your receiver. - * Therefore, we force the tick count to round up. - */ - - if (ret % USEC_PER_TICK == 0) - { - ret = ret/USEC_PER_TICK; - } - else - { - ret = ret/USEC_PER_TICK; - ret++; - } - - return ret; -} - -/**************************************************************************** - * Name: mac802154_timerstart - * - * Description: - * Helper function wrapping the watchdog timer interface. Helps isolate - * different operations from having to worry about work queues and watchdog - * timers. - * - * Assumptions: - * priv MAC struct is locked when calling. - * - ****************************************************************************/ - -int mac802154_timerstart(FAR struct ieee802154_privmac_s *priv, - uint32_t numsymbols, mac802154_worker_t worker) -{ - /* TODO: Add check to make sure timer is not already being used. I'd like to - * design this so that it absolutely never happens */ - - /* Convert the number of symbols to the number of CPU ticks */ - - uint32_t ticks = mac802154_symtoticks(priv, numsymbols); - - /* Save the function pointer to call if the timeout expires */ - - priv->timeout_worker = worker; - - /* Start the watchdog */ - - wd_start(priv->timeout, (int32_t)ticks, mac802154_timeout_expiry, - 1, (wdparm_t)priv); - - return OK; -} - -/**************************************************************************** - * Function: mac802154_timeout_expiry - * - * Description: - * The watchdog timed out. Called from the timer interrupt handler. - * - * Parameters: - * argc - The number of available arguments - * arg - The first argument - * - * Returned Value: - * None - * - * Assumptions: - * Global interrupts are disabled by the watchdog logic. - * - ****************************************************************************/ - -static void mac802154_timeout_expiry(int argc, wdparm_t arg, ...) -{ - FAR struct ieee802154_privmac_s *priv = (FAR struct ieee802154_privmac_s *)arg; - - /* There should never be a case where the timeout is used twice at the same - * time. */ - - DEBUGASSERT(work_available(&priv->timeout_work)); - - /* Check to make sure the function pointer is still valid */ - - DEBUGASSERT(priv->timeout_worker != NULL); - - wlinfo("Timer expired\n"); - - work_queue(MAC802154_WORK, &priv->timeout_work, (worker_t)priv->timeout_worker, - priv, 0); -} - /**************************************************************************** * Public Functions ****************************************************************************/ @@ -2092,10 +1966,6 @@ MACHANDLE mac802154_create(FAR struct ieee802154_radio_s *radiodev) sem_init(&mac->opsem, 0, 1); - /* Setup watchdog for extraction timeout */ - - mac->timeout = wd_create(); - /* Initialize fields */ mac->radio = radiodev; diff --git a/wireless/ieee802154/mac802154_assoc.c b/wireless/ieee802154/mac802154_assoc.c index beaf1c34f65..42ee5c46184 100644 --- a/wireless/ieee802154/mac802154_assoc.c +++ b/wireless/ieee802154/mac802154_assoc.c @@ -58,7 +58,7 @@ * Private Function Prototypes ****************************************************************************/ -static void mac802154_assoctimeout(FAR struct ieee802154_privmac_s *priv); +static void mac802154_assoctimeout(FAR void *arg); /**************************************************************************** * Public MAC Functions @@ -858,10 +858,22 @@ void mac802154_rx_assocresp(FAR struct ieee802154_privmac_s *priv, * ****************************************************************************/ -static void mac802154_assoctimeout(FAR struct ieee802154_privmac_s *priv) +static void mac802154_assoctimeout(FAR void *arg) { + FAR struct ieee802154_privmac_s *priv = (FAR struct ieee802154_privmac_s *)arg; FAR struct ieee802154_notif_s *notif; + /* If there is work scheduled for the rxframe_worker, we want to reschedule + * this work, so that we make sure if the frame we were waiting for was just + * received, we don't timeout + */ + + if (!work_available(&priv->rx_work)) + { + work_queue(MAC802154_WORK, &priv->timer_work, mac802154_assoctimeout, priv, 0); + return; + } + DEBUGASSERT(priv->curr_op == MAC802154_OP_ASSOC); /* If the device does not extract an association response command diff --git a/wireless/ieee802154/mac802154_internal.h b/wireless/ieee802154/mac802154_internal.h index fc097cfbf69..6fcfaaeb8e1 100644 --- a/wireless/ieee802154/mac802154_internal.h +++ b/wireless/ieee802154/mac802154_internal.h @@ -139,9 +139,6 @@ enum mac802154_operation_e MAC802154_OP_AUTOEXTRACT, }; -struct ieee802154_privmac_s; /* Forward Reference */ -typedef void (*mac802154_worker_t)(FAR struct ieee802154_privmac_s *priv); - /* The privmac structure holds the internal state of the MAC and is the * underlying represention of the opaque MACHANDLE. It contains storage for * the IEEE802.15.4 MIB attributes. @@ -254,12 +251,8 @@ struct ieee802154_privmac_s struct work_s tx_work; struct work_s rx_work; - - struct work_s timeout_work; - WDOG_ID timeout; /* Timeout watchdog */ - mac802154_worker_t timeout_worker; - struct work_s purge_work; + struct work_s timer_work; /****************** Uncategorized MAC PIB attributes ***********************/ @@ -375,9 +368,6 @@ int mac802154_txdesc_alloc(FAR struct ieee802154_privmac_s *priv, FAR struct ieee802154_txdesc_s **txdesc, bool allow_interrupt); -int mac802154_timerstart(FAR struct ieee802154_privmac_s *priv, - uint32_t numsymbols, mac802154_worker_t); - void mac802154_setupindirect(FAR struct ieee802154_privmac_s *priv, FAR struct ieee802154_txdesc_s *txdesc); @@ -624,6 +614,77 @@ static inline void mac802154_txdesc_free(FAR struct ieee802154_privmac_s *priv, mac802154_givesem(&priv->txdesc_sem); } +/**************************************************************************** + * Name: mac802154_symtoticks + * + * Description: + * Helper function for converting symbols to system clock ticks + * + * Assumptions: + * priv MAC struct is locked when calling. + * + ****************************************************************************/ + +static inline uint32_t mac802154_symtoticks(FAR struct ieee802154_privmac_s *priv, + uint32_t symbols) +{ + union ieee802154_attr_u attrval; + uint32_t ret; + + /* First, get the symbol duration from the radio layer. Symbol duration is + * returned in picoseconds to ensure precision is kept when multiplying to + * get overall times. + */ + + priv->radio->getattr(priv->radio, IEEE802154_ATTR_PHY_SYMBOL_DURATION, + &attrval); + + /* After this step, ret represents microseconds */ + + ret = ((uint64_t)attrval.phy.symdur_picosec * symbols) / (1000 * 1000); + + /* This method should only be used for things that can be late. For instance, + * it's always okay to wait a little longer before disabling your receiver. + * Therefore, we force the tick count to round up. + */ + + if (ret % USEC_PER_TICK == 0) + { + ret = ret/USEC_PER_TICK; + } + else + { + ret = ret/USEC_PER_TICK; + ret++; + } + + return ret; +} + +/**************************************************************************** + * Name: mac802154_timerstart + * + * Description: + * Helper function wrapping the watchdog timer interface. Helps isolate + * different operations from having to worry about work queues and watchdog + * timers. + * + * Assumptions: + * priv MAC struct is locked when calling. + * + ****************************************************************************/ + +static inline void mac802154_timerstart(FAR struct ieee802154_privmac_s *priv, + uint32_t numsymbols, worker_t worker) +{ + DEBUGASSERT(work_available(&priv->timer_work)); + + /* Schedule the work, converting the number of symbols to the number of CPU ticks */ + + work_queue(MAC802154_WORK, &priv->timer_work, worker, priv, + mac802154_symtoticks(priv, numsymbols)); +} + /**************************************************************************** * Name: mac802154_timercancel * @@ -637,8 +698,7 @@ static inline void mac802154_txdesc_free(FAR struct ieee802154_privmac_s *priv, static inline int mac802154_timercancel(FAR struct ieee802154_privmac_s *priv) { - wd_cancel(priv->timeout); - priv->timeout_worker = NULL; + work_cancel(MAC802154_WORK, &priv->timer_work); wlinfo("Timer cancelled\n"); return OK; } diff --git a/wireless/ieee802154/mac802154_poll.c b/wireless/ieee802154/mac802154_poll.c index 715518e916c..3271a8f92af 100644 --- a/wireless/ieee802154/mac802154_poll.c +++ b/wireless/ieee802154/mac802154_poll.c @@ -60,7 +60,7 @@ * Private Function Prototypes ****************************************************************************/ -static void mac802154_polltimeout(FAR struct ieee802154_privmac_s *priv); +static void mac802154_polltimeout(FAR void *arg); /**************************************************************************** * Public MAC Functions @@ -152,6 +152,8 @@ int mac802154_req_poll(MACHANDLE mac, FAR struct ieee802154_poll_req_s *req) priv->cmd_desc = txdesc; + wlinfo("Queuing POLL.request in CSMA queue\n"); + /* Link the transaction into the CSMA transaction list */ sq_addlast((FAR sq_entry_t *)txdesc, &priv->csma_queue); @@ -259,10 +261,22 @@ void mac802154_txdone_datareq_poll(FAR struct ieee802154_privmac_s *priv, * ****************************************************************************/ -void mac802154_polltimeout(FAR struct ieee802154_privmac_s *priv) +void mac802154_polltimeout(FAR void *arg) { + FAR struct ieee802154_privmac_s *priv = (FAR struct ieee802154_privmac_s *)arg; FAR struct ieee802154_notif_s *notif; + /* If there is work scheduled for the rxframe_worker, we want to reschedule + * this work, so that we make sure if the frame we were waiting for was just + * received, we don't timeout + */ + + if (!work_available(&priv->rx_work)) + { + work_queue(MAC802154_WORK, &priv->timer_work, mac802154_polltimeout, priv, 0); + return; + } + DEBUGASSERT(priv->curr_op == MAC802154_OP_POLL); /* Allocate a notification struct to pass to the next highest layer. diff --git a/wireless/ieee802154/mac802154_scan.c b/wireless/ieee802154/mac802154_scan.c index c24ae0b5f1b..0c6140b1926 100644 --- a/wireless/ieee802154/mac802154_scan.c +++ b/wireless/ieee802154/mac802154_scan.c @@ -60,7 +60,7 @@ * Private Function Prototypes ****************************************************************************/ -static void mac802154_scantimeout(FAR struct ieee802154_privmac_s *priv); +static void mac802154_scantimeout(FAR void *arg); /**************************************************************************** * Public MAC Functions @@ -251,8 +251,9 @@ void mac802154_scanfinish(FAR struct ieee802154_privmac_s *priv, * ****************************************************************************/ -static void mac802154_scantimeout(FAR struct ieee802154_privmac_s *priv) +static void mac802154_scantimeout(FAR void *arg) { + FAR struct ieee802154_privmac_s *priv = (FAR struct ieee802154_privmac_s *)arg; DEBUGASSERT(priv->curr_op == MAC802154_OP_SCAN); /* If we got here it means we are done scanning that channel */