Exemple #1
0
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(micromac_radio_process, ev, data)
{
  PROCESS_BEGIN();

  while(1) {
    PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL);

    /* Pass received packets to upper layer */
    int16_t read_index;
    /* Loop on accessing (without removing) a pending input packet */
    while((read_index = ringbufindex_peek_get(&input_ringbuf)) != -1) {
      input_frame_buffer = &input_array[read_index];
      /* Put packet into packetbuf for input callback */
      packetbuf_clear();
      int len = read(packetbuf_dataptr(), PACKETBUF_SIZE);
      /* is packet valid? */
      if(len > 0) {
        packetbuf_set_datalen(len);
        NETSTACK_RDC.input();
      }
      /* Remove packet from ringbuf */
      ringbufindex_get(&input_ringbuf);
      /* Disable further read attempts */
      input_frame_buffer->u8PayloadLength = 0;
    }

    /* Are we recovering from overflow? */
    if(rx_frame_buffer == NULL) {
      /* get pointer to next input slot */
      int 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];
        /* do we need to turn radio on? */
        if(MICROMAC_CONF_ALWAYS_ON || missed_radio_on_request) {
          missed_radio_on_request = 0;
          on();
        }
      } else {
        rx_frame_buffer = NULL;
      }
    }
  }
  PROCESS_END();
}
Exemple #2
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;
}
Exemple #3
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();
  }
}
Exemple #4
0
/*---------------------------------------------------------------------------*/
static int
init(void)
{
  int put_index;
  tsExtAddr node_long_address;
  uint16_t node_short_address;

  tx_in_progress = 0;

  u32JPT_Init();
  vMMAC_Enable();

  /* Enable/disable interrupts */
  if(poll_mode) {
    vMMAC_EnableInterrupts(NULL);
    vMMAC_ConfigureInterruptSources(0);
  } else {
    vMMAC_EnableInterrupts(&radio_interrupt_handler);
  } vMMAC_ConfigureRadio();
  set_channel(MICROMAC_CONF_CHANNEL);
  set_txpower(MICROMAC_CONF_TX_POWER);

  vMMAC_GetMacAddress(&node_long_address);

  /* Short addresses are disabled by default */
  node_short_address = (uint16_t)node_long_address.u32L;
  vMMAC_SetRxAddress(frame802154_get_pan_id(), node_short_address, &node_long_address);

  /* Disable hardware backoff */
  vMMAC_SetTxParameters(1, 0, 0, 0);
  vMMAC_SetCutOffTimer(0, FALSE);

  /* Initialize ring buffer and first input packet pointer */
  ringbufindex_init(&input_ringbuf, MIRCOMAC_CONF_BUF_NUM);
  /* get pointer to next input slot */
  put_index = ringbufindex_peek_put(&input_ringbuf);
  if(put_index == -1) {
    rx_frame_buffer = NULL;
    printf("micromac_radio init:! no buffer available. Abort init.\n");
    off();
    return 0;
  } else {
    rx_frame_buffer = &input_array[put_index];
  }
  input_frame_buffer = rx_frame_buffer;

  process_start(&micromac_radio_process, NULL);

#if RADIO_TEST_MODE == RADIO_TEST_MODE_HIGH_PWR
  /* Enable high power mode.
   * In this mode DIO2 goes high during RX
   * and DIO3 goes high during TX
   **/
  vREG_SysWrite(REG_SYS_PWR_CTRL,
                u32REG_SysRead(REG_SYS_PWR_CTRL)
                | REG_SYSCTRL_PWRCTRL_RFRXEN_MASK
                | REG_SYSCTRL_PWRCTRL_RFTXEN_MASK);
#elif RADIO_TEST_MODE == RADIO_TEST_MODE_ADVANCED
  /* output internal radio status on IO pins.
   * See Chris@NXP email */
  vREG_SysWrite(REG_SYS_PWR_CTRL,
                u32REG_SysRead(REG_SYS_PWR_CTRL) | (1UL << 26UL));
#endif /* TEST_MODE */

  return 1;
}