[core] Split lt_api.c into separate units
This commit is contained in:
3
.github/workflows/docs.yml
vendored
3
.github/workflows/docs.yml
vendored
@@ -25,7 +25,8 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
mkdir -p site/
|
mkdir -p site/
|
||||||
boardgen ltci
|
boardgen ltci
|
||||||
python docs/scripts/update_docs.py
|
python docs/scripts/write_boards.py
|
||||||
|
python docs/scripts/write_apis.py
|
||||||
python docs/scripts/prepare_doxygen.py
|
python docs/scripts/prepare_doxygen.py
|
||||||
python docs/scripts/build_json.py
|
python docs/scripts/build_json.py
|
||||||
cp *.json site/
|
cp *.json site/
|
||||||
|
|||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -264,3 +264,5 @@ docs/status/supported_*.md
|
|||||||
docs/status/unsupported_boards_*.md
|
docs/status/unsupported_boards_*.md
|
||||||
boards/**/*.svg
|
boards/**/*.svg
|
||||||
boards/**/*.md
|
boards/**/*.md
|
||||||
|
# other generated files
|
||||||
|
docs/contrib/lt-api-functions.md
|
||||||
|
|||||||
@@ -48,8 +48,9 @@
|
|||||||
* [File list](ltapi/files.md)
|
* [File list](ltapi/files.md)
|
||||||
* 👷 Contributor's manual (WIP)
|
* 👷 Contributor's manual (WIP)
|
||||||
* [Porting new families](docs/contrib/porting.md)
|
* [Porting new families](docs/contrib/porting.md)
|
||||||
* [📁 Project structure](docs/contrib/project-structure.md)
|
* [API functions guide](docs/contrib/lt-api.md)
|
||||||
* [C standard library](docs/contrib/stdlib.md)
|
* [C standard library](docs/contrib/stdlib.md)
|
||||||
|
* [📁 Project structure](docs/contrib/project-structure.md)
|
||||||
* [✈️ OTA format](docs/contrib/ota/README.md)
|
* [✈️ OTA format](docs/contrib/ota/README.md)
|
||||||
* [uf2ota.py tool](docs/contrib/ota/uf2ota.md)
|
* [uf2ota.py tool](docs/contrib/ota/uf2ota.md)
|
||||||
* [uf2ota.h library](docs/contrib/ota/library.md)
|
* [uf2ota.h library](docs/contrib/ota/library.md)
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ def env_add_core_sources(env: Environment, queue, name: str, path: str) -> bool:
|
|||||||
base_dir=path,
|
base_dir=path,
|
||||||
srcs=[
|
srcs=[
|
||||||
"+<*.c*>",
|
"+<*.c*>",
|
||||||
|
"+<api/*.c>",
|
||||||
"+<common/*.c*>",
|
"+<common/*.c*>",
|
||||||
"+<compat/*.c*>",
|
"+<compat/*.c*>",
|
||||||
"+<port/*.c*>",
|
"+<port/*.c*>",
|
||||||
|
|||||||
13
cores/beken-72xx/base/api/lt_cpu.c
Normal file
13
cores/beken-72xx/base/api/lt_cpu.c
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
/* Copyright (c) Kuba Szczodrzyński 2023-02-27. */
|
||||||
|
|
||||||
|
#include <libretiny.h>
|
||||||
|
#include <sdk_private.h>
|
||||||
|
|
||||||
|
lt_cpu_model_t lt_cpu_get_model() {
|
||||||
|
uint8_t chipId = *(uint8_t *)(SCTRL_CHIP_ID);
|
||||||
|
return CPU_MODEL_ENUM(FAMILY, chipId);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *lt_cpu_get_core_type() {
|
||||||
|
return "ARM968E-S (ARMv5TE)";
|
||||||
|
}
|
||||||
41
cores/beken-72xx/base/api/lt_device.c
Normal file
41
cores/beken-72xx/base/api/lt_device.c
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
/* Copyright (c) Kuba Szczodrzyński 2023-02-27. */
|
||||||
|
|
||||||
|
#include <libretiny.h>
|
||||||
|
#include <sdk_private.h>
|
||||||
|
|
||||||
|
void lt_get_device_mac(uint8_t *mac) {
|
||||||
|
cfg_load_mac(mac);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lt_reboot() {
|
||||||
|
bk_reboot();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool lt_reboot_download_mode() {
|
||||||
|
bk_reboot();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
lt_reboot_reason_t lt_get_reboot_reason() {
|
||||||
|
switch (bk_misc_get_start_type()) {
|
||||||
|
case RESET_SOURCE_POWERON:
|
||||||
|
return REBOOT_REASON_POWER;
|
||||||
|
case RESET_SOURCE_REBOOT:
|
||||||
|
return REBOOT_REASON_SOFTWARE;
|
||||||
|
case RESET_SOURCE_WATCHDOG:
|
||||||
|
return REBOOT_REASON_WATCHDOG;
|
||||||
|
case RESET_SOURCE_CRASH_XAT0:
|
||||||
|
case RESET_SOURCE_CRASH_UNDEFINED:
|
||||||
|
case RESET_SOURCE_CRASH_PREFETCH_ABORT:
|
||||||
|
case RESET_SOURCE_CRASH_DATA_ABORT:
|
||||||
|
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;
|
||||||
|
default:
|
||||||
|
return REBOOT_REASON_UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
26
cores/beken-72xx/base/api/lt_flash.c
Normal file
26
cores/beken-72xx/base/api/lt_flash.c
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
/* Copyright (c) Kuba Szczodrzyński 2023-02-27. */
|
||||||
|
|
||||||
|
#include <libretiny.h>
|
||||||
|
#include <sdk_private.h>
|
||||||
|
|
||||||
|
// can't include <flash.h> as it collides with <Flash.h> on Windows -_-
|
||||||
|
#define REG_FLASH_BASE 0x00803000
|
||||||
|
#define REG_FLASH_OPERATE_SW (REG_FLASH_BASE + 0 * 4)
|
||||||
|
#define REG_FLASH_RDID (REG_FLASH_BASE + 4 * 4)
|
||||||
|
#define FLASH_BUSY_SW (0x01UL << 31)
|
||||||
|
#define FLASH_WP_VALUE (0x01UL << 30)
|
||||||
|
#define FLASH_OP_SW (0x01UL << 29)
|
||||||
|
#define FLASH_OP_TYPE_POS 24
|
||||||
|
#define FLASH_OP_RDID 20
|
||||||
|
|
||||||
|
lt_flash_id_t lt_flash_get_id() {
|
||||||
|
uint32_t data = (FLASH_OP_RDID << FLASH_OP_TYPE_POS) | FLASH_OP_SW | FLASH_WP_VALUE;
|
||||||
|
REG_WRITE(REG_FLASH_OPERATE_SW, data);
|
||||||
|
while (REG_READ(REG_FLASH_OPERATE_SW) & FLASH_BUSY_SW) {}
|
||||||
|
lt_flash_id_t id = {
|
||||||
|
.manufacturer_id = REG_RD8(REG_FLASH_RDID, 2),
|
||||||
|
.chip_id = REG_RD8(REG_FLASH_RDID, 1),
|
||||||
|
.chip_size_id = REG_RD8(REG_FLASH_RDID, 0),
|
||||||
|
};
|
||||||
|
return id;
|
||||||
|
}
|
||||||
9
cores/beken-72xx/base/api/lt_init.c
Normal file
9
cores/beken-72xx/base/api/lt_init.c
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
/* Copyright (c) Kuba Szczodrzyński 2023-02-27. */
|
||||||
|
|
||||||
|
#include <libretiny.h>
|
||||||
|
#include <sdk_private.h>
|
||||||
|
|
||||||
|
void lt_init_family() {
|
||||||
|
// set default UART output port
|
||||||
|
uart_print_port = LT_UART_DEFAULT_PORT - 1;
|
||||||
|
}
|
||||||
21
cores/beken-72xx/base/api/lt_mem.c
Normal file
21
cores/beken-72xx/base/api/lt_mem.c
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
/* Copyright (c) Kuba Szczodrzyński 2023-02-27. */
|
||||||
|
|
||||||
|
#include <libretiny.h>
|
||||||
|
#include <sdk_private.h>
|
||||||
|
|
||||||
|
uint32_t lt_ram_get_size() {
|
||||||
|
return 256 * 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t lt_heap_get_size() {
|
||||||
|
#if configDYNAMIC_HEAP_SIZE
|
||||||
|
extern unsigned char _empty_ram;
|
||||||
|
#if CFG_SOC_NAME == SOC_BK7231N
|
||||||
|
return (0x00400000 + 192 * 1024) - (uint32_t)(&_empty_ram);
|
||||||
|
#else
|
||||||
|
return (0x00400000 + 256 * 1024) - (uint32_t)(&_empty_ram);
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
return configTOTAL_HEAP_SIZE;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
39
cores/beken-72xx/base/api/lt_ota.c
Normal file
39
cores/beken-72xx/base/api/lt_ota.c
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
/* Copyright (c) Kuba Szczodrzyński 2023-02-27. */
|
||||||
|
|
||||||
|
#include <libretiny.h>
|
||||||
|
#include <sdk_private.h>
|
||||||
|
|
||||||
|
lt_ota_type_t lt_ota_get_type() {
|
||||||
|
return OTA_TYPE_SINGLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool lt_ota_is_valid(uint8_t index) {
|
||||||
|
if (index != 0)
|
||||||
|
return false;
|
||||||
|
// check download RBL
|
||||||
|
// TODO: maybe check header CRC or even binary hashes
|
||||||
|
uint32_t magic;
|
||||||
|
lt_flash_read(FLASH_DOWNLOAD_OFFSET, (uint8_t *)&magic, 4);
|
||||||
|
return magic == 0x004C4252; // "RBL\0", little-endian
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t lt_ota_dual_get_current() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t lt_ota_dual_get_stored() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool lt_ota_switch(bool revert) {
|
||||||
|
if (!lt_ota_is_valid(0))
|
||||||
|
// no valid "download" image
|
||||||
|
// - return false when trying to activate
|
||||||
|
// - return true when trying to revert
|
||||||
|
return revert;
|
||||||
|
if (revert) {
|
||||||
|
// there's a valid "download" image, which has to be removed
|
||||||
|
return lt_flash_erase_block(FLASH_DOWNLOAD_OFFSET);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
18
cores/beken-72xx/base/api/lt_wdt.c
Normal file
18
cores/beken-72xx/base/api/lt_wdt.c
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
/* Copyright (c) Kuba Szczodrzyński 2023-02-27. */
|
||||||
|
|
||||||
|
#include <libretiny.h>
|
||||||
|
#include <sdk_private.h>
|
||||||
|
|
||||||
|
bool lt_wdt_enable(uint32_t timeout) {
|
||||||
|
wdt_ctrl(WCMD_SET_PERIOD, &timeout);
|
||||||
|
wdt_ctrl(WCMD_POWER_UP, NULL);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lt_wdt_disable() {
|
||||||
|
wdt_ctrl(WCMD_POWER_DOWN, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lt_wdt_feed() {
|
||||||
|
wdt_ctrl(WCMD_RELOAD_PERIOD, NULL);
|
||||||
|
}
|
||||||
@@ -1,184 +0,0 @@
|
|||||||
/* Copyright (c) Kuba Szczodrzyński 2023-02-27. */
|
|
||||||
|
|
||||||
#include <libretiny.h>
|
|
||||||
#include <sdk_private.h>
|
|
||||||
|
|
||||||
// can't include <flash.h> as it collides with <Flash.h> on Windows -_-
|
|
||||||
#define REG_FLASH_BASE 0x00803000
|
|
||||||
#define REG_FLASH_OPERATE_SW (REG_FLASH_BASE + 0 * 4)
|
|
||||||
#define REG_FLASH_RDID (REG_FLASH_BASE + 4 * 4)
|
|
||||||
#define FLASH_BUSY_SW (0x01UL << 31)
|
|
||||||
#define FLASH_WP_VALUE (0x01UL << 30)
|
|
||||||
#define FLASH_OP_SW (0x01UL << 29)
|
|
||||||
#define FLASH_OP_TYPE_POS 24
|
|
||||||
#define FLASH_OP_RDID 20
|
|
||||||
|
|
||||||
void lt_init_family() {
|
|
||||||
// set default UART output port
|
|
||||||
uart_print_port = LT_UART_DEFAULT_PORT - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* _____ _____ _ _
|
|
||||||
/ ____| __ \| | | |
|
|
||||||
| | | |__) | | | |
|
|
||||||
| | | ___/| | | |
|
|
||||||
| |____| | | |__| |
|
|
||||||
\_____|_| \____*/
|
|
||||||
lt_cpu_model_t lt_cpu_get_model() {
|
|
||||||
uint8_t chipId = *(uint8_t *)(SCTRL_CHIP_ID);
|
|
||||||
return CPU_MODEL_ENUM(FAMILY, chipId);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *lt_cpu_get_core_type() {
|
|
||||||
return "ARM968E-S (ARMv5TE)";
|
|
||||||
}
|
|
||||||
|
|
||||||
/*_____ _
|
|
||||||
| __ \ (_)
|
|
||||||
| | | | _____ ___ ___ ___
|
|
||||||
| | | |/ _ \ \ / / |/ __/ _ \
|
|
||||||
| |__| | __/\ V /| | (_| __/
|
|
||||||
|_____/ \___| \_/ |_|\___\__*/
|
|
||||||
void lt_get_device_mac(uint8_t *mac) {
|
|
||||||
cfg_load_mac(mac);
|
|
||||||
}
|
|
||||||
|
|
||||||
void lt_reboot() {
|
|
||||||
bk_reboot();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool lt_reboot_download_mode() {
|
|
||||||
bk_reboot();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
lt_reboot_reason_t lt_get_reboot_reason() {
|
|
||||||
switch (bk_misc_get_start_type()) {
|
|
||||||
case RESET_SOURCE_POWERON:
|
|
||||||
return REBOOT_REASON_POWER;
|
|
||||||
case RESET_SOURCE_REBOOT:
|
|
||||||
return REBOOT_REASON_SOFTWARE;
|
|
||||||
case RESET_SOURCE_WATCHDOG:
|
|
||||||
return REBOOT_REASON_WATCHDOG;
|
|
||||||
case RESET_SOURCE_CRASH_XAT0:
|
|
||||||
case RESET_SOURCE_CRASH_UNDEFINED:
|
|
||||||
case RESET_SOURCE_CRASH_PREFETCH_ABORT:
|
|
||||||
case RESET_SOURCE_CRASH_DATA_ABORT:
|
|
||||||
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;
|
|
||||||
default:
|
|
||||||
return REBOOT_REASON_UNKNOWN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*______ _ _
|
|
||||||
| ____| | | |
|
|
||||||
| |__ | | __ _ ___| |__
|
|
||||||
| __| | |/ _` / __| '_ \
|
|
||||||
| | | | (_| \__ \ | | |
|
|
||||||
|_| |_|\__,_|___/_| |*/
|
|
||||||
lt_flash_id_t lt_flash_get_id() {
|
|
||||||
uint32_t data = (FLASH_OP_RDID << FLASH_OP_TYPE_POS) | FLASH_OP_SW | FLASH_WP_VALUE;
|
|
||||||
REG_WRITE(REG_FLASH_OPERATE_SW, data);
|
|
||||||
while (REG_READ(REG_FLASH_OPERATE_SW) & FLASH_BUSY_SW) {}
|
|
||||||
lt_flash_id_t id = {
|
|
||||||
.manufacturer_id = REG_RD8(REG_FLASH_RDID, 2),
|
|
||||||
.chip_id = REG_RD8(REG_FLASH_RDID, 1),
|
|
||||||
.chip_size_id = REG_RD8(REG_FLASH_RDID, 0),
|
|
||||||
};
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*__ __
|
|
||||||
| \/ |
|
|
||||||
| \ / | ___ _ __ ___ ___ _ __ _ _
|
|
||||||
| |\/| |/ _ \ '_ ` _ \ / _ \| '__| | | |
|
|
||||||
| | | | __/ | | | | | (_) | | | |_| |
|
|
||||||
|_| |_|\___|_| |_| |_|\___/|_| \__, |
|
|
||||||
__/ |
|
|
||||||
|__*/
|
|
||||||
uint32_t lt_ram_get_size() {
|
|
||||||
return 256 * 1024;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t lt_heap_get_size() {
|
|
||||||
#if configDYNAMIC_HEAP_SIZE
|
|
||||||
extern unsigned char _empty_ram;
|
|
||||||
#if CFG_SOC_NAME == SOC_BK7231N
|
|
||||||
return (0x00400000 + 192 * 1024) - (uint32_t)(&_empty_ram);
|
|
||||||
#else
|
|
||||||
return (0x00400000 + 256 * 1024) - (uint32_t)(&_empty_ram);
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
return configTOTAL_HEAP_SIZE;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ____ _______
|
|
||||||
/ __ \__ __|/\
|
|
||||||
| | | | | | / \
|
|
||||||
| | | | | | / /\ \
|
|
||||||
| |__| | | |/ ____ \
|
|
||||||
\____/ |_/_/ \*/
|
|
||||||
|
|
||||||
lt_ota_type_t lt_ota_get_type() {
|
|
||||||
return OTA_TYPE_SINGLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool lt_ota_is_valid(uint8_t index) {
|
|
||||||
if (index != 0)
|
|
||||||
return false;
|
|
||||||
// check download RBL
|
|
||||||
// TODO: maybe check header CRC or even binary hashes
|
|
||||||
uint32_t magic;
|
|
||||||
lt_flash_read(FLASH_DOWNLOAD_OFFSET, (uint8_t *)&magic, 4);
|
|
||||||
return magic == 0x004C4252; // "RBL\0", little-endian
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t lt_ota_dual_get_current() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t lt_ota_dual_get_stored() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool lt_ota_switch(bool revert) {
|
|
||||||
if (!lt_ota_is_valid(0))
|
|
||||||
// no valid "download" image
|
|
||||||
// - return false when trying to activate
|
|
||||||
// - return true when trying to revert
|
|
||||||
return revert;
|
|
||||||
if (revert) {
|
|
||||||
// there's a valid "download" image, which has to be removed
|
|
||||||
return lt_flash_erase_block(FLASH_DOWNLOAD_OFFSET);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*_ __ _ _ _
|
|
||||||
\ \ / / | | | | | |
|
|
||||||
\ \ /\ / /_ _| |_ ___| |__ __| | ___ __ _
|
|
||||||
\ \/ \/ / _` | __/ __| '_ \ / _` |/ _ \ / _` |
|
|
||||||
\ /\ / (_| | || (__| | | | (_| | (_) | (_| |
|
|
||||||
\/ \/ \__,_|\__\___|_| |_|\__,_|\___/ \__, |
|
|
||||||
__/ |
|
|
||||||
|___*/
|
|
||||||
bool lt_wdt_enable(uint32_t timeout) {
|
|
||||||
wdt_ctrl(WCMD_SET_PERIOD, &timeout);
|
|
||||||
wdt_ctrl(WCMD_POWER_UP, NULL);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void lt_wdt_disable() {
|
|
||||||
wdt_ctrl(WCMD_POWER_DOWN, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void lt_wdt_feed() {
|
|
||||||
wdt_ctrl(WCMD_RELOAD_PERIOD, NULL);
|
|
||||||
}
|
|
||||||
58
cores/common/base/api/lt_cpu.c
Normal file
58
cores/common/base/api/lt_cpu.c
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/* Copyright (c) Kuba Szczodrzyński 2022-04-29. */
|
||||||
|
|
||||||
|
#include "lt_cpu.h"
|
||||||
|
|
||||||
|
#if LT_HAS_FREERTOS
|
||||||
|
#include <FreeRTOS.h>
|
||||||
|
#include <task.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
lt_cpu_family_t lt_cpu_get_family() {
|
||||||
|
return FAMILY;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *lt_cpu_get_family_name() {
|
||||||
|
return STRINGIFY_MACRO(FAMILY) + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((weak)) lt_cpu_model_t lt_cpu_get_model() {
|
||||||
|
return MCU;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *lt_cpu_get_model_name() {
|
||||||
|
return STRINGIFY_MACRO(MCU);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *lt_cpu_get_model_code() {
|
||||||
|
return STRINGIFY_MACRO(MCULC);
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((weak)) uint32_t lt_cpu_get_unique_id() {
|
||||||
|
return lt_cpu_get_mac_id();
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((weak)) uint32_t lt_cpu_get_mac_id() {
|
||||||
|
uint8_t mac[6];
|
||||||
|
lt_get_device_mac(mac);
|
||||||
|
return (mac[3] << 0) | (mac[4] << 8) | (mac[5] << 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((weak)) uint8_t lt_cpu_get_core_count() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if LT_HAS_FREERTOS
|
||||||
|
__attribute__((weak)) uint32_t lt_cpu_get_freq() {
|
||||||
|
return configCPU_CLOCK_HZ;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uint32_t lt_cpu_get_freq_mhz() {
|
||||||
|
return lt_cpu_get_freq() / 1000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if LT_HAS_FREERTOS
|
||||||
|
__attribute__((weak)) uint32_t lt_cpu_get_cycle_count() {
|
||||||
|
return xTaskGetTickCount() * (configCPU_CLOCK_HZ / configTICK_RATE_HZ);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
80
cores/common/base/api/lt_device.c
Normal file
80
cores/common/base/api/lt_device.c
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
/* Copyright (c) Kuba Szczodrzyński 2022-04-29. */
|
||||||
|
|
||||||
|
#include "lt_device.h"
|
||||||
|
|
||||||
|
static char *device_name = NULL;
|
||||||
|
|
||||||
|
const char *lt_get_version() {
|
||||||
|
return LT_VERSION_STR;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *lt_get_board_code() {
|
||||||
|
return LT_BOARD_STR;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *lt_get_device_name() {
|
||||||
|
if (device_name)
|
||||||
|
return device_name;
|
||||||
|
uint32_t chip_id = lt_cpu_get_mac_id();
|
||||||
|
uint8_t *id = (uint8_t *)&chip_id;
|
||||||
|
|
||||||
|
const char *model = lt_cpu_get_model_code();
|
||||||
|
uint8_t model_len = strlen(model);
|
||||||
|
device_name = (char *)malloc(3 + model_len + 1 + 6 + 1);
|
||||||
|
|
||||||
|
sprintf(device_name, "LT-%s-%02x%02x%02x", model, id[0], id[1], id[2]);
|
||||||
|
return device_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((weak)) void lt_reboot() {
|
||||||
|
// The Watchdog Way
|
||||||
|
lt_wdt_enable(1L);
|
||||||
|
while (1) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((weak)) bool lt_reboot_wdt() {
|
||||||
|
if (!lt_wdt_enable(1L))
|
||||||
|
return false;
|
||||||
|
while (1) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((weak)) bool lt_reboot_download_mode() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((weak)) lt_reboot_reason_t lt_get_reboot_reason() {
|
||||||
|
return REBOOT_REASON_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *lt_get_reboot_reason_name(lt_reboot_reason_t reason) {
|
||||||
|
if (!reason)
|
||||||
|
reason = lt_get_reboot_reason();
|
||||||
|
switch (reason) {
|
||||||
|
case REBOOT_REASON_POWER:
|
||||||
|
return "Power-On";
|
||||||
|
case REBOOT_REASON_BROWNOUT:
|
||||||
|
return "Brownout";
|
||||||
|
case REBOOT_REASON_HARDWARE:
|
||||||
|
return "HW Reboot";
|
||||||
|
case REBOOT_REASON_SOFTWARE:
|
||||||
|
return "SW Reboot";
|
||||||
|
case REBOOT_REASON_WATCHDOG:
|
||||||
|
return "WDT Reset";
|
||||||
|
case REBOOT_REASON_CRASH:
|
||||||
|
return "Crash";
|
||||||
|
case REBOOT_REASON_SLEEP:
|
||||||
|
return "Sleep Wakeup";
|
||||||
|
case REBOOT_REASON_DEBUGGER:
|
||||||
|
return "Debugger";
|
||||||
|
default:
|
||||||
|
return "Unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((weak)) bool lt_set_debug_mode(lt_debug_mode_t mode) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((weak)) void lt_gpio_recover() {
|
||||||
|
lt_set_debug_mode(DEBUG_MODE_OFF);
|
||||||
|
}
|
||||||
39
cores/common/base/api/lt_flash.c
Normal file
39
cores/common/base/api/lt_flash.c
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
/* Copyright (c) Kuba Szczodrzyński 2022-04-29. */
|
||||||
|
|
||||||
|
#include "lt_flash.h"
|
||||||
|
|
||||||
|
#include <fal.h>
|
||||||
|
|
||||||
|
__attribute__((weak)) uint32_t lt_flash_get_size() {
|
||||||
|
lt_flash_id_t id = lt_flash_get_id();
|
||||||
|
if (id.chip_size_id >= 0x14 && id.chip_size_id <= 0x19) {
|
||||||
|
return (1 << id.chip_size_id);
|
||||||
|
}
|
||||||
|
#ifdef FLASH_LENGTH
|
||||||
|
return FLASH_LENGTH;
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool lt_flash_erase(uint32_t offset, size_t length) {
|
||||||
|
return fal_partition_erase(fal_root_part, offset, length) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool lt_flash_erase_block(uint32_t offset) {
|
||||||
|
return fal_partition_erase(fal_root_part, offset, 1) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t lt_flash_read(uint32_t offset, uint8_t *data, size_t length) {
|
||||||
|
int ret = fal_partition_read(fal_root_part, offset, data, length);
|
||||||
|
if (ret == -1)
|
||||||
|
return 0;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t lt_flash_write(uint32_t offset, const uint8_t *data, size_t length) {
|
||||||
|
int ret = fal_partition_write(fal_root_part, offset, data, length);
|
||||||
|
if (ret == -1)
|
||||||
|
return 0;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
26
cores/common/base/api/lt_mem.c
Normal file
26
cores/common/base/api/lt_mem.c
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
/* Copyright (c) Kuba Szczodrzyński 2022-04-29. */
|
||||||
|
|
||||||
|
#include "lt_mem.h"
|
||||||
|
|
||||||
|
#if LT_HAS_FREERTOS
|
||||||
|
#include <FreeRTOS.h>
|
||||||
|
#include <task.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if LT_HAS_FREERTOS
|
||||||
|
__attribute__((weak)) uint32_t lt_heap_get_size() {
|
||||||
|
return configTOTAL_HEAP_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((weak)) uint32_t lt_heap_get_free() {
|
||||||
|
return xPortGetFreeHeapSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((weak)) uint32_t lt_heap_get_min_free() {
|
||||||
|
return xPortGetMinimumEverFreeHeapSize();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
__attribute__((weak)) uint32_t lt_heap_get_max_alloc() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
18
cores/common/base/api/lt_ota.c
Normal file
18
cores/common/base/api/lt_ota.c
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
/* Copyright (c) Kuba Szczodrzyński 2022-04-29. */
|
||||||
|
|
||||||
|
#include "lt_ota.h"
|
||||||
|
|
||||||
|
bool lt_ota_can_rollback() {
|
||||||
|
if (lt_ota_get_type() != OTA_TYPE_DUAL)
|
||||||
|
return false;
|
||||||
|
uint8_t current = lt_ota_dual_get_current();
|
||||||
|
return lt_ota_is_valid(current ^ 0b11);
|
||||||
|
}
|
||||||
|
|
||||||
|
uf2_ota_scheme_t lt_ota_get_uf2_scheme() {
|
||||||
|
if (lt_ota_get_type() == OTA_TYPE_SINGLE)
|
||||||
|
return UF2_SCHEME_DEVICE_SINGLE;
|
||||||
|
uint8_t current = lt_ota_dual_get_current();
|
||||||
|
// UF2_SCHEME_DEVICE_DUAL_1 or UF2_SCHEME_DEVICE_DUAL_2
|
||||||
|
return (uf2_ota_scheme_t)(current ^ 0b11);
|
||||||
|
}
|
||||||
41
cores/common/base/api/lt_utils.c
Normal file
41
cores/common/base/api/lt_utils.c
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
/* Copyright (c) Kuba Szczodrzyński 2022-04-29. */
|
||||||
|
|
||||||
|
#include "lt_utils.h"
|
||||||
|
|
||||||
|
void lt_rand_bytes(uint8_t *buf, size_t len) {
|
||||||
|
int *data = (int *)buf;
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; len >= sizeof(int); len -= sizeof(int)) {
|
||||||
|
data[i++] = rand();
|
||||||
|
}
|
||||||
|
if (len) {
|
||||||
|
int rem = rand();
|
||||||
|
unsigned char *pRem = (unsigned char *)&rem;
|
||||||
|
memcpy(buf + i * sizeof(int), pRem, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void hexdump(const uint8_t *buf, size_t len, uint32_t offset, uint8_t width) {
|
||||||
|
uint16_t pos = 0;
|
||||||
|
while (pos < len) {
|
||||||
|
// print hex offset
|
||||||
|
printf("%06lx ", offset + pos);
|
||||||
|
// calculate current line width
|
||||||
|
uint8_t lineWidth = MIN(width, len - pos);
|
||||||
|
// print hexadecimal representation
|
||||||
|
for (uint8_t i = 0; i < lineWidth; i++) {
|
||||||
|
if (i % 8 == 0) {
|
||||||
|
printf(" ");
|
||||||
|
}
|
||||||
|
printf("%02x ", buf[pos + i]);
|
||||||
|
}
|
||||||
|
// print ascii representation
|
||||||
|
printf(" |");
|
||||||
|
for (uint8_t i = 0; i < lineWidth; i++) {
|
||||||
|
char c = buf[pos + i];
|
||||||
|
putchar((c >= 0x20 && c <= 0x7f) ? c : '.');
|
||||||
|
}
|
||||||
|
puts("|\r");
|
||||||
|
pos += lineWidth;
|
||||||
|
}
|
||||||
|
}
|
||||||
11
cores/common/base/api/lt_wdt.c
Normal file
11
cores/common/base/api/lt_wdt.c
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
/* Copyright (c) Kuba Szczodrzyński 2022-04-29. */
|
||||||
|
|
||||||
|
#include "lt_wdt.h"
|
||||||
|
|
||||||
|
__attribute__((weak)) bool lt_wdt_enable(uint32_t timeout) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((weak)) void lt_wdt_disable() {}
|
||||||
|
|
||||||
|
__attribute__((weak)) void lt_wdt_feed() {}
|
||||||
@@ -1,296 +0,0 @@
|
|||||||
/* Copyright (c) Kuba Szczodrzyński 2022-04-29. */
|
|
||||||
|
|
||||||
#include "lt_api.h"
|
|
||||||
|
|
||||||
#include <fal.h>
|
|
||||||
|
|
||||||
#if LT_HAS_FREERTOS
|
|
||||||
#include <FreeRTOS.h>
|
|
||||||
#include <task.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* _____ _____ _ _
|
|
||||||
/ ____| __ \| | | |
|
|
||||||
| | | |__) | | | |
|
|
||||||
| | | ___/| | | |
|
|
||||||
| |____| | | |__| |
|
|
||||||
\_____|_| \____*/
|
|
||||||
lt_cpu_family_t lt_cpu_get_family() {
|
|
||||||
return FAMILY;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *lt_cpu_get_family_name() {
|
|
||||||
return STRINGIFY_MACRO(FAMILY) + 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
__attribute__((weak)) lt_cpu_model_t lt_cpu_get_model() {
|
|
||||||
return MCU;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *lt_cpu_get_model_name() {
|
|
||||||
return STRINGIFY_MACRO(MCU);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *lt_cpu_get_model_code() {
|
|
||||||
return STRINGIFY_MACRO(MCULC);
|
|
||||||
}
|
|
||||||
|
|
||||||
__attribute__((weak)) uint32_t lt_cpu_get_unique_id() {
|
|
||||||
return lt_cpu_get_mac_id();
|
|
||||||
}
|
|
||||||
|
|
||||||
__attribute__((weak)) uint32_t lt_cpu_get_mac_id() {
|
|
||||||
uint8_t mac[6];
|
|
||||||
lt_get_device_mac(mac);
|
|
||||||
return (mac[3] << 0) | (mac[4] << 8) | (mac[5] << 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
__attribute__((weak)) uint8_t lt_cpu_get_core_count() {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if LT_HAS_FREERTOS
|
|
||||||
__attribute__((weak)) uint32_t lt_cpu_get_freq() {
|
|
||||||
return configCPU_CLOCK_HZ;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
uint32_t lt_cpu_get_freq_mhz() {
|
|
||||||
return lt_cpu_get_freq() / 1000000;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if LT_HAS_FREERTOS
|
|
||||||
__attribute__((weak)) uint32_t lt_cpu_get_cycle_count() {
|
|
||||||
return xTaskGetTickCount() * (configCPU_CLOCK_HZ / configTICK_RATE_HZ);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*_____ _
|
|
||||||
| __ \ (_)
|
|
||||||
| | | | _____ ___ ___ ___
|
|
||||||
| | | |/ _ \ \ / / |/ __/ _ \
|
|
||||||
| |__| | __/\ V /| | (_| __/
|
|
||||||
|_____/ \___| \_/ |_|\___\__*/
|
|
||||||
static char *device_name = NULL;
|
|
||||||
|
|
||||||
const char *lt_get_version() {
|
|
||||||
return LT_VERSION_STR;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *lt_get_board_code() {
|
|
||||||
return LT_BOARD_STR;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *lt_get_device_name() {
|
|
||||||
if (device_name)
|
|
||||||
return device_name;
|
|
||||||
uint32_t chip_id = lt_cpu_get_mac_id();
|
|
||||||
uint8_t *id = (uint8_t *)&chip_id;
|
|
||||||
|
|
||||||
const char *model = lt_cpu_get_model_code();
|
|
||||||
uint8_t model_len = strlen(model);
|
|
||||||
device_name = (char *)malloc(3 + model_len + 1 + 6 + 1);
|
|
||||||
|
|
||||||
sprintf(device_name, "LT-%s-%02x%02x%02x", model, id[0], id[1], id[2]);
|
|
||||||
return device_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
__attribute__((weak)) void lt_reboot() {
|
|
||||||
// The Watchdog Way
|
|
||||||
lt_wdt_enable(1L);
|
|
||||||
while (1) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
__attribute__((weak)) bool lt_reboot_wdt() {
|
|
||||||
if (!lt_wdt_enable(1L))
|
|
||||||
return false;
|
|
||||||
while (1) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
__attribute__((weak)) bool lt_reboot_download_mode() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
__attribute__((weak)) lt_reboot_reason_t lt_get_reboot_reason() {
|
|
||||||
return REBOOT_REASON_UNKNOWN;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *lt_get_reboot_reason_name(lt_reboot_reason_t reason) {
|
|
||||||
if (!reason)
|
|
||||||
reason = lt_get_reboot_reason();
|
|
||||||
switch (reason) {
|
|
||||||
case REBOOT_REASON_POWER:
|
|
||||||
return "Power-On";
|
|
||||||
case REBOOT_REASON_BROWNOUT:
|
|
||||||
return "Brownout";
|
|
||||||
case REBOOT_REASON_HARDWARE:
|
|
||||||
return "HW Reboot";
|
|
||||||
case REBOOT_REASON_SOFTWARE:
|
|
||||||
return "SW Reboot";
|
|
||||||
case REBOOT_REASON_WATCHDOG:
|
|
||||||
return "WDT Reset";
|
|
||||||
case REBOOT_REASON_CRASH:
|
|
||||||
return "Crash";
|
|
||||||
case REBOOT_REASON_SLEEP:
|
|
||||||
return "Sleep Wakeup";
|
|
||||||
case REBOOT_REASON_DEBUGGER:
|
|
||||||
return "Debugger";
|
|
||||||
default:
|
|
||||||
return "Unknown";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
__attribute__((weak)) bool lt_set_debug_mode(lt_debug_mode_t mode) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
__attribute__((weak)) void lt_gpio_recover() {
|
|
||||||
lt_set_debug_mode(DEBUG_MODE_OFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*______ _ _
|
|
||||||
| ____| | | |
|
|
||||||
| |__ | | __ _ ___| |__
|
|
||||||
| __| | |/ _` / __| '_ \
|
|
||||||
| | | | (_| \__ \ | | |
|
|
||||||
|_| |_|\__,_|___/_| |*/
|
|
||||||
__attribute__((weak)) uint32_t lt_flash_get_size() {
|
|
||||||
lt_flash_id_t id = lt_flash_get_id();
|
|
||||||
if (id.chip_size_id >= 0x14 && id.chip_size_id <= 0x19) {
|
|
||||||
return (1 << id.chip_size_id);
|
|
||||||
}
|
|
||||||
#ifdef FLASH_LENGTH
|
|
||||||
return FLASH_LENGTH;
|
|
||||||
#else
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
bool lt_flash_erase(uint32_t offset, size_t length) {
|
|
||||||
return fal_partition_erase(fal_root_part, offset, length) >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool lt_flash_erase_block(uint32_t offset) {
|
|
||||||
return fal_partition_erase(fal_root_part, offset, 1) >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t lt_flash_read(uint32_t offset, uint8_t *data, size_t length) {
|
|
||||||
int ret = fal_partition_read(fal_root_part, offset, data, length);
|
|
||||||
if (ret == -1)
|
|
||||||
return 0;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t lt_flash_write(uint32_t offset, const uint8_t *data, size_t length) {
|
|
||||||
int ret = fal_partition_write(fal_root_part, offset, data, length);
|
|
||||||
if (ret == -1)
|
|
||||||
return 0;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*__ __
|
|
||||||
| \/ |
|
|
||||||
| \ / | ___ _ __ ___ ___ _ __ _ _
|
|
||||||
| |\/| |/ _ \ '_ ` _ \ / _ \| '__| | | |
|
|
||||||
| | | | __/ | | | | | (_) | | | |_| |
|
|
||||||
|_| |_|\___|_| |_| |_|\___/|_| \__, |
|
|
||||||
__/ |
|
|
||||||
|__*/
|
|
||||||
#if LT_HAS_FREERTOS
|
|
||||||
__attribute__((weak)) uint32_t lt_heap_get_size() {
|
|
||||||
return configTOTAL_HEAP_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
__attribute__((weak)) uint32_t lt_heap_get_free() {
|
|
||||||
return xPortGetFreeHeapSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
__attribute__((weak)) uint32_t lt_heap_get_min_free() {
|
|
||||||
return xPortGetMinimumEverFreeHeapSize();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
__attribute__((weak)) uint32_t lt_heap_get_max_alloc() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ____ _______
|
|
||||||
/ __ \__ __|/\
|
|
||||||
| | | | | | / \
|
|
||||||
| | | | | | / /\ \
|
|
||||||
| |__| | | |/ ____ \
|
|
||||||
\____/ |_/_/ \*/
|
|
||||||
bool lt_ota_can_rollback() {
|
|
||||||
if (lt_ota_get_type() != OTA_TYPE_DUAL)
|
|
||||||
return false;
|
|
||||||
uint8_t current = lt_ota_dual_get_current();
|
|
||||||
return lt_ota_is_valid(current ^ 0b11);
|
|
||||||
}
|
|
||||||
|
|
||||||
uf2_ota_scheme_t lt_ota_get_uf2_scheme() {
|
|
||||||
if (lt_ota_get_type() == OTA_TYPE_SINGLE)
|
|
||||||
return UF2_SCHEME_DEVICE_SINGLE;
|
|
||||||
uint8_t current = lt_ota_dual_get_current();
|
|
||||||
// UF2_SCHEME_DEVICE_DUAL_1 or UF2_SCHEME_DEVICE_DUAL_2
|
|
||||||
return (uf2_ota_scheme_t)(current ^ 0b11);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*_ _ _ _ _
|
|
||||||
| | | | | (_) |
|
|
||||||
| | | | |_ _| |___
|
|
||||||
| | | | __| | / __|
|
|
||||||
| |__| | |_| | \__ \
|
|
||||||
\____/ \__|_|_|__*/
|
|
||||||
void lt_rand_bytes(uint8_t *buf, size_t len) {
|
|
||||||
int *data = (int *)buf;
|
|
||||||
size_t i;
|
|
||||||
for (i = 0; len >= sizeof(int); len -= sizeof(int)) {
|
|
||||||
data[i++] = rand();
|
|
||||||
}
|
|
||||||
if (len) {
|
|
||||||
int rem = rand();
|
|
||||||
unsigned char *pRem = (unsigned char *)&rem;
|
|
||||||
memcpy(buf + i * sizeof(int), pRem, len);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void hexdump(const uint8_t *buf, size_t len, uint32_t offset, uint8_t width) {
|
|
||||||
uint16_t pos = 0;
|
|
||||||
while (pos < len) {
|
|
||||||
// print hex offset
|
|
||||||
printf("%06lx ", offset + pos);
|
|
||||||
// calculate current line width
|
|
||||||
uint8_t lineWidth = MIN(width, len - pos);
|
|
||||||
// print hexadecimal representation
|
|
||||||
for (uint8_t i = 0; i < lineWidth; i++) {
|
|
||||||
if (i % 8 == 0) {
|
|
||||||
printf(" ");
|
|
||||||
}
|
|
||||||
printf("%02x ", buf[pos + i]);
|
|
||||||
}
|
|
||||||
// print ascii representation
|
|
||||||
printf(" |");
|
|
||||||
for (uint8_t i = 0; i < lineWidth; i++) {
|
|
||||||
char c = buf[pos + i];
|
|
||||||
putchar((c >= 0x20 && c <= 0x7f) ? c : '.');
|
|
||||||
}
|
|
||||||
puts("|\r");
|
|
||||||
pos += lineWidth;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*_ __ _ _ _
|
|
||||||
\ \ / / | | | | | |
|
|
||||||
\ \ /\ / /_ _| |_ ___| |__ __| | ___ __ _
|
|
||||||
\ \/ \/ / _` | __/ __| '_ \ / _` |/ _ \ / _` |
|
|
||||||
\ /\ / (_| | || (__| | | | (_| | (_) | (_| |
|
|
||||||
\/ \/ \__,_|\__\___|_| |_|\__,_|\___/ \__, |
|
|
||||||
__/ |
|
|
||||||
|___*/
|
|
||||||
__attribute__((weak)) bool lt_wdt_enable(uint32_t timeout) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
__attribute__((weak)) void lt_wdt_disable() {}
|
|
||||||
|
|
||||||
__attribute__((weak)) void lt_wdt_feed() {}
|
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// This file collects all LibreTiny C API includes.
|
// This file collects all LibreTiny C API includes.
|
||||||
// The functions are implemented in lt_api.c, which is located
|
// The functions are implemented in api/*.c units, which are located
|
||||||
// in the common core, and in the family cores.
|
// in the common core, and in the family cores.
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
14
cores/realtek-amb/base/api/lt_flash.c
Normal file
14
cores/realtek-amb/base/api/lt_flash.c
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
/* Copyright (c) Kuba Szczodrzyński 2023-05-23. */
|
||||||
|
|
||||||
|
#include <libretiny.h>
|
||||||
|
#include <sdk_private.h>
|
||||||
|
|
||||||
|
lt_flash_id_t lt_flash_get_id() {
|
||||||
|
lt_flash_id_t id;
|
||||||
|
uint8_t idBytes[3];
|
||||||
|
flash_read_id(<_flash_obj, idBytes, 3);
|
||||||
|
id.manufacturer_id = idBytes[0];
|
||||||
|
id.chip_id = idBytes[1];
|
||||||
|
id.chip_size_id = idBytes[2];
|
||||||
|
return id;
|
||||||
|
}
|
||||||
18
cores/realtek-amb/base/api/lt_wdt.c
Normal file
18
cores/realtek-amb/base/api/lt_wdt.c
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
/* Copyright (c) Kuba Szczodrzyński 2023-05-23. */
|
||||||
|
|
||||||
|
#include <libretiny.h>
|
||||||
|
#include <sdk_private.h>
|
||||||
|
|
||||||
|
bool lt_wdt_enable(uint32_t timeout) {
|
||||||
|
watchdog_init(timeout);
|
||||||
|
watchdog_start();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lt_wdt_disable() {
|
||||||
|
watchdog_stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void lt_wdt_feed() {
|
||||||
|
watchdog_refresh();
|
||||||
|
}
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
/* Copyright (c) Kuba Szczodrzyński 2023-05-23. */
|
|
||||||
|
|
||||||
#include <libretiny.h>
|
|
||||||
#include <sdk_private.h>
|
|
||||||
|
|
||||||
/*______ _ _
|
|
||||||
| ____| | | |
|
|
||||||
| |__ | | __ _ ___| |__
|
|
||||||
| __| | |/ _` / __| '_ \
|
|
||||||
| | | | (_| \__ \ | | |
|
|
||||||
|_| |_|\__,_|___/_| |*/
|
|
||||||
lt_flash_id_t lt_flash_get_id() {
|
|
||||||
lt_flash_id_t id;
|
|
||||||
uint8_t idBytes[3];
|
|
||||||
flash_read_id(<_flash_obj, idBytes, 3);
|
|
||||||
id.manufacturer_id = idBytes[0];
|
|
||||||
id.chip_id = idBytes[1];
|
|
||||||
id.chip_size_id = idBytes[2];
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*_ __ _ _ _
|
|
||||||
\ \ / / | | | | | |
|
|
||||||
\ \ /\ / /_ _| |_ ___| |__ __| | ___ __ _
|
|
||||||
\ \/ \/ / _` | __/ __| '_ \ / _` |/ _ \ / _` |
|
|
||||||
\ /\ / (_| | || (__| | | | (_| | (_) | (_| |
|
|
||||||
\/ \/ \__,_|\__\___|_| |_|\__,_|\___/ \__, |
|
|
||||||
__/ |
|
|
||||||
|___*/
|
|
||||||
bool lt_wdt_enable(uint32_t timeout) {
|
|
||||||
watchdog_init(timeout);
|
|
||||||
watchdog_start();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void lt_wdt_disable() {
|
|
||||||
watchdog_stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
void lt_wdt_feed() {
|
|
||||||
watchdog_refresh();
|
|
||||||
}
|
|
||||||
34
cores/realtek-ambz/base/api/lt_cpu.c
Normal file
34
cores/realtek-ambz/base/api/lt_cpu.c
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
/* Copyright (c) Kuba Szczodrzyński 2023-02-27. */
|
||||||
|
|
||||||
|
#include <libretiny.h>
|
||||||
|
#include <sdk_private.h>
|
||||||
|
|
||||||
|
lt_cpu_model_t lt_cpu_get_model() {
|
||||||
|
uint8_t chipId;
|
||||||
|
EFUSE_OneByteReadROM(9902, 0xF8, &chipId, L25EOUTVOLTAGE);
|
||||||
|
return CPU_MODEL_ENUM(FAMILY, chipId);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t lt_cpu_get_mac_id() {
|
||||||
|
uint32_t chipId = 0;
|
||||||
|
uint8_t *id = (uint8_t *)&chipId;
|
||||||
|
// 9902 was extracted from ROM disassembly, probably not needed
|
||||||
|
/* EFUSE_OneByteReadROM(9902, 0x3B, id + 0, L25EOUTVOLTAGE);
|
||||||
|
EFUSE_OneByteReadROM(9902, 0x3C, id + 1, L25EOUTVOLTAGE);
|
||||||
|
EFUSE_OneByteReadROM(9902, 0x3D, id + 2, L25EOUTVOLTAGE); */
|
||||||
|
// new method, based on EFUSE logical map
|
||||||
|
uint8_t *efuse = (uint8_t *)malloc(512);
|
||||||
|
// TODO do what EFUSE_LogicalMapRead() does, and read only the used data
|
||||||
|
EFUSE_LogicalMap_Read(efuse);
|
||||||
|
memcpy(id, efuse + 0x11A + 3, 3);
|
||||||
|
free(efuse);
|
||||||
|
return chipId;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *lt_cpu_get_core_type() {
|
||||||
|
return "ARM Cortex-M4F (ARMv7E-M)";
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t lt_cpu_get_freq() {
|
||||||
|
return CPU_ClkGet(false);
|
||||||
|
}
|
||||||
39
cores/realtek-ambz/base/api/lt_device.c
Normal file
39
cores/realtek-ambz/base/api/lt_device.c
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
/* Copyright (c) Kuba Szczodrzyński 2023-02-27. */
|
||||||
|
|
||||||
|
#include <libretiny.h>
|
||||||
|
#include <sdk_private.h>
|
||||||
|
|
||||||
|
void lt_get_device_mac(uint8_t *mac) {
|
||||||
|
uint8_t *efuse = (uint8_t *)malloc(512);
|
||||||
|
EFUSE_LogicalMap_Read(efuse);
|
||||||
|
memcpy(mac, efuse + 0x11A, 6);
|
||||||
|
free(efuse);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool lt_reboot_download_mode() {
|
||||||
|
// mww 0x40000138 0x8
|
||||||
|
HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_NORESET_FF, 0x08);
|
||||||
|
// reboot it the ugly way
|
||||||
|
sys_reset();
|
||||||
|
while (1) {}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool lt_set_debug_mode(lt_debug_mode_t mode) {
|
||||||
|
uint32_t *swd;
|
||||||
|
switch (mode) {
|
||||||
|
case DEBUG_MODE_OFF:
|
||||||
|
sys_jtag_off();
|
||||||
|
Pinmux_Config(PA_14, PINMUX_FUNCTION_GPIO);
|
||||||
|
Pinmux_Config(PA_15, PINMUX_FUNCTION_GPIO);
|
||||||
|
return true;
|
||||||
|
case DEBUG_MODE_SWD:
|
||||||
|
Pinmux_Config(PA_14, PINMUX_FUNCTION_SWD);
|
||||||
|
Pinmux_Config(PA_15, PINMUX_FUNCTION_SWD);
|
||||||
|
uint32_t *swd = (uint32_t *)0x400000A4;
|
||||||
|
*swd |= 0x1000;
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
14
cores/realtek-ambz/base/api/lt_flash.c
Normal file
14
cores/realtek-ambz/base/api/lt_flash.c
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
/* Copyright (c) Kuba Szczodrzyński 2023-02-27. */
|
||||||
|
|
||||||
|
#include <libretiny.h>
|
||||||
|
#include <sdk_private.h>
|
||||||
|
|
||||||
|
lt_flash_id_t lt_flash_get_id() {
|
||||||
|
lt_flash_id_t id;
|
||||||
|
uint8_t idBytes[3];
|
||||||
|
flash_read_id(NULL, idBytes, 3);
|
||||||
|
id.manufacturer_id = idBytes[0];
|
||||||
|
id.chip_id = idBytes[1];
|
||||||
|
id.chip_size_id = idBytes[2];
|
||||||
|
return id;
|
||||||
|
}
|
||||||
16
cores/realtek-ambz/base/api/lt_init.c
Normal file
16
cores/realtek-ambz/base/api/lt_init.c
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
/* Copyright (c) Kuba Szczodrzyński 2023-02-27. */
|
||||||
|
|
||||||
|
#include <libretiny.h>
|
||||||
|
#include <sdk_private.h>
|
||||||
|
|
||||||
|
extern uint32_t GlobalDebugEnable;
|
||||||
|
extern uint16_t GlobalDebugLevel;
|
||||||
|
extern uint8_t GlobalPrivateLog;
|
||||||
|
extern uint8_t lt_uart_port;
|
||||||
|
|
||||||
|
void lt_init_family() {
|
||||||
|
// make the SDK less verbose by default
|
||||||
|
GlobalDebugEnable = 0;
|
||||||
|
GlobalPrivateLog = 0;
|
||||||
|
lt_uart_port = LT_UART_DEFAULT_PORT;
|
||||||
|
}
|
||||||
8
cores/realtek-ambz/base/api/lt_mem.c
Normal file
8
cores/realtek-ambz/base/api/lt_mem.c
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
/* Copyright (c) Kuba Szczodrzyński 2023-02-27. */
|
||||||
|
|
||||||
|
#include <libretiny.h>
|
||||||
|
#include <sdk_private.h>
|
||||||
|
|
||||||
|
uint32_t lt_ram_get_size() {
|
||||||
|
return 256 * 1024;
|
||||||
|
}
|
||||||
78
cores/realtek-ambz/base/api/lt_ota.c
Normal file
78
cores/realtek-ambz/base/api/lt_ota.c
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
/* Copyright (c) Kuba Szczodrzyński 2023-02-27. */
|
||||||
|
|
||||||
|
#include <libretiny.h>
|
||||||
|
#include <sdk_private.h>
|
||||||
|
|
||||||
|
lt_ota_type_t lt_ota_get_type() {
|
||||||
|
return OTA_TYPE_DUAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool lt_ota_is_valid(uint8_t index) {
|
||||||
|
uint32_t offset;
|
||||||
|
switch (index) {
|
||||||
|
case 1:
|
||||||
|
offset = FLASH_OTA1_OFFSET;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
offset = FLASH_OTA2_OFFSET;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
uint8_t *address = (uint8_t *)(SPI_FLASH_BASE + offset);
|
||||||
|
return memcmp(address, "81958711", 8) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t lt_ota_dual_get_current() {
|
||||||
|
// RTL8710B is XIP, so check the code offset in flash
|
||||||
|
uint32_t addr = (uint32_t)lt_log;
|
||||||
|
uint32_t offs = addr - SPI_FLASH_BASE;
|
||||||
|
return offs > FLASH_OTA2_OFFSET ? 2 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t lt_ota_dual_get_stored() {
|
||||||
|
uint32_t *ota_address = (uint32_t *)0x8009000;
|
||||||
|
if (*ota_address == 0xFFFFFFFF)
|
||||||
|
return 1;
|
||||||
|
uint32_t ota_counter = *((uint32_t *)0x8009004);
|
||||||
|
// even count of zero-bits means OTA1, odd count means OTA2
|
||||||
|
// this allows to switch OTA images by simply clearing next bits,
|
||||||
|
// without needing to erase the flash
|
||||||
|
uint8_t count = 0;
|
||||||
|
for (uint8_t i = 0; i < 32; i++) {
|
||||||
|
if ((ota_counter & (1 << i)) == 0)
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
return 1 + (count % 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool lt_ota_switch(bool revert) {
|
||||||
|
uint8_t current = lt_ota_dual_get_current();
|
||||||
|
uint8_t stored = lt_ota_dual_get_stored();
|
||||||
|
if ((current == stored) == revert)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (!lt_ota_is_valid(stored ^ 0b11))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// - read current OTA switch value from 0x9004
|
||||||
|
// - reset OTA switch to 0xFFFFFFFE if it's 0x0
|
||||||
|
// - else check first non-zero bit of OTA switch
|
||||||
|
// - write OTA switch with first non-zero bit cleared
|
||||||
|
|
||||||
|
uint32_t value = HAL_READ32(SPI_FLASH_BASE, FLASH_SYSTEM_OFFSET + 4);
|
||||||
|
if (value == 0) {
|
||||||
|
uint8_t *system = (uint8_t *)malloc(64);
|
||||||
|
lt_flash_read(FLASH_SYSTEM_OFFSET, system, 64);
|
||||||
|
// reset OTA switch
|
||||||
|
((uint32_t *)system)[1] = -2;
|
||||||
|
lt_flash_erase_block(FLASH_SYSTEM_OFFSET);
|
||||||
|
return lt_flash_write(FLASH_SYSTEM_OFFSET, system, 64);
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear first non-zero bit
|
||||||
|
value <<= 1;
|
||||||
|
// write OTA switch to flash
|
||||||
|
flash_write_word(NULL, FLASH_SYSTEM_OFFSET + 4, value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
@@ -1,201 +0,0 @@
|
|||||||
/* Copyright (c) Kuba Szczodrzyński 2023-02-27. */
|
|
||||||
|
|
||||||
#include <libretiny.h>
|
|
||||||
#include <sdk_private.h>
|
|
||||||
|
|
||||||
extern uint32_t GlobalDebugEnable;
|
|
||||||
extern uint16_t GlobalDebugLevel;
|
|
||||||
extern uint8_t GlobalPrivateLog;
|
|
||||||
extern uint8_t lt_uart_port;
|
|
||||||
|
|
||||||
void lt_init_family() {
|
|
||||||
// make the SDK less verbose by default
|
|
||||||
GlobalDebugEnable = 0;
|
|
||||||
GlobalPrivateLog = 0;
|
|
||||||
lt_uart_port = LT_UART_DEFAULT_PORT;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* _____ _____ _ _
|
|
||||||
/ ____| __ \| | | |
|
|
||||||
| | | |__) | | | |
|
|
||||||
| | | ___/| | | |
|
|
||||||
| |____| | | |__| |
|
|
||||||
\_____|_| \____*/
|
|
||||||
lt_cpu_model_t lt_cpu_get_model() {
|
|
||||||
uint8_t chipId;
|
|
||||||
EFUSE_OneByteReadROM(9902, 0xF8, &chipId, L25EOUTVOLTAGE);
|
|
||||||
return CPU_MODEL_ENUM(FAMILY, chipId);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t lt_cpu_get_mac_id() {
|
|
||||||
uint32_t chipId = 0;
|
|
||||||
uint8_t *id = (uint8_t *)&chipId;
|
|
||||||
// 9902 was extracted from ROM disassembly, probably not needed
|
|
||||||
/* EFUSE_OneByteReadROM(9902, 0x3B, id + 0, L25EOUTVOLTAGE);
|
|
||||||
EFUSE_OneByteReadROM(9902, 0x3C, id + 1, L25EOUTVOLTAGE);
|
|
||||||
EFUSE_OneByteReadROM(9902, 0x3D, id + 2, L25EOUTVOLTAGE); */
|
|
||||||
// new method, based on EFUSE logical map
|
|
||||||
uint8_t *efuse = (uint8_t *)malloc(512);
|
|
||||||
// TODO do what EFUSE_LogicalMapRead() does, and read only the used data
|
|
||||||
EFUSE_LogicalMap_Read(efuse);
|
|
||||||
memcpy(id, efuse + 0x11A + 3, 3);
|
|
||||||
free(efuse);
|
|
||||||
return chipId;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *lt_cpu_get_core_type() {
|
|
||||||
return "ARM Cortex-M4F (ARMv7E-M)";
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t lt_cpu_get_freq() {
|
|
||||||
return CPU_ClkGet(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*_____ _
|
|
||||||
| __ \ (_)
|
|
||||||
| | | | _____ ___ ___ ___
|
|
||||||
| | | |/ _ \ \ / / |/ __/ _ \
|
|
||||||
| |__| | __/\ V /| | (_| __/
|
|
||||||
|_____/ \___| \_/ |_|\___\__*/
|
|
||||||
void lt_get_device_mac(uint8_t *mac) {
|
|
||||||
uint8_t *efuse = (uint8_t *)malloc(512);
|
|
||||||
EFUSE_LogicalMap_Read(efuse);
|
|
||||||
memcpy(mac, efuse + 0x11A, 6);
|
|
||||||
free(efuse);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool lt_reboot_download_mode() {
|
|
||||||
// mww 0x40000138 0x8
|
|
||||||
HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_NORESET_FF, 0x08);
|
|
||||||
// reboot it the ugly way
|
|
||||||
sys_reset();
|
|
||||||
while (1) {}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool lt_set_debug_mode(lt_debug_mode_t mode) {
|
|
||||||
uint32_t *swd;
|
|
||||||
switch (mode) {
|
|
||||||
case DEBUG_MODE_OFF:
|
|
||||||
sys_jtag_off();
|
|
||||||
Pinmux_Config(PA_14, PINMUX_FUNCTION_GPIO);
|
|
||||||
Pinmux_Config(PA_15, PINMUX_FUNCTION_GPIO);
|
|
||||||
return true;
|
|
||||||
case DEBUG_MODE_SWD:
|
|
||||||
Pinmux_Config(PA_14, PINMUX_FUNCTION_SWD);
|
|
||||||
Pinmux_Config(PA_15, PINMUX_FUNCTION_SWD);
|
|
||||||
uint32_t *swd = (uint32_t *)0x400000A4;
|
|
||||||
*swd |= 0x1000;
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*______ _ _
|
|
||||||
| ____| | | |
|
|
||||||
| |__ | | __ _ ___| |__
|
|
||||||
| __| | |/ _` / __| '_ \
|
|
||||||
| | | | (_| \__ \ | | |
|
|
||||||
|_| |_|\__,_|___/_| |*/
|
|
||||||
lt_flash_id_t lt_flash_get_id() {
|
|
||||||
lt_flash_id_t id;
|
|
||||||
uint8_t idBytes[3];
|
|
||||||
flash_read_id(NULL, idBytes, 3);
|
|
||||||
id.manufacturer_id = idBytes[0];
|
|
||||||
id.chip_id = idBytes[1];
|
|
||||||
id.chip_size_id = idBytes[2];
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*__ __
|
|
||||||
| \/ |
|
|
||||||
| \ / | ___ _ __ ___ ___ _ __ _ _
|
|
||||||
| |\/| |/ _ \ '_ ` _ \ / _ \| '__| | | |
|
|
||||||
| | | | __/ | | | | | (_) | | | |_| |
|
|
||||||
|_| |_|\___|_| |_| |_|\___/|_| \__, |
|
|
||||||
__/ |
|
|
||||||
|__*/
|
|
||||||
uint32_t lt_ram_get_size() {
|
|
||||||
return 256 * 1024;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ____ _______
|
|
||||||
/ __ \__ __|/\
|
|
||||||
| | | | | | / \
|
|
||||||
| | | | | | / /\ \
|
|
||||||
| |__| | | |/ ____ \
|
|
||||||
\____/ |_/_/ \*/
|
|
||||||
lt_ota_type_t lt_ota_get_type() {
|
|
||||||
return OTA_TYPE_DUAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool lt_ota_is_valid(uint8_t index) {
|
|
||||||
uint32_t offset;
|
|
||||||
switch (index) {
|
|
||||||
case 1:
|
|
||||||
offset = FLASH_OTA1_OFFSET;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
offset = FLASH_OTA2_OFFSET;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
uint8_t *address = (uint8_t *)(SPI_FLASH_BASE + offset);
|
|
||||||
return memcmp(address, "81958711", 8) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t lt_ota_dual_get_current() {
|
|
||||||
// RTL8710B is XIP, so check the code offset in flash
|
|
||||||
uint32_t addr = (uint32_t)lt_log;
|
|
||||||
uint32_t offs = addr - SPI_FLASH_BASE;
|
|
||||||
return offs > FLASH_OTA2_OFFSET ? 2 : 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t lt_ota_dual_get_stored() {
|
|
||||||
uint32_t *ota_address = (uint32_t *)0x8009000;
|
|
||||||
if (*ota_address == 0xFFFFFFFF)
|
|
||||||
return 1;
|
|
||||||
uint32_t ota_counter = *((uint32_t *)0x8009004);
|
|
||||||
// even count of zero-bits means OTA1, odd count means OTA2
|
|
||||||
// this allows to switch OTA images by simply clearing next bits,
|
|
||||||
// without needing to erase the flash
|
|
||||||
uint8_t count = 0;
|
|
||||||
for (uint8_t i = 0; i < 32; i++) {
|
|
||||||
if ((ota_counter & (1 << i)) == 0)
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
return 1 + (count % 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool lt_ota_switch(bool revert) {
|
|
||||||
uint8_t current = lt_ota_dual_get_current();
|
|
||||||
uint8_t stored = lt_ota_dual_get_stored();
|
|
||||||
if ((current == stored) == revert)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (!lt_ota_is_valid(stored ^ 0b11))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// - read current OTA switch value from 0x9004
|
|
||||||
// - reset OTA switch to 0xFFFFFFFE if it's 0x0
|
|
||||||
// - else check first non-zero bit of OTA switch
|
|
||||||
// - write OTA switch with first non-zero bit cleared
|
|
||||||
|
|
||||||
uint32_t value = HAL_READ32(SPI_FLASH_BASE, FLASH_SYSTEM_OFFSET + 4);
|
|
||||||
if (value == 0) {
|
|
||||||
uint8_t *system = (uint8_t *)malloc(64);
|
|
||||||
lt_flash_read(FLASH_SYSTEM_OFFSET, system, 64);
|
|
||||||
// reset OTA switch
|
|
||||||
((uint32_t *)system)[1] = -2;
|
|
||||||
lt_flash_erase_block(FLASH_SYSTEM_OFFSET);
|
|
||||||
return lt_flash_write(FLASH_SYSTEM_OFFSET, system, 64);
|
|
||||||
}
|
|
||||||
|
|
||||||
// clear first non-zero bit
|
|
||||||
value <<= 1;
|
|
||||||
// write OTA switch to flash
|
|
||||||
flash_write_word(NULL, FLASH_SYSTEM_OFFSET + 4, value);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
21
cores/realtek-ambz2/base/api/lt_cpu.c
Normal file
21
cores/realtek-ambz2/base/api/lt_cpu.c
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
/* Copyright (c) Kuba Szczodrzyński 2023-05-22. */
|
||||||
|
|
||||||
|
#include <libretiny.h>
|
||||||
|
#include <sdk_private.h>
|
||||||
|
|
||||||
|
lt_cpu_model_t lt_cpu_get_model() {
|
||||||
|
uint32_t *addr = (uint32_t *)0x40000038;
|
||||||
|
uint8_t flash_mode = (addr[0] >> 5) & 0b11;
|
||||||
|
uint32_t chip_id = 0;
|
||||||
|
hal_get_chip_id(&chip_id);
|
||||||
|
chip_id <<= 2;
|
||||||
|
return CPU_MODEL_ENUM(FAMILY, (chip_id & 0xFF) | flash_mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *lt_cpu_get_core_type() {
|
||||||
|
return "ARM Cortex-M33 (ARMv8-M)";
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t lt_cpu_get_freq() {
|
||||||
|
return hal_syson_query_sys_clk();
|
||||||
|
}
|
||||||
61
cores/realtek-ambz2/base/api/lt_device.c
Normal file
61
cores/realtek-ambz2/base/api/lt_device.c
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
/* Copyright (c) Kuba Szczodrzyński 2023-05-22. */
|
||||||
|
|
||||||
|
#include <libretiny.h>
|
||||||
|
#include <sdk_private.h>
|
||||||
|
|
||||||
|
void lt_get_device_mac(uint8_t *mac) {
|
||||||
|
efuse_logical_read(0x11A, 6, mac);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lt_reboot() {
|
||||||
|
sys_cpu_reset();
|
||||||
|
while (1) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool lt_reboot_download_mode() {
|
||||||
|
sys_uart_download_mode();
|
||||||
|
while (1) {}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
lt_reboot_reason_t lt_get_reboot_reason() {
|
||||||
|
hal_reset_reason_t reason = -1;
|
||||||
|
rtl8710c_reset_reason_get(&reason);
|
||||||
|
switch (reason) {
|
||||||
|
case HAL_RESET_REASON_POWER_ON:
|
||||||
|
return REBOOT_REASON_POWER;
|
||||||
|
case HAL_RESET_REASON_SOFTWARE:
|
||||||
|
return REBOOT_REASON_SOFTWARE;
|
||||||
|
case HAL_RESET_REASON_WATCHDOG:
|
||||||
|
return REBOOT_REASON_WATCHDOG;
|
||||||
|
case HAL_RESET_REASON_JTAG:
|
||||||
|
return REBOOT_REASON_DEBUGGER;
|
||||||
|
default:
|
||||||
|
return REBOOT_REASON_UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool lt_set_debug_mode(lt_debug_mode_t mode) {
|
||||||
|
switch (mode) {
|
||||||
|
case DEBUG_MODE_OFF:
|
||||||
|
if (hal_misc_jtag_pin_ctrl(0) != HAL_OK)
|
||||||
|
return false;
|
||||||
|
if (hal_misc_swd_pin_ctrl(0) != HAL_OK)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
case DEBUG_MODE_JTAG:
|
||||||
|
if (hal_misc_swd_pin_ctrl(0) != HAL_OK)
|
||||||
|
return false;
|
||||||
|
if (hal_misc_jtag_pin_ctrl(1) != HAL_OK)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
case DEBUG_MODE_SWD:
|
||||||
|
if (hal_misc_jtag_pin_ctrl(0) != HAL_OK)
|
||||||
|
return false;
|
||||||
|
if (hal_misc_swd_pin_ctrl(1) != HAL_OK)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
14
cores/realtek-ambz2/base/api/lt_init.c
Normal file
14
cores/realtek-ambz2/base/api/lt_init.c
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
/* Copyright (c) Kuba Szczodrzyński 2023-05-22. */
|
||||||
|
|
||||||
|
#include <libretiny.h>
|
||||||
|
#include <sdk_private.h>
|
||||||
|
|
||||||
|
extern uint8_t lt_uart_port;
|
||||||
|
|
||||||
|
void lt_init_family() {
|
||||||
|
// make the SDK less verbose by default
|
||||||
|
ConfigDebugErr = _DBG_MISC_ | _DBG_FAULT_ | _DBG_BOOT_;
|
||||||
|
ConfigDebugWarn = 0;
|
||||||
|
ConfigDebugInfo = 0;
|
||||||
|
lt_uart_port = LT_UART_DEFAULT_PORT;
|
||||||
|
}
|
||||||
8
cores/realtek-ambz2/base/api/lt_mem.c
Normal file
8
cores/realtek-ambz2/base/api/lt_mem.c
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
/* Copyright (c) Kuba Szczodrzyński 2023-05-22. */
|
||||||
|
|
||||||
|
#include <libretiny.h>
|
||||||
|
#include <sdk_private.h>
|
||||||
|
|
||||||
|
uint32_t lt_ram_get_size() {
|
||||||
|
return 256 * 1024;
|
||||||
|
}
|
||||||
24
cores/realtek-ambz2/base/api/lt_ota.c
Normal file
24
cores/realtek-ambz2/base/api/lt_ota.c
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
/* Copyright (c) Kuba Szczodrzyński 2023-05-22. */
|
||||||
|
|
||||||
|
#include <libretiny.h>
|
||||||
|
#include <sdk_private.h>
|
||||||
|
|
||||||
|
lt_ota_type_t lt_ota_get_type() {
|
||||||
|
return OTA_TYPE_DUAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool lt_ota_is_valid(uint8_t index) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t lt_ota_dual_get_current() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t lt_ota_dual_get_stored() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool lt_ota_switch(bool revert) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
@@ -1,138 +0,0 @@
|
|||||||
/* Copyright (c) Kuba Szczodrzyński 2023-05-22. */
|
|
||||||
|
|
||||||
#include <libretiny.h>
|
|
||||||
#include <sdk_private.h>
|
|
||||||
|
|
||||||
extern uint8_t lt_uart_port;
|
|
||||||
|
|
||||||
void lt_init_family() {
|
|
||||||
// make the SDK less verbose by default
|
|
||||||
ConfigDebugErr = _DBG_MISC_ | _DBG_FAULT_ | _DBG_BOOT_;
|
|
||||||
ConfigDebugWarn = 0;
|
|
||||||
ConfigDebugInfo = 0;
|
|
||||||
lt_uart_port = LT_UART_DEFAULT_PORT;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* _____ _____ _ _
|
|
||||||
/ ____| __ \| | | |
|
|
||||||
| | | |__) | | | |
|
|
||||||
| | | ___/| | | |
|
|
||||||
| |____| | | |__| |
|
|
||||||
\_____|_| \____*/
|
|
||||||
lt_cpu_model_t lt_cpu_get_model() {
|
|
||||||
uint32_t *addr = (uint32_t *)0x40000038;
|
|
||||||
uint8_t flash_mode = (addr[0] >> 5) & 0b11;
|
|
||||||
uint32_t chip_id = 0;
|
|
||||||
hal_get_chip_id(&chip_id);
|
|
||||||
chip_id <<= 2;
|
|
||||||
return CPU_MODEL_ENUM(FAMILY, (chip_id & 0xFF) | flash_mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *lt_cpu_get_core_type() {
|
|
||||||
return "ARM Cortex-M33 (ARMv8-M)";
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t lt_cpu_get_freq() {
|
|
||||||
return hal_syson_query_sys_clk();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*_____ _
|
|
||||||
| __ \ (_)
|
|
||||||
| | | | _____ ___ ___ ___
|
|
||||||
| | | |/ _ \ \ / / |/ __/ _ \
|
|
||||||
| |__| | __/\ V /| | (_| __/
|
|
||||||
|_____/ \___| \_/ |_|\___\__*/
|
|
||||||
void lt_get_device_mac(uint8_t *mac) {
|
|
||||||
efuse_logical_read(0x11A, 6, mac);
|
|
||||||
}
|
|
||||||
|
|
||||||
void lt_reboot() {
|
|
||||||
sys_cpu_reset();
|
|
||||||
while (1) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool lt_reboot_download_mode() {
|
|
||||||
sys_uart_download_mode();
|
|
||||||
while (1) {}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
lt_reboot_reason_t lt_get_reboot_reason() {
|
|
||||||
hal_reset_reason_t reason = -1;
|
|
||||||
rtl8710c_reset_reason_get(&reason);
|
|
||||||
switch (reason) {
|
|
||||||
case HAL_RESET_REASON_POWER_ON:
|
|
||||||
return REBOOT_REASON_POWER;
|
|
||||||
case HAL_RESET_REASON_SOFTWARE:
|
|
||||||
return REBOOT_REASON_SOFTWARE;
|
|
||||||
case HAL_RESET_REASON_WATCHDOG:
|
|
||||||
return REBOOT_REASON_WATCHDOG;
|
|
||||||
case HAL_RESET_REASON_JTAG:
|
|
||||||
return REBOOT_REASON_DEBUGGER;
|
|
||||||
default:
|
|
||||||
return REBOOT_REASON_UNKNOWN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool lt_set_debug_mode(lt_debug_mode_t mode) {
|
|
||||||
switch (mode) {
|
|
||||||
case DEBUG_MODE_OFF:
|
|
||||||
if (hal_misc_jtag_pin_ctrl(0) != HAL_OK)
|
|
||||||
return false;
|
|
||||||
if (hal_misc_swd_pin_ctrl(0) != HAL_OK)
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
case DEBUG_MODE_JTAG:
|
|
||||||
if (hal_misc_swd_pin_ctrl(0) != HAL_OK)
|
|
||||||
return false;
|
|
||||||
if (hal_misc_jtag_pin_ctrl(1) != HAL_OK)
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
case DEBUG_MODE_SWD:
|
|
||||||
if (hal_misc_jtag_pin_ctrl(0) != HAL_OK)
|
|
||||||
return false;
|
|
||||||
if (hal_misc_swd_pin_ctrl(1) != HAL_OK)
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*__ __
|
|
||||||
| \/ |
|
|
||||||
| \ / | ___ _ __ ___ ___ _ __ _ _
|
|
||||||
| |\/| |/ _ \ '_ ` _ \ / _ \| '__| | | |
|
|
||||||
| | | | __/ | | | | | (_) | | | |_| |
|
|
||||||
|_| |_|\___|_| |_| |_|\___/|_| \__, |
|
|
||||||
__/ |
|
|
||||||
|__*/
|
|
||||||
uint32_t lt_ram_get_size() {
|
|
||||||
return 256 * 1024;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ____ _______
|
|
||||||
/ __ \__ __|/\
|
|
||||||
| | | | | | / \
|
|
||||||
| | | | | | / /\ \
|
|
||||||
| |__| | | |/ ____ \
|
|
||||||
\____/ |_/_/ \*/
|
|
||||||
lt_ota_type_t lt_ota_get_type() {
|
|
||||||
return OTA_TYPE_DUAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool lt_ota_is_valid(uint8_t index) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t lt_ota_dual_get_current() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t lt_ota_dual_get_stored() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool lt_ota_switch(bool revert) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
13
docs/contrib/lt-api.md
Normal file
13
docs/contrib/lt-api.md
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
# API functions guide
|
||||||
|
|
||||||
|
The [LibreTiny C API](../dev/lt-api.md) functions are split between three types: common, weak and family.
|
||||||
|
|
||||||
|
- Common functions are implemented in the base, common core and are the same between all families.
|
||||||
|
- Weak functions are provided in the common core, but can (and sometimes should) be overridden by family cores. They sometimes provide usable default implementations (which *can* be overriden to provide e.g. a better way to do something), otherwise they're empty (e.g. if a family doesn't support such a feature).
|
||||||
|
- Family functions are not provided in the common core and have to be implemented in the family core.
|
||||||
|
|
||||||
|
A quick outline of all available functions and their types:
|
||||||
|
|
||||||
|
{%
|
||||||
|
include-markdown "lt-api-functions.md"
|
||||||
|
%}
|
||||||
@@ -31,6 +31,7 @@ Here's what has to be done to make that work:
|
|||||||
5. Add base core code.
|
5. Add base core code.
|
||||||
|
|
||||||
- `lt_defs.h`, `lt_family.h` and `lt_api.c` files need to be created, and initialized with (even empty) functions and definitions.
|
- `lt_defs.h`, `lt_family.h` and `lt_api.c` files need to be created, and initialized with (even empty) functions and definitions.
|
||||||
|
- The list of family functions can be found [here](lt-api.md).
|
||||||
- Make the SDK call `lt_main()` as the entrypoint. If needed, use fixups.
|
- Make the SDK call `lt_main()` as the entrypoint. If needed, use fixups.
|
||||||
|
|
||||||
6. Write a binary manipulation tool.
|
6. Write a binary manipulation tool.
|
||||||
|
|||||||
6
docs/script.js
Normal file
6
docs/script.js
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
document$.subscribe(function () {
|
||||||
|
var tables = document.querySelectorAll("article table:not([class])")
|
||||||
|
tables.forEach(function (table) {
|
||||||
|
new Tablesort(table)
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import json
|
import json
|
||||||
|
|
||||||
from ltchiptool import Board
|
from ltchiptool import Board
|
||||||
from update_docs import board_obj_sort
|
from write_boards import board_obj_sort
|
||||||
|
|
||||||
boards = map(Board, Board.get_list())
|
boards = map(Board, Board.get_list())
|
||||||
boards = list(sorted(boards, key=board_obj_sort))
|
boards = list(sorted(boards, key=board_obj_sort))
|
||||||
|
|||||||
125
docs/scripts/write_apis.py
Normal file
125
docs/scripts/write_apis.py
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
# Copyright (c) Kuba Szczodrzyński 2023-06-22.
|
||||||
|
|
||||||
|
import re
|
||||||
|
from glob import glob
|
||||||
|
from os.path import dirname, join
|
||||||
|
|
||||||
|
import colorama
|
||||||
|
from colorama import Fore, Style
|
||||||
|
from markdown import Markdown
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
colorama.init()
|
||||||
|
|
||||||
|
api_path = join(dirname(__file__), "..", "..", "cores/common/base/api/lt_*.*")
|
||||||
|
out_path = join(dirname(__file__), "..", "contrib")
|
||||||
|
|
||||||
|
declaration = ""
|
||||||
|
implementation = ""
|
||||||
|
|
||||||
|
for file in glob(api_path):
|
||||||
|
with open(file, "r") as f:
|
||||||
|
data = f.read()
|
||||||
|
if file.endswith(".h"):
|
||||||
|
declaration += data
|
||||||
|
elif file.endswith(".c"):
|
||||||
|
implementation += data
|
||||||
|
|
||||||
|
block_comment_regex = r"\/\*[\d\D]+?\*\/"
|
||||||
|
line_comment_regex = r"\/\/.+?$"
|
||||||
|
macro_regex = r"#(?:[^\n\\]|\\\n)+$"
|
||||||
|
line_regex = r"\n+"
|
||||||
|
declaration = re.sub(block_comment_regex, "", declaration)
|
||||||
|
declaration = re.sub(line_comment_regex, "", declaration, flags=re.MULTILINE)
|
||||||
|
declaration = re.sub(macro_regex, "", declaration, flags=re.MULTILINE)
|
||||||
|
declaration = re.sub(line_regex, "\n", declaration)
|
||||||
|
implementation = re.sub(block_comment_regex, "", implementation)
|
||||||
|
implementation = re.sub(line_comment_regex, "", implementation, flags=re.MULTILINE)
|
||||||
|
implementation = re.sub(macro_regex, "", implementation, flags=re.MULTILINE)
|
||||||
|
implementation = re.sub(line_regex, "\n", implementation)
|
||||||
|
|
||||||
|
declaration_regex = r"^([\d\w\s]+ \*?)([\S]+?)\(.*?\);$"
|
||||||
|
implementation_regex = r"^(__attribute__\(\(weak\)\) )?([\w\d* ]+?)([\w\d]+)\(.+?{"
|
||||||
|
|
||||||
|
function_types = {}
|
||||||
|
decl_functions = set()
|
||||||
|
impl_functions = set()
|
||||||
|
weak_functions = set()
|
||||||
|
|
||||||
|
for match in re.finditer(
|
||||||
|
pattern=declaration_regex,
|
||||||
|
string=declaration,
|
||||||
|
flags=re.DOTALL | re.MULTILINE,
|
||||||
|
):
|
||||||
|
function_type = match[1].strip()
|
||||||
|
function_name = match[2].strip()
|
||||||
|
|
||||||
|
if function_types.get(function_name, function_type) != function_type:
|
||||||
|
print(
|
||||||
|
Fore.YELLOW
|
||||||
|
+ "WARNING: Wrong return type: "
|
||||||
|
+ f"'{function_types[function_name]} {function_name}'"
|
||||||
|
+ f"vs '{function_type} {function_name}'"
|
||||||
|
+ Style.RESET_ALL
|
||||||
|
)
|
||||||
|
|
||||||
|
function_types[function_name] = function_type
|
||||||
|
decl_functions.add(function_name)
|
||||||
|
|
||||||
|
for match in re.finditer(
|
||||||
|
pattern=implementation_regex,
|
||||||
|
string=implementation,
|
||||||
|
flags=re.DOTALL | re.MULTILINE,
|
||||||
|
):
|
||||||
|
is_weak = match[1]
|
||||||
|
function_type = match[2].strip()
|
||||||
|
function_name = match[3].strip()
|
||||||
|
function_types[function_name] = function_type
|
||||||
|
|
||||||
|
if function_types.get(function_name, function_type) != function_type:
|
||||||
|
print(
|
||||||
|
Fore.YELLOW
|
||||||
|
+ "WARNING: Wrong return type: "
|
||||||
|
+ f"'{function_types[function_name]} {function_name}'"
|
||||||
|
+ f"vs '{function_type} {function_name}'"
|
||||||
|
+ Style.RESET_ALL
|
||||||
|
)
|
||||||
|
|
||||||
|
if is_weak:
|
||||||
|
weak_functions.add(function_name)
|
||||||
|
else:
|
||||||
|
impl_functions.add(function_name)
|
||||||
|
|
||||||
|
|
||||||
|
common_functions = impl_functions.union(weak_functions)
|
||||||
|
family_functions = decl_functions - common_functions
|
||||||
|
undecl_functions = common_functions - decl_functions
|
||||||
|
if undecl_functions:
|
||||||
|
print(Fore.RED + "ERROR: Undeclared functions: " + ", ".join(undecl_functions))
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
md = Markdown(out_path, "lt-api-functions")
|
||||||
|
header = [
|
||||||
|
"Type",
|
||||||
|
"Function",
|
||||||
|
"Common",
|
||||||
|
"Weak",
|
||||||
|
"Family",
|
||||||
|
]
|
||||||
|
rows = []
|
||||||
|
|
||||||
|
for function in (
|
||||||
|
sorted(family_functions) + sorted(weak_functions) + sorted(impl_functions)
|
||||||
|
):
|
||||||
|
rows.append(
|
||||||
|
[
|
||||||
|
f"`{function_types[function]}`",
|
||||||
|
f"{function}()",
|
||||||
|
"✔️" if function in impl_functions else "",
|
||||||
|
"✔️" if function in weak_functions else "",
|
||||||
|
"✔️" if function not in common_functions else "",
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
md.add_table(header, *rows)
|
||||||
|
md.write()
|
||||||
@@ -39,6 +39,10 @@ plugins:
|
|||||||
extra_css:
|
extra_css:
|
||||||
- docs/style.css
|
- docs/style.css
|
||||||
|
|
||||||
|
extra_javascript:
|
||||||
|
- https://unpkg.com/tablesort@5.3.0/dist/tablesort.min.js
|
||||||
|
- docs/script.js
|
||||||
|
|
||||||
markdown_extensions:
|
markdown_extensions:
|
||||||
- md_in_html
|
- md_in_html
|
||||||
- admonition
|
- admonition
|
||||||
|
|||||||
Reference in New Issue
Block a user