Skip to content

Commit

Permalink
drivers: ieee802154: Add auto-ack support to KW41Z driver
Browse files Browse the repository at this point in the history
- Enabled and fixed auto-ack offload support for 802.15.4 transmit

Signed-off-by: David Leach <[email protected]>
  • Loading branch information
dleach02 authored and jukkar committed Apr 11, 2018
1 parent c90b9f5 commit 7738a50
Showing 1 changed file with 48 additions and 41 deletions.
89 changes: 48 additions & 41 deletions drivers/ieee802154/ieee802154_kw41z.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@

struct kw41_dbg_trace {
u8_t type;
u32_t time;
u32_t irqsts;
u32_t phy_ctrl;
u32_t seq_state;
Expand All @@ -53,6 +54,8 @@ int kw41_dbg_idx;
#define KW_DBG_TRACE(_type, _irqsts, _phy_ctrl, _seq_state) \
do { \
kw41_dbg[kw41_dbg_idx].type = (_type); \
kw41_dbg[kw41_dbg_idx].time = \
ZLL->EVENT_TMR >> ZLL_EVENT_TMR_EVENT_TMR_SHIFT; \
kw41_dbg[kw41_dbg_idx].irqsts = (_irqsts); \
kw41_dbg[kw41_dbg_idx].phy_ctrl = (_phy_ctrl); \
kw41_dbg[kw41_dbg_idx].seq_state = (_seq_state); \
Expand Down Expand Up @@ -81,12 +84,6 @@ int kw41_dbg_idx;
#define KW41Z_OUTPUT_POWER_MAX 2
#define KW41Z_OUTPUT_POWER_MIN (-19)

/*
* When ACK offload is implemented in the 15.4 stack we can enable
* things here.
*/
#define KW41Z_AUTOACK_ENABLED 0

#define BM_ZLL_IRQSTS_TMRxMSK (ZLL_IRQSTS_TMR1MSK_MASK | \
ZLL_IRQSTS_TMR2MSK_MASK | \
ZLL_IRQSTS_TMR3MSK_MASK | \
Expand Down Expand Up @@ -518,11 +515,6 @@ static inline void kw41z_rx(struct kw41z_context *kw41z, u8_t len)

net_buf_add(frag, pkt_len);

if (ieee802154_radio_handle_ack(kw41z->iface, pkt) == NET_OK) {
SYS_LOG_DBG("ACK packet handled");
goto out;
}

hw_lqi = (ZLL->LQI_AND_RSSI & ZLL_LQI_AND_RSSI_LQI_VALUE_MASK) >>
ZLL_LQI_AND_RSSI_LQI_VALUE_SHIFT;
net_pkt_set_ieee802154_lqi(pkt, kw41z_convert_lqi(hw_lqi));
Expand All @@ -546,9 +538,9 @@ static int kw41z_tx(struct device *dev, struct net_pkt *pkt,
{
struct kw41z_context *kw41z = dev->driver_data;
u8_t payload_len = net_pkt_ll_reserve(pkt) + frag->len;
#if KW41Z_AUTOACK_ENABLED
u32_t tx_timeout;
#endif
u8_t xcvseq;
int key;

/*
* The transmit requests are preceded by the CCA request. On
Expand All @@ -565,6 +557,12 @@ static int kw41z_tx(struct device *dev, struct net_pkt *pkt,
return 0;
}

key = irq_lock();

/* Disable the 802.15.4 radio IRQ */
ZLL->PHY_CTRL |= ZLL_PHY_CTRL_TRCV_MSK_MASK;
kw41z_disable_seq_irq();

#if CONFIG_SOC_MKW41Z4
((u8_t *)ZLL->PKT_BUFFER_TX)[0] = payload_len + KW41Z_FCS_LENGTH;
memcpy(((u8_t *)ZLL->PKT_BUFFER_TX) + 1,
Expand All @@ -586,32 +584,38 @@ static int kw41z_tx(struct device *dev, struct net_pkt *pkt,
* Current Zephyr 802.15.4 stack doesn't support ACK offload
*/

#if KW41Z_AUTOACK_ENABLED
/* Perform automatic reception of ACK frame, if required */
if (ieee802154_is_ar_flag_set(pkt)) {
tx_timeout = kw41z->tx_warmup_time + KW41Z_SHR_PHY_TIME +
payload_len * KW41Z_PER_BYTE_TIME + 10 +
KW41Z_ACK_WAIT_TIME;

SYS_LOG_DBG("AUTOACK_ENABLED: len: %d, timeout: %d, seq: %d",
SYS_LOG_DBG("AUTOACK ENABLED: len: %d, timeout: %d, seq: %d",
payload_len, tx_timeout,
(frag->data - net_pkt_ll_reserve(pkt))[2]);

kw41z_tmr3_set_timeout(tx_timeout);
ZLL->PHY_CTRL |= ZLL_PHY_CTRL_RXACKRQD_MASK;
kw41z_set_seq_state(KW41Z_STATE_TXRX);
} else
#endif
{
SYS_LOG_DBG("AUTOACK disabled: len: %d, seq: %d",
xcvseq = KW41Z_STATE_TXRX;
} else {
SYS_LOG_DBG("AUTOACK DISABLED: len: %d, seq: %d",
payload_len, (frag->data - net_pkt_ll_reserve(pkt))[2]);

ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_RXACKRQD_MASK;
kw41z_set_seq_state(KW41Z_STATE_TX);
xcvseq = KW41Z_STATE_TX;
}

kw41z_enable_seq_irq();

/*
* PHY_CTRL is sensitive to multiple writes that can kick off
* the sequencer engine causing TX with AR request to send the
* TX frame multiple times.
*
* To minimize, ensure there is only one write to PHY_CTRL with
* TXRX sequence enable and the 802.15.4 radio IRQ.
*/
ZLL->PHY_CTRL = (ZLL->PHY_CTRL & ~ZLL_PHY_CTRL_TRCV_MSK_MASK) | xcvseq;
irq_unlock(key);
k_sem_take(&kw41z->seq_sync, K_FOREVER);

SYS_LOG_DBG("seq_retval: %d", kw41z->seq_retval);
Expand Down Expand Up @@ -669,25 +673,27 @@ static void kw41z_isr(int unused)
rx_len = (irqsts & ZLL_IRQSTS_RX_FRAME_LENGTH_MASK)
>> ZLL_IRQSTS_RX_FRAME_LENGTH_SHIFT;

SYS_LOG_DBG("WMRK irq: seq_state: 0x%08x, rx_len: %d",
seq_state, rx_len);

KW_DBG_TRACE(KW41_DBG_TRACE_WTRM, irqsts,
(unsigned int)ZLL->PHY_CTRL, seq_state);

/*
* Assume the RX includes an auto-ACK so set the timer to
* include the RX frame size, crc, IFS, and ACK length and
* convert to symbols.
*
* IFS is 12 symbols
*
* ACK frame is 11 bytes: 4 preamble, 1 start of frame, 1 frame
* length, 2 frame control, 1 sequence, 2 FCS. Times two to
* convert to symbols.
*/
rx_len = rx_len * 2 + 12 + 22 + 2;
kw41z_tmr3_set_timeout(rx_len);
if (rx_len > IEEE802154_ACK_LENGTH) {

SYS_LOG_DBG("WMRK irq: seq_state: 0x%08x, rx_len: %d",
seq_state, rx_len);
/*
* Assume the RX includes an auto-ACK so set the timer to
* include the RX frame size, crc, IFS, and ACK length and
* convert to symbols.
*
* IFS is 12 symbols
*
* ACK frame is 11 bytes: 4 preamble, 1 start of frame, 1 frame
* length, 2 frame control, 1 sequence, 2 FCS. Times two to
* convert to symbols.
*/
rx_len = rx_len * 2 + 12 + 22 + 2;
kw41z_tmr3_set_timeout(rx_len);
}
restart_rx = 0;
}

Expand Down Expand Up @@ -726,6 +732,7 @@ static void kw41z_isr(int unused)
/* TODO: What is the right error for no ACK? */
atomic_set(&kw41z_context_data.seq_retval,
-EBUSY);
k_sem_give(&kw41z_context_data.seq_sync);
}
} else {
kw41z_isr_seq_cleanup();
Expand Down Expand Up @@ -823,7 +830,7 @@ static void kw41z_isr(int unused)
/* Restart RX */
if (restart_rx) {
SYS_LOG_DBG("RESET RX");

kw41z_phy_abort();
kw41z_set_seq_state(KW41Z_STATE_RX);
kw41z_enable_seq_irq();
}
Expand Down Expand Up @@ -879,15 +886,14 @@ static int kw41z_init(struct device *dev)
ZLL_PHY_CTRL_CCAMSK_MASK |
ZLL_PHY_CTRL_RXMSK_MASK |
ZLL_PHY_CTRL_TXMSK_MASK |
ZLL_PHY_CTRL_CCABFRTX_MASK |
ZLL_PHY_CTRL_SEQMSK_MASK;

#if CONFIG_SOC_MKW41Z4
ZLL->PHY_CTRL |= ZLL_IRQSTS_WAKE_IRQ_MASK;
#endif

#if KW41Z_AUTOACK_ENABLED
ZLL->PHY_CTRL |= ZLL_PHY_CTRL_AUTOACK_MASK;
#endif

/*
* Clear all PP IRQ bits to avoid unexpected interrupts immediately
Expand All @@ -904,6 +910,7 @@ static int kw41z_init(struct device *dev)
ZLL->RX_FRAME_FILTER = ZLL_RX_FRAME_FILTER_FRM_VER_FILTER(3) |
ZLL_RX_FRAME_FILTER_CMD_FT_MASK |
ZLL_RX_FRAME_FILTER_DATA_FT_MASK |
ZLL_RX_FRAME_FILTER_ACK_FT_MASK |
ZLL_RX_FRAME_FILTER_BEACON_FT_MASK;

/* Set prescaller to obtain 1 symbol (16us) timebase */
Expand Down

0 comments on commit 7738a50

Please sign in to comment.