Skip to content

Add basic stats reporting to blinky. #144

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

Merged
merged 1 commit into from
Nov 28, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
148 changes: 129 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Getting started with Blinky on mbed OS
# Getting started example for Mbed OS

This guide reviews the steps required to get Blinky working on an mbed OS platform.
This guide reviews the steps required to get Blinky with the addition of dynamic OS statistics working on an Mbed OS platform.

Please install [mbed CLI](https://github.com/ARMmbed/mbed-cli#installing-mbed-cli).

Expand All @@ -26,22 +26,26 @@ Your PC may take a few minutes to compile your code. At the end, you see the fol
```
[snip]
+----------------------------+-------+-------+------+
| Module | .text | .data | .bss |
+----------------------------+-------+-------+------+
| Misc | 13939 | 24 | 1372 |
| core/hal | 16993 | 96 | 296 |
| core/rtos | 7384 | 92 | 4204 |
| features/FEATURE_IPV4 | 80 | 0 | 176 |
| frameworks/greentea-client | 1830 | 60 | 44 |
| frameworks/utest | 2392 | 512 | 292 |
| Subtotals | 42618 | 784 | 6384 |
+----------------------------+-------+-------+------+
Allocated Heap: unknown
Allocated Stack: unknown
Total Static RAM memory (data + bss): 7168 bytes
Total RAM memory (data + bss + heap + stack): 7168 bytes
Total Flash memory (text + data + misc): 43402 bytes
Image: .\.build\K64F\ARM\mbed-os-example-blinky.bin
| Module | .text | .data | .bss |
|--------------------|-----------|----------|----------|
| [fill] | 98(+0) | 0(+0) | 2211(+0) |
| [lib]/c.a | 27835(+0) | 2472(+0) | 89(+0) |
| [lib]/gcc.a | 3168(+0) | 0(+0) | 0(+0) |
| [lib]/misc | 248(+0) | 8(+0) | 28(+0) |
| [lib]/nosys.a | 32(+0) | 0(+0) | 0(+0) |
| main.o | 924(+0) | 0(+0) | 12(+0) |
| mbed-os/components | 134(+0) | 0(+0) | 0(+0) |
| mbed-os/drivers | 56(+0) | 0(+0) | 0(+0) |
| mbed-os/features | 42(+0) | 0(+0) | 184(+0) |
| mbed-os/hal | 2087(+0) | 8(+0) | 152(+0) |
| mbed-os/platform | 3633(+0) | 260(+0) | 209(+0) |
| mbed-os/rtos | 9370(+0) | 168(+0) | 6053(+0) |
| mbed-os/targets | 9536(+0) | 12(+0) | 382(+0) |
| Subtotals | 57163(+0) | 2928(+0) | 9320(+0) |
Total Static RAM memory (data + bss): 12248(+0) bytes
Total Flash memory (text + data): 60091(+0) bytes

Image: ./BUILD/K64F/GCC_ARM/mbed-os-example-blinky.bin
```

### Program your board
Expand All @@ -50,8 +54,114 @@ Image: .\.build\K64F\ARM\mbed-os-example-blinky.bin
1. Copy the binary file to the mbed device.
1. Press the reset button to start the program.

The LED on your platform turns on and off.
The LED on your platform turns on and off. The main thread will additionally take a snapshot of the device's runtime statistics and display it over serial to your PC. The snapshot includes:

* System Information:
* Mbed OS Version: Will currently default to 999999
* Compiler ID
* ARM = 1
* GCC_ARM = 2
* IAR = 3
* [CPUID Register Information](#cpuid-register-information)
* [Compiler Version](#compiler-version)
* CPU Statistics
* Percentage of runtime that the device has spent awake versus in sleep
* Heap Statistics
* Current heap size
* Max heap size which refers to the largest the heap has grown to
* Thread Statistics
* Provides information on all running threads in the OS including
* Thread ID
* Thread Name
* Thread State
* Thread Priority
* Thread Stack Size
* Thread Stack Space

#### Compiler Version

| Compiler | Version Layout |
| -------- | -------------- |
| ARM | PVVbbbb (P = Major; VV = Minor; bbbb = build number) |
| GCC | VVRRPP (VV = Version; RR = Revision; PP = Patch) |
| IAR | VRRRPPP (V = Version; RRR = Revision; PPP = Patch) |

#### CPUID Register Information

| Bit Field | Field Description | Values |
| --------- | ----------------- | ------ |
|[31:24] | Implementer | 0x41 = ARM |
|[23:20] | Variant | Major revision 0x0 = Revision 0 |
|[19:16] | Architecture | 0xC = Baseline Architecture |
| | | 0xF = Constant (Mainline Architecture) |
|[15:4] | Part Number | 0xC20 = Cortex-M0 |
| | | 0xC60 = Cortex-M0+ |
| | | 0xC23 = Cortex-M3 |
| | | 0xC24 = Cortex-M4 |
| | | 0xC27 = Cortex-M7 |
| | | 0xD20 = Cortex-M23 |
| | | 0xD21 = Cortex-M33 |
|[3:0] | Revision | Minor revision: 0x1 = Patch 1 |



You can view individual examples and additional API information of the statistics collection tools at the bottom of the page in the [related links section](#related-links).


### Output

To view the serial output you can use any terminal client of your choosing such as [PuTTY](http://www.putty.org/) or [CoolTerm](http://freeware.the-meiers.org/).

The default baud rate for this application is set to `115200` and may be modified in the `mbed_app.json` file.

You can find more information on the Mbed OS configuration tools and serail communication in Mbed OS in the related [related links section](#related-links).

The output should contain the following block transmitted at the blinking LED frequency (actual values may vary depending on your target, build profile, and toolchain):

```
=============================== SYSTEM INFO ================================
Mbed OS Version: 999999
CPU ID: 0x410fc241
Compiler ID: 2
Compiler Version: 60300
RAM0: Start 0x20000000 Size: 0x30000
RAM1: Start 0x1fff0000 Size: 0x10000
ROM0: Start 0x0 Size: 0x100000
================= CPU STATS =================
Idle: 98% Usage: 2%
================ HEAP STATS =================
Current heap: 1096
Max heap size: 1096
================ THREAD STATS ===============
ID: 0x20001eac
Name: main_thread
State: 2
Priority: 24
Stack Size: 4096
Stack Space: 3296

ID: 0x20000f5c
Name: idle_thread
State: 1
Priority: 1
Stack Size: 512
Stack Space: 352

ID: 0x20000f18
Name: timer_thread
State: 3
Priority: 40
Stack Size: 768
Stack Space: 664

```

## Troubleshooting

If you have problems, you can review the [documentation](https://os.mbed.com/docs/latest/tutorials/debugging.html) for suggestions on what could be wrong and how to fix it.

## Related Links

* [Mbed OS Stats API](https://os.mbed.com/docs/latest/apis/mbed-statistics.html)
* [Mbed OS Configuration](https://os.mbed.com/docs/latest/reference/configuration.html)
* [Mbed OS Serial Communication](https://os.mbed.com/docs/latest/tutorials/serial-communication.html)

Choose a reason for hiding this comment

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

@kegilbert - Maybe we can point to other stats examples as well - https://github.com/ARMmbed/mbed-os-example-cpu-stats

Copy link
Contributor Author

@kegilbert kegilbert Nov 27, 2018

Choose a reason for hiding this comment

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

The stats API link has examples on that page inline that are pulled from the teams repo which is copied from the github repo (quite the path...). I can add the github links as well if we'd like a direct link to the Github hosted examples (the docs site does lose the README info).

Choose a reason for hiding this comment

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

If the stats API link has the links already we ca skip adding them here.

18 changes: 15 additions & 3 deletions main.cpp
Original file line number Diff line number Diff line change
@@ -1,12 +1,24 @@
/* mbed Microcontroller Library
* Copyright (c) 2018 ARM Limited
* SPDX-License-Identifier: Apache-2.0
*/

#include "mbed.h"
#include "stats_report.h"

DigitalOut led1(LED1);

// main() runs in its own thread in the OS
int main() {
int main()
{
SystemReport sys_state(500 /* Loop delay time in ms */);

while (true) {
// Blink LED and wait 0.5 seconds
led1 = !led1;
wait(0.5);
wait(0.5f);

// Following the main thread wait, report on the current system status
sys_state.report_state();
}
}

12 changes: 12 additions & 0 deletions mbed_app.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"target_overrides": {
"*": {
"platform.stdio-baud-rate": 115200,
Copy link
Contributor

Choose a reason for hiding this comment

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

We should check with docs team if changing this will require docs change too, as we now need to specify the baud rate in any place where we mention serial.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Quick start makes mention of it, but pinging @AnotherButler to double check.

"platform.stack-stats-enabled": true,
"platform.heap-stats-enabled": true,
"platform.cpu-stats-enabled": true,
"platform.thread-stats-enabled": true,
"platform.sys-stats-enabled": true
}
}
}
132 changes: 132 additions & 0 deletions stats_report.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
/* mbed Microcontroller Library
* Copyright (c) 2018 ARM Limited
* SPDX-License-Identifier: Apache-2.0
*/

#ifndef STATS_REPORT_H
#define STATS_REPORT

#include "mbed.h"

/**
* System Reporting library. Provides runtime information on device:
* - CPU sleep, idle, and wake times
* - Heap and stack usage
* - Thread information
* - Static system information
*/
class SystemReport {
mbed_stats_heap_t heap_stats;
mbed_stats_cpu_t cpu_stats;
mbed_stats_sys_t sys_stats;

mbed_stats_thread_t *thread_stats;
uint8_t thread_count;
uint8_t max_thread_count;
uint32_t sample_time_ms;

public:
/**
* SystemReport - Sample rate in ms is required to handle the CPU percent awake logic
*/
SystemReport(uint32_t sample_rate) : max_thread_count(8), sample_time_ms(sample_rate)
{
thread_stats = new mbed_stats_thread_t[max_thread_count];

// Collect the static system information
mbed_stats_sys_get(&sys_stats);

printf("=============================== SYSTEM INFO ================================\r\n");
printf("Mbed OS Version: %ld \r\n", sys_stats.os_version);
printf("CPU ID: 0x%lx \r\n", sys_stats.cpu_id);
printf("Compiler ID: %d \r\n", sys_stats.compiler_id);
printf("Compiler Version: %ld \r\n", sys_stats.compiler_version);

for (int i = 0; i < MBED_MAX_MEM_REGIONS; i++) {
if (sys_stats.ram_size[i] != 0) {
printf("RAM%d: Start 0x%lx Size: 0x%lx \r\n", i, sys_stats.ram_start[i], sys_stats.ram_size[i]);
}
}
for (int i = 0; i < MBED_MAX_MEM_REGIONS; i++) {
if (sys_stats.rom_size[i] != 0) {
printf("ROM%d: Start 0x%lx Size: 0x%lx \r\n", i, sys_stats.rom_start[i], sys_stats.rom_size[i]);
}
}
}

~SystemReport(void)
{
free(thread_stats);
}

/**
* Report on each Mbed OS Platform stats API
*/
void report_state(void)
{
report_cpu_stats();
report_heap_stats();
report_thread_stats();

// Clear next line to separate subsequent report logs
printf("\r\n");
}

/**
* Report CPU idle and awake time in terms of percentage
*/
void report_cpu_stats(void)
{
static uint64_t prev_idle_time = 0;

printf("================= CPU STATS =================\r\n");

// Collect and print cpu stats
mbed_stats_cpu_get(&cpu_stats);

uint64_t diff = (cpu_stats.idle_time - prev_idle_time);
uint8_t idle = (diff * 100) / (sample_time_ms * 1000); // usec;
uint8_t usage = 100 - ((diff * 100) / (sample_time_ms * 1000)); // usec;;
prev_idle_time = cpu_stats.idle_time;

printf("Idle: %d%% Usage: %d%% \r\n", idle, usage);
}

/**
* Report current heap stats. Current heap refers to the current amount of
* allocated heap. Max heap refers to the highest amount of heap allocated
* since reset.
*/
void report_heap_stats(void)
{
printf("================ HEAP STATS =================\r\n");

// Collect and print heap stats
mbed_stats_heap_get(&heap_stats);

printf("Current heap: %lu\r\n", heap_stats.current_size);
printf("Max heap size: %lu\r\n", heap_stats.max_size);
}

/**
* Report active thread stats
*/
void report_thread_stats(void)
{
printf("================ THREAD STATS ===============\r\n");

// Collect and print running thread stats
int count = mbed_stats_thread_get_each(thread_stats, max_thread_count);

for (int i = 0; i < count; i++) {
printf("ID: 0x%lx \r\n", thread_stats[i].id);
printf("Name: %s \r\n", thread_stats[i].name);
printf("State: %ld \r\n", thread_stats[i].state);
printf("Priority: %ld \r\n", thread_stats[i].priority);
printf("Stack Size: %ld \r\n", thread_stats[i].stack_size);
printf("Stack Space: %ld \r\n", thread_stats[i].stack_space);
}
}
};

#endif // STATS_REPORT_H