Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

riscv: telink: add functional features for tlsr9528 and tl3218 #362

Merged
merged 1 commit into from
Jan 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions config/telink/chip-module/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -213,4 +213,16 @@ if (CONFIG_CHIP_FACTORY_DATA_BUILD)
telink_generate_factory_data()
endif()

# ==============================================================================
# Define 'build_user_token' target for building the user token image
# ==============================================================================

if(DEFINED CONFIG_USER_TOKEN AND CONFIG_USER_TOKEN STREQUAL "y")
add_custom_target(build_user_token ALL
COMMAND ${Python3_EXECUTABLE} ${CHIP_ROOT}/examples/lighting-app/telink/process_token.py
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
)
add_dependencies(build_user_token ${ZEPHYR_FINAL_EXECUTABLE})
endif()

endif() # CONFIG_CHIP
8 changes: 8 additions & 0 deletions config/telink/chip-module/Kconfig.defaults
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,14 @@ config I2C_LED
default n
select I2C

config USER_TOKEN
bool "Generate the user token image"
default n

config STARTUP_OPTIMIZATION
bool "Optimize startup speed"
default n

# Set multiplicator of Name Value Storage (NVS) as 1 to reach NVS sector size 4KB
# nvs_sector_size = flash_page_size * mult = 4KB * 1 = 4KB
config SETTINGS_NVS_SECTOR_SIZE_MULT
Expand Down
233 changes: 233 additions & 0 deletions examples/lighting-app/telink/process_token.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
import json
import os


def find_json(json_path):
"""
Find token.json in given path.

Args:
json_path (string): The file path of token.json.

Returns:
json_data (structure): The json data structure.
"""
try:
with open(json_path, 'r') as f:
json_data = json.load(f)

except FileNotFoundError:
print(json_path + " is not find, abort.")
exit(1)

except json.JSONDecodeError:
print(json_path + " parse error, abort.")
exit(1)

return json_data


def get_json_data(json_data):
"""
Get the json data from token.json.

Args:
json_data (structure): The data structure of json.

Returns:
[ start_addr, sizeByte, write_data ]: The array of json data.
"""
startAddr = json_data.get("offset")
sizeByte = json_data.get("sizeB")
writeData = json_data.get("data")

return [startAddr, sizeByte, writeData]


def intervals_intersect(interval1, interval2):
if interval1[1] <= interval2[0] or interval1[0] >= interval2[1]:
return False # no intersection return False
else:
return True


def find_intersection(interval1, interval2):
if not intervals_intersect(interval1, interval2):
return []

start = max(interval1[0], interval2[0])
end = min(interval1[1], interval2[1])

return [hex(start), hex(end)]


def two_find_intersection(intervalArry, interval):
for inter in intervalArry:
intersection = find_intersection(inter, interval)
if len(intersection) != 0: # has intersection
print("Intersection: ", end="\n")
print(intersection, end="\n")
return -1
return 0


def curOffsetAddrCheck(curOffset, curSizeB, intervalArry, token_bin_size):
curOffset_INT = int(curOffset, 16)

result = two_find_intersection(
intervalArry,
[curOffset_INT + 0, curOffset_INT + curSizeB]
)
if result == (-1):
print("\ncurOffset: " + str(curOffset) + ",curSizeB: " + str(curSizeB), end="\n")

print("\nThe current write offset address is invalid,", end="\n")
print("there is a risk of overwriting the previous write interval,", end="\n")
print("abort!", end="\n")

exit(1)

if (curOffset_INT + curSizeB) >= token_bin_size:
print("curOffset: " + curOffset + ",curSizeB: " + curSizeB, end="\n")

print("The current write offset address is invalid,", end="\n")
print("exceed the write range of the token.bin,", end="\n")
print("abort!", end="\n")

exit(1)


def offsetNewSet(preOffset, preSizeB, curOffset):
_TMP_ = curOffset.split("0x")

if len(_TMP_) == 1: # use pre offset + pre sizeB to calculate cur offset
curOffset = hex(
int(preOffset, 16) + preSizeB
)

return curOffset


def covertData(data):
_TMP_ = data.split("0x")

if len(_TMP_) == 1:
return [format(ord(char), '02x') for char in _TMP_[0]]
else:
return [Str.strip().replace(',', '') for Str in _TMP_[1:]]


def adjustWrittenData(sizeB, data, offset, baseVAL="ff"):
dataLen = len(data)

if sizeB == dataLen:
return data
elif sizeB > dataLen:
return (data + ([baseVAL] * (sizeB - dataLen)))
elif sizeB < dataLen:
print("offset: " + str(offset) + ", sizeB: " + str(sizeB) + ", dataLen: " + str(dataLen), end="\n")
print("sizeB < len(data), illegal operation, abort!", end="\n")
exit(1)


def generate_token(token_bin_path, offset, data):
"""
Generate token.bin according to the data of token.json.

Args:
token_bin_path (string): The path of token.bin for new generate.
addr (int): Location of written data.
data (string): The data to be written.
"""
try:
with open(token_bin_path, 'r+b') as f:
f.seek(int(offset, 16))

for val in data:
f.write(bytes.fromhex(val))

except IOError:
print("An error occurred while open or write to the bin, abort.")
exit(1)


def main():
current_abs_path = os.path.dirname(os.path.abspath(__file__))
# print(current_abs_path)

token_json_path = current_abs_path + "/token.json"
token_bin_path = "./token.bin"

token_bin_size = 4096 # 4KB

# Create a bin with all values of '0xff'
with open(token_bin_path, 'wb+') as f:
f.write(bytes([0xff] * token_bin_size))

# Find the token.json.
_JSON_DATA_ = find_json(
token_json_path
)

preOffset = "null"
preSizeB = -1

intervalArry = []

for json_data in _JSON_DATA_:
# Get the json data.
offset, sizeB, data = get_json_data(json_data)

if (sizeB == 0):
continue

# Init preOffset and preSizeB.
if (preOffset == "null") or (preSizeB == -1):
preOffset = offset
preSizeB = sizeB

# Get a new offset addr.
newOffset = offsetNewSet(
preOffset,
preSizeB,
offset
)
# print(newOffset, end = "\t")
# print(sizeB, end = "\n")

# Check if the current write offset address is valid.
curOffsetAddrCheck(
newOffset,
sizeB,
intervalArry,
token_bin_size
)

# Covert input data and get the new write data.
covertArray = covertData(data)
newData = adjustWrittenData(sizeB, covertArray, newOffset, "ff")
# print(covertArray, end = "\n")
# print(newData, end = "\n\n")

# Generate token bin.
generate_token(
token_bin_path,
newOffset,
newData
)

# Update preOffset and preSizeB.
preOffset = newOffset
preSizeB = sizeB
# Use to two way find intersection.
intervalArry.append([
int(preOffset, 16) + 0,
int(preOffset, 16) + preSizeB
])
# print(intervalArry, end="\n\n")

print("Generate successfully for the token.bin.")


if __name__ == '__main__':
main()
78 changes: 78 additions & 0 deletions examples/lighting-app/telink/src/ZclCallbacks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,47 @@ LOG_MODULE_DECLARE(app, CONFIG_CHIP_APP_LOG_LEVEL);
using namespace chip;
using namespace chip::app::Clusters;

#if CONFIG_STARTUP_OPTIMIZATION
#include "AppTaskCommon.h"

static uint8_t latest_level = 0;
#define CLUTER_SOTRE_TIMEOUT 500
#define TRANSTION_TIMER_INIT_FLAG 0x55
#define TRANSTION_TIMER_DEINIT_FLAG 0x00

struct k_timer LevelChangeTimer;
static int timer_period = CLUTER_SOTRE_TIMEOUT;
static uint8_t init_timer = TRANSTION_TIMER_INIT_FLAG;

static void LevelTimeoutCallback(struct k_timer * timer)
{
if (!timer)
{
return;
}

cluster_startup_para cluster_para;
if (read_cluster_para(&cluster_para) != 0)
{
if (uart_init_flag)
{
printk("Fail read cluster parameter when execute LevelTimeoutCallback\n");
}
}
if (cluster_para.level != latest_level)
{
cluster_para.level = latest_level;
if (store_cluster_para(&cluster_para) != 0)
{
if (uart_init_flag)
{
printk("Fail store cluster parameter when execute LevelTimeoutCallback\n");
}
}
}
}
#endif // CONFIG_STARTUP_OPTIMIZATION

void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & attributePath, uint8_t type, uint16_t size,
uint8_t * value)
{
Expand Down Expand Up @@ -125,4 +166,41 @@ void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath &
}
}
#endif

#if CONFIG_STARTUP_OPTIMIZATION
if (init_timer == TRANSTION_TIMER_INIT_FLAG)
{
k_timer_init(&LevelChangeTimer, &LevelTimeoutCallback, nullptr);
init_timer = TRANSTION_TIMER_DEINIT_FLAG;
}

if (clusterId == OnOff::Id && attributeId == OnOff::Attributes::OnOff::Id)
{
cluster_startup_para cluster_para;
if (read_cluster_para(&cluster_para) != 0)
{
if (uart_init_flag)
{
printk("Fail read cluster parameter when clusterId is OnOff\n");
}
}
if (cluster_para.onoff != *value)
{
cluster_para.onoff = *value;
if (store_cluster_para(&cluster_para) != 0)
{
if (uart_init_flag)
{
printk("Fail store cluster parameter when clusterId is OnOff\n");
}
}
}
}
else if (clusterId == LevelControl::Id && attributeId == LevelControl::Attributes::CurrentLevel::Id)
{
latest_level = *value;
k_timer_stop(&LevelChangeTimer);
k_timer_start(&LevelChangeTimer, K_MSEC(timer_period), K_NO_WAIT);
}
#endif // CONFIG_STARTUP_OPTIMIZATION
}
Loading
Loading