Browse Source

HAL_PX4: use hrt timer and semaphores to improve timing

this gives much more accurate microsecond delays, while also ensuring
we yield the CPU when possible
mission-4.1.18
Andrew Tridgell 11 years ago
parent
commit
d973730b88
  1. 15
      libraries/AP_HAL_PX4/HAL_PX4_Class.cpp
  2. 27
      libraries/AP_HAL_PX4/Scheduler.cpp
  3. 2
      libraries/AP_HAL_PX4/Scheduler.h

15
libraries/AP_HAL_PX4/HAL_PX4_Class.cpp

@ -76,11 +76,6 @@ static bool ran_overtime; @@ -76,11 +76,6 @@ static bool ran_overtime;
extern const AP_HAL::HAL& hal;
static void semaphore_yield(void *sem)
{
sem_post((sem_t *)sem);
}
/*
set the priority of the main APM task
*/
@ -130,12 +125,9 @@ static int main_loop(int argc, char **argv) @@ -130,12 +125,9 @@ static int main_loop(int argc, char **argv)
perf_counter_t perf_loop = perf_alloc(PC_ELAPSED, "APM_loop");
perf_counter_t perf_overrun = perf_alloc(PC_COUNT, "APM_overrun");
sem_t loop_semaphore;
struct hrt_call loop_call;
struct hrt_call loop_overtime_call;
sem_init(&loop_semaphore, 0, 0);
thread_running = true;
/*
@ -179,11 +171,10 @@ static int main_loop(int argc, char **argv) @@ -179,11 +171,10 @@ static int main_loop(int argc, char **argv)
/*
give up 500 microseconds of time, to ensure drivers get a
chance to run. This gives us better timing performance than
a poll(NULL, 0, 1)
chance to run. This relies on the accurate semaphore wait
using hrt in semaphore.cpp
*/
hrt_call_after(&loop_call, 500, (hrt_callout)semaphore_yield, &loop_semaphore);
sem_wait(&loop_semaphore);
hal.scheduler->delay_microseconds(500);
}
thread_running = false;
return 0;

27
libraries/AP_HAL_PX4/Scheduler.cpp

@ -14,6 +14,7 @@ @@ -14,6 +14,7 @@
#include <drivers/drv_hrt.h>
#include <nuttx/arch.h>
#include <systemlib/systemlib.h>
#include <pthread.h>
#include <poll.h>
#include "UARTDriver.h"
@ -82,15 +83,26 @@ uint32_t PX4Scheduler::millis() @@ -82,15 +83,26 @@ uint32_t PX4Scheduler::millis()
return hrt_absolute_time() / 1000;
}
/**
delay for a specified number of microseconds using a semaphore wait
*/
void PX4Scheduler::delay_microseconds_semaphore(uint16_t usec)
{
sem_t wait_semaphore;
struct hrt_call wait_call;
sem_init(&wait_semaphore, 0, 0);
hrt_call_after(&wait_call, usec, (hrt_callout)sem_post, &wait_semaphore);
sem_wait(&wait_semaphore);
}
void PX4Scheduler::delay_microseconds(uint16_t usec)
{
#if 0
if (_in_timer_proc) {
::printf("ERROR: delay_microseconds() from timer process\n");
perf_begin(_perf_delay);
if (usec >= 500) {
delay_microseconds_semaphore(usec);
perf_end(_perf_delay);
return;
}
#endif
perf_begin(_perf_delay);
uint32_t start = micros();
uint32_t dt;
while ((dt=(micros() - start)) < usec) {
@ -112,8 +124,7 @@ void PX4Scheduler::delay(uint16_t ms) @@ -112,8 +124,7 @@ void PX4Scheduler::delay(uint16_t ms)
while ((hrt_absolute_time() - start)/1000 < ms &&
!_px4_thread_should_exit) {
// this yields the CPU to other apps
poll(NULL, 0, 1);
delay_microseconds_semaphore(1000);
if (_min_delay_cb_ms <= ms) {
if (_delay_cb) {
_delay_cb();
@ -221,7 +232,7 @@ void PX4Scheduler::_run_timers(bool called_from_timer_thread) @@ -221,7 +232,7 @@ void PX4Scheduler::_run_timers(bool called_from_timer_thread)
void *PX4Scheduler::_timer_thread(void)
{
while (!_px4_thread_should_exit) {
poll(NULL, 0, 1);
delay_microseconds_semaphore(1000);
// run registered timers
perf_begin(_perf_timers);

2
libraries/AP_HAL_PX4/Scheduler.h

@ -74,6 +74,8 @@ private: @@ -74,6 +74,8 @@ private:
void _run_timers(bool called_from_timer_thread);
void _run_io(void);
void delay_microseconds_semaphore(uint16_t us);
perf_counter_t _perf_timers;
perf_counter_t _perf_io_timers;
perf_counter_t _perf_delay;

Loading…
Cancel
Save