summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJukka Rissanen <jukka.rissanen@linux.intel.com>2016-03-01 14:17:13 +0200
committerJukka Rissanen <jukka.rissanen@linux.intel.com>2016-03-01 14:22:46 +0200
commitbf2c827dcf1389d5d92ab1d58e0a305db0dd5026 (patch)
treed163cd73b70ca995c1929000f20f2531cabc4a23
parent7795ec4435869175ec510857be51e8f0e38f4566 (diff)
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 <jukka.rissanen@linux.intel.com>
-rw-r--r--drivers/802.15.4/cc2520.c153
1 files 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;