Bring python packages into the mbed-os source (#192)

* Initial import of python packages

* Move tests to subfolder, use tests in generate_configuration.cmake

* Bring python packages into the source tree instead of needing to be installed separately

* Use python3

* Just use distro default python

* Install all the requirements with apt-get

* unittests is part of Python now

* Add appdirs, set python version

* Add some missing dependencies

* Add more packages

* Add requirements.apt.txt files, fix relative paths with scancode_evaluate.py

* Fix return code handling for license scan errors

* ok let's try that again, also improve error output from scancode evaluate

* Add missing license headers
pull/15494/head
Jamie Smith 2023-10-10 09:54:53 -07:00 committed by GitHub
parent e1a1542310
commit 3af1c75ca8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
440 changed files with 46246 additions and 83 deletions

View File

@ -25,8 +25,11 @@ jobs:
-
name: install dependencies
shell: bash
# TODO scancode 32.0 introduced significant breaking changes to the license
# detection output format: https://github.com/nexB/scancode-toolkit/releases/tag/v32.0.0
# Need to update Mbed's scripts for the new format.
run: |
pip install -U scancode-toolkit "click>=7,<8"
pip install -U "scancode-toolkit<32.0" "click>=7,<8"
-
name: license check
@ -43,10 +46,14 @@ jobs:
| while read file; do cp --parents "${file}" SCANCODE; done
ls SCANCODE
scancode -l --json-pp scancode.json SCANCODE
python ./tools/test/ci/scancode-evaluate.py scancode.json || true
cat scancode-evaluate.log
COUNT=$(cat scancode-evaluate.log | grep 'File:' | grep -v 'SPDX' | wc -l) || true
if [ $COUNT = 0 ]; then
cd tools/python
# Run the evaluation script, which may fail, and save its exit code.
EVALUATE_EXITCODE=0
python -m scancode_evaluate.scancode_evaluate ../../scancode.json || EVALUATE_EXITCODE=$?
cat scancode_evaluate.log
if [ "$EVALUATE_EXITCODE" = 0 ]; then
echo "License check OK";
true;
else
@ -158,25 +165,18 @@ jobs:
name: Checkout repo
uses: actions/checkout@v3
- uses: actions/setup-python@v2
with:
python-version: '3.7'
-
name: install dependencies
run: |
pip install -r tools/requirements.txt
pip install -r tools/test/requirements.txt
xargs sudo apt-get install -y < tools/requirements.apt.txt
xargs sudo apt-get install -y < tools/python/python_tests/requirements.apt.txt
-
name: pytest
name: Python Tests
run: |
set -x
coverage run -a -m pytest tools/test
python tools/test/pylint.py
coverage run -a tools/project.py -S | sed -n '/^Total/p'
coverage html
cd tools/python
./run_python_tests.sh
pin-validation:
runs-on: ubuntu-latest

2
.gitignore vendored
View File

@ -31,7 +31,7 @@ venv/
*.egg
*.egg-info
dist
build
/build
eggs
parts
bin

View File

@ -15,7 +15,7 @@ find_package(Python3 REQUIRED COMPONENTS Interpreter)
include(CheckPythonPackage)
# Check python packages
set(PYTHON_PACKAGES_TO_CHECK intelhex prettytable future jinja2 mbed_tools)
set(PYTHON_PACKAGES_TO_CHECK intelhex prettytable future jinja2)
foreach(PACKAGE_NAME ${PYTHON_PACKAGES_TO_CHECK})
string(TOUPPER ${PACKAGE_NAME} PACKAGE_NAME_UCASE) # Ucase name needed for CMake variable
string(TOLOWER ${PACKAGE_NAME} PACKAGE_NAME_LCASE) # Lcase name needed for import statement

View File

@ -18,6 +18,6 @@ message("Executing: mbedhtrun ${MBEDHTRUN_ARGS_FOR_DISPLAY}")
# Note: For this command, we need to survive mbedhtrun not being on the PATH, so we import the package and call the main function using "python -c"
execute_process(
COMMAND @Python3_EXECUTABLE@ -c "import mbed_host_tests.mbedhtrun; exit(mbed_host_tests.mbedhtrun.main())" ${MBEDHTRUN_ARGS}
WORKING_DIRECTORY "@CMAKE_CURRENT_BINARY_DIR@"
COMMAND @Python3_EXECUTABLE@ -m mbed_host_tests.mbedhtrun ${MBEDHTRUN_ARGS}
WORKING_DIRECTORY "@mbed-os_SOURCE_DIR@/tools/python"
COMMAND_ERROR_IS_FATAL ANY)

View File

@ -103,7 +103,7 @@ if(MBED_NEED_TO_RECONFIGURE)
execute_process(
COMMAND ${MBEDTOOLS_CONFIGURE_COMMAND}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/../python
RESULT_VARIABLE MBEDTOOLS_CONFIGURE_RESULT
OUTPUT_VARIABLE MBEDTOOLS_CONFIGURE_OUTPUT
ERROR_VARIABLE MBEDTOOLS_CONFIGURE_ERROR_OUTPUT

View File

@ -53,11 +53,11 @@ function(mbed_generate_map_file target)
TARGET
${target}
POST_BUILD
COMMAND ${Python3_EXECUTABLE} ${mbed-os_SOURCE_DIR}/tools/memap.py
COMMAND ${Python3_EXECUTABLE} -m memap.memap
-t ${MBED_TOOLCHAIN} ${CMAKE_CURRENT_BINARY_DIR}/${target}${CMAKE_EXECUTABLE_SUFFIX}.map
--depth ${MBED_MEMAP_DEPTH}
WORKING_DIRECTORY
${CMAKE_CURRENT_BINARY_DIR}
${mbed-os_SOURCE_DIR}/tools/python
)
# generate json file
@ -66,13 +66,13 @@ function(mbed_generate_map_file target)
TARGET
${target}
POST_BUILD
COMMAND ${Python3_EXECUTABLE} ${mbed-os_SOURCE_DIR}/tools/memap.py
COMMAND ${Python3_EXECUTABLE} -m memap.memap
-t ${MBED_TOOLCHAIN} ${CMAKE_CURRENT_BINARY_DIR}/${target}${CMAKE_EXECUTABLE_SUFFIX}.map
--depth ${MBED_MEMAP_DEPTH}
-e json
-o ${CMAKE_CURRENT_BINARY_DIR}/${target}${CMAKE_EXECUTABLE_SUFFIX}.memmap.json
WORKING_DIRECTORY
${CMAKE_CURRENT_BINARY_DIR}
${mbed-os_SOURCE_DIR}/tools/python
)
endif()
@ -82,13 +82,13 @@ function(mbed_generate_map_file target)
TARGET
${target}
POST_BUILD
COMMAND ${Python3_EXECUTABLE} ${mbed-os_SOURCE_DIR}/tools/memap.py
COMMAND ${Python3_EXECUTABLE} -m memap.memap
-t ${MBED_TOOLCHAIN} ${CMAKE_CURRENT_BINARY_DIR}/${target}${CMAKE_EXECUTABLE_SUFFIX}.map
--depth ${MBED_MEMAP_DEPTH}
-e html
-o ${CMAKE_CURRENT_BINARY_DIR}/${target}${CMAKE_EXECUTABLE_SUFFIX}.memmap.html
WORKING_DIRECTORY
${CMAKE_CURRENT_BINARY_DIR}
${mbed-os_SOURCE_DIR}/tools/python
)
endif()
endfunction()

View File

@ -7,8 +7,7 @@
set(UPLOAD_SUPPORTS_DEBUG FALSE)
### Check if upload method can be enabled on this machine
check_python_package(mbed_os_tools HAVE_MBED_OS_TOOLS)
set(UPLOAD_MBED_FOUND ${HAVE_MBED_OS_TOOLS})
set(UPLOAD_MBED_FOUND ${Python3_FOUND})
if(NOT DEFINED MBED_RESET_BAUDRATE)
set(MBED_RESET_BAUDRATE 9600)
@ -20,11 +19,14 @@ set(MBED_TARGET_UID "" CACHE STRING "UID of mbed target to upload to if there ar
function(gen_upload_target TARGET_NAME BIN_FILE)
add_custom_target(flash-${TARGET_NAME}
COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/install_bin_file.py
${BIN_FILE}
${MBED_TARGET}
${MBED_RESET_BAUDRATE}
${MBED_TARGET_UID})
COMMAND ${Python3_EXECUTABLE} -m install_bin_file
${BIN_FILE}
${MBED_TARGET}
${MBED_RESET_BAUDRATE}
${MBED_TARGET_UID}
WORKING_DIRECTORY
${mbed-os_SOURCE_DIR}/tools/python
VERBATIM)
add_dependencies(flash-${TARGET_NAME} ${TARGET_NAME})

5
tools/python/.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
# Python coverage database
.coverage
# Coverage report
htmlcov/

174
tools/python/LICENSE Normal file
View File

@ -0,0 +1,174 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.

4
tools/python/__init__.py Normal file
View File

@ -0,0 +1,4 @@
#
# Copyright (c) 2020-2023 Arm Limited and Contributors. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
#

View File

@ -42,7 +42,7 @@ def error(lines, code=-1):
sys.exit(code)
if len(sys.argv) < 3:
print("Error: Usage: python " + sys.argv[0] + " <path to bin file> <Mbed OS target name> <serial baudrate for sending break> [Target UID for distinguishing multiple targets]")
print("Error: Usage: " + sys.argv[0] + " <path to bin file> <Mbed OS target name> <serial baudrate for sending break> [Target UID for distinguishing multiple targets]")
sys.exit(1)
bin_file = sys.argv[1]
@ -81,7 +81,7 @@ elif len(all_connected) > 1:
error_lines = ["There are multiple of the targeted board connected to the system. Which do you wish to flash?"]
for target in all_connected:
error_lines.append("Board: %s, Mount Point: %s, UID: %s" % (target['name'], target['mount'], target['uid']))
error_lines.append("Please set MBED_TARGET_UID to the UID of the board you wish to flash.")
error_lines.append("Please set the CMake variable MBED_TARGET_UID to the UID of the board you wish to flash.")
error(error_lines, 5)
connected = all_connected[0]

View File

@ -0,0 +1,227 @@
# Development moved
The development of Greentea has been moved into the [mbed-os-tools](../../src/mbed_os_tools) package. You can continue to use this module for legacy reasons, however all further development should be continued in the new package.
-------------
[![PyPI version](https://badge.fury.io/py/mbed-greentea.svg)](https://badge.fury.io/py/mbed-greentea)
# Greentea - test automation for mbed
_**G**eneric **re**gression **en**vironment for **te**st **a**utomation_
## Introduction
Greentea is the automated testing tool for mbed OS development. It automates the process of flashing mbed boards, driving the test and accumulating test results into test reports. Developers use it for local development as well as for automation in a Continuous Integration environment.
This document should help you start using Greentea. Please see the [htrun documentation](https://github.com/ARMmbed/htrun), the tool Greentea uses to drive tests, for the technical details of the interactions between the platform and the host machine.
Because Greentea is an open source project, we accept contributions! Please see our [contributing document](CONTRIBUTING.md) for more information.
### Prerequistes
Greentea requires [Python version 2.7](https://www.python.org/downloads/). It supports the following OSes:
- Windows
- Linux (Ubuntu preferred)
- OS X (experimental)
### Installing
Tools that depend on Greentea usually install it. Determine if Greentea is already installed by running:
```
$ mbedgt --version
1.2.5
```
You can also install it manually via pip.
```
pip install mbed-greentea
```
## Test specification JSON format
The Greentea test specification format decouples the tool from your build system. It provides important data, such as test names, paths to test binaries and the platform on which the binaries should run.
Greentea automatically looks for files called `test_spec.json` in your working directory. You can also use the `--test-spec` argument to direct Greentea to a specific test specification file.
When you use the `-t` / `--target` argument with the `--test-spec` argument, you can select which "build" should be used. In the example below, you could provide the arguments `--test-spec test_spec.json -t K64F-ARM` to only run that build's tests.
### Example of test specification file
In the below example, there are two defined builds:
* Build `K64F-ARM` for NXP `K64F` platform compiled with `ARMCC` compiler.
* Build `K64F-GCC` for NXP `K64F` platform compiled with `GCC ARM` compiler.
```json
{
"builds": {
"K64F-ARM": {
"platform": "K64F",
"toolchain": "ARM",
"base_path": "./BUILD/K64F/ARM",
"baud_rate": 9600,
"tests": {
"tests-mbedmicro-rtos-mbed-mail": {
"binaries": [
{
"binary_type": "bootable",
"path": "./BUILD/K64F/ARM/tests-mbedmicro-rtos-mbed-mail.bin"
}
]
},
"tests-mbed_drivers-c_strings": {
"binaries": [
{
"binary_type": "bootable",
"path": "./BUILD/K64F/ARM/tests-mbed_drivers-c_strings.bin"
}
]
}
}
},
"K64F-GCC": {
"platform": "K64F",
"toolchain": "GCC_ARM",
"base_path": "./BUILD/K64F/GCC_ARM",
"baud_rate": 9600,
"tests": {
"tests-mbedmicro-rtos-mbed-mail": {
"binaries": [
{
"binary_type": "bootable",
"path": "./BUILD/K64F/GCC_ARM/tests-mbedmicro-rtos-mbed-mail.bin"
}
]
}
}
}
}
}
```
The examples below use the above test specification file.
## Command-line usage
This section highlights a few of the capabilities of the Greentea command-line interface. For a full list of the available options, please run `mbedgt --help`.
Assume for the examples below that the above `test_spec.json` file is in the current directory.
### Listing all tests
You can use the `-l` argument to list all available tests:
```
$ mbedgt -l
mbedgt: greentea test automation tool ver. 1.2.5
mbedgt: using multiple test specifications from current directory!
using 'BUILD\tests\K64F\ARM\test_spec.json'
using 'BUILD\tests\K64F\GCC_ARM\test_spec.json'
mbedgt: available tests for built 'K64F-GCC_ARM', location 'BUILD/tests/K64F/GCC_ARM'
test 'tests-mbedmicro-rtos-mbed-mail'
mbedgt: available tests for built 'K64F-ARM', location 'BUILD/tests/K64F/ARM'
test 'tests-mbed_drivers-c_strings'
test 'tests-mbedmicro-rtos-mbed-mail'
```
### Executing all tests
The default action of Greentea using `mbedgt` is to execute all tests that are found in `test_spec.json` files. You can also add `-V` to make the output more verbose.
### Limiting tests
You can select test cases by name using the `-n` argument. This command executes all tests named `tests-mbedmicro-rtos-mbed-mail` from all builds in the test specification:
```
$ mbedgt -n tests-mbedmicro-rtos-mbed-mail
```
When using the `-n` argument, you can use the `*` character at the end of a test name to match all tests that share a prefix. This command executes all tests that start with `tests*`:
```
$ mbedgt -n tests*
```
You can use the `-t` argument to select which build to use when finding tests. This command executes the test `tests-mbedmicro-rtos-mbed-mail` for the `K64F-ARM` build in the test specification:
```
$ mbedgt -n tests-mbedmicro-rtos-mbed-mail -t K64F-ARM
```
You can use a comma (`,`) to separate test names (argument `-n`) and build names (argument `-t`). This command executes the tests `tests-mbedmicro-rtos-mbed-mail` and `tests-mbed_drivers-c_strings` for the `K64F-ARM` and `K64F-GCC_ARM` builds in the test specification:
```
$ mbedgt -n tests-mbedmicro-rtos-mbed-mail,tests-mbed_drivers-c_strings -t K64F-ARM,K64F-GCC_ARM
```
### Selecting platforms
You can limit which boards Greentea uses for testing by using the `--use-tids` argument.
```
$ mbedgt --use-tids 02400203C3423E603EBEC3D8,024002031E031E6AE3FFE3D2
```
Where ```02400203C3423E603EBEC3D8``` and ```024002031E031E6AE3FFE3D2``` are the target IDs of platforms attached to your system.
You can view target IDs using the [mbed-ls](https://pypi.org/project/mbed-ls) tool (installed with Greentea).
```
$ mbedls
+--------------+---------------------+------------+------------+-------------------------+
|platform_name |platform_name_unique |mount_point |serial_port |target_id |
+--------------+---------------------+------------+------------+-------------------------+
|K64F |K64F[0] |E: |COM160 |024002031E031E6AE3FFE3D2 |
|K64F |K64F[1] |F: |COM162 |02400203C3423E603EBEC3D8 |
|LPC1768 |LPC1768[0] |G: |COM5 |1010ac87cfc4f23c4c57438d |
+--------------+---------------------+------------+------------+-------------------------+
```
In this case, you won't test one target, the LPC1768.
### Testing on Fast Model FVPs
Fast Models FVPs are software models for Arm reference design platfrom
Greentea supports running test on Fast Models. And [mbed-fastmodel-agent](https://github.com/ARMmbed/mbed-fastmodel-agent) module is required for this purpose.
The "--fm" option only available when the `mbed-fastmodel-agent` module is installed :
You can run tests for FVP_MPS2_Cortex-M3 models, by '--fm' option:
```
$ mbedgt --fm FVP_MPS2_M3:DEFAULT
```
Where ```FVP_MPS2_M3``` is the platfrom name for the ```FVP_MPS2_Cortex-M3``` models in mbed OS.
And ```DEFAULT``` is the config to the Fast Model, you can find out using ```mbedfm``` command
### Creating reports
Greentea supports a number of report formats.
#### HTML
This creates an interactive HTML page with test results and logs.
```
mbedgt --report-html html_report.html
```
#### JUnit
This creates an XML JUnit report, which you can use with popular Continuous Integration software, such as [Jenkins](https://jenkins.io/index.html).
```
mbedgt --report-junit junit_report.xml
```
#### JSON
This creates a general JSON report.
```
mbedgt --report-json json_report.json
```
#### Plain text
This creates a human-friendly text summary of the test run.
```
mbedgt --report-text text_report.text
```
## Host test detection
When developing with mbed OS, Greentea detects host tests automatically if you place them in the correct location. All tests in mbed OS are placed under a `TESTS` directory. You may place custom host test scripts in a folder named `host_tests` in this folder. For more information about the mbed OS test directory structure, please see the [mbed CLI documentation](https://docs.mbed.com/docs/mbed-os-handbook/en/latest/dev_tools/cli/#test-directory-structure).
## Common issues
### `IOERR_SERIAL` errors
Possible causes:
- Another program is using the serial port. Be sure all terminals and other instances of Greentea are closed before trying again.
- The mbed interface firmware is out of date. Please see the platform's page on [developer.mbed.org](https://developer.mbed.org/) for details about how to update it.

View File

@ -0,0 +1,29 @@
"""
mbed SDK
Copyright (c) 2011-2015 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.
Author: Przemyslaw Wirkus <Przemyslaw.Wirkus@arm.com>
"""
from .mbed_greentea_cli import main
"""! @package mbed-greentea
This is a test suite used by mbed project. If you have yotta package with tests you can run them on supported hardware
This test suite supports:
* mbed-ls - mbed-enabled device auto detection module
* mbed-host-test - mbed-enabled device test framework (flash, reset and make host tests)
"""

View File

@ -0,0 +1,19 @@
"""
mbed SDK
Copyright (c) 2011-2015 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.
"""
from mbed_greentea.mbed_greentea_cli import main
exit(main())

View File

@ -0,0 +1,25 @@
"""
mbed SDK
Copyright (c) 2011-2016 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.
Author: Przemyslaw Wirkus <Przemyslaw.Wirkus@arm.com>
"""
from mbed_os_tools.test.cmake_handlers import (
load_ctest_testsuite,
parse_ctesttestfile_line,
list_binaries_for_targets,
list_binaries_for_builds,
)

View File

@ -0,0 +1,23 @@
"""
mbed SDK
Copyright (c) 2011-2016 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.
Author: Przemyslaw Wirkus <Przemyslaw.wirkus@arm.com>
"""
from mbed_os_tools.test.mbed_common_api import (
run_cli_command,
run_cli_process,
)

View File

@ -0,0 +1,23 @@
"""
mbed SDK
Copyright (c) 2011-2016 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.
Author: Przemyslaw Wirkus <Przemyslaw.wirkus@arm.com>
"""
from mbed_os_tools.test.mbed_coverage_api import (
coverage_pack_hex_payload,
coverage_dump_file,
)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,37 @@
"""
mbed SDK
Copyright (c) 2011-2015 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.
Author: Przemyslaw Wirkus <Przemyslaw.Wirkus@arm.com>
"""
from mbed_os_tools.test.mbed_greentea_dlm import (
HOME_DIR,
GREENTEA_HOME_DIR,
GREENTEA_GLOBAL_LOCK,
GREENTEA_KETTLE,
GREENTEA_KETTLE_PATH,
greentea_home_dir_init,
greentea_get_app_sem,
greentea_get_target_lock,
greentea_get_global_lock,
greentea_update_kettle,
greentea_clean_kettle,
greentea_acquire_target_id,
greentea_acquire_target_id_from_list,
greentea_release_target_id,
get_json_data_from_file,
greentea_kettle_info,
)

View File

@ -0,0 +1,21 @@
"""
mbed SDK
Copyright (c) 2011-2015 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.
Author: Przemyslaw Wirkus <Przemyslaw.wirkus@arm.com>
"""
from mbed_os_tools.test.mbed_greentea_hooks import (
GreenteaTestHook,
GreenteaCliTestHook,
LcovHook,
GreenteaHooks,
)

View File

@ -0,0 +1,24 @@
"""
mbed SDK
Copyright (c) 2011-2015 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.
Author: Przemyslaw Wirkus <Przemyslaw.Wirkus@arm.com>
"""
from mbed_os_tools.test.mbed_greentea_log import (
COLORAMA,
GreenTeaSimpleLockLogger,
gt_logger,
)

View File

@ -0,0 +1,38 @@
"""
mbed SDK
Copyright (c) 2011-2015 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.
Author: Przemyslaw Wirkus <Przemyslaw.wirkus@arm.com>
"""
from mbed_os_tools.test.mbed_report_api import (
export_to_file,
exporter_json,
exporter_text,
exporter_testcase_text,
exporter_testcase_junit,
html_template,
TEST_RESULT_COLOURS,
TEST_RESULT_DEFAULT_COLOUR,
get_result_colour_class_css,
get_result_colour_class,
get_dropdown_html,
get_result_overlay_testcase_dropdown,
get_result_overlay_testcases_dropdown_menu,
get_result_overlay_dropdowns,
get_result_overlay,
exporter_html,
exporter_memory_metrics_csv,
)

View File

@ -0,0 +1,36 @@
"""
mbed SDK
Copyright (c) 2011-2016 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.
Author: Przemyslaw Wirkus <Przemyslaw.Wirkus@arm.com>
"""
from mbed_os_tools.test.mbed_target_info import (
TARGET_INFO_MAPPING,
TARGET_TOOLCAHINS,
get_mbed_target_call_yotta_target,
parse_yotta_json_for_build_name,
get_yotta_target_from_local_config,
get_mbed_target_from_current_dir,
parse_yotta_target_cmd_output,
get_mbed_targets_from_yotta_local_module,
parse_mbed_target_from_target_json,
get_mbed_targets_from_yotta,
parse_yotta_search_cmd_output,
add_target_info_mapping,
get_mbed_clasic_target_info,
get_binary_type_for_platform,
get_platform_property,
)

View File

@ -0,0 +1,267 @@
"""
mbed SDK
Copyright (c) 2011-2016 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.
Author: Przemyslaw Wirkus <Przemyslaw.wirkus@arm.com>
"""
import os
from time import time
from mbed_os_tools.test.mbed_test_api import (
TEST_RESULT_OK,
TEST_RESULT_FAIL,
TEST_RESULT_ERROR,
TEST_RESULT_SKIPPED,
TEST_RESULT_UNDEF,
TEST_RESULT_IOERR_COPY,
TEST_RESULT_IOERR_DISK,
TEST_RESULT_IOERR_SERIAL,
TEST_RESULT_TIMEOUT,
TEST_RESULT_NO_IMAGE,
TEST_RESULT_MBED_ASSERT,
TEST_RESULT_BUILD_FAILED,
TEST_RESULT_SYNC_FAILED,
TEST_RESULTS,
TEST_RESULT_MAPPING,
RUN_HOST_TEST_POPEN_ERROR,
get_test_result,
run_command,
run_htrun,
get_testcase_count_and_names,
get_testcase_utest,
get_coverage_data,
get_printable_string,
get_testcase_summary,
get_testcase_result,
get_memory_metrics,
get_thread_with_max_stack_size,
get_thread_stack_info_summary,
log_mbed_devices_in_table,
get_test_spec,
get_test_build_properties,
parse_global_resource_mgr,
parse_fast_model_connection,
gt_logger,
)
def run_host_test(image_path,
disk,
port,
build_path,
target_id,
duration=10,
micro=None,
reset=None,
verbose=False,
copy_method=None,
program_cycle_s=None,
forced_reset_timeout=None,
digest_source=None,
json_test_cfg=None,
max_failed_properties=5,
enum_host_tests_path=None,
global_resource_mgr=None,
fast_model_connection=None,
compare_log=None,
num_sync_packtes=None,
polling_timeout=None,
retry_count=1,
tags=None,
run_app=None):
"""! This function runs host test supervisor (executes mbedhtrun) and checks output from host test process.
@param image_path Path to binary file for flashing
@param disk Currently mounted mbed-enabled devices disk (mount point)
@param port Currently mounted mbed-enabled devices serial port (console)
@param duration Test case timeout
@param micro Mbed-enabled device name
@param reset Reset type
@param forced_reset_timeout Reset timeout (sec)
@param verbose Verbose mode flag
@param copy_method Copy method type (name)
@param program_cycle_s Wait after flashing delay (sec)
@param json_test_cfg Additional test configuration file path passed to host tests in JSON format
@param max_failed_properties After how many unknown properties we will assume test is not ported
@param enum_host_tests_path Directory where locally defined host tests may reside
@param num_sync_packtes sync packets to send for host <---> device communication
@param polling_timeout Timeout in sec for readiness of mount point and serial port of local or remote device
@param tags Filter list of available devices under test to only run on devices with the provided list
of tags [tag-filters tag1,tag]
@param run_app Run application mode flag (we run application and grab serial port data)
@param digest_source if None mbedhtrun will be executed. If 'stdin',
stdin will be used via StdInObserver or file (if
file name was given as switch option)
@return Tuple with test results, test output, test duration times, test case results, and memory metrics.
Return int > 0 if running mbedhtrun process failed.
Retrun int < 0 if something went wrong during mbedhtrun execution.
"""
def get_binary_host_tests_dir(binary_path, level=2):
"""! Checks if in binary test group has host_tests directory
@param binary_path Path to binary in test specification
@param level How many directories above test host_tests dir exists
@return Path to host_tests dir in group binary belongs too, None if not found
"""
try:
binary_path_norm = os.path.normpath(binary_path)
current_path_norm = os.path.normpath(os.getcwd())
host_tests_path = binary_path_norm.split(os.sep)[:-level] + ['host_tests']
build_dir_candidates = ['BUILD', '.build']
idx = None
for build_dir_candidate in build_dir_candidates:
if build_dir_candidate in host_tests_path:
idx = host_tests_path.index(build_dir_candidate)
break
if idx is None:
msg = 'The following directories were not in the path: %s' % (', '.join(build_dir_candidates))
raise Exception(msg)
# Cut /<build dir>/tests/TOOLCHAIN/TARGET
host_tests_path = host_tests_path[:idx] + host_tests_path[idx+4:]
host_tests_path = os.sep.join(host_tests_path)
except Exception as e:
gt_logger.gt_log_warn("there was a problem while looking for host_tests directory")
gt_logger.gt_log_tab("level %d, path: %s"% (level, binary_path))
gt_logger.gt_log_tab(str(e))
return None
if os.path.isdir(host_tests_path):
return host_tests_path
return None
if not enum_host_tests_path:
# If there is -e specified we will try to find a host_tests path ourselves
#
# * Path to binary starts from "build" directory, and goes 4 levels
# deep: ./build/tests/compiler/toolchain
# * Binary is inside test group.
# For example: <app>/tests/test_group_name/test_dir/*,cpp.
# * We will search for directory called host_tests on the level of test group (level=2)
# or on the level of tests directory (level=3).
#
# If host_tests directory is found above test code will will pass it to mbedhtrun using
# switch -e <path_to_host_tests_dir>
gt_logger.gt_log("checking for 'host_tests' directory above image directory structure", print_text=verbose)
test_group_ht_path = get_binary_host_tests_dir(image_path, level=2)
TESTS_dir_ht_path = get_binary_host_tests_dir(image_path, level=3)
if test_group_ht_path:
enum_host_tests_path = test_group_ht_path
elif TESTS_dir_ht_path:
enum_host_tests_path = TESTS_dir_ht_path
if enum_host_tests_path:
gt_logger.gt_log_tab("found 'host_tests' directory in: '%s'"% enum_host_tests_path, print_text=verbose)
else:
gt_logger.gt_log_tab("'host_tests' directory not found: two directory levels above image path checked", print_text=verbose)
gt_logger.gt_log("selecting test case observer...", print_text=verbose)
if digest_source:
gt_logger.gt_log_tab("selected digest source: %s"% digest_source, print_text=verbose)
# Select who will digest test case serial port data
if digest_source == 'stdin':
# When we want to scan stdin for test results
raise NotImplementedError
elif digest_source is not None:
# When we want to open file to scan for test results
raise NotImplementedError
# Command executing CLI for host test supervisor (in detect-mode)
cmd = ["mbedhtrun",
'-m', micro,
'-p', port,
'-f', '"%s"'% image_path,
]
if enum_host_tests_path:
cmd += ["-e", '"%s"'% enum_host_tests_path]
if global_resource_mgr:
# Use global resource manager to execute test
# Example:
# $ mbedhtrun -p :9600 -f "tests-mbed_drivers-generic_tests.bin" -m K64F --grm raas_client:10.2.203.31:8000
cmd += ['--grm', global_resource_mgr]
else:
# Use local resources to execute tests
# Add extra parameters to host_test
if disk:
cmd += ["-d", disk]
if copy_method:
cmd += ["-c", copy_method]
if target_id:
cmd += ["-t", target_id]
if reset:
cmd += ["-r", reset]
if run_app:
cmd += ["--run"] # -f stores binary name!
if fast_model_connection:
# Use simulator resource manager to execute test
# Example:
# $ mbedhtrun -f "tests-mbed_drivers-generic_tests.elf" -m FVP_MPS2_M3 --fm DEFAULT
cmd += ['--fm', fast_model_connection]
if compare_log:
cmd += ['--compare-log', compare_log]
if program_cycle_s:
cmd += ["-C", str(program_cycle_s)]
if forced_reset_timeout:
cmd += ["-R", str(forced_reset_timeout)]
if json_test_cfg:
cmd += ["--test-cfg", '"%s"' % str(json_test_cfg)]
if num_sync_packtes:
cmd += ["--sync",str(num_sync_packtes)]
if tags:
cmd += ["--tag-filters", tags]
if polling_timeout:
cmd += ["-P", str(polling_timeout)]
gt_logger.gt_log_tab("calling mbedhtrun: %s" % " ".join(cmd), print_text=verbose)
gt_logger.gt_log("mbed-host-test-runner: started")
for retry in range(1, 1 + retry_count):
start_time = time()
returncode, htrun_output = run_htrun(cmd, verbose)
end_time = time()
if returncode < 0:
return returncode
elif returncode == 0:
break
gt_logger.gt_log("retry mbedhtrun {}/{}".format(retry, retry_count))
else:
gt_logger.gt_log("{} failed after {} count".format(cmd, retry_count))
testcase_duration = end_time - start_time # Test case duration from reset to {end}
htrun_output = get_printable_string(htrun_output)
result = get_test_result(htrun_output)
result_test_cases = get_testcase_result(htrun_output)
test_cases_summary = get_testcase_summary(htrun_output)
max_heap, reserved_heap, thread_stack_info = get_memory_metrics(htrun_output)
thread_stack_summary = []
if thread_stack_info:
thread_stack_summary = get_thread_stack_info_summary(thread_stack_info)
memory_metrics = {
"max_heap": max_heap,
"reserved_heap": reserved_heap,
"thread_stack_info": thread_stack_info,
"thread_stack_summary": thread_stack_summary
}
get_coverage_data(build_path, htrun_output)
gt_logger.gt_log("mbed-host-test-runner: stopped and returned '%s'"% result, print_text=verbose)
return (result, htrun_output, testcase_duration, duration, result_test_cases, test_cases_summary, memory_metrics)

View File

@ -0,0 +1,25 @@
"""
mbed SDK
Copyright (c) 2011-2016 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.
Author: Przemyslaw Wirkus <Przemyslaw.wirkus@arm.com>
"""
from mbed_os_tools.test.mbed_yotta_api import (
YottaError,
build_with_yotta,
get_platform_name_from_yotta_target,
get_test_spec_from_yt_module,
)

View File

@ -0,0 +1,23 @@
"""
mbed SDK
Copyright (c) 2011-2016 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.
Author: Przemyslaw Wirkus <Przemyslaw.Wirkus@arm.com>
"""
from mbed_os_tools.test.mbed_yotta_module_parse import (
YottaConfig,
YottaModule
)

View File

@ -0,0 +1,30 @@
"""
mbed SDK
Copyright (c) 2011-2016 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.
Author: Azim Khan <Azim.Khan@arm.com>
"""
"""
This module contains classes to represent Test Specification interface that defines the data to be generated by/from
a build system to give enough information to Greentea.
"""
from mbed_os_tools.test.tests_spec import (
TestBinary,
Test,
TestBuild,
TestSpec,
)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,36 @@
"""
mbed SDK
Copyright (c) 2011-2016 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.
Author: Przemyslaw Wirkus <Przemyslaw.Wirkus@arm.com>
"""
"""! @package mbed-host-tests
Flash, reset and perform host supervised tests on mbed platforms.
Write your own programs (import this package) or use 'mbedhtrun' command line tool instead.
"""
from mbed_os_tools.test import (
host_tests_plugins,
HostRegistry,
BaseHostTest,
event_callback,
DEFAULT_BAUD_RATE,
get_plugin_caps,
init_host_test_cli_params,
)

View File

@ -0,0 +1,19 @@
"""
mbed SDK
Copyright (c) 2011-2013 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.
"""
# base host test class
from .base_host_test import BaseHostTest, event_callback

View File

@ -0,0 +1,23 @@
"""
mbed SDK
Copyright (c) 2011-2016 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.
"""
from mbed_os_tools.test.host_tests.base_host_test import (
BaseHostTestAbstract,
event_callback,
HostTestCallbackBase,
BaseHostTest,
)

View File

@ -0,0 +1,18 @@
"""
mbed SDK
Copyright (c) 2011-2013 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.
"""
from mbed_os_tools.test.host_tests.default_auto import DefaultAuto

View File

@ -0,0 +1,18 @@
"""
mbed SDK
Copyright (c) 2011-2013 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.
"""
from mbed_os_tools.test.host_tests.detect_auto import DetectPlatformTest

View File

@ -0,0 +1,18 @@
"""
mbed SDK
Copyright (c) 2011-2013 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.
"""
from mbed_os_tools.test.host_tests.dev_null_auto import DevNullTest

View File

@ -0,0 +1,18 @@
"""
mbed SDK
Copyright (c) 2011-2016 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.
"""
from mbed_os_tools.test.host_tests.echo import EchoTest

View File

@ -0,0 +1,18 @@
"""
mbed SDK
Copyright (c) 2011-2013 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.
"""
from mbed_os_tools.test.host_tests.hello_auto import HelloTest

View File

@ -0,0 +1,18 @@
"""
mbed SDK
Copyright (c) 2011-2013 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.
"""
from mbed_os_tools.test.host_tests.rtc_auto import RTCTest

View File

@ -0,0 +1,18 @@
"""
mbed SDK
Copyright (c) 2011-2013 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.
"""
from mbed_os_tools.test.host_tests.wait_us_auto import WaitusTest

View File

@ -0,0 +1,20 @@
"""
mbed SDK
Copyright (c) 2011-2016 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.
Author: Przemyslaw Wirkus <Przemyslaw.Wirkus@arm.com>
"""
from .conn_proxy import conn_process

View File

@ -0,0 +1,21 @@
"""
mbed SDK
Copyright (c) 2011-2016 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.
"""
from mbed_os_tools.test.host_tests_conn_proxy.conn_primitive import (
ConnectorPrimitiveException,
ConnectorPrimitive,
)

View File

@ -0,0 +1,20 @@
"""
mbed SDK
Copyright (c) 2011-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.
"""
from mbed_os_tools.test.host_tests_conn_proxy.conn_primitive_fastmodel import (
FastmodelConnectorPrimitive,
)

View File

@ -0,0 +1,20 @@
"""
mbed SDK
Copyright (c) 2011-2016 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.
"""
from mbed_os_tools.test.host_tests_conn_proxy.conn_primitive_remote import (
RemoteConnectorPrimitive,
)

View File

@ -0,0 +1,21 @@
"""
mbed SDK
Copyright (c) 2011-2016 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.
"""
from mbed_os_tools.test.host_tests_conn_proxy.conn_primitive_serial import (
SerialConnectorPrimitive,
)

View File

@ -0,0 +1,22 @@
"""
mbed SDK
Copyright (c) 2011-2016 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.
"""
from mbed_os_tools.test.host_tests_conn_proxy.conn_proxy import (
KiViBufferWalker,
conn_primitive_factory,
conn_process,
)

View File

@ -0,0 +1,20 @@
"""
mbed SDK
Copyright (c) 2011-2016 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.
Author: Przemyslaw Wirkus <Przemyslaw.Wirkus@arm.com>
"""
from .ht_logger import HtrunLogger

View File

@ -0,0 +1,18 @@
"""
mbed SDK
Copyright (c) 2011-2016 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.
"""
from mbed_os_tools.test.host_tests_logger.ht_logger import HtrunLogger

View File

@ -0,0 +1,33 @@
"""
mbed SDK
Copyright (c) 2011-2015 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.
Author: Przemyslaw Wirkus <Przemyslaw.Wirkus@arm.com>
"""
"""! @package mbed-host-test-plugins
This package contains plugins used by host test to reset, flash devices etc.
This package can be extended with new packages to add more generic functionality
"""
from mbed_os_tools.test.host_tests_plugins import (
HOST_TEST_PLUGIN_REGISTRY,
call_plugin,
get_plugin_caps,
get_plugin_info,
print_plugin_info,
)

View File

@ -0,0 +1,22 @@
"""
mbed SDK
Copyright (c) 2011-2015 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.
Author: Przemyslaw Wirkus <Przemyslaw.Wirkus@arm.com>
"""
from mbed_os_tools.test.host_tests_plugins.host_test_plugins import (
HostTestPluginBase,
)

View File

@ -0,0 +1,22 @@
"""
mbed SDK
Copyright (c) 2011-2015 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.
Author: Przemyslaw Wirkus <Przemyslaw.Wirkus@arm.com>
"""
from mbed_os_tools.test.host_tests_plugins.host_test_registry import (
HostTestRegistry,
)

View File

@ -0,0 +1,23 @@
"""
mbed SDK
Copyright (c) 2011-2015 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.
Author: Przemyslaw Wirkus <Przemyslaw.Wirkus@arm.com>
"""
from mbed_os_tools.test.host_tests_plugins.module_copy_jn51xx import (
HostTestPluginCopyMethod_JN51xx,
load_plugin,
)

View File

@ -0,0 +1,23 @@
"""
mbed SDK
Copyright (c) 2011-2015 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.
Author: Przemyslaw Wirkus <Przemyslaw.Wirkus@arm.com>
"""
from mbed_os_tools.test.host_tests_plugins.module_copy_mbed import (
HostTestPluginCopyMethod_Mbed,
load_plugin,
)

View File

@ -0,0 +1,23 @@
"""
mbed SDK
Copyright (c) 2011-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.
Author: Przemyslaw Wirkus <Przemyslaw.Wirkus@arm.com>
"""
from mbed_os_tools.test.host_tests_plugins.module_copy_mps2 import (
HostTestPluginCopyMethod_MPS2,
load_plugin,
)

View File

@ -0,0 +1,23 @@
"""
mbed SDK
Copyright (c) 2016-2016,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.
Author: Russ Butler <russ.butler@arm.com>
"""
from mbed_os_tools.test.host_tests_plugins.module_copy_pyocd import (
HostTestPluginCopyMethod_pyOCD,
load_plugin,
)

View File

@ -0,0 +1,23 @@
"""
mbed SDK
Copyright (c) 2011-2015 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.
Author: Przemyslaw Wirkus <Przemyslaw.Wirkus@arm.com>
"""
from mbed_os_tools.test.host_tests_plugins.module_copy_shell import (
HostTestPluginCopyMethod_Shell,
load_plugin,
)

View File

@ -0,0 +1,23 @@
"""
mbed SDK
Copyright (c) 2011-2015 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.
Author: Przemyslaw Wirkus <Przemyslaw.Wirkus@arm.com>
"""
from mbed_os_tools.test.host_tests_plugins.module_copy_silabs import (
HostTestPluginCopyMethod_Silabs,
load_plugin,
)

View File

@ -0,0 +1,23 @@
"""
mbed SDK
Copyright (c) 2011-2015 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.
Author: Przemyslaw Wirkus <Przemyslaw.Wirkus@arm.com>
"""
from mbed_os_tools.test.host_tests_plugins.module_copy_stlink import (
HostTestPluginCopyMethod_Stlink,
load_plugin,
)

View File

@ -0,0 +1,23 @@
"""
mbed SDK
Copyright (c) 2011-2015 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.
Author: Przemyslaw Wirkus <Przemyslaw.Wirkus@arm.com>
"""
from mbed_os_tools.test.host_tests_plugins.module_copy_ublox import (
HostTestPluginCopyMethod_ublox,
load_plugin,
)

View File

@ -0,0 +1,23 @@
"""
mbed SDK
Copyright (c) 2011-2015 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.
Author: Przemyslaw Wirkus <Przemyslaw.Wirkus@arm.com>
"""
from mbed_os_tools.test.host_tests_plugins.module_power_cycle_mbed import (
HostTestPluginPowerCycleResetMethod,
load_plugin,
)

View File

@ -0,0 +1,23 @@
"""
mbed SDK
Copyright (c) 2011-2015 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.
Author: Przemyslaw Wirkus <Przemyslaw.Wirkus@arm.com>
"""
from mbed_os_tools.test.host_tests_plugins.module_reset_jn51xx import (
HostTestPluginResetMethod_JN51xx,
load_plugin,
)

View File

@ -0,0 +1,23 @@
"""
mbed SDK
Copyright (c) 2011-2015 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.
Author: Przemyslaw Wirkus <Przemyslaw.Wirkus@arm.com>
"""
from mbed_os_tools.test.host_tests_plugins.module_reset_mbed import (
HostTestPluginResetMethod_Mbed,
load_plugin,
)

View File

@ -0,0 +1,23 @@
"""
mbed SDK
Copyright (c) 2011-2015 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.
Author: Przemyslaw Wirkus <Przemyslaw.Wirkus@arm.com>
"""
from mbed_os_tools.test.host_tests_plugins.module_reset_mps2 import (
HostTestPluginResetMethod_MPS2,
load_plugin,
)

View File

@ -0,0 +1,23 @@
"""
mbed SDK
Copyright (c) 2016-2016,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.
Author: Russ Butler <russ.butler@arm.com>
"""
from mbed_os_tools.test.host_tests_plugins.module_reset_pyocd import (
HostTestPluginResetMethod_pyOCD,
load_plugin,
)

View File

@ -0,0 +1,23 @@
"""
mbed SDK
Copyright (c) 2011-2015 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.
Author: Przemyslaw Wirkus <Przemyslaw.Wirkus@arm.com>
"""
from mbed_os_tools.test.host_tests_plugins.module_reset_silabs import (
HostTestPluginResetMethod_SiLabs,
load_plugin,
)

View File

@ -0,0 +1,23 @@
"""
mbed SDK
Copyright (c) 2011-2015 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.
Author: Przemyslaw Wirkus <Przemyslaw.Wirkus@arm.com>
"""
from mbed_os_tools.test.host_tests_plugins.module_reset_stlink import (
HostTestPluginResetMethod_Stlink,
load_plugin,
)

View File

@ -0,0 +1,23 @@
"""
mbed SDK
Copyright (c) 2011-2015 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.
Author: Przemyslaw Wirkus <Przemyslaw.Wirkus@arm.com>
"""
from mbed_os_tools.test.host_tests_plugins.module_reset_ublox import (
HostTestPluginResetMethod_ublox,
load_plugin,
)

View File

@ -0,0 +1,26 @@
"""
mbed SDK
Copyright (c) 2011-2015 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.
Author: Przemyslaw Wirkus <Przemyslaw.Wirkus@arm.com>
"""
"""! @package host_registry
Host registry is used to store all host tests (by id) which can be called from test framework
"""
from .host_registry import HostRegistry

View File

@ -0,0 +1,20 @@
"""
mbed SDK
Copyright (c) 2011-2015 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.
Author: Przemyslaw Wirkus <Przemyslaw.Wirkus@arm.com>
"""
from mbed_os_tools.test.host_tests_registry.host_registry import HostRegistry

View File

@ -0,0 +1,25 @@
"""
mbed SDK
Copyright (c) 2011-2015 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.
Author: Przemyslaw Wirkus <Przemyslaw.Wirkus@arm.com>
"""
"""! @package mbed-host-test-runner
This package contains basic host test implementation with algorithms to flash and reset device.
Functionality can be overridden by set of plugins which can provide specialised flashing and reset implementations.
"""

View File

@ -0,0 +1,24 @@
"""
mbed SDK
Copyright (c) 2011-2016 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.
Author: Przemyslaw Wirkus <Przemyslaw.Wirkus@arm.com>
"""
from mbed_os_tools.test.host_tests_runner.host_test import (
HostTestResults,
Test,
DefaultTestSelectorBase,
)

View File

@ -0,0 +1,22 @@
"""
mbed SDK
Copyright (c) 2011-2016 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.
Author: Przemyslaw Wirkus <Przemyslaw.Wirkus@arm.com>
"""
from mbed_os_tools.test.host_tests_runner.host_test_default import (
DefaultTestSelector,
)

View File

@ -0,0 +1,20 @@
"""
mbed SDK
Copyright (c) 2011-2016 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.
Author: Przemyslaw Wirkus <Przemyslaw.Wirkus@arm.com>
"""
from mbed_os_tools.test.host_tests_runner.mbed_base import Mbed

View File

@ -0,0 +1,22 @@
"""
mbed SDK
Copyright (c) 2011-2016 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.
Author: Przemyslaw Wirkus <Przemyslaw.Wirkus@arm.com>
"""
from .host_functional import reset_dev
from .host_functional import flash_dev
from .host_functional import handle_send_break_cmd

View File

@ -0,0 +1,24 @@
"""
mbed SDK
Copyright (c) 2011-2016 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.
Author: Przemyslaw Wirkus <Przemyslaw.Wirkus@arm.com>
"""
from mbed_os_tools.test.host_tests_toolbox.host_functional import (
flash_dev,
reset_dev,
handle_send_break_cmd,
)

View File

@ -0,0 +1,99 @@
"""
mbed SDK
Copyright (c) 2011-2016 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.
Author: Przemyslaw Wirkus <Przemyslaw.Wirkus@arm.com>
"""
import sys
import optparse
### Flashing/Reset API provided by mbed--host-tests (mbedhtrun)
from mbed_os_tools.test import host_tests_plugins
def cmd_parser_setup():
"""! Creates simple command line parser
"""
parser = optparse.OptionParser()
parser.add_option('-f', '--file',
dest='filename',
help='File to flash onto mbed device')
parser.add_option("-d", "--disk",
dest="disk",
help="Target disk (mount point) path. Example: F:, /mnt/MBED",
metavar="DISK_PATH")
copy_methods_str = "Plugin support: " + ', '.join(host_tests_plugins.get_plugin_caps('CopyMethod'))
parser.add_option("-c", "--copy",
dest="copy_method",
default='shell',
help="Copy (flash the target) method selector. " + copy_methods_str,
metavar="COPY_METHOD")
parser.add_option('', '--plugins',
dest='list_plugins',
default=False,
action="store_true",
help='Prints registered plugins and exits')
parser.add_option('', '--version',
dest='version',
default=False,
action="store_true",
help='Prints package version and exits')
parser.description = """Flash mbed devices from command line.""" \
"""This module is using build in to mbed-host-tests plugins used for flashing mbed devices"""
parser.epilog = """Example: mbedflsh -d E: -f /path/to/file.bin"""
(opts, args) = parser.parse_args()
return (opts, args)
def main():
"""! Function wrapping flashing (copy) plugin
@details USers can use mbedflsh command to flash mbeds from command line
"""
errorlevel_flag = 0
(opts, args) = cmd_parser_setup()
if opts.version:
import pkg_resources # part of setuptools
version = pkg_resources.require("mbed-host-tests")[0].version
print(version)
sys.exit(0)
elif opts.list_plugins: # --plugins option
host_tests_plugins.print_plugin_info()
sys.exit(0)
else:
pass
if opts.filename:
print("mbedflsh: opening file %s..."% opts.filename)
result = host_tests_plugins.call_plugin('CopyMethod',
opts.copy_method,
image_path=opts.filename,
destination_disk=opts.disk)
errorlevel_flag = result == True
return errorlevel_flag
if __name__ == '__main__':
exit(main())

View File

@ -0,0 +1,66 @@
"""
mbed SDK
Copyright (c) 2011-2016 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.
Author: Przemyslaw Wirkus <Przemyslaw.Wirkus@arm.com>
"""
from __future__ import print_function
from multiprocessing import freeze_support
from mbed_os_tools.test import init_host_test_cli_params
from mbed_os_tools.test.host_tests_runner.host_test_default import DefaultTestSelector
from mbed_os_tools.test.host_tests_toolbox.host_functional import handle_send_break_cmd
def main():
"""! This function drives command line tool 'mbedhtrun' which is using DefaultTestSelector
@details 1. Create DefaultTestSelector object and pass command line parameters
2. Call default test execution function run() to start test instrumentation
"""
freeze_support()
result = 0
cli_params = init_host_test_cli_params()
if cli_params.version: # --version
import pkg_resources # part of setuptools
version = pkg_resources.require("mbed-host-tests")[0].version
print(version)
elif cli_params.send_break_cmd: # -b with -p PORT (and optional -r RESET_TYPE)
handle_send_break_cmd(
port=cli_params.port,
disk=cli_params.disk,
reset_type=cli_params.forced_reset_type,
baudrate=cli_params.baud_rate,
verbose=cli_params.verbose
)
else:
test_selector = DefaultTestSelector(cli_params)
try:
result = test_selector.execute()
# Ensure we don't return a negative value
if result < 0 or result > 255:
result = 1
except (KeyboardInterrupt, SystemExit):
test_selector.finish()
result = 1
raise
else:
test_selector.finish()
return result
if __name__ == '__main__':
exit(main())

View File

@ -0,0 +1,454 @@
# Development moved
The development of Mbed LS has been moved into the [mbed-os-tools](../../src/mbed_os_tools) package. You can continue to use this module for legacy reasons, however all further development should be continued in the new package.
-------------
[![PyPI version](https://badge.fury.io/py/mbed-ls.svg)](https://badge.fury.io/py/mbed-ls)
# Mbed LS
Mbed LS is a Python (2 and 3) module that detects and lists Mbed Enabled devices connected to the host computer. The Mbed OS team publishes Mbed LS on PyPI. It works on all major operating systems (Windows, Linux and Mac OS X).
It provides the following information for all connected boards in a console (terminal) output:
- Mbed OS platform name.
- Mount point (MSD or disk).
- Serial port.
# Installation
## Installation from PyPI (Python Package Index)
To install Mbed LS from [PyPI](https://pypi.python.org/pypi/mbed-ls), run the following command:
```bash
$ pip install mbed-ls --upgrade
```
## Installation from Python sources
**Prerequisites:** You need to have [Python 2.7.x](https://www.python.org/download/releases/2.7/) or [Python 3.6.x](https://www.python.org/downloads/release/python-362/) installed on your system.
**Note:** If your OS is Windows, please follow the installation instructions [for the serial port driver](https://os.mbed.com/docs/latest/tutorials/windows-serial-driver.html).
Install Mbed LS from sources with the following commands:
```bash
$ git clone https://github.com/ARMmbed/mbed-os-tools.git
$ cd mbed-os-tools/packages/mbed-ls
$ python setup.py install
```
# Command-line
The command-line tool is available with the command `mbedls`.
**Note:** [Mbed CLI](https://github.com/armmbed/mbed-cli) has a similarly-named command `mbed ls`; however, the commands are different. Be sure to omit the space when using the Mbed LS command-line tool.
```bash
$ mbedls
+---------------+----------------------+-------------+-------------+--------------------------------------------------+-----------------+
| platform_name | platform_name_unique | mount_point | serial_port | target_id | daplink_version |
+---------------+----------------------+-------------+-------------+--------------------------------------------------+-----------------+
| K64F | K64F[0] | D: | COM18 | 0240000032044e4500257009997b00386781000097969900 | 0244 |
+---------------+----------------------+-------------+-------------+--------------------------------------------------+-----------------+
```
## Result formats
The Mbed LS command-line accepts a few arguments to change the format of the results. The default format is a table. You may pass `--simple` to simplify this table format, and `--json` to print the table as a json list of the rows.
### Simple (no table formatting)
```
$ mbedls --simple
K64F K64F[0] D: COM18 0240000032044e4500257009997b00386781000097969900 0244
```
### JSON
```bash
$ mbedls --json
[
{
"daplink_auto_reset": "0",
"daplink_automation_allowed": "1",
"daplink_bootloader_crc": "0xa65218eb",
"daplink_bootloader_version": "0242",
"daplink_daplink_mode": "Interface",
"daplink_git_sha": "67f8727a030bcc585e982d899fb6382db56d673b",
"daplink_hic_id": "97969900",
"daplink_interface_crc": "0xe4422294",
"daplink_interface_version": "0244",
"daplink_local_mods": "0",
"daplink_overflow_detection": "1",
"daplink_remount_count": "0",
"daplink_unique_id": "0240000032044e4500257009997b00386781000097969900",
"daplink_usb_interfaces": "MSD, CDC, HID",
"daplink_version": "0244",
"mount_point": "D:",
"platform_name": "K64F",
"platform_name_unique": "K64F[0]",
"product_id": "0204",
"serial_port": "COM18",
"target_id": "0240000032044e4500257009997b00386781000097969900",
"target_id_mbed_htm": "0240000032044e4500257009997b00386781000097969900",
"target_id_usb_id": "0240000032044e4500257009997b00386781000097969900",
"vendor_id": "0d28"
}
]
```
## Mocking (renaming) platforms
Override a platform's name using the `--mock` parameter:
```
$ mbedls --mock 0240:MY_NEW_PLATFORM
$ mbedls
+-----------------+----------------------+-------------+-------------+--------------------------------------------------+-----------------+
| platform_name | platform_name_unique | mount_point | serial_port | target_id | daplink_version |
+-----------------+----------------------+-------------+-------------+--------------------------------------------------+-----------------+
| MY_NEW_PLATFORM | MY_NEW_PLATFORM[0] | D: | COM18 | 0240000032044e4500257009997b00386781000097969900 | 0244 |
+-----------------+----------------------+-------------+-------------+--------------------------------------------------+-----------------+
```
The `--mock` parameter accepts a platform ID and a platform name, separated by the `:` character. The platform ID is the first 4 characters of the `target_id`. The platform name is the name you are temporarily assigning to this platform.
To remove a mocked platform, use the `--mock` parameter again. Continuing from the previous example, use `-<platform id>` as the value:
```
$ mbedls --mock -0240
$ mbedls
+---------------+----------------------+-------------+-------------+--------------------------------------------------+-----------------+
| platform_name | platform_name_unique | mount_point | serial_port | target_id | daplink_version |
+---------------+----------------------+-------------+-------------+--------------------------------------------------+-----------------+
| K64F | K64F[0] | D: | COM18 | 0240000032044e4500257009997b00386781000097969900 | 0244 |
+---------------+----------------------+-------------+-------------+--------------------------------------------------+-----------------+
```
You can also remove all mocked platforms by supplying `*` as the `target_id`:
```
$ mbedls --mock="-*"
```
**NOTE:** Due to a quirk in the parameter formatting, the command-line can interpret `-*` as another parameter instead of a value. It is necessary to use the complete `--mock="-*"` syntax, so the command-line interprets each part of the command correctly.
## Retargeting platforms
It is possible to change the returned results for certain platforms depending on the current directory. This is especially useful when developing new platforms.
The command-line tool and Python API check the current directory for a file named `mbedls.json`. When it is present, it overrides the returned values. The format of the `mbedls.json` file is:
```json
{
"<target_id>": {
"<key>": "<value>"
}
}
```
For example, to change the `serial_port` of the K64F with a `target_id` of `0240000032044e4500257009997b00386781000097969900`, the `mbedls.json` file contains the following:
```json
{
"0240000032044e4500257009997b00386781000097969900": {
"serial_port": "COM99"
}
}
```
This results in the following output from the command-line tool:
```bash
$ mbedls
+---------------+----------------------+-------------+-------------+--------------------------------------------------+-----------------+
| platform_name | platform_name_unique | mount_point | serial_port | target_id | daplink_version |
+---------------+----------------------+-------------+-------------+--------------------------------------------------+-----------------+
| K64F | K64F[0] | D: | COM99 | 0240000032044e4500257009997b00386781000097969900 | 0244 |
+---------------+----------------------+-------------+-------------+--------------------------------------------------+-----------------+
```
Note how the `serial_port` value changed from `COM18` to `COM99`. Deleting the `mbedls.json` or using the `--skip-retarget` parameter removes these changes.
# Python API
The Python API is available through the `mbed_lstools` module.
## `mbed_lstools.create(...)`
```python
>>> import mbed_lstools
>>> mbeds = mbed_lstools.create()
>>> mbeds
<mbed_lstools.lstools_win7.MbedLsToolsWin7 instance at 0x02F542B0>
```
This returns an instance that provides access to the rest of the API.
### Arguments
#### `skip_retarget`
**Default:** `False`
When set to `True`, this skips the retargetting step, and the results are unmodified. This enables the same behavior as the `--skip-retarget` command-line flag.
#### `list_unmounted`
**Default:** `False`
When set to `True`, this includes unmounted platforms in the results. This enables the same behavior as the `-u` command-line flag.
## `mbeds.list_mbeds(...)`
```python
>>> import mbed_lstools
>>> mbeds = mbed_lstools.create()
>>> mbeds.list_mbeds(fs_interaction=FSInteraction.BeforeFilter,
filter_function=None,
unique_names=False,
read_details_txt=False)
[{'target_id_mbed_htm': u'0240000032044e4500257009997b00386781000097969900', 'mount_point': 'D:', 'target_id': u'0240000032044e4500257009997b00386781000097969900', 'serial_port': u'COM18', 'target_id_usb_id': u'0240000032044e4500257009997b00386781000097969900', 'platform_name': u'K64F'}]
```
### Arguments
#### `filter_function`
**Default:** `None`
This function allows you to filter results based on platform data. This can hasten the execution of the `list_mbeds` function.
As a normal function definition:
```python
def filter_func(mbed):
return m['platform_name'] == 'K64F'
mbeds.list_mbeds(filter_function=filter_func)
```
As a lambda function:
```python
platforms = mbeds.list_mbeds(filter_function=lambda m: m['platform_name'] == 'K64F')
```
#### `fs_interaction`
**Default:** `FSInteraction.BeforeFilter`
This argument controls the accuracy and speed of this function. There are three choices (in ascending order of accuracy and decreasing order of speed):
- `FSInteraction.NEVER` - This is the fastest option but also potentially the least accurate. It never touches the file system of the devices. It uses only the information available through the USB descriptors. This is appropriate for use in a highly controlled environment (such as an automated Continuous Integration setup). **This has the potential to provide incorrect names and data. It may also lead to devices not being detected at all.**
- `FSInterfaction.AfterFilter` - This accesses the file system but only after application of the `filter_function`. This can lead to speed increases but at the risk of filtering on inaccurate information.
- `FSInteraction.BeforeFilter` - This accesses the file system before doing any filtering. It is the most accurate option and is recommended for most uses. This is the default behavior of the command-line tool and the API.
#### `unique_names`
**Default:** `False`.
Mbed LS assigns a unique name to each platform when this is set to `True`. The unique name takes the form of `K64F[0]`, where the number between the brackets is an incrementing value. This name is accessible through the dictionary member `platform_unique_name` in the returned platform data.
#### `read_details_txt`
**Default:** `False`
Mbed LS reads more data from the file system on each device when this is set to `True`. It can provide useful management data but also takes more time to execute.
## `mbeds.mock_manufacture_id(...)`
```python
>>> import mbed_lstools
>>> mbeds = mbed_lstools.create()
>>> mbeds.mock_manufacture_id('0240', 'CUSTOM_PLATFORM', oper='+')
>>> mbeds.list_mbeds()
[{'target_id': u'0240000032044e4500257009997b00386781000097969900', ... 'platform_name': u'CUSTOM_PLATFORM'}]
>>> mbeds.mock_manufacture_id('0240', '', oper='-')
>>> mbeds.list_mbeds()
[{'target_id': u'0240000032044e4500257009997b00386781000097969900', ... 'platform_name': u'K64F'}]
```
### Arguments
#### `mid`
**Required**
The first four characters of the `target_id` that you want to mock.
#### `platform_name`
**Required**
Overrides the `platform_name` for any platform with a `target_id` that starts with `mid`.
#### `oper`
**Default:** `'+'`
If set to `'+'`, the mocked platform is enabled. If `'-'`, the mocked platform is disabled.
## `mbeds.get_supported_platforms(...)`
```python
>>> import mbed_lstools
>>> mbeds = mbed_lstools.create()
>>> mbeds.get_supported_platforms(device_type='daplink')
{'0240': 'K64F', '0311': 'K66F'}
```
### Arguments
#### `device_type`
**Default:** `'daplink'`
Chooses which device type entries are retrieved from the platform database.
## Logging
Mbed LS uses the Python `logging` module for all of its logging needs. Mbed LS uses the logger `"mbedls"` as its root, and all other loggers start with `"mbedls."`. Configuring the Python root logger automatically redirects all of the Mbed LS logs to the configured endpoint. When using the Python API, configure logging, such as by calling `logging.basicConfig()`.
# Testing
The `/test` directory contains all tests. You can run the tests with the following command:
```
$ python setup.py test
```
## Code coverage
The `coverage` Python package measures code coverage. You can install it with following command:
```
$ pip install coverage --upgrade
```
To run the tests while measuring code coverage, use the following command:
```
$ coverage run setup.py test
```
You can then generate a report:
```
$ coverage report
Name Stmts Miss Cover
-------------------------------------------------------
mbed_lstools\__init__.py 2 0 100%
mbed_lstools\darwin.py 85 7 92%
mbed_lstools\linux.py 45 3 93%
mbed_lstools\lstools_base.py 299 124 59%
mbed_lstools\main.py 134 44 67%
mbed_lstools\platform_database.py 114 4 96%
mbed_lstools\windows.py 98 21 79%
-------------------------------------------------------
TOTAL 777 203 74%
```
# OS-specific behavior
## Windows
The Mbed serial port works by default on Mac and Linux, but Windows needs a driver. Check [here](https://os.mbed.com/docs/latest/tutorials/windows-serial-driver.html) for more details.
## Linux
Mbed LS requires you to mount a platform before it shows up in the results. Many Linux systems do not automatically mount USB devices. We recommend you use an automounter to manage this for you.
There are many automounters available, and it is ultimately up to you to determine which is the best one for your use case. However, the `usbmount` package on Ubuntu makes it easy to start. If you need more control over your automounter, you can build and run an open source project called [ldm](https://github.com/LemonBoy/ldm).
# Mbed Enabled technical requirements overview
This tool relies on board interfaces conforming to certain standards, so it can detect platforms properly. The [Mbed Enabled](https://www.mbed.com/en/about-mbed/mbed-enabled/) program sets these standards. Please see the [Technical Requirements](https://www.mbed.com/en/about-mbed/mbed-enabled/mbed-enabled-program-requirements/) for more information.
## Device unique identifier
Each device must have a unique identifier. This identifier has two parts: a **platform ID** and a **platform unique string**.
The **platform ID** contains four ASCII characters containing only hexadecimal values (A-F and 0-9). This platform ID is the same for all platforms of the same type. For example, all `K64F` platforms have a platform ID of `0240`. `mbedls` uses this to identify the platform.
The **platform unique string** can be any length of characters (a-z, A-Z and 0-9) that you can use to uniquely identify platforms of the same type on the same machine. For example, two FRDM-K64F platforms attached to the same machine could have the following attributes:
```
$ mbedls
+---------------+----------------------+-------------+-------------+--------------------------------------------------+-----------------+
| platform_name | platform_name_unique | mount_point | serial_port | target_id | daplink_version |
+---------------+----------------------+-------------+-------------+--------------------------------------------------+-----------------+
| K64F | K64F[0] | D: | COM18 | 0240000032044e4500257009997b00386781000097969900 | 0244 |
| K64F | K64F[1] | E: | COM19 | 0240000032044e4500257009997b00386781000097840023 | 0244 |
+---------------+----------------------+-------------+-------------+--------------------------------------------------+-----------------+
```
Note how both platforms share the same platform ID (`0240`) but have a unique ending string.
# Adding platform support
If a platform meets the Mbed Enabled technical requirements (stated above), it can be added to Mbed LS.
## Adding a new platform with a supported debugger
Mbed LS currently supports the following types of debuggers:
- [DAPLink](https://github.com/ARMmbed/DAPLink)
- As well as the related but legacy [CMSIS-DAP](https://github.com/mbedmicro/CMSIS-DAP) firmware
- ST-LINK
- J-Link
### Adding support for DAPLink-compatible platforms (DAPLink, ST-LINK, and CMSIS-DAP)
Add an entry to the `daplink` section of the [`DEFAULT_PLATFORM_DB`](../../src/mbed_os_tools/detect/platform_database.py).
If your platform's name is `NEW_PLATFORM` and it has platform ID of `9999`, the new entry should be:
```
DEFAULT_PLATFORM_DB = {
u'daplink': {
...
u'9999': u'NEW_PLATFORM',
...
}
}
```
Please order the entries by the platform ID when adding new platforms.
### Adding support for J-Link platforms
J-Link detection works differently due to the information present on the platform's filesystem. All new entries should be added to the `jlink` section of the [`DEFAULT_PLATFORM_DB`](../../src/mbed_os_tools/detect/platform_database.py).
The following is an example `jlink` platform entry:
```
DEFAULT_PLATFORM_DB = {
...
u'jlink': {
u'X729475D28G': {
u'platform_name': u'NRF51_DK',
u'jlink_device_name': u'nRF51422_xxAC'
},
...
}
}
```
Instead of a platform ID, there is a target-unique string (`X729475D28G` in this case). This should correspond with the unique part of the link present in the `Board.html` or `User Guide.html`. This seems to vary among the platforms. In general, try following the links in each file. You want to use the url that links to a product page that references the platform. The J-Link logic in Mbed LS assumes that the url has the target-unique string on the end (after the last `/` character). In the above example, the expected url structure would be `http://www.nordicsemi.com/X729475D28G`.
If your J-Link platform does not follow this convention, please raise an issue with the following information:
- The name of the platform
- The file **names and contents** present on the platform's filesystem
- A link to the J-Link firmware binary if possible
## Adding a new type of debugger
The type of debugger present on the platform affects how it is detected. The USB Vendor ID is used to detect which type of debugger is present on the platform.
If a new type of debugger is being introduced to Mbed LS with the platform, you will need to add the Vendor ID to the [identification map](../../src/mbed_os_tools/detect/lstools_base.py). You will also need to assign the correct "update from the filesystem" logic [here](../../src/mbed_os_tools/detect/lstools_base.py). If the debugger is compatible with the files presented by DAPLink, you may reuse that implementation when updating the device information from the filesystem. If it is not, you may need to write your own update logic. If you need guidance on this, please ask for it when you submit an issue or a pull request.

View File

@ -0,0 +1,38 @@
"""
mbed SDK
Copyright (c) 2011-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.
"""
"""! @package mbed-ls
mbed-ls package is a set of tools inherited from mbed-lmtools used to detect
mbed enabled devices on host (Windows, Linux and MacOS).
mbed-lstools is a Python module that detects and lists mbed-enabled devices
connected to the host computer. It will be delivered as a redistributable
Python module (package) and command line tool.
Currently supported operating system:
* Windows 7.
* Ubuntu.
* Mac OS X (Darwin).
The stand-alone mbed-lstools Python package is still under development,
but it's already delivered as part of the mbed SDK's test suite and a command
line tool (see below).
"""
from .main import mbedls_main
from .main import create

View File

@ -0,0 +1,18 @@
"""
mbed SDK
Copyright (c) 2011-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.
"""
from mbed_os_tools.detect.darwin import MbedLsToolsDarwin

View File

@ -0,0 +1,18 @@
"""
mbed SDK
Copyright (c) 2011-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.
"""
from mbed_os_tools.detect.linux import MbedLsToolsLinuxGeneric

View File

@ -0,0 +1,25 @@
"""
mbed SDK
Copyright (c) 2011-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.
"""
import functools
import json
import logging
from mbed_os_tools.detect.lstools_base import (
FSInteraction,
MbedLsToolsBase,
)

View File

@ -0,0 +1,202 @@
"""
mbed SDK
Copyright (c) 2011-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.
"""
import sys
import json
import argparse
from collections import defaultdict
# Make sure that any global generic setup is run
from . import lstools_base
from mbed_os_tools.detect.main import (
create,
mbed_os_support,
mbed_lstools_os_info,
mock_platform
)
import logging
logger = logging.getLogger("mbedls.main")
logger.addHandler(logging.NullHandler())
del logging
def get_version():
"""! Get mbed-ls Python module version string """
import mbed_os_tools
return mbed_os_tools.VERSION
def print_version(mbeds, args):
print(get_version())
def print_mbeds(mbeds, args, simple):
devices = mbeds.list_mbeds(unique_names=True, read_details_txt=True)
if devices:
from prettytable import PrettyTable, HEADER
columns = ['platform_name', 'platform_name_unique', 'mount_point',
'serial_port', 'target_id', 'daplink_version']
columns_header = ['platform_name', 'platform_name_unique', 'mount_point',
'serial_port', 'target_id', 'interface_version']
pt = PrettyTable(columns_header, junction_char="|", hrules=HEADER)
pt.align = 'l'
for d in devices:
pt.add_row([d.get(col, None) or 'unknown' for col in columns])
print(pt.get_string(border=not simple, header=not simple,
padding_width=1, sortby='platform_name_unique'))
def print_table(mbeds, args):
return print_mbeds(mbeds, args, False)
def print_simple(mbeds, args):
return print_mbeds(mbeds, args, True)
def list_platforms(mbeds, args):
print(mbeds.list_manufacture_ids())
def mbeds_as_json(mbeds, args):
print(json.dumps(mbeds.list_mbeds(unique_names=True,
read_details_txt=True),
indent=4, sort_keys=True))
def json_by_target_id(mbeds, args):
print(json.dumps({m['target_id']: m for m
in mbeds.list_mbeds(unique_names=True,
read_details_txt=True)},
indent=4, sort_keys=True))
def json_platforms(mbeds, args):
platforms = set()
for d in mbeds.list_mbeds():
platforms |= set([d['platform_name']])
print(json.dumps(list(platforms), indent=4, sort_keys=True))
def json_platforms_ext(mbeds, args):
platforms = defaultdict(lambda: 0)
for d in mbeds.list_mbeds():
platforms[d['platform_name']] += 1
print(json.dumps(platforms, indent=4, sort_keys=True))
def parse_cli(to_parse):
"""! Parse the command line
@return Retrun a namespace that contains:
* command - python function to run
* skip_retarget - bool indicting to skip retargeting
* list_unmounted - list boards that are not mounted
* debug - turn on debug logging
"""
parser = argparse.ArgumentParser()
parser.set_defaults(command=print_table)
commands = parser.add_argument_group('sub commands')\
.add_mutually_exclusive_group()
commands.add_argument(
'-s', '--simple', dest='command', action='store_const',
const=print_simple,
help='list attached targets without column headers and borders')
commands.add_argument(
'-j', '--json', dest='command', action='store_const',
const=mbeds_as_json,
help='list attached targets with detailed information in JSON format')
commands.add_argument(
'-J', '--json-by-target-id', dest='command', action='store_const',
const=json_by_target_id,
help='map attached targets from their target ID to their detailed '
'information in JSON format')
commands.add_argument(
'-p', '--json-platforms', dest='command', action='store_const',
const=json_platforms,
help='list attached platform names in JSON format.')
commands.add_argument(
'-P', '--json-platforms-ext', dest='command', action='store_const',
const=json_platforms_ext,
help='map attached platform names to the number of attached boards in '
'JSON format')
commands.add_argument(
'-l', '--list', dest='command', action='store_const',
const=list_platforms,
help='list all target IDs and their corresponding platform names '
'understood by mbed-ls')
commands.add_argument(
'--version', dest='command', action='store_const', const=print_version,
help='print package version and exit')
commands.add_argument(
'-m', '--mock', metavar='ID:NAME',
help='substitute or create a target ID to platform name mapping used'
'when invoking mbedls in the current directory')
parser.add_argument(
'--skip-retarget', dest='skip_retarget', default=False,
action="store_true",
help='skip parsing and interpretation of the re-target file,'
' `./mbedls.json`')
parser.add_argument(
'-u', '--list-unmounted', dest='list_unmounted', default=False,
action='store_true',
help='list mbeds, regardless of whether they are mounted or not')
parser.add_argument(
'-d', '--debug', dest='debug', default=False, action="store_true",
help='outputs extra debug information useful when creating issues!')
args = parser.parse_args(to_parse)
if args.mock:
args.command = mock_platform
return args
def start_logging():
try:
import colorlog
colorlog.basicConfig(
format='%(log_color)s%(levelname)s%(reset)s:%(name)s:%(message)s')
except ImportError:
import logging
logging.basicConfig()
del logging
def mbedls_main():
"""! Function used to drive CLI (command line interface) application
@return Function exits with success code
"""
start_logging()
args = parse_cli(sys.argv[1:])
import logging
root_logger = logging.getLogger("mbedls")
if args.debug:
root_logger.setLevel(logging.DEBUG)
else:
root_logger.setLevel(logging.INFO)
del logging
logger.debug("mbed-ls ver. %s", get_version())
logger.debug("host: %s", str(mbed_lstools_os_info()))
mbeds = create(skip_retarget=args.skip_retarget,
list_unmounted=args.list_unmounted,
force_mock=args.command is mock_platform)
if mbeds is None:
logger.critical('This platform is not supported! Pull requests welcome at github.com/ARMmbed/mbed-ls')
sys.exit(1)
ret_code = args.command(mbeds, args)
if not ret_code:
ret_code = 0
logger.debug("Return code: %d", ret_code)
sys.exit(ret_code)

View File

@ -0,0 +1,31 @@
"""
mbed SDK
Copyright (c) 2017-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.
"""
"""Functions that manage a platform database"""
from mbed_os_tools.detect.platform_database import (
LOCAL_PLATFORM_DATABASE,
LOCAL_MOCKS_DATABASE,
DEFAULT_PLATFORM_DB,
PlatformDatabase
)
"""
NOTE: The platform database is now in the mbed-os-tools package.
You can find it in the following file: mbed_os_tools/detect/platform_database.py
Please make all further contributions to the new package.
"""

View File

@ -0,0 +1,21 @@
"""
mbed SDK
Copyright (c) 2011-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.
"""
from mbed_os_tools.detect.windows import (
MbedLsToolsWin7,
CompatibleIDsNotFoundException
)

View File

@ -0,0 +1,17 @@
# Copyright (c) 2018, Arm Limited and affiliates.
# SPDX-License-Identifier: Apache-2.0
#
# 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.
# Mbed CE: added hardcoded version
VERSION = "0.0.16"

View File

@ -0,0 +1,37 @@
# Copyright (c) 2018, Arm Limited and affiliates.
# SPDX-License-Identifier: Apache-2.0
#
# 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.
"""! @package mbed-ls
mbed-ls package is a set of tools inherited from mbed-lmtools used to detect
mbed enabled devices on host (Windows, Linux and MacOS).
mbed-lstools is a Python module that detects and lists mbed-enabled devices
connected to the host computer. It will be delivered as a redistributable
Python module (package) and command line tool.
Currently supported operating system:
* Windows 7.
* Ubuntu.
* Mac OS X (Darwin).
The stand-alone mbed-lstools Python package is still under development,
but it's already delivered as part of the mbed SDK's test suite and a command
line tool (see below).
"""
from .main import create
create = create

View File

@ -0,0 +1,226 @@
# Copyright (c) 2018, Arm Limited and affiliates.
# SPDX-License-Identifier: Apache-2.0
#
# 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.
import re
import subprocess
import platform
from bs4 import BeautifulSoup
try:
from plistlib import loads
except ImportError:
from plistlib import readPlistFromString as loads
from xml.parsers.expat import ExpatError
from .lstools_base import MbedLsToolsBase
import logging
logger = logging.getLogger("mbedls.lstools_darwin")
logger.addHandler(logging.NullHandler())
DEBUG = logging.DEBUG
del logging
mbed_volume_name_match = re.compile(r"\b(mbed|SEGGER MSD|ATMEL EDBG Media)\b", re.I)
def _plist_from_popen(popen):
out, _ = popen.communicate()
if not out:
return []
try:
try:
# Try simple and fast first if this fails fall back to the slower but
# more robust process.
return loads(out)
except ExpatError:
# Beautiful soup ensures the XML is properly formed after it is parsed
# so that it can be used by other less lenient commands without problems
xml_representation = BeautifulSoup(out.decode('utf8'), 'xml')
if not xml_representation.get_text():
# The output is not in the XML format
return loads(out)
return loads(xml_representation.decode().encode('utf8'))
except ExpatError:
return []
def _find_TTY(obj):
""" Find the first tty (AKA IODialinDevice) that we can find in the
children of the specified object, or None if no tty is present.
"""
try:
return obj["IODialinDevice"]
except KeyError:
for child in obj.get("IORegistryEntryChildren", []):
found = _find_TTY(child)
if found:
return found
return None
def _prune(current, keys):
""" Reduce the amount of data we have to sift through to only
include the specified keys, and children that contain the
specified keys
"""
pruned_current = {k: current[k] for k in keys if k in current}
pruned_children = list(
filter(
None, [_prune(c, keys) for c in current.get("IORegistryEntryChildren", [])]
)
)
keep_current = any(k in current for k in keys) or pruned_children
if keep_current:
if pruned_children:
pruned_current["IORegistryEntryChildren"] = pruned_children
return pruned_current
else:
return {}
def _dfs_usb_info(obj, parents):
""" Find all of the usb info that we can from this particular IORegistry
tree with depth first search (and searching the parent stack....)
"""
output = {}
if (
"BSD Name" in obj
and obj["BSD Name"].startswith("disk")
and mbed_volume_name_match.search(obj["IORegistryEntryName"])
):
disk_id = obj["BSD Name"]
usb_info = {"serial": None, "vendor_id": None, "product_id": None, "tty": None}
for parent in [obj] + parents:
if "USB Serial Number" in parent:
usb_info["serial"] = parent["USB Serial Number"]
if "idVendor" in parent and "idProduct" in parent:
usb_info["vendor_id"] = format(parent["idVendor"], "04x")
usb_info["product_id"] = format(parent["idProduct"], "04x")
if usb_info["serial"]:
usb_info["tty"] = _find_TTY(parent)
if all(usb_info.values()):
break
logger.debug("found usb info %r", usb_info)
output[disk_id] = usb_info
for child in obj.get("IORegistryEntryChildren", []):
output.update(_dfs_usb_info(child, [obj] + parents))
return output
class MbedLsToolsDarwin(MbedLsToolsBase):
""" mbed-enabled platform detection on Mac OS X
"""
def __init__(self, **kwargs):
MbedLsToolsBase.__init__(self, **kwargs)
self.mac_version = float(".".join(platform.mac_ver()[0].split(".")[:2]))
def find_candidates(self):
# {volume_id: {serial:, vendor_id:, product_id:, tty:}}
volumes = self._volumes()
# {volume_id: mount_point}
mounts = self._mount_points()
return [
{
"mount_point": mounts[v],
"serial_port": volumes[v]["tty"],
"target_id_usb_id": volumes[v].get("serial"),
"vendor_id": volumes[v].get("vendor_id"),
"product_id": volumes[v].get("product_id"),
}
for v in set(volumes.keys()) and set(mounts.keys())
if v in mounts and v in volumes
]
def _mount_points(self):
""" Returns map {volume_id: mount_point} """
diskutil_ls = subprocess.Popen(
["diskutil", "list", "-plist"], stdout=subprocess.PIPE
)
disks = _plist_from_popen(diskutil_ls)
if logger.isEnabledFor(DEBUG):
import pprint
logger.debug(
"disks dict \n%s", pprint.PrettyPrinter(indent=2).pformat(disks)
)
return {
disk["DeviceIdentifier"]: disk.get("MountPoint", None)
for disk in disks["AllDisksAndPartitions"]
}
def _volumes(self):
""" returns a map {volume_id: {serial:, vendor_id:, product_id:, tty:}"""
# to find all the possible mbed volumes, we look for registry entries
# under all possible USB tree which have a "BSD Name" that starts with
# "disk" # (i.e. this is a USB disk), and have a IORegistryEntryName that
# matches /\cmbed/
# Once we've found a disk, we can search up for a parent with a valid
# serial number, and then search down again to find a tty that's part
# of the same composite device
# ioreg -a -r -n <usb_controller_name> -l
usb_controllers = [
"AppleUSBXHCI",
"AppleUSBUHCI",
"AppleUSBEHCI",
"AppleUSBOHCI",
"IOUSBHostDevice",
]
cmp_par = "-n"
# For El Captain we need to list all the instances of (-c) rather than
# compare names (-n)
if self.mac_version >= 10.11:
cmp_par = "-c"
usb_tree = []
for usb_controller in usb_controllers:
ioreg_usb = subprocess.Popen(
["ioreg", "-a", "-r", cmp_par, usb_controller, "-l"],
stdout=subprocess.PIPE,
)
usb_tree.extend(_plist_from_popen(ioreg_usb))
r = {}
for name, obj in enumerate(usb_tree):
pruned_obj = _prune(
obj,
[
"USB Serial Number",
"idVendor",
"BSD Name",
"IORegistryEntryName",
"idProduct",
"IODialinDevice",
],
)
if logger.isEnabledFor(DEBUG):
import pprint
logger.debug(
"finding in \n%s",
pprint.PrettyPrinter(indent=2).pformat(pruned_obj),
)
r.update(_dfs_usb_info(pruned_obj, []))
logger.debug("_volumes return %r", r)
return r

View File

@ -0,0 +1,177 @@
# Copyright (c) 2018, Arm Limited and affiliates.
# SPDX-License-Identifier: Apache-2.0
#
# 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.
import re
import os
from .lstools_base import MbedLsToolsBase
import logging
logger = logging.getLogger("mbedls.lstools_linux")
logger.addHandler(logging.NullHandler())
del logging
SYSFS_BLOCK_DEVICE_PATH = "/sys/class/block"
def _readlink(link):
content = os.readlink(link)
if content.startswith(".."):
return os.path.abspath(os.path.join(os.path.dirname(link), content))
else:
return content
class MbedLsToolsLinuxGeneric(MbedLsToolsBase):
""" mbed-enabled platform for Linux with udev
"""
def __init__(self, **kwargs):
"""! ctor
"""
MbedLsToolsBase.__init__(self, **kwargs)
self.nlp = re.compile(r"(pci|usb)-[0-9a-zA-Z:_-]*_(?P<usbid>[0-9a-zA-Z]*)-.*$")
self.mmp = re.compile(r"(?P<dev>(/[^/ ]*)+) on (?P<dir>(/[^/ ]*)+) ")
self.udp = re.compile(r"^[0-9]+-[0-9]+[^:\s]*$")
def find_candidates(self):
disk_ids = self._dev_by_id("disk")
serial_ids = self._dev_by_id("serial")
mount_ids = dict(self._fat_mounts())
usb_info = self._sysfs_block_devices(disk_ids.values())
logger.debug("Mount mapping %r", mount_ids)
return [
{
"mount_point": mount_ids.get(disk_dev),
"serial_port": serial_ids.get(disk_uuid),
"target_id_usb_id": disk_uuid,
"vendor_id": usb_info.get(disk_dev, {}).get("vendor_id"),
"product_id": usb_info.get(disk_dev, {}).get("product_id"),
}
for disk_uuid, disk_dev in disk_ids.items()
]
def _dev_by_id(self, device_type):
"""! Get a dict, USBID -> device, for a device class
@param device_type The type of devices to search. For exmaple, "serial"
looks for all serial devices connected to this computer
@return A dict: Device USBID -> device file in /dev
"""
dir = os.path.join("/dev", device_type, "by-id")
if os.path.isdir(dir):
to_ret = dict(
self._hex_ids([os.path.join(dir, f) for f in os.listdir(dir)])
)
logger.debug("Found %s devices by id %r", device_type, to_ret)
return to_ret
else:
logger.error(
"Could not get %s devices by id. "
"This could be because your Linux distribution "
"does not use udev, or does not create /dev/%s/by-id "
"symlinks. Please submit an issue to github.com/"
"armmbed/mbed-ls.",
device_type,
device_type,
)
return {}
def _fat_mounts(self):
"""! Lists mounted devices with vfat file system (potential mbeds)
@result Returns list of all mounted vfat devices
@details Uses Linux shell command: 'mount'
"""
_stdout, _, retval = self._run_cli_process("mount")
if not retval:
for line in _stdout.splitlines():
if b"vfat" in line:
match = self.mmp.search(line.decode("utf-8"))
if match:
yield match.group("dev"), match.group("dir")
def _hex_ids(self, dev_list):
"""! Build a USBID map for a device list
@param disk_list List of disks in a system with USBID decoration
@return Returns map USBID -> device file in /dev
@details Uses regular expressions to get a USBID (TargeTIDs) a "by-id"
symbolic link
"""
logger.debug("Converting device list %r", dev_list)
for dl in dev_list:
match = self.nlp.search(dl)
if match:
yield match.group("usbid"), _readlink(dl)
def _sysfs_block_devices(self, block_devices):
device_names = {os.path.basename(d): d for d in block_devices}
sysfs_block_devices = set(os.listdir(SYSFS_BLOCK_DEVICE_PATH))
common_device_names = sysfs_block_devices.intersection(set(device_names.keys()))
result = {}
for common_device_name in common_device_names:
sysfs_path = os.path.join(SYSFS_BLOCK_DEVICE_PATH, common_device_name)
full_sysfs_path = os.readlink(sysfs_path)
path_parts = full_sysfs_path.split("/")
end_index = None
for index, part in enumerate(path_parts):
if self.udp.search(part):
end_index = index
if end_index is None:
logger.debug(
"Did not find suitable usb folder for usb info: %s", full_sysfs_path
)
continue
usb_info_rel_path = path_parts[: end_index + 1]
usb_info_path = os.path.join(
SYSFS_BLOCK_DEVICE_PATH, os.sep.join(usb_info_rel_path)
)
vendor_id = None
product_id = None
vendor_id_file_paths = os.path.join(usb_info_path, "idVendor")
product_id_file_paths = os.path.join(usb_info_path, "idProduct")
try:
with open(vendor_id_file_paths, "r") as vendor_file:
vendor_id = vendor_file.read().strip()
except OSError as e:
logger.debug(
"Failed to read vendor id file %s weith error:",
vendor_id_file_paths,
e,
)
try:
with open(product_id_file_paths, "r") as product_file:
product_id = product_file.read().strip()
except OSError as e:
logger.debug(
"Failed to read product id file %s weith error:",
product_id_file_paths,
e,
)
result[device_names[common_device_name]] = {
"vendor_id": vendor_id,
"product_id": product_id,
}
return result

View File

@ -0,0 +1,805 @@
# Copyright (c) 2018, Arm Limited and affiliates.
# SPDX-License-Identifier: Apache-2.0
#
# 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.
import re
from abc import ABCMeta, abstractmethod
from io import open
from json import load
from os import listdir
from os.path import expanduser, isfile, join, exists, isdir
import logging
import functools
import json
from .platform_database import (
PlatformDatabase,
LOCAL_PLATFORM_DATABASE,
LOCAL_MOCKS_DATABASE,
)
from future.utils import with_metaclass
mbedls_root_logger = logging.getLogger("mbedls")
mbedls_root_logger.setLevel(logging.WARNING)
logger = logging.getLogger("mbedls.lstools_base")
logger.addHandler(logging.NullHandler())
def deprecated(reason):
"""Deprecate a function/method with a decorator"""
def actual_decorator(func):
@functools.wraps(func)
def new_func(*args, **kwargs):
logger.warning("Call to deprecated function %s. %s", func.__name__, reason)
return func(*args, **kwargs)
return new_func
return actual_decorator
class FSInteraction(object):
BeforeFilter = 1
AfterFilter = 2
Never = 3
class MbedLsToolsBase(with_metaclass(ABCMeta, object)):
""" Base class for mbed-lstools, defines mbed-ls tools interface for
mbed-enabled devices detection for various hosts
"""
# Which OSs are supported by this module
# Note: more than one OS can be supported by mbed-lstools_* module
os_supported = []
# Directory where we will store global (OS user specific mocking)
HOME_DIR = expanduser("~")
MOCK_FILE_NAME = ".mbedls-mock"
RETARGET_FILE_NAME = "mbedls.json"
DETAILS_TXT_NAME = "DETAILS.TXT"
MBED_HTM_NAME = "mbed.htm"
VENDOR_ID_DEVICE_TYPE_MAP = {
"0483": "stlink",
"0d28": "daplink",
"1366": "jlink",
"03eb": "atmel",
}
def __init__(self, list_unmounted=False, **kwargs):
""" ctor
"""
self.retarget_data = {} # Used to retarget mbed-enabled platform properties
platform_dbs = []
if isfile(self.MOCK_FILE_NAME) or (
"force_mock" in kwargs and kwargs["force_mock"]
):
platform_dbs.append(self.MOCK_FILE_NAME)
elif isfile(LOCAL_MOCKS_DATABASE):
platform_dbs.append(LOCAL_MOCKS_DATABASE)
platform_dbs.append(LOCAL_PLATFORM_DATABASE)
self.plat_db = PlatformDatabase(platform_dbs, primary_database=platform_dbs[0])
self.list_unmounted = list_unmounted
if "skip_retarget" not in kwargs or not kwargs["skip_retarget"]:
self.retarget()
@abstractmethod
def find_candidates(self):
"""Find all candidate devices connected to this computer
Note: Should not open any files
@return A dict with the keys 'mount_point', 'serial_port' and 'target_id_usb_id'
"""
raise NotImplementedError
def list_mbeds(
self,
fs_interaction=FSInteraction.BeforeFilter,
filter_function=None,
unique_names=False,
read_details_txt=False,
):
""" List details of connected devices
@return Returns list of structures with detailed info about each mbed
@param fs_interaction A member of the FSInteraction class that picks the
trade of between quality of service and speed
@param filter_function Function that is passed each mbed candidate,
should return True if it should be included in the result
Ex. mbeds = list_mbeds(filter_function=lambda m: m['platform_name'] == 'K64F')
@param unique_names A boolean controlling the presence of the
'platform_unique_name' member of the output dict
@param read_details_txt A boolean controlling the presense of the
output dict attributes read from other files present on the 'mount_point'
@details Function returns list of dictionaries with mbed attributes
'mount_point', TargetID name etc.
Function returns mbed list with platform names if possible
"""
platform_count = {}
candidates = list(self.find_candidates())
logger.debug("Candidates for display %r", candidates)
result = []
for device in candidates:
device["device_type"] = self._detect_device_type(device)
if (
not device["mount_point"]
or not self.mount_point_ready(device["mount_point"])
) and not self.list_unmounted:
if device["target_id_usb_id"] and device["serial_port"]:
logger.warning(
"MBED with target id '%s' is connected, but not mounted. "
"Use the '-u' flag to include it in the list.",
device["target_id_usb_id"],
)
else:
platform_data = self.plat_db.get(
device["target_id_usb_id"][0:4],
device_type=device["device_type"] or "daplink",
verbose_data=True,
)
device.update(platform_data or {"platform_name": None})
maybe_device = {
FSInteraction.BeforeFilter: self._fs_before_id_check,
FSInteraction.AfterFilter: self._fs_after_id_check,
FSInteraction.Never: self._fs_never,
}[fs_interaction](device, filter_function, read_details_txt)
if maybe_device and (
maybe_device["mount_point"] or self.list_unmounted
):
if unique_names:
name = device["platform_name"]
platform_count.setdefault(name, -1)
platform_count[name] += 1
device["platform_name_unique"] = "%s[%d]" % (
name,
platform_count[name],
)
try:
device.update(self.retarget_data[device["target_id"]])
logger.debug(
"retargeting %s with %r",
device["target_id"],
self.retarget_data[device["target_id"]],
)
except KeyError:
pass
# This is done for API compatibility, would prefer for this to
# just be None
device["device_type"] = (
device["device_type"] if device["device_type"] else "unknown"
)
result.append(maybe_device)
return result
def _fs_never(self, device, filter_function, read_details_txt):
"""Filter device without touching the file system of the device"""
device["target_id"] = device["target_id_usb_id"]
device["target_id_mbed_htm"] = None
if not filter_function or filter_function(device):
return device
else:
return None
def _fs_before_id_check(self, device, filter_function, read_details_txt):
"""Filter device after touching the file system of the device.
Said another way: Touch the file system before filtering
"""
device["target_id"] = device["target_id_usb_id"]
self._update_device_from_fs(device, read_details_txt)
if not filter_function or filter_function(device):
return device
else:
return None
def _fs_after_id_check(self, device, filter_function, read_details_txt):
"""Filter device before touching the file system of the device.
Said another way: Touch the file system after filtering
"""
device["target_id"] = device["target_id_usb_id"]
device["target_id_mbed_htm"] = None
if not filter_function or filter_function(device):
self._update_device_from_fs(device, read_details_txt)
return device
else:
return None
def _update_device_from_fs(self, device, read_details_txt):
""" Updates the device information based on files from its 'mount_point'
@param device Dictionary containing device information
@param read_details_txt A boolean controlling the presense of the
output dict attributes read from other files present on the 'mount_point'
"""
if not device.get("mount_point", None):
return
try:
directory_entries = listdir(device["mount_point"])
device["directory_entries"] = directory_entries
device["target_id"] = device["target_id_usb_id"]
# Always try to update using daplink compatible boards processself.
# This is done for backwards compatibility.
self._update_device_details_daplink_compatible(device, read_details_txt)
if device.get("device_type") == "jlink":
self._update_device_details_jlink(device, read_details_txt)
if device.get("device_type") == "atmel":
self._update_device_details_atmel(device, read_details_txt)
except (OSError, IOError) as e:
logger.warning(
'Marking device with mount point "%s" as unmounted due to the '
"following error: %s",
device["mount_point"],
e,
)
device["mount_point"] = None
def _detect_device_type(self, device):
""" Returns a string of the device type
@param device Dictionary containing device information
@return Device type located in VENDOR_ID_DEVICE_TYPE_MAP or None if unknown
"""
return self.VENDOR_ID_DEVICE_TYPE_MAP.get(device.get("vendor_id"))
def _update_device_details_daplink_compatible(self, device, read_details_txt):
""" Updates the daplink-specific device information based on files from its
'mount_point'
@param device Dictionary containing device information
@param read_details_txt A boolean controlling the presense of the
output dict attributes read from other files present on the 'mount_point'
"""
lowercase_directory_entries = [e.lower() for e in device["directory_entries"]]
if self.MBED_HTM_NAME.lower() in lowercase_directory_entries:
self._update_device_from_htm(device)
elif not read_details_txt:
logger.debug(
"Since mbed.htm is not present, attempting to use "
"details.txt for the target id"
)
read_details_txt = True
if (
read_details_txt
and self.DETAILS_TXT_NAME.lower() in lowercase_directory_entries
):
details_txt = self._details_txt(device["mount_point"]) or {}
device.update(
{
"daplink_%s" % f.lower().replace(" ", "_"): v
for f, v in details_txt.items()
}
)
# If details.txt contains the target id, this is the most trusted source
if device.get("daplink_unique_id", None):
device["target_id"] = device["daplink_unique_id"]
if device["target_id"]:
identifier = device["target_id"][0:4]
platform_data = self.plat_db.get(
identifier, device_type="daplink", verbose_data=True
)
if not platform_data:
logger.warning(
'daplink entry: "%s" not found in platform database', identifier
)
else:
device.update(platform_data)
else:
device["platform_name"] = None
def _update_device_details_jlink(self, device, _):
""" Updates the jlink-specific device information based on files from its 'mount_point'
@param device Dictionary containing device information
"""
lower_case_map = {e.lower(): e for e in device["directory_entries"]}
if "board.html" in lower_case_map:
board_file_key = "board.html"
elif "user guide.html" in lower_case_map:
board_file_key = "user guide.html"
else:
logger.warning("No valid file found to update JLink device details")
return
board_file_path = join(device["mount_point"], lower_case_map[board_file_key])
with open(board_file_path, "r") as board_file:
board_file_lines = board_file.readlines()
for line in board_file_lines:
m = re.search(r"url=([\w\d\:\-/\\\?\.=-_]+)", line)
if m:
device["url"] = m.group(1).strip()
identifier = device["url"].split("/")[-1]
platform_data = self.plat_db.get(
identifier, device_type="jlink", verbose_data=True
)
if not platform_data:
logger.warning(
'jlink entry: "%s", not found in platform database', identifier
)
else:
device.update(platform_data)
break
def _update_device_from_htm(self, device):
"""Set the 'target_id', 'target_id_mbed_htm', 'platform_name' and
'daplink_*' attributes by reading from mbed.htm on the device
"""
htm_target_id, daplink_info = self._read_htm_ids(device["mount_point"])
if daplink_info:
device.update(
{
"daplink_%s" % f.lower().replace(" ", "_"): v
for f, v in daplink_info.items()
}
)
if htm_target_id:
logger.debug(
"Found htm target id, %s, for usb target id %s",
htm_target_id,
device["target_id_usb_id"],
)
device["target_id"] = htm_target_id
else:
logger.debug(
"Could not read htm on from usb id %s. Falling back to usb id",
device["target_id_usb_id"],
)
device["target_id"] = device["target_id_usb_id"]
device["target_id_mbed_htm"] = htm_target_id
def _update_device_details_atmel(self, device, _):
""" Updates the Atmel device information based on files from its 'mount_point'
@param device Dictionary containing device information
@param read_details_txt A boolean controlling the presense of the
output dict attributes read from other files present on the 'mount_point'
"""
# Atmel uses a system similar to DAPLink, but there's no details.txt with a
# target ID to identify device we can use the serial, which is ATMLXXXXYYYYYYY
# where XXXX is the board identifier.
# This can be verified by looking at readme.htm, which also uses the board ID
# to redirect to platform page
device["target_id"] = device["target_id_usb_id"][4:8]
platform_data = self.plat_db.get(
device["target_id"], device_type="atmel", verbose_data=True
)
device.update(platform_data or {"platform_name": None})
def mock_manufacture_id(self, mid, platform_name, oper="+"):
"""! Replace (or add if manufacture id doesn't exist) entry in self.manufacture_ids
@param oper '+' add new mock / override existing entry
'-' remove mid from mocking entry
@return Mocked structure (json format)
"""
if oper == "+":
self.plat_db.add(mid, platform_name, permanent=True)
elif oper == "-":
self.plat_db.remove(mid, permanent=True)
else:
raise ValueError("oper can only be [+-]")
def retarget_read(self):
"""! Load retarget data from local file
@return Curent retarget configuration (dictionary)
"""
if isfile(self.RETARGET_FILE_NAME):
logger.debug("reading retarget file %s", self.RETARGET_FILE_NAME)
try:
with open(self.RETARGET_FILE_NAME, "r", encoding="utf-8") as f:
return load(f)
except IOError as e:
logger.exception(e)
except ValueError as e:
logger.exception(e)
return {}
def retarget(self):
"""! Enable retargeting
@details Read data from local retarget configuration file
@return Retarget data structure read from configuration file
"""
self.retarget_data = self.retarget_read()
return self.retarget_data
def get_dummy_platform(self, platform_name):
"""! Returns simple dummy platform """
if not hasattr(self, "dummy_counter"):
self.dummy_counter = {} # platform<str>: counter<int>
if platform_name not in self.dummy_counter:
self.dummy_counter[platform_name] = 0
platform = {
"platform_name": platform_name,
"platform_name_unique": "%s[%d]"
% (platform_name, self.dummy_counter[platform_name]),
"mount_point": "DUMMY",
"serial_port": "DUMMY",
"target_id": "DUMMY",
"target_id_mbed_htm": "DUMMY",
"target_id_usb_id": "DUMMY",
"daplink_version": "DUMMY",
}
self.dummy_counter[platform_name] += 1
return platform
def get_supported_platforms(self, device_type=None):
"""! Return a dictionary of supported target ids and the corresponding platform name
@param device_type Filter which device entries are returned from the platform
database
@return Dictionary of { 'target_id': 'platform_name', ... }
"""
kwargs = {}
if device_type is not None:
kwargs["device_type"] = device_type
items = self.plat_db.items(**kwargs)
return {i[0]: i[1] for i in items}
# Private functions supporting API
def _read_htm_ids(self, mount_point):
"""! Function scans mbed.htm to get information about TargetID.
@param mount_point mbed mount point (disk / drive letter)
@return Function returns targetID, in case of failure returns None.
@details Note: This function should be improved to scan variety of boards'
mbed.htm files
"""
result = {}
target_id = None
for line in self._htm_lines(mount_point):
target_id = target_id or self._target_id_from_htm(line)
ver_bld = self._mbed_htm_comment_section_ver_build(line)
if ver_bld:
result["version"], result["build"] = ver_bld
m = re.search(r"url=([\w\d\:/\\\?\.=-_]+)", line)
if m:
result["url"] = m.group(1).strip()
return target_id, result
def _mbed_htm_comment_section_ver_build(self, line):
"""! Check for Version and Build date of interface chip firmware im mbed.htm file
@return (version, build) tuple if successful, None if no info found
"""
# <!-- Version: 0200 Build: Mar 26 2014 13:22:20 -->
m = re.search(r"^<!-- Version: (\d+) Build: ([\d\w: ]+) -->", line)
if m:
version_str, build_str = m.groups()
return (version_str.strip(), build_str.strip())
# <!-- Version: 0219 Build: Feb 2 2016 15:20:54 Git Commit SHA:
# 0853ba0cdeae2436c52efcba0ba76a6434c200ff Git local mods:No-->
m = re.search(r"^<!-- Version: (\d+) Build: ([\d\w: ]+) Git Commit SHA", line)
if m:
version_str, build_str = m.groups()
return (version_str.strip(), build_str.strip())
# <!-- Version: 0.14.3. build 471 -->
m = re.search(r"^<!-- Version: ([\d+\.]+)\. build (\d+) -->", line)
if m:
version_str, build_str = m.groups()
return (version_str.strip(), build_str.strip())
return None
def _htm_lines(self, mount_point):
if mount_point:
mbed_htm_path = join(mount_point, self.MBED_HTM_NAME)
with open(mbed_htm_path, "r") as f:
return f.readlines()
def _details_txt(self, mount_point):
"""! Load DETAILS.TXT to dictionary:
DETAILS.TXT example:
Version: 0226
Build: Aug 24 2015 17:06:30
Git Commit SHA: 27a236b9fe39c674a703c5c89655fbd26b8e27e1
Git Local mods: Yes
or:
# DAPLink Firmware - see https://mbed.com/daplink
Unique ID: 0240000029164e45002f0012706e0006f301000097969900
HIF ID: 97969900
Auto Reset: 0
Automation allowed: 0
Daplink Mode: Interface
Interface Version: 0240
Git SHA: c765cbb590f57598756683254ca38b211693ae5e
Local Mods: 0
USB Interfaces: MSD, CDC, HID
Interface CRC: 0x26764ebf
"""
if mount_point:
path_to_details_txt = join(mount_point, self.DETAILS_TXT_NAME)
with open(path_to_details_txt, "r") as f:
return self._parse_details(f.readlines())
return None
def _parse_details(self, lines):
result = {}
for line in lines:
if not line.startswith("#"):
key, _, value = line.partition(":")
if value:
result[key] = value.strip()
if "Interface Version" in result:
result["Version"] = result["Interface Version"]
return result
def _target_id_from_htm(self, line):
"""! Extract Target id from htm line.
@return Target id or None
"""
# Detecting modern mbed.htm file format
m = re.search("\\?code=([a-fA-F0-9]+)", line)
if m:
result = m.groups()[0]
logger.debug("Found target id %s in htm line %s", result, line)
return result
# Last resort, we can try to see if old mbed.htm format is there
m = re.search("\\?auth=([a-fA-F0-9]+)", line)
if m:
result = m.groups()[0]
logger.debug("Found target id %s in htm line %s", result, line)
return result
return None
def mount_point_ready(self, path):
"""! Check if a mount point is ready for file operations
"""
return exists(path) and isdir(path)
@staticmethod
def _run_cli_process(cmd, shell=True):
"""! Runs command as a process and return stdout, stderr and ret code
@param cmd Command to execute
@return Tuple of (stdout, stderr, returncode)
"""
from subprocess import Popen, PIPE
p = Popen(cmd, shell=shell, stdout=PIPE, stderr=PIPE)
_stdout, _stderr = p.communicate()
return _stdout, _stderr, p.returncode
@deprecated(
"Functionality has been moved into 'list_mbeds'. "
"Please use list_mbeds with 'unique_names=True' and "
"'read_details_txt=True'"
)
def list_mbeds_ext(self):
"""! Function adds extra information for each mbed device
@return Returns list of mbed devices plus extended data like
'platform_name_unique'
@details Get information about mbeds with extended parameters/info included
"""
return self.list_mbeds(unique_names=True, read_details_txt=True)
@deprecated(
"List formatting methods are deprecated for a simpler API. "
"Please use 'list_mbeds' instead."
)
def list_manufacture_ids(self):
"""! Creates list of all available mappings for target_id -> Platform
@return String with table formatted output
"""
from prettytable import PrettyTable, HEADER
columns = ["target_id_prefix", "platform_name"]
pt = PrettyTable(columns, junction_char="|", hrules=HEADER)
for col in columns:
pt.align[col] = "l"
for target_id_prefix, platform_name in sorted(self.plat_db.items()):
pt.add_row([target_id_prefix, platform_name])
return pt.get_string()
@deprecated(
"List formatting methods are deprecated to simplify the API. "
"Please use 'list_mbeds' instead."
)
def list_platforms(self):
"""! Useful if you just want to know which platforms are currently
available on the system
@return List of (unique values) available platforms
"""
result = []
mbeds = self.list_mbeds()
for i, val in enumerate(mbeds):
platform_name = str(val["platform_name"])
if platform_name not in result:
result.append(platform_name)
return result
@deprecated(
"List formatting methods are deprecated to simplify the API. "
"Please use 'list_mbeds' instead."
)
def list_platforms_ext(self):
"""! Useful if you just want to know how many platforms of each type are
currently available on the system
@return Dict of platform: platform_count
"""
result = {}
mbeds = self.list_mbeds()
for i, val in enumerate(mbeds):
platform_name = str(val["platform_name"])
if platform_name not in result:
result[platform_name] = 1
else:
result[platform_name] += 1
return result
@deprecated(
"List formatting methods are deprecated to simplify the API. "
"Please use 'list_mbeds' instead."
)
def list_mbeds_by_targetid(self):
"""! Get information about mbeds with extended parameters/info included
@return Returns dictionary where keys are TargetIDs and values are mbed
structures
@details Ordered by target id (key: target_id).
"""
result = {}
mbed_list = self.list_mbeds_ext()
for mbed in mbed_list:
target_id = mbed["target_id"]
result[target_id] = mbed
return result
@deprecated(
"List formatting methods are deprecated to simplify the API. "
"Please use 'list_mbeds' instead."
)
def get_string(
self, border=False, header=True, padding_width=1, sortby="platform_name"
):
"""! Printing with some sql table like decorators
@param border Table border visibility
@param header Table header visibility
@param padding_width Table padding
@param sortby Column used to sort results
@return Returns string which can be printed on console
"""
from prettytable import PrettyTable, HEADER
result = ""
mbeds = self.list_mbeds(unique_names=True, read_details_txt=True)
if mbeds:
""" ['platform_name', 'mount_point', 'serial_port', 'target_id'] -
columns generated from USB auto-detection
['platform_name_unique', ...] -
columns generated outside detection subsystem (OS dependent detection)
"""
columns = [
"platform_name",
"platform_name_unique",
"mount_point",
"serial_port",
"target_id",
"daplink_version",
]
pt = PrettyTable(columns, junction_char="|", hrules=HEADER)
for col in columns:
pt.align[col] = "l"
for mbed in mbeds:
row = []
for col in columns:
row.append(mbed[col] if col in mbed and mbed[col] else "unknown")
pt.add_row(row)
result = pt.get_string(
border=border, header=header, padding_width=padding_width, sortby=sortby
)
return result
# Private functions supporting API
@deprecated(
"This method will be removed from the public API. "
"Please use 'list_mbeds' instead"
)
def get_json_data_from_file(self, json_spec_filename, verbose=False):
"""! Loads from file JSON formatted string to data structure
@return None if JSON can be loaded
"""
try:
with open(json_spec_filename) as data_file:
try:
return json.load(data_file)
except ValueError as json_error_msg:
logger.error(
"Parsing file(%s): %s", json_spec_filename, json_error_msg
)
return None
except IOError as fileopen_error_msg:
logger.warning(fileopen_error_msg)
return None
@deprecated(
"This method will be removed from the public API. "
"Please use 'list_mbeds' instead"
)
def get_htm_target_id(self, mount_point):
target_id, _ = self._read_htm_ids(mount_point)
return target_id
@deprecated(
"This method will be removed from the public API. "
"Please use 'list_mbeds' instead"
)
def get_mbed_htm(self, mount_point):
_, build_info = self._read_htm_ids(mount_point)
return build_info
@deprecated(
"This method will be removed from the public API. "
"Please use 'list_mbeds' instead"
)
def get_mbed_htm_comment_section_ver_build(self, line):
return self._mbed_htm_comment_section_ver_build(line)
@deprecated(
"This method will be removed from the public API. "
"Please use 'list_mbeds' instead"
)
def get_mbed_htm_lines(self, mount_point):
return self._htm_lines(mount_point)
@deprecated(
"This method will be removed from the public API. "
"Please use 'list_mbeds' instead"
)
def get_details_txt(self, mount_point):
return self._details_txt(mount_point)
@deprecated(
"This method will be removed from the public API. "
"Please use 'list_mbeds' instead"
)
def parse_details_txt(self, lines):
return self._parse_details(lines)
@deprecated(
"This method will be removed from the public API. "
"Please use 'list_mbeds' instead"
)
def scan_html_line_for_target_id(self, line):
return self._target_id_from_htm(line)
@staticmethod
@deprecated(
"This method will be removed from the public API. "
"Please use 'list_mbeds' instead"
)
def run_cli_process(cmd, shell=True):
return MbedLsToolsBase._run_cli_process(cmd, shell)

View File

@ -0,0 +1,104 @@
# Copyright (c) 2018, Arm Limited and affiliates.
# SPDX-License-Identifier: Apache-2.0
#
# 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.
import os
import sys
import platform
# Make sure that any global generic setup is run
from . import lstools_base # noqa: F401
import logging
logger = logging.getLogger("mbedls.main")
logger.addHandler(logging.NullHandler())
del logging
def create(**kwargs):
"""! Factory used to create host OS specific mbed-lstools object
:param kwargs: keyword arguments to pass along to the constructors
@return Returns MbedLsTools object or None if host OS is not supported
"""
result = None
mbed_os = mbed_os_support()
if mbed_os is not None:
if mbed_os == "Windows7":
from .windows import MbedLsToolsWin7
result = MbedLsToolsWin7(**kwargs)
elif mbed_os == "LinuxGeneric":
from .linux import MbedLsToolsLinuxGeneric
result = MbedLsToolsLinuxGeneric(**kwargs)
elif mbed_os == "Darwin":
from .darwin import MbedLsToolsDarwin
result = MbedLsToolsDarwin(**kwargs)
return result
def mbed_os_support():
"""! Function used to determine if host OS is supported by mbed-lstools
@return Returns None if host OS is not supported else return OS short name
@details This function should be ported for new OS support
"""
result = None
os_info = mbed_lstools_os_info()
if os_info[0] == "nt" and os_info[1] == "Windows":
result = "Windows7"
elif os_info[0] == "posix" and os_info[1] == "Linux":
result = "LinuxGeneric"
elif os_info[0] == "posix" and os_info[1] == "Darwin":
result = "Darwin"
return result
def mbed_lstools_os_info():
"""! Returns information about host OS
@return Returns tuple with information about OS and host platform
"""
result = (
os.name,
platform.system(),
platform.release(),
platform.version(),
sys.platform,
)
return result
def mock_platform(mbeds, args):
for token in args.mock.split(","):
if ":" in token:
oper = "+" # Default
mid, platform_name = token.split(":")
if mid and mid[0] in ["+", "-"]:
oper = mid[0] # Operation (character)
mid = mid[1:] # We remove operation character
mbeds.mock_manufacture_id(mid, platform_name, oper=oper)
elif token and token[0] in ["-", "!"]:
# Operations where do not specify data after colon: --mock=-1234,-7678
oper = token[0]
mid = token[1:]
mbeds.mock_manufacture_id(mid, "dummy", oper=oper)
else:
logger.error("Could not parse mock from token: '%s'", token)

View File

@ -0,0 +1,571 @@
# Copyright (c) 2018, Arm Limited and affiliates.
# SPDX-License-Identifier: Apache-2.0
#
# 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.
"""Functions that manage a platform database"""
import datetime
import json
import re
from collections import OrderedDict, defaultdict
from copy import copy
from io import open
from os import makedirs
from os.path import join, dirname, getmtime
from appdirs import user_data_dir
from fasteners import InterProcessLock
import logging
logger = logging.getLogger("mbedls.platform_database")
logger.addHandler(logging.NullHandler())
del logging
try:
unicode
except NameError:
unicode = str
LOCAL_PLATFORM_DATABASE = join(user_data_dir("mbedls"), "platforms.json")
LOCAL_MOCKS_DATABASE = join(user_data_dir("mbedls"), "mock.json")
DEFAULT_PLATFORM_DB = {
u"daplink": {
u"0200": u"KL25Z",
u"0201": u"KW41Z",
u"0210": u"KL05Z",
u"0214": u"HEXIWEAR",
u"0217": u"K82F",
u"0218": u"KL82Z",
u"0220": u"KL46Z",
u"0227": u"MIMXRT1050_EVK",
u"0228": u"RAPIDIOT_K64F",
u"0230": u"K20D50M",
u"0231": u"K22F",
u"0234": u"RAPIDIOT_KW41Z",
u"0236": u"LPC55S69",
u"0240": u"K64F",
u"0245": u"K64F",
u"0250": u"KW24D",
u"0261": u"KL27Z",
u"0262": u"KL43Z",
u"0300": u"MTS_GAMBIT",
u"0305": u"MTS_MDOT_F405RG",
u"0310": u"MTS_DRAGONFLY_F411RE",
u"0311": u"K66F",
u"0312": u"MTS_DRAGONFLY_L471QG",
u"0313": u"MTS_DRAGONFLY_L496VG",
u"0315": u"MTS_MDOT_F411RE",
u"0316": u"MTS_DRAGONFLY_F413RH",
u"0350": u"XDOT_L151CC",
u"0360": u"HANI_IOT",
u"0400": u"MAXWSNENV",
u"0405": u"MAX32600MBED",
u"0407": u"MAX32620HSP",
u"0408": u"MAX32625NEXPAQ",
u"0409": u"MAX32630FTHR",
u"0410": u"ETTEPLAN_LORA",
u"0415": u"MAX32625MBED",
u"0416": u"MAX32625PICO",
u"0418": u"MAX32620FTHR",
u"0419": u"MAX35103EVKIT2",
u"0421": u"MAX32660EVSYS",
u"0424": u"MAX32670EVKIT",
u"0450": u"MTB_UBLOX_ODIN_W2",
u"0451": u"MTB_MXCHIP_EMW3166",
u"0452": u"MTB_LAIRD_BL600",
u"0453": u"MTB_MTS_XDOT",
u"0454": u"MTB_MTS_DRAGONFLY",
u"0455": u"MTB_UBLOX_NINA_B1",
u"0456": u"MTB_MURATA_ABZ",
u"0457": u"MTB_RAK811",
u"0458": u"ADV_WISE_1510",
u"0459": u"ADV_WISE_1530",
u"0460": u"ADV_WISE_1570",
u"0461": u"MTB_LAIRD_BL652",
u"0462": u"MTB_USI_WM_BN_BM_22",
u"0465": u"MTB_LAIRD_BL654",
u"0466": u"MTB_MURATA_WSM_BL241",
u"0467": u"MTB_STM_S2LP",
u"0468": u"MTB_STM_L475",
u"0469": u"MTB_STM32_F439",
u"0472": u"MTB_ACONNO_ACN52832",
u"0602": u"EV_COG_AD3029LZ",
u"0603": u"EV_COG_AD4050LZ",
u"0604": u"SDP_K1",
u"0700": u"NUCLEO_F103RB",
u"0705": u"NUCLEO_F302R8",
u"0710": u"NUCLEO_L152RE",
u"0715": u"NUCLEO_L053R8",
u"0720": u"NUCLEO_F401RE",
u"0725": u"NUCLEO_F030R8",
u"0729": u"NUCLEO_G071RB",
u"0730": u"NUCLEO_F072RB",
u"0735": u"NUCLEO_F334R8",
u"0740": u"NUCLEO_F411RE",
u"0742": u"NUCLEO_F413ZH",
u"0743": u"DISCO_F413ZH",
u"0744": u"NUCLEO_F410RB",
u"0745": u"NUCLEO_F303RE",
u"0746": u"DISCO_F303VC",
u"0747": u"NUCLEO_F303ZE",
u"0750": u"NUCLEO_F091RC",
u"0755": u"NUCLEO_F070RB",
u"0760": u"NUCLEO_L073RZ",
u"0764": u"DISCO_L475VG_IOT01A",
u"0765": u"NUCLEO_L476RG",
u"0766": u"SILICA_SENSOR_NODE",
u"0770": u"NUCLEO_L432KC",
u"0774": u"DISCO_L4R9I",
u"0775": u"NUCLEO_F303K8",
u"0776": u"NUCLEO_L4R5ZI",
u"0777": u"NUCLEO_F446RE",
u"0778": u"NUCLEO_F446ZE",
u"0779": u"NUCLEO_L433RC_P",
u"0780": u"NUCLEO_L011K4",
u"0781": u"NUCLEO_L4R5ZI_P",
u"0783": u"NUCLEO_L010RB",
u"0785": u"NUCLEO_F042K6",
u"0788": u"DISCO_F469NI",
u"0790": u"NUCLEO_L031K6",
u"0791": u"NUCLEO_F031K6",
u"0795": u"DISCO_F429ZI",
u"0796": u"NUCLEO_F429ZI",
u"0797": u"NUCLEO_F439ZI",
u"0805": u"DISCO_L053C8",
u"0810": u"DISCO_F334C8",
u"0812": u"NUCLEO_F722ZE",
u"0813": u"NUCLEO_H743ZI",
u"0814": u"DISCO_H747I",
u"0815": u"DISCO_F746NG",
u"0816": u"NUCLEO_F746ZG",
u"0817": u"DISCO_F769NI",
u"0818": u"NUCLEO_F767ZI",
u"0820": u"DISCO_L476VG",
u"0821": u"NUCLEO_L452RE",
u"0822": u"DISCO_L496AG",
u"0823": u"NUCLEO_L496ZG",
u"0824": u"LPC824",
u"0825": u"DISCO_F412ZG",
u"0826": u"NUCLEO_F412ZG",
u"0827": u"NUCLEO_L486RG",
u"0828": u"NUCLEO_L496ZG_P",
u"0829": u"NUCLEO_L452RE_P",
u"0830": u"DISCO_F407VG",
u"0833": u"DISCO_L072CZ_LRWAN1",
u"0835": u"NUCLEO_F207ZG",
u"0836": u"NUCLEO_H743ZI2",
u"0839": u"NUCLEO_WB55RG",
u"0840": u"B96B_F446VE",
u"0841": u"NUCLEO_G474RE",
u"0842": u"NUCLEO_H753ZI",
u"0843": u"NUCLEO_H745ZI_Q",
u"0844": u"NUCLEO_H755ZI_Q",
u"0847": u"DISCO_H745I",
u"0849": u"NUCLEO_G070RB",
u"0850": u"NUCLEO_G431RB",
u"0851": u"NUCLEO_G431KB",
u"0852": u"NUCLEO_G031K8",
u"0853": u"NUCLEO_F301K8",
u"0854": u"NUCLEO_L552ZE_Q",
u"0855": u"DISCO_L562QE",
u"0858": u"DISCO_H750B",
u"0859": u"DISCO_H7B3I",
u"0860": u"NUCLEO_H7A3ZI_Q",
u"0863": u"DISCO_L4P5G",
u"0865": u"NUCLEO_L4P5ZG",
u"0866": u"NUCLEO_WL55JC",
u"0871": u"NUCLEO_H723ZG",
u"0872": u"NUCLEO_G0B1RE",
u"0875": u"DISCO_H735G",
u"0879": u"NUCLEO_F756ZG",
u"0882": u"NUCLEO_G491RE",
u"0883": u"NUCLEO_WB15CC",
u"0884": u"DISCO_WB5MMG",
u"0885": u"B_L4S5I_IOT01A",
u"0886": u"NUCLEO_U575ZI_Q",
u"0887": u"B_U585I_IOT02A",
u"0900": u"SAMR21G18A",
u"0905": u"SAMD21G18A",
u"0910": u"SAML21J18A",
u"0915": u"SAMD21J18A",
u"1000": u"LPC2368",
u"1010": u"LPC1768",
u"1017": u"HRM1017",
u"1018": u"SSCI824",
u"1019": u"TY51822R3",
u"1022": u"RO359B",
u"1034": u"LPC11U34",
u"1040": u"LPC11U24",
u"1045": u"LPC11U24",
u"1050": u"LPC812",
u"1054": u"LPC54114",
u"1056": u"LPC546XX",
u"1060": u"LPC4088",
u"1061": u"LPC11U35_401",
u"1062": u"LPC4088_DM",
u"1070": u"NRF51822",
u"1075": u"NRF51822_OTA",
u"1080": u"OC_MBUINO",
u"1090": u"RBLAB_NRF51822",
u"1093": u"RBLAB_BLENANO2",
u"1095": u"RBLAB_BLENANO",
u"1100": u"NRF51_DK",
u"1101": u"NRF52_DK",
u"1102": u"NRF52840_DK",
u"1105": u"NRF51_DK_OTA",
u"1114": u"LPC1114",
u"1120": u"NRF51_DONGLE",
u"1130": u"NRF51822_SBK",
u"1140": u"WALLBOT_BLE",
u"1168": u"LPC11U68",
u"1200": u"NCS36510",
u"1234": u"UBLOX_C027",
u"1236": u"UBLOX_EVK_ODIN_W2",
u"1237": u"UBLOX_EVK_NINA_B1",
u"1280": u"OKDO_ODIN_W2",
u"1300": u"NUC472-NUTINY",
u"1301": u"NUMBED",
u"1302": u"NUMAKER_PFM_NUC472",
u"1303": u"NUMAKER_PFM_M453",
u"1304": u"NUMAKER_PFM_M487",
u"1305": u"NU_PFM_M2351",
u"1306": u"NUMAKER_PFM_NANO130",
u"1307": u"NUMAKER_PFM_NUC240",
u"1308": u"NUMAKER_IOT_M487",
u"1309": u"NUMAKER_IOT_M252",
u"1310": u"NUMAKER_IOT_M263A",
u"1312": u"NU_M2354",
u"1313": u"NUMAKER_IOT_M467",
u"1500": u"RHOMBIO_L476DMW1K",
u"1549": u"LPC1549",
u"1600": u"LPC4330_M4",
u"1605": u"LPC4330_M4",
u"1701": u"GD32_F307VG",
u"1702": u"GD32_F450ZI",
u"1703": u"GD32_E103VB",
u'1900': u'CY8CKIT_062_WIFI_BT',
u'1901': u'CY8CPROTO_062_4343W',
u'1902': u'CY8CKIT_062_BLE',
u'1903': u'CYW9P62S1_43012EVB_01',
u'1904': u'CY8CPROTO_063_BLE',
u'1905': u'CY8CKIT_062S2_4343W',
u'1906': u'CYW943012P6EVB_01',
u'1907': u'CY8CPROTO_064_SB',
u'1908': u'CYW9P62S1_43438EVB_01',
u'1909': u'CY8CPROTO_062S2_43012',
u'190A': u'CY8CKIT_064S2_4343W',
u'190B': u'CY8CKIT_062S2_43012',
u'190C': u'CY8CPROTO_064B0S3',
u'190E': u'CY8CPROTO_062S3_4343W',
u'190F': u'CY8CPROTO_064B0S1_BLE',
u'1910': u'CY8CKIT064B0S2_4343W',
u'1911': u'CY8CKIT064S0S2_4343W',
u'1912': u'CYSBSYSKIT_01',
u"2000": u"EFM32_G8XX_STK",
u"2005": u"EFM32HG_STK3400",
u"2010": u"EFM32WG_STK3800",
u"2015": u"EFM32GG_STK3700",
u"2020": u"EFM32LG_STK3600",
u"2025": u"EFM32TG_STK3300",
u"2030": u"EFM32ZG_STK3200",
u"2035": u"EFM32PG_STK3401",
u"2040": u"EFM32PG12_STK3402",
u"2041": u"TB_SENSE_12",
u"2042": u"EFM32GG11_STK3701",
u"2043": u"EFM32TG11_STK3301",
u"2045": u"TB_SENSE_1",
u"2100": u"XBED_LPC1768",
u"2201": u"WIZWIKI_W7500",
u"2202": u"WIZWIKI_W7500ECO",
u"2203": u"WIZWIKI_W7500P",
u"2600": u"EP_AGORA",
u"3001": u"LPC11U24",
u"3101": u"SDT32620B",
u"3102": u"SDT32625B",
u"3103": u"SDT51822B",
u"3104": u"SDT52832B",
u"3105": u"SDT64B",
u"3701": u"S5JS100",
u"3702": u"S3JT100",
u"3703": u"S1SBP6A",
u"4000": u"LPC11U35_Y5_MBUG",
u"4005": u"NRF51822_Y5_MBUG",
u"4100": u"MOTE_L152RC",
u"4337": u"LPC4337",
u"4500": u"DELTA_DFCM_NNN40",
u"4501": u"DELTA_DFBM_NQ620",
u"4502": u"DELTA_DFCM_NNN50",
u"4600": u"REALTEK_RTL8195AM",
u"5000": u"ARM_MPS2",
u"5001": u"ARM_IOTSS_BEID",
u"5002": u"ARM_BEETLE_SOC",
u"5003": u"ARM_MPS2_M0P",
u"5004": u"ARM_CM3DS_MPS2",
u"5005": u"ARM_MPS2_M0DS",
u"5006": u"ARM_MUSCA_A1",
u"5007": u"ARM_MUSCA_B1",
u"5009": u"ARM_MUSCA_S1",
u"5020": u"HOME_GATEWAY_6LOWPAN",
u"5500": u"RZ_A1H",
u"5501": u"GR_LYCHEE",
u"5502": u"GR_MANGO",
u"6000": u"FUTURE_SEQUANA",
u"6660": u"NZ32_SC151",
u"7011": u"TMPM066",
u"7012": u"TMPM3H6",
u"7013": u"TMPM46B",
u"7014": u"TMPM3HQ",
u"7015": u"TMPM4G9",
u"7020": u"TMPM4KN",
u"7402": u"MBED_BR_HAT",
u"7778": u"TEENSY3_1",
u"8001": u"UNO_91H",
u"8012": u"TT_M3HQ",
u"8013": u"TT_M4G9",
u"8080": u"FF1705_L151CC",
u"8081": u"FF_LPC546XX",
u"9001": u"LPC1347",
u"9002": u"LPC11U24",
u"9003": u"LPC1347",
u"9004": u"ARCH_PRO",
u"9006": u"LPC11U24",
u"9007": u"LPC11U35_501",
u"9008": u"XADOW_M0",
u"9009": u"ARCH_BLE",
u"9010": u"ARCH_GPRS",
u"9011": u"ARCH_MAX",
u"9012": u"SEEED_TINY_BLE",
u"9014": u"WIO_3G",
u"9015": u"WIO_BG96",
u"9017": u"WIO_EMW3166",
u"9020": u"UHURU_RAVEN",
u"9900": u"NRF51_MICROBIT",
u"C002": u"VK_RZ_A1H",
u"C005": u"MTM_MTCONNECT04S",
u"C006": u"VBLUNO51",
u"C008": u"SAKURAIO_EVB_01",
u"C030": u"UBLOX_C030_U201",
u"C031": u"UBLOX_C030_N211",
u"C032": u"UBLOX_C030_R404M",
u"C033": u"UBLOX_C030_R410M",
u"C034": u"UBLOX_C030_S200",
u"C035": u"UBLOX_C030_R3121",
u"C036": u"UBLOX_C030_R412M",
u"RIOT": u"RIOT",
},
u"jlink": {
u"X729475D28G": {
u"platform_name": u"NRF51_DK",
u"jlink_device_name": u"nRF51422_xxAC",
},
u"X349858SLYN": {
u"platform_name": u"NRF52_DK",
u"jlink_device_name": u"nRF52832_xxaa",
},
u"FRDM-KL25Z": {
u"platform_name": u"KL25Z",
u"jlink_device_name": u"MKL25Z128xxx4",
},
u"FRDM-KL27Z": {
u"platform_name": u"KL27Z",
u"jlink_device_name": u"MKL27Z64xxx4",
},
u"FRDM-KL43Z": {
u"platform_name": u"KL43Z",
u"jlink_device_name": u"MKL43Z256xxx4",
},
},
u"atmel": {u"2241": "SAML21J18A"},
}
def _get_modified_time(path):
try:
mtime = getmtime(path)
except OSError:
mtime = 0
return datetime.datetime.fromtimestamp(mtime)
def _older_than_me(path):
return _get_modified_time(path) < _get_modified_time(__file__)
def _modify_data_format(data, verbose_data, simple_data_key="platform_name"):
if isinstance(data, dict):
if verbose_data:
return data
return data[simple_data_key]
else:
if verbose_data:
return {simple_data_key: data}
return data
def _overwrite_or_open(db):
try:
if db is LOCAL_PLATFORM_DATABASE and _older_than_me(db):
raise ValueError("Platform Database is out of date")
with open(db, encoding="utf-8") as db_in:
return json.load(db_in)
except (IOError, ValueError) as exc:
if db is LOCAL_PLATFORM_DATABASE:
logger.warning("Error loading database %s: %s; Recreating", db, str(exc))
try:
makedirs(dirname(db))
except OSError:
pass
try:
with open(db, "w", encoding="utf-8") as out:
out.write(unicode(json.dumps(DEFAULT_PLATFORM_DB)))
except IOError:
pass
return copy(DEFAULT_PLATFORM_DB)
else:
return {}
class PlatformDatabase(object):
"""Represents a union of multiple platform database files.
Handles inter-process synchronization of database files.
"""
target_id_pattern = re.compile(r"^[a-fA-F0-9]{4}$")
def __init__(self, database_files, primary_database=None):
"""Construct a PlatformDatabase object from a series of platform database
files
"""
self._prim_db = primary_database
if not self._prim_db and len(database_files) == 1:
self._prim_db = database_files[0]
self._dbs = OrderedDict()
self._keys = defaultdict(set)
for db in database_files:
new_db = _overwrite_or_open(db)
first_value = None
if new_db.values():
first_value = next(iter(new_db.values()))
if not isinstance(first_value, dict):
new_db = {"daplink": new_db}
if new_db:
for device_type in new_db:
duplicates = self._keys[device_type].intersection(
set(new_db[device_type].keys())
)
duplicates = set(["%s.%s" % (device_type, k) for k in duplicates])
if duplicates:
logger.warning(
"Duplicate platform ids found: %s,"
" ignoring the definitions from %s",
" ".join(duplicates),
db,
)
self._dbs[db] = new_db
self._keys[device_type] = self._keys[device_type].union(
new_db[device_type].keys()
)
else:
self._dbs[db] = new_db
def items(self, device_type="daplink"):
for db in self._dbs.values():
for entry in db.get(device_type, {}).items():
yield entry
def all_ids(self, device_type="daplink"):
return iter(self._keys[device_type])
def get(self, index, default=None, device_type="daplink", verbose_data=False):
"""Standard lookup function. Works exactly like a dict. If 'verbose_data'
is True, all data for the platform is returned as a dict."""
for db in self._dbs.values():
if device_type in db:
maybe_answer = db[device_type].get(index, None)
if maybe_answer:
return _modify_data_format(maybe_answer, verbose_data)
return default
def _update_db(self):
if self._prim_db:
lock = InterProcessLock("%s.lock" % self._prim_db)
acquired = lock.acquire(blocking=False)
if not acquired:
logger.debug("Waiting 60 seconds for file lock")
acquired = lock.acquire(blocking=True, timeout=60)
if acquired:
try:
with open(self._prim_db, "w", encoding="utf-8") as out:
out.write(unicode(json.dumps(self._dbs[self._prim_db])))
return True
finally:
lock.release()
else:
logger.error(
"Could not update platform database: "
"Lock acquire failed after 60 seconds"
)
return False
else:
logger.error(
"Can't update platform database: destination database is ambiguous"
)
return False
def add(self, id, platform_name, permanent=False, device_type="daplink"):
"""Add a platform to this database, optionally updating an origin
database
"""
if self.target_id_pattern.match(id):
if self._prim_db:
if device_type not in self._dbs[self._prim_db]:
self._dbs[self._prim_db][device_type] = {}
self._dbs[self._prim_db][device_type][id] = platform_name
else:
cur_db = next(iter(self._dbs.values()))
if device_type not in cur_db:
cur_db[device_type] = {}
cur_db[device_type][id] = platform_name
self._keys[device_type].add(id)
if permanent:
self._update_db()
else:
raise ValueError("Invald target id: %s" % id)
def remove(self, id, permanent=False, device_type="daplink", verbose_data=False):
"""Remove a platform from this database, optionally updating an origin
database. If 'verbose_data' is True, all data for the platform is returned
as a dict.
"""
logger.debug("Trying remove of %s", id)
if id == "*" and device_type in self._dbs[self._prim_db]:
self._dbs[self._prim_db][device_type] = {}
if permanent:
self._update_db()
else:
for db in self._dbs.values():
if device_type in db and id in db[device_type]:
logger.debug("Removing id...")
removed = db[device_type][id]
del db[device_type][id]
self._keys[device_type].remove(id)
if permanent:
self._update_db()
return _modify_data_format(removed, verbose_data)

View File

@ -0,0 +1,517 @@
# Copyright (c) 2018, Arm Limited and affiliates.
# SPDX-License-Identifier: Apache-2.0
#
# 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.
import re
import sys
from collections import defaultdict
from copy import copy
from .lstools_base import MbedLsToolsBase
import logging
logger = logging.getLogger("mbedls.lstools_win7")
logger.addHandler(logging.NullHandler())
DEBUG = logging.DEBUG
del logging
if sys.version_info[0] < 3:
import _winreg as winreg
else:
import winreg
MAX_COMPOSITE_DEVICE_SUBDEVICES = 8
MBED_STORAGE_DEVICE_VENDOR_STRINGS = [
"ven_mbed",
"ven_segger",
"ven_arm_v2m",
"ven_nxp",
"ven_atmel",
]
def _get_values_with_numeric_keys(reg_key):
result = []
try:
for v in _iter_vals(reg_key):
try:
# The only values we care about are ones that have an integer key.
# The other values are metadata for the registry
int(v[0])
result.append(v[1])
except ValueError:
continue
except OSError:
logger.debug("Failed to iterate over all keys")
return result
def _is_mbed_volume(volume_string):
for vendor_string in MBED_STORAGE_DEVICE_VENDOR_STRINGS:
if vendor_string.lower() in volume_string.lower():
return True
return False
def _get_cached_mounted_points():
"""! Get the volumes present on the system
@return List of mount points and their associated volume string
Ex. [{ 'mount_point': 'D:', 'volume_string': 'xxxx'}, ...]
"""
result = []
try:
# Open the registry key for mounted devices
mounted_devices_key = winreg.OpenKey(
winreg.HKEY_LOCAL_MACHINE, "SYSTEM\\MountedDevices"
)
for v in _iter_vals(mounted_devices_key):
# Valid entries have the following format: \\DosDevices\\D:
if "DosDevices" not in v[0]:
continue
volume_string = v[1].decode("utf-16le", "ignore")
if not _is_mbed_volume(volume_string):
continue
mount_point_match = re.match(".*\\\\(.:)$", v[0])
if not mount_point_match:
logger.debug("Invalid disk pattern for entry %s, skipping", v[0])
continue
mount_point = mount_point_match.group(1)
logger.debug(
"Mount point %s found for volume %s", mount_point, volume_string
)
result.append({"mount_point": mount_point, "volume_string": volume_string})
except OSError:
logger.error('Failed to open "MountedDevices" in registry')
return result
def _get_disks():
logger.debug("Fetching mounted devices from disk service registry entry")
try:
disks_key = winreg.OpenKey(
winreg.HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Disk\\Enum"
)
disk_strings = _get_values_with_numeric_keys(disks_key)
return [v for v in disk_strings if _is_mbed_volume(v)]
except OSError:
logger.debug("No disk service found, no device can be detected")
return []
def _get_usb_storage_devices():
logger.debug("Fetching usb storage devices from USBSTOR service registry entry")
try:
usbstor_key = winreg.OpenKey(
winreg.HKEY_LOCAL_MACHINE,
"SYSTEM\\CurrentControlSet\\Services\\USBSTOR\\Enum",
)
return _get_values_with_numeric_keys(usbstor_key)
except OSError:
logger.debug("No USBSTOR service found, no device can be detected")
return []
def _determine_valid_non_composite_devices(devices, target_id_usb_id_mount_point_map):
# Some Mbed devices do not expose a composite USB device. This is typical for
# DAPLink devices in bootloader mode. Since we only have to check one endpoint
# (specifically, the mass storage device), we handle this case separately
candidates = {}
for device in devices:
device_key_string = "SYSTEM\\CurrentControlSet\\Enum\\" + device["full_path"]
try:
device_key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, device_key_string)
except OSError:
logger.debug('Key "%s" not found', device_key_string)
continue
try:
capability = _determine_subdevice_capability(device_key)
except CompatibleIDsNotFoundException:
logger.debug(
'Expected %s to have subkey "CompatibleIDs". Skipping.',
device_key_string,
)
continue
if capability != "msd":
logger.debug(
"Expected msd device but got %s, skipping %s",
capability,
device["full_path"],
)
continue
target_id_usb_id = device["entry_key_string"]
try:
candidates[target_id_usb_id] = {
"target_id_usb_id": target_id_usb_id,
"mount_point": target_id_usb_id_mount_point_map[target_id_usb_id],
}
candidates[target_id_usb_id].update(
_vid_pid_path_to_usb_info(device["vid_pid_path"])
)
except KeyError:
pass
return candidates
def _determine_subdevice_capability(key):
try:
vals = winreg.QueryValueEx(key, "CompatibleIDs")
compatible_ids = [x.lower() for x in vals[0]]
except OSError:
raise CompatibleIDsNotFoundException()
if "usb\\class_00" in compatible_ids or "usb\\devclass_00" in compatible_ids:
return "composite"
elif "usb\\class_08" in compatible_ids:
return "msd"
elif "usb\\class_02" in compatible_ids:
return "serial"
else:
logger.debug("Unknown capabilities from the following ids: %s", compatible_ids)
return None
def _vid_pid_path_to_usb_info(vid_pid_path):
"""! Provide the vendor ID and product ID of a device based on its entry in the registry
@return Returns {'vendor_id': '<vendor ID>', 'product': '<product ID>'}
@details If the vendor ID or product ID can't be determined, they will be returned
as None.
"""
result = {"vendor_id": None, "product_id": None}
for component in vid_pid_path.split("&"):
component_part = component.lower().split("_")
if len(component_part) != 2:
logger.debug("Unexpected VID/PID string structure %s", component)
break
if component_part[0] == "vid":
result["vendor_id"] = component_part[1]
elif component_part[0] == "pid":
result["product_id"] = component_part[1]
return result
def _iter_keys_as_str(key):
"""! Iterate over subkeys of a key returning subkey as string
"""
for i in range(winreg.QueryInfoKey(key)[0]):
yield winreg.EnumKey(key, i)
def _iter_keys(key):
"""! Iterate over subkeys of a key
"""
for i in range(winreg.QueryInfoKey(key)[0]):
yield winreg.OpenKey(key, winreg.EnumKey(key, i))
def _iter_vals(key):
"""! Iterate over values of a key
"""
logger.debug("_iter_vals %r", key)
for i in range(winreg.QueryInfoKey(key)[1]):
yield winreg.EnumValue(key, i)
class CompatibleIDsNotFoundException(Exception):
pass
class MbedLsToolsWin7(MbedLsToolsBase):
""" mbed-enabled platform detection for Windows
"""
def __init__(self, **kwargs):
MbedLsToolsBase.__init__(self, **kwargs)
self.os_supported.append("Windows7")
def find_candidates(self):
cached_mount_points = _get_cached_mounted_points()
disks = _get_disks()
usb_storage_devices = _get_usb_storage_devices()
target_id_usb_id_mount_point_map = {}
for cached_mount_point_info in cached_mount_points:
for index, disk in enumerate(copy(disks)):
match_string = disk.split("\\")[-1]
if match_string in cached_mount_point_info["volume_string"]:
# TargetID is a hex string with 10-48 chars
target_id_usb_id_match = re.search(
"[&#]([0-9A-Za-z]{10,48})[&#]",
cached_mount_point_info["volume_string"],
)
if not target_id_usb_id_match:
logger.debug(
"Entry %s has invalid target id pattern %s, skipping",
cached_mount_point_info["mount_point"],
cached_mount_point_info["volume_string"],
)
continue
target_id_usb_id_mount_point_map[
target_id_usb_id_match.group(1)
] = cached_mount_point_info["mount_point"]
disks.pop(index)
break
logger.debug(
"target_id_usb_id -> mount_point mapping: %s ",
target_id_usb_id_mount_point_map,
)
non_composite_devices = []
composite_devices = []
for vid_pid_path in usb_storage_devices:
# Split paths like "USB\VID_0483&PID_374B&MI_01\7&25b4dc8e&0&0001" by "\"
vid_pid_path_componets = vid_pid_path.split("\\")
vid_pid_components = vid_pid_path_componets[1].split("&")
if len(vid_pid_components) != 2 and len(vid_pid_components) != 3:
logger.debug(
"Skipping USBSTOR device with unusual VID/PID string format '%s'",
vid_pid_path,
)
continue
device = {
"full_path": vid_pid_path,
"vid_pid_path": "&".join(vid_pid_components[:2]),
"entry_key_string": vid_pid_path_componets[2],
}
# A composite device's vid/pid path always has a third component
if len(vid_pid_components) == 3:
composite_devices.append(device)
else:
non_composite_devices.append(device)
candidates = defaultdict(dict)
candidates.update(
_determine_valid_non_composite_devices(
non_composite_devices, target_id_usb_id_mount_point_map
)
)
# Now we'll find all valid VID/PID and target ID combinations
target_id_usb_ids = set(target_id_usb_id_mount_point_map.keys()) - set(
candidates.keys()
)
vid_pid_entry_key_string_map = defaultdict(set)
for device in composite_devices:
vid_pid_entry_key_string_map[device["vid_pid_path"]].add(
device["entry_key_string"]
)
vid_pid_target_id_usb_id_map = defaultdict(dict)
usb_key_string = "SYSTEM\\CurrentControlSet\\Enum\\USB"
for vid_pid_path, entry_key_strings in vid_pid_entry_key_string_map.items():
vid_pid_key_string = "%s\\%s" % (usb_key_string, vid_pid_path)
try:
vid_pid_key = winreg.OpenKey(
winreg.HKEY_LOCAL_MACHINE, vid_pid_key_string
)
target_id_usb_id_sub_keys = set(
[k for k in _iter_keys_as_str(vid_pid_key)]
)
except OSError:
logger.debug('VID/PID "%s" not found', vid_pid_key_string)
continue
overlapping_target_id_usb_ids = target_id_usb_id_sub_keys.intersection(
set(target_id_usb_ids)
)
for target_id_usb_id in overlapping_target_id_usb_ids:
composite_device_key_string = "%s\\%s" % (
vid_pid_key_string,
target_id_usb_id,
)
composite_device_key = winreg.OpenKey(vid_pid_key, target_id_usb_id)
entry_key_string = target_id_usb_id
is_prefix = False
try:
new_entry_key_string, _ = winreg.QueryValueEx(
composite_device_key, "ParentIdPrefix"
)
if any(
e.startswith(new_entry_key_string) for e in entry_key_strings
):
logger.debug(
"Assigning new entry key string of %s to device %s, "
"as found in ParentIdPrefix",
new_entry_key_string,
target_id_usb_id,
)
entry_key_string = new_entry_key_string
is_prefix = True
except OSError:
logger.debug(
'Device %s did not have a "ParentIdPrefix" key, '
"sticking with %s as entry key string",
composite_device_key_string,
target_id_usb_id,
)
vid_pid_target_id_usb_id_map[vid_pid_path][entry_key_string] = {
"target_id_usb_id": target_id_usb_id,
"is_prefix": is_prefix,
}
for (
vid_pid_path,
entry_key_string_target_id_usb_id_map,
) in vid_pid_target_id_usb_id_map.items():
for composite_device_subdevice_number in range(
MAX_COMPOSITE_DEVICE_SUBDEVICES
):
subdevice_type_key_string = "%s\\%s&MI_0%d" % (
usb_key_string,
vid_pid_path,
composite_device_subdevice_number,
)
try:
subdevice_type_key = winreg.OpenKey(
winreg.HKEY_LOCAL_MACHINE, subdevice_type_key_string
)
except OSError:
logger.debug(
"Composite device subdevice key %s was not found, skipping",
subdevice_type_key_string,
)
continue
for (
entry_key_string,
entry_data,
) in entry_key_string_target_id_usb_id_map.items():
if entry_data["is_prefix"]:
prepared_entry_key_string = "%s&000%d" % (
entry_key_string,
composite_device_subdevice_number,
)
else:
prepared_entry_key_string = entry_key_string
subdevice_key_string = "%s\\%s" % (
subdevice_type_key_string,
prepared_entry_key_string,
)
try:
subdevice_key = winreg.OpenKey(
subdevice_type_key, prepared_entry_key_string
)
except OSError:
logger.debug(
"Sub-device %s not found, skipping", subdevice_key_string
)
continue
try:
capability = _determine_subdevice_capability(subdevice_key)
except CompatibleIDsNotFoundException:
logger.debug(
'Expected %s to have subkey "CompatibleIDs". Skipping.',
subdevice_key_string,
)
continue
if capability == "msd":
candidates[entry_data["target_id_usb_id"]][
"mount_point"
] = target_id_usb_id_mount_point_map[
entry_data["target_id_usb_id"]
]
candidates[entry_data["target_id_usb_id"]].update(
_vid_pid_path_to_usb_info(vid_pid_path)
)
elif capability == "serial":
try:
device_parameters_key = winreg.OpenKey(
subdevice_key, "Device Parameters"
)
except OSError:
logger.debug(
'Key "Device Parameters" not under serial device entry'
)
continue
try:
candidates[entry_data["target_id_usb_id"]][
"serial_port"
], _ = winreg.QueryValueEx(
device_parameters_key, "PortName"
)
candidates[entry_data["target_id_usb_id"]].update(
_vid_pid_path_to_usb_info(vid_pid_path)
)
except OSError:
logger.debug(
'"PortName" value not found under serial device entry'
)
continue
final_candidates = []
for target_id_usb_id, candidate in candidates.items():
candidate["target_id_usb_id"] = target_id_usb_id
if "serial_port" not in candidate:
candidate["serial_port"] = None
if "mount_point" not in candidate:
candidate["mount_point"] = None
final_candidates.append(candidate)
return final_candidates
def mount_point_ready(self, path):
"""! Check if a mount point is ready for file operations
@return Returns True if the given path exists, False otherwise
@details Calling the Windows command `dir` instead of using the python
`os.path.exists`. The latter causes a Python error box to appear claiming
there is "No Disk" for some devices that are in the ejected state. Calling
`dir` prevents this since it uses the Windows API to determine if the
device is ready before accessing the file system.
"""
stdout, stderr, retcode = self._run_cli_process("dir %s" % path)
result = True if retcode == 0 else False
if result:
logger.debug("Mount point %s is ready", path)
else:
logger.debug(
"Mount point %s reported not ready with error '%s'",
path,
stderr.strip(),
)
return result

View File

@ -0,0 +1,382 @@
# Copyright (c) 2018, Arm Limited and affiliates.
# SPDX-License-Identifier: Apache-2.0
#
# 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.
"""! @package mbed-host-tests
Flash, reset and perform host supervised tests on mbed platforms.
Write your own programs (import this package) or use 'mbedhtrun'
command line tool instead.
"""
import imp
import sys
from optparse import OptionParser
from optparse import SUPPRESS_HELP
from . import host_tests_plugins
from .host_tests_registry import HostRegistry # noqa: F401
from .host_tests import BaseHostTest, event_callback # noqa: F401
# Set the default baud rate
DEFAULT_BAUD_RATE = 9600
###############################################################################
# Functional interface for test supervisor registry
###############################################################################
def get_plugin_caps(methods=None):
if not methods:
methods = ["CopyMethod", "ResetMethod"]
result = {}
for method in methods:
result[method] = host_tests_plugins.get_plugin_caps(method)
return result
def init_host_test_cli_params():
"""! Function creates CLI parser object and returns populated options object.
@return Function returns 'options' object returned from OptionParser class
@details Options object later can be used to populate host test selector script.
"""
parser = OptionParser()
parser.add_option(
"-m",
"--micro",
dest="micro",
help="Target microcontroller name",
metavar="MICRO",
)
parser.add_option(
"-p", "--port", dest="port", help="Serial port of the target", metavar="PORT"
)
parser.add_option(
"-d",
"--disk",
dest="disk",
help="Target disk (mount point) path",
metavar="DISK_PATH",
)
parser.add_option(
"-t",
"--target-id",
dest="target_id",
help="Unique Target Id or mbed platform",
metavar="TARGET_ID",
)
parser.add_option(
"",
"--sync",
dest="sync_behavior",
default=2,
type=int,
help=(
"Define how many times __sync packet will be sent to device: 0: "
"none; -1: forever; 1,2,3... - number of times (Default 2 time)"
),
metavar="SYNC_BEHAVIOR",
)
parser.add_option(
"",
"--sync-timeout",
dest="sync_timeout",
default=5,
type=int,
help="Define delay in seconds between __sync packet (Default is 5 seconds)",
metavar="SYNC_TIMEOUT",
)
parser.add_option(
"-f",
"--image-path",
dest="image_path",
help="Path with target's binary image",
metavar="IMAGE_PATH",
)
copy_methods_str = "Plugin support: " + ", ".join(
host_tests_plugins.get_plugin_caps("CopyMethod")
)
parser.add_option(
"-c",
"--copy",
dest="copy_method",
help="Copy (flash the target) method selector. " + copy_methods_str,
metavar="COPY_METHOD",
)
parser.add_option(
"",
"--retry-copy",
dest="retry_copy",
default=3,
type=int,
help="Number of attempts to flash the target",
metavar="RETRY_COPY",
)
parser.add_option(
"",
"--tag-filters",
dest="tag_filters",
default="",
type=str,
help=(
"Comma seperated list of device tags used when allocating a target "
"to specify required hardware or attributes [--tag-filters tag1,tag2]"
),
metavar="TAG_FILTERS",
)
reset_methods_str = "Plugin support: " + ", ".join(
host_tests_plugins.get_plugin_caps("ResetMethod")
)
parser.add_option(
"-r",
"--reset",
dest="forced_reset_type",
help="Forces different type of reset. " + reset_methods_str,
)
parser.add_option(
"-C",
"--program_cycle_s",
dest="program_cycle_s",
default=4,
help=(
"Program cycle sleep. Define how many seconds you want wait after "
"copying binary onto target (Default is 4 second)"
),
type="float",
metavar="PROGRAM_CYCLE_S",
)
parser.add_option(
"-R",
"--reset-timeout",
dest="forced_reset_timeout",
default=1,
metavar="NUMBER",
type="float",
help=(
"When forcing a reset using option -r you can set up after reset "
"idle delay in seconds (Default is 1 second)"
),
)
parser.add_option(
"--process-start-timeout",
dest="process_start_timeout",
default=60,
metavar="NUMBER",
type="float",
help=(
"This sets the maximum time in seconds to wait for an internal "
"process to start. This mostly only affects machines under heavy "
"load (Default is 60 seconds)"
),
)
parser.add_option(
"-e",
"--enum-host-tests",
dest="enum_host_tests",
action="append",
default=["./test/host_tests"],
help="Define directory with local host tests",
)
parser.add_option(
"",
"--test-cfg",
dest="json_test_configuration",
help="Pass to host test class data about host test configuration",
)
parser.add_option(
"",
"--list",
dest="list_reg_hts",
default=False,
action="store_true",
help="Prints registered host test and exits",
)
parser.add_option(
"",
"--plugins",
dest="list_plugins",
default=False,
action="store_true",
help="Prints registered plugins and exits",
)
parser.add_option(
"-g",
"--grm",
dest="global_resource_mgr",
help=(
'Global resource manager: "<remote mgr module>:<host url or IP address>'
'[:<port>]", Ex. "module_name:10.2.123.43:3334", '
'module_name:https://example.com"'
),
)
# Show --fm option only if "fm_agent" module installed
try:
imp.find_module("fm_agent")
except ImportError:
fm_help = SUPPRESS_HELP
else:
fm_help = (
'Fast Model connection, This option requires mbed-fastmodel-agent '
'module installed, list CONFIGs via "mbedfm"'
)
parser.add_option(
"",
"--fm",
dest="fast_model_connection",
metavar="CONFIG",
default=None,
help=fm_help,
)
parser.add_option(
"",
"--run",
dest="run_binary",
default=False,
action="store_true",
help="Runs binary image on target (workflow: flash, reset, output console)",
)
parser.add_option(
"",
"--skip-flashing",
dest="skip_flashing",
default=False,
action="store_true",
help="Skips use of copy/flash plugin. Note: target will not be reflashed",
)
parser.add_option(
"",
"--skip-reset",
dest="skip_reset",
default=False,
action="store_true",
help="Skips use of reset plugin. Note: target will not be reset",
)
parser.add_option(
"-P",
"--polling-timeout",
dest="polling_timeout",
default=60,
metavar="NUMBER",
type="int",
help=(
"Timeout in sec for readiness of mount point and serial port of "
"local or remote device. Default 60 sec"
),
)
parser.add_option(
"-b",
"--send-break",
dest="send_break_cmd",
default=False,
action="store_true",
help=(
"Send reset signal to board on specified port (-p PORT) and print "
"serial output. You can combine this with (-r RESET_TYPE) switch"
),
)
parser.add_option(
"",
"--baud-rate",
dest="baud_rate",
help=(
"Baud rate of target, overrides values from mbed-ls, disk/mount "
"point (-d, --disk-path), and serial port -p <port>:<baud rate>"
),
metavar="BAUD_RATE",
)
parser.add_option(
"-v",
"--verbose",
dest="verbose",
default=False,
action="store_true",
help="More verbose mode",
)
parser.add_option(
"",
"--serial-output-file",
dest="serial_output_file",
default=None,
help="Save target serial output to this file.",
)
parser.add_option(
"",
"--compare-log",
dest="compare_log",
default=None,
help="Log file to compare with the serial output from target.",
)
parser.add_option(
"",
"--version",
dest="version",
default=False,
action="store_true",
help="Prints package version and exits",
)
parser.add_option(
"",
"--format",
dest="format",
help="Image file format passed to pyocd (elf, bin, hex, axf...).",
)
parser.description = (
"""Flash, reset and perform host supervised tests on mbed platforms"""
)
parser.epilog = (
"""Example: mbedhtrun -d E: -p COM5 -f "test.bin" -C 4 -c shell -m K64F"""
)
(options, _) = parser.parse_args()
if len(sys.argv) == 1:
parser.print_help()
sys.exit()
return options

View File

@ -0,0 +1,17 @@
# Copyright (c) 2018, Arm Limited and affiliates.
# SPDX-License-Identifier: Apache-2.0
#
# 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.
from .mbed_greentea_cli import main
main()

View File

@ -0,0 +1,144 @@
# Copyright (c) 2018, Arm Limited and affiliates.
# SPDX-License-Identifier: Apache-2.0
#
# 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.
import re
import os
import os.path
from .mbed_greentea_log import gt_logger
def load_ctest_testsuite(link_target, binary_type=".bin", verbose=False):
"""! Loads CMake.CTest formatted data about tests from test directory
@return Dictionary of { test_case : test_case_path } pairs
"""
result = {}
if link_target is not None:
ctest_path = os.path.join(link_target, "test", "CTestTestfile.cmake")
try:
with open(ctest_path) as ctest_file:
for line in ctest_file:
line_parse = parse_ctesttestfile_line(
link_target, binary_type, line, verbose=verbose
)
if line_parse:
test_case, test_case_path = line_parse
result[test_case] = test_case_path
except: # noqa: E722
pass # Return empty list if path is not found
return result
def parse_ctesttestfile_line(link_target, binary_type, line, verbose=False):
"""! Parse lines of CTestTestFile.cmake file and searches for 'add_test'
@return Dictionary of { test_case : test_case_path } pairs or None if
failed to parse 'add_test' line
@details Example path with CTestTestFile.cmake:
c:/temp/xxx/mbed-sdk-private/build/frdm-k64f-gcc/test/
Example format of CTestTestFile.cmake:
# CMake generated Testfile for
# Source directory: c:/temp/xxx/mbed-sdk-private/build/frdm-k64f-gcc/test
# Build directory: c:/temp/xxx/mbed-sdk-private/build/frdm-k64f-gcc/test
#
# This file includes the relevant testing commands required for
# testing this directory and lists subdirectories to be tested as well.
add_test(mbed-test-stdio "mbed-test-stdio")
add_test(mbed-test-call_before_main "mbed-test-call_before_main")
add_test(mbed-test-dev_null "mbed-test-dev_null")
add_test(mbed-test-div "mbed-test-div")
add_test(mbed-test-echo "mbed-test-echo")
add_test(mbed-test-ticker "mbed-test-ticker")
add_test(mbed-test-hello "mbed-test-hello")
"""
add_test_pattern = r'[adtesADTES_]{8}\([\w\d_-]+ \"([\w\d_-]+)\"'
re_ptrn = re.compile(add_test_pattern)
if line.lower().startswith("add_test"):
m = re_ptrn.search(line)
if m and len(m.groups()) > 0:
if verbose:
print(m.group(1) + binary_type)
test_case = m.group(1)
test_case_path = os.path.join(link_target, "test", m.group(1) + binary_type)
return test_case, test_case_path
return None
def list_binaries_for_targets(build_dir="./build", verbose_footer=False):
"""! Prints tests in target directories, only if tests exist.
@param build_dir Yotta default build directory where tests will be
@param verbose_footer Prints additional "how to use" Greentea footer
@details Skips empty / no tests for target directories.
"""
dir = build_dir
sub_dirs = (
[
os.path.join(dir, o)
for o in os.listdir(dir)
if os.path.isdir(os.path.join(dir, o))
]
if os.path.exists(dir)
else []
)
def count_tests():
result = 0
for sub_dir in sub_dirs:
test_list = load_ctest_testsuite(sub_dir, binary_type="")
if len(test_list):
for test in test_list:
result += 1
return result
if count_tests():
for sub_dir in sub_dirs:
target_name = sub_dir.split(os.sep)[-1]
gt_logger.gt_log(
"available tests for target '%s', location '%s'"
% (target_name, os.path.abspath(os.path.join(build_dir, sub_dir)))
)
test_list = load_ctest_testsuite(sub_dir, binary_type="")
if len(test_list):
for test in sorted(test_list):
gt_logger.gt_log_tab("test '%s'" % test)
else:
gt_logger.gt_log_warn("no tests found in current location")
if verbose_footer:
print(
"\nExample: execute 'mbedgt -t TARGET_NAME -n TEST_NAME' to run "
"test TEST_NAME for target TARGET_NAME"
)
def list_binaries_for_builds(test_spec, verbose_footer=False):
"""! Parse test spec and list binaries (BOOTABLE) in lexicographical order
@param test_spec Test specification object
@param verbose_footer Prints additional "how to use" Greentea footer
"""
test_builds = test_spec.get_test_builds()
for tb in test_builds:
gt_logger.gt_log(
"available tests for build '%s', location '%s'"
% (tb.get_name(), tb.get_path())
)
for tc in sorted(tb.get_tests().keys()):
gt_logger.gt_log_tab("test '%s'" % tc)
if verbose_footer:
print(
"\nExample: execute 'mbedgt -t BUILD_NAME -n TEST_NAME' to run test "
"TEST_NAME for build TARGET_NAME in current test specification"
)

View File

@ -0,0 +1,17 @@
# Copyright (c) 2018, Arm Limited and affiliates.
# SPDX-License-Identifier: Apache-2.0
#
# 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.
# base host test class
from .base_host_test import BaseHostTest, event_callback

View File

@ -0,0 +1,269 @@
# Copyright (c) 2018, Arm Limited and affiliates.
# SPDX-License-Identifier: Apache-2.0
#
# 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.
import inspect
import six
from time import time
from inspect import isfunction, ismethod
class BaseHostTestAbstract(object):
""" Base class for each host-test test cases with standard
setup, test and teardown set of functions
"""
name = '' # name of the host test (used for local registration)
__event_queue = None # To main even loop
__dut_event_queue = None # To DUT
script_location = None # Path to source file used to load host test
__config = {}
def __notify_prn(self, text):
if self.__event_queue:
self.__event_queue.put(('__notify_prn', text, time()))
def __notify_conn_lost(self, text):
if self.__event_queue:
self.__event_queue.put(('__notify_conn_lost', text, time()))
def __notify_sync_failed(self, text):
if self.__event_queue:
self.__event_queue.put(('__notify_sync_failed', text, time()))
def __notify_dut(self, key, value):
"""! Send data over serial to DUT """
if self.__dut_event_queue:
self.__dut_event_queue.put((key, value, time()))
def notify_complete(self, result=None):
"""! Notify main even loop that host test finished processing
@param result True for success, False failure. If None - no action in main even loop
"""
if self.__event_queue:
self.__event_queue.put(('__notify_complete', result, time()))
def reset_dut(self, value):
"""
Reset device under test
:return:
"""
if self.__event_queue:
self.__event_queue.put(('__reset_dut', value, time()))
def reset(self):
"""
Reset the device under test and continue running the host test
:return:
"""
if self.__event_queue:
self.__event_queue.put(("__reset", "0", time()))
def notify_conn_lost(self, text):
"""! Notify main even loop that there was a DUT-host test connection error
@param consume If True htrun will process (consume) all remaining events
"""
self.__notify_conn_lost(text)
def log(self, text):
"""! Send log message to main event loop """
self.__notify_prn(text)
def send_kv(self, key, value):
"""! Send Key-Value data to DUT """
self.__notify_dut(key, value)
def setup_communication(self, event_queue, dut_event_queue, config={}):
"""! Setup queues used for IPC """
self.__event_queue = event_queue # To main even loop
self.__dut_event_queue = dut_event_queue # To DUT
self.__config = config
def get_config_item(self, name):
"""
Return test config
:param name:
:return:
"""
return self.__config.get(name, None)
def setup(self):
"""! Setup your tests and callbacks """
raise NotImplementedError
def result(self):
"""! Returns host test result (True, False or None) """
raise NotImplementedError
def teardown(self):
"""! Blocking always guaranteed test teardown """
raise NotImplementedError
def event_callback(key):
"""
Decorator for defining a event callback method. Adds a property attribute "event_key" with value as the passed key.
:param key:
:return:
"""
def decorator(func):
func.event_key = key
return func
return decorator
class HostTestCallbackBase(BaseHostTestAbstract):
def __init__(self):
BaseHostTestAbstract.__init__(self)
self.__callbacks = {}
self.__restricted_callbacks = [
'__coverage_start',
'__testcase_start',
'__testcase_finish',
'__testcase_summary',
'__exit',
'__exit_event_queue'
]
self.__consume_by_default = [
'__coverage_start',
'__testcase_start',
'__testcase_finish',
'__testcase_count',
'__testcase_name',
'__testcase_summary',
'__rxd_line',
]
self.__assign_default_callbacks()
self.__assign_decorated_callbacks()
def __callback_default(self, key, value, timestamp):
"""! Default callback """
#self.log("CALLBACK: key=%s, value=%s, timestamp=%f"% (key, value, timestamp))
pass
def __default_end_callback(self, key, value, timestamp):
"""
Default handler for event 'end' that gives test result from target.
This callback is not decorated as we don't know then in what order this
callback would be registered. We want to let users over write this callback.
Hence it should be registered before registering user defined callbacks.
:param key:
:param value:
:param timestamp:
:return:
"""
self.notify_complete(value == 'success')
def __assign_default_callbacks(self):
"""! Assigns default callback handlers """
for key in self.__consume_by_default:
self.__callbacks[key] = self.__callback_default
# Register default handler for event 'end' before assigning user defined callbacks to let users over write it.
self.register_callback('end', self.__default_end_callback)
def __assign_decorated_callbacks(self):
"""
It looks for any callback methods decorated with @event_callback
Example:
Define a method with @event_callback decorator like:
@event_callback('<event key>')
def event_handler(self, key, value, timestamp):
do something..
:return:
"""
for name, method in inspect.getmembers(self, inspect.ismethod):
key = getattr(method, 'event_key', None)
if key:
self.register_callback(key, method)
def register_callback(self, key, callback, force=False):
"""! Register callback for a specific event (key: event name)
@param key String with name of the event
@param callback Callable which will be registstered for event "key"
@param force God mode
"""
# Non-string keys are not allowed
if type(key) is not str:
raise TypeError("event non-string keys are not allowed")
# And finally callback should be callable
if not callable(callback):
raise TypeError("event callback should be callable")
# Check if callback has all three required parameters (key, value, timestamp)
# When callback is class method should have 4 arguments (self, key, value, timestamp)
if ismethod(callback):
arg_count = six.get_function_code(callback).co_argcount
if arg_count != 4:
err_msg = "callback 'self.%s('%s', ...)' defined with %d arguments"% (callback.__name__, key, arg_count)
err_msg += ", should have 4 arguments: self.%s(self, key, value, timestamp)"% callback.__name__
raise TypeError(err_msg)
# When callback is just a function should have 3 arguments func(key, value, timestamp)
if isfunction(callback):
arg_count = six.get_function_code(callback).co_argcount
if arg_count != 3:
err_msg = "callback '%s('%s', ...)' defined with %d arguments"% (callback.__name__, key, arg_count)
err_msg += ", should have 3 arguments: %s(key, value, timestamp)"% callback.__name__
raise TypeError(err_msg)
if not force:
# Event starting with '__' are reserved
if key.startswith('__'):
raise ValueError("event key starting with '__' are reserved")
# We predefined few callbacks you can't use
if key in self.__restricted_callbacks:
raise ValueError("we predefined few callbacks you can't use e.g. '%s'"% key)
self.__callbacks[key] = callback
def get_callbacks(self):
return self.__callbacks
def setup(self):
pass
def result(self):
pass
def teardown(self):
pass
class BaseHostTest(HostTestCallbackBase):
__BaseHostTest_Called = False
def base_host_test_inited(self):
""" This function will check if BaseHostTest ctor was called
Call to BaseHostTest is required in order to force required
interfaces implementation.
@return Returns True if ctor was called (ok behaviour)
"""
return self.__BaseHostTest_Called
def __init__(self):
HostTestCallbackBase.__init__(self)
self.__BaseHostTest_Called = True

View File

@ -0,0 +1,24 @@
# Copyright (c) 2018, Arm Limited and affiliates.
# SPDX-License-Identifier: Apache-2.0
#
# 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.
from .. import BaseHostTest
class DefaultAuto(BaseHostTest):
""" Simple, basic host test's test runner waiting for serial port
output from MUT, no supervision over test running in MUT is executed.
"""
pass

View File

@ -0,0 +1,57 @@
# Copyright (c) 2018, Arm Limited and affiliates.
# SPDX-License-Identifier: Apache-2.0
#
# 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.
import re
from .. import BaseHostTest
class DetectPlatformTest(BaseHostTest):
PATTERN_MICRO_NAME = "Target '(\w+)'"
re_detect_micro_name = re.compile(PATTERN_MICRO_NAME)
def result(self):
raise NotImplementedError
def test(self, selftest):
result = True
c = selftest.mbed.serial_readline() # {{start}} preamble
if c is None:
return selftest.RESULT_IO_SERIAL
selftest.notify(c.strip())
selftest.notify("HOST: Detecting target name...")
c = selftest.mbed.serial_readline()
if c is None:
return selftest.RESULT_IO_SERIAL
selftest.notify(c.strip())
# Check for target name
m = self.re_detect_micro_name.search(c)
if m and len(m.groups()):
micro_name = m.groups()[0]
micro_cmp = selftest.mbed.options.micro == micro_name
result = result and micro_cmp
selftest.notify("HOST: MUT Target name '%s', expected '%s'... [%s]"% (micro_name,
selftest.mbed.options.micro,
"OK" if micro_cmp else "FAIL"))
for i in range(0, 2):
c = selftest.mbed.serial_readline()
if c is None:
return selftest.RESULT_IO_SERIAL
selftest.notify(c.strip())
return selftest.RESULT_SUCCESS if result else selftest.RESULT_FAILURE

View File

@ -0,0 +1,36 @@
# Copyright (c) 2018, Arm Limited and affiliates.
# SPDX-License-Identifier: Apache-2.0
#
# 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.
from .. import BaseHostTest
class DevNullTest(BaseHostTest):
__result = None
def _callback_result(self, key, value, timestamp):
# We should not see result data in this test
self.__result = False
def _callback_to_stdout(self, key, value, timestamp):
self.__result = True
self.log("_callback_to_stdout !")
def setup(self):
self.register_callback("end", self._callback_result)
self.register_callback("to_null", self._callback_result)
self.register_callback("to_stdout", self._callback_to_stdout)
def result(self):
return self.__result

View File

@ -0,0 +1,55 @@
# Copyright (c) 2018, Arm Limited and affiliates.
# SPDX-License-Identifier: Apache-2.0
#
# 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.
import uuid
from .. import BaseHostTest
class EchoTest(BaseHostTest):
__result = None
echo_count = 0
count = 0
uuid_sent = []
uuid_recv = []
def __send_echo_uuid(self):
if self.echo_count:
str_uuid = str(uuid.uuid4())
self.send_kv("echo", str_uuid)
self.uuid_sent.append(str_uuid)
self.echo_count -= 1
def _callback_echo(self, key, value, timestamp):
self.uuid_recv.append(value)
self.__send_echo_uuid()
def _callback_echo_count(self, key, value, timestamp):
# Handshake
self.echo_count = int(value)
self.send_kv(key, value)
# Send first echo to echo server on DUT
self.__send_echo_uuid()
def setup(self):
self.register_callback("echo", self._callback_echo)
self.register_callback("echo_count", self._callback_echo_count)
def result(self):
self.__result = self.uuid_sent == self.uuid_recv
return self.__result
def teardown(self):
pass

Some files were not shown because too many files have changed in this diff Show More