Add TactilityFreeRtos to TactilitySDK (#441)

- TactlitySDK updates fro TactilityFreeRtos
- Enable auto-uploading of SDKs to the CDN when merging code
This commit is contained in:
Ken Van Hoeylandt 2026-01-03 16:28:07 +01:00 committed by GitHub
parent 7283920def
commit 524b197105
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 261 additions and 80 deletions

View File

@ -6,10 +6,10 @@ runs:
- name: 'Download artifacts'
uses: actions/download-artifact@v4
with:
path: firmwares
path: artifacts
- name: 'Upload Artifact'
uses: actions/upload-artifact@v4
with:
name: 'all-firmwares'
path: firmwares/
name: 'all-artifacts'
path: artifacts/
retention-days: 3

View File

@ -8,17 +8,17 @@ inputs:
runs:
using: 'composite'
steps:
- name: 'Download all-firmwares'
- name: 'Download all-artifacts'
uses: actions/download-artifact@v4
with:
name: 'all-firmwares'
path: firmwares
name: 'all-artifacts'
path: artifacts
- name: 'Install boto3'
shell: bash
run: pip install boto3
- name: 'Generate files'
shell: bash
run: version=`cat version.txt` && python Buildscripts/CDN/generate-files.py firmwares firmwares-cdn $version
run: version=`cat version.txt` && python Buildscripts/CDN/generate-firmware-files.py artifacts artifacts-cdn $version
- name: 'Upload files'
shell: bash
run: python Buildscripts/CDN/upload-files.py firmwares-cdn ${{ inputs.cdn_version }} ${{ env.CDN_ID }} ${{ env.CDN_TOKEN_NAME }} ${{ env.CDN_TOKEN_VALUE }}
run: python Buildscripts/CDN/upload-firmware-files.py artifacts-cdn ${{ inputs.cdn_version }} ${{ env.CDN_ID }} ${{ env.CDN_TOKEN_NAME }} ${{ env.CDN_TOKEN_VALUE }}

19
.github/actions/publish-sdk/action.yml vendored Normal file
View File

@ -0,0 +1,19 @@
name: Publish SDK
runs:
using: 'composite'
steps:
- name: 'Download all-artifacts'
uses: actions/download-artifact@v4
with:
name: 'all-artifacts'
path: artifacts
- name: 'Install boto3'
shell: bash
run: pip install boto3
- name: 'Generate files'
shell: bash
run: version=`cat version.txt` && python Buildscripts/CDN/generate-sdk-files.py artifacts artifacts-cdn $version
- name: 'Upload files'
shell: bash
run: version=`cat version.txt` && python Buildscripts/CDN/upload-sdk-files.py artifacts-cdn $version ${{ env.CDN_ID }} ${{ env.CDN_TOKEN_NAME }} ${{ env.CDN_TOKEN_VALUE }}

View File

@ -78,7 +78,7 @@ jobs:
with:
board_id: ${{ matrix.board.id }}
arch: ${{ matrix.board.arch }}
BundleFirmware:
BundleArtifacts:
runs-on: ubuntu-latest
needs: [ BuildFirmware ]
if: |
@ -86,11 +86,11 @@ jobs:
(github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v'))
steps:
- uses: actions/checkout@v4
- name: "Bundle Firmware"
uses: ./.github/actions/bundle-firmware
- name: "Bundle Artifacts"
uses: ./.github/actions/bundle-artifacts
PublishFirmwareSnapshot:
runs-on: ubuntu-latest
needs: [ BundleFirmware ]
needs: [ BundleArtifacts ]
if: (github.event_name == 'push' && github.ref == 'refs/heads/main')
steps:
- uses: actions/checkout@v4
@ -104,7 +104,7 @@ jobs:
cdn_version: snapshot
PublishFirmwareStable:
runs-on: ubuntu-latest
needs: [ BundleFirmware ]
needs: [ BundleArtifacts ]
if: (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v'))
steps:
- uses: actions/checkout@v4
@ -116,3 +116,15 @@ jobs:
uses: ./.github/actions/publish-firmware
with:
cdn_version: stable
PublishSdk:
runs-on: ubuntu-latest
needs: [ BundleArtifacts ]
if: (github.event_name == 'push' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')))
steps:
- uses: actions/checkout@v4
- name: "Publish SDKs"
env:
CDN_ID: ${{ secrets.CDN_ID }}
CDN_TOKEN_NAME: ${{ secrets.CDN_TOKEN_NAME }}
CDN_TOKEN_VALUE: ${{ secrets.CDN_TOKEN_VALUE }}
uses: ./.github/actions/publish-sdk

View File

@ -45,11 +45,6 @@ class DeviceIndex:
gitCommit: str
devices: list
if sys.platform == "win32":
shell_color_red = ""
shell_color_orange = ""
shell_color_reset = ""
else:
shell_color_red = "\033[91m"
shell_color_orange = "\033[93m"
shell_color_reset = "\033[m"
@ -61,7 +56,7 @@ def print_error(message):
print(f"{shell_color_red}ERROR: {message}{shell_color_reset}")
def print_help():
print("Usage: python generate-files.py [inPath] [outPath] [version]")
print("Usage: python generate-firmware-files.py [inPath] [outPath] [version]")
print(" inPath path with the extracted release files")
print(" outPath path where the CDN files will become available")
print(" version technical version name (e.g. 1.2.0)")
@ -228,7 +223,7 @@ if __name__ == "__main__":
# Argument validation
if len(sys.argv) < 4:
print_help()
sys.exit()
sys.exit(1)
if "--verbose" in sys.argv:
VERBOSE = True
sys.argv.remove("--verbose")

View File

@ -0,0 +1,86 @@
import subprocess
from datetime import datetime, UTC
import os
import sys
from dataclasses import dataclass, asdict
import json
import shutil
VERBOSE = False
@dataclass
class SdkIndex:
version: str
created: str
gitCommit: str
platforms: dict
shell_color_red = "\033[91m"
shell_color_orange = "\033[93m"
shell_color_reset = "\033[m"
def print_warning(message):
print(f"{shell_color_orange}WARNING: {message}{shell_color_reset}")
def print_error(message):
print(f"{shell_color_red}ERROR: {message}{shell_color_reset}")
def exit_with_error(message):
print_error(message)
sys.exit(1)
def print_help():
print("Usage: python generate-sdk-files.py [inPath] [outPath] [version]")
print(" inPath path with the extracted release files")
print(" outPath path where the CDN files will become available")
print(" version technical version name (e.g. 1.2.0)")
print("Options:")
print(" --verbose Show extra console output")
def get_git_commit_hash():
return subprocess.check_output(['git', 'rev-parse', 'HEAD']).decode('ascii').strip()
def main(in_path: str, out_path: str, version: str):
if not os.path.exists(in_path):
exit_with_error(f"Input path not found: {in_path}")
if os.path.exists(out_path):
shutil.rmtree(out_path)
os.mkdir(out_path)
artifact_directories = os.listdir(in_path)
sdk_index = SdkIndex(
version=version,
created=datetime.now(UTC).strftime('%Y-%m-%dT%H:%M:%S'),
gitCommit=get_git_commit_hash(),
platforms={}
)
for artifact_directory in artifact_directories:
if VERBOSE:
print(f"Processing {in_path}/{artifact_directory}")
if not artifact_directory.startswith("TactilitySDK-"):
continue
sdk_platform = artifact_directory.removeprefix("TactilitySDK-")
if not sdk_platform:
exit_with_error(f"Cannot derive platform from directory name: {artifact_directory}")
sdk_index.platforms[sdk_platform] = f"{artifact_directory}.zip"
if VERBOSE:
print(f"Archiving {in_path}/{artifact_directory} to {out_path}/{artifact_directory}.zip")
shutil.make_archive(os.path.join(out_path, artifact_directory), 'zip', os.path.join(in_path, artifact_directory))
index_file_path = os.path.join(out_path, "index.json")
if VERBOSE:
print(f"Generating {index_file_path}")
with open(index_file_path, "w") as index_file:
json.dump(asdict(sdk_index), index_file, indent=2)
if __name__ == "__main__":
print("Tactility CDN SDK File Generator")
if "--help" in sys.argv:
print_help()
sys.exit()
# Argument validation
if len(sys.argv) < 4:
print_help()
sys.exit(1)
if "--verbose" in sys.argv:
VERBOSE = True
sys.argv.remove("--verbose")
main(in_path=sys.argv[1], out_path=sys.argv[2], version=sys.argv[3])

View File

@ -2,11 +2,6 @@ import os
import sys
import boto3
if sys.platform == "win32":
SHELL_COLOR_RED = ""
SHELL_COLOR_ORANGE = ""
SHELL_COLOR_RESET = ""
else:
SHELL_COLOR_RED = "\033[91m"
SHELL_COLOR_ORANGE = "\033[93m"
SHELL_COLOR_RESET = "\033[m"
@ -18,7 +13,7 @@ def print_error(message):
print(f"{SHELL_COLOR_RED}ERROR: {message}{SHELL_COLOR_RESET}")
def print_help():
print("Usage: python upload-files.py [path] [version] [cloudflareAccountId] [cloudflareTokenName] [cloudflareTokenValue]")
print("Usage: python upload-firmware-files.py [path] [version] [cloudflareAccountId] [cloudflareTokenName] [cloudflareTokenValue]")
print("")
print("Options:")
print(" --index-only Upload only index.json")
@ -52,14 +47,14 @@ def main(path: str, version: str, cloudflare_account_id, cloudflare_token_name:
counter += 1
if __name__ == "__main__":
print("Tactility CDN Uploader")
print("Tactility CDN Firmware Uploader")
if "--help" in sys.argv:
print_help()
sys.exit()
# Argument validation
if len(sys.argv) < 6:
print_help()
sys.exit()
sys.exit(1)
main(
path=sys.argv[1],
version=sys.argv[2],

View File

@ -0,0 +1,65 @@
import os
import sys
import boto3
SHELL_COLOR_RED = "\033[91m"
SHELL_COLOR_ORANGE = "\033[93m"
SHELL_COLOR_RESET = "\033[m"
def print_warning(message):
print(f"{SHELL_COLOR_ORANGE}WARNING: {message}{SHELL_COLOR_RESET}")
def print_error(message):
print(f"{SHELL_COLOR_RED}ERROR: {message}{SHELL_COLOR_RESET}")
def print_help():
print("Usage: python upload-sdk-files.py [path] [version] [cloudflareAccountId] [cloudflareTokenName] [cloudflareTokenValue]")
print("")
print("Options:")
print(" --index-only Upload only index.json")
def exit_with_error(message):
print_error(message)
sys.exit(1)
def main(path: str, version: str, cloudflare_account_id, cloudflare_token_name: str, cloudflare_token_value: str, index_only: bool):
if not os.path.exists(path):
exit_with_error(f"Path not found: {path}")
s3 = boto3.client(
service_name="s3",
endpoint_url=f"https://{cloudflare_account_id}.r2.cloudflarestorage.com",
aws_access_key_id=cloudflare_token_name,
aws_secret_access_key=cloudflare_token_value,
region_name="auto"
)
files_to_upload = os.listdir(path)
counter = 1
total = len(files_to_upload)
for file_name in files_to_upload:
if not index_only or file_name == 'index.json':
object_path = f"sdk/{version}/{file_name}"
print(f"[{counter}/{total}] Uploading {file_name} to {object_path}")
file_path = os.path.join(path, file_name)
try:
s3.upload_file(file_path, "tactility", object_path)
except Exception as e:
exit_with_error(f"Failed to upload {file_name}: {str(e)}")
counter += 1
if __name__ == "__main__":
print("Tactility CDN SDK Uploader")
if "--help" in sys.argv:
print_help()
sys.exit()
# Argument validation
if len(sys.argv) < 6:
print_help()
sys.exit(1)
main(
path=sys.argv[1],
version=sys.argv[2],
cloudflare_account_id=sys.argv[3],
cloudflare_token_name=sys.argv[4],
cloudflare_token_value=sys.argv[5],
index_only="--index-only" in sys.argv
)

View File

@ -1,5 +1,6 @@
idf_component_register(
INCLUDE_DIRS "Libraries/TactilityC/Include" "Libraries/lvgl/Include"
INCLUDE_DIRS "Libraries/TactilityC/Include" "Libraries/lvgl/Include" "Libraries/TactilityFreeRtos/Include"
REQUIRES esp_timer
)
add_prebuilt_library(TactilityC Libraries/TactilityC/Binary/libTactilityC.a)

View File

@ -8,20 +8,12 @@ else ()
set(TACTILITY_TARGET " @ Simulator")
endif ()
if (NOT WIN32)
string(ASCII 27 Esc)
set(ColorReset "${Esc}[m")
set(Cyan "${Esc}[36m")
set(Grey "${Esc}[37m")
set(LightPurple "${Esc}[1;35m")
set(White "${Esc}[1;37m")
else ()
set(ColorReset "")
set(Cyan "")
set(Grey "")
set(LightPurple "")
set(White "")
endif ()
# Some terminals (e.g. GitHub Actions) reset colour for every in a multiline message(),
# so we add the colour to each line instead of assuming it would automatically be re-used.

View File

@ -24,6 +24,13 @@ find_target_dir=$build_dir/$tactility_library_path/Include/
cp TactilityC/Include/* $find_target_dir
cp Documentation/license-tactilitysdk.md $build_dir/$tactility_library_path/LICENSE.md
# TactilityFreeRtos
tactilityfreertos_library_path=$library_path/TactilityFreeRtos
mkdir -p $tactilityfreertos_library_path/Include
find_target_dir=$build_dir/$tactilityfreertos_library_path/Include/
cp -r TactilityFreeRtos/Include/* $find_target_dir
cp Documentation/license-tactilitysdk.md $build_dir/$tactilityfreertos_library_path/LICENSE.md
# lvgl
lvgl_library_path=$library_path/lvgl
mkdir -p $lvgl_library_path/Binary

View File

@ -1,21 +1,14 @@
cmake_minimum_required(VERSION 3.20)
add_definitions(-DTT_DEBUG)
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_ASM_COMPILE_OBJECT "${CMAKE_CXX_COMPILER_TARGET}")
include("Buildscripts/logo.cmake")
if (NOT WIN32)
string(ASCII 27 Esc)
set(ColorReset "${Esc}[m")
set(Cyan "${Esc}[36m")
else ()
set(ColorReset "")
set(Cyan "")
endif ()
file(READ version.txt TACTILITY_VERSION)
add_compile_definitions(TT_VERSION="${TACTILITY_VERSION}")
@ -77,19 +70,16 @@ if (NOT DEFINED ENV{ESP_IDF_VERSION})
add_subdirectory(TactilityCore)
add_subdirectory(TactilityFreeRtos)
add_subdirectory(Devices/simulator)
endif ()
if (NOT DEFINED ENV{ESP_IDF_VERSION})
# FreeRTOS
set(FREERTOS_CONFIG_FILE_DIRECTORY ${PROJECT_SOURCE_DIR}/Devices/simulator/Source CACHE STRING "")
set(FREERTOS_PORT GCC_POSIX CACHE STRING "")
add_subdirectory(Libraries/cJSON)
add_subdirectory(Libraries/FreeRTOS-Kernel)
add_subdirectory(Libraries/lv_screenshot)
add_subdirectory(Libraries/QRCode)
add_subdirectory(Libraries/minitar)
add_subdirectory(Libraries/minmea)
# FreeRTOS
set(FREERTOS_CONFIG_FILE_DIRECTORY ${PROJECT_SOURCE_DIR}/Devices/simulator/Source CACHE STRING "")
set(FREERTOS_PORT GCC_POSIX CACHE STRING "")
add_subdirectory(Libraries/FreeRTOS-Kernel)
target_compile_definitions(freertos_kernel PUBLIC "projCOVERAGE_TEST=0")
target_include_directories(freertos_kernel
PUBLIC Devices/Simulator/Source # for FreeRTOSConfig.h

View File

@ -3,12 +3,20 @@
#include <symbols/freertos.h>
#include <Tactility/freertoscompat/RTOS.h>
#include <freertos/task.h>
#include <freertos/FreeRTOS.h>
#include <freertos/event_groups.h>
#include <freertos/queue.h>
#include <freertos/semphr.h>
#include <freertos/task.h>
#include <freertos/timers.h>
const esp_elfsym freertos_symbols[] = {
// Task
ESP_ELFSYM_EXPORT(uxTaskGetStackHighWaterMark),
ESP_ELFSYM_EXPORT(uxTaskGetNumberOfTasks),
ESP_ELFSYM_EXPORT(uxTaskGetTaskNumber),
ESP_ELFSYM_EXPORT(uxTaskPriorityGet),
ESP_ELFSYM_EXPORT(uxTaskPriorityGetFromISR),
ESP_ELFSYM_EXPORT(vTaskDelay),
ESP_ELFSYM_EXPORT(vTaskDelete),
ESP_ELFSYM_EXPORT(vTaskDeleteWithCaps),
@ -28,13 +36,10 @@ const esp_elfsym freertos_symbols[] = {
ESP_ELFSYM_EXPORT(xTaskDelayUntil),
ESP_ELFSYM_EXPORT(xTaskGenericNotify),
ESP_ELFSYM_EXPORT(xTaskGenericNotifyFromISR),
ESP_ELFSYM_EXPORT(xTaskGetTickCount),
ESP_ELFSYM_EXPORT(xTaskGetTickCountFromISR),
ESP_ELFSYM_EXPORT(pvTaskGetThreadLocalStoragePointer),
ESP_ELFSYM_EXPORT(pvTaskIncrementMutexHeldCount),
ESP_ELFSYM_EXPORT(uxTaskGetStackHighWaterMark),
ESP_ELFSYM_EXPORT(uxTaskGetNumberOfTasks),
ESP_ELFSYM_EXPORT(uxTaskGetTaskNumber),
ESP_ELFSYM_EXPORT(uxTaskPriorityGet),
ESP_ELFSYM_EXPORT(uxTaskPriorityGetFromISR),
// EventGroup
ESP_ELFSYM_EXPORT(xEventGroupCreate),
ESP_ELFSYM_EXPORT(xEventGroupCreateWithCaps),
@ -49,11 +54,6 @@ const esp_elfsym freertos_symbols[] = {
ESP_ELFSYM_EXPORT(xEventGroupSync),
ESP_ELFSYM_EXPORT(xEventGroupWaitBits),
// Queue
ESP_ELFSYM_EXPORT(xQueueGenericCreate),
ESP_ELFSYM_EXPORT(xQueueGenericCreateStatic),
ESP_ELFSYM_EXPORT(xQueueGenericReset),
ESP_ELFSYM_EXPORT(xQueueGenericSend),
ESP_ELFSYM_EXPORT(xQueueGenericSendFromISR),
ESP_ELFSYM_EXPORT(vQueueDelete),
ESP_ELFSYM_EXPORT(vQueueDeleteWithCaps),
ESP_ELFSYM_EXPORT(vQueueSetQueueNumber),
@ -62,6 +62,21 @@ const esp_elfsym freertos_symbols[] = {
ESP_ELFSYM_EXPORT(uxQueueMessagesWaiting),
ESP_ELFSYM_EXPORT(uxQueueMessagesWaitingFromISR),
ESP_ELFSYM_EXPORT(uxQueueSpacesAvailable),
ESP_ELFSYM_EXPORT(xQueueCreateCountingSemaphore),
ESP_ELFSYM_EXPORT(xQueueCreateCountingSemaphoreStatic),
ESP_ELFSYM_EXPORT(xQueueCreateMutex),
ESP_ELFSYM_EXPORT(xQueueCreateMutexStatic),
ESP_ELFSYM_EXPORT(xQueueCreateSet),
ESP_ELFSYM_EXPORT(xQueueGetMutexHolder),
ESP_ELFSYM_EXPORT(xQueueGetMutexHolderFromISR),
ESP_ELFSYM_EXPORT(xQueueGiveMutexRecursive),
ESP_ELFSYM_EXPORT(xQueueTakeMutexRecursive),
ESP_ELFSYM_EXPORT(xQueueGenericCreate),
ESP_ELFSYM_EXPORT(xQueueGenericCreateStatic),
ESP_ELFSYM_EXPORT(xQueueGenericReset),
ESP_ELFSYM_EXPORT(xQueueGenericSend),
ESP_ELFSYM_EXPORT(xQueueGenericSendFromISR),
ESP_ELFSYM_EXPORT(xQueueSemaphoreTake),
// Timer
ESP_ELFSYM_EXPORT(xTimerCreate),
ESP_ELFSYM_EXPORT(xTimerCreateStatic),
@ -72,6 +87,9 @@ const esp_elfsym freertos_symbols[] = {
ESP_ELFSYM_EXPORT(xTimerPendFunctionCallFromISR),
ESP_ELFSYM_EXPORT(xTimerGetPeriod),
// portmacro.h
ESP_ELFSYM_EXPORT(vPortYield),
ESP_ELFSYM_EXPORT(vPortEnterCritical),
ESP_ELFSYM_EXPORT(vPortExitCritical),
ESP_ELFSYM_EXPORT(xPortInIsrContext),
ESP_ELFSYM_EXPORT(xPortCanYield),
ESP_ELFSYM_EXPORT(xPortGetCoreID),

View File

@ -11,6 +11,7 @@ const esp_elfsym stl_symbols[] = {
{ "_ZSt28__throw_bad_array_new_lengthv", (void*)&(std::__throw_bad_array_new_length) },
{ "_ZSt25__throw_bad_function_callv", (void*)&(std::__throw_bad_function_call) },
{ "_ZSt20__throw_length_errorPKc", (void*)&(std::__throw_length_error) },
{ "_ZSt19__throw_logic_errorPKc", (void*)&std::__throw_logic_error },
// { "", (void*)&(std::) },
// delimiter
ESP_ELFSYM_END