Skip to content

Commit

Permalink
Merge pull request #6857 from deepikabhavnani/cpu_stats
Browse files Browse the repository at this point in the history
CPU Statistics
  • Loading branch information
0xc0170 committed May 22, 2018
2 parents 02af950 + 25e2b88 commit 5d027f4
Show file tree
Hide file tree
Showing 5 changed files with 234 additions and 4 deletions.
112 changes: 112 additions & 0 deletions TESTS/mbed_platform/stats_cpu/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@

/* mbed Microcontroller Library
* Copyright (c) 2018 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "greentea-client/test_env.h"
#include "unity/unity.h"
#include "utest/utest.h"

#include "mbed.h"

#if !defined(MBED_CPU_STATS_ENABLED) || !defined(DEVICE_LOWPOWERTIMER) || !defined(DEVICE_SLEEP)
#error [NOT_SUPPORTED] test not supported
#endif

using namespace utest::v1;

DigitalOut led1(LED1);

#define MAX_THREAD_STACK 384
#define SAMPLE_TIME 1000 // msec
#define LOOP_TIME 2000 // msec

static int32_t wait_time = 5000;

static void busy_thread()
{
volatile uint64_t i = ~0;

while (i--) {
led1 = !led1;
wait_us(wait_time);
}
}

void get_cpu_usage()
{
static uint64_t prev_idle_time = 0;
mbed_stats_cpu_t stats;

while (1) {
mbed_stats_cpu_get(&stats);
uint64_t diff = (stats.idle_time - prev_idle_time);
uint8_t usage = 100 - ((diff * 100) / (SAMPLE_TIME * 1000));
prev_idle_time = stats.idle_time;
TEST_ASSERT_NOT_EQUAL(0, usage);
Thread::wait(SAMPLE_TIME);
}
}

void test_cpu_info(void)
{
mbed_stats_cpu_t stats;
// Additional read to make sure timer is initialized
mbed_stats_cpu_get(&stats);
Thread::wait(1);
mbed_stats_cpu_get(&stats);
TEST_ASSERT_NOT_EQUAL(0, stats.uptime);
TEST_ASSERT_NOT_EQUAL(0, stats.idle_time);
return;
}

void test_cpu_load(void)
{

Thread thread(osPriorityNormal, MAX_THREAD_STACK);
Thread thread_stats(osPriorityNormal, MAX_THREAD_STACK);

thread.start(busy_thread);
thread_stats.start(get_cpu_usage);

// Steadily increase the system load
for (int count = 1; ; count++) {
Thread::wait(LOOP_TIME);
if (wait_time <= 0) {
break;
}
wait_time -= 1000; // usec
}
thread.terminate();
thread_stats.terminate();
}

Case cases[] = {
Case("Test CPU Info", test_cpu_info),
Case("Test CPU load", test_cpu_load)
};

utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(20, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}

Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);

int main()
{
Harness::run(specification);
}
57 changes: 55 additions & 2 deletions hal/mbed_sleep_manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,63 @@
#include "sleep_api.h"
#include "mbed_error.h"
#include "mbed_debug.h"
#include "mbed_stats.h"
#include "lp_ticker_api.h"
#include <limits.h>
#include <stdio.h>
#include "mbed_stats.h"


#if DEVICE_SLEEP

// deep sleep locking counter. A target is allowed to deep sleep if counter == 0
static uint16_t deep_sleep_lock = 0U;
static us_timestamp_t sleep_time = 0;
static us_timestamp_t deep_sleep_time = 0;

#if defined(MBED_CPU_STATS_ENABLED) && defined(DEVICE_LOWPOWERTIMER)
static ticker_data_t *sleep_ticker = NULL;
#endif

static inline us_timestamp_t read_us(void)
{
#if defined(MBED_CPU_STATS_ENABLED) && defined(DEVICE_LOWPOWERTIMER)
if (NULL == sleep_ticker) {
sleep_ticker = (ticker_data_t *)get_lp_ticker_data();
}
return ticker_read_us(sleep_ticker);
#else
return 0;
#endif
}

us_timestamp_t mbed_time_idle(void)
{
return (sleep_time + deep_sleep_time);
}

us_timestamp_t mbed_uptime(void)
{
return read_us();
}

us_timestamp_t mbed_time_sleep(void)
{
return sleep_time;
}

us_timestamp_t mbed_time_deepsleep(void)
{
return deep_sleep_time;
}

#ifdef MBED_SLEEP_TRACING_ENABLED

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

typedef struct sleep_statistic {
const char* identifier;
const char *identifier;
uint8_t count;
} sleep_statistic_t;

Expand Down Expand Up @@ -83,7 +125,7 @@ static void sleep_tracker_print_stats(void)
}
}

void sleep_tracker_lock(const char* const filename, int line)
void sleep_tracker_lock(const char *const filename, int line)
{
sleep_statistic_t *stat = sleep_tracker_find(filename);

Expand Down Expand Up @@ -147,16 +189,27 @@ void sleep_manager_sleep_auto(void)
sleep_tracker_print_stats();
#endif
core_util_critical_section_enter();
us_timestamp_t start = read_us();
bool deep = false;

// debug profile should keep debuggers attached, no deep sleep allowed
#ifdef MBED_DEBUG
hal_sleep();
#else
if (sleep_manager_can_deep_sleep()) {
deep = true;
hal_deepsleep();
} else {
hal_sleep();
}
#endif

us_timestamp_t end = read_us();
if (true == deep) {
deep_sleep_time += end - start;
} else {
sleep_time += end - start;
}
core_util_critical_section_exit();
}

Expand Down
29 changes: 29 additions & 0 deletions platform/mbed_power_mgmt.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

#include "sleep_api.h"
#include "mbed_toolchain.h"
#include "hal/ticker_api.h"
#include <stdbool.h>

#ifdef __cplusplus
Expand Down Expand Up @@ -205,6 +206,34 @@ static inline void system_reset(void)
{
NVIC_SystemReset();
}

/** Provides the time spent in sleep mode since boot.
*
* @return Time spent in sleep
* @note Works only if platform supports LP ticker.
*/
us_timestamp_t mbed_time_sleep(void);

/** Provides the time spent in deep sleep mode since boot.
*
* @return Time spent in deep sleep
* @note Works only if platform supports LP ticker.
*/
us_timestamp_t mbed_time_deepsleep(void);

/** Provides the time spent in idle mode since boot.
*
* @return Idle thread time.
* @note Works only if platform supports LP ticker.
*/
us_timestamp_t mbed_time_idle(void);

/** Provides the time since the system is up i.e. boot.
*
* @return System uptime.
* @note Works only if platform supports LP ticker.
*/
us_timestamp_t mbed_uptime(void);

#ifdef __cplusplus
}
Expand Down
21 changes: 19 additions & 2 deletions platform/mbed_stats.c
Original file line number Diff line number Diff line change
@@ -1,17 +1,34 @@
#include "mbed_assert.h"
#include "mbed_stats.h"
#include "mbed_power_mgmt.h"
#include <string.h>
#include <stdlib.h>

#include "device.h"
#ifdef MBED_CONF_RTOS_PRESENT
#include "cmsis_os2.h"
#elif defined(MBED_STACK_STATS_ENABLED) || defined(MBED_THREAD_STATS_ENABLED)
#include "rtos_idle.h"
#elif defined(MBED_STACK_STATS_ENABLED) || defined(MBED_THREAD_STATS_ENABLED) || defined(MBED_CPU_STATS_ENABLED)
#warning Statistics are currently not supported without the rtos.
#endif

// note: mbed_stats_heap_get defined in mbed_alloc_wrappers.cpp
#if defined(MBED_CPU_STATS_ENABLED) && (!defined(DEVICE_LOWPOWERTIMER) || !defined(DEVICE_SLEEP))
#warning CPU statistics are not supported without low power timer support.
#endif

void mbed_stats_cpu_get(mbed_stats_cpu_t *stats)
{
MBED_ASSERT(stats != NULL);
memset(stats, 0, sizeof(mbed_stats_cpu_t));
#if defined(MBED_CPU_STATS_ENABLED) && defined(DEVICE_LOWPOWERTIMER) && defined(DEVICE_SLEEP)
stats->uptime = mbed_uptime();
stats->idle_time = mbed_time_idle();
stats->sleep_time = mbed_time_sleep();
stats->deep_sleep_time = mbed_time_deepsleep();
#endif
}

// note: mbed_stats_heap_get defined in mbed_alloc_wrappers.cpp
void mbed_stats_stack_get(mbed_stats_stack_t *stats)
{
MBED_ASSERT(stats != NULL);
Expand Down
19 changes: 19 additions & 0 deletions platform/mbed_stats.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#define MBED_STATS_H
#include <stdint.h>
#include <stddef.h>
#include "hal/ticker_api.h"

#ifdef __cplusplus
extern "C" {
Expand All @@ -32,6 +33,7 @@ extern "C" {
#ifdef MBED_ALL_STATS_ENABLED
#define MBED_SYS_STATS_ENABLED 1
#define MBED_STACK_STATS_ENABLED 1
#define MBED_CPU_STATS_ENABLED 1
#define MBED_HEAP_STATS_ENABLED 1
#define MBED_THREAD_STATS_ENABLED 1
#endif
Expand Down Expand Up @@ -83,6 +85,23 @@ void mbed_stats_stack_get(mbed_stats_stack_t *stats);
*/
size_t mbed_stats_stack_get_each(mbed_stats_stack_t *stats, size_t count);

/**
* struct mbed_stats_cpu_t definition
*/
typedef struct {
us_timestamp_t uptime; /**< Time since system is up and running */
us_timestamp_t idle_time; /**< Time spent in idle thread since system is up and running */
us_timestamp_t sleep_time; /**< Time spent in sleep since system is up and running */
us_timestamp_t deep_sleep_time; /**< Time spent in deep sleep since system is up and running */
} mbed_stats_cpu_t;

/**
* Fill the passed in CPU stat structure with CPU statistics.
*
* @param stats A pointer to the mbed_stats_cpu_t structure to fill
*/
void mbed_stats_cpu_get(mbed_stats_cpu_t *stats);

/**
* struct mbed_stats_thread_t definition
*/
Expand Down

0 comments on commit 5d027f4

Please sign in to comment.