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:
Ken Van Hoeylandt
2023-12-30 12:39:07 +01:00
committed by GitHub
parent 60372076d5
commit b9427d4eba
83 changed files with 1180 additions and 623 deletions
+19
View File
@@ -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);
+102
View File
@@ -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;
}
+23
View File
@@ -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
+32
View File
@@ -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
View File
@@ -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();
}
-60
View File
@@ -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
+2 -1
View File
@@ -1,4 +1,5 @@
#include "common_defines.h"
#include "critical.h"
#include "furi_core_defines.h"
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
+22
View File
@@ -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 -1
View File
@@ -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>
+1 -1
View File
@@ -4,7 +4,7 @@
*/
#pragma once
#include "base.h"
#include "furi_core_types.h"
#ifdef __cplusplus
extern "C" {
+30
View File
@@ -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();
}
+28
View File
@@ -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
+12
View File
@@ -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"
+40
View File
@@ -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
+2 -4
View File
@@ -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"
-2
View File
@@ -1,7 +1,5 @@
#pragma once
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#ifdef __cplusplus
+11 -31
View File
@@ -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;
}
+2 -2
View File
@@ -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
*
+22
View File
@@ -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
+7 -7
View File
@@ -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;
+1 -1
View File
@@ -4,7 +4,7 @@
*/
#pragma once
#include "base.h"
#include "furi_core_types.h"
#ifdef __cplusplus
extern "C" {
+1 -1
View File
@@ -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>
+1 -1
View File
@@ -4,7 +4,7 @@
*/
#pragma once
#include "base.h"
#include "furi_core_types.h"
#include "thread.h"
#ifdef __cplusplus
+1 -2
View File
@@ -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)
+6 -6
View File
@@ -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.
+38 -15
View File
@@ -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);
}
}
+25 -12
View File
@@ -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
}
+2 -2
View File
@@ -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>
+2 -2
View File
@@ -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 -1
View File
@@ -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"
+2 -2
View File
@@ -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>
+9 -9
View File
@@ -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 -1
View File
@@ -1,6 +1,6 @@
#pragma once
#include "base.h"
#include "furi_core_types.h"
#ifdef __cplusplus
extern "C" {