1818#include < platform/silabs/platformAbstraction/SilabsPlatform.h>
1919#include < sl_si91x_common_flash_intf.h>
2020
21- #include " sl_si91x_driver_gpio.h"
22- #include " sl_si91x_gpio.h"
23-
24- #include < FreeRTOS.h>
25- #include < task.h>
21+ #include < cmsis_os2.h>
22+ #include < sl_cmsis_os2_common.h>
2623
2724#include < app/icd/server/ICDServerConfig.h>
2825
@@ -72,6 +69,11 @@ const sl_rgb_led_t * ledPinArray[SL_LED_COUNT] = { &led_led0 };
7269uint8_t ledPinArray[SL_LED_COUNT] = { SL_LED_LED0_PIN, SL_LED_LED1_PIN };
7370#endif // (defined(SL_MATTER_RGB_LED_ENABLED) && SL_MATTER_RGB_LED_ENABLED)
7471#endif // ENABLE_WSTK_LEDS
72+
73+ #if SL_ICD_ENABLED
74+ #include " sl_si91x_driver_gpio.h"
75+ #include " sl_si91x_power_manager.h"
76+ #endif // SL_ICD_ENABLED
7577}
7678
7779#ifdef SL_CATALOG_SYSTEMVIEW_TRACE_PRESENT
@@ -91,9 +93,16 @@ namespace {
9193uint8_t sButtonStates [SL_SI91x_BUTTON_COUNT] = { 0 };
9294#endif // SL_CATALOG_SIMPLE_BUTTON_PRESENT
9395
94- #if CHIP_CONFIG_ENABLE_ICD_SERVER && defined(SL_CATALOG_SIMPLE_BUTTON_PRESENT)
95- bool btn0_pressed = false ;
96- #endif // CHIP_CONFIG_ENABLE_ICD_SERVER && defined(SL_CATALOG_SIMPLE_BUTTON_PRESENT)
96+ #if CHIP_CONFIG_ENABLE_ICD_SERVER && (SL_MATTER_GN_BUILD == 0)
97+
98+ // Keep awake duration in milliseconds
99+ static constexpr uint32_t kSiWxKeepAwakeDurationMs = 10000 ;
100+
101+ // CMSIS-RTOS2 one-shot timer: each BTN0 press (re)starts the full kSiWxKeepAwakeDurationMs window.
102+ static osTimerId_t sSiWxKeepAwakeOsTimer = nullptr ;
103+ static bool sSiWxKeepAwakePs4Active = false ;
104+
105+ #endif // CHIP_CONFIG_ENABLE_ICD_SERVER && (SL_MATTER_GN_BUILD == 0)
97106
98107#if CHIP_CONFIG_ENABLE_ICD_SERVER == 0
99108int soc_pll_config (void )
@@ -234,22 +243,10 @@ extern "C" void sl_button_on_change(uint8_t btn, uint8_t btnAction)
234243 // if the btn was not pressed and only a release event came, ignore it
235244 // if the btn was already pressed and another press event came, ignore it
236245 // essentially, if both of them are in the same state then ignore it.
237- VerifyOrReturn (btnAction != btn0_pressed);
238-
239- if ((btnAction == BUTTON_PRESSED) && (btn0_pressed == false ))
240- {
241- btn0_pressed = true ;
242- }
243- else if ((btnAction == BUTTON_RELEASED) && (btn0_pressed == true ))
244- {
245- btn0_pressed = false ;
246- }
246+ VerifyOrReturn (btnAction != GetPlatform ().GetButtonState (SL_BUTTON_BTN0_NUMBER));
247247 }
248248#endif // SL_ICD_ENABLED
249- if (Silabs::GetPlatform ().mButtonCallback == nullptr )
250- {
251- return ;
252- }
249+ VerifyOrReturn (GetPlatform ().mButtonCallback != nullptr );
253250
254251 if (btn < SL_SI91x_BUTTON_COUNT)
255252 {
@@ -268,6 +265,76 @@ uint8_t SilabsPlatform::GetButtonState(uint8_t button)
268265{
269266 return (button < SL_SI91x_BUTTON_COUNT) ? sButtonStates [button] : 0 ;
270267}
268+
269+ #if SL_ICD_ENABLED
270+ /* *
271+ * @brief invoked when button press event is received when in sleep
272+ * @param[in] pin_intr GPIO pin interrupt number.
273+ * @return none.
274+ * @note this is a callback from the Wiseconnect SDK
275+ */
276+ extern " C" void gpio_uulp_pin_interrupt_callback (uint32_t pin_intr)
277+ {
278+ // UULP_GPIO_2 is used to detect the button 0 press
279+ VerifyOrReturn (pin_intr == RTE_UULP_GPIO_2_PIN, ChipLogError (DeviceLayer, " invalid pin interrupt: %ld" , pin_intr));
280+ sl_status_t status = SL_STATUS_OK;
281+ uint8_t pin_intr_status = sl_si91x_gpio_get_uulp_npss_pin (pin_intr);
282+ if (pin_intr_status == LOW)
283+ {
284+ // BTN_0 is pressed
285+ // NOTE: the GPIO is masked since the interrupt is invoked before scheduler is started, thus this is required to hand over
286+ // control to scheduler, the PIN is unmasked in the power manager flow before going to sleep
287+ status = sl_si91x_gpio_driver_mask_set_uulp_npss_interrupt (pin_intr);
288+ VerifyOrReturn (status == SL_STATUS_OK, ChipLogError (DeviceLayer, " failed to mask interrupt: %ld" , status));
289+ }
290+ }
291+ #if SL_MATTER_GN_BUILD == 0
292+ static void SiWxKeepAwakeOsTimerCallback (void * arg)
293+ {
294+ (void ) arg;
295+ VerifyOrReturn (sSiWxKeepAwakePs4Active == true );
296+ sl_status_t status = sl_si91x_power_manager_remove_ps_requirement (SL_SI91X_POWER_MANAGER_PS4);
297+ VerifyOrReturn (status == SL_STATUS_OK, ChipLogError (DeviceLayer, " remove_ps failed: %lx" , status));
298+ sSiWxKeepAwakePs4Active = false ;
299+ }
300+
301+ static void SiWxArmKeepAwakeOnBtn0Press ()
302+ {
303+ if (!sSiWxKeepAwakePs4Active )
304+ {
305+ sl_status_t status = sl_si91x_power_manager_add_ps_requirement (SL_SI91X_POWER_MANAGER_PS4);
306+ VerifyOrReturn (status == SL_STATUS_OK, ChipLogError (DeviceLayer, " add_ps failed: %lx" , status));
307+ button_init_instances ();
308+ sSiWxKeepAwakePs4Active = true ;
309+ }
310+
311+ if (sSiWxKeepAwakeOsTimer == nullptr )
312+ {
313+ sSiWxKeepAwakeOsTimer = osTimerNew (SiWxKeepAwakeOsTimerCallback, osTimerOnce, nullptr , nullptr );
314+ VerifyOrReturn (sSiWxKeepAwakeOsTimer != nullptr , ChipLogError (DeviceLayer, " keep awake osTimerNew failed" ));
315+ }
316+
317+ if (osTimerStart (sSiWxKeepAwakeOsTimer , pdMS_TO_TICKS (kSiWxKeepAwakeDurationMs )) != osOK)
318+ {
319+ ChipLogError (DeviceLayer, " keep awake osTimerStart failed" );
320+ }
321+ }
322+ #endif // SL_MATTER_GN_BUILD == 0
323+
324+ void SilabsPlatform::SleepButtonActionHandler ()
325+ {
326+ const uint8_t btnAction = (sl_si91x_gpio_get_uulp_npss_pin (SL_BUTTON_BTN0_PIN) == LOW) ? BUTTON_PRESSED : BUTTON_RELEASED;
327+ // If the button state is the same as the last state, return
328+ VerifyOrReturn (btnAction != GetButtonState (SL_BUTTON_BTN0_NUMBER));
329+ if (btnAction == BUTTON_PRESSED)
330+ {
331+ #if SL_MATTER_GN_BUILD == 0
332+ SiWxArmKeepAwakeOnBtn0Press ();
333+ #endif // SL_MATTER_GN_BUILD == 0
334+ }
335+ sl_button_on_change (SL_BUTTON_BTN0_NUMBER, btnAction);
336+ }
337+ #endif // SL_ICD_ENABLED
271338#else
272339uint8_t SilabsPlatform::GetButtonState (uint8_t button)
273340{
0 commit comments