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

Refactor LwM2M engine to support tickless operation #60887

Merged

Conversation

SeppoTakalo
Copy link
Collaborator

This is a combination of 3 changes that allows LwM2M engine to sleep longer without ticking 500 ms timer.

Create socketpair that can wake up zsock_poll()]

Allow socket-loop to wake up immediately, if there are changes,
instead of waiting for zsock_poll() to timeout.
This change makes engine more reactive and removes
hard coded timeout from zsock_poll().

New API (internal):

/**
 * @brief Trigger the LwM2M engine to run.
 *
 * This function wakes up ongoing poll() from the socket-loop.
 * It should be called when new transmissions are scheduled or service schedules are modified.
 */
void lwm2m_engine_wake_up(void);

Add support for non-periodic services

Engine now allows registering service callbacks that are
called only once on a given timestamp.
This allows tickless services to be developed.
New API proposed:

/**
 * @brief Call specific service handler only once at given timestamp.
 *
 * @param[in] service service to be called
 * @param[in] timestamp Time when to call
 * @return 0 for success or negative in case of error
 */
int lwm2m_engine_call_at(k_work_handler_t service, int64_t timestamp);

Refactor RD client to be tickless

Call RD client service only when there is state transitioning by using lwm2m_engine_call_at()
Remove periodic 500 ms timer.

When all these changes are combined, client will react to changes immediately as there is no 500ms timeout in zsock_poll(). Also it sleeps properly, when in QUEUE_RX_OFF. I measure the change on nRF9160. Current usage on sleep was reduced from 4 uA to 2 uA. So 50% power saving in sleep mode, where we are going to spend most of the time.

@SeppoTakalo
Copy link
Collaborator Author

Unfortunately this creates dependency to heap as the Socketpair uses heap to allocate storage.

Is this acceptable? I could refactor the socketpair to support statically allocated storage as well, if that would be preferred.

@SeppoTakalo
Copy link
Collaborator Author

I have a proposal that would allocate socketpairs statically on devices that don't define heap by default: #60914

@SeppoTakalo
Copy link
Collaborator Author

Power measurements of the changes in this PR

Measurements are done in nRF Connect SDK with these changes cherry-picked into the working tree. Target chip is nRF9160 and tool is Nordic Semiconductor Power Profiler Kit.

Client is configured to use LwM2M QUEUE mode and LTE modem is configured to use eDRX and PSM power saving modes.

Effect of these changes are clearly visible in the PSM power saving mode, where only thing that is constantly ticking in 500 ms interval is our LwM2M client. Floor current stays aroung 4 uA.

When client is re-build using tickless mode, those spikes in 500 ms interval disappear and the floor current drops below 2 uA.

Current main (without this PR)

image

This PR

image

Copy link
Contributor

@rlubos rlubos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a significant improvement, however I'm wondering - perhaps we should retain the old behaviour (timeout-based poll()) as a Kconfig option? For the sake of platforms, that use socket offloading and are not able to use socketpair (i.e. offload entire poll() call).

@SeppoTakalo
Copy link
Collaborator Author

This is a significant improvement, however I'm wondering - perhaps we should retain the old behaviour (timeout-based poll()) as a Kconfig option? For the sake of platforms, that use socket offloading and are not able to use socketpair (i.e. offload entire poll() call).

I think this makes sense.
I can keep all the same APIs, but have Kconfig selection about tickless or interval based operation. The tickless operation would depend on NET_SOCKETPAIR. Interval based operation would leave the lwm2m_engine_wake_up() as an empty function and would just add 500 ms cap into zsock_poll() call.

@SeppoTakalo
Copy link
Collaborator Author

SeppoTakalo commented Jul 28, 2023

Updated the first commit, so there is now Kconfig option CONFIG_LWM2M_TICKLESS.
If it is not selected, maximum timeout for zsock_poll() is 500 ms. So it works almost like it used to be.

Btw. Whoever is reviewing, all 3 commits can be reviewed independently. I tried to separate the logical changes so that you can see what changes I did for engine, and what changes are done into RD state machine.

rlubos
rlubos previously approved these changes Jul 28, 2023
Copy link
Contributor

@rlubos rlubos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, thanks. We should probably wait for conclusion on #60914 so we can get rid of heap dependency?

Allow socket-loop to wake up immediately, if there are changes,
instead of waiting for zsock_poll() to timeout.
This change makes engine more reactive and removes
hard coded timeout from zsock_poll().

Signed-off-by: Seppo Takalo <seppo.takalo@nordicsemi.no>
Engine now allows registering service callbacks that are
called only once on a given timestamp.
This allows tickless services to be developed.

Signed-off-by: Seppo Takalo <seppo.takalo@nordicsemi.no>
Call RD client service only when there is state transitioning.
Remove periodic 500 ms timer.

Signed-off-by: Seppo Takalo <seppo.takalo@nordicsemi.no>
@SeppoTakalo
Copy link
Collaborator Author

Now that #60914 is merged in, this PR does not add any dependency to heap.

I rebased on top of main branch and added overlay-tickless.conf that can be used to enable the new operating mode.

@carlescufi carlescufi merged commit 518bbc1 into zephyrproject-rtos:main Aug 1, 2023
18 checks passed
@SeppoTakalo SeppoTakalo deleted the lwm2m_tickless_upstream branch August 1, 2023 10:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants