@ -26,7 +26,9 @@
@@ -26,7 +26,9 @@
# include <AP_Logger/AP_Logger.h>
# include <AP_InertialSensor/AP_InertialSensor.h>
# include <AP_InternalError/AP_InternalError.h>
# if CONFIG_HAL_BOARD == HAL_BOARD_SITL
# include <SITL/SITL.h>
# endif
# include <stdio.h>
# if APM_BUILD_TYPE(APM_BUILD_ArduCopter) || APM_BUILD_TYPE(APM_BUILD_ArduSub)
@ -131,8 +133,8 @@ void AP_Scheduler::run(uint32_t time_available)
@@ -131,8 +133,8 @@ void AP_Scheduler::run(uint32_t time_available)
}
for ( uint8_t i = 0 ; i < _num_tasks ; i + + ) {
uint16 _t dt = _tick_counter - _last_run [ i ] ;
uint16 _t interval_ticks = _loop_rate_hz / _tasks [ i ] . rate_hz ;
uint32 _t dt = _tick_counter - _last_run [ i ] ;
uint32 _t interval_ticks = _loop_rate_hz / _tasks [ i ] . rate_hz ;
if ( interval_ticks < 1 ) {
interval_ticks = 1 ;
}
@ -153,6 +155,12 @@ void AP_Scheduler::run(uint32_t time_available)
@@ -153,6 +155,12 @@ void AP_Scheduler::run(uint32_t time_available)
( unsigned ) _task_time_allowed ) ;
}
if ( dt > = interval_ticks * max_task_slowdown ) {
// we are going beyond the maximum slowdown factor for a
// task. This will trigger increasing the time budget
task_not_achieved + + ;
}
if ( _task_time_allowed > time_available ) {
// not enough time to run this task. Continue loop -
// maybe another task will fit into time remaining
@ -253,6 +261,17 @@ void AP_Scheduler::loop()
@@ -253,6 +261,17 @@ void AP_Scheduler::loop()
hal . util - > persistent_data . scheduler_task = - 1 ;
}
# if CONFIG_HAL_BOARD == HAL_BOARD_SITL
{
/*
for testing low CPU conditions we can add an optional delay in SITL
*/
auto * sitl = AP : : sitl ( ) ;
uint32_t loop_delay_us = sitl - > loop_delay . get ( ) ;
hal . scheduler - > delay_microseconds ( loop_delay_us ) ;
}
# endif
// tell the scheduler one tick has passed
tick ( ) ;
@ -262,14 +281,41 @@ void AP_Scheduler::loop()
@@ -262,14 +281,41 @@ void AP_Scheduler::loop()
// the first call to the scheduler they won't run on a later
// call until scheduler.tick() is called again
const uint32_t loop_us = get_loop_period_us ( ) ;
const uint32_t time_available = ( sample_time_us + loop_us ) - AP_HAL : : micros ( ) ;
run ( time_available > loop_us ? 0u : time_available ) ;
uint32_t now = AP_HAL : : micros ( ) ;
uint32_t time_available = 0 ;
if ( now - sample_time_us < loop_us ) {
// get remaining time available for this loop
time_available = loop_us - ( now - sample_time_us ) ;
}
// add in extra loop time determined by not achieving scheduler tasks
time_available + = extra_loop_us ;
// run the tasks
run ( time_available ) ;
# if CONFIG_HAL_BOARD == HAL_BOARD_SITL
// move result of AP_HAL::micros() forward:
hal . scheduler - > delay_microseconds ( 1 ) ;
# endif
if ( task_not_achieved > 0 ) {
// add some extra time to the budget
extra_loop_us = MIN ( extra_loop_us + 100U , 5000U ) ;
task_not_achieved = 0 ;
task_all_achieved = 0 ;
} else if ( extra_loop_us > 0 ) {
task_all_achieved + + ;
if ( task_all_achieved > 50 ) {
// we have gone through 50 loops without a task taking too
// long. CPU pressure has eased, so drop the extra time we're
// giving each loop
task_all_achieved = 0 ;
// we are achieving all tasks, slowly lower the extra loop time
extra_loop_us = MAX ( 0U , extra_loop_us - 50U ) ;
}
}
// check loop time
perf_info . check_loop_time ( sample_time_us - _loop_timer_start_us ) ;
@ -306,6 +352,7 @@ void AP_Scheduler::Log_Write_Performance()
@@ -306,6 +352,7 @@ void AP_Scheduler::Log_Write_Performance()
spi_count : pd . spi_count ,
i2c_count : pd . i2c_count ,
i2c_isr_count : pd . i2c_isr_count ,
extra_loop_us : extra_loop_us ,
} ;
AP : : logger ( ) . WriteCriticalBlock ( & pkt , sizeof ( pkt ) ) ;
}