mirror of
https://github.com/ByteWelder/Tactility.git
synced 2026-04-18 09:25:06 +00:00
Create hal-device module, fix GPIO, fix tests, fix TactilityC (#471)
* **New Features** * Added a HAL device module providing device enumeration, type queries and a HAL↔kernel bridge. * **Improvements** * Integrated HAL module into startup; standardized module names, includes and lifecycle logging; safer file append behavior; broader build support. * **API Changes** * Driver lifecycle now uses explicit add/remove semantics; C and HAL device type/lookup APIs clarified. * **Chores** * Added module README and Apache‑2.0 license; updated build configuration to include the new module. * **Fixes** * Updated tests and object file handling to behave correctly.
This commit is contained in:
parent
5993ceb232
commit
3fe1dc0312
@ -32,6 +32,7 @@ if (DEFINED ENV{ESP_IDF_VERSION})
|
||||
"Firmware"
|
||||
"Devices/${TACTILITY_DEVICE_PROJECT}"
|
||||
"Drivers"
|
||||
"Modules"
|
||||
"Platforms/PlatformEsp32"
|
||||
"TactilityKernel"
|
||||
"Tactility"
|
||||
@ -84,6 +85,7 @@ if (NOT DEFINED ENV{ESP_IDF_VERSION})
|
||||
add_subdirectory(Libraries/QRCode)
|
||||
add_subdirectory(Libraries/minitar)
|
||||
add_subdirectory(Libraries/minmea)
|
||||
add_subdirectory(Modules/hal-device)
|
||||
|
||||
# FreeRTOS
|
||||
set(FREERTOS_CONFIG_FILE_DIRECTORY ${PROJECT_SOURCE_DIR}/Devices/simulator/Source CACHE STRING "")
|
||||
|
||||
@ -36,7 +36,7 @@ static bool initBoot() {
|
||||
|
||||
using namespace tt::hal;
|
||||
|
||||
static std::vector<std::shared_ptr<Device>> createDevices() {
|
||||
static std::vector<std::shared_ptr<tt::hal::Device>> createDevices() {
|
||||
return {
|
||||
createPower(),
|
||||
ButtonControl::createOneButtonControl(0),
|
||||
|
||||
@ -12,7 +12,7 @@ bool initBoot();
|
||||
|
||||
using namespace tt::hal;
|
||||
|
||||
static std::vector<std::shared_ptr<Device>> createDevices() {
|
||||
static std::vector<std::shared_ptr<tt::hal::Device>> createDevices() {
|
||||
return {
|
||||
createPower(),
|
||||
createDisplay(),
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <Tactility/hal/Device.h>
|
||||
#include <tactility/hal/Device.h>
|
||||
#include <Tactility/TactilityCore.h>
|
||||
|
||||
class KeyboardBacklightDevice final : public tt::hal::Device {
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
#include <Tactility/settings/KeyboardSettings.h>
|
||||
#include <Tactility/settings/DisplaySettings.h>
|
||||
#include <Tactility/hal/display/DisplayDevice.h>
|
||||
#include <Tactility/hal/Device.h>
|
||||
#include <tactility/hal/Device.h>
|
||||
#include <Tactility/Logger.h>
|
||||
#include <KeyboardBacklight/KeyboardBacklight.h>
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <Tactility/hal/Device.h>
|
||||
#include <tactility/hal/Device.h>
|
||||
#include <lvgl.h>
|
||||
|
||||
class TrackballDevice : public tt::hal::Device {
|
||||
|
||||
@ -9,7 +9,7 @@ bool initBoot();
|
||||
|
||||
using namespace tt::hal;
|
||||
|
||||
static std::vector<std::shared_ptr<Device>> createDevices() {
|
||||
static std::vector<std::shared_ptr<tt::hal::Device>> createDevices() {
|
||||
return {
|
||||
createPower(),
|
||||
createDisplay(),
|
||||
|
||||
@ -11,7 +11,7 @@ static bool initBoot() {
|
||||
return driver::pwmbacklight::init(LCD_PIN_BACKLIGHT);
|
||||
}
|
||||
|
||||
static std::vector<std::shared_ptr<Device>> createDevices() {
|
||||
static std::vector<std::shared_ptr<tt::hal::Device>> createDevices() {
|
||||
return {
|
||||
createDisplay(),
|
||||
ButtonControl::createTwoButtonControl(35, 0)
|
||||
|
||||
@ -10,7 +10,7 @@ bool initBoot();
|
||||
|
||||
using namespace tt::hal;
|
||||
|
||||
static std::vector<std::shared_ptr<Device>> createDevices() {
|
||||
static std::vector<std::shared_ptr<tt::hal::Device>> createDevices() {
|
||||
return {
|
||||
createDisplay(),
|
||||
createSdCard()
|
||||
|
||||
@ -22,7 +22,7 @@ static DeviceVector createDevices() {
|
||||
auto tca8418 = std::make_shared<Tca8418>(I2C_NUM_0);
|
||||
auto keyboard = std::make_shared<TpagerKeyboard>(tca8418);
|
||||
|
||||
return std::vector<std::shared_ptr<Device>> {
|
||||
return std::vector<std::shared_ptr<tt::hal::Device>> {
|
||||
tca8418,
|
||||
std::make_shared<Bq25896>(I2C_NUM_0),
|
||||
bq27220,
|
||||
|
||||
@ -9,14 +9,14 @@ extern Driver tlora_pager_driver;
|
||||
static error_t start() {
|
||||
/* We crash when construct fails, because if a single driver fails to construct,
|
||||
* there is no guarantee that the previously constructed drivers can be destroyed */
|
||||
check(driver_construct(&tlora_pager_driver) == ERROR_NONE);
|
||||
check(driver_construct_add(&tlora_pager_driver) == ERROR_NONE);
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
static error_t stop() {
|
||||
/* We crash when destruct fails, because if a single driver fails to destruct,
|
||||
* there is no guarantee that the previously destroyed drivers can be recovered */
|
||||
check(driver_destruct(&tlora_pager_driver) == ERROR_NONE);
|
||||
check(driver_remove_destruct(&tlora_pager_driver) == ERROR_NONE);
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
|
||||
@ -28,7 +28,7 @@ static void deinitPower() {
|
||||
#endif
|
||||
}
|
||||
|
||||
static std::vector<std::shared_ptr<Device>> createDevices() {
|
||||
static std::vector<std::shared_ptr<tt::hal::Device>> createDevices() {
|
||||
return {
|
||||
std::make_shared<SdlDisplay>(),
|
||||
std::make_shared<SdlKeyboard>(),
|
||||
|
||||
@ -10,7 +10,7 @@ bool initBoot();
|
||||
|
||||
using namespace tt::hal;
|
||||
|
||||
static std::vector<std::shared_ptr<Device>> createDevices() {
|
||||
static std::vector<std::shared_ptr<tt::hal::Device>> createDevices() {
|
||||
return {
|
||||
createDisplay(),
|
||||
createSdCard()
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
#include "Xpt2046Touch.h"
|
||||
|
||||
#include <Tactility/Logger.h>
|
||||
#include <Tactility/hal/Device.h>
|
||||
#include <tactility/hal/Device.h>
|
||||
|
||||
static const auto LOGGER = tt::Logger("Xpt2046Power");
|
||||
|
||||
|
||||
@ -36,6 +36,7 @@ else ()
|
||||
TactilityCore
|
||||
TactilityFreeRtos
|
||||
TactilityKernel
|
||||
hal-device
|
||||
Simulator
|
||||
PlatformPosix
|
||||
SDL2::SDL2-static SDL2-static
|
||||
|
||||
46
Modules/hal-device/CMakeLists.txt
Normal file
46
Modules/hal-device/CMakeLists.txt
Normal file
@ -0,0 +1,46 @@
|
||||
cmake_minimum_required(VERSION 3.20)
|
||||
|
||||
if (DEFINED ENV{ESP_IDF_VERSION})
|
||||
file(GLOB_RECURSE SOURCE_FILES Source/*.c*)
|
||||
|
||||
list(APPEND REQUIRES_LIST
|
||||
TactilityKernel
|
||||
TactilityCore
|
||||
TactilityFreeRtos
|
||||
)
|
||||
|
||||
idf_component_register(
|
||||
SRCS ${SOURCE_FILES}
|
||||
INCLUDE_DIRS "Include/"
|
||||
REQUIRES ${REQUIRES_LIST}
|
||||
)
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
target_compile_options(${COMPONENT_LIB} PUBLIC -Wno-unused-variable)
|
||||
endif ()
|
||||
|
||||
else ()
|
||||
|
||||
file(GLOB_RECURSE SOURCES "Source/*.c*")
|
||||
|
||||
add_library(hal-device OBJECT)
|
||||
|
||||
target_sources(hal-device PRIVATE ${SOURCES})
|
||||
|
||||
target_include_directories(hal-device
|
||||
PRIVATE Private/
|
||||
PUBLIC Include/
|
||||
)
|
||||
|
||||
add_definitions(-D_Nullable=)
|
||||
add_definitions(-D_Nonnull=)
|
||||
|
||||
target_link_libraries(hal-device PUBLIC
|
||||
TactilityFreeRtos
|
||||
TactilityCore
|
||||
TactilityKernel
|
||||
freertos_kernel
|
||||
)
|
||||
|
||||
endif ()
|
||||
|
||||
28
Modules/hal-device/Include/tactility/drivers/hal_device.h
Normal file
28
Modules/hal-device/Include/tactility/drivers/hal_device.h
Normal file
@ -0,0 +1,28 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum class HalDeviceType {
|
||||
HAL_DEVICE_TYPE_I2C,
|
||||
HAL_DEVICE_TYPE_DISPLAY,
|
||||
HAL_DEVICE_TYPE_TOUCH,
|
||||
HAL_DEVICE_TYPE_SDCARD,
|
||||
HAL_DEVICE_TYPE_KEYBOARD,
|
||||
HAL_DEVICE_TYPE_ENCODER,
|
||||
HAL_DEVICE_TYPE_POWER,
|
||||
HAL_DEVICE_TYPE_GPS,
|
||||
HAL_DEVICE_TYPE_OTHER
|
||||
};
|
||||
|
||||
HalDeviceType hal_device_get_type(struct Device* device);
|
||||
|
||||
void hal_device_for_each_of_type(HalDeviceType type, void* context, bool(*onDevice)(struct Device* device, void* context));
|
||||
|
||||
extern const struct DeviceType HAL_DEVICE_TYPE;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
21
Modules/hal-device/Include/tactility/drivers/hal_device.hpp
Normal file
21
Modules/hal-device/Include/tactility/drivers/hal_device.hpp
Normal file
@ -0,0 +1,21 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
#pragma once
|
||||
|
||||
#include "hal_device.h"
|
||||
|
||||
#include <memory>
|
||||
#include <tactility/hal/Device.h>
|
||||
|
||||
namespace tt::hal {
|
||||
|
||||
/**
|
||||
* @brief Get a tt::hal::Device object from a Kernel device.
|
||||
* @warning The input device must be of type HAL_DEVICE_TYPE
|
||||
* @param kernelDevice The kernel device
|
||||
* @return std::shared_ptr<Device>
|
||||
*/
|
||||
std::shared_ptr<Device> hal_device_get_device(::Device* kernelDevice);
|
||||
|
||||
void hal_device_set_device(::Device* kernelDevice, std::shared_ptr<Device> halDevice);
|
||||
|
||||
}
|
||||
@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
@ -7,6 +8,10 @@
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
|
||||
#include <tactility/device.h>
|
||||
|
||||
typedef ::Device KernelDevice;
|
||||
|
||||
namespace tt::hal {
|
||||
/** Base class for HAL-related devices. */
|
||||
class Device {
|
||||
@ -27,9 +32,19 @@ public:
|
||||
|
||||
typedef uint32_t Id;
|
||||
|
||||
struct KernelDeviceHolder {
|
||||
const std::string name;
|
||||
std::shared_ptr<KernelDevice> device = std::make_shared<KernelDevice>();
|
||||
|
||||
explicit KernelDeviceHolder(std::string name) : name(name) {
|
||||
device->name = this->name.c_str();
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
Id id;
|
||||
std::shared_ptr<KernelDeviceHolder> kernelDeviceHolder;
|
||||
|
||||
public:
|
||||
|
||||
@ -49,6 +64,10 @@ public:
|
||||
* e.g. "USB charging controller with I2C interface."
|
||||
*/
|
||||
virtual std::string getDescription() const = 0;
|
||||
|
||||
void setKernelDeviceHolder(std::shared_ptr<KernelDeviceHolder> kernelDeviceHolder) { this->kernelDeviceHolder = kernelDeviceHolder; }
|
||||
|
||||
std::shared_ptr<KernelDeviceHolder> getKernelDeviceHolder() const { return kernelDeviceHolder; }
|
||||
};
|
||||
|
||||
/**
|
||||
@ -92,7 +111,7 @@ std::vector<std::shared_ptr<DeviceType>> findDevices(Device::Type type) {
|
||||
assert(target_device != nullptr);
|
||||
result.push_back(target_device);
|
||||
}
|
||||
return std::move(result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
12
Modules/hal-device/Include/tactility/hal_device_module.h
Normal file
12
Modules/hal-device/Include/tactility/hal_device_module.h
Normal file
@ -0,0 +1,12 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern struct Module hal_device_module;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
195
Modules/hal-device/LICENSE-Apache-2.0.md
Normal file
195
Modules/hal-device/LICENSE-Apache-2.0.md
Normal file
@ -0,0 +1,195 @@
|
||||
Apache License
|
||||
==============
|
||||
|
||||
_Version 2.0, January 2004_
|
||||
_<<http://www.apache.org/licenses/>>_
|
||||
|
||||
### Terms and Conditions for use, reproduction, and distribution
|
||||
|
||||
#### 1. Definitions
|
||||
|
||||
“License” shall mean the terms and conditions for use, reproduction, and
|
||||
distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
“Licensor” shall mean the copyright owner or entity authorized by the copyright
|
||||
owner that is granting the License.
|
||||
|
||||
“Legal Entity” shall mean the union of the acting entity and all other entities
|
||||
that control, are controlled by, or are under common control with that entity.
|
||||
For the purposes of this definition, “control” means **(i)** the power, direct or
|
||||
indirect, to cause the direction or management of such entity, whether by
|
||||
contract or otherwise, or **(ii)** ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or **(iii)** beneficial ownership of such entity.
|
||||
|
||||
“You” (or “Your”) shall mean an individual or Legal Entity exercising
|
||||
permissions granted by this License.
|
||||
|
||||
“Source” form shall mean the preferred form for making modifications, including
|
||||
but not limited to software source code, documentation source, and configuration
|
||||
files.
|
||||
|
||||
“Object” form shall mean any form resulting from mechanical transformation or
|
||||
translation of a Source form, including but not limited to compiled object code,
|
||||
generated documentation, and conversions to other media types.
|
||||
|
||||
“Work” shall mean the work of authorship, whether in Source or Object form, made
|
||||
available under the License, as indicated by a copyright notice that is included
|
||||
in or attached to the work (an example is provided in the Appendix below).
|
||||
|
||||
“Derivative Works” shall mean any work, whether in Source or Object form, that
|
||||
is based on (or derived from) the Work and for which the editorial revisions,
|
||||
annotations, elaborations, or other modifications represent, as a whole, an
|
||||
original work of authorship. For the purposes of this License, Derivative Works
|
||||
shall not include works that remain separable from, or merely link (or bind by
|
||||
name) to the interfaces of, the Work and Derivative Works thereof.
|
||||
|
||||
“Contribution” shall mean any work of authorship, including the original version
|
||||
of the Work and any modifications or additions to that Work or Derivative Works
|
||||
thereof, that is intentionally submitted to Licensor for inclusion in the Work
|
||||
by the copyright owner or by an individual or Legal Entity authorized to submit
|
||||
on behalf of the copyright owner. For the purposes of this definition,
|
||||
“submitted” means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems, and
|
||||
issue tracking systems that are managed by, or on behalf of, the Licensor for
|
||||
the purpose of discussing and improving the Work, but excluding communication
|
||||
that is conspicuously marked or otherwise designated in writing by the copyright
|
||||
owner as “Not a Contribution.”
|
||||
|
||||
“Contributor” shall mean Licensor and any individual or Legal Entity on behalf
|
||||
of whom a Contribution has been received by Licensor and subsequently
|
||||
incorporated within the Work.
|
||||
|
||||
#### 2. Grant of Copyright License
|
||||
|
||||
Subject to the terms and conditions of this License, each Contributor hereby
|
||||
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
|
||||
irrevocable copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the Work and such
|
||||
Derivative Works in Source or Object form.
|
||||
|
||||
#### 3. Grant of Patent License
|
||||
|
||||
Subject to the terms and conditions of this License, each Contributor hereby
|
||||
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
|
||||
irrevocable (except as stated in this section) patent license to make, have
|
||||
made, use, offer to sell, sell, import, and otherwise transfer the Work, where
|
||||
such license applies only to those patent claims licensable by such Contributor
|
||||
that are necessarily infringed by their Contribution(s) alone or by combination
|
||||
of their Contribution(s) with the Work to which such Contribution(s) was
|
||||
submitted. If You institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work or a
|
||||
Contribution incorporated within the Work constitutes direct or contributory
|
||||
patent infringement, then any patent licenses granted to You under this License
|
||||
for that Work shall terminate as of the date such litigation is filed.
|
||||
|
||||
#### 4. Redistribution
|
||||
|
||||
You may reproduce and distribute copies of the Work or Derivative Works thereof
|
||||
in any medium, with or without modifications, and in Source or Object form,
|
||||
provided that You meet the following conditions:
|
||||
|
||||
* **(a)** You must give any other recipients of the Work or Derivative Works a copy of
|
||||
this License; and
|
||||
* **(b)** You must cause any modified files to carry prominent notices stating that You
|
||||
changed the files; and
|
||||
* **(c)** You must retain, in the Source form of any Derivative Works that You distribute,
|
||||
all copyright, patent, trademark, and attribution notices from the Source form
|
||||
of the Work, excluding those notices that do not pertain to any part of the
|
||||
Derivative Works; and
|
||||
* **(d)** If the Work includes a “NOTICE” text file as part of its distribution, then any
|
||||
Derivative Works that You distribute must include a readable copy of the
|
||||
attribution notices contained within such NOTICE file, excluding those notices
|
||||
that do not pertain to any part of the Derivative Works, in at least one of the
|
||||
following places: within a NOTICE text file distributed as part of the
|
||||
Derivative Works; within the Source form or documentation, if provided along
|
||||
with the Derivative Works; or, within a display generated by the Derivative
|
||||
Works, if and wherever such third-party notices normally appear. The contents of
|
||||
the NOTICE file are for informational purposes only and do not modify the
|
||||
License. You may add Your own attribution notices within Derivative Works that
|
||||
You distribute, alongside or as an addendum to the NOTICE text from the Work,
|
||||
provided that such additional attribution notices cannot be construed as
|
||||
modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and may provide
|
||||
additional or different license terms and conditions for use, reproduction, or
|
||||
distribution of Your modifications, or for any such Derivative Works as a whole,
|
||||
provided Your use, reproduction, and distribution of the Work otherwise complies
|
||||
with the conditions stated in this License.
|
||||
|
||||
#### 5. Submission of Contributions
|
||||
|
||||
Unless You explicitly state otherwise, any Contribution intentionally submitted
|
||||
for inclusion in the Work by You to the Licensor shall be under the terms and
|
||||
conditions of this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify the terms of
|
||||
any separate license agreement you may have executed with Licensor regarding
|
||||
such Contributions.
|
||||
|
||||
#### 6. Trademarks
|
||||
|
||||
This License does not grant permission to use the trade names, trademarks,
|
||||
service marks, or product names of the Licensor, except as required for
|
||||
reasonable and customary use in describing the origin of the Work and
|
||||
reproducing the content of the NOTICE file.
|
||||
|
||||
#### 7. Disclaimer of Warranty
|
||||
|
||||
Unless required by applicable law or agreed to in writing, Licensor provides the
|
||||
Work (and each Contributor provides its Contributions) on an “AS IS” BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
|
||||
including, without limitation, any warranties or conditions of TITLE,
|
||||
NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
|
||||
solely responsible for determining the appropriateness of using or
|
||||
redistributing the Work and assume any risks associated with Your exercise of
|
||||
permissions under this License.
|
||||
|
||||
#### 8. Limitation of Liability
|
||||
|
||||
In no event and under no legal theory, whether in tort (including negligence),
|
||||
contract, or otherwise, unless required by applicable law (such as deliberate
|
||||
and grossly negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special, incidental,
|
||||
or consequential damages of any character arising as a result of this License or
|
||||
out of the use or inability to use the Work (including but not limited to
|
||||
damages for loss of goodwill, work stoppage, computer failure or malfunction, or
|
||||
any and all other commercial damages or losses), even if such Contributor has
|
||||
been advised of the possibility of such damages.
|
||||
|
||||
#### 9. Accepting Warranty or Additional Liability
|
||||
|
||||
While redistributing the Work or Derivative Works thereof, You may choose to
|
||||
offer, and charge a fee for, acceptance of support, warranty, indemnity, or
|
||||
other liability obligations and/or rights consistent with this License. However,
|
||||
in accepting such obligations, You may act only on Your own behalf and on Your
|
||||
sole responsibility, not on behalf of any other Contributor, and only if You
|
||||
agree to indemnify, defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason of your
|
||||
accepting any such warranty or additional liability.
|
||||
|
||||
_END OF TERMS AND CONDITIONS_
|
||||
|
||||
### APPENDIX: How to apply the Apache License to your work
|
||||
|
||||
To apply the Apache License to your work, attach the following boilerplate
|
||||
notice, with the fields enclosed by brackets `[]` replaced with your own
|
||||
identifying information. (Don't include the brackets!) The text should be
|
||||
enclosed in the appropriate comment syntax for the file format. We also
|
||||
recommend that a file or class name and description of purpose be included on
|
||||
the same “printed page” as the copyright notice for easier identification within
|
||||
third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
8
Modules/hal-device/README.md
Normal file
8
Modules/hal-device/README.md
Normal file
@ -0,0 +1,8 @@
|
||||
**WARNING: This module contains deprecated code**
|
||||
|
||||
This module is the basis for the old Tactility HAL.
|
||||
This HAL existed before TactilityKernel.
|
||||
|
||||
The C++ `tt::hal::Device` class is replaced by `struct Device` from TactilityKernel.
|
||||
|
||||
License: Apache v2.0
|
||||
126
Modules/hal-device/Source/drivers/hal_device.cpp
Normal file
126
Modules/hal-device/Source/drivers/hal_device.cpp
Normal file
@ -0,0 +1,126 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
#include <tactility/drivers/hal_device.h>
|
||||
#include <tactility/device.h>
|
||||
#include <tactility/driver.h>
|
||||
|
||||
#include <tactility/log.h>
|
||||
#include <tactility/hal/Device.h>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#define TAG LOG_TAG(HalDevice)
|
||||
|
||||
struct HalDevicePrivate {
|
||||
std::shared_ptr<tt::hal::Device> halDevice;
|
||||
};
|
||||
|
||||
#define GET_DATA(device) ((struct HalDevicePrivate*)device->internal.driver_data)
|
||||
|
||||
static enum HalDeviceType getHalDeviceType(tt::hal::Device::Type type) {
|
||||
switch (type) {
|
||||
case tt::hal::Device::Type::I2c:
|
||||
return HalDeviceType::HAL_DEVICE_TYPE_I2C;
|
||||
case tt::hal::Device::Type::Display:
|
||||
return HalDeviceType::HAL_DEVICE_TYPE_DISPLAY;
|
||||
case tt::hal::Device::Type::Touch:
|
||||
return HalDeviceType::HAL_DEVICE_TYPE_TOUCH;
|
||||
case tt::hal::Device::Type::SdCard:
|
||||
return HalDeviceType::HAL_DEVICE_TYPE_SDCARD;
|
||||
case tt::hal::Device::Type::Keyboard:
|
||||
return HalDeviceType::HAL_DEVICE_TYPE_KEYBOARD;
|
||||
case tt::hal::Device::Type::Encoder:
|
||||
return HalDeviceType::HAL_DEVICE_TYPE_ENCODER;
|
||||
case tt::hal::Device::Type::Power:
|
||||
return HalDeviceType::HAL_DEVICE_TYPE_POWER;
|
||||
case tt::hal::Device::Type::Gps:
|
||||
return HalDeviceType::HAL_DEVICE_TYPE_GPS;
|
||||
case tt::hal::Device::Type::Other:
|
||||
return HalDeviceType::HAL_DEVICE_TYPE_OTHER;
|
||||
default:
|
||||
LOG_W(TAG, "Device type %d is not implemented", static_cast<int>(type));
|
||||
return HalDeviceType::HAL_DEVICE_TYPE_OTHER;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
HalDeviceType hal_device_get_type(struct Device* device) {
|
||||
auto type = GET_DATA(device)->halDevice->getType();
|
||||
return getHalDeviceType(type);
|
||||
}
|
||||
|
||||
void hal_device_for_each_of_type(HalDeviceType type, void* context, bool(*onDevice)(struct Device* device, void* context)) {
|
||||
struct InternalContext {
|
||||
HalDeviceType typeParam;
|
||||
void* contextParam;
|
||||
bool(*onDeviceParam)(struct Device* device, void* context);
|
||||
};
|
||||
|
||||
InternalContext internal_context = {
|
||||
.typeParam = type,
|
||||
.contextParam = context,
|
||||
.onDeviceParam = onDevice
|
||||
};
|
||||
|
||||
for_each_device_of_type(&HAL_DEVICE_TYPE, &internal_context, [](Device* device, void* context){
|
||||
auto* hal_device_private = GET_DATA(device);
|
||||
auto* internal_context = static_cast<InternalContext*>(context);
|
||||
auto hal_device_type = getHalDeviceType(hal_device_private->halDevice->getType());
|
||||
if (hal_device_type == internal_context->typeParam) {
|
||||
if (!internal_context->onDeviceParam(device, internal_context->contextParam)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace tt::hal {
|
||||
|
||||
std::shared_ptr<Device> hal_device_get_device(::Device* device) {
|
||||
auto* hal_device_private = GET_DATA(device);
|
||||
return hal_device_private->halDevice;
|
||||
}
|
||||
|
||||
void hal_device_set_device(::Device* kernelDevice, std::shared_ptr<Device> halDevice) {
|
||||
GET_DATA(kernelDevice)->halDevice = std::move(halDevice);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#pragma region Lifecycle
|
||||
|
||||
static error_t start(Device* device) {
|
||||
LOG_I(TAG, "start %s", device->name);
|
||||
device->internal.driver_data = new HalDevicePrivate();
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
static error_t stop(Device* device) {
|
||||
LOG_I(TAG, "stop %s", device->name);
|
||||
delete GET_DATA(device);
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
extern "C" {
|
||||
|
||||
const struct DeviceType HAL_DEVICE_TYPE {0};
|
||||
|
||||
extern struct Module hal_device_module;
|
||||
|
||||
Driver hal_device_driver = {
|
||||
.name = "hal-device",
|
||||
.compatible = (const char*[]) {"hal-device", nullptr},
|
||||
.startDevice = start,
|
||||
.stopDevice = stop,
|
||||
.api = nullptr,
|
||||
.deviceType = &HAL_DEVICE_TYPE,
|
||||
.owner = &hal_device_module,
|
||||
.driver_private = nullptr
|
||||
};
|
||||
|
||||
}
|
||||
143
Modules/hal-device/Source/hal/Device.cpp
Normal file
143
Modules/hal-device/Source/hal/Device.cpp
Normal file
@ -0,0 +1,143 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
#include <tactility/hal/Device.h>
|
||||
#include <tactility/driver.h>
|
||||
#include <tactility/drivers/hal_device.hpp>
|
||||
|
||||
#include <Tactility/Logger.h>
|
||||
#include <Tactility/RecursiveMutex.h>
|
||||
#include <algorithm>
|
||||
|
||||
namespace tt::hal {
|
||||
|
||||
RecursiveMutex mutex;
|
||||
static Device::Id nextId = 0;
|
||||
|
||||
static const auto LOGGER = Logger("Devices");
|
||||
|
||||
Device::Device() : id(nextId++) {}
|
||||
|
||||
static std::shared_ptr<Device::KernelDeviceHolder> createKernelDeviceHolder(const std::shared_ptr<Device>& device) {
|
||||
auto kernel_device_name = std::format("hal-device-{}", device->getId());
|
||||
LOGGER.info("Registering {} with id {} as kernel device {}", device->getName(), device->getId(), kernel_device_name);
|
||||
auto kernel_device_holder = std::make_shared<Device::KernelDeviceHolder>(kernel_device_name);
|
||||
auto* kernel_device = kernel_device_holder->device.get();
|
||||
check(device_construct(kernel_device) == ERROR_NONE);
|
||||
check(device_add(kernel_device) == ERROR_NONE);
|
||||
auto* driver = driver_find_compatible("hal-device");
|
||||
check(driver);
|
||||
device_set_driver(kernel_device, driver);
|
||||
check(device_start(kernel_device) == ERROR_NONE);
|
||||
hal_device_set_device(kernel_device, device);
|
||||
return kernel_device_holder;
|
||||
}
|
||||
|
||||
static void destroyKernelDeviceHolder(std::shared_ptr<Device::KernelDeviceHolder>& holder) {
|
||||
auto kernel_device = holder->device.get();
|
||||
hal_device_set_device(kernel_device, nullptr);
|
||||
check(device_stop(kernel_device) == ERROR_NONE);
|
||||
check(device_remove(kernel_device) == ERROR_NONE);
|
||||
check(device_destruct(kernel_device) == ERROR_NONE);
|
||||
holder->device = nullptr;
|
||||
}
|
||||
|
||||
void registerDevice(const std::shared_ptr<Device>& device) {
|
||||
auto scoped_mutex = mutex.asScopedLock();
|
||||
scoped_mutex.lock();
|
||||
|
||||
if (device->getKernelDeviceHolder() == nullptr) {
|
||||
// Kernel device
|
||||
auto kernel_device_holder = createKernelDeviceHolder(device);
|
||||
device->setKernelDeviceHolder(kernel_device_holder);
|
||||
} else {
|
||||
LOGGER.warn("Device {} with id {} was already registered", device->getName(), device->getId());
|
||||
}
|
||||
}
|
||||
|
||||
void deregisterDevice(const std::shared_ptr<Device>& device) {
|
||||
auto scoped_mutex = mutex.asScopedLock();
|
||||
scoped_mutex.lock();
|
||||
|
||||
// Kernel device
|
||||
auto kernel_device_holder = device->getKernelDeviceHolder();
|
||||
if (kernel_device_holder) {
|
||||
destroyKernelDeviceHolder(kernel_device_holder);
|
||||
device->setKernelDeviceHolder(nullptr);
|
||||
} else {
|
||||
LOGGER.warn("Device {} with id {} was not registered", device->getName(), device->getId());
|
||||
}
|
||||
}
|
||||
|
||||
template<typename R>
|
||||
auto toVector(R&& range) {
|
||||
using T = std::ranges::range_value_t<R>;
|
||||
std::vector<T> result;
|
||||
if constexpr (std::ranges::common_range<R>) {
|
||||
result.reserve(std::ranges::distance(range));
|
||||
}
|
||||
std::ranges::copy(range, std::back_inserter(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<Device>> findDevices(const std::function<bool(const std::shared_ptr<Device>&)>& filterFunction) {
|
||||
auto scoped_mutex = mutex.asScopedLock();
|
||||
scoped_mutex.lock();
|
||||
|
||||
auto devices_view = getDevices() | std::views::filter([&filterFunction](auto& device) {
|
||||
return filterFunction(device);
|
||||
});
|
||||
return toVector(devices_view);
|
||||
}
|
||||
|
||||
std::shared_ptr<Device> _Nullable findDevice(const std::function<bool(const std::shared_ptr<Device>&)>& filterFunction) {
|
||||
auto scoped_mutex = mutex.asScopedLock();
|
||||
scoped_mutex.lock();
|
||||
|
||||
auto result_set = getDevices() | std::views::filter([&filterFunction](auto& device) {
|
||||
return filterFunction(device);
|
||||
});
|
||||
if (!result_set.empty()) {
|
||||
return result_set.front();
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<Device> _Nullable findDevice(std::string name) {
|
||||
return findDevice([&name](auto& device){
|
||||
return device->getName() == name;
|
||||
});
|
||||
}
|
||||
|
||||
std::shared_ptr<Device> _Nullable findDevice(Device::Id id) {
|
||||
return findDevice([id](auto& device){
|
||||
return device->getId() == id;
|
||||
});
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<Device>> findDevices(Device::Type type) {
|
||||
return findDevices([type](auto& device) {
|
||||
return device->getType() == type;
|
||||
});
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<Device>> getDevices() {
|
||||
std::vector<std::shared_ptr<Device>> devices;
|
||||
for_each_device_of_type(&HAL_DEVICE_TYPE, &devices ,[](auto* kernelDevice, auto* context) {
|
||||
auto devices_ptr = static_cast<std::vector<std::shared_ptr<Device>>*>(context);
|
||||
auto hal_device = hal_device_get_device(kernelDevice);
|
||||
(*devices_ptr).push_back(hal_device);
|
||||
return true;
|
||||
});
|
||||
return devices;
|
||||
}
|
||||
|
||||
bool hasDevice(Device::Type type) {
|
||||
auto scoped_mutex = mutex.asScopedLock();
|
||||
scoped_mutex.lock();
|
||||
auto result_set = getDevices() | std::views::filter([&type](auto& device) {
|
||||
return device->getType() == type;
|
||||
});
|
||||
return !result_set.empty();
|
||||
}
|
||||
|
||||
}
|
||||
31
Modules/hal-device/Source/module.cpp
Normal file
31
Modules/hal-device/Source/module.cpp
Normal file
@ -0,0 +1,31 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
#include <tactility/check.h>
|
||||
#include <tactility/driver.h>
|
||||
#include <tactility/module.h>
|
||||
|
||||
extern "C" {
|
||||
|
||||
extern Driver hal_device_driver;
|
||||
|
||||
static error_t start() {
|
||||
/* We crash when construct fails, because if a single driver fails to construct,
|
||||
* there is no guarantee that the previously constructed drivers can be destroyed */
|
||||
check(driver_construct_add(&hal_device_driver) == ERROR_NONE);
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
static error_t stop() {
|
||||
/* We crash when destruct fails, because if a single driver fails to destruct,
|
||||
* there is no guarantee that the previously destroyed drivers can be recovered */
|
||||
check(driver_remove(&hal_device_driver) == ERROR_NONE);
|
||||
check(driver_destruct(&hal_device_driver) == ERROR_NONE);
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
struct Module hal_device_module = {
|
||||
.name = "hal-device",
|
||||
.start = start,
|
||||
.stop = stop
|
||||
};
|
||||
|
||||
}
|
||||
@ -11,7 +11,7 @@
|
||||
|
||||
#define TAG LOG_TAG(esp32_gpio)
|
||||
|
||||
#define GET_CONFIG(device) ((struct Esp32GpioConfig*)device->internal.driver_data)
|
||||
#define GET_CONFIG(device) ((struct Esp32GpioConfig*)device->config)
|
||||
|
||||
extern "C" {
|
||||
|
||||
|
||||
@ -10,22 +10,22 @@ extern Driver esp32_i2c_driver;
|
||||
static error_t start() {
|
||||
/* We crash when construct fails, because if a single driver fails to construct,
|
||||
* there is no guarantee that the previously constructed drivers can be destroyed */
|
||||
check(driver_construct(&esp32_gpio_driver) == ERROR_NONE);
|
||||
check(driver_construct(&esp32_i2c_driver) == ERROR_NONE);
|
||||
check(driver_construct_add(&esp32_gpio_driver) == ERROR_NONE);
|
||||
check(driver_construct_add(&esp32_i2c_driver) == ERROR_NONE);
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
static error_t stop() {
|
||||
/* We crash when destruct fails, because if a single driver fails to destruct,
|
||||
* there is no guarantee that the previously destroyed drivers can be recovered */
|
||||
check(driver_destruct(&esp32_gpio_driver) == ERROR_NONE);
|
||||
check(driver_destruct(&esp32_i2c_driver) == ERROR_NONE);
|
||||
check(driver_remove_destruct(&esp32_gpio_driver) == ERROR_NONE);
|
||||
check(driver_remove_destruct(&esp32_i2c_driver) == ERROR_NONE);
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
// The name must be exactly "platform_module"
|
||||
struct Module platform_module = {
|
||||
.name = "ESP32 Platform",
|
||||
.name = "platform-esp32",
|
||||
.start = start,
|
||||
.stop = stop
|
||||
};
|
||||
|
||||
@ -14,7 +14,7 @@ static error_t stop() {
|
||||
|
||||
// The name must be exactly "platform_module"
|
||||
struct Module platform_module = {
|
||||
.name = "POSIX Platform",
|
||||
.name = "platform-posix",
|
||||
.start = start,
|
||||
.stop = stop
|
||||
};
|
||||
|
||||
@ -8,6 +8,7 @@ if (DEFINED ENV{ESP_IDF_VERSION})
|
||||
PlatformEsp32
|
||||
TactilityCore
|
||||
TactilityFreeRtos
|
||||
hal-device
|
||||
lvgl
|
||||
driver
|
||||
elf_loader
|
||||
@ -71,6 +72,7 @@ else()
|
||||
TactilityCore
|
||||
TactilityKernel
|
||||
PlatformPosix
|
||||
hal-device
|
||||
freertos_kernel
|
||||
lvgl
|
||||
lv_screenshot
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "../Device.h"
|
||||
#include <tactility/hal/Device.h>
|
||||
|
||||
#include <lvgl.h>
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "../Device.h"
|
||||
#include <tactility/hal/Device.h>
|
||||
|
||||
#include <lvgl.h>
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "../Device.h"
|
||||
#include <tactility/hal/Device.h>
|
||||
#include "GpsConfiguration.h"
|
||||
#include "Satellites.h"
|
||||
|
||||
@ -110,7 +110,7 @@ public:
|
||||
return lastRmcSubscriptionId;
|
||||
}
|
||||
|
||||
void unsubscribeRmc(GgaSubscriptionId subscriptionId) {
|
||||
void unsubscribeRmc(RmcSubscriptionId subscriptionId) {
|
||||
auto lock = mutex.asScopedLock();
|
||||
lock.lock();
|
||||
std::erase_if(rmcSubscriptions, [subscriptionId](auto& subscription) { return subscription.id == subscriptionId; });
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "../Device.h"
|
||||
#include <tactility/hal/Device.h>
|
||||
#include "I2c.h"
|
||||
|
||||
namespace tt::hal::i2c {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "../Device.h"
|
||||
#include <tactility/hal/Device.h>
|
||||
|
||||
#include <lvgl.h>
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "../Device.h"
|
||||
#include <tactility/hal/Device.h>
|
||||
#include <cstdint>
|
||||
|
||||
namespace tt::hal::power {
|
||||
@ -44,4 +44,4 @@ public:
|
||||
virtual void powerOff() { /* NO-OP*/ }
|
||||
};
|
||||
|
||||
} // namespace tt
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "../Device.h"
|
||||
#include <tactility/hal/Device.h>
|
||||
|
||||
#include <Tactility/TactilityCore.h>
|
||||
#include <Tactility/Lock.h>
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
#include "SdCardDevice.h"
|
||||
|
||||
#include <Tactility/RecursiveMutex.h>
|
||||
#include <Tactility/hal/Device.h>
|
||||
#include <tactility/hal/Device.h>
|
||||
#include <Tactility/hal/spi/Spi.h>
|
||||
#include <sd_protocol_types.h>
|
||||
#include <soc/gpio_num.h>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "../Device.h"
|
||||
#include <tactility/hal/Device.h>
|
||||
#include "TouchDriver.h"
|
||||
|
||||
#include <lvgl.h>
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#include "Tactility/MountPoints.h"
|
||||
|
||||
#include "Tactility/TactilityConfig.h"
|
||||
#include "Tactility/hal/Device.h"
|
||||
#include <tactility/hal/Device.h>
|
||||
#include "Tactility/hal/sdcard/SdCardDevice.h"
|
||||
|
||||
#include <Tactility/file/File.h>
|
||||
|
||||
@ -23,6 +23,7 @@
|
||||
#include <Tactility/settings/TimePrivate.h>
|
||||
|
||||
#include <tactility/kernel_init.h>
|
||||
#include <tactility/hal_device_module.h>
|
||||
|
||||
#include <map>
|
||||
#include <format>
|
||||
@ -38,6 +39,11 @@ static auto LOGGER = Logger("Tactility");
|
||||
static const Configuration* config_instance = nullptr;
|
||||
static Dispatcher mainDispatcher;
|
||||
|
||||
struct ModuleParent tactility_module_parent {
|
||||
"tactility",
|
||||
nullptr
|
||||
};
|
||||
|
||||
// region Default services
|
||||
namespace service {
|
||||
// Primary
|
||||
@ -330,6 +336,11 @@ void run(const Configuration& config, Module* platformModule, Module* deviceModu
|
||||
return;
|
||||
}
|
||||
|
||||
// HAL compatibility module: it creates kernel driver wrappers for tt::hal::Device
|
||||
check(module_parent_construct(&tactility_module_parent) == ERROR_NONE);
|
||||
check(module_set_parent(&hal_device_module, &tactility_module_parent) == ERROR_NONE);
|
||||
check(module_start(&hal_device_module) == ERROR_NONE);
|
||||
|
||||
const hal::Configuration& hardware = *config.hardware;
|
||||
|
||||
// Assign early so starting services can use it
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
#include <Tactility/file/File.h>
|
||||
#include <Tactility/file/FileLock.h>
|
||||
#include <Tactility/file/PropertiesFile.h>
|
||||
#include <Tactility/hal/Device.h>
|
||||
#include <tactility/hal/Device.h>
|
||||
#include <Tactility/Logger.h>
|
||||
#include <Tactility/Paths.h>
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
#include <Tactility/app/crashdiagnostics/QrHelpers.h>
|
||||
#include <Tactility/app/crashdiagnostics/QrUrl.h>
|
||||
#include <Tactility/app/launcher/Launcher.h>
|
||||
#include <Tactility/hal/Device.h>
|
||||
#include <tactility/hal/Device.h>
|
||||
#include <Tactility/Logger.h>
|
||||
#include <Tactility/lvgl/Statusbar.h>
|
||||
#include <Tactility/service/loader/Loader.h>
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
#include <Tactility/hal/power/PowerDevice.h>
|
||||
#include <Tactility/Timer.h>
|
||||
#include <Tactility/Assets.h>
|
||||
#include <Tactility/hal/Device.h>
|
||||
#include <tactility/hal/Device.h>
|
||||
|
||||
#include <lvgl.h>
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
#include <Tactility/lvgl/LvglSync.h>
|
||||
|
||||
#include <Tactility/Assets.h>
|
||||
#include <Tactility/hal/Device.h>
|
||||
#include <tactility/hal/Device.h>
|
||||
#include <Tactility/Tactility.h>
|
||||
#include <Tactility/Timer.h>
|
||||
|
||||
|
||||
@ -16,7 +16,7 @@ bool ObjectFileWriter::open() {
|
||||
}
|
||||
|
||||
// Edit existing or create a new file
|
||||
auto opening_file = std::unique_ptr<FILE, FileCloser>(std::fopen(filePath.c_str(), "wb"));
|
||||
auto opening_file = std::unique_ptr<FILE, FileCloser>(std::fopen(filePath.c_str(), edit_existing ? "rb+" : "wb"));
|
||||
if (opening_file == nullptr) {
|
||||
LOGGER.error("Failed to open file {}", filePath);
|
||||
return false;
|
||||
|
||||
@ -1,106 +0,0 @@
|
||||
#include <Tactility/hal/Device.h>
|
||||
|
||||
#include <Tactility/Logger.h>
|
||||
#include <Tactility/RecursiveMutex.h>
|
||||
#include <algorithm>
|
||||
|
||||
namespace tt::hal {
|
||||
|
||||
std::vector<std::shared_ptr<Device>> devices;
|
||||
RecursiveMutex mutex;
|
||||
static Device::Id nextId = 0;
|
||||
|
||||
static const auto LOGGER = Logger("Devices");
|
||||
|
||||
Device::Device() : id(nextId++) {}
|
||||
|
||||
template <std::ranges::range RangeType>
|
||||
auto toVector(RangeType&& range) {
|
||||
auto view = range | std::views::common;
|
||||
return std::vector(view.begin(), view.end());
|
||||
}
|
||||
|
||||
void registerDevice(const std::shared_ptr<Device>& device) {
|
||||
auto scoped_mutex = mutex.asScopedLock();
|
||||
scoped_mutex.lock();
|
||||
|
||||
if (findDevice(device->getId()) == nullptr) {
|
||||
devices.push_back(device);
|
||||
LOGGER.info("Registered {} with id {}", device->getName(), device->getId());
|
||||
} else {
|
||||
LOGGER.warn("Device {} with id {} was already registered", device->getName(), device->getId());
|
||||
}
|
||||
}
|
||||
|
||||
void deregisterDevice(const std::shared_ptr<Device>& device) {
|
||||
auto scoped_mutex = mutex.asScopedLock();
|
||||
scoped_mutex.lock();
|
||||
|
||||
auto id_to_remove = device->getId();
|
||||
auto remove_iterator = std::remove_if(devices.begin(), devices.end(), [id_to_remove](const auto& device) {
|
||||
return device->getId() == id_to_remove;
|
||||
});
|
||||
if (remove_iterator != devices.end()) {
|
||||
LOGGER.info("Deregistering {} with id {}", device->getName(), device->getId());
|
||||
devices.erase(remove_iterator);
|
||||
} else {
|
||||
LOGGER.warn("Deregistering {} with id {} failed: not found", device->getName(), device->getId());
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<Device>> findDevices(const std::function<bool(const std::shared_ptr<Device>&)>& filterFunction) {
|
||||
auto scoped_mutex = mutex.asScopedLock();
|
||||
scoped_mutex.lock();
|
||||
|
||||
auto devices_view = devices | std::views::filter([&filterFunction](auto& device) {
|
||||
return filterFunction(device);
|
||||
});
|
||||
return toVector(devices_view);
|
||||
}
|
||||
|
||||
std::shared_ptr<Device> _Nullable findDevice(const std::function<bool(const std::shared_ptr<Device>&)>& filterFunction) {
|
||||
auto scoped_mutex = mutex.asScopedLock();
|
||||
scoped_mutex.lock();
|
||||
|
||||
auto result_set = devices | std::views::filter([&filterFunction](auto& device) {
|
||||
return filterFunction(device);
|
||||
});
|
||||
if (!result_set.empty()) {
|
||||
return result_set.front();
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<Device> _Nullable findDevice(std::string name) {
|
||||
return findDevice([&name](auto& device){
|
||||
return device->getName() == name;
|
||||
});
|
||||
}
|
||||
|
||||
std::shared_ptr<Device> _Nullable findDevice(Device::Id id) {
|
||||
return findDevice([id](auto& device){
|
||||
return device->getId() == id;
|
||||
});
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<Device>> findDevices(Device::Type type) {
|
||||
return findDevices([type](auto& device) {
|
||||
return device->getType() == type;
|
||||
});
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<Device>> getDevices() {
|
||||
return devices;
|
||||
}
|
||||
|
||||
bool hasDevice(Device::Type type) {
|
||||
auto scoped_mutex = mutex.asScopedLock();
|
||||
scoped_mutex.lock();
|
||||
auto result_set = devices | std::views::filter([&type](auto& device) {
|
||||
return device->getType() == type;
|
||||
});
|
||||
return !result_set.empty();
|
||||
}
|
||||
|
||||
}
|
||||
@ -2,7 +2,7 @@
|
||||
#include <Tactility/Tactility.h>
|
||||
#include <tactility/check.h>
|
||||
#include <Tactility/hal/Configuration.h>
|
||||
#include <Tactility/hal/Device.h>
|
||||
#include <tactility/hal/Device.h>
|
||||
#include <Tactility/hal/power/PowerDevice.h>
|
||||
#include <Tactility/hal/spi/SpiInit.h>
|
||||
#include <Tactility/hal/uart/UartInit.h>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
#include "Tactility/hal/Device.h"
|
||||
#include <tactility/hal/Device.h>
|
||||
#include "Tactility/hal/sdcard/SdCardDevice.h"
|
||||
|
||||
namespace tt::hal::sdcard {
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
|
||||
#include <Tactility/Tactility.h>
|
||||
#include <Tactility/TactilityConfig.h>
|
||||
#include <Tactility/hal/Device.h>
|
||||
#include <tactility/hal/Device.h>
|
||||
#include <Tactility/app/AppRegistration.h>
|
||||
#include <Tactility/app/AppManifest.h>
|
||||
#include <Tactility/app/App.h>
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#include <Tactility/settings/DisplaySettings.h>
|
||||
|
||||
#include <Tactility/file/PropertiesFile.h>
|
||||
#include <Tactility/hal/Device.h>
|
||||
#include <tactility/hal/Device.h>
|
||||
#include <Tactility/hal/display/DisplayDevice.h>
|
||||
|
||||
#include <map>
|
||||
|
||||
@ -15,7 +15,7 @@ typedef enum {
|
||||
DEVICE_TYPE_KEYBOARD,
|
||||
DEVICE_TYPE_POWER,
|
||||
DEVICE_TYPE_GPS
|
||||
} DeviceType;
|
||||
} TtDeviceType;
|
||||
|
||||
typedef uint32_t DeviceId;
|
||||
|
||||
@ -27,7 +27,7 @@ typedef uint32_t DeviceId;
|
||||
* @param[in] maxCount the maximum number of items that the "deviceIds" output can contain (minimum value is 1)
|
||||
* @return true if one or more devices were found
|
||||
*/
|
||||
bool tt_hal_device_find(DeviceType type, DeviceId* deviceIds, uint16_t* count, uint16_t maxCount);
|
||||
bool tt_hal_device_find(TtDeviceType type, DeviceId* deviceIds, uint16_t* count, uint16_t maxCount);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@ -2,9 +2,9 @@
|
||||
|
||||
#include <tactility/check.h>
|
||||
|
||||
#include <Tactility/hal/Device.h>
|
||||
#include <tactility/hal/Device.h>
|
||||
|
||||
static tt::hal::Device::Type toTactilityDeviceType(DeviceType type) {
|
||||
static tt::hal::Device::Type toTactilityDeviceType(TtDeviceType type) {
|
||||
switch (type) {
|
||||
case DEVICE_TYPE_I2C:
|
||||
return tt::hal::Device::Type::I2c;
|
||||
@ -27,7 +27,7 @@ static tt::hal::Device::Type toTactilityDeviceType(DeviceType type) {
|
||||
|
||||
extern "C" {
|
||||
|
||||
bool tt_hal_device_find(DeviceType type, DeviceId* deviceIds, uint16_t* count, uint16_t maxCount) {
|
||||
bool tt_hal_device_find(TtDeviceType type, DeviceId* deviceIds, uint16_t* count, uint16_t maxCount) {
|
||||
assert(maxCount > 0);
|
||||
|
||||
int16_t currentIndex = -1;
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
#include <tactility/check.h>
|
||||
|
||||
#include <Tactility/hal/Device.h>
|
||||
#include <tactility/hal/Device.h>
|
||||
#include <Tactility/hal/display/DisplayDevice.h>
|
||||
#include <Tactility/hal/display/DisplayDriver.h>
|
||||
|
||||
|
||||
@ -24,7 +24,7 @@ bool tt_hal_gpio_get_level(GpioPin pin) {
|
||||
Device* device_result = find_first_gpio_controller();
|
||||
if (device_result == nullptr) return false;
|
||||
bool pin_state = false;
|
||||
if (!gpio_controller_get_level(device_result, pin, &pin_state)) return false;
|
||||
if (gpio_controller_get_level(device_result, pin, &pin_state) != ERROR_NONE) return false;
|
||||
return pin_state;
|
||||
}
|
||||
|
||||
@ -32,7 +32,7 @@ int tt_hal_gpio_get_pin_count() {
|
||||
Device* device_result = find_first_gpio_controller();
|
||||
if (device_result == nullptr) return 0;
|
||||
uint32_t pin_count = 0;
|
||||
if (!gpio_controller_get_pin_count(device_result, &pin_count)) return 0;
|
||||
if (gpio_controller_get_pin_count(device_result, &pin_count) != ERROR_NONE) return 0;
|
||||
return (int)pin_count;
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
#include "tt_hal_touch.h"
|
||||
|
||||
#include "Tactility/hal/Device.h"
|
||||
#include <tactility/hal/Device.h>
|
||||
#include "Tactility/hal/touch/TouchDevice.h"
|
||||
#include "Tactility/hal/touch/TouchDriver.h"
|
||||
|
||||
|
||||
@ -4,5 +4,10 @@
|
||||
#include "RTOS.h"
|
||||
|
||||
#ifndef ESP_PLATFORM
|
||||
#define xPortInIsrContext(x) (false)
|
||||
|
||||
// TactilityKernel co-existence check
|
||||
#ifndef xPortInIsrContext
|
||||
#define xPortInIsrContext() (false)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@ -37,6 +37,14 @@ error_t driver_construct(struct Driver* driver);
|
||||
|
||||
error_t driver_destruct(struct Driver* driver);
|
||||
|
||||
error_t driver_add(struct Driver* driver);
|
||||
|
||||
error_t driver_remove(struct Driver* driver);
|
||||
|
||||
error_t driver_construct_add(struct Driver* driver);
|
||||
|
||||
error_t driver_remove_destruct(struct Driver* driver);
|
||||
|
||||
error_t driver_bind(struct Driver* driver, struct Device* device);
|
||||
|
||||
error_t driver_unbind(struct Driver* driver, struct Device* device);
|
||||
|
||||
@ -5,6 +5,15 @@
|
||||
#include "freertos.h"
|
||||
|
||||
#ifndef ESP_PLATFORM
|
||||
|
||||
// TactilityFreeRTOS co-existence check
|
||||
#ifndef xPortInIsrContext
|
||||
#define xPortInIsrContext() (pdFALSE)
|
||||
#endif
|
||||
|
||||
// TactilityFreeRTOS co-existence check
|
||||
#ifndef vPortAssertIfInISR
|
||||
#define vPortAssertIfInISR()
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@ -11,8 +11,8 @@ extern "C" {
|
||||
/**
|
||||
* Initialize the kernel with platform and device modules, and a device tree.
|
||||
* @param platform_module The platform module to start. This module should not be constructed yet.
|
||||
* @param device_module The device module to start. This module should not be constructed yet.
|
||||
* @param devicetree_devices The list of generated devices from the devicetree. The array must be terminated by an entry { NULL, NULL }
|
||||
* @param device_module The device module to start. This module should not be constructed yet. This parameter can be NULL.
|
||||
* @param devicetree_devices The list of generated devices from the devicetree. The array must be terminated by an entry { NULL, NULL }. This parameter can be NULL.
|
||||
* @return ERROR_NONE on success, otherwise an error code
|
||||
*/
|
||||
error_t kernel_init(struct Module* platform_module, struct Module* device_module, struct CompatibleDevice devicetree_devices[]);
|
||||
|
||||
@ -17,6 +17,8 @@ struct Module {
|
||||
/**
|
||||
* The name of the module, for logging/debugging purposes
|
||||
* Should never be NULL.
|
||||
* Characters allowed: a-z A-Z 0-9 - _ .
|
||||
* Desirable format "platform-esp32", "lilygo-tdeck", etc.
|
||||
*/
|
||||
const char* name;
|
||||
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
#include <cstdlib>
|
||||
#include <tactility/freertos/task.h>
|
||||
#include <tactility/log.h>
|
||||
|
||||
@ -31,7 +32,7 @@ __attribute__((noreturn)) void __crash(void) {
|
||||
#ifdef ESP_PLATFORM
|
||||
esp_system_abort("System halted. Connect debugger for more info.");
|
||||
#else
|
||||
while (true) { /* Indefinite lock-up */ }
|
||||
exit(1);
|
||||
#endif
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
@ -49,7 +49,7 @@ error_t device_construct(Device* device) {
|
||||
if (device->internal.device_private == nullptr) {
|
||||
return ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
LOG_I(TAG, "construct %s", device->name);
|
||||
LOG_D(TAG, "construct %s", device->name);
|
||||
mutex_construct(&device->internal.mutex);
|
||||
return ERROR_NONE;
|
||||
}
|
||||
@ -61,7 +61,7 @@ error_t device_destruct(Device* device) {
|
||||
if (!get_device_private(device)->children.empty()) {
|
||||
return ERROR_INVALID_STATE;
|
||||
}
|
||||
LOG_I(TAG, "destruct %s", device->name);
|
||||
LOG_D(TAG, "destruct %s", device->name);
|
||||
mutex_destruct(&device->internal.mutex);
|
||||
delete get_device_private(device);
|
||||
device->internal.device_private = nullptr;
|
||||
@ -88,7 +88,7 @@ static void device_remove_child(struct Device* device, struct Device* child) {
|
||||
}
|
||||
|
||||
error_t device_add(Device* device) {
|
||||
LOG_I(TAG, "add %s", device->name);
|
||||
LOG_D(TAG, "add %s", device->name);
|
||||
|
||||
// Already added
|
||||
if (device->internal.state.started || device->internal.state.added) {
|
||||
@ -111,7 +111,7 @@ error_t device_add(Device* device) {
|
||||
}
|
||||
|
||||
error_t device_remove(Device* device) {
|
||||
LOG_I(TAG, "remove %s", device->name);
|
||||
LOG_D(TAG, "remove %s", device->name);
|
||||
|
||||
if (device->internal.state.started || !device->internal.state.added) {
|
||||
return ERROR_INVALID_STATE;
|
||||
|
||||
@ -58,28 +58,6 @@ static DriverLedger& get_ledger() {
|
||||
#define driver_lock(driver) mutex_lock(&get_driver_private(driver)->mutex);
|
||||
#define driver_unlock(driver) mutex_unlock(&get_driver_private(driver)->mutex);
|
||||
|
||||
static void driver_add(Driver* driver) {
|
||||
LOG_I(TAG, "add %s", driver->name);
|
||||
ledger.lock();
|
||||
ledger.drivers.push_back(driver);
|
||||
ledger.unlock();
|
||||
}
|
||||
|
||||
static error_t driver_remove(Driver* driver) {
|
||||
LOG_I(TAG, "remove %s", driver->name);
|
||||
|
||||
ledger.lock();
|
||||
const auto iterator = std::ranges::find(ledger.drivers, driver);
|
||||
if (iterator == ledger.drivers.end()) {
|
||||
ledger.unlock();
|
||||
return ERROR_NOT_FOUND;
|
||||
}
|
||||
ledger.drivers.erase(iterator);
|
||||
ledger.unlock();
|
||||
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
error_t driver_construct(Driver* driver) {
|
||||
@ -87,7 +65,6 @@ error_t driver_construct(Driver* driver) {
|
||||
if (driver->driver_private == nullptr) {
|
||||
return ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
driver_add(driver);
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
@ -104,10 +81,6 @@ error_t driver_destruct(Driver* driver) {
|
||||
}
|
||||
get_driver_private(driver)->destroying = true;
|
||||
|
||||
if (driver_remove(driver) != ERROR_NONE) {
|
||||
LOG_W(TAG, "Failed to remove driver from ledger: %s", driver->name);
|
||||
}
|
||||
|
||||
driver_unlock(driver);
|
||||
delete get_driver_private(driver);
|
||||
driver->driver_private = nullptr;
|
||||
@ -115,6 +88,41 @@ error_t driver_destruct(Driver* driver) {
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
error_t driver_add(Driver* driver) {
|
||||
LOG_I(TAG, "add %s", driver->name);
|
||||
ledger.lock();
|
||||
ledger.drivers.push_back(driver);
|
||||
ledger.unlock();
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
error_t driver_remove(Driver* driver) {
|
||||
LOG_I(TAG, "remove %s", driver->name);
|
||||
|
||||
ledger.lock();
|
||||
const auto iterator = std::ranges::find(ledger.drivers, driver);
|
||||
if (iterator == ledger.drivers.end()) {
|
||||
ledger.unlock();
|
||||
return ERROR_NOT_FOUND;
|
||||
}
|
||||
ledger.drivers.erase(iterator);
|
||||
ledger.unlock();
|
||||
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
error_t driver_construct_add(struct Driver* driver) {
|
||||
if (driver_construct(driver) != ERROR_NONE) return ERROR_RESOURCE;
|
||||
if (driver_add(driver) != ERROR_NONE) return ERROR_RESOURCE;
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
error_t driver_remove_destruct(struct Driver* driver) {
|
||||
if (driver_remove(driver) != ERROR_NONE) return ERROR_RESOURCE;
|
||||
if (driver_destruct(driver) != ERROR_NONE) return ERROR_RESOURCE;
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
bool driver_is_compatible(Driver* driver, const char* compatible) {
|
||||
if (compatible == nullptr || driver->compatible == nullptr) {
|
||||
return false;
|
||||
|
||||
@ -14,7 +14,7 @@ struct ModuleParent kernel_module_parent = {
|
||||
|
||||
static error_t init_kernel_drivers() {
|
||||
extern Driver root_driver;
|
||||
if (driver_construct(&root_driver) != ERROR_NONE) return ERROR_RESOURCE;
|
||||
if (driver_construct_add(&root_driver) != ERROR_NONE) return ERROR_RESOURCE;
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
@ -37,19 +37,23 @@ error_t kernel_init(struct Module* platform_module, struct Module* device_module
|
||||
return ERROR_RESOURCE;
|
||||
}
|
||||
|
||||
module_set_parent(device_module, &kernel_module_parent);
|
||||
if (module_start(device_module) != ERROR_NONE) {
|
||||
LOG_E(TAG, "init failed to start device module");
|
||||
return ERROR_RESOURCE;
|
||||
}
|
||||
|
||||
CompatibleDevice* compatible_device = devicetree_devices;
|
||||
while (compatible_device->device != nullptr) {
|
||||
if (device_construct_add_start(compatible_device->device, compatible_device->compatible) != ERROR_NONE) {
|
||||
LOG_E(TAG, "kernel_init failed to construct device: %s (%s)", compatible_device->device->name, compatible_device->compatible);
|
||||
if (device_module != nullptr) {
|
||||
module_set_parent(device_module, &kernel_module_parent);
|
||||
if (module_start(device_module) != ERROR_NONE) {
|
||||
LOG_E(TAG, "init failed to start device module");
|
||||
return ERROR_RESOURCE;
|
||||
}
|
||||
compatible_device++;
|
||||
}
|
||||
|
||||
if (devicetree_devices) {
|
||||
CompatibleDevice* compatible_device = devicetree_devices;
|
||||
while (compatible_device->device != nullptr) {
|
||||
if (device_construct_add_start(compatible_device->device, compatible_device->compatible) != ERROR_NONE) {
|
||||
LOG_E(TAG, "kernel_init failed to construct device: %s (%s)", compatible_device->device->name, compatible_device->compatible);
|
||||
return ERROR_RESOURCE;
|
||||
}
|
||||
compatible_device++;
|
||||
}
|
||||
}
|
||||
|
||||
LOG_I(TAG, "init done");
|
||||
|
||||
@ -3,6 +3,8 @@
|
||||
#include <tactility/concurrent/mutex.h>
|
||||
#include <tactility/module.h>
|
||||
|
||||
#define TAG LOG_TAG(module)
|
||||
|
||||
struct ModuleParentPrivate {
|
||||
std::vector<struct Module*> modules;
|
||||
struct Mutex mutex = { 0 };
|
||||
@ -72,6 +74,8 @@ error_t module_set_parent(struct Module* module, struct ModuleParent* parent) {
|
||||
}
|
||||
|
||||
error_t module_start(struct Module* module) {
|
||||
LOG_I(TAG, "start %s", module->name);
|
||||
|
||||
if (module->internal.started) return ERROR_NONE;
|
||||
if (!module->internal.parent) return ERROR_INVALID_STATE;
|
||||
|
||||
@ -85,6 +89,8 @@ bool module_is_started(struct Module* module) {
|
||||
}
|
||||
|
||||
error_t module_stop(struct Module* module) {
|
||||
LOG_I(TAG, "stop %s", module->name);
|
||||
|
||||
if (!module->internal.started) return ERROR_NONE;
|
||||
|
||||
error_t error = module->stop();
|
||||
|
||||
@ -22,6 +22,8 @@ target_link_libraries(TactilityTests PRIVATE
|
||||
Tactility
|
||||
TactilityCore
|
||||
TactilityKernel
|
||||
PlatformPosix
|
||||
hal-device
|
||||
Simulator
|
||||
SDL2::SDL2-static SDL2-static
|
||||
)
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#include "doctest.h"
|
||||
#include <Tactility/hal/Device.h>
|
||||
#include <tactility/hal/Device.h>
|
||||
|
||||
#include <utility>
|
||||
|
||||
|
||||
@ -5,12 +5,27 @@
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
#include <tactility/kernel_init.h>
|
||||
#include <tactility/hal_device_module.h>
|
||||
|
||||
typedef struct {
|
||||
int argc;
|
||||
char** argv;
|
||||
int result;
|
||||
} TestTaskData;
|
||||
|
||||
extern "C" {
|
||||
// From the relevant platform
|
||||
extern struct Module platform_module;
|
||||
// From the relevant device
|
||||
extern struct Module device_module;
|
||||
}
|
||||
|
||||
struct ModuleParent tactility_tests_module_parent {
|
||||
"tactility-tests",
|
||||
nullptr
|
||||
};
|
||||
|
||||
void test_task(void* parameter) {
|
||||
auto* data = (TestTaskData*)parameter;
|
||||
|
||||
@ -21,6 +36,12 @@ void test_task(void* parameter) {
|
||||
// overrides
|
||||
context.setOption("no-breaks", true); // don't break in the debugger when assertions fail
|
||||
|
||||
check(kernel_init(&platform_module, &device_module, nullptr) == ERROR_NONE);
|
||||
// HAL compatibility module: it creates kernel driver wrappers for tt::hal::Device
|
||||
check(module_parent_construct(&tactility_tests_module_parent) == ERROR_NONE);
|
||||
check(module_set_parent(&hal_device_module, &tactility_tests_module_parent) == ERROR_NONE);
|
||||
check(module_start(&hal_device_module) == ERROR_NONE);
|
||||
|
||||
data->result = context.run();
|
||||
|
||||
vTaskEndScheduler();
|
||||
@ -46,4 +67,6 @@ int main(int argc, char** argv) {
|
||||
assert(task_result == pdPASS);
|
||||
|
||||
vTaskStartScheduler();
|
||||
|
||||
return data.result;
|
||||
}
|
||||
|
||||
@ -56,8 +56,10 @@ TEST_CASE("Appending records to a file") {
|
||||
CHECK_EQ(reader.open(), true);
|
||||
CHECK_EQ(reader.hasNext(), true);
|
||||
CHECK_EQ(reader.readNext(&record_in), true);
|
||||
CHECK_EQ(record_in.value, 0xAAAAAAAA);
|
||||
CHECK_EQ(reader.hasNext(), true);
|
||||
CHECK_EQ(reader.readNext(&record_in), true);
|
||||
CHECK_EQ(record_in.value, 0xBBBBBBBB);
|
||||
CHECK_EQ(reader.hasNext(), false);
|
||||
reader.close();
|
||||
|
||||
|
||||
@ -11,4 +11,8 @@ target_include_directories(TactilityKernelTests PRIVATE ${DOCTESTINC})
|
||||
|
||||
add_test(NAME TactilityKernelTests COMMAND TactilityKernelTests)
|
||||
|
||||
target_link_libraries(TactilityKernelTests PUBLIC TactilityKernel)
|
||||
target_link_libraries(TactilityKernelTests PUBLIC
|
||||
TactilityKernel
|
||||
PlatformPosix
|
||||
hal-device
|
||||
)
|
||||
|
||||
@ -177,7 +177,7 @@ TEST_CASE("device_is_ready should return true only when it is started") {
|
||||
|
||||
Device device = { 0 };
|
||||
|
||||
CHECK_EQ(driver_construct(&driver), ERROR_NONE);
|
||||
CHECK_EQ(driver_construct_add(&driver), ERROR_NONE);
|
||||
CHECK_EQ(device_construct(&device), ERROR_NONE);
|
||||
|
||||
CHECK_EQ(device.internal.state.started, false);
|
||||
@ -192,6 +192,6 @@ TEST_CASE("device_is_ready should return true only when it is started") {
|
||||
CHECK_EQ(device_remove(&device), ERROR_NONE);
|
||||
CHECK_EQ(device.internal.state.started, false);
|
||||
|
||||
CHECK_EQ(driver_destruct(&driver), ERROR_NONE);
|
||||
CHECK_EQ(device_destruct(&device), ERROR_NONE);
|
||||
CHECK_EQ(driver_remove_destruct(&driver), ERROR_NONE);
|
||||
}
|
||||
|
||||
@ -55,7 +55,7 @@ TEST_CASE("driver with with start success and stop success should start and stop
|
||||
.parent = nullptr,
|
||||
};
|
||||
|
||||
CHECK_EQ(driver_construct(&integration_driver), ERROR_NONE);
|
||||
CHECK_EQ(driver_construct_add(&integration_driver), ERROR_NONE);
|
||||
|
||||
CHECK_EQ(device_construct(&integration_device), ERROR_NONE);
|
||||
device_add(&integration_device);
|
||||
@ -68,5 +68,5 @@ TEST_CASE("driver with with start success and stop success should start and stop
|
||||
CHECK_EQ(device_remove(&integration_device), ERROR_NONE);
|
||||
CHECK_EQ(device_destruct(&integration_device), ERROR_NONE);
|
||||
|
||||
CHECK_EQ(driver_destruct(&integration_driver), ERROR_NONE);
|
||||
CHECK_EQ(driver_remove_destruct(&integration_driver), ERROR_NONE);
|
||||
}
|
||||
|
||||
@ -14,7 +14,9 @@ TEST_CASE("driver_construct and driver_destruct should set and unset the correct
|
||||
driver.owner = &module;
|
||||
|
||||
CHECK_EQ(driver_construct(&driver), ERROR_NONE);
|
||||
CHECK_EQ(driver_add(&driver), ERROR_NONE);
|
||||
CHECK_NE(driver.driver_private, nullptr);
|
||||
CHECK_EQ(driver_remove(&driver), ERROR_NONE);
|
||||
CHECK_EQ(driver_destruct(&driver), ERROR_NONE);
|
||||
CHECK_EQ(driver.driver_private, nullptr);
|
||||
}
|
||||
@ -62,10 +64,12 @@ TEST_CASE("driver_find should only find a compatible driver when the driver was
|
||||
CHECK_EQ(found_driver, nullptr);
|
||||
|
||||
CHECK_EQ(driver_construct(&driver), ERROR_NONE);
|
||||
CHECK_EQ(driver_add(&driver), ERROR_NONE);
|
||||
|
||||
found_driver = driver_find_compatible("test_compatible");
|
||||
CHECK_EQ(found_driver, &driver);
|
||||
|
||||
CHECK_EQ(driver_remove(&driver), ERROR_NONE);
|
||||
CHECK_EQ(driver_destruct(&driver), ERROR_NONE);
|
||||
|
||||
found_driver = driver_find_compatible("test_compatible");
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
#include <cassert>
|
||||
|
||||
#include <tactility/freertos/task.h>
|
||||
#include <tactility/kernel_init.h>
|
||||
|
||||
typedef struct {
|
||||
int argc;
|
||||
@ -10,6 +11,11 @@ typedef struct {
|
||||
int result;
|
||||
} TestTaskData;
|
||||
|
||||
extern "C" {
|
||||
// From the relevant platform
|
||||
extern struct Module platform_module;
|
||||
}
|
||||
|
||||
void test_task(void* parameter) {
|
||||
auto* data = (TestTaskData*)parameter;
|
||||
|
||||
@ -20,6 +26,8 @@ void test_task(void* parameter) {
|
||||
// overrides
|
||||
context.setOption("no-breaks", true); // don't break in the debugger when assertions fail
|
||||
|
||||
check(kernel_init(&platform_module, nullptr, nullptr) == ERROR_NONE);
|
||||
|
||||
data->result = context.run();
|
||||
|
||||
vTaskEndScheduler();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user