Skip to content

Commit

Permalink
[nrfconnect] Fixed a timer problem on WindowApp (#19224)
Browse files Browse the repository at this point in the history
Nrfconnect WindowApp example fell into a hard fault
after receiving `windowcovering` commands from a chip-tool.
Moved the application timer's invocation to SystemLayer because previously,
it was called from ISR, and it caused a hard fault.
Added also DFU SMP to the example and set proper pins to PWM.
  • Loading branch information
ArekBalysNordic authored and pull[bot] committed Oct 12, 2023
1 parent d7382bb commit 1655044
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 39 deletions.
22 changes: 22 additions & 0 deletions examples/window-app/nrfconnect/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,20 @@ requests to start sending the update packages.
An OTA Requestor is a node that wants to download a new firmware image and sends
requests to an OTA Provider to start the update process.

#### Simple Management Protocol

Simple Management Protocol (SMP) is a basic transfer encoding that is used for
device management purposes, including application image management. SMP supports
using different transports, such as Bluetooth LE, UDP, or serial USB/UART.

In this example, the Matter device runs the SMP Server to download the
application update image using the Bluetooth LE transport.

See the
[Building with Device Firmware Upgrade support](#building-with-device-firmware-upgrade-support)
section to learn how to enable SMP and use it for the DFU purpose in this
example.

#### Bootloader

MCUboot is a secure bootloader used for swapping firmware images of different
Expand Down Expand Up @@ -394,6 +408,14 @@ For example, use the following command for `nrf52840dk_nrf52840`:

Support for DFU using Matter OTA is enabled by default.

To enable DFU over Bluetooth LE, run the following command with _build-target_
replaced with the build target name of the Nordic Semiconductor kit you are
using (for example `nrf52840dk_nrf52840`):

```
$ west build -b build-target -- -DCONFIG_CHIP_DFU_OVER_BT_SMP=y
```

To completely disable support for DFU, run the following command with
_build-target_ replaced with the build target name of the Nordic Semiconductor
kit you are using (for example `nrf52840dk_nrf52840`):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@
chosen {
nordic,pm-ext-flash = &mx25r64;
};
};


/ {
/*
* In some default configurations within the nRF Connect SDK,
* e.g. on nRF52840, the chosen zephyr,entropy node is &cryptocell.
Expand All @@ -30,17 +33,15 @@
};

/*
* By default, PWM module is only configured for led0 (LED1 on the board).
* The window-app, however, uses LED2 to show the state of the window cover,
* by using the LED's brightness level.
* Configure LED2 and LED3 to show the state of the
* window cover,by using the LED's brightness level.
*/
aliases {
pwm-led1 = &pwm_led1;
pwm-led2 = &pwm_led2;
};

pwmleds {
compatible = "pwm-leds";
pwm_led1: pwm_led_1 {
pwms = <&pwm0 1 PWM_MSEC(20) PWM_POLARITY_INVERTED>;
};
Expand Down Expand Up @@ -82,15 +83,15 @@
&pinctrl {
pwm0_default_alt: pwm0_default_alt {
group1 {
psels = <NRF_PSEL(PWM_OUT1, 0, 29)>, <NRF_PSEL(PWM_OUT2, 0, 30)>;
psels = <NRF_PSEL(PWM_OUT1, 0, 14)>, <NRF_PSEL(PWM_OUT2, 0, 15)>;
nordic,invert;
};
};

pwm0_sleep_alt: pwm0_sleep_alt {
group1 {
psels = <NRF_PSEL(PWM_OUT1, 0, 29)>, <NRF_PSEL(PWM_OUT2, 0, 30)>;
psels = <NRF_PSEL(PWM_OUT1, 0, 14)>, <NRF_PSEL(PWM_OUT2, 0, 15)>;
low-power-enable;
};
};
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,16 @@
};

/*
* By default, PWM module is only configured for led0 (LED1 on the board).
* The lighting-app, however, uses LED2 to show the state of the lighting,
* including its brightness level.
* Configure LED2 and LED3 to show the state of the
* window cover,by using the LED's brightness level.
*/
aliases {
pwm-led1 = &pwm_led1;
pwm-led2 = &pwm_led2;
};

pwmleds {
compatible = "pwm-leds";
pwm_led1: pwm_led_1 {
pwms = <&pwm0 1 PWM_MSEC(20) PWM_POLARITY_INVERTED>;
};
Expand Down Expand Up @@ -81,9 +81,9 @@
};
};
};

};


/* Disable unused peripherals to reduce power consumption */
&adc {
status = "disabled";
Expand All @@ -110,14 +110,14 @@
&pinctrl {
pwm0_default_alt: pwm0_default_alt {
group1 {
psels = <NRF_PSEL(PWM_OUT1, 0, 14)>, <NRF_PSEL(PWM_OUT2, 0, 15)>;
psels = <NRF_PSEL(PWM_OUT1, 0, 29)>, <NRF_PSEL(PWM_OUT2, 0, 30)>;
nordic,invert;
};
};

pwm0_sleep_alt: pwm0_sleep_alt {
group1 {
psels = <NRF_PSEL(PWM_OUT1, 0, 14)>, <NRF_PSEL(PWM_OUT2, 0, 15)>;
psels = <NRF_PSEL(PWM_OUT1, 0, 29)>, <NRF_PSEL(PWM_OUT2, 0, 30)>;
low-power-enable;
};
};
Expand Down
22 changes: 21 additions & 1 deletion examples/window-app/nrfconnect/main/AppTask.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,12 @@ CHIP_ERROR AppTask::Init()
k_timer_init(&sFunctionTimer, &AppTask::FunctionTimerTimeoutCallback, nullptr);
k_timer_user_data_set(&sFunctionTimer, this);

#ifdef CONFIG_MCUMGR_SMP_BT
/* Initialize DFU over SMP */
GetDFUOverSMP().Init(RequestSMPAdvertisingStart);
GetDFUOverSMP().ConfirmNewImage();
#endif

// Initialize CHIP server
SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider());

Expand Down Expand Up @@ -224,6 +230,16 @@ void AppTask::ButtonEventHandler(uint32_t aButtonState, uint32_t aHasChanged)
}
}

#ifdef CONFIG_MCUMGR_SMP_BT
void AppTask::RequestSMPAdvertisingStart(void)
{
AppEvent event;
event.Type = AppEvent::Type::StartSMPAdvertising;
event.Handler = [](AppEvent *) { GetDFUOverSMP().StartBLEAdvertising(); };
PostEvent(&event);
}
#endif

void AppTask::FunctionTimerTimeoutCallback(k_timer * aTimer)
{
if (!aTimer)
Expand Down Expand Up @@ -295,7 +311,11 @@ void AppTask::FunctionHandler(AppEvent * aEvent)

UpdateStatusLED();
CancelTimer();

#ifdef CONFIG_MCUMGR_SMP_BT
GetDFUOverSMP().StartServer();
#else
LOG_INF("Software update is disabled");
#endif
// Change the function to none selected since factory reset has been canceled.
Instance().mMode = OperatingMode::Normal;

Expand Down
44 changes: 20 additions & 24 deletions examples/window-app/nrfconnect/main/WindowCovering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,7 @@ using namespace chip::app::Clusters::WindowCovering;

static const struct pwm_dt_spec sLiftPwmDevice = PWM_DT_SPEC_GET(DT_ALIAS(pwm_led1));
static const struct pwm_dt_spec sTiltPwmDevice = PWM_DT_SPEC_GET(DT_ALIAS(pwm_led2));
static k_timer sLiftTimer;
static k_timer sTiltTimer;

static constexpr uint32_t sMoveTimeoutMs{ 200 };

WindowCovering::WindowCovering()
Expand All @@ -52,24 +51,6 @@ WindowCovering::WindowCovering()
{
LOG_ERR("Cannot initialize the tilt indicator");
}

k_timer_init(&sLiftTimer, MoveTimerTimeoutCallback, nullptr);
k_timer_init(&sTiltTimer, MoveTimerTimeoutCallback, nullptr);
}

void WindowCovering::MoveTimerTimeoutCallback(k_timer * aTimer)
{
if (!aTimer)
return;

if (aTimer == &sLiftTimer)
{
chip::DeviceLayer::PlatformMgr().ScheduleWork(DriveCurrentLiftPosition);
}
else if (aTimer == &sTiltTimer)
{
chip::DeviceLayer::PlatformMgr().ScheduleWork(DriveCurrentTiltPosition);
}
}

void WindowCovering::DriveCurrentLiftPosition(intptr_t)
Expand Down Expand Up @@ -162,14 +143,29 @@ bool WindowCovering::TargetCompleted(MoveType aMoveType, NPercent100ths aCurrent

void WindowCovering::StartTimer(MoveType aMoveType, uint32_t aTimeoutMs)
{
if (aMoveType == MoveType::LIFT)
MoveType * moveType = chip::Platform::New<MoveType>();
VerifyOrReturn(moveType != nullptr);

*moveType = aMoveType;
(void) chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Milliseconds32(aTimeoutMs), MoveTimerTimeoutCallback,
reinterpret_cast<void *>(moveType));
}

void WindowCovering::MoveTimerTimeoutCallback(chip::System::Layer * systemLayer, void * appState)
{
MoveType * moveType = reinterpret_cast<MoveType *>(appState);
VerifyOrReturn(moveType != nullptr);

if (*moveType == MoveType::LIFT)
{
k_timer_start(&sLiftTimer, K_MSEC(sMoveTimeoutMs), K_NO_WAIT);
chip::DeviceLayer::PlatformMgr().ScheduleWork(WindowCovering::DriveCurrentLiftPosition);
}
else if (aMoveType == MoveType::TILT)
else if (*moveType == MoveType::TILT)
{
k_timer_start(&sTiltTimer, K_MSEC(sMoveTimeoutMs), K_NO_WAIT);
chip::DeviceLayer::PlatformMgr().ScheduleWork(WindowCovering::DriveCurrentTiltPosition);
}

chip::Platform::Delete(moveType);
}

void WindowCovering::DriveCurrentTiltPosition(intptr_t)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ class WindowCovering
static chip::Percent100ths CalculateSingleStep(MoveType aMoveType);
static void DriveCurrentLiftPosition(intptr_t);
static void DriveCurrentTiltPosition(intptr_t);
static void MoveTimerTimeoutCallback(k_timer * aTimer);
static void MoveTimerTimeoutCallback(chip::System::Layer * systemLayer, void * appState);
static void DoPostAttributeChange(intptr_t aArg);

MoveType mCurrentUIMoveType;
Expand Down

0 comments on commit 1655044

Please sign in to comment.