static void configure_next_event() { //this function should only be called from an atomic context timer_tick_t next_fire_time; do { //find the next event that has not yet passed, and schedule //the 'late' events while we're at it NG(next_event) = get_next_event(); if(NG(next_event) != NO_EVENT) { next_fire_time = NG(timers)[NG(next_event)].next_event; if ( (((int32_t)next_fire_time) - ((int32_t)timer_get_counter_value())) <= 0 ) { sched_post_task_prio(NG(timers)[NG(next_event)].f, NG(timers)[NG(next_event)].priority); NG(timers)[NG(next_event)].f = 0x0; } } } while(NG(next_event) != NO_EVENT && ( (((int32_t)next_fire_time) - ((int32_t)timer_get_counter_value())) <= 0 ) ); //at this point NG(next_event) is eiter equal to NO_EVENT (no tasks left) //or we have the next event we can schedule if(NG(next_event) == NO_EVENT) { //cancel the timer in case it is still running (can happen if we're called from timer_cancel_event) NG(hw_event_scheduled) = false; hw_timer_cancel(HW_TIMER_ID); } else { //calculate schedule time relative to current time rather than //latest overflow time, to counteract any delays in updating counter_offset //(eg when we're scheduling an event from an interrupt and thereby delaying //the updating of counter_offset) timer_tick_t fire_delay = (next_fire_time - timer_get_counter_value()); //if the timer should fire in less ticks than supported by the HW timer --> schedule it //(otherwise it is scheduled from timer_overflow when needed) if(fire_delay < COUNTER_OVERFLOW_INCREASE) { NG(hw_event_scheduled) = true; hw_timer_schedule_delay(HW_TIMER_ID, (hwtimer_tick_t)fire_delay); #ifndef NDEBUG //check that we didn't try to schedule a timer in the past //normally this shouldn't happen but it IS theoretically possible... fire_delay = (next_fire_time - timer_get_counter_value()); //fire_delay should be in [0,COUNTER_OVERFLOW_INCREASE]. if this is not the case, it is because timer_get_counter() is //now larger than next_fire_event, which means we 'missed' the event assert(((int32_t)fire_delay) > 0); #endif } else { //set hw_event_scheduled explicitly to false to allow timer_overflow //to schedule the event when needed NG(hw_event_scheduled) = false; } } }
static void timer_fired() { assert(NG(next_event) != NO_EVENT); assert(NG(timers)[NG(next_event)].f != 0x0); sched_post_task_prio(NG(timers)[NG(next_event)].f, NG(timers)[NG(next_event)].priority); NG(timers)[NG(next_event)].f = 0x0; configure_next_event(); }
void packet_received(hw_radio_packet_t* hw_radio_packet) { assert(dll_state == DLL_STATE_FOREGROUND_SCAN || dll_state == DLL_STATE_SCAN_AUTOMATION); // we are in interrupt context here, so mark packet for further processing, // schedule it and return DPRINT("packet received @ %i , RSSI = %i", hw_radio_packet->rx_meta.timestamp, hw_radio_packet->rx_meta.rssi); packet_queue_mark_received(hw_radio_packet); packet_t* packet = packet_queue_find_packet(hw_radio_packet); /* the received packet needs to be handled in priority */ sched_post_task_prio(&process_received_packets, MAX_PRIORITY); }
static void rx_cb(uint8_t byte) { fifo_put_byte(&rx_fifo, byte); if(!sched_is_scheduled(&process_rx_fifo)) sched_post_task_prio(&process_rx_fifo, MAX_PRIORITY, NULL); }