diff --git a/radio/src/CMakeLists.txt b/radio/src/CMakeLists.txt index 739ec570880..d40887daca5 100644 --- a/radio/src/CMakeLists.txt +++ b/radio/src/CMakeLists.txt @@ -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) diff --git a/radio/src/audio.cpp b/radio/src/audio.cpp index ce299856d9c..9d9e24873ea 100644 --- a/radio/src/audio.cpp +++ b/radio/src/audio.cpp @@ -21,6 +21,9 @@ #include +#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(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(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) diff --git a/radio/src/audio.h b/radio/src/audio.h index 0e987a6f674..f42e873e335 100644 --- a/radio/src/audio.h +++ b/radio/src/audio.h @@ -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) diff --git a/radio/src/bluetooth.cpp b/radio/src/bluetooth.cpp index 5b77e72a176..8e64e99818e 100644 --- a/radio/src/bluetooth.cpp +++ b/radio/src/bluetooth.cpp @@ -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(); diff --git a/radio/src/boards/generic_stm32/rgb_leds.cpp b/radio/src/boards/generic_stm32/rgb_leds.cpp index e93f4c8c003..d928d623167 100644 --- a/radio/src/boards/generic_stm32/rgb_leds.cpp +++ b/radio/src/boards/generic_stm32/rgb_leds.cpp @@ -30,18 +30,13 @@ #include "stm32_dma.h" #include "stm32_gpio.h" #include "hal/gpio.h" - -#if !defined(SIMU) -#include -#include -#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 = { diff --git a/radio/src/cli.cpp b/radio/src/cli.cpp index 108b9dc9b96..5872c743c24 100644 --- a/radio/src/cli.cpp +++ b/radio/src/cli.cpp @@ -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 &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); } diff --git a/radio/src/edgetx.cpp b/radio/src/edgetx.cpp index 05421d6ae0b..4b48890e17a 100644 --- a/radio/src/edgetx.cpp +++ b/radio/src/edgetx.cpp @@ -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 -#include - -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; } diff --git a/radio/src/gui/128x64/view_statistics.cpp b/radio/src/gui/128x64/view_statistics.cpp index f37b6a55fa5..1b952909228 100644 --- a/radio/src/gui/128x64/view_statistics.cpp +++ b/radio/src/gui/128x64/view_statistics.cpp @@ -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; diff --git a/radio/src/gui/212x64/view_statistics.cpp b/radio/src/gui/212x64/view_statistics.cpp index 4c892904ac3..93dfb4e08ea 100644 --- a/radio/src/gui/212x64/view_statistics.cpp +++ b/radio/src/gui/212x64/view_statistics.cpp @@ -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); diff --git a/radio/src/gui/colorlcd/LvglWrapper.cpp b/radio/src/gui/colorlcd/LvglWrapper.cpp index f44c8e5c7dd..81cf7038a73 100644 --- a/radio/src/gui/colorlcd/LvglWrapper.cpp +++ b/radio/src/gui/colorlcd/LvglWrapper.cpp @@ -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(); } diff --git a/radio/src/gui/colorlcd/LvglWrapper.h b/radio/src/gui/colorlcd/LvglWrapper.h index 2c50e50e8e8..b65732bd79e 100644 --- a/radio/src/gui/colorlcd/LvglWrapper.h +++ b/radio/src/gui/colorlcd/LvglWrapper.h @@ -33,9 +33,6 @@ class LvglWrapper static LvglWrapper *_instance; static void pollInputs(); - tmr10ms_t lastTick = 0; - // TODO: add driver instances here - LvglWrapper(); ~LvglWrapper() {} diff --git a/radio/src/gui/colorlcd/libui/fullscreen_dialog.cpp b/radio/src/gui/colorlcd/libui/fullscreen_dialog.cpp index deb2e3efdb6..2c45a69287b 100644 --- a/radio/src/gui/colorlcd/libui/fullscreen_dialog.cpp +++ b/radio/src/gui/colorlcd/libui/fullscreen_dialog.cpp @@ -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; } } diff --git a/radio/src/gui/colorlcd/libui/popups.cpp b/radio/src/gui/colorlcd/libui/popups.cpp index 131ba71b65a..14e284de181 100644 --- a/radio/src/gui/colorlcd/libui/popups.cpp +++ b/radio/src/gui/colorlcd/libui/popups.cpp @@ -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) diff --git a/radio/src/gui/colorlcd/libui/tabsgroup.cpp b/radio/src/gui/colorlcd/libui/tabsgroup.cpp index 4cf32d76078..6cb87cbb702 100644 --- a/radio/src/gui/colorlcd/libui/tabsgroup.cpp +++ b/radio/src/gui/colorlcd/libui/tabsgroup.cpp @@ -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 } } diff --git a/radio/src/gui/colorlcd/mainview/topbar_impl.cpp b/radio/src/gui/colorlcd/mainview/topbar_impl.cpp index bd6b42564d3..ae4753d0030 100644 --- a/radio/src/gui/colorlcd/mainview/topbar_impl.cpp +++ b/radio/src/gui/colorlcd/mainview/topbar_impl.cpp @@ -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(); diff --git a/radio/src/gui/colorlcd/mainview/view_statistics.cpp b/radio/src/gui/colorlcd/mainview/view_statistics.cpp index 72a077fa936..700a64ad610 100644 --- a/radio/src/gui/colorlcd/mainview/view_statistics.cpp +++ b/radio/src/gui/colorlcd/mainview/view_statistics.cpp @@ -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( 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( 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( 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) diff --git a/radio/src/gui/colorlcd/model/model_telemetry.cpp b/radio/src/gui/colorlcd/model/model_telemetry.cpp index 93e8c83a053..d8e8670de47 100644 --- a/radio/src/gui/colorlcd/model/model_telemetry.cpp +++ b/radio/src/gui/colorlcd/model/model_telemetry.cpp @@ -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()) { diff --git a/radio/src/gui/colorlcd/module/module_setup.cpp b/radio/src/gui/colorlcd/module/module_setup.cpp index d648fa3a056..3c12a691488 100644 --- a/radio/src/gui/colorlcd/module/module_setup.cpp +++ b/radio/src/gui/colorlcd/module/module_setup.cpp @@ -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 diff --git a/radio/src/gui/colorlcd/module/multi_rfprotos.cpp b/radio/src/gui/colorlcd/module/multi_rfprotos.cpp index 2fce5244aa2..888002d1210 100644 --- a/radio/src/gui/colorlcd/module/multi_rfprotos.cpp +++ b/radio/src/gui/colorlcd/module/multi_rfprotos.cpp @@ -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(); diff --git a/radio/src/gui/colorlcd/radio/radio_ghost_module_config.cpp b/radio/src/gui/colorlcd/radio/radio_ghost_module_config.cpp index 2f9bff2390c..8ec6250c7bf 100644 --- a/radio/src/gui/colorlcd/radio/radio_ghost_module_config.cpp +++ b/radio/src/gui/colorlcd/radio/radio_ghost_module_config.cpp @@ -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 diff --git a/radio/src/gui/colorlcd/startup_shutdown.cpp b/radio/src/gui/colorlcd/startup_shutdown.cpp index 918ad462cf3..c97604c6764 100644 --- a/radio/src/gui/colorlcd/startup_shutdown.cpp +++ b/radio/src/gui/colorlcd/startup_shutdown.cpp @@ -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); diff --git a/radio/src/gui/common/stdlcd/radio_ghost_menu.cpp b/radio/src/gui/common/stdlcd/radio_ghost_menu.cpp index 8742214ab13..a0e1e816e76 100644 --- a/radio/src/gui/common/stdlcd/radio_ghost_menu.cpp +++ b/radio/src/gui/common/stdlcd/radio_ghost_menu.cpp @@ -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; } diff --git a/radio/src/gui/common/stdlcd/radio_power_meter.cpp b/radio/src/gui/common/stdlcd/radio_power_meter.cpp index 05f2e1eccad..c7d6978d5eb 100644 --- a/radio/src/gui/common/stdlcd/radio_power_meter.cpp +++ b/radio/src/gui/common/stdlcd/radio_power_meter.cpp @@ -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; } diff --git a/radio/src/gui/common/stdlcd/radio_spectrum_analyser.cpp b/radio/src/gui/common/stdlcd/radio_spectrum_analyser.cpp index cea18b8b291..1dd5921f014 100644 --- a/radio/src/gui/common/stdlcd/radio_spectrum_analyser.cpp +++ b/radio/src/gui/common/stdlcd/radio_spectrum_analyser.cpp @@ -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; } diff --git a/radio/src/gui/common/stdlcd/splash.cpp b/radio/src/gui/common/stdlcd/splash.cpp index 0bf96ddc3ba..d52a116dead 100644 --- a/radio/src/gui/common/stdlcd/splash.cpp +++ b/radio/src/gui/common/stdlcd/splash.cpp @@ -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(); diff --git a/radio/src/gui/gui_common.cpp b/radio/src/gui/gui_common.cpp index aa597920a6d..39635b08fb9 100644 --- a/radio/src/gui/gui_common.cpp +++ b/radio/src/gui/gui_common.cpp @@ -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; diff --git a/radio/src/hal/fatfs_diskio.cpp b/radio/src/hal/fatfs_diskio.cpp index e5b62fd456b..39789489336 100644 --- a/radio/src/hal/fatfs_diskio.cpp +++ b/radio/src/hal/fatfs_diskio.cpp @@ -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) { } diff --git a/radio/src/io/bootloader_flash.cpp b/radio/src/io/bootloader_flash.cpp index b92e4a38889..37603c1b2a3 100644 --- a/radio/src/io/bootloader_flash.cpp +++ b/radio/src/io/bootloader_flash.cpp @@ -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 } diff --git a/radio/src/io/frsky_firmware_update.cpp b/radio/src/io/frsky_firmware_update.cpp index 9febcbfae5f..6a64873ecf8 100644 --- a/radio/src/io/frsky_firmware_update.cpp +++ b/radio/src/io/frsky_firmware_update.cpp @@ -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); diff --git a/radio/src/io/multi_firmware_update.cpp b/radio/src/io/multi_firmware_update.cpp index 0a9bec47d78..cb13f3bdb26 100644 --- a/radio/src/io/multi_firmware_update.cpp +++ b/radio/src/io/multi_firmware_update.cpp @@ -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 @@ -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); diff --git a/radio/src/io/multi_protolist.cpp b/radio/src/io/multi_protolist.cpp index bd566e80d31..dac982da94d 100644 --- a/radio/src/io/multi_protolist.cpp +++ b/radio/src/io/multi_protolist.cpp @@ -29,30 +29,20 @@ #include "gui_common.h" #include "edgetx.h" // reusableBuffer +#include "os/time.h" #include -#if !defined(SIMU) +static timer_handle_t _protoScanTimers[NUM_MODULES] = {TIMER_INITIALIZER}; -#include -#include - -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; } diff --git a/radio/src/io/multi_protolist.h b/radio/src/io/multi_protolist.h index a8f56d1b34c..dfe1546fd89 100644 --- a/radio/src/io/multi_protolist.h +++ b/radio/src/io/multi_protolist.h @@ -22,17 +22,13 @@ #include "dataconstants.h" #include "edgetx_types.h" +#include "os/timer.h" + #include #include #include #include -#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: diff --git a/radio/src/logs.cpp b/radio/src/logs.cpp index 3fd9e9ca978..0d2bc1916b5 100644 --- a/radio/src/logs.cpp +++ b/radio/src/logs.cpp @@ -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 -#include - -#include "tasks/mixer_task.h" +static timer_handle_t loggingTimer = TIMER_INITIALIZER; -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(); diff --git a/radio/src/lua/lua_widget.cpp b/radio/src/lua/lua_widget.cpp index e1ee83e81cb..08667943500 100644 --- a/radio/src/lua/lua_widget.cpp +++ b/radio/src/lua/lua_widget.cpp @@ -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; diff --git a/radio/src/main.cpp b/radio/src/main.cpp index cbcc6fb2ece..496129122a9 100644 --- a/radio/src/main.cpp +++ b/radio/src/main.cpp @@ -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(); diff --git a/radio/src/mixer_scheduler.cpp b/radio/src/mixer_scheduler.cpp index 1fcca7ce339..b150e5f0a43 100644 --- a/radio/src/mixer_scheduler.cpp +++ b/radio/src/mixer_scheduler.cpp @@ -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 + 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 diff --git a/radio/src/os/async.h b/radio/src/os/async.h new file mode 100644 index 00000000000..bf3cfbafa24 --- /dev/null +++ b/radio/src/os/async.h @@ -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 +#include + +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); diff --git a/radio/src/os/async_freertos.cpp b/radio/src/os/async_freertos.cpp new file mode 100644 index 00000000000..61d99468a90 --- /dev/null +++ b/radio/src/os/async_freertos.cpp @@ -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 +#include + +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; +} diff --git a/radio/src/os/async_native.cpp b/radio/src/os/async_native.cpp new file mode 100644 index 00000000000..140dba1248f --- /dev/null +++ b/radio/src/os/async_native.cpp @@ -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); +} diff --git a/radio/src/os/sleep.h b/radio/src/os/sleep.h new file mode 100644 index 00000000000..fee5dff46bd --- /dev/null +++ b/radio/src/os/sleep.h @@ -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); diff --git a/radio/src/os/sleep_freertos.cpp b/radio/src/os/sleep_freertos.cpp new file mode 100644 index 00000000000..492edb99d45 --- /dev/null +++ b/radio/src/os/sleep_freertos.cpp @@ -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 +#include + +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); +} diff --git a/radio/src/os/sleep_native.cpp b/radio/src/os/sleep_native.cpp new file mode 100644 index 00000000000..2f6849373e8 --- /dev/null +++ b/radio/src/os/sleep_native.cpp @@ -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 + +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{inc}; + std::this_thread::sleep_until(*tp); +} diff --git a/radio/src/os/sleep_nortos.cpp b/radio/src/os/sleep_nortos.cpp new file mode 100644 index 00000000000..b317da8c2ba --- /dev/null +++ b/radio/src/os/sleep_nortos.cpp @@ -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) {} +} + diff --git a/radio/src/os/task.h b/radio/src/os/task.h new file mode 100644 index 00000000000..8a48120d647 --- /dev/null +++ b/radio/src/os/task.h @@ -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 +#include + +// 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); + diff --git a/radio/src/os/task_freertos.cpp b/radio/src/os/task_freertos.cpp new file mode 100644 index 00000000000..ae60ff40b1e --- /dev/null +++ b/radio/src/os/task_freertos.cpp @@ -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); } diff --git a/radio/src/os/task_freertos.h b/radio/src/os/task_freertos.h new file mode 100644 index 00000000000..8e12d51b725 --- /dev/null +++ b/radio/src/os/task_freertos.h @@ -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 +#include +#include + +#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; +}; diff --git a/radio/src/os/task_pthread.cpp b/radio/src/os/task_pthread.cpp new file mode 100644 index 00000000000..d2775bd0136 --- /dev/null +++ b/radio/src/os/task_pthread.cpp @@ -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; +} + + diff --git a/radio/src/os/task_pthread.h b/radio/src/os/task_pthread.h new file mode 100644 index 00000000000..1da334cfb73 --- /dev/null +++ b/radio/src/os/task_pthread.h @@ -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 +#include + +#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; diff --git a/radio/src/os/time.h b/radio/src/os/time.h new file mode 100644 index 00000000000..d497c9c293a --- /dev/null +++ b/radio/src/os/time.h @@ -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 + +// 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(); diff --git a/radio/src/os/time_freertos.cpp b/radio/src/os/time_freertos.cpp new file mode 100644 index 00000000000..140bbb175ba --- /dev/null +++ b/radio/src/os/time_freertos.cpp @@ -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 +#include + +uint32_t time_get_ms() +{ + return xTaskGetTickCount() / portTICK_PERIOD_MS; +} + +time_point_t time_point_now() +{ + return xTaskGetTickCount(); +} diff --git a/radio/src/os/time_freertos.h b/radio/src/os/time_freertos.h new file mode 100644 index 00000000000..d95d96d8f97 --- /dev/null +++ b/radio/src/os/time_freertos.h @@ -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 + +typedef TickType_t time_point_t; diff --git a/radio/src/os/time_native.cpp b/radio/src/os/time_native.cpp new file mode 100644 index 00000000000..59f0ad370f9 --- /dev/null +++ b/radio/src/os/time_native.cpp @@ -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 + +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(); +} diff --git a/radio/src/os/time_native.h b/radio/src/os/time_native.h new file mode 100644 index 00000000000..eb8d2a3dcf5 --- /dev/null +++ b/radio/src/os/time_native.h @@ -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 + +typedef std::chrono::time_point time_point_t; + diff --git a/radio/src/os/time_nortos.cpp b/radio/src/os/time_nortos.cpp new file mode 100644 index 00000000000..255e81c3a85 --- /dev/null +++ b/radio/src/os/time_nortos.cpp @@ -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(); +} + diff --git a/radio/src/os/time_nortos.h b/radio/src/os/time_nortos.h new file mode 100644 index 00000000000..0579aed526c --- /dev/null +++ b/radio/src/os/time_nortos.h @@ -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 + +typedef uint32_t time_point_t; + diff --git a/radio/src/os/timer.h b/radio/src/os/timer.h new file mode 100644 index 00000000000..ba56385cb83 --- /dev/null +++ b/radio/src/os/timer.h @@ -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 +#include + +// 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); diff --git a/radio/src/os/timer_freertos.cpp b/radio/src/os/timer_freertos.cpp new file mode 100644 index 00000000000..895f23480f0 --- /dev/null +++ b/radio/src/os/timer_freertos.cpp @@ -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; +} diff --git a/radio/src/os/timer_freertos.h b/radio/src/os/timer_freertos.h new file mode 100644 index 00000000000..4b372f7c811 --- /dev/null +++ b/radio/src/os/timer_freertos.h @@ -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 +#include + +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 } diff --git a/radio/src/os/timer_pthread.cpp b/radio/src/os/timer_pthread.cpp new file mode 100644 index 00000000000..02e3e0d6388 --- /dev/null +++ b/radio/src/os/timer_pthread.cpp @@ -0,0 +1,215 @@ +#include "timer.h" +#include "timer_pthread_impl.h" + +#include + +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 lock(_cmds_mutex); + if (!_running) { + _running = true; + _thread = std::make_unique([&]() { main_loop(); }); + } +} + +void timer_queue::stop() { + bool stopping = false; + + std::unique_lock lock(_cmds_mutex); + std::unique_lock 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; +} diff --git a/radio/src/os/timer_pthread.h b/radio/src/os/timer_pthread.h new file mode 100644 index 00000000000..f879d1b8045 --- /dev/null +++ b/radio/src/os/timer_pthread.h @@ -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 + +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; + +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 {} + diff --git a/radio/src/os/timer_pthread_impl.h b/radio/src/os/timer_pthread_impl.h new file mode 100644 index 00000000000..931d3d9eb0c --- /dev/null +++ b/radio/src/os/timer_pthread_impl.h @@ -0,0 +1,74 @@ +#include "timer_pthread.h" + +#include +#include +#include +#include +#include +#include + +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 _thread; + bool _running; + + std::deque _cmds; + std::mutex _cmds_mutex; + std::condition_variable _cmds_condition; + + std::mutex _stop_mutex; + std::condition_variable _stop_condition; + + std::vector _timers; + std::vector _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); +}; diff --git a/radio/src/pulses/pulses.cpp b/radio/src/pulses/pulses.cpp index 5ee31deee09..5106c1000b4 100644 --- a/radio/src/pulses/pulses.cpp +++ b/radio/src/pulses/pulses.cpp @@ -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 -#include +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); diff --git a/radio/src/pulses/pxx2_ota.cpp b/radio/src/pulses/pxx2_ota.cpp index 7287a5245f4..16db5115472 100644 --- a/radio/src/pulses/pxx2_ota.cpp +++ b/radio/src/pulses/pxx2_ota.cpp @@ -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(); } diff --git a/radio/src/rtos.h b/radio/src/rtos.h index 705502ddf10..e0beae59caa 100644 --- a/radio/src/rtos.h +++ b/radio/src/rtos.h @@ -32,200 +32,25 @@ extern "C++" { #include #include - #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 - 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 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 - inline void RTOS_CREATE_TASK(pthread_t &taskId, void *(*task)(void *), - const char *name, TaskStack &, - 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 - #include - #include -#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 + #include 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 - 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 __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 diff --git a/radio/src/simu.cpp b/radio/src/simu.cpp index 5cf6e578a70..65e735e2703 100644 --- a/radio/src/simu.cpp +++ b/radio/src/simu.cpp @@ -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 @@ -166,7 +168,6 @@ OpenTxSim::~OpenTxSim() TRACE("OpenTxSim::~OpenTxSim()"); simuStop(); - stopAudioThread(); delete bmp; delete sliders[0]; @@ -492,7 +493,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; @@ -500,12 +501,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; @@ -644,8 +644,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(); diff --git a/radio/src/spacemouse.cpp b/radio/src/spacemouse.cpp index 74828f8256a..c09657852f5 100644 --- a/radio/src/spacemouse.cpp +++ b/radio/src/spacemouse.cpp @@ -20,13 +20,8 @@ */ #include "edgetx.h" -// #include #include "tasks/mixer_task.h" - -#if !defined(SIMU) - #include - #include -#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) diff --git a/radio/src/storage/modelslist.cpp b/radio/src/storage/modelslist.cpp index f7895c9ac37..d7370d2ac2a 100644 --- a/radio/src/storage/modelslist.cpp +++ b/radio/src/storage/modelslist.cpp @@ -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 } diff --git a/radio/src/storage/storage_common.cpp b/radio/src/storage/storage_common.cpp index 2fec387a5cd..72e3bdc39e2 100644 --- a/radio/src/storage/storage_common.cpp +++ b/radio/src/storage/storage_common.cpp @@ -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() diff --git a/radio/src/switches.cpp b/radio/src/switches.cpp index 2d06c9d3bc5..752d9c824ae 100644 --- a/radio/src/switches.cpp +++ b/radio/src/switches.cpp @@ -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(); diff --git a/radio/src/targets/common/arm/stm32/audio_dac_driver.cpp b/radio/src/targets/common/arm/stm32/audio_dac_driver.cpp index 48f8d174a8b..80a49d0a953 100644 --- a/radio/src/targets/common/arm/stm32/audio_dac_driver.cpp +++ b/radio/src/targets/common/arm/stm32/audio_dac_driver.cpp @@ -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; diff --git a/radio/src/targets/common/arm/stm32/bootloader/CMakeLists.txt b/radio/src/targets/common/arm/stm32/bootloader/CMakeLists.txt index 874f07fe847..5bf7ea35490 100644 --- a/radio/src/targets/common/arm/stm32/bootloader/CMakeLists.txt +++ b/radio/src/targets/common/arm/stm32/bootloader/CMakeLists.txt @@ -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 diff --git a/radio/src/targets/common/arm/stm32/bootloader/boot.cpp b/radio/src/targets/common/arm/stm32/bootloader/boot.cpp index 31835fca7b6..c9b93c9db93 100644 --- a/radio/src/targets/common/arm/stm32/bootloader/boot.cpp +++ b/radio/src/targets/common/arm/stm32/bootloader/boot.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() {} diff --git a/radio/src/targets/common/arm/stm32/bootloader/boot_dfu.cpp b/radio/src/targets/common/arm/stm32/bootloader/boot_dfu.cpp index fdf8177a7cc..918d938fc60 100644 --- a/radio/src/targets/common/arm/stm32/bootloader/boot_dfu.cpp +++ b/radio/src/targets/common/arm/stm32/bootloader/boot_dfu.cpp @@ -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(); diff --git a/radio/src/targets/common/arm/stm32/bootloader/boot_menu.cpp b/radio/src/targets/common/arm/stm32/bootloader/boot_menu.cpp index a519a1f1963..c0c62ddf310 100644 --- a/radio/src/targets/common/arm/stm32/bootloader/boot_menu.cpp +++ b/radio/src/targets/common/arm/stm32/bootloader/boot_menu.cpp @@ -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) { diff --git a/radio/src/targets/common/arm/stm32/bootloader/boot_uf2.cpp b/radio/src/targets/common/arm/stm32/bootloader/boot_uf2.cpp index 01ca1ea503f..0d8ba745148 100644 --- a/radio/src/targets/common/arm/stm32/bootloader/boot_uf2.cpp +++ b/radio/src/targets/common/arm/stm32/bootloader/boot_uf2.cpp @@ -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,18 +11,9 @@ #include "board.h" #include "lcd.h" -extern uf2_fat_write_state_t _uf2_write_state; - -volatile tmr10ms_t g_tmr10ms; -volatile uint8_t tenms = 1; +#define FRAME_INTERVAL_MS 20 -void per5ms() {} // make linker happy - -void per10ms() -{ - tenms |= 1u; // 10 mS has passed - g_tmr10ms++; -} +extern uf2_fat_write_state_t _uf2_write_state; void bootloaderUF2() { @@ -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()) { diff --git a/radio/src/targets/common/arm/stm32/rotary_encoder_driver.cpp b/radio/src/targets/common/arm/stm32/rotary_encoder_driver.cpp index 4faac300681..a26f768e96d 100644 --- a/radio/src/targets/common/arm/stm32/rotary_encoder_driver.cpp +++ b/radio/src/targets/common/arm/stm32/rotary_encoder_driver.cpp @@ -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; diff --git a/radio/src/targets/common/arm/stm32/timers_driver.cpp b/radio/src/targets/common/arm/stm32/timers_driver.cpp index bcb98170111..9cca5d0f663 100644 --- a/radio/src/targets/common/arm/stm32/timers_driver.cpp +++ b/radio/src/targets/common/arm/stm32/timers_driver.cpp @@ -100,8 +100,6 @@ static inline void _interrupt_1ms() watchdogTimeout -= 1; WDG_RESET(); // Retrigger hardware watchdog } - - per10ms(); } } diff --git a/radio/src/targets/common/arm/stm32/vs1053b.cpp b/radio/src/targets/common/arm/stm32/vs1053b.cpp index f86f3033649..829378f0ba1 100644 --- a/radio/src/targets/common/arm/stm32/vs1053b.cpp +++ b/radio/src/targets/common/arm/stm32/vs1053b.cpp @@ -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; diff --git a/radio/src/targets/horus/cst8xx_driver.cpp b/radio/src/targets/horus/cst8xx_driver.cpp index 36ac8426d77..71092978cd1 100644 --- a/radio/src/targets/horus/cst8xx_driver.cpp +++ b/radio/src/targets/horus/cst8xx_driver.cpp @@ -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()) { diff --git a/radio/src/targets/horus/tp_gt911.cpp b/radio/src/targets/horus/tp_gt911.cpp index 47bab716a91..6e6d21a5277 100644 --- a/radio/src/targets/horus/tp_gt911.cpp +++ b/radio/src/targets/horus/tp_gt911.cpp @@ -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) { diff --git a/radio/src/targets/simu/CMakeLists.txt b/radio/src/targets/simu/CMakeLists.txt index 664aa930305..a97d2899c94 100644 --- a/radio/src/targets/simu/CMakeLists.txt +++ b/radio/src/targets/simu/CMakeLists.txt @@ -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) diff --git a/radio/src/targets/simu/opentxsimulator.cpp b/radio/src/targets/simu/opentxsimulator.cpp index 0254f04c7e2..0d84baf4d05 100644 --- a/radio/src/targets/simu/opentxsimulator.cpp +++ b/radio/src/targets/simu/opentxsimulator.cpp @@ -28,6 +28,7 @@ #include "hal/adc_driver.h" #include "hal/rotary_encoder.h" +#include "os/time.h" #include #include @@ -270,9 +271,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 @@ -288,8 +289,6 @@ void OpenTxSimulator::stop() QMutexLocker lckr(&m_mtxSimuMain); simuStop(); - stopAudioThread(); - stopEepromThread(); emit stopped(); } @@ -309,20 +308,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(EEPROM_SIZE, data.size())); - memcpy(eeprom, data.data(), qMin(EEPROM_SIZE, data.size())); -#endif +// #if defined(EEPROM_SIZE) +// QMutexLocker lckr(&m_mtxRadioData); +// eeprom = (uint8_t *)malloc(qMin(EEPROM_SIZE, data.size())); +// memcpy(eeprom, data.data(), qMin(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(EEPROM_SIZE, dest.size())); -#endif +// #if defined(EEPROM_SIZE) +// QMutexLocker lckr(&m_mtxRadioData); +// if (eeprom) +// memcpy(dest.data(), eeprom, qMin(EEPROM_SIZE, dest.size())); +// #endif } uint8_t * OpenTxSimulator::getLcd() @@ -416,7 +415,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; @@ -759,8 +758,6 @@ void OpenTxSimulator::run() ++loops; - per10ms(); - checkLcdChanged(); if (!(loops % 5)) { diff --git a/radio/src/targets/simu/simpgmspace.cpp b/radio/src/targets/simu/simpgmspace.cpp index eecbf0c5369..4ca92e6dfe9 100644 --- a/radio/src/targets/simu/simpgmspace.cpp +++ b/radio/src/targets/simu/simpgmspace.cpp @@ -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 #include #include @@ -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. - - if ( !SDL_WasInit(SDL_INIT_AUDIO) ) { - fprintf(stderr, "ERROR: couldn't initialize SDL audio support\n"); - return 0; - } - */ + simuAudio = { + .volumeGain = volumeGain, + .leftoverLen = 0, + }; - SDL_AudioSpec wanted, have; + TRACE("startAudioThread(%d)", volumeGain); + audioSetVolume(VOLUME_LEVEL_DEF); /* 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 ) { + 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 nullptr; + return -1; } 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); - 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 + 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() {} diff --git a/radio/src/targets/simu/simpgmspace.h b/radio/src/targets/simu/simpgmspace.h index e18aebdbf89..b54afa439d3 100644 --- a/radio/src/targets/simu/simpgmspace.h +++ b/radio/src/targets/simu/simpgmspace.h @@ -30,17 +30,11 @@ #include #include -// #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 diff --git a/radio/src/targets/stm32h7s78-dk/tp_gt911.cpp b/radio/src/targets/stm32h7s78-dk/tp_gt911.cpp index d6966548a95..d4936b7213f 100644 --- a/radio/src/targets/stm32h7s78-dk/tp_gt911.cpp +++ b/radio/src/targets/stm32h7s78-dk/tp_gt911.cpp @@ -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) { diff --git a/radio/src/targets/taranis/gx12/bsp_io.cpp b/radio/src/targets/taranis/gx12/bsp_io.cpp index 235f575c1ac..4695e57de0c 100644 --- a/radio/src/targets/taranis/gx12/bsp_io.cpp +++ b/radio/src/targets/taranis/gx12/bsp_io.cpp @@ -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 #include -#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() diff --git a/radio/src/tasks.cpp b/radio/src/tasks.cpp index 8944f6039b5..2d8804fc018 100644 --- a/radio/src/tasks.cpp +++ b/radio/src/tasks.cpp @@ -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(); +} + +static void audioTask() +{ + while (!audioQueue.started()) { + sleep_ms(1); + } - TASK_RETURN(); +#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(); diff --git a/radio/src/tasks.h b/radio/src/tasks.h index 89f60156ddc..129abf7c78b 100644 --- a/radio/src/tasks.h +++ b/radio/src/tasks.h @@ -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 menusStack; -extern TaskStack mixerStack; +extern task_handle_t menusTaskId; #if defined(AUDIO) -extern TaskStack audioStack; +extern task_handle_t audioTaskId; #endif #if defined(CLI) -extern TaskStack cliStack; +extern task_handle_t cliTaskId; #endif void tasksStart(); diff --git a/radio/src/tasks/mixer_task.cpp b/radio/src/tasks/mixer_task.cpp index 921c92c7f6c..76b1cb89a8a 100644 --- a/radio/src/tasks/mixer_task.cpp +++ b/radio/src/tasks/mixer_task.cpp @@ -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() diff --git a/radio/src/tasks/mixer_task.h b/radio/src/tasks/mixer_task.h index 65c4e67b493..457b3591b9e 100644 --- a/radio/src/tasks/mixer_task.h +++ b/radio/src/tasks/mixer_task.h @@ -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(); diff --git a/radio/src/telemetry/hitec.cpp b/radio/src/telemetry/hitec.cpp index b9b54deac69..a05681a5eef 100644 --- a/radio/src/telemetry/hitec.cpp +++ b/radio/src/telemetry/hitec.cpp @@ -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) diff --git a/radio/src/telemetry/telemetry.cpp b/radio/src/telemetry/telemetry.cpp index c7c1f11b45e..c4019bd92e5 100644 --- a/radio/src/telemetry/telemetry.cpp +++ b/radio/src/telemetry/telemetry.cpp @@ -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() {