mirror of
https://github.com/ArduPilot/ardupilot
synced 2025-02-07 00:13:59 -04:00
HAL_Linux: better realtime setup
lock all memory and pre-fault the stack in all threads
This commit is contained in:
parent
2422b94292
commit
91511e6503
@ -11,6 +11,8 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
|
||||||
using namespace Linux;
|
using namespace Linux;
|
||||||
|
|
||||||
@ -26,10 +28,23 @@ LinuxScheduler::LinuxScheduler()
|
|||||||
|
|
||||||
typedef void *(*pthread_startroutine_t)(void *);
|
typedef void *(*pthread_startroutine_t)(void *);
|
||||||
|
|
||||||
|
/*
|
||||||
|
setup for realtime. Lock all of memory in the thread and pre-fault
|
||||||
|
the given stack size, so stack faults don't cause timing jitter
|
||||||
|
*/
|
||||||
|
void LinuxScheduler::_setup_realtime(uint32_t size)
|
||||||
|
{
|
||||||
|
uint8_t dummy[size];
|
||||||
|
mlockall(MCL_CURRENT|MCL_FUTURE);
|
||||||
|
memset(dummy, 0, sizeof(dummy));
|
||||||
|
}
|
||||||
|
|
||||||
void LinuxScheduler::init(void* machtnichts)
|
void LinuxScheduler::init(void* machtnichts)
|
||||||
{
|
{
|
||||||
clock_gettime(CLOCK_MONOTONIC, &_sketch_start_time);
|
clock_gettime(CLOCK_MONOTONIC, &_sketch_start_time);
|
||||||
|
|
||||||
|
_setup_realtime(32768);
|
||||||
|
|
||||||
pthread_attr_t thread_attr;
|
pthread_attr_t thread_attr;
|
||||||
struct sched_param param;
|
struct sched_param param;
|
||||||
|
|
||||||
@ -62,13 +77,21 @@ void LinuxScheduler::init(void* machtnichts)
|
|||||||
pthread_create(&_io_thread_ctx, &thread_attr, (pthread_startroutine_t)&Linux::LinuxScheduler::_io_thread, this);
|
pthread_create(&_io_thread_ctx, &thread_attr, (pthread_startroutine_t)&Linux::LinuxScheduler::_io_thread, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LinuxScheduler::_microsleep(uint32_t usec)
|
||||||
|
{
|
||||||
|
struct timespec ts;
|
||||||
|
ts.tv_sec = 0;
|
||||||
|
ts.tv_nsec = usec*1000UL;
|
||||||
|
while (nanosleep(&ts, &ts) == -1 && errno == EINTR) ;
|
||||||
|
}
|
||||||
|
|
||||||
void LinuxScheduler::delay(uint16_t ms)
|
void LinuxScheduler::delay(uint16_t ms)
|
||||||
{
|
{
|
||||||
uint32_t start = millis();
|
uint32_t start = millis();
|
||||||
|
|
||||||
while ((millis() - start) < ms) {
|
while ((millis() - start) < ms) {
|
||||||
// this yields the CPU to other apps
|
// this yields the CPU to other apps
|
||||||
poll(NULL, 0, 1);
|
_microsleep(1000);
|
||||||
if (_min_delay_cb_ms <= ms) {
|
if (_min_delay_cb_ms <= ms) {
|
||||||
if (_delay_cb) {
|
if (_delay_cb) {
|
||||||
_delay_cb();
|
_delay_cb();
|
||||||
@ -97,7 +120,7 @@ uint32_t LinuxScheduler::micros()
|
|||||||
|
|
||||||
void LinuxScheduler::delay_microseconds(uint16_t us)
|
void LinuxScheduler::delay_microseconds(uint16_t us)
|
||||||
{
|
{
|
||||||
usleep(us);
|
_microsleep(us);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LinuxScheduler::register_delay_callback(AP_HAL::Proc proc,
|
void LinuxScheduler::register_delay_callback(AP_HAL::Proc proc,
|
||||||
@ -189,8 +212,9 @@ void LinuxScheduler::_run_timers(bool called_from_timer_thread)
|
|||||||
|
|
||||||
void *LinuxScheduler::_timer_thread(void)
|
void *LinuxScheduler::_timer_thread(void)
|
||||||
{
|
{
|
||||||
|
_setup_realtime(32768);
|
||||||
while (true) {
|
while (true) {
|
||||||
poll(NULL, 0, 1);
|
_microsleep(1000);
|
||||||
|
|
||||||
// run registered timers
|
// run registered timers
|
||||||
_run_timers(true);
|
_run_timers(true);
|
||||||
@ -220,8 +244,9 @@ void LinuxScheduler::_run_io(void)
|
|||||||
|
|
||||||
void *LinuxScheduler::_uart_thread(void)
|
void *LinuxScheduler::_uart_thread(void)
|
||||||
{
|
{
|
||||||
|
_setup_realtime(32768);
|
||||||
while (true) {
|
while (true) {
|
||||||
poll(NULL, 0, 1);
|
_microsleep(1000);
|
||||||
|
|
||||||
// process any pending serial bytes
|
// process any pending serial bytes
|
||||||
((LinuxUARTDriver *)hal.uartA)->_timer_tick();
|
((LinuxUARTDriver *)hal.uartA)->_timer_tick();
|
||||||
@ -233,8 +258,9 @@ void *LinuxScheduler::_uart_thread(void)
|
|||||||
|
|
||||||
void *LinuxScheduler::_io_thread(void)
|
void *LinuxScheduler::_io_thread(void)
|
||||||
{
|
{
|
||||||
|
_setup_realtime(32768);
|
||||||
while (true) {
|
while (true) {
|
||||||
poll(NULL, 0, 1);
|
_microsleep(1000);
|
||||||
|
|
||||||
// process any pending storage writes
|
// process any pending storage writes
|
||||||
((LinuxStorage *)hal.storage)->_timer_tick();
|
((LinuxStorage *)hal.storage)->_timer_tick();
|
||||||
|
@ -42,6 +42,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
struct timespec _sketch_start_time;
|
struct timespec _sketch_start_time;
|
||||||
void _timer_handler(int signum);
|
void _timer_handler(int signum);
|
||||||
|
void _microsleep(uint32_t usec);
|
||||||
|
|
||||||
AP_HAL::Proc _delay_cb;
|
AP_HAL::Proc _delay_cb;
|
||||||
uint16_t _min_delay_cb_ms;
|
uint16_t _min_delay_cb_ms;
|
||||||
@ -73,6 +74,7 @@ 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 _setup_realtime(uint32_t size);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CONFIG_HAL_BOARD
|
#endif // CONFIG_HAL_BOARD
|
||||||
|
Loading…
Reference in New Issue
Block a user