From bf2c827dcf1389d5d92ab1d58e0a305db0dd5026 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 1 Mar 2016 14:17:13 +0200 Subject: Revert "cc2520: Rework reception logic" This reverts commit bf77d902ac15ad654cb8fb07e96f6b9e5117f051. The commit is reverted because it causes hangs in packet reception. After transferring data a while, the chip stops packet reception. Change-Id: Icb94e978e3ba526314afd5e80f35c877febe8740 Signed-off-by: Jukka Rissanen --- drivers/802.15.4/cc2520.c | 153 ++++++++++++++++++++++++---------------------- 1 file changed, 80 insertions(+), 73 deletions(-) diff --git a/drivers/802.15.4/cc2520.c b/drivers/802.15.4/cc2520.c index f56b92b00..8c5c5bf0d 100644 --- a/drivers/802.15.4/cc2520.c +++ b/drivers/802.15.4/cc2520.c @@ -54,12 +54,13 @@ #include "cc2520.h" #include "cc2520_arch.h" -#define CC2520_CONF_AUTOACK 1 +#ifndef CC2520_CONF_AUTOACK +#define CC2520_CONF_AUTOACK 0 +#endif /* CC2520_CONF_AUTOACK */ + #define WITH_SEND_CCA 1 #define FOOTER_LEN 2 -/* Len + FCF + SEQ + FCS + PAN ID */ -#define MIN_LENGTH_BEFORE_ACCEPT 10 #define AUTOCRC (1 << 6) #define AUTOACK (1 << 5) @@ -252,8 +253,6 @@ static inline void print_exceptions_1(void) DBG("DPU_DONE_H"); } DBG("\n"); - - setreg(CC2520_EXCFLAG1, 0); } static inline void print_errors(void) @@ -283,7 +282,14 @@ static inline void print_errors(void) DBG("RFBUFMOV_TIMEOUT"); } DBG("\n"); +} + +static void clear_exceptions(void) +{ + DBG("Clearing up exceptions & errors\n"); + setreg(CC2520_EXCFLAG0, 0); + setreg(CC2520_EXCFLAG1, 0); setreg(CC2520_EXCFLAG2, 0); } @@ -304,6 +310,7 @@ static void cc2520_print_gpio_config(void) #define print_exceptions_0() #define print_exceptions_1() #define print_errors() +#define clear_exceptions() #define cc2520_print_gpio_config() #endif @@ -482,6 +489,7 @@ static radio_result_t cc2520_set_rx_mode(radio_value_t value) } old_value = value; +#if 1 if (receive_on) { cc2520_strobe(CC2520_INS_SRXON); @@ -490,6 +498,7 @@ static radio_result_t cc2520_set_rx_mode(radio_value_t value) return RADIO_RESULT_ERROR; } } +#endif /* 1/0 */ return RADIO_RESULT_OK; } @@ -657,7 +666,7 @@ static int cc2520_transmit(struct net_buf *buf, unsigned short payload_len) */ BUSYWAIT_UNTIL(!(status() & BIT(CC2520_TX_ACTIVE)), WAIT_500ms); - DBG("Transmitted!\n"); + DBG("status 0x%x\n", status()); if (!receive_on) { /* We need to explicitly turn off the radio, @@ -701,12 +710,18 @@ static int cc2520_prepare(const void *payload, unsigned short payload_len) DBG("cc2520: sending %d bytes\n", payload_len); + clear_exceptions(); + /* Write packet to TX FIFO. */ strobe(CC2520_INS_SFLUSHTX); total_len = payload_len + FOOTER_LEN; + DBG("TX FIFO has %u bytes\n", getreg(CC2520_TXFIFOCNT)); cc2520_write_fifo_buf(&total_len, 1); cc2520_write_fifo_buf(buf, payload_len); + DBG("TX FIFO has %u bytes\n", getreg(CC2520_TXFIFOCNT)); + + print_errors(); return 0; } @@ -810,79 +825,65 @@ bool cc2520_set_pan_addr(unsigned pan, unsigned addr, return true; } -static inline uint8_t rxcount(void) -{ - return getreg(CC2520_RXFIFOCNT); -} - static int cc2520_read(void *buf, unsigned short bufsize) { + struct cc2520_config *info = cc2520_sgl_dev->config->config_info; uint8_t footer[2]; - uint8_t pkt_len; uint8_t len; - uint8_t cnt; if (!init_ok) { return -EIO; } - cnt = rxcount(); - if (cnt < MIN_LENGTH_BEFORE_ACCEPT) { + if (!cc2520_pending_packet()) { return -EAGAIN; } - getrxbyte(&pkt_len); - len = pkt_len - FOOTER_LEN; - - while (1) { - if (cnt > len) { - cnt = len; - } - - getrxdata(buf, cnt); + cc2520_packets_read++; - buf += cnt; - len -= cnt; + getrxbyte(&len); - if (len <= 0) { - break; - } + DBG("%s: Incoming packet length: %d\n", __func__, len); - while (!(cnt = rxcount())) { - }; + if ((len - FOOTER_LEN > bufsize) || + (len <= FOOTER_LEN)) { + goto error; } - while (rxcount() < FOOTER_LEN) { - }; - + getrxdata(buf, len - FOOTER_LEN); getrxdata(footer, FOOTER_LEN); + if (footer[1] & FOOTER1_CRC_OK) { cc2520_last_rssi = footer[0]; cc2520_last_correlation = footer[1] & FOOTER1_CORRELATION; } else { - DBG("RX: Bad CRC\n"); - print_exceptions_0(); - print_exceptions_1(); - - return -EINVAL; + goto error; } if (cc2520_pending_packet()) { - /* Clean up in case of FIFO overflow! - * This should not happen unless we were too slow to read - * the previous packet. This is signaled by: - * FIFOP = 1 and FIFO = 0 - */ if (!CC2520_FIFO_IS_1) { - DBG("RX: Overflow\n"); - print_exceptions_0(); + /* Clean up in case of FIFO overflow! This happens + * for every full length frame and is signaled by + * FIFOP = 1 and FIFO = 0 + */ flushrx(); + } else { + /* Another packet might be waiting + * Let's unlock reading_packet_fiber() + */ + nano_fiber_sem_give(&info->read_lock); } } - cc2520_packets_read++; + return len - FOOTER_LEN; - return pkt_len - FOOTER_LEN; +error: + print_exceptions_0(); + print_exceptions_1(); + print_errors(); + + flushrx(); + return -EINVAL; } static void read_packet(void) @@ -890,34 +891,35 @@ static void read_packet(void) struct net_buf *buf; int len; - do { - buf = l2_buf_get_reserve(0); - if (!buf) { - DBG("%s: Could not allocate buffer\n", __func__); - break; - } + buf = l2_buf_get_reserve(0); + if (!buf) { + DBG("%s: Could not allocate buffer\n", __func__); + return; + } - packetbuf_set_attr(buf, PACKETBUF_ATTR_TIMESTAMP, - last_packet_timestamp); + packetbuf_set_attr(buf, PACKETBUF_ATTR_TIMESTAMP, + last_packet_timestamp); - len = cc2520_read(packetbuf_dataptr(buf), PACKETBUF_SIZE); - if (len < 0) { - l2_buf_unref(buf); - break; - } + len = cc2520_read(packetbuf_dataptr(buf), PACKETBUF_SIZE); + if (len < 0) { + goto out; + } - packetbuf_set_attr(buf, PACKETBUF_ATTR_RSSI, cc2520_last_rssi); - packetbuf_set_attr(buf, PACKETBUF_ATTR_LINK_QUALITY, - cc2520_last_correlation); - packetbuf_set_datalen(buf, len); + packetbuf_set_attr(buf, PACKETBUF_ATTR_RSSI, cc2520_last_rssi); + packetbuf_set_attr(buf, PACKETBUF_ATTR_LINK_QUALITY, + cc2520_last_correlation); + packetbuf_set_datalen(buf, len); - if (net_driver_15_4_recv_from_hw(buf) < 0) { - l2_buf_unref(buf); - } + DBG("%s: received %d bytes\n", __func__, len); - last_packet_timestamp = cc2520_sfd_start_time; - cc2520_packets_seen++; - } while (len > 0); + if (net_driver_15_4_recv_from_hw(buf) < 0) { + DBG("%s: rdc input failed, packet discarded\n", __func__); + goto out; + } + + return; +out: + l2_buf_unref(buf); } /* Reading incoming packet, so through SPI, cannot be done directly @@ -937,6 +939,9 @@ static void reading_packet_fiber(int unused1, int unused2) read_packet(); cc2520_radio_unlock(); + last_packet_timestamp = cc2520_sfd_start_time; + cc2520_packets_seen++; + net_analyze_stack("CC2520 Rx Fiber stack", cc2520_read_stack, CC2520_READING_STACK_SIZE); } @@ -946,6 +951,8 @@ static void cc2520_gpio_int_handler(struct device *port, uint32_t pin) { struct cc2520_config *info = cc2520_sgl_dev->config->config_info; + DBG("%s: RX interrupt in pin %lu\n", __func__, pin); + /* In order to make this driver available for 2+ instances * it would require this handler to get access to the concerned * instance @@ -1140,7 +1147,7 @@ static void cc2520_configure(struct device *dev) /* Set auto CRC on frame. */ #if CC2520_CONF_AUTOACK setreg(CC2520_FRMCTRL0, AUTOCRC | AUTOACK); - setreg(CC2520_FRMFILT0, FRAME_MAX_VERSION | FRAME_FILTER_ENABLE); + setreg(CC2520_FRMFILT0, FRAME_MAX_VERSION|FRAME_FILTER_ENABLE); #else /* setreg(CC2520_FRMCTRL0, 0x60); */ setreg(CC2520_FRMCTRL0, AUTOCRC); @@ -1150,7 +1157,7 @@ static void cc2520_configure(struct device *dev) /* SET_RXENMASK_ON_TX */ setreg(CC2520_FRMCTRL1, 1); /* Set FIFOP threshold to maximum .*/ - setreg(CC2520_FIFOPCTRL, FIFOP_THR(MIN_LENGTH_BEFORE_ACCEPT)); + setreg(CC2520_FIFOPCTRL, FIFOP_THR(0x7F)); if (!cc2520_set_pan_addr(0xffff, 0x0000, NULL)) { return; -- cgit v1.2.3