/* 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; }
/*---------------------------------------------------------------------------*/ 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(µmac_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(); } }