mirror of https://github.com/ARMmbed/mbed-os.git
commit
5d027f4e27
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -20,13 +20,55 @@
|
|||
#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
|
||||
|
||||
|
|
@ -34,7 +76,7 @@ static uint16_t deep_sleep_lock = 0U;
|
|||
#define STATISTIC_COUNT 10
|
||||
|
||||
typedef struct sleep_statistic {
|
||||
const char* identifier;
|
||||
const char *identifier;
|
||||
uint8_t count;
|
||||
} sleep_statistic_t;
|
||||
|
||||
|
|
@ -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);
|
||||
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
#include "sleep_api.h"
|
||||
#include "mbed_toolchain.h"
|
||||
#include "hal/ticker_api.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#define MBED_STATS_H
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include "hal/ticker_api.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
*/
|
||||
|
|
|
|||
Loading…
Reference in New Issue