fix power button shutdown: use an orb topic instead of a work queue call

px4_shutdown_request() was called from the power button IRQ callback, which
invoked a work queue callback. But on NuttX, the work queue uses a
semaphore, and thus it cannot be called from IRQ context.
This patch switches to publishing an uORB msg instead, which is handled in
the commander main thread.

To increase failure resistance, we could subscribe to the same topic in
another module for redundancy, in case commander runs wild.
This commit is contained in:
Beat Küng
2017-07-24 13:05:52 +02:00
committed by Lorenz Meier
parent 61b0a81bf9
commit 2815c62acf
4 changed files with 53 additions and 6 deletions
+43 -4
View File
@@ -104,6 +104,7 @@
#include <uORB/topics/mission_result.h>
#include <uORB/topics/offboard_control_mode.h>
#include <uORB/topics/position_setpoint_triplet.h>
#include <uORB/topics/power_button_state.h>
#include <uORB/topics/vehicle_roi.h>
#include <uORB/topics/parameter_update.h>
#include <uORB/topics/safety.h>
@@ -174,6 +175,8 @@ static int64_t lvel_probation_time_us = POSVEL_PROBATION_TAKEOFF;
/* Mavlink log uORB handle */
static orb_advert_t mavlink_log_pub = nullptr;
static orb_advert_t power_button_state_pub = nullptr;
/* System autostart ID */
static int autostart_id;
@@ -334,11 +337,34 @@ static void publish_status_flags(orb_advert_t &vehicle_status_flags_pub);
static int power_button_state_notification_cb(board_power_button_state_notification_e request)
{
// Note: this can be called from IRQ handlers
if (request == PWR_BUTTON_REQUEST_SHUT_DOWN) {
px4_shutdown_request(false, false);
// Note: this can be called from IRQ handlers, so we publish a message that will be handled
// on the main thread of commander.
power_button_state_s button_state;
button_state.timestamp = hrt_absolute_time();
int ret = PWR_BUTTON_RESPONSE_SHUT_DOWN_PENDING;
switch(request) {
case PWR_BUTTON_IDEL:
button_state.event = power_button_state_s::PWR_BUTTON_STATE_IDEL;
break;
case PWR_BUTTON_DOWN:
button_state.event = power_button_state_s::PWR_BUTTON_STATE_DOWN;
break;
case PWR_BUTTON_UP:
button_state.event = power_button_state_s::PWR_BUTTON_STATE_UP;
break;
case PWR_BUTTON_REQUEST_SHUT_DOWN:
button_state.event = power_button_state_s::PWR_BUTTON_STATE_REQUEST_SHUTDOWN;
break;
default:
PX4_ERR("unhandled power button state: %i", (int)request);
return ret;
}
return PWR_BUTTON_RESPONSE_SHUT_DOWN_PENDING;
int instance;
orb_publish_auto(ORB_ID(power_button_state), &power_button_state_pub, &button_state, &instance, ORB_PRIO_DEFAULT);
return ret;
}
int commander_main(int argc, char *argv[])
@@ -1641,6 +1667,8 @@ int commander_thread_main(int argc, char *argv[])
struct system_power_s system_power;
memset(&system_power, 0, sizeof(system_power));
int power_button_state_sub = orb_subscribe(ORB_ID(power_button_state));
/* Subscribe to actuator controls (outputs) */
int actuator_controls_sub = orb_subscribe(ORB_ID_VEHICLE_ATTITUDE_CONTROLS);
struct actuator_controls_s actuator_controls;
@@ -1878,6 +1906,17 @@ int commander_thread_main(int argc, char *argv[])
param_init_forced = false;
}
/* handle power button state */
orb_check(power_button_state_sub, &updated);
if (updated) {
power_button_state_s button_state;
orb_copy(ORB_ID(power_button_state), power_button_state_sub, &button_state);
if (button_state.event == power_button_state_s::PWR_BUTTON_STATE_REQUEST_SHUTDOWN) {
px4_shutdown_request(false, false);
}
}
orb_check(sp_man_sub, &updated);
if (updated) {