summaryrefslogtreecommitdiff
path: root/src/ao_packet.c
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2010-11-26 16:14:15 -0800
committerKeith Packard <keithp@keithp.com>2010-12-22 20:39:40 -0800
commit07213dc34fa20470a4b36a327a83d75b0f010ebb (patch)
treea85d444ab7d2ccf01153c15e6fb2adf8473b602f /src/ao_packet.c
parentb62580855c5144f5bc7e0172289bce08814d9472 (diff)
altos: clean up radio abort paths. Share radio code.
Instead of aborting the DMA and radio operation and expecting that to be handled reasonably by the radio receiving task, rewrite things so that the abort function just wakes the receiving task while that terminates the DMA and cleans up the radio. This eliminates all kinds of nasty bugs dealing with radio abort smashing the radio registers at the wrong time, or interrupting a radio transmission. Signed-off-by: Keith Packard <keithp@keithp.com>
Diffstat (limited to 'src/ao_packet.c')
-rw-r--r--src/ao_packet.c98
1 files changed, 43 insertions, 55 deletions
diff --git a/src/ao_packet.c b/src/ao_packet.c
index d52f2a68..9896149c 100644
--- a/src/ao_packet.c
+++ b/src/ao_packet.c
@@ -33,8 +33,6 @@ void
ao_packet_send(void)
{
ao_led_on(AO_LED_RED);
- ao_radio_get();
-
/* If any tx data is pending then copy it into the tx packet */
if (ao_packet_tx_used && ao_tx_packet.len == 0) {
memcpy(&ao_tx_packet.d, tx_data, ao_packet_tx_used);
@@ -43,22 +41,7 @@ ao_packet_send(void)
ao_packet_tx_used = 0;
ao_wakeup(&tx_data);
}
- ao_radio_done = 0;
- ao_dma_set_transfer(ao_radio_dma,
- &ao_tx_packet,
- &RFDXADDR,
- sizeof (struct ao_packet),
- DMA_CFG0_WORDSIZE_8 |
- DMA_CFG0_TMODE_SINGLE |
- DMA_CFG0_TRIGGER_RADIO,
- DMA_CFG1_SRCINC_1 |
- DMA_CFG1_DESTINC_0 |
- DMA_CFG1_PRIORITY_HIGH);
- ao_dma_start(ao_radio_dma);
- RFST = RFST_STX;
- __critical while (!ao_radio_done)
- ao_sleep(&ao_radio_done);
- ao_radio_put();
+ ao_radio_send(&ao_tx_packet, sizeof (ao_tx_packet));
ao_led_off(AO_LED_RED);
}
@@ -70,51 +53,56 @@ ao_packet_recv(void)
#ifdef AO_LED_GREEN
ao_led_on(AO_LED_GREEN);
#endif
- ao_radio_get();
- ao_dma_set_transfer(ao_radio_dma,
- &RFDXADDR,
- &ao_rx_packet,
- sizeof (struct ao_packet_recv),
- DMA_CFG0_WORDSIZE_8 |
- DMA_CFG0_TMODE_SINGLE |
- DMA_CFG0_TRIGGER_RADIO,
- DMA_CFG1_SRCINC_0 |
- DMA_CFG1_DESTINC_1 |
- DMA_CFG1_PRIORITY_HIGH);
- ao_dma_start(ao_radio_dma);
- RFST = RFST_SRX;
- __critical while (!ao_radio_dma_done)
- if (ao_sleep(&ao_radio_dma_done) != 0)
- ao_radio_abort();
- dma_done = ao_radio_dma_done;
- ao_radio_put();
+ dma_done = ao_radio_recv(&ao_rx_packet, sizeof (struct ao_packet_recv));
#ifdef AO_LED_GREEN
ao_led_off(AO_LED_GREEN);
#endif
- if (dma_done & AO_DMA_DONE) {
- if (!(ao_rx_packet.status & PKT_APPEND_STATUS_1_CRC_OK))
- return AO_DMA_ABORTED;
- if (ao_rx_packet.packet.len == AO_PACKET_SYN) {
+ /* Check to see if we got a valid packet */
+ if (!dma_done)
+ return 0;
+ if (!(ao_rx_packet.status & PKT_APPEND_STATUS_1_CRC_OK))
+ return 0;
+
+ /* SYN packets carry no data */
+ if (ao_rx_packet.packet.len == AO_PACKET_SYN) {
+ rx_seq = ao_rx_packet.packet.seq;
+ ao_tx_packet.seq = ao_rx_packet.packet.ack;
+ ao_tx_packet.ack = rx_seq;
+ } else if (ao_rx_packet.packet.len) {
+
+ /* Check for incoming data at the next sequence and
+ * for an empty data buffer
+ */
+ if (ao_rx_packet.packet.seq == (uint8_t) (rx_seq + (uint8_t) 1) &&
+ ao_packet_rx_used == ao_packet_rx_len) {
+
+ /* Copy data to the receive data buffer and set up the
+ * offsets
+ */
+ memcpy(rx_data, ao_rx_packet.packet.d, ao_rx_packet.packet.len);
+ ao_packet_rx_used = 0;
+ ao_packet_rx_len = ao_rx_packet.packet.len;
+
+ /* Mark the sequence that we've received to
+ * let the sender know when we return a packet
+ */
rx_seq = ao_rx_packet.packet.seq;
- ao_tx_packet.seq = ao_rx_packet.packet.ack;
ao_tx_packet.ack = rx_seq;
- } else if (ao_rx_packet.packet.len) {
- if (ao_rx_packet.packet.seq == (uint8_t) (rx_seq + (uint8_t) 1) && ao_packet_rx_used == ao_packet_rx_len) {
- memcpy(rx_data, ao_rx_packet.packet.d, ao_rx_packet.packet.len);
- ao_packet_rx_used = 0;
- ao_packet_rx_len = ao_rx_packet.packet.len;
- rx_seq = ao_rx_packet.packet.seq;
- ao_tx_packet.ack = rx_seq;
- ao_wakeup(&ao_stdin_ready);
- }
- }
- if (ao_rx_packet.packet.ack == ao_tx_packet.seq) {
- ao_tx_packet.len = 0;
- ao_wakeup(&ao_tx_packet);
+
+ /* Poke anyone looking for received data */
+ ao_wakeup(&ao_stdin_ready);
}
}
- return dma_done;
+
+ /* If the other side has seen the latest data we queued,
+ * wake up any task waiting to send data and let them go again
+ */
+ if (ao_rx_packet.packet.ack == ao_tx_packet.seq) {
+ ao_tx_packet.len = 0;
+ ao_wakeup(&ao_tx_packet);
+ }
+ return 1;
}
#ifndef PACKET_HAS_MASTER