Skip to content
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

Enhance memap, and configure depth level #4392

Merged
merged 2 commits into from
Aug 14, 2017
Merged

Enhance memap, and configure depth level #4392

merged 2 commits into from
Aug 14, 2017

Conversation

MarceloSalazar
Copy link

@MarceloSalazar MarceloSalazar commented May 25, 2017

Generates a detailed report by analysing static memory information from the map file.

The information from the map file is combined with the information from the BUILD directory (compiled objects and path to these objects), including the main application and user libraries.

In addition, it's now possible to visualise compiler libraries and identify other miscellaneous objects introduced by the toolchain.

By default, memap generates a report with depth=2, but it's possible to specify a different depth level, and even to enable a full report (depth=0).

It has been tested with the three major toolchains: GCC, ARM and IAR compiler.

Status

READY

Migrations

NO

Todos

@sg- @theotherjimmy @screamerbg please review

Usage

$ mbed compile -t <toolchain> -m <target>    # displays memap info with depth=2 (default)
$ python mbed-os/tools/memap.py BUILD/<TARGET>/<TOOLCHAIN>/<memap-file.map> -t <TOOLCHAIN> -d <DEPTH_LEVEL>

Examples

$ python mbed-os/tools/memap.py BUILD/K64F/GCC_ARM/example.map -t GCC_ARM -d 1
+-----------+-------+-------+-------+
| Module    | .text | .data |  .bss |
+-----------+-------+-------+-------+
| [fill]    |    62 |     4 |  2513 |
| [lib]     | 26514 |  2212 |    84 |
| main.o    |    56 |     0 |     4 |
| mbed-os   | 17487 |    40 |  7719 |
| Subtotals | 44119 |  2256 | 10320 |
+-----------+-------+-------+-------+
Allocated Heap: 24576 bytes
Allocated Stack: unknown
Total Static RAM memory (data + bss): 12576 bytes
Total RAM memory (data + bss + heap + stack): 37152 bytes
Total Flash memory (text + data + misc): 47415 bytes

$ python mbed-os/tools/memap.py BUILD/K64F/GCC_ARM/example.map -t GCC_ARM -d 2
+------------------+-------+-------+-------+
| Module           | .text | .data |  .bss |
+------------------+-------+-------+-------+
| [fill]           |    62 |     4 |  2513 |
| [lib]/libc.a     | 22434 |  2204 |    56 |
| [lib]/libgcc.a   |  3728 |     0 |     0 |
| [lib]/libm.a     |    88 |     0 |     0 |
| [lib]/libnosys.a |    32 |     0 |     0 |
| [lib]/misc       |   232 |     8 |    28 |
| main.o           |    56 |     0 |     4 |
| mbed-os/features |    42 |     0 |   184 |
| mbed-os/hal      |   450 |     0 |     8 |
| mbed-os/platform |  1252 |     4 |   269 |
| mbed-os/rtos     |  5955 |    24 |  6874 |
| mbed-os/targets  |  9788 |    12 |   384 |
| Subtotals        | 44119 |  2256 | 10320 |
+------------------+-------+-------+-------+
Allocated Heap: 24576 bytes
Allocated Stack: unknown
Total Static RAM memory (data + bss): 12576 bytes
Total RAM memory (data + bss + heap + stack): 37152 bytes
Total Flash memory (text + data + misc): 47415 bytes

$ python mbed-os/tools/memap.py BUILD/K64F/GCC_ARM/example.map -t GCC_ARM -d 3
+----------------------------------------+-------+-------+-------+
| Module                                 | .text | .data |  .bss |
+----------------------------------------+-------+-------+-------+
| [fill]                                 |    62 |     4 |  2513 |
| [lib]/libc.a/lib_a-abort.o             |    16 |     0 |     0 |
| [lib]/libc.a/lib_a-assert.o            |   123 |     0 |     0 |
| [lib]/libc.a/lib_a-callocr.o           |    96 |     0 |     0 |
| [lib]/libc.a/lib_a-closer.o            |    36 |     0 |     0 |
| [lib]/libc.a/lib_a-dtoa.o              |  4044 |     0 |     0 |
| [lib]/libc.a/lib_a-errno.o             |    12 |     0 |     0 |
| [lib]/libc.a/lib_a-fclose.o            |   132 |     0 |     0 |
| [lib]/libc.a/lib_a-fflush.o            |   420 |     0 |     0 |
| [lib]/libc.a/lib_a-findfp.o            |   272 |     0 |     0 |
| [lib]/libc.a/lib_a-fiprintf.o          |    40 |     0 |     0 |
| [lib]/libc.a/lib_a-fputwc.o            |   212 |     0 |     0 |
| [lib]/libc.a/lib_a-freer.o             |   588 |     0 |     0 |
| [lib]/libc.a/lib_a-fstatr.o            |    40 |     0 |     0 |
| [lib]/libc.a/lib_a-fvwrite.o           |   792 |     0 |     0 |
| [lib]/libc.a/lib_a-fwalk.o             |    84 |     0 |     0 |
| [lib]/libc.a/lib_a-impure.o            |     6 |  1068 |     0 |
| [lib]/libc.a/lib_a-init.o              |    80 |     0 |     0 |
| [lib]/libc.a/lib_a-isattyr.o           |    36 |     0 |     0 |
| [lib]/libc.a/lib_a-locale.o            |    40 |    92 |     0 |
| [lib]/libc.a/lib_a-lseekr.o            |    40 |     0 |     0 |
| [lib]/libc.a/lib_a-makebuf.o           |   224 |     0 |     0 |
| [lib]/libc.a/lib_a-mallocr.o           |  1316 |  1040 |    52 |
| [lib]/libc.a/lib_a-memchr.o            |   148 |     0 |     0 |
| [lib]/libc.a/lib_a-memcpy.o            |   308 |     0 |     0 |
| [lib]/libc.a/lib_a-memmove.o           |   200 |     0 |     0 |
| [lib]/libc.a/lib_a-memset.o            |   156 |     0 |     0 |
| [lib]/libc.a/lib_a-mprec.o             |  1764 |     0 |     0 |
| [lib]/libc.a/lib_a-readr.o             |    40 |     0 |     0 |
| [lib]/libc.a/lib_a-reallocr.o          |  1004 |     0 |     0 |
| [lib]/libc.a/lib_a-reent.o             |     0 |     0 |     4 |
| [lib]/libc.a/lib_a-sbrkr.o             |    36 |     0 |     0 |
| [lib]/libc.a/lib_a-signal.o            |   104 |     0 |     0 |
| [lib]/libc.a/lib_a-signalr.o           |    44 |     0 |     0 |
| [lib]/libc.a/lib_a-stdio.o             |   132 |     0 |     0 |
| [lib]/libc.a/lib_a-strlen.o            |    92 |     0 |     0 |
| [lib]/libc.a/lib_a-svfiprintf.o        |   260 |     0 |     0 |
| [lib]/libc.a/lib_a-svfprintf.o         |  5426 |     0 |     0 |
| [lib]/libc.a/lib_a-vfiprintf.o         |  3407 |     0 |     0 |
| [lib]/libc.a/lib_a-vsnprintf.o         |   148 |     0 |     0 |
| [lib]/libc.a/lib_a-wbuf.o              |   168 |     0 |     0 |
| [lib]/libc.a/lib_a-wcrtomb.o           |    84 |     0 |     0 |
| [lib]/libc.a/lib_a-wctomb_r.o          |    28 |     4 |     0 |
| [lib]/libc.a/lib_a-writer.o            |    40 |     0 |     0 |
| [lib]/libc.a/lib_a-wsetup.o            |   196 |     0 |     0 |
| [lib]/libgcc.a/_aeabi_uldivmod.o       |    48 |     0 |     0 |
| [lib]/libgcc.a/_arm_addsubdf3.o        |   880 |     0 |     0 |
| [lib]/libgcc.a/_arm_cmpdf2.o           |   272 |     0 |     0 |
| [lib]/libgcc.a/_arm_fixdfsi.o          |    80 |     0 |     0 |
| [lib]/libgcc.a/_arm_muldivdf3.o        |  1060 |     0 |     0 |
| [lib]/libgcc.a/_divdi3.o               |   668 |     0 |     0 |
| [lib]/libgcc.a/_dvmd_tls.o             |     4 |     0 |     0 |
| [lib]/libgcc.a/_udivdi3.o              |   620 |     0 |     0 |
| [lib]/libgcc.a/bpabi.o                 |    96 |     0 |     0 |
| [lib]/libm.a/lib_a-s_fpclassify.o      |    88 |     0 |     0 |
| [lib]/libnosys.a/getpid.o              |    16 |     0 |     0 |
| [lib]/libnosys.a/kill.o                |    16 |     0 |     0 |
| [lib]/misc/crt0.o                      |   116 |     0 |     0 |
| [lib]/misc/crtbegin.o                  |    92 |     4 |    28 |
| [lib]/misc/crtend.o                    |     0 |     4 |     0 |
| [lib]/misc/crti.o                      |     8 |     0 |     0 |
| [lib]/misc/crtn.o                      |    16 |     0 |     0 |
| main.o                                 |    56 |     0 |     4 |
| mbed-os/features/storage               |    42 |     0 |   184 |
| mbed-os/hal/mbed_gpio.o                |    96 |     0 |     0 |
| mbed-os/hal/mbed_pinmap_common.o       |   242 |     0 |     0 |
| mbed-os/hal/mbed_ticker_api.o          |    72 |     0 |     0 |
| mbed-os/hal/mbed_us_ticker_api.o       |    40 |     0 |     8 |
| mbed-os/platform/mbed_alloc_wrappers.o |    16 |     0 |     0 |
| mbed-os/platform/mbed_assert.o         |    85 |     0 |     0 |
| mbed-os/platform/mbed_board.o          |   156 |     0 |     0 |
| mbed-os/platform/mbed_critical.o       |   251 |     0 |     5 |
| mbed-os/platform/mbed_error.o          |    22 |     0 |     0 |
| mbed-os/platform/mbed_retarget.o       |   636 |     4 |   264 |
| mbed-os/platform/mbed_wait_api_rtos.o  |    86 |     0 |     0 |
| mbed-os/rtos/Thread.o                  |    20 |     0 |     4 |
| mbed-os/rtos/rtos_idle.o               |    20 |     4 |     0 |
| mbed-os/rtos/rtx                       |  5915 |    20 |  6870 |
| mbed-os/targets/TARGET_Freescale       |  9788 |    12 |   384 |
| Subtotals                              | 44119 |  2256 | 10320 |
+----------------------------------------+-------+-------+-------+
Allocated Heap: 24576 bytes
Allocated Stack: unknown
Total Static RAM memory (data + bss): 12576 bytes
Total RAM memory (data + bss + heap + stack): 37152 bytes
Total Flash memory (text + data + misc): 47415 bytes

@sg-
Copy link
Contributor

sg- commented May 25, 2017

Looking good. A few questions:

  • Can we change the depth using mbed compile, not memmap specifically? If not, this is a feature request!
  • I'm guessing Allocated Stack is wrong given it's computed at run time? If so can we remove allocated stack and heap from the output? This would leave something like:
Total Static RAM memory (data + bss): 12576 bytes
Total Flash memory (text + data): 47415 bytes

@MarceloSalazar
Copy link
Author

  • Can we change the depth using mbed compile, not memmap specifically? If not, this is a feature request!

Sure, the depth number can be passed to memap - see here:
https://github.com/MarceloSalazar/mbed-os/blob/69ffd620ae2009757f737d006ad4bed79cc52926/tools/build_api.py#L543

I'd need a bit of help to be able to pass a parameter from mbed compile.

I'm guessing Allocated Stack is wrong given it's computed at run time? If so can we remove allocated stack and heap from the output? This would leave something like:

I agree. Commit coming soon.

@AnotherButler
Copy link
Contributor

@MarceloSalazar Thanks for the PR.

Also, we recommend PRs follow Chris Beam’s seven rules of great commit messages. This helps us with the release notes.

To match this format, please change the subject line to the imperative mood by changing it to "Enhance memap, and configure depth level"

Thanks so much for your help.

@MarceloSalazar MarceloSalazar changed the title memap enhancements + depth level configurable Enhance memap, and configure depth level May 25, 2017
@MarceloSalazar
Copy link
Author

Parameter added to set depth from mbed compile. Example
mbed compile -t GCC_ARM -m K64F --stats-depth 3

@@ -439,7 +439,7 @@ def build_project(src_paths, build_path, target, toolchain_name,
macros=None, inc_dirs=None, jobs=1, silent=False,
report=None, properties=None, project_id=None,
project_description=None, extra_verbose=False, config=None,
app_config=None, build_profile=None):
app_config=None, build_profile=None, stats_depth=None):
Copy link
Contributor

Choose a reason for hiding this comment

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

Oooph. I'm not a fan of these 15+ argument functions.

Copy link
Contributor

Choose a reason for hiding this comment

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

Not your fault @MarceloSalazar. Not going to block this PR.

Copy link
Contributor

Choose a reason for hiding this comment

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

Alternate suggestions?

Copy link
Contributor

Choose a reason for hiding this comment

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

I have to revisit all of "build_api.py". I think that most of these arguments are passed on to constructors for the various objects that make up a project in the tools. We could move where we construct the objects elsewhere and pass them into the build_project function. That would reduce the number of arguments considerably.

That's also why I said that this was not blocking this PR. I would not expect to refactor "build_api.py" in a memap PR.

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think there is an alternative that does not involve changing the way that the functions in "build_api.py" take parameters. That alternative is going to be a much bigger change than would be appropriate for this PR.

Copy link
Contributor

@theotherjimmy theotherjimmy left a comment

Choose a reason for hiding this comment

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

These changes look very good. I have some style comments and naming bikeshedding comments below.

tools/make.py Outdated
@@ -103,6 +103,9 @@
default=None,
help='For some commands you can use filter to filter out results')

parser.add_argument("--stats-depth", type=int, dest="stats_depth",
default=2, help="Depth level for static memory report")
Copy link
Contributor

Choose a reason for hiding this comment

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

This indentation looks incorrect. Maybe it's a tabs vs spaces issue?

tools/memap.py Outdated
RE_ARMCC = re.compile(
r'^\s+0x(\w{8})\s+0x(\w{8})\s+(\w+)\s+(\w+)\s+(\d+)\s+[*]?.+\s+(.+)$')
RE_IAR = re.compile(
r'^\s+(.+)\s+(zero|const|ro code|inited|uninit)\s'
r'+0x(\w{8})\s+0x(\w+)\s+(.+)\s.+$')

# Pending:
# 1. Add tests
# 2. Update markdown documentation
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this in the PR description? if not, let's add it.

Copy link
Contributor

Choose a reason for hiding this comment

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

Looks like it's in the PR description! Good job on that one!

tools/memap.py Outdated
class MemapParser(object):
"""An object that represents parsed results, parses the memory map files,
and writes out different file types of memory results
"""

print_sections = ('.text', '.data', '.bss')

# Info from this section can be shown as misc or startup code (.text)
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this comment really needed? I think that the variable is named well enough to get the point across.

This will not block the PR

tools/memap.py Outdated

# this is required to differenciate: main.o vs xxxmain.o
key_split = key.split('/')[-1]
obj_split = object_name.split('/')[-1]
Copy link
Contributor

Choose a reason for hiding this comment

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

Should the preceding two lines use os.path.basename instead of splitting things manually?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes they should. I need to be more direct. Please change the implementation to use os.path.basename or explain why the implementation must avoid using that function.

Copy link
Author

Choose a reason for hiding this comment

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

Good spot :)

tools/memap.py Outdated
"""

# Check if object is a sub-string of key
for key, value in self.modules.items():
Copy link
Contributor

Choose a reason for hiding this comment

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

Where is value used it this loop? I could not find it.

If value is unused, just iterate through self.modules

Further, the variable name key adds no new information about the structure of the data being processed; by definition of iterating through the dict, key must contain keys. It looks like this is the module's file name. so fname or file_name or module_path would all give me an indication that we are processing file paths in this loop.

tools/memap.py Outdated

"""

rex_address_line = re.compile(r'^\s+(.+\.o)\s.*')
Copy link
Contributor

Choose a reason for hiding this comment

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

This comment is the same as the other Regular expression related ones:

  1. re not rex is common in python
  2. Please make this a Class or global constant

tools/memap.py Outdated
"""

path = path.replace('\\', '/')

# check location of map file
rex = r'^(.+)' + r'\/(.+\.map)$'
#rex = r'^(.+)' + r'\/(.+\.map)$'
rex = r'^(.+)\/(.+\.map)$'
Copy link
Contributor

Choose a reason for hiding this comment

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

This comment is the same as the other Regular expression related ones:

  1. re not rex is common in python
  2. Please make this a Class or global constant

tools/memap.py Outdated
"""

path = path.replace('\\', '/')

# check location of map file
rex = r'^(.+)' + r'\/(.+\.map)$'
#rex = r'^(.+)' + r'\/(.+\.map)$'
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we delete old, unused code?

tools/memap.py Outdated

for section_idx in self.all_sections:
self.short_modules[temp][section_idx] += \
self.modules[line][section_idx]
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you indent this line so that, when I read this file again in 2 months, I know that it's a continuation of the prior line?

tools/memap.py Outdated

Returns: generated string for the 'table' format, otherwise None
"""

self.module_remove_unused() # clean up unused modules/objects
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this method is named well enough that we don't need this comment.

Not blocking this PR.

Copy link
Contributor

@theotherjimmy theotherjimmy left a comment

Choose a reason for hiding this comment

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

Looks great! Let's create those issues to track future work and then get this merged.

tools/make.py Outdated
type=int,
dest="stats_depth",
default=2,
help="Depth level for static memory report")
Copy link
Contributor

Choose a reason for hiding this comment

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

This, and the 3 prior lines, still look like they do not line up with the character after the (, which is the style we have throughout the tools.

@theotherjimmy
Copy link
Contributor

Oh yeah, and write those tests! Can't forget the tests!

Copy link
Contributor

@theotherjimmy theotherjimmy left a comment

Choose a reason for hiding this comment

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

💯 👍

@geky
Copy link
Contributor

geky commented Jun 8, 2017

I'm not sure if this is a user error, but with using mbed test to compile (mbed test --compile) we seem to no longer be getting the memory stats as output?

@theotherjimmy
Copy link
Contributor

bumping travis.

@MarceloSalazar
Copy link
Author

(mbed test --compile) we seem to no longer be getting the memory stats as output?

You are right, I'm able to reproduce this. I'll investigate further.

@MarceloSalazar
Copy link
Author

@geky memap for mbed tests has been fixed. Could you have a look?

@theotherjimmy
Copy link
Contributor

@MarceloSalazar Thanks for the fix. Confirmed that mbed test --compile produces memap output.

@geky
Copy link
Contributor

geky commented Aug 8, 2017

@MarceloSalazar, looks good now, thanks for the fix!

LGTM

@theotherjimmy
Copy link
Contributor

/morph test

@mbed-bot
Copy link

mbed-bot commented Aug 8, 2017

Result: SUCCESS

Your command has finished executing! Here's what you wrote!

/morph test

Output

mbed Build Number: 967

All builds and test passed!

@theotherjimmy
Copy link
Contributor

@MarceloSalazar I'm going to open a new PR with your branch to trigger Travis.

@theotherjimmy
Copy link
Contributor

Travis Triggered.

@theotherjimmy
Copy link
Contributor

@tommikas It looks like your CI forgot to report, so I retriggered it.

@0xc0170
Copy link
Contributor

0xc0170 commented Aug 11, 2017

@tommikas It looks like your CI forgot to report, so I retriggered it.

Again not reported. Tommi, can you please? I am not seein there build now command

@tommikas
Copy link
Contributor

Looks to me like Jenkins missed the latest reopening notification so it currently thinks the PR is closed.

I'm not sure how to best fix it. @miklis, could you please have a look?

@tommikas
Copy link
Contributor

@miklis noticed that the jenkins/pr-head Details link actually pointed to the wrong Jenkins job - the one for #4887. Restarting the build from the correct job seems to have fixed the issue so the update should come to the right place.

Creating two PRs from the same branch probably confused Jenkins/github a bit.

@jeromecoutant
Copy link
Collaborator

Hi
there is no more OS2 tests in the CI ?

@theotherjimmy
Copy link
Contributor

There should be in Travis.

@0xc0170 0xc0170 self-assigned this Aug 18, 2017
exmachina-auto-deployer pushed a commit to exmachina-dev/mbed-os that referenced this pull request Sep 13, 2017
mbed OS 5.5.6 release

We are pleased to announce the [mbed OS 5.5.6
release](https://github.com/ARMmbed/mbed-os/releases/tag/mbed-os-5.5.6)
is now available.

This release includes ...

Known Issues

The following list of known issues apply to this release:

Contents

Ports for Upcoming Targets

[4608](ARMmbed#4608)
Support Nuvoton's new target NUMAKER_PFM_M487

[4840](ARMmbed#4840)
Add Support for TOSHIBA TMPM066 board

Fixes and Changes

[4801](ARMmbed#4801)
STM32 CAN: Fix issue with speed function calculation

[4808](ARMmbed#4808)
Make HAL & US tickers idle safe

[4812](ARMmbed#4812)
Use DSPI SDK driver API's in SPI HAL driver

[4832](ARMmbed#4832)
NUC472/M453: Fix several startup and hal bugs

[4842](ARMmbed#4842)
Add call to DAC_Enable as this is no longer done as part

[4849](ARMmbed#4849)
Allow using of malloc() for reserving the Nanostack's heap.

[4850](ARMmbed#4850)
Add list of defines to vscode exporter

[4863](ARMmbed#4863)
Optimize memory usage of wifi scan for REALTEK_RTW8195AM

[4869](ARMmbed#4869)
HAL LPCs SPI: Fix mask bits for SPI clock rate

[4873](ARMmbed#4873)
Fix Cortex-A cache file

[4878](ARMmbed#4878)
STM32 : Separate internal ADC channels with new pinmap

[4392](ARMmbed#4392)
Enhance memap, and configure depth level

[4895](ARMmbed#4895)
Turn on doxygen for DEVICE_* features

[4817](ARMmbed#4817)
Move RTX error handlers into RTX handler file

[4902](ARMmbed#4902)
Using CMSIS/RTX Exclusive access macro

[4923](ARMmbed#4923)
fix export static_files to zip

[4844](ARMmbed#4844)
bd: Add ProfilingBlockDevice for measuring higher-level applications

[4896](ARMmbed#4896)
target BLUEPILL_F103C8 compile fix

[4921](ARMmbed#4921)
Update gcc-arm-embedded PPA in Travis

[4926](ARMmbed#4926)
STM32L053x8: Refactor NUCLEO_L053R8 and DISCO_L053C8 targets

[4831](ARMmbed#4831)
Remove excessive use of printf/scanf in mbed_fdopen/_open

[4922](ARMmbed#4922)
bug fix: xdot clock config

[4935](ARMmbed#4935)
STM32: fix F410RB vectors size

[4940](ARMmbed#4940)
Update mbed-coap to version 4.0.9

[4941](ARMmbed#4941)
Update of MemoryPool.h header file.

You can fetch this release from the [mbed-os
GitHub](https://github.com/ARMmbed/mbed-os) repository,
using the tag "mbed-os-5.5.6".

Please feel free to ask any questions or provide feedback on this
release [on the forum](https://forums.mbed.com/),
or to contact us at [[email protected]](mailto:[email protected]).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants