Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(radio): async call handling to prevent GX12 switch lockups #5949

Merged
merged 7 commits into from
Mar 5, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions radio/src/edgetx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -250,19 +250,31 @@ void timer_10ms()
#include <FreeRTOS/include/FreeRTOS.h>
#include <FreeRTOS/include/timers.h>

static volatile bool _timer_10ms_cb_in_queue = false;

static void _timer_10ms_cb(void *pvParameter1, uint32_t ulParameter2)
{
(void)pvParameter1;
(void)ulParameter2;
_timer_10ms_cb_in_queue = false;
timer_10ms();
}

void per10ms()
{
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {

if (!_timer_10ms_cb_in_queue && xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xTimerPendFunctionCallFromISR(_timer_10ms_cb, nullptr, 0, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
BaseType_t xReturn = pdFALSE;

xReturn = xTimerPendFunctionCallFromISR(_timer_10ms_cb, nullptr, 0, &xHigherPriorityTaskWoken);

if (xReturn == pdPASS) {
_timer_10ms_cb_in_queue = true;
} else {
TRACE("xTimerPendFunctionCallFromISR() queue full");
}
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}
}

Expand Down
27 changes: 15 additions & 12 deletions radio/src/targets/taranis/gx12/bsp_io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ struct bsp_io_expander {
uint32_t state;
};

static volatile bool _poll_switches_in_queue = false;
static bsp_io_expander _io_switches;
static bsp_io_expander _io_fs_switches;

Expand All @@ -60,27 +61,29 @@ static uint32_t _read_io_expander(bsp_io_expander* io)
static void _poll_switches(void *pvParameter1, uint32_t ulParameter2)
{
(void)ulParameter2;
bsp_io_expander* io = (bsp_io_expander*)pvParameter1;
_read_io_expander(io);
_poll_switches_in_queue = false;
bsp_io_read_switches();
bsp_io_read_fs_switches();
}

static void _io_int_handler(bsp_io_expander* io)
static void _io_int_handler()
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
xTimerPendFunctionCallFromISR(_poll_switches, (void*)io, 0,
BaseType_t xReturn = pdFALSE;

if (!_poll_switches_in_queue && xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
xReturn = xTimerPendFunctionCallFromISR(_poll_switches, nullptr, 0,
&xHigherPriorityTaskWoken);

if (xReturn == pdPASS) {
_poll_switches_in_queue = true;
} else {
TRACE("xTimerPendFunctionCallFromISR() queue full");
}
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
} else {
_read_io_expander(io);
}
}

static void _io_int_handler() {
_io_int_handler(&_io_switches);
_io_int_handler(&_io_fs_switches);
}

int bsp_io_init()
{
timersInit();
Expand Down
17 changes: 15 additions & 2 deletions radio/src/telemetry/telemetry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -205,12 +205,15 @@ void telemetryStop()
}
}

static volatile bool _poll_frame_queued[NUM_MODULES] = {false};

static void _poll_frame(void *pvParameter1, uint32_t ulParameter2)
{
_telemetryIsPolling = true;

auto drv = (const etx_proto_driver_t*)pvParameter1;
auto module = (uint8_t)ulParameter2;
_poll_frame_queued[module] = false;

auto mod = pulsesGetModuleDriver(module);
if (!mod || !mod->drv || !mod->ctx || (drv != mod->drv))
Expand Down Expand Up @@ -246,8 +249,18 @@ static void _poll_frame(void *pvParameter1, uint32_t ulParameter2)
void telemetryFrameTrigger_ISR(uint8_t module, const etx_proto_driver_t* drv)
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xTimerPendFunctionCallFromISR(_poll_frame, (void*)drv, module, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
BaseType_t xReturn = pdFALSE;

if (!_poll_frame_queued[module] && xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
xReturn = xTimerPendFunctionCallFromISR(_poll_frame, (void*)drv, module, &xHigherPriorityTaskWoken);

if (xReturn == pdPASS) {
_poll_frame_queued[module] = true;
} else {
TRACE("xTimerPendFunctionCallFromISR() queue full");
}
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}
}
#endif

Expand Down