drivers: ieee802154: Add auto-ack support to KW41Z driver
- Enabled and fixed auto-ack offload support for 802.15.4 transmit Signed-off-by: David Leach <david.leach@nxp.com>
This commit is contained in:
parent
c90b9f53cd
commit
7738a501d9
|
@ -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;
|
||||
|
@ -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); \
|
||||
|
@ -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 | \
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
|
Loading…
Reference in a new issue