Morse Micro IoT SDK  2.10.4
wnm_sleep.c
Go to the documentation of this file.
1/*
2 * Copyright 2023 Morse Micro
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
27#include <string.h>
28#include "mmhal_app.h"
29#include "mmosal.h"
30#include "mmwlan.h"
31#include "mmping.h"
32#include "mmconfig.h"
33#include "mmutils.h"
34
35#include "mmipal.h"
36
37#include "mm_app_common.h"
38
39/* Default Application configurations. These are used if the required parameters cannot be found in
40 * the configstore*/
41#ifndef DEFAULT_PING_COUNT
43#define DEFAULT_PING_COUNT 10
44#endif
45#ifndef DEFAULT_PING_DATA_SIZE
47#define DEFAULT_PING_DATA_SIZE 56
48#endif
49#ifndef DEFAULT_PING_INTERVAL_MS
51#define DEFAULT_PING_INTERVAL_MS 1000
52#endif
53#ifndef DEFAULT_WNM_SLEEP_DURATION_MS
55#define DEFAULT_WNM_SLEEP_DURATION_MS 20000
56#endif
57#ifndef POST_PING_DELAY_MS
59#define POST_PING_DELAY_MS 10000
60#endif
61#ifndef UPDATE_INTERVAL_MS
64#define UPDATE_INTERVAL_MS (5000)
65#endif
66
70#define MIN_WNM_SLEEP_EXIT_STATE_DURATION_MS 20
71
72#if defined(ENABLE_PWR_MEAS) && ENABLE_PWR_MEAS
74#define PWR_MEAS_DELAY_MS(delay_ms) mmosal_task_sleep(delay_ms)
76#define SET_DEBUG_STATE(state) mmhal_set_debug_pins(MMHAL_ALL_DEBUG_PINS, state);
77#else
79#define PWR_MEAS_DELAY_MS(delay_ms) MM_UNUSED(delay_ms)
81#define SET_DEBUG_STATE(state) MM_UNUSED(state)
82#endif
83
91{
120};
121
129static void execute_ping_request(int iteration)
130{
131 struct mmping_args args = MMPING_ARGS_DEFAULT;
132
134
135 /* Get the target IP */
137 enum mmipal_status status = mmipal_get_ip_config(&ip_config);
138 if (status == MMIPAL_SUCCESS)
139 {
140 memcpy(args.ping_target, ip_config.gateway_addr, sizeof(ip_config.gateway_addr));
141 }
142 else
143 {
144 printf("Failed to retrieve IP config\n");
145 }
146 /* If ping.target is set, we use it as an override */
147 (void)mmconfig_read_string("ping.target", args.ping_target, sizeof(args.ping_target));
148
149 status = mmipal_get_local_addr(args.ping_src, args.ping_target);
150 if (status != MMIPAL_SUCCESS)
151 {
152 printf("failed to get local address for PING\n");
153 }
154
156 mmconfig_read_uint32("ping.count", &args.ping_count);
157
159 mmconfig_read_uint32("ping.target", &args.ping_size);
160
162 mmconfig_read_uint32("ping.interval", &args.ping_interval_ms);
163
164 mmping_start(&args);
165 printf("\nPing %s %lu(%lu) bytes of data.\n",
166 args.ping_target,
167 args.ping_size,
169
170 struct mmping_stats stats;
171 uint32_t next_update_time_ms = mmosal_get_time_ms() + UPDATE_INTERVAL_MS;
172 unsigned last_ping_recv_count = 0;
173 mmping_stats(&stats);
174 while (stats.ping_is_running)
175 {
177 mmping_stats(&stats);
178 if (stats.ping_recv_count != last_ping_recv_count ||
179 mmosal_time_has_passed(next_update_time_ms))
180 {
181 printf("(%s) packets transmitted/received = %lu/%lu, "
182 "round-trip min/avg/max = %lu/%lu/%lu ms\n",
183 stats.ping_receiver,
184 stats.ping_total_count,
185 stats.ping_recv_count,
186 stats.ping_min_time_ms,
187 stats.ping_avg_time_ms,
188 stats.ping_max_time_ms);
189 last_ping_recv_count = stats.ping_recv_count;
190 next_update_time_ms = mmosal_get_time_ms() + UPDATE_INTERVAL_MS;
191 }
192 }
193 uint32_t loss = 0;
194 if (stats.ping_total_count == 0)
195 {
196 loss = 0;
197 }
198 else
199 {
200 loss = (1000 *
201 (stats.ping_total_count - stats.ping_recv_count) *
202 100 /
203 stats.ping_total_count);
204 }
205
207
208 printf("\n--- %s ping statistics ---\n%lu packets transmitted, %lu packets received, ",
209 stats.ping_receiver,
210 stats.ping_total_count,
211 stats.ping_recv_count);
212 printf("%lu.%03lu%% packet loss\nround-trip min/avg/max = %lu/%lu/%lu ms\n",
213 loss / 1000,
214 loss % 1000,
215 stats.ping_min_time_ms,
216 stats.ping_avg_time_ms,
217 stats.ping_max_time_ms);
218}
219
225static void execute_wnm_sleep(uint32_t wnm_sleep_duration_ms)
226{
227 enum mmwlan_status status = MMWLAN_ERROR;
228
229 printf("\nEntering WNM sleep with chip power down disabled\n");
230 printf("Expected sleep time %lums.\n", wnm_sleep_duration_ms);
231 /* Delay to allow printf's to settle so we measure only idle current */
233
235
236 uint32_t timestamp = mmosal_get_time_ms();
237 status = mmwlan_set_wnm_sleep_enabled(true);
238 uint32_t wnm_sleep_enable_duration_ms = mmosal_get_time_ms() - timestamp;
239 if (status != MMWLAN_SUCCESS)
240 {
241 printf("Failed to enable WNM sleep\n");
242 return;
243 }
244
245 mmosal_task_sleep(wnm_sleep_duration_ms);
246
247 timestamp = mmosal_get_time_ms();
248
250 status = mmwlan_set_wnm_sleep_enabled(false);
251
252 uint32_t sleep_exit_duration = mmosal_get_time_ms() - timestamp;
253 int32_t exit_duration_delta = MIN_WNM_SLEEP_EXIT_STATE_DURATION_MS - sleep_exit_duration;
254 if (exit_duration_delta > 0)
255 {
256 PWR_MEAS_DELAY_MS(exit_duration_delta);
257 }
259
260 if (status == MMWLAN_SUCCESS)
261 {
262 printf("\nEnter WNM sleep took %lu ms.\n", wnm_sleep_enable_duration_ms);
263 printf("\nExit WNM sleep took %lu ms.\n", sleep_exit_duration);
264 }
265 else
266 {
267 printf("Failed to disable WNM sleep\n");
268 }
269}
270
278static void execute_wnm_sleep_ext(uint32_t wnm_sleep_duration_ms)
279{
280 enum mmwlan_status status = MMWLAN_ERROR;
281 struct mmwlan_set_wnm_sleep_enabled_args wnm_sleep_args =
283
284 printf("\nEntering WNM sleep with chip power down enabled.\n");
285 printf("Expected sleep time %lums.\n", wnm_sleep_duration_ms);
286 /* Delay to allow printf's to settle so we measure only idle current */
289
290 uint32_t timestamp = mmosal_get_time_ms();
291 wnm_sleep_args.wnm_sleep_enabled = true;
292 wnm_sleep_args.chip_powerdown_enabled = true;
293 status = mmwlan_set_wnm_sleep_enabled_ext(&wnm_sleep_args);
294 uint32_t wnm_sleep_enable_duration_ms = mmosal_get_time_ms() - timestamp;
295 if (status != MMWLAN_SUCCESS)
296 {
297 printf("Failed to enable WNM sleep\n");
298 return;
299 }
300
301 mmosal_task_sleep(wnm_sleep_duration_ms);
302
303 timestamp = mmosal_get_time_ms();
304 wnm_sleep_args.wnm_sleep_enabled = false;
305
307 status = mmwlan_set_wnm_sleep_enabled_ext(&wnm_sleep_args);
308
309 uint32_t sleep_exit_duration = mmosal_get_time_ms() - timestamp;
310 int32_t exit_duration_delta = MIN_WNM_SLEEP_EXIT_STATE_DURATION_MS - sleep_exit_duration;
311 if (exit_duration_delta > 0)
312 {
313 PWR_MEAS_DELAY_MS(exit_duration_delta);
314 }
315
317
318 if (status == MMWLAN_SUCCESS)
319 {
320 printf("\nEnter WNM sleep took %lu ms.\n", wnm_sleep_enable_duration_ms);
321 printf("\nExit WNM sleep took %lu ms.\n", sleep_exit_duration);
322 }
323 else
324 {
325 printf("Failed to disable WNM sleep\n");
326 }
327}
328
333void app_init(void)
334{
335 printf("\n\nMorse WNM Sleep Demo (Built " __DATE__ " " __TIME__ ")\n\n");
336
337 /* Initialize and connect to Wi-Fi, blocks till connected */
339
341
343
345
347
348 /* Delay to allow communications to settle so we measure only idle current */
350
351 uint32_t wnm_sleep_duration_ms = DEFAULT_WNM_SLEEP_DURATION_MS;
352 mmconfig_read_uint32("wlan.wnm_sleep_duration_ms", &wnm_sleep_duration_ms);
353
355
356 /* The following demonstrates basic WNM Sleep functionality. The MM chip remains powered,
357 * but does not wake up to receive beacons. */
358 execute_wnm_sleep(wnm_sleep_duration_ms);
359
361
362 /* The following demonstrates extended WNM Sleep API that allows the chip to be shutdown
363 * while in WNM Sleep. */
364 execute_wnm_sleep_ext(wnm_sleep_duration_ms);
365
366 /* Delay to allow communications to settle so we measure only idle current */
368
370
371 /* Disconnect from Wi-Fi */
373}
int mmconfig_read_string(const char *key, char *buffer, int bufsize)
Returns the persistent store string value identified by the key.
int mmconfig_read_uint32(const char *key, uint32_t *value)
Returns the unsigned integer stored in persistent store identified by the key.
#define MMIPAL_IP_CONFIG_DEFAULT
Initializer for mmipal_ip_config.
Definition: mmipal.h:109
mmipal_status
Enumeration of status codes returned by MMIPAL functions.
Definition: mmipal.h:43
enum mmipal_status mmipal_get_ip_config(struct mmipal_ip_config *config)
Get the IP configurations.
enum mmipal_status mmipal_get_local_addr(mmipal_ip_addr_t local_addr, const mmipal_ip_addr_t dest_addr)
Gets the local address for the MMWLAN interface that is appropriate for a given destination address.
@ MMIPAL_SUCCESS
Completed successfully.
Definition: mmipal.h:45
void mmosal_task_sleep(uint32_t duration_ms)
Sleep for a period of time, yielding during that time.
uint32_t mmosal_get_time_ms(void)
Get the system time in milliseconds.
static bool mmosal_time_has_passed(uint32_t t)
Check if the given time has already passed.
Definition: mmosal.h:727
#define MMPING_ICMP_ECHO_HDR_LEN
Length of the ICMP echo header in octets.
Definition: mmping.h:65
uint16_t mmping_start(const struct mmping_args *args)
Initialize ping parameters and start ping.
#define MMPING_ARGS_DEFAULT
Initializer for mmping_args.
Definition: mmping.h:96
void mmping_stats(struct mmping_stats *stats)
Get Ping Statistics.
static enum mmwlan_status mmwlan_set_wnm_sleep_enabled(bool wnm_sleep_enabled)
Sets whether WNM sleep mode is enabled.
Definition: mmwlan.h:2114
#define MMWLAN_SET_WNM_SLEEP_ENABLED_ARGS_INIT
Initializer for mmwlan_set_wnm_sleep_enabled_args.
Definition: mmwlan.h:2058
enum mmwlan_status mmwlan_set_wnm_sleep_enabled_ext(const struct mmwlan_set_wnm_sleep_enabled_args *args)
Sets extended WNM sleep mode.
mmwlan_status
Enumeration of status return codes.
Definition: mmwlan.h:51
@ MMWLAN_SUCCESS
The operation was successful.
Definition: mmwlan.h:53
@ MMWLAN_ERROR
The operation failed with an unspecified error.
Definition: mmwlan.h:55
Morse Micro application helper routines for initializing/de-initializing the Wireless LAN interface a...
void app_wlan_stop(void)
Disconnects from Wi-Fi and de-initializes the WLAN interface.
void app_wlan_init(void)
Initializes the WLAN interface (and dependencies) using settings specified in the config store.
void app_wlan_start(void)
Starts the WLAN interface and connects to Wi-Fi using settings specified in the config store.
debug_state
Enumeration of debug states that will be reflected on debug pins.
Definition: ping.c:75
IPv4 configuration structure.
Definition: mmipal.h:97
mmipal_ip_addr_t gateway_addr
Gateway address.
Definition: mmipal.h:105
Ping request arguments data structure.
Definition: mmping.h:78
uint32_t ping_size
Specifies the data packet size in bytes excluding 8 bytes ICMP header.
Definition: mmping.h:92
char ping_src[MMPING_IPADDR_MAXLEN]
String representation of the local IP address.
Definition: mmping.h:80
char ping_target[MMPING_IPADDR_MAXLEN]
String representation of the IP address of the ping target.
Definition: mmping.h:82
uint32_t ping_interval_ms
The time interval between ping requests (in milliseconds)
Definition: mmping.h:84
uint32_t ping_count
This specifies the number of ping requests to send before terminating the session.
Definition: mmping.h:90
Data structure to store ping results.
Definition: mmping.h:109
uint32_t ping_avg_time_ms
The average latency in ms between request sent and response received.
Definition: mmping.h:119
bool ping_is_running
Stores the ping running status.
Definition: mmping.h:123
uint32_t ping_min_time_ms
The minimum latency in ms between request sent and response received.
Definition: mmping.h:117
uint32_t ping_max_time_ms
The maximum latency in ms between request sent and response received.
Definition: mmping.h:121
char ping_receiver[MMPING_IPADDR_MAXLEN]
String representation of the IP address of the ping receiver.
Definition: mmping.h:111
uint32_t ping_recv_count
The number of ping responses received.
Definition: mmping.h:115
uint32_t ping_total_count
Total number of requests sent.
Definition: mmping.h:113
Structure for storing WNM sleep extended arguments.
Definition: mmwlan.h:2042
bool wnm_sleep_enabled
Boolean indicating whether WNM sleep is enabled.
Definition: mmwlan.h:2044
bool chip_powerdown_enabled
Boolean indicating whether chip should be powered down during WNM sleep.
Definition: mmwlan.h:2046
#define SET_DEBUG_STATE(state)
Disable GPIO writing if not measuring power consumption.
Definition: wnm_sleep.c:81
static void execute_wnm_sleep(uint32_t wnm_sleep_duration_ms)
Function to execute WNM sleep.
Definition: wnm_sleep.c:225
#define MIN_WNM_SLEEP_EXIT_STATE_DURATION_MS
Minimum duration for WNM_SLEEP_EXIT state.
Definition: wnm_sleep.c:70
#define DEFAULT_PING_DATA_SIZE
Size of the ping request data, excluding 8-byte ICMP header.
Definition: wnm_sleep.c:47
#define DEFAULT_PING_INTERVAL_MS
Interval between successive ping requests.
Definition: wnm_sleep.c:51
#define PWR_MEAS_DELAY_MS(delay_ms)
Disable delays which are only useful for power consumption accuracy.
Definition: wnm_sleep.c:79
#define DEFAULT_WNM_SLEEP_DURATION_MS
Duration to remain in wnm sleep between transmissions.
Definition: wnm_sleep.c:55
static void execute_ping_request(int iteration)
Function to execute ping request.
Definition: wnm_sleep.c:129
#define UPDATE_INTERVAL_MS
Interval (in milliseconds) at which to provide updates when the receive count has not changed.
Definition: wnm_sleep.c:64
void app_init(void)
Main entry point to the application.
Definition: wnm_sleep.c:333
static void execute_wnm_sleep_ext(uint32_t wnm_sleep_duration_ms)
Function to enter WNM Sleep and power off the MM chip while asleep.
Definition: wnm_sleep.c:278
@ DEBUG_STATE_INIT
Initial state at startup.
Definition: wnm_sleep.c:93
@ DEBUG_STATE_WNM_SLEEP_POWER_DOWN
Indicates that WNM sleep is in progress with chip powered down.
Definition: wnm_sleep.c:113
@ DEBUG_STATE_PINGING_0
Indicates that the ping is in progress.
Definition: wnm_sleep.c:99
@ DEBUG_STATE_WNM_SLEEP_DONE
Indicates that WNM sleep has completed.
Definition: wnm_sleep.c:107
@ DEBUG_STATE_PING_0_DONE
Indicates that the ping has completed.
Definition: wnm_sleep.c:101
@ DEBUG_STATE_CONNECTED
Indicates we are connected to the AP.
Definition: wnm_sleep.c:97
@ DEBUG_STATE_PING_1_DONE
Indicates that the ping has completed.
Definition: wnm_sleep.c:111
@ DEBUG_STATE_EXITING_WNM_SLEEP_POWER_DOWN
Indicates that we are exiting WNM sleep with chip powered down.
Definition: wnm_sleep.c:115
@ DEBUG_STATE_WNM_SLEEP
Indicates that WNM sleep is in progress.
Definition: wnm_sleep.c:103
@ DEBUG_STATE_PINGING_1
Indicates that the ping is in progress.
Definition: wnm_sleep.c:109
@ DEBUG_STATE_WNM_SLEEP_POWER_DOWN_DONE
Indicates that WNM sleep with chip powered down has completed.
Definition: wnm_sleep.c:117
@ DEBUG_STATE_EXITING_WNM_SLEEP
Indicates that we are exiting WNM sleep.
Definition: wnm_sleep.c:105
@ DEBUG_STATE_TERMINATING
Indicates that we are disconnecting from the AP.
Definition: wnm_sleep.c:119
@ DEBUG_STATE_CONNECTING
Indicates we are connecting to the AP.
Definition: wnm_sleep.c:95
#define DEFAULT_PING_COUNT
Number of ping requests to send.
Definition: wnm_sleep.c:43