Skip to content

Commit

Permalink
Merge pull request #9838 from artokin/nanostack_for_mbed_os_5_12
Browse files Browse the repository at this point in the history
Nanostack release for Mbed OS 5.12
  • Loading branch information
0xc0170 committed Feb 27, 2019
2 parents 5b78adc + 5486a38 commit 7027eac
Show file tree
Hide file tree
Showing 316 changed files with 23,978 additions and 1,199 deletions.
1 change: 1 addition & 0 deletions features/frameworks/mbed-trace/.mbedignore
Expand Up @@ -2,3 +2,4 @@ build/*
yotta_modules/*
yotta_targets/*
test/*
example/*
1 change: 0 additions & 1 deletion features/frameworks/mbed-trace/.yotta_ignore

This file was deleted.

281 changes: 281 additions & 0 deletions features/frameworks/mbed-trace/Jenkinsfile
@@ -0,0 +1,281 @@
echo "Start to build"

properties ([
buildDiscarder(
logRotator(
artifactNumToKeepStr: '10',
numToKeepStr: '100'
)
)
])

// List of targets to compile
def morpheusTargets = [
//"LPC1768",
//"NUCLEO_F401RE",
//"NRF51DK",
"K64F"
]
// Map morpheus toolchains to compiler labels on Jenkins
def toolchains = [
ARM: "armcc",
IAR: "iar_arm",
GCC_ARM: "arm-none-eabi-gcc"
]
// yotta target includes toolchain
def yottaTargets = [
"frdm-k64f-gcc": "gcc",
"frdm-k64f-armcc": "armcc",
"nrf51dk-gcc": "gcc",
"stm32f429i-disco-gcc": "gcc",
"x86-linux-native": "linux && astyle"
]

// Initial maps for parallel build steps
def stepsForParallel = [:]
// Jenkins pipeline does not support map.each, we need to use oldschool for loop
for (int i = 0; i < morpheusTargets.size(); i++) {
for(int j = 0; j < toolchains.size(); j++) {
def target = morpheusTargets.get(i)
def toolchain = toolchains.keySet().asList().get(j)
def compilerLabel = toolchains.get(toolchain)
def stepName = "mbed-os5-${target} ${toolchain}"
stepsForParallel[stepName] = morpheusBuildStep(target, compilerLabel, toolchain)
}
}
// map yotta steps
for (int i = 0; i < yottaTargets.size(); i++) {
def target = yottaTargets.keySet().asList().get(i)
def compilerLabel = yottaTargets.get(target)
def stepName = "mbed-os3-${target}"
stepsForParallel[stepName] = yottaBuildStep(target, compilerLabel)
}

/* Jenkins does not allow stages inside parallel execution,
* https://issues.jenkins-ci.org/browse/JENKINS-26107 will solve this by adding labeled blocks
*/
// Actually run the steps in parallel - parallel takes a map as an argument, hence the above.
timestamps {
timeout(time: 30, unit: "MINUTES") {
parallel stepsForParallel
}
}

def execute(cmd) {
if(isUnix()) {
sh "${cmd}"
} else {
bat "${cmd}"
}
}

//Create morpheus build steps for parallel execution
def morpheusBuildStep(target, compilerLabel, toolchain) {
return {
node ("${compilerLabel}") {
deleteDir()
dir("mbed-trace") {
String buildName = "mbed-os5-${target}-${toolchain}"
def scmVars = checkout scm
env.GIT_COMMIT_HASH = scmVars.GIT_COMMIT
setBuildStatus('PENDING', "build ${buildName}", 'build starts')
stage ("build:${buildName}") {
try{
execute("mbed --version")
execute("echo https://github.com/armmbed/mbed-os/#6a0a86538c0b9b2bfcc4583b1e2b7fea8f4e71e9 > mbed-os.lib")
execute("mbed deploy")
execute("rm -rf ./mbed-os/features/frameworks/mbed-trace")
execute("mbed compile -m ${target} -t ${toolchain} --library")
setBuildStatus('SUCCESS', "build ${buildName}", "build done")
} catch (err) {
echo "Caught exception: ${err}"
setBuildStatus('FAILURE', "build ${buildName}", "build failed")
throw err
}
}
stage("build:example:${buildName}") {
execute("mkdir ../example-mbed-os-5 || true")
execute("cp -R example/mbed-os-5 ../example-mbed-os-5")
dir("../example-mbed-os-5") {
def exampleName = "example-${buildName}"
setBuildStatus('PENDING', "build ${exampleName}", 'build starts')
try {
execute("echo \"https://github.com/ARMmbed/mbed-os/#6a0a86538c0b9b2bfcc4583b1e2b7fea8f4e71e9\" > mbed-os.lib")
execute("echo \"https://github.com/ARMmbed/mbed-trace#${env.GIT_COMMIT_HASH}\" > mbed-trace.lib")
execute("mbed new .")
execute("mbed deploy")
execute("rm -rf ./mbed-os/features/frameworks/mbed-trace")
execute("rm -rf ./mbed-trace/example")
execute("rm -rf ./mbed-trace/test")
execute("mbed compile -t ${toolchain} -m ${target}")
setBuildStatus('SUCCESS', "build ${exampleName}", "build done")
} catch(err) {
echo "Caught exception: ${err}"
setBuildStatus('FAILURE', "build ${exampleName}", "build failed")
currentBuild.result = 'FAILURE'
} finally {
// clean up
postBuild(buildName, false)
step([$class: 'WsCleanup'])
}
}
}
}
}
}
}

//Create yotta build steps for parallel execution
def yottaBuildStep(target, compilerLabel) {
return {
String buildName = "mbed-os3-${target}"
node ("${compilerLabel}") {
deleteDir()
dir("mbed-trace") {
def scmVars = checkout scm
env.GIT_COMMIT_HASH = scmVars.GIT_COMMIT
def isTest = target == "x86-linux-native" // tests are valid only in linux target
stage ("build:${buildName}") {
setBuildStatus('PENDING', "build ${buildName}", 'build starts')
try{
execute("yotta --version")
execute("yotta target $target")
execute("yotta --plain build mbed-trace")
setBuildStatus('SUCCESS', "build ${buildName}", "build done")
} catch (err) {
echo "Caught exception: ${err}"
setBuildStatus('FAILURE', "build ${buildName}", "build failed")
currentBuild.result = 'FAILURE'
}
} // stage
if (isTest) {
stage("test:${buildName}") {
setBuildStatus('PENDING', "test ${buildName}", 'test starts')
try {
execute("yotta test mbed_trace_test")
execute("lcov --base-directory . --directory . --capture --output-file coverage.info")
execute("genhtml -o ./test_coverage coverage.info")
execute("gcovr -x -o junit.xml")
execute("cppcheck --enable=all --std=c99 --inline-suppr --template=\"{file},{line},{severity},{id},{message}\" source 2> cppcheck.txt")

// check if astyle is correct
execute("astyle --options=.astylerc source/*.c mbed-trace/*.h")
// check differency
execute("git diff-index -p --exit-code HEAD")

setBuildStatus('SUCCESS', "test ${buildName}", "test done")
} catch(err) {
echo "Caught exception: ${err}"
setBuildStatus('FAILURE', "test ${buildName}", "test failed")
currentBuild.result = 'FAILURE'
}
} // stage
stage("example:${buildName}") {
dir("example/linux") {
def exampleName = "example-linux"
setBuildStatus('PENDING', "build ${exampleName}", 'build starts')
try {
execute("make")
setBuildStatus('SUCCESS', "build ${exampleName}", "build done")
} catch(err) {
echo "Caught exception: ${err}"
setBuildStatus('FAILURE', "build ${exampleName}", "build failed")
currentBuild.result = 'FAILURE'
}
}
} // stage

stage("leak-check:${buildName}") {
dir("example/linux") {
def stageName = "leak-check"
setBuildStatus('PENDING', "test ${stageName}", 'test starts')
try {
execute("./memtest.sh")
setBuildStatus('SUCCESS', "test ${stageName}", "test done")
} catch(err) {
echo "Caught exception: ${err}"
setBuildStatus('FAILURE', "test ${stageName}", "test failed")
currentBuild.result = 'FAILURE'
}
}
} // stage
} // if linux
postBuild(buildName, isTest)
step([$class: 'WsCleanup'])
} // dir
}
}
}

def postBuild(buildName, isTest) {
// move files to target+toolchain specific folder
execute("mkdir -p output/${buildName}")
execute("find . -name 'libmbed-trace.a' -exec mv {} 'output/${buildName}' \\;")
execute("find . -name 'mbed-trace.ar' -exec mv {} 'output/${buildName}' \\;")
execute("find ../example-mbed-os-5 -name 'example-mbed-os-5.bin' -exec mv {} 'output/${buildName}/example-mbed-os-5.bin' \\; || true")
// Archive artifacts
step([
$class: 'ArtifactArchiver',
artifacts: "cppcheck.txt,output/**",
fingerprint: true,
allowEmptyArchive: true
])
if (isTest) {
// Publish cobertura
step([
$class: 'CoberturaPublisher',
coberturaReportFile: 'junit.xml'
])
// Publish compiler warnings
step([
$class: 'WarningsPublisher',
parserConfigurations: [[
parserName: 'GNU Make + GNU C Compiler (gcc)',
pattern: 'mbed-trace/*.h,source/*.c,test/*.cpp'
]],
unstableTotalAll: '0',
useDeltaValues: true,
usePreviousBuildAsReference: true
])
// Publish HTML reports
publishHTML(target: [
alwayLinkToLastBuild: false,
keepAll: true,
reportDir: "test_coverage",
reportFiles: "index.html",
reportName: "Build HTML Report"
])
}
}
// helper function to set build status to github PR
def setBuildStatus(String state, String context, String message) {
step([
$class: "GitHubCommitStatusSetter",
reposSource: [
$class: "ManuallyEnteredRepositorySource",
url: "https://github.com/ARMmbed/mbed-trace.git"
],
contextSource: [
$class: "ManuallyEnteredCommitContextSource",
context: context
],
errorHandlers: [[
$class: "ChangingBuildStatusErrorHandler",
result: "UNSTABLE"
]],
commitShaSource: [
$class: "ManuallyEnteredShaSource",
sha: env.GIT_COMMIT_HASH
],
statusResultSource: [
$class: 'ConditionalStatusResultSource',
results: [
[
$class: 'AnyBuildResult',
message: message,
state: state
]
]
]
])
}
23 changes: 16 additions & 7 deletions features/frameworks/mbed-trace/README.md
Expand Up @@ -20,14 +20,14 @@ The purpose of the library is to provide a light, simple and general tracing sol
## Compromises

* The traces are stored as ASCII arrays in the flash memory (pretty high memory consumption). Therefore, it is not necessary to:
* encode/decode the trace messages on the fly (this may take too much CPU time) or
* have external dev-env dependencies to encode the traces compile time and an external application to decode the traces.
* encode/decode the trace messages on the fly (this may take too much CPU time) or
* have external dev-env dependencies to encode the traces compile time and an external application to decode the traces.
* The group name length is limited to four characters. This makes the lines cleaner and it is enough for most use cases for separating the module names. The group name length may not be suitable for a clean human readable format, but still four characters is enough for unique module names.
* The trace function uses `stdout` as the default output target because it goes directly to serial port when initialized.
* The trace function uses `stdout` as the default output target because it goes directly to serial port in mbed-os.
* The trace function produces traces like: `[<levl>][grp ]: msg`. This provides an easy way to detect trace prints and separate traces from normal prints (for example with _regex_).
* This approach requires a `sprintf` implementation (`stdio.h`). The memory consumption is pretty high, but it allows an efficient way to format traces.
* The solution is not Interrupt safe. (PRs are more than welcome.)
* The solution is not Thread safe by default. Thread safety for the actual trace calls can be enabled by providing wait and release callback functions that use mutexes defined by the application.
* The solution is not thread safe by default. Thread safety for the actual trace calls can be enabled by providing wait and release callback functions that use mutexes defined by the application.

## Examples of traces

Expand All @@ -43,7 +43,7 @@ The purpose of the library is to provide a light, simple and general tracing sol
### Prerequisites

* Initialize the serial port so that `stdout` works. You can verify that the serial port works using the `printf()` function.
* if you want to redirect the traces somewhere else, see the [trace API](https://github.com/ARMmbed/mbed-trace/blob/master/mbed-trace/mbed_trace.h#L170).
* if you want to redirect the traces somewhere else, see the [trace API](https://github.com/ARMmbed/mbed-trace/blob/master/mbed-trace/mbed_trace.h#L245).
* To enable the tracing API:
* With yotta: set `YOTTA_CFG_MBED_TRACE` to 1 or true. Setting the flag to 0 or false disables tracing.
* [With mbed OS 5](#enabling-the-tracing-api-in-mbed-os-5)
Expand Down Expand Up @@ -76,9 +76,16 @@ Don't forget to fulfill the other [prerequisites](#prerequisites)!

([Click here for more information on the configuration system](https://docs.mbed.com/docs/mbed-os-api/en/latest/config_system/))


## Examples

* [mbed-os-5](example/mbed-os-5)
* [linux](example/linux)

### Traces

When you want to print traces, use the `tr_<level>` macros. The macros behave like `printf()`. For example, `tr_debug("hello %s", "trace")` produces the following trace line: `[DBG ][APPL] hello trace<cr><lf>`.
When you want to print traces, use the `tr_<level>` macros. The macros behave like `printf()`. For example,
`tr_debug("hello %s", "trace")` produces the following trace line: `[DBG ][APPL] hello trace<cr><lf>`.

Available levels:

Expand Down Expand Up @@ -146,7 +153,9 @@ In Mbed OS, the build time maximum tracing level can be set through `mbed_app.js

### Helping functions

The purpose of the helping functions is to provide simple conversions, for example from an array to C string, so that you can print everything to single trace line. They must be called inside the actual trace calls, for example:
The purpose of the helping functions is to provide simple conversions,
for example from an array to C string, so that you can print everything to single trace line.
They must be called inside the actual trace calls, for example:

```
tr_debug("My IP6 address: %s", mbed_trace_ipv6(addr));
Expand Down
1 change: 1 addition & 0 deletions features/frameworks/mbed-trace/source/mbed_trace.c
Expand Up @@ -142,6 +142,7 @@ static trace_t m_trace = {
.line_length = DEFAULT_TRACE_LINE_LENGTH,
.tmp_data = 0,
.tmp_data_length = DEFAULT_TRACE_TMP_LINE_LEN,
.tmp_data_ptr = 0,
.prefix_f = 0,
.suffix_f = 0,
.printf = mbed_trace_default_print,
Expand Down
25 changes: 0 additions & 25 deletions features/frameworks/mbed-trace/test/CMakeLists.txt

This file was deleted.

0 comments on commit 7027eac

Please sign in to comment.