Run Loop Embedded
Run Loop Embedded
/*
* run_loop_embedded.c
*
* For this run loop, we assume that there's no global way to wait for a list
* of data sources to get ready. Instead, each data source has to queried
* individually. Calling ds->isReady() before calling ds->process() doesn't
* make sense, so we just poll each data source round robin.
*
* To support an idle state, where an MCU could go to sleep, the process function
* has to return if it has to called again as soon as possible
*
* After calling process() on every data source and evaluating the pending timers,
* the idle hook gets called if no data source did indicate that it needs to be
* called right away.
*
*/
#include <btstack/run_loop.h>
#include <btstack/linked_list.h>
#include <btstack/hal_tick.h>
#include <btstack/hal_cpu.h>
#include "run_loop_private.h"
#include "debug.h"
#ifdef HAVE_TIME_MS
#include <btstack/hal_time_ms.h>
#endif
#ifdef TIMER_SUPPORT
static linked_list_t timers;
#endif
#ifdef HAVE_TICK
static volatile uint32_t system_ticks;
#endif
/**
* Add data_source to run_loop
*/
static void embedded_add_data_source(data_source_t *ds){
linked_list_add(&data_sources, (linked_item_t *) ds);
}
/**
* Remove data_source from run loop
*/
static int embedded_remove_data_source(data_source_t *ds){
return linked_list_remove(&data_sources, (linked_item_t *) ds);
}
// set timer
static void embedded_set_timer(timer_source_t *ts, uint32_t timeout_in_ms){
#ifdef HAVE_TICK
uint32_t ticks = embedded_ticks_for_ms(timeout_in_ms);
if (ticks == 0) ticks++;
// time until next tick is < hal_tick_get_tick_period_in_ms() and we don't
know, so we add one
ts->timeout = system_ticks + 1 + ticks;
#endif
#ifdef HAVE_TIME_MS
ts->timeout = hal_time_ms() + timeout_in_ms + 1;
#endif
}
/**
* Add timer to run_loop (keep list sorted)
*/
static void embedded_add_timer(timer_source_t *ts){
#ifdef TIMER_SUPPORT
linked_item_t *it;
for (it = (linked_item_t *) &timers; it->next ; it = it->next){
// don't add timer that's already in there
if ((timer_source_t *) it->next == ts){
log_error( "run_loop_timer_add error: timer to add already in list!");
return;
}
if (ts->timeout < ((timer_source_t *) it->next)->timeout) {
break;
}
}
ts->item.next = it->next;
it->next = (linked_item_t *) ts;
#endif
}
/**
* Remove timer from run loop
*/
static int embedded_remove_timer(timer_source_t *ts){
#ifdef TIMER_SUPPORT
return linked_list_remove(&timers, (linked_item_t *) ts);
#else
return 0;
#endif
}
/**
* Execute run_loop once
*/
void embedded_execute_once(void) {
data_source_t *ds;
// disable IRQs and check if run loop iteration has been requested. if not, go
to sleep
hal_cpu_disable_irqs();
if (trigger_event_received){
trigger_event_received = 0;
hal_cpu_enable_irqs();
} else {
hal_cpu_enable_irqs_and_sleep();
}
}
/**
* Execute run_loop
*/
static void embedded_execute(void) {
while (1) {
embedded_execute_once();
}
}
#ifdef HAVE_TICK
static void embedded_tick_handler(void){
system_ticks++;
trigger_event_received = 1;
}
uint32_t embedded_get_ticks(void){
return system_ticks;
}
/**
* trigger run loop iteration
*/
void embedded_trigger(void){
trigger_event_received = 1;
}
data_sources = NULL;
#ifdef TIMER_SUPPORT
timers = NULL;
#endif
#ifdef HAVE_TICK
system_ticks = 0;
hal_tick_init();
hal_tick_set_handler(&embedded_tick_handler);
#endif
}