committed by
GitHub
parent
3b9986fcef
commit
e842e30ab3
@@ -10,20 +10,11 @@ extern "C" {
|
||||
typedef struct _lv_obj_t lv_obj_t;
|
||||
|
||||
typedef enum {
|
||||
AppTypeService,
|
||||
AppTypeSystem,
|
||||
AppTypeDesktop,
|
||||
AppTypeSettings,
|
||||
AppTypeUser
|
||||
} AppType;
|
||||
|
||||
typedef enum {
|
||||
AppStackSizeTiny = 512,
|
||||
AppStackSizeSmall = 1024,
|
||||
AppStackSizeNormal = 2048,
|
||||
AppStackSizeLarge = 4096,
|
||||
AppStackSizeHuge = 8192,
|
||||
} AppStackSize;
|
||||
|
||||
typedef void (*AppOnStart)(void _Nonnull* parameter);
|
||||
typedef void (*AppOnStop)();
|
||||
typedef void (*AppOnShow)(lv_obj_t* parent, void* context);
|
||||
|
||||
@@ -6,10 +6,6 @@
|
||||
|
||||
#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) \
|
||||
@@ -17,7 +13,7 @@ DICT_DEF2(AppManifestDict, const char*, M_CSTR_DUP_OPLIST, const AppManifest*, M
|
||||
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; \
|
||||
const AppManifest*(manifest_var_name) = AppManifestDict_cref(it)->value; \
|
||||
code_to_execute; \
|
||||
} \
|
||||
app_registry_unlock(); \
|
||||
|
||||
@@ -37,7 +37,7 @@ FURI_NORETURN void __furi_halt_implementation();
|
||||
/** Crash system with message. */
|
||||
#define __furi_crash(message) \
|
||||
do { \
|
||||
ESP_LOGE("crash", "%s\n\tat %s:%d", ((message) ? ((const char*)message) : ""), __FILE__, __LINE__); \
|
||||
ESP_LOGE("crash", "%s\n\tat %s:%d", ((message) ? (message) : ""), __FILE__, __LINE__); \
|
||||
__furi_crash_implementation(); \
|
||||
} while (0)
|
||||
|
||||
@@ -50,7 +50,7 @@ FURI_NORETURN void __furi_halt_implementation();
|
||||
/** Halt system with message. */
|
||||
#define __furi_halt(message) \
|
||||
do { \
|
||||
ESP_LOGE("halt", "%s\n\tat %s:%d", ((message) ? ((const char*)message) : ""), __FILE__, __LINE__); \
|
||||
ESP_LOGE("halt", "%s\n\tat %s:%d", ((message) ? (message) : ""), __FILE__, __LINE__); \
|
||||
__furi_halt_implementation(); \
|
||||
} while (0)
|
||||
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
#include "furi.h"
|
||||
#include "app_manifest_registry.h"
|
||||
#include <string.h>
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/queue.h"
|
||||
|
||||
#define TAG "furi"
|
||||
|
||||
void furi_init() {
|
||||
FURI_LOG_I(TAG, "init start");
|
||||
furi_assert(!furi_kernel_is_irq());
|
||||
|
||||
if (xTaskGetSchedulerState() == taskSCHEDULER_RUNNING) {
|
||||
vTaskSuspendAll();
|
||||
}
|
||||
|
||||
furi_record_init();
|
||||
|
||||
xTaskResumeAll();
|
||||
|
||||
#if defined(__ARM_ARCH_7A__) && (__ARM_ARCH_7A__ == 0U)
|
||||
@@ -24,4 +23,5 @@ void furi_init() {
|
||||
#endif
|
||||
|
||||
app_manifest_registry_init();
|
||||
FURI_LOG_I(TAG, "init complete");
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
#include "message_queue.h"
|
||||
#include "mutex.h"
|
||||
#include "pubsub.h"
|
||||
#include "record.h"
|
||||
#include "semaphore.h"
|
||||
#include "stream_buffer.h"
|
||||
#include "string.h"
|
||||
|
||||
@@ -1,151 +0,0 @@
|
||||
#include "record.h"
|
||||
#include "check.h"
|
||||
#include "event_flag.h"
|
||||
#include "mutex.h"
|
||||
#include "m-dict.h"
|
||||
#include "m_cstr_dup.h"
|
||||
#include "log.h"
|
||||
|
||||
#define TAG "record"
|
||||
|
||||
#define FURI_RECORD_FLAG_READY (0x1)
|
||||
|
||||
typedef struct {
|
||||
FuriEventFlag* flags;
|
||||
void* data;
|
||||
size_t holders_count;
|
||||
} FuriRecordData;
|
||||
|
||||
DICT_DEF2(FuriRecordDataDict, const char*, M_CSTR_DUP_OPLIST, FuriRecordData, M_POD_OPLIST)
|
||||
|
||||
typedef struct {
|
||||
FuriMutex* mutex;
|
||||
FuriRecordDataDict_t records;
|
||||
} FuriRecord;
|
||||
|
||||
static FuriRecord* furi_record = NULL;
|
||||
|
||||
static FuriRecordData* furi_record_get(const char* name) {
|
||||
return FuriRecordDataDict_get(furi_record->records, name);
|
||||
}
|
||||
|
||||
static void furi_record_put(const char* name, FuriRecordData* record_data) {
|
||||
FuriRecordDataDict_set_at(furi_record->records, name, *record_data);
|
||||
}
|
||||
|
||||
static void furi_record_erase(const char* name, FuriRecordData* record_data) {
|
||||
furi_event_flag_free(record_data->flags);
|
||||
FuriRecordDataDict_erase(furi_record->records, name);
|
||||
}
|
||||
|
||||
void furi_record_init() {
|
||||
furi_record = malloc(sizeof(FuriRecord));
|
||||
furi_record->mutex = furi_mutex_alloc(FuriMutexTypeRecursive);
|
||||
furi_check(furi_record->mutex);
|
||||
FuriRecordDataDict_init(furi_record->records);
|
||||
}
|
||||
|
||||
static FuriRecordData* furi_record_data_get_or_create(const char* name) {
|
||||
furi_assert(furi_record);
|
||||
FuriRecordData* record_data = furi_record_get(name);
|
||||
if (!record_data) {
|
||||
FuriRecordData new_record;
|
||||
new_record.flags = furi_event_flag_alloc();
|
||||
new_record.data = NULL;
|
||||
new_record.holders_count = 0;
|
||||
furi_record_put(name, &new_record);
|
||||
record_data = furi_record_get(name);
|
||||
}
|
||||
return record_data;
|
||||
}
|
||||
|
||||
static void furi_record_lock() {
|
||||
furi_check(furi_mutex_acquire(furi_record->mutex, FuriWaitForever) == FuriStatusOk);
|
||||
}
|
||||
|
||||
static void furi_record_unlock() {
|
||||
furi_check(furi_mutex_release(furi_record->mutex) == FuriStatusOk);
|
||||
}
|
||||
|
||||
bool furi_record_exists(const char* name) {
|
||||
furi_assert(furi_record);
|
||||
furi_assert(name);
|
||||
|
||||
bool ret = false;
|
||||
|
||||
furi_record_lock();
|
||||
ret = (furi_record_get(name) != NULL);
|
||||
furi_record_unlock();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void furi_record_create(const char* name, void* data) {
|
||||
furi_assert(furi_record);
|
||||
|
||||
furi_record_lock();
|
||||
|
||||
// Get record data and fill it
|
||||
FuriRecordData* record_data = furi_record_data_get_or_create(name);
|
||||
furi_assert(record_data->data == NULL);
|
||||
record_data->data = data;
|
||||
furi_event_flag_set(record_data->flags, FURI_RECORD_FLAG_READY);
|
||||
|
||||
furi_record_unlock();
|
||||
}
|
||||
|
||||
bool furi_record_destroy(const char* name) {
|
||||
furi_assert(furi_record);
|
||||
|
||||
bool ret = false;
|
||||
|
||||
furi_record_lock();
|
||||
|
||||
FuriRecordData* record_data = furi_record_get(name);
|
||||
furi_assert(record_data);
|
||||
if (record_data->holders_count == 0) {
|
||||
furi_record_erase(name, record_data);
|
||||
ret = true;
|
||||
}
|
||||
|
||||
furi_record_unlock();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void* furi_record_open(const char* name) {
|
||||
furi_assert(name);
|
||||
furi_assert(furi_record);
|
||||
|
||||
furi_record_lock();
|
||||
|
||||
FuriRecordData* record_data = furi_record_data_get_or_create(name);
|
||||
record_data->holders_count++;
|
||||
|
||||
furi_record_unlock();
|
||||
|
||||
// Wait for record to become ready
|
||||
furi_check(
|
||||
furi_event_flag_wait(
|
||||
record_data->flags,
|
||||
FURI_RECORD_FLAG_READY,
|
||||
FuriFlagWaitAny | FuriFlagNoClear,
|
||||
FuriWaitForever
|
||||
) == FURI_RECORD_FLAG_READY
|
||||
);
|
||||
|
||||
return record_data->data;
|
||||
}
|
||||
|
||||
void furi_record_close(const char* name) {
|
||||
furi_assert(name);
|
||||
furi_assert(furi_record);
|
||||
|
||||
furi_record_lock();
|
||||
|
||||
FuriRecordData* record_data = furi_record_get(name);
|
||||
furi_assert(record_data);
|
||||
record_data->holders_count--;
|
||||
|
||||
furi_record_unlock();
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
/**
|
||||
* @file record.h
|
||||
* Furi: record API
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "furi_extra_defines.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Opens a record, calls the code and then closes the record.
|
||||
* @param record_name const char* that contains the name of the record
|
||||
* @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_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.
|
||||
*/
|
||||
void furi_record_init();
|
||||
|
||||
/** Check if record exists
|
||||
*
|
||||
* @param name record name
|
||||
* @note Thread safe. Create and destroy must be executed from the same
|
||||
* thread.
|
||||
*/
|
||||
bool furi_record_exists(const char* name);
|
||||
|
||||
/** Create record
|
||||
*
|
||||
* @param name record name
|
||||
* @param data data pointer
|
||||
* @note Thread safe. Create and destroy must be executed from the same
|
||||
* thread.
|
||||
*/
|
||||
void furi_record_create(const char* name, void* data);
|
||||
|
||||
/** Destroy record
|
||||
*
|
||||
* @param name record name
|
||||
*
|
||||
* @return true if successful, false if still have holders or thread is not
|
||||
* owner.
|
||||
* @note Thread safe. Create and destroy must be executed from the same
|
||||
* thread.
|
||||
*/
|
||||
bool furi_record_destroy(const char* name);
|
||||
|
||||
/** Open record
|
||||
*
|
||||
* @param name record name
|
||||
*
|
||||
* @return pointer to the record
|
||||
* @note Thread safe. Open and close must be executed from the same
|
||||
* thread. Suspends caller thread till record is available
|
||||
*/
|
||||
FURI_RETURNS_NONNULL void* furi_record_open(const char* name);
|
||||
|
||||
/** Close record
|
||||
*
|
||||
* @param name record name
|
||||
* @note Thread safe. Open and close must be executed from the same
|
||||
* thread.
|
||||
*/
|
||||
void furi_record_close(const char* name);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void (*ServiceOnStart)(void _Nonnull* parameter);
|
||||
typedef void (*ServiceOnStop)();
|
||||
|
||||
typedef struct {
|
||||
/**
|
||||
* The identifier by which the app is launched by the system and other apps.
|
||||
*/
|
||||
const char* _Nonnull id;
|
||||
|
||||
/**
|
||||
* Non-blocking method to call when service is started.
|
||||
*/
|
||||
const ServiceOnStart _Nullable on_start;
|
||||
|
||||
/**
|
||||
* Non-blocking method to call when service is stopped.
|
||||
*/
|
||||
const ServiceOnStop _Nullable on_stop;
|
||||
|
||||
} ServiceManifest;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user