From 55d3a7b0f042720f7e5d4aecc087622159468cb1 Mon Sep 17 00:00:00 2001 From: Haiwen Xia Date: Thu, 2 Jan 2025 19:48:14 +0800 Subject: [PATCH] riscv: telink: add dual mode for b92 and buteo and CI. - clean the boot flag in init part . - add the kDnsstimer to protect from init to dnss . - add special proc for ikea. - add the user-para proc in matter. - add 2m flash for buteo ,and 4m for b92. - update CI for b92 and tl3218x . - fix the switch logic part . Signed-off-by: Haiwen Xia --- config/telink/chip-module/Kconfig.defaults | 5 + .../lighting-app/telink/include/AppTask.h | 2 + examples/lighting-app/telink/src/AppTask.cpp | 131 ++++++++++++++++-- .../lighting-app/telink/src/ZclCallbacks.cpp | 9 ++ .../telink/common/include/AppTaskCommon.h | 32 ++++- .../telink/common/src/AppTaskCommon.cpp | 62 +++++++-- .../platform/telink/common/src/mainCommon.cpp | 37 +++++ src/platform/telink/FactoryDataProvider.cpp | 4 +- 8 files changed, 259 insertions(+), 23 deletions(-) diff --git a/config/telink/chip-module/Kconfig.defaults b/config/telink/chip-module/Kconfig.defaults index 7041c9ea1c23df..4d1c86f8e3de41 100644 --- a/config/telink/chip-module/Kconfig.defaults +++ b/config/telink/chip-module/Kconfig.defaults @@ -265,6 +265,11 @@ config COMPRESS_LZMA default y if SOC_RISCV_TELINK_TL321X default n +config CUSTOMER_MODE + bool "control the demo code" + default n if SOC_RISCV_TELINK_TL321X || SOC_RISCV_TELINK_B92 + default n + config DUAL_MODE_SWTICH bool "Control Dual-Mode Switching" default y if SOC_RISCV_TELINK_TL321X || SOC_RISCV_TELINK_B92 diff --git a/examples/lighting-app/telink/include/AppTask.h b/examples/lighting-app/telink/include/AppTask.h index d3327d1ed3f6b8..d9314bc596cfed 100644 --- a/examples/lighting-app/telink/include/AppTask.h +++ b/examples/lighting-app/telink/include/AppTask.h @@ -42,6 +42,8 @@ class AppTask : public AppTaskCommon bool IsTurnedOn() const; void SetInitiateAction(Fixture_Action aAction, int32_t aActor, uint8_t * value); void UpdateClusterState(void); + void Init_cluster_info(void); + void Set_cluster_info(void); private: friend AppTask & GetAppTask(void); diff --git a/examples/lighting-app/telink/src/AppTask.cpp b/examples/lighting-app/telink/src/AppTask.cpp index 28caf3dea8f067..61614cab028787 100644 --- a/examples/lighting-app/telink/src/AppTask.cpp +++ b/examples/lighting-app/telink/src/AppTask.cpp @@ -22,6 +22,9 @@ #include "ColorFormat.h" #include "LEDManager.h" #include "PWMManager.h" +#include +#include +#include #include @@ -55,22 +58,134 @@ void AppTask::PowerOnFactoryReset(void) } #endif /* CONFIG_CHIP_ENABLE_POWER_ON_FACTORY_RESET */ +#if CONFIG_CUSTOMER_MODE +void i2c_demo_proc() +{ + const uint8_t tx_buf[23] = { 0xc0, 0x63, 0x3f, 0x63, 0x63, 0x63, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, + 0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x2b, 0x06, 0xbe }; + /* add the i2c module here */ + printk("i2c demo start \n."); + uint32_t i2c_cfg = I2C_SPEED_SET(I2C_SPEED_FAST) | I2C_MODE_CONTROLLER; + /* get i2c device */ + int rc; + const struct i2c_dt_spec i2c = I2C_DT_SPEC_GET(DT_COMPAT_GET_ANY_STATUS_OKAY(ledcontrol_i2c)); + if (!device_is_ready(i2c.bus)) + { + printf("Device %s is not ready\n", i2c.bus->name); + return; + } + rc = i2c_configure(i2c.bus, i2c_cfg); + if (rc != 0) + { + printf("Failed to configure i2c device\n"); + return; + } + i2c_write(i2c.bus, tx_buf + 1, sizeof(tx_buf) - 1, tx_buf[0]); + printk("i2c demo stop ,finish transfer\n"); +} + +#define MATTER_COLORMODE_ENABLE 0 + +void AppTask::Set_cluster_info(void) +{ + printk("%%%%%%Set_cluster_info!!!!%%%%%%\n"); + light_para_t * p_para = &light_para; + Protocols::InteractionModel::Status status; + printk("%%%%%%Set_cluster_info:p_para->onoff:%d!!!!%%%%%%\n", p_para->onoff); + status = Clusters::OnOff::Attributes::OnOff::Set(1, p_para->onoff); + // Set brightness value + printk("%%%%%%Set_cluster_info:p_para->level:%d!!!!%%%%%%\n", p_para->level); + status = Clusters::LevelControl::Attributes::CurrentLevel::Set(kExampleEndpointId, p_para->level); + +#if MATTER_COLORMODE_ENABLE + // Set ColorMode value + printk("%%%%%%Set_cluster_info:p_para->color_mode:%d!!!!%%%%%%\n", p_para->color_mode); + status = Clusters::ColorControl::Attributes::ColorMode::Set(1, p_para->color_mode); +#endif + + // Set ColorTemperatureMireds value + status = Clusters::ColorControl::Attributes::ColorTemperatureMireds::Set(1, p_para->color_temp_mireds); + // Set CurrentX value + status = Clusters::ColorControl::Attributes::CurrentX::Set(1, p_para->currentx); + // Set CurrentY value + status = Clusters::ColorControl::Attributes::CurrentY::Set(1, p_para->currenty); + // Set EnhancedCurrentHue value + status = Clusters::ColorControl::Attributes::EnhancedCurrentHue::Set(1, p_para->enhanced_current_hue); + // Set CurrentHue value + status = Clusters::ColorControl::Attributes::CurrentHue::Set(1, p_para->cur_hue); + // Set CurrentSaturation value + status = Clusters::ColorControl::Attributes::CurrentSaturation::Set(1, p_para->cur_saturation); + // Set OnOffTransitionTime value + status = Clusters::LevelControl::Attributes::OnOffTransitionTime::Set(1, p_para->onoff_transition); +} + +void AppTask::Init_cluster_info(void) +{ + light_para_t * p_para = &light_para; + Protocols::InteractionModel::Status status; + bool onoff_sts; + status = Clusters::OnOff::Attributes::OnOff::Get(1, &(onoff_sts)); + p_para->onoff = (uint8_t) onoff_sts; + app::DataModel::Nullable brightness; + // Read brightness value + status = Clusters::LevelControl::Attributes::CurrentLevel::Get(kExampleEndpointId, brightness); + if (status == Protocols::InteractionModel::Status::Success && !brightness.IsNull()) + { + p_para->level = brightness.Value(); + } + +#if MATTER_COLORMODE_ENABLE + // Read ColorMode value + status = Clusters::ColorControl::Attributes::ColorMode::Get(1, &(p_para->color_mode)); +#endif + + // Read ColorTemperatureMireds value + status = Clusters::ColorControl::Attributes::ColorTemperatureMireds::Get(1, &(p_para->color_temp_mireds)); + + // Read CurrentX value + status = Clusters::ColorControl::Attributes::CurrentX::Get(1, &(p_para->currentx)); + + // Read CurrentY value + status = Clusters::ColorControl::Attributes::CurrentY::Get(1, &(p_para->currenty)); + + // Read EnhancedCurrentHue value + status = Clusters::ColorControl::Attributes::EnhancedCurrentHue::Get(1, &(p_para->enhanced_current_hue)); + + // Read CurrentHue value + status = Clusters::ColorControl::Attributes::CurrentHue::Get(1, &(p_para->cur_hue)); + + // Read CurrentSaturation value + status = Clusters::ColorControl::Attributes::CurrentSaturation::Get(1, &(p_para->cur_saturation)); + + // Read OnOffTransitionTime value + status = Clusters::LevelControl::Attributes::OnOffTransitionTime::Get(1, &(p_para->onoff_transition)); +} + +#endif + CHIP_ERROR AppTask::Init(void) { SetExampleButtonCallbacks(LightingActionEventHandler); InitCommonParts(); -#if CONFIG_DUAL_MODE_SWTICH - if (sBoot_zb) +#if CONFIG_CUSTOMER_MODE + if (user_para.val == USER_ZB_SW_VAL) { /* Switching from TouchLink (Zigbee) to Matter. Restore previous states. */ - sfixture_on = user_para.onoff; - sBrightness = user_para.lightness; - sAppTask.UpdateClusterState(); - printk("Matter: Restored Zigbee On/Off and brightness states.\n"); + Set_cluster_info(); } -#endif + else if (user_para.val == USER_MATTER_PAIR_VAL) + { + /* start from matter , add cluster info demo here*/ + Init_cluster_info(); + } + else + { + /* start from matter , but without zigbee fw*/ + } + /* if need , can call i2c_demo_proc here to see light works or not*/ +#else Protocols::InteractionModel::Status status; app::DataModel::Nullable brightness; @@ -91,7 +206,7 @@ CHIP_ERROR AppTask::Init(void) // Set actual state to stored before reboot SetInitiateAction(storedValue ? ON_ACTION : OFF_ACTION, static_cast(AppEvent::kEventType_DeviceAction), nullptr); } - +#endif return CHIP_NO_ERROR; } diff --git a/examples/lighting-app/telink/src/ZclCallbacks.cpp b/examples/lighting-app/telink/src/ZclCallbacks.cpp index e28d31c833de43..8b49fe6d3642ef 100644 --- a/examples/lighting-app/telink/src/ZclCallbacks.cpp +++ b/examples/lighting-app/telink/src/ZclCallbacks.cpp @@ -33,6 +33,14 @@ using namespace chip::app::Clusters; void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & attributePath, uint8_t type, uint16_t size, uint8_t * value) { +#if CONFIG_CUSTOMER_MODE + /* customer mode , add the customer code here for cb*/ + ClusterId clusterId = attributePath.mClusterId; + AttributeId attributeId = attributePath.mAttributeId; + ChipLogProgress(Zcl, "========MatterPostAttributeChangeCallback:clusterId=0x%x,AttributeId=0x%x,value=0x%x", clusterId, + attributeId, *value); + +#else static HsvColor_t hsv; static XyColor_t xy; ClusterId clusterId = attributePath.mClusterId; @@ -116,4 +124,5 @@ void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & ChipLogDetail(Zcl, "Ignore ColorControl attribute (%u) that is not currently processed!", attributeId); } } +#endif } diff --git a/examples/platform/telink/common/include/AppTaskCommon.h b/examples/platform/telink/common/include/AppTaskCommon.h index c50ededcfb337b..4440673b1e1db8 100644 --- a/examples/platform/telink/common/include/AppTaskCommon.h +++ b/examples/platform/telink/common/include/AppTaskCommon.h @@ -43,9 +43,22 @@ #include #include +#if CONFIG_SOC_RISCV_TELINK_B92 +#define ZB_NVS_PARTITION zigbee_partition +#define ZB_NVS_SEC_SIZE FIXED_PARTITION_SIZE(ZB_NVS_PARTITION) +#elif CONFIG_SOC_RISCV_TELINK_TL321X +#define ZB_NVS_PARTITION slot1_partition +/* zb para locate in the slot1 , and it will cost 104k size in slot1 */ +#define ZB_NVS_SEC_SIZE (104 * 1024) +#endif + +#define ZB_NVS_PARTITION_DEVICE FIXED_PARTITION_DEVICE(ZB_NVS_PARTITION) +#define ZB_NVS_START_ADR FIXED_PARTITION_OFFSET(ZB_NVS_PARTITION) + #define USER_INIT_VAL 0xff #define USER_ZB_SW_VAL 0xaa #define USER_MATTER_PAIR_VAL 0x55 +#define USER_MATTER_BACK_ZB 0xa0 // only commisiion fail will back to zb #define USER_PARA_MAC_OFFSET 0x100 #define USER_PARTITION user_para_partition #define USER_PARTITION_DEVICE FIXED_PARTITION_DEVICE(USER_PARTITION) @@ -55,11 +68,24 @@ typedef struct { uint8_t val; - uint8_t rfu; - uint8_t onoff; - uint8_t lightness; + uint8_t on_net; } user_para_t; +typedef struct +{ + uint8_t onoff; + uint8_t level; + uint16_t color_temp_mireds; + uint16_t currentx; + uint16_t currenty; + uint16_t enhanced_current_hue; + uint16_t onoff_transition; + uint8_t cur_hue; + uint8_t cur_saturation; + uint8_t color_mode; +} light_para_t; + +extern light_para_t light_para; extern user_para_t user_para; extern uint8_t para_lightness; extern uint8_t sBoot_zb; diff --git a/examples/platform/telink/common/src/AppTaskCommon.cpp b/examples/platform/telink/common/src/AppTaskCommon.cpp index f602a7d814026f..c7faaf7deafb76 100644 --- a/examples/platform/telink/common/src/AppTaskCommon.cpp +++ b/examples/platform/telink/common/src/AppTaskCommon.cpp @@ -47,13 +47,15 @@ #include #endif +#include #include #include #if CONFIG_DUAL_MODE_SWTICH -uint8_t sBoot_zb = 0; -user_para_t user_para; +uint8_t sBoot_zb = 0; uint8_t para_lightness = 0; +user_para_t user_para; +light_para_t light_para; #endif using namespace chip::app; @@ -75,6 +77,7 @@ constexpr uint32_t kIdentifyBreatheRateMs = 1000; #if CONFIG_DUAL_MODE_SWTICH const struct device * flash_para_dev = USER_PARTITION_DEVICE; +const struct device * zb_para_dev = ZB_NVS_PARTITION_DEVICE; constexpr int kDnssTimeout = 60000; static k_timer sDnssTimer; #endif @@ -143,6 +146,8 @@ void FactoryResetExtHandler(void) { // Erase the user parameters partition to reset mode settings flash_erase(flash_para_dev, USER_PARTITION_OFFSET, USER_PARTITION_SIZE); + // Erase ZigBee NVS data during factory reset + flash_erase(zb_para_dev, ZB_NVS_START_ADR, ZB_NVS_SEC_SIZE); } #endif @@ -232,6 +237,14 @@ void AppTaskCommon::PowerOnFactoryReset(void) #endif /* CONFIG_CHIP_ENABLE_POWER_ON_FACTORY_RESET */ #if CONFIG_DUAL_MODE_SWTICH + +void SwitchBackToZigbee() +{ + uint8_t switch_flag = USER_MATTER_BACK_ZB; + flash_write(flash_para_dev, USER_PARTITION_OFFSET, &switch_flag, 1); + sys_reboot(0); +} + void AppTaskCommon::DnssTimerTimeoutCallback(k_timer * timer) { if (!timer) @@ -242,8 +255,11 @@ void AppTaskCommon::DnssTimerTimeoutCallback(k_timer * timer) * If Dnss initialization takes longer than 60 seconds, * the device will reboot and revert to Zigbee mode. */ - printk("Matter: DnssTimer expired. Rebooting...\n"); - sys_reboot(0); + if (sBoot_zb) + { + printk("Matter: DnssTimer expired. Rebooting...\n"); + SwitchBackToZigbee(); + } } #endif @@ -257,25 +273,28 @@ CHIP_ERROR AppTaskCommon::StartApp(void) * a given timeframe. */ flash_read(flash_para_dev, USER_PARTITION_OFFSET, &user_para, sizeof(user_para)); + /* If booting from Zigbee mode, set a flag and clean deprecated parameter sectors. */ if (user_para.val == USER_ZB_SW_VAL) { sBoot_zb = 1; + /* If switching from ZigBee mode, get all existing clusters information. */ + flash_read(flash_para_dev, USER_PARTITION_OFFSET + sizeof(user_para), &light_para, sizeof(light_para)); /* Ensure brightness is at least 2 to avoid display issues on HomePod Mini */ - if (user_para.lightness < 2) + if (light_para.level < 2) { - user_para.lightness = 2; + light_para.level = 2; } /* * Pass the brightness value to the initialization code * to avoid gaps in PWM pool initialization. */ - if (user_para.onoff) + if (light_para.onoff) { - para_lightness = user_para.lightness; + para_lightness = light_para.level; } k_timer_init(&sDnssTimer, &AppTask::DnssTimerTimeoutCallback, nullptr); k_timer_start(&sDnssTimer, K_MSEC(kDnssTimeout), K_NO_WAIT); - printk("Matter: Started DNS protection timer. user_para=%x\n", *(int *) (&user_para)); + printk("Matter: Started DNS protection timer."); } #endif @@ -334,12 +353,17 @@ CHIP_ERROR AppTaskCommon::InitCommonParts(void) PrintFirmwareInfo(); +/* Leave empty condition clause for development on customers boards */ +#if CONFIG_CUSTOMER_MODE + +#else InitLeds(); UpdateStatusLED(); InitPwms(); InitButtons(); +#endif // Initialize function button timer k_timer_init(&sFactoryResetTimer, &AppTask::FactoryResetTimerTimeoutCallback, nullptr); @@ -823,6 +847,24 @@ void AppTaskCommon::ChipEventHandler(const ChipDeviceEvent * event, intptr_t /* #if CONFIG_DUAL_MODE_SWTICH case DeviceEventType::kCommissioningComplete: { uint8_t val = USER_MATTER_PAIR_VAL; +#if CONFIG_CUSTOMER_MODE + /* need to add here to update the cluster information , only in the zb switch and touchlink is paired*/ + if (user_para.val == USER_ZB_SW_VAL && user_para.on_net) + { + Protocols::InteractionModel::Status status; + /* Update all cluster information, only if switching from ZigBee mode and the touchlink is paired. */ + status = Clusters::OnOff::Attributes::OnOff::Set(kExampleEndpointId, light_para.onoff); + if (status != Protocols::InteractionModel::Status::Success) + { + LOG_ERR("Update OnOff fail: %x", to_underlying(status)); + } + status = Clusters::LevelControl::Attributes::CurrentLevel::Set(kExampleEndpointId, light_para.level); + { + LOG_ERR("Update brightness fail: %x", to_underlying(status)); + } + } +#endif + sBoot_zb = 0; flash_erase(flash_para_dev, USER_PARTITION_OFFSET, USER_PARTITION_SIZE); flash_write(flash_para_dev, USER_PARTITION_OFFSET, &val, 1); printk("Commissioning complete; Matter commissioned flag set.\n"); @@ -833,7 +875,7 @@ void AppTaskCommon::ChipEventHandler(const ChipDeviceEvent * event, intptr_t /* if (sBoot_zb) { printk("FailSafeTimer expired; Matter commissioning failed. Rebooting to Zigbee mode...\n"); - sys_reboot(0); + SwitchBackToZigbee(); } else { diff --git a/examples/platform/telink/common/src/mainCommon.cpp b/examples/platform/telink/common/src/mainCommon.cpp index 583d61c0082c57..3f68acab099528 100644 --- a/examples/platform/telink/common/src/mainCommon.cpp +++ b/examples/platform/telink/common/src/mainCommon.cpp @@ -105,6 +105,43 @@ static void FactoryResetOnBoot(void) } #endif /* CONFIG_CHIP_ENABLE_POWER_ON_FACTORY_RESET */ +#if CONFIG_CUSTOMER_MODE + +#define MATTER_NVS_DEMO_EN 0 + +#if MATTER_NVS_DEMO_EN +void matter_nvs_raw_demo(void) +{ + static constexpr char kFactoryResetOnBootStoreKey[] = "TelinkFactoryResetOnBootCnt"; + uint32_t test_flag = 0x55; + + if (chip::DeviceLayer::PersistedStorage::KeyValueStoreMgr().Put(kFactoryResetOnBootStoreKey, &test_flag, sizeof(test_flag)) != + CHIP_NO_ERROR) + { + printk("FactoryResetOnBootCnt write fail\n"); + } + + test_flag = 0xaa; + CHIP_ERROR FactoryResetOnBootErr = + chip::DeviceLayer::PersistedStorage::KeyValueStoreMgr().Get(kFactoryResetOnBootStoreKey, &test_flag, sizeof(test_flag)); + if (FactoryResetOnBootErr != CHIP_NO_ERROR) + { + printk("FactoryResetOnBootCnt get fail\n"); + } + printk("nvs read value is %x \n", test_flag); + (void) chip::DeviceLayer::PersistedStorage::KeyValueStoreMgr().Delete(kFactoryResetOnBootStoreKey); + test_flag = 0xbb; + FactoryResetOnBootErr = + chip::DeviceLayer::PersistedStorage::KeyValueStoreMgr().Get(kFactoryResetOnBootStoreKey, &test_flag, sizeof(test_flag)); + if (FactoryResetOnBootErr != CHIP_NO_ERROR) + { + printk("FactoryResetOnBootCnt delete after read fail \n"); + } +} +#endif + +#endif + int main(void) { #if defined(CONFIG_USB_DEVICE_STACK) && !defined(CONFIG_CHIP_PW_RPC) diff --git a/src/platform/telink/FactoryDataProvider.cpp b/src/platform/telink/FactoryDataProvider.cpp index b2d58313f6178e..4e0b24f49af2c4 100644 --- a/src/platform/telink/FactoryDataProvider.cpp +++ b/src/platform/telink/FactoryDataProvider.cpp @@ -52,7 +52,7 @@ CHIP_ERROR GetFactoryDataString(const FactoryDataString & str, char * buf, size_ } // namespace namespace DeviceLayer { - +static constexpr uint32_t kFactoryDataOffset = 6; template CHIP_ERROR FactoryDataProvider::Init() { @@ -81,7 +81,7 @@ CHIP_ERROR FactoryDataProvider::Init() return error; } - if (!ParseFactoryData(factoryData, factoryDataSize, &mFactoryData)) + if (!ParseFactoryData(factoryData + kFactoryDataOffset, factoryDataSize - kFactoryDataOffset, &mFactoryData)) { ChipLogError(DeviceLayer, "Failed to parse factory data"); return CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND;