From 69d14af28e8e8821a8e21484989b29c0716f282f Mon Sep 17 00:00:00 2001 From: Praveen Chandran Date: Mon, 15 Aug 2022 19:27:06 -0700 Subject: [PATCH] [Infineon] Support Factory reset for all-clusters example apps (#21877) --- .../all-clusters-app/p6/include/AppConfig.h | 5 +- .../all-clusters-app/p6/include/AppTask.h | 14 +++ .../p6/include/ButtonHandler.h | 1 + examples/all-clusters-app/p6/src/AppTask.cpp | 113 +++++++++++++++++- .../all-clusters-app/p6/src/ButtonHandler.cpp | 52 ++++++-- .../p6/include/AppConfig.h | 5 +- .../p6/include/AppTask.h | 14 +++ .../p6/include/ButtonHandler.h | 1 + .../p6/src/AppTask.cpp | 113 +++++++++++++++++- .../p6/src/ButtonHandler.cpp | 52 ++++++-- examples/lighting-app/p6/include/AppConfig.h | 2 +- examples/lighting-app/p6/include/AppTask.h | 7 +- examples/lighting-app/p6/src/AppTask.cpp | 59 +++------ .../lighting-app/p6/src/ButtonHandler.cpp | 7 +- examples/lock-app/p6/include/AppConfig.h | 2 +- examples/lock-app/p6/include/AppTask.h | 7 +- examples/lock-app/p6/src/AppTask.cpp | 85 +++++++------ examples/lock-app/p6/src/ButtonHandler.cpp | 6 +- 18 files changed, 412 insertions(+), 133 deletions(-) diff --git a/examples/all-clusters-app/p6/include/AppConfig.h b/examples/all-clusters-app/p6/include/AppConfig.h index 8e9ebe286ef421..bffd31f0d8a23b 100644 --- a/examples/all-clusters-app/p6/include/AppConfig.h +++ b/examples/all-clusters-app/p6/include/AppConfig.h @@ -28,8 +28,11 @@ #define APP_TASK_NAME "APP" #define APP_LIGHT_BUTTON_IDX 0 +#define APP_FUNCTION_BUTTON_IDX 1 + #define APP_LIGHT_BUTTON CYBSP_USER_BTN1 -#define APP_BUTTON_DEBOUNCE_PERIOD_MS 50 +#define APP_FUNCTION_BUTTON CYBSP_USER_BTN2 +#define APP_BUTTON_DEBOUNCE_PERIOD_MS 200 #define APP_BUTTON_PRESSED 0 #define APP_BUTTON_RELEASED 1 diff --git a/examples/all-clusters-app/p6/include/AppTask.h b/examples/all-clusters-app/p6/include/AppTask.h index 499de504d53ee6..9fade8c82356bf 100644 --- a/examples/all-clusters-app/p6/include/AppTask.h +++ b/examples/all-clusters-app/p6/include/AppTask.h @@ -54,8 +54,22 @@ class AppTask CHIP_ERROR Init(); static AppTask sAppTask; + void CancelTimer(void); void DispatchEvent(AppEvent * event); + static void FunctionTimerEventHandler(AppEvent * event); + static void FunctionHandler(AppEvent * event); + static void TimerEventHandler(TimerHandle_t timer); static void OnOffUpdateClusterState(intptr_t context); + void StartTimer(uint32_t aTimeoutMs); + + enum class Function + { + kNoneSelected = 0, + kFactoryReset = 1, + kInvalid + }; + Function mFunction = Function::kNoneSelected; + bool mFunctionTimerActive = false; }; inline AppTask & GetAppTask(void) diff --git a/examples/all-clusters-app/p6/include/ButtonHandler.h b/examples/all-clusters-app/p6/include/ButtonHandler.h index a4128c68f86f0e..ac4d795d64280e 100644 --- a/examples/all-clusters-app/p6/include/ButtonHandler.h +++ b/examples/all-clusters-app/p6/include/ButtonHandler.h @@ -36,5 +36,6 @@ class ButtonHandler private: static void GpioInit(void); static void light_button_callback(void * handler_arg, cyhal_gpio_event_t event); + static void func_button_callback(void * handler_arg, cyhal_gpio_event_t event); static void TimerCallback(TimerHandle_t xTimer); }; diff --git a/examples/all-clusters-app/p6/src/AppTask.cpp b/examples/all-clusters-app/p6/src/AppTask.cpp index 584b4cbed491d7..615660976db3ef 100644 --- a/examples/all-clusters-app/p6/src/AppTask.cpp +++ b/examples/all-clusters-app/p6/src/AppTask.cpp @@ -72,12 +72,14 @@ using namespace ::chip::System; #define APP_EVENT_QUEUE_SIZE 10 #define APP_TASK_STACK_SIZE (4096) #define APP_WAIT_LOOP 1000 +#define FACTORY_RESET_CANCEL_WINDOW_TIMEOUT 5000 LEDWidget sStatusLED; LEDWidget sLightLED; LEDWidget sClusterLED; namespace { +TimerHandle_t sFunctionTimer; // FreeRTOS app sw timer. TaskHandle_t sAppTaskHandle; QueueHandle_t sAppEventQueue; @@ -184,6 +186,18 @@ CHIP_ERROR AppTask::Init() // Initialise WSTK buttons PB0 and PB1 (including debounce). ButtonHandler::Init(); + // Create FreeRTOS sw timer for Function Selection. + sFunctionTimer = xTimerCreate("FnTmr", // Just a text name, not used by the RTOS kernel + 1, // == default timer period (mS) + false, // no timer reload (==one-shot) + (void *) this, // init timer id = app task obj context + TimerEventHandler // timer callback handler + ); + if (sFunctionTimer == NULL) + { + P6_LOG("funct timer create failed"); + appError(APP_ERROR_CREATE_TIMER_FAILED); + } NetWorkCommissioningInstInit(); P6_LOG("Current Software Version: %s", CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING); @@ -234,7 +248,7 @@ void AppTask::LightActionEventHandler(AppEvent * event) void AppTask::ButtonEventHandler(uint8_t btnIdx, uint8_t btnAction) { - if (btnIdx != APP_LIGHT_BUTTON_IDX) + if (btnIdx != APP_LIGHT_BUTTON_IDX && btnIdx != APP_FUNCTION_BUTTON_IDX) { return; } @@ -244,11 +258,106 @@ void AppTask::ButtonEventHandler(uint8_t btnIdx, uint8_t btnAction) button_event.ButtonEvent.ButtonIdx = btnIdx; button_event.ButtonEvent.Action = btnAction; - if ((btnIdx == APP_LIGHT_BUTTON_IDX) && (btnAction == APP_BUTTON_RELEASED)) + if (btnIdx == APP_LIGHT_BUTTON_IDX) { button_event.Handler = LightActionEventHandler; sAppTask.PostEvent(&button_event); } + else if (btnIdx == APP_FUNCTION_BUTTON_IDX) + { + button_event.Handler = FunctionHandler; + sAppTask.PostEvent(&button_event); + } +} + +void AppTask::TimerEventHandler(TimerHandle_t timer) +{ + AppEvent event; + event.Type = AppEvent::kEventType_Timer; + event.TimerEvent.Context = (void *) timer; + event.Handler = FunctionTimerEventHandler; + sAppTask.PostEvent(&event); +} + +void AppTask::FunctionTimerEventHandler(AppEvent * event) +{ + if (event->Type != AppEvent::kEventType_Timer) + { + return; + } + + if (sAppTask.mFunctionTimerActive && sAppTask.mFunction == Function::kFactoryReset) + { + // Actually trigger Factory Reset + sAppTask.mFunction = Function::kNoneSelected; + chip::Server::GetInstance().ScheduleFactoryReset(); + } +} + +void AppTask::FunctionHandler(AppEvent * event) +{ + if (event->ButtonEvent.Action == APP_BUTTON_PRESSED) + { + if (!sAppTask.mFunctionTimerActive && sAppTask.mFunction == Function::kNoneSelected) + { + P6_LOG("Factory Reset Triggered. Press button again within %us to cancel.", FACTORY_RESET_CANCEL_WINDOW_TIMEOUT / 1000); + // Start timer for FACTORY_RESET_CANCEL_WINDOW_TIMEOUT to allow user to + // cancel, if required. + sAppTask.StartTimer(FACTORY_RESET_CANCEL_WINDOW_TIMEOUT); + + sAppTask.mFunction = Function::kFactoryReset; + + // Turn off all LEDs before starting blink to make sure blink is + // co-ordinated. + sStatusLED.Set(false); + sLightLED.Set(false); + + sStatusLED.Blink(500); + sLightLED.Blink(500); + } + else if (sAppTask.mFunctionTimerActive && sAppTask.mFunction == Function::kFactoryReset) + { + + sAppTask.CancelTimer(); + + // Change the function to none selected since factory reset has been + // canceled. + sAppTask.mFunction = Function::kNoneSelected; + + P6_LOG("Factory Reset has been Canceled"); + } + } +} + +void AppTask::CancelTimer() +{ + if (xTimerStop(sFunctionTimer, 0) == pdFAIL) + { + P6_LOG("app timer stop() failed"); + appError(APP_ERROR_STOP_TIMER_FAILED); + } + + mFunctionTimerActive = false; +} + +void AppTask::StartTimer(uint32_t aTimeoutInMs) +{ + if (xTimerIsTimerActive(sFunctionTimer)) + { + P6_LOG("app timer already started!"); + CancelTimer(); + } + + // timer is not active, change its period to required value (== restart). + // FreeRTOS- Block for a maximum of 100 ticks if the change period command + // cannot immediately be sent to the timer command queue. + if (xTimerChangePeriod(sFunctionTimer, aTimeoutInMs / portTICK_PERIOD_MS, 100) != pdPASS) + { + P6_LOG("app timer start() failed"); + appError(APP_ERROR_START_TIMER_FAILED); + } + + mFunctionTimerActive = true; } void AppTask::PostEvent(const AppEvent * event) diff --git a/examples/all-clusters-app/p6/src/ButtonHandler.cpp b/examples/all-clusters-app/p6/src/ButtonHandler.cpp index b9765cbeec03b3..56c088b46ad83d 100644 --- a/examples/all-clusters-app/p6/src/ButtonHandler.cpp +++ b/examples/all-clusters-app/p6/src/ButtonHandler.cpp @@ -23,22 +23,28 @@ #include "AppTask.h" namespace { +constexpr int kButtonCount = 2; -TimerHandle_t buttonTimer; // FreeRTOS timers used for debouncing buttons +TimerHandle_t buttonTimers[kButtonCount]; // FreeRTOS timers used for debouncing +// buttons. Array to hold handles to +// the created timers. } // namespace void ButtonHandler::Init(void) { GpioInit(); - - buttonTimer = xTimerCreate("BtnTmr", // Just a text name, not used by the RTOS kernel - APP_BUTTON_DEBOUNCE_PERIOD_MS, // timer period - false, // no timer reload (==one-shot) - (void *) (int) APP_LIGHT_BUTTON_IDX, // init timer id = button index - TimerCallback // timer callback handler (all buttons use - // the same timer cn function) - ); + // Create FreeRTOS sw timers for debouncing buttons. + for (uint8_t i = 0; i < kButtonCount; i++) + { + buttonTimers[i] = xTimerCreate("BtnTmr", // Just a text name, not used by the RTOS kernel + APP_BUTTON_DEBOUNCE_PERIOD_MS, // timer period + false, // no timer reload (==one-shot) + (void *) (int) i, // init timer id = button index + TimerCallback // timer callback handler (all buttons use + // the same timer cn function) + ); + } } void ButtonHandler::GpioInit(void) @@ -50,19 +56,34 @@ void ButtonHandler::GpioInit(void) { printf(" cyhal_gpio_init failed for APP_LIGHT_BUTTON\r\n"); } - + result = cyhal_gpio_init(APP_FUNCTION_BUTTON, CYHAL_GPIO_DIR_INPUT, CYHAL_GPIO_DRIVE_PULLUP, CYBSP_BTN_OFF); + if (result != CY_RSLT_SUCCESS) + { + printf(" cyhal_gpio_init failed for APP_FUNCTION_BUTTON\r\n"); + } /* Configure GPIO interrupt. */ static cyhal_gpio_callback_data_t light_button_cbdata; + static cyhal_gpio_callback_data_t func_button_cbdata; light_button_cbdata.callback = light_button_callback; light_button_cbdata.callback_arg = NULL; cyhal_gpio_register_callback(APP_LIGHT_BUTTON, &light_button_cbdata); + func_button_cbdata.callback = func_button_callback; + func_button_cbdata.callback_arg = NULL; + cyhal_gpio_register_callback(APP_FUNCTION_BUTTON, &func_button_cbdata); cyhal_gpio_enable_event(APP_LIGHT_BUTTON, CYHAL_GPIO_IRQ_FALL, GPIO_INTERRUPT_PRIORITY, true); + cyhal_gpio_enable_event(APP_FUNCTION_BUTTON, CYHAL_GPIO_IRQ_FALL, GPIO_INTERRUPT_PRIORITY, true); } void ButtonHandler::light_button_callback(void * handler_arg, cyhal_gpio_event_t event) { portBASE_TYPE taskWoken = pdFALSE; - xTimerStartFromISR(buttonTimer, &taskWoken); + xTimerStartFromISR(buttonTimers[APP_LIGHT_BUTTON_IDX], &taskWoken); +} + +void ButtonHandler::func_button_callback(void * handler_arg, cyhal_gpio_event_t event) +{ + portBASE_TYPE taskWoken = pdFALSE; + xTimerStartFromISR(buttonTimers[APP_FUNCTION_BUTTON_IDX], &taskWoken); } void ButtonHandler::TimerCallback(TimerHandle_t xTimer) @@ -77,11 +98,16 @@ void ButtonHandler::TimerCallback(TimerHandle_t xTimer) case APP_LIGHT_BUTTON_IDX: buttonevent = cyhal_gpio_read(APP_LIGHT_BUTTON); break; - + case APP_FUNCTION_BUTTON_IDX: + buttonevent = cyhal_gpio_read(APP_FUNCTION_BUTTON); + break; default: P6_LOG("Unhandled TimerID: %d", timerId); break; } - GetAppTask().ButtonEventHandler(timerId, (buttonevent) ? APP_BUTTON_PRESSED : APP_BUTTON_RELEASED); + if (buttonevent) + { + GetAppTask().ButtonEventHandler(timerId, APP_BUTTON_PRESSED); + } } diff --git a/examples/all-clusters-minimal-app/p6/include/AppConfig.h b/examples/all-clusters-minimal-app/p6/include/AppConfig.h index 8e9ebe286ef421..bffd31f0d8a23b 100644 --- a/examples/all-clusters-minimal-app/p6/include/AppConfig.h +++ b/examples/all-clusters-minimal-app/p6/include/AppConfig.h @@ -28,8 +28,11 @@ #define APP_TASK_NAME "APP" #define APP_LIGHT_BUTTON_IDX 0 +#define APP_FUNCTION_BUTTON_IDX 1 + #define APP_LIGHT_BUTTON CYBSP_USER_BTN1 -#define APP_BUTTON_DEBOUNCE_PERIOD_MS 50 +#define APP_FUNCTION_BUTTON CYBSP_USER_BTN2 +#define APP_BUTTON_DEBOUNCE_PERIOD_MS 200 #define APP_BUTTON_PRESSED 0 #define APP_BUTTON_RELEASED 1 diff --git a/examples/all-clusters-minimal-app/p6/include/AppTask.h b/examples/all-clusters-minimal-app/p6/include/AppTask.h index 5bb9a9163225bf..6dbd906b8104d6 100644 --- a/examples/all-clusters-minimal-app/p6/include/AppTask.h +++ b/examples/all-clusters-minimal-app/p6/include/AppTask.h @@ -54,8 +54,22 @@ class AppTask CHIP_ERROR Init(); static AppTask sAppTask; + void CancelTimer(void); void DispatchEvent(AppEvent * event); + static void FunctionTimerEventHandler(AppEvent * event); + static void FunctionHandler(AppEvent * event); + static void TimerEventHandler(TimerHandle_t timer); static void OnOffUpdateClusterState(intptr_t context); + void StartTimer(uint32_t aTimeoutMs); + + enum class Function + { + kNoneSelected = 0, + kFactoryReset = 1, + kInvalid + }; + Function mFunction = Function::kNoneSelected; + bool mFunctionTimerActive = false; }; inline AppTask & GetAppTask(void) diff --git a/examples/all-clusters-minimal-app/p6/include/ButtonHandler.h b/examples/all-clusters-minimal-app/p6/include/ButtonHandler.h index a4128c68f86f0e..ac4d795d64280e 100644 --- a/examples/all-clusters-minimal-app/p6/include/ButtonHandler.h +++ b/examples/all-clusters-minimal-app/p6/include/ButtonHandler.h @@ -36,5 +36,6 @@ class ButtonHandler private: static void GpioInit(void); static void light_button_callback(void * handler_arg, cyhal_gpio_event_t event); + static void func_button_callback(void * handler_arg, cyhal_gpio_event_t event); static void TimerCallback(TimerHandle_t xTimer); }; diff --git a/examples/all-clusters-minimal-app/p6/src/AppTask.cpp b/examples/all-clusters-minimal-app/p6/src/AppTask.cpp index e9ce95ad12c304..45a3dfb8af90b7 100644 --- a/examples/all-clusters-minimal-app/p6/src/AppTask.cpp +++ b/examples/all-clusters-minimal-app/p6/src/AppTask.cpp @@ -72,12 +72,14 @@ using namespace ::chip::System; #define APP_EVENT_QUEUE_SIZE 10 #define APP_TASK_STACK_SIZE (4096) #define APP_WAIT_LOOP 1000 +#define FACTORY_RESET_CANCEL_WINDOW_TIMEOUT 5000 LEDWidget sStatusLED; LEDWidget sLightLED; LEDWidget sClusterLED; namespace { +TimerHandle_t sFunctionTimer; // FreeRTOS app sw timer. TaskHandle_t sAppTaskHandle; QueueHandle_t sAppEventQueue; @@ -184,6 +186,18 @@ CHIP_ERROR AppTask::Init() // Initialise WSTK buttons PB0 and PB1 (including debounce). ButtonHandler::Init(); + // Create FreeRTOS sw timer for Function Selection. + sFunctionTimer = xTimerCreate("FnTmr", // Just a text name, not used by the RTOS kernel + 1, // == default timer period (mS) + false, // no timer reload (==one-shot) + (void *) this, // init timer id = app task obj context + TimerEventHandler // timer callback handler + ); + if (sFunctionTimer == NULL) + { + P6_LOG("funct timer create failed"); + appError(APP_ERROR_CREATE_TIMER_FAILED); + } NetWorkCommissioningInstInit(); P6_LOG("Current Software Version: %s", CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING); @@ -234,7 +248,7 @@ void AppTask::LightActionEventHandler(AppEvent * aEvent) void AppTask::ButtonEventHandler(uint8_t btnIdx, uint8_t btnAction) { - if (btnIdx != APP_LIGHT_BUTTON_IDX) + if (btnIdx != APP_LIGHT_BUTTON_IDX && btnIdx != APP_FUNCTION_BUTTON_IDX) { return; } @@ -244,11 +258,106 @@ void AppTask::ButtonEventHandler(uint8_t btnIdx, uint8_t btnAction) button_event.ButtonEvent.ButtonIdx = btnIdx; button_event.ButtonEvent.Action = btnAction; - if ((btnIdx == APP_LIGHT_BUTTON_IDX) && (btnAction == APP_BUTTON_RELEASED)) + if (btnIdx == APP_LIGHT_BUTTON_IDX) { button_event.Handler = LightActionEventHandler; sAppTask.PostEvent(&button_event); } + else if (btnIdx == APP_FUNCTION_BUTTON_IDX) + { + button_event.Handler = FunctionHandler; + sAppTask.PostEvent(&button_event); + } +} + +void AppTask::TimerEventHandler(TimerHandle_t timer) +{ + AppEvent event; + event.Type = AppEvent::kEventType_Timer; + event.TimerEvent.Context = (void *) timer; + event.Handler = FunctionTimerEventHandler; + sAppTask.PostEvent(&event); +} + +void AppTask::FunctionTimerEventHandler(AppEvent * event) +{ + if (event->Type != AppEvent::kEventType_Timer) + { + return; + } + + if (sAppTask.mFunctionTimerActive && sAppTask.mFunction == Function::kFactoryReset) + { + // Actually trigger Factory Reset + sAppTask.mFunction = Function::kNoneSelected; + chip::Server::GetInstance().ScheduleFactoryReset(); + } +} + +void AppTask::FunctionHandler(AppEvent * event) +{ + if (event->ButtonEvent.Action == APP_BUTTON_PRESSED) + { + if (!sAppTask.mFunctionTimerActive && sAppTask.mFunction == Function::kNoneSelected) + { + P6_LOG("Factory Reset Triggered. Press button again within %us to cancel.", FACTORY_RESET_CANCEL_WINDOW_TIMEOUT / 1000); + // Start timer for FACTORY_RESET_CANCEL_WINDOW_TIMEOUT to allow user to + // cancel, if required. + sAppTask.StartTimer(FACTORY_RESET_CANCEL_WINDOW_TIMEOUT); + + sAppTask.mFunction = Function::kFactoryReset; + + // Turn off all LEDs before starting blink to make sure blink is + // co-ordinated. + sStatusLED.Set(false); + sLightLED.Set(false); + + sStatusLED.Blink(500); + sLightLED.Blink(500); + } + else if (sAppTask.mFunctionTimerActive && sAppTask.mFunction == Function::kFactoryReset) + { + + sAppTask.CancelTimer(); + + // Change the function to none selected since factory reset has been + // canceled. + sAppTask.mFunction = Function::kNoneSelected; + + P6_LOG("Factory Reset has been Canceled"); + } + } +} + +void AppTask::CancelTimer() +{ + if (xTimerStop(sFunctionTimer, 0) == pdFAIL) + { + P6_LOG("app timer stop() failed"); + appError(APP_ERROR_STOP_TIMER_FAILED); + } + + mFunctionTimerActive = false; +} + +void AppTask::StartTimer(uint32_t aTimeoutInMs) +{ + if (xTimerIsTimerActive(sFunctionTimer)) + { + P6_LOG("app timer already started!"); + CancelTimer(); + } + + // timer is not active, change its period to required value (== restart). + // FreeRTOS- Block for a maximum of 100 ticks if the change period command + // cannot immediately be sent to the timer command queue. + if (xTimerChangePeriod(sFunctionTimer, aTimeoutInMs / portTICK_PERIOD_MS, 100) != pdPASS) + { + P6_LOG("app timer start() failed"); + appError(APP_ERROR_START_TIMER_FAILED); + } + + mFunctionTimerActive = true; } void AppTask::PostEvent(const AppEvent * aEvent) diff --git a/examples/all-clusters-minimal-app/p6/src/ButtonHandler.cpp b/examples/all-clusters-minimal-app/p6/src/ButtonHandler.cpp index b9765cbeec03b3..56c088b46ad83d 100644 --- a/examples/all-clusters-minimal-app/p6/src/ButtonHandler.cpp +++ b/examples/all-clusters-minimal-app/p6/src/ButtonHandler.cpp @@ -23,22 +23,28 @@ #include "AppTask.h" namespace { +constexpr int kButtonCount = 2; -TimerHandle_t buttonTimer; // FreeRTOS timers used for debouncing buttons +TimerHandle_t buttonTimers[kButtonCount]; // FreeRTOS timers used for debouncing +// buttons. Array to hold handles to +// the created timers. } // namespace void ButtonHandler::Init(void) { GpioInit(); - - buttonTimer = xTimerCreate("BtnTmr", // Just a text name, not used by the RTOS kernel - APP_BUTTON_DEBOUNCE_PERIOD_MS, // timer period - false, // no timer reload (==one-shot) - (void *) (int) APP_LIGHT_BUTTON_IDX, // init timer id = button index - TimerCallback // timer callback handler (all buttons use - // the same timer cn function) - ); + // Create FreeRTOS sw timers for debouncing buttons. + for (uint8_t i = 0; i < kButtonCount; i++) + { + buttonTimers[i] = xTimerCreate("BtnTmr", // Just a text name, not used by the RTOS kernel + APP_BUTTON_DEBOUNCE_PERIOD_MS, // timer period + false, // no timer reload (==one-shot) + (void *) (int) i, // init timer id = button index + TimerCallback // timer callback handler (all buttons use + // the same timer cn function) + ); + } } void ButtonHandler::GpioInit(void) @@ -50,19 +56,34 @@ void ButtonHandler::GpioInit(void) { printf(" cyhal_gpio_init failed for APP_LIGHT_BUTTON\r\n"); } - + result = cyhal_gpio_init(APP_FUNCTION_BUTTON, CYHAL_GPIO_DIR_INPUT, CYHAL_GPIO_DRIVE_PULLUP, CYBSP_BTN_OFF); + if (result != CY_RSLT_SUCCESS) + { + printf(" cyhal_gpio_init failed for APP_FUNCTION_BUTTON\r\n"); + } /* Configure GPIO interrupt. */ static cyhal_gpio_callback_data_t light_button_cbdata; + static cyhal_gpio_callback_data_t func_button_cbdata; light_button_cbdata.callback = light_button_callback; light_button_cbdata.callback_arg = NULL; cyhal_gpio_register_callback(APP_LIGHT_BUTTON, &light_button_cbdata); + func_button_cbdata.callback = func_button_callback; + func_button_cbdata.callback_arg = NULL; + cyhal_gpio_register_callback(APP_FUNCTION_BUTTON, &func_button_cbdata); cyhal_gpio_enable_event(APP_LIGHT_BUTTON, CYHAL_GPIO_IRQ_FALL, GPIO_INTERRUPT_PRIORITY, true); + cyhal_gpio_enable_event(APP_FUNCTION_BUTTON, CYHAL_GPIO_IRQ_FALL, GPIO_INTERRUPT_PRIORITY, true); } void ButtonHandler::light_button_callback(void * handler_arg, cyhal_gpio_event_t event) { portBASE_TYPE taskWoken = pdFALSE; - xTimerStartFromISR(buttonTimer, &taskWoken); + xTimerStartFromISR(buttonTimers[APP_LIGHT_BUTTON_IDX], &taskWoken); +} + +void ButtonHandler::func_button_callback(void * handler_arg, cyhal_gpio_event_t event) +{ + portBASE_TYPE taskWoken = pdFALSE; + xTimerStartFromISR(buttonTimers[APP_FUNCTION_BUTTON_IDX], &taskWoken); } void ButtonHandler::TimerCallback(TimerHandle_t xTimer) @@ -77,11 +98,16 @@ void ButtonHandler::TimerCallback(TimerHandle_t xTimer) case APP_LIGHT_BUTTON_IDX: buttonevent = cyhal_gpio_read(APP_LIGHT_BUTTON); break; - + case APP_FUNCTION_BUTTON_IDX: + buttonevent = cyhal_gpio_read(APP_FUNCTION_BUTTON); + break; default: P6_LOG("Unhandled TimerID: %d", timerId); break; } - GetAppTask().ButtonEventHandler(timerId, (buttonevent) ? APP_BUTTON_PRESSED : APP_BUTTON_RELEASED); + if (buttonevent) + { + GetAppTask().ButtonEventHandler(timerId, APP_BUTTON_PRESSED); + } } diff --git a/examples/lighting-app/p6/include/AppConfig.h b/examples/lighting-app/p6/include/AppConfig.h index 5ed6edd44bd594..b199aaf7a1b4d5 100644 --- a/examples/lighting-app/p6/include/AppConfig.h +++ b/examples/lighting-app/p6/include/AppConfig.h @@ -31,7 +31,7 @@ #define APP_LIGHT_BUTTON CYBSP_USER_BTN1 #define APP_FUNCTION_BUTTON CYBSP_USER_BTN2 -#define APP_BUTTON_DEBOUNCE_PERIOD_MS 50 +#define APP_BUTTON_DEBOUNCE_PERIOD_MS 200 #define APP_BUTTON_PRESSED 0 #define APP_BUTTON_RELEASED 1 diff --git a/examples/lighting-app/p6/include/AppTask.h b/examples/lighting-app/p6/include/AppTask.h index a3760122a17ce5..580744cb2fe2d2 100644 --- a/examples/lighting-app/p6/include/AppTask.h +++ b/examples/lighting-app/p6/include/AppTask.h @@ -74,11 +74,8 @@ class AppTask enum class Function { - kNoneSelected = 0, - kSoftwareUpdate = 0, - kStartBleAdv = 1, - kFactoryReset = 2, - + kNoneSelected = 0, + kFactoryReset = 1, kInvalid }; diff --git a/examples/lighting-app/p6/src/AppTask.cpp b/examples/lighting-app/p6/src/AppTask.cpp index c0b2833ad40086..08f9b76a1a3f8f 100644 --- a/examples/lighting-app/p6/src/AppTask.cpp +++ b/examples/lighting-app/p6/src/AppTask.cpp @@ -67,8 +67,7 @@ using namespace ::chip::DeviceLayer; using namespace ::chip::System; #endif -#define FACTORY_RESET_TRIGGER_TIMEOUT 3000 -#define FACTORY_RESET_CANCEL_WINDOW_TIMEOUT 3000 +#define FACTORY_RESET_CANCEL_WINDOW_TIMEOUT 5000 #define APP_TASK_STACK_SIZE (4096) #define APP_TASK_PRIORITY 2 #define APP_EVENT_QUEUE_SIZE 10 @@ -367,27 +366,7 @@ void AppTask::FunctionTimerEventHandler(AppEvent * event) return; } - // If we reached here, the button was held past FACTORY_RESET_TRIGGER_TIMEOUT, - // initiate factory reset - if (sAppTask.mFunctionTimerActive && sAppTask.mFunction == Function::kStartBleAdv) - { - P6_LOG("Factory Reset Triggered. Release button within %ums to cancel.", FACTORY_RESET_CANCEL_WINDOW_TIMEOUT); - - // Start timer for FACTORY_RESET_CANCEL_WINDOW_TIMEOUT to allow user to - // cancel, if required. - sAppTask.StartTimer(FACTORY_RESET_CANCEL_WINDOW_TIMEOUT); - - sAppTask.mFunction = Function::kFactoryReset; - - // Turn off all LEDs before starting blink to make sure blink is - // co-ordinated. - sStatusLED.Set(false); - sLightLED.Set(false); - - sStatusLED.Blink(500); - sLightLED.Blink(500); - } - else if (sAppTask.mFunctionTimerActive && sAppTask.mFunction == Function::kFactoryReset) + if (sAppTask.mFunctionTimerActive && sAppTask.mFunction == Function::kFactoryReset) { // Actually trigger Factory Reset sAppTask.mFunction = Function::kNoneSelected; @@ -397,28 +376,24 @@ void AppTask::FunctionTimerEventHandler(AppEvent * event) void AppTask::FunctionHandler(AppEvent * event) { - // To trigger software update: press the APP_FUNCTION_BUTTON button briefly (< - // FACTORY_RESET_TRIGGER_TIMEOUT) To initiate factory reset: press the - // APP_FUNCTION_BUTTON for FACTORY_RESET_TRIGGER_TIMEOUT + - // FACTORY_RESET_CANCEL_WINDOW_TIMEOUT All LEDs start blinking after - // FACTORY_RESET_TRIGGER_TIMEOUT to signal factory reset has been initiated. - // To cancel factory reset: release the APP_FUNCTION_BUTTON once all LEDs - // start blinking within the FACTORY_RESET_CANCEL_WINDOW_TIMEOUT - if (event->ButtonEvent.Action == APP_BUTTON_RELEASED) + if (event->ButtonEvent.Action == APP_BUTTON_PRESSED) { if (!sAppTask.mFunctionTimerActive && sAppTask.mFunction == Function::kNoneSelected) { - sAppTask.StartTimer(FACTORY_RESET_TRIGGER_TIMEOUT); - sAppTask.mFunction = Function::kStartBleAdv; - } - } - else - { - // If the button was released before factory reset got initiated, start Thread Network - if (sAppTask.mFunctionTimerActive && sAppTask.mFunction == Function::kStartBleAdv) - { - sAppTask.CancelTimer(); - sAppTask.mFunction = Function::kNoneSelected; + P6_LOG("Factory Reset Triggered. Press button again within %us to cancel.", FACTORY_RESET_CANCEL_WINDOW_TIMEOUT / 1000); + // Start timer for FACTORY_RESET_CANCEL_WINDOW_TIMEOUT to allow user to + // cancel, if required. + sAppTask.StartTimer(FACTORY_RESET_CANCEL_WINDOW_TIMEOUT); + + sAppTask.mFunction = Function::kFactoryReset; + + // Turn off all LEDs before starting blink to make sure blink is + // co-ordinated. + sStatusLED.Set(false); + sLightLED.Set(false); + + sStatusLED.Blink(500); + sLightLED.Blink(500); } else if (sAppTask.mFunctionTimerActive && sAppTask.mFunction == Function::kFactoryReset) { diff --git a/examples/lighting-app/p6/src/ButtonHandler.cpp b/examples/lighting-app/p6/src/ButtonHandler.cpp index 80384347fd24a6..e4a0d483d20c69 100644 --- a/examples/lighting-app/p6/src/ButtonHandler.cpp +++ b/examples/lighting-app/p6/src/ButtonHandler.cpp @@ -53,7 +53,7 @@ void ButtonHandler::GpioInit(void) result = cyhal_gpio_init(APP_LIGHT_BUTTON, CYHAL_GPIO_DIR_INPUT, CYHAL_GPIO_DRIVE_PULLUP, CYBSP_BTN_OFF); if (result != CY_RSLT_SUCCESS) { - printf(" cyhal_gpio_init failed for APP_LOCK_BUTTON\r\n"); + printf(" cyhal_gpio_init failed for APP_LIGHT_BUTTON\r\n"); } result = cyhal_gpio_init(APP_FUNCTION_BUTTON, CYHAL_GPIO_DIR_INPUT, CYHAL_GPIO_DRIVE_PULLUP, CYBSP_BTN_OFF); if (result != CY_RSLT_SUCCESS) @@ -98,5 +98,8 @@ void ButtonHandler::TimerCallback(TimerHandle_t xTimer) { buttonevent = cyhal_gpio_read(APP_LIGHT_BUTTON); } - GetAppTask().ButtonEventHandler(timerId, (buttonevent) ? APP_BUTTON_PRESSED : APP_BUTTON_RELEASED); + if (buttonevent) + { + GetAppTask().ButtonEventHandler(timerId, APP_BUTTON_PRESSED); + } } diff --git a/examples/lock-app/p6/include/AppConfig.h b/examples/lock-app/p6/include/AppConfig.h index 1046f7821a6b9e..5e9c988a389a8f 100644 --- a/examples/lock-app/p6/include/AppConfig.h +++ b/examples/lock-app/p6/include/AppConfig.h @@ -31,7 +31,7 @@ #define APP_LOCK_BUTTON CYBSP_USER_BTN1 #define APP_FUNCTION_BUTTON CYBSP_USER_BTN2 -#define APP_BUTTON_DEBOUNCE_PERIOD_MS 50 +#define APP_BUTTON_DEBOUNCE_PERIOD_MS 200 #define APP_BUTTON_PRESSED 0 #define APP_BUTTON_RELEASED 1 diff --git a/examples/lock-app/p6/include/AppTask.h b/examples/lock-app/p6/include/AppTask.h index 8974d83523baa9..f83ba6c1e42730 100644 --- a/examples/lock-app/p6/include/AppTask.h +++ b/examples/lock-app/p6/include/AppTask.h @@ -76,11 +76,8 @@ class AppTask enum class Function { - kNoneSelected = 0, - kSoftwareUpdate = 0, - kStartBleAdv = 1, - kFactoryReset = 2, - + kNoneSelected = 0, + kFactoryReset = 1, kInvalid }; diff --git a/examples/lock-app/p6/src/AppTask.cpp b/examples/lock-app/p6/src/AppTask.cpp index 866f43de610ae9..f93438d47cbbf5 100644 --- a/examples/lock-app/p6/src/AppTask.cpp +++ b/examples/lock-app/p6/src/AppTask.cpp @@ -76,8 +76,7 @@ using namespace ::chip::System; #endif -#define FACTORY_RESET_TRIGGER_TIMEOUT 3000 -#define FACTORY_RESET_CANCEL_WINDOW_TIMEOUT 3000 +#define FACTORY_RESET_CANCEL_WINDOW_TIMEOUT 5000 #define APP_TASK_STACK_SIZE (4096) #define APP_TASK_PRIORITY 2 #define APP_EVENT_QUEUE_SIZE 10 @@ -448,27 +447,7 @@ void AppTask::FunctionTimerEventHandler(AppEvent * event) return; } - // If we reached here, the button was held past FACTORY_RESET_TRIGGER_TIMEOUT, - // initiate factory reset - if (sAppTask.mFunctionTimerActive && sAppTask.mFunction == Function::kStartBleAdv) - { - P6_LOG("Factory Reset Triggered. Release button within %ums to cancel.", FACTORY_RESET_CANCEL_WINDOW_TIMEOUT); - - // Start timer for FACTORY_RESET_CANCEL_WINDOW_TIMEOUT to allow user to - // cancel, if required. - sAppTask.StartTimer(FACTORY_RESET_CANCEL_WINDOW_TIMEOUT); - - sAppTask.mFunction = Function::kFactoryReset; - - // Turn off all LEDs before starting blink to make sure blink is - // co-ordinated. - sStatusLED.Set(false); - sLockLED.Set(false); - - sStatusLED.Blink(500); - sLockLED.Blink(500); - } - else if (sAppTask.mFunctionTimerActive && sAppTask.mFunction == Function::kFactoryReset) + if (sAppTask.mFunctionTimerActive && sAppTask.mFunction == Function::kFactoryReset) { // Actually trigger Factory Reset sAppTask.mFunction = Function::kNoneSelected; @@ -482,28 +461,25 @@ void AppTask::FunctionHandler(AppEvent * event) { return; } - // To trigger software update: press the APP_FUNCTION_BUTTON button briefly (< - // FACTORY_RESET_TRIGGER_TIMEOUT) To initiate factory reset: press the - // APP_FUNCTION_BUTTON for FACTORY_RESET_TRIGGER_TIMEOUT + - // FACTORY_RESET_CANCEL_WINDOW_TIMEOUT All LEDs start blinking after - // FACTORY_RESET_TRIGGER_TIMEOUT to signal factory reset has been initiated. - // To cancel factory reset: release the APP_FUNCTION_BUTTON once all LEDs - // start blinking within the FACTORY_RESET_CANCEL_WINDOW_TIMEOUT - if (event->ButtonEvent.Action == APP_BUTTON_RELEASED) + + if (event->ButtonEvent.Action == APP_BUTTON_PRESSED) { if (!sAppTask.mFunctionTimerActive && sAppTask.mFunction == Function::kNoneSelected) { - sAppTask.StartTimer(FACTORY_RESET_TRIGGER_TIMEOUT); - sAppTask.mFunction = Function::kStartBleAdv; - } - } - else - { - // If the button was released before factory reset got initiated, start Thread Network - if (sAppTask.mFunctionTimerActive && sAppTask.mFunction == Function::kStartBleAdv) - { - sAppTask.CancelTimer(); - sAppTask.mFunction = Function::kNoneSelected; + P6_LOG("Factory Reset Triggered. Press button again within %us to cancel.", FACTORY_RESET_CANCEL_WINDOW_TIMEOUT / 1000); + // Start timer for FACTORY_RESET_CANCEL_WINDOW_TIMEOUT to allow user to + // cancel, if required. + sAppTask.StartTimer(FACTORY_RESET_CANCEL_WINDOW_TIMEOUT); + + sAppTask.mFunction = Function::kFactoryReset; + + // Turn off all LEDs before starting blink to make sure blink is + // co-ordinated. + sStatusLED.Set(false); + sLockLED.Set(false); + + sStatusLED.Blink(500); + sLockLED.Blink(500); } else if (sAppTask.mFunctionTimerActive && sAppTask.mFunction == Function::kFactoryReset) { @@ -612,10 +588,31 @@ void AppTask::PostEvent(const AppEvent * event) { if (sAppEventQueue != NULL) { - if (!xQueueSend(sAppEventQueue, event, 1)) + BaseType_t status; + if (xPortIsInsideInterrupt()) { - P6_LOG("Failed to post event to app task event queue"); + BaseType_t higherPrioTaskWoken = pdFALSE; + status = xQueueSendFromISR(sAppEventQueue, event, &higherPrioTaskWoken); + +#ifdef portYIELD_FROM_ISR + portYIELD_FROM_ISR(higherPrioTaskWoken); +#elif portEND_SWITCHING_ISR // portYIELD_FROM_ISR or portEND_SWITCHING_ISR + portEND_SWITCHING_ISR(higherPrioTaskWoken); +#else // portYIELD_FROM_ISR or portEND_SWITCHING_ISR +#error "Must have portYIELD_FROM_ISR or portEND_SWITCHING_ISR" +#endif // portYIELD_FROM_ISR or portEND_SWITCHING_ISR } + else + { + status = xQueueSend(sAppEventQueue, event, 1); + } + + if (!status) + P6_LOG("Failed to post event to app task event queue"); + } + else + { + P6_LOG("Event Queue is NULL should never happen"); } } diff --git a/examples/lock-app/p6/src/ButtonHandler.cpp b/examples/lock-app/p6/src/ButtonHandler.cpp index d0bd98a52686ed..20a7c6bce7d1c0 100644 --- a/examples/lock-app/p6/src/ButtonHandler.cpp +++ b/examples/lock-app/p6/src/ButtonHandler.cpp @@ -97,5 +97,9 @@ void ButtonHandler::TimerCallback(TimerHandle_t xTimer) { buttonevent = cyhal_gpio_read(APP_LOCK_BUTTON); } - GetAppTask().ButtonEventHandler(timerId, (buttonevent) ? APP_BUTTON_PRESSED : APP_BUTTON_RELEASED); + + if (buttonevent) + { + GetAppTask().ButtonEventHandler(timerId, APP_BUTTON_PRESSED); + } }