App Loading via Loader (#1)
* app loading wip * various improvements irq/isr stuff is now working lvgl locking where needed hello world now uses proper mutex for app unlocking etc? * various improvements * cmsis_esp improvements * implement interrupts
This commit is contained in:
committed by
GitHub
parent
60372076d5
commit
b9427d4eba
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
#include "furi.h"
|
||||
|
||||
typedef FuriEventFlag* FuriApiLock;
|
||||
|
||||
#define API_LOCK_EVENT (1U << 0)
|
||||
|
||||
#define api_lock_alloc_locked() furi_event_flag_alloc()
|
||||
|
||||
#define api_lock_wait_unlock(_lock) \
|
||||
furi_event_flag_wait(_lock, API_LOCK_EVENT, FuriFlagWaitAny, FuriWaitForever)
|
||||
|
||||
#define api_lock_free(_lock) furi_event_flag_free(_lock)
|
||||
|
||||
#define api_lock_unlock(_lock) furi_event_flag_set(_lock, API_LOCK_EVENT)
|
||||
|
||||
#define api_lock_wait_unlock_and_free(_lock) \
|
||||
api_lock_wait_unlock(_lock); \
|
||||
api_lock_free(_lock);
|
||||
@@ -0,0 +1,102 @@
|
||||
#include "app_i.h"
|
||||
#include "furi_core.h"
|
||||
#include "log.h"
|
||||
#include "furi_string.h"
|
||||
|
||||
#define TAG "app"
|
||||
|
||||
const char* prv_type_service = "service";
|
||||
const char* prv_type_system = "system";
|
||||
const char* prv_type_user = "user";
|
||||
|
||||
static FuriThreadPriority get_thread_priority(AppType type) {
|
||||
switch (type) {
|
||||
case AppTypeService:
|
||||
return FuriThreadPriorityHighest;
|
||||
case AppTypeSystem:
|
||||
return FuriThreadPriorityHigh;
|
||||
case AppTypeUser:
|
||||
return FuriThreadPriorityNormal;
|
||||
default:
|
||||
furi_crash("no priority defined for app type");
|
||||
}
|
||||
}
|
||||
|
||||
const char* furi_app_type_to_string(AppType type) {
|
||||
switch (type) {
|
||||
case AppTypeService:
|
||||
return prv_type_service;
|
||||
case AppTypeSystem:
|
||||
return prv_type_system;
|
||||
case AppTypeUser:
|
||||
return prv_type_user;
|
||||
default:
|
||||
furi_crash();
|
||||
}
|
||||
}
|
||||
|
||||
App* furi_app_alloc(const AppManifest* _Nonnull manifest) {
|
||||
App app = {
|
||||
.manifest = manifest,
|
||||
.thread = NULL,
|
||||
.ep_thread_args = NULL
|
||||
};
|
||||
App* app_ptr = malloc(sizeof(App));
|
||||
return memcpy(app_ptr, &app, sizeof(App));
|
||||
}
|
||||
|
||||
void furi_app_free(App* app) {
|
||||
furi_assert(app);
|
||||
|
||||
if(app->thread) {
|
||||
furi_thread_join(app->thread);
|
||||
furi_thread_free(app->thread);
|
||||
}
|
||||
|
||||
if (app->ep_thread_args) {
|
||||
free(app->ep_thread_args);
|
||||
app->ep_thread_args = NULL;
|
||||
}
|
||||
|
||||
free(app);
|
||||
}
|
||||
|
||||
FuriThread* furi_app_alloc_thread(App _Nonnull* app, const char* args) {
|
||||
FURI_LOG_I(
|
||||
TAG,
|
||||
"Starting %s app \"%s\"",
|
||||
furi_app_type_to_string(app->manifest->type),
|
||||
app->manifest->name
|
||||
);
|
||||
|
||||
// Free any previous app launching arguments
|
||||
if (app->ep_thread_args) {
|
||||
free(app->ep_thread_args);
|
||||
}
|
||||
|
||||
if (args) {
|
||||
app->ep_thread_args = strdup(args);
|
||||
} else {
|
||||
app->ep_thread_args = NULL;
|
||||
}
|
||||
|
||||
FuriThread* thread = furi_thread_alloc_ex(
|
||||
app->manifest->name,
|
||||
app->manifest->stack_size,
|
||||
app->manifest->entry_point,
|
||||
app
|
||||
);
|
||||
|
||||
if (app->manifest->type == AppTypeService) {
|
||||
furi_thread_mark_as_service(thread);
|
||||
}
|
||||
|
||||
FuriString* app_name = furi_string_alloc();
|
||||
furi_thread_set_appid(thread, furi_string_get_cstr(app_name));
|
||||
furi_string_free(app_name);
|
||||
|
||||
FuriThreadPriority priority = get_thread_priority(app->manifest->type);
|
||||
furi_thread_set_priority(thread, priority);
|
||||
|
||||
return thread;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include "app_manifest.h"
|
||||
#include "thread.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
FuriThread* thread;
|
||||
const AppManifest* manifest;
|
||||
void* ep_thread_args;
|
||||
} App;
|
||||
|
||||
const char* furi_app_type_to_string(AppType type);
|
||||
FuriThread* furi_app_alloc_thread(App* _Nonnull app, const char* args);
|
||||
App* furi_app_alloc(const AppManifest* _Nonnull manifest);
|
||||
void furi_app_free(App* _Nonnull app);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
AppTypeService,
|
||||
AppTypeSystem,
|
||||
AppTypeUser
|
||||
} AppType;
|
||||
|
||||
typedef enum {
|
||||
AppStackSizeNormal = 2048
|
||||
} AppStackSize;
|
||||
|
||||
typedef int32_t (*AppEntryPoint)(void _Nonnull* parameter);
|
||||
|
||||
typedef struct {
|
||||
const char* _Nonnull id;
|
||||
const char* _Nonnull name;
|
||||
const char* _Nullable icon;
|
||||
const AppType type;
|
||||
const AppEntryPoint _Nullable entry_point;
|
||||
const AppStackSize stack_size;
|
||||
} AppManifest;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,79 @@
|
||||
#include "app_manifest_registry.h"
|
||||
#include "furi_core.h"
|
||||
#include "m-dict.h"
|
||||
#include "m_cstr_dup.h"
|
||||
#include "mutex.h"
|
||||
|
||||
#define TAG "app_registry"
|
||||
|
||||
typedef struct {
|
||||
const AppManifest* manifest;
|
||||
} AppEntry;
|
||||
|
||||
DICT_DEF2(AppManifestDict, const char*, M_CSTR_DUP_OPLIST, const AppManifest*, M_PTR_OPLIST)
|
||||
|
||||
#define APP_REGISTRY_FOR_EACH(manifest_var_name, code_to_execute) \
|
||||
{ \
|
||||
app_registry_lock(); \
|
||||
AppManifestDict_it_t it; \
|
||||
for (AppManifestDict_it(it, app_manifest_dict); !AppManifestDict_end_p(it); AppManifestDict_next(it)) { \
|
||||
const AppManifest* (manifest_var_name) = AppManifestDict_cref(it)->value; \
|
||||
code_to_execute; \
|
||||
} \
|
||||
app_registry_unlock(); \
|
||||
}
|
||||
|
||||
AppManifestDict_t app_manifest_dict;
|
||||
FuriMutex* mutex = NULL;
|
||||
|
||||
void app_manifest_registry_init() {
|
||||
furi_assert(mutex == NULL);
|
||||
mutex = furi_mutex_alloc(FuriMutexTypeNormal);
|
||||
AppManifestDict_init(app_manifest_dict);
|
||||
}
|
||||
|
||||
void app_registry_lock() {
|
||||
furi_assert(mutex != NULL);
|
||||
furi_mutex_acquire(mutex, FuriWaitForever);
|
||||
}
|
||||
|
||||
void app_registry_unlock() {
|
||||
furi_assert(mutex != NULL);
|
||||
furi_mutex_release(mutex);
|
||||
}
|
||||
|
||||
void app_manifest_registry_add(const AppManifest _Nonnull* manifest) {
|
||||
FURI_LOG_I(TAG, "adding %s", manifest->id);
|
||||
|
||||
app_registry_lock();
|
||||
AppManifestDict_set_at(app_manifest_dict, manifest->id, manifest);
|
||||
app_registry_unlock();
|
||||
}
|
||||
|
||||
void app_manifest_registry_remove(const AppManifest _Nonnull* manifest) {
|
||||
FURI_LOG_I(TAG, "removing %s", manifest->id);
|
||||
app_registry_lock();
|
||||
AppManifestDict_erase(app_manifest_dict, manifest->id);
|
||||
app_registry_unlock();
|
||||
}
|
||||
|
||||
const AppManifest _Nullable* app_manifest_registry_find_by_id(const char* id) {
|
||||
app_registry_lock();
|
||||
const AppManifest _Nullable** manifest = AppManifestDict_get(app_manifest_dict, id);
|
||||
app_registry_unlock();
|
||||
return (manifest != NULL) ? *manifest : NULL;
|
||||
}
|
||||
|
||||
void app_manifest_registry_for_each_of_type(AppType type, AppManifestCallback callback) {
|
||||
APP_REGISTRY_FOR_EACH(manifest, {
|
||||
if (manifest->type == type) {
|
||||
callback(manifest);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void app_manifest_registry_for_each(AppManifestCallback callback) {
|
||||
APP_REGISTRY_FOR_EACH(manifest, {
|
||||
callback(manifest);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include "app_manifest.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern const AppManifest* const INTERNAL_APP_MANIFESTS[];
|
||||
extern const size_t INTERNAL_APP_COUNT;
|
||||
|
||||
typedef void (*AppManifestCallback)(const AppManifest*);
|
||||
|
||||
void app_manifest_registry_init();
|
||||
void app_manifest_registry_add(const AppManifest _Nonnull* manifest);
|
||||
void app_manifest_registry_remove(const AppManifest _Nonnull* manifest);
|
||||
const AppManifest _Nullable* app_manifest_registry_find_by_id(const char* id);
|
||||
void app_manifest_registry_for_each(AppManifestCallback callback);
|
||||
void app_manifest_registry_for_each_of_type(AppType type, AppManifestCallback callback);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
+7
-110
@@ -1,110 +1,29 @@
|
||||
#include "check.h"
|
||||
#include "common_defines.h"
|
||||
#include "furi_core_defines.h"
|
||||
|
||||
#include "furi_hal_console.h"
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
PLACE_IN_SECTION("MB_MEM2")
|
||||
const char* __furi_check_message = NULL;
|
||||
PLACE_IN_SECTION("MB_MEM2")
|
||||
uint32_t __furi_check_registers[13] = {0};
|
||||
|
||||
/** Load r12 value to __furi_check_message and store registers to __furi_check_registers */
|
||||
/*#define GET_MESSAGE_AND_STORE_REGISTERS() \
|
||||
asm volatile("ldr r11, =__furi_check_message \n" \
|
||||
"str r12, [r11] \n" \
|
||||
"ldr r12, =__furi_check_registers \n" \
|
||||
"stm r12, {r0-r11} \n" \
|
||||
"str lr, [r12, #48] \n" \
|
||||
: \
|
||||
: \
|
||||
: "memory");*/
|
||||
|
||||
/** Restore registers and halt MCU
|
||||
*
|
||||
* - Always use it with GET_MESSAGE_AND_STORE_REGISTERS
|
||||
* - If debugger is(was) connected this routine will raise bkpt
|
||||
* - If debugger is not connected then endless loop
|
||||
*
|
||||
*/
|
||||
/*#define RESTORE_REGISTERS_AND_HALT_MCU(debug) \
|
||||
register bool a0 asm("a0") = debug; \
|
||||
asm volatile("cbnz a0, with_debugger%= \n" \
|
||||
"ldr a12, =__furi_check_registers\n" \
|
||||
"ldm a12, {a0-a11} \n" \
|
||||
"loop%=: \n" \
|
||||
"wfi \n" \
|
||||
"b loop%= \n" \
|
||||
"with_debugger%=: \n" \
|
||||
"ldr a12, =__furi_check_registers\n" \
|
||||
"ldm a12, {a0-a11} \n" \
|
||||
"debug_loop%=: \n" \
|
||||
"bkpt 0x00 \n" \
|
||||
"wfi \n" \
|
||||
"b debug_loop%= \n" \
|
||||
: \
|
||||
: "a"(a0) \
|
||||
: "memory");*/
|
||||
|
||||
extern size_t xPortGetTotalHeapSize(void);
|
||||
|
||||
static void __furi_put_uint32_as_text(uint32_t data) {
|
||||
char tmp_str[] = "-2147483648";
|
||||
itoa(data, tmp_str, 10);
|
||||
furi_hal_console_puts(tmp_str);
|
||||
}
|
||||
|
||||
static void __furi_put_uint32_as_hex(uint32_t data) {
|
||||
char tmp_str[] = "0xFFFFFFFF";
|
||||
itoa(data, tmp_str, 16);
|
||||
furi_hal_console_puts(tmp_str);
|
||||
}
|
||||
|
||||
static void __furi_print_register_info() {
|
||||
// Print registers
|
||||
for (uint8_t i = 0; i < 12; i++) {
|
||||
furi_hal_console_puts("\r\n\tr");
|
||||
__furi_put_uint32_as_text(i);
|
||||
furi_hal_console_puts(" : ");
|
||||
__furi_put_uint32_as_hex(__furi_check_registers[i]);
|
||||
}
|
||||
|
||||
furi_hal_console_puts("\r\n\tlr : ");
|
||||
__furi_put_uint32_as_hex(__furi_check_registers[12]);
|
||||
}
|
||||
|
||||
static void __furi_print_stack_info() {
|
||||
furi_hal_console_puts("\r\n\tstack watermark: ");
|
||||
__furi_put_uint32_as_text(uxTaskGetStackHighWaterMark(NULL) * 4);
|
||||
}
|
||||
|
||||
static void __furi_print_bt_stack_info() {
|
||||
/*
|
||||
const FuriHalBtHardfaultInfo* fault_info = furi_hal_bt_get_hardfault_info();
|
||||
if(fault_info == NULL) {
|
||||
furi_hal_console_puts("\r\n\tcore2: not faulted");
|
||||
} else {
|
||||
furi_hal_console_puts("\r\n\tcore2: hardfaulted.\r\n\tPC: ");
|
||||
__furi_put_uint32_as_hex(fault_info->source_pc);
|
||||
furi_hal_console_puts("\r\n\tLR: ");
|
||||
__furi_put_uint32_as_hex(fault_info->source_lr);
|
||||
furi_hal_console_puts("\r\n\tSP: ");
|
||||
__furi_put_uint32_as_hex(fault_info->source_sp);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
static void __furi_print_heap_info() {
|
||||
/*
|
||||
furi_hal_console_puts("\r\n\t heap total: ");
|
||||
__furi_put_uint32_as_text(xPortGetTotalHeapSize());
|
||||
*/
|
||||
furi_hal_console_puts("\r\n\t heap free: ");
|
||||
__furi_put_uint32_as_text(xPortGetFreeHeapSize());
|
||||
furi_hal_console_puts("\r\n\t heap watermark: ");
|
||||
__furi_put_uint32_as_text(xPortGetMinimumEverFreeHeapSize());
|
||||
furi_hal_console_puts("\r\n\theap total: ");
|
||||
__furi_put_uint32_as_text(heap_caps_get_total_size(MALLOC_CAP_DEFAULT));
|
||||
furi_hal_console_puts("\r\n\theap free: ");
|
||||
__furi_put_uint32_as_text(heap_caps_get_free_size(MALLOC_CAP_DEFAULT));
|
||||
furi_hal_console_puts("\r\n\theap min free: ");
|
||||
__furi_put_uint32_as_text(heap_caps_get_minimum_free_size(MALLOC_CAP_DEFAULT));
|
||||
}
|
||||
|
||||
static void __furi_print_name(bool isr) {
|
||||
@@ -130,24 +49,13 @@ FURI_NORETURN void __furi_crash_implementation() {
|
||||
|
||||
bool isr = FURI_IS_IRQ_MODE();
|
||||
|
||||
if (__furi_check_message == NULL) {
|
||||
__furi_check_message = "Fatal Error";
|
||||
} else if (__furi_check_message == (void*)__FURI_ASSERT_MESSAGE_FLAG) {
|
||||
__furi_check_message = "furi_assert failed";
|
||||
} else if (__furi_check_message == (void*)__FURI_CHECK_MESSAGE_FLAG) {
|
||||
__furi_check_message = "furi_check failed";
|
||||
}
|
||||
|
||||
furi_hal_console_puts("\r\n\033[0;31m[CRASH]");
|
||||
__furi_print_name(isr);
|
||||
furi_hal_console_puts(__furi_check_message);
|
||||
|
||||
__furi_print_register_info();
|
||||
if (!isr) {
|
||||
__furi_print_stack_info();
|
||||
}
|
||||
__furi_print_heap_info();
|
||||
__furi_print_bt_stack_info();
|
||||
|
||||
// Check if debug enabled by DAP
|
||||
// https://developer.arm.com/documentation/ddi0403/d/Debug-Architecture/ARMv7-M-Debug/Debug-register-support-in-the-SCS/Debug-Halting-Control-and-Status-Register--DHCSR?lang=en
|
||||
@@ -176,24 +84,13 @@ FURI_NORETURN void __furi_crash_implementation() {
|
||||
}
|
||||
FURI_NORETURN void __furi_halt_implementation() {
|
||||
__disable_irq();
|
||||
// GET_MESSAGE_AND_STORE_REGISTERS();
|
||||
|
||||
bool isr = FURI_IS_IRQ_MODE();
|
||||
|
||||
if (__furi_check_message == NULL) {
|
||||
__furi_check_message = "System halt requested.";
|
||||
}
|
||||
|
||||
furi_hal_console_puts("\r\n\033[0;31m[HALT]");
|
||||
__furi_print_name(isr);
|
||||
furi_hal_console_puts(__furi_check_message);
|
||||
furi_hal_console_puts("\r\nSystem halted. Bye-bye!\r\n");
|
||||
furi_hal_console_puts("\033[0m\r\n");
|
||||
|
||||
// Check if debug enabled by DAP
|
||||
// https://developer.arm.com/documentation/ddi0403/d/Debug-Architecture/ARMv7-M-Debug/Debug-register-support-in-the-SCS/Debug-Halting-Control-and-Status-Register--DHCSR?lang=en
|
||||
// bool debug = CoreDebug->DHCSR & CoreDebug_DHCSR_C_DEBUGEN_Msk;
|
||||
// RESTORE_REGISTERS_AND_HALT_MCU(true);
|
||||
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "core_defines.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <cmsis_compiler.h>
|
||||
|
||||
#ifndef FURI_WARN_UNUSED
|
||||
#define FURI_WARN_UNUSED __attribute__((warn_unused_result))
|
||||
#endif
|
||||
|
||||
#ifndef FURI_WEAK
|
||||
#define FURI_WEAK __attribute__((weak))
|
||||
#endif
|
||||
|
||||
#ifndef FURI_PACKED
|
||||
#define FURI_PACKED __attribute__((packed))
|
||||
#endif
|
||||
|
||||
#ifndef FURI_IS_IRQ_MASKED
|
||||
#define FURI_IS_IRQ_MASKED() (__get_PRIMASK() != 0U)
|
||||
#endif
|
||||
|
||||
#ifndef FURI_IS_IRQ_MODE
|
||||
#define FURI_IS_IRQ_MODE() (__get_IPSR() != 0U)
|
||||
#endif
|
||||
|
||||
#ifndef FURI_IS_ISR
|
||||
#define FURI_IS_ISR() (FURI_IS_IRQ_MODE() || FURI_IS_IRQ_MASKED())
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
uint32_t isrm;
|
||||
bool from_isr;
|
||||
bool kernel_running;
|
||||
} __FuriCriticalInfo;
|
||||
|
||||
__FuriCriticalInfo __furi_critical_enter(void);
|
||||
|
||||
void __furi_critical_exit(__FuriCriticalInfo info);
|
||||
|
||||
#ifndef FURI_CRITICAL_ENTER
|
||||
#define FURI_CRITICAL_ENTER() __FuriCriticalInfo __furi_critical_info = __furi_critical_enter();
|
||||
#endif
|
||||
|
||||
#ifndef FURI_CRITICAL_EXIT
|
||||
#define FURI_CRITICAL_EXIT() __furi_critical_exit(__furi_critical_info);
|
||||
#endif
|
||||
|
||||
#ifndef FURI_CHECK_RETURN
|
||||
#define FURI_CHECK_RETURN __attribute__((__warn_unused_result__))
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "common_defines.h"
|
||||
#include "critical.h"
|
||||
#include "furi_core_defines.h"
|
||||
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifndef FURI_CRITICAL_ENTER
|
||||
#define FURI_CRITICAL_ENTER() __FuriCriticalInfo __furi_critical_info = __furi_critical_enter();
|
||||
#endif
|
||||
|
||||
#ifndef FURI_CRITICAL_EXIT
|
||||
#define FURI_CRITICAL_EXIT() __furi_critical_exit(__furi_critical_info);
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
uint32_t isrm;
|
||||
bool from_isr;
|
||||
bool kernel_running;
|
||||
} __FuriCriticalInfo;
|
||||
|
||||
__FuriCriticalInfo __furi_critical_enter(void);
|
||||
|
||||
void __furi_critical_exit(__FuriCriticalInfo info);
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "event_flag.h"
|
||||
#include "check.h"
|
||||
#include "common_defines.h"
|
||||
#include "furi_core_defines.h"
|
||||
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/event_groups.h>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "base.h"
|
||||
#include "furi_core_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
#include "furi.h"
|
||||
#include "app_manifest_registry.h"
|
||||
#include <string.h>
|
||||
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/queue.h>
|
||||
|
||||
static bool scheduler_was_running = false;
|
||||
|
||||
void furi_init() {
|
||||
furi_assert(!furi_kernel_is_irq());
|
||||
|
||||
if (xTaskGetSchedulerState() == taskSCHEDULER_RUNNING) {
|
||||
vTaskSuspendAll();
|
||||
scheduler_was_running = true;
|
||||
}
|
||||
|
||||
furi_record_init();
|
||||
|
||||
xTaskResumeAll();
|
||||
|
||||
#if defined(__ARM_ARCH_7A__) && (__ARM_ARCH_7A__ == 0U)
|
||||
/* Service Call interrupt might be configured before kernel start */
|
||||
/* and when its priority is lower or equal to BASEPRI, svc instruction */
|
||||
/* causes a Hard Fault. */
|
||||
NVIC_SetPriority(SVCall_IRQn, 0U);
|
||||
#endif
|
||||
|
||||
app_manifest_registry_init();
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "furi_core.h"
|
||||
|
||||
#include "furi_string.h"
|
||||
#include "event_flag.h"
|
||||
#include "kernel.h"
|
||||
#include "message_queue.h"
|
||||
#include "mutex.h"
|
||||
#include "pubsub.h"
|
||||
#include "record.h"
|
||||
#include "semaphore.h"
|
||||
#include "stream_buffer.h"
|
||||
#include "string.h"
|
||||
#include "thread.h"
|
||||
#include "timer.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void furi_init();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "check.h"
|
||||
#include "critical.h"
|
||||
#include "event_flag.h"
|
||||
#include "furi_core_defines.h"
|
||||
#include "furi_core_types.h"
|
||||
#include "furi_extra_defines.h"
|
||||
#include "log.h"
|
||||
@@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
|
||||
#include "freertos/portmacro.h"
|
||||
#include "furi_extra_defines.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <cmsis_compiler.h>
|
||||
|
||||
#ifndef FURI_WARN_UNUSED
|
||||
#define FURI_WARN_UNUSED __attribute__((warn_unused_result))
|
||||
#endif
|
||||
|
||||
#ifndef FURI_WEAK
|
||||
#define FURI_WEAK __attribute__((weak))
|
||||
#endif
|
||||
|
||||
#ifndef FURI_PACKED
|
||||
#define FURI_PACKED __attribute__((packed))
|
||||
#endif
|
||||
|
||||
// Used by portENABLE_INTERRUPTS and portDISABLE_INTERRUPTS?
|
||||
#ifndef FURI_IS_IRQ_MODE
|
||||
#define FURI_IS_IRQ_MODE() (xPortInIsrContext() == pdTRUE)
|
||||
#endif
|
||||
|
||||
#ifndef FURI_IS_ISR
|
||||
#define FURI_IS_ISR() (FURI_IS_IRQ_MODE())
|
||||
#endif
|
||||
|
||||
#ifndef FURI_CHECK_RETURN
|
||||
#define FURI_CHECK_RETURN __attribute__((__warn_unused_result__))
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,10 +1,8 @@
|
||||
#include "furi_hal_console.h"
|
||||
#include "common_defines.h"
|
||||
#include "furi_core.h"
|
||||
#include "furi_string.h"
|
||||
|
||||
#include <esp_log.h>
|
||||
#include <memory.h>
|
||||
#include <stdbool.h>
|
||||
#include "esp_log.h" // TODO remove
|
||||
|
||||
#define TAG "FuriHalConsole"
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -1,34 +1,14 @@
|
||||
#include "kernel.h"
|
||||
#include "base.h"
|
||||
#include "check.h"
|
||||
#include "common_defines.h"
|
||||
#include "furi_core_defines.h"
|
||||
#include "furi_core_types.h"
|
||||
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
#include <rom/ets_sys.h>
|
||||
|
||||
bool furi_kernel_is_irq_or_masked() {
|
||||
bool irq = false;
|
||||
BaseType_t state;
|
||||
|
||||
if (FURI_IS_IRQ_MODE()) {
|
||||
/* Called from interrupt context */
|
||||
irq = true;
|
||||
} else {
|
||||
/* Get FreeRTOS scheduler state */
|
||||
state = xTaskGetSchedulerState();
|
||||
|
||||
if (state != taskSCHEDULER_NOT_STARTED) {
|
||||
/* Scheduler was started */
|
||||
if (FURI_IS_IRQ_MASKED()) {
|
||||
/* Interrupts are masked */
|
||||
irq = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Return context, 0: thread context, 1: IRQ context */
|
||||
return (irq);
|
||||
bool furi_kernel_is_irq() {
|
||||
return FURI_IS_IRQ_MODE();
|
||||
}
|
||||
|
||||
bool furi_kernel_is_running() {
|
||||
@@ -36,7 +16,7 @@ bool furi_kernel_is_running() {
|
||||
}
|
||||
|
||||
int32_t furi_kernel_lock() {
|
||||
furi_assert(!furi_kernel_is_irq_or_masked());
|
||||
furi_assert(!furi_kernel_is_irq());
|
||||
|
||||
int32_t lock;
|
||||
|
||||
@@ -61,7 +41,7 @@ int32_t furi_kernel_lock() {
|
||||
}
|
||||
|
||||
int32_t furi_kernel_unlock() {
|
||||
furi_assert(!furi_kernel_is_irq_or_masked());
|
||||
furi_assert(!furi_kernel_is_irq());
|
||||
|
||||
int32_t lock;
|
||||
|
||||
@@ -91,7 +71,7 @@ int32_t furi_kernel_unlock() {
|
||||
}
|
||||
|
||||
int32_t furi_kernel_restore_lock(int32_t lock) {
|
||||
furi_assert(!furi_kernel_is_irq_or_masked());
|
||||
furi_assert(!furi_kernel_is_irq());
|
||||
|
||||
switch (xTaskGetSchedulerState()) {
|
||||
case taskSCHEDULER_SUSPENDED:
|
||||
@@ -127,7 +107,7 @@ uint32_t furi_kernel_get_tick_frequency() {
|
||||
}
|
||||
|
||||
void furi_delay_tick(uint32_t ticks) {
|
||||
furi_assert(!furi_kernel_is_irq_or_masked());
|
||||
furi_assert(!furi_kernel_is_irq());
|
||||
if (ticks == 0U) {
|
||||
taskYIELD();
|
||||
} else {
|
||||
@@ -136,7 +116,7 @@ void furi_delay_tick(uint32_t ticks) {
|
||||
}
|
||||
|
||||
FuriStatus furi_delay_until_tick(uint32_t tick) {
|
||||
furi_assert(!furi_kernel_is_irq_or_masked());
|
||||
furi_assert(!furi_kernel_is_irq());
|
||||
|
||||
TickType_t tcnt, delay;
|
||||
FuriStatus stat;
|
||||
@@ -165,7 +145,7 @@ FuriStatus furi_delay_until_tick(uint32_t tick) {
|
||||
uint32_t furi_get_tick() {
|
||||
TickType_t ticks;
|
||||
|
||||
if (furi_kernel_is_irq_or_masked() != 0U) {
|
||||
if (furi_kernel_is_irq() != 0U) {
|
||||
ticks = xTaskGetTickCountFromISR();
|
||||
} else {
|
||||
ticks = xTaskGetTickCount();
|
||||
@@ -183,7 +163,7 @@ uint32_t furi_ms_to_ticks(uint32_t milliseconds) {
|
||||
}
|
||||
|
||||
void furi_delay_ms(uint32_t milliseconds) {
|
||||
if (!FURI_IS_ISR() && xTaskGetSchedulerState() == taskSCHEDULER_RUNNING) {
|
||||
if (xTaskGetSchedulerState() == taskSCHEDULER_RUNNING) {
|
||||
if (milliseconds > 0 && milliseconds < portMAX_DELAY - 1) {
|
||||
milliseconds += 1;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "base.h"
|
||||
#include "furi_core_types.h"
|
||||
|
||||
#define configTICK_RATE_HZ_RAW 1000
|
||||
|
||||
@@ -27,7 +27,7 @@ extern "C" {
|
||||
*
|
||||
* @return true if CPU is in IRQ or kernel running and IRQ is masked
|
||||
*/
|
||||
bool furi_kernel_is_irq_or_masked();
|
||||
bool furi_kernel_is_irq();
|
||||
|
||||
/** Check if kernel is running
|
||||
*
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include "esp_log.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define FURI_LOG_E(tag, format, ...) \
|
||||
ESP_LOGE(tag, format, ##__VA_ARGS__)
|
||||
#define FURI_LOG_W(tag, format, ...) \
|
||||
ESP_LOGW(tag, format, ##__VA_ARGS__)
|
||||
#define FURI_LOG_I(tag, format, ...) \
|
||||
ESP_LOGI(tag, format, ##__VA_ARGS__)
|
||||
#define FURI_LOG_D(tag, format, ...) \
|
||||
ESP_LOGD(tag, format, ##__VA_ARGS__)
|
||||
#define FURI_LOG_T(tag, format, ...) \
|
||||
ESP_LOGT(tag, format, ##__VA_ARGS__)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -6,7 +6,7 @@
|
||||
#include <freertos/queue.h>
|
||||
|
||||
FuriMessageQueue* furi_message_queue_alloc(uint32_t msg_count, uint32_t msg_size) {
|
||||
furi_assert((furi_kernel_is_irq_or_masked() == 0U) && (msg_count > 0U) && (msg_size > 0U));
|
||||
furi_assert((furi_kernel_is_irq() == 0U) && (msg_count > 0U) && (msg_size > 0U));
|
||||
|
||||
QueueHandle_t handle = xQueueCreate(msg_count, msg_size);
|
||||
furi_check(handle);
|
||||
@@ -15,7 +15,7 @@ FuriMessageQueue* furi_message_queue_alloc(uint32_t msg_count, uint32_t msg_size
|
||||
}
|
||||
|
||||
void furi_message_queue_free(FuriMessageQueue* instance) {
|
||||
furi_assert(furi_kernel_is_irq_or_masked() == 0U);
|
||||
furi_assert(furi_kernel_is_irq() == 0U);
|
||||
furi_assert(instance);
|
||||
|
||||
vQueueDelete((QueueHandle_t)instance);
|
||||
@@ -29,7 +29,7 @@ furi_message_queue_put(FuriMessageQueue* instance, const void* msg_ptr, uint32_t
|
||||
|
||||
stat = FuriStatusOk;
|
||||
|
||||
if (furi_kernel_is_irq_or_masked() != 0U) {
|
||||
if (furi_kernel_is_irq() != 0U) {
|
||||
if ((hQueue == NULL) || (msg_ptr == NULL) || (timeout != 0U)) {
|
||||
stat = FuriStatusErrorParameter;
|
||||
} else {
|
||||
@@ -66,7 +66,7 @@ FuriStatus furi_message_queue_get(FuriMessageQueue* instance, void* msg_ptr, uin
|
||||
|
||||
stat = FuriStatusOk;
|
||||
|
||||
if (furi_kernel_is_irq_or_masked() != 0U) {
|
||||
if (furi_kernel_is_irq() != 0U) {
|
||||
if ((hQueue == NULL) || (msg_ptr == NULL) || (timeout != 0U)) {
|
||||
stat = FuriStatusErrorParameter;
|
||||
} else {
|
||||
@@ -132,7 +132,7 @@ uint32_t furi_message_queue_get_count(FuriMessageQueue* instance) {
|
||||
|
||||
if (hQueue == NULL) {
|
||||
count = 0U;
|
||||
} else if (furi_kernel_is_irq_or_masked() != 0U) {
|
||||
} else if (furi_kernel_is_irq() != 0U) {
|
||||
count = uxQueueMessagesWaitingFromISR(hQueue);
|
||||
} else {
|
||||
count = uxQueueMessagesWaiting(hQueue);
|
||||
@@ -149,7 +149,7 @@ uint32_t furi_message_queue_get_space(FuriMessageQueue* instance) {
|
||||
|
||||
if (mq == NULL) {
|
||||
space = 0U;
|
||||
} else if (furi_kernel_is_irq_or_masked() != 0U) {
|
||||
} else if (furi_kernel_is_irq() != 0U) {
|
||||
isrm = taskENTER_CRITICAL_FROM_ISR();
|
||||
|
||||
/* space = pxQueue->uxLength - pxQueue->uxMessagesWaiting; */
|
||||
@@ -168,7 +168,7 @@ FuriStatus furi_message_queue_reset(FuriMessageQueue* instance) {
|
||||
QueueHandle_t hQueue = (QueueHandle_t)instance;
|
||||
FuriStatus stat;
|
||||
|
||||
if (furi_kernel_is_irq_or_masked() != 0U) {
|
||||
if (furi_kernel_is_irq() != 0U) {
|
||||
stat = FuriStatusErrorISR;
|
||||
} else if (hQueue == NULL) {
|
||||
stat = FuriStatusErrorParameter;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "base.h"
|
||||
#include "furi_core_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "mutex.h"
|
||||
#include "check.h"
|
||||
#include "common_defines.h"
|
||||
#include "furi_core_defines.h"
|
||||
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/semphr.h>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "base.h"
|
||||
#include "furi_core_types.h"
|
||||
#include "thread.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -2,9 +2,8 @@
|
||||
#include "check.h"
|
||||
#include "event_flag.h"
|
||||
#include "mutex.h"
|
||||
|
||||
#include "m-dict.h"
|
||||
#include "m_cstr_dup.h"
|
||||
#include <m-dict.h>
|
||||
|
||||
#define FURI_RECORD_FLAG_READY (0x1)
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core_defines.h"
|
||||
#include "furi_extra_defines.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -18,11 +18,11 @@ extern "C" {
|
||||
* @param variable_name the name of the variable that is used in the `code`
|
||||
* @param code the code to execute: consider putting it between {}
|
||||
*/
|
||||
#define FURI_RECORD_TRANSACTION(record_name, variable_name, code) \
|
||||
{ \
|
||||
Gui*(variable_name) = (Gui*)furi_record_open(record_name); \
|
||||
code; \
|
||||
furi_record_close(record_name); \
|
||||
#define FURI_RECORD_TRANSACTION(record_name, variable_type, variable_name, code) \
|
||||
{ \
|
||||
variable_type (variable_name) = (variable_type)furi_record_open(record_name); \
|
||||
code; \
|
||||
furi_record_close(record_name); \
|
||||
}
|
||||
|
||||
/** Initialize record storage For internal use only.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "semaphore.h"
|
||||
#include "check.h"
|
||||
#include "common_defines.h"
|
||||
#include "furi_core_defines.h"
|
||||
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/semphr.h>
|
||||
@@ -99,18 +99,41 @@ FuriStatus furi_semaphore_release(FuriSemaphore* instance) {
|
||||
return (stat);
|
||||
}
|
||||
|
||||
//uint32_t furi_semaphore_get_count(FuriSemaphore* instance) {
|
||||
// furi_assert(instance);
|
||||
//
|
||||
// SemaphoreHandle_t hSemaphore = (SemaphoreHandle_t)instance;
|
||||
// uint32_t count;
|
||||
//
|
||||
// if(FURI_IS_IRQ_MODE()) {
|
||||
uint32_t furi_semaphore_get_count(FuriSemaphore* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
SemaphoreHandle_t hSemaphore = (SemaphoreHandle_t)instance;
|
||||
uint32_t count;
|
||||
|
||||
if(FURI_IS_IRQ_MODE()) {
|
||||
furi_crash("not implemented");
|
||||
// count = (uint32_t)uxSemaphoreGetCountFromISR(hSemaphore);
|
||||
// } else {
|
||||
// count = (uint32_t)uxSemaphoreGetCount(hSemaphore);
|
||||
// }
|
||||
//
|
||||
// /* Return number of tokens */
|
||||
// return (count);
|
||||
//}
|
||||
} else {
|
||||
count = (uint32_t)uxSemaphoreGetCount(hSemaphore);
|
||||
}
|
||||
|
||||
/* Return number of tokens */
|
||||
return (count);
|
||||
}
|
||||
|
||||
bool furi_semaphore_take(FuriSemaphore* instance, TickType_t timeout) {
|
||||
furi_assert(instance);
|
||||
SemaphoreHandle_t hSemaphore = (SemaphoreHandle_t)instance;
|
||||
|
||||
if(FURI_IS_IRQ_MODE()) {
|
||||
furi_crash("not implemented");
|
||||
} else {
|
||||
return xSemaphoreTake(hSemaphore, timeout) == pdTRUE;
|
||||
}
|
||||
}
|
||||
|
||||
bool furi_semaphore_give(FuriSemaphore* instance) {
|
||||
furi_assert(instance);
|
||||
SemaphoreHandle_t hSemaphore = (SemaphoreHandle_t)instance;
|
||||
|
||||
if(FURI_IS_IRQ_MODE()) {
|
||||
furi_crash("not implemented");
|
||||
} else {
|
||||
return xSemaphoreGive(hSemaphore);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
/**
|
||||
* @file semaphore.h
|
||||
* FuriSemaphore
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "base.h"
|
||||
#include "furi_core_types.h"
|
||||
#include "thread.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -45,13 +41,30 @@ FuriStatus furi_semaphore_acquire(FuriSemaphore* instance, uint32_t timeout);
|
||||
*/
|
||||
FuriStatus furi_semaphore_release(FuriSemaphore* instance);
|
||||
|
||||
///** Get semaphore count
|
||||
// *
|
||||
// * @param instance The pointer to FuriSemaphore instance
|
||||
// *
|
||||
// * @return Semaphore count
|
||||
// */
|
||||
//uint32_t furi_semaphore_get_count(FuriSemaphore* instance);
|
||||
/** Get semaphore count
|
||||
*
|
||||
* @param instance The pointer to FuriSemaphore instance
|
||||
*
|
||||
* @return Semaphore count
|
||||
*/
|
||||
uint32_t furi_semaphore_get_count(FuriSemaphore* instance);
|
||||
|
||||
/** Wait for the semaphore to become available
|
||||
*
|
||||
* @param instance The pointer to FuriSemaphore instance
|
||||
* @param timeout The maximum amount of ticks to wait for the semaphore to become available
|
||||
*
|
||||
* @return True if the semaphore became available. False on timeout.
|
||||
*/
|
||||
bool furi_semaphore_take(FuriSemaphore* instance, TickType_t timeout);
|
||||
|
||||
/** Wait for the semaphore to become available
|
||||
*
|
||||
* @param instance The pointer to FuriSemaphore instance
|
||||
*
|
||||
* @return True if the semaphore became available. False on timeout.
|
||||
*/
|
||||
bool furi_semaphore_give(FuriSemaphore* instance);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "stream_buffer.h"
|
||||
#include "base.h"
|
||||
#include "check.h"
|
||||
#include "common_defines.h"
|
||||
#include "furi_core_defines.h"
|
||||
#include "furi_core_types.h"
|
||||
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/stream_buffer.h>
|
||||
|
||||
@@ -12,10 +12,10 @@
|
||||
* interrupt that will read from the buffer (the reader).
|
||||
*/
|
||||
#pragma once
|
||||
#include "furi_core_types.h"
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "base.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "thread.h"
|
||||
#include "check.h"
|
||||
#include "common_defines.h"
|
||||
#include "furi_core_defines.h"
|
||||
#include "furi_string.h"
|
||||
#include "kernel.h"
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base.h"
|
||||
#include "common_defines.h"
|
||||
#include "furi_core_defines.h"
|
||||
#include "furi_core_types.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -25,7 +25,7 @@ static void TimerCallback(TimerHandle_t hTimer) {
|
||||
}
|
||||
|
||||
FuriTimer* furi_timer_alloc(FuriTimerCallback func, FuriTimerType type, void* context) {
|
||||
furi_assert((furi_kernel_is_irq_or_masked() == 0U) && (func != NULL));
|
||||
furi_assert((furi_kernel_is_irq() == 0U) && (func != NULL));
|
||||
|
||||
TimerHandle_t hTimer;
|
||||
TimerCallback_t* callb;
|
||||
@@ -58,7 +58,7 @@ FuriTimer* furi_timer_alloc(FuriTimerCallback func, FuriTimerType type, void* co
|
||||
}
|
||||
|
||||
void furi_timer_free(FuriTimer* instance) {
|
||||
furi_assert(!furi_kernel_is_irq_or_masked());
|
||||
furi_assert(!furi_kernel_is_irq());
|
||||
furi_assert(instance);
|
||||
|
||||
TimerHandle_t hTimer = (TimerHandle_t)instance;
|
||||
@@ -80,7 +80,7 @@ void furi_timer_free(FuriTimer* instance) {
|
||||
}
|
||||
|
||||
FuriStatus furi_timer_start(FuriTimer* instance, uint32_t ticks) {
|
||||
furi_assert(!furi_kernel_is_irq_or_masked());
|
||||
furi_assert(!furi_kernel_is_irq());
|
||||
furi_assert(instance);
|
||||
furi_assert(ticks < portMAX_DELAY);
|
||||
|
||||
@@ -98,7 +98,7 @@ FuriStatus furi_timer_start(FuriTimer* instance, uint32_t ticks) {
|
||||
}
|
||||
|
||||
FuriStatus furi_timer_restart(FuriTimer* instance, uint32_t ticks) {
|
||||
furi_assert(!furi_kernel_is_irq_or_masked());
|
||||
furi_assert(!furi_kernel_is_irq());
|
||||
furi_assert(instance);
|
||||
furi_assert(ticks < portMAX_DELAY);
|
||||
|
||||
@@ -117,7 +117,7 @@ FuriStatus furi_timer_restart(FuriTimer* instance, uint32_t ticks) {
|
||||
}
|
||||
|
||||
FuriStatus furi_timer_stop(FuriTimer* instance) {
|
||||
furi_assert(!furi_kernel_is_irq_or_masked());
|
||||
furi_assert(!furi_kernel_is_irq());
|
||||
furi_assert(instance);
|
||||
|
||||
TimerHandle_t hTimer = (TimerHandle_t)instance;
|
||||
@@ -128,7 +128,7 @@ FuriStatus furi_timer_stop(FuriTimer* instance) {
|
||||
}
|
||||
|
||||
uint32_t furi_timer_is_running(FuriTimer* instance) {
|
||||
furi_assert(!furi_kernel_is_irq_or_masked());
|
||||
furi_assert(!furi_kernel_is_irq());
|
||||
furi_assert(instance);
|
||||
|
||||
TimerHandle_t hTimer = (TimerHandle_t)instance;
|
||||
@@ -138,7 +138,7 @@ uint32_t furi_timer_is_running(FuriTimer* instance) {
|
||||
}
|
||||
|
||||
uint32_t furi_timer_get_expire_time(FuriTimer* instance) {
|
||||
furi_assert(!furi_kernel_is_irq_or_masked());
|
||||
furi_assert(!furi_kernel_is_irq());
|
||||
furi_assert(instance);
|
||||
|
||||
TimerHandle_t hTimer = (TimerHandle_t)instance;
|
||||
@@ -148,7 +148,7 @@ uint32_t furi_timer_get_expire_time(FuriTimer* instance) {
|
||||
|
||||
void furi_timer_pending_callback(FuriTimerPendigCallback callback, void* context, uint32_t arg) {
|
||||
BaseType_t ret = pdFAIL;
|
||||
if (furi_kernel_is_irq_or_masked()) {
|
||||
if (furi_kernel_is_irq()) {
|
||||
ret = xTimerPendFunctionCallFromISR(callback, context, arg, NULL);
|
||||
} else {
|
||||
ret = xTimerPendFunctionCall(callback, context, arg, FuriWaitForever);
|
||||
@@ -157,7 +157,7 @@ void furi_timer_pending_callback(FuriTimerPendigCallback callback, void* context
|
||||
}
|
||||
|
||||
void furi_timer_set_thread_priority(FuriTimerThreadPriority priority) {
|
||||
furi_assert(!furi_kernel_is_irq_or_masked());
|
||||
furi_assert(!furi_kernel_is_irq());
|
||||
|
||||
TaskHandle_t task_handle = xTimerGetTimerDaemonTaskHandle();
|
||||
furi_check(task_handle); // Don't call this method before timer task start
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "base.h"
|
||||
#include "furi_core_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
||||
Reference in New Issue
Block a user