AP_HAL: added register_io_process()

this is used to register a low priority IO task. Used for file IO in
DataFlash_File.cpp
This commit is contained in:
Andrew Tridgell 2013-04-17 21:33:50 +10:00
parent 5df4796b9a
commit af7381e9e0
7 changed files with 113 additions and 2 deletions

View File

@ -18,7 +18,13 @@ public:
virtual void register_delay_callback(AP_HAL::Proc, virtual void register_delay_callback(AP_HAL::Proc,
uint16_t min_time_ms) = 0; uint16_t min_time_ms) = 0;
// register a high priority timer task
virtual void register_timer_process(AP_HAL::TimedProc) = 0; virtual void register_timer_process(AP_HAL::TimedProc) = 0;
// register a low priority IO task
virtual void register_io_process(AP_HAL::TimedProc) = 0;
// suspend and resume both timer and IO processes
virtual void suspend_timer_procs() = 0; virtual void suspend_timer_procs() = 0;
virtual void resume_timer_procs() = 0; virtual void resume_timer_procs() = 0;

View File

@ -108,6 +108,11 @@ void AVRScheduler::register_timer_process(AP_HAL::TimedProc proc) {
} }
void AVRScheduler::register_io_process(AP_HAL::TimedProc proc)
{
// IO processes not supported on AVR
}
void AVRScheduler::register_timer_failsafe( void AVRScheduler::register_timer_failsafe(
AP_HAL::TimedProc failsafe, uint32_t period_us) { AP_HAL::TimedProc failsafe, uint32_t period_us) {
/* XXX Assert period_us == 1000 */ /* XXX Assert period_us == 1000 */

View File

@ -32,6 +32,7 @@ public:
void register_delay_callback(AP_HAL::Proc, uint16_t min_time_ms); void register_delay_callback(AP_HAL::Proc, uint16_t min_time_ms);
void register_timer_process(AP_HAL::TimedProc); void register_timer_process(AP_HAL::TimedProc);
void register_io_process(AP_HAL::TimedProc);
void suspend_timer_procs(); void suspend_timer_procs();
void resume_timer_procs(); void resume_timer_procs();

View File

@ -16,9 +16,15 @@ extern const AP_HAL::HAL& hal;
AP_HAL::TimedProc SITLScheduler::_failsafe = NULL; AP_HAL::TimedProc SITLScheduler::_failsafe = NULL;
volatile bool SITLScheduler::_timer_suspended = false; volatile bool SITLScheduler::_timer_suspended = false;
volatile bool SITLScheduler::_timer_event_missed = false; volatile bool SITLScheduler::_timer_event_missed = false;
AP_HAL::TimedProc SITLScheduler::_timer_proc[SITL_SCHEDULER_MAX_TIMER_PROCS] = {NULL}; AP_HAL::TimedProc SITLScheduler::_timer_proc[SITL_SCHEDULER_MAX_TIMER_PROCS] = {NULL};
uint8_t SITLScheduler::_num_timer_procs = 0; uint8_t SITLScheduler::_num_timer_procs = 0;
bool SITLScheduler::_in_timer_proc = false; bool SITLScheduler::_in_timer_proc = false;
AP_HAL::TimedProc SITLScheduler::_io_proc[SITL_SCHEDULER_MAX_TIMER_PROCS] = {NULL};
uint8_t SITLScheduler::_num_io_procs = 0;
bool SITLScheduler::_in_io_proc = false;
struct timeval SITLScheduler::_sketch_start_time; struct timeval SITLScheduler::_sketch_start_time;
SITLScheduler::SITLScheduler() SITLScheduler::SITLScheduler()
@ -100,6 +106,21 @@ void SITLScheduler::register_timer_process(AP_HAL::TimedProc proc)
} }
void SITLScheduler::register_io_process(AP_HAL::TimedProc proc)
{
for (uint8_t i = 0; i < _num_io_procs; i++) {
if (_io_proc[i] == proc) {
return;
}
}
if (_num_io_procs < SITL_SCHEDULER_MAX_TIMER_PROCS) {
_io_proc[_num_io_procs] = proc;
_num_io_procs++;
}
}
void SITLScheduler::register_timer_failsafe(AP_HAL::TimedProc failsafe, uint32_t period_us) void SITLScheduler::register_timer_failsafe(AP_HAL::TimedProc failsafe, uint32_t period_us)
{ {
_failsafe = failsafe; _failsafe = failsafe;
@ -118,7 +139,7 @@ void SITLScheduler::resume_timer_procs() {
} }
bool SITLScheduler::in_timerprocess() { bool SITLScheduler::in_timerprocess() {
return _in_timer_proc; return _in_timer_proc || _in_io_proc;
} }
bool SITLScheduler::system_initializing() { bool SITLScheduler::system_initializing() {
@ -185,6 +206,28 @@ void SITLScheduler::_run_timer_procs(bool called_from_isr)
_in_timer_proc = false; _in_timer_proc = false;
} }
void SITLScheduler::_run_io_procs(bool called_from_isr)
{
uint32_t tnow = _micros();
if (_in_io_proc) {
return;
}
_in_io_proc = true;
if (!_timer_suspended) {
// now call the IO based drivers
for (int i = 0; i < _num_io_procs; i++) {
if (_io_proc[i] != NULL) {
_io_proc[i](tnow);
}
}
} else if (called_from_isr) {
_timer_event_missed = true;
}
_in_io_proc = false;
}
void SITLScheduler::panic(const prog_char_t *errormsg) { void SITLScheduler::panic(const prog_char_t *errormsg) {
hal.console->println_P(errormsg); hal.console->println_P(errormsg);
for(;;); for(;;);

View File

@ -23,6 +23,7 @@ public:
void register_delay_callback(AP_HAL::Proc, uint16_t min_time_ms); void register_delay_callback(AP_HAL::Proc, uint16_t min_time_ms);
void register_timer_process(AP_HAL::TimedProc); void register_timer_process(AP_HAL::TimedProc);
void register_io_process(AP_HAL::TimedProc);
void suspend_timer_procs(); void suspend_timer_procs();
void resume_timer_procs(); void resume_timer_procs();
@ -43,7 +44,7 @@ public:
// callable from interrupt handler // callable from interrupt handler
static uint32_t _micros(); static uint32_t _micros();
static void timer_event() { _run_timer_procs(true); } static void timer_event() { _run_timer_procs(true); _run_io_procs(true); }
private: private:
uint8_t _nested_atomic_ctr; uint8_t _nested_atomic_ctr;
@ -53,12 +54,16 @@ private:
static AP_HAL::TimedProc _failsafe; static AP_HAL::TimedProc _failsafe;
static void _run_timer_procs(bool called_from_isr); static void _run_timer_procs(bool called_from_isr);
static void _run_io_procs(bool called_from_isr);
static volatile bool _timer_suspended; static volatile bool _timer_suspended;
static volatile bool _timer_event_missed; static volatile bool _timer_event_missed;
static AP_HAL::TimedProc _timer_proc[SITL_SCHEDULER_MAX_TIMER_PROCS]; static AP_HAL::TimedProc _timer_proc[SITL_SCHEDULER_MAX_TIMER_PROCS];
static AP_HAL::TimedProc _io_proc[SITL_SCHEDULER_MAX_TIMER_PROCS];
static uint8_t _num_timer_procs; static uint8_t _num_timer_procs;
static uint8_t _num_io_procs;
static bool _in_timer_proc; static bool _in_timer_proc;
static bool _in_io_proc;
bool _initialized; bool _initialized;

View File

@ -29,6 +29,7 @@ extern bool _px4_thread_should_exit;
PX4Scheduler::PX4Scheduler() : PX4Scheduler::PX4Scheduler() :
_perf_timers(perf_alloc(PC_ELAPSED, "APM_timers")), _perf_timers(perf_alloc(PC_ELAPSED, "APM_timers")),
_perf_io_timers(perf_alloc(PC_ELAPSED, "APM_IO_timers")),
_perf_delay(perf_alloc(PC_ELAPSED, "APM_delay")) _perf_delay(perf_alloc(PC_ELAPSED, "APM_delay"))
{} {}
@ -132,6 +133,22 @@ void PX4Scheduler::register_timer_process(AP_HAL::TimedProc proc)
} }
} }
void PX4Scheduler::register_io_process(AP_HAL::TimedProc proc)
{
for (uint8_t i = 0; i < _num_io_procs; i++) {
if (_io_proc[i] == proc) {
return;
}
}
if (_num_io_procs < PX4_SCHEDULER_MAX_TIMER_PROCS) {
_io_proc[_num_io_procs] = proc;
_num_io_procs++;
} else {
hal.console->printf("Out of IO processes\n");
}
}
void PX4Scheduler::register_timer_failsafe(AP_HAL::TimedProc failsafe, uint32_t period_us) void PX4Scheduler::register_timer_failsafe(AP_HAL::TimedProc failsafe, uint32_t period_us)
{ {
_failsafe = failsafe; _failsafe = failsafe;
@ -202,6 +219,26 @@ void *PX4Scheduler::_timer_thread(void)
return NULL; return NULL;
} }
void PX4Scheduler::_run_io(void)
{
uint32_t tnow = micros();
if (_in_io_proc) {
return;
}
_in_io_proc = true;
if (!_timer_suspended) {
// now call the IO based drivers
for (int i = 0; i < _num_io_procs; i++) {
if (_io_proc[i] != NULL) {
_io_proc[i](tnow);
}
}
}
_in_io_proc = false;
}
void *PX4Scheduler::_io_thread(void) void *PX4Scheduler::_io_thread(void)
{ {
while (!_px4_thread_should_exit) { while (!_px4_thread_should_exit) {
@ -214,6 +251,11 @@ void *PX4Scheduler::_io_thread(void)
// process any pending storage writes // process any pending storage writes
((PX4Storage *)hal.storage)->_timer_tick(); ((PX4Storage *)hal.storage)->_timer_tick();
// run registered IO processes
perf_begin(_perf_io_timers);
_run_io();
perf_end(_perf_io_timers);
} }
return NULL; return NULL;
} }

View File

@ -31,6 +31,7 @@ public:
void delay_microseconds(uint16_t us); void delay_microseconds(uint16_t us);
void register_delay_callback(AP_HAL::Proc, uint16_t min_time_ms); void register_delay_callback(AP_HAL::Proc, uint16_t min_time_ms);
void register_timer_process(AP_HAL::TimedProc); void register_timer_process(AP_HAL::TimedProc);
void register_io_process(AP_HAL::TimedProc);
void register_timer_failsafe(AP_HAL::TimedProc, uint32_t period_us); void register_timer_failsafe(AP_HAL::TimedProc, uint32_t period_us);
void suspend_timer_procs(); void suspend_timer_procs();
void resume_timer_procs(); void resume_timer_procs();
@ -50,9 +51,15 @@ private:
uint64_t _sketch_start_time; uint64_t _sketch_start_time;
volatile bool _timer_suspended; volatile bool _timer_suspended;
AP_HAL::TimedProc _timer_proc[PX4_SCHEDULER_MAX_TIMER_PROCS]; AP_HAL::TimedProc _timer_proc[PX4_SCHEDULER_MAX_TIMER_PROCS];
uint8_t _num_timer_procs; uint8_t _num_timer_procs;
volatile bool _in_timer_proc; volatile bool _in_timer_proc;
AP_HAL::TimedProc _io_proc[PX4_SCHEDULER_MAX_TIMER_PROCS];
uint8_t _num_io_procs;
volatile bool _in_io_proc;
volatile bool _timer_event_missed; volatile bool _timer_event_missed;
pthread_t _timer_thread_ctx; pthread_t _timer_thread_ctx;
@ -62,8 +69,10 @@ private:
void *_io_thread(void); void *_io_thread(void);
void _run_timers(bool called_from_timer_thread); void _run_timers(bool called_from_timer_thread);
void _run_io(void);
perf_counter_t _perf_timers; perf_counter_t _perf_timers;
perf_counter_t _perf_io_timers;
perf_counter_t _perf_delay; perf_counter_t _perf_delay;
}; };
#endif #endif