/* Add a TSCH neighbor */ struct tsch_neighbor * tsch_queue_add_nbr(const linkaddr_t *addr) { struct tsch_neighbor *n = NULL; /* If we have an entry for this neighbor already, we simply update it */ n = tsch_queue_get_nbr(addr); if(n == NULL) { if(tsch_get_lock()) { /* Allocate a neighbor */ n = memb_alloc(&neighbor_memb); if(n != NULL) { /* Initialize neighbor entry */ memset(n, 0, sizeof(struct tsch_neighbor)); ringbufindex_init(&n->tx_ringbuf, TSCH_QUEUE_NUM_PER_NEIGHBOR); linkaddr_copy(&n->addr, addr); n->is_broadcast = linkaddr_cmp(addr, &tsch_eb_address) || linkaddr_cmp(addr, &tsch_broadcast_address); tsch_queue_backoff_reset(n); /* Add neighbor to the list */ list_add(neighbor_list, n); } tsch_release_lock(); } } return n; }
/*---------------------------------------------------------------------------*/ static void tsch_init(void) { radio_value_t radio_rx_mode; radio_value_t radio_tx_mode; rtimer_clock_t t; /* Radio Rx mode */ if(NETSTACK_RADIO.get_value(RADIO_PARAM_RX_MODE, &radio_rx_mode) != RADIO_RESULT_OK) { printf("TSCH:! radio does not support getting RADIO_PARAM_RX_MODE. Abort init.\n"); return; } /* Disable radio in frame filtering */ radio_rx_mode &= ~RADIO_RX_MODE_ADDRESS_FILTER; /* Unset autoack */ radio_rx_mode &= ~RADIO_RX_MODE_AUTOACK; /* Set radio in poll mode */ radio_rx_mode |= RADIO_RX_MODE_POLL_MODE; if(NETSTACK_RADIO.set_value(RADIO_PARAM_RX_MODE, radio_rx_mode) != RADIO_RESULT_OK) { printf("TSCH:! radio does not support setting required RADIO_PARAM_RX_MODE. Abort init.\n"); return; } /* Radio Tx mode */ if(NETSTACK_RADIO.get_value(RADIO_PARAM_TX_MODE, &radio_tx_mode) != RADIO_RESULT_OK) { printf("TSCH:! radio does not support getting RADIO_PARAM_TX_MODE. Abort init.\n"); return; } /* Unset CCA */ radio_tx_mode &= ~RADIO_TX_MODE_SEND_ON_CCA; if(NETSTACK_RADIO.set_value(RADIO_PARAM_TX_MODE, radio_tx_mode) != RADIO_RESULT_OK) { printf("TSCH:! radio does not support setting required RADIO_PARAM_TX_MODE. Abort init.\n"); return; } /* Test setting channel */ if(NETSTACK_RADIO.set_value(RADIO_PARAM_CHANNEL, TSCH_DEFAULT_HOPPING_SEQUENCE[0]) != RADIO_RESULT_OK) { printf("TSCH:! radio does not support setting channel. Abort init.\n"); return; } /* Test getting timestamp */ if(NETSTACK_RADIO.get_object(RADIO_PARAM_LAST_PACKET_TIMESTAMP, &t, sizeof(rtimer_clock_t)) != RADIO_RESULT_OK) { printf("TSCH:! radio does not support getting last packet timestamp. Abort init.\n"); return; } /* Check max hopping sequence length vs default sequence length */ if(TSCH_HOPPING_SEQUENCE_MAX_LEN < sizeof(TSCH_DEFAULT_HOPPING_SEQUENCE)) { printf("TSCH:! TSCH_HOPPING_SEQUENCE_MAX_LEN < sizeof(TSCH_DEFAULT_HOPPING_SEQUENCE). Abort init.\n"); } /* Init TSCH sub-modules */ tsch_reset(); tsch_queue_init(); tsch_schedule_init(); tsch_log_init(); ringbufindex_init(&input_ringbuf, TSCH_MAX_INCOMING_PACKETS); ringbufindex_init(&dequeued_ringbuf, TSCH_DEQUEUED_ARRAY_SIZE); tsch_is_initialized = 1; #if TSCH_AUTOSTART /* Start TSCH operation. * If TSCH_AUTOSTART is not set, one needs to call NETSTACK_MAC.on() to start TSCH. */ NETSTACK_MAC.on(); #endif /* TSCH_AUTOSTART */ }
/*---------------------------------------------------------------------------*/ 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(µmac_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; }