1
0
mirror of git://projects.qi-hardware.com/ben-wpan.git synced 2024-11-26 04:56:16 +02:00

atusb/fw/mac.c: remove queued_rx; buffer frames in the MCU instead

queued_rx held a frame in the transceiver's receive buffer until we could
transfer it. This may cause frame loss if a new reception begins.

We now retrieve frames from the transceiver immediately and buffer them
in the MCU.
This commit is contained in:
Werner Almesberger 2013-07-24 07:57:35 -03:00
parent 6416fa8d0b
commit b73d5fc1af

View File

@ -22,15 +22,18 @@
#include "mac.h" #include "mac.h"
#define RX_BUFS 2
bool (*mac_irq)(void) = NULL; bool (*mac_irq)(void) = NULL;
static uint8_t rx_buf[MAX_PSDU+2]; /* PHDR+payload+LQ */ static uint8_t rx_buf[RX_BUFS][MAX_PSDU+2]; /* PHDR+payload+LQ */
static bool rx_in = 0, rx_out = 0;
static uint8_t tx_buf[MAX_PSDU]; static uint8_t tx_buf[MAX_PSDU];
static uint8_t tx_size = 0; static uint8_t tx_size = 0;
static bool txing = 0; static bool txing = 0;
static bool queued_tx_ack = 0; static bool queued_tx_ack = 0;
static bool queued_rx = 0;
static uint8_t next_seq, this_seq, queued_seq; static uint8_t next_seq, this_seq, queued_seq;
@ -62,27 +65,45 @@ static void reg_write(uint8_t reg, uint8_t value)
/* ----- Interrupt handling ------------------------------------------------ */ /* ----- Interrupt handling ------------------------------------------------ */
static void receive_frame(void); static void rx_done(void *user);
static void tx_ack_done(void *user);
static void usb_next(void)
{
const uint8_t *buf;
if (rx_in != rx_out) {
buf = rx_buf[rx_out];
led(1);
usb_send(&eps[1], buf, buf[0]+2, rx_done, NULL);
}
if (queued_tx_ack) {
usb_send(&eps[1], &queued_seq, 1, tx_ack_done, NULL);
queued_tx_ack = 0;
}
}
static void tx_ack_done(void *user)
{
usb_next();
}
static void rx_done(void *user) static void rx_done(void *user)
{ {
led(0); led(0);
if (queued_rx) { rx_out = (rx_out+1) & (RX_BUFS-1);
receive_frame(); usb_next();
queued_rx = 0;
return;
}
if (queued_tx_ack) {
usb_send(&eps[1], &queued_seq, 1, rx_done, NULL);
queued_tx_ack = 0;
}
} }
static void receive_frame(void) static void receive_frame(void)
{ {
uint8_t size, i; uint8_t size, i;
uint8_t *buf;
spi_begin(); spi_begin();
if (!(spi_io(AT86RF230_BUF_READ) & RX_CRC_VALID)) { if (!(spi_io(AT86RF230_BUF_READ) & RX_CRC_VALID)) {
@ -95,20 +116,16 @@ static void receive_frame(void)
return; return;
} }
rx_buf[0] = size; buf = rx_buf[rx_in];
for (i = 0; i != size+1; i++) for (i = 0; i != size+1; i++)
rx_buf[i+1] = spi_recv(); buf[i+1] = spi_recv();
spi_end(); spi_end();
led(1);
usb_send(&eps[1], rx_buf, size+2, rx_done, NULL);
}
buf[0] = size;
rx_in = (rx_in+1) & (RX_BUFS-1);
static void flush_queued_rx(void) if (eps[1].state == EP_IDLE)
{ usb_next();
if (queued_rx)
receive_frame();
queued_rx = 0;
} }
@ -122,7 +139,7 @@ static bool handle_irq(void)
if (txing) { if (txing) {
if (eps[1].state == EP_IDLE) { if (eps[1].state == EP_IDLE) {
usb_send(&eps[1], &this_seq, 1, rx_done, NULL); usb_send(&eps[1], &this_seq, 1, tx_ack_done, NULL);
} else { } else {
queued_tx_ack = 1; queued_tx_ack = 1;
queued_seq = this_seq; queued_seq = this_seq;
@ -131,13 +148,9 @@ static bool handle_irq(void)
return 1; return 1;
} }
/* unlikely */ /* likely */
if (eps[1].state != EP_IDLE) { if (eps[1].state == EP_IDLE || rx_in != rx_out)
queued_rx = 1; receive_frame();
return 1;
}
receive_frame();
return 1; return 1;
} }
@ -193,9 +206,7 @@ static void do_tx(void *user)
*/ */
reg_write(REG_TRX_STATE, TRX_CMD_FORCE_PLL_ON); reg_write(REG_TRX_STATE, TRX_CMD_FORCE_PLL_ON);
flush_queued_rx();
handle_irq(); handle_irq();
queued_rx = 0;
spi_begin(); spi_begin();
spi_send(AT86RF230_BUF_WRITE); spi_send(AT86RF230_BUF_WRITE);
@ -233,7 +244,7 @@ void mac_reset(void)
mac_irq = NULL; mac_irq = NULL;
txing = 0; txing = 0;
queued_tx_ack = 0; queued_tx_ack = 0;
queued_rx = 0; rx_in = rx_out = 0;
next_seq = this_seq = queued_seq = 0; next_seq = this_seq = queued_seq = 0;
/* enable CRC and PHY_RSSI (with RX_CRC_VALID) in SPI status return */ /* enable CRC and PHY_RSSI (with RX_CRC_VALID) in SPI status return */