11 Commits

Author SHA1 Message Date
Kuba Szczodrzyński
fbaae21011 [release] v1.6.0
Some checks failed
Release / Run Clang lint (push) Has been cancelled
Release / Publish PlatformIO platform (push) Has been cancelled
Release / Publish GitHub release (push) Has been cancelled
2024-05-31 15:01:17 +02:00
Jaco Malan
fa2064b957 [realtek-ambz] Temporarily workaround CHANGE interrupts not supported (#282)
* fix change interruptsnot supported on rtl8710b

* Update cores/realtek-amb/arduino/src/wiring_irq.c

---------

Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>
2024-05-31 14:59:46 +02:00
Kuba Szczodrzyński
21a194f43d [core] Fix lwIP debugging support 2024-05-31 14:58:38 +02:00
devgs
b255402659 [beken-72xx] Fix race condition when checking Wi-Fi SSID (#274)
* Fix for a race condition in WiFi connection loop

There seems to be the race between the event RW_EVT_STA_CONNECTED
and an actual valid SSID value returned by BDK. If even a small delay
is injected immediately after the event reception the valid value
becomes available. Without this fix, due to a polling nature of ESPHome
WiFiComponent::check_connecting_finished function may observe the
WiFiSTAConnectStatus::CONNECTED status but with an empty SSID value,
leading to `Incomplete connection.` warning and immediate attempt to
start another connection, while the current one was actually established.

* Fixed clang format conformance

* Apply suggestions from code review

* Update cores/beken-72xx/arduino/libraries/WiFi/WiFiEvents.cpp

Co-authored-by: Cossid <83468485+Cossid@users.noreply.github.com>

---------

Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>
Co-authored-by: Cossid <83468485+Cossid@users.noreply.github.com>
2024-05-31 14:54:41 +02:00
Kuba Szczodrzyński
dfabfbb921 [beken-72xx] Increase MBEDTLS_ENTROPY_MAX_SOURCES 2024-05-18 13:50:25 +02:00
Kuba Szczodrzyński
3b36a70c9a [core] Fix ESP_LOG#() macro syntax 2024-05-18 13:50:10 +02:00
Piotr Szulc
d1386a8e9d [libs] Fix mDNS string memory corruption, print error on record add failure (#260)
* Fixed unsafe conversion to underscore string

* Fixed formatting

* Save one byte if underscore not needed

* Don't allocate new string if already underscored

* Fix missing first character while copying

* Renamed function and made it inline

* Don't use signed index variable when searching for service

* Add proper cleanup of LwIPmDNS

- Free allocated memory both on end() and in the destructor
- Unregister callback from netif

* Don't free const pointer

* Removed unneeded casting

* Don't break the loop if failed to add txt record

* Fixed code formatting
2024-03-08 12:21:14 +01:00
Kuba Szczodrzyński
67b92b7f56 [release] v1.5.1
Some checks failed
Release / Run Clang lint (push) Has been cancelled
Release / Publish PlatformIO platform (push) Has been cancelled
Release / Publish GitHub release (push) Has been cancelled
2024-02-29 14:14:01 +01:00
Hajo Noerenberg
a1f8516e60 [realtek-ambz] Fix crash after WiFi scan (#258) 2024-02-26 21:35:35 +01:00
cap9qd
cf52021d38 [core] Split reboot reasons due to wakeup (#254)
* Updates to break out wakeup reasons.

Per https://github.com/libretiny-eu/libretiny/issues/234

* Update cores/common/base/api/lt_device.h

Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>

* fix clang-format

* Fix formatting of python files.

* Update lt_device.h

---------

Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>
2024-02-25 18:45:22 +01:00
cap9qd
b78c9387a6 [beken-72xx] Fix duration rollover in deep sleep (#253) 2024-02-22 20:24:40 +01:00
19 changed files with 228 additions and 103 deletions

View File

@@ -20,8 +20,6 @@ env.ParseCustomOptions(platform)
env.ParseCustomFlashLayout(platform, board)
# Add flash layout C defines
env.AddFlashLayout(board)
# Write custom header options
env.ApplyCustomOptions(platform)
# Export board manifest for ltchiptool
env.ExportBoardData(board)
# Print information about versions and custom options

View File

@@ -89,15 +89,17 @@ def env_add_arduino_libraries(env: Environment, queue, name: str, path: str) ->
srcs=[
"+<**/*.c*>",
],
includes=[
"!<*/.>",
"!<*/*>",
]
if name.startswith("common")
else [
"!<.>",
"!<*>",
],
includes=(
[
"!<*/.>",
"!<*/*>",
]
if name.startswith("common")
else [
"!<.>",
"!<*>",
]
),
)
return True

View File

@@ -184,6 +184,9 @@ class LibraryQueue:
else:
self.env.Append(CPPPATH=self.includes)
# prepend headers with custom options
self.env.ApplyCustomOptions(self.env.PioPlatform())
# clone the environment for the whole library queue
queue_env = self.env.Clone()
# add private options to the cloned environment

View File

@@ -27,6 +27,40 @@ static void wifiEventTask(void *arg) {
}
}
// There is a race condition, when we have an event about a successful
// connection but no SSID yet returned by BDK. Even a single millisecond
// delay should prevent this from happening. It's better to waste a bit
// of time here than to lose a valid connection down the line.
static String waitForValidSSID(WiFiClass *pWiFi) {
String result;
// Read the initial value that might just be available already.
result = pWiFi->SSID();
if (!result.length()) {
std::size_t i = 0;
for (; i < 10; i++) {
// Delay and query again.
delay(1);
result = pWiFi->SSID();
if (result.length()) {
LT_DM(WIFI, "Got valid SSID after %u delays", i + 1);
break;
}
// It's a good idea to yield.
yield();
}
if (!result.length()) {
LT_WM(WIFI, "Could not obtain a valid SSID after %u delays", i);
}
}
return result;
}
void wifiEventSendArduino(EventId event) {
event = (EventId)(RW_EVT_ARDUINO | event);
wifiStatusCallback((rw_evt_type *)&event);
@@ -52,11 +86,6 @@ void wifiEventHandler(rw_evt_type event) {
LT_DM(WIFI, "BK event %u", event);
if (event <= RW_EVT_STA_GOT_IP)
pDATA->lastStaEvent = event;
else
pDATA->lastApEvent = event;
EventId eventId;
EventInfo eventInfo;
String ssid;
@@ -103,7 +132,7 @@ void wifiEventHandler(rw_evt_type event) {
case RW_EVT_STA_CONNECTED:
eventId = ARDUINO_EVENT_WIFI_STA_CONNECTED;
ssid = pWiFi->SSID();
ssid = waitForValidSSID(pWiFi);
eventInfo.wifi_sta_connected.ssid_len = ssid.length();
eventInfo.wifi_sta_connected.channel = pWiFi->channel();
eventInfo.wifi_sta_connected.authmode = pWiFi->getEncryption();
@@ -145,5 +174,13 @@ void wifiEventHandler(rw_evt_type event) {
break;
}
// Publish state update only after the event data is retrieved.
// This relates to the race condition with RW_EVT_STA_CONNECTED.
if (event <= RW_EVT_STA_GOT_IP) {
pDATA->lastStaEvent = event;
} else {
pDATA->lastApEvent = event;
}
pWiFi->postEvent(eventId, eventInfo);
}

View File

@@ -31,10 +31,12 @@ lt_reboot_reason_t lt_get_reboot_reason() {
case RESET_SOURCE_CRASH_UNUSED:
case RESET_SOURCE_CRASH_PER_XAT0:
return REBOOT_REASON_CRASH;
case RESET_SOURCE_DEEPPS_GPIO:
case RESET_SOURCE_DEEPPS_RTC:
case RESET_SOURCE_DEEPPS_USB:
return REBOOT_REASON_SLEEP;
return REBOOT_REASON_SLEEP_USB;
case RESET_SOURCE_DEEPPS_GPIO:
return REBOOT_REASON_SLEEP_GPIO;
case RESET_SOURCE_DEEPPS_RTC:
return REBOOT_REASON_SLEEP_RTC;
default:
return REBOOT_REASON_UNKNOWN;
}

View File

@@ -19,14 +19,13 @@ void lt_deep_sleep_unset_gpio(uint32_t gpio_index_map) {
deep_sleep_param.gpio_index_map &= (~gpio_index_map);
}
void lt_deep_sleep_config_timer(uint32_t sleep_duration) {
void lt_deep_sleep_config_timer(uint32_t sleep_duration_ms) {
deep_sleep_param.wake_up_way |= PS_DEEP_WAKEUP_RTC;
uint64_t duration_math = 32768 * sleep_duration;
if (duration_math / 1000 > 0xFFFFFFFF) {
// Sleep forever
deep_sleep_param.sleep_time = 0xFFFFFFFF;
uint64_t sleep_ticks = 32.768 * sleep_duration_ms;
if (sleep_ticks >= 0xFFFFFFFF) {
deep_sleep_param.sleep_time = 0xFFFFFFFE;
} else {
deep_sleep_param.sleep_time = (duration_math / 1000) & 0xFFFFFFFF;
deep_sleep_param.sleep_time = sleep_ticks & 0xFFFFFFFF;
}
}

View File

@@ -0,0 +1,9 @@
/* Copyright (c) Kuba Szczodrzyński 2024-05-18. */
#pragma once
#include_next "tls_config.h"
// allow more entropy sources
#undef MBEDTLS_ENTROPY_MAX_SOURCES
#define MBEDTLS_ENTROPY_MAX_SOURCES 10

View File

@@ -31,9 +31,34 @@ static const char *hostName;
NETIF_DECLARE_EXT_CALLBACK(netif_callback)
#endif
static inline void freeAllocatedStrings(const std::vector<char *> &strings) {
for (auto &str : strings) {
free(str);
}
}
mDNS::mDNS() {}
mDNS::~mDNS() {}
mDNS::~mDNS() {
cleanup();
}
void mDNS::cleanup() {
freeAllocatedStrings(services_name);
services_name.clear();
freeAllocatedStrings(services);
services.clear();
for (auto &record : records) {
freeAllocatedStrings(record);
}
records.clear();
free((void *)hostName);
hostName = NULL;
free((void *)instanceName);
instanceName = NULL;
}
static void mdnsTxtCallback(struct mdns_service *service, void *userdata) {
size_t index = (size_t)userdata;
@@ -42,8 +67,9 @@ static void mdnsTxtCallback(struct mdns_service *service, void *userdata) {
for (const auto record : records[index]) {
err_t err = mdns_resp_add_service_txtitem(service, record, strlen(record));
if (err != ERR_OK)
return;
if (err != ERR_OK) {
LT_DM(MDNS, "Error %d while adding txt record: %s", err, record);
}
}
}
@@ -136,12 +162,18 @@ bool mDNS::begin(const char *hostname) {
}
void mDNS::end() {
#ifdef LWIP_NETIF_EXT_STATUS_CALLBACK
netif_remove_ext_callback(&netif_callback);
#endif
struct netif *netif = netif_list;
while (netif != NULL) {
if (netif_is_up(netif))
mdns_resp_remove_netif(netif);
netif = netif->next;
}
cleanup();
}
bool mDNS::addServiceImpl(const char *name, const char *service, uint8_t proto, uint16_t port) {
@@ -181,18 +213,17 @@ bool mDNS::addServiceImpl(const char *name, const char *service, uint8_t proto,
}
bool mDNS::addServiceTxtImpl(const char *service, uint8_t proto, const char *item) {
int8_t index = -1;
for (uint8_t i = 0; i < services.size(); i++) {
uint8_t i;
for (i = 0; i < services.size(); i++) {
// find a matching service
if (strcmp(services[i], service) == 0 && protos[i] == proto) {
index = i;
break;
}
}
if (index == -1)
if (i == services.size())
return false;
records[index].push_back(strdup(item));
records[i].push_back(strdup(item));
return true;
}

View File

@@ -2,14 +2,23 @@
#include "mDNS.h"
static char *ensureUnderscore(const char *value) {
uint8_t len = strlen(value) + 1;
static char *ensureUnderscore(char *value) {
if (value[0] == '_') {
return value;
}
size_t len = strlen(value) + 1 + 1; // 1 for underscore, 1 for null-terminator
char *result = (char *)malloc(len);
result[0] = '_';
strcpy(result + 1, value + (value[0] == '_'));
strcpy(result + 1, value);
return result;
}
static inline void freeIfCopied(const char *original, char *duplicate) {
if ((duplicate) && (original != duplicate)) {
free(duplicate);
}
}
void mDNS::setInstanceName(const char *name) {
if (instanceName)
free(instanceName);
@@ -21,7 +30,7 @@ bool mDNS::addService(char *service, char *proto, uint16_t port) {
uint8_t _proto = strncmp(proto + (proto[0] == '_'), "tcp", 3) == 0 ? MDNS_TCP : MDNS_UDP;
bool result = addServiceImpl(instanceName ? instanceName : "LT mDNS", _service, _proto, port);
free(_service);
freeIfCopied(service, _service);
return result;
}
@@ -34,7 +43,7 @@ bool mDNS::addServiceTxt(char *service, char *proto, char *key, char *value) {
sprintf(txt, "%s=%s", key, value);
bool result = addServiceTxtImpl(_service, _proto, txt);
free(_service);
freeIfCopied(service, _service);
free(txt);
return result;
}

View File

@@ -51,6 +51,7 @@ class mDNS {
private:
bool addServiceImpl(const char *name, const char *service, uint8_t proto, uint16_t port);
bool addServiceTxtImpl(const char *service, uint8_t proto, const char *item);
void cleanup();
char *instanceName = NULL;

View File

@@ -62,8 +62,12 @@ const char *lt_get_reboot_reason_name(lt_reboot_reason_t reason) {
return "WDT Reset";
case REBOOT_REASON_CRASH:
return "Crash";
case REBOOT_REASON_SLEEP:
return "Sleep Wakeup";
case REBOOT_REASON_SLEEP_GPIO:
return "Sleep Wakeup (GPIO)";
case REBOOT_REASON_SLEEP_RTC:
return "Sleep Wakeup (RTC)";
case REBOOT_REASON_SLEEP_USB:
return "Sleep Wakeup (USB)";
case REBOOT_REASON_DEBUGGER:
return "Debugger";
default:

View File

@@ -4,32 +4,40 @@
#include <libretiny.h>
#define RESET_REASON_UNKNOWN REBOOT_REASON_UNKNOWN
#define RESET_REASON_POWER REBOOT_REASON_POWER
#define RESET_REASON_BROWNOUT REBOOT_REASON_BROWNOUT
#define RESET_REASON_HARDWARE REBOOT_REASON_HARDWARE
#define RESET_REASON_SOFTWARE REBOOT_REASON_SOFTWARE
#define RESET_REASON_WATCHDOG REBOOT_REASON_WATCHDOG
#define RESET_REASON_CRASH REBOOT_REASON_CRASH
#define RESET_REASON_SLEEP REBOOT_REASON_SLEEP
#define RESET_REASON_MAX REBOOT_REASON_MAX
#define RESET_REASON_UNKNOWN REBOOT_REASON_UNKNOWN
#define RESET_REASON_POWER REBOOT_REASON_POWER
#define RESET_REASON_BROWNOUT REBOOT_REASON_BROWNOUT
#define RESET_REASON_HARDWARE REBOOT_REASON_HARDWARE
#define RESET_REASON_SOFTWARE REBOOT_REASON_SOFTWARE
#define RESET_REASON_WATCHDOG REBOOT_REASON_WATCHDOG
#define RESET_REASON_CRASH REBOOT_REASON_CRASH
#define RESET_REASON_SLEEP_GPIO REBOOT_REASON_SLEEP_GPIO
#define RESET_REASON_SLEEP_RTC REBOOT_REASON_SLEEP_RTC
#define RESET_REASON_SLEEP_USB REBOOT_REASON_SLEEP_USB
#define RESET_REASON_MAX REBOOT_REASON_MAX
/**
* @brief Reset reason enumeration.
*/
typedef enum {
REBOOT_REASON_UNKNOWN = 1,
REBOOT_REASON_POWER = 2,
REBOOT_REASON_BROWNOUT = 3,
REBOOT_REASON_HARDWARE = 4,
REBOOT_REASON_SOFTWARE = 5,
REBOOT_REASON_WATCHDOG = 6,
REBOOT_REASON_CRASH = 7,
REBOOT_REASON_SLEEP = 8,
REBOOT_REASON_DEBUGGER = 9,
REBOOT_REASON_MAX = 10,
REBOOT_REASON_UNKNOWN = 1,
REBOOT_REASON_POWER = 2,
REBOOT_REASON_BROWNOUT = 3,
REBOOT_REASON_HARDWARE = 4,
REBOOT_REASON_SOFTWARE = 5,
REBOOT_REASON_WATCHDOG = 6,
REBOOT_REASON_CRASH = 7,
REBOOT_REASON_SLEEP_GPIO = 8,
REBOOT_REASON_SLEEP_RTC = 9,
REBOOT_REASON_SLEEP_USB = 10,
REBOOT_REASON_DEBUGGER = 11,
REBOOT_REASON_MAX = 12,
} lt_reboot_reason_t;
// RESET_REASON_SLEEP deprecated, kept for compatibility
#define RESET_REASON_SLEEP REBOOT_REASON_SLEEP_GPIO
#define REBOOT_REASON_SLEEP REBOOT_REASON_SLEEP_GPIO
/**
* @brief Debugging mode enumeration.
*/

View File

@@ -15,8 +15,15 @@
// set lwIP debugging options according to LT config
#if LT_DEBUG_LWIP
// enable main debugging switch
#undef LWIP_DEBUG
#define LWIP_DEBUG 1
// enable all messages
#undef LWIP_DBG_MIN_LEVEL
#define LWIP_DBG_MIN_LEVEL 0
// enable all debugging types
#undef LWIP_DBG_TYPES_ON
#define LWIP_DBG_TYPES_ON 0xF8
// make lwIP use printf() library
#include <stdio.h>
#undef LWIP_PLATFORM_DIAG

View File

@@ -100,31 +100,31 @@ void lt_log_disable();
#endif
// ESP32 compat
#define log_printf(...) LT_I(__VA_ARGS__)
#define log_v(...) LT_V(__VA_ARGS__)
#define log_d(...) LT_D(__VA_ARGS__)
#define log_i(...) LT_I(__VA_ARGS__)
#define log_w(...) LT_W(__VA_ARGS__)
#define log_e(...) LT_E(__VA_ARGS__)
#define log_n(...) LT_E(__VA_ARGS__)
#define isr_log_v(...) LT_V(__VA_ARGS__)
#define isr_log_d(...) LT_D(__VA_ARGS__)
#define isr_log_i(...) LT_I(__VA_ARGS__)
#define isr_log_w(...) LT_W(__VA_ARGS__)
#define isr_log_e(...) LT_E(__VA_ARGS__)
#define isr_log_n(...) LT_E(__VA_ARGS__)
#define ESP_LOGV(...) LT_V(__VA_ARGS__)
#define ESP_LOGD(...) LT_D(__VA_ARGS__)
#define ESP_LOGI(...) LT_I(__VA_ARGS__)
#define ESP_LOGW(...) LT_W(__VA_ARGS__)
#define ESP_LOGE(...) LT_E(__VA_ARGS__)
#define ESP_EARLY_LOGV(...) LT_V(__VA_ARGS__)
#define ESP_EARLY_LOGD(...) LT_D(__VA_ARGS__)
#define ESP_EARLY_LOGI(...) LT_I(__VA_ARGS__)
#define ESP_EARLY_LOGW(...) LT_W(__VA_ARGS__)
#define ESP_EARLY_LOGE(...) LT_E(__VA_ARGS__)
#define ets_printf(...) LT_I(__VA_ARGS__)
#define ETS_PRINTF(...) LT_I(__VA_ARGS__)
#define log_printf(...) LT_I(__VA_ARGS__)
#define log_v(...) LT_V(__VA_ARGS__)
#define log_d(...) LT_D(__VA_ARGS__)
#define log_i(...) LT_I(__VA_ARGS__)
#define log_w(...) LT_W(__VA_ARGS__)
#define log_e(...) LT_E(__VA_ARGS__)
#define log_n(...) LT_E(__VA_ARGS__)
#define isr_log_v(...) LT_V(__VA_ARGS__)
#define isr_log_d(...) LT_D(__VA_ARGS__)
#define isr_log_i(...) LT_I(__VA_ARGS__)
#define isr_log_w(...) LT_W(__VA_ARGS__)
#define isr_log_e(...) LT_E(__VA_ARGS__)
#define isr_log_n(...) LT_E(__VA_ARGS__)
#define ESP_LOGV(tag, ...) LT_V(__VA_ARGS__)
#define ESP_LOGD(tag, ...) LT_D(__VA_ARGS__)
#define ESP_LOGI(tag, ...) LT_I(__VA_ARGS__)
#define ESP_LOGW(tag, ...) LT_W(__VA_ARGS__)
#define ESP_LOGE(tag, ...) LT_E(__VA_ARGS__)
#define ESP_EARLY_LOGV(tag, ...) LT_V(__VA_ARGS__)
#define ESP_EARLY_LOGD(tag, ...) LT_D(__VA_ARGS__)
#define ESP_EARLY_LOGI(tag, ...) LT_I(__VA_ARGS__)
#define ESP_EARLY_LOGW(tag, ...) LT_W(__VA_ARGS__)
#define ESP_EARLY_LOGE(tag, ...) LT_E(__VA_ARGS__)
#define ets_printf(...) LT_I(__VA_ARGS__)
#define ETS_PRINTF(...) LT_I(__VA_ARGS__)
#define LT_RET(ret) \
LT_E("ret=%d", ret); \

View File

@@ -24,6 +24,7 @@ static rtw_result_t scanHandler(rtw_scan_handler_result_t *result) {
if (cls->scanAlloc(last) < last) {
return RTW_SUCCESS;
}
last--;
scan->ap[last].ssid = strdup((char *)net->SSID.val);
scan->ap[last].auth = securityTypeToAuthMode(net->security);

View File

@@ -61,6 +61,9 @@ void attachInterruptParam(pin_size_t interruptNumber, voidFuncPtrParam callback,
case CHANGE:
#if LT_RTL8720C
event = IRQ_FALL_RISE;
// Prevents Change interrupt errors on RTL8710B chips.
#elif LT_RTL8710B
event = IRQ_RISE;
#else
LT_W("CHANGE interrupts not supported");
#endif

View File

@@ -13,7 +13,10 @@ custom_fw_version = 1.2.0
# custom build options (#defines, NOT compiler flags)
custom_options.lwip =
LWIP_IPV4 = 1
# make sure to enable LT_DEBUG_LWIP as well
NETIF_DEBUG = 0x80
IP_DEBUG = 0x80
TCP_DEBUG = 0x80
custom_options.freertos =
configUSE_TICK_HOOK = 1
@@ -82,7 +85,7 @@ To see debug messages from i.e. OTA, loglevel must also be changed.
- `LT_DEBUG_OTA` (1) - OTA updates (`Update` library)
- `LT_DEBUG_FDB` (0) - FlashDB debugging (macros within the library)
- `LT_DEBUG_MDNS` (0) - mDNS client library
- `LT_DEBUG_LWIP` (0) - enables `LWIP_DEBUG`, provides `LWIP_PLATFORM_DIAG`; per-module options (i.e. `TCP_DEBUG`) are off by default and need to be enabled separately
- `LT_DEBUG_LWIP` (0) - enables `LWIP_DEBUG`, provides `LWIP_PLATFORM_DIAG`; per-module options (i.e. `TCP_DEBUG`) are off by default and need to be enabled separately - see example in `Project options` above
- `LT_DEBUG_LWIP_ASSERT` (0) - enables assertions within lwIP (doesn't need `LT_DEBUG_LWIP`)
!!! tip

View File

@@ -285,12 +285,14 @@ def write_families(supported: list[Family]):
docs = get_readme_family_link(family)
row = [
# Title
"[{}]({})".format(
family.description,
docs,
)
if docs
else family.description,
(
"[{}]({})".format(
family.description,
docs,
)
if docs
else family.description
),
# Name
family.is_supported and f"`{family.name}`" or "`-`",
# Code
@@ -301,16 +303,22 @@ def write_families(supported: list[Family]):
family.id,
),
# Arduino Core
"✔️"
if family in supported and family.is_supported and family.has_arduino_core
else "",
(
"✔️"
if family in supported
and family.is_supported
and family.has_arduino_core
else ""
),
# Source SDK
"[`{}`]({})".format(
family.target_package,
f"https://github.com/libretiny-eu/{family.target_package}",
)
if family.target_package
else "-",
(
"[`{}`]({})".format(
family.target_package,
f"https://github.com/libretiny-eu/{family.target_package}",
)
if family.target_package
else "-"
),
]
rows.append(row)
md.add_table(header, *rows)

View File

@@ -6,7 +6,7 @@
"type": "git",
"url": "https://github.com/libretiny-eu/libretiny.git"
},
"version": "1.5.0",
"version": "1.6.0",
"frameworks": {
"base": {
"title": "Base Framework (SDK only)",