Kernel and TactilitySDK improvements (#479)
* **New Features** * Expanded public device and driver APIs (accessors, sync, lifecycle, binding) and a module construct+start helper. * Added kernel symbol registry and new exported symbols (lvgl, C++ nothrow, I2S APIs, additional math funcs). * **Refactor** * Renamed device traversal APIs for consistency (device_for_each*). * Moved inline helpers to explicit public declarations. * **Chores** * Replaced several shell release scripts with Python-based SDK release tooling. * **Style** * Header naming consistency fixes.
This commit is contained in:
committed by
GitHub
parent
9cc96fd32b
commit
9a672a30ff
@@ -3,18 +3,18 @@
|
||||
#pragma once
|
||||
|
||||
#include "driver.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include "error.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "error.h"
|
||||
#include <tactility/concurrent/mutex.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct Driver;
|
||||
struct DevicePrivate;
|
||||
|
||||
@@ -64,9 +64,9 @@ struct CompatibleDevice {
|
||||
/**
|
||||
* Initialize the properties of a device.
|
||||
*
|
||||
* @param[in] device a device with all non-internal properties set
|
||||
* @retval ERROR_OUT_OF_MEMORY
|
||||
* @retval ERROR_NONE
|
||||
* @param[in,out] device a device with all non-internal properties set
|
||||
* @retval ERROR_OUT_OF_MEMORY if internal data allocation failed
|
||||
* @retval ERROR_NONE on success
|
||||
*/
|
||||
error_t device_construct(struct Device* device);
|
||||
|
||||
@@ -74,31 +74,20 @@ error_t device_construct(struct Device* device);
|
||||
* Deinitialize the properties of a device.
|
||||
* This fails when a device is busy or has children.
|
||||
*
|
||||
* @param[in] device
|
||||
* @retval ERROR_INVALID_STATE
|
||||
* @retval ERROR_NONE
|
||||
* @param[in,out] device non-null device pointer
|
||||
* @retval ERROR_INVALID_STATE if the device is busy or has children
|
||||
* @retval ERROR_NONE on success
|
||||
*/
|
||||
error_t device_destruct(struct Device* device);
|
||||
|
||||
/**
|
||||
* Indicates whether the device is in a state where its API is available
|
||||
*
|
||||
* @param[in] device non-null device pointer
|
||||
* @return true if the device is ready for use
|
||||
*/
|
||||
static inline bool device_is_ready(const struct Device* device) {
|
||||
return device->internal.state.started;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a device to all relevant systems:
|
||||
* - the global ledger
|
||||
* - its parent (if any)
|
||||
* - a bus (if any)
|
||||
*
|
||||
* @param[in] device non-null device pointer
|
||||
* @retval ERROR_INVALID_STATE
|
||||
* @retval ERROR_NONE
|
||||
* @param[in,out] device non-null device pointer
|
||||
* @retval ERROR_INVALID_STATE if the device is already added
|
||||
* @retval ERROR_NONE on success
|
||||
*/
|
||||
error_t device_add(struct Device* device);
|
||||
|
||||
@@ -106,12 +95,11 @@ error_t device_add(struct Device* device);
|
||||
* Deregister a device. Remove it from all relevant systems:
|
||||
* - the global ledger
|
||||
* - its parent (if any)
|
||||
* - a bus (if any)
|
||||
*
|
||||
* @param[in] device non-null device pointer
|
||||
* @retval ERROR_INVALID_STATE
|
||||
* @retval ERROR_NOT_FOUND
|
||||
* @retval ERROR_NONE
|
||||
* @param[in,out] device non-null device pointer
|
||||
* @retval ERROR_INVALID_STATE if the device is still started
|
||||
* @retval ERROR_NOT_FOUND if the device was not found in the system
|
||||
* @retval ERROR_NONE on success
|
||||
*/
|
||||
error_t device_remove(struct Device* device);
|
||||
|
||||
@@ -119,91 +107,164 @@ error_t device_remove(struct Device* device);
|
||||
* Attach the driver.
|
||||
*
|
||||
* @warning must call device_construct() and device_add() first
|
||||
* @param device
|
||||
* @retval ERROR_INVALID_STATE
|
||||
* @param[in,out] device non-null device pointer
|
||||
* @retval ERROR_INVALID_STATE if the device is already started or not added
|
||||
* @retval ERROR_RESOURCE when driver binding fails
|
||||
* @retval ERROR_NONE
|
||||
* @retval ERROR_NONE on success
|
||||
*/
|
||||
error_t device_start(struct Device* device);
|
||||
|
||||
/**
|
||||
* Detach the driver.
|
||||
*
|
||||
* @param device
|
||||
* @retval ERROR_INVALID_STATE
|
||||
* @param[in,out] device non-null device pointer
|
||||
* @retval ERROR_INVALID_STATE if the device is not started
|
||||
* @retval ERROR_RESOURCE when driver unbinding fails
|
||||
* @retval ERROR_NONE
|
||||
* @retval ERROR_NONE on success
|
||||
*/
|
||||
error_t device_stop(struct Device* device);
|
||||
|
||||
/**
|
||||
* Construct and add a device with the given compatible string.
|
||||
*
|
||||
* @param[in,out] device non-NULL device
|
||||
* @param[in] compatible compatible string
|
||||
* @retval ERROR_NONE on success
|
||||
* @retval error_t error code on failure
|
||||
*/
|
||||
error_t device_construct_add_start(struct Device* device, const char* compatible);
|
||||
|
||||
/**
|
||||
* Construct and add a device with the given compatible string.
|
||||
*
|
||||
* @param[in,out] device non-NULL device
|
||||
* @param[in] compatible compatible string
|
||||
* @retval ERROR_NONE on success
|
||||
* @retval error_t error code on failure
|
||||
*/
|
||||
error_t device_construct_add(struct Device* device, const char* compatible);
|
||||
|
||||
/**
|
||||
* Set or unset a parent.
|
||||
*
|
||||
* @warning must call before device_add()
|
||||
* @param device non-NULL device
|
||||
* @param parent nullable parent device
|
||||
* @param[in,out] device non-NULL device
|
||||
* @param[in] parent nullable parent device
|
||||
*/
|
||||
void device_set_parent(struct Device* device, struct Device* parent);
|
||||
|
||||
error_t device_construct_add(struct Device* device, const char* compatible);
|
||||
/**
|
||||
* Set the driver for a device.
|
||||
*
|
||||
* @warning must call before device_add()
|
||||
* @param[in,out] device non-NULL device
|
||||
* @param[in] driver nullable driver
|
||||
*/
|
||||
void device_set_driver(struct Device* device, struct Driver* driver);
|
||||
|
||||
error_t device_construct_add_start(struct Device* device, const char* compatible);
|
||||
/**
|
||||
* Get the driver for a device.
|
||||
*
|
||||
* @param[in] device non-null device pointer
|
||||
* @return the driver, or NULL if the device has no driver
|
||||
*/
|
||||
struct Driver* device_get_driver(struct Device* device);
|
||||
|
||||
static inline void device_set_driver(struct Device* device, struct Driver* driver) {
|
||||
device->internal.driver = driver;
|
||||
}
|
||||
/**
|
||||
* Get the parent device of a device.
|
||||
*
|
||||
* @param[in] device non-null device pointer
|
||||
* @return the parent device, or NULL if the device has no parent
|
||||
*/
|
||||
struct Device* device_get_parent(struct Device* device);
|
||||
|
||||
static inline struct Driver* device_get_driver(struct Device* device) {
|
||||
return device->internal.driver;
|
||||
}
|
||||
/**
|
||||
* Indicates whether the device is in a state where its API is available
|
||||
*
|
||||
* @param[in] device non-null device pointer
|
||||
* @return true if the device is ready for use
|
||||
*/
|
||||
bool device_is_ready(const struct Device* device);
|
||||
|
||||
static inline void device_set_driver_data(struct Device* device, void* driver_data) {
|
||||
device->internal.driver_data = driver_data;
|
||||
}
|
||||
/**
|
||||
* Set the driver data for a device.
|
||||
*
|
||||
* @param[in,out] device non-null device pointer
|
||||
* @param[in] driver_data the driver data
|
||||
*/
|
||||
void device_set_driver_data(struct Device* device, void* driver_data);
|
||||
|
||||
static inline void* device_get_driver_data(struct Device* device) {
|
||||
return device->internal.driver_data;
|
||||
}
|
||||
/**
|
||||
* Get the driver data for a device.
|
||||
*
|
||||
* @param[in] device non-null device pointer
|
||||
* @return the driver data
|
||||
*/
|
||||
void* device_get_driver_data(struct Device* device);
|
||||
|
||||
static inline bool device_is_added(const struct Device* device) {
|
||||
return device->internal.state.added;
|
||||
}
|
||||
/**
|
||||
* Indicates whether the device has been added to the system.
|
||||
*
|
||||
* @param[in] device non-null device pointer
|
||||
* @return true if the device has been added
|
||||
*/
|
||||
bool device_is_added(const struct Device* device);
|
||||
|
||||
static inline void device_lock(struct Device* device) {
|
||||
mutex_lock(&device->internal.mutex);
|
||||
}
|
||||
/**
|
||||
* Lock the device for exclusive access.
|
||||
*
|
||||
* @param[in,out] device non-null device pointer
|
||||
*/
|
||||
void device_lock(struct Device* device);
|
||||
|
||||
static inline bool device_try_lock(struct Device* device) {
|
||||
return mutex_try_lock(&device->internal.mutex);
|
||||
}
|
||||
/**
|
||||
* Try to lock the device for exclusive access.
|
||||
*
|
||||
* @param[in,out] device non-null device pointer
|
||||
* @return true if the device was locked successfully
|
||||
*/
|
||||
bool device_try_lock(struct Device* device);
|
||||
|
||||
static inline void device_unlock(struct Device* device) {
|
||||
mutex_unlock(&device->internal.mutex);
|
||||
}
|
||||
/**
|
||||
* Unlock the device.
|
||||
*
|
||||
* @param[in,out] device non-null device pointer
|
||||
*/
|
||||
void device_unlock(struct Device* device);
|
||||
|
||||
/**
|
||||
* Get the type of a device.
|
||||
*
|
||||
* @param[in] device non-null device pointer
|
||||
* @return the device type
|
||||
*/
|
||||
const struct DeviceType* device_get_type(struct Device* device);
|
||||
|
||||
static inline const struct DeviceType* device_get_type(struct Device* device) {
|
||||
return device->internal.driver ? device->internal.driver->device_type : NULL;
|
||||
}
|
||||
/**
|
||||
* Iterate through all the known devices
|
||||
* @param callback_context the parameter to pass to the callback. NULL is valid.
|
||||
* @param on_device the function to call for each filtered device. return true to continue iterating or false to stop.
|
||||
*
|
||||
* @param[in] callback_context the parameter to pass to the callback. NULL is valid.
|
||||
* @param[in] on_device the function to call for each filtered device. return true to continue iterating or false to stop.
|
||||
*/
|
||||
void for_each_device(void* callback_context, bool(*on_device)(struct Device* device, void* context));
|
||||
void device_for_each(void* callback_context, bool(*on_device)(struct Device* device, void* context));
|
||||
|
||||
/**
|
||||
* Iterate through all the child devices of the specified device
|
||||
* @param callbackContext the parameter to pass to the callback. NULL is valid.
|
||||
* @param on_device the function to call for each filtered device. return true to continue iterating or false to stop.
|
||||
*
|
||||
* @param[in] device non-null device pointer
|
||||
* @param[in] callback_context the parameter to pass to the callback. NULL is valid.
|
||||
* @param[in] on_device the function to call for each filtered device. return true to continue iterating or false to stop.
|
||||
*/
|
||||
void for_each_device_child(struct Device* device, void* callbackContext, bool(*on_device)(struct Device* device, void* context));
|
||||
void device_for_each_child(struct Device* device, void* callback_context, bool(*on_device)(struct Device* device, void* context));
|
||||
|
||||
/**
|
||||
* Iterate through all the known devices of a specific type
|
||||
* @param type the type to filter
|
||||
* @param callbackContext the parameter to pass to the callback. NULL is valid.
|
||||
* @param on_device the function to call for each filtered device. return true to continue iterating or false to stop.
|
||||
*
|
||||
* @param[in] type the type to filter
|
||||
* @param[in] callback_context the parameter to pass to the callback. NULL is valid.
|
||||
* @param[in] on_device the function to call for each filtered device. return true to continue iterating or false to stop.
|
||||
*/
|
||||
void for_each_device_of_type(const struct DeviceType* type, void* callbackContext, bool(*on_device)(struct Device* device, void* context));
|
||||
void device_for_each_of_type(const struct DeviceType* type, void* callback_context, bool(*on_device)(struct Device* device, void* context));
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -33,29 +33,108 @@ struct Driver {
|
||||
struct DriverPrivate* driver_private;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Construct a driver.
|
||||
*
|
||||
* This initializes the internal state of the driver.
|
||||
*
|
||||
* @param driver The driver to construct.
|
||||
* @return ERROR_NONE if successful, or an error code otherwise.
|
||||
*/
|
||||
error_t driver_construct(struct Driver* driver);
|
||||
|
||||
/**
|
||||
* @brief Destruct a driver.
|
||||
*
|
||||
* This cleans up the internal state of the driver.
|
||||
*
|
||||
* @param driver The driver to destruct.
|
||||
* @return ERROR_NONE if successful, or an error code otherwise.
|
||||
*/
|
||||
error_t driver_destruct(struct Driver* driver);
|
||||
|
||||
/**
|
||||
* @brief Add a driver to the system.
|
||||
*
|
||||
* This registers the driver so it can be used to bind to devices.
|
||||
*
|
||||
* @param driver The driver to add.
|
||||
* @return ERROR_NONE if successful, or an error code otherwise.
|
||||
*/
|
||||
error_t driver_add(struct Driver* driver);
|
||||
|
||||
/**
|
||||
* @brief Remove a driver from the system.
|
||||
*
|
||||
* This unregisters the driver.
|
||||
*
|
||||
* @param driver The driver to remove.
|
||||
* @return ERROR_NONE if successful, or an error code otherwise.
|
||||
*/
|
||||
error_t driver_remove(struct Driver* driver);
|
||||
|
||||
/**
|
||||
* @brief Construct and add a driver to the system.
|
||||
*
|
||||
* @param driver The driver to construct and add.
|
||||
* @return ERROR_NONE if successful, or an error code otherwise.
|
||||
*/
|
||||
error_t driver_construct_add(struct Driver* driver);
|
||||
|
||||
/**
|
||||
* @brief Remove and destruct a driver.
|
||||
*
|
||||
* @param driver The driver to remove and destruct.
|
||||
* @return ERROR_NONE if successful, or an error code otherwise.
|
||||
*/
|
||||
error_t driver_remove_destruct(struct Driver* driver);
|
||||
|
||||
/**
|
||||
* @brief Bind a driver to a device.
|
||||
*
|
||||
* This calls the driver's start_device function and increments the driver's use count.
|
||||
*
|
||||
* @param driver The driver to bind.
|
||||
* @param device The device to bind to.
|
||||
* @return ERROR_NONE if successful, or an error code otherwise.
|
||||
*/
|
||||
error_t driver_bind(struct Driver* driver, struct Device* device);
|
||||
|
||||
/**
|
||||
* @brief Unbind a driver from a device.
|
||||
*
|
||||
* This calls the driver's stop_device function and decrements the driver's use count.
|
||||
*
|
||||
* @param driver The driver to unbind.
|
||||
* @param device The device to unbind from.
|
||||
* @return ERROR_NONE if successful, or an error code otherwise.
|
||||
*/
|
||||
error_t driver_unbind(struct Driver* driver, struct Device* device);
|
||||
|
||||
/**
|
||||
* @brief Check if a driver is compatible with a given string.
|
||||
*
|
||||
* @param driver The driver to check.
|
||||
* @param compatible The compatibility string to check.
|
||||
* @return true if compatible, false otherwise.
|
||||
*/
|
||||
bool driver_is_compatible(struct Driver* driver, const char* compatible);
|
||||
|
||||
/**
|
||||
* @brief Find a driver compatible with a given string.
|
||||
*
|
||||
* @param compatible The compatibility string to find.
|
||||
* @return The compatible driver, or NULL if not found.
|
||||
*/
|
||||
struct Driver* driver_find_compatible(const char* compatible);
|
||||
|
||||
static inline const struct DeviceType* driver_get_device_type(struct Driver* driver) {
|
||||
return driver->device_type;
|
||||
}
|
||||
/**
|
||||
* @brief Get the device type of a driver.
|
||||
*
|
||||
* @param driver The driver to get the device type from.
|
||||
* @return The device type of the driver.
|
||||
*/
|
||||
const struct DeviceType* driver_get_device_type(struct Driver* driver);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -59,7 +59,6 @@ struct Module {
|
||||
*/
|
||||
const struct ModuleSymbol* symbols;
|
||||
|
||||
|
||||
struct {
|
||||
bool started;
|
||||
} internal;
|
||||
@@ -101,13 +100,6 @@ error_t module_remove(struct Module* module);
|
||||
*/
|
||||
error_t module_start(struct Module* module);
|
||||
|
||||
/**
|
||||
* @brief Check if the module is started.
|
||||
* @param module module to check
|
||||
* @return true if the module is started, false otherwise
|
||||
*/
|
||||
bool module_is_started(struct Module* module);
|
||||
|
||||
/**
|
||||
* @brief Stop the module.
|
||||
* @param module module
|
||||
@@ -115,6 +107,20 @@ bool module_is_started(struct Module* module);
|
||||
*/
|
||||
error_t module_stop(struct Module* module);
|
||||
|
||||
/**
|
||||
* @brief Construct, add and start a module.
|
||||
* @param module module
|
||||
* @return ERROR_NONE if successful
|
||||
*/
|
||||
error_t module_construct_add_start(struct Module* module);
|
||||
|
||||
/**
|
||||
* @brief Check if the module is started.
|
||||
* @param module module to check
|
||||
* @return true if the module is started, false otherwise
|
||||
*/
|
||||
bool module_is_started(struct Module* module);
|
||||
|
||||
/**
|
||||
* @brief Resolve a symbol from the module.
|
||||
* @details The module must be started for symbol resolution to succeed.
|
||||
|
||||
@@ -6,10 +6,10 @@
|
||||
|
||||
#include "tactility/error.h"
|
||||
|
||||
#include <tactility/concurrent/eventgroup.h>
|
||||
#include <atomic>
|
||||
#include <tactility/concurrent/event_group.h>
|
||||
#include <tactility/concurrent/mutex.h>
|
||||
#include <tactility/log.h>
|
||||
#include <atomic>
|
||||
|
||||
#define TAG "Dispatcher"
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#include <tactility/concurrent/eventgroup.h>
|
||||
#include <tactility/concurrent/event_group.h>
|
||||
#include <tactility/error.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -240,7 +240,51 @@ void device_set_parent(Device* device, Device* parent) {
|
||||
device->parent = parent;
|
||||
}
|
||||
|
||||
void for_each_device(void* callback_context, bool(*on_device)(Device* device, void* context)) {
|
||||
Device* device_get_parent(struct Device* device) {
|
||||
return device->parent;
|
||||
}
|
||||
|
||||
void device_set_driver(struct Device* device, struct Driver* driver) {
|
||||
device->internal.driver = driver;
|
||||
}
|
||||
|
||||
struct Driver* device_get_driver(struct Device* device) {
|
||||
return device->internal.driver;
|
||||
}
|
||||
|
||||
bool device_is_ready(const struct Device* device) {
|
||||
return device->internal.state.started;
|
||||
}
|
||||
|
||||
void device_set_driver_data(struct Device* device, void* driver_data) {
|
||||
device->internal.driver_data = driver_data;
|
||||
}
|
||||
|
||||
void* device_get_driver_data(struct Device* device) {
|
||||
return device->internal.driver_data;
|
||||
}
|
||||
|
||||
bool device_is_added(const struct Device* device) {
|
||||
return device->internal.state.added;
|
||||
}
|
||||
|
||||
void device_lock(struct Device* device) {
|
||||
mutex_lock(&device->internal.mutex);
|
||||
}
|
||||
|
||||
bool device_try_lock(struct Device* device) {
|
||||
return mutex_try_lock(&device->internal.mutex);
|
||||
}
|
||||
|
||||
void device_unlock(struct Device* device) {
|
||||
mutex_unlock(&device->internal.mutex);
|
||||
}
|
||||
|
||||
const struct DeviceType* device_get_type(struct Device* device) {
|
||||
return device->internal.driver ? device->internal.driver->device_type : NULL;
|
||||
}
|
||||
|
||||
void device_for_each(void* callback_context, bool(*on_device)(Device* device, void* context)) {
|
||||
ledger_lock();
|
||||
for (auto* device : ledger.devices) {
|
||||
if (!on_device(device, callback_context)) {
|
||||
@@ -250,7 +294,7 @@ void for_each_device(void* callback_context, bool(*on_device)(Device* device, vo
|
||||
ledger_unlock();
|
||||
}
|
||||
|
||||
void for_each_device_child(Device* device, void* callbackContext, bool(*on_device)(struct Device* device, void* context)) {
|
||||
void device_for_each_child(Device* device, void* callbackContext, bool(*on_device)(struct Device* device, void* context)) {
|
||||
auto* data = get_device_private(device);
|
||||
for (auto* child_device : data->children) {
|
||||
if (!on_device(child_device, callbackContext)) {
|
||||
@@ -259,7 +303,7 @@ void for_each_device_child(Device* device, void* callbackContext, bool(*on_devic
|
||||
}
|
||||
}
|
||||
|
||||
void for_each_device_of_type(const DeviceType* type, void* callbackContext, bool(*on_device)(Device* device, void* context)) {
|
||||
void device_for_each_of_type(const DeviceType* type, void* callbackContext, bool(*on_device)(Device* device, void* context)) {
|
||||
ledger_lock();
|
||||
for (auto* device : ledger.devices) {
|
||||
auto* driver = device->internal.driver;
|
||||
|
||||
@@ -199,4 +199,8 @@ error:
|
||||
return error;
|
||||
}
|
||||
|
||||
const struct DeviceType* driver_get_device_type(struct Driver* driver) {
|
||||
return driver->device_type;
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
@@ -7,48 +7,41 @@ extern "C" {
|
||||
|
||||
#define TAG "kernel"
|
||||
|
||||
static error_t init_kernel_drivers() {
|
||||
extern const struct ModuleSymbol KERNEL_SYMBOLS[];
|
||||
|
||||
static error_t start() {
|
||||
extern Driver root_driver;
|
||||
if (driver_construct_add(&root_driver) != ERROR_NONE) return ERROR_RESOURCE;
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
static error_t stop() {
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
struct Module root_module = {
|
||||
.name = "kernel",
|
||||
.start = start,
|
||||
.stop = stop,
|
||||
.symbols = (const struct ModuleSymbol*)KERNEL_SYMBOLS
|
||||
};
|
||||
|
||||
error_t kernel_init(struct Module* platform_module, struct Module* device_module, struct CompatibleDevice devicetree_devices[]) {
|
||||
LOG_I(TAG, "init");
|
||||
|
||||
if (init_kernel_drivers() != ERROR_NONE) {
|
||||
LOG_E(TAG, "init failed to init kernel drivers");
|
||||
if (module_construct_add_start(&root_module) != ERROR_NONE) {
|
||||
LOG_E(TAG, "root module init failed");
|
||||
return ERROR_RESOURCE;
|
||||
}
|
||||
|
||||
if (module_construct(platform_module) != ERROR_NONE) {
|
||||
LOG_E(TAG, "init failed to construct platform module");
|
||||
return ERROR_RESOURCE;
|
||||
}
|
||||
|
||||
if (module_add(platform_module) != ERROR_NONE) {
|
||||
LOG_E(TAG, "init failed to add platform module");
|
||||
return ERROR_RESOURCE;
|
||||
}
|
||||
|
||||
if (module_start(platform_module) != ERROR_NONE) {
|
||||
LOG_E(TAG, "init failed to start platform module");
|
||||
if (module_construct_add_start(platform_module) != ERROR_NONE) {
|
||||
LOG_E(TAG, "platform module init failed");
|
||||
return ERROR_RESOURCE;
|
||||
}
|
||||
|
||||
if (device_module != nullptr) {
|
||||
if (module_construct(device_module) != ERROR_NONE) {
|
||||
LOG_E(TAG, "init failed to construct device module");
|
||||
return ERROR_RESOURCE;
|
||||
}
|
||||
|
||||
if (module_add(device_module) != ERROR_NONE) {
|
||||
LOG_E(TAG, "init failed to add device module");
|
||||
return ERROR_RESOURCE;
|
||||
}
|
||||
|
||||
if (module_start(device_module) != ERROR_NONE) {
|
||||
LOG_E(TAG, "init failed to start device module");
|
||||
if (module_construct_add_start(device_module) != ERROR_NONE) {
|
||||
LOG_E(TAG, "device module init failed");
|
||||
return ERROR_RESOURCE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
#include <tactility/device.h>
|
||||
#include <tactility/driver.h>
|
||||
#include <tactility/drivers/i2c_controller.h>
|
||||
#include <tactility/drivers/gpio_controller.h>
|
||||
#include <tactility/concurrent/dispatcher.h>
|
||||
#include <tactility/concurrent/event_group.h>
|
||||
#include <tactility/concurrent/thread.h>
|
||||
#include <tactility/concurrent/timer.h>
|
||||
#include <tactility/error.h>
|
||||
#include <tactility/log.h>
|
||||
#include <tactility/module.h>
|
||||
|
||||
/**
|
||||
* This file is a C file instead of C++, so we can import all headers as C code.
|
||||
* The intent is to catch errors that only show up when compiling as C and not as C++.
|
||||
* For example: wrong header includes.
|
||||
*/
|
||||
const struct ModuleSymbol KERNEL_SYMBOLS[] = {
|
||||
// device
|
||||
DEFINE_MODULE_SYMBOL(device_construct),
|
||||
DEFINE_MODULE_SYMBOL(device_destruct),
|
||||
DEFINE_MODULE_SYMBOL(device_add),
|
||||
DEFINE_MODULE_SYMBOL(device_remove),
|
||||
DEFINE_MODULE_SYMBOL(device_start),
|
||||
DEFINE_MODULE_SYMBOL(device_stop),
|
||||
DEFINE_MODULE_SYMBOL(device_construct_add),
|
||||
DEFINE_MODULE_SYMBOL(device_construct_add_start),
|
||||
DEFINE_MODULE_SYMBOL(device_set_parent),
|
||||
DEFINE_MODULE_SYMBOL(device_get_parent),
|
||||
DEFINE_MODULE_SYMBOL(device_set_driver),
|
||||
DEFINE_MODULE_SYMBOL(device_get_driver),
|
||||
DEFINE_MODULE_SYMBOL(device_set_driver_data),
|
||||
DEFINE_MODULE_SYMBOL(device_get_driver_data),
|
||||
DEFINE_MODULE_SYMBOL(device_is_added),
|
||||
DEFINE_MODULE_SYMBOL(device_is_ready),
|
||||
DEFINE_MODULE_SYMBOL(device_lock),
|
||||
DEFINE_MODULE_SYMBOL(device_try_lock),
|
||||
DEFINE_MODULE_SYMBOL(device_unlock),
|
||||
DEFINE_MODULE_SYMBOL(device_get_type),
|
||||
DEFINE_MODULE_SYMBOL(device_for_each),
|
||||
DEFINE_MODULE_SYMBOL(device_for_each_child),
|
||||
DEFINE_MODULE_SYMBOL(device_for_each_of_type),
|
||||
// driver
|
||||
DEFINE_MODULE_SYMBOL(driver_construct),
|
||||
DEFINE_MODULE_SYMBOL(driver_destruct),
|
||||
DEFINE_MODULE_SYMBOL(driver_add),
|
||||
DEFINE_MODULE_SYMBOL(driver_remove),
|
||||
DEFINE_MODULE_SYMBOL(driver_construct_add),
|
||||
DEFINE_MODULE_SYMBOL(driver_remove_destruct),
|
||||
DEFINE_MODULE_SYMBOL(driver_bind),
|
||||
DEFINE_MODULE_SYMBOL(driver_unbind),
|
||||
DEFINE_MODULE_SYMBOL(driver_is_compatible),
|
||||
DEFINE_MODULE_SYMBOL(driver_find_compatible),
|
||||
DEFINE_MODULE_SYMBOL(driver_get_device_type),
|
||||
// drivers/gpio_controller
|
||||
DEFINE_MODULE_SYMBOL(gpio_controller_set_level),
|
||||
DEFINE_MODULE_SYMBOL(gpio_controller_get_level),
|
||||
DEFINE_MODULE_SYMBOL(gpio_controller_set_options),
|
||||
DEFINE_MODULE_SYMBOL(gpio_controller_get_options),
|
||||
DEFINE_MODULE_SYMBOL(gpio_controller_get_pin_count),
|
||||
// drivers/i2c_controller
|
||||
DEFINE_MODULE_SYMBOL(i2c_controller_read),
|
||||
DEFINE_MODULE_SYMBOL(i2c_controller_write),
|
||||
DEFINE_MODULE_SYMBOL(i2c_controller_write_read),
|
||||
DEFINE_MODULE_SYMBOL(i2c_controller_read_register),
|
||||
DEFINE_MODULE_SYMBOL(i2c_controller_write_register),
|
||||
DEFINE_MODULE_SYMBOL(i2c_controller_write_register_array),
|
||||
DEFINE_MODULE_SYMBOL(i2c_controller_has_device_at_address),
|
||||
// concurrent/dispatcher
|
||||
DEFINE_MODULE_SYMBOL(dispatcher_alloc),
|
||||
DEFINE_MODULE_SYMBOL(dispatcher_free),
|
||||
DEFINE_MODULE_SYMBOL(dispatcher_dispatch_timed),
|
||||
DEFINE_MODULE_SYMBOL(dispatcher_consume_timed),
|
||||
// concurrent/event_group
|
||||
DEFINE_MODULE_SYMBOL(event_group_set),
|
||||
DEFINE_MODULE_SYMBOL(event_group_clear),
|
||||
DEFINE_MODULE_SYMBOL(event_group_get),
|
||||
DEFINE_MODULE_SYMBOL(event_group_wait),
|
||||
// concurrent/thread
|
||||
DEFINE_MODULE_SYMBOL(thread_alloc),
|
||||
DEFINE_MODULE_SYMBOL(thread_alloc_full),
|
||||
DEFINE_MODULE_SYMBOL(thread_free),
|
||||
DEFINE_MODULE_SYMBOL(thread_set_name),
|
||||
DEFINE_MODULE_SYMBOL(thread_set_stack_size),
|
||||
DEFINE_MODULE_SYMBOL(thread_set_affinity),
|
||||
DEFINE_MODULE_SYMBOL(thread_set_main_function),
|
||||
DEFINE_MODULE_SYMBOL(thread_set_priority),
|
||||
DEFINE_MODULE_SYMBOL(thread_set_state_callback),
|
||||
DEFINE_MODULE_SYMBOL(thread_get_state),
|
||||
DEFINE_MODULE_SYMBOL(thread_start),
|
||||
DEFINE_MODULE_SYMBOL(thread_join),
|
||||
DEFINE_MODULE_SYMBOL(thread_get_task_handle),
|
||||
DEFINE_MODULE_SYMBOL(thread_get_return_code),
|
||||
DEFINE_MODULE_SYMBOL(thread_get_stack_space),
|
||||
DEFINE_MODULE_SYMBOL(thread_get_current),
|
||||
// concurrent/timer
|
||||
DEFINE_MODULE_SYMBOL(timer_alloc),
|
||||
DEFINE_MODULE_SYMBOL(timer_free),
|
||||
DEFINE_MODULE_SYMBOL(timer_start),
|
||||
DEFINE_MODULE_SYMBOL(timer_stop),
|
||||
DEFINE_MODULE_SYMBOL(timer_reset_with_interval),
|
||||
DEFINE_MODULE_SYMBOL(timer_reset),
|
||||
DEFINE_MODULE_SYMBOL(timer_is_running),
|
||||
DEFINE_MODULE_SYMBOL(timer_get_expiry_time),
|
||||
DEFINE_MODULE_SYMBOL(timer_set_pending_callback),
|
||||
DEFINE_MODULE_SYMBOL(timer_set_callback_priority),
|
||||
// error
|
||||
DEFINE_MODULE_SYMBOL(error_to_string),
|
||||
// log
|
||||
#ifndef ESP_PLATFORM
|
||||
DEFINE_MODULE_SYMBOL(log_generic),
|
||||
#endif
|
||||
// module
|
||||
DEFINE_MODULE_SYMBOL(module_construct),
|
||||
DEFINE_MODULE_SYMBOL(module_destruct),
|
||||
DEFINE_MODULE_SYMBOL(module_add),
|
||||
DEFINE_MODULE_SYMBOL(module_remove),
|
||||
DEFINE_MODULE_SYMBOL(module_construct_add_start),
|
||||
DEFINE_MODULE_SYMBOL(module_start),
|
||||
DEFINE_MODULE_SYMBOL(module_stop),
|
||||
DEFINE_MODULE_SYMBOL(module_is_started),
|
||||
DEFINE_MODULE_SYMBOL(module_resolve_symbol),
|
||||
DEFINE_MODULE_SYMBOL(module_resolve_symbol_global),
|
||||
// terminator
|
||||
MODULE_SYMBOL_TERMINATOR
|
||||
};
|
||||
@@ -69,6 +69,14 @@ error_t module_stop(struct Module* module) {
|
||||
return error;
|
||||
}
|
||||
|
||||
error_t module_construct_add_start(struct Module* module) {
|
||||
error_t error = module_construct(module);
|
||||
if (error != ERROR_NONE) return error;
|
||||
error = module_add(module);
|
||||
if (error != ERROR_NONE) return error;
|
||||
return module_start(module);
|
||||
}
|
||||
|
||||
bool module_resolve_symbol(Module* module, const char* symbol_name, uintptr_t* symbol_address) {
|
||||
if (!module_is_started(module)) return false;
|
||||
auto* symbol_ptr = module->symbols;
|
||||
|
||||
Reference in New Issue
Block a user