feat(radio): OS compatibility layer (#5840)

This commit is contained in:
Raphael Coeffic
2025-05-03 19:07:49 +10:00
committed by GitHub
parent c996612b0a
commit ab2a19e153
92 changed files with 1740 additions and 896 deletions
+21 -4
View File
@@ -484,9 +484,16 @@ if(NATIVE_BUILD)
${RADIOLIB_NATIVE_SRC}
)
# Add -DSIMU here PUBLIC, so it can be imported by other targets
# Add SIMU and POSIX_THREAD here PUBLIC, so it can be imported by other targets
# via INTERFACE_COMPILE_OPTIONS
target_compile_options(radiolib_native PUBLIC -DSIMU)
target_compile_options(radiolib_native PUBLIC -DSIMU -DPOSIX_THREADS)
target_sources(radiolib_native PUBLIC
os/async_native.cpp
os/sleep_native.cpp
os/task_pthread.cpp
os/time_native.cpp
os/timer_pthread.cpp
)
add_dependencies(radiolib_native ${RADIO_DEPENDENCIES})
set_property(TARGET radiolib_native PROPERTY POSITION_INDEPENDENT_CODE ON)
@@ -554,13 +561,23 @@ if(BOOTLOADER)
set(RADIO_DEPENDENCIES ${RADIO_DEPENDENCIES} bootloader)
endif()
add_definitions(-DFREE_RTOS)
add_executable(firmware ${SRC})
link_libraries(firmware -lstdc++)
add_dependencies(firmware ${RADIO_DEPENDENCIES})
set_target_properties(firmware PROPERTIES EXCLUDE_FROM_ALL TRUE)
target_compile_definitions(board PUBLIC FREE_RTOS)
target_compile_definitions(board_lib PUBLIC FREE_RTOS)
target_compile_definitions(firmware PUBLIC FREE_RTOS)
target_sources(firmware PUBLIC
os/async_freertos.cpp
os/sleep_freertos.cpp
os/task_freertos.cpp
os/time_freertos.cpp
os/timer_freertos.cpp
)
if(DEBUG)
target_compile_definitions(board PRIVATE -DDEBUG)
target_compile_definitions(firmware PRIVATE -DDEBUG)
+16 -35
View File
@@ -21,6 +21,9 @@
#include <math.h>
#include "os/sleep.h"
#include "os/task.h"
#include "edgetx.h"
#include "strhelpers.h"
#include "switches.h"
@@ -32,7 +35,7 @@
#include "model_audio.h"
#include "hal/audio_driver.h"
extern RTOS_MUTEX_HANDLE audioMutex;
extern mutex_handle_t audioMutex;
// Only first quadrant values - other quadrants calulated taking advantage of symmetry in sine wave.
const int16_t sineValues[] =
@@ -373,28 +376,6 @@ AudioQueue::AudioQueue()
#define CODEC_ID_PCM_S16LE 1
#if !defined(SIMU)
void audioTask(void * pdata)
{
while (!audioQueue.started()) {
RTOS_WAIT_TICKS(1);
}
#if defined(PCBX12S) || defined(RADIO_TX16S) || defined(RADIO_F16) || defined(RADIO_V16)
// The audio amp needs ~2s to start
RTOS_WAIT_MS(1000); // 1s
#endif
while (true) {
DEBUG_TIMER_SAMPLE(debugTimerAudioIterval);
DEBUG_TIMER_START(debugTimerAudioDuration);
audioQueue.wakeup();
DEBUG_TIMER_STOP(debugTimerAudioDuration);
RTOS_WAIT_MS(4); // ???
}
}
#endif
#if !defined(__SSAT)
#define _sat_s16(x) ((int16_t)limit<int32_t>(INT16_MIN, (x), INT16_MAX))
#else
@@ -638,9 +619,9 @@ void AudioQueue::wakeup()
// mix the normal context (tones and wavs)
if (normalContext.isEmpty() && !fragmentsFifo.empty()) {
RTOS_LOCK_MUTEX(audioMutex);
mutex_lock(&audioMutex);
normalContext.setFragment(fragmentsFifo.get());
RTOS_UNLOCK_MUTEX(audioMutex);
mutex_unlock(&audioMutex);
}
result = normalContext.mixBuffer(buffer, g_eeGeneral.beepVolume, g_eeGeneral.wavVolume, fade);
if (result > 0) {
@@ -724,7 +705,7 @@ void AudioQueue::playTone(uint16_t freq, uint16_t len, uint16_t pause, uint8_t f
return;
#endif
RTOS_LOCK_MUTEX(audioMutex);
mutex_lock(&audioMutex);
freq = limit<uint16_t>(BEEP_MIN_FREQ, freq, BEEP_MAX_FREQ);
@@ -747,7 +728,7 @@ void AudioQueue::playTone(uint16_t freq, uint16_t len, uint16_t pause, uint8_t f
}
}
RTOS_UNLOCK_MUTEX(audioMutex);
mutex_unlock(&audioMutex);
}
void AudioQueue::playFile(const char * filename, uint8_t flags, uint8_t id, int8_t fragmentVolume)
@@ -774,7 +755,7 @@ void AudioQueue::playFile(const char * filename, uint8_t flags, uint8_t id, int8
return;
}
RTOS_LOCK_MUTEX(audioMutex);
mutex_lock(&audioMutex);
if (flags & PLAY_BACKGROUND) {
backgroundContext.clear();
@@ -784,7 +765,7 @@ void AudioQueue::playFile(const char * filename, uint8_t flags, uint8_t id, int8
fragmentsFifo.push(AudioFragment(filename, flags & 0x0f, fragmentVolume, id));
}
RTOS_UNLOCK_MUTEX(audioMutex);
mutex_unlock(&audioMutex);
}
void AudioQueue::stopPlay(uint8_t id)
@@ -797,12 +778,12 @@ void AudioQueue::stopPlay(uint8_t id)
return;
#endif
RTOS_LOCK_MUTEX(audioMutex);
mutex_lock(&audioMutex);
fragmentsFifo.removePromptById(id);
backgroundContext.stop(id);
RTOS_UNLOCK_MUTEX(audioMutex);
mutex_unlock(&audioMutex);
}
void AudioQueue::stopSD()
@@ -815,19 +796,19 @@ void AudioQueue::stopSD()
void AudioQueue::stopAll()
{
flush();
RTOS_LOCK_MUTEX(audioMutex);
mutex_lock(&audioMutex);
priorityContext.clear();
normalContext.clear();
RTOS_UNLOCK_MUTEX(audioMutex);
mutex_unlock(&audioMutex);
}
void AudioQueue::flush()
{
RTOS_LOCK_MUTEX(audioMutex);
mutex_lock(&audioMutex);
fragmentsFifo.clear();
varioContext.clear();
backgroundContext.clear();
RTOS_UNLOCK_MUTEX(audioMutex);
mutex_unlock(&audioMutex);
}
void audioPlay(unsigned int index, uint8_t id)
-1
View File
@@ -470,7 +470,6 @@ void codecsInit();
void audioEvent(unsigned int index);
void audioPlay(unsigned int index, uint8_t id=0);
void audioStart();
void audioTask(void * pdata);
#if defined(AUDIO) && defined(BUZZER)
#define AUDIO_BUZZER(a, b) do { a; b; } while(0)
+5 -4
View File
@@ -23,6 +23,7 @@
#include "edgetx.h"
#include "io/frsky_firmware_update.h"
#include "bluetooth_driver.h"
#include "os/sleep.h"
#include "trainer.h"
#if defined(LIBOPENUI)
@@ -571,7 +572,7 @@ uint8_t Bluetooth::read(uint8_t * data, uint8_t size, uint32_t timeout)
if (elapsed++ >= timeout) {
return len;
}
RTOS_WAIT_MS(1);
sleep_ms(1);
}
data[len++] = byte;
}
@@ -829,11 +830,11 @@ const char * Bluetooth::flashFirmware(const char * filename, ProgressHandler pro
bluetoothInit(BLUETOOTH_BOOTLOADER_BAUDRATE, true); // normal mode
watchdogSuspend(500 /*5s*/);
RTOS_WAIT_MS(1000);
sleep_ms(1000);
bluetoothInit(BLUETOOTH_BOOTLOADER_BAUDRATE, false); // bootloader mode
watchdogSuspend(500 /*5s*/);
RTOS_WAIT_MS(1000);
sleep_ms(1000);
const char * result = doFlashFirmware(filename, progressHandler);
@@ -851,7 +852,7 @@ const char * Bluetooth::flashFirmware(const char * filename, ProgressHandler pro
/* wait 1s off */
watchdogSuspend(500 /*5s*/);
RTOS_WAIT_MS(1000);
sleep_ms(1000);
state = BLUETOOTH_STATE_OFF;
pulsesStart();
+9 -24
View File
@@ -30,18 +30,13 @@
#include "stm32_dma.h"
#include "stm32_gpio.h"
#include "hal/gpio.h"
#if !defined(SIMU)
#include <FreeRTOS/include/FreeRTOS.h>
#include <FreeRTOS/include/timers.h>
#endif
#include "os/timer.h"
static uint8_t _led_colors[WS2812_BYTES_PER_LED * LED_STRIP_LENGTH];
extern const stm32_pulse_timer_t _led_timer;
static TimerHandle_t rgbLedTimer = nullptr;
static StaticTimer_t rgbLedTimerBuffer;
static timer_handle_t _refresh_timer = TIMER_INITIALIZER;
void rgbSetLedColor(uint8_t led, uint8_t r, uint8_t g, uint8_t b)
{
@@ -77,35 +72,25 @@ void rgbLedClearAll()
ws2812_update(&_led_timer);
}
static void rgbLedTimerCb(TimerHandle_t xTimer)
static void _refresh_cb(timer_handle_t* timer)
{
(void)xTimer;
(void)timer;
ws2812_update(&_led_timer);
}
void rgbLedStart()
{
if (!rgbLedTimer) {
rgbLedTimer =
xTimerCreateStatic("rgbLed", LED_STRIP_REFRESH_PERIOD / RTOS_MS_PER_TICK, pdTRUE, (void*)0,
rgbLedTimerCb, &rgbLedTimerBuffer);
if (!timer_is_created(&_refresh_timer)) {
timer_create(&_refresh_timer, _refresh_cb, "rgbled",
LED_STRIP_REFRESH_PERIOD, true);
}
if (rgbLedTimer) {
if( xTimerStart( rgbLedTimer, 0 ) != pdPASS ) {
/* The timer could not be set into the Active state. */
}
}
timer_start(&_refresh_timer);
}
void rgbLedStop()
{
if (rgbLedTimer) {
if( xTimerStop( rgbLedTimer, 5 / RTOS_MS_PER_TICK ) != pdPASS ) {
/* The timer could not be stopped. */
}
}
timer_stop(&_refresh_timer);
}
const stm32_pulse_timer_t _led_timer = {
+30 -28
View File
@@ -32,6 +32,9 @@
#include "hal/watchdog_driver.h"
#include "edgetx.h"
#include "os/sleep.h"
#include "os/time.h"
#include "os/task.h"
#include "timers_driver.h"
#if defined(BLUETOOTH)
@@ -58,8 +61,8 @@
#define CLI_PRINT_BUFFER_SIZE 128
RTOS_TASK_HANDLE cliTaskId;
RTOS_DEFINE_STACK(cliTaskId, cliStack, CLI_STACK_SIZE);
task_handle_t cliTaskId;
TASK_DEFINE_STACK(cliStack, CLI_STACK_SIZE);
static uint8_t cliRxBufferStorage[CLI_RX_BUFFER_SIZE];
static StaticStreamBuffer_t cliRxBufferStatic;
@@ -188,9 +191,9 @@ static uint32_t cliGetBaudRate()
char cliLastLine[CLI_COMMAND_MAX_LEN+1];
typedef int (* CliFunction) (const char ** args);
int cliExecLine(char * line);
int cliExecCommand(const char ** argv);
int cliHelp(const char ** argv);
static int cliExecLine(char * line);
static int cliExecCommand(const char ** argv);
static int cliHelp(const char ** argv);
struct CliCommand
{
@@ -466,7 +469,7 @@ int cliTestNew()
{
char * tmp = nullptr;
cliSerialPrint("Allocating 1kB with new()");
RTOS_WAIT_MS(200);
sleep_ms(200);
tmp = new char[1024];
if (tmp) {
cliSerialPrint("\tsuccess");
@@ -478,7 +481,7 @@ int cliTestNew()
}
cliSerialPrint("Allocating 10MB with (std::nothrow) new()");
RTOS_WAIT_MS(200);
sleep_ms(200);
tmp = new (std::nothrow) char[1024*1024*10];
if (tmp) {
cliSerialPrint("\tFAILURE, tmp = %p", tmp);
@@ -490,7 +493,7 @@ int cliTestNew()
}
cliSerialPrint("Allocating 10MB with new()");
RTOS_WAIT_MS(200);
sleep_ms(200);
tmp = new char[1024*1024*10];
if (tmp) {
cliSerialPrint("\tFAILURE, tmp = %p", tmp);
@@ -569,10 +572,10 @@ void testClear() { lcdClear(); }
float runTimedFunctionTest(timedTestFunc_t func, const char *name,
uint32_t runtime, uint16_t step)
{
const uint32_t start = RTOS_GET_MS();
const uint32_t start = time_get_ms();
uint32_t noRuns = 0;
uint32_t actualRuntime = 0;
while ((actualRuntime = RTOS_GET_MS() - start) < runtime) {
while ((actualRuntime = time_get_ms() - start) < runtime) {
for (uint16_t n = 0; n < step; n++) {
func();
}
@@ -583,14 +586,14 @@ float runTimedFunctionTest(timedTestFunc_t func, const char *name,
cliSerialPrint("Test %s speed: %lu.%02u, (%lu runs in %lu ms)", name,
uint32_t(result), uint16_t((result - uint32_t(result)) * 100.0f),
noRuns, actualRuntime);
RTOS_WAIT_MS(200);
sleep_ms(200);
return result;
}
int cliTestGraphics()
{
cliSerialPrint("Starting graphics performance test...");
RTOS_WAIT_MS(200);
sleep_ms(200);
watchdogSuspend(6000 /*60s*/);
if (pulsesStarted()) {
@@ -723,7 +726,7 @@ void testMemoryCopyFrom_SDRAM_to_SDRAM_8bit()
int cliTestMemorySpeed()
{
cliSerialPrint("Starting memory speed test...");
RTOS_WAIT_MS(200);
sleep_ms(200);
watchdogSuspend(6000 /*60s*/);
if (pulsesStarted()) {
@@ -744,7 +747,7 @@ int cliTestMemorySpeed()
LTDC_Cmd(DISABLE);
cliSerialPrint("Disabling LCD...");
RTOS_WAIT_MS(200);
sleep_ms(200);
result += RUN_MEMORY_TEST(testMemoryReadFrom_RAM_8bit, 200);
result += RUN_MEMORY_TEST(testMemoryReadFrom_RAM_32bit, 200);
@@ -783,7 +786,7 @@ int cliTestModelsList()
int count = 0;
cliSerialPrint("Starting fetching RF data 100x...");
const uint32_t start = RTOS_GET_MS();
const uint32_t start = time_get_ms();
const list<ModelsCategory *> &cats = modList.getCategories();
while (1) {
@@ -803,7 +806,7 @@ int cliTestModelsList()
done:
cliSerialPrint("Done fetching %ix RF data: %lu ms", count,
(RTOS_GET_MS() - start));
(time_get_ms() - start));
return 0;
}
@@ -1474,7 +1477,7 @@ int cliRepeat(const char ** argv)
counter = interval;
uint8_t c;
const TickType_t xTimeout = 20 / RTOS_MS_PER_TICK;
const TickType_t xTimeout = 20 / portTICK_PERIOD_MS;
while (!xStreamBufferReceive(cliRxBuffer, &c, 1, xTimeout)
|| !(c == '\r' || c == '\n' || c == ' ')) {
@@ -1610,9 +1613,9 @@ int cliCrypt(const char ** argv)
mixerTaskStop();
perMainEnabled = false;
uint32_t startMs = RTOS_GET_MS();
uint32_t startMs = time_get_ms();
testAccessDenied(100000);
cliSerialPrintf("access_denied: %f us/run\r\n", (RTOS_GET_MS() - startMs)*1000.0f / 100000.0f);
cliSerialPrintf("access_denied: %f us/run\r\n", (time_get_ms() - startMs)*1000.0f / 100000.0f);
cliSerialPrint("Decrypted (SW):");
dumpBody(cryptOutput, sizeof(cryptOutput));
@@ -1706,7 +1709,7 @@ const CliCommand cliCommands[] = {
{ nullptr, nullptr, nullptr } /* sentinel */
};
int cliHelp(const char ** argv)
static int cliHelp(const char ** argv)
{
for (const CliCommand * command = cliCommands; command->name != nullptr; command++) {
if (argv[1][0] == '\0' || !strcmp(command->name, argv[0])) {
@@ -1722,7 +1725,7 @@ int cliHelp(const char ** argv)
return -1;
}
int cliExecCommand(const char ** argv)
static int cliExecCommand(const char ** argv)
{
if (argv[0][0] == '\0')
return 0;
@@ -1736,7 +1739,7 @@ int cliExecCommand(const char ** argv)
return -1;
}
int cliExecLine(char * line)
static int cliExecLine(char * line)
{
int len = strlen(line);
const char * argv[CLI_COMMAND_MAX_ARGS];
@@ -1759,7 +1762,7 @@ int cliExecLine(char * line)
#define CHAR_CR 0x0D
#define CHAR_DEL 0x7F
void cliTask(void * pdata)
static void cliTask()
{
char line[CLI_COMMAND_MAX_LEN+1];
int pos = 0;
@@ -1773,7 +1776,7 @@ void cliTask(void * pdata)
// of going byte-by-byte.
/* Block for max 100ms. */
const TickType_t xTimeout = 100 / RTOS_MS_PER_TICK;
const TickType_t xTimeout = 100 / portTICK_PERIOD_MS;
size_t xReceivedBytes = xStreamBufferReceive(cliRxBuffer, &c, 1, xTimeout);
if (!mixerTaskRunning()) {
@@ -1811,8 +1814,7 @@ void cliTask(void * pdata)
if (pos == 0 && cliLastLine[0]) {
// execute (repeat) last command
strcpy(line, cliLastLine);
}
else {
} else {
// save new command
strcpy(cliLastLine, line);
}
@@ -1843,6 +1845,6 @@ void cliStart()
// Setup consumer callback
cliReceiveCallBack = cliDefaultRx;
RTOS_CREATE_TASK(cliTaskId, cliTask, "CLI", cliStack, CLI_STACK_SIZE,
CLI_TASK_PRIO);
task_create(&cliTaskId, cliTask, "CLI", cliStack, CLI_STACK_SIZE,
CLI_TASK_PRIO);
}
+9 -46
View File
@@ -19,6 +19,7 @@
* GNU General Public License for more details.
*/
#include "os/sleep.h"
#if !defined(SIMU)
#include "stm32_ws2812.h"
#include "boards/generic_stm32/rgb_leds.h"
@@ -45,6 +46,7 @@
#include "tasks.h"
#include "tasks/mixer_task.h"
#include "os/async.h"
#if defined(BLUETOOTH)
#include "bluetooth_driver.h"
@@ -167,7 +169,7 @@ void checkValidMCU(void)
static bool evalFSok = false;
#endif
void timer_10ms()
void per10ms()
{
DEBUG_TIMER_START(debugTimerPer10ms);
DEBUG_TIMER_SAMPLE(debugTimerPer10msPeriod);
@@ -245,44 +247,6 @@ void timer_10ms()
DEBUG_TIMER_STOP(debugTimerPer10ms);
}
#if !defined(SIMU)
// Handle 10ms timer asynchronously
#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 (!_timer_10ms_cb_in_queue && xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
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 );
}
}
#else // !defined(SIMU)
void per10ms() { timer_10ms(); }
#endif
FlightModeData *flightModeAddress(uint8_t idx)
{
return &g_model.flightModeData[idx];
@@ -757,7 +721,7 @@ void checkAll(bool isBootCheck)
showMessageBox(STR_KEYSTUCK);
tmr10ms_t tgtime = get_tmr10ms() + 500;
while (tgtime != get_tmr10ms()) {
RTOS_WAIT_MS(1);
sleep_ms(1);
WDG_RESET();
}
}
@@ -875,8 +839,7 @@ void checkThrottleStick()
checkBacklight();
WDG_RESET();
RTOS_WAIT_MS(10);
sleep_ms(10);
}
LED_ERROR_END();
@@ -907,7 +870,7 @@ void alert(const char * title, const char * msg , uint8_t sound)
#endif
while (true) {
RTOS_WAIT_MS(10);
sleep_ms(10);
if (getEvent()) // wait for key release
break;
@@ -1131,10 +1094,10 @@ void edgeTxClose(uint8_t shutdown)
storageCheck(true);
while (IS_PLAYING(ID_PLAY_PROMPT_BASE + AU_BYE)) {
RTOS_WAIT_MS(10);
sleep_ms(10);
}
RTOS_WAIT_MS(100);
sleep_ms(100);
#if defined(COLORLCD)
cancelShutdownAnimation(); // To prevent simulator crash
@@ -1887,7 +1850,7 @@ uint32_t pwrCheck()
RAISE_ALERT(STR_MODEL, STR_MODEL_STILL_POWERED, STR_PRESS_ENTER_TO_CONFIRM, AU_MODEL_STILL_POWERED);
while (TELEMETRY_STREAMING()) {
resetForcePowerOffRequest();
RTOS_WAIT_MS(20);
sleep_ms(20);
if (pwrPressed()) {
return e_power_on;
}
+5 -3
View File
@@ -21,7 +21,9 @@
#include "edgetx.h"
#include "tasks.h"
#include "mixer_scheduler.h"
#include "tasks/mixer_task.h"
#include "hal/adc_driver.h"
@@ -169,12 +171,12 @@ void menuStatisticsDebug(event_t event)
y += FH;
lcdDrawTextAlignedLeft(y, STR_FREE_STACK);
lcdDrawNumber(MENU_DEBUG_COL1_OFS, y, menusStack.available(), LEFT);
lcdDrawNumber(MENU_DEBUG_COL1_OFS, y, task_get_stack_usage(&menusTaskId), LEFT);
lcdDrawText(lcdLastRightPos, y, "/");
lcdDrawNumber(lcdLastRightPos, y, mixerStack.available(), LEFT);
lcdDrawNumber(lcdLastRightPos, y, task_get_stack_usage(&mixerTaskId), LEFT);
#if defined(AUDIO)
lcdDrawText(lcdLastRightPos, y, "/");
lcdDrawNumber(lcdLastRightPos, y, audioStack.available(), LEFT);
lcdDrawNumber(lcdLastRightPos, y, task_get_stack_usage(&audioTaskId), LEFT);
#endif
y += FH;
+5 -3
View File
@@ -21,7 +21,9 @@
#include "hal/adc_driver.h"
#include "edgetx.h"
#include "tasks.h"
#include "tasks/mixer_task.h"
#define STATS_1ST_COLUMN FW/2
#define STATS_2ND_COLUMN 12*FW+FW/2
@@ -188,12 +190,12 @@ void menuStatisticsDebug(event_t event)
lcdDrawTextAlignedLeft(y, STR_FREE_STACK);
lcdDrawText(MENU_DEBUG_COL1_OFS, y+1, "[M]", SMLSIZE);
lcdDrawNumber(lcdLastRightPos, y, menusStack.available(), LEFT);
lcdDrawNumber(lcdLastRightPos, y, task_get_stack_usage(&menusTaskId), LEFT);
lcdDrawText(lcdLastRightPos+2, y+1, "[X]", SMLSIZE);
lcdDrawNumber(lcdLastRightPos, y, mixerStack.available(), LEFT);
lcdDrawNumber(lcdLastRightPos, y, task_get_stack_usage(&mixerTaskId), LEFT);
#if defined(AUDIO)
lcdDrawText(lcdLastRightPos+2, y+1, "[A]", SMLSIZE);
lcdDrawNumber(lcdLastRightPos, y, audioStack.available(), LEFT);
lcdDrawNumber(lcdLastRightPos, y, task_get_stack_usage(&audioTaskId), LEFT);
#endif
lcdDrawText(lcdLastRightPos+2, y+1, "[I]", SMLSIZE);
lcdDrawNumber(lcdLastRightPos, y, mainStackAvailable(), LEFT);
+5 -3
View File
@@ -21,6 +21,7 @@
#include "edgetx.h"
#include "hal/rotary_encoder.h"
#include "os/time.h"
#include "LvglWrapper.h"
#include "etx_lv_theme.h"
@@ -359,9 +360,10 @@ LvglWrapper* LvglWrapper::instance()
void LvglWrapper::run()
{
#if defined(SIMU)
tmr10ms_t tick = get_tmr10ms();
lv_tick_inc((tick - lastTick) * 10);
lastTick = tick;
static uint32_t last_tick = 0;
uint32_t tick = time_get_ms();
lv_tick_inc(tick - last_tick);
last_tick = tick;
#endif
lv_timer_handler();
}
-3
View File
@@ -33,9 +33,6 @@ class LvglWrapper
static LvglWrapper *_instance;
static void pollInputs();
tmr10ms_t lastTick = 0;
// TODO: add driver instances here
LvglWrapper();
~LvglWrapper() {}
@@ -26,6 +26,7 @@
#include "mainwindow.h"
#include "edgetx.h"
#include "etx_lv_theme.h"
#include "os/sleep.h"
#include "view_main.h"
#include "hal/watchdog_driver.h"
@@ -186,7 +187,7 @@ static void run_ui_manually()
checkBacklight();
WDG_RESET();
RTOS_WAIT_MS(10);
sleep_ms(10);
LvglWrapper::runNested();
MainWindow::instance()->run(false);
}
@@ -211,7 +212,7 @@ void FullScreenDialog::runForever(bool checkPwr)
#endif
} else if (check == e_power_press) {
WDG_RESET();
RTOS_WAIT_MS(1);
sleep_ms(1);
continue;
}
}
+11 -9
View File
@@ -23,6 +23,8 @@
#include "libopenui.h"
#include "edgetx.h"
#include "lvgl/src/hal/lv_hal_tick.h"
#include "os/sleep.h"
#include "pwr.h"
#include "hal/watchdog_driver.h"
#include "etx_lv_theme.h"
@@ -51,7 +53,7 @@ static void _run_popup_dialog(const char* title, const char* msg,
#endif
} else if (check == e_power_press) {
WDG_RESET();
RTOS_WAIT_MS(1);
sleep_ms(1);
continue;
}
@@ -59,7 +61,7 @@ static void _run_popup_dialog(const char* title, const char* msg,
WDG_RESET();
MainWindow::instance()->run();
LvglWrapper::runNested();
RTOS_WAIT_MS(20);
sleep_ms(20);
}
}
@@ -95,7 +97,7 @@ void POPUP_WARNING_ON_UI_TASK(const char* message, const char* info,
// Wait in case already in popup.
while (ui_popup_active) {
RTOS_WAIT_MS(20);
sleep_ms(20);
}
ui_popup_title = "Warning";
ui_popup_msg = message;
@@ -105,7 +107,7 @@ void POPUP_WARNING_ON_UI_TASK(const char* message, const char* info,
// Wait until closed
if (waitForClose) {
while (ui_popup_active) {
RTOS_WAIT_MS(20);
sleep_ms(20);
}
}
}
@@ -151,7 +153,8 @@ class BubbleDialog : public Window
public:
BubbleDialog(const char* message, int timeout, coord_t width) :
Window(MainWindow::instance(), rect_t{(LCD_W - width) / 2, LCD_H - 100, width, 50},
bubble_popup_create)
bubble_popup_create),
startTime(lv_tick_get()), timeout(timeout)
{
setWindowFlag(OPAQUE);
@@ -163,21 +166,20 @@ class BubbleDialog : public Window
lv_obj_set_width(label, lv_pct(100));
etx_obj_add_style(label, styles->text_align_center, LV_PART_MAIN);
lv_label_set_long_mode(label, LV_LABEL_LONG_WRAP);
endTime = RTOS_GET_MS() + timeout;
}
bool isBubblePopup() override { return true; }
void checkEvents() override
{
if (RTOS_GET_MS() >= endTime) {
if (lv_tick_elaps(startTime) >= timeout) {
deleteLater();
}
}
protected:
uint32_t endTime;
uint32_t startTime;
uint32_t timeout;
};
void POPUP_BUBBLE(const char* message, uint32_t timeout, coord_t width)
+4 -4
View File
@@ -37,13 +37,13 @@ static bool timepg = false;
static void on_draw_begin(lv_event_t* e)
{
if (timepg) {
dsms = RTOS_GET_MS();
dsms = lv_tick_get();
}
}
static void on_draw_end(lv_event_t* e)
{
timepg = false;
dems = RTOS_GET_MS();
dems = lv_tick_get();
TRACE("tab time: build %ld layout %ld draw %ld total %ld",
end_ms - start_ms, dsms - end_ms, dems - dsms, dems - start_ms);
}
@@ -301,7 +301,7 @@ void TabsGroup::setCurrentTab(unsigned index)
currentTab = tab;
#if defined(DEBUG)
start_ms = RTOS_GET_MS();
start_ms = lv_tick_get();
timepg = true;
#endif
@@ -321,7 +321,7 @@ void TabsGroup::setCurrentTab(unsigned index)
lv_obj_refresh_style(body->getLvObj(), LV_PART_ANY, LV_STYLE_PROP_ANY);
#if defined(DEBUG)
end_ms = RTOS_GET_MS();
end_ms = lv_tick_get();
#endif
}
}
@@ -114,7 +114,7 @@ coord_t TopBar::getVisibleHeight(float visible) const // 0.0 -> 1.0
void TopBar::checkEvents()
{
uint32_t now = RTOS_GET_MS();
uint32_t now = lv_tick_get();
if (now - lastRefresh >= TOPBAR_REFRESH) {
lastRefresh = now;
TopBarBase::checkEvents();
@@ -20,6 +20,7 @@
*/
#include "view_statistics.h"
#include "os/task.h"
#include "edgetx.h"
#include "tasks.h"
@@ -333,14 +334,14 @@ void DebugViewPage::build(Window* window)
#endif
new DebugInfoNumber<uint32_t>(
line, rect_t{0, 0, DBG_B_WIDTH, DBG_B_HEIGHT},
[] { return menusStack.available(); }, STR_STACK_MENU);
[] { return task_get_stack_usage(&menusTaskId); }, STR_STACK_MENU);
new DebugInfoNumber<uint32_t>(
line, rect_t{0, 0, DBG_B_WIDTH, DBG_B_HEIGHT},
[] { return mixerStack.available(); }, STR_STACK_MIX);
[] { return task_get_stack_usage(&mixerTaskId); }, STR_STACK_MIX);
#if defined(AUDIO)
new DebugInfoNumber<uint32_t>(
line, rect_t{0, 0, DBG_B_WIDTH, DBG_B_HEIGHT},
[] { return audioStack.available(); }, STR_STACK_AUDIO);
[] { return task_get_stack_usage(&audioTaskId); }, STR_STACK_AUDIO);
#endif
#if defined(DEBUG_LATENCY)
@@ -367,7 +367,7 @@ class SensorButton : public ListLineButton
else
lv_obj_add_flag(fresh, LV_OBJ_FLAG_HIDDEN);
uint32_t now = RTOS_GET_MS();
uint32_t now = lv_tick_get();
TelemetryItem& telemetryItem = telemetryItems[index];
// Update value
@@ -479,7 +479,7 @@ class SensorEditWindow : public SubPage
void checkEvents() override
{
uint32_t now = RTOS_GET_MS();
uint32_t now = lv_tick_get();
TelemetryItem& telemetryItem = telemetryItems[index];
if ((now - lastRefresh >= 200) || telemetryItem.isFresh()) {
@@ -609,8 +609,8 @@ class ModuleSubTypeChoice : public Choice
MultiModuleStatus& status = getMultiModuleStatus(moduleIdx);
status.invalidate();
uint32_t startUpdate = RTOS_GET_MS();
while (!status.isValid() && (RTOS_GET_MS() - startUpdate < 250))
uint32_t startUpdate = lv_tick_get();
while (!status.isValid() && (lv_tick_elaps(startUpdate) < 250))
;
SET_DIRTY();
#endif
@@ -44,9 +44,9 @@ void RfScanDialog::checkEvents()
{
if (!protos->isScanning()) {
closeDialog();
} else if (RTOS_GET_MS() - lastUpdate >= 200) {
} else if (lv_tick_elaps(lastUpdate) >= 200) {
showProgress();
lastUpdate = RTOS_GET_MS();
lastUpdate = lv_tick_get();
}
ProgressDialog::checkEvents();
@@ -25,6 +25,7 @@
#include "edgetx.h"
#include "telemetry/ghost.h"
#include "telemetry/ghost_menu.h"
#include "os/sleep.h"
class GhostModuleConfigWindow : public Window
{
@@ -166,7 +167,7 @@ void RadioGhostModuleConfig::onLongPressRTN()
reusableBuffer.ghostMenu.buttonAction = GHST_BTN_NONE;
reusableBuffer.ghostMenu.menuAction = GHST_MENU_CTRL_CLOSE;
moduleState[EXTERNAL_MODULE].counter = GHST_MENU_CONTROL;
RTOS_WAIT_MS(10);
sleep_ms(10);
#if defined(TRIMS_EMULATE_BUTTONS)
setHatsAsKeys(false); // switch trims back to normal
#endif
@@ -183,7 +184,7 @@ void RadioGhostModuleConfig::checkEvents()
reusableBuffer.ghostMenu.menuAction = GHST_MENU_CTRL_OPEN;
moduleState[EXTERNAL_MODULE].counter = GHST_MENU_CONTROL;
} else if (reusableBuffer.ghostMenu.menuStatus == GHST_MENU_STATUS_CLOSING) {
RTOS_WAIT_MS(10);
sleep_ms(10);
deleteLater();
#if defined(TRIMS_EMULATE_BUTTONS)
setHatsAsKeys(false); // switch trims back to normal
+3 -2
View File
@@ -22,6 +22,7 @@
#include "hal/abnormal_reboot.h"
#include "inactivity_timer.h"
#include "edgetx.h"
#include "os/sleep.h"
#include "stamp.h"
#include "theme_manager.h"
@@ -123,7 +124,7 @@ void waitSplash()
if (splashStartTime) {
#if defined(SIMU)
// Simulator - inputsMoved() returns true immediately without this!
RTOS_WAIT_TICKS(30);
sleep_ms(30);
#endif // defined(SIMU)
splashStartTime += SPLASH_TIMEOUT;
@@ -133,7 +134,7 @@ void waitSplash()
WDG_RESET();
checkSpeakerVolume();
checkBacklight();
RTOS_WAIT_TICKS(10);
sleep_ms(10);
auto evt = getEvent();
if (evt || inactivityCheckInputs()) {
if (evt) killEvents(evt);
@@ -20,6 +20,7 @@
*/
#include "edgetx.h"
#include "os/sleep.h"
#if defined(GHOST) && defined(HARDWARE_EXTERNAL_MODULE)
@@ -84,7 +85,7 @@ void menuGhostModuleConfig(event_t event)
reusableBuffer.ghostMenu.buttonAction = GHST_BTN_NONE;
reusableBuffer.ghostMenu.menuAction = GHST_MENU_CTRL_CLOSE;
moduleState[EXTERNAL_MODULE].counter = GHST_MENU_CONTROL;
RTOS_WAIT_MS(10);
sleep_ms(10);
popMenu();
break;
}
@@ -20,6 +20,7 @@
*/
#include "edgetx.h"
#include "os/sleep.h"
#include "timers_driver.h"
extern uint8_t g_moduleIdx;
@@ -52,7 +53,7 @@ void menuRadioPowerMeter(event_t event)
moduleState[g_moduleIdx].readModuleInformation(&reusableBuffer.moduleSetup.pxx2.moduleInformation, PXX2_HW_INFO_TX_ID, PXX2_HW_INFO_TX_ID);
/* wait 1s to resume normal operation before leaving */
watchdogSuspend(500 /*5s*/);
RTOS_WAIT_MS(1000);
sleep_ms(1000);
return;
}
@@ -20,6 +20,7 @@
*/
#include "edgetx.h"
#include "os/sleep.h"
#include "timers_driver.h"
extern uint8_t g_moduleIdx;
@@ -49,7 +50,7 @@ void menuRadioSpectrumAnalyser(event_t event)
#endif
/* wait 1s to resume normal operation before leaving */
watchdogSuspend(500 /*5s*/);
RTOS_WAIT_MS(1000);
sleep_ms(1000);
return;
}
+2 -1
View File
@@ -21,6 +21,7 @@
#include "edgetx.h"
#include "inactivity_timer.h"
#include "os/sleep.h"
static bool splashStarted = false;
@@ -53,7 +54,7 @@ void waitSplash()
tmr10ms_t tgtime = get_tmr10ms() + SPLASH_TIMEOUT;
while (tgtime > get_tmr10ms()) {
RTOS_WAIT_TICKS(1);
sleep_ms(1);
getADC();
+3 -2
View File
@@ -27,6 +27,7 @@
#include "edgetx.h"
#include "switches.h"
#include "mixes.h"
#include "os/sleep.h"
#undef CPN
#include "MultiSubtypeDefs.h"
@@ -756,7 +757,7 @@ static void runAntennaSelectionMenu()
WDG_RESET();
MainWindow::instance()->run();
LvglWrapper::runNested();
RTOS_WAIT_MS(20);
sleep_ms(20);
}
}
#else
@@ -1229,7 +1230,7 @@ bool confirmModelChange()
if (TELEMETRY_STREAMING()) {
RAISE_ALERT(STR_MODEL, STR_MODEL_STILL_POWERED, STR_PRESS_ENTER_TO_CONFIRM, AU_MODEL_STILL_POWERED);
while (TELEMETRY_STREAMING()) {
RTOS_WAIT_MS(20);
sleep_ms(20);
if (readKeys() == (1 << KEY_ENTER)) {
killEvents(KEY_ENTER);
return true;
+5 -5
View File
@@ -23,7 +23,7 @@
#include "FatFs/diskio.h"
#if FF_FS_REENTRANT != 0
#include "rtos.h"
#include "os/task.h"
#endif
struct fatfs_drive_t {
@@ -31,7 +31,7 @@ struct fatfs_drive_t {
uint8_t lun;
bool initialized;
#if FF_FS_REENTRANT != 0
RTOS_MUTEX_HANDLE mutex;
mutex_handle_t mutex;
#endif
};
@@ -52,7 +52,7 @@ int fatfsRegisterDriver(const diskio_driver_t* drv, uint8_t lun)
#if FF_FS_REENTRANT != 0
// init IO mutex only once
RTOS_CREATE_MUTEX(drive.mutex);
mutex_create(&drive.mutex);
#endif
return 1;
@@ -100,10 +100,10 @@ int ff_mutex_create(int vol)
int ff_mutex_take(int vol)
{
return RTOS_LOCK_MUTEX(_fatfs_drives[vol].mutex);
return mutex_lock(&_fatfs_drives[vol].mutex);
}
void ff_mutex_give(int vol) { RTOS_UNLOCK_MUTEX(_fatfs_drives[vol].mutex); }
void ff_mutex_give(int vol) { mutex_unlock(&_fatfs_drives[vol].mutex); }
void ff_mutex_delete(int vol) { }
+2 -3
View File
@@ -27,6 +27,7 @@
#include "flash_driver.h"
#include "hal/watchdog_driver.h"
#include "os/sleep.h"
#if defined(LIBOPENUI)
#include "libopenui.h"
@@ -104,9 +105,7 @@ void BootloaderFirmwareUpdate::flashFirmware(const char * filename, ProgressHand
if (f_eof(&file)) break;
#if defined(SIMU)
// add an artificial delay and check for simu quit
if (SIMU_SLEEP_OR_EXIT_MS(30))
break;
sleep_ms(30);
#endif
}
+13 -14
View File
@@ -23,6 +23,7 @@
#include "edgetx.h"
#include "frsky_firmware_update.h"
#include "debug.h"
#include "os/sleep.h"
#include "timers_driver.h"
#include "tasks/mixer_task.h"
@@ -118,11 +119,9 @@ bool FrskyDeviceFirmwareUpdate::readBuffer(uint8_t * buffer, uint8_t count, uint
while (index < count && elapsed < timeout) {
if (uart_drv->getByte(uart_ctx, &(buffer[index]))) {
++index;
}
else {
RTOS_WAIT_MS(1);
if (++elapsed == timeout)
return false;
} else {
sleep_ms(1);
if (++elapsed == timeout) return false;
}
}
@@ -131,7 +130,7 @@ bool FrskyDeviceFirmwareUpdate::readBuffer(uint8_t * buffer, uint8_t count, uint
const uint8_t * FrskyDeviceFirmwareUpdate::readFrame(uint32_t timeout)
{
RTOS_WAIT_MS(1);
sleep_ms(1);
uint8_t len = 0;
bool bytestuff = false;
@@ -142,7 +141,7 @@ const uint8_t * FrskyDeviceFirmwareUpdate::readFrame(uint32_t timeout)
uint8_t byte = 0;
while (uart_drv->getByte(uart_ctx, &byte) == 0) {
RTOS_WAIT_MS(1);
sleep_ms(1);
if (elapsed++ >= timeout) {
TRACE("timeout in frame (len=%d)",len);
return nullptr;
@@ -178,7 +177,7 @@ bool FrskyDeviceFirmwareUpdate::waitState(State newState, uint32_t timeout)
static uint8_t pass = 0;
if (++pass == 10) {
pass = 0;
RTOS_WAIT_MS(1);
sleep_ms(1);
}
return true;
#else
@@ -226,7 +225,7 @@ const char * FrskyDeviceFirmwareUpdate::sendPowerOn()
{
state = SPORT_POWERUP_REQ;
RTOS_WAIT_MS(50);
sleep_ms(50);
uart_drv->clearRxBuffer(uart_ctx);
for (int i=0; i<10; i++) {
@@ -242,7 +241,7 @@ const char * FrskyDeviceFirmwareUpdate::sendPowerOn()
const char * FrskyDeviceFirmwareUpdate::sendReqVersion()
{
RTOS_WAIT_MS(20);
sleep_ms(20);
uart_drv->clearRxBuffer(uart_ctx);
state = SPORT_VERSION_REQ;
@@ -354,7 +353,7 @@ const char *FrskyDeviceFirmwareUpdate::doFlashFirmware(
if (set_pwr) set_pwr(true);
// wait a bit for PWR to settle
RTOS_WAIT_MS(1);
sleep_ms(1);
// Special update method for X12S / X10 iXJT
if (module == INTERNAL_MODULE && port == ETX_MOD_PORT_UART && set_bootcmd != nullptr) {
@@ -408,7 +407,7 @@ const char *FrskyDeviceFirmwareUpdate::uploadFileToHorusXJT(
if (count == 0) {
uart_drv->sendByte(uart_ctx, 0xA1);
RTOS_WAIT_MS(50);
sleep_ms(50);
return nullptr;
}
@@ -453,7 +452,7 @@ const char *FrskyDeviceFirmwareUpdate::uploadFileNormal(
if (result)
return result;
RTOS_WAIT_MS(200);
sleep_ms(200);
uart_drv->clearRxBuffer(uart_ctx);
state = SPORT_DATA_TRANSFER;
@@ -519,7 +518,7 @@ const char *FrskyDeviceFirmwareUpdate::flashFirmware(
/* wait 2s off */
watchdogSuspend(1000 /*10s*/);
RTOS_WAIT_MS(2000);
sleep_ms(2000);
const char * result = doFlashFirmware(filename, progressHandler);
+9 -8
View File
@@ -19,6 +19,7 @@
* GNU General Public License for more details.
*/
#include "os/sleep.h"
#if !defined(DISABLE_MULTI_UPDATE)
#include "hal.h"
@@ -32,6 +33,7 @@
#include "timers_driver.h"
#include "hal/watchdog_driver.h"
#include "os/time.h"
#include <memory>
@@ -157,9 +159,9 @@ void MultiFirmwareUpdateDriver::deinit()
bool MultiFirmwareUpdateDriver::getRxByte(uint8_t & byte) const
{
uint32_t time = RTOS_GET_MS();
uint32_t time = time_get_ms();
while ((RTOS_GET_MS() - time) < 100) { // 100ms
while ((time_get_ms() - time) < 100) { // 100ms
if (getByte(byte)) {
#if defined(DEBUG_EXT_MODULE_FLASH)
TRACE("[RX] 0x%X", byte);
@@ -220,7 +222,7 @@ const char * MultiFirmwareUpdateDriver::waitForInitialSync()
// avoids sending STK_READ_SIGN with STK_OK
// in case the receiver is too slow changing
// to RX mode (half-duplex).
RTOS_WAIT_TICKS(1);
sleep_ms(1);
return nullptr;
}
@@ -258,7 +260,7 @@ const char * MultiFirmwareUpdateDriver::loadAddress(uint32_t offset) const
// avoids sending next page back-to-back with STK_OK
// in case the receiver is to slow changing to RX mode (half-duplex).
RTOS_WAIT_TICKS(1);
sleep_ms(1);
return nullptr;
}
@@ -310,8 +312,7 @@ const char* MultiFirmwareUpdateDriver::flashFirmware(
#if defined(SIMU)
for (uint16_t i = 0; i < 100; i++) {
progressHandler(label, STR_WRITING, i, 100);
if (SIMU_SLEEP_OR_EXIT_MS(30))
break;
sleep_ms(30);
}
return nullptr;
#endif
@@ -321,7 +322,7 @@ const char* MultiFirmwareUpdateDriver::flashFirmware(
/* wait 500ms for power on */
watchdogSuspend(500 /*5s*/);
RTOS_WAIT_MS(500);
sleep_ms(500);
result = waitForInitialSync();
if (result) {
@@ -553,7 +554,7 @@ bool MultiDeviceFirmwareUpdate::flashFirmware(const char * filename, ProgressHan
/* wait 2s off */
watchdogSuspend(500 /*5s*/);
RTOS_WAIT_MS(3000);
sleep_ms(3000);
MultiFirmwareUpdateDriver driver(module, type);
const char * result = driver.flashFirmware(&file, getBasename(filename), progressHandler);
+16 -52
View File
@@ -29,30 +29,20 @@
#include "gui_common.h"
#include "edgetx.h" // reusableBuffer
#include "os/time.h"
#include <algorithm>
#if !defined(SIMU)
static timer_handle_t _protoScanTimers[NUM_MODULES] = {TIMER_INITIALIZER};
#include <FreeRTOS/include/FreeRTOS.h>
#include <FreeRTOS/include/timers.h>
struct ProtoScanTimer {
TimerHandle_t timer = nullptr;
StaticTimer_t timerBuffer;
};
static ProtoScanTimer _protoScanTimers[NUM_MODULES];
void MultiRfProtocols::timerCb(TimerHandle_t xTimer)
void MultiRfProtocols::timerCb(timer_handle_t* h)
{
uint8_t moduleIdx = (uint8_t)(uintptr_t)pvTimerGetTimerID(xTimer);
uint8_t moduleIdx = (uint8_t)(h - _protoScanTimers);
auto instance = MultiRfProtocols::instance(moduleIdx);
if (instance->scanState == ScanBegin || instance->scanState == Scanning) {
instance->fillBuiltinProtos();
}
}
#endif
MultiRfProtocols* MultiRfProtocols::_instance[MAX_MODULES] = {};
@@ -201,7 +191,7 @@ float MultiRfProtocols::getProgress() const
if (scanState == ScanStop) return 0.0;
if (scanState == ScanBegin) {
float t = (float)(RTOS_GET_MS() - scanStart) / (float)MULTI_PROTOLIST_START_TIMEOUT;
float t = (float)(time_get_ms() - scanStart) / (float)MULTI_PROTOLIST_START_TIMEOUT;
return t * WAIT_TIME_RATIO;
}
@@ -225,29 +215,17 @@ bool MultiRfProtocols::triggerScan()
scanState = ScanBegin;
currentProto = MULTI_INVALID_PROTO;
moduleState[moduleIdx].mode = MODULE_MODE_GET_HARDWARE_INFO;
scanStart = lastScan = RTOS_GET_MS();
scanStart = lastScan = time_get_ms();
#if !defined(SIMU)
auto scanTimer = &_protoScanTimers[moduleIdx];
if (!scanTimer->timer) {
scanTimer->timer = xTimerCreateStatic(
"MPM", MULTI_PROTOLIST_START_TIMEOUT / RTOS_MS_PER_TICK, pdTRUE,
(void*)moduleIdx, MultiRfProtocols::timerCb, &scanTimer->timerBuffer);
if (!timer_is_created(scanTimer)) {
timer_create(scanTimer, MultiRfProtocols::timerCb, "mpm",
MULTI_PROTOLIST_START_TIMEOUT, false);
timer_start(scanTimer);
} else {
if (xTimerChangePeriod(scanTimer->timer,
MULTI_PROTOLIST_START_TIMEOUT / RTOS_MS_PER_TICK,
0) != pdPASS) {
/* The timer period could not be reset. */
}
timer_set_period(scanTimer, MULTI_PROTOLIST_START_TIMEOUT);
}
if (scanTimer->timer) {
if( xTimerStart( scanTimer->timer, 0 ) != pdPASS ) {
/* The timer could not be set into the Active state. */
}
}
#endif
return true;
}
@@ -291,32 +269,18 @@ bool MultiRfProtocols::scanReply(const uint8_t* packet, uint8_t len)
}
currentProto++;
lastScan = RTOS_GET_MS();
lastScan = time_get_ms();
#if !defined(SIMU)
auto scanTimer = &_protoScanTimers[moduleIdx];
if (scanTimer->timer) {
if (xTimerChangePeriod(scanTimer->timer,
MULTI_PROTOLIST_TIMEOUT / RTOS_MS_PER_TICK,
0) != pdPASS) {
/* The timer period could not be reset. */
}
}
#endif
timer_set_period(scanTimer, MULTI_PROTOLIST_TIMEOUT);
return true;
} else {
scanState = ScanEnd;
setModuleMode(moduleIdx, MODULE_MODE_NORMAL);
#if !defined(SIMU)
auto scanTimer = &_protoScanTimers[moduleIdx];
if (scanTimer->timer) {
if (xTimerStop(scanTimer->timer, 0) != pdPASS) {
/* The timer period could not be stopped. */
}
}
#endif
timer_stop(scanTimer);
break;
}
} else {
@@ -328,7 +292,7 @@ bool MultiRfProtocols::scanReply(const uint8_t* packet, uint8_t len)
timeout = MULTI_PROTOLIST_START_TIMEOUT;
}
if (RTOS_GET_MS() - lastScan >= timeout) {
if (time_get_ms() - lastScan >= timeout) {
TRACE("proto scan timeout!");
scanState = ScanInvalid;
}
+3 -9
View File
@@ -22,17 +22,13 @@
#include "dataconstants.h"
#include "edgetx_types.h"
#include "os/timer.h"
#include <functional>
#include <string>
#include <vector>
#include <map>
#if !defined(SIMU)
// Forward declare FreeRTOS timer
struct tmrTimerControl;
typedef struct tmrTimerControl * TimerHandle_t;
#endif
class MultiRfProtocols
{
static MultiRfProtocols* _instance[NUM_MODULES];
@@ -51,9 +47,7 @@ class MultiRfProtocols
MultiRfProtocols(unsigned int moduleIdx);
void fillBuiltinProtos();
#if !defined(SIMU)
static void timerCb(TimerHandle_t xTimer);
#endif
static void timerCb(timer_handle_t* h);
public:
+19 -35
View File
@@ -28,6 +28,9 @@
#include "hal/switch_driver.h"
#include "hal/usb_driver.h"
#include "os/timer.h"
#include "tasks/mixer_task.h"
#if defined(LIBOPENUI)
#include "libopenui.h"
#endif
@@ -36,18 +39,11 @@ FIL g_oLogFile __DMA;
uint8_t logDelay100ms;
static tmr10ms_t lastLogTime = 0;
#if !defined(SIMU)
#include <FreeRTOS/include/FreeRTOS.h>
#include <FreeRTOS/include/timers.h>
static timer_handle_t loggingTimer = TIMER_INITIALIZER;
#include "tasks/mixer_task.h"
static TimerHandle_t loggingTimer = nullptr;
static StaticTimer_t loggingTimerBuffer;
static void loggingTimerCb(TimerHandle_t xTimer)
static void loggingTimerCb(timer_handle_t* timer)
{
(void)xTimer;
(void)timer;
if (mixerTaskRunning()) {
DEBUG_TIMER_START(debugTimerLoggingWakeup);
logsWrite();
@@ -55,51 +51,39 @@ static void loggingTimerCb(TimerHandle_t xTimer)
}
}
void loggingTimerStart()
void loggingTimerStart(uint32_t period)
{
if (!loggingTimer) {
loggingTimer =
xTimerCreateStatic("Logging", logDelay100ms*100 / RTOS_MS_PER_TICK, pdTRUE, (void*)0,
loggingTimerCb, &loggingTimerBuffer);
if (!timer_is_created(&loggingTimer)) {
timer_create(&loggingTimer, loggingTimerCb, "logs", period, true);
}
if (loggingTimer) {
if( xTimerStart( loggingTimer, 0 ) != pdPASS ) {
/* The timer could not be set into the Active state. */
}
}
timer_start(&loggingTimer);
}
void loggingTimerStop()
void loggingTimerStop() { timer_stop(&loggingTimer); }
bool loggingTimerIsRunning()
{
if (loggingTimer) {
if( xTimerStop( loggingTimer, 120 / RTOS_MS_PER_TICK ) != pdPASS ) {
/* The timer could not be stopped. */
}
loggingTimer = nullptr;
}
return timer_is_active(&loggingTimer);
}
void initLoggingTimer() { // called cyclically by main.cpp:perMain()
void initLoggingTimer()
{ // called cyclically by main.cpp:perMain()
static uint8_t logDelay100msOld = 0;
if(loggingTimer == nullptr) { // log Timer not running
if(!timer_is_active(&loggingTimer)) { // log Timer not running
if(isFunctionActive(FUNCTION_LOGS) && logDelay100ms > 0) { // if SF Logging is active and log rate is valid
loggingTimerStart(); // start log timer
loggingTimerStart(logDelay100ms * 100); // start log timer
}
} else { // log timer is already running
if(logDelay100msOld != logDelay100ms) { // if log rate was changed
logDelay100msOld = logDelay100ms; // memorize new log rate
if(logDelay100ms > 0) {
if(xTimerChangePeriod( loggingTimer, logDelay100ms*100, 0 ) != pdPASS ) { // and restart timer with new log rate
/* The timer period could not be changed */
}
timer_set_period(&loggingTimer, logDelay100ms * 100);
}
}
}
}
#endif
void writeHeader();
+3 -2
View File
@@ -28,6 +28,7 @@
#include "touch.h"
#include "view_main.h"
#include "os/time.h"
#define MAX_INSTRUCTIONS (20000 / 100)
@@ -117,11 +118,11 @@ void LuaEventHandler::event_cb(lv_event_t* e)
_startX = rel_pos.x;
_startY = rel_pos.y;
downTime = RTOS_GET_MS();
downTime = time_get_ms();
}
} else if (code == LV_EVENT_RELEASED) {
// tap count handling
uint32_t now = RTOS_GET_MS();
uint32_t now = time_get_ms();
if (now - downTime <= LUA_TAP_TIME) {
if (now - tapTime > LUA_TAP_TIME) {
tapCount = 1;
+1 -7
View File
@@ -465,9 +465,8 @@ void guiMain(event_t evt)
}
#endif
#if !defined(SIMU)
// from logs.cpp
void initLoggingTimer();
#endif
void perMain()
{
@@ -477,12 +476,7 @@ void perMain()
if (!usbPlugged() || (getSelectedUsbMode() == USB_UNSELECTED_MODE)) {
checkStorageUpdate();
#if !defined(SIMU) // use FreeRTOS software timer if radio firmware
initLoggingTimer(); // initialize software timer for logging
#else
logsWrite(); // call logsWrite the old way for simu
#endif
}
handleUsbConnection();
+5 -3
View File
@@ -19,11 +19,13 @@
* GNU General Public License for more details.
*/
#include "edgetx.h"
#include "mixer_scheduler.h"
#include "tasks/mixer_task.h"
#include "hal/usb_driver.h"
#include "dataconstants.h"
#include <string.h>
bool mixerSchedulerWaitForTrigger(uint8_t timeoutMs)
{
#if !defined(SIMU)
@@ -111,10 +113,10 @@ void mixerSchedulerISRTrigger()
/* At this point xTaskToNotify should not be NULL as
a transmission was in progress. */
configASSERT( mixerTaskId.rtos_handle != NULL );
configASSERT( mixerTaskId._rtos_handle != NULL );
/* Notify the task that the transmission is complete. */
vTaskNotifyGiveFromISR( mixerTaskId.rtos_handle,
vTaskNotifyGiveFromISR( mixerTaskId._rtos_handle,
&xHigherPriorityTaskWoken );
/* If xHigherPriorityTaskWoken is now set to pdTRUE then a
+36
View File
@@ -0,0 +1,36 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#pragma once
#include <stdint.h>
#include <stdbool.h>
typedef void (*async_func_t)(void* param1, uint32_t param2);
// schedule a function call for later
// return true if the async call could be stacked, false otherwise
bool async_call(async_func_t func, volatile bool* excl_flag, void* param1,
uint32_t param2);
// schedule a function call for later (interrupt handler)
bool async_call_isr(async_func_t func, volatile bool* excl_flag, void* param1,
uint32_t param2);
+68
View File
@@ -0,0 +1,68 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "async.h"
#include <FreeRTOS/include/FreeRTOS.h>
#include <FreeRTOS/include/timers.h>
bool async_call(async_func_t func, volatile bool* excl_flag, void* param1,
uint32_t param2)
{
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
// check exclusive flag first
if (excl_flag && *excl_flag) return false;
BaseType_t xReturn = xTimerPendFunctionCall(func, param1, param2, 0);
// update exclusive flag if provided
if (excl_flag && (xReturn == pdPASS)) *excl_flag = true;
return xReturn == pdPASS;
}
func(param1, param2);
return true;
}
bool async_call_isr(async_func_t func, volatile bool* excl_flag, void* param1,
uint32_t param2)
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
// check exclusive flag first
if (excl_flag && *excl_flag) return false;
BaseType_t xReturn = xTimerPendFunctionCallFromISR(
func, param1, param2, &xHigherPriorityTaskWoken);
// update exclusive flag if provided
if (excl_flag && (xReturn == pdPASS)) *excl_flag = true;
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
return xReturn == pdPASS;
}
func(param1, param2);
return true;
}
+38
View File
@@ -0,0 +1,38 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "async.h"
#include "timer_pthread_impl.h"
bool async_call(async_func_t func, volatile bool* excl_flag, void* param1,
uint32_t param2)
{
if (excl_flag && *excl_flag) return false;
timer_queue::instance().pend_function(func, param1, param2);
if (excl_flag) *excl_flag = true;
return true;
}
bool async_call_isr(async_func_t func, volatile bool* excl_flag, void* param1,
uint32_t param2)
{
return async_call(func, excl_flag, param1, param2);
}
+27
View File
@@ -0,0 +1,27 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#pragma once
#include "time.h"
void sleep_ms(uint32_t ms);
void sleep_until(time_point_t* tp, uint32_t ts_ms);
+41
View File
@@ -0,0 +1,41 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "sleep.h"
#include <FreeRTOS/include/FreeRTOS.h>
#include <FreeRTOS/include/task.h>
void sleep_ms(uint32_t ms)
{
if (!ms) return;
ms /= portTICK_PERIOD_MS;
if (!ms) ms = 1;
vTaskDelay(ms);
}
void sleep_until(time_point_t* tp, uint32_t inc)
{
inc /= portTICK_PERIOD_MS;
vTaskDelayUntil(tp, inc);
}
+37
View File
@@ -0,0 +1,37 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "sleep.h"
#include <thread>
extern uint8_t simuSleep(uint32_t ms);
void sleep_ms(uint32_t ms)
{
simuSleep(ms);
}
void sleep_until(time_point_t* tp, uint32_t inc)
{
*tp += std::chrono::duration<uint32_t, std::milli>{inc};
std::this_thread::sleep_until(*tp);
}
+41
View File
@@ -0,0 +1,41 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "sleep.h"
#include "timers_driver.h"
void sleep_ms(uint32_t ms)
{
if (!ms) return;
uint32_t timeout = timersGetMsTick();
while (timersGetMsTick() - timeout < ms) {}
}
void sleep_until(time_point_t* tp, uint32_t inc)
{
uint32_t start = *tp;
*tp = start + inc;
while (timersGetMsTick() - start < inc) {}
}
+46
View File
@@ -0,0 +1,46 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#pragma once
#include <stdint.h>
#include <stdbool.h>
// OS specific implementation
#if defined(POSIX_THREADS)
#include "task_pthread.h"
#elif defined(FREE_RTOS)
#include "task_freertos.h"
#endif
typedef void (*task_func_t)();
void task_create(task_handle_t* h, task_func_t func, const char* name,
void* stack, unsigned stack_size, unsigned priority);
unsigned task_get_stack_usage(task_handle_t* h);
unsigned task_get_stack_size(task_handle_t* h);
void mutex_create(mutex_handle_t* h);
bool mutex_lock(mutex_handle_t* h);
void mutex_unlock(mutex_handle_t* h);
bool mutex_trylock(mutex_handle_t* h);
+62
View File
@@ -0,0 +1,62 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "task.h"
static void _task_stub(void* p)
{
task_func_t func = (task_func_t)p;
func();
}
void task_create(task_handle_t* h, task_func_t func, const char* name,
void* stack, unsigned stack_size, unsigned priority)
{
h->_stack_size = stack_size;
h->_rtos_handle =
xTaskCreateStatic(_task_stub, name, stack_size, (void*)func, priority,
(StackType_t*)stack, &h->_task_struct);
}
unsigned task_get_stack_usage(task_handle_t* h)
{
return uxTaskGetStackHighWaterMark(h->_rtos_handle);
}
unsigned task_get_stack_size(task_handle_t* h)
{
return h->_stack_size * sizeof(StackType_t);
}
void mutex_create(mutex_handle_t* h)
{
h->_rtos_handle = xSemaphoreCreateMutexStatic(&h->_mutex_struct);
mutex_unlock(h);
}
static inline bool _lock_mutex(mutex_handle_t* h, TickType_t xTickToWait)
{
return xSemaphoreTake(h->_rtos_handle, xTickToWait) == pdTRUE;
}
bool mutex_lock(mutex_handle_t* h) { return _lock_mutex(h, portMAX_DELAY); }
bool mutex_trylock(mutex_handle_t* h) { return _lock_mutex(h, (TickType_t)0); }
void mutex_unlock(mutex_handle_t* h) { xSemaphoreGive(h->_rtos_handle); }
+41
View File
@@ -0,0 +1,41 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#pragma once
#include <FreeRTOS/include/FreeRTOS.h>
#include <FreeRTOS/include/task.h>
#include <FreeRTOS/include/semphr.h>
#include "definitions.h"
#define TASK_DEFINE_STACK(name, size) StackType_t __ALIGNED(8) name[size] __CCMRAM
struct task_handle_t {
TaskHandle_t _rtos_handle;
StaticTask_t _task_struct;
uint32_t _stack_size;
};
struct mutex_handle_t {
SemaphoreHandle_t _rtos_handle;
StaticSemaphore_t _mutex_struct;
};
+69
View File
@@ -0,0 +1,69 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "task.h"
static void* _task_stub(void* p)
{
task_func_t func = (task_func_t)p;
func();
return nullptr;
}
void task_create(task_handle_t* h, task_func_t func, const char* name,
void* stack, unsigned stack_size, unsigned priority)
{
h->_stack_size = stack_size;
pthread_create(&h->_thread_handle, nullptr, _task_stub, (void*)func);
}
unsigned task_get_stack_usage(task_handle_t* h)
{
// fake...
return 0;
}
unsigned task_get_stack_size(task_handle_t* h)
{
return h->_stack_size * 4;
}
void mutex_create(mutex_handle_t* h)
{
*h = PTHREAD_MUTEX_INITIALIZER;
}
bool mutex_lock(mutex_handle_t* h)
{
return pthread_mutex_lock(h) == 0;
}
void mutex_unlock(mutex_handle_t* h)
{
pthread_mutex_unlock(h);
}
bool mutex_trylock(mutex_handle_t* h)
{
return pthread_mutex_trylock(h) == 0;
}
+36
View File
@@ -0,0 +1,36 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#pragma once
#include <pthread.h>
#include <semaphore.h>
#include "definitions.h"
#define TASK_DEFINE_STACK(name, size) void* name
struct task_handle_t {
pthread_t _thread_handle;
uint32_t _stack_size;
};
typedef pthread_mutex_t mutex_handle_t;
+37
View File
@@ -0,0 +1,37 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#pragma once
#include <stdint.h>
// OS specific implementation
#if defined(POSIX_THREADS)
#include "time_native.h"
#elif defined(FREE_RTOS)
#include "time_freertos.h"
#else
#include "time_nortos.h"
#endif
uint32_t time_get_ms();
time_point_t time_point_now();
+35
View File
@@ -0,0 +1,35 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "time.h"
#include <FreeRTOS/include/FreeRTOS.h>
#include <FreeRTOS/include/task.h>
uint32_t time_get_ms()
{
return xTaskGetTickCount() / portTICK_PERIOD_MS;
}
time_point_t time_point_now()
{
return xTaskGetTickCount();
}
+26
View File
@@ -0,0 +1,26 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#pragma once
#include <FreeRTOS/include/FreeRTOS.h>
typedef TickType_t time_point_t;
+36
View File
@@ -0,0 +1,36 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "time.h"
#include <chrono>
extern uint64_t simuTimerMicros(void);
uint32_t time_get_ms()
{
return simuTimerMicros() / 1000;
}
time_point_t time_point_now()
{
return std::chrono::steady_clock::now();
}
+27
View File
@@ -0,0 +1,27 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#pragma once
#include <chrono>
typedef std::chrono::time_point<std::chrono::steady_clock> time_point_t;
+35
View File
@@ -0,0 +1,35 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "time.h"
#include "timers_driver.h"
uint32_t time_get_ms()
{
return timersGetMsTick();
}
time_point_t time_point_now()
{
return time_get_ms();
}
+27
View File
@@ -0,0 +1,27 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#pragma once
#include <stdint.h>
typedef uint32_t time_point_t;
+45
View File
@@ -0,0 +1,45 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#pragma once
#include <stdint.h>
#include <stdbool.h>
// OS specific implementation
#if defined(POSIX_THREADS)
#include "timer_pthread.h"
#elif defined(FREE_RTOS)
#include "timer_freertos.h"
#endif
typedef void (*timer_func_t)(timer_handle_t*);
int timer_create(timer_handle_t* h, timer_func_t func, const char* name,
unsigned period, bool repeat);
bool timer_is_created(timer_handle_t* h);
bool timer_is_active(timer_handle_t* h);
int timer_start(timer_handle_t* h);
int timer_stop(timer_handle_t* h);
int timer_set_period(timer_handle_t* h, unsigned period);
+70
View File
@@ -0,0 +1,70 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "timer.h"
static void _timer_cb(TimerHandle_t xTimer)
{
timer_handle_t* h = (timer_handle_t*)pvTimerGetTimerID(xTimer);
if (h->_func) h->_func(h);
}
int timer_create(timer_handle_t* h, timer_func_t func, const char* name,
unsigned period, bool repeat)
{
if (h->_rtos_handle) return -1;
h->_rtos_handle = xTimerCreateStatic(name, period / portTICK_PERIOD_MS,
repeat ? pdTRUE : pdFALSE, (void*)h,
_timer_cb, &h->_timer_struct);
h->_func = func;
return 0;
}
bool timer_is_created(timer_handle_t* h)
{
return h->_rtos_handle != nullptr;
}
bool timer_is_active(timer_handle_t* h)
{
return (h->_rtos_handle != nullptr) && (xTimerIsTimerActive(h->_rtos_handle));
}
int timer_start(timer_handle_t* h)
{
if (!h->_rtos_handle) return -1;
return xTimerStart(h->_rtos_handle, 0) == pdPASS ? 0 : -1;
}
int timer_stop(timer_handle_t* h)
{
if (!h->_rtos_handle) return -1;
return xTimerStop(h->_rtos_handle, 0) == pdPASS ? 0 : -1;
}
int timer_set_period(timer_handle_t* h, unsigned period)
{
if (!h->_rtos_handle) return -1;
return xTimerChangePeriod(h->_rtos_handle, period / portTICK_PERIOD_MS, 0) ==
pdPASS
? 0
: -1;
}
+35
View File
@@ -0,0 +1,35 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#pragma once
#include <FreeRTOS/include/FreeRTOS.h>
#include <FreeRTOS/include/timers.h>
struct timer_handle_t;
struct timer_handle_t {
TimerHandle_t _rtos_handle;
StaticTimer_t _timer_struct;
void (*_func)(timer_handle_t*);
};
#define TIMER_INITIALIZER { ._rtos_handle = nullptr }
+215
View File
@@ -0,0 +1,215 @@
#include "timer.h"
#include "timer_pthread_impl.h"
#include <algorithm>
bool _timer_cmp(timer_handle_t *lh, timer_handle_t *rh) {
return lh->next_trigger < rh->next_trigger;
}
timer_queue::timer_queue() {}
void timer_queue::update_current_time() {
_current_time = std::chrono::steady_clock::now();
}
void timer_queue::sort_timers() {
std::sort(_timers.begin(), _timers.end(), _timer_cmp);
}
timer_queue& timer_queue::instance()
{
static timer_queue _instance;
return _instance;
}
void timer_queue::start()
{
std::lock_guard<std::mutex> lock(_cmds_mutex);
if (!_running) {
_running = true;
_thread = std::make_unique<std::thread>([&]() { main_loop(); });
}
}
void timer_queue::stop() {
bool stopping = false;
std::unique_lock<std::mutex> lock(_cmds_mutex);
std::unique_lock<std::mutex> slock(_stop_mutex);
if (_running) {
stopping = true;
_running = false;
lock.unlock();
_cmds_condition.notify_one();
_stop_condition.wait(slock);
slock.unlock();
}
_thread->join();
}
void timer_queue::create_timer(timer_handle_t *timer, timer_func_t func, const char *name,
unsigned period, bool repeat) {
timer->func = func;
timer->name = name;
timer->period = period;
timer->repeat = repeat;
timer->next_trigger = time_point_t{};
}
void timer_queue::send_cmd(timer_req_t&& req)
{
{
std::lock_guard lock(_cmds_mutex);
_cmds.emplace_back(req);
}
_cmds_condition.notify_one();
}
void timer_queue::start_timer(timer_handle_t *timer) {
send_cmd(timer_req_t{.cmd = timer_req_t::cmd_start, .timer = timer});
}
void timer_queue::stop_timer(timer_handle_t *timer) {
send_cmd(timer_req_t{.cmd = timer_req_t::cmd_stop, .timer = timer});
}
void timer_queue::pend_function(timer_async_func_t func, void *param1,
uint32_t param2) {
send_cmd(timer_req_t{
.cmd = timer_req_t::cmd_pend_func,
.func_call = {.func = func, .param1 = param1, .param2 = param2}});
}
void timer_queue::main_loop() {
while (true) {
{
std::unique_lock lock(_cmds_mutex);
time_point_t until;
update_current_time();
process_cmds();
if (_timers.size() > 0) {
timer_handle_t* t = _timers[0];
until = t->next_trigger;
} else {
until = _current_time + std::chrono::milliseconds(1000);
}
std::cv_status result = _cmds_condition.wait_until(lock, until);
if (!_running) break;
}
async_calls();
trigger_timers();
}
_stop_condition.notify_one();
}
void timer_queue::process_cmds()
{
while (!_cmds.empty()) {
timer_req_t req = _cmds.back();
_cmds.pop_back();
if (req.cmd == timer_req_t::cmd_pend_func) {
if (req.func_call.func) {
_funcs.emplace_back(std::move(req.func_call));
}
} else {
timer_handle_t *t = req.timer;
auto pos = std::find(_timers.begin(), _timers.end(), t);
switch (req.cmd) {
case timer_req_t::cmd_start:
t->next_trigger = _current_time + std::chrono::milliseconds(t->period);
t->active = true;
if (pos == _timers.end()) {
_timers.emplace_back(t);
}
break;
case timer_req_t::cmd_stop:
if (pos != _timers.end()) {
_timers.erase(pos);
}
break;
default:
break;
}
}
}
}
void timer_queue::trigger_timers() {
int triggered = 0;
for (auto t : _timers) {
if (t->next_trigger <= _current_time) {
if (t->repeat) {
t->next_trigger += std::chrono::milliseconds(t->period);
} else {
t->active = false;
stop_timer(t);
}
t->func(t);
triggered++;
} else {
break;
}
}
if (triggered) {
sort_timers();
}
}
void timer_queue::async_calls() {
for (auto f : _funcs) {
f.func(f.param1, f.param2);
}
_funcs.clear();
}
int timer_create(timer_handle_t* h, timer_func_t func, const char* name,
unsigned period, bool repeat)
{
if (!h || !func) return -1;
timer_queue::create_timer(h, func, name, period, repeat);
return 0;
}
bool timer_is_created(timer_handle_t* h)
{
return h && h->func;
}
bool timer_is_active(timer_handle_t* h)
{
return h && h->active;
}
int timer_start(timer_handle_t* h)
{
if (!timer_is_created(h)) return -1;
timer_queue::instance().start_timer(h);
return 0;
}
int timer_stop(timer_handle_t* h)
{
if (!timer_is_created(h)) return -1;
timer_queue::instance().stop_timer(h);
return 0;
}
int timer_set_period(timer_handle_t *h, unsigned period)
{
if (!timer_is_created(h)) return -1;
h->period = period;
timer_queue::instance().start_timer(h);
return 0;
}
+45
View File
@@ -0,0 +1,45 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#pragma once
#include "time.h"
#include <atomic>
struct timer_handle_t;
typedef void (*timer_func_t)(timer_handle_t*);
typedef void (*timer_async_func_t)(void*, uint32_t);
using time_point = std::chrono::time_point<std::chrono::steady_clock>;
struct timer_handle_t {
timer_func_t func;
const char* name;
unsigned period;
bool repeat;
time_point_t next_trigger;
std::atomic_bool active;
};
#define TIMER_INITIALIZER {}
+74
View File
@@ -0,0 +1,74 @@
#include "timer_pthread.h"
#include <condition_variable>
#include <deque>
#include <memory>
#include <mutex>
#include <thread>
#include <vector>
struct timer_async_call_t {
timer_async_func_t func;
void *param1;
uint32_t param2;
};
struct timer_req_t {
enum type {
cmd_start,
cmd_stop,
cmd_pend_func,
};
type cmd;
union {
timer_handle_t *timer;
timer_async_call_t func_call;
};
};
class timer_queue {
std::unique_ptr<std::thread> _thread;
bool _running;
std::deque<timer_req_t> _cmds;
std::mutex _cmds_mutex;
std::condition_variable _cmds_condition;
std::mutex _stop_mutex;
std::condition_variable _stop_condition;
std::vector<timer_handle_t*> _timers;
std::vector<timer_async_call_t> _funcs;
time_point_t _current_time;
timer_queue();
void update_current_time();
void sort_timers();
void main_loop();
void trigger_timers();
void async_calls();
void process_cmds();
void send_cmd(timer_req_t&& req);
public:
timer_queue(timer_queue const &) = delete;
void operator=(timer_queue const &) = delete;
static timer_queue &instance();
static void create_timer(timer_handle_t *timer, timer_func_t func, const char *name,
unsigned period, bool repeat);
void start();
void stop();
void start_timer(timer_handle_t *timer);
void stop_timer(timer_handle_t *timer);
void pend_function(timer_async_func_t func, void* param1, uint32_t param2);
};
+13 -16
View File
@@ -25,7 +25,9 @@
#include "mixer_scheduler.h"
#include "heartbeat_driver.h"
#include "hal/module_port.h"
#include "os/sleep.h"
#include "tasks/mixer_task.h"
#include "os/async.h"
#include "pulses/pxx2.h"
#include "pulses/flysky.h"
@@ -106,7 +108,7 @@ void restartModule(uint8_t module)
// wait for the power output to be drained
pulsesStopModule(module);
RTOS_WAIT_MS(200);
sleep_ms(200);
mixerTaskStart();
}
@@ -124,21 +126,21 @@ void pulsesRestartModuleUnsafe(uint8_t module)
mod_drv->ctx = drv->init(module);
}
#if !defined(SIMU)
#include <FreeRTOS/include/FreeRTOS.h>
#include <FreeRTOS/include/timers.h>
static volatile bool _module_restart_queued[NUM_MODULES] = {false};
static void _setup_async_module_restart(void* p1, uint32_t p2)
{
uint8_t module = (uint8_t)(uintptr_t)p1;
_module_restart_queued[module] = false;
if (!mixerTaskTryLock()) {
// In case the mixer cannot be locked, try again later
// and make the same function pending again.
PendedFunction_t cb = _setup_async_module_restart;
xTimerPendFunctionCall(cb, p1, p2, 0/* do not wait */);
async_call(_setup_async_module_restart, &_module_restart_queued[module], p1,
p2);
return;
}
uint8_t module = (uint8_t)(uintptr_t)p1;
moduleState[module].forced_off = 1;
uint32_t timeout = p2;
@@ -146,18 +148,13 @@ static void _setup_async_module_restart(void* p1, uint32_t p2)
mixerTaskUnlock();
}
#endif
// return true if the request could be posted to the timer queue
bool restartModuleAsync(uint8_t module, uint8_t cnt_delay)
{
#if !defined(SIMU)
PendedFunction_t cb = _setup_async_module_restart;
return xTimerPendFunctionCall(cb, (void*)(uintptr_t)module, cnt_delay,
0/* do not wait */) == pdPASS;
#else
return true;
#endif
void* param1 = (void*)(uintptr_t)module;
return async_call(_setup_async_module_restart,
&_module_restart_queued[module], param1, cnt_delay);
}
void pulsesModuleSettingsUpdate(uint8_t module)
@@ -497,7 +494,7 @@ void pulsesStopModule(uint8_t module)
while(_telemetryIsPolling) {
// In case the telemetry timer is currently polling the port,
// we give the timer task a chance to run and finish the polling.
RTOS_WAIT_MS(1);
sleep_ms(1);
}
_deinit_module(module);
+4 -3
View File
@@ -21,6 +21,7 @@
#include "edgetx.h"
#include "io/frsky_firmware_update.h"
#include "os/sleep.h"
#include "tasks/mixer_task.h"
#include "pxx2_ota.h"
@@ -37,7 +38,7 @@ bool Pxx2OtaUpdate::waitStep(uint8_t step, uint8_t timeout)
if (elapsed++ > timeout) {
return false;
}
RTOS_WAIT_MS(1);
sleep_ms(1);
telemetryWakeup();
}
@@ -135,7 +136,7 @@ void Pxx2OtaUpdate::flashFirmware(const char * filename, ProgressHandler progres
mixerTaskStop();
watchdogSuspend(100 /*1s*/);
RTOS_WAIT_MS(100);
sleep_ms(100);
moduleState[module].mode = MODULE_MODE_OTA_UPDATE;
const char * result = doFlashFirmware(filename, progressHandler);
@@ -152,7 +153,7 @@ void Pxx2OtaUpdate::flashFirmware(const char * filename, ProgressHandler progres
}
watchdogSuspend(100);
RTOS_WAIT_MS(100);
sleep_ms(100);
mixerTaskStart();
}
+3 -249
View File
@@ -32,200 +32,25 @@ extern "C++" {
#include <pthread.h>
#include <semaphore.h>
#define SIMU_SLEEP_OR_EXIT_MS(x) simuSleep(x)
#define RTOS_MS_PER_TICK 1
typedef pthread_t RTOS_TASK_HANDLE;
typedef pthread_mutex_t RTOS_MUTEX_HANDLE;
typedef uint32_t RTOS_FLAG_HANDLE;
typedef sem_t * RTOS_EVENT_HANDLE;
extern uint64_t simuTimerMicros(void);
extern uint8_t simuSleep(uint32_t ms);
static inline void RTOS_START()
{
}
static inline void RTOS_WAIT_MS(uint32_t x)
{
simuSleep(x);
}
static inline void RTOS_WAIT_TICKS(uint32_t x)
{
RTOS_WAIT_MS(x * RTOS_MS_PER_TICK);
}
#ifdef __cplusplus
static inline void RTOS_CREATE_MUTEX(pthread_mutex_t &mutex)
{
mutex = PTHREAD_MUTEX_INITIALIZER;
}
static inline bool RTOS_LOCK_MUTEX(pthread_mutex_t &mutex)
{
return pthread_mutex_lock(&mutex) == 0;
}
static inline bool RTOS_TRYLOCK_MUTEX(pthread_mutex_t &mutex)
{
return pthread_mutex_trylock(&mutex) == 0;
}
static inline void RTOS_UNLOCK_MUTEX(pthread_mutex_t &mutex)
{
pthread_mutex_unlock(&mutex);
}
template<int SIZE>
class TaskStack
{
public:
TaskStack()
{
}
void paint()
{
}
uint32_t size()
{
return SIZE;
}
uint32_t available()
{
return SIZE / 2;
}
};
#define RTOS_DEFINE_STACK(taskHandle, name, size) TaskStack<size> name
#define TASK_FUNCTION(task) void* task(void *)
inline void RTOS_CREATE_TASK(pthread_t &taskId, void * (*task)(void *), const char * name)
{
pthread_create(&taskId, nullptr, task, nullptr);
#ifdef __linux__
pthread_setname_np(taskId, name);
#endif
}
template <int SIZE>
inline void RTOS_CREATE_TASK(pthread_t &taskId, void *(*task)(void *),
const char *name, TaskStack<SIZE> &,
unsigned size = 0, unsigned priority = 0)
{
(void)size;
(void)priority;
RTOS_CREATE_TASK(taskId, task, name);
}
#define TASK_RETURN() return nullptr
constexpr uint32_t mainStackAvailable()
static inline uint32_t mainStackAvailable()
{
return 500;
}
#endif // __cplusplus
// return 2ms resolution to match CoOS settings
static inline uint32_t RTOS_GET_TIME(void)
{
return (uint32_t)(simuTimerMicros() / 2000);
}
static inline uint32_t RTOS_GET_MS(void)
{
return (uint32_t)(simuTimerMicros() / 1000);
}
#elif defined(FREE_RTOS)
#ifdef __cplusplus
extern "C" {
#endif
#include <FreeRTOS/include/FreeRTOS.h>
#include <FreeRTOS/include/task.h>
#include <FreeRTOS/include/semphr.h>
#ifdef __cplusplus
}
#endif
#define RTOS_MS_PER_TICK portTICK_PERIOD_MS
typedef struct {
TaskHandle_t rtos_handle;
StaticTask_t task_struct;
} RTOS_TASK_HANDLE;
typedef struct {
SemaphoreHandle_t rtos_handle;
StaticSemaphore_t mutex_struct;
} RTOS_MUTEX_HANDLE;
typedef RTOS_MUTEX_HANDLE RTOS_FLAG_HANDLE;
#include <FreeRTOS/include/FreeRTOS.h>
#include <FreeRTOS/include/task.h>
static inline void RTOS_START()
{
vTaskStartScheduler();
}
static inline void RTOS_WAIT_MS(uint32_t x)
{
if (!x)
return;
if ((x = x / RTOS_MS_PER_TICK) < 1)
x = 1;
vTaskDelay(x);
}
static inline void RTOS_WAIT_TICKS(uint32_t x)
{
vTaskDelay(x);
}
static inline void _RTOS_CREATE_TASK(RTOS_TASK_HANDLE *h,
TaskFunction_t pxTaskCode,
const char *name,
StackType_t *const puxStackBuffer,
const uint32_t ulStackDepth,
UBaseType_t uxPriority)
{
h->rtos_handle = xTaskCreateStatic(
pxTaskCode, name, ulStackDepth, NULL, uxPriority,
puxStackBuffer, &h->task_struct);
}
#define RTOS_CREATE_TASK(h,task,name,stackStruct,stackSize,prio) \
_RTOS_CREATE_TASK(&h,task,name,stackStruct.stack,stackSize,prio)
static inline void _RTOS_CREATE_MUTEX(RTOS_MUTEX_HANDLE* h)
{
h->rtos_handle = xSemaphoreCreateMutexStatic(&h->mutex_struct);
xSemaphoreGive(h->rtos_handle);
}
#define RTOS_CREATE_MUTEX(handle) _RTOS_CREATE_MUTEX(&handle)
static inline bool _RTOS_LOCK_MUTEX(RTOS_MUTEX_HANDLE* h, TickType_t xTickToWait)
{
return xSemaphoreTake(h->rtos_handle, xTickToWait) == pdTRUE;
}
#define RTOS_LOCK_MUTEX(handle) _RTOS_LOCK_MUTEX(&handle, portMAX_DELAY)
#define RTOS_TRYLOCK_MUTEX(handle) _RTOS_LOCK_MUTEX(&handle, (TickType_t)0)
static inline void _RTOS_UNLOCK_MUTEX(RTOS_MUTEX_HANDLE* h)
{
xSemaphoreGive(h->rtos_handle);
}
#define RTOS_UNLOCK_MUTEX(handle) _RTOS_UNLOCK_MUTEX(&handle)
static inline uint32_t getStackAvailable(void * address, uint32_t size)
{
uint32_t * array = (uint32_t *)address;
@@ -248,77 +73,6 @@ extern "C++" {
return getStackAvailable(&_main_stack_start, stackSize());
}
//#define RTOS_CREATE_FLAG(flag) flag = CoCreateFlag(false, false)
//#define RTOS_SET_FLAG(flag) (void)CoSetFlag(flag)
//#define RTOS_CLEAR_FLAG(flag) (void)CoClearFlag(flag)
// returns true if timeout
static inline bool _RTOS_WAIT_FLAG(RTOS_FLAG_HANDLE* flag, uint32_t timeout)
{
return xSemaphoreTake(flag->rtos_handle, timeout * RTOS_MS_PER_TICK)
== pdFALSE;
}
#define RTOS_WAIT_FLAG(flag,timeout) _RTOS_WAIT_FLAG(&flag,timeout)
static inline void _RTOS_ISR_SET_FLAG(RTOS_FLAG_HANDLE* flag)
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
// Give semaphore back from ISR to trigger a task waiting for it
xSemaphoreGiveFromISR( flag->rtos_handle, &xHigherPriorityTaskWoken );
// If xHigherPriorityTaskWoken was set to true we should yield
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}
#define RTOS_ISR_SET_FLAG(flag) _RTOS_ISR_SET_FLAG(&flag)
#ifdef __cplusplus
template<int SIZE>
class TaskStack
{
public:
TaskStack(RTOS_TASK_HANDLE *h) {
this->h = h;
}
uint32_t size()
{
return SIZE * 4;
}
uint32_t available()
{
return uxTaskGetStackHighWaterMark(h->rtos_handle);
}
StackType_t stack[SIZE];
protected:
RTOS_TASK_HANDLE *h;
};
#endif // __cplusplus
static inline TickType_t RTOS_GET_TIME(void)
{
return xTaskGetTickCount();
}
static inline uint32_t RTOS_GET_MS(void)
{
return (RTOS_GET_TIME() * RTOS_MS_PER_TICK);
}
// stack must be aligned to 8 bytes otherwise printf for %f does not work!
#define RTOS_DEFINE_STACK(taskHandle, name, size) TaskStack<size> __ALIGNED(8) name __CCMRAM (&taskHandle)
#define TASK_FUNCTION(task) void task(void *)
#define TASK_RETURN() vTaskDelete(nullptr)
#else // no RTOS
#error "No RTOS implementation defined"
#endif // RTOS type
#ifdef __cplusplus
+7 -6
View File
@@ -37,6 +37,8 @@
#include "hal/adc_driver.h"
#include "hal/rotary_encoder.h"
#include "os/time.h"
#if LCD_W > 212
#define LCD_ZOOM 1
#else
@@ -181,7 +183,6 @@ OpenTxSim::~OpenTxSim()
TRACE("OpenTxSim::~OpenTxSim()");
simuStop();
stopAudioThread();
delete bmp;
delete sliders[0];
@@ -520,7 +521,7 @@ long OpenTxSim::onTimeout(FXObject*, FXSelector, void*)
static uint32_t last_tick = 0;
if (rotencAction) {
uint32_t now = RTOS_GET_MS();
uint32_t now = time_get_ms();
uint32_t dt = now - last_tick;
rotencDt += dt;
last_tick = now;
@@ -528,12 +529,11 @@ long OpenTxSim::onTimeout(FXObject*, FXSelector, void*)
#endif
}
#if !defined(SIMU_BOOTLOADER)
per10ms();
#else
#if defined(SIMU_BOOTLOADER)
void interrupt10ms();
interrupt10ms();
#endif
refreshDisplay();
getApp()->addTimeout(this, 2, 10);
return 0;
@@ -681,8 +681,9 @@ int main(int argc, char ** argv)
printf("Model size = %d\n", (int)sizeof(g_model));
#if !defined(SIMU_BOOTLOADER)
startAudioThread();
startAudio();
#endif
simuStart(true/*false*/, argc >= 3 ? argv[2] : 0, argc >= 4 ? argv[3] : 0);
return application.run();
+7 -27
View File
@@ -20,13 +20,8 @@
*/
#include "edgetx.h"
// #include <ctype.h>
#include "tasks/mixer_task.h"
#if !defined(SIMU)
#include <FreeRTOS/include/FreeRTOS.h>
#include <FreeRTOS/include/timers.h>
#endif
#include "os/timer.h"
struct spacemousedata_t
{
@@ -57,11 +52,9 @@ spacemousedata_t spacemouseData;
void spacemouseWakeup();
#if !defined(SIMU)
static TimerHandle_t spacemouseTimer = nullptr;
static StaticTimer_t spacemouseTimerBuffer;
static timer_handle_t spacemouseTimer = TIMER_INITIALIZER;
static void spacemouseTimerCb(TimerHandle_t xTimer)
static void spacemouseTimerCb(timer_handle_t* timer)
{
if (mixerTaskRunning()) {
DEBUG_TIMER_START(debugTimerSpacemouseWakeup);
@@ -73,28 +66,17 @@ static void spacemouseTimerCb(TimerHandle_t xTimer)
void spacemouseStart()
{
if (!spacemouseTimer) {
spacemouseTimer =
xTimerCreateStatic("SpaceM", 10 / RTOS_MS_PER_TICK, pdTRUE, (void*)0,
spacemouseTimerCb, &spacemouseTimerBuffer);
if (!timer_is_created(&spacemouseTimer)) {
timer_create(&spacemouseTimer, spacemouseTimerCb, "spacem", 10, true);
}
if (spacemouseTimer) {
if( xTimerStart( spacemouseTimer, 0 ) != pdPASS ) {
/* The timer could not be set into the Active state. */
}
}
timer_start(&spacemouseTimer);
}
void spacemouseStop()
{
if (spacemouseTimer) {
if( xTimerStop( spacemouseTimer, 12 / RTOS_MS_PER_TICK ) != pdPASS ) {
/* The timer could not be stopped. */
}
}
timer_stop(&spacemouseTimer);
}
#endif
void spacemouseParseNewData(uint8_t c)
{
@@ -155,9 +137,7 @@ void spacemouseSetSerialDriver(void* ctx, const etx_serial_driver_t* drv)
spacemouseSerialCtx = ctx;
spacemouseSerialDrv = drv;
spaceMouseTelegram.parsestate = sm_bytetype::SM_START;
#if !defined(SIMU)
spacemouseStart();
#endif
}
int16_t get_spacemouse_value(uint8_t ch)
+2 -1
View File
@@ -31,6 +31,7 @@ using std::list;
#include "yaml/yaml_labelslist.h"
#include "yaml/yaml_modelslist.h"
#include "yaml/yaml_parser.h"
#include "os/sleep.h"
#if defined(USBJ_EX)
#include "usb_joystick.h"
@@ -727,7 +728,7 @@ bool ModelMap::renameLabel(const std::string &from, std::string to,
(uint8_t *)modeldata, 0) != NULL);
}
#if defined(SIMU)
if (SIMU_SLEEP_OR_EXIT_MS(100)) break;
sleep_ms(100);
#endif
}
+4 -2
View File
@@ -20,6 +20,7 @@
*/
#include "edgetx.h"
#include "os/sleep.h"
#include "timers_driver.h"
#include "tasks/mixer_task.h"
#include "mixes.h"
@@ -76,8 +77,9 @@ void preModelLoad()
LayoutFactory::deleteCustomScreens(true);
#endif
if (needDelay)
RTOS_WAIT_MS(200);
if (needDelay) {
sleep_ms(200);
}
}
void postRadioSettingsLoad()
+2 -2
View File
@@ -26,6 +26,7 @@
#include "myeeprom.h"
#include "edgetx.h"
#include "edgetx_constants.h"
#include "os/sleep.h"
#include "switches.h"
#include "input_mapping.h"
#include "inactivity_timer.h"
@@ -1051,8 +1052,7 @@ void checkSwitches()
checkBacklight();
WDG_RESET();
RTOS_WAIT_MS(10);
sleep_ms(10);
}
LED_ERROR_END();
@@ -22,6 +22,7 @@
#include "hal/gpio.h"
#include "hal/audio_driver.h"
#include "os/sleep.h"
#include "stm32_gpio.h"
#include "stm32_timer.h"
#include "stm32_dma.h"
@@ -162,7 +163,7 @@ void audioUnmute()
if (get_mute_pin()) {
// ..un-mute
set_mute_pin(false);
RTOS_WAIT_MS(AUDIO_UNMUTE_DELAY);
sleep_ms(AUDIO_UNMUTE_DELAY);
}
// reset the mute delay
audioQueue.lastAudioPlayTime = 0;
@@ -6,6 +6,8 @@ AddHWGenTarget(${HW_DESC_JSON} hal_keys hal_keys.inc)
set(BOOTLOADER_SRC ${BOOTLOADER_SRC}
${CMAKE_CURRENT_BINARY_DIR}/hal_keys.inc
${RADIO_SRC_DIR}/os/time_nortos.cpp
${RADIO_SRC_DIR}/os/sleep_nortos.cpp
${RADIO_SRC_DIR}/keys.cpp
${RADIO_SRC_DIR}/strhelpers.cpp
${RADIO_SRC_DIR}/stamp.cpp
@@ -135,6 +135,11 @@ void bootloaderInitApp()
boardBLInit();
}
#if defined(FIRMWARE_FORMAT_UF2)
// make linker happy
void per5ms() {}
#endif
int main()
#else // SIMU
void bootloaderInitApp() {}
@@ -2,9 +2,11 @@
#include "boot.h"
#include "hal/usb_driver.h"
#include "os/time.h"
#include "lcd.h"
extern volatile uint8_t tenms;
#define FRAME_INTERVAL_MS 20
void bootloaderDFU()
{
@@ -13,8 +15,11 @@ void bootloaderDFU()
bootloaderDrawDFUScreen();
uint32_t next_frame = time_get_ms();
for (;;) {
if (tenms) {
if (time_get_ms() - next_frame >= FRAME_INTERVAL_MS) {
next_frame += FRAME_INTERVAL_MS;
if (!usbPlugged()) break;
bootloaderDrawDFUScreen();
lcdRefresh();
@@ -3,9 +3,12 @@
#include "hal/usb_driver.h"
#include "hal/rotary_encoder.h"
#include "os/time.h"
#include "lcd.h"
#define FRAME_INTERVAL_MS 20
#if defined(SPI_FLASH)
#define MAIN_MENU_LEN 3
#else
@@ -17,16 +20,8 @@
#define SEL_CLEAR_FLASH_STORAGE_MENU_LEN 2
#endif
volatile tmr10ms_t g_tmr10ms;
volatile uint8_t tenms = 1;
void per5ms() {} // make linker happy
void per10ms()
void pollInputs()
{
tenms |= 1u; // 10 mS has passed
g_tmr10ms++;
keysPollingCycle();
// TODO: use rotaryEncoderPollingCycle() instead
@@ -42,6 +37,13 @@ void per10ms()
#endif
}
// poll inputs every 10ms
void per5ms()
{
static uint32_t cnt = 0;
if (++cnt & 1) { pollInputs(); }
}
FlashCheckRes valid;
int menuFlashFile(uint32_t index, event_t event)
@@ -74,10 +76,12 @@ void bootloaderMenu()
sdInit();
uint32_t next_frame = time_get_ms();
for (;;) {
if (tenms) {
tenms = 0;
if (time_get_ms() - next_frame >= FRAME_INTERVAL_MS) {
next_frame += FRAME_INTERVAL_MS;
if (state != ST_USB && state != ST_FLASHING
&& state != ST_FLASH_DONE && state != ST_RADIO_MENU) {
@@ -3,6 +3,7 @@
#include "hal/usb_driver.h"
#include "hal/storage.h"
#include "hal/fatfs_diskio.h"
#include "os/time.h"
#include "thirdparty/FatFs/diskio.h"
#include "drivers/uf2_ghostfat.h"
@@ -10,19 +11,10 @@
#include "board.h"
#include "lcd.h"
#define FRAME_INTERVAL_MS 20
extern uf2_fat_write_state_t _uf2_write_state;
volatile tmr10ms_t g_tmr10ms;
volatile uint8_t tenms = 1;
void per5ms() {} // make linker happy
void per10ms()
{
tenms |= 1u; // 10 mS has passed
g_tmr10ms++;
}
void bootloaderUF2()
{
BootloaderState state = ST_START;
@@ -31,10 +23,12 @@ void bootloaderUF2()
storageInit();
disk_initialize(0);
uint32_t next_frame = time_get_ms();
for (;;) {
if (tenms) {
tenms = 0;
if (time_get_ms() - next_frame >= FRAME_INTERVAL_MS) {
next_frame += FRAME_INTERVAL_MS;
if (state != ST_USB && state != ST_FLASHING && state != ST_FLASH_DONE) {
if (usbPlugged()) {
@@ -137,7 +137,7 @@ void rotaryEncoderCheck()
rotenc_t diff = (value - last_value);
if (diff != 0) {
uint32_t now = RTOS_GET_MS();
uint32_t now = timersGetMsTick();
uint32_t dt = now - last_tick;
// pre-compute accumulated dt (dx/dt is done later in LVGL driver)
rotencDt += dt;
@@ -100,8 +100,6 @@ static inline void _interrupt_1ms()
watchdogTimeout -= 1;
WDG_RESET(); // Retrigger hardware watchdog
}
per10ms();
}
}
@@ -21,6 +21,7 @@
#include "vs1053b.h"
#include "os/sleep.h"
#include "stm32_hal_ll.h"
#include "stm32_gpio_driver.h"
#include "stm32_gpio.h"
@@ -327,7 +328,7 @@ static void vs1053b_unmute()
if (_is_muted) {
// ..un-mute
_set_mute_pin(false);
RTOS_WAIT_MS(_instance->unmute_delay_ms);
sleep_ms(_instance->unmute_delay_ms);
}
// reset the mute delay
_last_play_ts = 0;
+3 -3
View File
@@ -42,8 +42,8 @@ volatile static bool touchEventOccured;
static tc_handle_TypeDef tc_handle = {0, 0};
tmr10ms_t downTime = 0;
tmr10ms_t tapTime = 0;
uint32_t downTime = 0;
uint32_t tapTime = 0;
short tapCount = 0;
#define TAP_TIME 250 // ms
@@ -251,7 +251,7 @@ TouchState touchPanelRead()
touchEventOccured = false;
tmr10ms_t now = RTOS_GET_MS();
uint32_t now = timersGetMsTick();
internalTouchState.tapCount = 0;
if (cst836u_TS_DetectTouch()) {
+6 -5
View File
@@ -29,10 +29,11 @@
#include "stm32_exti_driver.h"
#include "hal.h"
#include "timers_driver.h"
#include "tp_gt911.h"
#include "delays_driver.h"
#include "rtos.h"
#include "os/sleep.h"
#include "edgetx_types.h"
#include "debug.h"
@@ -651,7 +652,7 @@ struct TouchState touchPanelRead()
touchEventOccured = false;
uint32_t startReadStatus = RTOS_GET_MS();
uint32_t startReadStatus = timersGetMsTick();
do {
if (!I2C_GT911_ReadRegister(GT911_READ_XY_REG, &state, 1)) {
// ledRed();
@@ -665,15 +666,15 @@ struct TouchState touchPanelRead()
// ready
break;
}
RTOS_WAIT_MS(1);
} while (RTOS_GET_MS() - startReadStatus < GT911_TIMEOUT);
sleep_ms(1);
} while (timersGetMsTick() - startReadStatus < GT911_TIMEOUT);
internalTouchState.deltaX = 0;
internalTouchState.deltaY = 0;
TRACE("touch state = 0x%x", state);
if (state & 0x80u) {
uint8_t pointsCount = (state & 0x0Fu);
uint32_t now = RTOS_GET_MS();
uint32_t now = timersGetMsTick();
internalTouchState.tapCount = 0;
if (pointsCount > 0 && pointsCount <= GT911_MAX_TP) {
+1 -2
View File
@@ -7,7 +7,6 @@ endif()
set(SIMU_DRIVERS
simpgmspace.cpp
simueeprom.cpp
simufatfs.cpp
simudisk.cpp
simulcd.cpp
@@ -186,7 +185,7 @@ if(FOX_FOUND)
target_include_directories(simu PUBLIC ${FOX_INCLUDE_DIR} )
target_link_libraries(simu ${FOX_LIBRARY} pthread ${SDL2_LIBRARIES})
target_compile_options(simu PRIVATE -DSIMU)
target_compile_options(simu PRIVATE ${SIMU_SRC_OPTIONS})
endif()
if(APPLE)
+15 -18
View File
@@ -28,6 +28,7 @@
#include "hal/adc_driver.h"
#include "hal/rotary_encoder.h"
#include "os/time.h"
#include <QDebug>
#include <QElapsedTimer>
@@ -282,9 +283,9 @@ void OpenTxSimulator::start(const char * filename, bool tests)
QMutexLocker lckr(&m_mtxSimuMain);
QMutexLocker slckr(&m_mtxSettings);
startEepromThread(filename);
startAudioThread(volumeGain);
simuStart(tests, simuSdDirectory.toLatin1().constData(), simuSettingsDirectory.toLatin1().constData());
startAudio(volumeGain);
simuStart(tests, simuSdDirectory.toLatin1().constData(),
simuSettingsDirectory.toLatin1().constData());
emit started();
QTimer::singleShot(0, this, SLOT(run())); // old style for Qt < 5.4
@@ -300,8 +301,6 @@ void OpenTxSimulator::stop()
QMutexLocker lckr(&m_mtxSimuMain);
simuStop();
stopAudioThread();
stopEepromThread();
emit stopped();
}
@@ -321,20 +320,20 @@ void OpenTxSimulator::setVolumeGain(const int value)
void OpenTxSimulator::setRadioData(const QByteArray & data)
{
#if defined(EEPROM_SIZE)
QMutexLocker lckr(&m_mtxRadioData);
eeprom = (uint8_t *)malloc(qMin<int>(EEPROM_SIZE, data.size()));
memcpy(eeprom, data.data(), qMin<int>(EEPROM_SIZE, data.size()));
#endif
// #if defined(EEPROM_SIZE)
// QMutexLocker lckr(&m_mtxRadioData);
// eeprom = (uint8_t *)malloc(qMin<int>(EEPROM_SIZE, data.size()));
// memcpy(eeprom, data.data(), qMin<int>(EEPROM_SIZE, data.size()));
// #endif
}
void OpenTxSimulator::readRadioData(QByteArray & dest)
{
#if defined(EEPROM_SIZE)
QMutexLocker lckr(&m_mtxRadioData);
if (eeprom)
memcpy(dest.data(), eeprom, qMin<int>(EEPROM_SIZE, dest.size()));
#endif
// #if defined(EEPROM_SIZE)
// QMutexLocker lckr(&m_mtxRadioData);
// if (eeprom)
// memcpy(dest.data(), eeprom, qMin<int>(EEPROM_SIZE, dest.size()));
// #endif
}
uint8_t * OpenTxSimulator::getLcd()
@@ -428,7 +427,7 @@ void OpenTxSimulator::rotaryEncoderEvent(int steps)
steps *= -1;
rotencValue += steps * ROTARY_ENCODER_GRANULARITY;
// TODO: set rotencDt
uint32_t now = RTOS_GET_MS();
uint32_t now = time_get_ms();
uint32_t dt = now - last_tick;
rotencDt += dt;
last_tick = now;
@@ -771,8 +770,6 @@ void OpenTxSimulator::run()
++loops;
per10ms();
checkLcdChanged();
if (!(loops % 5)) {
+41 -72
View File
@@ -34,6 +34,9 @@
#include "hal/usb_driver.h"
#include "hal/audio_driver.h"
#include "os/task.h"
#include "os/timer_pthread_impl.h"
#include <errno.h>
#include <stdarg.h>
#include <string>
@@ -211,6 +214,7 @@ void simuStart(bool tests, const char * sdPath, const char * settingsPath)
lcdInit();
#if !defined(SIMU_BOOTLOADER)
timer_queue::instance().start();
simuMain();
#else
pthread_attr_t attr;
@@ -232,8 +236,8 @@ void simuStart(bool tests, const char * sdPath, const char * settingsPath)
#endif
}
extern RTOS_TASK_HANDLE mixerTaskId;
extern RTOS_TASK_HANDLE menusTaskId;
extern task_handle_t mixerTaskId;
extern task_handle_t menusTaskId;
void simuStop()
{
@@ -242,8 +246,12 @@ void simuStop()
simu_shutdown = true;
pthread_join(mixerTaskId, nullptr);
pthread_join(menusTaskId, nullptr);
pthread_join(mixerTaskId._thread_handle, nullptr);
pthread_join(menusTaskId._thread_handle, nullptr);
#if defined(SIMU_AUDIO)
stopAudio();
#endif
simu_running = false;
}
@@ -253,8 +261,6 @@ struct SimulatorAudio {
int currentVolume;
int16_t leftoverData[AUDIO_BUFFER_SIZE];
int leftoverLen;
bool threadRunning;
pthread_t threadPid;
} simuAudio;
bool simuIsRunning()
@@ -264,10 +270,9 @@ bool simuIsRunning()
uint8_t simuSleep(uint32_t ms)
{
for (uint32_t i = 0; i < ms; ++i){
if (simu_shutdown || !simu_running)
return 1;
sleep(1);
for (uint32_t i = 0; i < ms; i++) {
if (simu_shutdown || !simu_running) return 1;
usleep(1);
}
return 0;
}
@@ -336,77 +341,44 @@ void fillAudioBuffer(void *udata, Uint8 *stream, int len)
}
}
//fill the rest of buffer with silence
// fill the rest of buffer with silence
if (len > 0) {
SDL_memset(stream, 0x8000, len); // make sure this is silence.
// putchar('.');
}
}
void * audioThread(void *)
int startAudio(int volumeGain)
{
/*
Checking here if SDL audio was initialized is wrong, because
the SDL_CloseAudio() de-initializes it.
simuAudio = {
.volumeGain = volumeGain,
.leftoverLen = 0,
};
if ( !SDL_WasInit(SDL_INIT_AUDIO) ) {
fprintf(stderr, "ERROR: couldn't initialize SDL audio support\n");
return 0;
}
*/
SDL_AudioSpec wanted, have;
/* Set the audio format */
wanted.freq = AUDIO_SAMPLE_RATE;
wanted.format = AUDIO_S16SYS;
wanted.channels = 1; /* 1 = mono, 2 = stereo */
wanted.samples =
AUDIO_BUFFER_SIZE * 2; /* Good low-latency value for callback */
wanted.callback = fillAudioBuffer;
wanted.userdata = nullptr;
/*
SDL_OpenAudio() internally calls SDL_InitSubSystem(SDL_INIT_AUDIO),
which initializes SDL Audio subsystem if necessary
*/
if ( SDL_OpenAudio(&wanted, &have) < 0 ) {
fprintf(stderr, "Couldn't open audio: %s\n", SDL_GetError());
return nullptr;
}
SDL_PauseAudio(0);
while (simuAudio.threadRunning) {
audioQueue.wakeup();
sleep(1);
}
SDL_CloseAudio();
return nullptr;
}
void startAudioThread(int volumeGain)
{
simuAudio.leftoverLen = 0;
simuAudio.threadRunning = true;
simuAudio.volumeGain = volumeGain;
TRACE_SIMPGMSPACE("startAudioThread(%d)", volumeGain);
TRACE("startAudioThread(%d)", volumeGain);
audioSetVolume(VOLUME_LEVEL_DEF);
pthread_attr_t attr;
pthread_attr_init(&attr);
struct sched_param sp;
sp.sched_priority = SCHED_RR;
pthread_attr_setschedparam(&attr, &sp);
pthread_create(&simuAudio.threadPid, &attr, &audioThread, nullptr);
#ifdef __linux__
pthread_setname_np(simuAudio.threadPid, "audio");
#endif
/* Set the audio format */
SDL_AudioSpec desired = {
.freq = AUDIO_SAMPLE_RATE,
.format = AUDIO_S16SYS,
.channels = 1,
.samples = AUDIO_BUFFER_SIZE * 2,
.callback = fillAudioBuffer,
.userdata = nullptr,
};
SDL_AudioSpec obtained;
if ( SDL_OpenAudio(&desired, &obtained) < 0 ) {
fprintf(stderr, "Couldn't open audio: %s\n", SDL_GetError());
return -1;
}
SDL_PauseAudio(0);
return 0;
}
void stopAudioThread()
void stopAudio()
{
simuAudio.threadRunning = false;
pthread_join(simuAudio.threadPid, nullptr);
SDL_CloseAudio();
}
#endif // #if defined(SIMU_AUDIO)
@@ -675,6 +647,3 @@ struct TouchState getInternalTouchState()
return simTouchState;
}
#endif
void telemetryStart() {}
void telemetryStop() {}
+4 -15
View File
@@ -30,17 +30,11 @@
#include <stddef.h>
#include <errno.h>
// #undef min
// #undef max
extern uint8_t * eeprom;
#define __disable_irq()
#define __enable_irq()
extern char * main_thread_error;
uint64_t simuTimerMicros(void);
uint8_t simuSleep(uint32_t ms); // returns true if thread shutdown requested
@@ -57,21 +51,16 @@ void startEepromThread(const char * filename = "eeprom.bin");
void stopEepromThread();
#if defined(SIMU_AUDIO)
void startAudioThread(int volumeGain = 10);
void stopAudioThread(void);
int startAudio(int volumeGain = 10);
void stopAudio();
#else
#define startAudioThread(dummy)
#define stopAudioThread()
#define startAudio(dummy) (-1)
#define stopAudio()
#endif
#endif
void simuMain();
// inline void delay_01us(uint32_t dummy) { }
#define configure_pins(...)
#if !defined(SKIP_FATFS_DECLARATION) && !defined(SIMU_DISKIO)
#define SIMU_USE_SDCARD
#endif
+6 -4
View File
@@ -19,6 +19,7 @@
* GNU General Public License for more details.
*/
#include "os/sleep.h"
#include "stm32_hal_ll.h"
#include "stm32_hal.h"
#include "stm32_i2c_driver.h"
@@ -32,6 +33,7 @@
#include "hal.h"
#include "stm32h7rsxx_hal_gpio.h"
#include "timers_driver.h"
#include "tp_gt911.h"
#include "delays_driver.h"
@@ -215,7 +217,7 @@ struct TouchState touchPanelRead()
touchEventOccured = false;
uint32_t startReadStatus = RTOS_GET_MS();
uint32_t startReadStatus = timersGetMsTick();
do {
if (!I2C_GT911_ReadRegister(GT911_READ_XY_REG, &state, 1)) {
// ledRed();
@@ -229,15 +231,15 @@ struct TouchState touchPanelRead()
// ready
break;
}
RTOS_WAIT_MS(1);
} while (RTOS_GET_MS() - startReadStatus < GT911_TIMEOUT);
sleep_ms(1);
} while (timersGetMsTick() - startReadStatus < GT911_TIMEOUT);
internalTouchState.deltaX = 0;
internalTouchState.deltaY = 0;
TRACE("touch state = 0x%x", state);
if (state & 0x80u) {
uint8_t pointsCount = (state & 0x0Fu);
uint32_t now = RTOS_GET_MS();
uint32_t now = timersGetMsTick();
internalTouchState.tapCount = 0;
if (pointsCount > 0 && pointsCount <= GT911_MAX_TP) {
+12 -24
View File
@@ -20,17 +20,17 @@
*/
#include "bsp_io.h"
#include "hal/switch_driver.h"
#include "drivers/pca95xx.h"
#include "os/async.h"
#include "stm32_i2c_driver.h"
#include "timers_driver.h"
#include "stm32_ws2812.h"
#include <FreeRTOS/include/FreeRTOS.h>
#include <FreeRTOS/include/timers.h>
#include "bitfield.h"
#include "drivers/pca95xx.h"
#include "hal/switch_driver.h"
#include "myeeprom.h"
#include "stm32_i2c_driver.h"
#include "stm32_ws2812.h"
#include "timers_driver.h"
struct bsp_io_expander {
pca95xx_t exp;
@@ -58,30 +58,18 @@ static uint32_t _read_io_expander(bsp_io_expander* io)
return io->state;
}
static void _poll_switches(void *pvParameter1, uint32_t ulParameter2)
static void _poll_switches(void *param1, uint32_t param2)
{
(void)ulParameter2;
(void)param1;
(void)param2;
_poll_switches_in_queue = false;
bsp_io_read_switches();
bsp_io_read_fs_switches();
_read_io_expander(&_io_switches);
_read_io_expander(&_io_fs_switches);
}
static void _io_int_handler()
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
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);
}
async_call_isr(_poll_switches, &_poll_switches_in_queue, nullptr, 0);
}
int bsp_io_init()
+60 -25
View File
@@ -19,7 +19,12 @@
* GNU General Public License for more details.
*/
#include "debug.h"
#include "edgetx.h"
#include "os/sleep.h"
#include "os/task.h"
#include "os/time.h"
#include "os/timer.h"
#include "timers_driver.h"
#include "hal/abnormal_reboot.h"
#include "hal/watchdog_driver.h"
@@ -32,23 +37,23 @@
#include "startup_shutdown.h"
#endif
RTOS_TASK_HANDLE menusTaskId;
RTOS_DEFINE_STACK(menusTaskId, menusStack, MENUS_STACK_SIZE);
task_handle_t menusTaskId;
TASK_DEFINE_STACK(menusStack, MENUS_STACK_SIZE);
#if defined(AUDIO)
RTOS_TASK_HANDLE audioTaskId;
RTOS_DEFINE_STACK(audioTaskId, audioStack, AUDIO_STACK_SIZE);
task_handle_t audioTaskId;
TASK_DEFINE_STACK(audioStack, AUDIO_STACK_SIZE);
#endif
RTOS_MUTEX_HANDLE audioMutex;
mutex_handle_t audioMutex;
#define MENU_TASK_PERIOD_TICKS (50 / RTOS_MS_PER_TICK) // 50ms
#define MENU_TASK_PERIOD (50) // 50ms
#if defined(COLORLCD) && defined(CLI)
bool perMainEnabled = true;
#endif
TASK_FUNCTION(menusTask)
static void menusTask()
{
#if defined(LIBOPENUI)
LvglWrapper::instance();
@@ -63,15 +68,14 @@ TASK_FUNCTION(menusTask)
uint32_t pwr_check = pwrCheck();
if (pwr_check == e_power_off) {
break;
}
else if (pwr_check == e_power_press) {
RTOS_WAIT_TICKS(MENU_TASK_PERIOD_TICKS);
} else if (pwr_check == e_power_press) {
sleep_ms(MENU_TASK_PERIOD);
continue;
}
#else
while (pwrCheck() != e_power_off) {
#endif
uint32_t start = (uint32_t)RTOS_GET_TIME();
time_point_t next_tick = time_point_now();
DEBUG_TIMER_START(debugTimerPerMain);
#if defined(COLORLCD) && defined(CLI)
if (perMainEnabled) {
@@ -81,14 +85,8 @@ TASK_FUNCTION(menusTask)
perMain();
#endif
DEBUG_TIMER_STOP(debugTimerPerMain);
// TODO remove completely massstorage from sky9x firmware
uint32_t runtime = ((uint32_t)RTOS_GET_TIME() - start);
// deduct the thread run-time from the wait, if run-time was more than
// desired period, then skip the wait all together
if (runtime < MENU_TASK_PERIOD_TICKS) {
RTOS_WAIT_TICKS(MENU_TASK_PERIOD_TICKS - runtime);
}
sleep_until(&next_tick, MENU_TASK_PERIOD);
resetForcePowerOffRequest();
}
@@ -99,24 +97,61 @@ TASK_FUNCTION(menusTask)
drawSleepBitmap();
edgeTxClose();
boardOff();
}
TASK_RETURN();
static void audioTask()
{
while (!audioQueue.started()) {
sleep_ms(1);
}
#if defined(PCBX12S) || defined(RADIO_TX16S) || defined(RADIO_F16) || defined(RADIO_V16)
// The audio amp needs ~2s to start
sleep_ms(1000); // 1s
#endif
time_point_t next_tick = time_point_now();
while (true) {
DEBUG_TIMER_SAMPLE(debugTimerAudioIterval);
DEBUG_TIMER_START(debugTimerAudioDuration);
audioQueue.wakeup();
DEBUG_TIMER_STOP(debugTimerAudioDuration);
sleep_until(&next_tick, 4);
}
}
static timer_handle_t _timer10ms = TIMER_INITIALIZER;
static void _timer_10ms_cb(timer_handle_t* h)
{
per10ms();
}
void timer10msStart()
{
if (!timer_is_created(&_timer10ms)) {
timer_create(&_timer10ms, _timer_10ms_cb, "10ms", 10, true);
}
timer_start(&_timer10ms);
}
void tasksStart()
{
RTOS_CREATE_MUTEX(audioMutex);
mutex_create(&audioMutex);
#if defined(CLI) && !defined(SIMU)
cliStart();
#endif
RTOS_CREATE_TASK(menusTaskId, menusTask, "menus", menusStack,
MENUS_STACK_SIZE, MENUS_TASK_PRIO);
timer10msStart();
#if !defined(SIMU) && defined(AUDIO)
RTOS_CREATE_TASK(audioTaskId, audioTask, "audio", audioStack,
AUDIO_STACK_SIZE, AUDIO_TASK_PRIO);
task_create(&menusTaskId, menusTask, "menus", menusStack, MENUS_STACK_SIZE,
MENUS_TASK_PRIO);
#if defined(AUDIO)
task_create(&audioTaskId, audioTask, "audio", audioStack, AUDIO_STACK_SIZE,
AUDIO_TASK_PRIO);
#endif
RTOS_START();
+4 -5
View File
@@ -21,7 +21,7 @@
#pragma once
#include "rtos.h"
#include "os/task.h"
// stack sizes should be in multiples of 8 for better alignment
#if defined (COLORLCD)
@@ -53,15 +53,14 @@
#endif
extern TaskStack<MENUS_STACK_SIZE> menusStack;
extern TaskStack<MIXER_STACK_SIZE> mixerStack;
extern task_handle_t menusTaskId;
#if defined(AUDIO)
extern TaskStack<AUDIO_STACK_SIZE> audioStack;
extern task_handle_t audioTaskId;
#endif
#if defined(CLI)
extern TaskStack<CLI_STACK_SIZE> cliStack;
extern task_handle_t cliTaskId;
#endif
void tasksStart();
+14 -22
View File
@@ -23,22 +23,25 @@
#include "mixer_task.h"
#include "mixer_scheduler.h"
#include "os/task.h"
#include "edgetx.h"
#include "switches.h"
#include "hal/usb_driver.h"
#include "hal/watchdog_driver.h"
#if defined(HALL_SYNC) && !defined(SIMU)
#include "stm32_gpio.h"
#include "hal/gpio.h"
#endif
RTOS_TASK_HANDLE mixerTaskId;
RTOS_DEFINE_STACK(mixerTaskId, mixerStack, MIXER_STACK_SIZE);
task_handle_t mixerTaskId;
TASK_DEFINE_STACK(mixerStack, MIXER_STACK_SIZE);
// mixer hold this mutex while computing
// channels and sending them out
static RTOS_MUTEX_HANDLE mixerMutex;
static mutex_handle_t mixerMutex;
// The mixer will start in 'paused' mode
// and start working properly once
@@ -49,26 +52,26 @@ static bool _mixer_exit = false;
void mixerTaskLock()
{
RTOS_LOCK_MUTEX(mixerMutex);
mutex_lock(&mixerMutex);
}
// returns true if the lock could be acquired
bool mixerTaskTryLock()
{
return RTOS_TRYLOCK_MUTEX(mixerMutex);
return mutex_trylock(&mixerMutex);
}
void mixerTaskUnlock()
{
RTOS_UNLOCK_MUTEX(mixerMutex);
mutex_unlock(&mixerMutex);
}
void mixerTaskInit()
{
mixerSchedulerInit();
RTOS_CREATE_MUTEX(mixerMutex);
RTOS_CREATE_TASK(mixerTaskId, mixerTask, "mixer", mixerStack,
MIXER_STACK_SIZE, MIXER_TASK_PRIO);
mutex_create(&mixerMutex);
task_create(&mixerTaskId, mixerTask, "mixer", mixerStack, MIXER_STACK_SIZE,
MIXER_TASK_PRIO);
mixerSchedulerStart();
}
@@ -133,17 +136,9 @@ void execMixerFrequentActions()
#if defined(BLUETOOTH)
bluetooth.wakeup();
#endif
#if defined(SIMU)
if (_mixer_running) {
DEBUG_TIMER_START(debugTimerTelemetryWakeup);
telemetryWakeup();
DEBUG_TIMER_STOP(debugTimerTelemetryWakeup);
}
#endif
}
TASK_FUNCTION(mixerTask)
void mixerTask()
{
#if defined(IMU)
gyroInit();
@@ -173,9 +168,8 @@ TASK_FUNCTION(mixerTask)
mixerSchedulerEnableTrigger();
#if defined(SIMU)
// TODO: should be using mixerTaskExit() instead...
if (pwrCheck() == e_power_off) {
TASK_RETURN();
return;
}
#else
// Emergency power OFF: in case the UI is not functional anymore
@@ -218,8 +212,6 @@ TASK_FUNCTION(mixerTask)
maxMixerDuration = t0;
}
}
TASK_RETURN();
}
void doMixerCalculations()
+3 -3
View File
@@ -19,13 +19,13 @@
* GNU General Public License for more details.
*/
#include "rtos.h"
#include "os/task.h"
// needed by the mixer scheduler
extern RTOS_TASK_HANDLE mixerTaskId;
extern task_handle_t mixerTaskId;
// function running the mixer task
TASK_FUNCTION(mixerTask);
void mixerTask();
// init, create and start the OS task itself
void mixerTaskInit();
+2 -1
View File
@@ -20,6 +20,7 @@
*/
#include "edgetx.h"
#include "os/time.h"
/* Full telemetry
packet[0] = TX RSSI value
@@ -354,7 +355,7 @@ void processHitecPacket(const uint8_t * packet)
alt = (int16_t) ((packet[3] << 8) | packet[4]);
sensor = getHitecSensor(HITEC_ID_ALT);
setTelemetryValue(PROTOCOL_TELEMETRY_HITEC, HITEC_ID_ALT, 0, 0, alt, sensor->unit, sensor->precision);
current_ms = RTOS_GET_MS();
current_ms = time_get_ms();
sensor = getHitecSensor(HITEC_ID_VARIO);
value = (alt - last_alt) * 100;
if ((current_ms - last_ms) < 1000)
+10 -33
View File
@@ -21,6 +21,8 @@
#include "edgetx.h"
#include "multi.h"
#include "os/async.h"
#include "os/timer.h"
#include "pulses/afhds3.h"
#include "pulses/flysky.h"
#include "mixer_scheduler.h"
@@ -168,14 +170,10 @@ void telemetryMirrorSend(uint8_t data)
}
}
#if !defined(SIMU)
static TimerHandle_t telemetryTimer = nullptr;
static StaticTimer_t telemetryTimerBuffer;
static timer_handle_t telemetryTimer = TIMER_INITIALIZER;
static void telemetryTimerCb(TimerHandle_t xTimer)
static void telemetryTimerCb(timer_handle_t* h)
{
(void)xTimer;
DEBUG_TIMER_START(debugTimerTelemetryWakeup);
telemetryWakeup();
DEBUG_TIMER_STOP(debugTimerTelemetryWakeup);
@@ -183,25 +181,17 @@ static void telemetryTimerCb(TimerHandle_t xTimer)
void telemetryStart()
{
if (!telemetryTimer) {
telemetryTimer =
xTimerCreateStatic("Telem", 2 / RTOS_MS_PER_TICK, pdTRUE, (void*)0,
telemetryTimerCb, &telemetryTimerBuffer);
if (!timer_is_created(&telemetryTimer)) {
timer_create(&telemetryTimer, telemetryTimerCb, "Telem", 2, true);
}
if (telemetryTimer) {
if( xTimerStart( telemetryTimer, 0 ) != pdPASS ) {
/* The timer could not be set into the Active state. */
}
}
timer_start(&telemetryTimer);
}
void telemetryStop()
{
if (telemetryTimer) {
if( xTimerStop( telemetryTimer, 5 / RTOS_MS_PER_TICK ) != pdPASS ) {
/* The timer could not be stopped. */
}
if (!timer_is_created(&telemetryTimer)) {
timer_stop(&telemetryTimer);
}
}
@@ -248,21 +238,8 @@ 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;
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 );
}
async_call_isr(_poll_frame, &_poll_frame_queued[module], (void*)drv, module);
}
#endif
inline bool isBadAntennaDetected()
{