Пример #1
0
/*---------------------------------------------------------------------------*/
static int
transmit(unsigned short payload_len)
{
  if(tx_in_progress) {
    return RADIO_TX_COLLISION;
  }
  tx_in_progress = 1;

  /* Energest */
  if(listen_on) {
    ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
  }
  ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);

  /* Transmit and wait */
  vMMAC_StartPhyTransmit(&tx_frame_buffer,
                         E_MMAC_TX_START_NOW |
                         (send_on_cca ? E_MMAC_TX_USE_CCA : E_MMAC_TX_NO_CCA));

  if(poll_mode) {
    BUSYWAIT_UNTIL(u32MMAC_PollInterruptSource(E_MMAC_INT_TX_COMPLETE), MAX_PACKET_DURATION);
  } else {
    if(in_ack_transmission) {
      /* as nested interupts are not possible, the tx flag will never be cleared */
      BUSYWAIT_UNTIL(FALSE, MAX_ACK_DURATION);
    } else {
      /* wait until the tx flag is cleared */
      BUSYWAIT_UNTIL(!tx_in_progress, MAX_PACKET_DURATION);
    }
  }

  /* Energest */
  ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
  if(listen_on) {
    ENERGEST_ON(ENERGEST_TYPE_LISTEN);
  }
  tx_in_progress = 0;

  /* Check error code */
  int ret;
  uint32_t tx_error = u32MMAC_GetTxErrors();
  if(tx_error == 0) {
    ret = RADIO_TX_OK;
    RIMESTATS_ADD(acktx);
  } else if(tx_error & E_MMAC_TXSTAT_ABORTED) {
    ret = RADIO_TX_ERR;
    RIMESTATS_ADD(sendingdrop);
  } else if(tx_error & E_MMAC_TXSTAT_CCA_BUSY) {
    ret = RADIO_TX_COLLISION;
    RIMESTATS_ADD(contentiondrop);
  } else if(tx_error & E_MMAC_TXSTAT_NO_ACK) {
    ret = RADIO_TX_NOACK;
    RIMESTATS_ADD(noacktx);
  } else {
    ret = RADIO_TX_ERR;
  }
  return ret;
}
Пример #2
0
/*---------------------------------------------------------------------------*/
static int
read(void *buf, unsigned short bufsize)
{
  int len = 0;
  uint16_t radio_last_rx_crc;
  uint8_t radio_last_rx_crc_ok = 1;

  len = input_frame_buffer->u8PayloadLength;

  if(len <= CHECKSUM_LEN) {
    input_frame_buffer->u8PayloadLength = 0;
    return 0;
  } else {
    len -= CHECKSUM_LEN;
    /* Check CRC */
#if CRC_SW
    uint16_t checksum = crc16_data(input_frame_buffer->uPayload.au8Byte, len, 0);
    radio_last_rx_crc =
      (uint16_t)(input_frame_buffer->uPayload.au8Byte[len + 1] << (uint16_t)8)
      | input_frame_buffer->uPayload.au8Byte[len];
    radio_last_rx_crc_ok = (checksum == radio_last_rx_crc);
    if(!radio_last_rx_crc_ok) {
      RIMESTATS_ADD(badcrc);
    }
#endif /* CRC_SW */
    if(radio_last_rx_crc_ok) {
      /* If we are in poll mode we need to check the frame here */
      if(poll_mode) {
        if(frame_filtering &&
           !is_packet_for_us(input_frame_buffer->uPayload.au8Byte, len, 0)) {
          len = 0;
        } else {
          read_last_rssi();
        }
      }
      if(len != 0) {
        bufsize = MIN(len, bufsize);
        memcpy(buf, input_frame_buffer->uPayload.au8Byte, bufsize);
        RIMESTATS_ADD(llrx);
        if(!poll_mode) {
          /* Not in poll mode: packetbuf should not be accessed in interrupt context */
          packetbuf_set_attr(PACKETBUF_ATTR_RSSI, radio_last_rssi);
          packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, radio_last_correlation);
        }
      }
    } else {
      len = 0;
    }
    /* Disable further read attempts */
    input_frame_buffer->u8PayloadLength = 0;
  }

  return len;
}
Пример #3
0
/*---------------------------------------------------------------------------*/
static int
prepare(const void *payload, unsigned short payload_len)
{
  uint8_t i;
  uint16_t checksum;

  RIMESTATS_ADD(lltx);

  if(tx_in_progress) {
    return 1;
  }
  if(payload_len > 127 || payload == NULL) {
    return 1;
  }
  /* Copy payload to (soft) Ttx buffer */
  memcpy(tx_frame_buffer.uPayload.au8Byte, payload, payload_len);
  i = payload_len;
#if CRC_SW
  /* Compute CRC */
  checksum = crc16_data(payload, payload_len, 0);
  tx_frame_buffer.uPayload.au8Byte[i++] = checksum;
  tx_frame_buffer.uPayload.au8Byte[i++] = (checksum >> 8) & 0xff;
  tx_frame_buffer.u8PayloadLength = payload_len + CHECKSUM_LEN;
#else
  tx_frame_buffer.u8PayloadLength = payload_len;
#endif

  return 0;
}
Пример #4
0
/*---------------------------------------------------------------------------*/
int
runicast_send(struct runicast_conn *c, const rimeaddr_t *receiver,
	      uint8_t max_retransmissions)
{
  int ret;
  if(runicast_is_transmitting(c)) {
    PRINTF("%d.%d: runicast: already transmitting\n",
        rimeaddr_node_addr.u8[0],rimeaddr_node_addr.u8[1]);
    return 0;
  }
  packetbuf_set_attr(PACKETBUF_ATTR_RELIABLE, 1);
  packetbuf_set_attr(PACKETBUF_ATTR_PACKET_TYPE, PACKETBUF_ATTR_PACKET_TYPE_DATA);
  packetbuf_set_attr(PACKETBUF_ATTR_PACKET_ID, c->sndnxt);
  packetbuf_set_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS, 3);
  c->max_rxmit = max_retransmissions;
  c->rxmit = 0;
  c->is_tx = 1;
  RIMESTATS_ADD(reliabletx);
  PRINTF("%d.%d: runicast: sending packet %d\n",
	 rimeaddr_node_addr.u8[0],rimeaddr_node_addr.u8[1],
	 c->sndnxt);
  ret = stunicast_send_stubborn(&c->c, receiver, REXMIT_TIME);
  if(!ret) {
    c->is_tx = 0;
  }
  return ret;
}
Пример #5
0
/*---------------------------------------------------------------------------*/
static int
cc2520_prepare(const void *payload, unsigned short payload_len)
{
  uint8_t total_len;
  GET_LOCK();

  PRINTF("cc2520: sending %d bytes\n", payload_len);
  /*int i;
  for(i = 0; i < payload_len;i++)
	  printf("%x",((uint8_t *) payload)[i]);
  printf("\n");*/
  RIMESTATS_ADD(lltx);

  /* Wait for any previous transmission to finish. */
  /*  while(status() & BV(CC2520_TX_ACTIVE));*/

  /* Write packet to TX FIFO. */
  strobe(CC2520_INS_SFLUSHTX);

  total_len = payload_len + FOOTER_LEN;
  CC2520_WRITE_FIFO_BUF(&total_len, 1);
  CC2520_WRITE_FIFO_BUF(payload, payload_len);

  RELEASE_LOCK();
  return 0;
}
Пример #6
0
/*---------------------------------------------------------------------------*/
static int
cc2420_prepare(const void *payload, unsigned short payload_len)
{
  uint8_t total_len;
#if CC2420_CONF_CHECKSUM
  uint16_t checksum;
#endif /* CC2420_CONF_CHECKSUM */
  GET_LOCK();

  PRINTF("cc2420: sending %d bytes\n", payload_len);

  RIMESTATS_ADD(lltx);

  /* Wait for any previous transmission to finish. */
  /*  while(status() & BV(CC2420_TX_ACTIVE));*/

  /* Write packet to TX FIFO. */
  strobe(CC2420_SFLUSHTX);

#if CC2420_CONF_CHECKSUM
  checksum = crc16_data(payload, payload_len, 0);
#endif /* CC2420_CONF_CHECKSUM */
  total_len = payload_len + AUX_LEN;
  CC2420_WRITE_FIFO_BUF(&total_len, 1);
  CC2420_WRITE_FIFO_BUF(payload, payload_len);
#if CC2420_CONF_CHECKSUM
  CC2420_WRITE_FIFO_BUF(&checksum, CHECKSUM_LEN);
#endif /* CC2420_CONF_CHECKSUM */

  RELEASE_LOCK();
  return 0;
}
Пример #7
0
void uwb_dma_interrupt(void)
{
  /* DMA transaction finished */
  if (uwb_fsm == UWB_STATE_RX_LEN_DOWNLOAD)
  {
    /* we downloaded the frame length - now download the frame! */
    if (ram_rx_buffer[2] > 0)
    {
      ram_tx_buffer[0] = CMD_READ_RAM_RX;
      hal_spi_dma_transfer(ram_tx_buffer, ram_rx_buffer, ram_rx_buffer[2]+3);
      uwb_fsm = UWB_STATE_RX_FRAME_DOWNLOAD;
    }
    else
    {
      /* directly poll process to handle zero-length frame */
      process_poll(&uwb_process);
      RIMESTATS_ADD(llrx);
      uwb_fsm = UWB_STATE_RX_PROCESS_POLLED;
    }
  }
  else if (uwb_fsm == UWB_STATE_RX_FRAME_DOWNLOAD)
  {
    /* download complete, poll process */
    process_poll(&uwb_process);
    RIMESTATS_ADD(llrx);
    uwb_fsm = UWB_STATE_RX_PROCESS_POLLED;
  }
  else if (uwb_fsm == USB_STATE_TX_FRAME_UPLOAD)
  {
    /* tx frame uploaded, move back to listen state */
    /* here we could also implement a mechanism that starts the tx by sending config right away */
    uwb_fsm = UWB_STATE_LISTEN;
//    PRINTF("d1");
  }
  else if (uwb_fsm == USB_STATE_TX_CONFIG_UPLOAD)
  {
    /* tx config uploaded, assume the phy is transmitting now */
    uwb_fsm = USB_STATE_TX_ACTIVE;
    /* enable tx-int */
    HAL_ENABLE_IRQ1( );
//    PRINTF("d2");
  }
}
Пример #8
0
/*---------------------------------------------------------------------------*/
int
rime_output(struct channel *c)
{
  RIMESTATS_ADD(tx);
  if(chameleon_create(c)) {
    packetbuf_compact();

    NETSTACK_MAC.send(packet_sent, c);
    return 1;
  }
  return 0;
}
Пример #9
0
/*---------------------------------------------------------------------------*/
static void
sent_by_stunicast(struct stunicast_conn *stunicast, int status, int num_tx)
{
  struct runicast_conn *c = (struct runicast_conn *)stunicast;

  PRINTF("runicast: sent_by_stunicast c->rxmit %d num_tx %d\n",
         c->rxmit, num_tx);

  /* Only process data packets, not ACKs. */
  if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) == PACKETBUF_ATTR_PACKET_TYPE_DATA) {
    
    c->rxmit += 1;
    
    if(c->rxmit != 0) {
      RIMESTATS_ADD(rexmit);
      PRINTF("%d.%d: runicast: sent_by_stunicast packet %u (%u) resent %u\n",
             rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
             packetbuf_attr(PACKETBUF_ATTR_PACKET_ID),
             c->sndnxt, c->rxmit);
    }
    if(c->rxmit >= c->max_rxmit) {
      RIMESTATS_ADD(timedout);
      c->is_tx = 0;
      stunicast_cancel(&c->c);
      if(c->u->timedout) {
        c->u->timedout(c, stunicast_receiver(&c->c), c->rxmit);
      }
      c->rxmit = 0;
      PRINTF("%d.%d: runicast: packet %d timed out\n",
             rimeaddr_node_addr.u8[0],rimeaddr_node_addr.u8[1],
             c->sndnxt);
      c->sndnxt = (c->sndnxt + 1) % (1 << RUNICAST_PACKET_ID_BITS);
    } else {
//      int shift;
      
//      shift = c->rxmit > 4? 4: c->rxmit;
//      stunicast_set_timer(&c->c, (REXMIT_TIME) << shift);
    }
  }
}
Пример #10
0
static int
qsend_packet(void)
{
  if(someone_is_sending) {
    PRINTF("xmac: should queue packet, now just dropping %d %d %d %d.\n",
	   waiting_for_packet, someone_is_sending, we_are_sending, radio_is_on);
    if(queued_packet != NULL) {
      RIMESTATS_ADD(sendingdrop);
      return 0;
    } else {
#if WITH_QUEUE
      queued_packet = queuebuf_new_from_rimebuf();
      return 1;
#else
      RIMESTATS_ADD(sendingdrop);
      return 0;
#endif
    }
  } else {
    PRINTF("xmac: send immediately.\n");
    return send_packet();
  }

}
Пример #11
0
/*---------------------------------------------------------------------------*/
static void
input(const struct mac_driver *r)
{
  int len;
  struct rime_sniffer *s;
  len = rime_mac->read();
  if(len > 0) {
    for(s = list_head(sniffers); s != NULL; s = s->next) {
      if(s->input_callback != NULL) {
	s->input_callback();
      }
    }
    RIMESTATS_ADD(rx);
    chameleon_input();
  }
}
Пример #12
0
/*---------------------------------------------------------------------------*/
static void
qsend_packet(mac_callback_t sent, void *ptr)
{
  int ret;
  if(someone_is_sending) {
    PRINTF("cxmac: should queue packet, now just dropping %d %d %d %d.\n",
	   waiting_for_packet, someone_is_sending, we_are_sending, radio_is_on);
    RIMESTATS_ADD(sendingdrop);
    ret = MAC_TX_COLLISION;
  } else {
    PRINTF("cxmac: send immediately.\n");
    ret = send_packet();
  }

  mac_call_sent_callback(sent, ptr, ret, 1);
}
Пример #13
0
/*---------------------------------------------------------------------------*/
static int
radio_read(void *buf, unsigned short bufsize)
{
  int tmp = simInSize;

  if (simInSize == 0) {
    return 0;
  }
  if(bufsize < simInSize) {
    simInSize = 0; /* rx flush */
    RIMESTATS_ADD(toolong);
    return 0;
  }

  memcpy(buf, simInDataBuffer, simInSize);
  simInSize = 0;
  return tmp;
}
Пример #14
0
/*---------------------------------------------------------------------------*/
static void
input(void)
{
  struct rime_sniffer *s;
  struct channel *c;

  RIMESTATS_ADD(rx);
  c = chameleon_parse();
  
  for(s = list_head(sniffers); s != NULL; s = list_item_next(s)) {
    if(s->input_callback != NULL) {
      s->input_callback();
    }
  }
  
  if(c != NULL) {
    abc_input(c);
  }
}
Пример #15
0
/*---------------------------------------------------------------------------*/
void
rime_output(void)
{
  struct rime_sniffer *s;
    
  RIMESTATS_ADD(tx);
  packetbuf_compact();

  if(rime_mac) {
    if(rime_mac->send()) {
      /* Call sniffers, but only if the packet was sent. */
      for(s = list_head(sniffers); s != NULL; s = s->next) {
	if(s->output_callback != NULL) {
	  s->output_callback();
	}
      }
    }
  }
}
Пример #16
0
/*---------------------------------------------------------------------------*/
static int
send_one_packet(mac_callback_t sent, void *ptr)
{
	int ret;
	int last_sent_ok = 0;

	packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &linkaddr_node_addr);
#if DISCOVERY_AWARE_RDC_802154_AUTOACK || DISCOVERY_AWARE_RDC_802154_AUTOACK_HW
	packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1);
#endif /* DISCOVERY_AWARE_RDC_802154_AUTOACK || DISCOVERY_AWARE_RDC_802154_AUTOACK_HW */

	if (!radio_status) {
		on();
	}


	if(NETSTACK_FRAMER.create() < 0) {
		/* Failed to allocate space for headers */
	    PRINTF("RDC: send failed, too large header\n");
		ret = MAC_TX_ERR_FATAL;
	} else {

#ifdef NETSTACK_ENCRYPT
		NETSTACK_ENCRYPT();
#endif /* NETSTACK_ENCRYPT */

#if DISCOVERY_AWARE_RDC_802154_AUTOACK
		int is_broadcast;
		uint8_t dsn;
		dsn = ((uint8_t *)packetbuf_hdrptr())[2] & 0xff;

		NETSTACK_RADIO.prepare(packetbuf_hdrptr(), packetbuf_totlen());

		is_broadcast = linkaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
				&linkaddr_null);

		if(NETSTACK_RADIO.receiving_packet() ||
				(!is_broadcast && NETSTACK_RADIO.pending_packet())) {

			/* Currently receiving a packet over air or the radio has
         already received a packet that needs to be read before
         sending with auto ack. */
			ret = MAC_TX_COLLISION;

		} else {
  		  if(!is_broadcast) {
			RIMESTATS_ADD(reliabletx);
		  }

			switch(NETSTACK_RADIO.transmit(packetbuf_totlen())) {
			case RADIO_TX_OK:
				if(is_broadcast) {
					ret = MAC_TX_OK;
				} else {
					rtimer_clock_t wt;

					/* Check for ack */
					wt = RTIMER_NOW();
					watchdog_periodic();
					while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + ACK_WAIT_TIME)) {
#if CONTIKI_TARGET_COOJA
						simProcessRunValue = 1;
						cooja_mt_yield();
#endif /* CONTIKI_TARGET_COOJA */
					}

					ret = MAC_TX_NOACK;
					if(NETSTACK_RADIO.receiving_packet() ||
							NETSTACK_RADIO.pending_packet() ||
							NETSTACK_RADIO.channel_clear() == 0) {
						int len;
						uint8_t ackbuf[ACK_LEN];

						if(AFTER_ACK_DETECTED_WAIT_TIME > 0) {
							wt = RTIMER_NOW();
							watchdog_periodic();
							while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + AFTER_ACK_DETECTED_WAIT_TIME)) {
#if CONTIKI_TARGET_COOJA
								simProcessRunValue = 1;
								cooja_mt_yield();
#endif /* CONTIKI_TARGET_COOJA */
							}
						}

						if(NETSTACK_RADIO.pending_packet()) {
							len = NETSTACK_RADIO.read(ackbuf, ACK_LEN);
							if(len == ACK_LEN && ackbuf[2] == dsn) {
								/* Ack received */
								RIMESTATS_ADD(ackrx);
								ret = MAC_TX_OK;
							} else {
								/* Not an ack or ack not for us: collision */
								ret = MAC_TX_COLLISION;
							}
						}
					} else {
						PRINTF("RDC tx noack\n");
					}
				}
				break;
			case RADIO_TX_COLLISION:
				ret = MAC_TX_COLLISION;
				break;
			default:
				ret = MAC_TX_ERR;
				break;
			}
		}

#else /* ! DISCOVERY_AWARE_RDC_802154_AUTOACK */

		switch(NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen())) {
		case RADIO_TX_OK:
			ret = MAC_TX_OK;
			break;
		case RADIO_TX_COLLISION:
			ret = MAC_TX_COLLISION;
			break;
		case RADIO_TX_NOACK:
			ret = MAC_TX_NOACK;
			break;
		default:
			ret = MAC_TX_ERR;
			break;
		}

#endif /* ! DISCOVERY_AWARE_RDC_802154_AUTOACK */
	}



	if (!linkaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &linkaddr_null)
			&&  ret == MAC_TX_OK) {
		send_flag = 1;
		to_modifier+=10;
	}

	if(ret == MAC_TX_OK) {
		last_sent_ok = 1;
	}

	mac_call_sent_callback(sent, ptr, ret, 1);

	return last_sent_ok;
}
Пример #17
0
/*---------------------------------------------------------------------------*/
static void
radio_interrupt_handler(uint32 mac_event)
{
  uint32_t rx_status;
  uint8_t overflow = 0;
  int get_index;
  int put_index;
  int packet_for_me = 0;

  if(mac_event & E_MMAC_INT_TX_COMPLETE) {
    /* Transmission attempt has finished */
    tx_in_progress = 0;
  } else if(mac_event & E_MMAC_INT_RX_COMPLETE) {
    rx_status = u32MMAC_GetRxErrors();
    /* If rx is successful */
    if(rx_status == 0) {
      /* Save SFD timestamp */
      last_packet_timestamp = get_packet_timestamp();

      if(!poll_mode && (mac_event & E_MMAC_INT_RX_COMPLETE)) {
        if(rx_frame_buffer->u8PayloadLength > CHECKSUM_LEN) {
          if(frame_filtering) {
            /* Check RX address */
            packet_for_me = is_packet_for_us(rx_frame_buffer->uPayload.au8Byte, rx_frame_buffer->u8PayloadLength - CHECKSUM_LEN, 1);
          } else if(!frame_filtering) {
            packet_for_me = 1;
          }
        }
        if(!packet_for_me) {
          /* Prevent reading */
          rx_frame_buffer->u8PayloadLength = 0;
        } else {
          /* read and cache RSSI and LQI values */
          read_last_rssi();
          /* Put received frame in queue */
          ringbufindex_put(&input_ringbuf);

          if((get_index = ringbufindex_peek_get(&input_ringbuf)) != -1) {
            input_frame_buffer = &input_array[get_index];
          }
          process_poll(&micromac_radio_process);

          /* get pointer to next input slot */
          put_index = ringbufindex_peek_put(&input_ringbuf);
          /* is there space? */
          if(put_index != -1) {
            /* move rx_frame_buffer to next empty slot */
            rx_frame_buffer = &input_array[put_index];
          } else {
            overflow = 1;
            rx_frame_buffer = NULL;
          }
        }
      }
    } else { /* if rx is not successful */
      if(rx_status & E_MMAC_RXSTAT_ABORTED) {
        RIMESTATS_ADD(badsynch);
      } else if(rx_status & E_MMAC_RXSTAT_ERROR) {
        RIMESTATS_ADD(badcrc);
      } else if(rx_status & E_MMAC_RXSTAT_MALFORMED) {
        RIMESTATS_ADD(toolong);
      }
    }
  }
  if(overflow) {
    off();
  } else if(MICROMAC_CONF_ALWAYS_ON
            && (mac_event & (E_MMAC_INT_TX_COMPLETE | E_MMAC_INT_RX_COMPLETE))) {
    on();
  }
}
Пример #18
0
/*---------------------------------------------------------------------------*/
static int
cc2420_transmit(unsigned short payload_len)
{
  int i, txpower;
  uint8_t total_len;
#if CC2420_CONF_CHECKSUM
  uint16_t checksum;
#endif /* CC2420_CONF_CHECKSUM */

  GET_LOCK();

  txpower = 0;
  if(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) > 0) {
    /* Remember the current transmission power */
    txpower = cc2420_get_txpower();
    /* Set the specified transmission power */
    set_txpower(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) - 1);
  }

  total_len = payload_len + AUX_LEN;
  
  /* The TX FIFO can only hold one packet. Make sure to not overrun
   * FIFO by waiting for transmission to start here and synchronizing
   * with the CC2420_TX_ACTIVE check in cc2420_send.
   *
   * Note that we may have to wait up to 320 us (20 symbols) before
   * transmission starts.
   */
#ifdef TMOTE_SKY
#define LOOP_20_SYMBOLS 400	/* 326us (msp430 @ 2.4576MHz) */
#elif __AVR__
#define LOOP_20_SYMBOLS 500	/* XXX */
#endif

#if WITH_SEND_CCA
  strobe(CC2420_SRXON);
  while(!(status() & BV(CC2420_RSSI_VALID)));
  strobe(CC2420_STXONCCA);
#else /* WITH_SEND_CCA */
  strobe(CC2420_STXON);
#endif /* WITH_SEND_CCA */

  for(i = LOOP_20_SYMBOLS; i > 0; i--) {
    if(SFD_IS_1) {
      if(!(status() & BV(CC2420_TX_ACTIVE))) {
        /* SFD went high but we are not transmitting. This means that
           we just started receiving a packet, so we drop the
           transmission. */
        return RADIO_TX_ERR;
      }
      if(receive_on) {
	ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
      }
      ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);

      /* We wait until transmission has ended so that we get an
	 accurate measurement of the transmission time.*/
      while(status() & BV(CC2420_TX_ACTIVE));


#ifdef ENERGEST_CONF_LEVELDEVICE_LEVELS
      ENERGEST_OFF_LEVEL(ENERGEST_TYPE_TRANSMIT,cc2420_get_txpower());
#endif
      ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
      if(receive_on) {
	ENERGEST_ON(ENERGEST_TYPE_LISTEN);
      } else {
	/* We need to explicitly turn off the radio,
	 * since STXON[CCA] -> TX_ACTIVE -> RX_ACTIVE */
	off();
      }

      if(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) > 0) {
        /* Restore the transmission power */
        set_txpower(txpower & 0xff);
      }

      RELEASE_LOCK();
      return RADIO_TX_OK;
    }
  }

  /* If we are using WITH_SEND_CCA, we get here if the packet wasn't
     transmitted because of other channel activity. */
  RIMESTATS_ADD(contentiondrop);
  PRINTF("cc2420: do_send() transmission never started\n");

  if(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) > 0) {
    /* Restore the transmission power */
    set_txpower(txpower & 0xff);
  }

  RELEASE_LOCK();
  return RADIO_TX_ERR;			/* Transmission never started! */
}
Пример #19
0
/*---------------------------------------------------------------------------*/
static int
read(void *buf, unsigned short bufsize)
{
  uint8_t i;
  uint8_t len;
  uint8_t crc_corr;
  int8_t rssi;

  PRINTF("RF: Read\n");

  if((REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_FIFOP) == 0) {
    return 0;
  }

  /* Check the length */
  len = REG(RFCORE_SFR_RFDATA);

  /* Check for validity */
  if(len > CC2538_RF_MAX_PACKET_LEN) {
    /* Oops, we must be out of sync. */
    PRINTF("RF: bad sync\n");

    RIMESTATS_ADD(badsynch);
    CC2538_RF_CSP_ISFLUSHRX();
    return 0;
  }

  if(len <= CC2538_RF_MIN_PACKET_LEN) {
    PRINTF("RF: too short\n");

    RIMESTATS_ADD(tooshort);
    CC2538_RF_CSP_ISFLUSHRX();
    return 0;
  }

  if(len - CHECKSUM_LEN > bufsize) {
    PRINTF("RF: too long\n");

    RIMESTATS_ADD(toolong);
    CC2538_RF_CSP_ISFLUSHRX();
    return 0;
  }

  /* If we reach here, chances are the FIFO is holding a valid frame */
  PRINTF("RF: read (0x%02x bytes) = ", len);
  len -= CHECKSUM_LEN;

  /* Don't bother with uDMA for short frames (e.g. ACKs) */
  if(CC2538_RF_CONF_RX_USE_DMA && len > UDMA_RX_SIZE_THRESHOLD) {
    PRINTF("<uDMA payload>");

    /* Set the transfer destination's end address */
    udma_set_channel_dst(CC2538_RF_CONF_RX_DMA_CHAN,
                         (uint32_t)(buf) + len - 1);

    /* Configure the control word */
    udma_set_channel_control_word(CC2538_RF_CONF_RX_DMA_CHAN,
                                  UDMA_RX_FLAGS | udma_xfer_size(len));

    /* Enabled the RF RX uDMA channel */
    udma_channel_enable(CC2538_RF_CONF_RX_DMA_CHAN);

    /* Trigger the uDMA transfer */
    udma_channel_sw_request(CC2538_RF_CONF_RX_DMA_CHAN);

    /* Wait for the transfer to complete. */
    while(udma_channel_get_mode(CC2538_RF_CONF_RX_DMA_CHAN));
  } else {
    for(i = 0; i < len; ++i) {
      ((unsigned char *)(buf))[i] = REG(RFCORE_SFR_RFDATA);
      PRINTF("%02x", ((unsigned char *)(buf))[i]);
    }
  }

  /* Read the RSSI and CRC/Corr bytes */
  rssi = ((int8_t)REG(RFCORE_SFR_RFDATA)) - RSSI_OFFSET;
  crc_corr = REG(RFCORE_SFR_RFDATA);

  PRINTF("%02x%02x\n", (uint8_t)rssi, crc_corr);

  /* MS bit CRC OK/Not OK, 7 LS Bits, Correlation value */
  if(crc_corr & CRC_BIT_MASK) {
    packetbuf_set_attr(PACKETBUF_ATTR_RSSI, rssi);
    packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, crc_corr & LQI_BIT_MASK);
    RIMESTATS_ADD(llrx);
  } else {
    RIMESTATS_ADD(badcrc);
    PRINTF("RF: Bad CRC\n");
    CC2538_RF_CSP_ISFLUSHRX();
    return 0;
  }

#if CC2538_RF_CONF_SNIFFER
  write_byte(magic[0]);
  write_byte(magic[1]);
  write_byte(magic[2]);
  write_byte(magic[3]);
  write_byte(len + 2);
  for(i = 0; i < len; ++i) {
    write_byte(((unsigned char *)(buf))[i]);
  }
  write_byte(rssi);
  write_byte(crc_corr);
  flush();
#endif

  /* If FIFOP==1 and FIFO==0 then we had a FIFO overflow at some point. */
  if(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_FIFOP) {
    if(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_FIFO) {
      process_poll(&cc2538_rf_process);
    } else {
      CC2538_RF_CSP_ISFLUSHRX();
    }
  }

  return (len);
}
Пример #20
0
/*---------------------------------------------------------------------------*/
static int
cc2420_read(void *buf, unsigned short bufsize)
{
  uint8_t footer[2];
  uint8_t len;
#if CC2420_CONF_CHECKSUM
  uint16_t checksum;
#endif /* CC2420_CONF_CHECKSUM */

  if(!CC2420_FIFOP_IS_1) {
    return 0;
  }
  /*  if(!pending) {
    return 0;
    }*/
  
  pending = 0;
  
  GET_LOCK();

  cc2420_packets_read++;

  getrxbyte(&len);

  if(len > CC2420_MAX_PACKET_LEN) {
    /* Oops, we must be out of sync. */
    flushrx();
    RIMESTATS_ADD(badsynch);
    RELEASE_LOCK();
    return 0;
  }

  if(len <= AUX_LEN) {
    flushrx();
    RIMESTATS_ADD(tooshort);
    RELEASE_LOCK();
    return 0;
  }

  if(len - AUX_LEN > bufsize) {
    flushrx();
    RIMESTATS_ADD(toolong);
    RELEASE_LOCK();
    return 0;
  }

  getrxdata(buf, len - AUX_LEN);
#if CC2420_CONF_CHECKSUM
  getrxdata(&checksum, CHECKSUM_LEN);
#endif /* CC2420_CONF_CHECKSUM */
  getrxdata(footer, FOOTER_LEN);

#if CC2420_CONF_CHECKSUM
  if(checksum != crc16_data(buf, len - AUX_LEN, 0)) {
    PRINTF("checksum failed 0x%04x != 0x%04x\n",
	   checksum, crc16_data(buf, len - AUX_LEN, 0));
  }

  if(footer[1] & FOOTER1_CRC_OK &&
     checksum == crc16_data(buf, len - AUX_LEN, 0)) {
#else
  if(footer[1] & FOOTER1_CRC_OK) {
#endif /* CC2420_CONF_CHECKSUM */
    cc2420_last_rssi = footer[0];
    cc2420_last_correlation = footer[1] & FOOTER1_CORRELATION;


    packetbuf_set_attr(PACKETBUF_ATTR_RSSI, cc2420_last_rssi);
    packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, cc2420_last_correlation);

    RIMESTATS_ADD(llrx);

  } else {
    RIMESTATS_ADD(badcrc);
    len = AUX_LEN;
  }

  if(CC2420_FIFOP_IS_1) {
    if(!CC2420_FIFO_IS_1) {
      /* 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 has been received and needs attention. */
      process_poll(&cc2420_process);
    }
  }

  RELEASE_LOCK();

  if(len < AUX_LEN) {
    return 0;
  }

  return len - AUX_LEN;
}
/*---------------------------------------------------------------------------*/
void
cc2420_set_txpower(uint8_t power)
{
  GET_LOCK();
  set_txpower(power);
  RELEASE_LOCK();
}
Пример #21
0
/*---------------------------------------------------------------------------*/
static int
send_one_packet(struct net_buf *buf, mac_callback_t sent, void *ptr)
{
  int ret;
  int last_sent_ok = 0;
#if NULLRDC_ENABLE_RETRANSMISSIONS
  rtimer_clock_t target_time;
  uint8_t tx_attempts = 0;
  uint8_t max_tx_attempts;

  if(packetbuf_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS) > 0) {
    max_tx_attempts = packetbuf_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS);
  } else {
    max_tx_attempts = NULLRDC_MAX_RETRANSMISSIONS + 1;
  }
#endif /* NULLRDC_ENABLE_RETRANSMISSIONS */

  packetbuf_set_addr(buf, PACKETBUF_ADDR_SENDER, &linkaddr_node_addr);
#if NULLRDC_802154_AUTOACK || NULLRDC_802154_AUTOACK_HW
  packetbuf_set_attr(buf, PACKETBUF_ATTR_MAC_ACK, 1);
#endif /* NULLRDC_802154_AUTOACK || NULLRDC_802154_AUTOACK_HW */

  if(NETSTACK_FRAMER.create_and_secure(buf) < 0) {
    /* Failed to allocate space for headers */
    PRINTF("nullrdc: send failed, too large header\n");
    ret = MAC_TX_ERR_FATAL;
  } else {
#if NULLRDC_802154_AUTOACK
    int is_broadcast;
    uint8_t dsn;
    dsn = ((uint8_t *)packetbuf_hdrptr())[2] & 0xff;

    NETSTACK_RADIO.prepare(packetbuf_hdrptr(), packetbuf_totlen());

    is_broadcast = packetbuf_holds_broadcast();

    if(NETSTACK_RADIO.receiving_packet() ||
       (!is_broadcast && NETSTACK_RADIO.pending_packet())) {

      /* Currently receiving a packet over air or the radio has
         already received a packet that needs to be read before
         sending with auto ack. */
      ret = MAC_TX_COLLISION;
    } else {
      if(!is_broadcast) {
        RIMESTATS_ADD(reliabletx);
      }
#if NULLRDC_ENABLE_RETRANSMISSIONS
  while(1) {
    /* Transmit packet and check status */
    tx_attempts++;
#endif /* NULLRDC_ENABLE_RETRANSMISSIONS */

      switch(NETSTACK_RADIO.transmit(packetbuf_totlen(buf))) {
      case RADIO_TX_OK:
        if(is_broadcast) {
          ret = MAC_TX_OK;
        } else {
          rtimer_clock_t wt;

          /* Check for ack */
          wt = RTIMER_NOW();
          watchdog_periodic();
          while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + ACK_WAIT_TIME)) {
#if CONTIKI_TARGET_COOJA
            simProcessRunValue = 1;
            cooja_mt_yield();
#endif /* CONTIKI_TARGET_COOJA */
          }

          ret = MAC_TX_NOACK;
          if(NETSTACK_RADIO.receiving_packet() ||
             NETSTACK_RADIO.pending_packet() ||
             NETSTACK_RADIO.channel_clear() == 0) {
            int len;
            uint8_t ackbuf[ACK_LEN];

            if(AFTER_ACK_DETECTED_WAIT_TIME > 0) {
              wt = RTIMER_NOW();
              watchdog_periodic();
              while(RTIMER_CLOCK_LT(RTIMER_NOW(),
                                    wt + AFTER_ACK_DETECTED_WAIT_TIME)) {
      #if CONTIKI_TARGET_COOJA
                  simProcessRunValue = 1;
                  cooja_mt_yield();
      #endif /* CONTIKI_TARGET_COOJA */
              }
            }

            if(NETSTACK_RADIO.pending_packet()) {
              len = NETSTACK_RADIO.read(ackbuf, ACK_LEN);
              if(len == ACK_LEN && ackbuf[2] == dsn) {
                /* Ack received */
                RIMESTATS_ADD(ackrx);
                ret = MAC_TX_OK;
              } else {
                /* Not an ack or ack not for us: collision */
                ret = MAC_TX_COLLISION;
              }
            }
          } else {
	    PRINTF("nullrdc tx noack\n");
	  }
        }
        break;
      case RADIO_TX_COLLISION:
        ret = MAC_TX_COLLISION;
        break;
      default:
        ret = MAC_TX_ERR;
        break;
      }
#if NULLRDC_ENABLE_RETRANSMISSIONS
    if(is_broadcast) {
#if !NULLRDC_ENABLE_RETRANSMISSIONS_BCAST
      break;
#else  /* NULLRDC_ENABLE_RETRANSMISSIONS_BCAST */
      if(ret != MAC_TX_COLLISION) {
        /* Retry broadcast frame only upon collision */
        break;
      }
#endif /* NULLRDC_ENABLE_RETRANSMISSIONS_BCAST */
    } else {
      /* Frame is unicast. Do not retry unless NO_ACK or COLLISION */
      if((ret != MAC_TX_NOACK) && (ret != MAC_TX_COLLISION)) {
        break;
      }
    }
    /* Do not retry if max attempts reached. */
    if(tx_attempts >= max_tx_attempts) {
      PRINTF("nullrdc: max tx attempts reached\n");
      break;
    }
    /* Block-wait before retrying the frame. */
    target_time = RTIMER_NOW() +
      (RTIMER_SECOND * NULLRDC_TX_RETRY_DELAY_MS / 1000);
    watchdog_periodic();
    while(RTIMER_CLOCK_LT(RTIMER_NOW(), target_time)) {
      /* Wait */
    }
    /* Attempt a new frame (re)transmission */
  }
#endif /* NULLRDC_ENABLE_RETRANSMISSIONS */
    }

#else /* ! NULLRDC_802154_AUTOACK */

    switch(NETSTACK_RADIO.send(buf, packetbuf_hdrptr(buf), packetbuf_totlen(buf))) {
    case RADIO_TX_OK:
      ret = MAC_TX_OK;
      break;
    case RADIO_TX_COLLISION:
      ret = MAC_TX_COLLISION;
      break;
    case RADIO_TX_NOACK:
      ret = MAC_TX_NOACK;
      break;
    default:
      ret = MAC_TX_ERR;
      break;
    }

#endif /* ! NULLRDC_802154_AUTOACK */
  }
  if(ret == MAC_TX_OK) {
    last_sent_ok = 1;
  }
#if ! NULLRDC_ENABLE_RETRANSMISSIONS
  mac_call_sent_callback(buf, sent, ptr, ret, 1);
#else
  mac_call_sent_callback(buf, sent, ptr, ret, tx_attempts);
#endif /* !NULLRDC_ENABLE_RETRANSMISSIONS */
  return last_sent_ok;
}
Пример #22
0
/*---------------------------------------------------------------------------*/
static int
transmit(unsigned short transmit_len)
{
  uint8_t counter;
  int ret = RADIO_TX_ERR;
  rtimer_clock_t t0;
  transmit_len; /* hush the warning */

  if(!(rf_flags & RX_ACTIVE)) {
    t0 = RTIMER_NOW();
    on();
    rf_flags |= WAS_OFF;
    while (RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + ONOFF_TIME));
  }

  if(channel_clear() == CC2530_RF_CCA_BUSY) {
    RIMESTATS_ADD(contentiondrop);
    return RADIO_TX_COLLISION;
  }

  /*
   * prepare() double checked that TX_ACTIVE is low. If SFD is high we are
   * receiving. Abort transmission and bail out with RADIO_TX_COLLISION
   */
  if(FSMSTAT1 & FSMSTAT1_SFD) {
    RIMESTATS_ADD(contentiondrop);
    return RADIO_TX_COLLISION;
  }

  /* Start the transmission */
  RF_TX_LED_ON();
  ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
  ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);

  CC2530_CSP_ISTXON();

  counter = 0;
  while(!(FSMSTAT1 & FSMSTAT1_TX_ACTIVE) && (counter++ < 3)) {
    clock_delay_usec(6);
  }

  if(!(FSMSTAT1 & FSMSTAT1_TX_ACTIVE)) {
    PUTSTRING("RF: TX never active.\n");
    CC2530_CSP_ISFLUSHTX();
    ret = RADIO_TX_ERR;
  } else {
    /* Wait for the transmission to finish */
    while(FSMSTAT1 & FSMSTAT1_TX_ACTIVE);
    ret = RADIO_TX_OK;
  }
  ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
  ENERGEST_ON(ENERGEST_TYPE_LISTEN);

  if(rf_flags & WAS_OFF){
    off();
  }

  RIMESTATS_ADD(lltx);

  RF_TX_LED_OFF();

  /* OK, sent. We are now ready to send more */
  return ret;
}
Пример #23
0
/*---------------------------------------------------------------------------*/
static int
cc2520_transmit(unsigned short payload_len)
{
  int i, txpower;

  GET_LOCK();

  txpower = 0;
  if(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) > 0) {
    /* Remember the current transmission power */
    txpower = cc2520_get_txpower();
    /* Set the specified transmission power */
    set_txpower(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) - 1);
  }

  /* The TX FIFO can only hold one packet. Make sure to not overrun
   * FIFO by waiting for transmission to start here and synchronizing
   * with the CC2520_TX_ACTIVE check in cc2520_send.
   *
   * Note that we may have to wait up to 320 us (20 symbols) before
   * transmission starts.
   */
#ifndef CC2520_CONF_SYMBOL_LOOP_COUNT
#error CC2520_CONF_SYMBOL_LOOP_COUNT needs to be set!!!
#else
#define LOOP_20_SYMBOLS CC2520_CONF_SYMBOL_LOOP_COUNT
#endif

#if WITH_SEND_CCA
  strobe(CC2520_INS_SRXON);
  BUSYWAIT_UNTIL(status() & BV(CC2520_RSSI_VALID) , RTIMER_SECOND / 10);
  strobe(CC2520_INS_STXONCCA);
#else /* WITH_SEND_CCA */
  strobe(CC2520_INS_STXON);
#endif /* WITH_SEND_CCA */
  for(i = LOOP_20_SYMBOLS; i > 0; i--) {
    if(CC2520_SFD_IS_1) {
      {
        rtimer_clock_t sfd_timestamp;
        sfd_timestamp = cc2520_sfd_start_time;
        if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) ==
           PACKETBUF_ATTR_PACKET_TYPE_TIMESTAMP) {
          /* Write timestamp to last two bytes of packet in TXFIFO. */
          CC2520_WRITE_RAM(&sfd_timestamp, CC2520RAM_TXFIFO + payload_len - 1, 2);
        }
      }

      if(!(status() & BV(CC2520_TX_ACTIVE))) {
        /* SFD went high but we are not transmitting. This means that
           we just started receiving a packet, so we drop the
           transmission. */
        RELEASE_LOCK();
        return RADIO_TX_COLLISION;
      }
      if(receive_on) {
	ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
      }
      ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);
      /* We wait until transmission has ended so that we get an
	 accurate measurement of the transmission time.*/
     //BUSYWAIT_UNTIL(getreg(CC2520_EXCFLAG0) & TX_FRM_DONE , RTIMER_SECOND / 100);
      BUSYWAIT_UNTIL(!(status() & BV(CC2520_TX_ACTIVE)), RTIMER_SECOND / 10);

#ifdef ENERGEST_CONF_LEVELDEVICE_LEVELS
      ENERGEST_OFF_LEVEL(ENERGEST_TYPE_TRANSMIT,cc2520_get_txpower());
#endif
      ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
      if(receive_on) {
	ENERGEST_ON(ENERGEST_TYPE_LISTEN);
      } else {
	/* We need to explicitly turn off the radio,
	 * since STXON[CCA] -> TX_ACTIVE -> RX_ACTIVE */
	off();
      }

      if(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) > 0) {
        /* Restore the transmission power */
        set_txpower(txpower & 0xff);
      }

      RELEASE_LOCK();

      return RADIO_TX_OK;
    }
  }

  /* If we are using WITH_SEND_CCA, we get here if the packet wasn't
     transmitted because of other channel activity. */
  RIMESTATS_ADD(contentiondrop);
  PRINTF("cc2520: do_send() transmission never started\n");

  if(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) > 0) {
    /* Restore the transmission power */
    set_txpower(txpower & 0xff);
  }

  RELEASE_LOCK();
  return RADIO_TX_COLLISION;
}
Пример #24
0
/*---------------------------------------------------------------------------*/
int
cc2420_send(const void *payload, unsigned short payload_len)
{
  int i;
  uint8_t total_len;
  struct timestamp timestamp;
  uint16_t checksum;

  GET_LOCK();

  PRINTF("cc2420: sending %d bytes\n", payload_len);
  
  RIMESTATS_ADD(lltx);

  /* Wait for any previous transmission to finish. */
  while(status() & BV(CC2420_TX_ACTIVE));

  /* Write packet to TX FIFO. */
  strobe(CC2420_SFLUSHTX);

  checksum = crc16_data(payload, payload_len, 0);
  total_len = payload_len + AUX_LEN;
  FASTSPI_WRITE_FIFO(&total_len, 1);
  FASTSPI_WRITE_FIFO(payload, payload_len);
  FASTSPI_WRITE_FIFO(&checksum, CHECKSUM_LEN);

#if CC2420_CONF_TIMESTAMPS
  timestamp.authority_level = timesynch_authority_level();
  timestamp.time = timesynch_time();
  FASTSPI_WRITE_FIFO(&timestamp, TIMESTAMP_LEN);
#endif /* CC2420_CONF_TIMESTAMPS */

  /* The TX FIFO can only hold one packet. Make sure to not overrun
   * FIFO by waiting for transmission to start here and synchronizing
   * with the CC2420_TX_ACTIVE check in cc2420_send.
   *
   * Note that we may have to wait up to 320 us (20 symbols) before
   * transmission starts.
   */
#ifdef TMOTE_SKY
#define LOOP_20_SYMBOLS 100	/* 326us (msp430 @ 2.4576MHz) */
#elif __AVR__
#define LOOP_20_SYMBOLS 500	/* XXX */
#endif

#if WITH_SEND_CCA
  strobe(CC2420_SRXON);
  while(!(status() & BV(CC2420_RSSI_VALID)));
  strobe(CC2420_STXONCCA);
#else /* WITH_SEND_CCA */
  strobe(CC2420_STXON);
#endif /* WITH_SEND_CCA */
  
  for(i = LOOP_20_SYMBOLS; i > 0; i--) {
    if(SFD_IS_1) {
#if CC2420_CONF_TIMESTAMPS
      rtimer_clock_t txtime = timesynch_time();
#endif /* CC2420_CONF_TIMESTAMPS */

      if(receive_on) {
	ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
      }
      ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);

      /* We wait until transmission has ended so that we get an
	 accurate measurement of the transmission time.*/
      while(status() & BV(CC2420_TX_ACTIVE));

#if CC2420_CONF_TIMESTAMPS
      setup_time_for_transmission = txtime - timestamp.time;

      if(num_transmissions < 10000) {
	total_time_for_transmission += timesynch_time() - txtime;
	total_transmission_len += total_len;
	num_transmissions++;
      }

#endif /* CC2420_CONF_TIMESTAMPS */

#ifdef ENERGEST_CONF_LEVELDEVICE_LEVELS
      ENERGEST_OFF_LEVEL(ENERGEST_TYPE_TRANSMIT,cc2420_get_txpower());
#endif
      ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
      if(receive_on) {
	ENERGEST_ON(ENERGEST_TYPE_LISTEN);
      }

      RELEASE_LOCK();
      return 0;
    }
  }
  
  /* If we are using WITH_SEND_CCA, we get here if the packet wasn't
     transmitted because of other channel activity. */
  RIMESTATS_ADD(contentiondrop);
  PRINTF("cc2420: do_send() transmission never started\n");
  RELEASE_LOCK();
  return -3;			/* Transmission never started! */
}
Пример #25
0
/*---------------------------------------------------------------------------*/
static int
cc2520_read(void *buf, unsigned short bufsize)
{
  uint8_t footer[2];
  uint8_t len;

  if(!CC2520_FIFOP_IS_1) {
    return 0;
  }

  GET_LOCK();

  cc2520_packets_read++;

  getrxbyte(&len);

  if(len > CC2520_MAX_PACKET_LEN) {
    /* Oops, we must be out of sync. */
    flushrx();
    RIMESTATS_ADD(badsynch);
    RELEASE_LOCK();
    return 0;
  }

  if(len <= FOOTER_LEN) {
    flushrx();
    RIMESTATS_ADD(tooshort);
    RELEASE_LOCK();
    return 0;
  }

  if(len - FOOTER_LEN > bufsize) {
    flushrx();
    RIMESTATS_ADD(toolong);
    RELEASE_LOCK();
    return 0;
  }

  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;


    packetbuf_set_attr(PACKETBUF_ATTR_RSSI, cc2520_last_rssi);
    packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, cc2520_last_correlation);

    RIMESTATS_ADD(llrx);

  } else {
    RIMESTATS_ADD(badcrc);
    len = FOOTER_LEN;
  }

  if(CC2520_FIFOP_IS_1) {
    if(!CC2520_FIFO_IS_1) {
      /* 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 has been received and needs attention. */
      process_poll(&cc2520_process);
    }
  }

  RELEASE_LOCK();

  if(len < FOOTER_LEN) {
    return 0;
  }

  return len - FOOTER_LEN;
}
Пример #26
0
/*---------------------------------------------------------------------------*/
int
cc2420_read(void *buf, unsigned short bufsize)
{
  uint8_t footer[2];
  uint8_t len;
  uint16_t checksum;
  struct timestamp t;
  
  if(!FIFOP_IS_1) {
    /* If FIFOP is 0, there is no packet in the RXFIFO. */
    return 0;
  }
  
  if(interrupt_time_set) {
#if CC2420_CONF_TIMESTAMPS
    cc2420_time_of_arrival = interrupt_time;
#endif /* CC2420_CONF_TIMESTAMPS */
    interrupt_time_set = 0;
  } else {
    cc2420_time_of_arrival = 0;
  }
  cc2420_time_of_departure = 0;
  GET_LOCK();

  getrxbyte(&len);

  if(len > CC2420_MAX_PACKET_LEN) {
    /* Oops, we must be out of sync. */
    flushrx();
    RIMESTATS_ADD(badsynch);
    RELEASE_LOCK();
    return 0;
  }

  if(len <= AUX_LEN) {
    flushrx();
    RIMESTATS_ADD(tooshort);
    RELEASE_LOCK();
    return 0;
  }
  
  if(len - AUX_LEN > bufsize) {
    flushrx();
    RIMESTATS_ADD(toolong);
    RELEASE_LOCK();
    return 0;
  }

  getrxdata(buf, len - AUX_LEN);
  getrxdata(&checksum, CHECKSUM_LEN);
  getrxdata(&t, TIMESTAMP_LEN);
  getrxdata(footer, FOOTER_LEN);
  
  if(footer[1] & FOOTER1_CRC_OK &&
     checksum == crc16_data(buf, len - AUX_LEN, 0)) {
    cc2420_last_rssi = footer[0];
    cc2420_last_correlation = footer[1] & FOOTER1_CORRELATION;
    RIMESTATS_ADD(llrx);
    
#if CC2420_CONF_TIMESTAMPS
    cc2420_time_of_departure =
      t.time +
      setup_time_for_transmission +
      (total_time_for_transmission * (len - 2)) / total_transmission_len;
  
    cc2420_authority_level_of_sender = t.authority_level;
  
#endif /* CC2420_CONF_TIMESTAMPS */
  
  } else {
    RIMESTATS_ADD(badcrc);
    len = AUX_LEN;
  }
  
  /* Clean up in case of FIFO overflow!  This happens for every full
   * length frame and is signaled by FIFOP = 1 and FIFO = 0.
   */
  if(FIFOP_IS_1 && !FIFO_IS_1) {
    /*    printf("cc2420_read: FIFOP_IS_1 1\n");*/
    flushrx();
  } else if(FIFOP_IS_1) {
    /* Another packet has been received and needs attention. */
    process_poll(&cc2420_process);
  }
  
  RELEASE_LOCK();
  
  if(len < AUX_LEN) {
    return 0;
  }

  return len - AUX_LEN;
}
Пример #27
0
/*---------------------------------------------------------------------------*/
static int
read(void *buf, unsigned short bufsize)
{
  uint8_t i;
  uint8_t len;
  uint8_t crc_corr;
  int8_t rssi;

  PUTSTRING("RF: Read\n");

  /* Check the length */
  len = RFD;

  /* Check for validity */
  if(len > CC2530_RF_MAX_PACKET_LEN) {
    /* Oops, we must be out of sync. */
    PUTSTRING("RF: bad sync\n");

    RIMESTATS_ADD(badsynch);
    CC2530_CSP_ISFLUSHRX();
    return 0;
  }

  if(len <= CC2530_RF_MIN_PACKET_LEN) {
    PUTSTRING("RF: too short\n");

    RIMESTATS_ADD(tooshort);
    CC2530_CSP_ISFLUSHRX();
    return 0;
  }

  if(len - CHECKSUM_LEN > bufsize) {
    PUTSTRING("RF: too long\n");

    RIMESTATS_ADD(toolong);
    CC2530_CSP_ISFLUSHRX();
    return 0;
  }

#if CC2530_RF_CONF_HEXDUMP
  /* If we reach here, chances are the FIFO is holding a valid frame */
  uart0_writeb(magic[0]);
  uart0_writeb(magic[1]);
  uart0_writeb(magic[2]);
  uart0_writeb(magic[3]);
  uart0_writeb(len);
#endif

  RF_RX_LED_ON();

  PUTSTRING("RF: read (0x");
  PUTHEX(len);
  PUTSTRING(" bytes) = ");
  len -= CHECKSUM_LEN;
  for(i = 0; i < len; ++i) {
    ((unsigned char*)(buf))[i] = RFD;
#if CC2530_RF_CONF_HEXDUMP
    uart0_writeb(((unsigned char*)(buf))[i]);
#endif
    PUTHEX(((unsigned char*)(buf))[i]);
  }
  PUTSTRING("\n");

  /* Read the RSSI and CRC/Corr bytes */
  rssi = ((int8_t) RFD) - 45;
  crc_corr = RFD;

#if CC2530_RF_CONF_HEXDUMP
  uart0_writeb(rssi);
  uart0_writeb(crc_corr);
#endif

  /* MS bit CRC OK/Not OK, 7 LS Bits, Correlation value */
  if(crc_corr & CRC_BIT_MASK) {
    packetbuf_set_attr(PACKETBUF_ATTR_RSSI, rssi);
    packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, crc_corr & LQI_BIT_MASK);
    RIMESTATS_ADD(llrx);
  } else {
    RIMESTATS_ADD(badcrc);
    CC2530_CSP_ISFLUSHRX();
    RF_RX_LED_OFF();
    return 0;
  }

  /* If FIFOP==1 and FIFO==0 then we had a FIFO overflow at some point. */
  if((FSMSTAT1 & (FSMSTAT1_FIFO | FSMSTAT1_FIFOP)) == FSMSTAT1_FIFOP) {
    /*
     * If we reach here means that there might be more intact packets in the
     * FIFO despite the overflow. This can happen with bursts of small packets.
     *
     * Only flush if the FIFO is actually empty. If not, then next pass we will
     * pick up one more packet or flush due to an error.
     */
    if(!RXFIFOCNT) {
      CC2530_CSP_ISFLUSHRX();
    }
  }

  RF_RX_LED_OFF();

  return (len);
}
Пример #28
0
/*---------------------------------------------------------------------------*/
static int send_one_packet(mac_callback_t sent, void *ptr)
{
  int ret;
  int last_sent_ok = 0;

  packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &linkaddr_node_addr);
  packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1);

  if(NETSTACK_FRAMER.create_and_secure() < 0){
    /* Failed to allocate space for headers */
    PRINTF("nullrdc: send failed, too large header\n");
    ret = MAC_TX_ERR_FATAL;
  }else{
    int is_broadcast;
    uint8_t dsn;
    dsn = ((uint8_t *)packetbuf_hdrptr())[2] & 0xff;

    NETSTACK_RADIO.prepare(packetbuf_hdrptr(), packetbuf_totlen());

    is_broadcast = packetbuf_holds_broadcast();

    if(NETSTACK_RADIO.receiving_packet() ||
       (!is_broadcast && NETSTACK_RADIO.pending_packet())){

      /* Currently receiving a packet over air or the radio has
         already received a packet that needs to be read before
         sending with auto ack. */
      ret = MAC_TX_COLLISION;
    }else{
      if(!is_broadcast){
        RIMESTATS_ADD(reliabletx);
      }

      switch(NETSTACK_RADIO.transmit(packetbuf_totlen())){
      case RADIO_TX_OK:
        if(is_broadcast) {
          ret = MAC_TX_OK;
        }else{
          rtimer_clock_t wt;

          /* Check for ack */
          wt = RTIMER_NOW();
          watchdog_periodic();
          while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + ACK_WAIT_TIME));

          ret = MAC_TX_NOACK;
          if(NETSTACK_RADIO.receiving_packet() ||
             NETSTACK_RADIO.pending_packet() ||
             NETSTACK_RADIO.channel_clear() == 0){
            int len;
            uint8_t ackbuf[ACK_LEN];

            if(AFTER_ACK_DETECTED_WAIT_TIME > 0){
              wt = RTIMER_NOW();
              watchdog_periodic();
              while(RTIMER_CLOCK_LT(RTIMER_NOW(),
                                    wt + AFTER_ACK_DETECTED_WAIT_TIME));
            }

            if(NETSTACK_RADIO.pending_packet()){
              len = NETSTACK_RADIO.read(ackbuf, ACK_LEN);
              if(len == ACK_LEN && ackbuf[2] == dsn){
                /* Ack received */
                RIMESTATS_ADD(ackrx);
                ret = MAC_TX_OK;
              }else{
                /* Not an ack or ack not for us: collision */
                ret = MAC_TX_COLLISION;
              }
            }
          }else{
            PRINTF("nullrdc tx noack\n");
          }
        }
        break;
      case RADIO_TX_COLLISION:
        ret = MAC_TX_COLLISION;
        break;
      default:
        ret = MAC_TX_ERR;
        break;
      }
    }
  }
  if(ret == MAC_TX_OK) {
    last_sent_ok = 1;
  }
  mac_call_sent_callback(sent, ptr, ret, 1);
  return last_sent_ok;
}
Пример #29
0
/*---------------------------------------------------------------------------*/
static void
rx_nok_isr(void)
{
  RIMESTATS_ADD(badcrc);
  PRINTF("RF: Bad CRC\n");
}
Пример #30
0
/*---------------------------------------------------------------------------*/
static int
transmit(unsigned short transmit_len)
{
  uint8_t counter;
  int ret = RADIO_TX_ERR;
  rtimer_clock_t t0;
  uint8_t was_off = 0;

  PRINTF("RF: Transmit\n");

  if(!(rf_flags & RX_ACTIVE)) {
    t0 = RTIMER_NOW();
    on();
    was_off = 1;
    while(RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + ONOFF_TIME));
  }

  if(channel_clear() == CC2538_RF_CCA_BUSY) {
    RIMESTATS_ADD(contentiondrop);
    return RADIO_TX_COLLISION;
  }

  /*
   * prepare() double checked that TX_ACTIVE is low. If SFD is high we are
   * receiving. Abort transmission and bail out with RADIO_TX_COLLISION
   */
  if(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_SFD) {
    RIMESTATS_ADD(contentiondrop);
    return RADIO_TX_COLLISION;
  }

  /* Start the transmission */
  ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
  ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);

  CC2538_RF_CSP_ISTXON();

  counter = 0;
  while(!((REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_TX_ACTIVE))
        && (counter++ < 3)) {
    clock_delay_usec(6);
  }

  if(!(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_TX_ACTIVE)) {
    PRINTF("RF: TX never active.\n");
    CC2538_RF_CSP_ISFLUSHTX();
    ret = RADIO_TX_ERR;
  } else {
    /* Wait for the transmission to finish */
    while(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_TX_ACTIVE);
    ret = RADIO_TX_OK;
  }
  ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
  ENERGEST_ON(ENERGEST_TYPE_LISTEN);

  if(was_off) {
    off();
  }

  RIMESTATS_ADD(lltx);

  return ret;
}