Skip to content
Snippets Groups Projects
Commit d973730b authored by Andrew Tridgell's avatar Andrew Tridgell
Browse files

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
parent aa7a1a5a
No related branches found
No related tags found
No related merge requests found
...@@ -76,11 +76,6 @@ static bool ran_overtime; ...@@ -76,11 +76,6 @@ static bool ran_overtime;
extern const AP_HAL::HAL& hal; 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 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_loop = perf_alloc(PC_ELAPSED, "APM_loop");
perf_counter_t perf_overrun = perf_alloc(PC_COUNT, "APM_overrun"); perf_counter_t perf_overrun = perf_alloc(PC_COUNT, "APM_overrun");
sem_t loop_semaphore;
struct hrt_call loop_call; struct hrt_call loop_call;
struct hrt_call loop_overtime_call; struct hrt_call loop_overtime_call;
sem_init(&loop_semaphore, 0, 0);
thread_running = true; 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 give up 500 microseconds of time, to ensure drivers get a
chance to run. This gives us better timing performance than chance to run. This relies on the accurate semaphore wait
a poll(NULL, 0, 1) using hrt in semaphore.cpp
*/ */
hrt_call_after(&loop_call, 500, (hrt_callout)semaphore_yield, &loop_semaphore); hal.scheduler->delay_microseconds(500);
sem_wait(&loop_semaphore);
} }
thread_running = false; thread_running = false;
return 0; return 0;
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <drivers/drv_hrt.h> #include <drivers/drv_hrt.h>
#include <nuttx/arch.h> #include <nuttx/arch.h>
#include <systemlib/systemlib.h> #include <systemlib/systemlib.h>
#include <pthread.h>
#include <poll.h> #include <poll.h>
#include "UARTDriver.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; 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) void PX4Scheduler::delay_microseconds(uint16_t usec)
{ {
#if 0 perf_begin(_perf_delay);
if (_in_timer_proc) { if (usec >= 500) {
::printf("ERROR: delay_microseconds() from timer process\n"); delay_microseconds_semaphore(usec);
perf_end(_perf_delay);
return; return;
} }
#endif
perf_begin(_perf_delay);
uint32_t start = micros(); uint32_t start = micros();
uint32_t dt; uint32_t dt;
while ((dt=(micros() - start)) < usec) { 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 && while ((hrt_absolute_time() - start)/1000 < ms &&
!_px4_thread_should_exit) { !_px4_thread_should_exit) {
// this yields the CPU to other apps delay_microseconds_semaphore(1000);
poll(NULL, 0, 1);
if (_min_delay_cb_ms <= ms) { if (_min_delay_cb_ms <= ms) {
if (_delay_cb) { if (_delay_cb) {
_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) void *PX4Scheduler::_timer_thread(void)
{ {
while (!_px4_thread_should_exit) { while (!_px4_thread_should_exit) {
poll(NULL, 0, 1); delay_microseconds_semaphore(1000);
// run registered timers // run registered timers
perf_begin(_perf_timers); perf_begin(_perf_timers);
......
...@@ -74,6 +74,8 @@ private: ...@@ -74,6 +74,8 @@ private:
void _run_timers(bool called_from_timer_thread); void _run_timers(bool called_from_timer_thread);
void _run_io(void); void _run_io(void);
void delay_microseconds_semaphore(uint16_t us);
perf_counter_t _perf_timers; perf_counter_t _perf_timers;
perf_counter_t _perf_io_timers; perf_counter_t _perf_io_timers;
perf_counter_t _perf_delay; perf_counter_t _perf_delay;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment