Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

[Infineon] Support Factory reset for all-clusters example apps #21877

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion examples/all-clusters-app/p6/include/AppConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
14 changes: 14 additions & 0 deletions examples/all-clusters-app/p6/include/AppTask.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions examples/all-clusters-app/p6/include/ButtonHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
};
113 changes: 111 additions & 2 deletions examples/all-clusters-app/p6/src/AppTask.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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;
}
Expand All @@ -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)
Expand Down
52 changes: 39 additions & 13 deletions examples/all-clusters-app/p6/src/ButtonHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand All @@ -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);
}
}
5 changes: 4 additions & 1 deletion examples/all-clusters-minimal-app/p6/include/AppConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
14 changes: 14 additions & 0 deletions examples/all-clusters-minimal-app/p6/include/AppTask.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
};
Loading