From 628e6ba3a8295f520704664a80a40f4f97870068 Mon Sep 17 00:00:00 2001 From: Sid Hsu Date: Thu, 2 Jun 2022 04:02:43 +0800 Subject: [PATCH] Update Infineon CYW30739 TE8 fixes. (#18733) * Update CYW30739 TE8 fixes. * DoFactoryReset would clear the key-value storage. * Enable OTA requestor for CYW30739 apps. * Refine the flash layout for the OTA functions. * Disable loggings for lighting and lock app. * Reuse Matter heap APIs for CYW30739 OpenThread implementation. * Enable MBEDTLS_CCM_ALT, MBEDTLS_AES_ALT, and MBEDTLS_SHA256_ALT. * Group keys into factory keys and config keys. * Fix CYW30739Config write methods. * Correct the storage entry count for additional keys. * Add and process OTA image header for CYW30739. * Implement network-interfaces and reboot-count. * Fix currentLevel value mismatch. * Implement PICS_MANUAL_OCCUPANCY_CHANGE. * Instantiate identify object for lighting app. * Implement IsFirstImageRun and ConfirmCurrentImage methods of OTAImageProcessorImpl. * Compress large "Data" entries in DS. * Change CHIP_CONFIG_MAX_FABRICS to 5 from 4. * Add a debug arg for CYW30739 SDK. * Implement SupportedCalendarTypes and SupportedLocales. * Implement Door lock cluster. * Revert implementing SupportedCalendarTypes and SupportedLocales. * Remove unneeded codes. * Turn OTAConfig into a namespace. * Use Platform::New Platform::Delete for NetworkInterface. * Fix clang-tidy: readability-else-after-return * Add license blurbs and improve readability for CYW30739 SDK scripts. * Add CHIP license blurbs into CYW30739 SDK scripts. * Remove unneeded returning value from the gen_image function. --- .gitmodules | 5 +- examples/lighting-app/cyw30739/BUILD.gn | 13 +- examples/lighting-app/cyw30739/args.gni | 7 + .../cyw30739/include/LightingManager.h | 2 +- .../cyw30739/src/ButtonHandler.cpp | 15 +- .../cyw30739/src/ZclCallbacks.cpp | 4 + examples/lighting-app/cyw30739/src/main.cpp | 19 +- examples/lock-app/cyw30739/BUILD.gn | 16 +- examples/lock-app/cyw30739/args.gni | 9 + examples/lock-app/cyw30739/include/AppEvent.h | 52 ++ .../cyw30739/include/BoltLockManager.h | 86 --- .../lock-app/cyw30739/include/LockManager.h | 119 ++++ .../cyw30739/src/AppShellCommands.cpp | 14 +- .../lock-app/cyw30739/src/BoltLockManager.cpp | 219 ------- .../lock-app/cyw30739/src/ButtonHandler.cpp | 30 +- .../lock-app/cyw30739/src/LockManager.cpp | 423 ++++++++++++++ .../lock-app/cyw30739/src/ZclCallbacks.cpp | 88 ++- examples/lock-app/cyw30739/src/main.cpp | 134 +++-- examples/ota-requestor-app/cyw30739/BUILD.gn | 13 +- examples/ota-requestor-app/cyw30739/args.gni | 4 - .../ota-requestor-app/cyw30739/src/main.cpp | 34 +- examples/platform/cyw30739/OTAConfig.cpp | 54 ++ examples/platform/cyw30739/OTAConfig.h | 25 + .../project_include/OpenThreadConfig.h | 1 + src/platform/CYW30739/CHIPPlatformConfig.h | 2 +- src/platform/CYW30739/CYW30739Config.cpp | 20 +- src/platform/CYW30739/CYW30739Config.h | 67 ++- .../CYW30739/ConfigurationManagerImpl.cpp | 31 + .../CYW30739/ConfigurationManagerImpl.h | 2 + .../CYW30739/DiagnosticDataProviderImpl.cpp | 48 ++ .../CYW30739/DiagnosticDataProviderImpl.h | 3 + .../CYW30739/KeyValueStoreManagerImpl.cpp | 13 + .../CYW30739/KeyValueStoreManagerImpl.h | 26 +- .../CYW30739/OTAImageProcessorImpl.cpp | 91 ++- src/platform/CYW30739/OTAImageProcessorImpl.h | 8 +- .../CYW30739/ThreadStackManagerImpl.cpp | 11 + src/platform/CYW30739/args.gni | 2 - .../CYW30739/cyw30739-chip-mbedtls-config.h | 6 +- third_party/cyw30739_sdk/BUILD.gn | 6 + .../bsp_design_modus/cycfg_pins.c | 110 ++-- .../bsp_design_modus/cycfg_pins.h | 33 +- .../bsp_design_modus/cycfg_routing.h | 29 +- third_party/cyw30739_sdk/btp_reader.py | 39 +- third_party/cyw30739_sdk/compress_cgs_data.py | 239 ++++++++ .../cyw30739_sdk/cyw30739_executable.gni | 26 +- third_party/cyw30739_sdk/cyw30739_sdk.gni | 332 +++++++++-- third_party/cyw30739_sdk/flash.btp | 4 +- third_party/cyw30739_sdk/gen_ota_image.py | 137 ++++- .../cyw30739_sdk/include/ota_fw_upgrade.h | 2 +- third_party/cyw30739_sdk/merge_hex.py | 45 ++ third_party/cyw30739_sdk/repos/30739A0 | 2 +- .../cyw30739_sdk/repos/CYW930739M2EVB-01 | 2 +- .../cyw30739_sdk/scripts/wiced-gen-ld.pl | 549 ++++++++++++++++++ third_party/cyw30739_sdk/src/ota_fw_upgrade.c | 86 +-- third_party/openthread/ot-ifx | 2 +- third_party/openthread/platforms/ifx/BUILD.gn | 6 +- 56 files changed, 2697 insertions(+), 668 deletions(-) create mode 100644 examples/lock-app/cyw30739/include/AppEvent.h delete mode 100644 examples/lock-app/cyw30739/include/BoltLockManager.h create mode 100644 examples/lock-app/cyw30739/include/LockManager.h delete mode 100644 examples/lock-app/cyw30739/src/BoltLockManager.cpp create mode 100644 examples/lock-app/cyw30739/src/LockManager.cpp create mode 100644 examples/platform/cyw30739/OTAConfig.cpp create mode 100644 examples/platform/cyw30739/OTAConfig.h mode change 100644 => 100755 src/platform/CYW30739/DiagnosticDataProviderImpl.cpp create mode 100644 third_party/cyw30739_sdk/compress_cgs_data.py create mode 100644 third_party/cyw30739_sdk/merge_hex.py create mode 100644 third_party/cyw30739_sdk/scripts/wiced-gen-ld.pl diff --git a/.gitmodules b/.gitmodules index 7a0b2154efd292..8e6b6ad0545da7 100644 --- a/.gitmodules +++ b/.gitmodules @@ -88,7 +88,6 @@ [submodule "third_party/openthread/ot-ifx"] path = third_party/openthread/ot-ifx url = https://github.com/Infineon/ot-ifx-release.git - branch = cyw30739 platforms = cyw30739 [submodule "third_party/mbed-os/repo"] path = third_party/mbed-os/repo @@ -203,7 +202,7 @@ url = https://github.com/open-source-parsers/jsoncpp.git [submodule "cyw30739_sdk/30739A0"] path = third_party/cyw30739_sdk/repos/30739A0 - url = https://github.com/Infineon/30739A0.git + url = https://github.com/Infineon/OT-Matter-30739A0.git platforms = cyw30739 [submodule "cyw30739_sdk/include"] path = third_party/cyw30739_sdk/repos/btsdk-include @@ -211,7 +210,7 @@ platforms = cyw30739 [submodule "cyw30739_sdk/target"] path = third_party/cyw30739_sdk/repos/CYW930739M2EVB-01 - url = https://github.com/Infineon/TARGET_CYW930739M2EVB-01.git + url = https://github.com/Infineon/OT-Matter-TARGET_CYW930739M2EVB-01.git platforms = cyw30739 [submodule "cyw30739_sdk/tools"] path = third_party/cyw30739_sdk/repos/btsdk-tools diff --git a/examples/lighting-app/cyw30739/BUILD.gn b/examples/lighting-app/cyw30739/BUILD.gn index e29a615a8ae7eb..9ebf17650960d3 100644 --- a/examples/lighting-app/cyw30739/BUILD.gn +++ b/examples/lighting-app/cyw30739/BUILD.gn @@ -20,6 +20,7 @@ import("${cyw30739_sdk_build_root}/cyw30739_executable.gni") import("${cyw30739_sdk_build_root}/cyw30739_sdk.gni") cyw30739_project_dir = "${chip_root}/examples/lighting-app/cyw30739" +examples_plat_dir = "${chip_root}/examples/platform/cyw30739" declare_args() { setupPinCode = 20202021 @@ -29,7 +30,10 @@ declare_args() { cyw30739_sdk("sdk") { sources = [ "${cyw30739_project_dir}/include/CHIPProjectConfig.h" ] - include_dirs = [ "${cyw30739_project_dir}/include" ] + include_dirs = [ + "${cyw30739_project_dir}/include", + "${examples_plat_dir}", + ] defines = [ "CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE=${setupPinCode}", @@ -56,6 +60,13 @@ cyw30739_executable("lighting_app") { ] include_dirs = [ "include" ] + + if (chip_enable_ota_requestor) { + sources += [ + "${examples_plat_dir}/OTAConfig.cpp", + "${examples_plat_dir}/OTAConfig.h", + ] + } } group("cyw30739") { diff --git a/examples/lighting-app/cyw30739/args.gni b/examples/lighting-app/cyw30739/args.gni index 8361c808a27a37..267c1db9b56817 100644 --- a/examples/lighting-app/cyw30739/args.gni +++ b/examples/lighting-app/cyw30739/args.gni @@ -18,3 +18,10 @@ import("${chip_root}/src/platform/CYW30739/args.gni") cyw30739_sdk_target = get_label_info(":sdk", "label_no_toolchain") chip_openthread_ftd = true + +chip_enable_ota_requestor = true + +chip_error_logging = false +chip_progress_logging = false +chip_detail_logging = false +chip_automation_logging = false diff --git a/examples/lighting-app/cyw30739/include/LightingManager.h b/examples/lighting-app/cyw30739/include/LightingManager.h index 0ce5b5c4073bfa..917bb37c023c63 100644 --- a/examples/lighting-app/cyw30739/include/LightingManager.h +++ b/examples/lighting-app/cyw30739/include/LightingManager.h @@ -55,10 +55,10 @@ class LightingManager typedef void (*Callback_fn_initiated)(Actor_t, Action_t, uint8_t); typedef void (*Callback_fn_completed)(Action_t); void SetCallbacks(Callback_fn_initiated aActionInitiated_CB, Callback_fn_completed aActionCompleted_CB); + void WriteClusterLevel(uint8_t value); private: void WriteClusterState(uint8_t value); - void WriteClusterLevel(uint8_t value); friend LightingManager & LightMgr(void); State_t mState; diff --git a/examples/lighting-app/cyw30739/src/ButtonHandler.cpp b/examples/lighting-app/cyw30739/src/ButtonHandler.cpp index 10c24a4b785440..c8665dfe492797 100644 --- a/examples/lighting-app/cyw30739/src/ButtonHandler.cpp +++ b/examples/lighting-app/cyw30739/src/ButtonHandler.cpp @@ -20,11 +20,15 @@ #include #include +#include +#include #include #include #include #include +using namespace chip::app::Clusters; + /****************************************************** * Macros ******************************************************/ @@ -56,7 +60,7 @@ wiced_result_t app_button_init(void) memset(app_buttons, 0, (sizeof(button_manager_button_t) * APP_MAX_BUTTON_DEF)); app_button_configurations[ON_OFF_BUTTON].button = PLATFORM_BUTTON_1; - app_button_configurations[ON_OFF_BUTTON].button_event_mask = BUTTON_CLICK_EVENT; + app_button_configurations[ON_OFF_BUTTON].button_event_mask = BUTTON_CLICK_EVENT | BUTTON_HOLDING_EVENT; app_buttons[ON_OFF_BUTTON].configuration = &app_button_configurations[ON_OFF_BUTTON]; result = wiced_button_manager_init(&app_button_manager, &app_button_manager_configuration, app_buttons, 1); @@ -71,7 +75,7 @@ wiced_result_t app_button_init(void) void app_button_event_handler(const button_manager_button_t * button_mgr, button_manager_event_t event, button_manager_button_state_t state) { - + uint8_t attributeValue; if (button_mgr[0].configuration->button == PLATFORM_BUTTON_1 && event == BUTTON_CLICK_EVENT && state == BUTTON_STATE_RELEASED) { if (LightMgr().IsLightOn()) @@ -85,4 +89,11 @@ void app_button_event_handler(const button_manager_button_t * button_mgr, button LightMgr().InitiateAction(LightingManager::ACTOR_BUTTON, LightingManager::ON_ACTION, 0); } } + else if (button_mgr[0].configuration->button == PLATFORM_BUTTON_1 && event == BUTTON_HOLDING_EVENT) + { + // update the current occupancy here for hardcoded endpoint 1 + OccupancySensing::Attributes::Occupancy::Get(1, &attributeValue); + printf("Button Holding Toggle: %d -> %d\n", attributeValue, !attributeValue); + OccupancySensing::Attributes::Occupancy::Set(1, !attributeValue); + } } diff --git a/examples/lighting-app/cyw30739/src/ZclCallbacks.cpp b/examples/lighting-app/cyw30739/src/ZclCallbacks.cpp index 8893b3616ed594..df3fcf7721d1a4 100644 --- a/examples/lighting-app/cyw30739/src/ZclCallbacks.cpp +++ b/examples/lighting-app/cyw30739/src/ZclCallbacks.cpp @@ -63,6 +63,10 @@ void MatterPostAttributeChangeCallback(const app::ConcreteAttributePath & attrib return; } break; + case Identify::Id: + ChipLogProgress(Zcl, "Identify attribute ID: " ChipLogFormatMEI " Type: %u Value: %u, length %u", + ChipLogValueMEI(attributePath.mClusterId), type, *value, size); + return; default: printf("Unhandled cluster ID: 0x%04lx\n", attributePath.mClusterId); return; diff --git a/examples/lighting-app/cyw30739/src/main.cpp b/examples/lighting-app/cyw30739/src/main.cpp index 97fbd3ede97602..e3ec9dc3d49345 100644 --- a/examples/lighting-app/cyw30739/src/main.cpp +++ b/examples/lighting-app/cyw30739/src/main.cpp @@ -16,16 +16,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include + #include #include #include #include +#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR +#include +#endif +#include #include #include #include #include #include -#include #include #include #include @@ -47,6 +52,13 @@ static wiced_led_config_t chip_lighting_led_config = { .bright = 50, }; +static Identify gIdentify = { + chip::EndpointId{ 1 }, + [](Identify *) { ChipLogProgress(Zcl, "onIdentifyStart"); }, + [](Identify *) { ChipLogProgress(Zcl, "onIdentifyStop"); }, + EMBER_ZCL_IDENTIFY_IDENTIFY_TYPE_VISIBLE_LED, +}; + APPLICATION_START() { CHIP_ERROR err; @@ -144,6 +156,11 @@ void InitApp(intptr_t args) LightMgr().Init(); LightMgr().SetCallbacks(LightManagerCallback, NULL); + LightMgr().WriteClusterLevel(254); + +#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR + OTAConfig::Init(); +#endif } void EventHandler(const ChipDeviceEvent * event, intptr_t arg) diff --git a/examples/lock-app/cyw30739/BUILD.gn b/examples/lock-app/cyw30739/BUILD.gn index c08ce53069bbfb..3a2b458a3a9e07 100644 --- a/examples/lock-app/cyw30739/BUILD.gn +++ b/examples/lock-app/cyw30739/BUILD.gn @@ -20,6 +20,7 @@ import("${cyw30739_sdk_build_root}/cyw30739_executable.gni") import("${cyw30739_sdk_build_root}/cyw30739_sdk.gni") cyw30739_project_dir = "${chip_root}/examples/lock-app/cyw30739" +examples_plat_dir = "${chip_root}/examples/platform/cyw30739" declare_args() { setupPinCode = 20202021 @@ -29,7 +30,10 @@ declare_args() { cyw30739_sdk("sdk") { sources = [ "${cyw30739_project_dir}/include/CHIPProjectConfig.h" ] - include_dirs = [ "${cyw30739_project_dir}/include" ] + include_dirs = [ + "${cyw30739_project_dir}/include", + "${examples_plat_dir}", + ] defines = [ "CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE=${setupPinCode}", @@ -42,8 +46,8 @@ cyw30739_executable("lock_app") { sources = [ "src/AppShellCommands.cpp", - "src/BoltLockManager.cpp", "src/ButtonHandler.cpp", + "src/LockManager.cpp", "src/ZclCallbacks.cpp", "src/main.cpp", ] @@ -53,10 +57,16 @@ cyw30739_executable("lock_app") { "${chip_root}/examples/lock-app/lock-common", "${chip_root}/examples/shell/shell_common:shell_common", "${chip_root}/src/lib", - "${chip_root}/third_party/openthread/repo:libopenthread-ftd", ] include_dirs = [ "include" ] + + if (chip_enable_ota_requestor) { + sources += [ + "${examples_plat_dir}/OTAConfig.cpp", + "${examples_plat_dir}/OTAConfig.h", + ] + } } group("cyw30739") { diff --git a/examples/lock-app/cyw30739/args.gni b/examples/lock-app/cyw30739/args.gni index 149f7d42b18b5f..267c1db9b56817 100644 --- a/examples/lock-app/cyw30739/args.gni +++ b/examples/lock-app/cyw30739/args.gni @@ -16,3 +16,12 @@ import("//build_overrides/chip.gni") import("${chip_root}/src/platform/CYW30739/args.gni") cyw30739_sdk_target = get_label_info(":sdk", "label_no_toolchain") + +chip_openthread_ftd = true + +chip_enable_ota_requestor = true + +chip_error_logging = false +chip_progress_logging = false +chip_detail_logging = false +chip_automation_logging = false diff --git a/examples/lock-app/cyw30739/include/AppEvent.h b/examples/lock-app/cyw30739/include/AppEvent.h new file mode 100644 index 00000000000000..60583eba2c2123 --- /dev/null +++ b/examples/lock-app/cyw30739/include/AppEvent.h @@ -0,0 +1,52 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2018 Nest Labs, Inc. + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +struct AppEvent +{ + enum AppEventTypes + { + kEventType_Button = 0, + kEventType_Timer, + kEventType_Lock, + kEventType_Install, + }; + + uint16_t Type; + + union + { + struct + { + uint8_t Action; + } ButtonEvent; + struct + { + void * Context; + } TimerEvent; + struct + { + uint8_t Action; + int32_t Actor; + } LockEvent; + }; +}; diff --git a/examples/lock-app/cyw30739/include/BoltLockManager.h b/examples/lock-app/cyw30739/include/BoltLockManager.h deleted file mode 100644 index 08cf1ccf0488a1..00000000000000 --- a/examples/lock-app/cyw30739/include/BoltLockManager.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * - * Copyright (c) 2019 Google LLC. - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include -#include -#include - -class BoltLockManager -{ -public: - enum Action_t - { - LOCK_ACTION = 0, - UNLOCK_ACTION, - - INVALID_ACTION - } Action; - - enum State_t - { - kState_LockingInitiated = 0, - kState_LockingCompleted, - kState_UnlockingInitiated, - kState_UnlockingCompleted, - } State; - - enum Actor_t - { - ACTOR_ZCL_CMD = 0, - ACTOR_APP_CMD, - ACTOR_BUTTON, - } Actor; - - CHIP_ERROR Init(); - bool IsUnlocked(); - void EnableAutoRelock(bool aOn); - void SetAutoLockDuration(uint32_t aDurationInSecs); - bool IsActionInProgress(); - bool InitiateAction(int32_t aActor, Action_t aAction); - - typedef void (*Callback_fn_initiated)(Action_t, int32_t aActor); - typedef void (*Callback_fn_completed)(Action_t); - void SetCallbacks(Callback_fn_initiated aActionInitiated_CB, Callback_fn_completed aActionCompleted_CB); - -private: - friend BoltLockManager & BoltLockMgr(void); - State_t mState; - - Callback_fn_initiated mActionInitiated_CB; - Callback_fn_completed mActionCompleted_CB; - - bool mAutoRelock; - uint32_t mAutoLockDuration; - bool mAutoLockTimerArmed; - - void CancelTimer(void); - void StartTimer(uint32_t aTimeoutMs); - - static void TimerEventHandler(WICED_TIMER_PARAM_TYPE cb_params); - static int AutoReLockTimerEventHandler(void * aEvent); - static int ActuatorMovementTimerEventHandler(void * aEvent); - - static BoltLockManager sLock; -}; - -inline BoltLockManager & BoltLockMgr(void) -{ - return BoltLockManager::sLock; -} diff --git a/examples/lock-app/cyw30739/include/LockManager.h b/examples/lock-app/cyw30739/include/LockManager.h new file mode 100644 index 00000000000000..596e5e9f42d035 --- /dev/null +++ b/examples/lock-app/cyw30739/include/LockManager.h @@ -0,0 +1,119 @@ +/* + * + * Copyright (c) 2019 Google LLC. + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "AppEvent.h" +#include +#include +#include +#include +#include +#include + +using namespace ::chip; + +#define DOOR_LOCK_MAX_CREDENTIAL_SIZE 8 + +static constexpr size_t DOOR_LOCK_CREDENTIAL_INFO_MAX_DATA_SIZE = 20; + +class LockManager +{ +public: + enum Action_t + { + LOCK_ACTION = 0, + UNLOCK_ACTION, + + INVALID_ACTION + } Action; + + enum State_t + { + kState_LockInitiated = 0, + kState_LockCompleted, + kState_UnlockInitiated, + kState_UnlockCompleted, + } State; + + enum Actor_t + { + ACTOR_ZCL_CMD = 0, + ACTOR_APP_CMD, + ACTOR_BUTTON, + } Actor; + + CHIP_ERROR Init(chip::app::DataModel::Nullable state, + uint8_t maxNumberOfCredentialsPerUser); + bool NextState(); + bool IsActionInProgress(); + bool InitiateAction(int32_t aActor, Action_t aAction); + + typedef void (*Callback_fn_initiated)(Action_t, int32_t aActor); + typedef void (*Callback_fn_completed)(Action_t); + void SetCallbacks(Callback_fn_initiated aActionInitiated_CB, Callback_fn_completed aActionCompleted_CB); + + bool Lock(chip::EndpointId endpointId, const Optional & pin, DlOperationError & err); + bool Unlock(chip::EndpointId endpointId, const Optional & pin, DlOperationError & err); + + bool GetUser(uint16_t userIndex, EmberAfPluginDoorLockUserInfo & user) const; + bool SetUser(uint16_t userIndex, chip::FabricIndex creator, chip::FabricIndex modifier, const chip::CharSpan & userName, + uint32_t uniqueId, DlUserStatus userStatus, DlUserType usertype, DlCredentialRule credentialRule, + const DlCredential * credentials, size_t totalCredentials); + + bool GetCredential(chip::EndpointId endpointId, uint16_t credentialIndex, DlCredentialType credentialType, + EmberAfPluginDoorLockCredentialInfo & credential) const; + + bool SetCredential(chip::EndpointId endpointId, uint16_t credentialIndex, DlCredentialStatus credentialStatus, + DlCredentialType credentialType, const chip::ByteSpan & credentialData); + + bool setLockState(chip::EndpointId endpointId, DlLockState lockState, const Optional & pin, + DlOperationError & err); + const char * lockStateToString(DlLockState lockState) const; + + bool ReadConfigValues(); + +private: + friend LockManager & LockMgr(); + chip::EndpointId mEndpointId; + State_t mState; + + Callback_fn_initiated mActionInitiated_CB; + Callback_fn_completed mActionCompleted_CB; + + void CancelTimer(void); + void StartTimer(uint32_t aTimeoutMs); + + static void TimerEventHandler(WICED_TIMER_PARAM_TYPE cb_params); + static int ActuatorMovementTimerEventHandler(void * aEvent); + + EmberAfPluginDoorLockUserInfo mLockUser; + EmberAfPluginDoorLockCredentialInfo mLockCredentials; + + char mUserName[DOOR_LOCK_MAX_USER_NAME_SIZE]; + uint8_t mCredentialData[DOOR_LOCK_MAX_CREDENTIAL_SIZE]; + chip::Platform::ScopedMemoryBuffer mCredentials; + uint8_t mMaxCredentialsPerUser; + + static LockManager sLock; +}; + +inline LockManager & LockMgr() +{ + return LockManager::sLock; +} diff --git a/examples/lock-app/cyw30739/src/AppShellCommands.cpp b/examples/lock-app/cyw30739/src/AppShellCommands.cpp index e086f0189637b7..beb21c26c4c023 100644 --- a/examples/lock-app/cyw30739/src/AppShellCommands.cpp +++ b/examples/lock-app/cyw30739/src/AppShellCommands.cpp @@ -17,7 +17,7 @@ * limitations under the License. */ -#include +#include #include #include @@ -65,25 +65,25 @@ CHIP_ERROR AppCommandLockHandler(int argc, char * argv[]) { if (argc == 0) { - streamer_printf(streamer_get(), "The lock is %s\n", BoltLockMgr().IsUnlocked() ? "unlocked" : "locked"); + streamer_printf(streamer_get(), "The lock is %s\n", LockMgr().NextState() ? "unlocked" : "locked"); } else if (strcmp(argv[0], "on") == 0) { streamer_printf(streamer_get(), "Lock ...\n"); - BoltLockMgr().InitiateAction(BoltLockManager::ACTOR_APP_CMD, BoltLockManager::LOCK_ACTION); + LockMgr().InitiateAction(LockManager::ACTOR_APP_CMD, LockManager::LOCK_ACTION); } else if (strcmp(argv[0], "off") == 0) { streamer_printf(streamer_get(), "Unlock ...\n"); - BoltLockMgr().InitiateAction(BoltLockManager::ACTOR_BUTTON, BoltLockManager::UNLOCK_ACTION); + LockMgr().InitiateAction(LockManager::ACTOR_BUTTON, LockManager::UNLOCK_ACTION); } else if (strcmp(argv[0], "toggle") == 0) { streamer_printf(streamer_get(), "Toggling the lock ...\n"); - if (BoltLockMgr().IsUnlocked()) - BoltLockMgr().InitiateAction(BoltLockManager::ACTOR_APP_CMD, BoltLockManager::LOCK_ACTION); + if (LockMgr().NextState()) + LockMgr().InitiateAction(LockManager::ACTOR_APP_CMD, LockManager::LOCK_ACTION); else - BoltLockMgr().InitiateAction(BoltLockManager::ACTOR_BUTTON, BoltLockManager::UNLOCK_ACTION); + LockMgr().InitiateAction(LockManager::ACTOR_BUTTON, LockManager::UNLOCK_ACTION); } else { diff --git a/examples/lock-app/cyw30739/src/BoltLockManager.cpp b/examples/lock-app/cyw30739/src/BoltLockManager.cpp deleted file mode 100644 index 7796fe64696166..00000000000000 --- a/examples/lock-app/cyw30739/src/BoltLockManager.cpp +++ /dev/null @@ -1,219 +0,0 @@ -/* - * - * Copyright (c) 2020 Project CHIP Authors - * Copyright (c) 2019 Google LLC. - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "BoltLockManager.h" -#include "wiced_bt_event.h" - -BoltLockManager BoltLockManager::sLock; - -wiced_timer_t sLockTimer; - -CHIP_ERROR BoltLockManager::Init() -{ - wiced_result_t result; - - // Create wiced timer for lock timer. - result = wiced_init_timer(&sLockTimer, TimerEventHandler, (WICED_TIMER_PARAM_TYPE) this, WICED_MILLI_SECONDS_TIMER); - if (result != WICED_BT_SUCCESS) - { - printf("sLockTimer timer create failed"); - return APP_ERROR_INIT_TIMER_FAILED; - } - - mState = kState_UnlockingCompleted; - mAutoLockTimerArmed = false; - mAutoRelock = false; - mAutoLockDuration = 0; - - return CHIP_NO_ERROR; -} - -void BoltLockManager::SetCallbacks(Callback_fn_initiated aActionInitiated_CB, Callback_fn_completed aActionCompleted_CB) -{ - mActionInitiated_CB = aActionInitiated_CB; - mActionCompleted_CB = aActionCompleted_CB; -} - -bool BoltLockManager::IsActionInProgress() -{ - return (mState == kState_LockingInitiated || mState == kState_UnlockingInitiated); -} - -bool BoltLockManager::IsUnlocked() -{ - return (mState == kState_UnlockingCompleted); -} - -void BoltLockManager::EnableAutoRelock(bool aOn) -{ - mAutoRelock = aOn; -} - -void BoltLockManager::SetAutoLockDuration(uint32_t aDurationInSecs) -{ - mAutoLockDuration = aDurationInSecs; -} - -bool BoltLockManager::InitiateAction(int32_t aActor, Action_t aAction) -{ - bool action_initiated = false; - State_t new_state; - - // Initiate Lock/Unlock Action only when the previous one is complete. - if (mState == kState_LockingCompleted && aAction == UNLOCK_ACTION) - { - action_initiated = true; - - new_state = kState_UnlockingInitiated; - } - else if (mState == kState_UnlockingCompleted && aAction == LOCK_ACTION) - { - action_initiated = true; - - new_state = kState_LockingInitiated; - } - - if (action_initiated) - { - if (mAutoLockTimerArmed && new_state == kState_LockingInitiated) - { - // If auto lock timer has been armed and someone initiates locking, - // cancel the timer and continue as normal. - mAutoLockTimerArmed = false; - - CancelTimer(); - } - - StartTimer(ACTUATOR_MOVEMENT_PERIOS_MS); - - // Since the timer started successfully, update the state and trigger callback - mState = new_state; - - if (mActionInitiated_CB) - { - mActionInitiated_CB(aAction, aActor); - } - } - - return action_initiated; -} - -void BoltLockManager::StartTimer(uint32_t aTimeoutMs) -{ - if (wiced_is_timer_in_use(&sLockTimer)) - { - printf("app timer already started!\n"); - CancelTimer(); - } - - if (wiced_start_timer(&sLockTimer, aTimeoutMs) != WICED_BT_SUCCESS) - { - printf("sLockTimer timer start() failed\n"); - return; - } -} - -void BoltLockManager::CancelTimer(void) -{ - if (wiced_stop_timer(&sLockTimer) != WICED_BT_SUCCESS) - { - printf("Lock timer timer stop() failed\n"); - return; - } -} - -void BoltLockManager::TimerEventHandler(WICED_TIMER_PARAM_TYPE cb_params) -{ - BoltLockManager * lock = reinterpret_cast(cb_params); - int (*fn)(void *); - - // The timer event handler will be called in the context of the timer task - // once sLockTimer expires. Post an event to apptask queue with the actual handler - // so that the event can be handled in the context of the apptask. - if (lock->mAutoLockTimerArmed) - { - fn = AutoReLockTimerEventHandler; - } - else - { - fn = ActuatorMovementTimerEventHandler; - } - - if (wiced_app_event_serialize(fn, (void *) lock) != WICED_TRUE) - { - printf("wiced_app_event_serialize failed\n"); - } -} - -int BoltLockManager::AutoReLockTimerEventHandler(void * data) -{ - BoltLockManager * lock = reinterpret_cast(data); - int32_t actor = 0; - - // Make sure auto lock timer is still armed. - if (!lock->mAutoLockTimerArmed) - { - return 0; - } - - lock->mAutoLockTimerArmed = false; - - printf("Auto Re-Lock has been triggered!\n"); - - lock->InitiateAction(actor, LOCK_ACTION); - - return 0; -} - -int BoltLockManager::ActuatorMovementTimerEventHandler(void * data) -{ - BoltLockManager * lock = reinterpret_cast(data); - Action_t actionCompleted = INVALID_ACTION; - - if (lock->mState == kState_LockingInitiated) - { - lock->mState = kState_LockingCompleted; - actionCompleted = LOCK_ACTION; - } - else if (lock->mState == kState_UnlockingInitiated) - { - lock->mState = kState_UnlockingCompleted; - actionCompleted = UNLOCK_ACTION; - } - - if (actionCompleted != INVALID_ACTION) - { - if (lock->mActionCompleted_CB) - { - lock->mActionCompleted_CB(actionCompleted); - } - - if (lock->mAutoRelock && actionCompleted == UNLOCK_ACTION) - { - // Start the timer for auto relock - lock->StartTimer(lock->mAutoLockDuration * 1000); - - lock->mAutoLockTimerArmed = true; - - printf("Auto Re-lock enabled. Will be triggered in %lu seconds\n", lock->mAutoLockDuration); - } - } - - return 0; -} diff --git a/examples/lock-app/cyw30739/src/ButtonHandler.cpp b/examples/lock-app/cyw30739/src/ButtonHandler.cpp index 47c37a7c2c65db..94f85a1b6259ab 100644 --- a/examples/lock-app/cyw30739/src/ButtonHandler.cpp +++ b/examples/lock-app/cyw30739/src/ButtonHandler.cpp @@ -18,8 +18,8 @@ * limitations under the License. */ -#include #include +#include #include #include #include @@ -73,18 +73,34 @@ void app_button_event_handler(const button_manager_button_t * button_mgr, button { // printf("app_button_event_handler. button=%d, event=%d, state=%d\n", button_mgr[ON_OFF_BUTTON].configuration->button, event, // state); - + bool initiated = false; + LockManager::Action_t action; + int32_t actor; + CHIP_ERROR err = CHIP_NO_ERROR; if (button_mgr[0].configuration->button == PLATFORM_BUTTON_1 && event == BUTTON_CLICK_EVENT && state == BUTTON_STATE_RELEASED) { - if (BoltLockMgr().IsUnlocked()) + if (LockMgr().NextState() == true) { - printf("Button Toggle:Lock\n"); - BoltLockMgr().InitiateAction(BoltLockManager::ACTOR_BUTTON, BoltLockManager::LOCK_ACTION); + action = LockManager::LOCK_ACTION; } else { - printf("Button Toggle:Unlock\n"); - BoltLockMgr().InitiateAction(BoltLockManager::ACTOR_BUTTON, BoltLockManager::UNLOCK_ACTION); + action = LockManager::UNLOCK_ACTION; + } + actor = AppEvent::kEventType_Button; + } + else + { + err = CHIP_ERROR_UNEXPECTED_EVENT; + } + + if (err == CHIP_NO_ERROR) + { + initiated = LockMgr().InitiateAction(LockManager::ACTOR_BUTTON, action); + + if (!initiated) + { + printf("Action is already in progress or active."); } } } diff --git a/examples/lock-app/cyw30739/src/LockManager.cpp b/examples/lock-app/cyw30739/src/LockManager.cpp new file mode 100644 index 00000000000000..d5af8592543829 --- /dev/null +++ b/examples/lock-app/cyw30739/src/LockManager.cpp @@ -0,0 +1,423 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2019 Google LLC. + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "LockManager.h" +#include "wiced_bt_event.h" +#include +#include + +using namespace chip::DeviceLayer::Internal; + +LockManager LockManager::sLock; + +wiced_timer_t sLockTimer; + +CHIP_ERROR LockManager::Init(chip::app::DataModel::Nullable state, + uint8_t maxNumberOfCredentialsPerUser) +{ + // Allocate buffer for credentials + if (!mCredentials.Alloc(maxNumberOfCredentialsPerUser)) + { + printf("Failed to allocate array for lock credentials"); + return CHIP_ERROR_NO_MEMORY; + } + mMaxCredentialsPerUser = maxNumberOfCredentialsPerUser; + + wiced_result_t result; + + // Create wiced timer for lock timer. + result = wiced_init_timer(&sLockTimer, TimerEventHandler, (WICED_TIMER_PARAM_TYPE) this, WICED_MILLI_SECONDS_TIMER); + if (result != WICED_BT_SUCCESS) + { + printf("sLockTimer timer create failed"); + return APP_ERROR_INIT_TIMER_FAILED; + } + + if (state.Value() == DlLockState::kUnlocked) + mState = kState_UnlockCompleted; + else + mState = kState_LockCompleted; + + return CHIP_NO_ERROR; +} + +bool LockManager::ReadConfigValues() +{ + size_t outLen; + CYW30739Config::ReadConfigValueBin(CYW30739Config::kConfigKey_LockUser, reinterpret_cast(&mLockUser), + sizeof(EmberAfPluginDoorLockUserInfo), outLen); + CYW30739Config::ReadConfigValueBin(CYW30739Config::kConfigKey_Credential, reinterpret_cast(&mLockCredentials), + sizeof(EmberAfPluginDoorLockCredentialInfo), outLen); + + CYW30739Config::ReadConfigValueStr(CYW30739Config::kConfigKey_LockUserName, mUserName, DOOR_LOCK_USER_NAME_BUFFER_SIZE, outLen); + + CYW30739Config::ReadConfigValueBin(CYW30739Config::kConfigKey_CredentialData, mCredentialData, sizeof(mCredentialData), outLen); + + CYW30739Config::ReadConfigValueBin(CYW30739Config::kConfigKey_UserCredentials, reinterpret_cast(mCredentials.Get()), + sizeof(DlCredential), outLen); + + return true; +} + +void LockManager::SetCallbacks(Callback_fn_initiated aActionInitiated_CB, Callback_fn_completed aActionCompleted_CB) +{ + mActionInitiated_CB = aActionInitiated_CB; + mActionCompleted_CB = aActionCompleted_CB; +} + +bool LockManager::IsActionInProgress() +{ + return (mState == kState_LockInitiated || mState == kState_UnlockInitiated); +} + +bool LockManager::NextState() +{ + return (mState == kState_UnlockCompleted); +} + +bool LockManager::InitiateAction(int32_t aActor, Action_t aAction) +{ + bool action_initiated = false; + State_t new_state; + + // Initiate Lock/Unlock Action only when the previous one is complete. + if (mState == kState_LockCompleted && aAction == UNLOCK_ACTION) + { + action_initiated = true; + + new_state = kState_UnlockInitiated; + } + else if (mState == kState_UnlockCompleted && aAction == LOCK_ACTION) + { + action_initiated = true; + + new_state = kState_LockInitiated; + } + + if (action_initiated) + { + + StartTimer(ACTUATOR_MOVEMENT_PERIOS_MS); + + // Since the timer started successfully, update the state and trigger callback + mState = new_state; + + if (mActionInitiated_CB) + { + mActionInitiated_CB(aAction, aActor); + } + } + + return action_initiated; +} + +void LockManager::StartTimer(uint32_t aTimeoutMs) +{ + if (wiced_is_timer_in_use(&sLockTimer)) + { + printf("app timer already started!\n"); + CancelTimer(); + } + + if (wiced_start_timer(&sLockTimer, aTimeoutMs) != WICED_BT_SUCCESS) + { + printf("sLockTimer timer start() failed\n"); + return; + } +} + +void LockManager::CancelTimer(void) +{ + if (wiced_stop_timer(&sLockTimer) != WICED_BT_SUCCESS) + { + printf("Lock timer timer stop() failed\n"); + return; + } +} + +void LockManager::TimerEventHandler(WICED_TIMER_PARAM_TYPE cb_params) +{ + LockManager * lock = reinterpret_cast(cb_params); + int (*fn)(void *); + + // The timer event handler will be called in the context of the timer task + // once sLockTimer expires. Post an event to apptask queue with the actual handler + // so that the event can be handled in the context of the apptask. + fn = ActuatorMovementTimerEventHandler; + + if (wiced_app_event_serialize(fn, (void *) lock) != WICED_TRUE) + { + printf("wiced_app_event_serialize failed\n"); + } +} + +int LockManager::ActuatorMovementTimerEventHandler(void * data) +{ + Action_t actionCompleted = INVALID_ACTION; + + LockManager * lock = reinterpret_cast(data); + + if (lock->mState == kState_LockInitiated) + { + lock->mState = kState_LockCompleted; + actionCompleted = LOCK_ACTION; + } + else if (lock->mState == kState_UnlockInitiated) + { + lock->mState = kState_UnlockCompleted; + actionCompleted = UNLOCK_ACTION; + } + + if (actionCompleted != INVALID_ACTION) + { + if (lock->mActionCompleted_CB) + { + lock->mActionCompleted_CB(actionCompleted); + } + } + + return 0; +} + +bool LockManager::Lock(chip::EndpointId endpointId, const Optional & pin, DlOperationError & err) +{ + return setLockState(endpointId, DlLockState::kLocked, pin, err); +} + +bool LockManager::Unlock(chip::EndpointId endpointId, const Optional & pin, DlOperationError & err) +{ + return setLockState(endpointId, DlLockState::kUnlocked, pin, err); +} + +bool LockManager::GetUser(uint16_t userIndex, EmberAfPluginDoorLockUserInfo & user) const +{ + // chip::ByteSpan credentialData(mLockCredentials.credentialData, mLockCredentials.credentialDataSize); + ChipLogProgress(Zcl, "Door Lock App: LockManager::GetUser [endpoint=%d,userIndex=%hu]", mEndpointId, userIndex); + + const auto & userInDb = mLockUser; + user.userStatus = userInDb.userStatus; + if (DlUserStatus::kAvailable == user.userStatus) + { + ChipLogDetail(Zcl, "Found unoccupied user [endpoint=%d]", mEndpointId); + return true; + } + + user.userName = chip::CharSpan(userInDb.userName.data(), userInDb.userName.size()); + user.credentials = chip::Span(userInDb.credentials.data(), userInDb.credentials.size()); + user.userUniqueId = userInDb.userUniqueId; + user.userType = userInDb.userType; + user.credentialRule = userInDb.credentialRule; + user.createdBy = userInDb.createdBy; + user.lastModifiedBy = userInDb.lastModifiedBy; + + ChipLogDetail(Zcl, + "Found occupied user " + "[endpoint=%d,name=\"%.*s\",credentialsCount=%u,uniqueId=%lx,type=%u,credentialRule=%u," + "createdBy=%d,lastModifiedBy=%d]", + mEndpointId, static_cast(user.userName.size()), user.userName.data(), user.credentials.size(), + user.userUniqueId, to_underlying(user.userType), to_underlying(user.credentialRule), user.createdBy, + user.lastModifiedBy); + + return true; +} + +bool LockManager::SetUser(uint16_t userIndex, chip::FabricIndex creator, chip::FabricIndex modifier, + const chip::CharSpan & userName, uint32_t uniqueId, DlUserStatus userStatus, DlUserType usertype, + DlCredentialRule credentialRule, const DlCredential * credentials, size_t totalCredentials) +{ + ChipLogProgress(Zcl, + "Door Lock App: LockManager::SetUser " + "[endpoint=%d,userIndex=%d,creator=%d,modifier=%d,userName=%s,uniqueId=%ld " + "userStatus=%u,userType=%u,credentialRule=%u,credentials=%p,totalCredentials=%u]", + mEndpointId, userIndex, creator, modifier, userName.data(), uniqueId, to_underlying(userStatus), + to_underlying(usertype), to_underlying(credentialRule), credentials, totalCredentials); + + auto & userInStorage = mLockUser; + + if (userName.size() > DOOR_LOCK_MAX_USER_NAME_SIZE) + { + ChipLogError(Zcl, "Cannot set user - user name is too long [endpoint=%d,index=%d]", mEndpointId, userIndex); + return false; + } + + if (totalCredentials > mMaxCredentialsPerUser) + { + ChipLogError(Zcl, "Cannot set user - total number of credentials is too big [endpoint=%d,index=%d,totalCredentials=%u]", + mEndpointId, userIndex, totalCredentials); + return false; + } + + chip::Platform::CopyString(mUserName, userName); + mUserName[userName.size()] = 0; + userInStorage.userName = chip::CharSpan(mUserName, userName.size()); + userInStorage.userUniqueId = uniqueId; + userInStorage.userStatus = userStatus; + userInStorage.userType = usertype; + userInStorage.credentialRule = credentialRule; + userInStorage.lastModifiedBy = modifier; + userInStorage.createdBy = creator; + + for (size_t i = 0; i < totalCredentials; ++i) + { + mCredentials[i] = credentials[i]; + mCredentials[i].CredentialType = 1; + mCredentials[i].CredentialIndex = i + 1; + } + + userInStorage.credentials = chip::Span(mCredentials.Get(), totalCredentials); + + // Save user information in NVM flash + CYW30739Config::WriteConfigValueBin(CYW30739Config::kConfigKey_LockUser, reinterpret_cast(&userInStorage), + sizeof(EmberAfPluginDoorLockUserInfo)); + + CYW30739Config::WriteConfigValueBin(CYW30739Config::kConfigKey_UserCredentials, + reinterpret_cast(mCredentials.Get()), sizeof(DlCredential)); + + CYW30739Config::WriteConfigValueStr(CYW30739Config::kConfigKey_LockUserName, mUserName, sizeof(userName.size())); + + ChipLogProgress(Zcl, "Successfully set the user [mEndpointId=%d,index=%d]", mEndpointId, userIndex); + + return true; +} + +bool LockManager::GetCredential(chip::EndpointId endpointId, uint16_t credentialIndex, DlCredentialType credentialType, + EmberAfPluginDoorLockCredentialInfo & credential) const +{ + ChipLogProgress(Zcl, "Lock App: LockManager::GetCredential [credentialType=%u]", to_underlying(credentialType)); + + const auto & credentialInStorage = mLockCredentials; + + credential.status = credentialInStorage.status; + if (DlCredentialStatus::kAvailable == credential.status) + { + ChipLogDetail(Zcl, "Found unoccupied credential "); + return true; + } + credential.credentialType = credentialInStorage.credentialType; + credential.credentialData = credentialInStorage.credentialData; + + ChipLogDetail(Zcl, "Found occupied credential [type=%u,dataSize=%u]", to_underlying(credential.credentialType), + credential.credentialData.size()); + + return true; +} + +bool LockManager::SetCredential(chip::EndpointId endpointId, uint16_t credentialIndex, DlCredentialStatus credentialStatus, + DlCredentialType credentialType, const chip::ByteSpan & credentialData) +{ + ChipLogProgress(Zcl, + "Door Lock App: LockManager::SetCredential " + "[credentialStatus=%u,credentialType=%u,credentialDataSize=%u]", + to_underlying(credentialStatus), to_underlying(credentialType), credentialData.size()); + + auto & credentialInStorage = mLockCredentials; + if (credentialData.size() > DOOR_LOCK_CREDENTIAL_INFO_MAX_DATA_SIZE) + { + ChipLogError(Zcl, + "Cannot get the credential - data size exceeds limit " + "[dataSize=%u,maxDataSize=%u]", + credentialData.size(), DOOR_LOCK_CREDENTIAL_INFO_MAX_DATA_SIZE); + return false; + } + credentialInStorage.status = credentialStatus; + credentialInStorage.credentialType = credentialType; + + memcpy(mCredentialData, credentialData.data(), credentialData.size()); + mCredentialData[credentialData.size()] = 0; + + credentialInStorage.credentialData = chip::ByteSpan{ mCredentialData, credentialData.size() }; + + // Save user information in NVM flash + CYW30739Config::WriteConfigValueBin(CYW30739Config::kConfigKey_Credential, + reinterpret_cast(&credentialInStorage), + sizeof(EmberAfPluginDoorLockCredentialInfo)); + + CYW30739Config::WriteConfigValueBin(CYW30739Config::kConfigKey_CredentialData, + reinterpret_cast(&mCredentialData), credentialData.size()); + + ChipLogProgress(Zcl, "Successfully set the credential [credentialType=%u]", to_underlying(credentialType)); + + return true; +} + +const char * LockManager::lockStateToString(DlLockState lockState) const +{ + switch (lockState) + { + case DlLockState::kNotFullyLocked: + return "Not Fully Locked"; + case DlLockState::kLocked: + return "Locked"; + case DlLockState::kUnlocked: + return "Unlocked"; + } + + return "Unknown"; +} + +bool LockManager::setLockState(chip::EndpointId endpointId, DlLockState lockState, const Optional & pin, + DlOperationError & err) +{ + DlLockState curState = DlLockState::kLocked; + if (mState == kState_UnlockCompleted) + curState = DlLockState::kUnlocked; + + if (curState == lockState) + { + ChipLogDetail(Zcl, "Door Lock App: door is already locked, set lock state to \"%s\" [endpointId=%d]", + lockStateToString(lockState), mEndpointId); + } + + if (!pin.HasValue()) + { + ChipLogDetail(Zcl, "Door Lock App: PIN code is not specified, setting door lock state to \"%s\" [endpointId=%d]", + lockStateToString(lockState), mEndpointId); + curState = lockState; + + return true; + } + + // Check the PIN code + for (uint8_t i; i < 10; i++) + { + if (mLockCredentials.credentialType != DlCredentialType::kPin || mLockCredentials.status == DlCredentialStatus::kAvailable) + { + continue; + } + + if (mLockCredentials.credentialData.data_equal(pin.Value())) + { + ChipLogDetail(Zcl, + "Lock App: specified PIN code was found in the database, setting lock state to \"%s\" [endpointId=%d]", + lockStateToString(lockState), mEndpointId); + + curState = lockState; + + return true; + } + } + + ChipLogDetail(Zcl, + "Door Lock App: specified PIN code was not found in the database, ignoring command to set lock state to \"%s\" " + "[endpointId=%d]", + lockStateToString(lockState), mEndpointId); + + err = DlOperationError::kInvalidCredential; + return false; +} diff --git a/examples/lock-app/cyw30739/src/ZclCallbacks.cpp b/examples/lock-app/cyw30739/src/ZclCallbacks.cpp index d49b6734d30fc3..ecbc2f78804b24 100644 --- a/examples/lock-app/cyw30739/src/ZclCallbacks.cpp +++ b/examples/lock-app/cyw30739/src/ZclCallbacks.cpp @@ -17,8 +17,9 @@ * limitations under the License. */ -#include +#include "LockManager.h" #include +#include #include #include @@ -46,12 +47,12 @@ void MatterPostAttributeChangeCallback(const app::ConcreteAttributePath & attrib { switch (attributePath.mClusterId) { - case OnOff::Id: - if (attributePath.mAttributeId == OnOff::Attributes::OnOff::Id) + case DoorLock::Id: + if (attributePath.mAttributeId == DoorLock::Attributes::LockState::Id) { + ChipLogProgress(Zcl, "Door lock cluster: " ChipLogFormatMEI, ChipLogValueMEI(attributePath.mClusterId)); printf("ZCL OnOff -> %u\n", *value); - BoltLockMgr().InitiateAction(BoltLockManager::ACTOR_ZCL_CMD, - (*value) ? BoltLockManager::LOCK_ACTION : BoltLockManager::UNLOCK_ACTION); + LockMgr().InitiateAction(LockManager::ACTOR_ZCL_CMD, (*value) ? LockManager::LOCK_ACTION : LockManager::UNLOCK_ACTION); return; } break; @@ -62,3 +63,80 @@ void MatterPostAttributeChangeCallback(const app::ConcreteAttributePath & attrib printf("ERROR clusterId: 0x%04lx, unknown attribute ID: 0x%04lx\n", attributePath.mClusterId, attributePath.mAttributeId); } + +bool emberAfPluginDoorLockOnDoorLockCommand(chip::EndpointId endpointId, const Optional & pinCode, DlOperationError & err) +{ + ChipLogProgress(Zcl, "Door Lock App: Lock Command endpoint=%d", endpointId); + bool status = LockMgr().Lock(endpointId, pinCode, err); + if (status == true) + { + LockMgr().InitiateAction(AppEvent::kEventType_Lock, LockManager::LOCK_ACTION); + } + return status; +} + +bool emberAfPluginDoorLockOnDoorUnlockCommand(chip::EndpointId endpointId, const Optional & pinCode, + DlOperationError & err) +{ + ChipLogProgress(Zcl, "Door Lock App: Unlock Command endpoint=%d", endpointId); + bool status = LockMgr().Unlock(endpointId, pinCode, err); + if (status == true) + { + LockMgr().InitiateAction(AppEvent::kEventType_Lock, LockManager::UNLOCK_ACTION); + } + + return status; +} + +bool emberAfPluginDoorLockGetCredential(chip::EndpointId endpointId, uint16_t credentialIndex, DlCredentialType credentialType, + EmberAfPluginDoorLockCredentialInfo & credential) +{ + return LockMgr().GetCredential(endpointId, credentialIndex, credentialType, credential); +} + +bool emberAfPluginDoorLockSetCredential(chip::EndpointId endpointId, uint16_t credentialIndex, DlCredentialStatus credentialStatus, + DlCredentialType credentialType, const chip::ByteSpan & credentialData) +{ + return LockMgr().SetCredential(endpointId, credentialIndex, credentialStatus, credentialType, credentialData); +} + +bool emberAfPluginDoorLockGetUser(chip::EndpointId endpointId, uint16_t userIndex, EmberAfPluginDoorLockUserInfo & user) +{ + return LockMgr().GetUser(userIndex, user); +} + +bool emberAfPluginDoorLockSetUser(chip::EndpointId endpointId, uint16_t userIndex, chip::FabricIndex creator, + chip::FabricIndex modifier, const chip::CharSpan & userName, uint32_t uniqueId, + DlUserStatus userStatus, DlUserType usertype, DlCredentialRule credentialRule, + const DlCredential * credentials, size_t totalCredentials) +{ + + return LockMgr().SetUser(userIndex, creator, modifier, userName, uniqueId, userStatus, usertype, credentialRule, credentials, + totalCredentials); +} + +// TODO: These functions will be supported by door-lock-server in the future. These are set to return failure until implemented. +DlStatus emberAfPluginDoorLockGetSchedule(chip::EndpointId endpointId, uint8_t weekdayIndex, uint16_t userIndex, + EmberAfPluginDoorLockWeekDaySchedule & schedule) +{ + return DlStatus::kFailure; +} + +DlStatus emberAfPluginDoorLockGetSchedule(chip::EndpointId endpointId, uint8_t yearDayIndex, uint16_t userIndex, + EmberAfPluginDoorLockYearDaySchedule & schedule) +{ + return DlStatus::kFailure; +} + +DlStatus emberAfPluginDoorLockSetSchedule(chip::EndpointId endpointId, uint8_t weekdayIndex, uint16_t userIndex, + DlScheduleStatus status, DlDaysMaskMap daysMask, uint8_t startHour, uint8_t startMinute, + uint8_t endHour, uint8_t endMinute) +{ + return DlStatus::kFailure; +} + +DlStatus emberAfPluginDoorLockSetSchedule(chip::EndpointId endpointId, uint8_t yearDayIndex, uint16_t userIndex, + DlScheduleStatus status, uint32_t localStartTime, uint32_t localEndTime) +{ + return DlStatus::kFailure; +} diff --git a/examples/lock-app/cyw30739/src/main.cpp b/examples/lock-app/cyw30739/src/main.cpp index e1681600146c69..47abd1b802bc3e 100644 --- a/examples/lock-app/cyw30739/src/main.cpp +++ b/examples/lock-app/cyw30739/src/main.cpp @@ -16,17 +16,23 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include + #include -#include #include #include +#include #include +#include +#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR +#include +#endif +#include #include #include #include #include #include -#include #include #include #include @@ -34,16 +40,24 @@ #include #include +using chip::app::Clusters::DoorLock::DlLockState; +using chip::app::Clusters::DoorLock::DlOperationError; +using chip::app::Clusters::DoorLock::DlOperationSource; + +using namespace chip; +using namespace ::chip::DeviceLayer::Internal; + using namespace ::chip::Credentials; using namespace ::chip::DeviceLayer; using namespace ::chip::Shell; wiced_bool_t syncClusterToButtonAction = false; +static void InitApp(intptr_t args); static void EventHandler(const ChipDeviceEvent * event, intptr_t arg); static void HandleThreadStateChangeEvent(const ChipDeviceEvent * event); -static void ActionInitiated(BoltLockManager::Action_t aAction, int32_t aActor); -static void ActionCompleted(BoltLockManager::Action_t aAction); +static void ActionInitiated(LockManager::Action_t aAction, int32_t aActor); +static void ActionCompleted(LockManager::Action_t aAction); static void WriteClusterState(uint8_t value); #ifndef _countof @@ -129,6 +143,24 @@ APPLICATION_START() } #endif + PlatformMgr().ScheduleWork(InitApp, 0); + + const int ret = Engine::Root().Init(); + if (!chip::ChipError::IsSuccess(ret)) + { + printf("ERROR Shell Init %d\n", ret); + } + cmd_ping_init(); + RegisterAppShellCommands(); + Engine::Root().RunMainLoop(); + + assert(!wiced_rtos_check_for_stack_overflow()); +} + +void InitApp(intptr_t args) +{ + ConfigurationMgr().LogDeviceConfig(); + PlatformMgrImpl().AddEventHandler(EventHandler, 0); /* Start CHIP datamodel server */ @@ -138,26 +170,34 @@ APPLICATION_START() SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider()); - err = BoltLockMgr().Init(); - if (err != CHIP_NO_ERROR) + // Initial lock state + chip::app::DataModel::Nullable state; + chip::EndpointId endpointId{ 1 }; + chip::DeviceLayer::PlatformMgr().LockChipStack(); + chip::app::Clusters::DoorLock::Attributes::LockState::Get(endpointId, state); + + uint8_t maxCredentialsPerUser = 0; + if (!DoorLockServer::Instance().GetNumberOfCredentialsSupportedPerUser(endpointId, maxCredentialsPerUser)) { - printf("BoltLockMgr().Init() failed\n"); + ChipLogError(Zcl, + "Unable to get number of credentials supported per user when initializing lock endpoint, defaulting to 5 " + "[endpointId=%d]", + endpointId); + maxCredentialsPerUser = 5; } + chip::DeviceLayer::PlatformMgr().UnlockChipStack(); - BoltLockMgr().SetCallbacks(ActionInitiated, ActionCompleted); - - ConfigurationMgr().LogDeviceConfig(); - - const int ret = streamer_init(streamer_get()); - if (!chip::ChipError::IsSuccess(ret)) + CHIP_ERROR err = LockMgr().Init(state, maxCredentialsPerUser); + if (err != CHIP_NO_ERROR) { - printf("ERROR streamer_init %d\n", ret); + printf("LockMgr().Init() failed\n"); } - cmd_ping_init(); - RegisterAppShellCommands(); - Engine::Root().RunMainLoop(); - assert(!wiced_rtos_check_for_stack_overflow()); + LockMgr().SetCallbacks(ActionInitiated, ActionCompleted); + +#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR + OTAConfig::Init(); +#endif } void EventHandler(const ChipDeviceEvent * event, intptr_t arg) @@ -174,57 +214,71 @@ void EventHandler(const ChipDeviceEvent * event, intptr_t arg) void HandleThreadStateChangeEvent(const ChipDeviceEvent * event) {} -void ActionInitiated(BoltLockManager::Action_t aAction, int32_t aActor) +void ActionInitiated(LockManager::Action_t aAction, int32_t aActor) { // If the action has been initiated by the lock, update the bolt lock trait // and start flashing the LEDs rapidly to indicate action initiation. - if (aAction == BoltLockManager::LOCK_ACTION) + if (aAction == LockManager::LOCK_ACTION) { printf("Lock Action has been initiated\n"); } - else if (aAction == BoltLockManager::UNLOCK_ACTION) + else if (aAction == LockManager::UNLOCK_ACTION) { printf("Unlock Action has been initiated\n"); } - if (aActor == BoltLockManager::ACTOR_BUTTON) + if (aActor == LockManager::ACTOR_BUTTON) { syncClusterToButtonAction = true; } - wiced_led_manager_enable_led(PLATFORM_LED_2); + // Action initiated, update the light led + if (aAction == LockManager::LOCK_ACTION) + { + printf("Lock Action has been initiated"); + wiced_led_manager_disable_led(PLATFORM_LED_2); + } + else if (aAction == LockManager::UNLOCK_ACTION) + { + printf("Unlock Action has been initiated"); + wiced_led_manager_enable_led(PLATFORM_LED_2); + } +} + +void UpdateClusterState(intptr_t context) +{ + bool unlocked = LockMgr().NextState(); + DlLockState newState = unlocked ? DlLockState::kUnlocked : DlLockState::kLocked; + + DlOperationSource source = DlOperationSource::kUnspecified; + + // write the new lock value + EmberAfStatus status = + DoorLockServer::Instance().SetLockState(1, newState, source) ? EMBER_ZCL_STATUS_SUCCESS : EMBER_ZCL_STATUS_FAILURE; + + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + printf("ERR: updating lock state %x", status); + } } -void ActionCompleted(BoltLockManager::Action_t aAction) +void ActionCompleted(LockManager::Action_t aAction) { // if the action has been completed by the lock, update the bolt lock trait. // Turn on the lock LED if in a LOCKED state OR // Turn off the lock LED if in an UNLOCKED state. - if (aAction == BoltLockManager::LOCK_ACTION) + if (aAction == LockManager::LOCK_ACTION) { printf("Lock Action has been completed\n"); - wiced_led_manager_enable_led(PLATFORM_LED_1); } - else if (aAction == BoltLockManager::UNLOCK_ACTION) + else if (aAction == LockManager::UNLOCK_ACTION) { printf("Unlock Action has been completed\n"); - wiced_led_manager_disable_led(PLATFORM_LED_1); } if (syncClusterToButtonAction) { - WriteClusterState(!BoltLockMgr().IsUnlocked()); + chip::DeviceLayer::PlatformMgr().ScheduleWork(UpdateClusterState, reinterpret_cast(nullptr)); syncClusterToButtonAction = false; } - - wiced_led_manager_disable_led(PLATFORM_LED_2); -} - -void WriteClusterState(uint8_t value) -{ - const EmberAfStatus status = chip::app::Clusters::OnOff::Attributes::OnOff::Set(1, value); - if (status != EMBER_ZCL_STATUS_SUCCESS) - { - printf("Error WriteServerAttribute 0x%02x\n", status); - } } diff --git a/examples/ota-requestor-app/cyw30739/BUILD.gn b/examples/ota-requestor-app/cyw30739/BUILD.gn index c4154a12aa32e0..b1ea6fde6aa876 100644 --- a/examples/ota-requestor-app/cyw30739/BUILD.gn +++ b/examples/ota-requestor-app/cyw30739/BUILD.gn @@ -20,6 +20,7 @@ import("${cyw30739_sdk_build_root}/cyw30739_executable.gni") import("${cyw30739_sdk_build_root}/cyw30739_sdk.gni") cyw30739_project_dir = "${chip_root}/examples/ota-requestor-app/cyw30739" +examples_plat_dir = "${chip_root}/examples/platform/cyw30739" declare_args() { setupPinCode = 20202021 @@ -29,7 +30,10 @@ declare_args() { cyw30739_sdk("sdk") { sources = [ "${cyw30739_project_dir}/include/CHIPProjectConfig.h" ] - include_dirs = [ "${cyw30739_project_dir}/include" ] + include_dirs = [ + "${cyw30739_project_dir}/include", + "${examples_plat_dir}", + ] defines = [ "CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE=${setupPinCode}", @@ -50,6 +54,13 @@ cyw30739_executable("ota_requestor_app") { ] include_dirs = [ "include" ] + + if (chip_enable_ota_requestor) { + sources += [ + "${examples_plat_dir}/OTAConfig.cpp", + "${examples_plat_dir}/OTAConfig.h", + ] + } } group("cyw30739") { diff --git a/examples/ota-requestor-app/cyw30739/args.gni b/examples/ota-requestor-app/cyw30739/args.gni index 28971944353082..8eda8fb616b4aa 100644 --- a/examples/ota-requestor-app/cyw30739/args.gni +++ b/examples/ota-requestor-app/cyw30739/args.gni @@ -19,8 +19,4 @@ cyw30739_sdk_target = get_label_info(":sdk", "label_no_toolchain") chip_openthread_ftd = true -# Disable progress logging to fit in flash -chip_progress_logging = false -chip_error_logging = false - chip_enable_ota_requestor = true diff --git a/examples/ota-requestor-app/cyw30739/src/main.cpp b/examples/ota-requestor-app/cyw30739/src/main.cpp index ca59a73f31cf7c..6dedd85ef62fe2 100644 --- a/examples/ota-requestor-app/cyw30739/src/main.cpp +++ b/examples/ota-requestor-app/cyw30739/src/main.cpp @@ -16,22 +16,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include + #include -#include -#include -#include -#include +#include #include #include #include #include #include -#include -#include #include #include #include -#include #include #include @@ -42,12 +38,6 @@ using namespace chip::Shell; static void InitApp(intptr_t args); -DefaultOTARequestor gRequestorCore; -DefaultOTARequestorStorage gRequestorStorage; -DeviceLayer::DefaultOTARequestorDriver gRequestorUser; -BDXDownloader gDownloader; -OTAImageProcessorImpl gImageProcessor; - APPLICATION_START() { CHIP_ERROR err; @@ -130,21 +120,5 @@ void InitApp(intptr_t args) SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider()); - // Initialize and interconnect the Requestor and Image Processor objects -- START - SetRequestorInstance(&gRequestorCore); - - gRequestorStorage.Init(chip::Server::GetInstance().GetPersistentStorage()); - gRequestorCore.Init(chip::Server::GetInstance(), gRequestorStorage, gRequestorUser, gDownloader); - gRequestorUser.Init(&gRequestorCore, &gImageProcessor); - - gImageProcessor.SetOTADownloader(&gDownloader); - - // Connect the Downloader and Image Processor objects - gDownloader.SetImageProcessorDelegate(&gImageProcessor); - // Initialize and interconnect the Requestor and Image Processor objects -- END - - if (!wiced_ota_fw_upgrade_init(NULL, NULL, NULL)) - { - ChipLogError(SoftwareUpdate, "wiced_ota_fw_upgrade_init"); - } + OTAConfig::Init(); } diff --git a/examples/platform/cyw30739/OTAConfig.cpp b/examples/platform/cyw30739/OTAConfig.cpp new file mode 100644 index 00000000000000..cf3553d23a9850 --- /dev/null +++ b/examples/platform/cyw30739/OTAConfig.cpp @@ -0,0 +1,54 @@ +/* + * + * Copyright (c) 2021 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "OTAConfig.h" + +#include +#include +#include +#include +#include +#include + +namespace OTAConfig { + +// Global OTA objects +chip::DefaultOTARequestor gRequestorCore; +chip::DefaultOTARequestorStorage gRequestorStorage; +chip::DeviceLayer::DefaultOTARequestorDriver gRequestorUser; +chip::BDXDownloader gDownloader; +chip::OTAImageProcessorImpl gImageProcessor; + +void Init() +{ + // Initialize and interconnect the Requestor and Image Processor objects -- START + SetRequestorInstance(&gRequestorCore); + + gRequestorStorage.Init(chip::Server::GetInstance().GetPersistentStorage()); + gRequestorCore.Init(chip::Server::GetInstance(), gRequestorStorage, gRequestorUser, gDownloader); + + gRequestorUser.Init(&gRequestorCore, &gImageProcessor); + + gImageProcessor.SetOTADownloader(&gDownloader); + + // Connect the Downloader and Image Processor objects + gDownloader.SetImageProcessorDelegate(&gImageProcessor); + // Initialize and interconnect the Requestor and Image Processor objects -- END +} + +} // namespace OTAConfig diff --git a/examples/platform/cyw30739/OTAConfig.h b/examples/platform/cyw30739/OTAConfig.h new file mode 100644 index 00000000000000..220b50d35cbbe2 --- /dev/null +++ b/examples/platform/cyw30739/OTAConfig.h @@ -0,0 +1,25 @@ +/* + * + * Copyright (c) 2021 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +namespace OTAConfig { + +void Init(); + +} // namespace OTAConfig diff --git a/examples/platform/cyw30739/project_include/OpenThreadConfig.h b/examples/platform/cyw30739/project_include/OpenThreadConfig.h index eb6006f52d5cfe..a6d9c265a245f7 100644 --- a/examples/platform/cyw30739/project_include/OpenThreadConfig.h +++ b/examples/platform/cyw30739/project_include/OpenThreadConfig.h @@ -29,6 +29,7 @@ #define OPENTHREAD_CONFIG_LOG_LEVEL OT_LOG_LEVEL_CRIT #endif +#define OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE 1 #define OPENTHREAD_CONFIG_PLATFORM_ASSERT_MANAGEMENT 1 #define OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_MAX_HOST_ADDRESSES 4 #define OPENTHREAD_CONFIG_TCP_ENABLE 0 diff --git a/src/platform/CYW30739/CHIPPlatformConfig.h b/src/platform/CYW30739/CHIPPlatformConfig.h index 3f9f965e4e4f55..12ee433af8c27d 100644 --- a/src/platform/CYW30739/CHIPPlatformConfig.h +++ b/src/platform/CYW30739/CHIPPlatformConfig.h @@ -23,7 +23,7 @@ #pragma once -#define CHIP_CONFIG_MAX_FABRICS 4 +#define CHIP_CONFIG_MAX_FABRICS 5 #define CHIP_CONFIG_UNAUTHENTICATED_CONNECTION_POOL_SIZE 10 #define CHIP_DEVICE_CONFIG_ENABLE_JUST_IN_TIME_PROVISIONING 1 #define CHIP_DEVICE_CONFIG_ENABLE_THREAD_COMMISSIONABLE_DISCOVERY 1 diff --git a/src/platform/CYW30739/CYW30739Config.cpp b/src/platform/CYW30739/CYW30739Config.cpp index cd845cdbd24bfe..997b573ba36aa9 100644 --- a/src/platform/CYW30739/CYW30739Config.cpp +++ b/src/platform/CYW30739/CYW30739Config.cpp @@ -76,7 +76,8 @@ template CHIP_ERROR CYW30739Config::ReadConfigValue(Key key, bool & val); template CHIP_ERROR CYW30739Config::ReadConfigValue(Key key, uint32_t & val); template CHIP_ERROR CYW30739Config::ReadConfigValue(Key key, uint64_t & val); -CHIP_ERROR CYW30739Config::WriteConfigValue(Key key, uint32_t val) +template +CHIP_ERROR CYW30739Config::WriteConfigValue(Key key, T val) { wiced_result_t result; uint16_t write_count = wiced_hal_write_nvram(PLATFORM_NVRAM_VSID_MATTER_BASE + key, sizeof(val), (uint8_t *) &val, &result); @@ -86,6 +87,10 @@ CHIP_ERROR CYW30739Config::WriteConfigValue(Key key, uint32_t val) return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; } +template CHIP_ERROR CYW30739Config::WriteConfigValue(Key key, bool val); +template CHIP_ERROR CYW30739Config::WriteConfigValue(Key key, uint32_t val); +template CHIP_ERROR CYW30739Config::WriteConfigValue(Key key, uint64_t val); + CHIP_ERROR CYW30739Config::WriteConfigValueStr(Key key, const char * str) { return WriteConfigValueStr(key, str, (str != NULL) ? strlen(str) : 0); @@ -98,9 +103,13 @@ CHIP_ERROR CYW30739Config::WriteConfigValueStr(Key key, const char * str, size_t CHIP_ERROR CYW30739Config::WriteConfigValueBin(Key key, const uint8_t * data, size_t dataLen) { + /* Skip writing because the write API reports error result for zero length data. */ + if (dataLen == 0) + return CHIP_NO_ERROR; + wiced_result_t result; - wiced_hal_write_nvram(PLATFORM_NVRAM_VSID_MATTER_BASE + key, dataLen, (uint8_t *) data, &result); - if (result == WICED_SUCCESS) + const uint16_t write_count = wiced_hal_write_nvram(PLATFORM_NVRAM_VSID_MATTER_BASE + key, dataLen, (uint8_t *) data, &result); + if (result == WICED_SUCCESS && write_count == dataLen) return CHIP_NO_ERROR; else return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; @@ -109,7 +118,8 @@ CHIP_ERROR CYW30739Config::WriteConfigValueBin(Key key, const uint8_t * data, si bool CYW30739Config::ConfigValueExists(Key key) { wiced_result_t result; - wiced_hal_read_nvram(PLATFORM_NVRAM_VSID_MATTER_BASE + key, 0, NULL, &result); + uint8_t val; + wiced_hal_read_nvram(PLATFORM_NVRAM_VSID_MATTER_BASE + key, sizeof(val), &val, &result); if (result != WICED_SUCCESS) wiced_hal_read_nvram_static(PLATFORM_NVRAM_SSID_MATTER_BASE + key, 0, NULL, &result); return result == WICED_SUCCESS; @@ -118,7 +128,7 @@ bool CYW30739Config::ConfigValueExists(Key key) CHIP_ERROR CYW30739Config::FactoryResetConfig(void) { wiced_result_t result; - for (Key key = kConfigKey_Base; key <= kConfigKey_Max; key++) + for (Key key = kMinConfigKey_ChipConfig; key <= kMaxConfigKey_ChipConfig; key++) wiced_hal_delete_nvram(PLATFORM_NVRAM_VSID_MATTER_BASE + key, &result); return CHIP_NO_ERROR; } diff --git a/src/platform/CYW30739/CYW30739Config.h b/src/platform/CYW30739/CYW30739Config.h index 00975a89f77fb6..ef192d83dc32cb 100644 --- a/src/platform/CYW30739/CYW30739Config.h +++ b/src/platform/CYW30739/CYW30739Config.h @@ -32,6 +32,11 @@ namespace chip { namespace DeviceLayer { namespace Internal { +constexpr inline uint32_t CYW30739ConfigKey(uint8_t keyBaseOffset, uint8_t id) +{ + return static_cast(keyBaseOffset) << 8 | id; +} + /** * Provides functions and definitions for accessing device configuration information. */ @@ -40,36 +45,45 @@ class CYW30739Config public: using Key = uint32_t; + static constexpr uint8_t kChipFactory_KeyBase = 0x00; + static constexpr uint8_t kChipConfig_KeyBase = 0x01; + // Key definitions for well-known keys. // Factory config keys - static constexpr Key kConfigKey_SerialNum = 0; - static constexpr Key kConfigKey_MfrDeviceId = 1; - static constexpr Key kConfigKey_MfrDeviceCert = 2; - static constexpr Key kConfigKey_MfrDevicePrivateKey = 3; - static constexpr Key kConfigKey_ManufacturingDate = 4; - static constexpr Key kConfigKey_SetupPinCode = 5; - static constexpr Key kConfigKey_MfrDeviceICACerts = 6; - static constexpr Key kConfigKey_SetupDiscriminator = 7; - static constexpr Key kConfigKey_Spake2pIterationCount = 8; - static constexpr Key kConfigKey_Spake2pSalt = 9; - static constexpr Key kConfigKey_Spake2pVerifier = 10; + static constexpr Key kConfigKey_SerialNum = CYW30739ConfigKey(kChipFactory_KeyBase, 0x00); + static constexpr Key kConfigKey_MfrDeviceId = CYW30739ConfigKey(kChipFactory_KeyBase, 0x01); + static constexpr Key kConfigKey_MfrDeviceCert = CYW30739ConfigKey(kChipFactory_KeyBase, 0x02); + static constexpr Key kConfigKey_MfrDevicePrivateKey = CYW30739ConfigKey(kChipFactory_KeyBase, 0x03); + static constexpr Key kConfigKey_ManufacturingDate = CYW30739ConfigKey(kChipFactory_KeyBase, 0x04); + static constexpr Key kConfigKey_SetupPinCode = CYW30739ConfigKey(kChipFactory_KeyBase, 0x05); + static constexpr Key kConfigKey_MfrDeviceICACerts = CYW30739ConfigKey(kChipFactory_KeyBase, 0x06); + static constexpr Key kConfigKey_SetupDiscriminator = CYW30739ConfigKey(kChipFactory_KeyBase, 0x07); + static constexpr Key kConfigKey_Spake2pIterationCount = CYW30739ConfigKey(kChipFactory_KeyBase, 0x08); + static constexpr Key kConfigKey_Spake2pSalt = CYW30739ConfigKey(kChipFactory_KeyBase, 0x09); + static constexpr Key kConfigKey_Spake2pVerifier = CYW30739ConfigKey(kChipFactory_KeyBase, 0x0a); // CHIP Config Keys - static constexpr Key kConfigKey_ServiceConfig = 9; - static constexpr Key kConfigKey_PairedAccountId = 10; - static constexpr Key kConfigKey_ServiceId = 11; - static constexpr Key kConfigKey_LastUsedEpochKeyId = 13; - static constexpr Key kConfigKey_FailSafeArmed = 14; - static constexpr Key kConfigKey_GroupKey = 15; - static constexpr Key kConfigKey_HardwareVersion = 16; - static constexpr Key kConfigKey_RegulatoryLocation = 17; - static constexpr Key kConfigKey_CountryCode = 18; - static constexpr Key kConfigKey_HourFormat = 20; - static constexpr Key kConfigKey_CalendarType = 21; - static constexpr Key kConfigKey_UniqueId = 23; + static constexpr Key kConfigKey_ServiceConfig = CYW30739ConfigKey(kChipConfig_KeyBase, 0x00); + static constexpr Key kConfigKey_PairedAccountId = CYW30739ConfigKey(kChipConfig_KeyBase, 0x01); + static constexpr Key kConfigKey_ServiceId = CYW30739ConfigKey(kChipConfig_KeyBase, 0x02); + static constexpr Key kConfigKey_LastUsedEpochKeyId = CYW30739ConfigKey(kChipConfig_KeyBase, 0x03); + static constexpr Key kConfigKey_FailSafeArmed = CYW30739ConfigKey(kChipConfig_KeyBase, 0x04); + static constexpr Key kConfigKey_GroupKey = CYW30739ConfigKey(kChipConfig_KeyBase, 0x05); + static constexpr Key kConfigKey_HardwareVersion = CYW30739ConfigKey(kChipConfig_KeyBase, 0x06); + static constexpr Key kConfigKey_RegulatoryLocation = CYW30739ConfigKey(kChipConfig_KeyBase, 0x07); + static constexpr Key kConfigKey_CountryCode = CYW30739ConfigKey(kChipConfig_KeyBase, 0x08); + static constexpr Key kConfigKey_RebootCount = CYW30739ConfigKey(kChipConfig_KeyBase, 0x09); + static constexpr Key kConfigKey_UniqueId = CYW30739ConfigKey(kChipConfig_KeyBase, 0x0a); + static constexpr Key kConfigKey_LockUser = CYW30739ConfigKey(kChipConfig_KeyBase, 0x0b); + static constexpr Key kConfigKey_Credential = CYW30739ConfigKey(kChipConfig_KeyBase, 0x0c); + static constexpr Key kConfigKey_LockUserName = CYW30739ConfigKey(kChipConfig_KeyBase, 0x0d); + static constexpr Key kConfigKey_CredentialData = CYW30739ConfigKey(kChipConfig_KeyBase, 0x0e); + static constexpr Key kConfigKey_UserCredentials = CYW30739ConfigKey(kChipConfig_KeyBase, 0x0f); // Set key id limits for each group. - static constexpr Key kConfigKey_Base = kConfigKey_SerialNum; - static constexpr Key kConfigKey_Max = kConfigKey_UniqueId; + static constexpr Key kMinConfigKey_ChipFactory = CYW30739ConfigKey(kChipFactory_KeyBase, 0x00); + static constexpr Key kMaxConfigKey_ChipFactory = CYW30739ConfigKey(kChipFactory_KeyBase, 0x0a); + static constexpr Key kMinConfigKey_ChipConfig = CYW30739ConfigKey(kChipConfig_KeyBase, 0x00); + static constexpr Key kMaxConfigKey_ChipConfig = CYW30739ConfigKey(kChipConfig_KeyBase, 0x0f); static CHIP_ERROR Init(void); @@ -79,7 +93,8 @@ class CYW30739Config static CHIP_ERROR ReadConfigValueStr(Key key, char * buf, size_t bufSize, size_t & outLen); static CHIP_ERROR ReadConfigValueBin(Key key, uint8_t * buf, size_t bufSize, size_t & outLen); - static CHIP_ERROR WriteConfigValue(Key key, uint32_t val); + template + static CHIP_ERROR WriteConfigValue(Key key, T val); static CHIP_ERROR WriteConfigValueStr(Key key, const char * str); static CHIP_ERROR WriteConfigValueStr(Key key, const char * str, size_t strLen); static CHIP_ERROR WriteConfigValueBin(Key key, const uint8_t * data, size_t dataLen); diff --git a/src/platform/CYW30739/ConfigurationManagerImpl.cpp b/src/platform/CYW30739/ConfigurationManagerImpl.cpp index 1bd7ad747301d6..80942ea58b6705 100644 --- a/src/platform/CYW30739/ConfigurationManagerImpl.cpp +++ b/src/platform/CYW30739/ConfigurationManagerImpl.cpp @@ -46,6 +46,21 @@ ConfigurationManagerImpl & ConfigurationManagerImpl::GetDefaultInstance() CHIP_ERROR ConfigurationManagerImpl::Init() { CHIP_ERROR err; + uint32_t rebootCount; + if (CYW30739Config::ConfigValueExists(CYW30739Config::kConfigKey_RebootCount)) + { + err = GetRebootCount(rebootCount); + SuccessOrExit(err); + + err = StoreRebootCount(rebootCount + 1); + SuccessOrExit(err); + } + else + { + // The first boot after factory reset of the Node. + err = StoreRebootCount(1); + SuccessOrExit(err); + } // Initialize the generic implementation base class. err = Internal::GenericConfigurationManagerImpl::Init(); @@ -55,6 +70,16 @@ CHIP_ERROR ConfigurationManagerImpl::Init() return err; } +CHIP_ERROR ConfigurationManagerImpl::GetRebootCount(uint32_t & rebootCount) +{ + return ReadConfigValue(CYW30739Config::kConfigKey_RebootCount, rebootCount); +} + +CHIP_ERROR ConfigurationManagerImpl::StoreRebootCount(uint32_t rebootCount) +{ + return WriteConfigValue(CYW30739Config::kConfigKey_RebootCount, rebootCount); +} + bool ConfigurationManagerImpl::CanFactoryReset(void) { return true; @@ -160,6 +185,12 @@ void ConfigurationManagerImpl::DoFactoryReset(intptr_t arg) #endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD + err = PersistedStorage::KeyValueStoreMgrImpl().EraseAll(); + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "Clear Key-Value Storage failed"); + } + // Restart the system. ChipLogProgress(DeviceLayer, "System restarting"); wiced_hal_wdog_reset_system(); diff --git a/src/platform/CYW30739/ConfigurationManagerImpl.h b/src/platform/CYW30739/ConfigurationManagerImpl.h index 021fde30a0067e..238425f7e28f52 100644 --- a/src/platform/CYW30739/ConfigurationManagerImpl.h +++ b/src/platform/CYW30739/ConfigurationManagerImpl.h @@ -39,6 +39,8 @@ class ConfigurationManagerImpl : public Internal::GenericConfigurationManagerImp public: // This returns an instance of this class. static ConfigurationManagerImpl & GetDefaultInstance(); + CHIP_ERROR GetRebootCount(uint32_t & rebootCount) override; + CHIP_ERROR StoreRebootCount(uint32_t rebootCount) override; private: // ===== Members that implement the ConfigurationManager public interface. diff --git a/src/platform/CYW30739/DiagnosticDataProviderImpl.cpp b/src/platform/CYW30739/DiagnosticDataProviderImpl.cpp old mode 100644 new mode 100755 index 7360320ad800ed..c39fda18dd545f --- a/src/platform/CYW30739/DiagnosticDataProviderImpl.cpp +++ b/src/platform/CYW30739/DiagnosticDataProviderImpl.cpp @@ -29,6 +29,10 @@ #include #include +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD +#include +#endif + namespace chip { namespace DeviceLayer { @@ -65,5 +69,49 @@ CHIP_ERROR DiagnosticDataProviderImpl::GetCurrentHeapHighWatermark(uint64_t & cu return CHIP_NO_ERROR; } +CHIP_ERROR DiagnosticDataProviderImpl::GetRebootCount(uint16_t & rebootCount) +{ + uint32_t count = 0; + CHIP_ERROR err = ConfigurationMgr().GetRebootCount(count); + if (err == CHIP_NO_ERROR) + { + // If the value overflows, return UINT16 max value to provide best-effort number. + rebootCount = static_cast(count <= UINT16_MAX ? count : UINT16_MAX); + } + return err; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetNetworkInterfaces(NetworkInterface ** netifpp) +{ + NetworkInterface * ifp = Platform::New(); + +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD + const char * threadNetworkName = otThreadGetNetworkName(ThreadStackMgrImpl().OTInstance()); + ifp->name = Span(threadNetworkName, strlen(threadNetworkName)); + ifp->isOperational = true; + ifp->offPremiseServicesReachableIPv4.SetNull(); + ifp->offPremiseServicesReachableIPv6.SetNull(); + ifp->type = app::Clusters::GeneralDiagnostics::InterfaceType::EMBER_ZCL_INTERFACE_TYPE_THREAD; +#else + /* TODO */ +#endif + uint8_t macBuffer[ConfigurationManager::kPrimaryMACAddressLength]; + ConfigurationMgr().GetPrimary802154MACAddress(macBuffer); + ifp->hardwareAddress = ByteSpan(macBuffer, ConfigurationManager::kPrimaryMACAddressLength); + + *netifpp = ifp; + return CHIP_NO_ERROR; +} + +void DiagnosticDataProviderImpl::ReleaseNetworkInterfaces(NetworkInterface * netifp) +{ + while (netifp) + { + NetworkInterface * del = netifp; + netifp = netifp->Next; + Platform::Delete(del); + } +} + } // namespace DeviceLayer } // namespace chip diff --git a/src/platform/CYW30739/DiagnosticDataProviderImpl.h b/src/platform/CYW30739/DiagnosticDataProviderImpl.h index 6505cf5eedff17..dbaa6f15c975da 100644 --- a/src/platform/CYW30739/DiagnosticDataProviderImpl.h +++ b/src/platform/CYW30739/DiagnosticDataProviderImpl.h @@ -42,6 +42,9 @@ class DiagnosticDataProviderImpl : public DiagnosticDataProvider CHIP_ERROR GetCurrentHeapFree(uint64_t & currentHeapFree) override; CHIP_ERROR GetCurrentHeapUsed(uint64_t & currentHeapUsed) override; CHIP_ERROR GetCurrentHeapHighWatermark(uint64_t & currentHeapHighWatermark) override; + CHIP_ERROR GetRebootCount(uint16_t & rebootCount) override; + CHIP_ERROR GetNetworkInterfaces(NetworkInterface ** netifpp) override; + void ReleaseNetworkInterfaces(NetworkInterface * netifp) override; }; } // namespace DeviceLayer diff --git a/src/platform/CYW30739/KeyValueStoreManagerImpl.cpp b/src/platform/CYW30739/KeyValueStoreManagerImpl.cpp index e89017b8c4adc6..2e274875f6c641 100644 --- a/src/platform/CYW30739/KeyValueStoreManagerImpl.cpp +++ b/src/platform/CYW30739/KeyValueStoreManagerImpl.cpp @@ -128,6 +128,19 @@ CHIP_ERROR KeyValueStoreManagerImpl::_Delete(const char * key) return err; } +CHIP_ERROR KeyValueStoreManagerImpl::EraseAll(void) +{ + wiced_result_t result; + wiced_hal_delete_nvram(PLATFORM_NVRAM_ID_ENTRY_INFO_STRING, &result); + if (result == WICED_SUCCESS) + { + return CHIP_NO_ERROR; + } + + ChipLogError(DeviceLayer, "%s wiced_hal_delete_nvram %u", __func__, result); + return CHIP_ERROR_PERSISTED_STORAGE_FAILED; +} + bool KeyValueStoreManagerImpl::KeyEntry::IsMatchKey(const char * key) { return mIsValid && strncmp(mKey, key, sizeof(mKey)) == 0; diff --git a/src/platform/CYW30739/KeyValueStoreManagerImpl.h b/src/platform/CYW30739/KeyValueStoreManagerImpl.h index de2928da942180..1d418844419777 100644 --- a/src/platform/CYW30739/KeyValueStoreManagerImpl.h +++ b/src/platform/CYW30739/KeyValueStoreManagerImpl.h @@ -44,11 +44,29 @@ class KeyValueStoreManagerImpl final : public KeyValueStoreManager CHIP_ERROR _Put(const char * key, const void * value, size_t value_size); + CHIP_ERROR EraseAll(void); + private: - static constexpr uint8_t mMaxEntryCount = 1 + /* For the global message counter */ - 1 + /* For the admin key count */ - CHIP_CONFIG_MAX_FABRICS + 1 /* For the session key count */ - ; + static constexpr uint8_t mMaxEntryCount = 1 + /* global event id counter */ + 1 + /* FabricIndexInfo */ + CHIP_CONFIG_MAX_FABRICS + /* FabricNOC */ + CHIP_CONFIG_MAX_FABRICS + /* FabricICAC */ + CHIP_CONFIG_MAX_FABRICS + /* FabricRCAC */ + CHIP_CONFIG_MAX_FABRICS + /* FabricMetadata */ + CHIP_CONFIG_MAX_FABRICS + /* FabricOpKey */ + 1 + /* AccessControlList */ + CHIP_CONFIG_EXAMPLE_ACCESS_CONTROL_MAX_ENTRIES_PER_FABRIC + /* AccessControlEntry */ + 1 + /* GroupDataCounter */ + 1 + /* GroupControlCounter */ + 1 + /* FabricTable */ + 4 + /* FabricGroups */ + CHIP_CONFIG_MAX_FABRICS * 3 + /* FabricKeyset */ + 1 + /* OTADefaultProviders */ + 1 + /* OTACurrentProvider */ + 1 + /* OTAUpdateToken */ + 1 + /* OTACurrentUpdateState */ + 1 + /* OTATargetVersion */ + 16; /* AttributeValue */ struct KeyEntry { diff --git a/src/platform/CYW30739/OTAImageProcessorImpl.cpp b/src/platform/CYW30739/OTAImageProcessorImpl.cpp index 1058afb042b501..27443e994829db 100644 --- a/src/platform/CYW30739/OTAImageProcessorImpl.cpp +++ b/src/platform/CYW30739/OTAImageProcessorImpl.cpp @@ -17,11 +17,14 @@ */ #include +#include #include #include #include "OTAImageProcessorImpl.h" +using namespace chip::System; + namespace chip { CHIP_ERROR OTAImageProcessorImpl::PrepareDownload() @@ -66,6 +69,35 @@ CHIP_ERROR OTAImageProcessorImpl::ProcessBlock(ByteSpan & block) return CHIP_NO_ERROR; } +bool OTAImageProcessorImpl::IsFirstImageRun() +{ + OTARequestorInterface * requestor = chip::GetRequestorInstance(); + if (requestor == nullptr) + { + return false; + } + + return requestor->GetCurrentUpdateState() == OTARequestorInterface::OTAUpdateStateEnum::kApplying; +} + +CHIP_ERROR OTAImageProcessorImpl::ConfirmCurrentImage() +{ + OTARequestorInterface * requestor = chip::GetRequestorInstance(); + if (requestor == nullptr) + { + return CHIP_ERROR_INTERNAL; + } + + uint32_t currentVersion; + ReturnErrorOnFailure(DeviceLayer::ConfigurationMgr().GetSoftwareVersion(currentVersion)); + if (currentVersion != requestor->GetTargetVersion()) + { + return CHIP_ERROR_INCORRECT_STATE; + } + + return CHIP_NO_ERROR; +} + void OTAImageProcessorImpl::HandlePrepareDownload(intptr_t context) { auto * imageProcessor = reinterpret_cast(context); @@ -80,6 +112,8 @@ void OTAImageProcessorImpl::HandlePrepareDownload(intptr_t context) return; } + imageProcessor->mHeaderParser.Init(); + if (!wiced_firmware_upgrade_prepare()) { ChipLogError(SoftwareUpdate, "wiced_firmware_upgrade_prepare"); @@ -113,10 +147,7 @@ void OTAImageProcessorImpl::HandleFinalize(intptr_t context) void OTAImageProcessorImpl::HandleApply(intptr_t context) { auto * imageProcessor = reinterpret_cast(context); - if (imageProcessor == nullptr) - { - return; - } + VerifyOrReturn(imageProcessor != nullptr); if (!wiced_firmware_upgrade_apply()) { @@ -126,7 +157,13 @@ void OTAImageProcessorImpl::HandleApply(intptr_t context) ChipLogProgress(SoftwareUpdate, "OTA upgrade completed"); - wiced_hal_wdog_reset_system(); + DeviceLayer::SystemLayer().StartTimer( + System::Clock::Seconds32(15), + [](Layer *, void *) { + ChipLogProgress(SoftwareUpdate, "Rebooting..."); + wiced_hal_wdog_reset_system(); + }, + nullptr); } void OTAImageProcessorImpl::HandleAbort(intptr_t context) @@ -158,11 +195,20 @@ void OTAImageProcessorImpl::HandleProcessBlock(intptr_t context) return; } - if (IsSpanUsable(imageProcessor->mBlock)) + ByteSpan block = imageProcessor->mBlock; + CHIP_ERROR error = imageProcessor->ProcessHeader(block); + if (error != CHIP_NO_ERROR) + { + ChipLogError(SoftwareUpdate, "Image does not contain a valid header"); + imageProcessor->mDownloader->EndDownload(CHIP_ERROR_INVALID_FILE_IDENTIFIER); + return; + } + + if (IsSpanUsable(block)) { - const uint32_t written = wiced_firmware_upgrade_process_block(imageProcessor->mParams.downloadedBytes, - imageProcessor->mBlock.data(), imageProcessor->mBlock.size()); - if (written != imageProcessor->mBlock.size()) + const uint32_t written = + wiced_firmware_upgrade_process_block(imageProcessor->mParams.downloadedBytes, block.data(), block.size()); + if (written != block.size()) { ChipLogError(SoftwareUpdate, "wiced_firmware_upgrade_process_block 0x%08lx", written); imageProcessor->mDownloader->EndDownload(CHIP_ERROR_WRITE_FAILED); @@ -170,10 +216,35 @@ void OTAImageProcessorImpl::HandleProcessBlock(intptr_t context) } } - imageProcessor->mParams.downloadedBytes += imageProcessor->mBlock.size(); + imageProcessor->mParams.downloadedBytes += block.size(); imageProcessor->mDownloader->FetchNextData(); } +CHIP_ERROR OTAImageProcessorImpl::ProcessHeader(ByteSpan & block) +{ + if (mHeaderParser.IsInitialized()) + { + OTAImageHeader header; + CHIP_ERROR error = mHeaderParser.AccumulateAndDecode(block, header); + + // Needs more data to decode the header + ReturnErrorCodeIf(error == CHIP_ERROR_BUFFER_TOO_SMALL, CHIP_NO_ERROR); + ReturnErrorOnFailure(error); + + mParams.totalFileBytes = header.mPayloadSize; + mHeaderParser.Clear(); + + /* Skip inserted zeroes before sections */ + const size_t header_size = mBlock.size() - block.size(); + if (header_size % 4 != 0) + { + block = block.SubSpan(4 - header_size % 4); + } + } + + return CHIP_NO_ERROR; +} + CHIP_ERROR OTAImageProcessorImpl::SetBlock(ByteSpan & block) { if (!IsSpanUsable(block)) diff --git a/src/platform/CYW30739/OTAImageProcessorImpl.h b/src/platform/CYW30739/OTAImageProcessorImpl.h index fc2e5f9da1ee72..d9ea2dfc5f071c 100644 --- a/src/platform/CYW30739/OTAImageProcessorImpl.h +++ b/src/platform/CYW30739/OTAImageProcessorImpl.h @@ -19,6 +19,7 @@ #pragma once #include +#include #include #include @@ -35,8 +36,8 @@ class OTAImageProcessorImpl : public OTAImageProcessorInterface CHIP_ERROR Apply() override; CHIP_ERROR Abort() override; CHIP_ERROR ProcessBlock(ByteSpan & block) override; - bool IsFirstImageRun() override { return false; } - CHIP_ERROR ConfirmCurrentImage() override { return CHIP_NO_ERROR; } + bool IsFirstImageRun() override; + CHIP_ERROR ConfirmCurrentImage() override; void SetOTADownloader(OTADownloader * downloader) { mDownloader = downloader; } @@ -48,6 +49,8 @@ class OTAImageProcessorImpl : public OTAImageProcessorInterface static void HandleAbort(intptr_t context); static void HandleProcessBlock(intptr_t context); + CHIP_ERROR ProcessHeader(ByteSpan & block); + /** * Called to allocate memory for mBlock if necessary and set it to block */ @@ -60,6 +63,7 @@ class OTAImageProcessorImpl : public OTAImageProcessorInterface MutableByteSpan mBlock; OTADownloader * mDownloader; + OTAImageHeaderParser mHeaderParser; }; } // namespace chip diff --git a/src/platform/CYW30739/ThreadStackManagerImpl.cpp b/src/platform/CYW30739/ThreadStackManagerImpl.cpp index f8d8a76b034120..dcdee6f6d27999 100644 --- a/src/platform/CYW30739/ThreadStackManagerImpl.cpp +++ b/src/platform/CYW30739/ThreadStackManagerImpl.cpp @@ -25,6 +25,7 @@ #include +#include #include #include #include @@ -101,6 +102,16 @@ void ThreadStackManagerImpl::ThreadTaskMain(uint32_t arg) } // namespace DeviceLayer } // namespace chip +extern "C" void * otPlatCAlloc(size_t aNum, size_t aSize) +{ + return CHIPPlatformMemoryCalloc(aNum, aSize); +} + +extern "C" void otPlatFree(void * aPtr) +{ + CHIPPlatformMemoryFree(aPtr); +} + /* A wrapper for the GenericThreadStackManagerImpl_OpenThread_LwIP implementation. */ err_t tcpip_input(struct pbuf * p, struct netif * inp) { diff --git a/src/platform/CYW30739/args.gni b/src/platform/CYW30739/args.gni index 474c15b41b7f5e..3cc85db63b6c25 100644 --- a/src/platform/CYW30739/args.gni +++ b/src/platform/CYW30739/args.gni @@ -29,8 +29,6 @@ chip_crypto = "mbedtls" chip_device_platform = "cyw30739" chip_mdns = "platform" -# Trying to fit into the available flash by disabling optional logging for now -chip_detail_logging = false chip_enable_openthread = true lwip_platform = "cyw30739" diff --git a/src/platform/CYW30739/cyw30739-chip-mbedtls-config.h b/src/platform/CYW30739/cyw30739-chip-mbedtls-config.h index 0a7a749871aa48..f9de67ab717faa 100644 --- a/src/platform/CYW30739/cyw30739-chip-mbedtls-config.h +++ b/src/platform/CYW30739/cyw30739-chip-mbedtls-config.h @@ -42,12 +42,12 @@ * digests and ciphers instead. * */ -//#define MBEDTLS_AES_ALT +#define MBEDTLS_AES_ALT //#define MBEDTLS_ARC4_ALT //#define MBEDTLS_ARIA_ALT //#define MBEDTLS_BLOWFISH_ALT //#define MBEDTLS_CAMELLIA_ALT -//#define MBEDTLS_CCM_ALT +#define MBEDTLS_CCM_ALT //#define MBEDTLS_CHACHA20_ALT //#define MBEDTLS_CHACHAPOLY_ALT //#define MBEDTLS_CMAC_ALT @@ -63,7 +63,7 @@ //#define MBEDTLS_RIPEMD160_ALT //#define MBEDTLS_RSA_ALT //#define MBEDTLS_SHA1_ALT -//#define MBEDTLS_SHA256_ALT +#define MBEDTLS_SHA256_ALT //#define MBEDTLS_SHA512_ALT //#define MBEDTLS_XTEA_ALT diff --git a/third_party/cyw30739_sdk/BUILD.gn b/third_party/cyw30739_sdk/BUILD.gn index 288d0135525ba7..a64a0293f54305 100644 --- a/third_party/cyw30739_sdk/BUILD.gn +++ b/third_party/cyw30739_sdk/BUILD.gn @@ -39,6 +39,12 @@ config("mbedtls_cyw30739_config") { } mbedtls_target("mbedtls") { + sources = [ + "${chip_root}/third_party/openthread/ot-ifx/src/cyw30739/mbedtls/library/aes_alt.c", + "${chip_root}/third_party/openthread/ot-ifx/src/cyw30739/mbedtls/library/ccm_alt.c", + "${chip_root}/third_party/openthread/ot-ifx/src/cyw30739/mbedtls/library/sha256_alt.c", + ] + public_configs = [ ":mbedtls_cyw30739_config" ] public_deps = [ "${openthread_root}/src/core:libopenthread_core_headers" ] diff --git a/third_party/cyw30739_sdk/bsp_design_modus/cycfg_pins.c b/third_party/cyw30739_sdk/bsp_design_modus/cycfg_pins.c index 074229958e8113..ec8bc6af4af752 100644 --- a/third_party/cyw30739_sdk/bsp_design_modus/cycfg_pins.c +++ b/third_party/cyw30739_sdk/bsp_design_modus/cycfg_pins.c @@ -4,14 +4,13 @@ * Description: * Pin configuration * This file was automatically generated and should not be modified. - * Tools Package 2.4.0.5880 - * 20739B2 CSP + * Tools Package 2.3.0.4276 + * 30739A0 CSP * personalities 1.0.0.31 - * udd 3.0.0.1454 + * udd 3.0.0.1636 * ******************************************************************************** - * Copyright 2021 Cypress Semiconductor Corporation (an Infineon company) or - * an affiliate of Cypress Semiconductor Corporation. + * Copyright 2022 Cypress Semiconductor Corporation * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -29,79 +28,118 @@ #include "cycfg_pins.h" +#if CHIP_PACKAGE_WLCSP #define BUTTON_USER_config \ { \ .gpio = (wiced_bt_gpio_numbers_t *) &platform_gpio_pins[PLATFORM_GPIO_0].gpio_pin, \ .config = GPIO_INPUT_ENABLE | GPIO_PULL_UP, .default_state = GPIO_PIN_OUTPUT_HIGH, \ .button_pressed_value = GPIO_PIN_OUTPUT_LOW, \ } -#define GPIO2_config \ +#define GPIO3_config \ { \ .gpio = (wiced_bt_gpio_numbers_t *) &platform_gpio_pins[PLATFORM_GPIO_5].gpio_pin, \ .config = GPIO_OUTPUT_ENABLE | GPIO_INPUT_DISABLE, .default_state = GPIO_PIN_OUTPUT_LOW, \ } -#define RX_PU_config \ +#define GPIO4_config \ { \ - .gpio = (wiced_bt_gpio_numbers_t *) &platform_gpio_pins[PLATFORM_GPIO_6].gpio_pin, \ - .config = GPIO_OUTPUT_ENABLE | GPIO_INPUT_DISABLE, .default_state = GPIO_PIN_OUTPUT_LOW, \ + .gpio = (wiced_bt_gpio_numbers_t *) &platform_gpio_pins[PLATFORM_GPIO_9].gpio_pin, \ + .config = GPIO_INPUT_ENABLE | GPIO_PULL_UP_DOWN_NONE, .default_state = GPIO_PIN_OUTPUT_LOW, \ } -#define GPIO3_config \ +#define GPIO5_config \ { \ - .gpio = (wiced_bt_gpio_numbers_t *) &platform_gpio_pins[PLATFORM_GPIO_7].gpio_pin, \ + .gpio = (wiced_bt_gpio_numbers_t *) &platform_gpio_pins[PLATFORM_GPIO_11].gpio_pin, \ .config = GPIO_INPUT_ENABLE | GPIO_PULL_UP_DOWN_NONE, .default_state = GPIO_PIN_OUTPUT_LOW, \ } -#define TX_PU_config \ +#define GPIO6_config \ { \ - .gpio = (wiced_bt_gpio_numbers_t *) &platform_gpio_pins[PLATFORM_GPIO_8].gpio_pin, \ - .config = GPIO_OUTPUT_ENABLE | GPIO_INPUT_DISABLE, .default_state = GPIO_PIN_OUTPUT_HIGH, \ + .gpio = (wiced_bt_gpio_numbers_t *) &platform_gpio_pins[PLATFORM_GPIO_12].gpio_pin, \ + .config = GPIO_INPUT_ENABLE | GPIO_PULL_UP_DOWN_NONE, .default_state = GPIO_PIN_OUTPUT_LOW, \ } -#define GPIO4_config \ +#define DEBUG_UART_TXD_config \ { \ - .gpio = (wiced_bt_gpio_numbers_t *) &platform_gpio_pins[PLATFORM_GPIO_9].gpio_pin, \ + .gpio = (wiced_bt_gpio_numbers_t *) &platform_gpio_pins[PLATFORM_GPIO_15].gpio_pin, \ .config = GPIO_INPUT_ENABLE | GPIO_PULL_UP_DOWN_NONE, .default_state = GPIO_PIN_OUTPUT_LOW, \ } -#define GPIO5_config \ +#define LED1_config \ { \ - .gpio = (wiced_bt_gpio_numbers_t *) &platform_gpio_pins[PLATFORM_GPIO_10].gpio_pin, \ + .gpio = (wiced_bt_gpio_numbers_t *) &platform_gpio_pins[PLATFORM_GPIO_16].gpio_pin, \ + .config = GPIO_OUTPUT_ENABLE | GPIO_PULL_UP, .default_state = GPIO_PIN_OUTPUT_HIGH, \ + } +#define LED2_config \ + { \ + .gpio = (wiced_bt_gpio_numbers_t *) &platform_gpio_pins[PLATFORM_GPIO_17].gpio_pin, \ + .config = GPIO_OUTPUT_ENABLE | GPIO_PULL_UP, .default_state = GPIO_PIN_OUTPUT_HIGH, \ + } +#define GPIO2_config \ + { \ + .gpio = (wiced_bt_gpio_numbers_t *) &platform_gpio_pins[PLATFORM_GPIO_3].gpio_pin, \ .config = GPIO_INPUT_ENABLE | GPIO_PULL_UP_DOWN_NONE, .default_state = GPIO_PIN_OUTPUT_LOW, \ } +#else // !CHIP_PACKAGE_WLCSP +#define BUTTON_USER_config \ + { \ + .gpio = (wiced_bt_gpio_numbers_t *) &platform_gpio_pins[PLATFORM_GPIO_0].gpio_pin, \ + .config = GPIO_INPUT_ENABLE | GPIO_PULL_UP, .default_state = GPIO_PIN_OUTPUT_HIGH, \ + .button_pressed_value = GPIO_PIN_OUTPUT_LOW, \ + } #define DEBUG_UART_TXD_config \ { \ - .gpio = (wiced_bt_gpio_numbers_t *) &platform_gpio_pins[PLATFORM_GPIO_12].gpio_pin, \ + .gpio = (wiced_bt_gpio_numbers_t *) &platform_gpio_pins[PLATFORM_GPIO_11].gpio_pin, \ .config = GPIO_INPUT_ENABLE | GPIO_PULL_UP_DOWN_NONE, .default_state = GPIO_PIN_OUTPUT_LOW, \ } #define LED1_config \ { \ - .gpio = (wiced_bt_gpio_numbers_t *) &platform_gpio_pins[PLATFORM_GPIO_13].gpio_pin, \ + .gpio = (wiced_bt_gpio_numbers_t *) &platform_gpio_pins[PLATFORM_GPIO_12].gpio_pin, \ .config = GPIO_OUTPUT_ENABLE | GPIO_PULL_UP, .default_state = GPIO_PIN_OUTPUT_HIGH, \ } #define LED2_config \ { \ - .gpio = (wiced_bt_gpio_numbers_t *) &platform_gpio_pins[PLATFORM_GPIO_14].gpio_pin, \ + .gpio = (wiced_bt_gpio_numbers_t *) &platform_gpio_pins[PLATFORM_GPIO_13].gpio_pin, \ .config = GPIO_OUTPUT_ENABLE | GPIO_PULL_UP, .default_state = GPIO_PIN_OUTPUT_HIGH, \ } -#define GPIO1_config \ +#define GPIO2_config \ { \ .gpio = (wiced_bt_gpio_numbers_t *) &platform_gpio_pins[PLATFORM_GPIO_3].gpio_pin, \ .config = GPIO_INPUT_ENABLE | GPIO_PULL_UP_DOWN_NONE, .default_state = GPIO_PIN_OUTPUT_LOW, \ } +#endif // CHIP_PACKAGE_WLCSP const wiced_platform_gpio_t platform_gpio_pins[] = { +#if CHIP_PACKAGE_WLCSP [PLATFORM_GPIO_0] = { WICED_P00, WICED_GPIO }, [PLATFORM_GPIO_1] = { WICED_P04, pwm_0_pwm_0_TRIGGER_IN }, [PLATFORM_GPIO_2] = { WICED_P06, uart_1_rxd_0_TRIGGER_IN }, [PLATFORM_GPIO_3] = { WICED_P07, WICED_GPIO }, [PLATFORM_GPIO_4] = { WICED_P10, uart_1_txd_0_TRIGGER_IN }, [PLATFORM_GPIO_5] = { WICED_P16, WICED_GPIO }, - [PLATFORM_GPIO_6] = { WICED_P17, WICED_GPIO }, - [PLATFORM_GPIO_7] = { WICED_P25, WICED_GPIO }, - [PLATFORM_GPIO_8] = { WICED_P26, WICED_GPIO }, - [PLATFORM_GPIO_9] = { WICED_P28, WICED_GPIO }, - [PLATFORM_GPIO_10] = { WICED_P29, WICED_GPIO }, - [PLATFORM_GPIO_11] = { WICED_P30, WICED_GPIO }, - [PLATFORM_GPIO_12] = { WICED_P33, WICED_GPIO }, - [PLATFORM_GPIO_13] = { WICED_P34, WICED_GPIO }, - [PLATFORM_GPIO_14] = { WICED_P38, WICED_GPIO }, + [PLATFORM_GPIO_6] = { WICED_P17, amplifiers_0_rx_pu_0_TRIGGER_IN }, + [PLATFORM_GPIO_7] = { WICED_P23, spi_1_mosi_0_TRIGGER_IN }, + [PLATFORM_GPIO_8] = { WICED_P24, spi_1_miso_0_TRIGGER_IN }, + [PLATFORM_GPIO_9] = { WICED_P25, WICED_GPIO }, + [PLATFORM_GPIO_10] = { WICED_P26, amplifiers_0_tx_pu_0_TRIGGER_IN }, + [PLATFORM_GPIO_11] = { WICED_P28, WICED_GPIO }, + [PLATFORM_GPIO_12] = { WICED_P29, WICED_GPIO }, + [PLATFORM_GPIO_13] = { WICED_P30, spi_1_cs_0_TRIGGER_IN }, + [PLATFORM_GPIO_14] = { WICED_P31, spi_1_clk_0_TRIGGER_IN }, + [PLATFORM_GPIO_15] = { WICED_P33, WICED_GPIO }, + [PLATFORM_GPIO_16] = { WICED_P34, WICED_GPIO }, + [PLATFORM_GPIO_17] = { WICED_P38, WICED_GPIO }, +#else // !CHIP_PACKAGE_WLCSP + [PLATFORM_GPIO_0] = { WICED_P00, WICED_GPIO }, + [PLATFORM_GPIO_1] = { WICED_P04, pwm_0_pwm_0_TRIGGER_IN }, + [PLATFORM_GPIO_2] = { WICED_P06, uart_1_rxd_0_TRIGGER_IN }, + [PLATFORM_GPIO_3] = { WICED_P07, WICED_GPIO }, + [PLATFORM_GPIO_4] = { WICED_P10, uart_1_txd_0_TRIGGER_IN }, + [PLATFORM_GPIO_5] = { WICED_P16, spi_1_clk_0_TRIGGER_IN }, + [PLATFORM_GPIO_6] = { WICED_P17, amplifiers_0_rx_pu_0_TRIGGER_IN }, + [PLATFORM_GPIO_7] = { WICED_P25, spi_1_cs_0_TRIGGER_IN }, + [PLATFORM_GPIO_8] = { WICED_P26, amplifiers_0_tx_pu_0_TRIGGER_IN }, + [PLATFORM_GPIO_9] = { WICED_P28, spi_1_mosi_0_TRIGGER_IN }, + [PLATFORM_GPIO_10] = { WICED_P29, spi_1_miso_0_TRIGGER_IN }, + [PLATFORM_GPIO_11] = { WICED_P33, WICED_GPIO }, + [PLATFORM_GPIO_12] = { WICED_P34, WICED_GPIO }, + [PLATFORM_GPIO_13] = { WICED_P38, WICED_GPIO }, +#endif // CHIP_PACKAGE_WLCSP }; const size_t platform_gpio_pin_count = (sizeof(platform_gpio_pins) / sizeof(wiced_platform_gpio_t)); const wiced_platform_led_config_t platform_led[] = { @@ -114,8 +152,12 @@ const wiced_platform_button_config_t platform_button[] = { }; const size_t button_count = (sizeof(platform_button) / sizeof(wiced_platform_button_config_t)); const wiced_platform_gpio_config_t platform_gpio[] = { - [WICED_PLATFORM_GPIO_1] = GPIO1_config, [WICED_PLATFORM_GPIO_2] = GPIO2_config, [WICED_PLATFORM_GPIO_7] = RX_PU_config, - [WICED_PLATFORM_GPIO_3] = GPIO3_config, [WICED_PLATFORM_GPIO_6] = TX_PU_config, [WICED_PLATFORM_GPIO_4] = GPIO4_config, - [WICED_PLATFORM_GPIO_5] = GPIO5_config, [WICED_PLATFORM_GPIO_8] = DEBUG_UART_TXD_config, +#if CHIP_PACKAGE_WLCSP + [WICED_PLATFORM_GPIO_2] = GPIO2_config, [WICED_PLATFORM_GPIO_3] = GPIO3_config, [WICED_PLATFORM_GPIO_4] = GPIO4_config, + [WICED_PLATFORM_GPIO_5] = GPIO5_config, [WICED_PLATFORM_GPIO_6] = GPIO6_config, [WICED_PLATFORM_GPIO_7] = DEBUG_UART_TXD_config, +#else // !CHIP_PACKAGE_WLCSP + [WICED_PLATFORM_GPIO_2] = GPIO2_config, + [WICED_PLATFORM_GPIO_7] = DEBUG_UART_TXD_config, +#endif // CHIP_PACKAGE_WLCSP }; const size_t gpio_count = (sizeof(platform_gpio) / sizeof(wiced_platform_gpio_config_t)); diff --git a/third_party/cyw30739_sdk/bsp_design_modus/cycfg_pins.h b/third_party/cyw30739_sdk/bsp_design_modus/cycfg_pins.h index de4b9f30d2d897..d8e3c8ab28fc58 100644 --- a/third_party/cyw30739_sdk/bsp_design_modus/cycfg_pins.h +++ b/third_party/cyw30739_sdk/bsp_design_modus/cycfg_pins.h @@ -4,14 +4,13 @@ * Description: * Pin configuration * This file was automatically generated and should not be modified. - * Tools Package 2.4.0.5880 - * 20739B2 CSP + * Tools Package 2.3.0.4276 + * 30739A0 CSP * personalities 1.0.0.31 - * udd 3.0.0.1454 + * udd 3.0.0.1636 * ******************************************************************************** - * Copyright 2021 Cypress Semiconductor Corporation (an Infineon company) or - * an affiliate of Cypress Semiconductor Corporation. + * Copyright 2022 Cypress Semiconductor Corporation * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -38,6 +37,7 @@ extern "C" { #endif +#define amplifiers_0_ENABLED 1U #define bluetooth_0_ENABLED 1U #define ioss_0_ENABLED 1U #define WICED_GET_PIN_FOR_LED(idx) (*(platform_led[(idx)].gpio)) @@ -47,20 +47,18 @@ extern "C" { #define BUTTON_USER WICED_P00 #define PUART_TXD_ENABLED 1U #define PUART_TXD WICED_P10 -#define GPIO2_ENABLED 1U -#define GPIO2 WICED_P16 +//#define GPIO3_ENABLED 1U +//#define GPIO3 WICED_P16 #define RX_PU_ENABLED 1U #define RX_PU WICED_P17 -#define GPIO3_ENABLED 1U -#define GPIO3 WICED_P25 +//#define GPIO4_ENABLED 1U +//#define GPIO4 WICED_P25 #define TX_PU_ENABLED 1U #define TX_PU WICED_P26 -#define GPIO4_ENABLED 1U -#define GPIO4 WICED_P28 -#define GPIO5_ENABLED 1U -#define GPIO5 WICED_P29 -#define ioss_0_pin_30_ENABLED 1U -#define ioss_0_pin_30 WICED_P30 +//#define GPIO5_ENABLED 1U +//#define GPIO5 WICED_P28 +//#define GPIO6_ENABLED 1U +//#define GPIO6 WICED_P29 #define DEBUG_UART_TXD_ENABLED 1U #define DEBUG_UART_TXD WICED_P33 #define LED1_ENABLED 1U @@ -71,9 +69,10 @@ extern "C" { #define PWM0 WICED_P04 #define PUART_RXD_ENABLED 1U #define PUART_RXD WICED_P06 -#define GPIO1_ENABLED 1U -#define GPIO1 WICED_P07 +#define GPIO2_ENABLED 1U +#define GPIO2 WICED_P07 #define pwm_0_ENABLED 1U +#define spi_1_ENABLED 1U #define uart_1_ENABLED 1U extern const wiced_platform_gpio_t platform_gpio_pins[]; diff --git a/third_party/cyw30739_sdk/bsp_design_modus/cycfg_routing.h b/third_party/cyw30739_sdk/bsp_design_modus/cycfg_routing.h index 47e1e82b52b8cc..b4e1a38b050feb 100644 --- a/third_party/cyw30739_sdk/bsp_design_modus/cycfg_routing.h +++ b/third_party/cyw30739_sdk/bsp_design_modus/cycfg_routing.h @@ -4,14 +4,13 @@ * Description: * Establishes all necessary connections between hardware elements. * This file was automatically generated and should not be modified. - * Tools Package 2.4.0.5880 - * 20739B2 CSP + * Tools Package 2.3.0.4276 + * 30739A0 CSP * personalities 1.0.0.31 - * udd 3.0.0.1454 + * udd 3.0.0.1636 * ******************************************************************************** - * Copyright 2021 Cypress Semiconductor Corporation (an Infineon company) or - * an affiliate of Cypress Semiconductor Corporation. + * Copyright 2022 Cypress Semiconductor Corporation * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -37,11 +36,31 @@ extern "C" { #include "cycfg_notices.h" static inline void init_cycfg_routing(void) {} #define init_cycfg_connectivity() init_cycfg_routing() +#if CHIP_PACKAGE_WLCSP #define ioss_0_pin_4_AUX UNKNOWN #define ioss_0_pin_6_AUX UNKNOWN #define ioss_0_pin_10_AUX UNKNOWN +#define ioss_0_pin_17_AUX UNKNOWN +#define ioss_0_pin_26_AUX UNKNOWN +#else // !CHIP_PACKAGE_WLCSP +#define ioss_0_pin_4_AUX UNKNOWN +#define ioss_0_pin_6_AUX UNKNOWN +#define ioss_0_pin_10_AUX UNKNOWN +#define ioss_0_pin_16_AUX UNKNOWN +#define ioss_0_pin_17_AUX UNKNOWN +#define ioss_0_pin_25_AUX UNKNOWN +#define ioss_0_pin_26_AUX UNKNOWN +#define ioss_0_pin_28_AUX UNKNOWN +#define ioss_0_pin_29_AUX UNKNOWN +#endif +#define amplifiers_0_rx_pu_0_TRIGGER_IN WICED_RX_PU +#define amplifiers_0_tx_pu_0_TRIGGER_IN WICED_TX_PU #define pwm_0_pwm_0_TRIGGER_IN WICED_PWM0 +#define spi_1_clk_0_TRIGGER_IN WICED_SPI_2_CLK +#define spi_1_cs_0_TRIGGER_IN WICED_SPI_2_CS +#define spi_1_miso_0_TRIGGER_IN WICED_SPI_2_MISO +#define spi_1_mosi_0_TRIGGER_IN WICED_SPI_2_MOSI #define uart_1_rxd_0_TRIGGER_IN WICED_UART_2_RXD #define uart_1_txd_0_TRIGGER_IN WICED_UART_2_TXD diff --git a/third_party/cyw30739_sdk/btp_reader.py b/third_party/cyw30739_sdk/btp_reader.py index 9dface1ff0b485..71fd7c28144ec7 100644 --- a/third_party/cyw30739_sdk/btp_reader.py +++ b/third_party/cyw30739_sdk/btp_reader.py @@ -1,4 +1,24 @@ #!/usr/bin/env python +# +# Copyright (c) 2022 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +"""BTP file reader + +This is a helper script to parse BTP file into json. + +""" import argparse import json @@ -26,17 +46,24 @@ def main(): else: items[key] = int(value, 0) - items["XS_LOCATION_ACTIVE"] = 0x0052E000 + ds_len = items["ConfigDS2Location"] - items["ConfigDSLocation"] + xs_location_end = 0x00600000 + + items["ConfigXS1Location"] = items["ConfigDS2Location"] + ds_len if option.enable_ota: - items["XS_LOCATION_UPGRADE"] = 0x005A3000 + items["ConfigXS1Length"] = 0x00076000 + items["ConfigXS2Location"] = ( + items["ConfigXS1Location"] + items["ConfigXS1Length"] + ) + items["ConfigXS2Length"] = xs_location_end - items["ConfigXS2Location"] else: - items["XS_LOCATION_UPGRADE"] = 0x00600000 + items["ConfigXS1Length"] = xs_location_end - items["ConfigXS1Location"] + items["ConfigXS2Length"] = 0 + items["ConfigXS2Location"] = xs_location_end - items["XIP_DS_OFFSET"] = items["XS_LOCATION_ACTIVE"] - \ + items["ConfigXS1DS1Offset"] = items["ConfigXS1Location"] - \ items["ConfigDSLocation"] - items["XIP_LEN"] = items["XS_LOCATION_UPGRADE"] - \ - items["XS_LOCATION_ACTIVE"] for key in items: if type(items[key]) is int: diff --git a/third_party/cyw30739_sdk/compress_cgs_data.py b/third_party/cyw30739_sdk/compress_cgs_data.py new file mode 100644 index 00000000000000..c159f61746f8f4 --- /dev/null +++ b/third_party/cyw30739_sdk/compress_cgs_data.py @@ -0,0 +1,239 @@ +#!/usr/bin/env python +# +# Copyright (c) 2022 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +"""CGS data entry compressor + +This script compresses "Data" entries into "Compressed data" entries +from the input CGS file to the output CGS file with the given LZSS tool. + +"Data" entries that are smaller than 512 bytes would be skipped. + +""" + +import argparse +import io +import pathlib +import re +import subprocess +import sys + +from collections import namedtuple + + +Item = namedtuple('Item', 'line type nested_data') +Entry = namedtuple('Entry', 'items name remark') +CommentedBytes = namedtuple('CommentedBytes', 'items data') + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("--output", required=True, type=pathlib.Path) + parser.add_argument("--input", required=True, type=pathlib.Path) + parser.add_argument("--lzss_tool", required=True, type=pathlib.Path) + + option = parser.parse_args() + + cgs = parse_cgs(option.input) + compress_cgs(option, cgs) + export_cgs(option.output, cgs) + + +def parse_cgs(file_name): + cgs = [] + + with open(file_name, mode="r") as file: + for line in file: + if len(line) == 0: + break + + striped_line = line.strip() + item_type = None + nested_data = None + + if striped_line.startswith('ENTRY'): + item_type = "entry" + nested_data = parse_entry(file, line) + elif striped_line.startswith('#') or striped_line.startswith('//'): + item_type = "comment" + elif striped_line.startswith('DEFINITION'): + item_type = "definition" + + cgs.append(Item(line, item_type, nested_data)) + + return cgs + + +def parse_entry(file: io.TextIOBase, line): + + # compile the regex for extracting name and remark of the entry. + data_re = re.compile(r""" + ^\s* # Allow leading spaces + ENTRY\s+"([^"]+)" # Parse the entry name + (?: # Optional non-capturing part begin + \s*=\s* # Allow leading and trailing spaces + "([^"]+)" # Parse the entry remark + )? # Optional non-capturing part end + \s*$ # Allow trailing spaces + """, re.VERBOSE) + + items = [] + name = None + remark = None + + while len(line) != 0: + striped_line = line.strip() + item_type = None + nested_data = None + + if striped_line.startswith('ENTRY'): + item_type = "entry" + match = data_re.match(striped_line) + if match: + name = match[1] + remark = match[2] + elif striped_line.startswith('COMMENTED_BYTES'): + item_type = "commented_bytes" + nested_data = parse_commented_bytes(file, line) + elif striped_line.startswith('{'): + item_type = "start" + elif striped_line.startswith('}'): + item_type = "end" + + items.append(Item(line, item_type, nested_data)) + if item_type == "end": + break + + line = file.readline() + + return Entry(items, name, remark) + + +def parse_commented_bytes(file: io.TextIOBase, line): + items = [] + data = bytearray() + + while len(line) != 0: + striped_line = line.strip() + name = None + + if striped_line.startswith('COMMENTED_BYTES'): + name = "commented_bytes" + elif striped_line.startswith(''): + name = "hex" + elif striped_line.startswith('{'): + name = "start" + elif striped_line.startswith('}'): + name = "end" + else: + name = "data" + data += bytearray.fromhex(striped_line) + + items.append(Item(line, name, None)) + if name == "end": + break + + line = file.readline() + + return CommentedBytes(items, data) + + +def compress_cgs(option, cgs): + for item in cgs: + if item.nested_data is None: + continue + entry = compress_entry(option, item.nested_data) + if entry is None: + continue + + cgs.insert(cgs.index(item), Item(item.line, item.type, entry)) + cgs.remove(item) + + +def compress_entry(option, entry): + if entry.name != 'Data': + return None + + for item in entry.items: + if item.nested_data is None: + continue + commented_bytes = compress_commented_bytes(option, item.nested_data) + if commented_bytes is None: + return None + + entry.items.insert(entry.items.index(item), Item(item.line, item.type, commented_bytes)) + entry.items.remove(item) + + return Entry(entry.items, 'Compressed data', entry.remark) + + +def compress_commented_bytes(option, commented_bytes): + if len(commented_bytes.data) < 512: + return None + return CommentedBytes(commented_bytes.items, compress_data(option, commented_bytes.data)) + + +def compress_data(option, data): + raw_file = str(option.input.with_suffix('.tmp')) + compressed_file = str(option.input.with_suffix('.tmp.lz')) + + with open(raw_file, mode="wb") as binary: + binary.write(data) + + subprocess.run([option.lzss_tool, "e", raw_file, + compressed_file, ], check=True) + + with open(compressed_file, mode="rb") as binary: + return binary.read() + + +def export_cgs(file_name, cgs): + with open(file_name, mode="w") as file: + for item in cgs: + if item.nested_data is None: + file.write(item.line) + else: + export_entry(file, item.nested_data) + + +def export_entry(file: io.TextIOBase, entry): + for item in entry.items: + if item.type == 'entry': + file.write('ENTRY "{}"'.format(entry.name)) + if entry.remark: + file.write(' = "{}"'.format(entry.remark)) + file.write('\n') + elif item.nested_data is None: + file.write(item.line) + else: + export_commented_bytes(file, item.nested_data, entry.name == 'Compressed data') + + +def export_commented_bytes(file: io.TextIOBase, commented_bytes, is_compressed_data): + for item in commented_bytes.items: + if is_compressed_data and item.type == 'data': + continue + + file.write(item.line) + + if is_compressed_data and item.type == 'hex': + indent = item.line.rstrip()[:-len('')] + + for i in range(0, len(commented_bytes.data), 16): + file.write(indent + commented_bytes.data[i:i + 16].hex(' ') + '\n') + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/third_party/cyw30739_sdk/cyw30739_executable.gni b/third_party/cyw30739_sdk/cyw30739_executable.gni index a99793e0198b7b..eed0f9341befa5 100644 --- a/third_party/cyw30739_sdk/cyw30739_executable.gni +++ b/third_party/cyw30739_sdk/cyw30739_executable.gni @@ -27,23 +27,29 @@ template("cyw30739_executable") { output_base_name = get_path_info(invoker.output_name, "name") ldscript_file = "${root_build_dir}/${output_base_name}.ld" flashable_target = "${target_name}.flashable" + pre_build_target = "${target_name}.pre_build" + post_build_target = "${target_name}.post_build" + ota_image_target = "${target_name}.ota_image" - cyw30739_sdk_pre_build("${target_name}.pre_build") { + cyw30739_sdk_pre_build(pre_build_target) { } - cyw30739_sdk_post_build("${target_name}.post_build") { - executable_target = ":${flashable_target}.executable" + cyw30739_sdk_post_build(post_build_target) { + executable_target = "${flashable_target}.executable" } - cyw30739_sdk_ota_image("${target_name}.ota_image") { - deps = [ ":${invoker.target_name}.post_build" ] + cyw30739_sdk_ota_image(ota_image_target) { + deps = [ ":${post_build_target}" ] } group(target_name) { - deps = [ - ":${flashable_target}", - ":${target_name}.ota_image", - ] + deps = [ ":${flashable_target}" ] + + if (chip_enable_ota_requestor) { + deps += [ ":${ota_image_target}" ] + } else { + deps += [ ":${post_build_target}" ] + } } # Copy flashing dependencies to the output directory so that the output @@ -76,7 +82,7 @@ template("cyw30739_executable") { forward_variables_from(invoker, "*") data_deps = [ ":${flashing_runtime_target}" ] - deps += [ ":${target_name}.pre_build" ] + deps += [ ":${pre_build_target}" ] inputs = [ ldscript_file ] diff --git a/third_party/cyw30739_sdk/cyw30739_sdk.gni b/third_party/cyw30739_sdk/cyw30739_sdk.gni index 2a4e06e11224d2..7bed70cf01ec28 100644 --- a/third_party/cyw30739_sdk/cyw30739_sdk.gni +++ b/third_party/cyw30739_sdk/cyw30739_sdk.gni @@ -22,6 +22,7 @@ declare_args() { # Location of the CYW30739 SDK. cyw30739_sdk_root = "${cyw30739_sdk_build_root}/repos" cyw30739_sdk_verbose = false + cyw30739_sdk_debug = 0 } assert(cyw30739_sdk_root != "", "cyw30739_sdk_root must be specified") @@ -54,7 +55,10 @@ if (chip_enable_ota_requestor) { } btp = exec_script("${cyw30739_sdk_build_root}/btp_reader.py", btp_reader_args, - "json") + "json", + [ cyw30739_sdk_btp_file ]) + +cyw30739_sdk_crt_entry = "spar_crt_setup" template("cyw30739_sdk_script") { action(target_name) { @@ -100,12 +104,6 @@ template("cyw30739_sdk") { assert(cyw30739_sdk_root != "", "cyw30739_sdk_root must be specified") - if (is_debug) { - enable_debug = 1 - } else { - enable_debug = 0 - } - config("${target_name}_config") { include_dirs = [] defines = [] @@ -138,7 +136,7 @@ template("cyw30739_sdk") { ldflags = [ "--specs=nano.specs", - "-Wl,--entry=spar_crt_setup", + "-Wl,--entry=${cyw30739_sdk_crt_entry}", "-Wl,--just-symbols=" + rebase_path(cyw30739_sdk_patch_sym_file, root_build_dir), "-nostartfiles", @@ -203,10 +201,10 @@ template("cyw30739_sdk") { "CHIP_HAVE_CONFIG_H=1", "CY_PLATFORM_SWDCK=WICED_P05", "CY_PLATFORM_SWDIO=WICED_P03", - "ENABLE_DEBUG=${enable_debug}", - "SPAR_CRT_SETUP=spar_crt_setup", - "XS_LOCATION_ACTIVE=" + btp.XS_LOCATION_ACTIVE, - "XS_LOCATION_UPGRADE=" + btp.XS_LOCATION_UPGRADE, + "ENABLE_DEBUG=${cyw30739_sdk_debug}", + "SPAR_CRT_SETUP=${cyw30739_sdk_crt_entry}", + "XS_LOCATION_ACTIVE=${btp.ConfigXS1Location}", + "XS_LOCATION_UPGRADE=${btp.ConfigXS2Location}", ] if (chip_enable_ota_requestor) { defines += [ "BLE_OTA_FW_UPGRADE=1" ] @@ -219,14 +217,29 @@ template("cyw30739_sdk") { } template("cyw30739_sdk_pre_build") { - cyw30739_sdk_script(target_name) { - script_file_name = "bt_pre_build.bash" + action(target_name) { + script_file = "${cyw30739_sdk_build_root}/scripts/wiced-gen-ld.pl" + + script = "${build_root}/gn_run_binary.py" + + inputs = [ + "${cyw30739_sdk_build_root}/btp_reader.py", + script_file, + ] - linker_defines = [ - "FLASH0_BEGIN_ADDR=" + btp.DLConfigSSLocation, + sources = [ cyw30739_sdk_btp_file ] + + outputs = [ invoker.ldscript_file ] + + args = [ + "perl", + "-I", + rebase_path(cyw30739_sdk_scripts_dir, root_build_dir), + rebase_path(script_file, root_build_dir), + "FLASH0_BEGIN_ADDR=${btp.DLConfigSSLocation}", "FLASH0_LENGTH=0x00100000", - "XIP_DS_OFFSET=" + btp.XIP_DS_OFFSET, - "XIP_LEN=" + btp.XIP_LEN, + "XIP_DS_OFFSET=${btp.ConfigXS1DS1Offset}", + "XIP_LEN=${btp.ConfigXS1Length}", "SRAM_BEGIN_ADDR=0x00200000", "SRAM_LENGTH=0x00070000", "AON_AREA_END=0x00284000", @@ -234,75 +247,260 @@ template("cyw30739_sdk_pre_build") { "ISTATIC_LEN=0x400", "NUM_PATCH_ENTRIES=256", "BTP=" + rebase_path(cyw30739_sdk_btp_file, root_build_dir), + rebase_path(cyw30739_sdk_patch_sym_file, root_build_dir), + "out=" + rebase_path(invoker.ldscript_file, root_build_dir), + ] + } +} + +template("cyw30739_sdk_post_build") { + output_base_path = "${root_out_dir}/${invoker.output_base_name}" + elf = "${output_base_path}.elf" + hex = "${output_base_path}_download.hex" + ds_hex = "${output_base_path}.ds.hex" + xs_hex = "${output_base_path}.xs.hex" + ss_cgs = "${output_base_path}.ss.cgs" + cgs = "${output_base_path}.cgs" + cx_cgs = "${output_base_path}.cx.cgs" + static_config = "${output_base_path}.static_config.txt" + hdf = "${root_out_dir}/configdef30739A0.hdf" + + patched_cgs_args = + exec_script("${build_root}/gn_run_binary.py", + [ + "perl", + rebase_path("${cyw30739_sdk_scripts_dir}/wiced-bdaddr.pl", + root_build_dir), + "30739A0", + rebase_path(cyw30739_sdk_btp_file, root_build_dir), + "-O", + "DLConfigBD_ADDRBase:default", + ], + "list lines", + [ "${cyw30739_sdk_scripts_dir}/wiced-bdaddr.pl" ]) + + cgs_args = [] + foreach(arg, patched_cgs_args) { + cgs_args += string_split(arg) + } + + action(target_name) { + script = "${cyw30739_sdk_build_root}/merge_hex.py" + + outputs = [ hex ] + + sources = [ + ds_hex, + xs_hex, ] args = [ - "--defs=" + string_join(" ", linker_defines), - "--ld=" + rebase_path(invoker.ldscript_file, root_build_dir), - "--patch=" + rebase_path(cyw30739_sdk_patch_sym_file, root_build_dir), + "--output=" + rebase_path(hex, root_build_dir), + "--ds_hex=" + rebase_path(ds_hex, root_build_dir), + "--xs_hex=" + rebase_path(xs_hex, root_build_dir), ] - sources = [ cyw30739_sdk_btp_file ] + deps = [ + ":${target_name}_gen_ds_hex", + ":${target_name}_gen_xs_hex", + ] - outputs = [ invoker.ldscript_file ] + data_deps = [ + ":${target_name}_btp", + ":${target_name}_disassemble", + ":${target_name}_hci_id", + ":${target_name}_minidriver", + ] } -} -template("cyw30739_sdk_post_build") { - copy("${target_name}_static_config") { - sources = [ "static_config.txt" ] - outputs = [ "${root_out_dir}/{{source_file_part}}" ] + action("${target_name}_gen_ds_hex") { + cgs_map = "${cgs}.map" + script = "${build_root}/gn_run_binary.py" + + outputs = [ + cgs_map, + ds_hex, + ] + + sources = [ + cx_cgs, + cyw30739_sdk_btp_file, + ss_cgs, + ] + + args = [ + rebase_path("${cyw30739_sdk_tools_dir}/CGS/cgs", root_build_dir), + "-D", + rebase_path(root_out_dir, root_build_dir), + "-M", + rebase_path(cgs_map, root_build_dir), + "-I", + rebase_path(ds_hex, root_build_dir), + "-B", + rebase_path(cyw30739_sdk_btp_file, root_build_dir), + "--ss-cgs", + rebase_path(ss_cgs, root_build_dir), + "--cgs-files", + rebase_path(cx_cgs, root_build_dir), + ] + args += cgs_args + + deps = [ + ":${invoker.target_name}_compress_cgs_data", + ":${invoker.target_name}_gen_ss_cgs", + ] } - cyw30739_sdk_script(target_name) { - script_file_name = "bt_post_build.bash" + action("${target_name}_gen_xs_hex") { + script = "${build_root}/gn_run_binary.py" + + outputs = [ xs_hex ] - cgs_list = [ - "${cyw30739_sdk_patch_dir}/patch.cgs", - "${cyw30739_sdk_platform_dir}/platform.cgs", - "${cyw30739_sdk_platform_dir}/platform_xip.cgs", + sources = [ elf ] + + args = [ + "arm-none-eabi-objcopy", + "--only-section=.app_xip_area", + "--output-target=ihex", + rebase_path(elf, root_build_dir), + rebase_path(xs_hex, root_build_dir), ] + deps = [ ":${invoker.executable_target}" ] + } + + action("${target_name}_compress_cgs_data") { + script = "${cyw30739_sdk_build_root}/compress_cgs_data.py" + + outputs = [ cx_cgs ] + + sources = [ cgs ] + args = [ - "--cross=arm-none-eabi-", - "--tools=" + rebase_path(cyw30739_sdk_tools_dir, root_build_dir), - "--builddir=" + rebase_path(root_out_dir, root_build_dir), - "--elfname=${invoker.output_base_name}.elf", - "--appname=${invoker.output_base_name}", - "--appver=0x00000000", - "--hdf=" + rebase_path( - "${cyw30739_sdk_baselib_dir}/internal/30739A0/configdef30739A0.hdf", - root_build_dir), - "--entry=spar_crt_setup.entry", - "--cgslist=" + string_join(" ", rebase_path(cgs_list, root_build_dir)), - "--cgsargs=-O DLConfigBD_ADDRBase:default", - "--btp=" + rebase_path(cyw30739_sdk_btp_file, root_build_dir), - "--id=" + rebase_path("${cyw30739_sdk_platform_dir}/IDFILE.txt", - root_build_dir), - "--overridebaudfile=" + - rebase_path("${cyw30739_sdk_platform_dir}/BAUDRATEFILE.txt", - root_build_dir), - "--chip=30739A0", - "--minidriver=" + - rebase_path("${cyw30739_sdk_platform_dir}/minidriver.hex", - root_build_dir), - "--clflags=-NOHCIRESET", - "--extras=static_config_XIP_", + "--output=" + rebase_path(cx_cgs, root_build_dir), + "--input=" + rebase_path(cgs, root_build_dir), + "--lzss_tool=" + + rebase_path(cyw30739_sdk_tools_dir + "/lzss/lzss", root_build_dir), + ] + + deps = [ ":${invoker.target_name}_gen_cgs" ] + } + + action("${target_name}_gen_ss_cgs") { + hdf_in = "${cyw30739_sdk_baselib_dir}/internal/30739A0/configdef30739A0.hdf" + + script_file = "${cyw30739_sdk_scripts_dir}/wiced-gen-ss-cgs.pl" + + script = "${build_root}/gn_run_binary.py" + + inputs = [ script_file ] + + sources = [ + hdf_in, + static_config, + ] + + outputs = [ + hdf, + ss_cgs, ] + args = [ + "perl", + "-I", + rebase_path(cyw30739_sdk_scripts_dir, root_build_dir), + rebase_path(script_file, root_build_dir), + "config=" + rebase_path(static_config, root_build_dir), + "hdf_in=" + rebase_path(hdf_in, root_build_dir), + "hdf_out=" + rebase_path(hdf, root_build_dir), + "cgs_out=" + rebase_path(ss_cgs, root_build_dir), + ] + args += cgs_args + + deps = [ ":${invoker.target_name}_static_config" ] + } + + action("${target_name}_gen_cgs") { + script_file = "${cyw30739_sdk_scripts_dir}/wiced-gen-cgs.pl" + + script = "${build_root}/gn_run_binary.py" + + inputs = [ script_file ] + sources = [ - "${root_out_dir}/static_config.txt", + "${cyw30739_sdk_patch_dir}/patch.cgs", + "${cyw30739_sdk_platform_dir}/platform.cgs", + "${cyw30739_sdk_platform_dir}/platform_xip.cgs", cyw30739_sdk_btp_file, + elf, + hdf, + invoker.ldscript_file, ] - sources += cgs_list - outputs = [ "${root_out_dir}/${invoker.output_base_name}_download.hex" ] + outputs = [ cgs ] + + args = [ + "perl", + "-I", + rebase_path(cyw30739_sdk_scripts_dir, root_build_dir), + rebase_path(script_file, root_build_dir), + "${cyw30739_sdk_crt_entry}.entry", + "out=" + rebase_path(cgs, root_build_dir), + ] + foreach(source, sources) { + args += [ rebase_path(source, root_build_dir) ] + } deps = [ - ":${target_name}_static_config", - invoker.executable_target, + ":${invoker.executable_target}", + ":${invoker.pre_build_target}", + ":${invoker.target_name}_gen_ss_cgs", ] } + + action("${target_name}_disassemble") { + asm = "${output_base_path}.asm" + + script = "${build_root}/gn_run_binary.py" + + outputs = [ asm ] + + sources = [ elf ] + + args = [ + "bash", + "--norc", + "--noprofile", + "-c", + "arm-none-eabi-objdump --disassemble " + + rebase_path(elf, root_build_dir) + " > " + + rebase_path(asm, root_build_dir), + ] + + deps = [ ":${invoker.executable_target}" ] + } + + copy("${target_name}_static_config") { + sources = [ "static_config.txt" ] + outputs = [ static_config ] + } + + copy("${target_name}_btp") { + sources = [ "${cyw30739_sdk_btp_file}" ] + outputs = [ "${output_base_path}.btp" ] + } + + copy("${target_name}_hci_id") { + sources = [ "${cyw30739_sdk_platform_dir}/IDFILE.txt" ] + outputs = [ "${output_base_path}_hci_id.txt" ] + } + + copy("${target_name}_minidriver") { + sources = [ "${cyw30739_sdk_platform_dir}/minidriver.hex" ] + outputs = [ "${root_out_dir}/{{source_file_part}}" ] + } + + write_file("${root_out_dir}/chipload_flags.txt", "-NOHCIRESET") } template("cyw30739_sdk_ota_image") { @@ -311,7 +509,7 @@ template("cyw30739_sdk_ota_image") { script = "${cyw30739_sdk_build_root}/gen_ota_image.py" - binary = "${root_out_dir}/${invoker.output_base_name}_download.ota.bin" + binary = "${root_out_dir}/${invoker.output_base_name}.bin" hex = "${root_out_dir}/${invoker.output_base_name}_download.hex" outputs = [ binary ] @@ -323,6 +521,12 @@ template("cyw30739_sdk_ota_image") { "--hex=" + rebase_path(hex, root_build_dir), "--lzss_tool=" + rebase_path(cyw30739_sdk_tools_dir + "/lzss/lzss", root_build_dir), + "--active_xs_len=${btp.ConfigXS1Length}", + "--upgrade_xs_len=${btp.ConfigXS2Length}", + "--project_config=" + + rebase_path("//include/CHIPProjectConfig.h", root_build_dir), + "--ota_image_tool=" + + rebase_path("${chip_root}/src/app/ota_image_tool.py", root_build_dir), ] } } diff --git a/third_party/cyw30739_sdk/flash.btp b/third_party/cyw30739_sdk/flash.btp index 71a08c458067ce..d6acdcb269a510 100644 --- a/third_party/cyw30739_sdk/flash.btp +++ b/third_party/cyw30739_sdk/flash.btp @@ -36,8 +36,8 @@ DevicePreset "30739 Flash" DLConfigSerialControlBaudRate = 115200 DLConfigEEPROMAccessSpeed = 100 DLConfigVSOffset = 0 - ConfigDSLocation = 0x508000 - ConfigDS2Location = 0x51b000 + ConfigDSLocation = 0x505000 + ConfigDS2Location = 0x519000 DLConfigSSLocation = 0x500000 DLConfigIncludeBTWSecurityKey = 0 DLConfigVSLocation = 0x501000 diff --git a/third_party/cyw30739_sdk/gen_ota_image.py b/third_party/cyw30739_sdk/gen_ota_image.py index e5d143ad6b6b04..2b86d9423b5bd8 100644 --- a/third_party/cyw30739_sdk/gen_ota_image.py +++ b/third_party/cyw30739_sdk/gen_ota_image.py @@ -1,4 +1,26 @@ #!/usr/bin/env python +# +# Copyright (c) 2022 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +"""OTA image generator + +This script generates OTA image file from the input hex file. + +The XS data would be compressed into OTA image with the given LZSS tool. + +""" import argparse import pathlib @@ -15,6 +37,12 @@ def main(): parser.add_argument("--binary", required=True, type=pathlib.Path) parser.add_argument("--hex", required=True, type=pathlib.Path) parser.add_argument("--lzss_tool", required=True, type=pathlib.Path) + parser.add_argument("--active_xs_len", required=True, + type=lambda x: int(x, 0)) + parser.add_argument("--upgrade_xs_len", required=True, + type=lambda x: int(x, 0)) + parser.add_argument("--project_config", required=True, type=pathlib.Path) + parser.add_argument("--ota_image_tool", required=True, type=pathlib.Path) option = parser.parse_args() @@ -52,11 +80,23 @@ def main(): print("XS: Length 0x{:08x}, CRC 0x{:08x}".format(len(xs_data), xs_crc)) print("CX: Length 0x{:08x}, CRC 0x{:08x}".format(len(cx_data), cx_crc)) - with open(str(option.binary), mode="wb") as binary: - binary.write(ds_header) - binary.write(ds_data) - binary.write(xs_header) - binary.write(cx_data) + print( + "Active XS: Used {:7,}, Free {:7,}".format( + len(xs_data), option.active_xs_len - len(xs_data) + ) + ) + upgrade_xs_len = len(xs_header) + len(cx_data) + print( + "Upgrade XS: Used {:7,}, Free {:7,}".format( + upgrade_xs_len, option.upgrade_xs_len - upgrade_xs_len + ) + ) + + if option.upgrade_xs_len < upgrade_xs_len: + print("Error: Insufficient space for the upgrade XS.") + return -1 + + gen_image(option, ds_header, ds_data, xs_header, cx_data) return 0 @@ -68,9 +108,8 @@ def compress_data(option, data, file_suffix): with open(raw_file, mode="wb") as binary: binary.write(data) - subprocess.run( - [option.lzss_tool, "e", raw_file, compressed_file, ] - ).check_returncode() + subprocess.run([option.lzss_tool, "e", raw_file, + compressed_file, ], check=True) with open(compressed_file, mode="rb") as binary: return binary.read() @@ -84,5 +123,87 @@ def pad_data(data, aligned_size): return data +def gen_image(option, ds_header, ds_data, xs_header, cx_data): + + configs = parse_config(option) + + write_binary(option, ds_header, ds_data, xs_header, cx_data) + run_ota_image_tool(option, configs) + + # Get the header size + header_size = 0 + for line in subprocess.run( + [option.ota_image_tool, "show", option.binary.with_suffix(".ota"), ], + check=True, + capture_output=True, + text=True, + ).stdout.splitlines(): + if line.startswith("Header Size:"): + header_size = int(line.split(":")[1]) + break + + if header_size % 4 == 0: + return + + # Insert zeroes to align sections to word + inserted_zero_count = 4 - header_size % 4 + write_binary(option, ds_header, ds_data, xs_header, + cx_data, inserted_zero_count) + run_ota_image_tool(option, configs) + + +def parse_config(option): + configs = {} + with open(option.project_config, "r") as config_file: + for line in config_file.readlines(): + + tokens = line.strip().split() + if not tokens or not tokens[0].endswith("define"): + continue + + key = tokens[1] + value = tokens[2] + + if value.startswith('"'): + configs[key] = value.strip('"') + else: + configs[key] = int(value, 0) + + return configs + + +def write_binary(option, ds_header, ds_data, xs_header, cx_data, inserted_zero_count=0): + with open(str(option.binary), mode="wb") as binary: + binary.write(bytes(inserted_zero_count)) + binary.write(ds_header) + binary.write(ds_data) + binary.write(xs_header) + binary.write(cx_data) + + +def run_ota_image_tool(option, configs): + subprocess.run( + [ + option.ota_image_tool, + "create", + "--vendor-id={}".format( + configs["CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID"]), + "--product-id={}".format( + configs["CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID"]), + "--version={}".format( + configs["CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION"] + ), + "--version-str={}".format( + configs["CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING"] + ), + "--digest-algorithm=sha256", + option.binary, + option.binary.with_suffix(".ota"), + ], + stderr=subprocess.STDOUT, + check=True, + ) + + if __name__ == "__main__": sys.exit(main()) diff --git a/third_party/cyw30739_sdk/include/ota_fw_upgrade.h b/third_party/cyw30739_sdk/include/ota_fw_upgrade.h index a6580f83adabfd..422da8230450a2 100644 --- a/third_party/cyw30739_sdk/include/ota_fw_upgrade.h +++ b/third_party/cyw30739_sdk/include/ota_fw_upgrade.h @@ -42,7 +42,7 @@ extern "C" { void wiced_firmware_upgrade_bootloader(void); bool wiced_firmware_upgrade_prepare(void); -uint32_t wiced_firmware_upgrade_process_block(uint32_t offset, uint8_t * data, uint32_t len); +uint32_t wiced_firmware_upgrade_process_block(uint32_t offset, const uint8_t * data, uint32_t len); bool wiced_firmware_upgrade_finalize(void); bool wiced_firmware_upgrade_apply(void); void wiced_firmware_upgrade_abort(void); diff --git a/third_party/cyw30739_sdk/merge_hex.py b/third_party/cyw30739_sdk/merge_hex.py new file mode 100644 index 00000000000000..8cf30eb2a526ad --- /dev/null +++ b/third_party/cyw30739_sdk/merge_hex.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python +# +# Copyright (c) 2022 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +"""Hex file merger + +This is a helper script for merging DS and XS into a single hex file. + +""" + +import argparse +import pathlib +import sys + +from intelhex import IntelHex + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("--output", required=True, type=pathlib.Path) + parser.add_argument("--ds_hex", required=True, type=pathlib.Path) + parser.add_argument("--xs_hex", required=True, type=pathlib.Path) + + option = parser.parse_args() + + ds_hex = IntelHex(str(option.ds_hex)) + xs_hex = IntelHex(str(option.xs_hex)) + ds_hex.merge(xs_hex) + ds_hex.write_hex_file(option.output) + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/third_party/cyw30739_sdk/repos/30739A0 b/third_party/cyw30739_sdk/repos/30739A0 index c50b1e77f78d7a..ab7601a74bdffc 160000 --- a/third_party/cyw30739_sdk/repos/30739A0 +++ b/third_party/cyw30739_sdk/repos/30739A0 @@ -1 +1 @@ -Subproject commit c50b1e77f78d7a52f3677bae8cdb58dd1880a9fe +Subproject commit ab7601a74bdffc7374353c1e19b22388bb3dcedd diff --git a/third_party/cyw30739_sdk/repos/CYW930739M2EVB-01 b/third_party/cyw30739_sdk/repos/CYW930739M2EVB-01 index 92ec8873d34162..3132c30e1ec305 160000 --- a/third_party/cyw30739_sdk/repos/CYW930739M2EVB-01 +++ b/third_party/cyw30739_sdk/repos/CYW930739M2EVB-01 @@ -1 +1 @@ -Subproject commit 92ec8873d34162c9ce5aab23bb7b0275d8e21806 +Subproject commit 3132c30e1ec305fc53969220e056f5e55532a9b3 diff --git a/third_party/cyw30739_sdk/scripts/wiced-gen-ld.pl b/third_party/cyw30739_sdk/scripts/wiced-gen-ld.pl new file mode 100644 index 00000000000000..28c3cff862cdd1 --- /dev/null +++ b/third_party/cyw30739_sdk/scripts/wiced-gen-ld.pl @@ -0,0 +1,549 @@ +#!/usr/bin/perl +# +# Copyright 2016-2021, Cypress Semiconductor Corporation (an Infineon company) or +# an affiliate of Cypress Semiconductor Corporation. All rights reserved. +# +# This software, including source code, documentation and related +# materials ("Software") is owned by Cypress Semiconductor Corporation +# or one of its affiliates ("Cypress") and is protected by and subject to +# worldwide patent protection (United States and foreign), +# United States copyright laws and international treaty provisions. +# Therefore, you may use this Software only as provided in the license +# agreement accompanying the software package from which you +# obtained this Software ("EULA"). +# If no EULA applies, Cypress hereby grants you a personal, non-exclusive, +# non-transferable license to copy, modify, and compile the Software +# source code solely for use in connection with Cypress's +# integrated circuit products. Any reproduction, modification, translation, +# compilation, or representation of this Software except as specified +# above is prohibited without the express written permission of Cypress. +# +# Disclaimer: THIS SOFTWARE IS PROVIDED AS-IS, WITH NO WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, NONINFRINGEMENT, IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. Cypress +# reserves the right to make changes to the Software without notice. Cypress +# does not assume any liability arising out of the application or use of the +# Software or any product or circuit described in the Software. Cypress does +# not authorize its products for use in any products where a malfunction or +# failure of the Cypress product may reasonably be expected to result in +# significant property damage, injury or death ("High Risk Product"). By +# including Cypress's product in a High Risk Product, the manufacturer +# of such system or application assumes all risk of such use and in doing +# so agrees to indemnify Cypress against all liability. +# +use READELF; +# read patch.elf and generate linker directive file + +# call with "perl wiced-gen-ld.pl patch.elf out=<*.ld>" +# the "patch.elf" is parsed to determine where to start the application memory +# the "out=<*.ld>" file is the output linker script +# arguments: +# SRAM_BEGIN_ADDR=0x123456, SRAM_LENGTH=0x1234: start and length of SRAM section for app code and data +# NUM_PATCH_ENTRIES=256: used to calculate reserved space in SRAM for patch entries +# ISTATIC_BEGIN=0x123456, ISTATIC_LEN=0x1234: start and length of static section data, typically encrypted keys +# PRAM_OBJ=abc.o;def.o;ghi.o: code/rodata for patch ram +# XIP_LEN=0x1234, XIP_OBJ=abc.o;def.o;ghi.o: execute in place area for on-chip-flash starting at 0x504000, contains code and rodata from listed object files +# UNUSED_BEGIN=0x123456, UNUSED_LEN=0x1234: start and length of an UNUSED section defined to avoid loading anything into +# DIRECT_LOAD=1: indicates RAM download rather than FLASH +# overlay=overlays.ld: a linker script snippet generated for an overlay section + +# ram is extended with PRAM (taking from patch space) or XIP (taking from on-chip-flash, code or rodata only) +# .dsp_pram_section is for dsp download (libraries/codec_ak4679_lib/akm4679_dsp_*.h) + +# look up for memory map and section input/output information +my $mem_lut = { + ".app_xip_area" => { + "sections" => [ + "KEEP(*(.xs_header))", +# argument XIP_OBJ will add section matches $(XIP_OBJ)(.text.* .gnu.linkonce.t.* .rodata .constdata* .rodata.* .gnu.linkonce.r.* ) +# special section for Position Independent trampoline functions. + "*(.pisec_*)", + "KEEP(*(.data_in_xip_area))", + "KEEP(*(.dsp_pram_section))",], + "mem_type" => "xip_section", + "pre" => ["xip_area_begin"], + "post" => ["spar_irom_end","xip_area_end"],}, + ".setup" => { + "sections" => [ + "*(.init_code)", + "*(.init_text)", + "*(.init_data)", + "*(.spar_setup)"], + "mem_type" => "ram", + "pre" => [], + "post" => [],}, + ".text" => { + "sections" => [ + "*(.app_init_code)", + "*(.emb_text)", + "*(.text)", + "*(.text_in_ram)", + "*(.text.*)", + "*(EmHeAacDec)", + "*(.gnu.linkonce.t.*)", + "*(.glue_7t)", + "*(.glue_7)", + "*(.vfp11_veneer)", + "*(.v4_bx)", + "*(.ARM.extab*)", + "*(.gnu.linkonce.armextab.*)", + "*(.ARM.exidx*)", + "*(.gnu.linkonce.armexidx.*)", + "*(.vpc_decoder_section)", + "PROVIDE_HIDDEN (__init_array_start = .);", + "KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))", + "KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))", + "PROVIDE_HIDDEN (__init_array_end = .);"], + "mem_type" => "ram", + "pre" => [], + "post" => [],}, + ".text.mbedtls" => { + "sections" => [ + "libmbedtls.*.o(.text.*)", + ], + "mem_type" => "ram", + "pre" => [], + "post" => [], + }, + ".rodata" => { + "sections" => [ + "*(const_drom_var)", + "*(.rodata)", + "*(.constdata*)", + "*(.rodata.*)", + "*(.gnu.linkonce.r.*)", + "*(.data.rom)"], + "mem_type" => "ram", + "pre" => [], + "post" => ["spar_irom_end"],}, + ".data" => { + "sections" => [ + "*(.data)", + "*(.data.*)", + "*(.gnu.linkonce.d.*)", + "*(.init_patch_table)"], + "mem_type" => "ram", + "pre" => ["spar_iram_begin", "spar_iram_data_begin"], + "post" => ["spar_iram_data_end"],}, + ".bss" => { + "sections" => [ + "*(.bss)", + "*(.bss.*)", + "*(.gnu.linkonce.b.*)", + "*(COMMON)"], + "mem_type" => "ram", + "pre" => ["spar_iram_bss_begin"], + "post" => ["spar_iram_bss_end", "spar_iram_end"],}, + ".unused" => { + "sections" => [ + "*(.code_in_retention_ram)", + "*(.data_in_retention_ram)"], + "mem_type" => "unused", + "pre" => ["unused_iram_begin"], + "post" => ["unused_iram_end"],}, + ".aon" => { + "sections" => [ + "*(always_on_ram_var)", + "*(.aon_code)", + "*(.data_in_retention_ram)", + "*(.code_in_retention_ram)"], + "mem_type" => "aon", + "pre" => ["aon_iram_begin"], + "post" => ["aon_iram_end"],}, + ".static_area" => { + "sections" => [ + "KEEP(*(.data_in_static_area))"], + "mem_type" => "static_section", + "pre" => ["static_area_begin"], + "post" => ["static_area_end"],}, + ".pram_rodata" => { + "sections" => [ + "KEEP(*(.dsp_pram_section))"], + "mem_type" => "pram", + "pre" => [], + "post" => ["pram_area_end"],}, + ".log_section" => { + "sections" => [ + "KEEP(*(log_data))"], + "mem_type" => "log_section", + "pre" => [], + "post" => [],}, +}; + +my $xip_extra_in = [ + "PROVIDE_HIDDEN (__init_array_start = .);", + "KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))", + "KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))", + "PROVIDE_HIDDEN (__init_array_end = .);", + "*(.app_init_code)", + "*(.emb_text)", + "*(.text)", + "*(EmHeAacDec)", + "*(.text.*)", + "*(.gnu.linkonce.t.*)", + "*(i.*)", + "*(.glue_7t)", + "*(.glue_7)", + "*(.vfp11_veneer)", + "*(.v4_bx)", + "*(.ARM.extab*)", + "*(.gnu.linkonce.armextab.*)", + "*(.ARM.exidx*)", + "*(.gnu.linkonce.armexidx.*)", + "*(const_drom_var)", + "*(.rodata)", + "*(.constdata*)", + "*(.rodata.*)", + "*(.gnu.linkonce.r.*)", + "*(.data.rom)", +]; + +main(); + +sub main +{ + my $param; +# print "args: @ARGS\n"; + + foreach my $arg (@ARGV) { + if($arg =~ /\.elf$/) { + $param->{'elf'} = $arg; + } + if($arg =~ /\.sym$/) { + $param->{'sym'} = $arg; + } + elsif($arg =~ /^ISTATIC_BEGIN=(\w+)/) { + $param->{'ISTATIC_BEGIN'} = hex($1); + } + elsif($arg =~ /^ISTATIC_LEN=(\w+)/) { + $param->{'ISTATIC_LEN'} = hex($1); + } + elsif($arg =~ /^UNUSED_BEGIN=(\w+)/) { + $param->{'UNUSED_BEGIN'} = hex($1); + } + elsif($arg =~ /^UNUSED_LEN=(\w+)/) { + $param->{'UNUSED_LEN'} = hex($1); + } + elsif($arg =~ /^AON_AREA_END=(\w+)/) { + $param->{'AON_AREA_END'} = hex($1); + } + elsif($arg =~ /^SRAM_BEGIN_ADDR=(\w+)/) { + $param->{'SRAM_BEGIN_ADDR'} = hex($1); + } + elsif($arg =~ /^SRAM_LENGTH=(\w+)/) { + $param->{'SRAM_LENGTH'} = hex($1); + } + elsif($arg =~ /^PATCH_RAM_OBJ=(.*)/) { + $param->{'PATCH_RAM_OBJ'} = $1; + my @patch_ram_obj = split ";", $1; + my @patch_ram_o; + foreach my $obj (@patch_ram_obj) { + $obj =~ s/^\./\*/; + $obj .= " (.text.* .gnu.linkonce.t.* .rodata .constdata* .rodata.* .gnu.linkonce.r.*)"; + push @patch_ram_o, $obj; + } + unshift @{$mem_lut->{'.pram_rodata'}->{sections}}, @patch_ram_o; + } + elsif($arg =~ /^NUM_PATCH_ENTRIES=(\d+)/) { + $param->{'NUM_PATCH_ENTRIES'} = $1; + } + elsif($arg =~ /^DIRECT_LOAD=(\d)/) { + $param->{'direct_load'} = $1; + } + elsif($arg =~ /^BTP=(.*)/) { + $param->{'btp'} = $1; + } + elsif($arg =~ /^FLASH0_BEGIN_ADDR=(\w+)/) { + $param->{'FLASH0_BEGIN_ADDR'} = hex($1); + } + elsif($arg =~ /^FLASH0_LENGTH=(\w+)/) { + $param->{'FLASH0_LENGTH'} = hex($1); + } + elsif($arg =~ /^XIP_DS_OFFSET=(\w+)/) { + $param->{'XIP_DS_OFFSET'} = hex($1); + $param->{'xip'} = 1; + push @{$mem_lut->{'.app_xip_area'}->{sections}}, @{$xip_extra_in}; + } + elsif($arg =~ /^XIP_LEN=(\w+)/) { + $param->{'XIP_LEN'} = hex($1); + } + elsif($arg =~ /^XIP_OBJ=(.*)/) { + my @xip_obj = split ";", $1; + my @xip_o; + foreach my $obj (@xip_obj) { + $obj =~ s/^\./\*/; + $obj .= " (.text.* .gnu.linkonce.t.* .rodata .constdata* .rodata.* .gnu.linkonce.r.*)"; + push @xip_o, $obj; + } + unshift @{$mem_lut->{'.app_xip_area'}->{sections}}, @xip_o; + } + elsif($arg =~ /^APP_DS2_LEN=(\w+)/) { + $param->{'APP_DS2_LEN'} = hex($1); + } + elsif($arg =~ /^DS_LOCATION=(\w+)/) { + $param->{'DS_LOCATION'} = hex($1); + } + elsif($arg =~ /^OTA_UPGRADE_STORE=(\w+)/) { + $param->{'OTA_UPGRADE_STORE'} = $1; + } + elsif($arg =~ /^overlay=(.*)$/) { + $param->{'overlay'} = $1; + warn "overlay is $1\n"; + } + elsif($arg =~ /^out=(.*)/) { + $param->{'outfile'} = $1; + } + } + + if(defined $param->{btp} && defined $param->{FLASH0_BEGIN_ADDR} && defined $param->{FLASH0_LENGTH}) { + open(my $BTP, "<", $param->{btp}) || die "Could not open *.btp file \"$param->{btp}\", $!"; + while(defined(my $line = <$BTP>)) { + if($line =~ /\s*(\w+)\s*\=\s*(0x[0-9a-fA-F]+)/) { + $param->{$1} = hex($2); + } + elsif($line =~ /\s*(\w+)\s*\=\s*([0-9]+)/) { + $param->{$1} = int($2); + } + } + close $BTP; + } + # override ConfigDSLocation if DS_LOCATION provided on command line + if(defined $param->{ConfigDSLocation} && defined $param->{DS_LOCATION}) { + $param->{ConfigDSLocation} = $param->{DS_LOCATION}; + } + + my $section_lut = {}; + if(defined $param->{elf}) { + my $sections = []; + my $stringtable = {}; + my $sym_str_tbl = {}; + my $symbol_entries = []; + parse_elf($param->{elf}, $sections, $stringtable, $sym_str_tbl, $symbol_entries, 1); + + #printf "got %d sections\n", scalar(@{$sections}); + foreach my $section (@{$sections}) { + if(!defined $section->{name}) { + #print "section name index $section->{sh_name}\n"; + #printf("%s\n", $stringtable->{$section->{sh_name}}) if defined $section->{sh_name}; + $section->{name} = $stringtable->{$section->{sh_name}}; + } + $section_lut->{$section->{name}} = $section; + #printf "section %s: start 0x%x len 0x%x\n", $section->{name}, $section->{sh_addr}, $section->{sh_size}; + } + } + elsif(defined $param->{sym}) { + # using sym file, so fake reading section headers from elf + open(my $SYM, "<", $param->{sym}) or die "Could not read $param->{sym}, $!\n"; + while(defined(my $line = <$SYM>)) { + if($line =~ /(\w+)\s*=\s*0x([0-9A-Fa-f]+)/) { + last if $1 eq "END_SECTION_INFO"; + $section_lut->{$1} = { sh_addr => hex($2) }; + } + } + close $SYM; + } + $param->{SRAM_START_ADDR} = $section_lut->{first_free_section_in_SRAM}->{sh_addr} + if defined $section_lut->{first_free_section_in_SRAM}->{sh_addr}; + $param->{SRAM_START_ADDR} = $section_lut->{FIRST_FREE_SECTION_IN_SRAM}->{sh_addr} + if defined $section_lut->{FIRST_FREE_SECTION_IN_SRAM}->{sh_addr}; + # for DIRECT_LOAD, add app code after init sections (including SlimBoot) + $param->{SRAM_START_ADDR} = $section_lut->{POST_INIT_SECTION_IN_SRAM}->{sh_addr} + if defined $section_lut->{POST_INIT_SECTION_IN_SRAM}->{sh_addr} && + defined $param->{direct_load} && $param->{direct_load}; + die "Ram start undefined\n" if !defined $param->{SRAM_START_ADDR}; + output_ld($section_lut, $param); +} + +sub output_ld +{ + my ($sections, $param) = @_; + my ($ram_start, $ram_begin, $ram_end, $ram_len, + $rom_start, $rom_begin, $rom_end, $rom_len, + $aon_begin, $aon_end, $aon_len, + $xip_start, $xip_len); + $rom_start = $sections->{CODE_AREA}->{sh_addr} if defined $sections->{CODE_AREA}; + die "Could not locate CODE_AREA in patch elf\n" if !defined $rom_start; + + $ram_start = $param->{SRAM_START_ADDR}; + my $num_patches = $param->{NUM_PATCH_ENTRIES}; + $num_patches = 256 if !defined $num_patches; + + $ram_begin = $param->{SRAM_BEGIN_ADDR}; + $ram_end = $ram_begin + $param->{SRAM_LENGTH}; + die "Could not locate data ram start in patch elf\n" if !defined $ram_begin; + die "Could not locate data ram end in patch elf\n" if !defined $ram_end; + if (defined $sections->{FIRST_FREE_SECTION_IN_PROM}) { + $rom_begin = $sections->{FIRST_FREE_SECTION_IN_PROM}->{sh_addr}; + $rom_end = $sections->{PATCH_CODE_END}->{sh_addr}; + die "Could not locate code ram start in patch elf\n" if !defined $rom_begin; + die "Could not locate code ram end in patch elf\n" if !defined $rom_end; + } + + if(defined $sections->{FIRST_FREE_SECTION_IN_AON}) { + $aon_begin = $sections->{FIRST_FREE_SECTION_IN_AON}->{sh_addr}; + $aon_end = $sections->{AON_AREA_END}->{sh_addr}; + $aon_end = $param->{AON_AREA_END} if !defined $aon_end; + die "Could not locate aon ram start in patch elf\n" if !defined $aon_begin; + die "Could not locate aon ram end in patch elf\n" if !defined $aon_end; + } + + my $patch_replace_area = $num_patches * 4; + $ram_len = $ram_end - $ram_start - $patch_replace_area; + $rom_len = $rom_end - $rom_begin if defined $rom_begin; + $aon_len = $aon_end - $aon_begin if defined $aon_begin; + +# $(eval LINK_LOC_FLAGS += ISTATIC_BEGIN=$(PLATFORM_APP_SPECIFIC_STATIC_DATA) ISTATIC_LEN=$(PLATFORM_APP_SPECIFIC_STATIC_LEN) IRAM_BEGIN=$(IRAM_BEGIN) IRAM_LEN=$(IRAM_LEN) IROM_BEGIN=$(IROM_BEGIN) IROM_LEN=$(IROM_LEN) IAON_BEGIN=$(IAON_BEGIN) IAON_LEN=$(IAON_LEN) ) +# $(QUIET)$(XCC) -E -x c -P $(addprefix -D,$(LINK_LOC_FLAGS)) -I $(dir $(ELF_OUT)) -o $@ $< + $param->{ISTATIC_BEGIN} = $param->{ISTATIC_BEGIN} if defined $param->{ISTATIC_BEGIN}; + $param->{ISTATIC_LEN} = $param->{ISTATIC_LEN} if defined $param->{ISTATIC_LEN}; + $param->{'direct_load'} = 0 if !defined $param->{direct_load}; + + open(my $OUT, ">", $param->{outfile}) || die "ERROR: Cannot open $param->{outfile}, $!"; + + print $OUT "OUTPUT_FORMAT (\"elf32-littlearm\", \"elf32-bigarm\", \"elf32-littlearm\")\n"; + print $OUT "SEARCH_DIR(.)\n"; +# print $OUT "/* @ARGV */\n"; +# print $OUT "/*\n"; +# foreach my$key (sort(keys(%{$param}))) { +# print $OUT "$key => $param->{$key}\n"; +# } +# print $OUT "*/\n"; + if(defined $rom_start) { + print $OUT sprintf "/* pram_patch_begin=0x%06X pram_patch_end=0x%06X pram_end=0x%06X */\n", $rom_start, $rom_begin, $rom_end; + } + print $OUT sprintf "/* ram_patch_begin=0x%06X ram_patch_end=0x%06X ram_end=0x%06X */\n", $sections->{SRAM_AREA}->{sh_addr}, $ram_start, $ram_end; + if(defined $aon_len) { + print $OUT sprintf "/* aon_patch_begin=0x%06X aon_patch_end=0x%06X aon_end=0x%06X */\n", $sections->{AON_AREA}->{sh_addr}, $aon_begin, $aon_end; + } + if(defined $aon_len) { + print $OUT sprintf "/* app_ram_begin=0x%06X app_ram_end=0x%06X */\n", $ram_start, $ram_start+$ram_len; + } + if(defined $param->{FLASH0_BEGIN_ADDR} && defined $param->{FLASH0_LENGTH}) { + print $OUT sprintf "/* FLASH0_BEGIN_ADDR=0x%06X FLASH0_LENGTH=0x%06X */\n", $param->{FLASH0_BEGIN_ADDR}, $param->{FLASH0_LENGTH}; + } + if(defined $param->{DLConfigSSLocation}) { + print $OUT sprintf "/* FLASH0_SS=0x%06X */\n", $param->{DLConfigSSLocation}; + } + if(defined $param->{DLConfigVSLocation}) { + print $OUT sprintf "/* FLASH0_VS=0x%06X */\n", $param->{DLConfigVSLocation}; + } + if(defined $param->{ConfigDSLocation}) { + print $OUT sprintf "/* FLASH0_DS=0x%06X */\n", $param->{ConfigDSLocation}; + } + if(defined $param->{ConfigDS2Location}) { + if(defined $param->{APP_DS2_LEN}) { + $param->{ConfigDS2Location} = $param->{FLASH0_BEGIN_ADDR} + $param->{FLASH0_LENGTH} - $param->{APP_DS2_LEN}; + } + print $OUT sprintf "/* FLASH0_DS2=0x%06X */\n", $param->{ConfigDS2Location}; + } + if(defined $param->{ConfigDSLocation}) { + my $store = $param->{ConfigDS2Location} - $param->{ConfigDSLocation}; + $param->{'OTA_UPGRADE_STORE'} = 'off_chip_sflash' if !defined $param->{OTA_UPGRADE_STORE}; + $store /=2 if $param->{OTA_UPGRADE_STORE} eq 'on_chip_flash'; + print $OUT sprintf "/* UPGRADE_STORAGE_LENGTH=0x%06X (%s) */\n", $store, $param->{OTA_UPGRADE_STORE}; + } + + print $OUT "MEMORY\n"; + print $OUT "{\n"; + print $OUT sprintf "\tram (rwx) : ORIGIN = 0x%X, LENGTH = 0x%X\n", $ram_start, $ram_len; + if(defined $aon_len) { + print $OUT sprintf "\taon (rwx) : ORIGIN = 0x%X, LENGTH = 0x%X\n", $aon_begin, $aon_len; + } + if(defined $param->{UNUSED_LEN}) { + print $OUT sprintf "\tunused (rwx) : ORIGIN = 0x%X, LENGTH = %d\n", $param->{UNUSED_BEGIN}, $param->{UNUSED_LEN}; + } + if(defined $param->{ISTATIC_BEGIN}) { + print $OUT sprintf "\tstatic_section (r) : ORIGIN = 0x%X, LENGTH = 0x%X\n", $param->{ISTATIC_BEGIN}, $param->{ISTATIC_LEN}; + } + if(defined $param->{xip}) { + $xip_start = $param->{ConfigDSLocation} + $param->{XIP_DS_OFFSET}; + $xip_len = $param->{XIP_LEN}; + $xip_len = $param->{FLASH0_LENGTH} - ($xip_start - $param->{ConfigDSLocation}) if !defined $xip_len; + print $OUT sprintf "\txip_section (rx) : ORIGIN = 0x%X, LENGTH = 0x%X\n", $xip_start, $xip_len; + } + if(defined $param->{PATCH_RAM_OBJ}) { + print $OUT sprintf "\tpram (rwx) : ORIGIN = 0x%X, LENGTH = 0x%X\n", $rom_begin, $rom_end - $rom_begin; + } + print $OUT sprintf "\tlog_section (r) : ORIGIN = 0x81000004, LENGTH = 0x100000\n"; + print $OUT "}\n"; + + print $OUT "EXTERN(spar_irom_begin spar_irom_end spar_irom_length);\n"; + print $OUT "EXTERN(spar_iram_begin spar_iram_end spar_iram_length);\n"; + print $OUT "EXTERN(spar_iram_data_begin spar_iram_data_end spar_iram_data_length);\n"; + print $OUT "EXTERN(spar_iram_bss_begin spar_iram_bss_end spar_iram_bss_length);\n"; + print $OUT "EXTERN(spar_irom_data_begin);\n"; + print $OUT "EXTERN(aon_iram_end);\n" if defined $aon_len; + print $OUT "EXTERN(xip_area_begin);\n" if defined $xip_start; + print $OUT "EXTERN(xip_area_end);\n" if defined $xip_len; + + print $OUT "PROVIDE(spar_irom_length = spar_irom_end - spar_irom_begin);\n"; + print $OUT "PROVIDE(spar_iram_length = spar_iram_end - spar_iram_begin);\n"; + print $OUT "PROVIDE(spar_iram_data_length = spar_iram_data_end - spar_iram_data_begin);\n"; + print $OUT "PROVIDE(spar_iram_bss_length = spar_iram_bss_end - spar_iram_bss_begin);\n"; + + print $OUT "SECTIONS\n"; + print $OUT "{\n"; + printf $OUT sprintf "\tspar_irom_begin = 0x%X;\n", $ram_start; + +# print "\t#include \"spar_ram_overlays.ld\"\n"; + if(defined $param->{overlay}) { + open(my $OVER, "<", $param->{overlay}) || die "Could not open overlay *.ld file \"$param->{overlay}\", $!"; + while(defined(my $line = <$OVER>)) { + print $OUT $line; + } + close $OVER; + } + + output_section('.text.mbedtls', $mem_lut, $OUT); + + # if objects are assigned to XIP, match their .text and .rodata + output_section('.app_xip_area', $mem_lut, $OUT) if defined $param->{xip}; + + # When direct loading, don't overlap init code with dynamic allocation. + if($param->{direct_load}) + { + output_section('.setup', $mem_lut, $OUT); + } + output_section('.pram_rodata', $mem_lut, $OUT) if defined $param->{PATCH_RAM_OBJ}; + output_section('.text', $mem_lut, $OUT); + output_section('.rodata', $mem_lut, $OUT); + output_section('.data', $mem_lut, $OUT); + + # Nothing to load because it is loaded from EEPROM/SF at boot. + print $OUT "\tspar_irom_data_begin = spar_iram_data_begin;\n"; + output_section('.bss', $mem_lut, $OUT); + + if(!$param->{direct_load}) { + # Place the setup area after bss so that when dynamic allocation occurs + # after spar setup, it will reclaim the RAM taken up by the setup function. + output_section('.setup', $mem_lut, $OUT); + } + output_section('.aon', $mem_lut, $OUT) if defined $aon_len; + output_section('.static_area', $mem_lut, $OUT) if defined $param->{ISTATIC_BEGIN}; + output_section('.log_section', $mem_lut, $OUT); + print $OUT "}\n"; +} + +sub output_section +{ + my ($name, $lut, $fh, $pre, $post) = @_; + my $info = $lut->{$name}; + die "Could not find ld table entry for $name\n" if !defined $info; + + my $align = "ALIGN (4)"; + $align = "" if $name eq '.text'; + + print $fh "\t$name : $align\n\t{\n"; + print $fh "\t\tCREATE_OBJECT_SYMBOLS\n"; + foreach my $sym (@{$info->{pre}}) { + print $fh "\t\t$sym = .;\n"; + } + foreach my $sect (@{$info->{sections}}) { + print $fh "\t\t$sect\n"; + } + foreach my $sym (@{$info->{post}}) { + print $fh "\t\t$sym = .;\n"; + } + print $fh "\t} >$info->{mem_type}\n"; +# print "\n"; +} diff --git a/third_party/cyw30739_sdk/src/ota_fw_upgrade.c b/third_party/cyw30739_sdk/src/ota_fw_upgrade.c index 3ed38600459895..a741a1ac42dc40 100644 --- a/third_party/cyw30739_sdk/src/ota_fw_upgrade.c +++ b/third_party/cyw30739_sdk/src/ota_fw_upgrade.c @@ -222,8 +222,7 @@ typedef struct upgrade_xs extern const CONFIG_INFO_t g_config_Info; -static uint32_t upgrade_location_write(uint32_t offset, uint8_t * data, uint32_t len); -static bool upgrade_location_erase(uint32_t offset, uint8_t * data); +static uint32_t upgrade_location_write(uint32_t offset, const uint8_t * data, uint32_t len); static bool lzss_decompress(const void * src, size_t n, bool (*data_writer)(uint32_t, int)) __attribute__((section(".text_in_ram"))); static bool xs_data_writer(uint32_t data_offset, int c) __attribute__((section(".text_in_ram"))); @@ -274,21 +273,36 @@ __attribute__((section(".init_code"))) void wiced_firmware_upgrade_bootloader(vo bool wiced_firmware_upgrade_prepare(void) { - const uint32_t ds1_location = g_config_Info.layout.failsafe_ds_base; - const uint32_t ds1_length = g_config_Info.layout.upgradable_ds_base - g_config_Info.layout.failsafe_ds_base; - const uint32_t ds2_location = g_config_Info.layout.upgradable_ds_base; - const uint32_t ds2_length = XS_LOCATION_ACTIVE - g_config_Info.layout.upgradable_ds_base; - - printf("DS1: 0x%08lx, len: 0x%08lx\n", ds1_location, ds1_length); - printf("DS2: 0x%08lx, len: 0x%08lx\n", ds2_location, ds2_length); - printf("Active DS: 0x%08x\n", g_config_Info.active_ds_base); - printf("Active XS: 0x%08x\n", XS_LOCATION_ACTIVE); - printf("Upgrade XS: 0x%08x\n", XS_LOCATION_UPGRADE); - - return upgrade_ds_location() != 0; + const uint32_t ds1_length = g_config_Info.layout.upgradable_ds_base - g_config_Info.layout.failsafe_ds_base; + const uint32_t ds2_length = XS_LOCATION_ACTIVE - g_config_Info.layout.upgradable_ds_base; + + printf("Active DS: 0x%08x\n", g_config_Info.active_ds_base); + printf("Active XS: 0x%08x\n", XS_LOCATION_ACTIVE); + + if (upgrade_ds_location() == 0 || ds1_length != ds2_length) + { + return false; + } + + printf("Erasing Upgrade DS: 0x%08lx, len: 0x%08lx\n", upgrade_ds_location(), ds1_length); + if (WICED_SUCCESS != wiced_hal_eflash_erase(ef_offset(upgrade_ds_location()), ds1_length)) + { + printf("ERROR erase\n"); + return false; + } + + const uint32_t upgrade_xs_length = FLASH_SIZE - ef_offset(XS_LOCATION_UPGRADE); + printf("Erasing Upgrade XS: 0x%08x, len: 0x%08lx\n", XS_LOCATION_UPGRADE, upgrade_xs_length); + if (WICED_SUCCESS != wiced_hal_eflash_erase(ef_offset(XS_LOCATION_UPGRADE), upgrade_xs_length)) + { + printf("ERROR erase\n"); + return false; + } + + return true; } -uint32_t wiced_firmware_upgrade_process_block(uint32_t offset, uint8_t * data, uint32_t len) +uint32_t wiced_firmware_upgrade_process_block(uint32_t offset, const uint8_t * data, uint32_t len) { const ds_header_t * ds_header = (const ds_header_t *) upgrade_ds_location(); @@ -337,44 +351,8 @@ uint32_t wiced_firmware_upgrade_process_block(uint32_t offset, uint8_t * data, u return byte_written; } -bool upgrade_location_erase(uint32_t offset, uint8_t * data) +uint32_t upgrade_location_write(uint32_t offset, const uint8_t * data, uint32_t len) { - uint32_t erase_length; - if (offset == upgrade_ds_location()) - { - const ds_header_t * ds_header = (const ds_header_t *) data; - erase_length = sizeof(*ds_header) + ds_header->length; - } - else if (offset == XS_LOCATION_UPGRADE) - { - const upgrade_xs_t * upgrade_xs = (const upgrade_xs_t *) data; - erase_length = sizeof(*upgrade_xs) + upgrade_xs->compressed_data_length; - } - else - { - return true; - } - - if (erase_length != 0) - { - printf("Erasing 0x%08lx, len: %lu\n", offset, erase_length); - if (WICED_SUCCESS != wiced_hal_eflash_erase(ef_offset(offset), erase_length)) - { - printf("ERROR erase\n"); - return false; - } - } - - return true; -} - -uint32_t upgrade_location_write(uint32_t offset, uint8_t * data, uint32_t len) -{ - if (!upgrade_location_erase(offset, data)) - { - return 0; - } - // reserve first 4 bytes of download to commit when complete, in case of unexpected power loss // boot rom checks this signature to validate DS uint32_t offset_adjustment; @@ -392,7 +370,7 @@ uint32_t upgrade_location_write(uint32_t offset, uint8_t * data, uint32_t len) printf("write: offset: 0x%08lx len: %lu\n", offset, len); /* write length should in words */ - if (wiced_hal_eflash_write(ef_offset(offset), data, (len + 3) & 0xfffffffc) == WICED_SUCCESS) + if (wiced_hal_eflash_write(ef_offset(offset), (uint8_t *) data, (len + 3) & 0xfffffffc) == WICED_SUCCESS) { return len + offset_adjustment; } @@ -564,7 +542,7 @@ uint32_t calc_crc32(const uint8_t * buf, uint32_t len) uint32_t ef_offset(uint32_t offset) { - return offset - 0x00500000u; + return offset - FLASH_BASE_ADDRESS; } uint32_t upgrade_ds_location(void) diff --git a/third_party/openthread/ot-ifx b/third_party/openthread/ot-ifx index fd4355aa7e61ab..e80949a96db29c 160000 --- a/third_party/openthread/ot-ifx +++ b/third_party/openthread/ot-ifx @@ -1 +1 @@ -Subproject commit fd4355aa7e61ab750036a604262ffd71cd3ce36d +Subproject commit e80949a96db29c6229cb78de650d120257284db7 diff --git a/third_party/openthread/platforms/ifx/BUILD.gn b/third_party/openthread/platforms/ifx/BUILD.gn index ce9f1e1b89fab2..fefabcd3562fef 100644 --- a/third_party/openthread/platforms/ifx/BUILD.gn +++ b/third_party/openthread/platforms/ifx/BUILD.gn @@ -20,7 +20,10 @@ openthread_ifx_root = "${chip_root}/third_party/openthread/ot-ifx" openthread_ifx_mcu = "cyw30739" config("openthread_ifx_config") { - include_dirs = [ "${openthread_ifx_root}/src/${openthread_ifx_mcu}" ] + include_dirs = [ + "${openthread_ifx_root}/src/${openthread_ifx_mcu}", + "${openthread_ifx_root}/src/${openthread_ifx_mcu}/mbedtls/include", + ] } source_set("openthread_core_config_ifx") { @@ -38,6 +41,7 @@ source_set("libopenthread-ifx") { "${openthread_ifx_root}/src/${openthread_ifx_mcu}/logging.c", "${openthread_ifx_root}/src/${openthread_ifx_mcu}/misc.c", "${openthread_ifx_root}/src/${openthread_ifx_mcu}/radio.c", + "${openthread_ifx_root}/src/${openthread_ifx_mcu}/radio_wrapper.cpp", "${openthread_ifx_root}/src/${openthread_ifx_mcu}/settings.c", "${openthread_ifx_root}/src/${openthread_ifx_mcu}/system.c", ]