mirror of
https://github.com/ByteWelder/Tactility.git
synced 2026-02-18 19:03:16 +00:00
Update docs and fix bugs (#149)
Improved the docs for the 3 main Tactility projects. I also fixed some inaccuracies and bugs in certain APIs as I went through the code.
This commit is contained in:
parent
ff4287e2ce
commit
415096c3b2
@ -18,9 +18,7 @@ void app_main() {
|
||||
.hardware = TT_BOARD_HARDWARE,
|
||||
.apps = {
|
||||
&hello_world_app,
|
||||
},
|
||||
.services = {},
|
||||
.autoStartAppId = nullptr
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
|
||||
@ -41,8 +41,8 @@ bool lvgl_task_is_running() {
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool lvgl_lock(uint32_t timeout_ticks) {
|
||||
return lvgl_mutex.acquire(timeout_ticks) == tt::TtStatusOk;
|
||||
static bool lvgl_lock(uint32_t timeoutMillis) {
|
||||
return lvgl_mutex.acquire(pdMS_TO_TICKS(timeoutMillis)) == tt::TtStatusOk;
|
||||
}
|
||||
|
||||
static void lvgl_unlock() {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# Bugs
|
||||
# Issues
|
||||
- WiFi bug: when pressing disconnect while between `WIFI_EVENT_STA_START` and `IP_EVENT_STA_GOT_IP`, then auto-connect becomes active again.
|
||||
- ESP32 (CYD) memory issues (or any device without PSRAM):
|
||||
- Boot app doesn't show logo
|
||||
@ -11,8 +11,17 @@
|
||||
- Clean up static_cast when casting to base class.
|
||||
- M5Stack CoreS3 SD card mounts, but cannot be read. There is currently a notice about it [here](https://github.com/espressif/esp-bsp/blob/master/bsp/m5stack_core_s3/README.md).
|
||||
- SD card statusbar icon shows error when there's a read timeout on the SD card status. Don't show the error icon in this scenario.
|
||||
- EventFlag: Fix return value of set/get/wait (the errors are weirdly mixed in)
|
||||
- getConfiguration() in TT headless is a reference, while in TT main project it's a pointer. Make it a pointer for headless too.
|
||||
|
||||
# TODOs
|
||||
- Tactility.h config: List of apps and services can be a std::vector (get rid of TT_CONFIG_SERVICES_LIMIT and TT_CONFIG_APPS_LIMIT)
|
||||
- Boot hooks instead of a single boot method in config. Define different boot phases/levels in enum.
|
||||
- Rename "Desktop" to "Launcher" because it more clearly communicates its purpose
|
||||
- Add toggle to Display app for sysmon overlay: https://docs.lvgl.io/master/API/others/sysmon/index.html
|
||||
- Mutex: Cleanup deprecated methods
|
||||
- CrashHandler: use "corrupted" flag
|
||||
- CrashHandler: process other types of crashes (WDT?)
|
||||
- Call tt::lvgl::isSyncSet after HAL init and show error (and crash?) when it is not set.
|
||||
- Create different partitions files for different ESP flash size targets (N4, N8, N16, N32)
|
||||
- Attach ELF data to wrapper app (as app data) (check that app state is "running"!) so you can run more than 1 external apps at a time.
|
||||
@ -37,6 +46,8 @@
|
||||
- Support hot-plugging SD card
|
||||
|
||||
# Nice-to-haves
|
||||
- OTA updates
|
||||
- Web flasher
|
||||
- T-Deck Plus: Create separate board config?
|
||||
- Support for displays with different DPI. Consider the layer-based system like on Android.
|
||||
- Make firmwares available via web serial website
|
||||
|
||||
@ -7,17 +7,23 @@
|
||||
|
||||
namespace tt {
|
||||
|
||||
typedef struct {
|
||||
/** @brief The configuration for the operating system
|
||||
* It contains the hardware configuration, apps and services
|
||||
*/
|
||||
struct Configuration {
|
||||
/** HAL configuration (drivers) */
|
||||
const hal::Configuration* hardware;
|
||||
// List of user applications
|
||||
const app::AppManifest* const apps[TT_CONFIG_APPS_LIMIT];
|
||||
const service::ServiceManifest* const services[TT_CONFIG_SERVICES_LIMIT];
|
||||
const char* autoStartAppId;
|
||||
} Configuration;
|
||||
/** List of user applications */
|
||||
const app::AppManifest* const apps[TT_CONFIG_APPS_LIMIT] = {};
|
||||
/** List of user services */
|
||||
const service::ServiceManifest* const services[TT_CONFIG_SERVICES_LIMIT] = {};
|
||||
/** Optional app to start automatically after the splash screen. */
|
||||
const char* _Nullable autoStartAppId = nullptr;
|
||||
};
|
||||
|
||||
/**
|
||||
* Attempts to initialize Tactility and all configured hardware.
|
||||
* @param config
|
||||
* @param[in] config
|
||||
*/
|
||||
void run(const Configuration& config);
|
||||
|
||||
|
||||
@ -16,8 +16,8 @@ typedef union {
|
||||
} Flags;
|
||||
|
||||
/**
|
||||
* A limited representation of the application instance.
|
||||
* Do not store references or pointers to these!
|
||||
* The public representation of an application instance.
|
||||
* @warning Do not store references or pointers to these! You can retrieve them via the service registry.
|
||||
*/
|
||||
class AppContext {
|
||||
|
||||
|
||||
@ -11,7 +11,8 @@ namespace tt::app {
|
||||
|
||||
class AppContext;
|
||||
|
||||
typedef enum {
|
||||
/** Application types */
|
||||
enum Type {
|
||||
/** Boot screen, shown before desktop is launched. */
|
||||
TypeBoot,
|
||||
/** A desktop app sits at the root of the app stack managed by the Loader service */
|
||||
@ -24,8 +25,9 @@ typedef enum {
|
||||
TypeSettings,
|
||||
/** User-provided apps. */
|
||||
TypeUser
|
||||
} Type;
|
||||
};
|
||||
|
||||
/** Result status code for application result callback. */
|
||||
typedef enum {
|
||||
ResultOk,
|
||||
ResultCancelled,
|
||||
@ -39,49 +41,31 @@ typedef void (*AppOnHide)(AppContext& app);
|
||||
typedef void (*AppOnResult)(AppContext& app, Result result, const Bundle& resultData);
|
||||
|
||||
struct AppManifest {
|
||||
/**
|
||||
* The identifier by which the app is launched by the system and other apps.
|
||||
*/
|
||||
/** The identifier by which the app is launched by the system and other apps. */
|
||||
std::string id;
|
||||
|
||||
/**
|
||||
* The user-readable name of the app. Used in UI.
|
||||
*/
|
||||
/** The user-readable name of the app. Used in UI. */
|
||||
std::string name;
|
||||
|
||||
/**
|
||||
* Optional icon.
|
||||
*/
|
||||
/** Optional icon. */
|
||||
std::string icon = {};
|
||||
|
||||
/**
|
||||
* App type affects launch behaviour.
|
||||
*/
|
||||
/** App type affects launch behaviour. */
|
||||
Type type = TypeUser;
|
||||
|
||||
/**
|
||||
* Non-blocking method to call when app is started.
|
||||
*/
|
||||
/** Non-blocking method to call when app is started. */
|
||||
AppOnStart onStart = nullptr;
|
||||
|
||||
/**
|
||||
* Non-blocking method to call when app is stopped.
|
||||
*/
|
||||
/** Non-blocking method to call when app is stopped. */
|
||||
AppOnStop _Nullable onStop = nullptr;
|
||||
|
||||
/**
|
||||
* Non-blocking method to create the GUI
|
||||
*/
|
||||
/** Non-blocking method to create the GUI. */
|
||||
AppOnShow _Nullable onShow = nullptr;
|
||||
|
||||
/**
|
||||
* Non-blocking method, called before gui is destroyed
|
||||
*/
|
||||
/** Non-blocking method, called before gui is destroyed. */
|
||||
AppOnHide _Nullable onHide = nullptr;
|
||||
|
||||
/**
|
||||
* Handle the result for apps that are launched
|
||||
*/
|
||||
/** Handle the result for apps that are launched. */
|
||||
AppOnResult _Nullable onResult = nullptr;
|
||||
};
|
||||
|
||||
|
||||
@ -22,7 +22,7 @@ bool startElfApp(const std::string& filePath) {
|
||||
assert(elfFileData == nullptr);
|
||||
|
||||
size_t size = 0;
|
||||
elfFileData = file::readBinary(filePath.c_str(), size);
|
||||
elfFileData = file::readBinary(filePath, size);
|
||||
if (elfFileData == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -6,8 +6,16 @@
|
||||
|
||||
namespace tt::app {
|
||||
|
||||
/** Register an application with its manifest */
|
||||
void addApp(const AppManifest* manifest);
|
||||
|
||||
/** Find an application manifest by its id
|
||||
* @param[in] id the manifest id
|
||||
* @return the application manifest if it was found
|
||||
*/
|
||||
const AppManifest _Nullable* findAppById(const std::string& id);
|
||||
|
||||
/** @return a list of all registered apps. This includes user and system apps. */
|
||||
std::vector<const AppManifest*> getApps();
|
||||
|
||||
} // namespace
|
||||
|
||||
@ -9,10 +9,10 @@
|
||||
#include <esp_cpu_utils.h>
|
||||
|
||||
std::string getUrlFromCrashData() {
|
||||
auto* crash_data = getRtcCrashData();
|
||||
auto* stack_buffer = (uint32_t*) malloc(crash_data->callstackLength * 2 * sizeof(uint32_t));
|
||||
for (int i = 0; i < crash_data->callstackLength; ++i) {
|
||||
const CallstackFrame&frame = crash_data->callstack[i];
|
||||
auto crash_data = getRtcCrashData();
|
||||
auto* stack_buffer = (uint32_t*) malloc(crash_data.callstackLength * 2 * sizeof(uint32_t));
|
||||
for (int i = 0; i < crash_data.callstackLength; ++i) {
|
||||
const CallstackFrame&frame = crash_data.callstack[i];
|
||||
uint32_t pc = esp_cpu_process_stack_pc(frame.pc);
|
||||
#if CRASH_DATA_INCLUDES_SP
|
||||
uint32_t sp = frame.sp;
|
||||
@ -30,7 +30,7 @@ std::string getUrlFromCrashData() {
|
||||
stream << "&a=" << CONFIG_IDF_TARGET; // Architecture
|
||||
stream << "&s="; // Stacktrace
|
||||
|
||||
for (int i = crash_data->callstackLength - 1; i >= 0; --i) {
|
||||
for (int i = crash_data.callstackLength - 1; i >= 0; --i) {
|
||||
uint32_t pc = stack_buffer[(i * 2)];
|
||||
stream << std::hex << pc;
|
||||
#if CRASH_DATA_INCLUDES_SP
|
||||
|
||||
@ -3,10 +3,10 @@
|
||||
|
||||
namespace tt::lvgl {
|
||||
|
||||
Mutex lockMutex;
|
||||
static Mutex lockMutex;
|
||||
|
||||
static bool defaultLock(uint32_t timeoutTicks) {
|
||||
return lockMutex.acquire(timeoutTicks) == TtStatusOk;
|
||||
static bool defaultLock(uint32_t timeoutMillis) {
|
||||
return lockMutex.acquire(timeoutMillis) == TtStatusOk;
|
||||
}
|
||||
|
||||
static void defaultUnlock() {
|
||||
@ -21,8 +21,8 @@ void syncSet(LvglLock lock, LvglUnlock unlock) {
|
||||
unlock_singleton = unlock;
|
||||
}
|
||||
|
||||
bool lock(uint32_t timeout_ticks) {
|
||||
return lock_singleton(timeout_ticks);
|
||||
bool lock(TickType_t timeout) {
|
||||
return lock_singleton(pdMS_TO_TICKS(timeout == 0 ? portMAX_DELAY : timeout));
|
||||
}
|
||||
|
||||
void unlock() {
|
||||
@ -33,7 +33,7 @@ class LvglSync : public Lockable {
|
||||
public:
|
||||
~LvglSync() override = default;
|
||||
|
||||
bool lock(uint32_t timeoutTicks) const override {
|
||||
bool lock(TickType_t timeoutTicks) const override {
|
||||
return tt::lvgl::lock(timeoutTicks);
|
||||
}
|
||||
|
||||
|
||||
@ -6,12 +6,23 @@
|
||||
|
||||
namespace tt::lvgl {
|
||||
|
||||
typedef bool (*LvglLock)(uint32_t timeout_ticks);
|
||||
/**
|
||||
* LVGL locking function
|
||||
* @param[in] timeoutMillis timeout in milliseconds. waits forever when 0 is passed.
|
||||
* @warning this works with milliseconds, as opposed to every other FreeRTOS function that works in ticks!
|
||||
* @warning when passing zero, we wait forever, as this is the default behaviour for esp_lvgl_port, and we want it to remain consistent
|
||||
*/
|
||||
typedef bool (*LvglLock)(uint32_t timeoutMillis);
|
||||
typedef void (*LvglUnlock)();
|
||||
|
||||
void syncSet(LvglLock lock, LvglUnlock unlock);
|
||||
bool isSyncSet();
|
||||
bool lock(uint32_t timeout_ticks);
|
||||
|
||||
/**
|
||||
* LVGL locking function
|
||||
* @param[in] timeout as ticks
|
||||
* @warning when passing zero, we wait forever, as this is the default behaviour for esp_lvgl_port, and we want it to remain consistent
|
||||
*/
|
||||
bool lock(TickType_t timeout);
|
||||
void unlock();
|
||||
|
||||
std::shared_ptr<Lockable> getLvglSyncLockable();
|
||||
|
||||
@ -9,12 +9,11 @@ typedef struct Gui Gui;
|
||||
|
||||
/**
|
||||
* Set the app viewport in the gui state and request the gui to draw it.
|
||||
*
|
||||
* @param app
|
||||
* @param on_show
|
||||
* @param on_hide
|
||||
* @param[in] app
|
||||
* @param[in] onShow
|
||||
* @param[in] onHide
|
||||
*/
|
||||
void showApp(app::AppContext& app, ViewPortShowCallback on_show, ViewPortHideCallback on_hide);
|
||||
void showApp(app::AppContext& app, ViewPortShowCallback onShow, ViewPortHideCallback onHide);
|
||||
|
||||
/**
|
||||
* Hide the current app's viewport.
|
||||
@ -25,7 +24,7 @@ void hideApp();
|
||||
|
||||
/**
|
||||
* Show the on-screen keyboard.
|
||||
* @param textarea the textarea to focus the input for
|
||||
* @param[in] textarea the textarea to focus the input for
|
||||
*/
|
||||
void keyboardShow(lv_obj_t* textarea);
|
||||
|
||||
@ -47,7 +46,7 @@ bool keyboardIsEnabled();
|
||||
* Glue code for the on-screen keyboard and the hardware keyboard:
|
||||
* - Attach automatic hide/show parameters for the on-screen keyboard.
|
||||
* - Registers the textarea to the default lv_group_t for hardware keyboards.
|
||||
* @param textarea
|
||||
* @param[in] textarea
|
||||
*/
|
||||
void keyboardAddTextArea(lv_obj_t* textarea);
|
||||
|
||||
|
||||
@ -26,26 +26,22 @@ typedef struct ViewPort {
|
||||
} ViewPort;
|
||||
|
||||
/** ViewPort allocator
|
||||
*
|
||||
* always returns view_port or stops system if not enough memory.
|
||||
* @param app
|
||||
* @param on_show Called to create LVGL widgets
|
||||
* @param on_hide Called before clearing the LVGL widget parent
|
||||
*
|
||||
* @return ViewPort instance
|
||||
* @param onShow Called to create LVGL widgets
|
||||
* @param onHide Called before clearing the LVGL widget parent
|
||||
* @return ViewPort instance
|
||||
*/
|
||||
ViewPort* view_port_alloc(
|
||||
app::AppContext& app,
|
||||
ViewPortShowCallback on_show,
|
||||
ViewPortHideCallback on_hide
|
||||
ViewPortShowCallback onShow,
|
||||
ViewPortHideCallback onHide
|
||||
);
|
||||
|
||||
/** ViewPort deallocator
|
||||
*
|
||||
/** ViewPort destruction
|
||||
* Ensure that view_port was unregistered in GUI system before use.
|
||||
*
|
||||
* @param view_port ViewPort instance
|
||||
* @param viewPort ViewPort instance
|
||||
*/
|
||||
void view_port_free(ViewPort* view_port);
|
||||
void view_port_free(ViewPort* viewPort);
|
||||
|
||||
} // namespace
|
||||
|
||||
@ -26,11 +26,10 @@ typedef enum {
|
||||
*/
|
||||
void startApp(const std::string& id, bool blocking = false, std::shared_ptr<const Bundle> _Nullable parameters = nullptr);
|
||||
|
||||
/**
|
||||
* @brief Stop the currently showing app. Show the previous app if any app was still running.
|
||||
*/
|
||||
/** @brief Stop the currently showing app. Show the previous app if any app was still running. */
|
||||
void stopApp();
|
||||
|
||||
/** @return the currently running app (it is only ever null before the splash screen is shown) */
|
||||
app::AppContext* _Nullable getCurrentApp();
|
||||
|
||||
/**
|
||||
|
||||
@ -39,7 +39,7 @@ void ScreenshotService::startApps(const char* path) {
|
||||
}
|
||||
}
|
||||
|
||||
void ScreenshotService::startTimed(const char* path, uint8_t delay_in_seconds, uint8_t amount) {
|
||||
void ScreenshotService::startTimed(const char* path, uint8_t delayInSeconds, uint8_t amount) {
|
||||
auto scoped_lockable = mutex.scoped();
|
||||
if (!scoped_lockable->lock(50 / portTICK_PERIOD_MS)) {
|
||||
TT_LOG_W(TAG, LOG_MESSAGE_MUTEX_LOCK_FAILED);
|
||||
@ -49,7 +49,7 @@ void ScreenshotService::startTimed(const char* path, uint8_t delay_in_seconds, u
|
||||
if (task == nullptr || task->isFinished()) {
|
||||
task = std::make_unique<ScreenshotTask>();
|
||||
mode = ScreenshotModeTimed;
|
||||
task->startTimed(path, delay_in_seconds, amount);
|
||||
task->startTimed(path, delayInSeconds, amount);
|
||||
} else {
|
||||
TT_LOG_W(TAG, "Screenshot task already running");
|
||||
}
|
||||
|
||||
@ -16,8 +16,10 @@ typedef enum {
|
||||
ScreenshotModeApps
|
||||
} Mode;
|
||||
|
||||
|
||||
class ScreenshotService {
|
||||
|
||||
private:
|
||||
|
||||
Mutex mutex;
|
||||
std::unique_ptr<ScreenshotTask> task;
|
||||
Mode mode = ScreenshotModeNone;
|
||||
@ -25,9 +27,23 @@ class ScreenshotService {
|
||||
public:
|
||||
|
||||
bool isTaskStarted();
|
||||
|
||||
/** The state of the service. */
|
||||
Mode getMode();
|
||||
|
||||
/** @brief Start taking screenshot whenever an app is started
|
||||
* @param[in] path the path to store the screenshots at
|
||||
*/
|
||||
void startApps(const char* path);
|
||||
void startTimed(const char* path, uint8_t delay_in_seconds, uint8_t amount);
|
||||
|
||||
/** @brief Start taking screenshots after a certain delay
|
||||
* @param[in] path the path to store the screenshots at
|
||||
* @param[in] delayInSeconds the delay before starting (and between successive screenshots)
|
||||
* @param[in] amount 0 = indefinite, >0 for a specific
|
||||
*/
|
||||
void startTimed(const char* path, uint8_t delayInSeconds, uint8_t amount);
|
||||
|
||||
/** @brief Stop taking screenshots */
|
||||
void stop();
|
||||
};
|
||||
|
||||
|
||||
@ -35,22 +35,18 @@ public:
|
||||
~ScreenshotTask();
|
||||
|
||||
/** @brief Start taking screenshots after a certain delay
|
||||
* @param task the screenshot task
|
||||
* @param path the path to store the screenshots at
|
||||
* @param delay_in_seconds the delay before starting (and between successive screenshots)
|
||||
* @param amount 0 = indefinite, >0 for a specific
|
||||
* @param[in] path the path to store the screenshots at
|
||||
* @param[in] delayInSeconds the delay before starting (and between successive screenshots)
|
||||
* @param[in] amount 0 = indefinite, >0 for a specific
|
||||
*/
|
||||
void startTimed(const char* path, uint8_t delay_in_seconds, uint8_t amount);
|
||||
void startTimed(const char* path, uint8_t delayInSeconds, uint8_t amount);
|
||||
|
||||
/** @brief Start taking screenshot whenever an app is started
|
||||
* @param task the screenshot task
|
||||
* @param path the path to store the screenshots at
|
||||
* @param[in] path the path to store the screenshots at
|
||||
*/
|
||||
void startApps(const char* path);
|
||||
|
||||
/** @brief Stop taking screenshots
|
||||
* @param task the screenshot task
|
||||
*/
|
||||
/** @brief Stop taking screenshots */
|
||||
void stop();
|
||||
|
||||
void taskMain();
|
||||
|
||||
@ -13,11 +13,11 @@ void tt_message_queue_free(MessageQueueHandle handle) {
|
||||
delete HANDLE_TO_MESSAGE_QUEUE(handle);
|
||||
}
|
||||
|
||||
bool tt_message_queue_put(MessageQueueHandle handle, const void* message, uint32_t timeout) {
|
||||
bool tt_message_queue_put(MessageQueueHandle handle, const void* message, TickType_t timeout) {
|
||||
return HANDLE_TO_MESSAGE_QUEUE(handle)->put(message, timeout);
|
||||
}
|
||||
|
||||
bool tt_message_queue_get(MessageQueueHandle handle, void* message, uint32_t timeout) {
|
||||
bool tt_message_queue_get(MessageQueueHandle handle, void* message, TickType_t timeout) {
|
||||
return HANDLE_TO_MESSAGE_QUEUE(handle)->get(message, timeout);
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <freertos/FreeRTOS.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@ -11,8 +13,8 @@ typedef void* MessageQueueHandle;
|
||||
|
||||
MessageQueueHandle tt_message_queue_alloc(uint32_t capacity, uint32_t messageSize);
|
||||
void tt_message_queue_free(MessageQueueHandle handle);
|
||||
bool tt_message_queue_put(MessageQueueHandle handle, const void* message, uint32_t timeout);
|
||||
bool tt_message_queue_get(MessageQueueHandle handle, void* message, uint32_t timeout);
|
||||
bool tt_message_queue_put(MessageQueueHandle handle, const void* message, TickType_t timeout);
|
||||
bool tt_message_queue_get(MessageQueueHandle handle, void* message, TickType_t timeout);
|
||||
uint32_t tt_message_queue_get_capacity(MessageQueueHandle handle);
|
||||
uint32_t tt_message_queue_get_message_size(MessageQueueHandle handle);
|
||||
uint32_t tt_message_queue_get_count(MessageQueueHandle handle);
|
||||
|
||||
@ -20,8 +20,8 @@ void tt_mutex_free(MutexHandle handle) {
|
||||
delete HANDLE_AS_MUTEX(handle);
|
||||
}
|
||||
|
||||
bool tt_mutex_lock(MutexHandle handle, uint32_t timeoutTicks) {
|
||||
return HANDLE_AS_MUTEX(handle)->lock(timeoutTicks);
|
||||
bool tt_mutex_lock(MutexHandle handle, TickType_t timeout) {
|
||||
return HANDLE_AS_MUTEX(handle)->lock((TickType_t)timeout);
|
||||
}
|
||||
|
||||
bool tt_mutex_unlock(MutexHandle handle) {
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <freertos/FreeRTOS.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@ -16,7 +18,7 @@ enum TtMutexType {
|
||||
|
||||
MutexHandle tt_mutex_alloc(enum TtMutexType);
|
||||
void tt_mutex_free(MutexHandle handle);
|
||||
bool tt_mutex_lock(MutexHandle handle, uint32_t timeoutTicks);
|
||||
bool tt_mutex_lock(MutexHandle handle, TickType_t timeoutTicks);
|
||||
bool tt_mutex_unlock(MutexHandle handle);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@ -5,7 +5,7 @@ extern "C" {
|
||||
|
||||
#define HANDLE_AS_SEMAPHORE(handle) ((tt::Semaphore*)(handle))
|
||||
|
||||
SemaphoreHandle tt_semaphore_alloc(uint32_t maxCount, uint32_t initialCount) {
|
||||
SemaphoreHandle tt_semaphore_alloc(uint32_t maxCount, TickType_t initialCount) {
|
||||
return new tt::Semaphore(maxCount, initialCount);
|
||||
}
|
||||
|
||||
@ -13,7 +13,7 @@ void tt_semaphore_free(SemaphoreHandle handle) {
|
||||
delete HANDLE_AS_SEMAPHORE(handle);
|
||||
}
|
||||
|
||||
bool tt_semaphore_acquire(SemaphoreHandle handle, uint32_t timeoutTicks) {
|
||||
bool tt_semaphore_acquire(SemaphoreHandle handle, TickType_t timeoutTicks) {
|
||||
return HANDLE_AS_SEMAPHORE(handle)->acquire(timeoutTicks);
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <freertos/FreeRTOS.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@ -9,9 +11,9 @@ extern "C" {
|
||||
|
||||
typedef void* SemaphoreHandle;
|
||||
|
||||
SemaphoreHandle tt_semaphore_alloc(uint32_t maxCount, uint32_t initialCount);
|
||||
SemaphoreHandle tt_semaphore_alloc(uint32_t maxCount, TickType_t initialCount);
|
||||
void tt_semaphore_free(SemaphoreHandle handle);
|
||||
bool tt_semaphore_acquire(SemaphoreHandle handle, uint32_t timeoutTicks);
|
||||
bool tt_semaphore_acquire(SemaphoreHandle handle, TickType_t timeoutTicks);
|
||||
bool tt_semaphore_release(SemaphoreHandle handle);
|
||||
uint32_t tt_semaphore_get_count(SemaphoreHandle handle);
|
||||
|
||||
|
||||
@ -29,11 +29,11 @@ void tt_timer_free(TimerHandle handle) {
|
||||
delete wrapper;
|
||||
}
|
||||
|
||||
bool tt_timer_start(TimerHandle handle, uint32_t intervalTicks) {
|
||||
bool tt_timer_start(TimerHandle handle, TickType_t intervalTicks) {
|
||||
return ((TimerWrapper*)handle)->timer->start(intervalTicks);
|
||||
}
|
||||
|
||||
bool tt_timer_restart(TimerHandle handle, uint32_t intervalTicks) {
|
||||
bool tt_timer_restart(TimerHandle handle, TickType_t intervalTicks) {
|
||||
return ((TimerWrapper*)handle)->timer->restart(intervalTicks);
|
||||
}
|
||||
|
||||
@ -49,11 +49,12 @@ uint32_t tt_timer_get_expire_time(TimerHandle handle) {
|
||||
return ((TimerWrapper*)handle)->timer->getExpireTime();
|
||||
}
|
||||
|
||||
bool tt_timer_set_pending_callback(TimerHandle handle, TimerPendingCallback callback, void* callbackContext, uint32_t arg) {
|
||||
bool tt_timer_set_pending_callback(TimerHandle handle, TimerPendingCallback callback, void* callbackContext, uint32_t callbackArg, TickType_t timeoutTicks) {
|
||||
return ((TimerWrapper*)handle)->timer->setPendingCallback(
|
||||
callback,
|
||||
callbackContext,
|
||||
arg
|
||||
callbackArg,
|
||||
(TickType_t)timeoutTicks
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <freertos/FreeRTOS.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@ -24,12 +26,12 @@ typedef void (*TimerPendingCallback)(void* context, uint32_t arg);
|
||||
|
||||
TimerHandle tt_timer_alloc(TimerType type, TimerCallback callback, void* callbackContext);
|
||||
void tt_timer_free(TimerHandle handle);
|
||||
bool tt_timer_start(TimerHandle handle, uint32_t intervalTicks);
|
||||
bool tt_timer_restart(TimerHandle handle, uint32_t intervalTicks);
|
||||
bool tt_timer_start(TimerHandle handle, TickType_t intervalTicks);
|
||||
bool tt_timer_restart(TimerHandle handle, TickType_t intervalTicks);
|
||||
bool tt_timer_stop(TimerHandle handle);
|
||||
bool tt_timer_is_running(TimerHandle handle);
|
||||
uint32_t tt_timer_get_expire_time(TimerHandle handle);
|
||||
bool tt_timer_set_pending_callback(TimerHandle handle, TimerPendingCallback callback, void* callbackContext, uint32_t arg);
|
||||
bool tt_timer_set_pending_callback(TimerHandle handle, TimerPendingCallback callback, void* callbackContext, uint32_t callbackArg, TickType_t timeoutTicks);
|
||||
void tt_timer_set_thread_priority(TimerHandle handle, TimerThreadPriority priority);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@ -10,6 +10,9 @@
|
||||
|
||||
namespace tt {
|
||||
|
||||
/**
|
||||
* A dictionary that maps keys (strings) onto several atomary types.
|
||||
*/
|
||||
class Bundle {
|
||||
|
||||
private:
|
||||
|
||||
@ -40,9 +40,8 @@ namespace tt {
|
||||
tt::_crash(); \
|
||||
} while (0)
|
||||
|
||||
/** Halt system
|
||||
*
|
||||
* @param optional message (const char*)
|
||||
/** Halt the system
|
||||
* @param[in] optional message (const char*)
|
||||
*/
|
||||
#define tt_halt(...) M_APPLY(__tt_halt, M_IF_EMPTY(__VA_ARGS__)((NULL), (__VA_ARGS__)))
|
||||
|
||||
@ -61,8 +60,8 @@ namespace tt {
|
||||
|
||||
/** Check condition and crash if failed
|
||||
*
|
||||
* @param condition to check
|
||||
* @param optional message (const char*)
|
||||
* @param[in] condition to check
|
||||
* @param[in] optional message (const char*)
|
||||
*/
|
||||
|
||||
#define tt_check(x, ...) if (!(x)) { TT_LOG_E("check", "Failed: %s", #x); tt::_crash(); }
|
||||
@ -89,10 +88,7 @@ namespace tt {
|
||||
#endif
|
||||
|
||||
/** Assert condition and crash if failed
|
||||
*
|
||||
* @warning only will do check if firmware compiled in debug mode
|
||||
*
|
||||
* @param condition to check
|
||||
* @param optional message (const char*)
|
||||
* @warning only will do check if firmware compiled in debug mode
|
||||
* @param[in] condition to check
|
||||
*/
|
||||
#define tt_assert(expression) assert(expression)
|
||||
|
||||
@ -45,5 +45,3 @@
|
||||
#define _TT_ARGCOUNT4(X,...) _TT_ARGCOUNT ## __VA_OPT__(5(__VA_ARGS__) TT_ARG_IGNORE) (4)
|
||||
#define _TT_ARGCOUNT5(X,...) 5
|
||||
#define _TT_ARGCOUNT(X) X
|
||||
|
||||
// endregion
|
||||
@ -1,5 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
/** Find the largest value
|
||||
* @param[in] a first value to compare
|
||||
* @param[in] b second value to compare
|
||||
* @return the largest value of a and b
|
||||
*/
|
||||
#define TT_MAX(a, b) \
|
||||
({ \
|
||||
__typeof__(a) _a = (a); \
|
||||
@ -7,6 +12,11 @@
|
||||
_a > _b ? _a : _b; \
|
||||
})
|
||||
|
||||
/** Find the smallest value
|
||||
* @param[in] a first value to compare
|
||||
* @param[in] b second value to compare
|
||||
* @return the smallest value of a and b
|
||||
*/
|
||||
#define TT_MIN(a, b) \
|
||||
({ \
|
||||
__typeof__(a) _a = (a); \
|
||||
@ -14,49 +24,12 @@
|
||||
_a < _b ? _a : _b; \
|
||||
})
|
||||
|
||||
/** @return the absolute value of the input */
|
||||
#define TT_ABS(a) ({ (a) < 0 ? -(a) : (a); })
|
||||
|
||||
#define TT_ROUND_UP_TO(a, b) \
|
||||
({ \
|
||||
__typeof__(a) _a = (a); \
|
||||
__typeof__(b) _b = (b); \
|
||||
_a / _b + !!(_a % _b); \
|
||||
})
|
||||
|
||||
/** Clamp a value between a min and a max.
|
||||
* @param[in] x value to clamp
|
||||
* @param[in] upper upper bounds for x
|
||||
* @param[in] lower lower bounds for x
|
||||
*/
|
||||
#define TT_CLAMP(x, upper, lower) (TT_MIN(upper, TT_MAX(x, lower)))
|
||||
|
||||
#define TT_COUNT_OF(x) (sizeof(x) / sizeof(x[0]))
|
||||
|
||||
#define TT_SWAP(x, y) \
|
||||
do { \
|
||||
typeof(x) SWAP = x; \
|
||||
x = y; \
|
||||
y = SWAP; \
|
||||
} while (0)
|
||||
|
||||
#define TT_STRINGIFY(x) #x
|
||||
|
||||
#define TT_TOSTRING(x) TT_STRINGIFY(x)
|
||||
|
||||
#define TT_CONCATENATE(a, b) CONCATENATE_(a, b)
|
||||
#define TT_CONCATENATE_(a, b) a##b
|
||||
|
||||
#define TT_REVERSE_BYTES_U32(x) \
|
||||
((((x) & 0x000000FF) << 24) | (((x) & 0x0000FF00) << 8) | (((x) & 0x00FF0000) >> 8) | \
|
||||
(((x) & 0xFF000000) >> 24))
|
||||
|
||||
#define TT_BIT(x, n) (((x) >> (n)) & 1)
|
||||
|
||||
#define TT_BIT_SET(x, n) \
|
||||
({ \
|
||||
__typeof__(x) _x = (1); \
|
||||
(x) |= (_x << (n)); \
|
||||
})
|
||||
|
||||
#define TT_BIT_CLEAR(x, n) \
|
||||
({ \
|
||||
__typeof__(x) _x = (1); \
|
||||
(x) &= ~(_x << (n)); \
|
||||
})
|
||||
|
||||
#define TT_SW_MEMBARRIER() asm volatile("" : : : "memory")
|
||||
|
||||
@ -18,8 +18,8 @@ Dispatcher::~Dispatcher() {
|
||||
mutex.release();
|
||||
}
|
||||
|
||||
void Dispatcher::dispatch(Callback callback, std::shared_ptr<void> context) {
|
||||
auto message = std::make_shared<DispatcherMessage>(callback, std::move(context));
|
||||
void Dispatcher::dispatch(Function function, std::shared_ptr<void> context) {
|
||||
auto message = std::make_shared<DispatcherMessage>(function, std::move(context));
|
||||
// Mutate
|
||||
if (mutex.lock(1000 / portTICK_PERIOD_MS)) {
|
||||
queue.push(std::move(message));
|
||||
@ -34,16 +34,16 @@ void Dispatcher::dispatch(Callback callback, std::shared_ptr<void> context) {
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t Dispatcher::consume(uint32_t timeout_ticks) {
|
||||
uint32_t Dispatcher::consume(TickType_t timeout) {
|
||||
// Wait for signal and clear
|
||||
TickType_t start_ticks = kernel::getTicks();
|
||||
if (eventFlag.wait(WAIT_FLAG, TtFlagWaitAny, timeout_ticks) == WAIT_FLAG) {
|
||||
if (eventFlag.wait(WAIT_FLAG, TtFlagWaitAny, timeout) == WAIT_FLAG) {
|
||||
eventFlag.clear(WAIT_FLAG);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
TickType_t ticks_remaining = TT_MAX(timeout_ticks - (kernel::getTicks() - start_ticks), 0);
|
||||
TickType_t ticks_remaining = TT_MAX(timeout - (kernel::getTicks() - start_ticks), 0);
|
||||
|
||||
TT_LOG_I(TAG, "Dispatcher continuing (%d ticks)", (int)ticks_remaining);
|
||||
|
||||
@ -59,7 +59,7 @@ uint32_t Dispatcher::consume(uint32_t timeout_ticks) {
|
||||
processing = !queue.empty();
|
||||
// Don't keep lock as callback might be slow
|
||||
tt_check(mutex.unlock());
|
||||
item->callback(item->context);
|
||||
item->function(item->context);
|
||||
} else {
|
||||
processing = false;
|
||||
tt_check(mutex.unlock());
|
||||
|
||||
@ -13,16 +13,24 @@
|
||||
|
||||
namespace tt {
|
||||
|
||||
typedef void (*Callback)(std::shared_ptr<void> data);
|
||||
|
||||
/**
|
||||
* A thread-safe way to defer code execution.
|
||||
* Generally, one task would dispatch the execution,
|
||||
* while the other thread consumes and executes the work.
|
||||
*/
|
||||
class Dispatcher {
|
||||
public:
|
||||
|
||||
typedef void (*Function)(std::shared_ptr<void> data);
|
||||
|
||||
private:
|
||||
struct DispatcherMessage {
|
||||
Callback callback;
|
||||
Function function;
|
||||
std::shared_ptr<void> context; // Can't use unique_ptr with void, so we use shared_ptr
|
||||
|
||||
DispatcherMessage(Callback callback, std::shared_ptr<void> context) :
|
||||
callback(callback),
|
||||
DispatcherMessage(Function function, std::shared_ptr<void> context) :
|
||||
function(function),
|
||||
context(std::move(context))
|
||||
{}
|
||||
|
||||
@ -38,8 +46,19 @@ public:
|
||||
explicit Dispatcher();
|
||||
~Dispatcher();
|
||||
|
||||
void dispatch(Callback callback, std::shared_ptr<void> context);
|
||||
uint32_t consume(uint32_t timeout_ticks);
|
||||
/**
|
||||
* Queue a function to be consumed elsewhere.
|
||||
* @param[in] function the function to execute elsewhere
|
||||
* @param[in] context the data to pass onto the function
|
||||
*/
|
||||
void dispatch(Function function, std::shared_ptr<void> context);
|
||||
|
||||
/**
|
||||
* Consume a dispatched function (if any)
|
||||
* @param[in] timeout the ticks to wait for a message
|
||||
* @return the amount of messages that were consumed
|
||||
*/
|
||||
uint32_t consume(TickType_t timeout);
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
@ -29,8 +29,8 @@ void DispatcherThread::_threadMain() {
|
||||
} while (!interruptThread);
|
||||
}
|
||||
|
||||
void DispatcherThread::dispatch(Callback callback, std::shared_ptr<void> context) {
|
||||
dispatcher.dispatch(callback, std::move(context));
|
||||
void DispatcherThread::dispatch(Dispatcher::Function function, std::shared_ptr<void> context) {
|
||||
dispatcher.dispatch(function, std::move(context));
|
||||
}
|
||||
|
||||
void DispatcherThread::start() {
|
||||
|
||||
@ -19,7 +19,7 @@ public:
|
||||
/**
|
||||
* Dispatch a message.
|
||||
*/
|
||||
void dispatch(Callback callback, std::shared_ptr<void> context);
|
||||
void dispatch(Dispatcher::Function function, std::shared_ptr<void> context);
|
||||
|
||||
/** Start the thread (blocking). */
|
||||
void start();
|
||||
|
||||
@ -1,22 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include "Check.h"
|
||||
#include "RtosCompat.h"
|
||||
#include <memory>
|
||||
|
||||
namespace tt {
|
||||
|
||||
class ScopedLockableUsage;
|
||||
|
||||
/** Represents a lock/mutex */
|
||||
class Lockable {
|
||||
public:
|
||||
virtual ~Lockable() = default;
|
||||
|
||||
virtual bool lock(uint32_t timeoutTicks) const = 0;
|
||||
virtual bool lock(TickType_t timeoutTicks) const = 0;
|
||||
|
||||
virtual bool unlock() const = 0;
|
||||
|
||||
std::unique_ptr<ScopedLockableUsage> scoped() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents a lockable instance that is scoped to a specific lifecycle.
|
||||
* Once the ScopedLockableUsage is destroyed, unlock() is called automatically.
|
||||
*
|
||||
* In other words:
|
||||
* You have to lock() this object manually, but unlock() happens automatically on destruction.
|
||||
*/
|
||||
class ScopedLockableUsage final : public Lockable {
|
||||
|
||||
const Lockable& lockable;
|
||||
@ -29,7 +39,7 @@ public:
|
||||
lockable.unlock(); // We don't care whether it succeeded or not
|
||||
}
|
||||
|
||||
bool lock(uint32_t timeout) const override {
|
||||
bool lock(TickType_t timeout) const override {
|
||||
return lockable.lock(timeout);
|
||||
}
|
||||
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
|
||||
namespace tt {
|
||||
|
||||
/** Used for log output filtering */
|
||||
enum LogLevel {
|
||||
LogLevelNone, /*!< No log output */
|
||||
LogLevelError, /*!< Critical errors, software module can not recover on its own */
|
||||
@ -26,6 +27,10 @@ struct LogEntry {
|
||||
char message[TT_LOG_MESSAGE_SIZE] = { 0 };
|
||||
};
|
||||
|
||||
/** Make a copy of the currently stored entries.
|
||||
* The array size is TT_LOG_ENTRY_COUNT
|
||||
* @param[out] outIndex the write index for the next log entry.
|
||||
*/
|
||||
LogEntry* copyLogEntries(unsigned int& outIndex);
|
||||
|
||||
} // namespace tt
|
||||
|
||||
@ -5,13 +5,13 @@
|
||||
namespace tt {
|
||||
|
||||
MessageQueue::MessageQueue(uint32_t capacity, uint32_t msg_size) {
|
||||
tt_assert((kernel::isIrq() == 0U) && (capacity > 0U) && (msg_size > 0U));
|
||||
tt_assert(!TT_IS_ISR() && (capacity > 0U) && (msg_size > 0U));
|
||||
queue_handle = xQueueCreate(capacity, msg_size);
|
||||
tt_check(queue_handle);
|
||||
}
|
||||
|
||||
MessageQueue::~MessageQueue() {
|
||||
tt_assert(kernel::isIrq() == 0U);
|
||||
tt_assert(!TT_IS_ISR());
|
||||
vQueueDelete(queue_handle);
|
||||
}
|
||||
|
||||
@ -19,7 +19,7 @@ bool MessageQueue::put(const void* message, uint32_t timeout) {
|
||||
bool result = true;
|
||||
BaseType_t yield;
|
||||
|
||||
if (kernel::isIrq() != 0U) {
|
||||
if (TT_IS_ISR()) {
|
||||
if ((queue_handle == nullptr) || (message == nullptr) || (timeout != 0U)) {
|
||||
result = false;
|
||||
} else {
|
||||
@ -45,7 +45,7 @@ bool MessageQueue::get(void* msg_ptr, uint32_t timeout_ticks) {
|
||||
BaseType_t yield;
|
||||
|
||||
|
||||
if (kernel::isIrq()) {
|
||||
if (TT_IS_ISR()) {
|
||||
if ((queue_handle == nullptr) || (msg_ptr == nullptr) || (timeout_ticks != 0U)) {
|
||||
result = false;
|
||||
} else {
|
||||
@ -91,7 +91,7 @@ uint32_t MessageQueue::getCount() const {
|
||||
|
||||
if (queue_handle == nullptr) {
|
||||
count = 0U;
|
||||
} else if (kernel::isIrq() != 0U) {
|
||||
} else if (TT_IS_ISR()) {
|
||||
count = uxQueueMessagesWaitingFromISR(queue_handle);
|
||||
} else {
|
||||
count = uxQueueMessagesWaiting(queue_handle);
|
||||
@ -108,7 +108,7 @@ uint32_t MessageQueue::getSpace() const {
|
||||
|
||||
if (mq == nullptr) {
|
||||
space = 0U;
|
||||
} else if (kernel::isIrq() != 0U) {
|
||||
} else if (TT_IS_ISR()) {
|
||||
isrm = taskENTER_CRITICAL_FROM_ISR();
|
||||
|
||||
/* space = pxQueue->uxLength - pxQueue->uxMessagesWaiting; */
|
||||
@ -123,7 +123,7 @@ uint32_t MessageQueue::getSpace() const {
|
||||
}
|
||||
|
||||
bool MessageQueue::reset() {
|
||||
tt_check(!kernel::isIrq());
|
||||
tt_check(!TT_IS_ISR());
|
||||
if (queue_handle == nullptr) {
|
||||
return false;
|
||||
} else {
|
||||
|
||||
@ -36,7 +36,8 @@ public:
|
||||
|
||||
~MessageQueue();
|
||||
|
||||
/** Put message into queue
|
||||
/** Post a message to the queue.
|
||||
* The message is queued by copy, not by reference.
|
||||
* @param[in] message A pointer to a message. The message will be copied into a buffer.
|
||||
* @param[in] timeoutTicks
|
||||
* @return success result
|
||||
@ -44,7 +45,7 @@ public:
|
||||
bool put(const void* message, uint32_t timeoutTicks);
|
||||
|
||||
/** Get message from queue
|
||||
* @param message A pointer to an already allocated message object
|
||||
* @param[out] message A pointer to an already allocated message object
|
||||
* @param[in] timeoutTicks
|
||||
* @return success result
|
||||
*/
|
||||
|
||||
@ -44,7 +44,7 @@ Mutex::~Mutex() {
|
||||
semaphore = nullptr; // If the mutex is used after release, this might help debugging
|
||||
}
|
||||
|
||||
TtStatus Mutex::acquire(uint32_t timeout) const {
|
||||
TtStatus Mutex::acquire(TickType_t timeout) const {
|
||||
tt_assert(!TT_IS_IRQ_MODE());
|
||||
tt_assert(semaphore);
|
||||
|
||||
@ -114,7 +114,7 @@ void tt_mutex_free(Mutex* mutex) {
|
||||
delete mutex;
|
||||
}
|
||||
|
||||
TtStatus tt_mutex_acquire(Mutex* mutex, uint32_t timeout) {
|
||||
TtStatus tt_mutex_acquire(Mutex* mutex, TickType_t timeout) {
|
||||
return mutex-> acquire(timeout);
|
||||
}
|
||||
|
||||
|
||||
@ -13,8 +13,6 @@
|
||||
|
||||
namespace tt {
|
||||
|
||||
class ScopedMutexUsage;
|
||||
|
||||
/**
|
||||
* Wrapper for FreeRTOS xSemaphoreCreateMutex and xSemaphoreCreateRecursiveMutex
|
||||
* Can be used in IRQ mode (within ISR context)
|
||||
@ -38,56 +36,64 @@ public:
|
||||
explicit Mutex(Type type = TypeNormal);
|
||||
~Mutex() override;
|
||||
|
||||
TtStatus acquire(uint32_t timeoutTicks) const;
|
||||
/** Attempt to lock the mutex. Blocks until timeout passes or lock is acquired.
|
||||
* @param[in] timeout
|
||||
* @return status result
|
||||
*/
|
||||
TtStatus acquire(TickType_t timeout) const;
|
||||
|
||||
/** Attempt to unlock the mutex.
|
||||
* @return status result
|
||||
*/
|
||||
TtStatus release() const;
|
||||
|
||||
bool lock(uint32_t timeoutTicks) const override { return acquire(timeoutTicks) == TtStatusOk; }
|
||||
/** Attempt to lock the mutex. Blocks until timeout passes or lock is acquired.
|
||||
* @param[in] timeout
|
||||
* @return success result
|
||||
*/
|
||||
bool lock(TickType_t timeout) const override { return acquire(timeout) == TtStatusOk; }
|
||||
|
||||
/** Attempt to unlock the mutex.
|
||||
* @return success result
|
||||
*/
|
||||
bool unlock() const override { return release() == TtStatusOk; }
|
||||
|
||||
/** @return the owner of the thread */
|
||||
ThreadId getOwner() const;
|
||||
};
|
||||
|
||||
/** Allocate Mutex
|
||||
*
|
||||
* @param[in] type The mutex type
|
||||
*
|
||||
* @return pointer to Mutex instance
|
||||
* @param[in] type The mutex type
|
||||
* @return pointer to Mutex instance
|
||||
*/
|
||||
|
||||
[[deprecated("use class")]]
|
||||
Mutex* tt_mutex_alloc(Mutex::Type type);
|
||||
|
||||
/** Free Mutex
|
||||
*
|
||||
* @param mutex The Mutex instance
|
||||
* @param[in] mutex The Mutex instance
|
||||
*/
|
||||
[[deprecated("use class")]]
|
||||
void tt_mutex_free(Mutex* mutex);
|
||||
|
||||
/** Acquire mutex
|
||||
*
|
||||
* @param mutex The Mutex instance
|
||||
* @param[in] timeout The timeout
|
||||
*
|
||||
* @return The status.
|
||||
* @param[in] mutex
|
||||
* @param[in] timeout
|
||||
* @return the status result
|
||||
*/
|
||||
[[deprecated("use class")]]
|
||||
TtStatus tt_mutex_acquire(Mutex* mutex, uint32_t timeout);
|
||||
TtStatus tt_mutex_acquire(Mutex* mutex, TickType_t timeout);
|
||||
|
||||
/** Release mutex
|
||||
*
|
||||
* @param mutex The Mutex instance
|
||||
*
|
||||
* @return The status.
|
||||
* @param[in] mutex The Mutex instance
|
||||
* @return the status result
|
||||
*/
|
||||
[[deprecated("use class")]]
|
||||
TtStatus tt_mutex_release(Mutex* mutex);
|
||||
|
||||
/** Get mutex owner thread id
|
||||
*
|
||||
* @param mutex The Mutex instance
|
||||
*
|
||||
* @return The thread identifier.
|
||||
* @param[in] mutex The Mutex instance
|
||||
* @return The thread identifier.
|
||||
*/
|
||||
[[deprecated("use class")]]
|
||||
ThreadId tt_mutex_get_owner(Mutex* mutex);
|
||||
|
||||
@ -3,12 +3,12 @@
|
||||
|
||||
namespace tt {
|
||||
|
||||
PubSubSubscription* tt_pubsub_subscribe(std::shared_ptr<PubSub> pubsub, PubSubCallback callback, void* callback_context) {
|
||||
PubSubSubscription* tt_pubsub_subscribe(std::shared_ptr<PubSub> pubsub, PubSubCallback callback, void* callbackContext) {
|
||||
tt_check(pubsub->mutex.acquire(TtWaitForever) == TtStatusOk);
|
||||
PubSubSubscription subscription = {
|
||||
.id = (++pubsub->last_id),
|
||||
.callback = callback,
|
||||
.callback_context = callback_context
|
||||
.callback_context = callbackContext
|
||||
};
|
||||
pubsub->items.push_back(
|
||||
subscription
|
||||
|
||||
@ -30,34 +30,27 @@ struct PubSub {
|
||||
};
|
||||
|
||||
/** Subscribe to PubSub
|
||||
*
|
||||
* Threadsafe, Reentrable
|
||||
*
|
||||
* @param pubsub pointer to PubSub instance
|
||||
* @param[in] callback The callback
|
||||
* @param callback_context The callback context
|
||||
*
|
||||
* @return pointer to PubSubSubscription instance
|
||||
* @param[in] pubsub pointer to PubSub instance
|
||||
* @param[in] callback
|
||||
* @param[in] callbackContext the data to pass to the callback
|
||||
* @return subscription instance
|
||||
*/
|
||||
PubSubSubscription*
|
||||
tt_pubsub_subscribe(std::shared_ptr<PubSub> pubsub, PubSubCallback callback, void* callback_context);
|
||||
tt_pubsub_subscribe(std::shared_ptr<PubSub> pubsub, PubSubCallback callback, void* callbackContext);
|
||||
|
||||
/** Unsubscribe from PubSub
|
||||
*
|
||||
* No use of `pubsub_subscription` allowed after call of this method
|
||||
* Threadsafe, Reentrable.
|
||||
*
|
||||
* @param pubsub pointer to PubSub instance
|
||||
* @param pubsub_subscription pointer to PubSubSubscription instance
|
||||
* No use of `tt_pubsub_subscription` allowed after call of this method
|
||||
* Threadsafe, Re-entrable.
|
||||
* @param[in] pubsub
|
||||
* @param[in] subscription
|
||||
*/
|
||||
void tt_pubsub_unsubscribe(std::shared_ptr<PubSub> pubsub, PubSubSubscription* pubsub_subscription);
|
||||
void tt_pubsub_unsubscribe(std::shared_ptr<PubSub> pubsub, PubSubSubscription* subscription);
|
||||
|
||||
/** Publish message to PubSub
|
||||
*
|
||||
* Threadsafe, Reentrable.
|
||||
*
|
||||
* @param pubsub pointer to PubSub instance
|
||||
* @param message message pointer to publish
|
||||
* @param[in] pubsub
|
||||
* @param[in] message message pointer to publish - it is passed as-is to the callback
|
||||
*/
|
||||
void tt_pubsub_publish(std::shared_ptr<PubSub> pubsub, void* message);
|
||||
|
||||
|
||||
@ -35,8 +35,8 @@ public:
|
||||
* interrupt that will write to the buffer (the writer), and only one task or
|
||||
* interrupt that will read from the buffer (the reader).
|
||||
*
|
||||
* @param size The total number of bytes the stream buffer will be able to hold at any one time.
|
||||
* @param triggerLevel The number of bytes that must be in the stream buffer
|
||||
* @param[in] size The total number of bytes the stream buffer will be able to hold at any one time.
|
||||
* @param[in] triggerLevel The number of bytes that must be in the stream buffer
|
||||
* before a task that is blocked on the stream buffer to wait for data is moved out of the blocked state.
|
||||
* @return The stream buffer instance.
|
||||
*/
|
||||
@ -50,7 +50,7 @@ public:
|
||||
* stream buffer before a task that is blocked on the stream buffer to
|
||||
* wait for data is moved out of the blocked state.
|
||||
*
|
||||
* @param triggerLevel The new trigger level for the stream buffer.
|
||||
* @param[in] triggerLevel The new trigger level for the stream buffer.
|
||||
* @return true if trigger level can be be updated (new trigger level was less than or equal to the stream buffer's length).
|
||||
* @return false if trigger level can't be be updated (new trigger level was greater than the stream buffer's length).
|
||||
*/
|
||||
@ -60,9 +60,9 @@ public:
|
||||
* @brief Sends bytes to a stream buffer. The bytes are copied into the stream buffer.
|
||||
* Wakes up task waiting for data to become available if called from ISR.
|
||||
*
|
||||
* @param data A pointer to the data that is to be copied into the stream buffer.
|
||||
* @param length The maximum number of bytes to copy from data into the stream buffer.
|
||||
* @param timeout The maximum amount of time the task should remain in the
|
||||
* @param[in] data A pointer to the data that is to be copied into the stream buffer.
|
||||
* @param[in] length The maximum number of bytes to copy from data into the stream buffer.
|
||||
* @param[in] timeout The maximum amount of time the task should remain in the
|
||||
* Blocked state to wait for space to become available if the stream buffer is full.
|
||||
* Will return immediately if timeout is zero.
|
||||
* Setting timeout to TtWaitForever will cause the task to wait indefinitely.
|
||||
@ -79,10 +79,10 @@ public:
|
||||
* @brief Receives bytes from a stream buffer.
|
||||
* Wakes up task waiting for space to become available if called from ISR.
|
||||
*
|
||||
* @param data A pointer to the buffer into which the received bytes will be
|
||||
* @param[in] data A pointer to the buffer into which the received bytes will be
|
||||
* copied.
|
||||
* @param length The length of the buffer pointed to by the data parameter.
|
||||
* @param timeout The maximum amount of time the task should remain in the
|
||||
* @param[in] length The length of the buffer pointed to by the data parameter.
|
||||
* @param[in] timeout The maximum amount of time the task should remain in the
|
||||
* Blocked state to wait for data to become available if the stream buffer is empty.
|
||||
* Will return immediately if timeout is zero.
|
||||
* Setting timeout to TtWaitForever will cause the task to wait indefinitely.
|
||||
|
||||
@ -7,13 +7,7 @@
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#else
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#endif
|
||||
#include "RtosCompatTask.h"
|
||||
|
||||
namespace tt {
|
||||
|
||||
@ -47,14 +41,14 @@ public:
|
||||
typedef int32_t (*Callback)(void* context);
|
||||
|
||||
/** Write to stdout callback
|
||||
* @param data pointer to data
|
||||
* @param size data size @warning your handler must consume everything
|
||||
* @param[in] data pointer to data
|
||||
* @param[in] size data size @warning your handler must consume everything
|
||||
*/
|
||||
typedef void (*StdoutWriteCallback)(const char* data, size_t size);
|
||||
|
||||
/** Thread state change callback called upon thread state change
|
||||
* @param state new thread state
|
||||
* @param context callback context
|
||||
* @param[in] state new thread state
|
||||
* @param[in] context callback context
|
||||
*/
|
||||
typedef void (*StateCallback)(State state, void* context);
|
||||
|
||||
@ -85,11 +79,10 @@ public:
|
||||
Thread();
|
||||
|
||||
/** Allocate Thread, shortcut version
|
||||
|
||||
* @param name
|
||||
* @param stack_size
|
||||
* @param callback
|
||||
* @param context
|
||||
* @param[in] name
|
||||
* @param[in] stack_size
|
||||
* @param[in] callback
|
||||
* @param[in] callbackContext
|
||||
* @return Thread*
|
||||
*/
|
||||
Thread(
|
||||
@ -102,8 +95,7 @@ public:
|
||||
~Thread();
|
||||
|
||||
/** Set Thread name
|
||||
*
|
||||
* @param name string
|
||||
* @param[in] name string
|
||||
*/
|
||||
void setName(const std::string& name);
|
||||
|
||||
@ -118,75 +110,49 @@ public:
|
||||
bool isMarkedAsStatic() const;
|
||||
|
||||
/** Set Thread stack size
|
||||
*
|
||||
* @param thread Thread instance
|
||||
* @param stackSize stack size in bytes
|
||||
* @param[in] stackSize stack size in bytes
|
||||
*/
|
||||
void setStackSize(size_t stackSize);
|
||||
|
||||
/** Set Thread callback
|
||||
*
|
||||
* @param thread Thread instance
|
||||
* @param callback ThreadCallback, called upon thread run
|
||||
* @param callbackContext what to pass to the callback
|
||||
* @param[in] callback ThreadCallback, called upon thread run
|
||||
* @param[in] callbackContext what to pass to the callback
|
||||
*/
|
||||
void setCallback(Callback callback, _Nullable void* callbackContext = nullptr);
|
||||
|
||||
/** Set Thread priority
|
||||
*
|
||||
* @param thread Thread instance
|
||||
* @param priority ThreadPriority value
|
||||
* @param[in] priority ThreadPriority value
|
||||
*/
|
||||
void setPriority(Priority priority);
|
||||
|
||||
|
||||
/** Set Thread state change callback
|
||||
*
|
||||
* @param thread Thread instance
|
||||
* @param callback state change callback
|
||||
* @param context pointer to context
|
||||
* @param[in] callback state change callback
|
||||
* @param[in] callbackContext pointer to context
|
||||
*/
|
||||
void setStateCallback(StateCallback callback, _Nullable void* callbackContext = nullptr);
|
||||
|
||||
/** Get Thread state
|
||||
*
|
||||
* @param thread Thread instance
|
||||
*
|
||||
* @return thread state from ThreadState
|
||||
*/
|
||||
State getState() const;
|
||||
|
||||
/** Start Thread
|
||||
*
|
||||
* @param thread Thread instance
|
||||
*/
|
||||
void start();
|
||||
|
||||
/** Join Thread
|
||||
*
|
||||
* @warning Use this method only when CPU is not busy(Idle task receives
|
||||
* control), otherwise it will wait forever.
|
||||
*
|
||||
* @param thread Thread instance
|
||||
*
|
||||
* @warning Use this method only when CPU is not busy (Idle task receives control), otherwise it will wait forever.
|
||||
* @return success result
|
||||
*/
|
||||
bool join();
|
||||
|
||||
/** Get FreeRTOS ThreadId for Thread instance
|
||||
*
|
||||
* @param thread Thread instance
|
||||
*
|
||||
* @return ThreadId or nullptr
|
||||
*/
|
||||
ThreadId getId();
|
||||
|
||||
/** Get thread return code
|
||||
*
|
||||
* @param thread Thread instance
|
||||
*
|
||||
* @return return code
|
||||
*/
|
||||
/** @return thread return code */
|
||||
int32_t getReturnCode();
|
||||
|
||||
private:
|
||||
@ -200,31 +166,17 @@ private:
|
||||
#define THREAD_PRIORITY_ISR (TT_CONFIG_THREAD_MAX_PRIORITIES - 1)
|
||||
|
||||
/** Set current thread priority
|
||||
*
|
||||
* @param priority ThreadPriority value
|
||||
* @param[in] priority ThreadPriority value
|
||||
*/
|
||||
void thread_set_current_priority(Thread::Priority priority);
|
||||
|
||||
/** Get current thread priority
|
||||
*
|
||||
* @return ThreadPriority value
|
||||
*/
|
||||
/** @return ThreadPriority value */
|
||||
Thread::Priority thread_get_current_priority();
|
||||
|
||||
/** Thread related methods that doesn't involve Thread directly */
|
||||
|
||||
/** Get FreeRTOS ThreadId for current thread
|
||||
*
|
||||
* @param thread Thread instance
|
||||
*
|
||||
* @return ThreadId or NULL
|
||||
*/
|
||||
/** @return FreeRTOS ThreadId or NULL */
|
||||
ThreadId thread_get_current_id();
|
||||
|
||||
/** Get Thread instance for current thread
|
||||
*
|
||||
* @return pointer to Thread or NULL if this thread doesn't belongs to Tactility
|
||||
*/
|
||||
/** @return pointer to Thread instance or NULL if this thread doesn't belongs to Tactility */
|
||||
Thread* thread_get_current();
|
||||
|
||||
/** Return control to scheduler */
|
||||
@ -240,44 +192,38 @@ uint32_t thread_flags_wait(uint32_t flags, uint32_t options, uint32_t timeout);
|
||||
|
||||
/**
|
||||
* @brief Get thread name
|
||||
*
|
||||
* @param thread_id
|
||||
* @param[in] threadId
|
||||
* @return const char* name or NULL
|
||||
*/
|
||||
const char* thread_get_name(ThreadId thread_id);
|
||||
const char* thread_get_name(ThreadId threadId);
|
||||
|
||||
/**
|
||||
* @brief Get thread stack watermark
|
||||
*
|
||||
* @param thread_id
|
||||
* @param[in] threadId
|
||||
* @return uint32_t
|
||||
*/
|
||||
uint32_t thread_get_stack_space(ThreadId thread_id);
|
||||
uint32_t thread_get_stack_space(ThreadId threadId);
|
||||
|
||||
/** Suspend thread
|
||||
*
|
||||
* @param thread_id thread id
|
||||
* @param[in] threadId thread id
|
||||
*/
|
||||
void thread_suspend(ThreadId thread_id);
|
||||
void thread_suspend(ThreadId threadId);
|
||||
|
||||
/** Resume thread
|
||||
*
|
||||
* @param thread_id thread id
|
||||
* @param[in] threadId thread id
|
||||
*/
|
||||
void thread_resume(ThreadId thread_id);
|
||||
void thread_resume(ThreadId threadId);
|
||||
|
||||
/** Get thread suspended state
|
||||
*
|
||||
* @param thread_id thread id
|
||||
* @param[in] threadId thread id
|
||||
* @return true if thread is suspended
|
||||
*/
|
||||
bool thread_is_suspended(ThreadId thread_id);
|
||||
bool thread_is_suspended(ThreadId threadId);
|
||||
|
||||
/** Check if the thread was created with static memory
|
||||
*
|
||||
* @param thread_id thread id
|
||||
* @param[in] threadId thread id
|
||||
* @return true if thread memory is static
|
||||
*/
|
||||
bool thread_mark_is_static(ThreadId thread_id);
|
||||
bool thread_mark_is_static(ThreadId threadId);
|
||||
|
||||
} // namespace
|
||||
|
||||
@ -16,7 +16,7 @@ static void timer_callback(TimerHandle_t hTimer) {
|
||||
}
|
||||
|
||||
Timer::Timer(Type type, Callback callback, std::shared_ptr<void> callbackContext) {
|
||||
tt_assert((kernel::isIrq() == 0U) && (callback != nullptr));
|
||||
tt_assert((!TT_IS_ISR()) && (callback != nullptr));
|
||||
|
||||
this->callback = callback;
|
||||
this->callbackContext = std::move(callbackContext);
|
||||
@ -33,48 +33,49 @@ Timer::Timer(Type type, Callback callback, std::shared_ptr<void> callbackContext
|
||||
}
|
||||
|
||||
Timer::~Timer() {
|
||||
tt_assert(!kernel::isIrq());
|
||||
tt_assert(!TT_IS_ISR());
|
||||
tt_check(xTimerDelete(timerHandle, portMAX_DELAY) == pdPASS);
|
||||
}
|
||||
|
||||
bool Timer::start(uint32_t intervalTicks) {
|
||||
tt_assert(!kernel::isIrq());
|
||||
tt_assert(!TT_IS_ISR());
|
||||
tt_assert(intervalTicks < portMAX_DELAY);
|
||||
return xTimerChangePeriod(timerHandle, intervalTicks, portMAX_DELAY) == pdPASS;
|
||||
}
|
||||
|
||||
bool Timer::restart(uint32_t intervalTicks) {
|
||||
tt_assert(!kernel::isIrq());
|
||||
tt_assert(!TT_IS_ISR());
|
||||
tt_assert(intervalTicks < portMAX_DELAY);
|
||||
return xTimerChangePeriod(timerHandle, intervalTicks, portMAX_DELAY) == pdPASS &&
|
||||
xTimerReset(timerHandle, portMAX_DELAY) == pdPASS;
|
||||
}
|
||||
|
||||
bool Timer::stop() {
|
||||
tt_assert(!kernel::isIrq());
|
||||
tt_assert(!TT_IS_ISR());
|
||||
return xTimerStop(timerHandle, portMAX_DELAY) == pdPASS;
|
||||
}
|
||||
|
||||
bool Timer::isRunning() {
|
||||
tt_assert(!kernel::isIrq());
|
||||
tt_assert(!TT_IS_ISR());
|
||||
return xTimerIsTimerActive(timerHandle) == pdTRUE;
|
||||
}
|
||||
|
||||
uint32_t Timer::getExpireTime() {
|
||||
tt_assert(!kernel::isIrq());
|
||||
tt_assert(!TT_IS_ISR());
|
||||
return (uint32_t)xTimerGetExpiryTime(timerHandle);
|
||||
}
|
||||
|
||||
bool Timer::setPendingCallback(PendingCallback callback, void* callbackContext, uint32_t arg) {
|
||||
if (kernel::isIrq()) {
|
||||
return xTimerPendFunctionCallFromISR(callback, callbackContext, arg, nullptr) == pdPASS;
|
||||
bool Timer::setPendingCallback(PendingCallback callback, void* callbackContext, uint32_t callbackArg, TickType_t timeout) {
|
||||
if (TT_IS_ISR()) {
|
||||
assert(timeout == 0);
|
||||
return xTimerPendFunctionCallFromISR(callback, callbackContext, callbackArg, nullptr) == pdPASS;
|
||||
} else {
|
||||
return xTimerPendFunctionCall(callback, callbackContext, arg, TtWaitForever) == pdPASS;
|
||||
return xTimerPendFunctionCall(callback, callbackContext, callbackArg, timeout) == pdPASS;
|
||||
}
|
||||
}
|
||||
|
||||
void Timer::setThreadPriority(ThreadPriority priority) {
|
||||
tt_assert(!kernel::isIrq());
|
||||
tt_assert(!TT_IS_ISR());
|
||||
|
||||
TaskHandle_t task_handle = xTimerGetTimerDaemonTaskHandle();
|
||||
tt_assert(task_handle); // Don't call this method before timer task start
|
||||
|
||||
@ -33,55 +33,44 @@ public:
|
||||
~Timer();
|
||||
|
||||
/** Start timer
|
||||
*
|
||||
* @warning This is asynchronous call, real operation will happen as soon as
|
||||
* timer service process this request.
|
||||
*
|
||||
* @warning This is asynchronous call, real operation will happen as soon as timer service process this request.
|
||||
* @param[in] ticks The interval in ticks
|
||||
* @return success result
|
||||
*/
|
||||
bool start(uint32_t intervalTicks);
|
||||
|
||||
/** Restart timer with previous timeout value
|
||||
*
|
||||
* @warning This is asynchronous call, real operation will happen as soon as
|
||||
* timer service process this request.
|
||||
*
|
||||
* @warning This is asynchronous call, real operation will happen as soon as timer service process this request.
|
||||
* @param[in] ticks The interval in ticks
|
||||
*
|
||||
* @return success result
|
||||
*/
|
||||
bool restart(uint32_t intervalTicks);
|
||||
|
||||
|
||||
/** Stop timer
|
||||
*
|
||||
* @warning This is asynchronous call, real operation will happen as soon as
|
||||
* timer service process this request.
|
||||
*
|
||||
* @warning This is asynchronous call, real operation will happen as soon as timer service process this request.
|
||||
* @return success result
|
||||
*/
|
||||
bool stop();
|
||||
|
||||
/** Is timer running
|
||||
*
|
||||
* @warning This cal may and will return obsolete timer state if timer
|
||||
* commands are still in the queue. Please read FreeRTOS timer
|
||||
* documentation first.
|
||||
*
|
||||
* @warning This cal may and will return obsolete timer state if timer commands are still in the queue. Please read FreeRTOS timer documentation first.
|
||||
* @return true when running
|
||||
*/
|
||||
bool isRunning();
|
||||
|
||||
/** Get timer expire time
|
||||
*
|
||||
* @param instance The Timer instance
|
||||
*
|
||||
* @return expire tick
|
||||
*/
|
||||
uint32_t getExpireTime();
|
||||
|
||||
bool setPendingCallback(PendingCallback callback, void* callbackContext, uint32_t arg);
|
||||
/**
|
||||
* Calls xTimerPendFunctionCall internally.
|
||||
* @param[in] callback the function to call
|
||||
* @param[in] callbackContext the first function argument
|
||||
* @param[in] callbackArg the second function argument
|
||||
* @param[in] timeout the function timeout (must set to 0 in ISR mode)
|
||||
*/
|
||||
bool setPendingCallback(PendingCallback callback, void* callbackContext, uint32_t callbackArg, TickType_t timeout);
|
||||
|
||||
typedef enum {
|
||||
TimerThreadPriorityNormal, /**< Lower then other threads */
|
||||
@ -89,7 +78,6 @@ public:
|
||||
} ThreadPriority;
|
||||
|
||||
/** Set Timer thread priority
|
||||
*
|
||||
* @param[in] priority The priority
|
||||
*/
|
||||
void setThreadPriority(ThreadPriority priority);
|
||||
|
||||
@ -91,14 +91,14 @@ static void get_nvs_key(uint8_t key[32]) {
|
||||
|
||||
/**
|
||||
* Performs XOR on 2 memory regions and stores it in a third
|
||||
* @param[in] in_left input buffer for XOR
|
||||
* @param[in] in_right second input buffer for XOR
|
||||
* @param[in] inLeft input buffer for XOR
|
||||
* @param[in] inRight second input buffer for XOR
|
||||
* @param[out] out output buffer for result of XOR
|
||||
* @param[in] length data length (all buffers must be at least this size)
|
||||
*/
|
||||
static void xorKey(const uint8_t* in_left, const uint8_t* in_right, uint8_t* out, size_t length) {
|
||||
static void xorKey(const uint8_t* inLeft, const uint8_t* inRight, uint8_t* out, size_t length) {
|
||||
for (int i = 0; i < length; ++i) {
|
||||
out[i] = in_left[i] ^ in_right[i];
|
||||
out[i] = inLeft[i] ^ inRight[i];
|
||||
}
|
||||
}
|
||||
|
||||
@ -112,10 +112,10 @@ static void getKey(uint8_t key[32]) {
|
||||
TT_LOG_W(TAG, "An attacker with physical access to your ESP32 can decrypt your secure data.");
|
||||
#endif
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
uint8_t hardware_key[32];
|
||||
uint8_t nvs_key[32];
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
get_hardware_key(hardware_key);
|
||||
get_nvs_key(nvs_key);
|
||||
xorKey(hardware_key, nvs_key, key, 32);
|
||||
@ -125,10 +125,10 @@ static void getKey(uint8_t key[32]) {
|
||||
#endif
|
||||
}
|
||||
|
||||
void getIv(const void* data, size_t data_length, uint8_t iv[16]) {
|
||||
void getIv(const void* data, size_t dataLength, uint8_t iv[16]) {
|
||||
memset((void*)iv, 0, 16);
|
||||
uint8_t* data_bytes = (uint8_t*)data;
|
||||
for (int i = 0; i < data_length; ++i) {
|
||||
auto* data_bytes = (uint8_t*)data;
|
||||
for (int i = 0; i < dataLength; ++i) {
|
||||
size_t safe_index = i % 16;
|
||||
iv[safe_index] %= data_bytes[i];
|
||||
}
|
||||
@ -160,8 +160,8 @@ static int aes256CryptCbc(
|
||||
return result;
|
||||
}
|
||||
|
||||
int encrypt(const uint8_t iv[16], uint8_t* in_data, uint8_t* out_data, size_t length) {
|
||||
tt_check(length % 16 == 0, "Length is not a multiple of 16 bytes (for AES 256");
|
||||
int encrypt(const uint8_t iv[16], uint8_t* inData, uint8_t* outData, size_t dataLength) {
|
||||
tt_check(dataLength % 16 == 0, "Length is not a multiple of 16 bytes (for AES 256");
|
||||
uint8_t key[32];
|
||||
getKey(key);
|
||||
|
||||
@ -169,11 +169,11 @@ int encrypt(const uint8_t iv[16], uint8_t* in_data, uint8_t* out_data, size_t le
|
||||
uint8_t iv_copy[16];
|
||||
memcpy(iv_copy, iv, sizeof(iv_copy));
|
||||
|
||||
return aes256CryptCbc(key, MBEDTLS_AES_ENCRYPT, length, iv_copy, in_data, out_data);
|
||||
return aes256CryptCbc(key, MBEDTLS_AES_ENCRYPT, dataLength, iv_copy, inData, outData);
|
||||
}
|
||||
|
||||
int decrypt(const uint8_t iv[16], uint8_t* in_data, uint8_t* out_data, size_t length) {
|
||||
tt_check(length % 16 == 0, "Length is not a multiple of 16 bytes (for AES 256");
|
||||
int decrypt(const uint8_t iv[16], uint8_t* inData, uint8_t* outData, size_t dataLength) {
|
||||
tt_check(dataLength % 16 == 0, "Length is not a multiple of 16 bytes (for AES 256");
|
||||
uint8_t key[32];
|
||||
getKey(key);
|
||||
|
||||
@ -181,7 +181,7 @@ int decrypt(const uint8_t iv[16], uint8_t* in_data, uint8_t* out_data, size_t le
|
||||
uint8_t iv_copy[16];
|
||||
memcpy(iv_copy, iv, sizeof(iv_copy));
|
||||
|
||||
return aes256CryptCbc(key, MBEDTLS_AES_DECRYPT, length, iv_copy, in_data, out_data);
|
||||
return aes256CryptCbc(key, MBEDTLS_AES_DECRYPT, dataLength, iv_copy, inData, outData);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@ -26,11 +26,11 @@ namespace tt::crypt {
|
||||
|
||||
/**
|
||||
* @brief Fills the IV with zeros and then creates an IV based on the input data.
|
||||
* @param data input data
|
||||
* @param data_length input data length
|
||||
* @param iv output IV
|
||||
* @param[in] data input data
|
||||
* @param[in] dataLength input data length
|
||||
* @param[out] iv output IV
|
||||
*/
|
||||
void getIv(const void* data, size_t data_length, uint8_t iv[16]);
|
||||
void getIv(const void* data, size_t dataLength, uint8_t iv[16]);
|
||||
|
||||
/**
|
||||
* @brief Encrypt data.
|
||||
@ -38,13 +38,13 @@ void getIv(const void* data, size_t data_length, uint8_t iv[16]);
|
||||
* Important: Use flash encryption to increase security.
|
||||
* Important: input and output data must be aligned to 16 bytes.
|
||||
*
|
||||
* @param iv the AES IV
|
||||
* @param data_in input data
|
||||
* @param data_out output data
|
||||
* @param length data length, a multiple of 16
|
||||
* @param[in] iv the AES IV
|
||||
* @param[in] inData input data
|
||||
* @param[out] outData output data
|
||||
* @param[in] dataLength data length, a multiple of 16 (for both inData and outData)
|
||||
* @return the result of esp_aes_crypt_cbc() (MBEDTLS_ERR_*)
|
||||
*/
|
||||
int encrypt(const uint8_t iv[16], uint8_t* in_data, uint8_t* out_data, size_t length);
|
||||
int encrypt(const uint8_t iv[16], uint8_t* inData, uint8_t* outData, size_t dataLength);
|
||||
|
||||
/**
|
||||
* @brief Decrypt data.
|
||||
@ -52,12 +52,12 @@ int encrypt(const uint8_t iv[16], uint8_t* in_data, uint8_t* out_data, size_t le
|
||||
* Important: Use flash encryption to increase security.
|
||||
* Important: input and output data must be aligned to 16 bytes.
|
||||
*
|
||||
* @param iv AES IV
|
||||
* @param data_in input data
|
||||
* @param data_out output data
|
||||
* @param length data length, a multiple of 16
|
||||
* @param[in] iv AES IV
|
||||
* @param[in] inData input data
|
||||
* @param[out] outData output data
|
||||
* @param[in] dataLength data length, a multiple of 16 (for both inData and outData)
|
||||
* @return the result of esp_aes_crypt_cbc() (MBEDTLS_ERR_*)
|
||||
*/
|
||||
int decrypt(const uint8_t iv[16], uint8_t* in_data, uint8_t* out_data, size_t length);
|
||||
int decrypt(const uint8_t iv[16], uint8_t* inData, uint8_t* outData, size_t dataLength);
|
||||
|
||||
} // namespace
|
||||
|
||||
@ -15,6 +15,7 @@ uint32_t djb2(const char* str);
|
||||
/**
|
||||
* Implementation of DJB2 hashing algorithm.
|
||||
* @param[in] data the bytes to calculate the hash for
|
||||
* @param[in] length the size of data
|
||||
* @return the hash
|
||||
*/
|
||||
uint32_t djb2(const void* data, size_t length);
|
||||
|
||||
@ -26,6 +26,11 @@ long getSize(FILE* file) {
|
||||
return file_size;
|
||||
}
|
||||
|
||||
/** Read a file.
|
||||
* @param[in] filepath
|
||||
* @param[out] outSize the amount of bytes that were read, excluding the sizePadding
|
||||
* @param[in] sizePadding optional padding to add at the end of the output data (the values are not set)
|
||||
*/
|
||||
static std::unique_ptr<uint8_t[]> readBinaryInternal(const std::string& filepath, size_t& outSize, size_t sizePadding = 0) {
|
||||
FILE* file = fopen(filepath.c_str(), "rb");
|
||||
|
||||
@ -53,15 +58,19 @@ static std::unique_ptr<uint8_t[]> readBinaryInternal(const std::string& filepath
|
||||
if (bytes_read > 0) {
|
||||
buffer_offset += bytes_read;
|
||||
} else { // Something went wrong?
|
||||
data = nullptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
outSize = buffer_offset;
|
||||
|
||||
fclose(file);
|
||||
return data;
|
||||
|
||||
if (buffer_offset == content_length) {
|
||||
outSize = buffer_offset;
|
||||
return data;
|
||||
} else {
|
||||
outSize = 0;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<uint8_t[]> readBinary(const std::string& filepath, size_t& outSize) {
|
||||
@ -71,15 +80,11 @@ std::unique_ptr<uint8_t[]> readBinary(const std::string& filepath, size_t& outSi
|
||||
std::unique_ptr<uint8_t[]> readString(const std::string& filepath) {
|
||||
size_t size = 0;
|
||||
auto data = readBinaryInternal(filepath, size, 1);
|
||||
if (data == nullptr) {
|
||||
return nullptr;
|
||||
} else if (size > 0) {
|
||||
if (data != nullptr) {
|
||||
data.get()[size] = 0; // Append null terminator
|
||||
return data;
|
||||
} else { // Empty file: return empty string
|
||||
auto value = std::make_unique<uint8_t[]>(1);
|
||||
value[0] = 0;
|
||||
return value;
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -7,7 +7,17 @@ namespace tt::file {
|
||||
|
||||
long getSize(FILE* file);
|
||||
|
||||
/** Read a file and return its data.
|
||||
* @param[in] filepath the path of the file
|
||||
* @param[out] size the amount of bytes that were read
|
||||
* @return null on error, or an array of bytes in case of success
|
||||
*/
|
||||
std::unique_ptr<uint8_t[]> readBinary(const std::string& filepath, size_t& outSize);
|
||||
|
||||
/** Read a file and return a null-terminated string that represents its content.
|
||||
* @param[in] filepath the path of the file
|
||||
* @return null on error, or an array of bytes in case of success. Empty string returns as a single 0 character.
|
||||
*/
|
||||
std::unique_ptr<uint8_t[]> readString(const std::string& filepath);
|
||||
|
||||
}
|
||||
|
||||
@ -12,16 +12,12 @@
|
||||
|
||||
namespace tt::kernel {
|
||||
|
||||
bool isIrq() {
|
||||
return TT_IS_IRQ_MODE();
|
||||
}
|
||||
|
||||
bool isRunning() {
|
||||
return xTaskGetSchedulerState() != taskSCHEDULER_RUNNING;
|
||||
}
|
||||
|
||||
int32_t lock() {
|
||||
tt_assert(!isIrq());
|
||||
tt_assert(!TT_IS_ISR());
|
||||
|
||||
int32_t lock;
|
||||
|
||||
@ -46,7 +42,7 @@ int32_t lock() {
|
||||
}
|
||||
|
||||
int32_t unlock() {
|
||||
tt_assert(!isIrq());
|
||||
tt_assert(!TT_IS_ISR());
|
||||
|
||||
int32_t lock;
|
||||
|
||||
@ -76,7 +72,7 @@ int32_t unlock() {
|
||||
}
|
||||
|
||||
int32_t restoreLock(int32_t lock) {
|
||||
tt_assert(!isIrq());
|
||||
tt_assert(!TT_IS_ISR());
|
||||
|
||||
switch (xTaskGetSchedulerState()) {
|
||||
case taskSCHEDULER_SUSPENDED:
|
||||
@ -112,7 +108,7 @@ uint32_t getTickFrequency() {
|
||||
}
|
||||
|
||||
void delayTicks(TickType_t ticks) {
|
||||
tt_assert(!isIrq());
|
||||
tt_assert(!TT_IS_ISR());
|
||||
if (ticks == 0U) {
|
||||
taskYIELD();
|
||||
} else {
|
||||
@ -121,7 +117,7 @@ void delayTicks(TickType_t ticks) {
|
||||
}
|
||||
|
||||
TtStatus delayUntilTick(TickType_t tick) {
|
||||
tt_assert(!isIrq());
|
||||
tt_assert(!TT_IS_ISR());
|
||||
|
||||
TickType_t tcnt, delay;
|
||||
TtStatus stat;
|
||||
@ -150,7 +146,7 @@ TtStatus delayUntilTick(TickType_t tick) {
|
||||
TickType_t getTicks() {
|
||||
TickType_t ticks;
|
||||
|
||||
if (isIrq() != 0U) {
|
||||
if (TT_IS_ISR() != 0U) {
|
||||
ticks = xTaskGetTickCountFromISR();
|
||||
} else {
|
||||
ticks = xTaskGetTickCount();
|
||||
|
||||
@ -10,87 +10,56 @@
|
||||
|
||||
namespace tt::kernel {
|
||||
|
||||
/** Recognized platform types */
|
||||
typedef enum {
|
||||
PlatformEsp,
|
||||
PlatformSimulator
|
||||
} Platform;
|
||||
|
||||
/** Check if CPU is in IRQ or kernel running and IRQ is masked
|
||||
*
|
||||
* Originally this primitive was born as a workaround for FreeRTOS kernel primitives shenanigans with PRIMASK.
|
||||
*
|
||||
* Meaningful use cases are:
|
||||
*
|
||||
* - When kernel is started and you want to ensure that you are not in IRQ or IRQ is not masked(like in critical section)
|
||||
* - When kernel is not started and you want to make sure that you are not in IRQ mode, ignoring PRIMASK.
|
||||
*
|
||||
* As you can see there will be edge case when kernel is not started and PRIMASK is not 0 that may cause some funky behavior.
|
||||
* Most likely it will happen after kernel primitives being used, but control not yet passed to kernel.
|
||||
* It's up to you to figure out if it is safe for your code or not.
|
||||
*
|
||||
* @return true if CPU is in IRQ or kernel running and IRQ is masked
|
||||
*/
|
||||
bool isIrq();
|
||||
|
||||
/** Check if kernel is running
|
||||
*
|
||||
* @return true if running, false otherwise
|
||||
* @return true if the FreeRTOS kernel is running, false otherwise
|
||||
*/
|
||||
bool isRunning();
|
||||
|
||||
/** Lock kernel, pause process scheduling
|
||||
*
|
||||
* @warning This should never be called in interrupt request context.
|
||||
*
|
||||
* @return previous lock state(0 - unlocked, 1 - locked)
|
||||
* @warning don't call from ISR context
|
||||
* @return previous lock state(0 - unlocked, 1 - locked)
|
||||
*/
|
||||
int32_t lock();
|
||||
|
||||
/** Unlock kernel, resume process scheduling
|
||||
*
|
||||
* @warning This should never be called in interrupt request context.
|
||||
*
|
||||
* @return previous lock state(0 - unlocked, 1 - locked)
|
||||
* @warning don't call from ISR context
|
||||
* @return previous lock state(0 - unlocked, 1 - locked)
|
||||
*/
|
||||
int32_t unlock();
|
||||
|
||||
/** Restore kernel lock state
|
||||
*
|
||||
* @warning This should never be called in interrupt request context.
|
||||
*
|
||||
* @param[in] lock The lock state
|
||||
*
|
||||
* @return new lock state or error
|
||||
* @warning don't call from ISR context
|
||||
* @param[in] lock The lock state
|
||||
* @return new lock state or error
|
||||
*/
|
||||
int32_t restoreLock(int32_t lock);
|
||||
|
||||
/** Get kernel systick frequency
|
||||
*
|
||||
* @return systick counts per second
|
||||
* @return systick counts per second
|
||||
*/
|
||||
uint32_t getTickFrequency();
|
||||
|
||||
TickType_t getTicks();
|
||||
|
||||
/** Delay execution
|
||||
*
|
||||
* @warning This should never be called in interrupt request context.
|
||||
*
|
||||
* @warning don't call from ISR context
|
||||
* Also keep in mind delay is aliased to scheduler timer intervals.
|
||||
*
|
||||
* @param[in] ticks The ticks count to pause
|
||||
* @param[in] ticks The ticks count to pause
|
||||
*/
|
||||
void delayTicks(TickType_t ticks);
|
||||
|
||||
/** Delay until tick
|
||||
*
|
||||
* @warning This should never be called in interrupt request context.
|
||||
*
|
||||
* @param[in] ticks The tick until which kerel should delay task execution
|
||||
*
|
||||
* @return The status.
|
||||
* @warning don't call from ISR context
|
||||
* @param[in] ticks The tick until which kerel should delay task execution
|
||||
* @return the status
|
||||
*/
|
||||
TtStatus delayUntilTick(uint32_t tick);
|
||||
TtStatus delayUntilTick(TickType_t tick);
|
||||
|
||||
/** Convert milliseconds to ticks
|
||||
*
|
||||
@ -100,26 +69,22 @@ TtStatus delayUntilTick(uint32_t tick);
|
||||
TickType_t millisToTicks(uint32_t milliSeconds);
|
||||
|
||||
/** Delay in milliseconds
|
||||
*
|
||||
* This method uses kernel ticks on the inside, which causes delay to be aliased to scheduler timer intervals.
|
||||
* Real wait time will be between X+ milliseconds.
|
||||
* Special value: 0, will cause task yield.
|
||||
* Also if used when kernel is not running will fall back to `tt_delay_us`.
|
||||
*
|
||||
* @warning Cannot be used from ISR
|
||||
*
|
||||
* @param[in] milliSeconds milliseconds to wait
|
||||
* Also if used when kernel is not running will fall back to delayMicros()
|
||||
* @warning don't call from ISR context
|
||||
* @param[in] milliSeconds milliseconds to wait
|
||||
*/
|
||||
void delayMillis(uint32_t milliSeconds);
|
||||
|
||||
/** Delay in microseconds
|
||||
*
|
||||
* Implemented using Cortex DWT counter. Blocking and non aliased.
|
||||
*
|
||||
* @param[in] microSeconds microseconds to wait
|
||||
* @param[in] microSeconds microseconds to wait
|
||||
*/
|
||||
void delayMicros(uint32_t microSeconds);
|
||||
|
||||
/** @return the platform that Tactility currently is running on. */
|
||||
Platform getPlatform();
|
||||
|
||||
} // namespace
|
||||
|
||||
@ -2,7 +2,6 @@
|
||||
|
||||
#include "PanicHandler.h"
|
||||
|
||||
#include <esp_rom_sys.h>
|
||||
#include <esp_debug_helpers.h>
|
||||
#include <esp_attr.h>
|
||||
#include <esp_memory_utils.h>
|
||||
@ -10,6 +9,10 @@
|
||||
|
||||
extern "C" {
|
||||
|
||||
/**
|
||||
* This static variable survives a crash reboot.
|
||||
* It is reset by the Boot app.
|
||||
*/
|
||||
static RTC_NOINIT_ATTR CrashData crashData;
|
||||
|
||||
void __real_esp_panic_handler(void* info);
|
||||
@ -61,6 +64,6 @@ void __wrap_esp_panic_handler(void* info) {
|
||||
|
||||
}
|
||||
|
||||
const CrashData* getRtcCrashData() { return &crashData; }
|
||||
const CrashData& getRtcCrashData() { return crashData; }
|
||||
|
||||
#endif
|
||||
@ -7,6 +7,7 @@
|
||||
#define CRASH_DATA_CALLSTACK_LIMIT 64
|
||||
#define CRASH_DATA_INCLUDES_SP false
|
||||
|
||||
/** Represents a single frame on the callstack. */
|
||||
struct CallstackFrame {
|
||||
uint32_t pc = 0;
|
||||
#if CRASH_DATA_INCLUDES_SP
|
||||
@ -14,12 +15,14 @@ struct CallstackFrame {
|
||||
#endif
|
||||
};
|
||||
|
||||
/** Callstack-related crash data. */
|
||||
struct CrashData {
|
||||
bool callstackCorrupted = false;
|
||||
uint8_t callstackLength = 0;
|
||||
CallstackFrame callstack[CRASH_DATA_CALLSTACK_LIMIT];
|
||||
};
|
||||
|
||||
const CrashData* getRtcCrashData();
|
||||
/** @return the crash data */
|
||||
const CrashData& getRtcCrashData();
|
||||
|
||||
#endif
|
||||
@ -10,8 +10,15 @@ typedef struct {
|
||||
bool kernelRunning;
|
||||
} TtCriticalInfo;
|
||||
|
||||
/** Enter a critical section
|
||||
* @return info on the status
|
||||
*/
|
||||
TtCriticalInfo enter();
|
||||
|
||||
/**
|
||||
* Exit a critical section
|
||||
* @param[in] info the info from when the critical section was started
|
||||
*/
|
||||
void exit(TtCriticalInfo info);
|
||||
|
||||
} // namespace
|
||||
|
||||
@ -5,6 +5,10 @@
|
||||
|
||||
namespace tt {
|
||||
|
||||
/**
|
||||
* Settings that persist on NVS flash for ESP32.
|
||||
* On simulator, the settings are only in-memory.
|
||||
*/
|
||||
class Preferences {
|
||||
private:
|
||||
const char* namespace_;
|
||||
|
||||
@ -7,14 +7,20 @@
|
||||
|
||||
namespace tt {
|
||||
|
||||
/** Initialize the hardware and started the internal services. */
|
||||
void initHeadless(const hal::Configuration& config);
|
||||
|
||||
/** Provides access to the dispatcher that runs on the main task.
|
||||
* @warning This dispatcher is used for WiFi and might block for some time during WiFi connection.
|
||||
* @return the dispatcher
|
||||
*/
|
||||
Dispatcher& getMainDispatcher();
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace tt::hal {
|
||||
|
||||
/** Can be called after initHeadless() is called. Will crash otherwise. */
|
||||
const Configuration& getConfiguration();
|
||||
|
||||
} // namespace
|
||||
|
||||
@ -8,6 +8,10 @@ namespace tt::service {
|
||||
|
||||
class Paths;
|
||||
|
||||
/**
|
||||
* The public representation of a service instance.
|
||||
* @warning Do not store references or pointers to these! You can retrieve them via the Loader service.
|
||||
*/
|
||||
class ServiceContext {
|
||||
|
||||
protected:
|
||||
@ -16,9 +20,13 @@ protected:
|
||||
|
||||
public:
|
||||
|
||||
/** @return a reference ot the service's manifest */
|
||||
virtual const service::ServiceManifest& getManifest() const = 0;
|
||||
virtual std::shared_ptr<void> getData() const = 0;
|
||||
/** @return a shared pointer to the data that is attached to the service */
|
||||
virtual std::shared_ptr<void> _Nullable getData() const = 0;
|
||||
/** Set the data for a service. */
|
||||
virtual void setData(std::shared_ptr<void> newData) = 0;
|
||||
/** Retrieve the paths that are relevant to this service */
|
||||
virtual std::unique_ptr<Paths> getPaths() const = 0;
|
||||
};
|
||||
|
||||
|
||||
@ -9,22 +9,16 @@ class ServiceContext;
|
||||
typedef void (*ServiceOnStart)(ServiceContext& service);
|
||||
typedef void (*ServiceOnStop)(ServiceContext& service);
|
||||
|
||||
/** A ledger that describes the main parts of a service. */
|
||||
struct ServiceManifest {
|
||||
/**
|
||||
* The identifier by which the app is launched by the system and other apps.
|
||||
*/
|
||||
/** The identifier by which the app is launched by the system and other apps. */
|
||||
std::string id {};
|
||||
|
||||
/**
|
||||
* Non-blocking method to call when service is started.
|
||||
*/
|
||||
/** Non-blocking method to call when service is started. */
|
||||
const ServiceOnStart onStart = nullptr;
|
||||
|
||||
/**
|
||||
* Non-blocking method to call when service is stopped.
|
||||
*/
|
||||
/** Non-blocking method to call when service is stopped. */
|
||||
const ServiceOnStop onStop = nullptr;
|
||||
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
@ -4,17 +4,40 @@
|
||||
|
||||
namespace tt::service {
|
||||
|
||||
typedef void (*ManifestCallback)(const ServiceManifest*, void* context);
|
||||
|
||||
void initRegistry();
|
||||
|
||||
/** Register a service.
|
||||
* @param[in] the service manifest
|
||||
*/
|
||||
void addService(const ServiceManifest* manifest);
|
||||
|
||||
/** Unregister a service.
|
||||
* @param[in] the service manifest
|
||||
*/
|
||||
void removeService(const ServiceManifest* manifest);
|
||||
|
||||
/** Start a service.
|
||||
* @param[in] the service id as defined in its manifest
|
||||
* @return true on success
|
||||
*/
|
||||
bool startService(const std::string& id);
|
||||
|
||||
/** Stop a service.
|
||||
* @param[in] the service id as defined in its manifest
|
||||
* @return true on success or false when service wasn't running.
|
||||
*/
|
||||
bool stopService(const std::string& id);
|
||||
|
||||
/** Find a service manifest by its id.
|
||||
* @param[in] id the id as defined in the manifest
|
||||
* @return the matching manifest or nullptr when it wasn't found
|
||||
*/
|
||||
const ServiceManifest* _Nullable findManifestId(const std::string& id);
|
||||
|
||||
/** Find a service by its manifest id.
|
||||
* @param[in] id the id as defined in the manifest
|
||||
* @return the service context or nullptr when it wasn't found
|
||||
*/
|
||||
ServiceContext* _Nullable findServiceById(const std::string& id);
|
||||
|
||||
} // namespace
|
||||
|
||||
@ -84,53 +84,42 @@ WifiRadioState getRadioState();
|
||||
*/
|
||||
void scan();
|
||||
|
||||
/**
|
||||
* @return true if wifi is actively scanning
|
||||
*/
|
||||
/** @return true if wifi is actively scanning */
|
||||
bool isScanning();
|
||||
|
||||
/**
|
||||
* @return true the ssid name or empty string
|
||||
*/
|
||||
/** @return true the ssid name or empty string */
|
||||
std::string getConnectionTarget();
|
||||
|
||||
/**
|
||||
* @brief Returns the access points from the last scan (if any). It only contains public APs.
|
||||
*/
|
||||
/** @return the access points from the last scan (if any). It only contains public APs. */
|
||||
std::vector<WifiApRecord> getScanResults();
|
||||
|
||||
/**
|
||||
* @brief Overrides the default scan result size of 16.
|
||||
* @param records the record limit for the scan result (84 bytes per record!)
|
||||
* @param[in] records the record limit for the scan result (84 bytes per record!)
|
||||
*/
|
||||
void setScanRecords(uint16_t records);
|
||||
|
||||
/**
|
||||
* @brief Enable/disable the radio. Ignores input if desired state matches current state.
|
||||
* @param enabled
|
||||
* @param[in] enabled
|
||||
*/
|
||||
void setEnabled(bool enabled);
|
||||
|
||||
/**
|
||||
* @brief Connect to a network. Disconnects any existing connection.
|
||||
* Returns immediately but runs in the background. Results are through pubsub.
|
||||
* @param ap
|
||||
* @param[in] ap
|
||||
* @param[in] remember whether to save the ap data to the settings upon successful connection
|
||||
*/
|
||||
void connect(const settings::WifiApSettings* ap, bool remember);
|
||||
|
||||
/**
|
||||
* @brief Disconnect from the access point. Doesn't have any effect when not connected.
|
||||
*/
|
||||
/** @brief Disconnect from the access point. Doesn't have any effect when not connected. */
|
||||
void disconnect();
|
||||
|
||||
/**
|
||||
* Return true if the connection isn't unencrypted.
|
||||
*/
|
||||
/** @return true if the connection isn't unencrypted. */
|
||||
bool isConnectionSecure();
|
||||
|
||||
/**
|
||||
* Returns the RSSI value (negative number) or return 1 when not connected
|
||||
*/
|
||||
/** @return the RSSI value (negative number) or return 1 when not connected. */
|
||||
int getRssi();
|
||||
|
||||
} // namespace
|
||||
|
||||
@ -780,7 +780,7 @@ static void dispatchConnect(std::shared_ptr<void> context) {
|
||||
TT_LOG_I(TAG, "Waiting for EventFlag by event_handler()");
|
||||
|
||||
if (bits & WIFI_CONNECTED_BIT) {
|
||||
wifi->setSecureConnection(wifi_config.sta.password[0] != 0x00);
|
||||
wifi->setSecureConnection(wifi_config.sta.password[0] != 0x00U);
|
||||
wifi->setRadioState(WIFI_RADIO_CONNECTION_ACTIVE);
|
||||
publish_event_simple(wifi, WifiEventTypeConnectionSuccess);
|
||||
TT_LOG_I(TAG, "Connected to %s", wifi->connection_target.ssid);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user