Skip to content

Commit 5d027f4

Browse files
authored
Merge pull request #6857 from deepikabhavnani/cpu_stats
CPU Statistics
2 parents 02af950 + 25e2b88 commit 5d027f4

File tree

5 files changed

+234
-4
lines changed

5 files changed

+234
-4
lines changed
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
2+
/* mbed Microcontroller Library
3+
* Copyright (c) 2018 ARM Limited
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
#include "greentea-client/test_env.h"
19+
#include "unity/unity.h"
20+
#include "utest/utest.h"
21+
22+
#include "mbed.h"
23+
24+
#if !defined(MBED_CPU_STATS_ENABLED) || !defined(DEVICE_LOWPOWERTIMER) || !defined(DEVICE_SLEEP)
25+
#error [NOT_SUPPORTED] test not supported
26+
#endif
27+
28+
using namespace utest::v1;
29+
30+
DigitalOut led1(LED1);
31+
32+
#define MAX_THREAD_STACK 384
33+
#define SAMPLE_TIME 1000 // msec
34+
#define LOOP_TIME 2000 // msec
35+
36+
static int32_t wait_time = 5000;
37+
38+
static void busy_thread()
39+
{
40+
volatile uint64_t i = ~0;
41+
42+
while (i--) {
43+
led1 = !led1;
44+
wait_us(wait_time);
45+
}
46+
}
47+
48+
void get_cpu_usage()
49+
{
50+
static uint64_t prev_idle_time = 0;
51+
mbed_stats_cpu_t stats;
52+
53+
while (1) {
54+
mbed_stats_cpu_get(&stats);
55+
uint64_t diff = (stats.idle_time - prev_idle_time);
56+
uint8_t usage = 100 - ((diff * 100) / (SAMPLE_TIME * 1000));
57+
prev_idle_time = stats.idle_time;
58+
TEST_ASSERT_NOT_EQUAL(0, usage);
59+
Thread::wait(SAMPLE_TIME);
60+
}
61+
}
62+
63+
void test_cpu_info(void)
64+
{
65+
mbed_stats_cpu_t stats;
66+
// Additional read to make sure timer is initialized
67+
mbed_stats_cpu_get(&stats);
68+
Thread::wait(1);
69+
mbed_stats_cpu_get(&stats);
70+
TEST_ASSERT_NOT_EQUAL(0, stats.uptime);
71+
TEST_ASSERT_NOT_EQUAL(0, stats.idle_time);
72+
return;
73+
}
74+
75+
void test_cpu_load(void)
76+
{
77+
78+
Thread thread(osPriorityNormal, MAX_THREAD_STACK);
79+
Thread thread_stats(osPriorityNormal, MAX_THREAD_STACK);
80+
81+
thread.start(busy_thread);
82+
thread_stats.start(get_cpu_usage);
83+
84+
// Steadily increase the system load
85+
for (int count = 1; ; count++) {
86+
Thread::wait(LOOP_TIME);
87+
if (wait_time <= 0) {
88+
break;
89+
}
90+
wait_time -= 1000; // usec
91+
}
92+
thread.terminate();
93+
thread_stats.terminate();
94+
}
95+
96+
Case cases[] = {
97+
Case("Test CPU Info", test_cpu_info),
98+
Case("Test CPU load", test_cpu_load)
99+
};
100+
101+
utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
102+
{
103+
GREENTEA_SETUP(20, "default_auto");
104+
return greentea_test_setup_handler(number_of_cases);
105+
}
106+
107+
Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
108+
109+
int main()
110+
{
111+
Harness::run(specification);
112+
}

hal/mbed_sleep_manager.c

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,63 @@
2020
#include "sleep_api.h"
2121
#include "mbed_error.h"
2222
#include "mbed_debug.h"
23+
#include "mbed_stats.h"
24+
#include "lp_ticker_api.h"
2325
#include <limits.h>
2426
#include <stdio.h>
27+
#include "mbed_stats.h"
28+
2529

2630
#if DEVICE_SLEEP
2731

2832
// deep sleep locking counter. A target is allowed to deep sleep if counter == 0
2933
static uint16_t deep_sleep_lock = 0U;
34+
static us_timestamp_t sleep_time = 0;
35+
static us_timestamp_t deep_sleep_time = 0;
36+
37+
#if defined(MBED_CPU_STATS_ENABLED) && defined(DEVICE_LOWPOWERTIMER)
38+
static ticker_data_t *sleep_ticker = NULL;
39+
#endif
40+
41+
static inline us_timestamp_t read_us(void)
42+
{
43+
#if defined(MBED_CPU_STATS_ENABLED) && defined(DEVICE_LOWPOWERTIMER)
44+
if (NULL == sleep_ticker) {
45+
sleep_ticker = (ticker_data_t *)get_lp_ticker_data();
46+
}
47+
return ticker_read_us(sleep_ticker);
48+
#else
49+
return 0;
50+
#endif
51+
}
52+
53+
us_timestamp_t mbed_time_idle(void)
54+
{
55+
return (sleep_time + deep_sleep_time);
56+
}
57+
58+
us_timestamp_t mbed_uptime(void)
59+
{
60+
return read_us();
61+
}
62+
63+
us_timestamp_t mbed_time_sleep(void)
64+
{
65+
return sleep_time;
66+
}
67+
68+
us_timestamp_t mbed_time_deepsleep(void)
69+
{
70+
return deep_sleep_time;
71+
}
3072

3173
#ifdef MBED_SLEEP_TRACING_ENABLED
3274

3375
// Number of drivers that can be stored in the structure
3476
#define STATISTIC_COUNT 10
3577

3678
typedef struct sleep_statistic {
37-
const char* identifier;
79+
const char *identifier;
3880
uint8_t count;
3981
} sleep_statistic_t;
4082

@@ -83,7 +125,7 @@ static void sleep_tracker_print_stats(void)
83125
}
84126
}
85127

86-
void sleep_tracker_lock(const char* const filename, int line)
128+
void sleep_tracker_lock(const char *const filename, int line)
87129
{
88130
sleep_statistic_t *stat = sleep_tracker_find(filename);
89131

@@ -147,16 +189,27 @@ void sleep_manager_sleep_auto(void)
147189
sleep_tracker_print_stats();
148190
#endif
149191
core_util_critical_section_enter();
192+
us_timestamp_t start = read_us();
193+
bool deep = false;
194+
150195
// debug profile should keep debuggers attached, no deep sleep allowed
151196
#ifdef MBED_DEBUG
152197
hal_sleep();
153198
#else
154199
if (sleep_manager_can_deep_sleep()) {
200+
deep = true;
155201
hal_deepsleep();
156202
} else {
157203
hal_sleep();
158204
}
159205
#endif
206+
207+
us_timestamp_t end = read_us();
208+
if (true == deep) {
209+
deep_sleep_time += end - start;
210+
} else {
211+
sleep_time += end - start;
212+
}
160213
core_util_critical_section_exit();
161214
}
162215

platform/mbed_power_mgmt.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
#include "sleep_api.h"
2727
#include "mbed_toolchain.h"
28+
#include "hal/ticker_api.h"
2829
#include <stdbool.h>
2930

3031
#ifdef __cplusplus
@@ -205,6 +206,34 @@ static inline void system_reset(void)
205206
{
206207
NVIC_SystemReset();
207208
}
209+
210+
/** Provides the time spent in sleep mode since boot.
211+
*
212+
* @return Time spent in sleep
213+
* @note Works only if platform supports LP ticker.
214+
*/
215+
us_timestamp_t mbed_time_sleep(void);
216+
217+
/** Provides the time spent in deep sleep mode since boot.
218+
*
219+
* @return Time spent in deep sleep
220+
* @note Works only if platform supports LP ticker.
221+
*/
222+
us_timestamp_t mbed_time_deepsleep(void);
223+
224+
/** Provides the time spent in idle mode since boot.
225+
*
226+
* @return Idle thread time.
227+
* @note Works only if platform supports LP ticker.
228+
*/
229+
us_timestamp_t mbed_time_idle(void);
230+
231+
/** Provides the time since the system is up i.e. boot.
232+
*
233+
* @return System uptime.
234+
* @note Works only if platform supports LP ticker.
235+
*/
236+
us_timestamp_t mbed_uptime(void);
208237

209238
#ifdef __cplusplus
210239
}

platform/mbed_stats.c

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,34 @@
11
#include "mbed_assert.h"
22
#include "mbed_stats.h"
3+
#include "mbed_power_mgmt.h"
34
#include <string.h>
45
#include <stdlib.h>
56

67
#include "device.h"
78
#ifdef MBED_CONF_RTOS_PRESENT
89
#include "cmsis_os2.h"
9-
#elif defined(MBED_STACK_STATS_ENABLED) || defined(MBED_THREAD_STATS_ENABLED)
10+
#include "rtos_idle.h"
11+
#elif defined(MBED_STACK_STATS_ENABLED) || defined(MBED_THREAD_STATS_ENABLED) || defined(MBED_CPU_STATS_ENABLED)
1012
#warning Statistics are currently not supported without the rtos.
1113
#endif
1214

13-
// note: mbed_stats_heap_get defined in mbed_alloc_wrappers.cpp
15+
#if defined(MBED_CPU_STATS_ENABLED) && (!defined(DEVICE_LOWPOWERTIMER) || !defined(DEVICE_SLEEP))
16+
#warning CPU statistics are not supported without low power timer support.
17+
#endif
18+
19+
void mbed_stats_cpu_get(mbed_stats_cpu_t *stats)
20+
{
21+
MBED_ASSERT(stats != NULL);
22+
memset(stats, 0, sizeof(mbed_stats_cpu_t));
23+
#if defined(MBED_CPU_STATS_ENABLED) && defined(DEVICE_LOWPOWERTIMER) && defined(DEVICE_SLEEP)
24+
stats->uptime = mbed_uptime();
25+
stats->idle_time = mbed_time_idle();
26+
stats->sleep_time = mbed_time_sleep();
27+
stats->deep_sleep_time = mbed_time_deepsleep();
28+
#endif
29+
}
1430

31+
// note: mbed_stats_heap_get defined in mbed_alloc_wrappers.cpp
1532
void mbed_stats_stack_get(mbed_stats_stack_t *stats)
1633
{
1734
MBED_ASSERT(stats != NULL);

platform/mbed_stats.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#define MBED_STATS_H
2525
#include <stdint.h>
2626
#include <stddef.h>
27+
#include "hal/ticker_api.h"
2728

2829
#ifdef __cplusplus
2930
extern "C" {
@@ -32,6 +33,7 @@ extern "C" {
3233
#ifdef MBED_ALL_STATS_ENABLED
3334
#define MBED_SYS_STATS_ENABLED 1
3435
#define MBED_STACK_STATS_ENABLED 1
36+
#define MBED_CPU_STATS_ENABLED 1
3537
#define MBED_HEAP_STATS_ENABLED 1
3638
#define MBED_THREAD_STATS_ENABLED 1
3739
#endif
@@ -83,6 +85,23 @@ void mbed_stats_stack_get(mbed_stats_stack_t *stats);
8385
*/
8486
size_t mbed_stats_stack_get_each(mbed_stats_stack_t *stats, size_t count);
8587

88+
/**
89+
* struct mbed_stats_cpu_t definition
90+
*/
91+
typedef struct {
92+
us_timestamp_t uptime; /**< Time since system is up and running */
93+
us_timestamp_t idle_time; /**< Time spent in idle thread since system is up and running */
94+
us_timestamp_t sleep_time; /**< Time spent in sleep since system is up and running */
95+
us_timestamp_t deep_sleep_time; /**< Time spent in deep sleep since system is up and running */
96+
} mbed_stats_cpu_t;
97+
98+
/**
99+
* Fill the passed in CPU stat structure with CPU statistics.
100+
*
101+
* @param stats A pointer to the mbed_stats_cpu_t structure to fill
102+
*/
103+
void mbed_stats_cpu_get(mbed_stats_cpu_t *stats);
104+
86105
/**
87106
* struct mbed_stats_thread_t definition
88107
*/

0 commit comments

Comments
 (0)