예제 #1
0
/* Add packet to neighbor queue. Use same lockfree implementation as ringbuf.c (put is atomic) */
struct tsch_packet *
tsch_queue_add_packet(const linkaddr_t *addr, mac_callback_t sent, void *ptr)
{
  struct tsch_neighbor *n = NULL;
  int16_t put_index = -1;
  struct tsch_packet *p = NULL;
  if(!tsch_is_locked()) {
    n = tsch_queue_add_nbr(addr);
    if(n != NULL) {
      put_index = ringbufindex_peek_put(&n->tx_ringbuf);
      if(put_index != -1) {
        p = memb_alloc(&packet_memb);
        if(p != NULL) {
          /* Enqueue packet */
#ifdef TSCH_CALLBACK_PACKET_READY
          TSCH_CALLBACK_PACKET_READY();
#endif
          p->qb = queuebuf_new_from_packetbuf();
          if(p->qb != NULL) {
            p->sent = sent;
            p->ptr = ptr;
            p->ret = MAC_TX_DEFERRED;
            p->transmissions = 0;
            /* Add to ringbuf (actual add committed through atomic operation) */
            n->tx_array[put_index] = p;
            ringbufindex_put(&n->tx_ringbuf);
            return p;
          } else {
            memb_free(&packet_memb, p);
          }
        }
      }
    }
  }
  PRINTF("TSCH-queue:! add packet failed: %u %p %d %p %p\n", tsch_is_locked(), n, put_index, p, p ? p->qb : NULL);
  return 0;
}
예제 #2
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();
  }
}